summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhil Hughes <me@iamphill.com>2017-08-30 11:20:34 +0100
committerPhil Hughes <me@iamphill.com>2017-08-30 11:20:34 +0100
commit75c4d2659bbcd51efc44123f3ab2c6496fa0eee2 (patch)
tree3b64f1f2d6c532c4472be1ff50662774a3299fa6
parenta8460f215cc1949b993e774dc00bad0b506abcfa (diff)
parent978b4b9cc0374c9cb5680612fe4154f393bbba9c (diff)
downloadgitlab-ce-75c4d2659bbcd51efc44123f3ab2c6496fa0eee2.tar.gz
Merge branch 'master' into breadcrumbs-improvements
-rw-r--r--.eslintrc1
-rw-r--r--.gitlab-ci.yml21
-rw-r--r--.rubocop.yml18
-rw-r--r--.rubocop_todo.yml8
-rw-r--r--CHANGELOG.md183
-rw-r--r--CONTRIBUTING.md2
-rw-r--r--GITALY_SERVER_VERSION2
-rw-r--r--Gemfile13
-rw-r--r--Gemfile.lock24
-rw-r--r--VERSION2
-rw-r--r--app/assets/javascripts/api.js24
-rw-r--r--app/assets/javascripts/boards/components/issue_card_inner.js2
-rw-r--r--app/assets/javascripts/copy_to_clipboard.js14
-rw-r--r--app/assets/javascripts/dispatcher.js4
-rw-r--r--app/assets/javascripts/droplab/drop_down.js7
-rw-r--r--app/assets/javascripts/filtered_search/dropdown_emoji.js82
-rw-r--r--app/assets/javascripts/filtered_search/dropdown_hint.js2
-rw-r--r--app/assets/javascripts/filtered_search/filtered_search_bundle.js1
-rw-r--r--app/assets/javascripts/filtered_search/filtered_search_dropdown_manager.js5
-rw-r--r--app/assets/javascripts/filtered_search/filtered_search_manager.js14
-rw-r--r--app/assets/javascripts/filtered_search/filtered_search_token_keys.js20
-rw-r--r--app/assets/javascripts/filtered_search/filtered_search_visual_tokens.js21
-rw-r--r--app/assets/javascripts/groups/components/group_item.vue6
-rw-r--r--app/assets/javascripts/lib/utils/sticky.js2
-rw-r--r--app/assets/javascripts/merge_request_tabs.js1
-rw-r--r--app/assets/javascripts/monitoring/components/monitoring_column.vue18
-rw-r--r--app/assets/javascripts/monitoring/components/monitoring_deployment.vue9
-rw-r--r--app/assets/javascripts/monitoring/components/monitoring_flag.vue7
-rw-r--r--app/assets/javascripts/monitoring/constants.js4
-rw-r--r--app/assets/javascripts/monitoring/utils/date_time_formatters.js15
-rw-r--r--app/assets/javascripts/new_sidebar.js1
-rw-r--r--app/assets/javascripts/pipelines/components/navigation_tabs.vue54
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines.vue4
-rw-r--r--app/assets/javascripts/project_select_combo_button.js33
-rw-r--r--app/assets/javascripts/repo/components/repo_commit_section.vue4
-rw-r--r--app/assets/javascripts/repo/components/repo_sidebar.vue9
-rw-r--r--app/assets/javascripts/repo/monaco_loader.js6
-rw-r--r--app/assets/javascripts/repo/services/repo_service.js20
-rw-r--r--app/assets/javascripts/users_select.js7
-rw-r--r--app/assets/javascripts/vue_shared/components/identicon.vue (renamed from app/assets/javascripts/groups/components/group_identicon.vue)0
-rw-r--r--app/assets/javascripts/webpack.js2
-rw-r--r--app/assets/stylesheets/framework/avatar.scss2
-rw-r--r--app/assets/stylesheets/framework/badges.scss2
-rw-r--r--app/assets/stylesheets/framework/blocks.scss4
-rw-r--r--app/assets/stylesheets/framework/buttons.scss2
-rw-r--r--app/assets/stylesheets/framework/calendar.scss6
-rw-r--r--app/assets/stylesheets/framework/common.scss16
-rw-r--r--app/assets/stylesheets/framework/dropdowns.scss39
-rw-r--r--app/assets/stylesheets/framework/filters.scss28
-rw-r--r--app/assets/stylesheets/framework/flash.scss2
-rw-r--r--app/assets/stylesheets/framework/forms.scss6
-rw-r--r--app/assets/stylesheets/framework/header.scss6
-rw-r--r--app/assets/stylesheets/framework/lists.scss4
-rw-r--r--app/assets/stylesheets/framework/mixins.scss2
-rw-r--r--app/assets/stylesheets/framework/modal.scss10
-rw-r--r--app/assets/stylesheets/framework/nav.scss4
-rw-r--r--app/assets/stylesheets/framework/page-header.scss2
-rw-r--r--app/assets/stylesheets/framework/selects.scss49
-rw-r--r--app/assets/stylesheets/framework/snippets.scss2
-rw-r--r--app/assets/stylesheets/framework/tables.scss2
-rw-r--r--app/assets/stylesheets/framework/tw_bootstrap.scss4
-rw-r--r--app/assets/stylesheets/framework/typography.scss18
-rw-r--r--app/assets/stylesheets/framework/variables.scss5
-rw-r--r--app/assets/stylesheets/framework/wells.scss2
-rw-r--r--app/assets/stylesheets/highlight/dark.scss8
-rw-r--r--app/assets/stylesheets/highlight/monokai.scss2
-rw-r--r--app/assets/stylesheets/highlight/solarized_dark.scss2
-rw-r--r--app/assets/stylesheets/highlight/solarized_light.scss2
-rw-r--r--app/assets/stylesheets/highlight/white.scss32
-rw-r--r--app/assets/stylesheets/mailers/highlighted_diff_email.scss32
-rw-r--r--app/assets/stylesheets/new_nav.scss4
-rw-r--r--app/assets/stylesheets/new_sidebar.scss13
-rw-r--r--app/assets/stylesheets/pages/boards.scss2
-rw-r--r--app/assets/stylesheets/pages/builds.scss4
-rw-r--r--app/assets/stylesheets/pages/ci_projects.scss2
-rw-r--r--app/assets/stylesheets/pages/commits.scss9
-rw-r--r--app/assets/stylesheets/pages/convdev_index.scss6
-rw-r--r--app/assets/stylesheets/pages/cycle_analytics.scss10
-rw-r--r--app/assets/stylesheets/pages/diff.scss6
-rw-r--r--app/assets/stylesheets/pages/editor.scss2
-rw-r--r--app/assets/stylesheets/pages/environments.scss6
-rw-r--r--app/assets/stylesheets/pages/events.scss2
-rw-r--r--app/assets/stylesheets/pages/issuable.scss6
-rw-r--r--app/assets/stylesheets/pages/issues.scss4
-rw-r--r--app/assets/stylesheets/pages/login.scss8
-rw-r--r--app/assets/stylesheets/pages/members.scss6
-rw-r--r--app/assets/stylesheets/pages/merge_requests.scss18
-rw-r--r--app/assets/stylesheets/pages/milestone.scss4
-rw-r--r--app/assets/stylesheets/pages/note_form.scss2
-rw-r--r--app/assets/stylesheets/pages/notes.scss14
-rw-r--r--app/assets/stylesheets/pages/notifications.scss4
-rw-r--r--app/assets/stylesheets/pages/pipeline_schedules.scss2
-rw-r--r--app/assets/stylesheets/pages/pipelines.scss16
-rw-r--r--app/assets/stylesheets/pages/profile.scss4
-rw-r--r--app/assets/stylesheets/pages/projects.scss16
-rw-r--r--app/assets/stylesheets/pages/repo.scss27
-rw-r--r--app/assets/stylesheets/pages/runners.scss2
-rw-r--r--app/assets/stylesheets/pages/search.scss2
-rw-r--r--app/assets/stylesheets/pages/sherlock.scss2
-rw-r--r--app/assets/stylesheets/pages/todos.scss10
-rw-r--r--app/assets/stylesheets/pages/tree.scss2
-rw-r--r--app/assets/stylesheets/pages/ui_dev_kit.scss2
-rw-r--r--app/assets/stylesheets/pages/wiki.scss4
-rw-r--r--app/assets/stylesheets/pages/xterm.scss2
-rw-r--r--app/assets/stylesheets/print.scss2
-rw-r--r--app/controllers/admin/logs_controller.rb9
-rw-r--r--app/controllers/admin/projects_controller.rb6
-rw-r--r--app/controllers/autocomplete_controller.rb18
-rw-r--r--app/controllers/concerns/issuable_collections.rb12
-rw-r--r--app/controllers/groups/milestones_controller.rb6
-rw-r--r--app/controllers/groups_controller.rb7
-rw-r--r--app/controllers/omniauth_callbacks_controller.rb8
-rw-r--r--app/controllers/projects/issues_controller.rb2
-rw-r--r--app/controllers/projects/merge_requests_controller.rb4
-rw-r--r--app/controllers/projects/services_controller.rb9
-rw-r--r--app/controllers/sessions_controller.rb8
-rw-r--r--app/finders/admin/projects_finder.rb80
-rw-r--r--app/finders/groups_finder.rb36
-rw-r--r--app/finders/issuable_finder.rb10
-rw-r--r--app/finders/projects_finder.rb17
-rw-r--r--app/helpers/application_helper.rb2
-rw-r--r--app/helpers/application_settings_helper.rb1
-rw-r--r--app/helpers/avatars_helper.rb11
-rw-r--r--app/helpers/button_helper.rb20
-rw-r--r--app/helpers/commits_helper.rb2
-rw-r--r--app/helpers/events_helper.rb3
-rw-r--r--app/helpers/issuables_helper.rb2
-rw-r--r--app/helpers/milestones_helper.rb2
-rw-r--r--app/helpers/milestones_routing_helper.rb8
-rw-r--r--app/models/broadcast_message.rb32
-rw-r--r--app/models/ci/build.rb5
-rw-r--r--app/models/ci/pipeline.rb3
-rw-r--r--app/models/ci/pipeline_schedule.rb2
-rw-r--r--app/models/ci/pipeline_schedule_variable.rb2
-rw-r--r--app/models/ci/runner.rb2
-rw-r--r--app/models/ci/stage.rb63
-rw-r--r--app/models/commit_status.rb9
-rw-r--r--app/models/concerns/awardable.rb15
-rw-r--r--app/models/concerns/editable.rb2
-rw-r--r--app/models/concerns/has_status.rb2
-rw-r--r--app/models/concerns/milestoneish.rb8
-rw-r--r--app/models/concerns/protected_ref.rb2
-rw-r--r--app/models/concerns/storage/legacy_project.rb76
-rw-r--r--app/models/dashboard_milestone.rb2
-rw-r--r--app/models/deployment.rb2
-rw-r--r--app/models/event.rb12
-rw-r--r--app/models/group.rb4
-rw-r--r--app/models/group_milestone.rb2
-rw-r--r--app/models/issue.rb10
-rw-r--r--app/models/merge_request.rb23
-rw-r--r--app/models/milestone.rb6
-rw-r--r--app/models/network/graph.rb4
-rw-r--r--app/models/notification_recipient.rb53
-rw-r--r--app/models/project.rb139
-rw-r--r--app/models/project_services/chat_notification_service.rb6
-rw-r--r--app/models/project_services/hipchat_service.rb6
-rw-r--r--app/models/project_services/kubernetes_service.rb6
-rw-r--r--app/models/repository.rb21
-rw-r--r--app/models/storage/hashed_project.rb42
-rw-r--r--app/models/storage/legacy_project.rb51
-rw-r--r--app/models/user.rb7
-rw-r--r--app/policies/group_policy.rb4
-rw-r--r--app/policies/project_policy.rb6
-rw-r--r--app/services/akismet_service.rb2
-rw-r--r--app/services/ci/create_pipeline_service.rb13
-rw-r--r--app/services/commits/create_service.rb2
-rw-r--r--app/services/concerns/users/new_user_notifier.rb9
-rw-r--r--app/services/create_branch_service.rb2
-rw-r--r--app/services/delete_branch_service.rb2
-rw-r--r--app/services/git_hooks_service.rb32
-rw-r--r--app/services/git_operation_service.rb14
-rw-r--r--app/services/git_push_service.rb10
-rw-r--r--app/services/groups/create_service.rb4
-rw-r--r--app/services/groups/destroy_service.rb2
-rw-r--r--app/services/groups/nested_create_service.rb49
-rw-r--r--app/services/issuable_base_service.rb4
-rw-r--r--app/services/issues/create_service.rb2
-rw-r--r--app/services/merge_requests/create_from_issue_service.rb5
-rw-r--r--app/services/merge_requests/create_service.rb2
-rw-r--r--app/services/merge_requests/merge_service.rb8
-rw-r--r--app/services/merge_requests/merge_when_pipeline_succeeds_service.rb2
-rw-r--r--app/services/merge_requests/update_service.rb2
-rw-r--r--app/services/milestones/close_service.rb2
-rw-r--r--app/services/milestones/create_service.rb2
-rw-r--r--app/services/milestones/destroy_service.rb2
-rw-r--r--app/services/milestones/reopen_service.rb2
-rw-r--r--app/services/notification_recipient_service.rb2
-rw-r--r--app/services/projects/count_service.rb43
-rw-r--r--app/services/projects/create_service.rb19
-rw-r--r--app/services/projects/forks_count_service.rb28
-rw-r--r--app/services/projects/housekeeping_service.rb3
-rw-r--r--app/services/projects/open_issues_count_service.rb15
-rw-r--r--app/services/projects/open_merge_requests_count_service.rb13
-rw-r--r--app/services/spam_service.rb2
-rw-r--r--app/services/system_note_service.rb2
-rw-r--r--app/services/tags/create_service.rb2
-rw-r--r--app/services/tags/destroy_service.rb2
-rw-r--r--app/services/test_hooks/system_service.rb37
-rw-r--r--app/services/user_project_access_changed_service.rb10
-rw-r--r--app/services/users/create_service.rb8
-rw-r--r--app/services/users/destroy_service.rb6
-rw-r--r--app/services/users/update_service.rb6
-rw-r--r--app/services/validate_new_branch_service.rb2
-rw-r--r--app/views/admin/application_settings/_form.html.haml15
-rw-r--r--app/views/admin/dashboard/_head.html.haml4
-rw-r--r--app/views/admin/logs/show.html.haml16
-rw-r--r--app/views/admin/monitoring/_head.html.haml4
-rw-r--r--app/views/dashboard/issues.html.haml4
-rw-r--r--app/views/dashboard/merge_requests.html.haml4
-rw-r--r--app/views/dashboard/milestones/index.html.haml4
-rw-r--r--app/views/doorkeeper/authorizations/new.html.haml78
-rw-r--r--app/views/events/_event_push.atom.haml13
-rw-r--r--app/views/events/event/_push.html.haml4
-rw-r--r--app/views/groups/issues.html.haml4
-rw-r--r--app/views/groups/merge_requests.html.haml10
-rw-r--r--app/views/groups/milestones/show.html.haml2
-rw-r--r--app/views/import/gitlab_projects/new.html.haml3
-rw-r--r--app/views/layouts/errors.html.haml4
-rw-r--r--app/views/layouts/nav/_breadcrumbs.html.haml5
-rw-r--r--app/views/layouts/nav/_new_admin_sidebar.html.haml12
-rw-r--r--app/views/layouts/nav/_new_group_sidebar.html.haml2
-rw-r--r--app/views/layouts/nav/_new_profile_sidebar.html.haml2
-rw-r--r--app/views/layouts/nav/_new_project_sidebar.html.haml8
-rw-r--r--app/views/layouts/nav/_project.html.haml6
-rw-r--r--app/views/layouts/oauth_error.html.haml2
-rw-r--r--app/views/profiles/gpg_keys/index.html.haml2
-rw-r--r--app/views/projects/_project_templates.html.haml2
-rw-r--r--app/views/projects/boards/_show.html.haml1
-rw-r--r--app/views/projects/commit/_signature_badge.html.haml2
-rw-r--r--app/views/projects/commits/_commit.html.haml8
-rw-r--r--app/views/projects/edit.html.haml2
-rw-r--r--app/views/projects/issues/show.html.haml3
-rw-r--r--app/views/projects/new.html.haml7
-rw-r--r--app/views/projects/notes/_actions.html.haml8
-rw-r--r--app/views/projects/notes/_more_actions_dropdown.html.haml2
-rw-r--r--app/views/projects/pipelines/charts/_pipelines.haml6
-rw-r--r--app/views/projects/runners/_runner.html.haml2
-rw-r--r--app/views/search/_form.html.haml2
-rw-r--r--app/views/shared/_group_form.html.haml5
-rw-r--r--app/views/shared/_new_project_item_select.html.haml2
-rw-r--r--app/views/shared/empty_states/_issues.html.haml2
-rw-r--r--app/views/shared/empty_states/_merge_requests.html.haml2
-rw-r--r--app/views/shared/icons/_icon_arrow_circle_o_right.svg3
-rw-r--r--app/views/shared/icons/_icon_check_square_o.svg3
-rw-r--r--app/views/shared/icons/_icon_clock_o.svg2
-rw-r--r--app/views/shared/icons/_icon_clone.svg5
-rw-r--r--app/views/shared/icons/_icon_code_fork.svg3
-rw-r--r--app/views/shared/icons/_icon_comment_o.svg3
-rw-r--r--app/views/shared/icons/_icon_commit.svg3
-rw-r--r--app/views/shared/icons/_icon_edit.svg3
-rw-r--r--app/views/shared/icons/_icon_eye.svg3
-rw-r--r--app/views/shared/icons/_icon_eye_slash.svg3
-rw-r--r--app/views/shared/icons/_icon_merged.svg3
-rw-r--r--app/views/shared/icons/_icon_pencil.svg3
-rw-r--r--app/views/shared/icons/_icon_random.svg3
-rw-r--r--app/views/shared/icons/_icon_status_closed.svg2
-rwxr-xr-xapp/views/shared/icons/_icon_status_success.svg2
-rw-r--r--app/views/shared/icons/_icon_status_success_solid.svg1
-rw-r--r--app/views/shared/icons/_icon_tags.svg3
-rw-r--r--app/views/shared/icons/_icon_user.svg2
-rw-r--r--app/views/shared/issuable/_close_reopen_button.html.haml3
-rw-r--r--app/views/shared/issuable/_close_reopen_report_toggle.html.haml22
-rw-r--r--app/views/shared/issuable/_search_bar.html.haml13
-rw-r--r--app/views/shared/issuable/_user_dropdown_item.html.haml2
-rw-r--r--app/views/shared/milestones/_milestone.html.haml8
-rw-r--r--app/views/shared/milestones/_top.html.haml8
-rw-r--r--app/views/shared/projects/_dropdown.html.haml5
-rw-r--r--app/workers/authorized_projects_worker.rb33
-rw-r--r--app/workers/build_coverage_worker.rb2
-rw-r--r--app/workers/build_finished_worker.rb4
-rw-r--r--app/workers/build_hooks_worker.rb4
-rw-r--r--app/workers/build_queue_worker.rb4
-rw-r--r--app/workers/build_success_worker.rb4
-rw-r--r--app/workers/concerns/build_queue.rb8
-rw-r--r--app/workers/concerns/exception_backtrace.rb8
-rw-r--r--app/workers/concerns/pipeline_queue.rb12
-rw-r--r--app/workers/expire_job_cache_worker.rb4
-rw-r--r--app/workers/expire_pipeline_cache_worker.rb2
-rw-r--r--app/workers/group_destroy_worker.rb1
-rw-r--r--app/workers/merge_worker.rb2
-rw-r--r--app/workers/namespaceless_project_destroy_worker.rb4
-rw-r--r--app/workers/pipeline_hooks_worker.rb2
-rw-r--r--app/workers/pipeline_process_worker.rb2
-rw-r--r--app/workers/pipeline_success_worker.rb2
-rw-r--r--app/workers/pipeline_update_worker.rb2
-rw-r--r--app/workers/project_destroy_worker.rb1
-rw-r--r--app/workers/project_export_worker.rb1
-rw-r--r--app/workers/repository_import_worker.rb1
-rw-r--r--app/workers/stage_update_worker.rb12
-rw-r--r--changelogs/unreleased/10085-stop-encoding-user-name.yml4
-rw-r--r--changelogs/unreleased/13247-api_project_events_target_iid.yml4
-rw-r--r--changelogs/unreleased/13265-project_events_noteable_iid.yml4
-rw-r--r--changelogs/unreleased/1827-prevent-concurrent-editing-wiki.yml4
-rw-r--r--changelogs/unreleased/19629-remove-inactive-tokens-list.yml4
-rw-r--r--changelogs/unreleased/20817-please-add-coordinator-url-to-admin-area-runner-page.yml4
-rw-r--r--changelogs/unreleased/22600-related-resources-uris-using-grape-source-helpers.yml4
-rw-r--r--changelogs/unreleased/23036-replace-dashboard-event-filters-spinach.yml4
-rw-r--r--changelogs/unreleased/23036-replace-dashboard-spinach.yml4
-rw-r--r--changelogs/unreleased/26372-duplicate-issue-slash-command.yml4
-rw-r--r--changelogs/unreleased/27616-fix-contributions-graph-utc-offset-mysql.yml4
-rw-r--r--changelogs/unreleased/28202_decrease_abc_threshold_step2.yml4
-rw-r--r--changelogs/unreleased/28283-uuid-storage.yml4
-rw-r--r--changelogs/unreleased/28472-ignore-auto-generated-mails.yml4
-rw-r--r--changelogs/unreleased/29289-project-destroy-clean-up-after-failure.yml4
-rw-r--r--changelogs/unreleased/29385-add_shrug_command.yml4
-rw-r--r--changelogs/unreleased/29901-refactor-initialization-dropzone_input-js.yml4
-rw-r--r--changelogs/unreleased/30634-protected-pipeline.yml5
-rw-r--r--changelogs/unreleased/31129-jira-project-key-elim.yml4
-rw-r--r--changelogs/unreleased/31207-clean-locked-merge-requests.yml4
-rw-r--r--changelogs/unreleased/31409-fix-group-and-project-search-for-anonymous-users.yml5
-rw-r--r--changelogs/unreleased/31533-usage-data-projects-stats.yml4
-rw-r--r--changelogs/unreleased/31571-don-t-let-webhooks-jobs-go-to-the-dead-jobs-queue.yml5
-rw-r--r--changelogs/unreleased/32483-jira-error.yml4
-rw-r--r--changelogs/unreleased/32844-issuables-performance.yml4
-rw-r--r--changelogs/unreleased/33095-mr-widget-ui.yml4
-rw-r--r--changelogs/unreleased/33097-issue-tracker.yml4
-rw-r--r--changelogs/unreleased/33601-add-csrf-token-verification-to-api.yml4
-rw-r--r--changelogs/unreleased/33620-remove-events-from-notification_settings.yml4
-rw-r--r--changelogs/unreleased/33741-clarify-k8s-service-keys.yml5
-rw-r--r--changelogs/unreleased/33770-respect-blockquote-line-breaks.yml4
-rw-r--r--changelogs/unreleased/33874_confi.yml5
-rw-r--r--changelogs/unreleased/34027-add-icons-to-sidebar.yml4
-rw-r--r--changelogs/unreleased/34028-collapse-sidebar.yml4
-rw-r--r--changelogs/unreleased/34075-pipelines-count-mt.yml5
-rw-r--r--changelogs/unreleased/34110-memory-usage-notice-doesn-t-link-anywhere.yml4
-rw-r--r--changelogs/unreleased/34339-user_avatar-url-in-push-event-webhook-json-payload-is-relative-should-be-absolute.yml4
-rw-r--r--changelogs/unreleased/34361-lazy-load-images-on-the-frontend.yml4
-rw-r--r--changelogs/unreleased/34413-move-convdev-index-location-to-after-cohorts.yml4
-rw-r--r--changelogs/unreleased/34519-extend-api-group-secret-variable.yml4
-rw-r--r--changelogs/unreleased/34527-make-edit-comment-button-always-available-outside-of-dropdown.yml4
-rw-r--r--changelogs/unreleased/34533-speed-up-group-project-authorizations.yml5
-rw-r--r--changelogs/unreleased/34534-update-vue-resource.yml4
-rw-r--r--changelogs/unreleased/34549-extract-devise-mappings-into-helper.yml4
-rw-r--r--changelogs/unreleased/34563-usage-ping-github.yml4
-rw-r--r--changelogs/unreleased/34764-rename-to-overview.yml4
-rw-r--r--changelogs/unreleased/34810-vue-pagination.yml4
-rw-r--r--changelogs/unreleased/34831-remove-coffee-rails-gem.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/34869-bump-rubocop-to-0-49-1-and-rubocop-rspec-to-1-15-1.yml4
-rw-r--r--changelogs/unreleased/34921-global-dropdown-ui-improvement.yml4
-rw-r--r--changelogs/unreleased/34927-protect-manual-actions-on-tags.yml4
-rw-r--r--changelogs/unreleased/34978-remove-public-ci-favicon-ico.yml4
-rw-r--r--changelogs/unreleased/34990-top-buttons-misaligned.yml5
-rw-r--r--changelogs/unreleased/35044-projects-logo-are-not-centered-vertically-on-projects-page.yml4
-rw-r--r--changelogs/unreleased/35048-empty-badges.yml5
-rw-r--r--changelogs/unreleased/35072-fix-pages-delete.yml5
-rw-r--r--changelogs/unreleased/35098-raise-encoding-confidence-threshold.yml4
-rw-r--r--changelogs/unreleased/35136-barchart-not-display-label-at-0-hour.yml4
-rw-r--r--changelogs/unreleased/35155-upgrade-fog-core-to-1-44-3-and-its-providers-to-the-latest.yml4
-rw-r--r--changelogs/unreleased/35163-url-in-commit-message-can-be-broken-in-blame.yml4
-rw-r--r--changelogs/unreleased/35164-cycle-analytics-firefox.yml4
-rw-r--r--changelogs/unreleased/35181-cannot-create-label-from-board-page.yml4
-rw-r--r--changelogs/unreleased/35191-prioritized-labels-for-non-member.yml4
-rw-r--r--changelogs/unreleased/35204-doc-api-ci-lint-typo.yml4
-rw-r--r--changelogs/unreleased/35225-transient-poll.yml4
-rw-r--r--changelogs/unreleased/35253-desc-protected-branches-for-non-member.yml4
-rw-r--r--changelogs/unreleased/35343-inherit-milestones-and-labels.yml5
-rw-r--r--changelogs/unreleased/35391-fix-star-i18n-in-js.yml4
-rw-r--r--changelogs/unreleased/35408-group-auto-avatars.yml4
-rw-r--r--changelogs/unreleased/35483-improve-mobile-sidebar.yml4
-rw-r--r--changelogs/unreleased/35659-rename-pipeline.yml4
-rw-r--r--changelogs/unreleased/35695-comment-appears-in-a-wrong-place-after-changing-diff-view-to-inline.yml4
-rw-r--r--changelogs/unreleased/35721-auth-style-confirmation.yml5
-rw-r--r--changelogs/unreleased/35761-convdev-perc.yml4
-rw-r--r--changelogs/unreleased/35769-fix-ruby-2-4-compatibility.yml4
-rw-r--r--changelogs/unreleased/35793_fix_predicate_names.yml5
-rw-r--r--changelogs/unreleased/35811-copy-link-note.yml5
-rw-r--r--changelogs/unreleased/35815-webhook-log-encoding-error.yml4
-rw-r--r--changelogs/unreleased/35845-improve-subgroup-creation-permissions.yml5
-rw-r--r--changelogs/unreleased/35994-archived-projects-only.yml5
-rw-r--r--changelogs/unreleased/36061-mr-ref.yml5
-rw-r--r--changelogs/unreleased/36114-stuck-mrs-job-follow-up.yml4
-rw-r--r--changelogs/unreleased/36185-or-separator.yml4
-rw-r--r--changelogs/unreleased/36262_merge_request_reference_in_merge_commit_global.yml5
-rw-r--r--changelogs/unreleased/36582-fix-note-resolved-icon.yml5
-rw-r--r--changelogs/unreleased/36792-inline-user-refresh-when-creating-project.yml5
-rw-r--r--changelogs/unreleased/36860-deleted-user-fix.yml5
-rw-r--r--changelogs/unreleased/3686_make_tarball_download_url.yml4
-rw-r--r--changelogs/unreleased/36882-disable-gitlab-project-import-button-if-source-disabled.yml5
-rw-r--r--changelogs/unreleased/36937-fix-invite-by-email-text.yml5
-rw-r--r--changelogs/unreleased/36939-fix-find-blobs-by-path.yml5
-rw-r--r--changelogs/unreleased/37104-fix-graph-date-format.yml5
-rw-r--r--changelogs/unreleased/37147-fix-fallback-emoji-alignment.yml5
-rw-r--r--changelogs/unreleased/37198-api-doesn-t-respect-default-group-visibility.yml5
-rw-r--r--changelogs/unreleased/5971-webhook-testing.yml4
-rw-r--r--changelogs/unreleased/add-filter-by-my-reaction.yml4
-rw-r--r--changelogs/unreleased/add-filtered-search-group-issues-ce.yml4
-rw-r--r--changelogs/unreleased/add-star-for-action-scope.yml4
-rw-r--r--changelogs/unreleased/api-delete-respect-headers.yml5
-rw-r--r--changelogs/unreleased/appearances-caching-and-schema.yml4
-rw-r--r--changelogs/unreleased/artifacts-download-dropdown-menu-is-too-narrow.yml4
-rw-r--r--changelogs/unreleased/backstage-gb-after-save-asynchronous-job-hooks.yml5
-rw-r--r--changelogs/unreleased/breadcrumbs-collapsed-title-width-fix.yml4
-rw-r--r--changelogs/unreleased/broadcast-messages-cache.yml4
-rw-r--r--changelogs/unreleased/bugfix-notify-custom-participants.yml5
-rw-r--r--changelogs/unreleased/bump-omniauth-ldap-gem-version.yml4
-rw-r--r--changelogs/unreleased/bvl-add-all-settings-to-api.yml4
-rw-r--r--changelogs/unreleased/bvl-free-unused-names.yml5
-rw-r--r--changelogs/unreleased/bvl-improve-bare-project-import.yml6
-rw-r--r--changelogs/unreleased/bvl-nfs-circuitbreaker.yml4
-rw-r--r--changelogs/unreleased/bvl-rollback-renamed-system-namespace.yml4
-rw-r--r--changelogs/unreleased/cache-issue-and-mr-counts.yml5
-rw-r--r--changelogs/unreleased/changes-bar-sticky-fix.yml5
-rw-r--r--changelogs/unreleased/commits-list-page-limit.yml5
-rw-r--r--changelogs/unreleased/diff-changed-files-dropdown.yml4
-rw-r--r--changelogs/unreleased/dm-large-push-performance.yml4
-rw-r--r--changelogs/unreleased/docs-document-version-for-group-milestones-api.yml5
-rw-r--r--changelogs/unreleased/docs-update-ci-docker-using-docker-images.yml5
-rw-r--r--changelogs/unreleased/dont-use-limit-offset-when-counting-projects.yml4
-rw-r--r--changelogs/unreleased/dz-fix-calendar-today.yml4
-rw-r--r--changelogs/unreleased/eager-load-project-creators-for-project-dashboards.yml4
-rw-r--r--changelogs/unreleased/enable-scss-lint-bang-format.yml4
-rw-r--r--changelogs/unreleased/enable-scss-lint-declaration-order.yml4
-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/ericy_ts-protected_branches_api.yml5
-rw-r--r--changelogs/unreleased/feature-backup-custom-path.yml4
-rw-r--r--changelogs/unreleased/feature-gb-auto-retry-failed-ci-job.yml4
-rw-r--r--changelogs/unreleased/feature-gpg-signed-commits.yml4
-rw-r--r--changelogs/unreleased/fix-500-error-when-rendering-avatar-for-deleted-project-creator.yml4
-rw-r--r--changelogs/unreleased/fix-gb-handle-max-pages-artifacts-size-correctly.yml4
-rw-r--r--changelogs/unreleased/fix-import-events.yml5
-rw-r--r--changelogs/unreleased/fix-import-fork-mr.yml5
-rw-r--r--changelogs/unreleased/fix-import-symbolink-links.yml4
-rw-r--r--changelogs/unreleased/fix-replying-to-commit-comment-in-mr-from-fork.yml4
-rw-r--r--changelogs/unreleased/fix-sm-37040-regression-pipeline-trigger-via-api-fails-with-500-internal-server-error-in-9-5-1.yml5
-rw-r--r--changelogs/unreleased/fix-thread-safe-gpgme-tmp-directory.yml4
-rw-r--r--changelogs/unreleased/fixes-for-internal-auth-disabled.yml4
-rw-r--r--changelogs/unreleased/font-weight-adjusted.yml5
-rw-r--r--changelogs/unreleased/forks-count-cache.yml5
-rw-r--r--changelogs/unreleased/gitaly_ref_exists.yml4
-rw-r--r--changelogs/unreleased/github.yml4
-rw-r--r--changelogs/unreleased/group-milestone-references-system-notes.yml4
-rw-r--r--changelogs/unreleased/group-mr-search-bar.yml5
-rw-r--r--changelogs/unreleased/group-new-issue.yml4
-rw-r--r--changelogs/unreleased/handle-reserved-words-for-oauth-usernames.yml4
-rw-r--r--changelogs/unreleased/issue-boards-breadcrumbs-container.yml5
-rw-r--r--changelogs/unreleased/issue_31790.yml4
-rw-r--r--changelogs/unreleased/issue_35580.yml4
-rw-r--r--changelogs/unreleased/memoize-user-personal-projects-count.yml4
-rw-r--r--changelogs/unreleased/merge-issuable-reopened-into-opened-state.yml4
-rw-r--r--changelogs/unreleased/migrate-events-into-a-new-format.yml4
-rw-r--r--changelogs/unreleased/mk-fix-user-namespace-rename.yml5
-rw-r--r--changelogs/unreleased/mk-fix-wiki-backup.yml4
-rw-r--r--changelogs/unreleased/mr-branch-link-use-tree.yml4
-rw-r--r--changelogs/unreleased/mr-index-eager-load.yml5
-rw-r--r--changelogs/unreleased/pagination-projects-explore.yml4
-rw-r--r--changelogs/unreleased/pass-before-script-as-is.yml4
-rw-r--r--changelogs/unreleased/pawel-add-sidekiq-metrics-endpoint-32145.yml4
-rw-r--r--changelogs/unreleased/pawel-add_more_variables_to_additional_metrics-35267.yml4
-rw-r--r--changelogs/unreleased/post-upload-pack-opt-out.yml4
-rw-r--r--changelogs/unreleased/rc-fix-branches-api-endpoint.yml5
-rw-r--r--changelogs/unreleased/rc-fix-commits-api.yml5
-rw-r--r--changelogs/unreleased/rc-fix-tags-api.yml5
-rw-r--r--changelogs/unreleased/remove-nprogress-gleaning.yml4
-rw-r--r--changelogs/unreleased/remove-redundant-query-when-retrieving-recent-pushes.yml4
-rw-r--r--changelogs/unreleased/reorganise-issues-indexes-for-sorting.yml4
-rw-r--r--changelogs/unreleased/replace_spinach_search_code-feature.yml5
-rw-r--r--changelogs/unreleased/replace_spinach_spec_browse_files.yml4
-rw-r--r--changelogs/unreleased/replace_spinach_star-feature.yml5
-rw-r--r--changelogs/unreleased/request-store-wrap.yml4
-rw-r--r--changelogs/unreleased/restrict-haml-javascript.yml4
-rw-r--r--changelogs/unreleased/revert-appearances-description-html-not-null.yml5
-rw-r--r--changelogs/unreleased/rouge-2-2-0.yml5
-rw-r--r--changelogs/unreleased/rs-alphanumeric-ssh-params.yml5
-rw-r--r--changelogs/unreleased/sh-structured-logging.yml4
-rw-r--r--changelogs/unreleased/skip-oauth-authorization-for-trusted-applications.yml4
-rw-r--r--changelogs/unreleased/tc-api-root-merge-requests.yml4
-rw-r--r--changelogs/unreleased/tc-git-tower-pagination-links.yml5
-rw-r--r--changelogs/unreleased/tc-issue-api-assignee.yml4
-rw-r--r--changelogs/unreleased/tc-no-todo-service-select.yml4
-rw-r--r--changelogs/unreleased/tc-remove-nonexisting-namespace-pending-delete-projects.yml5
-rw-r--r--changelogs/unreleased/toggle-new-project-import-description.yml4
-rw-r--r--changelogs/unreleased/use-a-specialized-class-for-querying-events.yml4
-rw-r--r--changelogs/unreleased/use_full_path_in_project_avatar_url_webhook.yml5
-rw-r--r--changelogs/unreleased/wiki_title.yml4
-rw-r--r--changelogs/unreleased/winh-derive-project-name.yml4
-rw-r--r--changelogs/unreleased/zj-add-pipeline-source-variable.yml5
-rw-r--r--changelogs/unreleased/zj-delete-mm-team.yml4
-rw-r--r--changelogs/unreleased/zj-pipeline-badge-improvements.yml4
-rw-r--r--changelogs/unreleased/zj-project-templates.yml4
-rw-r--r--changelogs/unreleased/zj-remove-ci-api-v1.yml5
-rw-r--r--changelogs/unreleased/zj-reword-job-to-pipeline-chart-view.yml5
-rw-r--r--config/initializers/7_prometheus_metrics.rb3
-rw-r--r--config/initializers/8_metrics.rb3
-rw-r--r--config/initializers/omniauth.rb6
-rw-r--r--config/initializers/workhorse_multipart.rb4
-rw-r--r--config/karma.config.js1
-rw-r--r--config/routes.rb1
-rw-r--r--config/routes/ci.rb4
-rw-r--r--config/sidekiq_queues.yml4
-rw-r--r--config/webpack.config.js12
-rw-r--r--db/fixtures/development/17_cycle_analytics.rb2
-rw-r--r--db/migrate/20140502125220_migrate_repo_size.rb2
-rw-r--r--db/migrate/20170711145320_add_status_to_ci_stages.rb9
-rw-r--r--db/migrate/20170720111708_add_lock_version_to_ci_stages.rb9
-rw-r--r--db/migrate/20170802013652_add_storage_fields_to_project.rb16
-rw-r--r--db/migrate/20170807071105_add_hashed_storage_to_settings.rb18
-rw-r--r--db/migrate/20170809142252_cleanup_appearances_schema.rb2
-rw-r--r--db/migrate/20170820100558_correct_protected_tags_foreign_keys.rb35
-rw-r--r--db/migrate/20170824162758_allow_appearances_description_html_null.rb18
-rw-r--r--db/post_migrate/20170711145558_migrate_stages_statuses.rb33
-rw-r--r--db/post_migrate/20170816102555_cleanup_nonexisting_namespace_pending_delete_projects.rb54
-rw-r--r--db/post_migrate/20170822101017_migrate_pipeline_sidekiq_queues.rb17
-rw-r--r--db/schema.rb10
-rw-r--r--doc/README.md2
-rw-r--r--doc/administration/auth/authentiq.md2
-rw-r--r--doc/api/README.md8
-rw-r--r--doc/api/ci/README.md24
-rw-r--r--doc/api/ci/builds.md147
-rw-r--r--doc/api/ci/runners.md59
-rw-r--r--doc/api/group_level_variables.md4
-rw-r--r--doc/api/group_milestones.md5
-rw-r--r--doc/api/groups.md9
-rw-r--r--doc/api/lint.md (renamed from doc/api/ci/lint.md)3
-rw-r--r--doc/api/project_snippets.md2
-rw-r--r--doc/articles/index.md3
-rw-r--r--doc/ci/api/README.md1
-rw-r--r--doc/ci/api/builds.md1
-rw-r--r--doc/ci/api/runners.md1
-rw-r--r--doc/ci/docker/using_docker_build.md10
-rw-r--r--doc/ci/docker/using_docker_images.md40
-rw-r--r--doc/ci/variables/README.md6
-rw-r--r--doc/ci/yaml/README.md2
-rw-r--r--doc/development/doc_styleguide.md13
-rw-r--r--doc/development/fe_guide/style_guide_js.md121
-rw-r--r--doc/development/licensing.md2
-rw-r--r--doc/development/testing.md5
-rw-r--r--doc/gitlab-basics/create-project.md17
-rw-r--r--doc/gitlab-basics/img/create_new_project_info.pngbin20385 -> 82725 bytes
-rw-r--r--doc/install/README.md12
-rw-r--r--doc/install/azure/img/azure-add-inbound-sec-rule-http.pngbin0 -> 16927 bytes
-rw-r--r--doc/install/azure/img/azure-add-inbound-sec-rule-ssh.pngbin0 -> 16817 bytes
-rw-r--r--doc/install/azure/img/azure-create-virtual-machine-basics-password.pngbin0 -> 24862 bytes
-rw-r--r--doc/install/azure/img/azure-create-virtual-machine-basics.pngbin0 -> 22925 bytes
-rw-r--r--doc/install/azure/img/azure-create-virtual-machine-deployment.pngbin0 -> 23707 bytes
-rw-r--r--doc/install/azure/img/azure-create-virtual-machine-purchase.pngbin0 -> 43698 bytes
-rw-r--r--doc/install/azure/img/azure-create-virtual-machine-settings.pngbin0 -> 25686 bytes
-rw-r--r--doc/install/azure/img/azure-create-virtual-machine-size.pngbin0 -> 33322 bytes
-rw-r--r--doc/install/azure/img/azure-dashboard-highlight-nsg.pngbin0 -> 34248 bytes
-rw-r--r--doc/install/azure/img/azure-dashboard-running-resources.pngbin0 -> 34306 bytes
-rw-r--r--doc/install/azure/img/azure-dashboard.pngbin0 -> 36396 bytes
-rw-r--r--doc/install/azure/img/azure-inbound-sec-rules-list.pngbin0 -> 24592 bytes
-rw-r--r--doc/install/azure/img/azure-new-gitlab-ce.pngbin0 -> 22701 bytes
-rw-r--r--doc/install/azure/img/azure-new-search-gitlab.pngbin0 -> 19034 bytes
-rw-r--r--doc/install/azure/img/azure-nsg-inbound-sec-rules-add-highlight.pngbin0 -> 22583 bytes
-rw-r--r--doc/install/azure/img/azure-nsg-inbound-sec-rules-highlight.pngbin0 -> 31485 bytes
-rw-r--r--doc/install/azure/img/azure-vm-domain-name.pngbin0 -> 23802 bytes
-rw-r--r--doc/install/azure/img/azure-vm-management-public-ip.pngbin0 -> 34991 bytes
-rw-r--r--doc/install/azure/img/azure-vm-management-settings-network-interfaces.pngbin0 -> 35849 bytes
-rw-r--r--doc/install/azure/img/azure-vm-management.pngbin0 -> 35363 bytes
-rw-r--r--doc/install/azure/img/gitlab-admin-area-9.4.0.pngbin0 -> 35249 bytes
-rw-r--r--doc/install/azure/img/gitlab-admin-area.pngbin0 -> 29333 bytes
-rw-r--r--doc/install/azure/img/gitlab-change-password.pngbin0 -> 24404 bytes
-rw-r--r--doc/install/azure/img/gitlab-home.pngbin0 -> 26302 bytes
-rw-r--r--doc/install/azure/img/gitlab-login.pngbin0 -> 24656 bytes
-rw-r--r--doc/install/azure/img/gitlab-new-project.pngbin0 -> 34164 bytes
-rw-r--r--doc/install/azure/img/gitlab-project-home-empty.pngbin0 -> 28375 bytes
-rw-r--r--doc/install/azure/img/gitlab-project-home-instructions.pngbin0 -> 31738 bytes
-rw-r--r--doc/install/azure/img/gitlab-ssh-update-in-progress.pngbin0 -> 32799 bytes
-rw-r--r--doc/install/azure/index.md439
-rw-r--r--doc/install/docker.md18
-rw-r--r--doc/install/kubernetes/gitlab_chart.md7
-rw-r--r--doc/install/kubernetes/gitlab_omnibus.md11
-rw-r--r--doc/install/kubernetes/gitlab_runner_chart.md7
-rw-r--r--doc/install/kubernetes/index.md6
-rw-r--r--doc/topics/authentication/index.md1
-rw-r--r--doc/user/group/index.md6
-rw-r--r--doc/user/index.md11
-rw-r--r--doc/user/profile/img/profile_settings_dropdown.pngbin0 -> 4184 bytes
-rw-r--r--doc/user/project/gpg_signed_commits/img/profile_settings_gpg_keys_paste_pub.png (renamed from doc/workflow/gpg_signed_commits/img/profile_settings_gpg_keys_paste_pub.png)bin24514 -> 24514 bytes
-rw-r--r--doc/user/project/gpg_signed_commits/img/profile_settings_gpg_keys_single_key.pngbin0 -> 4403 bytes
-rw-r--r--doc/user/project/gpg_signed_commits/img/project_signed_and_unsigned_commits.pngbin0 -> 41193 bytes
-rw-r--r--doc/user/project/gpg_signed_commits/img/project_signed_commit_unverified_signature.png (renamed from doc/workflow/gpg_signed_commits/img/project_signed_commit_unverified_signature.png)bin9542 -> 9542 bytes
-rw-r--r--doc/user/project/gpg_signed_commits/img/project_signed_commit_verified_signature.png (renamed from doc/workflow/gpg_signed_commits/img/project_signed_commit_verified_signature.png)bin14029 -> 14029 bytes
-rw-r--r--doc/user/project/gpg_signed_commits/index.md245
-rw-r--r--doc/user/project/import/clearcase.md47
-rw-r--r--doc/user/project/import/index.md1
-rw-r--r--doc/user/project/index.md1
-rw-r--r--doc/user/project/issues/img/group_issues_list_view.pngbin0 -> 265130 bytes
-rwxr-xr-xdoc/user/project/issues/img/issue_tracker.pngbin37037 -> 0 bytes
-rw-r--r--doc/user/project/issues/img/project_issues_list_view.pngbin0 -> 309131 bytes
-rw-r--r--doc/user/project/issues/index.md30
-rw-r--r--doc/user/project/merge_requests/img/group_merge_requests_list_view.pngbin0 -> 283066 bytes
-rw-r--r--doc/user/project/merge_requests/img/merge_request_diff_file_navigation.pngbin0 -> 76052 bytes
-rw-r--r--doc/user/project/merge_requests/img/project_merge_requests_list_view.pngbin0 -> 325819 bytes
-rw-r--r--doc/user/project/merge_requests/index.md28
-rw-r--r--doc/user/search/index.md8
-rw-r--r--doc/workflow/gpg_signed_commits/img/profile_settings_gpg_keys.pngbin32699 -> 0 bytes
-rw-r--r--doc/workflow/gpg_signed_commits/img/profile_settings_gpg_keys_single_key.pngbin10331 -> 0 bytes
-rw-r--r--doc/workflow/gpg_signed_commits/img/project_signed_and_unsigned_commits.pngbin112812 -> 0 bytes
-rw-r--r--doc/workflow/gpg_signed_commits/index.md84
-rw-r--r--docker/README.md6
-rw-r--r--features/project/source/search_code.feature15
-rw-r--r--features/project/star.feature39
-rw-r--r--features/steps/project/graph.rb6
-rw-r--r--features/steps/project/pages.rb6
-rw-r--r--features/steps/project/source/search_code.rb19
-rw-r--r--features/steps/project/star.rb37
-rw-r--r--features/steps/shared/paths.rb4
-rw-r--r--lib/after_commit_queue.rb2
-rw-r--r--lib/api/access_requests.rb8
-rw-r--r--lib/api/award_emoji.rb3
-rw-r--r--lib/api/boards.rb10
-rw-r--r--lib/api/branches.rb15
-rw-r--r--lib/api/broadcast_messages.rb3
-rw-r--r--lib/api/deploy_keys.rb3
-rw-r--r--lib/api/environments.rb3
-rw-r--r--lib/api/group_variables.rb3
-rw-r--r--lib/api/groups.rb25
-rw-r--r--lib/api/helpers.rb19
-rw-r--r--lib/api/issues.rb4
-rw-r--r--lib/api/labels.rb3
-rw-r--r--lib/api/members.rb8
-rw-r--r--lib/api/merge_requests.rb4
-rw-r--r--lib/api/notes.rb6
-rw-r--r--lib/api/pipeline_schedules.rb3
-rw-r--r--lib/api/project_hooks.rb3
-rw-r--r--lib/api/project_snippets.rb4
-rw-r--r--lib/api/projects.rb12
-rw-r--r--lib/api/protected_branches.rb4
-rw-r--r--lib/api/runner.rb8
-rw-r--r--lib/api/runners.rb7
-rw-r--r--lib/api/services.rb12
-rw-r--r--lib/api/snippets.rb3
-rw-r--r--lib/api/system_hooks.rb3
-rw-r--r--lib/api/tags.rb15
-rw-r--r--lib/api/triggers.rb3
-rw-r--r--lib/api/users.rb32
-rw-r--r--lib/api/variables.rb1
-rw-r--r--lib/backup/repository.rb2
-rw-r--r--lib/ci/api/api.rb39
-rw-r--r--lib/ci/api/builds.rb219
-rw-r--r--lib/ci/api/entities.rb93
-rw-r--r--lib/ci/api/helpers.rb89
-rw-r--r--lib/ci/api/runners.rb50
-rw-r--r--lib/ci/api/triggers.rb39
-rw-r--r--lib/github/import.rb2
-rw-r--r--lib/gitlab/background_migration/deserialize_merge_request_diffs_and_commits.rb14
-rw-r--r--lib/gitlab/background_migration/migrate_stage_status.rb77
-rw-r--r--lib/gitlab/bare_repository_importer.rb96
-rw-r--r--lib/gitlab/checks/force_push.rb2
-rw-r--r--lib/gitlab/data_builder/push.rb33
-rw-r--r--lib/gitlab/data_builder/repository.rb21
-rw-r--r--lib/gitlab/database/migration_helpers.rb19
-rw-r--r--lib/gitlab/diff/file.rb11
-rw-r--r--lib/gitlab/file_finder.rb43
-rw-r--r--lib/gitlab/git/commit.rb8
-rw-r--r--lib/gitlab/git/committer.rb21
-rw-r--r--lib/gitlab/git/hook.rb17
-rw-r--r--lib/gitlab/git/hooks_service.rb36
-rw-r--r--lib/gitlab/git/repository.rb120
-rw-r--r--lib/gitlab/git_access.rb19
-rw-r--r--lib/gitlab/gitaly_client/commit_service.rb20
-rw-r--r--lib/gitlab/gitaly_client/ref_service.rb8
-rw-r--r--lib/gitlab/health_checks/db_check.rb2
-rw-r--r--lib/gitlab/health_checks/redis/cache_check.rb2
-rw-r--r--lib/gitlab/health_checks/redis/queues_check.rb2
-rw-r--r--lib/gitlab/health_checks/redis/redis_check.rb2
-rw-r--r--lib/gitlab/health_checks/redis/shared_state_check.rb2
-rw-r--r--lib/gitlab/health_checks/simple_abstract_check.rb8
-rw-r--r--lib/gitlab/import_export/import_export.yml7
-rw-r--r--lib/gitlab/import_export/merge_request_parser.rb2
-rw-r--r--lib/gitlab/job_waiter.rb57
-rw-r--r--lib/gitlab/ldap/adapter.rb6
-rw-r--r--lib/gitlab/ldap/person.rb9
-rw-r--r--lib/gitlab/logger.rb8
-rw-r--r--lib/gitlab/prometheus/queries/matched_metrics_query.rb4
-rw-r--r--lib/gitlab/regex.rb3
-rw-r--r--lib/gitlab/sidekiq_throttler.rb2
-rw-r--r--lib/system_check/app/git_config_check.rb2
-rw-r--r--lib/system_check/base_check.rb2
-rw-r--r--lib/system_check/simple_executor.rb2
-rw-r--r--lib/tasks/gitlab/import.rake65
-rw-r--r--lib/tasks/gitlab/task_helpers.rb4
-rw-r--r--lib/tasks/import.rake18
-rw-r--r--locale/bg/gitlab.po384
-rw-r--r--locale/de/gitlab.po1014
-rw-r--r--locale/eo/gitlab.po377
-rw-r--r--locale/es/gitlab.po187
-rw-r--r--locale/fr/gitlab.po429
-rw-r--r--locale/gitlab.pot22
-rw-r--r--locale/it/gitlab.po439
-rw-r--r--locale/ja/gitlab.po325
-rw-r--r--locale/ko/gitlab.po324
-rw-r--r--locale/pt_BR/gitlab.po406
-rw-r--r--locale/ru/gitlab.po393
-rw-r--r--locale/uk/gitlab.po386
-rw-r--r--locale/zh_CN/gitlab.po285
-rw-r--r--locale/zh_HK/gitlab.po284
-rw-r--r--locale/zh_TW/gitlab.po310
-rw-r--r--package.json4
-rw-r--r--public/404.html6
-rw-r--r--public/422.html6
-rw-r--r--public/500.html6
-rw-r--r--public/502.html6
-rw-r--r--public/503.html6
-rw-r--r--public/deploy.html6
-rw-r--r--spec/controllers/autocomplete_controller_spec.rb38
-rw-r--r--spec/controllers/projects/issues_controller_spec.rb8
-rw-r--r--spec/controllers/projects/protected_tags_controller_spec.rb17
-rw-r--r--spec/controllers/projects/services_controller_spec.rb42
-rw-r--r--spec/controllers/projects/snippets_controller_spec.rb4
-rw-r--r--spec/controllers/snippets_controller_spec.rb4
-rw-r--r--spec/factories/ci/stages.rb8
-rw-r--r--spec/factories/ci/triggers.rb2
-rw-r--r--spec/factories/projects.rb4
-rw-r--r--spec/features/admin/admin_projects_spec.rb8
-rw-r--r--spec/features/atom/users_spec.rb6
-rw-r--r--spec/features/calendar_spec.rb2
-rw-r--r--spec/features/dashboard/activity_spec.rb2
-rw-r--r--spec/features/dashboard/archived_projects_spec.rb7
-rw-r--r--spec/features/explore/new_menu_spec.rb2
-rw-r--r--spec/features/groups/merge_requests_spec.rb15
-rw-r--r--spec/features/groups_spec.rb17
-rw-r--r--spec/features/issues/filtered_search/dropdown_assignee_spec.rb6
-rw-r--r--spec/features/issues/filtered_search/dropdown_emoji_spec.rb182
-rw-r--r--spec/features/issues/filtered_search/dropdown_hint_spec.rb288
-rw-r--r--spec/features/issues/filtered_search/dropdown_label_spec.rb6
-rw-r--r--spec/features/issues/filtered_search/dropdown_milestone_spec.rb6
-rw-r--r--spec/features/issues/filtered_search/filter_issues_spec.rb50
-rw-r--r--spec/features/issues/filtered_search/search_bar_spec.rb2
-rw-r--r--spec/features/issues/issue_detail_spec.rb14
-rw-r--r--spec/features/merge_requests/merge_commit_message_toggle_spec.rb4
-rw-r--r--spec/features/projects/commit/mini_pipeline_graph_spec.rb18
-rw-r--r--spec/features/projects/files/find_files_spec.rb23
-rw-r--r--spec/features/projects/files/user_searches_for_files_spec.rb58
-rw-r--r--spec/features/projects/import_export/import_file_spec.rb84
-rw-r--r--spec/features/projects/user_creates_files_spec.rb3
-rw-r--r--spec/features/projects/user_interacts_with_stars_spec.rb38
-rw-r--r--spec/features/runners_spec.rb198
-rw-r--r--spec/features/search_spec.rb26
-rw-r--r--spec/features/snippets/notes_on_personal_snippets_spec.rb2
-rw-r--r--spec/features/tags/master_deletes_tag_spec.rb4
-rw-r--r--spec/finders/admin/projects_finder_spec.rb6
-rw-r--r--spec/finders/issues_finder_spec.rb35
-rw-r--r--spec/finders/projects_finder_spec.rb6
-rw-r--r--spec/fixtures/emails/ios_default.eml12
-rw-r--r--spec/fixtures/emails/on_wrote.eml6
-rw-r--r--spec/helpers/avatars_helper_spec.rb42
-rw-r--r--spec/helpers/button_helper_spec.rb63
-rw-r--r--spec/helpers/events_helper_spec.rb10
-rw-r--r--spec/javascripts/api_spec.js26
-rw-r--r--spec/javascripts/boards/board_new_issue_spec.js8
-rw-r--r--spec/javascripts/boards/issue_card_spec.js19
-rw-r--r--spec/javascripts/droplab/drop_down_spec.js15
-rw-r--r--spec/javascripts/fixtures/project_select_combo_button.html.haml2
-rw-r--r--spec/javascripts/helpers/vue_mount_component_helper.js4
-rw-r--r--spec/javascripts/lib/utils/text_utility_spec.js1
-rw-r--r--spec/javascripts/merge_request_tabs_spec.js11
-rw-r--r--spec/javascripts/pipelines/navigation_tabs_spec.js127
-rw-r--r--spec/javascripts/project_select_combo_button_spec.js35
-rw-r--r--spec/javascripts/project_title_spec.js6
-rw-r--r--spec/javascripts/repo/components/repo_commit_section_spec.js9
-rw-r--r--spec/javascripts/repo/monaco_loader_spec.js12
-rw-r--r--spec/javascripts/repo/services/repo_service_spec.js50
-rw-r--r--spec/javascripts/vue_shared/components/identicon_spec.js (renamed from spec/javascripts/groups/group_identicon_spec.js)14
-rw-r--r--spec/lib/gitlab/background_migration/deserialize_merge_request_diffs_and_commits_spec.rb11
-rw-r--r--spec/lib/gitlab/background_migration/migrate_stage_status_spec.rb80
-rw-r--r--spec/lib/gitlab/bare_repository_importer_spec.rb100
-rw-r--r--spec/lib/gitlab/database/migration_helpers_spec.rb51
-rw-r--r--spec/lib/gitlab/diff/file_spec.rb58
-rw-r--r--spec/lib/gitlab/file_finder_spec.rb14
-rw-r--r--spec/lib/gitlab/git/blame_spec.rb2
-rw-r--r--spec/lib/gitlab/git/blob_spec.rb2
-rw-r--r--spec/lib/gitlab/git/branch_spec.rb2
-rw-r--r--spec/lib/gitlab/git/commit_spec.rb8
-rw-r--r--spec/lib/gitlab/git/committer_spec.rb22
-rw-r--r--spec/lib/gitlab/git/compare_spec.rb2
-rw-r--r--spec/lib/gitlab/git/diff_spec.rb2
-rw-r--r--spec/lib/gitlab/git/hook_spec.rb9
-rw-r--r--spec/lib/gitlab/git/hooks_service_spec.rb (renamed from spec/services/git_hooks_service_spec.rb)22
-rw-r--r--spec/lib/gitlab/git/index_spec.rb2
-rw-r--r--spec/lib/gitlab/git/repository_spec.rb149
-rw-r--r--spec/lib/gitlab/git/storage/forked_storage_check_spec.rb2
-rw-r--r--spec/lib/gitlab/git/tag_spec.rb2
-rw-r--r--spec/lib/gitlab/git/tree_spec.rb2
-rw-r--r--spec/lib/gitlab/git_access_spec.rb251
-rw-r--r--spec/lib/gitlab/gitaly_client/commit_service_spec.rb39
-rw-r--r--spec/lib/gitlab/gitaly_client/ref_service_spec.rb21
-rw-r--r--spec/lib/gitlab/import_export/project.json5
-rw-r--r--spec/lib/gitlab/import_export/project_tree_restorer_spec.rb11
-rw-r--r--spec/lib/gitlab/import_export/project_tree_saver_spec.rb10
-rw-r--r--spec/lib/gitlab/import_export/repo_restorer_spec.rb2
-rw-r--r--spec/lib/gitlab/import_export/safe_model_attributes.yml2
-rw-r--r--spec/lib/gitlab/job_waiter_spec.rb41
-rw-r--r--spec/lib/gitlab/ldap/adapter_spec.rb6
-rw-r--r--spec/lib/gitlab/sidekiq_throttler_spec.rb50
-rw-r--r--spec/migrations/cleanup_namespaceless_pending_delete_projects_spec.rb2
-rw-r--r--spec/migrations/cleanup_nonexisting_namespace_pending_delete_projects_spec.rb32
-rw-r--r--spec/migrations/migrate_pipeline_sidekiq_queues_spec.rb55
-rw-r--r--spec/migrations/migrate_stage_id_reference_in_background_spec.rb13
-rw-r--r--spec/migrations/migrate_stages_statuses_spec.rb68
-rw-r--r--spec/migrations/remove_dot_git_from_usernames_spec.rb3
-rw-r--r--spec/models/broadcast_message_spec.rb23
-rw-r--r--spec/models/ci/build_spec.rb10
-rw-r--r--spec/models/ci/pipeline_spec.rb14
-rw-r--r--spec/models/ci/stage_spec.rb90
-rw-r--r--spec/models/commit_status_spec.rb6
-rw-r--r--spec/models/concerns/awardable_spec.rb22
-rw-r--r--spec/models/concerns/editable_spec.rb6
-rw-r--r--spec/models/event_spec.rb44
-rw-r--r--spec/models/issue_spec.rb18
-rw-r--r--spec/models/merge_request_spec.rb50
-rw-r--r--spec/models/project_services/kubernetes_service_spec.rb3
-rw-r--r--spec/models/project_spec.rb231
-rw-r--r--spec/models/repository_spec.rb59
-rw-r--r--spec/models/user_spec.rb63
-rw-r--r--spec/policies/group_policy_spec.rb36
-rw-r--r--spec/requests/api/award_emoji_spec.rb16
-rw-r--r--spec/requests/api/boards_spec.rb4
-rw-r--r--spec/requests/api/branches_spec.rb4
-rw-r--r--spec/requests/api/broadcast_messages_spec.rb4
-rw-r--r--spec/requests/api/deploy_keys_spec.rb4
-rw-r--r--spec/requests/api/environments_spec.rb4
-rw-r--r--spec/requests/api/group_variables_spec.rb4
-rw-r--r--spec/requests/api/groups_spec.rb26
-rw-r--r--spec/requests/api/issues_spec.rb8
-rw-r--r--spec/requests/api/labels_spec.rb5
-rw-r--r--spec/requests/api/members_spec.rb4
-rw-r--r--spec/requests/api/merge_requests_spec.rb4
-rw-r--r--spec/requests/api/notes_spec.rb12
-rw-r--r--spec/requests/api/pipeline_schedules_spec.rb7
-rw-r--r--spec/requests/api/project_hooks_spec.rb4
-rw-r--r--spec/requests/api/project_snippets_spec.rb11
-rw-r--r--spec/requests/api/projects_spec.rb71
-rw-r--r--spec/requests/api/protected_branches_spec.rb4
-rw-r--r--spec/requests/api/runner_spec.rb5
-rw-r--r--spec/requests/api/runners_spec.rb12
-rw-r--r--spec/requests/api/snippets_spec.rb8
-rw-r--r--spec/requests/api/system_hooks_spec.rb4
-rw-r--r--spec/requests/api/tags_spec.rb6
-rw-r--r--spec/requests/api/triggers_spec.rb27
-rw-r--r--spec/requests/api/users_spec.rb24
-rw-r--r--spec/requests/api/v3/issues_spec.rb4
-rw-r--r--spec/requests/api/v3/project_snippets_spec.rb4
-rw-r--r--spec/requests/api/v3/snippets_spec.rb2
-rw-r--r--spec/requests/api/v3/triggers_spec.rb5
-rw-r--r--spec/requests/ci/api/builds_spec.rb912
-rw-r--r--spec/requests/ci/api/runners_spec.rb127
-rw-r--r--spec/requests/ci/api/triggers_spec.rb90
-rw-r--r--spec/services/ci/create_pipeline_service_spec.rb87
-rw-r--r--spec/services/files/update_service_spec.rb2
-rw-r--r--spec/services/git_push_service_spec.rb4
-rw-r--r--spec/services/groups/create_service_spec.rb16
-rw-r--r--spec/services/groups/destroy_service_spec.rb26
-rw-r--r--spec/services/groups/nested_create_service_spec.rb88
-rw-r--r--spec/services/issues/close_service_spec.rb5
-rw-r--r--spec/services/issues/create_service_spec.rb8
-rw-r--r--spec/services/issues/reopen_service_spec.rb7
-rw-r--r--spec/services/merge_requests/close_service_spec.rb7
-rw-r--r--spec/services/merge_requests/create_from_issue_service_spec.rb20
-rw-r--r--spec/services/merge_requests/create_service_spec.rb32
-rw-r--r--spec/services/merge_requests/merge_service_spec.rb34
-rw-r--r--spec/services/merge_requests/reopen_service_spec.rb7
-rw-r--r--spec/services/notification_service_spec.rb17
-rw-r--r--spec/services/projects/count_service_spec.rb73
-rw-r--r--spec/services/projects/create_service_spec.rb2
-rw-r--r--spec/services/projects/forks_count_service_spec.rb32
-rw-r--r--spec/services/projects/open_issues_count_service_spec.rb21
-rw-r--r--spec/services/projects/open_merge_requests_count_service_spec.rb15
-rw-r--r--spec/services/spam_service_spec.rb6
-rw-r--r--spec/services/system_note_service_spec.rb29
-rw-r--r--spec/services/tags/create_service_spec.rb2
-rw-r--r--spec/services/test_hooks/system_service_spec.rb33
-rw-r--r--spec/services/user_project_access_changed_service_spec.rb7
-rw-r--r--spec/services/users/destroy_service_spec.rb27
-rw-r--r--spec/services/users/update_service_spec.rb32
-rw-r--r--spec/spec_helper.rb12
-rw-r--r--spec/support/api_helpers.rb14
-rw-r--r--spec/support/background_migrations_matchers.rb13
-rw-r--r--spec/support/cycle_analytics_helpers.rb2
-rw-r--r--spec/support/db_cleaner.rb6
-rw-r--r--spec/support/features/reportable_note_shared_examples.rb2
-rw-r--r--spec/support/filtered_search_helpers.rb10
-rw-r--r--spec/support/helpers/note_interaction_helpers.rb2
-rw-r--r--spec/support/import_export/export_file_helper.rb3
-rw-r--r--spec/support/migrations_helpers.rb2
-rw-r--r--spec/support/shared_examples/requests/api/status_shared_examples.rb25
-rw-r--r--spec/workers/authorized_projects_worker_spec.rb71
-rw-r--r--spec/workers/build_finished_worker_spec.rb2
-rw-r--r--spec/workers/concerns/build_queue_spec.rb14
-rw-r--r--spec/workers/concerns/pipeline_queue_spec.rb14
-rw-r--r--spec/workers/merge_worker_spec.rb11
-rw-r--r--spec/workers/namespaceless_project_destroy_worker_spec.rb16
-rw-r--r--spec/workers/pipeline_metrics_worker_spec.rb9
-rw-r--r--spec/workers/stage_update_worker_spec.rb22
-rw-r--r--vendor/assets/stylesheets/katex.scss34
-rw-r--r--vendor/assets/stylesheets/xterm/xterm.css2
-rw-r--r--vendor/project_templates/express.tar.gzbin4572 -> 5645 bytes
-rw-r--r--vendor/project_templates/rails.tar.gzbin23749 -> 24777 bytes
-rw-r--r--vendor/project_templates/spring.tar.gzbin49882 -> 50845 bytes
-rw-r--r--yarn.lock894
896 files changed, 12137 insertions, 7456 deletions
diff --git a/.eslintrc b/.eslintrc
index 3e07edbccfe..44ad6a4896c 100644
--- a/.eslintrc
+++ b/.eslintrc
@@ -6,6 +6,7 @@
},
"extends": "airbnb-base",
"globals": {
+ "__webpack_public_path__": true,
"_": false,
"gl": false,
"gon": false,
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index df7244d5a2e..ab9627d4ab7 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -68,19 +68,6 @@ stages:
- mysql:latest
- redis:alpine
-.only-if-want-mysql: &only-if-want-mysql
- only:
- - /mysql/
- - /-stable/
- - master@gitlab-org/gitlab-ce
- - master@gitlab-org/gitlab-ee
- - master@gitlab/gitlabhq
- - master@gitlab/gitlab-ee
- - tags@gitlab-org/gitlab-ce
- - tags@gitlab-org/gitlab-ee
- - tags@gitlab/gitlabhq
- - tags@gitlab/gitlab-ee
-
# Skip all jobs except the ones that begin with 'docs/'.
# Used for commits including ONLY documentation changes.
# https://docs.gitlab.com/ce/development/writing_documentation.html#testing
@@ -124,7 +111,6 @@ stages:
.rspec-metadata-mysql: &rspec-metadata-mysql
<<: *rspec-metadata
<<: *use-mysql
- <<: *only-if-want-mysql
<<: *except-docs
.spinach-metadata: &spinach-metadata
@@ -156,7 +142,6 @@ stages:
.spinach-metadata-mysql: &spinach-metadata-mysql
<<: *spinach-metadata
<<: *use-mysql
- <<: *only-if-want-mysql
<<: *except-docs
.only-canonical-masters: &only-canonical-masters
@@ -259,7 +244,7 @@ setup-test-env:
<<: *default-cache
script:
- node --version
- - yarn install --pure-lockfile --cache-folder .yarn-cache
+ - yarn install --frozen-lockfile --cache-folder .yarn-cache
- bundle exec rake gettext:po_to_json
- bundle exec rake gitlab:assets:compile
- bundle exec ruby -Ispec -e 'require "spec_helper" ; TestEnv.init'
@@ -508,7 +493,7 @@ gitlab:assets:compile:
WEBPACK_REPORT: "true"
NO_COMPRESSION: "true"
script:
- - yarn install --pure-lockfile --production --cache-folder .yarn-cache
+ - yarn install --frozen-lockfile --production --cache-folder .yarn-cache
- bundle exec rake gettext:po_to_json
- bundle exec rake gitlab:assets:compile
artifacts:
@@ -522,7 +507,7 @@ karma:
<<: *dedicated-runner
<<: *except-docs
<<: *pull-cache
- image: "dev.gitlab.org:5005/gitlab/gitlab-build-images:ruby-2.3.3-golang-1.8-git-2.13-chrome-59.0-node-7.1-postgresql-9.6"
+ image: "dev.gitlab.org:5005/gitlab/gitlab-build-images:ruby-2.3.3-golang-1.8-git-2.13-chrome-60.0-node-7.1-postgresql-9.6"
stage: test
variables:
BABEL_ENV: "coverage"
diff --git a/.rubocop.yml b/.rubocop.yml
index 23bb0fa8be8..3edd1643d48 100644
--- a/.rubocop.yml
+++ b/.rubocop.yml
@@ -606,6 +606,18 @@ Style/YodaCondition:
Style/Proc:
Enabled: true
+# Use `spam?` instead of `is_spam?`
+# Configuration parameters: NamePrefix, NamePrefixBlacklist, NameWhitelist.
+# NamePrefix: is_, has_, have_
+# NamePrefixBlacklist: is_, has_, have_
+# NameWhitelist: is_a?
+Style/PredicateName:
+ Enabled: true
+ NamePrefixBlacklist: is_
+ Exclude:
+ - 'spec/**/*'
+ - 'features/**/*'
+
# Metrics #####################################################################
# A calculated magnitude based on number of assignments,
@@ -631,7 +643,7 @@ Metrics/ClassLength:
# of test cases needed to validate a method.
Metrics/CyclomaticComplexity:
Enabled: true
- Max: 16
+ Max: 15
# Limit lines to 80 characters.
Metrics/LineLength:
@@ -1181,6 +1193,10 @@ GitlabSecurity/DeepMunge:
- 'lib/**/*.rake'
- 'spec/**/*'
+# To be enabled by https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/13610
+GitlabSecurity/JsonSerialization:
+ Enabled: false
+
GitlabSecurity/PublicSend:
Enabled: true
Exclude:
diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml
index 4b4f14efea4..cdf97d1d842 100644
--- a/.rubocop_todo.yml
+++ b/.rubocop_todo.yml
@@ -237,14 +237,6 @@ Style/PercentLiteralDelimiters:
Style/PerlBackrefs:
Enabled: false
-# Offense count: 105
-# Configuration parameters: NamePrefix, NamePrefixBlacklist, NameWhitelist.
-# NamePrefix: is_, has_, have_
-# NamePrefixBlacklist: is_, has_, have_
-# NameWhitelist: is_a?
-Style/PredicateName:
- Enabled: false
-
# Offense count: 58
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle, SupportedStyles.
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 3ecedd44c89..ac0d22ced46 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,189 @@
documentation](doc/development/changelog.md) for instructions on adding your own
entry.
+## 9.5.2 (2017-08-28)
+
+- [FIXED] Fix signing in using LDAP when attribute mapping uses simple strings instead of arrays.
+- [FIXED] Show un-highlighted text diffs when we do not have references to the correct blobs.
+- [FIXED] Fix display of push events for removed refs.
+- [FIXED] Testing of some integrations were broken due to missing ServiceHook record.
+- [FIXED] Fire system hooks when a user is created via LDAP.
+- [FIXED] Fix new project form not resetting the template value.
+
+## 9.5.1 (2017-08-23)
+
+- [FIXED] Fix merge request pipeline status when pipeline has errors. !13664
+- [FIXED] Commit rows would occasionally render with the wrong language.
+- [FIXED] Fix caching of future broadcast messages.
+- [FIXED] Only require Sidekiq throttling library when enabled, to reduce cache misses.
+- Raise Housekeeping timeout to 24 hours. !13719
+
+## 9.5.0 (2017-08-22)
+
+- [FIXED] Fix timeouts when creating projects in groups with many members. !13508
+- [FIXED] Improve API pagination headers when no record found. !13629 (Jordan Patterson)
+- [FIXED] Fix deleting GitLab Pages files when a project is removed. !13631
+- [FIXED] Fix commit list not loading the correct page when scrolling.
+- [OTHER] Cache the number of forks of a project. !13535
+- GPG signed commits integration. !9546 (Alexis Reigel)
+- Alert the user if a Wiki page changed while they were editing it in order to prevent overwriting changes. !9707 (Hiroyuki Sato)
+- Add custom linter for inline JavaScript to haml_lint. !9742 (winniehell)
+- Add /shrug and /tableflip commands. !10068 (Alex Ives)
+- Allow wiki pages to be renamed in the UI. !10069 (wendy0402)
+- Insert user name directly without encoding. !10085 (Nathan Neulinger <nneul@neulinger.org>)
+- Avoid plucking Todo ids in TodoService. !10845
+- Handle errors while a project is being deleted asynchronously. !11088
+- Decrease ABC threshold to 56.96. !11227 (Maxim Rydkin)
+- Remove Mattermost team when deleting a group. !11362
+- Block access to failing repository storage. !11449
+- Add coordinator url to admin area runner page. !11603
+- Allow testing any events for project hooks and system hooks. !11728 (Alexander Randa (@randaalex))
+- Disallow running the pipeline if ref is protected and user cannot merge the branch or create the tag. !11910
+- Remove project_key from the Jira configuration. !12050
+- Add CSRF token verification to API. !12154 (Vitaliy @blackst0ne Klachkov)
+- Fixes needed when GitLab sign-in is not enabled. !12491 (Robin Bobbitt)
+- Lazy load images for better Frontend performance. !12503
+- Replaces dashboard/event_filters.feature spinach with rspec. !12651 (Alexander Randa (@randaalex))
+- Toggle import description with import_sources_enabled. !12691 (Brianna Kicia)
+- Bump scss-lint to 0.54.0. !12733 (Takuya Noguchi)
+- Enable SpaceAfterComma in scss-lint. !12734 (Takuya Noguchi)
+- Remove CSS for nprogress removed. !12737 (Takuya Noguchi)
+- Enable UnnecessaryParentReference in scss-lint. !12738 (Takuya Noguchi)
+- Extract "@request.env[devise.mapping] = Devise.mappings[:user]" to a test helper. !12742 (Jacopo Beschi @jacopo-beschi)
+- Enable ImportPath in scss-lint. !12749 (Takuya Noguchi)
+- Enable PropertySpelling in scss-lint. !12752 (Takuya Noguchi)
+- Add API for protected branches to allow for wildcard matching and no access restrictions. !12756 (Eric Yu)
+- refactor initializations in dropzone_input.js. !12768 (Brandon Everett)
+- Improve CSS for global nav dropdown UI. !12772 (Takuya Noguchi)
+- Remove public/ci/favicon.ico. !12803 (Takuya Noguchi)
+- Enable DeclarationOrder in scss-lint. !12805 (Takuya Noguchi)
+- Increase width of dropdown menus automatically. !12809 (Thomas Wucher)
+- Enable BangFormat in scss-lint [ci skip]. !12815 (Takuya Noguchi)
+- Added /duplicate quick action to close a duplicate issue. !12845 (Ryan Scott)
+- Make all application-settings accessible through the API. !12851
+- Remove Inactive Personal Access Tokens list from Access Tokens page. !12866
+- Replaces dashboard/dashboard.feature spinach with rspec. !12876 (Alexander Randa (@randaalex))
+- Reduce memory usage of the GitHub importer. !12886
+- Bump fog-core to 1.44.3 and fog providers' plugins to latest. !12897 (Takuya Noguchi)
+- Use only CSS to truncate commit message in blame. !12900 (Takuya Noguchi)
+- Protect manual actions against protected tag too. !12908
+- Allow to configure automatic retry of a failed CI/CD job. !12909
+- Remove help message about prioritized labels for non-members. !12912 (Takuya Noguchi)
+- Add link to doc/api/ci/lint.md. !12914 (Takuya Noguchi)
+- Add RequestCache which makes caching with RequestStore easier. !12920
+- Free up some top level words, reject top level groups named like files in the public folder. !12932
+- Extend API for Group Secret Variable. !12936
+- Hide description about protected branches to non-member. !12945 (Takuya Noguchi)
+- Support custom directory in gitlab:backup:create task. !12984 (Markus Koller)
+- Raise guessed encoding confidence threshold to 50. !12990
+- Add author_id & assignee_id param to /issues API. !13004
+- Fix today day highlight in calendar. !13048
+- Prevent LDAP login callback from being called with a GET request. !13059
+- Add top-level merge_requests API endpoint. !13060
+- Handle maximum pages artifacts size correctly. !13072
+- Enable gitaly_post_upload_pack by default. !13078
+- Add Prometheus metrics exporter to Sidekiq. !13082
+- Fix improperly skipped backups of wikis. !13096
+- Projects can be created from templates. !13108
+- Fix the /projects/:id/repository/branches endpoint to handle dots in the branch name when the project full path contains a `/`. !13115
+- Fix project logos that are not centered vertically on list pages. !13124 (Florian Lemaitre)
+- Derive project path from import URL. !13131
+- Fix deletion of deploy keys linked to other projects. !13162
+- repository archive download url now ends with selected file extension. !13178 (haseebeqx)
+- Show auto-generated avatars for Groups without avatars. !13188
+- Allow any logged in users to read_users_list even if it's restricted. !13201
+- Unlock stuck merge request and set the proper state. !13207
+- Fix timezone inconsistencies in user contribution graph. !13208
+- Fix Issue board when using Ruby 2.4. !13220
+- Don't rename namespace called system when upgrading from 9.1.x to 9.5. !13228
+- Fix encoding error for WebHook logging. !13230 (Alexander Randa (@randaalex))
+- Uniquify reserved word usernames on OAuth user creation. !13244 (Robin Bobbitt)
+- Expose target_iid in Events API. !13247 (sue445)
+- Add star for action scope, in order to delete image from registry. !13248 (jean)
+- Make Delete Merged Branches handle wildcard protected branches correctly. !13251
+- Fix an order of operations for CI connection error message in merge request widget. !13252
+- Don't send rejection mails for all auto-generated mails. !13254
+- Expose noteable_iid in Note. !13265 (sue445)
+- Fix pipeline_schedules pages when active schedule has an abnormal state. !13286
+- Move some code from services to workers in order to improve performance. !13326
+- Fix destroy of case-insensitive conflicting redirects. !13357
+- Fix the /projects/:id/repository/tags endpoint to handle dots in the tag name when the project full path contains a `/`. !13368
+- Fix the /projects/:id/repository/commits endpoint to handle dots in the ref name when the project full path contains a `/`. !13370
+- Project pending delete no longer return 500 error in admins projects view. !13389
+- Use full path of user's avatar in webhooks. !13401 (Vitaliy @blackst0ne Klachkov)
+- Make GPGME temporary directory handling thread safe. !13481 (Alexis Reigel)
+- Add support for kube_namespace in Metrics queries. !16169
+- Fix bar chart does not display label at 0 hour. !35136 (Jason Dai)
+- Use project_ref_path to create the link to a branch to fix links that 404.
+- Declare related resources into V4 API entities.
+- Add Slack and JIRA services counts to Usage Data.
+- Prevent web hook and project service background jobs from going to the dead jobs queue.
+- Display specific error message when JIRA test fails.
+- clean up merge request widget UI.
+- Associate Issues tab only with internal issues tracker.
+- Remove events column from notification settings table.
+- Clarifies and rearranges the input variables on the kubernetes integration page and adjusts the docs slightly to meet the same order.
+- Respect blockquote line breaks in markdown.
+- Update confidential issue UI - add confidential visibility and settings to sidebar.
+- Add icons to contextual sidebars.
+- Make contextual sidebar collapsible.
+- Update Pipeline's badge count in Merge Request and Commits view to match real-time content.
+- Added link to the MR widget that directs to the monitoring dashboard.
+- Use jQuery to control scroll behavior in job log for cross browser consistency.
+- move edit comment button outside of dropdown.
+- Updates vue resource and code according to breaking changes.
+- Add GitHub imported projects count to usage data.
+- Rename about to overview for group and project page.
+- Prevent disabled pagination button to be clicked.
+- Remove coffee-rails gem. (Takuya Noguchi)
+- Remove net-ssh gem. (Takuya Noguchi)
+- Bump rubocop to 0.49.1 and rubocop-rspec to 1.15.1. (Takuya Noguchi)
+- improve file upload/replace experience.
+- allow closing Cycle Analytics intro box in firefox.
+- Fix label creation from new list for subgroup projects.
+- fix transient js error in rspec tests.
+- fix jump to next discussion button.
+- Fix translations for Star/Unstar in JS file.
+- Improve mobile sidebar.
+- Rename Pipelines tab to CI / CD in new navigation.
+- Fix display of new diff comments after changing b between diff views.
+- Store & use ConvDev percentages returned by the Version app.
+- Fixes new issue button for failed job returning 404.
+- Align OR separator to center in new project page.
+- Add filtered search to group issue dashboard.
+- Cache Appearance instances in Redis.
+- Fixed breadcrumbs title aggressively collapsing.
+- Better caching and indexing of broadcast messages.
+- Moved diff changed files into a dropdown.
+- Improve performance of large (initial) push into default branch.
+- Improve performance of checking for projects on the projects dashboard.
+- Eager load project creators for project dashboards.
+- Modify if condition to be more readable.
+- Fix links to group milestones from issue and merge request sidebar.
+- Remove hidden symlinks from project import files.
+- Fixed sign-in restrictions buttons not toggling active state.
+- Fix replying to commit comments on merge requests created from forks.
+- Support Markdown references, autocomplete, and quick actions for group milestones.
+- Cache recent projects for group-level new resource creation.
+- Fix API responses when dealing with txt files.
+- Fix project milestones import when projects belongs to a group.
+- Fix Mattermost integration.
+- Memoize the number of personal projects a user has to reduce COUNT queries.
+- Merge issuable "reopened" state into "opened".
+- Migrate events into a new format to reduce the storage necessary and improve performance.
+- MR branch link now links to tree instead of commits.
+- Use Prev/Next pagination for exploring projects.
+- Pass before_script and script as-is preserving arrays.
+- Change project FK migration to skip existing FKs.
+- Remove redundant query when retrieving the most recent push of a user.
+- Re-organise "issues" indexes for faster ordering.
+- Disallow Git URLs that include a username or hostname beginning with a non-alphanumeric character.
+- Fix search box losing focus when typing.
+- Add structured logging for Rails processes.
+- Skip oAuth authorization for trusted applications.
+- Use a specialized class for querying events to improve performance.
+- Update build badges to be pipeline badges and display passing instead of success.
+
## 9.4.5 (2017-08-14)
- Fix deletion of deploy keys linked to other projects. !13162
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 12fb34b24be..6cc34f1de08 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -164,7 +164,7 @@ Assigning a team label makes sure issues get the attention of the appropriate
people.
The current team labels are ~Build, ~CI, ~Discussion, ~Documentation, ~Edge,
-~Gitaly, ~Platform, ~Prometheus, ~Release, and ~"UX".
+~Geo, ~Gitaly, ~Platform, ~Prometheus, ~Release, and ~"UX".
The descriptions on the [labels page][labels-page] explain what falls under the
responsibility of each team.
diff --git a/GITALY_SERVER_VERSION b/GITALY_SERVER_VERSION
index 26bea73e811..be386c9ede3 100644
--- a/GITALY_SERVER_VERSION
+++ b/GITALY_SERVER_VERSION
@@ -1 +1 @@
-0.31.0
+0.33.0
diff --git a/Gemfile b/Gemfile
index 62d6b1e6446..8bcf1278267 100644
--- a/Gemfile
+++ b/Gemfile
@@ -152,7 +152,7 @@ gem 'acts-as-taggable-on', '~> 4.0'
gem 'sidekiq', '~> 5.0'
gem 'sidekiq-cron', '~> 0.6.0'
gem 'redis-namespace', '~> 1.5.2'
-gem 'sidekiq-limit_fetch', '~> 3.4'
+gem 'sidekiq-limit_fetch', '~> 3.4', require: false
# Cron Parser
gem 'rufus-scheduler', '~> 3.4'
@@ -207,9 +207,6 @@ gem 'kubeclient', '~> 2.2.0'
# d3
gem 'd3_rails', '~> 3.5.0'
-# underscore-rails
-gem 'underscore-rails', '~> 1.8.0'
-
# Sanitize user input
gem 'sanitize', '~> 2.0'
gem 'babosa', '~> 1.0.2'
@@ -287,7 +284,7 @@ group :metrics do
gem 'influxdb', '~> 0.2', require: false
# Prometheus
- gem 'prometheus-client-mmap', '~>0.7.0.beta11'
+ gem 'prometheus-client-mmap', '~>0.7.0.beta14'
gem 'raindrops', '~> 0.18'
end
@@ -340,7 +337,7 @@ group :development, :test do
gem 'rubocop', '~> 0.49.1', require: false
gem 'rubocop-rspec', '~> 1.15.1', require: false
- gem 'rubocop-gitlab-security', '~> 0.0.6', require: false
+ gem 'rubocop-gitlab-security', '~> 0.1.0', require: false
gem 'scss_lint', '~> 0.54.0', require: false
gem 'haml_lint', '~> 0.26.0', require: false
gem 'simplecov', '~> 0.14.0', require: false
@@ -396,12 +393,12 @@ gem 'net-ssh', '~> 4.1.0'
# Required for ED25519 SSH host key support
group :ed25519 do
gem 'rbnacl-libsodium'
- gem 'rbnacl', '~> 3.2'
+ gem 'rbnacl', '~> 4.0'
gem 'bcrypt_pbkdf', '~> 1.0'
end
# Gitaly GRPC client
-gem 'gitaly', '~> 0.27.0'
+gem 'gitaly-proto', '~> 0.31.0', require: 'gitaly'
gem 'toml-rb', '~> 0.3.15', require: false
diff --git a/Gemfile.lock b/Gemfile.lock
index ae1df783a80..3cb458c1707 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -203,7 +203,7 @@ GEM
multi_json
fast_gettext (1.4.0)
ffaker (2.4.0)
- ffi (1.9.10)
+ ffi (1.9.18)
flay (2.8.1)
erubis (~> 2.7.0)
path_expander (~> 1.0)
@@ -275,7 +275,7 @@ GEM
po_to_json (>= 1.0.0)
rails (>= 3.2.0)
gherkin-ruby (0.3.2)
- gitaly (0.27.0)
+ gitaly-proto (0.31.0)
google-protobuf (~> 3.1)
grpc (~> 1.0)
github-linguist (4.7.6)
@@ -619,7 +619,7 @@ GEM
parser
unparser
procto (0.0.3)
- prometheus-client-mmap (0.7.0.beta11)
+ prometheus-client-mmap (0.7.0.beta14)
mmap2 (~> 2.2, >= 2.2.7)
pry (0.10.4)
coderay (~> 1.1.0)
@@ -682,7 +682,7 @@ GEM
rake (12.0.0)
rblineprof (0.3.6)
debugger-ruby_core_source (~> 1.3)
- rbnacl (3.4.0)
+ rbnacl (4.0.2)
ffi
rbnacl-libsodium (1.0.11)
rbnacl (>= 3.0.1)
@@ -722,7 +722,7 @@ GEM
retriable (1.4.1)
rinku (2.0.0)
rotp (2.1.2)
- rouge (2.1.0)
+ rouge (2.2.0)
rqrcode (0.7.0)
chunky_png
rqrcode-rails3 (0.1.7)
@@ -769,7 +769,7 @@ GEM
rainbow (>= 1.99.1, < 3.0)
ruby-progressbar (~> 1.7)
unicode-display_width (~> 1.0, >= 1.0.1)
- rubocop-gitlab-security (0.0.6)
+ rubocop-gitlab-security (0.1.0)
rubocop (>= 0.47.1)
rubocop-rspec (1.15.1)
rubocop (>= 0.42.0)
@@ -899,7 +899,6 @@ GEM
uglifier (2.7.2)
execjs (>= 0.3.0)
json (>= 1.8.0)
- underscore-rails (1.8.3)
unf (0.1.4)
unf_ext
unf_ext (0.0.7.2)
@@ -1019,7 +1018,7 @@ DEPENDENCIES
gettext (~> 3.2.2)
gettext_i18n_rails (~> 1.8.0)
gettext_i18n_rails_js (~> 1.2.0)
- gitaly (~> 0.27.0)
+ gitaly-proto (~> 0.31.0)
github-linguist (~> 4.7.0)
gitlab-flowdock-git-hook (~> 1.0.1)
gitlab-markup (~> 1.5.1)
@@ -1094,7 +1093,7 @@ DEPENDENCIES
pg (~> 0.18.2)
poltergeist (~> 1.9.0)
premailer-rails (~> 1.9.7)
- prometheus-client-mmap (~> 0.7.0.beta11)
+ prometheus-client-mmap (~> 0.7.0.beta14)
pry-byebug (~> 3.4.1)
pry-rails (~> 0.3.4)
rack-attack (~> 4.4.1)
@@ -1107,7 +1106,7 @@ DEPENDENCIES
rainbow (~> 2.2)
raindrops (~> 0.18)
rblineprof (~> 0.3.6)
- rbnacl (~> 3.2)
+ rbnacl (~> 4.0)
rbnacl-libsodium
rdoc (~> 4.2)
re2 (~> 1.1.1)
@@ -1126,7 +1125,7 @@ DEPENDENCIES
rspec-set (~> 0.1.3)
rspec_profiling (~> 0.0.5)
rubocop (~> 0.49.1)
- rubocop-gitlab-security (~> 0.0.6)
+ rubocop-gitlab-security (~> 0.1.0)
rubocop-rspec (~> 1.15.1)
ruby-fogbugz (~> 0.2.1)
ruby-prof (~> 0.16.2)
@@ -1163,7 +1162,6 @@ DEPENDENCIES
truncato (~> 0.7.8)
u2f (~> 0.2.1)
uglifier (~> 2.7.2)
- underscore-rails (~> 1.8.0)
unf (~> 0.1.4)
unicorn (~> 5.1.0)
unicorn-worker-killer (~> 0.4.4)
@@ -1176,4 +1174,4 @@ DEPENDENCIES
wikicloth (= 0.8.1)
BUNDLED WITH
- 1.15.3
+ 1.15.4
diff --git a/VERSION b/VERSION
index 027fe8dd2cf..ddadd9f9c5a 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-9.5.0-pre
+9.6.0-pre
diff --git a/app/assets/javascripts/api.js b/app/assets/javascripts/api.js
index 56f91e95bb9..78cb3def879 100644
--- a/app/assets/javascripts/api.js
+++ b/app/assets/javascripts/api.js
@@ -55,13 +55,18 @@ const Api = {
// Return projects list. Filtered by query
projects(query, options, callback) {
const url = Api.buildUrl(Api.projectsPath);
+ const defaults = {
+ search: query,
+ per_page: 20,
+ };
+
+ if (gon.current_user_id) {
+ defaults.membership = true;
+ }
+
return $.ajax({
url,
- data: Object.assign({
- search: query,
- per_page: 20,
- membership: true,
- }, options),
+ data: Object.assign(defaults, options),
dataType: 'json',
})
.done(projects => callback(projects));
@@ -96,18 +101,17 @@ const Api = {
.done(projects => callback(projects));
},
- commitMultiple(id, data, callback) {
+ commitMultiple(id, data) {
+ // see https://docs.gitlab.com/ce/api/commits.html#create-a-commit-with-multiple-files-and-actions
const url = Api.buildUrl(Api.commitPath)
.replace(':id', id);
- return $.ajax({
+ return this.wrapAjaxCall({
url,
type: 'POST',
contentType: 'application/json; charset=utf-8',
data: JSON.stringify(data),
dataType: 'json',
- })
- .done(commitData => callback(commitData))
- .fail(message => callback(message.responseJSON));
+ });
},
// Return text for a specific license
diff --git a/app/assets/javascripts/boards/components/issue_card_inner.js b/app/assets/javascripts/boards/components/issue_card_inner.js
index d3de1830895..9a5d87ede7e 100644
--- a/app/assets/javascripts/boards/components/issue_card_inner.js
+++ b/app/assets/javascripts/boards/components/issue_card_inner.js
@@ -97,7 +97,7 @@ gl.issueBoards.IssueCardInner = Vue.extend({
return `Avatar for ${assignee.name}`;
},
showLabel(label) {
- if (!this.list || !label) return true;
+ if (!label.id) return false;
return true;
},
filterByLabel(label, e) {
diff --git a/app/assets/javascripts/copy_to_clipboard.js b/app/assets/javascripts/copy_to_clipboard.js
index ab9a8e43dd1..1f3c7e1772d 100644
--- a/app/assets/javascripts/copy_to_clipboard.js
+++ b/app/assets/javascripts/copy_to_clipboard.js
@@ -29,12 +29,14 @@ showTooltip = function(target, title) {
var $target = $(target);
var originalTitle = $target.data('original-title');
- $target
- .attr('title', 'Copied')
- .tooltip('fixTitle')
- .tooltip('show')
- .attr('title', originalTitle)
- .tooltip('fixTitle');
+ if (!$target.data('hideTooltip')) {
+ $target
+ .attr('title', 'Copied')
+ .tooltip('fixTitle')
+ .tooltip('show')
+ .attr('title', originalTitle)
+ .tooltip('fixTitle');
+ }
};
$(function() {
diff --git a/app/assets/javascripts/dispatcher.js b/app/assets/javascripts/dispatcher.js
index 2bba7f55de1..b71c449090e 100644
--- a/app/assets/javascripts/dispatcher.js
+++ b/app/assets/javascripts/dispatcher.js
@@ -184,13 +184,13 @@ import initChangesDropdown from './init_changes_dropdown';
break;
case 'dashboard:issues':
case 'dashboard:merge_requests':
- case 'groups:merge_requests':
new ProjectSelect();
initLegacyFilters();
break;
case 'groups:issues':
+ case 'groups:merge_requests':
if (filteredSearchEnabled) {
- const filteredSearchManager = new gl.FilteredSearchManager('issues');
+ const filteredSearchManager = new gl.FilteredSearchManager(page === 'groups:issues' ? 'issues' : 'merge_requests');
filteredSearchManager.setup();
}
new ProjectSelect();
diff --git a/app/assets/javascripts/droplab/drop_down.js b/app/assets/javascripts/droplab/drop_down.js
index 70cd337fb8a..3901bb177fe 100644
--- a/app/assets/javascripts/droplab/drop_down.js
+++ b/app/assets/javascripts/droplab/drop_down.js
@@ -85,6 +85,13 @@ class DropDown {
const renderableList = this.list.querySelector('ul[data-dynamic]') || this.list;
renderableList.innerHTML = children.join('');
+
+ const listEvent = new CustomEvent('render.dl', {
+ detail: {
+ list: this,
+ },
+ });
+ this.list.dispatchEvent(listEvent);
}
renderChildren(data) {
diff --git a/app/assets/javascripts/filtered_search/dropdown_emoji.js b/app/assets/javascripts/filtered_search/dropdown_emoji.js
new file mode 100644
index 00000000000..f9bbbf0cbc1
--- /dev/null
+++ b/app/assets/javascripts/filtered_search/dropdown_emoji.js
@@ -0,0 +1,82 @@
+/* global Flash */
+
+import Ajax from '~/droplab/plugins/ajax';
+import Filter from '~/droplab/plugins/filter';
+import './filtered_search_dropdown';
+
+class DropdownEmoji extends gl.FilteredSearchDropdown {
+ constructor(options = {}) {
+ super(options);
+ this.config = {
+ Ajax: {
+ endpoint: `${gon.relative_url_root || ''}/autocomplete/award_emojis`,
+ method: 'setData',
+ loadingTemplate: this.loadingTemplate,
+ onError() {
+ /* eslint-disable no-new */
+ new Flash('An error occured fetching the dropdown data.');
+ /* eslint-enable no-new */
+ },
+ },
+ Filter: {
+ template: 'name',
+ },
+ };
+
+ import(/* webpackChunkName: 'emoji' */ '~/emoji')
+ .then(({ glEmojiTag }) => { this.glEmojiTag = glEmojiTag; })
+ .catch(() => { /* ignore error and leave emoji name in the search bar */ });
+
+ this.unbindEvents();
+ this.bindEvents();
+ }
+
+ bindEvents() {
+ super.bindEvents();
+
+ this.listRenderedWrapper = this.listRendered.bind(this);
+ this.dropdown.addEventListener('render.dl', this.listRenderedWrapper);
+ }
+
+ unbindEvents() {
+ this.dropdown.removeEventListener('render.dl', this.listRenderedWrapper);
+ super.unbindEvents();
+ }
+
+ listRendered() {
+ this.replaceEmojiElement();
+ }
+
+ itemClicked(e) {
+ super.itemClicked(e, (selected) => {
+ const name = selected.querySelector('.js-data-value').innerText.trim();
+ return gl.DropdownUtils.getEscapedText(name);
+ });
+ }
+
+ renderContent(forceShowList = false) {
+ this.droplab.changeHookList(this.hookId, this.dropdown, [Ajax, Filter], this.config);
+ super.renderContent(forceShowList);
+ }
+
+ replaceEmojiElement() {
+ if (!this.glEmojiTag) return;
+
+ // Replace empty gl-emoji tag to real content
+ const dropdownItems = [...this.dropdown.querySelectorAll('.filter-dropdown-item')];
+ dropdownItems.forEach((dropdownItem) => {
+ const name = dropdownItem.querySelector('.js-data-value').innerText;
+ const emojiTag = this.glEmojiTag(name);
+ const emojiElement = dropdownItem.querySelector('gl-emoji');
+ emojiElement.outerHTML = emojiTag;
+ });
+ }
+
+ init() {
+ this.droplab
+ .addHook(this.input, this.dropdown, [Ajax, Filter], this.config).init();
+ }
+}
+
+window.gl = window.gl || {};
+gl.DropdownEmoji = DropdownEmoji;
diff --git a/app/assets/javascripts/filtered_search/dropdown_hint.js b/app/assets/javascripts/filtered_search/dropdown_hint.js
index a81389ab088..1c5ca1d3cf9 100644
--- a/app/assets/javascripts/filtered_search/dropdown_hint.js
+++ b/app/assets/javascripts/filtered_search/dropdown_hint.js
@@ -61,7 +61,7 @@ class DropdownHint extends gl.FilteredSearchDropdown {
.map(tokenKey => ({
icon: `fa-${tokenKey.icon}`,
hint: tokenKey.key,
- tag: `<${tokenKey.symbol}${tokenKey.key}>`,
+ tag: `<${tokenKey.tag}>`,
type: tokenKey.type,
}));
diff --git a/app/assets/javascripts/filtered_search/filtered_search_bundle.js b/app/assets/javascripts/filtered_search/filtered_search_bundle.js
index 132b6fe698a..6d5dd747224 100644
--- a/app/assets/javascripts/filtered_search/filtered_search_bundle.js
+++ b/app/assets/javascripts/filtered_search/filtered_search_bundle.js
@@ -1,3 +1,4 @@
+import './dropdown_emoji';
import './dropdown_hint';
import './dropdown_non_user';
import './dropdown_user';
diff --git a/app/assets/javascripts/filtered_search/filtered_search_dropdown_manager.js b/app/assets/javascripts/filtered_search/filtered_search_dropdown_manager.js
index dd1c067df87..46c80dfd45e 100644
--- a/app/assets/javascripts/filtered_search/filtered_search_dropdown_manager.js
+++ b/app/assets/javascripts/filtered_search/filtered_search_dropdown_manager.js
@@ -58,6 +58,11 @@ class FilteredSearchDropdownManager {
},
element: this.container.querySelector('#js-dropdown-label'),
},
+ 'my-reaction': {
+ reference: null,
+ gl: 'DropdownEmoji',
+ element: this.container.querySelector('#js-dropdown-my-reaction'),
+ },
hint: {
reference: null,
gl: 'DropdownHint',
diff --git a/app/assets/javascripts/filtered_search/filtered_search_manager.js b/app/assets/javascripts/filtered_search/filtered_search_manager.js
index a31be2b0bc7..038239bf466 100644
--- a/app/assets/javascripts/filtered_search/filtered_search_manager.js
+++ b/app/assets/javascripts/filtered_search/filtered_search_manager.js
@@ -439,8 +439,13 @@ class FilteredSearchManager {
const match = this.filteredSearchTokenKeys.searchByKeyParam(keyParam);
if (match) {
- const indexOf = keyParam.indexOf('_');
- const sanitizedKey = indexOf !== -1 ? keyParam.slice(0, keyParam.indexOf('_')) : keyParam;
+ // Use lastIndexOf because the token key is allowed to contain underscore
+ // e.g. 'my_reaction' is the token key of 'my_reaction_emoji'
+ const lastIndexOf = keyParam.lastIndexOf('_');
+ let sanitizedKey = lastIndexOf !== -1 ? keyParam.slice(0, lastIndexOf) : keyParam;
+ // Replace underscore with hyphen in the sanitizedkey.
+ // e.g. 'my_reaction' => 'my-reaction'
+ sanitizedKey = sanitizedKey.replace('_', '-');
const symbol = match.symbol;
let quotationsToUse = '';
@@ -515,7 +520,10 @@ class FilteredSearchManager {
const condition = this.filteredSearchTokenKeys
.searchByConditionKeyValue(token.key, token.value.toLowerCase());
const { param } = this.filteredSearchTokenKeys.searchByKey(token.key) || {};
- const keyParam = param ? `${token.key}_${param}` : token.key;
+ // Replace hyphen with underscore to use as request parameter
+ // e.g. 'my-reaction' => 'my_reaction'
+ const underscoredKey = token.key.replace('-', '_');
+ const keyParam = param ? `${underscoredKey}_${param}` : underscoredKey;
let tokenPath = '';
if (condition) {
diff --git a/app/assets/javascripts/filtered_search/filtered_search_token_keys.js b/app/assets/javascripts/filtered_search/filtered_search_token_keys.js
index 025d4d8795b..be595d7df1a 100644
--- a/app/assets/javascripts/filtered_search/filtered_search_token_keys.js
+++ b/app/assets/javascripts/filtered_search/filtered_search_token_keys.js
@@ -4,26 +4,42 @@ const tokenKeys = [{
param: 'username',
symbol: '@',
icon: 'pencil',
+ tag: '@author',
}, {
key: 'assignee',
type: 'string',
param: 'username',
symbol: '@',
icon: 'user',
+ tag: '@assignee',
}, {
key: 'milestone',
type: 'string',
param: 'title',
symbol: '%',
icon: 'clock-o',
+ tag: '%milestone',
}, {
key: 'label',
type: 'array',
param: 'name[]',
symbol: '~',
icon: 'tag',
+ tag: '~label',
}];
+if (gon.current_user_id) {
+ // Appending tokenkeys only logged-in
+ tokenKeys.push({
+ key: 'my-reaction',
+ type: 'string',
+ param: 'emoji',
+ symbol: '',
+ icon: 'thumbs-up',
+ tag: 'emoji',
+ });
+}
+
const alternativeTokenKeys = [{
key: 'label',
type: 'string',
@@ -84,6 +100,10 @@ class FilteredSearchTokenKeys {
return tokenKeysWithAlternative.find((tokenKey) => {
let tokenKeyParam = tokenKey.key;
+ // Replace hyphen with underscore to compare keyParam with tokenKeyParam
+ // e.g. 'my-reaction' => 'my_reaction'
+ tokenKeyParam = tokenKeyParam.replace('-', '_');
+
if (tokenKey.param) {
tokenKeyParam += `_${tokenKey.param}`;
}
diff --git a/app/assets/javascripts/filtered_search/filtered_search_visual_tokens.js b/app/assets/javascripts/filtered_search/filtered_search_visual_tokens.js
index 243ee4d723a..28e8240169d 100644
--- a/app/assets/javascripts/filtered_search/filtered_search_visual_tokens.js
+++ b/app/assets/javascripts/filtered_search/filtered_search_visual_tokens.js
@@ -132,6 +132,23 @@ class FilteredSearchVisualTokens {
.catch(() => { });
}
+ static updateEmojiTokenAppearance(tokenValueContainer, tokenValueElement, tokenValue) {
+ const container = tokenValueContainer;
+ const element = tokenValueElement;
+
+ return import(/* webpackChunkName: 'emoji' */ '../emoji')
+ .then((Emoji) => {
+ if (!Emoji.isEmojiNameValid(tokenValue)) {
+ return;
+ }
+
+ container.dataset.originalValue = tokenValue;
+ element.innerHTML = Emoji.glEmojiTag(tokenValue);
+ })
+ // ignore error and leave emoji name in the search bar
+ .catch(() => { });
+ }
+
static renderVisualTokenValue(parentElement, tokenName, tokenValue) {
const tokenValueContainer = parentElement.querySelector('.value-container');
const tokenValueElement = tokenValueContainer.querySelector('.value');
@@ -144,6 +161,10 @@ class FilteredSearchVisualTokens {
FilteredSearchVisualTokens.updateUserTokenAppearance(
tokenValueContainer, tokenValueElement, tokenValue,
);
+ } else if (tokenType === 'my-reaction') {
+ FilteredSearchVisualTokens.updateEmojiTokenAppearance(
+ tokenValueContainer, tokenValueElement, tokenValue,
+ );
}
}
diff --git a/app/assets/javascripts/groups/components/group_item.vue b/app/assets/javascripts/groups/components/group_item.vue
index cb133cf7535..2060410e991 100644
--- a/app/assets/javascripts/groups/components/group_item.vue
+++ b/app/assets/javascripts/groups/components/group_item.vue
@@ -1,10 +1,10 @@
<script>
+import identicon from '../../vue_shared/components/identicon.vue';
import eventHub from '../event_hub';
-import groupIdenticon from './group_identicon.vue';
export default {
components: {
- groupIdenticon,
+ identicon,
},
props: {
group: {
@@ -205,7 +205,7 @@ export default {
class="avatar s40"
:src="group.avatarUrl"
/>
- <group-identicon
+ <identicon
v-else
:entity-id=group.id
:entity-name="group.name"
diff --git a/app/assets/javascripts/lib/utils/sticky.js b/app/assets/javascripts/lib/utils/sticky.js
index ff2b66046b4..283c0ec0410 100644
--- a/app/assets/javascripts/lib/utils/sticky.js
+++ b/app/assets/javascripts/lib/utils/sticky.js
@@ -1,5 +1,5 @@
export const isSticky = (el, scrollY, stickyTop) => {
- const top = el.offsetTop - scrollY;
+ const top = Math.floor(el.offsetTop - scrollY);
if (top <= stickyTop) {
el.classList.add('is-stuck');
diff --git a/app/assets/javascripts/merge_request_tabs.js b/app/assets/javascripts/merge_request_tabs.js
index 5a9b3d19f84..3b3620fe61b 100644
--- a/app/assets/javascripts/merge_request_tabs.js
+++ b/app/assets/javascripts/merge_request_tabs.js
@@ -253,6 +253,7 @@ import bp from './breakpoints';
loadDiff(source) {
if (this.diffsLoaded) {
+ document.dispatchEvent(new CustomEvent('scroll'));
return;
}
diff --git a/app/assets/javascripts/monitoring/components/monitoring_column.vue b/app/assets/javascripts/monitoring/components/monitoring_column.vue
index 407af51cb7a..a31c26fb4fc 100644
--- a/app/assets/javascripts/monitoring/components/monitoring_column.vue
+++ b/app/assets/javascripts/monitoring/components/monitoring_column.vue
@@ -7,6 +7,7 @@
import eventHub from '../event_hub';
import measurements from '../utils/measurements';
import { formatRelevantDigits } from '../../lib/utils/number_utils';
+ import { timeScaleFormat } from '../utils/date_time_formatters';
import bp from '../../breakpoints';
const bisectDate = d3.bisector(d => d.time).left;
@@ -159,6 +160,7 @@
const xAxis = d3.svg.axis()
.scale(axisXScale)
.ticks(measurements.xTicks)
+ .tickFormat(timeScaleFormat)
.orient('bottom');
const yAxis = d3.svg.axis()
@@ -266,14 +268,6 @@
stroke-width="2"
transform="translate(-5, 20)">
</path>
- <rect
- class="prometheus-graph-overlay"
- :width="(graphWidth - 70)"
- :height="(graphHeight - 100)"
- transform="translate(-5, 20)"
- ref="graphOverlay"
- @mousemove="handleMouseOverGraph($event)">
- </rect>
<monitoring-deployment
:show-deploy-info="showDeployInfo"
:deployment-data="reducedDeploymentData"
@@ -289,6 +283,14 @@
:graph-height="graphHeight"
:graph-height-offset="graphHeightOffset"
/>
+ <rect
+ class="prometheus-graph-overlay"
+ :width="(graphWidth - 70)"
+ :height="(graphHeight - 100)"
+ transform="translate(-5, 20)"
+ ref="graphOverlay"
+ @mousemove="handleMouseOverGraph($event)">
+ </rect>
</svg>
</svg>
</div>
diff --git a/app/assets/javascripts/monitoring/components/monitoring_deployment.vue b/app/assets/javascripts/monitoring/components/monitoring_deployment.vue
index e6432ba3191..dadbcd1aaa6 100644
--- a/app/assets/javascripts/monitoring/components/monitoring_deployment.vue
+++ b/app/assets/javascripts/monitoring/components/monitoring_deployment.vue
@@ -1,8 +1,5 @@
<script>
- import {
- dateFormat,
- timeFormat,
- } from '../constants';
+ import { dateFormat, timeFormat } from '../utils/date_time_formatters';
export default {
props: {
@@ -58,7 +55,7 @@
class="deploy-info"
v-if="showDeployInfo">
<g
- v-for="(deployment, index) in deploymentData"
+ v-for="(deployment, index) in deploymentData"
:key="index"
:class="nameDeploymentClass(deployment)"
:transform="transformDeploymentGroup(deployment)">
@@ -92,7 +89,7 @@
width="90"
height="58">
</rect>
- <g
+ <g
transform="translate(5, 2)">
<text
class="deploy-info-text text-metric-bold">
diff --git a/app/assets/javascripts/monitoring/components/monitoring_flag.vue b/app/assets/javascripts/monitoring/components/monitoring_flag.vue
index 5a0e50fcab3..61cbeeebb17 100644
--- a/app/assets/javascripts/monitoring/components/monitoring_flag.vue
+++ b/app/assets/javascripts/monitoring/components/monitoring_flag.vue
@@ -1,8 +1,5 @@
<script>
- import {
- dateFormat,
- timeFormat,
- } from '../constants';
+ import { dateFormat, timeFormat } from '../utils/date_time_formatters';
export default {
props: {
@@ -72,7 +69,7 @@
r="5"
transform="translate(-5, 20)">
</circle>
- <svg
+ <svg
class="rect-text-metric"
:x="currentFlagPosition"
y="0">
diff --git a/app/assets/javascripts/monitoring/constants.js b/app/assets/javascripts/monitoring/constants.js
deleted file mode 100644
index c3a8da52404..00000000000
--- a/app/assets/javascripts/monitoring/constants.js
+++ /dev/null
@@ -1,4 +0,0 @@
-import d3 from 'd3';
-
-export const dateFormat = d3.time.format('%b %d, %Y');
-export const timeFormat = d3.time.format('%H:%M%p');
diff --git a/app/assets/javascripts/monitoring/utils/date_time_formatters.js b/app/assets/javascripts/monitoring/utils/date_time_formatters.js
new file mode 100644
index 00000000000..26bcaa02511
--- /dev/null
+++ b/app/assets/javascripts/monitoring/utils/date_time_formatters.js
@@ -0,0 +1,15 @@
+import d3 from 'd3';
+
+export const dateFormat = d3.time.format('%b %-d, %Y');
+export const timeFormat = d3.time.format('%-I:%M%p');
+
+export const timeScaleFormat = d3.time.format.multi([
+ ['.%L', d => d.getMilliseconds()],
+ [':%S', d => d.getSeconds()],
+ ['%-I:%M', d => d.getMinutes()],
+ ['%-I %p', d => d.getHours()],
+ ['%a %-d', d => d.getDay() && d.getDate() !== 1],
+ ['%b %-d', d => d.getDate() !== 1],
+ ['%B', d => d.getMonth()],
+ ['%Y', () => true],
+]);
diff --git a/app/assets/javascripts/new_sidebar.js b/app/assets/javascripts/new_sidebar.js
index 2d1ed9e4076..b18d12b48b5 100644
--- a/app/assets/javascripts/new_sidebar.js
+++ b/app/assets/javascripts/new_sidebar.js
@@ -47,7 +47,6 @@ export default class NewNavSidebar {
if (this.$sidebar.length) {
this.$sidebar.toggleClass('sidebar-icons-only', collapsed);
- this.$page.toggleClass('page-with-new-sidebar', !collapsed);
this.$page.toggleClass('page-with-icon-sidebar', breakpoint === 'sm' ? true : collapsed);
}
NewNavSidebar.setCollapsedCookie(collapsed);
diff --git a/app/assets/javascripts/pipelines/components/navigation_tabs.vue b/app/assets/javascripts/pipelines/components/navigation_tabs.vue
index d2f6d47f043..73f7e3a0cad 100644
--- a/app/assets/javascripts/pipelines/components/navigation_tabs.vue
+++ b/app/assets/javascripts/pipelines/components/navigation_tabs.vue
@@ -1,23 +1,29 @@
<script>
-export default {
- name: 'PipelineNavigationTabs',
- props: {
- scope: {
- type: String,
- required: true,
+ export default {
+ name: 'PipelineNavigationTabs',
+ props: {
+ scope: {
+ type: String,
+ required: true,
+ },
+ count: {
+ type: Object,
+ required: true,
+ },
+ paths: {
+ type: Object,
+ required: true,
+ },
},
- count: {
- type: Object,
- required: true,
+ mounted() {
+ $(document).trigger('init.scrolling-tabs');
},
- paths: {
- type: Object,
- required: true,
+ methods: {
+ shouldRenderBadge(count) {
+ // 0 is valid in a badge, but evaluates to false, we need to check for undefined
+ return count !== undefined;
+ },
},
- },
- mounted() {
- $(document).trigger('init.scrolling-tabs');
- },
};
</script>
<template>
@@ -27,7 +33,9 @@ export default {
:class="{ active: scope === 'all'}">
<a :href="paths.allPath">
All
- <span class="badge js-totalbuilds-count">
+ <span
+ v-if="shouldRenderBadge(count.all)"
+ class="badge js-totalbuilds-count">
{{count.all}}
</span>
</a>
@@ -37,7 +45,9 @@ export default {
:class="{ active: scope === 'pending'}">
<a :href="paths.pendingPath">
Pending
- <span class="badge">
+ <span
+ v-if="shouldRenderBadge(count.pending)"
+ class="badge">
{{count.pending}}
</span>
</a>
@@ -47,7 +57,9 @@ export default {
:class="{ active: scope === 'running'}">
<a :href="paths.runningPath">
Running
- <span class="badge">
+ <span
+ v-if="shouldRenderBadge(count.running)"
+ class="badge">
{{count.running}}
</span>
</a>
@@ -57,7 +69,9 @@ export default {
:class="{ active: scope === 'finished'}">
<a :href="paths.finishedPath">
Finished
- <span class="badge">
+ <span
+ v-if="shouldRenderBadge(count.finished)"
+ class="badge">
{{count.finished}}
</span>
</a>
diff --git a/app/assets/javascripts/pipelines/components/pipelines.vue b/app/assets/javascripts/pipelines/components/pipelines.vue
index 5df317a76bf..010063a0240 100644
--- a/app/assets/javascripts/pipelines/components/pipelines.vue
+++ b/app/assets/javascripts/pipelines/components/pipelines.vue
@@ -139,7 +139,9 @@
};
</script>
<template>
- <div :class="cssClass">
+ <div
+ class="pipelines-container"
+ :class="cssClass">
<div
class="top-area scrolling-tabs-container inner-page-scroll-tabs"
v-if="!isLoading && !shouldRenderEmptyState">
diff --git a/app/assets/javascripts/project_select_combo_button.js b/app/assets/javascripts/project_select_combo_button.js
index f799d9d619a..46a26fb91f4 100644
--- a/app/assets/javascripts/project_select_combo_button.js
+++ b/app/assets/javascripts/project_select_combo_button.js
@@ -4,10 +4,10 @@ export default class ProjectSelectComboButton {
constructor(select) {
this.projectSelectInput = $(select);
this.newItemBtn = $('.new-project-item-link');
- this.newItemBtnBaseText = this.newItemBtn.data('label');
- this.itemType = this.deriveItemTypeFromLabel();
+ this.resourceType = this.newItemBtn.data('type');
+ this.resourceLabel = this.newItemBtn.data('label');
+ this.formattedText = this.deriveTextVariants();
this.groupId = this.projectSelectInput.data('groupId');
-
this.bindEvents();
this.initLocalStorage();
}
@@ -23,9 +23,7 @@ export default class ProjectSelectComboButton {
const localStorageIsSafe = AccessorUtilities.isLocalStorageAccessSafe();
if (localStorageIsSafe) {
- const itemTypeKebabed = this.newItemBtnBaseText.toLowerCase().split(' ').join('-');
-
- this.localStorageKey = ['group', this.groupId, itemTypeKebabed, 'recent-project'].join('-');
+ this.localStorageKey = ['group', this.groupId, this.formattedText.localStorageItemType, 'recent-project'].join('-');
this.setBtnTextFromLocalStorage();
}
}
@@ -57,19 +55,14 @@ export default class ProjectSelectComboButton {
setNewItemBtnAttributes(project) {
if (project) {
this.newItemBtn.attr('href', project.url);
- this.newItemBtn.text(`${this.newItemBtnBaseText} in ${project.name}`);
+ this.newItemBtn.text(`${this.formattedText.defaultTextPrefix} in ${project.name}`);
this.newItemBtn.enable();
} else {
- this.newItemBtn.text(`Select project to create ${this.itemType}`);
+ this.newItemBtn.text(`Select project to create ${this.formattedText.presetTextSuffix}`);
this.newItemBtn.disable();
}
}
- deriveItemTypeFromLabel() {
- // label is either 'New issue' or 'New merge request'
- return this.newItemBtnBaseText.split(' ').slice(1).join(' ');
- }
-
getProjectFromLocalStorage() {
const projectString = localStorage.getItem(this.localStorageKey);
@@ -81,5 +74,19 @@ export default class ProjectSelectComboButton {
localStorage.setItem(this.localStorageKey, projectString);
}
+
+ deriveTextVariants() {
+ const defaultTextPrefix = this.resourceLabel;
+
+ // the trailing slice call depluralizes each of these strings (e.g. new-issues -> new-issue)
+ const localStorageItemType = `new-${this.resourceType.split('_').join('-').slice(0, -1)}`;
+ const presetTextSuffix = this.resourceType.split('_').join(' ').slice(0, -1);
+
+ return {
+ localStorageItemType, // new-issue / new-merge-request
+ defaultTextPrefix, // New issue / New merge request
+ presetTextSuffix, // issue / merge request
+ };
+ }
}
diff --git a/app/assets/javascripts/repo/components/repo_commit_section.vue b/app/assets/javascripts/repo/components/repo_commit_section.vue
index 5ec4a9b6593..1282828b504 100644
--- a/app/assets/javascripts/repo/components/repo_commit_section.vue
+++ b/app/assets/javascripts/repo/components/repo_commit_section.vue
@@ -42,7 +42,9 @@ export default {
actions,
};
Store.submitCommitsLoading = true;
- Service.commitFiles(payload, this.resetCommitState);
+ Service.commitFiles(payload)
+ .then(this.resetCommitState)
+ .catch(() => Flash('An error occured while committing your changes'));
},
resetCommitState() {
diff --git a/app/assets/javascripts/repo/components/repo_sidebar.vue b/app/assets/javascripts/repo/components/repo_sidebar.vue
index 72b40288566..3414128526d 100644
--- a/app/assets/javascripts/repo/components/repo_sidebar.vue
+++ b/app/assets/javascripts/repo/components/repo_sidebar.vue
@@ -74,7 +74,8 @@ export default {
<tbody>
<repo-file-options
:is-mini="isMini"
- :project-name="projectName"/>
+ :project-name="projectName"
+ />
<repo-previous-directory
v-if="isRoot"
:prev-url="prevURL"
@@ -84,7 +85,8 @@ export default {
:key="n"
:loading="loading"
:has-files="!!files.length"
- :is-mini="isMini"/>
+ :is-mini="isMini"
+ />
<repo-file
v-for="file in files"
:key="file.id"
@@ -93,7 +95,8 @@ export default {
@linkclicked="fileClicked(file)"
:is-tree="isTree"
:has-files="!!files.length"
- :active-file="activeFile"/>
+ :active-file="activeFile"
+ />
</tbody>
</table>
</div>
diff --git a/app/assets/javascripts/repo/monaco_loader.js b/app/assets/javascripts/repo/monaco_loader.js
index ad1370a7730..af83a1ec0b4 100644
--- a/app/assets/javascripts/repo/monaco_loader.js
+++ b/app/assets/javascripts/repo/monaco_loader.js
@@ -1,13 +1,11 @@
-/* eslint-disable no-underscore-dangle, camelcase */
-/* global __webpack_public_path__ */
-
import monacoContext from 'monaco-editor/dev/vs/loader';
monacoContext.require.config({
paths: {
- vs: `${__webpack_public_path__}monaco-editor/vs`,
+ vs: `${__webpack_public_path__}monaco-editor/vs`, // eslint-disable-line camelcase
},
});
+// eslint-disable-next-line no-underscore-dangle
window.__monaco_context__ = monacoContext;
export default monacoContext.require;
diff --git a/app/assets/javascripts/repo/services/repo_service.js b/app/assets/javascripts/repo/services/repo_service.js
index 3cf204e6ec8..af83497fa39 100644
--- a/app/assets/javascripts/repo/services/repo_service.js
+++ b/app/assets/javascripts/repo/services/repo_service.js
@@ -65,15 +65,17 @@ const RepoService = {
return urlArray.join('/');
},
- commitFiles(payload, cb) {
- Api.commitMultiple(Store.projectId, payload, (data) => {
- if (data.short_id && data.stats) {
- Flash(`Your changes have been committed. Commit ${data.short_id} with ${data.stats.additions} additions, ${data.stats.deletions} deletions.`, 'notice');
- } else {
- Flash(data.message);
- }
- cb();
- });
+ commitFiles(payload) {
+ return Api.commitMultiple(Store.projectId, payload)
+ .then(this.commitFlash);
+ },
+
+ commitFlash(data) {
+ if (data.short_id && data.stats) {
+ window.Flash(`Your changes have been committed. Commit ${data.short_id} with ${data.stats.additions} additions, ${data.stats.deletions} deletions.`, 'notice');
+ } else {
+ window.Flash(data.message);
+ }
},
};
diff --git a/app/assets/javascripts/users_select.js b/app/assets/javascripts/users_select.js
index 16ebf5916dc..a31fedee021 100644
--- a/app/assets/javascripts/users_select.js
+++ b/app/assets/javascripts/users_select.js
@@ -588,9 +588,10 @@ function UsersSelect(currentUser, els) {
if (showEmailUser && data.results.length === 0 && query.term.match(/^[^@]+@[^@]+$/)) {
var trimmed = query.term.trim();
emailUser = {
- name: "Invite \"" + query.term + "\"",
+ name: "Invite \"" + query.term + "\" by email",
username: trimmed,
- id: trimmed
+ id: trimmed,
+ invite: true
};
data.results.unshift(emailUser);
}
@@ -642,7 +643,7 @@ UsersSelect.prototype.formatResult = function(user) {
} else {
avatar = gon.default_avatar_url;
}
- return "<div class='user-result " + (!user.username ? 'no-username' : void 0) + "'> <div class='user-image'><img class='avatar avatar-inline s32' src='" + avatar + "'></div> <div class='user-name dropdown-menu-user-full-name'>" + user.name + "</div> <div class='user-username dropdown-menu-user-username'>" + ("@" + user.username || "") + "</div> </div>";
+ return "<div class='user-result " + (!user.username ? 'no-username' : void 0) + "'> <div class='user-image'><img class='avatar avatar-inline s32' src='" + avatar + "'></div> <div class='user-name dropdown-menu-user-full-name'>" + user.name + "</div> <div class='user-username dropdown-menu-user-username'>" + (!user.invite ? "@" + _.escape(user.username) : "") + "</div> </div>";
};
UsersSelect.prototype.formatSelection = function(user) {
diff --git a/app/assets/javascripts/groups/components/group_identicon.vue b/app/assets/javascripts/vue_shared/components/identicon.vue
index 0edd820743f..0edd820743f 100644
--- a/app/assets/javascripts/groups/components/group_identicon.vue
+++ b/app/assets/javascripts/vue_shared/components/identicon.vue
diff --git a/app/assets/javascripts/webpack.js b/app/assets/javascripts/webpack.js
index 9a9cf395fb8..ced847294ae 100644
--- a/app/assets/javascripts/webpack.js
+++ b/app/assets/javascripts/webpack.js
@@ -5,5 +5,5 @@
*/
if (gon && gon.webpack_public_path) {
- __webpack_public_path__ = gon.webpack_public_path; // eslint-disable-line
+ __webpack_public_path__ = gon.webpack_public_path; // eslint-disable-line camelcase
}
diff --git a/app/assets/stylesheets/framework/avatar.scss b/app/assets/stylesheets/framework/avatar.scss
index 486d88efbc5..bdcbd4021b3 100644
--- a/app/assets/stylesheets/framework/avatar.scss
+++ b/app/assets/stylesheets/framework/avatar.scss
@@ -78,7 +78,7 @@
&.s60 { font-size: 32px; line-height: 58px; }
&.s70 { font-size: 34px; line-height: 70px; }
&.s90 { font-size: 36px; line-height: 88px; }
- &.s110 { font-size: 40px; line-height: 108px; font-weight: 300; }
+ &.s110 { font-size: 40px; line-height: 108px; font-weight: $gl-font-weight-normal; }
&.s140 { font-size: 72px; line-height: 138px; }
&.s160 { font-size: 96px; line-height: 158px; }
}
diff --git a/app/assets/stylesheets/framework/badges.scss b/app/assets/stylesheets/framework/badges.scss
index 47a8f44c709..6bbe32df772 100644
--- a/app/assets/stylesheets/framework/badges.scss
+++ b/app/assets/stylesheets/framework/badges.scss
@@ -1,5 +1,5 @@
.badge {
- font-weight: normal;
+ font-weight: $gl-font-weight-normal;
background-color: $badge-bg;
color: $badge-color;
vertical-align: baseline;
diff --git a/app/assets/stylesheets/framework/blocks.scss b/app/assets/stylesheets/framework/blocks.scss
index 95a08c960ea..b575ec9de18 100644
--- a/app/assets/stylesheets/framework/blocks.scss
+++ b/app/assets/stylesheets/framework/blocks.scss
@@ -8,7 +8,7 @@
text-align: center;
padding: 20px;
color: $gl-text-color;
- font-weight: normal;
+ font-weight: $gl-font-weight-normal;
font-size: 14px;
line-height: 36px;
@@ -213,7 +213,7 @@
h1 {
display: inline;
- font-weight: normal;
+ font-weight: $gl-font-weight-normal;
font-size: 24px;
color: $gl-text-color;
}
diff --git a/app/assets/stylesheets/framework/buttons.scss b/app/assets/stylesheets/framework/buttons.scss
index 6eabdc63d9e..b4a6b214e98 100644
--- a/app/assets/stylesheets/framework/buttons.scss
+++ b/app/assets/stylesheets/framework/buttons.scss
@@ -1,7 +1,7 @@
@mixin btn-default {
border-radius: 3px;
font-size: $gl-font-size;
- font-weight: 400;
+ font-weight: $gl-font-weight-normal;
padding: $gl-vert-padding $gl-btn-padding;
&:focus,
diff --git a/app/assets/stylesheets/framework/calendar.scss b/app/assets/stylesheets/framework/calendar.scss
index 0ded4a3b423..4ce767e4cc4 100644
--- a/app/assets/stylesheets/framework/calendar.scss
+++ b/app/assets/stylesheets/framework/calendar.scss
@@ -52,13 +52,13 @@
.pika-label {
color: $gl-text-color-secondary;
font-size: 14px;
- font-weight: normal;
+ font-weight: $gl-font-weight-normal;
}
th {
padding: 2px 0;
color: $note-disabled-comment-color;
- font-weight: normal;
+ font-weight: $gl-font-weight-normal;
text-transform: lowercase;
border-top: 1px solid $calendar-border-color;
}
@@ -88,7 +88,7 @@
.is-today {
.pika-day {
color: inherit;
- font-weight: normal;
+ font-weight: $gl-font-weight-normal;
}
}
diff --git a/app/assets/stylesheets/framework/common.scss b/app/assets/stylesheets/framework/common.scss
index 293aa194528..e16fbbf43b5 100644
--- a/app/assets/stylesheets/framework/common.scss
+++ b/app/assets/stylesheets/framework/common.scss
@@ -36,12 +36,12 @@
color: $common-gray;
font-size: 14px;
margin-bottom: 12px;
- font-weight: normal;
+ font-weight: $gl-font-weight-normal;
line-height: 24px;
}
.bold {
- font-weight: 600;
+ font-weight: $gl-font-weight-bold;
}
.tab-content {
@@ -89,7 +89,7 @@ hr {
}
}
-.item-title { font-weight: 600; }
+.item-title { font-weight: $gl-font-weight-bold; }
/** FLASH message **/
.author_link,
@@ -118,18 +118,18 @@ table a code {
span.update-author {
display: block;
color: $update-author-color;
- font-weight: normal;
+ font-weight: $gl-font-weight-normal;
font-style: italic;
strong {
- font-weight: bold;
+ font-weight: $gl-font-weight-bold;
font-style: normal;
}
}
.user-mention {
color: $user-mention-color;
- font-weight: bold;
+ font-weight: $gl-font-weight-bold;
}
.field_with_errors {
@@ -222,7 +222,7 @@ li.note {
text-align: center;
background: $error-bg;
color: $white-light;
- font-weight: bold;
+ font-weight: $gl-font-weight-bold;
a {
color: $white-light;
@@ -339,7 +339,7 @@ table {
.header-with-avatar {
h3 {
margin: 0;
- font-weight: bold;
+ font-weight: $gl-font-weight-bold;
}
.username {
diff --git a/app/assets/stylesheets/framework/dropdowns.scss b/app/assets/stylesheets/framework/dropdowns.scss
index b60f69a5d37..df8d7c431d3 100644
--- a/app/assets/stylesheets/framework/dropdowns.scss
+++ b/app/assets/stylesheets/framework/dropdowns.scss
@@ -195,7 +195,7 @@
margin-top: 2px;
margin-bottom: 0;
font-size: 14px;
- font-weight: normal;
+ font-weight: $gl-font-weight-normal;
padding: 8px 0;
background-color: $white-light;
border: 1px solid $dropdown-border-color;
@@ -268,7 +268,7 @@
}
.dropdown-bold-header {
- font-weight: 600;
+ font-weight: $gl-font-weight-bold;
line-height: 22px;
padding: 0 16px;
}
@@ -432,7 +432,7 @@
.dropdown-menu-user-full-name {
display: block;
- font-weight: 500;
+ font-weight: $gl-font-weight-normal;
line-height: 16px;
text-overflow: ellipsis;
overflow: hidden;
@@ -468,7 +468,7 @@
&.is-indeterminate,
&.is-active {
- font-weight: 600;
+ font-weight: $gl-font-weight-bold;
color: $gl-text-color;
&::before {
@@ -502,7 +502,7 @@
position: relative;
padding: 2px 25px 10px;
margin: 0 10px 10px;
- font-weight: 600;
+ font-weight: $gl-font-weight-bold;
line-height: 1;
text-align: center;
text-overflow: ellipsis;
@@ -685,7 +685,7 @@
.dropdown-menu-inner-title {
display: block;
color: $gl-text-color;
- font-weight: 600;
+ font-weight: $gl-font-weight-bold;
}
.dropdown-menu-inner-content {
@@ -728,18 +728,27 @@
@mixin new-style-dropdown($selector: '') {
#{$selector}.dropdown-menu,
#{$selector}.dropdown-menu-nav {
- .divider {
- margin: 6px 0;
- }
-
li {
padding: 0 1px;
+ &:hover {
+ background-color: transparent;
+ }
+
+ &.divider {
+ margin: 6px 0;
+
+ &:hover {
+ background-color: $dropdown-divider-color;
+ }
+ }
+
&.dropdown-header {
padding: 8px 16px;
}
- a {
+ a,
+ button {
border-radius: 0;
padding: 8px 16px;
@@ -752,7 +761,8 @@
&:hover,
&:active,
&:focus {
- background-color: $gray-darker;
+ background-color: $dropdown-item-hover-bg;
+ color: $gl-text-color;
}
&.is-active {
@@ -761,6 +771,11 @@
&::before {
top: 16px;
}
+
+ &.dropdown-menu-user-link::before {
+ top: 50%;
+ transform: translateY(-50%);
+ }
}
}
}
diff --git a/app/assets/stylesheets/framework/filters.scss b/app/assets/stylesheets/framework/filters.scss
index ec13a86ccf7..b2847c348eb 100644
--- a/app/assets/stylesheets/framework/filters.scss
+++ b/app/assets/stylesheets/framework/filters.scss
@@ -50,6 +50,8 @@
}
.filtered-search-wrapper {
+ @include new-style-dropdown;
+
display: -webkit-flex;
display: flex;
@@ -223,6 +225,18 @@
color: $common-gray-dark;
}
+ gl-emoji {
+ display: inline-block;
+ font-family: inherit;
+ font-size: inherit;
+ vertical-align: inherit;
+
+ img {
+ height: 18px;
+ width: 18px;
+ }
+ }
+
.form-control {
position: relative;
min-width: 200px;
@@ -275,7 +289,7 @@
}
.filtered-search-input-dropdown-menu {
- max-height: 225px;
+ max-height: 260px;
max-width: 280px;
overflow: auto;
@@ -369,7 +383,7 @@
}
> .value {
- font-weight: 600;
+ font-weight: $gl-font-weight-bold;
}
}
@@ -411,8 +425,6 @@
}
%filter-dropdown-item-btn-hover {
- background-color: $dropdown-hover-color;
- color: $white-light;
text-decoration: none;
outline: 0;
@@ -422,8 +434,6 @@
}
.droplab-dropdown .dropdown-menu .filter-dropdown-item {
- padding: 0;
-
.btn {
border: none;
width: 100%;
@@ -454,7 +464,7 @@
.dropdown-light-content {
font-size: 14px;
- font-weight: 400;
+ font-weight: $gl-font-weight-normal;
}
.dropdown-user {
@@ -480,3 +490,7 @@
padding: 8px 16px;
text-align: center;
}
+
+.issues-details-filters {
+ @include new-style-dropdown;
+}
diff --git a/app/assets/stylesheets/framework/flash.scss b/app/assets/stylesheets/framework/flash.scss
index 38d884bc7eb..e1b086ebb2b 100644
--- a/app/assets/stylesheets/framework/flash.scss
+++ b/app/assets/stylesheets/framework/flash.scss
@@ -25,7 +25,7 @@
a.flash-action {
margin-left: 5px;
text-decoration: none;
- font-weight: normal;
+ font-weight: $gl-font-weight-normal;
border-bottom: 1px solid;
&:hover {
diff --git a/app/assets/stylesheets/framework/forms.scss b/app/assets/stylesheets/framework/forms.scss
index 61e3897f369..be96c8ee964 100644
--- a/app/assets/stylesheets/framework/forms.scss
+++ b/app/assets/stylesheets/framework/forms.scss
@@ -32,7 +32,7 @@ label {
}
&.label-light {
- font-weight: 600;
+ font-weight: $gl-font-weight-bold;
}
}
@@ -73,7 +73,7 @@ label {
margin-right: 0;
.control-label {
- font-weight: bold;
+ font-weight: $gl-font-weight-bold;
padding-top: 4px;
}
@@ -157,7 +157,7 @@ label {
.form-group .control-label,
.form-group .control-label-full-width {
- font-weight: normal;
+ font-weight: $gl-font-weight-normal;
}
.form-control::-webkit-input-placeholder {
diff --git a/app/assets/stylesheets/framework/header.scss b/app/assets/stylesheets/framework/header.scss
index b677882eba4..35bd97980e2 100644
--- a/app/assets/stylesheets/framework/header.scss
+++ b/app/assets/stylesheets/framework/header.scss
@@ -160,7 +160,7 @@ header {
li {
&.active a {
- font-weight: bold;
+ font-weight: $gl-font-weight-bold;
}
}
}
@@ -250,7 +250,7 @@ header {
font-size: 18px;
line-height: 22px;
display: inline-block;
- font-weight: normal;
+ font-weight: $gl-font-weight-normal;
color: $gl-text-color;
vertical-align: top;
white-space: nowrap;
@@ -326,7 +326,7 @@ header {
.badge {
position: inherit;
top: -8px;
- font-weight: normal;
+ font-weight: $gl-font-weight-normal;
margin-left: -11px;
font-size: 11px;
color: $white-light;
diff --git a/app/assets/stylesheets/framework/lists.scss b/app/assets/stylesheets/framework/lists.scss
index df2bf561194..0fb19344510 100644
--- a/app/assets/stylesheets/framework/lists.scss
+++ b/app/assets/stylesheets/framework/lists.scss
@@ -113,7 +113,7 @@ ul.content-list {
}
.title {
- font-weight: 600;
+ font-weight: $gl-font-weight-bold;
}
a {
@@ -212,7 +212,7 @@ ul.content-list {
}
.row-title {
- font-weight: 600;
+ font-weight: $gl-font-weight-bold;
}
.row-second-line {
diff --git a/app/assets/stylesheets/framework/mixins.scss b/app/assets/stylesheets/framework/mixins.scss
index 6f91d11b369..d40b65bb2cc 100644
--- a/app/assets/stylesheets/framework/mixins.scss
+++ b/app/assets/stylesheets/framework/mixins.scss
@@ -43,7 +43,7 @@
background: $gray-light;
a {
- font-weight: 600;
+ font-weight: $gl-font-weight-bold;
}
}
diff --git a/app/assets/stylesheets/framework/modal.scss b/app/assets/stylesheets/framework/modal.scss
index a28f54936be..5b581780447 100644
--- a/app/assets/stylesheets/framework/modal.scss
+++ b/app/assets/stylesheets/framework/modal.scss
@@ -8,7 +8,7 @@
}
.text-danger {
- font-weight: bold;
+ font-weight: $gl-font-weight-bold;
}
}
@@ -16,6 +16,14 @@ body.modal-open {
overflow: hidden;
}
+.modal-no-backdrop {
+ @extend .modal-dialog;
+
+ .modal-content {
+ box-shadow: none;
+ }
+}
+
@media (min-width: $screen-md-min) {
.modal-dialog {
width: 860px;
diff --git a/app/assets/stylesheets/framework/nav.scss b/app/assets/stylesheets/framework/nav.scss
index 071f20fc457..e20108b171b 100644
--- a/app/assets/stylesheets/framework/nav.scss
+++ b/app/assets/stylesheets/framework/nav.scss
@@ -70,7 +70,7 @@
&.active a {
border-bottom: 2px solid $link-underline-blue;
color: $black;
- font-weight: 600;
+ font-weight: $gl-font-weight-bold;
.badge {
color: $black;
@@ -352,7 +352,7 @@
z-index: 300;
li.active {
- font-weight: bold;
+ font-weight: $gl-font-weight-bold;
}
}
}
diff --git a/app/assets/stylesheets/framework/page-header.scss b/app/assets/stylesheets/framework/page-header.scss
index f1ecd050a0a..0c879f40930 100644
--- a/app/assets/stylesheets/framework/page-header.scss
+++ b/app/assets/stylesheets/framework/page-header.scss
@@ -43,7 +43,7 @@
.commit-committer-link,
.commit-author-link {
color: $gl-text-color;
- font-weight: bold;
+ font-weight: $gl-font-weight-bold;
}
.commit-info {
diff --git a/app/assets/stylesheets/framework/selects.scss b/app/assets/stylesheets/framework/selects.scss
index 40e654f4838..8018eb8ba84 100644
--- a/app/assets/stylesheets/framework/selects.scss
+++ b/app/assets/stylesheets/framework/selects.scss
@@ -76,7 +76,7 @@
}
.select2-results li.select2-result-with-children > .select2-result-label {
- font-weight: 600;
+ font-weight: $gl-font-weight-bold;
color: $gl-text-color;
}
@@ -227,7 +227,7 @@
}
.group-name {
- font-weight: bold;
+ font-weight: $gl-font-weight-bold;
}
.group-path {
@@ -252,15 +252,56 @@
.namespace-result {
.namespace-kind {
color: $namespace-kind-color;
- font-weight: normal;
+ font-weight: $gl-font-weight-normal;
}
.namespace-path {
margin-left: 10px;
- font-weight: bolder;
+ font-weight: $gl-font-weight-bold;
}
}
.ajax-users-dropdown {
min-width: 250px !important;
}
+
+// TODO: change global style
+.ajax-project-dropdown,
+body[data-page="projects:blob:new"] #select2-drop,
+body[data-page="profiles:show"] #select2-drop,
+body[data-page="projects:blob:edit"] #select2-drop {
+ &.select2-drop {
+ color: $gl-text-color;
+ }
+
+ .select2-results {
+ .select2-no-results,
+ .select2-searching,
+ .select2-ajax-error,
+ .select2-selection-limit {
+ background: transparent;
+ }
+
+ .select2-result {
+ padding: 0 1px;
+
+ .select2-match {
+ font-weight: $gl-font-weight-bold;
+ text-decoration: none;
+ }
+
+ .select2-result-label {
+ padding: #{$gl-padding / 2} $gl-padding;
+ }
+
+ &.select2-highlighted {
+ background-color: transparent !important;
+ color: $gl-text-color;
+
+ .select2-result-label {
+ background-color: $dropdown-item-hover-bg;
+ }
+ }
+ }
+ }
+}
diff --git a/app/assets/stylesheets/framework/snippets.scss b/app/assets/stylesheets/framework/snippets.scss
index 5f7e1b17cc7..30c15c231d5 100644
--- a/app/assets/stylesheets/framework/snippets.scss
+++ b/app/assets/stylesheets/framework/snippets.scss
@@ -30,7 +30,7 @@
.snippet-title {
font-size: 24px;
- font-weight: 600;
+ font-weight: $gl-font-weight-bold;
}
.snippet-edited-ago {
diff --git a/app/assets/stylesheets/framework/tables.scss b/app/assets/stylesheets/framework/tables.scss
index 6d9fa74a030..4dd31bf28cd 100644
--- a/app/assets/stylesheets/framework/tables.scss
+++ b/app/assets/stylesheets/framework/tables.scss
@@ -32,7 +32,7 @@ table {
th {
background-color: $gray-light;
- font-weight: normal;
+ font-weight: $gl-font-weight-normal;
border-bottom: none;
&.wide {
diff --git a/app/assets/stylesheets/framework/tw_bootstrap.scss b/app/assets/stylesheets/framework/tw_bootstrap.scss
index e54cc2866a7..d5c6ddbb4a5 100644
--- a/app/assets/stylesheets/framework/tw_bootstrap.scss
+++ b/app/assets/stylesheets/framework/tw_bootstrap.scss
@@ -103,7 +103,7 @@ summary {
padding: 4px 5px;
font-size: 12px;
font-style: normal;
- font-weight: normal;
+ font-weight: $gl-font-weight-normal;
display: inline-block;
&.label-gray {
@@ -165,7 +165,7 @@ summary {
.panel-heading {
padding: 6px 15px;
font-size: 13px;
- font-weight: normal;
+ font-weight: $gl-font-weight-normal;
a {
color: $panel-heading-link-color;
diff --git a/app/assets/stylesheets/framework/typography.scss b/app/assets/stylesheets/framework/typography.scss
index 0bd84c9e08c..b2423bc1a66 100644
--- a/app/assets/stylesheets/framework/typography.scss
+++ b/app/assets/stylesheets/framework/typography.scss
@@ -10,9 +10,11 @@
color: $md-link-color;
}
- img {
- /*max-width: 100%;*/
+ img:not(.emoji) {
margin: 0 0 8px;
+ }
+
+ img.lazy {
min-width: 200px;
min-height: 100px;
background-color: $gray-lightest;
@@ -71,7 +73,7 @@
h1 {
font-size: 1.75em;
- font-weight: 600;
+ font-weight: $gl-font-weight-bold;
margin: 24px 0 16px;
padding-bottom: 0.3em;
border-bottom: 1px solid $white-dark;
@@ -84,7 +86,7 @@
h2 {
font-size: 1.5em;
- font-weight: 600;
+ font-weight: $gl-font-weight-bold;
margin: 24px 0 16px;
padding-bottom: 0.3em;
border-bottom: 1px solid $white-dark;
@@ -277,7 +279,7 @@ body {
margin-top: $gl-padding;
line-height: 1.3;
font-size: 1.25em;
- font-weight: 600;
+ font-weight: $gl-font-weight-bold;
&:last-child {
margin-bottom: 0;
@@ -288,7 +290,7 @@ body {
margin-top: 0;
line-height: 1.3;
font-size: 1.25em;
- font-weight: 600;
+ font-weight: $gl-font-weight-bold;
margin: 12px 7px;
}
@@ -299,11 +301,11 @@ h4,
h5,
h6 {
color: $gl-text-color;
- font-weight: 600;
+ font-weight: $gl-font-weight-bold;
}
.light-header {
- font-weight: 600;
+ font-weight: $gl-font-weight-bold;
}
/** CODE **/
diff --git a/app/assets/stylesheets/framework/variables.scss b/app/assets/stylesheets/framework/variables.scss
index 3c109a5a929..26920869bec 100644
--- a/app/assets/stylesheets/framework/variables.scss
+++ b/app/assets/stylesheets/framework/variables.scss
@@ -111,6 +111,8 @@ $well-light-text-color: #5b6169;
* Text
*/
$gl-font-size: 14px;
+$gl-font-weight-normal: 400;
+$gl-font-weight-bold: 600;
$gl-text-color: #2e2e2e;
$gl-text-color-secondary: #707070;
$gl-text-color-tertiary: #949494;
@@ -118,6 +120,7 @@ $gl-text-color-quaternary: #d6d6d6;
$gl-text-color-inverted: rgba(255, 255, 255, 1.0);
$gl-text-color-secondary-inverted: rgba(255, 255, 255, .85);
$gl-text-green: $green-600;
+$gl-text-green-hover: $green-700;
$gl-text-red: $red-500;
$gl-text-orange: $orange-600;
$gl-link-color: $blue-600;
@@ -294,7 +297,7 @@ $dropdown-input-focus-shadow: rgba($dropdown-input-focus-border, .4);
$dropdown-loading-bg: rgba(#fff, .6);
$dropdown-chevron-size: 10px;
$dropdown-toggle-active-border-color: darken($border-color, 14%);
-
+$dropdown-item-hover-bg: $gray-darker;
/*
* Filtered Search
diff --git a/app/assets/stylesheets/framework/wells.scss b/app/assets/stylesheets/framework/wells.scss
index b1ff2659131..5f9756bf58a 100644
--- a/app/assets/stylesheets/framework/wells.scss
+++ b/app/assets/stylesheets/framework/wells.scss
@@ -69,7 +69,7 @@
.well-centered {
h1 {
- font-weight: normal;
+ font-weight: $gl-font-weight-normal;
text-align: center;
font-size: 48px;
}
diff --git a/app/assets/stylesheets/highlight/dark.scss b/app/assets/stylesheets/highlight/dark.scss
index 6e3829d994f..f0ac9b46f91 100644
--- a/app/assets/stylesheets/highlight/dark.scss
+++ b/app/assets/stylesheets/highlight/dark.scss
@@ -204,11 +204,11 @@ $dark-il: #de935f;
.cs { color: $dark-cs; } /* Comment.Special */
.gd { color: $dark-gd; } /* Generic.Deleted */
.ge { font-style: italic; } /* Generic.Emph */
- .gh { color: $dark-gh; font-weight: bold; } /* Generic.Heading */
+ .gh { color: $dark-gh; font-weight: $gl-font-weight-bold; } /* Generic.Heading */
.gi { color: $dark-gi; } /* Generic.Inserted */
- .gp { color: $dark-gp; font-weight: bold; } /* Generic.Prompt */
- .gs { font-weight: bold; } /* Generic.Strong */
- .gu { color: $dark-gu; font-weight: bold; } /* Generic.Subheading */
+ .gp { color: $dark-gp; font-weight: $gl-font-weight-bold; } /* Generic.Prompt */
+ .gs { font-weight: $gl-font-weight-bold; } /* Generic.Strong */
+ .gu { color: $dark-gu; font-weight: $gl-font-weight-bold; } /* Generic.Subheading */
.kc { color: $dark-kc; } /* Keyword.Constant */
.kd { color: $dark-kd; } /* Keyword.Declaration */
.kn { color: $dark-kn; } /* Keyword.Namespace */
diff --git a/app/assets/stylesheets/highlight/monokai.scss b/app/assets/stylesheets/highlight/monokai.scss
index 68eb0c7720f..eba7919ada9 100644
--- a/app/assets/stylesheets/highlight/monokai.scss
+++ b/app/assets/stylesheets/highlight/monokai.scss
@@ -203,7 +203,7 @@ $monokai-gi: #a6e22e;
.c1 { color: $monokai-c1; } /* Comment.Single */
.cs { color: $monokai-cs; } /* Comment.Special */
.ge { font-style: italic; } /* Generic.Emph */
- .gs { font-weight: bold; } /* Generic.Strong */
+ .gs { font-weight: $gl-font-weight-bold; } /* Generic.Strong */
.kc { color: $monokai-kc; } /* Keyword.Constant */
.kd { color: $monokai-kd; } /* Keyword.Declaration */
.kn { color: $monokai-kn; } /* Keyword.Namespace */
diff --git a/app/assets/stylesheets/highlight/solarized_dark.scss b/app/assets/stylesheets/highlight/solarized_dark.scss
index 2cc968c32f2..ba53ef0352b 100644
--- a/app/assets/stylesheets/highlight/solarized_dark.scss
+++ b/app/assets/stylesheets/highlight/solarized_dark.scss
@@ -231,7 +231,7 @@ $solarized-dark-il: #2aa198;
.gi { color: $solarized-dark-gi; } /* Generic.Inserted */
.go { color: $solarized-dark-go; } /* Generic.Output */
.gp { color: $solarized-dark-gp; } /* Generic.Prompt */
- .gs { color: $solarized-dark-gs; font-weight: bold; } /* Generic.Strong */
+ .gs { color: $solarized-dark-gs; font-weight: $gl-font-weight-bold; } /* Generic.Strong */
.gu { color: $solarized-dark-gu; } /* Generic.Subheading */
.gt { color: $solarized-dark-gt; } /* Generic.Traceback */
.kc { color: $solarized-dark-kc; } /* Keyword.Constant */
diff --git a/app/assets/stylesheets/highlight/solarized_light.scss b/app/assets/stylesheets/highlight/solarized_light.scss
index b61b85a2cd1..e9fccf1b58a 100644
--- a/app/assets/stylesheets/highlight/solarized_light.scss
+++ b/app/assets/stylesheets/highlight/solarized_light.scss
@@ -239,7 +239,7 @@ $solarized-light-il: #2aa198;
.gi { color: $solarized-light-gi; } /* Generic.Inserted */
.go { color: $solarized-light-go; } /* Generic.Output */
.gp { color: $solarized-light-gp; } /* Generic.Prompt */
- .gs { color: $solarized-light-gs; font-weight: bold; } /* Generic.Strong */
+ .gs { color: $solarized-light-gs; font-weight: $gl-font-weight-bold; } /* Generic.Strong */
.gu { color: $solarized-light-gu; } /* Generic.Subheading */
.gt { color: $solarized-light-gt; } /* Generic.Traceback */
.kc { color: $solarized-light-kc; } /* Keyword.Constant */
diff --git a/app/assets/stylesheets/highlight/white.scss b/app/assets/stylesheets/highlight/white.scss
index 578f1902cce..65b140cd7f8 100644
--- a/app/assets/stylesheets/highlight/white.scss
+++ b/app/assets/stylesheets/highlight/white.scss
@@ -211,12 +211,12 @@ $white-gc-bg: #eaf2f5;
.hll { background-color: $white-hll-bg; }
.c { color: $white-c; font-style: italic; }
.err { color: $white-err; background-color: $white-err-bg; }
- .k { font-weight: bold; }
- .o { font-weight: bold; }
+ .k { font-weight: $gl-font-weight-bold; }
+ .o { font-weight: $gl-font-weight-bold; }
.cm { color: $white-cm; font-style: italic; }
- .cp { color: $white-cp; font-weight: bold; }
+ .cp { color: $white-cp; font-weight: $gl-font-weight-bold; }
.c1 { color: $white-c1; font-style: italic; }
- .cs { color: $white-cs; font-weight: bold; font-style: italic; }
+ .cs { color: $white-cs; font-weight: $gl-font-weight-bold; font-style: italic; }
.gd { color: $white-gd; background-color: $white-gd-bg; }
.gd .x { color: $white-gd-x; background-color: $white-gd-x-bg; }
.ge { font-style: italic; }
@@ -226,29 +226,29 @@ $white-gc-bg: #eaf2f5;
.gi .x { color: $white-gi-x; background-color: $white-gi-x-bg; }
.go { color: $white-go; }
.gp { color: $white-gp; }
- .gs { font-weight: bold; }
- .gu { color: $white-gu; font-weight: bold; }
+ .gs { font-weight: $gl-font-weight-bold; }
+ .gu { color: $white-gu; font-weight: $gl-font-weight-bold; }
.gt { color: $white-gt; }
- .kc { font-weight: bold; }
- .kd { font-weight: bold; }
- .kn { font-weight: bold; }
- .kp { font-weight: bold; }
- .kr { font-weight: bold; }
- .kt { color: $white-kt; font-weight: bold; }
+ .kc { font-weight: $gl-font-weight-bold; }
+ .kd { font-weight: $gl-font-weight-bold; }
+ .kn { font-weight: $gl-font-weight-bold; }
+ .kp { font-weight: $gl-font-weight-bold; }
+ .kr { font-weight: $gl-font-weight-bold; }
+ .kt { color: $white-kt; font-weight: $gl-font-weight-bold; }
.m { color: $white-m; }
.s { color: $white-s; }
.n { color: $white-n; }
.na { color: $white-na; }
.nb { color: $white-nb; }
- .nc { color: $white-nc; font-weight: bold; }
+ .nc { color: $white-nc; font-weight: $gl-font-weight-bold; }
.no { color: $white-no; }
.ni { color: $white-ni; }
- .ne { color: $white-ne; font-weight: bold; }
- .nf { color: $white-nf; font-weight: bold; }
+ .ne { color: $white-ne; font-weight: $gl-font-weight-bold; }
+ .nf { color: $white-nf; font-weight: $gl-font-weight-bold; }
.nn { color: $white-nn; }
.nt { color: $white-nt; }
.nv { color: $white-nv; }
- .ow { font-weight: bold; }
+ .ow { font-weight: $gl-font-weight-bold; }
.w { color: $white-w; }
.mf { color: $white-mf; }
.mh { color: $white-mh; }
diff --git a/app/assets/stylesheets/mailers/highlighted_diff_email.scss b/app/assets/stylesheets/mailers/highlighted_diff_email.scss
index ea40f449134..fbe538ad1d7 100644
--- a/app/assets/stylesheets/mailers/highlighted_diff_email.scss
+++ b/app/assets/stylesheets/mailers/highlighted_diff_email.scss
@@ -152,12 +152,12 @@ span.highlight_word {
.hll { background-color: $highlighted-hll-bg; }
.c { color: $highlighted-c; font-style: italic; }
.err { color: $highlighted-err; background-color: $highlighted-err-bg; }
-.k { font-weight: bold; }
-.o { font-weight: bold; }
+.k { font-weight: $gl-font-weight-bold; }
+.o { font-weight: $gl-font-weight-bold; }
.cm { color: $highlighted-cm; font-style: italic; }
-.cp { color: $highlighted-cp; font-weight: bold; }
+.cp { color: $highlighted-cp; font-weight: $gl-font-weight-bold; }
.c1 { color: $highlighted-c1; font-style: italic; }
-.cs { color: $highlighted-cs; font-weight: bold; font-style: italic; }
+.cs { color: $highlighted-cs; font-weight: $gl-font-weight-bold; font-style: italic; }
.gd { color: $highlighted-gd; background-color: $highlighted-gd-bg; }
.gd .x { color: $highlighted-gd; background-color: $highlighted-gd-x-bg; }
.ge { font-style: italic; }
@@ -167,29 +167,29 @@ span.highlight_word {
.gi .x { color: $highlighted-gi; background-color: $highlighted-gi-x-bg; }
.go { color: $highlighted-go; }
.gp { color: $highlighted-gp; }
-.gs { font-weight: bold; }
-.gu { color: $highlighted-gu; font-weight: bold; }
+.gs { font-weight: $gl-font-weight-bold; }
+.gu { color: $highlighted-gu; font-weight: $gl-font-weight-bold; }
.gt { color: $highlighted-gt; }
-.kc { font-weight: bold; }
-.kd { font-weight: bold; }
-.kn { font-weight: bold; }
-.kp { font-weight: bold; }
-.kr { font-weight: bold; }
-.kt { color: $highlighted-kt; font-weight: bold; }
+.kc { font-weight: $gl-font-weight-bold; }
+.kd { font-weight: $gl-font-weight-bold; }
+.kn { font-weight: $gl-font-weight-bold; }
+.kp { font-weight: $gl-font-weight-bold; }
+.kr { font-weight: $gl-font-weight-bold; }
+.kt { color: $highlighted-kt; font-weight: $gl-font-weight-bold; }
.m { color: $highlighted-m; }
.s { color: $highlighted-s; }
.n { color: $highlighted-n; }
.na { color: $highlighted-na; }
.nb { color: $highlighted-nb; }
-.nc { color: $highlighted-nc; font-weight: bold; }
+.nc { color: $highlighted-nc; font-weight: $gl-font-weight-bold; }
.no { color: $highlighted-no; }
.ni { color: $highlighted-ni; }
-.ne { color: $highlighted-ne; font-weight: bold; }
-.nf { color: $highlighted-nf; font-weight: bold; }
+.ne { color: $highlighted-ne; font-weight: $gl-font-weight-bold; }
+.nf { color: $highlighted-nf; font-weight: $gl-font-weight-bold; }
.nn { color: $highlighted-nn; }
.nt { color: $highlighted-nt; }
.nv { color: $highlighted-nv; }
-.ow { font-weight: bold; }
+.ow { font-weight: $gl-font-weight-bold; }
.w { color: $highlighted-w; }
.mf { color: $highlighted-mf; }
.mh { color: $highlighted-mh; }
diff --git a/app/assets/stylesheets/new_nav.scss b/app/assets/stylesheets/new_nav.scss
index 2ff1098b8e5..bb7df00f79f 100644
--- a/app/assets/stylesheets/new_nav.scss
+++ b/app/assets/stylesheets/new_nav.scss
@@ -135,7 +135,7 @@ header.navbar-gitlab-new {
li {
.badge {
box-shadow: none;
- font-weight: 600;
+ font-weight: $gl-font-weight-bold;
}
}
}
@@ -194,7 +194,7 @@ header.navbar-gitlab-new {
&.active > a {
box-shadow: inset 0 -3px 0 $indigo-500;
color: $white-light;
- font-weight: 700;
+ font-weight: $gl-font-weight-bold;
}
> a {
diff --git a/app/assets/stylesheets/new_sidebar.scss b/app/assets/stylesheets/new_sidebar.scss
index 2642d16d33d..e21d52b7db6 100644
--- a/app/assets/stylesheets/new_sidebar.scss
+++ b/app/assets/stylesheets/new_sidebar.scss
@@ -45,7 +45,7 @@ $new-sidebar-collapsed-width: 50px;
margin-right: 2px;
a {
- font-weight: 600;
+ font-weight: $gl-font-weight-bold;
display: flex;
align-items: center;
padding: 10px 16px 10px 10px;
@@ -69,8 +69,7 @@ $new-sidebar-collapsed-width: 50px;
background-color: $white-light;
}
- .project-title,
- .group-title {
+ .sidebar-context-title {
overflow: hidden;
text-overflow: ellipsis;
}
@@ -108,7 +107,7 @@ $new-sidebar-collapsed-width: 50px;
}
.badge,
- .project-title {
+ .sidebar-context-title {
display: none;
}
@@ -159,7 +158,7 @@ $new-sidebar-collapsed-width: 50px;
> a {
color: $active-color;
- font-weight: 700;
+ font-weight: $gl-font-weight-bold;
}
svg {
@@ -307,7 +306,7 @@ $new-sidebar-collapsed-width: 50px;
.badge {
color: $active-color;
- font-weight: 600;
+ font-weight: $gl-font-weight-bold;
}
.sidebar-sub-level-items {
@@ -473,6 +472,6 @@ $new-sidebar-collapsed-width: 50px;
border-bottom-color: $active-border;
.badge {
- font-weight: 600;
+ font-weight: $gl-font-weight-bold;
}
}
diff --git a/app/assets/stylesheets/pages/boards.scss b/app/assets/stylesheets/pages/boards.scss
index e5b467a2691..0f3074076ce 100644
--- a/app/assets/stylesheets/pages/boards.scss
+++ b/app/assets/stylesheets/pages/boards.scss
@@ -471,7 +471,7 @@
padding-right: 35px;
> strong {
- font-weight: 600;
+ font-weight: $gl-font-weight-bold;
}
}
}
diff --git a/app/assets/stylesheets/pages/builds.scss b/app/assets/stylesheets/pages/builds.scss
index 486424fb729..3d04df8d820 100644
--- a/app/assets/stylesheets/pages/builds.scss
+++ b/app/assets/stylesheets/pages/builds.scss
@@ -277,7 +277,7 @@
}
.trigger-build-variable {
- font-weight: normal;
+ font-weight: $gl-font-weight-normal;
color: $code-color;
}
@@ -378,7 +378,7 @@
}
&.active {
- font-weight: bold;
+ font-weight: $gl-font-weight-bold;
.fa-arrow-right {
display: block;
diff --git a/app/assets/stylesheets/pages/ci_projects.scss b/app/assets/stylesheets/pages/ci_projects.scss
index 7b4eb689f1b..bf6a48889bf 100644
--- a/app/assets/stylesheets/pages/ci_projects.scss
+++ b/app/assets/stylesheets/pages/ci_projects.scss
@@ -22,7 +22,7 @@
vertical-align: middle !important;
a {
- font-weight: normal;
+ font-weight: $gl-font-weight-normal;
text-decoration: none;
}
}
diff --git a/app/assets/stylesheets/pages/commits.scss b/app/assets/stylesheets/pages/commits.scss
index 01f5d2b67aa..b518036b01d 100644
--- a/app/assets/stylesheets/pages/commits.scss
+++ b/app/assets/stylesheets/pages/commits.scss
@@ -213,7 +213,7 @@
.commit-sha {
font-size: 14px;
- font-weight: 600;
+ font-weight: $gl-font-weight-bold;
}
}
@@ -286,6 +286,9 @@
.gpg-status-box {
+ padding: 2px 10px;
+ margin-right: $gl-padding;
+
&:empty {
display: none;
}
@@ -303,7 +306,7 @@
.gpg-popover-status {
display: flex;
align-items: center;
- font-weight: normal;
+ font-weight: $gl-font-weight-normal;
line-height: 1.5;
}
@@ -314,7 +317,6 @@
&.valid {
svg {
border: 1px solid $brand-success;
-
fill: $brand-success;
}
}
@@ -322,7 +324,6 @@
&.invalid {
svg {
border: 1px solid $common-gray-light;
-
fill: $common-gray-light;
}
}
diff --git a/app/assets/stylesheets/pages/convdev_index.scss b/app/assets/stylesheets/pages/convdev_index.scss
index 0413114c279..16702442f50 100644
--- a/app/assets/stylesheets/pages/convdev_index.scss
+++ b/app/assets/stylesheets/pages/convdev_index.scss
@@ -23,7 +23,7 @@ $space-between-cards: 8px;
line-height: 1;
color: $gl-text-color-secondary;
margin-left: 8px;
- font-weight: 500;
+ font-weight: $gl-font-weight-normal;
a {
font-size: 18px;
@@ -139,7 +139,7 @@ $space-between-cards: 8px;
.card-score-value {
font-size: 16px;
color: $gl-text-color;
- font-weight: 500;
+ font-weight: $gl-font-weight-normal;
}
.card-score-big {
@@ -147,7 +147,7 @@ $space-between-cards: 8px;
border-bottom: 1px solid $border-color;
font-size: 22px;
padding: 10px 0;
- font-weight: 500;
+ font-weight: $gl-font-weight-normal;
}
.card-buttons {
diff --git a/app/assets/stylesheets/pages/cycle_analytics.scss b/app/assets/stylesheets/pages/cycle_analytics.scss
index 6753eb08285..2a92673d9fa 100644
--- a/app/assets/stylesheets/pages/cycle_analytics.scss
+++ b/app/assets/stylesheets/pages/cycle_analytics.scss
@@ -68,7 +68,7 @@
}
.stage-name {
- font-weight: 600;
+ font-weight: $gl-font-weight-bold;
}
}
@@ -93,7 +93,7 @@
.header {
font-size: 30px;
line-height: 38px;
- font-weight: normal;
+ font-weight: $gl-font-weight-normal;
margin: 0;
}
@@ -130,7 +130,7 @@
&.title {
line-height: 19px;
font-size: 14px;
- font-weight: 600;
+ font-weight: $gl-font-weight-bold;
color: $gl-text-color;
}
@@ -211,7 +211,7 @@
box-shadow: inset 2px 0 0 0 $active-item-blue;
.stage-name {
- font-weight: 600;
+ font-weight: $gl-font-weight-bold;
}
}
@@ -404,7 +404,7 @@
color: $gl-link-color;
line-height: 1.3;
vertical-align: top;
- font-weight: normal;
+ font-weight: $gl-font-weight-normal;
}
.fa {
diff --git a/app/assets/stylesheets/pages/diff.scss b/app/assets/stylesheets/pages/diff.scss
index 913a1a95dca..8cbf0ec6180 100644
--- a/app/assets/stylesheets/pages/diff.scss
+++ b/app/assets/stylesheets/pages/diff.scss
@@ -40,7 +40,7 @@
// "Changes suppressed. Click to show." link
.show-suppressed-diff {
font-size: 110%;
- font-weight: bold;
+ font-weight: $gl-font-weight-bold;
}
}
@@ -104,7 +104,7 @@
a {
float: left;
width: 35px;
- font-weight: normal;
+ font-weight: $gl-font-weight-normal;
&[disabled] {
cursor: default;
@@ -395,7 +395,7 @@
background-color: transparent;
border: 0;
color: $gl-link-color;
- font-weight: 600;
+ font-weight: $gl-font-weight-bold;
&:hover,
&:focus {
diff --git a/app/assets/stylesheets/pages/editor.scss b/app/assets/stylesheets/pages/editor.scss
index f6b8c8ee2bc..d3cd4d507de 100644
--- a/app/assets/stylesheets/pages/editor.scss
+++ b/app/assets/stylesheets/pages/editor.scss
@@ -204,6 +204,8 @@
.gitlab-ci-yml-selector,
.dockerfile-selector,
.template-type-selector {
+ @include new-style-dropdown;
+
display: inline-block;
vertical-align: top;
font-family: $regular_font;
diff --git a/app/assets/stylesheets/pages/environments.scss b/app/assets/stylesheets/pages/environments.scss
index 00ebf4e26ac..a8d2ae0af28 100644
--- a/app/assets/stylesheets/pages/environments.scss
+++ b/app/assets/stylesheets/pages/environments.scss
@@ -6,7 +6,7 @@
}
.environments-folder-name {
- font-weight: normal;
+ font-weight: $gl-font-weight-normal;
padding-top: 20px;
}
@@ -246,13 +246,13 @@
}
.text-metric-bold {
- font-weight: 600;
+ font-weight: $gl-font-weight-bold;
}
.label-axis-text,
.text-metric-usage {
fill: $black;
- font-weight: 500;
+ font-weight: $gl-font-weight-normal;
font-size: 12px;
}
diff --git a/app/assets/stylesheets/pages/events.scss b/app/assets/stylesheets/pages/events.scss
index 4c3fa1fb8d4..1723d716805 100644
--- a/app/assets/stylesheets/pages/events.scss
+++ b/app/assets/stylesheets/pages/events.scss
@@ -57,7 +57,7 @@
.event-title {
@include str-truncated(calc(100% - 174px));
- font-weight: 600;
+ font-weight: $gl-font-weight-bold;
color: $list-text-color;
}
diff --git a/app/assets/stylesheets/pages/issuable.scss b/app/assets/stylesheets/pages/issuable.scss
index 49839a9b528..ab5a901da71 100644
--- a/app/assets/stylesheets/pages/issuable.scss
+++ b/app/assets/stylesheets/pages/issuable.scss
@@ -271,7 +271,7 @@
}
.light {
- font-weight: normal;
+ font-weight: $gl-font-weight-normal;
}
.no-value {
@@ -306,7 +306,7 @@
display: block;
margin-top: 4px;
font-size: 13px;
- font-weight: normal;
+ font-weight: $gl-font-weight-normal;
}
.hide-expanded {
@@ -689,7 +689,7 @@
.issuable-info,
.task-status,
.issuable-updated-at {
- font-weight: normal;
+ font-weight: $gl-font-weight-normal;
color: $gl-text-color-secondary;
a {
diff --git a/app/assets/stylesheets/pages/issues.scss b/app/assets/stylesheets/pages/issues.scss
index 8cdb3f34ae5..e2177f96aee 100644
--- a/app/assets/stylesheets/pages/issues.scss
+++ b/app/assets/stylesheets/pages/issues.scss
@@ -75,7 +75,7 @@ ul.related-merge-requests > li {
.merge-requests-title,
.related-branches-title {
font-size: 16px;
- font-weight: 600;
+ font-weight: $gl-font-weight-bold;
}
.merge-request-id {
@@ -244,7 +244,7 @@ ul.related-merge-requests > li {
strong {
display: block;
- font-weight: 600;
+ font-weight: $gl-font-weight-bold;
}
}
}
diff --git a/app/assets/stylesheets/pages/login.scss b/app/assets/stylesheets/pages/login.scss
index 3cbe8dededb..d4dc43035eb 100644
--- a/app/assets/stylesheets/pages/login.scss
+++ b/app/assets/stylesheets/pages/login.scss
@@ -22,7 +22,7 @@
}
h1:first-child {
- font-weight: normal;
+ font-weight: $gl-font-weight-normal;
margin-bottom: 0.68em;
margin-top: 0;
font-size: 34px;
@@ -38,7 +38,7 @@
}
a {
- font-weight: bold;
+ font-weight: $gl-font-weight-bold;
}
}
@@ -54,7 +54,7 @@
padding: 15px;
.login-heading h3 {
- font-weight: 300;
+ font-weight: $gl-font-weight-normal;
line-height: 1.5;
margin: 0 0 10px;
}
@@ -186,7 +186,7 @@
}
label {
- font-weight: normal;
+ font-weight: $gl-font-weight-normal;
}
.submit-container {
diff --git a/app/assets/stylesheets/pages/members.scss b/app/assets/stylesheets/pages/members.scss
index e7c07ef67f0..3fb02e9964f 100644
--- a/app/assets/stylesheets/pages/members.scss
+++ b/app/assets/stylesheets/pages/members.scss
@@ -46,7 +46,7 @@
}
strong {
- font-weight: 600;
+ font-weight: $gl-font-weight-bold;
}
}
@@ -96,6 +96,8 @@
}
.member-search-form {
+ @include new-style-dropdown;
+
position: relative;
@media (min-width: $screen-sm-min) {
@@ -221,7 +223,7 @@
}
.member {
- font-weight: bold;
+ font-weight: $gl-font-weight-bold;
overflow-wrap: break-word;
word-break: break-all;
}
diff --git a/app/assets/stylesheets/pages/merge_requests.scss b/app/assets/stylesheets/pages/merge_requests.scss
index 6bb013cca85..334bec8dd7e 100644
--- a/app/assets/stylesheets/pages/merge_requests.scss
+++ b/app/assets/stylesheets/pages/merge_requests.scss
@@ -197,7 +197,7 @@
@extend .ref-name;
color: $gl-text-color;
- font-weight: 600;
+ font-weight: $gl-font-weight-bold;
overflow: hidden;
word-break: break-all;
@@ -228,7 +228,7 @@
.mr-widget-body {
h4 {
float: left;
- font-weight: 600;
+ font-weight: $gl-font-weight-bold;
font-size: 14px;
line-height: inherit;
margin-top: 0;
@@ -239,7 +239,7 @@
}
time {
- font-weight: normal;
+ font-weight: $gl-font-weight-normal;
}
}
@@ -249,7 +249,7 @@
}
label {
- font-weight: normal;
+ font-weight: $gl-font-weight-normal;
}
.spacing {
@@ -257,12 +257,12 @@
}
.bold {
- font-weight: 600;
+ font-weight: $gl-font-weight-bold;
color: $gl-gray-light;
}
.state-label {
- font-weight: 600;
+ font-weight: $gl-font-weight-bold;
padding-right: 10px;
}
@@ -336,7 +336,7 @@
.text {
span {
- font-weight: 600;
+ font-weight: $gl-font-weight-bold;
}
p {
@@ -489,6 +489,8 @@
}
.mr-source-target {
+ @include new-style-dropdown;
+
display: flex;
flex-wrap: wrap;
justify-content: space-between;
@@ -505,7 +507,7 @@
.panel-new-merge-request {
.panel-heading {
padding: 5px 10px;
- font-weight: 600;
+ font-weight: $gl-font-weight-bold;
line-height: 25px;
}
diff --git a/app/assets/stylesheets/pages/milestone.scss b/app/assets/stylesheets/pages/milestone.scss
index 55e0ee1936e..32039936be7 100644
--- a/app/assets/stylesheets/pages/milestone.scss
+++ b/app/assets/stylesheets/pages/milestone.scss
@@ -7,7 +7,7 @@
padding: 10px 16px;
h4 {
- font-weight: bold;
+ font-weight: $gl-font-weight-bold;
}
.progress {
@@ -81,7 +81,7 @@
}
.remaining-days strong {
- font-weight: normal;
+ font-weight: $gl-font-weight-normal;
}
.milestone-stat {
diff --git a/app/assets/stylesheets/pages/note_form.scss b/app/assets/stylesheets/pages/note_form.scss
index b4468d6d0a2..9558924bbcb 100644
--- a/app/assets/stylesheets/pages/note_form.scss
+++ b/app/assets/stylesheets/pages/note_form.scss
@@ -188,7 +188,7 @@
.close {
color: $white-light;
opacity: 0.85;
- font-weight: normal;
+ font-weight: $gl-font-weight-normal;
&:hover {
opacity: 1;
diff --git a/app/assets/stylesheets/pages/notes.scss b/app/assets/stylesheets/pages/notes.scss
index 0a194f3707f..fbfe5d3c682 100644
--- a/app/assets/stylesheets/pages/notes.scss
+++ b/app/assets/stylesheets/pages/notes.scss
@@ -766,17 +766,25 @@ ul.notes {
background-color: transparent;
border: none;
outline: 0;
+ transition: color $general-hover-transition-duration $general-hover-transition-curve;
&.is-disabled {
cursor: default;
}
- &:not(.is-disabled):hover,
+ &:not(.is-disabled) {
+ &:hover,
+ &:focus {
+ color: $gl-text-green;
+ }
+ }
+
&.is-active {
color: $gl-text-green;
- svg {
- fill: $gl-text-green;
+ &:hover,
+ &:focus {
+ color: $gl-text-green-hover;
}
}
diff --git a/app/assets/stylesheets/pages/notifications.scss b/app/assets/stylesheets/pages/notifications.scss
index bdf07a99daf..c28b1e68008 100644
--- a/app/assets/stylesheets/pages/notifications.scss
+++ b/app/assets/stylesheets/pages/notifications.scss
@@ -14,3 +14,7 @@
font-size: 18px;
}
}
+
+.notification-form {
+ @include new-style-dropdown;
+}
diff --git a/app/assets/stylesheets/pages/pipeline_schedules.scss b/app/assets/stylesheets/pages/pipeline_schedules.scss
index dc1654e006e..7e2297c283f 100644
--- a/app/assets/stylesheets/pages/pipeline_schedules.scss
+++ b/app/assets/stylesheets/pages/pipeline_schedules.scss
@@ -12,7 +12,7 @@
.interval-pattern-form-group {
label {
margin-right: 10px;
- font-weight: normal;
+ font-weight: $gl-font-weight-normal;
&[for='custom'] {
margin-right: 0;
diff --git a/app/assets/stylesheets/pages/pipelines.scss b/app/assets/stylesheets/pages/pipelines.scss
index 85d1905ad40..51656669c98 100644
--- a/app/assets/stylesheets/pages/pipelines.scss
+++ b/app/assets/stylesheets/pages/pipelines.scss
@@ -128,7 +128,7 @@
.branch-commit {
.ref-name {
- font-weight: bold;
+ font-weight: $gl-font-weight-bold;
max-width: 120px;
overflow: hidden;
display: inline-block;
@@ -272,7 +272,7 @@
.build-name {
float: right;
- font-weight: 500;
+ font-weight: $gl-font-weight-normal;
}
.ci-status-icon-failed svg {
@@ -281,7 +281,7 @@
.stage {
color: $gl-text-color-secondary;
- font-weight: 500;
+ font-weight: $gl-font-weight-normal;
vertical-align: middle;
}
}
@@ -420,7 +420,7 @@
.stage-name {
margin: 0 0 15px 10px;
- font-weight: bold;
+ font-weight: $gl-font-weight-bold;
width: 176px;
white-space: nowrap;
overflow: hidden;
@@ -580,7 +580,7 @@
vertical-align: bottom;
display: inline-block;
position: relative;
- font-weight: normal;
+ font-weight: $gl-font-weight-normal;
}
@mixin mini-pipeline-graph-color($color-light, $color-main, $color-dark) {
@@ -724,7 +724,7 @@ button.mini-pipeline-graph-dropdown-toggle {
.mini-pipeline-graph-dropdown-item {
padding: 3px 7px 4px;
clear: both;
- font-weight: normal;
+ font-weight: $gl-font-weight-normal;
line-height: 1.428571429;
white-space: nowrap;
margin: 0 5px;
@@ -927,3 +927,7 @@ button.mini-pipeline-graph-dropdown-toggle {
}
}
}
+
+.pipelines-container .top-area .nav-controls > .btn:last-child {
+ float: none;
+}
diff --git a/app/assets/stylesheets/pages/profile.scss b/app/assets/stylesheets/pages/profile.scss
index 14ad06b0ac2..c5d6ff66dd6 100644
--- a/app/assets/stylesheets/pages/profile.scss
+++ b/app/assets/stylesheets/pages/profile.scss
@@ -83,7 +83,7 @@
&::after {
content: "\00B7"; // Middle Dot
padding: 0 6px;
- font-weight: bold;
+ font-weight: $gl-font-weight-bold;
}
&:last-child {
@@ -277,7 +277,7 @@ table.u2f-registrations {
.oauth-application-show {
.scope-name {
- font-weight: 600;
+ font-weight: $gl-font-weight-bold;
}
.scopes-list {
diff --git a/app/assets/stylesheets/pages/projects.scss b/app/assets/stylesheets/pages/projects.scss
index d01326637ea..39c4264e496 100644
--- a/app/assets/stylesheets/pages/projects.scss
+++ b/app/assets/stylesheets/pages/projects.scss
@@ -2,7 +2,7 @@
margin: -16px;
.alert-link {
- font-weight: normal;
+ font-weight: $gl-font-weight-normal;
}
}
@@ -114,7 +114,7 @@
margin-top: 10px;
margin-bottom: 10px;
font-size: 24px;
- font-weight: 400;
+ font-weight: $gl-font-weight-normal;
line-height: 1;
word-wrap: break-word;
@@ -259,7 +259,7 @@
border-width: 1px;
border-style: solid;
font-size: 13px;
- font-weight: 600;
+ font-weight: $gl-font-weight-bold;
line-height: 13px;
letter-spacing: .4px;
padding: 6px 14px;
@@ -309,7 +309,7 @@
}
.option-title {
- font-weight: normal;
+ font-weight: $gl-font-weight-normal;
display: inline-block;
color: $gl-text-color;
}
@@ -575,7 +575,7 @@ a.deploy-project-label {
color: $gl-text-color-tertiary;
transform: translateY(-50%);
font-size: 12px;
- font-weight: bold;
+ font-weight: $gl-font-weight-bold;
line-height: 20px;
// Mobile
@@ -826,7 +826,7 @@ pre.light-well {
.new-protected-tag {
label {
margin-top: 6px;
- font-weight: normal;
+ font-weight: $gl-font-weight-normal;
}
}
@@ -853,7 +853,7 @@ pre.light-well {
}
&.is-active {
- font-weight: 600;
+ font-weight: $gl-font-weight-bold;
}
}
@@ -952,7 +952,7 @@ pre.light-well {
&::before {
font-family: FontAwesome;
- font-weight: normal;
+ font-weight: $gl-font-weight-normal;
font-style: normal;
}
}
diff --git a/app/assets/stylesheets/pages/repo.scss b/app/assets/stylesheets/pages/repo.scss
index 1f4d4698199..efc47861768 100644
--- a/app/assets/stylesheets/pages/repo.scss
+++ b/app/assets/stylesheets/pages/repo.scss
@@ -99,6 +99,30 @@
.blob-viewer-container {
flex: 1;
overflow: auto;
+
+ > div,
+ .file-content {
+ display: flex;
+ }
+
+ > div,
+ .file-content,
+ .blob-viewer,
+ .line-number,
+ .blob-content,
+ .code {
+ min-height: 100%;
+ width: 100%;
+ }
+
+ .line-numbers {
+ min-width: 44px;
+ }
+
+ .blob-content {
+ flex: 1;
+ overflow-x: auto;
+ }
}
#tabs {
@@ -182,7 +206,6 @@
padding: 5px 10px;
position: relative;
border-top: 1px solid $white-normal;
- margin-top: -5px;
}
#binary-viewer {
@@ -267,7 +290,7 @@
display: inline-block;
font-size: 10px;
text-transform: uppercase;
- font-weight: bold;
+ font-weight: $gl-font-weight-bold;
color: $gray-darkest;
white-space: nowrap;
overflow: hidden;
diff --git a/app/assets/stylesheets/pages/runners.scss b/app/assets/stylesheets/pages/runners.scss
index 57c73295d1e..6cac37a4e28 100644
--- a/app/assets/stylesheets/pages/runners.scss
+++ b/app/assets/stylesheets/pages/runners.scss
@@ -30,7 +30,7 @@
}
h4 {
- font-weight: normal;
+ font-weight: $gl-font-weight-normal;
}
}
diff --git a/app/assets/stylesheets/pages/search.scss b/app/assets/stylesheets/pages/search.scss
index b9818ffcf42..8d73246223d 100644
--- a/app/assets/stylesheets/pages/search.scss
+++ b/app/assets/stylesheets/pages/search.scss
@@ -94,7 +94,7 @@ input[type="checkbox"]:hover {
&::before {
font-family: FontAwesome;
- font-weight: normal;
+ font-weight: $gl-font-weight-normal;
font-style: normal;
}
}
diff --git a/app/assets/stylesheets/pages/sherlock.scss b/app/assets/stylesheets/pages/sherlock.scss
index 23a9c2ada80..bfe065dbbaf 100644
--- a/app/assets/stylesheets/pages/sherlock.scss
+++ b/app/assets/stylesheets/pages/sherlock.scss
@@ -29,5 +29,5 @@ table .sherlock-code {
.sherlock-line-samples-table .slow {
color: $red-500;
- font-weight: bold;
+ font-weight: $gl-font-weight-bold;
}
diff --git a/app/assets/stylesheets/pages/todos.scss b/app/assets/stylesheets/pages/todos.scss
index d7a9dda3770..6c8d87185e9 100644
--- a/app/assets/stylesheets/pages/todos.scss
+++ b/app/assets/stylesheets/pages/todos.scss
@@ -108,14 +108,14 @@
margin: 0;
float: none;
display: inline-block;
- font-weight: normal;
+ font-weight: $gl-font-weight-normal;
padding: 0 5px;
line-height: inherit;
font-size: 14px;
}
.action-name {
- font-weight: normal;
+ font-weight: $gl-font-weight-normal;
}
.todo-body {
@@ -262,6 +262,10 @@
}
a {
- font-weight: 600;
+ font-weight: $gl-font-weight-bold;
}
}
+
+.todos-filters {
+ @include new-style-dropdown;
+}
diff --git a/app/assets/stylesheets/pages/tree.scss b/app/assets/stylesheets/pages/tree.scss
index 0028e207f3e..224eee90a3f 100644
--- a/app/assets/stylesheets/pages/tree.scss
+++ b/app/assets/stylesheets/pages/tree.scss
@@ -231,7 +231,7 @@
}
.upload-link {
- font-weight: normal;
+ font-weight: $gl-font-weight-normal;
color: $md-link-color;
}
diff --git a/app/assets/stylesheets/pages/ui_dev_kit.scss b/app/assets/stylesheets/pages/ui_dev_kit.scss
index 798e060a261..48ac5b21db8 100644
--- a/app/assets/stylesheets/pages/ui_dev_kit.scss
+++ b/app/assets/stylesheets/pages/ui_dev_kit.scss
@@ -1,7 +1,7 @@
.gitlab-ui-dev-kit {
> h2 {
margin: 35px 0 20px;
- font-weight: bold;
+ font-weight: $gl-font-weight-bold;
}
.example {
diff --git a/app/assets/stylesheets/pages/wiki.scss b/app/assets/stylesheets/pages/wiki.scss
index fa6bdd297eb..b7d4e7bf582 100644
--- a/app/assets/stylesheets/pages/wiki.scss
+++ b/app/assets/stylesheets/pages/wiki.scss
@@ -37,7 +37,7 @@
}
.light {
- font-weight: normal;
+ font-weight: $gl-font-weight-normal;
color: $gl-text-color-secondary;
}
@@ -89,7 +89,7 @@
h3 {
font-size: 19px;
- font-weight: normal;
+ font-weight: $gl-font-weight-normal;
margin: $gl-padding 0;
}
}
diff --git a/app/assets/stylesheets/pages/xterm.scss b/app/assets/stylesheets/pages/xterm.scss
index b085c56390d..c7297a34ad8 100644
--- a/app/assets/stylesheets/pages/xterm.scss
+++ b/app/assets/stylesheets/pages/xterm.scss
@@ -281,7 +281,7 @@
$xterm-fg-255: #eee;
.term-bold {
- font-weight: bold;
+ font-weight: $gl-font-weight-bold;
}
.term-italic {
diff --git a/app/assets/stylesheets/print.scss b/app/assets/stylesheets/print.scss
index 113e6e86bb5..b07a5ae22cd 100644
--- a/app/assets/stylesheets/print.scss
+++ b/app/assets/stylesheets/print.scss
@@ -17,7 +17,7 @@
.wiki h3 {
font-size: 18px;
- font-weight: bold;
+ font-weight: 600;
}
header,
diff --git a/app/controllers/admin/logs_controller.rb b/app/controllers/admin/logs_controller.rb
index b999018dde4..bdc4332ae69 100644
--- a/app/controllers/admin/logs_controller.rb
+++ b/app/controllers/admin/logs_controller.rb
@@ -1,2 +1,11 @@
class Admin::LogsController < Admin::ApplicationController
+ def show
+ @loggers = [
+ Gitlab::AppLogger,
+ Gitlab::GitLogger,
+ Gitlab::EnvironmentLogger,
+ Gitlab::SidekiqLogger,
+ Gitlab::RepositoryCheckLogger
+ ]
+ end
end
diff --git a/app/controllers/admin/projects_controller.rb b/app/controllers/admin/projects_controller.rb
index 0b6cd71e651..50cf2643390 100644
--- a/app/controllers/admin/projects_controller.rb
+++ b/app/controllers/admin/projects_controller.rb
@@ -3,9 +3,9 @@ class Admin::ProjectsController < Admin::ApplicationController
before_action :group, only: [:show, :transfer]
def index
- finder = Admin::ProjectsFinder.new(params: params, current_user: current_user)
- @projects = finder.execute
- @sort = finder.sort
+ params[:sort] ||= 'latest_activity_desc'
+ @sort = params[:sort]
+ @projects = Admin::ProjectsFinder.new(params: params, current_user: current_user).execute
respond_to do |format|
format.html
diff --git a/app/controllers/autocomplete_controller.rb b/app/controllers/autocomplete_controller.rb
index 3120916c5bb..54f78fc8719 100644
--- a/app/controllers/autocomplete_controller.rb
+++ b/app/controllers/autocomplete_controller.rb
@@ -1,5 +1,7 @@
class AutocompleteController < ApplicationController
- skip_before_action :authenticate_user!, only: [:users]
+ AWARD_EMOJI_MAX = 100
+
+ skip_before_action :authenticate_user!, only: [:users, :award_emojis]
before_action :load_project, only: [:users]
before_action :find_users, only: [:users]
@@ -48,6 +50,20 @@ class AutocompleteController < ApplicationController
render json: projects.to_json(only: [:id, :name_with_namespace], methods: :name_with_namespace)
end
+ def award_emojis
+ emoji_with_count = AwardEmoji
+ .limit(AWARD_EMOJI_MAX)
+ .where(user: current_user)
+ .group(:name)
+ .order(count: :desc, name: :asc)
+ .count
+
+ # Transform from hash to array to guarantee json order
+ # e.g. { 'thumbsup' => 2, 'thumbsdown' = 1 }
+ # => [{ name: 'thumbsup' }, { name: 'thumbsdown' }]
+ render json: emoji_with_count.map { |k, v| { name: k } }
+ end
+
private
def find_users
diff --git a/app/controllers/concerns/issuable_collections.rb b/app/controllers/concerns/issuable_collections.rb
index b43b2c5621f..a34a82b7ba6 100644
--- a/app/controllers/concerns/issuable_collections.rb
+++ b/app/controllers/concerns/issuable_collections.rb
@@ -15,7 +15,17 @@ module IssuableCollections
end
def merge_requests_collection
- merge_requests_finder.execute.preload(:source_project, :target_project, :author, :assignee, :labels, :milestone, :head_pipeline, target_project: :namespace, merge_request_diff: :merge_request_diff_commits)
+ merge_requests_finder.execute.preload(
+ :source_project,
+ :target_project,
+ :author,
+ :assignee,
+ :labels,
+ :milestone,
+ head_pipeline: :project,
+ target_project: :namespace,
+ merge_request_diff: :merge_request_diff_commits
+ )
end
def issues_finder
diff --git a/app/controllers/groups/milestones_controller.rb b/app/controllers/groups/milestones_controller.rb
index 5c10d7bc261..7a7bcb1a3d2 100644
--- a/app/controllers/groups/milestones_controller.rb
+++ b/app/controllers/groups/milestones_controller.rb
@@ -35,13 +35,13 @@ class Groups::MilestonesController < Groups::ApplicationController
end
def edit
- render_404 if @milestone.is_legacy_group_milestone?
+ render_404 if @milestone.legacy_group_milestone?
end
def update
# Keep this compatible with legacy group milestones where we have to update
# all projects milestones states at once.
- if @milestone.is_legacy_group_milestone?
+ if @milestone.legacy_group_milestone?
update_params = milestone_params.select { |key| key == "state_event" }
milestones = @milestone.milestones
else
@@ -67,7 +67,7 @@ class Groups::MilestonesController < Groups::ApplicationController
end
def milestone_path
- if @milestone.is_legacy_group_milestone?
+ if @milestone.legacy_group_milestone?
group_milestone_path(group, @milestone.safe_title, title: @milestone.title)
else
group_milestone_path(group, @milestone.iid)
diff --git a/app/controllers/groups_controller.rb b/app/controllers/groups_controller.rb
index f76b3f69e9e..994e736d66e 100644
--- a/app/controllers/groups_controller.rb
+++ b/app/controllers/groups_controller.rb
@@ -26,6 +26,13 @@ class GroupsController < Groups::ApplicationController
def new
@group = Group.new
+
+ if params[:parent_id].present?
+ parent = Group.find_by(id: params[:parent_id])
+ if can?(current_user, :create_subgroup, parent)
+ @group.parent = parent
+ end
+ end
end
def create
diff --git a/app/controllers/omniauth_callbacks_controller.rb b/app/controllers/omniauth_callbacks_controller.rb
index 7444826a5d1..9612b8d8514 100644
--- a/app/controllers/omniauth_callbacks_controller.rb
+++ b/app/controllers/omniauth_callbacks_controller.rb
@@ -10,6 +10,14 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController
end
end
+ if Gitlab::LDAP::Config.enabled?
+ Gitlab::LDAP::Config.available_servers.each do |server|
+ define_method server['provider_name'] do
+ ldap
+ end
+ end
+ end
+
# Extend the standard message generation to accept our custom exception
def failure_message
exception = env["omniauth.error"]
diff --git a/app/controllers/projects/issues_controller.rb b/app/controllers/projects/issues_controller.rb
index 8893a514207..1afaceac567 100644
--- a/app/controllers/projects/issues_controller.rb
+++ b/app/controllers/projects/issues_controller.rb
@@ -202,7 +202,7 @@ class Projects::IssuesController < Projects::ApplicationController
task_status: @issue.task_status
}
- if @issue.is_edited?
+ if @issue.edited?
response[:updated_at] = @issue.updated_at
response[:updated_by_name] = @issue.last_edited_by.name
response[:updated_by_path] = user_path(@issue.last_edited_by)
diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb
index 2a3b73577a5..e3fa3736808 100644
--- a/app/controllers/projects/merge_requests_controller.rb
+++ b/app/controllers/projects/merge_requests_controller.rb
@@ -318,14 +318,14 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
elsif @merge_request.head_pipeline.success?
# This can be triggered when a user clicks the auto merge button while
# the tests finish at about the same time
- MergeWorker.perform_async(@merge_request.id, current_user.id, params)
+ @merge_request.merge_async(current_user.id, params)
:success
else
:failed
end
else
- MergeWorker.perform_async(@merge_request.id, current_user.id, params)
+ @merge_request.merge_async(current_user.id, params)
:success
end
diff --git a/app/controllers/projects/services_controller.rb b/app/controllers/projects/services_controller.rb
index d54a1111f11..daa5c88aae0 100644
--- a/app/controllers/projects/services_controller.rb
+++ b/app/controllers/projects/services_controller.rb
@@ -4,7 +4,6 @@ class Projects::ServicesController < Projects::ApplicationController
# Authorize
before_action :authorize_admin_project!
before_action :service, only: [:edit, :update, :test]
- before_action :update_service, only: [:update, :test]
respond_to :html
@@ -14,6 +13,8 @@ class Projects::ServicesController < Projects::ApplicationController
end
def update
+ @service.attributes = service_params[:service]
+
if @service.save(context: :manual_change)
redirect_to(project_settings_integrations_path(@project), notice: success_message)
else
@@ -24,7 +25,7 @@ class Projects::ServicesController < Projects::ApplicationController
def test
message = {}
- if @service.can_test?
+ if @service.can_test? && @service.update_attributes(service_params[:service])
data = @service.test_data(project, current_user)
outcome = @service.test(data)
@@ -50,10 +51,6 @@ class Projects::ServicesController < Projects::ApplicationController
end
end
- def update_service
- @service.assign_attributes(service_params[:service])
- end
-
def service
@service ||= @project.find_or_initialize_service(params[:id])
end
diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb
index 9e743685d60..be6491d042c 100644
--- a/app/controllers/sessions_controller.rb
+++ b/app/controllers/sessions_controller.rb
@@ -5,14 +5,6 @@ class SessionsController < Devise::SessionsController
skip_before_action :check_two_factor_requirement, only: [:destroy]
- # Explicitly call protect from forgery before anything else. Otherwise the
- # CSFR-token might be cleared before authentication is done. This was the case
- # when LDAP was enabled and the `OmniauthCallbacksController` is loaded
- #
- # *Note:* `prepend: true` is the default for rails4, but this will be changed
- # to `prepend: false` in rails5.
- protect_from_forgery prepend: true, with: :exception
-
prepend_before_action :check_initial_setup, only: [:new]
prepend_before_action :authenticate_with_two_factor,
if: :two_factor_enabled?, only: [:create]
diff --git a/app/finders/admin/projects_finder.rb b/app/finders/admin/projects_finder.rb
index 7176bfe22d6..d6bcd939522 100644
--- a/app/finders/admin/projects_finder.rb
+++ b/app/finders/admin/projects_finder.rb
@@ -1,33 +1,67 @@
class Admin::ProjectsFinder
- attr_reader :sort, :namespace_id, :visibility_level, :with_push,
- :abandoned, :last_repository_check_failed, :archived,
- :personal, :name, :page, :current_user
+ attr_reader :params, :current_user
def initialize(params:, current_user:)
+ @params = params
@current_user = current_user
- @sort = params.fetch(:sort) { 'latest_activity_desc' }
- @namespace_id = params[:namespace_id]
- @visibility_level = params[:visibility_level]
- @with_push = params[:with_push]
- @abandoned = params[:abandoned]
- @last_repository_check_failed = params[:last_repository_check_failed]
- @archived = params[:archived]
- @personal = params[:personal]
- @name = params[:name]
- @page = params[:page]
end
def execute
items = Project.without_deleted.with_statistics
- items = items.in_namespace(namespace_id) if namespace_id.present?
- items = items.where(visibility_level: visibility_level) if visibility_level.present?
- items = items.with_push if with_push.present?
- items = items.abandoned if abandoned.present?
- items = items.where(last_repository_check_failed: true) if last_repository_check_failed.present?
- items = items.non_archived unless archived.present?
- items = items.personal(current_user) if personal.present?
- items = items.search(name) if name.present?
- items = items.sort(sort)
- items.includes(:namespace).order("namespaces.path, projects.name ASC").page(page)
+ items = by_namespace_id(items)
+ items = by_visibilty_level(items)
+ items = by_with_push(items)
+ items = by_abandoned(items)
+ items = by_last_repository_check_failed(items)
+ items = by_archived(items)
+ items = by_personal(items)
+ items = by_name(items)
+ items = sort(items)
+ items.includes(:namespace).order("namespaces.path, projects.name ASC").page(params[:page])
+ end
+
+ private
+
+ def by_namespace_id(items)
+ params[:namespace_id].present? ? items.in_namespace(params[:namespace_id]) : items
+ end
+
+ def by_visibilty_level(items)
+ params[:visibility_level].present? ? items.where(visibility_level: params[:visibility_level]) : items
+ end
+
+ def by_with_push(items)
+ params[:with_push].present? ? items.with_push : items
+ end
+
+ def by_abandoned(items)
+ params[:abandoned].present? ? items.abandoned : items
+ end
+
+ def by_last_repository_check_failed(items)
+ params[:last_repository_check_failed].present? ? items.where(last_repository_check_failed: true) : items
+ end
+
+ def by_archived(items)
+ if params[:archived] == 'only'
+ items.archived
+ elsif params[:archived].blank?
+ items.non_archived
+ else
+ items
+ end
+ end
+
+ def by_personal(items)
+ params[:personal].present? ? items.personal(current_user) : items
+ end
+
+ def by_name(items)
+ params[:name].present? ? items.search(params[:name]) : items
+ end
+
+ def sort(items)
+ sort = params.fetch(:sort) { 'latest_activity_desc' }
+ items.sort(sort)
end
end
diff --git a/app/finders/groups_finder.rb b/app/finders/groups_finder.rb
index e6fb112e7f2..88d71b0a87b 100644
--- a/app/finders/groups_finder.rb
+++ b/app/finders/groups_finder.rb
@@ -1,3 +1,19 @@
+# GroupsFinder
+#
+# Used to filter Groups by a set of params
+#
+# Arguments:
+# current_user - which user is requesting groups
+# params:
+# owned: boolean
+# parent: Group
+# all_available: boolean (defaults to true)
+#
+# Users with full private access can see all groups. The `owned` and `parent`
+# params can be used to restrict the groups that are returned.
+#
+# Anonymous users will never return any `owned` groups. They will return all
+# public groups instead, even if `all_available` is set to false.
class GroupsFinder < UnionFinder
def initialize(current_user = nil, params = {})
@current_user = current_user
@@ -16,13 +32,13 @@ class GroupsFinder < UnionFinder
attr_reader :current_user, :params
def all_groups
- groups = []
-
- if current_user
- groups << Gitlab::GroupHierarchy.new(groups_for_ancestors, groups_for_descendants).all_groups
- end
- groups << Group.unscoped.public_to_user(current_user)
+ return [owned_groups] if params[:owned]
+ return [Group.all] if current_user&.full_private_access?
+ groups = []
+ groups << Gitlab::GroupHierarchy.new(groups_for_ancestors, groups_for_descendants).all_groups if current_user
+ groups << Group.unscoped.public_to_user(current_user) if include_public_groups?
+ groups << Group.none if groups.empty?
groups
end
@@ -39,4 +55,12 @@ class GroupsFinder < UnionFinder
groups.where(parent: params[:parent])
end
+
+ def owned_groups
+ current_user&.groups || Group.none
+ end
+
+ def include_public_groups?
+ current_user.nil? || params.fetch(:all_available, true)
+ end
end
diff --git a/app/finders/issuable_finder.rb b/app/finders/issuable_finder.rb
index 08a843ada97..7e0d3b5c979 100644
--- a/app/finders/issuable_finder.rb
+++ b/app/finders/issuable_finder.rb
@@ -18,6 +18,7 @@
# sort: string
# non_archived: boolean
# iids: integer[]
+# my_reaction_emoji: string
#
class IssuableFinder
include CreatedAtFilter
@@ -46,6 +47,7 @@ class IssuableFinder
items = by_iids(items)
items = by_milestone(items)
items = by_label(items)
+ items = by_my_reaction_emoji(items)
# Filtering by project HAS TO be the last because we use the project IDs yielded by the issuable query thus far
items = by_project(items)
@@ -371,6 +373,14 @@ class IssuableFinder
items
end
+ def by_my_reaction_emoji(items)
+ if params[:my_reaction_emoji].present? && current_user
+ items = items.awarded(current_user, params[:my_reaction_emoji])
+ end
+
+ items
+ end
+
def by_due_date(items)
if due_date?
if filter_by_no_due_date?
diff --git a/app/finders/projects_finder.rb b/app/finders/projects_finder.rb
index aa80dfc3f37..fa6fea2588a 100644
--- a/app/finders/projects_finder.rb
+++ b/app/finders/projects_finder.rb
@@ -125,9 +125,18 @@ class ProjectsFinder < UnionFinder
end
def by_archived(projects)
- # Back-compatibility with the places where `params[:archived]` can be set explicitly to `false`
- params[:non_archived] = !Gitlab::Utils.to_boolean(params[:archived]) if params.key?(:archived)
-
- params[:non_archived] ? projects.non_archived : projects
+ if params[:non_archived]
+ projects.non_archived
+ elsif params.key?(:archived) # Back-compatibility with the places where `params[:archived]` can be set explicitly to `false`
+ if params[:archived] == 'only'
+ projects.archived
+ elsif Gitlab::Utils.to_boolean(params[:archived])
+ projects
+ else
+ projects.non_archived
+ end
+ else
+ projects
+ end
end
end
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index bcee81bdc15..07775a8b159 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -178,7 +178,7 @@ module ApplicationHelper
end
def edited_time_ago_with_tooltip(object, placement: 'top', html_class: 'time_ago', exclude_author: false)
- return unless object.is_edited?
+ return unless object.edited?
content_tag :small, class: 'edited-text' do
output = content_tag(:span, 'Edited ')
diff --git a/app/helpers/application_settings_helper.rb b/app/helpers/application_settings_helper.rb
index 150188f0b65..3b76da238e0 100644
--- a/app/helpers/application_settings_helper.rb
+++ b/app/helpers/application_settings_helper.rb
@@ -116,6 +116,7 @@ module ApplicationSettingsHelper
:email_author_in_body,
:enabled_git_access_protocol,
:gravatar_enabled,
+ :hashed_storage_enabled,
:help_page_hide_commercial_content,
:help_page_support_url,
:help_page_text,
diff --git a/app/helpers/avatars_helper.rb b/app/helpers/avatars_helper.rb
index 4b51269533c..a4c226a6aad 100644
--- a/app/helpers/avatars_helper.rb
+++ b/app/helpers/avatars_helper.rb
@@ -12,11 +12,18 @@ module AvatarsHelper
avatar_size = options[:size] || 16
user_name = options[:user].try(:name) || options[:user_name]
avatar_url = options[:url] || avatar_icon(options[:user] || options[:user_email], avatar_size)
- data_attributes = { container: 'body' }
+ has_tooltip = options[:has_tooltip].nil? ? true : options[:has_tooltip]
+ data_attributes = {}
+ css_class = %W[avatar s#{avatar_size}].push(*options[:css_class])
+
+ if has_tooltip
+ css_class.push('has-tooltip')
+ data_attributes = { container: 'body' }
+ end
image_tag(
avatar_url,
- class: %W[avatar has-tooltip s#{avatar_size}].push(*options[:css_class]),
+ class: css_class,
alt: "#{user_name}'s avatar",
title: user_name,
data: data_attributes,
diff --git a/app/helpers/button_helper.rb b/app/helpers/button_helper.rb
index bf9ad95b7c2..48cf30a48ab 100644
--- a/app/helpers/button_helper.rb
+++ b/app/helpers/button_helper.rb
@@ -20,6 +20,9 @@ module ButtonHelper
def clipboard_button(data = {})
css_class = data[:class] || 'btn-clipboard btn-transparent'
title = data[:title] || 'Copy to clipboard'
+ button_text = data[:button_text] || ''
+ hide_tooltip = data[:hide_tooltip] || false
+ hide_button_icon = data[:hide_button_icon] || false
# This supports code in app/assets/javascripts/copy_to_clipboard.js that
# works around ClipboardJS limitations to allow the context-specific copy/pasting of plain text or GFM.
@@ -35,17 +38,22 @@ module ButtonHelper
target = data.delete(:target)
data[:clipboard_target] = target if target
- data = { toggle: 'tooltip', placement: 'bottom', container: 'body' }.merge(data)
+ unless hide_tooltip
+ data = { toggle: 'tooltip', placement: 'bottom', container: 'body' }.merge(data)
+ end
- content_tag :button,
- icon('clipboard', 'aria-hidden': 'true'),
+ button_attributes = {
class: "btn #{css_class}",
data: data,
type: :button,
title: title,
- aria: {
- label: title
- }
+ aria: { label: title }
+ }
+
+ content_tag :button, button_attributes do
+ concat(icon('clipboard', 'aria-hidden': 'true')) unless hide_button_icon
+ concat(button_text)
+ end
end
def http_clone_button(project, placement = 'right', append_link: true)
diff --git a/app/helpers/commits_helper.rb b/app/helpers/commits_helper.rb
index 72e26b64e60..9651f9733f9 100644
--- a/app/helpers/commits_helper.rb
+++ b/app/helpers/commits_helper.rb
@@ -114,7 +114,7 @@ module CommitsHelper
end
def commit_signature_badge_classes(additional_classes)
- %w(btn status-box gpg-status-box) + Array(additional_classes)
+ %w(btn gpg-status-box) + Array(additional_classes)
end
protected
diff --git a/app/helpers/events_helper.rb b/app/helpers/events_helper.rb
index 722a65eeb98..b331693c789 100644
--- a/app/helpers/events_helper.rb
+++ b/app/helpers/events_helper.rb
@@ -176,11 +176,12 @@ module EventsHelper
sanitize(
text,
tags: %w(a img gl-emoji b pre code p span),
- attributes: Rails::Html::WhiteListSanitizer.allowed_attributes + ['style', 'data-name', 'data-unicode-version']
+ attributes: Rails::Html::WhiteListSanitizer.allowed_attributes + ['style', 'data-src', 'data-name', 'data-unicode-version']
)
end
def event_commit_title(message)
+ message ||= ''
(message.split("\n").first || "").truncate(70)
rescue
"--broken encoding"
diff --git a/app/helpers/issuables_helper.rb b/app/helpers/issuables_helper.rb
index eba8aed05d3..9e5992bf68f 100644
--- a/app/helpers/issuables_helper.rb
+++ b/app/helpers/issuables_helper.rb
@@ -238,7 +238,7 @@ module IssuablesHelper
end
def updated_at_by(issuable)
- return {} unless issuable.is_edited?
+ return {} unless issuable.edited?
{
updatedAt: issuable.updated_at.to_time.iso8601,
diff --git a/app/helpers/milestones_helper.rb b/app/helpers/milestones_helper.rb
index 86666022a2a..446a59030a6 100644
--- a/app/helpers/milestones_helper.rb
+++ b/app/helpers/milestones_helper.rb
@@ -164,7 +164,7 @@ module MilestonesHelper
def group_milestone_route(milestone, params = {})
params = nil if params.empty?
- if milestone.is_legacy_group_milestone?
+ if milestone.legacy_group_milestone?
group_milestone_path(@group, milestone.safe_title, title: milestone.title, milestone: params)
else
group_milestone_path(@group, milestone.iid, milestone: params)
diff --git a/app/helpers/milestones_routing_helper.rb b/app/helpers/milestones_routing_helper.rb
index 766d5262018..a0b2616f224 100644
--- a/app/helpers/milestones_routing_helper.rb
+++ b/app/helpers/milestones_routing_helper.rb
@@ -1,16 +1,16 @@
module MilestonesRoutingHelper
def milestone_path(milestone, *args)
- if milestone.is_group_milestone?
+ if milestone.group_milestone?
group_milestone_path(milestone.group, milestone, *args)
- elsif milestone.is_project_milestone?
+ elsif milestone.project_milestone?
project_milestone_path(milestone.project, milestone, *args)
end
end
def milestone_url(milestone, *args)
- if milestone.is_group_milestone?
+ if milestone.group_milestone?
group_milestone_url(milestone.group, milestone, *args)
- elsif milestone.is_project_milestone?
+ elsif milestone.project_milestone?
project_milestone_url(milestone.project, milestone, *args)
end
end
diff --git a/app/models/broadcast_message.rb b/app/models/broadcast_message.rb
index 3692bcc680d..fdc5a2adea0 100644
--- a/app/models/broadcast_message.rb
+++ b/app/models/broadcast_message.rb
@@ -19,11 +19,21 @@ class BroadcastMessage < ActiveRecord::Base
after_commit :flush_redis_cache
def self.current
- Rails.cache.fetch(CACHE_KEY) do
- where('ends_at > :now AND starts_at <= :now', now: Time.zone.now)
- .reorder(id: :asc)
- .to_a
- end
+ messages = Rails.cache.fetch(CACHE_KEY) { current_and_future_messages.to_a }
+
+ return messages if messages.empty?
+
+ now_or_future = messages.select(&:now_or_future?)
+
+ # If there are cached entries but none are to be displayed we'll purge the
+ # cache so we don't keep running this code all the time.
+ Rails.cache.delete(CACHE_KEY) if now_or_future.empty?
+
+ now_or_future.select(&:now?)
+ end
+
+ def self.current_and_future_messages
+ where('ends_at > :now', now: Time.zone.now).reorder(id: :asc)
end
def active?
@@ -38,6 +48,18 @@ class BroadcastMessage < ActiveRecord::Base
ends_at < Time.zone.now
end
+ def now?
+ (starts_at..ends_at).cover?(Time.zone.now)
+ end
+
+ def future?
+ starts_at > Time.zone.now
+ end
+
+ def now_or_future?
+ now? || future?
+ end
+
def flush_redis_cache
Rails.cache.delete(CACHE_KEY)
end
diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb
index 4692fb5644a..095192e9894 100644
--- a/app/models/ci/build.rb
+++ b/app/models/ci/build.rb
@@ -46,7 +46,10 @@ module Ci
before_save :ensure_token
before_destroy { unscoped_project }
- after_create :execute_hooks
+ after_create do |build|
+ run_after_commit { BuildHooksWorker.perform_async(build.id) }
+ end
+
after_commit :update_project_statistics_after_save, on: [:create, :update]
after_commit :update_project_statistics, on: :destroy
diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb
index ea7331cb27f..2d40f8012a3 100644
--- a/app/models/ci/pipeline.rb
+++ b/app/models/ci/pipeline.rb
@@ -393,7 +393,8 @@ module Ci
def predefined_variables
[
{ key: 'CI_PIPELINE_ID', value: id.to_s, public: true },
- { key: 'CI_CONFIG_PATH', value: ci_yaml_file_path, public: true }
+ { key: 'CI_CONFIG_PATH', value: ci_yaml_file_path, public: true },
+ { key: 'CI_PIPELINE_SOURCE', value: source.to_s, public: true }
]
end
diff --git a/app/models/ci/pipeline_schedule.rb b/app/models/ci/pipeline_schedule.rb
index 085eeeae157..e7e02587759 100644
--- a/app/models/ci/pipeline_schedule.rb
+++ b/app/models/ci/pipeline_schedule.rb
@@ -9,7 +9,7 @@ module Ci
belongs_to :owner, class_name: 'User'
has_one :last_pipeline, -> { order(id: :desc) }, class_name: 'Ci::Pipeline'
has_many :pipelines
- has_many :variables, class_name: 'Ci::PipelineScheduleVariable'
+ has_many :variables, class_name: 'Ci::PipelineScheduleVariable', validate: false
validates :cron, unless: :importing?, cron: true, presence: { unless: :importing? }
validates :cron_timezone, cron_timezone: true, presence: { unless: :importing? }
diff --git a/app/models/ci/pipeline_schedule_variable.rb b/app/models/ci/pipeline_schedule_variable.rb
index 1ff177616e8..ee5b8733fac 100644
--- a/app/models/ci/pipeline_schedule_variable.rb
+++ b/app/models/ci/pipeline_schedule_variable.rb
@@ -4,5 +4,7 @@ module Ci
include HasVariable
belongs_to :pipeline_schedule
+
+ validates :key, uniqueness: { scope: :pipeline_schedule_id }
end
end
diff --git a/app/models/ci/runner.rb b/app/models/ci/runner.rb
index c6d23898560..906a76ec560 100644
--- a/app/models/ci/runner.rb
+++ b/app/models/ci/runner.rb
@@ -142,7 +142,7 @@ module Ci
expire: RUNNER_QUEUE_EXPIRY_TIME, overwrite: false)
end
- def is_runner_queue_value_latest?(value)
+ def runner_queue_value_latest?(value)
ensure_runner_queue_value == value if value.present?
end
diff --git a/app/models/ci/stage.rb b/app/models/ci/stage.rb
index 59570924c8d..754c37518b3 100644
--- a/app/models/ci/stage.rb
+++ b/app/models/ci/stage.rb
@@ -1,11 +1,70 @@
module Ci
class Stage < ActiveRecord::Base
extend Ci::Model
+ include Importable
+ include HasStatus
+ include Gitlab::OptimisticLocking
+
+ enum status: HasStatus::STATUSES_ENUM
belongs_to :project
belongs_to :pipeline
- has_many :statuses, class_name: 'CommitStatus', foreign_key: :commit_id
- has_many :builds, foreign_key: :commit_id
+ has_many :statuses, class_name: 'CommitStatus', foreign_key: :stage_id
+ has_many :builds, foreign_key: :stage_id
+
+ validates :project, presence: true, unless: :importing?
+ validates :pipeline, presence: true, unless: :importing?
+ validates :name, presence: true, unless: :importing?
+
+ after_initialize do |stage|
+ self.status = DEFAULT_STATUS if self.status.nil?
+ end
+
+ state_machine :status, initial: :created do
+ event :enqueue do
+ transition created: :pending
+ transition [:success, :failed, :canceled, :skipped] => :running
+ end
+
+ event :run do
+ transition any - [:running] => :running
+ end
+
+ event :skip do
+ transition any - [:skipped] => :skipped
+ end
+
+ event :drop do
+ transition any - [:failed] => :failed
+ end
+
+ event :succeed do
+ transition any - [:success] => :success
+ end
+
+ event :cancel do
+ transition any - [:canceled] => :canceled
+ end
+
+ event :block do
+ transition any - [:manual] => :manual
+ end
+ end
+
+ def update_status
+ retry_optimistic_lock(self) do
+ case statuses.latest.status
+ when 'pending' then enqueue
+ when 'running' then run
+ when 'success' then succeed
+ when 'failed' then drop
+ when 'canceled' then cancel
+ when 'manual' then block
+ when 'skipped' then skip
+ else skip
+ end
+ end
+ end
end
end
diff --git a/app/models/commit_status.rb b/app/models/commit_status.rb
index 07cec63b939..842c6e5cb50 100644
--- a/app/models/commit_status.rb
+++ b/app/models/commit_status.rb
@@ -39,14 +39,14 @@ class CommitStatus < ActiveRecord::Base
scope :after_stage, -> (index) { where('stage_idx > ?', index) }
state_machine :status do
- event :enqueue do
- transition [:created, :skipped, :manual] => :pending
- end
-
event :process do
transition [:skipped, :manual] => :created
end
+ event :enqueue do
+ transition [:created, :skipped, :manual] => :pending
+ end
+
event :run do
transition pending: :running
end
@@ -91,6 +91,7 @@ class CommitStatus < ActiveRecord::Base
end
end
+ StageUpdateWorker.perform_async(commit_status.stage_id)
ExpireJobCacheWorker.perform_async(commit_status.id)
end
end
diff --git a/app/models/concerns/awardable.rb b/app/models/concerns/awardable.rb
index f4f9b037957..9adc309a22b 100644
--- a/app/models/concerns/awardable.rb
+++ b/app/models/concerns/awardable.rb
@@ -11,6 +11,21 @@ module Awardable
end
module ClassMethods
+ def awarded(user, name)
+ sql = <<~EOL
+ EXISTS (
+ SELECT TRUE
+ FROM award_emoji
+ WHERE user_id = :user_id AND
+ name = :name AND
+ awardable_type = :awardable_type AND
+ awardable_id = #{self.arel_table.name}.id
+ )
+ EOL
+
+ where(sql, user_id: user.id, name: name, awardable_type: self.name)
+ end
+
def order_upvotes_desc
order_votes_desc(AwardEmoji::UPVOTE_NAME)
end
diff --git a/app/models/concerns/editable.rb b/app/models/concerns/editable.rb
index 28623d257a6..c0a3099f676 100644
--- a/app/models/concerns/editable.rb
+++ b/app/models/concerns/editable.rb
@@ -1,7 +1,7 @@
module Editable
extend ActiveSupport::Concern
- def is_edited?
+ def edited?
last_edited_at.present? && last_edited_at != created_at
end
diff --git a/app/models/concerns/has_status.rb b/app/models/concerns/has_status.rb
index 32af5566135..3803e18a96e 100644
--- a/app/models/concerns/has_status.rb
+++ b/app/models/concerns/has_status.rb
@@ -8,6 +8,8 @@ module HasStatus
ACTIVE_STATUSES = %w[pending running].freeze
COMPLETED_STATUSES = %w[success failed canceled skipped].freeze
ORDERED_STATUSES = %w[failed pending running manual canceled success skipped created].freeze
+ STATUSES_ENUM = { created: 0, pending: 1, running: 2, success: 3,
+ failed: 4, canceled: 5, skipped: 6, manual: 7 }.freeze
class_methods do
def status_sql
diff --git a/app/models/concerns/milestoneish.rb b/app/models/concerns/milestoneish.rb
index f0998465822..710fc1ed647 100644
--- a/app/models/concerns/milestoneish.rb
+++ b/app/models/concerns/milestoneish.rb
@@ -70,19 +70,19 @@ module Milestoneish
due_date && due_date.past?
end
- def is_group_milestone?
+ def group_milestone?
false
end
- def is_project_milestone?
+ def project_milestone?
false
end
- def is_legacy_group_milestone?
+ def legacy_group_milestone?
false
end
- def is_dashboard_milestone?
+ def dashboard_milestone?
false
end
diff --git a/app/models/concerns/protected_ref.rb b/app/models/concerns/protected_ref.rb
index ef95d6b0f98..454374121f3 100644
--- a/app/models/concerns/protected_ref.rb
+++ b/app/models/concerns/protected_ref.rb
@@ -23,7 +23,7 @@ module ProtectedRef
# If we don't `protected_branch` or `protected_tag` would be empty and
# `project` cannot be delegated to it, which in turn would cause validations
# to fail.
- has_many :"#{type}_access_levels", dependent: :destroy, inverse_of: self.model_name.singular # rubocop:disable Cop/ActiveRecordDependent
+ has_many :"#{type}_access_levels", inverse_of: self.model_name.singular # rubocop:disable Cop/ActiveRecordDependent
validates :"#{type}_access_levels", length: { is: 1, message: "are restricted to a single instance per #{self.model_name.human}." }
diff --git a/app/models/concerns/storage/legacy_project.rb b/app/models/concerns/storage/legacy_project.rb
deleted file mode 100644
index 815db712285..00000000000
--- a/app/models/concerns/storage/legacy_project.rb
+++ /dev/null
@@ -1,76 +0,0 @@
-module Storage
- module LegacyProject
- extend ActiveSupport::Concern
-
- def disk_path
- full_path
- end
-
- def ensure_storage_path_exist
- gitlab_shell.add_namespace(repository_storage_path, namespace.full_path)
- end
-
- def rename_repo
- path_was = previous_changes['path'].first
- old_path_with_namespace = File.join(namespace.full_path, path_was)
- new_path_with_namespace = File.join(namespace.full_path, path)
-
- Rails.logger.error "Attempting to rename #{old_path_with_namespace} -> #{new_path_with_namespace}"
-
- if has_container_registry_tags?
- Rails.logger.error "Project #{old_path_with_namespace} cannot be renamed because container registry tags are present!"
-
- # we currently doesn't support renaming repository if it contains images in container registry
- raise StandardError.new('Project cannot be renamed, because images are present in its container registry')
- end
-
- expire_caches_before_rename(old_path_with_namespace)
-
- if gitlab_shell.mv_repository(repository_storage_path, old_path_with_namespace, new_path_with_namespace)
- # If repository moved successfully we need to send update instructions to users.
- # However we cannot allow rollback since we moved repository
- # So we basically we mute exceptions in next actions
- begin
- gitlab_shell.mv_repository(repository_storage_path, "#{old_path_with_namespace}.wiki", "#{new_path_with_namespace}.wiki")
- send_move_instructions(old_path_with_namespace)
- expires_full_path_cache
-
- @old_path_with_namespace = old_path_with_namespace
-
- SystemHooksService.new.execute_hooks_for(self, :rename)
-
- @repository = nil
- rescue => e
- Rails.logger.error "Exception renaming #{old_path_with_namespace} -> #{new_path_with_namespace}: #{e}"
- # Returning false does not rollback after_* transaction but gives
- # us information about failing some of tasks
- false
- end
- else
- Rails.logger.error "Repository could not be renamed: #{old_path_with_namespace} -> #{new_path_with_namespace}"
-
- # if we cannot move namespace directory we should rollback
- # db changes in order to prevent out of sync between db and fs
- raise StandardError.new('repository cannot be renamed')
- end
-
- Gitlab::AppLogger.info "Project was renamed: #{old_path_with_namespace} -> #{new_path_with_namespace}"
-
- Gitlab::UploadsTransfer.new.rename_project(path_was, path, namespace.full_path)
- Gitlab::PagesTransfer.new.rename_project(path_was, path, namespace.full_path)
- end
-
- def create_repository(force: false)
- # Forked import is handled asynchronously
- return if forked? && !force
-
- if gitlab_shell.add_repository(repository_storage_path, path_with_namespace)
- repository.after_create
- true
- else
- errors.add(:base, 'Failed to create repository via gitlab-shell')
- false
- end
- end
- end
-end
diff --git a/app/models/dashboard_milestone.rb b/app/models/dashboard_milestone.rb
index fac7c5e5c85..86eb4ec76fc 100644
--- a/app/models/dashboard_milestone.rb
+++ b/app/models/dashboard_milestone.rb
@@ -3,7 +3,7 @@ class DashboardMilestone < GlobalMilestone
{ authorized_only: true }
end
- def is_dashboard_milestone?
+ def dashboard_milestone?
true
end
end
diff --git a/app/models/deployment.rb b/app/models/deployment.rb
index 056c49e7162..7bcded5b5e1 100644
--- a/app/models/deployment.rb
+++ b/app/models/deployment.rb
@@ -49,7 +49,7 @@ class Deployment < ActiveRecord::Base
# created before then could have a `sha` referring to a commit that no
# longer exists in the repository, so just ignore those.
begin
- project.repository.is_ancestor?(commit.id, sha)
+ project.repository.ancestor?(commit.id, sha)
rescue Rugged::OdbError
false
end
diff --git a/app/models/event.rb b/app/models/event.rb
index f2a560a6b56..996768a267b 100644
--- a/app/models/event.rb
+++ b/app/models/event.rb
@@ -83,6 +83,10 @@ class Event < ActiveRecord::Base
self.inheritance_column = 'action'
class << self
+ def model_name
+ ActiveModel::Name.new(self, nil, 'event')
+ end
+
def find_sti_class(action)
if action.to_i == PUSHED
PushEvent
@@ -402,7 +406,7 @@ class Event < ActiveRecord::Base
def body?
if push?
- push_with_commits? || rm_ref?
+ push_with_commits?
elsif note?
true
else
@@ -438,6 +442,12 @@ class Event < ActiveRecord::Base
EventForMigration.create!(new_attributes)
end
+ def to_partial_path
+ # We are intentionally using `Event` rather than `self.class` so that
+ # subclasses also use the `Event` implementation.
+ Event._to_partial_path
+ end
+
private
def recent_update?
diff --git a/app/models/group.rb b/app/models/group.rb
index 2816a68257c..cb3ee032f69 100644
--- a/app/models/group.rb
+++ b/app/models/group.rb
@@ -206,9 +206,9 @@ class Group < Namespace
SystemHooksService.new
end
- def refresh_members_authorized_projects
+ def refresh_members_authorized_projects(blocking: true)
UserProjectAccessChangedService.new(user_ids_for_project_authorizations)
- .execute
+ .execute(blocking: blocking)
end
def user_ids_for_project_authorizations
diff --git a/app/models/group_milestone.rb b/app/models/group_milestone.rb
index 65249bd7bfc..98135ee3c8b 100644
--- a/app/models/group_milestone.rb
+++ b/app/models/group_milestone.rb
@@ -17,7 +17,7 @@ class GroupMilestone < GlobalMilestone
{ group_id: group.id }
end
- def is_legacy_group_milestone?
+ def legacy_group_milestone?
true
end
end
diff --git a/app/models/issue.rb b/app/models/issue.rb
index 1c948c8957e..b9aa937d2f9 100644
--- a/app/models/issue.rb
+++ b/app/models/issue.rb
@@ -9,11 +9,8 @@ class Issue < ActiveRecord::Base
include Spammable
include FasterCacheKeys
include RelativePositioning
- include IgnorableColumn
include CreatedAtFilterable
- ignore_column :position
-
DueDateStruct = Struct.new(:title, :name).freeze
NoDueDate = DueDateStruct.new('No Due Date', '0').freeze
AnyDueDate = DueDateStruct.new('Any Due Date', '').freeze
@@ -53,7 +50,10 @@ class Issue < ActiveRecord::Base
scope :preload_associations, -> { preload(:labels, project: :namespace) }
+ scope :public_only, -> { where(confidential: false) }
+
after_save :expire_etag_cache
+ after_commit :update_project_counter_caches, on: :destroy
attr_spammable :title, spam_title: true
attr_spammable :description, spam_description: true
@@ -269,6 +269,10 @@ class Issue < ActiveRecord::Base
end
end
+ def update_project_counter_caches
+ Projects::OpenIssuesCountService.new(project).refresh_cache
+ end
+
private
# Returns `true` if the given User can read the current Issue.
diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb
index ac08dc0ee1f..7f73de67625 100644
--- a/app/models/merge_request.rb
+++ b/app/models/merge_request.rb
@@ -7,7 +7,6 @@ class MergeRequest < ActiveRecord::Base
include IgnorableColumn
include CreatedAtFilterable
- ignore_column :position
ignore_column :locked_at
belongs_to :target_project, class_name: "Project"
@@ -32,6 +31,7 @@ class MergeRequest < ActiveRecord::Base
after_create :ensure_merge_request_diff, unless: :importing?
after_update :reload_diff_if_branch_changed
+ after_commit :update_project_counter_caches, on: :destroy
# When this attribute is true some MR validation is ignored
# It allows us to close or modify broken merge requests
@@ -241,6 +241,14 @@ class MergeRequest < ActiveRecord::Base
end
end
+ # Calls `MergeWorker` to proceed with the merge process and
+ # updates `merge_jid` with the MergeWorker#jid.
+ # This helps tracking enqueued and ongoing merge jobs.
+ def merge_async(user_id, params)
+ jid = MergeWorker.perform_async(id, user_id, params)
+ update_column(:merge_jid, jid)
+ end
+
def first_commit
merge_request_diff ? merge_request_diff.first_commit : compare_commits.first
end
@@ -384,9 +392,7 @@ class MergeRequest < ActiveRecord::Base
end
def merge_ongoing?
- return false unless merge_jid
-
- Gitlab::SidekiqStatus.num_running([merge_jid]) > 0
+ !!merge_jid && !merged?
end
def closed_without_fork?
@@ -683,9 +689,8 @@ class MergeRequest < ActiveRecord::Base
if !include_description && closes_issues_references.present?
message << "Closes #{closes_issues_references.to_sentence}"
end
-
message << "#{description}" if include_description && description.present?
- message << "See merge request #{to_reference}"
+ message << "See merge request #{to_reference(full: true)}"
message.join("\n\n")
end
@@ -820,7 +825,7 @@ class MergeRequest < ActiveRecord::Base
lock_mr
yield
ensure
- unlock_mr if locked?
+ unlock_mr
end
end
@@ -937,6 +942,10 @@ class MergeRequest < ActiveRecord::Base
true
end
+ def update_project_counter_caches
+ Projects::OpenMergeRequestsCountService.new(target_project).refresh_cache
+ end
+
private
def write_ref
diff --git a/app/models/milestone.rb b/app/models/milestone.rb
index 01e0d0155a3..a3070a12b7c 100644
--- a/app/models/milestone.rb
+++ b/app/models/milestone.rb
@@ -163,7 +163,7 @@ class Milestone < ActiveRecord::Base
# Milestone.first.to_reference(same_namespace_project) # => "gitlab-ce%1"
#
def to_reference(from_project = nil, format: :iid, full: false)
- return if is_group_milestone? && format != :name
+ return if group_milestone? && format != :name
format_reference = milestone_format_reference(format)
reference = "#{self.class.reference_prefix}#{format_reference}"
@@ -207,11 +207,11 @@ class Milestone < ActiveRecord::Base
group || project
end
- def is_group_milestone?
+ def group_milestone?
group_id.present?
end
- def is_project_milestone?
+ def project_milestone?
project_id.present?
end
diff --git a/app/models/network/graph.rb b/app/models/network/graph.rb
index 0e5acb22d50..3845e485413 100644
--- a/app/models/network/graph.rb
+++ b/app/models/network/graph.rb
@@ -152,14 +152,14 @@ module Network
end
def find_free_parent_space(range, space_base, space_step, space_default)
- if is_overlap?(range, space_default)
+ if overlap?(range, space_default)
find_free_space(range, space_step, space_base, space_default)
else
space_default
end
end
- def is_overlap?(range, overlap_space)
+ def overlap?(range, overlap_space)
range.each do |i|
if i != range.first &&
i != range.last &&
diff --git a/app/models/notification_recipient.rb b/app/models/notification_recipient.rb
index dc862565a71..183e098d819 100644
--- a/app/models/notification_recipient.rb
+++ b/app/models/notification_recipient.rb
@@ -27,46 +27,45 @@ class NotificationRecipient
@notification_setting ||= find_notification_setting
end
- def raw_notification_level
- notification_setting&.level&.to_sym
- end
-
def notification_level
- # custom is treated the same as watch if it's enabled - otherwise it's
- # set to :custom, meaning to send exactly when our type is :participating
- # or :mention.
- @notification_level ||=
- case raw_notification_level
- when :custom
- if @custom_action && notification_setting&.event_enabled?(@custom_action)
- :watch
- else
- :custom
- end
- else
- raw_notification_level
- end
+ @notification_level ||= notification_setting&.level&.to_sym
end
def notifiable?
return false unless has_access?
return false if own_activity?
- return true if @type == :subscription
-
- return false if notification_level.nil? || notification_level == :disabled
-
- return %i[participating mention].include?(@type) if notification_level == :custom
+ # even users with :disabled notifications receive manual subscriptions
+ return !unsubscribed? if @type == :subscription
- return false if %i[watch participating].include?(notification_level) && excluded_watcher_action?
-
- return false unless NotificationSetting.levels[notification_level] <= NotificationSetting.levels[@type]
+ return false unless suitable_notification_level?
+ # check this last because it's expensive
+ # nobody should receive notifications if they've specifically unsubscribed
return false if unsubscribed?
true
end
+ def suitable_notification_level?
+ case notification_level
+ when :disabled, nil
+ false
+ when :custom
+ custom_enabled? || %i[participating mention].include?(@type)
+ when :watch, :participating
+ !excluded_watcher_action?
+ when :mention
+ @type == :mention
+ else
+ false
+ end
+ end
+
+ def custom_enabled?
+ @custom_action && notification_setting&.event_enabled?(@custom_action)
+ end
+
def unsubscribed?
return false unless @target
return false unless @target.respond_to?(:subscriptions)
@@ -98,7 +97,7 @@ class NotificationRecipient
def excluded_watcher_action?
return false unless @custom_action
- return false if raw_notification_level == :custom
+ return false if notification_level == :custom
NotificationSetting::EXCLUDED_WATCHER_EVENTS.include?(@custom_action)
end
diff --git a/app/models/project.rb b/app/models/project.rb
index be248bc99e1..d5324ceac31 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -17,7 +17,6 @@ class Project < ActiveRecord::Base
include ProjectFeaturesCompatibility
include SelectForProjectAuthorization
include Routable
- include Storage::LegacyProject
extend Gitlab::ConfigHelper
@@ -25,6 +24,7 @@ class Project < ActiveRecord::Base
NUMBER_OF_PERMITTED_BOARDS = 1
UNKNOWN_IMPORT_URL = 'http://unknown.git'.freeze
+ LATEST_STORAGE_VERSION = 1
cache_markdown_field :description, pipeline: :description
@@ -32,6 +32,8 @@ class Project < ActiveRecord::Base
:merge_requests_enabled?, :issues_enabled?, to: :project_feature,
allow_nil: true
+ delegate :base_dir, :disk_path, :ensure_storage_path_exists, to: :storage
+
default_value_for :archived, false
default_value_for :visibility_level, gitlab_config_features.visibility_level
default_value_for :container_registry_enabled, gitlab_config_features.container_registry
@@ -44,32 +46,24 @@ class Project < ActiveRecord::Base
default_value_for :snippets_enabled, gitlab_config_features.snippets
default_value_for :only_allow_merge_if_all_discussions_are_resolved, false
- after_create :ensure_storage_path_exist
- after_create :create_project_feature, unless: :project_feature
- after_save :update_project_statistics, if: :namespace_id_changed?
+ add_authentication_token_field :runners_token
+ before_save :ensure_runners_token
- # set last_activity_at to the same as created_at
+ after_save :update_project_statistics, if: :namespace_id_changed?
+ after_create :create_project_feature, unless: :project_feature
after_create :set_last_activity_at
- def set_last_activity_at
- update_column(:last_activity_at, self.created_at)
- end
-
after_create :set_last_repository_updated_at
- def set_last_repository_updated_at
- update_column(:last_repository_updated_at, self.created_at)
- end
+ after_update :update_forks_visibility_level
before_destroy :remove_private_deploy_keys
after_destroy -> { run_after_commit { remove_pages } }
- # update visibility_level of forks
- after_update :update_forks_visibility_level
-
after_validation :check_pending_delete
- # Legacy Storage specific hooks
-
- after_save :ensure_storage_path_exist, if: :namespace_id_changed?
+ # Storage specific hooks
+ after_initialize :use_hashed_storage
+ after_create :ensure_storage_path_exists
+ after_save :ensure_storage_path_exists, if: :namespace_id_changed?
acts_as_taggable
@@ -238,9 +232,6 @@ class Project < ActiveRecord::Base
presence: true,
inclusion: { in: ->(_object) { Gitlab.config.repositories.storages.keys } }
- add_authentication_token_field :runners_token
- before_save :ensure_runners_token
-
mount_uploader :avatar, AvatarUploader
has_many :uploads, as: :model, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent
@@ -256,6 +247,7 @@ class Project < ActiveRecord::Base
scope :joined, ->(user) { where('namespace_id != ?', user.namespace_id) }
scope :starred_by, ->(user) { joins(:users_star_projects).where('users_star_projects.user_id': user.id) }
scope :visible_to_user, ->(user) { where(id: user.authorized_projects.select(:id).reorder(nil)) }
+ scope :archived, -> { where(archived: true) }
scope :non_archived, -> { where(archived: false) }
scope :for_milestones, ->(ids) { joins(:milestones).where('milestones.id' => ids).distinct }
scope :with_push, -> { joins(:events).where('events.action = ?', Event::PUSHED) }
@@ -487,6 +479,10 @@ class Project < ActiveRecord::Base
@repository ||= Repository.new(full_path, self, disk_path: disk_path)
end
+ def reload_repository!
+ @repository = nil
+ end
+
def container_registry_url
if Gitlab.config.registry.enabled
"#{Gitlab.config.registry.host_port}/#{full_path.downcase}"
@@ -1004,12 +1000,25 @@ class Project < ActiveRecord::Base
end
end
+ def create_repository(force: false)
+ # Forked import is handled asynchronously
+ return if forked? && !force
+
+ if gitlab_shell.add_repository(repository_storage_path, disk_path)
+ repository.after_create
+ true
+ else
+ errors.add(:base, 'Failed to create repository via gitlab-shell')
+ false
+ end
+ end
+
def hook_attrs(backward: true)
attrs = {
name: name,
description: description,
web_url: web_url,
- avatar_url: avatar_url,
+ avatar_url: avatar_url(only_path: false),
git_ssh_url: ssh_url_to_repo,
git_http_url: http_url_to_repo,
namespace: namespace.name,
@@ -1086,6 +1095,7 @@ class Project < ActiveRecord::Base
!!repository.exists?
end
+ # update visibility_level of forks
def update_forks_visibility_level
return unless visibility_level < visibility_level_was
@@ -1158,7 +1168,11 @@ class Project < ActiveRecord::Base
end
def open_issues_count
- issues.opened.count
+ Projects::OpenIssuesCountService.new(self).count
+ end
+
+ def open_merge_requests_count
+ Projects::OpenMergeRequestsCountService.new(self).count
end
def visibility_level_allowed_as_fork?(level = self.visibility_level)
@@ -1213,7 +1227,8 @@ class Project < ActiveRecord::Base
end
def pages_path
- File.join(Settings.pages.path, disk_path)
+ # TODO: when we migrate Pages to work with new storage types, change here to use disk_path
+ File.join(Settings.pages.path, full_path)
end
def public_pages_path
@@ -1252,6 +1267,50 @@ class Project < ActiveRecord::Base
end
end
+ def rename_repo
+ new_full_path = build_full_path
+
+ Rails.logger.error "Attempting to rename #{full_path_was} -> #{new_full_path}"
+
+ if has_container_registry_tags?
+ Rails.logger.error "Project #{full_path_was} cannot be renamed because container registry tags are present!"
+
+ # we currently doesn't support renaming repository if it contains images in container registry
+ raise StandardError.new('Project cannot be renamed, because images are present in its container registry')
+ end
+
+ expire_caches_before_rename(full_path_was)
+
+ if storage.rename_repo
+ Gitlab::AppLogger.info "Project was renamed: #{full_path_was} -> #{new_full_path}"
+ rename_repo_notify!
+ after_rename_repo
+ else
+ Rails.logger.error "Repository could not be renamed: #{full_path_was} -> #{new_full_path}"
+
+ # if we cannot move namespace directory we should rollback
+ # db changes in order to prevent out of sync between db and fs
+ raise StandardError.new('repository cannot be renamed')
+ end
+ end
+
+ def rename_repo_notify!
+ send_move_instructions(full_path_was)
+ expires_full_path_cache
+
+ self.old_path_with_namespace = full_path_was
+ SystemHooksService.new.execute_hooks_for(self, :rename)
+
+ reload_repository!
+ end
+
+ def after_rename_repo
+ path_before_change = previous_changes['path'].first
+
+ Gitlab::UploadsTransfer.new.rename_project(path_before_change, self.path, namespace.full_path)
+ Gitlab::PagesTransfer.new.rename_project(path_before_change, self.path, namespace.full_path)
+ end
+
def running_or_pending_build_count(force: false)
Rails.cache.fetch(['projects', id, 'running_or_pending_build_count'], force: force) do
builds.running_or_pending.count(:all)
@@ -1410,6 +1469,10 @@ class Project < ActiveRecord::Base
end
end
+ def full_path_was
+ File.join(namespace.full_path, previous_changes['path'].first)
+ end
+
alias_method :name_with_namespace, :full_name
alias_method :human_name, :full_name
# @deprecated cannot remove yet because it has an index with its name in elasticsearch
@@ -1419,8 +1482,36 @@ class Project < ActiveRecord::Base
Projects::ForksCountService.new(self).count
end
+ def legacy_storage?
+ self.storage_version.nil?
+ end
+
private
+ def storage
+ @storage ||=
+ if self.storage_version && self.storage_version >= 1
+ Storage::HashedProject.new(self)
+ else
+ Storage::LegacyProject.new(self)
+ end
+ end
+
+ def use_hashed_storage
+ if self.new_record? && current_application_settings.hashed_storage_enabled
+ self.storage_version = LATEST_STORAGE_VERSION
+ end
+ end
+
+ # set last_activity_at to the same as created_at
+ def set_last_activity_at
+ update_column(:last_activity_at, self.created_at)
+ end
+
+ def set_last_repository_updated_at
+ update_column(:last_repository_updated_at, self.created_at)
+ end
+
def cross_namespace_reference?(from)
case from
when Project
diff --git a/app/models/project_services/chat_notification_service.rb b/app/models/project_services/chat_notification_service.rb
index 7b15a5dd04d..818cfb01b14 100644
--- a/app/models/project_services/chat_notification_service.rb
+++ b/app/models/project_services/chat_notification_service.rb
@@ -101,9 +101,9 @@ class ChatNotificationService < Service
when "push", "tag_push"
ChatMessage::PushMessage.new(data)
when "issue"
- ChatMessage::IssueMessage.new(data) unless is_update?(data)
+ ChatMessage::IssueMessage.new(data) unless update?(data)
when "merge_request"
- ChatMessage::MergeMessage.new(data) unless is_update?(data)
+ ChatMessage::MergeMessage.new(data) unless update?(data)
when "note"
ChatMessage::NoteMessage.new(data)
when "pipeline"
@@ -136,7 +136,7 @@ class ChatNotificationService < Service
project.web_url
end
- def is_update?(data)
+ def update?(data)
data[:object_attributes][:action] == 'update'
end
diff --git a/app/models/project_services/hipchat_service.rb b/app/models/project_services/hipchat_service.rb
index f422e0ea036..976d85246a8 100644
--- a/app/models/project_services/hipchat_service.rb
+++ b/app/models/project_services/hipchat_service.rb
@@ -85,9 +85,9 @@ class HipchatService < Service
when "push", "tag_push"
create_push_message(data)
when "issue"
- create_issue_message(data) unless is_update?(data)
+ create_issue_message(data) unless update?(data)
when "merge_request"
- create_merge_request_message(data) unless is_update?(data)
+ create_merge_request_message(data) unless update?(data)
when "note"
create_note_message(data)
when "pipeline"
@@ -282,7 +282,7 @@ class HipchatService < Service
"<a href=\"#{project_url}\">#{project_name}</a>"
end
- def is_update?(data)
+ def update?(data)
data[:object_attributes][:action] == 'update'
end
diff --git a/app/models/project_services/kubernetes_service.rb b/app/models/project_services/kubernetes_service.rb
index dee99bbb859..8ba07173c74 100644
--- a/app/models/project_services/kubernetes_service.rb
+++ b/app/models/project_services/kubernetes_service.rb
@@ -24,6 +24,8 @@ class KubernetesService < DeploymentService
validates :token
end
+ before_validation :enforce_namespace_to_lower_case
+
validates :namespace,
allow_blank: true,
length: 1..63,
@@ -207,4 +209,8 @@ class KubernetesService < DeploymentService
max_session_time: current_application_settings.terminal_max_session_time
}
end
+
+ def enforce_namespace_to_lower_case
+ self.namespace = self.namespace&.downcase
+ end
end
diff --git a/app/models/repository.rb b/app/models/repository.rb
index c1e4fcf94a4..cb7aba89020 100644
--- a/app/models/repository.rb
+++ b/app/models/repository.rb
@@ -206,12 +206,18 @@ class Repository
end
def branch_exists?(branch_name)
- branch_names.include?(branch_name)
+ return false unless raw_repository
+
+ @branch_exists_memo ||= Hash.new do |hash, key|
+ hash[key] = raw_repository.branch_exists?(key)
+ end
+
+ @branch_exists_memo[branch_name]
end
def ref_exists?(ref)
- rugged.references.exist?(ref)
- rescue Rugged::ReferenceError
+ !!raw_repository&.ref_exists?(ref)
+ rescue ArgumentError
false
end
@@ -266,6 +272,7 @@ class Repository
def expire_branches_cache
expire_method_caches(%i(branch_names branch_count))
@local_branches = nil
+ @branch_exists_memo = nil
end
def expire_statistics_caches
@@ -937,7 +944,7 @@ class Repository
if branch_commit
same_head = branch_commit.id == root_ref_commit.id
- !same_head && is_ancestor?(branch_commit.id, root_ref_commit.id)
+ !same_head && ancestor?(branch_commit.id, root_ref_commit.id)
else
nil
end
@@ -951,12 +958,12 @@ class Repository
nil
end
- def is_ancestor?(ancestor_id, descendant_id)
+ def ancestor?(ancestor_id, descendant_id)
return false if ancestor_id.nil? || descendant_id.nil?
Gitlab::GitalyClient.migrate(:is_ancestor) do |is_enabled|
if is_enabled
- raw_repository.is_ancestor?(ancestor_id, descendant_id)
+ raw_repository.ancestor?(ancestor_id, descendant_id)
else
rugged_is_ancestor?(ancestor_id, descendant_id)
end
@@ -1185,7 +1192,7 @@ class Repository
end
def initialize_raw_repository
- Gitlab::Git::Repository.new(project.repository_storage, disk_path + '.git')
+ Gitlab::Git::Repository.new(project.repository_storage, disk_path + '.git', Gitlab::GlRepository.gl_repository(project, false))
end
def circuit_breaker
diff --git a/app/models/storage/hashed_project.rb b/app/models/storage/hashed_project.rb
new file mode 100644
index 00000000000..fae1b64961a
--- /dev/null
+++ b/app/models/storage/hashed_project.rb
@@ -0,0 +1,42 @@
+module Storage
+ class HashedProject
+ attr_accessor :project
+ delegate :gitlab_shell, :repository_storage_path, to: :project
+
+ ROOT_PATH_PREFIX = '@hashed'.freeze
+
+ def initialize(project)
+ @project = project
+ end
+
+ # Base directory
+ #
+ # @return [String] directory where repository is stored
+ def base_dir
+ "#{ROOT_PATH_PREFIX}/#{disk_hash[0..1]}/#{disk_hash[2..3]}" if disk_hash
+ end
+
+ # Disk path is used to build repository and project's wiki path on disk
+ #
+ # @return [String] combination of base_dir and the repository own name without `.git` or `.wiki.git` extensions
+ def disk_path
+ "#{base_dir}/#{disk_hash}" if disk_hash
+ end
+
+ def ensure_storage_path_exists
+ gitlab_shell.add_namespace(repository_storage_path, base_dir)
+ end
+
+ def rename_repo
+ true
+ end
+
+ private
+
+ # Generates the hash for the project path and name on disk
+ # If you need to refer to the repository on disk, use the `#disk_path`
+ def disk_hash
+ @disk_hash ||= Digest::SHA2.hexdigest(project.id.to_s) if project.id
+ end
+ end
+end
diff --git a/app/models/storage/legacy_project.rb b/app/models/storage/legacy_project.rb
new file mode 100644
index 00000000000..9d9e5e1d352
--- /dev/null
+++ b/app/models/storage/legacy_project.rb
@@ -0,0 +1,51 @@
+module Storage
+ class LegacyProject
+ attr_accessor :project
+ delegate :namespace, :gitlab_shell, :repository_storage_path, to: :project
+
+ def initialize(project)
+ @project = project
+ end
+
+ # Base directory
+ #
+ # @return [String] directory where repository is stored
+ def base_dir
+ namespace.full_path
+ end
+
+ # Disk path is used to build repository and project's wiki path on disk
+ #
+ # @return [String] combination of base_dir and the repository own name without `.git` or `.wiki.git` extensions
+ def disk_path
+ project.full_path
+ end
+
+ def ensure_storage_path_exists
+ return unless namespace
+
+ gitlab_shell.add_namespace(repository_storage_path, base_dir)
+ end
+
+ def rename_repo
+ new_full_path = project.build_full_path
+
+ if gitlab_shell.mv_repository(repository_storage_path, project.full_path_was, new_full_path)
+ # If repository moved successfully we need to send update instructions to users.
+ # However we cannot allow rollback since we moved repository
+ # So we basically we mute exceptions in next actions
+ begin
+ gitlab_shell.mv_repository(repository_storage_path, "#{project.full_path_was}.wiki", "#{new_full_path}.wiki")
+ return true
+ rescue => e
+ Rails.logger.error "Exception renaming #{project.full_path_was} -> #{new_full_path}: #{e}"
+ # Returning false does not rollback after_* transaction but gives
+ # us information about failing some of tasks
+ return false
+ end
+ end
+
+ false
+ end
+ end
+end
diff --git a/app/models/user.rb b/app/models/user.rb
index 02c3ab6654b..fbd08bc4d0a 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -837,7 +837,12 @@ class User < ActiveRecord::Base
create_namespace!(path: username, name: username) unless namespace
if username_changed?
- namespace.update_attributes(path: username, name: username)
+ unless namespace.update_attributes(path: username, name: username)
+ namespace.errors.each do |attribute, message|
+ self.errors.add(:"namespace_#{attribute}", message)
+ end
+ raise ActiveRecord::RecordInvalid.new(namespace)
+ end
end
end
diff --git a/app/policies/group_policy.rb b/app/policies/group_policy.rb
index 6defab75fce..8ada661e571 100644
--- a/app/policies/group_policy.rb
+++ b/app/policies/group_policy.rb
@@ -13,6 +13,8 @@ class GroupPolicy < BasePolicy
condition(:master) { access_level >= GroupMember::MASTER }
condition(:reporter) { access_level >= GroupMember::REPORTER }
+ condition(:nested_groups_supported, scope: :global) { Group.supports_nested_groups? }
+
condition(:has_projects) do
GroupProjectsFinder.new(group: @subject, current_user: @user).execute.any?
end
@@ -42,7 +44,7 @@ class GroupPolicy < BasePolicy
enable :change_visibility_level
end
- rule { owner & can_create_group }.enable :create_subgroup
+ rule { owner & can_create_group & nested_groups_supported }.enable :create_subgroup
rule { public_group | logged_in_viewable }.enable :view_globally
diff --git a/app/policies/project_policy.rb b/app/policies/project_policy.rb
index 0133091db57..a925fac7d3e 100644
--- a/app/policies/project_policy.rb
+++ b/app/policies/project_policy.rb
@@ -17,13 +17,13 @@ class ProjectPolicy < BasePolicy
desc "Project has public builds enabled"
condition(:public_builds, scope: :subject) { project.public_builds? }
- # For guest access we use #is_team_member? so we can use
+ # For guest access we use #team_member? so we can use
# project.members, which gets cached in subject scope.
# This is safe because team_access_level is guaranteed
# by ProjectAuthorization's validation to be at minimum
# GUEST
desc "User has guest access"
- condition(:guest) { is_team_member? }
+ condition(:guest) { team_member? }
desc "User has reporter access"
condition(:reporter) { team_access_level >= Gitlab::Access::REPORTER }
@@ -293,7 +293,7 @@ class ProjectPolicy < BasePolicy
private
- def is_team_member?
+ def team_member?
return false if @user.nil?
greedy_load_subject = false
diff --git a/app/services/akismet_service.rb b/app/services/akismet_service.rb
index 59153cbbc0a..7b5482b3cd1 100644
--- a/app/services/akismet_service.rb
+++ b/app/services/akismet_service.rb
@@ -7,7 +7,7 @@ class AkismetService
@options = options
end
- def is_spam?
+ def spam?
return false unless akismet_enabled?
params = {
diff --git a/app/services/ci/create_pipeline_service.rb b/app/services/ci/create_pipeline_service.rb
index 884b681ff81..de2cd7e87be 100644
--- a/app/services/ci/create_pipeline_service.rb
+++ b/app/services/ci/create_pipeline_service.rb
@@ -15,7 +15,7 @@ module Ci
pipeline_schedule: schedule
)
- result = validate(current_user || trigger_request.trigger.owner,
+ result = validate(current_user,
ignore_skip_ci: ignore_skip_ci,
save_on_errors: save_on_errors)
@@ -176,9 +176,14 @@ module Ci
end
def error(message, save: false)
- pipeline.errors.add(:base, message)
- pipeline.drop if save
- pipeline
+ pipeline.tap do
+ pipeline.errors.add(:base, message)
+
+ if save
+ pipeline.drop
+ update_merge_requests_head_pipeline
+ end
+ end
end
def pipeline_created_counter
diff --git a/app/services/commits/create_service.rb b/app/services/commits/create_service.rb
index c58f04a252b..dbd0b9ef43a 100644
--- a/app/services/commits/create_service.rb
+++ b/app/services/commits/create_service.rb
@@ -17,7 +17,7 @@ module Commits
new_commit = create_commit!
success(result: new_commit)
- rescue ValidationError, ChangeError, Gitlab::Git::Index::IndexError, Repository::CommitError, GitHooksService::PreReceiveError => ex
+ rescue ValidationError, ChangeError, Gitlab::Git::Index::IndexError, Repository::CommitError, Gitlab::Git::HooksService::PreReceiveError => ex
error(ex.message)
end
diff --git a/app/services/concerns/users/new_user_notifier.rb b/app/services/concerns/users/new_user_notifier.rb
new file mode 100644
index 00000000000..231693ce7a9
--- /dev/null
+++ b/app/services/concerns/users/new_user_notifier.rb
@@ -0,0 +1,9 @@
+module Users
+ module NewUserNotifier
+ def notify_new_user(user, reset_token)
+ log_info("User \"#{user.name}\" (#{user.email}) was created")
+ notification_service.new_user(user, reset_token) if reset_token
+ system_hook_service.execute_hooks_for(user, :create)
+ end
+ end
+end
diff --git a/app/services/create_branch_service.rb b/app/services/create_branch_service.rb
index 673ed02f952..0ba6a0ac6b5 100644
--- a/app/services/create_branch_service.rb
+++ b/app/services/create_branch_service.rb
@@ -14,7 +14,7 @@ class CreateBranchService < BaseService
else
error('Invalid reference name')
end
- rescue GitHooksService::PreReceiveError => ex
+ rescue Gitlab::Git::HooksService::PreReceiveError => ex
error(ex.message)
end
diff --git a/app/services/delete_branch_service.rb b/app/services/delete_branch_service.rb
index 64b3c0118fb..1f059c31944 100644
--- a/app/services/delete_branch_service.rb
+++ b/app/services/delete_branch_service.rb
@@ -16,7 +16,7 @@ class DeleteBranchService < BaseService
else
error('Failed to remove branch')
end
- rescue GitHooksService::PreReceiveError => ex
+ rescue Gitlab::Git::HooksService::PreReceiveError => ex
error(ex.message)
end
diff --git a/app/services/git_hooks_service.rb b/app/services/git_hooks_service.rb
deleted file mode 100644
index eab65d09299..00000000000
--- a/app/services/git_hooks_service.rb
+++ /dev/null
@@ -1,32 +0,0 @@
-class GitHooksService
- PreReceiveError = Class.new(StandardError)
-
- attr_accessor :oldrev, :newrev, :ref
-
- def execute(user, project, oldrev, newrev, ref)
- @project = project
- @user = Gitlab::GlId.gl_id(user)
- @oldrev = oldrev
- @newrev = newrev
- @ref = ref
-
- %w(pre-receive update).each do |hook_name|
- status, message = run_hook(hook_name)
-
- unless status
- raise PreReceiveError, message
- end
- end
-
- yield(self).tap do
- run_hook('post-receive')
- end
- end
-
- private
-
- def run_hook(name)
- hook = Gitlab::Git::Hook.new(name, @project)
- hook.trigger(@user, oldrev, newrev, ref)
- end
-end
diff --git a/app/services/git_operation_service.rb b/app/services/git_operation_service.rb
index 545ca0742e4..6b7a56e6922 100644
--- a/app/services/git_operation_service.rb
+++ b/app/services/git_operation_service.rb
@@ -1,8 +1,10 @@
class GitOperationService
- attr_reader :user, :repository
+ attr_reader :committer, :repository
+
+ def initialize(committer, new_repository)
+ committer = Gitlab::Git::Committer.from_user(committer) if committer.is_a?(User)
+ @committer = committer
- def initialize(new_user, new_repository)
- @user = new_user
@repository = new_repository
end
@@ -118,9 +120,9 @@ class GitOperationService
end
def with_hooks(ref, newrev, oldrev)
- GitHooksService.new.execute(
- user,
- repository.project,
+ Gitlab::Git::HooksService.new.execute(
+ committer,
+ repository,
oldrev,
newrev,
ref) do |service|
diff --git a/app/services/git_push_service.rb b/app/services/git_push_service.rb
index e81a56672e2..bb61136e33b 100644
--- a/app/services/git_push_service.rb
+++ b/app/services/git_push_service.rb
@@ -30,7 +30,7 @@ class GitPushService < BaseService
@project.repository.after_create_branch
# Re-find the pushed commits.
- if is_default_branch?
+ if default_branch?
# Initial push to the default branch. Take the full history of that branch as "newly pushed".
process_default_branch
else
@@ -50,7 +50,7 @@ class GitPushService < BaseService
# Update the bare repositories info/attributes file using the contents of the default branches
# .gitattributes file
- update_gitattributes if is_default_branch?
+ update_gitattributes if default_branch?
end
execute_related_hooks
@@ -66,7 +66,7 @@ class GitPushService < BaseService
end
def update_caches
- if is_default_branch?
+ if default_branch?
if push_to_new_branch?
# If this is the initial push into the default branch, the file type caches
# will already be reset as a result of `Project#change_head`.
@@ -108,7 +108,7 @@ class GitPushService < BaseService
# Schedules processing of commit messages.
def process_commit_messages
- default = is_default_branch?
+ default = default_branch?
@push_commits.last(PROCESS_COMMIT_LIMIT).each do |commit|
if commit.matches_cross_reference_regex?
@@ -202,7 +202,7 @@ class GitPushService < BaseService
Gitlab::Git.branch_ref?(params[:ref])
end
- def is_default_branch?
+ def default_branch?
Gitlab::Git.branch_ref?(params[:ref]) &&
(Gitlab::Git.ref_name(params[:ref]) == project.default_branch || project.default_branch.nil?)
end
diff --git a/app/services/groups/create_service.rb b/app/services/groups/create_service.rb
index c4e9b8fd8e0..c7c27621085 100644
--- a/app/services/groups/create_service.rb
+++ b/app/services/groups/create_service.rb
@@ -13,9 +13,9 @@ module Groups
return @group
end
- if @group.parent && !can?(current_user, :admin_group, @group.parent)
+ if @group.parent && !can?(current_user, :create_subgroup, @group.parent)
@group.parent = nil
- @group.errors.add(:parent_id, 'manage access required to create subgroup')
+ @group.errors.add(:parent_id, 'You don’t have permission to create a subgroup in this group.')
return @group
end
diff --git a/app/services/groups/destroy_service.rb b/app/services/groups/destroy_service.rb
index f565612a89d..e3f9d9ee95d 100644
--- a/app/services/groups/destroy_service.rb
+++ b/app/services/groups/destroy_service.rb
@@ -13,7 +13,7 @@ module Groups
# Execute the destruction of the models immediately to ensure atomic cleanup.
# Skip repository removal because we remove directory with namespace
# that contain all these repositories
- ::Projects::DestroyService.new(project, current_user, skip_repo: true).execute
+ ::Projects::DestroyService.new(project, current_user, skip_repo: project.legacy_storage?).execute
end
group.children.each do |group|
diff --git a/app/services/groups/nested_create_service.rb b/app/services/groups/nested_create_service.rb
new file mode 100644
index 00000000000..d6f08fc3cce
--- /dev/null
+++ b/app/services/groups/nested_create_service.rb
@@ -0,0 +1,49 @@
+module Groups
+ class NestedCreateService < Groups::BaseService
+ attr_reader :group_path
+
+ def initialize(user, params)
+ @current_user, @params = user, params.dup
+
+ @group_path = @params.delete(:group_path)
+ end
+
+ def execute
+ return nil unless group_path
+
+ if group = Group.find_by_full_path(group_path)
+ return group
+ end
+
+ if group_path.include?('/') && !Group.supports_nested_groups?
+ raise 'Nested groups are not supported on MySQL'
+ end
+
+ create_group_path
+ end
+
+ private
+
+ def create_group_path
+ group_path_segments = group_path.split('/')
+
+ last_group = nil
+ partial_path_segments = []
+ while subgroup_name = group_path_segments.shift
+ partial_path_segments << subgroup_name
+ partial_path = partial_path_segments.join('/')
+
+ new_params = params.reverse_merge(
+ path: subgroup_name,
+ name: subgroup_name,
+ parent: last_group
+ )
+ new_params[:visibility_level] ||= Gitlab::CurrentSettings.current_application_settings.default_group_visibility
+
+ last_group = Group.find_by_full_path(partial_path) || Groups::CreateService.new(current_user, new_params).execute
+ end
+
+ last_group
+ end
+ end
+end
diff --git a/app/services/issuable_base_service.rb b/app/services/issuable_base_service.rb
index 4a4f2b91182..1486db046b5 100644
--- a/app/services/issuable_base_service.rb
+++ b/app/services/issuable_base_service.rb
@@ -192,6 +192,8 @@ class IssuableBaseService < BaseService
def after_create(issuable)
# To be overridden by subclasses
+
+ issuable.update_project_counter_caches
end
def before_update(issuable)
@@ -200,6 +202,8 @@ class IssuableBaseService < BaseService
def after_update(issuable)
# To be overridden by subclasses
+
+ issuable.update_project_counter_caches
end
def update(issuable)
diff --git a/app/services/issues/create_service.rb b/app/services/issues/create_service.rb
index 234fcbede03..0307634c0b6 100644
--- a/app/services/issues/create_service.rb
+++ b/app/services/issues/create_service.rb
@@ -27,6 +27,8 @@ module Issues
todo_service.new_issue(issuable, current_user)
user_agent_detail_service.create
resolve_discussions_with_issue(issuable)
+
+ super
end
def resolve_discussions_with_issue(issue)
diff --git a/app/services/merge_requests/create_from_issue_service.rb b/app/services/merge_requests/create_from_issue_service.rb
index 738cedbaed7..da39a380451 100644
--- a/app/services/merge_requests/create_from_issue_service.rb
+++ b/app/services/merge_requests/create_from_issue_service.rb
@@ -3,6 +3,8 @@ module MergeRequests
def execute
return error('Invalid issue iid') unless issue_iid.present? && issue.present?
+ params[:label_ids] = issue.label_ids if issue.label_ids.any?
+
result = CreateBranchService.new(project, current_user).execute(branch_name, ref)
return result if result[:status] == :error
@@ -43,7 +45,8 @@ module MergeRequests
{
source_project_id: project.id,
source_branch: branch_name,
- target_project_id: project.id
+ target_project_id: project.id,
+ milestone_id: issue.milestone_id
}
end
diff --git a/app/services/merge_requests/create_service.rb b/app/services/merge_requests/create_service.rb
index 194413bf321..3d53fe0646b 100644
--- a/app/services/merge_requests/create_service.rb
+++ b/app/services/merge_requests/create_service.rb
@@ -28,6 +28,8 @@ module MergeRequests
todo_service.new_merge_request(issuable, current_user)
issuable.cache_merge_request_closes_issues!(current_user)
update_merge_requests_head_pipeline(issuable)
+
+ super
end
private
diff --git a/app/services/merge_requests/merge_service.rb b/app/services/merge_requests/merge_service.rb
index bc846e07f24..b2b6c5627fb 100644
--- a/app/services/merge_requests/merge_service.rb
+++ b/app/services/merge_requests/merge_service.rb
@@ -26,10 +26,12 @@ module MergeRequests
merge_request.in_locked_state do
if commit
after_merge
+ clean_merge_jid
success
end
end
rescue MergeError => e
+ clean_merge_jid
log_merge_error(e.message, save_message_on_model: true)
end
@@ -49,7 +51,7 @@ module MergeRequests
raise MergeError, 'Conflicts detected during merge' unless commit_id
merge_request.update(merge_commit_sha: commit_id)
- rescue GitHooksService::PreReceiveError => e
+ rescue Gitlab::Git::HooksService::PreReceiveError => e
raise MergeError, e.message
rescue StandardError => e
raise MergeError, "Something went wrong during merge: #{e.message}"
@@ -70,6 +72,10 @@ module MergeRequests
end
end
+ def clean_merge_jid
+ merge_request.update_column(:merge_jid, nil)
+ end
+
def branch_deletion_user
@merge_request.force_remove_source_branch? ? @merge_request.author : current_user
end
diff --git a/app/services/merge_requests/merge_when_pipeline_succeeds_service.rb b/app/services/merge_requests/merge_when_pipeline_succeeds_service.rb
index aed5287940e..850deb0ac7a 100644
--- a/app/services/merge_requests/merge_when_pipeline_succeeds_service.rb
+++ b/app/services/merge_requests/merge_when_pipeline_succeeds_service.rb
@@ -30,7 +30,7 @@ module MergeRequests
next
end
- MergeWorker.perform_async(merge_request.id, merge_request.merge_user_id, merge_request.merge_params)
+ merge_request.merge_async(merge_request.merge_user_id, merge_request.merge_params)
end
end
diff --git a/app/services/merge_requests/update_service.rb b/app/services/merge_requests/update_service.rb
index 75a65aecd1a..2832d893e95 100644
--- a/app/services/merge_requests/update_service.rb
+++ b/app/services/merge_requests/update_service.rb
@@ -83,7 +83,7 @@ module MergeRequests
if merge_request.head_pipeline && merge_request.head_pipeline.active?
MergeRequests::MergeWhenPipelineSucceedsService.new(project, current_user).execute(merge_request)
else
- MergeWorker.perform_async(merge_request.id, current_user.id, {})
+ merge_request.merge_async(current_user.id, {})
end
end
diff --git a/app/services/milestones/close_service.rb b/app/services/milestones/close_service.rb
index 776ec4b287b..5b06c4b601d 100644
--- a/app/services/milestones/close_service.rb
+++ b/app/services/milestones/close_service.rb
@@ -1,7 +1,7 @@
module Milestones
class CloseService < Milestones::BaseService
def execute(milestone)
- if milestone.close && milestone.is_project_milestone?
+ if milestone.close && milestone.project_milestone?
event_service.close_milestone(milestone, current_user)
end
diff --git a/app/services/milestones/create_service.rb b/app/services/milestones/create_service.rb
index aef3124c7e3..ed2e833d833 100644
--- a/app/services/milestones/create_service.rb
+++ b/app/services/milestones/create_service.rb
@@ -3,7 +3,7 @@ module Milestones
def execute
milestone = parent.milestones.new(params)
- if milestone.save && milestone.is_project_milestone?
+ if milestone.save && milestone.project_milestone?
event_service.open_milestone(milestone, current_user)
end
diff --git a/app/services/milestones/destroy_service.rb b/app/services/milestones/destroy_service.rb
index 600ebcfbecb..b18651476a8 100644
--- a/app/services/milestones/destroy_service.rb
+++ b/app/services/milestones/destroy_service.rb
@@ -1,7 +1,7 @@
module Milestones
class DestroyService < Milestones::BaseService
def execute(milestone)
- return unless milestone.is_project_milestone?
+ return unless milestone.project_milestone?
Milestone.transaction do
update_params = { milestone: nil }
diff --git a/app/services/milestones/reopen_service.rb b/app/services/milestones/reopen_service.rb
index 5b8b682caaf..3efb33157c5 100644
--- a/app/services/milestones/reopen_service.rb
+++ b/app/services/milestones/reopen_service.rb
@@ -1,7 +1,7 @@
module Milestones
class ReopenService < Milestones::BaseService
def execute(milestone)
- if milestone.activate && milestone.is_project_milestone?
+ if milestone.activate && milestone.project_milestone?
event_service.reopen_milestone(milestone, current_user)
end
diff --git a/app/services/notification_recipient_service.rb b/app/services/notification_recipient_service.rb
index 21c9c314a2a..c9f07c140f7 100644
--- a/app/services/notification_recipient_service.rb
+++ b/app/services/notification_recipient_service.rb
@@ -95,7 +95,7 @@ module NotificationRecipientService
def add_participants(user)
return unless target.respond_to?(:participants)
- self << [target.participants(user), :watch]
+ self << [target.participants(user), :participating]
end
# Get project/group users with CUSTOM notification level
diff --git a/app/services/projects/count_service.rb b/app/services/projects/count_service.rb
new file mode 100644
index 00000000000..5e633c37bf8
--- /dev/null
+++ b/app/services/projects/count_service.rb
@@ -0,0 +1,43 @@
+module Projects
+ # Base class for the various service classes that count project data (e.g.
+ # issues or forks).
+ class CountService
+ def initialize(project)
+ @project = project
+ end
+
+ def relation_for_count
+ raise(
+ NotImplementedError,
+ '"relation_for_count" must be implemented and return an ActiveRecord::Relation'
+ )
+ end
+
+ def count
+ Rails.cache.fetch(cache_key) { uncached_count }
+ end
+
+ def refresh_cache
+ Rails.cache.write(cache_key, uncached_count)
+ end
+
+ def uncached_count
+ relation_for_count.count
+ end
+
+ def delete_cache
+ Rails.cache.delete(cache_key)
+ end
+
+ def cache_key_name
+ raise(
+ NotImplementedError,
+ '"cache_key_name" must be implemented and return a String'
+ )
+ end
+
+ def cache_key
+ ['projects', @project.id, cache_key_name]
+ end
+ end
+end
diff --git a/app/services/projects/create_service.rb b/app/services/projects/create_service.rb
index 48578b6d9e5..71533da31b1 100644
--- a/app/services/projects/create_service.rb
+++ b/app/services/projects/create_service.rb
@@ -44,6 +44,8 @@ module Projects
@project.namespace_id = current_user.namespace_id
end
+ yield(@project) if block_given?
+
@project.creator = current_user
if forked_from_project_id
@@ -99,12 +101,19 @@ module Projects
event_service.create_project(@project, current_user)
system_hook_service.execute_hooks_for(@project, :create)
- unless @project.group || @project.gitlab_project_import?
- owners = [current_user, @project.namespace.owner].compact.uniq
- @project.add_master(owners, current_user: current_user)
- end
+ setup_authorizations
+ end
- @project.group&.refresh_members_authorized_projects
+ # Refresh the current user's authorizations inline (so they can access the
+ # project immediately after this request completes), and any other affected
+ # users in the background
+ def setup_authorizations
+ if @project.group
+ @project.group.refresh_members_authorized_projects(blocking: false)
+ current_user.refresh_authorized_projects
+ else
+ @project.add_master(@project.namespace.owner, current_user: current_user)
+ end
end
def skip_wiki?
diff --git a/app/services/projects/forks_count_service.rb b/app/services/projects/forks_count_service.rb
index e2e2b1da91d..3a0fa84b868 100644
--- a/app/services/projects/forks_count_service.rb
+++ b/app/services/projects/forks_count_service.rb
@@ -1,30 +1,12 @@
module Projects
# Service class for getting and caching the number of forks of a project.
- class ForksCountService
- def initialize(project)
- @project = project
+ class ForksCountService < CountService
+ def relation_for_count
+ @project.forks
end
- def count
- Rails.cache.fetch(cache_key) { uncached_count }
- end
-
- def refresh_cache
- Rails.cache.write(cache_key, uncached_count)
- end
-
- def delete_cache
- Rails.cache.delete(cache_key)
- end
-
- private
-
- def uncached_count
- @project.forks.count
- end
-
- def cache_key
- ['projects', @project.id, 'forks_count']
+ def cache_key_name
+ 'forks_count'
end
end
end
diff --git a/app/services/projects/housekeeping_service.rb b/app/services/projects/housekeeping_service.rb
index 4b8946f8ee2..d66ef676088 100644
--- a/app/services/projects/housekeeping_service.rb
+++ b/app/services/projects/housekeeping_service.rb
@@ -9,7 +9,8 @@ module Projects
class HousekeepingService < BaseService
include Gitlab::CurrentSettings
- LEASE_TIMEOUT = 3600
+ # Timeout set to 24h
+ LEASE_TIMEOUT = 86400
class LeaseTaken < StandardError
def to_s
diff --git a/app/services/projects/open_issues_count_service.rb b/app/services/projects/open_issues_count_service.rb
new file mode 100644
index 00000000000..3c0d186a73c
--- /dev/null
+++ b/app/services/projects/open_issues_count_service.rb
@@ -0,0 +1,15 @@
+module Projects
+ # Service class for counting and caching the number of open issues of a
+ # project.
+ class OpenIssuesCountService < CountService
+ def relation_for_count
+ # We don't include confidential issues in this number since this would
+ # expose the number of confidential issues to non project members.
+ @project.issues.opened.public_only
+ end
+
+ def cache_key_name
+ 'open_issues_count'
+ end
+ end
+end
diff --git a/app/services/projects/open_merge_requests_count_service.rb b/app/services/projects/open_merge_requests_count_service.rb
new file mode 100644
index 00000000000..2a90f78b90d
--- /dev/null
+++ b/app/services/projects/open_merge_requests_count_service.rb
@@ -0,0 +1,13 @@
+module Projects
+ # Service class for counting and caching the number of open merge requests of
+ # a project.
+ class OpenMergeRequestsCountService < CountService
+ def relation_for_count
+ @project.merge_requests.opened
+ end
+
+ def cache_key_name
+ 'open_merge_requests_count'
+ end
+ end
+end
diff --git a/app/services/spam_service.rb b/app/services/spam_service.rb
index 3e65b7d31a3..73ea3018fbd 100644
--- a/app/services/spam_service.rb
+++ b/app/services/spam_service.rb
@@ -45,7 +45,7 @@ class SpamService
def check(api)
return false unless request && check_for_spam?
- return false unless akismet.is_spam?
+ return false unless akismet.spam?
create_spam_log(api)
true
diff --git a/app/services/system_note_service.rb b/app/services/system_note_service.rb
index 1763f64a4e4..1f66a2668f9 100644
--- a/app/services/system_note_service.rb
+++ b/app/services/system_note_service.rb
@@ -142,7 +142,7 @@ module SystemNoteService
#
# Returns the created Note object
def change_milestone(noteable, project, author, milestone)
- format = milestone&.is_group_milestone? ? :name : :iid
+ format = milestone&.group_milestone? ? :name : :iid
body = milestone.nil? ? 'removed milestone' : "changed milestone to #{milestone.to_reference(project, format: format)}"
create_note(NoteSummary.new(noteable, project, author, body, action: 'milestone'))
diff --git a/app/services/tags/create_service.rb b/app/services/tags/create_service.rb
index 674792f6138..b3f4a72d6fe 100644
--- a/app/services/tags/create_service.rb
+++ b/app/services/tags/create_service.rb
@@ -13,7 +13,7 @@ module Tags
new_tag = repository.add_tag(current_user, tag_name, target, message)
rescue Rugged::TagError
return error("Tag #{tag_name} already exists")
- rescue GitHooksService::PreReceiveError => ex
+ rescue Gitlab::Git::HooksService::PreReceiveError => ex
return error(ex.message)
end
diff --git a/app/services/tags/destroy_service.rb b/app/services/tags/destroy_service.rb
index a368f4f5b61..d3d46064729 100644
--- a/app/services/tags/destroy_service.rb
+++ b/app/services/tags/destroy_service.rb
@@ -21,7 +21,7 @@ module Tags
else
error('Failed to remove tag')
end
- rescue GitHooksService::PreReceiveError => ex
+ rescue Gitlab::Git::HooksService::PreReceiveError => ex
error(ex.message)
end
diff --git a/app/services/test_hooks/system_service.rb b/app/services/test_hooks/system_service.rb
index 76c3c19bd74..67552edefc9 100644
--- a/app/services/test_hooks/system_service.rb
+++ b/app/services/test_hooks/system_service.rb
@@ -2,47 +2,16 @@ module TestHooks
class SystemService < TestHooks::BaseService
private
- def project
- @project ||= begin
- project = Project.first
-
- throw(:validation_error, 'Ensure that at least one project exists.') unless project
-
- project
- end
- end
-
def push_events_data
- if project.empty_repo?
- throw(:validation_error, "Ensure project \"#{project.human_name}\" has commits.")
- end
-
- Gitlab::DataBuilder::Push.build_sample(project, current_user)
+ Gitlab::DataBuilder::Push.sample_data
end
def tag_push_events_data
- if project.repository.tags.empty?
- throw(:validation_error, "Ensure project \"#{project.human_name}\" has tags.")
- end
-
- Gitlab::DataBuilder::Push.build_sample(project, current_user)
+ Gitlab::DataBuilder::Push.sample_data
end
def repository_update_events_data
- commit = project.commit
- ref = "#{Gitlab::Git::BRANCH_REF_PREFIX}#{project.default_branch}"
-
- unless commit
- throw(:validation_error, "Ensure project \"#{project.human_name}\" has commits.")
- end
-
- change = Gitlab::DataBuilder::Repository.single_change(
- commit.parent_id || Gitlab::Git::BLANK_SHA,
- commit.id,
- ref
- )
-
- Gitlab::DataBuilder::Repository.update(project, current_user, [change], [ref])
+ Gitlab::DataBuilder::Repository.sample_data
end
end
end
diff --git a/app/services/user_project_access_changed_service.rb b/app/services/user_project_access_changed_service.rb
index d7a6804ee88..8630e572624 100644
--- a/app/services/user_project_access_changed_service.rb
+++ b/app/services/user_project_access_changed_service.rb
@@ -3,7 +3,13 @@ class UserProjectAccessChangedService
@user_ids = Array.wrap(user_ids)
end
- def execute
- AuthorizedProjectsWorker.bulk_perform_and_wait(@user_ids.map { |id| [id] })
+ def execute(blocking: true)
+ bulk_args = @user_ids.map { |id| [id] }
+
+ if blocking
+ AuthorizedProjectsWorker.bulk_perform_and_wait(bulk_args)
+ else
+ AuthorizedProjectsWorker.bulk_perform_async(bulk_args)
+ end
end
end
diff --git a/app/services/users/create_service.rb b/app/services/users/create_service.rb
index 74abc017cea..c8a3c461d60 100644
--- a/app/services/users/create_service.rb
+++ b/app/services/users/create_service.rb
@@ -1,5 +1,7 @@
module Users
class CreateService < BaseService
+ include NewUserNotifier
+
def initialize(current_user, params = {})
@current_user = current_user
@params = params.dup
@@ -10,11 +12,7 @@ module Users
@reset_token = user.generate_reset_token if user.recently_sent_password_reset?
- if user.save
- log_info("User \"#{user.name}\" (#{user.email}) was created")
- notification_service.new_user(user, @reset_token) if @reset_token
- system_hook_service.execute_hooks_for(user, :create)
- end
+ notify_new_user(user, @reset_token) if user.save
user
end
diff --git a/app/services/users/destroy_service.rb b/app/services/users/destroy_service.rb
index 9d7237c2fbb..8e20de8dfa5 100644
--- a/app/services/users/destroy_service.rb
+++ b/app/services/users/destroy_service.rb
@@ -35,16 +35,18 @@ module Users
Groups::DestroyService.new(group, current_user).execute
end
+ namespace = user.namespace
+ namespace.prepare_for_destroy
+
user.personal_projects.each do |project|
# Skip repository removal because we remove directory with namespace
# that contain all this repositories
- ::Projects::DestroyService.new(project, current_user, skip_repo: true).execute
+ ::Projects::DestroyService.new(project, current_user, skip_repo: project.legacy_storage?).execute
end
MigrateToGhostUserService.new(user).execute unless options[:hard_delete]
# Destroy the namespace after destroying the user since certain methods may depend on the namespace existing
- namespace = user.namespace
user_data = user.destroy
namespace.really_destroy!
diff --git a/app/services/users/update_service.rb b/app/services/users/update_service.rb
index dfbd6016c3f..2f9855273dc 100644
--- a/app/services/users/update_service.rb
+++ b/app/services/users/update_service.rb
@@ -1,5 +1,7 @@
module Users
class UpdateService < BaseService
+ include NewUserNotifier
+
def initialize(user, params = {})
@user = user
@params = params.dup
@@ -10,7 +12,11 @@ module Users
assign_attributes(&block)
+ user_exists = @user.persisted?
+
if @user.save(validate: validate)
+ notify_new_user(@user, nil) unless user_exists
+
success
else
error(@user.errors.full_messages.uniq.join('. '))
diff --git a/app/services/validate_new_branch_service.rb b/app/services/validate_new_branch_service.rb
index d232e85cd33..7d1ed768ee8 100644
--- a/app/services/validate_new_branch_service.rb
+++ b/app/services/validate_new_branch_service.rb
@@ -13,7 +13,7 @@ class ValidateNewBranchService < BaseService
end
success
- rescue GitHooksService::PreReceiveError => ex
+ rescue Gitlab::Git::HooksService::PreReceiveError => ex
error(ex.message)
end
end
diff --git a/app/views/admin/application_settings/_form.html.haml b/app/views/admin/application_settings/_form.html.haml
index 8bf6556079b..959af5c0d13 100644
--- a/app/views/admin/application_settings/_form.html.haml
+++ b/app/views/admin/application_settings/_form.html.haml
@@ -362,7 +362,9 @@
%fieldset
%legend Background Jobs
%p
- These settings require a restart to take effect.
+ These settings require a
+ = link_to 'restart', help_page_path('administration/restart_gitlab')
+ to take effect.
.form-group
.col-sm-offset-2.col-sm-10
.checkbox
@@ -491,6 +493,16 @@
%fieldset
%legend Repository Storage
.form-group
+ .col-sm-offset-2.col-sm-10
+ .checkbox
+ = f.label :hashed_storage_enabled do
+ = f.check_box :hashed_storage_enabled
+ Create new projects using hashed storage paths
+ .help-block
+ Enable immutable, hash-based paths and repository names to store repositories on disk. This prevents
+ repositories from having to be moved or renamed when the Project URL changes and may improve disk I/O performance.
+ %em (EXPERIMENTAL)
+ .form-group
= f.label :repository_storages, 'Storage paths for new projects', class: 'control-label col-sm-2'
.col-sm-10
= f.select :repository_storages, repository_storages_options_for_select, {include_hidden: false}, multiple: true, class: 'form-control'
@@ -499,6 +511,7 @@
= succeed "." do
= link_to "repository storages documentation", help_page_path("administration/repository_storages")
+
%fieldset
%legend Repository Checks
.form-group
diff --git a/app/views/admin/dashboard/_head.html.haml b/app/views/admin/dashboard/_head.html.haml
index dff549f502c..c2151710884 100644
--- a/app/views/admin/dashboard/_head.html.haml
+++ b/app/views/admin/dashboard/_head.html.haml
@@ -31,3 +31,7 @@
= link_to admin_cohorts_path, title: 'Cohorts' do
%span
Cohorts
+ = nav_link(controller: :conversational_development_index) do
+ = link_to admin_conversational_development_index_path, title: 'ConvDev Index' do
+ %span
+ ConvDev Index
diff --git a/app/views/admin/logs/show.html.haml b/app/views/admin/logs/show.html.haml
index 487f1cf5c4f..ee87f25a225 100644
--- a/app/views/admin/logs/show.html.haml
+++ b/app/views/admin/logs/show.html.haml
@@ -1,25 +1,21 @@
- @no_container = true
- page_title "Logs"
-- loggers = [Gitlab::GitLogger, Gitlab::AppLogger,
- Gitlab::EnvironmentLogger, Gitlab::SidekiqLogger,
- Gitlab::RepositoryCheckLogger]
= render 'admin/monitoring/head'
%div{ class: container_class }
%ul.nav-links.log-tabs
- - loggers.each do |klass|
- %li{ class: active_when(klass == Gitlab::GitLogger) }>
- = link_to klass::file_name, "##{klass::file_name_noext}",
- 'data-toggle' => 'tab'
+ - @loggers.each do |klass|
+ %li{ class: active_when(klass == @loggers.first) }>
+ = link_to klass.file_name, "##{klass.file_name_noext}", data: { toggle: 'tab' }
.row-content-block
To prevent performance issues admin logs output the last 2000 lines
.tab-content
- - loggers.each do |klass|
- .tab-pane{ class: active_when(klass == Gitlab::GitLogger), id: klass::file_name_noext }
+ - @loggers.each do |klass|
+ .tab-pane{ class: active_when(klass == @loggers.first), id: klass.file_name_noext }
.file-holder#README
.js-file-title.file-title
%i.fa.fa-file
- = klass::file_name
+ = klass.file_name
.pull-right
= link_to '#', class: 'log-bottom' do
%i.fa.fa-arrow-down
diff --git a/app/views/admin/monitoring/_head.html.haml b/app/views/admin/monitoring/_head.html.haml
index 901e30275fd..b3530915068 100644
--- a/app/views/admin/monitoring/_head.html.haml
+++ b/app/views/admin/monitoring/_head.html.haml
@@ -3,10 +3,6 @@
= render 'shared/nav_scroll'
.nav-links.sub-nav.scrolling-tabs
%ul{ class: (container_class) }
- = nav_link(controller: :conversational_development_index) do
- = link_to admin_conversational_development_index_path, title: 'ConvDev Index' do
- %span
- ConvDev Index
= nav_link(controller: :system_info) do
= link_to admin_system_info_path, title: 'System Info' do
%span
diff --git a/app/views/dashboard/issues.html.haml b/app/views/dashboard/issues.html.haml
index 52e0012fd7d..9ac44674b73 100644
--- a/app/views/dashboard/issues.html.haml
+++ b/app/views/dashboard/issues.html.haml
@@ -8,14 +8,14 @@
- content_for :breadcrumbs_extra do
= link_to params.merge(rss_url_options), class: 'btn has-tooltip append-right-10', title: 'Subscribe' do
= icon('rss')
- = render 'shared/new_project_item_select', path: 'issues/new', label: "New issue", with_feature_enabled: 'issues'
+ = render 'shared/new_project_item_select', path: 'issues/new', label: "New issue", with_feature_enabled: 'issues', type: :issues
.top-area
= render 'shared/issuable/nav', type: :issues
.nav-controls{ class: ("visible-xs" if show_new_nav?) }
= link_to params.merge(rss_url_options), class: 'btn has-tooltip', title: 'Subscribe' do
= icon('rss')
- = render 'shared/new_project_item_select', path: 'issues/new', label: "New issue", with_feature_enabled: 'issues'
+ = render 'shared/new_project_item_select', path: 'issues/new', label: "New issue", with_feature_enabled: 'issues', type: :issues
= render 'shared/issuable/filter', type: :issues
= render 'shared/issues'
diff --git a/app/views/dashboard/merge_requests.html.haml b/app/views/dashboard/merge_requests.html.haml
index c3fe14da2b2..960e1e55f36 100644
--- a/app/views/dashboard/merge_requests.html.haml
+++ b/app/views/dashboard/merge_requests.html.haml
@@ -4,12 +4,12 @@
- if show_new_nav?
- content_for :breadcrumbs_extra do
- = render 'shared/new_project_item_select', path: 'merge_requests/new', label: "New merge request", with_feature_enabled: 'merge_requests'
+ = render 'shared/new_project_item_select', path: 'merge_requests/new', label: "New merge request", with_feature_enabled: 'merge_requests', type: :merge_requests
.top-area
= render 'shared/issuable/nav', type: :merge_requests
.nav-controls{ class: ("visible-xs" if show_new_nav?) }
- = render 'shared/new_project_item_select', path: 'merge_requests/new', label: "New merge request", with_feature_enabled: 'merge_requests'
+ = render 'shared/new_project_item_select', path: 'merge_requests/new', label: "New merge request", with_feature_enabled: 'merge_requests', type: :merge_requests
= render 'shared/issuable/filter', type: :merge_requests
= render 'shared/merge_requests'
diff --git a/app/views/dashboard/milestones/index.html.haml b/app/views/dashboard/milestones/index.html.haml
index 37dbcaf5cb8..cb8bf57cba1 100644
--- a/app/views/dashboard/milestones/index.html.haml
+++ b/app/views/dashboard/milestones/index.html.haml
@@ -4,13 +4,13 @@
- if show_new_nav?
- content_for :breadcrumbs_extra do
- = render 'shared/new_project_item_select', path: 'milestones/new', label: 'New milestone', include_groups: true
+ = render 'shared/new_project_item_select', path: 'milestones/new', label: 'New milestone', include_groups: true, type: :milestones
.top-area
= render 'shared/milestones_filter', counts: @milestone_states
.nav-controls{ class: ("visible-xs" if show_new_nav?) }
- = render 'shared/new_project_item_select', path: 'milestones/new', label: 'New milestone', include_groups: true
+ = render 'shared/new_project_item_select', path: 'milestones/new', label: 'New milestone', include_groups: true, type: :milestones
.milestones
%ul.content-list
diff --git a/app/views/doorkeeper/authorizations/new.html.haml b/app/views/doorkeeper/authorizations/new.html.haml
index 82aa51f9778..8ba88906714 100644
--- a/app/views/doorkeeper/authorizations/new.html.haml
+++ b/app/views/doorkeeper/authorizations/new.html.haml
@@ -1,39 +1,43 @@
-%h3.page-title Authorization required
%main{ :role => "main" }
- %p.h4
- Authorize
- %strong.text-info= @pre_auth.client.name
- to use your account?
+ .modal-no-backdrop
+ .modal-content
+ .modal-header
+ %h3.page-title
+ Authorize
+ = link_to @pre_auth.client.name, @pre_auth.redirect_uri, target: '_blank', rel: 'noopener noreferrer'
+ to use your account?
- - if current_user.admin?
- .text-warning.prepend-top-20
- %p
- = icon("exclamation-triangle fw")
- You are an admin, which means granting access to
- %strong= @pre_auth.client.name
- will allow them to interact with GitLab as an admin as well. Proceed with caution.
-
- - if @pre_auth.scopes
- #oauth-permissions
- %p This application will be able to:
- %ul.text-info
- - @pre_auth.scopes.each do |scope|
- %li= t scope, scope: [:doorkeeper, :scopes]
- %hr/
- .actions
- = form_tag oauth_authorization_path, method: :post do
- = hidden_field_tag :client_id, @pre_auth.client.uid
- = hidden_field_tag :redirect_uri, @pre_auth.redirect_uri
- = hidden_field_tag :state, @pre_auth.state
- = hidden_field_tag :response_type, @pre_auth.response_type
- = hidden_field_tag :scope, @pre_auth.scope
- = hidden_field_tag :nonce, @pre_auth.nonce
- = submit_tag "Authorize", class: "btn btn-success wide pull-left"
- = form_tag oauth_authorization_path, method: :delete do
- = hidden_field_tag :client_id, @pre_auth.client.uid
- = hidden_field_tag :redirect_uri, @pre_auth.redirect_uri
- = hidden_field_tag :state, @pre_auth.state
- = hidden_field_tag :response_type, @pre_auth.response_type
- = hidden_field_tag :scope, @pre_auth.scope
- = hidden_field_tag :nonce, @pre_auth.nonce
- = submit_tag "Deny", class: "btn btn-danger prepend-left-10"
+ .modal-body
+ - if current_user.admin?
+ .text-warning
+ %p
+ = icon("exclamation-triangle fw")
+ You are an admin, which means granting access to
+ %strong= @pre_auth.client.name
+ will allow them to interact with GitLab as an admin as well. Proceed with caution.
+ %p
+ You are about to authorize
+ = link_to @pre_auth.client.name, @pre_auth.redirect_uri, target: '_blank', rel: 'noopener noreferrer'
+ to use your account.
+ - if @pre_auth.scopes
+ This application will be able to:
+ %ul
+ - @pre_auth.scopes.each do |scope|
+ %li= t scope, scope: [:doorkeeper, :scopes]
+ .form-actions.text-right
+ = form_tag oauth_authorization_path, method: :delete, class: 'inline' do
+ = hidden_field_tag :client_id, @pre_auth.client.uid
+ = hidden_field_tag :redirect_uri, @pre_auth.redirect_uri
+ = hidden_field_tag :state, @pre_auth.state
+ = hidden_field_tag :response_type, @pre_auth.response_type
+ = hidden_field_tag :scope, @pre_auth.scope
+ = hidden_field_tag :nonce, @pre_auth.nonce
+ = submit_tag "Deny", class: "btn btn-danger"
+ = form_tag oauth_authorization_path, method: :post, class: 'inline' do
+ = hidden_field_tag :client_id, @pre_auth.client.uid
+ = hidden_field_tag :redirect_uri, @pre_auth.redirect_uri
+ = hidden_field_tag :state, @pre_auth.state
+ = hidden_field_tag :response_type, @pre_auth.response_type
+ = hidden_field_tag :scope, @pre_auth.scope
+ = hidden_field_tag :nonce, @pre_auth.nonce
+ = submit_tag "Authorize", class: "btn btn-success prepend-left-10"
diff --git a/app/views/events/_event_push.atom.haml b/app/views/events/_event_push.atom.haml
index bf655f9d21a..e3c5fd55f08 100644
--- a/app/views/events/_event_push.atom.haml
+++ b/app/views/events/_event_push.atom.haml
@@ -5,9 +5,10 @@
%i
at
= event.created_at.to_s(:short)
- %blockquote= markdown(escape_once(event.commit_title), pipeline: :atom, project: event.project, author: event.author)
- - if event.commits_count > 1
- %p
- %i
- \... and
- = pluralize(event.commits_count - 1, "more commit")
+ - unless event.rm_ref?
+ %blockquote= markdown(escape_once(event.commit_title), pipeline: :atom, project: event.project, author: event.author)
+ - if event.commits_count > 1
+ %p
+ %i
+ \... and
+ = pluralize(event.commits_count - 1, "more commit")
diff --git a/app/views/events/event/_push.html.haml b/app/views/events/event/_push.html.haml
index 973c652ad88..53ebdd6d2ff 100644
--- a/app/views/events/event/_push.html.haml
+++ b/app/views/events/event/_push.html.haml
@@ -41,7 +41,3 @@
%li.commits-stat
= link_to create_mr_path(project.default_branch, event.ref_name, project) do
Create Merge Request
-- elsif event.rm_ref?
- .event-body
- %ul.well-list.event_commits
- = render "events/commit", project: project, event: event
diff --git a/app/views/groups/issues.html.haml b/app/views/groups/issues.html.haml
index f83ebbf09ef..12bc092d216 100644
--- a/app/views/groups/issues.html.haml
+++ b/app/views/groups/issues.html.haml
@@ -12,7 +12,7 @@
- content_for :breadcrumbs_extra do
= link_to params.merge(rss_url_options), class: 'btn btn-default append-right-10' do
= icon('rss')
- = render 'shared/new_project_item_select', path: 'issues/new', label: "New issue"
+ = render 'shared/new_project_item_select', path: 'issues/new', label: "New issue", type: :issues
- if group_issues_exists
.top-area
@@ -22,7 +22,7 @@
= icon('rss')
%span.icon-label
Subscribe
- = render 'shared/new_project_item_select', path: 'issues/new', label: "New issue"
+ = render 'shared/new_project_item_select', path: 'issues/new', label: "New issue", type: :issues
= render 'shared/issuable/search_bar', type: :issues
diff --git a/app/views/groups/merge_requests.html.haml b/app/views/groups/merge_requests.html.haml
index 997c82c77d9..184df6f5406 100644
--- a/app/views/groups/merge_requests.html.haml
+++ b/app/views/groups/merge_requests.html.haml
@@ -1,8 +1,12 @@
- page_title "Merge Requests"
+- content_for :page_specific_javascripts do
+ = webpack_bundle_tag 'common_vue'
+ = webpack_bundle_tag 'filtered_search'
+
- if show_new_nav? && current_user
- content_for :breadcrumbs_extra do
- = render 'shared/new_project_item_select', path: 'merge_requests/new', label: "New merge request"
+ = render 'shared/new_project_item_select', path: 'merge_requests/new', label: "New merge request", type: :merge_requests
- if @group_merge_requests.empty?
= render 'shared/empty_states/merge_requests', project_select_button: true
@@ -11,9 +15,9 @@
= render 'shared/issuable/nav', type: :merge_requests
- if current_user
.nav-controls{ class: ("visible-xs" if show_new_nav?) }
- = render 'shared/new_project_item_select', path: 'merge_requests/new', label: "New merge request"
+ = render 'shared/new_project_item_select', path: 'merge_requests/new', label: "New merge request", type: :merge_requests
- = render 'shared/issuable/filter', type: :merge_requests
+ = render 'shared/issuable/search_bar', type: :merge_requests
.row-content-block.second-block
Only merge requests from
diff --git a/app/views/groups/milestones/show.html.haml b/app/views/groups/milestones/show.html.haml
index 54b1b7a734a..23b1a22240f 100644
--- a/app/views/groups/milestones/show.html.haml
+++ b/app/views/groups/milestones/show.html.haml
@@ -1,4 +1,4 @@
= render "header_title"
= render 'shared/milestones/top', milestone: @milestone, group: @group
-= render 'shared/milestones/tabs', milestone: @milestone, show_project_name: true if @milestone.is_legacy_group_milestone?
+= render 'shared/milestones/tabs', milestone: @milestone, show_project_name: true if @milestone.legacy_group_milestone?
= render 'shared/milestones/sidebar', milestone: @milestone, affix_offset: 102
diff --git a/app/views/import/gitlab_projects/new.html.haml b/app/views/import/gitlab_projects/new.html.haml
index 008e8287aa3..5d68e1e2156 100644
--- a/app/views/import/gitlab_projects/new.html.haml
+++ b/app/views/import/gitlab_projects/new.html.haml
@@ -25,7 +25,7 @@
= hidden_field_tag :namespace_id, value: current_user.namespace_id
.form-group.col-xs-12.col-sm-6.project-path
= label_tag :path, 'Project name', class: 'label-light'
- = text_field_tag :path, nil, placeholder: "my-awesome-project", class: "js-path-name form-control", tabindex: 2, autofocus: true, required: true
+ = text_field_tag :path, @path, placeholder: "my-awesome-project", class: "js-path-name form-control", tabindex: 2, autofocus: true, required: true
.row
.form-group.col-md-12
@@ -33,7 +33,6 @@
.row
.form-group.col-sm-12
= hidden_field_tag :namespace_id, @namespace.id
- = hidden_field_tag :path, @path
= label_tag :file, 'GitLab project export', class: 'label-light'
.form-group
= file_field_tag :file, class: ''
diff --git a/app/views/layouts/errors.html.haml b/app/views/layouts/errors.html.haml
index 6d9ec043590..9382ee8715e 100644
--- a/app/views/layouts/errors.html.haml
+++ b/app/views/layouts/errors.html.haml
@@ -15,7 +15,7 @@
h1 {
font-size: 56px;
line-height: 100px;
- font-weight: normal;
+ font-weight: 400;
color: #456;
}
@@ -28,7 +28,7 @@
h3 {
color: #456;
font-size: 20px;
- font-weight: normal;
+ font-weight: 400;
line-height: 28px;
}
diff --git a/app/views/layouts/nav/_breadcrumbs.html.haml b/app/views/layouts/nav/_breadcrumbs.html.haml
index 8933fdd14db..6e2a959b86e 100644
--- a/app/views/layouts/nav/_breadcrumbs.html.haml
+++ b/app/views/layouts/nav/_breadcrumbs.html.haml
@@ -1,7 +1,8 @@
+- container = @no_breadcrumb_container ? 'container-fluid' : container_class
- hide_top_links = @hide_top_links || false
-%nav.breadcrumbs{ role: "navigation", class: [container_class, @content_class] }
- .breadcrumbs-container
+%nav.breadcrumbs{ role: "navigation" }
+ .breadcrumbs-container{ class: [container, @content_class] }
- if defined?(@new_sidebar)
= button_tag class: 'toggle-mobile-nav', type: 'button' do
%span.sr-only Open sidebar
diff --git a/app/views/layouts/nav/_new_admin_sidebar.html.haml b/app/views/layouts/nav/_new_admin_sidebar.html.haml
index 3cbcd841aff..9294529f496 100644
--- a/app/views/layouts/nav/_new_admin_sidebar.html.haml
+++ b/app/views/layouts/nav/_new_admin_sidebar.html.haml
@@ -4,7 +4,7 @@
= link_to admin_root_path, title: 'Admin Overview' do
.avatar-container.s40.settings-avatar
= icon('wrench')
- .project-title Admin Area
+ .sidebar-context-title Admin Area
%ul.sidebar-top-level-items
= nav_link(controller: %w(dashboard admin projects users groups jobs runners cohorts), html_options: {class: 'home'}) do
= link_to admin_root_path, title: 'Overview', class: 'shortcuts-tree' do
@@ -42,6 +42,10 @@
= link_to admin_cohorts_path, title: 'Cohorts' do
%span
Cohorts
+ = nav_link(controller: :conversational_development_index) do
+ = link_to admin_conversational_development_index_path, title: 'ConvDev Index' do
+ %span
+ ConvDev Index
= nav_link(controller: %w(conversational_development_index system_info background_jobs logs health_check requests_profiles)) do
= link_to admin_conversational_development_index_path, title: 'Monitoring' do
@@ -51,10 +55,6 @@
Monitoring
%ul.sidebar-sub-level-items
- = nav_link(controller: :conversational_development_index) do
- = link_to admin_conversational_development_index_path, title: 'ConvDev Index' do
- %span
- ConvDev Index
= nav_link(controller: :system_info) do
= link_to admin_system_info_path, title: 'System Info' do
%span
@@ -82,6 +82,7 @@
= custom_icon('messages')
%span.nav-item-name
Messages
+
= nav_link(controller: [:hooks, :hook_logs]) do
= link_to admin_hooks_path, title: 'Hooks' do
.nav-icon-container
@@ -140,7 +141,6 @@
%span.nav-item-name
Appearance
- %li.divider
= nav_link(controller: :application_settings) do
= link_to admin_application_settings_path, title: 'Settings' do
.nav-icon-container
diff --git a/app/views/layouts/nav/_new_group_sidebar.html.haml b/app/views/layouts/nav/_new_group_sidebar.html.haml
index ed5793f09fe..d90aea2e361 100644
--- a/app/views/layouts/nav/_new_group_sidebar.html.haml
+++ b/app/views/layouts/nav/_new_group_sidebar.html.haml
@@ -4,7 +4,7 @@
= link_to group_path(@group), title: @group.name do
.avatar-container.s40.group-avatar
= image_tag group_icon(@group), class: "avatar s40 avatar-tile"
- .group-title
+ .sidebar-context-title
= @group.name
%ul.sidebar-top-level-items
= nav_link(path: ['groups#show', 'groups#activity', 'groups#subgroups'], html_options: { class: 'home' }) do
diff --git a/app/views/layouts/nav/_new_profile_sidebar.html.haml b/app/views/layouts/nav/_new_profile_sidebar.html.haml
index 4234df56d1d..85b2c7630c8 100644
--- a/app/views/layouts/nav/_new_profile_sidebar.html.haml
+++ b/app/views/layouts/nav/_new_profile_sidebar.html.haml
@@ -4,7 +4,7 @@
= link_to profile_path, title: 'Profile Settings' do
.avatar-container.s40.settings-avatar
= icon('user')
- .project-title User Settings
+ .sidebar-context-title User Settings
%ul.sidebar-top-level-items
= nav_link(path: 'profiles#show', html_options: {class: 'home'}) do
= link_to profile_path, title: 'Profile Settings' do
diff --git a/app/views/layouts/nav/_new_project_sidebar.html.haml b/app/views/layouts/nav/_new_project_sidebar.html.haml
index 0ef81375c3a..341943cf833 100644
--- a/app/views/layouts/nav/_new_project_sidebar.html.haml
+++ b/app/views/layouts/nav/_new_project_sidebar.html.haml
@@ -5,7 +5,7 @@
= link_to project_path(@project), title: @project.name do
.avatar-container.s40.project-avatar
= project_icon(@project, alt: @project.name, class: 'avatar s40 avatar-tile')
- .project-title
+ .sidebar-context-title
= @project.name
%ul.sidebar-top-level-items
= nav_link(path: ['projects#show', 'projects#activity', 'cycle_analytics#show'], html_options: { class: 'home' }) do
@@ -86,7 +86,8 @@
%span.nav-item-name
Issues
- if @project.issues_enabled?
- %span.badge.count.issue_counter= number_with_delimiter(IssuesFinder.new(current_user, project_id: @project.id).execute.opened.count)
+ %span.badge.count.issue_counter
+ = number_with_delimiter(@project.open_issues_count)
%ul.sidebar-sub-level-items
= nav_link(controller: :issues) do
@@ -116,7 +117,8 @@
= custom_icon('mr_bold')
%span.nav-item-name
Merge Requests
- %span.badge.count.merge_counter.js-merge-counter= number_with_delimiter(MergeRequestsFinder.new(current_user, project_id: @project.id).execute.opened.count)
+ %span.badge.count.merge_counter.js-merge-counter
+ = number_with_delimiter(@project.open_merge_requests_count)
- if project_nav_tab? :pipelines
= nav_link(controller: [:pipelines, :builds, :jobs, :pipeline_schedules, :environments, :artifacts]) do
diff --git a/app/views/layouts/nav/_project.html.haml b/app/views/layouts/nav/_project.html.haml
index 924cd2e9681..b88465848e3 100644
--- a/app/views/layouts/nav/_project.html.haml
+++ b/app/views/layouts/nav/_project.html.haml
@@ -28,7 +28,8 @@
%span
Issues
- if @project.issues_enabled?
- %span.badge.count.issue_counter= number_with_delimiter(issuables_count_for_state(:issues, :opened, finder: IssuesFinder.new(current_user, project_id: @project.id)))
+ %span.badge.count.issue_counter
+ = number_with_delimiter(@project.open_issues_count)
- if project_nav_tab? :merge_requests
- controllers = [:merge_requests, 'projects/merge_requests/conflicts']
@@ -37,7 +38,8 @@
= 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(issuables_count_for_state(:merge_requests, :opened, finder: MergeRequestsFinder.new(current_user, project_id: @project.id)))
+ %span.badge.count.merge_counter.js-merge-counter
+ = number_with_delimiter(@project.open_merge_requests_count)
- if project_nav_tab? :pipelines
= nav_link(controller: [:pipelines, :builds, :environments, :artifacts]) do
diff --git a/app/views/layouts/oauth_error.html.haml b/app/views/layouts/oauth_error.html.haml
index 34bcd2a8b3a..03b387f8181 100644
--- a/app/views/layouts/oauth_error.html.haml
+++ b/app/views/layouts/oauth_error.html.haml
@@ -19,7 +19,7 @@
h3 {
color: #456;
font-size: 22px;
- font-weight: bold;
+ font-weight: 600;
margin-bottom: 6px;
}
diff --git a/app/views/profiles/gpg_keys/index.html.haml b/app/views/profiles/gpg_keys/index.html.haml
index 8331daeeb75..720a97cddb7 100644
--- a/app/views/profiles/gpg_keys/index.html.haml
+++ b/app/views/profiles/gpg_keys/index.html.haml
@@ -12,7 +12,7 @@
Add a GPG key
%p.profile-settings-content
Before you can add a GPG key you need to
- = link_to 'generate it.', help_page_path('workflow/gpg_signed_commits/index.md')
+ = link_to 'generate it.', help_page_path('user/project/gpg_signed_commits/index.md')
= render 'form'
%hr
%h5
diff --git a/app/views/projects/_project_templates.html.haml b/app/views/projects/_project_templates.html.haml
index 97cf13df070..5638b7da1b0 100644
--- a/app/views/projects/_project_templates.html.haml
+++ b/app/views/projects/_project_templates.html.haml
@@ -1,6 +1,6 @@
.project-templates-buttons.import-buttons{ data: { toggle: "buttons" } }
.btn.blank-option.active
- %input{ type: "radio", autocomplete: "off", name: "project_templates", id: "blank", checked: "true" }
+ %input{ type: "radio", autocomplete: "off", name: "project[template_name]", id: "blank", checked: "true", value: "" }
= icon('file-o', class: 'btn-template-icon')
Blank
- Gitlab::ProjectTemplate.all.each do |template|
diff --git a/app/views/projects/boards/_show.html.haml b/app/views/projects/boards/_show.html.haml
index cea942f213d..f6b5df4c91a 100644
--- a/app/views/projects/boards/_show.html.haml
+++ b/app/views/projects/boards/_show.html.haml
@@ -1,3 +1,4 @@
+- @no_breadcrumb_container = true
- @no_container = true
- @content_class = "issue-boards-content"
- breadcrumb_title "Issues Board"
diff --git a/app/views/projects/commit/_signature_badge.html.haml b/app/views/projects/commit/_signature_badge.html.haml
index 66f00eb5507..a3783b31b86 100644
--- a/app/views/projects/commit/_signature_badge.html.haml
+++ b/app/views/projects/commit/_signature_badge.html.haml
@@ -12,7 +12,7 @@
%span.monospace= signature.gpg_key_primary_keyid
- = link_to('Learn more about signing commits', help_page_path('workflow/gpg_signed_commits/index.md'), class: 'gpg-popover-help-link')
+ = link_to('Learn more about signing commits', help_page_path('user/project/gpg_signed_commits/index.md'), class: 'gpg-popover-help-link')
%button{ class: css_classes, data: { toggle: 'popover', html: 'true', placement: 'auto top', title: title, content: content } }
= label
diff --git a/app/views/projects/commits/_commit.html.haml b/app/views/projects/commits/_commit.html.haml
index e7da47032be..1214aabe837 100644
--- a/app/views/projects/commits/_commit.html.haml
+++ b/app/views/projects/commits/_commit.html.haml
@@ -5,7 +5,7 @@
- notes = commit.notes
- note_count = notes.user.count
-- cache_key = [project.full_path, commit.id, current_application_settings, note_count, @path.presence, current_controller?(:commits)]
+- cache_key = [project.full_path, commit.id, current_application_settings, note_count, @path.presence, current_controller?(:commits), I18n.locale]
- cache_key.push(commit.status(ref)) if commit.status(ref)
= cache(cache_key, expires_in: 1.day) do
@@ -37,14 +37,14 @@
.commit-actions.hidden-xs
- - if commit.status(ref)
- = render_commit_status(commit, ref: ref)
-
- if request.xhr?
= render partial: 'projects/commit/signature', object: commit.signature
- else
= render partial: 'projects/commit/ajax_signature', locals: { commit: commit }
+ - if commit.status(ref)
+ = render_commit_status(commit, ref: ref)
+
= link_to commit.short_id, project_commit_path(project, commit), class: "commit-sha btn btn-transparent"
= clipboard_button(text: commit.id, title: _("Copy commit SHA to clipboard"))
= link_to_browse_code(project, commit)
diff --git a/app/views/projects/edit.html.haml b/app/views/projects/edit.html.haml
index fcc4b5c06c7..994119051d2 100644
--- a/app/views/projects/edit.html.haml
+++ b/app/views/projects/edit.html.haml
@@ -203,8 +203,6 @@
.sub-section.rename-respository
%h4.warning-title
Rename repository
- %p
- Export this project with all its related data in order to move your project to a new GitLab instance. Once the export is finished, you can import the file from the "New Project" page.
= render 'projects/errors'
= form_for([@project.namespace.becomes(Namespace), @project]) do |f|
.form-group.project_name_holder
diff --git a/app/views/projects/issues/show.html.haml b/app/views/projects/issues/show.html.haml
index fd4588ca101..40886c9d597 100644
--- a/app/views/projects/issues/show.html.haml
+++ b/app/views/projects/issues/show.html.haml
@@ -34,7 +34,8 @@
%ul
- if can_update_issue
%li= link_to 'Edit', edit_project_issue_path(@project, @issue)
- - unless current_user == @issue.author
+ / TODO: simplify condition back #36860
+ - if @issue.author && current_user != @issue.author
%li= link_to 'Report abuse', new_abuse_report_path(user_id: @issue.author.id, ref_url: issue_url(@issue))
- if can_update_issue
%li= link_to 'Close issue', issue_path(@issue, issue: { state_event: :close }, format: 'json'), class: "btn-close #{issue_button_visibility(@issue, true)}", title: 'Close issue'
diff --git a/app/views/projects/new.html.haml b/app/views/projects/new.html.haml
index 647e0a772b1..5698bb281b4 100644
--- a/app/views/projects/new.html.haml
+++ b/app/views/projects/new.html.haml
@@ -68,9 +68,10 @@
- if git_import_enabled?
%button.btn.js-toggle-button.import_git{ type: "button" }
= icon('git', text: 'Repo by URL')
- .import_gitlab_project.has-tooltip{ data: { container: 'body' } }
- = link_to new_import_gitlab_project_path, class: 'btn btn_import_gitlab_project project-submit' do
- = icon('gitlab', text: 'GitLab export')
+ - if gitlab_project_import_enabled?
+ .import_gitlab_project.has-tooltip{ data: { container: 'body' } }
+ = link_to new_import_gitlab_project_path, class: 'btn btn_import_gitlab_project project-submit' do
+ = icon('gitlab', text: 'GitLab export')
.row
.col-lg-12
diff --git a/app/views/projects/notes/_actions.html.haml b/app/views/projects/notes/_actions.html.haml
index cb737d129f0..b04f5efe1f9 100644
--- a/app/views/projects/notes/_actions.html.haml
+++ b/app/views/projects/notes/_actions.html.haml
@@ -26,8 +26,12 @@
":title" => "buttonText",
":ref" => "'button'" }
- = icon('spin spinner', 'v-show' => 'loading', class: 'loading', 'aria-hidden' => 'true', 'aria-label' => 'Loading')
- %div{ 'v-show' => '!loading' }= render 'shared/icons/icon_status_success.svg'
+ = icon('spin spinner', 'v-if' => 'loading', class: 'loading', 'aria-hidden' => 'true', 'aria-label' => 'Loading')
+ %div{ 'v-else' => '' }
+ %template{ 'v-if' => 'isResolved' }
+ = render 'shared/icons/icon_status_success_solid.svg'
+ %template{ 'v-else' => '' }
+ = render 'shared/icons/icon_status_success.svg'
- if current_user
- if note.emoji_awardable?
diff --git a/app/views/projects/notes/_more_actions_dropdown.html.haml b/app/views/projects/notes/_more_actions_dropdown.html.haml
index 5930209a682..7e854186973 100644
--- a/app/views/projects/notes/_more_actions_dropdown.html.haml
+++ b/app/views/projects/notes/_more_actions_dropdown.html.haml
@@ -6,6 +6,8 @@
%span.icon
= custom_icon('ellipsis_v')
%ul.dropdown-menu.more-actions-dropdown.dropdown-open-left
+ %li
+ = clipboard_button(text: noteable_note_url(note), title: "Copy reference to clipboard", button_text: 'Copy link', hide_tooltip: true, hide_button_icon: true)
- unless is_current_user
%li
= link_to new_abuse_report_path(user_id: note.author.id, ref_url: noteable_note_url(note)) do
diff --git a/app/views/projects/pipelines/charts/_pipelines.haml b/app/views/projects/pipelines/charts/_pipelines.haml
index 02f1ef4b6da..7a100843f5e 100644
--- a/app/views/projects/pipelines/charts/_pipelines.haml
+++ b/app/views/projects/pipelines/charts/_pipelines.haml
@@ -14,19 +14,19 @@
.prepend-top-default
%p.light
- = _("Jobs for last week")
+ = _("Pipelines for last week")
(#{date_from_to(Date.today - 7.days, Date.today)})
%canvas#weekChart{ height: 200 }
.prepend-top-default
%p.light
- = _("Jobs for last month")
+ = _("Pipelines for last month")
(#{date_from_to(Date.today - 30.days, Date.today)})
%canvas#monthChart{ height: 200 }
.prepend-top-default
%p.light
- = _("Jobs for last year")
+ = _("Pipelines for last year")
%canvas#yearChart.padded{ height: 250 }
%script#pipelinesChartsData{ type: "application/json" }
diff --git a/app/views/projects/runners/_runner.html.haml b/app/views/projects/runners/_runner.html.haml
index abc97bcdff5..25d862ab4de 100644
--- a/app/views/projects/runners/_runner.html.haml
+++ b/app/views/projects/runners/_runner.html.haml
@@ -8,7 +8,7 @@
- if runner.locked?
= icon('lock', class: 'has-tooltip', title: 'Locked to current projects')
- %small
+ %small.edit-runner
= link_to edit_project_runner_path(@project, runner) do
%i.fa.fa-edit.btn
- else
diff --git a/app/views/search/_form.html.haml b/app/views/search/_form.html.haml
index 3139be1cd37..a4a5cec1314 100644
--- a/app/views/search/_form.html.haml
+++ b/app/views/search/_form.html.haml
@@ -11,5 +11,5 @@
%span.sr-only
Clear search
- unless params[:snippets].eql? 'true'
- = render 'filter' if current_user
+ = render 'filter'
= button_tag "Search", class: "btn btn-success btn-search"
diff --git a/app/views/shared/_group_form.html.haml b/app/views/shared/_group_form.html.haml
index 8d5b5129454..2e1bd5a088c 100644
--- a/app/views/shared/_group_form.html.haml
+++ b/app/views/shared/_group_form.html.haml
@@ -1,6 +1,6 @@
- content_for :page_specific_javascripts do
= page_specific_javascript_bundle_tag('group')
-- parent = GroupFinder.new(current_user).execute(id: params[:parent_id] || @group.parent_id)
+- parent = @group.parent
- group_path = root_url
- group_path << parent.full_path + '/' if parent
@@ -13,13 +13,12 @@
%span>= root_url
- if parent
%strong= parent.full_path + '/'
+ = f.hidden_field :parent_id
= f.text_field :path, placeholder: 'open-source', class: 'form-control',
autofocus: local_assigns[:autofocus] || false, required: true,
pattern: Gitlab::PathRegex::NAMESPACE_FORMAT_REGEX_JS,
title: 'Please choose a group path with no special characters.',
"data-bind-in" => "#{'create_chat_team' if Gitlab.config.mattermost.enabled}"
- - if parent
- = f.hidden_field :parent_id, value: parent.id
- if @group.persisted?
.alert.alert-warning.prepend-top-10
diff --git a/app/views/shared/_new_project_item_select.html.haml b/app/views/shared/_new_project_item_select.html.haml
index 96502d7ce93..dc912d800cf 100644
--- a/app/views/shared/_new_project_item_select.html.haml
+++ b/app/views/shared/_new_project_item_select.html.haml
@@ -1,6 +1,6 @@
- if any_projects?(@projects)
.project-item-select-holder.btn-group.pull-right
- %a.btn.btn-new.new-project-item-link{ href: '', data: { label: local_assigns[:label] } }
+ %a.btn.btn-new.new-project-item-link{ href: '', data: { label: local_assigns[:label], type: local_assigns[:type] } }
= icon('spinner spin')
= project_select_tag :project_path, class: "project-item-select", data: { include_groups: local_assigns[:include_groups], order_by: 'last_activity_at', relative_path: local_assigns[:path] }, with_feature_enabled: local_assigns[:with_feature_enabled]
%button.btn.btn-new.new-project-item-select-button
diff --git a/app/views/shared/empty_states/_issues.html.haml b/app/views/shared/empty_states/_issues.html.haml
index b0c0ab523c7..68737e8da66 100644
--- a/app/views/shared/empty_states/_issues.html.haml
+++ b/app/views/shared/empty_states/_issues.html.haml
@@ -15,7 +15,7 @@
Issues can be bugs, tasks or ideas to be discussed.
Also, issues are searchable and filterable.
- if project_select_button
- = render 'shared/new_project_item_select', path: 'issues/new', label: 'New issue'
+ = render 'shared/new_project_item_select', path: 'issues/new', label: 'New issue', type: :issues
- else
= link_to 'New issue', button_path, class: 'btn btn-new', title: 'New issue', id: 'new_issue_link'
- else
diff --git a/app/views/shared/empty_states/_merge_requests.html.haml b/app/views/shared/empty_states/_merge_requests.html.haml
index 3e64f403b8b..ff5741b6d61 100644
--- a/app/views/shared/empty_states/_merge_requests.html.haml
+++ b/app/views/shared/empty_states/_merge_requests.html.haml
@@ -14,7 +14,7 @@
%p
Interested parties can even contribute by pushing commits if they want to.
- if project_select_button
- = render 'shared/new_project_item_select', path: 'merge_requests/new', label: 'New merge request'
+ = render 'shared/new_project_item_select', path: 'merge_requests/new', label: 'New merge request', type: :merge_requests
- else
= link_to 'New merge request', button_path, class: 'btn btn-new', title: 'New merge request', id: 'new_merge_request_link'
- else
diff --git a/app/views/shared/icons/_icon_arrow_circle_o_right.svg b/app/views/shared/icons/_icon_arrow_circle_o_right.svg
index 5e45c6c15ce..29bdc8e5754 100644
--- a/app/views/shared/icons/_icon_arrow_circle_o_right.svg
+++ b/app/views/shared/icons/_icon_arrow_circle_o_right.svg
@@ -1 +1,2 @@
-<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 14 14"><g fill-rule="evenodd"><path fill-rule="nonzero" d="m0 7c0-3.866 3.142-7 7-7 3.866 0 7 3.142 7 7 0 3.866-3.142 7-7 7-3.866 0-7-3.142-7-7m1 0c0 3.309 2.69 6 6 6 3.309 0 6-2.69 6-6 0-3.309-2.69-6-6-6-3.309 0-6 2.69-6 6"/><path d="m7 6h-2.702c-.154 0-.298.132-.298.295v1.41c0 .164.133.295.298.295h2.702v1.694c0 .18.095.209.213.09l2.539-2.568c.115-.116.118-.312 0-.432l-2.539-2.568c-.115-.116-.213-.079-.213.09v1.694"/></g></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m9 6h-7a2 2 0 1 0 0 4h7v2.586a1 1 0 0 0 1.707.707l4.586-4.586a1 1 0 0 0 0-1.414l-4.586-4.586a1 1 0 0 0 -1.707.707z" fill-rule="evenodd"/></svg>
+
diff --git a/app/views/shared/icons/_icon_check_square_o.svg b/app/views/shared/icons/_icon_check_square_o.svg
index 3dfbfc8c0e9..05ed4d715d5 100644
--- a/app/views/shared/icons/_icon_check_square_o.svg
+++ b/app/views/shared/icons/_icon_check_square_o.svg
@@ -1 +1,2 @@
-<svg width="1792" height="1792" viewBox="0 0 1792 1792" xmlns="http://www.w3.org/2000/svg"><path d="M1472 930v318q0 119-84.5 203.5t-203.5 84.5h-832q-119 0-203.5-84.5t-84.5-203.5v-832q0-119 84.5-203.5t203.5-84.5h832q63 0 117 25 15 7 18 23 3 17-9 29l-49 49q-10 10-23 10-3 0-9-2-23-6-45-6h-832q-66 0-113 47t-47 113v832q0 66 47 113t113 47h832q66 0 113-47t47-113v-254q0-13 9-22l64-64q10-10 23-10 6 0 12 3 20 8 20 29zm231-489l-814 814q-24 24-57 24t-57-24l-430-430q-24-24-24-57t24-57l110-110q24-24 57-24t57 24l263 263 647-647q24-24 57-24t57 24l110 110q24 24 24 57t-24 57z"/></svg>
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path d="M7.536 8.657l2.828-2.829a1 1 0 0 1 1.414 1.415l-3.535 3.535a.997.997 0 0 1-1.415 0l-2.12-2.121A1 1 0 0 1 6.12 7.243l1.415 1.414zM3 0h10a3 3 0 0 1 3 3v10a3 3 0 0 1-3 3H3a3 3 0 0 1-3-3V3a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v10a1 1 0 0 0 1 1h10a1 1 0 0 0 1-1V3a1 1 0 0 0-1-1H3z"/></svg>
+
diff --git a/app/views/shared/icons/_icon_clock_o.svg b/app/views/shared/icons/_icon_clock_o.svg
index 8ddce62614c..9787ff6cb9e 100644
--- a/app/views/shared/icons/_icon_clock_o.svg
+++ b/app/views/shared/icons/_icon_clock_o.svg
@@ -1 +1 @@
-<svg width="1792" height="1792" viewBox="0 0 1792 1792" xmlns="http://www.w3.org/2000/svg"><path d="M1024 544v448q0 14-9 23t-23 9h-320q-14 0-23-9t-9-23v-64q0-14 9-23t23-9h224v-352q0-14 9-23t23-9h64q14 0 23 9t9 23zm416 352q0-148-73-273t-198-198-273-73-273 73-198 198-73 273 73 273 198 198 273 73 273-73 198-198 73-273zm224 0q0 209-103 385.5t-279.5 279.5-385.5 103-385.5-103-279.5-279.5-103-385.5 103-385.5 279.5-279.5 385.5-103 385.5 103 279.5 279.5 103 385.5z"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="M9 7h1c.552 0 1 .448 1 1s-.448 1-1 1H8c-.276 0-.526-.112-.707-.293S7 8.277 7 8V5c0-.552.448-1 1-1s1 .448 1 1zm-1 9c-4.418 0-8-3.582-8-8s3.582-8 8-8 8 3.582 8 8-3.582 8-8 8zm0-2c3.314 0 6-2.686 6-6s-2.686-6-6-6-6 2.686-6 6 2.686 6 6 6z"/></svg>
diff --git a/app/views/shared/icons/_icon_clone.svg b/app/views/shared/icons/_icon_clone.svg
index ccc897aa98f..faba51b5797 100644
--- a/app/views/shared/icons/_icon_clone.svg
+++ b/app/views/shared/icons/_icon_clone.svg
@@ -1,3 +1,2 @@
-<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="14" height="14" viewBox="0 0 14 14">
-<path d="M13 12.75v-8.5q0-0.102-0.074-0.176t-0.176-0.074h-8.5q-0.102 0-0.176 0.074t-0.074 0.176v8.5q0 0.102 0.074 0.176t0.176 0.074h8.5q0.102 0 0.176-0.074t0.074-0.176zM14 4.25v8.5q0 0.516-0.367 0.883t-0.883 0.367h-8.5q-0.516 0-0.883-0.367t-0.367-0.883v-8.5q0-0.516 0.367-0.883t0.883-0.367h8.5q0.516 0 0.883 0.367t0.367 0.883zM11 1.25v1.25h-1v-1.25q0-0.102-0.074-0.176t-0.176-0.074h-8.5q-0.102 0-0.176 0.074t-0.074 0.176v8.5q0 0.102 0.074 0.176t0.176 0.074h1.25v1h-1.25q-0.516 0-0.883-0.367t-0.367-0.883v-8.5q0-0.516 0.367-0.883t0.883-0.367h8.5q0.516 0 0.883 0.367t0.367 0.883z"></path>
-</svg>
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path d="M10.874 2H12a3 3 0 0 1 3 3v8a3 3 0 0 1-3 3h-2c-.918 0-1.74-.413-2.29-1.063a3.987 3.987 0 0 0 1.988-.984A1 1 0 0 0 10 14h2a1 1 0 0 0 1-1V5a1 1 0 0 0-1-1h-1V3c0-.345-.044-.68-.126-1zM4 0h3a3 3 0 0 1 3 3v8a3 3 0 0 1-3 3H4a3 3 0 0 1-3-3V3a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h3a1 1 0 0 0 1-1V3a1 1 0 0 0-1-1H4z"/></svg>
+
diff --git a/app/views/shared/icons/_icon_code_fork.svg b/app/views/shared/icons/_icon_code_fork.svg
index 5a0df2eee19..968e0ad3b2b 100644
--- a/app/views/shared/icons/_icon_code_fork.svg
+++ b/app/views/shared/icons/_icon_code_fork.svg
@@ -1 +1,2 @@
-<svg width="1792" height="1792" viewBox="0 0 1792 1792" xmlns="http://www.w3.org/2000/svg"><path d="M672 1472q0-40-28-68t-68-28-68 28-28 68 28 68 68 28 68-28 28-68zm0-1152q0-40-28-68t-68-28-68 28-28 68 28 68 68 28 68-28 28-68zm640 128q0-40-28-68t-68-28-68 28-28 68 28 68 68 28 68-28 28-68zm96 0q0 52-26 96.5t-70 69.5q-2 287-226 414-68 38-203 81-128 40-169.5 71t-41.5 100v26q44 25 70 69.5t26 96.5q0 80-56 136t-136 56-136-56-56-136q0-52 26-96.5t70-69.5v-820q-44-25-70-69.5t-26-96.5q0-80 56-136t136-56 136 56 56 136q0 52-26 96.5t-70 69.5v497q54-26 154-57 55-17 87.5-29.5t70.5-31 59-39.5 40.5-51 28-69.5 8.5-91.5q-44-25-70-69.5t-26-96.5q0-80 56-136t136-56 136 56 56 136z"/></svg>
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path d="M6 11.978v.29a2 2 0 1 1-2 0V3.732a2 2 0 1 1 2 0v3.849c.592-.491 1.31-.854 2.15-1.081 1.308-.353 1.875-.882 1.893-1.743a2 2 0 1 1 2.002-.051C12.053 6.54 10.857 7.84 8.67 8.43 7.056 8.867 6.195 9.98 6 11.978zM5 3a1 1 0 1 0 0-2 1 1 0 0 0 0 2zm6 1a1 1 0 1 0 0-2 1 1 0 0 0 0 2zM5 15a1 1 0 1 0 0-2 1 1 0 0 0 0 2z"/></svg>
+
diff --git a/app/views/shared/icons/_icon_comment_o.svg b/app/views/shared/icons/_icon_comment_o.svg
index b99bd5f42c8..050d7356f54 100644
--- a/app/views/shared/icons/_icon_comment_o.svg
+++ b/app/views/shared/icons/_icon_comment_o.svg
@@ -1 +1,2 @@
-<svg width="1792" height="1792" viewBox="0 0 1792 1792" xmlns="http://www.w3.org/2000/svg"><path d="M896 384q-204 0-381.5 69.5t-282 187.5-104.5 255q0 112 71.5 213.5t201.5 175.5l87 50-27 96q-24 91-70 172 152-63 275-171l43-38 57 6q69 8 130 8 204 0 381.5-69.5t282-187.5 104.5-255-104.5-255-282-187.5-381.5-69.5zm896 512q0 174-120 321.5t-326 233-450 85.5q-70 0-145-8-198 175-460 242-49 14-114 22h-5q-15 0-27-10.5t-16-27.5v-1q-3-4-.5-12t2-10 4.5-9.5l6-9 7-8.5 8-9q7-8 31-34.5t34.5-38 31-39.5 32.5-51 27-59 26-76q-157-89-247.5-220t-90.5-281q0-174 120-321.5t326-233 450-85.5 450 85.5 326 233 120 321.5z"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m1.707 15.707c-.63.63-1.707.184-1.707-.707v-12a3 3 0 0 1 3-3h10a3 3 0 0 1 3 3v6a3 3 0 0 1 -3 3h-7.586zm.293-3.121 2.293-2.293a1 1 0 0 1 .707-.293h8a1 1 0 0 0 1-1v-6a1 1 0 0 0 -1-1h-10a1 1 0 0 0 -1 1z"/></svg>
+
diff --git a/app/views/shared/icons/_icon_commit.svg b/app/views/shared/icons/_icon_commit.svg
index 7e9c0ded04e..6060d2e2aa4 100644
--- a/app/views/shared/icons/_icon_commit.svg
+++ b/app/views/shared/icons/_icon_commit.svg
@@ -1 +1,2 @@
-<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 18" enable-background="new 0 0 36 18"><path d="m34 7h-7.2c-.9-4-4.5-7-8.8-7s-7.9 3-8.8 7h-7.2c-1.1 0-2 .9-2 2 0 1.1.9 2 2 2h7.2c.9 4 4.5 7 8.8 7s7.9-3 8.8-7h7.2c1.1 0 2-.9 2-2 0-1.1-.9-2-2-2m-16 7c-2.8 0-5-2.2-5-5s2.2-5 5-5 5 2.2 5 5-2.2 5-5 5"/></svg>
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path d="M8 10a2 2 0 1 0 0-4 2 2 0 0 0 0 4zm3.876-1.008a4.002 4.002 0 0 1-7.752 0A1.01 1.01 0 0 1 4 9H1a1 1 0 1 1 0-2h3c.042 0 .083.003.124.008a4.002 4.002 0 0 1 7.752 0A1.01 1.01 0 0 1 12 7h3a1 1 0 0 1 0 2h-3a1.01 1.01 0 0 1-.124-.008z"/></svg>
+
diff --git a/app/views/shared/icons/_icon_edit.svg b/app/views/shared/icons/_icon_edit.svg
index cd4e34147e1..1c10ef138b5 100644
--- a/app/views/shared/icons/_icon_edit.svg
+++ b/app/views/shared/icons/_icon_edit.svg
@@ -1 +1,2 @@
-<svg width="1792" height="1792" viewBox="0 0 1792 1792" xmlns="http://www.w3.org/2000/svg"><path d="M888 1184l116-116-152-152-116 116v56h96v96h56zm440-720q-16-16-33 1l-350 350q-17 17-1 33t33-1l350-350q17-17 1-33zm80 594v190q0 119-84.5 203.5t-203.5 84.5h-832q-119 0-203.5-84.5t-84.5-203.5v-832q0-119 84.5-203.5t203.5-84.5h832q63 0 117 25 15 7 18 23 3 17-9 29l-49 49q-14 14-32 8-23-6-45-6h-832q-66 0-113 47t-47 113v832q0 66 47 113t113 47h832q66 0 113-47t47-113v-126q0-13 9-22l64-64q15-15 35-7t20 29zm-96-738l288 288-672 672h-288v-288zm444 132l-92 92-288-288 92-92q28-28 68-28t68 28l152 152q28 28 28 68t-28 68z"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m13.436 1.413 1.415 1.414a1 1 0 0 1 0 1.414l-10.316 10.315a1 1 0 0 1 -.703.293l-2.407.008-.008-2.421a1 1 0 0 1 .293-.71l10.312-10.314a1 1 0 0 1 1.414 0zm-9.608 12.436 10.315-10.315-1.413-1.414-10.313 10.312.005 1.422zm7.486-10.313 1.414 1.414-7.778 7.778-1.407.007-.007-1.421zm1.414-1.415 1.414 1.415-.707.707-1.414-1.415z"/></svg>
+
diff --git a/app/views/shared/icons/_icon_eye.svg b/app/views/shared/icons/_icon_eye.svg
index 2e2ae67142f..9fea9841eb3 100644
--- a/app/views/shared/icons/_icon_eye.svg
+++ b/app/views/shared/icons/_icon_eye.svg
@@ -1 +1,2 @@
-<svg width="1792" height="1792" viewBox="0 0 1792 1792" xmlns="http://www.w3.org/2000/svg"><path d="M1664 960q-152-236-381-353 61 104 61 225 0 185-131.5 316.5t-316.5 131.5-316.5-131.5-131.5-316.5q0-121 61-225-229 117-381 353 133 205 333.5 326.5t434.5 121.5 434.5-121.5 333.5-326.5zm-720-384q0-20-14-34t-34-14q-125 0-214.5 89.5t-89.5 214.5q0 20 14 34t34 14 34-14 14-34q0-86 61-147t147-61q20 0 34-14t14-34zm848 384q0 34-20 69-140 230-376.5 368.5t-499.5 138.5-499.5-139-376.5-368q-20-35-20-69t20-69q140-229 376.5-368t499.5-139 499.5 139 376.5 368q20 35 20 69z"/></svg>
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path d="M8 14C4.816 14 2.253 12.284.393 8.981a2 2 0 0 1 0-1.962C2.253 3.716 4.816 2 8 2s5.747 1.716 7.607 5.019a2 2 0 0 1 0 1.962C13.747 12.284 11.184 14 8 14zm0-2c2.41 0 4.338-1.29 5.864-4C12.338 5.29 10.411 4 8 4 5.59 4 3.662 5.29 2.136 8 3.662 10.71 5.589 12 8 12zm0-1a3 3 0 1 1 0-6 3 3 0 0 1 0 6zm1-3a1 1 0 1 0 0-2 1 1 0 0 0 0 2z"/></svg>
+
diff --git a/app/views/shared/icons/_icon_eye_slash.svg b/app/views/shared/icons/_icon_eye_slash.svg
index a16c5dcb24b..45c06b3495d 100644
--- a/app/views/shared/icons/_icon_eye_slash.svg
+++ b/app/views/shared/icons/_icon_eye_slash.svg
@@ -1 +1,2 @@
-<svg width="1792" height="1792" viewBox="0 0 1792 1792" xmlns="http://www.w3.org/2000/svg"><path d="M555 1335l78-141q-87-63-136-159t-49-203q0-121 61-225-229 117-381 353 167 258 427 375zm389-759q0-20-14-34t-34-14q-125 0-214.5 89.5t-89.5 214.5q0 20 14 34t34 14 34-14 14-34q0-86 61-147t147-61q20 0 34-14t14-34zm363-191q0 7-1 9-105 188-315 566t-316 567l-49 89q-10 16-28 16-12 0-134-70-16-10-16-28 0-12 44-87-143-65-263.5-173t-208.5-245q-20-31-20-69t20-69q153-235 380-371t496-136q89 0 180 17l54-97q10-16 28-16 5 0 18 6t31 15.5 33 18.5 31.5 18.5 19.5 11.5q16 10 16 27zm37 447q0 139-79 253.5t-209 164.5l280-502q8 45 8 84zm448 128q0 35-20 69-39 64-109 145-150 172-347.5 267t-419.5 95l74-132q212-18 392.5-137t301.5-307q-115-179-282-294l63-112q95 64 182.5 153t144.5 184q20 34 20 69z"/></svg>
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path d="M13.618 2.62L1.62 14.619a1 1 0 0 1-.985-1.668l1.525-1.526C1.516 10.742.926 9.927.393 8.981a2 2 0 0 1 0-1.962C2.253 3.716 4.816 2 8 2c1.074 0 2.076.195 3.006.58l.944-.944a1 1 0 0 1 1.668.985zM8.068 11a3 3 0 0 0 2.931-2.932l-2.931 2.931zm-3.02-2.462a3 3 0 0 1 3.49-3.49l.884-.884A6.044 6.044 0 0 0 8 4C5.59 4 3.662 5.29 2.136 8c.445.79.924 1.46 1.439 2.011l1.473-1.473zm.421 5.06l1.658-1.658c.283.04.575.06.873.06 2.41 0 4.338-1.29 5.864-4a11.023 11.023 0 0 0-1.133-1.664l1.418-1.418a12.799 12.799 0 0 1 1.458 2.1 2 2 0 0 1 0 1.963C13.747 12.284 11.184 14 8 14a7.883 7.883 0 0 1-2.53-.402z"/></svg>
+
diff --git a/app/views/shared/icons/_icon_merged.svg b/app/views/shared/icons/_icon_merged.svg
index 43d591daefa..77d170b2491 100644
--- a/app/views/shared/icons/_icon_merged.svg
+++ b/app/views/shared/icons/_icon_merged.svg
@@ -1 +1,2 @@
-<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><path d="m2 3c.552 0 1-.448 1-1 0-.552-.448-1-1-1-.552 0-1 .448-1 1 0 .552.448 1 1 1m.761.85c.154 2.556 1.987 4.692 4.45 5.255.328-.655 1.01-1.105 1.789-1.105 1.105 0 2 .895 2 2 0 1.105-.895 2-2 2-.89 0-1.645-.582-1.904-1.386-1.916-.376-3.548-1.5-4.596-3.044v4.493c.863.222 1.5 1.01 1.5 1.937 0 1.105-.895 2-2 2-1.105 0-2-.895-2-2 0-.74.402-1.387 1-1.732v-8.535c-.598-.346-1-.992-1-1.732 0-1.105.895-2 2-2 1.105 0 2 .895 2 2 0 .835-.512 1.551-1.239 1.85m6.239 7.15c.552 0 1-.448 1-1 0-.552-.448-1-1-1-.552 0-1 .448-1 1 0 .552.448 1 1 1m-7 4c.552 0 1-.448 1-1 0-.552-.448-1-1-1-.552 0-1 .448-1 1 0 .552.448 1 1 1" transform="translate(3)"/></svg>
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path d="M11 12.268V5a1 1 0 0 0-1-1v1a.5.5 0 0 1-.8.4l-2.667-2a.5.5 0 0 1 0-.8L9.2.6a.5.5 0 0 1 .8.4v1a3 3 0 0 1 3 3v7.268a2 2 0 1 1-2 0zm-6 0a2 2 0 1 1-2 0V4.732a2 2 0 1 1 2 0v7.536zM4 4a1 1 0 1 0 0-2 1 1 0 0 0 0 2zm0 11a1 1 0 1 0 0-2 1 1 0 0 0 0 2zm8 0a1 1 0 1 0 0-2 1 1 0 0 0 0 2z"/></svg>
+
diff --git a/app/views/shared/icons/_icon_pencil.svg b/app/views/shared/icons/_icon_pencil.svg
index a3b48404f87..bcde54bd1e1 100644
--- a/app/views/shared/icons/_icon_pencil.svg
+++ b/app/views/shared/icons/_icon_pencil.svg
@@ -1 +1,2 @@
-<svg width="1792" height="1792" viewBox="0 0 1792 1792" xmlns="http://www.w3.org/2000/svg"><path d="M491 1536l91-91-235-235-91 91v107h128v128h107zm523-928q0-22-22-22-10 0-17 7l-542 542q-7 7-7 17 0 22 22 22 10 0 17-7l542-542q7-7 7-17zm-54-192l416 416-832 832h-416v-416zm683 96q0 53-37 90l-166 166-416-416 166-165q36-38 90-38 53 0 91 38l235 234q37 39 37 91z"/></svg>
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path d="M13.02 1.293l1.414 1.414a1 1 0 0 1 0 1.414L4.119 14.436a1 1 0 0 1-.704.293l-2.407.008L1 12.316a1 1 0 0 1 .293-.71L11.605 1.292a1 1 0 0 1 1.414 0zm-1.416 1.415l-.707.707L12.31 4.83l.707-.707-1.414-1.415zM3.411 13.73l1.123-1.122H3.12v-1.415L2 12.312l.005 1.422 1.406-.005z"/></svg>
+
diff --git a/app/views/shared/icons/_icon_random.svg b/app/views/shared/icons/_icon_random.svg
index 763bd2d3dd8..74c1c903657 100644
--- a/app/views/shared/icons/_icon_random.svg
+++ b/app/views/shared/icons/_icon_random.svg
@@ -1 +1,2 @@
-<svg width="1792" height="1792" viewBox="0 0 1792 1792" xmlns="http://www.w3.org/2000/svg"><path d="M666 481q-60 92-137 273-22-45-37-72.5t-40.5-63.5-51-56.5-63-35-81.5-14.5h-224q-14 0-23-9t-9-23v-192q0-14 9-23t23-9h224q250 0 410 225zm1126 799q0 14-9 23l-320 320q-9 9-23 9-13 0-22.5-9.5t-9.5-22.5v-192q-32 0-85 .5t-81 1-73-1-71-5-64-10.5-63-18.5-58-28.5-59-40-55-53.5-56-69.5q59-93 136-273 22 45 37 72.5t40.5 63.5 51 56.5 63 35 81.5 14.5h256v-192q0-14 9-23t23-9q12 0 24 10l319 319q9 9 9 23zm0-896q0 14-9 23l-320 320q-9 9-23 9-13 0-22.5-9.5t-9.5-22.5v-192h-256q-48 0-87 15t-69 45-51 61.5-45 77.5q-32 62-78 171-29 66-49.5 111t-54 105-64 100-74 83-90 68.5-106.5 42-128 16.5h-224q-14 0-23-9t-9-23v-192q0-14 9-23t23-9h224q48 0 87-15t69-45 51-61.5 45-77.5q32-62 78-171 29-66 49.5-111t54-105 64-100 74-83 90-68.5 106.5-42 128-16.5h256v-192q0-14 9-23t23-9q12 0 24 10l319 319q9 9 9 23z"/></svg>
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path d="M1.707 15.707C1.077 16.337 0 15.891 0 15V3a3 3 0 0 1 3-3h10a3 3 0 0 1 3 3v6a3 3 0 0 1-3 3H5.414l-3.707 3.707zM2 12.586l2.293-2.293A1 1 0 0 1 5 10h8a1 1 0 0 0 1-1V3a1 1 0 0 0-1-1H3a1 1 0 0 0-1 1v9.586zM5 7a1 1 0 1 1 0-2 1 1 0 0 1 0 2zm3 0a1 1 0 1 1 0-2 1 1 0 0 1 0 2zm3 0a1 1 0 1 1 0-2 1 1 0 0 1 0 2z"/></svg>
+
diff --git a/app/views/shared/icons/_icon_status_closed.svg b/app/views/shared/icons/_icon_status_closed.svg
index de448ee1194..dc39223e721 100644
--- a/app/views/shared/icons/_icon_status_closed.svg
+++ b/app/views/shared/icons/_icon_status_closed.svg
@@ -1 +1 @@
-<svg width="14" height="14" viewBox="0 0 14 14" xmlns="http://www.w3.org/2000/svg"><path d="M0 7c0-3.866 3.142-7 7-7 3.866 0 7 3.142 7 7 0 3.866-3.142 7-7 7-3.866 0-7-3.142-7-7z"/><path d="M1 7c0 3.309 2.69 6 6 6 3.309 0 6-2.69 6-6 0-3.309-2.69-6-6-6-3.309 0-6 2.69-6 6z" fill="#FFF"/><rect x="3.36" y="6.16" width="7.28" height="1.68" rx=".84"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="M7.536 8.657l2.828-2.83c.39-.39 1.024-.39 1.414 0 .39.392.39 1.025 0 1.416l-3.535 3.535c-.196.195-.452.293-.707.293-.256 0-.512-.097-.708-.292l-2.12-2.12c-.39-.392-.39-1.025 0-1.415s1.023-.39 1.413 0zM8 16c-4.418 0-8-3.582-8-8s3.582-8 8-8 8 3.582 8 8-3.582 8-8 8zm0-2c3.314 0 6-2.686 6-6s-2.686-6-6-6-6 2.686-6 6 2.686 6 6 6z"/></svg>
diff --git a/app/views/shared/icons/_icon_status_success.svg b/app/views/shared/icons/_icon_status_success.svg
index eed5006bebe..845562e9320 100755
--- a/app/views/shared/icons/_icon_status_success.svg
+++ b/app/views/shared/icons/_icon_status_success.svg
@@ -1 +1 @@
-<svg width="14" height="14" viewBox="0 0 14 14" xmlns="http://www.w3.org/2000/svg"><g fill-rule="evenodd"><path d="M0 7a7 7 0 1 1 14 0A7 7 0 0 1 0 7z"/><path d="M13 7A6 6 0 1 0 1 7a6 6 0 0 0 12 0z" fill="#FFF"/><path d="M6.278 7.697L5.045 6.464a.296.296 0 0 0-.42-.002l-.613.614a.298.298 0 0 0 .002.42l1.91 1.909a.5.5 0 0 0 .703.005l.265-.265L9.997 6.04a.291.291 0 0 0-.009-.408l-.614-.614a.29.29 0 0 0-.408-.009L6.278 7.697z"/></g></svg>
+<svg width="14" height="14" viewBox="0 0 14 14" xmlns="http://www.w3.org/2000/svg"><path d="M0 7a7 7 0 1 1 14 0A7 7 0 0 1 0 7z M13 7A6 6 0 1 0 1 7a6 6 0 0 0 12 0z" fill-rule="evenodd"/><path d="M6.278 7.697L5.045 6.464a.296.296 0 0 0-.42-.002l-.613.614a.298.298 0 0 0 .002.42l1.91 1.909a.5.5 0 0 0 .703.005l.265-.265L9.997 6.04a.291.291 0 0 0-.009-.408l-.614-.614a.29.29 0 0 0-.408-.009L6.278 7.697z"/></svg>
diff --git a/app/views/shared/icons/_icon_status_success_solid.svg b/app/views/shared/icons/_icon_status_success_solid.svg
new file mode 100644
index 00000000000..0aac6d933e1
--- /dev/null
+++ b/app/views/shared/icons/_icon_status_success_solid.svg
@@ -0,0 +1 @@
+<svg width="14" height="14" viewBox="0 0 14 14" xmlns="http://www.w3.org/2000/svg"><path d="M0 7a7 7 0 1 1 14 0A7 7 0 0 1 0 7z M6.278 7.697L5.045 6.464a.296.296 0 0 0-.42-.002l-.613.614a.298.298 0 0 0 .002.42l1.91 1.909a.5.5 0 0 0 .703.005l.265-.265L9.997 6.04a.291.291 0 0 0-.009-.408l-.614-.614a.29.29 0 0 0-.408-.009L6.278 7.697z" fill-rule="evenodd"/></svg>
diff --git a/app/views/shared/icons/_icon_tags.svg b/app/views/shared/icons/_icon_tags.svg
index fc5acc89c5e..d36ea022f92 100644
--- a/app/views/shared/icons/_icon_tags.svg
+++ b/app/views/shared/icons/_icon_tags.svg
@@ -1 +1,2 @@
-<svg width="1792" height="1792" viewBox="0 0 1792 1792" xmlns="http://www.w3.org/2000/svg"><path d="M384 448q0-53-37.5-90.5t-90.5-37.5-90.5 37.5-37.5 90.5 37.5 90.5 90.5 37.5 90.5-37.5 37.5-90.5zm1067 576q0 53-37 90l-491 492q-39 37-91 37-53 0-90-37l-715-716q-38-37-64.5-101t-26.5-117v-416q0-52 38-90t90-38h416q53 0 117 26.5t102 64.5l715 714q37 39 37 91zm384 0q0 53-37 90l-491 492q-39 37-91 37-36 0-59-14t-53-45l470-470q37-37 37-90 0-52-37-91l-715-714q-38-38-102-64.5t-117-26.5h224q53 0 117 26.5t102 64.5l715 714q37 39 37 91z"/></svg>
+<svg viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="m7.222.222c1.657 0 3 1.343 3 3v8.327c0 .631-.298 1.226-.805 1.603l-3 2.237c-.709.529-1.682.529-2.391 0l-3-2.237c-.506-.377-.805-.972-.805-1.603v-8.327c0-1.657 1.343-3 3-3h4m-5 3v8.08c0 .158.075.306.201.401l2.5 1.864c.177.132.42.132.598 0l2.5-1.864c.127-.094.201-.243.201-.401v-8.08c0-.552-.448-1-1-1h-4c-.552 0-1 .448-1 1m2.778 7.778c-.552 0-1-.448-1-1s .448-1 1-1 1 .448 1 1-.448 1-1 1" transform="matrix(-.70711 .70711 -.70711 -.70711 17.05 9.767)"/></svg>
+
diff --git a/app/views/shared/icons/_icon_user.svg b/app/views/shared/icons/_icon_user.svg
index 9b8cd74d62b..6e7406f7eac 100644
--- a/app/views/shared/icons/_icon_user.svg
+++ b/app/views/shared/icons/_icon_user.svg
@@ -1 +1 @@
-<svg width="1792" height="1792" viewBox="0 0 1792 1792" xmlns="http://www.w3.org/2000/svg"><path d="M1600 1405q0 120-73 189.5t-194 69.5h-874q-121 0-194-69.5t-73-189.5q0-53 3.5-103.5t14-109 26.5-108.5 43-97.5 62-81 85.5-53.5 111.5-20q9 0 42 21.5t74.5 48 108 48 133.5 21.5 133.5-21.5 108-48 74.5-48 42-21.5q61 0 111.5 20t85.5 53.5 62 81 43 97.5 26.5 108.5 14 109 3.5 103.5zm-320-893q0 159-112.5 271.5t-271.5 112.5-271.5-112.5-112.5-271.5 112.5-271.5 271.5-112.5 271.5 112.5 112.5 271.5z"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="M8 7C6.343 7 5 5.657 5 4s1.343-3 3-3 3 1.343 3 3-1.343 3-3 3zm0 8c-6.888 0-6.976-.78-6.976-2.52S2.144 8 8 8s6.976 2.692 6.976 4.48S14.888 15 8 15z" fill-rule="evenodd"/></svg>
diff --git a/app/views/shared/issuable/_close_reopen_button.html.haml b/app/views/shared/issuable/_close_reopen_button.html.haml
index 8a1268a1c6d..f22b6c9a6c2 100644
--- a/app/views/shared/issuable/_close_reopen_button.html.haml
+++ b/app/views/shared/issuable/_close_reopen_button.html.haml
@@ -9,6 +9,7 @@
class: "hidden-xs hidden-sm btn btn-grouped btn-reopen #{issuable_button_visibility(issuable, false)}", title: "Reopen #{display_issuable_type}"
- elsif can_update && !is_current_user
= render 'shared/issuable/close_reopen_report_toggle', issuable: issuable
-- else
+- elsif issuable.author
+ / TODO: change back to else #36860
= link_to 'Report abuse', new_abuse_report_path(user_id: issuable.author.id, ref_url: issuable_url(issuable)),
class: 'hidden-xs hidden-sm btn btn-grouped btn-close-color', title: 'Report abuse'
diff --git a/app/views/shared/issuable/_close_reopen_report_toggle.html.haml b/app/views/shared/issuable/_close_reopen_report_toggle.html.haml
index 6756a7f17fd..daa05990ae9 100644
--- a/app/views/shared/issuable/_close_reopen_report_toggle.html.haml
+++ b/app/views/shared/issuable/_close_reopen_report_toggle.html.haml
@@ -37,13 +37,15 @@
%li.divider.droplab-item-ignore
- %li.report-item{ data: { text: 'Report abuse', url: new_abuse_report_path(user_id: issuable.author.id, ref_url: issuable_url(issuable)),
- button_class: "#{button_class} btn-close-color", toggle_class: "#{toggle_class} btn-close-color", method: '' } }
- %button.btn.btn-transparent
- = icon('check', class: 'icon')
- .description
- %strong.title Report abuse
- %p.text
- Report
- = display_issuable_type.pluralize
- that are abusive, inappropriate or spam.
+ / TODO: remove condition #36860
+ - if issuable.author
+ %li.report-item{ data: { text: 'Report abuse', url: new_abuse_report_path(user_id: issuable.author.id, ref_url: issuable_url(issuable)),
+ button_class: "#{button_class} btn-close-color", toggle_class: "#{toggle_class} btn-close-color", method: '' } }
+ %button.btn.btn-transparent
+ = icon('check', class: 'icon')
+ .description
+ %strong.title Report abuse
+ %p.text
+ Report
+ = display_issuable_type.pluralize
+ that are abusive, inappropriate or spam.
diff --git a/app/views/shared/issuable/_search_bar.html.haml b/app/views/shared/issuable/_search_bar.html.haml
index 1ad00461d76..e81789ea7a2 100644
--- a/app/views/shared/issuable/_search_bar.html.haml
+++ b/app/views/shared/issuable/_search_bar.html.haml
@@ -57,7 +57,7 @@
%li.filter-dropdown-item{ data: { value: 'none' } }
%button.btn.btn-link
No Assignee
- %li.divider
+ %li.divider.droplab-item-ignore
- if current_user
= render 'shared/issuable/user_dropdown_item',
user: current_user
@@ -76,7 +76,7 @@
%li.filter-dropdown-item{ 'data-value' => 'started' }
%button.btn.btn-link
Started
- %li.divider
+ %li.divider.droplab-item-ignore
%ul.filter-dropdown{ data: { dynamic: true, dropdown: true } }
%li.filter-dropdown-item
%button.btn.btn-link.js-data-value
@@ -86,13 +86,20 @@
%li.filter-dropdown-item{ data: { value: 'none' } }
%button.btn.btn-link
No Label
- %li.divider
+ %li.divider.droplab-item-ignore
%ul.filter-dropdown{ data: { dynamic: true, dropdown: true } }
%li.filter-dropdown-item
%button.btn.btn-link
%span.dropdown-label-box{ style: 'background: {{color}}' }
%span.label-title.js-data-value
{{title}}
+ #js-dropdown-my-reaction.filtered-search-input-dropdown-menu.dropdown-menu
+ %ul.filter-dropdown{ data: { dynamic: true, dropdown: true } }
+ %li.filter-dropdown-item
+ %button.btn.btn-link
+ %gl-emoji
+ %span.js-data-value.prepend-left-10
+ {{name}}
%button.clear-search.hidden{ type: 'button' }
= icon('times')
.filter-dropdown-container
diff --git a/app/views/shared/issuable/_user_dropdown_item.html.haml b/app/views/shared/issuable/_user_dropdown_item.html.haml
index c18e4975bb8..48d04678d47 100644
--- a/app/views/shared/issuable/_user_dropdown_item.html.haml
+++ b/app/views/shared/issuable/_user_dropdown_item.html.haml
@@ -4,7 +4,7 @@
%li.filter-dropdown-item{ class: ('js-current-user' if user == current_user) }
%button.btn.btn-link.dropdown-user{ type: :button }
.avatar-container.s40
- = user_avatar_without_link(user: user, lazy: avatar[:lazy], url: avatar[:url], size: 40).gsub('/images/{{avatar_url}}','{{avatar_url}}').html_safe
+ = user_avatar_without_link(user: user, lazy: avatar[:lazy], url: avatar[:url], size: 40, has_tooltip: false).gsub('/images/{{avatar_url}}','{{avatar_url}}').html_safe
.dropdown-user-details
%span
= user.name
diff --git a/app/views/shared/milestones/_milestone.html.haml b/app/views/shared/milestones/_milestone.html.haml
index 6a85f7d0564..305e2542281 100644
--- a/app/views/shared/milestones/_milestone.html.haml
+++ b/app/views/shared/milestones/_milestone.html.haml
@@ -5,7 +5,7 @@
.row
.col-sm-6
%strong= link_to truncate(milestone.title, length: 100), milestone_path
- - if milestone.is_group_milestone?
+ - if milestone.group_milestone?
%span - Group Milestone
- else
%span - Project Milestone
@@ -18,10 +18,10 @@
&middot;
= link_to pluralize(milestone.merge_requests.size, 'Merge Request'), merge_requests_path
.col-sm-6= milestone_progress_bar(milestone)
- - if milestone.is_a?(GlobalMilestone) || milestone.is_group_milestone?
+ - if milestone.is_a?(GlobalMilestone) || milestone.group_milestone?
.row
.col-sm-6
- - if milestone.is_legacy_group_milestone?
+ - if milestone.legacy_group_milestone?
.expiration= render('shared/milestone_expired', milestone: milestone)
.projects
- milestone.milestones.each do |milestone|
@@ -31,7 +31,7 @@
- if @group
.col-sm-6.milestone-actions
- if can?(current_user, :admin_milestones, @group)
- - if milestone.is_group_milestone?
+ - if milestone.group_milestone?
= link_to edit_group_milestone_path(@group, milestone), class: "btn btn-xs btn-grouped" do
Edit
\
diff --git a/app/views/shared/milestones/_top.html.haml b/app/views/shared/milestones/_top.html.haml
index 3014300fbe7..fd0760d83a5 100644
--- a/app/views/shared/milestones/_top.html.haml
+++ b/app/views/shared/milestones/_top.html.haml
@@ -22,7 +22,7 @@
- if group
.pull-right
- if can?(current_user, :admin_milestones, group)
- - if milestone.is_group_milestone?
+ - if milestone.group_milestone?
= link_to edit_group_milestone_path(group, milestone), class: "btn btn btn-grouped" do
Edit
- if milestone.active?
@@ -33,7 +33,7 @@
.detail-page-description.milestone-detail
%h2.title
= markdown_field(milestone, :title)
- - if @milestone.is_group_milestone? && @milestone.description.present?
+ - if @milestone.group_milestone? && @milestone.description.present?
%div
.description
.wiki
@@ -44,7 +44,7 @@
- close_msg = group ? 'You may close the milestone now.' : 'Navigate to the project to close the milestone.'
%span All issues for this milestone are closed. #{close_msg}
-- if @milestone.is_legacy_group_milestone? || @milestone.is_dashboard_milestone?
+- if @milestone.legacy_group_milestone? || @milestone.dashboard_milestone?
.table-holder
%table.table
%thead
@@ -67,7 +67,7 @@
Open
%td
= ms.expires_at
-- elsif @milestone.is_group_milestone?
+- elsif @milestone.group_milestone?
%br
View
= link_to 'Issues', issues_group_path(@group, milestone_title: milestone.title)
diff --git a/app/views/shared/projects/_dropdown.html.haml b/app/views/shared/projects/_dropdown.html.haml
index 8939aeb6c3a..80432a73e4e 100644
--- a/app/views/shared/projects/_dropdown.html.haml
+++ b/app/views/shared/projects/_dropdown.html.haml
@@ -15,8 +15,11 @@
= link_to filter_projects_path(archived: nil), class: ("is-active" unless params[:archived].present?) do
Hide archived projects
%li
- = link_to filter_projects_path(archived: true), class: ("is-active" if params[:archived].present?) do
+ = link_to filter_projects_path(archived: true), class: ("is-active" if Gitlab::Utils.to_boolean(params[:archived])) do
Show archived projects
+ %li
+ = link_to filter_projects_path(archived: 'only'), class: ("is-active" if params[:archived] == 'only') do
+ Show archived projects only
- if current_user
%li.divider
%li
diff --git a/app/workers/authorized_projects_worker.rb b/app/workers/authorized_projects_worker.rb
index 13207a8bc71..55d8d0c69d1 100644
--- a/app/workers/authorized_projects_worker.rb
+++ b/app/workers/authorized_projects_worker.rb
@@ -4,18 +4,45 @@ class AuthorizedProjectsWorker
# Schedules multiple jobs and waits for them to be completed.
def self.bulk_perform_and_wait(args_list)
- job_ids = bulk_perform_async(args_list)
+ # Short-circuit: it's more efficient to do small numbers of jobs inline
+ return bulk_perform_inline(args_list) if args_list.size <= 3
- Gitlab::JobWaiter.new(job_ids).wait
+ waiter = Gitlab::JobWaiter.new(args_list.size)
+
+ # Point all the bulk jobs at the same JobWaiter. Converts, [[1], [2], [3]]
+ # into [[1, "key"], [2, "key"], [3, "key"]]
+ waiting_args_list = args_list.map { |args| [*args, waiter.key] }
+ bulk_perform_async(waiting_args_list)
+
+ waiter.wait
end
+ # Schedules multiple jobs to run in sidekiq without waiting for completion
def self.bulk_perform_async(args_list)
Sidekiq::Client.push_bulk('class' => self, 'queue' => sidekiq_options['queue'], 'args' => args_list)
end
- def perform(user_id)
+ # Performs multiple jobs directly. Failed jobs will be put into sidekiq so
+ # they can benefit from retries
+ def self.bulk_perform_inline(args_list)
+ failed = []
+
+ args_list.each do |args|
+ begin
+ new.perform(*args)
+ rescue
+ failed << args
+ end
+ end
+
+ bulk_perform_async(failed) if failed.present?
+ end
+
+ def perform(user_id, notify_key = nil)
user = User.find_by(id: user_id)
user&.refresh_authorized_projects
+ ensure
+ Gitlab::JobWaiter.notify(notify_key, jid) if notify_key
end
end
diff --git a/app/workers/build_coverage_worker.rb b/app/workers/build_coverage_worker.rb
index f7ae996bb17..cd4af85d047 100644
--- a/app/workers/build_coverage_worker.rb
+++ b/app/workers/build_coverage_worker.rb
@@ -1,6 +1,6 @@
class BuildCoverageWorker
include Sidekiq::Worker
- include BuildQueue
+ include PipelineQueue
def perform(build_id)
Ci::Build.find_by(id: build_id)&.update_coverage
diff --git a/app/workers/build_finished_worker.rb b/app/workers/build_finished_worker.rb
index 466410bf08c..e2a1b3dcc41 100644
--- a/app/workers/build_finished_worker.rb
+++ b/app/workers/build_finished_worker.rb
@@ -1,6 +1,8 @@
class BuildFinishedWorker
include Sidekiq::Worker
- include BuildQueue
+ include PipelineQueue
+
+ enqueue_in group: :processing
def perform(build_id)
Ci::Build.find_by(id: build_id).try do |build|
diff --git a/app/workers/build_hooks_worker.rb b/app/workers/build_hooks_worker.rb
index 9965af935d4..dedaf2835e6 100644
--- a/app/workers/build_hooks_worker.rb
+++ b/app/workers/build_hooks_worker.rb
@@ -1,6 +1,8 @@
class BuildHooksWorker
include Sidekiq::Worker
- include BuildQueue
+ include PipelineQueue
+
+ enqueue_in group: :hooks
def perform(build_id)
Ci::Build.find_by(id: build_id)
diff --git a/app/workers/build_queue_worker.rb b/app/workers/build_queue_worker.rb
index fa9e097e40a..e5ceb9ef715 100644
--- a/app/workers/build_queue_worker.rb
+++ b/app/workers/build_queue_worker.rb
@@ -1,6 +1,8 @@
class BuildQueueWorker
include Sidekiq::Worker
- include BuildQueue
+ include PipelineQueue
+
+ enqueue_in group: :processing
def perform(build_id)
Ci::Build.find_by(id: build_id).try do |build|
diff --git a/app/workers/build_success_worker.rb b/app/workers/build_success_worker.rb
index bf009dfab0f..20ec24bd18a 100644
--- a/app/workers/build_success_worker.rb
+++ b/app/workers/build_success_worker.rb
@@ -1,6 +1,8 @@
class BuildSuccessWorker
include Sidekiq::Worker
- include BuildQueue
+ include PipelineQueue
+
+ enqueue_in group: :processing
def perform(build_id)
Ci::Build.find_by(id: build_id).try do |build|
diff --git a/app/workers/concerns/build_queue.rb b/app/workers/concerns/build_queue.rb
deleted file mode 100644
index cf0ead40a8b..00000000000
--- a/app/workers/concerns/build_queue.rb
+++ /dev/null
@@ -1,8 +0,0 @@
-# Concern for setting Sidekiq settings for the various CI build workers.
-module BuildQueue
- extend ActiveSupport::Concern
-
- included do
- sidekiq_options queue: :build
- end
-end
diff --git a/app/workers/concerns/exception_backtrace.rb b/app/workers/concerns/exception_backtrace.rb
new file mode 100644
index 00000000000..ea0f1f8d19b
--- /dev/null
+++ b/app/workers/concerns/exception_backtrace.rb
@@ -0,0 +1,8 @@
+# Concern for enabling a few lines of exception backtraces in Sidekiq
+module ExceptionBacktrace
+ extend ActiveSupport::Concern
+
+ included do
+ sidekiq_options backtrace: 5
+ end
+end
diff --git a/app/workers/concerns/pipeline_queue.rb b/app/workers/concerns/pipeline_queue.rb
index ca3860e1d38..ddf45b91345 100644
--- a/app/workers/concerns/pipeline_queue.rb
+++ b/app/workers/concerns/pipeline_queue.rb
@@ -1,8 +1,18 @@
+##
# Concern for setting Sidekiq settings for the various CI pipeline workers.
+#
module PipelineQueue
extend ActiveSupport::Concern
included do
- sidekiq_options queue: :pipeline
+ sidekiq_options queue: 'pipeline_default'
+ end
+
+ class_methods do
+ def enqueue_in(group:)
+ raise ArgumentError, 'Unspecified queue group!' if group.empty?
+
+ sidekiq_options queue: "pipeline_#{group}"
+ end
end
end
diff --git a/app/workers/expire_job_cache_worker.rb b/app/workers/expire_job_cache_worker.rb
index e383202260d..98a7500bffe 100644
--- a/app/workers/expire_job_cache_worker.rb
+++ b/app/workers/expire_job_cache_worker.rb
@@ -1,6 +1,8 @@
class ExpireJobCacheWorker
include Sidekiq::Worker
- include BuildQueue
+ include PipelineQueue
+
+ enqueue_in group: :cache
def perform(job_id)
job = CommitStatus.joins(:pipeline, :project).find_by(id: job_id)
diff --git a/app/workers/expire_pipeline_cache_worker.rb b/app/workers/expire_pipeline_cache_worker.rb
index 7c02d6cf892..1a0e7f92875 100644
--- a/app/workers/expire_pipeline_cache_worker.rb
+++ b/app/workers/expire_pipeline_cache_worker.rb
@@ -2,6 +2,8 @@ class ExpirePipelineCacheWorker
include Sidekiq::Worker
include PipelineQueue
+ enqueue_in group: :cache
+
def perform(pipeline_id)
pipeline = Ci::Pipeline.find_by(id: pipeline_id)
return unless pipeline
diff --git a/app/workers/group_destroy_worker.rb b/app/workers/group_destroy_worker.rb
index 07e82767b06..bd8e212e928 100644
--- a/app/workers/group_destroy_worker.rb
+++ b/app/workers/group_destroy_worker.rb
@@ -1,6 +1,7 @@
class GroupDestroyWorker
include Sidekiq::Worker
include DedicatedSidekiqQueue
+ include ExceptionBacktrace
def perform(group_id, user_id)
begin
diff --git a/app/workers/merge_worker.rb b/app/workers/merge_worker.rb
index c3b58df92c1..48e2da338f6 100644
--- a/app/workers/merge_worker.rb
+++ b/app/workers/merge_worker.rb
@@ -7,8 +7,6 @@ class MergeWorker
current_user = User.find(current_user_id)
merge_request = MergeRequest.find(merge_request_id)
- merge_request.update_column(:merge_jid, jid)
-
MergeRequests::MergeService.new(merge_request.target_project, current_user, params)
.execute(merge_request)
end
diff --git a/app/workers/namespaceless_project_destroy_worker.rb b/app/workers/namespaceless_project_destroy_worker.rb
index a9073742ff7..f1cd1769421 100644
--- a/app/workers/namespaceless_project_destroy_worker.rb
+++ b/app/workers/namespaceless_project_destroy_worker.rb
@@ -7,6 +7,7 @@
class NamespacelessProjectDestroyWorker
include Sidekiq::Worker
include DedicatedSidekiqQueue
+ include ExceptionBacktrace
def self.bulk_perform_async(args_list)
Sidekiq::Client.push_bulk('class' => self, 'queue' => sidekiq_options['queue'], 'args' => args_list)
@@ -18,7 +19,8 @@ class NamespacelessProjectDestroyWorker
rescue ActiveRecord::RecordNotFound
return
end
- return unless project.namespace_id.nil? # Reject doing anything for projects that *do* have a namespace
+
+ return if project.namespace # Reject doing anything for projects that *do* have a namespace
project.team.truncate
diff --git a/app/workers/pipeline_hooks_worker.rb b/app/workers/pipeline_hooks_worker.rb
index 7e36eacebf8..30a75ec8435 100644
--- a/app/workers/pipeline_hooks_worker.rb
+++ b/app/workers/pipeline_hooks_worker.rb
@@ -2,6 +2,8 @@ class PipelineHooksWorker
include Sidekiq::Worker
include PipelineQueue
+ enqueue_in group: :hooks
+
def perform(pipeline_id)
Ci::Pipeline.find_by(id: pipeline_id)
.try(:execute_hooks)
diff --git a/app/workers/pipeline_process_worker.rb b/app/workers/pipeline_process_worker.rb
index 357e4a9a1c3..8c067d05081 100644
--- a/app/workers/pipeline_process_worker.rb
+++ b/app/workers/pipeline_process_worker.rb
@@ -2,6 +2,8 @@ class PipelineProcessWorker
include Sidekiq::Worker
include PipelineQueue
+ enqueue_in group: :processing
+
def perform(pipeline_id)
Ci::Pipeline.find_by(id: pipeline_id)
.try(:process!)
diff --git a/app/workers/pipeline_success_worker.rb b/app/workers/pipeline_success_worker.rb
index cc0eb708cf9..cb8bb2ffe75 100644
--- a/app/workers/pipeline_success_worker.rb
+++ b/app/workers/pipeline_success_worker.rb
@@ -2,6 +2,8 @@ class PipelineSuccessWorker
include Sidekiq::Worker
include PipelineQueue
+ enqueue_in group: :processing
+
def perform(pipeline_id)
Ci::Pipeline.find_by(id: pipeline_id).try do |pipeline|
MergeRequests::MergeWhenPipelineSucceedsService
diff --git a/app/workers/pipeline_update_worker.rb b/app/workers/pipeline_update_worker.rb
index 96c4152c674..5fa399dff4c 100644
--- a/app/workers/pipeline_update_worker.rb
+++ b/app/workers/pipeline_update_worker.rb
@@ -2,6 +2,8 @@ class PipelineUpdateWorker
include Sidekiq::Worker
include PipelineQueue
+ enqueue_in group: :processing
+
def perform(pipeline_id)
Ci::Pipeline.find_by(id: pipeline_id)
.try(:update_status)
diff --git a/app/workers/project_destroy_worker.rb b/app/workers/project_destroy_worker.rb
index a9188b78460..3be7e686609 100644
--- a/app/workers/project_destroy_worker.rb
+++ b/app/workers/project_destroy_worker.rb
@@ -1,6 +1,7 @@
class ProjectDestroyWorker
include Sidekiq::Worker
include DedicatedSidekiqQueue
+ include ExceptionBacktrace
def perform(project_id, user_id, params)
project = Project.find(project_id)
diff --git a/app/workers/project_export_worker.rb b/app/workers/project_export_worker.rb
index 6009aa1b191..f13ac9e5db2 100644
--- a/app/workers/project_export_worker.rb
+++ b/app/workers/project_export_worker.rb
@@ -1,6 +1,7 @@
class ProjectExportWorker
include Sidekiq::Worker
include DedicatedSidekiqQueue
+ include ExceptionBacktrace
sidekiq_options retry: 3
diff --git a/app/workers/repository_import_worker.rb b/app/workers/repository_import_worker.rb
index 2c2d1e8b91f..00a021abbdc 100644
--- a/app/workers/repository_import_worker.rb
+++ b/app/workers/repository_import_worker.rb
@@ -3,6 +3,7 @@ class RepositoryImportWorker
include Sidekiq::Worker
include DedicatedSidekiqQueue
+ include ExceptionBacktrace
sidekiq_options status_expiration: StuckImportJobsWorker::IMPORT_JOBS_EXPIRATION
diff --git a/app/workers/stage_update_worker.rb b/app/workers/stage_update_worker.rb
new file mode 100644
index 00000000000..c301cea5ad6
--- /dev/null
+++ b/app/workers/stage_update_worker.rb
@@ -0,0 +1,12 @@
+class StageUpdateWorker
+ include Sidekiq::Worker
+ include PipelineQueue
+
+ enqueue_in group: :processing
+
+ def perform(stage_id)
+ Ci::Stage.find_by(id: stage_id).try do |stage|
+ stage.update_status
+ end
+ end
+end
diff --git a/changelogs/unreleased/10085-stop-encoding-user-name.yml b/changelogs/unreleased/10085-stop-encoding-user-name.yml
deleted file mode 100644
index 8fab474e047..00000000000
--- a/changelogs/unreleased/10085-stop-encoding-user-name.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: "Insert user name directly without encoding"
-merge_request: 10085
-author: Nathan Neulinger <nneul@neulinger.org>
diff --git a/changelogs/unreleased/13247-api_project_events_target_iid.yml b/changelogs/unreleased/13247-api_project_events_target_iid.yml
deleted file mode 100644
index 08a31039f77..00000000000
--- a/changelogs/unreleased/13247-api_project_events_target_iid.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Expose target_iid in Events API
-merge_request: 13247
-author: sue445
diff --git a/changelogs/unreleased/13265-project_events_noteable_iid.yml b/changelogs/unreleased/13265-project_events_noteable_iid.yml
deleted file mode 100644
index 54d538bb548..00000000000
--- a/changelogs/unreleased/13265-project_events_noteable_iid.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Expose noteable_iid in Note
-merge_request: 13265
-author: sue445
diff --git a/changelogs/unreleased/1827-prevent-concurrent-editing-wiki.yml b/changelogs/unreleased/1827-prevent-concurrent-editing-wiki.yml
deleted file mode 100644
index c8c2bb3eb4c..00000000000
--- a/changelogs/unreleased/1827-prevent-concurrent-editing-wiki.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Alert the user if a Wiki page changed while they were editing it in order to prevent overwriting changes.
-merge_request: 9707
-author: Hiroyuki Sato
diff --git a/changelogs/unreleased/19629-remove-inactive-tokens-list.yml b/changelogs/unreleased/19629-remove-inactive-tokens-list.yml
deleted file mode 100644
index 414e3d49e29..00000000000
--- a/changelogs/unreleased/19629-remove-inactive-tokens-list.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Remove Inactive Personal Access Tokens list from Access Tokens page
-merge_request: 12866
-author:
diff --git a/changelogs/unreleased/20817-please-add-coordinator-url-to-admin-area-runner-page.yml b/changelogs/unreleased/20817-please-add-coordinator-url-to-admin-area-runner-page.yml
deleted file mode 100644
index c4c3fc7ceb2..00000000000
--- a/changelogs/unreleased/20817-please-add-coordinator-url-to-admin-area-runner-page.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Add coordinator url to admin area runner page
-merge_request: 11603
-author:
diff --git a/changelogs/unreleased/22600-related-resources-uris-using-grape-source-helpers.yml b/changelogs/unreleased/22600-related-resources-uris-using-grape-source-helpers.yml
deleted file mode 100644
index 837a34bd067..00000000000
--- a/changelogs/unreleased/22600-related-resources-uris-using-grape-source-helpers.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Declare related resources into V4 API entities
-merge_request:
-author:
diff --git a/changelogs/unreleased/23036-replace-dashboard-event-filters-spinach.yml b/changelogs/unreleased/23036-replace-dashboard-event-filters-spinach.yml
deleted file mode 100644
index 807cd097178..00000000000
--- a/changelogs/unreleased/23036-replace-dashboard-event-filters-spinach.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Replaces dashboard/event_filters.feature spinach with rspec
-merge_request: 12651
-author: Alexander Randa (@randaalex)
diff --git a/changelogs/unreleased/23036-replace-dashboard-spinach.yml b/changelogs/unreleased/23036-replace-dashboard-spinach.yml
deleted file mode 100644
index b3197c4cfa6..00000000000
--- a/changelogs/unreleased/23036-replace-dashboard-spinach.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Replaces dashboard/dashboard.feature spinach with rspec
-merge_request: 12876
-author: Alexander Randa (@randaalex)
diff --git a/changelogs/unreleased/26372-duplicate-issue-slash-command.yml b/changelogs/unreleased/26372-duplicate-issue-slash-command.yml
deleted file mode 100644
index 3108344e0bf..00000000000
--- a/changelogs/unreleased/26372-duplicate-issue-slash-command.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Added /duplicate quick action to close a duplicate issue
-merge_request: 12845
-author: Ryan Scott
diff --git a/changelogs/unreleased/27616-fix-contributions-graph-utc-offset-mysql.yml b/changelogs/unreleased/27616-fix-contributions-graph-utc-offset-mysql.yml
deleted file mode 100644
index 1b3c3b8538d..00000000000
--- a/changelogs/unreleased/27616-fix-contributions-graph-utc-offset-mysql.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Fix timezone inconsistencies in user contribution graph
-merge_request: 13208
-author:
diff --git a/changelogs/unreleased/28202_decrease_abc_threshold_step2.yml b/changelogs/unreleased/28202_decrease_abc_threshold_step2.yml
deleted file mode 100644
index b8f30b52b18..00000000000
--- a/changelogs/unreleased/28202_decrease_abc_threshold_step2.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Decrease ABC threshold to 56.96
-merge_request: 11227
-author: Maxim Rydkin
diff --git a/changelogs/unreleased/28283-uuid-storage.yml b/changelogs/unreleased/28283-uuid-storage.yml
new file mode 100644
index 00000000000..283e06d4b7f
--- /dev/null
+++ b/changelogs/unreleased/28283-uuid-storage.yml
@@ -0,0 +1,4 @@
+---
+title: Hashed Storage support for Repositories (EXPERIMENTAL)
+merge_request: 13246
+author:
diff --git a/changelogs/unreleased/28472-ignore-auto-generated-mails.yml b/changelogs/unreleased/28472-ignore-auto-generated-mails.yml
deleted file mode 100644
index af63b43e62e..00000000000
--- a/changelogs/unreleased/28472-ignore-auto-generated-mails.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Don't send rejection mails for all auto-generated mails
-merge_request: 13254
-author:
diff --git a/changelogs/unreleased/29289-project-destroy-clean-up-after-failure.yml b/changelogs/unreleased/29289-project-destroy-clean-up-after-failure.yml
deleted file mode 100644
index 488b37ac37f..00000000000
--- a/changelogs/unreleased/29289-project-destroy-clean-up-after-failure.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Handle errors while a project is being deleted asynchronously.
-merge_request: 11088
-author:
diff --git a/changelogs/unreleased/29385-add_shrug_command.yml b/changelogs/unreleased/29385-add_shrug_command.yml
deleted file mode 100644
index 14b8f486d5c..00000000000
--- a/changelogs/unreleased/29385-add_shrug_command.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Add /shrug and /tableflip commands
-merge_request: 10068
-author: Alex Ives
diff --git a/changelogs/unreleased/29901-refactor-initialization-dropzone_input-js.yml b/changelogs/unreleased/29901-refactor-initialization-dropzone_input-js.yml
deleted file mode 100644
index 8850422fc88..00000000000
--- a/changelogs/unreleased/29901-refactor-initialization-dropzone_input-js.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: refactor initializations in dropzone_input.js
-merge_request: 12768
-author: Brandon Everett
diff --git a/changelogs/unreleased/30634-protected-pipeline.yml b/changelogs/unreleased/30634-protected-pipeline.yml
deleted file mode 100644
index e46538e5b46..00000000000
--- a/changelogs/unreleased/30634-protected-pipeline.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Disallow running the pipeline if ref is protected and user cannot merge the
- branch or create the tag
-merge_request: 11910
-author:
diff --git a/changelogs/unreleased/31129-jira-project-key-elim.yml b/changelogs/unreleased/31129-jira-project-key-elim.yml
deleted file mode 100644
index bfa0e99f250..00000000000
--- a/changelogs/unreleased/31129-jira-project-key-elim.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Remove project_key from the Jira configuration
-merge_request: 12050
-author:
diff --git a/changelogs/unreleased/31207-clean-locked-merge-requests.yml b/changelogs/unreleased/31207-clean-locked-merge-requests.yml
deleted file mode 100644
index 1f52987baef..00000000000
--- a/changelogs/unreleased/31207-clean-locked-merge-requests.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Unlock stuck merge request and set the proper state
-merge_request: 13207
-author:
diff --git a/changelogs/unreleased/31409-fix-group-and-project-search-for-anonymous-users.yml b/changelogs/unreleased/31409-fix-group-and-project-search-for-anonymous-users.yml
new file mode 100644
index 00000000000..06e8180db64
--- /dev/null
+++ b/changelogs/unreleased/31409-fix-group-and-project-search-for-anonymous-users.yml
@@ -0,0 +1,5 @@
+---
+title: Fix group and project search for anonymous users
+merge_request: 13745
+author:
+type: fixed
diff --git a/changelogs/unreleased/31533-usage-data-projects-stats.yml b/changelogs/unreleased/31533-usage-data-projects-stats.yml
deleted file mode 100644
index 11bb6118337..00000000000
--- a/changelogs/unreleased/31533-usage-data-projects-stats.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Add Slack and JIRA services counts to Usage Data
-merge_request:
-author:
diff --git a/changelogs/unreleased/31571-don-t-let-webhooks-jobs-go-to-the-dead-jobs-queue.yml b/changelogs/unreleased/31571-don-t-let-webhooks-jobs-go-to-the-dead-jobs-queue.yml
deleted file mode 100644
index 69900f0b314..00000000000
--- a/changelogs/unreleased/31571-don-t-let-webhooks-jobs-go-to-the-dead-jobs-queue.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Prevent web hook and project service background jobs from going to the dead
- jobs queue
-merge_request:
-author:
diff --git a/changelogs/unreleased/32483-jira-error.yml b/changelogs/unreleased/32483-jira-error.yml
deleted file mode 100644
index 1c530ca5e0f..00000000000
--- a/changelogs/unreleased/32483-jira-error.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Display specific error message when JIRA test fails
-merge_request:
-author:
diff --git a/changelogs/unreleased/32844-issuables-performance.yml b/changelogs/unreleased/32844-issuables-performance.yml
deleted file mode 100644
index e9b21c1aa45..00000000000
--- a/changelogs/unreleased/32844-issuables-performance.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Move some code from services to workers in order to improve performance
-merge_request: 13326
-author:
diff --git a/changelogs/unreleased/33095-mr-widget-ui.yml b/changelogs/unreleased/33095-mr-widget-ui.yml
deleted file mode 100644
index 9ce3086df27..00000000000
--- a/changelogs/unreleased/33095-mr-widget-ui.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: clean up merge request widget UI
-merge_request:
-author:
diff --git a/changelogs/unreleased/33097-issue-tracker.yml b/changelogs/unreleased/33097-issue-tracker.yml
deleted file mode 100644
index 0b13f7165db..00000000000
--- a/changelogs/unreleased/33097-issue-tracker.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Associate Issues tab only with internal issues tracker
-merge_request:
-author:
diff --git a/changelogs/unreleased/33601-add-csrf-token-verification-to-api.yml b/changelogs/unreleased/33601-add-csrf-token-verification-to-api.yml
deleted file mode 100644
index 88cfb99a73e..00000000000
--- a/changelogs/unreleased/33601-add-csrf-token-verification-to-api.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Add CSRF token verification to API
-merge_request: 12154
-author: Vitaliy @blackst0ne Klachkov
diff --git a/changelogs/unreleased/33620-remove-events-from-notification_settings.yml b/changelogs/unreleased/33620-remove-events-from-notification_settings.yml
deleted file mode 100644
index f5f3ef3fb82..00000000000
--- a/changelogs/unreleased/33620-remove-events-from-notification_settings.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Remove events column from notification settings table
-merge_request:
-author:
diff --git a/changelogs/unreleased/33741-clarify-k8s-service-keys.yml b/changelogs/unreleased/33741-clarify-k8s-service-keys.yml
deleted file mode 100644
index 91142a0d580..00000000000
--- a/changelogs/unreleased/33741-clarify-k8s-service-keys.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Clarifies and rearranges the input variables on the kubernetes integration
- page and adjusts the docs slightly to meet the same order
-merge_request: !12188
-author:
diff --git a/changelogs/unreleased/33770-respect-blockquote-line-breaks.yml b/changelogs/unreleased/33770-respect-blockquote-line-breaks.yml
deleted file mode 100644
index 3a45ad88270..00000000000
--- a/changelogs/unreleased/33770-respect-blockquote-line-breaks.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Respect blockquote line breaks in markdown
-merge_request:
-author:
diff --git a/changelogs/unreleased/33874_confi.yml b/changelogs/unreleased/33874_confi.yml
deleted file mode 100644
index 940753d9aaa..00000000000
--- a/changelogs/unreleased/33874_confi.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Update confidential issue UI - add confidential visibility and settings to
- sidebar
-merge_request:
-author:
diff --git a/changelogs/unreleased/34027-add-icons-to-sidebar.yml b/changelogs/unreleased/34027-add-icons-to-sidebar.yml
deleted file mode 100644
index f5b50ca1dee..00000000000
--- a/changelogs/unreleased/34027-add-icons-to-sidebar.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Add icons to contextual sidebars
-merge_request:
-author:
diff --git a/changelogs/unreleased/34028-collapse-sidebar.yml b/changelogs/unreleased/34028-collapse-sidebar.yml
deleted file mode 100644
index 468212240ac..00000000000
--- a/changelogs/unreleased/34028-collapse-sidebar.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Make contextual sidebar collapsible
-merge_request:
-author:
diff --git a/changelogs/unreleased/34075-pipelines-count-mt.yml b/changelogs/unreleased/34075-pipelines-count-mt.yml
deleted file mode 100644
index 3846e7b06a4..00000000000
--- a/changelogs/unreleased/34075-pipelines-count-mt.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Update Pipeline's badge count in Merge Request and Commits view to match real-time
- content
-merge_request:
-author:
diff --git a/changelogs/unreleased/34110-memory-usage-notice-doesn-t-link-anywhere.yml b/changelogs/unreleased/34110-memory-usage-notice-doesn-t-link-anywhere.yml
deleted file mode 100644
index 1911705dd2b..00000000000
--- a/changelogs/unreleased/34110-memory-usage-notice-doesn-t-link-anywhere.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Added link to the MR widget that directs to the monitoring dashboard
-merge_request:
-author:
diff --git a/changelogs/unreleased/34339-user_avatar-url-in-push-event-webhook-json-payload-is-relative-should-be-absolute.yml b/changelogs/unreleased/34339-user_avatar-url-in-push-event-webhook-json-payload-is-relative-should-be-absolute.yml
deleted file mode 100644
index 13f28da8577..00000000000
--- a/changelogs/unreleased/34339-user_avatar-url-in-push-event-webhook-json-payload-is-relative-should-be-absolute.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Use full path of user's avatar in webhooks
-merge_request: 13401
-author: Vitaliy @blackst0ne Klachkov
diff --git a/changelogs/unreleased/34361-lazy-load-images-on-the-frontend.yml b/changelogs/unreleased/34361-lazy-load-images-on-the-frontend.yml
deleted file mode 100644
index d188a558d38..00000000000
--- a/changelogs/unreleased/34361-lazy-load-images-on-the-frontend.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Lazy load images for better Frontend performance
-merge_request: 12503
-author:
diff --git a/changelogs/unreleased/34413-move-convdev-index-location-to-after-cohorts.yml b/changelogs/unreleased/34413-move-convdev-index-location-to-after-cohorts.yml
new file mode 100644
index 00000000000..d33b55ef681
--- /dev/null
+++ b/changelogs/unreleased/34413-move-convdev-index-location-to-after-cohorts.yml
@@ -0,0 +1,4 @@
+---
+title: Move ConvDev Index location to after Cohorts.
+merge_request: !13398
+author:
diff --git a/changelogs/unreleased/34519-extend-api-group-secret-variable.yml b/changelogs/unreleased/34519-extend-api-group-secret-variable.yml
deleted file mode 100644
index e0b625c392f..00000000000
--- a/changelogs/unreleased/34519-extend-api-group-secret-variable.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Extend API for Group Secret Variable
-merge_request: 12936
-author:
diff --git a/changelogs/unreleased/34527-make-edit-comment-button-always-available-outside-of-dropdown.yml b/changelogs/unreleased/34527-make-edit-comment-button-always-available-outside-of-dropdown.yml
deleted file mode 100644
index 08171f6bcec..00000000000
--- a/changelogs/unreleased/34527-make-edit-comment-button-always-available-outside-of-dropdown.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: move edit comment button outside of dropdown
-merge_request:
-author:
diff --git a/changelogs/unreleased/34533-speed-up-group-project-authorizations.yml b/changelogs/unreleased/34533-speed-up-group-project-authorizations.yml
deleted file mode 100644
index ddaaf4a2507..00000000000
--- a/changelogs/unreleased/34533-speed-up-group-project-authorizations.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix timeouts when creating projects in groups with many members
-merge_request: 13508
-author:
-type: fixed
diff --git a/changelogs/unreleased/34534-update-vue-resource.yml b/changelogs/unreleased/34534-update-vue-resource.yml
deleted file mode 100644
index 2d0af0c9bfe..00000000000
--- a/changelogs/unreleased/34534-update-vue-resource.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Updates vue resource and code according to breaking changes
-merge_request:
-author:
diff --git a/changelogs/unreleased/34549-extract-devise-mappings-into-helper.yml b/changelogs/unreleased/34549-extract-devise-mappings-into-helper.yml
deleted file mode 100644
index e843bbac239..00000000000
--- a/changelogs/unreleased/34549-extract-devise-mappings-into-helper.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Extract "@request.env[devise.mapping] = Devise.mappings[:user]" to a test helper
-merge_request: 12742
-author: Jacopo Beschi @jacopo-beschi
diff --git a/changelogs/unreleased/34563-usage-ping-github.yml b/changelogs/unreleased/34563-usage-ping-github.yml
deleted file mode 100644
index 3ab982beea3..00000000000
--- a/changelogs/unreleased/34563-usage-ping-github.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Add GitHub imported projects count to usage data
-merge_request:
-author:
diff --git a/changelogs/unreleased/34764-rename-to-overview.yml b/changelogs/unreleased/34764-rename-to-overview.yml
deleted file mode 100644
index 5b9643285b7..00000000000
--- a/changelogs/unreleased/34764-rename-to-overview.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Rename about to overview for group and project page
-merge_request:
-author:
diff --git a/changelogs/unreleased/34810-vue-pagination.yml b/changelogs/unreleased/34810-vue-pagination.yml
deleted file mode 100644
index 5cd03518a98..00000000000
--- a/changelogs/unreleased/34810-vue-pagination.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Prevent disabled pagination button to be clicked
-merge_request:
-author:
diff --git a/changelogs/unreleased/34831-remove-coffee-rails-gem.yml b/changelogs/unreleased/34831-remove-coffee-rails-gem.yml
deleted file mode 100644
index b555f112b8d..00000000000
--- a/changelogs/unreleased/34831-remove-coffee-rails-gem.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Remove coffee-rails gem
-merge_request:
-author: Takuya Noguchi
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
deleted file mode 100644
index e6cd834aed2..00000000000
--- a/changelogs/unreleased/34858-bump-scss-lint-to-0-54-0.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-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
deleted file mode 100644
index f5648d62467..00000000000
--- a/changelogs/unreleased/34867-remove-net-ssh-gem.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Remove net-ssh gem
-merge_request:
-author: Takuya Noguchi
diff --git a/changelogs/unreleased/34869-bump-rubocop-to-0-49-1-and-rubocop-rspec-to-1-15-1.yml b/changelogs/unreleased/34869-bump-rubocop-to-0-49-1-and-rubocop-rspec-to-1-15-1.yml
deleted file mode 100644
index 0eb2d069719..00000000000
--- a/changelogs/unreleased/34869-bump-rubocop-to-0-49-1-and-rubocop-rspec-to-1-15-1.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Bump rubocop to 0.49.1 and rubocop-rspec to 1.15.1
-merge_request:
-author: Takuya Noguchi
diff --git a/changelogs/unreleased/34921-global-dropdown-ui-improvement.yml b/changelogs/unreleased/34921-global-dropdown-ui-improvement.yml
deleted file mode 100644
index 6a17353ba3f..00000000000
--- a/changelogs/unreleased/34921-global-dropdown-ui-improvement.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Improve CSS for global nav dropdown UI
-merge_request: 12772
-author: Takuya Noguchi
diff --git a/changelogs/unreleased/34927-protect-manual-actions-on-tags.yml b/changelogs/unreleased/34927-protect-manual-actions-on-tags.yml
deleted file mode 100644
index d996ae2826a..00000000000
--- a/changelogs/unreleased/34927-protect-manual-actions-on-tags.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Protect manual actions against protected tag too
-merge_request: 12908
-author:
diff --git a/changelogs/unreleased/34978-remove-public-ci-favicon-ico.yml b/changelogs/unreleased/34978-remove-public-ci-favicon-ico.yml
deleted file mode 100644
index 25cc8b5e45f..00000000000
--- a/changelogs/unreleased/34978-remove-public-ci-favicon-ico.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Remove public/ci/favicon.ico
-merge_request: 12803
-author: Takuya Noguchi
diff --git a/changelogs/unreleased/34990-top-buttons-misaligned.yml b/changelogs/unreleased/34990-top-buttons-misaligned.yml
new file mode 100644
index 00000000000..db60f83ed71
--- /dev/null
+++ b/changelogs/unreleased/34990-top-buttons-misaligned.yml
@@ -0,0 +1,5 @@
+---
+title: Fixes margins on the top buttons of the pipeline table
+merge_request:
+author:
+type: fixed
diff --git a/changelogs/unreleased/35044-projects-logo-are-not-centered-vertically-on-projects-page.yml b/changelogs/unreleased/35044-projects-logo-are-not-centered-vertically-on-projects-page.yml
deleted file mode 100644
index 9de4dbefd35..00000000000
--- a/changelogs/unreleased/35044-projects-logo-are-not-centered-vertically-on-projects-page.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Fix project logos that are not centered vertically on list pages
-merge_request: 13124
-author: Florian Lemaitre
diff --git a/changelogs/unreleased/35048-empty-badges.yml b/changelogs/unreleased/35048-empty-badges.yml
new file mode 100644
index 00000000000..816fe82887c
--- /dev/null
+++ b/changelogs/unreleased/35048-empty-badges.yml
@@ -0,0 +1,5 @@
+---
+title: Prevents rendering empty badges when request fails
+merge_request:
+author:
+type: fixed
diff --git a/changelogs/unreleased/35072-fix-pages-delete.yml b/changelogs/unreleased/35072-fix-pages-delete.yml
deleted file mode 100644
index 21af2bde201..00000000000
--- a/changelogs/unreleased/35072-fix-pages-delete.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix deleting GitLab Pages files when a project is removed
-merge_request: 13631
-author:
-type: fixed
diff --git a/changelogs/unreleased/35098-raise-encoding-confidence-threshold.yml b/changelogs/unreleased/35098-raise-encoding-confidence-threshold.yml
deleted file mode 100644
index 3cdb3011f5b..00000000000
--- a/changelogs/unreleased/35098-raise-encoding-confidence-threshold.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Raise guessed encoding confidence threshold to 50
-merge_request: 12990
-author:
diff --git a/changelogs/unreleased/35136-barchart-not-display-label-at-0-hour.yml b/changelogs/unreleased/35136-barchart-not-display-label-at-0-hour.yml
deleted file mode 100644
index ea8f31cca9d..00000000000
--- a/changelogs/unreleased/35136-barchart-not-display-label-at-0-hour.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Fix bar chart does not display label at 0 hour
-merge_request: 35136
-author: Jason Dai
diff --git a/changelogs/unreleased/35155-upgrade-fog-core-to-1-44-3-and-its-providers-to-the-latest.yml b/changelogs/unreleased/35155-upgrade-fog-core-to-1-44-3-and-its-providers-to-the-latest.yml
deleted file mode 100644
index 9d9558347ba..00000000000
--- a/changelogs/unreleased/35155-upgrade-fog-core-to-1-44-3-and-its-providers-to-the-latest.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Bump fog-core to 1.44.3 and fog providers' plugins to latest
-merge_request: 12897
-author: Takuya Noguchi
diff --git a/changelogs/unreleased/35163-url-in-commit-message-can-be-broken-in-blame.yml b/changelogs/unreleased/35163-url-in-commit-message-can-be-broken-in-blame.yml
deleted file mode 100644
index 4fd60a79782..00000000000
--- a/changelogs/unreleased/35163-url-in-commit-message-can-be-broken-in-blame.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Use only CSS to truncate commit message in blame
-merge_request: 12900
-author: Takuya Noguchi
diff --git a/changelogs/unreleased/35164-cycle-analytics-firefox.yml b/changelogs/unreleased/35164-cycle-analytics-firefox.yml
deleted file mode 100644
index 0b7115136ca..00000000000
--- a/changelogs/unreleased/35164-cycle-analytics-firefox.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: allow closing Cycle Analytics intro box in firefox
-merge_request:
-author:
diff --git a/changelogs/unreleased/35181-cannot-create-label-from-board-page.yml b/changelogs/unreleased/35181-cannot-create-label-from-board-page.yml
deleted file mode 100644
index 4afe603720d..00000000000
--- a/changelogs/unreleased/35181-cannot-create-label-from-board-page.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Fix label creation from new list for subgroup projects
-merge_request:
-author:
diff --git a/changelogs/unreleased/35191-prioritized-labels-for-non-member.yml b/changelogs/unreleased/35191-prioritized-labels-for-non-member.yml
deleted file mode 100644
index fbe55d4c2b0..00000000000
--- a/changelogs/unreleased/35191-prioritized-labels-for-non-member.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Remove help message about prioritized labels for non-members
-merge_request: 12912
-author: Takuya Noguchi
diff --git a/changelogs/unreleased/35204-doc-api-ci-lint-typo.yml b/changelogs/unreleased/35204-doc-api-ci-lint-typo.yml
deleted file mode 100644
index 45b6c57579b..00000000000
--- a/changelogs/unreleased/35204-doc-api-ci-lint-typo.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Add link to doc/api/ci/lint.md
-merge_request: 12914
-author: Takuya Noguchi
diff --git a/changelogs/unreleased/35225-transient-poll.yml b/changelogs/unreleased/35225-transient-poll.yml
deleted file mode 100644
index 59e2e738c7b..00000000000
--- a/changelogs/unreleased/35225-transient-poll.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: fix transient js error in rspec tests
-merge_request:
-author:
diff --git a/changelogs/unreleased/35253-desc-protected-branches-for-non-member.yml b/changelogs/unreleased/35253-desc-protected-branches-for-non-member.yml
deleted file mode 100644
index 9b2a66da1c3..00000000000
--- a/changelogs/unreleased/35253-desc-protected-branches-for-non-member.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Hide description about protected branches to non-member
-merge_request: 12945
-author: Takuya Noguchi
diff --git a/changelogs/unreleased/35343-inherit-milestones-and-labels.yml b/changelogs/unreleased/35343-inherit-milestones-and-labels.yml
new file mode 100644
index 00000000000..ce737a67356
--- /dev/null
+++ b/changelogs/unreleased/35343-inherit-milestones-and-labels.yml
@@ -0,0 +1,5 @@
+---
+title: inherits milestone and labels when a merge request is created from issue
+merge_request: 13461
+author: haseebeqx
+type: added
diff --git a/changelogs/unreleased/35391-fix-star-i18n-in-js.yml b/changelogs/unreleased/35391-fix-star-i18n-in-js.yml
deleted file mode 100644
index a6fd4dc89fd..00000000000
--- a/changelogs/unreleased/35391-fix-star-i18n-in-js.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Fix translations for Star/Unstar in JS file
-merge_request:
-author:
diff --git a/changelogs/unreleased/35408-group-auto-avatars.yml b/changelogs/unreleased/35408-group-auto-avatars.yml
deleted file mode 100644
index 77b644a7f94..00000000000
--- a/changelogs/unreleased/35408-group-auto-avatars.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Show auto-generated avatars for Groups without avatars
-merge_request: 13188
-author:
diff --git a/changelogs/unreleased/35483-improve-mobile-sidebar.yml b/changelogs/unreleased/35483-improve-mobile-sidebar.yml
deleted file mode 100644
index eb3dab1da9e..00000000000
--- a/changelogs/unreleased/35483-improve-mobile-sidebar.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Improve mobile sidebar
-merge_request:
-author:
diff --git a/changelogs/unreleased/35659-rename-pipeline.yml b/changelogs/unreleased/35659-rename-pipeline.yml
deleted file mode 100644
index 0fe211868e4..00000000000
--- a/changelogs/unreleased/35659-rename-pipeline.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Rename Pipelines tab to CI / CD in new navigation
-merge_request:
-author:
diff --git a/changelogs/unreleased/35695-comment-appears-in-a-wrong-place-after-changing-diff-view-to-inline.yml b/changelogs/unreleased/35695-comment-appears-in-a-wrong-place-after-changing-diff-view-to-inline.yml
deleted file mode 100644
index 1c9ad20bc95..00000000000
--- a/changelogs/unreleased/35695-comment-appears-in-a-wrong-place-after-changing-diff-view-to-inline.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Fix display of new diff comments after changing b between diff views
-merge_request:
-author:
diff --git a/changelogs/unreleased/35721-auth-style-confirmation.yml b/changelogs/unreleased/35721-auth-style-confirmation.yml
new file mode 100644
index 00000000000..9963f76e845
--- /dev/null
+++ b/changelogs/unreleased/35721-auth-style-confirmation.yml
@@ -0,0 +1,5 @@
+---
+title: restyling of OAuth authorization confirmation
+merge_request:
+author: Jacopo Beschi @jacopo-beschi
+type: changed
diff --git a/changelogs/unreleased/35761-convdev-perc.yml b/changelogs/unreleased/35761-convdev-perc.yml
deleted file mode 100644
index 319c4d18219..00000000000
--- a/changelogs/unreleased/35761-convdev-perc.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Store & use ConvDev percentages returned by the Version app
-merge_request:
-author:
diff --git a/changelogs/unreleased/35769-fix-ruby-2-4-compatibility.yml b/changelogs/unreleased/35769-fix-ruby-2-4-compatibility.yml
deleted file mode 100644
index ac480993d85..00000000000
--- a/changelogs/unreleased/35769-fix-ruby-2-4-compatibility.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Fix Issue board when using Ruby 2.4
-merge_request: 13220
-author:
diff --git a/changelogs/unreleased/35793_fix_predicate_names.yml b/changelogs/unreleased/35793_fix_predicate_names.yml
new file mode 100644
index 00000000000..d4da177dc2e
--- /dev/null
+++ b/changelogs/unreleased/35793_fix_predicate_names.yml
@@ -0,0 +1,5 @@
+---
+title: Remove `is_` prefix from predicate method names
+merge_request: 13810
+author: Maxim Rydkin
+type: other
diff --git a/changelogs/unreleased/35811-copy-link-note.yml b/changelogs/unreleased/35811-copy-link-note.yml
new file mode 100644
index 00000000000..9fa74884c8a
--- /dev/null
+++ b/changelogs/unreleased/35811-copy-link-note.yml
@@ -0,0 +1,5 @@
+---
+title: Add support for copying permalink to notes via more actions dropdown
+merge_request: 13299
+author:
+type: added
diff --git a/changelogs/unreleased/35815-webhook-log-encoding-error.yml b/changelogs/unreleased/35815-webhook-log-encoding-error.yml
deleted file mode 100644
index 76ec235086c..00000000000
--- a/changelogs/unreleased/35815-webhook-log-encoding-error.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Fix encoding error for WebHook logging
-merge_request: 13230
-author: Alexander Randa (@randaalex)
diff --git a/changelogs/unreleased/35845-improve-subgroup-creation-permissions.yml b/changelogs/unreleased/35845-improve-subgroup-creation-permissions.yml
new file mode 100644
index 00000000000..eac8dbe23c2
--- /dev/null
+++ b/changelogs/unreleased/35845-improve-subgroup-creation-permissions.yml
@@ -0,0 +1,5 @@
+---
+title: Improves subgroup creation permissions
+merge_request: 13418
+author:
+type: bugifx
diff --git a/changelogs/unreleased/35994-archived-projects-only.yml b/changelogs/unreleased/35994-archived-projects-only.yml
new file mode 100644
index 00000000000..ce565b177d0
--- /dev/null
+++ b/changelogs/unreleased/35994-archived-projects-only.yml
@@ -0,0 +1,5 @@
+---
+title: Add an option to list only archived projects
+merge_request: 13492
+author: Mehdi Lahmam (@mehlah)
+type: added
diff --git a/changelogs/unreleased/36061-mr-ref.yml b/changelogs/unreleased/36061-mr-ref.yml
new file mode 100644
index 00000000000..039666070a7
--- /dev/null
+++ b/changelogs/unreleased/36061-mr-ref.yml
@@ -0,0 +1,5 @@
+---
+title: Instrument MergeRequest#ensure_ref_fetched
+merge_request:
+author:
+type: other
diff --git a/changelogs/unreleased/36114-stuck-mrs-job-follow-up.yml b/changelogs/unreleased/36114-stuck-mrs-job-follow-up.yml
new file mode 100644
index 00000000000..1b664efb8c2
--- /dev/null
+++ b/changelogs/unreleased/36114-stuck-mrs-job-follow-up.yml
@@ -0,0 +1,4 @@
+---
+title: Present enqueued merge jobs as Merging as well
+merge_request:
+author:
diff --git a/changelogs/unreleased/36185-or-separator.yml b/changelogs/unreleased/36185-or-separator.yml
deleted file mode 100644
index 4e46e60ea1b..00000000000
--- a/changelogs/unreleased/36185-or-separator.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Align OR separator to center in new project page
-merge_request:
-author:
diff --git a/changelogs/unreleased/36262_merge_request_reference_in_merge_commit_global.yml b/changelogs/unreleased/36262_merge_request_reference_in_merge_commit_global.yml
new file mode 100644
index 00000000000..356857d6e8a
--- /dev/null
+++ b/changelogs/unreleased/36262_merge_request_reference_in_merge_commit_global.yml
@@ -0,0 +1,5 @@
+---
+title: Merge request reference in merge commit changed to full reference
+merge_request: 13518
+author: haseebeqx
+type: fixed
diff --git a/changelogs/unreleased/36582-fix-note-resolved-icon.yml b/changelogs/unreleased/36582-fix-note-resolved-icon.yml
new file mode 100644
index 00000000000..758c0ecd212
--- /dev/null
+++ b/changelogs/unreleased/36582-fix-note-resolved-icon.yml
@@ -0,0 +1,5 @@
+---
+title: Update and fix resolvable note icons for easier recognition
+merge_request:
+author:
+type: changed
diff --git a/changelogs/unreleased/36792-inline-user-refresh-when-creating-project.yml b/changelogs/unreleased/36792-inline-user-refresh-when-creating-project.yml
new file mode 100644
index 00000000000..be08da0433a
--- /dev/null
+++ b/changelogs/unreleased/36792-inline-user-refresh-when-creating-project.yml
@@ -0,0 +1,5 @@
+---
+title: Never wait for sidekiq jobs when creating projects
+merge_request: 13775
+author:
+type: other
diff --git a/changelogs/unreleased/36860-deleted-user-fix.yml b/changelogs/unreleased/36860-deleted-user-fix.yml
new file mode 100644
index 00000000000..79e75441134
--- /dev/null
+++ b/changelogs/unreleased/36860-deleted-user-fix.yml
@@ -0,0 +1,5 @@
+---
+title: Fix failure when issue is authored by a deleted user
+merge_request: 13807
+author:
+type: fixed
diff --git a/changelogs/unreleased/3686_make_tarball_download_url.yml b/changelogs/unreleased/3686_make_tarball_download_url.yml
deleted file mode 100644
index 4e75e52e3ac..00000000000
--- a/changelogs/unreleased/3686_make_tarball_download_url.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: repository archive download url now ends with selected file extension
-merge_request: 13178
-author: haseebeqx
diff --git a/changelogs/unreleased/36882-disable-gitlab-project-import-button-if-source-disabled.yml b/changelogs/unreleased/36882-disable-gitlab-project-import-button-if-source-disabled.yml
new file mode 100644
index 00000000000..a06c84c30e6
--- /dev/null
+++ b/changelogs/unreleased/36882-disable-gitlab-project-import-button-if-source-disabled.yml
@@ -0,0 +1,5 @@
+---
+title: Disable GitLab Project Import Button if source disabled
+merge_request:
+author:
+type: fixed
diff --git a/changelogs/unreleased/36937-fix-invite-by-email-text.yml b/changelogs/unreleased/36937-fix-invite-by-email-text.yml
new file mode 100644
index 00000000000..06c6105fab6
--- /dev/null
+++ b/changelogs/unreleased/36937-fix-invite-by-email-text.yml
@@ -0,0 +1,5 @@
+---
+title: Fix invite by email address duplication
+merge_request:
+author:
+type: fixed
diff --git a/changelogs/unreleased/36939-fix-find-blobs-by-path.yml b/changelogs/unreleased/36939-fix-find-blobs-by-path.yml
new file mode 100644
index 00000000000..b48b10049ed
--- /dev/null
+++ b/changelogs/unreleased/36939-fix-find-blobs-by-path.yml
@@ -0,0 +1,5 @@
+---
+title: Fix searching for files by path
+merge_request: 13798
+author:
+type: fixed
diff --git a/changelogs/unreleased/37104-fix-graph-date-format.yml b/changelogs/unreleased/37104-fix-graph-date-format.yml
new file mode 100644
index 00000000000..f7d39fe8283
--- /dev/null
+++ b/changelogs/unreleased/37104-fix-graph-date-format.yml
@@ -0,0 +1,5 @@
+---
+title: Fix incorrect date/time formatting on prometheus graphs
+merge_request: 13865
+author:
+type: fixed
diff --git a/changelogs/unreleased/37147-fix-fallback-emoji-alignment.yml b/changelogs/unreleased/37147-fix-fallback-emoji-alignment.yml
new file mode 100644
index 00000000000..34161e63c81
--- /dev/null
+++ b/changelogs/unreleased/37147-fix-fallback-emoji-alignment.yml
@@ -0,0 +1,5 @@
+---
+title: Better align fallback image emojis
+merge_request:
+author:
+type: fixed
diff --git a/changelogs/unreleased/37198-api-doesn-t-respect-default-group-visibility.yml b/changelogs/unreleased/37198-api-doesn-t-respect-default-group-visibility.yml
new file mode 100644
index 00000000000..ef83dc1d10a
--- /dev/null
+++ b/changelogs/unreleased/37198-api-doesn-t-respect-default-group-visibility.yml
@@ -0,0 +1,5 @@
+---
+title: 'API: Respect default group visibility when creating a group'
+merge_request: 13903
+author: Robert Schilling
+type: fixed
diff --git a/changelogs/unreleased/5971-webhook-testing.yml b/changelogs/unreleased/5971-webhook-testing.yml
deleted file mode 100644
index 58233091977..00000000000
--- a/changelogs/unreleased/5971-webhook-testing.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Allow testing any events for project hooks and system hooks
-merge_request: 11728
-author: Alexander Randa (@randaalex)
diff --git a/changelogs/unreleased/add-filter-by-my-reaction.yml b/changelogs/unreleased/add-filter-by-my-reaction.yml
new file mode 100644
index 00000000000..dc1601cf3ee
--- /dev/null
+++ b/changelogs/unreleased/add-filter-by-my-reaction.yml
@@ -0,0 +1,4 @@
+---
+title: Add my reaction filter to search bar
+merge_request: 12962
+author: Hiroyuki Sato
diff --git a/changelogs/unreleased/add-filtered-search-group-issues-ce.yml b/changelogs/unreleased/add-filtered-search-group-issues-ce.yml
deleted file mode 100644
index f83f4173890..00000000000
--- a/changelogs/unreleased/add-filtered-search-group-issues-ce.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Add filtered search to group issue dashboard
-merge_request:
-author:
diff --git a/changelogs/unreleased/add-star-for-action-scope.yml b/changelogs/unreleased/add-star-for-action-scope.yml
deleted file mode 100644
index a8119a01ec4..00000000000
--- a/changelogs/unreleased/add-star-for-action-scope.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Add star for action scope, in order to delete image from registry
-merge_request: 13248
-author: jean
diff --git a/changelogs/unreleased/api-delete-respect-headers.yml b/changelogs/unreleased/api-delete-respect-headers.yml
new file mode 100644
index 00000000000..cfc8fbfdf91
--- /dev/null
+++ b/changelogs/unreleased/api-delete-respect-headers.yml
@@ -0,0 +1,5 @@
+---
+title: 'API: Respect the "If-Unmodified-Since" header when delting a resource'
+merge_request: 9621
+author: Robert Schilling
+type: added
diff --git a/changelogs/unreleased/appearances-caching-and-schema.yml b/changelogs/unreleased/appearances-caching-and-schema.yml
deleted file mode 100644
index 5743f6e0f2d..00000000000
--- a/changelogs/unreleased/appearances-caching-and-schema.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Cache Appearance instances in Redis
-merge_request:
-author:
diff --git a/changelogs/unreleased/artifacts-download-dropdown-menu-is-too-narrow.yml b/changelogs/unreleased/artifacts-download-dropdown-menu-is-too-narrow.yml
deleted file mode 100644
index 7d47c60e262..00000000000
--- a/changelogs/unreleased/artifacts-download-dropdown-menu-is-too-narrow.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Increase width of dropdown menus automatically
-merge_request: 12809
-author: Thomas Wucher
diff --git a/changelogs/unreleased/backstage-gb-after-save-asynchronous-job-hooks.yml b/changelogs/unreleased/backstage-gb-after-save-asynchronous-job-hooks.yml
new file mode 100644
index 00000000000..fd0b7c4f43c
--- /dev/null
+++ b/changelogs/unreleased/backstage-gb-after-save-asynchronous-job-hooks.yml
@@ -0,0 +1,5 @@
+---
+title: Fire hooks asynchronously when creating a new job to improve performance
+merge_request: 13734
+author:
+type: changed
diff --git a/changelogs/unreleased/breadcrumbs-collapsed-title-width-fix.yml b/changelogs/unreleased/breadcrumbs-collapsed-title-width-fix.yml
deleted file mode 100644
index 988fdacb5fd..00000000000
--- a/changelogs/unreleased/breadcrumbs-collapsed-title-width-fix.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Fixed breadcrumbs title aggressively collapsing
-merge_request:
-author:
diff --git a/changelogs/unreleased/broadcast-messages-cache.yml b/changelogs/unreleased/broadcast-messages-cache.yml
deleted file mode 100644
index a3c9e1ff465..00000000000
--- a/changelogs/unreleased/broadcast-messages-cache.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Better caching and indexing of broadcast messages
-merge_request:
-author:
diff --git a/changelogs/unreleased/bugfix-notify-custom-participants.yml b/changelogs/unreleased/bugfix-notify-custom-participants.yml
new file mode 100644
index 00000000000..04fcb95e18a
--- /dev/null
+++ b/changelogs/unreleased/bugfix-notify-custom-participants.yml
@@ -0,0 +1,5 @@
+---
+title: Fixed: Notifications weren't sending to participating users with a `Custom` notification setting.
+merge_request: 13680
+author: jneen
+type: fixed
diff --git a/changelogs/unreleased/bump-omniauth-ldap-gem-version.yml b/changelogs/unreleased/bump-omniauth-ldap-gem-version.yml
deleted file mode 100644
index 42e1c9e8f83..00000000000
--- a/changelogs/unreleased/bump-omniauth-ldap-gem-version.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Prevent LDAP login callback from being called with a GET request
-merge_request: 13059
-author:
diff --git a/changelogs/unreleased/bvl-add-all-settings-to-api.yml b/changelogs/unreleased/bvl-add-all-settings-to-api.yml
deleted file mode 100644
index bfaf237a21c..00000000000
--- a/changelogs/unreleased/bvl-add-all-settings-to-api.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Make all application-settings accessible through the API
-merge_request: 12851
-author:
diff --git a/changelogs/unreleased/bvl-free-unused-names.yml b/changelogs/unreleased/bvl-free-unused-names.yml
deleted file mode 100644
index 53acb95e5bb..00000000000
--- a/changelogs/unreleased/bvl-free-unused-names.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Free up some top level words, reject top level groups named like files in the
- public folder
-merge_request: 12932
-author:
diff --git a/changelogs/unreleased/bvl-improve-bare-project-import.yml b/changelogs/unreleased/bvl-improve-bare-project-import.yml
new file mode 100644
index 00000000000..74c1da4ea40
--- /dev/null
+++ b/changelogs/unreleased/bvl-improve-bare-project-import.yml
@@ -0,0 +1,6 @@
+---
+title: 'Improve bare project import: Allow subgroups, take default visibility level
+ into account'
+merge_request: 13670
+author:
+type: fixed
diff --git a/changelogs/unreleased/bvl-nfs-circuitbreaker.yml b/changelogs/unreleased/bvl-nfs-circuitbreaker.yml
deleted file mode 100644
index 151854ed31f..00000000000
--- a/changelogs/unreleased/bvl-nfs-circuitbreaker.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Block access to failing repository storage
-merge_request: 11449
-author:
diff --git a/changelogs/unreleased/bvl-rollback-renamed-system-namespace.yml b/changelogs/unreleased/bvl-rollback-renamed-system-namespace.yml
deleted file mode 100644
index a24cc7a1c43..00000000000
--- a/changelogs/unreleased/bvl-rollback-renamed-system-namespace.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Don't rename namespace called system when upgrading from 9.1.x to 9.5
-merge_request: 13228
-author:
diff --git a/changelogs/unreleased/cache-issue-and-mr-counts.yml b/changelogs/unreleased/cache-issue-and-mr-counts.yml
new file mode 100644
index 00000000000..fe3fe3be976
--- /dev/null
+++ b/changelogs/unreleased/cache-issue-and-mr-counts.yml
@@ -0,0 +1,5 @@
+---
+title: Cache the number of open issues and merge requests
+merge_request:
+author:
+type: other
diff --git a/changelogs/unreleased/changes-bar-sticky-fix.yml b/changelogs/unreleased/changes-bar-sticky-fix.yml
new file mode 100644
index 00000000000..7d62773ef7a
--- /dev/null
+++ b/changelogs/unreleased/changes-bar-sticky-fix.yml
@@ -0,0 +1,5 @@
+---
+title: Fixed diff changes bar buttons from showing/hiding whilst scrolling
+merge_request:
+author:
+type: fixed
diff --git a/changelogs/unreleased/commits-list-page-limit.yml b/changelogs/unreleased/commits-list-page-limit.yml
deleted file mode 100644
index 2fd54c5960a..00000000000
--- a/changelogs/unreleased/commits-list-page-limit.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix commit list not loading the correct page when scrolling
-merge_request:
-author:
-type: fixed
diff --git a/changelogs/unreleased/diff-changed-files-dropdown.yml b/changelogs/unreleased/diff-changed-files-dropdown.yml
deleted file mode 100644
index 2d2a26ffea2..00000000000
--- a/changelogs/unreleased/diff-changed-files-dropdown.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Moved diff changed files into a dropdown
-merge_request:
-author:
diff --git a/changelogs/unreleased/dm-large-push-performance.yml b/changelogs/unreleased/dm-large-push-performance.yml
deleted file mode 100644
index f5fe1bd3b28..00000000000
--- a/changelogs/unreleased/dm-large-push-performance.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Improve performance of large (initial) push into default branch
-merge_request:
-author:
diff --git a/changelogs/unreleased/docs-document-version-for-group-milestones-api.yml b/changelogs/unreleased/docs-document-version-for-group-milestones-api.yml
new file mode 100644
index 00000000000..d75c46313f4
--- /dev/null
+++ b/changelogs/unreleased/docs-document-version-for-group-milestones-api.yml
@@ -0,0 +1,5 @@
+---
+title: Document version Group Milestones API introduced
+merge_request:
+author:
+type: changed
diff --git a/changelogs/unreleased/docs-update-ci-docker-using-docker-images.yml b/changelogs/unreleased/docs-update-ci-docker-using-docker-images.yml
new file mode 100644
index 00000000000..d8a5073f110
--- /dev/null
+++ b/changelogs/unreleased/docs-update-ci-docker-using-docker-images.yml
@@ -0,0 +1,5 @@
+---
+title: Update 'Using Docker images' documentation
+merge_request: 13848
+author:
+type: other
diff --git a/changelogs/unreleased/dont-use-limit-offset-when-counting-projects.yml b/changelogs/unreleased/dont-use-limit-offset-when-counting-projects.yml
deleted file mode 100644
index 8ecea635ce5..00000000000
--- a/changelogs/unreleased/dont-use-limit-offset-when-counting-projects.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: "Improve performance of checking for projects on the projects dashboard"
-merge_request:
-author:
diff --git a/changelogs/unreleased/dz-fix-calendar-today.yml b/changelogs/unreleased/dz-fix-calendar-today.yml
deleted file mode 100644
index 5320d8b26b5..00000000000
--- a/changelogs/unreleased/dz-fix-calendar-today.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Fix today day highlight in calendar
-merge_request: 13048
-author:
diff --git a/changelogs/unreleased/eager-load-project-creators-for-project-dashboards.yml b/changelogs/unreleased/eager-load-project-creators-for-project-dashboards.yml
deleted file mode 100644
index e550e0b2f44..00000000000
--- a/changelogs/unreleased/eager-load-project-creators-for-project-dashboards.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Eager load project creators for project dashboards
-merge_request:
-author:
diff --git a/changelogs/unreleased/enable-scss-lint-bang-format.yml b/changelogs/unreleased/enable-scss-lint-bang-format.yml
deleted file mode 100644
index 0b73760198e..00000000000
--- a/changelogs/unreleased/enable-scss-lint-bang-format.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Enable BangFormat in scss-lint [ci skip]
-merge_request: 12815
-author: Takuya Noguchi
diff --git a/changelogs/unreleased/enable-scss-lint-declaration-order.yml b/changelogs/unreleased/enable-scss-lint-declaration-order.yml
deleted file mode 100644
index 7ac2f55592e..00000000000
--- a/changelogs/unreleased/enable-scss-lint-declaration-order.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Enable DeclarationOrder in scss-lint
-merge_request: 12805
-author: Takuya Noguchi
diff --git a/changelogs/unreleased/enable-scss-lint-import-path.yml b/changelogs/unreleased/enable-scss-lint-import-path.yml
deleted file mode 100644
index d158cf5b5f3..00000000000
--- a/changelogs/unreleased/enable-scss-lint-import-path.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-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
deleted file mode 100644
index c5a5a4dddb6..00000000000
--- a/changelogs/unreleased/enable-scss-lint-property-spelling.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-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
deleted file mode 100644
index 210f34fbb87..00000000000
--- a/changelogs/unreleased/enable-scss-lint-space-after-comma.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-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
deleted file mode 100644
index 59d5df56525..00000000000
--- a/changelogs/unreleased/enable-scss-lint-unnecessary-parent-reference.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Enable UnnecessaryParentReference in scss-lint
-merge_request: 12738
-author: Takuya Noguchi
diff --git a/changelogs/unreleased/ericy_ts-protected_branches_api.yml b/changelogs/unreleased/ericy_ts-protected_branches_api.yml
deleted file mode 100644
index 4cd275c5e8f..00000000000
--- a/changelogs/unreleased/ericy_ts-protected_branches_api.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Add API for protected branches to allow for wildcard matching and no access
- restrictions
-merge_request: 12756
-author: Eric Yu
diff --git a/changelogs/unreleased/feature-backup-custom-path.yml b/changelogs/unreleased/feature-backup-custom-path.yml
deleted file mode 100644
index 1c5f25b3ee5..00000000000
--- a/changelogs/unreleased/feature-backup-custom-path.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Support custom directory in gitlab:backup:create task
-merge_request: 12984
-author: Markus Koller
diff --git a/changelogs/unreleased/feature-gb-auto-retry-failed-ci-job.yml b/changelogs/unreleased/feature-gb-auto-retry-failed-ci-job.yml
deleted file mode 100644
index bdafc5929c0..00000000000
--- a/changelogs/unreleased/feature-gb-auto-retry-failed-ci-job.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Allow to configure automatic retry of a failed CI/CD job
-merge_request: 12909
-author:
diff --git a/changelogs/unreleased/feature-gpg-signed-commits.yml b/changelogs/unreleased/feature-gpg-signed-commits.yml
deleted file mode 100644
index 99bc5a309ef..00000000000
--- a/changelogs/unreleased/feature-gpg-signed-commits.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: GPG signed commits integration
-merge_request: 9546
-author: Alexis Reigel
diff --git a/changelogs/unreleased/fix-500-error-when-rendering-avatar-for-deleted-project-creator.yml b/changelogs/unreleased/fix-500-error-when-rendering-avatar-for-deleted-project-creator.yml
deleted file mode 100644
index be6f1ea00fb..00000000000
--- a/changelogs/unreleased/fix-500-error-when-rendering-avatar-for-deleted-project-creator.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Modify if condition to be more readable
-merge_request:
-author:
diff --git a/changelogs/unreleased/fix-gb-handle-max-pages-artifacts-size-correctly.yml b/changelogs/unreleased/fix-gb-handle-max-pages-artifacts-size-correctly.yml
deleted file mode 100644
index 3d9592bbf2a..00000000000
--- a/changelogs/unreleased/fix-gb-handle-max-pages-artifacts-size-correctly.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Handle maximum pages artifacts size correctly
-merge_request: 13072
-author:
diff --git a/changelogs/unreleased/fix-import-events.yml b/changelogs/unreleased/fix-import-events.yml
new file mode 100644
index 00000000000..84b4410a019
--- /dev/null
+++ b/changelogs/unreleased/fix-import-events.yml
@@ -0,0 +1,5 @@
+---
+title: Fix events error importing GitLab projects
+merge_request:
+author:
+type: fixed
diff --git a/changelogs/unreleased/fix-import-fork-mr.yml b/changelogs/unreleased/fix-import-fork-mr.yml
new file mode 100644
index 00000000000..4e9cf7faae8
--- /dev/null
+++ b/changelogs/unreleased/fix-import-fork-mr.yml
@@ -0,0 +1,5 @@
+---
+title: Fix Import/Export issue to do with fork merge requests
+merge_request:
+author:
+type: fixed
diff --git a/changelogs/unreleased/fix-import-symbolink-links.yml b/changelogs/unreleased/fix-import-symbolink-links.yml
deleted file mode 100644
index 36e73821bdc..00000000000
--- a/changelogs/unreleased/fix-import-symbolink-links.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Remove hidden symlinks from project import files
-merge_request:
-author:
diff --git a/changelogs/unreleased/fix-replying-to-commit-comment-in-mr-from-fork.yml b/changelogs/unreleased/fix-replying-to-commit-comment-in-mr-from-fork.yml
deleted file mode 100644
index f4136460626..00000000000
--- a/changelogs/unreleased/fix-replying-to-commit-comment-in-mr-from-fork.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Fix replying to commit comments on merge requests created from forks
-merge_request:
-author:
diff --git a/changelogs/unreleased/fix-sm-37040-regression-pipeline-trigger-via-api-fails-with-500-internal-server-error-in-9-5-1.yml b/changelogs/unreleased/fix-sm-37040-regression-pipeline-trigger-via-api-fails-with-500-internal-server-error-in-9-5-1.yml
new file mode 100644
index 00000000000..fb97bdb6b30
--- /dev/null
+++ b/changelogs/unreleased/fix-sm-37040-regression-pipeline-trigger-via-api-fails-with-500-internal-server-error-in-9-5-1.yml
@@ -0,0 +1,5 @@
+---
+title: Fix pipeline trigger via API fails with 500 Internal Server Error in 9.5
+merge_request:
+author:
+type: fixed
diff --git a/changelogs/unreleased/fix-thread-safe-gpgme-tmp-directory.yml b/changelogs/unreleased/fix-thread-safe-gpgme-tmp-directory.yml
deleted file mode 100644
index 66b5b6b4f47..00000000000
--- a/changelogs/unreleased/fix-thread-safe-gpgme-tmp-directory.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Make GPGME temporary directory handling thread safe
-merge_request: 13481
-author: Alexis Reigel
diff --git a/changelogs/unreleased/fixes-for-internal-auth-disabled.yml b/changelogs/unreleased/fixes-for-internal-auth-disabled.yml
deleted file mode 100644
index 188d2770455..00000000000
--- a/changelogs/unreleased/fixes-for-internal-auth-disabled.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Fixes needed when GitLab sign-in is not enabled
-merge_request: 12491
-author: Robin Bobbitt
diff --git a/changelogs/unreleased/font-weight-adjusted.yml b/changelogs/unreleased/font-weight-adjusted.yml
new file mode 100644
index 00000000000..827f3485099
--- /dev/null
+++ b/changelogs/unreleased/font-weight-adjusted.yml
@@ -0,0 +1,5 @@
+---
+title: Changed all font-weight values to 400 and 600 and introduced 2 variables to
+ manage them
+merge_request: !12896
+author:
diff --git a/changelogs/unreleased/forks-count-cache.yml b/changelogs/unreleased/forks-count-cache.yml
deleted file mode 100644
index da8c53c2abd..00000000000
--- a/changelogs/unreleased/forks-count-cache.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Cache the number of forks of a project
-merge_request: 13535
-author:
-type: other
diff --git a/changelogs/unreleased/gitaly_ref_exists.yml b/changelogs/unreleased/gitaly_ref_exists.yml
new file mode 100644
index 00000000000..f62b646e406
--- /dev/null
+++ b/changelogs/unreleased/gitaly_ref_exists.yml
@@ -0,0 +1,4 @@
+---
+title: Implement the Gitaly RefService::RefExists endpoint
+merge_request: 13528
+author: Andrew Newdigate
diff --git a/changelogs/unreleased/github.yml b/changelogs/unreleased/github.yml
deleted file mode 100644
index 585b9b13b65..00000000000
--- a/changelogs/unreleased/github.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Reduce memory usage of the GitHub importer
-merge_request: 12886
-author:
diff --git a/changelogs/unreleased/group-milestone-references-system-notes.yml b/changelogs/unreleased/group-milestone-references-system-notes.yml
deleted file mode 100644
index 58215352305..00000000000
--- a/changelogs/unreleased/group-milestone-references-system-notes.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Support Markdown references, autocomplete, and quick actions for group milestones
-merge_request:
-author:
diff --git a/changelogs/unreleased/group-mr-search-bar.yml b/changelogs/unreleased/group-mr-search-bar.yml
new file mode 100644
index 00000000000..0b554a5d7c9
--- /dev/null
+++ b/changelogs/unreleased/group-mr-search-bar.yml
@@ -0,0 +1,5 @@
+---
+title: Add filtered search to group merge requests dashboard
+merge_request: 13688
+author: Hiroyuki Sato
+type: changed
diff --git a/changelogs/unreleased/group-new-issue.yml b/changelogs/unreleased/group-new-issue.yml
deleted file mode 100644
index 5480a44526b..00000000000
--- a/changelogs/unreleased/group-new-issue.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Cache recent projects for group-level new resource creation.
-merge_request: !13058
-author:
diff --git a/changelogs/unreleased/handle-reserved-words-for-oauth-usernames.yml b/changelogs/unreleased/handle-reserved-words-for-oauth-usernames.yml
deleted file mode 100644
index 0d64844a2b8..00000000000
--- a/changelogs/unreleased/handle-reserved-words-for-oauth-usernames.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Uniquify reserved word usernames on OAuth user creation
-merge_request: 13244
-author: Robin Bobbitt
diff --git a/changelogs/unreleased/issue-boards-breadcrumbs-container.yml b/changelogs/unreleased/issue-boards-breadcrumbs-container.yml
new file mode 100644
index 00000000000..5e042de7000
--- /dev/null
+++ b/changelogs/unreleased/issue-boards-breadcrumbs-container.yml
@@ -0,0 +1,5 @@
+---
+title: Fix breadcrumbs container in issue boards
+merge_request:
+author:
+type: fixed
diff --git a/changelogs/unreleased/issue_31790.yml b/changelogs/unreleased/issue_31790.yml
deleted file mode 100644
index df02cad423a..00000000000
--- a/changelogs/unreleased/issue_31790.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Fix API responses when dealing with txt files
-merge_request:
-author:
diff --git a/changelogs/unreleased/issue_35580.yml b/changelogs/unreleased/issue_35580.yml
deleted file mode 100644
index 3a94e771e25..00000000000
--- a/changelogs/unreleased/issue_35580.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Fix project milestones import when projects belongs to a group
-merge_request:
-author:
diff --git a/changelogs/unreleased/memoize-user-personal-projects-count.yml b/changelogs/unreleased/memoize-user-personal-projects-count.yml
deleted file mode 100644
index 3839a97f185..00000000000
--- a/changelogs/unreleased/memoize-user-personal-projects-count.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Memoize the number of personal projects a user has to reduce COUNT queries
-merge_request:
-author:
diff --git a/changelogs/unreleased/merge-issuable-reopened-into-opened-state.yml b/changelogs/unreleased/merge-issuable-reopened-into-opened-state.yml
deleted file mode 100644
index 5d7af8971e5..00000000000
--- a/changelogs/unreleased/merge-issuable-reopened-into-opened-state.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Merge issuable "reopened" state into "opened"
-merge_request:
-author:
diff --git a/changelogs/unreleased/migrate-events-into-a-new-format.yml b/changelogs/unreleased/migrate-events-into-a-new-format.yml
deleted file mode 100644
index 8a29f75323f..00000000000
--- a/changelogs/unreleased/migrate-events-into-a-new-format.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Migrate events into a new format to reduce the storage necessary and improve performance
-merge_request:
-author:
diff --git a/changelogs/unreleased/mk-fix-user-namespace-rename.yml b/changelogs/unreleased/mk-fix-user-namespace-rename.yml
new file mode 100644
index 00000000000..bb43b21f708
--- /dev/null
+++ b/changelogs/unreleased/mk-fix-user-namespace-rename.yml
@@ -0,0 +1,5 @@
+---
+title: Make username update fail if the namespace update fails
+merge_request: 13642
+author:
+type: fixed
diff --git a/changelogs/unreleased/mk-fix-wiki-backup.yml b/changelogs/unreleased/mk-fix-wiki-backup.yml
deleted file mode 100644
index ba9c1e85955..00000000000
--- a/changelogs/unreleased/mk-fix-wiki-backup.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Fix improperly skipped backups of wikis.
-merge_request: 13096
-author:
diff --git a/changelogs/unreleased/mr-branch-link-use-tree.yml b/changelogs/unreleased/mr-branch-link-use-tree.yml
deleted file mode 100644
index f4c4d9f5082..00000000000
--- a/changelogs/unreleased/mr-branch-link-use-tree.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: MR branch link now links to tree instead of commits
-merge_request:
-author:
diff --git a/changelogs/unreleased/mr-index-eager-load.yml b/changelogs/unreleased/mr-index-eager-load.yml
new file mode 100644
index 00000000000..11c33055b17
--- /dev/null
+++ b/changelogs/unreleased/mr-index-eager-load.yml
@@ -0,0 +1,5 @@
+---
+title: Eager load head pipeline projects for MRs index
+merge_request:
+author:
+type: other
diff --git a/changelogs/unreleased/pagination-projects-explore.yml b/changelogs/unreleased/pagination-projects-explore.yml
deleted file mode 100644
index dc9c4218793..00000000000
--- a/changelogs/unreleased/pagination-projects-explore.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Use Prev/Next pagination for exploring projects
-merge_request:
-author:
diff --git a/changelogs/unreleased/pass-before-script-as-is.yml b/changelogs/unreleased/pass-before-script-as-is.yml
deleted file mode 100644
index ac6513dcff6..00000000000
--- a/changelogs/unreleased/pass-before-script-as-is.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Pass before_script and script as-is preserving arrays
-merge_request:
-author:
diff --git a/changelogs/unreleased/pawel-add-sidekiq-metrics-endpoint-32145.yml b/changelogs/unreleased/pawel-add-sidekiq-metrics-endpoint-32145.yml
deleted file mode 100644
index 71eabdc16d2..00000000000
--- a/changelogs/unreleased/pawel-add-sidekiq-metrics-endpoint-32145.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Add Prometheus metrics exporter to Sidekiq
-merge_request: 13082
-author:
diff --git a/changelogs/unreleased/pawel-add_more_variables_to_additional_metrics-35267.yml b/changelogs/unreleased/pawel-add_more_variables_to_additional_metrics-35267.yml
deleted file mode 100644
index c1e831306df..00000000000
--- a/changelogs/unreleased/pawel-add_more_variables_to_additional_metrics-35267.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Add support for kube_namespace in Metrics queries
-merge_request: 16169
-author:
diff --git a/changelogs/unreleased/post-upload-pack-opt-out.yml b/changelogs/unreleased/post-upload-pack-opt-out.yml
deleted file mode 100644
index 302a99795a0..00000000000
--- a/changelogs/unreleased/post-upload-pack-opt-out.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Enable gitaly_post_upload_pack by default
-merge_request: 13078
-author:
diff --git a/changelogs/unreleased/rc-fix-branches-api-endpoint.yml b/changelogs/unreleased/rc-fix-branches-api-endpoint.yml
deleted file mode 100644
index b36663bbe91..00000000000
--- a/changelogs/unreleased/rc-fix-branches-api-endpoint.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix the /projects/:id/repository/branches endpoint to handle dots in the branch
- name when the project full path contains a `/`
-merge_request: 13115
-author:
diff --git a/changelogs/unreleased/rc-fix-commits-api.yml b/changelogs/unreleased/rc-fix-commits-api.yml
deleted file mode 100644
index 215429eaf6b..00000000000
--- a/changelogs/unreleased/rc-fix-commits-api.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix the /projects/:id/repository/commits endpoint to handle dots in the ref
- name when the project full path contains a `/`
-merge_request: 13370
-author:
diff --git a/changelogs/unreleased/rc-fix-tags-api.yml b/changelogs/unreleased/rc-fix-tags-api.yml
deleted file mode 100644
index 0a7dd5ca6ab..00000000000
--- a/changelogs/unreleased/rc-fix-tags-api.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix the /projects/:id/repository/tags endpoint to handle dots in the tag name
- when the project full path contains a `/`
-merge_request: 13368
-author:
diff --git a/changelogs/unreleased/remove-nprogress-gleaning.yml b/changelogs/unreleased/remove-nprogress-gleaning.yml
deleted file mode 100644
index 78e4dc82dd4..00000000000
--- a/changelogs/unreleased/remove-nprogress-gleaning.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Remove CSS for nprogress removed
-merge_request: 12737
-author: Takuya Noguchi
diff --git a/changelogs/unreleased/remove-redundant-query-when-retrieving-recent-pushes.yml b/changelogs/unreleased/remove-redundant-query-when-retrieving-recent-pushes.yml
deleted file mode 100644
index 83934217e6a..00000000000
--- a/changelogs/unreleased/remove-redundant-query-when-retrieving-recent-pushes.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Remove redundant query when retrieving the most recent push of a user
-merge_request:
-author:
diff --git a/changelogs/unreleased/reorganise-issues-indexes-for-sorting.yml b/changelogs/unreleased/reorganise-issues-indexes-for-sorting.yml
deleted file mode 100644
index 5bfe55e562f..00000000000
--- a/changelogs/unreleased/reorganise-issues-indexes-for-sorting.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Re-organise "issues" indexes for faster ordering
-merge_request:
-author:
diff --git a/changelogs/unreleased/replace_spinach_search_code-feature.yml b/changelogs/unreleased/replace_spinach_search_code-feature.yml
new file mode 100644
index 00000000000..28d2108c871
--- /dev/null
+++ b/changelogs/unreleased/replace_spinach_search_code-feature.yml
@@ -0,0 +1,5 @@
+---
+title: Replace 'source/search_code.feature' spinach test with an rspec analog
+merge_request: 13697
+author: blackst0ne
+type: other
diff --git a/changelogs/unreleased/replace_spinach_spec_browse_files.yml b/changelogs/unreleased/replace_spinach_spec_browse_files.yml
deleted file mode 100644
index 7380d39fa9f..00000000000
--- a/changelogs/unreleased/replace_spinach_spec_browse_files.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Replace 'browse_files.feature' spinach test with an rspec analog
-merge_request: 12251
-author: @blackst0ne
diff --git a/changelogs/unreleased/replace_spinach_star-feature.yml b/changelogs/unreleased/replace_spinach_star-feature.yml
new file mode 100644
index 00000000000..6a058691fe5
--- /dev/null
+++ b/changelogs/unreleased/replace_spinach_star-feature.yml
@@ -0,0 +1,5 @@
+---
+title: Replace 'project/star.feature' spinach test with an rspec analog
+merge_request: 13855
+author: Vitaliy @blackst0ne Klachkov
+type: other
diff --git a/changelogs/unreleased/request-store-wrap.yml b/changelogs/unreleased/request-store-wrap.yml
deleted file mode 100644
index 8017054b77b..00000000000
--- a/changelogs/unreleased/request-store-wrap.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Add RequestCache which makes caching with RequestStore easier
-merge_request: 12920
-author:
diff --git a/changelogs/unreleased/restrict-haml-javascript.yml b/changelogs/unreleased/restrict-haml-javascript.yml
deleted file mode 100644
index 3d0a52f416d..00000000000
--- a/changelogs/unreleased/restrict-haml-javascript.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Add custom linter for inline JavaScript to haml_lint
-merge_request: 9742
-author: winniehell
diff --git a/changelogs/unreleased/revert-appearances-description-html-not-null.yml b/changelogs/unreleased/revert-appearances-description-html-not-null.yml
new file mode 100644
index 00000000000..4e3c39cb5fd
--- /dev/null
+++ b/changelogs/unreleased/revert-appearances-description-html-not-null.yml
@@ -0,0 +1,5 @@
+---
+title: Re-allow appearances.description_html to be NULL
+merge_request:
+author:
+type: fixed
diff --git a/changelogs/unreleased/rouge-2-2-0.yml b/changelogs/unreleased/rouge-2-2-0.yml
new file mode 100644
index 00000000000..0b53cd14628
--- /dev/null
+++ b/changelogs/unreleased/rouge-2-2-0.yml
@@ -0,0 +1,5 @@
+---
+title: Bump rouge to v2.2.0
+merge_request: 13633
+author:
+type: other
diff --git a/changelogs/unreleased/rs-alphanumeric-ssh-params.yml b/changelogs/unreleased/rs-alphanumeric-ssh-params.yml
deleted file mode 100644
index 426b01cafad..00000000000
--- a/changelogs/unreleased/rs-alphanumeric-ssh-params.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Disallow Git URLs that include a username or hostname beginning with a non-alphanumeric
- character
-merge_request:
-author:
diff --git a/changelogs/unreleased/sh-structured-logging.yml b/changelogs/unreleased/sh-structured-logging.yml
deleted file mode 100644
index d89eb93f689..00000000000
--- a/changelogs/unreleased/sh-structured-logging.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Add structured logging for Rails processes
-merge_request:
-author:
diff --git a/changelogs/unreleased/skip-oauth-authorization-for-trusted-applications.yml b/changelogs/unreleased/skip-oauth-authorization-for-trusted-applications.yml
deleted file mode 100644
index 7b4ae355978..00000000000
--- a/changelogs/unreleased/skip-oauth-authorization-for-trusted-applications.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Skip oAuth authorization for trusted applications
-merge_request:
-author:
diff --git a/changelogs/unreleased/tc-api-root-merge-requests.yml b/changelogs/unreleased/tc-api-root-merge-requests.yml
deleted file mode 100644
index 17456f943eb..00000000000
--- a/changelogs/unreleased/tc-api-root-merge-requests.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Add top-level merge_requests API endpoint
-merge_request: 13060
-author:
diff --git a/changelogs/unreleased/tc-git-tower-pagination-links.yml b/changelogs/unreleased/tc-git-tower-pagination-links.yml
deleted file mode 100644
index b99ef8c3c4c..00000000000
--- a/changelogs/unreleased/tc-git-tower-pagination-links.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Improve API pagination headers when no record found
-merge_request: 13629
-author: Jordan Patterson
-type: fixed
diff --git a/changelogs/unreleased/tc-issue-api-assignee.yml b/changelogs/unreleased/tc-issue-api-assignee.yml
deleted file mode 100644
index 8d6360d5baf..00000000000
--- a/changelogs/unreleased/tc-issue-api-assignee.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Add author_id & assignee_id param to /issues API
-merge_request: 13004
-author:
diff --git a/changelogs/unreleased/tc-no-todo-service-select.yml b/changelogs/unreleased/tc-no-todo-service-select.yml
deleted file mode 100644
index ddcae334aa7..00000000000
--- a/changelogs/unreleased/tc-no-todo-service-select.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Avoid plucking Todo ids in TodoService
-merge_request: 10845
-author:
diff --git a/changelogs/unreleased/tc-remove-nonexisting-namespace-pending-delete-projects.yml b/changelogs/unreleased/tc-remove-nonexisting-namespace-pending-delete-projects.yml
new file mode 100644
index 00000000000..218336df5d2
--- /dev/null
+++ b/changelogs/unreleased/tc-remove-nonexisting-namespace-pending-delete-projects.yml
@@ -0,0 +1,5 @@
+---
+title: Migration to remove pending delete projects with non-existing namespace
+merge_request: 13598
+author:
+type: other
diff --git a/changelogs/unreleased/toggle-new-project-import-description.yml b/changelogs/unreleased/toggle-new-project-import-description.yml
deleted file mode 100644
index 8f0d09e0540..00000000000
--- a/changelogs/unreleased/toggle-new-project-import-description.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-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/use-a-specialized-class-for-querying-events.yml b/changelogs/unreleased/use-a-specialized-class-for-querying-events.yml
deleted file mode 100644
index 6c1ec10aa12..00000000000
--- a/changelogs/unreleased/use-a-specialized-class-for-querying-events.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Use a specialized class for querying events to improve performance
-merge_request:
-author:
diff --git a/changelogs/unreleased/use_full_path_in_project_avatar_url_webhook.yml b/changelogs/unreleased/use_full_path_in_project_avatar_url_webhook.yml
new file mode 100644
index 00000000000..0c3acce1455
--- /dev/null
+++ b/changelogs/unreleased/use_full_path_in_project_avatar_url_webhook.yml
@@ -0,0 +1,5 @@
+---
+title: Use full path of project's avatar in webhooks
+merge_request: 13649
+author: Vitaliy @blackst0ne Klachkov
+type: changed
diff --git a/changelogs/unreleased/wiki_title.yml b/changelogs/unreleased/wiki_title.yml
deleted file mode 100644
index 3ef5fa2969b..00000000000
--- a/changelogs/unreleased/wiki_title.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Allow wiki pages to be renamed in the UI
-merge_request: 10069
-author: wendy0402
diff --git a/changelogs/unreleased/winh-derive-project-name.yml b/changelogs/unreleased/winh-derive-project-name.yml
deleted file mode 100644
index 2244d21d768..00000000000
--- a/changelogs/unreleased/winh-derive-project-name.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Derive project path from import URL
-merge_request: 13131
-author:
diff --git a/changelogs/unreleased/zj-add-pipeline-source-variable.yml b/changelogs/unreleased/zj-add-pipeline-source-variable.yml
new file mode 100644
index 00000000000..5d98cd8086a
--- /dev/null
+++ b/changelogs/unreleased/zj-add-pipeline-source-variable.yml
@@ -0,0 +1,5 @@
+---
+title: Add CI_PIPELINE_SOURCE variable on CI Jobs
+merge_request:
+author:
+type: added
diff --git a/changelogs/unreleased/zj-delete-mm-team.yml b/changelogs/unreleased/zj-delete-mm-team.yml
deleted file mode 100644
index f0c782c4566..00000000000
--- a/changelogs/unreleased/zj-delete-mm-team.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Remove Mattermost team when deleting a group
-merge_request: 11362
-author:
diff --git a/changelogs/unreleased/zj-pipeline-badge-improvements.yml b/changelogs/unreleased/zj-pipeline-badge-improvements.yml
deleted file mode 100644
index 735192ede2d..00000000000
--- a/changelogs/unreleased/zj-pipeline-badge-improvements.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Update build badges to be pipeline badges and display passing instead of success
-merge_request:
-author:
diff --git a/changelogs/unreleased/zj-project-templates.yml b/changelogs/unreleased/zj-project-templates.yml
deleted file mode 100644
index ab6e0f2d5f2..00000000000
--- a/changelogs/unreleased/zj-project-templates.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Projects can be created from templates
-merge_request: 13108
-author:
diff --git a/changelogs/unreleased/zj-remove-ci-api-v1.yml b/changelogs/unreleased/zj-remove-ci-api-v1.yml
new file mode 100644
index 00000000000..8f2dc321b36
--- /dev/null
+++ b/changelogs/unreleased/zj-remove-ci-api-v1.yml
@@ -0,0 +1,5 @@
+---
+title: Remove CI API v1
+merge_request:
+author:
+type: removed
diff --git a/changelogs/unreleased/zj-reword-job-to-pipeline-chart-view.yml b/changelogs/unreleased/zj-reword-job-to-pipeline-chart-view.yml
new file mode 100644
index 00000000000..474392a8cdd
--- /dev/null
+++ b/changelogs/unreleased/zj-reword-job-to-pipeline-chart-view.yml
@@ -0,0 +1,5 @@
+---
+title: Reword job to pipeline to reflect what the graphs are really about
+merge_request:
+author:
+type: fixed
diff --git a/config/initializers/7_prometheus_metrics.rb b/config/initializers/7_prometheus_metrics.rb
index 54c797e0714..31839297523 100644
--- a/config/initializers/7_prometheus_metrics.rb
+++ b/config/initializers/7_prometheus_metrics.rb
@@ -1,4 +1,5 @@
require 'prometheus/client'
+require 'prometheus/client/support/unicorn'
Prometheus::Client.configure do |config|
config.logger = Rails.logger
@@ -9,6 +10,8 @@ Prometheus::Client.configure do |config|
if Rails.env.development? || Rails.env.test?
config.multiprocess_files_dir ||= Rails.root.join('tmp/prometheus_multiproc_dir')
end
+
+ config.pid_provider = Prometheus::Client::Support::Unicorn.method(:worker_pid_provider)
end
Sidekiq.configure_server do |config|
diff --git a/config/initializers/8_metrics.rb b/config/initializers/8_metrics.rb
index 2aeb94d47cd..370a976b64a 100644
--- a/config/initializers/8_metrics.rb
+++ b/config/initializers/8_metrics.rb
@@ -119,6 +119,9 @@ def instrument_classes(instrumentation)
# Needed for https://gitlab.com/gitlab-org/gitlab-ce/issues/30224#note_32306159
instrumentation.instrument_instance_method(MergeRequestDiff, :load_commits)
+
+ # Needed for https://gitlab.com/gitlab-org/gitlab-ce/issues/36061
+ instrumentation.instrument_instance_method(MergeRequest, :ensure_ref_fetched)
end
# rubocop:enable Metrics/AbcSize
diff --git a/config/initializers/omniauth.rb b/config/initializers/omniauth.rb
index 56c279ffcf4..fddb018e948 100644
--- a/config/initializers/omniauth.rb
+++ b/config/initializers/omniauth.rb
@@ -6,12 +6,6 @@ if Gitlab::LDAP::Config.enabled?
const_set(server['provider_class'], Class.new(LDAP))
end
end
-
- OmniauthCallbacksController.class_eval do
- Gitlab::LDAP::Config.available_servers.each do |server|
- alias_method server['provider_name'], :ldap
- end
- end
end
OmniAuth.config.full_host = Settings.gitlab['base_url']
diff --git a/config/initializers/workhorse_multipart.rb b/config/initializers/workhorse_multipart.rb
index 064e5964f09..4196e3a8f61 100644
--- a/config/initializers/workhorse_multipart.rb
+++ b/config/initializers/workhorse_multipart.rb
@@ -10,10 +10,8 @@ end
#
module Gitlab
module StrongParameterScalars
- GITLAB_PERMITTED_SCALAR_TYPES = [::UploadedFile].freeze
-
def permitted_scalar?(value)
- super || GITLAB_PERMITTED_SCALAR_TYPES.any? { |type| value.is_a?(type) }
+ super || value.is_a?(::UploadedFile)
end
end
end
diff --git a/config/karma.config.js b/config/karma.config.js
index 2f571978e08..e459f5cdac3 100644
--- a/config/karma.config.js
+++ b/config/karma.config.js
@@ -8,6 +8,7 @@ if (webpackConfig.plugins) {
webpackConfig.plugins = webpackConfig.plugins.filter(function (plugin) {
return !(
plugin instanceof webpack.optimize.CommonsChunkPlugin ||
+ plugin instanceof webpack.optimize.ModuleConcatenationPlugin ||
plugin instanceof webpack.DefinePlugin
);
});
diff --git a/config/routes.rb b/config/routes.rb
index 4fd6cb5d439..ce7ab1d20f6 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -27,6 +27,7 @@ Rails.application.routes.draw do
get '/autocomplete/users' => 'autocomplete#users'
get '/autocomplete/users/:id' => 'autocomplete#user'
get '/autocomplete/projects' => 'autocomplete#projects'
+ get '/autocomplete/award_emojis' => 'autocomplete#award_emojis'
# Search
get 'search' => 'search#show'
diff --git a/config/routes/ci.rb b/config/routes/ci.rb
index 8d23aa8fbf6..cbd4c2db852 100644
--- a/config/routes/ci.rb
+++ b/config/routes/ci.rb
@@ -1,8 +1,4 @@
namespace :ci do
- # CI API
- Ci::API::API.logger Rails.logger
- mount Ci::API::API => '/api'
-
resource :lint, only: [:show, :create]
root to: redirect('/')
diff --git a/config/sidekiq_queues.yml b/config/sidekiq_queues.yml
index 83abc83c9f0..24c001362c6 100644
--- a/config/sidekiq_queues.yml
+++ b/config/sidekiq_queues.yml
@@ -27,6 +27,10 @@
- [new_merge_request, 2]
- [build, 2]
- [pipeline, 2]
+ - [pipeline_processing, 5]
+ - [pipeline_default, 3]
+ - [pipeline_cache, 3]
+ - [pipeline_hooks, 2]
- [gitlab_shell, 2]
- [email_receiver, 2]
- [emails_on_push, 2]
diff --git a/config/webpack.config.js b/config/webpack.config.js
index 6a347c2e660..7d63a42d7d8 100644
--- a/config/webpack.config.js
+++ b/config/webpack.config.js
@@ -76,7 +76,6 @@ var config = {
terminal: './terminal/terminal_bundle.js',
u2f: ['vendor/u2f'],
ui_development_kit: './ui_development_kit.js',
- users: './users/index.js',
raven: './raven/index.js',
vue_merge_request_widget: './vue_merge_request_widget/index.js',
test: './test.js',
@@ -171,7 +170,7 @@ var config = {
if (chunk.name) {
return chunk.name;
}
- return chunk.modules.map((m) => {
+ return chunk.mapModules((m) => {
var chunkPath = m.request.split('!').pop();
return path.relative(m.context, chunkPath);
}).join('_');
@@ -277,14 +276,9 @@ if (IS_PRODUCTION) {
})
);
- // zopfli requires a lot of compute time and is disabled in CI
+ // compression can require a lot of compute time and is disabled in CI
if (!NO_COMPRESSION) {
- // gracefully fall back to gzip if `node-zopfli` is unavailable (e.g. in CentOS 6)
- try {
- config.plugins.push(new CompressionPlugin({ algorithm: 'zopfli' }));
- } catch(err) {
- config.plugins.push(new CompressionPlugin({ algorithm: 'gzip' }));
- }
+ config.plugins.push(new CompressionPlugin());
}
}
diff --git a/db/fixtures/development/17_cycle_analytics.rb b/db/fixtures/development/17_cycle_analytics.rb
index 7c1d758dada..383782112a8 100644
--- a/db/fixtures/development/17_cycle_analytics.rb
+++ b/db/fixtures/development/17_cycle_analytics.rb
@@ -15,7 +15,7 @@ class Gitlab::Seeder::CycleAnalytics
# to disable the `pre_receive` hook in order to remove this
# dependency on the GitLab API.
def stub_git_pre_receive!
- GitHooksService.class_eval do
+ Gitlab::Git::HooksService.class_eval do
def run_hook(name)
[true, '']
end
diff --git a/db/migrate/20140502125220_migrate_repo_size.rb b/db/migrate/20140502125220_migrate_repo_size.rb
index f5d5d834307..ca1b054600c 100644
--- a/db/migrate/20140502125220_migrate_repo_size.rb
+++ b/db/migrate/20140502125220_migrate_repo_size.rb
@@ -11,7 +11,7 @@ class MigrateRepoSize < ActiveRecord::Migration
path = File.join(namespace_path, project['project_path'] + '.git')
begin
- repo = Gitlab::Git::Repository.new('default', path)
+ repo = Gitlab::Git::Repository.new('default', path, '')
if repo.empty?
print '-'
else
diff --git a/db/migrate/20170711145320_add_status_to_ci_stages.rb b/db/migrate/20170711145320_add_status_to_ci_stages.rb
new file mode 100644
index 00000000000..d497a61a959
--- /dev/null
+++ b/db/migrate/20170711145320_add_status_to_ci_stages.rb
@@ -0,0 +1,9 @@
+class AddStatusToCiStages < ActiveRecord::Migration
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def change
+ add_column :ci_stages, :status, :integer
+ end
+end
diff --git a/db/migrate/20170720111708_add_lock_version_to_ci_stages.rb b/db/migrate/20170720111708_add_lock_version_to_ci_stages.rb
new file mode 100644
index 00000000000..e1c4f033286
--- /dev/null
+++ b/db/migrate/20170720111708_add_lock_version_to_ci_stages.rb
@@ -0,0 +1,9 @@
+class AddLockVersionToCiStages < ActiveRecord::Migration
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def change
+ add_column :ci_stages, :lock_version, :integer
+ end
+end
diff --git a/db/migrate/20170802013652_add_storage_fields_to_project.rb b/db/migrate/20170802013652_add_storage_fields_to_project.rb
new file mode 100644
index 00000000000..c2381a9d0b2
--- /dev/null
+++ b/db/migrate/20170802013652_add_storage_fields_to_project.rb
@@ -0,0 +1,16 @@
+# See http://doc.gitlab.com/ce/development/migration_style_guide.html
+# for more information on how to write migrations for GitLab.
+
+class AddStorageFieldsToProject < ActiveRecord::Migration
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def up
+ add_column :projects, :storage_version, :integer, limit: 2
+ end
+
+ def down
+ remove_column :projects, :storage_version
+ end
+end
diff --git a/db/migrate/20170807071105_add_hashed_storage_to_settings.rb b/db/migrate/20170807071105_add_hashed_storage_to_settings.rb
new file mode 100644
index 00000000000..0846557add8
--- /dev/null
+++ b/db/migrate/20170807071105_add_hashed_storage_to_settings.rb
@@ -0,0 +1,18 @@
+# See http://doc.gitlab.com/ce/development/migration_style_guide.html
+# for more information on how to write migrations for GitLab.
+
+class AddHashedStorageToSettings < ActiveRecord::Migration
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ add_column_with_default :application_settings, :hashed_storage_enabled, :boolean, default: false
+ end
+
+ def down
+ remove_columns :application_settings, :hashed_storage_enabled
+ end
+end
diff --git a/db/migrate/20170809142252_cleanup_appearances_schema.rb b/db/migrate/20170809142252_cleanup_appearances_schema.rb
index 90d12925ba2..acf45060114 100644
--- a/db/migrate/20170809142252_cleanup_appearances_schema.rb
+++ b/db/migrate/20170809142252_cleanup_appearances_schema.rb
@@ -7,7 +7,7 @@ class CleanupAppearancesSchema < ActiveRecord::Migration
# Set this constant to true if this migration requires downtime.
DOWNTIME = false
- NOT_NULL_COLUMNS = %i[title description description_html created_at updated_at]
+ NOT_NULL_COLUMNS = %i[title description created_at updated_at]
TIME_COLUMNS = %i[created_at updated_at]
diff --git a/db/migrate/20170820100558_correct_protected_tags_foreign_keys.rb b/db/migrate/20170820100558_correct_protected_tags_foreign_keys.rb
new file mode 100644
index 00000000000..229298e1946
--- /dev/null
+++ b/db/migrate/20170820100558_correct_protected_tags_foreign_keys.rb
@@ -0,0 +1,35 @@
+# See http://doc.gitlab.com/ce/development/migration_style_guide.html
+# for more information on how to write migrations for GitLab.
+
+class CorrectProtectedTagsForeignKeys < ActiveRecord::Migration
+ include Gitlab::Database::MigrationHelpers
+
+ # Set this constant to true if this migration requires downtime.
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ remove_foreign_key_without_error(:protected_tag_create_access_levels,
+ column: :protected_tag_id)
+
+ execute <<-EOF
+ DELETE FROM protected_tag_create_access_levels
+ WHERE NOT EXISTS (
+ SELECT true
+ FROM protected_tags
+ WHERE protected_tag_create_access_levels.protected_tag_id = protected_tags.id
+ )
+ AND protected_tag_id IS NOT NULL
+ EOF
+
+ add_concurrent_foreign_key(:protected_tag_create_access_levels,
+ :protected_tags,
+ column: :protected_tag_id)
+ end
+
+ def down
+ # Previously there was a foreign key without a CASCADING DELETE, so we'll
+ # just leave the foreign key in place.
+ end
+end
diff --git a/db/migrate/20170824162758_allow_appearances_description_html_null.rb b/db/migrate/20170824162758_allow_appearances_description_html_null.rb
new file mode 100644
index 00000000000..d7f481ee894
--- /dev/null
+++ b/db/migrate/20170824162758_allow_appearances_description_html_null.rb
@@ -0,0 +1,18 @@
+# See http://doc.gitlab.com/ce/development/migration_style_guide.html
+# for more information on how to write migrations for GitLab.
+
+class AllowAppearancesDescriptionHtmlNull < ActiveRecord::Migration
+ include Gitlab::Database::MigrationHelpers
+
+ # Set this constant to true if this migration requires downtime.
+ DOWNTIME = false
+
+ def up
+ change_column_null :appearances, :description_html, true
+ end
+
+ def down
+ # This column should not have a `NOT NULL` class, so we don't want to revert
+ # back to re-adding it.
+ end
+end
diff --git a/db/post_migrate/20170711145558_migrate_stages_statuses.rb b/db/post_migrate/20170711145558_migrate_stages_statuses.rb
new file mode 100644
index 00000000000..aeb900354db
--- /dev/null
+++ b/db/post_migrate/20170711145558_migrate_stages_statuses.rb
@@ -0,0 +1,33 @@
+class MigrateStagesStatuses < ActiveRecord::Migration
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ BATCH_SIZE = 10000
+ RANGE_SIZE = 100
+ MIGRATION = 'MigrateStageStatus'.freeze
+
+ class Stage < ActiveRecord::Base
+ self.table_name = 'ci_stages'
+ include ::EachBatch
+ end
+
+ def up
+ Stage.where(status: nil).each_batch(of: BATCH_SIZE) do |relation, index|
+ relation.each_batch(of: RANGE_SIZE) do |batch|
+ range = batch.pluck('MIN(id)', 'MAX(id)').first
+ delay = index * 5.minutes
+
+ BackgroundMigrationWorker.perform_in(delay, MIGRATION, range)
+ end
+ end
+ end
+
+ def down
+ disable_statement_timeout
+
+ update_column_in_batches(:ci_stages, :status, nil)
+ end
+end
diff --git a/db/post_migrate/20170816102555_cleanup_nonexisting_namespace_pending_delete_projects.rb b/db/post_migrate/20170816102555_cleanup_nonexisting_namespace_pending_delete_projects.rb
new file mode 100644
index 00000000000..3f085c17133
--- /dev/null
+++ b/db/post_migrate/20170816102555_cleanup_nonexisting_namespace_pending_delete_projects.rb
@@ -0,0 +1,54 @@
+# Follow up of CleanupNamespacelessPendingDeleteProjects and it cleans
+# all projects with `pending_delete = true` and for which the
+# namespace no longer exists.
+class CleanupNonexistingNamespacePendingDeleteProjects < ActiveRecord::Migration
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ class Project < ActiveRecord::Base
+ self.table_name = 'projects'
+
+ include ::EachBatch
+ end
+
+ class Namespace < ActiveRecord::Base
+ self.table_name = 'namespaces'
+ end
+
+ def up
+ find_projects.each_batch do |batch|
+ args = batch.pluck(:id).map { |id| [id] }
+
+ NamespacelessProjectDestroyWorker.bulk_perform_async(args)
+ end
+ end
+
+ def down
+ # NOOP
+ end
+
+ private
+
+ def find_projects
+ projects = Project.arel_table
+ namespaces = Namespace.arel_table
+
+ namespace_query = namespaces.project(1)
+ .where(namespaces[:id].eq(projects[:namespace_id]))
+ .exists.not
+
+ # SELECT "projects"."id"
+ # FROM "projects"
+ # WHERE "projects"."pending_delete" = 't'
+ # AND (NOT (EXISTS
+ # (SELECT 1
+ # FROM "namespaces"
+ # WHERE "namespaces"."id" = "projects"."namespace_id")))
+ Project.where(projects[:pending_delete].eq(true))
+ .where(namespace_query)
+ .select(:id)
+ end
+end
diff --git a/db/post_migrate/20170822101017_migrate_pipeline_sidekiq_queues.rb b/db/post_migrate/20170822101017_migrate_pipeline_sidekiq_queues.rb
new file mode 100644
index 00000000000..8441cfe7968
--- /dev/null
+++ b/db/post_migrate/20170822101017_migrate_pipeline_sidekiq_queues.rb
@@ -0,0 +1,17 @@
+class MigratePipelineSidekiqQueues < ActiveRecord::Migration
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def up
+ sidekiq_queue_migrate 'build', to: 'pipeline_default'
+ sidekiq_queue_migrate 'pipeline', to: 'pipeline_default'
+ end
+
+ def down
+ sidekiq_queue_migrate 'pipeline_default', to: 'pipeline'
+ sidekiq_queue_migrate 'pipeline_processing', to: 'pipeline'
+ sidekiq_queue_migrate 'pipeline_hooks', to: 'pipeline'
+ sidekiq_queue_migrate 'pipeline_cache', to: 'pipeline'
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 2ea6ae29dc7..0f4b0c0c3b3 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -11,7 +11,7 @@
#
# It's strongly recommended that you check this file into your version control system.
-ActiveRecord::Schema.define(version: 20170815060945) do
+ActiveRecord::Schema.define(version: 20170824162758) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
@@ -34,7 +34,7 @@ ActiveRecord::Schema.define(version: 20170815060945) do
t.string "logo"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
- t.text "description_html", null: false
+ t.text "description_html"
t.integer "cached_markdown_version"
end
@@ -128,6 +128,7 @@ ActiveRecord::Schema.define(version: 20170815060945) do
t.integer "performance_bar_allowed_group_id"
t.boolean "password_authentication_enabled"
t.boolean "project_export_enabled", default: true, null: false
+ t.boolean "hashed_storage_enabled", default: false, null: false
end
create_table "audit_events", force: :cascade do |t|
@@ -379,6 +380,8 @@ ActiveRecord::Schema.define(version: 20170815060945) do
t.datetime "created_at"
t.datetime "updated_at"
t.string "name"
+ t.integer "status"
+ t.integer "lock_version"
end
add_index "ci_stages", ["pipeline_id", "name"], name: "index_ci_stages_on_pipeline_id_and_name", using: :btree
@@ -1206,6 +1209,7 @@ ActiveRecord::Schema.define(version: 20170815060945) do
t.datetime "last_repository_updated_at"
t.string "ci_config_path"
t.text "delete_error"
+ t.integer "storage_version", limit: 2
end
add_index "projects", ["ci_id"], name: "index_projects_on_ci_id", using: :btree
@@ -1726,7 +1730,7 @@ ActiveRecord::Schema.define(version: 20170815060945) do
add_foreign_key "protected_branch_push_access_levels", "protected_branches", name: "fk_9ffc86a3d9", on_delete: :cascade
add_foreign_key "protected_branches", "projects", name: "fk_7a9c6d93e7", on_delete: :cascade
add_foreign_key "protected_tag_create_access_levels", "namespaces", column: "group_id"
- add_foreign_key "protected_tag_create_access_levels", "protected_tags"
+ add_foreign_key "protected_tag_create_access_levels", "protected_tags", name: "fk_f7dfda8c51", on_delete: :cascade
add_foreign_key "protected_tag_create_access_levels", "users"
add_foreign_key "protected_tags", "projects", name: "fk_8e4af87648", on_delete: :cascade
add_foreign_key "push_event_payloads", "events_for_migration", column: "event_id", name: "fk_36c74129da", on_delete: :cascade
diff --git a/doc/README.md b/doc/README.md
index 267487520cd..76d4c3e51fe 100644
--- a/doc/README.md
+++ b/doc/README.md
@@ -98,7 +98,7 @@ Manage your [repositories](user/project/repository/index.md) from the UI (user i
- [Git](topics/git/index.md): Getting started with Git, branching strategies, Git LFS, advanced use.
- [Git cheatsheet](https://gitlab.com/gitlab-com/marketing/raw/master/design/print/git-cheatsheet/print-pdf/git-cheatsheet.pdf): Download a PDF describing the most used Git operations.
- [GitLab Flow](workflow/gitlab_flow.md): explore the best of Git with the GitLab Flow strategy.
-- [Signing commits](workflow/gpg_signed_commits/index.md): use GPG to sign your commits.
+- [Signing commits](user/project/gpg_signed_commits/index.md): use GPG to sign your commits.
### Migrate and import your projects from other platforms
diff --git a/doc/administration/auth/authentiq.md b/doc/administration/auth/authentiq.md
index 1528f1d2b17..252ff1f4b15 100644
--- a/doc/administration/auth/authentiq.md
+++ b/doc/administration/auth/authentiq.md
@@ -4,7 +4,7 @@ To enable the Authentiq OmniAuth provider for passwordless authentication you mu
Authentiq will generate a Client ID and the accompanying Client Secret for you to use.
-1. Get your Client credentials (Client ID and Client Secret) at [Authentiq](https://www.authentiq.com/register).
+1. Get your Client credentials (Client ID and Client Secret) at [Authentiq](https://www.authentiq.com/developers).
2. On your GitLab server, open the configuration file:
diff --git a/doc/api/README.md b/doc/api/README.md
index 8acb2145f1a..c2a08dcff07 100644
--- a/doc/api/README.md
+++ b/doc/api/README.md
@@ -55,15 +55,10 @@ following locations:
- [Tags](tags.md)
- [Todos](todos.md)
- [Users](users.md)
-- [Validate CI configuration](ci/lint.md)
+- [Validate CI configuration](lint.md)
- [V3 to V4](v3_to_v4.md)
- [Version](version.md)
-The following documentation is for the [internal CI API](ci/README.md):
-
-- [Builds](ci/builds.md)
-- [Runners](ci/runners.md)
-
## Road to GraphQL
Going forward, we will start on moving to
@@ -268,6 +263,7 @@ The following table shows the possible return codes for API requests.
| `404 Not Found` | A resource could not be accessed, e.g., an ID for a resource could not be found. |
| `405 Method Not Allowed` | The request is not supported. |
| `409 Conflict` | A conflicting resource already exists, e.g., creating a project with a name that already exists. |
+| `412` | Indicates the request was denied. May happen if the `If-Unmodified-Since` header is provided when trying to delete a resource, which was modified in between. |
| `422 Unprocessable` | The entity could not be processed. |
| `500 Server Error` | While handling the request something went wrong server-side. |
diff --git a/doc/api/ci/README.md b/doc/api/ci/README.md
deleted file mode 100644
index 96a281e27c8..00000000000
--- a/doc/api/ci/README.md
+++ /dev/null
@@ -1,24 +0,0 @@
-# GitLab CI API
-
-## Purpose
-
-The main purpose of GitLab CI API is to provide the necessary data and context
-for GitLab CI Runners.
-
-All relevant information about the consumer API can be found in a
-[separate document](../../api/README.md).
-
-## API Prefix
-
-The current CI API prefix is `/ci/api/v1`.
-
-You need to prepend this prefix to all examples in this documentation, like:
-
-```bash
-GET /ci/api/v1/builds/:id/artifacts
-```
-
-## Resources
-
-- [Builds](builds.md)
-- [Runners](runners.md)
diff --git a/doc/api/ci/builds.md b/doc/api/ci/builds.md
deleted file mode 100644
index c8374d94716..00000000000
--- a/doc/api/ci/builds.md
+++ /dev/null
@@ -1,147 +0,0 @@
-# Builds API
-
-API used by runners to receive and update builds.
-
->**Note:**
-This API is intended to be used only by Runners as their own
-communication channel. For the consumer API see the
-[Jobs API](../jobs.md).
-
-## Authentication
-
-This API uses two types of authentication:
-
-1. Unique Runner's token which is the token assigned to the Runner after it
- has been registered.
-
-2. Using the build authorization token.
- This is project's CI token that can be found under the **Builds** section of
- a project's settings. The build authorization token can be passed as a
- parameter or a value of `BUILD-TOKEN` header.
-
-These two methods of authentication are interchangeable.
-
-## Builds
-
-### Runs oldest pending build by runner
-
-```
-POST /ci/api/v1/builds/register
-```
-
-| Attribute | Type | Required | Description |
-|-----------|---------|----------|---------------------|
-| `token` | string | yes | Unique runner token |
-
-
-```
-curl --request POST "https://gitlab.example.com/ci/api/v1/builds/register" --form "token=t0k3n"
-```
-
-**Responses:**
-
-| Status | Data |Description |
-|--------|------|---------------------------------------------------------------------------|
-| `201` | yes | When a build is scheduled for a runner |
-| `204` | no | When no builds are scheduled for a runner (for GitLab Runner >= `v1.3.0`) |
-| `403` | no | When invalid token is used or no token is sent |
-| `404` | no | When no builds are scheduled for a runner (for GitLab Runner < `v1.3.0`) **or** when the runner is set to `paused` in GitLab runner's configuration page |
-
-### Update details of an existing build
-
-```
-PUT /ci/api/v1/builds/:id
-```
-
-| Attribute | Type | Required | Description |
-|-----------|---------|----------|----------------------|
-| `id` | integer | yes | The ID of a project |
-| `token` | string | yes | Unique runner token |
-| `state` | string | no | The state of a build |
-| `trace` | string | no | The trace of a build |
-
-```
-curl --request PUT "https://gitlab.example.com/ci/api/v1/builds/1234" --form "token=t0k3n" --form "state=running" --form "trace=Running git clone...\n"
-```
-
-### Incremental build trace update
-
-Using this method you need to send trace content as a request body. You also need to provide the `Content-Range` header
-with a range of sent trace part. Note that you need to send parts in the proper order, so the begining of the part
-must start just after the end of the previous part. If you provide the wrong part, then GitLab CI API will return `416
-Range Not Satisfiable` response with a header `Range: 0-X`, where `X` is the current trace length.
-
-For example, if you receive `Range: 0-11` in the response, then your next part must contain a `Content-Range: 11-...`
-header and a trace part covered by this range.
-
-For a valid update API will return `202` response with:
-* `Build-Status: {status}` header containing current status of the build,
-* `Range: 0-{length}` header with the current trace length.
-
-```
-PATCH /ci/api/v1/builds/:id/trace.txt
-```
-
-Parameters:
-
-| Attribute | Type | Required | Description |
-|-----------|---------|----------|----------------------|
-| `id` | integer | yes | The ID of a build |
-
-Headers:
-
-| Attribute | Type | Required | Description |
-|-----------------|---------|----------|-----------------------------------|
-| `BUILD-TOKEN` | string | yes | The build authorization token |
-| `Content-Range` | string | yes | Bytes range of trace that is sent |
-
-```
-curl --request PATCH "https://gitlab.example.com/ci/api/v1/builds/1234/trace.txt" --header "BUILD-TOKEN=build_t0k3n" --header "Content-Range=0-21" --data "Running git clone...\n"
-```
-
-
-### Upload artifacts to build
-
-```
-POST /ci/api/v1/builds/:id/artifacts
-```
-
-| Attribute | Type | Required | Description |
-|-----------|---------|----------|-------------------------------|
-| `id` | integer | yes | The ID of a build |
-| `token` | string | yes | The build authorization token |
-| `file` | mixed | yes | Artifacts file |
-
-```
-curl --request POST "https://gitlab.example.com/ci/api/v1/builds/1234/artifacts" --form "token=build_t0k3n" --form "file=@/path/to/file"
-```
-
-### Download the artifacts file from build
-
-```
-GET /ci/api/v1/builds/:id/artifacts
-```
-
-| Attribute | Type | Required | Description |
-|-----------|---------|----------|-------------------------------|
-| `id` | integer | yes | The ID of a build |
-| `token` | string | yes | The build authorization token |
-
-```
-curl "https://gitlab.example.com/ci/api/v1/builds/1234/artifacts" --form "token=build_t0k3n"
-```
-
-### Remove the artifacts file from build
-
-```
-DELETE /ci/api/v1/builds/:id/artifacts
-```
-
-| Attribute | Type | Required | Description |
-|-----------|---------|----------|-------------------------------|
-| ` id` | integer | yes | The ID of a build |
-| `token` | string | yes | The build authorization token |
-
-```
-curl --request DELETE "https://gitlab.example.com/ci/api/v1/builds/1234/artifacts" --form "token=build_t0k3n"
-```
diff --git a/doc/api/ci/runners.md b/doc/api/ci/runners.md
deleted file mode 100644
index 342c039dad8..00000000000
--- a/doc/api/ci/runners.md
+++ /dev/null
@@ -1,59 +0,0 @@
-# Register and Delete Runners API
-
-API used by Runners to register and delete themselves.
-
->**Note:**
-This API is intended to be used only by Runners as their own
-communication channel. For the consumer API see the
-[new Runners API](../runners.md).
-
-## Authentication
-
-This API uses two types of authentication:
-
-1. Unique Runner's token, which is the token assigned to the Runner after it
- has been registered. This token can be found on the Runner's edit page (go to
- **Project > Runners**, select one of the Runners listed under **Runners activated for
- this project**).
-
-2. Using Runners' registration token.
- This is a token that can be found in project's settings.
- It can also be found in the **Admin > Runners** settings area.
- There are two types of tokens you can pass: shared Runner registration
- token or project specific registration token.
-
-## Register a new runner
-
-Used to make GitLab CI aware of available runners.
-
-```sh
-POST /ci/api/v1/runners/register
-```
-
-| Attribute | Type | Required | Description |
-| --------- | ------- | --------- | ----------- |
-| `token` | string | yes | Runner's registration token |
-
-Example request:
-
-```sh
-curl --request POST "https://gitlab.example.com/ci/api/v1/runners/register" --form "token=t0k3n"
-```
-
-## Delete a Runner
-
-Used to remove a Runner.
-
-```sh
-DELETE /ci/api/v1/runners/delete
-```
-
-| Attribute | Type | Required | Description |
-| --------- | ------- | --------- | ----------- |
-| `token` | string | yes | Unique Runner's token |
-
-Example request:
-
-```sh
-curl --request DELETE "https://gitlab.example.com/ci/api/v1/runners/delete" --form "token=t0k3n"
-```
diff --git a/doc/api/group_level_variables.md b/doc/api/group_level_variables.md
index e19be7b35c4..33c6da08018 100644
--- a/doc/api/group_level_variables.md
+++ b/doc/api/group_level_variables.md
@@ -1,5 +1,7 @@
# Group-level Variables API
+> [Introduced][ce-34519] in GitLab 9.5
+
## List group variables
Get list of a group's variables.
@@ -123,3 +125,5 @@ DELETE /groups/:id/variables/:key
```
curl --request DELETE --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/groups/1/variables/VARIABLE_1"
```
+
+[ce-34519]: https://gitlab.com/gitlab-org/gitlab-ce/issues/34519
diff --git a/doc/api/group_milestones.md b/doc/api/group_milestones.md
index dbfc7529125..a96fb3124fc 100644
--- a/doc/api/group_milestones.md
+++ b/doc/api/group_milestones.md
@@ -1,5 +1,8 @@
# Group milestones API
+> **Notes:**
+> [Introduced][ce-12819] in GitLab 9.5.
+
## List group milestones
Returns a list of group milestones.
@@ -118,3 +121,5 @@ Parameters:
- `id` (required) - The ID or [URL-encoded path of the group](README.md#namespaced-path-encoding) owned by the authenticated user
- `milestone_id` (required) - The ID of a group milestone
+
+[ce-12819]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/12819
diff --git a/doc/api/groups.md b/doc/api/groups.md
index 2b3d8e125c8..c2daa8bc029 100644
--- a/doc/api/groups.md
+++ b/doc/api/groups.md
@@ -2,7 +2,8 @@
## List groups
-Get a list of groups. (As user: my groups or all available, as admin: all groups).
+Get a list of visible groups for the authenticated user. When accessed without
+authentication, only public groups are returned.
Parameters:
@@ -43,7 +44,8 @@ You can search for groups by name or path, see below.
## List a group's projects
-Get a list of projects in this group.
+Get a list of projects in this group. When accessed without authentication, only
+public projects are returned.
```
GET /groups/:id/projects
@@ -109,7 +111,8 @@ Example response:
## Details of a group
-Get all details of a group.
+Get all details of a group. This endpoint can be accessed without authentication
+if the group is publicly accessible.
```
GET /groups/:id
diff --git a/doc/api/ci/lint.md b/doc/api/lint.md
index e4a6dc809b1..bd5a216a99d 100644
--- a/doc/api/ci/lint.md
+++ b/doc/api/lint.md
@@ -5,7 +5,7 @@
Checks if your .gitlab-ci.yml file is valid.
```
-POST ci/lint
+POST /lint
```
| Attribute | Type | Required | Description |
@@ -49,3 +49,4 @@ Example responses:
```
[ce-5953]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/5953
+
diff --git a/doc/api/project_snippets.md b/doc/api/project_snippets.md
index d74398c6e65..24c8ff5fa7a 100644
--- a/doc/api/project_snippets.md
+++ b/doc/api/project_snippets.md
@@ -150,4 +150,4 @@ Example response:
}
```
-[ce-[ce-29508]: https://gitlab.com/gitlab-org/gitlab-ce/issues/29508]: https://gitlab.com/gitlab-org/gitlab-ce/issues/29508
+[ce-29508]: https://gitlab.com/gitlab-org/gitlab-ce/issues/29508
diff --git a/doc/articles/index.md b/doc/articles/index.md
index 1aa65504852..4b0c85b9272 100644
--- a/doc/articles/index.md
+++ b/doc/articles/index.md
@@ -76,7 +76,8 @@ Learn how to deploy a static website with [GitLab Pages](../user/project/pages/i
## Install and maintain GitLab
-Install, upgrade, integrate, migrate to GitLab:
+[Admin](../README.md#administrator-documentation), [install](../install/README.md),
+upgrade, integrate, migrate to GitLab:
| Article title | Category | Publishing date |
| :------------ | :------: | --------------: |
diff --git a/doc/ci/api/README.md b/doc/ci/api/README.md
deleted file mode 100644
index 98f37935427..00000000000
--- a/doc/ci/api/README.md
+++ /dev/null
@@ -1 +0,0 @@
-This document was moved to a [new location](../../api/ci/README.md).
diff --git a/doc/ci/api/builds.md b/doc/ci/api/builds.md
deleted file mode 100644
index 0563a367609..00000000000
--- a/doc/ci/api/builds.md
+++ /dev/null
@@ -1 +0,0 @@
-This document was moved to a [new location](../../api/ci/builds.md).
diff --git a/doc/ci/api/runners.md b/doc/ci/api/runners.md
deleted file mode 100644
index 1027363851c..00000000000
--- a/doc/ci/api/runners.md
+++ /dev/null
@@ -1 +0,0 @@
-This document was moved to a [new location](../../api/ci/runners.md).
diff --git a/doc/ci/docker/using_docker_build.md b/doc/ci/docker/using_docker_build.md
index f7c2a0ef0ca..f28c9791bee 100644
--- a/doc/ci/docker/using_docker_build.md
+++ b/doc/ci/docker/using_docker_build.md
@@ -134,7 +134,7 @@ In order to do that, follow the steps:
# When using dind, it's wise to use the overlayfs driver for
# improved performance.
variables:
- DOCKER_DRIVER: overlay
+ DOCKER_DRIVER: overlay2
services:
- docker:dind
@@ -248,7 +248,7 @@ aware of the following implications:
By default, when using `docker:dind`, Docker uses the `vfs` storage driver which
copies the filesystem on every run. This is a very disk-intensive operation
-which can be avoided if a different driver is used, for example `overlay`.
+which can be avoided if a different driver is used, for example `overlay2`.
1. Make sure a recent kernel is used, preferably `>= 4.2`.
1. Check whether the `overlay` module is loaded:
@@ -275,8 +275,12 @@ which can be avoided if a different driver is used, for example `overlay`.
```
variables:
- DOCKER_DRIVER: overlay
+ DOCKER_DRIVER: overlay2
```
+
+> **Note:**
+- For more information about using OverlayFS with Docker, you can read
+ [Use the OverlayFS storage driver](https://docs.docker.com/engine/userguide/storagedriver/overlayfs-driver/).
## Using the GitLab Container Registry
diff --git a/doc/ci/docker/using_docker_images.md b/doc/ci/docker/using_docker_images.md
index dc5313c5597..6e8beceb6fe 100644
--- a/doc/ci/docker/using_docker_images.md
+++ b/doc/ci/docker/using_docker_images.md
@@ -388,15 +388,40 @@ that runner.
As an example, let's assume that you want to use the `registry.example.com/private/image:latest`
image which is private and requires you to login into a private container registry.
+
+Let's also assume that these are the login credentials:
+
+| Key | Value |
+|----------|----------------------|
+| registry | registry.example.com |
+| username | my_username |
+| password | my_password |
+
To configure access for `registry.example.com`, follow these steps:
-1. Do a `docker login` on your computer:
+1. Find what the value of `DOCKER_AUTH_CONFIG` should be. There are two ways to
+ accomplish this:
+ - **First way -** Do a `docker login` on your local machine:
- ```bash
- docker login registry.example.com --username my_username --password my_password
- ```
+ ```bash
+ docker login registry.example.com --username my_username --password my_password
+ ```
+
+ Then copy the content of `~/.docker/config.json`.
+ - **Second way -** In some setups, it's possible that Docker client will use
+ the available system keystore to store the result of `docker login`. In
+ that case, it's impossible to read `~/.docker/config.json`, so you will
+ need to prepare the required base64-encoded version of
+ `${username}:${password}` manually. Open a terminal and execute the
+ following command:
+
+ ```bash
+ echo -n "my_username:my_password" | base64
+
+ # Example output to copy
+ bXlfdXNlcm5hbWU6bXlfcGFzc3dvcmQ=
+ ```
-1. Copy the content of `~/.docker/config.json`
1. Create a [secret variable] `DOCKER_AUTH_CONFIG` with the content of the
Docker configuration file as the value:
@@ -410,7 +435,8 @@ To configure access for `registry.example.com`, follow these steps:
}
```
-1. Do a `docker logout` on your computer if you don't need access to the
+1. Optionally,if you followed the first way of finding the `DOCKER_AUTH_CONFIG`
+ value, do a `docker logout` on your computer if you don't need access to the
registry from it:
```bash
@@ -418,7 +444,7 @@ To configure access for `registry.example.com`, follow these steps:
```
1. You can now use any private image from `registry.example.com` defined in
- `image` and/or `services` in your [`.gitlab-ci.yml` file][yaml-priv-reg]:
+ `image` and/or `services` in your `.gitlab-ci.yml` file:
```yaml
image: my.registry.tld:5000/namespace/image:tag
diff --git a/doc/ci/variables/README.md b/doc/ci/variables/README.md
index 22e7f6879ed..234dc530db0 100644
--- a/doc/ci/variables/README.md
+++ b/doc/ci/variables/README.md
@@ -57,6 +57,7 @@ future GitLab releases.**
| **CI_RUNNER_TAGS** | 8.10 | 0.5 | The defined runner tags |
| **CI_PIPELINE_ID** | 8.10 | 0.5 | The unique id of the current pipeline that GitLab CI uses internally |
| **CI_PIPELINE_TRIGGERED** | all | all | The flag to indicate that job was [triggered] |
+| **CI_PIPELINE_SOURCE** | 10.0 | all | The source for this pipeline, one of: push, web, trigger, schedule, api, external. Pipelines created before 9.5 will have unknown as source |
| **CI_PROJECT_DIR** | all | all | The full path where the repository is cloned and where the job is run |
| **CI_PROJECT_ID** | all | all | The unique id of the current project that GitLab CI uses internally |
| **CI_PROJECT_NAME** | 8.10 | 0.5 | The project name that is currently being built (actually it is project folder name) |
@@ -85,6 +86,11 @@ To follow conventions of naming across GitLab, and to futher move away from the
`build` term and toward `job` CI variables have been renamed for the 9.0
release.
+>**Note:**
+Starting with GitLab 9.0, we have deprecated the `$CI_BUILD_*` variables. **You are
+strongly advised to use the new variables as we will remove the old ones in
+future GitLab releases.**
+
| 8.x name | 9.0+ name |
| --------------------- |------------------------ |
| `CI_BUILD_ID` | `CI_JOB_ID` |
diff --git a/doc/ci/yaml/README.md b/doc/ci/yaml/README.md
index 1869782fe6e..abf4ec7dbf8 100644
--- a/doc/ci/yaml/README.md
+++ b/doc/ci/yaml/README.md
@@ -1065,6 +1065,8 @@ a list of all previous jobs from which the artifacts should be downloaded.
You can only define jobs from stages that are executed before the current one.
An error will be shown if you define jobs from the current stage or next ones.
Defining an empty array will skip downloading any artifacts for that job.
+The status of the previous job is not considered when using `dependencies`, so
+if it failed or it is a manual job that was not run, no error occurs.
---
diff --git a/doc/development/doc_styleguide.md b/doc/development/doc_styleguide.md
index 90d1d9657b9..798f40eef3d 100644
--- a/doc/development/doc_styleguide.md
+++ b/doc/development/doc_styleguide.md
@@ -113,13 +113,12 @@ merge request.
## Links
-- If a link makes the paragraph to span across multiple lines, do not use
- the regular Markdown approach: `[Text](https://example.com)`. Instead use
- `[Text][identifier]` and at the very bottom of the document add:
- `[identifier]: https://example.com`. This is another way to create Markdown
- links which keeps the document clear and concise. Bonus points if you also
- add an alternative text: `[identifier]: https://example.com "Alternative text"`
- that appears when hovering your mouse on a link
+- Use the regular inline link markdown markup `[Text](https://example.com)`.
+ It's easier to read, review, and maintain.
+- If there's a link that repeats several times through the same document,
+ you can use `[Text][identifier]` and at the bottom of the section or the
+ document add: `[identifier]: https://example.com`, in which case, we do
+ encourage you to also add an alternative text: `[identifier]: https://example.com "Alternative text"` that appears when hovering your mouse on a link.
### Linking to inline docs
diff --git a/doc/development/fe_guide/style_guide_js.md b/doc/development/fe_guide/style_guide_js.md
index 9c72fda0229..4f20aa070de 100644
--- a/doc/development/fe_guide/style_guide_js.md
+++ b/doc/development/fe_guide/style_guide_js.md
@@ -102,42 +102,41 @@ followed by any global declarations, then a blank newline prior to any imports o
1. Relative paths: when importing a module in the same directory, a child
directory, or an immediate parent directory prefer relative paths. When
-importing a module which is two or more levels up, prefer either `~/` or `ee/`
-.
+importing a module which is two or more levels up, prefer either `~/` or `ee/`.
-In **app/assets/javascripts/my-feature/subdir**:
+ In **app/assets/javascripts/my-feature/subdir**:
-``` javascript
-// bad
-import Foo from '~/my-feature/foo';
-import Bar from '~/my-feature/subdir/bar';
-import Bin from '~/my-feature/subdir/lib/bin';
+ ```javascript
+ // bad
+ import Foo from '~/my-feature/foo';
+ import Bar from '~/my-feature/subdir/bar';
+ import Bin from '~/my-feature/subdir/lib/bin';
-// good
-import Foo from '../foo';
-import Bar from './bar';
-import Bin from './lib/bin';
-```
+ // good
+ import Foo from '../foo';
+ import Bar from './bar';
+ import Bin from './lib/bin';
+ ```
-In **spec/javascripts**:
+ In **spec/javascripts**:
-``` javascript
-// bad
-import Foo from '../../app/assets/javascripts/my-feature/foo';
+ ```javascript
+ // bad
+ import Foo from '../../app/assets/javascripts/my-feature/foo';
-// good
-import Foo from '~/my-feature/foo';
-```
+ // good
+ import Foo from '~/my-feature/foo';
+ ```
-When referencing an **EE component**:
+ When referencing an **EE component**:
-``` javascript
-// bad
-import Foo from '../../../../../ee/app/assets/javascripts/my-feature/ee-foo';
+ ```javascript
+ // bad
+ import Foo from '../../../../../ee/app/assets/javascripts/my-feature/ee-foo';
-// good
-import Foo from 'ee/my-feature/foo';
-```
+ // good
+ import Foo from 'ee/my-feature/foo';
+ ```
1. Avoid using IIFE. Although we have a lot of examples of files which wrap their
contents in IIFEs (immediately-invoked function expressions),
@@ -145,24 +144,23 @@ this is no longer necessary after the transition from Sprockets to webpack.
Do not use them anymore and feel free to remove them when refactoring legacy code.
1. Avoid adding to the global namespace.
- ```javascript
- // bad
- window.MyClass = class { /* ... */ };
+ ```javascript
+ // bad
+ window.MyClass = class { /* ... */ };
- // good
- export default class MyClass { /* ... */ }
- ```
+ // good
+ export default class MyClass { /* ... */ }
+ ```
1. Side effects are forbidden in any script which contains exports
- ```javascript
- // bad
- export default class MyClass { /* ... */ }
-
- document.addEventListener("DOMContentLoaded", function(event) {
- new MyClass();
- }
- ```
+ ```javascript
+ // bad
+ export default class MyClass { /* ... */ }
+ document.addEventListener("DOMContentLoaded", function(event) {
+ new MyClass();
+ }
+ ```
#### Data Mutation and Pure functions
1. Strive to write many small pure functions, and minimize where mutations occur.
@@ -414,19 +412,19 @@ A forEach will cause side effects, it will be mutating the array being iterated.
#### Data
1. `data` method should always be a function
- ```javascript
- // bad
- data: {
- foo: 'foo'
- }
-
- // good
- data() {
- return {
+ ```javascript
+ // bad
+ data: {
foo: 'foo'
- };
- }
- ```
+ }
+
+ // good
+ data() {
+ return {
+ foo: 'foo'
+ };
+ }
+ ```
#### Directives
@@ -481,7 +479,8 @@ A forEach will cause side effects, it will be mutating the array being iterated.
1. `beforeDestroy`
1. `destroyed`
-#### Vue and Boostrap
+#### Vue and Bootstrap
+
1. Tooltips: Do not rely on `has-tooltip` class name for Vue components
```javascript
// bad
@@ -511,23 +510,19 @@ A forEach will cause side effects, it will be mutating the array being iterated.
$('span').tooltip('fixTitle');
```
+
### The Javascript/Vue Accord
The goal of this accord is to make sure we are all on the same page.
1. When writing Vue, you may not use jQuery in your application.
-1.1 If you need to grab data from the DOM, you may query the DOM 1 time while bootstrapping your application to grab data attributes using `dataset`. You can do this without jQuery.
-1.2 You may use a jQuery dependency in Vue.js following [this example from the docs](https://vuejs.org/v2/examples/select2.html).
-1.3 If an outside jQuery Event needs to be listen to inside the Vue application, you may use jQuery event listeners.
-1.4 We will avoid adding new jQuery events when they are not required. Instead of adding new jQuery events take a look at [different methods to do the same task](https://vuejs.org/v2/api/#vm-emit).
-
+ 1. If you need to grab data from the DOM, you may query the DOM 1 time while bootstrapping your application to grab data attributes using `dataset`. You can do this without jQuery.
+ 1. You may use a jQuery dependency in Vue.js following [this example from the docs](https://vuejs.org/v2/examples/select2.html).
+ 1. If an outside jQuery Event needs to be listen to inside the Vue application, you may use jQuery event listeners.
+ 1. We will avoid adding new jQuery events when they are not required. Instead of adding new jQuery events take a look at [different methods to do the same task](https://vuejs.org/v2/api/#vm-emit).
1. You may query the `window` object 1 time, while bootstrapping your application for application specific data (e.g. `scrollTo` is ok to access anytime). Do this access during the bootstrapping of your application.
-
1. You may have a temporary but immediate need to create technical debt by writing code that does not follow our standards, to be refactored later. Maintainers need to be ok with the tech debt in the first place. An issue should be created for that tech debt to evaluate it further and discuss. In the coming months you should fix that tech debt, with it's priority to be determined by maintainers.
-
1. When creating tech debt you must write the tests for that code before hand and those tests may not be rewritten. e.g. jQuery tests rewritten to Vue tests.
-
1. You may choose to use VueX as a centralized state management. If you choose not to use VueX, you must use the *store pattern* which can be found in the [Vue.js documentation](https://vuejs.org/v2/guide/state-management.html#Simple-State-Management-from-Scratch).
-
1. Once you have chosen a centralized state management solution you must use it for your entire application. i.e. Don't mix and match your state management solutions.
## SCSS
diff --git a/doc/development/licensing.md b/doc/development/licensing.md
index 1f115059fb8..2b16dfe0e7c 100644
--- a/doc/development/licensing.md
+++ b/doc/development/licensing.md
@@ -66,7 +66,7 @@ Libraries with the following licenses are unacceptable for use:
## Requesting Approval for Licenses
-Libraries that are not listed in the [Acceptable Licenses][Acceptable-Licenses] or [Unacceptable Licenses][Unacceptable-Licenses] list can be submitted to the legal team for review. Please create an issue in the [Organization Repository][Org-Repo] and cc `@gl-legal`. After a decision has been made, the original requestor is responsible for updating this document.
+Libraries that are not listed in the [Acceptable Licenses][Acceptable-Licenses] or [Unacceptable Licenses][Unacceptable-Licenses] list can be submitted to the legal team for review. Please email `legal@gitlab.com` with the details. After a decision has been made, the original requestor is responsible for updating this document.
## Notes
diff --git a/doc/development/testing.md b/doc/development/testing.md
index efd56484b12..83269303005 100644
--- a/doc/development/testing.md
+++ b/doc/development/testing.md
@@ -529,10 +529,7 @@ slowest test files and try to improve them.
## CI setup
-- On CE, the test suite only runs against PostgreSQL by default. We additionally
- run the suite against MySQL for tags, `master`, and any branch that includes
- `mysql` in the name.
-- On EE, the test suite always runs both PostgreSQL and MySQL.
+- On CE and EE, the test suite runs both PostgreSQL and MySQL.
- Rails logging to `log/test.log` is disabled by default in CI [for
performance reasons][logging]. To override this setting, provide the
`RAILS_ENABLE_TEST_LOG` environment variable.
diff --git a/doc/gitlab-basics/create-project.md b/doc/gitlab-basics/create-project.md
index b4b77a2f94b..67ef189fee9 100644
--- a/doc/gitlab-basics/create-project.md
+++ b/doc/gitlab-basics/create-project.md
@@ -13,13 +13,17 @@
![Project information](img/create_new_project_info.png)
+1. Choose if you want start a blank project, or with one of the predefined
+ [Project Templates](https://gitlab.com/gitlab-org/project-templates):
+ this will kickstart your repository code and CI automatically.
+ Otherwise, if you have a project in a different repository, you can [import it] by
+ clicking an **Import project from** button provided this is enabled in
+ your GitLab instance. Ask your administrator if not.
+
1. Provide the following information:
- Enter the name of your project in the **Project name** field. You can't use
special characters, but you can use spaces, hyphens, underscores or even
emoji.
- - If you have a project in a different repository, you can [import it] by
- clicking an **Import project from** button provided this is enabled in
- your GitLab instance. Ask your administrator if not.
- The **Project description (optional)** field enables you to enter a
description for your project's dashboard, which will help others
understand what your project is about. Though it's not required, it's a good
@@ -29,12 +33,5 @@
1. Click **Create project**.
-## From a template
-
-To kickstart your development GitLab projects can be started from a template.
-For example, one of the templates included is Ruby on Rails. When filling out the
-form for new projects, click the 'Ruby on Rails' button. During project creation,
-this will import a Ruby on Rails template with GitLab CI preconfigured.
-
[import it]: ../workflow/importing/README.md
[reserved]: ../user/reserved_names.md
diff --git a/doc/gitlab-basics/img/create_new_project_info.png b/doc/gitlab-basics/img/create_new_project_info.png
index fcfbca87b91..ef8753e224b 100644
--- a/doc/gitlab-basics/img/create_new_project_info.png
+++ b/doc/gitlab-basics/img/create_new_project_info.png
Binary files differ
diff --git a/doc/install/README.md b/doc/install/README.md
index bc831a37735..656f8720361 100644
--- a/doc/install/README.md
+++ b/doc/install/README.md
@@ -17,10 +17,18 @@ the hardware requirements.
- [Installation from source](installation.md) - Install GitLab from source.
Useful for unsupported systems like *BSD. For an overview of the directory
structure, read the [structure documentation](structure.md).
-- [Docker](https://docs.gitlab.com/omnibus/docker/) - Install GitLab using Docker.
+- [Docker](docker.md) - Install GitLab using Docker.
+
+## Install GitLab on cloud providers
+
- [Installing in Kubernetes](kubernetes/index.md) - Install GitLab into a Kubernetes
Cluster using our official Helm Chart Repository.
-- Testing only! [DigitalOcean and Docker Machine](digitaloceandocker.md) -
+- [Install GitLab on OpenShift](../articles/openshift_and_gitlab/index.md)
+- [Install GitLab on DC/OS](https://mesosphere.com/blog/gitlab-dcos/) via [GitLab-Mesosphere integration](https://about.gitlab.com/2016/09/16/announcing-gitlab-and-mesosphere/)
+- [Install GitLab on Azure](azure/index.md)
+- [Install GitLab on Google Cloud Platform](google_cloud_platform/index.md)
+- [Install on AWS](https://about.gitlab.com/aws/)
+- _Testing only!_ [DigitalOcean and Docker Machine](digitaloceandocker.md) -
Quickly test any version of GitLab on DigitalOcean using Docker Machine.
## Database
diff --git a/doc/install/azure/img/azure-add-inbound-sec-rule-http.png b/doc/install/azure/img/azure-add-inbound-sec-rule-http.png
new file mode 100644
index 00000000000..abf500cb63a
--- /dev/null
+++ b/doc/install/azure/img/azure-add-inbound-sec-rule-http.png
Binary files differ
diff --git a/doc/install/azure/img/azure-add-inbound-sec-rule-ssh.png b/doc/install/azure/img/azure-add-inbound-sec-rule-ssh.png
new file mode 100644
index 00000000000..f7a8a04dfa7
--- /dev/null
+++ b/doc/install/azure/img/azure-add-inbound-sec-rule-ssh.png
Binary files differ
diff --git a/doc/install/azure/img/azure-create-virtual-machine-basics-password.png b/doc/install/azure/img/azure-create-virtual-machine-basics-password.png
new file mode 100644
index 00000000000..80bf39ecb48
--- /dev/null
+++ b/doc/install/azure/img/azure-create-virtual-machine-basics-password.png
Binary files differ
diff --git a/doc/install/azure/img/azure-create-virtual-machine-basics.png b/doc/install/azure/img/azure-create-virtual-machine-basics.png
new file mode 100644
index 00000000000..229c073fe17
--- /dev/null
+++ b/doc/install/azure/img/azure-create-virtual-machine-basics.png
Binary files differ
diff --git a/doc/install/azure/img/azure-create-virtual-machine-deployment.png b/doc/install/azure/img/azure-create-virtual-machine-deployment.png
new file mode 100644
index 00000000000..5cfdd973a58
--- /dev/null
+++ b/doc/install/azure/img/azure-create-virtual-machine-deployment.png
Binary files differ
diff --git a/doc/install/azure/img/azure-create-virtual-machine-purchase.png b/doc/install/azure/img/azure-create-virtual-machine-purchase.png
new file mode 100644
index 00000000000..f4de62299f1
--- /dev/null
+++ b/doc/install/azure/img/azure-create-virtual-machine-purchase.png
Binary files differ
diff --git a/doc/install/azure/img/azure-create-virtual-machine-settings.png b/doc/install/azure/img/azure-create-virtual-machine-settings.png
new file mode 100644
index 00000000000..20097921660
--- /dev/null
+++ b/doc/install/azure/img/azure-create-virtual-machine-settings.png
Binary files differ
diff --git a/doc/install/azure/img/azure-create-virtual-machine-size.png b/doc/install/azure/img/azure-create-virtual-machine-size.png
new file mode 100644
index 00000000000..a408394151f
--- /dev/null
+++ b/doc/install/azure/img/azure-create-virtual-machine-size.png
Binary files differ
diff --git a/doc/install/azure/img/azure-dashboard-highlight-nsg.png b/doc/install/azure/img/azure-dashboard-highlight-nsg.png
new file mode 100644
index 00000000000..025efd33977
--- /dev/null
+++ b/doc/install/azure/img/azure-dashboard-highlight-nsg.png
Binary files differ
diff --git a/doc/install/azure/img/azure-dashboard-running-resources.png b/doc/install/azure/img/azure-dashboard-running-resources.png
new file mode 100644
index 00000000000..7e661a6aa65
--- /dev/null
+++ b/doc/install/azure/img/azure-dashboard-running-resources.png
Binary files differ
diff --git a/doc/install/azure/img/azure-dashboard.png b/doc/install/azure/img/azure-dashboard.png
new file mode 100644
index 00000000000..375ec8622b8
--- /dev/null
+++ b/doc/install/azure/img/azure-dashboard.png
Binary files differ
diff --git a/doc/install/azure/img/azure-inbound-sec-rules-list.png b/doc/install/azure/img/azure-inbound-sec-rules-list.png
new file mode 100644
index 00000000000..1667671b21d
--- /dev/null
+++ b/doc/install/azure/img/azure-inbound-sec-rules-list.png
Binary files differ
diff --git a/doc/install/azure/img/azure-new-gitlab-ce.png b/doc/install/azure/img/azure-new-gitlab-ce.png
new file mode 100644
index 00000000000..88949f69a94
--- /dev/null
+++ b/doc/install/azure/img/azure-new-gitlab-ce.png
Binary files differ
diff --git a/doc/install/azure/img/azure-new-search-gitlab.png b/doc/install/azure/img/azure-new-search-gitlab.png
new file mode 100644
index 00000000000..f96ed577d62
--- /dev/null
+++ b/doc/install/azure/img/azure-new-search-gitlab.png
Binary files differ
diff --git a/doc/install/azure/img/azure-nsg-inbound-sec-rules-add-highlight.png b/doc/install/azure/img/azure-nsg-inbound-sec-rules-add-highlight.png
new file mode 100644
index 00000000000..c9a08b87ce6
--- /dev/null
+++ b/doc/install/azure/img/azure-nsg-inbound-sec-rules-add-highlight.png
Binary files differ
diff --git a/doc/install/azure/img/azure-nsg-inbound-sec-rules-highlight.png b/doc/install/azure/img/azure-nsg-inbound-sec-rules-highlight.png
new file mode 100644
index 00000000000..6423625ca8b
--- /dev/null
+++ b/doc/install/azure/img/azure-nsg-inbound-sec-rules-highlight.png
Binary files differ
diff --git a/doc/install/azure/img/azure-vm-domain-name.png b/doc/install/azure/img/azure-vm-domain-name.png
new file mode 100644
index 00000000000..01c03004b24
--- /dev/null
+++ b/doc/install/azure/img/azure-vm-domain-name.png
Binary files differ
diff --git a/doc/install/azure/img/azure-vm-management-public-ip.png b/doc/install/azure/img/azure-vm-management-public-ip.png
new file mode 100644
index 00000000000..ef313641db8
--- /dev/null
+++ b/doc/install/azure/img/azure-vm-management-public-ip.png
Binary files differ
diff --git a/doc/install/azure/img/azure-vm-management-settings-network-interfaces.png b/doc/install/azure/img/azure-vm-management-settings-network-interfaces.png
new file mode 100644
index 00000000000..4ff10718059
--- /dev/null
+++ b/doc/install/azure/img/azure-vm-management-settings-network-interfaces.png
Binary files differ
diff --git a/doc/install/azure/img/azure-vm-management.png b/doc/install/azure/img/azure-vm-management.png
new file mode 100644
index 00000000000..a0e0067258c
--- /dev/null
+++ b/doc/install/azure/img/azure-vm-management.png
Binary files differ
diff --git a/doc/install/azure/img/gitlab-admin-area-9.4.0.png b/doc/install/azure/img/gitlab-admin-area-9.4.0.png
new file mode 100644
index 00000000000..b7ee4598731
--- /dev/null
+++ b/doc/install/azure/img/gitlab-admin-area-9.4.0.png
Binary files differ
diff --git a/doc/install/azure/img/gitlab-admin-area.png b/doc/install/azure/img/gitlab-admin-area.png
new file mode 100644
index 00000000000..028f0b0a0eb
--- /dev/null
+++ b/doc/install/azure/img/gitlab-admin-area.png
Binary files differ
diff --git a/doc/install/azure/img/gitlab-change-password.png b/doc/install/azure/img/gitlab-change-password.png
new file mode 100644
index 00000000000..7350d604d56
--- /dev/null
+++ b/doc/install/azure/img/gitlab-change-password.png
Binary files differ
diff --git a/doc/install/azure/img/gitlab-home.png b/doc/install/azure/img/gitlab-home.png
new file mode 100644
index 00000000000..7c935805ea2
--- /dev/null
+++ b/doc/install/azure/img/gitlab-home.png
Binary files differ
diff --git a/doc/install/azure/img/gitlab-login.png b/doc/install/azure/img/gitlab-login.png
new file mode 100644
index 00000000000..95fe5aec1e0
--- /dev/null
+++ b/doc/install/azure/img/gitlab-login.png
Binary files differ
diff --git a/doc/install/azure/img/gitlab-new-project.png b/doc/install/azure/img/gitlab-new-project.png
new file mode 100644
index 00000000000..3b6b9a81682
--- /dev/null
+++ b/doc/install/azure/img/gitlab-new-project.png
Binary files differ
diff --git a/doc/install/azure/img/gitlab-project-home-empty.png b/doc/install/azure/img/gitlab-project-home-empty.png
new file mode 100644
index 00000000000..54d0b36a251
--- /dev/null
+++ b/doc/install/azure/img/gitlab-project-home-empty.png
Binary files differ
diff --git a/doc/install/azure/img/gitlab-project-home-instructions.png b/doc/install/azure/img/gitlab-project-home-instructions.png
new file mode 100644
index 00000000000..fd040d33e95
--- /dev/null
+++ b/doc/install/azure/img/gitlab-project-home-instructions.png
Binary files differ
diff --git a/doc/install/azure/img/gitlab-ssh-update-in-progress.png b/doc/install/azure/img/gitlab-ssh-update-in-progress.png
new file mode 100644
index 00000000000..8a686ebde26
--- /dev/null
+++ b/doc/install/azure/img/gitlab-ssh-update-in-progress.png
Binary files differ
diff --git a/doc/install/azure/index.md b/doc/install/azure/index.md
new file mode 100644
index 00000000000..9cc4b56c932
--- /dev/null
+++ b/doc/install/azure/index.md
@@ -0,0 +1,439 @@
+# Install GitLab on Microsoft Azure
+
+> _This article was originally written by Dave Wentzel and [published on the GitLab Blog][Original-Blog-Post]._
+>
+> _Ported to the GitLab documentation and updated on 2017-08-24 by [Ian Scorer](https://gitlab.com/iscorer)._
+
+Azure is Microsoft's business cloud and GitLab is a pre-configured offering on the Azure Marketplace.
+Hopefully, you aren't surprised to hear that Microsoft and Azure have embraced open source software
+like Ubuntu, Red Hat Enterprise Linux, and of course - GitLab! This means that you can spin up a
+pre-configured GitLab VM and have your very own private GitLab up and running in around 30 minutes.
+Let's get started.
+
+## Getting started
+
+First, you'll need an account on Azure. There are three ways to do this:
+
+- If your company (or you) already has an account, then you are ready to go!
+- You can also open your own Azure account for free. _At time of writing_, you get $200
+of credit to spend on Azure services for 30 days. You can use this credit to try out paid Azure
+services, exploring Microsoft's cloud for free. Even after the first 30 days, you never have to pay
+anything unless you decide to transition to paid services with a Pay-As-You-Go Azure subscription.
+This is a great way to try out Azure and cloud computing, and you can
+[read more in their comprehensive FAQ][Azure-Free-Account-FAQ].
+- If you have an MSDN subscription, you can activate your Azure subscriber benefits. Your MSDN
+subscription gives you recurring Azure credits every month, so why not put those credits to use and
+try out GitLab right now?
+
+## Working with Azure
+
+Once you have an Azure account, you can get started. Login to Azure using
+[portal.azure.com](https://portal.azure.com) and the first thing you will see is the Dashboard:
+
+![Azure Dashboard](img/azure-dashboard.png)
+
+The Dashboard gives you a quick overview of Azure resources, and from here you you can build VMs,
+create SQL Databases, author websites, and perform lots of other cloud tasks.
+
+## Create New VM
+
+The [Azure Marketplace][Azure-Marketplace] is an online store for pre-configured applications and
+services which have been optimized for the cloud by software vendors like GitLab, and both
+the [Community Edition ("CE")][CE] and the [Enterprise Edition ("EE")][EE] versions of GitLab are
+available on the Azure Marketplace as pre-configured solutions.
+
+To begin creating a new GitLab VM, click on the **+ New** icon, type "GitLab" into the search
+box, and then click the **"GitLab Community Edition"** search result:
+
+![Azure - New - Search for 'GitLab'](img/azure-new-search-gitlab.png)
+
+A new "blade" window will pop-out, where you can read more about the **"GitLab Community Edition"**
+offering which is freely available under the MIT Expat License:
+
+![Azure - New - Select 'GitLab Community Edition'](img/azure-new-gitlab-ce.png)
+
+Click **"Create"** and you will be presented with the "Create virtual machine" blade:
+
+![Azure - Create Virtual Machine - Basics](img/azure-create-virtual-machine-basics.png)
+
+## Basics
+
+The first items we need to configure are the basic settings of the underlying virtual machine:
+
+1. Enter a `Name` for the VM - e.g. **"GitLab-CE"**
+1. Select a `VM disk type` - either **HDD** _(slower, lower cost)_ or **SSD** _(faster, higher cost)_
+1. Enter a `User name` - e.g. **"gitlab-admin"**
+1. Select an `Authentication type`, either **SSH public key** or **Password**:
+
+ >**Note:** if you're unsure which authentication type to use, select **Password**
+
+ 1. If you chose **SSH public key** - enter your `SSH public key` into the field provided
+ _(read the [SSH documentation][GitLab-Docs-SSH] to learn more about how to setup SSH
+ public keys)_
+ 1. If you chose **Password** - enter the password you wish to use _(this is the password that you
+ will use later in this tutorial to [SSH] into the VM, so make sure it's a strong password/passphrase)_
+1. Choose the appropriate `Subscription` tier for your Azure account
+1. Choose an existing `Resource Group` or create a new one - e.g. **"GitLab-CE-Azure"**
+>**Note:** a "Resource group" is a way to group related resources together for easier administration.
+We chose "GitLab-CE-Azure", but your resource group can have the same name as your VM.
+1. Choose a `Location` - if you're unsure, select the default location
+
+Here are the settings we've used:
+
+![Azure - Create Virtual Machine - Basics Completed](img/azure-create-virtual-machine-basics-password.png)
+
+Check the settings you have entered, and then click **"OK"** when you're ready to proceed.
+
+## Size
+
+Next, you need to choose the size of your VM - selecting features such as the number of CPU cores,
+the amount of RAM, the size of storage (and its speed), etc.
+
+>**Note:** in common with other cloud vendors, Azure operates a resource/usage pricing model, i.e.
+the more resources your VM consumes the more it will cost you to run, so make your selection
+carefully. You'll see that Azure provides an _estimated_ monthly cost beneath each VM Size to help
+guide your selection.
+
+The default size - the lowest cost **"DS1_V2 Standard"** VM - meets the minimum system requirements
+to run a small GitLab environment for testing and evaluation purposes, and so we're going to go
+ahead and select this one, but please choose the size which best meets your own requirements:
+
+![Azure - Create Virtual Machine - Size](img/azure-create-virtual-machine-size.png)
+
+>**Note:** be aware that whilst your VM is active (known as "allocated"), it will incur
+"compute charges" which, ultimately, you will be billed for. So, even if you're using the
+free trial credits, you'll likely want to learn
+[how to properly shutdown an Azure VM to save money][Azure-Properly-Shutdown-VM].
+
+Go ahead and click your chosen size, then click **"Select"** when you're ready to proceed to the
+next step.
+
+## Settings
+
+On the next blade, you're asked to configure the Storage, Network and Extension settings.
+We've gone with the default settings as they're sufficient for test-driving GitLab, but please
+choose the settings which best meet your own requirements:
+
+![Azure - Create Virtual Machine - Settings](img/azure-create-virtual-machine-settings.png)
+
+Review the settings and then click **"OK"** when you're ready to proceed to the last step.
+
+## Purchase
+
+The Purchase page is the last step and here you will be presented with the price per hour for your
+new VM. You'll be billed only for the VM itself (e.g. "Standard DS1 v2") because the
+**"GitLab Community Edition"** marketplace solution is free to use at 0 USD/hr:
+
+![Azure - Create Virtual Machine - Purchase](img/azure-create-virtual-machine-purchase.png)
+
+>**Note:** at this stage, you can review and modify the any of the settings you have made during all
+previous steps, just click on any of the four steps to re-open them.
+
+When you have read and agreed to the terms of use and are ready to proceed, click **"Purchase"**.
+
+## Deployment
+
+At this point, Azure will begin deploying your new VM. The deployment process will take a few
+minutes to complete, with progress displayed on the **"Deployment"** blade:
+
+![Azure - Create Virtual Machine - Deployment](img/azure-create-virtual-machine-deployment.png)
+
+Once the deployment process is complete, the new VM and its associated resources will be displayed
+on the Azure Dashboard (you may need to refresh the page):
+
+![Azure - Dashboard - All resources](img/azure-dashboard-running-resources.png)
+
+The new VM can also be accessed by clicking the `All resources` or `Virtual machines` icons in the
+Azure Portal sidebar navigation menu.
+
+## Setup a domain name
+
+The VM will have a public IP address (static by default), but Azure allows us to assign a friendly
+DNS name to the VM, so let's go ahead and do that.
+
+From the Dashboard, click on the **"GitLab-CE"** tile to open the management blade for the new VM.
+The public IP address that the VM uses is shown in the 'Essentials' section:
+
+![Azure - VM - Management - Public IP Address](img/azure-vm-management-public-ip.png)
+
+Click on the public IP address - which should open the **"Public IP address - Configuration"** blade,
+then click on **"Configuration"** (under "Settings"). Now enter a friendly DNS name for your instance
+in the `DNS name label` field:
+
+![Azure - VM - Domain Name](img/azure-vm-domain-name.png)
+
+In the screenshot above, you'll see that we've set the `DNS name label` to **"gitlab-ce-test"**.
+This will make our VM accessible at `gitlab-ce-test.centralus.cloudapp.azure.com`
+_(the full domain name of your own VM will be different, of course)_.
+
+Click **"Save"** for the changes to take effect.
+
+>**Note:** if you want to use your own domain name, you will need to add a DNS `A` record at your
+domain registrar which points to the public IP address of your Azure VM. If you do this, you'll need
+to make sure your VM is configured to use a _static_ public IP address (i.e. not a _dynamic_ one)
+or you will have to reconfigure the DNS `A` record each time Azure reassigns your VM a new public IP
+address. Read [IP address types and allocation methods in Azure][Azure-IP-Address-Types] to learn more.
+
+## Let's open some ports!
+
+At this stage you should have a running and fully operational VM. However, none of the services on
+your VM (e.g. GitLab) will be publicly accessible via the internet until you have opened up the
+neccessary ports to enable access to those services.
+
+Ports are opened by adding _security rules_ to the **"Network security group"** (NSG) which our VM
+has been assigned to. If you followed the process above, then Azure will have automatically created
+an NSG named `GitLab-CE-nsg` and assigned the `GitLab-CE` VM to it.
+
+>**Note:** if you gave your VM a different name then the NSG automatically created by Azure will
+also have a different name - the name you have your VM, with `-nsg` appended to it.
+
+You can navigate to the NSG settings via many different routes in the Azure Portal, but one of the
+simplest ways is to go to the Azure Dashboard, and then click on the Network Security Group listed
+in the **"All resources"** tile:
+
+![Azure - Dashboard - All resources - Network security group](img/azure-dashboard-highlight-nsg.png)
+
+With the **"Network security group"** blade open, click on **"Inbound security rules"** under
+**"Settings"**:
+
+![Azure - Network security group - Inbound security rules](img/azure-nsg-inbound-sec-rules-highlight.png)
+
+Next, click **"Add"**:
+
+![Azure - Network security group - Inbound security rules - Add](img/azure-nsg-inbound-sec-rules-add-highlight.png)
+
+### Which ports to open?
+
+Like all servers, our VM will be running many services. However, we want to open up the correct
+ports to enable public internet access to two services in particular:
+
+1. **HTTP** (port 80) - opening port 80 will enable our VM to respond to HTTP requests, allowing
+public access to the instance of GitLab running on our VM.
+1. **SSH** (port 22) - opening port 22 will enable our VM to respond to SSH connection requests,
+allowing public access (with authentication) to remote terminal sessions
+_(you'll see why we need [SSH] access to our VM [later on in this tutorial](#maintaining-your-gitlab-instance))_
+
+### Open HTTP on Port 80
+
+In the **"Add inbound security rule"** blade, let's open port 80 so that our VM will accept HTTP
+connections:
+
+![Azure - Add inbound security rules - HTTP](img/azure-add-inbound-sec-rule-http.png)
+
+1. Enter **"HTTP"** in the `Name` field
+1. Select **HTTP** from the options in the `Service` drop-down
+1. Make sure the `Action` is set to **Allow**
+1. Click **"OK"**
+
+### Open SSH on Port 22
+
+Repeat the above process, adding a second Inbound security rule to open port 22, enabling our VM to
+accept [SSH] connections:
+
+![Azure - Add inbound security rules - SSH](img/azure-add-inbound-sec-rule-ssh.png)
+
+1. Enter **"SSH"** in the `Name` field
+1. Select **SSH** from the options in the `Service` drop-down
+1. Make sure the `Action` is set to **Allow**
+1. Click **"OK"**
+
+
+It will take a moment for Azure to add each new Inbound Security Rule (and you may need to click on
+**"Inbound security rules"** to refresh the list), but once completed, you should see the two new
+rules in the list:
+
+![Azure - Inbound security rules - List](img/azure-inbound-sec-rules-list.png)
+
+## Connecting to GitLab
+Use the domain name you set up earlier (or the public IP address) to visit your new GitLab instance
+in your browser. If everything has gone according to plan you should be presented with the
+following page, asking you to set a _new_ password for the administrator account automatically
+created by GitLab:
+
+![GitLab - Change Password](img/gitlab-change-password.png)
+
+Enter your _new_ password into both form fields, and then click **"Change your password"**.
+
+Once you have changed the password you will be redirected to the GitLab login page. Use `root` as
+the username, enter the new password you set in the previous step, and then click **"Sign in"**:
+
+![GitLab - Login](img/gitlab-login.png)
+
+### Success?
+
+After signing in successfully, you should see the GitLab Projects page displaying a
+**"Welcome to GitLab!"** message:
+
+![GitLab - Projects Page](img/gitlab-home.png)
+
+If so, you now have a working GitLab instance on your own private Azure VM. **Congratulations!**
+
+## Creating your first GitLab project
+
+You can skip this section if you are familiar with Git and GitLab. Otherwise, let's create our first
+project. From the Welcome page, click **"New Project"**.
+
+Let's give our project a name and a description, and then accept the default values for everything
+else:
+
+1. Enter **"demo"** into the `Project path` project name field
+1. Enter a `description`, e.g. **"My awesome demo project!"**
+1. Click **"Create project"**
+
+![GitLab - New Project](img/gitlab-new-project.png)
+
+Once the new project has been created (which should only take a moment), you'll be redirected to
+homepage for the project:
+
+![GitLab - Empty Project](img/gitlab-project-home-empty.png)
+
+If you scroll further down the project's home page, you'll see some basic instructions on how to
+setup a local clone of your new repository and push and pull from it:
+
+![GitLab - Empty Project - Basic Instructions](img/gitlab-project-home-instructions.png)
+
+**That's it! You now have your own private GitLab environment installed and running in the cloud!**
+
+## Maintaining your GitLab instance
+
+It's important to keep your GitLab environment up-to-date. The GitLab team is constantly making
+enhancements and occasionally you may need to update for security reasons. So let's review how to
+update GitLab.
+
+### Checking our current version
+
+To check which version of GitLab we're currently running, click on the "Admin Area" link - it's the
+the wrench icon displayed in the top-right, next to the search box.
+
+In the following screenshot you can see an **"update asap"** notification message in the top-right.
+This particular message indicates that there is a newer version of GitLab available which contains
+one or more security fixes:
+
+![GitLab - update asap](img/gitlab-admin-area.png)
+
+Under the **"Components"** section, we can see that our VM is currently running version `8.6.5` of
+GitLab. This is the version of GitLab which was contained in the Azure Marketplace
+**"GitLab Community Edition"** offering we used to build the VM when we wrote this tutorial.
+
+>**Note:** The version of GitLab in your own VM instance may well be different, but the update
+process will still be the same.
+
+### Connect via SSH
+
+To perform an update, we need to connect directly to our Azure VM instance and run some commands
+from the terminal. Our Azure VM is actually a server running Linux (Ubuntu), so we'll need to
+connect to it using SSH ([Secure Shell][SSH]).
+
+If you're running Windows, you'll need to connect using [PuTTY] or an equivalent Windows SSH client.
+If you're running Linux or macOS, then you already have an SSH client installed.
+
+>**Note:**
+- Remember that you will need to login with the username and password you specified
+[when you created](#basics) your Azure VM
+- If you need to reset your VM password, read
+[how to reset SSH credentials for a user on an Azure VM][Azure-Troubleshoot-SSH-Connection].
+
+#### SSH from the command-line
+
+If you're running [SSH] from the command-line (terminal), then type in the following command to
+connect to your VM, substituting `username` and `your-azure-domain-name.com` for the correct values.
+
+Again, remember that your Azure VM domain name will be the one you
+[setup previously in the tutorial](#set-up-a-domain-name). If you didn't setup a domain name for
+your VM, you can use the IP address in its place in the following command:
+
+```bash
+ssh username@your-azure-domain-name.com
+```
+Provide your password at the prompt to authenticate.
+
+#### SSH from Windows (PuTTY)
+
+If you're using [PuTTY] in Windows as your [SSH] client, then you might want to take a quick
+read on [using PuTTY in Windows][Using-SSH-In-Putty].
+
+### Updating GitLab
+
+Once you've logged in via SSH, enter the following command to update GitLab to the latest
+version:
+
+```bash
+sudo apt-get update && sudo apt-get install gitlab-ce
+```
+
+This command will update GitLab and its associated components to the latest versions, so it will
+take a little time to complete. You'll see various update tasks being completed in your SSH
+terminal window:
+
+![GitLab updating](img/gitlab-ssh-update-in-progress.png)
+
+Once the update process has completed, you'll see a message like this:
+
+```
+Upgrade complete! If your GitLab server is misbehaving try running
+
+ sudo gitlab-ctl restart
+
+before anything else.
+```
+
+#### Check out your updated GitLab
+
+Refresh your GitLab instance in the browser and navigate to the Admin Area. You should now have an
+up-to-date GitLab instance.
+
+When we wrote this tutorial our Azure VM GitLab instance was updated to the latest version at time
+of writing (`9.4.0`). You can see that the message which was previously displaying **"update asap"**
+is now showing **"up-to-date"**:
+
+![GitLab up to date](img/gitlab-admin-area-9.4.0.png)
+
+## Conclusion
+
+Naturally, we believe that GitLab is a great git repository tool. However, GitLab is a whole lot
+more than that too. GitLab unifies issues, code review, CI and CD into a single UI, helping you to
+move faster from idea to production, and in this tutorial we showed you how quick and easy it is to
+setup and run your own instance of GitLab on Azure, Microsoft's cloud service.
+
+Azure is a great way to experiment with GitLab, and if you decide (as we hope) that GitLab is for
+you, you can continue to use Azure as your secure, scalable cloud provider or of course run GitLab
+on any cloud service you choose.
+
+## Where to next?
+
+Check out our other [Technical Articles][GitLab-Technical-Articles] or browse the [GitLab Documentation][GitLab-Docs] to learn more about GitLab.
+
+### Useful links
+
+- [GitLab Community Edition][CE]
+- [GitLab Enterprise Edition][EE]
+- [Microsoft Azure][Azure]
+ - [Azure - Free Account FAQ][Azure-Free-Account-FAQ]
+ - [Azure - Marketplace][Azure-Marketplace]
+ - [Azure Portal][Azure-Portal]
+ - [Azure - Pricing Calculator][Azure-Pricing-Calculator]
+ - [Azure - Troubleshoot SSH Connections to an Azure Linux VM][Azure-Troubleshoot-SSH-Connection]
+ - [Azure - Properly Shutdown an Azure VM][Azure-Properly-Shutdown-VM]
+- [SSH], [PuTTY] and [Using SSH in PuTTY][Using-SSH-In-Putty]
+
+[Original-Blog-Post]: https://about.gitlab.com/2016/07/13/how-to-setup-a-gitlab-instance-on-microsoft-azure/ "How to Setup a GitLab Instance on Microsoft Azure"
+[GitLab-Docs]: https://docs.gitlab.com/ce/README.html "GitLab Documentation"
+[GitLab-Technical-Articles]: https://docs.gitlab.com/ce/articles/index.html "GitLab Technical Articles"
+[GitLab-Docs-SSH]: https://docs.gitlab.com/ce/ssh/README.html "GitLab Documentation: SSH"
+[CE]: https://about.gitlab.com/features/
+[EE]: https://about.gitlab.com/features/#ee-starter
+
+[Azure-Troubleshoot-Linux-VM]: https://docs.microsoft.com/en-us/azure/virtual-machines/linux/troubleshoot-app-connection "Troubleshoot application connectivity issues on a Linux virtual machine in Azure"
+[Azure-IP-Address-Types]: https://docs.microsoft.com/en-us/azure/virtual-network/virtual-network-ip-addresses-overview-arm "IP address types and allocation methods in Azure"
+[Azure-How-To-Open-Ports]: https://docs.microsoft.com/en-us/azure/virtual-machines/windows/nsg-quickstart-portal "How to open ports to a virtual machine with the Azure portal"
+[Azure-Troubleshoot-SSH-Connection]: https://docs.microsoft.com/en-us/azure/virtual-machines/linux/troubleshoot-ssh-connection "Troubleshoot SSH connections to an Azure Linux VM"
+[Azure]: https://azure.microsoft.com/en-us/
+[Azure-Free-Account-FAQ]: https://azure.microsoft.com/en-us/free/free-account-faq/
+[Azure-Marketplace]: https://azure.microsoft.com/en-us/marketplace/
+[Azure-Portal]: https://portal.azure.com
+[Azure-Pricing-Calculator]: https://azure.microsoft.com/en-us/pricing/calculator/
+[Azure-Properly-Shutdown-VM]: https://buildazure.com/2017/03/16/properly-shutdown-azure-vm-to-save-money/ "Properly Shutdown an Azure VM to Save Money"
+
+[SSH]: https://en.wikipedia.org/wiki/Secure_Shell
+[PuTTY]: http://www.putty.org/
+[Using-SSH-In-Putty]: https://mediatemple.net/community/products/dv/204404604/using-ssh-in-putty- \ No newline at end of file
diff --git a/doc/install/docker.md b/doc/install/docker.md
new file mode 100644
index 00000000000..933756072ff
--- /dev/null
+++ b/doc/install/docker.md
@@ -0,0 +1,18 @@
+# GitLab Docker images
+
+[Docker](https://www.docker.com) and container technology have been revolutionizing the software world for the past few years. They combine the performance and efficiency of native execution with the abstraction, security, and immutability of virtualization.
+
+GitLab provides official Docker images to allowing you to easily take advantage of the benefits of containerization while operating your GitLab instance.
+
+## Omnibus GitLab based images
+
+GitLab maintains a set of [official Docker images](https://hub.docker.com/r/gitlab) based on our [Omnibus GitLab package](https://docs.gitlab.com/omnibus/README.html). These images include:
+* [GitLab Community Edition](https://hub.docker.com/r/gitlab/gitlab-ce/)
+* [GitLab Enterprise Edition](https://hub.docker.com/r/gitlab/gitlab-ee/)
+* [GitLab Runner](https://hub.docker.com/r/gitlab/gitlab-runner/)
+
+A [complete usage guide](https://docs.gitlab.com/omnibus/docker/) to these images is available, as well as the [Dockerfile used for building the images](https://gitlab.com/gitlab-org/omnibus-gitlab/tree/master/docker).
+
+## Cloud native images
+
+GitLab is also working towards a [cloud native set of containers](https://gitlab.com/charts/helm.gitlab.io#docker-container-images), with a single image for each component service. We intend for these images to eventually replace the [Omnibus GitLab based images](#omnibus-gitlab-based-images).
diff --git a/doc/install/kubernetes/gitlab_chart.md b/doc/install/kubernetes/gitlab_chart.md
index 0fad181f59e..81057736e3a 100644
--- a/doc/install/kubernetes/gitlab_chart.md
+++ b/doc/install/kubernetes/gitlab_chart.md
@@ -428,6 +428,13 @@ ingress:
## Installing GitLab using the Helm Chart
> You may see a temporary error message `SchedulerPredicates failed due to PersistentVolumeClaim is not bound` while storage provisions. Once the storage provisions, the pods will automatically restart. This may take a couple minutes depending on your cloud provider. If the error persists, please review the [prerequisites](#prerequisites) to ensure you have enough RAM, CPU, and storage.
+Ensure the GitLab repo has been added and re-initialize Helm:
+
+```bash
+helm repo add gitlab https://charts.gitlab.io
+helm init
+```
+
Once you [have configured](#configuration) GitLab in your `values.yml` file,
run the following:
diff --git a/doc/install/kubernetes/gitlab_omnibus.md b/doc/install/kubernetes/gitlab_omnibus.md
index bd3a85272d0..05e0a59ffeb 100644
--- a/doc/install/kubernetes/gitlab_omnibus.md
+++ b/doc/install/kubernetes/gitlab_omnibus.md
@@ -126,14 +126,23 @@ Let's Encrypt limits a single TLD to five certificate requests within a single w
## Installing GitLab using the Helm Chart
> You may see a temporary error message `SchedulerPredicates failed due to PersistentVolumeClaim is not bound` while storage provisions. Once the storage provisions, the pods will automatically restart. This may take a couple minutes depending on your cloud provider. If the error persists, please review the [prerequisites](#prerequisites) to ensure you have enough RAM, CPU, and storage.
-Once you have reviewed the [configuration settings](#configuring-and-installing-gitlab) and [added the Helm repository](index.md#add-the-gitlab-helm-repository), you can install the chart. We recommending saving your configuration options in a `values.yaml` file for easier upgrades in the future.
+Ensure the GitLab repo has been added and re-initialize Helm:
+
+```bash
+helm repo add gitlab https://charts.gitlab.io
+helm init
+```
+
+Once you have reviewed the [configuration settings](#configuring-and-installing-gitlab) you can install the chart. We recommending saving your configuration options in a `values.yaml` file for easier upgrades in the future.
For example:
+
```bash
helm install --name gitlab -f values.yaml gitlab/gitlab-omnibus
```
or passing them on the command line:
+
```bash
helm install --name gitlab --set baseDomain=gitlab.io,baseIP=1.1.1.1,gitlab=ee,gitlabEELicense=$LICENSE,legoEmail=email@gitlab.com gitlab/gitlab-omnibus
```
diff --git a/doc/install/kubernetes/gitlab_runner_chart.md b/doc/install/kubernetes/gitlab_runner_chart.md
index b0fe91d6337..51f94a33109 100644
--- a/doc/install/kubernetes/gitlab_runner_chart.md
+++ b/doc/install/kubernetes/gitlab_runner_chart.md
@@ -190,6 +190,13 @@ certsSecretName: <SECRET NAME>
## Installing GitLab Runner using the Helm Chart
+Ensure the GitLab repo has been added and re-initialize Helm:
+
+```bash
+helm repo add gitlab https://charts.gitlab.io
+helm init
+```
+
Once you [have configured](#configuration) GitLab Runner in your `values.yml` file,
run the following:
diff --git a/doc/install/kubernetes/index.md b/doc/install/kubernetes/index.md
index 3608aa6b2d6..eb98dc06a18 100644
--- a/doc/install/kubernetes/index.md
+++ b/doc/install/kubernetes/index.md
@@ -35,12 +35,14 @@ helm init
## Using the GitLab Helm Charts
-GitLab makes available three Helm Charts: an easy to use bundled chart, and a specific chart for GitLab itself and the Runner.
+GitLab makes available three Helm Charts.
-- [gitlab-omnibus](gitlab_omnibus.md): The easiest way to get started. Includes everything needed to run GitLab, including: a Runner, Container Registry, automatic SSL, and an Ingress.
+- [gitlab-omnibus](gitlab_omnibus.md): **Recommended** and the easiest way to get started. Includes everything needed to run GitLab, including: a [Runner](https://docs.gitlab.com/runner/), [Container Registry](https://docs.gitlab.com/ee/user/project/container_registry.html#gitlab-container-registry), [automatic SSL](https://github.com/kubernetes/charts/tree/master/stable/kube-lego), and an [Ingress](https://github.com/kubernetes/ingress/tree/master/controllers/nginx).
- [gitlab](gitlab_chart.md): Just the GitLab service, with optional Postgres and Redis.
- [gitlab-runner](gitlab_runner_chart.md): GitLab Runner, to process CI jobs.
+We are also working on a new set of [cloud native Charts](https://gitlab.com/charts/helm.gitlab.io) which will eventually replace these.
+
[chart]: https://github.com/kubernetes/charts
[helm-quick]: https://github.com/kubernetes/helm/blob/master/docs/quickstart.md
[helm]: https://github.com/kubernetes/helm/blob/master/README.md
diff --git a/doc/topics/authentication/index.md b/doc/topics/authentication/index.md
index 0c0d482499a..fac91935a45 100644
--- a/doc/topics/authentication/index.md
+++ b/doc/topics/authentication/index.md
@@ -37,7 +37,6 @@ This page gathers all the resources for the topic **Authentication** within GitL
- [Private Tokens](../../api/README.md#private-tokens)
- [Impersonation tokens](../../api/README.md#impersonation-tokens)
- [GitLab as an OAuth2 provider](../../api/oauth2.md#gitlab-as-an-oauth2-provider)
-- [GitLab Runner API - Authentication](../../api/ci/runners.md#authentication)
## Third-party resources
diff --git a/doc/user/group/index.md b/doc/user/group/index.md
index 9e168e830e5..fbc05261a32 100644
--- a/doc/user/group/index.md
+++ b/doc/user/group/index.md
@@ -55,6 +55,12 @@ By doing so:
- John mentions everyone from his team with `@john-team`
- John mentions only his marketing team with `@john-team/marketing`
+## Issues and merge requests within a group
+
+Issues and merge requests are part of projects. For a given group, view all the
+[issues](../project/issues/index.md#issues-per-group) and [merge requests](../project/merge_requests/index.md#merge-requests-per-group) across all the projects in that group,
+together in a single list view.
+
## Create a new group
> **Notes:**
diff --git a/doc/user/index.md b/doc/user/index.md
index d664fd62754..f239a15d441 100644
--- a/doc/user/index.md
+++ b/doc/user/index.md
@@ -119,6 +119,13 @@ When performing inline reviews to implementations
to your codebase through merge requests you can
gather feedback through [resolvable discussions](discussions/index.md#resolvable-discussions).
+### GitLab Flavored Markdown (GFM)
+
+Read through the [GFM documentation](markdown.md) to learn how to apply
+the best of GitLab Flavored Markdown in your discussions, comments,
+issues and merge requests descriptions, and everywhere else GMF is
+supported.
+
## Todos
Never forget to reply to your collaborators. [GitLab Todos](../workflow/todos.md)
@@ -126,6 +133,10 @@ are a tool for working faster and more effectively with your team,
by listing all user or group mentions, as well as issues and merge
requests you're assigned to.
+## Search
+
+[Search and filter](search/index.md) through groups, projects, issues, merge requests, files, code, and more.
+
## Snippets
[Snippets](snippets.md) are code blocks that you want to store in GitLab, from which
diff --git a/doc/user/profile/img/profile_settings_dropdown.png b/doc/user/profile/img/profile_settings_dropdown.png
new file mode 100644
index 00000000000..a2c620642e2
--- /dev/null
+++ b/doc/user/profile/img/profile_settings_dropdown.png
Binary files differ
diff --git a/doc/workflow/gpg_signed_commits/img/profile_settings_gpg_keys_paste_pub.png b/doc/user/project/gpg_signed_commits/img/profile_settings_gpg_keys_paste_pub.png
index 8e26d98f1b0..8e26d98f1b0 100644
--- a/doc/workflow/gpg_signed_commits/img/profile_settings_gpg_keys_paste_pub.png
+++ b/doc/user/project/gpg_signed_commits/img/profile_settings_gpg_keys_paste_pub.png
Binary files differ
diff --git a/doc/user/project/gpg_signed_commits/img/profile_settings_gpg_keys_single_key.png b/doc/user/project/gpg_signed_commits/img/profile_settings_gpg_keys_single_key.png
new file mode 100644
index 00000000000..5c14df36d73
--- /dev/null
+++ b/doc/user/project/gpg_signed_commits/img/profile_settings_gpg_keys_single_key.png
Binary files differ
diff --git a/doc/user/project/gpg_signed_commits/img/project_signed_and_unsigned_commits.png b/doc/user/project/gpg_signed_commits/img/project_signed_and_unsigned_commits.png
new file mode 100644
index 00000000000..33936a7d6d7
--- /dev/null
+++ b/doc/user/project/gpg_signed_commits/img/project_signed_and_unsigned_commits.png
Binary files differ
diff --git a/doc/workflow/gpg_signed_commits/img/project_signed_commit_unverified_signature.png b/doc/user/project/gpg_signed_commits/img/project_signed_commit_unverified_signature.png
index 22565cf7c7e..22565cf7c7e 100644
--- a/doc/workflow/gpg_signed_commits/img/project_signed_commit_unverified_signature.png
+++ b/doc/user/project/gpg_signed_commits/img/project_signed_commit_unverified_signature.png
Binary files differ
diff --git a/doc/workflow/gpg_signed_commits/img/project_signed_commit_verified_signature.png b/doc/user/project/gpg_signed_commits/img/project_signed_commit_verified_signature.png
index 1778b2ddf2b..1778b2ddf2b 100644
--- a/doc/workflow/gpg_signed_commits/img/project_signed_commit_verified_signature.png
+++ b/doc/user/project/gpg_signed_commits/img/project_signed_commit_verified_signature.png
Binary files differ
diff --git a/doc/user/project/gpg_signed_commits/index.md b/doc/user/project/gpg_signed_commits/index.md
new file mode 100644
index 00000000000..3ea2203c895
--- /dev/null
+++ b/doc/user/project/gpg_signed_commits/index.md
@@ -0,0 +1,245 @@
+# Signing commits with GPG
+
+> [Introduced][ce-9546] in GitLab 9.5.
+
+GitLab can show whether a commit is verified or not when signed with a GPG key.
+All you need to do is upload the public GPG key in your profile settings.
+
+GPG verified tags are not supported yet.
+
+## Getting started with GPG
+
+Here are a few guides to get you started with GPG:
+
+- [Git Tools - Signing Your Work](https://git-scm.com/book/en/v2/Git-Tools-Signing-Your-Work)
+- [Managing OpenPGP Keys](https://riseup.net/en/security/message-security/openpgp/gpg-keys)
+- [OpenPGP Best Practices](https://riseup.net/en/security/message-security/openpgp/best-practices)
+- [Creating a new GPG key with subkeys](https://www.void.gr/kargig/blog/2013/12/02/creating-a-new-gpg-key-with-subkeys/) (advanced)
+
+## How GitLab handles GPG
+
+GitLab uses its own keyring to verify the GPG signature. It does not access any
+public key server.
+
+In order to have a commit verified on GitLab the corresponding public key needs
+to be uploaded to GitLab. For a signature to be verified two prerequisites need
+to be met:
+
+1. The public key needs to be added your GitLab account
+1. One of the emails in the GPG key matches your **primary** email
+
+## Generating a GPG key
+
+If you don't already have a GPG key, the following steps will help you get
+started:
+
+1. [Install GPG](https://www.gnupg.org/download/index.html) for your operating system
+1. Generate the private/public key pair with the following command:
+
+ ```sh
+ gpg --full-gen-key
+ ```
+
+ This will spawn a series of questions.
+
+1. The first question is which algorithm can be used. Select the kind you want
+ or press <kbd>Enter</kbd> to choose the default (RSA and RSA):
+
+ ```
+ Please select what kind of key you want:
+ (1) RSA and RSA (default)
+ (2) DSA and Elgamal
+ (3) DSA (sign only)
+ (4) RSA (sign only)
+ Your selection? 1
+ ```
+
+1. The next question is key length. We recommend to choose the highest value
+ which is `4096`:
+
+ ```
+ RSA keys may be between 1024 and 4096 bits long.
+ What keysize do you want? (2048) 4096
+ Requested keysize is 4096 bits
+ ```
+1. Next, you need to specify the validity period of your key. This is something
+ subjective, and you can use the default value which is to never expire:
+
+ ```
+ Please specify how long the key should be valid.
+ 0 = key does not expire
+ <n> = key expires in n days
+ <n>w = key expires in n weeks
+ <n>m = key expires in n months
+ <n>y = key expires in n years
+ Key is valid for? (0) 0
+ Key does not expire at all
+ ```
+
+1. Confirm that the answers you gave were correct by typing `y`:
+
+ ```
+ Is this correct? (y/N) y
+ ```
+
+1. Enter you real name, the email address to be associated with this key (should
+ match the primary email address you use in GitLab) and an optional comment
+ (press <kbd>Enter</kbd> to skip):
+
+ ```
+ GnuPG needs to construct a user ID to identify your key.
+
+ Real name: Mr. Robot
+ Email address: mr@robot.sh
+ Comment:
+ You selected this USER-ID:
+ "Mr. Robot <mr@robot.sh>"
+
+ Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? O
+ ```
+
+1. Pick a strong password when asked and type it twice to confirm.
+1. Use the following command to list the private GPG key you just created:
+
+ ```
+ gpg --list-secret-keys mr@robot.sh
+ ```
+
+ Replace `mr@robot.sh` with the email address you entered above.
+
+1. Copy the GPG key ID that starts with `sec`. In the following example, that's
+ `0x30F2B65B9246B6CA`:
+
+ ```
+ sec rsa4096/0x30F2B65B9246B6CA 2017-08-18 [SC]
+ D5E4F29F3275DC0CDA8FFC8730F2B65B9246B6CA
+ uid [ultimate] Mr. Robot <mr@robot.sh>
+ ssb rsa4096/0xB7ABC0813E4028C0 2017-08-18 [E]
+ ```
+
+1. Export the public key of that ID (replace your key ID from the previous step):
+
+ ```
+ gpg --armor --export 0x30F2B65B9246B6CA
+ ```
+
+1. Finally, copy the public key and [add it in your profile settings](#adding-a-gpg-key-to-your-account)
+
+## Adding a GPG key to your account
+
+>**Note:**
+Once you add a key, you cannot edit it, only remove it. In case the paste
+didn't work, you'll have to remove the offending key and re-add it.
+
+You can add a GPG key in your profile's settings:
+
+1. On the upper right corner, click on your avatar and go to your **Settings**.
+
+ ![Settings dropdown](../../profile/img/profile_settings_dropdown.png)
+
+1. Navigate to the **GPG keys** tab and paste your _public_ key in the 'Key'
+ box.
+
+ ![Paste GPG public key](img/profile_settings_gpg_keys_paste_pub.png)
+
+1. Finally, click on **Add key** to add it to GitLab. You will be able to see
+ its fingerprint, the corresponding email address and creation date.
+
+ ![GPG key single page](img/profile_settings_gpg_keys_single_key.png)
+
+## Associating your GPG key with Git
+
+After you have [created your GPG key](#generating-a-gpg-key) and [added it to
+your account](#adding-a-gpg-key-to-your-account), it's time to tell Git which
+key to use.
+
+1. Use the following command to list the private GPG key you just created:
+
+ ```
+ gpg --list-secret-keys mr@robot.sh
+ ```
+
+ Replace `mr@robot.sh` with the email address you entered above.
+
+1. Copy the GPG key ID that starts with `sec`. In the following example, that's
+ `0x30F2B65B9246B6CA`:
+
+ ```
+ sec rsa4096/0x30F2B65B9246B6CA 2017-08-18 [SC]
+ D5E4F29F3275DC0CDA8FFC8730F2B65B9246B6CA
+ uid [ultimate] Mr. Robot <mr@robot.sh>
+ ssb rsa4096/0xB7ABC0813E4028C0 2017-08-18 [E]
+ ```
+
+1. Tell Git to use that key to sign the commits:
+
+ ```
+ git config --global user.signingkey 0x30F2B65B9246B6CA
+ ```
+
+ Replace `0x30F2B65B9246B6CA` with your GPG key ID.
+
+## Signing commits
+
+After you have [created your GPG key](#generating-a-gpg-key) and [added it to
+your account](#adding-a-gpg-key-to-your-account), you can start signing your
+commits:
+
+1. Commit like you used to, the only difference is the addition of the `-S` flag:
+
+ ```
+ git commit -S -m "My commit msg"
+ ```
+
+1. Enter the passphrase of your GPG key when asked.
+1. Push to GitLab and check that your commits [are verified](#verifying-commits).
+
+If you don't want to type the `-S` flag every time you commit, you can tell Git
+to sign your commits automatically:
+
+```
+git config --global commit.gpgsign true
+```
+
+## Verifying commits
+
+1. Within a project or [merge request](../merge_requests/index.md), navigate to
+ the **Commits** tab. Signed commits will show a badge containing either
+ "Verified" or "Unverified", depending on the verification status of the GPG
+ signature.
+
+ ![Signed and unsigned commits](img/project_signed_and_unsigned_commits.png)
+
+1. By clicking on the GPG badge, details of the signature are displayed.
+
+ ![Signed commit with verified signature](img/project_signed_commit_verified_signature.png)
+
+ ![Signed commit with verified signature](img/project_signed_commit_unverified_signature.png)
+
+## Revoking a GPG key
+
+Revoking a key **unverifies** already signed commits. Commits that were
+verified by using this key will change to an unverified state. Future commits
+will also stay unverified once you revoke this key. This action should be used
+in case your key has been compromised.
+
+To revoke a GPG key:
+
+1. On the upper right corner, click on your avatar and go to your **Settings**.
+1. Navigate to the **GPG keys** tab.
+1. Click on **Revoke** besides the GPG key you want to delete.
+
+## Removing a GPG key
+
+Removing a key **does not unverify** already signed commits. Commits that were
+verified by using this key will stay verified. Only unpushed commits will stay
+unverified once you remove this key. To unverify already signed commits, you need
+to [revoke the associated GPG key](#revoking-a-gpg-key) from your account.
+
+To remove a GPG key from your account:
+
+1. On the upper right corner, click on your avatar and go to your **Settings**.
+1. Navigate to the **GPG keys** tab.
+1. Click on the trash icon besides the GPG key you want to delete.
+
+[ce-9546]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/9546
diff --git a/doc/user/project/import/clearcase.md b/doc/user/project/import/clearcase.md
new file mode 100644
index 00000000000..f23623ed485
--- /dev/null
+++ b/doc/user/project/import/clearcase.md
@@ -0,0 +1,47 @@
+# Migrating from ClearCase
+
+[ClearCase](https://www-03.ibm.com/software/products/en/clearcase/) is a set of
+tools developed by IBM which also include a centralized version control system
+similar to Git.
+
+A good read of ClearCase's basic concepts is can be found in this [StackOverflow
+post](https://stackoverflow.com/a/645771/974710).
+
+The following table illustrates the main differences between ClearCase and Git:
+
+| Aspect | ClearCase | Git |
+| ------ | --------- | --- |
+| Repository model | Client-server | Distributed |
+| Revision IDs | Branch + number | Global alphanumeric ID |
+| Scope of Change | File | Directory tree snapshot |
+| Concurrency model | Merge | Merge |
+| Storage Method | Deltas | Full content |
+| Client | CLI, Eclipse, CC Client | CLI, Eclipse, Git client/GUIs |
+| Server | UNIX, Windows legacy systems | UNIX, macOS |
+| License | Proprietary | GPL |
+
+_Taken from the slides [ClearCase and the journey to Git](https://www.open.collab.net/media/pdfs/ClearCase-and-the-journey-to-Git.pdf) provided by collab.net_
+
+## Why migrate
+
+ClearCase can be difficult to manage both from a user and an admin perspective.
+Migrating to Git/GitLab there is:
+
+- **No licensing costs**, Git is GPL while ClearCase is proprietary.
+- **Shorter learning curve**, Git has a big community and a vast number of
+ tutorials to get you started.
+- **Integration with modern tools**, migrating to Git and GitLab you can have
+ an open source end-to-end software development platform with built-in version
+ control, issue tracking, code review, CI/CD, and more.
+
+## How to migrate
+
+While there doesn't exist a tool to fully migrate from ClearCase to Git, here
+are some useful links to get you started:
+
+- [Bridge for Git and ClearCase](https://github.com/charleso/git-cc)
+- [Slides "ClearCase and the journey to Git"](https://www.open.collab.net/media/pdfs/ClearCase-and-the-journey-to-Git.pdf)
+- [ClearCase to Git](https://therub.org/2013/07/19/clearcase-to-git/)
+- [Dual syncing ClearCase to Git](https://therub.org/2013/10/22/dual-syncing-clearcase-and-git/)
+- [Moving to Git from ClearCase](https://sateeshkumarb.wordpress.com/2011/01/15/moving-to-git-from-clearcase/)
+- [ClearCase to Git webinar](https://www.brighttalk.com/webcast/11817/162473/clearcase-to-git)
diff --git a/doc/user/project/import/index.md b/doc/user/project/import/index.md
index 06e8c81ef06..2a8728ed96e 100644
--- a/doc/user/project/import/index.md
+++ b/doc/user/project/import/index.md
@@ -6,6 +6,7 @@
1. [From FogBugz](fogbugz.md)
1. [From Gitea](gitea.md)
1. [From SVN](svn.md)
+1. [From ClearCase](clearcase.md)
In addition to the specific migration documentation above, you can import any
Git repository via HTTP from the New Project page. Be aware that if the
diff --git a/doc/user/project/index.md b/doc/user/project/index.md
index ba6ac2797b3..41a96246292 100644
--- a/doc/user/project/index.md
+++ b/doc/user/project/index.md
@@ -24,6 +24,7 @@ integrated platform
from messing with history or pushing code without review
- [Protected tags](protected_tags.md): Control over who has
permission to create tags, and prevent accidental update or deletion
+ - [Signing commits](gpg_signed_commits/index.md): use GPG to sign your commits
- [Merge Requests](merge_requests/index.md): Apply your branching
strategy and get reviewed by your team
- [Merge Request Approvals](https://docs.gitlab.com/ee/user/project/merge_requests/merge_request_approvals.html) (**EES/EEP**): Ask for approval before
diff --git a/doc/user/project/issues/img/group_issues_list_view.png b/doc/user/project/issues/img/group_issues_list_view.png
new file mode 100644
index 00000000000..5d20e8cbc89
--- /dev/null
+++ b/doc/user/project/issues/img/group_issues_list_view.png
Binary files differ
diff --git a/doc/user/project/issues/img/issue_tracker.png b/doc/user/project/issues/img/issue_tracker.png
deleted file mode 100755
index ab25cb64d13..00000000000
--- a/doc/user/project/issues/img/issue_tracker.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/issues/img/project_issues_list_view.png b/doc/user/project/issues/img/project_issues_list_view.png
new file mode 100644
index 00000000000..2fcc9e8d9da
--- /dev/null
+++ b/doc/user/project/issues/img/project_issues_list_view.png
Binary files differ
diff --git a/doc/user/project/issues/index.md b/doc/user/project/issues/index.md
index 1f78849a92c..20901e01f6e 100644
--- a/doc/user/project/issues/index.md
+++ b/doc/user/project/issues/index.md
@@ -7,7 +7,7 @@ of solving a problem.
It allows you, your team, and your collaborators to share
and discuss proposals before and while implementing them.
-Issues and the GitLab Issue Tracker are available in all
+GitLab Issues and the GitLab Issue Tracker are available in all
[GitLab Products](https://about.gitlab.com/products/) as
part of the [GitLab Workflow](https://about.gitlab.com/2016/10/25/gitlab-workflow-an-overview/).
@@ -48,11 +48,27 @@ for feature proposals and another one for bug reports.
## Issue Tracker
-The issue tracker is the collection of opened and closed issues created in a project.
+The Issue Tracker is the collection of opened and closed issues created in a project.
+It is available for all projects, from the moment the project is created.
-![Issue tracker](img/issue_tracker.png)
+Find the issue tracker by navigating to your **Project's homepage** > **Issues**.
-Find the issue tracker by navigating to your **Project's Dashboard** > **Issues**.
+### Issues per project
+
+When you access your project's issues, GitLab will present them in a list,
+and you can use the tabs available to quickly filter by open and closed issues.
+
+![Project issues list view](img/project_issues_list_view.png)
+
+You can also [search and filter](../../search/index.md#issues-and-merge-requests-per-project) the results more deeply with GitLab's search capacities.
+
+### Issues per group
+
+View all the issues in a group (that is, all the issues across all projects in that
+group) by navigating to **Group > Issues**. This view also has the open and closed
+issue tabs.
+
+![Group Issues list view](img/group_issues_list_view.png)
## GitLab Issues Functionalities
@@ -120,6 +136,12 @@ to find out more about this feature.
With [GitLab Enterprise Edition Starter](https://about.gitlab.com/gitlab-ee/), you can also
create various boards per project with [Multiple Issue Boards](https://docs.gitlab.com/ee/user/project/issue_board.html#multiple-issue-boards).
+### External Issue Tracker
+
+Alternatively to GitLab's built-in Issue Tracker, you can also use an [external
+tracker](../../../integration/external-issue-tracker.md) such as Jira, Redmine,
+or Bugzilla.
+
### Issue's API
Read through the [API documentation](../../../api/issues.md).
diff --git a/doc/user/project/merge_requests/img/group_merge_requests_list_view.png b/doc/user/project/merge_requests/img/group_merge_requests_list_view.png
new file mode 100644
index 00000000000..02a88d0112f
--- /dev/null
+++ b/doc/user/project/merge_requests/img/group_merge_requests_list_view.png
Binary files differ
diff --git a/doc/user/project/merge_requests/img/merge_request_diff_file_navigation.png b/doc/user/project/merge_requests/img/merge_request_diff_file_navigation.png
new file mode 100644
index 00000000000..9b8aee47411
--- /dev/null
+++ b/doc/user/project/merge_requests/img/merge_request_diff_file_navigation.png
Binary files differ
diff --git a/doc/user/project/merge_requests/img/project_merge_requests_list_view.png b/doc/user/project/merge_requests/img/project_merge_requests_list_view.png
new file mode 100644
index 00000000000..702ec1a2949
--- /dev/null
+++ b/doc/user/project/merge_requests/img/project_merge_requests_list_view.png
Binary files differ
diff --git a/doc/user/project/merge_requests/index.md b/doc/user/project/merge_requests/index.md
index 9bdf2a998d3..26c6277d33a 100644
--- a/doc/user/project/merge_requests/index.md
+++ b/doc/user/project/merge_requests/index.md
@@ -56,6 +56,23 @@ B. Consider you're a web developer writing a webpage for your company's:
1. Once approved, your merge request is [squashed and merged](https://docs.gitlab.com/ee/user/project/merge_requests/squash_and_merge.html), and [deployed to staging with GitLab Pages](https://about.gitlab.com/2016/08/26/ci-deployment-and-environments/) (Squash and Merge is available in GitLab Enterprise Edition Starter)
1. Your production team [cherry picks](#cherry-pick-changes) the merge commit into production
+## Merge requests per project
+
+View all the merge requests within a project by navigating to **Project > Merge Requests**.
+
+When you access your project's merge requests, GitLab will present them in a list,
+and you can use the tabs available to quickly filter by open and closed. You can also [search and filter the results](../../search/index.md#issues-and-merge-requests-per-project).
+
+![Project merge requests list view](img/project_merge_requests_list_view.png)
+
+## Merge requests per group
+
+View all the merge requests in a group (that is, all the merge requests across all projects in that
+group) by navigating to **Group > Merge Requests**. This view also has the open, merged, and closed
+merge request tabs, from which you can [search and filter the results](../../search/index.md#issues-and-merge-requests-per-group).
+
+![Group Issues list view](img/group_merge_requests_list_view.png)
+
## Authorization for merge requests
There are two main ways to have a merge request flow with GitLab:
@@ -120,6 +137,14 @@ have been marked as a **Work In Progress**.
[Learn more about settings a merge request as "Work In Progress".](work_in_progress_merge_requests.md)
+## Merge request diff file navigation
+
+The diff view has a persistent dropdown for file navigation. As you scroll through
+diffs with a large number of files and/or many changes in those files, you can
+easily jump to any changed file through the dropdown navigation.
+
+![Merge request diff file navigation](img/merge_request_diff_file_navigation.png)
+
## Ignore whitespace changes in Merge Request diff view
If you click the **Hide whitespace changes** button, you can see the diff
@@ -141,7 +166,6 @@ all your changes will be available to preview by anyone with the Review Apps lin
[Read more about Review Apps.](../../../ci/review_apps/index.md)
-
## Tips
Here are some tips that will help you be more efficient with merge requests in
@@ -230,4 +254,4 @@ git checkout origin/merge-requests/1
```
[protected branches]: ../protected_branches.md
-[ee]: https://about.gitlab.com/gitlab-ee/ "GitLab Enterprise Edition"
+[ee]: https://about.gitlab.com/gitlab-ee/ "GitLab Enterprise Edition" \ No newline at end of file
diff --git a/doc/user/search/index.md b/doc/user/search/index.md
index 79f34fd29ba..f5c7ce49e8e 100644
--- a/doc/user/search/index.md
+++ b/doc/user/search/index.md
@@ -27,7 +27,7 @@ on the search field on the top-right of your screen:
![shortcut to your issues and mrs](img/issues_mrs_shortcut.png)
-## Issues and merge requests per project
+### Issues and merge requests per project
If you want to search for issues present in a specific project, navigate to
a project's **Issues** tab, and click on the field **Search or filter results...**. It will
@@ -40,7 +40,7 @@ The same process is valid for merge requests. Navigate to your project's **Merge
and click **Search or filter results...**. Merge requests can be filtered by author, assignee,
milestone, and label.
-## Issues and merge requests per group
+### Issues and merge requests per group
Similar to **Issues and merge requests per project**, you can also search for issues
within a group. Navigate to a group's **Issues** tab and query search results in
@@ -48,6 +48,10 @@ the same way as you do for projects.
![filter issues in a group](img/group_issues_filter.png)
+The same process is valid for merge requests. Navigate to your project's **Merge Requests** tab.
+The search and filter UI currently uses dropdowns. In a future release, the same
+dynamic UI as above will be carried over here.
+
## Search history
You can view recent searches by clicking on the little arrow-clock icon, which is to the left of the search input. Click the search entry to run that search again. This feature is available for issues and merge requests. Searches are stored locally in your browser.
diff --git a/doc/workflow/gpg_signed_commits/img/profile_settings_gpg_keys.png b/doc/workflow/gpg_signed_commits/img/profile_settings_gpg_keys.png
deleted file mode 100644
index e525083918b..00000000000
--- a/doc/workflow/gpg_signed_commits/img/profile_settings_gpg_keys.png
+++ /dev/null
Binary files differ
diff --git a/doc/workflow/gpg_signed_commits/img/profile_settings_gpg_keys_single_key.png b/doc/workflow/gpg_signed_commits/img/profile_settings_gpg_keys_single_key.png
deleted file mode 100644
index f715c46adc3..00000000000
--- a/doc/workflow/gpg_signed_commits/img/profile_settings_gpg_keys_single_key.png
+++ /dev/null
Binary files differ
diff --git a/doc/workflow/gpg_signed_commits/img/project_signed_and_unsigned_commits.png b/doc/workflow/gpg_signed_commits/img/project_signed_and_unsigned_commits.png
deleted file mode 100644
index 16ec2d031ae..00000000000
--- a/doc/workflow/gpg_signed_commits/img/project_signed_and_unsigned_commits.png
+++ /dev/null
Binary files differ
diff --git a/doc/workflow/gpg_signed_commits/index.md b/doc/workflow/gpg_signed_commits/index.md
deleted file mode 100644
index 7d5762d2b9d..00000000000
--- a/doc/workflow/gpg_signed_commits/index.md
+++ /dev/null
@@ -1,84 +0,0 @@
-# Signing commits with GPG
-
-## Getting started
-
-- [Git Tools - Signing Your Work](https://git-scm.com/book/en/v2/Git-Tools-Signing-Your-Work)
-- [Git Tools - Signing Your Work: GPG introduction](https://git-scm.com/book/en/v2/Git-Tools-Signing-Your-Work#_gpg_introduction)
-- [Git Tools - Signing Your Work: Signing commits](https://git-scm.com/book/en/v2/Git-Tools-Signing-Your-Work#_signing_commits)
-
-## How GitLab handles GPG
-
-GitLab uses its own keyring to verify the GPG signature. It does not access any
-public key server.
-
-In order to have a commit verified on GitLab the corresponding public key needs
-to be uploaded to GitLab.
-
-For a signature to be verified two prerequisites need to be met:
-
-1. The public key needs to be added to GitLab
-1. One of the emails in the GPG key matches your **primary** email
-
-## Add a GPG key
-
-1. On the upper right corner, click on your avatar and go to your **Settings**.
-
- ![Settings dropdown](../../gitlab-basics/img/profile_settings.png)
-
-1. Navigate to the **GPG keys** tab.
-
- ![GPG Keys](img/profile_settings_gpg_keys.png)
-
-1. Paste your **public** key in the 'Key' box.
-
- ![Paste GPG public key](img/profile_settings_gpg_keys_paste_pub.png)
-
-1. Finally, click on **Add key** to add it to GitLab. You will be able to see
- its fingerprint, the corresponding email address and creation date.
-
- ![GPG key single page](img/profile_settings_gpg_keys_single_key.png)
-
->**Note:**
-Once you add a key, you cannot edit it, only remove it. In case the paste
-didn't work, you will have to remove the offending key and re-add it.
-
-## Remove a GPG key
-
-1. On the upper right corner, click on your avatar and go to your **Settings**.
-
-1. Navigate to the **GPG keys** tab.
-
-1. Click on the trash icon besides the GPG key you want to delete.
-
->**Note:**
-Removing a key **does not unverify** already signed commits. Commits that were
-verified by using this key will stay verified. Only unpushed commits will stay
-unverified once you remove this key.
-
-## Revoke a GPG key
-
-1. On the upper right corner, click on your avatar and go to your **Settings**.
-
-1. Navigate to the **GPG keys** tab.
-
-1. Click on **Revoke** besides the GPG key you want to delete.
-
->**Note:**
-Revoking a key **unverifies** already signed commits. Commits that were
-verified by using this key will change to an unverified state. Future commits
-will also stay unverified once you revoke this key. This action should be used
-in case your key has been compromised.
-
-## Verifying commits
-
-1. Within a project navigate to the **Commits** tag. Signed commits will show a
- badge containing either "Verified" or "Unverified", depending on the
- verification status of the GPG signature.
-
- ![Signed and unsigned commits](img/project_signed_and_unsigned_commits.png)
-
-1. By clicking on the GPG badge details of the signature are displayed.
-
- ![Signed commit with verified signature](img/project_signed_commit_verified_signature.png)
-
- ![Signed commit with verified signature](img/project_signed_commit_unverified_signature.png)
diff --git a/docker/README.md b/docker/README.md
index f9e12c5733b..61b41d2f109 100644
--- a/docker/README.md
+++ b/docker/README.md
@@ -1,7 +1,3 @@
# GitLab Docker images
-* The official GitLab Community Edition Docker image is [available on Docker Hub](https://hub.docker.com/r/gitlab/gitlab-ce/).
-* The official GitLab Enterprise Edition Docker image is [available on Docker Hub](https://hub.docker.com/r/gitlab/gitlab-ee/).
-* The complete usage guide can be found in [Using GitLab Docker images](https://docs.gitlab.com/omnibus/docker/)
-* The Dockerfile used for building public images is in [Omnibus Repository](https://gitlab.com/gitlab-org/omnibus-gitlab/tree/master/docker)
-* Check the guide for [creating Omnibus-based Docker Image](https://docs.gitlab.com/omnibus/build/README.html#build-docker-image)
+This content has been moved to [our documentation site](https://docs.gitlab.com/ce/install/docker.html).
diff --git a/features/project/source/search_code.feature b/features/project/source/search_code.feature
deleted file mode 100644
index 4f9dcea249f..00000000000
--- a/features/project/source/search_code.feature
+++ /dev/null
@@ -1,15 +0,0 @@
-Feature: Project Source Search Code
- Background:
- Given I sign in as a user
-
- Scenario: Search for term "coffee"
- Given I own project "Shop"
- And I visit project source page
- When I search for term "coffee"
- Then I should see files from repository containing "coffee"
-
- Scenario: Search on empty project
- Given I own an empty project
- And I visit my project's home page
- When I search for term "coffee"
- Then I should see empty result
diff --git a/features/project/star.feature b/features/project/star.feature
deleted file mode 100644
index 618f44fe6dc..00000000000
--- a/features/project/star.feature
+++ /dev/null
@@ -1,39 +0,0 @@
-@project-stars
-Feature: Project Star
- Scenario: New projects have 0 stars
- Given public project "Community"
- When I visit project "Community" page
- Then The project has no stars
-
- Scenario: Empty projects show star count
- Given public empty project "Empty Public Project"
- When I visit empty project page
- Then The project has no stars
-
- Scenario: Signed off users can't star projects
- Given public project "Community"
- And I visit project "Community" page
- When I click on the star toggle button
- Then I redirected to sign in page
-
- @javascript
- Scenario: Signed in users can toggle star
- Given I sign in as "John Doe"
- And public project "Community"
- And I visit project "Community" page
- When I click on the star toggle button
- Then The project has 1 star
- When I click on the star toggle button
- Then The project has 0 stars
-
- @javascript
- Scenario: Star count sums stars
- Given I sign in as "John Doe"
- And public project "Community"
- And I visit project "Community" page
- And I click on the star toggle button
- And I logout
- And I sign in as "Mary Jane"
- And I visit project "Community" page
- When I click on the star toggle button
- Then The project has 2 stars
diff --git a/features/steps/project/graph.rb b/features/steps/project/graph.rb
index e78e25318a6..b9cddf4041d 100644
--- a/features/steps/project/graph.rb
+++ b/features/steps/project/graph.rb
@@ -38,9 +38,9 @@ class Spinach::Features::ProjectGraph < Spinach::FeatureSteps
step 'page should have CI graphs' do
expect(page).to have_content 'Overall'
- expect(page).to have_content 'Jobs for last week'
- expect(page).to have_content 'Jobs for last month'
- expect(page).to have_content 'Jobs for last year'
+ expect(page).to have_content 'Pipelines for last week'
+ expect(page).to have_content 'Pipelines for last month'
+ expect(page).to have_content 'Pipelines for last year'
expect(page).to have_content 'Commit duration in minutes for last 30 commits'
end
diff --git a/features/steps/project/pages.rb b/features/steps/project/pages.rb
index 275fb4fc010..bb69c0d6e99 100644
--- a/features/steps/project/pages.rb
+++ b/features/steps/project/pages.rb
@@ -35,7 +35,10 @@ class Spinach::Features::ProjectPages < Spinach::FeatureSteps
end
step 'pages are deployed' do
- pipeline = @project.pipelines.create(ref: 'HEAD', sha: @project.commit('HEAD').sha)
+ pipeline = @project.pipelines.create(ref: 'HEAD',
+ sha: @project.commit('HEAD').sha,
+ source: :push)
+
build = build(:ci_build,
project: @project,
pipeline: pipeline,
@@ -43,6 +46,7 @@ class Spinach::Features::ProjectPages < Spinach::FeatureSteps
artifacts_file: fixture_file_upload(Rails.root + 'spec/fixtures/pages.zip'),
artifacts_metadata: fixture_file_upload(Rails.root + 'spec/fixtures/pages.zip.meta')
)
+
result = ::Projects::UpdatePagesService.new(@project, build).execute
expect(result[:status]).to eq(:success)
end
diff --git a/features/steps/project/source/search_code.rb b/features/steps/project/source/search_code.rb
deleted file mode 100644
index feee756d7ec..00000000000
--- a/features/steps/project/source/search_code.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-class Spinach::Features::ProjectSourceSearchCode < Spinach::FeatureSteps
- include SharedAuthentication
- include SharedProject
- include SharedPaths
-
- step 'I search for term "coffee"' do
- fill_in "search", with: "coffee"
- click_button "Go"
- end
-
- step 'I should see files from repository containing "coffee"' do
- expect(page).to have_content 'coffee'
- expect(page).to have_content 'CONTRIBUTING.md'
- end
-
- step 'I should see empty result' do
- expect(page).to have_content "We couldn't find any"
- end
-end
diff --git a/features/steps/project/star.rb b/features/steps/project/star.rb
deleted file mode 100644
index 9f7c748a3b7..00000000000
--- a/features/steps/project/star.rb
+++ /dev/null
@@ -1,37 +0,0 @@
-class Spinach::Features::ProjectStar < Spinach::FeatureSteps
- include SharedAuthentication
- include SharedProject
- include SharedPaths
- include SharedUser
-
- step "The project has no stars" do
- expect(page).not_to have_content '.toggle-star'
- end
-
- step "The project has 0 stars" do
- has_n_stars(0)
- end
-
- step "The project has 1 star" do
- has_n_stars(1)
- end
-
- step "The project has 2 stars" do
- has_n_stars(2)
- end
-
- # Requires @javascript
- step "I click on the star toggle button" do
- find(".star-btn", visible: true).click
- end
-
- step 'I redirected to sign in page' do
- expect(current_path).to eq new_user_session_path
- end
-
- protected
-
- def has_n_stars(n)
- expect(page).to have_css(".star-count", text: n, visible: true)
- end
-end
diff --git a/features/steps/shared/paths.rb b/features/steps/shared/paths.rb
index 830263fd038..be69a96c3ee 100644
--- a/features/steps/shared/paths.rb
+++ b/features/steps/shared/paths.rb
@@ -304,10 +304,6 @@ module SharedPaths
visit project_commits_path(@project, 'stable', { limit: 5 })
end
- step 'I visit project source page' do
- visit project_tree_path(@project, root_ref)
- end
-
step 'I visit blob file from repo' do
visit project_blob_path(@project, File.join(sample_commit.id, sample_blob.path))
end
diff --git a/lib/after_commit_queue.rb b/lib/after_commit_queue.rb
index b67575a3ac2..4750a2c373a 100644
--- a/lib/after_commit_queue.rb
+++ b/lib/after_commit_queue.rb
@@ -7,7 +7,7 @@ module AfterCommitQueue
end
def run_after_commit(method = nil, &block)
- _after_commit_queue << proc { self.send(method) } if method
+ _after_commit_queue << proc { self.send(method) } if method # rubocop:disable GitlabSecurity/PublicSend
_after_commit_queue << block if block
true
end
diff --git a/lib/api/access_requests.rb b/lib/api/access_requests.rb
index cdacf9839e5..4fa9b2b2494 100644
--- a/lib/api/access_requests.rb
+++ b/lib/api/access_requests.rb
@@ -67,10 +67,12 @@ module API
end
delete ":id/access_requests/:user_id" do
source = find_source(source_type, params[:id])
+ member = source.requesters.find_by!(user_id: params[:user_id])
- status 204
- ::Members::DestroyService.new(source, current_user, params)
- .execute(:requesters)
+ destroy_conditionally!(member) do
+ ::Members::DestroyService.new(source, current_user, params)
+ .execute(:requesters)
+ end
end
end
end
diff --git a/lib/api/award_emoji.rb b/lib/api/award_emoji.rb
index 5a028fc9d0b..8e3851640da 100644
--- a/lib/api/award_emoji.rb
+++ b/lib/api/award_emoji.rb
@@ -88,8 +88,7 @@ module API
unauthorized! unless award.user == current_user || current_user.admin?
- status 204
- award.destroy
+ destroy_conditionally!(award)
end
end
end
diff --git a/lib/api/boards.rb b/lib/api/boards.rb
index 5a2d7a681e3..0d11c5fc971 100644
--- a/lib/api/boards.rb
+++ b/lib/api/boards.rb
@@ -122,13 +122,13 @@ module API
end
delete "/lists/:list_id" do
authorize!(:admin_list, user_project)
-
list = board_lists.find(params[:list_id])
- service = ::Boards::Lists::DestroyService.new(user_project, current_user)
-
- unless service.execute(list)
- render_api_error!({ error: 'List could not be deleted!' }, 400)
+ destroy_conditionally!(list) do |list|
+ service = ::Boards::Lists::DestroyService.new(user_project, current_user)
+ unless service.execute(list)
+ render_api_error!({ error: 'List could not be deleted!' }, 400)
+ end
end
end
end
diff --git a/lib/api/branches.rb b/lib/api/branches.rb
index d3dbf941298..b87f7cdbad1 100644
--- a/lib/api/branches.rb
+++ b/lib/api/branches.rb
@@ -125,11 +125,18 @@ module API
delete ':id/repository/branches/:branch', requirements: BRANCH_ENDPOINT_REQUIREMENTS do
authorize_push_project
- result = DeleteBranchService.new(user_project, current_user)
- .execute(params[:branch])
+ branch = user_project.repository.find_branch(params[:branch])
+ not_found!('Branch') unless branch
+
+ commit = user_project.repository.commit(branch.dereferenced_target)
+
+ destroy_conditionally!(commit, last_update_field: :authored_date) do
+ result = DeleteBranchService.new(user_project, current_user)
+ .execute(params[:branch])
- if result[:status] != :success
- render_api_error!(result[:message], result[:return_code])
+ if result[:status] != :success
+ render_api_error!(result[:message], result[:return_code])
+ end
end
end
diff --git a/lib/api/broadcast_messages.rb b/lib/api/broadcast_messages.rb
index 9980aec4752..0b45621ce7b 100644
--- a/lib/api/broadcast_messages.rb
+++ b/lib/api/broadcast_messages.rb
@@ -91,8 +91,7 @@ module API
delete ':id' do
message = find_message
- status 204
- message.destroy
+ destroy_conditionally!(message)
end
end
end
diff --git a/lib/api/deploy_keys.rb b/lib/api/deploy_keys.rb
index 42e7c1486b0..f405c341398 100644
--- a/lib/api/deploy_keys.rb
+++ b/lib/api/deploy_keys.rb
@@ -125,8 +125,7 @@ module API
key = user_project.deploy_keys_projects.find_by(deploy_key_id: params[:key_id])
not_found!('Deploy Key') unless key
- status 204
- key.destroy
+ destroy_conditionally!(key)
end
end
end
diff --git a/lib/api/environments.rb b/lib/api/environments.rb
index c774a5c6685..e33269f9483 100644
--- a/lib/api/environments.rb
+++ b/lib/api/environments.rb
@@ -79,8 +79,7 @@ module API
environment = user_project.environments.find(params[:environment_id])
- status 204
- environment.destroy
+ destroy_conditionally!(environment)
end
desc 'Stops an existing environment' do
diff --git a/lib/api/group_variables.rb b/lib/api/group_variables.rb
index f64da4ab77b..25152f30998 100644
--- a/lib/api/group_variables.rb
+++ b/lib/api/group_variables.rb
@@ -88,8 +88,7 @@ module API
variable = user_group.variables.find_by(key: params[:key])
not_found!('GroupVariable') unless variable
- status 204
- variable.destroy
+ destroy_conditionally!(variable)
end
end
end
diff --git a/lib/api/groups.rb b/lib/api/groups.rb
index 49c3b2278c7..8c494a54329 100644
--- a/lib/api/groups.rb
+++ b/lib/api/groups.rb
@@ -2,12 +2,16 @@ module API
class Groups < Grape::API
include PaginationParams
- before { authenticate! }
+ before { authenticate_non_get! }
helpers do
params :optional_params_ce do
optional :description, type: String, desc: 'The description of the group'
- optional :visibility, type: String, values: Gitlab::VisibilityLevel.string_values, desc: 'The visibility of the group'
+ optional :visibility, type: String,
+ values: Gitlab::VisibilityLevel.string_values,
+ default: Gitlab::VisibilityLevel.string_level(
+ Gitlab::CurrentSettings.current_application_settings.default_group_visibility),
+ desc: 'The visibility of the group'
optional :lfs_enabled, type: Boolean, desc: 'Enable/disable LFS for the projects in this group'
optional :request_access_enabled, type: Boolean, desc: 'Allow users to request member access'
optional :share_with_group_lock, type: Boolean, desc: 'Prevent sharing a project with another group within this group'
@@ -47,16 +51,8 @@ module API
use :pagination
end
get do
- groups = if params[:owned]
- current_user.owned_groups
- elsif current_user.admin
- Group.all
- elsif params[:all_available]
- GroupsFinder.new(current_user).execute
- else
- current_user.groups
- end
-
+ find_params = { all_available: params[:all_available], owned: params[:owned] }
+ groups = GroupsFinder.new(current_user, find_params).execute
groups = groups.search(params[:search]) if params[:search].present?
groups = groups.where.not(id: params[:skip_groups]) if params[:skip_groups].present?
groups = groups.reorder(params[:order_by] => params[:sort])
@@ -126,8 +122,9 @@ module API
group = find_group!(params[:id])
authorize! :admin_group, group
- status 204
- ::Groups::DestroyService.new(group, current_user).execute
+ destroy_conditionally!(group) do |group|
+ ::Groups::DestroyService.new(group, current_user).execute
+ end
end
desc 'Get a list of projects in this group.' do
diff --git a/lib/api/helpers.rb b/lib/api/helpers.rb
index b56fd2388b3..84980864151 100644
--- a/lib/api/helpers.rb
+++ b/lib/api/helpers.rb
@@ -11,6 +11,25 @@ module API
declared(params, options).to_h.symbolize_keys
end
+ def check_unmodified_since!(last_modified)
+ if_unmodified_since = Time.parse(headers['If-Unmodified-Since']) rescue nil
+
+ if if_unmodified_since && last_modified && last_modified > if_unmodified_since
+ render_api_error!('412 Precondition Failed', 412)
+ end
+ end
+
+ def destroy_conditionally!(resource, last_update_field: :updated_at)
+ check_unmodified_since!(resource.public_send(last_update_field))
+
+ status 204
+ if block_given?
+ yield resource
+ else
+ resource.destroy
+ end
+ end
+
def current_user
return @current_user if defined?(@current_user)
diff --git a/lib/api/issues.rb b/lib/api/issues.rb
index 4cec1145f3a..6503629e2a2 100644
--- a/lib/api/issues.rb
+++ b/lib/api/issues.rb
@@ -230,8 +230,8 @@ module API
not_found!('Issue') unless issue
authorize!(:destroy_issue, issue)
- status 204
- issue.destroy
+
+ destroy_conditionally!(issue)
end
desc 'List merge requests closing issue' do
diff --git a/lib/api/labels.rb b/lib/api/labels.rb
index 4520c98d951..c0cf618ee8d 100644
--- a/lib/api/labels.rb
+++ b/lib/api/labels.rb
@@ -56,8 +56,7 @@ module API
label = user_project.labels.find_by(title: params[:name])
not_found!('Label') unless label
- status 204
- label.destroy
+ destroy_conditionally!(label)
end
desc 'Update an existing label. At least one optional parameter is required.' do
diff --git a/lib/api/members.rb b/lib/api/members.rb
index bb970b7cd54..a5d3d7f25a0 100644
--- a/lib/api/members.rb
+++ b/lib/api/members.rb
@@ -93,11 +93,11 @@ module API
end
delete ":id/members/:user_id" do
source = find_source(source_type, params[:id])
- # Ensure that memeber exists
- source.members.find_by!(user_id: params[:user_id])
+ member = source.members.find_by!(user_id: params[:user_id])
- status 204
- ::Members::DestroyService.new(source, current_user, declared_params).execute
+ destroy_conditionally!(member) do
+ ::Members::DestroyService.new(source, current_user, declared_params).execute
+ end
end
end
end
diff --git a/lib/api/merge_requests.rb b/lib/api/merge_requests.rb
index 8810d4e441d..969c6064662 100644
--- a/lib/api/merge_requests.rb
+++ b/lib/api/merge_requests.rb
@@ -164,8 +164,8 @@ module API
merge_request = find_project_merge_request(params[:merge_request_iid])
authorize!(:destroy_merge_request, merge_request)
- status 204
- merge_request.destroy
+
+ destroy_conditionally!(merge_request)
end
params do
diff --git a/lib/api/notes.rb b/lib/api/notes.rb
index 4e4e473994b..e116448c15b 100644
--- a/lib/api/notes.rb
+++ b/lib/api/notes.rb
@@ -129,10 +129,12 @@ module API
end
delete ":id/#{noteables_str}/:noteable_id/notes/:note_id" do
note = user_project.notes.find(params[:note_id])
+
authorize! :admin_note, note
- status 204
- ::Notes::DestroyService.new(user_project, current_user).execute(note)
+ destroy_conditionally!(note) do |note|
+ ::Notes::DestroyService.new(user_project, current_user).execute(note)
+ end
end
end
end
diff --git a/lib/api/pipeline_schedules.rb b/lib/api/pipeline_schedules.rb
index dbeaf9e17ef..e3123ef4e2d 100644
--- a/lib/api/pipeline_schedules.rb
+++ b/lib/api/pipeline_schedules.rb
@@ -117,8 +117,7 @@ module API
not_found!('PipelineSchedule') unless pipeline_schedule
authorize! :admin_pipeline_schedule, pipeline_schedule
- status :accepted
- present pipeline_schedule.destroy, with: Entities::PipelineScheduleDetails
+ destroy_conditionally!(pipeline_schedule)
end
end
diff --git a/lib/api/project_hooks.rb b/lib/api/project_hooks.rb
index 649dd891f56..5b457bbe639 100644
--- a/lib/api/project_hooks.rb
+++ b/lib/api/project_hooks.rb
@@ -96,8 +96,7 @@ module API
delete ":id/hooks/:hook_id" do
hook = user_project.hooks.find(params.delete(:hook_id))
- status 204
- hook.destroy
+ destroy_conditionally!(hook)
end
end
end
diff --git a/lib/api/project_snippets.rb b/lib/api/project_snippets.rb
index f3d905b0068..704e8c6718d 100644
--- a/lib/api/project_snippets.rb
+++ b/lib/api/project_snippets.rb
@@ -116,8 +116,8 @@ module API
not_found!('Snippet') unless snippet
authorize! :admin_project_snippet, snippet
- status 204
- snippet.destroy
+
+ destroy_conditionally!(snippet)
end
desc 'Get a raw project snippet'
diff --git a/lib/api/projects.rb b/lib/api/projects.rb
index 15c3832b032..78d900984ac 100644
--- a/lib/api/projects.rb
+++ b/lib/api/projects.rb
@@ -1,7 +1,6 @@
require_dependency 'declarative_policy'
module API
- # Projects API
class Projects < Grape::API
include PaginationParams
@@ -334,7 +333,10 @@ module API
desc 'Remove a project'
delete ":id" do
authorize! :remove_project, user_project
- ::Projects::DestroyService.new(user_project, current_user, {}).async_execute
+
+ destroy_conditionally!(user_project) do
+ ::Projects::DestroyService.new(user_project, current_user, {}).async_execute
+ end
accepted!
end
@@ -363,8 +365,7 @@ module API
authorize! :remove_fork_project, user_project
if user_project.forked?
- status 204
- user_project.forked_project_link.destroy
+ destroy_conditionally!(user_project.forked_project_link)
else
not_modified!
end
@@ -408,8 +409,7 @@ module API
link = user_project.project_group_links.find_by(group_id: params[:group_id])
not_found!('Group Link') unless link
- status 204
- link.destroy
+ destroy_conditionally!(link)
end
desc 'Upload a file'
diff --git a/lib/api/protected_branches.rb b/lib/api/protected_branches.rb
index dccf4fa27a7..15fcb9e8e27 100644
--- a/lib/api/protected_branches.rb
+++ b/lib/api/protected_branches.rb
@@ -76,9 +76,7 @@ module API
delete ':id/protected_branches/:name', requirements: BRANCH_ENDPOINT_REQUIREMENTS do
protected_branch = user_project.protected_branches.find_by!(name: params[:name])
- protected_branch.destroy
-
- status 204
+ destroy_conditionally!(protected_branch)
end
end
end
diff --git a/lib/api/runner.rb b/lib/api/runner.rb
index 88fc62d33df..11999354594 100644
--- a/lib/api/runner.rb
+++ b/lib/api/runner.rb
@@ -45,8 +45,10 @@ module API
end
delete '/' do
authenticate_runner!
- status 204
- Ci::Runner.find_by_token(params[:token]).destroy
+
+ runner = Ci::Runner.find_by_token(params[:token])
+
+ destroy_conditionally!(runner)
end
desc 'Validates authentication credentials' do
@@ -78,7 +80,7 @@ module API
no_content! unless current_runner.active?
update_runner_info
- if current_runner.is_runner_queue_value_latest?(params[:last_update])
+ if current_runner.runner_queue_value_latest?(params[:last_update])
header 'X-GitLab-Last-Update', params[:last_update]
Gitlab::Metrics.add_event(:build_not_found_cached)
return no_content!
diff --git a/lib/api/runners.rb b/lib/api/runners.rb
index 31f940fe96b..68c2120cc15 100644
--- a/lib/api/runners.rb
+++ b/lib/api/runners.rb
@@ -77,10 +77,10 @@ module API
end
delete ':id' do
runner = get_runner(params[:id])
+
authenticate_delete_runner!(runner)
- status 204
- runner.destroy!
+ destroy_conditionally!(runner)
end
end
@@ -135,8 +135,7 @@ module API
runner = runner_project.runner
forbidden!("Only one project associated with the runner. Please remove the runner instead") if runner.projects.count == 1
- status 204
- runner_project.destroy
+ destroy_conditionally!(runner_project)
end
end
diff --git a/lib/api/services.rb b/lib/api/services.rb
index 843c05ae32e..ff9ddd44439 100644
--- a/lib/api/services.rb
+++ b/lib/api/services.rb
@@ -656,12 +656,14 @@ module API
delete ":id/services/:service_slug" do
service = user_project.find_or_initialize_service(params[:service_slug].underscore)
- attrs = service_attributes(service).inject({}) do |hash, key|
- hash.merge!(key => nil)
- end
+ destroy_conditionally!(service) do
+ attrs = service_attributes(service).inject({}) do |hash, key|
+ hash.merge!(key => nil)
+ end
- unless service.update_attributes(attrs.merge(active: false))
- render_api_error!('400 Bad Request', 400)
+ unless service.update_attributes(attrs.merge(active: false))
+ render_api_error!('400 Bad Request', 400)
+ end
end
end
diff --git a/lib/api/snippets.rb b/lib/api/snippets.rb
index 35ece56c65c..00eb7c60f16 100644
--- a/lib/api/snippets.rb
+++ b/lib/api/snippets.rb
@@ -123,8 +123,7 @@ module API
authorize! :destroy_personal_snippet, snippet
- status 204
- snippet.destroy
+ destroy_conditionally!(snippet)
end
desc 'Get a raw snippet' do
diff --git a/lib/api/system_hooks.rb b/lib/api/system_hooks.rb
index c0179037440..6b6a03e3300 100644
--- a/lib/api/system_hooks.rb
+++ b/lib/api/system_hooks.rb
@@ -66,8 +66,7 @@ module API
hook = SystemHook.find_by(id: params[:id])
not_found!('System hook') unless hook
- status 204
- hook.destroy
+ destroy_conditionally!(hook)
end
end
end
diff --git a/lib/api/tags.rb b/lib/api/tags.rb
index 1333747cced..81b17935b81 100644
--- a/lib/api/tags.rb
+++ b/lib/api/tags.rb
@@ -65,11 +65,18 @@ module API
delete ':id/repository/tags/:tag_name', requirements: TAG_ENDPOINT_REQUIREMENTS do
authorize_push_project
- result = ::Tags::DestroyService.new(user_project, current_user)
- .execute(params[:tag_name])
+ tag = user_project.repository.find_tag(params[:tag_name])
+ not_found!('Tag') unless tag
+
+ commit = user_project.repository.commit(tag.dereferenced_target)
+
+ destroy_conditionally!(commit, last_update_field: :authored_date) do
+ result = ::Tags::DestroyService.new(user_project, current_user)
+ .execute(params[:tag_name])
- if result[:status] != :success
- render_api_error!(result[:message], result[:return_code])
+ if result[:status] != :success
+ render_api_error!(result[:message], result[:return_code])
+ end
end
end
diff --git a/lib/api/triggers.rb b/lib/api/triggers.rb
index edfdb63d183..c9fee7e5193 100644
--- a/lib/api/triggers.rb
+++ b/lib/api/triggers.rb
@@ -140,8 +140,7 @@ module API
trigger = user_project.triggers.find(params.delete(:trigger_id))
return not_found!('Trigger') unless trigger
- status 204
- trigger.destroy
+ destroy_conditionally!(trigger)
end
end
end
diff --git a/lib/api/users.rb b/lib/api/users.rb
index e2019d6d512..96f47bb618a 100644
--- a/lib/api/users.rb
+++ b/lib/api/users.rb
@@ -230,8 +230,7 @@ module API
key = user.keys.find_by(id: params[:key_id])
not_found!('Key') unless key
- status 204
- key.destroy
+ destroy_conditionally!(key)
end
desc 'Add an email address to a specified user. Available only for admins.' do
@@ -287,7 +286,11 @@ module API
email = user.emails.find_by(id: params[:email_id])
not_found!('Email') unless email
- Emails::DestroyService.new(user, email: email.email).execute
+ destroy_conditionally!(email) do |email|
+ Emails::DestroyService.new(current_user, email: email.email).execute
+ end
+
+ user.update_secondary_emails!
end
desc 'Delete a user. Available only for admins.' do
@@ -299,11 +302,13 @@ module API
end
delete ":id" do
authenticated_as_admin!
+
user = User.find_by(id: params[:id])
not_found!('User') unless user
- status 204
- user.delete_async(deleted_by: current_user, params: params)
+ destroy_conditionally!(user) do
+ user.delete_async(deleted_by: current_user, params: params)
+ end
end
desc 'Block a user. Available only for admins.'
@@ -403,8 +408,11 @@ module API
requires :impersonation_token_id, type: Integer, desc: 'The ID of the impersonation token'
end
delete ':impersonation_token_id' do
- status 204
- find_impersonation_token.revoke!
+ token = find_impersonation_token
+
+ destroy_conditionally!(token) do
+ token.revoke!
+ end
end
end
end
@@ -481,8 +489,7 @@ module API
key = current_user.keys.find_by(id: params[:key_id])
not_found!('Key') unless key
- status 204
- key.destroy
+ destroy_conditionally!(key)
end
desc "Get the currently authenticated user's email addresses" do
@@ -533,8 +540,11 @@ module API
email = current_user.emails.find_by(id: params[:email_id])
not_found!('Email') unless email
- status 204
- Emails::DestroyService.new(current_user, email: email.email).execute
+ destroy_conditionally!(email) do |email|
+ Emails::DestroyService.new(current_user, email: email.email).execute
+ end
+
+ current_user.update_secondary_emails!
end
desc 'Get a list of user activities'
diff --git a/lib/api/variables.rb b/lib/api/variables.rb
index 7c0fdd3d1be..da71787abab 100644
--- a/lib/api/variables.rb
+++ b/lib/api/variables.rb
@@ -88,6 +88,7 @@ module API
variable = user_project.variables.find_by(key: params[:key])
not_found!('Variable') unless variable
+ # Variables don't have any timestamp. Therfore, destroy unconditionally.
status 204
variable.destroy
end
diff --git a/lib/backup/repository.rb b/lib/backup/repository.rb
index 88821ae56e0..4e92be85110 100644
--- a/lib/backup/repository.rb
+++ b/lib/backup/repository.rb
@@ -75,7 +75,7 @@ module Backup
path_to_project_repo = path_to_repo(project)
path_to_project_bundle = path_to_bundle(project)
- project.ensure_storage_path_exist
+ project.ensure_storage_path_exists
cmd = if File.exist?(path_to_project_bundle)
%W(#{Gitlab.config.git.bin_path} clone --bare #{path_to_project_bundle} #{path_to_project_repo})
diff --git a/lib/ci/api/api.rb b/lib/ci/api/api.rb
deleted file mode 100644
index 24bb3649a76..00000000000
--- a/lib/ci/api/api.rb
+++ /dev/null
@@ -1,39 +0,0 @@
-module Ci
- module API
- class API < Grape::API
- include ::API::APIGuard
- version 'v1', using: :path
-
- rescue_from ActiveRecord::RecordNotFound do
- rack_response({ 'message' => '404 Not found' }.to_json, 404)
- end
-
- # Retain 405 error rather than a 500 error for Grape 0.15.0+.
- # https://github.com/ruby-grape/grape/blob/a3a28f5b5dfbb2797442e006dbffd750b27f2a76/UPGRADING.md#changes-to-method-not-allowed-routes
- rescue_from Grape::Exceptions::MethodNotAllowed do |e|
- error! e.message, e.status, e.headers
- end
-
- rescue_from Grape::Exceptions::Base do |e|
- error! e.message, e.status, e.headers
- end
-
- rescue_from :all do |exception|
- handle_api_exception(exception)
- end
-
- content_type :txt, 'text/plain'
- content_type :json, 'application/json'
- format :json
-
- helpers ::SentryHelper
- helpers ::Ci::API::Helpers
- helpers ::API::Helpers
- helpers Gitlab::CurrentSettings
-
- mount ::Ci::API::Builds
- mount ::Ci::API::Runners
- mount ::Ci::API::Triggers
- end
- end
-end
diff --git a/lib/ci/api/builds.rb b/lib/ci/api/builds.rb
deleted file mode 100644
index 79058c02ce5..00000000000
--- a/lib/ci/api/builds.rb
+++ /dev/null
@@ -1,219 +0,0 @@
-module Ci
- module API
- # Builds API
- class Builds < Grape::API
- resource :builds do
- # Runs oldest pending build by runner - Runners only
- #
- # Parameters:
- # token (required) - The uniq token of runner
- #
- # Example Request:
- # POST /builds/register
- post "register" do
- authenticate_runner!
- required_attributes! [:token]
- not_found! unless current_runner.active?
- update_runner_info
-
- if current_runner.is_runner_queue_value_latest?(params[:last_update])
- header 'X-GitLab-Last-Update', params[:last_update]
- Gitlab::Metrics.add_event(:build_not_found_cached)
- return build_not_found!
- end
-
- new_update = current_runner.ensure_runner_queue_value
-
- result = Ci::RegisterJobService.new(current_runner).execute
-
- if result.valid?
- if result.build
- Gitlab::Metrics.add_event(:build_found,
- project: result.build.project.full_path)
-
- present result.build, with: Entities::BuildDetails
- else
- Gitlab::Metrics.add_event(:build_not_found)
-
- header 'X-GitLab-Last-Update', new_update
-
- build_not_found!
- end
- else
- # We received build that is invalid due to concurrency conflict
- Gitlab::Metrics.add_event(:build_invalid)
- conflict!
- end
- end
-
- # Update an existing build - Runners only
- #
- # Parameters:
- # id (required) - The ID of a project
- # state (optional) - The state of a build
- # trace (optional) - The trace of a build
- # Example Request:
- # PUT /builds/:id
- put ":id" do
- authenticate_runner!
- build = Ci::Build.where(runner_id: current_runner.id).running.find(params[:id])
- validate_build!(build)
-
- update_runner_info
-
- build.trace.set(params[:trace]) if params[:trace]
-
- Gitlab::Metrics.add_event(:update_build,
- project: build.project.full_path)
-
- case params[:state].to_s
- when 'success'
- build.success
- when 'failed'
- build.drop
- end
- end
-
- # Send incremental log update - Runners only
- #
- # Parameters:
- # id (required) - The ID of a build
- # Body:
- # content of logs to append
- # Headers:
- # Content-Range (required) - range of content that was sent
- # BUILD-TOKEN (required) - The build authorization token
- # Example Request:
- # PATCH /builds/:id/trace.txt
- patch ":id/trace.txt" do
- build = authenticate_build!
-
- error!('400 Missing header Content-Range', 400) unless request.headers.key?('Content-Range')
- content_range = request.headers['Content-Range']
- content_range = content_range.split('-')
-
- stream_size = build.trace.append(request.body.read, content_range[0].to_i)
- if stream_size < 0
- return error!('416 Range Not Satisfiable', 416, { 'Range' => "0-#{-stream_size}" })
- end
-
- status 202
- header 'Build-Status', build.status
- header 'Range', "0-#{stream_size}"
- end
-
- # Authorize artifacts uploading for build - Runners only
- #
- # Parameters:
- # id (required) - The ID of a build
- # token (required) - The build authorization token
- # filesize (optional) - the size of uploaded file
- # Example Request:
- # POST /builds/:id/artifacts/authorize
- post ":id/artifacts/authorize" do
- require_gitlab_workhorse!
- Gitlab::Workhorse.verify_api_request!(headers)
- not_allowed! unless Gitlab.config.artifacts.enabled
- build = authenticate_build!
- forbidden!('build is not running') unless build.running?
-
- if params[:filesize]
- file_size = params[:filesize].to_i
- file_to_large! unless file_size < max_artifacts_size
- end
-
- status 200
- content_type Gitlab::Workhorse::INTERNAL_API_CONTENT_TYPE
- Gitlab::Workhorse.artifact_upload_ok
- end
-
- # Upload artifacts to build - Runners only
- #
- # Parameters:
- # id (required) - The ID of a build
- # token (required) - The build authorization token
- # file (required) - Artifacts file
- # expire_in (optional) - Specify when artifacts should expire (ex. 7d)
- # Parameters (accelerated by GitLab Workhorse):
- # file.path - path to locally stored body (generated by Workhorse)
- # file.name - real filename as send in Content-Disposition
- # file.type - real content type as send in Content-Type
- # metadata.path - path to locally stored body (generated by Workhorse)
- # metadata.name - filename (generated by Workhorse)
- # Headers:
- # BUILD-TOKEN (required) - The build authorization token, the same as token
- # Body:
- # The file content
- #
- # Example Request:
- # POST /builds/:id/artifacts
- post ":id/artifacts" do
- require_gitlab_workhorse!
- not_allowed! unless Gitlab.config.artifacts.enabled
- build = authenticate_build!
- forbidden!('Build is not running!') unless build.running?
-
- artifacts_upload_path = ArtifactUploader.artifacts_upload_path
- artifacts = uploaded_file(:file, artifacts_upload_path)
- metadata = uploaded_file(:metadata, artifacts_upload_path)
-
- bad_request!('Missing artifacts file!') unless artifacts
- file_to_large! unless artifacts.size < max_artifacts_size
-
- build.artifacts_file = artifacts
- build.artifacts_metadata = metadata
- build.artifacts_expire_in =
- params['expire_in'] ||
- Gitlab::CurrentSettings.current_application_settings
- .default_artifacts_expire_in
-
- if build.save
- present(build, with: Entities::BuildDetails)
- else
- render_validation_error!(build)
- end
- end
-
- # Download the artifacts file from build - Runners only
- #
- # Parameters:
- # id (required) - The ID of a build
- # token (required) - The build authorization token
- # Headers:
- # BUILD-TOKEN (required) - The build authorization token, the same as token
- # Example Request:
- # GET /builds/:id/artifacts
- get ":id/artifacts" do
- build = authenticate_build!
- artifacts_file = build.artifacts_file
-
- unless artifacts_file.exists?
- not_found!
- end
-
- unless artifacts_file.file_storage?
- return redirect_to build.artifacts_file.url
- end
-
- present_file!(artifacts_file.path, artifacts_file.filename)
- end
-
- # Remove the artifacts file from build - Runners only
- #
- # Parameters:
- # id (required) - The ID of a build
- # token (required) - The build authorization token
- # Headers:
- # BUILD-TOKEN (required) - The build authorization token, the same as token
- # Example Request:
- # DELETE /builds/:id/artifacts
- delete ":id/artifacts" do
- build = authenticate_build!
-
- status(200)
- build.erase_artifacts!
- end
- end
- end
- end
-end
diff --git a/lib/ci/api/entities.rb b/lib/ci/api/entities.rb
deleted file mode 100644
index 31f66dd5a58..00000000000
--- a/lib/ci/api/entities.rb
+++ /dev/null
@@ -1,93 +0,0 @@
-module Ci
- module API
- module Entities
- class Commit < Grape::Entity
- expose :id, :sha, :project_id, :created_at
- expose :status, :finished_at, :duration
- expose :git_commit_message, :git_author_name, :git_author_email
- end
-
- class CommitWithBuilds < Commit
- expose :builds
- end
-
- class ArtifactFile < Grape::Entity
- expose :filename, :size
- end
-
- class BuildOptions < Grape::Entity
- expose :image
- expose :services
- expose :artifacts
- expose :cache
- expose :dependencies
- expose :after_script
- end
-
- class Build < Grape::Entity
- expose :id, :ref, :tag, :sha, :status
- expose :name, :token, :stage
- expose :project_id
- expose :project_name
- expose :artifacts_file, using: ArtifactFile, if: ->(build, _) { build.artifacts? }
- end
-
- class BuildCredentials < Grape::Entity
- expose :type, :url, :username, :password
- end
-
- class BuildDetails < Build
- expose :commands
- expose :repo_url
- expose :before_sha
- expose :allow_git_fetch
- expose :token
- expose :artifacts_expire_at, if: ->(build, _) { build.artifacts? }
-
- expose :options do |model|
- # This part ensures that output of old API is still the same after adding support
- # for extended docker configuration options, used by new API
- #
- # I'm leaving this here, not in the model, because it should be removed at the same time
- # when old API will be removed (planned for August 2017).
- model.options.dup.tap do |options|
- options[:image] = options[:image][:name] if options[:image].is_a?(Hash)
- options[:services]&.map! do |service|
- if service.is_a?(Hash)
- service[:name]
- else
- service
- end
- end
- end
- end
-
- expose :timeout do |model|
- model.timeout
- end
-
- expose :variables
- expose :depends_on_builds, using: Build
-
- expose :credentials, using: BuildCredentials
- end
-
- class Runner < Grape::Entity
- expose :id, :token
- end
-
- class RunnerProject < Grape::Entity
- expose :id, :project_id, :runner_id
- end
-
- class WebHook < Grape::Entity
- expose :id, :project_id, :url
- end
-
- class TriggerRequest < Grape::Entity
- expose :id, :variables
- expose :pipeline, using: Commit, as: :commit
- end
- end
- end
-end
diff --git a/lib/ci/api/helpers.rb b/lib/ci/api/helpers.rb
deleted file mode 100644
index a40b6ab6c9f..00000000000
--- a/lib/ci/api/helpers.rb
+++ /dev/null
@@ -1,89 +0,0 @@
-module Ci
- module API
- module Helpers
- BUILD_TOKEN_HEADER = "HTTP_BUILD_TOKEN".freeze
- BUILD_TOKEN_PARAM = :token
- UPDATE_RUNNER_EVERY = 10 * 60
-
- def authenticate_runners!
- forbidden! unless runner_registration_token_valid?
- end
-
- def authenticate_runner!
- forbidden! unless current_runner
- end
-
- def authenticate_build!
- build = Ci::Build.find_by_id(params[:id])
-
- validate_build!(build) do
- forbidden! unless build_token_valid?(build)
- end
-
- build
- end
-
- def validate_build!(build)
- not_found! unless build
-
- yield if block_given?
-
- project = build.project
- forbidden!('Project has been deleted!') if project.nil? || project.pending_delete?
- forbidden!('Build has been erased!') if build.erased?
- end
-
- def runner_registration_token_valid?
- ActiveSupport::SecurityUtils.variable_size_secure_compare(
- params[:token],
- current_application_settings.runners_registration_token)
- end
-
- def build_token_valid?(build)
- token = (params[BUILD_TOKEN_PARAM] || env[BUILD_TOKEN_HEADER]).to_s
-
- # We require to also check `runners_token` to maintain compatibility with old version of runners
- token && (build.valid_token?(token) || build.project.valid_runners_token?(token))
- end
-
- def update_runner_info
- return unless update_runner?
-
- current_runner.contacted_at = Time.now
- current_runner.assign_attributes(get_runner_version_from_params)
- current_runner.save if current_runner.changed?
- end
-
- def update_runner?
- # Use a random threshold to prevent beating DB updates.
- # It generates a distribution between [40m, 80m].
- #
- contacted_at_max_age = UPDATE_RUNNER_EVERY + Random.rand(UPDATE_RUNNER_EVERY)
-
- current_runner.contacted_at.nil? ||
- (Time.now - current_runner.contacted_at) >= contacted_at_max_age
- end
-
- def build_not_found!
- if headers['User-Agent'].to_s =~ /gitlab-ci-multi-runner \d+\.\d+\.\d+(~beta\.\d+\.g[0-9a-f]+)? /
- no_content!
- else
- not_found!
- end
- end
-
- def current_runner
- @runner ||= Runner.find_by_token(params[:token].to_s)
- end
-
- def get_runner_version_from_params
- return unless params["info"].present?
- attributes_for_keys(%w(name version revision platform architecture), params["info"])
- end
-
- def max_artifacts_size
- current_application_settings.max_artifacts_size.megabytes.to_i
- end
- end
- end
-end
diff --git a/lib/ci/api/runners.rb b/lib/ci/api/runners.rb
deleted file mode 100644
index 45aa2adccf5..00000000000
--- a/lib/ci/api/runners.rb
+++ /dev/null
@@ -1,50 +0,0 @@
-module Ci
- module API
- class Runners < Grape::API
- resource :runners do
- desc 'Delete a runner'
- params do
- requires :token, type: String, desc: 'The unique token of the runner'
- end
- delete "delete" do
- authenticate_runner!
-
- status(200)
- Ci::Runner.find_by_token(params[:token]).destroy
- end
-
- desc 'Register a new runner' do
- success Entities::Runner
- end
- params do
- requires :token, type: String, desc: 'The unique token of the runner'
- optional :description, type: String, desc: 'The description of the runner'
- optional :tag_list, type: Array[String], desc: 'A list of tags the runner should run for'
- optional :run_untagged, type: Boolean, desc: 'Flag if the runner should execute untagged jobs'
- optional :locked, type: Boolean, desc: 'Lock this runner for this specific project'
- end
- post "register" do
- runner_params = declared(params, include_missing: false).except(:token)
-
- runner =
- if runner_registration_token_valid?
- # Create shared runner. Requires admin access
- Ci::Runner.create(runner_params.merge(is_shared: true))
- elsif project = Project.find_by(runners_token: params[:token])
- # Create a specific runner for project.
- project.runners.create(runner_params)
- end
-
- return forbidden! unless runner
-
- if runner.id
- runner.update(get_runner_version_from_params)
- present runner, with: Entities::Runner
- else
- not_found!
- end
- end
- end
- end
- end
-end
diff --git a/lib/ci/api/triggers.rb b/lib/ci/api/triggers.rb
deleted file mode 100644
index 6225203f223..00000000000
--- a/lib/ci/api/triggers.rb
+++ /dev/null
@@ -1,39 +0,0 @@
-module Ci
- module API
- class Triggers < Grape::API
- resource :projects do
- desc 'Trigger a GitLab CI project build' do
- success Entities::TriggerRequest
- end
- params do
- requires :id, type: Integer, desc: 'The ID of a CI project'
- requires :ref, type: String, desc: "The name of project's branch or tag"
- requires :token, type: String, desc: 'The unique token of the trigger'
- optional :variables, type: Hash, desc: 'Optional build variables'
- end
- post ":id/refs/:ref/trigger" do
- project = Project.find_by(ci_id: params[:id])
- trigger = Ci::Trigger.find_by_token(params[:token])
- not_found! unless project && trigger
- unauthorized! unless trigger.project == project
-
- # Validate variables
- variables = params[:variables].to_h
- unless variables.all? { |key, value| key.is_a?(String) && value.is_a?(String) }
- render_api_error!('variables needs to be a map of key-valued strings', 400)
- end
-
- # create request and trigger builds
- result = Ci::CreateTriggerRequestService.execute(project, trigger, params[:ref], variables)
- pipeline = result.pipeline
-
- if pipeline.persisted?
- present result.trigger_request, with: Entities::TriggerRequest
- else
- render_validation_error!(pipeline)
- end
- end
- end
- end
- end
-end
diff --git a/lib/github/import.rb b/lib/github/import.rb
index 4cc01593ef4..7b848081e85 100644
--- a/lib/github/import.rb
+++ b/lib/github/import.rb
@@ -107,7 +107,7 @@ module Github
# this means that repo has wiki enabled, but have no pages. So,
# we can skip the import.
if e.message !~ /repository not exported/
- errors(:wiki, wiki_url, e.message)
+ error(:wiki, wiki_url, e.message)
end
end
diff --git a/lib/gitlab/background_migration/deserialize_merge_request_diffs_and_commits.rb b/lib/gitlab/background_migration/deserialize_merge_request_diffs_and_commits.rb
index 310a69a4bd4..3fde1b09efb 100644
--- a/lib/gitlab/background_migration/deserialize_merge_request_diffs_and_commits.rb
+++ b/lib/gitlab/background_migration/deserialize_merge_request_diffs_and_commits.rb
@@ -81,12 +81,15 @@ module Gitlab
relative_order: index
)
- # Compatibility with old diffs created with Psych.
diff_hash.tap do |hash|
diff_text = hash[:diff]
hash[:too_large] = !!hash[:too_large]
+ hash[:a_mode] ||= guess_mode(hash[:new_file], hash[:diff])
+ hash[:b_mode] ||= guess_mode(hash[:deleted_file], hash[:diff])
+
+ # Compatibility with old diffs created with Psych.
if diff_text.encoding == Encoding::BINARY && !diff_text.ascii_only?
hash[:binary] = true
hash[:diff] = [diff_text].pack('m0')
@@ -97,6 +100,15 @@ module Gitlab
[commit_rows, file_rows]
end
+ # This doesn't have to be 100% accurate, because it's only used for
+ # display - it won't change file modes in the repository. Submodules are
+ # created as 600, regular files as 644.
+ def guess_mode(file_missing, diff)
+ return '0' if file_missing
+
+ diff.include?('Subproject commit') ? '160000' : '100644'
+ end
+
# Unlike MergeRequestDiff#valid_raw_diff?, don't count Rugged objects as
# valid, because we don't render them usefully anyway.
def valid_raw_diffs?(diffs)
diff --git a/lib/gitlab/background_migration/migrate_stage_status.rb b/lib/gitlab/background_migration/migrate_stage_status.rb
new file mode 100644
index 00000000000..b1ff0900709
--- /dev/null
+++ b/lib/gitlab/background_migration/migrate_stage_status.rb
@@ -0,0 +1,77 @@
+module Gitlab
+ module BackgroundMigration
+ class MigrateStageStatus
+ STATUSES = { created: 0, pending: 1, running: 2, success: 3,
+ failed: 4, canceled: 5, skipped: 6, manual: 7 }.freeze
+
+ class Build < ActiveRecord::Base
+ self.table_name = 'ci_builds'
+
+ scope :latest, -> { where(retried: [false, nil]) }
+ scope :created, -> { where(status: 'created') }
+ scope :running, -> { where(status: 'running') }
+ scope :pending, -> { where(status: 'pending') }
+ scope :success, -> { where(status: 'success') }
+ scope :failed, -> { where(status: 'failed') }
+ scope :canceled, -> { where(status: 'canceled') }
+ scope :skipped, -> { where(status: 'skipped') }
+ scope :manual, -> { where(status: 'manual') }
+
+ scope :failed_but_allowed, -> do
+ where(allow_failure: true, status: [:failed, :canceled])
+ end
+
+ scope :exclude_ignored, -> do
+ where("allow_failure = ? OR status IN (?)",
+ false, %w[created pending running success skipped])
+ end
+
+ def self.status_sql
+ scope_relevant = latest.exclude_ignored
+ scope_warnings = latest.failed_but_allowed
+
+ builds = scope_relevant.select('count(*)').to_sql
+ created = scope_relevant.created.select('count(*)').to_sql
+ success = scope_relevant.success.select('count(*)').to_sql
+ manual = scope_relevant.manual.select('count(*)').to_sql
+ pending = scope_relevant.pending.select('count(*)').to_sql
+ running = scope_relevant.running.select('count(*)').to_sql
+ skipped = scope_relevant.skipped.select('count(*)').to_sql
+ canceled = scope_relevant.canceled.select('count(*)').to_sql
+ warnings = scope_warnings.select('count(*) > 0').to_sql
+
+ <<-SQL.strip_heredoc
+ (CASE
+ WHEN (#{builds}) = (#{skipped}) AND (#{warnings}) THEN #{STATUSES[:success]}
+ WHEN (#{builds}) = (#{skipped}) THEN #{STATUSES[:skipped]}
+ WHEN (#{builds}) = (#{success}) THEN #{STATUSES[:success]}
+ WHEN (#{builds}) = (#{created}) THEN #{STATUSES[:created]}
+ WHEN (#{builds}) = (#{success}) + (#{skipped}) THEN #{STATUSES[:success]}
+ WHEN (#{builds}) = (#{success}) + (#{skipped}) + (#{canceled}) THEN #{STATUSES[:canceled]}
+ WHEN (#{builds}) = (#{created}) + (#{skipped}) + (#{pending}) THEN #{STATUSES[:pending]}
+ WHEN (#{running}) + (#{pending}) > 0 THEN #{STATUSES[:running]}
+ WHEN (#{manual}) > 0 THEN #{STATUSES[:manual]}
+ WHEN (#{created}) > 0 THEN #{STATUSES[:running]}
+ ELSE #{STATUSES[:failed]}
+ END)
+ SQL
+ end
+ end
+
+ def perform(start_id, stop_id)
+ status_sql = Build
+ .where('ci_builds.commit_id = ci_stages.pipeline_id')
+ .where('ci_builds.stage = ci_stages.name')
+ .status_sql
+
+ sql = <<-SQL
+ UPDATE ci_stages SET status = (#{status_sql})
+ WHERE ci_stages.status IS NULL
+ AND ci_stages.id BETWEEN #{start_id.to_i} AND #{stop_id.to_i}
+ SQL
+
+ ActiveRecord::Base.connection.execute(sql)
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/bare_repository_importer.rb b/lib/gitlab/bare_repository_importer.rb
new file mode 100644
index 00000000000..9323bfc7fb2
--- /dev/null
+++ b/lib/gitlab/bare_repository_importer.rb
@@ -0,0 +1,96 @@
+module Gitlab
+ class BareRepositoryImporter
+ NoAdminError = Class.new(StandardError)
+
+ def self.execute
+ Gitlab.config.repositories.storages.each do |storage_name, repository_storage|
+ git_base_path = repository_storage['path']
+ repos_to_import = Dir.glob(git_base_path + '/**/*.git')
+
+ repos_to_import.each do |repo_path|
+ if repo_path.end_with?('.wiki.git')
+ log " * Skipping wiki repo"
+ next
+ end
+
+ log "Processing #{repo_path}".color(:yellow)
+
+ repo_relative_path = repo_path[repository_storage['path'].length..-1]
+ .sub(/^\//, '') # Remove leading `/`
+ .sub(/\.git$/, '') # Remove `.git` at the end
+ new(storage_name, repo_relative_path).create_project_if_needed
+ end
+ end
+ end
+
+ attr_reader :storage_name, :full_path, :group_path, :project_path, :user
+ delegate :log, to: :class
+
+ def initialize(storage_name, repo_path)
+ @storage_name = storage_name
+ @full_path = repo_path
+
+ unless @user = User.admins.order_id_asc.first
+ raise NoAdminError.new('No admin user found to import repositories')
+ end
+
+ @group_path, @project_path = File.split(repo_path)
+ @group_path = nil if @group_path == '.'
+ end
+
+ def create_project_if_needed
+ if project = Project.find_by_full_path(full_path)
+ log " * #{project.name} (#{full_path}) exists"
+ return project
+ end
+
+ create_project
+ end
+
+ private
+
+ def create_project
+ group = find_or_create_group
+
+ project_params = {
+ name: project_path,
+ path: project_path,
+ repository_storage: storage_name,
+ namespace_id: group&.id
+ }
+
+ project = Projects::CreateService.new(user, project_params).execute
+
+ if project.persisted?
+ log " * Created #{project.name} (#{full_path})".color(:green)
+ ProjectCacheWorker.perform_async(project.id)
+ else
+ log " * Failed trying to create #{project.name} (#{full_path})".color(:red)
+ log " Errors: #{project.errors.messages}".color(:red)
+ end
+
+ project
+ end
+
+ def find_or_create_group
+ return nil unless group_path
+
+ if namespace = Namespace.find_by_full_path(group_path)
+ log " * Namespace #{group_path} exists.".color(:green)
+ return namespace
+ end
+
+ log " * Creating Group: #{group_path}"
+ Groups::NestedCreateService.new(user, group_path: group_path).execute
+ end
+
+ # This is called from within a rake task only used by Admins, so allow writing
+ # to STDOUT
+ #
+ # rubocop:disable Rails/Output
+ def self.log(message)
+ puts message
+ end
+ # rubocop:enable Rails/Output
+ end
+end
diff --git a/lib/gitlab/checks/force_push.rb b/lib/gitlab/checks/force_push.rb
index 714464fd5e7..dc5d285ea65 100644
--- a/lib/gitlab/checks/force_push.rb
+++ b/lib/gitlab/checks/force_push.rb
@@ -12,7 +12,7 @@ module Gitlab
!project
.repository
.gitaly_commit_client
- .is_ancestor(oldrev, newrev)
+ .ancestor?(oldrev, newrev)
else
Gitlab::Git::RevList.new(
path_to_repo: project.repository.path_to_repo,
diff --git a/lib/gitlab/data_builder/push.rb b/lib/gitlab/data_builder/push.rb
index 5c5f507d44d..4ab5b3455a5 100644
--- a/lib/gitlab/data_builder/push.rb
+++ b/lib/gitlab/data_builder/push.rb
@@ -3,6 +3,35 @@ module Gitlab
module Push
extend self
+ SAMPLE_DATA =
+ {
+ object_kind: "push",
+ event_name: "push",
+ before: "95790bf891e76fee5e1747ab589903a6a1f80f22",
+ after: "da1560886d4f094c3e6c9ef40349f7d38b5d27d7",
+ ref: "refs/heads/master",
+ checkout_sha: "da1560886d4f094c3e6c9ef40349f7d38b5d27d7",
+ message: "Hello World",
+ user_id: 4,
+ user_name: "John Smith",
+ user_email: "john@example.com",
+ user_avatar: "https://s.gravatar.com/avatar/d4c74594d841139328695756648b6bd6?s=8://s.gravatar.com/avatar/d4c74594d841139328695756648b6bd6?s=80",
+ project_id: 15,
+ commits: [
+ {
+ id: "c5feabde2d8cd023215af4d2ceeb7a64839fc428",
+ message: "Add simple search to projects in public area",
+ timestamp: "2013-05-13T18:18:08+00:00",
+ url: "https://test.example.com/gitlab/gitlabhq/commit/c5feabde2d8cd023215af4d2ceeb7a64839fc428",
+ author: {
+ name: "Test User",
+ email: "test@example.com"
+ }
+ }
+ ],
+ total_commits_count: 1
+ }.freeze
+
# Produce a hash of post-receive data
#
# data = {
@@ -74,6 +103,10 @@ module Gitlab
build(project, user, commits.last&.id, commits.first&.id, ref, commits)
end
+ def sample_data
+ SAMPLE_DATA
+ end
+
private
def checkout_sha(repository, newrev, ref)
diff --git a/lib/gitlab/data_builder/repository.rb b/lib/gitlab/data_builder/repository.rb
index b42dc052949..c9c13ec6487 100644
--- a/lib/gitlab/data_builder/repository.rb
+++ b/lib/gitlab/data_builder/repository.rb
@@ -3,6 +3,23 @@ module Gitlab
module Repository
extend self
+ SAMPLE_DATA = {
+ event_name: 'repository_update',
+ user_id: 10,
+ user_name: 'john.doe',
+ user_email: 'test@example.com',
+ user_avatar: 'http://example.com/avatar/user.png',
+ project_id: 40,
+ changes: [
+ {
+ before: "8205ea8d81ce0c6b90fbe8280d118cc9fdad6130",
+ after: "4045ea7a3df38697b3730a20fb73c8bed8a3e69e",
+ ref: "refs/heads/master"
+ }
+ ],
+ "refs": ["refs/heads/master"]
+ }.freeze
+
# Produce a hash of post-receive data
def update(project, user, changes, refs)
{
@@ -30,6 +47,10 @@ module Gitlab
ref: ref
}
end
+
+ def sample_data
+ SAMPLE_DATA
+ end
end
end
end
diff --git a/lib/gitlab/database/migration_helpers.rb b/lib/gitlab/database/migration_helpers.rb
index 69ca9aa596b..5e2c6cc5cad 100644
--- a/lib/gitlab/database/migration_helpers.rb
+++ b/lib/gitlab/database/migration_helpers.rb
@@ -606,6 +606,25 @@ module Gitlab
Arel::Nodes::SqlLiteral.new(replace.to_sql)
end
end
+
+ def remove_foreign_key_without_error(*args)
+ remove_foreign_key(*args)
+ rescue ArgumentError
+ end
+
+ def sidekiq_queue_migrate(queue_from, to:)
+ while sidekiq_queue_length(queue_from) > 0
+ Sidekiq.redis do |conn|
+ conn.rpoplpush "queue:#{queue_from}", "queue:#{to}"
+ end
+ end
+ end
+
+ def sidekiq_queue_length(queue_name)
+ Sidekiq.redis do |conn|
+ conn.llen("queue:#{queue_name}")
+ end
+ end
end
end
end
diff --git a/lib/gitlab/diff/file.rb b/lib/gitlab/diff/file.rb
index 6d7de52cb80..1dabd4ebdd0 100644
--- a/lib/gitlab/diff/file.rb
+++ b/lib/gitlab/diff/file.rb
@@ -186,7 +186,10 @@ module Gitlab
end
def content_changed?
- old_blob && new_blob && old_blob.id != new_blob.id
+ return blobs_changed? if diff_refs
+ return false if new_file? || deleted_file? || renamed_file?
+
+ text? && diff_lines.any?
end
def different_type?
@@ -225,6 +228,10 @@ module Gitlab
private
+ def blobs_changed?
+ old_blob && new_blob && old_blob.id != new_blob.id
+ end
+
def simple_viewer_class
return DiffViewer::NotDiffable unless diffable?
@@ -250,6 +257,8 @@ module Gitlab
DiffViewer::Renamed
elsif mode_changed?
DiffViewer::ModeChanged
+ else
+ DiffViewer::NoPreview
end
end
diff --git a/lib/gitlab/file_finder.rb b/lib/gitlab/file_finder.rb
index 093d9ed8092..10ffc345bd5 100644
--- a/lib/gitlab/file_finder.rb
+++ b/lib/gitlab/file_finder.rb
@@ -6,27 +6,48 @@ module Gitlab
attr_reader :project, :ref
+ delegate :repository, to: :project
+
def initialize(project, ref)
@project = project
@ref = ref
end
def find(query)
- blobs = project.repository.search_files_by_content(query, ref).first(BATCH_SIZE)
- found_file_names = Set.new
+ by_content = find_by_content(query)
- results = blobs.map do |blob|
- blob = Gitlab::ProjectSearchResults.parse_search_result(blob)
- found_file_names << blob.filename
+ already_found = Set.new(by_content.map(&:filename))
+ by_filename = find_by_filename(query, except: already_found)
- [blob.filename, blob]
- end
+ (by_content + by_filename)
+ .sort_by(&:filename)
+ .map { |blob| [blob.filename, blob] }
+ end
- project.repository.search_files_by_name(query, ref).first(BATCH_SIZE).each do |filename|
- results << [filename, OpenStruct.new(ref: ref)] unless found_file_names.include?(filename)
- end
+ private
- results.sort_by(&:first)
+ def find_by_content(query)
+ results = repository.search_files_by_content(query, ref).first(BATCH_SIZE)
+ results.map { |result| Gitlab::ProjectSearchResults.parse_search_result(result) }
+ end
+
+ def find_by_filename(query, except: [])
+ filenames = repository.search_files_by_name(query, ref).first(BATCH_SIZE)
+ filenames.delete_if { |filename| except.include?(filename) } unless except.empty?
+
+ blob_refs = filenames.map { |filename| [ref, filename] }
+ blobs = Gitlab::Git::Blob.batch(repository, blob_refs, blob_size_limit: 1024)
+
+ blobs.map do |blob|
+ Gitlab::SearchResults::FoundBlob.new(
+ id: blob.id,
+ filename: blob.path,
+ basename: File.basename(blob.path),
+ ref: ref,
+ startline: 1,
+ data: blob.data
+ )
+ end
end
end
end
diff --git a/lib/gitlab/git/commit.rb b/lib/gitlab/git/commit.rb
index a499bbc6266..5ee6669050c 100644
--- a/lib/gitlab/git/commit.rb
+++ b/lib/gitlab/git/commit.rb
@@ -271,7 +271,13 @@ module Gitlab
#
# Gitaly migration: https://gitlab.com/gitlab-org/gitaly/issues/324
def to_diff
- rugged_diff_from_parent.patch
+ Gitlab::GitalyClient.migrate(:commit_patch) do |is_enabled|
+ if is_enabled
+ @repository.gitaly_commit_client.patch(id)
+ else
+ rugged_diff_from_parent.patch
+ end
+ end
end
# Returns a diff object for the changes from this commit's first parent.
diff --git a/lib/gitlab/git/committer.rb b/lib/gitlab/git/committer.rb
new file mode 100644
index 00000000000..1f4bcf7a3a0
--- /dev/null
+++ b/lib/gitlab/git/committer.rb
@@ -0,0 +1,21 @@
+module Gitlab
+ module Git
+ class Committer
+ attr_reader :name, :email, :gl_id
+
+ def self.from_user(user)
+ new(user.name, user.email, Gitlab::GlId.gl_id(user))
+ end
+
+ def initialize(name, email, gl_id)
+ @name = name
+ @email = email
+ @gl_id = gl_id
+ end
+
+ def ==(other)
+ [name, email, gl_id] == [other.name, other.email, other.gl_id]
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/git/hook.rb b/lib/gitlab/git/hook.rb
index 8f0c377ef4f..cc35d77c6e4 100644
--- a/lib/gitlab/git/hook.rb
+++ b/lib/gitlab/git/hook.rb
@@ -1,20 +1,23 @@
-# Gitaly note: JV: looks like this is only used by GitHooksService in
+# Gitaly note: JV: looks like this is only used by Gitlab::Git::HooksService in
# app/services. We shouldn't bother migrating this until we know how
-# GitHooksService will be migrated.
+# Gitlab::Git::HooksService will be migrated.
module Gitlab
module Git
class Hook
GL_PROTOCOL = 'web'.freeze
- attr_reader :name, :repo_path, :path
+ attr_reader :name, :path, :repository
- def initialize(name, project)
+ def initialize(name, repository)
@name = name
- @project = project
- @repo_path = project.repository.path
+ @repository = repository
@path = File.join(repo_path.strip, 'hooks', name)
end
+ def repo_path
+ repository.path
+ end
+
def exists?
File.exist?(path)
end
@@ -44,7 +47,7 @@ module Gitlab
'GL_ID' => gl_id,
'PWD' => repo_path,
'GL_PROTOCOL' => GL_PROTOCOL,
- 'GL_REPOSITORY' => Gitlab::GlRepository.gl_repository(@project, false)
+ 'GL_REPOSITORY' => repository.gl_repository
}
options = {
diff --git a/lib/gitlab/git/hooks_service.rb b/lib/gitlab/git/hooks_service.rb
new file mode 100644
index 00000000000..ea8a87a1290
--- /dev/null
+++ b/lib/gitlab/git/hooks_service.rb
@@ -0,0 +1,36 @@
+module Gitlab
+ module Git
+ class HooksService
+ PreReceiveError = Class.new(StandardError)
+
+ attr_accessor :oldrev, :newrev, :ref
+
+ def execute(committer, repository, oldrev, newrev, ref)
+ @repository = repository
+ @gl_id = committer.gl_id
+ @oldrev = oldrev
+ @newrev = newrev
+ @ref = ref
+
+ %w(pre-receive update).each do |hook_name|
+ status, message = run_hook(hook_name)
+
+ unless status
+ raise PreReceiveError, message
+ end
+ end
+
+ yield(self).tap do
+ run_hook('post-receive')
+ end
+ end
+
+ private
+
+ def run_hook(name)
+ hook = Gitlab::Git::Hook.new(name, @repository)
+ hook.trigger(@gl_id, oldrev, newrev, ref)
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/git/repository.rb b/lib/gitlab/git/repository.rb
index aef7ae659fe..03e2bec84dd 100644
--- a/lib/gitlab/git/repository.rb
+++ b/lib/gitlab/git/repository.rb
@@ -49,13 +49,14 @@ module Gitlab
# Rugged repo object
attr_reader :rugged
- attr_reader :storage
+ attr_reader :storage, :gl_repository, :relative_path
# 'path' must be the path to a _bare_ git repository, e.g.
# /path/to/my-repo.git
- def initialize(storage, relative_path)
+ def initialize(storage, relative_path, gl_repository)
@storage = storage
@relative_path = relative_path
+ @gl_repository = gl_repository
storage_path = Gitlab.config.repositories.storages[@storage]['path']
@path = File.join(storage_path, @relative_path)
@@ -64,7 +65,6 @@ module Gitlab
end
delegate :empty?,
- :bare?,
to: :rugged
delegate :exists?, to: :gitaly_repository_client
@@ -126,6 +126,8 @@ module Gitlab
# This is to work around a bug in libgit2 that causes in-memory refs to
# be stale/invalid when packed-refs is changed.
# See https://gitlab.com/gitlab-org/gitlab-ce/issues/15392#note_14538333
+ #
+ # Gitaly migration: https://gitlab.com/gitlab-org/gitaly/issues/474
def find_branch(name, force_reload = false)
reload_rugged if force_reload
@@ -152,7 +154,7 @@ module Gitlab
if is_enabled
gitaly_ref_client.count_branch_names
else
- rugged.branches.count do |ref|
+ rugged.branches.each(:local).count do |ref|
begin
ref.name && ref.target # ensures the branch is valid
@@ -200,25 +202,43 @@ module Gitlab
end
end
+ # Returns true if the given ref name exists
+ #
+ # Ref names must start with `refs/`.
+ def ref_exists?(ref_name)
+ gitaly_migrate(:ref_exists) do |is_enabled|
+ if is_enabled
+ gitaly_ref_exists?(ref_name)
+ else
+ rugged_ref_exists?(ref_name)
+ end
+ end
+ end
+
# Returns true if the given tag exists
#
# name - The name of the tag as a String.
def tag_exists?(name)
- !!rugged.tags[name]
+ gitaly_migrate(:ref_exists_tags) do |is_enabled|
+ if is_enabled
+ gitaly_ref_exists?("refs/tags/#{name}")
+ else
+ rugged_tag_exists?(name)
+ end
+ end
end
# Returns true if the given branch exists
#
# name - The name of the branch as a String.
def branch_exists?(name)
- rugged.branches.exists?(name)
-
- # If the branch name is invalid (e.g. ".foo") Rugged will raise an error.
- # Whatever code calls this method shouldn't have to deal with that so
- # instead we just return `false` (which is true since a branch doesn't
- # exist when it has an invalid name).
- rescue Rugged::ReferenceError
- false
+ gitaly_migrate(:ref_exists_branches) do |is_enabled|
+ if is_enabled
+ gitaly_ref_exists?("refs/heads/#{name}")
+ else
+ rugged_branch_exists?(name)
+ end
+ end
end
# Returns an Array of branch and tag names
@@ -226,10 +246,6 @@ module Gitlab
branch_names + tag_names
end
- def has_commits?
- !empty?
- end
-
# Discovers the default branch based on the repository's available branches
#
# - If no branches are present, returns nil
@@ -423,8 +439,8 @@ module Gitlab
end
# Returns true is +from+ is direct ancestor to +to+, otherwise false
- def is_ancestor?(from, to)
- gitaly_commit_client.is_ancestor(from, to)
+ def ancestor?(from, to)
+ gitaly_commit_client.ancestor?(from, to)
end
# Return an array of Diff objects that represent the diff
@@ -569,6 +585,8 @@ module Gitlab
end
# Delete the specified branch from the repository
+ #
+ # Gitaly migration: https://gitlab.com/gitlab-org/gitaly/issues/476
def delete_branch(branch_name)
rugged.branches.delete(branch_name)
end
@@ -578,6 +596,8 @@ module Gitlab
# Examples:
# create_branch("feature")
# create_branch("other-feature", "master")
+ #
+ # Gitaly migration: https://gitlab.com/gitlab-org/gitaly/issues/476
def create_branch(ref, start_point = "HEAD")
rugged_ref = rugged.branches.create(ref, start_point)
target_commit = Gitlab::Git::Commit.find(self, rugged_ref.target)
@@ -587,38 +607,26 @@ module Gitlab
raise InvalidRef.new("Invalid reference #{start_point}")
end
- # Return an array of this repository's remote names
- def remote_names
- rugged.remotes.each_name.to_a
- end
-
# Delete the specified remote from this repository.
def remote_delete(remote_name)
rugged.remotes.delete(remote_name)
+ nil
end
- # Add a new remote to this repository. Returns a Rugged::Remote object
+ # Add a new remote to this repository.
def remote_add(remote_name, url)
rugged.remotes.create(remote_name, url)
+ nil
end
# Update the specified remote using the values in the +options+ hash
#
# Example
# repo.update_remote("origin", url: "path/to/repo")
- def remote_update(remote_name, options = {})
+ def remote_update(remote_name, url:)
# TODO: Implement other remote options
- rugged.remotes.set_url(remote_name, options[:url]) if options[:url]
- end
-
- # Fetch the specified remote
- def fetch(remote_name)
- rugged.remotes[remote_name].fetch
- end
-
- # Push +*refspecs+ to the remote identified by +remote_name+.
- def push(remote_name, *refspecs)
- rugged.remotes[remote_name].push(refspecs)
+ rugged.remotes.set_url(remote_name, url)
+ nil
end
AUTOCRLF_VALUES = {
@@ -995,6 +1003,44 @@ module Gitlab
raw_output.compact
end
+ # Returns true if the given ref name exists
+ #
+ # Ref names must start with `refs/`.
+ def rugged_ref_exists?(ref_name)
+ raise ArgumentError, 'invalid refname' unless ref_name.start_with?('refs/')
+ rugged.references.exist?(ref_name)
+ rescue Rugged::ReferenceError
+ false
+ end
+
+ # Returns true if the given ref name exists
+ #
+ # Ref names must start with `refs/`.
+ def gitaly_ref_exists?(ref_name)
+ gitaly_ref_client.ref_exists?(ref_name)
+ end
+
+ # Returns true if the given tag exists
+ #
+ # name - The name of the tag as a String.
+ def rugged_tag_exists?(name)
+ !!rugged.tags[name]
+ end
+
+ # Returns true if the given branch exists
+ #
+ # name - The name of the branch as a String.
+ def rugged_branch_exists?(name)
+ rugged.branches.exists?(name)
+
+ # If the branch name is invalid (e.g. ".foo") Rugged will raise an error.
+ # Whatever code calls this method shouldn't have to deal with that so
+ # instead we just return `false` (which is true since a branch doesn't
+ # exist when it has an invalid name).
+ rescue Rugged::ReferenceError
+ false
+ end
+
def gitaly_copy_gitattributes(revision)
gitaly_repository_client.apply_gitattributes(revision)
end
diff --git a/lib/gitlab/git_access.rb b/lib/gitlab/git_access.rb
index 0b62911958d..3e8b83c0f90 100644
--- a/lib/gitlab/git_access.rb
+++ b/lib/gitlab/git_access.rb
@@ -4,6 +4,7 @@ module Gitlab
class GitAccess
UnauthorizedError = Class.new(StandardError)
NotFoundError = Class.new(StandardError)
+ ProjectMovedError = Class.new(NotFoundError)
ERROR_MESSAGES = {
upload: 'You are not allowed to upload code for this project.',
@@ -90,18 +91,18 @@ module Gitlab
end
def check_project_moved!
- if redirected_path
- url = protocol == 'ssh' ? project.ssh_url_to_repo : project.http_url_to_repo
- message = <<-MESSAGE.strip_heredoc
- Project '#{redirected_path}' was moved to '#{project.full_path}'.
+ return unless redirected_path
- Please update your Git remote and try again:
+ url = protocol == 'ssh' ? project.ssh_url_to_repo : project.http_url_to_repo
+ message = <<-MESSAGE.strip_heredoc
+ Project '#{redirected_path}' was moved to '#{project.full_path}'.
- git remote set-url origin #{url}
- MESSAGE
+ Please update your Git remote and try again:
- raise NotFoundError, message
- end
+ git remote set-url origin #{url}
+ MESSAGE
+
+ raise ProjectMovedError, message
end
def check_command_disabled!(cmd)
diff --git a/lib/gitlab/gitaly_client/commit_service.rb b/lib/gitlab/gitaly_client/commit_service.rb
index b36e81278d6..21a32a7e0db 100644
--- a/lib/gitlab/gitaly_client/commit_service.rb
+++ b/lib/gitlab/gitaly_client/commit_service.rb
@@ -22,7 +22,7 @@ module Gitlab
end
end
- def is_ancestor(ancestor_id, child_id)
+ def ancestor?(ancestor_id, child_id)
request = Gitaly::CommitIsAncestorRequest.new(
repository: @gitaly_repo,
ancestor_id: ancestor_id,
@@ -80,8 +80,8 @@ module Gitlab
def tree_entries(repository, revision, path)
request = Gitaly::GetTreeEntriesRequest.new(
repository: @gitaly_repo,
- revision: revision,
- path: path.presence || '.'
+ revision: GitalyClient.encode(revision),
+ path: path.present? ? GitalyClient.encode(path) : '.'
)
response = GitalyClient.call(@repository.storage, :commit_service, :get_tree_entries, request)
@@ -175,8 +175,8 @@ module Gitlab
def raw_blame(revision, path)
request = Gitaly::RawBlameRequest.new(
repository: @gitaly_repo,
- revision: revision,
- path: path
+ revision: GitalyClient.encode(revision),
+ path: GitalyClient.encode(path)
)
response = GitalyClient.call(@repository.storage, :commit_service, :raw_blame, request)
@@ -194,6 +194,16 @@ module Gitlab
response.commit
end
+ def patch(revision)
+ request = Gitaly::CommitPatchRequest.new(
+ repository: @gitaly_repo,
+ revision: GitalyClient.encode(revision)
+ )
+ response = GitalyClient.call(@repository.storage, :diff_service, :commit_patch, request)
+
+ response.sum(&:data)
+ end
+
private
def commit_diff_request_params(commit, options = {})
diff --git a/lib/gitlab/gitaly_client/ref_service.rb b/lib/gitlab/gitaly_client/ref_service.rb
index 919fb68b8c7..8c0008c6971 100644
--- a/lib/gitlab/gitaly_client/ref_service.rb
+++ b/lib/gitlab/gitaly_client/ref_service.rb
@@ -70,6 +70,14 @@ module Gitlab
consume_tags_response(response)
end
+ def ref_exists?(ref_name)
+ request = Gitaly::RefExistsRequest.new(repository: @gitaly_repo, ref: GitalyClient.encode(ref_name))
+ response = GitalyClient.call(@storage, :ref_service, :ref_exists, request)
+ response.value
+ rescue GRPC::InvalidArgument => e
+ raise ArgumentError, e.message
+ end
+
private
def consume_refs_response(response)
diff --git a/lib/gitlab/health_checks/db_check.rb b/lib/gitlab/health_checks/db_check.rb
index fd94984f8a2..e27e16ddaf6 100644
--- a/lib/gitlab/health_checks/db_check.rb
+++ b/lib/gitlab/health_checks/db_check.rb
@@ -10,7 +10,7 @@ module Gitlab
'db_ping'
end
- def is_successful?(result)
+ def successful?(result)
result == '1'
end
diff --git a/lib/gitlab/health_checks/redis/cache_check.rb b/lib/gitlab/health_checks/redis/cache_check.rb
index a28658d42d4..0eb9b77634a 100644
--- a/lib/gitlab/health_checks/redis/cache_check.rb
+++ b/lib/gitlab/health_checks/redis/cache_check.rb
@@ -15,7 +15,7 @@ module Gitlab
'redis_cache_ping'
end
- def is_successful?(result)
+ def successful?(result)
result == 'PONG'
end
diff --git a/lib/gitlab/health_checks/redis/queues_check.rb b/lib/gitlab/health_checks/redis/queues_check.rb
index f97d50d3947..f322fe831b8 100644
--- a/lib/gitlab/health_checks/redis/queues_check.rb
+++ b/lib/gitlab/health_checks/redis/queues_check.rb
@@ -15,7 +15,7 @@ module Gitlab
'redis_queues_ping'
end
- def is_successful?(result)
+ def successful?(result)
result == 'PONG'
end
diff --git a/lib/gitlab/health_checks/redis/redis_check.rb b/lib/gitlab/health_checks/redis/redis_check.rb
index fe4e3c4a3ab..8ceb0a0aa46 100644
--- a/lib/gitlab/health_checks/redis/redis_check.rb
+++ b/lib/gitlab/health_checks/redis/redis_check.rb
@@ -11,7 +11,7 @@ module Gitlab
'redis_ping'
end
- def is_successful?(result)
+ def successful?(result)
result == 'PONG'
end
diff --git a/lib/gitlab/health_checks/redis/shared_state_check.rb b/lib/gitlab/health_checks/redis/shared_state_check.rb
index e3244392902..07e6f707998 100644
--- a/lib/gitlab/health_checks/redis/shared_state_check.rb
+++ b/lib/gitlab/health_checks/redis/shared_state_check.rb
@@ -15,7 +15,7 @@ module Gitlab
'redis_shared_state_ping'
end
- def is_successful?(result)
+ def successful?(result)
result == 'PONG'
end
diff --git a/lib/gitlab/health_checks/simple_abstract_check.rb b/lib/gitlab/health_checks/simple_abstract_check.rb
index f5026171ba4..96945ce5b20 100644
--- a/lib/gitlab/health_checks/simple_abstract_check.rb
+++ b/lib/gitlab/health_checks/simple_abstract_check.rb
@@ -5,7 +5,7 @@ module Gitlab
def readiness
check_result = check
- if is_successful?(check_result)
+ if successful?(check_result)
HealthChecks::Result.new(true)
elsif check_result.is_a?(Timeout::Error)
HealthChecks::Result.new(false, "#{human_name} check timed out")
@@ -16,10 +16,10 @@ module Gitlab
def metrics
result, elapsed = with_timing(&method(:check))
- Rails.logger.error("#{human_name} check returned unexpected result #{result}") unless is_successful?(result)
+ Rails.logger.error("#{human_name} check returned unexpected result #{result}") unless successful?(result)
[
metric("#{metric_prefix}_timeout", result.is_a?(Timeout::Error) ? 1 : 0),
- metric("#{metric_prefix}_success", is_successful?(result) ? 1 : 0),
+ metric("#{metric_prefix}_success", successful?(result) ? 1 : 0),
metric("#{metric_prefix}_latency_seconds", elapsed)
]
end
@@ -30,7 +30,7 @@ module Gitlab
raise NotImplementedError
end
- def is_successful?(result)
+ def successful?(result)
raise NotImplementedError
end
diff --git a/lib/gitlab/import_export/import_export.yml b/lib/gitlab/import_export/import_export.yml
index 9d9ebcb389a..78795dd3d92 100644
--- a/lib/gitlab/import_export/import_export.yml
+++ b/lib/gitlab/import_export/import_export.yml
@@ -98,6 +98,7 @@ excluded_attributes:
- :last_activity_at
- :last_repository_updated_at
- :last_repository_check_at
+ - :storage_version
snippets:
- :expired_at
merge_request_diff:
@@ -133,5 +134,11 @@ methods:
- :utf8_diff
merge_requests:
- :diff_head_sha
+ - :source_branch_sha
+ - :target_branch_sha
project:
- :description_html
+ events:
+ - :action
+ push_event_payload:
+ - :action \ No newline at end of file
diff --git a/lib/gitlab/import_export/merge_request_parser.rb b/lib/gitlab/import_export/merge_request_parser.rb
index c20adc20bfd..81a213e8321 100644
--- a/lib/gitlab/import_export/merge_request_parser.rb
+++ b/lib/gitlab/import_export/merge_request_parser.rb
@@ -30,7 +30,7 @@ module Gitlab
end
def branch_exists?(branch_name)
- @project.repository.branch_exists?(branch_name)
+ @project.repository.raw.branch_exists?(branch_name)
end
def fork_merge_request?
diff --git a/lib/gitlab/job_waiter.rb b/lib/gitlab/job_waiter.rb
index 208f0e1bbea..4d6bbda15f3 100644
--- a/lib/gitlab/job_waiter.rb
+++ b/lib/gitlab/job_waiter.rb
@@ -1,12 +1,31 @@
module Gitlab
# JobWaiter can be used to wait for a number of Sidekiq jobs to complete.
+ #
+ # Its use requires the cooperation of the sidekiq jobs themselves. Set up the
+ # waiter, then start the jobs, passing them its `key`. Their `perform` methods
+ # should look like:
+ #
+ # def perform(args, notify_key)
+ # # do work
+ # ensure
+ # ::Gitlab::JobWaiter.notify(notify_key, jid)
+ # end
+ #
+ # The JobWaiter blocks popping items from a Redis array. All the sidekiq jobs
+ # push to that array when done. Once the waiter has popped `count` items, it
+ # knows all the jobs are done.
class JobWaiter
- # The sleep interval between checking keys, in seconds.
- INTERVAL = 0.1
+ def self.notify(key, jid)
+ Gitlab::Redis::SharedState.with { |redis| redis.lpush(key, jid) }
+ end
+
+ attr_reader :key, :jobs_remaining, :finished
- # jobs - The job IDs to wait for.
- def initialize(jobs)
- @jobs = jobs
+ # jobs_remaining - the number of jobs left to wait for
+ def initialize(jobs_remaining)
+ @key = "gitlab:job_waiter:#{SecureRandom.uuid}"
+ @jobs_remaining = jobs_remaining
+ @finished = []
end
# Waits for all the jobs to be completed.
@@ -15,13 +34,33 @@ module Gitlab
# ensures we don't indefinitely block a caller in case a job takes
# long to process, or is never processed.
def wait(timeout = 10)
- start = Time.current
+ deadline = Time.now.utc + timeout
+
+ Gitlab::Redis::SharedState.with do |redis|
+ # Fallback key expiry: allow a long grace period to reduce the chance of
+ # a job pushing to an expired key and recreating it
+ redis.expire(key, [timeout * 2, 10.minutes.to_i].max)
+
+ while jobs_remaining > 0
+ # Redis will not take fractional seconds. Prefer waiting too long over
+ # not waiting long enough
+ seconds_left = (deadline - Time.now.utc).ceil
- while (Time.current - start) <= timeout
- break if SidekiqStatus.all_completed?(@jobs)
+ # Redis interprets 0 as "wait forever", so skip the final `blpop` call
+ break if seconds_left <= 0
- sleep(INTERVAL) # to not overload Redis too much.
+ list, jid = redis.blpop(key, timeout: seconds_left)
+ break unless list && jid # timed out
+
+ @finished << jid
+ @jobs_remaining -= 1
+ end
+
+ # All jobs have finished, so expire the key immediately
+ redis.expire(key, 0) if jobs_remaining == 0
end
+
+ finished
end
end
end
diff --git a/lib/gitlab/ldap/adapter.rb b/lib/gitlab/ldap/adapter.rb
index 8867a91c244..cd7e4ca7b7e 100644
--- a/lib/gitlab/ldap/adapter.rb
+++ b/lib/gitlab/ldap/adapter.rb
@@ -73,7 +73,7 @@ module Gitlab
private
def user_options(field, value, limit)
- options = { attributes: user_attributes }
+ options = { attributes: Gitlab::LDAP::Person.ldap_attributes(config).compact.uniq }
options[:size] = limit if limit
if field.to_sym == :dn
@@ -99,10 +99,6 @@ module Gitlab
filter
end
end
-
- def user_attributes
- %W(#{config.uid} cn dn) + config.attributes['username'] + config.attributes['email']
- end
end
end
end
diff --git a/lib/gitlab/ldap/person.rb b/lib/gitlab/ldap/person.rb
index e138b466a34..4d6f8ac79de 100644
--- a/lib/gitlab/ldap/person.rb
+++ b/lib/gitlab/ldap/person.rb
@@ -21,6 +21,15 @@ module Gitlab
adapter.dn_matches_filter?(dn, AD_USER_DISABLED)
end
+ def self.ldap_attributes(config)
+ [
+ 'dn', # Used in `dn`
+ config.uid, # Used in `uid`
+ *config.attributes['name'], # Used in `name`
+ *config.attributes['email'] # Used in `email`
+ ]
+ end
+
def initialize(entry, provider)
Rails.logger.debug { "Instantiating #{self.class.name} with LDIF:\n#{entry.to_ldif}" }
@entry = entry
diff --git a/lib/gitlab/logger.rb b/lib/gitlab/logger.rb
index 59b21149a9a..6bffd410ed0 100644
--- a/lib/gitlab/logger.rb
+++ b/lib/gitlab/logger.rb
@@ -14,13 +14,9 @@ module Gitlab
def self.read_latest
path = Rails.root.join("log", file_name)
- self.build unless File.exist?(path)
- tail_output, _ = Gitlab::Popen.popen(%W(tail -n 2000 #{path}))
- tail_output.split("\n")
- end
- def self.read_latest_for(filename)
- path = Rails.root.join("log", filename)
+ return [] unless File.readable?(path)
+
tail_output, _ = Gitlab::Popen.popen(%W(tail -n 2000 #{path}))
tail_output.split("\n")
end
diff --git a/lib/gitlab/prometheus/queries/matched_metrics_query.rb b/lib/gitlab/prometheus/queries/matched_metrics_query.rb
index d4894c87f8d..4c3edccc71a 100644
--- a/lib/gitlab/prometheus/queries/matched_metrics_query.rb
+++ b/lib/gitlab/prometheus/queries/matched_metrics_query.rb
@@ -42,13 +42,13 @@ module Gitlab
lookup = series.each_slice(MAX_QUERY_ITEMS).flat_map do |batched_series|
client_series(*batched_series, start: timeframe_start, stop: timeframe_end)
- .select(&method(:has_matching_label))
+ .select(&method(:has_matching_label?))
.map { |series_info| [series_info['__name__'], true] }
end
lookup.to_h
end
- def has_matching_label(series_info)
+ def has_matching_label?(series_info)
series_info.key?('environment')
end
diff --git a/lib/gitlab/regex.rb b/lib/gitlab/regex.rb
index 1adc5ec952a..58f6245579a 100644
--- a/lib/gitlab/regex.rb
+++ b/lib/gitlab/regex.rb
@@ -53,7 +53,8 @@ module Gitlab
end
def kubernetes_namespace_regex_message
- "can contain only letters, digits or '-', and cannot start or end with '-'"
+ "can contain only lowercase letters, digits, and '-'. " \
+ "Must start with a letter, and cannot end with '-'"
end
def environment_slug_regex
diff --git a/lib/gitlab/sidekiq_throttler.rb b/lib/gitlab/sidekiq_throttler.rb
index d4d39a888e7..5512afa45a8 100644
--- a/lib/gitlab/sidekiq_throttler.rb
+++ b/lib/gitlab/sidekiq_throttler.rb
@@ -3,6 +3,8 @@ module Gitlab
class << self
def execute!
if Gitlab::CurrentSettings.sidekiq_throttling_enabled?
+ require 'sidekiq-limit_fetch'
+
Gitlab::CurrentSettings.current_application_settings.sidekiq_throttling_queues.each do |queue|
Sidekiq::Queue[queue].limit = queue_limit
end
diff --git a/lib/system_check/app/git_config_check.rb b/lib/system_check/app/git_config_check.rb
index 198867f7ac6..d08a81639e3 100644
--- a/lib/system_check/app/git_config_check.rb
+++ b/lib/system_check/app/git_config_check.rb
@@ -20,7 +20,7 @@ module SystemCheck
# Returns true if all subcommands were successful (according to their exit code)
# Returns false if any or all subcommands failed.
def repair!
- return false unless is_gitlab_user?
+ return false unless gitlab_user?
command_success = OPTIONS.map do |name, value|
system(*%W(#{Gitlab.config.git.bin_path} config --global #{name} #{value}))
diff --git a/lib/system_check/base_check.rb b/lib/system_check/base_check.rb
index 5dcb3f0886b..7f9e2ffffc2 100644
--- a/lib/system_check/base_check.rb
+++ b/lib/system_check/base_check.rb
@@ -73,7 +73,7 @@ module SystemCheck
self.class.instance_methods(false).include?(:skip?)
end
- def is_multi_check?
+ def multi_check?
self.class.instance_methods(false).include?(:multi_check)
end
diff --git a/lib/system_check/simple_executor.rb b/lib/system_check/simple_executor.rb
index e5986612908..6604b1078cf 100644
--- a/lib/system_check/simple_executor.rb
+++ b/lib/system_check/simple_executor.rb
@@ -53,7 +53,7 @@ module SystemCheck
end
# When implements a multi check, we don't control the output
- if check.is_multi_check?
+ if check.multi_check?
check.multi_check
return
end
diff --git a/lib/tasks/gitlab/import.rake b/lib/tasks/gitlab/import.rake
index 48bd9139ce8..d227a0c8bdb 100644
--- a/lib/tasks/gitlab/import.rake
+++ b/lib/tasks/gitlab/import.rake
@@ -9,71 +9,16 @@ namespace :gitlab do
# * The project owner will set to the first administator of the system
# * Existing projects will be skipped
#
+ #
desc "GitLab | Import bare repositories from repositories -> storages into GitLab project instance"
task repos: :environment do
- Gitlab.config.repositories.storages.each_value do |repository_storage|
- git_base_path = repository_storage['path']
- repos_to_import = Dir.glob(git_base_path + '/**/*.git')
-
- repos_to_import.each do |repo_path|
- # strip repo base path
- repo_path[0..git_base_path.length] = ''
-
- path = repo_path.sub(/\.git$/, '')
- group_name, name = File.split(path)
- group_name = nil if group_name == '.'
-
- puts "Processing #{repo_path}".color(:yellow)
-
- if path.end_with?('.wiki')
- puts " * Skipping wiki repo"
- next
- end
-
- project = Project.find_by_full_path(path)
-
- if project
- puts " * #{project.name} (#{repo_path}) exists"
- else
- user = User.admins.reorder("id").first
-
- project_params = {
- name: name,
- path: name
- }
-
- # find group namespace
- if group_name
- group = Namespace.find_by(path: group_name)
- # create group namespace
- unless group
- group = Group.new(name: group_name)
- group.path = group_name
- group.owner = user
- if group.save
- puts " * Created Group #{group.name} (#{group.id})".color(:green)
- else
- puts " * Failed trying to create group #{group.name}".color(:red)
- end
- end
- # set project group
- project_params[:namespace_id] = group.id
- end
-
- project = Projects::CreateService.new(user, project_params).execute
+ if Project.current_application_settings.hashed_storage_enabled
+ puts 'Cannot import repositories when Hashed Storage is enabled'.color(:red)
- if project.persisted?
- puts " * Created #{project.name} (#{repo_path})".color(:green)
- ProjectCacheWorker.perform_async(project.id)
- else
- puts " * Failed trying to create #{project.name} (#{repo_path})".color(:red)
- puts " Errors: #{project.errors.messages}".color(:red)
- end
- end
- end
+ exit 1
end
- puts "Done!".color(:green)
+ Gitlab::BareRepositoryImporter.execute
end
end
end
diff --git a/lib/tasks/gitlab/task_helpers.rb b/lib/tasks/gitlab/task_helpers.rb
index d85b810ac66..8a63f486fa3 100644
--- a/lib/tasks/gitlab/task_helpers.rb
+++ b/lib/tasks/gitlab/task_helpers.rb
@@ -104,7 +104,7 @@ module Gitlab
Gitlab.config.gitlab.user
end
- def is_gitlab_user?
+ def gitlab_user?
return @is_gitlab_user unless @is_gitlab_user.nil?
current_user = run_command(%w(whoami)).chomp
@@ -114,7 +114,7 @@ module Gitlab
def warn_user_is_not_gitlab
return if @warned_user_not_gitlab
- unless is_gitlab_user?
+ unless gitlab_user?
current_user = run_command(%w(whoami)).chomp
puts " Warning ".color(:black).background(:yellow)
diff --git a/lib/tasks/import.rake b/lib/tasks/import.rake
index 96b8f59242c..1206302cb76 100644
--- a/lib/tasks/import.rake
+++ b/lib/tasks/import.rake
@@ -72,23 +72,7 @@ class GithubImport
return @current_user.namespace if names == @current_user.namespace_path
return @current_user.namespace unless @current_user.can_create_group?
- full_path_namespace = Namespace.find_by_full_path(names)
-
- return full_path_namespace if full_path_namespace
-
- names.split('/').inject(nil) do |parent, name|
- begin
- namespace = Group.create!(name: name,
- path: name,
- owner: @current_user,
- parent: parent)
- namespace.add_owner(@current_user)
-
- namespace
- rescue ActiveRecord::RecordNotUnique, ActiveRecord::RecordInvalid
- Namespace.where(parent: parent).find_by_path_or_name(name)
- end
- end
+ Groups::NestedCreateService.new(@current_user, group_path: names).execute
end
def full_path_namespace(names)
diff --git a/locale/bg/gitlab.po b/locale/bg/gitlab.po
index 5c531f0cd7d..d8ab1f253e8 100644
--- a/locale/bg/gitlab.po
+++ b/locale/bg/gitlab.po
@@ -1,34 +1,51 @@
-# Huang Tao <htve@outlook.com>, 2017. #zanata
-# Lyubomir Vasilev <lyubomirv@abv.bg>, 2017. #zanata
msgid ""
msgstr ""
-"Project-Id-Version: gitlab 1.0.0\n"
+"Project-Id-Version: gitlab-ee\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2017-07-13 12:07-0500\n"
+"POT-Creation-Date: 2017-08-18 14:15+0530\n"
+"PO-Revision-Date: 2017-08-23 10:02-0400\n"
+"Last-Translator: gitlab <mbartlett+crowdin@gitlab.com>\n"
+"Language-Team: Bulgarian\n"
+"Language: bg_BG\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"PO-Revision-Date: 2017-08-03 04:43-0400\n"
-"Last-Translator: Lyubomir Vasilev <lyubomirv@abv.bg>\n"
-"Language-Team: Bulgarian (https://translate.zanata.org/project/view/GitLab)\n"
-"Language: bg\n"
-"X-Generator: Zanata 3.9.6\n"
-"Plural-Forms: nplurals=2; plural=(n != 1)\n"
-
-msgid "%s additional commit has been omitted to prevent performance issues."
-msgid_plural ""
-"%s additional commits have been omitted to prevent performance issues."
-msgstr[0] "%s подаване беше пропуÑнато, за да не Ñе натоварва ÑиÑтемата."
-msgstr[1] "%s Ð¿Ð¾Ð´Ð°Ð²Ð°Ð½Ð¸Ñ Ð±Ñха пропуÑнати, за да не Ñе натоварва ÑиÑтемата."
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Generator: crowdin.com\n"
+"X-Crowdin-Project: gitlab-ee\n"
+"X-Crowdin-Language: bg\n"
+"X-Crowdin-File: /master/locale/gitlab.pot\n"
msgid "%d commit"
msgid_plural "%d commits"
msgstr[0] "%d подаване"
msgstr[1] "%d подаваниÑ"
+msgid "%s additional commit has been omitted to prevent performance issues."
+msgid_plural "%s additional commits have been omitted to prevent performance issues."
+msgstr[0] "%s подаване беше пропуÑнато, за да не Ñе натоварва ÑиÑтемата."
+msgstr[1] "%s Ð¿Ð¾Ð´Ð°Ð²Ð°Ð½Ð¸Ñ Ð±Ñха пропуÑнати, за да не Ñе натоварва ÑиÑтемата."
+
msgid "%{commit_author_link} committed %{commit_timeago}"
msgstr "%{commit_author_link} подаде %{commit_timeago}"
+msgid "%{number_of_failures} of %{maximum_failures} failures. GitLab will allow access on the next attempt."
+msgstr ""
+
+msgid "%{number_of_failures} of %{maximum_failures} failures. GitLab will block access for %{number_of_seconds} seconds."
+msgstr ""
+
+msgid "%{number_of_failures} of %{maximum_failures} failures. GitLab will not retry automatically. Reset storage information when the problem is resolved."
+msgstr ""
+
+msgid "%{storage_name}: failed storage access attempt on host:"
+msgid_plural "%{storage_name}: %{failed_attempts} failed storage access attempts:"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "(checkout the %{link} for information on how to install it)."
+msgstr ""
+
msgid "1 pipeline"
msgid_plural "%d pipelines"
msgstr[0] "1 Ñхема"
@@ -40,6 +57,9 @@ msgstr "Ðабор от графики отноÑно непрекъÑнатат
msgid "About auto deploy"
msgstr "ОтноÑно автоматичното внедрÑване"
+msgid "Access to failing storages has been temporarily disabled to allow the mount to recover. Reset storage information after the issue has been resolved to allow access again."
+msgstr ""
+
msgid "Active"
msgstr "Ðктивно"
@@ -56,19 +76,32 @@ msgid "Add License"
msgstr "ДобавÑне на лиценз"
msgid "Add an SSH key to your profile to pull or push via SSH."
-msgstr ""
-"Добавете SSH ключ в профила Ñи, за да можете да изтеглÑте или изпращате "
-"промени чрез SSH."
+msgstr "Добавете SSH ключ в профила Ñи, за да можете да изтеглÑте или изпращате промени чрез SSH."
msgid "Add new directory"
msgstr "ДобавÑне на нова папка"
+msgid "All"
+msgstr ""
+
msgid "Archived project! Repository is read-only"
msgstr "Ðрхивиран проект! Хранилището е Ñамо за четене"
msgid "Are you sure you want to delete this pipeline schedule?"
msgstr "ÐаиÑтина ли иÑкате да изтриете този план за Ñхема?"
+msgid "Are you sure you want to discard your changes?"
+msgstr ""
+
+msgid "Are you sure you want to reset registration token?"
+msgstr ""
+
+msgid "Are you sure you want to reset the health check token?"
+msgstr ""
+
+msgid "Are you sure?"
+msgstr ""
+
msgid "Attach a file by drag &amp; drop or %{upload_link}"
msgstr "Прикачете файл чрез влачене и пуÑкане или %{upload_link}"
@@ -77,14 +110,8 @@ msgid_plural "Branches"
msgstr[0] "Клон"
msgstr[1] "Клонове"
-msgid ""
-"Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, "
-"choose a GitLab CI Yaml template and commit your changes. "
-"%{link_to_autodeploy_doc}"
-msgstr ""
-"Клонът <strong>%{branch_name}</strong> беше Ñъздаден. За да наÑтроите "
-"автоматичното внедрÑване, изберете Yaml шаблон за GitLab CI и подайте "
-"промените Ñи. %{link_to_autodeploy_doc}"
+msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
+msgstr "Клонът <strong>%{branch_name}</strong> беше Ñъздаден. За да наÑтроите автоматичното внедрÑване, изберете Yaml шаблон за GitLab CI и подайте промените Ñи. %{link_to_autodeploy_doc}"
msgid "BranchSwitcherPlaceholder|Search branches"
msgstr "ТърÑете в клоновете"
@@ -116,6 +143,9 @@ msgstr "ÐšÐ¾Ð½Ñ„Ð¸Ð³ÑƒÑ€Ð°Ñ†Ð¸Ñ Ð½Ð° непрекъÑната интеграцÐ
msgid "Cancel"
msgstr "Отказ"
+msgid "Cancel edit"
+msgstr ""
+
msgid "ChangeTypeActionLabel|Pick into branch"
msgstr "Избиране в клона"
@@ -194,6 +224,9 @@ msgstr "пропуÑнато"
msgid "CiStatus|running"
msgstr "протича в момента"
+msgid "Comments"
+msgstr ""
+
msgid "Commit"
msgid_plural "Commits"
msgstr[0] "Подаване"
@@ -241,12 +274,11 @@ msgstr "Копиране на идентификатора на подаване
msgid "Create New Directory"
msgstr "Създаване на нова папка"
-msgid ""
-"Create a personal access token on your account to pull or push via "
-"%{protocol}."
+msgid "Create a new branch"
msgstr ""
-"Създайте Ñи личен жетон за доÑтъп в профила Ñи, за да можете да изтеглÑте и "
-"изпращате промени чрез %{protocol}."
+
+msgid "Create a personal access token on your account to pull or push via %{protocol}."
+msgstr "Създайте Ñи личен жетон за доÑтъп в профила Ñи, за да можете да изтеглÑте и изпращате промени чрез %{protocol}."
msgid "Create directory"
msgstr "Създаване на папка"
@@ -278,24 +310,14 @@ msgstr "СинтакÑÐ¸Ñ Ð½Ð° „Cron“"
msgid "Custom notification events"
msgstr "ПерÑонализирани ÑÑŠÐ±Ð¸Ñ‚Ð¸Ñ Ð·Ð° извеÑÑ‚Ñване"
-msgid ""
-"Custom notification levels are the same as participating levels. With custom "
-"notification levels you will also receive notifications for select events. "
-"To find out more, check out %{notification_link}."
-msgstr ""
-"ПерÑонализираните нива на извеÑÑ‚Ñване Ñа Ñъщите като нивата за учаÑтие. С "
-"перÑонализираните нива на извеÑÑ‚Ñване ще можете да получавате и извеÑÑ‚Ð¸Ñ Ð·Ð° "
-"избрани ÑъбитиÑ. За да научите повече, прегледайте %{notification_link}."
+msgid "Custom notification levels are the same as participating levels. With custom notification levels you will also receive notifications for select events. To find out more, check out %{notification_link}."
+msgstr "ПерÑонализираните нива на извеÑÑ‚Ñване Ñа Ñъщите като нивата за учаÑтие. С перÑонализираните нива на извеÑÑ‚Ñване ще можете да получавате и извеÑÑ‚Ð¸Ñ Ð·Ð° избрани ÑъбитиÑ. За да научите повече, прегледайте %{notification_link}."
msgid "Cycle Analytics"
msgstr "Ðнализ на циклите"
-msgid ""
-"Cycle Analytics gives an overview of how much time it takes to go from idea "
-"to production in your project."
-msgstr ""
-"Ðнализът на циклите дава общ поглед върху това колко време е нужно на една "
-"Ð¸Ð´ÐµÑ Ð´Ð° Ñе превърне в завършена функционалноÑÑ‚ в проекта."
+msgid "Cycle Analytics gives an overview of how much time it takes to go from idea to production in your project."
+msgstr "Ðнализът на циклите дава общ поглед върху това колко време е нужно на една Ð¸Ð´ÐµÑ Ð´Ð° Ñе превърне в завършена функционалноÑÑ‚ в проекта."
msgid "CycleAnalyticsStage|Code"
msgstr "Програмиране"
@@ -332,9 +354,15 @@ msgstr[1] "ВнедрÑваниÑ"
msgid "Description"
msgstr "ОпиÑание"
+msgid "Details"
+msgstr ""
+
msgid "Directory name"
msgstr "Име на папката"
+msgid "Discard changes"
+msgstr ""
+
msgid "Don't show again"
msgstr "Да не Ñе показва повече"
@@ -371,6 +399,24 @@ msgstr "Редактиране"
msgid "Edit Pipeline Schedule %{id}"
msgstr "Редактиране на плана %{id} за Ñхема"
+msgid "EventFilterBy|Filter by all"
+msgstr ""
+
+msgid "EventFilterBy|Filter by comments"
+msgstr ""
+
+msgid "EventFilterBy|Filter by issue events"
+msgstr ""
+
+msgid "EventFilterBy|Filter by merge events"
+msgstr ""
+
+msgid "EventFilterBy|Filter by push events"
+msgstr ""
+
+msgid "EventFilterBy|Filter by team"
+msgstr ""
+
msgid "Every day (at 4:00am)"
msgstr "Ð’Ñеки ден (в 4 ч. Ñутринта)"
@@ -416,8 +462,13 @@ msgid "From issue creation until deploy to production"
msgstr "От Ñъздаването на проблема до внедрÑването в крайната верÑиÑ"
msgid "From merge request merge until deploy to production"
+msgstr "От прилагането на заÑвката за Ñливане до внедрÑването в крайната верÑиÑ"
+
+msgid "Git storage health information has been reset"
+msgstr ""
+
+msgid "GitLab Runner section"
msgstr ""
-"От прилагането на заÑвката за Ñливане до внедрÑването в крайната верÑиÑ"
msgid "Go to your fork"
msgstr "Към Вашето разклонение"
@@ -425,6 +476,24 @@ msgstr "Към Вашето разклонение"
msgid "GoToYourFork|Fork"
msgstr "Разклонение"
+msgid "Health Check"
+msgstr ""
+
+msgid "Health information can be retrieved from the following endpoints. More information is available"
+msgstr ""
+
+msgid "HealthCheck|Access token is"
+msgstr ""
+
+msgid "HealthCheck|Healthy"
+msgstr ""
+
+msgid "HealthCheck|No Health Problems Detected"
+msgstr ""
+
+msgid "HealthCheck|Unhealthy"
+msgstr ""
+
msgid "Home"
msgstr "Ðачало"
@@ -434,12 +503,18 @@ msgstr "ОÑвежаването започна уÑпешно"
msgid "Import repository"
msgstr "ВнаÑÑне на хранилище"
+msgid "Install a Runner compatible with GitLab CI"
+msgstr ""
+
msgid "Interval Pattern"
msgstr "Шаблон за интервала"
msgid "Introducing Cycle Analytics"
msgstr "ПредÑтавÑме Ви анализа на циклите"
+msgid "Issue events"
+msgstr ""
+
msgid "Jobs for last month"
msgstr "Задачи за поÑÐ»ÐµÐ´Ð½Ð¸Ñ Ð¼ÐµÑец"
@@ -469,6 +544,12 @@ msgstr "ПоÑледна промÑна"
msgid "Last commit"
msgstr "ПоÑледно подаване"
+msgid "LastPushEvent|You pushed to"
+msgstr ""
+
+msgid "LastPushEvent|at"
+msgstr ""
+
msgid "Learn more in the"
msgstr "Ðаучете повече в"
@@ -489,9 +570,15 @@ msgstr[1] "Ограничено до показване на най-много %
msgid "Median"
msgstr "Медиана"
+msgid "Merge events"
+msgstr ""
+
msgid "MissingSSHKeyWarningLink|add an SSH key"
msgstr "добавите SSH ключ"
+msgid "More information is available|here"
+msgstr ""
+
msgid "New Issue"
msgid_plural "New Issues"
msgstr[0] "Ðов проблем"
@@ -689,6 +776,9 @@ msgstr "Ñ ÐµÑ‚Ð°Ð¿"
msgid "Pipeline|with stages"
msgstr "Ñ ÐµÑ‚Ð°Ð¿Ð¸"
+msgid "Project"
+msgstr ""
+
msgid "Project '%{project_name}' queued for deletion."
msgstr "Проектът „%{project_name}“ е добавен в опашката за изтриване."
@@ -702,8 +792,10 @@ msgid "Project '%{project_name}' will be deleted."
msgstr "Проектът „%{project_name}“ ще бъде изтрит."
msgid "Project access must be granted explicitly to each user."
+msgstr "ДоÑтъпът до проекта Ñ‚Ñ€Ñбва да бъде даван поотделно на вÑеки потребител."
+
+msgid "Project details"
msgstr ""
-"ДоÑтъпът до проекта Ñ‚Ñ€Ñбва да бъде даван поотделно на вÑеки потребител."
msgid "Project export could not be deleted."
msgstr "ИзнеÑените данни на проекта не могат да бъдат изтрити."
@@ -711,20 +803,18 @@ msgstr "ИзнеÑените данни на проекта не могат да
msgid "Project export has been deleted."
msgstr "ИзнеÑените данни на проекта бÑха изтрити."
-msgid ""
-"Project export link has expired. Please generate a new export from your "
-"project settings."
-msgstr ""
-"Връзката към изнеÑените данни на проекта изгуби давноÑÑ‚. МолÑ, Ñъздайте нова "
-"от наÑтройките на проекта."
+msgid "Project export link has expired. Please generate a new export from your project settings."
+msgstr "Връзката към изнеÑените данни на проекта изгуби давноÑÑ‚. МолÑ, Ñъздайте нова от наÑтройките на проекта."
msgid "Project export started. A download link will be sent by email."
-msgstr ""
-"ИзнаÑÑнето на проекта започна. Ще получите връзка към данните по е-поща."
+msgstr "ИзнаÑÑнето на проекта започна. Ще получите връзка към данните по е-поща."
msgid "Project home"
msgstr "Ðачална Ñтраница на проекта"
+msgid "ProjectActivityRSS|Subscribe"
+msgstr ""
+
msgid "ProjectFeature|Disabled"
msgstr "Изключено"
@@ -746,6 +836,9 @@ msgstr "Етап"
msgid "ProjectNetworkGraph|Graph"
msgstr "Графика"
+msgid "Push events"
+msgstr ""
+
msgid "Read more"
msgstr "Прочетете повече"
@@ -782,9 +875,21 @@ msgstr "ÐапомнÑне по-къÑно"
msgid "Remove project"
msgstr "Премахване на проекта"
+msgid "Repository"
+msgstr ""
+
msgid "Request Access"
msgstr "ЗаÑвка за доÑтъп"
+msgid "Reset git storage health information"
+msgstr ""
+
+msgid "Reset health check access token"
+msgstr ""
+
+msgid "Reset runners registration token"
+msgstr ""
+
msgid "Revert this commit"
msgstr "ОтмÑна на това подаване"
@@ -809,13 +914,14 @@ msgstr "Изберете формата на архива"
msgid "Select a timezone"
msgstr "Изберете чаÑова зона"
+msgid "Select existing branch"
+msgstr ""
+
msgid "Select target branch"
msgstr "Изберете целеви клон"
msgid "Set a password on your account to pull or push via %{protocol}."
-msgstr ""
-"Задайте парола на профила Ñи, за да можете да изтеглÑте и изпращате промени "
-"чрез %{protocol}."
+msgstr "Задайте парола на профила Ñи, за да можете да изтеглÑте и изпращате промени чрез %{protocol}."
msgid "Set up CI"
msgstr "ÐаÑтройка на ÐИ"
@@ -837,12 +943,18 @@ msgstr[1] "Показване на %d ÑъбитиÑ"
msgid "Source code"
msgstr "Изходен код"
+msgid "Specify the following URL during the Runner setup:"
+msgstr ""
+
msgid "StarProject|Star"
msgstr "Звезда"
msgid "Start a %{new_merge_request} with these changes"
msgstr "Създайте %{new_merge_request} Ñ Ñ‚ÐµÐ·Ð¸ промени"
+msgid "Start the Runner!"
+msgstr ""
+
msgid "Switch branch/tag"
msgstr "Преминаване към клон/етикет"
@@ -857,14 +969,11 @@ msgstr "Етикети"
msgid "Target Branch"
msgstr "Целеви клон"
-msgid ""
-"The coding stage shows the time from the first commit to creating the merge "
-"request. The data will automatically be added here once you create your "
-"first merge request."
+msgid "Team"
msgstr ""
-"Етапът на програмиране показва времето от първото подаване до Ñъздаването на "
-"заÑвката за Ñливане. Данните ще бъдат добавени тук автоматично Ñлед като "
-"бъде Ñъздадена първата заÑвка за Ñливане."
+
+msgid "The coding stage shows the time from the first commit to creating the merge request. The data will automatically be added here once you create your first merge request."
+msgstr "Етапът на програмиране показва времето от първото подаване до Ñъздаването на заÑвката за Ñливане. Данните ще бъдат добавени тук автоматично Ñлед като бъде Ñъздадена първата заÑвка за Ñливане."
msgid "The collection of events added to the data gathered for that stage."
msgstr "СъвкупноÑтта от ÑÑŠÐ±Ð¸Ñ‚Ð¸Ñ Ð´Ð¾Ð±Ð°Ð²ÐµÐ½Ð¸ към данните Ñъбрани за този етап."
@@ -872,46 +981,20 @@ msgstr "СъвкупноÑтта от ÑÑŠÐ±Ð¸Ñ‚Ð¸Ñ Ð´Ð¾Ð±Ð°Ð²ÐµÐ½Ð¸ към дÐ
msgid "The fork relationship has been removed."
msgstr "Връзката на разклонение беше премахната."
-msgid ""
-"The issue stage shows the time it takes from creating an issue to assigning "
-"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 ""
-"Етапът на проблемите показва колко е времето от Ñъздаването на проблем до "
-"определÑнето на целеви етап на проекта за него, или до добавÑнето му в "
-"ÑпиÑък на дъÑката за проблеми. Започнете да добавÑте проблеми, за да видите "
-"данните за този етап."
+msgid "The issue stage shows the time it takes from creating an issue to assigning 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 "Етапът на проблемите показва колко е времето от Ñъздаването на проблем до определÑнето на целеви етап на проекта за него, или до добавÑнето му в ÑпиÑък на дъÑката за проблеми. Започнете да добавÑте проблеми, за да видите данните за този етап."
msgid "The phase of the development lifecycle."
msgstr "Етапът от цикъла на разработка"
-msgid ""
-"The pipelines schedule runs pipelines in the future, repeatedly, for "
-"specific branches or tags. Those scheduled pipelines will inherit limited "
-"project access based on their associated user."
-msgstr ""
-"Планът за Ñхемата ще изпълнÑва Ñхемите в бъдеще, периодично, за определени "
-"клонове или етикети. Тези планирани Ñхеми ще наÑледÑÑ‚ ограничениÑта на "
-"доÑтъпа до проекта на ÑÐ²ÑŠÑ€Ð·Ð°Ð½Ð¸Ñ Ñ Ñ‚ÑÑ… потребител."
+msgid "The pipelines schedule runs pipelines in the future, repeatedly, for specific branches or tags. Those scheduled pipelines will inherit limited project access based on their associated user."
+msgstr "Планът за Ñхемата ще изпълнÑва Ñхемите в бъдеще, периодично, за определени клонове или етикети. Тези планирани Ñхеми ще наÑледÑÑ‚ ограничениÑта на доÑтъпа до проекта на ÑÐ²ÑŠÑ€Ð·Ð°Ð½Ð¸Ñ Ñ Ñ‚ÑÑ… потребител."
-msgid ""
-"The planning stage shows the time from the previous step to pushing your "
-"first commit. This time will be added automatically once you push your first "
-"commit."
-msgstr ""
-"Етапът на планиране показва колко е времето от преходната Ñтъпка до "
-"изпращането на първото подаване. Това време ще бъде добавено автоматично "
-"Ñлед като изпратите първото Ñи подаване."
+msgid "The planning stage shows the time from the previous step to pushing your first commit. This time will be added automatically once you push your first commit."
+msgstr "Етапът на планиране показва колко е времето от преходната Ñтъпка до изпращането на първото подаване. Това време ще бъде добавено автоматично Ñлед като изпратите първото Ñи подаване."
-msgid ""
-"The production stage shows the total time it takes between creating an issue "
-"and deploying the code to production. The data will be automatically added "
-"once you have completed the full idea to production cycle."
-msgstr ""
-"Етапът на издаване показва общото време, което е нужно от Ñъздаването на "
-"проблем до внедрÑването на кода в крайната верÑиÑ. Данните ще бъдат добавени "
-"автоматично Ñлед като завършите един пълен цикъл и превърнете първата Ñи "
-"Ð¸Ð´ÐµÑ Ð² реалноÑÑ‚."
+msgid "The production stage shows the total time it takes between creating an issue and deploying the code to production. The data will be automatically added once you have completed the full idea to production cycle."
+msgstr "Етапът на издаване показва общото време, което е нужно от Ñъздаването на проблем до внедрÑването на кода в крайната верÑиÑ. Данните ще бъдат добавени автоматично Ñлед като завършите един пълен цикъл и превърнете първата Ñи Ð¸Ð´ÐµÑ Ð² реалноÑÑ‚."
msgid "The project can be accessed by any logged in user."
msgstr "Ð’Ñеки впиÑан потребител има доÑтъп до проекта."
@@ -922,52 +1005,26 @@ msgstr "Ð’Ñеки може да има доÑтъп до проекта, без
msgid "The repository for this project does not exist."
msgstr "Хранилището за този проект не ÑъщеÑтвува."
-msgid ""
-"The review stage shows the time from creating the merge request to merging "
-"it. The data will automatically be added after you merge your first merge "
-"request."
-msgstr ""
-"Етапът на преглед и одобрение показва времето от Ñъздаването на заÑвката за "
-"Ñливане до прилагането Ñ. Данните ще бъдат добавени автоматично Ñлед като "
-"приложите първата Ñи заÑвка за Ñливане."
+msgid "The review stage shows the time from creating the merge request to merging it. The data will automatically be added after you merge your first merge request."
+msgstr "Етапът на преглед и одобрение показва времето от Ñъздаването на заÑвката за Ñливане до прилагането Ñ. Данните ще бъдат добавени автоматично Ñлед като приложите първата Ñи заÑвка за Ñливане."
-msgid ""
-"The staging stage shows the time between merging the MR and deploying code "
-"to the production environment. The data will be automatically added once you "
-"deploy to production for the first time."
-msgstr ""
-"Етапът на подготовка за издаване показва времето между прилагането на "
-"заÑвката за Ñливане и внедрÑването на кода в Ñредата на работещата крайна "
-"верÑиÑ. Данните ще бъдат добавени автоматично Ñлед като направите първото Ñи "
-"внедрÑване в крайната верÑиÑ."
+msgid "The staging stage shows the time between merging the MR and deploying code to the production environment. The data will be automatically added once you deploy to production for the first time."
+msgstr "Етапът на подготовка за издаване показва времето между прилагането на заÑвката за Ñливане и внедрÑването на кода в Ñредата на работещата крайна верÑиÑ. Данните ще бъдат добавени автоматично Ñлед като направите първото Ñи внедрÑване в крайната верÑиÑ."
-msgid ""
-"The testing stage shows the time GitLab CI takes to run every pipeline for "
-"the related merge request. The data will automatically be added after your "
-"first pipeline finishes running."
-msgstr ""
-"Етапът на теÑтване показва времето, което е нужно на „Gitlab CI“ да изпълни "
-"вÑÑка Ñхема от задачи за Ñвързаната заÑвка за Ñливане. Данните ще бъдат "
-"добавени автоматично Ñлед като приключи изпълнението на първата Ви Ñхема."
+msgid "The testing stage shows the time GitLab CI takes to run every pipeline for the related merge request. The data will automatically be added after your first pipeline finishes running."
+msgstr "Етапът на теÑтване показва времето, което е нужно на „Gitlab CI“ да изпълни вÑÑка Ñхема от задачи за Ñвързаната заÑвка за Ñливане. Данните ще бъдат добавени автоматично Ñлед като приключи изпълнението на първата Ви Ñхема."
msgid "The time taken by each data entry gathered by that stage."
msgstr "Времето, което отнема вÑеки Ð·Ð°Ð¿Ð¸Ñ Ð¾Ñ‚ данни за ÑÑŠÐ¾Ñ‚Ð²ÐµÑ‚Ð½Ð¸Ñ ÐµÑ‚Ð°Ð¿."
-msgid ""
-"The value lying at the midpoint of a series of observed values. E.g., "
-"between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 ="
-" 6."
-msgstr ""
-"СтойноÑтта, коÑто Ñе намира в Ñредата на поÑледователноÑтта от наблюдавани "
-"данни. Ðапример: медианата на 3, 5 и 9 е 5, а медианата на 3, 5, 7 и 8 е "
-"(5+7)/2 = 6."
+msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
+msgstr "СтойноÑтта, коÑто Ñе намира в Ñредата на поÑледователноÑтта от наблюдавани данни. Ðапример: медианата на 3, 5 и 9 е 5, а медианата на 3, 5, 7 и 8 е (5+7)/2 = 6."
-msgid ""
-"This means you can not push code until you create an empty repository or "
-"import existing one."
+msgid "There are problems accessing Git storage: "
msgstr ""
-"Това означава, че нÑма да можете да изпращате код, докато не Ñъздадете "
-"празно хранилище или не внеÑете ÑъщеÑтвуващо такова."
+
+msgid "This means you can not push code until you create an empty repository or import existing one."
+msgstr "Това означава, че нÑма да можете да изпращате код, докато не Ñъздадете празно хранилище или не внеÑете ÑъщеÑтвуващо такова."
msgid "Time before an issue gets scheduled"
msgstr "Време преди един проблем да бъде планиран за работа"
@@ -976,8 +1033,7 @@ msgid "Time before an issue starts implementation"
msgstr "Време преди работата по проблем да започне"
msgid "Time between merge request creation and merge/close"
-msgstr ""
-"Време между Ñъздаване на заÑвка за Ñливане и прилагането/отхвърлÑнето Ñ"
+msgstr "Време между Ñъздаване на заÑвка за Ñливане и прилагането/отхвърлÑнето Ñ"
msgid "Time until first merge request"
msgstr "Време преди първата заÑвка за Ñливане"
@@ -1136,6 +1192,9 @@ msgstr "Качване на файл"
msgid "UploadLink|click to upload"
msgstr "щракнете за качване"
+msgid "Use the following registration token during setup:"
+msgstr ""
+
msgid "Use your global notification setting"
msgstr "Използване на глобалната Ви наÑтройка за извеÑтиÑта"
@@ -1167,22 +1226,13 @@ msgid "You are going to remove %{group_name}. Removed groups CANNOT be restored!
msgstr "Ðа път Ñте да премахнете „%{group_name}“. Ðко Ñ Ð¿Ñ€ÐµÐ¼Ð°Ñ…Ð½ÐµÑ‚Ðµ, групата ÐЕ може да бъде възÑтановена! ÐÐИСТИÐРли иÑкате това?"
msgid "You are going to remove %{project_name_with_namespace}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
-msgstr "Ðа път Ñте да премахнете „%{project_name_with_namespace}“. Ðко го премахнете, той ÐЕ може да бъде възÑтановен!"
-"ÐÐИСТИÐРли иÑкате това?"
+msgstr "Ðа път Ñте да премахнете „%{project_name_with_namespace}“. Ðко го премахнете, той ÐЕ може да бъде възÑтановен!ÐÐИСТИÐРли иÑкате това?"
-msgid ""
-"You are going to remove the fork relationship to source project "
-"%{forked_from_project}. Are you ABSOLUTELY sure?"
-msgstr ""
-"Ðа път Ñте да премахнете връзката на разклонението към Ð¾Ñ€Ð¸Ð³Ð¸Ð½Ð°Ð»Ð½Ð¸Ñ Ð¿Ñ€Ð¾ÐµÐºÑ‚, "
-"„%{forked_from_project}“. ÐÐИСТИÐРли иÑкате това?"
+msgid "You are going to remove the fork relationship to source project %{forked_from_project}. Are you ABSOLUTELY sure?"
+msgstr "Ðа път Ñте да премахнете връзката на разклонението към Ð¾Ñ€Ð¸Ð³Ð¸Ð½Ð°Ð»Ð½Ð¸Ñ Ð¿Ñ€Ð¾ÐµÐºÑ‚, „%{forked_from_project}“. ÐÐИСТИÐРли иÑкате това?"
-msgid ""
-"You are going to transfer %{project_name_with_namespace} to another owner. "
-"Are you ABSOLUTELY sure?"
-msgstr ""
-"Ðа път Ñте да прехвърлите „%{project_name_with_namespace}“ към друг "
-"ÑобÑтвеник. ÐÐИСТИÐРли иÑкате това?"
+msgid "You are going to transfer %{project_name_with_namespace} to another owner. Are you ABSOLUTELY sure?"
+msgstr "Ðа път Ñте да прехвърлите „%{project_name_with_namespace}“ към друг ÑобÑтвеник. ÐÐИСТИÐРли иÑкате това?"
msgid "You can only add files when you are on a branch"
msgstr "Можете да добавÑте файлове Ñамо когато Ñе намирате в клон"
@@ -1202,31 +1252,20 @@ msgstr "ÐÑма да получавате никакви извеÑÑ‚Ð¸Ñ Ð¿Ð¾
msgid "You will only receive notifications for the events you choose"
msgstr "Ще получавате извеÑÑ‚Ð¸Ñ Ñамо за ÑъбитиÑта, за които желаете"
-msgid ""
-"You will only receive notifications for threads you have participated in"
+msgid "You will only receive notifications for threads you have participated in"
msgstr "Ще получавате извеÑÑ‚Ð¸Ñ Ñамо за нещата, в които учаÑтвате"
msgid "You will receive notifications for any activity"
msgstr "Ще получавате извеÑÑ‚Ð¸Ñ Ð·Ð° вÑÑка дейноÑÑ‚"
-msgid ""
-"You will receive notifications only for comments in which you were "
-"@mentioned"
+msgid "You will receive notifications only for comments in which you were @mentioned"
msgstr "Ще получавате извеÑÑ‚Ð¸Ñ Ñамо за коментари, в които Ви @Ñпоменават"
-msgid ""
-"You won't be able to pull or push project code via %{protocol} until you "
-"%{set_password_link} on your account"
-msgstr ""
-"ÐÑма да можете да изтеглÑте или изпращате код в проекта чрез %{protocol}, "
-"докато не %{set_password_link} за профила Ñи"
+msgid "You won't be able to pull or push project code via %{protocol} until you %{set_password_link} on your account"
+msgstr "ÐÑма да можете да изтеглÑте или изпращате код в проекта чрез %{protocol}, докато не %{set_password_link} за профила Ñи"
-msgid ""
-"You won't be able to pull or push project code via SSH until you "
-"%{add_ssh_key_link} to your profile"
-msgstr ""
-"ÐÑма да можете да изтеглÑте или изпращате код в проекта чрез SSH, докато не "
-"%{add_ssh_key_link} в профила Ñи"
+msgid "You won't be able to pull or push project code via SSH until you %{add_ssh_key_link} to your profile"
+msgstr "ÐÑма да можете да изтеглÑте или изпращате код в проекта чрез SSH, докато не %{add_ssh_key_link} в профила Ñи"
msgid "Your name"
msgstr "Вашето име"
@@ -1245,5 +1284,4 @@ msgstr "извеÑÑ‚Ð¸Ñ Ð¿Ð¾ е-поща"
msgid "parent"
msgid_plural "parents"
msgstr[0] "родител"
-msgstr[1] "родители"
-
+msgstr[1] "родители" \ No newline at end of file
diff --git a/locale/de/gitlab.po b/locale/de/gitlab.po
index ea864091b10..3cefb26d234 100644
--- a/locale/de/gitlab.po
+++ b/locale/de/gitlab.po
@@ -1,39 +1,321 @@
-# German translations for gitlab package.
-# Copyright (C) 2017 THE PACKAGE'S COPYRIGHT HOLDER
-# This file is distributed under the same license as the gitlab package.
-# FIRST AUTHOR <EMAIL@ADDRESS>, 2017.
-#
msgid ""
msgstr ""
-"Project-Id-Version: gitlab 1.0.0\n"
+"Project-Id-Version: gitlab-ee\n"
"Report-Msgid-Bugs-To: \n"
-"PO-Revision-Date: 2017-05-09 13:44+0200\n"
+"POT-Creation-Date: 2017-08-18 14:15+0530\n"
+"PO-Revision-Date: 2017-08-23 09:29-0400\n"
+"Last-Translator: gitlab <mbartlett+crowdin@gitlab.com>\n"
"Language-Team: German\n"
-"Language: de\n"
+"Language: de_DE\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"Plural-Forms: nplurals=2; plural=n != 1;\n"
-"Last-Translator: \n"
-"X-Generator: Poedit 2.0.1\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Generator: crowdin.com\n"
+"X-Crowdin-Project: gitlab-ee\n"
+"X-Crowdin-Language: de\n"
+"X-Crowdin-File: /master/locale/gitlab.pot\n"
+
+msgid "%d commit"
+msgid_plural "%d commits"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%s additional commit has been omitted to prevent performance issues."
+msgid_plural "%s additional commits have been omitted to prevent performance issues."
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{commit_author_link} committed %{commit_timeago}"
+msgstr ""
+
+msgid "%{number_of_failures} of %{maximum_failures} failures. GitLab will allow access on the next attempt."
+msgstr ""
+
+msgid "%{number_of_failures} of %{maximum_failures} failures. GitLab will block access for %{number_of_seconds} seconds."
+msgstr ""
+
+msgid "%{number_of_failures} of %{maximum_failures} failures. GitLab will not retry automatically. Reset storage information when the problem is resolved."
+msgstr ""
+
+msgid "%{storage_name}: failed storage access attempt on host:"
+msgid_plural "%{storage_name}: %{failed_attempts} failed storage access attempts:"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "(checkout the %{link} for information on how to install it)."
+msgstr ""
+
+msgid "1 pipeline"
+msgid_plural "%d pipelines"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "A collection of graphs regarding Continuous Integration"
+msgstr ""
+
+msgid "About auto deploy"
+msgstr ""
+
+msgid "Access to failing storages has been temporarily disabled to allow the mount to recover. Reset storage information after the issue has been resolved to allow access again."
+msgstr ""
+
+msgid "Active"
+msgstr ""
+
+msgid "Activity"
+msgstr ""
+
+msgid "Add Changelog"
+msgstr ""
+
+msgid "Add Contribution guide"
+msgstr ""
+
+msgid "Add License"
+msgstr ""
+
+msgid "Add an SSH key to your profile to pull or push via SSH."
+msgstr ""
+
+msgid "Add new directory"
+msgstr ""
+
+msgid "All"
+msgstr ""
+
+msgid "Archived project! Repository is read-only"
+msgstr ""
msgid "Are you sure you want to delete this pipeline schedule?"
msgstr ""
+msgid "Are you sure you want to discard your changes?"
+msgstr ""
+
+msgid "Are you sure you want to reset registration token?"
+msgstr ""
+
+msgid "Are you sure you want to reset the health check token?"
+msgstr ""
+
+msgid "Are you sure?"
+msgstr ""
+
+msgid "Attach a file by drag &amp; drop or %{upload_link}"
+msgstr ""
+
+msgid "Branch"
+msgid_plural "Branches"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
+msgstr ""
+
+msgid "BranchSwitcherPlaceholder|Search branches"
+msgstr ""
+
+msgid "BranchSwitcherTitle|Switch branch"
+msgstr ""
+
+msgid "Branches"
+msgstr ""
+
+msgid "Browse Directory"
+msgstr ""
+
+msgid "Browse File"
+msgstr ""
+
+msgid "Browse Files"
+msgstr ""
+
+msgid "Browse files"
+msgstr ""
+
msgid "ByAuthor|by"
msgstr "Von"
+msgid "CI configuration"
+msgstr ""
+
msgid "Cancel"
msgstr ""
+msgid "Cancel edit"
+msgstr ""
+
+msgid "ChangeTypeActionLabel|Pick into branch"
+msgstr ""
+
+msgid "ChangeTypeActionLabel|Revert in branch"
+msgstr ""
+
+msgid "ChangeTypeAction|Cherry-pick"
+msgstr ""
+
+msgid "ChangeTypeAction|Revert"
+msgstr ""
+
+msgid "Changelog"
+msgstr ""
+
+msgid "Charts"
+msgstr ""
+
+msgid "Cherry-pick this commit"
+msgstr ""
+
+msgid "Cherry-pick this merge request"
+msgstr ""
+
+msgid "CiStatusLabel|canceled"
+msgstr ""
+
+msgid "CiStatusLabel|created"
+msgstr ""
+
+msgid "CiStatusLabel|failed"
+msgstr ""
+
+msgid "CiStatusLabel|manual action"
+msgstr ""
+
+msgid "CiStatusLabel|passed"
+msgstr ""
+
+msgid "CiStatusLabel|passed with warnings"
+msgstr ""
+
+msgid "CiStatusLabel|pending"
+msgstr ""
+
+msgid "CiStatusLabel|skipped"
+msgstr ""
+
+msgid "CiStatusLabel|waiting for manual action"
+msgstr ""
+
+msgid "CiStatusText|blocked"
+msgstr ""
+
+msgid "CiStatusText|canceled"
+msgstr ""
+
+msgid "CiStatusText|created"
+msgstr ""
+
+msgid "CiStatusText|failed"
+msgstr ""
+
+msgid "CiStatusText|manual"
+msgstr ""
+
+msgid "CiStatusText|passed"
+msgstr ""
+
+msgid "CiStatusText|pending"
+msgstr ""
+
+msgid "CiStatusText|skipped"
+msgstr ""
+
+msgid "CiStatus|running"
+msgstr ""
+
+msgid "Comments"
+msgstr ""
+
msgid "Commit"
msgid_plural "Commits"
-msgstr[0] "Commit"
-msgstr[1] "Commits"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Commit duration in minutes for last 30 commits"
+msgstr ""
+
+msgid "Commit message"
+msgstr ""
+
+msgid "CommitBoxTitle|Commit"
+msgstr ""
+
+msgid "CommitMessage|Add %{file_name}"
+msgstr ""
+
+msgid "Commits"
+msgstr ""
+
+msgid "Commits feed"
+msgstr ""
+
+msgid "Commits|History"
+msgstr ""
+
+msgid "Committed by"
+msgstr ""
+
+msgid "Compare"
+msgstr ""
+
+msgid "Contribution guide"
+msgstr ""
+
+msgid "Contributors"
+msgstr ""
+
+msgid "Copy URL to clipboard"
+msgstr ""
+
+msgid "Copy commit SHA to clipboard"
+msgstr ""
+
+msgid "Create New Directory"
+msgstr ""
+
+msgid "Create a new branch"
+msgstr ""
+
+msgid "Create a personal access token on your account to pull or push via %{protocol}."
+msgstr ""
+
+msgid "Create directory"
+msgstr ""
+
+msgid "Create empty bare repository"
+msgstr ""
+
+msgid "Create merge request"
+msgstr ""
+
+msgid "Create new..."
+msgstr ""
+
+msgid "CreateNewFork|Fork"
+msgstr ""
+
+msgid "CreateTag|Tag"
+msgstr ""
+
+msgid "CreateTokenToCloneLink|create a personal access token"
+msgstr ""
msgid "Cron Timezone"
msgstr ""
+msgid "Cron syntax"
+msgstr ""
+
+msgid "Custom notification events"
+msgstr ""
+
+msgid "Custom notification levels are the same as participating levels. With custom notification levels you will also receive notifications for select events. To find out more, check out %{notification_link}."
+msgstr ""
+
+msgid "Cycle Analytics"
+msgstr ""
+
msgid "Cycle Analytics gives an overview of how much time it takes to go from idea to production in your project."
msgstr "Cycle Analytics liefern einen Überblick darüber, wie viel Zeit in Ihrem Projekt von einer Idee bis zum Produktivdeployment vergeht."
@@ -58,6 +340,9 @@ msgstr "Staging"
msgid "CycleAnalyticsStage|Test"
msgstr "Test"
+msgid "Define a custom pattern with cron syntax"
+msgstr ""
+
msgid "Delete"
msgstr ""
@@ -69,19 +354,94 @@ msgstr[1] "Deployments"
msgid "Description"
msgstr ""
+msgid "Details"
+msgstr ""
+
+msgid "Directory name"
+msgstr ""
+
+msgid "Discard changes"
+msgstr ""
+
+msgid "Don't show again"
+msgstr ""
+
+msgid "Download"
+msgstr ""
+
+msgid "Download tar"
+msgstr ""
+
+msgid "Download tar.bz2"
+msgstr ""
+
+msgid "Download tar.gz"
+msgstr ""
+
+msgid "Download zip"
+msgstr ""
+
+msgid "DownloadArtifacts|Download"
+msgstr ""
+
+msgid "DownloadCommit|Email Patches"
+msgstr ""
+
+msgid "DownloadCommit|Plain Diff"
+msgstr ""
+
+msgid "DownloadSource|Download"
+msgstr ""
+
msgid "Edit"
msgstr ""
msgid "Edit Pipeline Schedule %{id}"
msgstr ""
+msgid "EventFilterBy|Filter by all"
+msgstr ""
+
+msgid "EventFilterBy|Filter by comments"
+msgstr ""
+
+msgid "EventFilterBy|Filter by issue events"
+msgstr ""
+
+msgid "EventFilterBy|Filter by merge events"
+msgstr ""
+
+msgid "EventFilterBy|Filter by push events"
+msgstr ""
+
+msgid "EventFilterBy|Filter by team"
+msgstr ""
+
+msgid "Every day (at 4:00am)"
+msgstr ""
+
+msgid "Every month (on the 1st at 4:00am)"
+msgstr ""
+
+msgid "Every week (Sundays at 4:00am)"
+msgstr ""
+
msgid "Failed to change the owner"
msgstr ""
msgid "Failed to remove the pipeline schedule"
msgstr ""
-msgid "Filter"
+msgid "Files"
+msgstr ""
+
+msgid "Filter by commit message"
+msgstr ""
+
+msgid "Find by path"
+msgstr ""
+
+msgid "Find file"
msgstr ""
msgid "FirstPushedBy|First"
@@ -90,18 +450,86 @@ msgstr "Erster"
msgid "FirstPushedBy|pushed by"
msgstr "gepusht von"
+msgid "Fork"
+msgid_plural "Forks"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ForkedFromProjectPath|Forked from"
+msgstr ""
+
msgid "From issue creation until deploy to production"
msgstr "Vom Anlegen des Issues bis zum Produktivdeployment"
msgid "From merge request merge until deploy to production"
msgstr "Vom Merge Request bis zum Produktivdeployment"
+msgid "Git storage health information has been reset"
+msgstr ""
+
+msgid "GitLab Runner section"
+msgstr ""
+
+msgid "Go to your fork"
+msgstr ""
+
+msgid "GoToYourFork|Fork"
+msgstr ""
+
+msgid "Health Check"
+msgstr ""
+
+msgid "Health information can be retrieved from the following endpoints. More information is available"
+msgstr ""
+
+msgid "HealthCheck|Access token is"
+msgstr ""
+
+msgid "HealthCheck|Healthy"
+msgstr ""
+
+msgid "HealthCheck|No Health Problems Detected"
+msgstr ""
+
+msgid "HealthCheck|Unhealthy"
+msgstr ""
+
+msgid "Home"
+msgstr ""
+
+msgid "Housekeeping successfully started"
+msgstr ""
+
+msgid "Import repository"
+msgstr ""
+
+msgid "Install a Runner compatible with GitLab CI"
+msgstr ""
+
msgid "Interval Pattern"
msgstr ""
msgid "Introducing Cycle Analytics"
msgstr "Was sind Cycle Analytics?"
+msgid "Issue events"
+msgstr ""
+
+msgid "Jobs for last month"
+msgstr ""
+
+msgid "Jobs for last week"
+msgstr ""
+
+msgid "Jobs for last year"
+msgstr ""
+
+msgid "LFSStatus|Disabled"
+msgstr ""
+
+msgid "LFSStatus|Enabled"
+msgstr ""
+
msgid "Last %d day"
msgid_plural "Last %d days"
msgstr[0] "Letzter %d Tag"
@@ -110,13 +538,46 @@ msgstr[1] "Letzten %d Tage"
msgid "Last Pipeline"
msgstr ""
+msgid "Last Update"
+msgstr ""
+
+msgid "Last commit"
+msgstr ""
+
+msgid "LastPushEvent|You pushed to"
+msgstr ""
+
+msgid "LastPushEvent|at"
+msgstr ""
+
+msgid "Learn more in the"
+msgstr ""
+
+msgid "Learn more in the|pipeline schedules documentation"
+msgstr ""
+
+msgid "Leave group"
+msgstr ""
+
+msgid "Leave project"
+msgstr ""
+
msgid "Limited to showing %d event at most"
msgid_plural "Limited to showing %d events at most"
msgstr[0] "Eingeschränkt auf maximal %d Ereignis"
msgstr[1] "Eingeschränkt auf maximal %d Ereignisse"
msgid "Median"
-msgstr "Median"
+msgstr ""
+
+msgid "Merge events"
+msgstr ""
+
+msgid "MissingSSHKeyWarningLink|add an SSH key"
+msgstr ""
+
+msgid "More information is available|here"
+msgstr ""
msgid "New Issue"
msgid_plural "New Issues"
@@ -126,6 +587,33 @@ msgstr[1] "Neue Issues"
msgid "New Pipeline Schedule"
msgstr ""
+msgid "New branch"
+msgstr ""
+
+msgid "New directory"
+msgstr ""
+
+msgid "New file"
+msgstr ""
+
+msgid "New issue"
+msgstr ""
+
+msgid "New merge request"
+msgstr ""
+
+msgid "New schedule"
+msgstr ""
+
+msgid "New snippet"
+msgstr ""
+
+msgid "New tag"
+msgstr ""
+
+msgid "No repository"
+msgstr ""
+
msgid "No schedules"
msgstr ""
@@ -135,12 +623,75 @@ msgstr "Nicht verfügbar"
msgid "Not enough data"
msgstr "Nicht genügend Daten"
+msgid "Notification events"
+msgstr ""
+
+msgid "NotificationEvent|Close issue"
+msgstr ""
+
+msgid "NotificationEvent|Close merge request"
+msgstr ""
+
+msgid "NotificationEvent|Failed pipeline"
+msgstr ""
+
+msgid "NotificationEvent|Merge merge request"
+msgstr ""
+
+msgid "NotificationEvent|New issue"
+msgstr ""
+
+msgid "NotificationEvent|New merge request"
+msgstr ""
+
+msgid "NotificationEvent|New note"
+msgstr ""
+
+msgid "NotificationEvent|Reassign issue"
+msgstr ""
+
+msgid "NotificationEvent|Reassign merge request"
+msgstr ""
+
+msgid "NotificationEvent|Reopen issue"
+msgstr ""
+
+msgid "NotificationEvent|Successful pipeline"
+msgstr ""
+
+msgid "NotificationLevel|Custom"
+msgstr ""
+
+msgid "NotificationLevel|Disabled"
+msgstr ""
+
+msgid "NotificationLevel|Global"
+msgstr ""
+
+msgid "NotificationLevel|On mention"
+msgstr ""
+
+msgid "NotificationLevel|Participate"
+msgstr ""
+
+msgid "NotificationLevel|Watch"
+msgstr ""
+
+msgid "OfSearchInADropdown|Filter"
+msgstr ""
+
msgid "OpenedNDaysAgo|Opened"
msgstr "Erstellt"
+msgid "Options"
+msgstr ""
+
msgid "Owner"
msgstr ""
+msgid "Pipeline"
+msgstr ""
+
msgid "Pipeline Health"
msgstr "Pipeline Kennzahlen"
@@ -150,6 +701,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 ""
@@ -162,6 +728,12 @@ msgstr ""
msgid "PipelineSchedules|Inactive"
msgstr ""
+msgid "PipelineSchedules|Input variable key"
+msgstr ""
+
+msgid "PipelineSchedules|Input variable value"
+msgstr ""
+
msgid "PipelineSchedules|Next Run"
msgstr ""
@@ -171,18 +743,114 @@ msgstr ""
msgid "PipelineSchedules|Provide a short description for this pipeline"
msgstr ""
+msgid "PipelineSchedules|Remove variable row"
+msgstr ""
+
msgid "PipelineSchedules|Take ownership"
msgstr ""
msgid "PipelineSchedules|Target"
msgstr ""
+msgid "PipelineSchedules|Variables"
+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 ""
+
+msgid "Pipeline|with stages"
+msgstr ""
+
+msgid "Project"
+msgstr ""
+
+msgid "Project '%{project_name}' queued for deletion."
+msgstr ""
+
+msgid "Project '%{project_name}' was successfully created."
+msgstr ""
+
+msgid "Project '%{project_name}' was successfully updated."
+msgstr ""
+
+msgid "Project '%{project_name}' will be deleted."
+msgstr ""
+
+msgid "Project access must be granted explicitly to each user."
+msgstr ""
+
+msgid "Project details"
+msgstr ""
+
+msgid "Project export could not be deleted."
+msgstr ""
+
+msgid "Project export has been deleted."
+msgstr ""
+
+msgid "Project export link has expired. Please generate a new export from your project settings."
+msgstr ""
+
+msgid "Project export started. A download link will be sent by email."
+msgstr ""
+
+msgid "Project home"
+msgstr ""
+
+msgid "ProjectActivityRSS|Subscribe"
+msgstr ""
+
+msgid "ProjectFeature|Disabled"
+msgstr ""
+
+msgid "ProjectFeature|Everyone with access"
+msgstr ""
+
+msgid "ProjectFeature|Only team members"
+msgstr ""
+
+msgid "ProjectFileTree|Name"
+msgstr ""
+
+msgid "ProjectLastActivity|Never"
+msgstr ""
+
msgid "ProjectLifecycle|Stage"
msgstr "Phase"
+msgid "ProjectNetworkGraph|Graph"
+msgstr ""
+
+msgid "Push events"
+msgstr ""
+
msgid "Read more"
msgstr "Mehr"
+msgid "Readme"
+msgstr ""
+
+msgid "RefSwitcher|Branches"
+msgstr ""
+
+msgid "RefSwitcher|Tags"
+msgstr ""
+
msgid "Related Commits"
msgstr "Zugehörige Commits"
@@ -201,44 +869,142 @@ msgstr "Zugehörige Merge Requests"
msgid "Related Merged Requests"
msgstr "Zugehörige abgeschlossene Merge Requests"
+msgid "Remind later"
+msgstr ""
+
+msgid "Remove project"
+msgstr ""
+
+msgid "Repository"
+msgstr ""
+
+msgid "Request Access"
+msgstr ""
+
+msgid "Reset git storage health information"
+msgstr ""
+
+msgid "Reset health check access token"
+msgstr ""
+
+msgid "Reset runners registration token"
+msgstr ""
+
+msgid "Revert this commit"
+msgstr ""
+
+msgid "Revert this merge request"
+msgstr ""
+
msgid "Save pipeline schedule"
msgstr ""
msgid "Schedule a new pipeline"
msgstr ""
+msgid "Scheduling Pipelines"
+msgstr ""
+
+msgid "Search branches and tags"
+msgstr ""
+
+msgid "Select Archive Format"
+msgstr ""
+
msgid "Select a timezone"
msgstr ""
+msgid "Select existing branch"
+msgstr ""
+
msgid "Select target branch"
msgstr ""
+msgid "Set a password on your account to pull or push via %{protocol}."
+msgstr ""
+
+msgid "Set up CI"
+msgstr ""
+
+msgid "Set up Koding"
+msgstr ""
+
+msgid "Set up auto deploy"
+msgstr ""
+
+msgid "SetPasswordToCloneLink|set a password"
+msgstr ""
+
msgid "Showing %d event"
msgid_plural "Showing %d events"
msgstr[0] "Zeige %d Ereignis"
msgstr[1] "Zeige %d Ereignisse"
+msgid "Source code"
+msgstr ""
+
+msgid "Specify the following URL during the Runner setup:"
+msgstr ""
+
+msgid "StarProject|Star"
+msgstr ""
+
+msgid "Start a %{new_merge_request} with these changes"
+msgstr ""
+
+msgid "Start the Runner!"
+msgstr ""
+
+msgid "Switch branch/tag"
+msgstr ""
+
+msgid "Tag"
+msgid_plural "Tags"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Tags"
+msgstr ""
+
msgid "Target Branch"
msgstr ""
+msgid "Team"
+msgstr ""
+
msgid "The coding stage shows the time from the first commit to creating the merge request. The data will automatically be added here once you create your first merge request."
msgstr "Die Code-Phase stellt die Zeit vom ersten Commit bis zum Erstellen eines Merge Requests dar. Sobald Sie Ihren ersten Merge Request anlegen, werden dessen Daten automatisch ergänzt."
msgid "The collection of events added to the data gathered for that stage."
msgstr "Ereignisse, die für diese Phase ausgewertet wurden."
+msgid "The fork relationship has been removed."
+msgstr ""
+
msgid "The issue stage shows the time it takes from creating an issue to assigning 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 "Die Issue-Phase stellt die Zeit vom Anlegen eines Issues bis zum Zuweisen eines Meilensteins oder Hinzufügen zum Issue Board dar. Erstellen Sie einen Issue, damit dessen Daten hier erscheinen."
msgid "The phase of the development lifecycle."
msgstr "Die Phase im Entwicklungsprozess."
+msgid "The pipelines schedule runs pipelines in the future, repeatedly, for specific branches or tags. Those scheduled pipelines will inherit limited project access based on their associated user."
+msgstr ""
+
msgid "The planning stage shows the time from the previous step to pushing your first commit. This time will be added automatically once you push your first commit."
msgstr "Die Planungsphase stellt die Zeit von der vorherigen Phase bis zum Pushen des ersten Commits dar. Sobald Sie den ersten Commit pushen, werden dessen Daten hier erscheinen."
msgid "The production stage shows the total time it takes between creating an issue and deploying the code to production. The data will be automatically added once you have completed the full idea to production cycle."
msgstr "Die Produktiv-Phase stellt die Gesamtzeit vom Anlegen eines Issues bis zum Deployment auf dem Produktivsystem dar. Sobald Sie den vollständigen Entwicklungszyklus von einer Idee bis zum Produktivdeployment durchlaufen haben, erscheinen die zugehörigen Daten hier."
+msgid "The project can be accessed by any logged in user."
+msgstr ""
+
+msgid "The project can be accessed without any authentication."
+msgstr ""
+
+msgid "The repository for this project does not exist."
+msgstr ""
+
msgid "The review stage shows the time from creating the merge request to merging it. The data will automatically be added after you merge your first merge request."
msgstr "Die Review-Phase stellt die Zeit vom Anlegen eines Merge Requests bis zum Mergen dar. Sobald Sie Ihren ersten Merge Request abschließen, werden dessen Daten hier automatisch angezeigt."
@@ -254,6 +1020,12 @@ msgstr "Zeit die für das jeweilige Ereignis in der Phase ermittelt wurde."
msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
msgstr "Der mittlere aller erfassten Werte. Zum Beispiel ist für 3, 5, 9 der Median 5. Bei 3, 5, 7, 8 ist der Median (5+7)/2 = 6."
+msgid "There are problems accessing Git storage: "
+msgstr ""
+
+msgid "This means you can not push code until you create an empty repository or import existing one."
+msgstr ""
+
msgid "Time before an issue gets scheduled"
msgstr "Zeit bis ein Issue geplant wird"
@@ -266,6 +1038,129 @@ msgstr "Zeit zwischen Anlegen und Mergen/Schließen eines Merge Requests"
msgid "Time until first merge request"
msgstr "Zeit bis zum ersten Merge Request"
+msgid "Timeago|%s days ago"
+msgstr ""
+
+msgid "Timeago|%s days remaining"
+msgstr ""
+
+msgid "Timeago|%s hours remaining"
+msgstr ""
+
+msgid "Timeago|%s minutes ago"
+msgstr ""
+
+msgid "Timeago|%s minutes remaining"
+msgstr ""
+
+msgid "Timeago|%s months ago"
+msgstr ""
+
+msgid "Timeago|%s months remaining"
+msgstr ""
+
+msgid "Timeago|%s seconds remaining"
+msgstr ""
+
+msgid "Timeago|%s weeks ago"
+msgstr ""
+
+msgid "Timeago|%s weeks remaining"
+msgstr ""
+
+msgid "Timeago|%s years ago"
+msgstr ""
+
+msgid "Timeago|%s years remaining"
+msgstr ""
+
+msgid "Timeago|1 day remaining"
+msgstr ""
+
+msgid "Timeago|1 hour remaining"
+msgstr ""
+
+msgid "Timeago|1 minute remaining"
+msgstr ""
+
+msgid "Timeago|1 month remaining"
+msgstr ""
+
+msgid "Timeago|1 week remaining"
+msgstr ""
+
+msgid "Timeago|1 year remaining"
+msgstr ""
+
+msgid "Timeago|Past due"
+msgstr ""
+
+msgid "Timeago|a day ago"
+msgstr ""
+
+msgid "Timeago|a month ago"
+msgstr ""
+
+msgid "Timeago|a week ago"
+msgstr ""
+
+msgid "Timeago|a while"
+msgstr ""
+
+msgid "Timeago|a year ago"
+msgstr ""
+
+msgid "Timeago|about %s hours ago"
+msgstr ""
+
+msgid "Timeago|about a minute ago"
+msgstr ""
+
+msgid "Timeago|about an hour ago"
+msgstr ""
+
+msgid "Timeago|in %s days"
+msgstr ""
+
+msgid "Timeago|in %s hours"
+msgstr ""
+
+msgid "Timeago|in %s minutes"
+msgstr ""
+
+msgid "Timeago|in %s months"
+msgstr ""
+
+msgid "Timeago|in %s seconds"
+msgstr ""
+
+msgid "Timeago|in %s weeks"
+msgstr ""
+
+msgid "Timeago|in %s years"
+msgstr ""
+
+msgid "Timeago|in 1 day"
+msgstr ""
+
+msgid "Timeago|in 1 hour"
+msgstr ""
+
+msgid "Timeago|in 1 minute"
+msgstr ""
+
+msgid "Timeago|in 1 month"
+msgstr ""
+
+msgid "Timeago|in 1 week"
+msgstr ""
+
+msgid "Timeago|in 1 year"
+msgstr ""
+
+msgid "Timeago|less than a minute ago"
+msgstr ""
+
msgid "Time|hr"
msgid_plural "Time|hrs"
msgstr[0] "h"
@@ -285,19 +1180,108 @@ msgstr "Gesamtzeit"
msgid "Total test time for all commits/merges"
msgstr "Gesamte Testlaufzeit für alle Commits/Merges"
+msgid "Unstar"
+msgstr ""
+
+msgid "Upload New File"
+msgstr ""
+
+msgid "Upload file"
+msgstr ""
+
+msgid "UploadLink|click to upload"
+msgstr ""
+
+msgid "Use the following registration token during setup:"
+msgstr ""
+
+msgid "Use your global notification setting"
+msgstr ""
+
+msgid "View open merge request"
+msgstr ""
+
+msgid "VisibilityLevel|Internal"
+msgstr ""
+
+msgid "VisibilityLevel|Private"
+msgstr ""
+
+msgid "VisibilityLevel|Public"
+msgstr ""
+
+msgid "VisibilityLevel|Unknown"
+msgstr ""
+
msgid "Want to see the data? Please ask an administrator for access."
msgstr "Um diese Daten einsehen zu können, wenden Sie sich bitte an Ihren Administrator."
msgid "We don't have enough data to show this stage."
msgstr "Es liegen nicht genügend Daten vor, um diese Phase anzuzeigen."
+msgid "Withdraw Access Request"
+msgstr ""
+
+msgid "You are going to remove %{group_name}. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
+msgstr ""
+
+msgid "You are going to remove %{project_name_with_namespace}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
+msgstr ""
+
+msgid "You are going to remove the fork relationship to source project %{forked_from_project}. Are you ABSOLUTELY sure?"
+msgstr ""
+
+msgid "You are going to transfer %{project_name_with_namespace} to another owner. Are you ABSOLUTELY sure?"
+msgstr ""
+
+msgid "You can only add files when you are on a branch"
+msgstr ""
+
msgid "You have reached your project limit"
msgstr ""
+msgid "You must sign in to star a project"
+msgstr ""
+
msgid "You need permission."
msgstr "Sie benötigen Zugriffsrechte."
+msgid "You will not get any notifications via email"
+msgstr ""
+
+msgid "You will only receive notifications for the events you choose"
+msgstr ""
+
+msgid "You will only receive notifications for threads you have participated in"
+msgstr ""
+
+msgid "You will receive notifications for any activity"
+msgstr ""
+
+msgid "You will receive notifications only for comments in which you were @mentioned"
+msgstr ""
+
+msgid "You won't be able to pull or push project code via %{protocol} until you %{set_password_link} on your account"
+msgstr ""
+
+msgid "You won't be able to pull or push project code via SSH until you %{add_ssh_key_link} to your profile"
+msgstr ""
+
+msgid "Your name"
+msgstr ""
+
msgid "day"
msgid_plural "days"
msgstr[0] "Tag"
msgstr[1] "Tage"
+
+msgid "new merge request"
+msgstr ""
+
+msgid "notification emails"
+msgstr ""
+
+msgid "parent"
+msgid_plural "parents"
+msgstr[0] ""
+msgstr[1] "" \ No newline at end of file
diff --git a/locale/eo/gitlab.po b/locale/eo/gitlab.po
index 94ae131186b..4617de25a7c 100644
--- a/locale/eo/gitlab.po
+++ b/locale/eo/gitlab.po
@@ -1,34 +1,51 @@
-# Huang Tao <htve@outlook.com>, 2017. #zanata
-# Lyubomir Vasilev <lyubomirv@abv.bg>, 2017. #zanata
msgid ""
msgstr ""
-"Project-Id-Version: gitlab 1.0.0\n"
+"Project-Id-Version: gitlab-ee\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2017-07-13 12:07-0500\n"
+"POT-Creation-Date: 2017-08-18 14:15+0530\n"
+"PO-Revision-Date: 2017-08-23 09:53-0400\n"
+"Last-Translator: gitlab <mbartlett+crowdin@gitlab.com>\n"
+"Language-Team: Esperanto\n"
+"Language: eo_UY\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"PO-Revision-Date: 2017-08-03 04:44-0400\n"
-"Last-Translator: Lyubomir Vasilev <lyubomirv@abv.bg>\n"
-"Language-Team: Esperanto (https://translate.zanata.org/project/view/GitLab)\n"
-"Language: eo\n"
-"X-Generator: Zanata 3.9.6\n"
-"Plural-Forms: nplurals=2; plural=(n != 1)\n"
-
-msgid "%s additional commit has been omitted to prevent performance issues."
-msgid_plural ""
-"%s additional commits have been omitted to prevent performance issues."
-msgstr[0] "%s enmetado estis transsaltita, por ne troÅarÄi la sistemon."
-msgstr[1] "%s enmetadoj estis transsaltitaj, por ne troÅarÄi la sistemon."
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Generator: crowdin.com\n"
+"X-Crowdin-Project: gitlab-ee\n"
+"X-Crowdin-Language: eo\n"
+"X-Crowdin-File: /master/locale/gitlab.pot\n"
msgid "%d commit"
msgid_plural "%d commits"
msgstr[0] "%d enmetado"
msgstr[1] "%d enmetadoj"
+msgid "%s additional commit has been omitted to prevent performance issues."
+msgid_plural "%s additional commits have been omitted to prevent performance issues."
+msgstr[0] "%s enmetado estis transsaltita, por ne troÅarÄi la sistemon."
+msgstr[1] "%s enmetadoj estis transsaltitaj, por ne troÅarÄi la sistemon."
+
msgid "%{commit_author_link} committed %{commit_timeago}"
msgstr "%{commit_author_link} enmetis %{commit_timeago}"
+msgid "%{number_of_failures} of %{maximum_failures} failures. GitLab will allow access on the next attempt."
+msgstr ""
+
+msgid "%{number_of_failures} of %{maximum_failures} failures. GitLab will block access for %{number_of_seconds} seconds."
+msgstr ""
+
+msgid "%{number_of_failures} of %{maximum_failures} failures. GitLab will not retry automatically. Reset storage information when the problem is resolved."
+msgstr ""
+
+msgid "%{storage_name}: failed storage access attempt on host:"
+msgid_plural "%{storage_name}: %{failed_attempts} failed storage access attempts:"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "(checkout the %{link} for information on how to install it)."
+msgstr ""
+
msgid "1 pipeline"
msgid_plural "%d pipelines"
msgstr[0] "1 ĉenstablo"
@@ -40,6 +57,9 @@ msgstr "Aro da diagramoj pri la seninterrompa integrado"
msgid "About auto deploy"
msgstr "Pri la aÅ­tomata disponigado"
+msgid "Access to failing storages has been temporarily disabled to allow the mount to recover. Reset storage information after the issue has been resolved to allow access again."
+msgstr ""
+
msgid "Active"
msgstr "Aktiva"
@@ -56,19 +76,32 @@ msgid "Add License"
msgstr "Aldoni rajtigilon"
msgid "Add an SSH key to your profile to pull or push via SSH."
-msgstr ""
-"Aldonu SSH-Ålosilon al via profilo por ebligi al vi eltiri kaj alpuÅi per "
-"SSH."
+msgstr "Aldonu SSH-Ålosilon al via profilo por ebligi al vi eltiri kaj alpuÅi per SSH."
msgid "Add new directory"
msgstr "Aldoni novan dosierujon"
+msgid "All"
+msgstr ""
+
msgid "Archived project! Repository is read-only"
msgstr "Arkivita projekto! La deponejo permesas nur legadon"
msgid "Are you sure you want to delete this pipeline schedule?"
msgstr "Ĉu vi certe volas forigi ĉi tiun ĉenstablan planon?"
+msgid "Are you sure you want to discard your changes?"
+msgstr ""
+
+msgid "Are you sure you want to reset registration token?"
+msgstr ""
+
+msgid "Are you sure you want to reset the health check token?"
+msgstr ""
+
+msgid "Are you sure?"
+msgstr ""
+
msgid "Attach a file by drag &amp; drop or %{upload_link}"
msgstr "Alkroĉu dosieron per Åovmetado aÅ­ %{upload_link}"
@@ -77,14 +110,8 @@ msgid_plural "Branches"
msgstr[0] "Branĉo"
msgstr[1] "Branĉoj"
-msgid ""
-"Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, "
-"choose a GitLab CI Yaml template and commit your changes. "
-"%{link_to_autodeploy_doc}"
-msgstr ""
-"La branĉo <strong>%{branch_name}</strong> estis kreita. Por agordi aŭtomatan "
-"disponigadon, bonvolu elekti Yaml-Åablonon por GitLab CI kaj enmeti viajn "
-"ÅanÄojn. %{link_to_autodeploy_doc}"
+msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
+msgstr "La branĉo <strong>%{branch_name}</strong> estis kreita. Por agordi aÅ­tomatan disponigadon, bonvolu elekti Yaml-Åablonon por GitLab CI kaj enmeti viajn ÅanÄojn. %{link_to_autodeploy_doc}"
msgid "BranchSwitcherPlaceholder|Search branches"
msgstr "Serĉu branĉon"
@@ -116,6 +143,9 @@ msgstr "Agordoj de seninterrompa integrado"
msgid "Cancel"
msgstr "Nuligi"
+msgid "Cancel edit"
+msgstr ""
+
msgid "ChangeTypeActionLabel|Pick into branch"
msgstr "Elekti en branĉon"
@@ -194,6 +224,9 @@ msgstr "transsaltita"
msgid "CiStatus|running"
msgstr "plenumiÄanta"
+msgid "Comments"
+msgstr ""
+
msgid "Commit"
msgid_plural "Commits"
msgstr[0] "Enmetado"
@@ -241,12 +274,11 @@ 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}."
+msgid "Create a new branch"
msgstr ""
-"Kreu propran atingoĵetonon en via konto por ebligi al vi eltiri kaj alpuÅi "
-"per %{protocol}."
+
+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"
@@ -278,24 +310,14 @@ msgstr "La sintakso de Cron"
msgid "Custom notification events"
msgstr "Propraj sciigaj eventoj"
-msgid ""
-"Custom notification levels are the same as participating levels. With custom "
-"notification levels you will also receive notifications for select events. "
-"To find out more, check out %{notification_link}."
-msgstr ""
-"La propraj sciigaj niveloj estas la samaj kiel la niveloj de partoprenado. "
-"Uzante la proprajn sciigajn nivelojn, vi ricevos ankaÅ­ sciigojn por "
-"elektitaj de vi eventoj. Por lerni pli, bonvolu vidi %{notification_link}."
+msgid "Custom notification levels are the same as participating levels. With custom notification levels you will also receive notifications for select events. To find out more, check out %{notification_link}."
+msgstr "La propraj sciigaj niveloj estas la samaj kiel la niveloj de partoprenado. Uzante la proprajn sciigajn nivelojn, vi ricevos ankaÅ­ sciigojn por elektitaj de vi eventoj. Por lerni pli, bonvolu vidi %{notification_link}."
msgid "Cycle Analytics"
msgstr "Cikla analizo"
-msgid ""
-"Cycle Analytics gives an overview of how much time it takes to go from idea "
-"to production in your project."
-msgstr ""
-"La cikla analizo esploras kiom da tempo necesas por disvolvi ideon Äis Äi "
-"fariÄos realaĵo."
+msgid "Cycle Analytics gives an overview of how much time it takes to go from idea to production in your project."
+msgstr "La cikla analizo esploras kiom da tempo necesas por disvolvi ideon Äis Äi fariÄos realaĵo."
msgid "CycleAnalyticsStage|Code"
msgstr "Programado"
@@ -332,9 +354,15 @@ msgstr[1] "Disponigadoj"
msgid "Description"
msgstr "Priskribo"
+msgid "Details"
+msgstr ""
+
msgid "Directory name"
msgstr "Nomo de dosierujo"
+msgid "Discard changes"
+msgstr ""
+
msgid "Don't show again"
msgstr "Ne montru denove"
@@ -371,6 +399,24 @@ msgstr "Redakti"
msgid "Edit Pipeline Schedule %{id}"
msgstr "Redakti ĉenstablan planon %{id}"
+msgid "EventFilterBy|Filter by all"
+msgstr ""
+
+msgid "EventFilterBy|Filter by comments"
+msgstr ""
+
+msgid "EventFilterBy|Filter by issue events"
+msgstr ""
+
+msgid "EventFilterBy|Filter by merge events"
+msgstr ""
+
+msgid "EventFilterBy|Filter by push events"
+msgstr ""
+
+msgid "EventFilterBy|Filter by team"
+msgstr ""
+
msgid "Every day (at 4:00am)"
msgstr "Ĉiutage (je 4:00)"
@@ -416,9 +462,13 @@ msgid "From issue creation until deploy to production"
msgstr "De la kreado de la problemo Äis la disponigado en la publika versio"
msgid "From merge request merge until deploy to production"
+msgstr "De la kunfandado de la peto pri kunfando Äis la disponigado en la publika versio"
+
+msgid "Git storage health information has been reset"
+msgstr ""
+
+msgid "GitLab Runner section"
msgstr ""
-"De la kunfandado de la peto pri kunfando Äis la disponigado en la publika "
-"versio"
msgid "Go to your fork"
msgstr "Al via disbranĉigo"
@@ -426,6 +476,24 @@ msgstr "Al via disbranĉigo"
msgid "GoToYourFork|Fork"
msgstr "Disbranĉigo"
+msgid "Health Check"
+msgstr ""
+
+msgid "Health information can be retrieved from the following endpoints. More information is available"
+msgstr ""
+
+msgid "HealthCheck|Access token is"
+msgstr ""
+
+msgid "HealthCheck|Healthy"
+msgstr ""
+
+msgid "HealthCheck|No Health Problems Detected"
+msgstr ""
+
+msgid "HealthCheck|Unhealthy"
+msgstr ""
+
msgid "Home"
msgstr "Hejmo"
@@ -435,12 +503,18 @@ msgstr "La refreÅigo komenciÄis sukcese"
msgid "Import repository"
msgstr "Enporti deponejon"
+msgid "Install a Runner compatible with GitLab CI"
+msgstr ""
+
msgid "Interval Pattern"
msgstr "Intervala Åablono"
msgid "Introducing Cycle Analytics"
msgstr "Ni prezentas al vi la ciklan analizon"
+msgid "Issue events"
+msgstr ""
+
msgid "Jobs for last month"
msgstr "Taskoj po la lasta monato"
@@ -470,6 +544,12 @@ msgstr "Lasta Äisdatigo"
msgid "Last commit"
msgstr "Lasta enmetado"
+msgid "LastPushEvent|You pushed to"
+msgstr ""
+
+msgid "LastPushEvent|at"
+msgstr ""
+
msgid "Learn more in the"
msgstr "Lernu pli en la"
@@ -490,9 +570,15 @@ msgstr[1] "Limigita al montrado de ne pli ol %d eventoj"
msgid "Median"
msgstr "Mediano"
+msgid "Merge events"
+msgstr ""
+
msgid "MissingSSHKeyWarningLink|add an SSH key"
msgstr "aldonos SSH-Ålosilon"
+msgid "More information is available|here"
+msgstr ""
+
msgid "New Issue"
msgid_plural "New Issues"
msgstr[0] "Nova problemo"
@@ -690,6 +776,9 @@ msgstr "kun etapo"
msgid "Pipeline|with stages"
msgstr "kun etapoj"
+msgid "Project"
+msgstr ""
+
msgid "Project '%{project_name}' queued for deletion."
msgstr "La projekto „%{project_name}“ estis alvicigita por forigado."
@@ -705,27 +794,27 @@ msgstr "La projekto „%{project_name}“ estos forigita."
msgid "Project access must be granted explicitly to each user."
msgstr "Ĉiu uzanto devas akiri propran atingon al la projekto."
+msgid "Project details"
+msgstr ""
+
msgid "Project export could not be deleted."
msgstr "Ne eblas forigi la projektan elporton."
msgid "Project export has been deleted."
msgstr "La projekta elporto estis forigita."
-msgid ""
-"Project export link has expired. Please generate a new export from your "
-"project settings."
-msgstr ""
-"La ligilo por la projekta elporto eksvalidiÄis. Bonvolu krei novan elporton "
-"en la agordoj de la projekto."
+msgid "Project export link has expired. Please generate a new export from your project settings."
+msgstr "La ligilo por la projekta elporto eksvalidiÄis. Bonvolu krei novan elporton en la agordoj de la projekto."
msgid "Project export started. A download link will be sent by email."
-msgstr ""
-"La elporto de la projekto komenciÄis. Vi ricevos ligilon per retpoÅto por "
-"elÅuti la datenoj."
+msgstr "La elporto de la projekto komenciÄis. Vi ricevos ligilon per retpoÅto por elÅuti la datenoj."
msgid "Project home"
msgstr "Hejmo de la projekto"
+msgid "ProjectActivityRSS|Subscribe"
+msgstr ""
+
msgid "ProjectFeature|Disabled"
msgstr "MalÅaltita"
@@ -747,6 +836,9 @@ msgstr "Etapo"
msgid "ProjectNetworkGraph|Graph"
msgstr "Grafeo"
+msgid "Push events"
+msgstr ""
+
msgid "Read more"
msgstr "Legu pli"
@@ -783,9 +875,21 @@ msgstr "Rememorigu denove"
msgid "Remove project"
msgstr "Forigi la projekton"
+msgid "Repository"
+msgstr ""
+
msgid "Request Access"
msgstr "Peti atingeblon"
+msgid "Reset git storage health information"
+msgstr ""
+
+msgid "Reset health check access token"
+msgstr ""
+
+msgid "Reset runners registration token"
+msgstr ""
+
msgid "Revert this commit"
msgstr "Malfari ĉi tiun enmetadon"
@@ -810,13 +914,14 @@ msgstr "Elektu formaton de arkivo"
msgid "Select a timezone"
msgstr "Elektu horzonon"
+msgid "Select existing branch"
+msgstr ""
+
msgid "Select target branch"
msgstr "Elektu celan branĉon"
msgid "Set a password on your account to pull or push via %{protocol}."
-msgstr ""
-"Kreu pasvorton por via konto por ebligi al vi eltiri kaj alpuÅi per "
-"%{protocol}."
+msgstr "Kreu pasvorton por via konto por ebligi al vi eltiri kaj alpuÅi per %{protocol}."
msgid "Set up CI"
msgstr "Agordi SI"
@@ -838,12 +943,18 @@ msgstr[1] "Estas montrataj %d eventoj"
msgid "Source code"
msgstr "Kodo"
+msgid "Specify the following URL during the Runner setup:"
+msgstr ""
+
msgid "StarProject|Star"
msgstr "Steligi"
msgid "Start a %{new_merge_request} with these changes"
msgstr "Kreu %{new_merge_request} kun ĉi tiuj ÅanÄoj"
+msgid "Start the Runner!"
+msgstr ""
+
msgid "Switch branch/tag"
msgstr "Iri al branĉo/etikedo"
@@ -858,62 +969,32 @@ msgstr "Etikedoj"
msgid "Target Branch"
msgstr "Cela branĉo"
-msgid ""
-"The coding stage shows the time from the first commit to creating the merge "
-"request. The data will automatically be added here once you create your "
-"first merge request."
+msgid "Team"
msgstr ""
-"La etapo de programado montras la tempon de la unua enmetado Äis la kreado "
-"de la peto pri kunfando. La datenoj aldoniÄos aÅ­tomate ĉi tie post kiam vi "
-"kreas la unuan peton pri kunfando."
+
+msgid "The coding stage shows the time from the first commit to creating the merge request. The data will automatically be added here once you create your first merge request."
+msgstr "La etapo de programado montras la tempon de la unua enmetado Äis la kreado de la peto pri kunfando. La datenoj aldoniÄos aÅ­tomate ĉi tie post kiam vi kreas la unuan peton pri kunfando."
msgid "The collection of events added to the data gathered for that stage."
-msgstr ""
-"La aro da eventoj, kiuj estas aldonitaj al la datenoj kolektitaj por la "
-"etapo."
+msgstr "La aro da eventoj, kiuj estas aldonitaj al la datenoj kolektitaj por la etapo."
msgid "The fork relationship has been removed."
msgstr "La rilato de disbranĉigo estis forigita."
-msgid ""
-"The issue stage shows the time it takes from creating an issue to assigning "
-"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 ""
-"La etapo de la problemo montras kiom la tempo pasas de la kreado de problemo "
-"Äis la atribuado de la problemo al cela etapo de la projekto, aÅ­ al listo "
-"sur la problemtabulo. Komencu krei problemojn por vidi la datenojn por ĉi "
-"tiu etapo."
+msgid "The issue stage shows the time it takes from creating an issue to assigning 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 "La etapo de la problemo montras kiom la tempo pasas de la kreado de problemo Äis la atribuado de la problemo al cela etapo de la projekto, aÅ­ al listo sur la problemtabulo. Komencu krei problemojn por vidi la datenojn por ĉi tiu etapo."
msgid "The phase of the development lifecycle."
msgstr "La etapo de la disvolva ciklo."
-msgid ""
-"The pipelines schedule runs pipelines in the future, repeatedly, for "
-"specific branches or tags. Those scheduled pipelines will inherit limited "
-"project access based on their associated user."
-msgstr ""
-"La ĉenstabla plano plenumas ĉenstablojn en la estonteco, ripete, por "
-"difinitaj branĉoj aŭ etikedoj. Tiuj planitaj ĉenstabloj heredos la limigitan "
-"atingon al la projekto de la rilata uzanto."
+msgid "The pipelines schedule runs pipelines in the future, repeatedly, for specific branches or tags. Those scheduled pipelines will inherit limited project access based on their associated user."
+msgstr "La ĉenstabla plano plenumas ĉenstablojn en la estonteco, ripete, por difinitaj branĉoj aŭ etikedoj. Tiuj planitaj ĉenstabloj heredos la limigitan atingon al la projekto de la rilata uzanto."
-msgid ""
-"The planning stage shows the time from the previous step to pushing your "
-"first commit. This time will be added automatically once you push your first "
-"commit."
-msgstr ""
-"La etapo de la plano montras la tempon de la antaÅ­a Åtupo Äis la alpuÅado de "
-"via unua enmetado. Ĉi tiu tempo aldoniÄos aÅ­tomate post kiam vi alpuÅas la "
-"unuan enmetadon."
+msgid "The planning stage shows the time from the previous step to pushing your first commit. This time will be added automatically once you push your first commit."
+msgstr "La etapo de la plano montras la tempon de la antaÅ­a Åtupo Äis la alpuÅado de via unua enmetado. Ĉi tiu tempo aldoniÄos aÅ­tomate post kiam vi alpuÅas la unuan enmetadon."
-msgid ""
-"The production stage shows the total time it takes between creating an issue "
-"and deploying the code to production. The data will be automatically added "
-"once you have completed the full idea to production cycle."
-msgstr ""
-"La etapo de eldonado montras la tutan tempon de la kreado de problemo Äis la "
-"disponigado en la publika versio. La datenoj aldoniÄos aÅ­tomate post kiam vi "
-"kompletigos plenan ciklon de ideo Äis realaĵo."
+msgid "The production stage shows the total time it takes between creating an issue and deploying the code to production. The data will be automatically added once you have completed the full idea to production cycle."
+msgstr "La etapo de eldonado montras la tutan tempon de la kreado de problemo Äis la disponigado en la publika versio. La datenoj aldoniÄos aÅ­tomate post kiam vi kompletigos plenan ciklon de ideo Äis realaĵo."
msgid "The project can be accessed by any logged in user."
msgstr "Ĉiu ensalutita uzanto havas atingon al la projekto"
@@ -924,52 +1005,26 @@ msgstr "Ĉiu povas havi atingon al la projekto, sen ensaluti"
msgid "The repository for this project does not exist."
msgstr "La deponejo por ĉi tiu projekto ne ekzistas."
-msgid ""
-"The review stage shows the time from creating the merge request to merging "
-"it. The data will automatically be added after you merge your first merge "
-"request."
-msgstr ""
-"La etapo de la kontrolo montras la tempon de la kreado de la peto pri "
-"kunfando Äis Äia aplikado. La datenoj aldoniÄos aÅ­tomate post kiam vi "
-"aplikos la unuan peton pri kunfando."
+msgid "The review stage shows the time from creating the merge request to merging it. The data will automatically be added after you merge your first merge request."
+msgstr "La etapo de la kontrolo montras la tempon de la kreado de la peto pri kunfando Äis Äia aplikado. La datenoj aldoniÄos aÅ­tomate post kiam vi aplikos la unuan peton pri kunfando."
-msgid ""
-"The staging stage shows the time between merging the MR and deploying code "
-"to the production environment. The data will be automatically added once you "
-"deploy to production for the first time."
-msgstr ""
-"La etapo de preparo por eldono montras la tempon inter la aplikado de la "
-"peto pri kunfando kaj la disponigado de la kodo en la publika versio. La "
-"datenoj aldoniÄos aÅ­tomate post kiam vi faros la unuan disponigadon en la "
-"publika versio."
+msgid "The staging stage shows the time between merging the MR and deploying code to the production environment. The data will be automatically added once you deploy to production for the first time."
+msgstr "La etapo de preparo por eldono montras la tempon inter la aplikado de la peto pri kunfando kaj la disponigado de la kodo en la publika versio. La datenoj aldoniÄos aÅ­tomate post kiam vi faros la unuan disponigadon en la publika versio."
-msgid ""
-"The testing stage shows the time GitLab CI takes to run every pipeline for "
-"the related merge request. The data will automatically be added after your "
-"first pipeline finishes running."
-msgstr ""
-"La etapo de testado montras kiom da tempo necesas al „GitLab CI“ por plenumi "
-"ĉiujn ĉenstablojn por la rilata peto pri kunfando. La datenoj aldoniÄos "
-"aÅ­tomate post kiam via unua ĉenstablo finiÄos."
+msgid "The testing stage shows the time GitLab CI takes to run every pipeline for the related merge request. The data will automatically be added after your first pipeline finishes running."
+msgstr "La etapo de testado montras kiom da tempo necesas al „GitLab CI“ por plenumi ĉiujn ĉenstablojn por la rilata peto pri kunfando. La datenoj aldoniÄos aÅ­tomate post kiam via unua ĉenstablo finiÄos."
msgid "The time taken by each data entry gathered by that stage."
msgstr "La tempo, kiu estas necesa por ĉiu dateno kolektita de la etapo."
-msgid ""
-"The value lying at the midpoint of a series of observed values. E.g., "
-"between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 ="
-" 6."
-msgstr ""
-"La valoro, kiu troviÄas en la mezo de aro da rigardataj valoroj. Ekzemple: "
-"inter 3, 5 kaj 9, la mediano estas 5. Inter 3, 5, 7 kaj 8, la mediano estas "
-"(5+7)/2 = 6."
+msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
+msgstr "La valoro, kiu troviÄas en la mezo de aro da rigardataj valoroj. Ekzemple: inter 3, 5 kaj 9, la mediano estas 5. Inter 3, 5, 7 kaj 8, la mediano estas (5+7)/2 = 6."
-msgid ""
-"This means you can not push code until you create an empty repository or "
-"import existing one."
+msgid "There are problems accessing Git storage: "
msgstr ""
-"Ĉi tiu signifas, ke vi ne povos alpuÅi kodon, antaÅ­ ol vi kreos malplenan "
-"deponejon aÅ­ enportos jam ekzistantan."
+
+msgid "This means you can not push code until you create an empty repository or import existing one."
+msgstr "Ĉi tiu signifas, ke vi ne povos alpuÅi kodon, antaÅ­ ol vi kreos malplenan deponejon aÅ­ enportos jam ekzistantan."
msgid "Time before an issue gets scheduled"
msgstr "Tempo antaÅ­ problemo estas planita por ellabori"
@@ -1137,6 +1192,9 @@ msgstr "AlÅuti dosieron"
msgid "UploadLink|click to upload"
msgstr "alklaku por alÅuti"
+msgid "Use the following registration token during setup:"
+msgstr ""
+
msgid "Use your global notification setting"
msgstr "Uzi vian Äeneralan agordon pri la sciigoj"
@@ -1156,8 +1214,7 @@ msgid "VisibilityLevel|Unknown"
msgstr "Nekonata"
msgid "Want to see the data? Please ask an administrator for access."
-msgstr ""
-"Ĉu vi volas vidi la datenojn? Bonvolu peti atingeblon de administranto."
+msgstr "Ĉu vi volas vidi la datenojn? Bonvolu peti atingeblon de administranto."
msgid "We don't have enough data to show this stage."
msgstr "Ne estas sufiĉe da datenoj por montri ĉi tiun etapon."
@@ -1174,12 +1231,8 @@ msgstr "Vi forigos „%{project_name_with_namespace}“. Oni NE POVAS malfari la
msgid "You are going to remove the fork relationship to source project %{forked_from_project}. Are you ABSOLUTELY sure?"
msgstr "Vi forigos la rilaton de la disbranĉigo al la originala projekto, „%{forked_from_project}“. Ĉu vi estas ABSOLUTE certa?"
-msgid ""
-"You are going to transfer %{project_name_with_namespace} to another owner. "
-"Are you ABSOLUTELY sure?"
-msgstr ""
-"Vi transigos „%{project_name_with_namespace}“ al alia posedanto. Ĉu vi estas "
-"ABSOLUTE certa?"
+msgid "You are going to transfer %{project_name_with_namespace} to another owner. Are you ABSOLUTELY sure?"
+msgstr "Vi transigos „%{project_name_with_namespace}“ al alia posedanto. Ĉu vi estas ABSOLUTE certa?"
msgid "You can only add files when you are on a branch"
msgstr "Oni povas aldoni dosierojn nur kiam oni estas en branĉo"
@@ -1199,31 +1252,20 @@ msgstr "VI ne ricevos sciigojn per retpoÅto"
msgid "You will only receive notifications for the events you choose"
msgstr "Vi ricevos sciigojn nur por la eventoj elektitaj de vi"
-msgid ""
-"You will only receive notifications for threads you have participated in"
+msgid "You will only receive notifications for threads you have participated in"
msgstr "Vi ricevos sciigojn nur por la fadenoj, en kiuj vi partoprenis"
msgid "You will receive notifications for any activity"
msgstr "Vi ricevos sciigojn por ĉiu ago"
-msgid ""
-"You will receive notifications only for comments in which you were "
-"@mentioned"
+msgid "You will receive notifications only for comments in which you were @mentioned"
msgstr "Vi ricevos sciigojn nur por komentoj, en kiuj vi estas @menciita"
-msgid ""
-"You won't be able to pull or push project code via %{protocol} until you "
-"%{set_password_link} on your account"
-msgstr ""
-"Vi ne povos eltiri aÅ­ alpuÅi kodon per %{protocol} antaÅ­ ol vi "
-"%{set_password_link} por via konto"
+msgid "You won't be able to pull or push project code via %{protocol} until you %{set_password_link} on your account"
+msgstr "Vi ne povos eltiri aÅ­ alpuÅi kodon per %{protocol} antaÅ­ ol vi %{set_password_link} por via konto"
-msgid ""
-"You won't be able to pull or push project code via SSH until you "
-"%{add_ssh_key_link} to your profile"
-msgstr ""
-"Vi ne povos eltiri aÅ­ alpuÅi kodon per SSH antaÅ­ ol vi %{add_ssh_key_link} "
-"al via profilo"
+msgid "You won't be able to pull or push project code via SSH until you %{add_ssh_key_link} to your profile"
+msgstr "Vi ne povos eltiri aÅ­ alpuÅi kodon per SSH antaÅ­ ol vi %{add_ssh_key_link} al via profilo"
msgid "Your name"
msgstr "Via nomo"
@@ -1242,5 +1284,4 @@ msgstr "sciigoj per retpoÅto"
msgid "parent"
msgid_plural "parents"
msgstr[0] "patro"
-msgstr[1] "patroj"
-
+msgstr[1] "patroj" \ No newline at end of file
diff --git a/locale/es/gitlab.po b/locale/es/gitlab.po
index e43fd5fea15..8158bd275bd 100644
--- a/locale/es/gitlab.po
+++ b/locale/es/gitlab.po
@@ -1,21 +1,20 @@
-# Spanish translations for gitlab package.
-# Copyright (C) 2017 THE PACKAGE'S COPYRIGHT HOLDER
-# This file is distributed under the same license as the gitlab package.
-# FIRST AUTHOR <EMAIL@ADDRESS>, 2017.
-#
msgid ""
msgstr ""
-"Project-Id-Version: gitlab 1.0.0\n"
+"Project-Id-Version: gitlab-ee\n"
"Report-Msgid-Bugs-To: \n"
-"PO-Revision-Date: 2017-07-13 12:10-0500\n"
+"POT-Creation-Date: 2017-08-18 14:15+0530\n"
+"PO-Revision-Date: 2017-08-23 09:37-0400\n"
+"Last-Translator: gitlab <mbartlett+crowdin@gitlab.com>\n"
"Language-Team: Spanish\n"
-"Language: es\n"
+"Language: es_ES\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"Plural-Forms: nplurals=2; plural=n != 1;\n"
-"Last-Translator: Bob Van Landuyt <bob@gitlab.com>\n"
-"X-Generator: Poedit 2.0.2\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Generator: crowdin.com\n"
+"X-Crowdin-Project: gitlab-ee\n"
+"X-Crowdin-Language: es-ES\n"
+"X-Crowdin-File: /master/locale/gitlab.pot\n"
msgid "%d commit"
msgid_plural "%d commits"
@@ -30,10 +29,27 @@ msgstr[1] "%s cambios adicionales han sido omitidos para evitar problemas de ren
msgid "%{commit_author_link} committed %{commit_timeago}"
msgstr "%{commit_author_link} cambió %{commit_timeago}"
+msgid "%{number_of_failures} of %{maximum_failures} failures. GitLab will allow access on the next attempt."
+msgstr ""
+
+msgid "%{number_of_failures} of %{maximum_failures} failures. GitLab will block access for %{number_of_seconds} seconds."
+msgstr ""
+
+msgid "%{number_of_failures} of %{maximum_failures} failures. GitLab will not retry automatically. Reset storage information when the problem is resolved."
+msgstr ""
+
+msgid "%{storage_name}: failed storage access attempt on host:"
+msgid_plural "%{storage_name}: %{failed_attempts} failed storage access attempts:"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "(checkout the %{link} for information on how to install it)."
+msgstr ""
+
msgid "1 pipeline"
msgid_plural "%d pipelines"
-msgstr[0] "1 pipeline"
-msgstr[1] "%d pipelines"
+msgstr[0] ""
+msgstr[1] ""
msgid "A collection of graphs regarding Continuous Integration"
msgstr "Una colección de gráficos sobre Integración Continua"
@@ -41,6 +57,9 @@ msgstr "Una colección de gráficos sobre Integración Continua"
msgid "About auto deploy"
msgstr "Acerca del auto despliegue"
+msgid "Access to failing storages has been temporarily disabled to allow the mount to recover. Reset storage information after the issue has been resolved to allow access again."
+msgstr ""
+
msgid "Active"
msgstr "Activo"
@@ -62,12 +81,27 @@ msgstr "Agregar una clave SSH a tu perfil para actualizar o enviar a través de
msgid "Add new directory"
msgstr "Agregar nuevo directorio"
+msgid "All"
+msgstr ""
+
msgid "Archived project! Repository is read-only"
msgstr "¡Proyecto archivado! El repositorio es de solo lectura"
msgid "Are you sure you want to delete this pipeline schedule?"
msgstr "¿Estás seguro que deseas eliminar esta programación del pipeline?"
+msgid "Are you sure you want to discard your changes?"
+msgstr ""
+
+msgid "Are you sure you want to reset registration token?"
+msgstr ""
+
+msgid "Are you sure you want to reset the health check token?"
+msgstr ""
+
+msgid "Are you sure?"
+msgstr ""
+
msgid "Attach a file by drag &amp; drop or %{upload_link}"
msgstr "Adjunte un archivo arrastrando &amp; soltando o %{upload_link}"
@@ -109,6 +143,9 @@ msgstr "Configuración de CI"
msgid "Cancel"
msgstr "Cancelar"
+msgid "Cancel edit"
+msgstr ""
+
msgid "ChangeTypeActionLabel|Pick into branch"
msgstr "Escoger en la rama"
@@ -122,7 +159,7 @@ msgid "ChangeTypeAction|Revert"
msgstr "Revertir"
msgid "Changelog"
-msgstr "Changelog"
+msgstr ""
msgid "Charts"
msgstr "Gráficos"
@@ -187,6 +224,9 @@ msgstr "omitido"
msgid "CiStatus|running"
msgstr "en ejecución"
+msgid "Comments"
+msgstr ""
+
msgid "Commit"
msgid_plural "Commits"
msgstr[0] "Cambio"
@@ -234,6 +274,9 @@ msgstr "Copiar SHA del cambio al portapapeles"
msgid "Create New Directory"
msgstr "Crear Nuevo Directorio"
+msgid "Create a new branch"
+msgstr ""
+
msgid "Create a personal access token on your account to pull or push via %{protocol}."
msgstr "Crear un token de acceso personal en tu cuenta para actualizar o enviar a través de %{protocol}."
@@ -271,7 +314,7 @@ msgid "Custom notification levels are the same as participating levels. With cus
msgstr "Los niveles de notificación personalizados son los mismos que los niveles participantes. Con los niveles de notificación personalizados, también recibirá notificaciones para eventos seleccionados. Para obtener más información, consulte %{notification_link}."
msgid "Cycle Analytics"
-msgstr "Cycle Analytics"
+msgstr ""
msgid "Cycle Analytics gives an overview of how much time it takes to go from idea to production in your project."
msgstr "Cycle Analytics ofrece una visión general de cuánto tiempo tarda en pasar de idea a producción en su proyecto."
@@ -311,9 +354,15 @@ msgstr[1] "Despliegues"
msgid "Description"
msgstr "Descripción"
+msgid "Details"
+msgstr ""
+
msgid "Directory name"
msgstr "Nombre del directorio"
+msgid "Discard changes"
+msgstr ""
+
msgid "Don't show again"
msgstr "No mostrar de nuevo"
@@ -350,6 +399,24 @@ msgstr "Editar"
msgid "Edit Pipeline Schedule %{id}"
msgstr "Editar Programación del Pipeline %{id}"
+msgid "EventFilterBy|Filter by all"
+msgstr ""
+
+msgid "EventFilterBy|Filter by comments"
+msgstr ""
+
+msgid "EventFilterBy|Filter by issue events"
+msgstr ""
+
+msgid "EventFilterBy|Filter by merge events"
+msgstr ""
+
+msgid "EventFilterBy|Filter by push events"
+msgstr ""
+
+msgid "EventFilterBy|Filter by team"
+msgstr ""
+
msgid "Every day (at 4:00am)"
msgstr "Todos los días (a las 4:00 am)"
@@ -397,12 +464,36 @@ msgstr "Desde la creación de la incidencia hasta el despliegue a producción"
msgid "From merge request merge until deploy to production"
msgstr "Desde la integración de la solicitud de fusión hasta el despliegue a producción"
+msgid "Git storage health information has been reset"
+msgstr ""
+
+msgid "GitLab Runner section"
+msgstr ""
+
msgid "Go to your fork"
msgstr "Ir a tu bifurcación"
msgid "GoToYourFork|Fork"
msgstr "Bifurcación"
+msgid "Health Check"
+msgstr ""
+
+msgid "Health information can be retrieved from the following endpoints. More information is available"
+msgstr ""
+
+msgid "HealthCheck|Access token is"
+msgstr ""
+
+msgid "HealthCheck|Healthy"
+msgstr ""
+
+msgid "HealthCheck|No Health Problems Detected"
+msgstr ""
+
+msgid "HealthCheck|Unhealthy"
+msgstr ""
+
msgid "Home"
msgstr "Inicio"
@@ -412,12 +503,18 @@ msgstr "Servicio de limpieza iniciado con éxito"
msgid "Import repository"
msgstr "Importar repositorio"
+msgid "Install a Runner compatible with GitLab CI"
+msgstr ""
+
msgid "Interval Pattern"
msgstr "Patrón de intervalo"
msgid "Introducing Cycle Analytics"
msgstr "Introducción a Cycle Analytics"
+msgid "Issue events"
+msgstr ""
+
msgid "Jobs for last month"
msgstr "Trabajos del mes pasado"
@@ -447,6 +544,12 @@ msgstr "Última actualización"
msgid "Last commit"
msgstr "Último cambio"
+msgid "LastPushEvent|You pushed to"
+msgstr ""
+
+msgid "LastPushEvent|at"
+msgstr ""
+
msgid "Learn more in the"
msgstr "Más información en la"
@@ -467,9 +570,15 @@ msgstr[1] "Limitado a mostrar máximo %d eventos"
msgid "Median"
msgstr "Mediana"
+msgid "Merge events"
+msgstr ""
+
msgid "MissingSSHKeyWarningLink|add an SSH key"
msgstr "agregar una clave SSH"
+msgid "More information is available|here"
+msgstr ""
+
msgid "New Issue"
msgid_plural "New Issues"
msgstr[0] "Nueva incidencia"
@@ -581,7 +690,7 @@ msgid "Owner"
msgstr "Propietario"
msgid "Pipeline"
-msgstr "Pipeline"
+msgstr ""
msgid "Pipeline Health"
msgstr "Estado del Pipeline"
@@ -650,7 +759,7 @@ msgid "PipelineSheduleIntervalPattern|Custom"
msgstr "Personalizado"
msgid "Pipelines"
-msgstr "Pipelines"
+msgstr ""
msgid "Pipelines charts"
msgstr "Gráficos de los pipelines"
@@ -667,6 +776,9 @@ msgstr "con etapa"
msgid "Pipeline|with stages"
msgstr "con etapas"
+msgid "Project"
+msgstr ""
+
msgid "Project '%{project_name}' queued for deletion."
msgstr "Proyecto ‘%{project_name}’ en cola para eliminación."
@@ -682,6 +794,9 @@ msgstr "Proyecto ‘%{project_name}’ será eliminado."
msgid "Project access must be granted explicitly to each user."
msgstr "El acceso al proyecto debe concederse explícitamente a cada usuario."
+msgid "Project details"
+msgstr ""
+
msgid "Project export could not be deleted."
msgstr "No se pudo eliminar la exportación del proyecto."
@@ -697,6 +812,9 @@ msgstr "Se inició la exportación del proyecto. Se enviará un enlace de descar
msgid "Project home"
msgstr "Inicio del proyecto"
+msgid "ProjectActivityRSS|Subscribe"
+msgstr ""
+
msgid "ProjectFeature|Disabled"
msgstr "Deshabilitada"
@@ -718,6 +836,9 @@ msgstr "Etapa"
msgid "ProjectNetworkGraph|Graph"
msgstr "Historial gráfico"
+msgid "Push events"
+msgstr ""
+
msgid "Read more"
msgstr "Leer más"
@@ -754,9 +875,21 @@ msgstr "Recordar después"
msgid "Remove project"
msgstr "Eliminar proyecto"
+msgid "Repository"
+msgstr ""
+
msgid "Request Access"
msgstr "Solicitar acceso"
+msgid "Reset git storage health information"
+msgstr ""
+
+msgid "Reset health check access token"
+msgstr ""
+
+msgid "Reset runners registration token"
+msgstr ""
+
msgid "Revert this commit"
msgstr "Revertir este cambio"
@@ -781,6 +914,9 @@ msgstr "Seleccionar formato de archivo"
msgid "Select a timezone"
msgstr "Selecciona una zona horaria"
+msgid "Select existing branch"
+msgstr ""
+
msgid "Select target branch"
msgstr "Selecciona una rama de destino"
@@ -807,12 +943,18 @@ msgstr[1] "Mostrando %d eventos"
msgid "Source code"
msgstr "Código fuente"
+msgid "Specify the following URL during the Runner setup:"
+msgstr ""
+
msgid "StarProject|Star"
msgstr "Destacar"
msgid "Start a %{new_merge_request} with these changes"
msgstr "Iniciar una %{new_merge_request} con estos cambios"
+msgid "Start the Runner!"
+msgstr ""
+
msgid "Switch branch/tag"
msgstr "Cambiar rama/etiqueta"
@@ -827,6 +969,9 @@ msgstr "Etiquetas"
msgid "Target Branch"
msgstr "Rama de destino"
+msgid "Team"
+msgstr ""
+
msgid "The coding stage shows the time from the first commit to creating the merge request. The data will automatically be added here once you create your first merge request."
msgstr "La etapa de desarrollo muestra el tiempo desde el primer cambio hasta la creación de la solicitud de fusión. Los datos serán automáticamente incorporados aquí una vez creada tu primera solicitud de fusión."
@@ -875,6 +1020,9 @@ msgstr "El tiempo utilizado por cada entrada de datos obtenido por esa etapa."
msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
msgstr "El valor en el punto medio de una serie de valores observados. Por ejemplo, entre 3, 5, 9, la mediana es 5. Entre 3, 5, 7, 8, la mediana es (5 + 7) / 2 = 6."
+msgid "There are problems accessing Git storage: "
+msgstr ""
+
msgid "This means you can not push code until you create an empty repository or import existing one."
msgstr "Esto significa que no puede enviar código hasta que cree un repositorio vacío o importe uno existente."
@@ -1044,6 +1192,9 @@ msgstr "Subir archivo"
msgid "UploadLink|click to upload"
msgstr "Hacer clic para subir"
+msgid "Use the following registration token during setup:"
+msgstr ""
+
msgid "Use your global notification setting"
msgstr "Utiliza tu configuración de notificación global"
@@ -1133,4 +1284,4 @@ msgstr "correos electrónicos de notificación"
msgid "parent"
msgid_plural "parents"
msgstr[0] "padre"
-msgstr[1] "padres"
+msgstr[1] "padres" \ No newline at end of file
diff --git a/locale/fr/gitlab.po b/locale/fr/gitlab.po
index 83f31f7a3b2..3daff3f5c19 100644
--- a/locale/fr/gitlab.po
+++ b/locale/fr/gitlab.po
@@ -1,43 +1,55 @@
-# Dremor <egeorget@opmbx.org>, 2017. #zanata
-# Huang Tao <htve@outlook.com>, 2017. #zanata
-# Rémy Coutable <remy@rymai.me>, 2017. #zanata
msgid ""
msgstr ""
-"Project-Id-Version: gitlab 1.0.0\n"
+"Project-Id-Version: gitlab-ee\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2017-07-13 12:07-0500\n"
+"POT-Creation-Date: 2017-08-18 14:15+0530\n"
+"PO-Revision-Date: 2017-08-23 09:53-0400\n"
+"Last-Translator: gitlab <mbartlett+crowdin@gitlab.com>\n"
+"Language-Team: French\n"
+"Language: fr_FR\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"Language-Team: French (https://translate.zanata.org/project/view/GitLab)\n"
-"PO-Revision-Date: 2017-08-03 03:35-0400\n"
-"Last-Translator: Rémy Coutable <remy@rymai.me>\n"
-"Language: fr\n"
-"X-Generator: Zanata 3.9.6\n"
-"Plural-Forms: nplurals=2; plural=(n > 1)\n"
-
-msgid "%s additional commit has been omitted to prevent performance issues."
-msgid_plural ""
-"%s additional commits have been omitted to prevent performance issues."
-msgstr[0] ""
-"%s validation supplémentaire a été masquée afin d'éviter de créer de "
-"problèmes de performances."
-msgstr[1] ""
-"%s validations supplémentaires ont été masquées afin d'éviter de créer de "
-"problèmes de performances."
+"Plural-Forms: nplurals=2; plural=(n > 1);\n"
+"X-Generator: crowdin.com\n"
+"X-Crowdin-Project: gitlab-ee\n"
+"X-Crowdin-Language: fr\n"
+"X-Crowdin-File: /master/locale/gitlab.pot\n"
msgid "%d commit"
msgid_plural "%d commits"
msgstr[0] "%d validation"
msgstr[1] "%d validations"
+msgid "%s additional commit has been omitted to prevent performance issues."
+msgid_plural "%s additional commits have been omitted to prevent performance issues."
+msgstr[0] "%s validation supplémentaire a été masquée afin d'éviter de créer de problèmes de performances."
+msgstr[1] "%s validations supplémentaires ont été masquées afin d'éviter de créer de problèmes de performances."
+
msgid "%{commit_author_link} committed %{commit_timeago}"
msgstr "%{commit_author_link} a validé %{commit_timeago}"
+msgid "%{number_of_failures} of %{maximum_failures} failures. GitLab will allow access on the next attempt."
+msgstr ""
+
+msgid "%{number_of_failures} of %{maximum_failures} failures. GitLab will block access for %{number_of_seconds} seconds."
+msgstr ""
+
+msgid "%{number_of_failures} of %{maximum_failures} failures. GitLab will not retry automatically. Reset storage information when the problem is resolved."
+msgstr ""
+
+msgid "%{storage_name}: failed storage access attempt on host:"
+msgid_plural "%{storage_name}: %{failed_attempts} failed storage access attempts:"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "(checkout the %{link} for information on how to install it)."
+msgstr ""
+
msgid "1 pipeline"
msgid_plural "%d pipelines"
-msgstr[0] "1 pipeline"
-msgstr[1] "%d pipelines"
+msgstr[0] ""
+msgstr[1] ""
msgid "A collection of graphs regarding Continuous Integration"
msgstr "Un ensemble de graphiques concernant l’Intégration Continue (CI)"
@@ -45,6 +57,9 @@ msgstr "Un ensemble de graphiques concernant l’Intégration Continue (CI)"
msgid "About auto deploy"
msgstr "A propos de l'auto-déploiement"
+msgid "Access to failing storages has been temporarily disabled to allow the mount to recover. Reset storage information after the issue has been resolved to allow access again."
+msgstr ""
+
msgid "Active"
msgstr "Actif"
@@ -61,36 +76,42 @@ msgid "Add License"
msgstr "Ajouter une licence"
msgid "Add an SSH key to your profile to pull or push via SSH."
-msgstr ""
-"Ajoutez une clef SSH à votre profil pour pouvoir récupérer et pousser par "
-"SSH."
+msgstr "Ajoutez une clef SSH à votre profil pour pouvoir récupérer et pousser par SSH."
msgid "Add new directory"
msgstr "Ajouter un nouveau dossier"
+msgid "All"
+msgstr ""
+
msgid "Archived project! Repository is read-only"
msgstr "Projet archivé ! Le dépôt est en lecture seule"
msgid "Are you sure you want to delete this pipeline schedule?"
msgstr "Êtes-vous sûr de vouloir supprimer ce pipeline programmé"
+msgid "Are you sure you want to discard your changes?"
+msgstr ""
+
+msgid "Are you sure you want to reset registration token?"
+msgstr ""
+
+msgid "Are you sure you want to reset the health check token?"
+msgstr ""
+
+msgid "Are you sure?"
+msgstr ""
+
msgid "Attach a file by drag &amp; drop or %{upload_link}"
msgstr "Attachez un fichier par glisser &amp; déposer ou %{upload_link}"
msgid "Branch"
msgid_plural "Branches"
-msgstr[0] "Branche"
-msgstr[1] "Branches"
+msgstr[0] ""
+msgstr[1] ""
-msgid ""
-"Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, "
-"choose a GitLab CI Yaml template and commit your changes. "
-"%{link_to_autodeploy_doc}"
-msgstr ""
-"La branche <strong>%{branch_name}</strong> a été crée. Pour mettre en place "
-"le déploiement automatisé, sélectionnez un modèle de fichier Yaml pour "
-"l'intégration continue (CI) de GitLab, et validez les modifications. "
-"%{link_to_autodeploy_doc}"
+msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
+msgstr "La branche <strong>%{branch_name}</strong> a été crée. Pour mettre en place le déploiement automatisé, sélectionnez un modèle de fichier Yaml pour l'intégration continue (CI) de GitLab, et validez les modifications. %{link_to_autodeploy_doc}"
msgid "BranchSwitcherPlaceholder|Search branches"
msgstr "Rechercher la branche"
@@ -99,7 +120,7 @@ msgid "BranchSwitcherTitle|Switch branch"
msgstr "Changer de branche"
msgid "Branches"
-msgstr "Branches"
+msgstr ""
msgid "Browse Directory"
msgstr "Parcourir le dossier"
@@ -122,6 +143,9 @@ msgstr "Configuration de l'intégration continue (CI)"
msgid "Cancel"
msgstr "Annuler"
+msgid "Cancel edit"
+msgstr ""
+
msgid "ChangeTypeActionLabel|Pick into branch"
msgstr "Sélectionner dans la branche"
@@ -200,6 +224,9 @@ msgstr "ignoré"
msgid "CiStatus|running"
msgstr "en cours"
+msgid "Comments"
+msgstr ""
+
msgid "Commit"
msgid_plural "Commits"
msgstr[0] "Validation"
@@ -247,12 +274,11 @@ msgstr "Copier le SHA de la validation"
msgid "Create New Directory"
msgstr "Créer un nouveau dossier"
-msgid ""
-"Create a personal access token on your account to pull or push via "
-"%{protocol}."
+msgid "Create a new branch"
msgstr ""
-"Créer un jeton d’accès personnel pour votre compte afin de récupérer ou "
-"pousser par %{protocol}."
+
+msgid "Create a personal access token on your account to pull or push via %{protocol}."
+msgstr "Créer un jeton d’accès personnel pour votre compte afin de récupérer ou pousser par %{protocol}."
msgid "Create directory"
msgstr "Créer un dossier"
@@ -284,25 +310,14 @@ msgstr "Syntaxe Cron"
msgid "Custom notification events"
msgstr "Événements de notification personnalisés"
-msgid ""
-"Custom notification levels are the same as participating levels. With custom "
-"notification levels you will also receive notifications for select events. "
-"To find out more, check out %{notification_link}."
-msgstr ""
-"Le niveau de notification Personnalisé est similaire au niveau Participation."
-" Cependant, il permet également de recevoir des notifications pour des "
-"événements sélectionnés. Pour plus d’information, vous pouvez consulter "
-"%{notification_link}."
+msgid "Custom notification levels are the same as participating levels. With custom notification levels you will also receive notifications for select events. To find out more, check out %{notification_link}."
+msgstr "Le niveau de notification Personnalisé est similaire au niveau Participation. Cependant, il permet également de recevoir des notifications pour des événements sélectionnés. Pour plus d’information, vous pouvez consulter %{notification_link}."
msgid "Cycle Analytics"
msgstr "Analyseur de cycle"
-msgid ""
-"Cycle Analytics gives an overview of how much time it takes to go from idea "
-"to production in your project."
-msgstr ""
-"L’analyseur de cycle permet d’avoir une vue d’ensemble du temps nécessaire "
-"pour aller d’une idée à sa mise en production pour votre projet."
+msgid "Cycle Analytics gives an overview of how much time it takes to go from idea to production in your project."
+msgstr "L’analyseur de cycle permet d’avoir une vue d’ensemble du temps nécessaire pour aller d’une idée à sa mise en production pour votre projet."
msgid "CycleAnalyticsStage|Code"
msgstr "Code"
@@ -337,11 +352,17 @@ msgstr[0] "Déploiement"
msgstr[1] "Déploiements"
msgid "Description"
-msgstr "Description"
+msgstr ""
+
+msgid "Details"
+msgstr ""
msgid "Directory name"
msgstr "Nom du dossier"
+msgid "Discard changes"
+msgstr ""
+
msgid "Don't show again"
msgstr "Ne plus montrer"
@@ -378,6 +399,24 @@ msgstr "Éditer"
msgid "Edit Pipeline Schedule %{id}"
msgstr "Éditer le pipeline programmé %{id}"
+msgid "EventFilterBy|Filter by all"
+msgstr ""
+
+msgid "EventFilterBy|Filter by comments"
+msgstr ""
+
+msgid "EventFilterBy|Filter by issue events"
+msgstr ""
+
+msgid "EventFilterBy|Filter by merge events"
+msgstr ""
+
+msgid "EventFilterBy|Filter by push events"
+msgstr ""
+
+msgid "EventFilterBy|Filter by team"
+msgstr ""
+
msgid "Every day (at 4:00am)"
msgstr "Chaque jour (à 4:00 du matin)"
@@ -423,8 +462,13 @@ msgid "From issue creation until deploy to production"
msgstr "Depuis la création de l'incident jusqu'au déploiement en production"
msgid "From merge request merge until deploy to production"
+msgstr "Depuis la fusion de la demande de fusion jusqu'au déploiement en production"
+
+msgid "Git storage health information has been reset"
+msgstr ""
+
+msgid "GitLab Runner section"
msgstr ""
-"Depuis la fusion de la demande de fusion jusqu'au déploiement en production"
msgid "Go to your fork"
msgstr "Aller à votre fourche"
@@ -432,6 +476,24 @@ msgstr "Aller à votre fourche"
msgid "GoToYourFork|Fork"
msgstr "Fourche"
+msgid "Health Check"
+msgstr ""
+
+msgid "Health information can be retrieved from the following endpoints. More information is available"
+msgstr ""
+
+msgid "HealthCheck|Access token is"
+msgstr ""
+
+msgid "HealthCheck|Healthy"
+msgstr ""
+
+msgid "HealthCheck|No Health Problems Detected"
+msgstr ""
+
+msgid "HealthCheck|Unhealthy"
+msgstr ""
+
msgid "Home"
msgstr "Accueil"
@@ -441,12 +503,18 @@ msgstr "Maintenance démarrée avec succès"
msgid "Import repository"
msgstr "Importer un dépôt"
+msgid "Install a Runner compatible with GitLab CI"
+msgstr ""
+
msgid "Interval Pattern"
msgstr "Schéma d’intervalle"
msgid "Introducing Cycle Analytics"
msgstr "Introduction à l'analyseur de cycle"
+msgid "Issue events"
+msgstr ""
+
msgid "Jobs for last month"
msgstr "Tâches pour le mois dernier"
@@ -476,6 +544,12 @@ msgstr "Dernière mise à jour"
msgid "Last commit"
msgstr "Dernière validation"
+msgid "LastPushEvent|You pushed to"
+msgstr ""
+
+msgid "LastPushEvent|at"
+msgstr ""
+
msgid "Learn more in the"
msgstr "En apprendre plus dans le"
@@ -496,9 +570,15 @@ msgstr[1] "Limiter l'affichage au plus à %d évènements"
msgid "Median"
msgstr "Médian"
+msgid "Merge events"
+msgstr ""
+
msgid "MissingSSHKeyWarningLink|add an SSH key"
msgstr "ajouter une clef SSH"
+msgid "More information is available|here"
+msgstr ""
+
msgid "New Issue"
msgid_plural "New Issues"
msgstr[0] "Nouvel incident"
@@ -604,13 +684,13 @@ msgid "OpenedNDaysAgo|Opened"
msgstr "Ouvert"
msgid "Options"
-msgstr "Options"
+msgstr ""
msgid "Owner"
msgstr "Propriétaire"
msgid "Pipeline"
-msgstr "Pipeline"
+msgstr ""
msgid "Pipeline Health"
msgstr "Santé du Pipeline"
@@ -679,7 +759,7 @@ msgid "PipelineSheduleIntervalPattern|Custom"
msgstr "Personnalisé"
msgid "Pipelines"
-msgstr "Pipelines"
+msgstr ""
msgid "Pipelines charts"
msgstr "Graphique des pipelines"
@@ -696,6 +776,9 @@ msgstr "avec l'étape"
msgid "Pipeline|with stages"
msgstr "avec les étapes"
+msgid "Project"
+msgstr ""
+
msgid "Project '%{project_name}' queued for deletion."
msgstr "Projet '%{project_name}' en attente de suppression."
@@ -709,8 +792,10 @@ msgid "Project '%{project_name}' will be deleted."
msgstr "Le projet '%{project_name}' sera supprimé."
msgid "Project access must be granted explicitly to each user."
+msgstr "L’accès au projet doit être explicitement accordé à chaque utilisateur."
+
+msgid "Project details"
msgstr ""
-"L’accès au projet doit être explicitement accordé à chaque utilisateur."
msgid "Project export could not be deleted."
msgstr "L'export du projet n'a pas pu être supprimé."
@@ -718,21 +803,18 @@ msgstr "L'export du projet n'a pas pu être supprimé."
msgid "Project export has been deleted."
msgstr "L'export du projet a été supprimé."
-msgid ""
-"Project export link has expired. Please generate a new export from your "
-"project settings."
-msgstr ""
-"Le lien de l’export du projet a expiré. Merci de générer un nouvel export "
-"depuis les paramètres du projet."
+msgid "Project export link has expired. Please generate a new export from your project settings."
+msgstr "Le lien de l’export du projet a expiré. Merci de générer un nouvel export depuis les paramètres du projet."
msgid "Project export started. A download link will be sent by email."
-msgstr ""
-"L'export du projet a débuté. Un lien de téléchargement sera envoyé par "
-"courriel."
+msgstr "L'export du projet a débuté. Un lien de téléchargement sera envoyé par courriel."
msgid "Project home"
msgstr "Accueil du projet"
+msgid "ProjectActivityRSS|Subscribe"
+msgstr ""
+
msgid "ProjectFeature|Disabled"
msgstr "Désactivé"
@@ -754,6 +836,9 @@ msgstr "Étape"
msgid "ProjectNetworkGraph|Graph"
msgstr "Graphique "
+msgid "Push events"
+msgstr ""
+
msgid "Read more"
msgstr "Lire plus"
@@ -790,9 +875,21 @@ msgstr "Me le rappeler ultérieurement"
msgid "Remove project"
msgstr "Supprimer le projet"
+msgid "Repository"
+msgstr ""
+
msgid "Request Access"
msgstr "Demander l'accès"
+msgid "Reset git storage health information"
+msgstr ""
+
+msgid "Reset health check access token"
+msgstr ""
+
+msgid "Reset runners registration token"
+msgstr ""
+
msgid "Revert this commit"
msgstr "Annuler cette validation"
@@ -817,13 +914,14 @@ msgstr "Sélectionnez le format de l'archive"
msgid "Select a timezone"
msgstr "Sélectionnez un fuseau horaire"
+msgid "Select existing branch"
+msgstr ""
+
msgid "Select target branch"
msgstr "Sélectionnez une branche cible"
msgid "Set a password on your account to pull or push via %{protocol}."
-msgstr ""
-"Définissez un mot de passe pour votre compte pour pouvoir tirer ou pousser "
-"par %{protocol}."
+msgstr "Définissez un mot de passe pour votre compte pour pouvoir tirer ou pousser par %{protocol}."
msgid "Set up CI"
msgstr "Mettre en place l'intégration continue (CI)"
@@ -845,12 +943,18 @@ msgstr[1] "Affichage de %d évènements"
msgid "Source code"
msgstr "Code source"
+msgid "Specify the following URL during the Runner setup:"
+msgstr ""
+
msgid "StarProject|Star"
msgstr "S'abonner"
msgid "Start a %{new_merge_request} with these changes"
msgstr "Créer une %{new_merge_request} avec ces changements"
+msgid "Start the Runner!"
+msgstr ""
+
msgid "Switch branch/tag"
msgstr "Changer de branche / d'étiquette"
@@ -865,67 +969,35 @@ msgstr "Étiquettes"
msgid "Target Branch"
msgstr "Branche cible"
-msgid ""
-"The coding stage shows the time from the first commit to creating the merge "
-"request. The data will automatically be added here once you create your "
-"first merge request."
+msgid "Team"
msgstr ""
-"L’étape de développement montre le temps entre la première validation et la "
-"création de la demande de fusion. Les données seront automatiquement "
-"ajoutées ici une fois que vous aurez créé votre première demande de fusion."
+
+msgid "The coding stage shows the time from the first commit to creating the merge request. The data will automatically be added here once you create your first merge request."
+msgstr "L’étape de développement montre le temps entre la première validation et la création de la demande de fusion. Les données seront automatiquement ajoutées ici une fois que vous aurez créé votre première demande de fusion."
msgid "The collection of events added to the data gathered for that stage."
-msgstr ""
-"L’ensemble d’évènements ajoutés aux données récupérées pour cette étape."
+msgstr "L’ensemble d’évènements ajoutés aux données récupérées pour cette étape."
msgid "The fork relationship has been removed."
msgstr "La relation de fourche a été supprimée."
-msgid ""
-"The issue stage shows the time it takes from creating an issue to assigning "
-"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 ""
-"L'étape des incidents montre le temps nécessaire entre la création d'un "
-"incident et son assignation à un jalon, ou son ajout à une liste d'un "
-"tableau d'incidents. Débutez à créer des incidents pour voir des données "
-"pour cette étape."
+msgid "The issue stage shows the time it takes from creating an issue to assigning 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 "L'étape des incidents montre le temps nécessaire entre la création d'un incident et son assignation à un jalon, ou son ajout à une liste d'un tableau d'incidents. Débutez à créer des incidents pour voir des données pour cette étape."
msgid "The phase of the development lifecycle."
msgstr "Les étapes du cycle de développement."
-msgid ""
-"The pipelines schedule runs pipelines in the future, repeatedly, for "
-"specific branches or tags. Those scheduled pipelines will inherit limited "
-"project access based on their associated user."
-msgstr ""
-"Les pipelines programmés exécutent des pipelines dans le futur, de façon "
-"répétée, pour les branches et étiquettes spécifiées. Ces pipelines "
-"programmés héritent d’un accès partiel au projet basé sur l’utilisateur qui "
-"leurs est associé."
+msgid "The pipelines schedule runs pipelines in the future, repeatedly, for specific branches or tags. Those scheduled pipelines will inherit limited project access based on their associated user."
+msgstr "Les pipelines programmés exécutent des pipelines dans le futur, de façon répétée, pour les branches et étiquettes spécifiées. Ces pipelines programmés héritent d’un accès partiel au projet basé sur l’utilisateur qui leurs est associé."
-msgid ""
-"The planning stage shows the time from the previous step to pushing your "
-"first commit. This time will be added automatically once you push your first "
-"commit."
-msgstr ""
-"L’étape de planification montre le temps entre l’étape précédente et l’envoi "
-"de votre première validation. Ce temps sera automatiquement ajouté quand "
-"vous pousserez votre première validation."
+msgid "The planning stage shows the time from the previous step to pushing your first commit. This time will be added automatically once you push your first commit."
+msgstr "L’étape de planification montre le temps entre l’étape précédente et l’envoi de votre première validation. Ce temps sera automatiquement ajouté quand vous pousserez votre première validation."
-msgid ""
-"The production stage shows the total time it takes between creating an issue "
-"and deploying the code to production. The data will be automatically added "
-"once you have completed the full idea to production cycle."
-msgstr ""
-"L’étape de mise en production montre le temps nécessaire entre la création "
-"d’un incident et le déploiement du code en production. Les données seront "
-"automatiquement ajoutées une fois que vous aurez complété le cycle complet, "
-"depuis l’idée jusqu’à la mise en production."
+msgid "The production stage shows the total time it takes between creating an issue and deploying the code to production. The data will be automatically added once you have completed the full idea to production cycle."
+msgstr "L’étape de mise en production montre le temps nécessaire entre la création d’un incident et le déploiement du code en production. Les données seront automatiquement ajoutées une fois que vous aurez complété le cycle complet, depuis l’idée jusqu’à la mise en production."
msgid "The project can be accessed by any logged in user."
-msgstr ""
-"Votre projet peut être accédé par n’importe quel utilisateur authentifié"
+msgstr "Votre projet peut être accédé par n’importe quel utilisateur authentifié"
msgid "The project can be accessed without any authentication."
msgstr "Votre projet peut être accédé sans aucune authentification."
@@ -933,52 +1005,26 @@ msgstr "Votre projet peut être accédé sans aucune authentification."
msgid "The repository for this project does not exist."
msgstr "Le dépôt pour ce projet n'existe pas."
-msgid ""
-"The review stage shows the time from creating the merge request to merging "
-"it. The data will automatically be added after you merge your first merge "
-"request."
-msgstr ""
-"L’étape d’évaluation montre le temps entre la création de la demande de "
-"fusion et la fusion effective de celle-ci. Ces données seront "
-"automatiquement ajoutées après que vous ayez fusionné votre première demande "
-"de fusion."
+msgid "The review stage shows the time from creating the merge request to merging it. The data will automatically be added after you merge your first merge request."
+msgstr "L’étape d’évaluation montre le temps entre la création de la demande de fusion et la fusion effective de celle-ci. Ces données seront automatiquement ajoutées après que vous ayez fusionné votre première demande de fusion."
-msgid ""
-"The staging stage shows the time between merging the MR and deploying code "
-"to the production environment. The data will be automatically added once you "
-"deploy to production for the first time."
-msgstr ""
-"L’étape de pré-production indique le temps entre la fusion de la DF et le "
-"déploiement du code dans l’environnent de production. Les données seront "
-"automatiquement ajoutées une fois que vous déploierez en production pour la "
-"première fois."
+msgid "The staging stage shows the time between merging the MR and deploying code to the production environment. The data will be automatically added once you deploy to production for the first time."
+msgstr "L’étape de pré-production indique le temps entre la fusion de la DF et le déploiement du code dans l’environnent de production. Les données seront automatiquement ajoutées une fois que vous déploierez en production pour la première fois."
-msgid ""
-"The testing stage shows the time GitLab CI takes to run every pipeline for "
-"the related merge request. The data will automatically be added after your "
-"first pipeline finishes running."
-msgstr ""
-"L’étape de test montre le temps que le CI de GitLab met pour exécuter chaque "
-"pipeline liés à la demande de fusion. Les données seront automatiquement "
-"ajoutées après que votre premier pipeline s’achèvera."
+msgid "The testing stage shows the time GitLab CI takes to run every pipeline for the related merge request. The data will automatically be added after your first pipeline finishes running."
+msgstr "L’étape de test montre le temps que le CI de GitLab met pour exécuter chaque pipeline liés à la demande de fusion. Les données seront automatiquement ajoutées après que votre premier pipeline s’achèvera."
msgid "The time taken by each data entry gathered by that stage."
msgstr "Le temps pris par chaque entrée récoltée durant cette étape."
-msgid ""
-"The value lying at the midpoint of a series of observed values. E.g., "
-"between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 ="
-" 6."
-msgstr ""
-"La valeur située au point médian d’une série de valeur observée. C.à.d., "
-"entre 3, 5, 9, le médian est 5. Entre 3, 5, 7, 8, le médian est (5+7)/2 = 6."
+msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
+msgstr "La valeur située au point médian d’une série de valeur observée. C.à.d., entre 3, 5, 9, le médian est 5. Entre 3, 5, 7, 8, le médian est (5+7)/2 = 6."
-msgid ""
-"This means you can not push code until you create an empty repository or "
-"import existing one."
+msgid "There are problems accessing Git storage: "
msgstr ""
-"Cela signifie que vous ne pouvez pas pousser du code tant que vous ne créez "
-"pas un dépôt vide, ou importez une dépôt existant."
+
+msgid "This means you can not push code until you create an empty repository or import existing one."
+msgstr "Cela signifie que vous ne pouvez pas pousser du code tant que vous ne créez pas un dépôt vide, ou importez une dépôt existant."
msgid "Time before an issue gets scheduled"
msgstr "Temps avant qu’un incident ne soit planifié"
@@ -1146,6 +1192,9 @@ msgstr "Téléverser un fichier"
msgid "UploadLink|click to upload"
msgstr "Cliquez pour envoyer"
+msgid "Use the following registration token during setup:"
+msgstr ""
+
msgid "Use your global notification setting"
msgstr "Utiliser vos paramètres de notification globaux"
@@ -1165,9 +1214,7 @@ msgid "VisibilityLevel|Unknown"
msgstr "Inconnu"
msgid "Want to see the data? Please ask an administrator for access."
-msgstr ""
-"Vous voulez voir les données ? Merci de contacter un administrateur pour en "
-"obtenir l’accès."
+msgstr "Vous voulez voir les données ? Merci de contacter un administrateur pour en obtenir l’accès."
msgid "We don't have enough data to show this stage."
msgstr "Nous n'avons pas suffisamment de données pour afficher cette étape."
@@ -1181,19 +1228,11 @@ msgstr "Vous êtes sur le point de supprimer %{group_name}. Les groupes supprimÃ
msgid "You are going to remove %{project_name_with_namespace}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr "Vous êtes sur le point de supprimer %{project_name_with_namespace}. Les projets supprimés NE PEUVENT PAS être restaurés ! Êtes vous ABSOLUMENT sûr ?"
-msgid ""
-"You are going to remove the fork relationship to source project "
-"%{forked_from_project}. Are you ABSOLUTELY sure?"
-msgstr ""
-"Vous allez supprimer la relation de fourche avec le projet source "
-"%{forked_from_project}. Êtes-vous VRAIMENT sûr."
+msgid "You are going to remove the fork relationship to source project %{forked_from_project}. Are you ABSOLUTELY sure?"
+msgstr "Vous allez supprimer la relation de fourche avec le projet source %{forked_from_project}. Êtes-vous VRAIMENT sûr."
-msgid ""
-"You are going to transfer %{project_name_with_namespace} to another owner. "
-"Are you ABSOLUTELY sure?"
-msgstr ""
-"Vous allez transférer %{project_name_with_namespace} à un nouveau "
-"propriétaire. Êtes vous VRAIMENT sûr ?"
+msgid "You are going to transfer %{project_name_with_namespace} to another owner. Are you ABSOLUTELY sure?"
+msgstr "Vous allez transférer %{project_name_with_namespace} à un nouveau propriétaire. Êtes vous VRAIMENT sûr ?"
msgid "You can only add files when you are on a branch"
msgstr "Vous ne pouvez ajouter de fichier que dans une branche"
@@ -1211,39 +1250,22 @@ msgid "You will not get any notifications via email"
msgstr "Vous ne recevrez aucune notification par courriel"
msgid "You will only receive notifications for the events you choose"
-msgstr ""
-"Vous ne recevrez de notification que pour les évènements que vous aurez "
-"choisis"
+msgstr "Vous ne recevrez de notification que pour les évènements que vous aurez choisis"
-msgid ""
-"You will only receive notifications for threads you have participated in"
-msgstr ""
-"Vous ne recevrez de notification que pour les sujets auxquels vous avez "
-"participé"
+msgid "You will only receive notifications for threads you have participated in"
+msgstr "Vous ne recevrez de notification que pour les sujets auxquels vous avez participé"
msgid "You will receive notifications for any activity"
msgstr "Vous recevrez des notifications pour n’importe quelles activités"
-msgid ""
-"You will receive notifications only for comments in which you were "
-"@mentioned"
-msgstr ""
-"Vous ne recevrez de notifications que pour les commentaires où vous êtes "
-"@mentionné"
+msgid "You will receive notifications only for comments in which you were @mentioned"
+msgstr "Vous ne recevrez de notifications que pour les commentaires où vous êtes @mentionné"
-msgid ""
-"You won't be able to pull or push project code via %{protocol} until you "
-"%{set_password_link} on your account"
-msgstr ""
-"Vous ne pourrez pas récupérer ou pousser de code par %{protocol} tant que "
-"vous n'aurez pas %{set_password_link} pour votre compte"
+msgid "You won't be able to pull or push project code via %{protocol} until you %{set_password_link} on your account"
+msgstr "Vous ne pourrez pas récupérer ou pousser de code par %{protocol} tant que vous n'aurez pas %{set_password_link} pour votre compte"
-msgid ""
-"You won't be able to pull or push project code via SSH until you "
-"%{add_ssh_key_link} to your profile"
-msgstr ""
-"Vous ne pourrez pas récupérer ou pousser de code par SSH tant que vous "
-"n’aurez pas %{add_ssh_key_link} dans votre profil"
+msgid "You won't be able to pull or push project code via SSH until you %{add_ssh_key_link} to your profile"
+msgstr "Vous ne pourrez pas récupérer ou pousser de code par SSH tant que vous n’aurez pas %{add_ssh_key_link} dans votre profil"
msgid "Your name"
msgstr "Votre nom"
@@ -1261,6 +1283,5 @@ msgstr "courriels de notification"
msgid "parent"
msgid_plural "parents"
-msgstr[0] "parent"
-msgstr[1] "parents"
-
+msgstr[0] ""
+msgstr[1] "" \ No newline at end of file
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index a4a3ef6c42c..5a1db208d5a 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -8,8 +8,8 @@ msgid ""
msgstr ""
"Project-Id-Version: gitlab 1.0.0\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2017-08-18 14:15+0530\n"
-"PO-Revision-Date: 2017-08-18 14:15+0530\n"
+"POT-Creation-Date: 2017-08-24 09:29+0200\n"
+"PO-Revision-Date: 2017-08-24 09:29+0200\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
@@ -517,15 +517,6 @@ msgstr ""
msgid "Issue events"
msgstr ""
-msgid "Jobs for last month"
-msgstr ""
-
-msgid "Jobs for last week"
-msgstr ""
-
-msgid "Jobs for last year"
-msgstr ""
-
msgid "LFSStatus|Disabled"
msgstr ""
@@ -766,6 +757,15 @@ msgstr ""
msgid "Pipelines charts"
msgstr ""
+msgid "Pipelines for last month"
+msgstr ""
+
+msgid "Pipelines for last week"
+msgstr ""
+
+msgid "Pipelines for last year"
+msgstr ""
+
msgid "Pipeline|all"
msgstr ""
diff --git a/locale/it/gitlab.po b/locale/it/gitlab.po
index e719a3988e3..7b8bea46e26 100644
--- a/locale/it/gitlab.po
+++ b/locale/it/gitlab.po
@@ -1,42 +1,55 @@
-# Huang Tao <htve@outlook.com>, 2017. #zanata
-# Paolo Falomo <info@paolofalomo.it>, 2017. #zanata
msgid ""
msgstr ""
-"Project-Id-Version: gitlab 1.0.0\n"
+"Project-Id-Version: gitlab-ee\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2017-07-13 12:07-0500\n"
+"POT-Creation-Date: 2017-08-18 14:15+0530\n"
+"PO-Revision-Date: 2017-08-23 10:25-0400\n"
+"Last-Translator: gitlab <mbartlett+crowdin@gitlab.com>\n"
+"Language-Team: Italian\n"
+"Language: it_IT\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"Language-Team: Italian (https://translate.zanata.org/project/view/GitLab)\n"
-"PO-Revision-Date: 2017-08-07 10:15-0400\n"
-"Last-Translator: Paolo Falomo <info@paolofalomo.it>\n"
-"Language: it\n"
-"X-Generator: Zanata 3.9.6\n"
-"Plural-Forms: nplurals=2; plural=(n != 1)\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Generator: crowdin.com\n"
+"X-Crowdin-Project: gitlab-ee\n"
+"X-Crowdin-Language: it\n"
+"X-Crowdin-File: /master/locale/gitlab.pot\n"
-msgid "%s additional commit has been omitted to prevent performance issues."
-msgid_plural ""
-"%s additional commits have been omitted to prevent performance issues."
+msgid "%d commit"
+msgid_plural "%d commits"
msgstr[0] ""
-"%s commit aggiuntivo è stato omesso per evitare degradi di prestazioni negli "
-"issues."
msgstr[1] ""
-"%s commit aggiuntivi sono stati omessi per evitare degradi di prestazioni "
-"negli issues."
-msgid "%d commit"
-msgid_plural "%d commits"
-msgstr[0] "%d commit"
-msgstr[1] "%d commit"
+msgid "%s additional commit has been omitted to prevent performance issues."
+msgid_plural "%s additional commits have been omitted to prevent performance issues."
+msgstr[0] "%s commit aggiuntivo è stato omesso per evitare degradi di prestazioni negli issues."
+msgstr[1] "%s commit aggiuntivi sono stati omessi per evitare degradi di prestazioni negli issues."
msgid "%{commit_author_link} committed %{commit_timeago}"
msgstr "%{commit_author_link} ha committato %{commit_timeago}"
+msgid "%{number_of_failures} of %{maximum_failures} failures. GitLab will allow access on the next attempt."
+msgstr ""
+
+msgid "%{number_of_failures} of %{maximum_failures} failures. GitLab will block access for %{number_of_seconds} seconds."
+msgstr ""
+
+msgid "%{number_of_failures} of %{maximum_failures} failures. GitLab will not retry automatically. Reset storage information when the problem is resolved."
+msgstr ""
+
+msgid "%{storage_name}: failed storage access attempt on host:"
+msgid_plural "%{storage_name}: %{failed_attempts} failed storage access attempts:"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "(checkout the %{link} for information on how to install it)."
+msgstr ""
+
msgid "1 pipeline"
msgid_plural "%d pipelines"
-msgstr[0] "1 pipeline"
-msgstr[1] "%d pipeline"
+msgstr[0] ""
+msgstr[1] ""
msgid "A collection of graphs regarding Continuous Integration"
msgstr "Un insieme di grafici riguardo la Continuous Integration"
@@ -44,6 +57,9 @@ msgstr "Un insieme di grafici riguardo la Continuous Integration"
msgid "About auto deploy"
msgstr "Riguardo il rilascio automatico"
+msgid "Access to failing storages has been temporarily disabled to allow the mount to recover. Reset storage information after the issue has been resolved to allow access again."
+msgstr ""
+
msgid "Active"
msgstr "Attivo"
@@ -60,36 +76,42 @@ msgid "Add License"
msgstr "Aggiungi Licenza"
msgid "Add an SSH key to your profile to pull or push via SSH."
-msgstr ""
-"Aggiungi una chiave SSH al tuo profilo per eseguire pull o push tramite SSH"
+msgstr "Aggiungi una chiave SSH al tuo profilo per eseguire pull o push tramite SSH"
msgid "Add new directory"
msgstr "Aggiungi una directory (cartella)"
+msgid "All"
+msgstr ""
+
msgid "Archived project! Repository is read-only"
msgstr "Progetto archiviato! La Repository è sola-lettura"
msgid "Are you sure you want to delete this pipeline schedule?"
msgstr "Sei sicuro di voler cancellare questa pipeline programmata?"
-msgid "Attach a file by drag &amp; drop or %{upload_link}"
+msgid "Are you sure you want to discard your changes?"
msgstr ""
-"Aggiungi un file tramite trascina &amp; rilascia ( drag &amp; drop) o "
-"%{upload_link}"
+
+msgid "Are you sure you want to reset registration token?"
+msgstr ""
+
+msgid "Are you sure you want to reset the health check token?"
+msgstr ""
+
+msgid "Are you sure?"
+msgstr ""
+
+msgid "Attach a file by drag &amp; drop or %{upload_link}"
+msgstr "Aggiungi un file tramite trascina &amp; rilascia ( drag &amp; drop) o %{upload_link}"
msgid "Branch"
msgid_plural "Branches"
-msgstr[0] "Branch"
-msgstr[1] "Branches"
+msgstr[0] ""
+msgstr[1] ""
-msgid ""
-"Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, "
-"choose a GitLab CI Yaml template and commit your changes. "
-"%{link_to_autodeploy_doc}"
-msgstr ""
-"La branch <strong>%{branch_name}</strong> è stata creata. Per impostare un "
-"rilascio automatico scegli un template CI di Gitlab e committa le tue "
-"modifiche %{link_to_autodeploy_doc}"
+msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
+msgstr "La branch <strong>%{branch_name}</strong> è stata creata. Per impostare un rilascio automatico scegli un template CI di Gitlab e committa le tue modifiche %{link_to_autodeploy_doc}"
msgid "BranchSwitcherPlaceholder|Search branches"
msgstr "Cerca branches"
@@ -98,7 +120,7 @@ msgid "BranchSwitcherTitle|Switch branch"
msgstr "Cambia branch"
msgid "Branches"
-msgstr "Branches"
+msgstr ""
msgid "Browse Directory"
msgstr "Naviga direttori"
@@ -121,6 +143,9 @@ msgstr "Configurazione CI (Integrazione Continua)"
msgid "Cancel"
msgstr "Cancella"
+msgid "Cancel edit"
+msgstr ""
+
msgid "ChangeTypeActionLabel|Pick into branch"
msgstr "Preleva nella branch"
@@ -134,13 +159,13 @@ msgid "ChangeTypeAction|Revert"
msgstr "Ripristina"
msgid "Changelog"
-msgstr "Changelog"
+msgstr ""
msgid "Charts"
msgstr "Grafici"
msgid "Cherry-pick this commit"
-msgstr "Cherry-pick this commit"
+msgstr ""
msgid "Cherry-pick this merge request"
msgstr "Cherry-pick questa richiesta di merge"
@@ -199,10 +224,13 @@ msgstr "saltata"
msgid "CiStatus|running"
msgstr "in corso"
+msgid "Comments"
+msgstr ""
+
msgid "Commit"
msgid_plural "Commits"
-msgstr[0] "Commit"
-msgstr[1] "Commits"
+msgstr[0] ""
+msgstr[1] ""
msgid "Commit duration in minutes for last 30 commits"
msgstr "Durata del commit (in minuti) per gli ultimi 30 commit"
@@ -217,7 +245,7 @@ msgid "CommitMessage|Add %{file_name}"
msgstr "Aggiungi %{file_name}"
msgid "Commits"
-msgstr "Commits"
+msgstr ""
msgid "Commits feed"
msgstr "Feed dei Commits"
@@ -246,12 +274,11 @@ 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}."
+msgid "Create a new branch"
msgstr ""
-"Creare un token di accesso sul tuo account per eseguire pull o push tramite "
-"%{protocol}"
+
+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"
@@ -275,7 +302,7 @@ msgid "CreateTokenToCloneLink|create a personal access token"
msgstr "Crea token d'accesso personale"
msgid "Cron Timezone"
-msgstr "Cron Timezone"
+msgstr ""
msgid "Cron syntax"
msgstr "Sintassi Cron"
@@ -283,24 +310,14 @@ msgstr "Sintassi Cron"
msgid "Custom notification events"
msgstr "Eventi-Notifica personalizzati"
-msgid ""
-"Custom notification levels are the same as participating levels. With custom "
-"notification levels you will also receive notifications for select events. "
-"To find out more, check out %{notification_link}."
-msgstr ""
-"I livelli di notifica personalizzati sono uguali a quelli di partecipazione. "
-"Con i livelli di notifica personalizzati riceverai anche notifiche per gli "
-"eventi da te scelti %{notification_link}."
+msgid "Custom notification levels are the same as participating levels. With custom notification levels you will also receive notifications for select events. To find out more, check out %{notification_link}."
+msgstr "I livelli di notifica personalizzati sono uguali a quelli di partecipazione. Con i livelli di notifica personalizzati riceverai anche notifiche per gli eventi da te scelti %{notification_link}."
msgid "Cycle Analytics"
msgstr "Statistiche Cicliche"
-msgid ""
-"Cycle Analytics gives an overview of how much time it takes to go from idea "
-"to production in your project."
-msgstr ""
-"L'Analisi Ciclica fornisce una panoramica sul tempo che trascorre tra l'idea "
-"ed il rilascio in produzione del tuo progetto"
+msgid "Cycle Analytics gives an overview of how much time it takes to go from idea to production in your project."
+msgstr "L'Analisi Ciclica fornisce una panoramica sul tempo che trascorre tra l'idea ed il rilascio in produzione del tuo progetto"
msgid "CycleAnalyticsStage|Code"
msgstr "Codice"
@@ -337,9 +354,15 @@ msgstr[1] "Rilasci"
msgid "Description"
msgstr "Descrizione"
+msgid "Details"
+msgstr ""
+
msgid "Directory name"
msgstr "Nome cartella"
+msgid "Discard changes"
+msgstr ""
+
msgid "Don't show again"
msgstr "Non mostrare più"
@@ -376,6 +399,24 @@ msgstr "Modifica"
msgid "Edit Pipeline Schedule %{id}"
msgstr "Cambia programmazione della pipeline %{id}"
+msgid "EventFilterBy|Filter by all"
+msgstr ""
+
+msgid "EventFilterBy|Filter by comments"
+msgstr ""
+
+msgid "EventFilterBy|Filter by issue events"
+msgstr ""
+
+msgid "EventFilterBy|Filter by merge events"
+msgstr ""
+
+msgid "EventFilterBy|Filter by push events"
+msgstr ""
+
+msgid "EventFilterBy|Filter by team"
+msgstr ""
+
msgid "Every day (at 4:00am)"
msgstr "Ogni giorno (alle 4 del mattino)"
@@ -392,7 +433,7 @@ msgid "Failed to remove the pipeline schedule"
msgstr "Impossibile rimuovere la pipeline pianificata"
msgid "Files"
-msgstr "Files"
+msgstr ""
msgid "Filter by commit message"
msgstr "Filtra per messaggio di commit"
@@ -411,8 +452,8 @@ msgstr "Push di"
msgid "Fork"
msgid_plural "Forks"
-msgstr[0] "Fork"
-msgstr[1] "Forks"
+msgstr[0] ""
+msgstr[1] ""
msgid "ForkedFromProjectPath|Forked from"
msgstr "Fork da"
@@ -421,9 +462,13 @@ msgid "From issue creation until deploy to production"
msgstr "Dalla creazione di un issue fino al rilascio in produzione"
msgid "From merge request merge until deploy to production"
+msgstr "Dalla richiesta di merge fino effettua il merge fino al rilascio in produzione"
+
+msgid "Git storage health information has been reset"
+msgstr ""
+
+msgid "GitLab Runner section"
msgstr ""
-"Dalla richiesta di merge fino effettua il merge fino al rilascio in "
-"produzione"
msgid "Go to your fork"
msgstr "Vai il tuo fork"
@@ -431,8 +476,26 @@ msgstr "Vai il tuo fork"
msgid "GoToYourFork|Fork"
msgstr "Fork"
+msgid "Health Check"
+msgstr ""
+
+msgid "Health information can be retrieved from the following endpoints. More information is available"
+msgstr ""
+
+msgid "HealthCheck|Access token is"
+msgstr ""
+
+msgid "HealthCheck|Healthy"
+msgstr ""
+
+msgid "HealthCheck|No Health Problems Detected"
+msgstr ""
+
+msgid "HealthCheck|Unhealthy"
+msgstr ""
+
msgid "Home"
-msgstr "Home"
+msgstr ""
msgid "Housekeeping successfully started"
msgstr "Housekeeping iniziato con successo"
@@ -440,12 +503,18 @@ msgstr "Housekeeping iniziato con successo"
msgid "Import repository"
msgstr "Importa repository"
+msgid "Install a Runner compatible with GitLab CI"
+msgstr ""
+
msgid "Interval Pattern"
msgstr "Intervallo di Pattern"
msgid "Introducing Cycle Analytics"
msgstr "Introduzione delle Analisi Cicliche"
+msgid "Issue events"
+msgstr ""
+
msgid "Jobs for last month"
msgstr "Jobs dell'ultimo mese"
@@ -475,6 +544,12 @@ msgstr "Ultimo Aggiornamento"
msgid "Last commit"
msgstr "Ultimo Commit"
+msgid "LastPushEvent|You pushed to"
+msgstr ""
+
+msgid "LastPushEvent|at"
+msgstr ""
+
msgid "Learn more in the"
msgstr "Leggi di più su"
@@ -495,9 +570,15 @@ msgstr[1] "Limita visualizzazione %d di eventi"
msgid "Median"
msgstr "Mediano"
+msgid "Merge events"
+msgstr ""
+
msgid "MissingSSHKeyWarningLink|add an SSH key"
msgstr "aggiungi una chiave SSH"
+msgid "More information is available|here"
+msgstr ""
+
msgid "New Issue"
msgid_plural "New Issues"
msgstr[0] "Nuovo Issue"
@@ -606,10 +687,10 @@ msgid "Options"
msgstr "Opzioni"
msgid "Owner"
-msgstr "Owner"
+msgstr ""
msgid "Pipeline"
-msgstr "Pipeline"
+msgstr ""
msgid "Pipeline Health"
msgstr "Stato della Pipeline"
@@ -695,6 +776,9 @@ msgstr "con stadio"
msgid "Pipeline|with stages"
msgstr "con più stadi"
+msgid "Project"
+msgstr ""
+
msgid "Project '%{project_name}' queued for deletion."
msgstr "Il Progetto '%{project_name}' in coda di eliminazione."
@@ -710,27 +794,27 @@ msgstr "Il Progetto '%{project_name}' verrà eliminato"
msgid "Project access must be granted explicitly to each user."
msgstr "L'accesso al progetto dev'esser fornito esplicitamente ad ogni utente"
+msgid "Project details"
+msgstr ""
+
msgid "Project export could not be deleted."
msgstr "L'esportazione del progetto non può essere eliminata."
msgid "Project export has been deleted."
msgstr "L'esportazione del progetto è stata eliminata."
-msgid ""
-"Project export link has expired. Please generate a new export from your "
-"project settings."
-msgstr ""
-"Il link d'esportazione del progetto è scaduto. Genera una nuova esportazione "
-"dalle impostazioni del tuo progetto."
+msgid "Project export link has expired. Please generate a new export from your project settings."
+msgstr "Il link d'esportazione del progetto è scaduto. Genera una nuova esportazione dalle impostazioni del tuo progetto."
msgid "Project export started. A download link will be sent by email."
-msgstr ""
-"Esportazione del progetto iniziata. Un link di download sarà inviato via "
-"email."
+msgstr "Esportazione del progetto iniziata. Un link di download sarà inviato via email."
msgid "Project home"
msgstr "Home di progetto"
+msgid "ProjectActivityRSS|Subscribe"
+msgstr ""
+
msgid "ProjectFeature|Disabled"
msgstr "Disabilitato"
@@ -752,6 +836,9 @@ msgstr "Stadio"
msgid "ProjectNetworkGraph|Graph"
msgstr "Grafico"
+msgid "Push events"
+msgstr ""
+
msgid "Read more"
msgstr "Vedi altro"
@@ -788,9 +875,21 @@ msgstr "Ricordamelo più tardi"
msgid "Remove project"
msgstr "Rimuovi progetto"
+msgid "Repository"
+msgstr ""
+
msgid "Request Access"
msgstr "Richiedi accesso"
+msgid "Reset git storage health information"
+msgstr ""
+
+msgid "Reset health check access token"
+msgstr ""
+
+msgid "Reset runners registration token"
+msgstr ""
+
msgid "Revert this commit"
msgstr "Ripristina questo commit"
@@ -815,13 +914,14 @@ msgstr "Seleziona formato d'archivio"
msgid "Select a timezone"
msgstr "Seleziona una timezone"
+msgid "Select existing branch"
+msgstr ""
+
msgid "Select target branch"
msgstr "Seleziona una branch di destinazione"
msgid "Set a password on your account to pull or push via %{protocol}."
-msgstr ""
-"Establezca una contraseña en su cuenta para actualizar o enviar a través de "
-"%{protocol}."
+msgstr "Establezca una contraseña en su cuenta para actualizar o enviar a través de %{protocol}."
msgid "Set up CI"
msgstr "Configura CI"
@@ -843,34 +943,37 @@ msgstr[1] "Visualizza %d eventi"
msgid "Source code"
msgstr "Codice Sorgente"
+msgid "Specify the following URL during the Runner setup:"
+msgstr ""
+
msgid "StarProject|Star"
msgstr "Star"
msgid "Start a %{new_merge_request} with these changes"
msgstr "inizia una %{new_merge_request} con queste modifiche"
+msgid "Start the Runner!"
+msgstr ""
+
msgid "Switch branch/tag"
msgstr "Cambia branch/tag"
msgid "Tag"
msgid_plural "Tags"
-msgstr[0] "Tag"
-msgstr[1] "Tags"
+msgstr[0] ""
+msgstr[1] ""
msgid "Tags"
-msgstr "Tags"
+msgstr ""
msgid "Target Branch"
msgstr "Branch di destinazione"
-msgid ""
-"The coding stage shows the time from the first commit to creating the merge "
-"request. The data will automatically be added here once you create your "
-"first merge request."
+msgid "Team"
msgstr ""
-"Lo stadio di programmazione mostra il tempo trascorso dal primo commit alla "
-"creazione di una richiesta di merge (MR). I dati saranno aggiunti una volta "
-"che avrai creato la prima richiesta di merge."
+
+msgid "The coding stage shows the time from the first commit to creating the merge request. The data will automatically be added here once you create your first merge request."
+msgstr "Lo stadio di programmazione mostra il tempo trascorso dal primo commit alla creazione di una richiesta di merge (MR). I dati saranno aggiunti una volta che avrai creato la prima richiesta di merge."
msgid "The collection of events added to the data gathered for that stage."
msgstr "L'insieme di eventi aggiunti ai dati raccolti per quello stadio."
@@ -878,102 +981,50 @@ msgstr "L'insieme di eventi aggiunti ai dati raccolti per quello stadio."
msgid "The fork relationship has been removed."
msgstr "La relazione del fork è stata rimossa"
-msgid ""
-"The issue stage shows the time it takes from creating an issue to assigning "
-"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 ""
-"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 issue stage shows the time it takes from creating an issue to assigning 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 "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."
-msgid ""
-"The pipelines schedule runs pipelines in the future, repeatedly, for "
-"specific branches or tags. Those scheduled pipelines will inherit limited "
-"project access based on their associated user."
-msgstr ""
-"Le pipelines pianificate vengono eseguite nel futuro, ripetitivamente, per "
-"specifici tag o branch ed ereditano restrizioni di progetto basate "
-"sull'utente ad esse associato."
+msgid "The pipelines schedule runs pipelines in the future, repeatedly, for specific branches or tags. Those scheduled pipelines will inherit limited project access based on their associated user."
+msgstr "Le pipelines pianificate vengono eseguite nel futuro, ripetitivamente, per specifici tag o branch ed ereditano restrizioni di progetto basate sull'utente ad esse associato."
-msgid ""
-"The planning stage shows the time from the previous step to pushing your "
-"first commit. This time will be added automatically once you push your first "
-"commit."
-msgstr ""
-"Lo stadio di pianificazione mostra il tempo trascorso dal primo commit al "
-"suo step precedente. Questo periodo sarà disponibile automaticamente nel "
-"momento in cui farai il primo commit."
+msgid "The planning stage shows the time from the previous step to pushing your first commit. This time will be added automatically once you push your first commit."
+msgstr "Lo stadio di pianificazione mostra il tempo trascorso dal primo commit al suo step precedente. Questo periodo sarà disponibile automaticamente nel momento in cui farai il primo commit."
-msgid ""
-"The production stage shows the total time it takes between creating an issue "
-"and deploying the code to production. The data will be automatically added "
-"once you have completed the full idea to production cycle."
-msgstr ""
-"Lo stadio di produzione mostra il tempo totale che trascorre tra la "
-"creazione di un issue il suo rilascio (inteso come codice) in produzione. "
-"Questo dato sarà disponibile automaticamente nel momento in cui avrai "
-"completato l'intero processo ideale del ciclo di produzione"
+msgid "The production stage shows the total time it takes between creating an issue and deploying the code to production. The data will be automatically added once you have completed the full idea to production cycle."
+msgstr "Lo stadio di produzione mostra il tempo totale che trascorre tra la creazione di un issue il suo rilascio (inteso come codice) in produzione. Questo dato sarà disponibile automaticamente nel momento in cui avrai completato l'intero processo ideale del ciclo di produzione"
msgid "The project can be accessed by any logged in user."
msgstr "Qualunque utente autenticato può accedere a questo progetto."
msgid "The project can be accessed without any authentication."
-msgstr ""
-"Chiunque può accedere a questo progetto (senza alcuna autenticazione)."
+msgstr "Chiunque può accedere a questo progetto (senza alcuna autenticazione)."
msgid "The repository for this project does not exist."
msgstr "La repository di questo progetto non esiste."
-msgid ""
-"The review stage shows the time from creating the merge request to merging "
-"it. The data will automatically be added after you merge your first merge "
-"request."
-msgstr ""
-"Lo stadio di revisione mostra il tempo tra una richiesta di merge al suo "
-"svolgimento effettivo. Questo dato sarà disponibile appena avrai completato "
-"una MR (Merger Request)"
+msgid "The review stage shows the time from creating the merge request to merging it. The data will automatically be added after you merge your first merge request."
+msgstr "Lo stadio di revisione mostra il tempo tra una richiesta di merge al suo svolgimento effettivo. Questo dato sarà disponibile appena avrai completato una MR (Merger Request)"
-msgid ""
-"The staging stage shows the time between merging the MR and deploying code "
-"to the production environment. The data will be automatically added once you "
-"deploy to production for the first time."
-msgstr ""
-"Lo stadio di pre-rilascio mostra il tempo che trascorre da una MR (Richiesta "
-"di Merge) completata al suo rilascio in ambiente di produzione. Questa "
-"informazione sarà disponibile dal tuo primo rilascio in produzione"
+msgid "The staging stage shows the time between merging the MR and deploying code to the production environment. The data will be automatically added once you deploy to production for the first time."
+msgstr "Lo stadio di pre-rilascio mostra il tempo che trascorre da una MR (Richiesta di Merge) completata al suo rilascio in ambiente di produzione. Questa informazione sarà disponibile dal tuo primo rilascio in produzione"
-msgid ""
-"The testing stage shows the time GitLab CI takes to run every pipeline for "
-"the related merge request. The data will automatically be added after your "
-"first pipeline finishes running."
-msgstr ""
-"Lo stadio di test mostra il tempo che ogni Pipeline impiega per essere "
-"eseguita in ogni Richiesta di Merge correlata. L'informazione sarà "
-"disponibile automaticamente quando la tua prima Pipeline avrà finito d'esser "
-"eseguita."
+msgid "The testing stage shows the time GitLab CI takes to run every pipeline for the related merge request. The data will automatically be added after your first pipeline finishes running."
+msgstr "Lo stadio di test mostra il tempo che ogni Pipeline impiega per essere eseguita in ogni Richiesta di Merge correlata. L'informazione sarà disponibile automaticamente quando la tua prima Pipeline avrà finito d'esser eseguita."
msgid "The time taken by each data entry gathered by that stage."
-msgstr ""
-"Il tempo aggregato relativo eventi/data entry raccolto in quello stadio."
+msgstr "Il tempo aggregato relativo eventi/data entry raccolto in quello stadio."
-msgid ""
-"The value lying at the midpoint of a series of observed values. E.g., "
-"between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 ="
-" 6."
-msgstr ""
-"Il valore falsato nel mezzo di una serie di dati osservati. ES: tra 3,5,9 il "
-"mediano è 5. Tra 3,5,7,8 il mediano è (5+7)/2 quindi 6."
+msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
+msgstr "Il valore falsato nel mezzo di una serie di dati osservati. ES: tra 3,5,9 il mediano è 5. Tra 3,5,7,8 il mediano è (5+7)/2 quindi 6."
-msgid ""
-"This means you can not push code until you create an empty repository or "
-"import existing one."
+msgid "There are problems accessing Git storage: "
msgstr ""
-"Questo significa che non è possibile effettuare push di codice fino a che "
-"non crei una repository vuota o ne importi una esistente"
+
+msgid "This means you can not push code until you create an empty repository or import existing one."
+msgstr "Questo significa che non è possibile effettuare push di codice fino a che non crei una repository vuota o ne importi una esistente"
msgid "Time before an issue gets scheduled"
msgstr "Il tempo che impiega un issue per esser pianificato"
@@ -1130,7 +1181,7 @@ msgid "Total test time for all commits/merges"
msgstr "Tempo totale di test per tutti i commits/merges"
msgid "Unstar"
-msgstr "Unstar"
+msgstr ""
msgid "Upload New File"
msgstr "Carica un nuovo file"
@@ -1141,6 +1192,9 @@ msgstr "Carica file"
msgid "UploadLink|click to upload"
msgstr "clicca per caricare"
+msgid "Use the following registration token during setup:"
+msgstr ""
+
msgid "Use your global notification setting"
msgstr "Usa le tue impostazioni globali "
@@ -1160,8 +1214,7 @@ msgid "VisibilityLevel|Unknown"
msgstr "Sconosciuto"
msgid "Want to see the data? Please ask an administrator for access."
-msgstr ""
-"Vuoi visualizzare i dati? Richiedi l'accesso ad un amministratore, grazie."
+msgstr "Vuoi visualizzare i dati? Richiedi l'accesso ad un amministratore, grazie."
msgid "We don't have enough data to show this stage."
msgstr "Non ci sono sufficienti dati da mostrare su questo stadio"
@@ -1175,19 +1228,11 @@ msgstr "Stai per rimuovere il gruppo %{group_name}. I gruppi rimossi NON POSSONO
msgid "You are going to remove %{project_name_with_namespace}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr "Stai per rimuovere %{project_name_with_namespace}. I progetti rimossi NON POSSONO essere ripristinati! Sei assolutamente sicuro?"
-msgid ""
-"You are going to remove the fork relationship to source project "
-"%{forked_from_project}. Are you ABSOLUTELY sure?"
-msgstr ""
-"Stai per rimuovere la relazione con il progetto sorgente "
-"%{forked_from_project}. Sei ASSOLUTAMENTE sicuro?"
+msgid "You are going to remove the fork relationship to source project %{forked_from_project}. Are you ABSOLUTELY sure?"
+msgstr "Stai per rimuovere la relazione con il progetto sorgente %{forked_from_project}. Sei ASSOLUTAMENTE sicuro?"
-msgid ""
-"You are going to transfer %{project_name_with_namespace} to another owner. "
-"Are you ABSOLUTELY sure?"
-msgstr ""
-"Stai per trasferire %{project_name_with_namespace} ad un altro owner. Sei "
-"ASSOLUTAMENTE sicuro?"
+msgid "You are going to transfer %{project_name_with_namespace} to another owner. Are you ABSOLUTELY sure?"
+msgstr "Stai per trasferire %{project_name_with_namespace} ad un altro owner. Sei ASSOLUTAMENTE sicuro?"
msgid "You can only add files when you are on a branch"
msgstr "Puoi aggiungere files solo quando sei in una branch"
@@ -1207,31 +1252,20 @@ msgstr "Non riceverai alcuna notifica via email"
msgid "You will only receive notifications for the events you choose"
msgstr "Riceverai notifiche solo per gli eventi che hai scelto"
-msgid ""
-"You will only receive notifications for threads you have participated in"
+msgid "You will only receive notifications for threads you have participated in"
msgstr "Riceverai notifiche solo per i threads a cui hai partecipato"
msgid "You will receive notifications for any activity"
msgstr "Riceverai notifiche per ogni attività"
-msgid ""
-"You will receive notifications only for comments in which you were "
-"@mentioned"
+msgid "You will receive notifications only for comments in which you were @mentioned"
msgstr "Riceverai notifiche solo per i commenti ai quale sei stato menzionato"
-msgid ""
-"You won't be able to pull or push project code via %{protocol} until you "
-"%{set_password_link} on your account"
-msgstr ""
-"Non sarai in grado di eseguire pull o push di codice tramite %{protocol} "
-"fino a che %{set_password_link} nel tuo account."
+msgid "You won't be able to pull or push project code via %{protocol} until you %{set_password_link} on your account"
+msgstr "Non sarai in grado di eseguire pull o push di codice tramite %{protocol} fino a che %{set_password_link} nel tuo account."
-msgid ""
-"You won't be able to pull or push project code via SSH until you "
-"%{add_ssh_key_link} to your profile"
-msgstr ""
-"Non sarai in grado di effettuare push o pull tramite SSH fino a che "
-"%{add_ssh_key_link} al tuo profilo"
+msgid "You won't be able to pull or push project code via SSH until you %{add_ssh_key_link} to your profile"
+msgstr "Non sarai in grado di effettuare push o pull tramite SSH fino a che %{add_ssh_key_link} al tuo profilo"
msgid "Your name"
msgstr "Il tuo nome"
@@ -1249,6 +1283,5 @@ msgstr "Notifiche via email"
msgid "parent"
msgid_plural "parents"
-msgstr[0] "parent"
-msgstr[1] "parents"
-
+msgstr[0] ""
+msgstr[1] "" \ No newline at end of file
diff --git a/locale/ja/gitlab.po b/locale/ja/gitlab.po
index bfa97aa21d7..4037ff731a2 100644
--- a/locale/ja/gitlab.po
+++ b/locale/ja/gitlab.po
@@ -1,40 +1,51 @@
-# Arthur Charron <arthur.charron@hotmail.fr>, 2017. #zanata
-# Huang Tao <htve@outlook.com>, 2017. #zanata
-# Kohei Ota <inductor@kela.jp>, 2017. #zanata
-# Taisuke Inoue <taisuke.inoue.jp@gmail.com>, 2017. #zanata
-# Takuya Noguchi <takninnovationresearch@gmail.com>, 2017. #zanata
-# YANO Tethurou <tetuyano+zana@gmail.com>, 2017. #zanata
msgid ""
msgstr ""
-"Project-Id-Version: gitlab 1.0.0\n"
+"Project-Id-Version: gitlab-ee\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2017-07-13 12:07-0500\n"
+"POT-Creation-Date: 2017-08-18 14:15+0530\n"
+"PO-Revision-Date: 2017-08-23 10:14-0400\n"
+"Last-Translator: gitlab <mbartlett+crowdin@gitlab.com>\n"
+"Language-Team: Japanese\n"
+"Language: ja_JP\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"PO-Revision-Date: 2017-08-06 11:23-0400\n"
-"Last-Translator: Taisuke Inoue <taisuke.inoue.jp@gmail.com>\n"
-"Language-Team: Japanese "Language-Team: Russian (https://translate.zanata.org/project/view/GitLab)\n"
-"Language: ja\n"
-"X-Generator: Zanata 3.9.6\n"
-"Plural-Forms: nplurals=1; plural=0\n"
-
-msgid "%s additional commit has been omitted to prevent performance issues."
-msgid_plural ""
-"%s additional commits have been omitted to prevent performance issues."
-msgstr[0] "パフォーマンス低下をé¿ã‘ã‚‹ãŸã‚ %s 個ã®ã‚³ãƒŸãƒƒãƒˆã‚’çœç•¥ã—ã¾ã—ãŸã€‚"
+"Plural-Forms: nplurals=1; plural=0;\n"
+"X-Generator: crowdin.com\n"
+"X-Crowdin-Project: gitlab-ee\n"
+"X-Crowdin-Language: ja\n"
+"X-Crowdin-File: /master/locale/gitlab.pot\n"
msgid "%d commit"
msgid_plural "%d commits"
msgstr[0] "%d個ã®ã‚³ãƒŸãƒƒãƒˆ"
+msgid "%s additional commit has been omitted to prevent performance issues."
+msgid_plural "%s additional commits have been omitted to prevent performance issues."
+msgstr[0] "パフォーマンス低下をé¿ã‘ã‚‹ãŸã‚ %s 個ã®ã‚³ãƒŸãƒƒãƒˆã‚’çœç•¥ã—ã¾ã—ãŸã€‚"
+
msgid "%{commit_author_link} committed %{commit_timeago}"
msgstr "%{commit_timeago}ã«%{commit_author_link}ãŒã‚³ãƒŸãƒƒãƒˆã—ã¾ã—ãŸã€‚"
+msgid "%{number_of_failures} of %{maximum_failures} failures. GitLab will allow access on the next attempt."
+msgstr ""
+
+msgid "%{number_of_failures} of %{maximum_failures} failures. GitLab will block access for %{number_of_seconds} seconds."
+msgstr ""
+
+msgid "%{number_of_failures} of %{maximum_failures} failures. GitLab will not retry automatically. Reset storage information when the problem is resolved."
+msgstr ""
+
+msgid "%{storage_name}: failed storage access attempt on host:"
+msgid_plural "%{storage_name}: %{failed_attempts} failed storage access attempts:"
+msgstr[0] ""
+
+msgid "(checkout the %{link} for information on how to install it)."
+msgstr ""
+
msgid "1 pipeline"
msgid_plural "%d pipelines"
msgstr[0] "1 個ã®ãƒ‘イプライン"
-msgstr[1] "%d 個ã®ãƒ‘イプライン"
msgid "A collection of graphs regarding Continuous Integration"
msgstr "CIã«ã¤ã„ã¦ã®ã‚°ãƒ©ãƒ•"
@@ -42,6 +53,9 @@ msgstr "CIã«ã¤ã„ã¦ã®ã‚°ãƒ©ãƒ•"
msgid "About auto deploy"
msgstr "自動デプロイã«ã¤ã„ã¦"
+msgid "Access to failing storages has been temporarily disabled to allow the mount to recover. Reset storage information after the issue has been resolved to allow access again."
+msgstr ""
+
msgid "Active"
msgstr "有効"
@@ -63,12 +77,27 @@ msgstr "SSHã§ãƒ—ルやプッシュã™ã‚‹å ´åˆã¯ã€ãƒ—ロフィールã«SSHéµ
msgid "Add new directory"
msgstr "æ–°è¦ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã‚’追加"
+msgid "All"
+msgstr ""
+
msgid "Archived project! Repository is read-only"
msgstr "アーカイブ済ã¿ãƒ—ロジェクトï¼ï¼ˆãƒ¬ãƒã‚¸ãƒˆãƒªãƒ¼ã¯èª­ã¿å–り専用ã§ã™ï¼‰"
msgid "Are you sure you want to delete this pipeline schedule?"
msgstr "ã“ã®ãƒ‘イプラインスケジュールを削除ã—ã¾ã™ã‹ï¼Ÿ"
+msgid "Are you sure you want to discard your changes?"
+msgstr ""
+
+msgid "Are you sure you want to reset registration token?"
+msgstr ""
+
+msgid "Are you sure you want to reset the health check token?"
+msgstr ""
+
+msgid "Are you sure?"
+msgstr ""
+
msgid "Attach a file by drag &amp; drop or %{upload_link}"
msgstr "ドラッグ&ドロップã¾ãŸã¯ %{upload_link} ã§ãƒ•ã‚¡ã‚¤ãƒ«ã‚’添付"
@@ -76,13 +105,8 @@ msgid "Branch"
msgid_plural "Branches"
msgstr[0] "ブランãƒ"
-msgid ""
-"Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, "
-"choose a GitLab CI Yaml template and commit your changes. "
-"%{link_to_autodeploy_doc}"
-msgstr ""
-"<strong>%{branch_name}</strong> ブランãƒãŒä½œæˆã•ã‚Œã¾ã—ãŸã€‚自動デプロイを設定ã™ã‚‹ã«ã¯ã€GitLab CI Yaml "
-"テンプレートをé¸æŠžã—ã¦ã€å¤‰æ›´ã‚’コミットã—ã¦ãã ã•ã„。 %{link_to_autodeploy_doc}"
+msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
+msgstr "<strong>%{branch_name}</strong> ブランãƒãŒä½œæˆã•ã‚Œã¾ã—ãŸã€‚自動デプロイを設定ã™ã‚‹ã«ã¯ã€GitLab CI Yaml テンプレートをé¸æŠžã—ã¦ã€å¤‰æ›´ã‚’コミットã—ã¦ãã ã•ã„。 %{link_to_autodeploy_doc}"
msgid "BranchSwitcherPlaceholder|Search branches"
msgstr "ブランãƒã‚’検索"
@@ -114,6 +138,9 @@ msgstr "CI 設定"
msgid "Cancel"
msgstr "キャンセル"
+msgid "Cancel edit"
+msgstr ""
+
msgid "ChangeTypeActionLabel|Pick into branch"
msgstr "ピック先ブランãƒ:"
@@ -192,6 +219,9 @@ msgstr "スキップ済ã¿"
msgid "CiStatus|running"
msgstr "実行中"
+msgid "Comments"
+msgstr ""
+
msgid "Commit"
msgid_plural "Commits"
msgstr[0] "コミット"
@@ -238,9 +268,10 @@ msgstr "コミットã®SHAをクリップボードã«ã‚³ãƒ”ー"
msgid "Create New Directory"
msgstr "æ–°è¦ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã‚’作æˆ"
-msgid ""
-"Create a personal access token on your account to pull or push via "
-"%{protocol}."
+msgid "Create a new branch"
+msgstr ""
+
+msgid "Create a personal access token on your account to pull or push via %{protocol}."
msgstr "%{protocol} ã§ãƒ—ッシュやプルã™ã‚‹ãŸã‚ã®ã‚ãªãŸå€‹äººç”¨ã‚¢ã‚¯ã‚»ã‚¹ãƒˆãƒ¼ã‚¯ãƒ³ã‚’作æˆ"
msgid "Create directory"
@@ -273,23 +304,14 @@ msgstr "Cron ã®æ§‹æ–‡"
msgid "Custom notification events"
msgstr "カスタム通知設定"
-msgid ""
-"Custom notification levels are the same as participating levels. With custom "
-"notification levels you will also receive notifications for select events. "
-"To find out more, check out %{notification_link}."
-msgstr ""
-"\"カスタム\" ã®é€šçŸ¥ãƒ¬ãƒ™ãƒ«ã®åŸºæœ¬ã¯ \"å‚加\" "
-"ã¨åŒã˜ã§ã™ã€‚ã¾ãŸã€ã‚«ã‚¹ã‚¿ãƒ é€šçŸ¥ã«è¨­å®šã™ã‚‹ã“ã¨ã§é¸æŠžã—ãŸã‚«ã‚¹ã‚¿ãƒ ã‚¤ãƒ™ãƒ³ãƒˆã®é€šçŸ¥ã‚’å—ã‘å–ã‚‹ã“ã¨ã‚‚ã§ãã¾ã™ã€‚ã‚‚ã£ã¨è©³ã—ã知りãŸã„å ´åˆã¯ "
-"%{notification_link} を見ã¦ãã ã•ã„。"
+msgid "Custom notification levels are the same as participating levels. With custom notification levels you will also receive notifications for select events. To find out more, check out %{notification_link}."
+msgstr "\"カスタム\" ã®é€šçŸ¥ãƒ¬ãƒ™ãƒ«ã®åŸºæœ¬ã¯ \"å‚加\" ã¨åŒã˜ã§ã™ã€‚ã¾ãŸã€ã‚«ã‚¹ã‚¿ãƒ é€šçŸ¥ã«è¨­å®šã™ã‚‹ã“ã¨ã§é¸æŠžã—ãŸã‚«ã‚¹ã‚¿ãƒ ã‚¤ãƒ™ãƒ³ãƒˆã®é€šçŸ¥ã‚’å—ã‘å–ã‚‹ã“ã¨ã‚‚ã§ãã¾ã™ã€‚ã‚‚ã£ã¨è©³ã—ã知りãŸã„å ´åˆã¯ %{notification_link} を見ã¦ãã ã•ã„。"
msgid "Cycle Analytics"
msgstr "サイクル分æž"
-msgid ""
-"Cycle Analytics gives an overview of how much time it takes to go from idea "
-"to production in your project."
-msgstr ""
-"サイクル分æžã«ã‚ˆã‚Šã€ã‚ãªãŸã®ãƒ—ロジェクトãŒã‚¢ã‚¤ãƒ‡ã‚£ã‚¢ã®æ®µéšŽã‹ã‚‰ãƒ—ロダクション環境ã«ãƒªãƒªãƒ¼ã‚¹ã•ã‚Œã‚‹ã¾ã§ã©ã‚Œãらã„時間ãŒã‹ã‹ã£ãŸã‹ä¿¯çž°ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚"
+msgid "Cycle Analytics gives an overview of how much time it takes to go from idea to production in your project."
+msgstr "サイクル分æžã«ã‚ˆã‚Šã€ã‚ãªãŸã®ãƒ—ロジェクトãŒã‚¢ã‚¤ãƒ‡ã‚£ã‚¢ã®æ®µéšŽã‹ã‚‰ãƒ—ロダクション環境ã«ãƒªãƒªãƒ¼ã‚¹ã•ã‚Œã‚‹ã¾ã§ã©ã‚Œãらã„時間ãŒã‹ã‹ã£ãŸã‹ä¿¯çž°ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚"
msgid "CycleAnalyticsStage|Code"
msgstr "コード"
@@ -325,9 +347,15 @@ msgstr[0] "デプロイ"
msgid "Description"
msgstr "説明"
+msgid "Details"
+msgstr ""
+
msgid "Directory name"
msgstr "ディレクトリå"
+msgid "Discard changes"
+msgstr ""
+
msgid "Don't show again"
msgstr "次回ã‹ã‚‰è¡¨ç¤ºã—ãªã„"
@@ -364,6 +392,24 @@ msgstr "編集"
msgid "Edit Pipeline Schedule %{id}"
msgstr "パイプラインスケジュール %{id} を編集"
+msgid "EventFilterBy|Filter by all"
+msgstr ""
+
+msgid "EventFilterBy|Filter by comments"
+msgstr ""
+
+msgid "EventFilterBy|Filter by issue events"
+msgstr ""
+
+msgid "EventFilterBy|Filter by merge events"
+msgstr ""
+
+msgid "EventFilterBy|Filter by push events"
+msgstr ""
+
+msgid "EventFilterBy|Filter by team"
+msgstr ""
+
msgid "Every day (at 4:00am)"
msgstr "毎日 (åˆå‰4:00)"
@@ -410,12 +456,36 @@ msgstr "課題ãŒç™»éŒ²ã•ã‚Œã¦ã‹ã‚‰ãƒ—ロダクションã«ãƒ‡ãƒ—ロイã•ã‚Œ
msgid "From merge request merge until deploy to production"
msgstr "マージリクエストãŒãƒžãƒ¼ã‚¸ã•ã‚Œã¦ã‹ã‚‰ãƒ—ロダクションã«ãƒ‡ãƒ—ロイã•ã‚Œã‚‹ã¾ã§"
+msgid "Git storage health information has been reset"
+msgstr ""
+
+msgid "GitLab Runner section"
+msgstr ""
+
msgid "Go to your fork"
msgstr "自分ã®ãƒ•ã‚©ãƒ¼ã‚¯ã¸ç§»å‹•"
msgid "GoToYourFork|Fork"
msgstr "フォーク"
+msgid "Health Check"
+msgstr ""
+
+msgid "Health information can be retrieved from the following endpoints. More information is available"
+msgstr ""
+
+msgid "HealthCheck|Access token is"
+msgstr ""
+
+msgid "HealthCheck|Healthy"
+msgstr ""
+
+msgid "HealthCheck|No Health Problems Detected"
+msgstr ""
+
+msgid "HealthCheck|Unhealthy"
+msgstr ""
+
msgid "Home"
msgstr "ホーム"
@@ -425,12 +495,18 @@ msgstr "ãƒã‚¦ã‚¹ã‚­ãƒ¼ãƒ”ングã¯æ­£å¸¸ã«èµ·å‹•ã—ã¾ã—ãŸã€‚"
msgid "Import repository"
msgstr "レãƒã‚¸ãƒˆãƒªãƒ¼ã‚’インãƒãƒ¼ãƒˆ"
+msgid "Install a Runner compatible with GitLab CI"
+msgstr ""
+
msgid "Interval Pattern"
msgstr "é–“éš”ã®ãƒ‘ターン"
msgid "Introducing Cycle Analytics"
msgstr "サイクル分æžã®ã”紹介"
+msgid "Issue events"
+msgstr ""
+
msgid "Jobs for last month"
msgstr "先月ã®ã‚¸ãƒ§ãƒ–"
@@ -459,6 +535,12 @@ msgstr "最新アップデート"
msgid "Last commit"
msgstr "最新コミット"
+msgid "LastPushEvent|You pushed to"
+msgstr ""
+
+msgid "LastPushEvent|at"
+msgstr ""
+
msgid "Learn more in the"
msgstr "詳ã—ã見る:"
@@ -478,9 +560,15 @@ msgstr[0] "イベント表示数を最大 %d 個ã«åˆ¶é™"
msgid "Median"
msgstr "中央値"
+msgid "Merge events"
+msgstr ""
+
msgid "MissingSSHKeyWarningLink|add an SSH key"
msgstr "SSH éµã‚’追加"
+msgid "More information is available|here"
+msgstr ""
+
msgid "New Issue"
msgid_plural "New Issues"
msgstr[0] "æ–°è¦èª²é¡Œ"
@@ -677,6 +765,9 @@ msgstr "ステージã‚ã‚Š"
msgid "Pipeline|with stages"
msgstr "ステージã‚ã‚Š"
+msgid "Project"
+msgstr ""
+
msgid "Project '%{project_name}' queued for deletion."
msgstr "'%{project_name}' プロジェクトã¯å‰Šé™¤å‡¦ç†å¾…ã¡ã§ã™ã€‚"
@@ -692,15 +783,16 @@ msgstr "'%{project_name}' プロジェクトã¯å‰Šé™¤ã•ã‚Œã¾ã™ã€‚"
msgid "Project access must be granted explicitly to each user."
msgstr "ユーザーã”ã¨ã«ãƒ—ロジェクトアクセスã®æ¨©é™ã‚’指定ã—ãªã‘ã‚Œã°ãªã‚Šã¾ã›ã‚“。"
+msgid "Project details"
+msgstr ""
+
msgid "Project export could not be deleted."
msgstr "プロジェクトã®ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆã‚’削除ã§ãã¾ã›ã‚“ã§ã—ãŸã€‚"
msgid "Project export has been deleted."
msgstr "プロジェクトã®ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆã‚’削除ã—ã¾ã—ãŸã€‚"
-msgid ""
-"Project export link has expired. Please generate a new export from your "
-"project settings."
+msgid "Project export link has expired. Please generate a new export from your project settings."
msgstr "プロジェクトã®ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆãƒªãƒ³ã‚¯ã¯æœŸé™åˆ‡ã‚Œã«ãªã‚Šã¾ã—ãŸã€‚プロジェクト設定ã«ã¦æ–°ã—ãエクスãƒãƒ¼ãƒˆãƒªãƒ³ã‚¯ã‚’作æˆã—ã¦ãã ã•ã„。"
msgid "Project export started. A download link will be sent by email."
@@ -709,6 +801,9 @@ msgstr "プロジェクトã®ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆã‚’開始ã—ã¾ã—ãŸã€‚ダウン
msgid "Project home"
msgstr "プロジェクトホーム"
+msgid "ProjectActivityRSS|Subscribe"
+msgstr ""
+
msgid "ProjectFeature|Disabled"
msgstr "無効"
@@ -730,11 +825,14 @@ msgstr "ステージ"
msgid "ProjectNetworkGraph|Graph"
msgstr "ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã‚°ãƒ©ãƒ•"
+msgid "Push events"
+msgstr ""
+
msgid "Read more"
msgstr "続ãを読む"
msgid "Readme"
-msgstr "Readme"
+msgstr ""
msgid "RefSwitcher|Branches"
msgstr "ブランãƒ"
@@ -766,9 +864,21 @@ msgstr "後ã§é€šçŸ¥"
msgid "Remove project"
msgstr "プロジェクトを削除"
+msgid "Repository"
+msgstr ""
+
msgid "Request Access"
msgstr "アクセス権é™ã‚’リクエストã™ã‚‹"
+msgid "Reset git storage health information"
+msgstr ""
+
+msgid "Reset health check access token"
+msgstr ""
+
+msgid "Reset runners registration token"
+msgstr ""
+
msgid "Revert this commit"
msgstr "ã“ã®ã‚³ãƒŸãƒƒãƒˆã‚’リãƒãƒ¼ãƒˆ"
@@ -793,6 +903,9 @@ msgstr "アーカイブã®ãƒ•ã‚©ãƒ¼ãƒžãƒƒãƒˆã‚’é¸æŠž"
msgid "Select a timezone"
msgstr "タイムゾーンをé¸æŠž"
+msgid "Select existing branch"
+msgstr ""
+
msgid "Select target branch"
msgstr "ターゲットブランãƒã‚’é¸æŠž"
@@ -818,12 +931,18 @@ msgstr[0] "%d ã®ã‚¤ãƒ™ãƒ³ãƒˆã‚’表示中"
msgid "Source code"
msgstr "ソースコード"
+msgid "Specify the following URL during the Runner setup:"
+msgstr ""
+
msgid "StarProject|Star"
msgstr "スターを付ã‘ã‚‹"
msgid "Start a %{new_merge_request} with these changes"
msgstr "ã“ã®å¤‰æ›´ã§ %{new_merge_request} を作æˆã™ã‚‹"
+msgid "Start the Runner!"
+msgstr ""
+
msgid "Switch branch/tag"
msgstr "ブランãƒãƒ»ã‚¿ã‚°åˆ‡ã‚Šæ›¿ãˆ"
@@ -837,12 +956,11 @@ msgstr "ã‚¿ã‚°"
msgid "Target Branch"
msgstr "ターゲットブランãƒ"
-msgid ""
-"The coding stage shows the time from the first commit to creating the merge "
-"request. The data will automatically be added here once you create your "
-"first merge request."
+msgid "Team"
msgstr ""
-"コーディングステージã§ã¯ã€æœ€åˆã®ã‚³ãƒŸãƒƒãƒˆã‹ã‚‰ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆãŒä½œæˆã•ã‚Œã‚‹ã¾ã§ã®æ™‚é–“ãŒè¡¨ç¤ºã•ã‚Œã¾ã™ã€‚ã“ã®ãƒ‡ãƒ¼ã‚¿ã¯æœ€åˆã®ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆãŒä½œæˆã•ã‚ŒãŸã¨ãã«è‡ªå‹•çš„ã«è¿½åŠ ã•ã‚Œã¾ã™ã€‚"
+
+msgid "The coding stage shows the time from the first commit to creating the merge request. The data will automatically be added here once you create your first merge request."
+msgstr "コーディングステージã§ã¯ã€æœ€åˆã®ã‚³ãƒŸãƒƒãƒˆã‹ã‚‰ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆãŒä½œæˆã•ã‚Œã‚‹ã¾ã§ã®æ™‚é–“ãŒè¡¨ç¤ºã•ã‚Œã¾ã™ã€‚ã“ã®ãƒ‡ãƒ¼ã‚¿ã¯æœ€åˆã®ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆãŒä½œæˆã•ã‚ŒãŸã¨ãã«è‡ªå‹•çš„ã«è¿½åŠ ã•ã‚Œã¾ã™ã€‚"
msgid "The collection of events added to the data gathered for that stage."
msgstr "ã“ã®ã‚¹ãƒ†ãƒ¼ã‚¸ã§è¨ˆæ¸¬ãƒ‡ãƒ¼ã‚¿ã«è¿½åŠ ã•ã‚ŒãŸã‚¤ãƒ™ãƒ³ãƒˆãƒªã‚¹ãƒˆ"
@@ -850,36 +968,20 @@ msgstr "ã“ã®ã‚¹ãƒ†ãƒ¼ã‚¸ã§è¨ˆæ¸¬ãƒ‡ãƒ¼ã‚¿ã«è¿½åŠ ã•ã‚ŒãŸã‚¤ãƒ™ãƒ³ãƒˆãƒªã‚¹
msgid "The fork relationship has been removed."
msgstr "フォークã®ãƒªãƒ¬ãƒ¼ã‚·ãƒ§ãƒ³ãŒå‰Šé™¤ã•ã‚Œã¾ã—ãŸã€‚"
-msgid ""
-"The issue stage shows the time it takes from creating an issue to assigning "
-"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 ""
-"課題ステージã§ã¯ã€èª²é¡ŒãŒç™»éŒ²ã•ã‚Œã¦ã‹ã‚‰ãƒžã‚¤ãƒ«ã‚¹ãƒˆãƒ¼ãƒ³ã«å‰²ã‚Šå½“ã¦ã‚‰ã‚Œã‚‹ã‹ã€èª²é¡Œãƒœãƒ¼ãƒ‰ã®ãƒªã‚¹ãƒˆã«è¿½åŠ ã•ã‚Œã‚‹ã¾ã§ã®æ™‚é–“ãŒè¡¨ç¤ºã•ã‚Œã¾ã™ã€‚ã“ã®ãƒªã‚¹ãƒˆã«è¡¨ç¤ºã™ã‚‹ã«ã¯èª²é¡Œã‚’最åˆã«ä½œæˆã—ã¦ãã ã•ã„。"
+msgid "The issue stage shows the time it takes from creating an issue to assigning 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 "課題ステージã§ã¯ã€èª²é¡ŒãŒç™»éŒ²ã•ã‚Œã¦ã‹ã‚‰ãƒžã‚¤ãƒ«ã‚¹ãƒˆãƒ¼ãƒ³ã«å‰²ã‚Šå½“ã¦ã‚‰ã‚Œã‚‹ã‹ã€èª²é¡Œãƒœãƒ¼ãƒ‰ã®ãƒªã‚¹ãƒˆã«è¿½åŠ ã•ã‚Œã‚‹ã¾ã§ã®æ™‚é–“ãŒè¡¨ç¤ºã•ã‚Œã¾ã™ã€‚ã“ã®ãƒªã‚¹ãƒˆã«è¡¨ç¤ºã™ã‚‹ã«ã¯èª²é¡Œã‚’最åˆã«ä½œæˆã—ã¦ãã ã•ã„。"
msgid "The phase of the development lifecycle."
msgstr "開発ライフサイクルã®æ®µéšŽ"
-msgid ""
-"The pipelines schedule runs pipelines in the future, repeatedly, for "
-"specific branches or tags. Those scheduled pipelines will inherit limited "
-"project access based on their associated user."
-msgstr ""
-"パイプラインスケジュールã¯æŒ‡å®šã®ãƒ–ランãƒã¾ãŸã¯ã‚¿ã‚°ã«å¯¾ã—ã¦è‡ªå‹•çš„ã«ãƒ‘イプラインを実行ã—ã¾ã™ã€‚計画済ã¿ãƒ‘イプラインã¯ãれらã®ç´ä»˜ã‘られãŸãƒ¦ãƒ¼ã‚¶ãƒ¼ã®ãƒ—ロジェクトã¨åŒã˜æ¨©é™ã‚’継承ã—ã¾ã™ã€‚"
+msgid "The pipelines schedule runs pipelines in the future, repeatedly, for specific branches or tags. Those scheduled pipelines will inherit limited project access based on their associated user."
+msgstr "パイプラインスケジュールã¯æŒ‡å®šã®ãƒ–ランãƒã¾ãŸã¯ã‚¿ã‚°ã«å¯¾ã—ã¦è‡ªå‹•çš„ã«ãƒ‘イプラインを実行ã—ã¾ã™ã€‚計画済ã¿ãƒ‘イプラインã¯ãれらã®ç´ä»˜ã‘られãŸãƒ¦ãƒ¼ã‚¶ãƒ¼ã®ãƒ—ロジェクトã¨åŒã˜æ¨©é™ã‚’継承ã—ã¾ã™ã€‚"
-msgid ""
-"The planning stage shows the time from the previous step to pushing your "
-"first commit. This time will be added automatically once you push your first "
-"commit."
-msgstr ""
-"計画ステージã§ã¯ã€èª²é¡Œã‚¹ãƒ†ãƒ¼ã‚¸ã«ç™»éŒ²ã•ã‚Œã¦ã‹ã‚‰ãƒ—ッシュã•ã‚ŒãŸæœ€åˆã®ã‚³ãƒŸãƒƒãƒˆæ™‚刻ã¾ã§ã®æ™‚é–“ãŒè¡¨ç¤ºã•ã‚Œã¾ã™ã€‚最åˆã®ã‚³ãƒŸãƒƒãƒˆãŒãƒ—ッシュã•ã‚Œã¨ãã«è‡ªå‹•çš„ã«è¿½åŠ ã•ã‚Œã¾ã™ã€‚"
+msgid "The planning stage shows the time from the previous step to pushing your first commit. This time will be added automatically once you push your first commit."
+msgstr "計画ステージã§ã¯ã€èª²é¡Œã‚¹ãƒ†ãƒ¼ã‚¸ã«ç™»éŒ²ã•ã‚Œã¦ã‹ã‚‰ãƒ—ッシュã•ã‚ŒãŸæœ€åˆã®ã‚³ãƒŸãƒƒãƒˆæ™‚刻ã¾ã§ã®æ™‚é–“ãŒè¡¨ç¤ºã•ã‚Œã¾ã™ã€‚最åˆã®ã‚³ãƒŸãƒƒãƒˆãŒãƒ—ッシュã•ã‚Œã¨ãã«è‡ªå‹•çš„ã«è¿½åŠ ã•ã‚Œã¾ã™ã€‚"
-msgid ""
-"The production stage shows the total time it takes between creating an issue "
-"and deploying the code to production. The data will be automatically added "
-"once you have completed the full idea to production cycle."
-msgstr ""
-"プロダクションステージã§ã¯ã€èª²é¡ŒãŒä½œæˆã•ã‚Œã¦ã‹ã‚‰ãƒ—ロダクションã¸ãƒ‡ãƒ—ロイã•ã‚Œã‚‹ã¾ã§ã®æ™‚é–“ãŒè¡¨ç¤ºã•ã‚Œã¾ã™ã€‚アイディアã®æ™‚点ã‹ã‚‰ãƒ—ロダクションã¾ã§ã®å…¨ã‚¹ãƒ†ãƒ¼ã‚¸ãŒå®Œäº†ã—ãŸã¨ãã«è‡ªå‹•çš„ã«è¿½åŠ ã•ã‚Œã¾ã™ã€‚"
+msgid "The production stage shows the total time it takes between creating an issue and deploying the code to production. The data will be automatically added once you have completed the full idea to production cycle."
+msgstr "プロダクションステージã§ã¯ã€èª²é¡ŒãŒä½œæˆã•ã‚Œã¦ã‹ã‚‰ãƒ—ロダクションã¸ãƒ‡ãƒ—ロイã•ã‚Œã‚‹ã¾ã§ã®æ™‚é–“ãŒè¡¨ç¤ºã•ã‚Œã¾ã™ã€‚アイディアã®æ™‚点ã‹ã‚‰ãƒ—ロダクションã¾ã§ã®å…¨ã‚¹ãƒ†ãƒ¼ã‚¸ãŒå®Œäº†ã—ãŸã¨ãã«è‡ªå‹•çš„ã«è¿½åŠ ã•ã‚Œã¾ã™ã€‚"
msgid "The project can be accessed by any logged in user."
msgstr "プロジェクトã¯ã€ãƒ­ã‚°ã‚¤ãƒ³ãƒ¦ãƒ¼ã‚¶ãƒ¼ã§ã‚ã‚Œã°èª°ã§ã‚‚アクセスã§ãã¾ã™ã€‚"
@@ -890,42 +992,25 @@ msgstr "プロジェクトã¯ã€ãƒ­ã‚°ã‚¤ãƒ³ãªã—ã«èª°ã§ã‚‚アクセスã§ã
msgid "The repository for this project does not exist."
msgstr "ã“ã®ãƒ—ロジェクトã«ãƒ¬ãƒã‚¸ãƒˆãƒªãƒ¼ã¯ã‚ã‚Šã¾ã›ã‚“。"
-msgid ""
-"The review stage shows the time from creating the merge request to merging "
-"it. The data will automatically be added after you merge your first merge "
-"request."
-msgstr ""
-"レビューステージã¨ã¯ã€ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆã‚’作æˆã—ã¦ã‹ã‚‰ãƒžãƒ¼ã‚¸ã™ã‚‹ã¾ã§ã®æ™‚é–“ã§ã™ã€‚ã“ã®ãƒ‡ãƒ¼ã‚¿ã¯æœ€åˆã®ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆãŒãƒžãƒ¼ã‚¸ã•ã‚ŒãŸã¨ãã«è‡ªå‹•çš„ã«è¿½åŠ ã•ã‚Œã¾ã™ã€‚"
+msgid "The review stage shows the time from creating the merge request to merging it. The data will automatically be added after you merge your first merge request."
+msgstr "レビューステージã¨ã¯ã€ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆã‚’作æˆã—ã¦ã‹ã‚‰ãƒžãƒ¼ã‚¸ã™ã‚‹ã¾ã§ã®æ™‚é–“ã§ã™ã€‚ã“ã®ãƒ‡ãƒ¼ã‚¿ã¯æœ€åˆã®ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆãŒãƒžãƒ¼ã‚¸ã•ã‚ŒãŸã¨ãã«è‡ªå‹•çš„ã«è¿½åŠ ã•ã‚Œã¾ã™ã€‚"
-msgid ""
-"The staging stage shows the time between merging the MR and deploying code "
-"to the production environment. The data will be automatically added once you "
-"deploy to production for the first time."
-msgstr ""
-"ステージングステージã§ã¯ã€ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆãŒãƒžãƒ¼ã‚¸ã•ã‚Œã¦ã‹ã‚‰ã‚³ãƒ¼ãƒ‰ãŒãƒ—ロダクション環境ã«ãƒ‡ãƒ—ロイã•ã‚Œã‚‹ã¾ã§ã®æ™‚é–“ãŒè¡¨ç¤ºã•ã‚Œã¾ã™ã€‚ã“ã®ãƒ‡ãƒ¼ã‚¿ã¯æœ€åˆã«ãƒ—ロダクションã«ãƒ‡ãƒ—ロイã—ãŸã¨ãã«è‡ªå‹•çš„ã«è¿½åŠ ã•ã‚Œã¾ã™ã€‚"
+msgid "The staging stage shows the time between merging the MR and deploying code to the production environment. The data will be automatically added once you deploy to production for the first time."
+msgstr "ステージングステージã§ã¯ã€ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆãŒãƒžãƒ¼ã‚¸ã•ã‚Œã¦ã‹ã‚‰ã‚³ãƒ¼ãƒ‰ãŒãƒ—ロダクション環境ã«ãƒ‡ãƒ—ロイã•ã‚Œã‚‹ã¾ã§ã®æ™‚é–“ãŒè¡¨ç¤ºã•ã‚Œã¾ã™ã€‚ã“ã®ãƒ‡ãƒ¼ã‚¿ã¯æœ€åˆã«ãƒ—ロダクションã«ãƒ‡ãƒ—ロイã—ãŸã¨ãã«è‡ªå‹•çš„ã«è¿½åŠ ã•ã‚Œã¾ã™ã€‚"
-msgid ""
-"The testing stage shows the time GitLab CI takes to run every pipeline for "
-"the related merge request. The data will automatically be added after your "
-"first pipeline finishes running."
-msgstr ""
-"テスティングステージã§ã¯ã€GitLab CI "
-"ãŒé–¢é€£ã™ã‚‹ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆã®å„パイプラインを実行ã™ã‚‹æ™‚é–“ãŒè¡¨ç¤ºã•ã‚Œã¾ã™ã€‚ã“ã®ãƒ‡ãƒ¼ã‚¿ã¯æœ€åˆã®ãƒ‘イプラインãŒå®Œäº†ã—ãŸã¨ãã«è‡ªå‹•çš„ã«è¿½åŠ ã•ã‚Œã¾ã™ã€‚"
+msgid "The testing stage shows the time GitLab CI takes to run every pipeline for the related merge request. The data will automatically be added after your first pipeline finishes running."
+msgstr "テスティングステージã§ã¯ã€GitLab CI ãŒé–¢é€£ã™ã‚‹ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆã®å„パイプラインを実行ã™ã‚‹æ™‚é–“ãŒè¡¨ç¤ºã•ã‚Œã¾ã™ã€‚ã“ã®ãƒ‡ãƒ¼ã‚¿ã¯æœ€åˆã®ãƒ‘イプラインãŒå®Œäº†ã—ãŸã¨ãã«è‡ªå‹•çš„ã«è¿½åŠ ã•ã‚Œã¾ã™ã€‚"
msgid "The time taken by each data entry gathered by that stage."
msgstr "ã“ã®ã‚¹ãƒ†ãƒ¼ã‚¸ã«åŽé›†ã•ã‚ŒãŸãƒ‡ãƒ¼ã‚¿æ¯Žã®æ™‚é–“"
-msgid ""
-"The value lying at the midpoint of a series of observed values. E.g., "
-"between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 ="
-" 6."
+msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
+msgstr "得られãŸä¸€é€£ã®ãƒ‡ãƒ¼ã‚¿ã‚’å°ã•ã„é †ã«ä¸¦ã¹ãŸã¨ãã«ä¸­å¤®ã«ä½ç½®ã™ã‚‹å€¤ã€‚例ãˆã°ã€3, 5, 9ã®ä¸­å¤®å€¤ã¯5。3, 5, 7, 8ã®ä¸­å¤®å€¤ã¯ (5+7)/2 = 6。"
+
+msgid "There are problems accessing Git storage: "
msgstr ""
-"得られãŸä¸€é€£ã®ãƒ‡ãƒ¼ã‚¿ã‚’å°ã•ã„é †ã«ä¸¦ã¹ãŸã¨ãã«ä¸­å¤®ã«ä½ç½®ã™ã‚‹å€¤ã€‚例ãˆã°ã€3, 5, 9ã®ä¸­å¤®å€¤ã¯5。3, 5, 7, 8ã®ä¸­å¤®å€¤ã¯ (5+7)/2 = "
-"6。"
-msgid ""
-"This means you can not push code until you create an empty repository or "
-"import existing one."
+msgid "This means you can not push code until you create an empty repository or import existing one."
msgstr "空レãƒã‚¸ãƒˆãƒªãƒ¼ã‚’作æˆã¾ãŸã¯æ—¢å­˜ãƒ¬ãƒã‚¸ãƒˆãƒªãƒ¼ã‚’インãƒãƒ¼ãƒˆã‚’ã—ãªã‘ã‚Œã°ã€ã‚³ãƒ¼ãƒ‰ã®ãƒ—ッシュã¯ã§ãã¾ã›ã‚“。"
msgid "Time before an issue gets scheduled"
@@ -1092,6 +1177,9 @@ msgstr "ファイルをアップロード"
msgid "UploadLink|click to upload"
msgstr "クリックã—ã¦ã‚¢ãƒƒãƒ—ロード"
+msgid "Use the following registration token during setup:"
+msgstr ""
+
msgid "Use your global notification setting"
msgstr "全体通知設定を利用"
@@ -1125,14 +1213,10 @@ msgstr "%{group_name} グループを削除ã—よã†ã¨ã—ã¦ã„ã¾ã™ã€‚ 削除
msgid "You are going to remove %{project_name_with_namespace}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr "%{project_name_with_namespace} プロジェクトを削除ã—よã†ã¨ã—ã¦ã„ã¾ã™ã€‚削除ã•ã‚ŒãŸãƒ—ロジェクトã¯çµ¶å¯¾ã«å…ƒã«ã¯æˆ»ã›ã¾ã›ã‚“ï¼æœ¬å½“ã«ã‚ˆã‚ã—ã„ã§ã™ã‹ï¼Ÿ"
-msgid ""
-"You are going to remove the fork relationship to source project "
-"%{forked_from_project}. Are you ABSOLUTELY sure?"
+msgid "You are going to remove the fork relationship to source project %{forked_from_project}. Are you ABSOLUTELY sure?"
msgstr "å…ƒã®ãƒ—ロジェクト (%{forked_from_project}) ã¨ã®ãƒªãƒ¬ãƒ¼ã‚·ãƒ§ãƒ³ã‚’削除ã—よã†ã¨ã—ã¦ã„ã¾ã™ã€‚本当ã«ã‚ˆã‚ã—ã„ã§ã™ã‹ï¼Ÿ"
-msgid ""
-"You are going to transfer %{project_name_with_namespace} to another owner. "
-"Are you ABSOLUTELY sure?"
+msgid "You are going to transfer %{project_name_with_namespace} to another owner. Are you ABSOLUTELY sure?"
msgstr "%{project_name_with_namespace} プロジェクトを別ã®ã‚ªãƒ¼ãƒŠãƒ¼ã«ç§»è­²ã—よã†ã¨ã—ã¦ã„ã¾ã™ã€‚本当ã«ã‚ˆã‚ã—ã„ã§ã™ã‹ï¼Ÿ"
msgid "You can only add files when you are on a branch"
@@ -1153,28 +1237,19 @@ msgstr "通知メールをé€ä¿¡ã—ã¾ã›ã‚“"
msgid "You will only receive notifications for the events you choose"
msgstr "é¸æŠžã—ãŸã‚¤ãƒ™ãƒ³ãƒˆã®ã¿é€šçŸ¥ã—ã¾ã™"
-msgid ""
-"You will only receive notifications for threads you have participated in"
+msgid "You will only receive notifications for threads you have participated in"
msgstr "å‚加ã—ãŸã‚¹ãƒ¬ãƒƒãƒ‰ã®ã¿é€šçŸ¥ã—ã¾ã™"
msgid "You will receive notifications for any activity"
msgstr "å…¨ã¦ã®ã‚¢ã‚¯ãƒ†ã‚£ãƒ“ティーを通知ã—ã¾ã™"
-msgid ""
-"You will receive notifications only for comments in which you were "
-"@mentioned"
+msgid "You will receive notifications only for comments in which you were @mentioned"
msgstr "ã‚ãªãŸãŒ @mentioned ã§ã‚³ãƒ¡ãƒ³ãƒˆã•ã‚ŒãŸæ™‚ã®ã¿é€šçŸ¥ã—ã¾ã™"
-msgid ""
-"You won't be able to pull or push project code via %{protocol} until you "
-"%{set_password_link} on your account"
-msgstr ""
-"%{set_password_link} ã§ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã®ãƒ‘スワードãŒã‚»ãƒƒãƒˆã•ã‚Œã¦ã„ãªã„ã®ã§ã€ãƒ—ロジェクト㫠%{protocol} "
-"ã§ã‚½ãƒ¼ã‚¹ã‚³ãƒ¼ãƒ‰ã‚’プッシュã€ãƒ—ルã§ãã¾ã›ã‚“"
+msgid "You won't be able to pull or push project code via %{protocol} until you %{set_password_link} on your account"
+msgstr "%{set_password_link} ã§ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã®ãƒ‘スワードãŒã‚»ãƒƒãƒˆã•ã‚Œã¦ã„ãªã„ã®ã§ã€ãƒ—ロジェクト㫠%{protocol} ã§ã‚½ãƒ¼ã‚¹ã‚³ãƒ¼ãƒ‰ã‚’プッシュã€ãƒ—ルã§ãã¾ã›ã‚“"
-msgid ""
-"You won't be able to pull or push project code via SSH until you "
-"%{add_ssh_key_link} to your profile"
+msgid "You won't be able to pull or push project code via SSH until you %{add_ssh_key_link} to your profile"
msgstr "%{add_ssh_key_link} をプロファイルã«è¿½åŠ ã—ã¦ã„ãªã„ã®ã§ã€ãƒ—ロジェクトã«ã‚½ãƒ¼ã‚¹ã‚³ãƒ¼ãƒ‰ã‚’プッシュã€ãƒ—ルã§ãã¾ã›ã‚“"
msgid "Your name"
@@ -1192,4 +1267,4 @@ msgstr "メール通知"
msgid "parent"
msgid_plural "parents"
-msgstr[0] "親"
+msgstr[0] "親" \ No newline at end of file
diff --git a/locale/ko/gitlab.po b/locale/ko/gitlab.po
index 340c8955d20..125ca220c81 100644
--- a/locale/ko/gitlab.po
+++ b/locale/ko/gitlab.po
@@ -1,39 +1,51 @@
-# Korean translations for gitlab package.
-# Copyright (C) 2017 THE PACKAGE'S COPYRIGHT HOLDER
-# This file is distributed under the same license as the gitlab package.
-# FIRST AUTHOR <EMAIL@ADDRESS>, 2017.
-# Huang Tao <htve@outlook.com>, 2017. #zanata
msgid ""
msgstr ""
-"Project-Id-Version: gitlab 1.0.0\n"
+"Project-Id-Version: gitlab-ee\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2017-07-13 12:07-0500\n"
+"POT-Creation-Date: 2017-08-18 14:15+0530\n"
+"PO-Revision-Date: 2017-08-23 10:05-0400\n"
+"Last-Translator: gitlab <mbartlett+crowdin@gitlab.com>\n"
+"Language-Team: Korean\n"
+"Language: ko_KR\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"PO-Revision-Date: 2017-08-08 08:32-0400\n"
-"Last-Translator: chang-ho,cha <changho.cha@gmail.com>\n"
-"Language-Team: Korean (https://translate.zanata.org/project/view/GitLab)\n"
-"Language: ko\n"
"Plural-Forms: nplurals=1; plural=0;\n"
-"X-Generator: Zanata 3.9.6\n"
+"X-Generator: crowdin.com\n"
+"X-Crowdin-Project: gitlab-ee\n"
+"X-Crowdin-Language: ko\n"
+"X-Crowdin-File: /master/locale/gitlab.pot\n"
msgid "%d commit"
msgid_plural "%d commits"
msgstr[0] "%d 커밋"
msgid "%s additional commit has been omitted to prevent performance issues."
-msgid_plural ""
-"%s additional commits have been omitted to prevent performance issues."
+msgid_plural "%s additional commits have been omitted to prevent performance issues."
msgstr[0] "%s 추가 ì»¤ë°‹ì€ ì„±ëŠ¥ ì´ìŠˆë¥¼ 방지하기 위해 ìƒëžµë˜ì—ˆìŠµë‹ˆë‹¤."
msgid "%{commit_author_link} committed %{commit_timeago}"
msgstr "%{commit_timeago} ì— %{commit_author_link} ë‹˜ì´ ì»¤ë°‹í•˜ì˜€ìŠµë‹ˆë‹¤. "
+msgid "%{number_of_failures} of %{maximum_failures} failures. GitLab will allow access on the next attempt."
+msgstr ""
+
+msgid "%{number_of_failures} of %{maximum_failures} failures. GitLab will block access for %{number_of_seconds} seconds."
+msgstr ""
+
+msgid "%{number_of_failures} of %{maximum_failures} failures. GitLab will not retry automatically. Reset storage information when the problem is resolved."
+msgstr ""
+
+msgid "%{storage_name}: failed storage access attempt on host:"
+msgid_plural "%{storage_name}: %{failed_attempts} failed storage access attempts:"
+msgstr[0] ""
+
+msgid "(checkout the %{link} for information on how to install it)."
+msgstr ""
+
msgid "1 pipeline"
msgid_plural "%d pipelines"
msgstr[0] "1 파ì´í”„ë¼ì¸"
-msgstr[1] "%d 파ì´í”„ë¼ì¸"
msgid "A collection of graphs regarding Continuous Integration"
msgstr "지ì†ì ì¸ í†µí•©ì— ê´€í•œ 그래프 모ìŒ"
@@ -41,6 +53,9 @@ msgstr "지ì†ì ì¸ í†µí•©ì— ê´€í•œ 그래프 모ìŒ"
msgid "About auto deploy"
msgstr "ìžë™ ë°°í¬ ì •ë³´"
+msgid "Access to failing storages has been temporarily disabled to allow the mount to recover. Reset storage information after the issue has been resolved to allow access again."
+msgstr ""
+
msgid "Active"
msgstr "활성"
@@ -62,12 +77,27 @@ msgstr "í”„ë¡œí•„ì— SSH 키를 추가하여 SSH를 통해 Pull 하거나 Pushí•
msgid "Add new directory"
msgstr "새 디렉토리 추가"
+msgid "All"
+msgstr ""
+
msgid "Archived project! Repository is read-only"
msgstr "프로ì íŠ¸ê°€ ë³´ê´€ë˜ì—ˆìŠµë‹ˆë‹¤! 저장소는 ì½ê¸°ë§Œ 가능합니다."
msgid "Are you sure you want to delete this pipeline schedule?"
msgstr "ì´ íŒŒì´í”„ë¼ì¸ ìŠ¤ì¼€ì¥´ì„ ì‚­ì œ 하시겠습니까?"
+msgid "Are you sure you want to discard your changes?"
+msgstr ""
+
+msgid "Are you sure you want to reset registration token?"
+msgstr ""
+
+msgid "Are you sure you want to reset the health check token?"
+msgstr ""
+
+msgid "Are you sure?"
+msgstr ""
+
msgid "Attach a file by drag &amp; drop or %{upload_link}"
msgstr "드래그 &amp; 드롭 ë˜ëŠ” %{upload_link}"
@@ -75,13 +105,8 @@ msgid "Branch"
msgid_plural "Branches"
msgstr[0] "브랜치"
-msgid ""
-"Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, "
-"choose a GitLab CI Yaml template and commit your changes. "
-"%{link_to_autodeploy_doc}"
-msgstr ""
-"<strong>%{branch_name}</strong> 브랜치가 ìƒì„±ë˜ì—ˆìŠµë‹ˆë‹¤. ìžë™ ë°°í¬ë¥¼ 설정하려면 GitLab CI Yaml "
-"í…œí”Œë¦¿ì„ ì„ íƒí•˜ê³  변경 ì‚¬í•­ì„ ì ìš©í•˜ì‹­ì‹œì˜¤. %{link_to_autodeploy_doc}"
+msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
+msgstr "<strong>%{branch_name}</strong> 브랜치가 ìƒì„±ë˜ì—ˆìŠµë‹ˆë‹¤. ìžë™ ë°°í¬ë¥¼ 설정하려면 GitLab CI Yaml í…œí”Œë¦¿ì„ ì„ íƒí•˜ê³  변경 ì‚¬í•­ì„ ì ìš©í•˜ì‹­ì‹œì˜¤. %{link_to_autodeploy_doc}"
msgid "BranchSwitcherPlaceholder|Search branches"
msgstr "브랜치 검색"
@@ -113,6 +138,9 @@ msgstr "CI 설정"
msgid "Cancel"
msgstr "취소"
+msgid "Cancel edit"
+msgstr ""
+
msgid "ChangeTypeActionLabel|Pick into branch"
msgstr "브랜치ì—ì„œ Pick"
@@ -191,6 +219,9 @@ msgstr "건너 뜀"
msgid "CiStatus|running"
msgstr "실행 중"
+msgid "Comments"
+msgstr ""
+
msgid "Commit"
msgid_plural "Commits"
msgstr[0] "커밋"
@@ -237,9 +268,10 @@ msgstr "ì»¤ë°‹ì˜ SHA를 í´ë¦½ë³´ë“œë¡œ 복사합니다"
msgid "Create New Directory"
msgstr "새 디렉토리 만들기"
-msgid ""
-"Create a personal access token on your account to pull or push via "
-"%{protocol}."
+msgid "Create a new branch"
+msgstr ""
+
+msgid "Create a personal access token on your account to pull or push via %{protocol}."
msgstr "%{protocol}ì„ (를) 통해 Pull 하거나 Push í•  ê°œì¸ ì•¡ì„¸ìŠ¤ 토í°ì„ 만드십시오."
msgid "Create directory"
@@ -272,20 +304,13 @@ msgstr "í¬ë¡  구문"
msgid "Custom notification events"
msgstr "ì‚¬ìš©ìž ì •ì˜ ì•Œë¦¼ ì´ë²¤íŠ¸"
-msgid ""
-"Custom notification levels are the same as participating levels. With custom "
-"notification levels you will also receive notifications for select events. "
-"To find out more, check out %{notification_link}."
-msgstr ""
-"ì‚¬ìš©ìž ì •ì˜ ì•Œë¦¼ ìˆ˜ì¤€ì€ ì°¸ì—¬ 수준과 ë™ì¼í•©ë‹ˆë‹¤. 맞춤 알림 ìˆ˜ì¤€ì„ ì‚¬ìš©í•˜ë©´ ì¼ë¶€ ì´ë²¤íŠ¸ì— 대한 ì•Œë¦¼ë„ ë°›ê²Œë©ë‹ˆë‹¤. ìžì„¸í•œ ë‚´ìš©ì€ "
-"%{notification_link}ì„ í™•ì¸í•˜ì‹­ì‹œì˜¤."
+msgid "Custom notification levels are the same as participating levels. With custom notification levels you will also receive notifications for select events. To find out more, check out %{notification_link}."
+msgstr "ì‚¬ìš©ìž ì •ì˜ ì•Œë¦¼ ìˆ˜ì¤€ì€ ì°¸ì—¬ 수준과 ë™ì¼í•©ë‹ˆë‹¤. 맞춤 알림 ìˆ˜ì¤€ì„ ì‚¬ìš©í•˜ë©´ ì¼ë¶€ ì´ë²¤íŠ¸ì— 대한 ì•Œë¦¼ë„ ë°›ê²Œë©ë‹ˆë‹¤. ìžì„¸í•œ ë‚´ìš©ì€ %{notification_link}ì„ í™•ì¸í•˜ì‹­ì‹œì˜¤."
msgid "Cycle Analytics"
-msgstr "Cycle Analytics"
+msgstr ""
-msgid ""
-"Cycle Analytics gives an overview of how much time it takes to go from idea "
-"to production in your project."
+msgid "Cycle Analytics gives an overview of how much time it takes to go from idea to production in your project."
msgstr "Cycle Analytics는 프로ì íŠ¸ì—ì„œ ì•„ì´ë””어를 프로ë•ì…˜ìœ¼ë¡œ 옮기는 ë° ê±¸ë¦¬ëŠ” ì‹œê°„ì„ ëŒ€ëžµì ìœ¼ë¡œ ë³´ì—¬ì¤ë‹ˆë‹¤."
msgid "CycleAnalyticsStage|Code"
@@ -322,9 +347,15 @@ msgstr[0] "ë°°í¬"
msgid "Description"
msgstr "설명"
+msgid "Details"
+msgstr ""
+
msgid "Directory name"
msgstr "디렉토리 ì´ë¦„"
+msgid "Discard changes"
+msgstr ""
+
msgid "Don't show again"
msgstr "다시 표시하지 ì•ŠìŒ"
@@ -361,6 +392,24 @@ msgstr "편집"
msgid "Edit Pipeline Schedule %{id}"
msgstr "파ì´í”„ë¼ì¸ 스케줄 편집 %{id}"
+msgid "EventFilterBy|Filter by all"
+msgstr ""
+
+msgid "EventFilterBy|Filter by comments"
+msgstr ""
+
+msgid "EventFilterBy|Filter by issue events"
+msgstr ""
+
+msgid "EventFilterBy|Filter by merge events"
+msgstr ""
+
+msgid "EventFilterBy|Filter by push events"
+msgstr ""
+
+msgid "EventFilterBy|Filter by team"
+msgstr ""
+
msgid "Every day (at 4:00am)"
msgstr "ë§¤ì¼ (오전 4ì‹œì—)"
@@ -407,12 +456,36 @@ msgstr "ì´ìŠˆ ìƒì„±ì—ì„œ 프로ë•ì…˜ ë°°í¬ê¹Œì§€"
msgid "From merge request merge until deploy to production"
msgstr "머지 리퀘스트 머지ì—ì„œ 프로ë•ì…˜ í™˜ê²½ì— ë°°í¬ê¹Œì§€"
+msgid "Git storage health information has been reset"
+msgstr ""
+
+msgid "GitLab Runner section"
+msgstr ""
+
msgid "Go to your fork"
msgstr "ë‹¹ì‹ ì˜ í¬í¬ë¡œ ì´ë™í•˜ì„¸ìš”"
msgid "GoToYourFork|Fork"
msgstr "í¬í¬"
+msgid "Health Check"
+msgstr ""
+
+msgid "Health information can be retrieved from the following endpoints. More information is available"
+msgstr ""
+
+msgid "HealthCheck|Access token is"
+msgstr ""
+
+msgid "HealthCheck|Healthy"
+msgstr ""
+
+msgid "HealthCheck|No Health Problems Detected"
+msgstr ""
+
+msgid "HealthCheck|Unhealthy"
+msgstr ""
+
msgid "Home"
msgstr "홈"
@@ -422,12 +495,18 @@ msgstr "Housekeepingì´ ì„±ê³µì ìœ¼ë¡œ 시작ë˜ì—ˆìŠµë‹ˆë‹¤"
msgid "Import repository"
msgstr "저장소 가져 오기"
+msgid "Install a Runner compatible with GitLab CI"
+msgstr ""
+
msgid "Interval Pattern"
msgstr "주기 패턴"
msgid "Introducing Cycle Analytics"
msgstr "Cycle Analytics 소개"
+msgid "Issue events"
+msgstr ""
+
msgid "Jobs for last month"
msgstr "지난달 Jobs"
@@ -456,6 +535,12 @@ msgstr "최근 ì—…ë°ì´íŠ¸:"
msgid "Last commit"
msgstr "최근 커밋"
+msgid "LastPushEvent|You pushed to"
+msgstr ""
+
+msgid "LastPushEvent|at"
+msgstr ""
+
msgid "Learn more in the"
msgstr "ë” ìžì„¸ížˆ 알아보기"
@@ -475,9 +560,15 @@ msgstr[0] "최대 %d ì´ë²¤íŠ¸ 만 표시하는 것으로 제한ë©ë‹ˆë‹¤."
msgid "Median"
msgstr "중앙값"
+msgid "Merge events"
+msgstr ""
+
msgid "MissingSSHKeyWarningLink|add an SSH key"
msgstr "SSH 키 추가"
+msgid "More information is available|here"
+msgstr ""
+
msgid "New Issue"
msgid_plural "New Issues"
msgstr[0] "새 ì´ìŠˆ"
@@ -674,6 +765,9 @@ msgstr "스테ì´ì§•"
msgid "Pipeline|with stages"
msgstr "스테ì´ì§•"
+msgid "Project"
+msgstr ""
+
msgid "Project '%{project_name}' queued for deletion."
msgstr "'%{project_name}'프로ì íŠ¸ê°€ ì‚­ì œ 처리 중입니다."
@@ -689,15 +783,16 @@ msgstr "'%{project_name}'프로ì íŠ¸ê°€ ì‚­ì œë©ë‹ˆë‹¤."
msgid "Project access must be granted explicitly to each user."
msgstr "프로ì íŠ¸ 액세스는 ê° ì‚¬ìš©ìžì—게 명시ì ìœ¼ë¡œ 부여ë˜ì–´ì•¼í•©ë‹ˆë‹¤."
+msgid "Project details"
+msgstr ""
+
msgid "Project export could not be deleted."
msgstr "프로ì íŠ¸ 내보내기를 삭제할 수 없습니다."
msgid "Project export has been deleted."
msgstr "프로ì íŠ¸ 내보내기가 ì‚­ì œë˜ì—ˆìŠµë‹ˆë‹¤."
-msgid ""
-"Project export link has expired. Please generate a new export from your "
-"project settings."
+msgid "Project export link has expired. Please generate a new export from your project settings."
msgstr "프로ì íŠ¸ 내보내기 ë§í¬ê°€ 만료ë˜ì—ˆìŠµë‹ˆë‹¤. 프로ì íŠ¸ 설정ì—ì„œ 새 내보내기를 ìƒì„±í•˜ì‹­ì‹œì˜¤."
msgid "Project export started. A download link will be sent by email."
@@ -706,6 +801,9 @@ msgstr "프로ì íŠ¸ 내보내기가 시작ë˜ì—ˆìŠµë‹ˆë‹¤. 다운로드 ë§í¬ë
msgid "Project home"
msgstr "프로ì íŠ¸ 홈"
+msgid "ProjectActivityRSS|Subscribe"
+msgstr ""
+
msgid "ProjectFeature|Disabled"
msgstr "사용 안 함"
@@ -727,11 +825,14 @@ msgstr "스테ì´ì§•"
msgid "ProjectNetworkGraph|Graph"
msgstr "그래프"
+msgid "Push events"
+msgstr ""
+
msgid "Read more"
msgstr "ë” ì½ê¸°"
msgid "Readme"
-msgstr "Readme"
+msgstr ""
msgid "RefSwitcher|Branches"
msgstr "브랜치"
@@ -763,9 +864,21 @@ msgstr "ë‚˜ì¤‘ì— ë‹¤ì‹œ 알림"
msgid "Remove project"
msgstr "프로ì íŠ¸ ì‚­ì œ"
+msgid "Repository"
+msgstr ""
+
msgid "Request Access"
msgstr "액세스 요청"
+msgid "Reset git storage health information"
+msgstr ""
+
+msgid "Reset health check access token"
+msgstr ""
+
+msgid "Reset runners registration token"
+msgstr ""
+
msgid "Revert this commit"
msgstr "ì´ ì»¤ë°‹ ë˜ëŒë¦¬ê¸°"
@@ -790,6 +903,9 @@ msgstr "ì•„ì¹´ì´ë¸Œ í¬ë§· ì„ íƒ"
msgid "Select a timezone"
msgstr "시간대 ì„ íƒ"
+msgid "Select existing branch"
+msgstr ""
+
msgid "Select target branch"
msgstr "ëŒ€ìƒ ë¸Œëžœì¹˜ ì„ íƒ"
@@ -815,12 +931,18 @@ msgstr[0] "%d ê°œì˜ ì´ë²¤íŠ¸ 표시 중"
msgid "Source code"
msgstr "소스 코드"
+msgid "Specify the following URL during the Runner setup:"
+msgstr ""
+
msgid "StarProject|Star"
msgstr "별표"
msgid "Start a %{new_merge_request} with these changes"
msgstr "ì´ ë³€ê²½ 사항으로 %{new_merge_request} ì„ ì‹œìž‘í•˜ì‹­ì‹œì˜¤."
+msgid "Start the Runner!"
+msgstr ""
+
msgid "Switch branch/tag"
msgstr "스위치 브랜치/태그"
@@ -834,13 +956,11 @@ msgstr "태그 "
msgid "Target Branch"
msgstr "ëŒ€ìƒ ë¸Œëžœì¹˜"
-msgid ""
-"The coding stage shows the time from the first commit to creating the merge "
-"request. The data will automatically be added here once you create your "
-"first merge request."
+msgid "Team"
msgstr ""
-"Coding Stage는 첫 번째 커밋ì—서부터 머지 리퀘스트 ìƒì„±ê¹Œì§€ì˜ ì‹œê°„ì„ ë³´ì—¬ì¤ë‹ˆë‹¤. 첫 번째 머지 ë¦¬í€˜ìŠ¤íŠ¸ì„ ìƒì„±í•˜ë©´ ë°ì´í„°ê°€ "
-"ìžë™ìœ¼ë¡œ ì—¬ê¸°ì— ì¶”ê°€ë©ë‹ˆë‹¤."
+
+msgid "The coding stage shows the time from the first commit to creating the merge request. The data will automatically be added here once you create your first merge request."
+msgstr "Coding Stage는 첫 번째 커밋ì—서부터 머지 리퀘스트 ìƒì„±ê¹Œì§€ì˜ ì‹œê°„ì„ ë³´ì—¬ì¤ë‹ˆë‹¤. 첫 번째 머지 ë¦¬í€˜ìŠ¤íŠ¸ì„ ìƒì„±í•˜ë©´ ë°ì´í„°ê°€ ìžë™ìœ¼ë¡œ ì—¬ê¸°ì— ì¶”ê°€ë©ë‹ˆë‹¤."
msgid "The collection of events added to the data gathered for that stage."
msgstr "해당 단계ì—ì„œ 수집 ëœ ë°ì´í„°ê°€ ì´ë²¤íŠ¸ 모ìŒì— 추가ë˜ì—ˆìŠµë‹ˆë‹¤."
@@ -848,38 +968,20 @@ msgstr "해당 단계ì—ì„œ 수집 ëœ ë°ì´í„°ê°€ ì´ë²¤íŠ¸ 모ìŒì— 추가ë
msgid "The fork relationship has been removed."
msgstr "í¬í¬ 관계가 제거ë˜ì—ˆìŠµë‹ˆë‹¤."
-msgid ""
-"The issue stage shows the time it takes from creating an issue to assigning "
-"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 ""
-"ì´ìŠˆ 단계ì—는 ì´ìŠˆë¥¼ 작성하여 마ì¼ìŠ¤í†¤ìœ¼ë¡œ 지정하는 ë° ê±¸ë¦¬ëŠ” 시간 ë˜ëŠ” ì´ìŠˆ ë³´ë“œì˜ ëª©ë¡ì— ì´ìŠˆë¥¼ 추가하는 ì‹œê°„ì´ í‘œì‹œë©ë‹ˆë‹¤. ì´ "
-"ë‹¨ê³„ì˜ ë°ì´í„°ë¥¼ 보기 위해서는 ì´ìŠˆë¥¼ 먼저 작성해야 합니다."
+msgid "The issue stage shows the time it takes from creating an issue to assigning 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 "ì´ìŠˆ 단계ì—는 ì´ìŠˆë¥¼ 작성하여 마ì¼ìŠ¤í†¤ìœ¼ë¡œ 지정하는 ë° ê±¸ë¦¬ëŠ” 시간 ë˜ëŠ” ì´ìŠˆ ë³´ë“œì˜ ëª©ë¡ì— ì´ìŠˆë¥¼ 추가하는 ì‹œê°„ì´ í‘œì‹œë©ë‹ˆë‹¤. ì´ ë‹¨ê³„ì˜ ë°ì´í„°ë¥¼ 보기 위해서는 ì´ìŠˆë¥¼ 먼저 작성해야 합니다."
msgid "The phase of the development lifecycle."
msgstr "개발 ìˆ˜ëª…ì£¼ê¸°ì˜ ë‹¨ê³„."
-msgid ""
-"The pipelines schedule runs pipelines in the future, repeatedly, for "
-"specific branches or tags. Those scheduled pipelines will inherit limited "
-"project access based on their associated user."
-msgstr ""
-"파ì´í”„ë¼ì¸ ì¼ì •ì€ ë¯¸ëž˜ì— íŠ¹ì • 브랜치 ë˜ëŠ” íƒœê·¸ì— ëŒ€í•´ 반복ì ìœ¼ë¡œ 파ì´í”„ë¼ì¸ì„ 실행합니다. ì˜ˆì •ëœ íŒŒì´í”„ë¼ì¸ì€ 관련 사용ìžë¥¼ 기반으로 "
-"ì œí•œëœ í”„ë¡œì íŠ¸ 액세스 ê¶Œí•œì„ ìƒì†ë°›ìŠµë‹ˆë‹¤."
+msgid "The pipelines schedule runs pipelines in the future, repeatedly, for specific branches or tags. Those scheduled pipelines will inherit limited project access based on their associated user."
+msgstr "파ì´í”„ë¼ì¸ ì¼ì •ì€ ë¯¸ëž˜ì— íŠ¹ì • 브랜치 ë˜ëŠ” íƒœê·¸ì— ëŒ€í•´ 반복ì ìœ¼ë¡œ 파ì´í”„ë¼ì¸ì„ 실행합니다. ì˜ˆì •ëœ íŒŒì´í”„ë¼ì¸ì€ 관련 사용ìžë¥¼ 기반으로 ì œí•œëœ í”„ë¡œì íŠ¸ 액세스 ê¶Œí•œì„ ìƒì†ë°›ìŠµë‹ˆë‹¤."
-msgid ""
-"The planning stage shows the time from the previous step to pushing your "
-"first commit. This time will be added automatically once you push your first "
-"commit."
+msgid "The planning stage shows the time from the previous step to pushing your first commit. This time will be added automatically once you push your first commit."
msgstr "ê³„íš ë‹¨ê³„ì—서는 ì´ì „ 단계ì—ì„œ 첫 번째 커밋 ì‹œê°„ì´ í‘œì‹œë©ë‹ˆë‹¤. ì´ ì‹œê°„ì€ ì²« 번째 ì»¤ë°‹ì„ ëˆ„ë¥´ë©´ ìžë™ìœ¼ë¡œ 추가ë©ë‹ˆë‹¤."
-msgid ""
-"The production stage shows the total time it takes between creating an issue "
-"and deploying the code to production. The data will be automatically added "
-"once you have completed the full idea to production cycle."
-msgstr ""
-"프로ë•ì…˜ 단계ì—서는 문제를 만들고 코드를 프로ë•ì…˜ 환경으로 ë°°í¬í•˜ëŠ” ë° ê±¸ë¦¬ëŠ” ì´ ì‹œê°„ì„ ë³´ì—¬ì¤ë‹ˆë‹¤. ìƒì‚°ì£¼ê¸°ì— 대한 완전한 ì•„ì´ë””어를 "
-"ì–»ì€ í›„ì—는 ë°ì´í„°ê°€ ìžë™ìœ¼ë¡œ 추가ë©ë‹ˆë‹¤."
+msgid "The production stage shows the total time it takes between creating an issue and deploying the code to production. The data will be automatically added once you have completed the full idea to production cycle."
+msgstr "프로ë•ì…˜ 단계ì—서는 문제를 만들고 코드를 프로ë•ì…˜ 환경으로 ë°°í¬í•˜ëŠ” ë° ê±¸ë¦¬ëŠ” ì´ ì‹œê°„ì„ ë³´ì—¬ì¤ë‹ˆë‹¤. ìƒì‚°ì£¼ê¸°ì— 대한 완전한 ì•„ì´ë””어를 ì–»ì€ í›„ì—는 ë°ì´í„°ê°€ ìžë™ìœ¼ë¡œ 추가ë©ë‹ˆë‹¤."
msgid "The project can be accessed by any logged in user."
msgstr "ì´ í”„ë¡œì íŠ¸ëŠ” ë¡œê·¸ì¸ í•œ 사용ìžê°€ë§Œ 액세스 í•  수 있습니다."
@@ -890,44 +992,25 @@ msgstr "ì´ í”„ë¡œì íŠ¸ëŠ” ì¸ì¦ì—†ì´ 액세스 í•  수 있습니다."
msgid "The repository for this project does not exist."
msgstr "ì´ í”„ë¡œì íŠ¸ì˜ 저장소가 존재하지 않습니다."
-msgid ""
-"The review stage shows the time from creating the merge request to merging "
-"it. The data will automatically be added after you merge your first merge "
-"request."
-msgstr ""
-"Review 단계ì—서는 머지 리퀘스트를 작성한 후 ë¨¸ì§€í•˜ê¸°ê¹Œì§€ì˜ ì‹œê°„ì„ ë³´ì—¬ì¤ë‹ˆë‹¤. ë°ì´í„°ëŠ” 첫 번째 머지 ë¦¬í€˜ìŠ¤íŠ¸ì„ ë¨¸ì§€ í•œ í›„ì— "
-"ìžë™ìœ¼ë¡œ 추가ë©ë‹ˆë‹¤."
+msgid "The review stage shows the time from creating the merge request to merging it. The data will automatically be added after you merge your first merge request."
+msgstr "Review 단계ì—서는 머지 리퀘스트를 작성한 후 ë¨¸ì§€í•˜ê¸°ê¹Œì§€ì˜ ì‹œê°„ì„ ë³´ì—¬ì¤ë‹ˆë‹¤. ë°ì´í„°ëŠ” 첫 번째 머지 ë¦¬í€˜ìŠ¤íŠ¸ì„ ë¨¸ì§€ í•œ í›„ì— ìžë™ìœ¼ë¡œ 추가ë©ë‹ˆë‹¤."
-msgid ""
-"The staging stage shows the time between merging the MR and deploying code "
-"to the production environment. The data will be automatically added once you "
-"deploy to production for the first time."
-msgstr ""
-"Staging 단계ì—서는 MR 머지과 프로ë•ì…˜ í™˜ê²½ì— ì½”ë“œ ë°°í¬ ì‚¬ì´ì˜ ì‹œê°„ì„ ë³´ì—¬ì¤ë‹ˆë‹¤. ë°ì´í„°ë¥¼ Production í™˜ê²½ì— ì²˜ìŒ "
-"ë°°í¬í•˜ë©´ ë°ì´í„°ê°€ ìžë™ìœ¼ë¡œ 추가ë©ë‹ˆë‹¤."
+msgid "The staging stage shows the time between merging the MR and deploying code to the production environment. The data will be automatically added once you deploy to production for the first time."
+msgstr "Staging 단계ì—서는 MR 머지과 프로ë•ì…˜ í™˜ê²½ì— ì½”ë“œ ë°°í¬ ì‚¬ì´ì˜ ì‹œê°„ì„ ë³´ì—¬ì¤ë‹ˆë‹¤. ë°ì´í„°ë¥¼ Production í™˜ê²½ì— ì²˜ìŒ ë°°í¬í•˜ë©´ ë°ì´í„°ê°€ ìžë™ìœ¼ë¡œ 추가ë©ë‹ˆë‹¤."
-msgid ""
-"The testing stage shows the time GitLab CI takes to run every pipeline for "
-"the related merge request. The data will automatically be added after your "
-"first pipeline finishes running."
-msgstr ""
-"테스트 단계ì—서는 GitLab CIê°€ 관련 머지 ë¦¬í€˜ìŠ¤íŠ¸ì„ ìœ„í•´ 모든 파ì´í”„ë¼ì¸ì„ 실행하는 ë° ê±¸ë¦¬ëŠ” ì‹œê°„ì„ ë³´ì—¬ì¤ë‹ˆë‹¤. 첫 번째 "
-"파ì´í”„ë¼ì¸ ì‹¤í–‰ì´ ì™„ë£Œë˜ë©´ ë°ì´í„°ê°€ ìžë™ìœ¼ë¡œ 추가ë©ë‹ˆë‹¤."
+msgid "The testing stage shows the time GitLab CI takes to run every pipeline for the related merge request. The data will automatically be added after your first pipeline finishes running."
+msgstr "테스트 단계ì—서는 GitLab CIê°€ 관련 머지 ë¦¬í€˜ìŠ¤íŠ¸ì„ ìœ„í•´ 모든 파ì´í”„ë¼ì¸ì„ 실행하는 ë° ê±¸ë¦¬ëŠ” ì‹œê°„ì„ ë³´ì—¬ì¤ë‹ˆë‹¤. 첫 번째 파ì´í”„ë¼ì¸ ì‹¤í–‰ì´ ì™„ë£Œë˜ë©´ ë°ì´í„°ê°€ ìžë™ìœ¼ë¡œ 추가ë©ë‹ˆë‹¤."
msgid "The time taken by each data entry gathered by that stage."
msgstr "해당 단계ì—ì„œ 수집 í•œ ê° ë°ì´í„° ìž…ë ¥ì— ì†Œìš” ëœ ì‹œê°„"
-msgid ""
-"The value lying at the midpoint of a series of observed values. E.g., "
-"between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 ="
-" 6."
+msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
+msgstr "ê°’ì€ ì¼ë ¨ì˜ 관측 ê°’ 중ì ì— 있습니다. 예를 들어, 3, 5, 9 사ì´ì˜ 중간 ê°’ì€ 5입니다. 3, 5, 7, 8 사ì´ì˜ 중간 ê°’ì€ (5 + 7) / 2 = 6입니다."
+
+msgid "There are problems accessing Git storage: "
msgstr ""
-"ê°’ì€ ì¼ë ¨ì˜ 관측 ê°’ 중ì ì— 있습니다. 예를 들어, 3, 5, 9 사ì´ì˜ 중간 ê°’ì€ 5입니다. 3, 5, 7, 8 사ì´ì˜ 중간 ê°’ì€ (5 "
-"+ 7) / 2 = 6입니다."
-msgid ""
-"This means you can not push code until you create an empty repository or "
-"import existing one."
+msgid "This means you can not push code until you create an empty repository or import existing one."
msgstr "즉, 빈 저장소를 만들거나 기존 저장소를 가져올 때까지 코드를 Push 할 수 없습니다."
msgid "Time before an issue gets scheduled"
@@ -1094,6 +1177,9 @@ msgstr "íŒŒì¼ ì—…ë¡œë“œ"
msgid "UploadLink|click to upload"
msgstr "업로드하려면 í´ë¦­í•˜ì‹­ì‹œì˜¤."
+msgid "Use the following registration token during setup:"
+msgstr ""
+
msgid "Use your global notification setting"
msgstr "전체 알림 설정 사용"
@@ -1125,16 +1211,12 @@ msgid "You are going to remove %{group_name}. Removed groups CANNOT be restored!
msgstr "%{group_name} ê·¸ë£¹ì„ ì œê±°í•˜ë ¤ê³ í•©ë‹ˆë‹¤. \"ì •ë§ë¡œ\" 확실합니까?"
msgid "You are going to remove %{project_name_with_namespace}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
-msgstr "%{project_name_with_namespace} 프로ì íŠ¸ë¥¼ 삭제하려고합니다. "ì‚­ì œëœ í”„ë¡œì íŠ¸ë¥¼ ë³µì› í•  수 없습니다! \"ì •ë§ë¡œ\" 확실합니까?"
+msgstr "%{project_name_with_namespace} 프로ì íŠ¸ë¥¼ 삭제하려고합니다. ì‚­ì œëœ í”„ë¡œì íŠ¸ë¥¼ ë³µì› í•  수 없습니다! \"ì •ë§ë¡œ\" 확실합니까?"
-msgid ""
-"You are going to remove the fork relationship to source project "
-"%{forked_from_project}. Are you ABSOLUTELY sure?"
+msgid "You are going to remove the fork relationship to source project %{forked_from_project}. Are you ABSOLUTELY sure?"
msgstr "í¬í¬ 관계를 소스 프로ì íŠ¸ %{forked_from_project}ì— ëŒ€í•´ 제거하려고합니다. \"ì •ë§ë¡œ\" 확실합니까?"
-msgid ""
-"You are going to transfer %{project_name_with_namespace} to another owner. "
-"Are you ABSOLUTELY sure?"
+msgid "You are going to transfer %{project_name_with_namespace} to another owner. Are you ABSOLUTELY sure?"
msgstr "%{project_name_with_namespace}ì„ ë‹¤ë¥¸ 소유ìžì—게 ì´ì „하려고합니다. \"ì •ë§ë¡œ\" 확실합니까?"
msgid "You can only add files when you are on a branch"
@@ -1155,31 +1237,20 @@ msgstr "ì´ë©”ì¼ë¡œ ì•Œë¦¼ì„ ë°›ì§€ 않습니다."
msgid "You will only receive notifications for the events you choose"
msgstr "ì„ íƒí•œ ì´ë²¤íŠ¸ì— 대한 알림만 받습니다."
-msgid ""
-"You will only receive notifications for threads you have participated in"
+msgid "You will only receive notifications for threads you have participated in"
msgstr "참여한 ìŠ¤ë ˆë“œì— ëŒ€í•œ 알림만 받습니다."
msgid "You will receive notifications for any activity"
msgstr "모든 활ë™ì— 대한 ì•Œë¦¼ì„ ë°›ê²Œë©ë‹ˆë‹¤."
-msgid ""
-"You will receive notifications only for comments in which you were "
-"@mentioned"
+msgid "You will receive notifications only for comments in which you were @mentioned"
msgstr "ë‹¹ì‹ ì€ ë‹¹ì‹ ì´ @mentioned í•œ ì½”ë©˜íŠ¸ì— ëŒ€í•´ì„œë§Œ 통지를 받게ë©ë‹ˆë‹¤."
-msgid ""
-"You won't be able to pull or push project code via %{protocol} until you "
-"%{set_password_link} on your account"
-msgstr ""
-"ë‹¹ì‹ ì˜ ê³„ì •ì— %{set_password_link} ì„ í•˜ê¸° ì „ì—는 %{protocol} í”„ë¡œí† ì½œì„ í†µí•´ 프로ì íŠ¸ 코드를 Pull 하거나 "
-"Push 할 수 없습니다"
+msgid "You won't be able to pull or push project code via %{protocol} until you %{set_password_link} on your account"
+msgstr "ë‹¹ì‹ ì˜ ê³„ì •ì— %{set_password_link} ì„ í•˜ê¸° ì „ì—는 %{protocol} í”„ë¡œí† ì½œì„ í†µí•´ 프로ì íŠ¸ 코드를 Pull 하거나 Push í•  수 없습니다"
-msgid ""
-"You won't be able to pull or push project code via SSH until you "
-"%{add_ssh_key_link} to your profile"
-msgstr ""
-"ë‹¹ì‹ ì˜ í”„ë¡œí•„ì— %{add_ssh_key_link} 를 하기 ì „ì—는 SSH를 통해 프로ì íŠ¸ 코드를 Pull 하거나 Push í•  수 "
-"없습니다"
+msgid "You won't be able to pull or push project code via SSH until you %{add_ssh_key_link} to your profile"
+msgstr "ë‹¹ì‹ ì˜ í”„ë¡œí•„ì— %{add_ssh_key_link} 를 하기 ì „ì—는 SSH를 통해 프로ì íŠ¸ 코드를 Pull 하거나 Push í•  수 없습니다"
msgid "Your name"
msgstr "ê·€í•˜ì˜ ì´ë¦„"
@@ -1196,5 +1267,4 @@ msgstr "알림 ì´ë©”ì¼"
msgid "parent"
msgid_plural "parents"
-msgstr[0] "부모"
-
+msgstr[0] "부모" \ No newline at end of file
diff --git a/locale/pt_BR/gitlab.po b/locale/pt_BR/gitlab.po
index a2df8ea549c..d8887110867 100644
--- a/locale/pt_BR/gitlab.po
+++ b/locale/pt_BR/gitlab.po
@@ -1,42 +1,55 @@
-# Alexandre Alencar <alexandre.alencar@gmail.com>, 2017. #zanata
-# Fabio Beneditto <fabiobeneditto@gmail.com>, 2017. #zanata
-# Leandro Nunes dos Santos <leandronunes@gmail.com>, 2017. #zanata
-# Huang Tao <htve@outlook.com>, 2017. #zanata
msgid ""
msgstr ""
-"Project-Id-Version: gitlab 1.0.0\n"
+"Project-Id-Version: gitlab-ee\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2017-07-13 12:07-0500\n"
+"POT-Creation-Date: 2017-08-18 14:15+0530\n"
+"PO-Revision-Date: 2017-08-23 10:14-0400\n"
+"Last-Translator: gitlab <mbartlett+crowdin@gitlab.com>\n"
+"Language-Team: Portuguese, Brazilian\n"
+"Language: pt_BR\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"Language-Team: Portuguese (Brazil) (https://translate.zanata.org/project/view/GitLab)\n"
-"PO-Revision-Date: 2017-08-03 11:29-0400\n"
-"Last-Translator: Alexandre Alencar <alexandre.alencar@gmail.com>\n"
-"Language: pt-BR\n"
-"X-Generator: Zanata 3.9.6\n"
-"Plural-Forms: nplurals=2; plural=(n != 1)\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Generator: crowdin.com\n"
+"X-Crowdin-Project: gitlab-ee\n"
+"X-Crowdin-Language: pt-BR\n"
+"X-Crowdin-File: /master/locale/gitlab.pot\n"
-msgid "%s additional commit has been omitted to prevent performance issues."
-msgid_plural ""
-"%s additional commits have been omitted to prevent performance issues."
+msgid "%d commit"
+msgid_plural "%d commits"
msgstr[0] ""
-"%s commit adicional foi omitido para prevenir problemas de performance."
msgstr[1] ""
-"%s commits adicionais foram omitidos para prevenir problemas de performance."
-msgid "%d commit"
-msgid_plural "%d commits"
-msgstr[0] "%d commit"
-msgstr[1] "%d commits"
+msgid "%s additional commit has been omitted to prevent performance issues."
+msgid_plural "%s additional commits have been omitted to prevent performance issues."
+msgstr[0] "%s commit adicional foi omitido para prevenir problemas de performance."
+msgstr[1] "%s commits adicionais foram omitidos para prevenir problemas de performance."
msgid "%{commit_author_link} committed %{commit_timeago}"
msgstr "%{commit_author_link} fez commit %{commit_timeago}"
+msgid "%{number_of_failures} of %{maximum_failures} failures. GitLab will allow access on the next attempt."
+msgstr ""
+
+msgid "%{number_of_failures} of %{maximum_failures} failures. GitLab will block access for %{number_of_seconds} seconds."
+msgstr ""
+
+msgid "%{number_of_failures} of %{maximum_failures} failures. GitLab will not retry automatically. Reset storage information when the problem is resolved."
+msgstr ""
+
+msgid "%{storage_name}: failed storage access attempt on host:"
+msgid_plural "%{storage_name}: %{failed_attempts} failed storage access attempts:"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "(checkout the %{link} for information on how to install it)."
+msgstr ""
+
msgid "1 pipeline"
msgid_plural "%d pipelines"
-msgstr[0] "1 pipeline"
-msgstr[1] "%d pipelines"
+msgstr[0] ""
+msgstr[1] ""
msgid "A collection of graphs regarding Continuous Integration"
msgstr "Uma coleção de gráficos sobre Integração Contínua"
@@ -44,6 +57,9 @@ msgstr "Uma coleção de gráficos sobre Integração Contínua"
msgid "About auto deploy"
msgstr "Sobre o deploy automático"
+msgid "Access to failing storages has been temporarily disabled to allow the mount to recover. Reset storage information after the issue has been resolved to allow access again."
+msgstr ""
+
msgid "Active"
msgstr "Ativo"
@@ -65,28 +81,37 @@ msgstr "Adicionar chave SSH ao seu perfil para fazer pull ou push via SSH."
msgid "Add new directory"
msgstr "Adicionar novo diretório"
+msgid "All"
+msgstr ""
+
msgid "Archived project! Repository is read-only"
msgstr "Projeto arquivado! O repositório é somente leitura"
msgid "Are you sure you want to delete this pipeline schedule?"
msgstr "Tem certeza que deseja excluir este agendamento de pipeline?"
+msgid "Are you sure you want to discard your changes?"
+msgstr ""
+
+msgid "Are you sure you want to reset registration token?"
+msgstr ""
+
+msgid "Are you sure you want to reset the health check token?"
+msgstr ""
+
+msgid "Are you sure?"
+msgstr ""
+
msgid "Attach a file by drag &amp; drop or %{upload_link}"
msgstr "Para anexar arquivo, arraste e solte ou %{upload_link}"
msgid "Branch"
msgid_plural "Branches"
-msgstr[0] "Branch"
-msgstr[1] "Branches"
+msgstr[0] ""
+msgstr[1] ""
-msgid ""
-"Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, "
-"choose a GitLab CI Yaml template and commit your changes. "
-"%{link_to_autodeploy_doc}"
-msgstr ""
-"O branch <strong>%{branch_name}</strong> foi criado. Para configurar o "
-"deploy automático, selecione um modelo de Yaml do GitLab CI e commit suas "
-"mudanças. %{link_to_autodeploy_doc}"
+msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
+msgstr "O branch <strong>%{branch_name}</strong> foi criado. Para configurar o deploy automático, selecione um modelo de Yaml do GitLab CI e commit suas mudanças. %{link_to_autodeploy_doc}"
msgid "BranchSwitcherPlaceholder|Search branches"
msgstr "Procurar por branches"
@@ -95,7 +120,7 @@ msgid "BranchSwitcherTitle|Switch branch"
msgstr "Mudar de branch"
msgid "Branches"
-msgstr "Branches"
+msgstr ""
msgid "Browse Directory"
msgstr "Navegar no Diretório"
@@ -118,6 +143,9 @@ msgstr "Configuração da IC"
msgid "Cancel"
msgstr "Cancelar"
+msgid "Cancel edit"
+msgstr ""
+
msgid "ChangeTypeActionLabel|Pick into branch"
msgstr "Pick para um branch"
@@ -196,10 +224,13 @@ msgstr "ignorado"
msgid "CiStatus|running"
msgstr "executando"
+msgid "Comments"
+msgstr ""
+
msgid "Commit"
msgid_plural "Commits"
-msgstr[0] "Commit"
-msgstr[1] "Commits"
+msgstr[0] ""
+msgstr[1] ""
msgid "Commit duration in minutes for last 30 commits"
msgstr "Duração do commit em minutos para os últimos 30 commits"
@@ -214,7 +245,7 @@ msgid "CommitMessage|Add %{file_name}"
msgstr "Adicionar %{file_name}"
msgid "Commits"
-msgstr "Commits"
+msgstr ""
msgid "Commits feed"
msgstr "Feed de commits"
@@ -243,12 +274,11 @@ msgstr "Copiar SHA do commit para a área de transferência"
msgid "Create New Directory"
msgstr "Criar Novo Diretório"
-msgid ""
-"Create a personal access token on your account to pull or push via "
-"%{protocol}."
+msgid "Create a new branch"
msgstr ""
-"Crie um token de acesso pessoal na sua conta para dar pull ou push via "
-"%{protocol}."
+
+msgid "Create a personal access token on your account to pull or push via %{protocol}."
+msgstr "Crie um token de acesso pessoal na sua conta para dar pull ou push via %{protocol}."
msgid "Create directory"
msgstr "Criar diretório"
@@ -280,25 +310,14 @@ msgstr "Sintaxe do cron"
msgid "Custom notification events"
msgstr "Eventos de notificação personalizados"
-msgid ""
-"Custom notification levels are the same as participating levels. With custom "
-"notification levels you will also receive notifications for select events. "
-"To find out more, check out %{notification_link}."
-msgstr ""
-"Níveis de notificação personalizados são equivalentes a níveis de "
-"participação. Com níveis de notificação personalizados você também será "
-"notificado sobre eventos selecionados. Para mais informações, visite "
-"%{notification_link}."
+msgid "Custom notification levels are the same as participating levels. With custom notification levels you will also receive notifications for select events. To find out more, check out %{notification_link}."
+msgstr "Níveis de notificação personalizados são equivalentes a níveis de participação. Com níveis de notificação personalizados você também será notificado sobre eventos selecionados. Para mais informações, visite %{notification_link}."
msgid "Cycle Analytics"
msgstr "Análise de Ciclo"
-msgid ""
-"Cycle Analytics gives an overview of how much time it takes to go from idea "
-"to production in your project."
-msgstr ""
-"A Análise de Ciclo fornece uma visão geral de quanto tempo uma ideia demora "
-"para ir para produção em seu projeto."
+msgid "Cycle Analytics gives an overview of how much time it takes to go from idea to production in your project."
+msgstr "A Análise de Ciclo fornece uma visão geral de quanto tempo uma ideia demora para ir para produção em seu projeto."
msgid "CycleAnalyticsStage|Code"
msgstr "Código"
@@ -335,9 +354,15 @@ msgstr[1] "Implantações"
msgid "Description"
msgstr "Descrição"
+msgid "Details"
+msgstr ""
+
msgid "Directory name"
msgstr "Nome do diretório"
+msgid "Discard changes"
+msgstr ""
+
msgid "Don't show again"
msgstr "Não exibir novamente"
@@ -374,6 +399,24 @@ msgstr "Alterar"
msgid "Edit Pipeline Schedule %{id}"
msgstr "Alterar Agendamento do Pipeline %{id}"
+msgid "EventFilterBy|Filter by all"
+msgstr ""
+
+msgid "EventFilterBy|Filter by comments"
+msgstr ""
+
+msgid "EventFilterBy|Filter by issue events"
+msgstr ""
+
+msgid "EventFilterBy|Filter by merge events"
+msgstr ""
+
+msgid "EventFilterBy|Filter by push events"
+msgstr ""
+
+msgid "EventFilterBy|Filter by team"
+msgstr ""
+
msgid "Every day (at 4:00am)"
msgstr "Todos os dias (às 4:00)"
@@ -409,8 +452,8 @@ msgstr "publicado por"
msgid "Fork"
msgid_plural "Forks"
-msgstr[0] "Fork"
-msgstr[1] "Forks"
+msgstr[0] ""
+msgstr[1] ""
msgid "ForkedFromProjectPath|Forked from"
msgstr "Fork criado a partir de"
@@ -421,12 +464,36 @@ msgstr "Da abertura de tarefas até a implantação para a produção"
msgid "From merge request merge until deploy to production"
msgstr "Do merge request até a implantação em produção"
+msgid "Git storage health information has been reset"
+msgstr ""
+
+msgid "GitLab Runner section"
+msgstr ""
+
msgid "Go to your fork"
msgstr "Ir para seu fork"
msgid "GoToYourFork|Fork"
msgstr "Fork"
+msgid "Health Check"
+msgstr ""
+
+msgid "Health information can be retrieved from the following endpoints. More information is available"
+msgstr ""
+
+msgid "HealthCheck|Access token is"
+msgstr ""
+
+msgid "HealthCheck|Healthy"
+msgstr ""
+
+msgid "HealthCheck|No Health Problems Detected"
+msgstr ""
+
+msgid "HealthCheck|Unhealthy"
+msgstr ""
+
msgid "Home"
msgstr "Início"
@@ -436,12 +503,18 @@ msgstr "Manutenção iniciada com sucesso"
msgid "Import repository"
msgstr "Importar repositório"
+msgid "Install a Runner compatible with GitLab CI"
+msgstr ""
+
msgid "Interval Pattern"
msgstr "Padrão de intervalo"
msgid "Introducing Cycle Analytics"
msgstr "Apresentando a Análise de Ciclo"
+msgid "Issue events"
+msgstr ""
+
msgid "Jobs for last month"
msgstr "Jobs no último mês"
@@ -471,6 +544,12 @@ msgstr "Última Atualização"
msgid "Last commit"
msgstr "Último commit"
+msgid "LastPushEvent|You pushed to"
+msgstr ""
+
+msgid "LastPushEvent|at"
+msgstr ""
+
msgid "Learn more in the"
msgstr "Saiba mais em"
@@ -491,9 +570,15 @@ msgstr[1] "Limitado a mostrar %d eventos, no máximo"
msgid "Median"
msgstr "Mediana"
+msgid "Merge events"
+msgstr ""
+
msgid "MissingSSHKeyWarningLink|add an SSH key"
msgstr "adicione uma chave SSH"
+msgid "More information is available|here"
+msgstr ""
+
msgid "New Issue"
msgid_plural "New Issues"
msgstr[0] "Nova Issue"
@@ -605,7 +690,7 @@ msgid "Owner"
msgstr "Proprietário"
msgid "Pipeline"
-msgstr "Pipeline"
+msgstr ""
msgid "Pipeline Health"
msgstr "Saúde da Pipeline"
@@ -674,7 +759,7 @@ msgid "PipelineSheduleIntervalPattern|Custom"
msgstr "Personalizado"
msgid "Pipelines"
-msgstr "Pipelines"
+msgstr ""
msgid "Pipelines charts"
msgstr "Gráficos de pipelines"
@@ -691,6 +776,9 @@ msgstr "com etapa"
msgid "Pipeline|with stages"
msgstr "com etapas"
+msgid "Project"
+msgstr ""
+
msgid "Project '%{project_name}' queued for deletion."
msgstr "Projeto'%{project_name}' marcado para exclusão."
@@ -704,8 +792,10 @@ msgid "Project '%{project_name}' will be deleted."
msgstr "Projeto '%{project_name}' será excluído."
msgid "Project access must be granted explicitly to each user."
+msgstr "Acesso ao projeto deve ser concedido explicitamente para cada usuário."
+
+msgid "Project details"
msgstr ""
-"Acesso ao projeto deve ser concedido explicitamente para cada usuário."
msgid "Project export could not be deleted."
msgstr "A exportação do projeto não pôde ser excluída."
@@ -713,21 +803,18 @@ msgstr "A exportação do projeto não pôde ser excluída."
msgid "Project export has been deleted."
msgstr "Exportação do projeto excluída."
-msgid ""
-"Project export link has expired. Please generate a new export from your "
-"project settings."
-msgstr ""
-"O link para a exportação do projeto expirou. Favor gerar uma nova exportação "
-"a partir das configurações do projeto."
+msgid "Project export link has expired. Please generate a new export from your project settings."
+msgstr "O link para a exportação do projeto expirou. Favor gerar uma nova exportação a partir das configurações do projeto."
msgid "Project export started. A download link will be sent by email."
-msgstr ""
-"Exportação do projeto iniciada. Um link para baixá-la será enviado por email."
-""
+msgstr "Exportação do projeto iniciada. Um link para baixá-la será enviado por email."
msgid "Project home"
msgstr "Página inicial do projeto"
+msgid "ProjectActivityRSS|Subscribe"
+msgstr ""
+
msgid "ProjectFeature|Disabled"
msgstr "Desabilitado"
@@ -749,6 +836,9 @@ msgstr "Etapa"
msgid "ProjectNetworkGraph|Graph"
msgstr "Ãrvore"
+msgid "Push events"
+msgstr ""
+
msgid "Read more"
msgstr "Leia mais"
@@ -785,9 +875,21 @@ msgstr "Lembrar mais tarde"
msgid "Remove project"
msgstr "Remover projeto"
+msgid "Repository"
+msgstr ""
+
msgid "Request Access"
msgstr "Solicitar acesso"
+msgid "Reset git storage health information"
+msgstr ""
+
+msgid "Reset health check access token"
+msgstr ""
+
+msgid "Reset runners registration token"
+msgstr ""
+
msgid "Revert this commit"
msgstr "Reverter este commit"
@@ -812,13 +914,14 @@ msgstr "Selecionar Formato do Arquivo"
msgid "Select a timezone"
msgstr "Selecionar fuso horário"
+msgid "Select existing branch"
+msgstr ""
+
msgid "Select target branch"
msgstr "Selecionar branch de destino"
msgid "Set a password on your account to pull or push via %{protocol}."
-msgstr ""
-"Defina uma senha para sua conta para aceitar ou entregar código via "
-"%{protocol}."
+msgstr "Defina uma senha para sua conta para aceitar ou entregar código via %{protocol}."
msgid "Set up CI"
msgstr "Configurar CI"
@@ -840,34 +943,37 @@ msgstr[1] "Mostrando %d eventos"
msgid "Source code"
msgstr "Código-fonte"
+msgid "Specify the following URL during the Runner setup:"
+msgstr ""
+
msgid "StarProject|Star"
msgstr "Marcar"
msgid "Start a %{new_merge_request} with these changes"
msgstr "Iniciar um %{new_merge_request} a partir dessas alterações"
+msgid "Start the Runner!"
+msgstr ""
+
msgid "Switch branch/tag"
msgstr "Trocar branch/tag"
msgid "Tag"
msgid_plural "Tags"
-msgstr[0] "Tag"
-msgstr[1] "Tags"
+msgstr[0] ""
+msgstr[1] ""
msgid "Tags"
-msgstr "Tags"
+msgstr ""
msgid "Target Branch"
msgstr "Branch de destino"
-msgid ""
-"The coding stage shows the time from the first commit to creating the merge "
-"request. The data will automatically be added here once you create your "
-"first merge request."
+msgid "Team"
msgstr ""
-"A etapa de codificação mostra o tempo desde a entrega do primeiro commit até "
-"a criação do merge request. Os dados serão automaticamente adicionados aqui "
-"desde o momento de criação do merge request."
+
+msgid "The coding stage shows the time from the first commit to creating the merge request. The data will automatically be added here once you create your first merge request."
+msgstr "A etapa de codificação mostra o tempo desde a entrega do primeiro commit até a criação do merge request. Os dados serão automaticamente adicionados aqui desde o momento de criação do merge request."
msgid "The collection of events added to the data gathered for that stage."
msgstr "A coleção de eventos adicionados aos dados coletados para essa etapa."
@@ -875,44 +981,20 @@ msgstr "A coleção de eventos adicionados aos dados coletados para essa etapa."
msgid "The fork relationship has been removed."
msgstr "O relacionamento como fork foi removido."
-msgid ""
-"The issue stage shows the time it takes from creating an issue to assigning "
-"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 ""
-"A etapa de planejamento mostra o tempo que se leva desde a criação de uma "
-"issue até sua atribuição à um milestone, ou sua adição a uma lista no seu "
-"Issue Board. Comece a criar issues para ver dados para esta etapa."
+msgid "The issue stage shows the time it takes from creating an issue to assigning 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 "A etapa de planejamento mostra o tempo que se leva desde a criação de uma issue até sua atribuição à um milestone, ou sua adição a uma lista no seu Issue Board. Comece a criar issues para ver dados para esta etapa."
msgid "The phase of the development lifecycle."
msgstr "A fase do ciclo de vida do desenvolvimento."
-msgid ""
-"The pipelines schedule runs pipelines in the future, repeatedly, for "
-"specific branches or tags. Those scheduled pipelines will inherit limited "
-"project access based on their associated user."
-msgstr ""
-"O agendamento de pipeline executa pipelines no futuro, repetidamente, para "
-"branches ou tags específicas. Essas pipelines agendadas terão acesso "
-"limitado ao projeto baseado no seu usuário associado."
+msgid "The pipelines schedule runs pipelines in the future, repeatedly, for specific branches or tags. Those scheduled pipelines will inherit limited project access based on their associated user."
+msgstr "O agendamento de pipeline executa pipelines no futuro, repetidamente, para branches ou tags específicas. Essas pipelines agendadas terão acesso limitado ao projeto baseado no seu usuário associado."
-msgid ""
-"The planning stage shows the time from the previous step to pushing your "
-"first commit. This time will be added automatically once you push your first "
-"commit."
-msgstr ""
-"A etapa de planejamento mostra o tempo do passo anterior até a publicação de "
-"seu primeiro conjunto de mudanças. Este tempo será adicionado "
-"automaticamente assim que você enviar seu primeiro conjunto de mudanças."
+msgid "The planning stage shows the time from the previous step to pushing your first commit. This time will be added automatically once you push your first commit."
+msgstr "A etapa de planejamento mostra o tempo do passo anterior até a publicação de seu primeiro conjunto de mudanças. Este tempo será adicionado automaticamente assim que você enviar seu primeiro conjunto de mudanças."
-msgid ""
-"The production stage shows the total time it takes between creating an issue "
-"and deploying the code to production. The data will be automatically added "
-"once you have completed the full idea to production cycle."
-msgstr ""
-"A etapa de produção mostra o tempo total que leva entre criar uma issue e "
-"implantar o código em produção. Os dados serão adicionados automaticamente "
-"assim que você completar todo o ciclo de produção."
+msgid "The production stage shows the total time it takes between creating an issue and deploying the code to production. The data will be automatically added once you have completed the full idea to production cycle."
+msgstr "A etapa de produção mostra o tempo total que leva entre criar uma issue e implantar o código em produção. Os dados serão adicionados automaticamente assim que você completar todo o ciclo de produção."
msgid "The project can be accessed by any logged in user."
msgstr "O projeto pode ser acessado por qualquer usuário autenticado."
@@ -923,51 +1005,26 @@ msgstr "O projeto pode ser acessado sem a necessidade de autenticação."
msgid "The repository for this project does not exist."
msgstr "Não existe repositório para este projeto."
-msgid ""
-"The review stage shows the time from creating the merge request to merging "
-"it. The data will automatically be added after you merge your first merge "
-"request."
-msgstr ""
-"A etapa de revisão mostra o tempo de criação de uma solicitação de "
-"incorporação até sua aceitação. Os dados serão automaticamente adicionados "
-"depois que sua primeira solicitação de incorporação for aceita."
+msgid "The review stage shows the time from creating the merge request to merging it. The data will automatically be added after you merge your first merge request."
+msgstr "A etapa de revisão mostra o tempo de criação de uma solicitação de incorporação até sua aceitação. Os dados serão automaticamente adicionados depois que sua primeira solicitação de incorporação for aceita."
-msgid ""
-"The staging stage shows the time between merging the MR and deploying code "
-"to the production environment. The data will be automatically added once you "
-"deploy to production for the first time."
-msgstr ""
-"A etapa de homologação mostra o tempo entre o aceite da solicitação de "
-"incorporação e a implantação do código no ambiente de produção. Os dados "
-"serão automaticamente adicionados depois que você implantar em produção pela "
-"primeira vez."
+msgid "The staging stage shows the time between merging the MR and deploying code to the production environment. The data will be automatically added once you deploy to production for the first time."
+msgstr "A etapa de homologação mostra o tempo entre o aceite da solicitação de incorporação e a implantação do código no ambiente de produção. Os dados serão automaticamente adicionados depois que você implantar em produção pela primeira vez."
-msgid ""
-"The testing stage shows the time GitLab CI takes to run every pipeline for "
-"the related merge request. The data will automatically be added after your "
-"first pipeline finishes running."
-msgstr ""
-"A etapa de testes mostra o tempo que o GitLab CI leva para executar cada "
-"pipeline para a solicitação de incorporação associada. Os dados serão "
-"automaticamente adicionados após a conclusão do primeiro pipeline."
+msgid "The testing stage shows the time GitLab CI takes to run every pipeline for the related merge request. The data will automatically be added after your first pipeline finishes running."
+msgstr "A etapa de testes mostra o tempo que o GitLab CI leva para executar cada pipeline para a solicitação de incorporação associada. Os dados serão automaticamente adicionados após a conclusão do primeiro pipeline."
msgid "The time taken by each data entry gathered by that stage."
msgstr "O tempo necessário por cada entrada de dados reunida por essa etapa."
-msgid ""
-"The value lying at the midpoint of a series of observed values. E.g., "
-"between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 ="
-" 6."
-msgstr ""
-"O valor situado no ponto médio de uma série de valores observados. Ex., "
-"entre 3, 5, 9, a mediana é 5. Entre 3, 5, 7, 8, a mediana é (5+7)/2 = 6."
+msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
+msgstr "O valor situado no ponto médio de uma série de valores observados. Ex., entre 3, 5, 9, a mediana é 5. Entre 3, 5, 7, 8, a mediana é (5+7)/2 = 6."
-msgid ""
-"This means you can not push code until you create an empty repository or "
-"import existing one."
+msgid "There are problems accessing Git storage: "
msgstr ""
-"Isto significa que você não pode entregar código até que crie um repositório "
-"vazio ou importe um existente."
+
+msgid "This means you can not push code until you create an empty repository or import existing one."
+msgstr "Isto significa que você não pode entregar código até que crie um repositório vazio ou importe um existente."
msgid "Time before an issue gets scheduled"
msgstr "Tempo até que uma issue seja agendada"
@@ -976,9 +1033,7 @@ msgid "Time before an issue starts implementation"
msgstr "Tempo até que uma issue comece a ser implementado"
msgid "Time between merge request creation and merge/close"
-msgstr ""
-"Tempo entre a criação da solicitação de incorporação e a aceitação/"
-"fechamento"
+msgstr "Tempo entre a criação da solicitação de incorporação e a aceitação/fechamento"
msgid "Time until first merge request"
msgstr "Tempo até a primeira solicitação de incorporação"
@@ -1137,6 +1192,9 @@ msgstr "Enviar arquivo"
msgid "UploadLink|click to upload"
msgstr "clique para fazer upload"
+msgid "Use the following registration token during setup:"
+msgstr ""
+
msgid "Use your global notification setting"
msgstr "Utilizar configuração de notificação global"
@@ -1164,19 +1222,17 @@ msgstr "Esta etapa não possui dados suficientes para exibição."
msgid "Withdraw Access Request"
msgstr "Remover Requisição de Acesso"
-
msgid "You are going to remove %{group_name}. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr "Você vai remover %{group_name}. Grupos removidos NÃO PODEM ser restaurados! Você está ABSOLUTAMENTE certo?"
msgid "You are going to remove %{project_name_with_namespace}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr "Você irá remover %{project_name_with_namespace}. O projeto removido NÃO PODE ser restaurado! Tem certeza ABSOLUTA?"
-msgid ""
-"You are going to transfer %{project_name_with_namespace} to another owner. "
-"Are you ABSOLUTELY sure?"
+msgid "You are going to remove the fork relationship to source project %{forked_from_project}. Are you ABSOLUTELY sure?"
msgstr ""
-"Você irá transferir %{project_name_with_namespace} para outro proprietário. "
-"Tem certeza ABSOLUTA?"
+
+msgid "You are going to transfer %{project_name_with_namespace} to another owner. Are you ABSOLUTELY sure?"
+msgstr "Você irá transferir %{project_name_with_namespace} para outro proprietário. Tem certeza ABSOLUTA?"
msgid "You can only add files when you are on a branch"
msgstr "Você somente pode adicionar arquivos quando estiver em um branch"
@@ -1196,31 +1252,20 @@ msgstr "Você não será notificado por email"
msgid "You will only receive notifications for the events you choose"
msgstr "Você será notificado apenas sobre eventos selecionados"
-msgid ""
-"You will only receive notifications for threads you have participated in"
+msgid "You will only receive notifications for threads you have participated in"
msgstr "Você será notificado apenas sobre tópicos nos quais participou"
msgid "You will receive notifications for any activity"
msgstr "Você será notificado sobre qualquer atividade"
-msgid ""
-"You will receive notifications only for comments in which you were "
-"@mentioned"
+msgid "You will receive notifications only for comments in which you were @mentioned"
msgstr "Você será notificado apenas sobre comentários que te @mencionam"
-msgid ""
-"You won't be able to pull or push project code via %{protocol} until you "
-"%{set_password_link} on your account"
-msgstr ""
-"Você não poderá fazer pull ou push via %{protocol} até que "
-"%{set_password_link} para sua conta"
+msgid "You won't be able to pull or push project code via %{protocol} until you %{set_password_link} on your account"
+msgstr "Você não poderá fazer pull ou push via %{protocol} até que %{set_password_link} para sua conta"
-msgid ""
-"You won't be able to pull or push project code via SSH until you "
-"%{add_ssh_key_link} to your profile"
-msgstr ""
-"Você não conseguirá fazer pull ou push no projeto via SSH até que adicione "
-"%{add_ssh_key_link} ao seu perfil"
+msgid "You won't be able to pull or push project code via SSH until you %{add_ssh_key_link} to your profile"
+msgstr "Você não conseguirá fazer pull ou push no projeto via SSH até que adicione %{add_ssh_key_link} ao seu perfil"
msgid "Your name"
msgstr "Seu nome"
@@ -1239,5 +1284,4 @@ msgstr "emails de notificação"
msgid "parent"
msgid_plural "parents"
msgstr[0] "pai"
-msgstr[1] "pais"
-
+msgstr[1] "pais" \ No newline at end of file
diff --git a/locale/ru/gitlab.po b/locale/ru/gitlab.po
index 6661232850a..926995d1f91 100644
--- a/locale/ru/gitlab.po
+++ b/locale/ru/gitlab.po
@@ -1,33 +1,20 @@
-# SAS <Stepanov.sa@bashkortostan.ru>, 2017. #zanata
-# Huang Tao <htve@outlook.com>, 2017. #zanata
msgid ""
msgstr ""
-"Project-Id-Version: gitlab 1.0.0\n"
+"Project-Id-Version: gitlab-ee\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2017-07-13 12:07-0500\n"
+"POT-Creation-Date: 2017-08-18 14:15+0530\n"
+"PO-Revision-Date: 2017-08-23 09:41-0400\n"
+"Last-Translator: gitlab <mbartlett+crowdin@gitlab.com>\n"
+"Language-Team: Russian\n"
+"Language: ru_RU\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"Language-Team: Russian (https://translate.zanata.org/project/view/GitLab)\n"
-"PO-Revision-Date: 2017-08-06 11:23-0400\n"
-"Last-Translator: Ðндрей П. <fenixnow33@gmail.com>\n"
-"Language: ru\n"
-"X-Generator: Zanata 3.9.6\n"
-"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
-"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)\n"
-
-msgid "%s additional commit has been omitted to prevent performance issues."
-msgid_plural ""
-"%s additional commits have been omitted to prevent performance issues."
-msgstr[0] ""
-"%s добавленный коммит был иÑключен Ð´Ð»Ñ Ð¿Ñ€ÐµÐ´Ð¾Ñ‚Ð²Ñ€Ð°Ñ‰ÐµÐ½Ð¸Ñ Ð¿Ñ€Ð¾Ð±Ð»ÐµÐ¼ Ñ "
-"производительноÑтью."
-msgstr[1] ""
-"%s добавленные коммиты были иÑключены Ð´Ð»Ñ Ð¿Ñ€ÐµÐ´Ð¾Ñ‚Ð²Ñ€Ð°Ñ‰ÐµÐ½Ð¸Ñ Ð¿Ñ€Ð¾Ð±Ð»ÐµÐ¼ Ñ "
-"производительноÑтью."
-msgstr[2] ""
-"%s добавленные коммиты были иÑключены Ð´Ð»Ñ Ð¿Ñ€ÐµÐ´Ð¾Ñ‚Ð²Ñ€Ð°Ñ‰ÐµÐ½Ð¸Ñ Ð¿Ñ€Ð¾Ð±Ð»ÐµÐ¼ Ñ "
-"производительноÑтью."
+"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
+"X-Generator: crowdin.com\n"
+"X-Crowdin-Project: gitlab-ee\n"
+"X-Crowdin-Language: ru\n"
+"X-Crowdin-File: /master/locale/gitlab.pot\n"
msgid "%d commit"
msgid_plural "%d commits"
@@ -35,9 +22,33 @@ msgstr[0] "%d коммит"
msgstr[1] "%d коммитов"
msgstr[2] "%d коммитов"
+msgid "%s additional commit has been omitted to prevent performance issues."
+msgid_plural "%s additional commits have been omitted to prevent performance issues."
+msgstr[0] "%s добавленный коммит был иÑключен Ð´Ð»Ñ Ð¿Ñ€ÐµÐ´Ð¾Ñ‚Ð²Ñ€Ð°Ñ‰ÐµÐ½Ð¸Ñ Ð¿Ñ€Ð¾Ð±Ð»ÐµÐ¼ Ñ Ð¿Ñ€Ð¾Ð¸Ð·Ð²Ð¾Ð´Ð¸Ñ‚ÐµÐ»ÑŒÐ½Ð¾Ñтью."
+msgstr[1] "%s добавленные коммиты были иÑключены Ð´Ð»Ñ Ð¿Ñ€ÐµÐ´Ð¾Ñ‚Ð²Ñ€Ð°Ñ‰ÐµÐ½Ð¸Ñ Ð¿Ñ€Ð¾Ð±Ð»ÐµÐ¼ Ñ Ð¿Ñ€Ð¾Ð¸Ð·Ð²Ð¾Ð´Ð¸Ñ‚ÐµÐ»ÑŒÐ½Ð¾Ñтью."
+msgstr[2] "%s добавленные коммиты были иÑключены Ð´Ð»Ñ Ð¿Ñ€ÐµÐ´Ð¾Ñ‚Ð²Ñ€Ð°Ñ‰ÐµÐ½Ð¸Ñ Ð¿Ñ€Ð¾Ð±Ð»ÐµÐ¼ Ñ Ð¿Ñ€Ð¾Ð¸Ð·Ð²Ð¾Ð´Ð¸Ñ‚ÐµÐ»ÑŒÐ½Ð¾Ñтью."
+
msgid "%{commit_author_link} committed %{commit_timeago}"
msgstr "%{commit_author_link} коммичено %{commit_timeago}"
+msgid "%{number_of_failures} of %{maximum_failures} failures. GitLab will allow access on the next attempt."
+msgstr ""
+
+msgid "%{number_of_failures} of %{maximum_failures} failures. GitLab will block access for %{number_of_seconds} seconds."
+msgstr ""
+
+msgid "%{number_of_failures} of %{maximum_failures} failures. GitLab will not retry automatically. Reset storage information when the problem is resolved."
+msgstr ""
+
+msgid "%{storage_name}: failed storage access attempt on host:"
+msgid_plural "%{storage_name}: %{failed_attempts} failed storage access attempts:"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "(checkout the %{link} for information on how to install it)."
+msgstr ""
+
msgid "1 pipeline"
msgid_plural "%d pipelines"
msgstr[0] "1 конвейер"
@@ -50,6 +61,9 @@ msgstr "Графики отноÑительно непрерывной интеÐ
msgid "About auto deploy"
msgstr "ÐвтоматичеÑкое развертывание"
+msgid "Access to failing storages has been temporarily disabled to allow the mount to recover. Reset storage information after the issue has been resolved to allow access again."
+msgstr ""
+
msgid "Active"
msgstr "Ðктивный"
@@ -66,19 +80,32 @@ msgid "Add License"
msgstr "Добавить лицензию"
msgid "Add an SSH key to your profile to pull or push via SSH."
-msgstr ""
-"Добавьте ключ SSH в Ñвой профиль, чтобы отправлÑÑ‚ÑŒ или получать код через "
-"SSH."
+msgstr "Добавьте ключ SSH в Ñвой профиль, чтобы отправлÑÑ‚ÑŒ или получать код через SSH."
msgid "Add new directory"
msgstr "Добавить каталог"
+msgid "All"
+msgstr ""
+
msgid "Archived project! Repository is read-only"
msgstr "Ðрхивный проект! Репозиторий доÑтупен только Ð´Ð»Ñ Ñ‡Ñ‚ÐµÐ½Ð¸Ñ"
msgid "Are you sure you want to delete this pipeline schedule?"
msgstr "Ð’Ñ‹ дейÑтвительно хотите удалить Ñто раÑпиÑание конвейера?"
+msgid "Are you sure you want to discard your changes?"
+msgstr ""
+
+msgid "Are you sure you want to reset registration token?"
+msgstr ""
+
+msgid "Are you sure you want to reset the health check token?"
+msgstr ""
+
+msgid "Are you sure?"
+msgstr ""
+
msgid "Attach a file by drag &amp; drop or %{upload_link}"
msgstr "Приложить файл через drag &amp; drop или %{upload_link}"
@@ -88,14 +115,8 @@ msgstr[0] "Ветка"
msgstr[1] "Ветки"
msgstr[2] "Ветки"
-msgid ""
-"Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, "
-"choose a GitLab CI Yaml template and commit your changes. "
-"%{link_to_autodeploy_doc}"
-msgstr ""
-"Ветка <strong>%{branch_name}</strong> Ñоздана. Ð”Ð»Ñ Ð½Ð°Ñтройки автоматичеÑкого "
-"Ñ€Ð°Ð·Ð²ÐµÑ€Ñ‚Ñ‹Ð²Ð°Ð½Ð¸Ñ Ð²Ñ‹Ð±ÐµÑ€ÐµÑ‚Ðµ GitLab CI Yaml-шаблон и зафикÑируйте изменениÑ. "
-"%{link_to_autodeploy_doc}"
+msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
+msgstr "Ветка <strong>%{branch_name}</strong> Ñоздана. Ð”Ð»Ñ Ð½Ð°Ñтройки автоматичеÑкого Ñ€Ð°Ð·Ð²ÐµÑ€Ñ‚Ñ‹Ð²Ð°Ð½Ð¸Ñ Ð²Ñ‹Ð±ÐµÑ€ÐµÑ‚Ðµ GitLab CI Yaml-шаблон и зафикÑируйте изменениÑ. %{link_to_autodeploy_doc}"
msgid "BranchSwitcherPlaceholder|Search branches"
msgstr "ПоиÑк веток"
@@ -127,6 +148,9 @@ msgstr "ÐаÑтройка CI"
msgid "Cancel"
msgstr "Отмена"
+msgid "Cancel edit"
+msgstr ""
+
msgid "ChangeTypeActionLabel|Pick into branch"
msgstr "Выбрать в ветке"
@@ -205,6 +229,9 @@ msgstr "пропущено"
msgid "CiStatus|running"
msgstr "выполнÑетÑÑ"
+msgid "Comments"
+msgstr ""
+
msgid "Commit"
msgid_plural "Commits"
msgstr[0] "Коммит"
@@ -253,12 +280,11 @@ msgstr "Копировать SHA коммита в буфер обмена"
msgid "Create New Directory"
msgstr "Создать директорию"
-msgid ""
-"Create a personal access token on your account to pull or push via "
-"%{protocol}."
+msgid "Create a new branch"
msgstr ""
-"Создать личный токен на аккаунте Ð´Ð»Ñ Ð¿Ð¾Ð»ÑƒÑ‡ÐµÐ½Ð¸Ñ Ð¸Ð»Ð¸ отправки через "
-"%{protocol}."
+
+msgid "Create a personal access token on your account to pull or push via %{protocol}."
+msgstr "Создать личный токен на аккаунте Ð´Ð»Ñ Ð¿Ð¾Ð»ÑƒÑ‡ÐµÐ½Ð¸Ñ Ð¸Ð»Ð¸ отправки через %{protocol}."
msgid "Create directory"
msgstr "Создать директорию"
@@ -290,25 +316,14 @@ msgstr "СинтакÑÐ¸Ñ Cron"
msgid "Custom notification events"
msgstr " ÐаÑтраиваемые ÑƒÐ²ÐµÐ´Ð¾Ð¼Ð»ÐµÐ½Ð¸Ñ Ð¾ ÑобытиÑÑ…"
-msgid ""
-"Custom notification levels are the same as participating levels. With custom "
-"notification levels you will also receive notifications for select events. "
-"To find out more, check out %{notification_link}."
-msgstr ""
-"ÐаÑтраиваемые уровни уведомлений аналогичны уровню уведомлений в "
-"ÑоответÑтвии Ñ ÑƒÑ‡Ð°Ñтием. С наÑтраиваемыми уровнÑми уведомлений вы также "
-"будете получать ÑƒÐ²ÐµÐ´Ð¾Ð¼Ð»ÐµÐ½Ð¸Ñ Ð¾ выбранных ÑобытиÑÑ…. Чтобы узнать больше, "
-"поÑмотрите %{notification_link}."
+msgid "Custom notification levels are the same as participating levels. With custom notification levels you will also receive notifications for select events. To find out more, check out %{notification_link}."
+msgstr "ÐаÑтраиваемые уровни уведомлений аналогичны уровню уведомлений в ÑоответÑтвии Ñ ÑƒÑ‡Ð°Ñтием. С наÑтраиваемыми уровнÑми уведомлений вы также будете получать ÑƒÐ²ÐµÐ´Ð¾Ð¼Ð»ÐµÐ½Ð¸Ñ Ð¾ выбранных ÑобытиÑÑ…. Чтобы узнать больше, поÑмотрите %{notification_link}."
msgid "Cycle Analytics"
msgstr "Цикл Ðналитик"
-msgid ""
-"Cycle Analytics gives an overview of how much time it takes to go from idea "
-"to production in your project."
-msgstr ""
-"Цикл Ðналитик дает предÑтавление о том, Ñколько времени требуетÑÑ, чтобы "
-"перейти от идеи к производÑтву в проекте."
+msgid "Cycle Analytics gives an overview of how much time it takes to go from idea to production in your project."
+msgstr "Цикл Ðналитик дает предÑтавление о том, Ñколько времени требуетÑÑ, чтобы перейти от идеи к производÑтву в проекте."
msgid "CycleAnalyticsStage|Code"
msgstr "ÐапиÑание кода"
@@ -346,9 +361,15 @@ msgstr[2] "Размещение"
msgid "Description"
msgstr "ОпиÑание"
+msgid "Details"
+msgstr ""
+
msgid "Directory name"
msgstr "Каталог"
+msgid "Discard changes"
+msgstr ""
+
msgid "Don't show again"
msgstr "Ðе показывать Ñнова"
@@ -385,6 +406,24 @@ msgstr "Редактировать"
msgid "Edit Pipeline Schedule %{id}"
msgstr "Изменить раÑпиÑание конвейера %{id}"
+msgid "EventFilterBy|Filter by all"
+msgstr ""
+
+msgid "EventFilterBy|Filter by comments"
+msgstr ""
+
+msgid "EventFilterBy|Filter by issue events"
+msgstr ""
+
+msgid "EventFilterBy|Filter by merge events"
+msgstr ""
+
+msgid "EventFilterBy|Filter by push events"
+msgstr ""
+
+msgid "EventFilterBy|Filter by team"
+msgstr ""
+
msgid "Every day (at 4:00am)"
msgstr "Ежедневно (в 4:00)"
@@ -433,12 +472,36 @@ msgstr "От ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ Ð¿Ñ€Ð¾Ð±Ð»ÐµÐ¼Ñ‹ до Ñ€Ð°Ð·Ð²ÐµÑ€Ñ‚Ñ‹Ð²Ð°Ð½Ð¸Ñ Ð
msgid "From merge request merge until deploy to production"
msgstr "От запроÑа на ÑлиÑние до Ñ€Ð°Ð·Ð²ÐµÑ€Ñ‚Ñ‹Ð²Ð°Ð½Ð¸Ñ Ð² рабочей Ñреде"
+msgid "Git storage health information has been reset"
+msgstr ""
+
+msgid "GitLab Runner section"
+msgstr ""
+
msgid "Go to your fork"
msgstr "Перейти к вашему форку"
msgid "GoToYourFork|Fork"
msgstr "Форк"
+msgid "Health Check"
+msgstr ""
+
+msgid "Health information can be retrieved from the following endpoints. More information is available"
+msgstr ""
+
+msgid "HealthCheck|Access token is"
+msgstr ""
+
+msgid "HealthCheck|Healthy"
+msgstr ""
+
+msgid "HealthCheck|No Health Problems Detected"
+msgstr ""
+
+msgid "HealthCheck|Unhealthy"
+msgstr ""
+
msgid "Home"
msgstr "ГлавнаÑ"
@@ -448,12 +511,18 @@ msgstr "ОчиÑтка уÑпешно запущена"
msgid "Import repository"
msgstr "Импорт репозиториÑ"
+msgid "Install a Runner compatible with GitLab CI"
+msgstr ""
+
msgid "Interval Pattern"
msgstr "Шаблон интервала"
msgid "Introducing Cycle Analytics"
msgstr "Внедрение Цикла Ðналитик"
+msgid "Issue events"
+msgstr ""
+
msgid "Jobs for last month"
msgstr "Работы за прошлый меÑÑц"
@@ -484,6 +553,12 @@ msgstr "ПоÑледнее обновление"
msgid "Last commit"
msgstr "ПоÑледний коммит"
+msgid "LastPushEvent|You pushed to"
+msgstr ""
+
+msgid "LastPushEvent|at"
+msgstr ""
+
msgid "Learn more in the"
msgstr "Узнайте больше в"
@@ -505,9 +580,15 @@ msgstr[2] "Ограничение %d Ñобытий"
msgid "Median"
msgstr "Среднее"
+msgid "Merge events"
+msgstr ""
+
msgid "MissingSSHKeyWarningLink|add an SSH key"
msgstr "добавить ключ SSH"
+msgid "More information is available|here"
+msgstr ""
+
msgid "New Issue"
msgid_plural "New Issues"
msgstr[0] "Обращение"
@@ -706,6 +787,9 @@ msgstr "Ñо Ñтадией"
msgid "Pipeline|with stages"
msgstr "Ñо ÑтадиÑми"
+msgid "Project"
+msgstr ""
+
msgid "Project '%{project_name}' queued for deletion."
msgstr "Проект '%{project_name}' добавлен в очередь на удаление."
@@ -721,27 +805,27 @@ msgstr "Проект '%{project_name}' удален."
msgid "Project access must be granted explicitly to each user."
msgstr "ДоÑтуп к проекту должен предоÑтавлÑÑ‚ÑŒÑÑ Ñвно каждому пользователю."
+msgid "Project details"
+msgstr ""
+
msgid "Project export could not be deleted."
msgstr "Ðевозможно удалить ÑкÑпорт проекта."
msgid "Project export has been deleted."
msgstr "ЭкÑпорт проекта удален."
-msgid ""
-"Project export link has expired. Please generate a new export from your "
-"project settings."
-msgstr ""
-"ИÑтек Ñрок дейÑÑ‚Ð²Ð¸Ñ ÑÑылки на проект. Создайте новый ÑкÑпорт в ваших "
-"наÑтройках проекта."
+msgid "Project export link has expired. Please generate a new export from your project settings."
+msgstr "ИÑтек Ñрок дейÑÑ‚Ð²Ð¸Ñ ÑÑылки на проект. Создайте новый ÑкÑпорт в ваших наÑтройках проекта."
msgid "Project export started. A download link will be sent by email."
-msgstr ""
-"Ðачат ÑкÑпорт проекта. СÑылка Ð´Ð»Ñ ÑÐºÐ°Ñ‡Ð¸Ð²Ð°Ð½Ð¸Ñ Ð±ÑƒÐ´ÐµÑ‚ отправлена по Ñлектронной "
-"почте."
+msgstr "Ðачат ÑкÑпорт проекта. СÑылка Ð´Ð»Ñ ÑÐºÐ°Ñ‡Ð¸Ð²Ð°Ð½Ð¸Ñ Ð±ÑƒÐ´ÐµÑ‚ отправлена по Ñлектронной почте."
msgid "Project home"
msgstr "ДомашнÑÑ Ñтраница"
+msgid "ProjectActivityRSS|Subscribe"
+msgstr ""
+
msgid "ProjectFeature|Disabled"
msgstr "Отключено"
@@ -763,11 +847,14 @@ msgstr "Этап"
msgid "ProjectNetworkGraph|Graph"
msgstr "Граф"
+msgid "Push events"
+msgstr ""
+
msgid "Read more"
msgstr "Подробнее"
msgid "Readme"
-msgstr "Readme"
+msgstr ""
msgid "RefSwitcher|Branches"
msgstr "Ветки"
@@ -799,9 +886,21 @@ msgstr "Ðапомнить позже"
msgid "Remove project"
msgstr "Удалить проект"
+msgid "Repository"
+msgstr ""
+
msgid "Request Access"
msgstr "Ð—Ð°Ð¿Ñ€Ð¾Ñ Ð´Ð¾Ñтупа"
+msgid "Reset git storage health information"
+msgstr ""
+
+msgid "Reset health check access token"
+msgstr ""
+
+msgid "Reset runners registration token"
+msgstr ""
+
msgid "Revert this commit"
msgstr "Отменить Ñто изменение"
@@ -826,13 +925,14 @@ msgstr "Выбрать формат архива"
msgid "Select a timezone"
msgstr "Выбор временной зоны"
+msgid "Select existing branch"
+msgstr ""
+
msgid "Select target branch"
msgstr "Выбор целевой ветки"
msgid "Set a password on your account to pull or push via %{protocol}."
-msgstr ""
-"УÑтановите пароль в Ñвоем аккаунте, чтобы отправлÑÑ‚ÑŒ или получать код через "
-"%{protocol}."
+msgstr "УÑтановите пароль в Ñвоем аккаунте, чтобы отправлÑÑ‚ÑŒ или получать код через %{protocol}."
msgid "Set up CI"
msgstr "ÐаÑтройка CI"
@@ -855,12 +955,18 @@ msgstr[2] "Показано %d Ñобытий"
msgid "Source code"
msgstr "ИÑходный код"
+msgid "Specify the following URL during the Runner setup:"
+msgstr ""
+
msgid "StarProject|Star"
msgstr "Отметить"
msgid "Start a %{new_merge_request} with these changes"
msgstr "Ðачать %{new_merge_request} Ñ Ñтих изменений"
+msgid "Start the Runner!"
+msgstr ""
+
msgid "Switch branch/tag"
msgstr "Переключить ветка/тег"
@@ -876,14 +982,11 @@ msgstr "Теги"
msgid "Target Branch"
msgstr "Ветка"
-msgid ""
-"The coding stage shows the time from the first commit to creating the merge "
-"request. The data will automatically be added here once you create your "
-"first merge request."
+msgid "Team"
msgstr ""
-"Ðа Ñтапе напиÑÐ°Ð½Ð¸Ñ ÐºÐ¾Ð´Ð° показывает Ð²Ñ€ÐµÐ¼Ñ Ð¿ÐµÑ€Ð²Ð¾Ð³Ð¾ коммита до ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ Ð·Ð°Ð¿Ñ€Ð¾Ñа "
-"на ÑлиÑние. Данные автоматичеÑки добавÑÑ‚ÑÑ Ð¿Ð¾Ñле того, как вы Ñоздать Ñвой "
-"первый Ð·Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° ÑлиÑние."
+
+msgid "The coding stage shows the time from the first commit to creating the merge request. The data will automatically be added here once you create your first merge request."
+msgstr "Ðа Ñтапе напиÑÐ°Ð½Ð¸Ñ ÐºÐ¾Ð´Ð° показывает Ð²Ñ€ÐµÐ¼Ñ Ð¿ÐµÑ€Ð²Ð¾Ð³Ð¾ коммита до ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ Ð·Ð°Ð¿Ñ€Ð¾Ñа на ÑлиÑние. Данные автоматичеÑки добавÑÑ‚ÑÑ Ð¿Ð¾Ñле того, как вы Ñоздать Ñвой первый Ð·Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° ÑлиÑние."
msgid "The collection of events added to the data gathered for that stage."
msgstr "ÐšÐ¾Ð»Ð»ÐµÐºÑ†Ð¸Ñ Ñобытий добавленных в данные Ñобранные Ð´Ð»Ñ Ñтого Ñтапа."
@@ -891,44 +994,20 @@ msgstr "ÐšÐ¾Ð»Ð»ÐµÐºÑ†Ð¸Ñ Ñобытий добавленных в данные
msgid "The fork relationship has been removed."
msgstr "СвÑзь форка удалена."
-msgid ""
-"The issue stage shows the time it takes from creating an issue to assigning "
-"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 ""
-"Ð¡Ñ‚Ð°Ð´Ð¸Ñ Ð¾Ð±Ñ€Ð°Ñ‰ÐµÐ½Ð¸Ñ Ð²Ñ€ÐµÐ¼Ñ, которое потребуетÑÑ Ñ Ð¼Ð¾Ð¼ÐµÐ½Ñ‚Ð° ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ Ð¾Ð±Ñ€Ð°Ñ‰ÐµÐ½Ð¸Ñ Ð´Ð¾ "
-"Ð½Ð°Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð¾Ð±Ñ€Ð°Ñ‰ÐµÐ½Ð¸ÑŽ вехи, или Ð´Ð¾Ð±Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ð¾Ð±Ñ€Ð°Ñ‰ÐµÐ½Ð¸Ñ Ð² вашу доÑку обращений. "
-"Ðачните Ñоздавать обращениÑ, чтобы увидеть ÑÐ²ÐµÐ´ÐµÐ½Ð¸Ñ Ð´Ð»Ñ Ñтой Ñтадии. "
+msgid "The issue stage shows the time it takes from creating an issue to assigning 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 "Ð¡Ñ‚Ð°Ð´Ð¸Ñ Ð¾Ð±Ñ€Ð°Ñ‰ÐµÐ½Ð¸Ñ Ð²Ñ€ÐµÐ¼Ñ, которое потребуетÑÑ Ñ Ð¼Ð¾Ð¼ÐµÐ½Ñ‚Ð° ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ Ð¾Ð±Ñ€Ð°Ñ‰ÐµÐ½Ð¸Ñ Ð´Ð¾ Ð½Ð°Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð¾Ð±Ñ€Ð°Ñ‰ÐµÐ½Ð¸ÑŽ вехи, или Ð´Ð¾Ð±Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ð¾Ð±Ñ€Ð°Ñ‰ÐµÐ½Ð¸Ñ Ð² вашу доÑку обращений. Ðачните Ñоздавать обращениÑ, чтобы увидеть ÑÐ²ÐµÐ´ÐµÐ½Ð¸Ñ Ð´Ð»Ñ Ñтой Ñтадии. "
msgid "The phase of the development lifecycle."
msgstr "Фаза жизненного цикла разработки."
-msgid ""
-"The pipelines schedule runs pipelines in the future, repeatedly, for "
-"specific branches or tags. Those scheduled pipelines will inherit limited "
-"project access based on their associated user."
-msgstr ""
-"РаÑпиÑание конвейеров запуÑкает в будущем неоднократно конвейеры, Ð´Ð»Ñ "
-"определенных ветвей или тегов. Запланированные конвейеры наÑледуют "
-"Ð¾Ð³Ñ€Ð°Ð½Ð¸Ñ‡ÐµÐ½Ð¸Ñ Ð½Ð° доÑтуп к проекту на оÑнове ÑвÑзанного Ñ Ð½Ð¸Ð¼Ð¸ пользователÑ."
+msgid "The pipelines schedule runs pipelines in the future, repeatedly, for specific branches or tags. Those scheduled pipelines will inherit limited project access based on their associated user."
+msgstr "РаÑпиÑание конвейеров запуÑкает в будущем неоднократно конвейеры, Ð´Ð»Ñ Ð¾Ð¿Ñ€ÐµÐ´ÐµÐ»ÐµÐ½Ð½Ñ‹Ñ… ветвей или тегов. Запланированные конвейеры наÑледуют Ð¾Ð³Ñ€Ð°Ð½Ð¸Ñ‡ÐµÐ½Ð¸Ñ Ð½Ð° доÑтуп к проекту на оÑнове ÑвÑзанного Ñ Ð½Ð¸Ð¼Ð¸ пользователÑ."
-msgid ""
-"The planning stage shows the time from the previous step to pushing your "
-"first commit. This time will be added automatically once you push your first "
-"commit."
-msgstr ""
-"Ðа Ñтапе Ð¿Ð»Ð°Ð½Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ð¿Ð¾ÐºÐ°Ð·Ñ‹Ð²Ð°ÐµÑ‚ Ð²Ñ€ÐµÐ¼Ñ Ð¾Ñ‚ предыдущего шага до Ð¿Ñ€Ð¾Ñ‚Ð°Ð»ÐºÐ¸Ð²Ð°Ð½Ð¸Ñ "
-"первого коммита. ДобавлÑетÑÑ Ð°Ð²Ñ‚Ð¾Ð¼Ð°Ñ‚Ð¸Ñ‡ÐµÑки, как только проталкиваете Ñвой "
-"первый коммит."
+msgid "The planning stage shows the time from the previous step to pushing your first commit. This time will be added automatically once you push your first commit."
+msgstr "Ðа Ñтапе Ð¿Ð»Ð°Ð½Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ð¿Ð¾ÐºÐ°Ð·Ñ‹Ð²Ð°ÐµÑ‚ Ð²Ñ€ÐµÐ¼Ñ Ð¾Ñ‚ предыдущего шага до Ð¿Ñ€Ð¾Ñ‚Ð°Ð»ÐºÐ¸Ð²Ð°Ð½Ð¸Ñ Ð¿ÐµÑ€Ð²Ð¾Ð³Ð¾ коммита. ДобавлÑетÑÑ Ð°Ð²Ñ‚Ð¾Ð¼Ð°Ñ‚Ð¸Ñ‡ÐµÑки, как только проталкиваете Ñвой первый коммит."
-msgid ""
-"The production stage shows the total time it takes between creating an issue "
-"and deploying the code to production. The data will be automatically added "
-"once you have completed the full idea to production cycle."
-msgstr ""
-"ПроизводÑтвенный Ñтап показывает общее Ð²Ñ€ÐµÐ¼Ñ Ð¼ÐµÐ¶Ð´Ñƒ Ñозданием задачи и "
-"развертывание кода в производÑтвенной Ñреде. Данные будут автоматичеÑки "
-"добавлены поÑле полного Ð·Ð°Ð²ÐµÑ€ÑˆÐµÐ½Ð¸Ñ Ð¸Ð´ÐµÐ¸ производÑтвенного цикла."
+msgid "The production stage shows the total time it takes between creating an issue and deploying the code to production. The data will be automatically added once you have completed the full idea to production cycle."
+msgstr "ПроизводÑтвенный Ñтап показывает общее Ð²Ñ€ÐµÐ¼Ñ Ð¼ÐµÐ¶Ð´Ñƒ Ñозданием задачи и развертывание кода в производÑтвенной Ñреде. Данные будут автоматичеÑки добавлены поÑле полного Ð·Ð°Ð²ÐµÑ€ÑˆÐµÐ½Ð¸Ñ Ð¸Ð´ÐµÐ¸ производÑтвенного цикла."
msgid "The project can be accessed by any logged in user."
msgstr "ДоÑтуп к проекту возможен любым зарегиÑтрированным пользователем."
@@ -939,50 +1018,26 @@ msgstr "ДоÑтуп к проекту возможен без какой-либ
msgid "The repository for this project does not exist."
msgstr "Репозиторий Ð´Ð»Ñ Ñтого проекта не ÑущеÑтвует."
-msgid ""
-"The review stage shows the time from creating the merge request to merging "
-"it. The data will automatically be added after you merge your first merge "
-"request."
-msgstr ""
-"Этап обзора показывает Ð²Ñ€ÐµÐ¼Ñ Ð¾Ñ‚ ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ Ð·Ð°Ð¿Ñ€Ð¾Ñа ÑлиÑÐ½Ð¸Ñ Ð´Ð¾ его выполнениÑ. "
-"Данные будут автоматичеÑки добавлены поÑле Ð·Ð°Ð²ÐµÑ€ÑˆÐµÐ½Ð¸Ñ Ð¿ÐµÑ€Ð²Ð¾Ð³Ð¾ запроÑа на "
-"ÑлиÑние."
+msgid "The review stage shows the time from creating the merge request to merging it. The data will automatically be added after you merge your first merge request."
+msgstr "Этап обзора показывает Ð²Ñ€ÐµÐ¼Ñ Ð¾Ñ‚ ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ Ð·Ð°Ð¿Ñ€Ð¾Ñа ÑлиÑÐ½Ð¸Ñ Ð´Ð¾ его выполнениÑ. Данные будут автоматичеÑки добавлены поÑле Ð·Ð°Ð²ÐµÑ€ÑˆÐµÐ½Ð¸Ñ Ð¿ÐµÑ€Ð²Ð¾Ð³Ð¾ запроÑа на ÑлиÑние."
-msgid ""
-"The staging stage shows the time between merging the MR and deploying code "
-"to the production environment. The data will be automatically added once you "
-"deploy to production for the first time."
-msgstr ""
-"Этап поÑтановки показывает Ð²Ñ€ÐµÐ¼Ñ Ð¼ÐµÐ¶Ð´Ñƒ ÑлиÑнием \"MR\" и развертыванием кода "
-"в производÑтвенной Ñреде. Данные будут автоматичеÑки добавлены поÑле "
-"Ñ€Ð°Ð·Ð²ÐµÑ€Ñ‚Ñ‹Ð²Ð°Ð½Ð¸Ñ Ð² производÑтве первый раз."
+msgid "The staging stage shows the time between merging the MR and deploying code to the production environment. The data will be automatically added once you deploy to production for the first time."
+msgstr "Этап поÑтановки показывает Ð²Ñ€ÐµÐ¼Ñ Ð¼ÐµÐ¶Ð´Ñƒ ÑлиÑнием \"MR\" и развертыванием кода в производÑтвенной Ñреде. Данные будут автоматичеÑки добавлены поÑле Ñ€Ð°Ð·Ð²ÐµÑ€Ñ‚Ñ‹Ð²Ð°Ð½Ð¸Ñ Ð² производÑтве первый раз."
-msgid ""
-"The testing stage shows the time GitLab CI takes to run every pipeline for "
-"the related merge request. The data will automatically be added after your "
-"first pipeline finishes running."
-msgstr ""
-"Этап теÑÑ‚Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ð¿Ð¾ÐºÐ°Ð·Ñ‹Ð²Ð°ÐµÑ‚ времÑ, которое GitLab CI занимает Ð´Ð»Ñ Ð·Ð°Ð¿ÑƒÑка "
-"каждого конвейера Ð´Ð»Ñ ÑоответÑтвующего запроÑа на ÑлиÑние. Данные будут "
-"автоматичеÑки добавлены поÑле Ð·Ð°Ð²ÐµÑ€ÑˆÐµÐ½Ð¸Ñ Ñ€Ð°Ð±Ð¾Ñ‚Ñ‹ вашего первого конвейера."
+msgid "The testing stage shows the time GitLab CI takes to run every pipeline for the related merge request. The data will automatically be added after your first pipeline finishes running."
+msgstr "Этап теÑÑ‚Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ð¿Ð¾ÐºÐ°Ð·Ñ‹Ð²Ð°ÐµÑ‚ времÑ, которое GitLab CI занимает Ð´Ð»Ñ Ð·Ð°Ð¿ÑƒÑка каждого конвейера Ð´Ð»Ñ ÑоответÑтвующего запроÑа на ÑлиÑние. Данные будут автоматичеÑки добавлены поÑле Ð·Ð°Ð²ÐµÑ€ÑˆÐµÐ½Ð¸Ñ Ñ€Ð°Ð±Ð¾Ñ‚Ñ‹ вашего первого конвейера."
msgid "The time taken by each data entry gathered by that stage."
msgstr "ВремÑ, затраченное каждым Ñлементом, Ñобранным на Ñтом Ñтапе."
-msgid ""
-"The value lying at the midpoint of a series of observed values. E.g., "
-"between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 ="
-" 6."
-msgstr ""
-"Среднее значение в Ñ€Ñду. Пример: между 3, 5, 9, Ñреднее 5, между 3, 5, 7, 8, "
-"Ñреднее (5+7)/2 = 6."
+msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
+msgstr "Среднее значение в Ñ€Ñду. Пример: между 3, 5, 9, Ñреднее 5, между 3, 5, 7, 8, Ñреднее (5+7)/2 = 6."
-msgid ""
-"This means you can not push code until you create an empty repository or "
-"import existing one."
+msgid "There are problems accessing Git storage: "
msgstr ""
-"Это означает, что вы не можете пушить код, пока не Ñоздадите пуÑтой "
-"репозиторий или не импортируете ÑущеÑтвующий."
+
+msgid "This means you can not push code until you create an empty repository or import existing one."
+msgstr "Это означает, что вы не можете пушить код, пока не Ñоздадите пуÑтой репозиторий или не импортируете ÑущеÑтвующий."
msgid "Time before an issue gets scheduled"
msgstr " Ð’Ñ€ÐµÐ¼Ñ Ð´Ð¾ начала Ð¿Ð¾Ð¿Ð°Ð´Ð°Ð½Ð¸Ñ Ð¿Ñ€Ð¾Ð±Ð»ÐµÐ¼Ñ‹ в планировщик"
@@ -1152,6 +1207,9 @@ msgstr "Загрузить файл"
msgid "UploadLink|click to upload"
msgstr "кликните Ð´Ð»Ñ Ð·Ð°Ð³Ñ€ÑƒÐ·ÐºÐ¸"
+msgid "Use the following registration token during setup:"
+msgstr ""
+
msgid "Use your global notification setting"
msgstr "ИÑпользуютÑÑ Ð³Ð»Ð¾Ð±Ð°Ð»ÑŒÐ½Ñ‹Ð¹ наÑтройки уведомлений"
@@ -1185,19 +1243,11 @@ msgstr "Ð’Ñ‹ ÑобираетеÑÑŒ удалить %{group_name}. Удаленн
msgid "You are going to remove %{project_name_with_namespace}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr "Ð’Ñ‹ хотите удалить %{project_name_with_namespace}. Удаленный проект ÐЕ МОЖЕТ быть воÑÑтановлен! Ð’Ñ‹ ÐБСОЛЮТÐО уверены?"
-msgid ""
-"You are going to remove the fork relationship to source project "
-"%{forked_from_project}. Are you ABSOLUTELY sure?"
-msgstr ""
-"Ð’Ñ‹ ÑобираетеÑÑŒ удалить ÑвÑзь форка Ñ Ð¸Ñходным проектом "
-"%{forked_from_project}. Ð’Ñ‹ ÐБСОЛЮТÐО уверены?"
+msgid "You are going to remove the fork relationship to source project %{forked_from_project}. Are you ABSOLUTELY sure?"
+msgstr "Ð’Ñ‹ ÑобираетеÑÑŒ удалить ÑвÑзь форка Ñ Ð¸Ñходным проектом %{forked_from_project}. Ð’Ñ‹ ÐБСОЛЮТÐО уверены?"
-msgid ""
-"You are going to transfer %{project_name_with_namespace} to another owner. "
-"Are you ABSOLUTELY sure?"
-msgstr ""
-"Ð’Ñ‹ ÑобираетеÑÑŒ передать проект %{project_name_with_namespace} другому "
-"владельцу. Ð’Ñ‹ ÐБСОЛЮТÐО уверены?"
+msgid "You are going to transfer %{project_name_with_namespace} to another owner. Are you ABSOLUTELY sure?"
+msgstr "Ð’Ñ‹ ÑобираетеÑÑŒ передать проект %{project_name_with_namespace} другому владельцу. Ð’Ñ‹ ÐБСОЛЮТÐО уверены?"
msgid "You can only add files when you are on a branch"
msgstr "Ð’Ñ‹ можете добавлÑÑ‚ÑŒ только файлы, когда находитеÑÑŒ в ветке"
@@ -1217,34 +1267,20 @@ msgstr "Ð’Ñ‹ не получите никаких уведомлений по Ñ
msgid "You will only receive notifications for the events you choose"
msgstr "Ð’Ñ‹ будете получать ÑƒÐ²ÐµÐ´Ð¾Ð¼Ð»ÐµÐ½Ð¸Ñ Ñ‚Ð¾Ð»ÑŒÐºÐ¾ о выбранных вами ÑобытиÑÑ…"
-msgid ""
-"You will only receive notifications for threads you have participated in"
-msgstr ""
-"Ð’Ñ‹ будете получать ÑƒÐ²ÐµÐ´Ð¾Ð¼Ð»ÐµÐ½Ð¸Ñ Ñ‚Ð¾Ð»ÑŒÐºÐ¾ о тех тредах, в которых вы учаÑтвовали"
+msgid "You will only receive notifications for threads you have participated in"
+msgstr "Ð’Ñ‹ будете получать ÑƒÐ²ÐµÐ´Ð¾Ð¼Ð»ÐµÐ½Ð¸Ñ Ñ‚Ð¾Ð»ÑŒÐºÐ¾ о тех тредах, в которых вы учаÑтвовали"
msgid "You will receive notifications for any activity"
msgstr "Ð’Ñ‹ будете получать ÑƒÐ²ÐµÐ´Ð¾Ð¼Ð»ÐµÐ½Ð¸Ñ Ð¾ любых дейÑтвиÑÑ…"
-msgid ""
-"You will receive notifications only for comments in which you were "
-"@mentioned"
-msgstr ""
-"Ð’Ñ‹ будете получать ÑƒÐ²ÐµÐ´Ð¾Ð¼Ð»ÐµÐ½Ð¸Ñ Ñ‚Ð¾Ð»ÑŒÐºÐ¾ Ð´Ð»Ñ ÐºÐ¾Ð¼Ð¼ÐµÐ½Ñ‚Ð°Ñ€Ð¸ÐµÐ², в которых вы были "
-"@упомÑнуты"
+msgid "You will receive notifications only for comments in which you were @mentioned"
+msgstr "Ð’Ñ‹ будете получать ÑƒÐ²ÐµÐ´Ð¾Ð¼Ð»ÐµÐ½Ð¸Ñ Ñ‚Ð¾Ð»ÑŒÐºÐ¾ Ð´Ð»Ñ ÐºÐ¾Ð¼Ð¼ÐµÐ½Ñ‚Ð°Ñ€Ð¸ÐµÐ², в которых вы были @упомÑнуты"
-msgid ""
-"You won't be able to pull or push project code via %{protocol} until you "
-"%{set_password_link} on your account"
-msgstr ""
-"Ð’Ñ‹ не Ñможете получать и отправлÑÑ‚ÑŒ код проекта через %{protocol} пока "
-"%{set_password_link} в ваш аккаунт"
+msgid "You won't be able to pull or push project code via %{protocol} until you %{set_password_link} on your account"
+msgstr "Ð’Ñ‹ не Ñможете получать и отправлÑÑ‚ÑŒ код проекта через %{protocol} пока %{set_password_link} в ваш аккаунт"
-msgid ""
-"You won't be able to pull or push project code via SSH until you "
-"%{add_ssh_key_link} to your profile"
-msgstr ""
-"Ð’Ñ‹ не Ñможете получать и отправлÑÑ‚ÑŒ код проекта через SSH пока "
-"%{add_ssh_key_link} в ваш профиль."
+msgid "You won't be able to pull or push project code via SSH until you %{add_ssh_key_link} to your profile"
+msgstr "Ð’Ñ‹ не Ñможете получать и отправлÑÑ‚ÑŒ код проекта через SSH пока %{add_ssh_key_link} в ваш профиль."
msgid "Your name"
msgstr "Ваше имÑ"
@@ -1265,5 +1301,4 @@ msgid "parent"
msgid_plural "parents"
msgstr[0] "иÑточник"
msgstr[1] "иÑточники"
-msgstr[2] "иÑточники"
-
+msgstr[2] "иÑточники" \ No newline at end of file
diff --git a/locale/uk/gitlab.po b/locale/uk/gitlab.po
index 0ac0499e315..5f9f087ff64 100644
--- a/locale/uk/gitlab.po
+++ b/locale/uk/gitlab.po
@@ -1,30 +1,20 @@
-# Huang Tao <htve@outlook.com>, 2017. #zanata
-# Ðндрей Витюк <andruwa13@gmail.com>, 2017. #zanata
msgid ""
msgstr ""
-"Project-Id-Version: gitlab 1.0.0\n"
+"Project-Id-Version: gitlab-ee\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2017-07-13 12:07-0500\n"
+"POT-Creation-Date: 2017-08-18 14:15+0530\n"
+"PO-Revision-Date: 2017-08-23 09:49-0400\n"
+"Last-Translator: gitlab <mbartlett+crowdin@gitlab.com>\n"
+"Language-Team: Ukrainian\n"
+"Language: uk_UA\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"Language-Team: Ukrainian (https://translate.zanata.org/project/view/GitLab)\n"
-"PO-Revision-Date: 2017-08-06 11:23-0400\n"
-"Last-Translator: Ðндрей Витюк <andruwa13@gmail.com>\n"
-"Language: uk\n"
-"X-Generator: Zanata 3.9.6\n"
-"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
-"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
-
-msgid "%s additional commit has been omitted to prevent performance issues."
-msgid_plural ""
-"%s additional commits have been omitted to prevent performance issues."
-msgstr[0] ""
-"%s доданий Комміт був виключений Ð´Ð»Ñ Ð·Ð°Ð¿Ð¾Ð±Ñ–Ð³Ð°Ð½Ð½Ñ Ð¿Ñ€Ð¾Ð±Ð»ÐµÐ¼ з продуктивніÑÑ‚ÑŽ."
-msgstr[1] ""
-"%s доданих коммітів були виключені Ð´Ð»Ñ Ð·Ð°Ð¿Ð¾Ð±Ñ–Ð³Ð°Ð½Ð½Ñ Ð¿Ñ€Ð¾Ð±Ð»ÐµÐ¼ з продуктивніÑÑ‚ÑŽ."
-msgstr[2] ""
-"%s доданих коммітів були виключені Ð´Ð»Ñ Ð·Ð°Ð¿Ð¾Ð±Ñ–Ð³Ð°Ð½Ð½Ñ Ð¿Ñ€Ð¾Ð±Ð»ÐµÐ¼ з продуктивніÑÑ‚ÑŽ."
+"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
+"X-Generator: crowdin.com\n"
+"X-Crowdin-Project: gitlab-ee\n"
+"X-Crowdin-Language: uk\n"
+"X-Crowdin-File: /master/locale/gitlab.pot\n"
msgid "%d commit"
msgid_plural "%d commits"
@@ -32,9 +22,33 @@ msgstr[0] "%d комміт"
msgstr[1] "%d комміта"
msgstr[2] "%d коммітів"
+msgid "%s additional commit has been omitted to prevent performance issues."
+msgid_plural "%s additional commits have been omitted to prevent performance issues."
+msgstr[0] "%s доданий Комміт був виключений Ð´Ð»Ñ Ð·Ð°Ð¿Ð¾Ð±Ñ–Ð³Ð°Ð½Ð½Ñ Ð¿Ñ€Ð¾Ð±Ð»ÐµÐ¼ з продуктивніÑÑ‚ÑŽ."
+msgstr[1] "%s доданих коммітів були виключені Ð´Ð»Ñ Ð·Ð°Ð¿Ð¾Ð±Ñ–Ð³Ð°Ð½Ð½Ñ Ð¿Ñ€Ð¾Ð±Ð»ÐµÐ¼ з продуктивніÑÑ‚ÑŽ."
+msgstr[2] "%s доданих коммітів були виключені Ð´Ð»Ñ Ð·Ð°Ð¿Ð¾Ð±Ñ–Ð³Ð°Ð½Ð½Ñ Ð¿Ñ€Ð¾Ð±Ð»ÐµÐ¼ з продуктивніÑÑ‚ÑŽ."
+
msgid "%{commit_author_link} committed %{commit_timeago}"
msgstr "%{commit_author_link} комміт %{commit_timeago}"
+msgid "%{number_of_failures} of %{maximum_failures} failures. GitLab will allow access on the next attempt."
+msgstr ""
+
+msgid "%{number_of_failures} of %{maximum_failures} failures. GitLab will block access for %{number_of_seconds} seconds."
+msgstr ""
+
+msgid "%{number_of_failures} of %{maximum_failures} failures. GitLab will not retry automatically. Reset storage information when the problem is resolved."
+msgstr ""
+
+msgid "%{storage_name}: failed storage access attempt on host:"
+msgid_plural "%{storage_name}: %{failed_attempts} failed storage access attempts:"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "(checkout the %{link} for information on how to install it)."
+msgstr ""
+
msgid "1 pipeline"
msgid_plural "%d pipelines"
msgstr[0] "1 конвеєр"
@@ -47,6 +61,9 @@ msgstr "Це набір графічних елементів Ð´Ð»Ñ Ð±ÐµÐ·Ð¿ÐµÑ
msgid "About auto deploy"
msgstr "Про авто розгортаннÑ"
+msgid "Access to failing storages has been temporarily disabled to allow the mount to recover. Reset storage information after the issue has been resolved to allow access again."
+msgstr ""
+
msgid "Active"
msgstr "Ðктивний"
@@ -63,19 +80,32 @@ msgid "Add License"
msgstr "Додати ліцензію"
msgid "Add an SSH key to your profile to pull or push via SSH."
-msgstr ""
-"Додати SSH ключа в Ñвій профіль, щоб мати можливіÑÑ‚ÑŒ завантажити чи "
-"надіÑлати зміни через SSH."
+msgstr "Додати SSH ключа в Ñвій профіль, щоб мати можливіÑÑ‚ÑŒ завантажити чи надіÑлати зміни через SSH."
msgid "Add new directory"
msgstr "Додати новий каталог"
+msgid "All"
+msgstr "Ð’ÑÑ–"
+
msgid "Archived project! Repository is read-only"
msgstr "Заархівований проект! Репозиторій доÑтупний лише Ð´Ð»Ñ Ñ‡Ð¸Ñ‚Ð°Ð½Ð½Ñ"
msgid "Are you sure you want to delete this pipeline schedule?"
msgstr "Ви впевнені, що хочете видалити цей розклад Ð´Ð»Ñ ÐšÐ¾Ð½Ð²ÐµÑ”Ñ€Ð°?"
+msgid "Are you sure you want to discard your changes?"
+msgstr "Ви впевнені, що бажаєте ÑкаÑувати ваші зміни?"
+
+msgid "Are you sure you want to reset registration token?"
+msgstr "Ви впевнені, що бажаєте Ñкинути реєÑтраційний токен?"
+
+msgid "Are you sure you want to reset the health check token?"
+msgstr ""
+
+msgid "Are you sure?"
+msgstr ""
+
msgid "Attach a file by drag &amp; drop or %{upload_link}"
msgstr "Прикріпити файл за допомогою перетÑÐ³ÑƒÐ²Ð°Ð½Ð½Ñ Ð°Ð±Ð¾ %{upload_link}"
@@ -85,14 +115,8 @@ msgstr[0] "Гілка"
msgstr[1] "Гілки"
msgstr[2] "Гілок"
-msgid ""
-"Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, "
-"choose a GitLab CI Yaml template and commit your changes. "
-"%{link_to_autodeploy_doc}"
-msgstr ""
-"Гілка <strong>%{branch_name}</strong> Ñтворена. Ð”Ð»Ñ Ð½Ð°Ñтройки автоматичного "
-"Ñ€Ð¾Ð·Ð³Ð¾Ñ€Ñ‚Ð°Ð½Ð½Ñ Ð²Ð¸Ð±ÐµÑ€Ñ–Ñ‚ÑŒ GitLab CI Yaml-шаблон Ñ– закоммітьте зміни. "
-"%{link_to_autodeploy_doc}"
+msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
+msgstr "Гілка <strong>%{branch_name}</strong> Ñтворена. Ð”Ð»Ñ Ð½Ð°Ñтройки автоматичного Ñ€Ð¾Ð·Ð³Ð¾Ñ€Ñ‚Ð°Ð½Ð½Ñ Ð²Ð¸Ð±ÐµÑ€Ñ–Ñ‚ÑŒ GitLab CI Yaml-шаблон Ñ– закоммітьте зміни. %{link_to_autodeploy_doc}"
msgid "BranchSwitcherPlaceholder|Search branches"
msgstr "Пошук гілок"
@@ -124,6 +148,9 @@ msgstr "ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ CI"
msgid "Cancel"
msgstr "СкаÑувати"
+msgid "Cancel edit"
+msgstr ""
+
msgid "ChangeTypeActionLabel|Pick into branch"
msgstr "Вибрати в гілці"
@@ -202,6 +229,9 @@ msgstr "пропущено"
msgid "CiStatus|running"
msgstr "виконуєтьÑÑ"
+msgid "Comments"
+msgstr ""
+
msgid "Commit"
msgid_plural "Commits"
msgstr[0] "Комміт"
@@ -250,12 +280,11 @@ msgstr "Скопіювати ідентифікатор в буфер обмін
msgid "Create New Directory"
msgstr "Створити новий каталог"
-msgid ""
-"Create a personal access token on your account to pull or push via "
-"%{protocol}."
+msgid "Create a new branch"
msgstr ""
-"Створити токен доÑтупу Ð´Ð»Ñ Ð²Ð°ÑˆÐ¾Ð³Ð¾ аккауета, щоб відправлÑти або отримувати "
-"через %{protocol}."
+
+msgid "Create a personal access token on your account to pull or push via %{protocol}."
+msgstr "Створити токен доÑтупу Ð´Ð»Ñ Ð²Ð°ÑˆÐ¾Ð³Ð¾ аккауета, щоб відправлÑти або отримувати через %{protocol}."
msgid "Create directory"
msgstr "Створити каталог"
@@ -287,24 +316,14 @@ msgstr "СинтакÑÐ¸Ñ Cron"
msgid "Custom notification events"
msgstr "КориÑтувацькі Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½ÑŒ про події"
-msgid ""
-"Custom notification levels are the same as participating levels. With custom "
-"notification levels you will also receive notifications for select events. "
-"To find out more, check out %{notification_link}."
-msgstr ""
-"Спеціальні рівні Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ñпівпадають з рівнем учаÑÑ‚Ñ–. За допомогою "
-"Ñпеціальних рівнів Ñповіщень ви також отримуватимете ÑÐ¿Ð¾Ð²Ñ–Ñ‰ÐµÐ½Ð½Ñ Ð¿Ñ€Ð¾ вибрані "
-"події. Щоб дізнатиÑÑŒ більше, переглÑньте %{notification_link}."
+msgid "Custom notification levels are the same as participating levels. With custom notification levels you will also receive notifications for select events. To find out more, check out %{notification_link}."
+msgstr "Спеціальні рівні Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ñпівпадають з рівнем учаÑÑ‚Ñ–. За допомогою Ñпеціальних рівнів Ñповіщень ви також отримуватимете ÑÐ¿Ð¾Ð²Ñ–Ñ‰ÐµÐ½Ð½Ñ Ð¿Ñ€Ð¾ вибрані події. Щоб дізнатиÑÑŒ більше, переглÑньте %{notification_link}."
msgid "Cycle Analytics"
msgstr "Ðналіз циклу"
-msgid ""
-"Cycle Analytics gives an overview of how much time it takes to go from idea "
-"to production in your project."
-msgstr ""
-"Ðналітика циклу дає оглÑд того, Ñкільки чаÑу потрібно, щоб перейти від ідеї "
-"до виробництва у вашому проекті."
+msgid "Cycle Analytics gives an overview of how much time it takes to go from idea to production in your project."
+msgstr "Ðналітика циклу дає оглÑд того, Ñкільки чаÑу потрібно, щоб перейти від ідеї до виробництва у вашому проекті."
msgid "CycleAnalyticsStage|Code"
msgstr "Код"
@@ -342,9 +361,15 @@ msgstr[2] "Розгортань"
msgid "Description"
msgstr "ОпиÑ"
+msgid "Details"
+msgstr ""
+
msgid "Directory name"
msgstr "Ім'Ñ ÐºÐ°Ñ‚Ð°Ð»Ð¾Ð³Ñƒ"
+msgid "Discard changes"
+msgstr ""
+
msgid "Don't show again"
msgstr "Ðе показувати знову"
@@ -381,6 +406,24 @@ msgstr "Редагувати"
msgid "Edit Pipeline Schedule %{id}"
msgstr "Редагувати Розклад Конвеєра %{id}"
+msgid "EventFilterBy|Filter by all"
+msgstr ""
+
+msgid "EventFilterBy|Filter by comments"
+msgstr ""
+
+msgid "EventFilterBy|Filter by issue events"
+msgstr ""
+
+msgid "EventFilterBy|Filter by merge events"
+msgstr ""
+
+msgid "EventFilterBy|Filter by push events"
+msgstr ""
+
+msgid "EventFilterBy|Filter by team"
+msgstr ""
+
msgid "Every day (at 4:00am)"
msgstr "Кожен день (в 4:00 ранку)"
@@ -429,12 +472,36 @@ msgstr "З моменту ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð¿Ñ€Ð¾Ð±Ð»ÐµÐ¼Ð¸ до розгорÑ
msgid "From merge request merge until deploy to production"
msgstr "З об'Ñ”Ð´Ð½Ð°Ð½Ð½Ñ Ð·Ð°Ð¿Ð¸Ñ‚Ñƒ Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ð´Ð¾ Ñ€Ð¾Ð·Ð³Ð¾Ñ€Ñ‚Ð°Ð½Ð½Ñ Ð½Ð° ПРОД"
+msgid "Git storage health information has been reset"
+msgstr ""
+
+msgid "GitLab Runner section"
+msgstr ""
+
msgid "Go to your fork"
msgstr "Перейти до вашого форку"
msgid "GoToYourFork|Fork"
msgstr "Форк"
+msgid "Health Check"
+msgstr ""
+
+msgid "Health information can be retrieved from the following endpoints. More information is available"
+msgstr ""
+
+msgid "HealthCheck|Access token is"
+msgstr ""
+
+msgid "HealthCheck|Healthy"
+msgstr ""
+
+msgid "HealthCheck|No Health Problems Detected"
+msgstr ""
+
+msgid "HealthCheck|Unhealthy"
+msgstr ""
+
msgid "Home"
msgstr "Головна"
@@ -444,12 +511,18 @@ msgstr "ÐžÑ‡Ð¸Ñ‰ÐµÐ½Ð½Ñ ÑƒÑпішно розпочато"
msgid "Import repository"
msgstr "Імпорт репозеторіÑ"
+msgid "Install a Runner compatible with GitLab CI"
+msgstr ""
+
msgid "Interval Pattern"
msgstr "Шаблон інтервалу"
msgid "Introducing Cycle Analytics"
msgstr "ПредÑтавлÑємо аналітику циклу"
+msgid "Issue events"
+msgstr ""
+
msgid "Jobs for last month"
msgstr "КількіÑÑ‚ÑŒ завдань за оÑтанній міÑÑць"
@@ -480,6 +553,12 @@ msgstr "ОÑтаннє оновленнÑ"
msgid "Last commit"
msgstr "ОÑтанній комміт"
+msgid "LastPushEvent|You pushed to"
+msgstr ""
+
+msgid "LastPushEvent|at"
+msgstr ""
+
msgid "Learn more in the"
msgstr "ДізнайтеÑÑŒ більше"
@@ -501,9 +580,15 @@ msgstr[2] "ÐžÐ±Ð¼ÐµÐ¶ÐµÐ½Ð½Ñ %d подій"
msgid "Median"
msgstr "Медіана"
+msgid "Merge events"
+msgstr ""
+
msgid "MissingSSHKeyWarningLink|add an SSH key"
msgstr "не додаÑте SSH ключ"
+msgid "More information is available|here"
+msgstr ""
+
msgid "New Issue"
msgid_plural "New Issues"
msgstr[0] "Ðова проблема"
@@ -702,6 +787,9 @@ msgstr "зі Ñтадією"
msgid "Pipeline|with stages"
msgstr "зі ÑтадіÑми"
+msgid "Project"
+msgstr ""
+
msgid "Project '%{project_name}' queued for deletion."
msgstr "Проект '%{project_name}' доданий в чергу на видаленнÑ."
@@ -717,27 +805,27 @@ msgstr "Проект '%{project_name}' видалений."
msgid "Project access must be granted explicitly to each user."
msgstr "ДоÑтуп до проекту повинен надаватиÑÑ ÐºÐ¾Ð¶Ð½Ð¾Ð¼Ñƒ кориÑтувачеві."
+msgid "Project details"
+msgstr ""
+
msgid "Project export could not be deleted."
msgstr "Ðеможливо видалити екÑпорт проекту."
msgid "Project export has been deleted."
msgstr "ЕкÑпорт проекту видалений."
-msgid ""
-"Project export link has expired. Please generate a new export from your "
-"project settings."
-msgstr ""
-"ЗакінчивÑÑ Ñ‚ÐµÑ€Ð¼Ñ–Ð½ дії поÑÐ¸Ð»Ð°Ð½Ð½Ñ Ð½Ð° проект. Створіть новий екÑпорт в ваших "
-"наÑтройках проекту."
+msgid "Project export link has expired. Please generate a new export from your project settings."
+msgstr "ЗакінчивÑÑ Ñ‚ÐµÑ€Ð¼Ñ–Ð½ дії поÑÐ¸Ð»Ð°Ð½Ð½Ñ Ð½Ð° проект. Створіть новий екÑпорт в ваших наÑтройках проекту."
msgid "Project export started. A download link will be sent by email."
-msgstr ""
-"Розпочато екÑпорт проекту. ПоÑÐ¸Ð»Ð°Ð½Ð½Ñ Ð´Ð»Ñ ÑÐºÐ°Ñ‡ÑƒÐ²Ð°Ð½Ð½Ñ Ð±ÑƒÐ´Ðµ надіÑлана "
-"електронною поштою."
+msgstr "Розпочато екÑпорт проекту. ПоÑÐ¸Ð»Ð°Ð½Ð½Ñ Ð´Ð»Ñ ÑÐºÐ°Ñ‡ÑƒÐ²Ð°Ð½Ð½Ñ Ð±ÑƒÐ´Ðµ надіÑлана електронною поштою."
msgid "Project home"
msgstr "Ð”Ð¾Ð¼Ð°ÑˆÐ½Ñ Ñторінка проекту"
+msgid "ProjectActivityRSS|Subscribe"
+msgstr ""
+
msgid "ProjectFeature|Disabled"
msgstr "Вимкнено"
@@ -759,6 +847,9 @@ msgstr "Етап"
msgid "ProjectNetworkGraph|Graph"
msgstr "ІÑторіÑ"
+msgid "Push events"
+msgstr ""
+
msgid "Read more"
msgstr "Докладніше"
@@ -795,9 +886,21 @@ msgstr "Ðагадати пізніше"
msgid "Remove project"
msgstr "Видалити проект"
+msgid "Repository"
+msgstr ""
+
msgid "Request Access"
msgstr "Запит доÑтупу"
+msgid "Reset git storage health information"
+msgstr ""
+
+msgid "Reset health check access token"
+msgstr ""
+
+msgid "Reset runners registration token"
+msgstr ""
+
msgid "Revert this commit"
msgstr "СкаÑувати цей комміт"
@@ -822,13 +925,14 @@ msgstr "Виберіть формат архіву"
msgid "Select a timezone"
msgstr "Вибрати чаÑовий поÑÑ"
+msgid "Select existing branch"
+msgstr ""
+
msgid "Select target branch"
msgstr "Вибір цільової гілки"
msgid "Set a password on your account to pull or push via %{protocol}."
-msgstr ""
-"Ð’Ñтановіть пароль Ñвого облікового запиÑу, щоб відправлÑти або отримувати "
-"код через %{protocol}."
+msgstr "Ð’Ñтановіть пароль Ñвого облікового запиÑу, щоб відправлÑти або отримувати код через %{protocol}."
msgid "Set up CI"
msgstr "ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ CI"
@@ -851,12 +955,18 @@ msgstr[2] "Показано %d подій"
msgid "Source code"
msgstr "Код"
+msgid "Specify the following URL during the Runner setup:"
+msgstr ""
+
msgid "StarProject|Star"
msgstr "ПідпиÑатиÑÑ"
msgid "Start a %{new_merge_request} with these changes"
msgstr "Почати %{new_merge_request} з цих змін"
+msgid "Start the Runner!"
+msgstr ""
+
msgid "Switch branch/tag"
msgstr "тег"
@@ -872,14 +982,11 @@ msgstr "Теги"
msgid "Target Branch"
msgstr "Цільова гілка"
-msgid ""
-"The coding stage shows the time from the first commit to creating the merge "
-"request. The data will automatically be added here once you create your "
-"first merge request."
+msgid "Team"
msgstr ""
-"Ðа Ñтадії напиÑÐ°Ð½Ð½Ñ ÐºÐ¾Ð´Ñƒ, показує Ñ‡Ð°Ñ Ð¿ÐµÑ€ÑˆÐ¾Ð³Ð¾ комміту до ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð·Ð°Ð¿Ð¸Ñ‚Ñƒ на "
-"об'єднаннÑ. Дані будуть автоматично додані піÑÐ»Ñ ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð²Ð°ÑˆÐ¾Ð³Ð¾ першого "
-"запиту на об'єднаннÑ."
+
+msgid "The coding stage shows the time from the first commit to creating the merge request. The data will automatically be added here once you create your first merge request."
+msgstr "Ðа Ñтадії напиÑÐ°Ð½Ð½Ñ ÐºÐ¾Ð´Ñƒ, показує Ñ‡Ð°Ñ Ð¿ÐµÑ€ÑˆÐ¾Ð³Ð¾ комміту до ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð·Ð°Ð¿Ð¸Ñ‚Ñƒ на об'єднаннÑ. Дані будуть автоматично додані піÑÐ»Ñ ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð²Ð°ÑˆÐ¾Ð³Ð¾ першого запиту на об'єднаннÑ."
msgid "The collection of events added to the data gathered for that stage."
msgstr "ÐšÐ¾Ð»ÐµÐºÑ†Ñ–Ñ Ð¿Ð¾Ð´Ñ–Ð¹ додана до даних, зібраних Ð´Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ етапу."
@@ -887,43 +994,20 @@ msgstr "ÐšÐ¾Ð»ÐµÐºÑ†Ñ–Ñ Ð¿Ð¾Ð´Ñ–Ð¹ додана до даних, зібрани
msgid "The fork relationship has been removed."
msgstr "Зв'Ñзок форка видалена."
-msgid ""
-"The issue stage shows the time it takes from creating an issue to assigning "
-"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 ""
-"Етап випуÑку показує, Ñкільки чаÑу потрібно від ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð¿Ñ€Ð¾Ð±Ð»ÐµÐ¼Ð¸ до "
-"приÑÐ²Ð¾Ñ”Ð½Ð½Ñ Ð²Ð¸Ð¿ÑƒÑку, або Ð´Ð¾Ð´Ð°Ð²Ð°Ð½Ð½Ñ Ð¿Ñ€Ð¾Ð±Ð»ÐµÐ¼Ð¸ в вашу дошку проблем. Почніть "
-"Ñтворювати проблеми, щоб переглÑдати дані Ð´Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ етапу."
+msgid "The issue stage shows the time it takes from creating an issue to assigning 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 "Етап випуÑку показує, Ñкільки чаÑу потрібно від ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð¿Ñ€Ð¾Ð±Ð»ÐµÐ¼Ð¸ до приÑÐ²Ð¾Ñ”Ð½Ð½Ñ Ð²Ð¸Ð¿ÑƒÑку, або Ð´Ð¾Ð´Ð°Ð²Ð°Ð½Ð½Ñ Ð¿Ñ€Ð¾Ð±Ð»ÐµÐ¼Ð¸ в вашу дошку проблем. Почніть Ñтворювати проблеми, щоб переглÑдати дані Ð´Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ етапу."
msgid "The phase of the development lifecycle."
msgstr "Фаза життєвого циклу розробки."
-msgid ""
-"The pipelines schedule runs pipelines in the future, repeatedly, for "
-"specific branches or tags. Those scheduled pipelines will inherit limited "
-"project access based on their associated user."
-msgstr ""
-"Розклад конвеєрів запуÑкає в майбутньому конвеєри, Ð´Ð»Ñ Ð¿ÐµÐ²Ð½Ð¸Ñ… гілок або "
-"тегів. Заплановані конвеєри уÑпадковують Ð¾Ð±Ð¼ÐµÐ¶ÐµÐ½Ð½Ñ Ð½Ð° доÑтуп до проекту на "
-"оÑнові пов'Ñзаного з ними кориÑтувача."
+msgid "The pipelines schedule runs pipelines in the future, repeatedly, for specific branches or tags. Those scheduled pipelines will inherit limited project access based on their associated user."
+msgstr "Розклад конвеєрів запуÑкає в майбутньому конвеєри, Ð´Ð»Ñ Ð¿ÐµÐ²Ð½Ð¸Ñ… гілок або тегів. Заплановані конвеєри уÑпадковують Ð¾Ð±Ð¼ÐµÐ¶ÐµÐ½Ð½Ñ Ð½Ð° доÑтуп до проекту на оÑнові пов'Ñзаного з ними кориÑтувача."
-msgid ""
-"The planning stage shows the time from the previous step to pushing your "
-"first commit. This time will be added automatically once you push your first "
-"commit."
-msgstr ""
-"Ðа етапі Ð¿Ð»Ð°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ð²Ñ–Ð´Ð¾Ð±Ñ€Ð°Ð¶Ð°Ñ”Ñ‚ÑŒÑÑ Ñ‡Ð°Ñ Ð²Ñ–Ð´ попереднього кроку до першого "
-"комміту. ДодаєтьÑÑ Ð°Ð²Ñ‚Ð¾Ð¼Ð°Ñ‚Ð¸Ñ‡Ð½Ð¾, Ñк тільки відправитÑÑ Ð¿ÐµÑ€ÑˆÐ¸Ð¹ комміт."
+msgid "The planning stage shows the time from the previous step to pushing your first commit. This time will be added automatically once you push your first commit."
+msgstr "Ðа етапі Ð¿Ð»Ð°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ð²Ñ–Ð´Ð¾Ð±Ñ€Ð°Ð¶Ð°Ñ”Ñ‚ÑŒÑÑ Ñ‡Ð°Ñ Ð²Ñ–Ð´ попереднього кроку до першого комміту. ДодаєтьÑÑ Ð°Ð²Ñ‚Ð¾Ð¼Ð°Ñ‚Ð¸Ñ‡Ð½Ð¾, Ñк тільки відправитÑÑ Ð¿ÐµÑ€ÑˆÐ¸Ð¹ комміт."
-msgid ""
-"The production stage shows the total time it takes between creating an issue "
-"and deploying the code to production. The data will be automatically added "
-"once you have completed the full idea to production cycle."
-msgstr ""
-"Ð¡Ñ‚Ð°Ð´Ñ–Ñ ÐŸÐ ÐžÐ”Ð°ÐºÑˆÐ¸Ð½ показує загальний Ñ‡Ð°Ñ Ð¼Ñ–Ð¶ ÑтвореннÑм проблеми та "
-"розгортаннÑм коду у ПРОДакшині. Дані будуть автоматично додані піÑÐ»Ñ "
-"Ð·Ð°Ð²ÐµÑ€ÑˆÐµÐ½Ð½Ñ Ð¿Ð¾Ð²Ð½Ð¾Ñ— ідеї до ПРОДакшин циклу."
+msgid "The production stage shows the total time it takes between creating an issue and deploying the code to production. The data will be automatically added once you have completed the full idea to production cycle."
+msgstr "Ð¡Ñ‚Ð°Ð´Ñ–Ñ ÐŸÐ ÐžÐ”Ð°ÐºÑˆÐ¸Ð½ показує загальний Ñ‡Ð°Ñ Ð¼Ñ–Ð¶ ÑтвореннÑм проблеми та розгортаннÑм коду у ПРОДакшині. Дані будуть автоматично додані піÑÐ»Ñ Ð·Ð°Ð²ÐµÑ€ÑˆÐµÐ½Ð½Ñ Ð¿Ð¾Ð²Ð½Ð¾Ñ— ідеї до ПРОДакшин циклу."
msgid "The project can be accessed by any logged in user."
msgstr "ДоÑтуп до проекту можливий будь-Ñким зареєÑтрованим кориÑтувачем."
@@ -934,49 +1018,26 @@ msgstr "ДоÑтуп до проекту можливий без будь-Ñко
msgid "The repository for this project does not exist."
msgstr "Репозиторій Ð´Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ проекту не Ñ–Ñнує."
-msgid ""
-"The review stage shows the time from creating the merge request to merging "
-"it. The data will automatically be added after you merge your first merge "
-"request."
-msgstr ""
-"Ð¡Ñ‚Ð°Ð´Ñ–Ñ Ð¾Ð³Ð»Ñду показує Ñ‡Ð°Ñ Ð²Ñ–Ð´ ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð·Ð°Ð¿Ð¸Ñ‚Ñƒ про об'Ñ”Ð´Ð½Ð°Ð½Ð½Ñ Ð´Ð¾ його "
-"виконаннÑ. Дані будуть автоматично додані піÑÐ»Ñ Ð·Ð°Ð²ÐµÑ€ÑˆÐµÐ½Ð½Ñ Ð¿ÐµÑ€ÑˆÐ¾Ð³Ð¾ запиту на "
-"злиттÑ."
+msgid "The review stage shows the time from creating the merge request to merging it. The data will automatically be added after you merge your first merge request."
+msgstr "Ð¡Ñ‚Ð°Ð´Ñ–Ñ Ð¾Ð³Ð»Ñду показує Ñ‡Ð°Ñ Ð²Ñ–Ð´ ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð·Ð°Ð¿Ð¸Ñ‚Ñƒ про об'Ñ”Ð´Ð½Ð°Ð½Ð½Ñ Ð´Ð¾ його виконаннÑ. Дані будуть автоматично додані піÑÐ»Ñ Ð·Ð°Ð²ÐµÑ€ÑˆÐµÐ½Ð½Ñ Ð¿ÐµÑ€ÑˆÐ¾Ð³Ð¾ запиту на злиттÑ."
-msgid ""
-"The staging stage shows the time between merging the MR and deploying code "
-"to the production environment. The data will be automatically added once you "
-"deploy to production for the first time."
-msgstr ""
-"Ð¡Ñ‚Ð°Ð´Ñ–Ñ Ð”Ð•Ð’ показує Ñ‡Ð°Ñ Ð¼Ñ–Ð¶ злиттÑм \"MR\" та розгортаннÑм коду у ПРОДакшин. "
-"Дані автоматично додаютьÑÑ Ð¿Ñ–ÑÐ»Ñ Ñ€Ð¾Ð·Ð³Ð¾Ñ€Ñ‚Ð°Ð½Ð½Ñ Ñƒ ПРОДакшин вперше."
+msgid "The staging stage shows the time between merging the MR and deploying code to the production environment. The data will be automatically added once you deploy to production for the first time."
+msgstr "Ð¡Ñ‚Ð°Ð´Ñ–Ñ Ð”Ð•Ð’ показує Ñ‡Ð°Ñ Ð¼Ñ–Ð¶ злиттÑм \"MR\" та розгортаннÑм коду у ПРОДакшин. Дані автоматично додаютьÑÑ Ð¿Ñ–ÑÐ»Ñ Ñ€Ð¾Ð·Ð³Ð¾Ñ€Ñ‚Ð°Ð½Ð½Ñ Ñƒ ПРОДакшин вперше."
-msgid ""
-"The testing stage shows the time GitLab CI takes to run every pipeline for "
-"the related merge request. The data will automatically be added after your "
-"first pipeline finishes running."
-msgstr ""
-"Ð¡Ñ‚Ð°Ð´Ñ–Ñ Ñ‚ÐµÑÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð¿Ð¾ÐºÐ°Ð·ÑƒÑ” чаÑ, Ñкий GitLab CI виконує Ð´Ð»Ñ Ð·Ð°Ð¿ÑƒÑку кожного "
-"конвеєра Ð´Ð»Ñ Ð²Ñ–Ð´Ð¿Ð¾Ð²Ñ–Ð´Ð½Ð¾Ð³Ð¾ запиту злиттÑ. Дані будуть автоматично додані "
-"піÑÐ»Ñ Ð·Ð°Ð²ÐµÑ€ÑˆÐµÐ½Ð½Ñ Ð¿ÐµÑ€ÑˆÐ¾Ð³Ð¾ конвеєра."
+msgid "The testing stage shows the time GitLab CI takes to run every pipeline for the related merge request. The data will automatically be added after your first pipeline finishes running."
+msgstr "Ð¡Ñ‚Ð°Ð´Ñ–Ñ Ñ‚ÐµÑÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð¿Ð¾ÐºÐ°Ð·ÑƒÑ” чаÑ, Ñкий GitLab CI виконує Ð´Ð»Ñ Ð·Ð°Ð¿ÑƒÑку кожного конвеєра Ð´Ð»Ñ Ð²Ñ–Ð´Ð¿Ð¾Ð²Ñ–Ð´Ð½Ð¾Ð³Ð¾ запиту злиттÑ. Дані будуть автоматично додані піÑÐ»Ñ Ð·Ð°Ð²ÐµÑ€ÑˆÐµÐ½Ð½Ñ Ð¿ÐµÑ€ÑˆÐ¾Ð³Ð¾ конвеєра."
msgid "The time taken by each data entry gathered by that stage."
msgstr "ЧаÑ, витрачений на кожен елемент, зібраний на цьому етапі."
-msgid ""
-"The value lying at the midpoint of a series of observed values. E.g., "
-"between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 ="
-" 6."
-msgstr ""
-"Середнє Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð² Ñ€Ñдку. Приклад: між 3, 5, 9, Ñередніми 5, між 3, 5, 7, 8, "
-"Ñередніми (5 + 7) / 2 = 6."
+msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
+msgstr "Середнє Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð² Ñ€Ñдку. Приклад: між 3, 5, 9, Ñередніми 5, між 3, 5, 7, 8, Ñередніми (5 + 7) / 2 = 6."
-msgid ""
-"This means you can not push code until you create an empty repository or "
-"import existing one."
+msgid "There are problems accessing Git storage: "
msgstr ""
-"Це означає, що ви не можете відправлÑти код, поки не Ñтворите порожній "
-"репозиторій або ÐЕ імпортуєте Ñ–Ñнуючий."
+
+msgid "This means you can not push code until you create an empty repository or import existing one."
+msgstr "Це означає, що ви не можете відправлÑти код, поки не Ñтворите порожній репозиторій або ÐЕ імпортуєте Ñ–Ñнуючий."
msgid "Time before an issue gets scheduled"
msgstr "Ð§Ð°Ñ Ð´Ð¾ початку потраплÑÐ½Ð½Ñ Ð¿Ñ€Ð¾Ð±Ð»ÐµÐ¼Ð¸ в планувальник"
@@ -1146,6 +1207,9 @@ msgstr "Завантажити файл"
msgid "UploadLink|click to upload"
msgstr "ÐатиÑніть, щоб завантажити"
+msgid "Use the following registration token during setup:"
+msgstr ""
+
msgid "Use your global notification setting"
msgstr "ВикориÑтовуютьÑÑ Ð³Ð»Ð¾Ð±Ð°Ð»ÑŒÐ½Ñ– Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½ÑŒ"
@@ -1179,19 +1243,11 @@ msgstr "Ви хочете видалити %{group_name}. Видалені грÑ
msgid "You are going to remove %{project_name_with_namespace}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr "Ви хочете видалити %{project_name_with_namespace}. Видалений проект ÐЕ МОЖЕ бути відновлений! Ви ÐБСОЛЮТÐО впевнені?"
-msgid ""
-"You are going to remove the fork relationship to source project "
-"%{forked_from_project}. Are you ABSOLUTELY sure?"
-msgstr ""
-"Ви збираєтеÑÑ Ð²Ð¸Ð´Ð°Ð»Ð¸Ñ‚Ð¸ зв'Ñзок з форка з вихідним проектом "
-"%{forked_from_project}. Ви ÐБСОЛЮТÐО впевнені?"
+msgid "You are going to remove the fork relationship to source project %{forked_from_project}. Are you ABSOLUTELY sure?"
+msgstr "Ви збираєтеÑÑ Ð²Ð¸Ð´Ð°Ð»Ð¸Ñ‚Ð¸ зв'Ñзок з форка з вихідним проектом %{forked_from_project}. Ви ÐБСОЛЮТÐО впевнені?"
-msgid ""
-"You are going to transfer %{project_name_with_namespace} to another owner. "
-"Are you ABSOLUTELY sure?"
-msgstr ""
-"Ви збираєтеÑÑ Ð¿ÐµÑ€ÐµÐ´Ð°Ñ‚Ð¸ проект %{project_name_with_namespace} іншому влаÑнику."
-" Ви ÐБСОЛЮТÐО впевнені?"
+msgid "You are going to transfer %{project_name_with_namespace} to another owner. Are you ABSOLUTELY sure?"
+msgstr "Ви збираєтеÑÑ Ð¿ÐµÑ€ÐµÐ´Ð°Ñ‚Ð¸ проект %{project_name_with_namespace} іншому влаÑнику. Ви ÐБСОЛЮТÐО впевнені?"
msgid "You can only add files when you are on a branch"
msgstr "Ви можете додавати тільки файли, коли перебуваєте в гілці"
@@ -1211,35 +1267,20 @@ msgstr "Ви не отримаєте ніÑких повідомлень по е
msgid "You will only receive notifications for the events you choose"
msgstr "Ви будете отримувати Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ñ‚Ñ–Ð»ÑŒÐºÐ¸ про обрані вами події"
-msgid ""
-"You will only receive notifications for threads you have participated in"
-msgstr ""
-"Ви будете отримувати Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ñ‚Ñ–Ð»ÑŒÐºÐ¸ про тих темах, в Ñких ви брали "
-"учаÑÑ‚ÑŒ"
+msgid "You will only receive notifications for threads you have participated in"
+msgstr "Ви будете отримувати Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ñ‚Ñ–Ð»ÑŒÐºÐ¸ про тих темах, в Ñких ви брали учаÑÑ‚ÑŒ"
msgid "You will receive notifications for any activity"
msgstr "Ви будете отримувати Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð¿Ñ€Ð¾ будь-Ñкі дії"
-msgid ""
-"You will receive notifications only for comments in which you were "
-"@mentioned"
-msgstr ""
-"Ви будете отримувати Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ñ‚Ñ–Ð»ÑŒÐºÐ¸ Ð´Ð»Ñ ÐºÐ¾Ð¼ÐµÐ½Ñ‚Ð°Ñ€Ñ–Ð², в Ñких ви були "
-"@згадані"
+msgid "You will receive notifications only for comments in which you were @mentioned"
+msgstr "Ви будете отримувати Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ñ‚Ñ–Ð»ÑŒÐºÐ¸ Ð´Ð»Ñ ÐºÐ¾Ð¼ÐµÐ½Ñ‚Ð°Ñ€Ñ–Ð², в Ñких ви були @згадані"
-msgid ""
-"You won't be able to pull or push project code via %{protocol} until you "
-"%{set_password_link} on your account"
-msgstr ""
-"Ви не зможете отримувати Ñ– відправлÑти код проекту через %{protocol} поки "
-"%{set_password_link} в ваш аккаунт"
+msgid "You won't be able to pull or push project code via %{protocol} until you %{set_password_link} on your account"
+msgstr "Ви не зможете отримувати Ñ– відправлÑти код проекту через %{protocol} поки %{set_password_link} в ваш аккаунт"
-msgid ""
-"You won't be able to pull or push project code via SSH until you "
-"%{add_ssh_key_link} to your profile"
-msgstr ""
-"Ви не зможете отримувати Ñ– відправлÑти код проекту через SSH поки "
-"%{add_ssh_key_link} в ваш профіль."
+msgid "You won't be able to pull or push project code via SSH until you %{add_ssh_key_link} to your profile"
+msgstr "Ви не зможете отримувати Ñ– відправлÑти код проекту через SSH поки %{add_ssh_key_link} в ваш профіль."
msgid "Your name"
msgstr "Ваше ім'Ñ"
@@ -1260,5 +1301,4 @@ msgid "parent"
msgid_plural "parents"
msgstr[0] "джерело"
msgstr[1] "джерела"
-msgstr[2] "джерел"
-
+msgstr[2] "джерел" \ No newline at end of file
diff --git a/locale/zh_CN/gitlab.po b/locale/zh_CN/gitlab.po
index a3d0027212c..b25234da030 100644
--- a/locale/zh_CN/gitlab.po
+++ b/locale/zh_CN/gitlab.po
@@ -1,36 +1,51 @@
-# Huang Tao <htve@outlook.com>, 2017. #zanata
-# Xiaogang Wen <xiaogang@gitlab.com>, 2017.
msgid ""
msgstr ""
-"Project-Id-Version: gitlab 1.0.0\n"
+"Project-Id-Version: gitlab-ee\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2017-07-05 08:50-0500\n"
+"POT-Creation-Date: 2017-08-18 14:15+0530\n"
+"PO-Revision-Date: 2017-08-23 09:59-0400\n"
+"Last-Translator: gitlab <mbartlett+crowdin@gitlab.com>\n"
+"Language-Team: Chinese Simplified\n"
+"Language: zh_CN\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"PO-Revision-Date: 2017-07-12 06:23-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"
-"X-Generator: Zanata 3.9.6\n"
-"Plural-Forms: nplurals=1; plural=0\n"
-
-msgid "%s additional commit has been omitted to prevent performance issues."
-msgid_plural ""
-"%s additional commits have been omitted to prevent performance issues."
-msgstr[0] "为æ高页é¢åŠ è½½é€Ÿåº¦åŠæ€§èƒ½ï¼Œå·²çœç•¥äº† %s 次æ交。"
+"Plural-Forms: nplurals=1; plural=0;\n"
+"X-Generator: crowdin.com\n"
+"X-Crowdin-Project: gitlab-ee\n"
+"X-Crowdin-Language: zh-CN\n"
+"X-Crowdin-File: /master/locale/gitlab.pot\n"
msgid "%d commit"
msgid_plural "%d commits"
msgstr[0] "%d 次æ交"
+msgid "%s additional commit has been omitted to prevent performance issues."
+msgid_plural "%s additional commits have been omitted to prevent performance issues."
+msgstr[0] "为æ高页é¢åŠ è½½é€Ÿåº¦åŠæ€§èƒ½ï¼Œå·²çœç•¥äº† %s 次æ交。"
+
msgid "%{commit_author_link} committed %{commit_timeago}"
msgstr "ç”± %{commit_author_link} æ交于 %{commit_timeago}"
+msgid "%{number_of_failures} of %{maximum_failures} failures. GitLab will allow access on the next attempt."
+msgstr ""
+
+msgid "%{number_of_failures} of %{maximum_failures} failures. GitLab will block access for %{number_of_seconds} seconds."
+msgstr ""
+
+msgid "%{number_of_failures} of %{maximum_failures} failures. GitLab will not retry automatically. Reset storage information when the problem is resolved."
+msgstr ""
+
+msgid "%{storage_name}: failed storage access attempt on host:"
+msgid_plural "%{storage_name}: %{failed_attempts} failed storage access attempts:"
+msgstr[0] ""
+
+msgid "(checkout the %{link} for information on how to install it)."
+msgstr ""
+
msgid "1 pipeline"
msgid_plural "%d pipelines"
msgstr[0] "1 æ¡æµæ°´çº¿"
-msgstr[1] "%d æ¡æµæ°´çº¿"
msgid "A collection of graphs regarding Continuous Integration"
msgstr "æŒç»­é›†æˆæ•°æ®å›¾"
@@ -38,6 +53,9 @@ msgstr "æŒç»­é›†æˆæ•°æ®å›¾"
msgid "About auto deploy"
msgstr "关于自动部署"
+msgid "Access to failing storages has been temporarily disabled to allow the mount to recover. Reset storage information after the issue has been resolved to allow access again."
+msgstr ""
+
msgid "Active"
msgstr "å¯ç”¨"
@@ -59,12 +77,27 @@ msgstr "新建一个用于推é€æˆ–拉å–çš„ SSH 秘钥到账å·ä¸­ã€‚"
msgid "Add new directory"
msgstr "添加目录"
+msgid "All"
+msgstr ""
+
msgid "Archived project! Repository is read-only"
msgstr "项目已归档ï¼å­˜å‚¨åº“为åªè¯»çŠ¶æ€"
msgid "Are you sure you want to delete this pipeline schedule?"
msgstr "确定è¦åˆ é™¤æ­¤æµæ°´çº¿è®¡åˆ’å—?"
+msgid "Are you sure you want to discard your changes?"
+msgstr ""
+
+msgid "Are you sure you want to reset registration token?"
+msgstr ""
+
+msgid "Are you sure you want to reset the health check token?"
+msgstr ""
+
+msgid "Are you sure?"
+msgstr ""
+
msgid "Attach a file by drag &amp; drop or %{upload_link}"
msgstr "拖放文件到此处或者 %{upload_link}"
@@ -72,13 +105,8 @@ msgid "Branch"
msgid_plural "Branches"
msgstr[0] "分支"
-msgid ""
-"Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, "
-"choose a GitLab CI Yaml template and commit your changes. "
-"%{link_to_autodeploy_doc}"
-msgstr ""
-"已创建分支 <strong>%{branch_name}</strong> 。如需设置自动部署, 请选择åˆé€‚çš„ GitLab CI Yaml "
-"模æ¿å¹¶æ交更改。%{link_to_autodeploy_doc}"
+msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
+msgstr "已创建分支 <strong>%{branch_name}</strong> 。如需设置自动部署, 请选择åˆé€‚çš„ GitLab CI Yaml 模æ¿å¹¶æ交更改。%{link_to_autodeploy_doc}"
msgid "BranchSwitcherPlaceholder|Search branches"
msgstr "æœç´¢åˆ†æ”¯"
@@ -110,6 +138,9 @@ msgstr "CI é…ç½®"
msgid "Cancel"
msgstr "å–消"
+msgid "Cancel edit"
+msgstr ""
+
msgid "ChangeTypeActionLabel|Pick into branch"
msgstr "选择分支"
@@ -188,6 +219,9 @@ msgstr "已跳过"
msgid "CiStatus|running"
msgstr "è¿è¡Œä¸­"
+msgid "Comments"
+msgstr ""
+
msgid "Commit"
msgid_plural "Commits"
msgstr[0] "æ交"
@@ -234,9 +268,10 @@ msgstr "å¤åˆ¶æ交 SHA 的值到剪贴æ¿"
msgid "Create New Directory"
msgstr "创建新目录"
-msgid ""
-"Create a personal access token on your account to pull or push via "
-"%{protocol}."
+msgid "Create a new branch"
+msgstr ""
+
+msgid "Create a personal access token on your account to pull or push via %{protocol}."
msgstr "在å¸æˆ·ä¸Šåˆ›å»ºä¸ªäººè®¿é—®ä»¤ç‰Œï¼Œä»¥é€šè¿‡ %{protocol} æ¥æ‹‰å–或推é€ã€‚"
msgid "Create directory"
@@ -269,19 +304,13 @@ msgstr "Cron 语法"
msgid "Custom notification events"
msgstr "自定义通知事件"
-msgid ""
-"Custom notification levels are the same as participating levels. With custom "
-"notification levels you will also receive notifications for select events. "
-"To find out more, check out %{notification_link}."
-msgstr ""
-"自定义通知级别继承自å‚与级别。使用自定义通知级别,您会收到å‚与级别åŠé€‰å®šäº‹ä»¶çš„通知。想了解更多信æ¯ï¼Œè¯·æŸ¥çœ‹ %{notification_link}."
+msgid "Custom notification levels are the same as participating levels. With custom notification levels you will also receive notifications for select events. To find out more, check out %{notification_link}."
+msgstr "自定义通知级别继承自å‚与级别。使用自定义通知级别,您会收到å‚与级别åŠé€‰å®šäº‹ä»¶çš„通知。想了解更多信æ¯ï¼Œè¯·æŸ¥çœ‹ %{notification_link}."
msgid "Cycle Analytics"
msgstr "周期分æž"
-msgid ""
-"Cycle Analytics gives an overview of how much time it takes to go from idea "
-"to production in your project."
+msgid "Cycle Analytics gives an overview of how much time it takes to go from idea to production in your project."
msgstr "周期分æžæ¦‚述了项目从想法到产å“实现的å„阶段所需的时间。"
msgid "CycleAnalyticsStage|Code"
@@ -318,9 +347,15 @@ msgstr[0] "部署"
msgid "Description"
msgstr "æè¿°"
+msgid "Details"
+msgstr ""
+
msgid "Directory name"
msgstr "目录å称"
+msgid "Discard changes"
+msgstr ""
+
msgid "Don't show again"
msgstr "ä¸å†æ˜¾ç¤º"
@@ -357,6 +392,24 @@ msgstr "编辑"
msgid "Edit Pipeline Schedule %{id}"
msgstr "编辑 %{id} æµæ°´çº¿è®¡åˆ’"
+msgid "EventFilterBy|Filter by all"
+msgstr ""
+
+msgid "EventFilterBy|Filter by comments"
+msgstr ""
+
+msgid "EventFilterBy|Filter by issue events"
+msgstr ""
+
+msgid "EventFilterBy|Filter by merge events"
+msgstr ""
+
+msgid "EventFilterBy|Filter by push events"
+msgstr ""
+
+msgid "EventFilterBy|Filter by team"
+msgstr ""
+
msgid "Every day (at 4:00am)"
msgstr "æ¯æ—¥æ‰§è¡Œï¼ˆå‡Œæ™¨ 4 点)"
@@ -403,12 +456,36 @@ msgstr "从创建议题到部署至生产环境"
msgid "From merge request merge until deploy to production"
msgstr "从åˆå¹¶è¯·æ±‚被åˆå¹¶åŽåˆ°éƒ¨ç½²è‡³ç”Ÿäº§çŽ¯å¢ƒ"
+msgid "Git storage health information has been reset"
+msgstr ""
+
+msgid "GitLab Runner section"
+msgstr ""
+
msgid "Go to your fork"
msgstr "跳转到派生项目"
msgid "GoToYourFork|Fork"
msgstr "跳转到派生项目"
+msgid "Health Check"
+msgstr ""
+
+msgid "Health information can be retrieved from the following endpoints. More information is available"
+msgstr ""
+
+msgid "HealthCheck|Access token is"
+msgstr ""
+
+msgid "HealthCheck|Healthy"
+msgstr ""
+
+msgid "HealthCheck|No Health Problems Detected"
+msgstr ""
+
+msgid "HealthCheck|Unhealthy"
+msgstr ""
+
msgid "Home"
msgstr "首页"
@@ -418,12 +495,18 @@ msgstr "已开始维护"
msgid "Import repository"
msgstr "导入存储库"
+msgid "Install a Runner compatible with GitLab CI"
+msgstr ""
+
msgid "Interval Pattern"
msgstr "循环周期"
msgid "Introducing Cycle Analytics"
msgstr "周期分æžç®€ä»‹"
+msgid "Issue events"
+msgstr ""
+
msgid "Jobs for last month"
msgstr "上个月的作业"
@@ -452,6 +535,12 @@ msgstr "最åŽæ›´æ–°"
msgid "Last commit"
msgstr "最åŽæ交"
+msgid "LastPushEvent|You pushed to"
+msgstr ""
+
+msgid "LastPushEvent|at"
+msgstr ""
+
msgid "Learn more in the"
msgstr "了解更多"
@@ -471,9 +560,15 @@ msgstr[0] "最多显示 %d 个事件"
msgid "Median"
msgstr "中ä½æ•°"
+msgid "Merge events"
+msgstr ""
+
msgid "MissingSSHKeyWarningLink|add an SSH key"
msgstr "新建 SSH 公钥"
+msgid "More information is available|here"
+msgstr ""
+
msgid "New Issue"
msgid_plural "New Issues"
msgstr[0] "新建议题"
@@ -670,6 +765,9 @@ msgstr "于阶段"
msgid "Pipeline|with stages"
msgstr "于阶段"
+msgid "Project"
+msgstr ""
+
msgid "Project '%{project_name}' queued for deletion."
msgstr "项目 '%{project_name}' 已进入删除队列。"
@@ -685,15 +783,16 @@ msgstr "项目 '%{project_name}' 将被删除。"
msgid "Project access must be granted explicitly to each user."
msgstr "项目访问æƒé™å¿…须明确授æƒç»™æ¯ä¸ªç”¨æˆ·ã€‚"
+msgid "Project details"
+msgstr ""
+
msgid "Project export could not be deleted."
msgstr "无法删除项目导出。"
msgid "Project export has been deleted."
msgstr "项目导出已被删除。"
-msgid ""
-"Project export link has expired. Please generate a new export from your "
-"project settings."
+msgid "Project export link has expired. Please generate a new export from your project settings."
msgstr "项目导出链接已过期。请从项目设置中é‡æ–°ç”Ÿæˆé¡¹ç›®å¯¼å‡ºã€‚"
msgid "Project export started. A download link will be sent by email."
@@ -702,6 +801,9 @@ msgstr "项目导出已开始。下载链接将通过电å­é‚®ä»¶å‘é€ã€‚"
msgid "Project home"
msgstr "项目首页"
+msgid "ProjectActivityRSS|Subscribe"
+msgstr ""
+
msgid "ProjectFeature|Disabled"
msgstr "åœç”¨"
@@ -723,6 +825,9 @@ msgstr "阶段"
msgid "ProjectNetworkGraph|Graph"
msgstr "分支图"
+msgid "Push events"
+msgstr ""
+
msgid "Read more"
msgstr "了解更多"
@@ -759,9 +864,21 @@ msgstr "ç¨åŽæ醒"
msgid "Remove project"
msgstr "删除项目"
+msgid "Repository"
+msgstr ""
+
msgid "Request Access"
msgstr "申请æƒé™"
+msgid "Reset git storage health information"
+msgstr ""
+
+msgid "Reset health check access token"
+msgstr ""
+
+msgid "Reset runners registration token"
+msgstr ""
+
msgid "Revert this commit"
msgstr "还原此æ交"
@@ -786,6 +903,9 @@ msgstr "选择下载格å¼"
msgid "Select a timezone"
msgstr "选择时区"
+msgid "Select existing branch"
+msgstr ""
+
msgid "Select target branch"
msgstr "选择目标分支"
@@ -811,12 +931,18 @@ msgstr[0] "显示 %d 个事件"
msgid "Source code"
msgstr "æºä»£ç "
+msgid "Specify the following URL during the Runner setup:"
+msgstr ""
+
msgid "StarProject|Star"
msgstr "星标"
msgid "Start a %{new_merge_request} with these changes"
msgstr "由此更改 %{new_merge_request}"
+msgid "Start the Runner!"
+msgstr ""
+
msgid "Switch branch/tag"
msgstr "切æ¢åˆ†æ”¯/标签"
@@ -830,10 +956,10 @@ msgstr "标签"
msgid "Target Branch"
msgstr "目标分支"
-msgid ""
-"The coding stage shows the time from the first commit to creating the merge "
-"request. The data will automatically be added here once you create your "
-"first merge request."
+msgid "Team"
+msgstr ""
+
+msgid "The coding stage shows the time from the first commit to creating the merge request. The data will automatically be added here once you create your first merge request."
msgstr "ç¼–ç é˜¶æ®µæ¦‚述了从第一次æ交到创建åˆå¹¶è¯·æ±‚的时间。创建第一个åˆå¹¶è¯·æ±‚åŽï¼Œæ•°æ®å°†è‡ªåŠ¨æ·»åŠ åˆ°æ­¤å¤„。"
msgid "The collection of events added to the data gathered for that stage."
@@ -842,31 +968,19 @@ msgstr "与该阶段相关的事件集åˆã€‚"
msgid "The fork relationship has been removed."
msgstr "派生关系已被删除。"
-msgid ""
-"The issue stage shows the time it takes from creating an issue to assigning "
-"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."
+msgid "The issue stage shows the time it takes from creating an issue to assigning 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 "议题阶段概述了从创建议题到将议题添加到里程碑或议题看æ¿æ‰€èŠ±è´¹çš„时间。创建第一个议题åŽï¼Œæ•°æ®å°†è‡ªåŠ¨æ·»åŠ åˆ°æ­¤å¤„.。"
msgid "The phase of the development lifecycle."
msgstr "项目生命周期中的å„个阶段。"
-msgid ""
-"The pipelines schedule runs pipelines in the future, repeatedly, for "
-"specific branches or tags. Those scheduled pipelines will inherit limited "
-"project access based on their associated user."
+msgid "The pipelines schedule runs pipelines in the future, repeatedly, for specific branches or tags. Those scheduled pipelines will inherit limited project access based on their associated user."
msgstr "æµæ°´çº¿è®¡åˆ’会周期性é‡å¤è¿è¡ŒæŒ‡å®šåˆ†æ”¯æˆ–标签的æµæ°´çº¿ã€‚这些æµæ°´çº¿å°†æ ¹æ®å…¶å…³è”用户继承有é™çš„项目访问æƒé™ã€‚"
-msgid ""
-"The planning stage shows the time from the previous step to pushing your "
-"first commit. This time will be added automatically once you push your first "
-"commit."
+msgid "The planning stage shows the time from the previous step to pushing your first commit. This time will be added automatically once you push your first commit."
msgstr "计划阶段概述了从议题添加到日程到推é€é¦–次æ交的时间。当首次推é€æ交åŽï¼Œæ•°æ®å°†è‡ªåŠ¨æ·»åŠ åˆ°æ­¤å¤„。"
-msgid ""
-"The production stage shows the total time it takes between creating an issue "
-"and deploying the code to production. The data will be automatically added "
-"once you have completed the full idea to production cycle."
+msgid "The production stage shows the total time it takes between creating an issue and deploying the code to production. The data will be automatically added once you have completed the full idea to production cycle."
msgstr "生产阶段概述了从创建一个议题到将代ç éƒ¨ç½²åˆ°ç”Ÿäº§çŽ¯å¢ƒçš„总时间。当完æˆæƒ³æ³•åˆ°éƒ¨ç½²ç”Ÿäº§çš„循环,数æ®å°†è‡ªåŠ¨æ·»åŠ åˆ°æ­¤å¤„。"
msgid "The project can be accessed by any logged in user."
@@ -878,36 +992,25 @@ msgstr "该项目å…许任何人访问。"
msgid "The repository for this project does not exist."
msgstr "此项目的存储库ä¸å­˜åœ¨ã€‚"
-msgid ""
-"The review stage shows the time from creating the merge request to merging "
-"it. The data will automatically be added after you merge your first merge "
-"request."
+msgid "The review stage shows the time from creating the merge request to merging it. The data will automatically be added after you merge your first merge request."
msgstr "评审阶段概述了从创建åˆå¹¶è¯·æ±‚到被åˆå¹¶çš„时间。当创建第一个åˆå¹¶è¯·æ±‚åŽï¼Œæ•°æ®å°†è‡ªåŠ¨æ·»åŠ åˆ°æ­¤å¤„。"
-msgid ""
-"The staging stage shows the time between merging the MR and deploying code "
-"to the production environment. The data will be automatically added once you "
-"deploy to production for the first time."
+msgid "The staging stage shows the time between merging the MR and deploying code to the production environment. The data will be automatically added once you deploy to production for the first time."
msgstr "预å‘布阶段概述了从åˆå¹¶è¯·æ±‚被åˆå¹¶åˆ°éƒ¨ç½²è‡³ç”Ÿäº§çŽ¯å¢ƒçš„总时间。首次部署到生产环境åŽï¼Œæ•°æ®å°†è‡ªåŠ¨æ·»åŠ åˆ°æ­¤å¤„。"
-msgid ""
-"The testing stage shows the time GitLab CI takes to run every pipeline for "
-"the related merge request. The data will automatically be added after your "
-"first pipeline finishes running."
+msgid "The testing stage shows the time GitLab CI takes to run every pipeline for the related merge request. The data will automatically be added after your first pipeline finishes running."
msgstr "测试阶段概述了 GitLab CI 为相关åˆå¹¶è¯·æ±‚è¿è¡Œæ¯ä¸ªæµæ°´çº¿æ‰€éœ€çš„时间。当第一个æµæ°´çº¿è¿è¡Œå®ŒæˆåŽï¼Œæ•°æ®å°†è‡ªåŠ¨æ·»åŠ åˆ°æ­¤å¤„。"
msgid "The time taken by each data entry gathered by that stage."
msgstr "该阶段æ¯æ¡æ•°æ®æ‰€èŠ±çš„时间"
-msgid ""
-"The value lying at the midpoint of a series of observed values. E.g., "
-"between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 ="
-" 6."
+msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
msgstr "中ä½æ•°æ˜¯ä¸€ä¸ªæ•°åˆ—中最中间的值。例如在 3ã€5ã€9 之间,中ä½æ•°æ˜¯ 5。在 3ã€5ã€7ã€8 之间,中ä½æ•°æ˜¯ (5 + 7)/ 2 = 6。"
-msgid ""
-"This means you can not push code until you create an empty repository or "
-"import existing one."
+msgid "There are problems accessing Git storage: "
+msgstr ""
+
+msgid "This means you can not push code until you create an empty repository or import existing one."
msgstr "在创建一个空的存储库或导入现有存储库之å‰ï¼Œå°†æ— æ³•æŽ¨é€ä»£ç ã€‚"
msgid "Time before an issue gets scheduled"
@@ -1074,6 +1177,9 @@ msgstr "上传文件"
msgid "UploadLink|click to upload"
msgstr "点击上传"
+msgid "Use the following registration token during setup:"
+msgstr ""
+
msgid "Use your global notification setting"
msgstr "使用全局通知设置"
@@ -1107,14 +1213,10 @@ msgstr "å³å°†åˆ é™¤ %{group_name}。已删除的群组无法æ¢å¤ï¼ç¡®å®šç»§ç
msgid "You are going to remove %{project_name_with_namespace}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr "å³å°†è¦åˆ é™¤ %{project_name_with_namespace}。已删除的项目无法æ¢å¤ï¼ç¡®å®šç»§ç»­å—?"
-msgid ""
-"You are going to remove the fork relationship to source project "
-"%{forked_from_project}. Are you ABSOLUTELY sure?"
+msgid "You are going to remove the fork relationship to source project %{forked_from_project}. Are you ABSOLUTELY sure?"
msgstr "å³å°†åˆ é™¤ä¸Žæºé¡¹ç›® %{forked_from_project} 的派生关系。确定继续å—?"
-msgid ""
-"You are going to transfer %{project_name_with_namespace} to another owner. "
-"Are you ABSOLUTELY sure?"
+msgid "You are going to transfer %{project_name_with_namespace} to another owner. Are you ABSOLUTELY sure?"
msgstr "å³å°† %{project_name_with_namespace} 转移给å¦ä¸€ä¸ªæ‰€æœ‰è€…。确定继续å—?"
msgid "You can only add files when you are on a branch"
@@ -1135,26 +1237,19 @@ msgstr "ä¸ä¼šæ”¶åˆ°ä»»ä½•é€šçŸ¥é‚®ä»¶"
msgid "You will only receive notifications for the events you choose"
msgstr "åªæŽ¥æ”¶é€‰æ‹©çš„事件通知"
-msgid ""
-"You will only receive notifications for threads you have participated in"
+msgid "You will only receive notifications for threads you have participated in"
msgstr "åªæŽ¥æ”¶å‚与的主题的通知"
msgid "You will receive notifications for any activity"
msgstr "接收所有活动的通知"
-msgid ""
-"You will receive notifications only for comments in which you were "
-"@mentioned"
+msgid "You will receive notifications only for comments in which you were @mentioned"
msgstr "åªæŽ¥æ”¶è¯„论中æåŠ(@)您的通知"
-msgid ""
-"You won't be able to pull or push project code via %{protocol} until you "
-"%{set_password_link} on your account"
+msgid "You won't be able to pull or push project code via %{protocol} until you %{set_password_link} on your account"
msgstr "在账å·ä¸­ %{set_password_link} 之å‰å°†æ— æ³•é€šè¿‡ %{protocol} 拉å–或推é€ä»£ç ã€‚"
-msgid ""
-"You won't be able to pull or push project code via SSH until you "
-"%{add_ssh_key_link} to your profile"
+msgid "You won't be able to pull or push project code via SSH until you %{add_ssh_key_link} to your profile"
msgstr "在账å·ä¸­ %{add_ssh_key_link} 之å‰å°†æ— æ³•é€šè¿‡ SSH 拉å–或推é€ä»£ç ã€‚"
msgid "Your name"
@@ -1172,4 +1267,4 @@ msgstr "通知邮件"
msgid "parent"
msgid_plural "parents"
-msgstr[0] "父级"
+msgstr[0] "父级" \ No newline at end of file
diff --git a/locale/zh_HK/gitlab.po b/locale/zh_HK/gitlab.po
index f4d33862a36..8a3a69a0ac0 100644
--- a/locale/zh_HK/gitlab.po
+++ b/locale/zh_HK/gitlab.po
@@ -1,35 +1,51 @@
-# Huang Tao <htve@outlook.com>, 2017. #zanata
msgid ""
msgstr ""
-"Project-Id-Version: gitlab 1.0.0\n"
+"Project-Id-Version: gitlab-ee\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2017-07-05 08:50-0500\n"
+"POT-Creation-Date: 2017-08-18 14:15+0530\n"
+"PO-Revision-Date: 2017-08-23 09:59-0400\n"
+"Last-Translator: gitlab <mbartlett+crowdin@gitlab.com>\n"
+"Language-Team: Chinese Traditional, Hong Kong\n"
+"Language: zh_HK\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"PO-Revision-Date: 2017-07-12 06:32-0400\n"
-"Last-Translator: Huang Tao <htve@outlook.com>\n"
-"Language-Team: Chinese (Hong Kong SAR China) (https://translate.zanata.org/project/view/GitLab)\n"
-"Language: zh-HK\n"
-"X-Generator: Zanata 3.9.6\n"
-"Plural-Forms: nplurals=1; plural=0\n"
-
-msgid "%s additional commit has been omitted to prevent performance issues."
-msgid_plural ""
-"%s additional commits have been omitted to prevent performance issues."
-msgstr[0] "為æ高é é¢åŠ è¼‰é€Ÿåº¦åŠæ€§èƒ½ï¼Œå·²çœç•¥äº† %s 次æ交。"
+"Plural-Forms: nplurals=1; plural=0;\n"
+"X-Generator: crowdin.com\n"
+"X-Crowdin-Project: gitlab-ee\n"
+"X-Crowdin-Language: zh-HK\n"
+"X-Crowdin-File: /master/locale/gitlab.pot\n"
msgid "%d commit"
msgid_plural "%d commits"
msgstr[0] " %d 次æ交"
+msgid "%s additional commit has been omitted to prevent performance issues."
+msgid_plural "%s additional commits have been omitted to prevent performance issues."
+msgstr[0] "為æ高é é¢åŠ è¼‰é€Ÿåº¦åŠæ€§èƒ½ï¼Œå·²çœç•¥äº† %s 次æ交。"
+
msgid "%{commit_author_link} committed %{commit_timeago}"
msgstr "ç”± %{commit_author_link} æ交於 %{commit_timeago}"
+msgid "%{number_of_failures} of %{maximum_failures} failures. GitLab will allow access on the next attempt."
+msgstr ""
+
+msgid "%{number_of_failures} of %{maximum_failures} failures. GitLab will block access for %{number_of_seconds} seconds."
+msgstr ""
+
+msgid "%{number_of_failures} of %{maximum_failures} failures. GitLab will not retry automatically. Reset storage information when the problem is resolved."
+msgstr ""
+
+msgid "%{storage_name}: failed storage access attempt on host:"
+msgid_plural "%{storage_name}: %{failed_attempts} failed storage access attempts:"
+msgstr[0] ""
+
+msgid "(checkout the %{link} for information on how to install it)."
+msgstr ""
+
msgid "1 pipeline"
msgid_plural "%d pipelines"
msgstr[0] "1 æ¢æµæ°´ç·š"
-msgstr[1] "%d æ¢æµæ°´ç·š"
msgid "A collection of graphs regarding Continuous Integration"
msgstr "相關æŒçºŒé›†æˆçš„圖åƒé›†åˆ"
@@ -37,6 +53,9 @@ msgstr "相關æŒçºŒé›†æˆçš„圖åƒé›†åˆ"
msgid "About auto deploy"
msgstr "關於自動部署"
+msgid "Access to failing storages has been temporarily disabled to allow the mount to recover. Reset storage information after the issue has been resolved to allow access again."
+msgstr ""
+
msgid "Active"
msgstr "啟用"
@@ -58,12 +77,27 @@ msgstr "新增壹個用於推é€æˆ–拉å–çš„ SSH 秘鑰到賬號中。"
msgid "Add new directory"
msgstr "添加新目錄"
+msgid "All"
+msgstr ""
+
msgid "Archived project! Repository is read-only"
msgstr "歸檔項目ï¼å­˜å„²åº«ç‚ºåªè®€"
msgid "Are you sure you want to delete this pipeline schedule?"
msgstr "確定è¦åˆªé™¤æ­¤æµæ°´ç·šè¨ˆåŠƒå—Žï¼Ÿ"
+msgid "Are you sure you want to discard your changes?"
+msgstr ""
+
+msgid "Are you sure you want to reset registration token?"
+msgstr ""
+
+msgid "Are you sure you want to reset the health check token?"
+msgstr ""
+
+msgid "Are you sure?"
+msgstr ""
+
msgid "Attach a file by drag &amp; drop or %{upload_link}"
msgstr "拖放文件到此處或者 %{upload_link}"
@@ -71,13 +105,8 @@ msgid "Branch"
msgid_plural "Branches"
msgstr[0] "分支"
-msgid ""
-"Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, "
-"choose a GitLab CI Yaml template and commit your changes. "
-"%{link_to_autodeploy_doc}"
-msgstr ""
-"分支 <strong>%{branch_name}</strong> 已創建。如需設置自動部署, è«‹é¸æ“‡åˆé©çš„ GitLab CI Yaml "
-"模æ¿ä½µæ交更改。%{link_to_autodeploy_doc}"
+msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
+msgstr "分支 <strong>%{branch_name}</strong> 已創建。如需設置自動部署, è«‹é¸æ“‡åˆé©çš„ GitLab CI Yaml 模æ¿ä½µæ交更改。%{link_to_autodeploy_doc}"
msgid "BranchSwitcherPlaceholder|Search branches"
msgstr "æœç´¢åˆ†æ”¯"
@@ -109,6 +138,9 @@ msgstr "CI é…ç½®"
msgid "Cancel"
msgstr "å–消"
+msgid "Cancel edit"
+msgstr ""
+
msgid "ChangeTypeActionLabel|Pick into branch"
msgstr "挑é¸åˆ°åˆ†æ”¯"
@@ -187,6 +219,9 @@ msgstr "已跳éŽ"
msgid "CiStatus|running"
msgstr "é‹è¡Œä¸­"
+msgid "Comments"
+msgstr ""
+
msgid "Commit"
msgid_plural "Commits"
msgstr[0] "æ交"
@@ -233,9 +268,10 @@ msgstr "複製æ交 SHA 到剪貼æ¿"
msgid "Create New Directory"
msgstr "創建新目錄"
-msgid ""
-"Create a personal access token on your account to pull or push via "
-"%{protocol}."
+msgid "Create a new branch"
+msgstr ""
+
+msgid "Create a personal access token on your account to pull or push via %{protocol}."
msgstr "在帳戶上創建個人訪å•ä»¤ç‰Œï¼Œä»¥é€šéŽ %{protocol} 來拉å–或推é€ã€‚"
msgid "Create directory"
@@ -268,19 +304,13 @@ msgstr "Cron 語法"
msgid "Custom notification events"
msgstr "自定義通知事件"
-msgid ""
-"Custom notification levels are the same as participating levels. With custom "
-"notification levels you will also receive notifications for select events. "
-"To find out more, check out %{notification_link}."
-msgstr ""
-"自定義通知級別繼承自åƒèˆ‡ç´šåˆ¥ã€‚使用自定義通知級別,您會收到åƒèˆ‡ç´šåˆ¥åŠé¸å®šäº‹ä»¶çš„通知。想了解更多信æ¯ï¼Œè«‹æŸ¥çœ‹ %{notification_link}."
+msgid "Custom notification levels are the same as participating levels. With custom notification levels you will also receive notifications for select events. To find out more, check out %{notification_link}."
+msgstr "自定義通知級別繼承自åƒèˆ‡ç´šåˆ¥ã€‚使用自定義通知級別,您會收到åƒèˆ‡ç´šåˆ¥åŠé¸å®šäº‹ä»¶çš„通知。想了解更多信æ¯ï¼Œè«‹æŸ¥çœ‹ %{notification_link}."
msgid "Cycle Analytics"
msgstr "週期分æž"
-msgid ""
-"Cycle Analytics gives an overview of how much time it takes to go from idea "
-"to production in your project."
+msgid "Cycle Analytics gives an overview of how much time it takes to go from idea to production in your project."
msgstr "週期分æžæ¦‚述了項目從想法到產å“實ç¾çš„å„階段所需的時間。"
msgid "CycleAnalyticsStage|Code"
@@ -317,9 +347,15 @@ msgstr[0] "部署"
msgid "Description"
msgstr "æè¿°"
+msgid "Details"
+msgstr ""
+
msgid "Directory name"
msgstr "目錄å稱"
+msgid "Discard changes"
+msgstr ""
+
msgid "Don't show again"
msgstr "ä¸å†é¡¯ç¤º"
@@ -356,6 +392,24 @@ msgstr "編輯"
msgid "Edit Pipeline Schedule %{id}"
msgstr "編輯 %{id} æµæ°´ç·šè¨ˆåŠƒ"
+msgid "EventFilterBy|Filter by all"
+msgstr ""
+
+msgid "EventFilterBy|Filter by comments"
+msgstr ""
+
+msgid "EventFilterBy|Filter by issue events"
+msgstr ""
+
+msgid "EventFilterBy|Filter by merge events"
+msgstr ""
+
+msgid "EventFilterBy|Filter by push events"
+msgstr ""
+
+msgid "EventFilterBy|Filter by team"
+msgstr ""
+
msgid "Every day (at 4:00am)"
msgstr "æ¯æ—¥åŸ·è¡Œï¼ˆæ·©æ™¨ 4 點)"
@@ -402,12 +456,36 @@ msgstr "從創建議題到部署到生產環境"
msgid "From merge request merge until deploy to production"
msgstr "從åˆä½µè«‹æ±‚çš„åˆä½µåˆ°éƒ¨ç½²è‡³ç”Ÿç”¢ç’°å¢ƒ"
+msgid "Git storage health information has been reset"
+msgstr ""
+
+msgid "GitLab Runner section"
+msgstr ""
+
msgid "Go to your fork"
msgstr "跳轉到派生項目"
msgid "GoToYourFork|Fork"
msgstr "跳轉到派生項目"
+msgid "Health Check"
+msgstr ""
+
+msgid "Health information can be retrieved from the following endpoints. More information is available"
+msgstr ""
+
+msgid "HealthCheck|Access token is"
+msgstr ""
+
+msgid "HealthCheck|Healthy"
+msgstr ""
+
+msgid "HealthCheck|No Health Problems Detected"
+msgstr ""
+
+msgid "HealthCheck|Unhealthy"
+msgstr ""
+
msgid "Home"
msgstr "首é "
@@ -417,12 +495,18 @@ msgstr "已開始維護"
msgid "Import repository"
msgstr "導入存儲庫"
+msgid "Install a Runner compatible with GitLab CI"
+msgstr ""
+
msgid "Interval Pattern"
msgstr "循環週期"
msgid "Introducing Cycle Analytics"
msgstr "週期分æžç°¡ä»‹"
+msgid "Issue events"
+msgstr ""
+
msgid "Jobs for last month"
msgstr "上個月的作業"
@@ -451,6 +535,12 @@ msgstr "最後更新"
msgid "Last commit"
msgstr "最後æ交"
+msgid "LastPushEvent|You pushed to"
+msgstr ""
+
+msgid "LastPushEvent|at"
+msgstr ""
+
msgid "Learn more in the"
msgstr "了解更多"
@@ -470,9 +560,15 @@ msgstr[0] "最多顯示 %d 個事件"
msgid "Median"
msgstr "中ä½æ•¸"
+msgid "Merge events"
+msgstr ""
+
msgid "MissingSSHKeyWarningLink|add an SSH key"
msgstr "添加壹個 SSH 公鑰"
+msgid "More information is available|here"
+msgstr ""
+
msgid "New Issue"
msgid_plural "New Issues"
msgstr[0] "新建議題"
@@ -669,6 +765,9 @@ msgstr "於階段"
msgid "Pipeline|with stages"
msgstr "於階段"
+msgid "Project"
+msgstr ""
+
msgid "Project '%{project_name}' queued for deletion."
msgstr "項目 '%{project_name}' 已進入刪除隊列。"
@@ -684,15 +783,16 @@ msgstr "項目 '%{project_name}' 將被刪除。"
msgid "Project access must be granted explicitly to each user."
msgstr "項目訪å•æ¬Šé™å¿…須明確授權給æ¯å€‹ç”¨æˆ¶ã€‚"
+msgid "Project details"
+msgstr ""
+
msgid "Project export could not be deleted."
msgstr "無法刪除項目導出。"
msgid "Project export has been deleted."
msgstr "項目導出已被刪除。"
-msgid ""
-"Project export link has expired. Please generate a new export from your "
-"project settings."
+msgid "Project export link has expired. Please generate a new export from your project settings."
msgstr "項目導出éˆæŽ¥å·²éŽæœŸã€‚請從項目設置中é‡æ–°ç”Ÿæˆé …目導出。"
msgid "Project export started. A download link will be sent by email."
@@ -701,6 +801,9 @@ msgstr "項目導出已開始。下載éˆæŽ¥å°‡é€šéŽé›»å­éƒµä»¶ç™¼é€ã€‚"
msgid "Project home"
msgstr "項目首é "
+msgid "ProjectActivityRSS|Subscribe"
+msgstr ""
+
msgid "ProjectFeature|Disabled"
msgstr "åœç”¨"
@@ -722,6 +825,9 @@ msgstr "階段"
msgid "ProjectNetworkGraph|Graph"
msgstr "分支圖"
+msgid "Push events"
+msgstr ""
+
msgid "Read more"
msgstr "了解更多"
@@ -758,9 +864,21 @@ msgstr "ç¨å¾Œæ醒"
msgid "Remove project"
msgstr "刪除項目"
+msgid "Repository"
+msgstr ""
+
msgid "Request Access"
msgstr "申請權é™"
+msgid "Reset git storage health information"
+msgstr ""
+
+msgid "Reset health check access token"
+msgstr ""
+
+msgid "Reset runners registration token"
+msgstr ""
+
msgid "Revert this commit"
msgstr "還原此æ交"
@@ -785,6 +903,9 @@ msgstr "é¸æ“‡ä¸‹è¼‰æ ¼å¼"
msgid "Select a timezone"
msgstr "é¸æ“‡æ™‚å€"
+msgid "Select existing branch"
+msgstr ""
+
msgid "Select target branch"
msgstr "é¸æ“‡ç›®æ¨™åˆ†æ”¯"
@@ -810,12 +931,18 @@ msgstr[0] "顯示 %d 個事件"
msgid "Source code"
msgstr "æºä»£ç¢¼"
+msgid "Specify the following URL during the Runner setup:"
+msgstr ""
+
msgid "StarProject|Star"
msgstr "星標"
msgid "Start a %{new_merge_request} with these changes"
msgstr "由此更改 %{new_merge_request}"
+msgid "Start the Runner!"
+msgstr ""
+
msgid "Switch branch/tag"
msgstr "切æ›åˆ†æ”¯/標籤"
@@ -829,10 +956,10 @@ msgstr "標籤"
msgid "Target Branch"
msgstr "目標分支"
-msgid ""
-"The coding stage shows the time from the first commit to creating the merge "
-"request. The data will automatically be added here once you create your "
-"first merge request."
+msgid "Team"
+msgstr ""
+
+msgid "The coding stage shows the time from the first commit to creating the merge request. The data will automatically be added here once you create your first merge request."
msgstr "編碼階段概述了從第壹次æ交到創建åˆä½µè«‹æ±‚的時間。創建第壹個åˆä½µè«‹æ±‚後,數據將自動添加到此處。"
msgid "The collection of events added to the data gathered for that stage."
@@ -841,31 +968,19 @@ msgstr "與該階段相關的事件。"
msgid "The fork relationship has been removed."
msgstr "派生關係已被刪除。"
-msgid ""
-"The issue stage shows the time it takes from creating an issue to assigning "
-"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."
+msgid "The issue stage shows the time it takes from creating an issue to assigning 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 "議題階段概述了從創建議題到將議題添加到è£ç¨‹ç¢‘或議題看æ¿æ‰€èŠ±è²»çš„時間。創建第壹個議題後,數據將自動添加到此處.。"
msgid "The phase of the development lifecycle."
msgstr "項目生命週期中的å„個階段。"
-msgid ""
-"The pipelines schedule runs pipelines in the future, repeatedly, for "
-"specific branches or tags. Those scheduled pipelines will inherit limited "
-"project access based on their associated user."
+msgid "The pipelines schedule runs pipelines in the future, repeatedly, for specific branches or tags. Those scheduled pipelines will inherit limited project access based on their associated user."
msgstr "æµæ°´ç·šè¨ˆåŠƒæœƒé€±æœŸæ€§é‡è¤‡é‹è¡ŒæŒ‡å®šåˆ†æ”¯æˆ–標籤的æµæ°´ç·šã€‚這些æµæ°´ç·šå°‡æ ¹æ“šå…¶é—œè¯ç”¨æˆ¶ç¹¼æ‰¿æœ‰é™çš„項目訪å•æ¬Šé™ã€‚"
-msgid ""
-"The planning stage shows the time from the previous step to pushing your "
-"first commit. This time will be added automatically once you push your first "
-"commit."
+msgid "The planning stage shows the time from the previous step to pushing your first commit. This time will be added automatically once you push your first commit."
msgstr "計劃階段概述了從議題添加到日程到推é€é¦–次æ交的時間。當首次推é€æ交後,數據將自動添加到此處。"
-msgid ""
-"The production stage shows the total time it takes between creating an issue "
-"and deploying the code to production. The data will be automatically added "
-"once you have completed the full idea to production cycle."
+msgid "The production stage shows the total time it takes between creating an issue and deploying the code to production. The data will be automatically added once you have completed the full idea to production cycle."
msgstr "生產階段概述了從創建議題到將代碼部署到生產環境的時間。當完æˆå®Œæ•´çš„想法到部署生產,數據將自動添加到此處。"
msgid "The project can be accessed by any logged in user."
@@ -877,36 +992,25 @@ msgstr "該項目å…許任何人訪å•ã€‚"
msgid "The repository for this project does not exist."
msgstr "此項目的存儲庫ä¸å­˜åœ¨ã€‚"
-msgid ""
-"The review stage shows the time from creating the merge request to merging "
-"it. The data will automatically be added after you merge your first merge "
-"request."
+msgid "The review stage shows the time from creating the merge request to merging it. The data will automatically be added after you merge your first merge request."
msgstr "評審階段概述了從創建åˆä½µè«‹æ±‚到åˆä½µçš„時間。當創建第壹個åˆä½µè«‹æ±‚後,數據將自動添加到此處。"
-msgid ""
-"The staging stage shows the time between merging the MR and deploying code "
-"to the production environment. The data will be automatically added once you "
-"deploy to production for the first time."
+msgid "The staging stage shows the time between merging the MR and deploying code to the production environment. The data will be automatically added once you deploy to production for the first time."
msgstr "é ç™¼å¸ƒéšŽæ®µæ¦‚述了åˆä½µè«‹æ±‚çš„åˆä½µåˆ°éƒ¨ç½²ä»£ç¢¼åˆ°ç”Ÿç”¢ç’°å¢ƒçš„總時間。當首次部署到生產環境後,數據將自動添加到此處。"
-msgid ""
-"The testing stage shows the time GitLab CI takes to run every pipeline for "
-"the related merge request. The data will automatically be added after your "
-"first pipeline finishes running."
+msgid "The testing stage shows the time GitLab CI takes to run every pipeline for the related merge request. The data will automatically be added after your first pipeline finishes running."
msgstr "測試階段概述了 GitLab CI 為相關åˆä½µè«‹æ±‚é‹è¡Œæ¯å€‹æµæ°´ç·šæ‰€éœ€çš„時間。當第壹個æµæ°´ç·šé‹è¡Œå®Œæˆå¾Œï¼Œæ•¸æ“šå°‡è‡ªå‹•æ·»åŠ åˆ°æ­¤è™•ã€‚"
msgid "The time taken by each data entry gathered by that stage."
msgstr "該階段æ¯æ¢æ•¸æ“šæ‰€èŠ±çš„時間"
-msgid ""
-"The value lying at the midpoint of a series of observed values. E.g., "
-"between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 ="
-" 6."
+msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
msgstr "中ä½æ•¸æ˜¯å£¹å€‹æ•¸åˆ—中最中間的值。例如在 3ã€5ã€9 之間,中ä½æ•¸æ˜¯ 5。在 3ã€5ã€7ã€8 之間,中ä½æ•¸æ˜¯ (5 + 7)/ 2 = 6。"
-msgid ""
-"This means you can not push code until you create an empty repository or "
-"import existing one."
+msgid "There are problems accessing Git storage: "
+msgstr ""
+
+msgid "This means you can not push code until you create an empty repository or import existing one."
msgstr "在創建壹個空的存儲庫或導入ç¾æœ‰å­˜å„²åº«ä¹‹å‰ï¼Œæ‚¨å°‡ç„¡æ³•æŽ¨é€ä»£ç¢¼ã€‚"
msgid "Time before an issue gets scheduled"
@@ -1073,6 +1177,9 @@ msgstr "上傳文件"
msgid "UploadLink|click to upload"
msgstr "點擊上傳"
+msgid "Use the following registration token during setup:"
+msgstr ""
+
msgid "Use your global notification setting"
msgstr "使用全局通知設置"
@@ -1106,14 +1213,10 @@ msgstr "å³å°‡åˆªé™¤ %{group_name}。已刪除的群組無法æ¢å¾©ï¼ç¢ºå®šç¹¼ç
msgid "You are going to remove %{project_name_with_namespace}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr "å³å°‡è¦åˆªé™¤ %{project_name_with_namespace}。已刪除的項目無法æ¢è¤‡ï¼ç¢ºå®šç¹¼çºŒå—Žï¼Ÿ"
-msgid ""
-"You are going to remove the fork relationship to source project "
-"%{forked_from_project}. Are you ABSOLUTELY sure?"
+msgid "You are going to remove the fork relationship to source project %{forked_from_project}. Are you ABSOLUTELY sure?"
msgstr "å³å°‡åˆªé™¤èˆ‡æºé …ç›® %{forked_from_project} 的派生關系。確定繼續嗎?"
-msgid ""
-"You are going to transfer %{project_name_with_namespace} to another owner. "
-"Are you ABSOLUTELY sure?"
+msgid "You are going to transfer %{project_name_with_namespace} to another owner. Are you ABSOLUTELY sure?"
msgstr "å³å°‡ %{project_name_with_namespace} 轉義給å¦å£¹å€‹æ‰€æœ‰è€…。確定繼續嗎?"
msgid "You can only add files when you are on a branch"
@@ -1134,26 +1237,19 @@ msgstr "ä¸æœƒæ”¶åˆ°ä»»ä½•é€šçŸ¥éƒµä»¶"
msgid "You will only receive notifications for the events you choose"
msgstr "åªæŽ¥æ”¶æ‚¨é¸æ“‡çš„事件通知"
-msgid ""
-"You will only receive notifications for threads you have participated in"
+msgid "You will only receive notifications for threads you have participated in"
msgstr "åªæŽ¥æ”¶æ‚¨åƒèˆ‡çš„主題的通知"
msgid "You will receive notifications for any activity"
msgstr "接收所有活動的通知"
-msgid ""
-"You will receive notifications only for comments in which you were "
-"@mentioned"
+msgid "You will receive notifications only for comments in which you were @mentioned"
msgstr "åªæŽ¥æ”¶è©•è«–中æåŠ(@)您的通知"
-msgid ""
-"You won't be able to pull or push project code via %{protocol} until you "
-"%{set_password_link} on your account"
+msgid "You won't be able to pull or push project code via %{protocol} until you %{set_password_link} on your account"
msgstr "在賬號上 %{set_password_link} 之å‰å°‡ç„¡æ³•é€šéŽ %{protocol} 拉å–或推é€ä»£ç¢¼ã€‚"
-msgid ""
-"You won't be able to pull or push project code via SSH until you "
-"%{add_ssh_key_link} to your profile"
+msgid "You won't be able to pull or push project code via SSH until you %{add_ssh_key_link} to your profile"
msgstr "在賬號中 %{add_ssh_key_link} 之å‰å°‡ç„¡æ³•é€šéŽ SSH 拉å–或推é€ä»£ç¢¼ã€‚"
msgid "Your name"
@@ -1171,4 +1267,4 @@ msgstr "通知郵件"
msgid "parent"
msgid_plural "parents"
-msgstr[0] "父級"
+msgstr[0] "父級" \ No newline at end of file
diff --git a/locale/zh_TW/gitlab.po b/locale/zh_TW/gitlab.po
index 205d4712316..91c1cc6bf66 100644
--- a/locale/zh_TW/gitlab.po
+++ b/locale/zh_TW/gitlab.po
@@ -1,39 +1,51 @@
-# Huang Tao <htve@outlook.com>, 2017. #zanata
-# 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"
+"Project-Id-Version: gitlab-ee\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2017-07-05 08:50-0500\n"
+"POT-Creation-Date: 2017-08-18 14:15+0530\n"
+"PO-Revision-Date: 2017-08-23 09:59-0400\n"
+"Last-Translator: gitlab <mbartlett+crowdin@gitlab.com>\n"
+"Language-Team: Chinese Traditional\n"
+"Language: zh_TW\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"Language-Team: Chinese (Taiwan) (https://translate.zanata.org/project/view/GitLab)\n"
-"PO-Revision-Date: 2017-08-07 03:30-0400\n"
-"Last-Translator: Huang Tao <htve@outlook.com>\n"
-"Language: zh-TW\n"
-"X-Generator: Zanata 3.9.6\n"
-"Plural-Forms: nplurals=1; plural=0\n"
-
-msgid "%s additional commit has been omitted to prevent performance issues."
-msgid_plural ""
-"%s additional commits have been omitted to prevent performance issues."
-msgstr[0] "因效能考é‡ï¼Œä¸é¡¯ç¤º %s 個更動 (commit)。"
+"Plural-Forms: nplurals=1; plural=0;\n"
+"X-Generator: crowdin.com\n"
+"X-Crowdin-Project: gitlab-ee\n"
+"X-Crowdin-Language: zh-TW\n"
+"X-Crowdin-File: /master/locale/gitlab.pot\n"
msgid "%d commit"
msgid_plural "%d commits"
msgstr[0] "%d 個更動 (commit)"
+msgid "%s additional commit has been omitted to prevent performance issues."
+msgid_plural "%s additional commits have been omitted to prevent performance issues."
+msgstr[0] "因效能考é‡ï¼Œä¸é¡¯ç¤º %s 個更動 (commit)。"
+
msgid "%{commit_author_link} committed %{commit_timeago}"
msgstr "%{commit_author_link} 在 %{commit_timeago} é€äº¤"
+msgid "%{number_of_failures} of %{maximum_failures} failures. GitLab will allow access on the next attempt."
+msgstr ""
+
+msgid "%{number_of_failures} of %{maximum_failures} failures. GitLab will block access for %{number_of_seconds} seconds."
+msgstr ""
+
+msgid "%{number_of_failures} of %{maximum_failures} failures. GitLab will not retry automatically. Reset storage information when the problem is resolved."
+msgstr ""
+
+msgid "%{storage_name}: failed storage access attempt on host:"
+msgid_plural "%{storage_name}: %{failed_attempts} failed storage access attempts:"
+msgstr[0] ""
+
+msgid "(checkout the %{link} for information on how to install it)."
+msgstr ""
+
msgid "1 pipeline"
msgid_plural "%d pipelines"
msgstr[0] "1 æ¢æµæ°´ç·š"
-msgstr[1] "%d æ¢æµæ°´ç·š"
msgid "A collection of graphs regarding Continuous Integration"
msgstr "æŒçºŒæ•´åˆ (CI) 相關的圖表"
@@ -41,6 +53,9 @@ msgstr "æŒçºŒæ•´åˆ (CI) 相關的圖表"
msgid "About auto deploy"
msgstr "關於自動部署"
+msgid "Access to failing storages has been temporarily disabled to allow the mount to recover. Reset storage information after the issue has been resolved to allow access again."
+msgstr ""
+
msgid "Active"
msgstr "啟用"
@@ -62,12 +77,27 @@ msgstr "請先新增 SSH 金鑰到您的個人帳號,æ‰èƒ½ä½¿ç”¨ SSH 來上å‚
msgid "Add new directory"
msgstr "新增目錄"
+msgid "All"
+msgstr ""
+
msgid "Archived project! Repository is read-only"
msgstr "此專案已å°å­˜ï¼æª”案庫 (repository) 為唯讀狀態"
msgid "Are you sure you want to delete this pipeline schedule?"
msgstr "確定è¦åˆªé™¤æ­¤æµæ°´ç·š (pipeline) 排程嗎?"
+msgid "Are you sure you want to discard your changes?"
+msgstr ""
+
+msgid "Are you sure you want to reset registration token?"
+msgstr ""
+
+msgid "Are you sure you want to reset the health check token?"
+msgstr ""
+
+msgid "Are you sure?"
+msgstr ""
+
msgid "Attach a file by drag &amp; drop or %{upload_link}"
msgstr "拖放檔案到此處或者 %{upload_link}"
@@ -75,13 +105,8 @@ msgid "Branch"
msgid_plural "Branches"
msgstr[0] "分支 (branch) "
-msgid ""
-"Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, "
-"choose a GitLab CI Yaml template and commit your changes. "
-"%{link_to_autodeploy_doc}"
-msgstr ""
-"已建立分支 (branch) <strong>%{branch_name}</strong> 。如è¦è¨­å®šè‡ªå‹•éƒ¨ç½²ï¼Œ è«‹é¸æ“‡åˆé©çš„ GitLab CI "
-"Yaml 模æ¿ï¼Œç„¶å¾Œè¨˜å¾—è¦é€äº¤ (commit) 您的編輯內容。%{link_to_autodeploy_doc}\n"
+msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
+msgstr "已建立分支 (branch) <strong>%{branch_name}</strong> 。如è¦è¨­å®šè‡ªå‹•éƒ¨ç½²ï¼Œ è«‹é¸æ“‡åˆé©çš„ GitLab CI Yaml 模æ¿ï¼Œç„¶å¾Œè¨˜å¾—è¦é€äº¤ (commit) 您的編輯內容。%{link_to_autodeploy_doc}\n"
msgid "BranchSwitcherPlaceholder|Search branches"
msgstr "æœå°‹åˆ†æ”¯ (branches)"
@@ -113,6 +138,9 @@ msgstr "CI 組態"
msgid "Cancel"
msgstr "å–消"
+msgid "Cancel edit"
+msgstr ""
+
msgid "ChangeTypeActionLabel|Pick into branch"
msgstr "挑é¸åˆ°åˆ†æ”¯ (branch) "
@@ -191,6 +219,9 @@ msgstr "已跳éŽ"
msgid "CiStatus|running"
msgstr "執行中"
+msgid "Comments"
+msgstr ""
+
msgid "Commit"
msgid_plural "Commits"
msgstr[0] "更動記錄 (commit) "
@@ -237,9 +268,10 @@ msgstr "複製更動記錄 (commit) 的 SHA 值到剪貼簿"
msgid "Create New Directory"
msgstr "建立新目錄"
-msgid ""
-"Create a personal access token on your account to pull or push via "
-"%{protocol}."
+msgid "Create a new branch"
+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"
@@ -272,19 +304,13 @@ msgstr "Cron 語法"
msgid "Custom notification events"
msgstr "自訂事件通知"
-msgid ""
-"Custom notification levels are the same as participating levels. With custom "
-"notification levels you will also receive notifications for select events. "
-"To find out more, check out %{notification_link}."
-msgstr ""
-"自訂通知層級相當於åƒèˆ‡åº¦è¨­å®šã€‚使用自訂通知層級,您å¯ä»¥åªæ”¶åˆ°ç‰¹å®šçš„事件通知。請åƒç…§ %{notification_link} 以ç²å¾—更多訊æ¯ã€‚"
+msgid "Custom notification levels are the same as participating levels. With custom notification levels you will also receive notifications for select events. To find out more, check out %{notification_link}."
+msgstr "自訂通知層級相當於åƒèˆ‡åº¦è¨­å®šã€‚使用自訂通知層級,您å¯ä»¥åªæ”¶åˆ°ç‰¹å®šçš„事件通知。請åƒç…§ %{notification_link} 以ç²å¾—更多訊æ¯ã€‚"
msgid "Cycle Analytics"
msgstr "週期分æž"
-msgid ""
-"Cycle Analytics gives an overview of how much time it takes to go from idea "
-"to production in your project."
+msgid "Cycle Analytics gives an overview of how much time it takes to go from idea to production in your project."
msgstr "週期分æžè®“您å¯ä»¥æœ‰æ•ˆçš„é‡æ¸…專案從發想到產å“推出所花的時間長短。"
msgid "CycleAnalyticsStage|Code"
@@ -321,9 +347,15 @@ msgstr[0] "部署"
msgid "Description"
msgstr "æè¿°"
+msgid "Details"
+msgstr ""
+
msgid "Directory name"
msgstr "目錄å稱"
+msgid "Discard changes"
+msgstr ""
+
msgid "Don't show again"
msgstr "ä¸å†é¡¯ç¤º"
@@ -360,6 +392,24 @@ msgstr "編輯"
msgid "Edit Pipeline Schedule %{id}"
msgstr "編輯 %{id} æµæ°´ç·š (pipeline) 排程"
+msgid "EventFilterBy|Filter by all"
+msgstr ""
+
+msgid "EventFilterBy|Filter by comments"
+msgstr ""
+
+msgid "EventFilterBy|Filter by issue events"
+msgstr ""
+
+msgid "EventFilterBy|Filter by merge events"
+msgstr ""
+
+msgid "EventFilterBy|Filter by push events"
+msgstr ""
+
+msgid "EventFilterBy|Filter by team"
+msgstr ""
+
msgid "Every day (at 4:00am)"
msgstr "æ¯æ—¥åŸ·è¡Œï¼ˆæ·©æ™¨å››é»žï¼‰"
@@ -406,12 +456,36 @@ msgstr "從議題 (issue) 建立直到部署至營é‹ç’°å¢ƒ"
msgid "From merge request merge until deploy to production"
msgstr "從請求被åˆä½µå¾Œ (merge request merged) 直到部署至營é‹ç’°å¢ƒ"
+msgid "Git storage health information has been reset"
+msgstr ""
+
+msgid "GitLab Runner section"
+msgstr ""
+
msgid "Go to your fork"
msgstr "å‰å¾€æ‚¨çš„分支 (fork) "
msgid "GoToYourFork|Fork"
msgstr "å‰å¾€æ‚¨çš„分支 (fork) "
+msgid "Health Check"
+msgstr ""
+
+msgid "Health information can be retrieved from the following endpoints. More information is available"
+msgstr ""
+
+msgid "HealthCheck|Access token is"
+msgstr ""
+
+msgid "HealthCheck|Healthy"
+msgstr ""
+
+msgid "HealthCheck|No Health Problems Detected"
+msgstr ""
+
+msgid "HealthCheck|Unhealthy"
+msgstr ""
+
msgid "Home"
msgstr "首é "
@@ -421,12 +495,18 @@ msgstr "已開始維護"
msgid "Import repository"
msgstr "匯入檔案庫 (repository)"
+msgid "Install a Runner compatible with GitLab CI"
+msgstr ""
+
msgid "Interval Pattern"
msgstr "循環週期"
msgid "Introducing Cycle Analytics"
msgstr "週期分æžç°¡ä»‹"
+msgid "Issue events"
+msgstr ""
+
msgid "Jobs for last month"
msgstr "上個月的任務 (job) "
@@ -455,6 +535,12 @@ msgstr "最後更新"
msgid "Last commit"
msgstr "最後更動記錄 (commit) "
+msgid "LastPushEvent|You pushed to"
+msgstr ""
+
+msgid "LastPushEvent|at"
+msgstr ""
+
msgid "Learn more in the"
msgstr "了解更多"
@@ -474,9 +560,15 @@ msgstr[0] "é™åˆ¶æœ€å¤šé¡¯ç¤º %d 個事件"
msgid "Median"
msgstr "中ä½æ•¸"
+msgid "Merge events"
+msgstr ""
+
msgid "MissingSSHKeyWarningLink|add an SSH key"
msgstr "新增 SSH 金鑰"
+msgid "More information is available|here"
+msgstr ""
+
msgid "New Issue"
msgid_plural "New Issues"
msgstr[0] "建立議題 (issue) "
@@ -673,6 +765,9 @@ msgstr "於階段"
msgid "Pipeline|with stages"
msgstr "於階段"
+msgid "Project"
+msgstr ""
+
msgid "Project '%{project_name}' queued for deletion."
msgstr "專案 '%{project_name}' 已加入刪除佇列。"
@@ -688,15 +783,16 @@ msgstr "專案 '%{project_name}' 將被刪除。"
msgid "Project access must be granted explicitly to each user."
msgstr "專案權é™å¿…須一一指派給æ¯å€‹ä½¿ç”¨è€…。"
+msgid "Project details"
+msgstr ""
+
msgid "Project export could not be deleted."
msgstr "匯出的專案無法被刪除。"
msgid "Project export has been deleted."
msgstr "匯出的專案已被刪除。"
-msgid ""
-"Project export link has expired. Please generate a new export from your "
-"project settings."
+msgid "Project export link has expired. Please generate a new export from your project settings."
msgstr "專案的匯出連çµå·²å¤±æ•ˆã€‚請到專案設定中產生新的連çµã€‚"
msgid "Project export started. A download link will be sent by email."
@@ -705,6 +801,9 @@ msgstr "專案導出已開始。完æˆå¾Œä¸‹è¼‰é€£çµæœƒé€åˆ°æ‚¨çš„信箱。"
msgid "Project home"
msgstr "專案首é "
+msgid "ProjectActivityRSS|Subscribe"
+msgstr ""
+
msgid "ProjectFeature|Disabled"
msgstr "åœç”¨"
@@ -726,6 +825,9 @@ msgstr "階段"
msgid "ProjectNetworkGraph|Graph"
msgstr "分支圖"
+msgid "Push events"
+msgstr ""
+
msgid "Read more"
msgstr "瞭解更多"
@@ -762,9 +864,21 @@ msgstr "ç¨å¾Œæ醒"
msgid "Remove project"
msgstr "刪除專案"
+msgid "Repository"
+msgstr ""
+
msgid "Request Access"
msgstr "申請權é™"
+msgid "Reset git storage health information"
+msgstr ""
+
+msgid "Reset health check access token"
+msgstr ""
+
+msgid "Reset runners registration token"
+msgstr ""
+
msgid "Revert this commit"
msgstr "還原此更動記錄 (commit)"
@@ -789,6 +903,9 @@ msgstr "é¸æ“‡ä¸‹è¼‰æ ¼å¼"
msgid "Select a timezone"
msgstr "é¸æ“‡æ™‚å€"
+msgid "Select existing branch"
+msgstr ""
+
msgid "Select target branch"
msgstr "é¸æ“‡ç›®æ¨™åˆ†æ”¯ (branch) "
@@ -814,12 +931,18 @@ msgstr[0] "顯示 %d 個事件"
msgid "Source code"
msgstr "原始碼"
+msgid "Specify the following URL during the Runner setup:"
+msgstr ""
+
msgid "StarProject|Star"
msgstr "收è—"
msgid "Start a %{new_merge_request} with these changes"
msgstr "以這些改動建立一個新的 %{new_merge_request} "
+msgid "Start the Runner!"
+msgstr ""
+
msgid "Switch branch/tag"
msgstr "切æ›åˆ†æ”¯ (branch) 或標籤"
@@ -833,12 +956,11 @@ msgstr "標籤"
msgid "Target Branch"
msgstr "目標分支 (branch) "
-msgid ""
-"The coding stage shows the time from the first commit to creating the merge "
-"request. The data will automatically be added here once you create your "
-"first merge request."
+msgid "Team"
msgstr ""
-"程å¼é–‹ç™¼éšŽæ®µé¡¯ç¤ºå¾žç¬¬ä¸€æ¬¡æ›´å‹•è¨˜éŒ„ (commit) 到建立åˆä½µè«‹æ±‚ (merge request) 的時間。建立第一個åˆä½µè«‹æ±‚後,資料將自動填入。"
+
+msgid "The coding stage shows the time from the first commit to creating the merge request. The data will automatically be added here once you create your first merge request."
+msgstr "程å¼é–‹ç™¼éšŽæ®µé¡¯ç¤ºå¾žç¬¬ä¸€æ¬¡æ›´å‹•è¨˜éŒ„ (commit) 到建立åˆä½µè«‹æ±‚ (merge request) 的時間。建立第一個åˆä½µè«‹æ±‚後,資料將自動填入。"
msgid "The collection of events added to the data gathered for that stage."
msgstr "該階段中的相關事件集åˆã€‚"
@@ -846,34 +968,19 @@ msgstr "該階段中的相關事件集åˆã€‚"
msgid "The fork relationship has been removed."
msgstr "åˆ†æ”¯èˆ‡ä¸»å¹¹é–“çš„é—œè¯ (fork relationship) 已被刪除。"
-msgid ""
-"The issue stage shows the time it takes from creating an issue to assigning "
-"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 ""
-"è­°é¡Œ (issue) éšŽæ®µé¡¯ç¤ºå¾žè­°é¡Œå»ºç«‹åˆ°è¨­å®šé‡Œç¨‹ç¢‘æ‰€èŠ±çš„æ™‚é–“ï¼Œæˆ–æ˜¯è­°é¡Œè¢«åˆ†é¡žåˆ°è­°é¡Œçœ‹æ¿ (issue board) "
-"中所花的時間。建立第一個議題後,資料將自動填入。"
+msgid "The issue stage shows the time it takes from creating an issue to assigning 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 "è­°é¡Œ (issue) éšŽæ®µé¡¯ç¤ºå¾žè­°é¡Œå»ºç«‹åˆ°è¨­å®šé‡Œç¨‹ç¢‘æ‰€èŠ±çš„æ™‚é–“ï¼Œæˆ–æ˜¯è­°é¡Œè¢«åˆ†é¡žåˆ°è­°é¡Œçœ‹æ¿ (issue board) 中所花的時間。建立第一個議題後,資料將自動填入。"
msgid "The phase of the development lifecycle."
msgstr "專案開發週期的å„個階段。"
-msgid ""
-"The pipelines schedule runs pipelines in the future, repeatedly, for "
-"specific branches or tags. Those scheduled pipelines will inherit limited "
-"project access based on their associated user."
-msgstr ""
-"在指定了特定分支 (branch) 或標籤後,此處的æµæ°´ç·š (pipeline) 排程會ä¸æ–·åœ°é‡è¤‡åŸ·è¡Œã€‚æµæ°´ç·šæŽ’程的存å–權é™èˆ‡å°ˆæ¡ˆæœ¬èº«ç›¸åŒã€‚"
+msgid "The pipelines schedule runs pipelines in the future, repeatedly, for specific branches or tags. Those scheduled pipelines will inherit limited project access based on their associated user."
+msgstr "在指定了特定分支 (branch) 或標籤後,此處的æµæ°´ç·š (pipeline) 排程會ä¸æ–·åœ°é‡è¤‡åŸ·è¡Œã€‚æµæ°´ç·šæŽ’程的存å–權é™èˆ‡å°ˆæ¡ˆæœ¬èº«ç›¸åŒã€‚"
-msgid ""
-"The planning stage shows the time from the previous step to pushing your "
-"first commit. This time will be added automatically once you push your first "
-"commit."
+msgid "The planning stage shows the time from the previous step to pushing your first commit. This time will be added automatically once you push your first commit."
msgstr "計劃階段顯示從更動記錄 (commit) 被排程至第一個推é€çš„時間。第一次推é€ä¹‹å¾Œï¼Œè³‡æ–™å°‡è‡ªå‹•å¡«å…¥ã€‚"
-msgid ""
-"The production stage shows the total time it takes between creating an issue "
-"and deploying the code to production. The data will be automatically added "
-"once you have completed the full idea to production cycle."
+msgid "The production stage shows the total time it takes between creating an issue and deploying the code to production. The data will be automatically added once you have completed the full idea to production cycle."
msgstr "營é‹éšŽæ®µé¡¯ç¤ºå¾žå»ºç«‹è­°é¡Œ (issue) 到部署程å¼ä¸Šç·šæ‰€èŠ±çš„時間。完æˆå¾žç™¼æƒ³åˆ°ä¸Šç·šçš„完整開發週期後,資料將自動填入。"
msgid "The project can be accessed by any logged in user."
@@ -885,39 +992,25 @@ msgstr "本專案å¯è®“任何人存å–"
msgid "The repository for this project does not exist."
msgstr "本專案沒有檔案庫 (repository) "
-msgid ""
-"The review stage shows the time from creating the merge request to merging "
-"it. The data will automatically be added after you merge your first merge "
-"request."
-msgstr ""
-"複閱階段顯示從åˆä½µè«‹æ±‚ (merge request) 建立後至被åˆä½µçš„時間。當建立第一個åˆä½µè«‹æ±‚ (merge request) 後,資料將自動填入。"
+msgid "The review stage shows the time from creating the merge request to merging it. The data will automatically be added after you merge your first merge request."
+msgstr "複閱階段顯示從åˆä½µè«‹æ±‚ (merge request) 建立後至被åˆä½µçš„時間。當建立第一個åˆä½µè«‹æ±‚ (merge request) 後,資料將自動填入。"
-msgid ""
-"The staging stage shows the time between merging the MR and deploying code "
-"to the production environment. The data will be automatically added once you "
-"deploy to production for the first time."
+msgid "The staging stage shows the time between merging the MR and deploying code to the production environment. The data will be automatically added once you deploy to production for the first time."
msgstr "試營é‹æ®µé¡¯ç¤ºå¾žåˆä½µè«‹æ±‚ (merge request) 被åˆä½µå¾Œè‡³éƒ¨ç½²ç‡Ÿé‹çš„時間。當第一次部署營é‹å¾Œï¼Œè³‡æ–™å°‡è‡ªå‹•å¡«å…¥"
-msgid ""
-"The testing stage shows the time GitLab CI takes to run every pipeline for "
-"the related merge request. The data will automatically be added after your "
-"first pipeline finishes running."
-msgstr ""
-"測試階段顯示相關åˆä½µè«‹æ±‚ (merge request) çš„æµæ°´ç·š (pipeline) 所花的時間。當第一個æµæ°´ç·š (pipeline) "
-"執行完畢後,資料將自動填入。"
+msgid "The testing stage shows the time GitLab CI takes to run every pipeline for the related merge request. The data will automatically be added after your first pipeline finishes running."
+msgstr "測試階段顯示相關åˆä½µè«‹æ±‚ (merge request) çš„æµæ°´ç·š (pipeline) 所花的時間。當第一個æµæ°´ç·š (pipeline) 執行完畢後,資料將自動填入。"
msgid "The time taken by each data entry gathered by that stage."
msgstr "該階段中æ¯ä¸€å€‹è³‡æ–™é …目所花的時間。"
-msgid ""
-"The value lying at the midpoint of a series of observed values. E.g., "
-"between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 ="
-" 6."
+msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
msgstr "中ä½æ•¸æ˜¯ä¸€å€‹æ•¸åˆ—中最中間的值。例如在 3ã€5ã€9 之間,中ä½æ•¸æ˜¯ 5。在 3ã€5ã€7ã€8 之間,中ä½æ•¸æ˜¯ (5 + 7)/ 2 = 6。"
-msgid ""
-"This means you can not push code until you create an empty repository or "
-"import existing one."
+msgid "There are problems accessing Git storage: "
+msgstr ""
+
+msgid "This means you can not push code until you create an empty repository or import existing one."
msgstr "這代表在您建立一個空的檔案庫 (repository) 或是匯入一個ç¾å­˜çš„檔案庫之å‰ï¼Œæ‚¨å°‡ç„¡æ³•ä¸Šå‚³æ›´æ–° (push) 。"
msgid "Time before an issue gets scheduled"
@@ -1084,6 +1177,9 @@ msgstr "上傳檔案"
msgid "UploadLink|click to upload"
msgstr "點擊上傳"
+msgid "Use the following registration token during setup:"
+msgstr ""
+
msgid "Use your global notification setting"
msgstr "使用全域通知設定"
@@ -1117,16 +1213,10 @@ msgstr "å³å°‡è¦åˆªé™¤ %{group_name}。被刪除的群組完全無法救回來å
msgid "You are going to remove %{project_name_with_namespace}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr "å³å°‡è¦åˆªé™¤ %{project_name_with_namespace}。被刪除的專案完全無法救回來喔ï¼çœŸçš„「100%確定ã€è¦é€™éº¼åšå—Žï¼Ÿ"
-msgid ""
-"You are going to remove the fork relationship to source project "
-"%{forked_from_project}. Are you ABSOLUTELY sure?"
-msgstr ""
-"å°‡è¦åˆªé™¤æœ¬åˆ†æ”¯å°ˆæ¡ˆèˆ‡ä¸»å¹¹çš„æ‰€æœ‰é—œè¯ (fork relationship) 。 %{forked_from_project} "
-"真的「100%確定ã€è¦é€™éº¼åšå—Žï¼Ÿ"
+msgid "You are going to remove the fork relationship to source project %{forked_from_project}. Are you ABSOLUTELY sure?"
+msgstr "å°‡è¦åˆªé™¤æœ¬åˆ†æ”¯å°ˆæ¡ˆèˆ‡ä¸»å¹¹çš„æ‰€æœ‰é—œè¯ (fork relationship) 。 %{forked_from_project} 真的「100%確定ã€è¦é€™éº¼åšå—Žï¼Ÿ"
-msgid ""
-"You are going to transfer %{project_name_with_namespace} to another owner. "
-"Are you ABSOLUTELY sure?"
+msgid "You are going to transfer %{project_name_with_namespace} to another owner. Are you ABSOLUTELY sure?"
msgstr "å°‡è¦æŠŠ %{project_name_with_namespace} 的所有權轉移給å¦ä¸€å€‹äººã€‚真的「100%確定ã€è¦é€™éº¼åšå—Žï¼Ÿ"
msgid "You can only add files when you are on a branch"
@@ -1147,27 +1237,19 @@ msgstr "ä¸æœƒæ”¶åˆ°ä»»ä½•é€šçŸ¥éƒµä»¶"
msgid "You will only receive notifications for the events you choose"
msgstr "åªæŽ¥æ”¶æ‚¨é¸æ“‡çš„事件通知"
-msgid ""
-"You will only receive notifications for threads you have participated in"
+msgid "You will only receive notifications for threads you have participated in"
msgstr "åªæŽ¥æ”¶åƒèˆ‡ä¸»é¡Œçš„通知"
msgid "You will receive notifications for any activity"
msgstr "接收所有活動的通知"
-msgid ""
-"You will receive notifications only for comments in which you were "
-"@mentioned"
+msgid "You will receive notifications only for comments in which you were @mentioned"
msgstr "åªæŽ¥æ”¶è©•è«–中æåŠ(@)您的通知"
-msgid ""
-"You won't be able to pull or push project code via %{protocol} until you "
-"%{set_password_link} on your account"
-msgstr ""
-"在帳號上 %{set_password_link} 之å‰ï¼Œ 將無法使用 %{protocol} 上傳 (push) 或下載 (pull) 程å¼ç¢¼ã€‚"
+msgid "You won't be able to pull or push project code via %{protocol} until you %{set_password_link} on your account"
+msgstr "在帳號上 %{set_password_link} 之å‰ï¼Œ 將無法使用 %{protocol} 上傳 (push) 或下載 (pull) 程å¼ç¢¼ã€‚"
-msgid ""
-"You won't be able to pull or push project code via SSH until you "
-"%{add_ssh_key_link} to your profile"
+msgid "You won't be able to pull or push project code via SSH until you %{add_ssh_key_link} to your profile"
msgstr "在個人帳號中 %{add_ssh_key_link} 之å‰ï¼Œ 將無法使用 SSH 上傳 (push) 或下載 (pull) 程å¼ç¢¼ã€‚"
msgid "Your name"
@@ -1185,4 +1267,4 @@ msgstr "通知信"
msgid "parent"
msgid_plural "parents"
-msgstr[0] "上層"
+msgstr[0] "上層" \ No newline at end of file
diff --git a/package.json b/package.json
index cbb9be3a27f..1725658729a 100644
--- a/package.json
+++ b/package.json
@@ -20,7 +20,7 @@
"babel-preset-latest": "^6.24.0",
"babel-preset-stage-2": "^6.22.0",
"bootstrap-sass": "^3.3.6",
- "compression-webpack-plugin": "^0.3.2",
+ "compression-webpack-plugin": "^1.0.0",
"copy-webpack-plugin": "^4.0.1",
"core-js": "^2.4.1",
"cropper": "^2.3.0",
@@ -63,7 +63,7 @@
"vue-loader": "^11.3.4",
"vue-resource": "^1.3.4",
"vue-template-compiler": "^2.2.6",
- "webpack": "^3.5.4",
+ "webpack": "^3.5.5",
"webpack-bundle-analyzer": "^2.8.2",
"webpack-stats-plugin": "^0.1.5"
},
diff --git a/public/404.html b/public/404.html
index 03e98e81862..4db72be6f8c 100644
--- a/public/404.html
+++ b/public/404.html
@@ -15,7 +15,7 @@
h1 {
font-size: 56px;
line-height: 100px;
- font-weight: normal;
+ font-weight: 400;
color: #456;
}
@@ -28,7 +28,7 @@
h3 {
color: #456;
font-size: 20px;
- font-weight: normal;
+ font-weight: 400;
line-height: 28px;
}
@@ -48,7 +48,7 @@
a {
line-height: 100px;
- font-weight: normal;
+ font-weight: 400;
color: #4A8BEE;
font-size: 18px;
text-decoration: none;
diff --git a/public/422.html b/public/422.html
index 49ebbe40f39..a67dcd02200 100644
--- a/public/422.html
+++ b/public/422.html
@@ -15,7 +15,7 @@
h1 {
font-size: 56px;
line-height: 100px;
- font-weight: normal;
+ font-weight: 400;
color: #456;
}
@@ -28,7 +28,7 @@
h3 {
color: #456;
font-size: 20px;
- font-weight: normal;
+ font-weight: 400;
line-height: 28px;
}
@@ -48,7 +48,7 @@
a {
line-height: 100px;
- font-weight: normal;
+ font-weight: 400;
color: #4A8BEE;
font-size: 18px;
text-decoration: none;
diff --git a/public/500.html b/public/500.html
index 516920f7471..7091d14dfc4 100644
--- a/public/500.html
+++ b/public/500.html
@@ -15,7 +15,7 @@
h1 {
font-size: 56px;
line-height: 100px;
- font-weight: normal;
+ font-weight: 400;
color: #456;
}
@@ -28,7 +28,7 @@
h3 {
color: #456;
font-size: 20px;
- font-weight: normal;
+ font-weight: 400;
line-height: 28px;
}
@@ -48,7 +48,7 @@
a {
line-height: 100px;
- font-weight: normal;
+ font-weight: 400;
color: #4A8BEE;
font-size: 18px;
text-decoration: none;
diff --git a/public/502.html b/public/502.html
index 189458c9816..82afd273248 100644
--- a/public/502.html
+++ b/public/502.html
@@ -15,7 +15,7 @@
h1 {
font-size: 56px;
line-height: 100px;
- font-weight: normal;
+ font-weight: 400;
color: #456;
}
@@ -28,7 +28,7 @@
h3 {
color: #456;
font-size: 20px;
- font-weight: normal;
+ font-weight: 400;
line-height: 28px;
}
@@ -48,7 +48,7 @@
a {
line-height: 100px;
- font-weight: normal;
+ font-weight: 400;
color: #4A8BEE;
font-size: 18px;
text-decoration: none;
diff --git a/public/503.html b/public/503.html
index b09b0e2a67e..f1486bc3e84 100644
--- a/public/503.html
+++ b/public/503.html
@@ -15,7 +15,7 @@
h1 {
font-size: 56px;
line-height: 100px;
- font-weight: normal;
+ font-weight: 400;
color: #456;
}
@@ -28,7 +28,7 @@
h3 {
color: #456;
font-size: 20px;
- font-weight: normal;
+ font-weight: 400;
line-height: 28px;
}
@@ -48,7 +48,7 @@
a {
line-height: 100px;
- font-weight: normal;
+ font-weight: 400;
color: #4A8BEE;
font-size: 18px;
text-decoration: none;
diff --git a/public/deploy.html b/public/deploy.html
index 49ec4ac5ce1..e463b62520c 100644
--- a/public/deploy.html
+++ b/public/deploy.html
@@ -20,7 +20,7 @@
h1 {
font-size: 56px;
line-height: 100px;
- font-weight: normal;
+ font-weight: 400;
color: #456;
}
@@ -33,7 +33,7 @@
h3 {
color: #456;
font-size: 20px;
- font-weight: normal;
+ font-weight: 400;
line-height: 28px;
}
@@ -66,4 +66,4 @@
<p>Please contact your GitLab administrator if this problem persists.</p>
</div>
</body>
-</html> \ No newline at end of file
+</html>
diff --git a/spec/controllers/autocomplete_controller_spec.rb b/spec/controllers/autocomplete_controller_spec.rb
index 2fbab1e4040..572b567cddf 100644
--- a/spec/controllers/autocomplete_controller_spec.rb
+++ b/spec/controllers/autocomplete_controller_spec.rb
@@ -339,4 +339,42 @@ describe AutocompleteController do
end
end
end
+
+ context 'GET award_emojis' do
+ let(:user2) { create(:user) }
+ let!(:award_emoji1) { create_list(:award_emoji, 2, user: user, name: 'thumbsup') }
+ let!(:award_emoji2) { create_list(:award_emoji, 1, user: user, name: 'thumbsdown') }
+ let!(:award_emoji3) { create_list(:award_emoji, 3, user: user, name: 'star') }
+ let!(:award_emoji4) { create_list(:award_emoji, 1, user: user, name: 'tea') }
+
+ context 'unauthorized user' do
+ it 'returns empty json' do
+ get :award_emojis
+
+ expect(json_response).to be_empty
+ end
+ end
+
+ context 'sign in as user without award emoji' do
+ it 'returns empty json' do
+ sign_in(user2)
+ get :award_emojis
+
+ expect(json_response).to be_empty
+ end
+ end
+
+ context 'sign in as user with award emoji' do
+ it 'returns json sorted by name count' do
+ sign_in(user)
+ get :award_emojis
+
+ expect(json_response.count).to eq 4
+ expect(json_response[0]).to match('name' => 'star')
+ expect(json_response[1]).to match('name' => 'thumbsup')
+ expect(json_response[2]).to match('name' => 'tea')
+ expect(json_response[3]).to match('name' => 'thumbsdown')
+ end
+ end
+ end
end
diff --git a/spec/controllers/projects/issues_controller_spec.rb b/spec/controllers/projects/issues_controller_spec.rb
index b571b11dcac..da8f9e8376e 100644
--- a/spec/controllers/projects/issues_controller_spec.rb
+++ b/spec/controllers/projects/issues_controller_spec.rb
@@ -268,7 +268,7 @@ describe Projects::IssuesController do
context 'when an issue is not identified as spam' do
before do
allow_any_instance_of(described_class).to receive(:verify_recaptcha).and_return(false)
- allow_any_instance_of(AkismetService).to receive(:is_spam?).and_return(false)
+ allow_any_instance_of(AkismetService).to receive(:spam?).and_return(false)
end
it 'normally updates the issue' do
@@ -278,7 +278,7 @@ describe Projects::IssuesController do
context 'when an issue is identified as spam' do
before do
- allow_any_instance_of(AkismetService).to receive(:is_spam?).and_return(true)
+ allow_any_instance_of(AkismetService).to receive(:spam?).and_return(true)
end
context 'when captcha is not verified' do
@@ -672,7 +672,7 @@ describe Projects::IssuesController do
context 'when an issue is not identified as spam' do
before do
allow_any_instance_of(described_class).to receive(:verify_recaptcha).and_return(false)
- allow_any_instance_of(AkismetService).to receive(:is_spam?).and_return(false)
+ allow_any_instance_of(AkismetService).to receive(:spam?).and_return(false)
end
it 'does not create an issue' do
@@ -682,7 +682,7 @@ describe Projects::IssuesController do
context 'when an issue is identified as spam' do
before do
- allow_any_instance_of(AkismetService).to receive(:is_spam?).and_return(true)
+ allow_any_instance_of(AkismetService).to receive(:spam?).and_return(true)
end
context 'when captcha is not verified' do
diff --git a/spec/controllers/projects/protected_tags_controller_spec.rb b/spec/controllers/projects/protected_tags_controller_spec.rb
index 64658988b3f..b6de90039f3 100644
--- a/spec/controllers/projects/protected_tags_controller_spec.rb
+++ b/spec/controllers/projects/protected_tags_controller_spec.rb
@@ -8,4 +8,21 @@ describe Projects::ProtectedTagsController do
get(:index, namespace_id: project.namespace.to_param, project_id: project)
end
end
+
+ describe "DELETE #destroy" do
+ let(:project) { create(:project, :repository) }
+ let(:protected_tag) { create(:protected_tag, :developers_can_create, project: project) }
+ let(:user) { create(:user) }
+
+ before do
+ project.add_master(user)
+ sign_in(user)
+ end
+
+ it "deletes the protected tag" do
+ delete(:destroy, namespace_id: project.namespace.to_param, project_id: project, id: protected_tag.id)
+
+ expect { ProtectedTag.find(protected_tag.id) }.to raise_error(ActiveRecord::RecordNotFound)
+ end
+ end
end
diff --git a/spec/controllers/projects/services_controller_spec.rb b/spec/controllers/projects/services_controller_spec.rb
index 4e9b0c09ff2..efba9cc7306 100644
--- a/spec/controllers/projects/services_controller_spec.rb
+++ b/spec/controllers/projects/services_controller_spec.rb
@@ -10,9 +10,6 @@ describe Projects::ServicesController do
before do
sign_in(user)
project.team << [user, :master]
-
- controller.instance_variable_set(:@project, project)
- controller.instance_variable_set(:@service, service)
end
describe '#test' do
@@ -20,7 +17,7 @@ describe Projects::ServicesController do
it 'renders 404' do
allow_any_instance_of(Service).to receive(:can_test?).and_return(false)
- put :test, namespace_id: project.namespace.id, project_id: project.id, id: service.id
+ put :test, namespace_id: project.namespace, project_id: project, id: service.to_param
expect(response).to have_http_status(404)
end
@@ -36,7 +33,7 @@ describe Projects::ServicesController do
it 'returns success' do
allow_any_instance_of(MicrosoftTeams::Notifier).to receive(:ping).and_return(true)
- put :test, namespace_id: project.namespace.id, project_id: project.id, id: service.id
+ put :test, namespace_id: project.namespace, project_id: project, id: service.to_param
expect(response.status).to eq(200)
end
@@ -45,7 +42,7 @@ describe Projects::ServicesController do
it 'returns success' do
expect(HipChat::Client).to receive(:new).with('hipchat_token_p', anything).and_return(hipchat_client)
- put :test, namespace_id: project.namespace.id, project_id: project.id, id: service.id, service: service_params
+ put :test, namespace_id: project.namespace, project_id: project, id: service.to_param, service: service_params
expect(response.status).to eq(200)
end
@@ -54,17 +51,42 @@ describe Projects::ServicesController do
it 'returns success' do
expect(HipChat::Client).to receive(:new).with('hipchat_token_p', anything).and_return(hipchat_client)
- put :test, namespace_id: project.namespace.id, project_id: project.id, id: service.id, service: service_params
+ put :test, namespace_id: project.namespace, project_id: project, id: service.to_param, service: service_params
expect(response.status).to eq(200)
end
+
+ context 'when service is configured for the first time' do
+ before do
+ allow_any_instance_of(ServiceHook).to receive(:execute).and_return(true)
+ end
+
+ it 'persist the object' do
+ do_put
+
+ expect(BuildkiteService.first).to be_present
+ end
+
+ it 'creates the ServiceHook object' do
+ do_put
+
+ expect(BuildkiteService.first.service_hook).to be_present
+ end
+
+ def do_put
+ put :test, namespace_id: project.namespace,
+ project_id: project,
+ id: 'buildkite',
+ service: { 'active' => '1', 'push_events' => '1', token: 'token', 'project_url' => 'http://test.com' }
+ end
+ end
end
context 'failure' do
it 'returns success status code and the error message' do
expect(HipChat::Client).to receive(:new).with('hipchat_token_p', anything).and_raise('Bad test')
- put :test, namespace_id: project.namespace.id, project_id: project.id, id: service.id, service: service_params
+ put :test, namespace_id: project.namespace, project_id: project, id: service.to_param, service: service_params
expect(response.status).to eq(200)
expect(JSON.parse(response.body))
@@ -77,7 +99,7 @@ describe Projects::ServicesController do
context 'when param `active` is set to true' do
it 'activates the service and redirects to integrations paths' do
put :update,
- namespace_id: project.namespace.id, project_id: project.id, id: service.id, service: { active: true }
+ namespace_id: project.namespace, project_id: project, id: service.to_param, service: { active: true }
expect(response).to redirect_to(project_settings_integrations_path(project))
expect(flash[:notice]).to eq 'HipChat activated.'
@@ -87,7 +109,7 @@ describe Projects::ServicesController do
context 'when param `active` is set to false' do
it 'does not activate the service but saves the settings' do
put :update,
- namespace_id: project.namespace.id, project_id: project.id, id: service.id, service: { active: false }
+ namespace_id: project.namespace, project_id: project, id: service.to_param, service: { active: false }
expect(flash[:notice]).to eq 'HipChat settings saved, but not activated.'
end
diff --git a/spec/controllers/projects/snippets_controller_spec.rb b/spec/controllers/projects/snippets_controller_spec.rb
index cc444f31797..3a1550aa730 100644
--- a/spec/controllers/projects/snippets_controller_spec.rb
+++ b/spec/controllers/projects/snippets_controller_spec.rb
@@ -98,7 +98,7 @@ describe Projects::SnippetsController do
context 'when the snippet is spam' do
before do
- allow_any_instance_of(AkismetService).to receive(:is_spam?).and_return(true)
+ allow_any_instance_of(AkismetService).to receive(:spam?).and_return(true)
end
context 'when the snippet is private' do
@@ -176,7 +176,7 @@ describe Projects::SnippetsController do
context 'when the snippet is spam' do
before do
- allow_any_instance_of(AkismetService).to receive(:is_spam?).and_return(true)
+ allow_any_instance_of(AkismetService).to receive(:spam?).and_return(true)
end
context 'when the snippet is private' do
diff --git a/spec/controllers/snippets_controller_spec.rb b/spec/controllers/snippets_controller_spec.rb
index 7c5d059760f..be273acb69b 100644
--- a/spec/controllers/snippets_controller_spec.rb
+++ b/spec/controllers/snippets_controller_spec.rb
@@ -217,7 +217,7 @@ describe SnippetsController do
context 'when the snippet is spam' do
before do
- allow_any_instance_of(AkismetService).to receive(:is_spam?).and_return(true)
+ allow_any_instance_of(AkismetService).to receive(:spam?).and_return(true)
end
context 'when the snippet is private' do
@@ -289,7 +289,7 @@ describe SnippetsController do
context 'when the snippet is spam' do
before do
- allow_any_instance_of(AkismetService).to receive(:is_spam?).and_return(true)
+ allow_any_instance_of(AkismetService).to receive(:spam?).and_return(true)
end
context 'when the snippet is private' do
diff --git a/spec/factories/ci/stages.rb b/spec/factories/ci/stages.rb
index d3c8bf9d54f..b2ded945738 100644
--- a/spec/factories/ci/stages.rb
+++ b/spec/factories/ci/stages.rb
@@ -15,4 +15,12 @@ FactoryGirl.define do
warnings: warnings)
end
end
+
+ factory :ci_stage_entity, class: Ci::Stage do
+ project factory: :project
+ pipeline factory: :ci_empty_pipeline
+
+ name 'test'
+ status 'pending'
+ end
end
diff --git a/spec/factories/ci/triggers.rb b/spec/factories/ci/triggers.rb
index 40c4663c6d8..3734c7040c0 100644
--- a/spec/factories/ci/triggers.rb
+++ b/spec/factories/ci/triggers.rb
@@ -1,5 +1,7 @@
FactoryGirl.define do
factory :ci_trigger_without_token, class: Ci::Trigger do
+ owner
+
factory :ci_trigger do
sequence(:token) { |n| "token#{n}" }
end
diff --git a/spec/factories/projects.rb b/spec/factories/projects.rb
index 4a2034b31b3..9ebda0ba03b 100644
--- a/spec/factories/projects.rb
+++ b/spec/factories/projects.rb
@@ -81,6 +81,10 @@ FactoryGirl.define do
archived true
end
+ trait :hashed do
+ storage_version Project::LATEST_STORAGE_VERSION
+ end
+
trait :access_requestable do
request_access_enabled true
end
diff --git a/spec/features/admin/admin_projects_spec.rb b/spec/features/admin/admin_projects_spec.rb
index 77710f80036..f4f2505d436 100644
--- a/spec/features/admin/admin_projects_spec.rb
+++ b/spec/features/admin/admin_projects_spec.rb
@@ -36,6 +36,14 @@ describe "Admin::Projects" do
expect(page).to have_content(archived_project.name)
expect(page).to have_xpath("//span[@class='label label-warning']", text: 'archived')
end
+
+ it 'renders only archived projects', js: true do
+ find(:css, '#sort-projects-dropdown').click
+ click_link 'Show archived projects only'
+
+ expect(page).to have_content(archived_project.name)
+ expect(page).not_to have_content(project.name)
+ end
end
describe "GET /admin/projects/:namespace_id/:id" do
diff --git a/spec/features/atom/users_spec.rb b/spec/features/atom/users_spec.rb
index 79069bbca8e..9ce687afb31 100644
--- a/spec/features/atom/users_spec.rb
+++ b/spec/features/atom/users_spec.rb
@@ -41,6 +41,8 @@ describe "User Feed" do
target_project: project,
description: "Here is the fix: ![an image](image.png)")
end
+ let(:push_event) { create(:push_event, project: project, author: user) }
+ let!(:push_event_payload) { create(:push_event_payload, event: push_event) }
before do
project.team << [user, :master]
@@ -70,6 +72,10 @@ describe "User Feed" do
it 'has XHTML summaries in merge request descriptions' do
expect(body).to match /Here is the fix: <a[^>]*><img[^>]*\/><\/a>/
end
+
+ it 'has push event commit ID' do
+ expect(body).to have_content(Commit.truncate_sha(push_event.commit_id))
+ end
end
end
diff --git a/spec/features/calendar_spec.rb b/spec/features/calendar_spec.rb
index 9a597a2d690..4fc6956d111 100644
--- a/spec/features/calendar_spec.rb
+++ b/spec/features/calendar_spec.rb
@@ -2,7 +2,7 @@ require 'spec_helper'
feature 'Contributions Calendar', :js do
let(:user) { create(:user) }
- let(:contributed_project) { create(:project, :public) }
+ let(:contributed_project) { create(:project, :public, :repository) }
let(:issue_note) { create(:note, project: contributed_project) }
# Ex/ Sunday Jan 1, 2016
diff --git a/spec/features/dashboard/activity_spec.rb b/spec/features/dashboard/activity_spec.rb
index 582868bac1e..bd115785646 100644
--- a/spec/features/dashboard/activity_spec.rb
+++ b/spec/features/dashboard/activity_spec.rb
@@ -17,7 +17,7 @@ feature 'Dashboard > Activity' do
end
context 'event filters', :js do
- let(:project) { create(:project) }
+ let(:project) { create(:project, :repository) }
let(:merge_request) do
create(:merge_request, author: user, source_project: project, target_project: project)
diff --git a/spec/features/dashboard/archived_projects_spec.rb b/spec/features/dashboard/archived_projects_spec.rb
index 814ec0e59c7..e8d699ff5e0 100644
--- a/spec/features/dashboard/archived_projects_spec.rb
+++ b/spec/features/dashboard/archived_projects_spec.rb
@@ -26,6 +26,13 @@ RSpec.describe 'Dashboard Archived Project' do
expect(page).to have_link(archived_project.name)
end
+ it 'renders only archived projects' do
+ click_link 'Show archived projects only'
+
+ expect(page).to have_content(archived_project.name)
+ expect(page).not_to have_content(project.name)
+ end
+
it 'searchs archived projects', :js do
click_button 'Last updated'
click_link 'Show archived projects'
diff --git a/spec/features/explore/new_menu_spec.rb b/spec/features/explore/new_menu_spec.rb
index 2cd06258e22..e1c74a24890 100644
--- a/spec/features/explore/new_menu_spec.rb
+++ b/spec/features/explore/new_menu_spec.rb
@@ -74,7 +74,7 @@ feature 'Top Plus Menu', :js do
expect(page).to have_content('Title')
end
- scenario 'Click on New subgroup shows new group page' do
+ scenario 'Click on New subgroup shows new group page', :nested_groups do
visit group_path(group)
click_topmenuitem("New subgroup")
diff --git a/spec/features/groups/merge_requests_spec.rb b/spec/features/groups/merge_requests_spec.rb
index c2241feb9f7..9ba9f5686f7 100644
--- a/spec/features/groups/merge_requests_spec.rb
+++ b/spec/features/groups/merge_requests_spec.rb
@@ -1,6 +1,8 @@
require 'spec_helper'
feature 'Group merge requests page' do
+ include FilteredSearchHelpers
+
let(:path) { merge_requests_group_path(group) }
let(:issuable) { create(:merge_request, source_project: project, target_project: project, title: 'this is my created issuable') }
@@ -33,4 +35,17 @@ feature 'Group merge requests page' do
expect(page.find('#state-all span.badge').text).to eq("1")
end
end
+
+ context 'group filtered search', :js do
+ let(:access_level) { ProjectFeature::ENABLED }
+ let(:user) { user_in_group }
+ let(:user2) { user_outside_group }
+
+ it 'filters by assignee only group users' do
+ filtered_search.set('assignee:')
+
+ expect(find('#js-dropdown-assignee .filter-dropdown')).to have_content(user.name)
+ expect(find('#js-dropdown-assignee .filter-dropdown')).not_to have_content(user2.name)
+ end
+ end
end
diff --git a/spec/features/groups_spec.rb b/spec/features/groups_spec.rb
index e59a484d992..20f9818b08b 100644
--- a/spec/features/groups_spec.rb
+++ b/spec/features/groups_spec.rb
@@ -104,18 +104,15 @@ feature 'Group' do
end
context 'as group owner' do
- let(:user) { create(:user) }
+ it 'creates a nested group' do
+ user = create(:user)
- before do
group.add_owner(user)
sign_out(:user)
sign_in(user)
visit subgroups_group_path(group)
click_link 'New Subgroup'
- end
-
- it 'creates a nested group' do
fill_in 'Group path', with: 'bar'
click_button 'Create group'
@@ -123,6 +120,16 @@ feature 'Group' do
expect(page).to have_content("Group 'bar' was successfully created.")
end
end
+
+ context 'when nested group feature is disabled' do
+ it 'renders 404' do
+ allow(Group).to receive(:supports_nested_groups?).and_return(false)
+
+ visit subgroups_group_path(group)
+
+ expect(page.status_code).to eq(404)
+ end
+ end
end
it 'checks permissions to avoid exposing groups by parent_id' do
diff --git a/spec/features/issues/filtered_search/dropdown_assignee_spec.rb b/spec/features/issues/filtered_search/dropdown_assignee_spec.rb
index 2cc027aac9e..1c4649d0ba9 100644
--- a/spec/features/issues/filtered_search/dropdown_assignee_spec.rb
+++ b/spec/features/issues/filtered_search/dropdown_assignee_spec.rb
@@ -204,6 +204,12 @@ describe 'Dropdown assignee', :js do
expect(page).to have_css(js_dropdown_assignee, visible: true)
end
+
+ it 'opens assignee dropdown with existing my-reaction' do
+ filtered_search.set('my-reaction:star assignee:')
+
+ expect(page).to have_css(js_dropdown_assignee, visible: true)
+ end
end
describe 'caching requests' do
diff --git a/spec/features/issues/filtered_search/dropdown_emoji_spec.rb b/spec/features/issues/filtered_search/dropdown_emoji_spec.rb
new file mode 100644
index 00000000000..44741bcc92d
--- /dev/null
+++ b/spec/features/issues/filtered_search/dropdown_emoji_spec.rb
@@ -0,0 +1,182 @@
+require 'rails_helper'
+
+describe 'Dropdown emoji', js: true do
+ include FilteredSearchHelpers
+
+ let!(:project) { create(:project, :public) }
+ let!(:user) { create(:user, name: 'administrator', username: 'root') }
+ let!(:issue) { create(:issue, project: project) }
+ let!(:award_emoji_star) { create(:award_emoji, name: 'star', user: user, awardable: issue) }
+ let(:filtered_search) { find('.filtered-search') }
+ let(:js_dropdown_emoji) { '#js-dropdown-my-reaction' }
+
+ def send_keys_to_filtered_search(input)
+ input.split("").each do |i|
+ filtered_search.send_keys(i)
+ end
+
+ sleep 0.5
+ wait_for_requests
+ end
+
+ def dropdown_emoji_size
+ page.all('#js-dropdown-my-reaction .filter-dropdown .filter-dropdown-item').size
+ end
+
+ def click_emoji(text)
+ find('#js-dropdown-my-reaction .filter-dropdown .filter-dropdown-item', text: text).click
+ end
+
+ before do
+ project.team << [user, :master]
+ create_list(:award_emoji, 2, user: user, name: 'thumbsup')
+ create_list(:award_emoji, 1, user: user, name: 'thumbsdown')
+ create_list(:award_emoji, 3, user: user, name: 'star')
+ create_list(:award_emoji, 1, user: user, name: 'tea')
+ end
+
+ context 'when user not logged in' do
+ before do
+ visit project_issues_path(project)
+ end
+
+ describe 'behavior' do
+ it 'does not open when the search bar has my-reaction:' do
+ filtered_search.set('my-reaction:')
+
+ expect(page).not_to have_css(js_dropdown_emoji)
+ end
+ end
+ end
+
+ context 'when user loggged in' do
+ before do
+ sign_in(user)
+
+ visit project_issues_path(project)
+ end
+
+ describe 'behavior' do
+ it 'opens when the search bar has my-reaction:' do
+ filtered_search.set('my-reaction:')
+
+ expect(page).to have_css(js_dropdown_emoji, visible: true)
+ end
+
+ it 'closes when the search bar is unfocused' do
+ find('body').click()
+
+ expect(page).to have_css(js_dropdown_emoji, visible: false)
+ end
+
+ it 'should show loading indicator when opened' do
+ filtered_search.set('my-reaction:')
+
+ expect(page).to have_css('#js-dropdown-my-reaction .filter-dropdown-loading', visible: true)
+ end
+
+ it 'should hide loading indicator when loaded' do
+ send_keys_to_filtered_search('my-reaction:')
+
+ expect(page).not_to have_css('#js-dropdown-my-reaction .filter-dropdown-loading')
+ end
+
+ it 'should load all the emojis when opened' do
+ send_keys_to_filtered_search('my-reaction:')
+
+ expect(dropdown_emoji_size).to eq(4)
+ end
+
+ it 'shows the most populated emoji at top of dropdown' do
+ send_keys_to_filtered_search('my-reaction:')
+
+ expect(first('#js-dropdown-my-reaction li')).to have_content(award_emoji_star.name)
+ end
+ end
+
+ describe 'filtering' do
+ before do
+ filtered_search.set('my-reaction')
+ send_keys_to_filtered_search(':')
+ end
+
+ it 'filters by name' do
+ send_keys_to_filtered_search('up')
+
+ expect(dropdown_emoji_size).to eq(1)
+ end
+
+ it 'filters by case insensitive name' do
+ send_keys_to_filtered_search('Up')
+
+ expect(dropdown_emoji_size).to eq(1)
+ end
+ end
+
+ describe 'selecting from dropdown' do
+ before do
+ filtered_search.set('my-reaction')
+ send_keys_to_filtered_search(':')
+ end
+
+ it 'fills in the my-reaction name' do
+ click_emoji('thumbsup')
+
+ wait_for_requests
+
+ expect(page).to have_css(js_dropdown_emoji, visible: false)
+ expect_tokens([emoji_token('thumbsup')])
+ expect_filtered_search_input_empty
+ end
+ end
+
+ describe 'input has existing content' do
+ it 'opens my-reaction dropdown with existing search term' do
+ filtered_search.set('searchTerm my-reaction:')
+
+ expect(page).to have_css(js_dropdown_emoji, visible: true)
+ end
+
+ it 'opens my-reaction dropdown with existing assignee' do
+ filtered_search.set('assignee:@user my-reaction:')
+
+ expect(page).to have_css(js_dropdown_emoji, visible: true)
+ end
+
+ it 'opens my-reaction dropdown with existing label' do
+ filtered_search.set('label:~bug my-reaction:')
+
+ expect(page).to have_css(js_dropdown_emoji, visible: true)
+ end
+
+ it 'opens my-reaction dropdown with existing milestone' do
+ filtered_search.set('milestone:%v1.0 my-reaction:')
+
+ expect(page).to have_css(js_dropdown_emoji, visible: true)
+ end
+
+ it 'opens my-reaction dropdown with existing my-reaction' do
+ filtered_search.set('my-reaction:star my-reaction:')
+
+ expect(page).to have_css(js_dropdown_emoji, visible: true)
+ end
+ end
+
+ describe 'caching requests' do
+ it 'caches requests after the first load' do
+ filtered_search.set('my-reaction')
+ send_keys_to_filtered_search(':')
+ initial_size = dropdown_emoji_size
+
+ expect(initial_size).to be > 0
+
+ create_list(:award_emoji, 1, user: user, name: 'smile')
+ find('.filtered-search-box .clear-search').click
+ filtered_search.set('my-reaction')
+ send_keys_to_filtered_search(':')
+
+ expect(dropdown_emoji_size).to eq(initial_size)
+ end
+ end
+ end
+end
diff --git a/spec/features/issues/filtered_search/dropdown_hint_spec.rb b/spec/features/issues/filtered_search/dropdown_hint_spec.rb
index 04d6dea4b8c..0183495a1db 100644
--- a/spec/features/issues/filtered_search/dropdown_hint_spec.rb
+++ b/spec/features/issues/filtered_search/dropdown_hint_spec.rb
@@ -3,7 +3,7 @@ require 'rails_helper'
describe 'Dropdown hint', :js do
include FilteredSearchHelpers
- let!(:project) { create(:project) }
+ let!(:project) { create(:project, :public) }
let!(:user) { create(:user) }
let(:filtered_search) { find('.filtered-search') }
let(:js_dropdown_hint) { '#js-dropdown-hint' }
@@ -14,165 +14,209 @@ describe 'Dropdown hint', :js do
before do
project.team << [user, :master]
- sign_in(user)
create(:issue, project: project)
-
- visit project_issues_path(project)
end
- describe 'behavior' do
+ context 'when user not logged in' do
before do
- expect(page).to have_css(js_dropdown_hint, visible: false)
- filtered_search.click
+ visit project_issues_path(project)
end
- it 'opens when the search bar is first focused' do
- expect(page).to have_css(js_dropdown_hint, visible: true)
- end
-
- it 'closes when the search bar is unfocused' do
- find('body').click
-
+ it 'does not exist my-reaction dropdown item' do
expect(page).to have_css(js_dropdown_hint, visible: false)
+ expect(page).not_to have_content('my-reaction')
end
end
- describe 'filtering' do
- it 'does not filter `Press Enter or click to search`' do
- filtered_search.set('randomtext')
-
- hint_dropdown = find(js_dropdown_hint)
+ context 'when user logged in' do
+ before do
+ sign_in(user)
- expect(hint_dropdown).to have_content('Press Enter or click to search')
- expect(hint_dropdown).to have_selector('.filter-dropdown .filter-dropdown-item', count: 0)
+ visit project_issues_path(project)
end
- it 'filters with text' do
- filtered_search.set('a')
+ describe 'behavior' do
+ before do
+ expect(page).to have_css(js_dropdown_hint, visible: false)
+ filtered_search.click
+ end
- expect(find(js_dropdown_hint)).to have_selector('.filter-dropdown .filter-dropdown-item', count: 3)
- end
- end
+ it 'opens when the search bar is first focused' do
+ expect(page).to have_css(js_dropdown_hint, visible: true)
+ end
- describe 'selecting from dropdown with no input' do
- before do
- filtered_search.click
- end
+ it 'closes when the search bar is unfocused' do
+ find('body').click
- it 'opens the author dropdown when you click on author' do
- click_hint('author')
-
- expect(page).to have_css(js_dropdown_hint, visible: false)
- expect(page).to have_css('#js-dropdown-author', visible: true)
- expect_tokens([{ name: 'author' }])
- expect_filtered_search_input_empty
+ expect(page).to have_css(js_dropdown_hint, visible: false)
+ end
end
- it 'opens the assignee dropdown when you click on assignee' do
- click_hint('assignee')
+ describe 'filtering' do
+ it 'does not filter `Press Enter or click to search`' do
+ filtered_search.set('randomtext')
- expect(page).to have_css(js_dropdown_hint, visible: false)
- expect(page).to have_css('#js-dropdown-assignee', visible: true)
- expect_tokens([{ name: 'assignee' }])
- expect_filtered_search_input_empty
- end
+ hint_dropdown = find(js_dropdown_hint)
- it 'opens the milestone dropdown when you click on milestone' do
- click_hint('milestone')
+ expect(hint_dropdown).to have_content('Press Enter or click to search')
+ expect(hint_dropdown).to have_selector('.filter-dropdown .filter-dropdown-item', count: 0)
+ end
- expect(page).to have_css(js_dropdown_hint, visible: false)
- expect(page).to have_css('#js-dropdown-milestone', visible: true)
- expect_tokens([{ name: 'milestone' }])
- expect_filtered_search_input_empty
- end
+ it 'filters with text' do
+ filtered_search.set('a')
- it 'opens the label dropdown when you click on label' do
- click_hint('label')
-
- expect(page).to have_css(js_dropdown_hint, visible: false)
- expect(page).to have_css('#js-dropdown-label', visible: true)
- expect_tokens([{ name: 'label' }])
- expect_filtered_search_input_empty
+ expect(find(js_dropdown_hint)).to have_selector('.filter-dropdown .filter-dropdown-item', count: 4)
+ end
end
- end
-
- describe 'selecting from dropdown with some input' do
- it 'opens the author dropdown when you click on author' do
- filtered_search.set('auth')
- click_hint('author')
- expect(page).to have_css(js_dropdown_hint, visible: false)
- expect(page).to have_css('#js-dropdown-author', visible: true)
- expect_tokens([{ name: 'author' }])
- expect_filtered_search_input_empty
- end
+ describe 'selecting from dropdown with no input' do
+ before do
+ filtered_search.click
+ end
- it 'opens the assignee dropdown when you click on assignee' do
- filtered_search.set('assign')
- click_hint('assignee')
+ it 'opens the author dropdown when you click on author' do
+ click_hint('author')
- expect(page).to have_css(js_dropdown_hint, visible: false)
- expect(page).to have_css('#js-dropdown-assignee', visible: true)
- expect_tokens([{ name: 'assignee' }])
- expect_filtered_search_input_empty
- end
+ expect(page).to have_css(js_dropdown_hint, visible: false)
+ expect(page).to have_css('#js-dropdown-author', visible: true)
+ expect_tokens([{ name: 'author' }])
+ expect_filtered_search_input_empty
+ end
- it 'opens the milestone dropdown when you click on milestone' do
- filtered_search.set('mile')
- click_hint('milestone')
+ it 'opens the assignee dropdown when you click on assignee' do
+ click_hint('assignee')
- expect(page).to have_css(js_dropdown_hint, visible: false)
- expect(page).to have_css('#js-dropdown-milestone', visible: true)
- expect_tokens([{ name: 'milestone' }])
- expect_filtered_search_input_empty
- end
+ expect(page).to have_css(js_dropdown_hint, visible: false)
+ expect(page).to have_css('#js-dropdown-assignee', visible: true)
+ expect_tokens([{ name: 'assignee' }])
+ expect_filtered_search_input_empty
+ end
- it 'opens the label dropdown when you click on label' do
- filtered_search.set('lab')
- click_hint('label')
+ it 'opens the milestone dropdown when you click on milestone' do
+ click_hint('milestone')
- expect(page).to have_css(js_dropdown_hint, visible: false)
- expect(page).to have_css('#js-dropdown-label', visible: true)
- expect_tokens([{ name: 'label' }])
- expect_filtered_search_input_empty
- end
- end
+ expect(page).to have_css(js_dropdown_hint, visible: false)
+ expect(page).to have_css('#js-dropdown-milestone', visible: true)
+ expect_tokens([{ name: 'milestone' }])
+ expect_filtered_search_input_empty
+ end
- describe 'reselecting from dropdown' do
- it 'reuses existing author text' do
- filtered_search.send_keys('author:')
- filtered_search.send_keys(:backspace)
- click_hint('author')
+ it 'opens the label dropdown when you click on label' do
+ click_hint('label')
- expect_tokens([{ name: 'author' }])
- expect_filtered_search_input_empty
- end
+ expect(page).to have_css(js_dropdown_hint, visible: false)
+ expect(page).to have_css('#js-dropdown-label', visible: true)
+ expect_tokens([{ name: 'label' }])
+ expect_filtered_search_input_empty
+ end
- it 'reuses existing assignee text' do
- filtered_search.send_keys('assignee:')
- filtered_search.send_keys(:backspace)
- click_hint('assignee')
+ it 'opens the emoji dropdown when you click on my-reaction' do
+ click_hint('my-reaction')
- expect_tokens([{ name: 'assignee' }])
- expect_filtered_search_input_empty
+ expect(page).to have_css(js_dropdown_hint, visible: false)
+ expect(page).to have_css('#js-dropdown-my-reaction', visible: true)
+ expect_tokens([{ name: 'my-reaction' }])
+ expect_filtered_search_input_empty
+ end
end
- it 'reuses existing milestone text' do
- filtered_search.send_keys('milestone:')
- filtered_search.send_keys(:backspace)
- click_hint('milestone')
-
- expect_tokens([{ name: 'milestone' }])
- expect_filtered_search_input_empty
- end
+ describe 'selecting from dropdown with some input' do
+ it 'opens the author dropdown when you click on author' do
+ filtered_search.set('auth')
+ click_hint('author')
- it 'reuses existing label text' do
- filtered_search.send_keys('label:')
- filtered_search.send_keys(:backspace)
- click_hint('label')
+ expect(page).to have_css(js_dropdown_hint, visible: false)
+ expect(page).to have_css('#js-dropdown-author', visible: true)
+ expect_tokens([{ name: 'author' }])
+ expect_filtered_search_input_empty
+ end
- expect_tokens([{ name: 'label' }])
- expect_filtered_search_input_empty
+ it 'opens the assignee dropdown when you click on assignee' do
+ filtered_search.set('assign')
+ click_hint('assignee')
+
+ expect(page).to have_css(js_dropdown_hint, visible: false)
+ expect(page).to have_css('#js-dropdown-assignee', visible: true)
+ expect_tokens([{ name: 'assignee' }])
+ expect_filtered_search_input_empty
+ end
+
+ it 'opens the milestone dropdown when you click on milestone' do
+ filtered_search.set('mile')
+ click_hint('milestone')
+
+ expect(page).to have_css(js_dropdown_hint, visible: false)
+ expect(page).to have_css('#js-dropdown-milestone', visible: true)
+ expect_tokens([{ name: 'milestone' }])
+ expect_filtered_search_input_empty
+ end
+
+ it 'opens the label dropdown when you click on label' do
+ filtered_search.set('lab')
+ click_hint('label')
+
+ expect(page).to have_css(js_dropdown_hint, visible: false)
+ expect(page).to have_css('#js-dropdown-label', visible: true)
+ expect_tokens([{ name: 'label' }])
+ expect_filtered_search_input_empty
+ end
+
+ it 'opens the emoji dropdown when you click on my-reaction' do
+ filtered_search.set('my')
+ click_hint('my-reaction')
+
+ expect(page).to have_css(js_dropdown_hint, visible: false)
+ expect(page).to have_css('#js-dropdown-my-reaction', visible: true)
+ expect_tokens([{ name: 'my-reaction' }])
+ expect_filtered_search_input_empty
+ end
+ end
+
+ describe 'reselecting from dropdown' do
+ it 'reuses existing author text' do
+ filtered_search.send_keys('author:')
+ filtered_search.send_keys(:backspace)
+ click_hint('author')
+
+ expect_tokens([{ name: 'author' }])
+ expect_filtered_search_input_empty
+ end
+
+ it 'reuses existing assignee text' do
+ filtered_search.send_keys('assignee:')
+ filtered_search.send_keys(:backspace)
+ click_hint('assignee')
+
+ expect_tokens([{ name: 'assignee' }])
+ expect_filtered_search_input_empty
+ end
+
+ it 'reuses existing milestone text' do
+ filtered_search.send_keys('milestone:')
+ filtered_search.send_keys(:backspace)
+ click_hint('milestone')
+
+ expect_tokens([{ name: 'milestone' }])
+ expect_filtered_search_input_empty
+ end
+
+ it 'reuses existing label text' do
+ filtered_search.send_keys('label:')
+ filtered_search.send_keys(:backspace)
+ click_hint('label')
+
+ expect_tokens([{ name: 'label' }])
+ expect_filtered_search_input_empty
+ end
+
+ it 'reuses existing emoji text' do
+ filtered_search.send_keys('my-reaction:')
+ filtered_search.send_keys(:backspace)
+ click_hint('my-reaction')
+
+ expect_tokens([{ name: 'my-reaction' }])
+ expect_filtered_search_input_empty
+ end
end
end
end
diff --git a/spec/features/issues/filtered_search/dropdown_label_spec.rb b/spec/features/issues/filtered_search/dropdown_label_spec.rb
index e84b07ec2ef..c46803112a9 100644
--- a/spec/features/issues/filtered_search/dropdown_label_spec.rb
+++ b/spec/features/issues/filtered_search/dropdown_label_spec.rb
@@ -270,6 +270,12 @@ describe 'Dropdown label', js: true do
expect(page).to have_css(js_dropdown_label)
end
+
+ it 'opens label dropdown with existing my-reaction' do
+ filtered_search.set('my-reaction:star label:')
+
+ expect(page).to have_css(js_dropdown_label)
+ end
end
describe 'caching requests' do
diff --git a/spec/features/issues/filtered_search/dropdown_milestone_spec.rb b/spec/features/issues/filtered_search/dropdown_milestone_spec.rb
index 5f99921ae2e..f6c2e952bea 100644
--- a/spec/features/issues/filtered_search/dropdown_milestone_spec.rb
+++ b/spec/features/issues/filtered_search/dropdown_milestone_spec.rb
@@ -242,6 +242,12 @@ describe 'Dropdown milestone', :js do
expect(page).to have_css(js_dropdown_milestone, visible: true)
end
+
+ it 'opens milestone dropdown with existing my-reaction' do
+ filtered_search.set('my-reaction:star milestone:')
+
+ expect(page).to have_css(js_dropdown_milestone, visible: true)
+ end
end
describe 'caching requests' do
diff --git a/spec/features/issues/filtered_search/filter_issues_spec.rb b/spec/features/issues/filtered_search/filter_issues_spec.rb
index 2070043d842..a64c1cf220b 100644
--- a/spec/features/issues/filtered_search/filter_issues_spec.rb
+++ b/spec/features/issues/filtered_search/filter_issues_spec.rb
@@ -103,14 +103,6 @@ describe 'Filter issues', js: true do
expect_issues_list_count(5)
expect_filtered_search_input_empty
end
-
- it 'filters issues by invalid author' do
- skip('to be tested, issue #26546')
- end
-
- it 'filters issues by multiple authors' do
- skip('to be tested, issue #26546')
- end
end
context 'author with other filters' do
@@ -165,10 +157,6 @@ describe 'Filter issues', js: true do
expect_filtered_search_input(search_term)
end
end
-
- it 'sorting' do
- skip('to be tested, issue #26546')
- end
end
describe 'filter issues by assignee' do
@@ -190,14 +178,6 @@ describe 'Filter issues', js: true do
expect_issues_list_count(8, 1)
expect_filtered_search_input_empty
end
-
- it 'filters issues by invalid assignee' do
- skip('to be tested, issue #26546')
- end
-
- it 'filters issues by multiple assignees' do
- skip('to be tested, issue #26546')
- end
end
context 'assignee with other filters' do
@@ -250,12 +230,6 @@ describe 'Filter issues', js: true do
expect_filtered_search_input(search_term)
end
end
-
- context 'sorting' do
- it 'sorts' do
- skip('to be tested, issue #26546')
- end
- end
end
describe 'filter issues by label' do
@@ -278,10 +252,6 @@ describe 'Filter issues', js: true do
expect_filtered_search_input_empty
end
- it 'filters issues by invalid label' do
- skip('to be tested, issue #26546')
- end
-
it 'filters issues by multiple labels' do
input_filtered_search("label:~#{bug_label.title} label:~#{caps_sensitive_label.title}")
@@ -493,12 +463,6 @@ describe 'Filter issues', js: true do
expect_filtered_search_input_empty
end
end
-
- context 'sorting' do
- it 'sorts' do
- skip('to be tested, issue #26546')
- end
- end
end
describe 'filter issues by milestone' do
@@ -535,14 +499,6 @@ describe 'Filter issues', js: true do
expect_filtered_search_input_empty
end
- it 'filters issues by invalid milestones' do
- skip('to be tested, issue #26546')
- end
-
- it 'filters issues by multiple milestones' do
- skip('to be tested, issue #26546')
- end
-
it 'filters issues by milestone containing special characters' do
special_milestone = create(:milestone, title: '!@\#{$%^&*()}', project: project)
create(:issue, title: "Issue with special character milestone", project: project, milestone: special_milestone)
@@ -618,12 +574,6 @@ describe 'Filter issues', js: true do
expect_filtered_search_input(search_term)
end
end
-
- context 'sorting' do
- it 'sorts' do
- skip('to be tested, issue #26546')
- end
- end
end
describe 'filter issues by text' do
diff --git a/spec/features/issues/filtered_search/search_bar_spec.rb b/spec/features/issues/filtered_search/search_bar_spec.rb
index a432d031337..d4dd570fb37 100644
--- a/spec/features/issues/filtered_search/search_bar_spec.rb
+++ b/spec/features/issues/filtered_search/search_bar_spec.rb
@@ -100,7 +100,7 @@ describe 'Search bar', js: true do
find('.filtered-search-box .clear-search').click
filtered_search.click
- expect(find('#js-dropdown-hint')).to have_selector('.filter-dropdown .filter-dropdown-item', count: 4)
+ expect(find('#js-dropdown-hint')).to have_selector('.filter-dropdown .filter-dropdown-item', count: 5)
expect(get_left_style(find('#js-dropdown-hint')['style'])).to eq(hint_offset)
end
end
diff --git a/spec/features/issues/issue_detail_spec.rb b/spec/features/issues/issue_detail_spec.rb
index 28b636f9359..c470cb7c716 100644
--- a/spec/features/issues/issue_detail_spec.rb
+++ b/spec/features/issues/issue_detail_spec.rb
@@ -40,4 +40,18 @@ feature 'Issue Detail', :js do
end
end
end
+
+ context 'when authored by a user who is later deleted' do
+ before do
+ issue.update_attribute(:author_id, nil)
+ sign_in(user)
+ visit project_issue_path(project, issue)
+ end
+
+ it 'shows the issue' do
+ page.within('.issuable-details') do
+ expect(find('h2')).to have_content(issue.title)
+ end
+ end
+ end
end
diff --git a/spec/features/merge_requests/merge_commit_message_toggle_spec.rb b/spec/features/merge_requests/merge_commit_message_toggle_spec.rb
index 429bc277d73..08a3bb84aac 100644
--- a/spec/features/merge_requests/merge_commit_message_toggle_spec.rb
+++ b/spec/features/merge_requests/merge_commit_message_toggle_spec.rb
@@ -19,7 +19,7 @@ feature 'Clicking toggle commit message link', js: true do
"Merge branch 'feature' into 'master'",
merge_request.title,
"Closes #{issue_1.to_reference} and #{issue_2.to_reference}",
- "See merge request #{merge_request.to_reference}"
+ "See merge request #{merge_request.to_reference(full: true)}"
].join("\n\n")
end
let(:message_with_description) do
@@ -27,7 +27,7 @@ feature 'Clicking toggle commit message link', js: true do
"Merge branch 'feature' into 'master'",
merge_request.title,
merge_request.description,
- "See merge request #{merge_request.to_reference}"
+ "See merge request #{merge_request.to_reference(full: true)}"
].join("\n\n")
end
diff --git a/spec/features/projects/commit/mini_pipeline_graph_spec.rb b/spec/features/projects/commit/mini_pipeline_graph_spec.rb
index 2ef74e8857c..807a2189cc4 100644
--- a/spec/features/projects/commit/mini_pipeline_graph_spec.rb
+++ b/spec/features/projects/commit/mini_pipeline_graph_spec.rb
@@ -1,13 +1,8 @@
require 'rails_helper'
feature 'Mini Pipeline Graph in Commit View', :js do
- let(:user) { create(:user) }
let(:project) { create(:project, :public, :repository) }
- before do
- sign_in(user)
- end
-
context 'when commit has pipelines' do
let(:pipeline) do
create(:ci_empty_pipeline,
@@ -15,21 +10,14 @@ feature 'Mini Pipeline Graph in Commit View', :js do
ref: project.default_branch,
sha: project.commit.sha)
end
+ let(:build) { create(:ci_build, pipeline: pipeline) }
- let(:build) do
- create(:ci_build, pipeline: pipeline)
- end
-
- before do
+ it 'displays a mini pipeline graph' do
build.run
visit project_commit_path(project, project.commit.id)
- end
- it 'should display a mini pipeline graph' do
expect(page).to have_selector('.mr-widget-pipeline-graph')
- end
- it 'should show the builds list when stage is clicked' do
first('.mini-pipeline-graph-dropdown-toggle').click
wait_for_requests
@@ -38,6 +26,8 @@ feature 'Mini Pipeline Graph in Commit View', :js do
expect(page).to have_selector('.ci-status-icon-running')
expect(page).to have_content(build.stage)
end
+
+ build.drop
end
end
diff --git a/spec/features/projects/files/find_files_spec.rb b/spec/features/projects/files/find_files_spec.rb
deleted file mode 100644
index 57d67b28920..00000000000
--- a/spec/features/projects/files/find_files_spec.rb
+++ /dev/null
@@ -1,23 +0,0 @@
-require 'spec_helper'
-
-feature 'Find files button in the tree header' do
- given(:user) { create(:user) }
- given(:project) { create(:project, :repository) }
-
- background do
- sign_in(user)
- project.team << [user, :developer]
- end
-
- scenario 'project main screen' do
- visit project_path(project)
-
- expect(page).to have_selector('.tree-controls .shortcuts-find-file')
- end
-
- scenario 'project tree screen' do
- visit project_tree_path(project, project.default_branch)
-
- expect(page).to have_selector('.tree-controls .shortcuts-find-file')
- end
-end
diff --git a/spec/features/projects/files/user_searches_for_files_spec.rb b/spec/features/projects/files/user_searches_for_files_spec.rb
new file mode 100644
index 00000000000..a105685bca7
--- /dev/null
+++ b/spec/features/projects/files/user_searches_for_files_spec.rb
@@ -0,0 +1,58 @@
+require 'spec_helper'
+
+describe 'User searches for files' do
+ let(:user) { create(:user) }
+ let(:project) { create(:project, :repository) }
+
+ before do
+ sign_in(user)
+ end
+
+ describe 'project main screen' do
+ context 'when project is empty' do
+ let(:empty_project) { create(:project) }
+
+ before do
+ empty_project.add_developer(user)
+ visit project_path(empty_project)
+ end
+
+ it 'does not show any result' do
+ fill_in('search', with: 'coffee')
+ click_button('Go')
+
+ expect(page).to have_content("We couldn't find any")
+ end
+ end
+
+ context 'when project is not empty' do
+ before do
+ project.add_developer(user)
+ visit project_path(project)
+ end
+
+ it 'shows "Find file" button' do
+ expect(page).to have_selector('.tree-controls .shortcuts-find-file')
+ end
+ end
+ end
+
+ describe 'project tree screen' do
+ before do
+ project.add_developer(user)
+ visit project_tree_path(project, project.default_branch)
+ end
+
+ it 'shows "Find file" button' do
+ expect(page).to have_selector('.tree-controls .shortcuts-find-file')
+ end
+
+ it 'shows found files' do
+ fill_in('search', with: 'coffee')
+ click_button('Go')
+
+ expect(page).to have_content('coffee')
+ expect(page).to have_content('CONTRIBUTING.md')
+ end
+ end
+end
diff --git a/spec/features/projects/import_export/import_file_spec.rb b/spec/features/projects/import_export/import_file_spec.rb
index 6a324d32ca7..2eb6fab129d 100644
--- a/spec/features/projects/import_export/import_file_spec.rb
+++ b/spec/features/projects/import_export/import_file_spec.rb
@@ -3,11 +3,13 @@ require 'spec_helper'
feature 'Import/Export - project import integration test', js: true do
include Select2Helper
+ let(:user) { create(:user) }
let(:file) { File.join(Rails.root, 'spec', 'features', 'projects', 'import_export', 'test_project_export.tar.gz') }
let(:export_path) { "#{Dir.tmpdir}/import_file_spec" }
background do
allow_any_instance_of(Gitlab::ImportExport).to receive(:storage_path).and_return(export_path)
+ gitlab_sign_in(user)
end
after do
@@ -18,57 +20,67 @@ feature 'Import/Export - project import integration test', js: true do
let(:user) { create(:admin) }
let!(:namespace) { create(:namespace, name: "asd", owner: user) }
- before do
- gitlab_sign_in(user)
- end
+ context 'prefilled the path' do
+ scenario 'user imports an exported project successfully' do
+ visit new_project_path
- scenario 'user imports an exported project successfully' do
- visit new_project_path
+ select2(namespace.id, from: '#project_namespace_id')
+ fill_in :project_path, with: 'test-project-path', visible: true
+ click_link 'GitLab export'
- select2(namespace.id, from: '#project_namespace_id')
- fill_in :project_path, with: 'test-project-path', visible: true
- click_link 'GitLab export'
+ expect(page).to have_content('Import an exported GitLab project')
+ expect(URI.parse(current_url).query).to eq("namespace_id=#{namespace.id}&path=test-project-path")
+ expect(Gitlab::ImportExport).to receive(:import_upload_path).with(filename: /\A\h{32}_test-project-path\z/).and_call_original
- expect(page).to have_content('Import an exported GitLab project')
- expect(URI.parse(current_url).query).to eq("namespace_id=#{namespace.id}&path=test-project-path")
- expect(Gitlab::ImportExport).to receive(:import_upload_path).with(filename: /\A\h{32}_test-project-path\z/).and_call_original
+ attach_file('file', file)
- attach_file('file', file)
+ expect { click_on 'Import project' }.to change { Project.count }.by(1)
- expect { click_on 'Import project' }.to change { Project.count }.from(0).to(1)
-
- project = Project.last
- expect(project).not_to be_nil
- expect(project.issues).not_to be_empty
- expect(project.merge_requests).not_to be_empty
- expect(project_hook_exists?(project)).to be true
- expect(wiki_exists?(project)).to be true
- expect(project.import_status).to eq('finished')
+ project = Project.last
+ expect(project).not_to be_nil
+ expect(project.issues).not_to be_empty
+ expect(project.merge_requests).not_to be_empty
+ expect(project_hook_exists?(project)).to be true
+ expect(wiki_exists?(project)).to be true
+ expect(project.import_status).to eq('finished')
+ end
end
- scenario 'invalid project' do
- project = create(:project, namespace: namespace)
+ context 'path is not prefilled' do
+ scenario 'user imports an exported project successfully' do
+ visit new_project_path
+ click_link 'GitLab export'
- visit new_project_path
+ fill_in :path, with: 'test-project-path', visible: true
+ attach_file('file', file)
- select2(namespace.id, from: '#project_namespace_id')
- fill_in :project_path, with: project.name, visible: true
- click_link 'GitLab export'
- attach_file('file', file)
- click_on 'Import project'
+ expect { click_on 'Import project' }.to change { Project.count }.by(1)
- page.within('.flash-container') do
- expect(page).to have_content('Project could not be imported')
+ project = Project.last
+ expect(project).not_to be_nil
+ expect(page).to have_content("Project 'test-project-path' is being imported")
end
end
end
- context 'when limited to the default user namespace' do
- let(:user) { create(:user) }
- before do
- gitlab_sign_in(user)
+ scenario 'invalid project' do
+ namespace = create(:namespace, name: "asd", owner: user)
+ project = create(:project, namespace: namespace)
+
+ visit new_project_path
+
+ select2(namespace.id, from: '#project_namespace_id')
+ fill_in :project_path, with: project.name, visible: true
+ click_link 'GitLab export'
+ attach_file('file', file)
+ click_on 'Import project'
+
+ page.within('.flash-container') do
+ expect(page).to have_content('Project could not be imported')
end
+ end
+ context 'when limited to the default user namespace' do
scenario 'passes correct namespace ID in the URL' do
visit new_project_path
@@ -87,6 +99,6 @@ feature 'Import/Export - project import integration test', js: true do
end
def project_hook_exists?(project)
- Gitlab::Git::Hook.new('post-receive', project).exists?
+ Gitlab::Git::Hook.new('post-receive', project.repository.raw_repository).exists?
end
end
diff --git a/spec/features/projects/user_creates_files_spec.rb b/spec/features/projects/user_creates_files_spec.rb
index 4b78cc4fc53..3d335687510 100644
--- a/spec/features/projects/user_creates_files_spec.rb
+++ b/spec/features/projects/user_creates_files_spec.rb
@@ -56,11 +56,10 @@ describe 'User creates files' do
find('.add-to-tree').click
click_link('New file')
+ expect(page).to have_selector('.file-editor')
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)
diff --git a/spec/features/projects/user_interacts_with_stars_spec.rb b/spec/features/projects/user_interacts_with_stars_spec.rb
new file mode 100644
index 00000000000..0ac3f8181fa
--- /dev/null
+++ b/spec/features/projects/user_interacts_with_stars_spec.rb
@@ -0,0 +1,38 @@
+require 'spec_helper'
+
+describe 'User interacts with project stars' do
+ let(:project) { create(:project, :public, :repository) }
+
+ context 'when user is signed in', js: true do
+ let(:user) { create(:user) }
+
+ before do
+ sign_in(user)
+ visit(project_path(project))
+ end
+
+ it 'toggles the star' do
+ find('.star-btn').click
+
+ expect(page).to have_css('.star-count', text: 1)
+
+ find('.star-btn').click
+
+ expect(page).to have_css('.star-count', text: 0)
+ end
+ end
+
+ context 'when user is not signed in' do
+ before do
+ visit(project_path(project))
+ end
+
+ it 'does not allow to star a project' do
+ expect(page).not_to have_content('.toggle-star')
+
+ find('.star-btn').click
+
+ expect(current_path).to eq(new_user_session_path)
+ end
+ end
+end
diff --git a/spec/features/runners_spec.rb b/spec/features/runners_spec.rb
index cac31c34ad1..785cfeb34bd 100644
--- a/spec/features/runners_spec.rb
+++ b/spec/features/runners_spec.rb
@@ -1,149 +1,135 @@
require 'spec_helper'
-describe "Runners" do
- let(:user) { create(:user) }
+feature 'Runners' do
+ given(:user) { create(:user) }
- before do
+ background do
sign_in(user)
end
- describe "specific runners" do
- before do
- @project = FactoryGirl.create :project, shared_runners_enabled: false
- @project.team << [user, :master]
+ context 'when a project has enabled shared_runners' do
+ given(:project) { create(:project) }
- @project2 = FactoryGirl.create :project
- @project2.team << [user, :master]
+ background do
+ project.add_master(user)
+ end
- @project3 = FactoryGirl.create :project
- @project3.team << [user, :developer]
+ context 'when a specific runner is activated on the project' do
+ given(:specific_runner) { create(:ci_runner, :specific) }
- @shared_runner = FactoryGirl.create :ci_runner, :shared
- @specific_runner = FactoryGirl.create :ci_runner
- @specific_runner2 = FactoryGirl.create :ci_runner
- @specific_runner3 = FactoryGirl.create :ci_runner
- @project.runners << @specific_runner
- @project2.runners << @specific_runner2
- @project3.runners << @specific_runner3
+ background do
+ project.runners << specific_runner
+ end
- visit runners_path(@project)
- end
+ scenario 'user sees the specific runner' do
+ visit runners_path(project)
- before do
- expect(page).not_to have_content(@specific_runner3.display_name)
- expect(page).not_to have_content(@specific_runner3.display_name)
- end
+ within '.activated-specific-runners' do
+ expect(page).to have_content(specific_runner.display_name)
+ end
- it "places runners in right places" do
- expect(page.find(".available-specific-runners")).to have_content(@specific_runner2.display_name)
- expect(page.find(".activated-specific-runners")).to have_content(@specific_runner.display_name)
- expect(page.find(".available-shared-runners")).to have_content(@shared_runner.display_name)
- end
+ click_on specific_runner.short_sha
- it "enables specific runner for project" do
- within ".available-specific-runners" do
- click_on "Enable for this project"
+ expect(page).to have_content(specific_runner.platform)
end
- expect(page.find(".activated-specific-runners")).to have_content(@specific_runner2.display_name)
- end
+ scenario 'user removes an activated specific runner if this is last project for that runners' do
+ visit runners_path(project)
- it "disables specific runner for project" do
- @project2.runners << @specific_runner
- visit runners_path(@project)
+ within '.activated-specific-runners' do
+ click_on 'Remove Runner'
+ end
- within ".activated-specific-runners" do
- click_on "Disable for this project"
+ expect(page).not_to have_content(specific_runner.display_name)
end
- expect(page.find(".available-specific-runners")).to have_content(@specific_runner.display_name)
- end
+ context 'when a runner has a tag' do
+ background do
+ specific_runner.update(tag_list: ['tag'])
+ end
- it "removes specific runner for project if this is last project for that runners" do
- within ".activated-specific-runners" do
- click_on "Remove Runner"
- end
+ scenario 'user edits runner not to run untagged jobs' do
+ visit runners_path(project)
- expect(Ci::Runner.exists?(id: @specific_runner)).to be_falsey
- end
- end
+ within '.activated-specific-runners' do
+ first('.edit-runner > a').click
+ end
- describe "shared runners" do
- before do
- @project = FactoryGirl.create :project, shared_runners_enabled: false
- @project.team << [user, :master]
- visit runners_path(@project)
- end
+ expect(page.find_field('runner[run_untagged]')).to be_checked
- it "enables shared runners" do
- click_on "Enable shared Runners"
- expect(@project.reload.shared_runners_enabled).to be_truthy
- end
- end
+ uncheck 'runner_run_untagged'
+ click_button 'Save changes'
- describe "shared runners description" do
- let(:shared_runners_text) { 'custom **shared** runners description' }
- let(:shared_runners_html) { 'custom shared runners description' }
+ expect(page).to have_content 'Can run untagged jobs No'
+ end
+ end
- before do
- stub_application_setting(shared_runners_text: shared_runners_text)
- project = FactoryGirl.create :project, shared_runners_enabled: false
- project.team << [user, :master]
- visit runners_path(project)
- end
+ context 'when a shared runner is activated on the project' do
+ given!(:shared_runner) { create(:ci_runner, :shared) }
- it "sees shared runners description" do
- expect(page.find(".shared-runners-description")).to have_content(shared_runners_html)
- end
- end
+ scenario 'user sees CI/CD setting page' do
+ visit runners_path(project)
- describe "show page" do
- before do
- @project = FactoryGirl.create :project
- @project.team << [user, :master]
- @specific_runner = FactoryGirl.create :ci_runner
- @project.runners << @specific_runner
+ expect(page.find('.available-shared-runners')).to have_content(shared_runner.display_name)
+ end
+ end
end
- it "shows runner information" do
- visit runners_path(@project)
- click_on @specific_runner.short_sha
- expect(page).to have_content(@specific_runner.platform)
- end
- end
+ context 'when a specific runner exists in another project' do
+ given(:another_project) { create(:project) }
+ given(:specific_runner) { create(:ci_runner, :specific) }
- feature 'configuring runners ability to picking untagged jobs' do
- given(:project) { create(:project) }
- given(:runner) { create(:ci_runner) }
+ background do
+ another_project.add_master(user)
+ another_project.runners << specific_runner
+ end
- background do
- project.team << [user, :master]
- project.runners << runner
- end
+ scenario 'user enables and disables a specific runner' do
+ visit runners_path(project)
+
+ within '.available-specific-runners' do
+ click_on 'Enable for this project'
+ end
- scenario 'user checks default configuration' do
- visit project_runner_path(project, runner)
+ expect(page.find('.activated-specific-runners')).to have_content(specific_runner.display_name)
- expect(page).to have_content 'Can run untagged jobs Yes'
+ within '.activated-specific-runners' do
+ click_on 'Disable for this project'
+ end
+
+ expect(page.find('.available-specific-runners')).to have_content(specific_runner.display_name)
+ end
end
- context 'when runner has tags' do
- before do
- runner.update_attribute(:tag_list, ['tag'])
+ context 'when application settings have shared_runners_text' do
+ given(:shared_runners_text) { 'custom **shared** runners description' }
+ given(:shared_runners_html) { 'custom shared runners description' }
+
+ background do
+ stub_application_setting(shared_runners_text: shared_runners_text)
end
- scenario 'user wants to prevent runner from running untagged job' do
+ scenario 'user sees shared runners description' do
visit runners_path(project)
- page.within('.activated-specific-runners') do
- first('small > a').click
- end
- uncheck 'runner_run_untagged'
- click_button 'Save changes'
-
- expect(page).to have_content 'Can run untagged jobs No'
- expect(runner.reload.run_untagged?).to eq false
+ expect(page.find('.shared-runners-description')).to have_content(shared_runners_html)
end
end
end
+
+ context 'when a project has disabled shared_runners' do
+ given(:project) { create(:project, shared_runners_enabled: false) }
+
+ background do
+ project.add_master(user)
+ end
+
+ scenario 'user enables shared runners' do
+ visit runners_path(project)
+
+ click_on 'Enable shared Runners'
+
+ expect(page.find('.shared-runners-description')).to have_content('Disable shared Runners')
+ end
+ end
end
diff --git a/spec/features/search_spec.rb b/spec/features/search_spec.rb
index 6742d77937f..31d509455ba 100644
--- a/spec/features/search_spec.rb
+++ b/spec/features/search_spec.rb
@@ -281,4 +281,30 @@ describe "Search" do
expect(page).to have_selector('.commit-row-description', count: 9)
end
end
+
+ context 'anonymous user' do
+ let(:project) { create(:project, :public) }
+
+ before do
+ sign_out(user)
+ end
+
+ it 'preserves the group being searched in' do
+ visit search_path(group_id: project.namespace.id)
+
+ fill_in 'search', with: 'foo'
+ click_button 'Search'
+
+ expect(find('#group_id').value).to eq(project.namespace.id.to_s)
+ end
+
+ it 'preserves the project being searched in' do
+ visit search_path(project_id: project.id)
+
+ fill_in 'search', with: 'foo'
+ click_button 'Search'
+
+ expect(find('#project_id').value).to eq(project.id.to_s)
+ end
+ end
end
diff --git a/spec/features/snippets/notes_on_personal_snippets_spec.rb b/spec/features/snippets/notes_on_personal_snippets_spec.rb
index c0c293dee78..bf79974b8c6 100644
--- a/spec/features/snippets/notes_on_personal_snippets_spec.rb
+++ b/spec/features/snippets/notes_on_personal_snippets_spec.rb
@@ -91,7 +91,7 @@ describe 'Comments on personal snippets', :js do
context 'when editing a note' do
it 'changes the text' do
- find('.js-note-edit').click
+ find('.js-note-edit').trigger('click')
page.within('.current-note-edit-form') do
fill_in 'note[note]', with: 'new content'
diff --git a/spec/features/tags/master_deletes_tag_spec.rb b/spec/features/tags/master_deletes_tag_spec.rb
index 4d6fc13557f..d6a6b8fc7d5 100644
--- a/spec/features/tags/master_deletes_tag_spec.rb
+++ b/spec/features/tags/master_deletes_tag_spec.rb
@@ -36,8 +36,8 @@ feature 'Master deletes tag' do
context 'when pre-receive hook fails', js: true do
before do
- allow_any_instance_of(GitHooksService).to receive(:execute)
- .and_raise(GitHooksService::PreReceiveError, 'Do not delete tags')
+ allow_any_instance_of(Gitlab::Git::HooksService).to receive(:execute)
+ .and_raise(Gitlab::Git::HooksService::PreReceiveError, 'Do not delete tags')
end
scenario 'shows the error message' do
diff --git a/spec/finders/admin/projects_finder_spec.rb b/spec/finders/admin/projects_finder_spec.rb
index 28e36330029..4b67203a0df 100644
--- a/spec/finders/admin/projects_finder_spec.rb
+++ b/spec/finders/admin/projects_finder_spec.rb
@@ -118,6 +118,12 @@ describe Admin::ProjectsFinder do
it { is_expected.to match_array([archived_project, shared_project, public_project, internal_project, private_project]) }
end
+
+ context 'archived=only' do
+ let(:params) { { archived: 'only' } }
+
+ it { is_expected.to eq([archived_project]) }
+ end
end
context 'filter by personal' do
diff --git a/spec/finders/issues_finder_spec.rb b/spec/finders/issues_finder_spec.rb
index 8769a52863c..0e80df94e18 100644
--- a/spec/finders/issues_finder_spec.rb
+++ b/spec/finders/issues_finder_spec.rb
@@ -10,6 +10,9 @@ describe IssuesFinder do
set(:issue1) { create(:issue, author: user, assignees: [user], project: project1, milestone: milestone, title: 'gitlab', created_at: 1.week.ago) }
set(:issue2) { create(:issue, author: user, assignees: [user], project: project2, description: 'gitlab') }
set(:issue3) { create(:issue, author: user2, assignees: [user2], project: project2, title: 'tanuki', description: 'tanuki', created_at: 1.week.from_now) }
+ set(:award_emoji1) { create(:award_emoji, name: 'thumbsup', user: user, awardable: issue1) }
+ set(:award_emoji2) { create(:award_emoji, name: 'thumbsup', user: user2, awardable: issue2) }
+ set(:award_emoji3) { create(:award_emoji, name: 'thumbsdown', user: user, awardable: issue3) }
describe '#execute' do
set(:closed_issue) { create(:issue, author: user2, assignees: [user2], project: project2, state: 'closed') }
@@ -26,6 +29,10 @@ describe IssuesFinder do
issue1
issue2
issue3
+
+ award_emoji1
+ award_emoji2
+ award_emoji3
end
context 'scope: all' do
@@ -250,6 +257,34 @@ describe IssuesFinder do
end
end
+ context 'filtering by reaction name' do
+ context 'user searches by "thumbsup" reaction' do
+ let(:params) { { my_reaction_emoji: 'thumbsup' } }
+
+ it 'returns issues that the user thumbsup to' do
+ expect(issues).to contain_exactly(issue1)
+ end
+ end
+
+ context 'user2 searches by "thumbsup" reaction' do
+ let(:search_user) { user2 }
+
+ let(:params) { { my_reaction_emoji: 'thumbsup' } }
+
+ it 'returns issues that the user2 thumbsup to' do
+ expect(issues).to contain_exactly(issue2)
+ end
+ end
+
+ context 'user searches by "thumbsdown" reaction' do
+ let(:params) { { my_reaction_emoji: 'thumbsdown' } }
+
+ it 'returns issues that the user thumbsdown to' do
+ expect(issues).to contain_exactly(issue3)
+ end
+ end
+ end
+
context 'when the user is unauthorized' do
let(:search_user) { nil }
diff --git a/spec/finders/projects_finder_spec.rb b/spec/finders/projects_finder_spec.rb
index a5de586e869..0dfe6ba9c32 100644
--- a/spec/finders/projects_finder_spec.rb
+++ b/spec/finders/projects_finder_spec.rb
@@ -123,6 +123,12 @@ describe ProjectsFinder do
it { is_expected.to match_array([public_project, internal_project, archived_project]) }
end
+ describe 'filter by archived only' do
+ let(:params) { { archived: 'only' } }
+
+ it { is_expected.to eq([archived_project]) }
+ end
+
describe 'filter by archived for backward compatibility' do
let(:params) { { archived: false } }
diff --git a/spec/fixtures/emails/ios_default.eml b/spec/fixtures/emails/ios_default.eml
index 8d4d58feb16..fa19475104a 100644
--- a/spec/fixtures/emails/ios_default.eml
+++ b/spec/fixtures/emails/ios_default.eml
@@ -76,7 +76,7 @@ Content-Transfer-Encoding: 7bit
<img src="https://meta-discourse.global.ssl.fastly.net/user_avatar/meta.discourse.org/techapj/45/3281.png" title="techAPJ" style="max-width:100%;" width="45" height="45">
</td>
<td>
- <a href="https://meta.discourse.org/users/techapj" target="_blank" style="text-decoration: none; font-weight: bold; color: #006699;; font-size:13px;font-family:'lucida grande',tahoma,verdana,arial,sans-serif;color:#3b5998;text-decoration:none;font-weight:bold">techAPJ</a><br>
+ <a href="https://meta.discourse.org/users/techapj" target="_blank" style="text-decoration: none; font-weight: 600; color: #006699;; font-size:13px;font-family:'lucida grande',tahoma,verdana,arial,sans-serif;color:#3b5998;text-decoration:none;font-weight:bold">techAPJ</a><br>
<span style="text-align:right;color:#999999;padding-right:5px;font-family:'lucida grande',tahoma,verdana,arial,sans-serif;font-size:11px">November 28</span>
</td>
</tr>
@@ -94,7 +94,7 @@ Content-Transfer-Encoding: 7bit
<div style="color:#666;">
- <p>To respond, reply to this email or visit <a href="https://meta.discourse.org/t/testing-default-email-replies/22638/3" style="text-decoration: none; font-weight: bold; color: #006699;; color:#666;">https://meta.discourse.org/t/testing-default-email-replies/22638/3</a> in your browser.</p>
+ <p>To respond, reply to this email or visit <a href="https://meta.discourse.org/t/testing-default-email-replies/22638/3" style="text-decoration: none; font-weight: 600; color: #006699;; color:#666;">https://meta.discourse.org/t/testing-default-email-replies/22638/3</a> in your browser.</p>
</div>
<hr style="background-color: #ddd; height: 1px; border: 1px;; background-color: #ddd; height: 1px; border: 1px;">
<h4>Previous Replies</h4>
@@ -106,7 +106,7 @@ Content-Transfer-Encoding: 7bit
<img src="https://meta-discourse.global.ssl.fastly.net/user_avatar/meta.discourse.org/codinghorror/45/5297.png" title="codinghorror" style="max-width:100%;" width="45" height="45">
</td>
<td>
- <a href="https://meta.discourse.org/users/codinghorror" target="_blank" style="text-decoration: none; font-weight: bold; color: #006699;; font-size:13px;font-family:'lucida grande',tahoma,verdana,arial,sans-serif;color:#3b5998;text-decoration:none;font-weight:bold">codinghorror</a><br>
+ <a href="https://meta.discourse.org/users/codinghorror" target="_blank" style="text-decoration: none; font-weight: 600; color: #006699;; font-size:13px;font-family:'lucida grande',tahoma,verdana,arial,sans-serif;color:#3b5998;text-decoration:none;font-weight:bold">codinghorror</a><br>
<span style="text-align:right;color:#999999;padding-right:5px;font-family:'lucida grande',tahoma,verdana,arial,sans-serif;font-size:11px">November 28</span>
</td>
</tr>
@@ -114,7 +114,7 @@ Content-Transfer-Encoding: 7bit
<td style="padding-top:5px;" colspan="2">
<p style="margin-top:0; border: 0;">We're testing the latest GitHub email processing library which we are integrating now.</p>
-<p style="margin-top:0; border: 0;"><a href="https://github.com/github/email_reply_parser" target="_blank" style="text-decoration: none; font-weight: bold; color: #006699;">https://github.com/github/email_reply_parser</a></p>
+<p style="margin-top:0; border: 0;"><a href="https://github.com/github/email_reply_parser" target="_blank" style="text-decoration: none; font-weight: 600; color: #006699;">https://github.com/github/email_reply_parser</a></p>
<p style="margin-top:0; border: 0;">Go ahead and reply to this topic and I'll reply from various email clients for testing.</p>
</td>
@@ -126,10 +126,10 @@ Content-Transfer-Encoding: 7bit
<hr style="background-color: #ddd; height: 1px; border: 1px;; background-color: #ddd; height: 1px; border: 1px;">
<div style="color:#666;">
-<p>To respond, reply to this email or visit <a href="https://meta.discourse.org/t/testing-default-email-replies/22638/3" style="text-decoration: none; font-weight: bold; color: #006699;; color:#666;">https://meta.discourse.org/t/testing-default-email-replies/22638/3</a> in your browser.</p>
+<p>To respond, reply to this email or visit <a href="https://meta.discourse.org/t/testing-default-email-replies/22638/3" style="text-decoration: none; font-weight: 600; color: #006699;; color:#666;">https://meta.discourse.org/t/testing-default-email-replies/22638/3</a> in your browser.</p>
</div>
<div style="color:#666;">
-<p>To unsubscribe from these emails, visit your <a href="https://meta.discourse.org/my/preferences" style="text-decoration: none; font-weight: bold; color: #006699;; color:#666;">user preferences</a>.</p>
+<p>To unsubscribe from these emails, visit your <a href="https://meta.discourse.org/my/preferences" style="text-decoration: none; font-weight: 600; color: #006699;; color:#666;">user preferences</a>.</p>
</div>
</div>
</div></blockquote></body></html>
diff --git a/spec/fixtures/emails/on_wrote.eml b/spec/fixtures/emails/on_wrote.eml
index feb59bd27bb..af6a4e50a49 100644
--- a/spec/fixtures/emails/on_wrote.eml
+++ b/spec/fixtures/emails/on_wrote.eml
@@ -53,7 +53,7 @@ y
> display: inline-block;
> font-family: FontAwesome;
> font-style: normal;
-> font-weight: normal;
+> font-weight: 400;
> line-height: 1;
> -webkit-font-smoothing: antialiased;
> -moz-osx-font-smoothing: grayscale;
@@ -227,7 +227,7 @@ ding:5px">.fa {
display: inline-block;
font-family: FontAwesome;
font-style: normal;
- font-weight: normal;
+ font-weight: 400;
line-height: 1;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
@@ -274,4 +274,4 @@ ight:bold;color:#006699" target=3D"_blank">user preferences</a>.</p>
</div>
</blockquote></div><br></div></div>
---001a11c34c389e728f0502aa26a0-- \ No newline at end of file
+--001a11c34c389e728f0502aa26a0--
diff --git a/spec/helpers/avatars_helper_spec.rb b/spec/helpers/avatars_helper_spec.rb
index d16fcf21e45..4632c679972 100644
--- a/spec/helpers/avatars_helper_spec.rb
+++ b/spec/helpers/avatars_helper_spec.rb
@@ -28,7 +28,7 @@ describe AvatarsHelper do
it 'displays user avatar' do
is_expected.to eq image_tag(
LazyImageTagHelper.placeholder_image,
- class: 'avatar has-tooltip s16 lazy',
+ class: 'avatar s16 has-tooltip lazy',
alt: "#{user.name}'s avatar",
title: user.name,
data: { container: 'body', src: avatar_icon(user, 16) }
@@ -41,7 +41,7 @@ describe AvatarsHelper do
it 'uses provided css_class' do
is_expected.to eq image_tag(
LazyImageTagHelper.placeholder_image,
- class: "avatar has-tooltip s16 #{options[:css_class]} lazy",
+ class: "avatar s16 #{options[:css_class]} has-tooltip lazy",
alt: "#{user.name}'s avatar",
title: user.name,
data: { container: 'body', src: avatar_icon(user, 16) }
@@ -55,7 +55,7 @@ describe AvatarsHelper do
it 'uses provided size' do
is_expected.to eq image_tag(
LazyImageTagHelper.placeholder_image,
- class: "avatar has-tooltip s#{options[:size]} lazy",
+ class: "avatar s#{options[:size]} has-tooltip lazy",
alt: "#{user.name}'s avatar",
title: user.name,
data: { container: 'body', src: avatar_icon(user, options[:size]) }
@@ -69,7 +69,7 @@ describe AvatarsHelper do
it 'uses provided url' do
is_expected.to eq image_tag(
LazyImageTagHelper.placeholder_image,
- class: 'avatar has-tooltip s16 lazy',
+ class: 'avatar s16 has-tooltip lazy',
alt: "#{user.name}'s avatar",
title: user.name,
data: { container: 'body', src: options[:url] }
@@ -77,6 +77,36 @@ describe AvatarsHelper do
end
end
+ context 'with has_tooltip parameter' do
+ context 'with has_tooltip set to true' do
+ let(:options) { { user: user, has_tooltip: true } }
+
+ it 'adds has-tooltip' do
+ is_expected.to eq image_tag(
+ LazyImageTagHelper.placeholder_image,
+ class: 'avatar s16 has-tooltip lazy',
+ alt: "#{user.name}'s avatar",
+ title: user.name,
+ data: { container: 'body', src: avatar_icon(user, 16) }
+ )
+ end
+ end
+
+ context 'with has_tooltip set to false' do
+ let(:options) { { user: user, has_tooltip: false } }
+
+ it 'does not add has-tooltip or data container' do
+ is_expected.to eq image_tag(
+ LazyImageTagHelper.placeholder_image,
+ class: 'avatar s16 lazy',
+ alt: "#{user.name}'s avatar",
+ title: user.name,
+ data: { src: avatar_icon(user, 16) }
+ )
+ end
+ end
+ end
+
context 'with user_name parameter' do
let(:options) { { user_name: 'Tinky Winky', user_email: 'no@f.un' } }
@@ -86,7 +116,7 @@ describe AvatarsHelper do
it 'prefers user parameter' do
is_expected.to eq image_tag(
LazyImageTagHelper.placeholder_image,
- class: 'avatar has-tooltip s16 lazy',
+ class: 'avatar s16 has-tooltip lazy',
alt: "#{user.name}'s avatar",
title: user.name,
data: { container: 'body', src: avatar_icon(user, 16) }
@@ -97,7 +127,7 @@ describe AvatarsHelper do
it 'uses user_name and user_email parameter if user is not present' do
is_expected.to eq image_tag(
LazyImageTagHelper.placeholder_image,
- class: 'avatar has-tooltip s16 lazy',
+ class: 'avatar s16 has-tooltip lazy',
alt: "#{options[:user_name]}'s avatar",
title: options[:user_name],
data: { container: 'body', src: avatar_icon(options[:user_email], 16) }
diff --git a/spec/helpers/button_helper_spec.rb b/spec/helpers/button_helper_spec.rb
index 250ba239033..4423560ecaa 100644
--- a/spec/helpers/button_helper_spec.rb
+++ b/spec/helpers/button_helper_spec.rb
@@ -62,4 +62,67 @@ describe ButtonHelper do
end
end
end
+
+ describe 'clipboard_button' do
+ let(:user) { create(:user) }
+ let(:project) { build_stubbed(:project) }
+
+ def element(data = {})
+ element = helper.clipboard_button(data)
+ Nokogiri::HTML::DocumentFragment.parse(element).first_element_child
+ end
+
+ before do
+ allow(helper).to receive(:current_user).and_return(user)
+ end
+
+ context 'with default options' do
+ context 'when no `text` attribute is not provided' do
+ it 'shows copy to clipboard button with default configuration and no text set to copy' do
+ expect(element.attr('class')).to eq('btn btn-clipboard btn-transparent')
+ expect(element.attr('type')).to eq('button')
+ expect(element.attr('aria-label')).to eq('Copy to clipboard')
+ expect(element.attr('data-toggle')).to eq('tooltip')
+ expect(element.attr('data-placement')).to eq('bottom')
+ expect(element.attr('data-container')).to eq('body')
+ expect(element.attr('data-clipboard-text')).to eq(nil)
+ expect(element.inner_text).to eq("")
+
+ expect(element).to have_selector('.fa.fa-clipboard')
+ end
+ end
+
+ context 'when `text` attribute is provided' do
+ it 'shows copy to clipboard button with provided `text` to copy' do
+ expect(element(text: 'Hello World!').attr('data-clipboard-text')).to eq('Hello World!')
+ end
+ end
+
+ context 'when `title` attribute is provided' do
+ it 'shows copy to clipboard button with provided `title` as tooltip' do
+ expect(element(title: 'Copy to my clipboard!').attr('aria-label')).to eq('Copy to my clipboard!')
+ end
+ end
+ end
+
+ context 'with `button_text` attribute provided' do
+ it 'shows copy to clipboard button with provided `button_text` as button label' do
+ expect(element(button_text: 'Copy text').inner_text).to eq('Copy text')
+ end
+ end
+
+ context 'with `hide_tooltip` attribute provided' do
+ it 'shows copy to clipboard button without tooltip support' do
+ expect(element(hide_tooltip: true).attr('data-placement')).to eq(nil)
+ expect(element(hide_tooltip: true).attr('data-toggle')).to eq(nil)
+ expect(element(hide_tooltip: true).attr('data-container')).to eq(nil)
+ end
+ end
+
+ context 'with `hide_button_icon` attribute provided' do
+ it 'shows copy to clipboard button without tooltip support' do
+ expect(element(hide_button_icon: true)).not_to have_selector('.fa.fa-clipboard')
+ end
+ end
+ end
end
diff --git a/spec/helpers/events_helper_spec.rb b/spec/helpers/events_helper_spec.rb
index aa138f25bd3..d5536fcb22b 100644
--- a/spec/helpers/events_helper_spec.rb
+++ b/spec/helpers/events_helper_spec.rb
@@ -62,6 +62,12 @@ describe EventsHelper do
expect(helper.event_note(input)).to eq(expected)
end
+ it 'preserves data-src for lazy images' do
+ input = "![ImageTest](/uploads/test.png)"
+ image_url = "data-src=\"/uploads/test.png\""
+ expect(helper.event_note(input)).to match(image_url)
+ end
+
context 'labels formatting' do
let(:input) { 'this should be ~label_1' }
@@ -100,5 +106,9 @@ describe EventsHelper do
it "handles empty strings" do
expect(helper.event_commit_title("")).to eq("")
end
+
+ it 'handles nil values' do
+ expect(helper.event_commit_title(nil)).to eq('')
+ end
end
end
diff --git a/spec/javascripts/api_spec.js b/spec/javascripts/api_spec.js
index 867322ce8ae..8c68ceff914 100644
--- a/spec/javascripts/api_spec.js
+++ b/spec/javascripts/api_spec.js
@@ -17,7 +17,7 @@ describe('Api', () => {
beforeEach(() => {
originalGon = window.gon;
- window.gon = dummyGon;
+ window.gon = Object.assign({}, dummyGon);
});
afterEach(() => {
@@ -98,10 +98,11 @@ describe('Api', () => {
});
describe('projects', () => {
- it('fetches projects', (done) => {
+ it('fetches projects with membership when logged in', (done) => {
const query = 'dummy query';
const options = { unused: 'option' };
const expectedUrl = `${dummyUrlRoot}/api/${dummyApiVersion}/projects.json?simple=true`;
+ window.gon.current_user_id = 1;
const expectedData = Object.assign({
search: query,
per_page: 20,
@@ -119,6 +120,27 @@ describe('Api', () => {
done();
});
});
+
+ it('fetches projects without membership when not logged in', (done) => {
+ const query = 'dummy query';
+ const options = { unused: 'option' };
+ const expectedUrl = `${dummyUrlRoot}/api/${dummyApiVersion}/projects.json?simple=true`;
+ const expectedData = Object.assign({
+ search: query,
+ per_page: 20,
+ }, options);
+ spyOn(jQuery, 'ajax').and.callFake((request) => {
+ expect(request.url).toEqual(expectedUrl);
+ expect(request.dataType).toEqual('json');
+ expect(request.data).toEqual(expectedData);
+ return sendDummyResponse();
+ });
+
+ Api.projects(query, options, (response) => {
+ expect(response).toBe(dummyResponse);
+ done();
+ });
+ });
});
describe('newLabel', () => {
diff --git a/spec/javascripts/boards/board_new_issue_spec.js b/spec/javascripts/boards/board_new_issue_spec.js
index c0a7323a505..eac2eecb6bc 100644
--- a/spec/javascripts/boards/board_new_issue_spec.js
+++ b/spec/javascripts/boards/board_new_issue_spec.js
@@ -30,6 +30,8 @@ describe('Issue boards new issue form', () => {
};
beforeEach((done) => {
+ setFixtures('<div class="test-container"></div>');
+
const BoardNewIssueComp = Vue.extend(boardNewIssue);
Vue.http.interceptors.push(boardsMockInterceptor);
@@ -46,15 +48,17 @@ describe('Issue boards new issue form', () => {
propsData: {
list,
},
- }).$mount();
+ }).$mount(document.querySelector('.test-container'));
Vue.nextTick()
.then(done)
.catch(done.fail);
});
+ afterEach(() => vm.$destroy());
+
it('calls submit if submit button is clicked', (done) => {
- spyOn(vm, 'submit');
+ spyOn(vm, 'submit').and.callFake(e => e.preventDefault());
vm.title = 'Testing Title';
Vue.nextTick()
diff --git a/spec/javascripts/boards/issue_card_spec.js b/spec/javascripts/boards/issue_card_spec.js
index 69cfcbbce5a..47aaa57e6b9 100644
--- a/spec/javascripts/boards/issue_card_spec.js
+++ b/spec/javascripts/boards/issue_card_spec.js
@@ -278,6 +278,25 @@ describe('Issue card component', () => {
nodes.includes(label1.color),
).toBe(true);
});
+
+ it('does not render label if label does not have an ID', (done) => {
+ component.issue.addLabel(new ListLabel({
+ title: 'closed',
+ }));
+
+ Vue.nextTick()
+ .then(() => {
+ expect(
+ component.$el.querySelectorAll('.label').length,
+ ).toBe(2);
+ expect(
+ component.$el.textContent,
+ ).not.toContain('closed');
+
+ done();
+ })
+ .catch(done.fail);
+ });
});
});
});
diff --git a/spec/javascripts/droplab/drop_down_spec.js b/spec/javascripts/droplab/drop_down_spec.js
index 2bbcebeeac0..1ef494a00b8 100644
--- a/spec/javascripts/droplab/drop_down_spec.js
+++ b/spec/javascripts/droplab/drop_down_spec.js
@@ -351,14 +351,17 @@ describe('DropDown', function () {
describe('render', function () {
beforeEach(function () {
- this.list = { querySelector: () => {} };
+ this.list = { querySelector: () => {}, dispatchEvent: () => {} };
this.dropdown = { renderChildren: () => {}, list: this.list };
this.renderableList = {};
this.data = [0, 1];
+ this.customEvent = {};
spyOn(this.dropdown, 'renderChildren').and.callFake(data => data);
spyOn(this.list, 'querySelector').and.returnValue(this.renderableList);
+ spyOn(this.list, 'dispatchEvent');
spyOn(this.data, 'map').and.callThrough();
+ spyOn(window, 'CustomEvent').and.returnValue(this.customEvent);
DropDown.prototype.render.call(this.dropdown, this.data);
});
@@ -375,6 +378,14 @@ describe('DropDown', function () {
expect(this.renderableList.innerHTML).toBe('01');
});
+ it('should call render.dl', function () {
+ expect(window.CustomEvent).toHaveBeenCalledWith('render.dl', jasmine.any(Object));
+ });
+
+ it('should call dispatchEvent with the customEvent', function () {
+ expect(this.list.dispatchEvent).toHaveBeenCalledWith(this.customEvent);
+ });
+
describe('if no data argument is passed', function () {
beforeEach(function () {
this.data.map.calls.reset();
@@ -394,7 +405,7 @@ describe('DropDown', function () {
describe('if no dynamic list is present', function () {
beforeEach(function () {
- this.list = { querySelector: () => {} };
+ this.list = { querySelector: () => {}, dispatchEvent: () => {} };
this.dropdown = { renderChildren: () => {}, list: this.list };
this.data = [0, 1];
diff --git a/spec/javascripts/fixtures/project_select_combo_button.html.haml b/spec/javascripts/fixtures/project_select_combo_button.html.haml
index 54bc1a59279..432cd5fcc74 100644
--- a/spec/javascripts/fixtures/project_select_combo_button.html.haml
+++ b/spec/javascripts/fixtures/project_select_combo_button.html.haml
@@ -1,6 +1,6 @@
.project-item-select-holder
%input.project-item-select{ data: { group_id: '12345' , relative_path: 'issues/new' } }
- %a.new-project-item-link{ data: { label: 'New issue' }, href: ''}
+ %a.new-project-item-link{ data: { label: 'New issue', type: 'issues' }, href: ''}
%i.fa.fa-spinner.spin
%a.new-project-item-select-button
%i.fa.fa-caret-down
diff --git a/spec/javascripts/helpers/vue_mount_component_helper.js b/spec/javascripts/helpers/vue_mount_component_helper.js
new file mode 100644
index 00000000000..d7a2e86771c
--- /dev/null
+++ b/spec/javascripts/helpers/vue_mount_component_helper.js
@@ -0,0 +1,4 @@
+export default (Component, props = {}) => new Component({
+ propsData: props,
+}).$mount();
+
diff --git a/spec/javascripts/lib/utils/text_utility_spec.js b/spec/javascripts/lib/utils/text_utility_spec.js
index ca1b1b7cc3c..f1a975ba962 100644
--- a/spec/javascripts/lib/utils/text_utility_spec.js
+++ b/spec/javascripts/lib/utils/text_utility_spec.js
@@ -52,6 +52,7 @@ describe('text_utility', () => {
beforeAll(() => {
textArea = document.createElement('textarea');
document.querySelector('body').appendChild(textArea);
+ textArea.focus();
});
afterAll(() => {
diff --git a/spec/javascripts/merge_request_tabs_spec.js b/spec/javascripts/merge_request_tabs_spec.js
index dc40244c20e..8830a2d29e5 100644
--- a/spec/javascripts/merge_request_tabs_spec.js
+++ b/spec/javascripts/merge_request_tabs_spec.js
@@ -295,6 +295,17 @@ import 'vendor/jquery.scrollTo';
this.class.loadDiff('/foo/bar/merge_requests/1/diffs');
});
+ it('triggers scroll event when diff already loaded', function () {
+ spyOn(document, 'dispatchEvent');
+
+ this.class.diffsLoaded = true;
+ this.class.loadDiff('/foo/bar/merge_requests/1/diffs');
+
+ expect(
+ document.dispatchEvent,
+ ).toHaveBeenCalledWith(new CustomEvent('scroll'));
+ });
+
describe('with inline diff', () => {
let noteId;
let noteLineNumId;
diff --git a/spec/javascripts/pipelines/navigation_tabs_spec.js b/spec/javascripts/pipelines/navigation_tabs_spec.js
new file mode 100644
index 00000000000..53a88e6322f
--- /dev/null
+++ b/spec/javascripts/pipelines/navigation_tabs_spec.js
@@ -0,0 +1,127 @@
+import Vue from 'vue';
+import navigationTabs from '~/pipelines/components/navigation_tabs.vue';
+import mountComponent from '../helpers/vue_mount_component_helper';
+
+describe('navigation tabs pipeline component', () => {
+ let vm;
+ let Component;
+ let data;
+
+ beforeEach(() => {
+ data = {
+ scope: 'all',
+ count: {
+ all: 16,
+ running: 1,
+ pending: 10,
+ finished: 0,
+ },
+ paths: {
+ allPath: '/gitlab-org/gitlab-ce/pipelines',
+ pendingPath: '/gitlab-org/gitlab-ce/pipelines?scope=pending',
+ finishedPath: '/gitlab-org/gitlab-ce/pipelines?scope=finished',
+ runningPath: '/gitlab-org/gitlab-ce/pipelines?scope=running',
+ branchesPath: '/gitlab-org/gitlab-ce/pipelines?scope=branches',
+ tagsPath: '/gitlab-org/gitlab-ce/pipelines?scope=tags',
+ },
+ };
+
+ Component = Vue.extend(navigationTabs);
+ });
+
+ afterEach(() => {
+ vm.$destroy();
+ });
+
+ it('should render tabs with correct paths', () => {
+ vm = mountComponent(Component, data);
+
+ // All
+ const allTab = vm.$el.querySelector('.js-pipelines-tab-all a');
+ expect(allTab.textContent.trim()).toContain('All');
+ expect(allTab.getAttribute('href')).toEqual(data.paths.allPath);
+
+ // Pending
+ const pendingTab = vm.$el.querySelector('.js-pipelines-tab-pending a');
+ expect(pendingTab.textContent.trim()).toContain('Pending');
+ expect(pendingTab.getAttribute('href')).toEqual(data.paths.pendingPath);
+
+ // Running
+ const runningTab = vm.$el.querySelector('.js-pipelines-tab-running a');
+ expect(runningTab.textContent.trim()).toContain('Running');
+ expect(runningTab.getAttribute('href')).toEqual(data.paths.runningPath);
+
+ // Finished
+ const finishedTab = vm.$el.querySelector('.js-pipelines-tab-finished a');
+ expect(finishedTab.textContent.trim()).toContain('Finished');
+ expect(finishedTab.getAttribute('href')).toEqual(data.paths.finishedPath);
+
+ // Branches
+ const branchesTab = vm.$el.querySelector('.js-pipelines-tab-branches a');
+ expect(branchesTab.textContent.trim()).toContain('Branches');
+
+ // Tags
+ const tagsTab = vm.$el.querySelector('.js-pipelines-tab-tags a');
+ expect(tagsTab.textContent.trim()).toContain('Tags');
+ });
+
+ describe('scope', () => {
+ it('should render scope provided as active tab', () => {
+ vm = mountComponent(Component, data);
+ expect(vm.$el.querySelector('.js-pipelines-tab-all').className).toContain('active');
+ });
+ });
+
+ describe('badges', () => {
+ it('should render provided number', () => {
+ vm = mountComponent(Component, data);
+ // All
+ expect(
+ vm.$el.querySelector('.js-totalbuilds-count').textContent.trim(),
+ ).toContain(data.count.all);
+
+ // Pending
+ expect(
+ vm.$el.querySelector('.js-pipelines-tab-pending .badge').textContent.trim(),
+ ).toContain(data.count.pending);
+
+ // Running
+ expect(
+ vm.$el.querySelector('.js-pipelines-tab-running .badge').textContent.trim(),
+ ).toContain(data.count.running);
+
+ // Finished
+ expect(
+ vm.$el.querySelector('.js-pipelines-tab-finished .badge').textContent.trim(),
+ ).toContain(data.count.finished);
+ });
+
+ it('should not render badge when number is undefined', () => {
+ vm = mountComponent(Component, {
+ scope: 'all',
+ paths: {},
+ count: {},
+ });
+
+ // All
+ expect(
+ vm.$el.querySelector('.js-totalbuilds-count'),
+ ).toEqual(null);
+
+ // Pending
+ expect(
+ vm.$el.querySelector('.js-pipelines-tab-pending .badge'),
+ ).toEqual(null);
+
+ // Running
+ expect(
+ vm.$el.querySelector('.js-pipelines-tab-running .badge'),
+ ).toEqual(null);
+
+ // Finished
+ expect(
+ vm.$el.querySelector('.js-pipelines-tab-finished .badge'),
+ ).toEqual(null);
+ });
+ });
+});
diff --git a/spec/javascripts/project_select_combo_button_spec.js b/spec/javascripts/project_select_combo_button_spec.js
index e10a5a3bef6..021804e0769 100644
--- a/spec/javascripts/project_select_combo_button_spec.js
+++ b/spec/javascripts/project_select_combo_button_spec.js
@@ -101,5 +101,40 @@ describe('Project Select Combo Button', function () {
window.localStorage.clear();
});
});
+
+ describe('deriveTextVariants', function () {
+ beforeEach(function () {
+ this.mockExecutionContext = {
+ resourceType: '',
+ resourceLabel: '',
+ };
+
+ this.comboButton = new ProjectSelectComboButton(this.projectSelectInput);
+
+ this.method = this.comboButton.deriveTextVariants.bind(this.mockExecutionContext);
+ });
+
+ it('correctly derives test variants for merge requests', function () {
+ this.mockExecutionContext.resourceType = 'merge_requests';
+ this.mockExecutionContext.resourceLabel = 'New merge request';
+
+ const returnedVariants = this.method();
+
+ expect(returnedVariants.localStorageItemType).toBe('new-merge-request');
+ expect(returnedVariants.defaultTextPrefix).toBe('New merge request');
+ expect(returnedVariants.presetTextSuffix).toBe('merge request');
+ });
+
+ it('correctly derives text variants for issues', function () {
+ this.mockExecutionContext.resourceType = 'issues';
+ this.mockExecutionContext.resourceLabel = 'New issue';
+
+ const returnedVariants = this.method();
+
+ expect(returnedVariants.localStorageItemType).toBe('new-issue');
+ expect(returnedVariants.defaultTextPrefix).toBe('New issue');
+ expect(returnedVariants.presetTextSuffix).toBe('issue');
+ });
+ });
});
diff --git a/spec/javascripts/project_title_spec.js b/spec/javascripts/project_title_spec.js
index cc336180ff7..3d36bb3e4d4 100644
--- a/spec/javascripts/project_title_spec.js
+++ b/spec/javascripts/project_title_spec.js
@@ -7,6 +7,7 @@ import '~/project_select';
import '~/project';
describe('Project Title', () => {
+ const dummyApiVersion = 'v3000';
preloadFixtures('issues/open-issue.html.raw');
loadJSONFixtures('projects.json');
@@ -14,7 +15,7 @@ describe('Project Title', () => {
loadFixtures('issues/open-issue.html.raw');
window.gon = {};
- window.gon.api_version = 'v3';
+ window.gon.api_version = dummyApiVersion;
// eslint-disable-next-line no-new
new Project();
@@ -37,9 +38,10 @@ describe('Project Title', () => {
it('toggles dropdown', () => {
const $menu = $('.js-dropdown-menu-projects');
+ window.gon.current_user_id = 1;
$('.js-projects-dropdown-toggle').click();
expect($menu).toHaveClass('open');
- expect(reqUrl).toBe('/api/v3/projects.json?simple=true');
+ expect(reqUrl).toBe(`/api/${dummyApiVersion}/projects.json?simple=true`);
expect(reqData).toEqual({
search: '',
order_by: 'last_activity_at',
diff --git a/spec/javascripts/repo/components/repo_commit_section_spec.js b/spec/javascripts/repo/components/repo_commit_section_spec.js
index 249a2f36fcd..e604dcc152d 100644
--- a/spec/javascripts/repo/components/repo_commit_section_spec.js
+++ b/spec/javascripts/repo/components/repo_commit_section_spec.js
@@ -1,7 +1,7 @@
import Vue from 'vue';
import repoCommitSection from '~/repo/components/repo_commit_section.vue';
import RepoStore from '~/repo/stores/repo_store';
-import Api from '~/api';
+import RepoService from '~/repo/services/repo_service';
describe('RepoCommitSection', () => {
const branch = 'master';
@@ -111,7 +111,7 @@ describe('RepoCommitSection', () => {
expect(submitCommit.disabled).toBeFalsy();
spyOn(vm, 'makeCommit').and.callThrough();
- spyOn(Api, 'commitMultiple');
+ spyOn(RepoService, 'commitFiles').and.callFake(() => Promise.resolve());
submitCommit.click();
@@ -119,10 +119,9 @@ describe('RepoCommitSection', () => {
expect(vm.makeCommit).toHaveBeenCalled();
expect(submitCommit.querySelector('.fa-spinner.fa-spin')).toBeTruthy();
- const args = Api.commitMultiple.calls.allArgs()[0];
- const { commit_message, actions, branch: payloadBranch } = args[1];
+ const args = RepoService.commitFiles.calls.allArgs()[0];
+ const { commit_message, actions, branch: payloadBranch } = args[0];
- expect(args[0]).toBe(projectId);
expect(commit_message).toBe(commitMessage);
expect(actions.length).toEqual(2);
expect(payloadBranch).toEqual(branch);
diff --git a/spec/javascripts/repo/monaco_loader_spec.js b/spec/javascripts/repo/monaco_loader_spec.js
index be6e779c50f..887a80160fc 100644
--- a/spec/javascripts/repo/monaco_loader_spec.js
+++ b/spec/javascripts/repo/monaco_loader_spec.js
@@ -1,17 +1,13 @@
-/* global __webpack_public_path__ */
import monacoContext from 'monaco-editor/dev/vs/loader';
+import monacoLoader from '~/repo/monaco_loader';
describe('MonacoLoader', () => {
it('calls require.config and exports require', () => {
- spyOn(monacoContext.require, 'config');
-
- const monacoLoader = require('~/repo/monaco_loader'); // eslint-disable-line global-require
-
- expect(monacoContext.require.config).toHaveBeenCalledWith({
+ expect(monacoContext.require.getConfig()).toEqual(jasmine.objectContaining({
paths: {
vs: `${__webpack_public_path__}monaco-editor/vs`, // eslint-disable-line camelcase
},
- });
- expect(monacoLoader.default).toBe(monacoContext.require);
+ }));
+ expect(monacoLoader).toBe(monacoContext.require);
});
});
diff --git a/spec/javascripts/repo/services/repo_service_spec.js b/spec/javascripts/repo/services/repo_service_spec.js
index d74e6a67b1e..6f530770525 100644
--- a/spec/javascripts/repo/services/repo_service_spec.js
+++ b/spec/javascripts/repo/services/repo_service_spec.js
@@ -1,5 +1,7 @@
import axios from 'axios';
import RepoService from '~/repo/services/repo_service';
+import RepoStore from '~/repo/stores/repo_store';
+import Api from '~/api';
describe('RepoService', () => {
it('has default json format param', () => {
@@ -118,4 +120,52 @@ describe('RepoService', () => {
}).catch(done.fail);
});
});
+
+ describe('commitFiles', () => {
+ it('calls commitMultiple and .then commitFlash', (done) => {
+ const projectId = 'projectId';
+ const payload = {};
+ RepoStore.projectId = projectId;
+
+ spyOn(Api, 'commitMultiple').and.returnValue(Promise.resolve());
+ spyOn(RepoService, 'commitFlash');
+
+ const apiPromise = RepoService.commitFiles(payload);
+
+ expect(Api.commitMultiple).toHaveBeenCalledWith(projectId, payload);
+
+ apiPromise.then(() => {
+ expect(RepoService.commitFlash).toHaveBeenCalled();
+ done();
+ }).catch(done.fail);
+ });
+ });
+
+ describe('commitFlash', () => {
+ it('calls Flash with data.message', () => {
+ const data = {
+ message: 'message',
+ };
+ spyOn(window, 'Flash');
+
+ RepoService.commitFlash(data);
+
+ expect(window.Flash).toHaveBeenCalledWith(data.message);
+ });
+
+ it('calls Flash with success string if short_id and stats', () => {
+ const data = {
+ short_id: 'short_id',
+ stats: {
+ additions: '4',
+ deletions: '5',
+ },
+ };
+ spyOn(window, 'Flash');
+
+ RepoService.commitFlash(data);
+
+ expect(window.Flash).toHaveBeenCalledWith(`Your changes have been committed. Commit ${data.short_id} with ${data.stats.additions} additions, ${data.stats.deletions} deletions.`, 'notice');
+ });
+ });
});
diff --git a/spec/javascripts/groups/group_identicon_spec.js b/spec/javascripts/vue_shared/components/identicon_spec.js
index 66772327503..4f194e5a64e 100644
--- a/spec/javascripts/groups/group_identicon_spec.js
+++ b/spec/javascripts/vue_shared/components/identicon_spec.js
@@ -1,22 +1,18 @@
import Vue from 'vue';
-import groupIdenticonComponent from '~/groups/components/group_identicon.vue';
-import GroupsStore from '~/groups/stores/groups_store';
-import { group1 } from './mock_data';
+import identiconComponent from '~/vue_shared/components/identicon.vue';
const createComponent = () => {
- const Component = Vue.extend(groupIdenticonComponent);
- const store = new GroupsStore();
- const group = store.decorateGroup(group1);
+ const Component = Vue.extend(identiconComponent);
return new Component({
propsData: {
- entityId: group.id,
- entityName: group.name,
+ entityId: 1,
+ entityName: 'entity-name',
},
}).$mount();
};
-describe('GroupIdenticonComponent', () => {
+describe('IdenticonComponent', () => {
let vm;
beforeEach(() => {
diff --git a/spec/lib/gitlab/background_migration/deserialize_merge_request_diffs_and_commits_spec.rb b/spec/lib/gitlab/background_migration/deserialize_merge_request_diffs_and_commits_spec.rb
index 7cd2ce82eda..c0427639746 100644
--- a/spec/lib/gitlab/background_migration/deserialize_merge_request_diffs_and_commits_spec.rb
+++ b/spec/lib/gitlab/background_migration/deserialize_merge_request_diffs_and_commits_spec.rb
@@ -134,6 +134,17 @@ describe Gitlab::BackgroundMigration::DeserializeMergeRequestDiffsAndCommits do
include_examples 'updated MR diff'
end
+ context 'when the merge request diffs do not have a_mode and b_mode set' do
+ let(:commits) { merge_request_diff.commits.map(&:to_hash) }
+ let(:expected_diffs) { diffs_to_hashes(merge_request_diff.merge_request_diff_files) }
+
+ let(:diffs) do
+ expected_diffs.map { |diff| diff.except(:a_mode, :b_mode) }
+ end
+
+ include_examples 'updated MR diff'
+ end
+
context 'when the merge request diffs have binary content' do
let(:commits) { merge_request_diff.commits.map(&:to_hash) }
let(:expected_diffs) { diffs }
diff --git a/spec/lib/gitlab/background_migration/migrate_stage_status_spec.rb b/spec/lib/gitlab/background_migration/migrate_stage_status_spec.rb
new file mode 100644
index 00000000000..878158910be
--- /dev/null
+++ b/spec/lib/gitlab/background_migration/migrate_stage_status_spec.rb
@@ -0,0 +1,80 @@
+require 'spec_helper'
+
+describe Gitlab::BackgroundMigration::MigrateStageStatus, :migration, schema: 20170711145320 do
+ let(:projects) { table(:projects) }
+ let(:pipelines) { table(:ci_pipelines) }
+ let(:stages) { table(:ci_stages) }
+ let(:jobs) { table(:ci_builds) }
+
+ STATUSES = { created: 0, pending: 1, running: 2, success: 3,
+ failed: 4, canceled: 5, skipped: 6, manual: 7 }.freeze
+
+ before do
+ projects.create!(id: 1, name: 'gitlab1', path: 'gitlab1')
+ pipelines.create!(id: 1, project_id: 1, ref: 'master', sha: 'adf43c3a')
+ stages.create!(id: 1, pipeline_id: 1, project_id: 1, name: 'test', status: nil)
+ stages.create!(id: 2, pipeline_id: 1, project_id: 1, name: 'deploy', status: nil)
+ end
+
+ context 'when stage status is known' do
+ before do
+ create_job(project: 1, pipeline: 1, stage: 'test', status: 'success')
+ create_job(project: 1, pipeline: 1, stage: 'test', status: 'running')
+ create_job(project: 1, pipeline: 1, stage: 'deploy', status: 'failed')
+ end
+
+ it 'sets a correct stage status' do
+ described_class.new.perform(1, 2)
+
+ expect(stages.first.status).to eq STATUSES[:running]
+ expect(stages.second.status).to eq STATUSES[:failed]
+ end
+ end
+
+ context 'when stage status is not known' do
+ it 'sets a skipped stage status' do
+ described_class.new.perform(1, 2)
+
+ expect(stages.first.status).to eq STATUSES[:skipped]
+ expect(stages.second.status).to eq STATUSES[:skipped]
+ end
+ end
+
+ context 'when stage status includes status of a retried job' do
+ before do
+ create_job(project: 1, pipeline: 1, stage: 'test', status: 'canceled')
+ create_job(project: 1, pipeline: 1, stage: 'deploy', status: 'failed', retried: true)
+ create_job(project: 1, pipeline: 1, stage: 'deploy', status: 'success')
+ end
+
+ it 'sets a correct stage status' do
+ described_class.new.perform(1, 2)
+
+ expect(stages.first.status).to eq STATUSES[:canceled]
+ expect(stages.second.status).to eq STATUSES[:success]
+ end
+ end
+
+ context 'when some job in the stage is blocked / manual' do
+ before do
+ create_job(project: 1, pipeline: 1, stage: 'test', status: 'failed')
+ create_job(project: 1, pipeline: 1, stage: 'test', status: 'manual')
+ create_job(project: 1, pipeline: 1, stage: 'deploy', status: 'success', when: 'manual')
+ end
+
+ it 'sets a correct stage status' do
+ described_class.new.perform(1, 2)
+
+ expect(stages.first.status).to eq STATUSES[:manual]
+ expect(stages.second.status).to eq STATUSES[:success]
+ end
+ end
+
+ def create_job(project:, pipeline:, stage:, status:, **opts)
+ stages = { test: 1, build: 2, deploy: 3 }
+
+ jobs.create!(project_id: project, commit_id: pipeline,
+ stage_idx: stages[stage.to_sym], stage: stage,
+ status: status, **opts)
+ end
+end
diff --git a/spec/lib/gitlab/bare_repository_importer_spec.rb b/spec/lib/gitlab/bare_repository_importer_spec.rb
new file mode 100644
index 00000000000..36d1844b5b1
--- /dev/null
+++ b/spec/lib/gitlab/bare_repository_importer_spec.rb
@@ -0,0 +1,100 @@
+require 'spec_helper'
+
+describe Gitlab::BareRepositoryImporter, repository: true do
+ subject(:importer) { described_class.new('default', project_path) }
+
+ let!(:admin) { create(:admin) }
+
+ before do
+ allow(described_class).to receive(:log)
+ end
+
+ shared_examples 'importing a repository' do
+ describe '.execute' do
+ it 'creates a project for a repository in storage' do
+ FileUtils.mkdir_p(File.join(TestEnv.repos_path, "#{project_path}.git"))
+ fake_importer = double
+
+ expect(described_class).to receive(:new).with('default', project_path)
+ .and_return(fake_importer)
+ expect(fake_importer).to receive(:create_project_if_needed)
+
+ described_class.execute
+ end
+
+ it 'skips wiki repos' do
+ FileUtils.mkdir_p(File.join(TestEnv.repos_path, 'the-group', 'the-project.wiki.git'))
+
+ expect(described_class).to receive(:log).with(' * Skipping wiki repo')
+ expect(described_class).not_to receive(:new)
+
+ described_class.execute
+ end
+ end
+
+ describe '#initialize' do
+ context 'without admin users' do
+ let(:admin) { nil }
+
+ it 'raises an error' do
+ expect { importer }.to raise_error(Gitlab::BareRepositoryImporter::NoAdminError)
+ end
+ end
+ end
+
+ describe '#create_project_if_needed' do
+ it 'starts an import for a project that did not exist' do
+ expect(importer).to receive(:create_project)
+
+ importer.create_project_if_needed
+ end
+
+ it 'skips importing when the project already exists' do
+ project = create(:project, path: 'a-project', namespace: existing_group)
+
+ expect(importer).not_to receive(:create_project)
+ expect(importer).to receive(:log).with(" * #{project.name} (#{project_path}) exists")
+
+ importer.create_project_if_needed
+ end
+
+ it 'creates a project with the correct path in the database' do
+ importer.create_project_if_needed
+
+ expect(Project.find_by_full_path(project_path)).not_to be_nil
+ end
+ end
+ end
+
+ context 'with subgroups', :nested_groups do
+ let(:project_path) { 'a-group/a-sub-group/a-project' }
+
+ let(:existing_group) do
+ group = create(:group, path: 'a-group')
+ create(:group, path: 'a-sub-group', parent: group)
+ end
+
+ it_behaves_like 'importing a repository'
+ end
+
+ context 'without subgroups' do
+ let(:project_path) { 'a-group/a-project' }
+ let(:existing_group) { create(:group, path: 'a-group') }
+
+ it_behaves_like 'importing a repository'
+ end
+
+ context 'when subgroups are not available' do
+ let(:project_path) { 'a-group/a-sub-group/a-project' }
+
+ before do
+ expect(Group).to receive(:supports_nested_groups?) { false }
+ end
+
+ describe '#create_project_if_needed' do
+ it 'raises an error' do
+ expect { importer.create_project_if_needed }.to raise_error('Nested groups are not supported on MySQL')
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/database/migration_helpers_spec.rb b/spec/lib/gitlab/database/migration_helpers_spec.rb
index ec2274a70aa..c25fd459dd7 100644
--- a/spec/lib/gitlab/database/migration_helpers_spec.rb
+++ b/spec/lib/gitlab/database/migration_helpers_spec.rb
@@ -2,9 +2,7 @@ require 'spec_helper'
describe Gitlab::Database::MigrationHelpers do
let(:model) do
- ActiveRecord::Migration.new.extend(
- described_class
- )
+ ActiveRecord::Migration.new.extend(described_class)
end
before do
@@ -845,4 +843,51 @@ describe Gitlab::Database::MigrationHelpers do
end
end
end
+
+ describe 'sidekiq migration helpers', :sidekiq, :redis do
+ let(:worker) do
+ Class.new do
+ include Sidekiq::Worker
+ sidekiq_options queue: 'test'
+ end
+ end
+
+ describe '#sidekiq_queue_length' do
+ context 'when queue is empty' do
+ it 'returns zero' do
+ Sidekiq::Testing.disable! do
+ expect(model.sidekiq_queue_length('test')).to eq 0
+ end
+ end
+ end
+
+ context 'when queue contains jobs' do
+ it 'returns correct size of the queue' do
+ Sidekiq::Testing.disable! do
+ worker.perform_async('Something', [1])
+ worker.perform_async('Something', [2])
+
+ expect(model.sidekiq_queue_length('test')).to eq 2
+ end
+ end
+ end
+ end
+
+ describe '#migrate_sidekiq_queue' do
+ it 'migrates jobs from one sidekiq queue to another' do
+ Sidekiq::Testing.disable! do
+ worker.perform_async('Something', [1])
+ worker.perform_async('Something', [2])
+
+ expect(model.sidekiq_queue_length('test')).to eq 2
+ expect(model.sidekiq_queue_length('new_test')).to eq 0
+
+ model.sidekiq_queue_migrate('test', to: 'new_test')
+
+ expect(model.sidekiq_queue_length('test')).to eq 0
+ expect(model.sidekiq_queue_length('new_test')).to eq 2
+ end
+ end
+ end
+ end
end
diff --git a/spec/lib/gitlab/diff/file_spec.rb b/spec/lib/gitlab/diff/file_spec.rb
index d3d841b0668..c91895cedc3 100644
--- a/spec/lib/gitlab/diff/file_spec.rb
+++ b/spec/lib/gitlab/diff/file_spec.rb
@@ -15,6 +15,17 @@ describe Gitlab::Diff::File do
it { expect(diff_lines.first).to be_kind_of(Gitlab::Diff::Line) }
end
+ describe '#highlighted_diff_lines' do
+ it 'highlights the diff and memoises the result' do
+ expect(Gitlab::Diff::Highlight).to receive(:new)
+ .with(diff_file, repository: project.repository)
+ .once
+ .and_call_original
+
+ diff_file.highlighted_diff_lines
+ end
+ end
+
describe '#mode_changed?' do
it { expect(diff_file.mode_changed?).to be_falsey }
end
@@ -122,8 +133,20 @@ describe Gitlab::Diff::File do
let(:commit) { project.commit('2f63565e7aac07bcdadb654e253078b727143ec4') }
let(:diff_file) { commit.diffs.diff_file_with_new_path('files/images/6049019_460s.jpg') }
- it 'returns true' do
- expect(diff_file.content_changed?).to be_truthy
+ context 'when the blobs are different' do
+ it 'returns true' do
+ expect(diff_file.content_changed?).to be_truthy
+ end
+ end
+
+ context 'when there are no diff refs' do
+ before do
+ allow(diff_file).to receive(:diff_refs).and_return(nil)
+ end
+
+ it 'returns false' do
+ expect(diff_file.content_changed?).to be_falsey
+ end
end
end
@@ -131,8 +154,20 @@ describe Gitlab::Diff::File do
let(:commit) { project.commit('570e7b2abdd848b95f2f578043fc23bd6f6fd24d') }
let(:diff_file) { commit.diffs.diff_file_with_new_path('files/ruby/popen.rb') }
- it 'returns true' do
- expect(diff_file.content_changed?).to be_truthy
+ context 'when the blobs are different' do
+ it 'returns true' do
+ expect(diff_file.content_changed?).to be_truthy
+ end
+ end
+
+ context 'when there are no diff refs' do
+ before do
+ allow(diff_file).to receive(:diff_refs).and_return(nil)
+ end
+
+ it 'returns true' do
+ expect(diff_file.content_changed?).to be_truthy
+ end
end
end
end
@@ -270,6 +305,21 @@ describe Gitlab::Diff::File do
expect(diff_file.simple_viewer).to be_a(DiffViewer::ModeChanged)
end
end
+
+ context 'when no other conditions apply' do
+ before do
+ allow(diff_file).to receive(:content_changed?).and_return(false)
+ allow(diff_file).to receive(:new_file?).and_return(false)
+ allow(diff_file).to receive(:deleted_file?).and_return(false)
+ allow(diff_file).to receive(:renamed_file?).and_return(false)
+ allow(diff_file).to receive(:mode_changed?).and_return(false)
+ allow(diff_file).to receive(:raw_text?).and_return(false)
+ end
+
+ it 'returns a No Preview viewer' do
+ expect(diff_file.simple_viewer).to be_a(DiffViewer::NoPreview)
+ end
+ end
end
describe '#rich_viewer' do
diff --git a/spec/lib/gitlab/file_finder_spec.rb b/spec/lib/gitlab/file_finder_spec.rb
index 3fb6315a39a..07cb10e563e 100644
--- a/spec/lib/gitlab/file_finder_spec.rb
+++ b/spec/lib/gitlab/file_finder_spec.rb
@@ -7,15 +7,23 @@ describe Gitlab::FileFinder do
it 'finds by name' do
results = finder.find('files')
- expect(results.map(&:first)).to include('files/images/wm.svg')
+
+ filename, blob = results.find { |_, blob| blob.filename == 'files/images/wm.svg' }
+ expect(filename).to eq('files/images/wm.svg')
+ expect(blob).to be_a(Gitlab::SearchResults::FoundBlob)
+ expect(blob.ref).to eq(finder.ref)
+ expect(blob.data).not_to be_empty
end
it 'finds by content' do
results = finder.find('files')
- blob = results.select { |result| result.first == "CHANGELOG" }.flatten.last
+ filename, blob = results.find { |_, blob| blob.filename == 'CHANGELOG' }
- expect(blob.filename).to eq("CHANGELOG")
+ expect(filename).to eq('CHANGELOG')
+ expect(blob).to be_a(Gitlab::SearchResults::FoundBlob)
+ expect(blob.ref).to eq(finder.ref)
+ expect(blob.data).not_to be_empty
end
end
end
diff --git a/spec/lib/gitlab/git/blame_spec.rb b/spec/lib/gitlab/git/blame_spec.rb
index 800c245b130..465c2012b05 100644
--- a/spec/lib/gitlab/git/blame_spec.rb
+++ b/spec/lib/gitlab/git/blame_spec.rb
@@ -2,7 +2,7 @@
require "spec_helper"
describe Gitlab::Git::Blame, seed_helper: true do
- let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH) }
+ let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH, '') }
let(:blame) do
Gitlab::Git::Blame.new(repository, SeedRepo::Commit::ID, "CONTRIBUTING.md")
end
diff --git a/spec/lib/gitlab/git/blob_spec.rb b/spec/lib/gitlab/git/blob_spec.rb
index dfab0c2fe85..66ba00acb7d 100644
--- a/spec/lib/gitlab/git/blob_spec.rb
+++ b/spec/lib/gitlab/git/blob_spec.rb
@@ -3,7 +3,7 @@
require "spec_helper"
describe Gitlab::Git::Blob, seed_helper: true do
- let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH) }
+ let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH, '') }
describe 'initialize' do
let(:blob) { Gitlab::Git::Blob.new(name: 'test') }
diff --git a/spec/lib/gitlab/git/branch_spec.rb b/spec/lib/gitlab/git/branch_spec.rb
index cdf1b8beee3..318a7b7a332 100644
--- a/spec/lib/gitlab/git/branch_spec.rb
+++ b/spec/lib/gitlab/git/branch_spec.rb
@@ -1,7 +1,7 @@
require "spec_helper"
describe Gitlab::Git::Branch, seed_helper: true do
- let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH) }
+ let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH, '') }
subject { repository.branches }
diff --git a/spec/lib/gitlab/git/commit_spec.rb b/spec/lib/gitlab/git/commit_spec.rb
index ac33cd8a2c9..14d64d8c4da 100644
--- a/spec/lib/gitlab/git/commit_spec.rb
+++ b/spec/lib/gitlab/git/commit_spec.rb
@@ -1,7 +1,7 @@
require "spec_helper"
describe Gitlab::Git::Commit, seed_helper: true do
- let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH) }
+ let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH, '') }
let(:commit) { described_class.find(repository, SeedRepo::Commit::ID) }
let(:rugged_commit) do
repository.rugged.lookup(SeedRepo::Commit::ID)
@@ -9,7 +9,7 @@ describe Gitlab::Git::Commit, seed_helper: true do
describe "Commit info" do
before do
- repo = Gitlab::Git::Repository.new('default', TEST_REPO_PATH).rugged
+ repo = Gitlab::Git::Repository.new('default', TEST_REPO_PATH, '').rugged
@committer = {
email: 'mike@smith.com',
@@ -59,7 +59,7 @@ describe Gitlab::Git::Commit, seed_helper: true do
after do
# Erase the new commit so other tests get the original repo
- repo = Gitlab::Git::Repository.new('default', TEST_REPO_PATH).rugged
+ repo = Gitlab::Git::Repository.new('default', TEST_REPO_PATH, '').rugged
repo.references.update("refs/heads/master", SeedRepo::LastCommit::ID)
end
end
@@ -144,7 +144,7 @@ describe Gitlab::Git::Commit, seed_helper: true do
end
context 'with broken repo' do
- let(:repository) { Gitlab::Git::Repository.new('default', TEST_BROKEN_REPO_PATH) }
+ let(:repository) { Gitlab::Git::Repository.new('default', TEST_BROKEN_REPO_PATH, '') }
it 'returns nil' do
expect(described_class.find(repository, SeedRepo::Commit::ID)).to be_nil
diff --git a/spec/lib/gitlab/git/committer_spec.rb b/spec/lib/gitlab/git/committer_spec.rb
new file mode 100644
index 00000000000..b0ddbb51449
--- /dev/null
+++ b/spec/lib/gitlab/git/committer_spec.rb
@@ -0,0 +1,22 @@
+require 'spec_helper'
+
+describe Gitlab::Git::Committer do
+ let(:name) { 'Jane Doe' }
+ let(:email) { 'janedoe@example.com' }
+ let(:gl_id) { 'user-123' }
+
+ subject { described_class.new(name, email, gl_id) }
+
+ describe '#==' do
+ def eq_other(name, email, gl_id)
+ eq(described_class.new(name, email, gl_id))
+ end
+
+ it { expect(subject).to eq_other(name, email, gl_id) }
+
+ it { expect(subject).not_to eq_other(nil, nil, nil) }
+ it { expect(subject).not_to eq_other(name + 'x', email, gl_id) }
+ it { expect(subject).not_to eq_other(name, email + 'x', gl_id) }
+ it { expect(subject).not_to eq_other(name, email, gl_id + 'x') }
+ end
+end
diff --git a/spec/lib/gitlab/git/compare_spec.rb b/spec/lib/gitlab/git/compare_spec.rb
index 4c9f4a28f32..b6a42e422b5 100644
--- a/spec/lib/gitlab/git/compare_spec.rb
+++ b/spec/lib/gitlab/git/compare_spec.rb
@@ -1,7 +1,7 @@
require "spec_helper"
describe Gitlab::Git::Compare, seed_helper: true do
- let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH) }
+ let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH, '') }
let(:compare) { Gitlab::Git::Compare.new(repository, SeedRepo::BigCommit::ID, SeedRepo::Commit::ID, straight: false) }
let(:compare_straight) { Gitlab::Git::Compare.new(repository, SeedRepo::BigCommit::ID, SeedRepo::Commit::ID, straight: true) }
diff --git a/spec/lib/gitlab/git/diff_spec.rb b/spec/lib/gitlab/git/diff_spec.rb
index 7ea3386ac2a..dfbdbee48f7 100644
--- a/spec/lib/gitlab/git/diff_spec.rb
+++ b/spec/lib/gitlab/git/diff_spec.rb
@@ -1,7 +1,7 @@
require "spec_helper"
describe Gitlab::Git::Diff, seed_helper: true do
- let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH) }
+ let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH, '') }
before do
@raw_diff_hash = {
diff --git a/spec/lib/gitlab/git/hook_spec.rb b/spec/lib/gitlab/git/hook_spec.rb
index 19391a70cf6..ea3e4680b1d 100644
--- a/spec/lib/gitlab/git/hook_spec.rb
+++ b/spec/lib/gitlab/git/hook_spec.rb
@@ -10,7 +10,8 @@ describe Gitlab::Git::Hook do
describe "#trigger" do
let(:project) { create(:project, :repository) }
- let(:repo_path) { project.repository.path }
+ let(:repository) { project.repository.raw_repository }
+ let(:repo_path) { repository.path }
let(:user) { create(:user) }
let(:gl_id) { Gitlab::GlId.gl_id(user) }
@@ -48,7 +49,7 @@ describe Gitlab::Git::Hook do
it "returns success with no errors" do
create_hook(hook_name)
- hook = described_class.new(hook_name, project)
+ hook = described_class.new(hook_name, repository)
blank = Gitlab::Git::BLANK_SHA
ref = Gitlab::Git::BRANCH_REF_PREFIX + 'new_branch'
@@ -66,7 +67,7 @@ describe Gitlab::Git::Hook do
context "when the hook is unsuccessful" do
it "returns failure with errors" do
create_failing_hook(hook_name)
- hook = described_class.new(hook_name, project)
+ hook = described_class.new(hook_name, repository)
blank = Gitlab::Git::BLANK_SHA
ref = Gitlab::Git::BRANCH_REF_PREFIX + 'new_branch'
@@ -80,7 +81,7 @@ describe Gitlab::Git::Hook do
context "when the hook doesn't exist" do
it "returns success with no errors" do
- hook = described_class.new('unknown_hook', project)
+ hook = described_class.new('unknown_hook', repository)
blank = Gitlab::Git::BLANK_SHA
ref = Gitlab::Git::BRANCH_REF_PREFIX + 'new_branch'
diff --git a/spec/services/git_hooks_service_spec.rb b/spec/lib/gitlab/git/hooks_service_spec.rb
index 3ce01a995b4..e9c0209fe3b 100644
--- a/spec/services/git_hooks_service_spec.rb
+++ b/spec/lib/gitlab/git/hooks_service_spec.rb
@@ -1,16 +1,14 @@
require 'spec_helper'
-describe GitHooksService do
- include RepoHelpers
-
- let(:user) { create(:user) }
- let(:project) { create(:project, :repository) }
+describe Gitlab::Git::HooksService, seed_helper: true do
+ let(:committer) { Gitlab::Git::Committer.new('Jane Doe', 'janedoe@example.com', 'user-456') }
+ let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH, 'project-123') }
let(:service) { described_class.new }
before do
@blankrev = Gitlab::Git::BLANK_SHA
- @oldrev = sample_commit.parent_id
- @newrev = sample_commit.id
+ @oldrev = SeedRepo::Commit::PARENT_ID
+ @newrev = SeedRepo::Commit::ID
@ref = 'refs/heads/feature'
end
@@ -20,7 +18,7 @@ describe GitHooksService do
hook = double(trigger: [true, nil])
expect(Gitlab::Git::Hook).to receive(:new).exactly(3).times.and_return(hook)
- service.execute(user, project, @blankrev, @newrev, @ref) { }
+ service.execute(committer, repository, @blankrev, @newrev, @ref) { }
end
end
@@ -30,8 +28,8 @@ describe GitHooksService do
expect(service).not_to receive(:run_hook).with('post-receive')
expect do
- service.execute(user, project, @blankrev, @newrev, @ref)
- end.to raise_error(GitHooksService::PreReceiveError)
+ service.execute(committer, repository, @blankrev, @newrev, @ref)
+ end.to raise_error(Gitlab::Git::HooksService::PreReceiveError)
end
end
@@ -42,8 +40,8 @@ describe GitHooksService do
expect(service).not_to receive(:run_hook).with('post-receive')
expect do
- service.execute(user, project, @blankrev, @newrev, @ref)
- end.to raise_error(GitHooksService::PreReceiveError)
+ service.execute(committer, repository, @blankrev, @newrev, @ref)
+ end.to raise_error(Gitlab::Git::HooksService::PreReceiveError)
end
end
end
diff --git a/spec/lib/gitlab/git/index_spec.rb b/spec/lib/gitlab/git/index_spec.rb
index 21b71654251..73fbc6a6afa 100644
--- a/spec/lib/gitlab/git/index_spec.rb
+++ b/spec/lib/gitlab/git/index_spec.rb
@@ -1,7 +1,7 @@
require 'spec_helper'
describe Gitlab::Git::Index, seed_helper: true do
- let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH) }
+ let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH, '') }
let(:index) { described_class.new(repository) }
before do
diff --git a/spec/lib/gitlab/git/repository_spec.rb b/spec/lib/gitlab/git/repository_spec.rb
index 4ef5d9070a2..6b9773c9b63 100644
--- a/spec/lib/gitlab/git/repository_spec.rb
+++ b/spec/lib/gitlab/git/repository_spec.rb
@@ -17,7 +17,7 @@ describe Gitlab::Git::Repository, seed_helper: true do
end
end
- let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH) }
+ let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH, '') }
describe "Respond to" do
subject { repository }
@@ -56,14 +56,14 @@ describe Gitlab::Git::Repository, seed_helper: true do
describe "#rugged" do
describe 'when storage is broken', broken_storage: true do
it 'raises a storage exception when storage is not available' do
- broken_repo = described_class.new('broken', 'a/path.git')
+ broken_repo = described_class.new('broken', 'a/path.git', '')
expect { broken_repo.rugged }.to raise_error(Gitlab::Git::Storage::Inaccessible)
end
end
it 'raises a no repository exception when there is no repo' do
- broken_repo = described_class.new('default', 'a/path.git')
+ broken_repo = described_class.new('default', 'a/path.git', '')
expect { broken_repo.rugged }.to raise_error(Gitlab::Git::Repository::NoRepository)
end
@@ -235,18 +235,10 @@ describe Gitlab::Git::Repository, seed_helper: true do
it { is_expected.to be < 2 }
end
- describe '#has_commits?' do
- it { expect(repository.has_commits?).to be_truthy }
- end
-
describe '#empty?' do
it { expect(repository.empty?).to be_falsey }
end
- describe '#bare?' do
- it { expect(repository.bare?).to be_truthy }
- end
-
describe '#ref_names' do
let(:ref_names) { repository.ref_names }
subject { ref_names }
@@ -265,7 +257,7 @@ describe Gitlab::Git::Repository, seed_helper: true do
end
describe '#submodule_url_for' do
- let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH) }
+ let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH, '') }
let(:ref) { 'master' }
def submodule_url(path)
@@ -303,7 +295,7 @@ describe Gitlab::Git::Repository, seed_helper: true do
end
context '#submodules' do
- let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH) }
+ let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH, '') }
context 'where repo has submodules' do
let(:submodules) { repository.send(:submodules, 'master') }
@@ -399,7 +391,7 @@ describe Gitlab::Git::Repository, seed_helper: true do
describe "#delete_branch" do
before(:all) do
- @repo = Gitlab::Git::Repository.new('default', TEST_MUTABLE_REPO_PATH)
+ @repo = Gitlab::Git::Repository.new('default', TEST_MUTABLE_REPO_PATH, '')
@repo.delete_branch("feature")
end
@@ -415,7 +407,7 @@ describe Gitlab::Git::Repository, seed_helper: true do
describe "#create_branch" do
before(:all) do
- @repo = Gitlab::Git::Repository.new('default', TEST_MUTABLE_REPO_PATH)
+ @repo = Gitlab::Git::Repository.new('default', TEST_MUTABLE_REPO_PATH, '')
end
it "should create a new branch" do
@@ -441,15 +433,6 @@ describe Gitlab::Git::Repository, seed_helper: true do
end
end
- describe "#remote_names" do
- let(:remotes) { repository.remote_names }
-
- it "should have one entry: 'origin'" do
- expect(remotes.size).to eq(1)
- expect(remotes.first).to eq("origin")
- end
- end
-
describe "#refs_hash" do
let(:refs) { repository.refs_hash }
@@ -462,7 +445,7 @@ describe Gitlab::Git::Repository, seed_helper: true do
describe "#remote_delete" do
before(:all) do
- @repo = Gitlab::Git::Repository.new('default', TEST_MUTABLE_REPO_PATH)
+ @repo = Gitlab::Git::Repository.new('default', TEST_MUTABLE_REPO_PATH, '')
@repo.remote_delete("expendable")
end
@@ -478,7 +461,7 @@ describe Gitlab::Git::Repository, seed_helper: true do
describe "#remote_add" do
before(:all) do
- @repo = Gitlab::Git::Repository.new('default', TEST_MUTABLE_REPO_PATH)
+ @repo = Gitlab::Git::Repository.new('default', TEST_MUTABLE_REPO_PATH, '')
@repo.remote_add("new_remote", SeedHelper::GITLAB_GIT_TEST_REPO_URL)
end
@@ -494,7 +477,7 @@ describe Gitlab::Git::Repository, seed_helper: true do
describe "#remote_update" do
before(:all) do
- @repo = Gitlab::Git::Repository.new('default', TEST_MUTABLE_REPO_PATH)
+ @repo = Gitlab::Git::Repository.new('default', TEST_MUTABLE_REPO_PATH, '')
@repo.remote_update("expendable", url: TEST_NORMAL_REPO_PATH)
end
@@ -523,7 +506,7 @@ describe Gitlab::Git::Repository, seed_helper: true do
before(:context) do
# Add new commits so that there's a renamed file in the commit history
- repo = Gitlab::Git::Repository.new('default', TEST_REPO_PATH).rugged
+ repo = Gitlab::Git::Repository.new('default', TEST_REPO_PATH, '').rugged
@commit_with_old_name_id = new_commit_edit_old_file(repo)
@rename_commit_id = new_commit_move_file(repo)
@commit_with_new_name_id = new_commit_edit_new_file(repo)
@@ -531,7 +514,7 @@ describe Gitlab::Git::Repository, seed_helper: true do
after(:context) do
# Erase our commits so other tests get the original repo
- repo = Gitlab::Git::Repository.new('default', TEST_REPO_PATH).rugged
+ repo = Gitlab::Git::Repository.new('default', TEST_REPO_PATH, '').rugged
repo.references.update("refs/heads/master", SeedRepo::LastCommit::ID)
end
@@ -866,7 +849,7 @@ describe Gitlab::Git::Repository, seed_helper: true do
describe '#autocrlf' do
before(:all) do
- @repo = Gitlab::Git::Repository.new('default', TEST_MUTABLE_REPO_PATH)
+ @repo = Gitlab::Git::Repository.new('default', TEST_MUTABLE_REPO_PATH, '')
@repo.rugged.config['core.autocrlf'] = true
end
@@ -881,7 +864,7 @@ describe Gitlab::Git::Repository, seed_helper: true do
describe '#autocrlf=' do
before(:all) do
- @repo = Gitlab::Git::Repository.new('default', TEST_MUTABLE_REPO_PATH)
+ @repo = Gitlab::Git::Repository.new('default', TEST_MUTABLE_REPO_PATH, '')
@repo.rugged.config['core.autocrlf'] = false
end
@@ -950,7 +933,7 @@ describe Gitlab::Git::Repository, seed_helper: true do
context 'with local and remote branches' do
let(:repository) do
- Gitlab::Git::Repository.new('default', File.join(TEST_MUTABLE_REPO_PATH, '.git'))
+ Gitlab::Git::Repository.new('default', File.join(TEST_MUTABLE_REPO_PATH, '.git'), '')
end
before do
@@ -994,6 +977,36 @@ describe Gitlab::Git::Repository, seed_helper: true do
it 'returns the number of branches' do
expect(repository.branch_count).to eq(10)
end
+
+ context 'with local and remote branches' do
+ let(:repository) do
+ Gitlab::Git::Repository.new('default', File.join(TEST_MUTABLE_REPO_PATH, '.git'), '')
+ end
+
+ before do
+ create_remote_branch(repository, 'joe', 'remote_branch', 'master')
+ repository.create_branch('local_branch', 'master')
+ end
+
+ after do
+ FileUtils.rm_rf(TEST_MUTABLE_REPO_PATH)
+ ensure_seeds
+ end
+
+ it 'returns the count of local branches' do
+ expect(repository.branch_count).to eq(repository.local_branches.count)
+ end
+
+ context 'with Gitaly disabled' do
+ before do
+ allow(Gitlab::GitalyClient).to receive(:feature_enabled?).and_return(false)
+ end
+
+ it 'returns the count of local branches' do
+ expect(repository.branch_count).to eq(repository.local_branches.count)
+ end
+ end
+ end
end
describe "#ls_files" do
@@ -1097,35 +1110,83 @@ describe Gitlab::Git::Repository, seed_helper: true do
end
end
+ describe '#ref_exists?' do
+ shared_examples 'checks the existence of refs' do
+ it 'returns true for an existing tag' do
+ expect(repository.ref_exists?('refs/heads/master')).to eq(true)
+ end
+
+ it 'returns false for a non-existing tag' do
+ expect(repository.ref_exists?('refs/tags/THIS_TAG_DOES_NOT_EXIST')).to eq(false)
+ end
+
+ it 'raises an ArgumentError for an empty string' do
+ expect { repository.ref_exists?('') }.to raise_error(ArgumentError)
+ end
+
+ it 'raises an ArgumentError for an invalid ref' do
+ expect { repository.ref_exists?('INVALID') }.to raise_error(ArgumentError)
+ end
+ end
+
+ context 'when Gitaly ref_exists feature is enabled' do
+ it_behaves_like 'checks the existence of refs'
+ end
+
+ context 'when Gitaly ref_exists feature is disabled', skip_gitaly_mock: true do
+ it_behaves_like 'checks the existence of refs'
+ end
+ end
+
describe '#tag_exists?' do
- it 'returns true for an existing tag' do
- tag = repository.tag_names.first
+ shared_examples 'checks the existence of tags' do
+ it 'returns true for an existing tag' do
+ tag = repository.tag_names.first
- expect(repository.tag_exists?(tag)).to eq(true)
+ expect(repository.tag_exists?(tag)).to eq(true)
+ end
+
+ it 'returns false for a non-existing tag' do
+ expect(repository.tag_exists?('v9000')).to eq(false)
+ end
end
- it 'returns false for a non-existing tag' do
- expect(repository.tag_exists?('v9000')).to eq(false)
+ context 'when Gitaly ref_exists_tags feature is enabled' do
+ it_behaves_like 'checks the existence of tags'
+ end
+
+ context 'when Gitaly ref_exists_tags feature is disabled', skip_gitaly_mock: true do
+ it_behaves_like 'checks the existence of tags'
end
end
describe '#branch_exists?' do
- it 'returns true for an existing branch' do
- expect(repository.branch_exists?('master')).to eq(true)
+ shared_examples 'checks the existence of branches' do
+ it 'returns true for an existing branch' do
+ expect(repository.branch_exists?('master')).to eq(true)
+ end
+
+ it 'returns false for a non-existing branch' do
+ expect(repository.branch_exists?('kittens')).to eq(false)
+ end
+
+ it 'returns false when using an invalid branch name' do
+ expect(repository.branch_exists?('.bla')).to eq(false)
+ end
end
- it 'returns false for a non-existing branch' do
- expect(repository.branch_exists?('kittens')).to eq(false)
+ context 'when Gitaly ref_exists_branches feature is enabled' do
+ it_behaves_like 'checks the existence of branches'
end
- it 'returns false when using an invalid branch name' do
- expect(repository.branch_exists?('.bla')).to eq(false)
+ context 'when Gitaly ref_exists_branches feature is disabled', skip_gitaly_mock: true do
+ it_behaves_like 'checks the existence of branches'
end
end
describe '#local_branches' do
before(:all) do
- @repo = Gitlab::Git::Repository.new('default', File.join(TEST_MUTABLE_REPO_PATH, '.git'))
+ @repo = Gitlab::Git::Repository.new('default', File.join(TEST_MUTABLE_REPO_PATH, '.git'), '')
end
after(:all) do
diff --git a/spec/lib/gitlab/git/storage/forked_storage_check_spec.rb b/spec/lib/gitlab/git/storage/forked_storage_check_spec.rb
index 12366151f44..c708b15853a 100644
--- a/spec/lib/gitlab/git/storage/forked_storage_check_spec.rb
+++ b/spec/lib/gitlab/git/storage/forked_storage_check_spec.rb
@@ -1,6 +1,6 @@
require 'spec_helper'
-describe Gitlab::Git::Storage::ForkedStorageCheck, skip_database_cleaner: true do
+describe Gitlab::Git::Storage::ForkedStorageCheck, broken_storage: true, skip_database_cleaner: true do
let(:existing_path) do
existing_path = TestEnv.repos_path
FileUtils.mkdir_p(existing_path)
diff --git a/spec/lib/gitlab/git/tag_spec.rb b/spec/lib/gitlab/git/tag_spec.rb
index 78d1e120013..cc10679ef1e 100644
--- a/spec/lib/gitlab/git/tag_spec.rb
+++ b/spec/lib/gitlab/git/tag_spec.rb
@@ -1,7 +1,7 @@
require "spec_helper"
describe Gitlab::Git::Tag, seed_helper: true do
- let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH) }
+ let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH, '') }
shared_examples 'Gitlab::Git::Repository#tags' do
describe 'first tag' do
diff --git a/spec/lib/gitlab/git/tree_spec.rb b/spec/lib/gitlab/git/tree_spec.rb
index 98ddd3c3664..c07a2d91768 100644
--- a/spec/lib/gitlab/git/tree_spec.rb
+++ b/spec/lib/gitlab/git/tree_spec.rb
@@ -1,7 +1,7 @@
require "spec_helper"
describe Gitlab::Git::Tree, seed_helper: true do
- let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH) }
+ let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH, '') }
context :repo do
let(:tree) { Gitlab::Git::Tree.where(repository, SeedRepo::Commit::ID) }
diff --git a/spec/lib/gitlab/git_access_spec.rb b/spec/lib/gitlab/git_access_spec.rb
index 2d6ea37d0ac..295a979da76 100644
--- a/spec/lib/gitlab/git_access_spec.rb
+++ b/spec/lib/gitlab/git_access_spec.rb
@@ -1,21 +1,17 @@
require 'spec_helper'
describe Gitlab::GitAccess do
- let(:pull_access_check) { access.check('git-upload-pack', '_any') }
- let(:push_access_check) { access.check('git-receive-pack', '_any') }
- let(:access) { described_class.new(actor, project, protocol, authentication_abilities: authentication_abilities, redirected_path: redirected_path) }
- let(:project) { create(:project, :repository) }
- let(:user) { create(:user) }
+ set(:user) { create(:user) }
+
let(:actor) { user }
+ let(:project) { create(:project, :repository) }
let(:protocol) { 'ssh' }
+ let(:authentication_abilities) { %i[read_project download_code push_code] }
let(:redirected_path) { nil }
- let(:authentication_abilities) do
- [
- :read_project,
- :download_code,
- :push_code
- ]
- end
+
+ let(:access) { described_class.new(actor, project, protocol, authentication_abilities: authentication_abilities, redirected_path: redirected_path) }
+ let(:push_access_check) { access.check('git-receive-pack', '_any') }
+ let(:pull_access_check) { access.check('git-upload-pack', '_any') }
describe '#check with single protocols allowed' do
def disable_protocol(protocol)
@@ -27,12 +23,11 @@ describe Gitlab::GitAccess do
disable_protocol('ssh')
end
- it 'blocks ssh git push' do
- expect { push_access_check }.to raise_unauthorized('Git access over SSH is not allowed')
- end
-
- it 'blocks ssh git pull' do
- expect { pull_access_check }.to raise_unauthorized('Git access over SSH is not allowed')
+ it 'blocks ssh git push and pull' do
+ aggregate_failures do
+ expect { push_access_check }.to raise_unauthorized('Git access over SSH is not allowed')
+ expect { pull_access_check }.to raise_unauthorized('Git access over SSH is not allowed')
+ end
end
end
@@ -43,12 +38,11 @@ describe Gitlab::GitAccess do
disable_protocol('http')
end
- it 'blocks http push' do
- expect { push_access_check }.to raise_unauthorized('Git access over HTTP is not allowed')
- end
-
- it 'blocks http git pull' do
- expect { pull_access_check }.to raise_unauthorized('Git access over HTTP is not allowed')
+ it 'blocks http push and pull' do
+ aggregate_failures do
+ expect { push_access_check }.to raise_unauthorized('Git access over HTTP is not allowed')
+ expect { pull_access_check }.to raise_unauthorized('Git access over HTTP is not allowed')
+ end
end
end
end
@@ -65,22 +59,20 @@ describe Gitlab::GitAccess do
deploy_key.projects << project
end
- it 'allows pull access' do
- expect { pull_access_check }.not_to raise_error
- end
-
- it 'allows push access' do
- expect { push_access_check }.not_to raise_error
+ it 'allows push and pull access' do
+ aggregate_failures do
+ expect { push_access_check }.not_to raise_error
+ expect { pull_access_check }.not_to raise_error
+ end
end
end
context 'when the Deploykey does not have access to the project' do
- it 'blocks pulls with "not found"' do
- expect { pull_access_check }.to raise_not_found('The project you were looking for could not be found.')
- end
-
- it 'blocks pushes with "not found"' do
- expect { push_access_check }.to raise_not_found('The project you were looking for could not be found.')
+ it 'blocks push and pull with "not found"' do
+ aggregate_failures do
+ expect { push_access_check }.to raise_not_found
+ expect { pull_access_check }.to raise_not_found
+ end
end
end
end
@@ -88,25 +80,23 @@ describe Gitlab::GitAccess do
context 'when actor is a User' do
context 'when the User can read the project' do
before do
- project.team << [user, :master]
+ project.add_master(user)
end
- it 'allows pull access' do
- expect { pull_access_check }.not_to raise_error
- end
-
- it 'allows push access' do
- expect { push_access_check }.not_to raise_error
+ it 'allows push and pull access' do
+ aggregate_failures do
+ expect { pull_access_check }.not_to raise_error
+ expect { push_access_check }.not_to raise_error
+ end
end
end
context 'when the User cannot read the project' do
- it 'blocks pulls with "not found"' do
- expect { pull_access_check }.to raise_not_found('The project you were looking for could not be found.')
- end
-
- it 'blocks pushes with "not found"' do
- expect { push_access_check }.to raise_not_found('The project you were looking for could not be found.')
+ it 'blocks push and pull with "not found"' do
+ aggregate_failures do
+ expect { push_access_check }.to raise_not_found
+ expect { pull_access_check }.to raise_not_found
+ end
end
end
end
@@ -121,7 +111,7 @@ describe Gitlab::GitAccess do
end
it 'does not block pushes with "not found"' do
- expect { push_access_check }.to raise_unauthorized('You are not allowed to upload code for this project.')
+ expect { push_access_check }.to raise_unauthorized(described_class::ERROR_MESSAGES[:upload])
end
end
end
@@ -137,17 +127,17 @@ describe Gitlab::GitAccess do
end
it 'does not block pushes with "not found"' do
- expect { push_access_check }.to raise_unauthorized('You are not allowed to upload code for this project.')
+ expect { push_access_check }.to raise_unauthorized(described_class::ERROR_MESSAGES[:upload])
end
end
context 'when guests cannot read the project' do
it 'blocks pulls with "not found"' do
- expect { pull_access_check }.to raise_not_found('The project you were looking for could not be found.')
+ expect { pull_access_check }.to raise_not_found
end
it 'blocks pushes with "not found"' do
- expect { push_access_check }.to raise_not_found('The project you were looking for could not be found.')
+ expect { push_access_check }.to raise_not_found
end
end
end
@@ -156,48 +146,50 @@ describe Gitlab::GitAccess do
context 'when the project is nil' do
let(:project) { nil }
- it 'blocks any command with "not found"' do
- expect { pull_access_check }.to raise_not_found('The project you were looking for could not be found.')
- expect { push_access_check }.to raise_not_found('The project you were looking for could not be found.')
+ it 'blocks push and pull with "not found"' do
+ aggregate_failures do
+ expect { pull_access_check }.to raise_not_found
+ expect { push_access_check }.to raise_not_found
+ end
end
end
end
describe '#check_project_moved!' do
before do
- project.team << [user, :master]
+ project.add_master(user)
end
context 'when a redirect was not followed to find the project' do
- context 'pull code' do
- it { expect { pull_access_check }.not_to raise_error }
- end
-
- context 'push code' do
- it { expect { push_access_check }.not_to raise_error }
+ it 'allows push and pull access' do
+ aggregate_failures do
+ expect { push_access_check }.not_to raise_error
+ expect { pull_access_check }.not_to raise_error
+ end
end
end
context 'when a redirect was followed to find the project' do
let(:redirected_path) { 'some/other-path' }
- context 'pull code' do
- it { expect { pull_access_check }.to raise_not_found(/Project '#{redirected_path}' was moved to '#{project.full_path}'/) }
- it { expect { pull_access_check }.to raise_not_found(/git remote set-url origin #{project.ssh_url_to_repo}/) }
+ it 'blocks push and pull access' do
+ aggregate_failures do
+ expect { push_access_check }.to raise_error(described_class::ProjectMovedError, /Project '#{redirected_path}' was moved to '#{project.full_path}'/)
+ expect { push_access_check }.to raise_error(described_class::ProjectMovedError, /git remote set-url origin #{project.ssh_url_to_repo}/)
- context 'http protocol' do
- let(:protocol) { 'http' }
- it { expect { pull_access_check }.to raise_not_found(/git remote set-url origin #{project.http_url_to_repo}/) }
+ expect { pull_access_check }.to raise_error(described_class::ProjectMovedError, /Project '#{redirected_path}' was moved to '#{project.full_path}'/)
+ expect { pull_access_check }.to raise_error(described_class::ProjectMovedError, /git remote set-url origin #{project.ssh_url_to_repo}/)
end
end
- context 'push code' do
- it { expect { push_access_check }.to raise_not_found(/Project '#{redirected_path}' was moved to '#{project.full_path}'/) }
- it { expect { push_access_check }.to raise_not_found(/git remote set-url origin #{project.ssh_url_to_repo}/) }
+ context 'http protocol' do
+ let(:protocol) { 'http' }
- context 'http protocol' do
- let(:protocol) { 'http' }
- it { expect { push_access_check }.to raise_not_found(/git remote set-url origin #{project.http_url_to_repo}/) }
+ it 'includes the path to the project using HTTP' do
+ aggregate_failures do
+ expect { push_access_check }.to raise_error(described_class::ProjectMovedError, /git remote set-url origin #{project.http_url_to_repo}/)
+ expect { pull_access_check }.to raise_error(described_class::ProjectMovedError, /git remote set-url origin #{project.http_url_to_repo}/)
+ end
end
end
end
@@ -242,40 +234,28 @@ describe Gitlab::GitAccess do
end
describe '#check_download_access!' do
- describe 'master permissions' do
- before do
- project.team << [user, :master]
- end
+ it 'allows masters to pull' do
+ project.add_master(user)
- context 'pull code' do
- it { expect { pull_access_check }.not_to raise_error }
- end
+ expect { pull_access_check }.not_to raise_error
end
- describe 'guest permissions' do
- before do
- project.team << [user, :guest]
- end
+ it 'disallows guests to pull' do
+ project.add_guest(user)
- context 'pull code' do
- it { expect { pull_access_check }.to raise_unauthorized('You are not allowed to download code from this project.') }
- end
+ expect { pull_access_check }.to raise_unauthorized(described_class::ERROR_MESSAGES[:download])
end
- describe 'blocked user' do
- before do
- project.team << [user, :master]
- user.block
- end
+ it 'disallows blocked users to pull' do
+ project.add_master(user)
+ user.block
- context 'pull code' do
- it { expect { pull_access_check }.to raise_unauthorized('Your account has been blocked.') }
- end
+ expect { pull_access_check }.to raise_unauthorized('Your account has been blocked.')
end
describe 'without access to project' do
context 'pull code' do
- it { expect { pull_access_check }.to raise_not_found('The project you were looking for could not be found.') }
+ it { expect { pull_access_check }.to raise_not_found }
end
context 'when project is public' do
@@ -292,7 +272,7 @@ describe Gitlab::GitAccess do
it 'does not give access to download code' do
public_project.project_feature.update_attribute(:repository_access_level, ProjectFeature::DISABLED)
- expect { pull_access_check }.to raise_unauthorized('You are not allowed to download code from this project.')
+ expect { pull_access_check }.to raise_unauthorized(described_class::ERROR_MESSAGES[:download])
end
end
end
@@ -321,13 +301,13 @@ describe Gitlab::GitAccess do
context 'from internal project' do
let(:project) { create(:project, :internal, :repository) }
- it { expect { pull_access_check }.to raise_not_found('The project you were looking for could not be found.') }
+ it { expect { pull_access_check }.to raise_not_found }
end
context 'from private project' do
let(:project) { create(:project, :private, :repository) }
- it { expect { pull_access_check }.to raise_not_found('The project you were looking for could not be found.') }
+ it { expect { pull_access_check }.to raise_not_found }
end
end
end
@@ -369,7 +349,7 @@ describe Gitlab::GitAccess do
context 'when is not member of the project' do
context 'pull code' do
- it { expect { pull_access_check }.to raise_unauthorized('You are not allowed to download code from this project.') }
+ it { expect { pull_access_check }.to raise_unauthorized(described_class::ERROR_MESSAGES[:download]) }
end
end
end
@@ -404,7 +384,7 @@ describe Gitlab::GitAccess do
def stub_git_hooks
# Running the `pre-receive` hook is expensive, and not necessary for this test.
- allow_any_instance_of(GitHooksService).to receive(:execute) do |service, &block|
+ allow_any_instance_of(Gitlab::Git::HooksService).to receive(:execute) do |service, &block|
block.call(service)
end
end
@@ -428,28 +408,30 @@ describe Gitlab::GitAccess do
end
end
- # Run permission checks for a user
def self.run_permission_checks(permissions_matrix)
- permissions_matrix.keys.each do |role|
- describe "#{role} access" do
- before do
- if role == :admin
- user.update_attribute(:admin, true)
- else
- project.team << [user, role]
- end
+ permissions_matrix.each_pair do |role, matrix|
+ # Run through the entire matrix for this role in one test to avoid
+ # repeated setup.
+ #
+ # Expectations are given a custom failure message proc so that it's
+ # easier to identify which check(s) failed.
+ it "has the correct permissions for #{role}s" do
+ if role == :admin
+ user.update_attribute(:admin, true)
+ else
+ project.team << [user, role]
end
- permissions_matrix[role].each do |action, allowed|
- context action.to_s do
- subject { access.send(:check_push_access!, changes[action]) }
+ aggregate_failures do
+ matrix.each do |action, allowed|
+ check = -> { access.send(:check_push_access!, changes[action]) }
- it do
- if allowed
- expect { subject }.not_to raise_error
- else
- expect { subject }.to raise_error(Gitlab::GitAccess::UnauthorizedError)
- end
+ if allowed
+ expect(&check).not_to raise_error,
+ -> { "expected #{action} to be allowed" }
+ else
+ expect(&check).to raise_error(Gitlab::GitAccess::UnauthorizedError),
+ -> { "expected #{action} to be disallowed" }
end
end
end
@@ -588,26 +570,26 @@ describe Gitlab::GitAccess do
project.team << [user, :reporter]
end
- it { expect { push_access_check }.to raise_unauthorized('You are not allowed to upload code for this project.') }
+ it { expect { push_access_check }.to raise_unauthorized(described_class::ERROR_MESSAGES[:upload]) }
end
context 'when unauthorized' do
context 'to public project' do
let(:project) { create(:project, :public, :repository) }
- it { expect { push_access_check }.to raise_unauthorized('You are not allowed to upload code for this project.') }
+ it { expect { push_access_check }.to raise_unauthorized(described_class::ERROR_MESSAGES[:upload]) }
end
context 'to internal project' do
let(:project) { create(:project, :internal, :repository) }
- it { expect { push_access_check }.to raise_unauthorized('You are not allowed to upload code for this project.') }
+ it { expect { push_access_check }.to raise_unauthorized(described_class::ERROR_MESSAGES[:upload]) }
end
context 'to private project' do
let(:project) { create(:project, :private, :repository) }
- it { expect { push_access_check }.to raise_not_found('The project you were looking for could not be found.') }
+ it { expect { push_access_check }.to raise_not_found }
end
end
end
@@ -631,19 +613,19 @@ describe Gitlab::GitAccess do
context 'to public project' do
let(:project) { create(:project, :public, :repository) }
- it { expect { push_access_check }.to raise_unauthorized('This deploy key does not have write access to this project.') }
+ it { expect { push_access_check }.to raise_unauthorized(described_class::ERROR_MESSAGES[:deploy_key_upload]) }
end
context 'to internal project' do
let(:project) { create(:project, :internal, :repository) }
- it { expect { push_access_check }.to raise_not_found('The project you were looking for could not be found.') }
+ it { expect { push_access_check }.to raise_not_found }
end
context 'to private project' do
let(:project) { create(:project, :private, :repository) }
- it { expect { push_access_check }.to raise_not_found('The project you were looking for could not be found.') }
+ it { expect { push_access_check }.to raise_not_found }
end
end
end
@@ -656,26 +638,26 @@ describe Gitlab::GitAccess do
key.projects << project
end
- it { expect { push_access_check }.to raise_unauthorized('This deploy key does not have write access to this project.') }
+ it { expect { push_access_check }.to raise_unauthorized(described_class::ERROR_MESSAGES[:deploy_key_upload]) }
end
context 'when unauthorized' do
context 'to public project' do
let(:project) { create(:project, :public, :repository) }
- it { expect { push_access_check }.to raise_unauthorized('This deploy key does not have write access to this project.') }
+ it { expect { push_access_check }.to raise_unauthorized(described_class::ERROR_MESSAGES[:deploy_key_upload]) }
end
context 'to internal project' do
let(:project) { create(:project, :internal, :repository) }
- it { expect { push_access_check }.to raise_not_found('The project you were looking for could not be found.') }
+ it { expect { push_access_check }.to raise_not_found }
end
context 'to private project' do
let(:project) { create(:project, :private, :repository) }
- it { expect { push_access_check }.to raise_not_found('The project you were looking for could not be found.') }
+ it { expect { push_access_check }.to raise_not_found }
end
end
end
@@ -687,8 +669,9 @@ describe Gitlab::GitAccess do
raise_error(Gitlab::GitAccess::UnauthorizedError, message)
end
- def raise_not_found(message)
- raise_error(Gitlab::GitAccess::NotFoundError, message)
+ def raise_not_found
+ raise_error(Gitlab::GitAccess::NotFoundError,
+ Gitlab::GitAccess::ERROR_MESSAGES[:project_not_found])
end
def build_authentication_abilities
diff --git a/spec/lib/gitlab/gitaly_client/commit_service_spec.rb b/spec/lib/gitlab/gitaly_client/commit_service_spec.rb
index 7fe698fcb18..f32fe5d8150 100644
--- a/spec/lib/gitlab/gitaly_client/commit_service_spec.rb
+++ b/spec/lib/gitlab/gitaly_client/commit_service_spec.rb
@@ -111,6 +111,20 @@ describe Gitlab::GitalyClient::CommitService do
client.tree_entries(repository, revision, path)
end
+
+ context 'with UTF-8 params strings' do
+ let(:revision) { "branch\u011F" }
+ let(:path) { "foo/\u011F.txt" }
+
+ it 'handles string encodings correctly' do
+ expect_any_instance_of(Gitaly::CommitService::Stub)
+ .to receive(:get_tree_entries)
+ .with(gitaly_request_with_path(storage_name, relative_path), kind_of(Hash))
+ .and_return([])
+
+ client.tree_entries(repository, revision, path)
+ end
+ end
end
describe '#find_commit' do
@@ -126,4 +140,29 @@ describe Gitlab::GitalyClient::CommitService do
described_class.new(repository).find_commit(revision)
end
end
+
+ describe '#patch' do
+ let(:request) do
+ Gitaly::CommitPatchRequest.new(
+ repository: repository_message, revision: revision
+ )
+ end
+ let(:response) { [double(data: "my "), double(data: "diff")] }
+
+ subject { described_class.new(repository).patch(revision) }
+
+ it 'sends an RPC request' do
+ expect_any_instance_of(Gitaly::DiffService::Stub).to receive(:commit_patch)
+ .with(request, kind_of(Hash)).and_return([])
+
+ subject
+ end
+
+ it 'concatenates the responses data' do
+ allow_any_instance_of(Gitaly::DiffService::Stub).to receive(:commit_patch)
+ .with(request, kind_of(Hash)).and_return(response)
+
+ expect(subject).to eq("my diff")
+ end
+ end
end
diff --git a/spec/lib/gitlab/gitaly_client/ref_service_spec.rb b/spec/lib/gitlab/gitaly_client/ref_service_spec.rb
index 46efc1b18f0..6f59750b4da 100644
--- a/spec/lib/gitlab/gitaly_client/ref_service_spec.rb
+++ b/spec/lib/gitlab/gitaly_client/ref_service_spec.rb
@@ -1,10 +1,11 @@
require 'spec_helper'
describe Gitlab::GitalyClient::RefService do
- let(:project) { create(:project) }
+ let(:project) { create(:project, :repository) }
let(:storage_name) { project.repository_storage }
let(:relative_path) { project.disk_path + '.git' }
- let(:client) { described_class.new(project.repository) }
+ let(:repository) { project.repository }
+ let(:client) { described_class.new(repository) }
describe '#branches' do
it 'sends a find_all_branches message' do
@@ -84,11 +85,23 @@ describe Gitlab::GitalyClient::RefService do
end
describe '#find_ref_name', seed_helper: true do
- let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH) }
- let(:client) { described_class.new(repository) }
subject { client.find_ref_name(SeedRepo::Commit::ID, 'refs/heads/master') }
it { is_expected.to be_utf8 }
it { is_expected.to eq('refs/heads/master') }
end
+
+ describe '#ref_exists?', seed_helper: true do
+ it 'finds the master branch ref' do
+ expect(client.ref_exists?('refs/heads/master')).to eq(true)
+ end
+
+ it 'returns false for an illegal tag name ref' do
+ expect(client.ref_exists?('refs/tags/.this-tag-name-is-illegal')).to eq(false)
+ end
+
+ it 'raises an argument error if the ref name parameter does not start with refs/' do
+ expect { client.ref_exists?('reXXXXX') }.to raise_error(ArgumentError)
+ end
+ end
end
diff --git a/spec/lib/gitlab/import_export/project.json b/spec/lib/gitlab/import_export/project.json
index 4e631e13410..331b7cf2fea 100644
--- a/spec/lib/gitlab/import_export/project.json
+++ b/spec/lib/gitlab/import_export/project.json
@@ -2522,7 +2522,7 @@
"id": 27,
"target_branch": "feature",
"source_branch": "feature_conflict",
- "source_project_id": 5,
+ "source_project_id": 999,
"author_id": 1,
"assignee_id": null,
"title": "MR1",
@@ -2536,6 +2536,9 @@
"position": 0,
"updated_by_id": null,
"merge_error": null,
+ "diff_head_sha": "HEAD",
+ "source_branch_sha": "ABCD",
+ "target_branch_sha": "DCBA",
"merge_params": {
"force_remove_source_branch": null
},
diff --git a/spec/lib/gitlab/import_export/project_tree_restorer_spec.rb b/spec/lib/gitlab/import_export/project_tree_restorer_spec.rb
index 956f1d56eb4..5b16fc5d084 100644
--- a/spec/lib/gitlab/import_export/project_tree_restorer_spec.rb
+++ b/spec/lib/gitlab/import_export/project_tree_restorer_spec.rb
@@ -10,6 +10,13 @@ describe Gitlab::ImportExport::ProjectTreeRestorer do
@shared = Gitlab::ImportExport::Shared.new(relative_path: "", project_path: 'path')
allow(@shared).to receive(:export_path).and_return('spec/lib/gitlab/import_export/')
@project = create(:project, :builds_disabled, :issues_disabled, name: 'project', path: 'project')
+
+ allow(@project.repository).to receive(:fetch_ref).and_return(true)
+ allow(@project.repository.raw).to receive(:rugged_branch_exists?).and_return(false)
+
+ expect_any_instance_of(Gitlab::Git::Repository).to receive(:create_branch).with('feature', 'DCBA')
+ allow_any_instance_of(Gitlab::Git::Repository).to receive(:create_branch)
+
project_tree_restorer = described_class.new(user: @user, shared: @shared, project: @project)
@restored_project_json = project_tree_restorer.restore
end
@@ -79,6 +86,10 @@ describe Gitlab::ImportExport::ProjectTreeRestorer do
expect(event).not_to be_nil
end
+ it 'has the action' do
+ expect(event.action).not_to be_nil
+ end
+
it 'event belongs to note, belongs to merge request, belongs to a project' do
expect(event.note.noteable.project).not_to be_nil
end
diff --git a/spec/lib/gitlab/import_export/project_tree_saver_spec.rb b/spec/lib/gitlab/import_export/project_tree_saver_spec.rb
index a278f89c1a1..065b0ec6658 100644
--- a/spec/lib/gitlab/import_export/project_tree_saver_spec.rb
+++ b/spec/lib/gitlab/import_export/project_tree_saver_spec.rb
@@ -11,6 +11,8 @@ describe Gitlab::ImportExport::ProjectTreeSaver do
before do
project.team << [user, :master]
allow_any_instance_of(Gitlab::ImportExport).to receive(:storage_path).and_return(export_path)
+ allow_any_instance_of(MergeRequest).to receive(:source_branch_sha).and_return('ABCD')
+ allow_any_instance_of(MergeRequest).to receive(:target_branch_sha).and_return('DCBA')
end
after do
@@ -43,6 +45,14 @@ describe Gitlab::ImportExport::ProjectTreeSaver do
expect(saved_project_json['merge_requests'].first['milestone']).not_to be_empty
end
+ it 'has merge request\'s source branch SHA' do
+ expect(saved_project_json['merge_requests'].first['source_branch_sha']).to eq('ABCD')
+ end
+
+ it 'has merge request\'s target branch SHA' do
+ expect(saved_project_json['merge_requests'].first['target_branch_sha']).to eq('DCBA')
+ end
+
it 'has events' do
expect(saved_project_json['merge_requests'].first['milestone']['events']).not_to be_empty
end
diff --git a/spec/lib/gitlab/import_export/repo_restorer_spec.rb b/spec/lib/gitlab/import_export/repo_restorer_spec.rb
index 2786bc92fe5..c49af602a01 100644
--- a/spec/lib/gitlab/import_export/repo_restorer_spec.rb
+++ b/spec/lib/gitlab/import_export/repo_restorer_spec.rb
@@ -34,7 +34,7 @@ describe Gitlab::ImportExport::RepoRestorer do
it 'has the webhooks' do
restorer.restore
- expect(Gitlab::Git::Hook.new('post-receive', project)).to exist
+ expect(Gitlab::Git::Hook.new('post-receive', project.repository.raw_repository)).to exist
end
end
end
diff --git a/spec/lib/gitlab/import_export/safe_model_attributes.yml b/spec/lib/gitlab/import_export/safe_model_attributes.yml
index ae3b0173160..a5e03e149a7 100644
--- a/spec/lib/gitlab/import_export/safe_model_attributes.yml
+++ b/spec/lib/gitlab/import_export/safe_model_attributes.yml
@@ -227,6 +227,8 @@ Ci::Pipeline:
Ci::Stage:
- id
- name
+- status
+- lock_version
- project_id
- pipeline_id
- created_at
diff --git a/spec/lib/gitlab/job_waiter_spec.rb b/spec/lib/gitlab/job_waiter_spec.rb
index 6186cec2689..b0b4fdc09bc 100644
--- a/spec/lib/gitlab/job_waiter_spec.rb
+++ b/spec/lib/gitlab/job_waiter_spec.rb
@@ -1,30 +1,39 @@
require 'spec_helper'
describe Gitlab::JobWaiter do
- describe '#wait' do
- let(:waiter) { described_class.new(%w(a)) }
- it 'returns when all jobs have been completed' do
- expect(Gitlab::SidekiqStatus).to receive(:all_completed?).with(%w(a))
- .and_return(true)
+ describe '.notify' do
+ it 'pushes the jid to the named queue' do
+ key = 'gitlab:job_waiter:foo'
+ jid = 1
- expect(waiter).not_to receive(:sleep)
+ redis = double('redis')
+ expect(Gitlab::Redis::SharedState).to receive(:with).and_yield(redis)
+ expect(redis).to receive(:lpush).with(key, jid)
- waiter.wait
+ described_class.notify(key, jid)
end
+ end
+
+ describe '#wait' do
+ let(:waiter) { described_class.new(2) }
- it 'sleeps between checking the job statuses' do
- expect(Gitlab::SidekiqStatus).to receive(:all_completed?)
- .with(%w(a))
- .and_return(false, true)
+ it 'returns when all jobs have been completed' do
+ described_class.notify(waiter.key, 'a')
+ described_class.notify(waiter.key, 'b')
- expect(waiter).to receive(:sleep).with(described_class::INTERVAL)
+ result = nil
+ expect { Timeout.timeout(1) { result = waiter.wait(2) } }.not_to raise_error
- waiter.wait
+ expect(result).to contain_exactly('a', 'b')
end
- it 'returns when timing out' do
- expect(waiter).not_to receive(:sleep)
- waiter.wait(0)
+ it 'times out if not all jobs complete' do
+ described_class.notify(waiter.key, 'a')
+
+ result = nil
+ expect { Timeout.timeout(2) { result = waiter.wait(1) } }.not_to raise_error
+
+ expect(result).to contain_exactly('a')
end
end
end
diff --git a/spec/lib/gitlab/ldap/adapter_spec.rb b/spec/lib/gitlab/ldap/adapter_spec.rb
index d17d440d833..d9ddb4326be 100644
--- a/spec/lib/gitlab/ldap/adapter_spec.rb
+++ b/spec/lib/gitlab/ldap/adapter_spec.rb
@@ -16,7 +16,7 @@ describe Gitlab::LDAP::Adapter do
expect(adapter).to receive(:ldap_search) do |arg|
expect(arg[:filter].to_s).to eq('(uid=johndoe)')
expect(arg[:base]).to eq('dc=example,dc=com')
- expect(arg[:attributes]).to match(%w{uid cn dn uid userid sAMAccountName mail email userPrincipalName})
+ expect(arg[:attributes]).to match(%w{dn uid cn mail email userPrincipalName})
end.and_return({})
adapter.users('uid', 'johndoe')
@@ -26,7 +26,7 @@ describe Gitlab::LDAP::Adapter do
expect(adapter).to receive(:ldap_search).with(
base: 'uid=johndoe,ou=users,dc=example,dc=com',
scope: Net::LDAP::SearchScope_BaseObject,
- attributes: %w{uid cn dn uid userid sAMAccountName mail email userPrincipalName},
+ attributes: %w{dn uid cn mail email userPrincipalName},
filter: nil
).and_return({})
@@ -63,7 +63,7 @@ describe Gitlab::LDAP::Adapter do
it 'uses the right uid attribute when non-default' do
stub_ldap_config(uid: 'sAMAccountName')
expect(adapter).to receive(:ldap_search).with(
- hash_including(attributes: %w{sAMAccountName cn dn uid userid sAMAccountName mail email userPrincipalName})
+ hash_including(attributes: %w{dn sAMAccountName cn mail email userPrincipalName})
).and_return({})
adapter.users('sAMAccountName', 'johndoe')
diff --git a/spec/lib/gitlab/sidekiq_throttler_spec.rb b/spec/lib/gitlab/sidekiq_throttler_spec.rb
index 6374ac80207..2dbb7bb7c34 100644
--- a/spec/lib/gitlab/sidekiq_throttler_spec.rb
+++ b/spec/lib/gitlab/sidekiq_throttler_spec.rb
@@ -1,28 +1,44 @@
require 'spec_helper'
describe Gitlab::SidekiqThrottler do
- before do
- Sidekiq.options[:concurrency] = 35
-
- stub_application_setting(
- sidekiq_throttling_enabled: true,
- sidekiq_throttling_factor: 0.1,
- sidekiq_throttling_queues: %w[build project_cache]
- )
- end
-
describe '#execute!' do
- it 'sets limits on the selected queues' do
- described_class.execute!
+ context 'when job throttling is enabled' do
+ before do
+ Sidekiq.options[:concurrency] = 35
+
+ stub_application_setting(
+ sidekiq_throttling_enabled: true,
+ sidekiq_throttling_factor: 0.1,
+ sidekiq_throttling_queues: %w[build project_cache]
+ )
+ end
+
+ it 'requires sidekiq-limit_fetch' do
+ expect(described_class).to receive(:require).with('sidekiq-limit_fetch').and_call_original
+
+ described_class.execute!
+ end
+
+ it 'sets limits on the selected queues' do
+ described_class.execute!
+
+ expect(Sidekiq::Queue['build'].limit).to eq 4
+ expect(Sidekiq::Queue['project_cache'].limit).to eq 4
+ end
+
+ it 'does not set limits on other queues' do
+ described_class.execute!
- expect(Sidekiq::Queue['build'].limit).to eq 4
- expect(Sidekiq::Queue['project_cache'].limit).to eq 4
+ expect(Sidekiq::Queue['merge'].limit).to be_nil
+ end
end
- it 'does not set limits on other queues' do
- described_class.execute!
+ context 'when job throttling is disabled' do
+ it 'does not require sidekiq-limit_fetch' do
+ expect(described_class).not_to receive(:require).with('sidekiq-limit_fetch')
- expect(Sidekiq::Queue['merge'].limit).to be_nil
+ described_class.execute!
+ end
end
end
end
diff --git a/spec/migrations/cleanup_namespaceless_pending_delete_projects_spec.rb b/spec/migrations/cleanup_namespaceless_pending_delete_projects_spec.rb
index 12cac1d033d..b47f3314926 100644
--- a/spec/migrations/cleanup_namespaceless_pending_delete_projects_spec.rb
+++ b/spec/migrations/cleanup_namespaceless_pending_delete_projects_spec.rb
@@ -4,7 +4,7 @@ require Rails.root.join('db', 'post_migrate', '20170502101023_cleanup_namespacel
describe CleanupNamespacelessPendingDeleteProjects do
before do
# Stub after_save callbacks that will fail when Project has no namespace
- allow_any_instance_of(Project).to receive(:ensure_storage_path_exist).and_return(nil)
+ allow_any_instance_of(Project).to receive(:ensure_storage_path_exists).and_return(nil)
allow_any_instance_of(Project).to receive(:update_project_statistics).and_return(nil)
end
diff --git a/spec/migrations/cleanup_nonexisting_namespace_pending_delete_projects_spec.rb b/spec/migrations/cleanup_nonexisting_namespace_pending_delete_projects_spec.rb
new file mode 100644
index 00000000000..7879105a334
--- /dev/null
+++ b/spec/migrations/cleanup_nonexisting_namespace_pending_delete_projects_spec.rb
@@ -0,0 +1,32 @@
+require 'spec_helper'
+require Rails.root.join('db', 'post_migrate', '20170816102555_cleanup_nonexisting_namespace_pending_delete_projects.rb')
+
+describe CleanupNonexistingNamespacePendingDeleteProjects do
+ before do
+ # Stub after_save callbacks that will fail when Project has invalid namespace
+ allow_any_instance_of(Project).to receive(:ensure_storage_path_exist).and_return(nil)
+ allow_any_instance_of(Project).to receive(:update_project_statistics).and_return(nil)
+ end
+
+ describe '#up' do
+ set(:some_project) { create(:project) }
+
+ it 'only cleans up when namespace does not exist' do
+ create(:project, pending_delete: true)
+ project = build(:project, pending_delete: true, namespace: nil, namespace_id: Namespace.maximum(:id).to_i.succ)
+ project.save(validate: false)
+
+ expect(NamespacelessProjectDestroyWorker).to receive(:bulk_perform_async).with([[project.id]])
+
+ described_class.new.up
+ end
+
+ it 'does nothing when no pending delete projects without namespace found' do
+ create(:project, pending_delete: true, namespace: create(:namespace))
+
+ expect(NamespacelessProjectDestroyWorker).not_to receive(:bulk_perform_async)
+
+ described_class.new.up
+ end
+ end
+end
diff --git a/spec/migrations/migrate_pipeline_sidekiq_queues_spec.rb b/spec/migrations/migrate_pipeline_sidekiq_queues_spec.rb
new file mode 100644
index 00000000000..e02bcd2f4da
--- /dev/null
+++ b/spec/migrations/migrate_pipeline_sidekiq_queues_spec.rb
@@ -0,0 +1,55 @@
+require 'spec_helper'
+require Rails.root.join('db', 'post_migrate', '20170822101017_migrate_pipeline_sidekiq_queues.rb')
+
+describe MigratePipelineSidekiqQueues, :sidekiq, :redis do
+ include Gitlab::Database::MigrationHelpers
+
+ context 'when there are jobs in the queues' do
+ it 'correctly migrates queue when migrating up' do
+ Sidekiq::Testing.disable! do
+ stubbed_worker(queue: :pipeline).perform_async('Something', [1])
+ stubbed_worker(queue: :build).perform_async('Something', [1])
+
+ described_class.new.up
+
+ expect(sidekiq_queue_length('pipeline')).to eq 0
+ expect(sidekiq_queue_length('build')).to eq 0
+ expect(sidekiq_queue_length('pipeline_default')).to eq 2
+ end
+ end
+
+ it 'correctly migrates queue when migrating down' do
+ Sidekiq::Testing.disable! do
+ stubbed_worker(queue: :pipeline_default).perform_async('Class', [1])
+ stubbed_worker(queue: :pipeline_processing).perform_async('Class', [2])
+ stubbed_worker(queue: :pipeline_hooks).perform_async('Class', [3])
+ stubbed_worker(queue: :pipeline_cache).perform_async('Class', [4])
+
+ described_class.new.down
+
+ expect(sidekiq_queue_length('pipeline')).to eq 4
+ expect(sidekiq_queue_length('pipeline_default')).to eq 0
+ expect(sidekiq_queue_length('pipeline_processing')).to eq 0
+ expect(sidekiq_queue_length('pipeline_hooks')).to eq 0
+ expect(sidekiq_queue_length('pipeline_cache')).to eq 0
+ end
+ end
+ end
+
+ context 'when there are no jobs in the queues' do
+ it 'does not raise error when migrating up' do
+ expect { described_class.new.up }.not_to raise_error
+ end
+
+ it 'does not raise error when migrating down' do
+ expect { described_class.new.down }.not_to raise_error
+ end
+ end
+
+ def stubbed_worker(queue:)
+ Class.new do
+ include Sidekiq::Worker
+ sidekiq_options queue: queue
+ end
+ end
+end
diff --git a/spec/migrations/migrate_stage_id_reference_in_background_spec.rb b/spec/migrations/migrate_stage_id_reference_in_background_spec.rb
index 260378adaa7..9b92f4b70b0 100644
--- a/spec/migrations/migrate_stage_id_reference_in_background_spec.rb
+++ b/spec/migrations/migrate_stage_id_reference_in_background_spec.rb
@@ -2,19 +2,6 @@ require 'spec_helper'
require Rails.root.join('db', 'post_migrate', '20170628080858_migrate_stage_id_reference_in_background')
describe MigrateStageIdReferenceInBackground, :migration, :sidekiq do
- matcher :be_scheduled_migration do |delay, *expected|
- match do |migration|
- BackgroundMigrationWorker.jobs.any? do |job|
- job['args'] == [migration, expected] &&
- job['at'].to_i == (delay.to_i + Time.now.to_i)
- end
- end
-
- failure_message do |migration|
- "Migration `#{migration}` with args `#{expected.inspect}` not scheduled!"
- end
- end
-
let(:jobs) { table(:ci_builds) }
let(:stages) { table(:ci_stages) }
let(:pipelines) { table(:ci_pipelines) }
diff --git a/spec/migrations/migrate_stages_statuses_spec.rb b/spec/migrations/migrate_stages_statuses_spec.rb
new file mode 100644
index 00000000000..094c9bc604e
--- /dev/null
+++ b/spec/migrations/migrate_stages_statuses_spec.rb
@@ -0,0 +1,68 @@
+require 'spec_helper'
+require Rails.root.join('db', 'post_migrate', '20170711145558_migrate_stages_statuses.rb')
+
+describe MigrateStagesStatuses, :migration do
+ let(:jobs) { table(:ci_builds) }
+ let(:stages) { table(:ci_stages) }
+ let(:pipelines) { table(:ci_pipelines) }
+ let(:projects) { table(:projects) }
+
+ STATUSES = { created: 0, pending: 1, running: 2, success: 3,
+ failed: 4, canceled: 5, skipped: 6, manual: 7 }.freeze
+
+ before do
+ stub_const("#{described_class.name}::BATCH_SIZE", 2)
+ stub_const("#{described_class.name}::RANGE_SIZE", 1)
+
+ projects.create!(id: 1, name: 'gitlab1', path: 'gitlab1')
+ projects.create!(id: 2, name: 'gitlab2', path: 'gitlab2')
+
+ pipelines.create!(id: 1, project_id: 1, ref: 'master', sha: 'adf43c3a')
+ pipelines.create!(id: 2, project_id: 2, ref: 'feature', sha: '21a3deb')
+
+ create_job(project: 1, pipeline: 1, stage: 'test', status: 'success')
+ create_job(project: 1, pipeline: 1, stage: 'test', status: 'running')
+ create_job(project: 1, pipeline: 1, stage: 'build', status: 'success')
+ create_job(project: 1, pipeline: 1, stage: 'build', status: 'failed')
+ create_job(project: 2, pipeline: 2, stage: 'test', status: 'success')
+ create_job(project: 2, pipeline: 2, stage: 'test', status: 'success')
+ create_job(project: 2, pipeline: 2, stage: 'test', status: 'failed', retried: true)
+
+ stages.create!(id: 1, pipeline_id: 1, project_id: 1, name: 'test', status: nil)
+ stages.create!(id: 2, pipeline_id: 1, project_id: 1, name: 'build', status: nil)
+ stages.create!(id: 3, pipeline_id: 2, project_id: 2, name: 'test', status: nil)
+ end
+
+ it 'correctly migrates stages statuses' do
+ Sidekiq::Testing.inline! do
+ expect(stages.where(status: nil).count).to eq 3
+
+ migrate!
+
+ expect(stages.where(status: nil)).to be_empty
+ expect(stages.all.order('id ASC').pluck(:status))
+ .to eq [STATUSES[:running], STATUSES[:failed], STATUSES[:success]]
+ end
+ end
+
+ it 'correctly schedules background migrations' do
+ Sidekiq::Testing.fake! do
+ Timecop.freeze do
+ migrate!
+
+ expect(described_class::MIGRATION).to be_scheduled_migration(5.minutes, 1, 1)
+ expect(described_class::MIGRATION).to be_scheduled_migration(5.minutes, 2, 2)
+ expect(described_class::MIGRATION).to be_scheduled_migration(10.minutes, 3, 3)
+ expect(BackgroundMigrationWorker.jobs.size).to eq 3
+ end
+ end
+ end
+
+ def create_job(project:, pipeline:, stage:, status:, **opts)
+ stages = { test: 1, build: 2, deploy: 3 }
+
+ jobs.create!(project_id: project, commit_id: pipeline,
+ stage_idx: stages[stage.to_sym], stage: stage,
+ status: status, **opts)
+ end
+end
diff --git a/spec/migrations/remove_dot_git_from_usernames_spec.rb b/spec/migrations/remove_dot_git_from_usernames_spec.rb
index 8737e00eaeb..129374cb38c 100644
--- a/spec/migrations/remove_dot_git_from_usernames_spec.rb
+++ b/spec/migrations/remove_dot_git_from_usernames_spec.rb
@@ -51,7 +51,6 @@ describe RemoveDotGitFromUsernames do
namespace.path = path
namespace.save!(validate: false)
- user.username = path
- user.save!(validate: false)
+ user.update_column(:username, path)
end
end
diff --git a/spec/models/broadcast_message_spec.rb b/spec/models/broadcast_message_spec.rb
index 3369aef1d3e..461e754dc1f 100644
--- a/spec/models/broadcast_message_spec.rb
+++ b/spec/models/broadcast_message_spec.rb
@@ -53,6 +53,29 @@ describe BroadcastMessage do
2.times { described_class.current }
end
+
+ it 'includes messages that need to be displayed in the future' do
+ create(:broadcast_message)
+
+ future = create(
+ :broadcast_message,
+ starts_at: Time.now + 10.minutes,
+ ends_at: Time.now + 20.minutes
+ )
+
+ expect(described_class.current.length).to eq(1)
+
+ Timecop.travel(future.starts_at) do
+ expect(described_class.current.length).to eq(2)
+ end
+ end
+
+ it 'does not clear the cache if only a future message should be displayed' do
+ create(:broadcast_message, :future)
+
+ expect(Rails.cache).not_to receive(:delete)
+ expect(described_class.current.length).to eq(0)
+ end
end
describe '#active?' do
diff --git a/spec/models/ci/build_spec.rb b/spec/models/ci/build_spec.rb
index 767f0ad9e65..4f77f0d85cd 100644
--- a/spec/models/ci/build_spec.rb
+++ b/spec/models/ci/build_spec.rb
@@ -21,6 +21,16 @@ describe Ci::Build do
it { is_expected.to respond_to(:has_trace?) }
it { is_expected.to respond_to(:trace) }
+ describe 'callbacks' do
+ context 'when running after_create callback' do
+ it 'triggers asynchronous build hooks worker' do
+ expect(BuildHooksWorker).to receive(:perform_async)
+
+ create(:ci_build)
+ end
+ end
+ end
+
describe '.manual_actions' do
let!(:manual_but_created) { create(:ci_build, :manual, status: :created, pipeline: pipeline) }
let!(:manual_but_succeeded) { create(:ci_build, :manual, status: :success, pipeline: pipeline) }
diff --git a/spec/models/ci/pipeline_spec.rb b/spec/models/ci/pipeline_spec.rb
index ac75c6501ee..b84e3ff18e8 100644
--- a/spec/models/ci/pipeline_spec.rb
+++ b/spec/models/ci/pipeline_spec.rb
@@ -2,7 +2,7 @@ require 'spec_helper'
describe Ci::Pipeline, :mailer do
let(:user) { create(:user) }
- let(:project) { create(:project) }
+ set(:project) { create(:project) }
let(:pipeline) do
create(:ci_empty_pipeline, status: :created, project: project)
@@ -159,6 +159,18 @@ describe Ci::Pipeline, :mailer do
end
end
+ describe '#predefined_variables' do
+ subject { pipeline.predefined_variables }
+
+ it { is_expected.to be_an(Array) }
+
+ it 'includes the defined keys' do
+ keys = subject.map { |v| v[:key] }
+
+ expect(keys).to include('CI_PIPELINE_ID', 'CI_CONFIG_PATH', 'CI_PIPELINE_SOURCE')
+ end
+ end
+
describe '#auto_canceled?' do
subject { pipeline.auto_canceled? }
diff --git a/spec/models/ci/stage_spec.rb b/spec/models/ci/stage_spec.rb
new file mode 100644
index 00000000000..586d073eb5e
--- /dev/null
+++ b/spec/models/ci/stage_spec.rb
@@ -0,0 +1,90 @@
+require 'spec_helper'
+
+describe Ci::Stage, :models do
+ let(:stage) { create(:ci_stage_entity) }
+
+ describe 'associations' do
+ before do
+ create(:ci_build, stage_id: stage.id)
+ create(:commit_status, stage_id: stage.id)
+ end
+
+ describe '#statuses' do
+ it 'returns all commit statuses' do
+ expect(stage.statuses.count).to be 2
+ end
+ end
+
+ describe '#builds' do
+ it 'returns only builds' do
+ expect(stage.builds).to be_one
+ end
+ end
+ end
+
+ describe '#status' do
+ context 'when stage is pending' do
+ let(:stage) { create(:ci_stage_entity, status: 'pending') }
+
+ it 'has a correct status value' do
+ expect(stage.status).to eq 'pending'
+ end
+ end
+
+ context 'when stage is success' do
+ let(:stage) { create(:ci_stage_entity, status: 'success') }
+
+ it 'has a correct status value' do
+ expect(stage.status).to eq 'success'
+ end
+ end
+
+ context 'when stage status is not defined' do
+ before do
+ stage.update_column(:status, nil)
+ end
+
+ it 'sets the default value' do
+ expect(described_class.find(stage.id).status)
+ .to eq 'created'
+ end
+ end
+ end
+
+ describe 'update_status' do
+ context 'when stage objects needs to be updated' do
+ before do
+ create(:ci_build, :success, stage_id: stage.id)
+ create(:ci_build, :running, stage_id: stage.id)
+ end
+
+ it 'updates stage status correctly' do
+ expect { stage.update_status }
+ .to change { stage.reload.status }
+ .to 'running'
+ end
+ end
+
+ context 'when stage is skipped' do
+ it 'updates status to skipped' do
+ expect { stage.update_status }
+ .to change { stage.reload.status }
+ .to 'skipped'
+ end
+ end
+
+ context 'when stage object is locked' do
+ before do
+ create(:ci_build, :failed, stage_id: stage.id)
+ end
+
+ it 'retries a lock to update a stage status' do
+ stage.lock_version = 100
+
+ stage.update_status
+
+ expect(stage.reload).to be_failed
+ end
+ end
+ end
+end
diff --git a/spec/models/commit_status_spec.rb b/spec/models/commit_status_spec.rb
index 8c4a366ef8f..f7583645e69 100644
--- a/spec/models/commit_status_spec.rb
+++ b/spec/models/commit_status_spec.rb
@@ -7,10 +7,10 @@ describe CommitStatus do
create(:ci_pipeline, project: project, sha: project.commit.id)
end
- let(:commit_status) { create_status }
+ let(:commit_status) { create_status(stage: 'test') }
- def create_status(args = {})
- create(:commit_status, args.merge(pipeline: pipeline))
+ def create_status(**opts)
+ create(:commit_status, pipeline: pipeline, **opts)
end
it { is_expected.to belong_to(:pipeline) }
diff --git a/spec/models/concerns/awardable_spec.rb b/spec/models/concerns/awardable_spec.rb
index 63ad3a3630b..34f923d3f0c 100644
--- a/spec/models/concerns/awardable_spec.rb
+++ b/spec/models/concerns/awardable_spec.rb
@@ -12,17 +12,25 @@ describe Awardable do
describe "ClassMethods" do
let!(:issue2) { create(:issue) }
+ let!(:award_emoji2) { create(:award_emoji, awardable: issue2) }
- before do
- create(:award_emoji, awardable: issue2)
- end
+ describe "orders" do
+ it "orders on upvotes" do
+ expect(Issue.order_upvotes_desc.to_a).to eq [issue2, issue]
+ end
- it "orders on upvotes" do
- expect(Issue.order_upvotes_desc.to_a).to eq [issue2, issue]
+ it "orders on downvotes" do
+ expect(Issue.order_downvotes_desc.to_a).to eq [issue, issue2]
+ end
end
- it "orders on downvotes" do
- expect(Issue.order_downvotes_desc.to_a).to eq [issue, issue2]
+ describe ".awarded" do
+ it "filters by user and emoji name" do
+ expect(Issue.awarded(award_emoji.user, "thumbsup")).to be_empty
+ expect(Issue.awarded(award_emoji.user, "thumbsdown")).to eq [issue]
+ expect(Issue.awarded(award_emoji2.user, "thumbsup")).to eq [issue2]
+ expect(Issue.awarded(award_emoji2.user, "thumbsdown")).to be_empty
+ end
end
end
diff --git a/spec/models/concerns/editable_spec.rb b/spec/models/concerns/editable_spec.rb
index cd73af3b480..49a9a8ebcbc 100644
--- a/spec/models/concerns/editable_spec.rb
+++ b/spec/models/concerns/editable_spec.rb
@@ -1,11 +1,11 @@
require 'spec_helper'
describe Editable do
- describe '#is_edited?' do
+ describe '#edited?' do
let(:issue) { create(:issue, last_edited_at: nil) }
let(:edited_issue) { create(:issue, created_at: 3.days.ago, last_edited_at: 2.days.ago) }
- it { expect(issue.is_edited?).to eq(false) }
- it { expect(edited_issue.is_edited?).to eq(true) }
+ it { expect(issue.edited?).to eq(false) }
+ it { expect(edited_issue.edited?).to eq(true) }
end
end
diff --git a/spec/models/event_spec.rb b/spec/models/event_spec.rb
index ff3224dd298..f55c161c821 100644
--- a/spec/models/event_spec.rb
+++ b/spec/models/event_spec.rb
@@ -304,6 +304,50 @@ describe Event do
end
end
+ describe '#body?' do
+ let(:push_event) do
+ event = build(:push_event)
+
+ allow(event).to receive(:push?).and_return(true)
+
+ event
+ end
+
+ it 'returns true for a push event with commits' do
+ allow(push_event).to receive(:push_with_commits?).and_return(true)
+
+ expect(push_event).to be_body
+ end
+
+ it 'returns false for a push event without a valid commit range' do
+ allow(push_event).to receive(:push_with_commits?).and_return(false)
+
+ expect(push_event).not_to be_body
+ end
+
+ it 'returns true for a Note event' do
+ event = build(:event)
+
+ allow(event).to receive(:note?).and_return(true)
+
+ expect(event).to be_body
+ end
+
+ it 'returns true if the target responds to #title' do
+ event = build(:event)
+
+ allow(event).to receive(:target).and_return(double(:target, title: 'foo'))
+
+ expect(event).to be_body
+ end
+
+ it 'returns false for a regular event without a target' do
+ event = build(:event)
+
+ expect(event).not_to be_body
+ end
+ end
+
def create_push_event(project, user)
event = create(:push_event, project: project, author: user)
diff --git a/spec/models/issue_spec.rb b/spec/models/issue_spec.rb
index 9203f6562f2..de86788d142 100644
--- a/spec/models/issue_spec.rb
+++ b/spec/models/issue_spec.rb
@@ -751,4 +751,22 @@ describe Issue do
end
end
end
+
+ describe 'removing an issue' do
+ it 'refreshes the number of open issues of the project' do
+ project = subject.project
+
+ expect { subject.destroy }
+ .to change { project.open_issues_count }.from(1).to(0)
+ end
+ end
+
+ describe '.public_only' do
+ it 'only returns public issues' do
+ public_issue = create(:issue)
+ create(:issue, confidential: true)
+
+ expect(described_class.public_only).to eq([public_issue])
+ end
+ end
end
diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb
index 026bdbd26d1..92cf15a5a51 100644
--- a/spec/models/merge_request_spec.rb
+++ b/spec/models/merge_request_spec.rb
@@ -604,7 +604,7 @@ describe MergeRequest do
request = build_stubbed(:merge_request)
expect(request.merge_commit_message)
- .to match("See merge request #{request.to_reference}")
+ .to match("See merge request #{request.to_reference(full: true)}")
end
it 'excludes multiple linebreak runs when description is blank' do
@@ -931,6 +931,23 @@ describe MergeRequest do
end
end
+ describe '#merge_async' do
+ it 'enqueues MergeWorker job and updates merge_jid' do
+ merge_request = create(:merge_request)
+ user_id = double(:user_id)
+ params = double(:params)
+ merge_jid = 'hash-123'
+
+ expect(MergeWorker).to receive(:perform_async).with(merge_request.id, user_id, params) do
+ merge_jid
+ end
+
+ merge_request.merge_async(user_id, params)
+
+ expect(merge_request.reload.merge_jid).to eq(merge_jid)
+ end
+ end
+
describe '#check_if_can_be_merged' do
let(:project) { create(:project, only_allow_merge_if_pipeline_succeeds: true) }
@@ -1370,29 +1387,11 @@ describe MergeRequest do
end
describe '#merge_ongoing?' do
- it 'returns true when merge process is ongoing for merge_jid' do
- merge_request = create(:merge_request, merge_jid: 'foo')
-
- allow(Gitlab::SidekiqStatus).to receive(:num_running).with(['foo']).and_return(1)
+ it 'returns true when merge_id is present and MR is not merged' do
+ merge_request = build_stubbed(:merge_request, state: :open, merge_jid: 'foo')
expect(merge_request.merge_ongoing?).to be(true)
end
-
- it 'returns false when no merge process running for merge_jid' do
- merge_request = build(:merge_request, merge_jid: 'foo')
-
- allow(Gitlab::SidekiqStatus).to receive(:num_running).with(['foo']).and_return(0)
-
- expect(merge_request.merge_ongoing?).to be(false)
- end
-
- it 'returns false when merge_jid is nil' do
- merge_request = build(:merge_request, merge_jid: nil)
-
- expect(Gitlab::SidekiqStatus).not_to receive(:num_running)
-
- expect(merge_request.merge_ongoing?).to be(false)
- end
end
describe "#closed_without_fork?" do
@@ -1692,4 +1691,13 @@ describe MergeRequest do
expect(subject.ref_fetched?).to be_falsey
end
end
+
+ describe 'removing a merge request' do
+ it 'refreshes the number of open merge requests of the target project' do
+ project = subject.target_project
+
+ expect { subject.destroy }
+ .to change { project.open_merge_requests_count }.from(1).to(0)
+ end
+ end
end
diff --git a/spec/models/project_services/kubernetes_service_spec.rb b/spec/models/project_services/kubernetes_service_spec.rb
index 55b96a0c12e..b1743cd608e 100644
--- a/spec/models/project_services/kubernetes_service_spec.rb
+++ b/spec/models/project_services/kubernetes_service_spec.rb
@@ -38,7 +38,8 @@ describe KubernetesService, :use_clean_rails_memory_store_caching do
'a' * 63 => true,
'a' * 64 => false,
'a.b' => false,
- 'a*b' => false
+ 'a*b' => false,
+ 'FOO' => true
}.each do |namespace, validity|
it "validates #{namespace} as #{validity ? 'valid' : 'invalid'}" do
subject.namespace = namespace
diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb
index 5e60511f3a8..2e613c44357 100644
--- a/spec/models/project_spec.rb
+++ b/spec/models/project_spec.rb
@@ -1251,60 +1251,6 @@ describe Project do
end
end
- describe '#rename_repo' do
- let(:project) { create(:project, :repository) }
- let(:gitlab_shell) { Gitlab::Shell.new }
-
- before do
- # Project#gitlab_shell returns a new instance of Gitlab::Shell on every
- # call. This makes testing a bit easier.
- allow(project).to receive(:gitlab_shell).and_return(gitlab_shell)
- allow(project).to receive(:previous_changes).and_return('path' => ['foo'])
- end
-
- it 'renames a repository' do
- stub_container_registry_config(enabled: false)
-
- expect(gitlab_shell).to receive(:mv_repository)
- .ordered
- .with(project.repository_storage_path, "#{project.namespace.full_path}/foo", "#{project.full_path}")
- .and_return(true)
-
- expect(gitlab_shell).to receive(:mv_repository)
- .ordered
- .with(project.repository_storage_path, "#{project.namespace.full_path}/foo.wiki", "#{project.full_path}.wiki")
- .and_return(true)
-
- expect_any_instance_of(SystemHooksService)
- .to receive(:execute_hooks_for)
- .with(project, :rename)
-
- expect_any_instance_of(Gitlab::UploadsTransfer)
- .to receive(:rename_project)
- .with('foo', project.path, project.namespace.full_path)
-
- expect(project).to receive(:expire_caches_before_rename)
-
- expect(project).to receive(:expires_full_path_cache)
-
- project.rename_repo
- end
-
- context 'container registry with images' do
- let(:container_repository) { create(:container_repository) }
-
- before do
- stub_container_registry_config(enabled: true)
- stub_container_registry_tags(repository: :any, tags: ['tag'])
- project.container_repositories << container_repository
- end
-
- subject { project.rename_repo }
-
- it { expect {subject}.to raise_error(StandardError) }
- end
- end
-
describe '#expire_caches_before_rename' do
let(:project) { create(:project, :repository) }
let(:repo) { double(:repo, exists?: true) }
@@ -2367,4 +2313,181 @@ describe Project do
expect(project.forks_count).to eq(1)
end
end
+
+ context 'legacy storage' do
+ let(:project) { create(:project, :repository) }
+ let(:gitlab_shell) { Gitlab::Shell.new }
+
+ before do
+ allow(project).to receive(:gitlab_shell).and_return(gitlab_shell)
+ end
+
+ describe '#base_dir' do
+ it 'returns base_dir based on namespace only' do
+ expect(project.base_dir).to eq(project.namespace.full_path)
+ end
+ end
+
+ describe '#disk_path' do
+ it 'returns disk_path based on namespace and project path' do
+ expect(project.disk_path).to eq("#{project.namespace.full_path}/#{project.path}")
+ end
+ end
+
+ describe '#ensure_storage_path_exists' do
+ it 'delegates to gitlab_shell to ensure namespace is created' do
+ expect(gitlab_shell).to receive(:add_namespace).with(project.repository_storage_path, project.base_dir)
+
+ project.ensure_storage_path_exists
+ end
+ end
+
+ describe '#legacy_storage?' do
+ it 'returns true when storage_version is nil' do
+ project = build(:project)
+
+ expect(project.legacy_storage?).to be_truthy
+ end
+ end
+
+ describe '#rename_repo' do
+ before do
+ # Project#gitlab_shell returns a new instance of Gitlab::Shell on every
+ # call. This makes testing a bit easier.
+ allow(project).to receive(:gitlab_shell).and_return(gitlab_shell)
+ allow(project).to receive(:previous_changes).and_return('path' => ['foo'])
+ end
+
+ it 'renames a repository' do
+ stub_container_registry_config(enabled: false)
+
+ expect(gitlab_shell).to receive(:mv_repository)
+ .ordered
+ .with(project.repository_storage_path, "#{project.namespace.full_path}/foo", "#{project.full_path}")
+ .and_return(true)
+
+ expect(gitlab_shell).to receive(:mv_repository)
+ .ordered
+ .with(project.repository_storage_path, "#{project.namespace.full_path}/foo.wiki", "#{project.full_path}.wiki")
+ .and_return(true)
+
+ expect_any_instance_of(SystemHooksService)
+ .to receive(:execute_hooks_for)
+ .with(project, :rename)
+
+ expect_any_instance_of(Gitlab::UploadsTransfer)
+ .to receive(:rename_project)
+ .with('foo', project.path, project.namespace.full_path)
+
+ expect(project).to receive(:expire_caches_before_rename)
+
+ expect(project).to receive(:expires_full_path_cache)
+
+ project.rename_repo
+ end
+
+ context 'container registry with images' do
+ let(:container_repository) { create(:container_repository) }
+
+ before do
+ stub_container_registry_config(enabled: true)
+ stub_container_registry_tags(repository: :any, tags: ['tag'])
+ project.container_repositories << container_repository
+ end
+
+ subject { project.rename_repo }
+
+ it { expect { subject }.to raise_error(StandardError) }
+ end
+ end
+
+ describe '#pages_path' do
+ it 'returns a path where pages are stored' do
+ expect(project.pages_path).to eq(File.join(Settings.pages.path, project.namespace.full_path, project.path))
+ end
+ end
+ end
+
+ context 'hashed storage' do
+ let(:project) { create(:project, :repository) }
+ let(:gitlab_shell) { Gitlab::Shell.new }
+ let(:hash) { '6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b' }
+
+ before do
+ stub_application_setting(hashed_storage_enabled: true)
+ allow(Digest::SHA2).to receive(:hexdigest) { hash }
+ allow(project).to receive(:gitlab_shell).and_return(gitlab_shell)
+ end
+
+ describe '#base_dir' do
+ it 'returns base_dir based on hash of project id' do
+ expect(project.base_dir).to eq('@hashed/6b/86')
+ end
+ end
+
+ describe '#disk_path' do
+ it 'returns disk_path based on hash of project id' do
+ hashed_path = '@hashed/6b/86/6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b'
+
+ expect(project.disk_path).to eq(hashed_path)
+ end
+ end
+
+ describe '#ensure_storage_path_exists' do
+ it 'delegates to gitlab_shell to ensure namespace is created' do
+ expect(gitlab_shell).to receive(:add_namespace).with(project.repository_storage_path, '@hashed/6b/86')
+
+ project.ensure_storage_path_exists
+ end
+ end
+
+ describe '#rename_repo' do
+ before do
+ # Project#gitlab_shell returns a new instance of Gitlab::Shell on every
+ # call. This makes testing a bit easier.
+ allow(project).to receive(:gitlab_shell).and_return(gitlab_shell)
+ allow(project).to receive(:previous_changes).and_return('path' => ['foo'])
+ end
+
+ it 'renames a repository' do
+ stub_container_registry_config(enabled: false)
+
+ expect(gitlab_shell).not_to receive(:mv_repository)
+
+ expect_any_instance_of(SystemHooksService)
+ .to receive(:execute_hooks_for)
+ .with(project, :rename)
+
+ expect_any_instance_of(Gitlab::UploadsTransfer)
+ .to receive(:rename_project)
+ .with('foo', project.path, project.namespace.full_path)
+
+ expect(project).to receive(:expire_caches_before_rename)
+
+ expect(project).to receive(:expires_full_path_cache)
+
+ project.rename_repo
+ end
+
+ context 'container registry with images' do
+ let(:container_repository) { create(:container_repository) }
+
+ before do
+ stub_container_registry_config(enabled: true)
+ stub_container_registry_tags(repository: :any, tags: ['tag'])
+ project.container_repositories << container_repository
+ end
+
+ subject { project.rename_repo }
+
+ it { expect { subject }.to raise_error(StandardError) }
+ end
+ end
+
+ describe '#pages_path' do
+ it 'returns a path where pages are stored' do
+ expect(project.pages_path).to eq(File.join(Settings.pages.path, project.namespace.full_path, project.path))
+ end
+ end
+ end
end
diff --git a/spec/models/repository_spec.rb b/spec/models/repository_spec.rb
index 4926d5d6c49..3151649b64e 100644
--- a/spec/models/repository_spec.rb
+++ b/spec/models/repository_spec.rb
@@ -8,6 +8,7 @@ describe Repository, models: true do
let(:repository) { project.repository }
let(:broken_repository) { create(:project, :broken_storage).repository }
let(:user) { create(:user) }
+ let(:committer) { Gitlab::Git::Committer.from_user(user) }
let(:commit_options) do
author = repository.user_to_committer(user)
@@ -846,7 +847,7 @@ describe Repository, models: true do
expect do
repository.add_branch(user, 'new_feature', 'master')
- end.to raise_error(GitHooksService::PreReceiveError)
+ end.to raise_error(Gitlab::Git::HooksService::PreReceiveError)
end
it 'does not create the branch' do
@@ -854,7 +855,7 @@ describe Repository, models: true do
expect do
repository.add_branch(user, 'new_feature', 'master')
- end.to raise_error(GitHooksService::PreReceiveError)
+ end.to raise_error(Gitlab::Git::HooksService::PreReceiveError)
expect(repository.find_branch('new_feature')).to be_nil
end
end
@@ -884,8 +885,8 @@ describe Repository, models: true do
context 'when pre hooks were successful' do
it 'runs without errors' do
- expect_any_instance_of(GitHooksService).to receive(:execute)
- .with(user, project, old_rev, blank_sha, 'refs/heads/feature')
+ expect_any_instance_of(Gitlab::Git::HooksService).to receive(:execute)
+ .with(committer, repository, old_rev, blank_sha, 'refs/heads/feature')
expect { repository.rm_branch(user, 'feature') }.not_to raise_error
end
@@ -905,7 +906,7 @@ describe Repository, models: true do
expect do
repository.rm_branch(user, 'feature')
- end.to raise_error(GitHooksService::PreReceiveError)
+ end.to raise_error(Gitlab::Git::HooksService::PreReceiveError)
end
it 'does not delete the branch' do
@@ -913,7 +914,7 @@ describe Repository, models: true do
expect do
repository.rm_branch(user, 'feature')
- end.to raise_error(GitHooksService::PreReceiveError)
+ end.to raise_error(Gitlab::Git::HooksService::PreReceiveError)
expect(repository.find_branch('feature')).not_to be_nil
end
end
@@ -925,23 +926,23 @@ describe Repository, models: true do
context 'when pre hooks were successful' do
before do
- service = GitHooksService.new
- expect(GitHooksService).to receive(:new).and_return(service)
+ service = Gitlab::Git::HooksService.new
+ expect(Gitlab::Git::HooksService).to receive(:new).and_return(service)
expect(service).to receive(:execute)
- .with(user, project, old_rev, new_rev, 'refs/heads/feature')
+ .with(committer, repository, old_rev, new_rev, 'refs/heads/feature')
.and_yield(service).and_return(true)
end
it 'runs without errors' do
expect do
- GitOperationService.new(user, repository).with_branch('feature') do
+ GitOperationService.new(committer, repository).with_branch('feature') do
new_rev
end
end.not_to raise_error
end
it 'ensures the autocrlf Git option is set to :input' do
- service = GitOperationService.new(user, repository)
+ service = GitOperationService.new(committer, repository)
expect(service).to receive(:update_autocrlf_option)
@@ -952,7 +953,7 @@ describe Repository, models: true do
it 'updates the head' do
expect(repository.find_branch('feature').dereferenced_target.id).to eq(old_rev)
- GitOperationService.new(user, repository).with_branch('feature') do
+ GitOperationService.new(committer, repository).with_branch('feature') do
new_rev
end
@@ -974,7 +975,7 @@ describe Repository, models: true do
end
expect do
- GitOperationService.new(user, target_project.repository)
+ GitOperationService.new(committer, target_project.repository)
.with_branch('feature',
start_project: project,
&:itself)
@@ -996,7 +997,7 @@ describe Repository, models: true do
repository.add_branch(user, branch, old_rev)
expect do
- GitOperationService.new(user, repository).with_branch(branch) do
+ GitOperationService.new(committer, repository).with_branch(branch) do
new_rev
end
end.not_to raise_error
@@ -1014,7 +1015,7 @@ describe Repository, models: true do
# Updating 'master' to new_rev would lose the commits on 'master' that
# are not contained in new_rev. This should not be allowed.
expect do
- GitOperationService.new(user, repository).with_branch(branch) do
+ GitOperationService.new(committer, repository).with_branch(branch) do
new_rev
end
end.to raise_error(Repository::CommitError)
@@ -1026,10 +1027,10 @@ describe Repository, models: true do
allow_any_instance_of(Gitlab::Git::Hook).to receive(:trigger).and_return([false, ''])
expect do
- GitOperationService.new(user, repository).with_branch('feature') do
+ GitOperationService.new(committer, repository).with_branch('feature') do
new_rev
end
- end.to raise_error(GitHooksService::PreReceiveError)
+ end.to raise_error(Gitlab::Git::HooksService::PreReceiveError)
end
end
@@ -1044,7 +1045,7 @@ describe Repository, models: true do
expect(repository).not_to receive(:expire_emptiness_caches)
expect(repository).to receive(:expire_branches_cache)
- GitOperationService.new(user, repository)
+ GitOperationService.new(committer, repository)
.with_branch('new-feature') do
new_rev
end
@@ -2035,23 +2036,23 @@ describe Repository, models: true do
end
end
- describe '#is_ancestor?' do
+ describe '#ancestor?' do
let(:commit) { repository.commit }
let(:ancestor) { commit.parents.first }
context 'with Gitaly enabled' do
it 'it is an ancestor' do
- expect(repository.is_ancestor?(ancestor.id, commit.id)).to eq(true)
+ expect(repository.ancestor?(ancestor.id, commit.id)).to eq(true)
end
it 'it is not an ancestor' do
- expect(repository.is_ancestor?(commit.id, ancestor.id)).to eq(false)
+ expect(repository.ancestor?(commit.id, ancestor.id)).to eq(false)
end
it 'returns false on nil-values' do
- expect(repository.is_ancestor?(nil, commit.id)).to eq(false)
- expect(repository.is_ancestor?(ancestor.id, nil)).to eq(false)
- expect(repository.is_ancestor?(nil, nil)).to eq(false)
+ expect(repository.ancestor?(nil, commit.id)).to eq(false)
+ expect(repository.ancestor?(ancestor.id, nil)).to eq(false)
+ expect(repository.ancestor?(nil, nil)).to eq(false)
end
end
@@ -2062,17 +2063,17 @@ describe Repository, models: true do
end
it 'it is an ancestor' do
- expect(repository.is_ancestor?(ancestor.id, commit.id)).to eq(true)
+ expect(repository.ancestor?(ancestor.id, commit.id)).to eq(true)
end
it 'it is not an ancestor' do
- expect(repository.is_ancestor?(commit.id, ancestor.id)).to eq(false)
+ expect(repository.ancestor?(commit.id, ancestor.id)).to eq(false)
end
it 'returns false on nil-values' do
- expect(repository.is_ancestor?(nil, commit.id)).to eq(false)
- expect(repository.is_ancestor?(ancestor.id, nil)).to eq(false)
- expect(repository.is_ancestor?(nil, nil)).to eq(false)
+ expect(repository.ancestor?(nil, commit.id)).to eq(false)
+ expect(repository.ancestor?(ancestor.id, nil)).to eq(false)
+ expect(repository.ancestor?(nil, nil)).to eq(false)
end
end
end
diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb
index 97bb91a6ac8..8e04eea56a7 100644
--- a/spec/models/user_spec.rb
+++ b/spec/models/user_spec.rb
@@ -1356,7 +1356,7 @@ describe User do
end
it "excludes push event if branch has been deleted" do
- allow_any_instance_of(Repository).to receive(:branch_names).and_return(['foo'])
+ allow_any_instance_of(Repository).to receive(:branch_exists?).with('master').and_return(false)
expect(subject.recent_push).to eq(nil)
end
@@ -2024,4 +2024,65 @@ describe User do
expect(user.projects_limit_left).to eq(5)
end
end
+
+ describe '#ensure_namespace_correct' do
+ context 'for a new user' do
+ let(:user) { build(:user) }
+
+ it 'creates the namespace' do
+ expect(user.namespace).to be_nil
+ user.save!
+ expect(user.namespace).not_to be_nil
+ end
+ end
+
+ context 'for an existing user' do
+ let(:username) { 'foo' }
+ let(:user) { create(:user, username: username) }
+
+ context 'when the user is updated' do
+ context 'when the username is changed' do
+ let(:new_username) { 'bar' }
+
+ it 'changes the namespace (just to compare to when username is not changed)' do
+ expect do
+ user.update_attributes!(username: new_username)
+ end.to change { user.namespace.updated_at }
+ end
+
+ it 'updates the namespace name' do
+ user.update_attributes!(username: new_username)
+ expect(user.namespace.name).to eq(new_username)
+ end
+
+ it 'updates the namespace path' do
+ user.update_attributes!(username: new_username)
+ expect(user.namespace.path).to eq(new_username)
+ end
+
+ context 'when there is a validation error (namespace name taken) while updating namespace' do
+ let!(:conflicting_namespace) { create(:group, name: new_username, path: 'quz') }
+
+ it 'causes the user save to fail' do
+ expect(user.update_attributes(username: new_username)).to be_falsey
+ expect(user.namespace.errors.messages[:name].first).to eq('has already been taken')
+ end
+
+ it 'adds the namespace errors to the user' do
+ user.update_attributes(username: new_username)
+ expect(user.errors.full_messages.first).to eq('Namespace name has already been taken')
+ end
+ end
+ end
+
+ context 'when the username is not changed' do
+ it 'does not change the namespace' do
+ expect do
+ user.update_attributes!(email: 'asdf@asdf.com')
+ end.not_to change { user.namespace.updated_at }
+ end
+ end
+ end
+ end
+ end
end
diff --git a/spec/policies/group_policy_spec.rb b/spec/policies/group_policy_spec.rb
index b17a93e3fbe..7f832bfa563 100644
--- a/spec/policies/group_policy_spec.rb
+++ b/spec/policies/group_policy_spec.rb
@@ -105,6 +105,8 @@ describe GroupPolicy do
let(:current_user) { owner }
it do
+ allow(Group).to receive(:supports_nested_groups?).and_return(true)
+
expect_allowed(:read_group)
expect_allowed(*reporter_permissions)
expect_allowed(*master_permissions)
@@ -116,6 +118,8 @@ describe GroupPolicy do
let(:current_user) { admin }
it do
+ allow(Group).to receive(:supports_nested_groups?).and_return(true)
+
expect_allowed(:read_group)
expect_allowed(*reporter_permissions)
expect_allowed(*master_permissions)
@@ -123,6 +127,36 @@ describe GroupPolicy do
end
end
+ describe 'when nested group support feature is disabled' do
+ before do
+ allow(Group).to receive(:supports_nested_groups?).and_return(false)
+ end
+
+ context 'admin' do
+ let(:current_user) { admin }
+
+ it 'allows every owner permission except creating subgroups' do
+ create_subgroup_permission = [:create_subgroup]
+ updated_owner_permissions = owner_permissions - create_subgroup_permission
+
+ expect_disallowed(*create_subgroup_permission)
+ expect_allowed(*updated_owner_permissions)
+ end
+ end
+
+ context 'owner' do
+ let(:current_user) { owner }
+
+ it 'allows every owner permission except creating subgroups' do
+ create_subgroup_permission = [:create_subgroup]
+ updated_owner_permissions = owner_permissions - create_subgroup_permission
+
+ expect_disallowed(*create_subgroup_permission)
+ expect_allowed(*updated_owner_permissions)
+ end
+ end
+ end
+
describe 'private nested group use the highest access level from the group and inherited permissions', :nested_groups do
let(:nested_group) { create(:group, :private, parent: group) }
@@ -199,6 +233,8 @@ describe GroupPolicy do
let(:current_user) { owner }
it do
+ allow(Group).to receive(:supports_nested_groups?).and_return(true)
+
expect_allowed(:read_group)
expect_allowed(*reporter_permissions)
expect_allowed(*master_permissions)
diff --git a/spec/requests/api/award_emoji_spec.rb b/spec/requests/api/award_emoji_spec.rb
index 1dd9f3f6ddc..593068b8cd7 100644
--- a/spec/requests/api/award_emoji_spec.rb
+++ b/spec/requests/api/award_emoji_spec.rb
@@ -253,6 +253,10 @@ describe API::AwardEmoji do
expect(response).to have_http_status(404)
end
+
+ it_behaves_like '412 response' do
+ let(:request) { api("/projects/#{project.id}/issues/#{issue.iid}/award_emoji/#{award_emoji.id}", user) }
+ end
end
context 'when the awardable is a Merge Request' do
@@ -269,6 +273,10 @@ describe API::AwardEmoji do
expect(response).to have_http_status(404)
end
+
+ it_behaves_like '412 response' do
+ let(:request) { api("/projects/#{project.id}/merge_requests/#{merge_request.iid}/award_emoji/#{downvote.id}", user) }
+ end
end
context 'when the awardable is a Snippet' do
@@ -282,6 +290,10 @@ describe API::AwardEmoji do
expect(response).to have_http_status(204)
end.to change { snippet.award_emoji.count }.from(1).to(0)
end
+
+ it_behaves_like '412 response' do
+ let(:request) { api("/projects/#{project.id}/snippets/#{snippet.id}/award_emoji/#{award.id}", user) }
+ end
end
end
@@ -295,5 +307,9 @@ describe API::AwardEmoji do
expect(response).to have_http_status(204)
end.to change { note.award_emoji.count }.from(1).to(0)
end
+
+ it_behaves_like '412 response' do
+ let(:request) { api("/projects/#{project.id}/issues/#{issue.iid}/notes/#{note.id}/award_emoji/#{rocket.id}", user) }
+ end
end
end
diff --git a/spec/requests/api/boards_spec.rb b/spec/requests/api/boards_spec.rb
index 43b381c2219..f698d5dddb3 100644
--- a/spec/requests/api/boards_spec.rb
+++ b/spec/requests/api/boards_spec.rb
@@ -195,6 +195,10 @@ describe API::Boards do
expect(response).to have_http_status(204)
end
+
+ it_behaves_like '412 response' do
+ let(:request) { api("#{base_url}/#{dev_list.id}", owner) }
+ end
end
end
end
diff --git a/spec/requests/api/branches_spec.rb b/spec/requests/api/branches_spec.rb
index 5a2e1b2cf2d..b1e011de604 100644
--- a/spec/requests/api/branches_spec.rb
+++ b/spec/requests/api/branches_spec.rb
@@ -499,6 +499,10 @@ describe API::Branches do
expect(response).to have_gitlab_http_status(404)
end
+
+ it_behaves_like '412 response' do
+ let(:request) { api("/projects/#{project.id}/repository/branches/#{branch_name}", user) }
+ end
end
describe 'DELETE /projects/:id/repository/merged_branches' do
diff --git a/spec/requests/api/broadcast_messages_spec.rb b/spec/requests/api/broadcast_messages_spec.rb
index 67989689799..b043a333d33 100644
--- a/spec/requests/api/broadcast_messages_spec.rb
+++ b/spec/requests/api/broadcast_messages_spec.rb
@@ -171,6 +171,10 @@ describe API::BroadcastMessages do
expect(response).to have_http_status(403)
end
+ it_behaves_like '412 response' do
+ let(:request) { api("/broadcast_messages/#{message.id}", admin) }
+ end
+
it 'deletes the broadcast message for admins' do
expect do
delete api("/broadcast_messages/#{message.id}", admin)
diff --git a/spec/requests/api/deploy_keys_spec.rb b/spec/requests/api/deploy_keys_spec.rb
index e497ec333a2..684877c33c0 100644
--- a/spec/requests/api/deploy_keys_spec.rb
+++ b/spec/requests/api/deploy_keys_spec.rb
@@ -190,6 +190,10 @@ describe API::DeployKeys do
expect(response).to have_http_status(404)
end
+
+ it_behaves_like '412 response' do
+ let(:request) { api("/projects/#{project.id}/deploy_keys/#{deploy_key.id}", admin) }
+ end
end
describe 'POST /projects/:id/deploy_keys/:key_id/enable' do
diff --git a/spec/requests/api/environments_spec.rb b/spec/requests/api/environments_spec.rb
index 87716c6fe3a..2361809e0e1 100644
--- a/spec/requests/api/environments_spec.rb
+++ b/spec/requests/api/environments_spec.rb
@@ -138,6 +138,10 @@ describe API::Environments do
expect(response).to have_http_status(404)
expect(json_response['message']).to eq('404 Not found')
end
+
+ it_behaves_like '412 response' do
+ let(:request) { api("/projects/#{project.id}/environments/#{environment.id}", user) }
+ end
end
context 'a non member' do
diff --git a/spec/requests/api/group_variables_spec.rb b/spec/requests/api/group_variables_spec.rb
index 2179790d098..93b9cf85c1d 100644
--- a/spec/requests/api/group_variables_spec.rb
+++ b/spec/requests/api/group_variables_spec.rb
@@ -200,6 +200,10 @@ describe API::GroupVariables do
expect(response).to have_http_status(404)
end
+
+ it_behaves_like '412 response' do
+ let(:request) { api("/groups/#{group.id}/variables/#{variable.key}", user) }
+ end
end
context 'authorized user with invalid permissions' do
diff --git a/spec/requests/api/groups_spec.rb b/spec/requests/api/groups_spec.rb
index 313c38cd29c..77c43f92456 100644
--- a/spec/requests/api/groups_spec.rb
+++ b/spec/requests/api/groups_spec.rb
@@ -20,10 +20,15 @@ describe API::Groups do
describe "GET /groups" do
context "when unauthenticated" do
- it "returns authentication error" do
+ it "returns public groups" do
get api("/groups")
- expect(response).to have_http_status(401)
+ expect(response).to have_http_status(200)
+ expect(response).to include_pagination_headers
+ expect(json_response).to be_an Array
+ expect(json_response.length).to eq(1)
+ expect(json_response)
+ .to satisfy_one { |group| group['name'] == group1.name }
end
end
@@ -165,6 +170,18 @@ describe API::Groups do
end
describe "GET /groups/:id" do
+ context 'when unauthenticated' do
+ it 'returns 404 for a private group' do
+ get api("/groups/#{group2.id}")
+ expect(response).to have_http_status(404)
+ end
+
+ it 'returns 200 for a public group' do
+ get api("/groups/#{group1.id}")
+ expect(response).to have_http_status(200)
+ end
+ end
+
context "when authenticated as user" do
it "returns one of user1's groups" do
project = create(:project, namespace: group2, path: 'Foo')
@@ -427,6 +444,7 @@ describe API::Groups do
expect(json_response["name"]).to eq(group[:name])
expect(json_response["path"]).to eq(group[:path])
expect(json_response["request_access_enabled"]).to eq(group[:request_access_enabled])
+ expect(json_response["visibility"]).to eq(Gitlab::VisibilityLevel.string_level(Gitlab::CurrentSettings.current_application_settings.default_group_visibility))
end
it "creates a nested group", :nested_groups do
@@ -471,6 +489,10 @@ describe API::Groups do
expect(response).to have_http_status(204)
end
+ it_behaves_like '412 response' do
+ let(:request) { api("/groups/#{group1.id}", user1) }
+ end
+
it "does not remove a group if not an owner" do
user4 = create(:user)
group1.add_master(user4)
diff --git a/spec/requests/api/issues_spec.rb b/spec/requests/api/issues_spec.rb
index 7d120e4a234..9a0c62467d3 100644
--- a/spec/requests/api/issues_spec.rb
+++ b/spec/requests/api/issues_spec.rb
@@ -984,7 +984,7 @@ describe API::Issues, :mailer do
describe 'POST /projects/:id/issues with spam filtering' do
before do
allow_any_instance_of(SpamService).to receive(:check_for_spam?).and_return(true)
- allow_any_instance_of(AkismetService).to receive_messages(is_spam?: true)
+ allow_any_instance_of(AkismetService).to receive_messages(spam?: true)
end
let(:params) do
@@ -1114,7 +1114,7 @@ describe API::Issues, :mailer do
it "does not create a new project issue" do
allow_any_instance_of(SpamService).to receive_messages(check_for_spam?: true)
- allow_any_instance_of(AkismetService).to receive_messages(is_spam?: true)
+ allow_any_instance_of(AkismetService).to receive_messages(spam?: true)
put api("/projects/#{project.id}/issues/#{issue.iid}", user), params
@@ -1304,6 +1304,10 @@ describe API::Issues, :mailer do
expect(response).to have_http_status(204)
end
+
+ it_behaves_like '412 response' do
+ let(:request) { api("/projects/#{project.id}/issues/#{issue.iid}", owner) }
+ end
end
context 'when issue does not exist' do
diff --git a/spec/requests/api/labels_spec.rb b/spec/requests/api/labels_spec.rb
index 5a4257d1009..b231fdea2a3 100644
--- a/spec/requests/api/labels_spec.rb
+++ b/spec/requests/api/labels_spec.rb
@@ -189,6 +189,11 @@ describe API::Labels do
delete api("/projects/#{project.id}/labels", user)
expect(response).to have_http_status(400)
end
+
+ it_behaves_like '412 response' do
+ let(:request) { api("/projects/#{project.id}/labels", user) }
+ let(:params) { { name: 'label1' } }
+ end
end
describe 'PUT /projects/:id/labels' do
diff --git a/spec/requests/api/members_spec.rb b/spec/requests/api/members_spec.rb
index 06aca698c91..d3bae8d2888 100644
--- a/spec/requests/api/members_spec.rb
+++ b/spec/requests/api/members_spec.rb
@@ -284,6 +284,10 @@ describe API::Members do
expect(response).to have_http_status(204)
end.to change { source.members.count }.by(-1)
end
+
+ it_behaves_like '412 response' do
+ let(:request) { api("/#{source_type.pluralize}/#{source.id}/members/#{developer.id}", master) }
+ end
end
it 'returns 404 if member does not exist' do
diff --git a/spec/requests/api/merge_requests_spec.rb b/spec/requests/api/merge_requests_spec.rb
index 0db645863fb..9027090aabd 100644
--- a/spec/requests/api/merge_requests_spec.rb
+++ b/spec/requests/api/merge_requests_spec.rb
@@ -698,6 +698,10 @@ describe API::MergeRequests do
expect(response).to have_gitlab_http_status(404)
end
+
+ it_behaves_like '412 response' do
+ let(:request) { api("/projects/#{project.id}/merge_requests/#{merge_request.iid}", user) }
+ end
end
end
diff --git a/spec/requests/api/notes_spec.rb b/spec/requests/api/notes_spec.rb
index 75e5062a99c..f5882c0c74a 100644
--- a/spec/requests/api/notes_spec.rb
+++ b/spec/requests/api/notes_spec.rb
@@ -390,6 +390,10 @@ describe API::Notes do
expect(response).to have_http_status(404)
end
+
+ it_behaves_like '412 response' do
+ let(:request) { api("/projects/#{project.id}/issues/#{issue.iid}/notes/#{issue_note.id}", user) }
+ end
end
context 'when noteable is a Snippet' do
@@ -410,6 +414,10 @@ describe API::Notes do
expect(response).to have_http_status(404)
end
+
+ it_behaves_like '412 response' do
+ let(:request) { api("/projects/#{project.id}/snippets/#{snippet.id}/notes/#{snippet_note.id}", user) }
+ end
end
context 'when noteable is a Merge Request' do
@@ -430,6 +438,10 @@ describe API::Notes do
expect(response).to have_http_status(404)
end
+
+ it_behaves_like '412 response' do
+ let(:request) { api("/projects/#{project.id}/merge_requests/#{merge_request.iid}/notes/#{merge_request_note.id}", user) }
+ end
end
end
end
diff --git a/spec/requests/api/pipeline_schedules_spec.rb b/spec/requests/api/pipeline_schedules_spec.rb
index 1fc0ec528b9..b6a5a7ffbb5 100644
--- a/spec/requests/api/pipeline_schedules_spec.rb
+++ b/spec/requests/api/pipeline_schedules_spec.rb
@@ -267,8 +267,7 @@ describe API::PipelineSchedules do
delete api("/projects/#{project.id}/pipeline_schedules/#{pipeline_schedule.id}", master)
end.to change { project.pipeline_schedules.count }.by(-1)
- expect(response).to have_http_status(:accepted)
- expect(response).to match_response_schema('pipeline_schedule')
+ expect(response).to have_http_status(204)
end
it 'responds with 404 Not Found if requesting non-existing pipeline_schedule' do
@@ -276,6 +275,10 @@ describe API::PipelineSchedules do
expect(response).to have_http_status(:not_found)
end
+
+ it_behaves_like '412 response' do
+ let(:request) { api("/projects/#{project.id}/pipeline_schedules/#{pipeline_schedule.id}", master) }
+ end
end
context 'authenticated user with invalid permissions' do
diff --git a/spec/requests/api/project_hooks_spec.rb b/spec/requests/api/project_hooks_spec.rb
index 2829c243af3..ac3bab09c4c 100644
--- a/spec/requests/api/project_hooks_spec.rb
+++ b/spec/requests/api/project_hooks_spec.rb
@@ -212,5 +212,9 @@ describe API::ProjectHooks, 'ProjectHooks' do
expect(response).to have_http_status(404)
expect(WebHook.exists?(hook.id)).to be_truthy
end
+
+ it_behaves_like '412 response' do
+ let(:request) { api("/projects/#{project.id}/hooks/#{hook.id}", user) }
+ end
end
end
diff --git a/spec/requests/api/project_snippets_spec.rb b/spec/requests/api/project_snippets_spec.rb
index 2b541f5719e..db34149eb73 100644
--- a/spec/requests/api/project_snippets_spec.rb
+++ b/spec/requests/api/project_snippets_spec.rb
@@ -117,7 +117,7 @@ describe API::ProjectSnippets do
end
before do
- allow_any_instance_of(AkismetService).to receive(:is_spam?).and_return(true)
+ allow_any_instance_of(AkismetService).to receive(:spam?).and_return(true)
end
context 'when the snippet is private' do
@@ -179,7 +179,7 @@ describe API::ProjectSnippets do
end
before do
- allow_any_instance_of(AkismetService).to receive(:is_spam?).and_return(true)
+ allow_any_instance_of(AkismetService).to receive(:spam?).and_return(true)
end
context 'when the snippet is private' do
@@ -228,9 +228,6 @@ describe API::ProjectSnippets do
let(:snippet) { create(:project_snippet, author: admin) }
it 'deletes snippet' do
- admin = create(:admin)
- snippet = create(:project_snippet, author: admin)
-
delete api("/projects/#{snippet.project.id}/snippets/#{snippet.id}/", admin)
expect(response).to have_http_status(204)
@@ -242,6 +239,10 @@ describe API::ProjectSnippets do
expect(response).to have_http_status(404)
expect(json_response['message']).to eq('404 Snippet Not Found')
end
+
+ it_behaves_like '412 response' do
+ let(:request) { api("/projects/#{snippet.project.id}/snippets/#{snippet.id}/", admin) }
+ end
end
describe 'GET /projects/:project_id/snippets/:id/raw' do
diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb
index a89a58ff713..4490e50702b 100644
--- a/spec/requests/api/projects_spec.rb
+++ b/spec/requests/api/projects_spec.rb
@@ -1029,6 +1029,10 @@ describe API::Projects do
delete api("/projects/#{project.id}/snippets/1234", user)
expect(response).to have_http_status(404)
end
+
+ it_behaves_like '412 response' do
+ let(:request) { api("/projects/#{project.id}/snippets/#{snippet.id}", user) }
+ end
end
describe 'GET /projects/:id/snippets/:snippet_id/raw' do
@@ -1104,23 +1108,31 @@ describe API::Projects do
project_fork_target.group.add_developer user2
end
- it 'is forbidden to non-owner users' do
- delete api("/projects/#{project_fork_target.id}/fork", user2)
- expect(response).to have_http_status(403)
- end
+ context 'for a forked project' do
+ before do
+ post api("/projects/#{project_fork_target.id}/fork/#{project_fork_source.id}", admin)
+ project_fork_target.reload
+ expect(project_fork_target.forked_from_project).not_to be_nil
+ expect(project_fork_target.forked?).to be_truthy
+ end
- it 'makes forked project unforked' do
- post api("/projects/#{project_fork_target.id}/fork/#{project_fork_source.id}", admin)
- project_fork_target.reload
- expect(project_fork_target.forked_from_project).not_to be_nil
- expect(project_fork_target.forked?).to be_truthy
+ it 'makes forked project unforked' do
+ delete api("/projects/#{project_fork_target.id}/fork", admin)
- delete api("/projects/#{project_fork_target.id}/fork", admin)
+ expect(response).to have_http_status(204)
+ project_fork_target.reload
+ expect(project_fork_target.forked_from_project).to be_nil
+ expect(project_fork_target.forked?).not_to be_truthy
+ end
- expect(response).to have_http_status(204)
- project_fork_target.reload
- expect(project_fork_target.forked_from_project).to be_nil
- expect(project_fork_target.forked?).not_to be_truthy
+ it_behaves_like '412 response' do
+ let(:request) { api("/projects/#{project_fork_target.id}/fork", admin) }
+ end
+ end
+
+ it 'is forbidden to non-owner users' do
+ delete api("/projects/#{project_fork_target.id}/fork", user2)
+ expect(response).to have_http_status(403)
end
it 'is idempotent if not forked' do
@@ -1188,14 +1200,23 @@ describe API::Projects do
end
describe 'DELETE /projects/:id/share/:group_id' do
- it 'returns 204 when deleting a group share' do
- group = create(:group, :public)
- create(:project_group_link, group: group, project: project)
+ context 'for a valid group' do
+ let(:group) { create(:group, :public) }
+
+ before do
+ create(:project_group_link, group: group, project: project)
+ end
+
+ it 'returns 204 when deleting a group share' do
+ delete api("/projects/#{project.id}/share/#{group.id}", user)
- delete api("/projects/#{project.id}/share/#{group.id}", user)
+ expect(response).to have_http_status(204)
+ expect(project.project_group_links).to be_empty
+ end
- expect(response).to have_http_status(204)
- expect(project.project_group_links).to be_empty
+ it_behaves_like '412 response' do
+ let(:request) { api("/projects/#{project.id}/share/#{group.id}", user) }
+ end
end
it 'returns a 400 when group id is not an integer' do
@@ -1519,6 +1540,11 @@ describe API::Projects do
expect(json_response['message']).to eql('202 Accepted')
end
+ it_behaves_like '412 response' do
+ let(:success_status) { 202 }
+ let(:request) { api("/projects/#{project.id}", user) }
+ end
+
it 'does not remove a project if not an owner' do
user3 = create(:user)
project.team << [user3, :developer]
@@ -1549,6 +1575,11 @@ describe API::Projects do
delete api('/projects/1328', admin)
expect(response).to have_http_status(404)
end
+
+ it_behaves_like '412 response' do
+ let(:success_status) { 202 }
+ let(:request) { api("/projects/#{project.id}", admin) }
+ end
end
end
diff --git a/spec/requests/api/protected_branches_spec.rb b/spec/requests/api/protected_branches_spec.rb
index 1aa8a95780e..07d7f96bd70 100644
--- a/spec/requests/api/protected_branches_spec.rb
+++ b/spec/requests/api/protected_branches_spec.rb
@@ -213,6 +213,10 @@ describe API::ProtectedBranches do
expect(response).to have_gitlab_http_status(204)
end
+ it_behaves_like '412 response' do
+ let(:request) { api("/projects/#{project.id}/protected_branches/#{branch_name}", user) }
+ end
+
it "returns 404 if branch does not exist" do
delete api("/projects/#{project.id}/protected_branches/barfoo", user)
diff --git a/spec/requests/api/runner_spec.rb b/spec/requests/api/runner_spec.rb
index e9ee3dd679d..993164aa8fe 100644
--- a/spec/requests/api/runner_spec.rb
+++ b/spec/requests/api/runner_spec.rb
@@ -149,6 +149,11 @@ describe API::Runner do
expect(response).to have_http_status 204
expect(Ci::Runner.count).to eq(0)
end
+
+ it_behaves_like '412 response' do
+ let(:request) { api('/runners') }
+ let(:params) { { token: runner.token } }
+ end
end
end
diff --git a/spec/requests/api/runners_spec.rb b/spec/requests/api/runners_spec.rb
index c8ff25f70fa..244895a417e 100644
--- a/spec/requests/api/runners_spec.rb
+++ b/spec/requests/api/runners_spec.rb
@@ -279,6 +279,10 @@ describe API::Runners do
expect(response).to have_http_status(204)
end.to change { Ci::Runner.shared.count }.by(-1)
end
+
+ it_behaves_like '412 response' do
+ let(:request) { api("/runners/#{shared_runner.id}", admin) }
+ end
end
context 'when runner is not shared' do
@@ -332,6 +336,10 @@ describe API::Runners do
expect(response).to have_http_status(204)
end.to change { Ci::Runner.specific.count }.by(-1)
end
+
+ it_behaves_like '412 response' do
+ let(:request) { api("/runners/#{specific_runner.id}", user) }
+ end
end
end
@@ -463,6 +471,10 @@ describe API::Runners do
expect(response).to have_http_status(204)
end.to change { project.runners.count }.by(-1)
end
+
+ it_behaves_like '412 response' do
+ let(:request) { api("/projects/#{project.id}/runners/#{two_projects_runner.id}", user) }
+ end
end
context 'when runner have one associated projects' do
diff --git a/spec/requests/api/snippets_spec.rb b/spec/requests/api/snippets_spec.rb
index d09b8bc42f1..d3905f698bd 100644
--- a/spec/requests/api/snippets_spec.rb
+++ b/spec/requests/api/snippets_spec.rb
@@ -137,7 +137,7 @@ describe API::Snippets do
end
before do
- allow_any_instance_of(AkismetService).to receive(:is_spam?).and_return(true)
+ allow_any_instance_of(AkismetService).to receive(:spam?).and_return(true)
end
context 'when the snippet is private' do
@@ -209,7 +209,7 @@ describe API::Snippets do
end
before do
- allow_any_instance_of(AkismetService).to receive(:is_spam?).and_return(true)
+ allow_any_instance_of(AkismetService).to receive(:spam?).and_return(true)
end
context 'when the snippet is private' do
@@ -270,6 +270,10 @@ describe API::Snippets do
expect(response).to have_http_status(404)
expect(json_response['message']).to eq('404 Snippet Not Found')
end
+
+ it_behaves_like '412 response' do
+ let(:request) { api("/snippets/#{public_snippet.id}", user) }
+ end
end
describe "GET /snippets/:id/user_agent_detail" do
diff --git a/spec/requests/api/system_hooks_spec.rb b/spec/requests/api/system_hooks_spec.rb
index f65b475fe44..216d278ad21 100644
--- a/spec/requests/api/system_hooks_spec.rb
+++ b/spec/requests/api/system_hooks_spec.rb
@@ -102,5 +102,9 @@ describe API::SystemHooks do
expect(response).to have_http_status(404)
end
+
+ it_behaves_like '412 response' do
+ let(:request) { api("/hooks/#{hook.id}", admin) }
+ end
end
end
diff --git a/spec/requests/api/tags_spec.rb b/spec/requests/api/tags_spec.rb
index 9884c1ec206..0bf7863bdc8 100644
--- a/spec/requests/api/tags_spec.rb
+++ b/spec/requests/api/tags_spec.rb
@@ -278,12 +278,16 @@ describe API::Tags do
expect(response).to have_gitlab_http_status(204)
end
+ it_behaves_like '412 response' do
+ let(:request) { api(route, current_user) }
+ end
+
context 'when tag does not exist' do
let(:tag_name) { 'unknown' }
it_behaves_like '404 response' do
let(:request) { delete api(route, current_user) }
- let(:message) { 'No such tag' }
+ let(:message) { '404 Tag Not Found' }
end
end
diff --git a/spec/requests/api/triggers_spec.rb b/spec/requests/api/triggers_spec.rb
index 572e9a0fd07..922b99a6cba 100644
--- a/spec/requests/api/triggers_spec.rb
+++ b/spec/requests/api/triggers_spec.rb
@@ -8,8 +8,8 @@ describe API::Triggers do
let!(:project) { create(:project, :repository, creator: user) }
let!(:master) { create(:project_member, :master, user: user, project: project) }
let!(:developer) { create(:project_member, :developer, user: user2, project: project) }
- let!(:trigger) { create(:ci_trigger, project: project, token: trigger_token) }
- let!(:trigger2) { create(:ci_trigger, project: project, token: trigger_token_2) }
+ let!(:trigger) { create(:ci_trigger, project: project, token: trigger_token, owner: user) }
+ let!(:trigger2) { create(:ci_trigger, project: project, token: trigger_token_2, owner: user2) }
let!(:trigger_request) { create(:ci_trigger_request, trigger: trigger, created_at: '2015-01-01 12:13:14') }
describe 'POST /projects/:project_id/trigger/pipeline' do
@@ -22,7 +22,6 @@ describe API::Triggers do
before do
stub_ci_pipeline_to_return_yaml_file
- trigger.update(owner: user)
end
context 'Handles errors' do
@@ -85,6 +84,22 @@ describe API::Triggers do
expect(pipeline.variables.map { |v| { v.key => v.value } }.last).to eq(variables)
end
end
+
+ context 'when legacy trigger' do
+ before do
+ trigger.update(owner: nil)
+ end
+
+ it 'creates pipeline' do
+ post api("/projects/#{project.id}/trigger/pipeline"), options.merge(ref: 'master')
+
+ expect(response).to have_http_status(201)
+ expect(json_response).to include('id' => pipeline.id)
+ pipeline.builds.reload
+ expect(pipeline.builds.pending.size).to eq(2)
+ expect(pipeline.builds.size).to eq(5)
+ end
+ end
end
context 'when triggering a pipeline from a trigger token' do
@@ -254,8 +269,6 @@ describe API::Triggers do
describe 'POST /projects/:id/triggers/:trigger_id/take_ownership' do
context 'authenticated user with valid permissions' do
it 'updates owner' do
- expect(trigger.owner).to be_nil
-
post api("/projects/#{project.id}/triggers/#{trigger.id}/take_ownership", user)
expect(response).to have_http_status(200)
@@ -296,6 +309,10 @@ describe API::Triggers do
expect(response).to have_http_status(404)
end
+
+ it_behaves_like '412 response' do
+ let(:request) { api("/projects/#{project.id}/triggers/#{trigger.id}", user) }
+ end
end
context 'authenticated user with invalid permissions' do
diff --git a/spec/requests/api/users_spec.rb b/spec/requests/api/users_spec.rb
index 49739a1601a..5fef4437997 100644
--- a/spec/requests/api/users_spec.rb
+++ b/spec/requests/api/users_spec.rb
@@ -733,6 +733,10 @@ describe API::Users do
end.to change { user.keys.count }.by(-1)
end
+ it_behaves_like '412 response' do
+ let(:request) { api("/users/#{user.id}/keys/#{key.id}", admin) }
+ end
+
it 'returns 404 error if user not found' do
user.keys << key
user.save
@@ -838,6 +842,10 @@ describe API::Users do
end.to change { user.emails.count }.by(-1)
end
+ it_behaves_like '412 response' do
+ let(:request) { api("/users/#{user.id}/emails/#{email.id}", admin) }
+ end
+
it 'returns 404 error if user not found' do
user.emails << email
user.save
@@ -876,6 +884,10 @@ describe API::Users do
expect { Namespace.find(namespace.id) }.to raise_error ActiveRecord::RecordNotFound
end
+ it_behaves_like '412 response' do
+ let(:request) { api("/users/#{user.id}", admin) }
+ end
+
it "does not delete for unauthenticated user" do
Sidekiq::Testing.inline! { delete api("/users/#{user.id}") }
expect(response).to have_http_status(401)
@@ -1116,6 +1128,10 @@ describe API::Users do
end.to change { user.keys.count}.by(-1)
end
+ it_behaves_like '412 response' do
+ let(:request) { api("/user/keys/#{key.id}", user) }
+ end
+
it "returns 404 if key ID not found" do
delete api("/user/keys/42", user)
@@ -1239,6 +1255,10 @@ describe API::Users do
end.to change { user.emails.count}.by(-1)
end
+ it_behaves_like '412 response' do
+ let(:request) { api("/user/emails/#{email.id}", user) }
+ end
+
it "returns 404 if email ID not found" do
delete api("/user/emails/42", user)
@@ -1551,6 +1571,10 @@ describe API::Users do
expect(json_response['message']).to eq('403 Forbidden')
end
+ it_behaves_like '412 response' do
+ let(:request) { api("/users/#{user.id}/impersonation_tokens/#{impersonation_token.id}", admin) }
+ end
+
it 'revokes a impersonation token' do
delete api("/users/#{user.id}/impersonation_tokens/#{impersonation_token.id}", admin)
diff --git a/spec/requests/api/v3/issues_spec.rb b/spec/requests/api/v3/issues_spec.rb
index 9eb538c4b09..9a0e6647ebf 100644
--- a/spec/requests/api/v3/issues_spec.rb
+++ b/spec/requests/api/v3/issues_spec.rb
@@ -884,7 +884,7 @@ describe API::V3::Issues, :mailer do
describe 'POST /projects/:id/issues with spam filtering' do
before do
allow_any_instance_of(SpamService).to receive(:check_for_spam?).and_return(true)
- allow_any_instance_of(AkismetService).to receive_messages(is_spam?: true)
+ allow_any_instance_of(AkismetService).to receive_messages(spam?: true)
end
let(:params) do
@@ -1016,7 +1016,7 @@ describe API::V3::Issues, :mailer do
it "does not create a new project issue" do
allow_any_instance_of(SpamService).to receive_messages(check_for_spam?: true)
- allow_any_instance_of(AkismetService).to receive_messages(is_spam?: true)
+ allow_any_instance_of(AkismetService).to receive_messages(spam?: true)
put v3_api("/projects/#{project.id}/issues/#{issue.id}", user), params
diff --git a/spec/requests/api/v3/project_snippets_spec.rb b/spec/requests/api/v3/project_snippets_spec.rb
index 3963924a066..7e88489082a 100644
--- a/spec/requests/api/v3/project_snippets_spec.rb
+++ b/spec/requests/api/v3/project_snippets_spec.rb
@@ -80,7 +80,7 @@ describe API::ProjectSnippets do
end
before do
- allow_any_instance_of(AkismetService).to receive(:is_spam?).and_return(true)
+ allow_any_instance_of(AkismetService).to receive(:spam?).and_return(true)
end
context 'when the snippet is private' do
@@ -140,7 +140,7 @@ describe API::ProjectSnippets do
end
before do
- allow_any_instance_of(AkismetService).to receive(:is_spam?).and_return(true)
+ allow_any_instance_of(AkismetService).to receive(:spam?).and_return(true)
end
context 'when the snippet is private' do
diff --git a/spec/requests/api/v3/snippets_spec.rb b/spec/requests/api/v3/snippets_spec.rb
index 9ead3cad8bb..79860725634 100644
--- a/spec/requests/api/v3/snippets_spec.rb
+++ b/spec/requests/api/v3/snippets_spec.rb
@@ -107,7 +107,7 @@ describe API::V3::Snippets do
end
before do
- allow_any_instance_of(AkismetService).to receive(:is_spam?).and_return(true)
+ allow_any_instance_of(AkismetService).to receive(:spam?).and_return(true)
end
context 'when the snippet is private' do
diff --git a/spec/requests/api/v3/triggers_spec.rb b/spec/requests/api/v3/triggers_spec.rb
index 075de2c0cba..d4648136841 100644
--- a/spec/requests/api/v3/triggers_spec.rb
+++ b/spec/requests/api/v3/triggers_spec.rb
@@ -7,7 +7,10 @@ describe API::V3::Triggers do
let!(:project) { create(:project, :repository, creator: user) }
let!(:master) { create(:project_member, :master, user: user, project: project) }
let!(:developer) { create(:project_member, :developer, user: user2, project: project) }
- let!(:trigger) { create(:ci_trigger, project: project, token: trigger_token) }
+
+ let!(:trigger) do
+ create(:ci_trigger, project: project, token: trigger_token, owner: user)
+ end
describe 'POST /projects/:project_id/trigger' do
let!(:project2) { create(:project) }
diff --git a/spec/requests/ci/api/builds_spec.rb b/spec/requests/ci/api/builds_spec.rb
deleted file mode 100644
index 7ccba4ba3ec..00000000000
--- a/spec/requests/ci/api/builds_spec.rb
+++ /dev/null
@@ -1,912 +0,0 @@
-require 'spec_helper'
-
-describe Ci::API::Builds do
- let(:runner) { FactoryGirl.create(:ci_runner, tag_list: %w(mysql ruby)) }
- let(:project) { FactoryGirl.create(:project, shared_runners_enabled: false) }
- let(:last_update) { nil }
-
- describe "Builds API for runners" do
- let(:pipeline) { create(:ci_pipeline_without_jobs, project: project, ref: 'master') }
-
- before do
- project.runners << runner
- end
-
- describe "POST /builds/register" do
- let!(:build) { create(:ci_build, pipeline: pipeline, name: 'spinach', stage: 'test', stage_idx: 0) }
- let(:user_agent) { 'gitlab-ci-multi-runner 1.5.2 (1-5-stable; go1.6.3; linux/amd64)' }
- let!(:last_update) { }
- let!(:new_update) { }
-
- before do
- stub_container_registry_config(enabled: false)
- end
-
- shared_examples 'no builds available' do
- context 'when runner sends version in User-Agent' do
- context 'for stable version' do
- it 'gives 204 and set X-GitLab-Last-Update' do
- expect(response).to have_http_status(204)
- expect(response.header).to have_key('X-GitLab-Last-Update')
- end
- end
-
- context 'when last_update is up-to-date' do
- let(:last_update) { runner.ensure_runner_queue_value }
-
- it 'gives 204 and set the same X-GitLab-Last-Update' do
- expect(response).to have_http_status(204)
- expect(response.header['X-GitLab-Last-Update'])
- .to eq(last_update)
- end
- end
-
- context 'when last_update is outdated' do
- let(:last_update) { runner.ensure_runner_queue_value }
- let(:new_update) { runner.tick_runner_queue }
-
- it 'gives 204 and set a new X-GitLab-Last-Update' do
- expect(response).to have_http_status(204)
- expect(response.header['X-GitLab-Last-Update'])
- .to eq(new_update)
- end
- end
-
- context 'for beta version' do
- let(:user_agent) { 'gitlab-ci-multi-runner 1.6.0~beta.167.g2b2bacc (1-5-stable; go1.6.3; linux/amd64)' }
- it { expect(response).to have_http_status(204) }
- end
- end
-
- context "when runner doesn't send version in User-Agent" do
- let(:user_agent) { 'Go-http-client/1.1' }
- it { expect(response).to have_http_status(404) }
- end
-
- context "when runner doesn't have a User-Agent" do
- let(:user_agent) { nil }
- it { expect(response).to have_http_status(404) }
- end
- end
-
- context 'when an old image syntax is used' do
- before do
- build.update!(options: { image: 'codeclimate' })
- end
-
- it 'starts a build' do
- register_builds info: { platform: :darwin }
-
- expect(response).to have_http_status(201)
- expect(json_response["options"]).to eq({ "image" => "codeclimate" })
- end
- end
-
- context 'when a new image syntax is used' do
- before do
- build.update!(options: { image: { name: 'codeclimate' } })
- end
-
- it 'starts a build' do
- register_builds info: { platform: :darwin }
-
- expect(response).to have_http_status(201)
- expect(json_response["options"]).to eq({ "image" => "codeclimate" })
- end
- end
-
- context 'when an old service syntax is used' do
- before do
- build.update!(options: { services: ['mysql'] })
- end
-
- it 'starts a build' do
- register_builds info: { platform: :darwin }
-
- expect(response).to have_http_status(201)
- expect(json_response["options"]).to eq({ "services" => ["mysql"] })
- end
- end
-
- context 'when a new service syntax is used' do
- before do
- build.update!(options: { services: [name: 'mysql'] })
- end
-
- it 'starts a build' do
- register_builds info: { platform: :darwin }
-
- expect(response).to have_http_status(201)
- expect(json_response["options"]).to eq({ "services" => ["mysql"] })
- end
- end
-
- context 'when no image or service is defined' do
- before do
- build.update!(options: {})
- end
-
- it 'starts a build' do
- register_builds info: { platform: :darwin }
-
- expect(response).to have_http_status(201)
-
- expect(json_response["options"]).to be_empty
- end
- end
-
- context 'when there is a pending build' do
- it 'starts a build' do
- register_builds info: { platform: :darwin }
-
- expect(response).to have_http_status(201)
- expect(response.headers).not_to have_key('X-GitLab-Last-Update')
- expect(json_response['sha']).to eq(build.sha)
- expect(runner.reload.platform).to eq("darwin")
- expect(json_response["options"]).to eq({ "image" => "ruby:2.1", "services" => ["postgres"] })
- expect(json_response["variables"]).to include(
- { "key" => "CI_JOB_NAME", "value" => "spinach", "public" => true },
- { "key" => "CI_JOB_STAGE", "value" => "test", "public" => true },
- { "key" => "DB_NAME", "value" => "postgres", "public" => true }
- )
- end
-
- it 'updates runner info' do
- expect { register_builds }.to change { runner.reload.contacted_at }
- end
-
- context 'when concurrently updating build' do
- before do
- expect_any_instance_of(Ci::Build).to receive(:run!)
- .and_raise(ActiveRecord::StaleObjectError.new(nil, nil))
- end
-
- it 'returns a conflict' do
- register_builds info: { platform: :darwin }
-
- expect(response).to have_http_status(409)
- expect(response.headers).not_to have_key('X-GitLab-Last-Update')
- end
- end
-
- context 'registry credentials' do
- let(:registry_credentials) do
- { 'type' => 'registry',
- 'url' => 'registry.example.com:5005',
- 'username' => 'gitlab-ci-token',
- 'password' => build.token }
- end
-
- context 'when registry is enabled' do
- before do
- stub_container_registry_config(enabled: true, host_port: 'registry.example.com:5005')
- end
-
- it 'sends registry credentials key' do
- register_builds info: { platform: :darwin }
-
- expect(json_response).to have_key('credentials')
- expect(json_response['credentials']).to include(registry_credentials)
- end
- end
-
- context 'when registry is disabled' do
- before do
- stub_container_registry_config(enabled: false, host_port: 'registry.example.com:5005')
- end
-
- it 'does not send registry credentials' do
- register_builds info: { platform: :darwin }
-
- expect(json_response).to have_key('credentials')
- expect(json_response['credentials']).not_to include(registry_credentials)
- end
- end
- end
-
- context 'when docker configuration options are used' do
- let!(:build) { create(:ci_build, :extended_options, pipeline: pipeline, name: 'spinach', stage: 'test', stage_idx: 0) }
-
- it 'starts a build' do
- register_builds info: { platform: :darwin }
-
- expect(response).to have_http_status(201)
- expect(json_response['options']['image']).to eq('ruby:2.1')
- expect(json_response['options']['services']).to eq(['postgres', 'docker:dind'])
- end
- end
- end
-
- context 'when builds are finished' do
- before do
- build.success
- register_builds
- end
-
- it_behaves_like 'no builds available'
- end
-
- context 'for other project with builds' do
- before do
- build.success
- create(:ci_build, :pending)
- register_builds
- end
-
- it_behaves_like 'no builds available'
- end
-
- context 'for shared runner' do
- let!(:runner) { create(:ci_runner, :shared, token: "SharedRunner") }
-
- before do
- register_builds(runner.token)
- end
-
- it_behaves_like 'no builds available'
- end
-
- context 'for triggered build' do
- before do
- trigger = create(:ci_trigger, project: project)
- create(:ci_trigger_request_with_variables, pipeline: pipeline, builds: [build], trigger: trigger)
- project.variables << Ci::Variable.new(key: "SECRET_KEY", value: "secret_value")
- end
-
- it "returns variables for triggers" do
- register_builds info: { platform: :darwin }
-
- expect(response).to have_http_status(201)
- expect(json_response["variables"]).to include(
- { "key" => "CI_JOB_NAME", "value" => "spinach", "public" => true },
- { "key" => "CI_JOB_STAGE", "value" => "test", "public" => true },
- { "key" => "CI_PIPELINE_TRIGGERED", "value" => "true", "public" => true },
- { "key" => "DB_NAME", "value" => "postgres", "public" => true },
- { "key" => "SECRET_KEY", "value" => "secret_value", "public" => false },
- { "key" => "TRIGGER_KEY_1", "value" => "TRIGGER_VALUE_1", "public" => false }
- )
- end
- end
-
- context 'with multiple builds' do
- before do
- build.success
- end
-
- let!(:test_build) { create(:ci_build, pipeline: pipeline, name: 'deploy', stage: 'deploy', stage_idx: 1) }
-
- it "returns dependent builds" do
- register_builds info: { platform: :darwin }
-
- expect(response).to have_http_status(201)
- expect(json_response["id"]).to eq(test_build.id)
- expect(json_response["depends_on_builds"].count).to eq(1)
- expect(json_response["depends_on_builds"][0]).to include('id' => build.id, 'name' => 'spinach')
- end
- end
-
- %w(name version revision platform architecture).each do |param|
- context "updates runner #{param}" do
- let(:value) { "#{param}_value" }
-
- subject { runner.read_attribute(param.to_sym) }
-
- it do
- register_builds info: { param => value }
-
- expect(response).to have_http_status(201)
- runner.reload
- is_expected.to eq(value)
- end
- end
- end
-
- context 'when build has no tags' do
- before do
- build.update(tags: [])
- end
-
- context 'when runner is allowed to pick untagged builds' do
- before do
- runner.update_column(:run_untagged, true)
- end
-
- it 'picks build' do
- register_builds
-
- expect(response).to have_http_status 201
- end
- end
-
- context 'when runner is not allowed to pick untagged builds' do
- before do
- runner.update_column(:run_untagged, false)
- register_builds
- end
-
- it_behaves_like 'no builds available'
- end
- end
-
- context 'when runner is paused' do
- let(:runner) { create(:ci_runner, :inactive, token: 'InactiveRunner') }
-
- it 'responds with 404' do
- register_builds
-
- expect(response).to have_http_status 404
- end
-
- it 'does not update runner info' do
- expect { register_builds }
- .not_to change { runner.reload.contacted_at }
- end
- end
-
- def register_builds(token = runner.token, **params)
- new_params = params.merge(token: token, last_update: last_update)
-
- post ci_api("/builds/register"), new_params, { 'User-Agent' => user_agent }
- end
- end
-
- describe "PUT /builds/:id" do
- let(:build) { create(:ci_build, :pending, :trace, pipeline: pipeline, runner_id: runner.id) }
-
- before do
- build.run!
- put ci_api("/builds/#{build.id}"), token: runner.token
- end
-
- it "updates a running build" do
- expect(response).to have_http_status(200)
- end
-
- it 'does not override trace information when no trace is given' do
- expect(build.reload.trace.raw).to eq 'BUILD TRACE'
- end
-
- context 'job has been erased' do
- let(:build) { create(:ci_build, runner_id: runner.id, erased_at: Time.now) }
-
- it 'responds with forbidden' do
- expect(response.status).to eq 403
- end
- end
- end
-
- describe 'PATCH /builds/:id/trace.txt' do
- let(:build) do
- attributes = { runner_id: runner.id, pipeline: pipeline }
- create(:ci_build, :running, :trace, attributes)
- end
-
- let(:headers) { { Ci::API::Helpers::BUILD_TOKEN_HEADER => build.token, 'Content-Type' => 'text/plain' } }
- let(:headers_with_range) { headers.merge({ 'Content-Range' => '11-20' }) }
- let(:update_interval) { 10.seconds.to_i }
-
- def patch_the_trace(content = ' appended', request_headers = nil)
- unless request_headers
- build.trace.read do |stream|
- offset = stream.size
- limit = offset + content.length - 1
- request_headers = headers.merge({ 'Content-Range' => "#{offset}-#{limit}" })
- end
- end
-
- Timecop.travel(build.updated_at + update_interval) do
- patch ci_api("/builds/#{build.id}/trace.txt"), content, request_headers
- build.reload
- end
- end
-
- def initial_patch_the_trace
- patch_the_trace(' appended', headers_with_range)
- end
-
- def force_patch_the_trace
- 2.times { patch_the_trace('') }
- end
-
- before do
- initial_patch_the_trace
- end
-
- context 'when request is valid' do
- it 'gets correct response' do
- expect(response.status).to eq 202
- expect(build.reload.trace.raw).to eq 'BUILD TRACE appended'
- expect(response.header).to have_key 'Range'
- expect(response.header).to have_key 'Build-Status'
- end
-
- context 'when build has been updated recently' do
- it { expect { patch_the_trace }.not_to change { build.updated_at }}
-
- it 'changes the build trace' do
- patch_the_trace
-
- expect(build.reload.trace.raw).to eq 'BUILD TRACE appended appended'
- end
-
- context 'when Runner makes a force-patch' do
- it { expect { force_patch_the_trace }.not_to change { build.updated_at }}
-
- it "doesn't change the build.trace" do
- force_patch_the_trace
-
- expect(build.reload.trace.raw).to eq 'BUILD TRACE appended'
- end
- end
- end
-
- context 'when build was not updated recently' do
- let(:update_interval) { 15.minutes.to_i }
-
- it { expect { patch_the_trace }.to change { build.updated_at } }
-
- it 'changes the build.trace' do
- patch_the_trace
-
- expect(build.reload.trace.raw).to eq 'BUILD TRACE appended appended'
- end
-
- context 'when Runner makes a force-patch' do
- it { expect { force_patch_the_trace }.to change { build.updated_at } }
-
- it "doesn't change the build.trace" do
- force_patch_the_trace
-
- expect(build.reload.trace.raw).to eq 'BUILD TRACE appended'
- end
- end
- end
-
- context 'when project for the build has been deleted' do
- let(:build) do
- attributes = { runner_id: runner.id, pipeline: pipeline }
- create(:ci_build, :running, :trace, attributes) do |build|
- build.project.update(pending_delete: true)
- end
- end
-
- it 'responds with forbidden' do
- expect(response.status).to eq(403)
- end
- end
- end
-
- context 'when Runner makes a force-patch' do
- before do
- force_patch_the_trace
- end
-
- it 'gets correct response' do
- expect(response.status).to eq 202
- expect(build.reload.trace.raw).to eq 'BUILD TRACE appended'
- expect(response.header).to have_key 'Range'
- expect(response.header).to have_key 'Build-Status'
- end
- end
-
- context 'when content-range start is too big' do
- let(:headers_with_range) { headers.merge({ 'Content-Range' => '15-20' }) }
-
- it 'gets 416 error response with range headers' do
- expect(response.status).to eq 416
- expect(response.header).to have_key 'Range'
- expect(response.header['Range']).to eq '0-11'
- end
- end
-
- context 'when content-range start is too small' do
- let(:headers_with_range) { headers.merge({ 'Content-Range' => '8-20' }) }
-
- it 'gets 416 error response with range headers' do
- expect(response.status).to eq 416
- expect(response.header).to have_key 'Range'
- expect(response.header['Range']).to eq '0-11'
- end
- end
-
- context 'when Content-Range header is missing' do
- let(:headers_with_range) { headers }
-
- it { expect(response.status).to eq 400 }
- end
-
- context 'when build has been errased' do
- let(:build) { create(:ci_build, runner_id: runner.id, erased_at: Time.now) }
-
- it { expect(response.status).to eq 403 }
- end
- end
-
- context "Artifacts" do
- let(:file_upload) { fixture_file_upload(Rails.root + 'spec/fixtures/banana_sample.gif', 'image/gif') }
- let(:file_upload2) { fixture_file_upload(Rails.root + 'spec/fixtures/dk.png', 'image/gif') }
- let(:build) { create(:ci_build, :pending, pipeline: pipeline, runner_id: runner.id) }
- let(:authorize_url) { ci_api("/builds/#{build.id}/artifacts/authorize") }
- let(:post_url) { ci_api("/builds/#{build.id}/artifacts") }
- let(:delete_url) { ci_api("/builds/#{build.id}/artifacts") }
- let(:get_url) { ci_api("/builds/#{build.id}/artifacts") }
- let(:jwt_token) { JWT.encode({ 'iss' => 'gitlab-workhorse' }, Gitlab::Workhorse.secret, 'HS256') }
- let(:headers) { { "GitLab-Workhorse" => "1.0", Gitlab::Workhorse::INTERNAL_API_REQUEST_HEADER => jwt_token } }
- let(:token) { build.token }
- let(:headers_with_token) { headers.merge(Ci::API::Helpers::BUILD_TOKEN_HEADER => token) }
-
- before do
- build.run!
- end
-
- describe "POST /builds/:id/artifacts/authorize" do
- context "authorizes posting artifact to running build" do
- it "using token as parameter" do
- post authorize_url, { token: build.token }, headers
-
- expect(response).to have_http_status(200)
- expect(response.content_type.to_s).to eq(Gitlab::Workhorse::INTERNAL_API_CONTENT_TYPE)
- expect(json_response["TempPath"]).not_to be_nil
- end
-
- it "using token as header" do
- post authorize_url, {}, headers_with_token
-
- expect(response).to have_http_status(200)
- expect(response.content_type.to_s).to eq(Gitlab::Workhorse::INTERNAL_API_CONTENT_TYPE)
- expect(json_response["TempPath"]).not_to be_nil
- end
-
- it "using runners token" do
- post authorize_url, { token: build.project.runners_token }, headers
-
- expect(response).to have_http_status(200)
- expect(response.content_type.to_s).to eq(Gitlab::Workhorse::INTERNAL_API_CONTENT_TYPE)
- expect(json_response["TempPath"]).not_to be_nil
- end
-
- it "reject requests that did not go through gitlab-workhorse" do
- headers.delete(Gitlab::Workhorse::INTERNAL_API_REQUEST_HEADER)
-
- post authorize_url, { token: build.token }, headers
-
- expect(response).to have_http_status(500)
- end
- end
-
- context "fails to post too large artifact" do
- it "using token as parameter" do
- stub_application_setting(max_artifacts_size: 0)
-
- post authorize_url, { token: build.token, filesize: 100 }, headers
-
- expect(response).to have_http_status(413)
- end
-
- it "using token as header" do
- stub_application_setting(max_artifacts_size: 0)
-
- post authorize_url, { filesize: 100 }, headers_with_token
-
- expect(response).to have_http_status(413)
- end
- end
-
- context 'authorization token is invalid' do
- before do
- post authorize_url, { token: 'invalid', filesize: 100 }
- end
-
- it 'responds with forbidden' do
- expect(response).to have_http_status(403)
- end
- end
- end
-
- describe "POST /builds/:id/artifacts" do
- context "disable sanitizer" do
- before do
- # by configuring this path we allow to pass temp file from any path
- allow(ArtifactUploader).to receive(:artifacts_upload_path).and_return('/')
- end
-
- describe 'build has been erased' do
- let(:build) { create(:ci_build, erased_at: Time.now) }
-
- before do
- upload_artifacts(file_upload, headers_with_token)
- end
-
- it 'responds with forbidden' do
- expect(response.status).to eq 403
- end
- end
-
- describe 'uploading artifacts for a running build' do
- shared_examples 'successful artifacts upload' do
- it 'updates successfully' do
- response_filename =
- json_response['artifacts_file']['filename']
-
- expect(response).to have_http_status(201)
- expect(response_filename).to eq(file_upload.original_filename)
- end
- end
-
- context 'uses regular file post' do
- before do
- upload_artifacts(file_upload, headers_with_token, false)
- end
-
- it_behaves_like 'successful artifacts upload'
- end
-
- context 'uses accelerated file post' do
- before do
- upload_artifacts(file_upload, headers_with_token, true)
- end
-
- it_behaves_like 'successful artifacts upload'
- end
-
- context 'updates artifact' do
- before do
- upload_artifacts(file_upload2, headers_with_token)
- upload_artifacts(file_upload, headers_with_token)
- end
-
- it_behaves_like 'successful artifacts upload'
- end
-
- context 'when using runners token' do
- let(:token) { build.project.runners_token }
-
- before do
- upload_artifacts(file_upload, headers_with_token)
- end
-
- it_behaves_like 'successful artifacts upload'
- end
- end
-
- context 'posts artifacts file and metadata file' do
- let!(:artifacts) { file_upload }
- let!(:metadata) { file_upload2 }
-
- let(:stored_artifacts_file) { build.reload.artifacts_file.file }
- let(:stored_metadata_file) { build.reload.artifacts_metadata.file }
- let(:stored_artifacts_size) { build.reload.artifacts_size }
-
- before do
- post(post_url, post_data, headers_with_token)
- end
-
- context 'posts data accelerated by workhorse is correct' do
- let(:post_data) do
- { 'file.path' => artifacts.path,
- 'file.name' => artifacts.original_filename,
- 'metadata.path' => metadata.path,
- 'metadata.name' => metadata.original_filename }
- end
-
- it 'stores artifacts and artifacts metadata' do
- expect(response).to have_http_status(201)
- expect(stored_artifacts_file.original_filename).to eq(artifacts.original_filename)
- expect(stored_metadata_file.original_filename).to eq(metadata.original_filename)
- expect(stored_artifacts_size).to eq(71759)
- end
- end
-
- context 'no artifacts file in post data' do
- let(:post_data) do
- { 'metadata' => metadata }
- end
-
- it 'is expected to respond with bad request' do
- expect(response).to have_http_status(400)
- end
-
- it 'does not store metadata' do
- expect(stored_metadata_file).to be_nil
- end
- end
- end
-
- context 'with an expire date' do
- let!(:artifacts) { file_upload }
- let(:default_artifacts_expire_in) {}
-
- let(:post_data) do
- { 'file.path' => artifacts.path,
- 'file.name' => artifacts.original_filename,
- 'expire_in' => expire_in }
- end
-
- before do
- stub_application_setting(
- default_artifacts_expire_in: default_artifacts_expire_in)
-
- post(post_url, post_data, headers_with_token)
- end
-
- context 'with an expire_in given' do
- let(:expire_in) { '7 days' }
-
- it 'updates when specified' do
- build.reload
- expect(response).to have_http_status(201)
- expect(json_response['artifacts_expire_at']).not_to be_empty
- expect(build.artifacts_expire_at)
- .to be_within(5.minutes).of(7.days.from_now)
- end
- end
-
- context 'with no expire_in given' do
- let(:expire_in) { nil }
-
- it 'ignores if not specified' do
- build.reload
- expect(response).to have_http_status(201)
- expect(json_response['artifacts_expire_at']).to be_nil
- expect(build.artifacts_expire_at).to be_nil
- end
-
- context 'with application default' do
- context 'default to 5 days' do
- let(:default_artifacts_expire_in) { '5 days' }
-
- it 'sets to application default' do
- build.reload
- expect(response).to have_http_status(201)
- expect(json_response['artifacts_expire_at'])
- .not_to be_empty
- expect(build.artifacts_expire_at)
- .to be_within(5.minutes).of(5.days.from_now)
- end
- end
-
- context 'default to 0' do
- let(:default_artifacts_expire_in) { '0' }
-
- it 'does not set expire_in' do
- build.reload
- expect(response).to have_http_status(201)
- expect(json_response['artifacts_expire_at']).to be_nil
- expect(build.artifacts_expire_at).to be_nil
- end
- end
- end
- end
- end
-
- context "artifacts file is too large" do
- it "fails to post too large artifact" do
- stub_application_setting(max_artifacts_size: 0)
- upload_artifacts(file_upload, headers_with_token)
- expect(response).to have_http_status(413)
- end
- end
-
- context "artifacts post request does not contain file" do
- it "fails to post artifacts without file" do
- post post_url, {}, headers_with_token
- expect(response).to have_http_status(400)
- end
- end
-
- context 'GitLab Workhorse is not configured' do
- it "fails to post artifacts without GitLab-Workhorse" do
- post post_url, { token: build.token }, {}
- expect(response).to have_http_status(403)
- end
- end
- end
-
- context "artifacts are being stored outside of tmp path" do
- before do
- # by configuring this path we allow to pass file from @tmpdir only
- # but all temporary files are stored in system tmp directory
- @tmpdir = Dir.mktmpdir
- allow(ArtifactUploader).to receive(:artifacts_upload_path).and_return(@tmpdir)
- end
-
- after do
- FileUtils.remove_entry @tmpdir
- end
-
- it "fails to post artifacts for outside of tmp path" do
- upload_artifacts(file_upload, headers_with_token)
- expect(response).to have_http_status(400)
- end
- end
-
- def upload_artifacts(file, headers = {}, accelerated = true)
- if accelerated
- post post_url, {
- 'file.path' => file.path,
- 'file.name' => file.original_filename
- }, headers
- else
- post post_url, { file: file }, headers
- end
- end
- end
-
- describe 'DELETE /builds/:id/artifacts' do
- let(:build) { create(:ci_build, :artifacts) }
-
- before do
- delete delete_url, token: build.token
- end
-
- shared_examples 'having removable artifacts' do
- it 'removes build artifacts' do
- build.reload
-
- expect(response).to have_http_status(200)
- expect(build.artifacts_file.exists?).to be_falsy
- expect(build.artifacts_metadata.exists?).to be_falsy
- expect(build.artifacts_size).to be_nil
- end
- end
-
- context 'when using build token' do
- before do
- delete delete_url, token: build.token
- end
-
- it_behaves_like 'having removable artifacts'
- end
-
- context 'when using runnners token' do
- before do
- delete delete_url, token: build.project.runners_token
- end
-
- it_behaves_like 'having removable artifacts'
- end
- end
-
- describe 'GET /builds/:id/artifacts' do
- before do
- get get_url, token: token
- end
-
- context 'build has artifacts' do
- let(:build) { create(:ci_build, :artifacts) }
- let(:download_headers) do
- { 'Content-Transfer-Encoding' => 'binary',
- 'Content-Disposition' => 'attachment; filename=ci_build_artifacts.zip' }
- end
-
- shared_examples 'having downloadable artifacts' do
- it 'download artifacts' do
- expect(response).to have_http_status(200)
- expect(response.headers).to include download_headers
- end
- end
-
- context 'when using build token' do
- let(:token) { build.token }
-
- it_behaves_like 'having downloadable artifacts'
- end
-
- context 'when using runnners token' do
- let(:token) { build.project.runners_token }
-
- it_behaves_like 'having downloadable artifacts'
- end
- end
-
- context 'build does not has artifacts' do
- let(:token) { build.token }
-
- it 'responds with not found' do
- expect(response).to have_http_status(404)
- end
- end
- end
- end
- end
-end
diff --git a/spec/requests/ci/api/runners_spec.rb b/spec/requests/ci/api/runners_spec.rb
deleted file mode 100644
index 75059dd20a0..00000000000
--- a/spec/requests/ci/api/runners_spec.rb
+++ /dev/null
@@ -1,127 +0,0 @@
-require 'spec_helper'
-
-describe Ci::API::Runners do
- include StubGitlabCalls
-
- let(:registration_token) { 'abcdefg123456' }
-
- before do
- stub_gitlab_calls
- stub_application_setting(runners_registration_token: registration_token)
- end
-
- describe "POST /runners/register" do
- context 'when runner token is provided' do
- before do
- post ci_api("/runners/register"), token: registration_token
- end
-
- it 'creates runner with default values' do
- expect(response).to have_http_status 201
- expect(Ci::Runner.first.run_untagged).to be true
- expect(Ci::Runner.first.token).not_to eq(registration_token)
- end
- end
-
- context 'when runner description is provided' do
- before do
- post ci_api("/runners/register"), token: registration_token,
- description: "server.hostname"
- end
-
- it 'creates runner' do
- expect(response).to have_http_status 201
- expect(Ci::Runner.first.description).to eq("server.hostname")
- end
- end
-
- context 'when runner tags are provided' do
- before do
- post ci_api("/runners/register"), token: registration_token,
- tag_list: "tag1, tag2"
- end
-
- it 'creates runner' do
- expect(response).to have_http_status 201
- expect(Ci::Runner.first.tag_list.sort).to eq(%w(tag1 tag2))
- end
- end
-
- context 'when option for running untagged jobs is provided' do
- context 'when tags are provided' do
- it 'creates runner' do
- post ci_api("/runners/register"), token: registration_token,
- run_untagged: false,
- tag_list: ['tag']
-
- expect(response).to have_http_status 201
- expect(Ci::Runner.first.run_untagged).to be false
- end
- end
-
- context 'when tags are not provided' do
- it 'does not create runner' do
- post ci_api("/runners/register"), token: registration_token,
- run_untagged: false
-
- expect(response).to have_http_status 404
- end
- end
- end
-
- context 'when project token is provided' do
- let(:project) { FactoryGirl.create(:project) }
-
- before do
- post ci_api("/runners/register"), token: project.runners_token
- end
-
- it 'creates runner' do
- expect(response).to have_http_status 201
- expect(project.runners.size).to eq(1)
- expect(Ci::Runner.first.token).not_to eq(registration_token)
- expect(Ci::Runner.first.token).not_to eq(project.runners_token)
- end
- end
-
- context 'when token is invalid' do
- it 'returns 403 error' do
- post ci_api("/runners/register"), token: 'invalid'
-
- expect(response).to have_http_status 403
- end
- end
-
- context 'when no token provided' do
- it 'returns 400 error' do
- post ci_api("/runners/register")
-
- expect(response).to have_http_status 400
- end
- end
-
- %w(name version revision platform architecture).each do |param|
- context "creates runner with #{param} saved" do
- let(:value) { "#{param}_value" }
-
- subject { Ci::Runner.first.read_attribute(param.to_sym) }
-
- it do
- post ci_api("/runners/register"), token: registration_token, info: { param => value }
- expect(response).to have_http_status 201
- is_expected.to eq(value)
- end
- end
- end
- end
-
- describe "DELETE /runners/delete" do
- it 'returns 200' do
- runner = FactoryGirl.create(:ci_runner)
- delete ci_api("/runners/delete"), token: runner.token
-
- expect(response).to have_http_status 200
- expect(Ci::Runner.count).to eq(0)
- end
- end
-end
diff --git a/spec/requests/ci/api/triggers_spec.rb b/spec/requests/ci/api/triggers_spec.rb
deleted file mode 100644
index 7c77ebb69a2..00000000000
--- a/spec/requests/ci/api/triggers_spec.rb
+++ /dev/null
@@ -1,90 +0,0 @@
-require 'spec_helper'
-
-describe Ci::API::Triggers do
- describe 'POST /projects/:project_id/refs/:ref/trigger' do
- let!(:trigger_token) { 'secure token' }
- let!(:project) { create(:project, :repository, ci_id: 10) }
- let!(:project2) { create(:project, ci_id: 11) }
-
- let!(:trigger) do
- create(:ci_trigger,
- project: project,
- token: trigger_token,
- owner: create(:user))
- end
-
- let(:options) do
- {
- token: trigger_token
- }
- end
-
- before do
- stub_ci_pipeline_to_return_yaml_file
-
- project.add_developer(trigger.owner)
- end
-
- context 'Handles errors' do
- it 'returns bad request if token is missing' do
- post ci_api("/projects/#{project.ci_id}/refs/master/trigger")
- expect(response).to have_http_status(400)
- end
-
- it 'returns not found if project is not found' do
- post ci_api('/projects/0/refs/master/trigger'), options
- expect(response).to have_http_status(404)
- end
-
- it 'returns unauthorized if token is for different project' do
- post ci_api("/projects/#{project2.ci_id}/refs/master/trigger"), options
- expect(response).to have_http_status(401)
- end
- end
-
- context 'Have a commit' do
- let(:pipeline) { project.pipelines.last }
-
- it 'creates builds' do
- post ci_api("/projects/#{project.ci_id}/refs/master/trigger"), options
- expect(response).to have_http_status(201)
- pipeline.builds.reload
- expect(pipeline.builds.pending.size).to eq(2)
- expect(pipeline.builds.size).to eq(5)
- end
-
- it 'returns bad request with no builds created if there\'s no commit for that ref' do
- post ci_api("/projects/#{project.ci_id}/refs/other-branch/trigger"), options
- expect(response).to have_http_status(400)
- expect(json_response['message']['base'])
- .to contain_exactly('Reference not found')
- end
-
- context 'Validates variables' do
- let(:variables) do
- { 'TRIGGER_KEY' => 'TRIGGER_VALUE' }
- end
-
- it 'validates variables to be a hash' do
- post ci_api("/projects/#{project.ci_id}/refs/master/trigger"), options.merge(variables: 'value')
- expect(response).to have_http_status(400)
-
- expect(json_response['error']).to eq('variables is invalid')
- end
-
- it 'validates variables needs to be a map of key-valued strings' do
- post ci_api("/projects/#{project.ci_id}/refs/master/trigger"), options.merge(variables: { key: %w(1 2) })
- expect(response).to have_http_status(400)
- expect(json_response['message']).to eq('variables needs to be a map of key-valued strings')
- end
-
- it 'creates trigger request with variables' do
- post ci_api("/projects/#{project.ci_id}/refs/master/trigger"), options.merge(variables: variables)
- expect(response).to have_http_status(201)
- pipeline.builds.reload
- expect(pipeline.builds.first.trigger_request.variables).to eq(variables)
- end
- end
- end
- end
-end
diff --git a/spec/services/ci/create_pipeline_service_spec.rb b/spec/services/ci/create_pipeline_service_spec.rb
index 53d4fcfed18..4ba3dada37c 100644
--- a/spec/services/ci/create_pipeline_service_spec.rb
+++ b/spec/services/ci/create_pipeline_service_spec.rb
@@ -55,10 +55,15 @@ describe Ci::CreatePipelineService do
context 'when merge requests already exist for this source branch' do
it 'updates head pipeline of each merge request' do
- merge_request_1 = create(:merge_request, source_branch: 'master', target_branch: "branch_1", source_project: project)
- merge_request_2 = create(:merge_request, source_branch: 'master', target_branch: "branch_2", source_project: project)
+ merge_request_1 = create(:merge_request, source_branch: 'master',
+ target_branch: "branch_1",
+ source_project: project)
- head_pipeline = pipeline
+ merge_request_2 = create(:merge_request, source_branch: 'master',
+ target_branch: "branch_2",
+ source_project: project)
+
+ head_pipeline = execute_service
expect(merge_request_1.reload.head_pipeline).to eq(head_pipeline)
expect(merge_request_2.reload.head_pipeline).to eq(head_pipeline)
@@ -66,9 +71,11 @@ describe Ci::CreatePipelineService do
context 'when there is no pipeline for source branch' do
it "does not update merge request head pipeline" do
- merge_request = create(:merge_request, source_branch: 'feature', target_branch: "branch_1", source_project: project)
+ merge_request = create(:merge_request, source_branch: 'feature',
+ target_branch: "branch_1",
+ source_project: project)
- head_pipeline = pipeline
+ head_pipeline = execute_service
expect(merge_request.reload.head_pipeline).not_to eq(head_pipeline)
end
@@ -76,13 +83,19 @@ describe Ci::CreatePipelineService do
context 'when merge request target project is different from source project' do
let!(:target_project) { create(:project, :repository) }
- let!(:forked_project_link) { create(:forked_project_link, forked_to_project: project, forked_from_project: target_project) }
+
+ let!(:forked_project_link) do
+ create(:forked_project_link, forked_to_project: project,
+ forked_from_project: target_project)
+ end
it 'updates head pipeline for merge request' do
- merge_request =
- create(:merge_request, source_branch: 'master', target_branch: "branch_1", source_project: project, target_project: target_project)
+ merge_request = create(:merge_request, source_branch: 'master',
+ target_branch: "branch_1",
+ source_project: project,
+ target_project: target_project)
- head_pipeline = pipeline
+ head_pipeline = execute_service
expect(merge_request.reload.head_pipeline).to eq(head_pipeline)
end
@@ -90,15 +103,36 @@ describe Ci::CreatePipelineService do
context 'when the pipeline is not the latest for the branch' do
it 'does not update merge request head pipeline' do
- merge_request = create(:merge_request, source_branch: 'master', target_branch: "branch_1", source_project: project)
+ merge_request = create(:merge_request, source_branch: 'master',
+ target_branch: "branch_1",
+ source_project: project)
- allow_any_instance_of(Ci::Pipeline).to receive(:latest?).and_return(false)
+ allow_any_instance_of(Ci::Pipeline)
+ .to receive(:latest?).and_return(false)
- pipeline
+ execute_service
expect(merge_request.reload.head_pipeline).to be_nil
end
end
+
+ context 'when pipeline has errors' do
+ before do
+ stub_ci_pipeline_yaml_file('some invalid syntax')
+ end
+
+ it 'updates merge request head pipeline reference' do
+ merge_request = create(:merge_request, source_branch: 'master',
+ target_branch: 'feature',
+ source_project: project)
+
+ head_pipeline = execute_service
+
+ expect(head_pipeline).to be_persisted
+ expect(head_pipeline.yaml_errors).to be_present
+ expect(merge_request.reload.head_pipeline).to eq head_pipeline
+ end
+ end
end
context 'auto-cancel enabled' do
@@ -379,14 +413,12 @@ describe Ci::CreatePipelineService do
end
context 'when trigger belongs to a developer' do
- let(:user) {}
+ let(:user) { create(:user) }
+ let(:trigger) { create(:ci_trigger, owner: user) }
+ let(:trigger_request) { create(:ci_trigger_request, trigger: trigger) }
- let(:trigger_request) do
- create(:ci_trigger_request).tap do |request|
- user = create(:user)
- project.add_developer(user)
- request.trigger.update(owner: user)
- end
+ before do
+ project.add_developer(user)
end
it 'does not create a pipeline' do
@@ -397,17 +429,15 @@ describe Ci::CreatePipelineService do
end
context 'when trigger belongs to a master' do
- let(:user) {}
+ let(:user) { create(:user) }
+ let(:trigger) { create(:ci_trigger, owner: user) }
+ let(:trigger_request) { create(:ci_trigger_request, trigger: trigger) }
- let(:trigger_request) do
- create(:ci_trigger_request).tap do |request|
- user = create(:user)
- project.add_master(user)
- request.trigger.update(owner: user)
- end
+ before do
+ project.add_master(user)
end
- it 'does not create a pipeline' do
+ it 'creates a pipeline' do
expect(execute_service(trigger_request: trigger_request))
.to be_persisted
expect(Ci::Pipeline.count).to eq(1)
@@ -436,7 +466,8 @@ describe Ci::CreatePipelineService do
context 'when ref is not protected' do
context 'when trigger belongs to no one' do
let(:user) {}
- let(:trigger_request) { create(:ci_trigger_request) }
+ let(:trigger) { create(:ci_trigger, owner: nil) }
+ let(:trigger_request) { create(:ci_trigger_request, trigger: trigger) }
it 'creates a pipeline' do
expect(execute_service(trigger_request: trigger_request))
diff --git a/spec/services/files/update_service_spec.rb b/spec/services/files/update_service_spec.rb
index cc950ae6bb3..2b4f8cd42ee 100644
--- a/spec/services/files/update_service_spec.rb
+++ b/spec/services/files/update_service_spec.rb
@@ -76,7 +76,7 @@ describe Files::UpdateService do
let(:branch_name) { "#{project.default_branch}-new" }
it 'fires hooks only once' do
- expect(GitHooksService).to receive(:new).once.and_call_original
+ expect(Gitlab::Git::HooksService).to receive(:new).once.and_call_original
subject.execute
end
diff --git a/spec/services/git_push_service_spec.rb b/spec/services/git_push_service_spec.rb
index e3c1bdce300..cc3d4e7da49 100644
--- a/spec/services/git_push_service_spec.rb
+++ b/spec/services/git_push_service_spec.rb
@@ -617,7 +617,7 @@ describe GitPushService, services: true do
context 'on the default branch' do
before do
- allow(service).to receive(:is_default_branch?).and_return(true)
+ allow(service).to receive(:default_branch?).and_return(true)
end
it 'flushes the caches of any special files that have been changed' do
@@ -638,7 +638,7 @@ describe GitPushService, services: true do
context 'on a non-default branch' do
before do
- allow(service).to receive(:is_default_branch?).and_return(false)
+ allow(service).to receive(:default_branch?).and_return(false)
end
it 'does not flush any conditional caches' do
diff --git a/spec/services/groups/create_service_spec.rb b/spec/services/groups/create_service_spec.rb
index b2175717a70..10dda45d2a1 100644
--- a/spec/services/groups/create_service_spec.rb
+++ b/spec/services/groups/create_service_spec.rb
@@ -22,7 +22,7 @@ describe Groups::CreateService, '#execute' do
end
end
- describe 'creating subgroup' do
+ describe 'creating subgroup', :nested_groups do
let!(:group) { create(:group) }
let!(:service) { described_class.new(user, group_params.merge(parent_id: group.id)) }
@@ -32,12 +32,24 @@ describe Groups::CreateService, '#execute' do
end
it { is_expected.to be_persisted }
+
+ context 'when nested groups feature is disabled' do
+ it 'does not save group and returns an error' do
+ allow(Group).to receive(:supports_nested_groups?).and_return(false)
+
+ is_expected.not_to be_persisted
+ expect(subject.errors[:parent_id]).to include('You don’t have permission to create a subgroup in this group.')
+ expect(subject.parent_id).to be_nil
+ end
+ end
end
context 'as guest' do
it 'does not save group and returns an error' do
+ allow(Group).to receive(:supports_nested_groups?).and_return(true)
+
is_expected.not_to be_persisted
- expect(subject.errors[:parent_id].first).to eq('manage access required to create subgroup')
+ expect(subject.errors[:parent_id].first).to eq('You don’t have permission to create a subgroup in this group.')
expect(subject.parent_id).to be_nil
end
end
diff --git a/spec/services/groups/destroy_service_spec.rb b/spec/services/groups/destroy_service_spec.rb
index 1b2ce3cd03e..ac4b9c02ba7 100644
--- a/spec/services/groups/destroy_service_spec.rb
+++ b/spec/services/groups/destroy_service_spec.rb
@@ -8,8 +8,8 @@ describe Groups::DestroyService do
let!(:nested_group) { create(:group, parent: group) }
let!(:project) { create(:project, namespace: group) }
let!(:notification_setting) { create(:notification_setting, source: group)}
- let!(:gitlab_shell) { Gitlab::Shell.new }
- let!(:remove_path) { group.path + "+#{group.id}+deleted" }
+ let(:gitlab_shell) { Gitlab::Shell.new }
+ let(:remove_path) { group.path + "+#{group.id}+deleted" }
before do
group.add_user(user, Gitlab::Access::OWNER)
@@ -134,4 +134,26 @@ describe Groups::DestroyService do
it_behaves_like 'group destruction', false
end
+
+ describe 'repository removal' do
+ before do
+ destroy_group(group, user, false)
+ end
+
+ context 'legacy storage' do
+ let!(:project) { create(:project, :empty_repo, namespace: group) }
+
+ it 'removes repository' do
+ expect(gitlab_shell.exists?(project.repository_storage_path, "#{project.disk_path}.git")).to be_falsey
+ end
+ end
+
+ context 'hashed storage' do
+ let!(:project) { create(:project, :hashed, :empty_repo, namespace: group) }
+
+ it 'removes repository' do
+ expect(gitlab_shell.exists?(project.repository_storage_path, "#{project.disk_path}.git")).to be_falsey
+ end
+ end
+ end
end
diff --git a/spec/services/groups/nested_create_service_spec.rb b/spec/services/groups/nested_create_service_spec.rb
new file mode 100644
index 00000000000..6491fb34777
--- /dev/null
+++ b/spec/services/groups/nested_create_service_spec.rb
@@ -0,0 +1,88 @@
+require 'spec_helper'
+
+describe Groups::NestedCreateService do
+ let(:user) { create(:user) }
+
+ subject(:service) { described_class.new(user, params) }
+
+ shared_examples 'with a visibility level' do
+ it 'creates the group with correct visibility level' do
+ allow(Gitlab::CurrentSettings.current_application_settings)
+ .to receive(:default_group_visibility) { Gitlab::VisibilityLevel::INTERNAL }
+
+ group = service.execute
+
+ expect(group.visibility_level).to eq(Gitlab::VisibilityLevel::INTERNAL)
+ end
+
+ context 'adding a visibility level ' do
+ it 'overwrites the visibility level' do
+ service = described_class.new(user, params.merge(visibility_level: Gitlab::VisibilityLevel::PRIVATE))
+
+ group = service.execute
+
+ expect(group.visibility_level).to eq(Gitlab::VisibilityLevel::PRIVATE)
+ end
+ end
+ end
+
+ describe 'without subgroups' do
+ let(:params) { { group_path: 'a-group' } }
+
+ before do
+ allow(Group).to receive(:supports_nested_groups?) { false }
+ end
+
+ it 'creates the group' do
+ group = service.execute
+
+ expect(group).to be_persisted
+ end
+
+ it 'returns the group if it already existed' do
+ existing_group = create(:group, path: 'a-group')
+
+ expect(service.execute).to eq(existing_group)
+ end
+
+ it 'raises an error when tring to create a subgroup' do
+ service = described_class.new(user, group_path: 'a-group/a-sub-group')
+
+ expect { service.execute }.to raise_error('Nested groups are not supported on MySQL')
+ end
+
+ it_behaves_like 'with a visibility level'
+ end
+
+ describe 'with subgroups', :nested_groups do
+ let(:params) { { group_path: 'a-group/a-sub-group' } }
+
+ describe "#execute" do
+ it 'returns the group if it already existed' do
+ parent = create(:group, path: 'a-group', owner: user)
+ child = create(:group, path: 'a-sub-group', parent: parent, owner: user)
+
+ expect(service.execute).to eq(child)
+ end
+
+ it 'reuses a parent if it already existed' do
+ parent = create(:group, path: 'a-group')
+ parent.add_owner(user)
+
+ expect(service.execute.parent).to eq(parent)
+ end
+
+ it 'creates group and subgroup in the database' do
+ service.execute
+
+ parent = Group.find_by_full_path('a-group')
+ child = parent.children.find_by(path: 'a-sub-group')
+
+ expect(parent).not_to be_nil
+ expect(child).not_to be_nil
+ end
+
+ it_behaves_like 'with a visibility level'
+ end
+ end
+end
diff --git a/spec/services/issues/close_service_spec.rb b/spec/services/issues/close_service_spec.rb
index a03f68434de..171f70c32a8 100644
--- a/spec/services/issues/close_service_spec.rb
+++ b/spec/services/issues/close_service_spec.rb
@@ -42,6 +42,11 @@ describe Issues::CloseService do
service.execute(issue)
end
+ it 'refreshes the number of open issues' do
+ expect { service.execute(issue) }
+ .to change { project.open_issues_count }.from(1).to(0)
+ end
+
it 'invalidates counter cache for assignees' do
expect_any_instance_of(User).to receive(:invalidate_issue_cache_counts)
diff --git a/spec/services/issues/create_service_spec.rb b/spec/services/issues/create_service_spec.rb
index 9b2d9e79f4f..cc3d648c340 100644
--- a/spec/services/issues/create_service_spec.rb
+++ b/spec/services/issues/create_service_spec.rb
@@ -35,6 +35,10 @@ describe Issues::CreateService do
expect(issue.due_date).to eq Date.tomorrow
end
+ it 'refreshes the number of open issues' do
+ expect { issue }.to change { project.open_issues_count }.from(0).to(1)
+ end
+
context 'when current user cannot admin issues in the project' do
let(:guest) { create(:user) }
@@ -366,7 +370,7 @@ describe Issues::CreateService do
context 'when recaptcha was not verified' do
context 'when akismet detects spam' do
before do
- allow_any_instance_of(AkismetService).to receive(:is_spam?).and_return(true)
+ allow_any_instance_of(AkismetService).to receive(:spam?).and_return(true)
end
it 'marks an issue as a spam ' do
@@ -388,7 +392,7 @@ describe Issues::CreateService do
context 'when akismet does not detect spam' do
before do
- allow_any_instance_of(AkismetService).to receive(:is_spam?).and_return(false)
+ allow_any_instance_of(AkismetService).to receive(:spam?).and_return(false)
end
it 'does not mark an issue as a spam ' do
diff --git a/spec/services/issues/reopen_service_spec.rb b/spec/services/issues/reopen_service_spec.rb
index 205e9ebd237..48fc98b3b2f 100644
--- a/spec/services/issues/reopen_service_spec.rb
+++ b/spec/services/issues/reopen_service_spec.rb
@@ -34,6 +34,13 @@ describe Issues::ReopenService do
described_class.new(project, user).execute(issue)
end
+ it 'refreshes the number of opened issues' do
+ service = described_class.new(project, user)
+
+ expect { service.execute(issue) }
+ .to change { project.open_issues_count }.from(0).to(1)
+ end
+
context 'when issue is not confidential' do
it 'executes issue hooks' do
expect(project).to receive(:execute_hooks).with(an_instance_of(Hash), :issue_hooks)
diff --git a/spec/services/merge_requests/close_service_spec.rb b/spec/services/merge_requests/close_service_spec.rb
index 04bf267d167..7e65369762c 100644
--- a/spec/services/merge_requests/close_service_spec.rb
+++ b/spec/services/merge_requests/close_service_spec.rb
@@ -52,6 +52,13 @@ describe MergeRequests::CloseService do
end
end
+ it 'refreshes the number of open merge requests for a valid MR' do
+ service = described_class.new(project, user, {})
+
+ expect { service.execute(merge_request) }
+ .to change { project.open_merge_requests_count }.from(1).to(0)
+ end
+
context 'current user is not authorized to close merge request' do
before do
perform_enqueued_jobs do
diff --git a/spec/services/merge_requests/create_from_issue_service_spec.rb b/spec/services/merge_requests/create_from_issue_service_spec.rb
index 492b55cdece..313f87ae1f6 100644
--- a/spec/services/merge_requests/create_from_issue_service_spec.rb
+++ b/spec/services/merge_requests/create_from_issue_service_spec.rb
@@ -2,8 +2,10 @@ require 'spec_helper'
describe MergeRequests::CreateFromIssueService do
let(:project) { create(:project, :repository) }
- let(:user) { create(:user) }
- let(:issue) { create(:issue, project: project) }
+ let(:user) { create(:user) }
+ let(:label_ids) { create_pair(:label, project: project).map(&:id) }
+ let(:milestone_id) { create(:milestone, project: project).id }
+ let(:issue) { create(:issue, project: project, milestone_id: milestone_id) }
subject(:service) { described_class.new(project, user, issue_iid: issue.iid) }
@@ -25,6 +27,20 @@ describe MergeRequests::CreateFromIssueService do
described_class.new(project, user, issue_iid: -1).execute
end
+ it "inherits labels" do
+ issue.assign_attributes(label_ids: label_ids)
+
+ result = service.execute
+
+ expect(result[:merge_request].label_ids).to eq(label_ids)
+ end
+
+ it "inherits milestones" do
+ result = service.execute
+
+ expect(result[:merge_request].milestone_id).to eq(milestone_id)
+ end
+
it 'delegates the branch creation to CreateBranchService' do
expect_any_instance_of(CreateBranchService).to receive(:execute).once.and_call_original
diff --git a/spec/services/merge_requests/create_service_spec.rb b/spec/services/merge_requests/create_service_spec.rb
index a1f3bec42cc..d6409c0d625 100644
--- a/spec/services/merge_requests/create_service_spec.rb
+++ b/spec/services/merge_requests/create_service_spec.rb
@@ -18,31 +18,35 @@ describe MergeRequests::CreateService do
end
let(:service) { described_class.new(project, user, opts) }
+ let(:merge_request) { service.execute }
before do
project.team << [user, :master]
project.team << [assignee, :developer]
allow(service).to receive(:execute_hooks)
-
- @merge_request = service.execute
end
it 'creates an MR' do
- expect(@merge_request).to be_valid
- expect(@merge_request.title).to eq('Awesome merge_request')
- expect(@merge_request.assignee).to be_nil
- expect(@merge_request.merge_params['force_remove_source_branch']).to eq('1')
+ expect(merge_request).to be_valid
+ expect(merge_request.title).to eq('Awesome merge_request')
+ expect(merge_request.assignee).to be_nil
+ expect(merge_request.merge_params['force_remove_source_branch']).to eq('1')
end
it 'executes hooks with default action' do
- expect(service).to have_received(:execute_hooks).with(@merge_request)
+ expect(service).to have_received(:execute_hooks).with(merge_request)
+ end
+
+ it 'refreshes the number of open merge requests' do
+ expect { service.execute }
+ .to change { project.open_merge_requests_count }.from(0).to(1)
end
it 'does not creates todos' do
attributes = {
project: project,
- target_id: @merge_request.id,
- target_type: @merge_request.class.name
+ target_id: merge_request.id,
+ target_type: merge_request.class.name
}
expect(Todo.where(attributes).count).to be_zero
@@ -51,8 +55,8 @@ describe MergeRequests::CreateService do
it 'creates exactly 1 create MR event' do
attributes = {
action: Event::CREATED,
- target_id: @merge_request.id,
- target_type: @merge_request.class.name
+ target_id: merge_request.id,
+ target_type: merge_request.class.name
}
expect(Event.where(attributes).count).to eq(1)
@@ -69,15 +73,15 @@ describe MergeRequests::CreateService do
}
end
- it { expect(@merge_request.assignee).to eq assignee }
+ it { expect(merge_request.assignee).to eq assignee }
it 'creates a todo for new assignee' do
attributes = {
project: project,
author: user,
user: assignee,
- target_id: @merge_request.id,
- target_type: @merge_request.class.name,
+ target_id: merge_request.id,
+ target_type: merge_request.class.name,
action: Todo::ASSIGNED,
state: :pending
}
diff --git a/spec/services/merge_requests/merge_service_spec.rb b/spec/services/merge_requests/merge_service_spec.rb
index e593bfeeaf7..b60136064b7 100644
--- a/spec/services/merge_requests/merge_service_spec.rb
+++ b/spec/services/merge_requests/merge_service_spec.rb
@@ -12,6 +12,38 @@ describe MergeRequests::MergeService do
end
describe '#execute' do
+ context 'MergeRequest#merge_jid' do
+ before do
+ merge_request.update_column(:merge_jid, 'hash-123')
+ end
+
+ it 'is cleaned when no error is raised' do
+ service = described_class.new(project, user, commit_message: 'Awesome message')
+
+ service.execute(merge_request)
+
+ expect(merge_request.reload.merge_jid).to be_nil
+ end
+
+ it 'is cleaned when expected error is raised' do
+ service = described_class.new(project, user, commit_message: 'Awesome message')
+ allow(service).to receive(:commit).and_raise(described_class::MergeError)
+
+ service.execute(merge_request)
+
+ expect(merge_request.reload.merge_jid).to be_nil
+ end
+
+ it 'is not cleaned when unexpected error is raised' do
+ service = described_class.new(project, user, commit_message: 'Awesome message')
+ allow(service).to receive(:commit).and_raise(StandardError)
+
+ expect { service.execute(merge_request) }.to raise_error(StandardError)
+
+ expect(merge_request.reload.merge_jid).to be_present
+ end
+ end
+
context 'valid params' do
let(:service) { described_class.new(project, user, commit_message: 'Awesome message') }
@@ -217,7 +249,7 @@ describe MergeRequests::MergeService do
it 'logs and saves error if there is an PreReceiveError exception' do
error_message = 'error message'
- allow(service).to receive(:repository).and_raise(GitHooksService::PreReceiveError, error_message)
+ allow(service).to receive(:repository).and_raise(Gitlab::Git::HooksService::PreReceiveError, error_message)
allow(service).to receive(:execute_hooks)
service.execute(merge_request)
diff --git a/spec/services/merge_requests/reopen_service_spec.rb b/spec/services/merge_requests/reopen_service_spec.rb
index f02af0c582e..fa652611c6b 100644
--- a/spec/services/merge_requests/reopen_service_spec.rb
+++ b/spec/services/merge_requests/reopen_service_spec.rb
@@ -47,6 +47,13 @@ describe MergeRequests::ReopenService do
end
end
+ it 'refreshes the number of open merge requests for a valid MR' do
+ service = described_class.new(project, user, {})
+
+ expect { service.execute(merge_request) }
+ .to change { project.open_merge_requests_count }.from(0).to(1)
+ end
+
context 'current user is not authorized to reopen merge request' do
before do
perform_enqueued_jobs do
diff --git a/spec/services/notification_service_spec.rb b/spec/services/notification_service_spec.rb
index 44b2d28d1d4..5b349017c8b 100644
--- a/spec/services/notification_service_spec.rb
+++ b/spec/services/notification_service_spec.rb
@@ -130,7 +130,18 @@ describe NotificationService, :mailer do
project.add_master(issue.author)
project.add_master(assignee)
project.add_master(note.author)
- create(:note_on_issue, noteable: issue, project_id: issue.project_id, note: '@subscribed_participant cc this guy')
+
+ @u_custom_off = create_user_with_notification(:custom, 'custom_off')
+ project.add_guest(@u_custom_off)
+
+ create(
+ :note_on_issue,
+ author: @u_custom_off,
+ noteable: issue,
+ project_id: issue.project_id,
+ note: 'i think @subscribed_participant should see this'
+ )
+
update_custom_notification(:new_note, @u_guest_custom, resource: project)
update_custom_notification(:new_note, @u_custom_global)
end
@@ -140,8 +151,7 @@ describe NotificationService, :mailer do
add_users_with_subscription(note.project, issue)
reset_delivered_emails!
- # Ensure create SentNotification by noteable = issue 6 times, not noteable = note
- expect(SentNotification).to receive(:record).with(issue, any_args).exactly(8).times
+ expect(SentNotification).to receive(:record).with(issue, any_args).exactly(9).times
notification.new_note(note)
@@ -153,6 +163,7 @@ describe NotificationService, :mailer do
should_email(@subscriber)
should_email(@watcher_and_subscriber)
should_email(@subscribed_participant)
+ should_email(@u_custom_off)
should_not_email(@u_guest_custom)
should_not_email(@u_guest_watcher)
should_not_email(note.author)
diff --git a/spec/services/projects/count_service_spec.rb b/spec/services/projects/count_service_spec.rb
new file mode 100644
index 00000000000..79b01e7620e
--- /dev/null
+++ b/spec/services/projects/count_service_spec.rb
@@ -0,0 +1,73 @@
+require 'spec_helper'
+
+describe Projects::CountService do
+ let(:project) { build(:project, id: 1) }
+ let(:service) { described_class.new(project) }
+
+ describe '#relation_for_count' do
+ it 'raises NotImplementedError' do
+ expect { service.relation_for_count }.to raise_error(NotImplementedError)
+ end
+ end
+
+ describe '#count' do
+ before do
+ allow(service).to receive(:cache_key_name).and_return('count_service')
+ end
+
+ it 'returns the number of rows' do
+ allow(service).to receive(:uncached_count).and_return(1)
+
+ expect(service.count).to eq(1)
+ end
+
+ it 'caches the number of rows', :use_clean_rails_memory_store_caching do
+ expect(service).to receive(:uncached_count).once.and_return(1)
+
+ 2.times do
+ expect(service.count).to eq(1)
+ end
+ end
+ end
+
+ describe '#refresh_cache', :use_clean_rails_memory_store_caching do
+ before do
+ allow(service).to receive(:cache_key_name).and_return('count_service')
+ end
+
+ it 'refreshes the cache' do
+ expect(service).to receive(:uncached_count).once.and_return(1)
+
+ service.refresh_cache
+
+ expect(service.count).to eq(1)
+ end
+ end
+
+ describe '#delete_cache', :use_clean_rails_memory_store_caching do
+ before do
+ allow(service).to receive(:cache_key_name).and_return('count_service')
+ end
+
+ it 'removes the cache' do
+ expect(service).to receive(:uncached_count).twice.and_return(1)
+
+ service.count
+ service.delete_cache
+ service.count
+ end
+ end
+
+ describe '#cache_key_name' do
+ it 'raises NotImplementedError' do
+ expect { service.cache_key_name }.to raise_error(NotImplementedError)
+ end
+ end
+
+ describe '#cache_key' do
+ it 'returns the cache key as an Array' do
+ allow(service).to receive(:cache_key_name).and_return('count_service')
+ expect(service.cache_key).to eq(['projects', 1, 'count_service'])
+ end
+ end
+end
diff --git a/spec/services/projects/create_service_spec.rb b/spec/services/projects/create_service_spec.rb
index b0dc7488b5f..088b7b4fc04 100644
--- a/spec/services/projects/create_service_spec.rb
+++ b/spec/services/projects/create_service_spec.rb
@@ -38,7 +38,7 @@ describe Projects::CreateService, '#execute' do
expect(project).to be_persisted
expect(project.owner).to eq(user)
- expect(project.team.masters).to include(user, admin)
+ expect(project.team.masters).to contain_exactly(user)
expect(project.namespace).to eq(user.namespace)
end
end
diff --git a/spec/services/projects/forks_count_service_spec.rb b/spec/services/projects/forks_count_service_spec.rb
index cf299c5d09b..9f8e7ee18a8 100644
--- a/spec/services/projects/forks_count_service_spec.rb
+++ b/spec/services/projects/forks_count_service_spec.rb
@@ -1,40 +1,14 @@
require 'spec_helper'
describe Projects::ForksCountService do
- let(:project) { build(:project, id: 42) }
- let(:service) { described_class.new(project) }
-
describe '#count' do
it 'returns the number of forks' do
- allow(service).to receive(:uncached_count).and_return(1)
-
- expect(service.count).to eq(1)
- end
-
- it 'caches the forks count', :use_clean_rails_memory_store_caching do
- expect(service).to receive(:uncached_count).once.and_return(1)
+ project = build(:project, id: 42)
+ service = described_class.new(project)
- 2.times { service.count }
- end
- end
-
- describe '#refresh_cache', :use_clean_rails_memory_store_caching do
- it 'refreshes the cache' do
- expect(service).to receive(:uncached_count).once.and_return(1)
-
- service.refresh_cache
+ allow(service).to receive(:uncached_count).and_return(1)
expect(service.count).to eq(1)
end
end
-
- describe '#delete_cache', :use_clean_rails_memory_store_caching do
- it 'removes the cache' do
- expect(service).to receive(:uncached_count).twice.and_return(1)
-
- service.count
- service.delete_cache
- service.count
- end
- end
end
diff --git a/spec/services/projects/open_issues_count_service_spec.rb b/spec/services/projects/open_issues_count_service_spec.rb
new file mode 100644
index 00000000000..f964f9972cd
--- /dev/null
+++ b/spec/services/projects/open_issues_count_service_spec.rb
@@ -0,0 +1,21 @@
+require 'spec_helper'
+
+describe Projects::OpenIssuesCountService do
+ describe '#count' do
+ it 'returns the number of open issues' do
+ project = create(:project)
+ create(:issue, :opened, project: project)
+
+ expect(described_class.new(project).count).to eq(1)
+ end
+
+ it 'does not include confidential issues in the issue count' do
+ project = create(:project)
+
+ create(:issue, :opened, project: project)
+ create(:issue, :opened, confidential: true, project: project)
+
+ expect(described_class.new(project).count).to eq(1)
+ end
+ end
+end
diff --git a/spec/services/projects/open_merge_requests_count_service_spec.rb b/spec/services/projects/open_merge_requests_count_service_spec.rb
new file mode 100644
index 00000000000..9f49b9ec6a2
--- /dev/null
+++ b/spec/services/projects/open_merge_requests_count_service_spec.rb
@@ -0,0 +1,15 @@
+require 'spec_helper'
+
+describe Projects::OpenMergeRequestsCountService do
+ describe '#count' do
+ it 'returns the number of open merge requests' do
+ project = create(:project)
+ create(:merge_request,
+ :opened,
+ source_project: project,
+ target_project: project)
+
+ expect(described_class.new(project).count).to eq(1)
+ end
+ end
+end
diff --git a/spec/services/spam_service_spec.rb b/spec/services/spam_service_spec.rb
index a14dfa3f01f..61312d55b84 100644
--- a/spec/services/spam_service_spec.rb
+++ b/spec/services/spam_service_spec.rb
@@ -23,7 +23,7 @@ describe SpamService do
before do
issue.closed_at = Time.zone.now
- allow(AkismetService).to receive(:new).and_return(double(is_spam?: true))
+ allow(AkismetService).to receive(:new).and_return(double(spam?: true))
end
it 'returns false' do
@@ -43,7 +43,7 @@ describe SpamService do
context 'when indicated as spam by akismet' do
before do
- allow(AkismetService).to receive(:new).and_return(double(is_spam?: true))
+ allow(AkismetService).to receive(:new).and_return(double(spam?: true))
end
it 'doesnt check as spam when request is missing' do
@@ -71,7 +71,7 @@ describe SpamService do
context 'when not indicated as spam by akismet' do
before do
- allow(AkismetService).to receive(:new).and_return(double(is_spam?: false))
+ allow(AkismetService).to receive(:new).and_return(double(spam?: false))
end
it 'returns false' do
diff --git a/spec/services/system_note_service_spec.rb b/spec/services/system_note_service_spec.rb
index 6d36affa9dc..e6a18654651 100644
--- a/spec/services/system_note_service_spec.rb
+++ b/spec/services/system_note_service_spec.rb
@@ -13,37 +13,16 @@ describe SystemNoteService do
let(:expected_noteable) { noteable }
let(:commit_count) { nil }
- it 'is valid' do
+ it 'has the correct attributes', :aggregate_failures do
expect(subject).to be_valid
- end
+ expect(subject).to be_system
- it 'sets the noteable model' do
expect(subject.noteable).to eq expected_noteable
- end
-
- it 'sets the project' do
expect(subject.project).to eq project
- end
-
- it 'sets the author' do
expect(subject.author).to eq author
- end
- it 'is a system note' do
- expect(subject).to be_system
- end
-
- context 'metadata' do
- it 'creates a new system note metadata record' do
- expect { subject }.to change { SystemNoteMetadata.count }.from(0).to(1)
- end
-
- it 'creates a record correctly' do
- metadata = subject.system_note_metadata
-
- expect(metadata.commit_count).to eq(commit_count)
- expect(metadata.action).to eq(action)
- end
+ expect(subject.system_note_metadata.action).to eq(action)
+ expect(subject.system_note_metadata.commit_count).to eq(commit_count)
end
end
diff --git a/spec/services/tags/create_service_spec.rb b/spec/services/tags/create_service_spec.rb
index 1b31ce29f7a..57013b54560 100644
--- a/spec/services/tags/create_service_spec.rb
+++ b/spec/services/tags/create_service_spec.rb
@@ -41,7 +41,7 @@ describe Tags::CreateService do
it 'returns an error' do
expect(repository).to receive(:add_tag)
.with(user, 'v1.1.0', 'master', 'Foo')
- .and_raise(GitHooksService::PreReceiveError, 'something went wrong')
+ .and_raise(Gitlab::Git::HooksService::PreReceiveError, 'something went wrong')
response = service.execute('v1.1.0', 'master', 'Foo')
diff --git a/spec/services/test_hooks/system_service_spec.rb b/spec/services/test_hooks/system_service_spec.rb
index 00d89924766..a15708bf82f 100644
--- a/spec/services/test_hooks/system_service_spec.rb
+++ b/spec/services/test_hooks/system_service_spec.rb
@@ -7,7 +7,6 @@ describe TestHooks::SystemService do
let(:project) { create(:project, :repository) }
let(:hook) { create(:system_hook) }
let(:service) { described_class.new(hook, current_user, trigger) }
- let(:sample_data) { { data: 'sample' }}
let(:success_result) { { status: :success, http_status: 200, message: 'ok' } }
before do
@@ -26,18 +25,11 @@ describe TestHooks::SystemService do
context 'push_events' do
let(:trigger) { 'push_events' }
- it 'returns error message if not enough data' do
- allow(project).to receive(:empty_repo?).and_return(true)
-
- expect(hook).not_to receive(:execute)
- expect(service.execute).to include({ status: :error, message: "Ensure project \"#{project.human_name}\" has commits." })
- end
-
it 'executes hook' do
allow(project).to receive(:empty_repo?).and_return(false)
- allow(Gitlab::DataBuilder::Push).to receive(:build_sample).and_return(sample_data)
+ expect(Gitlab::DataBuilder::Push).to receive(:sample_data).and_call_original
- expect(hook).to receive(:execute).with(sample_data, trigger).and_return(success_result)
+ expect(hook).to receive(:execute).with(Gitlab::DataBuilder::Push::SAMPLE_DATA, trigger).and_return(success_result)
expect(service.execute).to include(success_result)
end
end
@@ -45,18 +37,11 @@ describe TestHooks::SystemService do
context 'tag_push_events' do
let(:trigger) { 'tag_push_events' }
- it 'returns error message if not enough data' do
- allow(project.repository).to receive(:tags).and_return([])
-
- expect(hook).not_to receive(:execute)
- expect(service.execute).to include({ status: :error, message: "Ensure project \"#{project.human_name}\" has tags." })
- end
-
it 'executes hook' do
allow(project.repository).to receive(:tags).and_return(['tag'])
- allow(Gitlab::DataBuilder::Push).to receive(:build_sample).and_return(sample_data)
+ expect(Gitlab::DataBuilder::Push).to receive(:sample_data).and_call_original
- expect(hook).to receive(:execute).with(sample_data, trigger).and_return(success_result)
+ expect(hook).to receive(:execute).with(Gitlab::DataBuilder::Push::SAMPLE_DATA, trigger).and_return(success_result)
expect(service.execute).to include(success_result)
end
end
@@ -64,17 +49,11 @@ describe TestHooks::SystemService do
context 'repository_update_events' do
let(:trigger) { 'repository_update_events' }
- it 'returns error message if not enough data' do
- allow(project).to receive(:commit).and_return(nil)
- expect(hook).not_to receive(:execute)
- expect(service.execute).to include({ status: :error, message: "Ensure project \"#{project.human_name}\" has commits." })
- end
-
it 'executes hook' do
allow(project).to receive(:empty_repo?).and_return(false)
- allow(Gitlab::DataBuilder::Repository).to receive(:update).and_return(sample_data)
+ expect(Gitlab::DataBuilder::Repository).to receive(:sample_data).and_call_original
- expect(hook).to receive(:execute).with(sample_data, trigger).and_return(success_result)
+ expect(hook).to receive(:execute).with(Gitlab::DataBuilder::Repository::SAMPLE_DATA, trigger).and_return(success_result)
expect(service.execute).to include(success_result)
end
end
diff --git a/spec/services/user_project_access_changed_service_spec.rb b/spec/services/user_project_access_changed_service_spec.rb
index 14a5e40350a..87a90378e2b 100644
--- a/spec/services/user_project_access_changed_service_spec.rb
+++ b/spec/services/user_project_access_changed_service_spec.rb
@@ -8,5 +8,12 @@ describe UserProjectAccessChangedService do
described_class.new([1, 2]).execute
end
+
+ it 'permits non-blocking operation' do
+ expect(AuthorizedProjectsWorker).to receive(:bulk_perform_async)
+ .with([[1], [2]])
+
+ described_class.new([1, 2]).execute(blocking: false)
+ end
end
end
diff --git a/spec/services/users/destroy_service_spec.rb b/spec/services/users/destroy_service_spec.rb
index a82567f6f43..58a5bede3de 100644
--- a/spec/services/users/destroy_service_spec.rb
+++ b/spec/services/users/destroy_service_spec.rb
@@ -4,9 +4,10 @@ describe Users::DestroyService do
describe "Deletes a user and all their personal projects" do
let!(:user) { create(:user) }
let!(:admin) { create(:admin) }
- let!(:namespace) { create(:namespace, owner: user) }
+ let!(:namespace) { user.namespace }
let!(:project) { create(:project, namespace: namespace) }
let(:service) { described_class.new(admin) }
+ let(:gitlab_shell) { Gitlab::Shell.new }
context 'no options are given' do
it 'deletes the user' do
@@ -14,7 +15,7 @@ describe Users::DestroyService do
expect { user_data['email'].to eq(user.email) }
expect { User.find(user.id) }.to raise_error(ActiveRecord::RecordNotFound)
- expect { Namespace.with_deleted.find(user.namespace.id) }.to raise_error(ActiveRecord::RecordNotFound)
+ expect { Namespace.with_deleted.find(namespace.id) }.to raise_error(ActiveRecord::RecordNotFound)
end
it 'will delete the project' do
@@ -165,5 +166,27 @@ describe Users::DestroyService do
expect(Issue.exists?(issue.id)).to be_falsy
end
end
+
+ describe "user personal's repository removal" do
+ before do
+ Sidekiq::Testing.inline! { service.execute(user) }
+ end
+
+ context 'legacy storage' do
+ let!(:project) { create(:project, :empty_repo, namespace: user.namespace) }
+
+ it 'removes repository' do
+ expect(gitlab_shell.exists?(project.repository_storage_path, "#{project.disk_path}.git")).to be_falsey
+ end
+ end
+
+ context 'hashed storage' do
+ let!(:project) { create(:project, :empty_repo, :hashed, namespace: user.namespace) }
+
+ it 'removes repository' do
+ expect(gitlab_shell.exists?(project.repository_storage_path, "#{project.disk_path}.git")).to be_falsey
+ end
+ end
+ end
end
end
diff --git a/spec/services/users/update_service_spec.rb b/spec/services/users/update_service_spec.rb
index 343804e3de0..6ee35a33b2d 100644
--- a/spec/services/users/update_service_spec.rb
+++ b/spec/services/users/update_service_spec.rb
@@ -12,9 +12,22 @@ describe Users::UpdateService do
end
it 'returns an error result when record cannot be updated' do
+ result = {}
expect do
- update_user(user, { email: 'invalid' })
+ result = update_user(user, { email: 'invalid' })
end.not_to change { user.reload.email }
+ expect(result[:status]).to eq(:error)
+ expect(result[:message]).to eq('Email is invalid')
+ end
+
+ it 'includes namespace error messages' do
+ create(:group, name: 'taken', path: 'something_else')
+ result = {}
+ expect do
+ result = update_user(user, { username: 'taken' })
+ end.not_to change { user.reload.username }
+ expect(result[:status]).to eq(:error)
+ expect(result[:message]).to eq('Namespace name has already been taken')
end
def update_user(user, opts)
@@ -24,7 +37,10 @@ describe Users::UpdateService do
describe '#execute!' do
it 'updates the name' do
- result = update_user(user, name: 'New Name')
+ service = described_class.new(user, name: 'New Name')
+ expect(service).not_to receive(:notify_new_user)
+
+ result = service.execute!
expect(result).to be true
expect(user.name).to eq('New Name')
@@ -36,6 +52,18 @@ describe Users::UpdateService do
end.to raise_error(ActiveRecord::RecordInvalid)
end
+ it 'fires system hooks when a new user is saved' do
+ system_hook_service = spy(:system_hook_service)
+ user = build(:user)
+ service = described_class.new(user, name: 'John Doe')
+ expect(service).to receive(:notify_new_user).and_call_original
+ expect(service).to receive(:system_hook_service).and_return(system_hook_service)
+
+ service.execute
+
+ expect(system_hook_service).to have_received(:execute_hooks_for).with(user, :create)
+ end
+
def update_user(user, opts)
described_class.new(user, opts).execute!
end
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
index c10197ff651..ff1754fbe7e 100644
--- a/spec/spec_helper.rb
+++ b/spec/spec_helper.rb
@@ -105,6 +105,18 @@ RSpec.configure do |config|
reset_delivered_emails!
end
+ # Stub the `ForkedStorageCheck.storage_available?` method unless
+ # `:broken_storage` metadata is defined
+ #
+ # This check can be slow and is unnecessary in a test environment where we
+ # know the storage is available, because we create it at runtime
+ config.before(:example) do |example|
+ unless example.metadata[:broken_storage]
+ allow(Gitlab::Git::Storage::ForkedStorageCheck)
+ .to receive(:storage_available?).and_return(true)
+ end
+ end
+
config.around(:each, :use_clean_rails_memory_store_caching) do |example|
caching_store = Rails.cache
Rails.cache = ActiveSupport::Cache::MemoryStore.new
diff --git a/spec/support/api_helpers.rb b/spec/support/api_helpers.rb
index ac0aaa524b7..01aca74274c 100644
--- a/spec/support/api_helpers.rb
+++ b/spec/support/api_helpers.rb
@@ -45,18 +45,4 @@ module ApiHelpers
oauth_access_token: oauth_access_token
)
end
-
- def ci_api(path, user = nil)
- "/ci/api/v1/#{path}" +
-
- # Normalize query string
- (path.index('?') ? '' : '?') +
-
- # Append private_token if given a User object
- if user.respond_to?(:private_token)
- "&private_token=#{user.private_token}"
- else
- ''
- end
- end
end
diff --git a/spec/support/background_migrations_matchers.rb b/spec/support/background_migrations_matchers.rb
new file mode 100644
index 00000000000..423c0e4cefc
--- /dev/null
+++ b/spec/support/background_migrations_matchers.rb
@@ -0,0 +1,13 @@
+RSpec::Matchers.define :be_scheduled_migration do |delay, *expected|
+ match do |migration|
+ BackgroundMigrationWorker.jobs.any? do |job|
+ job['args'] == [migration, expected] &&
+ job['at'].to_i == (delay.to_i + Time.now.to_i)
+ end
+ end
+
+ failure_message do |migration|
+ "Migration `#{migration}` with args `#{expected.inspect}` " \
+ 'not scheduled in expected time!'
+ end
+end
diff --git a/spec/support/cycle_analytics_helpers.rb b/spec/support/cycle_analytics_helpers.rb
index 30911e7fa86..39586d37e93 100644
--- a/spec/support/cycle_analytics_helpers.rb
+++ b/spec/support/cycle_analytics_helpers.rb
@@ -78,6 +78,8 @@ module CycleAnalyticsHelpers
@dummy_pipeline ||=
Ci::Pipeline.new(
sha: project.repository.commit('master').sha,
+ ref: 'master',
+ source: :push,
project: project)
end
diff --git a/spec/support/db_cleaner.rb b/spec/support/db_cleaner.rb
index b0f520d08e8..edaee03ea6c 100644
--- a/spec/support/db_cleaner.rb
+++ b/spec/support/db_cleaner.rb
@@ -4,18 +4,18 @@ RSpec.configure do |config|
end
config.append_after(:context) do
- DatabaseCleaner.clean_with(:truncation)
+ DatabaseCleaner.clean_with(:truncation, cache_tables: false)
end
config.before(:each) do
DatabaseCleaner.strategy = :transaction
end
- config.before(:each, js: true) do
+ config.before(:each, :js) do
DatabaseCleaner.strategy = :truncation
end
- config.before(:each, truncate: true) do
+ config.before(:each, :truncate) do
DatabaseCleaner.strategy = :truncation
end
diff --git a/spec/support/features/reportable_note_shared_examples.rb b/spec/support/features/reportable_note_shared_examples.rb
index cb483ae9a5a..5a0e7c3d099 100644
--- a/spec/support/features/reportable_note_shared_examples.rb
+++ b/spec/support/features/reportable_note_shared_examples.rb
@@ -34,7 +34,7 @@ shared_examples 'reportable note' do
end
def open_dropdown(dropdown)
- dropdown.click
+ dropdown.find('.more-actions-toggle').trigger('click')
dropdown.find('.dropdown-menu li', match: :first)
end
end
diff --git a/spec/support/filtered_search_helpers.rb b/spec/support/filtered_search_helpers.rb
index 99b8b6b7ea4..05021ea9054 100644
--- a/spec/support/filtered_search_helpers.rb
+++ b/spec/support/filtered_search_helpers.rb
@@ -58,11 +58,17 @@ module FilteredSearchHelpers
page.all(:css, '.tokens-container li .selectable').each_with_index do |el, index|
token_name = tokens[index][:name]
token_value = tokens[index][:value]
+ token_emoji = tokens[index][:emoji_name]
expect(el.find('.name')).to have_content(token_name)
if token_value
expect(el.find('.value')).to have_content(token_value)
end
+ # gl-emoji content is blank when the emoji unicode is not supported
+ if token_emoji
+ selector = %(gl-emoji[data-name="#{token_emoji}"])
+ expect(el.find('.value')).to have_css(selector)
+ end
end
end
end
@@ -89,6 +95,10 @@ module FilteredSearchHelpers
create_token('Label', label_name, symbol)
end
+ def emoji_token(emoji_name = nil)
+ { name: 'My-Reaction', emoji_name: emoji_name }
+ end
+
def default_placeholder
'Search or filter results...'
end
diff --git a/spec/support/helpers/note_interaction_helpers.rb b/spec/support/helpers/note_interaction_helpers.rb
index 551c759133c..86008698692 100644
--- a/spec/support/helpers/note_interaction_helpers.rb
+++ b/spec/support/helpers/note_interaction_helpers.rb
@@ -2,7 +2,7 @@ module NoteInteractionHelpers
def open_more_actions_dropdown(note)
note_element = find("#note_#{note.id}")
- note_element.find('.more-actions').click
+ note_element.find('.more-actions-toggle').trigger('click')
note_element.find('.more-actions .dropdown-menu li', match: :first)
end
end
diff --git a/spec/support/import_export/export_file_helper.rb b/spec/support/import_export/export_file_helper.rb
index 2011408be93..562423afc2a 100644
--- a/spec/support/import_export/export_file_helper.rb
+++ b/spec/support/import_export/export_file_helper.rb
@@ -35,7 +35,8 @@ module ExportFileHelper
project: project,
commit_id: ci_pipeline.sha)
- create(:event, :created, target: milestone, project: project, author: user)
+ event = create(:event, :created, target: milestone, project: project, author: user, action: 5)
+ create(:push_event_payload, event: event)
create(:project_member, :master, user: user, project: project)
create(:ci_variable, project: project)
create(:ci_trigger, project: project)
diff --git a/spec/support/migrations_helpers.rb b/spec/support/migrations_helpers.rb
index 255b3d96a62..4ca019c1b05 100644
--- a/spec/support/migrations_helpers.rb
+++ b/spec/support/migrations_helpers.rb
@@ -16,6 +16,8 @@ module MigrationsHelpers
end
def reset_column_in_migration_models
+ ActiveRecord::Base.clear_cache!
+
described_class.constants.sort.each do |name|
const = described_class.const_get(name)
diff --git a/spec/support/shared_examples/requests/api/status_shared_examples.rb b/spec/support/shared_examples/requests/api/status_shared_examples.rb
index 226277411d6..7d7f66adeab 100644
--- a/spec/support/shared_examples/requests/api/status_shared_examples.rb
+++ b/spec/support/shared_examples/requests/api/status_shared_examples.rb
@@ -40,3 +40,28 @@ shared_examples_for '404 response' do
end
end
end
+
+shared_examples_for '412 response' do
+ let(:params) { nil }
+ let(:success_status) { 204 }
+
+ context 'for a modified ressource' do
+ before do
+ delete request, params, { 'HTTP_IF_UNMODIFIED_SINCE' => '1990-01-12T00:00:48-0600' }
+ end
+
+ it 'returns 412' do
+ expect(response).to have_gitlab_http_status(412)
+ end
+ end
+
+ context 'for an unmodified ressource' do
+ before do
+ delete request, params, { 'HTTP_IF_UNMODIFIED_SINCE' => Time.now }
+ end
+
+ it 'returns accepted' do
+ expect(response).to have_gitlab_http_status(success_status)
+ end
+ end
+end
diff --git a/spec/workers/authorized_projects_worker_spec.rb b/spec/workers/authorized_projects_worker_spec.rb
index 03b9b99e263..90ed1309d4a 100644
--- a/spec/workers/authorized_projects_worker_spec.rb
+++ b/spec/workers/authorized_projects_worker_spec.rb
@@ -3,47 +3,100 @@ require 'spec_helper'
describe AuthorizedProjectsWorker do
let(:project) { create(:project) }
+ def build_args_list(*ids, multiply: 1)
+ args_list = ids.map { |id| [id] }
+ args_list * multiply
+ end
+
describe '.bulk_perform_and_wait' do
it 'schedules the ids and waits for the jobs to complete' do
+ args_list = build_args_list(project.owner.id)
+
project.owner.project_authorizations.delete_all
+ described_class.bulk_perform_and_wait(args_list)
+
+ expect(project.owner.project_authorizations.count).to eq(1)
+ end
- described_class.bulk_perform_and_wait([[project.owner.id]])
+ it 'inlines workloads <= 3 jobs' do
+ args_list = build_args_list(project.owner.id, multiply: 3)
+ expect(described_class).to receive(:bulk_perform_inline).with(args_list)
+
+ described_class.bulk_perform_and_wait(args_list)
+ end
+
+ it 'runs > 3 jobs using sidekiq' do
+ project.owner.project_authorizations.delete_all
+
+ expect(described_class).to receive(:bulk_perform_async).and_call_original
+
+ args_list = build_args_list(project.owner.id, multiply: 4)
+ described_class.bulk_perform_and_wait(args_list)
expect(project.owner.project_authorizations.count).to eq(1)
end
end
+ describe '.bulk_perform_inline' do
+ it 'refreshes the authorizations inline' do
+ project.owner.project_authorizations.delete_all
+
+ expect_any_instance_of(described_class).to receive(:perform).and_call_original
+
+ described_class.bulk_perform_inline(build_args_list(project.owner.id))
+
+ expect(project.owner.project_authorizations.count).to eq(1)
+ end
+
+ it 'enqueues jobs if an error is raised' do
+ invalid_id = -1
+ args_list = build_args_list(project.owner.id, invalid_id)
+
+ allow_any_instance_of(described_class).to receive(:perform).with(project.owner.id)
+ allow_any_instance_of(described_class).to receive(:perform).with(invalid_id).and_raise(ArgumentError)
+ expect(described_class).to receive(:bulk_perform_async).with(build_args_list(invalid_id))
+
+ described_class.bulk_perform_inline(args_list)
+ end
+ end
+
describe '.bulk_perform_async' do
it "uses it's respective sidekiq queue" do
- args = [[project.owner.id]]
+ args_list = build_args_list(project.owner.id)
push_bulk_args = {
'class' => described_class,
'queue' => described_class.sidekiq_options['queue'],
- 'args' => args
+ 'args' => args_list
}
expect(Sidekiq::Client).to receive(:push_bulk).with(push_bulk_args).once
- described_class.bulk_perform_async(args)
+ described_class.bulk_perform_async(args_list)
end
end
describe '#perform' do
- subject { described_class.new }
+ let(:user) { create(:user) }
- it "refreshes user's authorized projects" do
- user = create(:user)
+ subject(:job) { described_class.new }
+ it "refreshes user's authorized projects" do
expect_any_instance_of(User).to receive(:refresh_authorized_projects)
- subject.perform(user.id)
+ job.perform(user.id)
+ end
+
+ it 'notifies the JobWaiter when done if the key is provided' do
+ expect(Gitlab::JobWaiter).to receive(:notify).with('notify-key', job.jid)
+
+ job.perform(user.id, 'notify-key')
end
context "when the user is not found" do
it "does nothing" do
expect_any_instance_of(User).not_to receive(:refresh_authorized_projects)
- subject.perform(-1)
+ job.perform(-1)
end
end
end
diff --git a/spec/workers/build_finished_worker_spec.rb b/spec/workers/build_finished_worker_spec.rb
index 2868167c7d4..8cc3f37ebe8 100644
--- a/spec/workers/build_finished_worker_spec.rb
+++ b/spec/workers/build_finished_worker_spec.rb
@@ -3,7 +3,7 @@ require 'spec_helper'
describe BuildFinishedWorker do
describe '#perform' do
context 'when build exists' do
- let(:build) { create(:ci_build) }
+ let!(:build) { create(:ci_build) }
it 'calculates coverage and calls hooks' do
expect(BuildCoverageWorker)
diff --git a/spec/workers/concerns/build_queue_spec.rb b/spec/workers/concerns/build_queue_spec.rb
deleted file mode 100644
index 6bf955e0be2..00000000000
--- a/spec/workers/concerns/build_queue_spec.rb
+++ /dev/null
@@ -1,14 +0,0 @@
-require 'spec_helper'
-
-describe BuildQueue do
- let(:worker) do
- Class.new do
- include Sidekiq::Worker
- include BuildQueue
- end
- end
-
- it 'sets the queue name of a worker' do
- expect(worker.sidekiq_options['queue'].to_s).to eq('build')
- end
-end
diff --git a/spec/workers/concerns/pipeline_queue_spec.rb b/spec/workers/concerns/pipeline_queue_spec.rb
index 40794d0e42a..eac5a770e5f 100644
--- a/spec/workers/concerns/pipeline_queue_spec.rb
+++ b/spec/workers/concerns/pipeline_queue_spec.rb
@@ -8,7 +8,17 @@ describe PipelineQueue do
end
end
- it 'sets the queue name of a worker' do
- expect(worker.sidekiq_options['queue'].to_s).to eq('pipeline')
+ it 'sets a default pipelines queue automatically' do
+ expect(worker.sidekiq_options['queue'])
+ .to eq 'pipeline_default'
+ end
+
+ describe '.enqueue_in' do
+ it 'sets a custom sidekiq queue with prefix and group' do
+ worker.enqueue_in(group: :processing)
+
+ expect(worker.sidekiq_options['queue'])
+ .to eq 'pipeline_processing'
+ end
end
end
diff --git a/spec/workers/merge_worker_spec.rb b/spec/workers/merge_worker_spec.rb
index ee51000161a..303193bab9b 100644
--- a/spec/workers/merge_worker_spec.rb
+++ b/spec/workers/merge_worker_spec.rb
@@ -27,15 +27,4 @@ describe MergeWorker do
expect(source_project.repository.branch_names).not_to include('markdown')
end
end
-
- it 'persists merge_jid' do
- merge_request = create(:merge_request, merge_jid: nil)
- user = create(:user)
- worker = described_class.new
-
- allow(worker).to receive(:jid) { '999' }
-
- expect { worker.perform(merge_request.id, user.id, {}) }
- .to change { merge_request.reload.merge_jid }.from(nil).to('999')
- end
end
diff --git a/spec/workers/namespaceless_project_destroy_worker_spec.rb b/spec/workers/namespaceless_project_destroy_worker_spec.rb
index f2706254284..20cf580af8a 100644
--- a/spec/workers/namespaceless_project_destroy_worker_spec.rb
+++ b/spec/workers/namespaceless_project_destroy_worker_spec.rb
@@ -5,7 +5,7 @@ describe NamespacelessProjectDestroyWorker do
before do
# Stub after_save callbacks that will fail when Project has no namespace
- allow_any_instance_of(Project).to receive(:ensure_storage_path_exist).and_return(nil)
+ allow_any_instance_of(Project).to receive(:ensure_storage_path_exists).and_return(nil)
allow_any_instance_of(Project).to receive(:update_project_statistics).and_return(nil)
end
@@ -75,5 +75,19 @@ describe NamespacelessProjectDestroyWorker do
end
end
end
+
+ context 'project has non-existing namespace' do
+ let!(:project) do
+ project = build(:project, namespace_id: Namespace.maximum(:id).to_i.succ)
+ project.save(validate: false)
+ project
+ end
+
+ it 'deletes the project' do
+ subject.perform(project.id)
+
+ expect(Project.unscoped.all).not_to include(project)
+ end
+ end
end
end
diff --git a/spec/workers/pipeline_metrics_worker_spec.rb b/spec/workers/pipeline_metrics_worker_spec.rb
index ef71125c0b6..896f9e6e7f2 100644
--- a/spec/workers/pipeline_metrics_worker_spec.rb
+++ b/spec/workers/pipeline_metrics_worker_spec.rb
@@ -2,7 +2,12 @@ require 'spec_helper'
describe PipelineMetricsWorker do
let(:project) { create(:project, :repository) }
- let!(:merge_request) { create(:merge_request, source_project: project, source_branch: pipeline.ref, head_pipeline: pipeline) }
+
+ let!(:merge_request) do
+ create(:merge_request, source_project: project,
+ source_branch: pipeline.ref,
+ head_pipeline: pipeline)
+ end
let(:pipeline) do
create(:ci_empty_pipeline,
@@ -14,6 +19,8 @@ describe PipelineMetricsWorker do
finished_at: Time.now)
end
+ let(:status) { 'pending' }
+
describe '#perform' do
before do
described_class.new.perform(pipeline.id)
diff --git a/spec/workers/stage_update_worker_spec.rb b/spec/workers/stage_update_worker_spec.rb
new file mode 100644
index 00000000000..7bc76c79464
--- /dev/null
+++ b/spec/workers/stage_update_worker_spec.rb
@@ -0,0 +1,22 @@
+require 'spec_helper'
+
+describe StageUpdateWorker do
+ describe '#perform' do
+ context 'when stage exists' do
+ let(:stage) { create(:ci_stage_entity) }
+
+ it 'updates stage status' do
+ expect_any_instance_of(Ci::Stage).to receive(:update_status)
+
+ described_class.new.perform(stage.id)
+ end
+ end
+
+ context 'when stage does not exist' do
+ it 'does not raise exception' do
+ expect { described_class.new.perform(123) }
+ .not_to raise_error
+ end
+ end
+ end
+end
diff --git a/vendor/assets/stylesheets/katex.scss b/vendor/assets/stylesheets/katex.scss
index 9dd8a30bf51..b45836716f2 100644
--- a/vendor/assets/stylesheets/katex.scss
+++ b/vendor/assets/stylesheets/katex.scss
@@ -45,112 +45,112 @@ SOFTWARE.
font-family: 'KaTeX_AMS';
src: url(font-path('KaTeX_AMS-Regular.eot'));
src: url(font-path('KaTeX_AMS-Regular.eot#iefix')) format('embedded-opentype'), url(font-path('KaTeX_AMS-Regular.woff2')) format('woff2'), url(font-path('KaTeX_AMS-Regular.woff')) format('woff'), url(font-path('KaTeX_AMS-Regular.ttf')) format('truetype');
- font-weight: normal;
+ font-weight: 400;
font-style: normal;
}
@font-face {
font-family: 'KaTeX_Caligraphic';
src: url(font-path('KaTeX_Caligraphic-Bold.eot'));
src: url(font-path('KaTeX_Caligraphic-Bold.eot#iefix')) format('embedded-opentype'), url(font-path('KaTeX_Caligraphic-Bold.woff2')) format('woff2'), url(font-path('KaTeX_Caligraphic-Bold.woff')) format('woff'), url(font-path('KaTeX_Caligraphic-Bold.ttf')) format('truetype');
- font-weight: bold;
+ font-weight: 600;
font-style: normal;
}
@font-face {
font-family: 'KaTeX_Caligraphic';
src: url(font-path('KaTeX_Caligraphic-Regular.eot'));
src: url(font-path('KaTeX_Caligraphic-Regular.eot#iefix')) format('embedded-opentype'), url(font-path('KaTeX_Caligraphic-Regular.woff2')) format('woff2'), url(font-path('KaTeX_Caligraphic-Regular.woff')) format('woff'), url(font-path('KaTeX_Caligraphic-Regular.ttf')) format('truetype');
- font-weight: normal;
+ font-weight: 400;
font-style: normal;
}
@font-face {
font-family: 'KaTeX_Fraktur';
src: url(font-path('KaTeX_Fraktur-Bold.eot'));
src: url(font-path('KaTeX_Fraktur-Bold.eot#iefix')) format('embedded-opentype'), url(font-path('KaTeX_Fraktur-Bold.woff2')) format('woff2'), url(font-path('KaTeX_Fraktur-Bold.woff')) format('woff'), url(font-path('KaTeX_Fraktur-Bold.ttf')) format('truetype');
- font-weight: bold;
+ font-weight: 600;
font-style: normal;
}
@font-face {
font-family: 'KaTeX_Fraktur';
src: url(font-path('KaTeX_Fraktur-Regular.eot'));
src: url(font-path('KaTeX_Fraktur-Regular.eot#iefix')) format('embedded-opentype'), url(font-path('KaTeX_Fraktur-Regular.woff2')) format('woff2'), url(font-path('KaTeX_Fraktur-Regular.woff')) format('woff'), url(font-path('KaTeX_Fraktur-Regular.ttf')) format('truetype');
- font-weight: normal;
+ font-weight: 400;
font-style: normal;
}
@font-face {
font-family: 'KaTeX_Main';
src: url(font-path('KaTeX_Main-Bold.eot'));
src: url(font-path('KaTeX_Main-Bold.eot#iefix')) format('embedded-opentype'), url(font-path('KaTeX_Main-Bold.woff2')) format('woff2'), url(font-path('KaTeX_Main-Bold.woff')) format('woff'), url(font-path('KaTeX_Main-Bold.ttf')) format('truetype');
- font-weight: bold;
+ font-weight: 600;
font-style: normal;
}
@font-face {
font-family: 'KaTeX_Main';
src: url(font-path('KaTeX_Main-Italic.eot'));
src: url(font-path('KaTeX_Main-Italic.eot#iefix')) format('embedded-opentype'), url(font-path('KaTeX_Main-Italic.woff2')) format('woff2'), url(font-path('KaTeX_Main-Italic.woff')) format('woff'), url(font-path('KaTeX_Main-Italic.ttf')) format('truetype');
- font-weight: normal;
+ font-weight: 400;
font-style: italic;
}
@font-face {
font-family: 'KaTeX_Main';
src: url(font-path('KaTeX_Main-Regular.eot'));
src: url(font-path('KaTeX_Main-Regular.eot#iefix')) format('embedded-opentype'), url(font-path('KaTeX_Main-Regular.woff2')) format('woff2'), url(font-path('KaTeX_Main-Regular.woff')) format('woff'), url(font-path('KaTeX_Main-Regular.ttf')) format('truetype');
- font-weight: normal;
+ font-weight: 400;
font-style: normal;
}
@font-face {
font-family: 'KaTeX_Math';
src: url(font-path('KaTeX_Math-Italic.eot'));
src: url(font-path('KaTeX_Math-Italic.eot#iefix')) format('embedded-opentype'), url(font-path('KaTeX_Math-Italic.woff2')) format('woff2'), url(font-path('KaTeX_Math-Italic.woff')) format('woff'), url(font-path('KaTeX_Math-Italic.ttf')) format('truetype');
- font-weight: normal;
+ font-weight: 400;
font-style: italic;
}
@font-face {
font-family: 'KaTeX_SansSerif';
src: url(font-path('KaTeX_SansSerif-Regular.eot'));
src: url(font-path('KaTeX_SansSerif-Regular.eot#iefix')) format('embedded-opentype'), url(font-path('KaTeX_SansSerif-Regular.woff2')) format('woff2'), url(font-path('KaTeX_SansSerif-Regular.woff')) format('woff'), url(font-path('KaTeX_SansSerif-Regular.ttf')) format('truetype');
- font-weight: normal;
+ font-weight: 400;
font-style: normal;
}
@font-face {
font-family: 'KaTeX_Script';
src: url(font-path('KaTeX_Script-Regular.eot'));
src: url(font-path('KaTeX_Script-Regular.eot#iefix')) format('embedded-opentype'), url(font-path('KaTeX_Script-Regular.woff2')) format('woff2'), url(font-path('KaTeX_Script-Regular.woff')) format('woff'), url(font-path('KaTeX_Script-Regular.ttf')) format('truetype');
- font-weight: normal;
+ font-weight: 400;
font-style: normal;
}
@font-face {
font-family: 'KaTeX_Size1';
src: url(font-path('KaTeX_Size1-Regular.eot'));
src: url(font-path('KaTeX_Size1-Regular.eot#iefix')) format('embedded-opentype'), url(font-path('KaTeX_Size1-Regular.woff2')) format('woff2'), url(font-path('KaTeX_Size1-Regular.woff')) format('woff'), url(font-path('KaTeX_Size1-Regular.ttf')) format('truetype');
- font-weight: normal;
+ font-weight: 400;
font-style: normal;
}
@font-face {
font-family: 'KaTeX_Size2';
src: url(font-path('KaTeX_Size2-Regular.eot'));
src: url(font-path('KaTeX_Size2-Regular.eot#iefix')) format('embedded-opentype'), url(font-path('KaTeX_Size2-Regular.woff2')) format('woff2'), url(font-path('KaTeX_Size2-Regular.woff')) format('woff'), url(font-path('KaTeX_Size2-Regular.ttf')) format('truetype');
- font-weight: normal;
+ font-weight: 400;
font-style: normal;
}
@font-face {
font-family: 'KaTeX_Size3';
src: url(font-path('KaTeX_Size3-Regular.eot'));
src: url(font-path('KaTeX_Size3-Regular.eot#iefix')) format('embedded-opentype'), url(font-path('KaTeX_Size3-Regular.woff2')) format('woff2'), url(font-path('KaTeX_Size3-Regular.woff')) format('woff'), url(font-path('KaTeX_Size3-Regular.ttf')) format('truetype');
- font-weight: normal;
+ font-weight: 400;
font-style: normal;
}
@font-face {
font-family: 'KaTeX_Size4';
src: url(font-path('KaTeX_Size4-Regular.eot'));
src: url(font-path('KaTeX_Size4-Regular.eot#iefix')) format('embedded-opentype'), url(font-path('KaTeX_Size4-Regular.woff2')) format('woff2'), url(font-path('KaTeX_Size4-Regular.woff')) format('woff'), url(font-path('KaTeX_Size4-Regular.ttf')) format('truetype');
- font-weight: normal;
+ font-weight: 400;
font-style: normal;
}
@font-face {
font-family: 'KaTeX_Typewriter';
src: url(font-path('KaTeX_Typewriter-Regular.eot'));
src: url(font-path('KaTeX_Typewriter-Regular.eot#iefix')) format('embedded-opentype'), url(font-path('KaTeX_Typewriter-Regular.woff2')) format('woff2'), url(font-path('KaTeX_Typewriter-Regular.woff')) format('woff'), url(font-path('KaTeX_Typewriter-Regular.ttf')) format('truetype');
- font-weight: normal;
+ font-weight: 400;
font-style: normal;
}
.katex-display {
@@ -192,7 +192,7 @@ SOFTWARE.
}
.katex .mathbf {
font-family: KaTeX_Main;
- font-weight: bold;
+ font-weight: 600;
}
.katex .amsrm {
font-family: KaTeX_AMS;
diff --git a/vendor/assets/stylesheets/xterm/xterm.css b/vendor/assets/stylesheets/xterm/xterm.css
index b30d7b493f1..fabc51b0e3d 100644
--- a/vendor/assets/stylesheets/xterm/xterm.css
+++ b/vendor/assets/stylesheets/xterm/xterm.css
@@ -142,7 +142,7 @@
* Determine default colors for xterm.js
*/
.terminal .xterm-bold {
- font-weight: bold;
+ font-weight: 600;
}
.terminal .xterm-underline {
diff --git a/vendor/project_templates/express.tar.gz b/vendor/project_templates/express.tar.gz
index 6353f6605d5..302a74637b2 100644
--- a/vendor/project_templates/express.tar.gz
+++ b/vendor/project_templates/express.tar.gz
Binary files differ
diff --git a/vendor/project_templates/rails.tar.gz b/vendor/project_templates/rails.tar.gz
index 0509016f130..0f406705563 100644
--- a/vendor/project_templates/rails.tar.gz
+++ b/vendor/project_templates/rails.tar.gz
Binary files differ
diff --git a/vendor/project_templates/spring.tar.gz b/vendor/project_templates/spring.tar.gz
index d7c0ab74d01..02006b14406 100644
--- a/vendor/project_templates/spring.tar.gz
+++ b/vendor/project_templates/spring.tar.gz
Binary files differ
diff --git a/yarn.lock b/yarn.lock
index 5fc28f8b5ba..396737a64a7 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -14,8 +14,8 @@ accepts@1.3.3, accepts@~1.3.3:
negotiator "0.6.1"
acorn-dynamic-import@^2.0.0:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/acorn-dynamic-import/-/acorn-dynamic-import-2.0.1.tgz#23f671eb6e650dab277fef477c321b1178a8cca2"
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/acorn-dynamic-import/-/acorn-dynamic-import-2.0.2.tgz#c752bd210bef679501b6c6cb7fc84f8f47158cc4"
dependencies:
acorn "^4.0.3"
@@ -25,17 +25,17 @@ acorn-jsx@^3.0.0:
dependencies:
acorn "^3.0.4"
-acorn@4.0.4, acorn@^4.0.3:
- version "4.0.4"
- resolved "https://registry.yarnpkg.com/acorn/-/acorn-4.0.4.tgz#17a8d6a7a6c4ef538b814ec9abac2779293bf30a"
-
acorn@^3.0.4:
version "3.3.0"
resolved "https://registry.yarnpkg.com/acorn/-/acorn-3.3.0.tgz#45e37fb39e8da3f25baee3ff5369e2bb5f22017a"
-acorn@^5.0.0, acorn@^5.0.3:
- version "5.0.3"
- resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.0.3.tgz#c460df08491463f028ccb82eab3730bf01087b3d"
+acorn@^4.0.3:
+ version "4.0.13"
+ resolved "https://registry.yarnpkg.com/acorn/-/acorn-4.0.13.tgz#105495ae5361d697bd195c825192e1ad7f253787"
+
+acorn@^5.0.0, acorn@^5.0.3, acorn@^5.1.1:
+ version "5.1.1"
+ resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.1.1.tgz#53fe161111f912ab999ee887a90a0bc52822fd75"
after@0.8.2:
version "0.8.2"
@@ -56,6 +56,13 @@ ajv@^4.7.0:
co "^4.6.0"
json-stable-stringify "^1.0.1"
+ajv@^4.9.1:
+ version "4.11.8"
+ resolved "https://registry.yarnpkg.com/ajv/-/ajv-4.11.8.tgz#82ffb02b29e662ae53bdc20af15947706739c536"
+ dependencies:
+ co "^4.6.0"
+ json-stable-stringify "^1.0.1"
+
ajv@^5.1.5:
version "5.2.0"
resolved "https://registry.yarnpkg.com/ajv/-/ajv-5.2.0.tgz#c1735024c5da2ef75cc190713073d44f098bf486"
@@ -102,11 +109,11 @@ ansi-styles@^2.2.1:
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe"
anymatch@^1.3.0:
- version "1.3.0"
- resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-1.3.0.tgz#a3e52fa39168c825ff57b0248126ce5a8ff95507"
+ version "1.3.2"
+ resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-1.3.2.tgz#553dcb8f91e3c889845dfdba34c77721b90b9d7a"
dependencies:
- arrify "^1.0.0"
micromatch "^2.1.5"
+ normalize-path "^2.0.0"
append-transform@^0.4.0:
version "0.4.0"
@@ -115,15 +122,15 @@ append-transform@^0.4.0:
default-require-extensions "^1.0.0"
aproba@^1.0.3:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.1.0.tgz#4d8f047a318604e18e3c06a0e52230d3d19f147b"
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.1.2.tgz#45c6629094de4e96f693ef7eab74ae079c240fc1"
are-we-there-yet@~1.1.2:
- version "1.1.2"
- resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.2.tgz#80e470e95a084794fe1899262c5667c6e88de1b3"
+ version "1.1.4"
+ resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.4.tgz#bb5dca382bb94f05e15194373d16fd3ba1ca110d"
dependencies:
delegates "^1.0.0"
- readable-stream "^2.0.0 || ^1.1.13"
+ readable-stream "^2.0.6"
argparse@^1.0.7:
version "1.0.9"
@@ -195,14 +202,14 @@ asn1@~0.2.3:
version "0.2.3"
resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.3.tgz#dac8787713c9966849fc8180777ebe9c1ddf3b86"
+assert-plus@1.0.0, assert-plus@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525"
+
assert-plus@^0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-0.2.0.tgz#d74e1b87e7affc0db8aadb7021f3fe48101ab234"
-assert-plus@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525"
-
assert@^1.1.1:
version "1.4.1"
resolved "https://registry.yarnpkg.com/assert/-/assert-1.4.1.tgz#99912d591836b5a6f5b345c0f07eefc08fc65d91"
@@ -213,17 +220,19 @@ async-each@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.1.tgz#19d386a1d9edc6e7c1c85d388aedbcc56d33602d"
-async@0.2.x:
- version "0.2.10"
- resolved "https://registry.yarnpkg.com/async/-/async-0.2.10.tgz#b6bbe0b0674b9d719708ca38de8c237cb526c3d1"
-
async@1.x, async@^1.4.0, async@^1.4.2, async@^1.5.2:
version "1.5.2"
resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a"
+async@2.4.1:
+ version "2.4.1"
+ resolved "https://registry.yarnpkg.com/async/-/async-2.4.1.tgz#62a56b279c98a11d0987096a01cc3eeb8eb7bbd7"
+ dependencies:
+ lodash "^4.14.0"
+
async@^2.1.2, async@^2.1.4:
- version "2.1.4"
- resolved "https://registry.yarnpkg.com/async/-/async-2.1.4.tgz#2d2160c7788032e4dd6cbe2502f1f9a2c8f6cde4"
+ version "2.5.0"
+ resolved "https://registry.yarnpkg.com/async/-/async-2.5.0.tgz#843190fd6b7357a0b9e1c956edddd5ec8462b54d"
dependencies:
lodash "^4.14.0"
@@ -261,7 +270,7 @@ axios@^0.16.2:
follow-redirects "^1.2.3"
is-buffer "^1.1.5"
-babel-code-frame@^6.11.0, babel-code-frame@^6.16.0, babel-code-frame@^6.22.0:
+babel-code-frame@^6.11.0, babel-code-frame@^6.22.0:
version "6.22.0"
resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.22.0.tgz#027620bee567a88c32561574e7fd0801d33118e4"
dependencies:
@@ -269,6 +278,14 @@ babel-code-frame@^6.11.0, babel-code-frame@^6.16.0, babel-code-frame@^6.22.0:
esutils "^2.0.2"
js-tokens "^3.0.0"
+babel-code-frame@^6.16.0:
+ version "6.26.0"
+ resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b"
+ dependencies:
+ chalk "^1.1.3"
+ esutils "^2.0.2"
+ js-tokens "^3.0.2"
+
babel-core@^6.22.1, babel-core@^6.23.0:
version "6.23.1"
resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.23.1.tgz#c143cb621bb2f621710c220c5d579d15b8a442df"
@@ -864,6 +881,10 @@ balanced-match@^0.4.1, balanced-match@^0.4.2:
version "0.4.2"
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-0.4.2.tgz#cb3f3e3c732dc0f01ee70b403f302e61d7709838"
+balanced-match@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767"
+
base64-arraybuffer@0.1.5:
version "0.1.5"
resolved "https://registry.yarnpkg.com/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz#73926771923b5a19747ad666aa5cd4bf9c6e9ce8"
@@ -876,9 +897,9 @@ base64id@1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/base64id/-/base64id-1.0.0.tgz#47688cb99bb6804f0e06d3e763b1c32e57d8e6b6"
-batch@0.5.3:
- version "0.5.3"
- resolved "https://registry.yarnpkg.com/batch/-/batch-0.5.3.tgz#3f3414f380321743bfc1042f9a83ff1d5824d464"
+batch@0.6.1:
+ version "0.6.1"
+ resolved "https://registry.yarnpkg.com/batch/-/batch-0.6.1.tgz#dc34314f4e679318093fc760272525f94bf25c16"
bcrypt-pbkdf@^1.0.0:
version "1.0.1"
@@ -897,8 +918,8 @@ big.js@^3.1.3:
resolved "https://registry.yarnpkg.com/big.js/-/big.js-3.1.3.tgz#4cada2193652eb3ca9ec8e55c9015669c9806978"
binary-extensions@^1.0.0:
- version "1.8.0"
- resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.8.0.tgz#48ec8d16df4377eae5fa5884682480af4d95c774"
+ version "1.10.0"
+ resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.10.0.tgz#9aeb9a6c5e88638aad171e167f5900abe24835d0"
blob@0.0.4:
version "0.0.4"
@@ -914,10 +935,14 @@ bluebird@^2.10.2:
version "2.11.0"
resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-2.11.0.tgz#534b9033c022c9579c56ba3b3e5a5caafbb650e1"
-bluebird@^3.0.5, bluebird@^3.1.1, bluebird@^3.3.0:
+bluebird@^3.0.5, bluebird@^3.1.1:
version "3.4.7"
resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.4.7.tgz#f72d760be09b7f76d08ed8fae98b289a8d05fab3"
+bluebird@^3.3.0:
+ version "3.5.0"
+ resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.0.tgz#791420d7f551eea2897453a8a77653f96606d67c"
+
bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.4.0:
version "4.11.6"
resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.6.tgz#53344adb14617a13f6e8dd2ce28905d1c0ba3215"
@@ -965,6 +990,13 @@ brace-expansion@^1.0.0:
balanced-match "^0.4.1"
concat-map "0.0.1"
+brace-expansion@^1.1.7:
+ version "1.1.8"
+ resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.8.tgz#c07b211c7c952ec1f8efd51a77ef0d1d3990a292"
+ dependencies:
+ balanced-match "^1.0.0"
+ concat-map "0.0.1"
+
braces@^0.1.2:
version "0.1.5"
resolved "https://registry.yarnpkg.com/braces/-/braces-0.1.5.tgz#c085711085291d8b75fdd74eab0f8597280711e6"
@@ -1069,14 +1101,14 @@ builtin-status-codes@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8"
-bytes@2.3.0:
- version "2.3.0"
- resolved "https://registry.yarnpkg.com/bytes/-/bytes-2.3.0.tgz#d5b680a165b6201739acb611542aabc2d8ceb070"
-
bytes@2.4.0:
version "2.4.0"
resolved "https://registry.yarnpkg.com/bytes/-/bytes-2.4.0.tgz#7d97196f9d5baf7f6935e25985549edd2a6c2339"
+bytes@2.5.0:
+ version "2.5.0"
+ resolved "https://registry.yarnpkg.com/bytes/-/bytes-2.5.0.tgz#4c9423ea2d252c270c41b2bdefeff9bb6b62c06a"
+
caller-path@^0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-0.1.0.tgz#94085ef63581ecd3daa92444a8fe94e82577751f"
@@ -1127,9 +1159,9 @@ caniuse-db@^1.0.30000529, caniuse-db@^1.0.30000634, caniuse-db@^1.0.30000639:
version "1.0.30000649"
resolved "https://registry.yarnpkg.com/caniuse-db/-/caniuse-db-1.0.30000649.tgz#1ee1754a6df235450c8b7cd15e0ebf507221a86a"
-caseless@~0.11.0:
- version "0.11.0"
- resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.11.0.tgz#715b96ea9841593cc33067923f5ec60ebda4f7d7"
+caseless@~0.12.0:
+ version "0.12.0"
+ resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc"
center-align@^0.1.1:
version "0.1.3"
@@ -1148,22 +1180,7 @@ chalk@1.1.3, chalk@^1.0.0, chalk@^1.1.0, chalk@^1.1.1, chalk@^1.1.3:
strip-ansi "^3.0.0"
supports-color "^2.0.0"
-chokidar@^1.4.1, chokidar@^1.4.3, chokidar@^1.6.0:
- version "1.6.1"
- resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-1.6.1.tgz#2f4447ab5e96e50fb3d789fd90d4c72e0e4c70c2"
- dependencies:
- anymatch "^1.3.0"
- async-each "^1.0.0"
- glob-parent "^2.0.0"
- inherits "^2.0.1"
- is-binary-path "^1.0.0"
- is-glob "^2.0.0"
- path-is-absolute "^1.0.0"
- readdirp "^2.0.0"
- optionalDependencies:
- fsevents "^1.0.0"
-
-chokidar@^1.7.0:
+chokidar@^1.4.1, chokidar@^1.4.3, chokidar@^1.6.0, chokidar@^1.7.0:
version "1.7.0"
resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-1.7.0.tgz#798e689778151c8076b4b360e5edd28cda2bb468"
dependencies:
@@ -1185,8 +1202,8 @@ cipher-base@^1.0.0, cipher-base@^1.0.1:
inherits "^2.0.1"
circular-json@^0.3.1:
- version "0.3.1"
- resolved "https://registry.yarnpkg.com/circular-json/-/circular-json-0.3.1.tgz#be8b36aefccde8b3ca7aa2d6afc07a37242c0d2d"
+ version "0.3.3"
+ resolved "https://registry.yarnpkg.com/circular-json/-/circular-json-0.3.3.tgz#815c99ea84f6809529d2f45791bdf82711352d66"
clap@^1.0.9:
version "1.1.3"
@@ -1294,7 +1311,7 @@ combined-stream@^1.0.5, combined-stream@~1.0.5:
dependencies:
delayed-stream "~1.0.0"
-commander@^2.8.1, commander@^2.9.0:
+commander@^2.9.0:
version "2.9.0"
resolved "https://registry.yarnpkg.com/commander/-/commander-2.9.0.tgz#9c99094176e12240cb22d6c5146098400fe0f7d4"
dependencies:
@@ -1320,37 +1337,36 @@ component-inherit@0.0.3:
version "0.0.3"
resolved "https://registry.yarnpkg.com/component-inherit/-/component-inherit-0.0.3.tgz#645fc4adf58b72b649d5cae65135619db26ff143"
-compressible@~2.0.8:
- version "2.0.9"
- resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.9.tgz#6daab4e2b599c2770dd9e21e7a891b1c5a755425"
+compressible@~2.0.10:
+ version "2.0.11"
+ resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.11.tgz#16718a75de283ed8e604041625a2064586797d8a"
dependencies:
- mime-db ">= 1.24.0 < 2"
+ mime-db ">= 1.29.0 < 2"
-compression-webpack-plugin@^0.3.2:
- version "0.3.2"
- resolved "https://registry.yarnpkg.com/compression-webpack-plugin/-/compression-webpack-plugin-0.3.2.tgz#1edfb0e749d7366d3e701670c463359b2c0cf704"
+compression-webpack-plugin@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/compression-webpack-plugin/-/compression-webpack-plugin-1.0.0.tgz#5c5eb6afd08ca6a5d66006eeef71da17b01bd676"
dependencies:
- async "0.2.x"
- webpack-sources "^0.1.0"
- optionalDependencies:
- node-zopfli "^2.0.0"
+ async "2.4.1"
+ webpack-sources "^1.0.1"
compression@^1.5.2:
- version "1.6.2"
- resolved "https://registry.yarnpkg.com/compression/-/compression-1.6.2.tgz#cceb121ecc9d09c52d7ad0c3350ea93ddd402bc3"
+ version "1.7.0"
+ resolved "https://registry.yarnpkg.com/compression/-/compression-1.7.0.tgz#030c9f198f1643a057d776a738e922da4373012d"
dependencies:
accepts "~1.3.3"
- bytes "2.3.0"
- compressible "~2.0.8"
- debug "~2.2.0"
+ bytes "2.5.0"
+ compressible "~2.0.10"
+ debug "2.6.8"
on-headers "~1.0.1"
- vary "~1.1.0"
+ safe-buffer "5.1.1"
+ vary "~1.1.1"
concat-map@0.0.1:
version "0.0.1"
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
-concat-stream@^1.4.6:
+concat-stream@^1.5.2:
version "1.6.0"
resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.0.tgz#0aac662fd52be78964d5532f694784e70110acf7"
dependencies:
@@ -1383,11 +1399,11 @@ connect-history-api-fallback@^1.3.0:
resolved "https://registry.yarnpkg.com/connect-history-api-fallback/-/connect-history-api-fallback-1.3.0.tgz#e51d17f8f0ef0db90a64fdb47de3051556e9f169"
connect@^3.6.0:
- version "3.6.2"
- resolved "https://registry.yarnpkg.com/connect/-/connect-3.6.2.tgz#694e8d20681bfe490282c8ab886be98f09f42fe7"
+ version "3.6.3"
+ resolved "https://registry.yarnpkg.com/connect/-/connect-3.6.3.tgz#f7320d46a25b4be7b483a2236517f24b1e27e301"
dependencies:
- debug "2.6.7"
- finalhandler "1.0.3"
+ debug "2.6.8"
+ finalhandler "1.0.4"
parseurl "~1.3.1"
utils-merge "1.0.0"
@@ -1448,7 +1464,11 @@ copy-webpack-plugin@^4.0.1:
minimatch "^3.0.0"
node-dir "^0.1.10"
-core-js@^2.2.0, core-js@^2.4.0, core-js@^2.4.1:
+core-js@^2.2.0:
+ version "2.5.0"
+ resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.5.0.tgz#569c050918be6486b3837552028ae0466b717086"
+
+core-js@^2.4.0, core-js@^2.4.1:
version "2.4.1"
resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.4.1.tgz#4de911e667b0eae9124e34254b53aea6fc618d3e"
@@ -1456,7 +1476,7 @@ core-js@~2.3.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.3.0.tgz#fab83fbb0b2d8dc85fa636c4b9d34c75420c6d65"
-core-util-is@~1.0.0:
+core-util-is@1.0.2, core-util-is@~1.0.0:
version "1.0.2"
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
@@ -1654,7 +1674,7 @@ de-indent@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/de-indent/-/de-indent-1.0.2.tgz#b2038e846dc33baa5796128d0804b455b8c1e21d"
-debug@2.2.0, debug@~2.2.0:
+debug@2.2.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/debug/-/debug-2.2.0.tgz#f87057e995b1a1f6ae6a4960664137bc56f039da"
dependencies:
@@ -1672,7 +1692,7 @@ debug@2.6.7:
dependencies:
ms "2.0.0"
-debug@^2.1.0, debug@^2.1.1, debug@^2.2.0, debug@^2.4.5, debug@^2.6.6, debug@^2.6.8:
+debug@2.6.8, debug@^2.1.0, debug@^2.1.1, debug@^2.2.0, debug@^2.4.5, debug@^2.6.6, debug@^2.6.8:
version "2.6.8"
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.8.tgz#e731531ca2ede27d188222427da17821d68ff4fc"
dependencies:
@@ -1697,8 +1717,8 @@ deep-equal@^1.0.1:
resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.0.1.tgz#f5d260292b660e084eff4cdbc9f08ad3247448b5"
deep-extend@~0.4.0:
- version "0.4.1"
- resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.4.1.tgz#efe4113d08085f4e6f9687759810f807469e2253"
+ version "0.4.2"
+ resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.4.2.tgz#48b699c27e334bf89f10892be432f6e4c7d34a7f"
deep-is@~0.1.3:
version "0.1.3"
@@ -1710,12 +1730,6 @@ default-require-extensions@^1.0.0:
dependencies:
strip-bom "^2.0.0"
-defaults@^1.0.2:
- version "1.0.3"
- resolved "https://registry.yarnpkg.com/defaults/-/defaults-1.0.3.tgz#c656051e9817d9ff08ed881477f3fe4019f3ef7d"
- dependencies:
- clone "^1.0.2"
-
defined@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/defined/-/defined-1.0.0.tgz#c98d9bcef75674188e110969151199e39b1fa693"
@@ -1755,10 +1769,14 @@ delegates@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a"
-depd@1.1.0, depd@~1.1.0:
+depd@1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.0.tgz#e1bd82c6aab6ced965b97b88b17ed3e528ca18c3"
+depd@1.1.1, depd@~1.1.0, depd@~1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.1.tgz#5783b4e1c459f06fa5ca27f991f3d06e7a310359"
+
des.js@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/des.js/-/des.js-1.0.0.tgz#c074d2e2aa6a8a9a07dbd61f9a15c2cd83ec8ecc"
@@ -1776,6 +1794,10 @@ detect-indent@^4.0.0:
dependencies:
repeating "^2.0.0"
+detect-node@^2.0.3:
+ version "2.0.3"
+ resolved "https://registry.yarnpkg.com/detect-node/-/detect-node-2.0.3.tgz#a2033c09cc8e158d37748fbde7507832bd6ce127"
+
di@^0.0.1:
version "0.0.1"
resolved "https://registry.yarnpkg.com/di/-/di-0.0.1.tgz#806649326ceaa7caa3306d75d985ea2748ba913c"
@@ -1793,8 +1815,8 @@ dns-equal@^1.0.0:
resolved "https://registry.yarnpkg.com/dns-equal/-/dns-equal-1.0.0.tgz#b39e7f1da6eb0a75ba9c17324b34753c47e0654d"
dns-packet@^1.0.1:
- version "1.1.1"
- resolved "https://registry.yarnpkg.com/dns-packet/-/dns-packet-1.1.1.tgz#2369d45038af045f3898e6fa56862aed3f40296c"
+ version "1.2.2"
+ resolved "https://registry.yarnpkg.com/dns-packet/-/dns-packet-1.2.2.tgz#a8a26bec7646438963fc86e06f8f8b16d6c8bf7a"
dependencies:
ip "^1.1.0"
safe-buffer "^5.0.1"
@@ -1805,13 +1827,20 @@ dns-txt@^2.0.2:
dependencies:
buffer-indexof "^1.0.0"
-doctrine@1.5.0, doctrine@^1.2.2:
+doctrine@1.5.0:
version "1.5.0"
resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-1.5.0.tgz#379dce730f6166f76cefa4e6707a159b02c5a6fa"
dependencies:
esutils "^2.0.2"
isarray "^1.0.0"
+doctrine@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.0.0.tgz#c73d8d2909d22291e1a007a395804da8b665fe63"
+ dependencies:
+ esutils "^2.0.2"
+ isarray "^1.0.0"
+
document-register-element@^1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/document-register-element/-/document-register-element-1.3.0.tgz#fb3babb523c74662be47be19c6bc33e71990d940"
@@ -1870,10 +1899,10 @@ duplexer@^0.1.1, duplexer@~0.1.1:
resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.1.tgz#ace6ff808c1ce66b57d1ebf97977acb02334cfc1"
duplexify@^3.2.0:
- version "3.5.0"
- resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.5.0.tgz#1aa773002e1578457e9d9d4a50b0ccaaebcbd604"
+ version "3.5.1"
+ resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.5.1.tgz#4e1516be68838bc90a49994f0b39a6e5960befcd"
dependencies:
- end-of-stream "1.0.0"
+ end-of-stream "^1.0.0"
inherits "^2.0.1"
readable-stream "^2.0.0"
stream-shift "^1.0.0"
@@ -1926,11 +1955,11 @@ encodeurl@~1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.1.tgz#79e3d58655346909fe6f0f45a5de68103b294d20"
-end-of-stream@1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.0.0.tgz#d4596e702734a93e40e9af864319eabd99ff2f0e"
+end-of-stream@^1.0.0:
+ version "1.4.0"
+ resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.0.tgz#7a90d833efda6cfa6eac0f4949dbb0fad3a63206"
dependencies:
- once "~1.3.0"
+ once "^1.4.0"
engine.io-client@1.8.3:
version "1.8.3"
@@ -2034,7 +2063,11 @@ es6-map@^0.1.3:
es6-symbol "~3.1.1"
event-emitter "~0.3.5"
-es6-promise@^3.0.2, es6-promise@~3.0.2:
+es6-promise@^3.0.2:
+ version "3.3.1"
+ resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-3.3.1.tgz#a08cdde84ccdbf34d027a1451bc91d4bcd28a613"
+
+es6-promise@~3.0.2:
version "3.0.2"
resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-3.0.2.tgz#010d5858423a5f118979665f46486a95c6ee2bb6"
@@ -2165,16 +2198,17 @@ eslint-plugin-promise@^3.5.0:
resolved "https://registry.yarnpkg.com/eslint-plugin-promise/-/eslint-plugin-promise-3.5.0.tgz#78fbb6ffe047201627569e85a6c5373af2a68fca"
eslint@^3.10.1:
- version "3.15.0"
- resolved "https://registry.yarnpkg.com/eslint/-/eslint-3.15.0.tgz#bdcc6a6c5ffe08160e7b93c066695362a91e30f2"
+ version "3.19.0"
+ resolved "https://registry.yarnpkg.com/eslint/-/eslint-3.19.0.tgz#c8fc6201c7f40dd08941b87c085767386a679acc"
dependencies:
babel-code-frame "^6.16.0"
chalk "^1.1.3"
- concat-stream "^1.4.6"
+ concat-stream "^1.5.2"
debug "^2.1.1"
- doctrine "^1.2.2"
+ doctrine "^2.0.0"
escope "^3.6.0"
espree "^3.4.0"
+ esquery "^1.0.0"
estraverse "^4.2.0"
esutils "^2.0.2"
file-entry-cache "^2.0.0"
@@ -2204,10 +2238,10 @@ eslint@^3.10.1:
user-home "^2.0.0"
espree@^3.4.0:
- version "3.4.0"
- resolved "https://registry.yarnpkg.com/espree/-/espree-3.4.0.tgz#41656fa5628e042878025ef467e78f125cb86e1d"
+ version "3.5.0"
+ resolved "https://registry.yarnpkg.com/espree/-/espree-3.5.0.tgz#98358625bdd055861ea27e2867ea729faf463d8d"
dependencies:
- acorn "4.0.4"
+ acorn "^5.1.1"
acorn-jsx "^3.0.0"
esprima@2.7.x, esprima@^2.6.0, esprima@^2.7.1:
@@ -2218,6 +2252,16 @@ esprima@^3.1.1:
version "3.1.3"
resolved "https://registry.yarnpkg.com/esprima/-/esprima-3.1.3.tgz#fdca51cee6133895e3c88d535ce49dbff62a4633"
+esprima@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.0.tgz#4499eddcd1110e0b218bacf2fa7f7f59f55ca804"
+
+esquery@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.0.0.tgz#cfba8b57d7fba93f17298a8a006a04cda13d80fa"
+ dependencies:
+ estraverse "^4.0.0"
+
esrecurse@^4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.1.0.tgz#4713b6536adf7f2ac4f327d559e7756bff648220"
@@ -2229,7 +2273,7 @@ estraverse@^1.9.1:
version "1.9.3"
resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-1.9.3.tgz#af67f2dc922582415950926091a4005d29c9bb44"
-estraverse@^4.1.1, estraverse@^4.2.0:
+estraverse@^4.0.0, estraverse@^4.1.1, estraverse@^4.2.0:
version "4.2.0"
resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.2.0.tgz#0dee3fed31fcd469618ce7342099fc1afa0bdb13"
@@ -2339,8 +2383,8 @@ exports-loader@^0.6.4:
source-map "0.5.x"
express@^4.13.3, express@^4.15.2:
- version "4.15.3"
- resolved "https://registry.yarnpkg.com/express/-/express-4.15.3.tgz#bab65d0f03aa80c358408972fc700f916944b662"
+ version "4.15.4"
+ resolved "https://registry.yarnpkg.com/express/-/express-4.15.4.tgz#032e2253489cf8fce02666beca3d11ed7a2daed1"
dependencies:
accepts "~1.3.3"
array-flatten "1.1.1"
@@ -2348,23 +2392,23 @@ express@^4.13.3, express@^4.15.2:
content-type "~1.0.2"
cookie "0.3.1"
cookie-signature "1.0.6"
- debug "2.6.7"
- depd "~1.1.0"
+ debug "2.6.8"
+ depd "~1.1.1"
encodeurl "~1.0.1"
escape-html "~1.0.3"
etag "~1.8.0"
- finalhandler "~1.0.3"
+ finalhandler "~1.0.4"
fresh "0.5.0"
merge-descriptors "1.0.1"
methods "~1.1.2"
on-finished "~2.3.0"
parseurl "~1.3.1"
path-to-regexp "0.1.7"
- proxy-addr "~1.1.4"
- qs "6.4.0"
+ proxy-addr "~1.1.5"
+ qs "6.5.0"
range-parser "~1.2.0"
- send "0.15.3"
- serve-static "1.12.3"
+ send "0.15.4"
+ serve-static "1.12.4"
setprototypeof "1.0.3"
statuses "~1.3.1"
type-is "~1.6.15"
@@ -2372,8 +2416,8 @@ express@^4.13.3, express@^4.15.2:
vary "~1.1.1"
extend@^3.0.0, extend@~3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.0.tgz#5a474353b9f3353ddd8176dfd37b91c83a46f1d4"
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.1.tgz#a755ea7bc1adfcc5a31ce7e762dbaadc5e636444"
extglob@^0.3.1:
version "0.3.2"
@@ -2381,9 +2425,9 @@ extglob@^0.3.1:
dependencies:
is-extglob "^1.0.0"
-extsprintf@1.0.2:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.0.2.tgz#e1080e0658e300b06294990cc70e1502235fd550"
+extsprintf@1.3.0, extsprintf@^1.2.0:
+ version "1.3.0"
+ resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05"
fast-deep-equal@^0.1.0:
version "0.1.0"
@@ -2464,11 +2508,11 @@ fill-range@^2.1.0:
repeat-element "^1.1.2"
repeat-string "^1.5.2"
-finalhandler@1.0.3, finalhandler@~1.0.3:
- version "1.0.3"
- resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.0.3.tgz#ef47e77950e999780e86022a560e3217e0d0cc89"
+finalhandler@1.0.4, finalhandler@~1.0.4:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.0.4.tgz#18574f2e7c4b98b8ae3b230c21f201f31bdb3fb7"
dependencies:
- debug "2.6.7"
+ debug "2.6.8"
encodeurl "~1.0.1"
escape-html "~1.0.3"
on-finished "~2.3.0"
@@ -2535,8 +2579,8 @@ forever-agent@~0.6.1:
resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91"
form-data@~2.1.1:
- version "2.1.2"
- resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.1.2.tgz#89c3534008b97eada4cbb157d58f6f5df025eae4"
+ version "2.1.4"
+ resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.1.4.tgz#33c183acf193276ecaa98143a69e94bfee1750d1"
dependencies:
asynckit "^0.4.0"
combined-stream "^1.0.5"
@@ -2575,13 +2619,13 @@ fs.realpath@^1.0.0:
resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
fsevents@^1.0.0:
- version "1.0.17"
- resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.0.17.tgz#8537f3f12272678765b4fd6528c0f1f66f8f4558"
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.1.2.tgz#3282b713fb3ad80ede0e9fcf4611b5aa6fc033f4"
dependencies:
nan "^2.3.0"
- node-pre-gyp "^0.6.29"
+ node-pre-gyp "^0.6.36"
-fstream-ignore@~1.0.5:
+fstream-ignore@^1.0.5:
version "1.0.5"
resolved "https://registry.yarnpkg.com/fstream-ignore/-/fstream-ignore-1.0.5.tgz#9c31dae34767018fe1d249b24dada67d092da105"
dependencies:
@@ -2589,9 +2633,9 @@ fstream-ignore@~1.0.5:
inherits "2"
minimatch "^3.0.0"
-fstream@^1.0.0, fstream@^1.0.2, fstream@~1.0.10:
- version "1.0.10"
- resolved "https://registry.yarnpkg.com/fstream/-/fstream-1.0.10.tgz#604e8a92fe26ffd9f6fae30399d4984e1ab22822"
+fstream@^1.0.0, fstream@^1.0.10, fstream@^1.0.2:
+ version "1.0.11"
+ resolved "https://registry.yarnpkg.com/fstream/-/fstream-1.0.11.tgz#5c1fb1f117477114f0632a0eb4b71b3cb0fd3171"
dependencies:
graceful-fs "^4.1.2"
inherits "~2.0.0"
@@ -2602,9 +2646,9 @@ function-bind@^1.0.2:
version "1.1.0"
resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.0.tgz#16176714c801798e4e8f2cf7f7529467bb4a5771"
-gauge@~2.7.1:
- version "2.7.2"
- resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.2.tgz#15cecc31b02d05345a5d6b0e171cdb3ad2307774"
+gauge@~2.7.3:
+ version "2.7.4"
+ resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7"
dependencies:
aproba "^1.0.3"
console-control-strings "^1.0.0"
@@ -2613,7 +2657,6 @@ gauge@~2.7.1:
signal-exit "^3.0.0"
string-width "^1.0.1"
strip-ansi "^3.0.1"
- supports-color "^0.2.0"
wide-align "^1.1.0"
generate-function@^2.0.0:
@@ -2639,8 +2682,8 @@ get-stream@^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"
+ version "0.1.7"
+ resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa"
dependencies:
assert-plus "^1.0.0"
@@ -2677,7 +2720,18 @@ glob@^6.0.4:
once "^1.3.0"
path-is-absolute "^1.0.0"
-glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.1.1:
+glob@^7.0.0, glob@^7.1.1:
+ version "7.1.2"
+ resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15"
+ dependencies:
+ fs.realpath "^1.0.0"
+ inflight "^1.0.4"
+ inherits "2"
+ minimatch "^3.0.4"
+ once "^1.3.0"
+ path-is-absolute "^1.0.0"
+
+glob@^7.0.3, glob@^7.0.5:
version "7.1.1"
resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.1.tgz#805211df04faaf1c63a3600306cdf5ade50b2ec8"
dependencies:
@@ -2688,10 +2742,14 @@ glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.1.1:
once "^1.3.0"
path-is-absolute "^1.0.0"
-globals@^9.0.0, globals@^9.14.0:
+globals@^9.0.0:
version "9.14.0"
resolved "https://registry.yarnpkg.com/globals/-/globals-9.14.0.tgz#8859936af0038741263053b39d0e76ca241e4034"
+globals@^9.14.0:
+ version "9.18.0"
+ resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a"
+
globby@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/globby/-/globby-5.0.0.tgz#ebd84667ca0dbb330b99bcfc68eac2bc54370e0d"
@@ -2767,7 +2825,7 @@ gzip-size@3.0.0, gzip-size@^3.0.0:
dependencies:
duplexer "^0.1.1"
-handle-thing@^1.2.4:
+handle-thing@^1.2.5:
version "1.2.5"
resolved "https://registry.yarnpkg.com/handle-thing/-/handle-thing-1.2.5.tgz#fd7aad726bf1a5fd16dfc29b2f7a6601d27139c4"
@@ -2781,14 +2839,16 @@ handlebars@^4.0.1, handlebars@^4.0.3:
optionalDependencies:
uglify-js "^2.6"
-har-validator@~2.0.6:
- version "2.0.6"
- resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-2.0.6.tgz#cdcbc08188265ad119b6a5a7c8ab70eecfb5d27d"
+har-schema@^1.0.5:
+ version "1.0.5"
+ resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-1.0.5.tgz#d263135f43307c02c602afc8fe95970c0151369e"
+
+har-validator@~4.2.1:
+ version "4.2.1"
+ resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-4.2.1.tgz#33481d0f1bbff600dd203d75812a6a5fba002e2a"
dependencies:
- chalk "^1.1.1"
- commander "^2.9.0"
- is-my-json-valid "^2.12.4"
- pinkie-promise "^2.0.0"
+ ajv "^4.9.1"
+ har-schema "^1.0.5"
has-ansi@^2.0.0:
version "2.0.0"
@@ -2885,10 +2945,14 @@ html-comment-regex@^1.1.0:
version "1.1.1"
resolved "https://registry.yarnpkg.com/html-comment-regex/-/html-comment-regex-1.1.1.tgz#668b93776eaae55ebde8f3ad464b307a4963625e"
-html-entities@1.2.0, html-entities@^1.2.0:
+html-entities@1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-1.2.0.tgz#41948caf85ce82fed36e4e6a0ed371a6664379e2"
+html-entities@^1.2.0:
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-1.2.1.tgz#0df29351f0721163515dfb9e5543e5f6eed5162f"
+
htmlparser2@^3.8.2:
version "3.9.2"
resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-3.9.2.tgz#1bdf87acca0f3f9e53fa4fcceb0f4b4cbb00b338"
@@ -2900,18 +2964,10 @@ htmlparser2@^3.8.2:
inherits "^2.0.1"
readable-stream "^2.0.2"
-http-deceiver@^1.2.4:
+http-deceiver@^1.2.7:
version "1.2.7"
resolved "https://registry.yarnpkg.com/http-deceiver/-/http-deceiver-1.2.7.tgz#fa7168944ab9a519d337cb0bec7284dc3e723d87"
-http-errors@~1.5.0:
- version "1.5.1"
- resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.5.1.tgz#788c0d2c1de2c81b9e6e8c01843b6b97eb920750"
- dependencies:
- inherits "2.0.3"
- setprototypeof "1.0.2"
- statuses ">= 1.3.1 < 2"
-
http-errors@~1.6.1:
version "1.6.1"
resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.1.tgz#5f8b8ed98aca545656bf572997387f904a722257"
@@ -2921,6 +2977,15 @@ http-errors@~1.6.1:
setprototypeof "1.0.3"
statuses ">= 1.3.1 < 2"
+http-errors@~1.6.2:
+ version "1.6.2"
+ resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.2.tgz#0a002cc85707192a7e7946ceedc11155f60ec736"
+ dependencies:
+ depd "1.1.1"
+ inherits "2.0.3"
+ setprototypeof "1.0.3"
+ statuses ">= 1.3.1 < 2"
+
http-proxy-middleware@~0.17.4:
version "0.17.4"
resolved "https://registry.yarnpkg.com/http-proxy-middleware/-/http-proxy-middleware-0.17.4.tgz#642e8848851d66f09d4f124912846dbaeb41b833"
@@ -2966,8 +3031,8 @@ ignore-by-default@^1.0.0:
resolved "https://registry.yarnpkg.com/ignore-by-default/-/ignore-by-default-1.0.1.tgz#48ca6d72f6c6a3af00a9ad4ae6876be3889e2b09"
ignore@^3.2.0:
- version "3.2.2"
- resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.2.2.tgz#1c51e1ef53bab6ddc15db4d9ac4ec139eceb3410"
+ version "3.3.3"
+ resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.3.tgz#432352e57accd87ab3110e82d3fea0e47812156d"
immediate@~3.0.5:
version "3.0.6"
@@ -3009,7 +3074,7 @@ inflight@^1.0.4:
once "^1.3.0"
wrappy "1"
-inherits@2, inherits@2.0.3, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.0, inherits@~2.0.1:
+inherits@2, inherits@2.0.3, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.0, inherits@~2.0.1, inherits@~2.0.3:
version "2.0.3"
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de"
@@ -3059,13 +3124,13 @@ invert-kv@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6"
-ip@^1.1.0:
+ip@^1.1.0, ip@^1.1.5:
version "1.1.5"
resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.5.tgz#bdded70114290828c0a039e72ef25f5aaec4354a"
-ipaddr.js@1.3.0:
- version "1.3.0"
- resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.3.0.tgz#1e03a52fdad83a8bbb2b25cbf4998b4cffcd3dec"
+ipaddr.js@1.4.0:
+ version "1.4.0"
+ resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.4.0.tgz#296aca878a821816e5b85d0a285a99bcff4582f0"
is-absolute-url@^2.0.0:
version "2.1.0"
@@ -3148,9 +3213,9 @@ is-glob@^3.1.0:
dependencies:
is-extglob "^2.1.0"
-is-my-json-valid@^2.10.0, is-my-json-valid@^2.12.4:
- version "2.15.0"
- resolved "https://registry.yarnpkg.com/is-my-json-valid/-/is-my-json-valid-2.15.0.tgz#936edda3ca3c211fd98f3b2d3e08da43f7b2915b"
+is-my-json-valid@^2.10.0:
+ version "2.16.0"
+ resolved "https://registry.yarnpkg.com/is-my-json-valid/-/is-my-json-valid-2.16.0.tgz#f079dd9bfdae65ee2038aae8acbc86ab109e3693"
dependencies:
generate-function "^2.0.0"
generate-object-property "^1.1.0"
@@ -3271,6 +3336,10 @@ isexe@^1.1.1:
version "1.1.2"
resolved "https://registry.yarnpkg.com/isexe/-/isexe-1.1.2.tgz#36f3e22e60750920f5e7241a476a8c6a42275ad0"
+isexe@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10"
+
isobject@^2.0.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89"
@@ -3383,12 +3452,6 @@ jed@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/jed/-/jed-1.1.1.tgz#7a549bbd9ffe1585b0cd0a191e203055bee574b4"
-jodid25519@^1.0.0:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/jodid25519/-/jodid25519-1.0.2.tgz#06d4912255093419477d425633606e0e90782967"
- dependencies:
- jsbn "~0.1.0"
-
jquery-ujs@^1.2.1:
version "1.2.1"
resolved "https://registry.yarnpkg.com/jquery-ujs/-/jquery-ujs-1.2.1.tgz#6ee75b1ef4e9ac95e7124f8d71f7d351f5548e92"
@@ -3420,13 +3483,24 @@ js-tokens@^3.0.0:
version "3.0.1"
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.1.tgz#08e9f132484a2c45a30907e9dc4d5567b7f114d7"
-js-yaml@3.x, js-yaml@^3.4.3, js-yaml@^3.5.1, js-yaml@^3.7.0:
+js-tokens@^3.0.2:
+ version "3.0.2"
+ resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b"
+
+js-yaml@3.x, js-yaml@^3.4.3, js-yaml@^3.7.0:
version "3.8.1"
resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.8.1.tgz#782ba50200be7b9e5a8537001b7804db3ad02628"
dependencies:
argparse "^1.0.7"
esprima "^3.1.1"
+js-yaml@^3.5.1:
+ version "3.9.1"
+ resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.9.1.tgz#08775cebdfdd359209f0d2acd383c8f86a6904a0"
+ dependencies:
+ argparse "^1.0.7"
+ esprima "^4.0.0"
+
js-yaml@~3.7.0:
version "3.7.0"
resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.7.0.tgz#5c967ddd837a9bfdca5f2de84253abe8a1c03b80"
@@ -3435,8 +3509,8 @@ js-yaml@~3.7.0:
esprima "^2.6.0"
jsbn@~0.1.0:
- version "0.1.0"
- resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.0.tgz#650987da0dd74f4ebf5a11377a2aa2d273e97dfd"
+ version "0.1.1"
+ resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513"
jsesc@^1.3.0:
version "1.3.0"
@@ -3447,12 +3521,12 @@ jsesc@~0.5.0:
resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d"
json-loader@^0.5.4:
- version "0.5.4"
- resolved "https://registry.yarnpkg.com/json-loader/-/json-loader-0.5.4.tgz#8baa1365a632f58a3c46d20175fc6002c96e37de"
+ version "0.5.7"
+ resolved "https://registry.yarnpkg.com/json-loader/-/json-loader-0.5.7.tgz#dca14a70235ff82f0ac9a3abeb60d337a365185d"
json-schema-traverse@^0.3.0:
- version "0.3.0"
- resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.3.0.tgz#0016c0b1ca1efe46d44d37541bcdfc19dcfae0db"
+ version "0.3.1"
+ resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz#349a6d44c53a51de89b40805c5d5e59b417d3340"
json-schema@0.2.3:
version "0.2.3"
@@ -3491,12 +3565,13 @@ jsonpointer@^4.0.0:
resolved "https://registry.yarnpkg.com/jsonpointer/-/jsonpointer-4.0.1.tgz#4fd92cb34e0e9db3c89c8622ecf51f9b978c6cb9"
jsprim@^1.2.2:
- version "1.3.1"
- resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.3.1.tgz#2a7256f70412a29ee3670aaca625994c4dcff252"
+ version "1.4.1"
+ resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2"
dependencies:
- extsprintf "1.0.2"
+ assert-plus "1.0.0"
+ extsprintf "1.3.0"
json-schema "0.2.3"
- verror "1.3.6"
+ verror "1.10.0"
jszip-utils@^0.0.2:
version "0.0.2"
@@ -3960,11 +4035,21 @@ miller-rabin@^4.0.0:
bn.js "^4.0.0"
brorand "^1.0.1"
-"mime-db@>= 1.24.0 < 2", mime-db@~1.27.0:
+"mime-db@>= 1.29.0 < 2", mime-db@~1.29.0:
+ version "1.29.0"
+ resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.29.0.tgz#48d26d235589651704ac5916ca06001914266878"
+
+mime-db@~1.27.0:
version "1.27.0"
resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.27.0.tgz#820f572296bbd20ec25ed55e5b5de869e5436eb1"
-mime-types@^2.1.12, mime-types@~2.1.11, mime-types@~2.1.15, mime-types@~2.1.7:
+mime-types@^2.1.12, mime-types@~2.1.7:
+ version "2.1.16"
+ resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.16.tgz#2b858a52e5ecd516db897ac2be87487830698e23"
+ dependencies:
+ mime-db "~1.29.0"
+
+mime-types@~2.1.11, mime-types@~2.1.15:
version "2.1.15"
resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.15.tgz#a4ebf5064094569237b8cf70046776d09fc92aed"
dependencies:
@@ -3992,6 +4077,12 @@ minimalistic-assert@^1.0.0:
dependencies:
brace-expansion "^1.0.0"
+minimatch@^3.0.4:
+ version "3.0.4"
+ resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
+ dependencies:
+ brace-expansion "^1.1.7"
+
minimist@0.0.8, minimist@~0.0.1:
version "0.0.8"
resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d"
@@ -4049,9 +4140,9 @@ name-all-modules-plugin@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/name-all-modules-plugin/-/name-all-modules-plugin-1.0.1.tgz#0abfb6ad835718b9fb4def0674e06657a954375c"
-nan@^2.0.0, nan@^2.3.0:
- version "2.5.1"
- resolved "https://registry.yarnpkg.com/nan/-/nan-2.5.1.tgz#d5b01691253326a97a2bbee9e61c55d8d60351e2"
+nan@^2.3.0:
+ version "2.6.2"
+ resolved "https://registry.yarnpkg.com/nan/-/nan-2.6.2.tgz#e4ff34e6c95fdfb5aecc08de6596f43605a7db45"
natural-compare@^1.4.0:
version "1.4.0"
@@ -4133,28 +4224,19 @@ node-libs-browser@^2.0.0:
util "^0.10.3"
vm-browserify "0.0.4"
-node-pre-gyp@^0.6.29, node-pre-gyp@^0.6.4:
- version "0.6.33"
- resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.6.33.tgz#640ac55198f6a925972e0c16c4ac26a034d5ecc9"
- dependencies:
- mkdirp "~0.5.1"
- nopt "~3.0.6"
- npmlog "^4.0.1"
- rc "~1.1.6"
- request "^2.79.0"
- rimraf "~2.5.4"
- semver "~5.3.0"
- tar "~2.2.1"
- tar-pack "~3.3.0"
-
-node-zopfli@^2.0.0:
- version "2.0.2"
- resolved "https://registry.yarnpkg.com/node-zopfli/-/node-zopfli-2.0.2.tgz#a7a473ae92aaea85d4c68d45bbf2c944c46116b8"
+node-pre-gyp@^0.6.36:
+ version "0.6.36"
+ resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.6.36.tgz#db604112cb74e0d477554e9b505b17abddfab786"
dependencies:
- commander "^2.8.1"
- defaults "^1.0.2"
- nan "^2.0.0"
- node-pre-gyp "^0.6.4"
+ mkdirp "^0.5.1"
+ nopt "^4.0.1"
+ npmlog "^4.0.2"
+ rc "^1.1.7"
+ request "^2.81.0"
+ rimraf "^2.6.1"
+ semver "^5.3.0"
+ tar "^2.2.1"
+ tar-pack "^3.4.0"
nodemon@^1.11.0:
version "1.11.0"
@@ -4171,19 +4253,26 @@ nodemon@^1.11.0:
undefsafe "0.0.3"
update-notifier "0.5.0"
-nopt@3.x, nopt@~3.0.1, nopt@~3.0.6:
+nopt@3.x, nopt@~3.0.1:
version "3.0.6"
resolved "https://registry.yarnpkg.com/nopt/-/nopt-3.0.6.tgz#c6465dbf08abcd4db359317f79ac68a646b28ff9"
dependencies:
abbrev "1"
+nopt@^4.0.1:
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.1.tgz#d0d4685afd5415193c8c7505602d0d17cd64474d"
+ dependencies:
+ abbrev "1"
+ osenv "^0.1.4"
+
nopt@~1.0.10:
version "1.0.10"
resolved "https://registry.yarnpkg.com/nopt/-/nopt-1.0.10.tgz#6ddd21bd2a31417b92727dd585f8a6f37608ebee"
dependencies:
abbrev "1"
-normalize-package-data@^2.3.2, normalize-package-data@^2.3.4:
+normalize-package-data@^2.3.2:
version "2.3.5"
resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.3.5.tgz#8d924f142960e1777e7ffe170543631cc7cb02df"
dependencies:
@@ -4192,9 +4281,20 @@ normalize-package-data@^2.3.2, normalize-package-data@^2.3.4:
semver "2 || 3 || 4 || 5"
validate-npm-package-license "^3.0.1"
-normalize-path@^2.0.1:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.0.1.tgz#47886ac1662760d4261b7d979d241709d3ce3f7a"
+normalize-package-data@^2.3.4:
+ version "2.4.0"
+ resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.4.0.tgz#12f95a307d58352075a04907b84ac8be98ac012f"
+ dependencies:
+ hosted-git-info "^2.1.4"
+ is-builtin-module "^1.0.0"
+ semver "2 || 3 || 4 || 5"
+ validate-npm-package-license "^3.0.1"
+
+normalize-path@^2.0.0, normalize-path@^2.0.1:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9"
+ dependencies:
+ remove-trailing-separator "^1.0.1"
normalize-range@^0.1.2:
version "0.1.2"
@@ -4215,13 +4315,13 @@ npm-run-path@^2.0.0:
dependencies:
path-key "^2.0.0"
-npmlog@^4.0.1:
- version "4.0.2"
- resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.0.2.tgz#d03950e0e78ce1527ba26d2a7592e9348ac3e75f"
+npmlog@^4.0.2:
+ version "4.1.2"
+ resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b"
dependencies:
are-we-there-yet "~1.1.2"
console-control-strings "~1.1.0"
- gauge "~2.7.1"
+ gauge "~2.7.3"
set-blocking "~2.0.0"
null-check@^1.0.0:
@@ -4263,7 +4363,7 @@ object.omit@^2.0.0:
for-own "^0.1.4"
is-extendable "^0.1.1"
-obuf@^1.0.0, obuf@^1.1.0:
+obuf@^1.0.0, obuf@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/obuf/-/obuf-1.1.1.tgz#104124b6c602c6796881a042541d36db43a5264e"
@@ -4277,18 +4377,12 @@ on-headers@~1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/on-headers/-/on-headers-1.0.1.tgz#928f5d0f470d49342651ea6794b0857c100693f7"
-once@1.x, once@^1.3.0, once@^1.4.0:
+once@1.x, once@^1.3.0, once@^1.3.3, once@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
dependencies:
wrappy "1"
-once@~1.3.0, once@~1.3.3:
- version "1.3.3"
- resolved "https://registry.yarnpkg.com/once/-/once-1.3.3.tgz#b2e261557ce4c314ec8304f3fa82663e4297ca20"
- dependencies:
- wrappy "1"
-
onetime@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/onetime/-/onetime-1.1.0.tgz#a1f7838f8314c516f05ecefcbc4ccfe04b4ed789"
@@ -4354,11 +4448,11 @@ os-locale@^2.0.0:
lcid "^1.0.0"
mem "^1.1.0"
-os-tmpdir@^1.0.0, os-tmpdir@^1.0.1, os-tmpdir@~1.0.1:
+os-tmpdir@^1.0.0, os-tmpdir@^1.0.1, os-tmpdir@~1.0.1, os-tmpdir@~1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274"
-osenv@^0.1.0:
+osenv@^0.1.0, osenv@^0.1.4:
version "0.1.4"
resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.4.tgz#42fe6d5953df06c8064be6f176c3d05aaaa34644"
dependencies:
@@ -4515,6 +4609,10 @@ pbkdf2@^3.0.3:
dependencies:
create-hmac "^1.1.2"
+performance-now@^0.2.0:
+ version "0.2.0"
+ resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-0.2.0.tgz#33ef30c5c77d4ea21c5a53869d91b56d8f2555e5"
+
pify@^2.0.0, pify@^2.3.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c"
@@ -4868,12 +4966,12 @@ proto-list@~1.2.1:
version "1.2.4"
resolved "https://registry.yarnpkg.com/proto-list/-/proto-list-1.2.4.tgz#212d5bfe1318306a420f6402b8e26ff39647a849"
-proxy-addr@~1.1.4:
- version "1.1.4"
- resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-1.1.4.tgz#27e545f6960a44a627d9b44467e35c1b6b4ce2f3"
+proxy-addr@~1.1.5:
+ version "1.1.5"
+ resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-1.1.5.tgz#71c0ee3b102de3f202f3b64f608d173fcba1a918"
dependencies:
forwarded "~0.1.0"
- ipaddr.js "1.3.0"
+ ipaddr.js "1.4.0"
prr@~0.0.0:
version "0.0.0"
@@ -4915,13 +5013,13 @@ qjobs@^1.1.4:
version "1.1.5"
resolved "https://registry.yarnpkg.com/qjobs/-/qjobs-1.1.5.tgz#659de9f2cf8dcc27a1481276f205377272382e73"
-qs@6.4.0:
+qs@6.4.0, qs@~6.4.0:
version "6.4.0"
resolved "https://registry.yarnpkg.com/qs/-/qs-6.4.0.tgz#13e26d28ad6b0ffaa91312cd3bf708ed351e7233"
-qs@~6.3.0:
- version "6.3.0"
- resolved "https://registry.yarnpkg.com/qs/-/qs-6.3.0.tgz#f403b264f23bc01228c74131b407f18d5ea5d442"
+qs@6.5.0:
+ version "6.5.0"
+ resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.0.tgz#8d04954d364def3efc55b5a0793e1e2c8b1e6e49"
query-string@^4.1.0:
version "4.3.2"
@@ -4985,14 +5083,14 @@ raw-loader@^0.5.1:
version "0.5.1"
resolved "https://registry.yarnpkg.com/raw-loader/-/raw-loader-0.5.1.tgz#0c3d0beaed8a01c966d9787bf778281252a979aa"
-rc@^1.0.1, rc@~1.1.6:
- version "1.1.6"
- resolved "https://registry.yarnpkg.com/rc/-/rc-1.1.6.tgz#43651b76b6ae53b5c802f1151fa3fc3b059969c9"
+rc@^1.0.1, rc@^1.1.7:
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.1.tgz#2e03e8e42ee450b8cb3dce65be1bf8974e1dfd95"
dependencies:
deep-extend "~0.4.0"
ini "~1.3.0"
minimist "^1.2.0"
- strip-json-comments "~1.0.4"
+ strip-json-comments "~2.0.1"
react-dev-utils@^0.5.2:
version "0.5.2"
@@ -5046,16 +5144,16 @@ read-pkg@^2.0.0:
normalize-package-data "^2.3.2"
path-type "^2.0.0"
-readable-stream@^2.0.0, "readable-stream@^2.0.0 || ^1.1.13", readable-stream@^2.1.0, readable-stream@^2.2.2:
- version "2.2.2"
- resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.2.2.tgz#a9e6fec3c7dda85f8bb1b3ba7028604556fc825e"
+readable-stream@^2.0.0, readable-stream@^2.0.6, readable-stream@^2.1.4, readable-stream@^2.2.2, readable-stream@^2.2.9:
+ version "2.3.3"
+ resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.3.tgz#368f2512d79f9d46fdfc71349ae7878bbc1eb95c"
dependencies:
- buffer-shims "^1.0.0"
core-util-is "~1.0.0"
- inherits "~2.0.1"
+ inherits "~2.0.3"
isarray "~1.0.0"
process-nextick-args "~1.0.6"
- string_decoder "~0.10.x"
+ safe-buffer "~5.1.1"
+ string_decoder "~1.0.3"
util-deprecate "~1.0.1"
readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.5, readable-stream@~2.0.6:
@@ -5069,26 +5167,26 @@ readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.5, readable
string_decoder "~0.10.x"
util-deprecate "~1.0.1"
-readable-stream@~1.0.2:
- version "1.0.34"
- resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.0.34.tgz#125820e34bc842d2f2aaafafe4c2916ee32c157c"
+readable-stream@^2.1.0:
+ version "2.2.2"
+ resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.2.2.tgz#a9e6fec3c7dda85f8bb1b3ba7028604556fc825e"
dependencies:
+ buffer-shims "^1.0.0"
core-util-is "~1.0.0"
inherits "~2.0.1"
- isarray "0.0.1"
+ isarray "~1.0.0"
+ process-nextick-args "~1.0.6"
string_decoder "~0.10.x"
+ util-deprecate "~1.0.1"
-readable-stream@~2.1.4:
- version "2.1.5"
- resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.1.5.tgz#66fa8b720e1438b364681f2ad1a63c618448c9d0"
+readable-stream@~1.0.2:
+ version "1.0.34"
+ resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.0.34.tgz#125820e34bc842d2f2aaafafe4c2916ee32c157c"
dependencies:
- buffer-shims "^1.0.0"
core-util-is "~1.0.0"
inherits "~2.0.1"
- isarray "~1.0.0"
- process-nextick-args "~1.0.6"
+ isarray "0.0.1"
string_decoder "~0.10.x"
- util-deprecate "~1.0.1"
readdirp@^2.0.0:
version "2.1.0"
@@ -5195,6 +5293,10 @@ regjsparser@^0.1.4:
dependencies:
jsesc "~0.5.0"
+remove-trailing-separator@^1.0.1:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef"
+
repeat-element@^1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.2.tgz#ef089a178d1483baae4d93eb98b4f9e4e11d990a"
@@ -5219,18 +5321,18 @@ repeating@^2.0.0:
dependencies:
is-finite "^1.0.0"
-request@^2.79.0:
- version "2.79.0"
- resolved "https://registry.yarnpkg.com/request/-/request-2.79.0.tgz#4dfe5bf6be8b8cdc37fcf93e04b65577722710de"
+request@^2.81.0:
+ version "2.81.0"
+ resolved "https://registry.yarnpkg.com/request/-/request-2.81.0.tgz#c6928946a0e06c5f8d6f8a9333469ffda46298a0"
dependencies:
aws-sign2 "~0.6.0"
aws4 "^1.2.1"
- caseless "~0.11.0"
+ caseless "~0.12.0"
combined-stream "~1.0.5"
extend "~3.0.0"
forever-agent "~0.6.1"
form-data "~2.1.1"
- har-validator "~2.0.6"
+ har-validator "~4.2.1"
hawk "~3.1.3"
http-signature "~1.1.0"
is-typedarray "~1.0.0"
@@ -5238,10 +5340,12 @@ request@^2.79.0:
json-stringify-safe "~5.0.1"
mime-types "~2.1.7"
oauth-sign "~0.8.1"
- qs "~6.3.0"
+ performance-now "^0.2.0"
+ qs "~6.4.0"
+ safe-buffer "^5.0.1"
stringstream "~0.0.4"
tough-cookie "~2.3.0"
- tunnel-agent "~0.4.1"
+ tunnel-agent "^0.6.0"
uuid "^3.0.0"
require-directory@^2.1.1:
@@ -5292,18 +5396,12 @@ right-align@^0.1.1:
dependencies:
align-text "^0.1.1"
-rimraf@2, rimraf@^2.2.8, rimraf@^2.4.3, rimraf@^2.4.4, rimraf@^2.6.0:
+rimraf@2, rimraf@^2.2.8, rimraf@^2.4.3, rimraf@^2.4.4, rimraf@^2.5.1, rimraf@^2.6.0, rimraf@^2.6.1:
version "2.6.1"
resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.1.tgz#c2338ec643df7a1b7fe5c54fa86f57428a55f33d"
dependencies:
glob "^7.0.5"
-rimraf@~2.5.1, rimraf@~2.5.4:
- version "2.5.4"
- resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.5.4.tgz#96800093cbf1a0c86bd95b4625467535c29dfa04"
- dependencies:
- glob "^7.0.5"
-
ripemd160@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-1.0.1.tgz#93a4bbd4942bc574b69a8fa57c71de10ecca7d6e"
@@ -5318,6 +5416,10 @@ rx-lite@^3.1.2:
version "3.1.2"
resolved "https://registry.yarnpkg.com/rx-lite/-/rx-lite-3.1.2.tgz#19ce502ca572665f3b647b10939f97fd1615f102"
+safe-buffer@5.1.1, safe-buffer@~5.1.0, safe-buffer@~5.1.1:
+ version "5.1.1"
+ resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853"
+
safe-buffer@^5.0.1, safe-buffer@~5.0.1:
version "5.0.1"
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.0.1.tgz#d263ca54696cd8a306b5ca6551e92de57918fbe7"
@@ -5339,8 +5441,8 @@ select@^1.1.2:
resolved "https://registry.yarnpkg.com/select/-/select-1.1.2.tgz#0e7350acdec80b1108528786ec1d4418d11b396d"
selfsigned@^1.9.1:
- version "1.9.1"
- resolved "https://registry.yarnpkg.com/selfsigned/-/selfsigned-1.9.1.tgz#cdda4492d70d486570f87c65546023558e1dfa5a"
+ version "1.10.1"
+ resolved "https://registry.yarnpkg.com/selfsigned/-/selfsigned-1.10.1.tgz#bf8cb7b83256c4551e31347c6311778db99eec52"
dependencies:
node-forge "0.6.33"
@@ -5350,26 +5452,30 @@ semver-diff@^2.0.0:
dependencies:
semver "^5.0.3"
-"semver@2 || 3 || 4 || 5", semver@^5.0.3, semver@^5.3.0, semver@~5.3.0:
+"semver@2 || 3 || 4 || 5", semver@^5.3.0:
version "5.3.0"
resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f"
+semver@^5.0.3:
+ version "5.4.1"
+ resolved "https://registry.yarnpkg.com/semver/-/semver-5.4.1.tgz#e059c09d8571f0540823733433505d3a2f00b18e"
+
semver@~4.3.3:
version "4.3.6"
resolved "https://registry.yarnpkg.com/semver/-/semver-4.3.6.tgz#300bc6e0e86374f7ba61068b5b1ecd57fc6532da"
-send@0.15.3:
- version "0.15.3"
- resolved "https://registry.yarnpkg.com/send/-/send-0.15.3.tgz#5013f9f99023df50d1bd9892c19e3defd1d53309"
+send@0.15.4:
+ version "0.15.4"
+ resolved "https://registry.yarnpkg.com/send/-/send-0.15.4.tgz#985faa3e284b0273c793364a35c6737bd93905b9"
dependencies:
- debug "2.6.7"
- depd "~1.1.0"
+ debug "2.6.8"
+ depd "~1.1.1"
destroy "~1.0.4"
encodeurl "~1.0.1"
escape-html "~1.0.3"
etag "~1.8.0"
fresh "0.5.0"
- http-errors "~1.6.1"
+ http-errors "~1.6.2"
mime "1.3.4"
ms "2.0.0"
on-finished "~2.3.0"
@@ -5377,25 +5483,25 @@ send@0.15.3:
statuses "~1.3.1"
serve-index@^1.7.2:
- version "1.8.0"
- resolved "https://registry.yarnpkg.com/serve-index/-/serve-index-1.8.0.tgz#7c5d96c13fb131101f93c1c5774f8516a1e78d3b"
+ version "1.9.0"
+ resolved "https://registry.yarnpkg.com/serve-index/-/serve-index-1.9.0.tgz#d2b280fc560d616ee81b48bf0fa82abed2485ce7"
dependencies:
accepts "~1.3.3"
- batch "0.5.3"
- debug "~2.2.0"
+ batch "0.6.1"
+ debug "2.6.8"
escape-html "~1.0.3"
- http-errors "~1.5.0"
- mime-types "~2.1.11"
+ http-errors "~1.6.1"
+ mime-types "~2.1.15"
parseurl "~1.3.1"
-serve-static@1.12.3:
- version "1.12.3"
- resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.12.3.tgz#9f4ba19e2f3030c547f8af99107838ec38d5b1e2"
+serve-static@1.12.4:
+ version "1.12.4"
+ resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.12.4.tgz#9b6aa98eeb7253c4eedc4c1f6fdbca609901a961"
dependencies:
encodeurl "~1.0.1"
escape-html "~1.0.3"
parseurl "~1.3.1"
- send "0.15.3"
+ send "0.15.4"
set-blocking@^2.0.0, set-blocking@~2.0.0:
version "2.0.0"
@@ -5409,10 +5515,6 @@ setimmediate@^1.0.4:
version "1.0.5"
resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285"
-setprototypeof@1.0.2:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.0.2.tgz#81a552141ec104b88e89ce383103ad5c66564d08"
-
setprototypeof@1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.0.3.tgz#66567e37043eeb4f04d91bd658c0cbefb55b8e04"
@@ -5434,8 +5536,8 @@ shebang-regex@^1.0.0:
resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3"
shelljs@^0.7.5:
- version "0.7.6"
- resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.7.6.tgz#379cccfb56b91c8601e4793356eb5382924de9ad"
+ version "0.7.8"
+ resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.7.8.tgz#decbcf874b0d1e5fb72e14b164a9683048e9acb3"
dependencies:
glob "^7.0.0"
interpret "^1.0.0"
@@ -5546,7 +5648,7 @@ sort-keys@^1.0.0:
dependencies:
is-plain-obj "^1.0.0"
-source-list-map@^0.1.7, source-list-map@~0.1.7:
+source-list-map@^0.1.7:
version "0.1.8"
resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-0.1.8.tgz#c550b2ab5427f6b3f21f5afead88c4f5587b2106"
@@ -5596,25 +5698,28 @@ spdx-license-ids@^1.0.2:
version "1.2.2"
resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-1.2.2.tgz#c9df7a3424594ade6bd11900d596696dc06bac57"
-spdy-transport@^2.0.15:
- version "2.0.18"
- resolved "https://registry.yarnpkg.com/spdy-transport/-/spdy-transport-2.0.18.tgz#43fc9c56be2cccc12bb3e2754aa971154e836ea6"
+spdy-transport@^2.0.18:
+ version "2.0.20"
+ resolved "https://registry.yarnpkg.com/spdy-transport/-/spdy-transport-2.0.20.tgz#735e72054c486b2354fe89e702256004a39ace4d"
dependencies:
- debug "^2.2.0"
+ debug "^2.6.8"
+ detect-node "^2.0.3"
hpack.js "^2.1.6"
- obuf "^1.1.0"
- readable-stream "^2.0.1"
- wbuf "^1.4.0"
+ obuf "^1.1.1"
+ readable-stream "^2.2.9"
+ safe-buffer "^5.0.1"
+ wbuf "^1.7.2"
spdy@^3.4.1:
- version "3.4.4"
- resolved "https://registry.yarnpkg.com/spdy/-/spdy-3.4.4.tgz#e0406407ca90ff01b553eb013505442649f5a819"
+ version "3.4.7"
+ resolved "https://registry.yarnpkg.com/spdy/-/spdy-3.4.7.tgz#42ff41ece5cc0f99a3a6c28aabb73f5c3b03acbc"
dependencies:
- debug "^2.2.0"
- handle-thing "^1.2.4"
- http-deceiver "^1.2.4"
+ debug "^2.6.8"
+ handle-thing "^1.2.5"
+ http-deceiver "^1.2.7"
+ safe-buffer "^5.0.1"
select-hose "^2.0.0"
- spdy-transport "^2.0.15"
+ spdy-transport "^2.0.18"
split@0.3:
version "0.3.3"
@@ -5631,8 +5736,8 @@ sql.js@^0.4.0:
resolved "https://registry.yarnpkg.com/sql.js/-/sql.js-0.4.0.tgz#23be9635520eb0ff43a741e7e830397266e88445"
sshpk@^1.7.0:
- version "1.10.2"
- resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.10.2.tgz#d5a804ce22695515638e798dbe23273de070a5fa"
+ version "1.13.1"
+ resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.13.1.tgz#512df6da6287144316dc4c18fe1cf1d940739be3"
dependencies:
asn1 "~0.2.3"
assert-plus "^1.0.0"
@@ -5641,7 +5746,6 @@ sshpk@^1.7.0:
optionalDependencies:
bcrypt-pbkdf "^1.0.0"
ecc-jsbn "~0.1.1"
- jodid25519 "^1.0.0"
jsbn "~0.1.0"
tweetnacl "~0.14.0"
@@ -5705,6 +5809,12 @@ string_decoder@^0.10.25, string_decoder@~0.10.x:
version "0.10.31"
resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94"
+string_decoder@~1.0.3:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.0.3.tgz#0fc67d7c141825de94282dd536bec6b9bce860ab"
+ dependencies:
+ safe-buffer "~5.1.0"
+
stringstream@~0.0.4:
version "0.0.5"
resolved "https://registry.yarnpkg.com/stringstream/-/stringstream-0.0.5.tgz#4e484cd4de5a0bbbee18e46307710a8a81621878"
@@ -5735,18 +5845,10 @@ strip-indent@^1.0.1:
dependencies:
get-stdin "^4.0.1"
-strip-json-comments@~1.0.4:
- version "1.0.4"
- resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-1.0.4.tgz#1e15fbcac97d3ee99bf2d73b4c656b082bbafb91"
-
strip-json-comments@~2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a"
-supports-color@^0.2.0:
- version "0.2.0"
- resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-0.2.0.tgz#d92de2694eb3f67323973d7ae3d8b55b4c22190a"
-
supports-color@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7"
@@ -5791,23 +5893,23 @@ tapable@^0.1.8:
resolved "https://registry.yarnpkg.com/tapable/-/tapable-0.1.10.tgz#29c35707c2b70e50d07482b5d202e8ed446dafd4"
tapable@^0.2.7:
- version "0.2.7"
- resolved "https://registry.yarnpkg.com/tapable/-/tapable-0.2.7.tgz#e46c0daacbb2b8a98b9b0cea0f4052105817ed5c"
+ version "0.2.8"
+ resolved "https://registry.yarnpkg.com/tapable/-/tapable-0.2.8.tgz#99372a5c999bf2df160afc0d74bed4f47948cd22"
-tar-pack@~3.3.0:
- version "3.3.0"
- resolved "https://registry.yarnpkg.com/tar-pack/-/tar-pack-3.3.0.tgz#30931816418f55afc4d21775afdd6720cee45dae"
- dependencies:
- debug "~2.2.0"
- fstream "~1.0.10"
- fstream-ignore "~1.0.5"
- once "~1.3.3"
- readable-stream "~2.1.4"
- rimraf "~2.5.1"
- tar "~2.2.1"
- uid-number "~0.0.6"
-
-tar@~2.2.1:
+tar-pack@^3.4.0:
+ version "3.4.0"
+ resolved "https://registry.yarnpkg.com/tar-pack/-/tar-pack-3.4.0.tgz#23be2d7f671a8339376cbdb0b8fe3fdebf317984"
+ dependencies:
+ debug "^2.2.0"
+ fstream "^1.0.10"
+ fstream-ignore "^1.0.5"
+ once "^1.3.3"
+ readable-stream "^2.1.4"
+ rimraf "^2.5.1"
+ tar "^2.2.1"
+ uid-number "^0.0.6"
+
+tar@^2.2.1:
version "2.2.1"
resolved "https://registry.yarnpkg.com/tar/-/tar-2.2.1.tgz#8e4d2a256c0e2185c6b18ad694aec968b83cb1d1"
dependencies:
@@ -5849,6 +5951,10 @@ thunky@^0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/thunky/-/thunky-0.1.0.tgz#bf30146824e2b6e67b0f2d7a4ac8beb26908684e"
+time-stamp@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/time-stamp/-/time-stamp-2.0.0.tgz#95c6a44530e15ba8d6f4a3ecb8c3a3fac46da357"
+
timeago.js@^2.0.5:
version "2.0.5"
resolved "https://registry.yarnpkg.com/timeago.js/-/timeago.js-2.0.5.tgz#730c74fbdb0b0917a553675a4460e3a7f80db86c"
@@ -5868,8 +5974,8 @@ timers-browserify@^1.4.2:
process "~0.11.0"
timers-browserify@^2.0.2:
- version "2.0.2"
- resolved "https://registry.yarnpkg.com/timers-browserify/-/timers-browserify-2.0.2.tgz#ab4883cf597dcd50af211349a00fbca56ac86b86"
+ version "2.0.4"
+ resolved "https://registry.yarnpkg.com/timers-browserify/-/timers-browserify-2.0.4.tgz#96ca53f4b794a5e7c0e1bd7cc88a372298fa01e6"
dependencies:
setimmediate "^1.0.4"
@@ -5877,12 +5983,18 @@ tiny-emitter@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/tiny-emitter/-/tiny-emitter-1.1.0.tgz#ab405a21ffed814a76c19739648093d70654fecb"
-tmp@0.0.31, tmp@0.0.x:
+tmp@0.0.31:
version "0.0.31"
resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.31.tgz#8f38ab9438e17315e5dbd8b3657e8bfb277ae4a7"
dependencies:
os-tmpdir "~1.0.1"
+tmp@0.0.x:
+ version "0.0.33"
+ resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9"
+ dependencies:
+ os-tmpdir "~1.0.2"
+
to-array@0.1.4:
version "0.1.4"
resolved "https://registry.yarnpkg.com/to-array/-/to-array-0.1.4.tgz#17e6c11f73dd4f3d74cda7a4ff3238e9ad9bf890"
@@ -5927,9 +6039,11 @@ tty-browserify@0.0.0:
version "0.0.0"
resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.0.tgz#a157ba402da24e9bf957f9aa69d524eed42901a6"
-tunnel-agent@~0.4.1:
- version "0.4.3"
- resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.4.3.tgz#6373db76909fe570e08d73583365ed828a74eeeb"
+tunnel-agent@^0.6.0:
+ version "0.6.0"
+ resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd"
+ dependencies:
+ safe-buffer "^5.0.1"
tweetnacl@^0.14.3, tweetnacl@~0.14.0:
version "0.14.5"
@@ -5973,7 +6087,7 @@ uglifyjs-webpack-plugin@^0.4.6:
uglify-js "^2.8.29"
webpack-sources "^1.0.1"
-uid-number@~0.0.6:
+uid-number@^0.0.6:
version "0.0.6"
resolved "https://registry.yarnpkg.com/uid-number/-/uid-number-0.0.6.tgz#0ea10e8035e8eb5b8e4449f06da1c730663baa81"
@@ -6079,8 +6193,8 @@ user-home@^2.0.0:
os-homedir "^1.0.0"
useragent@^2.1.12:
- version "2.1.13"
- resolved "https://registry.yarnpkg.com/useragent/-/useragent-2.1.13.tgz#bba43e8aa24d5ceb83c2937473e102e21df74c10"
+ version "2.2.1"
+ resolved "https://registry.yarnpkg.com/useragent/-/useragent-2.2.1.tgz#cf593ef4f2d175875e8bb658ea92e18a4fd06d8e"
dependencies:
lru-cache "2.2.x"
tmp "0.0.x"
@@ -6104,8 +6218,8 @@ uuid@^2.0.1, uuid@^2.0.2:
resolved "https://registry.yarnpkg.com/uuid/-/uuid-2.0.3.tgz#67e2e863797215530dff318e5bf9dcebfd47b21a"
uuid@^3.0.0:
- version "3.0.1"
- resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.0.1.tgz#6544bba2dfda8c1cf17e629a3a305e2bb1fee6c1"
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.1.0.tgz#3dd3d3e790abc24d7b0d3a034ffababe28ebbc04"
validate-npm-package-license@^3.0.1:
version "3.0.1"
@@ -6114,7 +6228,7 @@ validate-npm-package-license@^3.0.1:
spdx-correct "~1.0.0"
spdx-expression-parse "~1.0.0"
-vary@~1.1.0, vary@~1.1.1:
+vary@~1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.1.tgz#67535ebb694c1d52257457984665323f587e8d37"
@@ -6122,11 +6236,13 @@ vendors@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/vendors/-/vendors-1.0.1.tgz#37ad73c8ee417fb3d580e785312307d274847f22"
-verror@1.3.6:
- version "1.3.6"
- resolved "https://registry.yarnpkg.com/verror/-/verror-1.3.6.tgz#cff5df12946d297d2baaefaa2689e25be01c005c"
+verror@1.10.0:
+ version "1.10.0"
+ resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400"
dependencies:
- extsprintf "1.0.2"
+ assert-plus "^1.0.0"
+ core-util-is "1.0.2"
+ extsprintf "^1.2.0"
visibilityjs@^1.2.4:
version "1.2.4"
@@ -6199,7 +6315,7 @@ watchpack@^1.4.0:
chokidar "^1.7.0"
graceful-fs "^4.1.2"
-wbuf@^1.1.0, wbuf@^1.4.0:
+wbuf@^1.1.0, wbuf@^1.7.2:
version "1.7.2"
resolved "https://registry.yarnpkg.com/wbuf/-/wbuf-1.7.2.tgz#d697b99f1f59512df2751be42769c1580b5801fe"
dependencies:
@@ -6221,7 +6337,7 @@ webpack-bundle-analyzer@^2.8.2:
opener "^1.4.3"
ws "^2.3.1"
-webpack-dev-middleware@^1.0.11, webpack-dev-middleware@^1.11.0:
+webpack-dev-middleware@^1.0.11:
version "1.11.0"
resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-1.11.0.tgz#09691d0973a30ad1f82ac73a12e2087f0a4754f9"
dependencies:
@@ -6230,9 +6346,19 @@ webpack-dev-middleware@^1.0.11, webpack-dev-middleware@^1.11.0:
path-is-absolute "^1.0.0"
range-parser "^1.0.3"
+webpack-dev-middleware@^1.11.0:
+ version "1.12.0"
+ resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-1.12.0.tgz#d34efefb2edda7e1d3b5dbe07289513219651709"
+ dependencies:
+ memory-fs "~0.4.1"
+ mime "^1.3.4"
+ path-is-absolute "^1.0.0"
+ range-parser "^1.0.3"
+ time-stamp "^2.0.0"
+
webpack-dev-server@^2.6.1:
- version "2.6.1"
- resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-2.6.1.tgz#0b292a9da96daf80a65988f69f87b4166e5defe7"
+ version "2.7.1"
+ resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-2.7.1.tgz#21580f5a08cd065c71144cf6f61c345bca59a8b8"
dependencies:
ansi-html "0.0.7"
bonjour "^3.5.0"
@@ -6244,6 +6370,7 @@ webpack-dev-server@^2.6.1:
html-entities "^1.2.0"
http-proxy-middleware "~0.17.4"
internal-ip "^1.2.0"
+ ip "^1.1.5"
loglevel "^1.4.1"
opn "4.0.2"
portfinder "^1.0.9"
@@ -6257,13 +6384,6 @@ webpack-dev-server@^2.6.1:
webpack-dev-middleware "^1.11.0"
yargs "^6.0.0"
-webpack-sources@^0.1.0:
- version "0.1.4"
- resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-0.1.4.tgz#ccc2c817e08e5fa393239412690bb481821393cd"
- dependencies:
- source-list-map "~0.1.7"
- source-map "~0.5.3"
-
webpack-sources@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-1.0.1.tgz#c7356436a4d13123be2e2426a05d1dad9cbe65cf"
@@ -6275,9 +6395,9 @@ webpack-stats-plugin@^0.1.5:
version "0.1.5"
resolved "https://registry.yarnpkg.com/webpack-stats-plugin/-/webpack-stats-plugin-0.1.5.tgz#29e5f12ebfd53158d31d656a113ac1f7b86179d9"
-webpack@^3.5.4:
- version "3.5.4"
- resolved "https://registry.yarnpkg.com/webpack/-/webpack-3.5.4.tgz#5583eb263ed27b78b5bd17bfdfb0eb1b1cd1bf81"
+webpack@^3.5.5:
+ version "3.5.5"
+ resolved "https://registry.yarnpkg.com/webpack/-/webpack-3.5.5.tgz#3226f09fc8b3e435ff781e7af34f82b68b26996c"
dependencies:
acorn "^5.0.0"
acorn-dynamic-import "^2.0.0"
@@ -6324,17 +6444,23 @@ which-module@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a"
-which@^1.1.1, which@^1.2.1, which@^1.2.9:
+which@^1.1.1, which@^1.2.1:
version "1.2.12"
resolved "https://registry.yarnpkg.com/which/-/which-1.2.12.tgz#de67b5e450269f194909ef23ece4ebe416fa1192"
dependencies:
isexe "^1.1.1"
+which@^1.2.9:
+ version "1.3.0"
+ resolved "https://registry.yarnpkg.com/which/-/which-1.3.0.tgz#ff04bdfc010ee547d780bec38e1ac1c2777d253a"
+ dependencies:
+ isexe "^2.0.0"
+
wide-align@^1.1.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.0.tgz#40edde802a71fea1f070da3e62dcda2e7add96ad"
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.2.tgz#571e0f1b0604636ebc0dfc21b0339bbe31341710"
dependencies:
- string-width "^1.0.1"
+ string-width "^1.0.2"
window-size@0.1.0:
version "0.1.0"
@@ -6364,8 +6490,8 @@ wrappy@1:
resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
write-file-atomic@^1.1.2:
- version "1.3.1"
- resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-1.3.1.tgz#7d45ba32316328dd1ec7d90f60ebc0d845bb759a"
+ version "1.3.4"
+ resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-1.3.4.tgz#f807a4f0b1d9e913ae7a48112e6cc3af1991b45f"
dependencies:
graceful-fs "^4.1.11"
imurmurhash "^0.1.4"