summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitlab-ci.yml15
-rw-r--r--.rubocop.yml22
-rw-r--r--.rubocop_todo.yml8
-rw-r--r--CHANGELOG.md9
-rw-r--r--CONTRIBUTING.md2
-rw-r--r--GITALY_SERVER_VERSION2
-rw-r--r--Gemfile15
-rw-r--r--Gemfile.lock57
-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/fly_out_nav.js13
-rw-r--r--app/assets/javascripts/groups/components/group_item.vue6
-rw-r--r--app/assets/javascripts/issue_show/components/edited.vue2
-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/dashboard.vue (renamed from app/assets/javascripts/monitoring/components/monitoring.vue)56
-rw-r--r--app/assets/javascripts/monitoring/components/empty_state.vue (renamed from app/assets/javascripts/monitoring/components/monitoring_state.vue)52
-rw-r--r--app/assets/javascripts/monitoring/components/graph.vue (renamed from app/assets/javascripts/monitoring/components/monitoring_column.vue)44
-rw-r--r--app/assets/javascripts/monitoring/components/graph/deployment.vue (renamed from app/assets/javascripts/monitoring/components/monitoring_deployment.vue)9
-rw-r--r--app/assets/javascripts/monitoring/components/graph/flag.vue (renamed from app/assets/javascripts/monitoring/components/monitoring_flag.vue)7
-rw-r--r--app/assets/javascripts/monitoring/components/graph/legend.vue (renamed from app/assets/javascripts/monitoring/components/monitoring_legends.vue)4
-rw-r--r--app/assets/javascripts/monitoring/components/graph_group.vue21
-rw-r--r--app/assets/javascripts/monitoring/components/graph_row.vue (renamed from app/assets/javascripts/monitoring/components/monitoring_row.vue)14
-rw-r--r--app/assets/javascripts/monitoring/constants.js4
-rw-r--r--app/assets/javascripts/monitoring/monitoring_bundle.js6
-rw-r--r--app/assets/javascripts/monitoring/utils/date_time_formatters.js15
-rw-r--r--app/assets/javascripts/new_sidebar.js6
-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.js16
-rw-r--r--app/assets/javascripts/vue_shared/components/commit.vue20
-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/stylesheets/framework/dropdowns.scss9
-rw-r--r--app/assets/stylesheets/framework/filters.scss18
-rw-r--r--app/assets/stylesheets/framework/selects.scss6
-rw-r--r--app/assets/stylesheets/framework/typography.scss4
-rw-r--r--app/assets/stylesheets/framework/variables.scss1
-rw-r--r--app/assets/stylesheets/pages/editor.scss2
-rw-r--r--app/assets/stylesheets/pages/members.scss2
-rw-r--r--app/assets/stylesheets/pages/merge_requests.scss4
-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/pipelines.scss4
-rw-r--r--app/assets/stylesheets/pages/repo.scss24
-rw-r--r--app/assets/stylesheets/pages/todos.scss4
-rw-r--r--app/controllers/admin/users_controller.rb15
-rw-r--r--app/controllers/autocomplete_controller.rb18
-rw-r--r--app/controllers/concerns/issuable_collections.rb12
-rw-r--r--app/controllers/concerns/requires_whitelisted_monitoring_client.rb3
-rw-r--r--app/controllers/groups/milestones_controller.rb6
-rw-r--r--app/controllers/projects/application_controller.rb2
-rw-r--r--app/controllers/projects/issues_controller.rb2
-rw-r--r--app/controllers/projects/merge_requests_controller.rb4
-rw-r--r--app/finders/issuable_finder.rb10
-rw-r--r--app/helpers/application_helper.rb4
-rw-r--r--app/helpers/application_settings_helper.rb3
-rw-r--r--app/helpers/auth_helper.rb2
-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/helpers/projects_helper.rb2
-rw-r--r--app/helpers/tab_helper.rb4
-rw-r--r--app/mailers/base_mailer.rb4
-rw-r--r--app/models/ci/build.rb4
-rw-r--r--app/models/ci/runner.rb2
-rw-r--r--app/models/concerns/awardable.rb15
-rw-r--r--app/models/concerns/editable.rb2
-rw-r--r--app/models/concerns/milestoneish.rb8
-rw-r--r--app/models/concerns/protected_ref.rb2
-rw-r--r--app/models/concerns/spammable.rb2
-rw-r--r--app/models/dashboard_milestone.rb2
-rw-r--r--app/models/deployment.rb2
-rw-r--r--app/models/environment.rb2
-rw-r--r--app/models/group.rb4
-rw-r--r--app/models/group_milestone.rb2
-rw-r--r--app/models/issue.rb6
-rw-r--r--app/models/merge_request.rb22
-rw-r--r--app/models/milestone.rb6
-rw-r--r--app/models/namespace.rb4
-rw-r--r--app/models/network/graph.rb4
-rw-r--r--app/models/notification_recipient.rb53
-rw-r--r--app/models/project.rb11
-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/protected_branch.rb2
-rw-r--r--app/models/repository.rb75
-rw-r--r--app/models/snippet.rb2
-rw-r--r--app/models/user.rb4
-rw-r--r--app/policies/base_policy.rb4
-rw-r--r--app/policies/project_policy.rb6
-rw-r--r--app/services/akismet_service.rb4
-rw-r--r--app/services/auth/container_registry_authentication_service.rb2
-rw-r--r--app/services/ci/create_pipeline_service.rb2
-rw-r--r--app/services/concerns/users/new_user_notifier.rb9
-rw-r--r--app/services/git_push_service.rb10
-rw-r--r--app/services/merge_requests/merge_service.rb6
-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/after_import_service.rb29
-rw-r--r--app/services/projects/create_service.rb19
-rw-r--r--app/services/projects/housekeeping_service.rb2
-rw-r--r--app/services/projects/update_pages_service.rb2
-rw-r--r--app/services/spam_service.rb2
-rw-r--r--app/services/system_note_service.rb2
-rw-r--r--app/services/test_hooks/system_service.rb37
-rw-r--r--app/services/upload_service.rb2
-rw-r--r--app/services/user_project_access_changed_service.rb10
-rw-r--r--app/services/users/build_service.rb2
-rw-r--r--app/services/users/create_service.rb8
-rw-r--r--app/services/users/update_service.rb6
-rw-r--r--app/views/admin/dashboard/_head.html.haml4
-rw-r--r--app/views/admin/monitoring/_head.html.haml4
-rw-r--r--app/views/groups/merge_requests.html.haml6
-rw-r--r--app/views/groups/milestones/show.html.haml2
-rw-r--r--app/views/layouts/nav/_breadcrumbs.html.haml3
-rw-r--r--app/views/layouts/nav/_new_admin_sidebar.html.haml34
-rw-r--r--app/views/layouts/nav/_new_group_sidebar.html.haml10
-rw-r--r--app/views/layouts/nav/_new_profile_sidebar.html.haml24
-rw-r--r--app/views/layouts/nav/_new_project_sidebar.html.haml20
-rw-r--r--app/views/profiles/gpg_keys/index.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/new.html.haml7
-rw-r--r--app/views/projects/notes/_actions.html.haml8
-rw-r--r--app/views/projects/settings/_head.html.haml2
-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/issuable/_search_bar.html.haml7
-rw-r--r--app/views/shared/milestones/_milestone.html.haml8
-rw-r--r--app/views/shared/milestones/_top.html.haml8
-rw-r--r--app/workers/authorized_projects_worker.rb22
-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/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/merge_worker.rb2
-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/stage_update_worker.rb2
-rw-r--r--changelogs/unreleased/26692-predefined-variable-gitlab-user-name.yml5
-rw-r--r--changelogs/unreleased/28202_decrease_abc_threshold_step3.yml5
-rw-r--r--changelogs/unreleased/28453-add-time-estimate-time-spent-to-api-issue-output.yml4
-rw-r--r--changelogs/unreleased/28938-password-change-workflow-for-admins.yml5
-rw-r--r--changelogs/unreleased/31470-fix-api-files-raw.yml5
-rw-r--r--changelogs/unreleased/34413-move-convdev-index-location-to-after-cohorts.yml4
-rw-r--r--changelogs/unreleased/34990-top-buttons-misaligned.yml5
-rw-r--r--changelogs/unreleased/35048-empty-badges.yml5
-rw-r--r--changelogs/unreleased/35793_fix_predicate_names.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/36582-fix-note-resolved-icon.yml5
-rw-r--r--changelogs/unreleased/36792-inline-user-refresh-when-creating-project.yml5
-rw-r--r--changelogs/unreleased/36807-gc-unwanted-refs-after-import.yml5
-rw-r--r--changelogs/unreleased/36882-disable-gitlab-project-import-button-if-source-disabled.yml5
-rw-r--r--changelogs/unreleased/36917-branch-tooltip.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/37179-dashboard-project-dropdown.yml5
-rw-r--r--changelogs/unreleased/37198-api-doesn-t-respect-default-group-visibility.yml5
-rw-r--r--changelogs/unreleased/add-filter-by-my-reaction.yml4
-rw-r--r--changelogs/unreleased/api-delete-respect-headers.yml5
-rw-r--r--changelogs/unreleased/bugfix-notify-custom-participants.yml5
-rw-r--r--changelogs/unreleased/changes-bar-sticky-fix.yml5
-rw-r--r--changelogs/unreleased/check-trigger-permissions.yml5
-rw-r--r--changelogs/unreleased/dm-ldap-adapter-attributes.yml6
-rw-r--r--changelogs/unreleased/docs-update-ci-docker-using-docker-images.yml5
-rw-r--r--changelogs/unreleased/fix-gem-security-updates.yml5
-rw-r--r--changelogs/unreleased/fix-import-events.yml5
-rw-r--r--changelogs/unreleased/fix-old-mr-diffs.yml6
-rw-r--r--changelogs/unreleased/fix-push-events-branch-removals.yml5
-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/group-mr-search-bar.yml5
-rw-r--r--changelogs/unreleased/improve-autocomplete-user-performance.yml5
-rw-r--r--changelogs/unreleased/issue-boards-breadcrumbs-container.yml5
-rw-r--r--changelogs/unreleased/mk-default-ldap-verify-certificates-secure.yml5
-rw-r--r--changelogs/unreleased/mr-index-eager-load.yml5
-rw-r--r--changelogs/unreleased/perf-slow-issuable.yml6
-rw-r--r--changelogs/unreleased/rd-fix-broken-configuration-for-some-integrations.yml5
-rw-r--r--changelogs/unreleased/replace_spinach_star-feature.yml5
-rw-r--r--changelogs/unreleased/replace_spinach_user_lookup-feature.yml5
-rw-r--r--changelogs/unreleased/sh-filter-csrf-params.yml5
-rw-r--r--changelogs/unreleased/sidebar-cache-updates.yml5
-rw-r--r--changelogs/unreleased/zj-disable-pages-in-subgroups.yml5
-rw-r--r--changelogs/unreleased/zj-fix-fe-blank-button.yml5
-rw-r--r--config/application.rb15
-rw-r--r--config/gitlab.yml.example5
-rw-r--r--config/initializers/1_settings.rb17
-rw-r--r--config/initializers/7_prometheus_metrics.rb3
-rw-r--r--config/initializers/8_metrics.rb3
-rw-r--r--config/initializers/sentry.rb5
-rw-r--r--config/initializers/session_store.rb3
-rw-r--r--config/routes.rb1
-rw-r--r--config/sidekiq_queues.yml4
-rw-r--r--db/post_migrate/20170822101017_migrate_pipeline_sidekiq_queues.rb17
-rw-r--r--doc/README.md3
-rw-r--r--doc/administration/auth/ldap.md9
-rw-r--r--doc/api/README.md1
-rw-r--r--doc/api/issues.md56
-rw-r--r--doc/api/merge_requests.md62
-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/ssh_keys/README.md2
-rw-r--r--doc/ci/variables/README.md2
-rw-r--r--doc/development/fe_guide/style_guide_js.md121
-rw-r--r--doc/development/testing.md5
-rw-r--r--doc/install/kubernetes/gitlab_chart.md12
-rw-r--r--doc/install/kubernetes/gitlab_omnibus.md54
-rw-r--r--doc/install/kubernetes/gitlab_runner_chart.md24
-rw-r--r--doc/install/kubernetes/index.md54
-rw-r--r--doc/install/requirements.md4
-rw-r--r--doc/raketasks/backup_restore.md5
-rw-r--r--doc/user/project/gpg_signed_commits/index.md246
-rw-r--r--doc/user/project/members/img/other_group_sees_shared_project.pngbin30182 -> 21154 bytes
-rw-r--r--doc/user/project/members/img/share_project_with_groups.pngbin30307 -> 37405 bytes
-rw-r--r--doc/user/project/members/img/share_project_with_groups_tab.pngbin0 -> 36482 bytes
-rw-r--r--doc/user/project/members/share_project_with_groups.md19
-rw-r--r--doc/user/project/pipelines/job_artifacts.md17
-rw-r--r--doc/user/project/repository/gpg_signed_commits/img/profile_settings_gpg_keys_paste_pub.png (renamed from doc/user/project/gpg_signed_commits/img/profile_settings_gpg_keys_paste_pub.png)bin24514 -> 24514 bytes
-rw-r--r--doc/user/project/repository/gpg_signed_commits/img/profile_settings_gpg_keys_single_key.png (renamed from doc/user/project/gpg_signed_commits/img/profile_settings_gpg_keys_single_key.png)bin4403 -> 4403 bytes
-rw-r--r--doc/user/project/repository/gpg_signed_commits/img/project_signed_and_unsigned_commits.png (renamed from doc/user/project/gpg_signed_commits/img/project_signed_and_unsigned_commits.png)bin41193 -> 41193 bytes
-rw-r--r--doc/user/project/repository/gpg_signed_commits/img/project_signed_commit_unverified_signature.png (renamed from doc/user/project/gpg_signed_commits/img/project_signed_commit_unverified_signature.png)bin9542 -> 9542 bytes
-rw-r--r--doc/user/project/repository/gpg_signed_commits/img/project_signed_commit_verified_signature.png (renamed from doc/user/project/gpg_signed_commits/img/project_signed_commit_verified_signature.png)bin14029 -> 14029 bytes
-rw-r--r--doc/user/project/repository/gpg_signed_commits/index.md245
-rw-r--r--doc/user/project/repository/index.md4
-rw-r--r--features/project/commits/user_lookup.feature16
-rw-r--r--features/project/star.feature39
-rw-r--r--features/steps/project/commits/user_lookup.rb49
-rw-r--r--features/steps/project/star.rb37
-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/entities.rb44
-rw-r--r--lib/api/environments.rb3
-rw-r--r--lib/api/files.rb14
-rw-r--r--lib/api/group_variables.rb3
-rw-r--r--lib/api/groups.rb11
-rw-r--r--lib/api/helpers.rb21
-rw-r--r--lib/api/helpers/runner.rb2
-rw-r--r--lib/api/issues.rb32
-rw-r--r--lib/api/labels.rb3
-rw-r--r--lib/api/members.rb8
-rw-r--r--lib/api/merge_requests.rb6
-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/email_template_interceptor.rb2
-rw-r--r--lib/github/import.rb82
-rw-r--r--lib/gitlab/asciidoc.rb2
-rw-r--r--lib/gitlab/auth.rb2
-rw-r--r--lib/gitlab/checks/force_push.rb2
-rw-r--r--lib/gitlab/ci/config/entry/attributable.rb4
-rw-r--r--lib/gitlab/ci/config/entry/configurable.rb3
-rw-r--r--lib/gitlab/ci/config/entry/job.rb4
-rw-r--r--lib/gitlab/ci/config/entry/node.rb18
-rw-r--r--lib/gitlab/ci/config/entry/policy.rb31
-rw-r--r--lib/gitlab/ci/config/entry/simplifiable.rb43
-rw-r--r--lib/gitlab/ci/config/entry/trigger.rb18
-rw-r--r--lib/gitlab/ci/config/entry/validatable.rb11
-rw-r--r--lib/gitlab/ci/config/entry/validator.rb16
-rw-r--r--lib/gitlab/current_settings.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.rb8
-rw-r--r--lib/gitlab/database/grant.rb34
-rw-r--r--lib/gitlab/database/migration_helpers.rb50
-rw-r--r--lib/gitlab/git/repository.rb32
-rw-r--r--lib/gitlab/gitaly_client/commit_service.rb2
-rw-r--r--lib/gitlab/gitaly_client/repository_service.rb16
-rw-r--r--lib/gitlab/gon_helper.rb1
-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.yml4
-rw-r--r--lib/gitlab/metrics/influx_db.rb2
-rw-r--r--lib/gitlab/performance_bar.rb2
-rw-r--r--lib/gitlab/polling_interval.rb2
-rw-r--r--lib/gitlab/prometheus/queries/matched_metrics_query.rb4
-rw-r--r--lib/gitlab/protocol_access.rb2
-rw-r--r--lib/gitlab/recaptcha.rb2
-rw-r--r--lib/gitlab/sentry.rb2
-rw-r--r--lib/gitlab/shell.rb55
-rw-r--r--lib/gitlab/sql/pattern.rb23
-rw-r--r--lib/gitlab/usage_data.rb4
-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/cleanup.rake2
-rw-r--r--lib/tasks/gitlab/task_helpers.rb4
-rw-r--r--lib/tasks/import.rake2
-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/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
-rwxr-xr-xscripts/static-analysis2
-rw-r--r--spec/controllers/admin/users_controller_spec.rb32
-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/pages_controller_spec.rb13
-rw-r--r--spec/controllers/projects/protected_tags_controller_spec.rb17
-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/triggers.rb2
-rw-r--r--spec/features/groups/merge_requests_spec.rb15
-rw-r--r--spec/features/issues/filtered_search/dropdown_assignee_spec.rb6
-rw-r--r--spec/features/issues/filtered_search/dropdown_author_spec.rb12
-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/projects/commit/mini_pipeline_graph_spec.rb18
-rw-r--r--spec/features/projects/commits/rss_spec.rb (renamed from spec/features/projects/commit/rss_spec.rb)0
-rw-r--r--spec/features/projects/commits/user_browses_commits_spec.rb44
-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/snippets/notes_on_personal_snippets_spec.rb2
-rw-r--r--spec/finders/issues_finder_spec.rb35
-rw-r--r--spec/fixtures/api/schemas/public_api/v4/issues.json8
-rw-r--r--spec/fixtures/api/schemas/public_api/v4/merge_requests.json8
-rw-r--r--spec/helpers/version_check_helper_spec.rb4
-rw-r--r--spec/javascripts/droplab/drop_down_spec.js15
-rw-r--r--spec/javascripts/fly_out_nav_spec.js34
-rw-r--r--spec/javascripts/helpers/vue_mount_component_helper.js4
-rw-r--r--spec/javascripts/issue_show/components/edited_spec.js10
-rw-r--r--spec/javascripts/merge_request_tabs_spec.js11
-rw-r--r--spec/javascripts/monitoring/dashboard_spec.js (renamed from spec/javascripts/monitoring/monitoring_spec.js)12
-rw-r--r--spec/javascripts/monitoring/dashboard_state_spec.js (renamed from spec/javascripts/monitoring/monitoring_state_spec.js)6
-rw-r--r--spec/javascripts/monitoring/graph/deployment_spec.js (renamed from spec/javascripts/monitoring/monitoring_deployment_spec.js)6
-rw-r--r--spec/javascripts/monitoring/graph/flag_spec.js (renamed from spec/javascripts/monitoring/monitoring_flag_spec.js)6
-rw-r--r--spec/javascripts/monitoring/graph/legend_spec.js (renamed from spec/javascripts/monitoring/monitoring_legends_spec.js)6
-rw-r--r--spec/javascripts/monitoring/graph_row_spec.js (renamed from spec/javascripts/monitoring/monitoring_row_spec.js)11
-rw-r--r--spec/javascripts/monitoring/graph_spec.js (renamed from spec/javascripts/monitoring/monitoring_column_spec.js)28
-rw-r--r--spec/javascripts/pipelines/navigation_tabs_spec.js127
-rw-r--r--spec/javascripts/project_select_combo_button_spec.js15
-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/ci/gitlab_ci_yaml_processor_spec.rb42
-rw-r--r--spec/lib/gitlab/auth/unique_ips_limiter_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/config/entry/attributable_spec.rb27
-rw-r--r--spec/lib/gitlab/ci/config/entry/configurable_spec.rb36
-rw-r--r--spec/lib/gitlab/ci/config/entry/policy_spec.rb73
-rw-r--r--spec/lib/gitlab/ci/config/entry/simplifiable_spec.rb88
-rw-r--r--spec/lib/gitlab/ci/config/entry/trigger_spec.rb56
-rw-r--r--spec/lib/gitlab/ci/config/entry/validatable_spec.rb10
-rw-r--r--spec/lib/gitlab/ci/config/entry/validator_spec.rb2
-rw-r--r--spec/lib/gitlab/database/grant_spec.rb30
-rw-r--r--spec/lib/gitlab/database/migration_helpers_spec.rb83
-rw-r--r--spec/lib/gitlab/git/repository_spec.rb34
-rw-r--r--spec/lib/gitlab/import_export/project_tree_restorer_spec.rb4
-rw-r--r--spec/lib/gitlab/shell_spec.rb64
-rw-r--r--spec/lib/gitlab/sql/pattern_spec.rb55
-rw-r--r--spec/migrations/migrate_pipeline_sidekiq_queues_spec.rb55
-rw-r--r--spec/models/ci/build_spec.rb8
-rw-r--r--spec/models/concerns/awardable_spec.rb22
-rw-r--r--spec/models/concerns/editable_spec.rb6
-rw-r--r--spec/models/issue_spec.rb18
-rw-r--r--spec/models/merge_request_spec.rb51
-rw-r--r--spec/models/project_spec.rb35
-rw-r--r--spec/models/repository_spec.rb58
-rw-r--r--spec/models/user_spec.rb17
-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/files_spec.rb9
-rw-r--r--spec/requests/api/group_variables_spec.rb4
-rw-r--r--spec/requests/api/groups_spec.rb5
-rw-r--r--spec/requests/api/issues_spec.rb20
-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/services/ci/create_pipeline_service_spec.rb29
-rw-r--r--spec/services/git_push_service_spec.rb4
-rw-r--r--spec/services/issues/create_service_spec.rb4
-rw-r--r--spec/services/merge_requests/merge_service_spec.rb32
-rw-r--r--spec/services/notification_service_spec.rb17
-rw-r--r--spec/services/projects/after_import_service_spec.rb55
-rw-r--r--spec/services/projects/create_service_spec.rb2
-rw-r--r--spec/services/projects/housekeeping_service_spec.rb13
-rw-r--r--spec/services/spam_service_spec.rb6
-rw-r--r--spec/services/system_note_service_spec.rb59
-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/update_service_spec.rb17
-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/support/stub_env.rb2
-rw-r--r--spec/views/admin/dashboard/index.html.haml_spec.rb1
-rw-r--r--spec/views/devise/shared/_signin_box.html.haml_spec.rb1
-rw-r--r--spec/views/help/index.html.haml_spec.rb1
-rw-r--r--spec/views/layouts/_head.html.haml_spec.rb4
-rw-r--r--spec/views/projects/commits/_commit.html.haml_spec.rb4
-rw-r--r--spec/views/projects/edit.html.haml_spec.rb4
-rw-r--r--spec/views/projects/merge_requests/creations/_new_submit.html.haml_spec.rb1
-rw-r--r--spec/views/projects/merge_requests/show.html.haml_spec.rb4
-rw-r--r--spec/views/projects/tree/show.html.haml_spec.rb1
-rw-r--r--spec/views/shared/projects/_project.html.haml_spec.rb4
-rw-r--r--spec/workers/authorized_projects_worker_spec.rb55
-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/pipeline_metrics_worker_spec.rb9
-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
476 files changed, 8241 insertions, 3890 deletions
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 6f356a07576..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
diff --git a/.rubocop.yml b/.rubocop.yml
index 23bb0fa8be8..16f2e4484fc 100644
--- a/.rubocop.yml
+++ b/.rubocop.yml
@@ -606,13 +606,25 @@ 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,
# branches, and conditions.
Metrics/AbcSize:
Enabled: true
- Max: 56.96
+ Max: 55.25
# This cop checks if the length of a block exceeds some maximum value.
Metrics/BlockLength:
@@ -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:
@@ -653,7 +665,7 @@ Metrics/ParameterLists:
# A complexity metric geared towards measuring complexity for a human reader.
Metrics/PerceivedComplexity:
Enabled: true
- Max: 18
+ Max: 17
# Lint ########################################################################
@@ -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 d32b6989388..ac0d22ced46 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,15 @@
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
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 be386c9ede3..85e60ed180c 100644
--- a/GITALY_SERVER_VERSION
+++ b/GITALY_SERVER_VERSION
@@ -1 +1 @@
-0.33.0
+0.34.0
diff --git a/Gemfile b/Gemfile
index dcdaf6cde7b..a05747e9ef5 100644
--- a/Gemfile
+++ b/Gemfile
@@ -27,7 +27,7 @@ gem 'doorkeeper-openid_connect', '~> 1.1.0'
gem 'omniauth', '~> 1.4.2'
gem 'omniauth-auth0', '~> 1.4.1'
gem 'omniauth-azure-oauth2', '~> 0.0.6'
-gem 'omniauth-cas3', '~> 1.1.2'
+gem 'omniauth-cas3', '~> 1.1.4'
gem 'omniauth-facebook', '~> 4.0.0'
gem 'omniauth-github', '~> 1.1.1'
gem 'omniauth-gitlab', '~> 1.0.2'
@@ -126,12 +126,9 @@ gem 'wikicloth', '0.8.1'
gem 'asciidoctor', '~> 1.5.2'
gem 'asciidoctor-plantuml', '0.0.7'
gem 'rouge', '~> 2.0'
-gem 'truncato', '~> 0.7.8'
+gem 'truncato', '~> 0.7.9'
gem 'bootstrap_form', '~> 2.7.0'
-
-# See https://groups.google.com/forum/#!topic/ruby-security-ann/aSbgDiwb24s
-# and https://groups.google.com/forum/#!topic/ruby-security-ann/Dy7YiKb_pMM
-gem 'nokogiri', '~> 1.6.7', '>= 1.6.7.2'
+gem 'nokogiri', '~> 1.8.0'
# Diffs
gem 'diffy', '~> 3.1.0'
@@ -245,7 +242,7 @@ gem 'uglifier', '~> 2.7.2'
gem 'addressable', '~> 2.3.8'
gem 'bootstrap-sass', '~> 3.3.0'
gem 'font-awesome-rails', '~> 4.7'
-gem 'gemojione', '~> 3.0'
+gem 'gemojione', '~> 3.3'
gem 'gon', '~> 6.1.0'
gem 'jquery-atwho-rails', '~> 1.3.2'
gem 'jquery-rails', '~> 4.1.0'
@@ -284,7 +281,7 @@ group :metrics do
gem 'influxdb', '~> 0.2', require: false
# Prometheus
- gem 'prometheus-client-mmap', '~>0.7.0.beta12'
+ gem 'prometheus-client-mmap', '~>0.7.0.beta14'
gem 'raindrops', '~> 0.18'
end
@@ -337,7 +334,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
diff --git a/Gemfile.lock b/Gemfile.lock
index 0fd52337b23..8634a9e8822 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -261,7 +261,7 @@ GEM
ruby-progressbar (~> 1.4)
gemnasium-gitlab-service (0.2.6)
rugged (~> 0.21)
- gemojione (3.0.1)
+ gemojione (3.3.0)
json
get_process_mem (0.2.0)
gettext (3.2.2)
@@ -283,7 +283,7 @@ GEM
escape_utils (~> 1.1.0)
mime-types (>= 1.19)
rugged (>= 0.23.0b)
- github-markup (1.4.0)
+ github-markup (1.6.1)
gitlab-flowdock-git-hook (1.0.1)
flowdock (~> 0.7)
gitlab-grit (>= 2.4.1)
@@ -303,13 +303,14 @@ GEM
activesupport (>= 4.1.0)
gollum-grit_adapter (1.0.1)
gitlab-grit (~> 2.7, >= 2.7.1)
- gollum-lib (4.2.1)
- github-markup (~> 1.4.0)
+ gollum-lib (4.2.7)
+ gemojione (~> 3.2)
+ github-markup (~> 1.6)
gollum-grit_adapter (~> 1.0)
- nokogiri (~> 1.6.4)
- rouge (~> 2.0)
- sanitize (~> 2.1.0)
- stringex (~> 2.5.1)
+ nokogiri (>= 1.6.1, < 2.0)
+ rouge (~> 2.1)
+ sanitize (~> 2.1)
+ stringex (~> 2.6)
gollum-rugged_adapter (0.4.4)
mime-types (>= 1.15)
rugged (~> 0.25)
@@ -329,7 +330,7 @@ GEM
multi_json (~> 1.10)
retriable (~> 1.4)
signet (~> 0.6)
- google-protobuf (3.3.0)
+ google-protobuf (3.4.0.2)
googleauth (0.5.1)
faraday (~> 0.9)
jwt (~> 1.4)
@@ -468,7 +469,7 @@ GEM
railties (>= 4, < 5.2)
loofah (2.0.3)
nokogiri (>= 1.5.9)
- mail (2.6.5)
+ mail (2.6.6)
mime-types (>= 1.16, < 4)
mail_room (0.9.1)
memoist (0.15.0)
@@ -477,7 +478,7 @@ GEM
method_source (0.8.2)
mime-types (2.99.3)
mimemagic (0.3.0)
- mini_portile2 (2.1.0)
+ mini_portile2 (2.2.0)
minitest (5.7.0)
mmap2 (2.2.7)
mousetrap-rails (1.4.6)
@@ -491,8 +492,8 @@ GEM
net-ldap (0.16.0)
net-ssh (4.1.0)
netrc (0.11.0)
- nokogiri (1.6.8.1)
- mini_portile2 (~> 2.1.0)
+ nokogiri (1.8.0)
+ mini_portile2 (~> 2.2.0)
numerizer (0.1.1)
oauth (0.5.1)
oauth2 (1.4.0)
@@ -515,9 +516,9 @@ GEM
jwt (~> 1.0)
omniauth (~> 1.0)
omniauth-oauth2 (~> 1.1)
- omniauth-cas3 (1.1.3)
+ omniauth-cas3 (1.1.4)
addressable (~> 2.3)
- nokogiri (~> 1.6.6)
+ nokogiri (~> 1.7, >= 1.7.1)
omniauth (~> 1.2)
omniauth-facebook (4.0.0)
omniauth-oauth2 (~> 1.2)
@@ -605,7 +606,7 @@ GEM
cliver (~> 0.3.1)
multi_json (~> 1.0)
websocket-driver (>= 0.2.0)
- posix-spawn (0.3.11)
+ posix-spawn (0.3.13)
powerpack (0.1.1)
premailer (1.10.4)
addressable
@@ -619,7 +620,7 @@ GEM
parser
unparser
procto (0.0.3)
- prometheus-client-mmap (0.7.0.beta12)
+ prometheus-client-mmap (0.7.0.beta14)
mmap2 (~> 2.2, >= 2.2.7)
pry (0.10.4)
coderay (~> 1.1.0)
@@ -769,7 +770,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)
@@ -871,7 +872,7 @@ GEM
state_machines-activerecord (0.4.0)
activerecord (>= 4.1, < 5.1)
state_machines-activemodel (>= 0.3.0)
- stringex (2.5.2)
+ stringex (2.7.1)
sys-filesystem (1.1.6)
ffi
sysexits (1.2.0)
@@ -890,9 +891,9 @@ GEM
timfel-krb5-auth (0.8.3)
toml-rb (0.3.15)
citrus (~> 3.0, > 3.0)
- truncato (0.7.8)
+ truncato (0.7.10)
htmlentities (~> 4.3.1)
- nokogiri (~> 1.6.1)
+ nokogiri (~> 1.8.0, >= 1.7.0)
tzinfo (1.2.3)
thread_safe (~> 0.1)
u2f (0.2.1)
@@ -1014,7 +1015,7 @@ DEPENDENCIES
foreman (~> 0.78.0)
fuubar (~> 2.2.0)
gemnasium-gitlab-service (~> 0.2)
- gemojione (~> 3.0)
+ gemojione (~> 3.3)
gettext (~> 3.2.2)
gettext_i18n_rails (~> 1.8.0)
gettext_i18n_rails_js (~> 1.2.0)
@@ -1060,7 +1061,7 @@ DEPENDENCIES
mysql2 (~> 0.4.5)
net-ldap
net-ssh (~> 4.1.0)
- nokogiri (~> 1.6.7, >= 1.6.7.2)
+ nokogiri (~> 1.8.0)
oauth2 (~> 1.4)
octokit (~> 4.6.2)
oj (~> 2.17.4)
@@ -1068,7 +1069,7 @@ DEPENDENCIES
omniauth-auth0 (~> 1.4.1)
omniauth-authentiq (~> 0.3.1)
omniauth-azure-oauth2 (~> 0.0.6)
- omniauth-cas3 (~> 1.1.2)
+ omniauth-cas3 (~> 1.1.4)
omniauth-facebook (~> 4.0.0)
omniauth-github (~> 1.1.1)
omniauth-gitlab (~> 1.0.2)
@@ -1093,7 +1094,7 @@ DEPENDENCIES
pg (~> 0.18.2)
poltergeist (~> 1.9.0)
premailer-rails (~> 1.9.7)
- prometheus-client-mmap (~> 0.7.0.beta12)
+ prometheus-client-mmap (~> 0.7.0.beta14)
pry-byebug (~> 3.4.1)
pry-rails (~> 0.3.4)
rack-attack (~> 4.4.1)
@@ -1125,7 +1126,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)
@@ -1159,7 +1160,7 @@ DEPENDENCIES
thin (~> 1.7.0)
timecop (~> 0.8.0)
toml-rb (~> 0.3.15)
- truncato (~> 0.7.8)
+ truncato (~> 0.7.9)
u2f (~> 0.2.1)
uglifier (~> 2.7.2)
unf (~> 0.1.4)
@@ -1174,4 +1175,4 @@ DEPENDENCIES
wikicloth (= 0.8.1)
BUNDLED WITH
- 1.15.3
+ 1.15.4
diff --git a/app/assets/javascripts/dispatcher.js b/app/assets/javascripts/dispatcher.js
index feb8735752b..c70a17104fd 100644
--- a/app/assets/javascripts/dispatcher.js
+++ b/app/assets/javascripts/dispatcher.js
@@ -185,13 +185,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/fly_out_nav.js b/app/assets/javascripts/fly_out_nav.js
index 32cb42c8b10..81697af189b 100644
--- a/app/assets/javascripts/fly_out_nav.js
+++ b/app/assets/javascripts/fly_out_nav.js
@@ -1,4 +1,3 @@
-import Cookies from 'js-cookie';
import bp from './breakpoints';
const HIDE_INTERVAL_TIMEOUT = 300;
@@ -8,9 +7,11 @@ const IS_SHOWING_FLY_OUT_CLASS = 'is-showing-fly-out';
let currentOpenMenu = null;
let menuCornerLocs;
let timeoutId;
+let sidebar;
export const mousePos = [];
+export const setSidebar = (el) => { sidebar = el; };
export const setOpenMenu = (menu = null) => { currentOpenMenu = menu; };
export const slope = (a, b) => (b.y - a.y) / (b.x - a.x);
@@ -20,10 +21,8 @@ let headerHeight = 50;
export const getHeaderHeight = () => headerHeight;
export const canShowActiveSubItems = (el) => {
- const isHiddenByMedia = bp.getBreakpointSize() === 'sm' || bp.getBreakpointSize() === 'md';
-
- if (el.classList.contains('active') && !isHiddenByMedia) {
- return Cookies.get('sidebar_collapsed') === 'true';
+ if (el.classList.contains('active') && (sidebar && !sidebar.classList.contains('sidebar-icons-only'))) {
+ return false;
}
return true;
@@ -143,13 +142,13 @@ export const documentMouseMove = (e) => {
};
export default () => {
- const sidebar = document.querySelector('.sidebar-top-level-items');
+ sidebar = document.querySelector('.nav-sidebar');
if (!sidebar) return;
const items = [...sidebar.querySelectorAll('.sidebar-top-level-items > li')];
- sidebar.addEventListener('mouseleave', () => {
+ sidebar.querySelector('.sidebar-top-level-items').addEventListener('mouseleave', () => {
clearTimeout(timeoutId);
timeoutId = setTimeout(() => {
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/issue_show/components/edited.vue b/app/assets/javascripts/issue_show/components/edited.vue
index d59e6d11032..992b7064c13 100644
--- a/app/assets/javascripts/issue_show/components/edited.vue
+++ b/app/assets/javascripts/issue_show/components/edited.vue
@@ -37,7 +37,7 @@ export default {
Edited
<time-ago-tooltip
v-if="updatedAt"
- placement="bottom"
+ tooltip-placement="bottom"
:time="updatedAt"
/>
<span
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.vue b/app/assets/javascripts/monitoring/components/dashboard.vue
index a6a2d3119e3..74244faa5d9 100644
--- a/app/assets/javascripts/monitoring/components/monitoring.vue
+++ b/app/assets/javascripts/monitoring/components/dashboard.vue
@@ -3,8 +3,9 @@
import _ from 'underscore';
import statusCodes from '../../lib/utils/http_status';
import MonitoringService from '../services/monitoring_service';
- import monitoringRow from './monitoring_row.vue';
- import monitoringState from './monitoring_state.vue';
+ import GraphGroup from './graph_group.vue';
+ import GraphRow from './graph_row.vue';
+ import EmptyState from './empty_state.vue';
import MonitoringStore from '../stores/monitoring_store';
import eventHub from '../event_hub';
@@ -31,8 +32,9 @@
},
components: {
- monitoringRow,
- monitoringState,
+ GraphGroup,
+ GraphRow,
+ EmptyState,
},
methods: {
@@ -94,7 +96,6 @@
this.updatedAspectRatios = 0;
}
},
-
},
created() {
@@ -118,40 +119,27 @@
},
};
</script>
+
<template>
- <div
- class="prometheus-graphs"
- v-if="!showEmptyState">
- <div
- class="row"
+ <div v-if="!showEmptyState" class="prometheus-graphs">
+ <graph-group
v-for="(groupData, index) in store.groups"
- :key="index">
- <div
- class="col-md-12">
- <div
- class="panel panel-default prometheus-panel">
- <div
- class="panel-heading">
- <h4>{{groupData.group}}</h4>
- </div>
- <div
- class="panel-body">
- <monitoring-row
- v-for="(row, index) in groupData.metrics"
- :key="index"
- :row-data="row"
- :update-aspect-ratio="updateAspectRatio"
- :deployment-data="store.deploymentData"
- />
- </div>
- </div>
- </div>
- </div>
+ :key="index"
+ :name="groupData.group"
+ >
+ <graph-row
+ v-for="(row, index) in groupData.metrics"
+ :key="index"
+ :row-data="row"
+ :update-aspect-ratio="updateAspectRatio"
+ :deployment-data="store.deploymentData"
+ />
+ </graph-group>
</div>
- <monitoring-state
+ <empty-state
+ v-else
:selected-state="state"
:documentation-path="documentationPath"
:settings-path="settingsPath"
- v-else
/>
</template>
diff --git a/app/assets/javascripts/monitoring/components/monitoring_state.vue b/app/assets/javascripts/monitoring/components/empty_state.vue
index 598021aa4df..a8708be76de 100644
--- a/app/assets/javascripts/monitoring/components/monitoring_state.vue
+++ b/app/assets/javascripts/monitoring/components/empty_state.vue
@@ -62,49 +62,33 @@
},
};
</script>
+
<template>
- <div
- class="prometheus-state">
- <div
- class="row">
- <div
- class="col-md-4 col-md-offset-4 state-svg"
- v-html="currentState.svg">
- </div>
+ <div class="prometheus-state">
+ <div class="row">
+ <div class="col-md-4 col-md-offset-4 state-svg" v-html="currentState.svg"></div>
</div>
- <div
- class="row">
- <div
- class="col-md-6 col-md-offset-3">
- <h4
- class="text-center state-title">
+ <div class="row">
+ <div class="col-md-6 col-md-offset-3">
+ <h4 class="text-center state-title">
{{currentState.title}}
</h4>
</div>
</div>
- <div
- class="row">
- <div
- class="col-md-6 col-md-offset-3">
- <div
- class="description-text text-center state-description">
- {{currentState.description}}
- <a
- :href="settingsPath"
- v-if="showButtonDescription">
- Prometheus server
- </a>
+ <div class="row">
+ <div class="col-md-6 col-md-offset-3">
+ <div class="description-text text-center state-description">
+ {{currentState.description}}
+ <a v-if="showButtonDescription" :href="settingsPath">
+ Prometheus server
+ </a>
</div>
</div>
</div>
- <div
- class="row state-button-section">
- <div
- class="col-md-4 col-md-offset-4 text-center state-button">
- <a
- class="btn btn-success"
- :href="buttonPath">
- {{currentState.buttonText}}
+ <div class="row state-button-section">
+ <div class="col-md-4 col-md-offset-4 text-center state-button">
+ <a class="btn btn-success" :href="buttonPath">
+ {{currentState.buttonText}}
</a>
</div>
</div>
diff --git a/app/assets/javascripts/monitoring/components/monitoring_column.vue b/app/assets/javascripts/monitoring/components/graph.vue
index 407af51cb7a..6f6da9e1463 100644
--- a/app/assets/javascripts/monitoring/components/monitoring_column.vue
+++ b/app/assets/javascripts/monitoring/components/graph.vue
@@ -1,19 +1,20 @@
<script>
import d3 from 'd3';
- import monitoringLegends from './monitoring_legends.vue';
- import monitoringFlag from './monitoring_flag.vue';
- import monitoringDeployment from './monitoring_deployment.vue';
+ import GraphLegend from './graph/legend.vue';
+ import GraphFlag from './graph/flag.vue';
+ import GraphDeployment from './graph/deployment.vue';
import MonitoringMixin from '../mixins/monitoring_mixins';
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;
export default {
props: {
- columnData: {
+ graphData: {
type: Object,
required: true,
},
@@ -65,9 +66,9 @@
},
components: {
- monitoringLegends,
- monitoringFlag,
- monitoringDeployment,
+ GraphLegend,
+ GraphFlag,
+ GraphDeployment,
},
computed: {
@@ -96,7 +97,7 @@
methods: {
draw() {
const breakpointSize = bp.getBreakpointSize();
- const query = this.columnData.queries[0];
+ const query = this.graphData.queries[0];
this.margin = measurements.large.margin;
if (breakpointSize === 'xs' || breakpointSize === 'sm') {
this.graphHeight = 300;
@@ -105,7 +106,7 @@
}
this.data = query.result[0].values;
this.unitOfDisplay = query.unit || '';
- this.yAxisLabel = this.columnData.y_label || 'Values';
+ this.yAxisLabel = this.graphData.y_label || 'Values';
this.legendTitle = query.label || 'Average';
this.graphWidth = this.$refs.baseSvg.clientWidth -
this.margin.left - this.margin.right;
@@ -159,6 +160,7 @@
const xAxis = d3.svg.axis()
.scale(axisXScale)
.ticks(measurements.xTicks)
+ .tickFormat(timeScaleFormat)
.orient('bottom');
const yAxis = d3.svg.axis()
@@ -222,7 +224,7 @@
:class="classType">
<h5
class="text-center graph-title">
- {{columnData.title}}
+ {{graphData.title}}
</h5>
<div
class="prometheus-svg-container"
@@ -238,7 +240,7 @@
class="y-axis"
transform="translate(70, 20)">
</g>
- <monitoring-legends
+ <graph-legend
:graph-width="graphWidth"
:graph-height="graphHeight"
:margin="margin"
@@ -266,21 +268,13 @@
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
+ <graph-deployment
:show-deploy-info="showDeployInfo"
:deployment-data="reducedDeploymentData"
:graph-height="graphHeight"
:graph-height-offset="graphHeightOffset"
/>
- <monitoring-flag
+ <graph-flag
v-if="showFlag"
:current-x-coordinate="currentXCoordinate"
:current-y-coordinate="currentYCoordinate"
@@ -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/graph/deployment.vue
index e6432ba3191..3623d2ed946 100644
--- a/app/assets/javascripts/monitoring/components/monitoring_deployment.vue
+++ b/app/assets/javascripts/monitoring/components/graph/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/graph/flag.vue
index 5a0e50fcab3..c4d4647d240 100644
--- a/app/assets/javascripts/monitoring/components/monitoring_flag.vue
+++ b/app/assets/javascripts/monitoring/components/graph/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/components/monitoring_legends.vue b/app/assets/javascripts/monitoring/components/graph/legend.vue
index 922a5e1bf0e..d08f9cbffd4 100644
--- a/app/assets/javascripts/monitoring/components/monitoring_legends.vue
+++ b/app/assets/javascripts/monitoring/components/graph/legend.vue
@@ -74,7 +74,7 @@
};
</script>
<template>
- <g
+ <g
class="axis-label-container">
<line
class="label-x-axis-line"
@@ -100,7 +100,7 @@
:width="yLabelWidth"
:height="yLabelHeight">
</rect>
- <text
+ <text
class="label-axis-text y-label-text"
text-anchor="middle"
:transform="textTransform"
diff --git a/app/assets/javascripts/monitoring/components/graph_group.vue b/app/assets/javascripts/monitoring/components/graph_group.vue
new file mode 100644
index 00000000000..32c90fda8cc
--- /dev/null
+++ b/app/assets/javascripts/monitoring/components/graph_group.vue
@@ -0,0 +1,21 @@
+<script>
+export default {
+ props: {
+ name: {
+ type: String,
+ required: true,
+ },
+ },
+};
+</script>
+
+<template>
+ <div class="panel panel-default prometheus-panel">
+ <div class="panel-heading">
+ <h4>{{name}}</h4>
+ </div>
+ <div class="panel-body">
+ <slot />
+ </div>
+ </div>
+</template>
diff --git a/app/assets/javascripts/monitoring/components/monitoring_row.vue b/app/assets/javascripts/monitoring/components/graph_row.vue
index e5528f17880..bdb9149c3b4 100644
--- a/app/assets/javascripts/monitoring/components/monitoring_row.vue
+++ b/app/assets/javascripts/monitoring/components/graph_row.vue
@@ -1,5 +1,5 @@
<script>
- import monitoringColumn from './monitoring_column.vue';
+ import Graph from './graph.vue';
export default {
props: {
@@ -17,7 +17,7 @@
},
},
components: {
- monitoringColumn,
+ Graph,
},
computed: {
bootstrapClass() {
@@ -26,12 +26,12 @@
},
};
</script>
+
<template>
- <div
- class="prometheus-row row">
- <monitoring-column
- v-for="(column, index) in rowData"
- :column-data="column"
+ <div class="prometheus-row row">
+ <graph
+ v-for="(graphData, index) in rowData"
+ :graph-data="graphData"
:class-type="bootstrapClass"
:key="index"
:update-aspect-ratio="updateAspectRatio"
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/monitoring_bundle.js b/app/assets/javascripts/monitoring/monitoring_bundle.js
index 5d5cb56af72..ef280e02092 100644
--- a/app/assets/javascripts/monitoring/monitoring_bundle.js
+++ b/app/assets/javascripts/monitoring/monitoring_bundle.js
@@ -1,10 +1,10 @@
import Vue from 'vue';
-import Monitoring from './components/monitoring.vue';
+import Dashboard from './components/dashboard.vue';
document.addEventListener('DOMContentLoaded', () => new Vue({
el: '#prometheus-graphs',
components: {
- 'monitoring-dashboard': Monitoring,
+ Dashboard,
},
- render: createElement => createElement('monitoring-dashboard'),
+ render: createElement => createElement('dashboard'),
}));
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..05e3f33f5ed 100644
--- a/app/assets/javascripts/new_sidebar.js
+++ b/app/assets/javascripts/new_sidebar.js
@@ -15,6 +15,7 @@ export default class NewNavSidebar {
this.$openSidebar = $('.toggle-mobile-nav');
this.$closeSidebar = $('.close-nav-button');
this.$sidebarToggle = $('.js-toggle-sidebar');
+ this.$topLevelLinks = $('.sidebar-top-level-items > li > a');
}
bindEvents() {
@@ -47,10 +48,13 @@ 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);
+
+ this.$topLevelLinks.attr('title', function updateTopLevelTitle() {
+ return collapsed ? this.getAttribute('aria-label') : '';
+ });
}
render() {
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 46a26fb91f4..99cea683d9a 100644
--- a/app/assets/javascripts/project_select_combo_button.js
+++ b/app/assets/javascripts/project_select_combo_button.js
@@ -14,7 +14,14 @@ export default class ProjectSelectComboButton {
bindEvents() {
this.projectSelectInput.siblings('.new-project-item-select-button')
- .on('click', this.openDropdown);
+ .on('click', e => this.openDropdown(e));
+
+ this.newItemBtn.on('click', (e) => {
+ if (!this.getProjectFromLocalStorage()) {
+ e.preventDefault();
+ this.openDropdown(e);
+ }
+ });
this.projectSelectInput.on('change', () => this.selectProject());
}
@@ -28,8 +35,9 @@ export default class ProjectSelectComboButton {
}
}
- openDropdown() {
- $(this).siblings('.project-item-select').select2('open');
+ // eslint-disable-next-line class-methods-use-this
+ openDropdown(event) {
+ $(event.currentTarget).siblings('.project-item-select').select2('open');
}
selectProject() {
@@ -56,10 +64,8 @@ export default class ProjectSelectComboButton {
if (project) {
this.newItemBtn.attr('href', project.url);
this.newItemBtn.text(`${this.formattedText.defaultTextPrefix} in ${project.name}`);
- this.newItemBtn.enable();
} else {
this.newItemBtn.text(`Select project to create ${this.formattedText.presetTextSuffix}`);
- this.newItemBtn.disable();
}
}
diff --git a/app/assets/javascripts/vue_shared/components/commit.vue b/app/assets/javascripts/vue_shared/components/commit.vue
index 262584769e0..50d14282cad 100644
--- a/app/assets/javascripts/vue_shared/components/commit.vue
+++ b/app/assets/javascripts/vue_shared/components/commit.vue
@@ -1,6 +1,7 @@
<script>
import commitIconSvg from 'icons/_icon_commit.svg';
import userAvatarLink from './user_avatar/user_avatar_link.vue';
+ import tooltip from '../directives/tooltip';
export default {
props: {
@@ -100,17 +101,22 @@
this.author.username ? `${this.author.username}'s avatar` : null;
},
},
- data() {
- return { commitIconSvg };
+ directives: {
+ tooltip,
},
components: {
userAvatarLink,
},
+ created() {
+ this.commitIconSvg = commitIconSvg;
+ },
};
</script>
<template>
<div class="branch-commit">
- <div v-if="hasCommitRef" class="icon-container hidden-xs">
+ <div
+ v-if="hasCommitRef"
+ class="icon-container hidden-xs">
<i
v-if="tag"
class="fa fa-tag"
@@ -126,7 +132,10 @@
<a
v-if="hasCommitRef"
class="ref-name hidden-xs"
- :href="commitRef.ref_url">
+ :href="commitRef.ref_url"
+ v-tooltip
+ data-container="body"
+ :title="commitRef.name">
{{commitRef.name}}
</a>
@@ -153,7 +162,8 @@
:img-alt="userImageAltDescription"
:tooltip-text="author.username"
/>
- <a class="commit-row-message"
+ <a
+ class="commit-row-message"
:href="commitUrl">
{{title}}
</a>
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/stylesheets/framework/dropdowns.scss b/app/assets/stylesheets/framework/dropdowns.scss
index a45d5a6dca0..5871383a57b 100644
--- a/app/assets/stylesheets/framework/dropdowns.scss
+++ b/app/assets/stylesheets/framework/dropdowns.scss
@@ -189,7 +189,7 @@
width: auto;
top: 100%;
left: 0;
- z-index: 9;
+ z-index: 200;
min-width: 240px;
max-width: 500px;
margin-top: 2px;
@@ -771,6 +771,11 @@
&::before {
top: 16px;
}
+
+ &.dropdown-menu-user-link::before {
+ top: 50%;
+ transform: translateY(-50%);
+ }
}
}
}
@@ -792,3 +797,5 @@
margin-top: 2px;
}
}
+
+@include new-style-dropdown('.js-namespace-select + ');
diff --git a/app/assets/stylesheets/framework/filters.scss b/app/assets/stylesheets/framework/filters.scss
index a5d33d410fb..b2847c348eb 100644
--- a/app/assets/stylesheets/framework/filters.scss
+++ b/app/assets/stylesheets/framework/filters.scss
@@ -225,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;
@@ -277,7 +289,7 @@
}
.filtered-search-input-dropdown-menu {
- max-height: 225px;
+ max-height: 260px;
max-width: 280px;
overflow: auto;
@@ -478,3 +490,7 @@
padding: 8px 16px;
text-align: center;
}
+
+.issues-details-filters {
+ @include new-style-dropdown;
+}
diff --git a/app/assets/stylesheets/framework/selects.scss b/app/assets/stylesheets/framework/selects.scss
index d93722e2174..a39927eb0df 100644
--- a/app/assets/stylesheets/framework/selects.scss
+++ b/app/assets/stylesheets/framework/selects.scss
@@ -266,7 +266,11 @@
}
// TODO: change global style
-.ajax-project-dropdown {
+.ajax-project-dropdown,
+body[data-page="projects:new"] #select2-drop,
+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;
}
diff --git a/app/assets/stylesheets/framework/typography.scss b/app/assets/stylesheets/framework/typography.scss
index 71eec0e1a5e..3c0b4c82d19 100644
--- a/app/assets/stylesheets/framework/typography.scss
+++ b/app/assets/stylesheets/framework/typography.scss
@@ -10,8 +10,7 @@
color: $md-link-color;
}
- img {
- /*max-width: 100%;*/
+ img:not(.emoji) {
margin: 0 0 8px;
}
@@ -26,6 +25,7 @@
min-width: inherit;
min-height: inherit;
background-color: inherit;
+ max-width: 100%;
}
p a:not(.no-attachment-icon) img {
diff --git a/app/assets/stylesheets/framework/variables.scss b/app/assets/stylesheets/framework/variables.scss
index 8a2e64f7bf5..26920869bec 100644
--- a/app/assets/stylesheets/framework/variables.scss
+++ b/app/assets/stylesheets/framework/variables.scss
@@ -120,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;
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/members.scss b/app/assets/stylesheets/pages/members.scss
index a385eb359e1..3fb02e9964f 100644
--- a/app/assets/stylesheets/pages/members.scss
+++ b/app/assets/stylesheets/pages/members.scss
@@ -96,6 +96,8 @@
}
.member-search-form {
+ @include new-style-dropdown;
+
position: relative;
@media (min-width: $screen-sm-min) {
diff --git a/app/assets/stylesheets/pages/merge_requests.scss b/app/assets/stylesheets/pages/merge_requests.scss
index d1678a17aaf..9d51c0b7a8a 100644
--- a/app/assets/stylesheets/pages/merge_requests.scss
+++ b/app/assets/stylesheets/pages/merge_requests.scss
@@ -489,6 +489,8 @@
}
.mr-source-target {
+ @include new-style-dropdown;
+
display: flex;
flex-wrap: wrap;
justify-content: space-between;
@@ -610,6 +612,8 @@
}
.mr-version-controls {
+ @include new-style-dropdown;
+
position: relative;
background: $gray-light;
color: $gl-text-color;
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/pipelines.scss b/app/assets/stylesheets/pages/pipelines.scss
index a408bde37d6..51656669c98 100644
--- a/app/assets/stylesheets/pages/pipelines.scss
+++ b/app/assets/stylesheets/pages/pipelines.scss
@@ -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/repo.scss b/app/assets/stylesheets/pages/repo.scss
index 1088eca5322..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 {
diff --git a/app/assets/stylesheets/pages/todos.scss b/app/assets/stylesheets/pages/todos.scss
index 5b9fafe31bd..6c8d87185e9 100644
--- a/app/assets/stylesheets/pages/todos.scss
+++ b/app/assets/stylesheets/pages/todos.scss
@@ -265,3 +265,7 @@
font-weight: $gl-font-weight-bold;
}
}
+
+.todos-filters {
+ @include new-style-dropdown;
+}
diff --git a/app/controllers/admin/users_controller.rb b/app/controllers/admin/users_controller.rb
index fa1bc72560e..a99563b7100 100644
--- a/app/controllers/admin/users_controller.rb
+++ b/app/controllers/admin/users_controller.rb
@@ -117,11 +117,14 @@ class Admin::UsersController < Admin::ApplicationController
user_params_with_pass = user_params.dup
if params[:user][:password].present?
- user_params_with_pass.merge!(
+ password_params = {
password: params[:user][:password],
- password_confirmation: params[:user][:password_confirmation],
- password_expires_at: Time.now
- )
+ password_confirmation: params[:user][:password_confirmation]
+ }
+
+ password_params[:password_expires_at] = Time.now unless changing_own_password?
+
+ user_params_with_pass.merge!(password_params)
end
respond_to do |format|
@@ -167,6 +170,10 @@ class Admin::UsersController < Admin::ApplicationController
protected
+ def changing_own_password?
+ user == current_user
+ end
+
def user
@user ||= User.find_by!(username: params[:id])
end
diff --git a/app/controllers/autocomplete_controller.rb b/app/controllers/autocomplete_controller.rb
index 3120916c5bb..59be955599d 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_all 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/concerns/requires_whitelisted_monitoring_client.rb b/app/controllers/concerns/requires_whitelisted_monitoring_client.rb
index ad2f4bbc486..0218ac83441 100644
--- a/app/controllers/concerns/requires_whitelisted_monitoring_client.rb
+++ b/app/controllers/concerns/requires_whitelisted_monitoring_client.rb
@@ -1,5 +1,8 @@
module RequiresWhitelistedMonitoringClient
extend ActiveSupport::Concern
+
+ include Gitlab::CurrentSettings
+
included do
before_action :validate_ip_whitelisted_or_valid_token!
end
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/projects/application_controller.rb b/app/controllers/projects/application_controller.rb
index 221e01b415a..d7dd8ddcb7d 100644
--- a/app/controllers/projects/application_controller.rb
+++ b/app/controllers/projects/application_controller.rb
@@ -94,6 +94,6 @@ class Projects::ApplicationController < ApplicationController
end
def require_pages_enabled!
- not_found unless Gitlab.config.pages.enabled
+ not_found unless @project.pages_available?
end
end
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/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/helpers/application_helper.rb b/app/helpers/application_helper.rb
index bcee81bdc15..36bb7015fa1 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 ')
@@ -202,7 +202,7 @@ module ApplicationHelper
end
def support_url
- current_application_settings.help_page_support_url.presence || promo_url + '/getting-help/'
+ Gitlab::CurrentSettings.current_application_settings.help_page_support_url.presence || promo_url + '/getting-help/'
end
def page_filter_path(options = {})
diff --git a/app/helpers/application_settings_helper.rb b/app/helpers/application_settings_helper.rb
index 3b76da238e0..04955ed625e 100644
--- a/app/helpers/application_settings_helper.rb
+++ b/app/helpers/application_settings_helper.rb
@@ -1,5 +1,8 @@
module ApplicationSettingsHelper
extend self
+
+ include Gitlab::CurrentSettings
+
delegate :gravatar_enabled?,
:signup_enabled?,
:password_authentication_enabled?,
diff --git a/app/helpers/auth_helper.rb b/app/helpers/auth_helper.rb
index 9c71d6c7f4c..66dc0b1e6f7 100644
--- a/app/helpers/auth_helper.rb
+++ b/app/helpers/auth_helper.rb
@@ -1,4 +1,6 @@
module AuthHelper
+ include Gitlab::CurrentSettings
+
PROVIDERS_WITH_ICONS = %w(twitter github gitlab bitbucket google_oauth2 facebook azure_oauth2 authentiq).freeze
FORM_BASED_PROVIDERS = [/\Aldap/, 'crowd'].freeze
diff --git a/app/helpers/issuables_helper.rb b/app/helpers/issuables_helper.rb
index 197c90c4081..2a748ce0a75 100644
--- a/app/helpers/issuables_helper.rb
+++ b/app/helpers/issuables_helper.rb
@@ -229,7 +229,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/helpers/projects_helper.rb b/app/helpers/projects_helper.rb
index bee4950e414..c5490a2d1a8 100644
--- a/app/helpers/projects_helper.rb
+++ b/app/helpers/projects_helper.rb
@@ -1,4 +1,6 @@
module ProjectsHelper
+ include Gitlab::CurrentSettings
+
def link_to_project(project)
link_to [project.namespace.becomes(Namespace), project], title: h(project.name) do
title = content_tag(:span, project.name, class: 'project-name')
diff --git a/app/helpers/tab_helper.rb b/app/helpers/tab_helper.rb
index ee701076a14..3308ab0c259 100644
--- a/app/helpers/tab_helper.rb
+++ b/app/helpers/tab_helper.rb
@@ -119,4 +119,8 @@ module TabHelper
'active' if current_controller?('oauth/applications')
end
+
+ def sidebar_link(href, title: nil, css: nil, &block)
+ link_to capture(&block), href, title: (title if collapsed_sidebar?), class: css, aria: { label: title }
+ end
end
diff --git a/app/mailers/base_mailer.rb b/app/mailers/base_mailer.rb
index 654468bc7fe..8e99db444d6 100644
--- a/app/mailers/base_mailer.rb
+++ b/app/mailers/base_mailer.rb
@@ -1,11 +1,13 @@
class BaseMailer < ActionMailer::Base
+ include Gitlab::CurrentSettings
+
around_action :render_with_default_locale
helper ApplicationHelper
helper MarkupHelper
attr_accessor :current_user
- helper_method :current_user, :can?
+ helper_method :current_user, :can?, :current_application_settings
default from: proc { default_sender_address.format }
default reply_to: proc { default_reply_to_address.format }
diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb
index 095192e9894..8adaafe6439 100644
--- a/app/models/ci/build.rb
+++ b/app/models/ci/build.rb
@@ -387,7 +387,9 @@ module Ci
[
{ key: 'GITLAB_USER_ID', value: user.id.to_s, public: true },
- { key: 'GITLAB_USER_EMAIL', value: user.email, public: true }
+ { key: 'GITLAB_USER_EMAIL', value: user.email, public: true },
+ { key: 'GITLAB_USER_LOGIN', value: user.username, public: true },
+ { key: 'GITLAB_USER_NAME', value: user.name, public: true }
]
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/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/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/spammable.rb b/app/models/concerns/spammable.rb
index f2707022a4b..731d9b9a745 100644
--- a/app/models/concerns/spammable.rb
+++ b/app/models/concerns/spammable.rb
@@ -28,7 +28,7 @@ module Spammable
def submittable_as_spam?
if user_agent_detail
- user_agent_detail.submittable? && current_application_settings.akismet_enabled
+ user_agent_detail.submittable? && Gitlab::CurrentSettings.current_application_settings.akismet_enabled
else
false
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/environment.rb b/app/models/environment.rb
index e9ebf0637f3..435eeaf0e2e 100644
--- a/app/models/environment.rb
+++ b/app/models/environment.rb
@@ -114,7 +114,7 @@ class Environment < ActiveRecord::Base
end
def ref_path
- "refs/environments/#{Shellwords.shellescape(name)}"
+ "refs/#{Repository::REF_ENVIRONMENTS}/#{Shellwords.shellescape(name)}"
end
def formatted_external_url
diff --git a/app/models/group.rb b/app/models/group.rb
index 3778b832a47..190b27cf66b 100644
--- a/app/models/group.rb
+++ b/app/models/group.rb
@@ -217,9 +217,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 b9aa937d2f9..dfcd4030ec3 100644
--- a/app/models/issue.rb
+++ b/app/models/issue.rb
@@ -269,7 +269,13 @@ class Issue < ActiveRecord::Base
end
end
+ def update_project_counter_caches?
+ state_changed? || confidential_changed?
+ end
+
def update_project_counter_caches
+ return unless update_project_counter_caches?
+
Projects::OpenIssuesCountService.new(project).refresh_cache
end
diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb
index dbc73ed3cd4..ca3a1806ee8 100644
--- a/app/models/merge_request.rb
+++ b/app/models/merge_request.rb
@@ -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?
@@ -797,7 +803,7 @@ class MergeRequest < ActiveRecord::Base
end
def ref_path
- "refs/merge-requests/#{iid}/head"
+ "refs/#{Repository::REF_MERGE_REQUEST}/#{iid}/head"
end
def ref_fetched?
@@ -819,7 +825,7 @@ class MergeRequest < ActiveRecord::Base
lock_mr
yield
ensure
- unlock_mr if locked?
+ unlock_mr
end
end
@@ -936,7 +942,13 @@ class MergeRequest < ActiveRecord::Base
true
end
+ def update_project_counter_caches?
+ state_changed?
+ end
+
def update_project_counter_caches
+ return unless update_project_counter_caches?
+
Projects::OpenMergeRequestsCountService.new(target_project).refresh_cache
end
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/namespace.rb b/app/models/namespace.rb
index e7bc1d1b080..e7cbc5170e8 100644
--- a/app/models/namespace.rb
+++ b/app/models/namespace.rb
@@ -195,6 +195,10 @@ class Namespace < ActiveRecord::Base
parent.present?
end
+ def subgroup?
+ has_parent?
+ end
+
def soft_delete_without_removing_associations
# We can't use paranoia's `#destroy` since this will hard-delete projects.
# Project uses `pending_delete` instead of the acts_as_paranoia gem.
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 d5324ceac31..5b4904a5c51 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -19,6 +19,7 @@ class Project < ActiveRecord::Base
include Routable
extend Gitlab::ConfigHelper
+ extend Gitlab::CurrentSettings
BoardLimitExceeded = Class.new(StandardError)
@@ -372,11 +373,7 @@ class Project < ActiveRecord::Base
if Gitlab::ImportSources.importer_names.include?(project.import_type) && project.repo_exists?
project.run_after_commit do
- begin
- Projects::HousekeepingService.new(project).execute
- rescue Projects::HousekeepingService::LeaseTaken => e
- Rails.logger.info("Could not perform housekeeping for project #{project.full_path} (#{project.id}): #{e}")
- end
+ Projects::AfterImportService.new(project).execute
end
end
end
@@ -1235,6 +1232,10 @@ class Project < ActiveRecord::Base
File.join(pages_path, 'public')
end
+ def pages_available?
+ Gitlab.config.pages.enabled && !namespace.subgroup?
+ end
+
def remove_private_deploy_keys
exclude_keys_linked_to_other_projects = <<-SQL
NOT EXISTS (
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/protected_branch.rb b/app/models/protected_branch.rb
index 5f0d0802ac9..89bfc5f9a9c 100644
--- a/app/models/protected_branch.rb
+++ b/app/models/protected_branch.rb
@@ -2,6 +2,8 @@ class ProtectedBranch < ActiveRecord::Base
include Gitlab::ShellAdapter
include ProtectedRef
+ extend Gitlab::CurrentSettings
+
protected_ref_access_levels :merge, :push
# Check if branch name is marked as protected in the system
diff --git a/app/models/repository.rb b/app/models/repository.rb
index 9fb2e2aa306..b3fa51a14f7 100644
--- a/app/models/repository.rb
+++ b/app/models/repository.rb
@@ -1,6 +1,18 @@
require 'securerandom'
class Repository
+ REF_MERGE_REQUEST = 'merge-requests'.freeze
+ REF_KEEP_AROUND = 'keep-around'.freeze
+ REF_ENVIRONMENTS = 'environments'.freeze
+
+ RESERVED_REFS_NAMES = %W[
+ heads
+ tags
+ #{REF_ENVIRONMENTS}
+ #{REF_KEEP_AROUND}
+ #{REF_ENVIRONMENTS}
+ ].freeze
+
include Gitlab::ShellAdapter
include RepositoryMirroring
@@ -60,6 +72,10 @@ class Repository
@project = project
end
+ def ==(other)
+ @disk_path == other.disk_path
+ end
+
def raw_repository
return nil unless full_path
@@ -75,6 +91,10 @@ class Repository
)
end
+ def inspect
+ "#<#{self.class.name}:#{@disk_path}>"
+ end
+
#
# Git repository can contains some hidden refs like:
# /refs/notes/*
@@ -234,10 +254,10 @@ class Repository
begin
write_ref(keep_around_ref_name(sha), sha)
rescue Rugged::ReferenceError => ex
- Rails.logger.error "Unable to create keep-around reference for repository #{path}: #{ex}"
+ Rails.logger.error "Unable to create #{REF_KEEP_AROUND} reference for repository #{path}: #{ex}"
rescue Rugged::OSError => ex
raise unless ex.message =~ /Failed to create locked file/ && ex.message =~ /File exists/
- Rails.logger.error "Unable to create keep-around reference for repository #{path}: #{ex}"
+ Rails.logger.error "Unable to create #{REF_KEEP_AROUND} reference for repository #{path}: #{ex}"
end
end
@@ -944,7 +964,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
@@ -958,12 +978,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
@@ -992,25 +1012,22 @@ class Repository
end
def with_repo_branch_commit(start_repository, start_branch_name)
- return yield(nil) if start_repository.empty_repo?
+ return yield nil if start_repository.empty_repo?
- branch_name_or_sha =
- if start_repository == self
- start_branch_name
- else
- tmp_ref = fetch_ref(
- start_repository.path_to_repo,
- "#{Gitlab::Git::BRANCH_REF_PREFIX}#{start_branch_name}",
- "refs/tmp/#{SecureRandom.hex}/head"
- )
+ if start_repository == self
+ yield commit(start_branch_name)
+ else
+ sha = start_repository.commit(start_branch_name).sha
- start_repository.commit(start_branch_name).sha
+ if branch_commit = commit(sha)
+ yield branch_commit
+ else
+ with_repo_tmp_commit(
+ start_repository, start_branch_name, sha) do |tmp_commit|
+ yield tmp_commit
+ end
end
-
- yield(commit(branch_name_or_sha))
-
- ensure
- rugged.references.delete(tmp_ref) if tmp_ref
+ end
end
def add_remote(name, url)
@@ -1027,7 +1044,7 @@ class Repository
end
def fetch_remote(remote, forced: false, no_tags: false)
- gitlab_shell.fetch_remote(repository_storage_path, disk_path, remote, forced: forced, no_tags: no_tags)
+ gitlab_shell.fetch_remote(raw_repository, remote, forced: forced, no_tags: no_tags)
end
def fetch_ref(source_path, source_ref, target_ref)
@@ -1159,7 +1176,7 @@ class Repository
end
def keep_around_ref_name(sha)
- "refs/keep-around/#{sha}"
+ "refs/#{REF_KEEP_AROUND}/#{sha}"
end
def repository_event(event, tags = {})
@@ -1219,4 +1236,16 @@ class Repository
.commits_by_message(query, revision: ref, path: path, limit: limit, offset: offset)
.map { |c| commit(c) }
end
+
+ def with_repo_tmp_commit(start_repository, start_branch_name, sha)
+ tmp_ref = fetch_ref(
+ start_repository.path_to_repo,
+ "#{Gitlab::Git::BRANCH_REF_PREFIX}#{start_branch_name}",
+ "refs/tmp/#{SecureRandom.hex}/head"
+ )
+
+ yield commit(sha)
+ ensure
+ delete_refs(tmp_ref) if tmp_ref
+ end
end
diff --git a/app/models/snippet.rb b/app/models/snippet.rb
index 09d5ff46618..9533aa7f555 100644
--- a/app/models/snippet.rb
+++ b/app/models/snippet.rb
@@ -10,6 +10,8 @@ class Snippet < ActiveRecord::Base
include Spammable
include Editable
+ extend Gitlab::CurrentSettings
+
cache_markdown_field :title, pipeline: :single_line
cache_markdown_field :description
cache_markdown_field :content
diff --git a/app/models/user.rb b/app/models/user.rb
index fbd08bc4d0a..78e7c750c3b 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -2,9 +2,11 @@ require 'carrierwave/orm/activerecord'
class User < ActiveRecord::Base
extend Gitlab::ConfigHelper
+ extend Gitlab::CurrentSettings
include Gitlab::ConfigHelper
include Gitlab::CurrentSettings
+ include Gitlab::SQL::Pattern
include Avatarable
include Referable
include Sortable
@@ -303,7 +305,7 @@ class User < ActiveRecord::Base
# Returns an ActiveRecord::Relation.
def search(query)
table = arel_table
- pattern = "%#{query}%"
+ pattern = User.to_pattern(query)
order = <<~SQL
CASE
diff --git a/app/policies/base_policy.rb b/app/policies/base_policy.rb
index a605a3457c8..8fa7b2753c7 100644
--- a/app/policies/base_policy.rb
+++ b/app/policies/base_policy.rb
@@ -1,8 +1,6 @@
require_dependency 'declarative_policy'
class BasePolicy < DeclarativePolicy::Base
- include Gitlab::CurrentSettings
-
desc "User is an instance admin"
with_options scope: :user, score: 0
condition(:admin) { @user&.admin? }
@@ -15,6 +13,6 @@ class BasePolicy < DeclarativePolicy::Base
desc "The application is restricted from public visibility"
condition(:restricted_public_level, scope: :global) do
- current_application_settings.restricted_visibility_levels.include?(Gitlab::VisibilityLevel::PUBLIC)
+ Gitlab::CurrentSettings.current_application_settings.restricted_visibility_levels.include?(Gitlab::VisibilityLevel::PUBLIC)
end
end
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..aa6f0e841c9 100644
--- a/app/services/akismet_service.rb
+++ b/app/services/akismet_service.rb
@@ -1,4 +1,6 @@
class AkismetService
+ include Gitlab::CurrentSettings
+
attr_accessor :owner, :text, :options
def initialize(owner, text, options = {})
@@ -7,7 +9,7 @@ class AkismetService
@options = options
end
- def is_spam?
+ def spam?
return false unless akismet_enabled?
params = {
diff --git a/app/services/auth/container_registry_authentication_service.rb b/app/services/auth/container_registry_authentication_service.rb
index 7dae5880931..9a636346899 100644
--- a/app/services/auth/container_registry_authentication_service.rb
+++ b/app/services/auth/container_registry_authentication_service.rb
@@ -1,6 +1,6 @@
module Auth
class ContainerRegistryAuthenticationService < BaseService
- include Gitlab::CurrentSettings
+ extend Gitlab::CurrentSettings
AUDIENCE = 'container_registry'.freeze
diff --git a/app/services/ci/create_pipeline_service.rb b/app/services/ci/create_pipeline_service.rb
index d0ba9f89460..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)
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/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/merge_requests/merge_service.rb b/app/services/merge_requests/merge_service.rb
index 5be749cd6a0..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
@@ -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/after_import_service.rb b/app/services/projects/after_import_service.rb
new file mode 100644
index 00000000000..e6a68d983ef
--- /dev/null
+++ b/app/services/projects/after_import_service.rb
@@ -0,0 +1,29 @@
+module Projects
+ class AfterImportService
+ RESERVED_REFS_REGEXP =
+ %r{\Arefs/(?:#{Regexp.union(*Repository::RESERVED_REFS_NAMES)})/}
+
+ def initialize(project)
+ @project = project
+ end
+
+ def execute
+ Projects::HousekeepingService.new(@project).execute do
+ repository.delete_refs(*garbage_refs)
+ end
+ rescue Projects::HousekeepingService::LeaseTaken => e
+ Rails.logger.info(
+ "Could not perform housekeeping for project #{@project.full_path} (#{@project.id}): #{e}")
+ end
+
+ private
+
+ def garbage_refs
+ @garbage_refs ||= repository.all_ref_names_except(RESERVED_REFS_REGEXP)
+ end
+
+ def repository
+ @repository ||= @project.repository
+ 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/housekeeping_service.rb b/app/services/projects/housekeeping_service.rb
index d66ef676088..dcef8b66215 100644
--- a/app/services/projects/housekeeping_service.rb
+++ b/app/services/projects/housekeeping_service.rb
@@ -26,6 +26,8 @@ module Projects
lease_uuid = try_obtain_lease
raise LeaseTaken unless lease_uuid.present?
+ yield if block_given?
+
execute_gitlab_shell_gc(lease_uuid)
end
diff --git a/app/services/projects/update_pages_service.rb b/app/services/projects/update_pages_service.rb
index 394b336a638..f6b83a2f621 100644
--- a/app/services/projects/update_pages_service.rb
+++ b/app/services/projects/update_pages_service.rb
@@ -1,5 +1,7 @@
module Projects
class UpdatePagesService < BaseService
+ include Gitlab::CurrentSettings
+
BLOCK_SIZE = 32.kilobytes
MAX_SIZE = 1.terabyte
SITE_PATH = 'public/'.freeze
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/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/upload_service.rb b/app/services/upload_service.rb
index 6c5b2baff41..76700dfcdee 100644
--- a/app/services/upload_service.rb
+++ b/app/services/upload_service.rb
@@ -1,4 +1,6 @@
class UploadService
+ include Gitlab::CurrentSettings
+
def initialize(model, file, uploader_class = FileUploader)
@model, @file, @uploader_class = model, file, uploader_class
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/build_service.rb b/app/services/users/build_service.rb
index ff234a3440f..6f05500adea 100644
--- a/app/services/users/build_service.rb
+++ b/app/services/users/build_service.rb
@@ -1,5 +1,7 @@
module Users
class BuildService < BaseService
+ include Gitlab::CurrentSettings
+
def initialize(current_user, params = {})
@current_user = current_user
@params = params.dup
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/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/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/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/groups/merge_requests.html.haml b/app/views/groups/merge_requests.html.haml
index 569eef46e6e..184df6f5406 100644
--- a/app/views/groups/merge_requests.html.haml
+++ b/app/views/groups/merge_requests.html.haml
@@ -1,5 +1,9 @@
- 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", type: :merge_requests
@@ -13,7 +17,7 @@
.nav-controls{ class: ("visible-xs" if show_new_nav?) }
= 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/layouts/nav/_breadcrumbs.html.haml b/app/views/layouts/nav/_breadcrumbs.html.haml
index 4db84771f4e..653452871a0 100644
--- a/app/views/layouts/nav/_breadcrumbs.html.haml
+++ b/app/views/layouts/nav/_breadcrumbs.html.haml
@@ -1,8 +1,9 @@
- breadcrumb_link = breadcrumb_title_link
+- container = @no_breadcrumb_container ? 'container-fluid' : container_class
- hide_top_links = @hide_top_links || false
%nav.breadcrumbs{ role: "navigation" }
- .breadcrumbs-container{ class: [container_class, @content_class] }
+ .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 1c3fd4a082c..3b53117deb6 100644
--- a/app/views/layouts/nav/_new_admin_sidebar.html.haml
+++ b/app/views/layouts/nav/_new_admin_sidebar.html.haml
@@ -7,7 +7,7 @@
.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
+ = sidebar_link admin_root_path, title: _('Overview'), css: 'shortcuts-tree' do
.nav-icon-container
= custom_icon('overview')
%span.nav-item-name
@@ -42,19 +42,19 @@
= 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
+ = sidebar_link admin_conversational_development_index_path, title: _('Monitoring') do
.nav-icon-container
= custom_icon('monitoring')
%span.nav-item-name
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
@@ -77,27 +77,28 @@
Requests Profiles
= nav_link(controller: :broadcast_messages) do
- = link_to admin_broadcast_messages_path, title: 'Messages' do
+ = sidebar_link admin_broadcast_messages_path, title: _('Messages') do
.nav-icon-container
= custom_icon('messages')
%span.nav-item-name
Messages
+
= nav_link(controller: [:hooks, :hook_logs]) do
- = link_to admin_hooks_path, title: 'Hooks' do
+ = sidebar_link admin_hooks_path, title: _('Hooks') do
.nav-icon-container
= custom_icon('system_hooks')
%span.nav-item-name
System Hooks
= nav_link(controller: :applications) do
- = link_to admin_applications_path, title: 'Applications' do
+ = sidebar_link admin_applications_path, title: _('Applications') do
.nav-icon-container
= custom_icon('applications')
%span.nav-item-name
Applications
= nav_link(controller: :abuse_reports) do
- = link_to admin_abuse_reports_path, title: "Abuse Reports" do
+ = sidebar_link admin_abuse_reports_path, title: _("Abuse Reports") do
.nav-icon-container
= custom_icon('abuse_reports')
%span.nav-item-name
@@ -106,43 +107,42 @@
- if akismet_enabled?
= nav_link(controller: :spam_logs) do
- = link_to admin_spam_logs_path, title: "Spam Logs" do
+ = sidebar_link admin_spam_logs_path, title: _("Spam Logs") do
.nav-icon-container
= custom_icon('spam_logs')
%span.nav-item-name
Spam Logs
= nav_link(controller: :deploy_keys) do
- = link_to admin_deploy_keys_path, title: 'Deploy Keys' do
+ = sidebar_link admin_deploy_keys_path, title: _('Deploy Keys') do
.nav-icon-container
= custom_icon('key')
%span.nav-item-name
Deploy Keys
= nav_link(controller: :services) do
- = link_to admin_application_settings_services_path, title: 'Service Templates' do
+ = sidebar_link admin_application_settings_services_path, title: _('Service Templates') do
.nav-icon-container
= custom_icon('service_templates')
%span.nav-item-name
Service Templates
= nav_link(controller: :labels) do
- = link_to admin_labels_path, title: 'Labels' do
+ = sidebar_link admin_labels_path, title: _('Labels') do
.nav-icon-container
= custom_icon('labels')
%span.nav-item-name
Labels
= nav_link(controller: :appearances) do
- = link_to admin_appearances_path, title: 'Appearances' do
+ = sidebar_link admin_appearances_path, title: _('Appearances') do
.nav-icon-container
= custom_icon('appearance')
%span.nav-item-name
Appearance
- %li.divider
= nav_link(controller: :application_settings) do
- = link_to admin_application_settings_path, title: 'Settings' do
+ = sidebar_link admin_application_settings_path, title: _('Settings') do
.nav-icon-container
= custom_icon('settings')
%span.nav-item-name
diff --git a/app/views/layouts/nav/_new_group_sidebar.html.haml b/app/views/layouts/nav/_new_group_sidebar.html.haml
index d90aea2e361..5a1511b262f 100644
--- a/app/views/layouts/nav/_new_group_sidebar.html.haml
+++ b/app/views/layouts/nav/_new_group_sidebar.html.haml
@@ -8,7 +8,7 @@
= @group.name
%ul.sidebar-top-level-items
= nav_link(path: ['groups#show', 'groups#activity', 'groups#subgroups'], html_options: { class: 'home' }) do
- = link_to group_path(@group), title: 'Group overview' do
+ = sidebar_link group_path(@group), title: _('Group overview') do
.nav-icon-container
= custom_icon('project')
%span.nav-item-name
@@ -26,7 +26,7 @@
Activity
= nav_link(path: ['groups#issues', 'labels#index', 'milestones#index']) do
- = link_to issues_group_path(@group), title: 'Issues' do
+ = sidebar_link issues_group_path(@group), title: _('Issues') do
.nav-icon-container
= custom_icon('issues')
%span.nav-item-name
@@ -51,7 +51,7 @@
Milestones
= nav_link(path: 'groups#merge_requests') do
- = link_to merge_requests_group_path(@group), title: 'Merge Requests' do
+ = sidebar_link merge_requests_group_path(@group), title: _('Merge Requests') do
.nav-icon-container
= custom_icon('mr_bold')
%span.nav-item-name
@@ -59,14 +59,14 @@
Merge Requests
%span.badge.count= number_with_delimiter(merge_requests.count)
= nav_link(path: 'group_members#index') do
- = link_to group_group_members_path(@group), title: 'Members' do
+ = sidebar_link group_group_members_path(@group), title: _('Members') do
.nav-icon-container
= custom_icon('members')
%span.nav-item-name
Members
- if current_user && can?(current_user, :admin_group, @group)
= nav_link(path: %w[groups#projects groups#edit ci_cd#show]) do
- = link_to edit_group_path(@group), title: 'Settings' do
+ = sidebar_link edit_group_path(@group), title: _('Settings') do
.nav-icon-container
= custom_icon('settings')
%span.nav-item-name
diff --git a/app/views/layouts/nav/_new_profile_sidebar.html.haml b/app/views/layouts/nav/_new_profile_sidebar.html.haml
index 85b2c7630c8..ccb6d1492f1 100644
--- a/app/views/layouts/nav/_new_profile_sidebar.html.haml
+++ b/app/views/layouts/nav/_new_profile_sidebar.html.haml
@@ -7,76 +7,76 @@
.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
+ = sidebar_link profile_path, title: _('Profile Settings') do
.nav-icon-container
= custom_icon('profile')
%span.nav-item-name
Profile
= nav_link(controller: [:accounts, :two_factor_auths]) do
- = link_to profile_account_path, title: 'Account' do
+ = sidebar_link profile_account_path, title: _('Account') do
.nav-icon-container
= custom_icon('account')
%span.nav-item-name
Account
- if current_application_settings.user_oauth_applications?
= nav_link(controller: 'oauth/applications') do
- = link_to applications_profile_path, title: 'Applications' do
+ = sidebar_link applications_profile_path, title: _('Applications') do
.nav-icon-container
= custom_icon('applications')
%span.nav-item-name
Applications
= nav_link(controller: :chat_names) do
- = link_to profile_chat_names_path, title: 'Chat' do
+ = sidebar_link profile_chat_names_path, title: _('Chat') do
.nav-icon-container
= custom_icon('chat')
%span.nav-item-name
Chat
= nav_link(controller: :personal_access_tokens) do
- = link_to profile_personal_access_tokens_path, title: 'Access Tokens' do
+ = sidebar_link profile_personal_access_tokens_path, title: _('Access Tokens') do
.nav-icon-container
= custom_icon('access_tokens')
%span.nav-item-name
Access Tokens
= nav_link(controller: :emails) do
- = link_to profile_emails_path, title: 'Emails' do
+ = sidebar_link profile_emails_path, title: _('Emails') do
.nav-icon-container
= custom_icon('emails')
%span.nav-item-name
Emails
- unless current_user.ldap_user?
= nav_link(controller: :passwords) do
- = link_to edit_profile_password_path, title: 'Password' do
+ = sidebar_link edit_profile_password_path, title: _('Password') do
.nav-icon-container
= custom_icon('lock')
%span.nav-item-name
Password
= nav_link(controller: :notifications) do
- = link_to profile_notifications_path, title: 'Notifications' do
+ = sidebar_link profile_notifications_path, title: _('Notifications') do
.nav-icon-container
= custom_icon('notifications')
%span.nav-item-name
Notifications
= nav_link(controller: :keys) do
- = link_to profile_keys_path, title: 'SSH Keys' do
+ = sidebar_link profile_keys_path, title: _('SSH Keys') do
.nav-icon-container
= custom_icon('key')
%span.nav-item-name
SSH Keys
= nav_link(controller: :gpg_keys) do
- = link_to profile_gpg_keys_path, title: 'GPG Keys' do
+ = sidebar_link profile_gpg_keys_path, title: _('GPG Keys') do
.nav-icon-container
= custom_icon('key_2')
%span.nav-item-name
GPG Keys
= nav_link(controller: :preferences) do
- = link_to profile_preferences_path, title: 'Preferences' do
+ = sidebar_link profile_preferences_path, title: _('Preferences') do
.nav-icon-container
= custom_icon('preferences')
%span.nav-item-name
Preferences
= nav_link(path: 'profiles#audit_log') do
- = link_to audit_log_profile_path, title: 'Authentication log' do
+ = sidebar_link audit_log_profile_path, title: _('Authentication log') do
.nav-icon-container
= custom_icon('authentication_log')
%span.nav-item-name
diff --git a/app/views/layouts/nav/_new_project_sidebar.html.haml b/app/views/layouts/nav/_new_project_sidebar.html.haml
index 341943cf833..f5361c7af0c 100644
--- a/app/views/layouts/nav/_new_project_sidebar.html.haml
+++ b/app/views/layouts/nav/_new_project_sidebar.html.haml
@@ -9,7 +9,7 @@
= @project.name
%ul.sidebar-top-level-items
= nav_link(path: ['projects#show', 'projects#activity', 'cycle_analytics#show'], html_options: { class: 'home' }) do
- = link_to project_path(@project), title: 'Project overview', class: 'shortcuts-project' do
+ = sidebar_link project_path(@project), title: _('Project overview'), css: 'shortcuts-project' do
.nav-icon-container
= custom_icon('project')
%span.nav-item-name
@@ -31,7 +31,7 @@
- if project_nav_tab? :files
= nav_link(controller: %w(tree blob blame edit_tree new_tree find_file commit commits compare projects/repositories tags branches releases graphs network)) do
- = link_to project_tree_path(@project), title: 'Repository', class: 'shortcuts-tree' do
+ = sidebar_link project_tree_path(@project), title: _('Repository'), css: 'shortcuts-tree' do
.nav-icon-container
= custom_icon('doc_text')
%span.nav-item-name
@@ -72,7 +72,7 @@
- if project_nav_tab? :container_registry
= nav_link(controller: %w[projects/registry/repositories]) do
- = link_to project_container_registry_index_path(@project), title: 'Container Registry', class: 'shortcuts-container-registry' do
+ = sidebar_link project_container_registry_index_path(@project), title: _('Container Registry'), css: 'shortcuts-container-registry' do
.nav-icon-container
= custom_icon('container_registry')
%span.nav-item-name
@@ -80,7 +80,7 @@
- if project_nav_tab? :issues
= nav_link(controller: @project.issues_enabled? ? [:issues, :labels, :milestones, :boards] : :issues) do
- = link_to project_issues_path(@project), title: 'Issues', class: 'shortcuts-issues' do
+ = sidebar_link project_issues_path(@project), title: _('Issues'), css: 'shortcuts-issues' do
.nav-icon-container
= custom_icon('issues')
%span.nav-item-name
@@ -112,7 +112,7 @@
- if project_nav_tab? :merge_requests
= nav_link(controller: @project.issues_enabled? ? :merge_requests : [:merge_requests, :labels, :milestones]) do
- = link_to project_merge_requests_path(@project), title: 'Merge Requests', class: 'shortcuts-merge_requests' do
+ = sidebar_link project_merge_requests_path(@project), title: _('Merge Requests'), css: 'shortcuts-merge_requests' do
.nav-icon-container
= custom_icon('mr_bold')
%span.nav-item-name
@@ -122,7 +122,7 @@
- if project_nav_tab? :pipelines
= nav_link(controller: [:pipelines, :builds, :jobs, :pipeline_schedules, :environments, :artifacts]) do
- = link_to project_pipelines_path(@project), title: 'CI / CD', class: 'shortcuts-pipelines' do
+ = sidebar_link project_pipelines_path(@project), title: _('CI / CD'), css: 'shortcuts-pipelines' do
.nav-icon-container
= custom_icon('pipeline')
%span.nav-item-name
@@ -161,7 +161,7 @@
- if project_nav_tab? :wiki
= nav_link(controller: :wikis) do
- = link_to get_project_wiki_path(@project), title: 'Wiki', class: 'shortcuts-wiki' do
+ = sidebar_link get_project_wiki_path(@project), title: _('Wiki'), css: 'shortcuts-wiki' do
.nav-icon-container
= custom_icon('wiki')
%span.nav-item-name
@@ -169,7 +169,7 @@
- if project_nav_tab? :snippets
= nav_link(controller: :snippets) do
- = link_to project_snippets_path(@project), title: 'Snippets', class: 'shortcuts-snippets' do
+ = sidebar_link project_snippets_path(@project), title: _('Snippets'), css: 'shortcuts-snippets' do
.nav-icon-container
= custom_icon('snippets')
%span.nav-item-name
@@ -177,7 +177,7 @@
- if project_nav_tab? :settings
= nav_link(path: %w[projects#edit project_members#index integrations#show services#edit repository#show ci_cd#show pages#show]) do
- = link_to edit_project_path(@project), title: 'Settings', class: 'shortcuts-tree' do
+ = sidebar_link edit_project_path(@project), title: _('Settings'), css: 'shortcuts-tree' do
.nav-icon-container
= custom_icon('settings')
%span.nav-item-name
@@ -208,7 +208,7 @@
= link_to project_settings_ci_cd_path(@project), title: 'CI / CD' do
%span
CI / CD
- - if Gitlab.config.pages.enabled
+ - if @project.pages_available?
= nav_link(controller: :pages) do
= link_to project_pages_path(@project), title: 'Pages' do
%span
diff --git a/app/views/profiles/gpg_keys/index.html.haml b/app/views/profiles/gpg_keys/index.html.haml
index 720a97cddb7..8dbb8aef31b 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('user/project/gpg_signed_commits/index.md')
+ = link_to 'generate it.', help_page_path('user/project/repository/gpg_signed_commits/index.md')
= render 'form'
%hr
%h5
diff --git a/app/views/projects/boards/_show.html.haml b/app/views/projects/boards/_show.html.haml
index 2076e46fde8..5354ec8522e 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"
- page_title "Boards"
diff --git a/app/views/projects/commit/_signature_badge.html.haml b/app/views/projects/commit/_signature_badge.html.haml
index a3783b31b86..d06b29db838 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('user/project/gpg_signed_commits/index.md'), class: 'gpg-popover-help-link')
+ = link_to('Learn more about signing commits', help_page_path('user/project/repository/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/new.html.haml b/app/views/projects/new.html.haml
index e2ea96b855d..adffd67029a 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/settings/_head.html.haml b/app/views/projects/settings/_head.html.haml
index 15ba09b10ba..7d24c6a9122 100644
--- a/app/views/projects/settings/_head.html.haml
+++ b/app/views/projects/settings/_head.html.haml
@@ -23,7 +23,7 @@
= link_to project_settings_ci_cd_path(@project), title: 'Pipelines' do
%span
Pipelines
- - if Gitlab.config.pages.enabled
+ - if @project.pages_available?
= nav_link(controller: :pages) do
= link_to project_pages_path(@project), title: 'Pages' do
%span
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/issuable/_search_bar.html.haml b/app/views/shared/issuable/_search_bar.html.haml
index f63b9698408..e81789ea7a2 100644
--- a/app/views/shared/issuable/_search_bar.html.haml
+++ b/app/views/shared/issuable/_search_bar.html.haml
@@ -93,6 +93,13 @@
%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/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/workers/authorized_projects_worker.rb b/app/workers/authorized_projects_worker.rb
index be4c77503bb..55d8d0c69d1 100644
--- a/app/workers/authorized_projects_worker.rb
+++ b/app/workers/authorized_projects_worker.rb
@@ -4,20 +4,40 @@ class AuthorizedProjectsWorker
# Schedules multiple jobs and waits for them to be completed.
def self.bulk_perform_and_wait(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
+
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 }
+ 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
+ # 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)
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/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/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/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/stage_update_worker.rb b/app/workers/stage_update_worker.rb
index eef0b11e70b..c301cea5ad6 100644
--- a/app/workers/stage_update_worker.rb
+++ b/app/workers/stage_update_worker.rb
@@ -2,6 +2,8 @@ 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
diff --git a/changelogs/unreleased/26692-predefined-variable-gitlab-user-name.yml b/changelogs/unreleased/26692-predefined-variable-gitlab-user-name.yml
new file mode 100644
index 00000000000..fa1ca3d25b2
--- /dev/null
+++ b/changelogs/unreleased/26692-predefined-variable-gitlab-user-name.yml
@@ -0,0 +1,5 @@
+---
+title: Add CI/CD job predefined variables with user name and login
+merge_request: 13824
+author:
+type: added
diff --git a/changelogs/unreleased/28202_decrease_abc_threshold_step3.yml b/changelogs/unreleased/28202_decrease_abc_threshold_step3.yml
new file mode 100644
index 00000000000..ed38fd37103
--- /dev/null
+++ b/changelogs/unreleased/28202_decrease_abc_threshold_step3.yml
@@ -0,0 +1,5 @@
+---
+title: Decrease ABC threshold to 55.25
+merge_request: 13904
+author: Maxim Rydkin
+type: other
diff --git a/changelogs/unreleased/28453-add-time-estimate-time-spent-to-api-issue-output.yml b/changelogs/unreleased/28453-add-time-estimate-time-spent-to-api-issue-output.yml
new file mode 100644
index 00000000000..129cf505a3f
--- /dev/null
+++ b/changelogs/unreleased/28453-add-time-estimate-time-spent-to-api-issue-output.yml
@@ -0,0 +1,4 @@
+---
+title: Add time stats to Issue and Merge Request API
+merge_request: 13335
+author: @travismiller
diff --git a/changelogs/unreleased/28938-password-change-workflow-for-admins.yml b/changelogs/unreleased/28938-password-change-workflow-for-admins.yml
new file mode 100644
index 00000000000..0781e1a2fce
--- /dev/null
+++ b/changelogs/unreleased/28938-password-change-workflow-for-admins.yml
@@ -0,0 +1,5 @@
+---
+title: Changes the password change workflow for admins.
+merge_request: 13901
+author:
+type: fixed
diff --git a/changelogs/unreleased/31470-fix-api-files-raw.yml b/changelogs/unreleased/31470-fix-api-files-raw.yml
new file mode 100644
index 00000000000..271a945a998
--- /dev/null
+++ b/changelogs/unreleased/31470-fix-api-files-raw.yml
@@ -0,0 +1,5 @@
+---
+title: Fix the /projects/:id/repository/files/:file_path/raw endpoint to handle dots in the file_path
+merge_request: 13512
+author: mahcsig
+type: fixed
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/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/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/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/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/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/36807-gc-unwanted-refs-after-import.yml b/changelogs/unreleased/36807-gc-unwanted-refs-after-import.yml
new file mode 100644
index 00000000000..a37de4325bb
--- /dev/null
+++ b/changelogs/unreleased/36807-gc-unwanted-refs-after-import.yml
@@ -0,0 +1,5 @@
+---
+title: Remove unwanted refs after importing a project
+merge_request: 13766
+author:
+type: other
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/36917-branch-tooltip.yml b/changelogs/unreleased/36917-branch-tooltip.yml
new file mode 100644
index 00000000000..2d37de50cec
--- /dev/null
+++ b/changelogs/unreleased/36917-branch-tooltip.yml
@@ -0,0 +1,5 @@
+---
+title: Adds tooltip to the branch name and improves performance
+merge_request:
+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/37179-dashboard-project-dropdown.yml b/changelogs/unreleased/37179-dashboard-project-dropdown.yml
new file mode 100644
index 00000000000..3ef080b8eae
--- /dev/null
+++ b/changelogs/unreleased/37179-dashboard-project-dropdown.yml
@@ -0,0 +1,5 @@
+---
+title: Removes disabled state from dashboard project button
+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/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/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/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/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/check-trigger-permissions.yml b/changelogs/unreleased/check-trigger-permissions.yml
new file mode 100644
index 00000000000..e0809cea9bf
--- /dev/null
+++ b/changelogs/unreleased/check-trigger-permissions.yml
@@ -0,0 +1,5 @@
+---
+title: Improve migrations using triggers
+merge_request:
+author:
+type: fixed
diff --git a/changelogs/unreleased/dm-ldap-adapter-attributes.yml b/changelogs/unreleased/dm-ldap-adapter-attributes.yml
deleted file mode 100644
index edd68ef08e7..00000000000
--- a/changelogs/unreleased/dm-ldap-adapter-attributes.yml
+++ /dev/null
@@ -1,6 +0,0 @@
----
-title: Fix signing in using LDAP when attribute mapping uses simple strings instead
- of arrays
-merge_request:
-author:
-type: fixed
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/fix-gem-security-updates.yml b/changelogs/unreleased/fix-gem-security-updates.yml
new file mode 100644
index 00000000000..dce11d08402
--- /dev/null
+++ b/changelogs/unreleased/fix-gem-security-updates.yml
@@ -0,0 +1,5 @@
+---
+title: Upgrade mail and nokogiri gems due to security issues
+merge_request: 13662
+author: Markus Koller
+type: security
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-old-mr-diffs.yml b/changelogs/unreleased/fix-old-mr-diffs.yml
deleted file mode 100644
index b0a011cf354..00000000000
--- a/changelogs/unreleased/fix-old-mr-diffs.yml
+++ /dev/null
@@ -1,6 +0,0 @@
----
-title: Show un-highlighted text diffs when we do not have references to the correct
- blobs
-merge_request:
-author:
-type: fixed
diff --git a/changelogs/unreleased/fix-push-events-branch-removals.yml b/changelogs/unreleased/fix-push-events-branch-removals.yml
deleted file mode 100644
index 71f368db296..00000000000
--- a/changelogs/unreleased/fix-push-events-branch-removals.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix display of push events for removed refs
-merge_request:
-author:
-type: fixed
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/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/improve-autocomplete-user-performance.yml b/changelogs/unreleased/improve-autocomplete-user-performance.yml
new file mode 100644
index 00000000000..5a7153771ff
--- /dev/null
+++ b/changelogs/unreleased/improve-autocomplete-user-performance.yml
@@ -0,0 +1,5 @@
+---
+title: Improve performance for AutocompleteController#users.json
+merge_request: 13754
+author: Hiroyuki Sato
+type: changed
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/mk-default-ldap-verify-certificates-secure.yml b/changelogs/unreleased/mk-default-ldap-verify-certificates-secure.yml
new file mode 100644
index 00000000000..865b57fb284
--- /dev/null
+++ b/changelogs/unreleased/mk-default-ldap-verify-certificates-secure.yml
@@ -0,0 +1,5 @@
+---
+title: Default LDAP config "verify_certificates" to true for security
+merge_request: 13915
+author:
+type: changed
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/perf-slow-issuable.yml b/changelogs/unreleased/perf-slow-issuable.yml
new file mode 100644
index 00000000000..29d15be1401
--- /dev/null
+++ b/changelogs/unreleased/perf-slow-issuable.yml
@@ -0,0 +1,6 @@
+---
+title: Fix repository equality check and avoid fetching ref if the commit is already
+ available. This affects merge request creation performance
+merge_request: 13685
+author:
+type: other
diff --git a/changelogs/unreleased/rd-fix-broken-configuration-for-some-integrations.yml b/changelogs/unreleased/rd-fix-broken-configuration-for-some-integrations.yml
deleted file mode 100644
index 00528397d64..00000000000
--- a/changelogs/unreleased/rd-fix-broken-configuration-for-some-integrations.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Testing of some integrations were broken due to missing ServiceHook record.
-merge_request:
-author:
-type: fixed
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/replace_spinach_user_lookup-feature.yml b/changelogs/unreleased/replace_spinach_user_lookup-feature.yml
new file mode 100644
index 00000000000..36248c54d99
--- /dev/null
+++ b/changelogs/unreleased/replace_spinach_user_lookup-feature.yml
@@ -0,0 +1,5 @@
+---
+title: Replace 'project/user_lookup.feature' spinach test with an rspec analog
+merge_request: 13863
+author: Vitaliy @blackst0ne Klachkov
+type: other
diff --git a/changelogs/unreleased/sh-filter-csrf-params.yml b/changelogs/unreleased/sh-filter-csrf-params.yml
new file mode 100644
index 00000000000..70eb3321e77
--- /dev/null
+++ b/changelogs/unreleased/sh-filter-csrf-params.yml
@@ -0,0 +1,5 @@
+---
+title: Filter additional secrets from Rails logs
+merge_request:
+author:
+type: security
diff --git a/changelogs/unreleased/sidebar-cache-updates.yml b/changelogs/unreleased/sidebar-cache-updates.yml
new file mode 100644
index 00000000000..aebe53ba5b2
--- /dev/null
+++ b/changelogs/unreleased/sidebar-cache-updates.yml
@@ -0,0 +1,5 @@
+---
+title: Only update the sidebar count caches when needed
+merge_request:
+author:
+type: other
diff --git a/changelogs/unreleased/zj-disable-pages-in-subgroups.yml b/changelogs/unreleased/zj-disable-pages-in-subgroups.yml
new file mode 100644
index 00000000000..22c36214e1f
--- /dev/null
+++ b/changelogs/unreleased/zj-disable-pages-in-subgroups.yml
@@ -0,0 +1,5 @@
+---
+title: Remove pages settings when not available
+merge_request:
+author:
+type: changed
diff --git a/changelogs/unreleased/zj-fix-fe-blank-button.yml b/changelogs/unreleased/zj-fix-fe-blank-button.yml
deleted file mode 100644
index 2165d4186c1..00000000000
--- a/changelogs/unreleased/zj-fix-fe-blank-button.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix new project form not resetting the template value
-merge_request:
-author:
-type: fixed
diff --git a/config/application.rb b/config/application.rb
index f69dab4de39..32a290f2002 100644
--- a/config/application.rb
+++ b/config/application.rb
@@ -51,31 +51,24 @@ module Gitlab
# Configure sensitive parameters which will be filtered from the log file.
#
# Parameters filtered:
- # - Password (:password, :password_confirmation)
- # - Private tokens
+ # - Any parameter ending with `_token`
+ # - Any parameter containing `password`
+ # - Any parameter containing `secret`
# - Two-factor tokens (:otp_attempt)
# - Repo/Project Import URLs (:import_url)
# - Build variables (:variables)
# - GitLab Pages SSL cert/key info (:certificate, :encrypted_key)
# - Webhook URLs (:hook)
- # - GitLab-shell secret token (:secret_token)
# - Sentry DSN (:sentry_dsn)
# - Deploy keys (:key)
+ config.filter_parameters += [/_token$/, /password/, /secret/]
config.filter_parameters += %i(
- authentication_token
certificate
encrypted_key
hook
import_url
- incoming_email_token
- rss_token
key
otp_attempt
- password
- password_confirmation
- private_token
- runners_token
- secret_token
sentry_dsn
variables
)
diff --git a/config/gitlab.yml.example b/config/gitlab.yml.example
index 25285525846..545c01e1156 100644
--- a/config/gitlab.yml.example
+++ b/config/gitlab.yml.example
@@ -273,9 +273,8 @@ production: &base
encryption: 'plain'
# Enables SSL certificate verification if encryption method is
- # "start_tls" or "simple_tls". (Defaults to false for backward-
- # compatibility)
- verify_certificates: false
+ # "start_tls" or "simple_tls". Defaults to true.
+ verify_certificates: true
# Specifies the path to a file containing a PEM-format CA certificate,
# e.g. if you need to use an internal CA.
diff --git a/config/initializers/1_settings.rb b/config/initializers/1_settings.rb
index abaabad5d65..360b72cdea3 100644
--- a/config/initializers/1_settings.rb
+++ b/config/initializers/1_settings.rb
@@ -155,18 +155,11 @@ if Settings.ldap['enabled'] || Rails.env.test?
server['encryption'] = 'simple_tls' if server['encryption'] == 'ssl'
server['encryption'] = 'start_tls' if server['encryption'] == 'tls'
- # Certificates are not verified for backwards compatibility.
- # This default should be flipped to true in 9.5.
- if server['verify_certificates'].nil?
- server['verify_certificates'] = false
-
- message = <<-MSG.strip_heredoc
- LDAP SSL certificate verification is disabled for backwards-compatibility.
- Please add the "verify_certificates" option to gitlab.yml for each LDAP
- server. Certificate verification will be enabled by default in GitLab 9.5.
- MSG
- Rails.logger.warn(message)
- end
+ # Certificate verification was added in 9.4.2, and defaulted to false for
+ # backwards-compatibility.
+ #
+ # Since GitLab 10.0, verify_certificates defaults to true for security.
+ server['verify_certificates'] = true if server['verify_certificates'].nil?
Settings.ldap['servers'][key] = server
end
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/sentry.rb b/config/initializers/sentry.rb
index 6b0cff75653..62d0967009a 100644
--- a/config/initializers/sentry.rb
+++ b/config/initializers/sentry.rb
@@ -1,19 +1,18 @@
# Be sure to restart your server when you modify this file.
require 'gitlab/current_settings'
-include Gitlab::CurrentSettings
if Rails.env.production?
# allow it to fail: it may do so when create_from_defaults is executed before migrations are actually done
begin
- sentry_enabled = current_application_settings.sentry_enabled
+ sentry_enabled = Gitlab::CurrentSettings.current_application_settings.sentry_enabled
rescue
sentry_enabled = false
end
if sentry_enabled
Raven.configure do |config|
- config.dsn = current_application_settings.sentry_dsn
+ config.dsn = Gitlab::CurrentSettings.current_application_settings.sentry_dsn
config.release = Gitlab::REVISION
# Sanitize fields based on those sanitized from Rails.
diff --git a/config/initializers/session_store.rb b/config/initializers/session_store.rb
index e8213ac8ba4..f2fde1e0048 100644
--- a/config/initializers/session_store.rb
+++ b/config/initializers/session_store.rb
@@ -1,11 +1,10 @@
# Be sure to restart your server when you modify this file.
require 'gitlab/current_settings'
-include Gitlab::CurrentSettings
# allow it to fail: it may do so when create_from_defaults is executed before migrations are actually done
begin
- Settings.gitlab['session_expire_delay'] = current_application_settings.session_expire_delay || 10080
+ Settings.gitlab['session_expire_delay'] = Gitlab::CurrentSettings.current_application_settings.session_expire_delay || 10080
rescue
Settings.gitlab['session_expire_delay'] ||= 10080
end
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/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/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/doc/README.md b/doc/README.md
index 76d4c3e51fe..63ba8ff03e9 100644
--- a/doc/README.md
+++ b/doc/README.md
@@ -77,6 +77,8 @@ Manage your [repositories](user/project/repository/index.md) from the UI (user i
- [Create a branch](user/project/repository/web_editor.md#create-a-new-branch)
- [Protected branches](user/project/protected_branches.md#protected-branches)
- [Delete merged branches](user/project/repository/branches/index.md#delete-merged-branches)
+- Commits
+ - [Signing commits](user/project/repository/gpg_signed_commits/index.md): use GPG to sign your commits.
### Issues and Merge Requests (MRs)
@@ -98,7 +100,6 @@ 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](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/ldap.md b/doc/administration/auth/ldap.md
index 425c924cdf2..d22815dfa5e 100644
--- a/doc/administration/auth/ldap.md
+++ b/doc/administration/auth/ldap.md
@@ -87,9 +87,12 @@ main: # 'main' is the GitLab 'provider ID' of this LDAP server
encryption: 'plain'
# Enables SSL certificate verification if encryption method is
- # "start_tls" or "simple_tls". (Defaults to false for backward-
- # compatibility)
- verify_certificates: false
+ # "start_tls" or "simple_tls". Defaults to true since GitLab 10.0 for
+ # security. This may break installations upon upgrade to 10.0, that did
+ # not know their LDAP SSL certificates were not setup properly. For
+ # example, when using self-signed certificates, the ca_file path may
+ # need to be specified.
+ verify_certificates: true
# Specifies the path to a file containing a PEM-format CA certificate,
# e.g. if you need to use an internal CA.
diff --git a/doc/api/README.md b/doc/api/README.md
index 266b5f018d9..c2a08dcff07 100644
--- a/doc/api/README.md
+++ b/doc/api/README.md
@@ -263,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/issues.md b/doc/api/issues.md
index f30ed08d0fa..14635114a31 100644
--- a/doc/api/issues.md
+++ b/doc/api/issues.md
@@ -101,6 +101,12 @@ Example response:
"user_notes_count": 1,
"due_date": "2016-07-22",
"web_url": "http://example.com/example/example/issues/6",
+ "time_stats": {
+ "time_estimate": 0,
+ "total_time_spent": 0,
+ "human_time_estimate": null,
+ "human_total_time_spent": null
+ },
"confidential": false
}
]
@@ -198,6 +204,12 @@ Example response:
"user_notes_count": 1,
"due_date": null,
"web_url": "http://example.com/example/example/issues/1",
+ "time_stats": {
+ "time_estimate": 0,
+ "total_time_spent": 0,
+ "human_time_estimate": null,
+ "human_total_time_spent": null
+ },
"confidential": false
}
]
@@ -296,6 +308,12 @@ Example response:
"user_notes_count": 1,
"due_date": "2016-07-22",
"web_url": "http://example.com/example/example/issues/1",
+ "time_stats": {
+ "time_estimate": 0,
+ "total_time_spent": 0,
+ "human_time_estimate": null,
+ "human_total_time_spent": null
+ },
"confidential": false
}
]
@@ -372,6 +390,12 @@ Example response:
"user_notes_count": 1,
"due_date": null,
"web_url": "http://example.com/example/example/issues/1",
+ "time_stats": {
+ "time_estimate": 0,
+ "total_time_spent": 0,
+ "human_time_estimate": null,
+ "human_total_time_spent": null
+ },
"confidential": false,
"_links": {
"self": "http://example.com/api/v4/projects/1/issues/2",
@@ -440,6 +464,12 @@ Example response:
"user_notes_count": 0,
"due_date": null,
"web_url": "http://example.com/example/example/issues/14",
+ "time_stats": {
+ "time_estimate": 0,
+ "total_time_spent": 0,
+ "human_time_estimate": null,
+ "human_total_time_spent": null
+ },
"confidential": false,
"_links": {
"self": "http://example.com/api/v4/projects/1/issues/2",
@@ -509,6 +539,12 @@ Example response:
"user_notes_count": 0,
"due_date": "2016-07-22",
"web_url": "http://example.com/example/example/issues/15",
+ "time_stats": {
+ "time_estimate": 0,
+ "total_time_spent": 0,
+ "human_time_estimate": null,
+ "human_total_time_spent": null
+ },
"confidential": false,
"_links": {
"self": "http://example.com/api/v4/projects/1/issues/2",
@@ -601,6 +637,12 @@ Example response:
},
"due_date": null,
"web_url": "http://example.com/example/example/issues/11",
+ "time_stats": {
+ "time_estimate": 0,
+ "total_time_spent": 0,
+ "human_time_estimate": null,
+ "human_total_time_spent": null
+ },
"confidential": false,
"_links": {
"self": "http://example.com/api/v4/projects/1/issues/2",
@@ -672,6 +714,12 @@ Example response:
},
"due_date": null,
"web_url": "http://example.com/example/example/issues/11",
+ "time_stats": {
+ "time_estimate": 0,
+ "total_time_spent": 0,
+ "human_time_estimate": null,
+ "human_total_time_spent": null
+ },
"confidential": false,
"_links": {
"self": "http://example.com/api/v4/projects/1/issues/2",
@@ -1001,7 +1049,13 @@ Example response:
"user_notes_count": 1,
"should_remove_source_branch": null,
"force_remove_source_branch": false,
- "web_url": "https://gitlab.example.com/gitlab-org/gitlab-test/merge_requests/6432"
+ "web_url": "https://gitlab.example.com/gitlab-org/gitlab-test/merge_requests/6432",
+ "time_stats": {
+ "time_estimate": 0,
+ "total_time_spent": 0,
+ "human_time_estimate": null,
+ "human_total_time_spent": null
+ }
}
]
```
diff --git a/doc/api/merge_requests.md b/doc/api/merge_requests.md
index 802e5362d70..4f67aa4b9d4 100644
--- a/doc/api/merge_requests.md
+++ b/doc/api/merge_requests.md
@@ -92,7 +92,13 @@ Parameters:
"user_notes_count": 1,
"should_remove_source_branch": true,
"force_remove_source_branch": false,
- "web_url": "http://example.com/example/example/merge_requests/1"
+ "web_url": "http://example.com/example/example/merge_requests/1",
+ "time_stats": {
+ "time_estimate": 0,
+ "total_time_spent": 0,
+ "human_time_estimate": null,
+ "human_total_time_spent": null
+ }
}
]
```
@@ -181,7 +187,13 @@ Parameters:
"user_notes_count": 1,
"should_remove_source_branch": true,
"force_remove_source_branch": false,
- "web_url": "http://example.com/example/example/merge_requests/1"
+ "web_url": "http://example.com/example/example/merge_requests/1",
+ "time_stats": {
+ "time_estimate": 0,
+ "total_time_spent": 0,
+ "human_time_estimate": null,
+ "human_total_time_spent": null
+ }
}
]
```
@@ -250,7 +262,13 @@ Parameters:
"user_notes_count": 1,
"should_remove_source_branch": true,
"force_remove_source_branch": false,
- "web_url": "http://example.com/example/example/merge_requests/1"
+ "web_url": "http://example.com/example/example/merge_requests/1",
+ "time_stats": {
+ "time_estimate": 0,
+ "total_time_spent": 0,
+ "human_time_estimate": null,
+ "human_total_time_spent": null
+ }
}
```
@@ -356,6 +374,12 @@ Parameters:
"should_remove_source_branch": true,
"force_remove_source_branch": false,
"web_url": "http://example.com/example/example/merge_requests/1",
+ "time_stats": {
+ "time_estimate": 0,
+ "total_time_spent": 0,
+ "human_time_estimate": null,
+ "human_total_time_spent": null
+ }
"changes": [
{
"old_path": "VERSION",
@@ -442,7 +466,13 @@ POST /projects/:id/merge_requests
"user_notes_count": 0,
"should_remove_source_branch": true,
"force_remove_source_branch": false,
- "web_url": "http://example.com/example/example/merge_requests/1"
+ "web_url": "http://example.com/example/example/merge_requests/1",
+ "time_stats": {
+ "time_estimate": 0,
+ "total_time_spent": 0,
+ "human_time_estimate": null,
+ "human_total_time_spent": null
+ }
}
```
@@ -519,7 +549,13 @@ Must include at least one non-required attribute from above.
"user_notes_count": 1,
"should_remove_source_branch": true,
"force_remove_source_branch": false,
- "web_url": "http://example.com/example/example/merge_requests/1"
+ "web_url": "http://example.com/example/example/merge_requests/1",
+ "time_stats": {
+ "time_estimate": 0,
+ "total_time_spent": 0,
+ "human_time_estimate": null,
+ "human_total_time_spent": null
+ }
}
```
@@ -617,7 +653,13 @@ Parameters:
"user_notes_count": 1,
"should_remove_source_branch": true,
"force_remove_source_branch": false,
- "web_url": "http://example.com/example/example/merge_requests/1"
+ "web_url": "http://example.com/example/example/merge_requests/1",
+ "time_stats": {
+ "time_estimate": 0,
+ "total_time_spent": 0,
+ "human_time_estimate": null,
+ "human_total_time_spent": null
+ }
}
```
@@ -687,7 +729,13 @@ Parameters:
"user_notes_count": 1,
"should_remove_source_branch": true,
"force_remove_source_branch": false,
- "web_url": "http://example.com/example/example/merge_requests/1"
+ "web_url": "http://example.com/example/example/merge_requests/1",
+ "time_stats": {
+ "time_estimate": 0,
+ "total_time_spent": 0,
+ "human_time_estimate": null,
+ "human_total_time_spent": null
+ }
}
```
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/ssh_keys/README.md b/doc/ci/ssh_keys/README.md
index cf25a8b618f..cdb9858e179 100644
--- a/doc/ci/ssh_keys/README.md
+++ b/doc/ci/ssh_keys/README.md
@@ -42,7 +42,7 @@ It is also good practice to check the server's own public key to make sure you
are not being targeted by a man-in-the-middle attack. To do this, add another
variable named `SSH_SERVER_HOSTKEYS`. To find out the hostkeys of your server, run
the `ssh-keyscan YOUR_SERVER` command from a trusted network (ideally, from the
-server itself), and paste its output into the `SSH_SERVER_HOSTKEY` variable. If
+server itself), and paste its output into the `SSH_SERVER_HOSTKEYS` variable. If
you need to connect to multiple servers, concatenate all the server public keys
that you collected into the **Value** of the variable. There must be one key per
line.
diff --git a/doc/ci/variables/README.md b/doc/ci/variables/README.md
index 234dc530db0..6513b31826a 100644
--- a/doc/ci/variables/README.md
+++ b/doc/ci/variables/README.md
@@ -78,6 +78,8 @@ future GitLab releases.**
| **GITLAB_CI** | all | all | Mark that job is executed in GitLab CI environment |
| **GITLAB_USER_ID** | 8.12 | all | The id of the user who started the job |
| **GITLAB_USER_EMAIL** | 8.12 | all | The email of the user who started the job |
+| **GITLAB_USER_LOGIN** | 10.0 | all | The login username of the user who started the job |
+| **GITLAB_USER_NAME** | 10.0 | all | The real name of the user who started the job |
| **RESTORE_CACHE_ATTEMPTS** | 8.15 | 1.9 | Number of attempts to restore the cache running a job |
## 9.0 Renaming
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/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/install/kubernetes/gitlab_chart.md b/doc/install/kubernetes/gitlab_chart.md
index 81057736e3a..6bcc58bb805 100644
--- a/doc/install/kubernetes/gitlab_chart.md
+++ b/doc/install/kubernetes/gitlab_chart.md
@@ -1,7 +1,7 @@
# GitLab Helm Chart
-> These Helm charts are in beta. GitLab is working on a [cloud-native](http://docs.gitlab.com/omnibus/package-information/cloud_native.html) set of [Charts](https://gitlab.com/charts/helm.gitlab.io) which will replace these.
-
-> Officially supported cloud providers are Google Container Service and Azure Container Service.
+> **Note:**
+* GitLab is working on a [cloud native set of Charts](https://gitlab.com/charts/helm.gitlab.io/blob/master/README.md) which will replace these.
+* Officially supported cloud providers are Google Container Service and Azure Container Service.
The `gitlab` Helm chart deploys GitLab into your Kubernetes cluster.
@@ -22,9 +22,7 @@ This chart includes the following:
- [Persistent Volume](https://kubernetes.io/docs/concepts/storage/persistent-volumes/) provisioner support in the underlying infrastructure
- The ability to point a DNS entry or URL at your GitLab install
- The `kubectl` CLI installed locally and authenticated for the cluster
-- The Helm Client installed locally
-- The Helm Server (Tiller) already installed and running in the cluster, by running `helm init`
-- The GitLab Helm Repo [added to your Helm Client](index.md#add-the-gitlab-helm-repository)
+- The [Helm client](https://github.com/kubernetes/helm/blob/master/docs/quickstart.md) installed locally on your machine
## Configuring GitLab
@@ -428,7 +426,7 @@ 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:
+Add the GitLab Helm repository and initialize Helm:
```bash
helm repo add gitlab https://charts.gitlab.io
diff --git a/doc/install/kubernetes/gitlab_omnibus.md b/doc/install/kubernetes/gitlab_omnibus.md
index 05e0a59ffeb..8636ce2507c 100644
--- a/doc/install/kubernetes/gitlab_omnibus.md
+++ b/doc/install/kubernetes/gitlab_omnibus.md
@@ -1,7 +1,8 @@
# GitLab-Omnibus Helm Chart
-> These Helm charts are in beta. GitLab is working on a [cloud-native](http://docs.gitlab.com/omnibus/package-information/cloud_native.html) set of [Charts](https://gitlab.com/charts/helm.gitlab.io) which will replace these.
-
-> Officially supported cloud providers are Google Container Service and Azure Container Service.
+> **Note:**
+* This Helm chart is in beta, while [additional features](https://gitlab.com/charts/charts.gitlab.io/issues/68) are being worked on.
+* GitLab is working on a [cloud native set of Charts](https://gitlab.com/charts/helm.gitlab.io/blob/master/README.md) which will eventually replace these.
+* Officially supported cloud providers are Google Container Service and Azure Container Service.
This work is based partially on: https://github.com/lwolf/kubernetes-gitlab/. GitLab would like to thank Sergey Nuzhdin for his work.
@@ -29,53 +30,51 @@ Terms:
## Prerequisites
-- _At least_ 4 GB of RAM available on your cluster, in chunks of 1 GB. 41GB of storage and 2 CPU are also required.
+- _At least_ 4 GB of RAM available on your cluster. 41GB of storage and 2 CPU are also required.
- Kubernetes 1.4+ with Beta APIs enabled
- [Persistent Volume](https://kubernetes.io/docs/concepts/storage/persistent-volumes/) provisioner support in the underlying infrastructure
-- An [external IP address](#networking-prerequisites)
- A [wildcard DNS entry](#networking-prerequisites), which resolves to the external IP address
- The `kubectl` CLI installed locally and authenticated for the cluster
-- The Helm Client installed locally
-- The Helm Server (Tiller) already installed and running in the cluster, by running `helm init`
-- The GitLab Helm Repo [added to your Helm Client](index.md#add-the-gitlab-helm-repository)
+- The [Helm client](https://github.com/kubernetes/helm/blob/master/docs/quickstart.md) installed locally on your machine
### Networking Prerequisites
This chart configures a GitLab server and Kubernetes cluster which can support dynamic [Review Apps](https://docs.gitlab.com/ee/ci/review_apps/index.html), as well as services like the integrated [Container Registry](https://docs.gitlab.com/ee/user/project/container_registry.html) and [Mattermost](https://docs.gitlab.com/omnibus/gitlab-mattermost/).
-To support the GitLab services and dynamic environments, a wildcard DNS entry is required which resolves to the external Load Balancer IP.
+To support the GitLab services and dynamic environments, a wildcard DNS entry is required which resolves to the [Load Balancer](#load-balancer-ip) or [External IP](#external-ip). Configuration of the DNS entry will depend upon the DNS service being used.
+
+#### External IP (Recommended)
To provision an external IP on GCP and Azure, simply request a new address from the Networking section. Ensure that the region matches the region your container cluster is created in. Note, it is important that the IP is not assigned at this point in time. It will be automatically assigned once the Helm chart is installed, and assigned to the Load Balancer.
Now that an external IP address has been allocated, ensure that the wildcard DNS entry you would like to use resolves to this IP. Please consult the documentation for your DNS service for more information on creating DNS records.
+Finally, set the `baseIP` setting to this IP address when [deploying GitLab](#configuring-and-installing-gitlab).
+
+#### Load Balancer IP
+
+If you do not specify a `baseIP`, an ephemeral IP will be assigned to the Load Balancer or Ingress. You can retrieve this IP by running the following command *after* deploying GitLab:
+
+`kubectl get svc -w --namespace nginx-ingress nginx`
+
+The IP address will be displayed in the `EXTERNAL-IP` field, and should be used to configure the Wildcard DNS entry. For more information on creating a wildcard DNS entry, consult the documentation for the DNS server you are using.
+
+For production deployments of GitLab, we strongly recommend using an [External IP](#external-ip).
+
## Configuring and Installing GitLab
For most installations, only two parameters are required:
-- `baseIP`: the desired [external IP address](#networking-prerequisites)
- `baseDomain`: the [base domain](#networking-prerequisites) with the wildcard host entry resolving to the `baseIP`. For example, `mycompany.io`.
+- `legoEmail`: Email address to use when requesting new SSL certificates from Let's Encrypt
Other common configuration options:
+- `baseIP`: the desired [external IP address](#networking-prerequisites)
- `gitlab`: Choose the [desired edition](https://about.gitlab.com/products), either `ee` or `ce`. `ce` is the default.
- `gitlabEELicense`: For Enterprise Edition, the [license](https://docs.gitlab.com/ee/user/admin_area/license.html) can be installed directly via the Chart
- `provider`: Optimizes the deployment for a cloud provider. The default is `gke` for GCP, with `acs` also supported for Azure.
-- `legoEmail`: Email address to use when requesting new SSL certificates from Let's Encrypt
For additional configuration options, consult the [values.yaml](https://gitlab.com/charts/charts.gitlab.io/blob/master/charts/gitlab-omnibus/values.yaml).
-These settings can either be passed directly 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
-```
-
-or within a YAML file:
-```bash
-helm install --name gitlab -f values.yaml gitlab/gitlab-omnibus
-```
-
-> **Note:**
-If you are using a machine type with support for less than 4 attached disks, like an Azure trial, you should disable dedicated storage for [Postgres and Redis](#persistent-storage).
-
### Choosing a different GitLab release version
The version of GitLab installed is based on the `gitlab` setting (see [section](#choosing-gitlab-edition) above), and
@@ -95,6 +94,8 @@ There is no guarantee that other release versions of GitLab, other than what are
used by default in the chart, will be supported by a chart install.
### Persistent storage
+> **Note:**
+If you are using a machine type with support for less than 4 attached disks, like an Azure trial, you should disable dedicated storage for [Postgres and Redis](#persistent-storage).
By default, persistent storage is enabled for GitLab and the charts it depends
on (Redis and PostgreSQL).
@@ -124,9 +125,10 @@ Ingress routing and SSL are automatically configured within this Chart. An NGINX
Let's Encrypt limits a single TLD to five certificate requests within a single week. This means that common DNS wildcard services like [xip.io](http://xip.io) and [nip.io](http://nip.io) are unlikely to work.
## 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.
+> **Note:**
+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 start. 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:
+Add the GitLab Helm repository and initialize Helm:
```bash
helm repo add gitlab https://charts.gitlab.io
diff --git a/doc/install/kubernetes/gitlab_runner_chart.md b/doc/install/kubernetes/gitlab_runner_chart.md
index 51f94a33109..d31c763ed64 100644
--- a/doc/install/kubernetes/gitlab_runner_chart.md
+++ b/doc/install/kubernetes/gitlab_runner_chart.md
@@ -1,7 +1,6 @@
# GitLab Runner Helm Chart
-> These Helm charts are in beta. GitLab is working on a [cloud-native](http://docs.gitlab.com/omnibus/package-information/cloud_native.html) set of [Charts](https://gitlab.com/charts/helm.gitlab.io) which will replace these.
-
-> Officially supported cloud providers are Google Container Service and Azure Container Service.
+> **Note:**
+Officially supported cloud providers are Google Container Service and Azure Container Service.
The `gitlab-runner` Helm chart deploys a GitLab Runner instance into your
Kubernetes cluster.
@@ -17,9 +16,7 @@ This chart configures the Runner to:
- Your GitLab Server's API is reachable from the cluster
- Kubernetes 1.4+ with Beta APIs enabled
- The `kubectl` CLI installed locally and authenticated for the cluster
-- The Helm Client installed locally
-- The Helm Server (Tiller) already installed and running in the cluster, by running `helm init`
-- The GitLab Helm Repo added to your Helm Client. See [Adding GitLab Helm Repo](index.md#add-the-gitlab-helm-repository)
+- The [Helm client](https://github.com/kubernetes/helm/blob/master/docs/quickstart.md) installed locally on your machine
## Configuring GitLab Runner using the Helm Chart
@@ -36,6 +33,8 @@ In order for GitLab Runner to function, your config file **must** specify the fo
- `runnerRegistrationToken` - The Registration Token for adding new Runners to the GitLab Server. This must be
retrieved from your GitLab Instance. See the [GitLab Runner Documentation](../../ci/runners/README.md#creating-and-registering-a-runner) for more information.
+Unless you need to specify additional configuration, you are [ready to install](#installing-gitlab-runner-using-the-helm-chart).
+
### Other configuration
The rest of the configuration is [documented in the `values.yaml`](https://gitlab.com/charts/charts.gitlab.io/blob/master/charts/gitlab-runner/values.yaml) in the chart repository.
@@ -115,6 +114,17 @@ runners:
```
+### Controlling maximum Runner concurrency
+
+A single GitLab Runner deployed on Kubernetes is able to execute multiple jobs in parallel by automatically starting additional Runner pods. The [`concurrent` setting](https://docs.gitlab.com/runner/configuration/advanced-configuration.html#the-global-section) controls the maximum number of pods allowed at a single time, and defaults to `10`.
+
+```yaml
+## Configure the maximum number of concurrent jobs
+## ref: https://docs.gitlab.com/runner/configuration/advanced-configuration.html#the-global-section
+##
+concurrent: 10
+```
+
### Running Docker-in-Docker containers with GitLab Runners
See [Running Privileged Containers for the Runners](#running-privileged-containers-for-the-runners) for how to enable it,
@@ -190,7 +200,7 @@ certsSecretName: <SECRET NAME>
## Installing GitLab Runner using the Helm Chart
-Ensure the GitLab repo has been added and re-initialize Helm:
+Add the GitLab Helm repository and initialize Helm:
```bash
helm repo add gitlab https://charts.gitlab.io
diff --git a/doc/install/kubernetes/index.md b/doc/install/kubernetes/index.md
index eb98dc06a18..8418b04936b 100644
--- a/doc/install/kubernetes/index.md
+++ b/doc/install/kubernetes/index.md
@@ -1,48 +1,52 @@
# Installing GitLab on Kubernetes
-> These Helm charts are in beta. GitLab is working on a [cloud-native](http://docs.gitlab.com/omnibus/package-information/cloud_native.html) set of [Charts](https://gitlab.com/charts/helm.gitlab.io) which will replace these.
-
> Officially supported cloud providers are Google Container Service and Azure Container Service.
The easiest method to deploy GitLab in [Kubernetes](https://kubernetes.io/) is
-to take advantage of the official GitLab Helm charts. [Helm] is a package
+to take advantage of GitLab's Helm charts. [Helm] is a package
management tool for Kubernetes, allowing apps to be easily managed via their
Charts. A [Chart] is a detailed description of the application including how it
should be deployed, upgraded, and configured.
-The GitLab Helm repository is located at https://charts.gitlab.io.
-You can report any issues related to GitLab's Helm Charts at
+GitLab provides [official Helm Charts](#official-gitlab-helm-charts-recommended) which is the recommended way to run GitLab with Kubernetes.
+
+There are also two other sets of charts:
+* Our [upcoming cloud native Charts](#upcoming-cloud-native-helm-charts), which are in development but will eventually replace the current official charts.
+* [Community contributed charts](#community-contributed-helm-charts). These charts should be considered deprecated, in favor of the official charts.
+
+## Official GitLab Helm Charts (Recommended)
+
+These charts utilize our [GitLab Omnibus Docker images](https://docs.gitlab.com/omnibus/docker/README.html). You can report any issues and feedback related to these charts at
https://gitlab.com/charts/charts.gitlab.io/issues.
-Contributions and improvements are also very welcome.
-## Prerequisites
+### Deploying GitLab on Kubernetes (Recommended)
+> *Note*: This chart will eventually be replaced by the [cloud native charts](#upcoming-cloud-native-helm-charts), which are presently in development.
+
+The best way to deploy GitLab on Kubernetes is to use the [gitlab-omnibus](gitlab_omnibus.md) chart. It 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). This chart is in beta while [additional features](https://gitlab.com/charts/charts.gitlab.io/issues/68) are being completed.
-To use the charts, the Helm tool must be installed and initialized. The best
-place to start is by reviewing the [Helm Quick Start Guide][helm-quick].
+### Deploying just the GitLab Runner
-## Add the GitLab Helm repository
+To deploy just the GitLab Runner, utilize the [gitlab-runner](gitlab_runner_chart.md) chart. It offers a quick way to configure and deploy the Runner on Kubernetes, regardless of where your GitLab server may be running.
-Once Helm has been installed, the GitLab chart repository must be added:
+### Advanced deployment of GitLab (Not recommended)
+> *Note*: This chart will eventually be replaced by the [cloud native charts](#upcoming-cloud-native-helm-charts), which are presently in development.
-```bash
-helm repo add gitlab https://charts.gitlab.io
-```
+If advanced configuration of GitLab is required, the beta [gitlab](gitlab_chart.md) chart can be used which deploys the GitLab service along with optional Postgres and Redis. It offers extensive configuration, but requires deep knowledge of Kubernetes and Helm to use.
-After adding the repository, Helm must be re-initialized:
+## Upcoming Cloud Native Helm Charts
-```bash
-helm init
-```
+GitLab is working towards a building a [cloud native deployment method](https://gitlab.com/charts/helm.gitlab.io/blob/master/README.md). A key part of this effort is to isolate each service into it's [own Docker container and Helm chart](https://gitlab.com/gitlab-org/omnibus-gitlab/issues/2420), rather than utilizing the all-in-one container image of the [current charts](#official-gitlab-helm-charts-recommended).
-## Using the GitLab Helm Charts
+By offering individual containers and charts, we will be able to provide a number of benefits:
+* Easier horizontal scaling of each service
+* Smaller more efficient images
+* Potential for rolling updates and canaries within a service
+* and plenty more.
-GitLab makes available three Helm Charts.
+This is a large project and will be worked on over the span of multiple releases. For the most up to date status and release information, please see our [tracking issue](https://gitlab.com/gitlab-org/omnibus-gitlab/issues/2420).
-- [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.
+## Community Contributed Helm Charts
-We are also working on a new set of [cloud native Charts](https://gitlab.com/charts/helm.gitlab.io) which will eventually replace these.
+The community has also [contributed GitLab charts](https://github.com/kubernetes/charts/tree/master/stable/gitlab-ce) to the [Helm Stable Repository](https://github.com/kubernetes/charts#repository-structure). These charts should be considered [deprecated](https://github.com/kubernetes/charts/issues/1138) in favor of the [official Charts](#official-gitlab-helm-charts-recommended).
[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/install/requirements.md b/doc/install/requirements.md
index 175dfc62096..f672b358096 100644
--- a/doc/install/requirements.md
+++ b/doc/install/requirements.md
@@ -82,7 +82,9 @@ errors during usage.
We recommend having at least 2GB of swap on your server, even if you currently have
enough available RAM. Having swap will help reduce the chance of errors occurring
-if your available memory changes.
+if your available memory changes. We also recommend [configuring the kernels swappiness setting](https://askubuntu.com/a/103916)
+to a low value like `10` to make the most of your RAM while still having the swap
+available when needed.
Notice: The 25 workers of Sidekiq will show up as separate processes in your process overview (such as top or htop) but they share the same RAM allocation since Sidekiq is a multithreaded application. Please see the section below about Unicorn workers for information about many you need of those.
diff --git a/doc/raketasks/backup_restore.md b/doc/raketasks/backup_restore.md
index 10f5ab3370d..ae69d7f92f2 100644
--- a/doc/raketasks/backup_restore.md
+++ b/doc/raketasks/backup_restore.md
@@ -144,9 +144,8 @@ gitlab_rails['backup_upload_connection'] = {
'region' => 'eu-west-1',
'aws_access_key_id' => 'AKIAKIAKI',
'aws_secret_access_key' => 'secret123'
- # If using an IAM Profile, leave aws_access_key_id & aws_secret_access_key empty
- # ie. 'aws_access_key_id' => '',
- # 'use_iam_profile' => 'true'
+ # If using an IAM Profile, don't configure aws_access_key_id & aws_secret_access_key
+ # 'use_iam_profile' => true
}
gitlab_rails['backup_upload_remote_directory'] = 'my.s3.bucket'
```
diff --git a/doc/user/project/gpg_signed_commits/index.md b/doc/user/project/gpg_signed_commits/index.md
index 3ea2203c895..261eedeb412 100644
--- a/doc/user/project/gpg_signed_commits/index.md
+++ b/doc/user/project/gpg_signed_commits/index.md
@@ -1,245 +1 @@
-# 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
+This document was moved to [another location](../repository/gpg_signed_commits/index.md).
diff --git a/doc/user/project/members/img/other_group_sees_shared_project.png b/doc/user/project/members/img/other_group_sees_shared_project.png
index 67af27043eb..e4c93a13abb 100644
--- a/doc/user/project/members/img/other_group_sees_shared_project.png
+++ b/doc/user/project/members/img/other_group_sees_shared_project.png
Binary files differ
diff --git a/doc/user/project/members/img/share_project_with_groups.png b/doc/user/project/members/img/share_project_with_groups.png
index 3cb4796f9f7..0907438cb84 100644
--- a/doc/user/project/members/img/share_project_with_groups.png
+++ b/doc/user/project/members/img/share_project_with_groups.png
Binary files differ
diff --git a/doc/user/project/members/img/share_project_with_groups_tab.png b/doc/user/project/members/img/share_project_with_groups_tab.png
new file mode 100644
index 00000000000..fc489aae003
--- /dev/null
+++ b/doc/user/project/members/img/share_project_with_groups_tab.png
Binary files differ
diff --git a/doc/user/project/members/share_project_with_groups.md b/doc/user/project/members/share_project_with_groups.md
index 4c1ddcdcba8..25e5b897825 100644
--- a/doc/user/project/members/share_project_with_groups.md
+++ b/doc/user/project/members/share_project_with_groups.md
@@ -5,7 +5,7 @@ possible to add a group of users to a project with a single action.
## Groups as collections of users
-Groups are used primarily to [create collections of projects](../user/group/index.md), but you can also
+Groups are used primarily to [create collections of projects](../../group/index.md), but you can also
take advantage of the fact that groups define collections of _users_, namely the group
members.
@@ -16,20 +16,23 @@ say 'Project Acme', in GitLab is to make the 'Engineering' group the owner of 'P
Acme'. But what if 'Project Acme' already belongs to another group, say 'Open Source'?
This is where the group sharing feature can be of use.
-To share 'Project Acme' with the 'Engineering' group, go to the project settings page for 'Project Acme' and use the left navigation menu to go to the 'Groups' section.
+To share 'Project Acme' with the 'Engineering' group, go to the project settings page for 'Project Acme' and use the left navigation menu to go to the **Settings > Members** section.
-![The 'Groups' section in the project settings screen](img/share_project_with_groups.png)
+![share project with groups](img/share_project_with_groups.png)
-Now you can add the 'Engineering' group with the maximum access level of your choice.
-After sharing 'Project Acme' with 'Engineering', the project is listed on the group dashboard.
+Then select the 'Share with group' tab by clicking it.
+
+Now you can add the 'Engineering' group with the maximum access level of your choice. Click 'Share' to share it.
+
+![share project with groups tab](img/share_project_with_groups_tab.png)
+
+After sharing 'Project Acme' with 'Engineering', the project will be listed on the group dashboard.
!['Project Acme' is listed as a shared project for 'Engineering'](img/other_group_sees_shared_project.png)
## Maximum access level
-!['Project Acme' is shared with 'Engineering' with a maximum access level of 'Developer'](img/max_access_level.png)
-
-In the screenshot above, the maximum access level of 'Developer' for members from 'Engineering' means that users with higher access levels in 'Engineering' ('Master' or 'Owner') will only have 'Developer' access to 'Project Acme'.
+In the example above, the maximum access level of 'Developer' for members from 'Engineering' means that users with higher access levels in 'Engineering' ('Master' or 'Owner') will only have 'Developer' access to 'Project Acme'.
## Share project with group lock (EES/EEP)
diff --git a/doc/user/project/pipelines/job_artifacts.md b/doc/user/project/pipelines/job_artifacts.md
index e853bfff444..4e93e680fd2 100644
--- a/doc/user/project/pipelines/job_artifacts.md
+++ b/doc/user/project/pipelines/job_artifacts.md
@@ -100,16 +100,21 @@ inside GitLab that make that possible.
It is possible to download the latest artifacts of a job via a well known URL
so you can use it for scripting purposes.
+>**Note:**
+The latest artifacts are considered as the artifacts created by jobs in the
+latest pipeline that succeeded for the specific ref.
+Artifacts for other pipelines can be accessed with direct access to them.
+
The structure of the URL to download the whole artifacts archive is the following:
```
-https://example.com/<namespace>/<project>/builds/artifacts/<ref>/download?job=<job_name>
+https://example.com/<namespace>/<project>/-/jobs/artifacts/<ref>/download?job=<job_name>
```
To download a single file from the artifacts use the following URL:
```
-https://example.com/<namespace>/<project>/builds/artifacts/<ref>/raw/<path_to_file>?job=<job_name>
+https://example.com/<namespace>/<project>/-/jobs/artifacts/<ref>/raw/<path_to_file>?job=<job_name>
```
For example, to download the latest artifacts of the job named `coverage` of
@@ -117,26 +122,26 @@ the `master` branch of the `gitlab-ce` project that belongs to the `gitlab-org`
namespace, the URL would be:
```
-https://gitlab.com/gitlab-org/gitlab-ce/builds/artifacts/master/download?job=coverage
+https://gitlab.com/gitlab-org/gitlab-ce/-/jobs/artifacts/master/download?job=coverage
```
To download the file `coverage/index.html` from the same
artifacts use the following URL:
```
-https://gitlab.com/gitlab-org/gitlab-ce/builds/artifacts/master/raw/coverage/index.html?job=coverage
+https://gitlab.com/gitlab-org/gitlab-ce/-/jobs/artifacts/master/raw/coverage/index.html?job=coverage
```
There is also a URL to browse the latest job artifacts:
```
-https://example.com/<namespace>/<project>/builds/artifacts/<ref>/browse?job=<job_name>
+https://example.com/<namespace>/<project>/-/jobs/artifacts/<ref>/browse?job=<job_name>
```
For example:
```
-https://gitlab.com/gitlab-org/gitlab-ce/builds/artifacts/master/browse?job=coverage
+https://gitlab.com/gitlab-org/gitlab-ce/-/jobs/artifacts/master/browse?job=coverage
```
The latest builds are also exposed in the UI in various places. Specifically,
diff --git a/doc/user/project/gpg_signed_commits/img/profile_settings_gpg_keys_paste_pub.png b/doc/user/project/repository/gpg_signed_commits/img/profile_settings_gpg_keys_paste_pub.png
index 8e26d98f1b0..8e26d98f1b0 100644
--- a/doc/user/project/gpg_signed_commits/img/profile_settings_gpg_keys_paste_pub.png
+++ b/doc/user/project/repository/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/repository/gpg_signed_commits/img/profile_settings_gpg_keys_single_key.png
index 5c14df36d73..5c14df36d73 100644
--- a/doc/user/project/gpg_signed_commits/img/profile_settings_gpg_keys_single_key.png
+++ b/doc/user/project/repository/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/repository/gpg_signed_commits/img/project_signed_and_unsigned_commits.png
index 33936a7d6d7..33936a7d6d7 100644
--- a/doc/user/project/gpg_signed_commits/img/project_signed_and_unsigned_commits.png
+++ b/doc/user/project/repository/gpg_signed_commits/img/project_signed_and_unsigned_commits.png
Binary files differ
diff --git a/doc/user/project/gpg_signed_commits/img/project_signed_commit_unverified_signature.png b/doc/user/project/repository/gpg_signed_commits/img/project_signed_commit_unverified_signature.png
index 22565cf7c7e..22565cf7c7e 100644
--- a/doc/user/project/gpg_signed_commits/img/project_signed_commit_unverified_signature.png
+++ b/doc/user/project/repository/gpg_signed_commits/img/project_signed_commit_unverified_signature.png
Binary files differ
diff --git a/doc/user/project/gpg_signed_commits/img/project_signed_commit_verified_signature.png b/doc/user/project/repository/gpg_signed_commits/img/project_signed_commit_verified_signature.png
index 1778b2ddf2b..1778b2ddf2b 100644
--- a/doc/user/project/gpg_signed_commits/img/project_signed_commit_verified_signature.png
+++ b/doc/user/project/repository/gpg_signed_commits/img/project_signed_commit_verified_signature.png
Binary files differ
diff --git a/doc/user/project/repository/gpg_signed_commits/index.md b/doc/user/project/repository/gpg_signed_commits/index.md
new file mode 100644
index 00000000000..ff419d714f9
--- /dev/null
+++ b/doc/user/project/repository/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/repository/index.md b/doc/user/project/repository/index.md
index 5e5ae880518..235af83353d 100644
--- a/doc/user/project/repository/index.md
+++ b/doc/user/project/repository/index.md
@@ -22,7 +22,7 @@ you to [connect with GitLab via SSH](../../../ssh/README.md).
## Files
-## Create and edit files
+### Create and edit files
Host your codebase in GitLab repositories by pushing your files to GitLab.
You can either use the user interface (UI), or connect your local computer
@@ -111,6 +111,8 @@ right from the UI.
- **Revert a commit:**
Easily [revert a commit](../merge_requests/revert_changes.md#reverting-a-commit)
from the UI to a selected branch.
+- **Sign a commit:**
+Use GPG to [sign your commits](gpg_signed_commits/index.md).
## Repository size
diff --git a/features/project/commits/user_lookup.feature b/features/project/commits/user_lookup.feature
deleted file mode 100644
index c18f4e070f3..00000000000
--- a/features/project/commits/user_lookup.feature
+++ /dev/null
@@ -1,16 +0,0 @@
-@project_commits
-Feature: Project Commits User Lookup
- Background:
- Given I sign in as a user
- And I own a project
- And I visit my project's commits page
-
- Scenario: I browse commit from list
- Given I have user with primary email
- When I click on commit link
- Then I see author based on primary email
-
- Scenario: I browse another commit from list
- Given I have user with secondary email
- When I click on another commit link
- Then I see author based on secondary email
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/commits/user_lookup.rb b/features/steps/project/commits/user_lookup.rb
deleted file mode 100644
index 4599e0d032a..00000000000
--- a/features/steps/project/commits/user_lookup.rb
+++ /dev/null
@@ -1,49 +0,0 @@
-class Spinach::Features::ProjectCommitsUserLookup < Spinach::FeatureSteps
- include SharedAuthentication
- include SharedProject
- include SharedPaths
-
- step 'I click on commit link' do
- visit project_commit_path(@project, sample_commit.id)
- end
-
- step 'I click on another commit link' do
- visit project_commit_path(@project, sample_commit.parent_id)
- end
-
- step 'I have user with primary email' do
- user_primary
- end
-
- step 'I have user with secondary email' do
- user_secondary
- end
-
- step 'I see author based on primary email' do
- check_author_link(sample_commit.author_email, user_primary)
- end
-
- step 'I see author based on secondary email' do
- check_author_link(sample_commit.author_email, user_secondary)
- end
-
- def check_author_link(email, user)
- author_link = find('.commit-author-link')
-
- expect(author_link['href']).to eq user_path(user)
- expect(author_link['title']).to eq email
- expect(find('.commit-author-name').text).to eq user.name
- end
-
- def user_primary
- @user_primary ||= create(:user, email: 'dmitriy.zaporozhets@gmail.com')
- end
-
- def user_secondary
- @user_secondary ||= begin
- user = create(:user, email: 'dzaporozhets@example.com')
- create(:email, { user: user, email: 'dmitriy.zaporozhets@gmail.com' })
- user
- end
- 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/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..a989394ad91 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_updated: commit.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/entities.rb b/lib/api/entities.rb
index e8dd61e493f..803b48dd88a 100644
--- a/lib/api/entities.rb
+++ b/lib/api/entities.rb
@@ -320,7 +320,10 @@ module API
end
class IssueBasic < ProjectEntity
- expose :label_names, as: :labels
+ expose :labels do |issue, options|
+ # Avoids an N+1 query since labels are preloaded
+ issue.labels.map(&:title).sort
+ end
expose :milestone, using: Entities::Milestone
expose :assignees, :author, using: Entities::UserBasic
@@ -329,13 +332,32 @@ module API
end
expose :user_notes_count
- expose :upvotes, :downvotes
+ expose :upvotes do |issue, options|
+ if options[:issuable_metadata]
+ # Avoids an N+1 query when metadata is included
+ options[:issuable_metadata][issue.id].upvotes
+ else
+ issue.upvotes
+ end
+ end
+ expose :downvotes do |issue, options|
+ if options[:issuable_metadata]
+ # Avoids an N+1 query when metadata is included
+ options[:issuable_metadata][issue.id].downvotes
+ else
+ issue.downvotes
+ end
+ end
expose :due_date
expose :confidential
expose :web_url do |issue, options|
Gitlab::UrlBuilder.build(issue)
end
+
+ expose :time_stats, using: 'API::Entities::IssuableTimeStats' do |issue|
+ issue
+ end
end
class Issue < IssueBasic
@@ -365,10 +387,22 @@ module API
end
class IssuableTimeStats < Grape::Entity
+ format_with(:time_tracking_formatter) do |time_spent|
+ Gitlab::TimeTrackingFormatter.output(time_spent)
+ end
+
expose :time_estimate
expose :total_time_spent
expose :human_time_estimate
- expose :human_total_time_spent
+
+ with_options(format_with: :time_tracking_formatter) do
+ expose :total_time_spent, as: :human_total_time_spent
+ end
+
+ def total_time_spent
+ # Avoids an N+1 query since timelogs are preloaded
+ object.timelogs.map(&:time_spent).sum
+ end
end
class ExternalIssue < Grape::Entity
@@ -418,6 +452,10 @@ module API
expose :web_url do |merge_request, options|
Gitlab::UrlBuilder.build(merge_request)
end
+
+ expose :time_stats, using: 'API::Entities::IssuableTimeStats' do |merge_request|
+ merge_request
+ end
end
class MergeRequest < MergeRequestBasic
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/files.rb b/lib/api/files.rb
index e2ac7142bc4..1598d3c00b8 100644
--- a/lib/api/files.rb
+++ b/lib/api/files.rb
@@ -1,5 +1,7 @@
module API
class Files < Grape::API
+ FILE_ENDPOINT_REQUIREMENTS = API::PROJECT_ENDPOINT_REQUIREMENTS.merge(file_path: API::NO_SLASH_URL_PART_REGEX)
+
# Prevents returning plain/text responses for files with .txt extension
after_validation { content_type "application/json" }
@@ -58,13 +60,13 @@ module API
params do
requires :id, type: String, desc: 'The project ID'
end
- resource :projects, requirements: { id: %r{[^/]+} } do
+ resource :projects, requirements: FILE_ENDPOINT_REQUIREMENTS do
desc 'Get raw file contents from the repository'
params do
requires :file_path, type: String, desc: 'The url encoded path to the file. Ex. lib%2Fclass%2Erb'
requires :ref, type: String, desc: 'The name of branch, tag commit'
end
- get ":id/repository/files/:file_path/raw" do
+ get ":id/repository/files/:file_path/raw", requirements: FILE_ENDPOINT_REQUIREMENTS do
assign_file_vars!
send_git_blob @repo, @blob
@@ -75,7 +77,7 @@ module API
requires :file_path, type: String, desc: 'The url encoded path to the file. Ex. lib%2Fclass%2Erb'
requires :ref, type: String, desc: 'The name of branch, tag or commit'
end
- get ":id/repository/files/:file_path", requirements: { file_path: /.+/ } do
+ get ":id/repository/files/:file_path", requirements: FILE_ENDPOINT_REQUIREMENTS do
assign_file_vars!
{
@@ -95,7 +97,7 @@ module API
params do
use :extended_file_params
end
- post ":id/repository/files/:file_path", requirements: { file_path: /.+/ } do
+ post ":id/repository/files/:file_path", requirements: FILE_ENDPOINT_REQUIREMENTS do
authorize! :push_code, user_project
file_params = declared_params(include_missing: false)
@@ -113,7 +115,7 @@ module API
params do
use :extended_file_params
end
- put ":id/repository/files/:file_path", requirements: { file_path: /.+/ } do
+ put ":id/repository/files/:file_path", requirements: FILE_ENDPOINT_REQUIREMENTS do
authorize! :push_code, user_project
file_params = declared_params(include_missing: false)
@@ -137,7 +139,7 @@ module API
params do
use :simple_file_params
end
- delete ":id/repository/files/:file_path", requirements: { file_path: /.+/ } do
+ delete ":id/repository/files/:file_path", requirements: FILE_ENDPOINT_REQUIREMENTS do
authorize! :push_code, user_project
file_params = declared_params(include_missing: false)
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 e56427304a6..8c494a54329 100644
--- a/lib/api/groups.rb
+++ b/lib/api/groups.rb
@@ -7,7 +7,11 @@ module API
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'
@@ -118,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..3d377fdb9eb 100644
--- a/lib/api/helpers.rb
+++ b/lib/api/helpers.rb
@@ -11,6 +11,27 @@ 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_updated: nil)
+ last_updated ||= resource.updated_at
+
+ check_unmodified_since!(last_updated)
+
+ 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/helpers/runner.rb b/lib/api/helpers/runner.rb
index f8645e364ce..282af32ca94 100644
--- a/lib/api/helpers/runner.rb
+++ b/lib/api/helpers/runner.rb
@@ -1,6 +1,8 @@
module API
module Helpers
module Runner
+ include Gitlab::CurrentSettings
+
JOB_TOKEN_HEADER = 'HTTP_JOB_TOKEN'.freeze
JOB_TOKEN_PARAM = :token
UPDATE_RUNNER_EVERY = 10 * 60
diff --git a/lib/api/issues.rb b/lib/api/issues.rb
index 4cec1145f3a..0297023226f 100644
--- a/lib/api/issues.rb
+++ b/lib/api/issues.rb
@@ -4,6 +4,8 @@ module API
before { authenticate! }
+ helpers ::Gitlab::IssuableMetadata
+
helpers do
def find_issues(args = {})
args = params.merge(args)
@@ -13,6 +15,7 @@ module API
args[:label_name] = args.delete(:labels)
issues = IssuesFinder.new(current_user, args).execute
+ .preload(:assignees, :labels, :notes, :timelogs)
issues.reorder(args[:order_by] => args[:sort])
end
@@ -65,7 +68,13 @@ module API
get do
issues = find_issues
- present paginate(issues), with: Entities::IssueBasic, current_user: current_user
+ options = {
+ with: Entities::IssueBasic,
+ current_user: current_user,
+ issuable_metadata: issuable_meta_data(issues, 'Issue')
+ }
+
+ present paginate(issues), options
end
end
@@ -86,7 +95,13 @@ module API
issues = find_issues(group_id: group.id)
- present paginate(issues), with: Entities::IssueBasic, current_user: current_user
+ options = {
+ with: Entities::IssueBasic,
+ current_user: current_user,
+ issuable_metadata: issuable_meta_data(issues, 'Issue')
+ }
+
+ present paginate(issues), options
end
end
@@ -109,7 +124,14 @@ module API
issues = find_issues(project_id: project.id)
- present paginate(issues), with: Entities::IssueBasic, current_user: current_user, project: user_project
+ options = {
+ with: Entities::IssueBasic,
+ current_user: current_user,
+ project: user_project,
+ issuable_metadata: issuable_meta_data(issues, 'Issue')
+ }
+
+ present paginate(issues), options
end
desc 'Get a single project issue' do
@@ -230,8 +252,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..eec8d9357aa 100644
--- a/lib/api/merge_requests.rb
+++ b/lib/api/merge_requests.rb
@@ -21,7 +21,7 @@ module API
return merge_requests if args[:view] == 'simple'
merge_requests
- .preload(:notes, :author, :assignee, :milestone, :merge_request_diff, :labels)
+ .preload(:notes, :author, :assignee, :milestone, :merge_request_diff, :labels, :timelogs)
end
params :merge_requests_params do
@@ -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..912415e3a7f 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_updated: commit.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/email_template_interceptor.rb b/lib/email_template_interceptor.rb
index 63f9f8d7a5a..f2bf3d0fb2b 100644
--- a/lib/email_template_interceptor.rb
+++ b/lib/email_template_interceptor.rb
@@ -1,6 +1,6 @@
# Read about interceptors in http://guides.rubyonrails.org/action_mailer_basics.html#intercepting-emails
class EmailTemplateInterceptor
- include Gitlab::CurrentSettings
+ extend Gitlab::CurrentSettings
def self.delivering_email(message)
# Remove HTML part if HTML emails are disabled.
diff --git a/lib/github/import.rb b/lib/github/import.rb
index 7b848081e85..9354e142d3d 100644
--- a/lib/github/import.rb
+++ b/lib/github/import.rb
@@ -226,49 +226,51 @@ module Github
while url
response = Github::Client.new(options).get(url, state: :all, sort: :created, direction: :asc)
- response.body.each do |raw|
- representation = Github::Representation::Issue.new(raw, options)
+ response.body.each { |raw| populate_issue(raw) }
- begin
- # Every pull request is an issue, but not every issue
- # is a pull request. For this reason, "shared" actions
- # for both features, like manipulating assignees, labels
- # and milestones, are provided within the Issues API.
- if representation.pull_request?
- next unless representation.has_labels?
-
- merge_request = MergeRequest.find_by!(target_project_id: project.id, iid: representation.iid)
- merge_request.update_attribute(:label_ids, label_ids(representation.labels))
- else
- next if Issue.where(iid: representation.iid, project_id: project.id).exists?
-
- author_id = user_id(representation.author, project.creator_id)
- issue = Issue.new
- issue.iid = representation.iid
- issue.project_id = project.id
- issue.title = representation.title
- issue.description = format_description(representation.description, representation.author)
- issue.state = representation.state
- issue.label_ids = label_ids(representation.labels)
- issue.milestone_id = milestone_id(representation.milestone)
- issue.author_id = author_id
- issue.assignee_ids = [user_id(representation.assignee)]
- issue.created_at = representation.created_at
- issue.updated_at = representation.updated_at
- issue.save!(validate: false)
-
- # Fetch comments
- if representation.has_comments?
- comments_url = "/repos/#{repo}/issues/#{issue.iid}/comments"
- fetch_comments(issue, :comment, comments_url)
- end
- end
- rescue => e
- error(:issue, representation.url, e.message)
+ url = response.rels[:next]
+ end
+ end
+
+ def populate_issue(raw)
+ representation = Github::Representation::Issue.new(raw, options)
+
+ begin
+ # Every pull request is an issue, but not every issue
+ # is a pull request. For this reason, "shared" actions
+ # for both features, like manipulating assignees, labels
+ # and milestones, are provided within the Issues API.
+ if representation.pull_request?
+ return unless representation.has_labels?
+
+ merge_request = MergeRequest.find_by!(target_project_id: project.id, iid: representation.iid)
+ merge_request.update_attribute(:label_ids, label_ids(representation.labels))
+ else
+ return if Issue.where(iid: representation.iid, project_id: project.id).exists?
+
+ author_id = user_id(representation.author, project.creator_id)
+ issue = Issue.new
+ issue.iid = representation.iid
+ issue.project_id = project.id
+ issue.title = representation.title
+ issue.description = format_description(representation.description, representation.author)
+ issue.state = representation.state
+ issue.label_ids = label_ids(representation.labels)
+ issue.milestone_id = milestone_id(representation.milestone)
+ issue.author_id = author_id
+ issue.assignee_ids = [user_id(representation.assignee)]
+ issue.created_at = representation.created_at
+ issue.updated_at = representation.updated_at
+ issue.save!(validate: false)
+
+ # Fetch comments
+ if representation.has_comments?
+ comments_url = "/repos/#{repo}/issues/#{issue.iid}/comments"
+ fetch_comments(issue, :comment, comments_url)
end
end
-
- url = response.rels[:next]
+ rescue => e
+ error(:issue, representation.url, e.message)
end
end
diff --git a/lib/gitlab/asciidoc.rb b/lib/gitlab/asciidoc.rb
index 3d41ac76406..cead1c7eacd 100644
--- a/lib/gitlab/asciidoc.rb
+++ b/lib/gitlab/asciidoc.rb
@@ -6,6 +6,8 @@ module Gitlab
# Parser/renderer for the AsciiDoc format that uses Asciidoctor and filters
# the resulting HTML through HTML pipeline filters.
module Asciidoc
+ extend Gitlab::CurrentSettings
+
DEFAULT_ADOC_ATTRS = [
'showtitle', 'idprefix=user-content-', 'idseparator=-', 'env=gitlab',
'env-gitlab', 'source-highlighter=html-pipeline', 'icons=font'
diff --git a/lib/gitlab/auth.rb b/lib/gitlab/auth.rb
index 8cb4060cd97..1790f380c33 100644
--- a/lib/gitlab/auth.rb
+++ b/lib/gitlab/auth.rb
@@ -19,6 +19,8 @@ module Gitlab
OPTIONAL_SCOPES = (AVAILABLE_SCOPES + OPENID_SCOPES - DEFAULT_SCOPES).freeze
class << self
+ include Gitlab::CurrentSettings
+
def find_for_git_client(login, password, project:, ip:)
raise "Must provide an IP for rate limiting" if ip.nil?
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/ci/config/entry/attributable.rb b/lib/gitlab/ci/config/entry/attributable.rb
index 1c8b55ee4c4..3e87a09704e 100644
--- a/lib/gitlab/ci/config/entry/attributable.rb
+++ b/lib/gitlab/ci/config/entry/attributable.rb
@@ -8,6 +8,10 @@ module Gitlab
class_methods do
def attributes(*attributes)
attributes.flatten.each do |attribute|
+ if method_defined?(attribute)
+ raise ArgumentError, 'Method already defined!'
+ end
+
define_method(attribute) do
return unless config.is_a?(Hash)
diff --git a/lib/gitlab/ci/config/entry/configurable.rb b/lib/gitlab/ci/config/entry/configurable.rb
index e05aca9881b..68b6742385a 100644
--- a/lib/gitlab/ci/config/entry/configurable.rb
+++ b/lib/gitlab/ci/config/entry/configurable.rb
@@ -15,9 +15,10 @@ module Gitlab
#
module Configurable
extend ActiveSupport::Concern
- include Validatable
included do
+ include Validatable
+
validations do
validates :config, type: Hash
end
diff --git a/lib/gitlab/ci/config/entry/job.rb b/lib/gitlab/ci/config/entry/job.rb
index 32f5c6ab142..91aac6df4b1 100644
--- a/lib/gitlab/ci/config/entry/job.rb
+++ b/lib/gitlab/ci/config/entry/job.rb
@@ -59,10 +59,10 @@ module Gitlab
entry :services, Entry::Services,
description: 'Services that will be used to execute this job.'
- entry :only, Entry::Trigger,
+ entry :only, Entry::Policy,
description: 'Refs policy this job will be executed for.'
- entry :except, Entry::Trigger,
+ entry :except, Entry::Policy,
description: 'Refs policy this job will be executed for.'
entry :variables, Entry::Variables,
diff --git a/lib/gitlab/ci/config/entry/node.rb b/lib/gitlab/ci/config/entry/node.rb
index a6a914d79c1..c868943c42e 100644
--- a/lib/gitlab/ci/config/entry/node.rb
+++ b/lib/gitlab/ci/config/entry/node.rb
@@ -16,8 +16,9 @@ module Gitlab
@metadata = metadata
@entries = {}
- @validator = self.class.validator.new(self)
- @validator.validate(:new)
+ self.class.aspects.to_a.each do |aspect|
+ instance_exec(&aspect)
+ end
end
def [](key)
@@ -47,7 +48,7 @@ module Gitlab
end
def errors
- @validator.messages + descendants.flat_map(&:errors)
+ []
end
def value
@@ -70,6 +71,13 @@ module Gitlab
true
end
+ def location
+ name = @key.presence || self.class.name.to_s.demodulize
+ .underscore.humanize.downcase
+
+ ancestors.map(&:key).append(name).compact.join(':')
+ end
+
def inspect
val = leaf? ? config : descendants
unspecified = specified? ? '' : '(unspecified) '
@@ -79,8 +87,8 @@ module Gitlab
def self.default
end
- def self.validator
- Validator
+ def self.aspects
+ @aspects ||= []
end
end
end
diff --git a/lib/gitlab/ci/config/entry/policy.rb b/lib/gitlab/ci/config/entry/policy.rb
new file mode 100644
index 00000000000..3cdae1cee4f
--- /dev/null
+++ b/lib/gitlab/ci/config/entry/policy.rb
@@ -0,0 +1,31 @@
+module Gitlab
+ module Ci
+ class Config
+ module Entry
+ ##
+ # Entry that represents an only/except trigger policy for the job.
+ #
+ class Policy < Simplifiable
+ strategy :RefsPolicy, if: -> (config) { config.is_a?(Array) }
+
+ class RefsPolicy < Entry::Node
+ include Entry::Validatable
+
+ validations do
+ validates :config, array_of_strings_or_regexps: true
+ end
+ end
+
+ class UnknownStrategy < Entry::Node
+ def errors
+ ["#{location} has to be either an array of conditions or a hash"]
+ end
+ end
+
+ def self.default
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/ci/config/entry/simplifiable.rb b/lib/gitlab/ci/config/entry/simplifiable.rb
new file mode 100644
index 00000000000..12764629686
--- /dev/null
+++ b/lib/gitlab/ci/config/entry/simplifiable.rb
@@ -0,0 +1,43 @@
+module Gitlab
+ module Ci
+ class Config
+ module Entry
+ class Simplifiable < SimpleDelegator
+ EntryStrategy = Struct.new(:name, :condition)
+
+ def initialize(config, **metadata)
+ unless self.class.const_defined?(:UnknownStrategy)
+ raise ArgumentError, 'UndefinedStrategy not available!'
+ end
+
+ strategy = self.class.strategies.find do |variant|
+ variant.condition.call(config)
+ end
+
+ entry = self.class.entry_class(strategy)
+
+ super(entry.new(config, metadata))
+ end
+
+ def self.strategy(name, **opts)
+ EntryStrategy.new(name, opts.fetch(:if)).tap do |strategy|
+ strategies.append(strategy)
+ end
+ end
+
+ def self.strategies
+ @strategies ||= []
+ end
+
+ def self.entry_class(strategy)
+ if strategy.present?
+ self.const_get(strategy.name)
+ else
+ self::UnknownStrategy
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/ci/config/entry/trigger.rb b/lib/gitlab/ci/config/entry/trigger.rb
deleted file mode 100644
index 16b234e6c59..00000000000
--- a/lib/gitlab/ci/config/entry/trigger.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-module Gitlab
- module Ci
- class Config
- module Entry
- ##
- # Entry that represents a trigger policy for the job.
- #
- class Trigger < Node
- include Validatable
-
- validations do
- validates :config, array_of_strings_or_regexps: true
- end
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/ci/config/entry/validatable.rb b/lib/gitlab/ci/config/entry/validatable.rb
index f7f1b111571..5ced778d311 100644
--- a/lib/gitlab/ci/config/entry/validatable.rb
+++ b/lib/gitlab/ci/config/entry/validatable.rb
@@ -5,6 +5,17 @@ module Gitlab
module Validatable
extend ActiveSupport::Concern
+ def self.included(node)
+ node.aspects.append -> do
+ @validator = self.class.validator.new(self)
+ @validator.validate(:new)
+ end
+ end
+
+ def errors
+ @validator.messages + descendants.flat_map(&:errors)
+ end
+
class_methods do
def validator
@validator ||= Class.new(Entry::Validator).tap do |validator|
diff --git a/lib/gitlab/ci/config/entry/validator.rb b/lib/gitlab/ci/config/entry/validator.rb
index 55343005fe3..2df23a3edcd 100644
--- a/lib/gitlab/ci/config/entry/validator.rb
+++ b/lib/gitlab/ci/config/entry/validator.rb
@@ -8,7 +8,6 @@ module Gitlab
def initialize(entry)
super(entry)
- @entry = entry
end
def messages
@@ -20,21 +19,6 @@ module Gitlab
def self.name
'Validator'
end
-
- private
-
- def location
- predecessors = ancestors.map(&:key).compact
- predecessors.append(key_name).join(':')
- end
-
- def key_name
- if key.blank?
- @entry.class.name.demodulize.underscore.humanize
- else
- key
- end
- end
end
end
end
diff --git a/lib/gitlab/current_settings.rb b/lib/gitlab/current_settings.rb
index 7fa02f3d7b3..642f0944354 100644
--- a/lib/gitlab/current_settings.rb
+++ b/lib/gitlab/current_settings.rb
@@ -1,5 +1,7 @@
module Gitlab
module CurrentSettings
+ extend self
+
def current_application_settings
if RequestStore.active?
RequestStore.fetch(:current_application_settings) { ensure_application_settings! }
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.rb b/lib/gitlab/database.rb
index e001d25e7b7..a6ec75da385 100644
--- a/lib/gitlab/database.rb
+++ b/lib/gitlab/database.rb
@@ -9,6 +9,14 @@ module Gitlab
ActiveRecord::Base.configurations[Rails.env]
end
+ def self.username
+ config['username'] || ENV['USER']
+ end
+
+ def self.database_name
+ config['database']
+ end
+
def self.adapter_name
config['adapter']
end
diff --git a/lib/gitlab/database/grant.rb b/lib/gitlab/database/grant.rb
new file mode 100644
index 00000000000..aee3981e79a
--- /dev/null
+++ b/lib/gitlab/database/grant.rb
@@ -0,0 +1,34 @@
+module Gitlab
+ module Database
+ # Model that can be used for querying permissions of a SQL user.
+ class Grant < ActiveRecord::Base
+ self.table_name =
+ if Database.postgresql?
+ 'information_schema.role_table_grants'
+ else
+ 'mysql.user'
+ end
+
+ def self.scope_to_current_user
+ if Database.postgresql?
+ where('grantee = user')
+ else
+ where("CONCAT(User, '@', Host) = current_user()")
+ end
+ end
+
+ # Returns true if the current user can create and execute triggers on the
+ # given table.
+ def self.create_and_execute_trigger?(table)
+ priv =
+ if Database.postgresql?
+ where(privilege_type: 'TRIGGER', table_name: table)
+ else
+ where(Trigger_priv: 'Y')
+ end
+
+ priv.scope_to_current_user.any?
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/database/migration_helpers.rb b/lib/gitlab/database/migration_helpers.rb
index b83e633c7ed..fb14798efe6 100644
--- a/lib/gitlab/database/migration_helpers.rb
+++ b/lib/gitlab/database/migration_helpers.rb
@@ -358,6 +358,8 @@ module Gitlab
raise 'rename_column_concurrently can not be run inside a transaction'
end
+ check_trigger_permissions!(table)
+
old_col = column_for(table, old)
new_type = type || old_col.type
@@ -430,6 +432,8 @@ module Gitlab
def cleanup_concurrent_column_rename(table, old, new)
trigger_name = rename_trigger_name(table, old, new)
+ check_trigger_permissions!(table)
+
if Database.postgresql?
remove_rename_triggers_for_postgresql(table, trigger_name)
else
@@ -485,14 +489,14 @@ module Gitlab
# Removes the triggers used for renaming a PostgreSQL column concurrently.
def remove_rename_triggers_for_postgresql(table, trigger)
- execute("DROP TRIGGER #{trigger} ON #{table}")
- execute("DROP FUNCTION #{trigger}()")
+ execute("DROP TRIGGER IF EXISTS #{trigger} ON #{table}")
+ execute("DROP FUNCTION IF EXISTS #{trigger}()")
end
# Removes the triggers used for renaming a MySQL column concurrently.
def remove_rename_triggers_for_mysql(trigger)
- execute("DROP TRIGGER #{trigger}_insert")
- execute("DROP TRIGGER #{trigger}_update")
+ execute("DROP TRIGGER IF EXISTS #{trigger}_insert")
+ execute("DROP TRIGGER IF EXISTS #{trigger}_update")
end
# Returns the (base) name to use for triggers when renaming columns.
@@ -611,6 +615,44 @@ module Gitlab
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
+
+ def check_trigger_permissions!(table)
+ unless Grant.create_and_execute_trigger?(table)
+ dbname = Database.database_name
+ user = Database.username
+
+ raise <<-EOF
+Your database user is not allowed to create, drop, or execute triggers on the
+table #{table}.
+
+If you are using PostgreSQL you can solve this by logging in to the GitLab
+database (#{dbname}) using a super user and running:
+
+ ALTER #{user} WITH SUPERUSER
+
+For MySQL you instead need to run:
+
+ GRANT ALL PRIVILEGES ON *.* TO #{user}@'%'
+
+Both queries will grant the user super user permissions, ensuring you don't run
+into similar problems in the future (e.g. when new tables are created).
+ EOF
+ end
+ end
end
end
end
diff --git a/lib/gitlab/git/repository.rb b/lib/gitlab/git/repository.rb
index b835dec24eb..554e40dc8a6 100644
--- a/lib/gitlab/git/repository.rb
+++ b/lib/gitlab/git/repository.rb
@@ -17,6 +17,7 @@ module Gitlab
NoRepository = Class.new(StandardError)
InvalidBlobName = Class.new(StandardError)
InvalidRef = Class.new(StandardError)
+ GitError = Class.new(StandardError)
class << self
# Unlike `new`, `create` takes the storage path, not the storage name
@@ -46,6 +47,9 @@ module Gitlab
# Directory name of repo
attr_reader :name
+ # Relative path of repo
+ attr_reader :relative_path
+
# Rugged repo object
attr_reader :rugged
@@ -246,6 +250,13 @@ module Gitlab
branch_names + tag_names
end
+ # Returns an Array of all ref names, except when it's matching pattern
+ #
+ # regexp - The pattern for ref names we don't want
+ def all_ref_names_except(regexp)
+ rugged.references.reject { |ref| ref.name =~ regexp }.map(&:name)
+ end
+
# Discovers the default branch based on the repository's available branches
#
# - If no branches are present, returns nil
@@ -439,8 +450,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
@@ -591,6 +602,23 @@ module Gitlab
rugged.branches.delete(branch_name)
end
+ def delete_refs(*ref_names)
+ instructions = ref_names.map do |ref|
+ "delete #{ref}\x00\x00"
+ end
+
+ command = %W[#{Gitlab.config.git.bin_path} update-ref --stdin -z]
+ message, status = Gitlab::Popen.popen(
+ command,
+ path) do |stdin|
+ stdin.write(instructions.join)
+ end
+
+ unless status.zero?
+ raise GitError.new("Could not delete refs #{ref_names}: #{message}")
+ end
+ end
+
# Create a new branch named **ref+ based on **stat_point+, HEAD by default
#
# Examples:
diff --git a/lib/gitlab/gitaly_client/commit_service.rb b/lib/gitlab/gitaly_client/commit_service.rb
index 57f42bd35ee..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,
diff --git a/lib/gitlab/gitaly_client/repository_service.rb b/lib/gitlab/gitaly_client/repository_service.rb
index a74a6dc6e78..177a1284f38 100644
--- a/lib/gitlab/gitaly_client/repository_service.rb
+++ b/lib/gitlab/gitaly_client/repository_service.rb
@@ -37,6 +37,22 @@ module Gitlab
request = Gitaly::ApplyGitattributesRequest.new(repository: @gitaly_repo, revision: revision)
GitalyClient.call(@storage, :repository_service, :apply_gitattributes, request)
end
+
+ def fetch_remote(remote, ssh_auth: nil, forced: false, no_tags: false)
+ request = Gitaly::FetchRemoteRequest.new(repository: @gitaly_repo, remote: remote, force: forced, no_tags: no_tags)
+
+ if ssh_auth&.ssh_import?
+ if ssh_auth.ssh_key_auth? && ssh_auth.ssh_private_key.present?
+ request.ssh_key = ssh_auth.ssh_private_key
+ end
+
+ if ssh_auth.ssh_known_hosts.present?
+ request.known_hosts = ssh_auth.ssh_known_hosts
+ end
+ end
+
+ GitalyClient.call(@storage, :repository_service, :fetch_remote, request)
+ end
end
end
end
diff --git a/lib/gitlab/gon_helper.rb b/lib/gitlab/gon_helper.rb
index 2d1ae6a5925..9bcc579278f 100644
--- a/lib/gitlab/gon_helper.rb
+++ b/lib/gitlab/gon_helper.rb
@@ -3,6 +3,7 @@
module Gitlab
module GonHelper
include WebpackHelper
+ include Gitlab::CurrentSettings
def add_gon_variables
gon.api_version = 'v4'
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 e5d4bb686e7..78795dd3d92 100644
--- a/lib/gitlab/import_export/import_export.yml
+++ b/lib/gitlab/import_export/import_export.yml
@@ -138,3 +138,7 @@ methods:
- :target_branch_sha
project:
- :description_html
+ events:
+ - :action
+ push_event_payload:
+ - :action \ No newline at end of file
diff --git a/lib/gitlab/metrics/influx_db.rb b/lib/gitlab/metrics/influx_db.rb
index d7c56463aac..7b06bb953aa 100644
--- a/lib/gitlab/metrics/influx_db.rb
+++ b/lib/gitlab/metrics/influx_db.rb
@@ -1,7 +1,7 @@
module Gitlab
module Metrics
module InfluxDb
- extend Gitlab::CurrentSettings
+ include Gitlab::CurrentSettings
extend self
MUTEX = Mutex.new
diff --git a/lib/gitlab/performance_bar.rb b/lib/gitlab/performance_bar.rb
index 56112ec2301..e73245b82c1 100644
--- a/lib/gitlab/performance_bar.rb
+++ b/lib/gitlab/performance_bar.rb
@@ -1,6 +1,6 @@
module Gitlab
module PerformanceBar
- include Gitlab::CurrentSettings
+ extend Gitlab::CurrentSettings
ALLOWED_USER_IDS_KEY = 'performance_bar_allowed_user_ids:v2'.freeze
EXPIRY_TIME = 5.minutes
diff --git a/lib/gitlab/polling_interval.rb b/lib/gitlab/polling_interval.rb
index f0c50584f07..4780675a492 100644
--- a/lib/gitlab/polling_interval.rb
+++ b/lib/gitlab/polling_interval.rb
@@ -1,6 +1,6 @@
module Gitlab
class PollingInterval
- include Gitlab::CurrentSettings
+ extend Gitlab::CurrentSettings
HEADER_NAME = 'Poll-Interval'.freeze
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/protocol_access.rb b/lib/gitlab/protocol_access.rb
index 21aefc884be..09fa14764e6 100644
--- a/lib/gitlab/protocol_access.rb
+++ b/lib/gitlab/protocol_access.rb
@@ -1,5 +1,7 @@
module Gitlab
module ProtocolAccess
+ extend Gitlab::CurrentSettings
+
def self.allowed?(protocol)
if protocol == 'web'
true
diff --git a/lib/gitlab/recaptcha.rb b/lib/gitlab/recaptcha.rb
index 4bc76ea033f..c463dd487a0 100644
--- a/lib/gitlab/recaptcha.rb
+++ b/lib/gitlab/recaptcha.rb
@@ -1,5 +1,7 @@
module Gitlab
module Recaptcha
+ extend Gitlab::CurrentSettings
+
def self.load_configurations!
if current_application_settings.recaptcha_enabled
::Recaptcha.configure do |config|
diff --git a/lib/gitlab/sentry.rb b/lib/gitlab/sentry.rb
index 2442c2ded3b..f6bdd6cf0fe 100644
--- a/lib/gitlab/sentry.rb
+++ b/lib/gitlab/sentry.rb
@@ -1,5 +1,7 @@
module Gitlab
module Sentry
+ extend Gitlab::CurrentSettings
+
def self.enabled?
Rails.env.production? && current_application_settings.sentry_enabled?
end
diff --git a/lib/gitlab/shell.rb b/lib/gitlab/shell.rb
index 280a9abf03e..81ecdf43ef9 100644
--- a/lib/gitlab/shell.rb
+++ b/lib/gitlab/shell.rb
@@ -98,33 +98,24 @@ module Gitlab
# Fetch remote for repository
#
- # name - project path with namespace
+ # repository - an instance of Git::Repository
# remote - remote name
# forced - should we use --force flag?
# no_tags - should we use --no-tags flag?
#
# Ex.
- # fetch_remote("gitlab/gitlab-ci", "upstream")
+ # fetch_remote(my_repo, "upstream")
#
# Gitaly migration: https://gitlab.com/gitlab-org/gitaly/issues/387
- def fetch_remote(storage, name, remote, ssh_auth: nil, forced: false, no_tags: false)
- args = [gitlab_shell_projects_path, 'fetch-remote', storage, "#{name}.git", remote, "#{Gitlab.config.gitlab_shell.git_timeout}"]
- args << '--force' if forced
- args << '--no-tags' if no_tags
-
- vars = {}
-
- if ssh_auth&.ssh_import?
- if ssh_auth.ssh_key_auth? && ssh_auth.ssh_private_key.present?
- vars['GITLAB_SHELL_SSH_KEY'] = ssh_auth.ssh_private_key
- end
-
- if ssh_auth.ssh_known_hosts.present?
- vars['GITLAB_SHELL_KNOWN_HOSTS'] = ssh_auth.ssh_known_hosts
+ def fetch_remote(repository, remote, ssh_auth: nil, forced: false, no_tags: false)
+ gitaly_migrate(:fetch_remote) do |is_enabled|
+ if is_enabled
+ repository.gitaly_repository_client.fetch_remote(remote, ssh_auth: ssh_auth, forced: forced, no_tags: no_tags)
+ else
+ storage_path = Gitlab.config.repositories.storages[repository.storage]["path"]
+ local_fetch_remote(storage_path, repository.relative_path, remote, ssh_auth: ssh_auth, forced: forced, no_tags: no_tags)
end
end
-
- gitlab_shell_fast_execute_raise_error(args, vars)
end
# Move repository
@@ -302,6 +293,26 @@ module Gitlab
private
+ def local_fetch_remote(storage, name, remote, ssh_auth: nil, forced: false, no_tags: false)
+ args = [gitlab_shell_projects_path, 'fetch-remote', storage, name, remote, "#{Gitlab.config.gitlab_shell.git_timeout}"]
+ args << '--force' if forced
+ args << '--no-tags' if no_tags
+
+ vars = {}
+
+ if ssh_auth&.ssh_import?
+ if ssh_auth.ssh_key_auth? && ssh_auth.ssh_private_key.present?
+ vars['GITLAB_SHELL_SSH_KEY'] = ssh_auth.ssh_private_key
+ end
+
+ if ssh_auth.ssh_known_hosts.present?
+ vars['GITLAB_SHELL_KNOWN_HOSTS'] = ssh_auth.ssh_known_hosts
+ end
+ end
+
+ gitlab_shell_fast_execute_raise_error(args, vars)
+ end
+
def gitlab_shell_fast_execute(cmd)
output, status = gitlab_shell_fast_execute_helper(cmd)
@@ -325,5 +336,13 @@ module Gitlab
# from wasting I/O by searching through GEM_PATH
Bundler.with_original_env { Popen.popen(cmd, nil, vars) }
end
+
+ def gitaly_migrate(method, &block)
+ Gitlab::GitalyClient.migrate(method, &block)
+ rescue GRPC::NotFound, GRPC::BadStatus => e
+ # Old Popen code returns [Error, output] to the caller, so we
+ # need to do the same here...
+ raise Error, e
+ end
end
end
diff --git a/lib/gitlab/sql/pattern.rb b/lib/gitlab/sql/pattern.rb
new file mode 100644
index 00000000000..b42bc67ccfc
--- /dev/null
+++ b/lib/gitlab/sql/pattern.rb
@@ -0,0 +1,23 @@
+module Gitlab
+ module SQL
+ module Pattern
+ extend ActiveSupport::Concern
+
+ MIN_CHARS_FOR_PARTIAL_MATCHING = 3
+
+ class_methods do
+ def to_pattern(query)
+ if partial_matching?(query)
+ "%#{sanitize_sql_like(query)}%"
+ else
+ sanitize_sql_like(query)
+ end
+ end
+
+ def partial_matching?(query)
+ query.length >= MIN_CHARS_FOR_PARTIAL_MATCHING
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/usage_data.rb b/lib/gitlab/usage_data.rb
index 748e0a29184..3cf26625108 100644
--- a/lib/gitlab/usage_data.rb
+++ b/lib/gitlab/usage_data.rb
@@ -1,8 +1,8 @@
module Gitlab
class UsageData
- include Gitlab::CurrentSettings
-
class << self
+ include Gitlab::CurrentSettings
+
def data(force_refresh: false)
Rails.cache.fetch('usage_data', force: force_refresh, expires_in: 2.weeks) { uncached_data }
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/cleanup.rake b/lib/tasks/gitlab/cleanup.rake
index f76bef5f4bf..8ae1b6a626a 100644
--- a/lib/tasks/gitlab/cleanup.rake
+++ b/lib/tasks/gitlab/cleanup.rake
@@ -111,7 +111,7 @@ namespace :gitlab do
next unless id > max_iid
project.deployments.find(id).create_ref
- rugged.references.delete(ref)
+ project.repository.delete_refs(ref)
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 1206302cb76..4d485108cf6 100644
--- a/lib/tasks/import.rake
+++ b/lib/tasks/import.rake
@@ -80,7 +80,7 @@ class GithubImport
end
def visibility_level
- @repo['private'] ? Gitlab::VisibilityLevel::PRIVATE : current_application_settings.default_project_visibility
+ @repo['private'] ? Gitlab::VisibilityLevel::PRIVATE : Gitlab::CurrentSettings.current_application_settings.default_project_visibility
end
end
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/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/scripts/static-analysis b/scripts/static-analysis
index e4f80e8fc6f..52529e64b30 100755
--- a/scripts/static-analysis
+++ b/scripts/static-analysis
@@ -3,7 +3,7 @@
require ::File.expand_path('../lib/gitlab/popen', __dir__)
tasks = [
- %w[bundle exec bundle-audit check --update --ignore CVE-2016-4658 CVE-2017-5029],
+ %w[bundle exec bundle-audit check --update],
%w[bundle exec rake config_lint],
%w[bundle exec rake flay],
%w[bundle exec rake haml_lint],
diff --git a/spec/controllers/admin/users_controller_spec.rb b/spec/controllers/admin/users_controller_spec.rb
index 3d21b695af4..aadd3317875 100644
--- a/spec/controllers/admin/users_controller_spec.rb
+++ b/spec/controllers/admin/users_controller_spec.rb
@@ -150,6 +150,18 @@ describe Admin::UsersController do
post :update, params
end
+ context 'when the admin changes his own password' do
+ it 'updates the password' do
+ expect { update_password(admin, 'AValidPassword1') }
+ .to change { admin.reload.encrypted_password }
+ end
+
+ it 'does not set the new password to expire immediately' do
+ expect { update_password(admin, 'AValidPassword1') }
+ .not_to change { admin.reload.password_expires_at }
+ end
+ end
+
context 'when the new password is valid' do
it 'redirects to the user' do
update_password(user, 'AValidPassword1')
@@ -158,15 +170,13 @@ describe Admin::UsersController do
end
it 'updates the password' do
- update_password(user, 'AValidPassword1')
-
- expect { user.reload }.to change { user.encrypted_password }
+ expect { update_password(user, 'AValidPassword1') }
+ .to change { user.reload.encrypted_password }
end
it 'sets the new password to expire immediately' do
- update_password(user, 'AValidPassword1')
-
- expect { user.reload }.to change { user.password_expires_at }.to(a_value <= Time.now)
+ expect { update_password(user, 'AValidPassword1') }
+ .to change { user.reload.password_expires_at }.to be_within(2.seconds).of(Time.now)
end
end
@@ -184,9 +194,8 @@ describe Admin::UsersController do
end
it 'does not update the password' do
- update_password(user, 'invalid')
-
- expect { user.reload }.not_to change { user.encrypted_password }
+ expect { update_password(user, 'invalid') }
+ .not_to change { user.reload.encrypted_password }
end
end
@@ -204,9 +213,8 @@ describe Admin::UsersController do
end
it 'does not update the password' do
- update_password(user, 'AValidPassword1', 'AValidPassword2')
-
- expect { user.reload }.not_to change { user.encrypted_password }
+ expect { update_password(user, 'AValidPassword1', 'AValidPassword2') }
+ .not_to change { user.reload.encrypted_password }
end
end
end
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/pages_controller_spec.rb b/spec/controllers/projects/pages_controller_spec.rb
index 4d0111302f3..83c7744a231 100644
--- a/spec/controllers/projects/pages_controller_spec.rb
+++ b/spec/controllers/projects/pages_controller_spec.rb
@@ -2,7 +2,7 @@ require 'spec_helper'
describe Projects::PagesController do
let(:user) { create(:user) }
- let(:project) { create(:project, :public, :access_requestable) }
+ let(:project) { create(:project, :public) }
let(:request_params) do
{
@@ -23,6 +23,17 @@ describe Projects::PagesController do
expect(response).to have_http_status(200)
end
+
+ context 'when the project is in a subgroup' do
+ let(:group) { create(:group, :nested) }
+ let(:project) { create(:project, namespace: group) }
+
+ it 'returns a 404 status code' do
+ get :show, request_params
+
+ expect(response).to have_http_status(404)
+ end
+ end
end
describe 'DELETE destroy' 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/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/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/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/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_author_spec.rb b/spec/features/issues/filtered_search/dropdown_author_spec.rb
index 975dc035f2d..3cec59050ab 100644
--- a/spec/features/issues/filtered_search/dropdown_author_spec.rb
+++ b/spec/features/issues/filtered_search/dropdown_author_spec.rb
@@ -6,7 +6,7 @@ describe 'Dropdown author', js: true do
let!(:project) { create(:project) }
let!(:user) { create(:user, name: 'administrator', username: 'root') }
let!(:user_john) { create(:user, name: 'John', username: 'th0mas') }
- let!(:user_jacob) { create(:user, name: 'Jacob', username: 'otter32') }
+ let!(:user_jacob) { create(:user, name: 'Jacob', username: 'ooter32') }
let(:filtered_search) { find('.filtered-search') }
let(:js_dropdown_author) { '#js-dropdown-author' }
@@ -82,31 +82,31 @@ describe 'Dropdown author', js: true do
end
it 'filters by name' do
- send_keys_to_filtered_search('ja')
+ send_keys_to_filtered_search('jac')
expect(dropdown_author_size).to eq(1)
end
it 'filters by case insensitive name' do
- send_keys_to_filtered_search('Ja')
+ send_keys_to_filtered_search('Jac')
expect(dropdown_author_size).to eq(1)
end
it 'filters by username with symbol' do
- send_keys_to_filtered_search('@ot')
+ send_keys_to_filtered_search('@oot')
expect(dropdown_author_size).to eq(2)
end
it 'filters by username without symbol' do
- send_keys_to_filtered_search('ot')
+ send_keys_to_filtered_search('oot')
expect(dropdown_author_size).to eq(2)
end
it 'filters by case insensitive username without symbol' do
- send_keys_to_filtered_search('OT')
+ send_keys_to_filtered_search('OOT')
expect(dropdown_author_size).to eq(2)
end
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/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/commit/rss_spec.rb b/spec/features/projects/commits/rss_spec.rb
index db958346f06..db958346f06 100644
--- a/spec/features/projects/commit/rss_spec.rb
+++ b/spec/features/projects/commits/rss_spec.rb
diff --git a/spec/features/projects/commits/user_browses_commits_spec.rb b/spec/features/projects/commits/user_browses_commits_spec.rb
new file mode 100644
index 00000000000..41f3c15a94c
--- /dev/null
+++ b/spec/features/projects/commits/user_browses_commits_spec.rb
@@ -0,0 +1,44 @@
+require 'spec_helper'
+
+describe 'User broweses commits' do
+ let(:user) { create(:user) }
+ let(:project) { create(:project, :repository, namespace: user.namespace) }
+
+ before do
+ project.add_master(user)
+ sign_in(user)
+ end
+
+ context 'primary email' do
+ it 'finds a commit by a primary email' do
+ user = create(:user, email: 'dmitriy.zaporozhets@gmail.com')
+
+ visit(project_commit_path(project, RepoHelpers.sample_commit.id))
+
+ check_author_link(RepoHelpers.sample_commit.author_email, user)
+ end
+ end
+
+ context 'secondary email' do
+ it 'finds a commit by a secondary email' do
+ user =
+ create(:user) do |user|
+ create(:email, { user: user, email: 'dmitriy.zaporozhets@gmail.com' })
+ end
+
+ visit(project_commit_path(project, RepoHelpers.sample_commit.parent_id))
+
+ check_author_link(RepoHelpers.sample_commit.author_email, user)
+ end
+ end
+end
+
+private
+
+def check_author_link(email, author)
+ author_link = find('.commit-author-link')
+
+ expect(author_link['href']).to eq(user_path(author))
+ expect(author_link['title']).to eq(email)
+ expect(find('.commit-author-name').text).to eq(author.name)
+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/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/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/fixtures/api/schemas/public_api/v4/issues.json b/spec/fixtures/api/schemas/public_api/v4/issues.json
index bd6bfc03199..8acd9488215 100644
--- a/spec/fixtures/api/schemas/public_api/v4/issues.json
+++ b/spec/fixtures/api/schemas/public_api/v4/issues.json
@@ -78,7 +78,13 @@
"downvotes": { "type": "integer" },
"due_date": { "type": ["date", "null"] },
"confidential": { "type": "boolean" },
- "web_url": { "type": "uri" }
+ "web_url": { "type": "uri" },
+ "time_stats": {
+ "time_estimate": { "type": "integer" },
+ "total_time_spent": { "type": "integer" },
+ "human_time_estimate": { "type": ["string", "null"] },
+ "human_total_time_spent": { "type": ["string", "null"] }
+ }
},
"required": [
"id", "iid", "project_id", "title", "description",
diff --git a/spec/fixtures/api/schemas/public_api/v4/merge_requests.json b/spec/fixtures/api/schemas/public_api/v4/merge_requests.json
index 60aa47c1259..31b3f4ba946 100644
--- a/spec/fixtures/api/schemas/public_api/v4/merge_requests.json
+++ b/spec/fixtures/api/schemas/public_api/v4/merge_requests.json
@@ -72,7 +72,13 @@
"user_notes_count": { "type": "integer" },
"should_remove_source_branch": { "type": ["boolean", "null"] },
"force_remove_source_branch": { "type": ["boolean", "null"] },
- "web_url": { "type": "uri" }
+ "web_url": { "type": "uri" },
+ "time_stats": {
+ "time_estimate": { "type": "integer" },
+ "total_time_spent": { "type": "integer" },
+ "human_time_estimate": { "type": ["string", "null"] },
+ "human_total_time_spent": { "type": ["string", "null"] }
+ }
},
"required": [
"id", "iid", "project_id", "title", "description",
diff --git a/spec/helpers/version_check_helper_spec.rb b/spec/helpers/version_check_helper_spec.rb
index 5eba03ef576..fa8cfda3b86 100644
--- a/spec/helpers/version_check_helper_spec.rb
+++ b/spec/helpers/version_check_helper_spec.rb
@@ -4,7 +4,7 @@ describe VersionCheckHelper do
describe '#version_status_badge' do
it 'should return nil if not dev environment and not enabled' do
allow(Rails.env).to receive(:production?) { false }
- allow(current_application_settings).to receive(:version_check_enabled) { false }
+ allow(helper.current_application_settings).to receive(:version_check_enabled) { false }
expect(helper.version_status_badge).to be(nil)
end
@@ -12,7 +12,7 @@ describe VersionCheckHelper do
context 'when production and enabled' do
before do
allow(Rails.env).to receive(:production?) { true }
- allow(current_application_settings).to receive(:version_check_enabled) { true }
+ allow(helper.current_application_settings).to receive(:version_check_enabled) { true }
allow_any_instance_of(VersionCheck).to receive(:url) { 'https://version.host.com/check.svg?gitlab_info=xxx' }
@image_tag = helper.version_status_badge
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/fly_out_nav_spec.js b/spec/javascripts/fly_out_nav_spec.js
index 2e81a1b056b..0847e463577 100644
--- a/spec/javascripts/fly_out_nav_spec.js
+++ b/spec/javascripts/fly_out_nav_spec.js
@@ -1,4 +1,3 @@
-import Cookies from 'js-cookie';
import {
calculateTop,
showSubLevelItems,
@@ -11,6 +10,7 @@ import {
getHideSubItemsInterval,
documentMouseMove,
getHeaderHeight,
+ setSidebar,
} from '~/fly_out_nav';
import bp from '~/breakpoints';
@@ -113,7 +113,6 @@ describe('Fly out sidebar navigation', () => {
clientX: el.getBoundingClientRect().left + 20,
clientY: el.getBoundingClientRect().top + 10,
});
- console.log(el);
expect(
getHideSubItemsInterval(),
@@ -283,7 +282,7 @@ describe('Fly out sidebar navigation', () => {
describe('canShowActiveSubItems', () => {
afterEach(() => {
- Cookies.remove('sidebar_collapsed');
+ setSidebar(null);
});
it('returns true by default', () => {
@@ -292,36 +291,23 @@ describe('Fly out sidebar navigation', () => {
).toBeTruthy();
});
- it('returns false when cookie is false & element is active', () => {
- Cookies.set('sidebar_collapsed', 'false');
+ it('returns false when active & expanded sidebar', () => {
+ const sidebar = document.createElement('div');
el.classList.add('active');
- expect(
- canShowActiveSubItems(el),
- ).toBeFalsy();
- });
-
- it('returns true when cookie is false & element is active', () => {
- Cookies.set('sidebar_collapsed', 'true');
- el.classList.add('active');
+ setSidebar(sidebar);
expect(
canShowActiveSubItems(el),
- ).toBeTruthy();
+ ).toBeFalsy();
});
- it('returns true when element is active & breakpoint is sm', () => {
- breakpointSize = 'sm';
+ it('returns true when active & collapsed sidebar', () => {
+ const sidebar = document.createElement('div');
+ sidebar.classList.add('sidebar-icons-only');
el.classList.add('active');
- expect(
- canShowActiveSubItems(el),
- ).toBeTruthy();
- });
-
- it('returns true when element is active & breakpoint is md', () => {
- breakpointSize = 'md';
- el.classList.add('active');
+ setSidebar(sidebar);
expect(
canShowActiveSubItems(el),
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/issue_show/components/edited_spec.js b/spec/javascripts/issue_show/components/edited_spec.js
index a0d0750ae34..2061def699b 100644
--- a/spec/javascripts/issue_show/components/edited_spec.js
+++ b/spec/javascripts/issue_show/components/edited_spec.js
@@ -46,4 +46,14 @@ describe('edited', () => {
expect(editedComponent.$el.querySelector('.author_link')).toBeFalsy();
expect(editedComponent.$el.querySelector('time')).toBeTruthy();
});
+
+ it('renders time ago tooltip at the bottom', () => {
+ const editedComponent = new EditedComponent({
+ propsData: {
+ updatedAt: '2017-05-15T12:31:04.428Z',
+ },
+ }).$mount();
+
+ expect(editedComponent.$el.querySelector('time').dataset.placement).toEqual('bottom');
+ });
});
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/monitoring/monitoring_spec.js b/spec/javascripts/monitoring/dashboard_spec.js
index 6c7b691baa4..752fdfb4614 100644
--- a/spec/javascripts/monitoring/monitoring_spec.js
+++ b/spec/javascripts/monitoring/dashboard_spec.js
@@ -1,21 +1,21 @@
import Vue from 'vue';
-import Monitoring from '~/monitoring/components/monitoring.vue';
+import Dashboard from '~/monitoring/components/dashboard.vue';
import { MonitorMockInterceptor } from './mock_data';
-describe('Monitoring', () => {
+describe('Dashboard', () => {
const fixtureName = 'environments/metrics/metrics.html.raw';
- let MonitoringComponent;
+ let DashboardComponent;
let component;
preloadFixtures(fixtureName);
beforeEach(() => {
loadFixtures(fixtureName);
- MonitoringComponent = Vue.extend(Monitoring);
+ DashboardComponent = Vue.extend(Dashboard);
});
describe('no metrics are available yet', () => {
it('shows a getting started empty state when no metrics are present', () => {
- component = new MonitoringComponent({
+ component = new DashboardComponent({
el: document.querySelector('#prometheus-graphs'),
});
@@ -36,7 +36,7 @@ describe('Monitoring', () => {
});
it('shows up a loading state', (done) => {
- component = new MonitoringComponent({
+ component = new DashboardComponent({
el: document.querySelector('#prometheus-graphs'),
});
component.$mount();
diff --git a/spec/javascripts/monitoring/monitoring_state_spec.js b/spec/javascripts/monitoring/dashboard_state_spec.js
index 4c0c558502f..e8f7042e131 100644
--- a/spec/javascripts/monitoring/monitoring_state_spec.js
+++ b/spec/javascripts/monitoring/dashboard_state_spec.js
@@ -1,9 +1,9 @@
import Vue from 'vue';
-import MonitoringState from '~/monitoring/components/monitoring_state.vue';
+import EmptyState from '~/monitoring/components/empty_state.vue';
import { statePaths } from './mock_data';
const createComponent = (propsData) => {
- const Component = Vue.extend(MonitoringState);
+ const Component = Vue.extend(EmptyState);
return new Component({
propsData,
@@ -14,7 +14,7 @@ function getTextFromNode(component, selector) {
return component.$el.querySelector(selector).firstChild.nodeValue.trim();
}
-describe('MonitoringState', () => {
+describe('EmptyState', () => {
describe('Computed props', () => {
it('currentState', () => {
const component = createComponent({
diff --git a/spec/javascripts/monitoring/monitoring_deployment_spec.js b/spec/javascripts/monitoring/graph/deployment_spec.js
index 5cc5b514824..c2ff38ffab9 100644
--- a/spec/javascripts/monitoring/monitoring_deployment_spec.js
+++ b/spec/javascripts/monitoring/graph/deployment_spec.js
@@ -1,9 +1,9 @@
import Vue from 'vue';
-import MonitoringState from '~/monitoring/components/monitoring_deployment.vue';
-import { deploymentData } from './mock_data';
+import GraphDeployment from '~/monitoring/components/graph/deployment.vue';
+import { deploymentData } from '../mock_data';
const createComponent = (propsData) => {
- const Component = Vue.extend(MonitoringState);
+ const Component = Vue.extend(GraphDeployment);
return new Component({
propsData,
diff --git a/spec/javascripts/monitoring/monitoring_flag_spec.js b/spec/javascripts/monitoring/graph/flag_spec.js
index 3861a95ff07..731076a7d2a 100644
--- a/spec/javascripts/monitoring/monitoring_flag_spec.js
+++ b/spec/javascripts/monitoring/graph/flag_spec.js
@@ -1,8 +1,8 @@
import Vue from 'vue';
-import MonitoringFlag from '~/monitoring/components/monitoring_flag.vue';
+import GraphFlag from '~/monitoring/components/graph/flag.vue';
const createComponent = (propsData) => {
- const Component = Vue.extend(MonitoringFlag);
+ const Component = Vue.extend(GraphFlag);
return new Component({
propsData,
@@ -14,7 +14,7 @@ function getCoordinate(component, selector, coordinate) {
return parseInt(coordinateVal, 10);
}
-describe('MonitoringFlag', () => {
+describe('GraphFlag', () => {
it('has a line and a circle located at the currentXCoordinate and currentYCoordinate', () => {
const component = createComponent({
currentXCoordinate: 200,
diff --git a/spec/javascripts/monitoring/monitoring_legends_spec.js b/spec/javascripts/monitoring/graph/legend_spec.js
index 4c69b81e650..e877832dffd 100644
--- a/spec/javascripts/monitoring/monitoring_legends_spec.js
+++ b/spec/javascripts/monitoring/graph/legend_spec.js
@@ -1,9 +1,9 @@
import Vue from 'vue';
-import MonitoringLegends from '~/monitoring/components/monitoring_legends.vue';
+import GraphLegend from '~/monitoring/components/graph/legend.vue';
import measurements from '~/monitoring/utils/measurements';
const createComponent = (propsData) => {
- const Component = Vue.extend(MonitoringLegends);
+ const Component = Vue.extend(GraphLegend);
return new Component({
propsData,
@@ -14,7 +14,7 @@ function getTextFromNode(component, selector) {
return component.$el.querySelector(selector).firstChild.nodeValue.trim();
}
-describe('MonitoringLegends', () => {
+describe('GraphLegend', () => {
describe('Computed props', () => {
it('textTransform', () => {
const component = createComponent({
diff --git a/spec/javascripts/monitoring/monitoring_row_spec.js b/spec/javascripts/monitoring/graph_row_spec.js
index a82480e8342..dd485473ccf 100644
--- a/spec/javascripts/monitoring/monitoring_row_spec.js
+++ b/spec/javascripts/monitoring/graph_row_spec.js
@@ -1,16 +1,21 @@
import Vue from 'vue';
-import MonitoringRow from '~/monitoring/components/monitoring_row.vue';
+import GraphRow from '~/monitoring/components/graph_row.vue';
+import MonitoringMixins from '~/monitoring/mixins/monitoring_mixins';
import { deploymentData, singleRowMetrics } from './mock_data';
const createComponent = (propsData) => {
- const Component = Vue.extend(MonitoringRow);
+ const Component = Vue.extend(GraphRow);
return new Component({
propsData,
}).$mount();
};
-describe('MonitoringRow', () => {
+describe('GraphRow', () => {
+ beforeEach(() => {
+ spyOn(MonitoringMixins.methods, 'formatDeployments').and.returnValue({});
+ });
+
describe('Computed props', () => {
it('bootstrapClass is set to col-md-6 when rowData is higher/equal to 2', () => {
const component = createComponent({
diff --git a/spec/javascripts/monitoring/monitoring_column_spec.js b/spec/javascripts/monitoring/graph_spec.js
index c423024dce0..6d6fe410113 100644
--- a/spec/javascripts/monitoring/monitoring_column_spec.js
+++ b/spec/javascripts/monitoring/graph_spec.js
@@ -1,39 +1,37 @@
import Vue from 'vue';
import _ from 'underscore';
-import MonitoringColumn from '~/monitoring/components/monitoring_column.vue';
+import Graph from '~/monitoring/components/graph.vue';
import MonitoringMixins from '~/monitoring/mixins/monitoring_mixins';
import eventHub from '~/monitoring/event_hub';
import { deploymentData, singleRowMetrics } from './mock_data';
const createComponent = (propsData) => {
- const Component = Vue.extend(MonitoringColumn);
+ const Component = Vue.extend(Graph);
return new Component({
propsData,
}).$mount();
};
-describe('MonitoringColumn', () => {
+describe('Graph', () => {
beforeEach(() => {
- spyOn(MonitoringMixins.methods, 'formatDeployments').and.callFake(function fakeFormat() {
- return {};
- });
+ spyOn(MonitoringMixins.methods, 'formatDeployments').and.returnValue({});
});
it('has a title', () => {
const component = createComponent({
- columnData: singleRowMetrics[0],
+ graphData: singleRowMetrics[0],
classType: 'col-md-6',
updateAspectRatio: false,
deploymentData,
});
- expect(component.$el.querySelector('.text-center').innerText.trim()).toBe(component.columnData.title);
+ expect(component.$el.querySelector('.text-center').innerText.trim()).toBe(component.graphData.title);
});
it('creates a path for the line and area of the graph', (done) => {
const component = createComponent({
- columnData: singleRowMetrics[0],
+ graphData: singleRowMetrics[0],
classType: 'col-md-6',
updateAspectRatio: false,
deploymentData,
@@ -53,7 +51,7 @@ describe('MonitoringColumn', () => {
describe('Computed props', () => {
it('axisTransform translates an element Y position depending of its height', () => {
const component = createComponent({
- columnData: singleRowMetrics[0],
+ graphData: singleRowMetrics[0],
classType: 'col-md-6',
updateAspectRatio: false,
deploymentData,
@@ -66,7 +64,7 @@ describe('MonitoringColumn', () => {
it('outterViewBox gets a width and height property based on the DOM size of the element', () => {
const component = createComponent({
- columnData: singleRowMetrics[0],
+ graphData: singleRowMetrics[0],
classType: 'col-md-6',
updateAspectRatio: false,
deploymentData,
@@ -81,7 +79,7 @@ describe('MonitoringColumn', () => {
it('sends an event to the eventhub when it has finished resizing', (done) => {
const component = createComponent({
- columnData: singleRowMetrics[0],
+ graphData: singleRowMetrics[0],
classType: 'col-md-6',
updateAspectRatio: false,
deploymentData,
@@ -97,13 +95,13 @@ describe('MonitoringColumn', () => {
it('has a title for the y-axis and the chart legend that comes from the backend', () => {
const component = createComponent({
- columnData: singleRowMetrics[0],
+ graphData: singleRowMetrics[0],
classType: 'col-md-6',
updateAspectRatio: false,
deploymentData,
});
- expect(component.yAxisLabel).toEqual(component.columnData.y_label);
- expect(component.legendTitle).toEqual(component.columnData.queries[0].label);
+ expect(component.yAxisLabel).toEqual(component.graphData.y_label);
+ expect(component.legendTitle).toEqual(component.graphData.queries[0].label);
});
});
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 021804e0769..dda83645c92 100644
--- a/spec/javascripts/project_select_combo_button_spec.js
+++ b/spec/javascripts/project_select_combo_button_spec.js
@@ -32,11 +32,6 @@ describe('Project Select Combo Button', function () {
this.comboButton = new ProjectSelectComboButton(this.projectSelectInput);
});
- it('newItemBtn is disabled', function () {
- expect(this.newItemBtn.hasAttribute('disabled')).toBe(true);
- expect(this.newItemBtn.classList.contains('disabled')).toBe(true);
- });
-
it('newItemBtn href is null', function () {
expect(this.newItemBtn.getAttribute('href')).toBe('');
});
@@ -53,11 +48,6 @@ describe('Project Select Combo Button', function () {
this.comboButton = new ProjectSelectComboButton(this.projectSelectInput);
});
- it('newItemBtn is not disabled', function () {
- expect(this.newItemBtn.hasAttribute('disabled')).toBe(false);
- expect(this.newItemBtn.classList.contains('disabled')).toBe(false);
- });
-
it('newItemBtn href is correctly set', function () {
expect(this.newItemBtn.getAttribute('href')).toBe(this.defaults.projectMeta.url);
});
@@ -82,11 +72,6 @@ describe('Project Select Combo Button', function () {
.trigger('change');
});
- it('newItemBtn is not disabled', function () {
- expect(this.newItemBtn.hasAttribute('disabled')).toBe(false);
- expect(this.newItemBtn.classList.contains('disabled')).toBe(false);
- });
-
it('newItemBtn href is correctly set', function () {
expect(this.newItemBtn.getAttribute('href'))
.toBe('http://myothercoolproject.com/issues/new');
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/ci/gitlab_ci_yaml_processor_spec.rb b/spec/lib/ci/gitlab_ci_yaml_processor_spec.rb
index ee28387cd48..c70a4cb55fe 100644
--- a/spec/lib/ci/gitlab_ci_yaml_processor_spec.rb
+++ b/spec/lib/ci/gitlab_ci_yaml_processor_spec.rb
@@ -344,28 +344,31 @@ module Ci
let(:config) { { rspec: { script: "rspec", type: "test", only: only } } }
let(:processor) { GitlabCiYamlProcessor.new(YAML.dump(config)) }
- shared_examples 'raises an error' do
- it do
- expect { processor }.to raise_error(GitlabCiYamlProcessor::ValidationError, 'jobs:rspec:only config should be an array of strings or regexps')
- end
- end
-
context 'when it is integer' do
let(:only) { 1 }
- it_behaves_like 'raises an error'
+ it do
+ expect { processor }.to raise_error(GitlabCiYamlProcessor::ValidationError,
+ 'jobs:rspec:only has to be either an array of conditions or a hash')
+ end
end
context 'when it is an array of integers' do
let(:only) { [1, 1] }
- it_behaves_like 'raises an error'
+ it do
+ expect { processor }.to raise_error(GitlabCiYamlProcessor::ValidationError,
+ 'jobs:rspec:only config should be an array of strings or regexps')
+ end
end
context 'when it is invalid regex' do
let(:only) { ["/*invalid/"] }
- it_behaves_like 'raises an error'
+ it do
+ expect { processor }.to raise_error(GitlabCiYamlProcessor::ValidationError,
+ 'jobs:rspec:only config should be an array of strings or regexps')
+ end
end
end
end
@@ -518,28 +521,31 @@ module Ci
let(:config) { { rspec: { script: "rspec", except: except } } }
let(:processor) { GitlabCiYamlProcessor.new(YAML.dump(config)) }
- shared_examples 'raises an error' do
- it do
- expect { processor }.to raise_error(GitlabCiYamlProcessor::ValidationError, 'jobs:rspec:except config should be an array of strings or regexps')
- end
- end
-
context 'when it is integer' do
let(:except) { 1 }
- it_behaves_like 'raises an error'
+ it do
+ expect { processor }.to raise_error(GitlabCiYamlProcessor::ValidationError,
+ 'jobs:rspec:except has to be either an array of conditions or a hash')
+ end
end
context 'when it is an array of integers' do
let(:except) { [1, 1] }
- it_behaves_like 'raises an error'
+ it do
+ expect { processor }.to raise_error(GitlabCiYamlProcessor::ValidationError,
+ 'jobs:rspec:except config should be an array of strings or regexps')
+ end
end
context 'when it is invalid regex' do
let(:except) { ["/*invalid/"] }
- it_behaves_like 'raises an error'
+ it do
+ expect { processor }.to raise_error(GitlabCiYamlProcessor::ValidationError,
+ 'jobs:rspec:except config should be an array of strings or regexps')
+ end
end
end
end
diff --git a/spec/lib/gitlab/auth/unique_ips_limiter_spec.rb b/spec/lib/gitlab/auth/unique_ips_limiter_spec.rb
index f29431b937c..22708687a56 100644
--- a/spec/lib/gitlab/auth/unique_ips_limiter_spec.rb
+++ b/spec/lib/gitlab/auth/unique_ips_limiter_spec.rb
@@ -41,7 +41,7 @@ describe Gitlab::Auth::UniqueIpsLimiter, :clean_gitlab_redis_shared_state do
context 'allow 2 unique ips' do
before do
- current_application_settings.update!(unique_ips_limit_per_user: 2)
+ Gitlab::CurrentSettings.current_application_settings.update!(unique_ips_limit_per_user: 2)
end
it 'blocks user trying to login from third ip' do
diff --git a/spec/lib/gitlab/ci/config/entry/attributable_spec.rb b/spec/lib/gitlab/ci/config/entry/attributable_spec.rb
index fde03c51e2c..b028b771375 100644
--- a/spec/lib/gitlab/ci/config/entry/attributable_spec.rb
+++ b/spec/lib/gitlab/ci/config/entry/attributable_spec.rb
@@ -1,18 +1,21 @@
require 'spec_helper'
describe Gitlab::Ci::Config::Entry::Attributable do
- let(:node) { Class.new }
+ let(:node) do
+ Class.new do
+ include Gitlab::Ci::Config::Entry::Attributable
+ end
+ end
+
let(:instance) { node.new }
before do
- node.include(described_class)
-
node.class_eval do
attributes :name, :test
end
end
- context 'config is a hash' do
+ context 'when config is a hash' do
before do
allow(instance)
.to receive(:config)
@@ -29,7 +32,7 @@ describe Gitlab::Ci::Config::Entry::Attributable do
end
end
- context 'config is not a hash' do
+ context 'when config is not a hash' do
before do
allow(instance)
.to receive(:config)
@@ -40,4 +43,18 @@ describe Gitlab::Ci::Config::Entry::Attributable do
expect(instance.test).to be_nil
end
end
+
+ context 'when method is already defined in a superclass' do
+ it 'raises an error' do
+ expectation = expect do
+ Class.new(String) do
+ include Gitlab::Ci::Config::Entry::Attributable
+
+ attributes :length
+ end
+ end
+
+ expectation.to raise_error(ArgumentError, 'Method already defined!')
+ end
+ end
end
diff --git a/spec/lib/gitlab/ci/config/entry/configurable_spec.rb b/spec/lib/gitlab/ci/config/entry/configurable_spec.rb
index ae7e628b5b5..088d4b472da 100644
--- a/spec/lib/gitlab/ci/config/entry/configurable_spec.rb
+++ b/spec/lib/gitlab/ci/config/entry/configurable_spec.rb
@@ -1,40 +1,26 @@
require 'spec_helper'
describe Gitlab::Ci::Config::Entry::Configurable do
- let(:entry) { Class.new }
-
- before do
- entry.include(described_class)
+ let(:entry) do
+ Class.new(Gitlab::Ci::Config::Entry::Node) do
+ include Gitlab::Ci::Config::Entry::Configurable
+ end
end
describe 'validations' do
- let(:validator) { entry.validator.new(instance) }
-
- before do
- entry.class_eval do
- attr_reader :config
+ context 'when entry is a hash' do
+ let(:instance) { entry.new(key: 'value') }
- def initialize(config)
- @config = config
- end
+ it 'correctly validates an instance' do
+ expect(instance).to be_valid
end
-
- validator.validate
end
- context 'when entry validator is invalid' do
+ context 'when entry is not a hash' do
let(:instance) { entry.new('ls') }
- it 'returns invalid validator' do
- expect(validator).to be_invalid
- end
- end
-
- context 'when entry instance is valid' do
- let(:instance) { entry.new(key: 'value') }
-
- it 'returns valid validator' do
- expect(validator).to be_valid
+ it 'invalidates the instance' do
+ expect(instance).not_to be_valid
end
end
end
diff --git a/spec/lib/gitlab/ci/config/entry/policy_spec.rb b/spec/lib/gitlab/ci/config/entry/policy_spec.rb
new file mode 100644
index 00000000000..36a84da4a52
--- /dev/null
+++ b/spec/lib/gitlab/ci/config/entry/policy_spec.rb
@@ -0,0 +1,73 @@
+require 'spec_helper'
+
+describe Gitlab::Ci::Config::Entry::Policy do
+ let(:entry) { described_class.new(config) }
+
+ context 'when using simplified policy' do
+ describe 'validations' do
+ context 'when entry config value is valid' do
+ context 'when config is a branch or tag name' do
+ let(:config) { %w[master feature/branch] }
+
+ describe '#valid?' do
+ it 'is valid' do
+ expect(entry).to be_valid
+ end
+ end
+
+ describe '#value' do
+ it 'returns key value' do
+ expect(entry.value).to eq config
+ end
+ end
+ end
+
+ context 'when config is a regexp' do
+ let(:config) { ['/^issue-.*$/'] }
+
+ describe '#valid?' do
+ it 'is valid' do
+ expect(entry).to be_valid
+ end
+ end
+ end
+
+ context 'when config is a special keyword' do
+ let(:config) { %w[tags triggers branches] }
+
+ describe '#valid?' do
+ it 'is valid' do
+ expect(entry).to be_valid
+ end
+ end
+ end
+ end
+
+ context 'when entry value is not valid' do
+ let(:config) { [1] }
+
+ describe '#errors' do
+ it 'saves errors' do
+ expect(entry.errors)
+ .to include /policy config should be an array of strings or regexps/
+ end
+ end
+ end
+ end
+ end
+
+ context 'when policy strategy does not match' do
+ let(:config) { 'string strategy' }
+
+ it 'returns information about errors' do
+ expect(entry.errors)
+ .to include /has to be either an array of conditions or a hash/
+ end
+ end
+
+ describe '.default' do
+ it 'does not have a default value' do
+ expect(described_class.default).to be_nil
+ end
+ end
+end
diff --git a/spec/lib/gitlab/ci/config/entry/simplifiable_spec.rb b/spec/lib/gitlab/ci/config/entry/simplifiable_spec.rb
new file mode 100644
index 00000000000..395062207a3
--- /dev/null
+++ b/spec/lib/gitlab/ci/config/entry/simplifiable_spec.rb
@@ -0,0 +1,88 @@
+require 'spec_helper'
+
+describe Gitlab::Ci::Config::Entry::Simplifiable do
+ describe '.strategy' do
+ let(:entry) do
+ Class.new(described_class) do
+ strategy :Something, if: -> { 'condition' }
+ strategy :DifferentOne, if: -> { 'condition' }
+ end
+ end
+
+ it 'defines entry strategies' do
+ expect(entry.strategies.size).to eq 2
+ expect(entry.strategies.map(&:name))
+ .to eq %i[Something DifferentOne]
+ end
+ end
+
+ describe 'setting strategy by a condition' do
+ let(:first) { double('first strategy') }
+ let(:second) { double('second strategy') }
+ let(:unknown) { double('unknown strategy') }
+
+ before do
+ stub_const("#{described_class.name}::Something", first)
+ stub_const("#{described_class.name}::DifferentOne", second)
+ stub_const("#{described_class.name}::UnknownStrategy", unknown)
+ end
+
+ context 'when first strategy should be used' do
+ let(:entry) do
+ Class.new(described_class) do
+ strategy :Something, if: -> (arg) { arg == 'something' }
+ strategy :DifferentOne, if: -> (*) { false }
+ end
+ end
+
+ it 'attemps to load a first strategy' do
+ expect(first).to receive(:new).with('something', anything)
+
+ entry.new('something')
+ end
+ end
+
+ context 'when second strategy should be used' do
+ let(:entry) do
+ Class.new(described_class) do
+ strategy :Something, if: -> (arg) { arg == 'something' }
+ strategy :DifferentOne, if: -> (arg) { arg == 'test' }
+ end
+ end
+
+ it 'attemps to load a second strategy' do
+ expect(second).to receive(:new).with('test', anything)
+
+ entry.new('test')
+ end
+ end
+
+ context 'when neither one is a valid strategy' do
+ let(:entry) do
+ Class.new(described_class) do
+ strategy :Something, if: -> (*) { false }
+ strategy :DifferentOne, if: -> (*) { false }
+ end
+ end
+
+ it 'instantiates an unknown strategy' do
+ expect(unknown).to receive(:new).with('test', anything)
+
+ entry.new('test')
+ end
+ end
+ end
+
+ context 'when a unknown strategy class is not defined' do
+ let(:entry) do
+ Class.new(described_class) do
+ strategy :String, if: -> (*) { true }
+ end
+ end
+
+ it 'raises an error when being initialized' do
+ expect { entry.new('something') }
+ .to raise_error ArgumentError, /UndefinedStrategy not available!/
+ end
+ end
+end
diff --git a/spec/lib/gitlab/ci/config/entry/trigger_spec.rb b/spec/lib/gitlab/ci/config/entry/trigger_spec.rb
deleted file mode 100644
index e4ee44f1274..00000000000
--- a/spec/lib/gitlab/ci/config/entry/trigger_spec.rb
+++ /dev/null
@@ -1,56 +0,0 @@
-require 'spec_helper'
-
-describe Gitlab::Ci::Config::Entry::Trigger do
- let(:entry) { described_class.new(config) }
-
- describe 'validations' do
- context 'when entry config value is valid' do
- context 'when config is a branch or tag name' do
- let(:config) { %w[master feature/branch] }
-
- describe '#valid?' do
- it 'is valid' do
- expect(entry).to be_valid
- end
- end
-
- describe '#value' do
- it 'returns key value' do
- expect(entry.value).to eq config
- end
- end
- end
-
- context 'when config is a regexp' do
- let(:config) { ['/^issue-.*$/'] }
-
- describe '#valid?' do
- it 'is valid' do
- expect(entry).to be_valid
- end
- end
- end
-
- context 'when config is a special keyword' do
- let(:config) { %w[tags triggers branches] }
-
- describe '#valid?' do
- it 'is valid' do
- expect(entry).to be_valid
- end
- end
- end
- end
-
- context 'when entry value is not valid' do
- let(:config) { [1] }
-
- describe '#errors' do
- it 'saves errors' do
- expect(entry.errors)
- .to include 'trigger config should be an array of strings or regexps'
- end
- end
- end
- end
-end
diff --git a/spec/lib/gitlab/ci/config/entry/validatable_spec.rb b/spec/lib/gitlab/ci/config/entry/validatable_spec.rb
index d1856801827..ae2a7a51ba6 100644
--- a/spec/lib/gitlab/ci/config/entry/validatable_spec.rb
+++ b/spec/lib/gitlab/ci/config/entry/validatable_spec.rb
@@ -1,10 +1,10 @@
require 'spec_helper'
describe Gitlab::Ci::Config::Entry::Validatable do
- let(:entry) { Class.new }
-
- before do
- entry.include(described_class)
+ let(:entry) do
+ Class.new(Gitlab::Ci::Config::Entry::Node) do
+ include Gitlab::Ci::Config::Entry::Validatable
+ end
end
describe '.validator' do
@@ -28,7 +28,7 @@ describe Gitlab::Ci::Config::Entry::Validatable do
end
context 'when validating entry instance' do
- let(:entry_instance) { entry.new }
+ let(:entry_instance) { entry.new('something') }
context 'when attribute is valid' do
before do
diff --git a/spec/lib/gitlab/ci/config/entry/validator_spec.rb b/spec/lib/gitlab/ci/config/entry/validator_spec.rb
index ad7e6f07d3c..172b6b47a4f 100644
--- a/spec/lib/gitlab/ci/config/entry/validator_spec.rb
+++ b/spec/lib/gitlab/ci/config/entry/validator_spec.rb
@@ -48,7 +48,7 @@ describe Gitlab::Ci::Config::Entry::Validator do
validator_instance.validate
expect(validator_instance.messages)
- .to include "node test attribute can't be blank"
+ .to include /test attribute can't be blank/
end
end
end
diff --git a/spec/lib/gitlab/database/grant_spec.rb b/spec/lib/gitlab/database/grant_spec.rb
new file mode 100644
index 00000000000..651da3e8476
--- /dev/null
+++ b/spec/lib/gitlab/database/grant_spec.rb
@@ -0,0 +1,30 @@
+require 'spec_helper'
+
+describe Gitlab::Database::Grant do
+ describe '.scope_to_current_user' do
+ it 'scopes the relation to the current user' do
+ user = Gitlab::Database.username
+ column = Gitlab::Database.postgresql? ? :grantee : :User
+ names = described_class.scope_to_current_user.pluck(column).uniq
+
+ expect(names).to eq([user])
+ end
+ end
+
+ describe '.create_and_execute_trigger' do
+ it 'returns true when the user can create and execute a trigger' do
+ # We assume the DB/user is set up correctly so that triggers can be
+ # created, which is necessary anyway for other tests to work.
+ expect(described_class.create_and_execute_trigger?('users')).to eq(true)
+ end
+
+ it 'returns false when the user can not create and/or execute a trigger' do
+ allow(described_class).to receive(:scope_to_current_user)
+ .and_return(described_class.none)
+
+ result = described_class.create_and_execute_trigger?('kittens')
+
+ expect(result).to eq(false)
+ 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..1bcdc369c44 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
@@ -452,6 +450,8 @@ describe Gitlab::Database::MigrationHelpers do
it 'renames a column concurrently' do
allow(Gitlab::Database).to receive(:postgresql?).and_return(false)
+ expect(model).to receive(:check_trigger_permissions!).with(:users)
+
expect(model).to receive(:install_rename_triggers_for_mysql)
.with(trigger_name, 'users', 'old', 'new')
@@ -479,6 +479,8 @@ describe Gitlab::Database::MigrationHelpers do
it 'renames a column concurrently' do
allow(Gitlab::Database).to receive(:postgresql?).and_return(true)
+ expect(model).to receive(:check_trigger_permissions!).with(:users)
+
expect(model).to receive(:install_rename_triggers_for_postgresql)
.with(trigger_name, 'users', 'old', 'new')
@@ -508,6 +510,8 @@ describe Gitlab::Database::MigrationHelpers do
it 'cleans up the renaming procedure for PostgreSQL' do
allow(Gitlab::Database).to receive(:postgresql?).and_return(true)
+ expect(model).to receive(:check_trigger_permissions!).with(:users)
+
expect(model).to receive(:remove_rename_triggers_for_postgresql)
.with(:users, /trigger_.{12}/)
@@ -519,6 +523,8 @@ describe Gitlab::Database::MigrationHelpers do
it 'cleans up the renaming procedure for MySQL' do
allow(Gitlab::Database).to receive(:postgresql?).and_return(false)
+ expect(model).to receive(:check_trigger_permissions!).with(:users)
+
expect(model).to receive(:remove_rename_triggers_for_mysql)
.with(/trigger_.{12}/)
@@ -575,8 +581,8 @@ describe Gitlab::Database::MigrationHelpers do
describe '#remove_rename_triggers_for_postgresql' do
it 'removes the function and trigger' do
- expect(model).to receive(:execute).with('DROP TRIGGER foo ON bar')
- expect(model).to receive(:execute).with('DROP FUNCTION foo()')
+ expect(model).to receive(:execute).with('DROP TRIGGER IF EXISTS foo ON bar')
+ expect(model).to receive(:execute).with('DROP FUNCTION IF EXISTS foo()')
model.remove_rename_triggers_for_postgresql('bar', 'foo')
end
@@ -584,8 +590,8 @@ describe Gitlab::Database::MigrationHelpers do
describe '#remove_rename_triggers_for_mysql' do
it 'removes the triggers' do
- expect(model).to receive(:execute).with('DROP TRIGGER foo_insert')
- expect(model).to receive(:execute).with('DROP TRIGGER foo_update')
+ expect(model).to receive(:execute).with('DROP TRIGGER IF EXISTS foo_insert')
+ expect(model).to receive(:execute).with('DROP TRIGGER IF EXISTS foo_update')
model.remove_rename_triggers_for_mysql('foo')
end
@@ -845,4 +851,67 @@ 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
+
+ describe '#check_trigger_permissions!' do
+ it 'does nothing when the user has the correct permissions' do
+ expect { model.check_trigger_permissions!('users') }
+ .not_to raise_error(RuntimeError)
+ end
+
+ it 'raises RuntimeError when the user does not have the correct permissions' do
+ allow(Gitlab::Database::Grant).to receive(:create_and_execute_trigger?)
+ .with('kittens')
+ .and_return(false)
+
+ expect { model.check_trigger_permissions!('kittens') }
+ .to raise_error(RuntimeError, /Your database user is not allowed/)
+ end
+ end
end
diff --git a/spec/lib/gitlab/git/repository_spec.rb b/spec/lib/gitlab/git/repository_spec.rb
index 6b9773c9b63..4cfb4b7d357 100644
--- a/spec/lib/gitlab/git/repository_spec.rb
+++ b/spec/lib/gitlab/git/repository_spec.rb
@@ -433,6 +433,40 @@ describe Gitlab::Git::Repository, seed_helper: true do
end
end
+ describe '#delete_refs' do
+ before(:all) do
+ @repo = Gitlab::Git::Repository.new('default', TEST_MUTABLE_REPO_PATH, '')
+ end
+
+ it 'deletes the ref' do
+ @repo.delete_refs('refs/heads/feature')
+
+ expect(@repo.rugged.references['refs/heads/feature']).to be_nil
+ end
+
+ it 'deletes all refs' do
+ refs = %w[refs/heads/wip refs/tags/v1.1.0]
+ @repo.delete_refs(*refs)
+
+ refs.each do |ref|
+ expect(@repo.rugged.references[ref]).to be_nil
+ end
+ end
+
+ it 'raises an error if it failed' do
+ expect(Gitlab::Popen).to receive(:popen).and_return(['Error', 1])
+
+ expect do
+ @repo.delete_refs('refs/heads/fix')
+ end.to raise_error(Gitlab::Git::Repository::GitError)
+ end
+
+ after(:all) do
+ FileUtils.rm_rf(TEST_MUTABLE_REPO_PATH)
+ ensure_seeds
+ end
+ end
+
describe "#refs_hash" do
let(:refs) { repository.refs_hash }
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 c10427d798f..5b16fc5d084 100644
--- a/spec/lib/gitlab/import_export/project_tree_restorer_spec.rb
+++ b/spec/lib/gitlab/import_export/project_tree_restorer_spec.rb
@@ -86,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/shell_spec.rb b/spec/lib/gitlab/shell_spec.rb
index cfadee0bcf5..c7930378240 100644
--- a/spec/lib/gitlab/shell_spec.rb
+++ b/spec/lib/gitlab/shell_spec.rb
@@ -186,22 +186,48 @@ describe Gitlab::Shell do
end
end
- describe '#fetch_remote' do
+ shared_examples 'fetch_remote' do |gitaly_on|
+ let(:project2) { create(:project, :repository) }
+ let(:repository) { project2.repository }
+
def fetch_remote(ssh_auth = nil)
- gitlab_shell.fetch_remote('current/storage', 'project/path', 'new/storage', ssh_auth: ssh_auth)
+ gitlab_shell.fetch_remote(repository.raw_repository, 'new/storage', ssh_auth: ssh_auth)
end
- def expect_popen(vars = {})
+ def expect_popen(fail = false, vars = {})
popen_args = [
projects_path,
'fetch-remote',
- 'current/storage',
- 'project/path.git',
+ TestEnv.repos_path,
+ repository.relative_path,
'new/storage',
Gitlab.config.gitlab_shell.git_timeout.to_s
]
- expect(Gitlab::Popen).to receive(:popen).with(popen_args, nil, popen_vars.merge(vars))
+ return_value = fail ? ["error", 1] : [nil, 0]
+
+ expect(Gitlab::Popen).to receive(:popen).with(popen_args, nil, popen_vars.merge(vars)).and_return(return_value)
+ end
+
+ def expect_gitaly_call(fail, vars = {})
+ receive_fetch_remote =
+ if fail
+ receive(:fetch_remote).and_raise(GRPC::NotFound)
+ else
+ receive(:fetch_remote).and_return(true)
+ end
+
+ expect_any_instance_of(Gitlab::GitalyClient::RepositoryService).to receive_fetch_remote
+ end
+
+ if gitaly_on
+ def expect_call(fail, vars = {})
+ expect_gitaly_call(fail, vars)
+ end
+ else
+ def expect_call(fail, vars = {})
+ expect_popen(fail, vars)
+ end
end
def build_ssh_auth(opts = {})
@@ -216,20 +242,20 @@ describe Gitlab::Shell do
end
it 'returns true when the command succeeds' do
- expect_popen.and_return([nil, 0])
+ expect_call(false)
expect(fetch_remote).to be_truthy
end
it 'raises an exception when the command fails' do
- expect_popen.and_return(["error", 1])
+ expect_call(true)
- expect { fetch_remote }.to raise_error(Gitlab::Shell::Error, "error")
+ expect { fetch_remote }.to raise_error(Gitlab::Shell::Error)
end
context 'SSH auth' do
it 'passes the SSH key if specified' do
- expect_popen('GITLAB_SHELL_SSH_KEY' => 'foo').and_return([nil, 0])
+ expect_call(false, 'GITLAB_SHELL_SSH_KEY' => 'foo')
ssh_auth = build_ssh_auth(ssh_key_auth?: true, ssh_private_key: 'foo')
@@ -237,7 +263,7 @@ describe Gitlab::Shell do
end
it 'does not pass an empty SSH key' do
- expect_popen.and_return([nil, 0])
+ expect_call(false)
ssh_auth = build_ssh_auth(ssh_key_auth: true, ssh_private_key: '')
@@ -245,7 +271,7 @@ describe Gitlab::Shell do
end
it 'does not pass the key unless SSH key auth is to be used' do
- expect_popen.and_return([nil, 0])
+ expect_call(false)
ssh_auth = build_ssh_auth(ssh_key_auth: false, ssh_private_key: 'foo')
@@ -253,7 +279,7 @@ describe Gitlab::Shell do
end
it 'passes the known_hosts data if specified' do
- expect_popen('GITLAB_SHELL_KNOWN_HOSTS' => 'foo').and_return([nil, 0])
+ expect_call(false, 'GITLAB_SHELL_KNOWN_HOSTS' => 'foo')
ssh_auth = build_ssh_auth(ssh_known_hosts: 'foo')
@@ -261,7 +287,7 @@ describe Gitlab::Shell do
end
it 'does not pass empty known_hosts data' do
- expect_popen.and_return([nil, 0])
+ expect_call(false)
ssh_auth = build_ssh_auth(ssh_known_hosts: '')
@@ -269,7 +295,7 @@ describe Gitlab::Shell do
end
it 'does not pass known_hosts data unless SSH is to be used' do
- expect_popen(popen_vars).and_return([nil, 0])
+ expect_call(false, popen_vars)
ssh_auth = build_ssh_auth(ssh_import?: false, ssh_known_hosts: 'foo')
@@ -278,6 +304,14 @@ describe Gitlab::Shell do
end
end
+ describe '#fetch_remote local', skip_gitaly_mock: true do
+ it_should_behave_like 'fetch_remote', false
+ end
+
+ describe '#fetch_remote gitaly' do
+ it_should_behave_like 'fetch_remote', true
+ end
+
describe '#import_repository' do
it 'returns true when the command succeeds' do
expect(Gitlab::Popen).to receive(:popen)
diff --git a/spec/lib/gitlab/sql/pattern_spec.rb b/spec/lib/gitlab/sql/pattern_spec.rb
new file mode 100644
index 00000000000..9d7b2136dab
--- /dev/null
+++ b/spec/lib/gitlab/sql/pattern_spec.rb
@@ -0,0 +1,55 @@
+require 'spec_helper'
+
+describe Gitlab::SQL::Pattern do
+ describe '.to_pattern' do
+ subject(:to_pattern) { User.to_pattern(query) }
+
+ context 'when a query is shorter than 3 chars' do
+ let(:query) { '12' }
+
+ it 'returns exact matching pattern' do
+ expect(to_pattern).to eq('12')
+ end
+ end
+
+ context 'when a query with a escape character is shorter than 3 chars' do
+ let(:query) { '_2' }
+
+ it 'returns sanitized exact matching pattern' do
+ expect(to_pattern).to eq('\_2')
+ end
+ end
+
+ context 'when a query is equal to 3 chars' do
+ let(:query) { '123' }
+
+ it 'returns partial matching pattern' do
+ expect(to_pattern).to eq('%123%')
+ end
+ end
+
+ context 'when a query with a escape character is equal to 3 chars' do
+ let(:query) { '_23' }
+
+ it 'returns partial matching pattern' do
+ expect(to_pattern).to eq('%\_23%')
+ end
+ end
+
+ context 'when a query is longer than 3 chars' do
+ let(:query) { '1234' }
+
+ it 'returns partial matching pattern' do
+ expect(to_pattern).to eq('%1234%')
+ end
+ end
+
+ context 'when a query with a escape character is longer than 3 chars' do
+ let(:query) { '_234' }
+
+ it 'returns sanitized partial matching pattern' do
+ expect(to_pattern).to eq('%\_234%')
+ end
+ 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/models/ci/build_spec.rb b/spec/models/ci/build_spec.rb
index 4f77f0d85cd..0c35ad3c9d8 100644
--- a/spec/models/ci/build_spec.rb
+++ b/spec/models/ci/build_spec.rb
@@ -1257,8 +1257,12 @@ describe Ci::Build do
context 'when build has user' do
let(:user_variables) do
- [{ key: 'GITLAB_USER_ID', value: user.id.to_s, public: true },
- { key: 'GITLAB_USER_EMAIL', value: user.email, public: true }]
+ [
+ { key: 'GITLAB_USER_ID', value: user.id.to_s, public: true },
+ { key: 'GITLAB_USER_EMAIL', value: user.email, public: true },
+ { key: 'GITLAB_USER_LOGIN', value: user.username, public: true },
+ { key: 'GITLAB_USER_NAME', value: user.name, public: true }
+ ]
end
before do
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/issue_spec.rb b/spec/models/issue_spec.rb
index de86788d142..e547da0cfbe 100644
--- a/spec/models/issue_spec.rb
+++ b/spec/models/issue_spec.rb
@@ -769,4 +769,22 @@ describe Issue do
expect(described_class.public_only).to eq([public_issue])
end
end
+
+ describe '#update_project_counter_caches?' do
+ it 'returns true when the state changes' do
+ subject.state = 'closed'
+
+ expect(subject.update_project_counter_caches?).to eq(true)
+ end
+
+ it 'returns true when the confidential flag changes' do
+ subject.confidential = true
+
+ expect(subject.update_project_counter_caches?).to eq(true)
+ end
+
+ it 'returns false when the state or confidential flag did not change' do
+ expect(subject.update_project_counter_caches?).to eq(false)
+ end
+ end
end
diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb
index 2d10c6ef1da..09f3b97ec58 100644
--- a/spec/models/merge_request_spec.rb
+++ b/spec/models/merge_request_spec.rb
@@ -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
@@ -1701,4 +1700,16 @@ describe MergeRequest do
.to change { project.open_merge_requests_count }.from(1).to(0)
end
end
+
+ describe '#update_project_counter_caches?' do
+ it 'returns true when the state changes' do
+ subject.state = 'closed'
+
+ expect(subject.update_project_counter_caches?).to eq(true)
+ end
+
+ it 'returns false when the state did not change' do
+ expect(subject.update_project_counter_caches?).to eq(false)
+ end
+ end
end
diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb
index 2e613c44357..3621023f4ca 100644
--- a/spec/models/project_spec.rb
+++ b/spec/models/project_spec.rb
@@ -1563,10 +1563,18 @@ describe Project do
describe 'project import state transitions' do
context 'state transition: [:started] => [:finished]' do
- let(:housekeeping_service) { spy }
+ let(:after_import_service) { spy(:after_import_service) }
+ let(:housekeeping_service) { spy(:housekeeping_service) }
before do
- allow(Projects::HousekeepingService).to receive(:new) { housekeeping_service }
+ allow(Projects::AfterImportService)
+ .to receive(:new) { after_import_service }
+
+ allow(after_import_service)
+ .to receive(:execute) { housekeeping_service.execute }
+
+ allow(Projects::HousekeepingService)
+ .to receive(:new) { housekeeping_service }
end
it 'resets project import_error' do
@@ -1581,6 +1589,7 @@ describe Project do
project.import_finish
+ expect(after_import_service).to have_received(:execute)
expect(housekeeping_service).to have_received(:execute)
end
@@ -2225,6 +2234,28 @@ describe Project do
end
end
+ describe '#pages_available?' do
+ let(:project) { create(:project, group: group) }
+
+ subject { project.pages_available? }
+
+ before do
+ allow(Gitlab.config.pages).to receive(:enabled).and_return(true)
+ end
+
+ context 'when the project is in a top level namespace' do
+ let(:group) { create(:group) }
+
+ it { is_expected.to be(true) }
+ end
+
+ context 'when the project is in a subgroup' do
+ let(:group) { create(:group, :nested) }
+
+ it { is_expected.to be(false) }
+ end
+ end
+
describe '#remove_private_deploy_keys' do
let!(:project) { create(:project) }
diff --git a/spec/models/repository_spec.rb b/spec/models/repository_spec.rb
index 462e92b8b62..34e1a955309 100644
--- a/spec/models/repository_spec.rb
+++ b/spec/models/repository_spec.rb
@@ -923,13 +923,16 @@ describe Repository, models: true do
describe '#update_branch_with_hooks' do
let(:old_rev) { '0b4bc9a49b562e85de7cc9e834518ea6828729b9' } # git rev-parse feature
let(:new_rev) { 'a74ae73c1ccde9b974a70e82b901588071dc142a' } # commit whose parent is old_rev
+ let(:updating_ref) { 'refs/heads/feature' }
+ let(:target_project) { project }
+ let(:target_repository) { target_project.repository }
context 'when pre hooks were successful' do
before do
service = Gitlab::Git::HooksService.new
expect(Gitlab::Git::HooksService).to receive(:new).and_return(service)
expect(service).to receive(:execute)
- .with(committer, repository, old_rev, new_rev, 'refs/heads/feature')
+ .with(committer, target_repository, old_rev, new_rev, updating_ref)
.and_yield(service).and_return(true)
end
@@ -960,6 +963,37 @@ describe Repository, models: true do
expect(repository.find_branch('feature').dereferenced_target.id).to eq(new_rev)
end
end
+
+ context 'when target project does not have the commit' do
+ let(:target_project) { create(:project, :empty_repo) }
+ let(:old_rev) { Gitlab::Git::BLANK_SHA }
+ let(:new_rev) { project.commit('feature').sha }
+ let(:updating_ref) { 'refs/heads/master' }
+
+ it 'fetch_ref and create the branch' do
+ expect(target_project.repository).to receive(:fetch_ref)
+ .and_call_original
+
+ GitOperationService.new(committer, target_repository)
+ .with_branch(
+ 'master',
+ start_project: project,
+ start_branch_name: 'feature') { new_rev }
+
+ expect(target_repository.branch_names).to contain_exactly('master')
+ end
+ end
+
+ context 'when target project already has the commit' do
+ let(:target_project) { create(:project, :repository) }
+
+ it 'does not fetch_ref and just pass the commit' do
+ expect(target_repository).not_to receive(:fetch_ref)
+
+ GitOperationService.new(committer, target_repository)
+ .with_branch('feature', start_project: project) { new_rev }
+ end
+ end
end
context 'when temporary ref failed to be created from other project' do
@@ -2036,23 +2070,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
@@ -2063,17 +2097,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 8e04eea56a7..b70ab5581ac 100644
--- a/spec/models/user_spec.rb
+++ b/spec/models/user_spec.rb
@@ -789,6 +789,7 @@ describe User do
describe '.search' do
let!(:user) { create(:user, name: 'user', username: 'usern', email: 'email@gmail.com') }
let!(:user2) { create(:user, name: 'user name', username: 'username', email: 'someemail@gmail.com') }
+ let!(:user3) { create(:user, name: 'us', username: 'se', email: 'foo@gmail.com') }
describe 'name matching' do
it 'returns users with a matching name with exact match first' do
@@ -802,6 +803,14 @@ describe User do
it 'returns users with a matching name regardless of the casing' do
expect(described_class.search(user2.name.upcase)).to eq([user2])
end
+
+ it 'returns users with a exact matching name shorter than 3 chars' do
+ expect(described_class.search(user3.name)).to eq([user3])
+ end
+
+ it 'returns users with a exact matching name shorter than 3 chars regardless of the casing' do
+ expect(described_class.search(user3.name.upcase)).to eq([user3])
+ end
end
describe 'email matching' do
@@ -830,6 +839,14 @@ describe User do
it 'returns users with a matching username regardless of the casing' do
expect(described_class.search(user2.username.upcase)).to eq([user2])
end
+
+ it 'returns users with a exact matching username shorter than 3 chars' do
+ expect(described_class.search(user3.username)).to eq([user3])
+ end
+
+ it 'returns users with a exact matching username shorter than 3 chars regardless of the casing' do
+ expect(described_class.search(user3.username.upcase)).to eq([user3])
+ end
end
end
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/files_spec.rb b/spec/requests/api/files_spec.rb
index ea97c556430..971eaf837cb 100644
--- a/spec/requests/api/files_spec.rb
+++ b/spec/requests/api/files_spec.rb
@@ -125,6 +125,15 @@ describe API::Files do
expect(response).to have_http_status(200)
end
+ it 'returns raw file info for files with dots' do
+ url = route('.gitignore') + "/raw"
+ expect(Gitlab::Workhorse).to receive(:send_git_blob)
+
+ get api(url, current_user), params
+
+ expect(response).to have_http_status(200)
+ end
+
it 'returns file by commit sha' do
# This file is deleted on HEAD
file_path = "files%2Fjs%2Fcommit%2Ejs%2Ecoffee"
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 a7557c7fb22..77c43f92456 100644
--- a/spec/requests/api/groups_spec.rb
+++ b/spec/requests/api/groups_spec.rb
@@ -444,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
@@ -488,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..dee75c96b86 100644
--- a/spec/requests/api/issues_spec.rb
+++ b/spec/requests/api/issues_spec.rb
@@ -509,6 +509,18 @@ describe API::Issues, :mailer do
describe "GET /projects/:id/issues" do
let(:base_url) { "/projects/#{project.id}" }
+ it 'avoids N+1 queries' do
+ control_count = ActiveRecord::QueryRecorder.new do
+ get api("/projects/#{project.id}/issues", user)
+ end.count
+
+ create(:issue, author: user, project: project)
+
+ expect do
+ get api("/projects/#{project.id}/issues", user)
+ end.not_to exceed_query_limit(control_count)
+ end
+
it 'returns 404 when project does not exist' do
get api('/projects/1000/issues', non_member)
@@ -984,7 +996,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 +1126,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 +1316,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/services/ci/create_pipeline_service_spec.rb b/spec/services/ci/create_pipeline_service_spec.rb
index 8465a6f99bd..4ba3dada37c 100644
--- a/spec/services/ci/create_pipeline_service_spec.rb
+++ b/spec/services/ci/create_pipeline_service_spec.rb
@@ -413,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
@@ -431,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)
@@ -470,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/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/issues/create_service_spec.rb b/spec/services/issues/create_service_spec.rb
index 78b11cd7991..cc3d648c340 100644
--- a/spec/services/issues/create_service_spec.rb
+++ b/spec/services/issues/create_service_spec.rb
@@ -370,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
@@ -392,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/merge_requests/merge_service_spec.rb b/spec/services/merge_requests/merge_service_spec.rb
index 5cfdb5372f3..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') }
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/after_import_service_spec.rb b/spec/services/projects/after_import_service_spec.rb
new file mode 100644
index 00000000000..c6678fc1f5c
--- /dev/null
+++ b/spec/services/projects/after_import_service_spec.rb
@@ -0,0 +1,55 @@
+require 'spec_helper'
+
+describe Projects::AfterImportService do
+ subject { described_class.new(project) }
+
+ let(:project) { create(:project, :repository) }
+ let(:repository) { project.repository }
+ let(:sha) { project.commit.sha }
+ let(:housekeeping_service) { double(:housekeeping_service) }
+
+ describe '#execute' do
+ before do
+ allow(Projects::HousekeepingService)
+ .to receive(:new).with(project).and_return(housekeeping_service)
+
+ allow(housekeeping_service)
+ .to receive(:execute).and_yield
+ end
+
+ it 'performs housekeeping' do
+ subject.execute
+
+ expect(housekeeping_service).to have_received(:execute)
+ end
+
+ context 'with some refs in refs/pull/**/*' do
+ before do
+ repository.write_ref('refs/pull/1/head', sha)
+ repository.write_ref('refs/pull/1/merge', sha)
+
+ subject.execute
+ end
+
+ it 'removes refs/pull/**/*' do
+ expect(repository.rugged.references.map(&:name))
+ .not_to include(%r{\Arefs/pull/})
+ end
+ end
+
+ Repository::RESERVED_REFS_NAMES.each do |name|
+ context "with a ref in refs/#{name}/tmp" do
+ before do
+ repository.write_ref("refs/#{name}/tmp", sha)
+
+ subject.execute
+ end
+
+ it "does not remove refs/#{name}/tmp" do
+ expect(repository.rugged.references.map(&:name))
+ .to include("refs/#{name}/tmp")
+ end
+ end
+ 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/housekeeping_service_spec.rb b/spec/services/projects/housekeeping_service_spec.rb
index 385f56e447f..9386c110385 100644
--- a/spec/services/projects/housekeeping_service_spec.rb
+++ b/spec/services/projects/housekeeping_service_spec.rb
@@ -23,6 +23,12 @@ describe Projects::HousekeepingService do
expect(project.reload.pushes_since_gc).to eq(0)
end
+ it 'yields the block if given' do
+ expect do |block|
+ subject.execute(&block)
+ end.to yield_with_no_args
+ end
+
context 'when no lease can be obtained' do
before do
expect(subject).to receive(:try_obtain_lease).and_return(false)
@@ -39,6 +45,13 @@ describe Projects::HousekeepingService do
expect { subject.execute }.to raise_error(Projects::HousekeepingService::LeaseTaken)
end.not_to change { project.pushes_since_gc }
end
+
+ it 'does not yield' do
+ expect do |block|
+ expect { subject.execute(&block) }
+ .to raise_error(Projects::HousekeepingService::LeaseTaken)
+ end.not_to yield_with_no_args
+ 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..c2d6d7781b9 100644
--- a/spec/services/system_note_service_spec.rb
+++ b/spec/services/system_note_service_spec.rb
@@ -3,9 +3,9 @@ require 'spec_helper'
describe SystemNoteService do
include Gitlab::Routing
- let(:group) { create(:group) }
- let(:project) { create(:project, group: group) }
- let(:author) { create(:user) }
+ set(:group) { create(:group) }
+ set(:project) { create(:project, :repository, group: group) }
+ set(:author) { create(:user) }
let(:noteable) { create(:issue, project: project) }
let(:issue) { noteable }
@@ -13,45 +13,23 @@ 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
describe '.add_commits' do
subject { described_class.add_commits(noteable, project, author, new_commits, old_commits, oldrev) }
- let(:project) { create(:project, :repository) }
- let(:noteable) { create(:merge_request, source_project: project) }
+ let(:noteable) { create(:merge_request, source_project: project, target_project: project) }
let(:new_commits) { noteable.commits }
let(:old_commits) { [] }
let(:oldrev) { nil }
@@ -206,7 +184,7 @@ describe SystemNoteService do
describe '.change_label' do
subject { described_class.change_label(noteable, project, author, added, removed) }
- let(:labels) { create_list(:label, 2) }
+ let(:labels) { create_list(:label, 2, project: project) }
let(:added) { [] }
let(:removed) { [] }
@@ -315,7 +293,6 @@ describe SystemNoteService do
end
describe '.merge_when_pipeline_succeeds' do
- let(:project) { create(:project, :repository) }
let(:pipeline) { build(:ci_pipeline_without_jobs )}
let(:noteable) do
create(:merge_request, source_project: project, target_project: project)
@@ -333,7 +310,6 @@ describe SystemNoteService do
end
describe '.cancel_merge_when_pipeline_succeeds' do
- let(:project) { create(:project, :repository) }
let(:noteable) do
create(:merge_request, source_project: project, target_project: project)
end
@@ -411,7 +387,6 @@ describe SystemNoteService do
describe '.change_branch' do
subject { described_class.change_branch(noteable, project, author, 'target', old_branch, new_branch) }
- let(:project) { create(:project, :repository) }
let(:old_branch) { 'old_branch'}
let(:new_branch) { 'new_branch'}
@@ -429,8 +404,6 @@ describe SystemNoteService do
describe '.change_branch_presence' do
subject { described_class.change_branch_presence(noteable, project, author, :source, 'feature', :delete) }
- let(:project) { create(:project, :repository) }
-
it_behaves_like 'a system note' do
let(:action) { 'branch' }
end
@@ -445,8 +418,6 @@ describe SystemNoteService do
describe '.new_issue_branch' do
subject { described_class.new_issue_branch(noteable, project, author, "1-mepmep") }
- let(:project) { create(:project, :repository) }
-
it_behaves_like 'a system note' do
let(:action) { 'branch' }
end
@@ -492,7 +463,7 @@ describe SystemNoteService do
describe 'note_body' do
context 'cross-project' do
- let(:project2) { create(:project, :repository) }
+ let(:project2) { create(:project, :repository) }
let(:mentioner) { create(:issue, project: project2) }
context 'from Commit' do
@@ -512,7 +483,6 @@ describe SystemNoteService do
context 'within the same project' do
context 'from Commit' do
- let(:project) { create(:project, :repository) }
let(:mentioner) { project.repository.commit }
it 'references the mentioning commit' do
@@ -554,7 +524,6 @@ describe SystemNoteService do
end
context 'when mentioner is a MergeRequest' do
- let(:project) { create(:project, :repository) }
let(:mentioner) { create(:merge_request, :simple, source_project: project) }
let(:noteable) { project.commit }
@@ -582,7 +551,6 @@ describe SystemNoteService do
end
describe '.cross_reference_exists?' do
- let(:project) { create(:project, :repository) }
let(:commit0) { project.commit }
let(:commit1) { project.commit('HEAD~2') }
@@ -920,9 +888,8 @@ describe SystemNoteService do
end
describe '.discussion_continued_in_issue' do
- let(:discussion) { create(:diff_note_on_merge_request).to_discussion }
+ let(:discussion) { create(:diff_note_on_merge_request, project: project).to_discussion }
let(:merge_request) { discussion.noteable }
- let(:project) { merge_request.source_project }
let(:issue) { create(:issue, project: project) }
def reloaded_merge_request
@@ -1044,7 +1011,6 @@ describe SystemNoteService do
end
describe '.add_merge_request_wip_from_commit' do
- let(:project) { create(:project, :repository) }
let(:noteable) do
create(:merge_request, source_project: project, target_project: project)
end
@@ -1099,9 +1065,8 @@ describe SystemNoteService do
end
describe '.diff_discussion_outdated' do
- let(:discussion) { create(:diff_note_on_merge_request).to_discussion }
+ let(:discussion) { create(:diff_note_on_merge_request, project: project).to_discussion }
let(:merge_request) { discussion.noteable }
- let(:project) { merge_request.source_project }
let(:change_position) { discussion.position }
def reloaded_merge_request
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/update_service_spec.rb b/spec/services/users/update_service_spec.rb
index 985f6d94876..6ee35a33b2d 100644
--- a/spec/services/users/update_service_spec.rb
+++ b/spec/services/users/update_service_spec.rb
@@ -37,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')
@@ -49,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/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/support/stub_env.rb b/spec/support/stub_env.rb
index b8928867174..19fbe572930 100644
--- a/spec/support/stub_env.rb
+++ b/spec/support/stub_env.rb
@@ -1,5 +1,7 @@
# Inspired by https://github.com/ljkbennett/stub_env/blob/master/lib/stub_env/helpers.rb
module StubENV
+ include Gitlab::CurrentSettings
+
def stub_env(key_or_hash, value = nil)
init_stub unless env_stubbed?
if key_or_hash.is_a? Hash
diff --git a/spec/views/admin/dashboard/index.html.haml_spec.rb b/spec/views/admin/dashboard/index.html.haml_spec.rb
index df742bf6848..b4359d819a0 100644
--- a/spec/views/admin/dashboard/index.html.haml_spec.rb
+++ b/spec/views/admin/dashboard/index.html.haml_spec.rb
@@ -9,6 +9,7 @@ describe 'admin/dashboard/index.html.haml' do
assign(:groups, create_list(:group, 1))
allow(view).to receive(:admin?).and_return(true)
+ allow(view).to receive(:current_application_settings).and_return(Gitlab::CurrentSettings.current_application_settings)
end
it "shows version of GitLab Workhorse" do
diff --git a/spec/views/devise/shared/_signin_box.html.haml_spec.rb b/spec/views/devise/shared/_signin_box.html.haml_spec.rb
index 9adbb0476be..0870b8f09f9 100644
--- a/spec/views/devise/shared/_signin_box.html.haml_spec.rb
+++ b/spec/views/devise/shared/_signin_box.html.haml_spec.rb
@@ -5,6 +5,7 @@ describe 'devise/shared/_signin_box' do
before do
stub_devise
assign(:ldap_servers, [])
+ allow(view).to receive(:current_application_settings).and_return(Gitlab::CurrentSettings.current_application_settings)
end
it 'is shown when Crowd is enabled' do
diff --git a/spec/views/help/index.html.haml_spec.rb b/spec/views/help/index.html.haml_spec.rb
index 1f8261cc46b..c030129559e 100644
--- a/spec/views/help/index.html.haml_spec.rb
+++ b/spec/views/help/index.html.haml_spec.rb
@@ -37,5 +37,6 @@ describe 'help/index' do
def stub_helpers
allow(view).to receive(:markdown).and_return('')
allow(view).to receive(:version_status_badge).and_return('')
+ allow(view).to receive(:current_application_settings).and_return(Gitlab::CurrentSettings.current_application_settings)
end
end
diff --git a/spec/views/layouts/_head.html.haml_spec.rb b/spec/views/layouts/_head.html.haml_spec.rb
index 8020faa1f9c..e8e6d2e7a75 100644
--- a/spec/views/layouts/_head.html.haml_spec.rb
+++ b/spec/views/layouts/_head.html.haml_spec.rb
@@ -1,6 +1,10 @@
require 'spec_helper'
describe 'layouts/_head' do
+ before do
+ allow(view).to receive(:current_application_settings).and_return(Gitlab::CurrentSettings.current_application_settings)
+ end
+
it 'escapes HTML-safe strings in page_title' do
stub_helper_with_safe_string(:page_title)
diff --git a/spec/views/projects/commits/_commit.html.haml_spec.rb b/spec/views/projects/commits/_commit.html.haml_spec.rb
index 4c247361bd7..00547e433c4 100644
--- a/spec/views/projects/commits/_commit.html.haml_spec.rb
+++ b/spec/views/projects/commits/_commit.html.haml_spec.rb
@@ -1,6 +1,10 @@
require 'spec_helper'
describe 'projects/commits/_commit.html.haml' do
+ before do
+ allow(view).to receive(:current_application_settings).and_return(Gitlab::CurrentSettings.current_application_settings)
+ end
+
context 'with a singed commit' do
let(:project) { create(:project, :repository) }
let(:repository) { project.repository }
diff --git a/spec/views/projects/edit.html.haml_spec.rb b/spec/views/projects/edit.html.haml_spec.rb
index 1af422941d7..c1398629749 100644
--- a/spec/views/projects/edit.html.haml_spec.rb
+++ b/spec/views/projects/edit.html.haml_spec.rb
@@ -10,7 +10,9 @@ describe 'projects/edit' do
assign(:project, project)
allow(controller).to receive(:current_user).and_return(user)
- allow(view).to receive_messages(current_user: user, can?: true)
+ allow(view).to receive_messages(current_user: user,
+ can?: true,
+ current_application_settings: Gitlab::CurrentSettings.current_application_settings)
end
context 'LFS enabled setting' do
diff --git a/spec/views/projects/merge_requests/creations/_new_submit.html.haml_spec.rb b/spec/views/projects/merge_requests/creations/_new_submit.html.haml_spec.rb
index 5770cf92b4e..9ab105c3238 100644
--- a/spec/views/projects/merge_requests/creations/_new_submit.html.haml_spec.rb
+++ b/spec/views/projects/merge_requests/creations/_new_submit.html.haml_spec.rb
@@ -14,6 +14,7 @@ describe 'projects/merge_requests/creations/_new_submit.html.haml' do
allow(view).to receive(:can?).and_return(true)
allow(view).to receive(:url_for).and_return('#')
allow(view).to receive(:current_user).and_return(merge_request.author)
+ allow(view).to receive(:current_application_settings).and_return(Gitlab::CurrentSettings.current_application_settings)
end
context 'when there are pipelines for merge request but no pipeline for last commit' do
diff --git a/spec/views/projects/merge_requests/show.html.haml_spec.rb b/spec/views/projects/merge_requests/show.html.haml_spec.rb
index dc2fcc3e715..6f29d12373a 100644
--- a/spec/views/projects/merge_requests/show.html.haml_spec.rb
+++ b/spec/views/projects/merge_requests/show.html.haml_spec.rb
@@ -25,7 +25,9 @@ describe 'projects/merge_requests/show.html.haml' do
assign(:notes, [])
assign(:pipelines, Ci::Pipeline.none)
- allow(view).to receive_messages(current_user: user, can?: true)
+ allow(view).to receive_messages(current_user: user,
+ can?: true,
+ current_application_settings: Gitlab::CurrentSettings.current_application_settings)
end
context 'when the merge request is closed' do
diff --git a/spec/views/projects/tree/show.html.haml_spec.rb b/spec/views/projects/tree/show.html.haml_spec.rb
index 33eba3e6d3d..3c25e341b39 100644
--- a/spec/views/projects/tree/show.html.haml_spec.rb
+++ b/spec/views/projects/tree/show.html.haml_spec.rb
@@ -12,6 +12,7 @@ describe 'projects/tree/show' do
allow(view).to receive(:can?).and_return(true)
allow(view).to receive(:can_collaborate_with_project?).and_return(true)
+ allow(view).to receive(:current_application_settings).and_return(Gitlab::CurrentSettings.current_application_settings)
end
context 'for branch names ending on .json' do
diff --git a/spec/views/shared/projects/_project.html.haml_spec.rb b/spec/views/shared/projects/_project.html.haml_spec.rb
index b500016016a..f0a4f153699 100644
--- a/spec/views/shared/projects/_project.html.haml_spec.rb
+++ b/spec/views/shared/projects/_project.html.haml_spec.rb
@@ -3,6 +3,10 @@ require 'spec_helper'
describe 'shared/projects/_project.html.haml' do
let(:project) { create(:project) }
+ before do
+ allow(view).to receive(:current_application_settings).and_return(Gitlab::CurrentSettings.current_application_settings)
+ end
+
it 'should render creator avatar if project has a creator' do
render 'shared/projects/project', use_creator_avatar: true, project: project
diff --git a/spec/workers/authorized_projects_worker_spec.rb b/spec/workers/authorized_projects_worker_spec.rb
index f8385ae7c72..90ed1309d4a 100644
--- a/spec/workers/authorized_projects_worker_spec.rb
+++ b/spec/workers/authorized_projects_worker_spec.rb
@@ -3,28 +3,75 @@ 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
+
+ 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
- described_class.bulk_perform_and_wait([[project.owner.id]])
+ 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
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/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/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