summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--.gitlab-ci.yml3
-rw-r--r--CHANGELOG.md228
-rw-r--r--CONTRIBUTING.md2
-rw-r--r--GITLAB_SHELL_VERSION2
-rw-r--r--Gemfile5
-rw-r--r--Gemfile.lock25
-rw-r--r--app/assets/images/new_nav.pngbin0 -> 23771 bytes
-rw-r--r--app/assets/images/old_nav.pngbin0 -> 25617 bytes
-rw-r--r--app/assets/javascripts/behaviors/quick_submit.js2
-rw-r--r--app/assets/javascripts/dispatcher.js4
-rw-r--r--app/assets/javascripts/environments/components/environment_actions.vue11
-rw-r--r--app/assets/javascripts/environments/components/environment_external_url.vue9
-rw-r--r--app/assets/javascripts/environments/components/environment_monitoring.vue9
-rw-r--r--app/assets/javascripts/environments/components/environment_stop.vue8
-rw-r--r--app/assets/javascripts/environments/components/environment_terminal_button.vue8
-rw-r--r--app/assets/javascripts/experimental_flags.js11
-rw-r--r--app/assets/javascripts/issue_show/components/fields/description.vue3
-rw-r--r--app/assets/javascripts/issue_show/components/fields/project_move.vue12
-rw-r--r--app/assets/javascripts/issue_show/components/fields/title.vue3
-rw-r--r--app/assets/javascripts/label_manager.js6
-rw-r--r--app/assets/javascripts/lib/utils/text_utility.js4
-rw-r--r--app/assets/javascripts/locale/bg/app.js1
-rw-r--r--app/assets/javascripts/locale/de/app.js1
-rw-r--r--app/assets/javascripts/locale/en/app.js1
-rw-r--r--app/assets/javascripts/locale/eo/app.js1
-rw-r--r--app/assets/javascripts/locale/es/app.js1
-rw-r--r--app/assets/javascripts/locale/fr/app.js1
-rw-r--r--app/assets/javascripts/locale/pt_BR/app.js1
-rw-r--r--app/assets/javascripts/locale/zh_CN/app.js1
-rw-r--r--app/assets/javascripts/locale/zh_HK/app.js1
-rw-r--r--app/assets/javascripts/locale/zh_TW/app.js1
-rw-r--r--app/assets/javascripts/main.js3
-rw-r--r--app/assets/javascripts/pipeline_schedules/components/interval_pattern_input.js148
-rw-r--r--app/assets/javascripts/pipeline_schedules/components/interval_pattern_input.vue144
-rw-r--r--app/assets/javascripts/pipeline_schedules/pipeline_schedule_form_bundle.js35
-rw-r--r--app/assets/javascripts/pipelines/components/async_button.vue11
-rw-r--r--app/assets/javascripts/pipelines/components/graph/action_component.vue11
-rw-r--r--app/assets/javascripts/pipelines/components/graph/dropdown_action_component.vue11
-rw-r--r--app/assets/javascripts/pipelines/components/graph/dropdown_job_component.vue12
-rw-r--r--app/assets/javascripts/pipelines/components/graph/job_component.vue14
-rw-r--r--app/assets/javascripts/pipelines/components/pipeline_url.vue16
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_actions.vue10
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_artifacts.vue12
-rw-r--r--app/assets/javascripts/pipelines/components/stage.vue13
-rw-r--r--app/assets/javascripts/pipelines/components/time_ago.vue8
-rw-r--r--app/assets/javascripts/sidebar/components/assignees/assignee_title.js18
-rw-r--r--app/assets/javascripts/sidebar/components/assignees/sidebar_assignees.js2
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline.js9
-rw-r--r--app/assets/javascripts/vue_shared/components/header_ci_component.vue12
-rw-r--r--app/assets/javascripts/vue_shared/components/markdown/header.vue12
-rw-r--r--app/assets/javascripts/vue_shared/components/markdown/toolbar_button.vue10
-rw-r--r--app/assets/javascripts/vue_shared/components/time_ago_tooltip.vue12
-rw-r--r--app/assets/javascripts/vue_shared/components/user_avatar/user_avatar_image.vue8
-rw-r--r--app/assets/javascripts/vue_shared/directives/tooltip.js13
-rw-r--r--app/assets/javascripts/vue_shared/mixins/tooltip.js13
-rw-r--r--app/assets/stylesheets/framework/files.scss2
-rw-r--r--app/assets/stylesheets/framework/header.scss17
-rw-r--r--app/assets/stylesheets/framework/variables.scss4
-rw-r--r--app/assets/stylesheets/new_nav.scss267
-rw-r--r--app/assets/stylesheets/pages/issuable.scss10
-rw-r--r--app/assets/stylesheets/pages/labels.scss1
-rw-r--r--app/assets/stylesheets/pages/notes.scss2
-rw-r--r--app/controllers/admin/users_controller.rb39
-rw-r--r--app/controllers/profiles/avatars_controller.rb3
-rw-r--r--app/controllers/profiles/emails_controller.rb7
-rw-r--r--app/controllers/profiles/notifications_controller.rb4
-rw-r--r--app/controllers/profiles/passwords_controller.rb22
-rw-r--r--app/controllers/profiles/preferences_controller.rb4
-rw-r--r--app/controllers/profiles/two_factor_auths_controller.rb13
-rw-r--r--app/controllers/profiles_controller.rb41
-rw-r--r--app/controllers/projects/pipelines_controller.rb7
-rw-r--r--app/controllers/sessions_controller.rb7
-rw-r--r--app/finders/issues_finder.rb2
-rw-r--r--app/helpers/application_helper.rb8
-rw-r--r--app/helpers/button_helper.rb11
-rw-r--r--app/helpers/graph_helper.rb9
-rw-r--r--app/helpers/labels_helper.rb15
-rw-r--r--app/helpers/projects_helper.rb17
-rw-r--r--app/models/concerns/has_status.rb23
-rw-r--r--app/models/environment.rb1
-rw-r--r--app/models/merge_request.rb9
-rw-r--r--app/models/network/graph.rb2
-rw-r--r--app/models/project.rb19
-rw-r--r--app/models/project_feature.rb2
-rw-r--r--app/models/project_services/prometheus_service.rb2
-rw-r--r--app/models/user.rb27
-rw-r--r--app/services/emails/base_service.rb8
-rw-r--r--app/services/emails/create_service.rb7
-rw-r--r--app/services/emails/destroy_service.rb17
-rw-r--r--app/services/users/build_service.rb1
-rw-r--r--app/services/users/create_service.rb1
-rw-r--r--app/services/users/update_service.rb34
-rw-r--r--app/views/admin/runners/index.html.haml35
-rw-r--r--app/views/groups/_home_panel.html.haml2
-rw-r--r--app/views/layouts/_head.html.haml3
-rw-r--r--app/views/layouts/application.html.haml5
-rw-r--r--app/views/layouts/header/_default.html.haml3
-rw-r--r--app/views/layouts/header/_new.html.haml93
-rw-r--r--app/views/layouts/header/_new_dropdown.haml8
-rw-r--r--app/views/layouts/nav/_new_dashboard.html.haml33
-rw-r--r--app/views/layouts/nav/_new_explore.html.haml19
-rw-r--r--app/views/profiles/preferences/show.html.haml19
-rw-r--r--app/views/profiles/show.html.haml2
-rw-r--r--app/views/projects/blame/show.html.haml2
-rw-r--r--app/views/projects/blob/_breadcrumb.html.haml2
-rw-r--r--app/views/projects/commits/_commit.html.haml2
-rw-r--r--app/views/projects/deployments/_deployment.html.haml11
-rw-r--r--app/views/projects/environments/show.html.haml4
-rw-r--r--app/views/projects/issues/_merge_requests.html.haml2
-rw-r--r--app/views/projects/pipelines/charts.html.haml4
-rw-r--r--app/views/projects/pipelines/charts/_overall.haml12
-rw-r--r--app/views/projects/pipelines/charts/_pipeline_times.haml (renamed from app/views/projects/pipelines/charts/_build_times.haml)4
-rw-r--r--app/views/projects/pipelines/charts/_pipelines.haml (renamed from app/views/projects/pipelines/charts/_builds.haml)0
-rw-r--r--app/views/shared/_label.html.haml41
-rw-r--r--app/views/shared/_label_row.html.haml4
-rw-r--r--app/views/shared/_no_password.html.haml7
-rw-r--r--app/views/shared/_no_ssh.html.haml4
-rw-r--r--app/views/shared/issuable/_sidebar.html.haml4
-rw-r--r--app/views/shared/issuable/_sidebar_assignees.html.haml5
-rw-r--r--app/views/shared/milestones/_issuable.html.haml2
-rw-r--r--app/views/shared/milestones/_milestone.html.haml2
-rw-r--r--app/views/shared/projects/_project.html.haml2
-rwxr-xr-xbin/ci/upgrade.rb3
-rw-r--r--changelogs/unreleased/10378-promote-blameless-culture.yml4
-rw-r--r--changelogs/unreleased/12614-fix-long-message-from-mr.yml4
-rw-r--r--changelogs/unreleased/12614-fix-long-message.yml4
-rw-r--r--changelogs/unreleased/12910-snippets-description.yml4
-rw-r--r--changelogs/unreleased/14707-allow-activity-feed-to-be-accessible-through-api.yml4
-rw-r--r--changelogs/unreleased/17489-hide-code-from-guests.yml4
-rw-r--r--changelogs/unreleased/18927-reorder-issue-action-buttons.yml4
-rw-r--r--changelogs/unreleased/19107-404-when-creating-new-milestone-or-issue-for-project-that-has-issues-disabled.yml4
-rw-r--r--changelogs/unreleased/20517-delete-projects-issuescontroller-redirect_old.yml4
-rw-r--r--changelogs/unreleased/23036-replace-all-spinach-tests-with-rspec-feature-tests.yml4
-rw-r--r--changelogs/unreleased/23036-replace-dashboard-mr-spinach.yml4
-rw-r--r--changelogs/unreleased/23036-replace-dashboard-todo-spinach.yml4
-rw-r--r--changelogs/unreleased/23603-add-extra-functionality-for-the-top-right-button.yml4
-rw-r--r--changelogs/unreleased/24032-when-changing-project-visibility-setting-change-other-dropdowns-automatically.yml4
-rw-r--r--changelogs/unreleased/24196-protected-variables.yml5
-rw-r--r--changelogs/unreleased/24373-warning-message-go-away.yml4
-rw-r--r--changelogs/unreleased/25373-jira-links.yml4
-rw-r--r--changelogs/unreleased/25426-group-dashboard-ui.yml4
-rw-r--r--changelogs/unreleased/25680-CI_ENVIRONMENT_URL.yml4
-rw-r--r--changelogs/unreleased/26325-system-hooks.yml4
-rw-r--r--changelogs/unreleased/27148-limit-bulk-create-memberships.yml4
-rw-r--r--changelogs/unreleased/27439-memory-usage-info.yml4
-rw-r--r--changelogs/unreleased/27614-improve-instant-comments-exp.yml4
-rw-r--r--changelogs/unreleased/28080-system-checks.yml4
-rw-r--r--changelogs/unreleased/28607-forking-and-configuring-project-via-api-works-very-unreliable.yml4
-rw-r--r--changelogs/unreleased/28694-hard-delete-user-from-admin-panel.yml4
-rw-r--r--changelogs/unreleased/28694-hard-delete-user-from-api.yml4
-rw-r--r--changelogs/unreleased/29010-perf-bar.yml4
-rw-r--r--changelogs/unreleased/29118-add-prometheus-instrumenting-to-gitlab-webapp.yml4
-rw-r--r--changelogs/unreleased/29690-rotate-otp-key-base.yml4
-rw-r--r--changelogs/unreleased/29852-latex-formatting.yml4
-rw-r--r--changelogs/unreleased/30378-simplified-repository-settings-page.yml4
-rw-r--r--changelogs/unreleased/30410-revert-9347-and-10079.yml5
-rw-r--r--changelogs/unreleased/30469-convdev-index.yml4
-rw-r--r--changelogs/unreleased/30651-improve-container-registry-description.yml4
-rw-r--r--changelogs/unreleased/30827-changes-to-audit-log.yml4
-rw-r--r--changelogs/unreleased/30892-add-api-support-for-pipeline-schedule.yml4
-rw-r--r--changelogs/unreleased/30917-wiki-is-not-searchable-with-guest-permissions.yml4
-rw-r--r--changelogs/unreleased/30949-empty-states.yml4
-rw-r--r--changelogs/unreleased/31061-26135-ci-project-slug-enviroment-variables.yml4
-rw-r--r--changelogs/unreleased/31384-new-issue-button-on-no-results-page-after-search-doesn-t-go-to-correct-form.yml4
-rw-r--r--changelogs/unreleased/31448-jira-urls.yml4
-rw-r--r--changelogs/unreleased/31474-issue-boards-sidebar-milestone-dropdown-should-not-be-multi-select.yml4
-rw-r--r--changelogs/unreleased/31483-ordered-task-list.yml4
-rw-r--r--changelogs/unreleased/31510-mask-password-field-edit.yml4
-rw-r--r--changelogs/unreleased/31511-jira-settings.yml4
-rw-r--r--changelogs/unreleased/31554-update-rufus-scheduler-and-sidekiq.yml5
-rw-r--r--changelogs/unreleased/31602-display-whether-shared-runner-is-enabled-in-the-admin-dashboard.yml4
-rw-r--r--changelogs/unreleased/31616-add-uptime-of-gitlab-instance-in-admin-area.yml4
-rw-r--r--changelogs/unreleased/31625-tag-editor-loses-all-inputs-when-you-try-to-add-a-tag-that-already-exists.yml4
-rw-r--r--changelogs/unreleased/31633-animate-issue.yml4
-rw-r--r--changelogs/unreleased/31644-make-cookie-sessions-unique.yml4
-rw-r--r--changelogs/unreleased/31757-single-click-on-filter-in-search-bar-to-activate-dropdown.yml4
-rw-r--r--changelogs/unreleased/31781-print-rendered-files-not-possible.yml4
-rw-r--r--changelogs/unreleased/31840-add-a-rubocop-that-forbids-redirect_to-inside-a-controller-destroy-action-without-an-explicit-status.yml4
-rw-r--r--changelogs/unreleased/31849-pipeline-real-time-header.yml4
-rw-r--r--changelogs/unreleased/31849-pipeline-show-view-realtime.yml5
-rw-r--r--changelogs/unreleased/31902-namespace-recent-searches-to-project.yml4
-rw-r--r--changelogs/unreleased/3191-deploy-keys-update.yml4
-rw-r--r--changelogs/unreleased/31943-document-go-183.yml3
-rw-r--r--changelogs/unreleased/31983-increase-merge-request-diff-file-size-limit-for-default-toggle-opening.yml4
-rw-r--r--changelogs/unreleased/31998-pipelines-empty-state.yml4
-rw-r--r--changelogs/unreleased/32086-atwho-is-still-enabled-for-personal-snippet-comments-form.yml4
-rw-r--r--changelogs/unreleased/32118-new-environment-btn-copy.yml4
-rw-r--r--changelogs/unreleased/32219-speed-up-yarn-install-in-ci-by-utilizing-inter-pipeline-cache.yml4
-rw-r--r--changelogs/unreleased/32395-duplicate-string-in-https-docs-gitlab-com-ce-administration-environment_variables-html.yml4
-rw-r--r--changelogs/unreleased/32418-make-link-to-self-less-obvious.yml4
-rw-r--r--changelogs/unreleased/32570-project-activity-tab-border.yml4
-rw-r--r--changelogs/unreleased/32598-avoid-resource-intensive-login-checks-if-password-is-not-provided-for-git-http.yml4
-rw-r--r--changelogs/unreleased/32642_last_commit_id_in_file_api.yml4
-rw-r--r--changelogs/unreleased/32682-skipped-ci-icon.yml4
-rw-r--r--changelogs/unreleased/32720-emoji-spacing.yml4
-rw-r--r--changelogs/unreleased/32799-remove-no_turbolink-attribute-from-haml.yml4
-rw-r--r--changelogs/unreleased/32807-company-icon.yml4
-rw-r--r--changelogs/unreleased/32832-confidential-issue-overflow.yml5
-rw-r--r--changelogs/unreleased/32851-postgres-min-version.yml4
-rw-r--r--changelogs/unreleased/32955-special-keywords.yml4
-rw-r--r--changelogs/unreleased/32983-merge-conflict-resolution-removed-the-newline-in-the-end-of-file.yml4
-rw-r--r--changelogs/unreleased/32992-consider-using-zopfli-over-standard-gzip-compression-for-webpack-assets.yml4
-rw-r--r--changelogs/unreleased/33000-tag-list-in-project-create-api.yml4
-rw-r--r--changelogs/unreleased/33032-invalid-you-directly-addressed-yourself-todo-when-using-unsubscribe.yml5
-rw-r--r--changelogs/unreleased/33154-permissions-for-project-labels-and-group-labels.yml4
-rw-r--r--changelogs/unreleased/33207-show-delete-option-in-admin-users-page.yml4
-rw-r--r--changelogs/unreleased/33215-fix-hard-delete-of-users.yml4
-rw-r--r--changelogs/unreleased/33242-create-project-for-user-api-ignores-path-parameter.yml4
-rw-r--r--changelogs/unreleased/33245-chinese_translation_of_cycle_analytics_page.yml4
-rw-r--r--changelogs/unreleased/33308-use-pre-wrap-for-commit-messages.yml4
-rw-r--r--changelogs/unreleased/33334-portuguese_brazil_translation_of_cycle_analytics_page.yml4
-rw-r--r--changelogs/unreleased/33383-bulgarian_translation_of_cycle_analytics_page.yml4
-rw-r--r--changelogs/unreleased/33442-supplement_traditional_chinese_in_hong_kong_translation_of_i18n.yml4
-rw-r--r--changelogs/unreleased/33561-supplement_bulgarian_translation_of_i18n.yml4
-rw-r--r--changelogs/unreleased/33846-no-runner-for-admin.yml4
-rw-r--r--changelogs/unreleased/33878_fix_edit_deploy_key.yml4
-rw-r--r--changelogs/unreleased/33917-mr-comment-system-note-highlight-don-t-have-the-same-width.yml4
-rw-r--r--changelogs/unreleased/34008-fix-CI_ENVIRONMENT_URL-2.yml4
-rw-r--r--changelogs/unreleased/34010-fix-linking-to-parallel-diff-line-number-creating-gray-box.yml4
-rw-r--r--changelogs/unreleased/34052-store-mr-ref-fetched-in-database.yml4
-rw-r--r--changelogs/unreleased/34207-remove-bin-ci-upgrade-rb.yml4
-rw-r--r--changelogs/unreleased/34286-add-esperanto-translations-for-cycle-analytics-and-project-and-repository-pages.yml4
-rw-r--r--changelogs/unreleased/34289-drop-gfm-on-milestone-issuable-title.yml4
-rw-r--r--changelogs/unreleased/34309-drop-gfm-mr-ms.yml4
-rw-r--r--changelogs/unreleased/UI-improvements-for-count-badges-and-permission-badges.yml5
-rw-r--r--changelogs/unreleased/adam-influxdb-hostname.yml4
-rw-r--r--changelogs/unreleased/add-index-for-auto_canceled_by_id-mysql.yml4
-rw-r--r--changelogs/unreleased/add-unicode-trace-feature-test.yml4
-rw-r--r--changelogs/unreleased/add_ability_to_cancel_attaching_file_and_redesign_attaching_files_ui.yml4
-rw-r--r--changelogs/unreleased/aliyun-backup-provider.yml4
-rw-r--r--changelogs/unreleased/allow-reporters-to-promote-group-labels.yml4
-rw-r--r--changelogs/unreleased/allow_numeric_pages_domain.yml4
-rw-r--r--changelogs/unreleased/allow_numeric_values_in_gitlab_ci_yml.yml4
-rw-r--r--changelogs/unreleased/artifacts-keyboard-shortcuts.yml4
-rw-r--r--changelogs/unreleased/auto-search-when-state-changed.yml4
-rw-r--r--changelogs/unreleased/bugfix-v3-deploy_keys-can_push.yml4
-rw-r--r--changelogs/unreleased/bvl-rename-build-events-to-job-events.yml4
-rw-r--r--changelogs/unreleased/bvl-translate-project-pages.yml4
-rw-r--r--changelogs/unreleased/ce-31853-projects-shared-groups.yml4
-rw-r--r--changelogs/unreleased/ce-32623-browser-tooltip-commits-branch-list.yml5
-rw-r--r--changelogs/unreleased/ci-build-pipeline-header-vue.yml4
-rw-r--r--changelogs/unreleased/disable-blocked-manual-actions.yml4
-rw-r--r--changelogs/unreleased/disable-environment-list-refresh.yml4
-rw-r--r--changelogs/unreleased/dm-async-tree-readme.yml4
-rw-r--r--changelogs/unreleased/dm-auxiliary-viewers.yml5
-rw-r--r--changelogs/unreleased/dm-comment-on-mr-commit-discussion.yml4
-rw-r--r--changelogs/unreleased/dm-commit-row-browse-button.yml4
-rw-r--r--changelogs/unreleased/dm-consistent-commit-sha-style.yml4
-rw-r--r--changelogs/unreleased/dm-consistent-last-push-event.yml4
-rw-r--r--changelogs/unreleased/dm-copy-as-gfm-without-empty-elements.yml4
-rw-r--r--changelogs/unreleased/dm-copy-gfm-when-parts-of-other-elements-are-selected.yml4
-rw-r--r--changelogs/unreleased/dm-dependency-linker-gemfile.yml4
-rw-r--r--changelogs/unreleased/dm-discussions-n-plus-1.yml4
-rw-r--r--changelogs/unreleased/dm-emails-are-not-user-references.yml4
-rw-r--r--changelogs/unreleased/dm-fix-jump-button.yml4
-rw-r--r--changelogs/unreleased/dm-fix-parser-cache.yml4
-rw-r--r--changelogs/unreleased/dm-gitmodules-parsing.yml4
-rw-r--r--changelogs/unreleased/dm-gravatar-username.yml4
-rw-r--r--changelogs/unreleased/dm-group-page-name.yml4
-rw-r--r--changelogs/unreleased/dm-more-dependency-linkers.yml4
-rw-r--r--changelogs/unreleased/dm-oauth-config-for.yml4
-rw-r--r--changelogs/unreleased/dm-outdated-system-note.yml4
-rw-r--r--changelogs/unreleased/dm-paste-code-inside-gfm-code.yml4
-rw-r--r--changelogs/unreleased/dm-revert-mr-8427.yml4
-rw-r--r--changelogs/unreleased/dm-tree-last-commit.yml4
-rw-r--r--changelogs/unreleased/document-foreign-keys.yml4
-rw-r--r--changelogs/unreleased/dturner-username.yml4
-rw-r--r--changelogs/unreleased/dz-fix-submodule-subgroup.yml4
-rw-r--r--changelogs/unreleased/dz-project-list-cache-key.yml4
-rw-r--r--changelogs/unreleased/dz-rename-pipelines-settings-tab.yml4
-rw-r--r--changelogs/unreleased/enable-auto-cancelling-by-default.yml4
-rw-r--r--changelogs/unreleased/environment-detail-view.yml4
-rw-r--r--changelogs/unreleased/expand-backlog-closed-lists-issue-boards.yml4
-rw-r--r--changelogs/unreleased/feature-flags-flipper.yml4
-rw-r--r--changelogs/unreleased/feature-gb-persist-pipeline-stages.yml4
-rw-r--r--changelogs/unreleased/feature-print-go-version-in-env-info.yml4
-rw-r--r--changelogs/unreleased/feature-rss-scoped-token.yml4
-rw-r--r--changelogs/unreleased/fix-33259.yml4
-rw-r--r--changelogs/unreleased/fix-33991.yml4
-rw-r--r--changelogs/unreleased/fix-counter-cache-for-acts-as-taggable.yml4
-rw-r--r--changelogs/unreleased/fix-encoding-binary-issue.yml4
-rw-r--r--changelogs/unreleased/fix-gb-exclude-manual-actions-from-cancelable-jobs.yml4
-rw-r--r--changelogs/unreleased/fix-gb-fix-skipped-pipeline-with-allowed-to-fail-jobs.yml4
-rw-r--r--changelogs/unreleased/fix-github-clone-wiki.yml4
-rw-r--r--changelogs/unreleased/fix-github-import.yml4
-rw-r--r--changelogs/unreleased/fix-head-pipeline-for-commit-status.yml4
-rw-r--r--changelogs/unreleased/fix-n-plus-one-queries-for-user-access.yml4
-rw-r--r--changelogs/unreleased/fix-support-for-external-ci-services.yml4
-rw-r--r--changelogs/unreleased/fix_commits_page.yml4
-rw-r--r--changelogs/unreleased/fix_diff_line_comments.yml5
-rw-r--r--changelogs/unreleased/gitaly-local-branches.yml4
-rw-r--r--changelogs/unreleased/gitaly-opt-out.yml4
-rw-r--r--changelogs/unreleased/instrument-merge-request-diff-load-commits.yml4
-rw-r--r--changelogs/unreleased/introduce-source-to-pipelines.yml4
-rw-r--r--changelogs/unreleased/issuable-form-create-label-sub-groups.yml4
-rw-r--r--changelogs/unreleased/issue-23254.yml4
-rw-r--r--changelogs/unreleased/issue-edit-inline.yml4
-rw-r--r--changelogs/unreleased/issue-form-multiple-line-markdown.yml4
-rw-r--r--changelogs/unreleased/issue-template-reproduce-in-example-project.yml4
-rw-r--r--changelogs/unreleased/issue-templates-summary-lines.yml4
-rw-r--r--changelogs/unreleased/issue_19262.yml4
-rw-r--r--changelogs/unreleased/issue_27166_2.yml4
-rw-r--r--changelogs/unreleased/issue_27168_2.yml4
-rw-r--r--changelogs/unreleased/issue_32225_2.yml4
-rw-r--r--changelogs/unreleased/jouve-gitlab-ce-admin_keys.yml5
-rw-r--r--changelogs/unreleased/mabes-gitlab-ce-bypass-auto-login.yml4
-rw-r--r--changelogs/unreleased/migrate-artifacts-to-a-new-path.yml4
-rw-r--r--changelogs/unreleased/mk-fix-breadcrumb-order-33938.yml4
-rw-r--r--changelogs/unreleased/mk-fix-git-over-http-rejections.yml4
-rw-r--r--changelogs/unreleased/mk-fix-issue-34068.yml4
-rw-r--r--changelogs/unreleased/mrchrisw-catch-openssl.yml4
-rw-r--r--changelogs/unreleased/omega-submodules.yml4
-rw-r--r--changelogs/unreleased/pat-alert-when-signin-disabled.yml4
-rw-r--r--changelogs/unreleased/polish-sidebar-toggle.yml4
-rw-r--r--changelogs/unreleased/prevent-project-transfer.yml4
-rw-r--r--changelogs/unreleased/projects-api-import-status.yml4
-rw-r--r--changelogs/unreleased/protected-branches-no-one-merge.yml4
-rw-r--r--changelogs/unreleased/reduce-sidekiq-wait-timings.yml4
-rw-r--r--changelogs/unreleased/refactor-projects-finder-init-collection.yml5
-rw-r--r--changelogs/unreleased/remove-old-isobject.yml4
-rw-r--r--changelogs/unreleased/rename-builds-controller.yml4
-rw-r--r--changelogs/unreleased/replace_spinach_spec_profile_notifications-feature.yml4
-rw-r--r--changelogs/unreleased/rework-authorizations-performance.yml6
-rw-r--r--changelogs/unreleased/search-restrict-projects-to-group.yml4
-rw-r--r--changelogs/unreleased/sh-fix-container-registry-s3-redirects.yml4
-rw-r--r--changelogs/unreleased/sh-fix-refactor-uploader-work-dir.yml4
-rw-r--r--changelogs/unreleased/sync-email-from-omniauth.yml4
-rw-r--r--changelogs/unreleased/task-list-2.yml4
-rw-r--r--changelogs/unreleased/tc-cache-trackable-attributes.yml4
-rw-r--r--changelogs/unreleased/tc-clean-pending-delete-projects.yml4
-rw-r--r--changelogs/unreleased/tc-improve-project-api-perf.yml4
-rw-r--r--changelogs/unreleased/tc-refactor-projects-finder-init-collection.yml4
-rw-r--r--changelogs/unreleased/up-arrow-focus-discussion-comment.yml4
-rw-r--r--changelogs/unreleased/update-admin-health-page.yml5
-rw-r--r--changelogs/unreleased/update_bootsnap_1-1-1.yml4
-rw-r--r--changelogs/unreleased/use_relative_path_for_project_avatars.yml4
-rw-r--r--changelogs/unreleased/wait-for-ajax-handling-all-js-requests.yml4
-rw-r--r--changelogs/unreleased/winh-current-user-filter.yml4
-rw-r--r--changelogs/unreleased/winh-pipeline-author-link.yml4
-rw-r--r--changelogs/unreleased/winh-styled-people-search-bar.yml4
-rw-r--r--changelogs/unreleased/zj-clean-up-ci-variables-table.yml4
-rw-r--r--changelogs/unreleased/zj-faster-charts-page.yml4
-rw-r--r--changelogs/unreleased/zj-i18n-pipeline-schedules.yml4
-rw-r--r--changelogs/unreleased/zj-job-view-goes-real-time.yml4
-rw-r--r--changelogs/unreleased/zj-pipeline-schedule-owner.yml4
-rw-r--r--changelogs/unreleased/zj-prom-pipeline-count.yml4
-rw-r--r--changelogs/unreleased/zj-raise-etag-route-regex-miss.yml4
-rw-r--r--changelogs/unreleased/zj-read-registry-pat.yml4
-rw-r--r--changelogs/unreleased/zj-realtime-env-list.yml4
-rw-r--r--changelogs/unreleased/zj-review-apps-usage-data.yml4
-rw-r--r--changelogs/unreleased/zj-sort-env-folders.yml4
-rw-r--r--config/application.rb1
-rw-r--r--config/boot.rb6
-rw-r--r--db/migrate/20170622162730_add_ref_fetched_to_merge_request.rb9
-rw-r--r--db/schema.rb3
-rw-r--r--doc/ci/examples/deployment/composer-npm-deploy.md6
-rw-r--r--doc/ci/quick_start/README.md6
-rw-r--r--doc/development/architecture.md4
-rw-r--r--doc/development/fe_guide/style_guide_js.md12
-rw-r--r--doc/install/requirements.md5
-rw-r--r--doc/user/project/integrations/webhooks.md2
-rw-r--r--doc/user/project/pipelines/settings.md2
-rw-r--r--features/dashboard/merge_requests.feature21
-rw-r--r--features/dashboard/todos.feature28
-rw-r--r--features/group/members.feature59
-rw-r--r--features/profile/notifications.feature15
-rw-r--r--features/steps/dashboard/merge_requests.rb121
-rw-r--r--features/steps/dashboard/todos.rb191
-rw-r--r--features/steps/groups.rb2
-rw-r--r--features/steps/project/source/browse_files.rb1
-rw-r--r--features/steps/shared/paths.rb4
-rw-r--r--lib/api/commit_statuses.rb3
-rw-r--r--lib/api/internal.rb7
-rw-r--r--lib/api/notification_settings.rb5
-rw-r--r--lib/api/users.rb20
-rw-r--r--lib/api/variables.rb2
-rw-r--r--lib/ci/charts.rb18
-rw-r--r--lib/gitlab/database.rb2
-rw-r--r--lib/gitlab/dependency_linker/requirements_txt_linker.rb2
-rw-r--r--lib/gitlab/ee_compat_check.rb21
-rw-r--r--lib/gitlab/exclusive_lease.rb19
-rw-r--r--lib/gitlab/git/commit.rb76
-rw-r--r--lib/gitlab/git/repository.rb78
-rw-r--r--lib/gitlab/i18n.rb3
-rw-r--r--lib/gitlab/import_export/import_export.yml1
-rw-r--r--lib/gitlab/ldap/access.rb4
-rw-r--r--lib/gitlab/o_auth/user.rb2
-rw-r--r--lib/gitlab/usage_data.rb1
-rw-r--r--lib/gitlab/visibility_level.rb2
-rw-r--r--lib/system_check/simple_executor.rb2
-rw-r--r--locale/bg/gitlab.po892
-rw-r--r--locale/eo/gitlab.po1143
-rw-r--r--locale/eo/gitlab.po.time_stamp0
-rw-r--r--locale/zh_HK/gitlab.po907
-rw-r--r--qa/Dockerfile13
-rw-r--r--spec/controllers/profiles/preferences_controller_spec.rb5
-rw-r--r--spec/features/admin/admin_runners_spec.rb61
-rw-r--r--spec/features/dashboard/merge_requests_spec.rb97
-rw-r--r--spec/features/dashboard/milestone_filter_spec.rb22
-rw-r--r--spec/features/dashboard/projects_spec.rb22
-rw-r--r--spec/features/dashboard/todos/target_state_spec.rb (renamed from spec/features/todos/target_state_spec.rb)10
-rw-r--r--spec/features/dashboard/todos/todos_filtering_spec.rb (renamed from spec/features/todos/todos_filtering_spec.rb)14
-rw-r--r--spec/features/dashboard/todos/todos_sorting_spec.rb (renamed from spec/features/todos/todos_sorting_spec.rb)56
-rw-r--r--spec/features/dashboard/todos/todos_spec.rb355
-rw-r--r--spec/features/groups/group_settings_spec.rb8
-rw-r--r--spec/features/groups/labels/subscription_spec.rb51
-rw-r--r--spec/features/groups/members/last_owner_cannot_leave_group_spec.rb16
-rw-r--r--spec/features/groups/members/leave_group_spec.rb62
-rw-r--r--spec/features/groups/members/list_members_spec.rb42
-rw-r--r--spec/features/groups/members/manage_access_requests_spec.rb (renamed from spec/features/groups/members/owner_manages_access_requests_spec.rb)6
-rw-r--r--spec/features/groups/members/manage_members.rb (renamed from spec/features/groups/members/list_spec.rb)52
-rw-r--r--spec/features/groups/members/member_cannot_request_access_to_his_project_spec.rb16
-rw-r--r--spec/features/groups/members/member_leaves_group_spec.rb21
-rw-r--r--spec/features/groups/members/request_access_spec.rb (renamed from spec/features/groups/members/user_requests_access_spec.rb)9
-rw-r--r--spec/features/groups/members/sort_members_spec.rb (renamed from spec/features/groups/members/sorting_spec.rb)2
-rw-r--r--spec/features/login_spec.rb23
-rw-r--r--spec/features/profiles/password_spec.rb2
-rw-r--r--spec/features/profiles/user_visits_notifications_tab_spec.rb21
-rw-r--r--spec/features/projects/blobs/blob_line_permalink_updater_spec.rb2
-rw-r--r--spec/features/projects/environments/environments_spec.rb2
-rw-r--r--spec/features/projects/files/browse_files_spec.rb2
-rw-r--r--spec/features/projects/no_password_spec.rb69
-rw-r--r--spec/features/projects/services/jira_service_spec.rb10
-rw-r--r--spec/features/snippets/notes_on_personal_snippets_spec.rb1
-rw-r--r--spec/features/todos/todos_spec.rb355
-rw-r--r--spec/helpers/button_helper_spec.rb65
-rw-r--r--spec/helpers/groups_helper_spec.rb2
-rw-r--r--spec/helpers/projects_helper_spec.rb76
-rw-r--r--spec/javascripts/behaviors/quick_submit_spec.js21
-rw-r--r--spec/javascripts/environments/environment_actions_spec.js9
-rw-r--r--spec/javascripts/environments/environment_monitoring_spec.js19
-rw-r--r--spec/javascripts/environments/environment_stop_spec.js9
-rw-r--r--spec/javascripts/environments/environment_terminal_button_spec.js9
-rw-r--r--spec/javascripts/issue_show/components/fields/description_spec.js20
-rw-r--r--spec/javascripts/issue_show/components/fields/title_spec.js20
-rw-r--r--spec/javascripts/issue_show/helpers.js10
-rw-r--r--spec/javascripts/pipeline_schedules/interval_pattern_input_spec.js5
-rw-r--r--spec/javascripts/pipelines/stage_spec.js43
-rw-r--r--spec/javascripts/sidebar/assignee_title_spec.js25
-rw-r--r--spec/javascripts/test_bundle.js4
-rw-r--r--spec/javascripts/vue_mr_widget/components/mr_widget_pipeline_spec.js66
-rw-r--r--spec/javascripts/vue_shared/components/markdown/field_spec.js105
-rw-r--r--spec/javascripts/vue_shared/components/time_ago_tooltip_spec.js1
-rw-r--r--spec/javascripts/vue_shared/directives/tooltip_spec.js63
-rw-r--r--spec/lib/ci/charts_spec.rb10
-rw-r--r--spec/lib/gitlab/database_spec.rb4
-rw-r--r--spec/lib/gitlab/dependency_linker/requirements_txt_linker_spec.rb4
-rw-r--r--spec/lib/gitlab/exclusive_lease_spec.rb13
-rw-r--r--spec/lib/gitlab/git/commit_spec.rb47
-rw-r--r--spec/lib/gitlab/git/repository_spec.rb29
-rw-r--r--spec/lib/gitlab/import_export/fork_spec.rb4
-rw-r--r--spec/lib/gitlab/usage_data_spec.rb1
-rw-r--r--spec/lib/gitlab/visibility_level_spec.rb6
-rw-r--r--spec/lib/system_check/simple_executor_spec.rb24
-rw-r--r--spec/models/commit_status_spec.rb35
-rw-r--r--spec/models/concerns/has_status_spec.rb2
-rw-r--r--spec/models/merge_request_spec.rb36
-rw-r--r--spec/models/project_services/bamboo_service_spec.rb4
-rw-r--r--spec/models/project_services/campfire_service_spec.rb11
-rw-r--r--spec/models/project_services/jira_service_spec.rb22
-rw-r--r--spec/models/project_services/prometheus_service_spec.rb7
-rw-r--r--spec/models/project_services/teamcity_service_spec.rb6
-rw-r--r--spec/models/user_spec.rb14
-rw-r--r--spec/requests/api/commit_statuses_spec.rb27
-rw-r--r--spec/requests/api/users_spec.rb19
-rw-r--r--spec/requests/api/variables_spec.rb11
-rw-r--r--spec/services/ci/process_pipeline_service_spec.rb4
-rw-r--r--spec/services/emails/create_service_spec.rb21
-rw-r--r--spec/services/emails/destroy_service_spec.rb14
-rw-r--r--spec/services/projects/destroy_service_spec.rb5
-rw-r--r--spec/services/users/update_service_spec.rb43
-rw-r--r--spec/support/filter_item_select_helper.rb19
-rw-r--r--spec/support/login_helpers.rb21
-rw-r--r--spec/support/stub_env.rb8
-rw-r--r--vendor/Dockerfile/Binary-alpine.Dockerfile14
-rw-r--r--vendor/Dockerfile/Binary-scratch.Dockerfile17
-rw-r--r--vendor/Dockerfile/Binary.Dockerfile11
-rw-r--r--vendor/Dockerfile/Golang-alpine.Dockerfile17
-rw-r--r--vendor/Dockerfile/Golang-scratch.Dockerfile20
-rw-r--r--vendor/Dockerfile/Golang.Dockerfile14
-rw-r--r--vendor/Dockerfile/Node-alpine.Dockerfile14
-rw-r--r--vendor/Dockerfile/Node.Dockerfile14
-rw-r--r--vendor/Dockerfile/Ruby-alpine.Dockerfile24
-rw-r--r--vendor/Dockerfile/Ruby.Dockerfile27
-rw-r--r--vendor/gitignore/Global/Archives.gitignore4
-rw-r--r--vendor/gitignore/Global/JEnv.gitignore5
-rw-r--r--vendor/gitignore/Global/SublimeText.gitignore10
-rw-r--r--vendor/gitignore/Global/Vagrant.gitignore4
-rw-r--r--vendor/gitignore/Global/Vim.gitignore10
-rw-r--r--vendor/gitignore/Global/Windows.gitignore3
-rw-r--r--vendor/gitignore/Global/macOS.gitignore1
-rw-r--r--vendor/gitignore/Python.gitignore8
-rw-r--r--vendor/gitignore/Qt.gitignore8
-rw-r--r--vendor/gitignore/SugarCRM.gitignore4
-rw-r--r--vendor/gitignore/VisualStudio.gitignore7
-rw-r--r--vendor/gitlab-ci-yml/.gitlab-ci.yml4
-rw-r--r--vendor/gitlab-ci-yml/Crystal.gitlab-ci.yml2
-rw-r--r--vendor/gitlab-ci-yml/Django.gitlab-ci.yml2
-rw-r--r--vendor/gitlab-ci-yml/Docker.gitlab-ci.yml8
-rw-r--r--vendor/gitlab-ci-yml/Elixir.gitlab-ci.yml2
-rw-r--r--vendor/gitlab-ci-yml/Laravel.gitlab-ci.yml2
-rw-r--r--vendor/gitlab-ci-yml/Nodejs.gitlab-ci.yml2
-rw-r--r--vendor/gitlab-ci-yml/Pages/JBake.gitlab-ci.yml6
-rw-r--r--vendor/gitlab-ci-yml/Ruby.gitlab-ci.yml2
-rw-r--r--vendor/gitlab-ci-yml/Rust.gitlab-ci.yml2
-rw-r--r--vendor/licenses.csv108
507 files changed, 6634 insertions, 2773 deletions
diff --git a/.gitignore b/.gitignore
index 89da29fd790..e529e33530a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -21,6 +21,7 @@ eslint-report.html
/.yarn-cache
/.byebug_history
/Vagrantfile
+/app/assets/javascripts/locale/**/app.js
/backups/*
/config/aws.yml
/config/database.yml
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 76a95ad6e0a..08aef3dd8ee 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -193,6 +193,7 @@ setup-test-env:
script:
- node --version
- yarn install --pure-lockfile --cache-folder .yarn-cache
+ - bundle exec rake gettext:po_to_json
- bundle exec rake gitlab:assets:compile
- bundle exec ruby -Ispec -e 'require "spec_helper" ; TestEnv.init'
artifacts:
@@ -433,6 +434,7 @@ gitlab:assets:compile:
NO_COMPRESSION: "true"
script:
- yarn install --pure-lockfile --production --cache-folder .yarn-cache
+ - bundle exec rake gettext:po_to_json
- bundle exec rake gitlab:assets:compile
artifacts:
name: webpack-report
@@ -450,6 +452,7 @@ karma:
BABEL_ENV: "coverage"
CHROME_LOG_FILE: "chrome_debug.log"
script:
+ - bundle exec rake gettext:po_to_json
- bundle exec rake karma
coverage: '/^Statements *: (\d+\.\d+%)/'
artifacts:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index af5f5809c41..f372cbf91e8 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,234 @@
documentation](doc/development/changelog.md) for instructions on adding your own
entry.
+## 9.3.2 (2017-06-27)
+
+- API: Fix optional arugments for POST :id/variables. !12474
+- Bump premailer-rails gem to 1.9.7 and its dependencies to prevent network retrieval of assets.
+
+## 9.3.1 (2017-06-26)
+
+- Fix reversed breadcrumb order for nested groups. !12322
+- Fix 500 when failing to create private group. !12394
+- Fix linking to line number on side-by-side diff creating empty discussion box.
+- Don't match tilde and exclamation mark as part of requirements.txt package name.
+- Perform project housekeeping after importing projects.
+- Fixed ctrl+enter not submit issue edit form.
+
+## 9.3.0 (2017-06-22)
+
+- Refactored gitlab:app:check into SystemCheck liberary and improve some checks. !9173
+- Add an ability to cancel attaching file and redesign attaching files UI. !9431 (blackst0ne)
+- Add Aliyun OSS as the backup storage provider. !9721 (Yuanfei Zhu)
+- Add suport for find_local_branches GRPC from Gitaly. !10059
+- Allow manual bypass of auto_sign_in_with_provider with a new param. !10187 (Maxime Besson)
+- Redirect to user's keys index instead of user's index after a key is deleted in the admin. !10227 (Cyril Jouve)
+- Changed Blame to Annotate in the UI to promote blameless culture. !10378 (Ilya Vassilevsky)
+- Implement ability to update deploy keys. !10383 (Alexander Randa)
+- Allow numeric values in gitlab-ci.yml. !10607 (blackst0ne)
+- Add a feature test for Unicode trace. !10736 (dosuken123)
+- Notes: Warning message should go away once resolved. !10823 (Jacopo Beschi @jacopo-beschi)
+- Project authorizations are calculated much faster when using PostgreSQL, and nested groups support for MySQL has been removed
+. !10885
+- Fix long urls in the title of commit. !10938 (Alexander Randa)
+- Update gem sidekiq-cron from 0.4.4 to 0.6.0 and rufus-scheduler from 3.1.10 to 3.4.0. !10976 (dosuken123)
+- Use relative paths for group/project/user avatars. !11001 (blackst0ne)
+- Enable cancelling non-HEAD pending pipelines by default for all projects. !11023
+- Implement web hook logging. !11027 (Alexander Randa)
+- Add indices for auto_canceled_by_id for ci_pipelines and ci_builds on PostgreSQL. !11034
+- Add post-deploy migration to clean up projects in `pending_delete` state. !11044
+- Limit User's trackable attributes, like `current_sign_in_at`, to update at most once/hour. !11053
+- Disallow multiple selections for Milestone dropdown. !11084
+- Link to commit author user page from pipelines. !11100
+- Fix the last coverage in trace log should be extracted. !11128 (dosuken123)
+- Remove redirect for old issue url containing id instead of iid. !11135 (blackst0ne)
+- Backported new SystemHook event: `repository_update`. !11140
+- Keep input data after creating a tag that already exists. !11155
+- Fix support for external CI services. !11176
+- Translate backend for Project & Repository pages. !11183
+- Fix LaTeX formatting for AsciiDoc wiki. !11212
+- Add foreign key for pipeline schedule owner. !11233
+- Print Go version in rake gitlab:env:info. !11241
+- Include the blob content when printing a blob page. !11247
+- Sync email address from specified omniauth provider. !11268 (Robin Bobbitt)
+- Disable reference prefixes in notes for Snippets. !11278
+- Rename build_events to job_events. !11287
+- Add API support for pipeline schedule. !11307 (dosuken123)
+- Use route.cache_key for project list cache key. !11325
+- Make environment table realtime. !11333
+- Cache npm modules between pipelines with yarn to speed up setup-test-env. !11343
+- Allow GitLab instance to start when InfluxDB hostname cannot be resolved. !11356
+- Add ConvDev Index page to admin area. !11377
+- Fix Git-over-HTTP error statuses and improve error messages. !11398
+- Renamed users 'Audit Log'' to 'Authentication Log'. !11400
+- Style people in issuable search bar. !11402
+- Change /builds in the URL to /-/jobs. Backward URLs were also added. !11407
+- Update password field label while editing service settings. !11431
+- Add an optional performance bar to view performance metrics for the current page. !11439
+- Update task_list to version 2.0.0. !11525 (Jared Deckard <jared.deckard@gmail.com>)
+- Avoid resource intensive login checks if password is not provided. !11537 (Horatiu Eugen Vlad)
+- Allow numeric pages domain. !11550
+- Exclude manual actions when checking if pipeline can be canceled. !11562
+- Add server uptime to System Info page in admin dashboard. !11590 (Justin Boltz)
+- Simplify testing and saving service integrations. !11599
+- Fixed handling of the `can_push` attribute in the v3 deploy_keys api. !11607 (Richard Clamp)
+- Improve user experience around slash commands in instant comments. !11612
+- Show current user immediately in issuable filters. !11630
+- Add extra context-sensitive functionality for the top right menu button. !11632
+- Reorder Issue action buttons in order of usability. !11642
+- Expose atom links with an RSS token instead of using the private token. !11647 (Alexis Reigel)
+- Respect merge, instead of push, permissions for protected actions. !11648
+- Job details page update real time. !11651
+- Improve performance of ProjectFinder used in /projects API endpoint. !11666
+- Remove redundant data-turbolink attributes from links. !11672 (blackst0ne)
+- Minimum postgresql version is now 9.2. !11677
+- Add protected variables which would only be passed to protected branches or protected tags. !11688
+- Introduce optimistic locking support via optional parameter last_commit_sha on File Update API. !11694 (electroma)
+- Add $CI_ENVIRONMENT_URL to predefined variables for pipelines. !11695
+- Simplify project repository settings page. !11698
+- Fix pipeline_schedules pages throwing error 500. !11706 (dosuken123)
+- Add performance deltas between app deployments on Merge Request widget. !11730
+- Add feature toggles and API endpoints for admins. !11747
+- Replace 'starred_projects.feature' spinach test with an rspec analog. !11752 (blackst0ne)
+- Introduce an Events API. !11755
+- Display Shared Runner status in Admin Dashboard. !11783 (Ivan Chernov)
+- Persist pipeline stages in the database. !11790
+- Revert the feature that would include the current user's username in the HTTP clone URL. !11792
+- Enable Gitaly by default in installations from source. !11796
+- Use zopfli compression for frontend assets. !11798
+- Add tag_list param to project api. !11799 (Ivan Chernov)
+- Add changelog for improved Registry description. !11816
+- Automatically adjust project settings to match changes in project visibility. !11831
+- Add slugify project path to CI enviroment variables. !11838 (Ivan Chernov)
+- Add all pipeline sources as special keywords to 'only' and 'except'. !11844 (Filip Krakowski)
+- Allow pulling of container images using personal access tokens. !11845
+- Expose import_status in Projects API. !11851 (Robin Bobbitt)
+- Allow admins to delete users from the admin users page. !11852
+- Allow users to be hard-deleted from the API. !11853
+- Fix hard-deleting users when they have authored issues. !11855
+- Fix missing optional path parameter in "Create project for user" API. !11868
+- Allow users to be hard-deleted from the admin panel. !11874
+- Add a Rake task to aid in rotating otp_key_base. !11881
+- Fix submodule link to then project under subgroup. !11906
+- Fix binary encoding error on MR diffs. !11929
+- Limit non-administrators to adding 100 members at a time to groups and projects. !11940
+- add bulgarian translation of cycle analytics page to I18N. !11958 (Lyubomir Vasilev)
+- Make backup task to continue on corrupt repositories. !11962
+- Fix incorrect ETag cache key when relative instance URL is used. !11964
+- Reinstate is_admin flag in users api when authenticated user is an admin. !12211 (rickettm)
+- Fix edit button for deploy keys available from other projects. !12301 (Alexander Randa)
+- Fix passing CI_ENVIRONMENT_NAME and CI_ENVIRONMENT_SLUG for CI_ENVIRONMENT_URL. !12344
+- Disable environment list refresh due to bug https://gitlab.com/gitlab-org/gitlab-ee/issues/2677. !12347
+- Standardize timeline note margins across different viewport sizes. !12364
+- Fix Ordered Task List Items. !31483 (Jared Deckard <jared.deckard@gmail.com>)
+- Upgrade dependency to Go 1.8.3. !31943
+- Add prometheus metrics on pipeline creation.
+- Fix etag route not being a match for environments.
+- Sort folder for environments.
+- Support descriptions for snippets.
+- Hide clone panel and file list when user is only a guest. (James Clark)
+- Don’t create comment on JIRA if it already exists for the entity.
+- Update Dashboard Groups UI with better support for subgroups.
+- Confirm Project forking behaviour via the API.
+- Add prometheus based metrics collection to gitlab webapp.
+- Fix: Wiki is not searchable with Guest permissions.
+- Center all empty states.
+- Remove 'New issue' button when issues search returns no results.
+- Add API URL to JIRA settings.
+- animate adding issue to boards.
+- Update session cookie key name to be unique to instance in development.
+- Single click on filter to open filtered search dropdown.
+- Makes header information of pipeline show page realtine.
+- Creates a mediator for pipeline details vue in order to mount several vue apps with the same data.
+- Scope issue/merge request recent searches to project.
+- Increase individual diff collapse limit to 100 KB, and render limit to 200 KB.
+- Fix Pipelines table empty state - only render empty state if we receive 0 pipelines.
+- Make New environment empty state btn lowercase.
+- Removes duplicate environment variable in documentation.
+- Change links in issuable meta to black.
+- Fix border-bottom for project activity tab.
+- Adds new icon for CI skipped status.
+- Create equal padding for emoji.
+- Use briefcase icon for company in profile page.
+- Remove overflow from comment form for confidential issues and vertically aligns confidential issue icon.
+- Keep trailing newline when resolving conflicts by picking sides.
+- Fix /unsubscribe slash command creating extra todos when you were already mentioned in an issue.
+- Fix math rendering on blob pages.
+- Allow group reporters to manage group labels.
+- Use pre-wrap for commit messages to keep lists indented.
+- Count badges depend on translucent color to better adjust to different background colors and permission badges now feature a pill shaped design similar to labels.
+- Allow reporters to promote project labels to group labels.
+- Enabled keyboard shortcuts on artifacts pages.
+- Perform filtered search when state tab is changed.
+- Remove duplication for sharing projects with groups in project settings.
+- Change order of commits ahead and behind on divergence graph for branch list view.
+- Creates CI Header component for Pipelines and Jobs details pages.
+- Invalidate cache for issue and MR counters more granularly.
+- disable blocked manual actions.
+- Load tree readme asynchronously.
+- Display extra info about files on .gitlab-ci.yml, .gitlab/route-map.yml and LICENSE blob pages.
+- Fix replying to a commit discussion displayed in the context of an MR.
+- Consistently use monospace font for commit SHAs and branch and tag names.
+- Consistently display last push event widget.
+- Don't copy empty elements that were not selected on purpose as GFM.
+- Copy as GFM even when parts of other elements are selected.
+- Autolink package names in Gemfile.
+- Resolve N+1 query issue with discussions.
+- Don't match email addresses or foo@bar as user references.
+- Fix title of discussion jump button at top of page.
+- Don't return nil for missing objects from parser cache.
+- Make .gitmodules parsing more resilient to syntax errors.
+- Add username parameter to gravatar URL.
+- Autolink package names in more dependency files.
+- Return nil when looking up config for unknown LDAP provider.
+- Add system note with link to diff comparison when MR discussion becomes outdated.
+- Don't wrap pasted code when it's already inside code tags.
+- Revert 'New file from interface on existing branch'.
+- Show last commit for current tree on tree page.
+- Add documentation about adding foreign keys.
+- add username field to push webhook. (David Turner)
+- Rename CI/CD Pipelines to Pipelines in the project settings.
+- Make environment tables responsive.
+- Expand/collapse backlog & closed lists in issue boards.
+- Fix GitHub importer performance on branch existence check.
+- Fix counter cache for acts as taggable.
+- Github - Fix token interpolation when cloning wiki repository.
+- Fix token interpolation when setting the Github remote.
+- Fix N+1 queries for non-members in comment threads.
+- Fix terminals support for Kubernetes Service.
+- Fix: A diff comment on a change at last line of a file shows as two comments in discussion.
+- Instrument MergeRequestDiff#load_commits.
+- Introduce source to Pipeline entity.
+- Fixed create new label form in issue form not working for sub-group projects.
+- Fixed style on unsubscribe page. (Gustav Ernberg)
+- Enables inline editing for an issues title & description.
+- Ask for an example project for bug reports.
+- Add summary lines for collapsed details in the bug report template.
+- Prevent commits from upstream repositories to be re-processed by forks.
+- Avoid repeated queries for pipeline builds on merge requests.
+- Preloads head pipeline for merge request collection.
+- Handle head pipeline when creating merge requests.
+- Migrate artifacts to a new path.
+- Rescue OpenSSL::SSL::SSLError in JiraService & IssueTrackerService.
+- Repository browser: handle in-repository submodule urls. (David Turner)
+- Prevent project transfers if a new group is not selected.
+- Allow 'no one' as an option for allowed to merge on a procted branch.
+- Reduce time spent waiting for certain Sidekiq jobs to complete.
+- Refactor ProjectsFinder#init_collection to produce more efficient queries for retrieving projects.
+- Remove unused code and uses underscore.
+- Restricts search projects dropdown to group projects when group is selected.
+- Properly handle container registry redirects to fix metadata stored on a S3 backend.
+- Fix LFS timeouts when trying to save large files.
+- Set artifact working directory to be in the destination store to prevent unnecessary I/O.
+- Strip trailing whitespaces in submodule URLs.
+- Make sure reCAPTCHA configuration is loaded when spam checks are initiated.
+- Fix up arrow not editing last discussion comment.
+- Added application readiness endpoints to the monitoring health check admin view.
+- Use wait_for_requests for both ajax and Vue requests.
+- Cleanup ci_variables schema and table.
+- Remove foreigh key on ci_trigger_schedules only if it exists.
+- Allow translation of Pipeline Schedules.
+
## 9.2.7 (2017-06-21)
- Reinstate is_admin flag in users api when authenticated user is an admin. !12211 (rickettm)
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 8b6c87ae518..89e505709a3 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -49,6 +49,8 @@ _This notice should stay as the first item in the CONTRIBUTING.MD file._
Thank you for your interest in contributing to GitLab. This guide details how
to contribute to GitLab in a way that is efficient for everyone.
+Looking for something to work on? Look for the label [Accepting Merge Requests](#i-want-to-contribute).
+
GitLab comes into two flavors, GitLab Community Edition (CE) our free and open
source edition, and GitLab Enterprise Edition (EE) which is our commercial
edition. Throughout this guide you will see references to CE and EE for
diff --git a/GITLAB_SHELL_VERSION b/GITLAB_SHELL_VERSION
index ab0fa336dd0..c20c645d7e4 100644
--- a/GITLAB_SHELL_VERSION
+++ b/GITLAB_SHELL_VERSION
@@ -1 +1 @@
-5.0.5
+5.0.6
diff --git a/Gemfile b/Gemfile
index 6c53bfe6efe..71d2eb1557c 100644
--- a/Gemfile
+++ b/Gemfile
@@ -2,6 +2,7 @@ source 'https://rubygems.org'
gem 'rails', '4.2.8'
gem 'rails-deprecated_sanitizer', '~> 1.0.3'
+gem 'bootsnap', '~> 1.1'
# Responders respond_to and respond_with
gem 'responders', '~> 2.0'
@@ -256,7 +257,7 @@ gem 'base32', '~> 0.3.0'
# Sentry integration
gem 'sentry-raven', '~> 2.4.0'
-gem 'premailer-rails', '~> 1.9.0'
+gem 'premailer-rails', '~> 1.9.7'
# I18n
gem 'ruby_parser', '~> 3.8', require: false
@@ -354,7 +355,7 @@ group :test do
gem 'shoulda-matchers', '~> 2.8.0', require: false
gem 'email_spec', '~> 1.6.0'
gem 'json-schema', '~> 2.6.2'
- gem 'webmock', '~> 1.24.0'
+ gem 'webmock', '~> 2.3.2'
gem 'test_after_commit', '~> 1.1'
gem 'sham_rack', '~> 1.3.6'
gem 'timecop', '~> 0.8.0'
diff --git a/Gemfile.lock b/Gemfile.lock
index 4715363c5b8..f4ddd30da1b 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -83,6 +83,8 @@ GEM
bindata (2.3.5)
binding_of_caller (0.7.2)
debug_inspector (>= 0.0.1)
+ bootsnap (1.1.1)
+ msgpack (~> 1.0)
bootstrap-sass (3.3.6)
autoprefixer-rails (>= 5.2.1)
sass (>= 3.3.4)
@@ -137,7 +139,7 @@ GEM
crack (0.4.3)
safe_yaml (~> 1.0.0)
creole (0.5.0)
- css_parser (1.4.1)
+ css_parser (1.5.0)
addressable
d3_rails (3.5.11)
railties (>= 3.1.0)
@@ -352,7 +354,7 @@ GEM
grape-entity (0.6.0)
activesupport
multi_json (>= 1.3.2)
- grpc (1.2.5)
+ grpc (1.4.0)
google-protobuf (~> 3.1)
googleauth (~> 0.5.1)
haml (4.0.7)
@@ -366,7 +368,7 @@ GEM
temple (~> 0.7.6)
thor
tilt
- hashdiff (0.3.2)
+ hashdiff (0.3.4)
hashie (3.5.5)
hashie-forbidden_attributes (0.1.1)
hashie (>= 3.0)
@@ -461,8 +463,9 @@ GEM
mimemagic (0.3.0)
mini_portile2 (2.1.0)
minitest (5.7.0)
- mmap2 (2.2.6)
+ mmap2 (2.2.7)
mousetrap-rails (1.4.6)
+ msgpack (1.1.0)
multi_json (1.12.1)
multi_xml (0.6.0)
multipart-post (2.0.0)
@@ -589,10 +592,11 @@ GEM
websocket-driver (>= 0.2.0)
posix-spawn (0.3.11)
powerpack (0.1.1)
- premailer (1.8.6)
- css_parser (>= 1.3.6)
+ premailer (1.10.4)
+ addressable
+ css_parser (>= 1.4.10)
htmlentities (>= 4.0.0)
- premailer-rails (1.9.2)
+ premailer-rails (1.9.7)
actionmailer (>= 3, < 6)
premailer (~> 1.7, >= 1.7.9)
prometheus-client-mmap (0.7.0.beta5)
@@ -887,7 +891,7 @@ GEM
vmstat (2.3.0)
warden (1.2.6)
rack (>= 1.0)
- webmock (1.24.6)
+ webmock (2.3.2)
addressable (>= 2.3.6)
crack (>= 0.3.2)
hashdiff
@@ -926,6 +930,7 @@ DEPENDENCIES
benchmark-ips (~> 2.3.0)
better_errors (~> 2.1.0)
binding_of_caller (~> 0.7.2)
+ bootsnap (~> 1.1)
bootstrap-sass (~> 3.3.0)
bootstrap_form (~> 2.7.0)
brakeman (~> 3.6.0)
@@ -1045,7 +1050,7 @@ DEPENDENCIES
peek-sidekiq (~> 1.0.3)
pg (~> 0.18.2)
poltergeist (~> 1.9.0)
- premailer-rails (~> 1.9.0)
+ premailer-rails (~> 1.9.7)
prometheus-client-mmap (~> 0.7.0.beta5)
pry-byebug (~> 3.4.1)
pry-rails (~> 0.3.4)
@@ -1117,7 +1122,7 @@ DEPENDENCIES
version_sorter (~> 2.1.0)
virtus (~> 1.0.1)
vmstat (~> 2.3.0)
- webmock (~> 1.24.0)
+ webmock (~> 2.3.2)
webpack-rails (~> 0.9.10)
wikicloth (= 0.8.1)
diff --git a/app/assets/images/new_nav.png b/app/assets/images/new_nav.png
new file mode 100644
index 00000000000..8879d26d341
--- /dev/null
+++ b/app/assets/images/new_nav.png
Binary files differ
diff --git a/app/assets/images/old_nav.png b/app/assets/images/old_nav.png
new file mode 100644
index 00000000000..23fae7aa19e
--- /dev/null
+++ b/app/assets/images/old_nav.png
Binary files differ
diff --git a/app/assets/javascripts/behaviors/quick_submit.js b/app/assets/javascripts/behaviors/quick_submit.js
index 1f9e0448084..bc693616460 100644
--- a/app/assets/javascripts/behaviors/quick_submit.js
+++ b/app/assets/javascripts/behaviors/quick_submit.js
@@ -40,7 +40,7 @@ $(document).on('keydown.quick_submit', '.js-quick-submit', (e) => {
e.preventDefault();
const $form = $(e.target).closest('form');
- const $submitButton = $form.find('input[type=submit], button[type=submit]');
+ const $submitButton = $form.find('input[type=submit], button[type=submit]').first();
if (!$submitButton.attr('disabled')) {
$submitButton.trigger('click', [e]);
diff --git a/app/assets/javascripts/dispatcher.js b/app/assets/javascripts/dispatcher.js
index 88b4b567fa9..31a86090242 100644
--- a/app/assets/javascripts/dispatcher.js
+++ b/app/assets/javascripts/dispatcher.js
@@ -55,6 +55,7 @@ import RefSelectDropdown from './ref_select_dropdown';
import GfmAutoComplete from './gfm_auto_complete';
import ShortcutsBlob from './shortcuts_blob';
import initSettingsPanels from './settings_panels';
+import initExperimentalFlags from './experimental_flags';
(function() {
var Dispatcher;
@@ -120,6 +121,9 @@ import initSettingsPanels from './settings_panels';
}
switch (page) {
+ case 'profiles:preferences:show':
+ initExperimentalFlags();
+ break;
case 'sessions:new':
new UsernameValidator();
new ActiveTabMemoizer();
diff --git a/app/assets/javascripts/environments/components/environment_actions.vue b/app/assets/javascripts/environments/components/environment_actions.vue
index a2448520a5f..e7495677e7c 100644
--- a/app/assets/javascripts/environments/components/environment_actions.vue
+++ b/app/assets/javascripts/environments/components/environment_actions.vue
@@ -2,6 +2,7 @@
import playIconSvg from 'icons/_icon_play.svg';
import eventHub from '../event_hub';
import loadingIcon from '../../vue_shared/components/loading_icon.vue';
+import tooltip from '../../vue_shared/directives/tooltip';
export default {
props: {
@@ -12,6 +13,10 @@ export default {
},
},
+ directives: {
+ tooltip,
+ },
+
components: {
loadingIcon,
},
@@ -33,8 +38,6 @@ export default {
onClickAction(endpoint) {
this.isLoading = true;
- $(this.$refs.tooltip).tooltip('destroy');
-
eventHub.$emit('postAction', endpoint);
},
@@ -53,11 +56,11 @@ export default {
class="btn-group"
role="group">
<button
+ v-tooltip
type="button"
- class="dropdown btn btn-default dropdown-new js-dropdown-play-icon-container has-tooltip"
+ class="dropdown btn btn-default dropdown-new js-dropdown-play-icon-container"
data-container="body"
data-toggle="dropdown"
- ref="tooltip"
:title="title"
:aria-label="title"
:disabled="isLoading">
diff --git a/app/assets/javascripts/environments/components/environment_external_url.vue b/app/assets/javascripts/environments/components/environment_external_url.vue
index eaeec2bc53c..6b749814ea4 100644
--- a/app/assets/javascripts/environments/components/environment_external_url.vue
+++ b/app/assets/javascripts/environments/components/environment_external_url.vue
@@ -1,4 +1,6 @@
<script>
+import tooltip from '../../vue_shared/directives/tooltip';
+
/**
* Renders the external url link in environments table.
*/
@@ -10,6 +12,10 @@ export default {
},
},
+ directives: {
+ tooltip,
+ },
+
computed: {
title() {
return 'Open';
@@ -19,7 +25,8 @@ export default {
</script>
<template>
<a
- class="btn external-url has-tooltip"
+ v-tooltip
+ class="btn external-url"
data-container="body"
target="_blank"
rel="noopener noreferrer nofollow"
diff --git a/app/assets/javascripts/environments/components/environment_monitoring.vue b/app/assets/javascripts/environments/components/environment_monitoring.vue
index 07cf92281a0..1655561cdd3 100644
--- a/app/assets/javascripts/environments/components/environment_monitoring.vue
+++ b/app/assets/javascripts/environments/components/environment_monitoring.vue
@@ -2,6 +2,8 @@
/**
* Renders the Monitoring (Metrics) link in environments table.
*/
+import tooltip from '../../vue_shared/directives/tooltip';
+
export default {
props: {
monitoringUrl: {
@@ -10,6 +12,10 @@ export default {
},
},
+ directives: {
+ tooltip,
+ },
+
computed: {
title() {
return 'Monitoring';
@@ -19,7 +25,8 @@ export default {
</script>
<template>
<a
- class="btn monitoring-url has-tooltip hidden-xs hidden-sm"
+ v-tooltip
+ class="btn monitoring-url hidden-xs hidden-sm"
data-container="body"
rel="noopener noreferrer nofollow"
:href="monitoringUrl"
diff --git a/app/assets/javascripts/environments/components/environment_stop.vue b/app/assets/javascripts/environments/components/environment_stop.vue
index 091c543860b..85f11d2071b 100644
--- a/app/assets/javascripts/environments/components/environment_stop.vue
+++ b/app/assets/javascripts/environments/components/environment_stop.vue
@@ -5,6 +5,7 @@
*/
import eventHub from '../event_hub';
import loadingIcon from '../../vue_shared/components/loading_icon.vue';
+import tooltip from '../../vue_shared/directives/tooltip';
export default {
props: {
@@ -14,6 +15,10 @@ export default {
},
},
+ directives: {
+ tooltip,
+ },
+
data() {
return {
isLoading: false,
@@ -46,8 +51,9 @@ export default {
</script>
<template>
<button
+ v-tooltip
type="button"
- class="btn stop-env-link has-tooltip hidden-xs hidden-sm"
+ class="btn stop-env-link hidden-xs hidden-sm"
data-container="body"
@click="onClick"
:disabled="isLoading"
diff --git a/app/assets/javascripts/environments/components/environment_terminal_button.vue b/app/assets/javascripts/environments/components/environment_terminal_button.vue
index 1ca65a79951..2037bf618e3 100644
--- a/app/assets/javascripts/environments/components/environment_terminal_button.vue
+++ b/app/assets/javascripts/environments/components/environment_terminal_button.vue
@@ -4,6 +4,7 @@
* Used in environments table.
*/
import terminalIconSvg from 'icons/_icon_terminal.svg';
+import tooltip from '../../vue_shared/directives/tooltip';
export default {
props: {
@@ -14,6 +15,10 @@ export default {
},
},
+ directives: {
+ tooltip,
+ },
+
data() {
return {
terminalIconSvg,
@@ -29,7 +34,8 @@ export default {
</script>
<template>
<a
- class="btn terminal-button has-tooltip hidden-xs hidden-sm"
+ v-tooltip
+ class="btn terminal-button hidden-xs hidden-sm"
data-container="body"
:title="title"
:aria-label="title"
diff --git a/app/assets/javascripts/experimental_flags.js b/app/assets/javascripts/experimental_flags.js
new file mode 100644
index 00000000000..dbd3843cef7
--- /dev/null
+++ b/app/assets/javascripts/experimental_flags.js
@@ -0,0 +1,11 @@
+import Cookies from 'js-cookie';
+
+export default () => {
+ $('.js-experiment-feature-toggle').on('change', (e) => {
+ const el = e.target;
+
+ Cookies.set(el.name, el.value, {
+ expires: 365 * 10,
+ });
+ });
+};
diff --git a/app/assets/javascripts/issue_show/components/fields/description.vue b/app/assets/javascripts/issue_show/components/fields/description.vue
index 54650d2f184..27b1b814f9a 100644
--- a/app/assets/javascripts/issue_show/components/fields/description.vue
+++ b/app/assets/javascripts/issue_show/components/fields/description.vue
@@ -47,7 +47,8 @@
ref="textarea"
slot="textarea"
placeholder="Write a comment or drag your files here..."
- @keydown.meta.enter="updateIssuable">
+ @keydown.meta.enter="updateIssuable"
+ @keydown.ctrl.enter="updateIssuable">
</textarea>
</markdown-field>
</div>
diff --git a/app/assets/javascripts/issue_show/components/fields/project_move.vue b/app/assets/javascripts/issue_show/components/fields/project_move.vue
index f811fb0de24..7bf2be8b28a 100644
--- a/app/assets/javascripts/issue_show/components/fields/project_move.vue
+++ b/app/assets/javascripts/issue_show/components/fields/project_move.vue
@@ -1,10 +1,10 @@
<script>
- import tooltipMixin from '../../../vue_shared/mixins/tooltip';
+ import tooltip from '../../../vue_shared/directives/tooltip';
export default {
- mixins: [
- tooltipMixin,
- ],
+ directives: {
+ tooltip,
+ },
props: {
formState: {
type: Object,
@@ -71,9 +71,9 @@
data-placeholder="Move to a different project" />
</div>
<span
+ v-tooltip
data-placement="auto top"
- title="Moving an issue will copy the discussion to a different project and close it here. All participants will be notified of the new location."
- ref="tooltip">
+ title="Moving an issue will copy the discussion to a different project and close it here. All participants will be notified of the new location.">
<i
class="fa fa-question-circle"
aria-hidden="true">
diff --git a/app/assets/javascripts/issue_show/components/fields/title.vue b/app/assets/javascripts/issue_show/components/fields/title.vue
index 6556bf117e2..83af8e1e245 100644
--- a/app/assets/javascripts/issue_show/components/fields/title.vue
+++ b/app/assets/javascripts/issue_show/components/fields/title.vue
@@ -26,6 +26,7 @@
placeholder="Issue title"
aria-label="Issue title"
v-model="formState.title"
- @keydown.meta.enter="updateIssuable" />
+ @keydown.meta.enter="updateIssuable"
+ @keydown.ctrl.enter="updateIssuable" />
</fieldset>
</template>
diff --git a/app/assets/javascripts/label_manager.js b/app/assets/javascripts/label_manager.js
index 38b2eb9ff14..d8814802d9e 100644
--- a/app/assets/javascripts/label_manager.js
+++ b/app/assets/javascripts/label_manager.js
@@ -21,6 +21,7 @@
}
bindEvents() {
+ this.prioritizedLabels.find('.btn-action').on('mousedown', this, this.onButtonActionClick);
return this.togglePriorityButton.on('click', this, this.onTogglePriorityClick);
}
@@ -36,6 +37,11 @@
_this.toggleEmptyState($label, $btn, action);
}
+ onButtonActionClick(e) {
+ e.stopPropagation();
+ $(e.currentTarget).tooltip('hide');
+ }
+
toggleEmptyState($label, $btn, action) {
this.emptyState.classList.toggle('hidden', !!this.prioritizedLabels[0].querySelector(':scope > li'));
}
diff --git a/app/assets/javascripts/lib/utils/text_utility.js b/app/assets/javascripts/lib/utils/text_utility.js
index 601d01e1be1..021f936a4fa 100644
--- a/app/assets/javascripts/lib/utils/text_utility.js
+++ b/app/assets/javascripts/lib/utils/text_utility.js
@@ -94,8 +94,8 @@ gl.text.insertText = function(textArea, text, tag, blockTag, selected, wrap) {
startChar = !wrap && !currentLineEmpty && textArea.selectionStart > 0 ? '\n' : '';
- if (selectedSplit.length > 1 && (!wrap || (blockTag != null))) {
- if (blockTag != null) {
+ if (selectedSplit.length > 1 && (!wrap || (blockTag != null && blockTag !== ''))) {
+ if (blockTag != null && blockTag !== '') {
insertText = this.blockTagText(text, textArea, blockTag, selected);
} else {
insertText = selectedSplit.map(function(val) {
diff --git a/app/assets/javascripts/locale/bg/app.js b/app/assets/javascripts/locale/bg/app.js
deleted file mode 100644
index ba56c0bea25..00000000000
--- a/app/assets/javascripts/locale/bg/app.js
+++ /dev/null
@@ -1 +0,0 @@
-var locales = locales || {}; locales['bg'] = {"domain":"app","locale_data":{"app":{"":{"Project-Id-Version":"gitlab 1.0.0","Report-Msgid-Bugs-To":"","POT-Creation-Date":"2017-05-04 19:24-0500","MIME-Version":"1.0","Content-Type":"text/plain; charset=UTF-8","Content-Transfer-Encoding":"8bit","PO-Revision-Date":"2017-06-05 09:40-0400","Last-Translator":"Lyubomir Vasilev <lyubomirv@abv.bg>","Language-Team":"Bulgarian","Language":"bg","X-Generator":"Zanata 3.9.6","Plural-Forms":"nplurals=2; plural=(n != 1)","lang":"bg","domain":"app","plural_forms":"nplurals=2; plural=(n != 1)"},"ByAuthor|by":["от"],"Commit":["Подаване","Подавания"],"Cycle Analytics gives an overview of how much time it takes to go from idea to production in your project.":["Анализът на циклите дава общ поглед върху това колко време е нужно на една идея да се превърне в завършена функционалност в проекта."],"CycleAnalyticsStage|Code":["Програмиране"],"CycleAnalyticsStage|Issue":["Проблем"],"CycleAnalyticsStage|Plan":["Планиране"],"CycleAnalyticsStage|Production":["Издаване"],"CycleAnalyticsStage|Review":["Преглед и одобрение"],"CycleAnalyticsStage|Staging":["Подготовка за издаване"],"CycleAnalyticsStage|Test":["Тестване"],"Deploy":["Внедряване","Внедрявания"],"FirstPushedBy|First":["Първо"],"FirstPushedBy|pushed by":["изпращане на промени от"],"From issue creation until deploy to production":["От създаването на проблема до внедряването в крайната версия"],"From merge request merge until deploy to production":["От прилагането на заявката за сливане до внедряването в крайната версия"],"Introducing Cycle Analytics":["Представяме Ви анализът на циклите"],"Last %d day":["Последния %d ден","Последните %d дни"],"Limited to showing %d event at most":["Ограничено до показване на последното %d събитие","Ограничено до показване на последните %d събития"],"Median":["Медиана"],"New Issue":["Нов проблем","Нови проблема"],"Not available":["Не е налично"],"Not enough data":["Няма достатъчно данни"],"OpenedNDaysAgo|Opened":["Отворен"],"Pipeline Health":["Състояние"],"ProjectLifecycle|Stage":["Етап"],"Read more":["Прочетете повече"],"Related Commits":["Свързани подавания"],"Related Deployed Jobs":["Свързани задачи за внедряване"],"Related Issues":["Свързани проблеми"],"Related Jobs":["Свързани задачи"],"Related Merge Requests":["Свързани заявки за сливане"],"Related Merged Requests":["Свързани приложени заявки за сливане"],"Showing %d event":["Показване на %d събитие","Показване на %d събития"],"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.":["Етапът на програмиране показва времето от първото подаване до създаването на заявката за сливане. Данните ще бъдат добавени тук автоматично след като бъде създадена първата заявка за сливане."],"The collection of events added to the data gathered for that stage.":["Съвкупността от събития добавени към данните събрани за този етап."],"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.":["Етапът на проблемите показва колко е времето от създаването на проблем до определянето на целеви етап на проекта за него, или до добавянето му в списък на дъската за проблеми. Започнете да добавяте проблеми, за да видите данните за този етап."],"The phase of the development lifecycle.":["Етапът от цикъла на разработка"],"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.":["Етапът на планиране показва колко е времето от преходната стъпка до изпращането на първото подаване. Това време ще бъде добавено автоматично след като изпратите първото си подаване."],"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.":["Етапът на издаване показва общото време, което е нужно от създаването на проблем до внедряването на кода в крайната версия."],"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.":["Етапът на преглед и одобрение показва времето от създаването на заявката за сливане до прилагането ѝ. Данните ще бъдат добавени автоматично след като приложите първата си заявка за сливане."],"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.":["Етапът на подготовка за издаване показва времето между прилагането на заявката за сливане и внедряването на кода в средата на работещата крайна версия. Данните ще бъдат добавени автоматично след като направите първото си внедряване в крайната версия."],"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.":["Етапът на тестване показва времето, което е нужно на „Gitlab CI“ да изпълни всички задачи за свързаната заявка за сливане. Данните ще бъдат добавени автоматично след като приключи изпълнените на първата Ви такава задача."],"The time taken by each data entry gathered by that stage.":["Времето, което отнема всеки запис от данни за съответния етап."],"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.":["Стойността, която се намира в средата на последователността от наблюдавани данни. Например: медианата на 3, 5 и 9 е 5, а медианата на 3, 5, 7 и 8 е (5+7)/2 = 6."],"Time before an issue gets scheduled":["Време преди един проблем да бъде планиран за работа"],"Time before an issue starts implementation":["Време преди работата по проблем да започне"],"Time between merge request creation and merge/close":["Време между създаване на заявка за сливане и прилагането/отхвърлянето ѝ"],"Time until first merge request":["Време преди първата заявка за сливане"],"Time|hr":["час","часа"],"Time|min":["мин","мин"],"Time|s":["сек"],"Total Time":["Общо време"],"Total test time for all commits/merges":["Общо време за тестване на всички подавания/сливания"],"Want to see the data? Please ask an administrator for access.":["Искате ли да видите данните? Помолете администратор за достъп."],"We don't have enough data to show this stage.":["Няма достатъчно данни за този етап."],"You need permission.":["Нуждаете се от разрешение."],"day":["ден","дни"]}}}; \ No newline at end of file
diff --git a/app/assets/javascripts/locale/de/app.js b/app/assets/javascripts/locale/de/app.js
deleted file mode 100644
index e7d2b174405..00000000000
--- a/app/assets/javascripts/locale/de/app.js
+++ /dev/null
@@ -1 +0,0 @@
-var locales = locales || {}; locales['de'] = {"domain":"app","locale_data":{"app":{"":{"Project-Id-Version":"gitlab 1.0.0","Report-Msgid-Bugs-To":"","PO-Revision-Date":"2017-05-09 13:44+0200","Language-Team":"German","Language":"de","MIME-Version":"1.0","Content-Type":"text/plain; charset=UTF-8","Content-Transfer-Encoding":"8bit","Plural-Forms":"nplurals=2; plural=n != 1;","Last-Translator":"","X-Generator":"Poedit 2.0.1","lang":"de","domain":"app","plural_forms":"nplurals=2; plural=n != 1;"},"Are you sure you want to delete this pipeline schedule?":[""],"ByAuthor|by":["Von"],"Cancel":[""],"Commit":["Commit","Commits"],"Cron Timezone":[""],"Cycle Analytics gives an overview of how much time it takes to go from idea to production in your project.":["Cycle Analytics liefern einen Überblick darüber, wie viel Zeit in Ihrem Projekt von einer Idee bis zum Produktivdeployment vergeht."],"CycleAnalyticsStage|Code":["Code"],"CycleAnalyticsStage|Issue":["Issue"],"CycleAnalyticsStage|Plan":["Planung"],"CycleAnalyticsStage|Production":["Produktiv"],"CycleAnalyticsStage|Review":["Review"],"CycleAnalyticsStage|Staging":["Staging"],"CycleAnalyticsStage|Test":["Test"],"Delete":[""],"Deploy":["Deployment","Deployments"],"Description":[""],"Edit":[""],"Edit Pipeline Schedule %{id}":[""],"Failed to change the owner":[""],"Failed to remove the pipeline schedule":[""],"Filter":[""],"FirstPushedBy|First":["Erster"],"FirstPushedBy|pushed by":["gepusht von"],"From issue creation until deploy to production":["Vom Anlegen des Issues bis zum Produktivdeployment"],"From merge request merge until deploy to production":["Vom Merge Request bis zum Produktivdeployment"],"Interval Pattern":[""],"Introducing Cycle Analytics":["Was sind Cycle Analytics?"],"Last %d day":["Letzter %d Tag","Letzten %d Tage"],"Last Pipeline":[""],"Limited to showing %d event at most":["Eingeschränkt auf maximal %d Ereignis","Eingeschränkt auf maximal %d Ereignisse"],"Median":["Median"],"New Issue":["Neues Issue","Neue Issues"],"New Pipeline Schedule":[""],"No schedules":[""],"Not available":["Nicht verfügbar"],"Not enough data":["Nicht genügend Daten"],"OpenedNDaysAgo|Opened":["Erstellt"],"Owner":[""],"Pipeline Health":["Pipeline Kennzahlen"],"Pipeline Schedule":[""],"Pipeline Schedules":[""],"PipelineSchedules|Activated":[""],"PipelineSchedules|Active":[""],"PipelineSchedules|All":[""],"PipelineSchedules|Inactive":[""],"PipelineSchedules|Next Run":[""],"PipelineSchedules|None":[""],"PipelineSchedules|Provide a short description for this pipeline":[""],"PipelineSchedules|Take ownership":[""],"PipelineSchedules|Target":[""],"ProjectLifecycle|Stage":["Phase"],"Read more":["Mehr"],"Related Commits":["Zugehörige Commits"],"Related Deployed Jobs":["Zugehörige Deploymentjobs"],"Related Issues":["Zugehörige Issues"],"Related Jobs":["Zugehörige Jobs"],"Related Merge Requests":["Zugehörige Merge Requests"],"Related Merged Requests":["Zugehörige abgeschlossene Merge Requests"],"Save pipeline schedule":[""],"Schedule a new pipeline":[""],"Select a timezone":[""],"Select target branch":[""],"Showing %d event":["Zeige %d Ereignis","Zeige %d Ereignisse"],"Target Branch":[""],"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.":["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."],"The collection of events added to the data gathered for that stage.":["Ereignisse, die für diese Phase ausgewertet wurden."],"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.":["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."],"The phase of the development lifecycle.":["Die Phase im Entwicklungsprozess."],"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.":["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."],"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.":["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."],"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.":["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."],"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.":["Die Staging-Phase stellt die Zeit zwischen Mergen eines Merge Requests und dem Produktivdeployment dar. Sobald Sie das erste Produktivdeployment durchgeführt haben, werden dessen Daten hier automatisch angezeigt."],"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.":["Die Test-Phase stellt die Zeit dar, die GitLab CI benötigt um die Pipelines von Merge Requests abzuarbeiten. Sobald die erste Pipeline abgeschlossen ist, werden deren Daten hier automatisch angezeigt."],"The time taken by each data entry gathered by that stage.":["Zeit die für das jeweilige Ereignis in der Phase ermittelt wurde."],"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.":["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."],"Time before an issue gets scheduled":["Zeit bis ein Issue geplant wird"],"Time before an issue starts implementation":["Zeit bis die Implementierung für ein Issue beginnt"],"Time between merge request creation and merge/close":["Zeit zwischen Anlegen und Mergen/Schließen eines Merge Requests"],"Time until first merge request":["Zeit bis zum ersten Merge Request"],"Time|hr":["h","h"],"Time|min":["min","min"],"Time|s":["s"],"Total Time":["Gesamtzeit"],"Total test time for all commits/merges":["Gesamte Testlaufzeit für alle Commits/Merges"],"Want to see the data? Please ask an administrator for access.":["Um diese Daten einsehen zu können, wenden Sie sich bitte an Ihren Administrator."],"We don't have enough data to show this stage.":["Es liegen nicht genügend Daten vor, um diese Phase anzuzeigen."],"You need permission.":["Sie benötigen Zugriffsrechte."],"day":["Tag","Tage"]}}}; \ No newline at end of file
diff --git a/app/assets/javascripts/locale/en/app.js b/app/assets/javascripts/locale/en/app.js
deleted file mode 100644
index d634af959e5..00000000000
--- a/app/assets/javascripts/locale/en/app.js
+++ /dev/null
@@ -1 +0,0 @@
-var locales = locales || {}; locales['en'] = {"domain":"app","locale_data":{"app":{"":{"Project-Id-Version":"gitlab 1.0.0","Report-Msgid-Bugs-To":"","PO-Revision-Date":"2017-04-12 22:36-0500","Last-Translator":"FULL NAME <EMAIL@ADDRESS>","Language-Team":"English","Language":"en","MIME-Version":"1.0","Content-Type":"text/plain; charset=UTF-8","Content-Transfer-Encoding":"8bit","Plural-Forms":"nplurals=2; plural=n != 1;","lang":"en","domain":"app","plural_forms":"nplurals=2; plural=n != 1;"},"%{commit_author_link} committed %{commit_timeago}":[""],"About auto deploy":[""],"Active":[""],"Activity":[""],"Add Changelog":[""],"Add Contribution guide":[""],"Add License":[""],"Add an SSH key to your profile to pull or push via SSH.":[""],"Add new directory":[""],"Archived project! Repository is read-only":[""],"Are you sure you want to delete this pipeline schedule?":[""],"Attach a file by drag &amp; drop or %{upload_link}":[""],"Branch":["",""],"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}":[""],"Branches":[""],"Browse files":[""],"ByAuthor|by":[""],"CI configuration":[""],"Cancel":[""],"ChangeTypeActionLabel|Pick into branch":[""],"ChangeTypeActionLabel|Revert in branch":[""],"ChangeTypeAction|Cherry-pick":[""],"Changelog":[""],"Charts":[""],"Cherry-pick this commit":[""],"Cherry-pick this merge request":[""],"CiStatusLabel|canceled":[""],"CiStatusLabel|created":[""],"CiStatusLabel|failed":[""],"CiStatusLabel|manual action":[""],"CiStatusLabel|passed":[""],"CiStatusLabel|passed with warnings":[""],"CiStatusLabel|pending":[""],"CiStatusLabel|skipped":[""],"CiStatusLabel|waiting for manual action":[""],"CiStatusText|blocked":[""],"CiStatusText|canceled":[""],"CiStatusText|created":[""],"CiStatusText|failed":[""],"CiStatusText|manual":[""],"CiStatusText|passed":[""],"CiStatusText|pending":[""],"CiStatusText|skipped":[""],"CiStatus|running":[""],"Commit":["",""],"Commit message":[""],"CommitBoxTitle|Commit":[""],"CommitMessage|Add %{file_name}":[""],"Commits":[""],"Commits|History":[""],"Committed by":[""],"Compare":[""],"Contribution guide":[""],"Contributors":[""],"Copy URL to clipboard":[""],"Copy commit SHA to clipboard":[""],"Create New Directory":[""],"Create directory":[""],"Create empty bare repository":[""],"Create merge request":[""],"Create new...":[""],"CreateNewFork|Fork":[""],"CreateTag|Tag":[""],"Cron Timezone":[""],"Cron syntax":[""],"Custom notification events":[""],"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}.":[""],"Cycle Analytics":[""],"Cycle Analytics gives an overview of how much time it takes to go from idea to production in your project.":[""],"CycleAnalyticsStage|Code":[""],"CycleAnalyticsStage|Issue":[""],"CycleAnalyticsStage|Plan":[""],"CycleAnalyticsStage|Production":[""],"CycleAnalyticsStage|Review":[""],"CycleAnalyticsStage|Staging":[""],"CycleAnalyticsStage|Test":[""],"Define a custom pattern with cron syntax":[""],"Delete":[""],"Deploy":["",""],"Description":[""],"Directory name":[""],"Don't show again":[""],"Download":[""],"Download tar":[""],"Download tar.bz2":[""],"Download tar.gz":[""],"Download zip":[""],"DownloadArtifacts|Download":[""],"DownloadCommit|Email Patches":[""],"DownloadCommit|Plain Diff":[""],"DownloadSource|Download":[""],"Edit":[""],"Edit Pipeline Schedule %{id}":[""],"Every day (at 4:00am)":[""],"Every month (on the 1st at 4:00am)":[""],"Every week (Sundays at 4:00am)":[""],"Failed to change the owner":[""],"Failed to remove the pipeline schedule":[""],"Files":[""],"Find by path":[""],"Find file":[""],"FirstPushedBy|First":[""],"FirstPushedBy|pushed by":[""],"Fork":["",""],"ForkedFromProjectPath|Forked from":[""],"From issue creation until deploy to production":[""],"From merge request merge until deploy to production":[""],"Go to your fork":[""],"GoToYourFork|Fork":[""],"Home":[""],"Housekeeping successfully started":[""],"Import repository":[""],"Interval Pattern":[""],"Introducing Cycle Analytics":[""],"LFSStatus|Disabled":[""],"LFSStatus|Enabled":[""],"Last %d day":["",""],"Last Pipeline":[""],"Last Update":[""],"Last commit":[""],"Learn more in the":[""],"Learn more in the|pipeline schedules documentation":[""],"Leave group":[""],"Leave project":[""],"Limited to showing %d event at most":["",""],"Median":[""],"MissingSSHKeyWarningLink|add an SSH key":[""],"New Issue":["",""],"New Pipeline Schedule":[""],"New branch":[""],"New directory":[""],"New file":[""],"New issue":[""],"New merge request":[""],"New schedule":[""],"New snippet":[""],"New tag":[""],"No repository":[""],"No schedules":[""],"Not available":[""],"Not enough data":[""],"Notification events":[""],"NotificationEvent|Close issue":[""],"NotificationEvent|Close merge request":[""],"NotificationEvent|Failed pipeline":[""],"NotificationEvent|Merge merge request":[""],"NotificationEvent|New issue":[""],"NotificationEvent|New merge request":[""],"NotificationEvent|New note":[""],"NotificationEvent|Reassign issue":[""],"NotificationEvent|Reassign merge request":[""],"NotificationEvent|Reopen issue":[""],"NotificationEvent|Successful pipeline":[""],"NotificationLevel|Custom":[""],"NotificationLevel|Disabled":[""],"NotificationLevel|Global":[""],"NotificationLevel|On mention":[""],"NotificationLevel|Participate":[""],"NotificationLevel|Watch":[""],"OfSearchInADropdown|Filter":[""],"OpenedNDaysAgo|Opened":[""],"Options":[""],"Owner":[""],"Pipeline":[""],"Pipeline Health":[""],"Pipeline Schedule":[""],"Pipeline Schedules":[""],"PipelineSchedules|Activated":[""],"PipelineSchedules|Active":[""],"PipelineSchedules|All":[""],"PipelineSchedules|Inactive":[""],"PipelineSchedules|Next Run":[""],"PipelineSchedules|None":[""],"PipelineSchedules|Provide a short description for this pipeline":[""],"PipelineSchedules|Take ownership":[""],"PipelineSchedules|Target":[""],"PipelineSheduleIntervalPattern|Custom":[""],"Pipeline|with stage":[""],"Pipeline|with stages":[""],"Project '%{project_name}' queued for deletion.":[""],"Project '%{project_name}' was successfully created.":[""],"Project '%{project_name}' was successfully updated.":[""],"Project '%{project_name}' will be deleted.":[""],"Project access must be granted explicitly to each user.":[""],"Project export could not be deleted.":[""],"Project export has been deleted.":[""],"Project export link has expired. Please generate a new export from your project settings.":[""],"Project export started. A download link will be sent by email.":[""],"Project home":[""],"ProjectFeature|Disabled":[""],"ProjectFeature|Everyone with access":[""],"ProjectFeature|Only team members":[""],"ProjectFileTree|Name":[""],"ProjectLastActivity|Never":[""],"ProjectLifecycle|Stage":[""],"ProjectNetworkGraph|Graph":[""],"Read more":[""],"Readme":[""],"RefSwitcher|Branches":[""],"RefSwitcher|Tags":[""],"Related Commits":[""],"Related Deployed Jobs":[""],"Related Issues":[""],"Related Jobs":[""],"Related Merge Requests":[""],"Related Merged Requests":[""],"Remind later":[""],"Remove project":[""],"Request Access":[""],"Revert this commit":[""],"Revert this merge request":[""],"Save pipeline schedule":[""],"Schedule a new pipeline":[""],"Scheduling Pipelines":[""],"Search branches and tags":[""],"Select Archive Format":[""],"Select a timezone":[""],"Select target branch":[""],"Set a password on your account to pull or push via %{protocol}":[""],"Set up CI":[""],"Set up Koding":[""],"Set up auto deploy":[""],"SetPasswordToCloneLink|set a password":[""],"Showing %d event":["",""],"Source code":[""],"StarProject|Star":[""],"Start a %{new_merge_request} with these changes":[""],"Start a <strong>new merge request</strong> with these changes":[""],"Switch branch/tag":[""],"Tag":["",""],"Tags":[""],"Target Branch":[""],"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.":[""],"The collection of events added to the data gathered for that stage.":[""],"The fork relationship has been removed.":[""],"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.":[""],"The phase of the development lifecycle.":[""],"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.":[""],"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.":[""],"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.":[""],"The project can be accessed by any logged in user.":[""],"The project can be accessed without any authentication.":[""],"The repository for this project does not exist.":[""],"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.":[""],"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.":[""],"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.":[""],"The time taken by each data entry gathered by that stage.":[""],"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.":[""],"This means you can not push code until you create an empty repository or import existing one.":[""],"Time before an issue gets scheduled":[""],"Time before an issue starts implementation":[""],"Time between merge request creation and merge/close":[""],"Time until first merge request":[""],"Timeago|%s days ago":[""],"Timeago|%s days remaining":[""],"Timeago|%s hours remaining":[""],"Timeago|%s minutes ago":[""],"Timeago|%s minutes remaining":[""],"Timeago|%s months ago":[""],"Timeago|%s months remaining":[""],"Timeago|%s seconds remaining":[""],"Timeago|%s weeks ago":[""],"Timeago|%s weeks remaining":[""],"Timeago|%s years ago":[""],"Timeago|%s years remaining":[""],"Timeago|1 day remaining":[""],"Timeago|1 hour remaining":[""],"Timeago|1 minute remaining":[""],"Timeago|1 month remaining":[""],"Timeago|1 week remaining":[""],"Timeago|1 year remaining":[""],"Timeago|Past due":[""],"Timeago|a day ago":[""],"Timeago|a month ago":[""],"Timeago|a week ago":[""],"Timeago|a while":[""],"Timeago|a year ago":[""],"Timeago|about %s hours ago":[""],"Timeago|about a minute ago":[""],"Timeago|about an hour ago":[""],"Timeago|in %s days":[""],"Timeago|in %s hours":[""],"Timeago|in %s minutes":[""],"Timeago|in %s months":[""],"Timeago|in %s seconds":[""],"Timeago|in %s weeks":[""],"Timeago|in %s years":[""],"Timeago|in 1 day":[""],"Timeago|in 1 hour":[""],"Timeago|in 1 minute":[""],"Timeago|in 1 month":[""],"Timeago|in 1 week":[""],"Timeago|in 1 year":[""],"Timeago|less than a minute ago":[""],"Time|hr":["",""],"Time|min":["",""],"Time|s":[""],"Total Time":[""],"Total test time for all commits/merges":[""],"Unstar":[""],"Upload New File":[""],"Upload file":[""],"Use your global notification setting":[""],"VisibilityLevel|Internal":[""],"VisibilityLevel|Private":[""],"VisibilityLevel|Public":[""],"Want to see the data? Please ask an administrator for access.":[""],"We don't have enough data to show this stage.":[""],"Withdraw Access Request":[""],"You are going to remove %{project_name_with_namespace}.\\nRemoved project CANNOT be restored!\\nAre you ABSOLUTELY sure?":[""],"You are going to remove the fork relationship to source project %{forked_from_project}. Are you ABSOLUTELY sure?":[""],"You are going to transfer %{project_name_with_namespace} to another owner. Are you ABSOLUTELY sure?":[""],"You can only add files when you are on a branch":[""],"You must sign in to star a project":[""],"You need permission.":[""],"You will not get any notifications via email":[""],"You will only receive notifications for the events you choose":[""],"You will only receive notifications for threads you have participated in":[""],"You will receive notifications for any activity":[""],"You will receive notifications only for comments in which you were @mentioned":[""],"You won't be able to pull or push project code via %{protocol} until you %{set_password_link} on your account":[""],"You won't be able to pull or push project code via SSH until you %{add_ssh_key_link} to your profile":[""],"Your name":[""],"day":["",""],"new merge request":[""],"notification emails":[""],"parent":["",""]}}}; \ No newline at end of file
diff --git a/app/assets/javascripts/locale/eo/app.js b/app/assets/javascripts/locale/eo/app.js
new file mode 100644
index 00000000000..55f000e9b88
--- /dev/null
+++ b/app/assets/javascripts/locale/eo/app.js
@@ -0,0 +1 @@
+var locales = locales || {}; locales['eo'] = {"domain":"app","locale_data":{"app":{"":{"Project-Id-Version":"gitlab 1.0.0","Report-Msgid-Bugs-To":"","POT-Creation-Date":"2017-06-15 21:59-0500","MIME-Version":"1.0","Content-Type":"text/plain; charset=UTF-8","Content-Transfer-Encoding":"8bit","PO-Revision-Date":"2017-06-20 06:24-0400","Last-Translator":"Lyubomir Vasilev <lyubomirv@abv.bg>","Language-Team":"Esperanto (https://translate.zanata.org/project/view/GitLab)","Language":"eo","X-Generator":"Zanata 3.9.6","Plural-Forms":"nplurals=2; plural=(n != 1)","lang":"eo","domain":"app","plural_forms":"nplurals=2; plural=(n != 1)"},"%{commit_author_link} committed %{commit_timeago}":["%{commit_author_link} enmetis %{commit_timeago}"],"About auto deploy":["Pri la aŭtomata disponigado"],"Active":["Aktiva"],"Activity":["Aktiveco"],"Add Changelog":["Aldoni liston de ŝanĝoj"],"Add Contribution guide":["Aldoni gvidliniojn por kontribuado"],"Add License":["Aldoni rajtigilon"],"Add an SSH key to your profile to pull or push via SSH.":["Aldonu SSH-ŝlosilon al via profilo por ebligi al vi eltiri kaj alpuŝi per SSH."],"Add new directory":["Aldoni novan dosierujon"],"Archived project! Repository is read-only":["Arkivita projekto! La deponejo permesas nur legadon"],"Are you sure you want to delete this pipeline schedule?":["Ĉu vi certe volas forigi ĉi tiun ĉenstablan planon?"],"Attach a file by drag &amp; drop or %{upload_link}":["Alkroĉu dosieron per ŝovmetado aŭ %{upload_link}"],"Branch":["Branĉo","Branĉoj"],"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}":["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}"],"Branches":["Branĉoj"],"Browse files":["Elekti dosierojn"],"ByAuthor|by":["de"],"CI configuration":["Agordoj de seninterrompa integrado"],"Cancel":["Nuligi"],"ChangeTypeActionLabel|Pick into branch":["Elekti en branĉon"],"ChangeTypeActionLabel|Revert in branch":["Malfari en branĉo"],"ChangeTypeAction|Cherry-pick":["Precize elekti"],"ChangeTypeAction|Revert":["Malfari"],"Changelog":["Listo de ŝanĝoj"],"Charts":["Diagramoj"],"Cherry-pick this commit":["Precize elekti ĉi tiun kunmetadon"],"Cherry-pick this merge request":["Precize elekti ĉi tiun peton pri kunfando"],"CiStatusLabel|canceled":["nuligita"],"CiStatusLabel|created":["kreita"],"CiStatusLabel|failed":["malsukcesa"],"CiStatusLabel|manual action":["mana ago"],"CiStatusLabel|passed":["sukcesa"],"CiStatusLabel|passed with warnings":["sukcesa, kun avertoj"],"CiStatusLabel|pending":["okazonta"],"CiStatusLabel|skipped":["transsaltita"],"CiStatusLabel|waiting for manual action":["atendanta manan agon"],"CiStatusText|blocked":["blokita"],"CiStatusText|canceled":["nuligita"],"CiStatusText|created":["kreita"],"CiStatusText|failed":["malsukcesa"],"CiStatusText|manual":["mana"],"CiStatusText|passed":["sukcesa"],"CiStatusText|pending":["okazonta"],"CiStatusText|skipped":["transsaltita"],"CiStatus|running":["plenumiĝanta"],"Commit":["Enmetado","Enmetadoj"],"Commit message":["Mesaĝo pri la enmetado"],"CommitBoxTitle|Commit":["Enmeti"],"CommitMessage|Add %{file_name}":["Aldoni „%{file_name}“"],"Commits":["Enmetadoj"],"Commits|History":["Historio"],"Committed by":["Enmetita de"],"Compare":["Kompari"],"Contribution guide":["Gvidlinioj por kontribuado"],"Contributors":["Kontribuantoj"],"Copy URL to clipboard":["Kopii la adreson en la kopibufron"],"Copy commit SHA to clipboard":["Kopii la identigilon de la enmetado"],"Create New Directory":["Krei novan dosierujon"],"Create directory":["Krei dosierujon"],"Create empty bare repository":["Krei malplenan deponejon"],"Create merge request":["Krei peton pri kunfando"],"Create new...":["Krei novan…"],"CreateNewFork|Fork":["Disbranĉigi"],"CreateTag|Tag":["Etikedo"],"Cron Timezone":["Horzono por Cron"],"Cron syntax":["La sintakso de Cron"],"Custom notification events":["Propraj sciigaj eventoj"],"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}.":["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}."],"Cycle Analytics":["Cikla analizo"],"Cycle Analytics gives an overview of how much time it takes to go from idea to production in your project.":["La cikla analizo esploras kiom da tempo necesas por disvolvi ideon ĝis ĝi fariĝos realaĵo."],"CycleAnalyticsStage|Code":["Programado"],"CycleAnalyticsStage|Issue":["Problemo"],"CycleAnalyticsStage|Plan":["Plano"],"CycleAnalyticsStage|Production":["Eldonado"],"CycleAnalyticsStage|Review":["Kontrolo"],"CycleAnalyticsStage|Staging":["Preparo por eldono"],"CycleAnalyticsStage|Test":["Testado"],"Define a custom pattern with cron syntax":["Difini propran ŝablonon, uzante la sintakson de Cron"],"Delete":["Forigi"],"Deploy":["Disponigado","Disponigadoj"],"Description":["Priskribo"],"Directory name":["Nomo de dosierujo"],"Don't show again":["Ne montru denove"],"Download":["Elŝuti"],"Download tar":["Elŝuti en formato „tar“"],"Download tar.bz2":["Elŝuti en formato „tar.bz2“"],"Download tar.gz":["Elŝuti en formato „tar.gz“"],"Download zip":["Elŝuti en formato „zip“"],"DownloadArtifacts|Download":["Elŝuti"],"DownloadCommit|Email Patches":["Sendi flikaĵojn per retpoŝto"],"DownloadCommit|Plain Diff":["Normala dosiero kun diferencoj"],"DownloadSource|Download":["Elŝuti"],"Edit":["Redakti"],"Edit Pipeline Schedule %{id}":["Redakti ĉenstablan planon %{id}"],"Every day (at 4:00am)":["Ĉiutage (je 4:00)"],"Every month (on the 1st at 4:00am)":["Ĉiumonate (en la 1a de la monato, je 4:00)"],"Every week (Sundays at 4:00am)":["Ĉiusemajne (en dimanĉo, je 4:00)"],"Failed to change the owner":["Ne eblas ŝanĝi la posedanton"],"Failed to remove the pipeline schedule":["Ne eblas forigi la ĉenstablan planon"],"Files":["Dosieroj"],"Find by path":["Trovi per dosierindiko"],"Find file":["Trovi dosieron"],"FirstPushedBy|First":["Unue"],"FirstPushedBy|pushed by":["alpuŝita de"],"Fork":["Disbranĉigo","Disbranĉigoj"],"ForkedFromProjectPath|Forked from":["Disbranĉigita el"],"From issue creation until deploy to production":["De la kreado de la problemo ĝis la disponigado en la publika versio"],"From merge request merge until deploy to production":["De la kunfandado de la peto pri kunfando ĝis la disponigado en la publika versio"],"Go to your fork":["Al via disbranĉigo"],"GoToYourFork|Fork":["Disbranĉigo"],"Home":["Hejmo"],"Housekeeping successfully started":["La refreŝigo komenciĝis sukcese"],"Import repository":["Enporti deponejon"],"Interval Pattern":["Intervala ŝablono"],"Introducing Cycle Analytics":["Ni prezentas al vi la ciklan analizon"],"LFSStatus|Disabled":["Malŝaltita"],"LFSStatus|Enabled":["Ŝaltita"],"Last %d day":["La lasta %d tago","La lastaj %d tagoj"],"Last Pipeline":["Lasta ĉenstablo"],"Last Update":["Lasta ĝisdatigo"],"Last commit":["Lasta enmetado"],"Learn more in the":["Lernu pli en la"],"Learn more in the|pipeline schedules documentation":["dokumentado pri ĉenstablaj planoj"],"Leave group":["Forlasi la grupon"],"Leave project":["Forlasi la projekton"],"Limited to showing %d event at most":["Limigita al montrado de ne pli ol %d evento","Limigita al montrado de ne pli ol %d eventoj"],"Median":["Mediano"],"MissingSSHKeyWarningLink|add an SSH key":["aldonos SSH-ŝlosilon"],"New Issue":["Nova problemo","Novaj problemoj"],"New Pipeline Schedule":["Nova ĉenstabla plano"],"New branch":["Nova branĉo"],"New directory":["Nova dosierujo"],"New file":["Nova dosiero"],"New issue":["Nova problemo"],"New merge request":["Nova peto pri kunfando"],"New schedule":["Nova plano"],"New snippet":["Nova kodaĵo"],"New tag":["Nova etikedo"],"No repository":["Ne estas deponejo"],"No schedules":["Ne estas planoj"],"Not available":["Ne disponebla"],"Not enough data":["Ne estas sufiĉe da datenoj"],"Notification events":["Sciigaj eventoj"],"NotificationEvent|Close issue":["Fermi problemon"],"NotificationEvent|Close merge request":["Fermi peton pri kunfando"],"NotificationEvent|Failed pipeline":["Malsukcesa ĉenstablo"],"NotificationEvent|Merge merge request":["Apliki peton pri kunfando"],"NotificationEvent|New issue":["Nova problemo"],"NotificationEvent|New merge request":["Nova peto pri kunfando"],"NotificationEvent|New note":["Nova noto"],"NotificationEvent|Reassign issue":["Reatribui problemon"],"NotificationEvent|Reassign merge request":["Reatribui peton pri kunfando"],"NotificationEvent|Reopen issue":["Remalfermi problemon"],"NotificationEvent|Successful pipeline":["Sukcesa ĉenstablo"],"NotificationLevel|Custom":["Propraj"],"NotificationLevel|Disabled":["Malŝaltitaj"],"NotificationLevel|Global":["Ĝeneralaj"],"NotificationLevel|On mention":["Ĉe mencio"],"NotificationLevel|Participate":["Partoprenado"],"NotificationLevel|Watch":["Rigardado"],"OfSearchInADropdown|Filter":["Filtrilo"],"OpenedNDaysAgo|Opened":["Malfermita"],"Options":["Opcioj"],"Owner":["Posedanto"],"Pipeline":["Ĉenstablo"],"Pipeline Health":["Stato"],"Pipeline Schedule":["Ĉenstabla plano"],"Pipeline Schedules":["Ĉenstablaj planoj"],"PipelineSchedules|Activated":["Ŝaltita"],"PipelineSchedules|Active":["Ŝaltitaj"],"PipelineSchedules|All":["Ĉiuj"],"PipelineSchedules|Inactive":["Malŝaltitaj"],"PipelineSchedules|Next Run":["Sekvanta plenumo"],"PipelineSchedules|None":["Nenio"],"PipelineSchedules|Provide a short description for this pipeline":["Entajpu mallongan priskribon pri ĉi tiu ĉenstablo"],"PipelineSchedules|Take ownership":["Akiri posedon"],"PipelineSchedules|Target":["Celo"],"PipelineSheduleIntervalPattern|Custom":["Propra"],"Pipeline|with stage":["kun etapo"],"Pipeline|with stages":["kun etapoj"],"Project '%{project_name}' queued for deletion.":["La projekto „%{project_name}“ estis alvicigita por forigado."],"Project '%{project_name}' was successfully created.":["La projekto „%{project_name}“ estis sukcese kreita."],"Project '%{project_name}' was successfully updated.":["La projekto „%{project_name}“ estis sukcese ĝisdatigita."],"Project '%{project_name}' will be deleted.":["La projekto „%{project_name}“ estos forigita."],"Project access must be granted explicitly to each user.":["Ĉiu uzanto devas akiri propran atingon al la projekto."],"Project export could not be deleted.":["Ne eblas forigi la projektan elporton."],"Project export has been deleted.":["La projekta elporto estis forigita."],"Project export link has expired. Please generate a new export from your project settings.":["La ligilo por la projekta elporto eksvalidiĝis. Bonvolu krei novan elporton en la agordoj de la projekto."],"Project export started. A download link will be sent by email.":["La elporto de la projekto komenciĝis. Vi ricevos ligilon per retpoŝto por elŝuti la datenoj."],"Project home":["Hejmo de la projekto"],"ProjectFeature|Disabled":["Malŝaltita"],"ProjectFeature|Everyone with access":["Ĉiu, kiu havas atingon"],"ProjectFeature|Only team members":["Nur skipanoj"],"ProjectFileTree|Name":["Nomo"],"ProjectLastActivity|Never":["Neniam"],"ProjectLifecycle|Stage":["Etapo"],"ProjectNetworkGraph|Graph":["Grafeo"],"Read more":["Legu pli"],"Readme":["LeguMin"],"RefSwitcher|Branches":["Branĉoj"],"RefSwitcher|Tags":["Etikedoj"],"Related Commits":["Rilataj enmetadoj"],"Related Deployed Jobs":["Rilataj disponigitaj taskoj"],"Related Issues":["Rilataj problemoj"],"Related Jobs":["Rilataj taskoj"],"Related Merge Requests":["Rilataj petoj pri kunfando"],"Related Merged Requests":["Rilataj aplikitaj petoj pri kunfando"],"Remind later":["Rememorigu denove"],"Remove project":["Forigi la projekton"],"Request Access":["Peti atingeblon"],"Revert this commit":["Malfari ĉi tiun enmetadon"],"Revert this merge request":["Malfari ĉi tiun peton pri kunfando"],"Save pipeline schedule":["Konservi ĉenstablan planon"],"Schedule a new pipeline":["Plani novan ĉenstablon"],"Scheduling Pipelines":["Planado de la ĉenstabloj"],"Search branches and tags":["Serĉu branĉon aŭ etikedon"],"Select Archive Format":["Elektu formaton de arkivo"],"Select a timezone":["Elektu horzonon"],"Select target branch":["Elektu celan branĉon"],"Set a password on your account to pull or push via %{protocol}":["Kreu pasvorton por via konto por ebligi al vi eltiri kaj alpuŝi per %{protocol}"],"Set up CI":["Agordi SI"],"Set up Koding":["Agordi „Koding“"],"Set up auto deploy":["Agordi aŭtomatan disponigadon"],"SetPasswordToCloneLink|set a password":["kreos pasvorton"],"Showing %d event":["Estas montrata %d evento","Estas montrataj %d eventoj"],"Source code":["Kodo"],"StarProject|Star":["Steligi"],"Start a %{new_merge_request} with these changes":["Kreu %{new_merge_request} kun ĉi tiuj ŝanĝoj"],"Switch branch/tag":["Iri al branĉo/etikedo"],"Tag":["Etikedo","Etikedoj"],"Tags":["Etikedoj"],"Target Branch":["Cela branĉo"],"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.":["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."],"The collection of events added to the data gathered for that stage.":["La aro da eventoj, kiuj estas aldonitaj al la datenoj kolektitaj por la etapo."],"The fork relationship has been removed.":["La rilato de disbranĉigo estis forigita."],"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.":["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."],"The phase of the development lifecycle.":["La etapo de la disvolva ciklo."],"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.":["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."],"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.":["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."],"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.":["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."],"The project can be accessed by any logged in user.":["Ĉiu ensalutita uzanto havas atingon al la projekto"],"The project can be accessed without any authentication.":["Ĉiu povas havi atingon al la projekto, sen ensaluti"],"The repository for this project does not exist.":["La deponejo por ĉi tiu projekto ne ekzistas."],"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.":["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."],"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.":["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."],"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.":["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."],"The time taken by each data entry gathered by that stage.":["La tempo, kiu estas necesa por ĉiu dateno kolektita de la etapo."],"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.":["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."],"This means you can not push code until you create an empty repository or import existing one.":["Ĉi tiu signifas, ke vi ne povos alpuŝi kodon, antaŭ ol vi kreos malplenan deponejon aŭ enportos jam ekzistantan."],"Time before an issue gets scheduled":["Tempo antaŭ problemo estas planita por ellabori"],"Time before an issue starts implementation":["Tempo antaŭ la komenco de laboro super problemo"],"Time between merge request creation and merge/close":["Tempo inter la kreado de poeto pri kunfando kaj ĝia aplikado/fermado"],"Time until first merge request":["Tempo ĝis la unua peto pri kunfando"],"Timeago|%s days ago":["antaŭ %s tagoj"],"Timeago|%s days remaining":["restas %s tagoj"],"Timeago|%s hours remaining":["restas %s horoj"],"Timeago|%s minutes ago":["antaŭ %s minutoj"],"Timeago|%s minutes remaining":["restas %s minutoj"],"Timeago|%s months ago":["antaŭ %s monatoj"],"Timeago|%s months remaining":["restas %s monatoj"],"Timeago|%s seconds remaining":["restas %s sekundoj"],"Timeago|%s weeks ago":["antaŭ %s semajnoj"],"Timeago|%s weeks remaining":["restas %s semajnoj"],"Timeago|%s years ago":["antaŭ %s jaroj"],"Timeago|%s years remaining":["restas %s jaroj"],"Timeago|1 day remaining":["restas 1 tago"],"Timeago|1 hour remaining":["restas 1 horo"],"Timeago|1 minute remaining":["restas 1 minuto"],"Timeago|1 month remaining":["restas 1 monato"],"Timeago|1 week remaining":["restas 1 semajno"],"Timeago|1 year remaining":["restas 1 jaro"],"Timeago|Past due":["Malfruiĝis"],"Timeago|a day ago":["antaŭ unu tago"],"Timeago|a month ago":["antaŭ unu monato"],"Timeago|a week ago":["antaŭ unu semajno"],"Timeago|a while":["antaŭ iom da tempo"],"Timeago|a year ago":["antaŭ unu jaro"],"Timeago|about %s hours ago":["antaŭ ĉirkaŭ %s horoj"],"Timeago|about a minute ago":["antaŭ ĉirkaŭ unu minuto"],"Timeago|about an hour ago":["antaŭ ĉirkaŭ unu horo"],"Timeago|in %s days":["post %s tagoj"],"Timeago|in %s hours":["post %s horoj"],"Timeago|in %s minutes":["post %s minutoj"],"Timeago|in %s months":["post %s monatoj"],"Timeago|in %s seconds":["post %s sekundoj"],"Timeago|in %s weeks":["post %s semajnoj"],"Timeago|in %s years":["post %s jaroj"],"Timeago|in 1 day":["post 1 tago"],"Timeago|in 1 hour":["post 1 horo"],"Timeago|in 1 minute":["post 1 minuto"],"Timeago|in 1 month":["post 1 monato"],"Timeago|in 1 week":["post 1 semajno"],"Timeago|in 1 year":["post 1 jaro"],"Timeago|less than a minute ago":["antaŭ malpli ol minuto"],"Time|hr":["h","h"],"Time|min":["min","min"],"Time|s":["s"],"Total Time":["Totala tempo"],"Total test time for all commits/merges":["Totala tempo por la testado de ĉiuj enmetadoj/kunfandoj"],"Unstar":["Malsteligi"],"Upload New File":["Alŝuti novan dosieron"],"Upload file":["Alŝuti dosieron"],"Use your global notification setting":["Uzi vian ĝeneralan agordon pri la sciigoj"],"VisibilityLevel|Internal":["Interna"],"VisibilityLevel|Private":["Privata"],"VisibilityLevel|Public":["Publika"],"Want to see the data? Please ask an administrator for access.":["Ĉu vi volas vidi la datenojn? Bonvolu peti atingeblon de administranto."],"We don't have enough data to show this stage.":["Ne estas sufiĉe da datenoj por montri ĉi tiun etapon."],"Withdraw Access Request":["Nuligi la peton pri atingeblo"],"You are going to remove %{project_name_with_namespace}.\\nRemoved project CANNOT be restored!\\nAre you ABSOLUTELY sure?":["Vi forigos „%{project_name_with_namespace}“.\\nOni NE POVAS malfari la forigon de projekto!\\nĈu vi estas ABSOLUTE certa?"],"You are going to remove the fork relationship to source project %{forked_from_project}. Are you ABSOLUTELY sure?":["Vi forigos la rilaton de la disbranĉigo al la originala projekto, „%{forked_from_project}“. Ĉu vi estas ABSOLUTE certa?"],"You are going to transfer %{project_name_with_namespace} to another owner. Are you ABSOLUTELY sure?":["Vi transigos „%{project_name_with_namespace}“ al alia posedanto. Ĉu vi estas ABSOLUTE certa?"],"You can only add files when you are on a branch":["Oni povas aldoni dosierojn nur kiam oni estas en branĉo"],"You have reached your project limit":["Vi ne povas krei pliajn projektojn"],"You must sign in to star a project":["Oni devas ensaluti por steligi projekton"],"You need permission.":["VI bezonas permeson."],"You will not get any notifications via email":["VI ne ricevos sciigojn per retpoŝto"],"You will only receive notifications for the events you choose":["Vi ricevos sciigojn nur por la eventoj elektitaj de vi"],"You will only receive notifications for threads you have participated in":["Vi ricevos sciigojn nur por la fadenoj, en kiuj vi partoprenis"],"You will receive notifications for any activity":["Vi ricevos sciigojn por ĉiu ago"],"You will receive notifications only for comments in which you were @mentioned":["Vi ricevos sciigojn nur por komentoj, en kiuj vi estas @menciita"],"You won't be able to pull or push project code via %{protocol} until you %{set_password_link} on your account":["Vi ne povos eltiri aŭ alpuŝi kodon per %{protocol} antaŭ ol vi %{set_password_link} por via konto"],"You won't be able to pull or push project code via SSH until you %{add_ssh_key_link} to your profile":["Vi ne povos eltiri aŭ alpuŝi kodon per SSH antaŭ ol vi %{add_ssh_key_link} al via profilo"],"Your name":["Via nomo"],"day":["tago","tagoj"],"new merge request":["novan peton pri kunfando"],"notification emails":["sciigoj per retpoŝto"],"parent":["patro","patroj"]}}}; \ No newline at end of file
diff --git a/app/assets/javascripts/locale/es/app.js b/app/assets/javascripts/locale/es/app.js
deleted file mode 100644
index 8d951928849..00000000000
--- a/app/assets/javascripts/locale/es/app.js
+++ /dev/null
@@ -1 +0,0 @@
-var locales = locales || {}; locales['es'] = {"domain":"app","locale_data":{"app":{"":{"Project-Id-Version":"gitlab 1.0.0","Report-Msgid-Bugs-To":"","PO-Revision-Date":"2017-06-21 12:09-0500","Language-Team":"Spanish","Language":"es","MIME-Version":"1.0","Content-Type":"text/plain; charset=UTF-8","Content-Transfer-Encoding":"8bit","Plural-Forms":"nplurals=2; plural=n != 1;","Last-Translator":"Bob Van Landuyt <bob@gitlab.com>","X-Generator":"Poedit 2.0.2","lang":"es","domain":"app","plural_forms":"nplurals=2; plural=n != 1;"},"%d additional commit has been omitted to prevent performance issues.":["%d cambio adicional ha sido omitido para evitar problemas de rendimiento.","%d cambios adicionales han sido omitidos para evitar problemas de rendimiento."],"%d commit":["%d cambio","%d cambios"],"%{commit_author_link} committed %{commit_timeago}":["%{commit_author_link} cambió %{commit_timeago}"],"About auto deploy":["Acerca del auto despliegue"],"Active":["Activo"],"Activity":["Actividad"],"Add Changelog":["Agregar Changelog"],"Add Contribution guide":["Agregar guía de contribución"],"Add License":["Agregar Licencia"],"Add an SSH key to your profile to pull or push via SSH.":["Agregar una clave SSH a tu perfil para actualizar o enviar a través de SSH."],"Add new directory":["Agregar nuevo directorio"],"Archived project! Repository is read-only":["¡Proyecto archivado! El repositorio es de solo lectura"],"Are you sure you want to delete this pipeline schedule?":["¿Estás seguro que deseas eliminar esta programación del pipeline?"],"Attach a file by drag &amp; drop or %{upload_link}":["Adjunte un archivo arrastrando &amp; soltando o %{upload_link}"],"Branch":["Rama","Ramas"],"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}":["La rama <strong>%{branch_name}</strong> fue creada. Para configurar el auto despliegue, escoge una plantilla Yaml para GitLab CI y envía tus cambios. %{link_to_autodeploy_doc}"],"BranchSwitcherPlaceholder|Search branches":["Buscar ramas"],"BranchSwitcherTitle|Switch branch":["Cambiar rama"],"Branches":["Ramas"],"Browse Directory":["Examinar directorio"],"Browse File":["Examinar archivo"],"Browse Files":["Examinar archivos"],"Browse files":["Examinar archivos"],"ByAuthor|by":["por"],"CI configuration":["Configuración de CI"],"Cancel":["Cancelar"],"ChangeTypeActionLabel|Pick into branch":["Escoger en la rama"],"ChangeTypeActionLabel|Revert in branch":["Revertir en la rama"],"ChangeTypeAction|Cherry-pick":["Cherry-pick"],"ChangeTypeAction|Revert":["Revertir"],"Changelog":["Changelog"],"Charts":["Gráficos"],"Cherry-pick this commit":["Escoger este cambio"],"Cherry-pick this merge request":["Escoger esta solicitud de fusión"],"CiStatusLabel|canceled":["cancelado"],"CiStatusLabel|created":["creado"],"CiStatusLabel|failed":["fallido"],"CiStatusLabel|manual action":["acción manual"],"CiStatusLabel|passed":["pasó"],"CiStatusLabel|passed with warnings":["pasó con advertencias"],"CiStatusLabel|pending":["pendiente"],"CiStatusLabel|skipped":["omitido"],"CiStatusLabel|waiting for manual action":["esperando acción manual"],"CiStatusText|blocked":["bloqueado"],"CiStatusText|canceled":["cancelado"],"CiStatusText|created":["creado"],"CiStatusText|failed":["fallado"],"CiStatusText|manual":["manual"],"CiStatusText|passed":["pasó"],"CiStatusText|pending":["pendiente"],"CiStatusText|skipped":["omitido"],"CiStatus|running":["en ejecución"],"Commit":["Cambio","Cambios"],"Commit message":["Mensaje del cambio"],"CommitBoxTitle|Commit":["Cambio"],"CommitMessage|Add %{file_name}":["Agregar %{file_name}"],"Commits":["Cambios"],"Commits feed":["Feed de cambios"],"Commits|History":["Historial"],"Committed by":["Enviado por"],"Compare":["Comparar"],"Contribution guide":["Guía de contribución"],"Contributors":["Contribuidores"],"Copy URL to clipboard":["Copiar URL al portapapeles"],"Copy commit SHA to clipboard":["Copiar SHA del cambio al portapapeles"],"Create New Directory":["Crear Nuevo Directorio"],"Create directory":["Crear directorio"],"Create empty bare repository":["Crear repositorio vacío"],"Create merge request":["Crear solicitud de fusión"],"Create new...":["Crear nuevo..."],"CreateNewFork|Fork":["Bifurcar"],"CreateTag|Tag":["Etiqueta"],"Cron Timezone":["Zona horaria del Cron"],"Cron syntax":["Sintaxis de Cron"],"Custom notification events":["Eventos de notificaciones personalizadas"],"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}.":["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}."],"Cycle Analytics":["Cycle Analytics"],"Cycle Analytics gives an overview of how much time it takes to go from idea to production in your project.":["Cycle Analytics ofrece una visión general de cuánto tiempo tarda en pasar de idea a producción en su proyecto."],"CycleAnalyticsStage|Code":["Código"],"CycleAnalyticsStage|Issue":["Incidencia"],"CycleAnalyticsStage|Plan":["Planificación"],"CycleAnalyticsStage|Production":["Producción"],"CycleAnalyticsStage|Review":["Revisión"],"CycleAnalyticsStage|Staging":["Puesta en escena"],"CycleAnalyticsStage|Test":["Pruebas"],"Define a custom pattern with cron syntax":["Definir un patrón personalizado con la sintaxis de cron"],"Delete":["Eliminar"],"Deploy":["Despliegue","Despliegues"],"Description":["Descripción"],"Directory name":["Nombre del directorio"],"Don't show again":["No mostrar de nuevo"],"Download":["Descargar"],"Download tar":["Descargar tar"],"Download tar.bz2":["Descargar tar.bz2"],"Download tar.gz":["Descargar tar.gz"],"Download zip":["Descargar zip"],"DownloadArtifacts|Download":["Descargar"],"DownloadCommit|Email Patches":["Parches por correo electrónico"],"DownloadCommit|Plain Diff":["Diferencias en texto plano"],"DownloadSource|Download":["Descargar"],"Edit":["Editar"],"Edit Pipeline Schedule %{id}":["Editar Programación del Pipeline %{id}"],"Every day (at 4:00am)":["Todos los días (a las 4:00 am)"],"Every month (on the 1st at 4:00am)":["Todos los meses (el día 1 a las 4:00 am)"],"Every week (Sundays at 4:00am)":["Todas las semanas (domingos a las 4:00 am)"],"Failed to change the owner":["Error al cambiar el propietario"],"Failed to remove the pipeline schedule":["Error al eliminar la programación del pipeline"],"Files":["Archivos"],"Filter by commit message":["Filtrar por mensaje del cambio"],"Find by path":["Buscar por ruta"],"Find file":["Buscar archivo"],"FirstPushedBy|First":["Primer"],"FirstPushedBy|pushed by":["enviado por"],"Fork":["Bifurcación","Bifurcaciones"],"ForkedFromProjectPath|Forked from":["Bifurcado de"],"From issue creation until deploy to production":["Desde la creación de la incidencia hasta el despliegue a producción"],"From merge request merge until deploy to production":["Desde la integración de la solicitud de fusión hasta el despliegue a producción"],"Go to your fork":["Ir a tu bifurcación"],"GoToYourFork|Fork":["Bifurcación"],"Home":["Inicio"],"Housekeeping successfully started":["Servicio de limpieza iniciado con éxito"],"Import repository":["Importar repositorio"],"Interval Pattern":["Patrón de intervalo"],"Introducing Cycle Analytics":["Introducción a Cycle Analytics"],"LFSStatus|Disabled":["Deshabilitado"],"LFSStatus|Enabled":["Habilitado"],"Last %d day":["Último %d día","Últimos %d días"],"Last Pipeline":["Último Pipeline"],"Last Update":["Última actualización"],"Last commit":["Último cambio"],"Learn more in the":["Más información en la"],"Learn more in the|pipeline schedules documentation":["documentación sobre la programación de pipelines"],"Leave group":["Abandonar grupo"],"Leave project":["Abandonar proyecto"],"Limited to showing %d event at most":["Limitado a mostrar máximo %d evento","Limitado a mostrar máximo %d eventos"],"Median":["Mediana"],"MissingSSHKeyWarningLink|add an SSH key":["agregar una clave SSH"],"New Issue":["Nueva incidencia","Nuevas incidencias"],"New Pipeline Schedule":["Nueva Programación del Pipeline"],"New branch":["Nueva rama"],"New directory":["Nuevo directorio"],"New file":["Nuevo archivo"],"New issue":["Nueva incidencia"],"New merge request":["Nueva solicitud de fusión"],"New schedule":["Nueva programación"],"New snippet":["Nuevo fragmento de código"],"New tag":["Nueva etiqueta"],"No repository":["No hay repositorio"],"No schedules":["No hay programaciones"],"Not available":["No disponible"],"Not enough data":["No hay suficientes datos"],"Notification events":["Eventos de notificación"],"NotificationEvent|Close issue":["Cerrar incidencia"],"NotificationEvent|Close merge request":["Cerrar solicitud de fusión"],"NotificationEvent|Failed pipeline":["Pipeline fallido"],"NotificationEvent|Merge merge request":["Integrar solicitud de fusión"],"NotificationEvent|New issue":["Nueva incidencia"],"NotificationEvent|New merge request":["Nueva solicitud de fusión"],"NotificationEvent|New note":["Nueva nota"],"NotificationEvent|Reassign issue":["Reasignar incidencia"],"NotificationEvent|Reassign merge request":["Reasignar solicitud de fusión"],"NotificationEvent|Reopen issue":["Reabrir incidencia"],"NotificationEvent|Successful pipeline":["Pipeline exitoso"],"NotificationLevel|Custom":["Personalizado"],"NotificationLevel|Disabled":["Deshabilitado"],"NotificationLevel|Global":["Global"],"NotificationLevel|On mention":["Cuando me mencionan"],"NotificationLevel|Participate":["Participación"],"NotificationLevel|Watch":["Vigilancia"],"OfSearchInADropdown|Filter":["Filtrar"],"OpenedNDaysAgo|Opened":["Abierto"],"Options":["Opciones"],"Owner":["Propietario"],"Pipeline":["Pipeline"],"Pipeline Health":["Estado del Pipeline"],"Pipeline Schedule":["Programación del Pipeline"],"Pipeline Schedules":["Programaciones de los Pipelines"],"PipelineSchedules|Activated":["Activado"],"PipelineSchedules|Active":["Activos"],"PipelineSchedules|All":["Todos"],"PipelineSchedules|Inactive":["Inactivos"],"PipelineSchedules|Next Run":["Próxima Ejecución"],"PipelineSchedules|None":["Ninguno"],"PipelineSchedules|Provide a short description for this pipeline":["Proporcione una breve descripción para este pipeline"],"PipelineSchedules|Take ownership":["Tomar posesión"],"PipelineSchedules|Target":["Destino"],"PipelineSheduleIntervalPattern|Custom":["Personalizado"],"Pipeline|with stage":["con etapa"],"Pipeline|with stages":["con etapas"],"Project '%{project_name}' queued for deletion.":["Proyecto ‘%{project_name}’ en cola para eliminación."],"Project '%{project_name}' was successfully created.":["Proyecto ‘%{project_name}’ fue creado satisfactoriamente."],"Project '%{project_name}' was successfully updated.":["Proyecto ‘%{project_name}’ fue actualizado satisfactoriamente."],"Project '%{project_name}' will be deleted.":["Proyecto ‘%{project_name}’ será eliminado."],"Project access must be granted explicitly to each user.":["El acceso al proyecto debe concederse explícitamente a cada usuario."],"Project export could not be deleted.":["No se pudo eliminar la exportación del proyecto."],"Project export has been deleted.":["La exportación del proyecto ha sido eliminada."],"Project export link has expired. Please generate a new export from your project settings.":["El enlace de exportación del proyecto ha caducado. Por favor, genera una nueva exportación desde la configuración del proyecto."],"Project export started. A download link will be sent by email.":["Se inició la exportación del proyecto. Se enviará un enlace de descarga por correo electrónico."],"Project home":["Inicio del proyecto"],"ProjectFeature|Disabled":["Deshabilitada"],"ProjectFeature|Everyone with access":["Todos con acceso"],"ProjectFeature|Only team members":["Solo miembros del equipo"],"ProjectFileTree|Name":["Nombre"],"ProjectLastActivity|Never":["Nunca"],"ProjectLifecycle|Stage":["Etapa"],"ProjectNetworkGraph|Graph":["Historial gráfico"],"Read more":["Leer más"],"Readme":["Léeme"],"RefSwitcher|Branches":["Ramas"],"RefSwitcher|Tags":["Etiquetas"],"Related Commits":["Cambios Relacionados"],"Related Deployed Jobs":["Trabajos Desplegados Relacionados"],"Related Issues":["Incidencias Relacionadas"],"Related Jobs":["Trabajos Relacionados"],"Related Merge Requests":["Solicitudes de fusión Relacionadas"],"Related Merged Requests":["Solicitudes de fusión Relacionadas"],"Remind later":["Recordar después"],"Remove project":["Eliminar proyecto"],"Request Access":["Solicitar acceso"],"Revert this commit":["Revertir este cambio"],"Revert this merge request":["Revertir esta solicitud de fusión"],"Save pipeline schedule":["Guardar programación del pipeline"],"Schedule a new pipeline":["Programar un nuevo pipeline"],"Scheduling Pipelines":["Programación de Pipelines"],"Search branches and tags":["Buscar ramas y etiquetas"],"Select Archive Format":["Seleccionar formato de archivo"],"Select a timezone":["Selecciona una zona horaria"],"Select target branch":["Selecciona una rama de destino"],"Set a password on your account to pull or push via %{protocol}":["Establezca una contraseña en su cuenta para actualizar o enviar a través de %{protocol}"],"Set up CI":["Configurar CI"],"Set up Koding":["Configurar Koding"],"Set up auto deploy":["Configurar auto despliegue"],"SetPasswordToCloneLink|set a password":["establecer una contraseña"],"Showing %d event":["Mostrando %d evento","Mostrando %d eventos"],"Source code":["Código fuente"],"StarProject|Star":["Destacar"],"Start a %{new_merge_request} with these changes":["Iniciar una %{new_merge_request} con estos cambios"],"Switch branch/tag":["Cambiar rama/etiqueta"],"Tag":["Etiqueta","Etiquetas"],"Tags":["Etiquetas"],"Target Branch":["Rama de destino"],"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.":["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."],"The collection of events added to the data gathered for that stage.":["La colección de eventos agregados a los datos recopilados para esa etapa."],"The fork relationship has been removed.":["La relación con la bifurcación se ha eliminado."],"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.":["La etapa de incidencia muestra el tiempo que toma desde la creación de un tema hasta asignar el tema a un hito, o añadir el tema a una lista en el panel de temas. Empieza a crear temas para ver los datos de esta etapa."],"The phase of the development lifecycle.":["La etapa del ciclo de vida de desarrollo."],"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.":["La programación de pipelines ejecuta pipelines en el futuro, repetidamente, para ramas o etiquetas específicas. Los pipelines programados heredarán acceso limitado al proyecto basado en su usuario asociado."],"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.":["La etapa de planificación muestra el tiempo desde el paso anterior hasta el envío de tu primera confirmación. Este tiempo se añadirá automáticamente una vez que usted envíe el primer cambio."],"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.":["La etapa de producción muestra el tiempo total que tarda entre la creación de una incidencia y el despliegue del código a producción. Los datos se añadirán automáticamente una vez haya finalizado por completo el ciclo de idea a producción."],"The project can be accessed by any logged in user.":["El proyecto puede ser accedido por cualquier usuario conectado."],"The project can be accessed without any authentication.":["El proyecto puede accederse sin ninguna autenticación."],"The repository for this project does not exist.":["El repositorio para este proyecto no existe."],"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.":["La etapa de revisión muestra el tiempo desde la creación de la solicitud de fusión hasta que los cambios se fusionaron. Los datos se añadirán automáticamente después de fusionar su primera solicitud de fusión."],"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.":["La etapa de puesta en escena muestra el tiempo entre la fusión y el despliegue de código en el entorno de producción. Los datos se añadirán automáticamente una vez que se despliega a producción por primera vez."],"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.":["La etapa de pruebas muestra el tiempo que GitLab CI toma para ejecutar cada pipeline para la solicitud de fusión relacionada. Los datos se añadirán automáticamente luego de que el primer pipeline termine de ejecutarse."],"The time taken by each data entry gathered by that stage.":["El tiempo utilizado por cada entrada de datos obtenido por esa etapa."],"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.":["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."],"This means you can not push code until you create an empty repository or import existing one.":["Esto significa que no puede enviar código hasta que cree un repositorio vacío o importe uno existente."],"Time before an issue gets scheduled":["Tiempo antes de que una incidencia sea programada"],"Time before an issue starts implementation":["Tiempo antes de que empieze la implementación de una incidencia"],"Time between merge request creation and merge/close":["Tiempo entre la creación de la solicitud de fusión y la integración o cierre de ésta"],"Time until first merge request":["Tiempo hasta la primera solicitud de fusión"],"Timeago|%s days ago":["hace %s días"],"Timeago|%s days remaining":["%s días restantes"],"Timeago|%s hours remaining":["%s horas restantes"],"Timeago|%s minutes ago":["hace %s minutos"],"Timeago|%s minutes remaining":["%s minutos restantes"],"Timeago|%s months ago":["hace %s meses"],"Timeago|%s months remaining":["%s meses restantes"],"Timeago|%s seconds remaining":["%s segundos restantes"],"Timeago|%s weeks ago":["hace %s semanas"],"Timeago|%s weeks remaining":["%s semanas restantes"],"Timeago|%s years ago":["hace %s años"],"Timeago|%s years remaining":["%s años restantes"],"Timeago|1 day remaining":["1 día restante"],"Timeago|1 hour remaining":["1 hora restante"],"Timeago|1 minute remaining":["1 minuto restante"],"Timeago|1 month remaining":["1 mes restante"],"Timeago|1 week remaining":["1 semana restante"],"Timeago|1 year remaining":["1 año restante"],"Timeago|Past due":["Atrasado"],"Timeago|a day ago":["hace un día"],"Timeago|a month ago":["hace un mes"],"Timeago|a week ago":["hace una semana"],"Timeago|a while":["hace un momento"],"Timeago|a year ago":["hace un año"],"Timeago|about %s hours ago":["hace alrededor de %s horas"],"Timeago|about a minute ago":["hace alrededor de 1 minuto"],"Timeago|about an hour ago":["hace alrededor de 1 hora"],"Timeago|in %s days":["en %s días"],"Timeago|in %s hours":["en %s horas"],"Timeago|in %s minutes":["en %s minutos"],"Timeago|in %s months":["en %s meses"],"Timeago|in %s seconds":["en %s segundos"],"Timeago|in %s weeks":["en %s semanas"],"Timeago|in %s years":["en %s años"],"Timeago|in 1 day":["en 1 día"],"Timeago|in 1 hour":["en 1 hora"],"Timeago|in 1 minute":["en 1 minuto"],"Timeago|in 1 month":["en 1 mes"],"Timeago|in 1 week":["en 1 semana"],"Timeago|in 1 year":["en 1 año"],"Timeago|less than a minute ago":["hace menos de 1 minuto"],"Time|hr":["hr","hrs"],"Time|min":["min","mins"],"Time|s":["s"],"Total Time":["Tiempo Total"],"Total test time for all commits/merges":["Tiempo total de pruebas para todos los cambios o integraciones"],"Unstar":["No Destacar"],"Upload New File":["Subir nuevo archivo"],"Upload file":["Subir archivo"],"UploadLink|click to upload":["Hacer clic para subir"],"Use your global notification setting":["Utiliza tu configuración de notificación global"],"View open merge request":["Ver solicitud de fusión abierta"],"VisibilityLevel|Internal":["Interno"],"VisibilityLevel|Private":["Privado"],"VisibilityLevel|Public":["Público"],"Want to see the data? Please ask an administrator for access.":["¿Quieres ver los datos? Por favor pide acceso al administrador."],"We don't have enough data to show this stage.":["No hay suficientes datos para mostrar en esta etapa."],"Withdraw Access Request":["Retirar Solicitud de Acceso"],"You are going to remove %{project_name_with_namespace}.\\nRemoved project CANNOT be restored!\\nAre you ABSOLUTELY sure?":["Va a eliminar %{project_name_with_namespace}.\\n¡El proyecto eliminado NO puede ser restaurado!\\n¿Estás TOTALMENTE seguro?"],"You are going to remove the fork relationship to source project %{forked_from_project}. Are you ABSOLUTELY sure?":["Vas a eliminar el enlace de la bifurcación con el proyecto original %{forked_from_project}. ¿Estás TOTALMENTE seguro?"],"You are going to transfer %{project_name_with_namespace} to another owner. Are you ABSOLUTELY sure?":["Vas a transferir %{project_name_with_namespace} a otro propietario. ¿Estás TOTALMENTE seguro?"],"You can only add files when you are on a branch":["Solo puedes agregar archivos cuando estás en una rama"],"You have reached your project limit":["Has alcanzado el límite de tu proyecto"],"You must sign in to star a project":["Debes iniciar sesión para destacar un proyecto"],"You need permission.":["Necesitas permisos."],"You will not get any notifications via email":["No recibirás ninguna notificación por correo electrónico"],"You will only receive notifications for the events you choose":["Solo recibirás notificaciones de los eventos que elijas"],"You will only receive notifications for threads you have participated in":["Solo recibirás notificaciones de los temas en los que has participado"],"You will receive notifications for any activity":["Recibirás notificaciones por cualquier actividad"],"You will receive notifications only for comments in which you were @mentioned":["Recibirás notificaciones solo para los comentarios en los que se te mencionó"],"You won't be able to pull or push project code via %{protocol} until you %{set_password_link} on your account":["No podrás actualizar o enviar código al proyecto a través de %{protocol} hasta que %{set_password_link} en tu cuenta"],"You won't be able to pull or push project code via SSH until you %{add_ssh_key_link} to your profile":["No podrás actualizar o enviar código al proyecto a través de SSH hasta que %{add_ssh_key_link} en su perfil"],"Your name":["Tu nombre"],"day":["día","días"],"new merge request":["nueva solicitud de fusión"],"notification emails":["correos electrónicos de notificación"],"parent":["padre","padres"]}}}; \ No newline at end of file
diff --git a/app/assets/javascripts/locale/fr/app.js b/app/assets/javascripts/locale/fr/app.js
deleted file mode 100644
index f9904ea61ea..00000000000
--- a/app/assets/javascripts/locale/fr/app.js
+++ /dev/null
@@ -1 +0,0 @@
-var locales = locales || {}; locales['fr'] = {"domain":"app","locale_data":{"app":{"":{"Project-Id-Version":"gitlab 1.0.0","Report-Msgid-Bugs-To":"","POT-Creation-Date":"2017-06-15 20:38+0000","MIME-Version":"1.0","Content-Type":"text/plain; charset=UTF-8","Content-Transfer-Encoding":"8bit","PO-Revision-Date":"2017-06-14 04:21-0400","Last-Translator":"Dremor <egeorget@opmbx.org>","Language-Team":"French (https://www.transifex.com/gitlab-fr/teams/75145/fr/)","Language":"fr","Plural-Forms":"nplurals=2; plural=(n > 1);","X-Generator":"Zanata 3.9.6","lang":"fr","domain":"app","plural_forms":"nplurals=2; plural=(n > 1);"},"ByAuthor|by":["par"],"Commit":["Validation","Validations"],"Cycle Analytics gives an overview of how much time it takes to go from idea to production in your project.":["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."],"CycleAnalyticsStage|Code":["Code"],"CycleAnalyticsStage|Issue":["Incident"],"CycleAnalyticsStage|Plan":["Planification"],"CycleAnalyticsStage|Production":["Production"],"CycleAnalyticsStage|Review":["Examen"],"CycleAnalyticsStage|Staging":["Pré-production"],"CycleAnalyticsStage|Test":["Test"],"Deploy":["Déploiement","Déploiements"],"FirstPushedBy|First":["En premier"],"FirstPushedBy|pushed by":["poussé par"],"From issue creation until deploy to production":["Depuis la création de l'incident jusqu'au déploiement en production"],"From merge request merge until deploy to production":["Depuis la fusion de la demande de fusion jusqu'au déploiement en production"],"Introducing Cycle Analytics":["Introduction à l'analyseur de cycle"],"Last %d day":["Le dernier %d jour","Les derniers %d jours"],"Limited to showing %d event at most":["Limiter l'affichage au plus à %d évènement","Limiter l'affichage au plus à %d évènements"],"Median":["Médian"],"New Issue":["Nouvel incident","Nouveaux incidents"],"Not available":["Indisponible"],"Not enough data":["Données insuffisantes"],"OpenedNDaysAgo|Opened":["Ouvert"],"Pipeline Health":["Santé du Pipeline"],"ProjectLifecycle|Stage":["Étape"],"Read more":["Lire plus"],"Related Commits":["Validations liés"],"Related Deployed Jobs":["Tâches de déploiement liés"],"Related Issues":["Incidents liés"],"Related Jobs":["Tâches liées"],"Related Merge Requests":["Demandes de fusion liées"],"Related Merged Requests":["Demandes fusionnées liées"],"Showing %d event":["Affichage de %d évènement","Affichage de %d évènements"],"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.":["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."],"The collection of events added to the data gathered for that stage.":["L’ensemble d’évènements ajoutés aux données récupérées pour cette étape."],"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.":["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'incident. Débutez à créer des incidents pour voir des données pour cette étape."],"The phase of the development lifecycle.":["Les étapes du cycle de développement."],"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.":["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."],"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.":["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."],"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.":["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."],"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.":["L’étape de pré-production indique le temps entre la fusion de la RF 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."],"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.":["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."],"The time taken by each data entry gathered by that stage.":["Le temps pris par chaque entrée récoltée durant cette étape."],"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.":["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."],"Time before an issue gets scheduled":["Temps avant qu’un incident ne soit planifié"],"Time before an issue starts implementation":["Temps avant que résolution ne débute"],"Time between merge request creation and merge/close":["Temps entre la création d'une demande de fusion et sa fusion/clôture"],"Time until first merge request":["Temps jusqu’à la première demande de fusion"],"Time|hr":["hr","hrs"],"Time|min":["min","mins"],"Time|s":["s"],"Total Time":["Temps total"],"Total test time for all commits/merges":["Temps total de test pour toutes les validations/fusions"],"Want to see the data? Please ask an administrator for access.":["Vous voulez voir les données ? Merci de contacter un administrateur pour en obtenir l’accès."],"We don't have enough data to show this stage.":["Nous n'avons pas suffisamment de données pour afficher cette étape."],"You need permission.":["Vous avez besoin d’une autorisation."],"day":["jour","jours"],"%{commit_author_link} committed %{commit_timeago}":["%{commit_author_link} a validé %{commit_timeago}"],"About auto deploy":["A propos de l'auto-déploiement"],"Active":["Actif"],"Activity":["Activité"],"Add Changelog":["Ajouter un journal des modifications"],"Add Contribution guide":["Ajouter un guide de contribution"],"Add License":["Ajouter une licence"],"Add an SSH key to your profile to pull or push via SSH.":["Ajoutez une clef SSH à votre profil pour pouvoir récupérer et pousser par SSH."],"Add new directory":["Ajouter un nouveau dossier"],"Archived project! Repository is read-only":["Projet archivé ! Le dépôt est en lecture seule"],"Are you sure you want to delete this pipeline schedule?":["Êtes-vous sûr de vouloir supprimer ce pipeline programmé"],"Attach a file by drag &amp; drop or %{upload_link}":["Attachez un fichier par glisser &amp; déposer ou %{upload_link}"],"Branch":["Branche","Branches"],"#~ \"Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, cho\"#~ \"ose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_do\"#~ \"c}\"":["#~ \"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 Gitlab CI\"#~ \", et validez les modifications. %{link_to_autodeploy_doc}\""],"Branches":["Branches"],"Browse files":["Parcourir les fichiers"],"CI configuration":["Configuration du CI"],"Cancel":["Annuler"],"ChangeTypeActionLabel|Pick into branch":["Sélectionner dans la branche"],"ChangeTypeActionLabel|Revert in branch":["Annuler dans la branche"],"ChangeTypeAction|Cherry-pick":["Sélectionner"],"ChangeType|commit":["validation"],"ChangeType|merge request":["demande de fusion"],"Changelog":["Journal des modifications"],"Charts":["Graphiques"],"Cherry-pick this commit":["Sélectionner cette validation"],"Cherry-pick this merge-request":["Sélectionner cette demande de fusion"],"CiStatusLabel|canceled":["annulé"],"CiStatusLabel|created":["créé"],"CiStatusLabel|failed":["échoué"],"CiStatusLabel|manual action":["action manuelle"],"CiStatusLabel|passed":["passé"],"CiStatusLabel|passed with warnings":["passé avec des avertissements"],"CiStatusLabel|pending":["en attente"],"CiStatusLabel|skipped":["ignoré"],"CiStatusLabel|waiting for manual action":["en attente d'action manuelle"],"CiStatusText|blocked":["bloqué"],"CiStatusText|canceled":["annulé "],"CiStatusText|created":["créé"],"CiStatusText|failed":["échoué"],"CiStatusText|manual":["manuel"],"CiStatusText|passed":["passé"],"CiStatusText|pending":["en attente"],"CiStatusText|skipped":["ignoré"],"CiStatus|running":["en cours"],"Commit message":["Message de validation"],"CommitMessage|Add %{file_name}":["Ajout de %{file_name}"],"Commits":["Validations"],"Commits|History":["Historique"],"Committed by":["Validé par"],"Compare":["Comparer"],"Contribution guide":["Guilde de contribution"],"Contributors":["Contributeurs"],"Copy URL to clipboard":["Copier l'URL dans le presse-papier"],"Copy commit SHA to clipboard":["Copier le SAH de la validation"],"Create New Directory":["Créer un nouveau dossier"],"Create directory":["Créer un dossier"],"Create empty bare repository":["Créer un dépôt vide"],"Create merge request":["Créer une demande de fusion"],"Create new...":["Créer nouveau..."],"CreateNewFork|Fork":["Fork"],"CreateTag|Tag":["Étiquette"],"Cron Timezone":["Fuseau horaire de Cron"],"Cron syntax":["Syntaxe CRON"],"Custom":["Personnalisé"],"Custom notification events":["Événements de notification personnalisés"],"#~ \"Custom notification levels are the same as participating levels. With custom n\"#~ \"otification levels you will also receive notifications for select events. To f\"#~ \"ind out more, check out %{notification_link}.\"":["#~ \"Le niveau de notification Personnalisé est similaire au niveau Participation. \"#~ \"Il permet cependant également de recevoir des notifications pour des événement\"#~ \"s sélectionnés. Pour plus d’information, vous pouvez consulter %{notification_\"#~ \"link}.\""],"Cycle Analytics":["Analyseur de cycle"],"Define a custom pattern with cron syntax":["Définir un schéma personnalisé avec une syntaxe CRON"],"Delete":["Supprimer"],"Description":["Description"],"Directory name":["Nom du dossier"],"Don't show again":["Ne plus montrer"],"Download":["Télécharger"],"Download tar":["Télécharger tar"],"Download tar.bz2":["Télécharger tar.bz2"],"Download tar.gz":["Télécharger tar.gz"],"Download zip":["Télécharger zip"],"DownloadArtifacts|Download":["Télécharger"],"DownloadCommit|Email Patches":["Patch email"],"DownloadCommit|Plain Diff":["Diff simple"],"DownloadSource|Download":["Télécharger"],"Edit":["Éditer"],"Edit Pipeline Schedule %{id}":["Éditer le pipeline programmé %{id}"],"Every day (at 4:00am)":["Chaque jour (à 4:00 du matin)"],"Every month (on the 1st at 4:00am)":["Chaque mois (le 1er à 4:00 du matin)"],"Every week (Sundays at 4:00am)":["Chaque semaine (Dimanche à 4:00 du matin)"],"Failed to change the owner":["Échec du changement de propriétaire"],"Failed to remove the pipeline schedule":["Échec de la suppression du pipeline programmé"],"Files":["Fichiers"],"Find by path":["Rechercher par chemin"],"Find file":["Rechercher un fichier"],"Fork":["Fork","Forks"],"ForkedFromProjectPath|Forked from":["Forké depuis"],"Go to your fork":["Aller à votre fork"],"GoToYourFork|Fork":["Fork"],"Home":["Accueil"],"Housekeeping successfully started":["Maintenance démarrée avec succès"],"Import repository":["Importer un dépôt"],"Interval Pattern":["Schéma d’intervalle"],"LFSStatus|Disabled":["Désactivé"],"LFSStatus|Enabled":["Activé"],"Last Pipeline":["Dernier pipeline"],"Last Update":["Dernière mise à jour"],"Last commit":["Dernière validation"],"Learn more in the":["En apprendre plus dans le"],"Leave group":["Quitter le groupe"],"Leave project":["Quitter le projet"],"MissingSSHKeyWarningLink|add an SSH key":["ajouter un clef SSH"],"New Pipeline Schedule":["Nouveau pipeline programmé"],"New branch":["Nouvelle branche"],"New directory":["Nouveau dossier"],"New file":["Nouveau Fichier"],"New issue":["Nouvel incident"],"New merge request":["Nouvelle demande de fusion"],"New schedule":["Nouveau programme"],"New snippet":["Nouvel extrait de code"],"New tag":["Nouvelle étiquette"],"No repository":["Pas de dépôt"],"No schedules":["Aucun programme"],"Notification events":["Événement de notifications"],"NotificationEvent|Close issue":["Clore l'incident"],"NotificationEvent|Close merge request":["Clore la demande de fusion"],"NotificationEvent|Failed pipeline":["Pipeline échoué"],"NotificationEvent|Merge merge request":["Fusionner le demande de fusion"],"NotificationEvent|New issue":["Nouvel incident"],"NotificationEvent|New merge request":["Nouvelle demande de fusion"],"NotificationEvent|New note":["Nouvelle note"],"NotificationEvent|Reassign issue":["Réassigner l'incident"],"NotificationEvent|Reassign merge request":["Réassigner la demande de fusion"],"NotificationEvent|Reopen issue":["Ré-ouvrir l'incident"],"NotificationEvent|Successful pipeline":["Pipeline réussi"],"NotificationLevel|Custom":["Personnalisé"],"NotificationLevel|Disabled":["Désactivé"],"NotificationLevel|Global":["Global"],"NotificationLevel|On mention":["En cas de mention"],"NotificationLevel|Participate":["Participation"],"NotificationLevel|Watch":["Surveillé"],"OfSearchInADropdown|Filter":["Filtre"],"Options":["Options"],"Owner":["Propriétaire"],"Pipeline":["Pipeline"],"Pipeline Schedule":["Programmation de pipeline"],"Pipeline Schedules":["Programmations de pipeline"],"PipelineSchedules|Activated":["Activé"],"PipelineSchedules|Active":["Active"],"PipelineSchedules|All":["Tous"],"PipelineSchedules|Inactive":["Inactive"],"PipelineSchedules|Next Run":["Prochaine exécution"],"PipelineSchedules|None":["Aucune"],"PipelineSchedules|Provide a short description for this pipeline":["Indiquez une courte description"],"PipelineSchedules|Take ownership":["S’approprier"],"PipelineSchedules|Target":["Cible"],"Project '%{project_name}' queued for deletion.":["Projet '%{project_name}' en attente de suppression."],"Project '%{project_name}' was successfully created.":["Projet '%{project_name}' créé avec succès."],"Project '%{project_name}' was successfully updated.":["Projet '%{project_name}' mis à jour avec succès."],"Project '%{project_name}' will be deleted.":["Projet '%{project_name}' sera supprimé."],"Project access must be granted explicitly to each user.":["L’accès au projet doit être explicitement accordé à chaque utilisateur."],"Project export could not be deleted.":["L'export du projet n'a pas pu être supprimé."],"Project export has been deleted.":["L'export du projet a été supprimé."],"#~ \"Project export link has expired. Please generate a new export from your projec\"#~ \"t settings.\"":["#~ \"Le lien de l’export du projet a expiré. Merci de générer un nouvel export depu\"#~ \"is les paramètres du projet.\""],"Project export started. A download link will be sent by email.":["#~ \"L'export du projet a débuté. Un lien de téléchargement sera envoyé par courrie\"#~ \"l.\""],"Project home":["Accueil du projet"],"ProjectFeature|Disabled":["Désactivé"],"ProjectFeature|Everyone with access":["Toute personne ayant accès"],"ProjectFeature|Only team members":["Seulement les membres de l'équipe"],"ProjectFileTree|Name":["Nom"],"ProjectLastActivity|Never":["Jamais"],"ProjectNetworkGraph|Graph":["Graphique "],"Readme":["LisezMoi"],"RefSwitcher|Branches":["Branches"],"RefSwitcher|Tags":["Étiquettes"],"Remind later":["Me le rappeler ultérieurement"],"Remove project":["Supprimer le projet"],"Request Access":["Demander l'accès"],"Revert this commit":["Annuler cette validation"],"Revert this merge-request":["Annuler cette demande de fusion"],"Save pipeline schedule":["Sauvegarder le pipeline programmé"],"Schedule a new pipeline":["Programmer un nouveau pipeline"],"Scheduling Pipelines":["Programmer des pipelines"],"Search branches and tags":["Rechercher dans les branches et les étiquettes"],"Select Archive Format":["Sélectionnez le format de l'archive"],"Select a timezone":["Sélectionnez un fuseau horaire"],"Select target branch":["Sélectionnez une branche cible"],"Set a password on your account to pull or push via %{protocol}":["#~ \"Définissez un mot de passe pour votre compte pour pouvoir tirer ou pousser par\"#~ \" %{protocol}\""],"Set up CI":["Mettre en place le CI"],"Set up Koding":["Mettre en place Koding"],"Set up auto deploy":["Mettre en place l’auto-déploiement "],"SetPasswordToCloneLink|set a password":["définir un mot de passe"],"Source code":["Code source"],"StarProject|Star":["S'abonner"],"Start a <strong>new merge request</strong> with these changes":["Créer une <strong>nouvelle demande de fusion</strong> avec ces changements"],"Switch branch/tag":["Changer de branche / d'étiquette"],"Tag":["Étiquette","Étiquettes"],"Tags":["Étiquettes"],"Target Branch":["Branche cible"],"The fork relationship has been removed.":["La relation de fork a été supprimée."],"#~ \"The pipelines schedule runs pipelines in the future, repeatedly, for specific \"#~ \"branches or tags. Those scheduled pipelines will inherit limited project acces\"#~ \"s based on their associated user.\"":["#~ \"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érit\"#~ \"ent d’un accès partiel au projet basé sur l’utilisateur que leurs est associé.\""],"The project can be accessed by any logged in user.":["Votre projet peut être accédé par n’importe quel utilisateur authentifié"],"The project can be accessed without any authentication.":["Votre projet peut être accédé sans aucune authentification."],"The repository for this project does not exist.":["Le dépôt pour ce projet n'existe pas."],"#~ \"This means you can not push code until you create an empty repository or impor\"#~ \"t existing one.\"":["#~ \"Cela signifie que vous ne pouvez pas pousser du code tant que vous ne créez pa\"#~ \"s un dépôt vide, ou importez une dépôt existant.\""],"Timeago|%s days ago":["Il y a %s jours"],"Timeago|%s days remaining":["Il reste %s jours"],"Timeago|%s hours remaining":["Il reste %s heures"],"Timeago|%s minutes ago":["Il y a %s minutes"],"Timeago|%s minutes remaining":["Il reste %s minutes"],"Timeago|%s months ago":["Il y a %s mois"],"Timeago|%s months remaining":["Il reste %s mois"],"Timeago|%s seconds remaining":["Il reste %s secondes"],"Timeago|%s weeks ago":["Il y a %s semaines"],"Timeago|%s weeks remaining":["Il reste %s semaines"],"Timeago|%s years ago":["Il y a %s ans"],"Timeago|%s years remaining":["Il reste %s ans"],"Timeago|1 day remaining":["Il reste un jour"],"Timeago|1 hour remaining":["Il reste une heure"],"Timeago|1 minute remaining":["Il reste une minute"],"Timeago|1 month remaining":["Il reste un mois"],"Timeago|1 week remaining":["Il reste une semaine"],"Timeago|1 year remaining":["Il reste un an"],"Timeago|Past due":["En retard"],"Timeago|a day ago":["Il y a un jour"],"Timeago|a month ago":["Il y a un mois"],"Timeago|a week ago":["Il y a une semaine"],"Timeago|a while":["Il y a un moment"],"Timeago|a year ago":["Il y a un an"],"Timeago|about %s hours ago":["Il y a environ %s heures"],"Timeago|about a minute ago":["Il y a environ une minute"],"Timeago|about an hour ago":["Il y a environ une heure"],"Timeago|in %s days":["Dans %s jours"],"Timeago|in %s hours":["Dans %s heures"],"Timeago|in %s minutes":["Dans %s minutes"],"Timeago|in %s months":["Dans %s mois"],"Timeago|in %s seconds":["Dans %s secondes"],"Timeago|in %s weeks":["Dans %s semaines"],"Timeago|in %s years":["Dans %s années"],"Timeago|in 1 day":["Dans 1 jour"],"Timeago|in 1 hour":["Dans 1 heure"],"Timeago|in 1 minute":["Dans 1 minute"],"Timeago|in 1 month":["Dans 1 mois"],"Timeago|in 1 week":["Dans 1 semaine"],"Timeago|in 1 year":["Dans 1 an"],"Timeago|less than a minute ago":["il y a moins d'une minute"],"Unstar":["Se désabonner"],"Upload New File":["Téléverser un nouveau fichier"],"Upload file":["Téléverser un fichier"],"Use your global notification setting":["Utiliser vos paramètres de notification globaux"],"VisibilityLevel|Internal":["Interne"],"VisibilityLevel|Private":["Privé"],"VisibilityLevel|Public":["Publique"],"Withdraw Access Request":["Retirer la demande d'accès"],"#~ \"You are going to remove %{project_name_with_namespace}.\\n\"#~ \"Removed project CANNOT be restored!\\n\"#~ \"Are you ABSOLUTELY sure?\"":["#~ \"Vous êtes sur le point de supprimer %{project_name_with_namespace}.\\n\"#~ \"Les projets supprimés NE PEUVENT PAS être restaurés !\\n\"#~ \"Êtes vous ABSOLUMENT sûr ? \""],"#~ \"You are going to remove the fork relationship to source project %{forked_from_\"#~ \"project}. Are you ABSOLUTELY sure?\"":["#~ \"Vous allez supprimer la relation de fork avec le projet source %{forked_from_p\"#~ \"roject}. Êtes-vous VRAIMENT sûr.\""],"#~ \"You are going to transfer %{project_name_with_namespace} to another owner. Are\"#~ \" you ABSOLUTELY sure?\"":["#~ \"Vous allez transférer %{project_name_with_namespace} à un nouveau propriétaire\"#~ \". Êtes vous VRAIMENT sûr ?\""],"You can only add files when you are on a branch":["Vous ne pouvez ajouter de fichier que dans une branche"],"You must sign in to star a project":["Vous devez vous identifier pour vous abonner à un projet"],"You will not get any notifications via email":["Vous ne recevrez aucune notification par courriel"],"You will only receive notifications for the events you choose":["#~ \"Vous ne recevrez de notification que pour les évènements que vous aurez choisi\"#~ \"s\""],"You will only receive notifications for threads you have participated in":["#~ \"Vous ne recevrez de notification que pour les sujets auxquels vous avez partic\"#~ \"ipé\""],"You will receive notifications for any activity":["Vous recevrez des notifications pour n’importe quelles activités"],"You will receive notifications only for comments in which you were @mentioned":["#~ \"Vous ne recevrez de notifications que pour les commentaires où vous êtes @ment\"#~ \"ionné\""],"#~ \"You won't be able to pull or push project code via %{protocol} until you %{set\"#~ \"_password_link} on your account\"":["#~ \"Vous ne pourrez pas récupérer ou pousser de code par %{protocol} tant que vo\"#~ \"us n'aurez pas %{set_password_link} pour votre compte\""],"#~ \"You won't be able to pull or push project code via SSH until you %{add_ssh_key\"#~ \"_link} to your profile\"":["#~ \"Vous ne pourrez pas récupérer ou pousser de code par SSH tant que vous n’aur\"#~ \"ez pas %{add_ssh_key_link} dans votre profil\""],"Your name":["Votre nom"],"notification emails":["courriels de notification"],"parent":["parent","parents"],"pipeline schedules documentation":["documentation des pipeline programmés"],"with stage":["avec l'étape","avec les étapes"]}}}; \ No newline at end of file
diff --git a/app/assets/javascripts/locale/pt_BR/app.js b/app/assets/javascripts/locale/pt_BR/app.js
deleted file mode 100644
index f2eed3da064..00000000000
--- a/app/assets/javascripts/locale/pt_BR/app.js
+++ /dev/null
@@ -1 +0,0 @@
-var locales = locales || {}; locales['pt_BR'] = {"domain":"app","locale_data":{"app":{"":{"Project-Id-Version":"gitlab 1.0.0","Report-Msgid-Bugs-To":"","POT-Creation-Date":"2017-05-04 19:24-0500","MIME-Version":"1.0","Content-Type":"text/plain; charset=UTF-8","Content-Transfer-Encoding":"8bit","PO-Revision-Date":"2017-06-05 03:29-0400","Last-Translator":"Alexandre Alencar <alexandre.alencar@gmail.com>","Language-Team":"Portuguese (Brazil)","Language":"pt-BR","X-Generator":"Zanata 3.9.6","Plural-Forms":"nplurals=2; plural=(n != 1)","lang":"pt_BR","domain":"app","plural_forms":"nplurals=2; plural=(n != 1)"},"ByAuthor|by":["por"],"Commit":["Commit","Commits"],"Cycle Analytics gives an overview of how much time it takes to go from idea to production in your project.":["A Análise de Ciclo fornece uma visão geral de quanto tempo uma ideia demora para ir para produção em seu projeto."],"CycleAnalyticsStage|Code":["Código"],"CycleAnalyticsStage|Issue":["Tarefa"],"CycleAnalyticsStage|Plan":["Plano"],"CycleAnalyticsStage|Production":["Produção"],"CycleAnalyticsStage|Review":["Revisão"],"CycleAnalyticsStage|Staging":["Homologação"],"CycleAnalyticsStage|Test":["Teste"],"Deploy":["Implantação","Implantações"],"FirstPushedBy|First":["Primeiro"],"FirstPushedBy|pushed by":["publicado por"],"From issue creation until deploy to production":["Da criação de tarefas até a implantação para a produção"],"From merge request merge until deploy to production":["Da incorporação do merge request até a implantação em produção"],"Introducing Cycle Analytics":["Apresentando a Análise de Ciclo"],"Last %d day":["Último %d dia","Últimos %d dias"],"Limited to showing %d event at most":["Limitado a mostrar %d evento no máximo","Limitado a mostrar %d eventos no máximo"],"Median":["Mediana"],"New Issue":["Nova Tarefa","Novas Tarefas"],"Not available":["Não disponível"],"Not enough data":["Dados insuficientes"],"OpenedNDaysAgo|Opened":["Aberto"],"Pipeline Health":["Saúde da Pipeline"],"ProjectLifecycle|Stage":["Etapa"],"Read more":["Ler mais"],"Related Commits":["Commits Relacionados"],"Related Deployed Jobs":["Jobs Relacionados Incorporados"],"Related Issues":["Tarefas Relacionadas"],"Related Jobs":["Jobs Relacionados"],"Related Merge Requests":["Merge Requests Relacionados"],"Related Merged Requests":["Merge Requests Relacionados"],"Showing %d event":["Mostrando %d evento","Mostrando %d eventos"],"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.":["O estágio de codificação mostra o tempo desde o primeiro commit até a criação do merge request. \\nOs dados serão automaticamente adicionados aqui uma vez que você tenha criado seu primeiro merge request."],"The collection of events added to the data gathered for that stage.":["A coleção de eventos adicionados aos dados coletados para esse estágio."],"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.":["O estágio em questão mostra o tempo que leva desde a criação de uma tarefa até a sua assinatura para um milestone, ou a sua adição para a lista no seu Painel de Tarefas. Comece a criar tarefas para ver dados para esta etapa."],"The phase of the development lifecycle.":["A fase do ciclo de vida do desenvolvimento."],"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.":["A fase de planejamento mostra o tempo do passo anterior até empurrar o seu primeiro commit. Este tempo será adicionado automaticamente assim que você realizar seu primeiro commit."],"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.":["O estágio de produção mostra o tempo total que leva entre criar uma tarefa e implantar o código na produção. Os dados serão adicionados automaticamente até que você complete todo o ciclo de produção."],"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.":["A etapa de revisão mostra o tempo de criação de um merge request até que o merge seja feito. Os dados serão automaticamente adicionados depois que você fizer seu primeiro merge request."],"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.":["O estágio de estágio mostra o tempo entre a fusão do MR e o código de implantação para o ambiente de produção. Os dados serão automaticamente adicionados depois de implantar na produção pela primeira vez."],"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.":["A fase de teste mostra o tempo que o GitLab CI leva para executar cada pipeline para o merge request relacionado. Os dados serão automaticamente adicionados após a conclusão do primeiro pipeline."],"The time taken by each data entry gathered by that stage.":["O tempo necessário para cada entrada de dados reunida por essa etapa."],"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.":["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."],"Time before an issue gets scheduled":["Tempo até que uma tarefa seja planejada"],"Time before an issue starts implementation":["Tempo até que uma tarefa comece a ser implementada"],"Time between merge request creation and merge/close":["Tempo entre a criação do merge request e o merge/fechamento"],"Time until first merge request":["Tempo até o primeiro merge request"],"Time|hr":["h","hs"],"Time|min":["min","mins"],"Time|s":["s"],"Total Time":["Tempo Total"],"Total test time for all commits/merges":["Tempo de teste total para todos os commits/merges"],"Want to see the data? Please ask an administrator for access.":["Precisa visualizar os dados? Solicite acesso ao administrador."],"We don't have enough data to show this stage.":["Não temos dados suficientes para mostrar esta fase."],"You need permission.":["Você precisa de permissão."],"day":["dia","dias"]}}}; \ No newline at end of file
diff --git a/app/assets/javascripts/locale/zh_CN/app.js b/app/assets/javascripts/locale/zh_CN/app.js
deleted file mode 100644
index 9c28e4e4627..00000000000
--- a/app/assets/javascripts/locale/zh_CN/app.js
+++ /dev/null
@@ -1 +0,0 @@
-var locales = locales || {}; locales['zh_CN'] = {"domain":"app","locale_data":{"app":{"":{"Project-Id-Version":"gitlab 1.0.0","Report-Msgid-Bugs-To":"","POT-Creation-Date":"2017-06-15 21:59-0500","MIME-Version":"1.0","Content-Type":"text/plain; charset=UTF-8","Content-Transfer-Encoding":"8bit","PO-Revision-Date":"2017-06-19 09:57-0400","Last-Translator":"Huang Tao <htve@outlook.com>","Language-Team":"Chinese (China) (https://translate.zanata.org/project/view/GitLab)","Language":"zh-CN","X-Generator":"Zanata 3.9.6","Plural-Forms":"nplurals=1; plural=0","lang":"zh_CN","domain":"app","plural_forms":"nplurals=1; plural=0"},"%{commit_author_link} committed %{commit_timeago}":["由 %{commit_author_link} 提交于 %{commit_timeago}"],"About auto deploy":["关于自动部署"],"Active":["启用"],"Activity":["活动"],"Add Changelog":["添加更新日志"],"Add Contribution guide":["添加贡献指南"],"Add License":["添加许可证"],"Add an SSH key to your profile to pull or push via SSH.":["新建一个用于推送或拉取的 SSH 秘钥到账号中。"],"Add new directory":["添加目录"],"Archived project! Repository is read-only":["项目已归档!存储库为只读状态"],"Are you sure you want to delete this pipeline schedule?":["确定要删除此流水线计划吗?"],"Attach a file by drag &amp; drop or %{upload_link}":["拖放文件到此处或者 %{upload_link}"],"Branch":["分支"],"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}":["已创建分支 <strong>%{branch_name}</strong> 。如需设置自动部署, 请选择合适的 GitLab CI Yaml 模板并提交更改。%{link_to_autodeploy_doc}"],"Branches":["分支"],"Browse files":["浏览文件"],"ByAuthor|by":["作者:"],"CI configuration":["CI 配置"],"Cancel":["取消"],"ChangeTypeActionLabel|Pick into branch":["选择分支"],"ChangeTypeActionLabel|Revert in branch":["还原分支"],"ChangeTypeAction|Cherry-pick":["优选"],"ChangeTypeAction|Revert":["还原"],"Changelog":["更新日志"],"Charts":["统计图"],"Cherry-pick this commit":["优选此提交"],"Cherry-pick this merge request":["优选此合并请求"],"CiStatusLabel|canceled":["已取消"],"CiStatusLabel|created":["已创建"],"CiStatusLabel|failed":["已失败"],"CiStatusLabel|manual action":["手动操作"],"CiStatusLabel|passed":["已通过"],"CiStatusLabel|passed with warnings":["已通过但有警告"],"CiStatusLabel|pending":["等待中"],"CiStatusLabel|skipped":["已跳过"],"CiStatusLabel|waiting for manual action":["等待手动操作"],"CiStatusText|blocked":["已阻塞"],"CiStatusText|canceled":["已取消"],"CiStatusText|created":["已创建"],"CiStatusText|failed":["已失败"],"CiStatusText|manual":["手动操作"],"CiStatusText|passed":["已通过"],"CiStatusText|pending":["等待中"],"CiStatusText|skipped":["已跳过"],"CiStatus|running":["运行中"],"Commit":["提交"],"Commit message":["提交信息"],"CommitBoxTitle|Commit":["提交"],"CommitMessage|Add %{file_name}":["添加 %{file_name}"],"Commits":["提交"],"Commits|History":["历史"],"Committed by":["提交者:"],"Compare":["比较"],"Contribution guide":["贡献指南"],"Contributors":["贡献者"],"Copy URL to clipboard":["复制 URL 到剪贴板"],"Copy commit SHA to clipboard":["复制提交 SHA 的值到剪贴板"],"Create New Directory":["创建新目录"],"Create directory":["创建目录"],"Create empty bare repository":["创建空的存储库"],"Create merge request":["创建合并请求"],"Create new...":["创建..."],"CreateNewFork|Fork":["派生"],"CreateTag|Tag":["标签"],"Cron Timezone":["Cron 时区"],"Cron syntax":["Cron 语法"],"Custom notification events":["自定义通知事件"],"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}.":["自定义通知级别继承自参与级别。使用自定义通知级别,您会收到参与级别及选定事件的通知。想了解更多信息,请查看 %{notification_link}."],"Cycle Analytics":["周期分析"],"Cycle Analytics gives an overview of how much time it takes to go from idea to production in your project.":["周期分析概述了项目从想法到产品实现的各阶段所需的时间。"],"CycleAnalyticsStage|Code":["编码"],"CycleAnalyticsStage|Issue":["议题"],"CycleAnalyticsStage|Plan":["计划"],"CycleAnalyticsStage|Production":["生产"],"CycleAnalyticsStage|Review":["评审"],"CycleAnalyticsStage|Staging":["预发布"],"CycleAnalyticsStage|Test":["测试"],"Define a custom pattern with cron syntax":["使用 Cron 语法定义自定义模式"],"Delete":["删除"],"Deploy":["部署"],"Description":["描述"],"Directory name":["目录名称"],"Don't show again":["不再显示"],"Download":["下载"],"Download tar":["下载 tar"],"Download tar.bz2":["下载 tar.bz2"],"Download tar.gz":["下载 tar.gz"],"Download zip":["下载 zip"],"DownloadArtifacts|Download":["下载"],"DownloadCommit|Email Patches":["电子邮件补丁"],"DownloadCommit|Plain Diff":["差异文件"],"DownloadSource|Download":["下载"],"Edit":["编辑"],"Edit Pipeline Schedule %{id}":["编辑 %{id} 流水线计划"],"Every day (at 4:00am)":["每日执行(凌晨 4 点)"],"Every month (on the 1st at 4:00am)":["每月执行(每月 1 日凌晨 4 点)"],"Every week (Sundays at 4:00am)":["每周执行(周日凌晨 4 点)"],"Failed to change the owner":["无法变更所有者"],"Failed to remove the pipeline schedule":["无法删除流水线计划"],"Files":["文件"],"Find by path":["按路径查找"],"Find file":["查找文件"],"FirstPushedBy|First":["首次推送"],"FirstPushedBy|pushed by":["推送者:"],"Fork":["派生"],"ForkedFromProjectPath|Forked from":["派生自"],"From issue creation until deploy to production":["从创建议题到部署至生产环境"],"From merge request merge until deploy to production":["从合并请求被合并后到部署至生产环境"],"Go to your fork":["跳转到派生项目"],"GoToYourFork|Fork":["跳转到派生项目"],"Home":["首页"],"Housekeeping successfully started":["已开始维护"],"Import repository":["导入存储库"],"Interval Pattern":["循环周期"],"Introducing Cycle Analytics":["周期分析简介"],"LFSStatus|Disabled":["停用"],"LFSStatus|Enabled":["启用"],"Last %d day":["最近 %d 天"],"Last Pipeline":["最新流水线"],"Last Update":["最后更新"],"Last commit":["最后提交"],"Learn more in the":["了解更多"],"Learn more in the|pipeline schedules documentation":["流水线计划文档"],"Leave group":["退出群组"],"Leave project":["退出项目"],"Limited to showing %d event at most":["最多显示 %d 个事件"],"Median":["中位数"],"MissingSSHKeyWarningLink|add an SSH key":["新建 SSH 公钥"],"New Issue":["新建议题"],"New Pipeline Schedule":["创建流水线计划"],"New branch":["新建分支"],"New directory":["新建目录"],"New file":["新建文件"],"New issue":["新建议题"],"New merge request":["新建合并请求"],"New schedule":["新建计划"],"New snippet":["新建代码片段"],"New tag":["新建标签"],"No repository":["没有存储库"],"No schedules":["没有计划"],"Not available":["数据不足"],"Not enough data":["数据不足"],"Notification events":["通知事件"],"NotificationEvent|Close issue":["关闭议题"],"NotificationEvent|Close merge request":["关闭合并请求"],"NotificationEvent|Failed pipeline":["流水线失败"],"NotificationEvent|Merge merge request":["合并请求被合并"],"NotificationEvent|New issue":["新建议题"],"NotificationEvent|New merge request":["新建合并请求"],"NotificationEvent|New note":["新建评论"],"NotificationEvent|Reassign issue":["重新指派议题"],"NotificationEvent|Reassign merge request":["重新指派合并请求"],"NotificationEvent|Reopen issue":["重启议题"],"NotificationEvent|Successful pipeline":["流水线成功完成"],"NotificationLevel|Custom":["自定义"],"NotificationLevel|Disabled":["停用"],"NotificationLevel|Global":["全局"],"NotificationLevel|On mention":["提及"],"NotificationLevel|Participate":["参与"],"NotificationLevel|Watch":["关注"],"OfSearchInADropdown|Filter":["筛选"],"OpenedNDaysAgo|Opened":["开始于"],"Options":["操作"],"Owner":["所有者"],"Pipeline":["流水线"],"Pipeline Health":["流水线健康指标"],"Pipeline Schedule":["流水线计划"],"Pipeline Schedules":["流水线计划"],"PipelineSchedules|Activated":["是否启用"],"PipelineSchedules|Active":["已启用"],"PipelineSchedules|All":["所有"],"PipelineSchedules|Inactive":["未启用"],"PipelineSchedules|Next Run":["下次运行时间"],"PipelineSchedules|None":["无"],"PipelineSchedules|Provide a short description for this pipeline":["为此流水线提供简短描述"],"PipelineSchedules|Take ownership":["取得所有者"],"PipelineSchedules|Target":["目标"],"PipelineSheduleIntervalPattern|Custom":["自定义"],"Pipeline|with stage":["于阶段"],"Pipeline|with stages":["于阶段"],"Project '%{project_name}' queued for deletion.":["项目 '%{project_name}' 已进入删除队列。"],"Project '%{project_name}' was successfully created.":["项目 '%{project_name}' 已创建成功。"],"Project '%{project_name}' was successfully updated.":["项目 '%{project_name}' 已更新完成。"],"Project '%{project_name}' will be deleted.":["项目 '%{project_name}' 将被删除。"],"Project access must be granted explicitly to each user.":["项目访问权限必须明确授权给每个用户。"],"Project export could not be deleted.":["无法删除项目导出。"],"Project export has been deleted.":["项目导出已被删除。"],"Project export link has expired. Please generate a new export from your project settings.":["项目导出链接已过期。请从项目设置中重新生成项目导出。"],"Project export started. A download link will be sent by email.":["项目导出已开始。下载链接将通过电子邮件发送。"],"Project home":["项目首页"],"ProjectFeature|Disabled":["停用"],"ProjectFeature|Everyone with access":["任何对项目有访问权的人"],"ProjectFeature|Only team members":["只限团队成员"],"ProjectFileTree|Name":["名称"],"ProjectLastActivity|Never":["从未"],"ProjectLifecycle|Stage":["阶段"],"ProjectNetworkGraph|Graph":["分支图"],"Read more":["了解更多"],"Readme":["自述文件"],"RefSwitcher|Branches":["分支"],"RefSwitcher|Tags":["标签"],"Related Commits":["相关的提交"],"Related Deployed Jobs":["相关的部署作业"],"Related Issues":["相关的议题"],"Related Jobs":["相关的作业"],"Related Merge Requests":["相关的合并请求"],"Related Merged Requests":["相关已合并的合并请求"],"Remind later":["稍后提醒"],"Remove project":["删除项目"],"Request Access":["申请权限"],"Revert this commit":["还原此提交"],"Revert this merge request":["还原此合并请求"],"Save pipeline schedule":["保存流水线计划"],"Schedule a new pipeline":["新建流水线计划"],"Scheduling Pipelines":["流水线计划"],"Search branches and tags":["搜索分支和标签"],"Select Archive Format":["选择下载格式"],"Select a timezone":["选择时区"],"Select target branch":["选择目标分支"],"Set a password on your account to pull or push via %{protocol}":["为账号创建一个用于推送或拉取的 %{protocol} 密码。"],"Set up CI":["设置 CI"],"Set up Koding":["设置 Koding"],"Set up auto deploy":["设置自动部署"],"SetPasswordToCloneLink|set a password":["设置密码"],"Showing %d event":["显示 %d 个事件"],"Source code":["源代码"],"StarProject|Star":["星标"],"Start a %{new_merge_request} with these changes":["由此更改 %{new_merge_request}"],"Switch branch/tag":["切换分支/标签"],"Tag":["标签"],"Tags":["标签"],"Target Branch":["目标分支"],"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.":["编码阶段概述了从第一次提交到创建合并请求的时间。创建第一个合并请求后,数据将自动添加到此处。"],"The collection of events added to the data gathered for that stage.":["与该阶段相关的事件集合。"],"The fork relationship has been removed.":["派生关系已被删除。"],"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.":["议题阶段概述了从创建议题到将议题添加到里程碑或议题看板所花费的时间。创建第一个议题后,数据将自动添加到此处.。"],"The phase of the development lifecycle.":["项目生命周期中的各个阶段。"],"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.":["流水线计划会周期性重复运行指定分支或标签的流水线。这些流水线将根据其关联用户继承有限的项目访问权限。"],"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.":["计划阶段概述了从议题添加到日程到推送首次提交的时间。当首次推送提交后,数据将自动添加到此处。"],"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.":["生产阶段概述了从创建一个议题到将代码部署到生产环境的总时间。当完成想法到部署生产的循环,数据将自动添加到此处。"],"The project can be accessed by any logged in user.":["该项目允许已登录的用户访问。"],"The project can be accessed without any authentication.":["该项目允许任何人访问。"],"The repository for this project does not exist.":["此项目的存储库不存在。"],"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.":["评审阶段概述了从创建合并请求到被合并的时间。当创建第一个合并请求后,数据将自动添加到此处。"],"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.":["预发布阶段概述了从合并请求被合并到部署至生产环境的总时间。首次部署到生产环境后,数据将自动添加到此处。"],"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.":["测试阶段概述了 GitLab CI 为相关合并请求运行每个流水线所需的时间。当第一个流水线运行完成后,数据将自动添加到此处。"],"The time taken by each data entry gathered by that stage.":["该阶段每条数据所花的时间"],"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.":["中位数是一个数列中最中间的值。例如在 3、5、9 之间,中位数是 5。在 3、5、7、8 之间,中位数是 (5 + 7)/ 2 = 6。"],"This means you can not push code until you create an empty repository or import existing one.":["在创建一个空的存储库或导入现有存储库之前,将无法推送代码。"],"Time before an issue gets scheduled":["议题被列入日程表的时间"],"Time before an issue starts implementation":["开始进行编码前的时间"],"Time between merge request creation and merge/close":["从创建合并请求到被合并或关闭的时间"],"Time until first merge request":["创建第一个合并请求之前的时间"],"Timeago|%s days ago":[" %s 天前"],"Timeago|%s days remaining":["剩余 %s 天"],"Timeago|%s hours remaining":["剩余 %s 小时"],"Timeago|%s minutes ago":[" %s 分钟前"],"Timeago|%s minutes remaining":["剩余 %s 分钟"],"Timeago|%s months ago":[" %s 个月前"],"Timeago|%s months remaining":["剩余 %s 月"],"Timeago|%s seconds remaining":["剩余 %s 秒"],"Timeago|%s weeks ago":[" %s 星期前"],"Timeago|%s weeks remaining":["剩余 %s 星期"],"Timeago|%s years ago":[" %s 年前"],"Timeago|%s years remaining":["剩余 %s 年"],"Timeago|1 day remaining":["剩余 1 天"],"Timeago|1 hour remaining":["剩余 1 小时"],"Timeago|1 minute remaining":["剩余 1 分钟"],"Timeago|1 month remaining":["剩余 1 个月"],"Timeago|1 week remaining":["剩余 1 星期"],"Timeago|1 year remaining":["剩余 1 年"],"Timeago|Past due":["逾期"],"Timeago|a day ago":[" 1 天前"],"Timeago|a month ago":[" 1 个月前"],"Timeago|a week ago":[" 1 星期前"],"Timeago|a while":["刚刚"],"Timeago|a year ago":[" 1 年前"],"Timeago|about %s hours ago":["约 %s 小时前"],"Timeago|about a minute ago":["约 1 分钟前"],"Timeago|about an hour ago":["约 1 小时前"],"Timeago|in %s days":[" %s 天后"],"Timeago|in %s hours":[" %s 小时后"],"Timeago|in %s minutes":[" %s 分钟后"],"Timeago|in %s months":[" %s 个月后"],"Timeago|in %s seconds":[" %s 秒后"],"Timeago|in %s weeks":[" %s 星期后"],"Timeago|in %s years":[" %s 年后"],"Timeago|in 1 day":[" 1 天后"],"Timeago|in 1 hour":[" 1 小时后"],"Timeago|in 1 minute":[" 1 分钟后"],"Timeago|in 1 month":[" 1 月后"],"Timeago|in 1 week":[" 1 星期后"],"Timeago|in 1 year":[" 1 年后"],"Timeago|less than a minute ago":["不到 1 分钟前"],"Time|hr":["小时"],"Time|min":["分钟"],"Time|s":["秒"],"Total Time":["总时间"],"Total test time for all commits/merges":["所有提交和合并的总测试时间"],"Unstar":["取消星标"],"Upload New File":["上传新文件"],"Upload file":["上传文件"],"Use your global notification setting":["使用全局通知设置"],"VisibilityLevel|Internal":["内部"],"VisibilityLevel|Private":["私有"],"VisibilityLevel|Public":["公开"],"Want to see the data? Please ask an administrator for access.":["权限不足。如需查看相关数据,请向管理员申请权限。"],"We don't have enough data to show this stage.":["该阶段的数据不足,无法显示。"],"Withdraw Access Request":["取消权限申请"],"You are going to remove %{project_name_with_namespace}.\\nRemoved project CANNOT be restored!\\nAre you ABSOLUTELY sure?":["即将要删除 %{project_name_with_namespace}。\\n已删除的项目无法恢复!\\n确定继续吗?"],"You are going to remove the fork relationship to source project %{forked_from_project}. Are you ABSOLUTELY sure?":["即将删除与源项目 %{forked_from_project} 的派生关系。确定继续吗?"],"You are going to transfer %{project_name_with_namespace} to another owner. Are you ABSOLUTELY sure?":["即将 %{project_name_with_namespace} 转移给另一个所有者。确定继续吗?"],"You can only add files when you are on a branch":["只能在分支上添加文件"],"You have reached your project limit":["您已达到项目数量限制"],"You must sign in to star a project":["必须登录才能对项目加星标"],"You need permission.":["需要相关的权限。"],"You will not get any notifications via email":["不会收到任何通知邮件"],"You will only receive notifications for the events you choose":["只接收选择的事件通知"],"You will only receive notifications for threads you have participated in":["只接收参与的主题的通知"],"You will receive notifications for any activity":["接收所有活动的通知"],"You will receive notifications only for comments in which you were @mentioned":["只接收评论中提及(@)您的通知"],"You won't be able to pull or push project code via %{protocol} until you %{set_password_link} on your account":["在账号中 %{set_password_link} 之前将无法通过 %{protocol} 拉取或推送代码。"],"You won't be able to pull or push project code via SSH until you %{add_ssh_key_link} to your profile":["在账号中 %{add_ssh_key_link} 之前将无法通过 SSH 拉取或推送代码。"],"Your name":["您的名字"],"day":["天"],"new merge request":["新建合并请求"],"notification emails":["通知邮件"],"parent":["父级"]}}}; \ No newline at end of file
diff --git a/app/assets/javascripts/locale/zh_HK/app.js b/app/assets/javascripts/locale/zh_HK/app.js
deleted file mode 100644
index 30cb1e6b89e..00000000000
--- a/app/assets/javascripts/locale/zh_HK/app.js
+++ /dev/null
@@ -1 +0,0 @@
-var locales = locales || {}; locales['zh_HK'] = {"domain":"app","locale_data":{"app":{"":{"Project-Id-Version":"gitlab 1.0.0","Report-Msgid-Bugs-To":"","PO-Revision-Date":"2017-05-04 19:24-0500","Last-Translator":"HuangTao <htve@outlook.com>, 2017","Language-Team":"Chinese (Hong Kong) (https://www.transifex.com/gitlab-zh/teams/75177/zh_HK/)","MIME-Version":"1.0","Content-Type":"text/plain; charset=UTF-8","Content-Transfer-Encoding":"8bit","Language":"zh_HK","Plural-Forms":"nplurals=1; plural=0;","lang":"zh_HK","domain":"app","plural_forms":"nplurals=1; plural=0;"},"Are you sure you want to delete this pipeline schedule?":[""],"ByAuthor|by":["作者:"],"Cancel":[""],"Commit":["提交"],"Cron Timezone":[""],"Cycle Analytics gives an overview of how much time it takes to go from idea to production in your project.":["週期分析概述了項目從想法到產品實現的各階段所需的時間。"],"CycleAnalyticsStage|Code":["編碼"],"CycleAnalyticsStage|Issue":["議題"],"CycleAnalyticsStage|Plan":["計劃"],"CycleAnalyticsStage|Production":["生產"],"CycleAnalyticsStage|Review":["評審"],"CycleAnalyticsStage|Staging":["預發布"],"CycleAnalyticsStage|Test":["測試"],"Delete":[""],"Deploy":["部署"],"Description":[""],"Edit":[""],"Edit Pipeline Schedule %{id}":[""],"Failed to change the owner":[""],"Failed to remove the pipeline schedule":[""],"Filter":[""],"FirstPushedBy|First":["首次推送"],"FirstPushedBy|pushed by":["推送者:"],"From issue creation until deploy to production":["從創建議題到部署到生產環境"],"From merge request merge until deploy to production":["從合併請求的合併到部署至生產環境"],"Interval Pattern":[""],"Introducing Cycle Analytics":["週期分析簡介"],"Last %d day":["最後 %d 天"],"Last Pipeline":[""],"Limited to showing %d event at most":["最多顯示 %d 個事件"],"Median":["中位數"],"New Issue":["新議題"],"New Pipeline Schedule":[""],"No schedules":[""],"Not available":["不可用"],"Not enough data":["數據不足"],"OpenedNDaysAgo|Opened":["開始於"],"Owner":[""],"Pipeline Health":["流水線健康指標"],"Pipeline Schedule":[""],"Pipeline Schedules":[""],"PipelineSchedules|Activated":[""],"PipelineSchedules|Active":[""],"PipelineSchedules|All":[""],"PipelineSchedules|Inactive":[""],"PipelineSchedules|Next Run":[""],"PipelineSchedules|None":[""],"PipelineSchedules|Provide a short description for this pipeline":[""],"PipelineSchedules|Take ownership":[""],"PipelineSchedules|Target":[""],"ProjectLifecycle|Stage":["項目生命週期"],"Read more":["了解更多"],"Related Commits":["相關的提交"],"Related Deployed Jobs":["相關的部署作業"],"Related Issues":["相關的議題"],"Related Jobs":["相關的作業"],"Related Merge Requests":["相關的合併請求"],"Related Merged Requests":["相關已合併的合並請求"],"Save pipeline schedule":[""],"Schedule a new pipeline":[""],"Select a timezone":[""],"Select target branch":[""],"Showing %d event":["顯示 %d 個事件"],"Target Branch":[""],"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.":["編碼階段概述了從第一次提交到創建合併請求的時間。創建第壹個合並請求後,數據將自動添加到此處。"],"The collection of events added to the data gathered for that stage.":["與該階段相關的事件。"],"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.":["議題階段概述了從創建議題到將議題設置裏程碑或將議題添加到議題看板的時間。創建一個議題後,數據將自動添加到此處。"],"The phase of the development lifecycle.":["項目生命週期中的各個階段。"],"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.":["計劃階段概述了從議題添加到日程後到推送首次提交的時間。當首次推送提交後,數據將自動添加到此處。"],"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.":["生產階段概述了從創建議題到將代碼部署到生產環境的時間。當完成完整的想法到部署生產,數據將自動添加到此處。"],"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.":["評審階段概述了從創建合並請求到合併的時間。當創建第壹個合並請求後,數據將自動添加到此處。"],"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.":["預發布階段概述了合並請求的合併到部署代碼到生產環境的總時間。當首次部署到生產環境後,數據將自動添加到此處。"],"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.":["測試階段概述了GitLab CI為相關合併請求運行每個流水線所需的時間。當第壹個流水線運行完成後,數據將自動添加到此處。"],"The time taken by each data entry gathered by that stage.":["該階段每條數據所花的時間"],"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.":["中位數是一個數列中最中間的值。例如在 3、5、9 之間,中位數是 5。在 3、5、7、8 之間,中位數是 (5 + 7)/ 2 = 6。"],"Time before an issue gets scheduled":["議題被列入日程表的時間"],"Time before an issue starts implementation":["開始進行編碼前的時間"],"Time between merge request creation and merge/close":["從創建合併請求到被合並或關閉的時間"],"Time until first merge request":["創建第壹個合併請求之前的時間"],"Time|hr":["小時"],"Time|min":["分鐘"],"Time|s":["秒"],"Total Time":["總時間"],"Total test time for all commits/merges":["所有提交和合併的總測試時間"],"Want to see the data? Please ask an administrator for access.":["權限不足。如需查看相關數據,請向管理員申請權限。"],"We don't have enough data to show this stage.":["該階段的數據不足,無法顯示。"],"You need permission.":["您需要相關的權限。"],"day":["天"]}}}; \ No newline at end of file
diff --git a/app/assets/javascripts/locale/zh_TW/app.js b/app/assets/javascripts/locale/zh_TW/app.js
deleted file mode 100644
index f0fe1e31f18..00000000000
--- a/app/assets/javascripts/locale/zh_TW/app.js
+++ /dev/null
@@ -1 +0,0 @@
-var locales = locales || {}; locales['zh_TW'] = {"domain":"app","locale_data":{"app":{"":{"Project-Id-Version":"gitlab 1.0.0","Report-Msgid-Bugs-To":"","PO-Revision-Date":"2017-05-04 19:24-0500","Last-Translator":"HuangTao <htve@outlook.com>, 2017","Language-Team":"Chinese (Taiwan) (https://www.transifex.com/gitlab-zh/teams/75177/zh_TW/)","MIME-Version":"1.0","Content-Type":"text/plain; charset=UTF-8","Content-Transfer-Encoding":"8bit","Language":"zh_TW","Plural-Forms":"nplurals=1; plural=0;","lang":"zh_TW","domain":"app","plural_forms":"nplurals=1; plural=0;"},"Are you sure you want to delete this pipeline schedule?":[""],"ByAuthor|by":["作者:"],"Cancel":[""],"Commit":["送交"],"Cron Timezone":[""],"Cycle Analytics gives an overview of how much time it takes to go from idea to production in your project.":["週期分析概述了你的專案從想法到產品實現,各階段所需的時間。"],"CycleAnalyticsStage|Code":["程式開發"],"CycleAnalyticsStage|Issue":["議題"],"CycleAnalyticsStage|Plan":["計劃"],"CycleAnalyticsStage|Production":["上線"],"CycleAnalyticsStage|Review":["複閱"],"CycleAnalyticsStage|Staging":["預備"],"CycleAnalyticsStage|Test":["測試"],"Delete":[""],"Deploy":["部署"],"Description":[""],"Edit":[""],"Edit Pipeline Schedule %{id}":[""],"Failed to change the owner":[""],"Failed to remove the pipeline schedule":[""],"Filter":[""],"FirstPushedBy|First":["首次推送"],"FirstPushedBy|pushed by":["推送者:"],"From issue creation until deploy to production":["從議題建立至線上部署"],"From merge request merge until deploy to production":["從請求被合併後至線上部署"],"Interval Pattern":[""],"Introducing Cycle Analytics":["週期分析簡介"],"Last %d day":["最後 %d 天"],"Last Pipeline":[""],"Limited to showing %d event at most":["最多顯示 %d 個事件"],"Median":["中位數"],"New Issue":["新議題"],"New Pipeline Schedule":[""],"No schedules":[""],"Not available":["無法使用"],"Not enough data":["資料不足"],"OpenedNDaysAgo|Opened":["開始於"],"Owner":[""],"Pipeline Health":["流水線健康指標"],"Pipeline Schedule":[""],"Pipeline Schedules":[""],"PipelineSchedules|Activated":[""],"PipelineSchedules|Active":[""],"PipelineSchedules|All":[""],"PipelineSchedules|Inactive":[""],"PipelineSchedules|Next Run":[""],"PipelineSchedules|None":[""],"PipelineSchedules|Provide a short description for this pipeline":[""],"PipelineSchedules|Take ownership":[""],"PipelineSchedules|Target":[""],"ProjectLifecycle|Stage":["專案生命週期"],"Read more":["了解更多"],"Related Commits":["相關的送交"],"Related Deployed Jobs":["相關的部署作業"],"Related Issues":["相關的議題"],"Related Jobs":["相關的作業"],"Related Merge Requests":["相關的合併請求"],"Related Merged Requests":["相關已合併的請求"],"Save pipeline schedule":[""],"Schedule a new pipeline":[""],"Select a timezone":[""],"Select target branch":[""],"Showing %d event":["顯示 %d 個事件"],"Target Branch":[""],"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.":["程式開發階段顯示從第一次送交到建立合併請求的時間。建立第一個合併請求後,資料將自動填入。"],"The collection of events added to the data gathered for that stage.":["與該階段相關的事件。"],"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.":["議題階段顯示從議題建立到設置里程碑、或將該議題加至議題看板的時間。建立第一個議題後,資料將自動填入。"],"The phase of the development lifecycle.":["專案開發生命週期的各個階段。"],"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.":["計劃階段顯示從議題添加到日程後至推送第一個送交的時間。當第一次推送送交後,資料將自動填入。"],"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.":["上線階段顯示從建立一個議題到部署程式至線上的總時間。當完成從想法到產品實現的循環後,資料將自動填入。"],"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.":["複閱階段顯示從合併請求建立後至被合併的時間。當建立第一個合併請求後,資料將自動填入。"],"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.":["預備階段顯示從合併請求被合併後至部署上線的時間。當第一次部署上線後,資料將自動填入。"],"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.":["測試階段顯示相關合併請求的流水線所花的時間。當第一個流水線運作完畢後,資料將自動填入。"],"The time taken by each data entry gathered by that stage.":["每筆該階段相關資料所花的時間。"],"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.":["中位數是一個數列中最中間的值。例如在 3、5、9 之間,中位數是 5。在 3、5、7、8 之間,中位數是 (5 + 7)/ 2 = 6。"],"Time before an issue gets scheduled":["議題被列入日程表的時間"],"Time before an issue starts implementation":["議題等待開始實作的時間"],"Time between merge request creation and merge/close":["合併請求被合併或是關閉的時間"],"Time until first merge request":["第一個合併請求被建立前的時間"],"Time|hr":["小時"],"Time|min":["分鐘"],"Time|s":["秒"],"Total Time":["總時間"],"Total test time for all commits/merges":["所有送交和合併的總測試時間"],"Want to see the data? Please ask an administrator for access.":["權限不足。如需查看相關資料,請向管理員申請權限。"],"We don't have enough data to show this stage.":["因該階段的資料不足而無法顯示相關資訊"],"You need permission.":["您需要相關的權限。"],"day":["天"]}}}; \ No newline at end of file
diff --git a/app/assets/javascripts/main.js b/app/assets/javascripts/main.js
index ed7629948ca..d27b4ec78c6 100644
--- a/app/assets/javascripts/main.js
+++ b/app/assets/javascripts/main.js
@@ -299,9 +299,10 @@ $(function () {
// Commit show suppressed diff
});
$('.navbar-toggle').on('click', function () {
- $('.header-content .title').toggle();
+ $('.header-content .title, .header-content .navbar-sub-nav').toggle();
$('.header-content .header-logo').toggle();
$('.header-content .navbar-collapse').toggle();
+ $('.js-navbar-toggle-left, .js-navbar-toggle-right, .title-container').toggle();
return $('.navbar-toggle').toggleClass('active');
});
// Show/hide comments on diff
diff --git a/app/assets/javascripts/pipeline_schedules/components/interval_pattern_input.js b/app/assets/javascripts/pipeline_schedules/components/interval_pattern_input.js
deleted file mode 100644
index 901adbe9fce..00000000000
--- a/app/assets/javascripts/pipeline_schedules/components/interval_pattern_input.js
+++ /dev/null
@@ -1,148 +0,0 @@
-import Vue from 'vue';
-import Translate from '../../vue_shared/translate';
-
-Vue.use(Translate);
-
-const inputNameAttribute = 'schedule[cron]';
-
-export default {
- props: {
- initialCronInterval: {
- type: String,
- required: false,
- default: '',
- },
- },
- data() {
- return {
- inputNameAttribute,
- cronInterval: this.initialCronInterval,
- cronIntervalPresets: {
- everyDay: '0 4 * * *',
- everyWeek: '0 4 * * 0',
- everyMonth: '0 4 1 * *',
- },
- cronSyntaxUrl: 'https://en.wikipedia.org/wiki/Cron',
- customInputEnabled: false,
- };
- },
- computed: {
- intervalIsPreset() {
- return _.contains(this.cronIntervalPresets, this.cronInterval);
- },
- // The text input is editable when there's a custom interval, or when it's
- // a preset interval and the user clicks the 'custom' radio button
- isEditable() {
- return !!(this.customInputEnabled || !this.intervalIsPreset);
- },
- },
- methods: {
- toggleCustomInput(shouldEnable) {
- this.customInputEnabled = shouldEnable;
-
- if (shouldEnable) {
- // We need to change the value so other radios don't remain selected
- // because the model (cronInterval) hasn't changed. The server trims it.
- this.cronInterval = `${this.cronInterval} `;
- }
- },
- },
- created() {
- if (this.intervalIsPreset) {
- this.enableCustomInput = false;
- }
- },
- watch: {
- cronInterval() {
- // updates field validation state when model changes, as
- // glFieldError only updates on input.
- Vue.nextTick(() => {
- gl.pipelineScheduleFieldErrors.updateFormValidityState();
- });
- },
- },
- template: `
- <div class="interval-pattern-form-group">
- <div class="cron-preset-radio-input">
- <input
- id="custom"
- class="label-light"
- type="radio"
- :name="inputNameAttribute"
- :value="cronInterval"
- :checked="isEditable"
- @click="toggleCustomInput(true)"
- />
-
- <label for="custom">
- {{ s__('PipelineSheduleIntervalPattern|Custom') }}
- </label>
-
- <span class="cron-syntax-link-wrap">
- (<a :href="cronSyntaxUrl" target="_blank">{{ __('Cron syntax') }}</a>)
- </span>
- </div>
-
- <div class="cron-preset-radio-input">
- <input
- id="every-day"
- class="label-light"
- type="radio"
- v-model="cronInterval"
- :name="inputNameAttribute"
- :value="cronIntervalPresets.everyDay"
- @click="toggleCustomInput(false)"
- />
-
- <label class="label-light" for="every-day">
- {{ __('Every day (at 4:00am)') }}
- </label>
- </div>
-
- <div class="cron-preset-radio-input">
- <input
- id="every-week"
- class="label-light"
- type="radio"
- v-model="cronInterval"
- :name="inputNameAttribute"
- :value="cronIntervalPresets.everyWeek"
- @click="toggleCustomInput(false)"
- />
-
- <label class="label-light" for="every-week">
- {{ __('Every week (Sundays at 4:00am)') }}
- </label>
- </div>
-
- <div class="cron-preset-radio-input">
- <input
- id="every-month"
- class="label-light"
- type="radio"
- v-model="cronInterval"
- :name="inputNameAttribute"
- :value="cronIntervalPresets.everyMonth"
- @click="toggleCustomInput(false)"
- />
-
- <label class="label-light" for="every-month">
- {{ __('Every month (on the 1st at 4:00am)') }}
- </label>
- </div>
-
- <div class="cron-interval-input-wrapper">
- <input
- id="schedule_cron"
- class="form-control inline cron-interval-input"
- type="text"
- :placeholder="__('Define a custom pattern with cron syntax')"
- required="true"
- v-model="cronInterval"
- :name="inputNameAttribute"
- :disabled="!isEditable"
- />
- </div>
- </div>
- `,
-};
diff --git a/app/assets/javascripts/pipeline_schedules/components/interval_pattern_input.vue b/app/assets/javascripts/pipeline_schedules/components/interval_pattern_input.vue
new file mode 100644
index 00000000000..ce46b3fa3fa
--- /dev/null
+++ b/app/assets/javascripts/pipeline_schedules/components/interval_pattern_input.vue
@@ -0,0 +1,144 @@
+<script>
+ export default {
+ props: {
+ initialCronInterval: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ },
+ data() {
+ return {
+ inputNameAttribute: 'schedule[cron]',
+ cronInterval: this.initialCronInterval,
+ cronIntervalPresets: {
+ everyDay: '0 4 * * *',
+ everyWeek: '0 4 * * 0',
+ everyMonth: '0 4 1 * *',
+ },
+ cronSyntaxUrl: 'https://en.wikipedia.org/wiki/Cron',
+ customInputEnabled: false,
+ };
+ },
+ computed: {
+ intervalIsPreset() {
+ return _.contains(this.cronIntervalPresets, this.cronInterval);
+ },
+ // The text input is editable when there's a custom interval, or when it's
+ // a preset interval and the user clicks the 'custom' radio button
+ isEditable() {
+ return !!(this.customInputEnabled || !this.intervalIsPreset);
+ },
+ },
+ methods: {
+ toggleCustomInput(shouldEnable) {
+ this.customInputEnabled = shouldEnable;
+
+ if (shouldEnable) {
+ // We need to change the value so other radios don't remain selected
+ // because the model (cronInterval) hasn't changed. The server trims it.
+ this.cronInterval = `${this.cronInterval} `;
+ }
+ },
+ },
+ created() {
+ if (this.intervalIsPreset) {
+ this.enableCustomInput = false;
+ }
+ },
+ watch: {
+ cronInterval() {
+ // updates field validation state when model changes, as
+ // glFieldError only updates on input.
+ this.$nextTick(() => {
+ gl.pipelineScheduleFieldErrors.updateFormValidityState();
+ });
+ },
+ },
+ };
+</script>
+
+<template>
+ <div class="interval-pattern-form-group">
+ <div class="cron-preset-radio-input">
+ <input
+ id="custom"
+ class="label-light"
+ type="radio"
+ :name="inputNameAttribute"
+ :value="cronInterval"
+ :checked="isEditable"
+ @click="toggleCustomInput(true)"
+ />
+
+ <label for="custom">
+ {{ s__('PipelineSheduleIntervalPattern|Custom') }}
+ </label>
+
+ <span class="cron-syntax-link-wrap">
+ (<a :href="cronSyntaxUrl" target="_blank">{{ __('Cron syntax') }}</a>)
+ </span>
+ </div>
+
+ <div class="cron-preset-radio-input">
+ <input
+ id="every-day"
+ class="label-light"
+ type="radio"
+ v-model="cronInterval"
+ :name="inputNameAttribute"
+ :value="cronIntervalPresets.everyDay"
+ @click="toggleCustomInput(false)"
+ />
+
+ <label class="label-light" for="every-day">
+ {{ __('Every day (at 4:00am)') }}
+ </label>
+ </div>
+
+ <div class="cron-preset-radio-input">
+ <input
+ id="every-week"
+ class="label-light"
+ type="radio"
+ v-model="cronInterval"
+ :name="inputNameAttribute"
+ :value="cronIntervalPresets.everyWeek"
+ @click="toggleCustomInput(false)"
+ />
+
+ <label class="label-light" for="every-week">
+ {{ __('Every week (Sundays at 4:00am)') }}
+ </label>
+ </div>
+
+ <div class="cron-preset-radio-input">
+ <input
+ id="every-month"
+ class="label-light"
+ type="radio"
+ v-model="cronInterval"
+ :name="inputNameAttribute"
+ :value="cronIntervalPresets.everyMonth"
+ @click="toggleCustomInput(false)"
+ />
+
+ <label class="label-light" for="every-month">
+ {{ __('Every month (on the 1st at 4:00am)') }}
+ </label>
+ </div>
+
+ <div class="cron-interval-input-wrapper">
+ <input
+ id="schedule_cron"
+ class="form-control inline cron-interval-input"
+ type="text"
+ :placeholder="__('Define a custom pattern with cron syntax')"
+ required="true"
+ v-model="cronInterval"
+ :name="inputNameAttribute"
+ :disabled="!isEditable"
+ />
+ </div>
+ </div>
+</template>
diff --git a/app/assets/javascripts/pipeline_schedules/pipeline_schedule_form_bundle.js b/app/assets/javascripts/pipeline_schedules/pipeline_schedule_form_bundle.js
index c60e77decce..b424e7f205d 100644
--- a/app/assets/javascripts/pipeline_schedules/pipeline_schedule_form_bundle.js
+++ b/app/assets/javascripts/pipeline_schedules/pipeline_schedule_form_bundle.js
@@ -1,20 +1,41 @@
import Vue from 'vue';
-import IntervalPatternInput from './components/interval_pattern_input';
+import Translate from '../vue_shared/translate';
+import intervalPatternInput from './components/interval_pattern_input.vue';
import TimezoneDropdown from './components/timezone_dropdown';
import TargetBranchDropdown from './components/target_branch_dropdown';
-document.addEventListener('DOMContentLoaded', () => {
- const IntervalPatternInputComponent = Vue.extend(IntervalPatternInput);
+Vue.use(Translate);
+
+function initIntervalPatternInput() {
const intervalPatternMount = document.getElementById('interval-pattern-input');
const initialCronInterval = intervalPatternMount ? intervalPatternMount.dataset.initialInterval : '';
- new IntervalPatternInputComponent({
- propsData: {
- initialCronInterval,
+ return new Vue({
+ el: intervalPatternMount,
+ components: {
+ intervalPatternInput,
},
- }).$mount(intervalPatternMount);
+ render(createElement) {
+ return createElement('interval-pattern-input', {
+ props: {
+ initialCronInterval,
+ },
+ });
+ },
+ });
+}
+
+document.addEventListener('DOMContentLoaded', () => {
+ /* Most of the form is written in haml, but for fields with more complex behaviors,
+ * you should mount individual Vue components here. If at some point components need
+ * to share state, it may make sense to refactor the whole form to Vue */
+
+ initIntervalPatternInput();
+
+ // Initialize non-Vue JS components in the form
const formElement = document.getElementById('new-pipeline-schedule-form');
+
gl.timezoneDropdown = new TimezoneDropdown();
gl.targetBranchDropdown = new TargetBranchDropdown();
gl.pipelineScheduleFieldErrors = new gl.GlFieldErrors(formElement);
diff --git a/app/assets/javascripts/pipelines/components/async_button.vue b/app/assets/javascripts/pipelines/components/async_button.vue
index abcd0c4ecea..16cc0761fc1 100644
--- a/app/assets/javascripts/pipelines/components/async_button.vue
+++ b/app/assets/javascripts/pipelines/components/async_button.vue
@@ -3,7 +3,7 @@
import eventHub from '../event_hub';
import loadingIcon from '../../vue_shared/components/loading_icon.vue';
-import tooltipMixin from '../../vue_shared/mixins/tooltip';
+import tooltip from '../../vue_shared/directives/tooltip';
export default {
props: {
@@ -28,12 +28,12 @@ export default {
required: false,
},
},
+ directives: {
+ tooltip,
+ },
components: {
loadingIcon,
},
- mixins: [
- tooltipMixin,
- ],
data() {
return {
isLoading: false,
@@ -58,7 +58,6 @@ export default {
makeRequest() {
this.isLoading = true;
- $(this.$refs.tooltip).tooltip('destroy');
eventHub.$emit('postAction', this.endpoint);
},
},
@@ -67,6 +66,7 @@ export default {
<template>
<button
+ v-tooltip
type="button"
@click="onClick"
:class="buttonClass"
@@ -74,7 +74,6 @@ export default {
:aria-label="title"
data-container="body"
data-placement="top"
- ref="tooltip"
:disabled="isLoading">
<i
:class="iconClass"
diff --git a/app/assets/javascripts/pipelines/components/graph/action_component.vue b/app/assets/javascripts/pipelines/components/graph/action_component.vue
index 1f9e3d39779..54227425d2a 100644
--- a/app/assets/javascripts/pipelines/components/graph/action_component.vue
+++ b/app/assets/javascripts/pipelines/components/graph/action_component.vue
@@ -1,6 +1,6 @@
<script>
import getActionIcon from '../../../vue_shared/ci_action_icons';
- import tooltipMixin from '../../../vue_shared/mixins/tooltip';
+ import tooltip from '../../../vue_shared/directives/tooltip';
/**
* Renders either a cancel, retry or play icon pointing to the given path.
@@ -29,9 +29,9 @@
},
},
- mixins: [
- tooltipMixin,
- ],
+ directives: {
+ tooltip,
+ },
computed: {
actionIconSvg() {
@@ -46,12 +46,11 @@
</script>
<template>
<a
+ v-tooltip
:data-method="actionMethod"
:title="tooltipText"
:href="link"
- ref="tooltip"
class="ci-action-icon-container"
- data-toggle="tooltip"
data-container="body">
<i
diff --git a/app/assets/javascripts/pipelines/components/graph/dropdown_action_component.vue b/app/assets/javascripts/pipelines/components/graph/dropdown_action_component.vue
index 19cafff4e1c..18fe1847eef 100644
--- a/app/assets/javascripts/pipelines/components/graph/dropdown_action_component.vue
+++ b/app/assets/javascripts/pipelines/components/graph/dropdown_action_component.vue
@@ -1,6 +1,6 @@
<script>
import getActionIcon from '../../../vue_shared/ci_action_icons';
- import tooltipMixin from '../../../vue_shared/mixins/tooltip';
+ import tooltip from '../../../vue_shared/directives/tooltip';
/**
* Renders either a cancel, retry or play icon pointing to the given path.
@@ -29,9 +29,9 @@
},
},
- mixins: [
- tooltipMixin,
- ],
+ directives: {
+ tooltip,
+ },
computed: {
actionIconSvg() {
@@ -42,13 +42,12 @@
</script>
<template>
<a
+ v-tooltip
:data-method="actionMethod"
:title="tooltipText"
:href="link"
- ref="tooltip"
rel="nofollow"
class="ci-action-icon-wrapper js-ci-status-icon"
- data-toggle="tooltip"
data-container="body"
v-html="actionIconSvg"
aria-label="Job's action">
diff --git a/app/assets/javascripts/pipelines/components/graph/dropdown_job_component.vue b/app/assets/javascripts/pipelines/components/graph/dropdown_job_component.vue
index d597af8dfb5..2944689a5a7 100644
--- a/app/assets/javascripts/pipelines/components/graph/dropdown_job_component.vue
+++ b/app/assets/javascripts/pipelines/components/graph/dropdown_job_component.vue
@@ -1,7 +1,7 @@
<script>
import jobNameComponent from './job_name_component.vue';
import jobComponent from './job_component.vue';
- import tooltipMixin from '../../../vue_shared/mixins/tooltip';
+ import tooltip from '../../../vue_shared/directives/tooltip';
/**
* Renders the dropdown for the pipeline graph.
@@ -34,9 +34,9 @@
},
},
- mixins: [
- tooltipMixin,
- ],
+ directives: {
+ tooltip,
+ },
components: {
jobComponent,
@@ -53,12 +53,12 @@
<template>
<div>
<button
+ v-tooltip
type="button"
data-toggle="dropdown"
data-container="body"
class="dropdown-menu-toggle build-content"
- :title="tooltipText"
- ref="tooltip">
+ :title="tooltipText">
<job-name-component
:name="job.name"
diff --git a/app/assets/javascripts/pipelines/components/graph/job_component.vue b/app/assets/javascripts/pipelines/components/graph/job_component.vue
index b39c936101e..1f5ed3f1074 100644
--- a/app/assets/javascripts/pipelines/components/graph/job_component.vue
+++ b/app/assets/javascripts/pipelines/components/graph/job_component.vue
@@ -2,7 +2,7 @@
import actionComponent from './action_component.vue';
import dropdownActionComponent from './dropdown_action_component.vue';
import jobNameComponent from './job_name_component.vue';
- import tooltipMixin from '../../../vue_shared/mixins/tooltip';
+ import tooltip from '../../../vue_shared/directives/tooltip';
/**
* Renders the badge for the pipeline graph and the job's dropdown.
@@ -54,9 +54,9 @@
jobNameComponent,
},
- mixins: [
- tooltipMixin,
- ],
+ directives: {
+ tooltip,
+ },
computed: {
tooltipText() {
@@ -77,12 +77,11 @@
<template>
<div>
<a
+ v-tooltip
v-if="job.status.details_path"
:href="job.status.details_path"
:title="tooltipText"
:class="cssClassJobName"
- ref="tooltip"
- data-toggle="tooltip"
data-container="body">
<job-name-component
@@ -93,10 +92,9 @@
<div
v-else
+ v-tooltip
:title="tooltipText"
:class="cssClassJobName"
- ref="tooltip"
- data-toggle="tooltip"
data-container="body">
<job-name-component
diff --git a/app/assets/javascripts/pipelines/components/pipeline_url.vue b/app/assets/javascripts/pipelines/components/pipeline_url.vue
index 8333ec0fbc3..2ca5ac2912f 100644
--- a/app/assets/javascripts/pipelines/components/pipeline_url.vue
+++ b/app/assets/javascripts/pipelines/components/pipeline_url.vue
@@ -1,6 +1,6 @@
<script>
import userAvatarLink from '../../vue_shared/components/user_avatar/user_avatar_link.vue';
-import tooltipMixin from '../../vue_shared/mixins/tooltip';
+import tooltip from '../../vue_shared/directives/tooltip';
export default {
props: {
@@ -12,9 +12,9 @@ export default {
components: {
userAvatarLink,
},
- mixins: [
- tooltipMixin,
- ],
+ directives: {
+ tooltip,
+ },
computed: {
user() {
return this.pipeline.user;
@@ -45,16 +45,16 @@ export default {
<div class="label-container">
<span
v-if="pipeline.flags.latest"
+ v-tooltip
class="js-pipeline-url-latest label label-success"
- title="Latest pipeline for this branch"
- ref="tooltip">
+ title="Latest pipeline for this branch">
latest
</span>
<span
v-if="pipeline.flags.yaml_errors"
+ v-tooltip
class="js-pipeline-url-yaml label label-danger"
- :title="pipeline.yaml_errors"
- ref="tooltip">
+ :title="pipeline.yaml_errors">
yaml invalid
</span>
<span
diff --git a/app/assets/javascripts/pipelines/components/pipelines_actions.vue b/app/assets/javascripts/pipelines/components/pipelines_actions.vue
index a6fc4f04237..01dfe51cc17 100644
--- a/app/assets/javascripts/pipelines/components/pipelines_actions.vue
+++ b/app/assets/javascripts/pipelines/components/pipelines_actions.vue
@@ -4,6 +4,7 @@
import playIconSvg from 'icons/_icon_play.svg';
import eventHub from '../event_hub';
import loadingIcon from '../../vue_shared/components/loading_icon.vue';
+ import tooltip from '../../vue_shared/directives/tooltip';
export default {
props: {
@@ -12,6 +13,9 @@
required: true,
},
},
+ directives: {
+ tooltip,
+ },
components: {
loadingIcon,
},
@@ -25,8 +29,6 @@
onClickAction(endpoint) {
this.isLoading = true;
- $(this.$refs.tooltip).tooltip('destroy');
-
eventHub.$emit('postAction', endpoint);
},
@@ -43,13 +45,13 @@
<template>
<div class="btn-group">
<button
+ v-tooltip
type="button"
- class="dropdown-new btn btn-default has-tooltip js-pipeline-dropdown-manual-actions"
+ class="dropdown-new btn btn-default js-pipeline-dropdown-manual-actions"
title="Manual job"
data-toggle="dropdown"
data-placement="top"
aria-label="Manual job"
- ref="tooltip"
:disabled="isLoading">
<span v-html="playIconSvg"></span>
<i
diff --git a/app/assets/javascripts/pipelines/components/pipelines_artifacts.vue b/app/assets/javascripts/pipelines/components/pipelines_artifacts.vue
index b4520481cdc..b19bd509a00 100644
--- a/app/assets/javascripts/pipelines/components/pipelines_artifacts.vue
+++ b/app/assets/javascripts/pipelines/components/pipelines_artifacts.vue
@@ -1,5 +1,5 @@
<script>
- import tooltipMixin from '../../vue_shared/mixins/tooltip';
+ import tooltip from '../../vue_shared/directives/tooltip';
export default {
props: {
@@ -8,9 +8,9 @@
required: true,
},
},
- mixins: [
- tooltipMixin,
- ],
+ directives: {
+ tooltip,
+ },
};
</script>
<template>
@@ -18,12 +18,12 @@
class="btn-group"
role="group">
<button
+ v-tooltip
class="dropdown-toggle btn btn-default build-artifacts js-pipeline-dropdown-download"
title="Artifacts"
data-placement="top"
data-toggle="dropdown"
- aria-label="Artifacts"
- ref="tooltip">
+ aria-label="Artifacts">
<i
class="fa fa-download"
aria-hidden="true">
diff --git a/app/assets/javascripts/pipelines/components/stage.vue b/app/assets/javascripts/pipelines/components/stage.vue
index c05c76c9a64..87b2725a045 100644
--- a/app/assets/javascripts/pipelines/components/stage.vue
+++ b/app/assets/javascripts/pipelines/components/stage.vue
@@ -16,7 +16,7 @@
/* global Flash */
import { borderlessStatusIconEntityMap } from '../../vue_shared/ci_status_icons';
import loadingIcon from '../../vue_shared/components/loading_icon.vue';
-import tooltipMixin from '../../vue_shared/mixins/tooltip';
+import tooltip from '../../vue_shared/directives/tooltip';
export default {
props: {
@@ -32,15 +32,14 @@ export default {
},
},
- mixins: [
- tooltipMixin,
- ],
+ directives: {
+ tooltip,
+ },
data() {
return {
isLoading: false,
dropdownContent: '',
- endpoint: this.stage.dropdown_path,
};
},
@@ -73,7 +72,7 @@ export default {
},
fetchJobs() {
- this.$http.get(this.endpoint)
+ this.$http.get(this.stage.dropdown_path)
.then((response) => {
this.dropdownContent = response.json().html;
this.isLoading = false;
@@ -132,7 +131,7 @@ export default {
<template>
<div class="dropdown">
<button
- ref="tooltip"
+ v-tooltip
:class="triggerButtonClass"
@click="onClickStage"
class="mini-pipeline-graph-dropdown-toggle js-builds-dropdown-button"
diff --git a/app/assets/javascripts/pipelines/components/time_ago.vue b/app/assets/javascripts/pipelines/components/time_ago.vue
index be3f32afa09..037684b4e72 100644
--- a/app/assets/javascripts/pipelines/components/time_ago.vue
+++ b/app/assets/javascripts/pipelines/components/time_ago.vue
@@ -1,7 +1,7 @@
<script>
import iconTimerSvg from 'icons/_icon_timer.svg';
import '../../lib/utils/datetime_utility';
- import tooltipMixin from '../../vue_shared/mixins/tooltip';
+ import tooltip from '../../vue_shared/directives/tooltip';
import timeagoMixin from '../../vue_shared/mixins/timeago';
export default {
@@ -16,9 +16,11 @@
},
},
mixins: [
- tooltipMixin,
timeagoMixin,
],
+ directives: {
+ tooltip,
+ },
data() {
return {
iconTimerSvg,
@@ -81,7 +83,7 @@
</i>
<time
- ref="tooltip"
+ v-tooltip
data-placement="top"
data-container="body"
:title="tooltipTitle(finishedTime)">
diff --git a/app/assets/javascripts/sidebar/components/assignees/assignee_title.js b/app/assets/javascripts/sidebar/components/assignees/assignee_title.js
index a9ad3708514..5a6e47e566e 100644
--- a/app/assets/javascripts/sidebar/components/assignees/assignee_title.js
+++ b/app/assets/javascripts/sidebar/components/assignees/assignee_title.js
@@ -14,6 +14,11 @@ export default {
type: Boolean,
required: true,
},
+ showToggle: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
},
computed: {
assigneeTitle() {
@@ -36,6 +41,19 @@ export default {
>
Edit
</a>
+ <a
+ v-if="showToggle"
+ aria-label="Toggle sidebar"
+ class="gutter-toggle pull-right js-sidebar-toggle"
+ href="#"
+ role="button"
+ >
+ <i
+ aria-hidden="true"
+ data-hidden="true"
+ class="fa fa-angle-double-right"
+ />
+ </a>
</div>
`,
};
diff --git a/app/assets/javascripts/sidebar/components/assignees/sidebar_assignees.js b/app/assets/javascripts/sidebar/components/assignees/sidebar_assignees.js
index da4abf0b68f..f83c3b037ed 100644
--- a/app/assets/javascripts/sidebar/components/assignees/sidebar_assignees.js
+++ b/app/assets/javascripts/sidebar/components/assignees/sidebar_assignees.js
@@ -64,6 +64,7 @@ export default {
},
beforeMount() {
this.field = this.$el.dataset.field;
+ this.signedIn = typeof this.$el.dataset.signedIn !== 'undefined';
},
template: `
<div>
@@ -71,6 +72,7 @@ export default {
:number-of-assignees="store.assignees.length"
:loading="loading || store.isFetching.assignees"
:editable="store.editable"
+ :show-toggle="!signedIn"
/>
<assignees
v-if="!store.isFetching.assignees"
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline.js b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline.js
index c02e10128e2..e8b3cf2f729 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline.js
+++ b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline.js
@@ -17,6 +17,9 @@ export default {
return hasCI && !ciStatus;
},
+ hasPipeline() {
+ return Object.keys(this.mr.pipeline || {}).length > 0;
+ },
svg() {
return statusIconEntityMap.icon_status_failed;
},
@@ -30,7 +33,11 @@ export default {
template: `
<div class="mr-widget-heading">
<div class="ci-widget">
- <template v-if="hasCIError">
+ <template v-if="!hasPipeline">
+ <i class="fa fa-spinner fa-spin append-right-10" aria-hidden="true"></i>
+ Waiting for pipeline...
+ </template>
+ <template v-else-if="hasCIError">
<div class="ci-status-icon ci-status-icon-failed ci-error js-ci-error">
<span class="js-icon-link icon-link">
<span
diff --git a/app/assets/javascripts/vue_shared/components/header_ci_component.vue b/app/assets/javascripts/vue_shared/components/header_ci_component.vue
index 1d4d90f75b6..bdc059f4a03 100644
--- a/app/assets/javascripts/vue_shared/components/header_ci_component.vue
+++ b/app/assets/javascripts/vue_shared/components/header_ci_component.vue
@@ -2,7 +2,7 @@
import ciIconBadge from './ci_badge_link.vue';
import loadingIcon from './loading_icon.vue';
import timeagoTooltip from './time_ago_tooltip.vue';
-import tooltipMixin from '../mixins/tooltip';
+import tooltip from '../directives/tooltip';
import userAvatarImage from './user_avatar/user_avatar_image.vue';
/**
@@ -47,9 +47,9 @@ export default {
},
},
- mixins: [
- tooltipMixin,
- ],
+ directives: {
+ tooltip,
+ },
components: {
ciIconBadge,
@@ -90,10 +90,10 @@ export default {
<template v-if="user">
<a
+ v-tooltip
:href="user.path"
:title="user.email"
- class="js-user-link commit-committer-link"
- ref="tooltip">
+ class="js-user-link commit-committer-link">
<user-avatar-image
:img-src="user.avatar_url"
diff --git a/app/assets/javascripts/vue_shared/components/markdown/header.vue b/app/assets/javascripts/vue_shared/components/markdown/header.vue
index 1a11f493b7f..5bf2a90cc3b 100644
--- a/app/assets/javascripts/vue_shared/components/markdown/header.vue
+++ b/app/assets/javascripts/vue_shared/components/markdown/header.vue
@@ -1,17 +1,17 @@
<script>
- import tooltipMixin from '../../mixins/tooltip';
+ import tooltip from '../../directives/tooltip';
import toolbarButton from './toolbar_button.vue';
export default {
- mixins: [
- tooltipMixin,
- ],
props: {
previewMarkdown: {
type: Boolean,
required: true,
},
},
+ directives: {
+ tooltip,
+ },
components: {
toolbarButton,
},
@@ -94,13 +94,13 @@
</div>
<div class="toolbar-group">
<button
+ v-tooltip
aria-label="Go full screen"
class="toolbar-btn js-zen-enter"
data-container="body"
tabindex="-1"
title="Go full screen"
- type="button"
- ref="tooltip">
+ type="button">
<i
aria-hidden="true"
class="fa fa-arrows-alt fa-fw">
diff --git a/app/assets/javascripts/vue_shared/components/markdown/toolbar_button.vue b/app/assets/javascripts/vue_shared/components/markdown/toolbar_button.vue
index 096be507625..f7da7ebfcfe 100644
--- a/app/assets/javascripts/vue_shared/components/markdown/toolbar_button.vue
+++ b/app/assets/javascripts/vue_shared/components/markdown/toolbar_button.vue
@@ -1,10 +1,7 @@
<script>
- import tooltipMixin from '../../mixins/tooltip';
+ import tooltip from '../../directives/tooltip';
export default {
- mixins: [
- tooltipMixin,
- ],
props: {
buttonTitle: {
type: String,
@@ -29,6 +26,9 @@
default: false,
},
},
+ directives: {
+ tooltip,
+ },
computed: {
iconClass() {
return `fa-${this.icon}`;
@@ -39,10 +39,10 @@
<template>
<button
+ v-tooltip
type="button"
class="toolbar-btn js-md hidden-xs"
tabindex="-1"
- ref="tooltip"
data-container="body"
:data-md-tag="tag"
:data-md-block="tagBlock"
diff --git a/app/assets/javascripts/vue_shared/components/time_ago_tooltip.vue b/app/assets/javascripts/vue_shared/components/time_ago_tooltip.vue
index 1c6ef071a6d..3ff7f6e2c4e 100644
--- a/app/assets/javascripts/vue_shared/components/time_ago_tooltip.vue
+++ b/app/assets/javascripts/vue_shared/components/time_ago_tooltip.vue
@@ -1,5 +1,5 @@
<script>
-import tooltipMixin from '../mixins/tooltip';
+import tooltip from '../directives/tooltip';
import timeagoMixin from '../mixins/timeago';
import '../../lib/utils/datetime_utility';
@@ -28,19 +28,21 @@ export default {
},
mixins: [
- tooltipMixin,
timeagoMixin,
],
+
+ directives: {
+ tooltip,
+ },
};
</script>
<template>
<time
+ v-tooltip
:class="cssClass"
- class="js-vue-timeago"
:title="tooltipTitle(time)"
:data-placement="tooltipPlacement"
- data-container="body"
- ref="tooltip">
+ data-container="body">
{{timeFormated(time)}}
</time>
</template>
diff --git a/app/assets/javascripts/vue_shared/components/user_avatar/user_avatar_image.vue b/app/assets/javascripts/vue_shared/components/user_avatar/user_avatar_image.vue
index cd6f8c7aee4..dd9a2ebb184 100644
--- a/app/assets/javascripts/vue_shared/components/user_avatar/user_avatar_image.vue
+++ b/app/assets/javascripts/vue_shared/components/user_avatar/user_avatar_image.vue
@@ -16,11 +16,10 @@
*/
import defaultAvatarUrl from 'images/no_avatar.png';
-import TooltipMixin from '../../mixins/tooltip';
+import tooltip from '../../directives/tooltip';
export default {
name: 'UserAvatarImage',
- mixins: [TooltipMixin],
props: {
imgSrc: {
type: String,
@@ -53,6 +52,9 @@ export default {
default: 'top',
},
},
+ directives: {
+ tooltip,
+ },
computed: {
tooltipContainer() {
return this.tooltipText ? 'body' : null;
@@ -72,6 +74,7 @@ export default {
<template>
<img
+ v-tooltip
class="avatar"
:class="[avatarSizeClass, cssClasses]"
:src="imageSource"
@@ -81,6 +84,5 @@ export default {
:data-container="tooltipContainer"
:data-placement="tooltipPlacement"
:title="tooltipText"
- ref="tooltip"
/>
</template>
diff --git a/app/assets/javascripts/vue_shared/directives/tooltip.js b/app/assets/javascripts/vue_shared/directives/tooltip.js
new file mode 100644
index 00000000000..dc896cf5c7d
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/directives/tooltip.js
@@ -0,0 +1,13 @@
+export default {
+ bind(el) {
+ $(el).tooltip();
+ },
+
+ componentUpdated(el) {
+ $(el).tooltip('fixTitle');
+ },
+
+ unbind(el) {
+ $(el).tooltip('destroy');
+ },
+};
diff --git a/app/assets/javascripts/vue_shared/mixins/tooltip.js b/app/assets/javascripts/vue_shared/mixins/tooltip.js
deleted file mode 100644
index 995c0c98505..00000000000
--- a/app/assets/javascripts/vue_shared/mixins/tooltip.js
+++ /dev/null
@@ -1,13 +0,0 @@
-export default {
- mounted() {
- $(this.$refs.tooltip).tooltip();
- },
-
- updated() {
- $(this.$refs.tooltip).tooltip('fixTitle');
- },
-
- beforeDestroy() {
- $(this.$refs.tooltip).tooltip('destroy');
- },
-};
diff --git a/app/assets/stylesheets/framework/files.scss b/app/assets/stylesheets/framework/files.scss
index 31220ab438e..245117b2559 100644
--- a/app/assets/stylesheets/framework/files.scss
+++ b/app/assets/stylesheets/framework/files.scss
@@ -129,7 +129,7 @@
}
/**
- * Annotate file
+ * Blame file
*/
&.blame {
table {
diff --git a/app/assets/stylesheets/framework/header.scss b/app/assets/stylesheets/framework/header.scss
index 94986badaf9..5bd6c095109 100644
--- a/app/assets/stylesheets/framework/header.scss
+++ b/app/assets/stylesheets/framework/header.scss
@@ -34,6 +34,8 @@ header {
top: 0;
left: 0;
right: 0;
+ color: $gl-text-color-secondary;
+ border-radius: 0;
@media (max-width: $screen-xs-min) {
padding: 0 16px;
@@ -59,7 +61,7 @@ header {
padding: 0;
.nav > li > a {
- color: $gl-text-color-secondary;
+ color: currentColor;
font-size: 18px;
padding: 0;
margin: (($header-height - 28) / 2) 3px;
@@ -84,7 +86,7 @@ header {
&:hover,
&:focus,
&:active {
- background-color: $gray-light;
+ background-color: transparent;
color: $gl-text-color;
svg {
@@ -96,13 +98,19 @@ header {
font-size: 14px;
}
+ .fa-chevron-down {
+ position: relative;
+ top: -3px;
+ font-size: 10px;
+ }
+
svg {
position: relative;
top: 2px;
height: 17px;
// hack to get SVG to line up with FA icons
width: 23px;
- fill: $gl-text-color-secondary;
+ fill: currentColor;
}
}
@@ -225,7 +233,7 @@ header {
}
a {
- color: $gl-text-color;
+ color: currentColor;
&:hover {
text-decoration: underline;
@@ -346,6 +354,7 @@ header {
width: auto;
min-width: 140px;
margin-top: -5px;
+ color: $gl-text-color;
left: auto;
.current-user {
diff --git a/app/assets/stylesheets/framework/variables.scss b/app/assets/stylesheets/framework/variables.scss
index 476427c1593..630f557602c 100644
--- a/app/assets/stylesheets/framework/variables.scss
+++ b/app/assets/stylesheets/framework/variables.scss
@@ -74,6 +74,10 @@ $red-700: #a62d19;
$red-800: #8b2615;
$red-900: #711e11;
+$purple-700: #4a2192;
+$purple-800: #2c0a5c;
+$purple-900: #380d75;
+
$black: #000;
$black-transparent: rgba(0, 0, 0, 0.3);
diff --git a/app/assets/stylesheets/new_nav.scss b/app/assets/stylesheets/new_nav.scss
new file mode 100644
index 00000000000..441bfc479f6
--- /dev/null
+++ b/app/assets/stylesheets/new_nav.scss
@@ -0,0 +1,267 @@
+@import "framework/variables";
+@import 'framework/tw_bootstrap_variables';
+@import "bootstrap/variables";
+
+header.navbar-gitlab-new {
+ color: $white-light;
+ background-color: $purple-900;
+ border-bottom: 0;
+
+ .header-content {
+ padding-left: 0;
+
+ .title-container {
+ padding-top: 0;
+ overflow: visible;
+ }
+
+ .title {
+ display: block;
+ height: 100%;
+ padding-right: 0;
+ color: currentColor;
+
+ > a {
+ display: flex;
+ align-items: center;
+ height: 100%;
+ padding-top: 3px;
+ padding-right: $gl-padding;
+ padding-left: $gl-padding;
+ margin-left: -$gl-padding;
+ border-bottom: 3px solid transparent;
+
+ @media (min-width: $screen-sm-min) {
+ padding-right: $gl-padding;
+ padding-left: $gl-padding;
+ }
+
+ svg {
+ margin-top: -3px;
+
+ @media (min-width: $screen-sm-min) {
+ margin-right: 10px;
+ }
+ }
+
+ &:hover,
+ &:focus {
+ color: currentColor;
+ text-decoration: none;
+ border-bottom-color: $white-light;
+ }
+ }
+ }
+
+ .dropdown.open {
+ > a {
+ border-bottom-color: $white-light;
+ }
+ }
+
+ .dropdown-menu {
+ margin-top: 4px;
+ min-width: 130px;
+
+ @media (max-width: $screen-xs-max) {
+ left: auto;
+ right: 0;
+ }
+ }
+ }
+
+ .navbar-collapse {
+ padding-left: 0;
+ color: $white-light;
+ box-shadow: 0;
+
+ @media (max-width: $screen-xs-max) {
+ margin-left: -$gl-padding;
+ margin-right: -10px;
+ }
+
+ .dropdown-bold-header {
+ color: initial;
+ }
+
+ .nav {
+ > li:not(.hidden-xs) a {
+ @media (max-width: $screen-xs-max) {
+ margin-left: 0;
+ min-width: 100%;
+ }
+ }
+ }
+ }
+
+ .container-fluid {
+ .navbar-toggle {
+ min-width: 45px;
+ padding: 6px $gl-padding;
+ margin-right: -7px;
+ font-size: 14px;
+ text-align: center;
+ color: currentColor;
+ border-left: 1px solid lighten($purple-700, 10%);
+
+ &:hover,
+ &:focus,
+ &.active {
+ color: currentColor;
+ background-color: transparent;
+ }
+ }
+
+ .navbar-nav {
+ @media (max-width: $screen-xs-max) {
+ display: flex;
+ padding-right: 10px;
+ }
+
+ li {
+ .badge {
+ box-shadow: none;
+ }
+ }
+ }
+
+ .nav > li {
+ &.header-user {
+ @media (max-width: $screen-xs-max) {
+ padding-left: 10px;
+ }
+ }
+
+ > a {
+ background: none;
+ opacity: .9;
+ will-change: opacity;
+
+ &.header-user-dropdown-toggle {
+ .header-user-avatar {
+ border-color: $white-light;
+ }
+ }
+
+ &:hover,
+ &:focus {
+ color: $white-light;
+ opacity: 1;
+
+ > svg {
+ fill: $white-light;
+ }
+
+ &.header-user-dropdown-toggle {
+ .header-user-avatar {
+ border-color: $white-light;
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+.navbar-sub-nav {
+ display: flex;
+ margin-bottom: 0;
+ color: $white-light;
+
+ > li {
+ &.active > a,
+ a:hover,
+ a:focus {
+ border-bottom-color: $white-light;
+ text-decoration: none;
+ outline: 0;
+ opacity: 1;
+ }
+
+ > a {
+ display: block;
+ padding: 16px 10px 13px;
+ font-size: 13px;
+ color: currentColor;
+ border-bottom: 3px solid transparent;
+ opacity: .9;
+ will-change: opacity;
+
+ @media (min-width: $screen-sm-min) {
+ padding: 15px $gl-padding 12px;
+ font-size: 14px;
+ }
+ }
+ }
+
+ .dropdown-chevron {
+ position: relative;
+ top: -1px;
+ font-size: 10px;
+ }
+}
+
+.header-user .dropdown-menu-nav,
+.header-new .dropdown-menu-nav {
+ margin-top: 4px;
+}
+
+.search {
+ form {
+ border-color: $purple-800;
+
+ &:hover {
+ border-color: rgba($white-light, .6);
+ box-shadow: none;
+ }
+ }
+
+ &.search-active form {
+ border-color: $white-light;
+ }
+
+ form,
+ .search-input {
+ background-color: $purple-700;
+ }
+
+ .search-input {
+ color: $white-light;
+ }
+
+ .search-input::placeholder {
+ color: rgba($white-light, .6);
+ }
+
+ .location-badge {
+ font-size: 12px;
+ color: rgba($white-light, .6);
+ background-color: $purple-800;
+ transition: color 0.15s;
+ will-change: color;
+ }
+
+ .search-input-wrap {
+ .search-icon,
+ .clear-icon {
+ color: rgba($white-light, .6);
+ }
+ }
+
+ &.search-active {
+ .location-badge {
+ color: $white-light;
+ background-color: $purple-800;
+ }
+
+ .search-input-wrap {
+ .search-icon {
+ color: rgba($white-light, .6);
+ }
+
+ .clear-icon {
+ color: $white-light;
+ }
+ }
+ }
+}
diff --git a/app/assets/stylesheets/pages/issuable.scss b/app/assets/stylesheets/pages/issuable.scss
index 0d1a360d12c..e3ebcc8af6c 100644
--- a/app/assets/stylesheets/pages/issuable.scss
+++ b/app/assets/stylesheets/pages/issuable.scss
@@ -228,6 +228,12 @@
padding-top: 10px;
}
+ &:not(.issue-boards-sidebar):not([data-signed-in]) {
+ .issuable-sidebar-header {
+ display: none;
+ }
+ }
+
.assign-yourself .btn-link {
padding-left: 0;
}
@@ -249,6 +255,10 @@
border-left: 1px solid $border-gray-normal;
}
+ .title .gutter-toggle {
+ margin-top: 0;
+ }
+
.assignee .avatar {
float: left;
margin-right: 10px;
diff --git a/app/assets/stylesheets/pages/labels.scss b/app/assets/stylesheets/pages/labels.scss
index c10588ac58e..b158416b940 100644
--- a/app/assets/stylesheets/pages/labels.scss
+++ b/app/assets/stylesheets/pages/labels.scss
@@ -138,6 +138,7 @@
.fa {
font-size: 18px;
vertical-align: middle;
+ pointer-events: none;
}
&:hover {
diff --git a/app/assets/stylesheets/pages/notes.scss b/app/assets/stylesheets/pages/notes.scss
index f0dbe4249c5..53d5cf2f7bc 100644
--- a/app/assets/stylesheets/pages/notes.scss
+++ b/app/assets/stylesheets/pages/notes.scss
@@ -473,7 +473,7 @@ ul.notes {
}
.more-actions {
- display: inline;
+ display: inline-block;
.tooltip {
white-space: nowrap;
diff --git a/app/controllers/admin/users_controller.rb b/app/controllers/admin/users_controller.rb
index b09eef17c23..fa1bc72560e 100644
--- a/app/controllers/admin/users_controller.rb
+++ b/app/controllers/admin/users_controller.rb
@@ -54,7 +54,7 @@ class Admin::UsersController < Admin::ApplicationController
end
def block
- if user.block
+ if update_user { |user| user.block }
redirect_back_or_admin_user(notice: "Successfully blocked")
else
redirect_back_or_admin_user(alert: "Error occurred. User was not blocked")
@@ -64,7 +64,7 @@ class Admin::UsersController < Admin::ApplicationController
def unblock
if user.ldap_blocked?
redirect_back_or_admin_user(alert: "This user cannot be unlocked manually from GitLab")
- elsif user.activate
+ elsif update_user { |user| user.activate }
redirect_back_or_admin_user(notice: "Successfully unblocked")
else
redirect_back_or_admin_user(alert: "Error occurred. User was not unblocked")
@@ -72,7 +72,7 @@ class Admin::UsersController < Admin::ApplicationController
end
def unlock
- if user.unlock_access!
+ if update_user { |user| user.unlock_access! }
redirect_back_or_admin_user(alert: "Successfully unlocked")
else
redirect_back_or_admin_user(alert: "Error occurred. User was not unlocked")
@@ -80,7 +80,7 @@ class Admin::UsersController < Admin::ApplicationController
end
def confirm
- if user.confirm
+ if update_user { |user| user.confirm }
redirect_back_or_admin_user(notice: "Successfully confirmed")
else
redirect_back_or_admin_user(alert: "Error occurred. User was not confirmed")
@@ -88,7 +88,8 @@ class Admin::UsersController < Admin::ApplicationController
end
def disable_two_factor
- user.disable_two_factor!
+ update_user { |user| user.disable_two_factor! }
+
redirect_to admin_user_path(user),
notice: 'Two-factor Authentication has been disabled for this user'
end
@@ -124,15 +125,18 @@ class Admin::UsersController < Admin::ApplicationController
end
respond_to do |format|
- user.skip_reconfirmation!
- if user.update_attributes(user_params_with_pass)
+ result = Users::UpdateService.new(user, user_params_with_pass).execute do |user|
+ user.skip_reconfirmation!
+ end
+
+ if result[:status] == :success
format.html { redirect_to [:admin, user], notice: 'User was successfully updated.' }
format.json { head :ok }
else
# restore username to keep form action url.
user.username = params[:id]
format.html { render "edit" }
- format.json { render json: user.errors, status: :unprocessable_entity }
+ format.json { render json: [result[:message]], status: result[:status] }
end
end
end
@@ -148,13 +152,16 @@ class Admin::UsersController < Admin::ApplicationController
def remove_email
email = user.emails.find(params[:email_id])
- email.destroy
-
- user.update_secondary_emails!
+ success = Emails::DestroyService.new(user, email: email.email).execute
respond_to do |format|
- format.html { redirect_back_or_admin_user(notice: "Successfully removed email.") }
- format.js { head :ok }
+ if success
+ format.html { redirect_back_or_admin_user(notice: 'Successfully removed email.') }
+ format.json { head :ok }
+ else
+ format.html { redirect_back_or_admin_user(alert: 'There was an error removing the e-mail.') }
+ format.json { render json: 'There was an error removing the e-mail.', status: 400 }
+ end
end
end
@@ -202,4 +209,10 @@ class Admin::UsersController < Admin::ApplicationController
:website_url
]
end
+
+ def update_user(&block)
+ result = Users::UpdateService.new(user).execute(&block)
+
+ result[:status] == :success
+ end
end
diff --git a/app/controllers/profiles/avatars_controller.rb b/app/controllers/profiles/avatars_controller.rb
index 933e0f3bceb..408650aac54 100644
--- a/app/controllers/profiles/avatars_controller.rb
+++ b/app/controllers/profiles/avatars_controller.rb
@@ -1,9 +1,8 @@
class Profiles::AvatarsController < Profiles::ApplicationController
def destroy
@user = current_user
- @user.remove_avatar!
- @user.save
+ Users::UpdateService.new(@user).execute { |user| user.remove_avatar! }
redirect_to profile_path, status: 302
end
diff --git a/app/controllers/profiles/emails_controller.rb b/app/controllers/profiles/emails_controller.rb
index 5655fb2ba0e..17b66df43e7 100644
--- a/app/controllers/profiles/emails_controller.rb
+++ b/app/controllers/profiles/emails_controller.rb
@@ -5,9 +5,9 @@ class Profiles::EmailsController < Profiles::ApplicationController
end
def create
- @email = current_user.emails.new(email_params)
+ @email = Emails::CreateService.new(current_user, email_params).execute
- if @email.save
+ if @email.errors.blank?
NotificationService.new.new_email(@email)
else
flash[:alert] = @email.errors.full_messages.first
@@ -18,9 +18,8 @@ class Profiles::EmailsController < Profiles::ApplicationController
def destroy
@email = current_user.emails.find(params[:id])
- @email.destroy
- current_user.update_secondary_emails!
+ Emails::DestroyService.new(current_user, email: @email.email).execute
respond_to do |format|
format.html { redirect_to profile_emails_url, status: 302 }
diff --git a/app/controllers/profiles/notifications_controller.rb b/app/controllers/profiles/notifications_controller.rb
index a271e2dfc4b..960b7512602 100644
--- a/app/controllers/profiles/notifications_controller.rb
+++ b/app/controllers/profiles/notifications_controller.rb
@@ -7,7 +7,9 @@ class Profiles::NotificationsController < Profiles::ApplicationController
end
def update
- if current_user.update_attributes(user_params)
+ result = Users::UpdateService.new(current_user, user_params).execute
+
+ if result[:status] == :success
flash[:notice] = "Notification settings saved"
else
flash[:alert] = "Failed to save new settings"
diff --git a/app/controllers/profiles/passwords_controller.rb b/app/controllers/profiles/passwords_controller.rb
index 6217ec5ecef..10145bae0d3 100644
--- a/app/controllers/profiles/passwords_controller.rb
+++ b/app/controllers/profiles/passwords_controller.rb
@@ -15,17 +15,17 @@ class Profiles::PasswordsController < Profiles::ApplicationController
return
end
- new_password = user_params[:password]
- new_password_confirmation = user_params[:password_confirmation]
-
- result = @user.update_attributes(
- password: new_password,
- password_confirmation: new_password_confirmation,
+ password_attributes = {
+ password: user_params[:password],
+ password_confirmation: user_params[:password_confirmation],
password_automatically_set: false
- )
+ }
+
+ result = Users::UpdateService.new(@user, password_attributes).execute
+
+ if result[:status] == :success
+ Users::UpdateService.new(@user, password_expires_at: nil).execute
- if result
- @user.update_attributes(password_expires_at: nil)
redirect_to root_path, notice: 'Password successfully changed'
else
render :new
@@ -46,7 +46,9 @@ class Profiles::PasswordsController < Profiles::ApplicationController
return
end
- if @user.update_attributes(password_attributes)
+ result = Users::UpdateService.new(@user, password_attributes).execute
+
+ if result[:status] == :success
flash[:notice] = "Password was successfully updated. Please login with it"
redirect_to new_user_session_path
else
diff --git a/app/controllers/profiles/preferences_controller.rb b/app/controllers/profiles/preferences_controller.rb
index 5414142e2df..1e557c47638 100644
--- a/app/controllers/profiles/preferences_controller.rb
+++ b/app/controllers/profiles/preferences_controller.rb
@@ -6,7 +6,9 @@ class Profiles::PreferencesController < Profiles::ApplicationController
def update
begin
- if @user.update_attributes(preferences_params)
+ result = Users::UpdateService.new(user, preferences_params).execute
+
+ if result[:status] == :success
flash[:notice] = 'Preferences saved.'
else
flash[:alert] = 'Failed to save preferences.'
diff --git a/app/controllers/profiles/two_factor_auths_controller.rb b/app/controllers/profiles/two_factor_auths_controller.rb
index 313cdcd1c15..1a4f77639e7 100644
--- a/app/controllers/profiles/two_factor_auths_controller.rb
+++ b/app/controllers/profiles/two_factor_auths_controller.rb
@@ -10,7 +10,7 @@ class Profiles::TwoFactorAuthsController < Profiles::ApplicationController
current_user.otp_grace_period_started_at = Time.current
end
- current_user.save! if current_user.changed?
+ Users::UpdateService.new(current_user).execute!
if two_factor_authentication_required? && !current_user.two_factor_enabled?
two_factor_authentication_reason(
@@ -41,9 +41,9 @@ class Profiles::TwoFactorAuthsController < Profiles::ApplicationController
def create
if current_user.validate_and_consume_otp!(params[:pin_code])
- current_user.otp_required_for_login = true
- @codes = current_user.generate_otp_backup_codes!
- current_user.save!
+ Users::UpdateService.new(current_user, otp_required_for_login: true).execute! do |user|
+ @codes = user.generate_otp_backup_codes!
+ end
render 'create'
else
@@ -70,8 +70,9 @@ class Profiles::TwoFactorAuthsController < Profiles::ApplicationController
end
def codes
- @codes = current_user.generate_otp_backup_codes!
- current_user.save!
+ Users::UpdateService.new(current_user).execute! do |user|
+ @codes = user.generate_otp_backup_codes!
+ end
end
def destroy
diff --git a/app/controllers/profiles_controller.rb b/app/controllers/profiles_controller.rb
index f98a9e24de1..076076fd1b3 100644
--- a/app/controllers/profiles_controller.rb
+++ b/app/controllers/profiles_controller.rb
@@ -12,39 +12,47 @@ class ProfilesController < Profiles::ApplicationController
user_params.except!(:email) if @user.external_email?
respond_to do |format|
- if @user.update_attributes(user_params)
+ result = Users::UpdateService.new(@user, user_params).execute
+
+ if result[:status] == :success
message = "Profile was successfully updated"
+
format.html { redirect_back_or_default(default: { action: 'show' }, options: { notice: message }) }
format.json { render json: { message: message } }
else
- message = @user.errors.full_messages.uniq.join('. ')
- format.html { redirect_back_or_default(default: { action: 'show' }, options: { alert: "Failed to update profile. #{message}" }) }
- format.json { render json: { message: message }, status: :unprocessable_entity }
+ format.html { redirect_back_or_default(default: { action: 'show' }, options: { alert: result[:message] }) }
+ format.json { render json: result }
end
end
end
def reset_private_token
- if current_user.reset_authentication_token!
- flash[:notice] = "Private token was successfully reset"
+ Users::UpdateService.new(@user).execute! do |user|
+ user.reset_authentication_token!
end
+ flash[:notice] = "Private token was successfully reset"
+
redirect_to profile_account_path
end
def reset_incoming_email_token
- if current_user.reset_incoming_email_token!
- flash[:notice] = "Incoming email token was successfully reset"
+ Users::UpdateService.new(@user).execute! do |user|
+ user.reset_incoming_email_token!
end
+ flash[:notice] = "Incoming email token was successfully reset"
+
redirect_to profile_account_path
end
def reset_rss_token
- if current_user.reset_rss_token!
- flash[:notice] = "RSS token was successfully reset"
+ Users::UpdateService.new(@user).execute! do |user|
+ user.reset_rss_token!
end
+ flash[:notice] = "RSS token was successfully reset"
+
redirect_to profile_account_path
end
@@ -55,12 +63,13 @@ class ProfilesController < Profiles::ApplicationController
end
def update_username
- if @user.update_attributes(username: user_params[:username])
- options = { notice: "Username successfully changed" }
- else
- message = @user.errors.full_messages.uniq.join('. ')
- options = { alert: "Username change failed - #{message}" }
- end
+ result = Users::UpdateService.new(@user, username: user_params[:username]).execute
+
+ options = if result[:status] == :success
+ { notice: "Username successfully changed" }
+ else
+ { alert: "Username change failed - #{result[:message]}" }
+ end
redirect_back_or_default(default: { action: 'show' }, options: options)
end
diff --git a/app/controllers/projects/pipelines_controller.rb b/app/controllers/projects/pipelines_controller.rb
index 8effb792689..303e91a8dc0 100644
--- a/app/controllers/projects/pipelines_controller.rb
+++ b/app/controllers/projects/pipelines_controller.rb
@@ -135,7 +135,12 @@ class Projects::PipelinesController < Projects::ApplicationController
@charts[:week] = Ci::Charts::WeekChart.new(project)
@charts[:month] = Ci::Charts::MonthChart.new(project)
@charts[:year] = Ci::Charts::YearChart.new(project)
- @charts[:build_times] = Ci::Charts::BuildTime.new(project)
+ @charts[:pipeline_times] = Ci::Charts::PipelineTime.new(project)
+
+ @counts = {}
+ @counts[:total] = @project.pipelines.count(:all)
+ @counts[:success] = @project.pipelines.success.count(:all)
+ @counts[:failed] = @project.pipelines.failed.count(:all)
end
private
diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb
index 0d8186dce02..f39441a281e 100644
--- a/app/controllers/sessions_controller.rb
+++ b/app/controllers/sessions_controller.rb
@@ -60,10 +60,11 @@ class SessionsController < Devise::SessionsController
return unless user && user.require_password?
- token = user.generate_reset_token
- user.save
+ Users::UpdateService.new(user).execute do |user|
+ @token = user.generate_reset_token
+ end
- redirect_to edit_user_password_path(reset_password_token: token),
+ redirect_to edit_user_password_path(reset_password_token: @token),
notice: "Please create a password for your new account."
end
diff --git a/app/finders/issues_finder.rb b/app/finders/issues_finder.rb
index b4c074bc69c..3da5508aefd 100644
--- a/app/finders/issues_finder.rb
+++ b/app/finders/issues_finder.rb
@@ -41,7 +41,7 @@ class IssuesFinder < IssuableFinder
def self.not_restricted_by_confidentiality(user)
return Issue.where('issues.confidential IS NOT TRUE') if user.blank?
- return Issue.all if user.admin?
+ return Issue.all if user.full_private_access?
Issue.where('
issues.confidential IS NOT TRUE
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index a3b243fccb7..dc7ff78f3df 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -300,4 +300,12 @@ module ApplicationHelper
"https://www.twitter.com/#{name}"
end
end
+
+ def can_toggle_new_nav?
+ Rails.env.development?
+ end
+
+ def show_new_nav?
+ cookies["new_nav"] == "true"
+ end
end
diff --git a/app/helpers/button_helper.rb b/app/helpers/button_helper.rb
index 00464810054..ba84dbe4a7a 100644
--- a/app/helpers/button_helper.rb
+++ b/app/helpers/button_helper.rb
@@ -50,10 +50,17 @@ module ButtonHelper
def http_clone_button(project, placement = 'right', append_link: true)
klass = 'http-selector'
- klass << ' has-tooltip' if current_user.try(:require_password?)
+ klass << ' has-tooltip' if current_user.try(:require_password?) || current_user.try(:require_personal_access_token?)
protocol = gitlab_config.protocol.upcase
+ tooltip_title =
+ if current_user.try(:require_password?)
+ _("Set a password on your account to pull or push via %{protocol}.") % { protocol: protocol }
+ else
+ _("Create a personal access token on your account to pull or push via %{protocol}.") % { protocol: protocol }
+ end
+
content_tag (append_link ? :a : :span), protocol,
class: klass,
href: (project.http_url_to_repo if append_link),
@@ -61,7 +68,7 @@ module ButtonHelper
html: true,
placement: placement,
container: 'body',
- title: _("Set a password on your account to pull or push via %{protocol}") % { protocol: protocol }
+ title: tooltip_title
}
end
diff --git a/app/helpers/graph_helper.rb b/app/helpers/graph_helper.rb
index c2ab80f2e0d..2e9b72e9613 100644
--- a/app/helpers/graph_helper.rb
+++ b/app/helpers/graph_helper.rb
@@ -17,13 +17,10 @@ module GraphHelper
ids.zip(parent_spaces)
end
- def success_ratio(success_builds, failed_builds)
- failed_builds = failed_builds.count(:all)
- success_builds = success_builds.count(:all)
+ def success_ratio(counts)
+ return 100 if counts[:failed].zero?
- return 100 if failed_builds.zero?
-
- ratio = (success_builds.to_f / (success_builds + failed_builds)) * 100
+ ratio = (counts[:success].to_f / (counts[:success] + counts[:failed])) * 100
ratio.to_i
end
end
diff --git a/app/helpers/labels_helper.rb b/app/helpers/labels_helper.rb
index 4e6e6805920..6baf6f31d8f 100644
--- a/app/helpers/labels_helper.rb
+++ b/app/helpers/labels_helper.rb
@@ -133,21 +133,28 @@ module LabelsHelper
end
end
+ def can_subscribe_to_label_in_different_levels?(label)
+ defined?(@project) && label.is_a?(GroupLabel)
+ end
+
def label_subscription_status(label, project)
- return 'project-level' if label.subscribed?(current_user, project)
return 'group-level' if label.subscribed?(current_user)
+ return 'project-level' if label.subscribed?(current_user, project)
'unsubscribed'
end
- def group_label_unsubscribe_path(label, project)
+ def toggle_subscription_label_path(label, project)
+ return toggle_subscription_group_label_path(label.group, label) unless project
+
case label_subscription_status(label, project)
- when 'project-level' then toggle_subscription_namespace_project_label_path(@project.namespace, @project, label)
when 'group-level' then toggle_subscription_group_label_path(label.group, label)
+ when 'project-level' then toggle_subscription_namespace_project_label_path(project.namespace, project, label)
+ when 'unsubscribed' then toggle_subscription_namespace_project_label_path(project.namespace, project, label)
end
end
- def label_subscription_toggle_button_text(label, project)
+ def label_subscription_toggle_button_text(label, project = nil)
label.subscribed?(current_user, project) ? 'Unsubscribe' : 'Subscribe'
end
diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb
index d10e0bd45b0..c04b1419a19 100644
--- a/app/helpers/projects_helper.rb
+++ b/app/helpers/projects_helper.rb
@@ -198,6 +198,23 @@ module ProjectsHelper
.load_in_batch_for_projects(projects)
end
+ def show_no_ssh_key_message?
+ cookies[:hide_no_ssh_message].blank? && !current_user.hide_no_ssh_key && current_user.require_ssh_key?
+ end
+
+ def show_no_password_message?
+ cookies[:hide_no_password_message].blank? && !current_user.hide_no_password &&
+ ( current_user.require_password? || current_user.require_personal_access_token? )
+ end
+
+ def link_to_set_password
+ if current_user.require_password?
+ link_to s_('SetPasswordToCloneLink|set a password'), edit_profile_password_path
+ else
+ link_to s_('CreateTokenToCloneLink|create a personal access token'), profile_personal_access_tokens_path
+ end
+ end
+
private
def repo_children_classes(field)
diff --git a/app/models/concerns/has_status.rb b/app/models/concerns/has_status.rb
index 3c9c6584e02..32af5566135 100644
--- a/app/models/concerns/has_status.rb
+++ b/app/models/concerns/has_status.rb
@@ -11,18 +11,21 @@ module HasStatus
class_methods do
def status_sql
- scope = respond_to?(:exclude_ignored) ? exclude_ignored : all
-
- builds = scope.select('count(*)').to_sql
- created = scope.created.select('count(*)').to_sql
- success = scope.success.select('count(*)').to_sql
- manual = scope.manual.select('count(*)').to_sql
- pending = scope.pending.select('count(*)').to_sql
- running = scope.running.select('count(*)').to_sql
- skipped = scope.skipped.select('count(*)').to_sql
- canceled = scope.canceled.select('count(*)').to_sql
+ scope_relevant = respond_to?(:exclude_ignored) ? exclude_ignored : all
+ scope_warnings = respond_to?(:failed_but_allowed) ? failed_but_allowed : none
+
+ builds = scope_relevant.select('count(*)').to_sql
+ created = scope_relevant.created.select('count(*)').to_sql
+ success = scope_relevant.success.select('count(*)').to_sql
+ manual = scope_relevant.manual.select('count(*)').to_sql
+ pending = scope_relevant.pending.select('count(*)').to_sql
+ running = scope_relevant.running.select('count(*)').to_sql
+ skipped = scope_relevant.skipped.select('count(*)').to_sql
+ canceled = scope_relevant.canceled.select('count(*)').to_sql
+ warnings = scope_warnings.select('count(*) > 0').to_sql.presence || 'false'
"(CASE
+ WHEN (#{builds})=(#{skipped}) AND (#{warnings}) THEN 'success'
WHEN (#{builds})=(#{skipped}) THEN 'skipped'
WHEN (#{builds})=(#{success}) THEN 'success'
WHEN (#{builds})=(#{created}) THEN 'created'
diff --git a/app/models/environment.rb b/app/models/environment.rb
index 7ad36f1d80c..66c96d0f586 100644
--- a/app/models/environment.rb
+++ b/app/models/environment.rb
@@ -45,6 +45,7 @@ class Environment < ActiveRecord::Base
.to_sql
order(Gitlab::Database.nulls_first_order("(#{max_deployment_id_sql})", 'ASC'))
end
+ scope :in_review_folder, -> { where(environment_type: "review") }
state_machine :state, initial: :available do
event :start do
diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb
index f581a25f093..c099d731082 100644
--- a/app/models/merge_request.rb
+++ b/app/models/merge_request.rb
@@ -771,6 +771,7 @@ class MergeRequest < ActiveRecord::Base
"refs/heads/#{source_branch}",
ref_path
)
+ update_column(:ref_fetched, true)
end
def ref_path
@@ -778,7 +779,13 @@ class MergeRequest < ActiveRecord::Base
end
def ref_fetched?
- project.repository.ref_exists?(ref_path)
+ super ||
+ begin
+ computed_value = project.repository.ref_exists?(ref_path)
+ update_column(:ref_fetched, true) if computed_value
+
+ computed_value
+ end
end
def ensure_ref_fetched
diff --git a/app/models/network/graph.rb b/app/models/network/graph.rb
index 59737bb6085..2bc00a082df 100644
--- a/app/models/network/graph.rb
+++ b/app/models/network/graph.rb
@@ -113,7 +113,7 @@ module Network
opts[:ref] = @commit.id if @filter_ref
- @repo.find_commits(opts)
+ Gitlab::Git::Commit.find_all(@repo.raw_repository, opts)
end
def commits_sort_by_ref
diff --git a/app/models/project.rb b/app/models/project.rb
index 2c2685875f8..1176bec8873 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -350,7 +350,10 @@ class Project < ActiveRecord::Base
project.run_after_commit { add_import_job }
end
- after_transition started: :finished, do: :reset_cache_and_import_attrs
+ after_transition started: :finished do |project, _|
+ project.reset_cache_and_import_attrs
+ project.perform_housekeeping
+ end
end
class << self
@@ -510,6 +513,18 @@ class Project < ActiveRecord::Base
remove_import_data
end
+ def perform_housekeeping
+ return unless repo_exists?
+
+ run_after_commit do
+ begin
+ Projects::HousekeepingService.new(self).execute
+ rescue Projects::HousekeepingService::LeaseTaken => e
+ Rails.logger.info("Could not perform housekeeping for project #{self.path_with_namespace} (#{self.id}): #{e}")
+ end
+ end
+ end
+
def remove_import_data
import_data&.destroy
end
@@ -689,7 +704,7 @@ class Project < ActiveRecord::Base
end
def last_activity_date
- last_activity_at || updated_at
+ last_repository_updated_at || last_activity_at || updated_at
end
def project_id
diff --git a/app/models/project_feature.rb b/app/models/project_feature.rb
index dde2a11440d..48edd0738ee 100644
--- a/app/models/project_feature.rb
+++ b/app/models/project_feature.rb
@@ -90,7 +90,7 @@ class ProjectFeature < ActiveRecord::Base
when DISABLED
false
when PRIVATE
- user && (project.team.member?(user) || user.admin?)
+ user && (project.team.member?(user) || user.full_private_access?)
when ENABLED
true
else
diff --git a/app/models/project_services/prometheus_service.rb b/app/models/project_services/prometheus_service.rb
index c9df678f97e..217f753f05f 100644
--- a/app/models/project_services/prometheus_service.rb
+++ b/app/models/project_services/prometheus_service.rb
@@ -60,7 +60,7 @@ class PrometheusService < MonitoringService
def deployment_metrics(deployment)
metrics = with_reactive_cache(Gitlab::Prometheus::Queries::DeploymentQuery.name, deployment.id, &method(:rename_data_to_metrics))
- metrics&.merge(deployment_time: created_at.to_i) || {}
+ metrics&.merge(deployment_time: deployment.created_at.to_i) || {}
end
def additional_environment_metrics(environment)
diff --git a/app/models/user.rb b/app/models/user.rb
index 954a30155f7..6dd1b1415d6 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -53,7 +53,7 @@ class User < ActiveRecord::Base
lease = Gitlab::ExclusiveLease.new("user_update_tracked_fields:#{id}", timeout: 1.hour.to_i)
return unless lease.try_obtain
- save(validate: false)
+ Users::UpdateService.new(self).execute(validate: false)
end
attr_accessor :force_random_password
@@ -494,10 +494,8 @@ class User < ActiveRecord::Base
def update_emails_with_primary_email
primary_email_record = emails.find_by(email: email)
if primary_email_record
- primary_email_record.destroy
- emails.create(email: email_was)
-
- update_secondary_emails!
+ Emails::DestroyService.new(self, email: email).execute
+ Emails::CreateService.new(self, email: email_was).execute
end
end
@@ -572,7 +570,13 @@ class User < ActiveRecord::Base
end
def require_password?
- password_automatically_set? && !ldap_user?
+ password_automatically_set? && !ldap_user? && current_application_settings.signin_enabled?
+ end
+
+ def require_personal_access_token?
+ return false if current_application_settings.signin_enabled? || ldap_user?
+
+ PersonalAccessTokensFinder.new(user: self, impersonation: false, state: 'active').execute.none?
end
def can_change_username?
@@ -965,7 +969,7 @@ class User < ActiveRecord::Base
if attempts_exceeded?
lock_access! unless access_locked?
else
- save(validate: false)
+ Users::UpdateService.new(self).execute(validate: false)
end
end
@@ -984,6 +988,12 @@ class User < ActiveRecord::Base
self.admin = (new_level == 'admin')
end
+ # Does the user have access to all private groups & projects?
+ # Overridden in EE to also check auditor?
+ def full_private_access?
+ admin?
+ end
+
def update_two_factor_requirement
periods = expanded_groups_requiring_two_factor_authentication.pluck(:two_factor_grace_period)
@@ -1123,7 +1133,8 @@ class User < ActiveRecord::Base
email: email,
&creation_block
)
- user.save(validate: false)
+
+ Users::UpdateService.new(user).execute(validate: false)
user
ensure
Gitlab::ExclusiveLease.cancel(lease_key, uuid)
diff --git a/app/services/emails/base_service.rb b/app/services/emails/base_service.rb
new file mode 100644
index 00000000000..ace49889097
--- /dev/null
+++ b/app/services/emails/base_service.rb
@@ -0,0 +1,8 @@
+module Emails
+ class BaseService
+ def initialize(user, opts)
+ @user = user
+ @email = opts[:email]
+ end
+ end
+end
diff --git a/app/services/emails/create_service.rb b/app/services/emails/create_service.rb
new file mode 100644
index 00000000000..b6491ee9804
--- /dev/null
+++ b/app/services/emails/create_service.rb
@@ -0,0 +1,7 @@
+module Emails
+ class CreateService < ::Emails::BaseService
+ def execute
+ @user.emails.create(email: @email)
+ end
+ end
+end
diff --git a/app/services/emails/destroy_service.rb b/app/services/emails/destroy_service.rb
new file mode 100644
index 00000000000..d586b9dfe0c
--- /dev/null
+++ b/app/services/emails/destroy_service.rb
@@ -0,0 +1,17 @@
+module Emails
+ class DestroyService < ::Emails::BaseService
+ def execute
+ Email.find_by_email!(@email).destroy && update_secondary_emails!
+ end
+
+ private
+
+ def update_secondary_emails!
+ result = ::Users::UpdateService.new(@user).execute do |user|
+ user.update_secondary_emails!
+ end
+
+ result[:status] == 'success'
+ end
+ end
+end
diff --git a/app/services/users/build_service.rb b/app/services/users/build_service.rb
index 363135ef09b..ff234a3440f 100644
--- a/app/services/users/build_service.rb
+++ b/app/services/users/build_service.rb
@@ -1,5 +1,4 @@
module Users
- # Service for building a new user.
class BuildService < BaseService
def initialize(current_user, params = {})
@current_user = current_user
diff --git a/app/services/users/create_service.rb b/app/services/users/create_service.rb
index e22f7225ae2..74abc017cea 100644
--- a/app/services/users/create_service.rb
+++ b/app/services/users/create_service.rb
@@ -1,5 +1,4 @@
module Users
- # Service for creating a new user.
class CreateService < BaseService
def initialize(current_user, params = {})
@current_user = current_user
diff --git a/app/services/users/update_service.rb b/app/services/users/update_service.rb
new file mode 100644
index 00000000000..dfbd6016c3f
--- /dev/null
+++ b/app/services/users/update_service.rb
@@ -0,0 +1,34 @@
+module Users
+ class UpdateService < BaseService
+ def initialize(user, params = {})
+ @user = user
+ @params = params.dup
+ end
+
+ def execute(validate: true, &block)
+ yield(@user) if block_given?
+
+ assign_attributes(&block)
+
+ if @user.save(validate: validate)
+ success
+ else
+ error(@user.errors.full_messages.uniq.join('. '))
+ end
+ end
+
+ def execute!(*args, &block)
+ result = execute(*args, &block)
+
+ raise ActiveRecord::RecordInvalid.new(@user) unless result[:status] == :success
+
+ true
+ end
+
+ private
+
+ def assign_attributes(&block)
+ @user.assign_attributes(params) if params.any?
+ end
+ end
+end
diff --git a/app/views/admin/runners/index.html.haml b/app/views/admin/runners/index.html.haml
index e242e851b4d..2da8f615470 100644
--- a/app/views/admin/runners/index.html.haml
+++ b/app/views/admin/runners/index.html.haml
@@ -58,20 +58,23 @@
%br
- .table-holder
- %table.table
- %thead
- %tr
- %th Type
- %th Runner token
- %th Description
- %th Version
- %th Projects
- %th Jobs
- %th Tags
- %th Last contact
- %th
+ - if @runners.any?
+ .table-holder
+ %table.table
+ %thead
+ %tr
+ %th Type
+ %th Runner token
+ %th Description
+ %th Version
+ %th Projects
+ %th Jobs
+ %th Tags
+ %th Last contact
+ %th
- - @runners.each do |runner|
- = render "admin/runners/runner", runner: runner
- = paginate @runners, theme: "gitlab"
+ - @runners.each do |runner|
+ = render "admin/runners/runner", runner: runner
+ = paginate @runners, theme: "gitlab"
+ - else
+ .nothing-here-block No runners found
diff --git a/app/views/groups/_home_panel.html.haml b/app/views/groups/_home_panel.html.haml
index 41f54f6bf42..181c7bee702 100644
--- a/app/views/groups/_home_panel.html.haml
+++ b/app/views/groups/_home_panel.html.haml
@@ -3,7 +3,7 @@
.avatar-container.s70.group-avatar
= image_tag group_icon(@group), class: "avatar s70 avatar-tile"
%h1.group-title
- @#{@group.path}
+ = @group.name
%span.visibility-icon.has-tooltip{ data: { container: 'body' }, title: visibility_icon_description(@group) }
= visibility_level_icon(@group.visibility_level, fw: false)
diff --git a/app/views/layouts/_head.html.haml b/app/views/layouts/_head.html.haml
index eea33b5966f..f7a1d7e8844 100644
--- a/app/views/layouts/_head.html.haml
+++ b/app/views/layouts/_head.html.haml
@@ -30,6 +30,9 @@
= stylesheet_link_tag "test", media: "all" if Rails.env.test?
= stylesheet_link_tag 'peek' if peek_enabled?
+ - if show_new_nav?
+ = stylesheet_link_tag "new_nav", media: "all"
+
= Gon::Base.render_data
= webpack_bundle_tag "runtime"
diff --git a/app/views/layouts/application.html.haml b/app/views/layouts/application.html.haml
index 2b07273a0a8..d879df8fc82 100644
--- a/app/views/layouts/application.html.haml
+++ b/app/views/layouts/application.html.haml
@@ -4,7 +4,10 @@
%body{ class: @body_class, data: { page: body_data_page, project: "#{@project.path if @project}", group: "#{@group.path if @group}" } }
= render "layouts/init_auto_complete" if @gfm_form
= render 'peek/bar'
- = render "layouts/header/default", title: header_title
+ - if show_new_nav?
+ = render "layouts/header/new"
+ - else
+ = render "layouts/header/default", title: header_title
= render 'layouts/page', sidebar: sidebar, nav: nav
= yield :scripts_body
diff --git a/app/views/layouts/header/_default.html.haml b/app/views/layouts/header/_default.html.haml
index 249253f4906..f056c0af968 100644
--- a/app/views/layouts/header/_default.html.haml
+++ b/app/views/layouts/header/_default.html.haml
@@ -74,6 +74,9 @@
= link_to "Profile", current_user, class: 'profile-link', data: { user: current_user.username }
%li
= link_to "Settings", profile_path
+ - if can_toggle_new_nav?
+ %li
+ = link_to "Turn on new nav", profile_preferences_path(anchor: "new-navigation")
%li.divider
%li
= link_to "Sign out", destroy_user_session_path, method: :delete, class: "sign-out-link"
diff --git a/app/views/layouts/header/_new.html.haml b/app/views/layouts/header/_new.html.haml
new file mode 100644
index 00000000000..c0833c64911
--- /dev/null
+++ b/app/views/layouts/header/_new.html.haml
@@ -0,0 +1,93 @@
+%header.navbar.navbar-gitlab.navbar-gitlab-new{ class: nav_header_class }
+ %a.sr-only.gl-accessibility{ href: "#content-body", tabindex: "1" } Skip to content
+ .container-fluid
+ .header-content
+ .title-container
+ %h1.title
+ = link_to root_path, title: 'Dashboard' do
+ = brand_header_logo
+ %span.hidden-xs
+ GitLab
+
+ - if current_user
+ = render "layouts/nav/new_dashboard"
+ - else
+ = render "layouts/nav/new_explore"
+
+ .navbar-collapse.collapse
+ %ul.nav.navbar-nav
+ %li.hidden-sm.hidden-xs
+ = render 'layouts/search' unless current_controller?(:search)
+ %li.visible-sm-inline-block.visible-xs-inline-block
+ = link_to search_path, title: 'Search', aria: { label: "Search" }, data: {toggle: 'tooltip', placement: 'bottom', container: 'body'} do
+ = icon('search')
+ - if current_user
+ - if session[:impersonator_id]
+ %li.impersonation
+ = link_to admin_impersonation_path, method: :delete, title: "Stop impersonation", aria: { label: 'Stop impersonation' }, data: { toggle: 'tooltip', placement: 'bottom', container: 'body' } do
+ = icon('user-secret fw')
+ - if current_user.admin?
+ %li
+ = link_to admin_root_path, title: 'Admin area', aria: { label: "Admin area" }, data: {toggle: 'tooltip', placement: 'bottom', container: 'body'} do
+ = icon('wrench fw')
+ = render 'layouts/header/new_dropdown'
+ - if Gitlab::Sherlock.enabled?
+ %li
+ = link_to sherlock_transactions_path, title: 'Sherlock Transactions',
+ data: {toggle: 'tooltip', placement: 'bottom', container: 'body'} do
+ = icon('tachometer fw')
+ %li
+ = link_to assigned_issues_dashboard_path, title: 'Issues', aria: { label: "Issues" }, data: {toggle: 'tooltip', placement: 'bottom', container: 'body'} do
+ = icon('hashtag fw')
+ - issues_count = assigned_issuables_count(:issues)
+ %span.badge.issues-count{ class: ('hidden' if issues_count.zero?) }
+ = number_with_delimiter(issues_count)
+ %li
+ = link_to assigned_mrs_dashboard_path, title: 'Merge requests', aria: { label: "Merge requests" }, data: {toggle: 'tooltip', placement: 'bottom', container: 'body'} do
+ = custom_icon('mr_bold')
+ - merge_requests_count = assigned_issuables_count(:merge_requests)
+ %span.badge.merge-requests-count{ class: ('hidden' if merge_requests_count.zero?) }
+ = number_with_delimiter(merge_requests_count)
+ %li
+ = link_to dashboard_todos_path, title: 'Todos', aria: { label: "Todos" }, class: 'shortcuts-todos', data: {toggle: 'tooltip', placement: 'bottom', container: 'body'} do
+ = icon('check-circle fw')
+ %span.badge.todos-count{ class: ('hidden' if todos_pending_count.zero?) }
+ = todos_count_format(todos_pending_count)
+ %li.header-user.dropdown
+ = link_to current_user, class: "header-user-dropdown-toggle", data: { toggle: "dropdown" } do
+ = image_tag avatar_icon(current_user, 26), width: 26, height: 26, class: "header-user-avatar"
+ = icon('chevron-down')
+ .dropdown-menu-nav.dropdown-menu-align-right
+ %ul
+ %li.current-user
+ .user-name.bold
+ = current_user.name
+ @#{current_user.username}
+ %li.divider
+ %li
+ = link_to "Profile", current_user, class: 'profile-link', data: { user: current_user.username }
+ %li
+ = link_to "Settings", profile_path
+ %li
+ = link_to "Turn off new nav", profile_preferences_path(anchor: "new-navigation")
+ %li.divider
+ %li
+ = link_to "Sign out", destroy_user_session_path, method: :delete, class: "sign-out-link"
+ - else
+ %li
+ %div
+ = link_to "Sign in", new_session_path(:user, redirect_to_referer: 'yes'), class: 'btn btn-sign-in btn-success'
+
+ %button.navbar-toggle.hidden-sm.hidden-md.hidden-lg{ type: 'button' }
+ %span.sr-only Toggle navigation
+ = icon('ellipsis-v', class: 'js-navbar-toggle-right')
+ = icon('times', class: 'js-navbar-toggle-left', style: 'display: none;')
+
+ = yield :header_content
+
+= render 'shared/outdated_browser'
+
+- if @project && !@project.empty_repo?
+ - if ref = @ref || @project.repository.root_ref
+ :javascript
+ var findFileURL = "#{namespace_project_find_file_path(@project.namespace, @project, ref)}";
diff --git a/app/views/layouts/header/_new_dropdown.haml b/app/views/layouts/header/_new_dropdown.haml
index 969c423b032..9ff1164f2ee 100644
--- a/app/views/layouts/header/_new_dropdown.haml
+++ b/app/views/layouts/header/_new_dropdown.haml
@@ -1,7 +1,11 @@
%li.header-new.dropdown
= link_to new_project_path, class: "header-new-dropdown-toggle has-tooltip", title: "New...", ref: 'tooltip', aria: { label: "New..." }, data: { toggle: 'dropdown', placement: 'bottom', container: 'body' } do
- = icon('plus fw')
- = icon('caret-down')
+ - if show_new_nav?
+ = icon('plus')
+ = icon('chevron-down')
+ - else
+ = icon('plus fw')
+ = icon('caret-down')
.dropdown-menu-nav.dropdown-menu-align-right
%ul
- if @group&.persisted?
diff --git a/app/views/layouts/nav/_new_dashboard.html.haml b/app/views/layouts/nav/_new_dashboard.html.haml
new file mode 100644
index 00000000000..7109baa4dad
--- /dev/null
+++ b/app/views/layouts/nav/_new_dashboard.html.haml
@@ -0,0 +1,33 @@
+%ul.list-unstyled.navbar-sub-nav
+ = nav_link(path: ['root#index', 'projects#trending', 'projects#starred', 'dashboard/projects#index'], html_options: {class: "home"}) do
+ = link_to dashboard_projects_path, title: 'Projects', class: 'dashboard-shortcuts-projects' do
+ Projects
+
+ = nav_link(controller: [:groups, 'groups/milestones', 'groups/group_members']) do
+ = link_to dashboard_groups_path, class: 'dashboard-shortcuts-groups', title: 'Groups' do
+ Groups
+
+ = nav_link(path: 'dashboard#activity', html_options: { class: "hidden-xs hidden-sm" }) do
+ = link_to activity_dashboard_path, class: 'dashboard-shortcuts-activity', title: 'Activity' do
+ Activity
+
+ %li.dropdown
+ %a{ href: "#", data: { toggle: "dropdown" } }
+ More
+ = icon("chevron-down", class: "dropdown-chevron")
+ .dropdown-menu
+ %ul
+ = nav_link(path: 'dashboard#activity', html_options: { class: "visible-xs visible-sm" }) do
+ = link_to activity_dashboard_path, title: 'Activity' do
+ Activity
+
+ = nav_link(controller: 'dashboard/milestones') do
+ = link_to dashboard_milestones_path, class: 'dashboard-shortcuts-milestones', title: 'Milestones' do
+ Milestones
+
+ = nav_link(controller: 'dashboard/snippets') do
+ = link_to dashboard_snippets_path, class: 'dashboard-shortcuts-snippets', title: 'Snippets' do
+ Snippets
+ %li.divider
+ %li
+ = link_to "Help", help_path, title: 'About GitLab CE'
diff --git a/app/views/layouts/nav/_new_explore.html.haml b/app/views/layouts/nav/_new_explore.html.haml
new file mode 100644
index 00000000000..40385f251e3
--- /dev/null
+++ b/app/views/layouts/nav/_new_explore.html.haml
@@ -0,0 +1,19 @@
+%ul.list-unstyled.navbar-sub-nav
+ = nav_link(path: ['dashboard#show', 'root#show', 'projects#trending', 'projects#starred', 'projects#index'], html_options: {class: 'home'}) do
+ = link_to explore_root_path, title: 'Projects', class: 'dashboard-shortcuts-projects' do
+ Projects
+ = nav_link(controller: [:groups, 'groups/milestones', 'groups/group_members']) do
+ = link_to explore_groups_path, title: 'Groups', class: 'dashboard-shortcuts-groups' do
+ Groups
+ %li.dropdown
+ %a{ href: "#", data: { toggle: "dropdown" } }
+ More
+ = icon("chevron-down", class: "dropdown-chevron")
+ .dropdown-menu
+ %ul
+ = nav_link(controller: :snippets) do
+ = link_to explore_snippets_path, title: 'Snippets', class: 'dashboard-shortcuts-snippets' do
+ Snippets
+ %li.divider
+ %li
+ = link_to "Help", help_path, title: 'About GitLab CE'
diff --git a/app/views/profiles/preferences/show.html.haml b/app/views/profiles/preferences/show.html.haml
index 0ff19b3eab1..0b5995415e9 100644
--- a/app/views/profiles/preferences/show.html.haml
+++ b/app/views/profiles/preferences/show.html.haml
@@ -15,6 +15,25 @@
.preview= image_tag "#{scheme.css_class}-scheme-preview.png"
= f.radio_button :color_scheme_id, scheme.id
= scheme.name
+ - if can_toggle_new_nav?
+ .col-sm-12
+ %hr
+ .col-lg-3.profile-settings-sidebar#new-navigation
+ %h4.prepend-top-0
+ New Navigation
+ %p
+ This setting allows you to turn on or off the new upcoming navigation concept.
+ = succeed '.' do
+ = link_to 'Learn more', '', target: '_blank'
+ .col-lg-9.syntax-theme
+ = label_tag do
+ .preview= image_tag "old_nav.png"
+ %input.js-experiment-feature-toggle{ type: "radio", value: "false", name: "new_nav", checked: !show_new_nav? }
+ Old
+ = label_tag do
+ .preview= image_tag "new_nav.png"
+ %input.js-experiment-feature-toggle{ type: "radio", value: "true", name: "new_nav", checked: show_new_nav? }
+ New
.col-sm-12
%hr
.col-lg-3.profile-settings-sidebar
diff --git a/app/views/profiles/show.html.haml b/app/views/profiles/show.html.haml
index 087ae778b0f..819c98946ab 100644
--- a/app/views/profiles/show.html.haml
+++ b/app/views/profiles/show.html.haml
@@ -48,7 +48,7 @@
= f.text_field :id, readonly: true, label: 'User ID', wrapper: { class: 'col-md-3' }
- if @user.external_email?
- = f.text_field :email, required: true, readonly: true, help: 'Your email address was automatically set based on your #{email_provider_label} account.'
+ = f.text_field :email, required: true, readonly: true, help: "Your email address was automatically set based on your #{email_provider_label} account."
- else
= f.text_field :email, required: true, value: (@user.email unless @user.temp_oauth_email?),
help: user_email_help_text(@user)
diff --git a/app/views/projects/blame/show.html.haml b/app/views/projects/blame/show.html.haml
index ce937ee1842..3627f72f5e1 100644
--- a/app/views/projects/blame/show.html.haml
+++ b/app/views/projects/blame/show.html.haml
@@ -1,6 +1,6 @@
- @no_container = true
- project_duration = age_map_duration(@blame_groups, @project)
-- page_title "Annotate", @blob.path, @ref
+- page_title "Blame", @blob.path, @ref
= render "projects/commits/head"
%div{ class: container_class }
diff --git a/app/views/projects/blob/_breadcrumb.html.haml b/app/views/projects/blob/_breadcrumb.html.haml
index 5840e9863f4..2c944b516a4 100644
--- a/app/views/projects/blob/_breadcrumb.html.haml
+++ b/app/views/projects/blob/_breadcrumb.html.haml
@@ -27,7 +27,7 @@
= link_to 'Normal view', namespace_project_blob_path(@project.namespace, @project, @id),
class: 'btn'
- else
- = link_to 'Annotate', namespace_project_blame_path(@project.namespace, @project, @id),
+ = link_to 'Blame', namespace_project_blame_path(@project.namespace, @project, @id),
class: 'btn js-blob-blame-link' unless blob.empty?
= link_to 'History', namespace_project_commits_path(@project.namespace, @project, @id),
diff --git a/app/views/projects/commits/_commit.html.haml b/app/views/projects/commits/_commit.html.haml
index 11de6915961..8a4ef5a45b3 100644
--- a/app/views/projects/commits/_commit.html.haml
+++ b/app/views/projects/commits/_commit.html.haml
@@ -5,7 +5,7 @@
- notes = commit.notes
- note_count = notes.user.count
-- cache_key = [project.path_with_namespace, commit.id, current_application_settings, note_count]
+- cache_key = [project.path_with_namespace, commit.id, current_application_settings, note_count, @path.presence, current_controller?(:commits)]
- cache_key.push(commit.status(ref)) if commit.status(ref)
= cache(cache_key, expires_in: 1.day) do
diff --git a/app/views/projects/deployments/_deployment.html.haml b/app/views/projects/deployments/_deployment.html.haml
index 26f3c297260..520696b01c6 100644
--- a/app/views/projects/deployments/_deployment.html.haml
+++ b/app/views/projects/deployments/_deployment.html.haml
@@ -11,11 +11,14 @@
.table-mobile-header{ role: 'rowheader' } Job
- if deployment.deployable
.table-mobile-content
- = link_to [@project.namespace.becomes(Namespace), @project, deployment.deployable], class: 'build-link' do
- #{deployment.deployable.name} (##{deployment.deployable.id})
+ .flex-truncate-parent
+ .flex-truncate-child
+ = link_to [@project.namespace.becomes(Namespace), @project, deployment.deployable], class: 'build-link' do
+ #{deployment.deployable.name} (##{deployment.deployable.id})
- if deployment.user
- by
- = user_avatar(user: deployment.user, size: 20)
+ %div
+ by
+ = user_avatar(user: deployment.user, size: 20)
.table-section.section-15{ role: 'gridcell' }
.table-mobile-header{ role: 'rowheader' } Created
diff --git a/app/views/projects/environments/show.html.haml b/app/views/projects/environments/show.html.haml
index 23aa4c29e69..31e2bb11ce8 100644
--- a/app/views/projects/environments/show.html.haml
+++ b/app/views/projects/environments/show.html.haml
@@ -31,8 +31,8 @@
.ci-table.environments{ role: 'grid' }
.gl-responsive-table-row.table-row-header{ role: 'row' }
.table-section.section-10{ role: 'columnheader' } ID
- .table-section.section-40{ role: 'columnheader' } Commit
- .table-section.section-15{ role: 'columnheader' } Job
+ .table-section.section-30{ role: 'columnheader' } Commit
+ .table-section.section-25{ role: 'columnheader' } Job
.table-section.section-15{ role: 'columnheader' } Created
= render @deployments
diff --git a/app/views/projects/issues/_merge_requests.html.haml b/app/views/projects/issues/_merge_requests.html.haml
index d48923b422a..bda52fe461c 100644
--- a/app/views/projects/issues/_merge_requests.html.haml
+++ b/app/views/projects/issues/_merge_requests.html.haml
@@ -14,7 +14,7 @@
= merge_request.to_reference
%span.merge-request-info
%strong
- = link_to_gfm merge_request.title, merge_request_path(merge_request), class: "row_title"
+ = link_to merge_request.title, merge_request_path(merge_request), class: "row_title"
- unless @issue.project.id == merge_request.target_project.id
in
- project = merge_request.target_project
diff --git a/app/views/projects/pipelines/charts.html.haml b/app/views/projects/pipelines/charts.html.haml
index 4a5043aac3c..8ffddfe6154 100644
--- a/app/views/projects/pipelines/charts.html.haml
+++ b/app/views/projects/pipelines/charts.html.haml
@@ -15,7 +15,7 @@
.col-md-6
= render 'projects/pipelines/charts/overall'
.col-md-6
- = render 'projects/pipelines/charts/build_times'
+ = render 'projects/pipelines/charts/pipeline_times'
%hr
- = render 'projects/pipelines/charts/builds'
+ = render 'projects/pipelines/charts/pipelines'
diff --git a/app/views/projects/pipelines/charts/_overall.haml b/app/views/projects/pipelines/charts/_overall.haml
index 0b7e3d22dd7..93083397d5b 100644
--- a/app/views/projects/pipelines/charts/_overall.haml
+++ b/app/views/projects/pipelines/charts/_overall.haml
@@ -2,18 +2,14 @@
%ul
%li
Total:
- %strong= pluralize @project.builds.count(:all), 'job'
+ %strong= pluralize @counts[:total], 'pipeline'
%li
Successful:
- %strong= pluralize @project.builds.success.count(:all), 'job'
+ %strong= pluralize @counts[:success], 'pipeline'
%li
Failed:
- %strong= pluralize @project.builds.failed.count(:all), 'job'
+ %strong= pluralize @counts[:failed], 'pipeline'
%li
Success ratio:
%strong
- #{success_ratio(@project.builds.success, @project.builds.failed)}%
- %li
- Commits covered:
- %strong
- = @project.pipelines.count(:all)
+ #{success_ratio(@counts)}%
diff --git a/app/views/projects/pipelines/charts/_build_times.haml b/app/views/projects/pipelines/charts/_pipeline_times.haml
index bb0975a9535..aee7c5492aa 100644
--- a/app/views/projects/pipelines/charts/_build_times.haml
+++ b/app/views/projects/pipelines/charts/_pipeline_times.haml
@@ -6,7 +6,7 @@
:javascript
var data = {
- labels : #{@charts[:build_times].labels.to_json},
+ labels : #{@charts[:pipeline_times].labels.to_json},
datasets : [
{
fillColor : "rgba(220,220,220,0.5)",
@@ -14,7 +14,7 @@
barStrokeWidth: 1,
barValueSpacing: 1,
barDatasetSpacing: 1,
- data : #{@charts[:build_times].build_times.to_json}
+ data : #{@charts[:pipeline_times].pipeline_times.to_json}
}
]
}
diff --git a/app/views/projects/pipelines/charts/_builds.haml b/app/views/projects/pipelines/charts/_pipelines.haml
index b6f453b9736..b6f453b9736 100644
--- a/app/views/projects/pipelines/charts/_builds.haml
+++ b/app/views/projects/pipelines/charts/_pipelines.haml
diff --git a/app/views/shared/_label.html.haml b/app/views/shared/_label.html.haml
index c185e9b73ee..de0281e97c6 100644
--- a/app/views/shared/_label.html.haml
+++ b/app/views/shared/_label.html.haml
@@ -1,12 +1,13 @@
- label_css_id = dom_id(label)
- status = label_subscription_status(label, @project).inquiry if current_user
- subject = local_assigns[:subject]
+- toggle_subscription_path = toggle_subscription_label_path(label, @project) if current_user
%li{ id: label_css_id, data: { id: label.id } }
= render "shared/label_row", label: label
.visible-xs.visible-sm-inline-block.visible-md-inline-block.dropdown
- %button.btn.btn-default.label-options-toggle{ data: { toggle: "dropdown" } }
+ %button.btn.btn-default.label-options-toggle{ type: 'button', data: { toggle: "dropdown" } }
Options
= icon('caret-down')
.dropdown-menu.dropdown-menu-align-right
@@ -17,18 +18,18 @@
%li
= link_to_label(label, subject: subject) do
view open issues
- - if current_user && defined?(@project)
+ - if current_user
%li.label-subscription
- - if label.is_a?(ProjectLabel)
- %a.js-subscribe-button.label-subscribe-button{ role: 'button', href: '#', data: { status: status, url: toggle_subscription_namespace_project_label_path(@project.namespace, @project, label) } }
- %span= label_subscription_toggle_button_text(label, @project)
- - else
- %a.js-unsubscribe-button.label-subscribe-button{ role: 'button', href: '#', class: ('hidden' if status.unsubscribed?), data: { url: group_label_unsubscribe_path(label, @project) } }
+ - if can_subscribe_to_label_in_different_levels?(label)
+ %a.js-unsubscribe-button.label-subscribe-button{ role: 'button', href: '#', class: ('hidden' if status.unsubscribed?), data: { url: toggle_subscription_path } }
%span Unsubscribe
%a.js-subscribe-button.label-subscribe-button{ role: 'button', href: '#', class: ('hidden' unless status.unsubscribed?), data: { url: toggle_subscription_namespace_project_label_path(@project.namespace, @project, label) } }
%span Subscribe at project level
%a.js-subscribe-button.label-subscribe-button{ role: 'button', href: '#', class: ('hidden' unless status.unsubscribed?), data: { url: toggle_subscription_group_label_path(label.group, label) } }
%span Subscribe at group level
+ - else
+ %a.js-subscribe-button.label-subscribe-button{ role: 'button', href: '#', data: { status: status, url: toggle_subscription_path } }
+ %span= label_subscription_toggle_button_text(label, @project)
- if can?(current_user, :admin_label, label)
%li
@@ -42,14 +43,10 @@
= link_to_label(label, subject: subject, css_class: 'btn btn-transparent btn-action') do
view open issues
- - if current_user && defined?(@project)
+ - if current_user
.label-subscription.inline
- - if label.is_a?(ProjectLabel)
- %button.js-subscribe-button.label-subscribe-button.btn.btn-default{ type: 'button', data: { status: status, url: toggle_subscription_namespace_project_label_path(@project.namespace, @project, label) } }
- %span= label_subscription_toggle_button_text(label, @project)
- = icon('spinner spin', class: 'label-subscribe-button-loading')
- - else
- %button.js-unsubscribe-button.label-subscribe-button.btn.btn-default{ type: 'button', class: ('hidden' if status.unsubscribed?), data: { url: group_label_unsubscribe_path(label, @project) } }
+ - if can_subscribe_to_label_in_different_levels?(label)
+ %button.js-unsubscribe-button.label-subscribe-button.btn.btn-default{ type: 'button', class: ('hidden' if status.unsubscribed?), data: { url: toggle_subscription_path } }
%span Unsubscribe
= icon('spinner spin', class: 'label-subscribe-button-loading')
@@ -59,10 +56,14 @@
= icon('chevron-down')
%ul.dropdown-menu
%li
- %a.js-subscribe-button{ data: { url: toggle_subscription_namespace_project_label_path(@project.namespace, @project, label) } }
+ %a.js-subscribe-button{ class: ('hidden' unless status.unsubscribed?), data: { url: toggle_subscription_namespace_project_label_path(@project.namespace, @project, label) } }
Project level
- %a.js-subscribe-button{ data: { url: toggle_subscription_group_label_path(label.group, label) } }
+ %a.js-subscribe-button{ class: ('hidden' unless status.unsubscribed?), data: { url: toggle_subscription_group_label_path(label.group, label) } }
Group level
+ - else
+ %button.js-subscribe-button.label-subscribe-button.btn.btn-default{ type: 'button', data: { status: status, url: toggle_subscription_path } }
+ %span= label_subscription_toggle_button_text(label, @project)
+ = icon('spinner spin', class: 'label-subscribe-button-loading')
- if label.is_a?(ProjectLabel) && label.project.group && can?(current_user, :admin_label, label.project.group)
= link_to promote_namespace_project_label_path(label.project.namespace, label.project, label), title: "Promote to Group Label", class: 'btn btn-transparent btn-action', data: {confirm: "Promoting this label will make this label available to all projects inside this group. Existing project labels with the same name will be merged. Are you sure?", toggle: "tooltip"}, method: :post do
@@ -76,10 +77,10 @@
%span.sr-only Delete
= icon('trash-o')
- - if current_user && defined?(@project)
- - if label.is_a?(ProjectLabel)
+ - if current_user
+ - if can_subscribe_to_label_in_different_levels?(label)
:javascript
- new gl.ProjectLabelSubscription('##{dom_id(label)} .label-subscription');
+ new gl.GroupLabelSubscription('##{dom_id(label)} .label-subscription');
- else
:javascript
- new gl.GroupLabelSubscription('##{dom_id(label)} .label-subscription');
+ new gl.ProjectLabelSubscription('##{dom_id(label)} .label-subscription');
diff --git a/app/views/shared/_label_row.html.haml b/app/views/shared/_label_row.html.haml
index d28f9421ecf..7b599dff0e3 100644
--- a/app/views/shared/_label_row.html.haml
+++ b/app/views/shared/_label_row.html.haml
@@ -4,9 +4,9 @@
= icon('bars')
.js-toggle-priority.toggle-priority{ data: { url: remove_priority_namespace_project_label_path(@project.namespace, @project, label),
dom_id: dom_id(label), type: label.type } }
- %button.add-priority.btn.has-tooltip{ title: 'Prioritize', :'data-placement' => 'top' }
+ %button.add-priority.btn.has-tooltip{ title: 'Prioritize', type: 'button', :'data-placement' => 'top' }
= icon('star-o')
- %button.remove-priority.btn.has-tooltip{ title: 'Remove priority', :'data-placement' => 'top' }
+ %button.remove-priority.btn.has-tooltip{ title: 'Remove priority', type: 'button', :'data-placement' => 'top' }
= icon('star')
%span.label-name
= link_to_label(label, subject: @project, tooltip: false)
diff --git a/app/views/shared/_no_password.html.haml b/app/views/shared/_no_password.html.haml
index b561e6dc248..9b1a467df6b 100644
--- a/app/views/shared/_no_password.html.haml
+++ b/app/views/shared/_no_password.html.haml
@@ -1,9 +1,8 @@
-- if cookies[:hide_no_password_message].blank? && !current_user.hide_no_password && current_user.require_password?
+- if show_no_password_message?
.no-password-message.alert.alert-warning
- - set_password_link = link_to s_('SetPasswordToCloneLink|set a password'), edit_profile_password_path
- - translation_params = { protocol: gitlab_config.protocol.upcase, set_password_link: set_password_link }
+ - translation_params = { protocol: gitlab_config.protocol.upcase, set_password_link: link_to_set_password }
- set_password_message = _("You won't be able to pull or push project code via %{protocol} until you %{set_password_link} on your account") % translation_params
-
+ = set_password_message.html_safe
.alert-link-group
= link_to _("Don't show again"), profile_path(user: {hide_no_password: true}), method: :put
|
diff --git a/app/views/shared/_no_ssh.html.haml b/app/views/shared/_no_ssh.html.haml
index e7815e28017..17ef5327341 100644
--- a/app/views/shared/_no_ssh.html.haml
+++ b/app/views/shared/_no_ssh.html.haml
@@ -1,8 +1,8 @@
-- if cookies[:hide_no_ssh_message].blank? && !current_user.hide_no_ssh_key && current_user.require_ssh_key?
+- if show_no_ssh_key_message?
.no-ssh-key-message.alert.alert-warning
- add_ssh_key_link = link_to s_('MissingSSHKeyWarningLink|add an SSH key'), profile_keys_path, class: 'alert-link'
- ssh_message = _("You won't be able to pull or push project code via SSH until you %{add_ssh_key_link} to your profile") % { add_ssh_key_link: add_ssh_key_link }
- #{ ssh_message.html_safe }
+ = ssh_message.html_safe
.alert-link-group
= link_to _("Don't show again"), profile_path(user: {hide_no_ssh_key: true}), method: :put, class: 'alert-link'
|
diff --git a/app/views/shared/issuable/_sidebar.html.haml b/app/views/shared/issuable/_sidebar.html.haml
index e49bd5ebb13..745f1ee62da 100644
--- a/app/views/shared/issuable/_sidebar.html.haml
+++ b/app/views/shared/issuable/_sidebar.html.haml
@@ -3,7 +3,7 @@
= page_specific_javascript_bundle_tag('common_vue')
= page_specific_javascript_bundle_tag('sidebar')
-%aside.right-sidebar.js-right-sidebar{ data: { "offset-top" => "50", "spy" => "affix" }, class: sidebar_gutter_collapsed_class, 'aria-live' => 'polite' }
+%aside.right-sidebar.js-right-sidebar{ data: { "offset-top" => "50", "spy" => "affix", signed: { in: current_user.present? } }, class: sidebar_gutter_collapsed_class, 'aria-live' => 'polite' }
.issuable-sidebar{ data: { endpoint: "#{issuable_json_path(issuable)}" } }
- can_edit_issuable = can?(current_user, :"admin_#{issuable.to_ability_name}", @project)
.block.issuable-sidebar-header
@@ -20,7 +20,7 @@
.block.todo.hide-expanded
= render "shared/issuable/sidebar_todo", todo: todo, issuable: issuable, is_collapsed: true
.block.assignee
- = render "shared/issuable/sidebar_assignees", issuable: issuable, can_edit_issuable: can_edit_issuable
+ = render "shared/issuable/sidebar_assignees", issuable: issuable, can_edit_issuable: can_edit_issuable, signed_in: current_user.present?
.block.milestone
.sidebar-collapsed-icon
= icon('clock-o', 'aria-hidden': 'true')
diff --git a/app/views/shared/issuable/_sidebar_assignees.html.haml b/app/views/shared/issuable/_sidebar_assignees.html.haml
index bcfa1dc826e..2ea5eb960c0 100644
--- a/app/views/shared/issuable/_sidebar_assignees.html.haml
+++ b/app/views/shared/issuable/_sidebar_assignees.html.haml
@@ -1,5 +1,5 @@
- if issuable.is_a?(Issue)
- #js-vue-sidebar-assignees{ data: { field: "#{issuable.to_ability_name}[assignee_ids]" } }
+ #js-vue-sidebar-assignees{ data: { field: "#{issuable.to_ability_name}[assignee_ids]", signed_in: signed_in } }
.title.hide-collapsed
Assignee
= icon('spinner spin')
@@ -14,6 +14,9 @@
= icon('spinner spin', class: 'hidden block-loading', 'aria-hidden': 'true')
- if can_edit_issuable
= link_to 'Edit', '#', class: 'edit-link pull-right'
+ - if !signed_in
+ %a.gutter-toggle.pull-right.js-sidebar-toggle{ role: "button", href: "#", "aria-label" => "Toggle sidebar" }
+ = sidebar_gutter_toggle_icon
.value.hide-collapsed
- if issuable.assignee
= link_to_member(@project, issuable.assignee, size: 32, extra_class: 'bold') do
diff --git a/app/views/shared/milestones/_issuable.html.haml b/app/views/shared/milestones/_issuable.html.haml
index 22547a30cdf..a7c67ac9980 100644
--- a/app/views/shared/milestones/_issuable.html.haml
+++ b/app/views/shared/milestones/_issuable.html.haml
@@ -16,7 +16,7 @@
%strong #{project.name_with_namespace} &middot;
- if issuable.is_a?(Issue)
= confidential_icon(issuable)
- = link_to_gfm issuable.title, issuable_url_args, title: issuable.title
+ = link_to issuable.title, issuable_url_args, title: issuable.title
.issuable-detail
= link_to [project.namespace.becomes(Namespace), project, issuable] do
%span.issuable-number= issuable.to_reference
diff --git a/app/views/shared/milestones/_milestone.html.haml b/app/views/shared/milestones/_milestone.html.haml
index 9e6a76e1ddb..680e1f3a4ea 100644
--- a/app/views/shared/milestones/_milestone.html.haml
+++ b/app/views/shared/milestones/_milestone.html.haml
@@ -4,7 +4,7 @@
%li{ class: "milestone milestone-#{milestone.closed? ? 'closed' : 'open'}", id: custom_dom_id }
.row
.col-sm-6
- %strong= link_to_gfm truncate(milestone.title, length: 100), milestone_path
+ %strong= link_to truncate(milestone.title, length: 100), milestone_path
.col-sm-6
.pull-right.light #{milestone.percent_complete(current_user)}% complete
.row
diff --git a/app/views/shared/projects/_project.html.haml b/app/views/shared/projects/_project.html.haml
index fbc335f6176..8c3d6351ac2 100644
--- a/app/views/shared/projects/_project.html.haml
+++ b/app/views/shared/projects/_project.html.haml
@@ -7,7 +7,7 @@
- show_last_commit_as_description = false unless local_assigns[:show_last_commit_as_description] == true && project.commit
- css_class += " no-description" if project.description.blank? && !show_last_commit_as_description
- cache_key = project_list_cache_key(project)
-- updated_tooltip = time_ago_with_tooltip(project.last_activity_at)
+- updated_tooltip = time_ago_with_tooltip(project.last_activity_date)
%li.project-row{ class: css_class }
= cache(cache_key) do
diff --git a/bin/ci/upgrade.rb b/bin/ci/upgrade.rb
deleted file mode 100755
index aab4f60ec60..00000000000
--- a/bin/ci/upgrade.rb
+++ /dev/null
@@ -1,3 +0,0 @@
-require_relative "../lib/ci/upgrader"
-
-Ci::Upgrader.new.execute
diff --git a/changelogs/unreleased/10378-promote-blameless-culture.yml b/changelogs/unreleased/10378-promote-blameless-culture.yml
deleted file mode 100644
index 8cf64dfd793..00000000000
--- a/changelogs/unreleased/10378-promote-blameless-culture.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Changed Blame to Annotate in the UI to promote blameless culture
-merge_request: 10378
-author: Ilya Vassilevsky
diff --git a/changelogs/unreleased/12614-fix-long-message-from-mr.yml b/changelogs/unreleased/12614-fix-long-message-from-mr.yml
deleted file mode 100644
index 30408ea4216..00000000000
--- a/changelogs/unreleased/12614-fix-long-message-from-mr.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Implement web hook logging
-merge_request: 11027
-author: Alexander Randa
diff --git a/changelogs/unreleased/12614-fix-long-message.yml b/changelogs/unreleased/12614-fix-long-message.yml
deleted file mode 100644
index 94f8127c3c1..00000000000
--- a/changelogs/unreleased/12614-fix-long-message.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Fix long urls in the title of commit
-merge_request: 10938
-author: Alexander Randa
diff --git a/changelogs/unreleased/12910-snippets-description.yml b/changelogs/unreleased/12910-snippets-description.yml
deleted file mode 100644
index ac3d754fee1..00000000000
--- a/changelogs/unreleased/12910-snippets-description.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Support descriptions for snippets
-merge_request:
-author:
diff --git a/changelogs/unreleased/14707-allow-activity-feed-to-be-accessible-through-api.yml b/changelogs/unreleased/14707-allow-activity-feed-to-be-accessible-through-api.yml
deleted file mode 100644
index 9c17c3b949c..00000000000
--- a/changelogs/unreleased/14707-allow-activity-feed-to-be-accessible-through-api.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Introduce an Events API
-merge_request: 11755
-author:
diff --git a/changelogs/unreleased/17489-hide-code-from-guests.yml b/changelogs/unreleased/17489-hide-code-from-guests.yml
deleted file mode 100644
index eb6daffedfe..00000000000
--- a/changelogs/unreleased/17489-hide-code-from-guests.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Hide clone panel and file list when user is only a guest
-merge_request:
-author: James Clark
diff --git a/changelogs/unreleased/18927-reorder-issue-action-buttons.yml b/changelogs/unreleased/18927-reorder-issue-action-buttons.yml
deleted file mode 100644
index 793d6582940..00000000000
--- a/changelogs/unreleased/18927-reorder-issue-action-buttons.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Reorder Issue action buttons in order of usability
-merge_request: 11642
-author:
diff --git a/changelogs/unreleased/19107-404-when-creating-new-milestone-or-issue-for-project-that-has-issues-disabled.yml b/changelogs/unreleased/19107-404-when-creating-new-milestone-or-issue-for-project-that-has-issues-disabled.yml
deleted file mode 100644
index bec9aa34761..00000000000
--- a/changelogs/unreleased/19107-404-when-creating-new-milestone-or-issue-for-project-that-has-issues-disabled.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: 'New issue'/'New merge request' dropdowns should show only projects with issues/merge requests feature enabled
-merge_request: 19107
-author: blackst0ne
diff --git a/changelogs/unreleased/20517-delete-projects-issuescontroller-redirect_old.yml b/changelogs/unreleased/20517-delete-projects-issuescontroller-redirect_old.yml
deleted file mode 100644
index 1f3ab3a2c10..00000000000
--- a/changelogs/unreleased/20517-delete-projects-issuescontroller-redirect_old.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Remove redirect for old issue url containing id instead of iid
-merge_request: 11135
-author: blackst0ne
diff --git a/changelogs/unreleased/23036-replace-all-spinach-tests-with-rspec-feature-tests.yml b/changelogs/unreleased/23036-replace-all-spinach-tests-with-rspec-feature-tests.yml
deleted file mode 100644
index b350b27d863..00000000000
--- a/changelogs/unreleased/23036-replace-all-spinach-tests-with-rspec-feature-tests.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Replace 'starred_projects.feature' spinach test with an rspec analog
-merge_request: 11752
-author: blackst0ne
diff --git a/changelogs/unreleased/23036-replace-dashboard-mr-spinach.yml b/changelogs/unreleased/23036-replace-dashboard-mr-spinach.yml
new file mode 100644
index 00000000000..07c201de96e
--- /dev/null
+++ b/changelogs/unreleased/23036-replace-dashboard-mr-spinach.yml
@@ -0,0 +1,4 @@
+---
+title: Replace 'dashboard/merge_requests' spinach with rspec
+merge_request: 12440
+author: Alexander Randa (@randaalex)
diff --git a/changelogs/unreleased/23036-replace-dashboard-todo-spinach.yml b/changelogs/unreleased/23036-replace-dashboard-todo-spinach.yml
new file mode 100644
index 00000000000..65df9a836a5
--- /dev/null
+++ b/changelogs/unreleased/23036-replace-dashboard-todo-spinach.yml
@@ -0,0 +1,4 @@
+---
+title: Replace 'dashboard/todos' spinach with rspec
+merge_request: 12453
+author: Alexander Randa (@randaalex)
diff --git a/changelogs/unreleased/23603-add-extra-functionality-for-the-top-right-button.yml b/changelogs/unreleased/23603-add-extra-functionality-for-the-top-right-button.yml
deleted file mode 100644
index 77f8e31e16e..00000000000
--- a/changelogs/unreleased/23603-add-extra-functionality-for-the-top-right-button.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Add extra context-sensitive functionality for the top right menu button
-merge_request: 11632
-author:
diff --git a/changelogs/unreleased/24032-when-changing-project-visibility-setting-change-other-dropdowns-automatically.yml b/changelogs/unreleased/24032-when-changing-project-visibility-setting-change-other-dropdowns-automatically.yml
deleted file mode 100644
index dbd8a538d51..00000000000
--- a/changelogs/unreleased/24032-when-changing-project-visibility-setting-change-other-dropdowns-automatically.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Automatically adjust project settings to match changes in project visibility
-merge_request: 11831
-author:
diff --git a/changelogs/unreleased/24196-protected-variables.yml b/changelogs/unreleased/24196-protected-variables.yml
deleted file mode 100644
index 71567a9d794..00000000000
--- a/changelogs/unreleased/24196-protected-variables.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Add protected variables which would only be passed to protected branches or
- protected tags
-merge_request: 11688
-author:
diff --git a/changelogs/unreleased/24373-warning-message-go-away.yml b/changelogs/unreleased/24373-warning-message-go-away.yml
deleted file mode 100644
index c0f2fd260ba..00000000000
--- a/changelogs/unreleased/24373-warning-message-go-away.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: 'Notes: Warning message should go away once resolved'
-merge_request: 10823
-author: Jacopo Beschi @jacopo-beschi
diff --git a/changelogs/unreleased/25373-jira-links.yml b/changelogs/unreleased/25373-jira-links.yml
deleted file mode 100644
index 09589d4b992..00000000000
--- a/changelogs/unreleased/25373-jira-links.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Don’t create comment on JIRA if it already exists for the entity
-merge_request:
-author:
diff --git a/changelogs/unreleased/25426-group-dashboard-ui.yml b/changelogs/unreleased/25426-group-dashboard-ui.yml
deleted file mode 100644
index cc2bf62d07b..00000000000
--- a/changelogs/unreleased/25426-group-dashboard-ui.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Update Dashboard Groups UI with better support for subgroups
-merge_request:
-author:
diff --git a/changelogs/unreleased/25680-CI_ENVIRONMENT_URL.yml b/changelogs/unreleased/25680-CI_ENVIRONMENT_URL.yml
deleted file mode 100644
index af9fe3b5041..00000000000
--- a/changelogs/unreleased/25680-CI_ENVIRONMENT_URL.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Add $CI_ENVIRONMENT_URL to predefined variables for pipelines
-merge_request: 11695
-author:
diff --git a/changelogs/unreleased/26325-system-hooks.yml b/changelogs/unreleased/26325-system-hooks.yml
deleted file mode 100644
index 62b8adaeccd..00000000000
--- a/changelogs/unreleased/26325-system-hooks.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: 'Backported new SystemHook event: `repository_update`'
-merge_request: 11140
-author:
diff --git a/changelogs/unreleased/27148-limit-bulk-create-memberships.yml b/changelogs/unreleased/27148-limit-bulk-create-memberships.yml
deleted file mode 100644
index ac4aba2f4e0..00000000000
--- a/changelogs/unreleased/27148-limit-bulk-create-memberships.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Limit non-administrators to adding 100 members at a time to groups and projects
-merge_request: 11940
-author:
diff --git a/changelogs/unreleased/27439-memory-usage-info.yml b/changelogs/unreleased/27439-memory-usage-info.yml
deleted file mode 100644
index dd212853f57..00000000000
--- a/changelogs/unreleased/27439-memory-usage-info.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Add performance deltas between app deployments on Merge Request widget
-merge_request: 11730
-author:
diff --git a/changelogs/unreleased/27614-improve-instant-comments-exp.yml b/changelogs/unreleased/27614-improve-instant-comments-exp.yml
deleted file mode 100644
index 4db676801f1..00000000000
--- a/changelogs/unreleased/27614-improve-instant-comments-exp.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Improve user experience around slash commands in instant comments
-merge_request: 11612
-author:
diff --git a/changelogs/unreleased/28080-system-checks.yml b/changelogs/unreleased/28080-system-checks.yml
deleted file mode 100644
index 7d83014279a..00000000000
--- a/changelogs/unreleased/28080-system-checks.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Refactored gitlab:app:check into SystemCheck liberary and improve some checks
-merge_request: 9173
-author:
diff --git a/changelogs/unreleased/28607-forking-and-configuring-project-via-api-works-very-unreliable.yml b/changelogs/unreleased/28607-forking-and-configuring-project-via-api-works-very-unreliable.yml
deleted file mode 100644
index 9cf8d745f92..00000000000
--- a/changelogs/unreleased/28607-forking-and-configuring-project-via-api-works-very-unreliable.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Confirm Project forking behaviour via the API
-merge_request:
-author:
diff --git a/changelogs/unreleased/28694-hard-delete-user-from-admin-panel.yml b/changelogs/unreleased/28694-hard-delete-user-from-admin-panel.yml
deleted file mode 100644
index 2308a528580..00000000000
--- a/changelogs/unreleased/28694-hard-delete-user-from-admin-panel.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Allow users to be hard-deleted from the admin panel
-merge_request: 11874
-author:
diff --git a/changelogs/unreleased/28694-hard-delete-user-from-api.yml b/changelogs/unreleased/28694-hard-delete-user-from-api.yml
deleted file mode 100644
index ad46540495c..00000000000
--- a/changelogs/unreleased/28694-hard-delete-user-from-api.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Allow users to be hard-deleted from the API
-merge_request: 11853
-author:
diff --git a/changelogs/unreleased/29010-perf-bar.yml b/changelogs/unreleased/29010-perf-bar.yml
deleted file mode 100644
index f4167e5562f..00000000000
--- a/changelogs/unreleased/29010-perf-bar.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Add an optional performance bar to view performance metrics for the current page
-merge_request: 11439
-author:
diff --git a/changelogs/unreleased/29118-add-prometheus-instrumenting-to-gitlab-webapp.yml b/changelogs/unreleased/29118-add-prometheus-instrumenting-to-gitlab-webapp.yml
deleted file mode 100644
index 99c55f128e3..00000000000
--- a/changelogs/unreleased/29118-add-prometheus-instrumenting-to-gitlab-webapp.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Add prometheus based metrics collection to gitlab webapp
-merge_request:
-author:
diff --git a/changelogs/unreleased/29690-rotate-otp-key-base.yml b/changelogs/unreleased/29690-rotate-otp-key-base.yml
deleted file mode 100644
index 94d73a24758..00000000000
--- a/changelogs/unreleased/29690-rotate-otp-key-base.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Add a Rake task to aid in rotating otp_key_base
-merge_request: 11881
-author:
diff --git a/changelogs/unreleased/29852-latex-formatting.yml b/changelogs/unreleased/29852-latex-formatting.yml
deleted file mode 100644
index e96cda1d6b3..00000000000
--- a/changelogs/unreleased/29852-latex-formatting.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Fix LaTeX formatting for AsciiDoc wiki
-merge_request: 11212
-author:
diff --git a/changelogs/unreleased/30378-simplified-repository-settings-page.yml b/changelogs/unreleased/30378-simplified-repository-settings-page.yml
deleted file mode 100644
index e8b87c8bb33..00000000000
--- a/changelogs/unreleased/30378-simplified-repository-settings-page.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Simplify project repository settings page
-merge_request: 11698
-author:
diff --git a/changelogs/unreleased/30410-revert-9347-and-10079.yml b/changelogs/unreleased/30410-revert-9347-and-10079.yml
deleted file mode 100644
index 0149209caf2..00000000000
--- a/changelogs/unreleased/30410-revert-9347-and-10079.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Revert the feature that would include the current user's username in the HTTP
- clone URL
-merge_request: 11792
-author:
diff --git a/changelogs/unreleased/30469-convdev-index.yml b/changelogs/unreleased/30469-convdev-index.yml
deleted file mode 100644
index 0bdd9c4a699..00000000000
--- a/changelogs/unreleased/30469-convdev-index.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Add ConvDev Index page to admin area
-merge_request: 11377
-author:
diff --git a/changelogs/unreleased/30651-improve-container-registry-description.yml b/changelogs/unreleased/30651-improve-container-registry-description.yml
deleted file mode 100644
index 0157c9885bc..00000000000
--- a/changelogs/unreleased/30651-improve-container-registry-description.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Add changelog for improved Registry description
-merge_request: 11816
-author:
diff --git a/changelogs/unreleased/30827-changes-to-audit-log.yml b/changelogs/unreleased/30827-changes-to-audit-log.yml
deleted file mode 100644
index 32db3bf8e95..00000000000
--- a/changelogs/unreleased/30827-changes-to-audit-log.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Renamed users 'Audit Log'' to 'Authentication Log'
-merge_request: 11400
-author:
diff --git a/changelogs/unreleased/30892-add-api-support-for-pipeline-schedule.yml b/changelogs/unreleased/30892-add-api-support-for-pipeline-schedule.yml
deleted file mode 100644
index 26ce84697d0..00000000000
--- a/changelogs/unreleased/30892-add-api-support-for-pipeline-schedule.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Add API support for pipeline schedule
-merge_request: 11307
-author: dosuken123
diff --git a/changelogs/unreleased/30917-wiki-is-not-searchable-with-guest-permissions.yml b/changelogs/unreleased/30917-wiki-is-not-searchable-with-guest-permissions.yml
deleted file mode 100644
index c9bd2dc465e..00000000000
--- a/changelogs/unreleased/30917-wiki-is-not-searchable-with-guest-permissions.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: 'Fix: Wiki is not searchable with Guest permissions'
-merge_request:
-author:
diff --git a/changelogs/unreleased/30949-empty-states.yml b/changelogs/unreleased/30949-empty-states.yml
deleted file mode 100644
index bef87a954b7..00000000000
--- a/changelogs/unreleased/30949-empty-states.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Center all empty states
-merge_request:
-author:
diff --git a/changelogs/unreleased/31061-26135-ci-project-slug-enviroment-variables.yml b/changelogs/unreleased/31061-26135-ci-project-slug-enviroment-variables.yml
deleted file mode 100644
index e71910dbd67..00000000000
--- a/changelogs/unreleased/31061-26135-ci-project-slug-enviroment-variables.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Add slugify project path to CI enviroment variables
-merge_request: 11838
-author: Ivan Chernov
diff --git a/changelogs/unreleased/31384-new-issue-button-on-no-results-page-after-search-doesn-t-go-to-correct-form.yml b/changelogs/unreleased/31384-new-issue-button-on-no-results-page-after-search-doesn-t-go-to-correct-form.yml
deleted file mode 100644
index 8d586616e07..00000000000
--- a/changelogs/unreleased/31384-new-issue-button-on-no-results-page-after-search-doesn-t-go-to-correct-form.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Remove 'New issue' button when issues search returns no results.
-merge_request: !11263
-author:
diff --git a/changelogs/unreleased/31448-jira-urls.yml b/changelogs/unreleased/31448-jira-urls.yml
deleted file mode 100644
index d0e39f61b55..00000000000
--- a/changelogs/unreleased/31448-jira-urls.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Add API URL to JIRA settings
-merge_request:
-author:
diff --git a/changelogs/unreleased/31474-issue-boards-sidebar-milestone-dropdown-should-not-be-multi-select.yml b/changelogs/unreleased/31474-issue-boards-sidebar-milestone-dropdown-should-not-be-multi-select.yml
deleted file mode 100644
index 88e79e3b6ea..00000000000
--- a/changelogs/unreleased/31474-issue-boards-sidebar-milestone-dropdown-should-not-be-multi-select.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Disallow multiple selections for Milestone dropdown
-merge_request: 11084
-author:
diff --git a/changelogs/unreleased/31483-ordered-task-list.yml b/changelogs/unreleased/31483-ordered-task-list.yml
deleted file mode 100644
index c43915b3268..00000000000
--- a/changelogs/unreleased/31483-ordered-task-list.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Fix Ordered Task List Items
-merge_request: 31483
-author: Jared Deckard <jared.deckard@gmail.com>
diff --git a/changelogs/unreleased/31510-mask-password-field-edit.yml b/changelogs/unreleased/31510-mask-password-field-edit.yml
deleted file mode 100644
index 0ef37be328d..00000000000
--- a/changelogs/unreleased/31510-mask-password-field-edit.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Update password field label while editing service settings
-merge_request: 11431
-author:
diff --git a/changelogs/unreleased/31511-jira-settings.yml b/changelogs/unreleased/31511-jira-settings.yml
deleted file mode 100644
index 4f9ddb13ef6..00000000000
--- a/changelogs/unreleased/31511-jira-settings.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Simplify testing and saving service integrations
-merge_request: 11599
-author:
diff --git a/changelogs/unreleased/31554-update-rufus-scheduler-and-sidekiq.yml b/changelogs/unreleased/31554-update-rufus-scheduler-and-sidekiq.yml
deleted file mode 100644
index 0a36b52d561..00000000000
--- a/changelogs/unreleased/31554-update-rufus-scheduler-and-sidekiq.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Update gem sidekiq-cron from 0.4.4 to 0.6.0 and rufus-scheduler from 3.1.10
- to 3.4.0
-merge_request: 10976
-author: dosuken123
diff --git a/changelogs/unreleased/31602-display-whether-shared-runner-is-enabled-in-the-admin-dashboard.yml b/changelogs/unreleased/31602-display-whether-shared-runner-is-enabled-in-the-admin-dashboard.yml
deleted file mode 100644
index 00957f7e4f7..00000000000
--- a/changelogs/unreleased/31602-display-whether-shared-runner-is-enabled-in-the-admin-dashboard.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Display Shared Runner status in Admin Dashboard
-merge_request: 11783
-author: Ivan Chernov
diff --git a/changelogs/unreleased/31616-add-uptime-of-gitlab-instance-in-admin-area.yml b/changelogs/unreleased/31616-add-uptime-of-gitlab-instance-in-admin-area.yml
deleted file mode 100644
index 6dc48d6b2d8..00000000000
--- a/changelogs/unreleased/31616-add-uptime-of-gitlab-instance-in-admin-area.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Add server uptime to System Info page in admin dashboard
-merge_request: 11590
-author: Justin Boltz
diff --git a/changelogs/unreleased/31625-tag-editor-loses-all-inputs-when-you-try-to-add-a-tag-that-already-exists.yml b/changelogs/unreleased/31625-tag-editor-loses-all-inputs-when-you-try-to-add-a-tag-that-already-exists.yml
deleted file mode 100644
index aae760b0ef5..00000000000
--- a/changelogs/unreleased/31625-tag-editor-loses-all-inputs-when-you-try-to-add-a-tag-that-already-exists.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Keep input data after creating a tag that already exists
-merge_request: 11155
-author:
diff --git a/changelogs/unreleased/31633-animate-issue.yml b/changelogs/unreleased/31633-animate-issue.yml
deleted file mode 100644
index 6df4135b09c..00000000000
--- a/changelogs/unreleased/31633-animate-issue.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: animate adding issue to boards
-merge_request:
-author:
diff --git a/changelogs/unreleased/31644-make-cookie-sessions-unique.yml b/changelogs/unreleased/31644-make-cookie-sessions-unique.yml
deleted file mode 100644
index e9a6a32cf70..00000000000
--- a/changelogs/unreleased/31644-make-cookie-sessions-unique.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Update session cookie key name to be unique to instance in development
-merge_request:
-author:
diff --git a/changelogs/unreleased/31757-single-click-on-filter-in-search-bar-to-activate-dropdown.yml b/changelogs/unreleased/31757-single-click-on-filter-in-search-bar-to-activate-dropdown.yml
deleted file mode 100644
index 48b8a8507ec..00000000000
--- a/changelogs/unreleased/31757-single-click-on-filter-in-search-bar-to-activate-dropdown.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Single click on filter to open filtered search dropdown
-merge_request:
-author:
diff --git a/changelogs/unreleased/31781-print-rendered-files-not-possible.yml b/changelogs/unreleased/31781-print-rendered-files-not-possible.yml
deleted file mode 100644
index 14915823ff7..00000000000
--- a/changelogs/unreleased/31781-print-rendered-files-not-possible.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Include the blob content when printing a blob page
-merge_request: 11247
-author:
diff --git a/changelogs/unreleased/31840-add-a-rubocop-that-forbids-redirect_to-inside-a-controller-destroy-action-without-an-explicit-status.yml b/changelogs/unreleased/31840-add-a-rubocop-that-forbids-redirect_to-inside-a-controller-destroy-action-without-an-explicit-status.yml
deleted file mode 100644
index 52bfe771e2b..00000000000
--- a/changelogs/unreleased/31840-add-a-rubocop-that-forbids-redirect_to-inside-a-controller-destroy-action-without-an-explicit-status.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Add a rubocop rule to check if a method 'redirect_to' is used without explicitly set 'status' in 'destroy' actions of controllers
-merge_request: 11749
-author: @blackst0ne
diff --git a/changelogs/unreleased/31849-pipeline-real-time-header.yml b/changelogs/unreleased/31849-pipeline-real-time-header.yml
deleted file mode 100644
index 2bb7af897ff..00000000000
--- a/changelogs/unreleased/31849-pipeline-real-time-header.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Makes header information of pipeline show page realtine
-merge_request:
-author:
diff --git a/changelogs/unreleased/31849-pipeline-show-view-realtime.yml b/changelogs/unreleased/31849-pipeline-show-view-realtime.yml
deleted file mode 100644
index 838a769a26e..00000000000
--- a/changelogs/unreleased/31849-pipeline-show-view-realtime.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Creates a mediator for pipeline details vue in order to mount several vue apps
- with the same data
-merge_request:
-author:
diff --git a/changelogs/unreleased/31902-namespace-recent-searches-to-project.yml b/changelogs/unreleased/31902-namespace-recent-searches-to-project.yml
deleted file mode 100644
index e00eb6d8f72..00000000000
--- a/changelogs/unreleased/31902-namespace-recent-searches-to-project.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Scope issue/merge request recent searches to project
-merge_request:
-author:
diff --git a/changelogs/unreleased/3191-deploy-keys-update.yml b/changelogs/unreleased/3191-deploy-keys-update.yml
deleted file mode 100644
index 4100163e94f..00000000000
--- a/changelogs/unreleased/3191-deploy-keys-update.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Implement ability to update deploy keys
-merge_request: 10383
-author: Alexander Randa
diff --git a/changelogs/unreleased/31943-document-go-183.yml b/changelogs/unreleased/31943-document-go-183.yml
deleted file mode 100644
index 201cd48f1ab..00000000000
--- a/changelogs/unreleased/31943-document-go-183.yml
+++ /dev/null
@@ -1,3 +0,0 @@
----
-title: Upgrade dependency to Go 1.8.3
-merge_request: 31943
diff --git a/changelogs/unreleased/31983-increase-merge-request-diff-file-size-limit-for-default-toggle-opening.yml b/changelogs/unreleased/31983-increase-merge-request-diff-file-size-limit-for-default-toggle-opening.yml
deleted file mode 100644
index f61aa0a6b6e..00000000000
--- a/changelogs/unreleased/31983-increase-merge-request-diff-file-size-limit-for-default-toggle-opening.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Increase individual diff collapse limit to 100 KB, and render limit to 200 KB
-merge_request:
-author:
diff --git a/changelogs/unreleased/31998-pipelines-empty-state.yml b/changelogs/unreleased/31998-pipelines-empty-state.yml
deleted file mode 100644
index 78ae222255e..00000000000
--- a/changelogs/unreleased/31998-pipelines-empty-state.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Fix Pipelines table empty state - only render empty state if we receive 0 pipelines
-merge_request:
-author:
diff --git a/changelogs/unreleased/32086-atwho-is-still-enabled-for-personal-snippet-comments-form.yml b/changelogs/unreleased/32086-atwho-is-still-enabled-for-personal-snippet-comments-form.yml
deleted file mode 100644
index 0fd248e0400..00000000000
--- a/changelogs/unreleased/32086-atwho-is-still-enabled-for-personal-snippet-comments-form.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Disable reference prefixes in notes for Snippets
-merge_request: 11278
-author:
diff --git a/changelogs/unreleased/32118-new-environment-btn-copy.yml b/changelogs/unreleased/32118-new-environment-btn-copy.yml
deleted file mode 100644
index 16a51c3db6a..00000000000
--- a/changelogs/unreleased/32118-new-environment-btn-copy.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Make New environment empty state btn lowercase
-merge_request:
-author:
diff --git a/changelogs/unreleased/32219-speed-up-yarn-install-in-ci-by-utilizing-inter-pipeline-cache.yml b/changelogs/unreleased/32219-speed-up-yarn-install-in-ci-by-utilizing-inter-pipeline-cache.yml
deleted file mode 100644
index 7fb3cb3a30b..00000000000
--- a/changelogs/unreleased/32219-speed-up-yarn-install-in-ci-by-utilizing-inter-pipeline-cache.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Cache npm modules between pipelines with yarn to speed up setup-test-env
-merge_request: 11343
-author:
diff --git a/changelogs/unreleased/32395-duplicate-string-in-https-docs-gitlab-com-ce-administration-environment_variables-html.yml b/changelogs/unreleased/32395-duplicate-string-in-https-docs-gitlab-com-ce-administration-environment_variables-html.yml
deleted file mode 100644
index d2be3d6cc4b..00000000000
--- a/changelogs/unreleased/32395-duplicate-string-in-https-docs-gitlab-com-ce-administration-environment_variables-html.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Removes duplicate environment variable in documentation
-merge_request:
-author:
diff --git a/changelogs/unreleased/32418-make-link-to-self-less-obvious.yml b/changelogs/unreleased/32418-make-link-to-self-less-obvious.yml
deleted file mode 100644
index aabe87dac0f..00000000000
--- a/changelogs/unreleased/32418-make-link-to-self-less-obvious.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Change links in issuable meta to black
-merge_request:
-author:
diff --git a/changelogs/unreleased/32570-project-activity-tab-border.yml b/changelogs/unreleased/32570-project-activity-tab-border.yml
deleted file mode 100644
index 100a3e6a74d..00000000000
--- a/changelogs/unreleased/32570-project-activity-tab-border.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Fix border-bottom for project activity tab
-merge_request:
-author:
diff --git a/changelogs/unreleased/32598-avoid-resource-intensive-login-checks-if-password-is-not-provided-for-git-http.yml b/changelogs/unreleased/32598-avoid-resource-intensive-login-checks-if-password-is-not-provided-for-git-http.yml
deleted file mode 100644
index 6da7491bbda..00000000000
--- a/changelogs/unreleased/32598-avoid-resource-intensive-login-checks-if-password-is-not-provided-for-git-http.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Avoid resource intensive login checks if password is not provided.
-merge_request: 11537
-author: Horatiu Eugen Vlad
diff --git a/changelogs/unreleased/32642_last_commit_id_in_file_api.yml b/changelogs/unreleased/32642_last_commit_id_in_file_api.yml
deleted file mode 100644
index 80435352e10..00000000000
--- a/changelogs/unreleased/32642_last_commit_id_in_file_api.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: 'Introduce optimistic locking support via optional parameter last_commit_sha on File Update API'
-merge_request: 11694
-author: electroma
diff --git a/changelogs/unreleased/32682-skipped-ci-icon.yml b/changelogs/unreleased/32682-skipped-ci-icon.yml
deleted file mode 100644
index ad498b51900..00000000000
--- a/changelogs/unreleased/32682-skipped-ci-icon.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Adds new icon for CI skipped status
-merge_request:
-author:
diff --git a/changelogs/unreleased/32720-emoji-spacing.yml b/changelogs/unreleased/32720-emoji-spacing.yml
deleted file mode 100644
index da3df0f9093..00000000000
--- a/changelogs/unreleased/32720-emoji-spacing.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Create equal padding for emoji
-merge_request:
-author:
diff --git a/changelogs/unreleased/32799-remove-no_turbolink-attribute-from-haml.yml b/changelogs/unreleased/32799-remove-no_turbolink-attribute-from-haml.yml
deleted file mode 100644
index 9c1c1fe77f2..00000000000
--- a/changelogs/unreleased/32799-remove-no_turbolink-attribute-from-haml.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Remove redundant data-turbolink attributes from links
-merge_request: 11672
-author: blackst0ne
diff --git a/changelogs/unreleased/32807-company-icon.yml b/changelogs/unreleased/32807-company-icon.yml
deleted file mode 100644
index 718108d3733..00000000000
--- a/changelogs/unreleased/32807-company-icon.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Use briefcase icon for company in profile page
-merge_request:
-author:
diff --git a/changelogs/unreleased/32832-confidential-issue-overflow.yml b/changelogs/unreleased/32832-confidential-issue-overflow.yml
deleted file mode 100644
index 7d3d3bfed2e..00000000000
--- a/changelogs/unreleased/32832-confidential-issue-overflow.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Remove overflow from comment form for confidential issues and vertically aligns
- confidential issue icon
-merge_request:
-author:
diff --git a/changelogs/unreleased/32851-postgres-min-version.yml b/changelogs/unreleased/32851-postgres-min-version.yml
deleted file mode 100644
index 139307d65c6..00000000000
--- a/changelogs/unreleased/32851-postgres-min-version.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Minimum postgresql version is now 9.2
-merge_request: 11677
-author:
diff --git a/changelogs/unreleased/32955-special-keywords.yml b/changelogs/unreleased/32955-special-keywords.yml
deleted file mode 100644
index 0f9939ced8c..00000000000
--- a/changelogs/unreleased/32955-special-keywords.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Add all pipeline sources as special keywords to 'only' and 'except'
-merge_request: 11844
-author: Filip Krakowski
diff --git a/changelogs/unreleased/32983-merge-conflict-resolution-removed-the-newline-in-the-end-of-file.yml b/changelogs/unreleased/32983-merge-conflict-resolution-removed-the-newline-in-the-end-of-file.yml
deleted file mode 100644
index eca42176501..00000000000
--- a/changelogs/unreleased/32983-merge-conflict-resolution-removed-the-newline-in-the-end-of-file.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Keep trailing newline when resolving conflicts by picking sides
-merge_request:
-author:
diff --git a/changelogs/unreleased/32992-consider-using-zopfli-over-standard-gzip-compression-for-webpack-assets.yml b/changelogs/unreleased/32992-consider-using-zopfli-over-standard-gzip-compression-for-webpack-assets.yml
deleted file mode 100644
index 93037d6181e..00000000000
--- a/changelogs/unreleased/32992-consider-using-zopfli-over-standard-gzip-compression-for-webpack-assets.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Use zopfli compression for frontend assets
-merge_request: 11798
-author:
diff --git a/changelogs/unreleased/33000-tag-list-in-project-create-api.yml b/changelogs/unreleased/33000-tag-list-in-project-create-api.yml
deleted file mode 100644
index b0d0d3cbeba..00000000000
--- a/changelogs/unreleased/33000-tag-list-in-project-create-api.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Add tag_list param to project api
-merge_request: 11799
-author: Ivan Chernov
diff --git a/changelogs/unreleased/33032-invalid-you-directly-addressed-yourself-todo-when-using-unsubscribe.yml b/changelogs/unreleased/33032-invalid-you-directly-addressed-yourself-todo-when-using-unsubscribe.yml
deleted file mode 100644
index 1eaa0d0124e..00000000000
--- a/changelogs/unreleased/33032-invalid-you-directly-addressed-yourself-todo-when-using-unsubscribe.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix /unsubscribe slash command creating extra todos when you were already mentioned
- in an issue
-merge_request:
-author:
diff --git a/changelogs/unreleased/33154-permissions-for-project-labels-and-group-labels.yml b/changelogs/unreleased/33154-permissions-for-project-labels-and-group-labels.yml
deleted file mode 100644
index 3b98525167d..00000000000
--- a/changelogs/unreleased/33154-permissions-for-project-labels-and-group-labels.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Allow group reporters to manage group labels
-merge_request:
-author:
diff --git a/changelogs/unreleased/33207-show-delete-option-in-admin-users-page.yml b/changelogs/unreleased/33207-show-delete-option-in-admin-users-page.yml
deleted file mode 100644
index 5eb4e15e311..00000000000
--- a/changelogs/unreleased/33207-show-delete-option-in-admin-users-page.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Allow admins to delete users from the admin users page
-merge_request: 11852
-author:
diff --git a/changelogs/unreleased/33215-fix-hard-delete-of-users.yml b/changelogs/unreleased/33215-fix-hard-delete-of-users.yml
deleted file mode 100644
index 29699ff745a..00000000000
--- a/changelogs/unreleased/33215-fix-hard-delete-of-users.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Fix hard-deleting users when they have authored issues
-merge_request: 11855
-author:
diff --git a/changelogs/unreleased/33242-create-project-for-user-api-ignores-path-parameter.yml b/changelogs/unreleased/33242-create-project-for-user-api-ignores-path-parameter.yml
deleted file mode 100644
index c33278998ee..00000000000
--- a/changelogs/unreleased/33242-create-project-for-user-api-ignores-path-parameter.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Fix missing optional path parameter in "Create project for user" API
-merge_request: 11868
-author:
diff --git a/changelogs/unreleased/33245-chinese_translation_of_cycle_analytics_page.yml b/changelogs/unreleased/33245-chinese_translation_of_cycle_analytics_page.yml
deleted file mode 100644
index 07dd0872d3b..00000000000
--- a/changelogs/unreleased/33245-chinese_translation_of_cycle_analytics_page.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Add Chinese translation of Cycle Analytics Page to I18N
-merge_request: 11644
-author:Huang Tao
diff --git a/changelogs/unreleased/33308-use-pre-wrap-for-commit-messages.yml b/changelogs/unreleased/33308-use-pre-wrap-for-commit-messages.yml
deleted file mode 100644
index 43e8f242947..00000000000
--- a/changelogs/unreleased/33308-use-pre-wrap-for-commit-messages.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Use pre-wrap for commit messages to keep lists indented
-merge_request:
-author:
diff --git a/changelogs/unreleased/33334-portuguese_brazil_translation_of_cycle_analytics_page.yml b/changelogs/unreleased/33334-portuguese_brazil_translation_of_cycle_analytics_page.yml
deleted file mode 100644
index a0e0458da16..00000000000
--- a/changelogs/unreleased/33334-portuguese_brazil_translation_of_cycle_analytics_page.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Add Portuguese Brazil of Cycle Analytics Page to I18N
-merge_request: 11920
-author:Huang Tao
diff --git a/changelogs/unreleased/33383-bulgarian_translation_of_cycle_analytics_page.yml b/changelogs/unreleased/33383-bulgarian_translation_of_cycle_analytics_page.yml
deleted file mode 100644
index 71bd5505be7..00000000000
--- a/changelogs/unreleased/33383-bulgarian_translation_of_cycle_analytics_page.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: add bulgarian translation of cycle analytics page to I18N
-merge_request: 11958
-author: Lyubomir Vasilev
diff --git a/changelogs/unreleased/33442-supplement_traditional_chinese_in_hong_kong_translation_of_i18n.yml b/changelogs/unreleased/33442-supplement_traditional_chinese_in_hong_kong_translation_of_i18n.yml
new file mode 100644
index 00000000000..e383bab23d6
--- /dev/null
+++ b/changelogs/unreleased/33442-supplement_traditional_chinese_in_hong_kong_translation_of_i18n.yml
@@ -0,0 +1,4 @@
+---
+title: Supplement Traditional Chinese in Hong Kong translation of Project Page & Repository Page
+merge_request: 11995
+author: Huang Tao
diff --git a/changelogs/unreleased/33561-supplement_bulgarian_translation_of_i18n.yml b/changelogs/unreleased/33561-supplement_bulgarian_translation_of_i18n.yml
new file mode 100644
index 00000000000..4f2ba2e1de3
--- /dev/null
+++ b/changelogs/unreleased/33561-supplement_bulgarian_translation_of_i18n.yml
@@ -0,0 +1,4 @@
+---
+title: Supplement Bulgarian translation of Project Page & Repository Page
+merge_request: 12083
+author: Lyubomir Vasilev
diff --git a/changelogs/unreleased/33846-no-runner-for-admin.yml b/changelogs/unreleased/33846-no-runner-for-admin.yml
new file mode 100644
index 00000000000..a2d46802c61
--- /dev/null
+++ b/changelogs/unreleased/33846-no-runner-for-admin.yml
@@ -0,0 +1,4 @@
+---
+title: Add explicit message when no runners on admin
+merge_request: 12266
+author: Takuya Noguchi
diff --git a/changelogs/unreleased/33878_fix_edit_deploy_key.yml b/changelogs/unreleased/33878_fix_edit_deploy_key.yml
deleted file mode 100644
index bc47d522240..00000000000
--- a/changelogs/unreleased/33878_fix_edit_deploy_key.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Fix edit button for deploy keys available from other projects
-merge_request: 12301
-author: Alexander Randa
diff --git a/changelogs/unreleased/33917-mr-comment-system-note-highlight-don-t-have-the-same-width.yml b/changelogs/unreleased/33917-mr-comment-system-note-highlight-don-t-have-the-same-width.yml
deleted file mode 100644
index f3b92878f6d..00000000000
--- a/changelogs/unreleased/33917-mr-comment-system-note-highlight-don-t-have-the-same-width.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Standardize timeline note margins across different viewport sizes
-merge_request: 12364
-author:
diff --git a/changelogs/unreleased/34008-fix-CI_ENVIRONMENT_URL-2.yml b/changelogs/unreleased/34008-fix-CI_ENVIRONMENT_URL-2.yml
deleted file mode 100644
index 7f4d6e3bc67..00000000000
--- a/changelogs/unreleased/34008-fix-CI_ENVIRONMENT_URL-2.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Fix passing CI_ENVIRONMENT_NAME and CI_ENVIRONMENT_SLUG for CI_ENVIRONMENT_URL
-merge_request: 12344
-author:
diff --git a/changelogs/unreleased/34010-fix-linking-to-parallel-diff-line-number-creating-gray-box.yml b/changelogs/unreleased/34010-fix-linking-to-parallel-diff-line-number-creating-gray-box.yml
deleted file mode 100644
index 705d44f8b10..00000000000
--- a/changelogs/unreleased/34010-fix-linking-to-parallel-diff-line-number-creating-gray-box.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Fix linking to line number on side-by-side diff creating empty discussion box
-merge_request:
-author:
diff --git a/changelogs/unreleased/34052-store-mr-ref-fetched-in-database.yml b/changelogs/unreleased/34052-store-mr-ref-fetched-in-database.yml
new file mode 100644
index 00000000000..4bacfca7551
--- /dev/null
+++ b/changelogs/unreleased/34052-store-mr-ref-fetched-in-database.yml
@@ -0,0 +1,4 @@
+---
+title: Store merge request ref_fetched status in the database
+merge_request: 12424
+author:
diff --git a/changelogs/unreleased/34207-remove-bin-ci-upgrade-rb.yml b/changelogs/unreleased/34207-remove-bin-ci-upgrade-rb.yml
new file mode 100644
index 00000000000..4fa385c3c27
--- /dev/null
+++ b/changelogs/unreleased/34207-remove-bin-ci-upgrade-rb.yml
@@ -0,0 +1,4 @@
+---
+title: Remove bin/ci/upgrade.rb as not working all
+merge_request: 12414
+author: Takuya Noguchi
diff --git a/changelogs/unreleased/34286-add-esperanto-translations-for-cycle-analytics-and-project-and-repository-pages.yml b/changelogs/unreleased/34286-add-esperanto-translations-for-cycle-analytics-and-project-and-repository-pages.yml
new file mode 100644
index 00000000000..af743f3e506
--- /dev/null
+++ b/changelogs/unreleased/34286-add-esperanto-translations-for-cycle-analytics-and-project-and-repository-pages.yml
@@ -0,0 +1,4 @@
+---
+title: Add Esperanto translations for Cycle Analytics, Project, and Repository pages
+merge_request: 12442
+author: Huang Tao
diff --git a/changelogs/unreleased/34289-drop-gfm-on-milestone-issuable-title.yml b/changelogs/unreleased/34289-drop-gfm-on-milestone-issuable-title.yml
new file mode 100644
index 00000000000..42e906d24c6
--- /dev/null
+++ b/changelogs/unreleased/34289-drop-gfm-on-milestone-issuable-title.yml
@@ -0,0 +1,4 @@
+---
+title: Drop GFM support for issuable title on milestone for consistency and performance
+merge_request:
+author: Takuya Noguchi
diff --git a/changelogs/unreleased/34309-drop-gfm-mr-ms.yml b/changelogs/unreleased/34309-drop-gfm-mr-ms.yml
new file mode 100644
index 00000000000..07fe79e90ee
--- /dev/null
+++ b/changelogs/unreleased/34309-drop-gfm-mr-ms.yml
@@ -0,0 +1,4 @@
+---
+title: Drop GFM support for the title of Milestone/MergeRequest in template
+merge_request: 12451
+author: Takuya Noguchi
diff --git a/changelogs/unreleased/UI-improvements-for-count-badges-and-permission-badges.yml b/changelogs/unreleased/UI-improvements-for-count-badges-and-permission-badges.yml
deleted file mode 100644
index 374f643faa7..00000000000
--- a/changelogs/unreleased/UI-improvements-for-count-badges-and-permission-badges.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Count badges depend on translucent color to better adjust to different background
- colors and permission badges now feature a pill shaped design similar to labels
-merge_request:
-author:
diff --git a/changelogs/unreleased/adam-influxdb-hostname.yml b/changelogs/unreleased/adam-influxdb-hostname.yml
deleted file mode 100644
index ab201ae7894..00000000000
--- a/changelogs/unreleased/adam-influxdb-hostname.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Allow GitLab instance to start when InfluxDB hostname cannot be resolved
-merge_request: 11356
-author:
diff --git a/changelogs/unreleased/add-index-for-auto_canceled_by_id-mysql.yml b/changelogs/unreleased/add-index-for-auto_canceled_by_id-mysql.yml
deleted file mode 100644
index eac78e9ee1f..00000000000
--- a/changelogs/unreleased/add-index-for-auto_canceled_by_id-mysql.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Add indices for auto_canceled_by_id for ci_pipelines and ci_builds on PostgreSQL
-merge_request: 11034
-author:
diff --git a/changelogs/unreleased/add-unicode-trace-feature-test.yml b/changelogs/unreleased/add-unicode-trace-feature-test.yml
deleted file mode 100644
index 90c6a9afefc..00000000000
--- a/changelogs/unreleased/add-unicode-trace-feature-test.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Add a feature test for Unicode trace
-merge_request: 10736
-author: dosuken123
diff --git a/changelogs/unreleased/add_ability_to_cancel_attaching_file_and_redesign_attaching_files_ui.yml b/changelogs/unreleased/add_ability_to_cancel_attaching_file_and_redesign_attaching_files_ui.yml
deleted file mode 100644
index fcf4efa2846..00000000000
--- a/changelogs/unreleased/add_ability_to_cancel_attaching_file_and_redesign_attaching_files_ui.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Add an ability to cancel attaching file and redesign attaching files UI
-merge_request: 9431
-author: blackst0ne
diff --git a/changelogs/unreleased/aliyun-backup-provider.yml b/changelogs/unreleased/aliyun-backup-provider.yml
deleted file mode 100644
index e7505e44a59..00000000000
--- a/changelogs/unreleased/aliyun-backup-provider.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Add Aliyun OSS as the backup storage provider
-merge_request: 9721
-author: Yuanfei Zhu
diff --git a/changelogs/unreleased/allow-reporters-to-promote-group-labels.yml b/changelogs/unreleased/allow-reporters-to-promote-group-labels.yml
deleted file mode 100644
index 2364ce6d068..00000000000
--- a/changelogs/unreleased/allow-reporters-to-promote-group-labels.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Allow reporters to promote project labels to group labels
-merge_request:
-author:
diff --git a/changelogs/unreleased/allow_numeric_pages_domain.yml b/changelogs/unreleased/allow_numeric_pages_domain.yml
deleted file mode 100644
index 10d9f26f88d..00000000000
--- a/changelogs/unreleased/allow_numeric_pages_domain.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Allow numeric pages domain
-merge_request: 11550
-author:
diff --git a/changelogs/unreleased/allow_numeric_values_in_gitlab_ci_yml.yml b/changelogs/unreleased/allow_numeric_values_in_gitlab_ci_yml.yml
deleted file mode 100644
index 8c7fa53a18b..00000000000
--- a/changelogs/unreleased/allow_numeric_values_in_gitlab_ci_yml.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Allow numeric values in gitlab-ci.yml
-merge_request: 10607
-author: blackst0ne
diff --git a/changelogs/unreleased/artifacts-keyboard-shortcuts.yml b/changelogs/unreleased/artifacts-keyboard-shortcuts.yml
deleted file mode 100644
index 69569504c4f..00000000000
--- a/changelogs/unreleased/artifacts-keyboard-shortcuts.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Enabled keyboard shortcuts on artifacts pages
-merge_request:
-author:
diff --git a/changelogs/unreleased/auto-search-when-state-changed.yml b/changelogs/unreleased/auto-search-when-state-changed.yml
deleted file mode 100644
index 2723beb8600..00000000000
--- a/changelogs/unreleased/auto-search-when-state-changed.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Perform filtered search when state tab is changed
-merge_request:
-author:
diff --git a/changelogs/unreleased/bugfix-v3-deploy_keys-can_push.yml b/changelogs/unreleased/bugfix-v3-deploy_keys-can_push.yml
deleted file mode 100644
index 0306663ac8d..00000000000
--- a/changelogs/unreleased/bugfix-v3-deploy_keys-can_push.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: "Fixed handling of the `can_push` attribute in the v3 deploy_keys api"
-merge_request: 11607
-author: Richard Clamp
diff --git a/changelogs/unreleased/bvl-rename-build-events-to-job-events.yml b/changelogs/unreleased/bvl-rename-build-events-to-job-events.yml
deleted file mode 100644
index 2ce01a71361..00000000000
--- a/changelogs/unreleased/bvl-rename-build-events-to-job-events.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Rename build_events to job_events
-merge_request: 11287
-author:
diff --git a/changelogs/unreleased/bvl-translate-project-pages.yml b/changelogs/unreleased/bvl-translate-project-pages.yml
deleted file mode 100644
index fb90aba08b4..00000000000
--- a/changelogs/unreleased/bvl-translate-project-pages.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Translate backend for Project & Repository pages
-merge_request: 11183
-author:
diff --git a/changelogs/unreleased/ce-31853-projects-shared-groups.yml b/changelogs/unreleased/ce-31853-projects-shared-groups.yml
deleted file mode 100644
index ffa3aed682d..00000000000
--- a/changelogs/unreleased/ce-31853-projects-shared-groups.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Remove duplication for sharing projects with groups in project settings
-merge_request:
-author:
diff --git a/changelogs/unreleased/ce-32623-browser-tooltip-commits-branch-list.yml b/changelogs/unreleased/ce-32623-browser-tooltip-commits-branch-list.yml
deleted file mode 100644
index 93edafed699..00000000000
--- a/changelogs/unreleased/ce-32623-browser-tooltip-commits-branch-list.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Change order of commits ahead and behind on divergence graph for branch list
- view
-merge_request:
-author:
diff --git a/changelogs/unreleased/ci-build-pipeline-header-vue.yml b/changelogs/unreleased/ci-build-pipeline-header-vue.yml
deleted file mode 100644
index 2bbff2fdd16..00000000000
--- a/changelogs/unreleased/ci-build-pipeline-header-vue.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Creates CI Header component for Pipelines and Jobs details pages
-merge_request:
-author:
diff --git a/changelogs/unreleased/disable-blocked-manual-actions.yml b/changelogs/unreleased/disable-blocked-manual-actions.yml
deleted file mode 100644
index a640f61a7dd..00000000000
--- a/changelogs/unreleased/disable-blocked-manual-actions.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: disable blocked manual actions
-merge_request:
-author:
diff --git a/changelogs/unreleased/disable-environment-list-refresh.yml b/changelogs/unreleased/disable-environment-list-refresh.yml
deleted file mode 100644
index 62fd71496a0..00000000000
--- a/changelogs/unreleased/disable-environment-list-refresh.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Disable environment list refresh due to bug https://gitlab.com/gitlab-org/gitlab-ee/issues/2677
-merge_request: 12347
-author:
diff --git a/changelogs/unreleased/dm-async-tree-readme.yml b/changelogs/unreleased/dm-async-tree-readme.yml
deleted file mode 100644
index fb1cfeb210a..00000000000
--- a/changelogs/unreleased/dm-async-tree-readme.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Load tree readme asynchronously
-merge_request:
-author:
diff --git a/changelogs/unreleased/dm-auxiliary-viewers.yml b/changelogs/unreleased/dm-auxiliary-viewers.yml
deleted file mode 100644
index ba73a499115..00000000000
--- a/changelogs/unreleased/dm-auxiliary-viewers.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Display extra info about files on .gitlab-ci.yml, .gitlab/route-map.yml and
- LICENSE blob pages
-merge_request:
-author:
diff --git a/changelogs/unreleased/dm-comment-on-mr-commit-discussion.yml b/changelogs/unreleased/dm-comment-on-mr-commit-discussion.yml
deleted file mode 100644
index 50db66c89ba..00000000000
--- a/changelogs/unreleased/dm-comment-on-mr-commit-discussion.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Fix replying to a commit discussion displayed in the context of an MR
-merge_request:
-author:
diff --git a/changelogs/unreleased/dm-commit-row-browse-button.yml b/changelogs/unreleased/dm-commit-row-browse-button.yml
new file mode 100644
index 00000000000..4240a7de5de
--- /dev/null
+++ b/changelogs/unreleased/dm-commit-row-browse-button.yml
@@ -0,0 +1,4 @@
+---
+title: Fix inconsistent display of the "Browse files" button in the commit list
+merge_request:
+author:
diff --git a/changelogs/unreleased/dm-consistent-commit-sha-style.yml b/changelogs/unreleased/dm-consistent-commit-sha-style.yml
deleted file mode 100644
index b6dace34d9b..00000000000
--- a/changelogs/unreleased/dm-consistent-commit-sha-style.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Consistently use monospace font for commit SHAs and branch and tag names
-merge_request:
-author:
diff --git a/changelogs/unreleased/dm-consistent-last-push-event.yml b/changelogs/unreleased/dm-consistent-last-push-event.yml
deleted file mode 100644
index acc17cb4523..00000000000
--- a/changelogs/unreleased/dm-consistent-last-push-event.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Consistently display last push event widget
-merge_request:
-author:
diff --git a/changelogs/unreleased/dm-copy-as-gfm-without-empty-elements.yml b/changelogs/unreleased/dm-copy-as-gfm-without-empty-elements.yml
deleted file mode 100644
index 45a61320ff2..00000000000
--- a/changelogs/unreleased/dm-copy-as-gfm-without-empty-elements.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Don't copy empty elements that were not selected on purpose as GFM
-merge_request:
-author:
diff --git a/changelogs/unreleased/dm-copy-gfm-when-parts-of-other-elements-are-selected.yml b/changelogs/unreleased/dm-copy-gfm-when-parts-of-other-elements-are-selected.yml
deleted file mode 100644
index ae916c30ff8..00000000000
--- a/changelogs/unreleased/dm-copy-gfm-when-parts-of-other-elements-are-selected.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Copy as GFM even when parts of other elements are selected
-merge_request:
-author:
diff --git a/changelogs/unreleased/dm-dependency-linker-gemfile.yml b/changelogs/unreleased/dm-dependency-linker-gemfile.yml
deleted file mode 100644
index 2d4167a1be5..00000000000
--- a/changelogs/unreleased/dm-dependency-linker-gemfile.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Autolink package names in Gemfile
-merge_request:
-author:
diff --git a/changelogs/unreleased/dm-discussions-n-plus-1.yml b/changelogs/unreleased/dm-discussions-n-plus-1.yml
deleted file mode 100644
index b97e4344248..00000000000
--- a/changelogs/unreleased/dm-discussions-n-plus-1.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Resolve N+1 query issue with discussions
-merge_request:
-author:
diff --git a/changelogs/unreleased/dm-emails-are-not-user-references.yml b/changelogs/unreleased/dm-emails-are-not-user-references.yml
deleted file mode 100644
index fe55a75a88f..00000000000
--- a/changelogs/unreleased/dm-emails-are-not-user-references.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Don't match email addresses or foo@bar as user references
-merge_request:
-author:
diff --git a/changelogs/unreleased/dm-fix-jump-button.yml b/changelogs/unreleased/dm-fix-jump-button.yml
deleted file mode 100644
index 4cde354fa28..00000000000
--- a/changelogs/unreleased/dm-fix-jump-button.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Fix title of discussion jump button at top of page
-merge_request:
-author:
diff --git a/changelogs/unreleased/dm-fix-parser-cache.yml b/changelogs/unreleased/dm-fix-parser-cache.yml
deleted file mode 100644
index 31c163b7272..00000000000
--- a/changelogs/unreleased/dm-fix-parser-cache.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Don't return nil for missing objects from parser cache
-merge_request:
-author:
diff --git a/changelogs/unreleased/dm-gitmodules-parsing.yml b/changelogs/unreleased/dm-gitmodules-parsing.yml
deleted file mode 100644
index a7d755d6c4d..00000000000
--- a/changelogs/unreleased/dm-gitmodules-parsing.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Make .gitmodules parsing more resilient to syntax errors
-merge_request:
-author:
diff --git a/changelogs/unreleased/dm-gravatar-username.yml b/changelogs/unreleased/dm-gravatar-username.yml
deleted file mode 100644
index d50455061ec..00000000000
--- a/changelogs/unreleased/dm-gravatar-username.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Add username parameter to gravatar URL
-merge_request:
-author:
diff --git a/changelogs/unreleased/dm-group-page-name.yml b/changelogs/unreleased/dm-group-page-name.yml
new file mode 100644
index 00000000000..233879364e3
--- /dev/null
+++ b/changelogs/unreleased/dm-group-page-name.yml
@@ -0,0 +1,4 @@
+---
+title: Show group name instead of path on group page
+merge_request:
+author:
diff --git a/changelogs/unreleased/dm-more-dependency-linkers.yml b/changelogs/unreleased/dm-more-dependency-linkers.yml
deleted file mode 100644
index 12d45e71e85..00000000000
--- a/changelogs/unreleased/dm-more-dependency-linkers.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Autolink package names in more dependency files
-merge_request:
-author:
diff --git a/changelogs/unreleased/dm-oauth-config-for.yml b/changelogs/unreleased/dm-oauth-config-for.yml
deleted file mode 100644
index 8fbbd45bb57..00000000000
--- a/changelogs/unreleased/dm-oauth-config-for.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Return nil when looking up config for unknown LDAP provider
-merge_request:
-author:
diff --git a/changelogs/unreleased/dm-outdated-system-note.yml b/changelogs/unreleased/dm-outdated-system-note.yml
deleted file mode 100644
index a1038a1051b..00000000000
--- a/changelogs/unreleased/dm-outdated-system-note.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Add system note with link to diff comparison when MR discussion becomes outdated
-merge_request:
-author:
diff --git a/changelogs/unreleased/dm-paste-code-inside-gfm-code.yml b/changelogs/unreleased/dm-paste-code-inside-gfm-code.yml
deleted file mode 100644
index d078ca449a5..00000000000
--- a/changelogs/unreleased/dm-paste-code-inside-gfm-code.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Don't wrap pasted code when it's already inside code tags
-merge_request:
-author:
diff --git a/changelogs/unreleased/dm-revert-mr-8427.yml b/changelogs/unreleased/dm-revert-mr-8427.yml
deleted file mode 100644
index a91cff2e9cd..00000000000
--- a/changelogs/unreleased/dm-revert-mr-8427.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Revert 'New file from interface on existing branch'
-merge_request:
-author:
diff --git a/changelogs/unreleased/dm-tree-last-commit.yml b/changelogs/unreleased/dm-tree-last-commit.yml
deleted file mode 100644
index 50619fd6ef2..00000000000
--- a/changelogs/unreleased/dm-tree-last-commit.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Show last commit for current tree on tree page
-merge_request:
-author:
diff --git a/changelogs/unreleased/document-foreign-keys.yml b/changelogs/unreleased/document-foreign-keys.yml
deleted file mode 100644
index faa467e8185..00000000000
--- a/changelogs/unreleased/document-foreign-keys.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Add documentation about adding foreign keys
-merge_request:
-author:
diff --git a/changelogs/unreleased/dturner-username.yml b/changelogs/unreleased/dturner-username.yml
deleted file mode 100644
index 09ba822ee65..00000000000
--- a/changelogs/unreleased/dturner-username.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: add username field to push webhook
-merge_request:
-author: David Turner
diff --git a/changelogs/unreleased/dz-fix-submodule-subgroup.yml b/changelogs/unreleased/dz-fix-submodule-subgroup.yml
deleted file mode 100644
index 20c7c9ce657..00000000000
--- a/changelogs/unreleased/dz-fix-submodule-subgroup.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Fix submodule link to then project under subgroup
-merge_request: 11906
-author:
diff --git a/changelogs/unreleased/dz-project-list-cache-key.yml b/changelogs/unreleased/dz-project-list-cache-key.yml
deleted file mode 100644
index 9e4826e686a..00000000000
--- a/changelogs/unreleased/dz-project-list-cache-key.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Use route.cache_key for project list cache key
-merge_request: 11325
-author:
diff --git a/changelogs/unreleased/dz-rename-pipelines-settings-tab.yml b/changelogs/unreleased/dz-rename-pipelines-settings-tab.yml
deleted file mode 100644
index 6a1232523bb..00000000000
--- a/changelogs/unreleased/dz-rename-pipelines-settings-tab.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Rename CI/CD Pipelines to Pipelines in the project settings
-merge_request:
-author:
diff --git a/changelogs/unreleased/enable-auto-cancelling-by-default.yml b/changelogs/unreleased/enable-auto-cancelling-by-default.yml
deleted file mode 100644
index 8b1659bf38b..00000000000
--- a/changelogs/unreleased/enable-auto-cancelling-by-default.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Enable cancelling non-HEAD pending pipelines by default for all projects
-merge_request: 11023
-author:
diff --git a/changelogs/unreleased/environment-detail-view.yml b/changelogs/unreleased/environment-detail-view.yml
deleted file mode 100644
index c74f70ea86d..00000000000
--- a/changelogs/unreleased/environment-detail-view.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Make environment tables responsive
-merge_request:
-author:
diff --git a/changelogs/unreleased/expand-backlog-closed-lists-issue-boards.yml b/changelogs/unreleased/expand-backlog-closed-lists-issue-boards.yml
deleted file mode 100644
index 4796f8e918b..00000000000
--- a/changelogs/unreleased/expand-backlog-closed-lists-issue-boards.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Expand/collapse backlog & closed lists in issue boards
-merge_request:
-author:
diff --git a/changelogs/unreleased/feature-flags-flipper.yml b/changelogs/unreleased/feature-flags-flipper.yml
deleted file mode 100644
index 5be5c44166d..00000000000
--- a/changelogs/unreleased/feature-flags-flipper.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Add feature toggles and API endpoints for admins
-merge_request: 11747
-author:
diff --git a/changelogs/unreleased/feature-gb-persist-pipeline-stages.yml b/changelogs/unreleased/feature-gb-persist-pipeline-stages.yml
deleted file mode 100644
index 1404b342359..00000000000
--- a/changelogs/unreleased/feature-gb-persist-pipeline-stages.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Persist pipeline stages in the database
-merge_request: 11790
-author:
diff --git a/changelogs/unreleased/feature-print-go-version-in-env-info.yml b/changelogs/unreleased/feature-print-go-version-in-env-info.yml
deleted file mode 100644
index 34c19b06eda..00000000000
--- a/changelogs/unreleased/feature-print-go-version-in-env-info.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Print Go version in rake gitlab:env:info
-merge_request: 11241
-author:
diff --git a/changelogs/unreleased/feature-rss-scoped-token.yml b/changelogs/unreleased/feature-rss-scoped-token.yml
deleted file mode 100644
index 740d8778be2..00000000000
--- a/changelogs/unreleased/feature-rss-scoped-token.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Expose atom links with an RSS token instead of using the private token
-merge_request: 11647
-author: Alexis Reigel
diff --git a/changelogs/unreleased/fix-33259.yml b/changelogs/unreleased/fix-33259.yml
deleted file mode 100644
index c68e42c02cf..00000000000
--- a/changelogs/unreleased/fix-33259.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Fix GitHub importer performance on branch existence check
-merge_request:
-author:
diff --git a/changelogs/unreleased/fix-33991.yml b/changelogs/unreleased/fix-33991.yml
new file mode 100644
index 00000000000..39732611b6e
--- /dev/null
+++ b/changelogs/unreleased/fix-33991.yml
@@ -0,0 +1,4 @@
+---
+title: Users can subscribe to group labels on the group labels page
+merge_request:
+author:
diff --git a/changelogs/unreleased/fix-counter-cache-for-acts-as-taggable.yml b/changelogs/unreleased/fix-counter-cache-for-acts-as-taggable.yml
deleted file mode 100644
index e40668546c0..00000000000
--- a/changelogs/unreleased/fix-counter-cache-for-acts-as-taggable.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Fix counter cache for acts as taggable
-merge_request:
-author:
diff --git a/changelogs/unreleased/fix-encoding-binary-issue.yml b/changelogs/unreleased/fix-encoding-binary-issue.yml
deleted file mode 100644
index ac9aff64a88..00000000000
--- a/changelogs/unreleased/fix-encoding-binary-issue.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Fix binary encoding error on MR diffs
-merge_request: 11929
-author:
diff --git a/changelogs/unreleased/fix-gb-exclude-manual-actions-from-cancelable-jobs.yml b/changelogs/unreleased/fix-gb-exclude-manual-actions-from-cancelable-jobs.yml
deleted file mode 100644
index a16fc775b5e..00000000000
--- a/changelogs/unreleased/fix-gb-exclude-manual-actions-from-cancelable-jobs.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Exclude manual actions when checking if pipeline can be canceled
-merge_request: 11562
-author:
diff --git a/changelogs/unreleased/fix-gb-fix-skipped-pipeline-with-allowed-to-fail-jobs.yml b/changelogs/unreleased/fix-gb-fix-skipped-pipeline-with-allowed-to-fail-jobs.yml
new file mode 100644
index 00000000000..f59c6ecd90c
--- /dev/null
+++ b/changelogs/unreleased/fix-gb-fix-skipped-pipeline-with-allowed-to-fail-jobs.yml
@@ -0,0 +1,4 @@
+---
+title: Fix CI/CD status in case there are only allowed to failed jobs in the pipeline
+merge_request: 11166
+author:
diff --git a/changelogs/unreleased/fix-github-clone-wiki.yml b/changelogs/unreleased/fix-github-clone-wiki.yml
deleted file mode 100644
index eadd90e1390..00000000000
--- a/changelogs/unreleased/fix-github-clone-wiki.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Github - Fix token interpolation when cloning wiki repository
-merge_request:
-author:
diff --git a/changelogs/unreleased/fix-github-import.yml b/changelogs/unreleased/fix-github-import.yml
deleted file mode 100644
index 3a57152f7a8..00000000000
--- a/changelogs/unreleased/fix-github-import.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Fix token interpolation when setting the Github remote
-merge_request:
-author:
diff --git a/changelogs/unreleased/fix-head-pipeline-for-commit-status.yml b/changelogs/unreleased/fix-head-pipeline-for-commit-status.yml
new file mode 100644
index 00000000000..f12e7b53790
--- /dev/null
+++ b/changelogs/unreleased/fix-head-pipeline-for-commit-status.yml
@@ -0,0 +1,4 @@
+---
+title: Fix head pipeline stored in merge request for external pipelines
+merge_request: 12478
+author:
diff --git a/changelogs/unreleased/fix-n-plus-one-queries-for-user-access.yml b/changelogs/unreleased/fix-n-plus-one-queries-for-user-access.yml
deleted file mode 100644
index c2671a96b83..00000000000
--- a/changelogs/unreleased/fix-n-plus-one-queries-for-user-access.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Fix N+1 queries for non-members in comment threads
-merge_request:
-author:
diff --git a/changelogs/unreleased/fix-support-for-external-ci-services.yml b/changelogs/unreleased/fix-support-for-external-ci-services.yml
deleted file mode 100644
index eecb4519259..00000000000
--- a/changelogs/unreleased/fix-support-for-external-ci-services.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Fix support for external CI services
-merge_request: 11176
-author:
diff --git a/changelogs/unreleased/fix_commits_page.yml b/changelogs/unreleased/fix_commits_page.yml
deleted file mode 100644
index a2afaf6e626..00000000000
--- a/changelogs/unreleased/fix_commits_page.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Fix duplication of commits header on commits page
-merge_request: 11006
-author: @blackst0ne
diff --git a/changelogs/unreleased/fix_diff_line_comments.yml b/changelogs/unreleased/fix_diff_line_comments.yml
deleted file mode 100644
index bdb0539b49d..00000000000
--- a/changelogs/unreleased/fix_diff_line_comments.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: 'Fix: A diff comment on a change at last line of a file shows as two comments
- in discussion'
-merge_request:
-author:
diff --git a/changelogs/unreleased/gitaly-local-branches.yml b/changelogs/unreleased/gitaly-local-branches.yml
deleted file mode 100644
index adcc0fa6280..00000000000
--- a/changelogs/unreleased/gitaly-local-branches.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Add suport for find_local_branches GRPC from Gitaly
-merge_request: 10059
-author:
diff --git a/changelogs/unreleased/gitaly-opt-out.yml b/changelogs/unreleased/gitaly-opt-out.yml
deleted file mode 100644
index 2f89e0bfc9a..00000000000
--- a/changelogs/unreleased/gitaly-opt-out.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Enable Gitaly by default in installations from source
-merge_request: 11796
-author:
diff --git a/changelogs/unreleased/instrument-merge-request-diff-load-commits.yml b/changelogs/unreleased/instrument-merge-request-diff-load-commits.yml
deleted file mode 100644
index 916b182a48b..00000000000
--- a/changelogs/unreleased/instrument-merge-request-diff-load-commits.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Instrument MergeRequestDiff#load_commits
-merge_request:
-author:
diff --git a/changelogs/unreleased/introduce-source-to-pipelines.yml b/changelogs/unreleased/introduce-source-to-pipelines.yml
deleted file mode 100644
index 7898bd31b39..00000000000
--- a/changelogs/unreleased/introduce-source-to-pipelines.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Introduce source to Pipeline entity
-merge_request:
-author:
diff --git a/changelogs/unreleased/issuable-form-create-label-sub-groups.yml b/changelogs/unreleased/issuable-form-create-label-sub-groups.yml
deleted file mode 100644
index 54b818d6d5e..00000000000
--- a/changelogs/unreleased/issuable-form-create-label-sub-groups.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Fixed create new label form in issue form not working for sub-group projects
-merge_request:
-author:
diff --git a/changelogs/unreleased/issue-23254.yml b/changelogs/unreleased/issue-23254.yml
deleted file mode 100644
index 568a7a41c30..00000000000
--- a/changelogs/unreleased/issue-23254.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Fixed style on unsubscribe page
-merge_request:
-author: Gustav Ernberg
diff --git a/changelogs/unreleased/issue-edit-inline.yml b/changelogs/unreleased/issue-edit-inline.yml
deleted file mode 100644
index db03d1bdac4..00000000000
--- a/changelogs/unreleased/issue-edit-inline.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Enables inline editing for an issues title & description
-merge_request:
-author:
diff --git a/changelogs/unreleased/issue-form-multiple-line-markdown.yml b/changelogs/unreleased/issue-form-multiple-line-markdown.yml
new file mode 100644
index 00000000000..23128f346bc
--- /dev/null
+++ b/changelogs/unreleased/issue-form-multiple-line-markdown.yml
@@ -0,0 +1,4 @@
+---
+title: Fixed multi-line markdown tooltip buttons in issue edit form
+merge_request:
+author:
diff --git a/changelogs/unreleased/issue-template-reproduce-in-example-project.yml b/changelogs/unreleased/issue-template-reproduce-in-example-project.yml
deleted file mode 100644
index 8116007b459..00000000000
--- a/changelogs/unreleased/issue-template-reproduce-in-example-project.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Ask for an example project for bug reports
-merge_request:
-author:
diff --git a/changelogs/unreleased/issue-templates-summary-lines.yml b/changelogs/unreleased/issue-templates-summary-lines.yml
deleted file mode 100644
index 0c8c3d884ce..00000000000
--- a/changelogs/unreleased/issue-templates-summary-lines.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Add summary lines for collapsed details in the bug report template
-merge_request:
-author:
diff --git a/changelogs/unreleased/issue_19262.yml b/changelogs/unreleased/issue_19262.yml
deleted file mode 100644
index 7bcbc647fcb..00000000000
--- a/changelogs/unreleased/issue_19262.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Prevent commits from upstream repositories to be re-processed by forks
-merge_request:
-author:
diff --git a/changelogs/unreleased/issue_27166_2.yml b/changelogs/unreleased/issue_27166_2.yml
deleted file mode 100644
index 9b9906e03dd..00000000000
--- a/changelogs/unreleased/issue_27166_2.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Avoid repeated queries for pipeline builds on merge requests
-merge_request:
-author:
diff --git a/changelogs/unreleased/issue_27168_2.yml b/changelogs/unreleased/issue_27168_2.yml
deleted file mode 100644
index c67692493e0..00000000000
--- a/changelogs/unreleased/issue_27168_2.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Preloads head pipeline for merge request collection
-merge_request:
-author:
diff --git a/changelogs/unreleased/issue_32225_2.yml b/changelogs/unreleased/issue_32225_2.yml
deleted file mode 100644
index 320b9fe00b8..00000000000
--- a/changelogs/unreleased/issue_32225_2.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Handle head pipeline when creating merge requests
-merge_request:
-author:
diff --git a/changelogs/unreleased/jouve-gitlab-ce-admin_keys.yml b/changelogs/unreleased/jouve-gitlab-ce-admin_keys.yml
deleted file mode 100644
index df4de9f4e21..00000000000
--- a/changelogs/unreleased/jouve-gitlab-ce-admin_keys.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Redirect to user's keys index instead of user's index after a key is deleted
- in the admin
-merge_request: 10227
-author: Cyril Jouve
diff --git a/changelogs/unreleased/mabes-gitlab-ce-bypass-auto-login.yml b/changelogs/unreleased/mabes-gitlab-ce-bypass-auto-login.yml
deleted file mode 100644
index a321ed9d7d8..00000000000
--- a/changelogs/unreleased/mabes-gitlab-ce-bypass-auto-login.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Allow manual bypass of auto_sign_in_with_provider with a new param
-merge_request: 10187
-author: Maxime Besson
diff --git a/changelogs/unreleased/migrate-artifacts-to-a-new-path.yml b/changelogs/unreleased/migrate-artifacts-to-a-new-path.yml
deleted file mode 100644
index bd022a3a91b..00000000000
--- a/changelogs/unreleased/migrate-artifacts-to-a-new-path.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Migrate artifacts to a new path
-merge_request:
-author:
diff --git a/changelogs/unreleased/mk-fix-breadcrumb-order-33938.yml b/changelogs/unreleased/mk-fix-breadcrumb-order-33938.yml
deleted file mode 100644
index 790af692b92..00000000000
--- a/changelogs/unreleased/mk-fix-breadcrumb-order-33938.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Fix reversed breadcrumb order for nested groups
-merge_request: 12322
-author:
diff --git a/changelogs/unreleased/mk-fix-git-over-http-rejections.yml b/changelogs/unreleased/mk-fix-git-over-http-rejections.yml
deleted file mode 100644
index e75740e913f..00000000000
--- a/changelogs/unreleased/mk-fix-git-over-http-rejections.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Fix Git-over-HTTP error statuses and improve error messages
-merge_request: 11398
-author:
diff --git a/changelogs/unreleased/mk-fix-issue-34068.yml b/changelogs/unreleased/mk-fix-issue-34068.yml
deleted file mode 100644
index af0a9139568..00000000000
--- a/changelogs/unreleased/mk-fix-issue-34068.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Fix 500 when failing to create private group
-merge_request: 12394
-author:
diff --git a/changelogs/unreleased/mrchrisw-catch-openssl.yml b/changelogs/unreleased/mrchrisw-catch-openssl.yml
deleted file mode 100644
index a8b433fb0cd..00000000000
--- a/changelogs/unreleased/mrchrisw-catch-openssl.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Rescue OpenSSL::SSL::SSLError in JiraService & IssueTrackerService
-merge_request:
-author:
diff --git a/changelogs/unreleased/omega-submodules.yml b/changelogs/unreleased/omega-submodules.yml
deleted file mode 100644
index 1488eb72174..00000000000
--- a/changelogs/unreleased/omega-submodules.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: 'Repository browser: handle in-repository submodule urls'
-merge_request:
-author: David Turner
diff --git a/changelogs/unreleased/pat-alert-when-signin-disabled.yml b/changelogs/unreleased/pat-alert-when-signin-disabled.yml
new file mode 100644
index 00000000000..dca3670aeb7
--- /dev/null
+++ b/changelogs/unreleased/pat-alert-when-signin-disabled.yml
@@ -0,0 +1,4 @@
+---
+title: Provide hint to create a personal access token for Git over HTTP
+merge_request: 12105
+author: Robin Bobbitt
diff --git a/changelogs/unreleased/polish-sidebar-toggle.yml b/changelogs/unreleased/polish-sidebar-toggle.yml
new file mode 100644
index 00000000000..41ec567fc52
--- /dev/null
+++ b/changelogs/unreleased/polish-sidebar-toggle.yml
@@ -0,0 +1,4 @@
+---
+title: Remove unused space in sidebar todo toggle when not signed in
+merge_request:
+author:
diff --git a/changelogs/unreleased/prevent-project-transfer.yml b/changelogs/unreleased/prevent-project-transfer.yml
deleted file mode 100644
index a5c74676aab..00000000000
--- a/changelogs/unreleased/prevent-project-transfer.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Prevent project transfers if a new group is not selected
-merge_request:
-author:
diff --git a/changelogs/unreleased/projects-api-import-status.yml b/changelogs/unreleased/projects-api-import-status.yml
deleted file mode 100644
index 06603c0adec..00000000000
--- a/changelogs/unreleased/projects-api-import-status.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Expose import_status in Projects API
-merge_request: 11851
-author: Robin Bobbitt
diff --git a/changelogs/unreleased/protected-branches-no-one-merge.yml b/changelogs/unreleased/protected-branches-no-one-merge.yml
deleted file mode 100644
index 52d93793f3d..00000000000
--- a/changelogs/unreleased/protected-branches-no-one-merge.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Allow 'no one' as an option for allowed to merge on a procted branch
-merge_request:
-author:
diff --git a/changelogs/unreleased/reduce-sidekiq-wait-timings.yml b/changelogs/unreleased/reduce-sidekiq-wait-timings.yml
deleted file mode 100644
index 4d23accc82e..00000000000
--- a/changelogs/unreleased/reduce-sidekiq-wait-timings.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Reduce time spent waiting for certain Sidekiq jobs to complete
-merge_request:
-author:
diff --git a/changelogs/unreleased/refactor-projects-finder-init-collection.yml b/changelogs/unreleased/refactor-projects-finder-init-collection.yml
deleted file mode 100644
index c8113419f21..00000000000
--- a/changelogs/unreleased/refactor-projects-finder-init-collection.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Refactor ProjectsFinder#init_collection to produce more efficient queries for
- retrieving projects
-merge_request:
-author:
diff --git a/changelogs/unreleased/remove-old-isobject.yml b/changelogs/unreleased/remove-old-isobject.yml
deleted file mode 100644
index 67b18642253..00000000000
--- a/changelogs/unreleased/remove-old-isobject.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Remove unused code and uses underscore
-merge_request:
-author:
diff --git a/changelogs/unreleased/rename-builds-controller.yml b/changelogs/unreleased/rename-builds-controller.yml
deleted file mode 100644
index 7f6872ccf95..00000000000
--- a/changelogs/unreleased/rename-builds-controller.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Change /builds in the URL to /-/jobs. Backward URLs were also added
-merge_request: 11407
-author:
diff --git a/changelogs/unreleased/replace_spinach_spec_profile_notifications-feature.yml b/changelogs/unreleased/replace_spinach_spec_profile_notifications-feature.yml
new file mode 100644
index 00000000000..38227ebfa7a
--- /dev/null
+++ b/changelogs/unreleased/replace_spinach_spec_profile_notifications-feature.yml
@@ -0,0 +1,4 @@
+---
+title: Replace 'profile/notifications.feature' spinach test with an rspec analog
+merge_request: 12345
+author: @blackst0ne
diff --git a/changelogs/unreleased/rework-authorizations-performance.yml b/changelogs/unreleased/rework-authorizations-performance.yml
deleted file mode 100644
index f64257a6f56..00000000000
--- a/changelogs/unreleased/rework-authorizations-performance.yml
+++ /dev/null
@@ -1,6 +0,0 @@
----
-title: >
- Project authorizations are calculated much faster when using PostgreSQL, and
- nested groups support for MySQL has been removed
-merge_request: 10885
-author:
diff --git a/changelogs/unreleased/search-restrict-projects-to-group.yml b/changelogs/unreleased/search-restrict-projects-to-group.yml
deleted file mode 100644
index ac134bc5bce..00000000000
--- a/changelogs/unreleased/search-restrict-projects-to-group.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Restricts search projects dropdown to group projects when group is selected
-merge_request:
-author:
diff --git a/changelogs/unreleased/sh-fix-container-registry-s3-redirects.yml b/changelogs/unreleased/sh-fix-container-registry-s3-redirects.yml
deleted file mode 100644
index 1e783811b66..00000000000
--- a/changelogs/unreleased/sh-fix-container-registry-s3-redirects.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Properly handle container registry redirects to fix metadata stored on a S3 backend
-merge_request:
-author:
diff --git a/changelogs/unreleased/sh-fix-refactor-uploader-work-dir.yml b/changelogs/unreleased/sh-fix-refactor-uploader-work-dir.yml
deleted file mode 100644
index 255608bd89a..00000000000
--- a/changelogs/unreleased/sh-fix-refactor-uploader-work-dir.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Set artifact working directory to be in the destination store to prevent unnecessary I/O
-merge_request:
-author:
diff --git a/changelogs/unreleased/sync-email-from-omniauth.yml b/changelogs/unreleased/sync-email-from-omniauth.yml
deleted file mode 100644
index ed14a95a5f1..00000000000
--- a/changelogs/unreleased/sync-email-from-omniauth.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Sync email address from specified omniauth provider
-merge_request: 11268
-author: Robin Bobbitt
diff --git a/changelogs/unreleased/task-list-2.yml b/changelogs/unreleased/task-list-2.yml
deleted file mode 100644
index cbae8178081..00000000000
--- a/changelogs/unreleased/task-list-2.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Update task_list to version 2.0.0
-merge_request: 11525
-author: Jared Deckard <jared.deckard@gmail.com>
diff --git a/changelogs/unreleased/tc-cache-trackable-attributes.yml b/changelogs/unreleased/tc-cache-trackable-attributes.yml
deleted file mode 100644
index 4a2cf50893a..00000000000
--- a/changelogs/unreleased/tc-cache-trackable-attributes.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: "Limit User's trackable attributes, like `current_sign_in_at`, to update at most once/hour"
-merge_request: 11053
-author:
diff --git a/changelogs/unreleased/tc-clean-pending-delete-projects.yml b/changelogs/unreleased/tc-clean-pending-delete-projects.yml
deleted file mode 100644
index 31b43999c31..00000000000
--- a/changelogs/unreleased/tc-clean-pending-delete-projects.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Add post-deploy migration to clean up projects in `pending_delete` state
-merge_request: 11044
-author:
diff --git a/changelogs/unreleased/tc-improve-project-api-perf.yml b/changelogs/unreleased/tc-improve-project-api-perf.yml
deleted file mode 100644
index 7e88466c058..00000000000
--- a/changelogs/unreleased/tc-improve-project-api-perf.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Improve performance of ProjectFinder used in /projects API endpoint
-merge_request: 11666
-author:
diff --git a/changelogs/unreleased/tc-refactor-projects-finder-init-collection.yml b/changelogs/unreleased/tc-refactor-projects-finder-init-collection.yml
new file mode 100644
index 00000000000..7bcbd6468c7
--- /dev/null
+++ b/changelogs/unreleased/tc-refactor-projects-finder-init-collection.yml
@@ -0,0 +1,4 @@
+---
+title: Add User#full_private_access? to check if user has access to all private groups & projects
+merge_request: 12373
+author:
diff --git a/changelogs/unreleased/up-arrow-focus-discussion-comment.yml b/changelogs/unreleased/up-arrow-focus-discussion-comment.yml
deleted file mode 100644
index 5457dab6d3d..00000000000
--- a/changelogs/unreleased/up-arrow-focus-discussion-comment.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Fix up arrow not editing last discussion comment
-merge_request:
-author:
diff --git a/changelogs/unreleased/update-admin-health-page.yml b/changelogs/unreleased/update-admin-health-page.yml
deleted file mode 100644
index 51aa6682b49..00000000000
--- a/changelogs/unreleased/update-admin-health-page.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Added application readiness endpoints to the monitoring health check admin
- view
-merge_request:
-author:
diff --git a/changelogs/unreleased/update_bootsnap_1-1-1.yml b/changelogs/unreleased/update_bootsnap_1-1-1.yml
new file mode 100644
index 00000000000..9ecfe4b60c8
--- /dev/null
+++ b/changelogs/unreleased/update_bootsnap_1-1-1.yml
@@ -0,0 +1,4 @@
+---
+title: Bump bootsnap to 1.1.1
+merge_request: 12425
+author: @blackst0ne
diff --git a/changelogs/unreleased/use_relative_path_for_project_avatars.yml b/changelogs/unreleased/use_relative_path_for_project_avatars.yml
deleted file mode 100644
index e3d0c0e1187..00000000000
--- a/changelogs/unreleased/use_relative_path_for_project_avatars.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Use relative paths for group/project/user avatars
-merge_request: 11001
-author: blackst0ne
diff --git a/changelogs/unreleased/wait-for-ajax-handling-all-js-requests.yml b/changelogs/unreleased/wait-for-ajax-handling-all-js-requests.yml
deleted file mode 100644
index 14aebe792c2..00000000000
--- a/changelogs/unreleased/wait-for-ajax-handling-all-js-requests.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Use wait_for_requests for both ajax and Vue requests
-merge_request:
-author:
diff --git a/changelogs/unreleased/winh-current-user-filter.yml b/changelogs/unreleased/winh-current-user-filter.yml
deleted file mode 100644
index e5409827b31..00000000000
--- a/changelogs/unreleased/winh-current-user-filter.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Show current user immediately in issuable filters
-merge_request: 11630
-author:
diff --git a/changelogs/unreleased/winh-pipeline-author-link.yml b/changelogs/unreleased/winh-pipeline-author-link.yml
deleted file mode 100644
index 1b903d1e357..00000000000
--- a/changelogs/unreleased/winh-pipeline-author-link.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Link to commit author user page from pipelines
-merge_request: 11100
-author:
diff --git a/changelogs/unreleased/winh-styled-people-search-bar.yml b/changelogs/unreleased/winh-styled-people-search-bar.yml
deleted file mode 100644
index a088af37d8d..00000000000
--- a/changelogs/unreleased/winh-styled-people-search-bar.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Style people in issuable search bar
-merge_request: 11402
-author:
diff --git a/changelogs/unreleased/zj-clean-up-ci-variables-table.yml b/changelogs/unreleased/zj-clean-up-ci-variables-table.yml
deleted file mode 100644
index ea2db40d590..00000000000
--- a/changelogs/unreleased/zj-clean-up-ci-variables-table.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Cleanup ci_variables schema and table
-merge_request:
-author:
diff --git a/changelogs/unreleased/zj-faster-charts-page.yml b/changelogs/unreleased/zj-faster-charts-page.yml
new file mode 100644
index 00000000000..9afcf111328
--- /dev/null
+++ b/changelogs/unreleased/zj-faster-charts-page.yml
@@ -0,0 +1,4 @@
+---
+title: Improve performance of the pipeline charts page
+merge_request: 12378
+author:
diff --git a/changelogs/unreleased/zj-i18n-pipeline-schedules.yml b/changelogs/unreleased/zj-i18n-pipeline-schedules.yml
deleted file mode 100644
index 51c82a16359..00000000000
--- a/changelogs/unreleased/zj-i18n-pipeline-schedules.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Allow translation of Pipeline Schedules
-merge_request:
-author:
diff --git a/changelogs/unreleased/zj-job-view-goes-real-time.yml b/changelogs/unreleased/zj-job-view-goes-real-time.yml
deleted file mode 100644
index 376c9dfa65f..00000000000
--- a/changelogs/unreleased/zj-job-view-goes-real-time.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Job details page update real time
-merge_request: 11651
-author:
diff --git a/changelogs/unreleased/zj-pipeline-schedule-owner.yml b/changelogs/unreleased/zj-pipeline-schedule-owner.yml
deleted file mode 100644
index be704e173ab..00000000000
--- a/changelogs/unreleased/zj-pipeline-schedule-owner.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Add foreign key for pipeline schedule owner
-merge_request: 11233
-author:
diff --git a/changelogs/unreleased/zj-prom-pipeline-count.yml b/changelogs/unreleased/zj-prom-pipeline-count.yml
deleted file mode 100644
index 191e4f2f949..00000000000
--- a/changelogs/unreleased/zj-prom-pipeline-count.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Add prometheus metrics on pipeline creation
-merge_request:
-author:
diff --git a/changelogs/unreleased/zj-raise-etag-route-regex-miss.yml b/changelogs/unreleased/zj-raise-etag-route-regex-miss.yml
deleted file mode 100644
index 57a5f4e44c0..00000000000
--- a/changelogs/unreleased/zj-raise-etag-route-regex-miss.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Fix etag route not being a match for environments
-merge_request:
-author:
diff --git a/changelogs/unreleased/zj-read-registry-pat.yml b/changelogs/unreleased/zj-read-registry-pat.yml
deleted file mode 100644
index d36159bbdf5..00000000000
--- a/changelogs/unreleased/zj-read-registry-pat.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Allow pulling of container images using personal access tokens
-merge_request: 11845
-author:
diff --git a/changelogs/unreleased/zj-realtime-env-list.yml b/changelogs/unreleased/zj-realtime-env-list.yml
deleted file mode 100644
index 6460d17edc9..00000000000
--- a/changelogs/unreleased/zj-realtime-env-list.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Make environment table realtime
-merge_request: 11333
-author:
diff --git a/changelogs/unreleased/zj-review-apps-usage-data.yml b/changelogs/unreleased/zj-review-apps-usage-data.yml
new file mode 100644
index 00000000000..7d224d0fc32
--- /dev/null
+++ b/changelogs/unreleased/zj-review-apps-usage-data.yml
@@ -0,0 +1,4 @@
+---
+title: Add review apps to usage metrics
+merge_request: 12185
+author:
diff --git a/changelogs/unreleased/zj-sort-env-folders.yml b/changelogs/unreleased/zj-sort-env-folders.yml
deleted file mode 100644
index b3ca97aef94..00000000000
--- a/changelogs/unreleased/zj-sort-env-folders.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Sort folder for environments
-merge_request:
-author:
diff --git a/config/application.rb b/config/application.rb
index 8bbecf3ed0f..12242c3b0f5 100644
--- a/config/application.rb
+++ b/config/application.rb
@@ -109,6 +109,7 @@ module Gitlab
config.assets.precompile << "lib/ace.js"
config.assets.precompile << "vendor/assets/fonts/*"
config.assets.precompile << "test.css"
+ config.assets.precompile << "new_nav.css"
# Version of your assets, change this if you want to expire all your assets
config.assets.version = '1.0'
diff --git a/config/boot.rb b/config/boot.rb
index 2d01092acd5..02baeab29ab 100644
--- a/config/boot.rb
+++ b/config/boot.rb
@@ -5,6 +5,12 @@ ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
require 'bundler/setup' if File.exist?(ENV['BUNDLE_GEMFILE'])
+begin
+ require 'bootsnap/setup'
+rescue SystemCallError => exception
+ $stderr.puts "WARNING: Bootsnap failed to setup: #{exception.message}"
+end
+
# set default directory for multiproces metrics gathering
if ENV['RAILS_ENV'] == 'development' || ENV['RAILS_ENV'] == 'test'
ENV['prometheus_multiproc_dir'] ||= 'tmp/prometheus_multiproc_dir'
diff --git a/db/migrate/20170622162730_add_ref_fetched_to_merge_request.rb b/db/migrate/20170622162730_add_ref_fetched_to_merge_request.rb
new file mode 100644
index 00000000000..62aa1a4b4f0
--- /dev/null
+++ b/db/migrate/20170622162730_add_ref_fetched_to_merge_request.rb
@@ -0,0 +1,9 @@
+class AddRefFetchedToMergeRequest < ActiveRecord::Migration
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def change
+ add_column :merge_requests, :ref_fetched, :boolean
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 028556bdccf..8c7440ee610 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -11,7 +11,7 @@
#
# It's strongly recommended that you check this file into your version control system.
-ActiveRecord::Schema.define(version: 20170621102400) do
+ActiveRecord::Schema.define(version: 20170622162730) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
@@ -770,6 +770,7 @@ ActiveRecord::Schema.define(version: 20170621102400) do
t.datetime "last_edited_at"
t.integer "last_edited_by_id"
t.integer "head_pipeline_id"
+ t.boolean "ref_fetched"
end
add_index "merge_requests", ["assignee_id"], name: "index_merge_requests_on_assignee_id", using: :btree
diff --git a/doc/ci/examples/deployment/composer-npm-deploy.md b/doc/ci/examples/deployment/composer-npm-deploy.md
index 8b0d8a003fd..b9f0485290e 100644
--- a/doc/ci/examples/deployment/composer-npm-deploy.md
+++ b/doc/ci/examples/deployment/composer-npm-deploy.md
@@ -20,12 +20,12 @@ before_script:
- php -r "unlink('composer-setup.php');"
```
-This will make sure we have all requirements ready. Next, we want to run `composer update` to fetch all PHP dependencies and `npm install` to load node packages, then run the `npm` script. We need to append them into `before_script` section:
+This will make sure we have all requirements ready. Next, we want to run `composer install` to fetch all PHP dependencies and `npm install` to load node packages, then run the `npm` script. We need to append them into `before_script` section:
```yaml
before_script:
# ...
- - php composer.phar update
+ - php composer.phar install
- npm install
- npm run deploy
```
@@ -133,7 +133,7 @@ before_script:
- php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
- php composer-setup.php
- php -r "unlink('composer-setup.php');"
- - php composer.phar update
+ - php composer.phar install
- npm install
- npm run deploy
- 'which ssh-agent || ( apt-get update -y && apt-get install openssh-client -y )'
diff --git a/doc/ci/quick_start/README.md b/doc/ci/quick_start/README.md
index 41cae58782d..88e53ff40e8 100644
--- a/doc/ci/quick_start/README.md
+++ b/doc/ci/quick_start/README.md
@@ -155,7 +155,7 @@ Find more information about different Runners in the
[Runners](../runners/README.md) documentation.
You can find whether any Runners are assigned to your project by going to
-**Settings ➔ CI/CD Pipelines**. Setting up a Runner is easy and straightforward. The
+**Settings ➔ Pipelines**. Setting up a Runner is easy and straightforward. The
official Runner supported by GitLab is written in Go and its documentation
can be found at <https://docs.gitlab.com/runner/>.
@@ -168,7 +168,7 @@ Follow the links above to set up your own Runner or use a Shared Runner as
described in the next section.
Once the Runner has been set up, you should see it on the Runners page of your
-project, following **Settings ➔ CI/CD Pipelines**.
+project, following **Settings ➔ Pipelines**.
![Activated runners](img/runners_activated.png)
@@ -181,7 +181,7 @@ These are special virtual machines that run on GitLab's infrastructure and can
build any project.
To enable the **Shared Runners** you have to go to your project's
-**Settings ➔ CI/CD Pipelines** and click **Enable shared runners**.
+**Settings ➔ Pipelines** and click **Enable shared runners**.
[Read more on Shared Runners](../runners/README.md).
diff --git a/doc/development/architecture.md b/doc/development/architecture.md
index acd5e3c2093..54029e00507 100644
--- a/doc/development/architecture.md
+++ b/doc/development/architecture.md
@@ -194,3 +194,7 @@ bundle exec rake gitlab:check RAILS_ENV=production
```
Note: It is recommended to log into the `git` user using `sudo -i -u git` or `sudo su - git`. While the sudo commands provided by gitlabhq work in Ubuntu they do not always work in RHEL.
+
+## GitLab.com
+
+We've also detailed [our architecture of GitLab.com](https://about.gitlab.com/handbook/infrastructure/production-architecture/) but this is probably over the top unless you have millions of users.
diff --git a/doc/development/fe_guide/style_guide_js.md b/doc/development/fe_guide/style_guide_js.md
index d2d89517241..ae844fa1051 100644
--- a/doc/development/fe_guide/style_guide_js.md
+++ b/doc/development/fe_guide/style_guide_js.md
@@ -463,20 +463,24 @@ A forEach will cause side effects, it will be mutating the array being iterated.
1. `destroyed`
#### Vue and Boostrap
-1. Tooltips: Do not rely on `has-tooltip` class name for vue components
+1. Tooltips: Do not rely on `has-tooltip` class name for Vue components
```javascript
// bad
- <span class="has-tooltip">
+ <span
+ class="has-tooltip"
+ title="Some tooltip text">
Text
</span>
// good
- <span data-toggle="tooltip">
+ <span
+ v-tooltip
+ title="Some tooltip text">
Text
</span>
```
-1. Tooltips: When using a tooltip, include the tooltip mixin
+1. Tooltips: When using a tooltip, include the tooltip directive, `./app/assets/javascripts/vue_shared/directives/tooltip.js`
1. Don't change `data-original-title`.
```javascript
diff --git a/doc/install/requirements.md b/doc/install/requirements.md
index 643fe5b686b..a3d676433e6 100644
--- a/doc/install/requirements.md
+++ b/doc/install/requirements.md
@@ -95,15 +95,16 @@ installation (e.g. the number of users, projects, etc).
We currently support the following databases:
- PostgreSQL (highly recommended)
-- MySQL/MariaDB (doesn't support all features)
+- MySQL/MariaDB (strongly discouraged, not all GitLab features are supported, no support for [MySQL/MariaDB GTID](https://mariadb.com/kb/en/mariadb/gtid/))
-We **highly recommend** the use of PostgreSQL instead of MySQL/MariaDB as not all
+We highly recommend the use of PostgreSQL instead of MySQL/MariaDB as not all
features of GitLab work with MySQL/MariaDB:
1. MySQL support for subgroups was [dropped with GitLab 9.3][post].
See [issue #30472][30472] for more information.
1. GitLab Geo does [not support MySQL](https://docs.gitlab.com/ee/gitlab-geo/database.html#mysql-replication).
1. [Zero downtime migrations][zero] do not work with MySQL
+1. We expect this list to grow over time.
Existing users using GitLab with MySQL/MariaDB are advised to
[migrate to PostgreSQL](../update/mysql_to_postgresql.md) instead.
diff --git a/doc/user/project/integrations/webhooks.md b/doc/user/project/integrations/webhooks.md
index 0517ed3ec18..023c6932e41 100644
--- a/doc/user/project/integrations/webhooks.md
+++ b/doc/user/project/integrations/webhooks.md
@@ -736,7 +736,7 @@ X-Gitlab-Event: Merge Request Hook
### Wiki Page events
-Triggered when a wiki page is created, edited or deleted.
+Triggered when a wiki page is created, updated or deleted.
**Request Header**:
diff --git a/doc/user/project/pipelines/settings.md b/doc/user/project/pipelines/settings.md
index 1d2eba4f74b..a992a348c0f 100644
--- a/doc/user/project/pipelines/settings.md
+++ b/doc/user/project/pipelines/settings.md
@@ -1,7 +1,7 @@
# Pipelines settings
To reach the pipelines settings navigate to your project's
-**Settings ➔ CI/CD Pipelines**.
+**Settings ➔ Pipelines**.
The following settings can be configured per project.
diff --git a/features/dashboard/merge_requests.feature b/features/dashboard/merge_requests.feature
deleted file mode 100644
index 4a2c997d707..00000000000
--- a/features/dashboard/merge_requests.feature
+++ /dev/null
@@ -1,21 +0,0 @@
-@dashboard
-Feature: Dashboard Merge Requests
- Background:
- Given I sign in as a user
- And I have authored merge requests
- And I have assigned merge requests
- And I have other merge requests
- And I visit dashboard merge requests page
-
- Scenario: I should see assigned merge_requests
- Then I should see merge requests assigned to me
-
- @javascript
- Scenario: I should see authored merge_requests
- When I click "Authored by me" link
- Then I should see merge requests authored by me
-
- @javascript
- Scenario: I should see all merge_requests
- When I click "All" link
- Then I should see all merge requests
diff --git a/features/dashboard/todos.feature b/features/dashboard/todos.feature
deleted file mode 100644
index 0b23bbb7951..00000000000
--- a/features/dashboard/todos.feature
+++ /dev/null
@@ -1,28 +0,0 @@
-@dashboard
-Feature: Dashboard Todos
- Background:
- Given I sign in as a user
- And I own project "Shop"
- And "John Doe" is a developer of project "Shop"
- And "Mary Jane" is a developer of project "Shop"
- And "Mary Jane" owns private project "Enterprise"
- And I am a developer of project "Enterprise"
- And I have todos
- And I visit dashboard todos page
-
- @javascript
- Scenario: I mark todos as done
- Then I should see todos assigned to me
- And I mark the todo as done
- Then I should see the todo marked as done
-
- @javascript
- Scenario: I mark all todos as done
- Then I should see todos assigned to me
- And I mark all todos as done
- Then I should see all todos marked as done
-
- @javascript
- Scenario: I click on a todo row
- Given I click on the todo
- Then I should be directed to the corresponding page
diff --git a/features/group/members.feature b/features/group/members.feature
index e539f6a1273..49a44f57cbb 100644
--- a/features/group/members.feature
+++ b/features/group/members.feature
@@ -4,65 +4,6 @@ Feature: Group Members
And "John Doe" is owner of group "Owned"
And "John Doe" is guest of group "Guest"
- # Leave
-
- @javascript
- Scenario: Owner should be able to remove himself from group if he is not the last owner
- Given "Mary Jane" is owner of group "Owned"
- When I visit group "Owned" members page
- Then I should see user "John Doe" in team list
- Then I should see user "Mary Jane" in team list
- When I click on the "Remove User From Group" button for "John Doe"
- And I visit group "Owned" members page
- Then I should not see user "John Doe" in team list
- Then I should see user "Mary Jane" in team list
-
- @javascript
- Scenario: Owner should not be able to remove himself from group if he is the last owner
- Given "Mary Jane" is guest of group "Owned"
- When I visit group "Owned" members page
- Then I should see user "John Doe" in team list
- Then I should see user "Mary Jane" in team list
- Then I should not see the "Remove User From Group" button for "John Doe"
-
- @javascript
- Scenario: Guest should be able to remove himself from group
- Given "Mary Jane" is guest of group "Guest"
- When I visit group "Guest" members page
- Then I should see user "John Doe" in team list
- Then I should see user "Mary Jane" in team list
- When I click on the "Remove User From Group" button for "John Doe"
- When I visit group "Guest" members page
- Then I should not see user "John Doe" in team list
- Then I should see user "Mary Jane" in team list
-
- @javascript
- Scenario: Guest should be able to remove himself from group even if he is the only user in the group
- When I visit group "Guest" members page
- Then I should see user "John Doe" in team list
- When I click on the "Remove User From Group" button for "John Doe"
- When I visit group "Guest" members page
- Then I should not see user "John Doe" in team list
-
- # Remove others
-
- Scenario: Owner should be able to remove other users from group
- Given "Mary Jane" is owner of group "Owned"
- When I visit group "Owned" members page
- Then I should see user "John Doe" in team list
- Then I should see user "Mary Jane" in team list
- When I click on the "Remove User From Group" button for "Mary Jane"
- When I visit group "Owned" members page
- Then I should see user "John Doe" in team list
- Then I should not see user "Mary Jane" in team list
-
- Scenario: Guest should not be able to remove other users from group
- Given "Mary Jane" is guest of group "Guest"
- When I visit group "Guest" members page
- Then I should see user "John Doe" in team list
- Then I should see user "Mary Jane" in team list
- Then I should not see the "Remove User From Group" button for "Mary Jane"
-
Scenario: Search member by name
Given "Mary Jane" is guest of group "Guest"
And I visit group "Guest" members page
diff --git a/features/profile/notifications.feature b/features/profile/notifications.feature
deleted file mode 100644
index ef8743932f5..00000000000
--- a/features/profile/notifications.feature
+++ /dev/null
@@ -1,15 +0,0 @@
-@profile
-Feature: Profile Notifications
- Background:
- Given I sign in as a user
- And I own project "Shop"
-
- Scenario: I visit notifications tab
- When I visit profile notifications page
- Then I should see global notifications settings
-
- @javascript
- Scenario: I edit Project Notifications
- Given I visit profile notifications page
- When I select Mention setting from dropdown
- Then I should see Notification saved message
diff --git a/features/steps/dashboard/merge_requests.rb b/features/steps/dashboard/merge_requests.rb
deleted file mode 100644
index 909ffec3646..00000000000
--- a/features/steps/dashboard/merge_requests.rb
+++ /dev/null
@@ -1,121 +0,0 @@
-class Spinach::Features::DashboardMergeRequests < Spinach::FeatureSteps
- include SharedAuthentication
- include SharedPaths
- include Select2Helper
-
- step 'I should see merge requests assigned to me' do
- should_see(assigned_merge_request)
- should_see(assigned_merge_request_from_fork)
- should_not_see(authored_merge_request)
- should_not_see(authored_merge_request_from_fork)
- should_not_see(other_merge_request)
- end
-
- step 'I should see merge requests authored by me' do
- should_see(authored_merge_request)
- should_see(authored_merge_request_from_fork)
- should_not_see(assigned_merge_request)
- should_not_see(assigned_merge_request_from_fork)
- should_not_see(other_merge_request)
- end
-
- step 'I should see all merge requests' do
- should_see(authored_merge_request)
- should_see(assigned_merge_request)
- should_see(other_merge_request)
- end
-
- step 'I have authored merge requests' do
- authored_merge_request
- authored_merge_request_from_fork
- end
-
- step 'I have assigned merge requests' do
- assigned_merge_request
- assigned_merge_request_from_fork
- end
-
- step 'I have other merge requests' do
- other_merge_request
- end
-
- step 'I click "Authored by me" link' do
- find("#assignee_id").set("")
- find(".js-author-search", match: :first).click
- find(".dropdown-menu-author li a", match: :first, text: current_user.to_reference).click
- end
-
- step 'I click "All" link' do
- find(".js-author-search").click
- expect(page).to have_selector(".dropdown-menu-author li a")
- find(".dropdown-menu-author li a", match: :first).click
- expect(page).not_to have_selector(".dropdown-menu-author li a")
-
- find(".js-assignee-search").click
- expect(page).to have_selector(".dropdown-menu-assignee li a")
- find(".dropdown-menu-assignee li a", match: :first).click
- expect(page).not_to have_selector(".dropdown-menu-assignee li a")
- end
-
- def should_see(merge_request)
- expect(page).to have_content(merge_request.title[0..10])
- end
-
- def should_not_see(merge_request)
- expect(page).not_to have_content(merge_request.title[0..10])
- end
-
- def assigned_merge_request
- @assigned_merge_request ||= create :merge_request,
- assignee: current_user,
- target_project: project,
- source_project: project
- end
-
- def authored_merge_request
- @authored_merge_request ||= create :merge_request,
- source_branch: 'markdown',
- author: current_user,
- target_project: project,
- source_project: project
- end
-
- def other_merge_request
- @other_merge_request ||= create :merge_request,
- source_branch: 'fix',
- target_project: project,
- source_project: project
- end
-
- def authored_merge_request_from_fork
- @authored_merge_request_from_fork ||= create :merge_request,
- source_branch: 'feature_conflict',
- author: current_user,
- target_project: public_project,
- source_project: forked_project
- end
-
- def assigned_merge_request_from_fork
- @assigned_merge_request_from_fork ||= create :merge_request,
- source_branch: 'markdown',
- assignee: current_user,
- target_project: public_project,
- source_project: forked_project
- end
-
- def project
- @project ||= begin
- project = create(:project, :repository)
- project.team << [current_user, :master]
- project
- end
- end
-
- def public_project
- @public_project ||= create(:project, :public, :repository)
- end
-
- def forked_project
- @forked_project ||= Projects::ForkService.new(public_project, current_user).execute
- end
-end
diff --git a/features/steps/dashboard/todos.rb b/features/steps/dashboard/todos.rb
deleted file mode 100644
index 4a33babe3bd..00000000000
--- a/features/steps/dashboard/todos.rb
+++ /dev/null
@@ -1,191 +0,0 @@
-class Spinach::Features::DashboardTodos < Spinach::FeatureSteps
- include SharedAuthentication
- include SharedPaths
- include SharedProject
- include SharedUser
- include WaitForRequests
-
- step '"John Doe" is a developer of project "Shop"' do
- project.team << [john_doe, :developer]
- end
-
- step 'I am a developer of project "Enterprise"' do
- enterprise.team << [current_user, :developer]
- end
-
- step '"Mary Jane" is a developer of project "Shop"' do
- project.team << [john_doe, :developer]
- end
-
- step 'I have todos' do
- create(:todo, user: current_user, project: project, author: mary_jane, target: issue, action: Todo::MENTIONED)
- create(:todo, user: current_user, project: project, author: john_doe, target: issue, action: Todo::ASSIGNED)
- note = create(:note, author: john_doe, noteable: issue, note: "#{current_user.to_reference} Wdyt?", project: project)
- create(:todo, user: current_user, project: project, author: john_doe, target: issue, action: Todo::MENTIONED, note: note)
- create(:todo, user: current_user, project: project, author: john_doe, target: merge_request, action: Todo::ASSIGNED)
- end
-
- step 'I should see todos assigned to me' do
- merge_request_reference = merge_request.to_reference(full: true)
- issue_reference = issue.to_reference(full: true)
-
- page.within('.todos-count') { expect(page).to have_content '4' }
- expect(page).to have_content 'To do 4'
- expect(page).to have_content 'Done 0'
-
- expect(page).to have_link project.name_with_namespace
- should_see_todo(1, "John Doe assigned you merge request #{merge_request_reference}", merge_request.title)
- should_see_todo(2, "John Doe mentioned you on issue #{issue_reference}", "#{current_user.to_reference} Wdyt?")
- should_see_todo(3, "John Doe assigned you issue #{issue_reference}", issue.title)
- should_see_todo(4, "Mary Jane mentioned you on issue #{issue_reference}", issue.title)
- end
-
- step 'I mark the todo as done' do
- page.within('.todo:nth-child(1)') do
- click_link 'Done'
- end
-
- page.within('.todos-count') { expect(page).to have_content '3' }
- expect(page).to have_content 'To do 3'
- expect(page).to have_content 'Done 1'
- should_see_todo(1, "John Doe assigned you merge request #{merge_request.to_reference(full: true)}", merge_request.title, state: :done_reversible)
- end
-
- step 'I mark all todos as done' do
- merge_request_reference = merge_request.to_reference(full: true)
- issue_reference = issue.to_reference(full: true)
-
- find('.js-todos-mark-all').trigger('click')
-
- page.within('.todos-count') { expect(page).to have_content '0' }
- expect(page).to have_content 'To do 0'
- expect(page).to have_content 'Done 4'
- expect(page).to have_content "You're all done!"
- expect('.prepend-top-default').not_to have_link project.name_with_namespace
- should_not_see_todo "John Doe assigned you merge request #{merge_request_reference}"
- should_not_see_todo "John Doe mentioned you on issue #{issue_reference}"
- should_not_see_todo "John Doe assigned you issue #{issue_reference}"
- should_not_see_todo "Mary Jane mentioned you on issue #{issue_reference}"
- end
-
- step 'I should see the todo marked as done' do
- find('.todos-done a').trigger('click')
-
- expect(page).to have_link project.name_with_namespace
- should_see_todo(1, "John Doe assigned you merge request #{merge_request.to_reference(full: true)}", merge_request.title, state: :done_irreversible)
- end
-
- step 'I should see all todos marked as done' do
- merge_request_reference = merge_request.to_reference(full: true)
- issue_reference = issue.to_reference(full: true)
-
- find('.todos-done a').trigger('click')
-
- expect(page).to have_link project.name_with_namespace
- should_see_todo(1, "John Doe assigned you merge request #{merge_request_reference}", merge_request.title, state: :done_irreversible)
- should_see_todo(2, "John Doe mentioned you on issue #{issue_reference}", "#{current_user.to_reference} Wdyt?", state: :done_irreversible)
- should_see_todo(3, "John Doe assigned you issue #{issue_reference}", issue.title, state: :done_irreversible)
- should_see_todo(4, "Mary Jane mentioned you on issue #{issue_reference}", issue.title, state: :done_irreversible)
- end
-
- step 'I filter by "Enterprise"' do
- click_button 'Project'
- page.within '.dropdown-menu-project' do
- click_link enterprise.name_with_namespace
- end
- end
-
- step 'I filter by "John Doe"' do
- click_button 'Author'
- page.within '.dropdown-menu-author' do
- click_link john_doe.username
- end
- end
-
- step 'I filter by "Issue"' do
- click_button 'Type'
- page.within '.dropdown-menu-type' do
- click_link 'Issue'
- end
- end
-
- step 'I filter by "Mentioned"' do
- click_button 'Action'
- page.within '.dropdown-menu-action' do
- click_link 'Mentioned'
- end
- end
-
- step 'I should not see todos' do
- expect(page).to have_content "You're all done!"
- end
-
- step 'I should not see todos related to "Mary Jane" in the list' do
- should_not_see_todo "Mary Jane mentioned you on issue #{issue.to_reference(full: true)}"
- end
-
- step 'I should not see todos related to "Merge Requests" in the list' do
- should_not_see_todo "John Doe assigned you merge request #{merge_request.to_reference(full: true)}"
- end
-
- step 'I should not see todos related to "Assignments" in the list' do
- should_not_see_todo "John Doe assigned you merge request #{merge_request.to_reference(full: true)}"
- should_not_see_todo "John Doe assigned you issue #{issue.to_reference(full: true)}"
- end
-
- step 'I click on the todo' do
- find('.todo:nth-child(1)').click
- end
-
- step 'I should be directed to the corresponding page' do
- page.should have_css('.identifier', text: 'Merge request !1')
- # Merge request page loads and issues a number of Ajax requests
- wait_for_requests
- end
-
- def should_see_todo(position, title, body, state: :pending)
- page.within(".todo:nth-child(#{position})") do
- expect(page).to have_content title
- expect(page).to have_content body
-
- if state == :pending
- expect(page).to have_link 'Done'
- elsif state == :done_reversible
- expect(page).to have_link 'Undo'
- elsif state == :done_irreversible
- expect(page).not_to have_link 'Undo'
- expect(page).not_to have_link 'Done'
- else
- raise 'Invalid state given, valid states: :pending, :done_reversible, :done_irreversible'
- end
- end
- end
-
- def should_not_see_todo(title)
- expect(page).not_to have_visible_content title
- end
-
- def have_visible_content(text)
- have_css('*', text: text, visible: true)
- end
-
- def john_doe
- @john_doe ||= user_exists("John Doe", { username: "john_doe" })
- end
-
- def mary_jane
- @mary_jane ||= user_exists("Mary Jane", { username: "mary_jane" })
- end
-
- def enterprise
- @enterprise ||= Project.find_by(name: 'Enterprise')
- end
-
- def issue
- @issue ||= create(:issue, assignees: [current_user], project: project)
- end
-
- def merge_request
- @merge_request ||= create(:merge_request, assignee: current_user, source_project: project)
- end
-end
diff --git a/features/steps/groups.rb b/features/steps/groups.rb
index 25bb374b868..0aedc422563 100644
--- a/features/steps/groups.rb
+++ b/features/steps/groups.rb
@@ -5,7 +5,7 @@ class Spinach::Features::Groups < Spinach::FeatureSteps
include SharedUser
step 'I should see group "Owned"' do
- expect(page).to have_content '@owned'
+ expect(page).to have_content 'Owned'
end
step 'I am a signed out user' do
diff --git a/features/steps/project/source/browse_files.rb b/features/steps/project/source/browse_files.rb
index 80aa3a047a0..9ed4f8ea1f9 100644
--- a/features/steps/project/source/browse_files.rb
+++ b/features/steps/project/source/browse_files.rb
@@ -369,7 +369,6 @@ class Spinach::Features::ProjectSourceBrowseFiles < Spinach::FeatureSteps
expect(page).to have_content 'Permalink'
expect(page).not_to have_content 'Edit'
expect(page).not_to have_content 'Blame'
- expect(page).not_to have_content 'Annotate'
expect(page).to have_content 'Delete'
expect(page).to have_content 'Replace'
end
diff --git a/features/steps/shared/paths.rb b/features/steps/shared/paths.rb
index f0e751b820a..8a5b4112ffe 100644
--- a/features/steps/shared/paths.rb
+++ b/features/steps/shared/paths.rb
@@ -112,10 +112,6 @@ module SharedPaths
visit dashboard_groups_path
end
- step 'I visit dashboard todos page' do
- visit dashboard_todos_path
- end
-
step 'I should be redirected to the dashboard groups page' do
expect(current_path).to eq dashboard_groups_path
end
diff --git a/lib/api/commit_statuses.rb b/lib/api/commit_statuses.rb
index 10f2d5ef6a3..485b680cd5f 100644
--- a/lib/api/commit_statuses.rb
+++ b/lib/api/commit_statuses.rb
@@ -108,6 +108,9 @@ module API
render_api_error!('invalid state', 400)
end
+ MergeRequest.where(source_project: @project, source_branch: ref)
+ .update_all(head_pipeline_id: pipeline) if pipeline.latest?
+
present status, with: Entities::CommitStatus
rescue StateMachines::InvalidTransition => e
render_api_error!(e.message, 400)
diff --git a/lib/api/internal.rb b/lib/api/internal.rb
index 479ee16a611..f1c79970ba4 100644
--- a/lib/api/internal.rb
+++ b/lib/api/internal.rb
@@ -132,8 +132,11 @@ module API
return { success: false, message: 'Two-factor authentication is not enabled for this user' }
end
- codes = user.generate_otp_backup_codes!
- user.save!
+ codes = nil
+
+ ::Users::UpdateService.new(user).execute! do |user|
+ codes = user.generate_otp_backup_codes!
+ end
{ success: true, recovery_codes: codes }
end
diff --git a/lib/api/notification_settings.rb b/lib/api/notification_settings.rb
index 992ea5dc24d..5d113c94b22 100644
--- a/lib/api/notification_settings.rb
+++ b/lib/api/notification_settings.rb
@@ -34,7 +34,10 @@ module API
notification_setting.transaction do
new_notification_email = params.delete(:notification_email)
- current_user.update(notification_email: new_notification_email) if new_notification_email
+ if new_notification_email
+ ::Users::UpdateService.new(current_user, notification_email: new_notification_email).execute
+ end
+
notification_setting.update(declared_params(include_missing: false))
end
rescue ArgumentError => e # catch level enum error
diff --git a/lib/api/users.rb b/lib/api/users.rb
index c10e3364382..f9555842daf 100644
--- a/lib/api/users.rb
+++ b/lib/api/users.rb
@@ -98,7 +98,7 @@ module API
authenticated_as_admin!
params = declared_params(include_missing: false)
- user = ::Users::CreateService.new(current_user, params).execute
+ user = ::Users::CreateService.new(current_user, params).execute(skip_authorization: true)
if user.persisted?
present user, with: Entities::UserPublic
@@ -156,7 +156,9 @@ module API
user_params[:password_expires_at] = Time.now if user_params[:password].present?
- if user.update_attributes(user_params.except(:extern_uid, :provider))
+ result = ::Users::UpdateService.new(user, user_params.except(:extern_uid, :provider)).execute
+
+ if result[:status] == :success
present user, with: Entities::UserPublic
else
render_validation_error!(user)
@@ -234,9 +236,9 @@ module API
user = User.find_by(id: params.delete(:id))
not_found!('User') unless user
- email = user.emails.new(declared_params(include_missing: false))
+ email = Emails::CreateService.new(user, declared_params(include_missing: false)).execute
- if email.save
+ if email.errors.blank?
NotificationService.new.new_email(email)
present email, with: Entities::Email
else
@@ -274,8 +276,7 @@ module API
email = user.emails.find_by(id: params[:email_id])
not_found!('Email') unless email
- email.destroy
- user.update_secondary_emails!
+ Emails::DestroyService.new(user, email: email.email).execute
end
desc 'Delete a user. Available only for admins.' do
@@ -487,9 +488,9 @@ module API
requires :email, type: String, desc: 'The new email'
end
post "emails" do
- email = current_user.emails.new(declared_params)
+ email = Emails::CreateService.new(current_user, declared_params).execute
- if email.save
+ if email.errors.blank?
NotificationService.new.new_email(email)
present email, with: Entities::Email
else
@@ -505,8 +506,7 @@ module API
email = current_user.emails.find_by(id: params[:email_id])
not_found!('Email') unless email
- email.destroy
- current_user.update_secondary_emails!
+ Emails::DestroyService.new(current_user, email: email.email).execute
end
desc 'Get a list of user activities'
diff --git a/lib/api/variables.rb b/lib/api/variables.rb
index 381c4ef50b0..10374995497 100644
--- a/lib/api/variables.rb
+++ b/lib/api/variables.rb
@@ -45,7 +45,7 @@ module API
optional :protected, type: String, desc: 'Whether the variable is protected'
end
post ':id/variables' do
- variable = user_project.variables.create(declared(params, include_parent_namespaces: false).to_h)
+ variable = user_project.variables.create(declared_params(include_missing: false))
if variable.valid?
present variable, with: Entities::Variable
diff --git a/lib/ci/charts.rb b/lib/ci/charts.rb
index 6063d6f45e8..872e418c788 100644
--- a/lib/ci/charts.rb
+++ b/lib/ci/charts.rb
@@ -3,7 +3,7 @@ module Ci
module DailyInterval
def grouped_count(query)
query
- .group("DATE(#{Ci::Build.table_name}.created_at)")
+ .group("DATE(#{Ci::Pipeline.table_name}.created_at)")
.count(:created_at)
.transform_keys { |date| date.strftime(@format) }
end
@@ -17,12 +17,12 @@ module Ci
def grouped_count(query)
if Gitlab::Database.postgresql?
query
- .group("to_char(#{Ci::Build.table_name}.created_at, '01 Month YYYY')")
+ .group("to_char(#{Ci::Pipeline.table_name}.created_at, '01 Month YYYY')")
.count(:created_at)
.transform_keys(&:squish)
else
query
- .group("DATE_FORMAT(#{Ci::Build.table_name}.created_at, '01 %M %Y')")
+ .group("DATE_FORMAT(#{Ci::Pipeline.table_name}.created_at, '01 %M %Y')")
.count(:created_at)
end
end
@@ -33,21 +33,21 @@ module Ci
end
class Chart
- attr_reader :labels, :total, :success, :project, :build_times
+ attr_reader :labels, :total, :success, :project, :pipeline_times
def initialize(project)
@labels = []
@total = []
@success = []
- @build_times = []
+ @pipeline_times = []
@project = project
collect
end
def collect
- query = project.builds
- .where("? > #{Ci::Build.table_name}.created_at AND #{Ci::Build.table_name}.created_at > ?", @to, @from)
+ query = project.pipelines
+ .where("? > #{Ci::Pipeline.table_name}.created_at AND #{Ci::Pipeline.table_name}.created_at > ?", @to, @from)
totals_count = grouped_count(query)
success_count = grouped_count(query.success)
@@ -101,14 +101,14 @@ module Ci
end
end
- class BuildTime < Chart
+ class PipelineTime < Chart
def collect
commits = project.pipelines.last(30)
commits.each do |commit|
@labels << commit.short_sha
duration = commit.duration || 0
- @build_times << (duration / 60)
+ @pipeline_times << (duration / 60)
end
end
end
diff --git a/lib/gitlab/database.rb b/lib/gitlab/database.rb
index 0d5a7cf0694..d7dab584a44 100644
--- a/lib/gitlab/database.rb
+++ b/lib/gitlab/database.rb
@@ -93,7 +93,7 @@ module Gitlab
row.values_at(*keys).map { |value| connection.quote(value) }
end
- connection.execute <<-EOF.strip_heredoc
+ connection.execute <<-EOF
INSERT INTO #{table} (#{columns.join(', ')})
VALUES #{tuples.map { |tuple| "(#{tuple.join(', ')})" }.join(', ')}
EOF
diff --git a/lib/gitlab/dependency_linker/requirements_txt_linker.rb b/lib/gitlab/dependency_linker/requirements_txt_linker.rb
index 2e197e5cd94..9c9620bc36a 100644
--- a/lib/gitlab/dependency_linker/requirements_txt_linker.rb
+++ b/lib/gitlab/dependency_linker/requirements_txt_linker.rb
@@ -6,7 +6,7 @@ module Gitlab
private
def link_dependencies
- link_regex(/^(?<name>(?![a-z+]+:)[^#.-][^ ><=;\[]+)/) do |name|
+ link_regex(/^(?<name>(?![a-z+]+:)[^#.-][^ ><=~!;\[]+)/) do |name|
"https://pypi.python.org/pypi/#{name}"
end
diff --git a/lib/gitlab/ee_compat_check.rb b/lib/gitlab/ee_compat_check.rb
index 6d326ee213a..1a5887dab7e 100644
--- a/lib/gitlab/ee_compat_check.rb
+++ b/lib/gitlab/ee_compat_check.rb
@@ -76,9 +76,13 @@ module Gitlab
step(
"Generating the patch against origin/master in #{patch_path}",
- %W[git diff --binary origin/master > #{patch_path}]
+ %w[git diff --binary origin/master...HEAD]
) do |output, status|
- throw(:halt_check, :ko) unless status.zero? && File.exist?(patch_path)
+ throw(:halt_check, :ko) unless status.zero?
+
+ File.write(patch_path, output)
+
+ throw(:halt_check, :ko) unless File.exist?(patch_path)
end
end
@@ -130,7 +134,15 @@ module Gitlab
step("Fetching CE/#{ce_branch}", %W[git fetch #{CE_REPO} #{ce_branch}])
step(
"Checking if #{patch_path} applies cleanly to EE/master",
- %W[git apply --check --3way #{patch_path}]
+ # Don't use --check here because it can result in a 0-exit status even
+ # though the patch doesn't apply cleanly, e.g.:
+ # > git apply --check --3way foo.patch
+ # error: patch failed: lib/gitlab/ee_compat_check.rb:74
+ # Falling back to three-way merge...
+ # Applied patch to 'lib/gitlab/ee_compat_check.rb' with conflicts.
+ # > echo $?
+ # 0
+ %W[git apply --3way #{patch_path}]
) do |output, status|
puts output
unless status.zero?
@@ -145,6 +157,7 @@ module Gitlab
status = 0 if failed_files.empty?
end
+ command(%w[git reset --hard])
status
end
end
@@ -292,7 +305,7 @@ module Gitlab
# In the CE repo
$ git fetch origin master
- $ git diff --binary origin/master > #{ce_branch}.patch
+ $ git diff --binary origin/master...HEAD -- > #{ce_branch}.patch
# In the EE repo
$ git fetch origin master
diff --git a/lib/gitlab/exclusive_lease.rb b/lib/gitlab/exclusive_lease.rb
index 62ddd45785d..a0f46594eb1 100644
--- a/lib/gitlab/exclusive_lease.rb
+++ b/lib/gitlab/exclusive_lease.rb
@@ -10,13 +10,21 @@ module Gitlab
# ExclusiveLease.
#
class ExclusiveLease
- LUA_CANCEL_SCRIPT = <<-EOS.freeze
+ LUA_CANCEL_SCRIPT = <<~EOS.freeze
local key, uuid = KEYS[1], ARGV[1]
if redis.call("get", key) == uuid then
redis.call("del", key)
end
EOS
+ LUA_RENEW_SCRIPT = <<~EOS.freeze
+ local key, uuid, ttl = KEYS[1], ARGV[1], ARGV[2]
+ if redis.call("get", key) == uuid then
+ redis.call("expire", key, ttl)
+ return uuid
+ end
+ EOS
+
def self.cancel(key, uuid)
Gitlab::Redis.with do |redis|
redis.eval(LUA_CANCEL_SCRIPT, keys: [redis_key(key)], argv: [uuid])
@@ -42,6 +50,15 @@ module Gitlab
end
end
+ # Try to renew an existing lease. Return lease UUID on success,
+ # false if the lease is taken by a different UUID or inexistent.
+ def renew
+ Gitlab::Redis.with do |redis|
+ result = redis.eval(LUA_RENEW_SCRIPT, keys: [@redis_key], argv: [@uuid, @timeout])
+ result == @uuid
+ end
+ end
+
# Returns true if the key for this lease is set.
def exists?
Gitlab::Redis.with do |redis|
diff --git a/lib/gitlab/git/commit.rb b/lib/gitlab/git/commit.rb
index d5d149f1423..9c0606d780a 100644
--- a/lib/gitlab/git/commit.rb
+++ b/lib/gitlab/git/commit.rb
@@ -104,9 +104,63 @@ module Gitlab
[]
end
- # Delegate Repository#find_commits
+ # Returns commits collection
+ #
+ # Ex.
+ # Commit.find_all(
+ # repo,
+ # ref: 'master',
+ # max_count: 10,
+ # skip: 5,
+ # order: :date
+ # )
+ #
+ # +options+ is a Hash of optional arguments to git
+ # :ref is the ref from which to begin (SHA1 or name)
+ # :max_count is the maximum number of commits to fetch
+ # :skip is the number of commits to skip
+ # :order is the commits order and allowed value is :none (default), :date,
+ # :topo, or any combination of them (in an array). Commit ordering types
+ # are documented here:
+ # http://www.rubydoc.info/github/libgit2/rugged/Rugged#SORT_NONE-constant)
+ #
def find_all(repo, options = {})
- repo.find_commits(options)
+ actual_options = options.dup
+
+ allowed_options = [:ref, :max_count, :skip, :order]
+
+ actual_options.keep_if do |key|
+ allowed_options.include?(key)
+ end
+
+ default_options = { skip: 0 }
+ actual_options = default_options.merge(actual_options)
+
+ rugged = repo.rugged
+ walker = Rugged::Walker.new(rugged)
+
+ if actual_options[:ref]
+ walker.push(rugged.rev_parse_oid(actual_options[:ref]))
+ else
+ rugged.references.each("refs/heads/*") do |ref|
+ walker.push(ref.target_id)
+ end
+ end
+
+ walker.sorting(rugged_sort_type(actual_options[:order]))
+
+ commits = []
+ offset = actual_options[:skip]
+ limit = actual_options[:max_count]
+ walker.each(offset: offset, limit: limit) do |commit|
+ commits.push(decorate(commit))
+ end
+
+ walker.reset
+
+ commits
+ rescue Rugged::OdbError
+ []
end
def decorate(commit, ref = nil)
@@ -131,6 +185,20 @@ module Gitlab
diff.find_similar!(break_rewrites: break_rewrites)
diff
end
+
+ # Returns the `Rugged` sorting type constant for one or more given
+ # sort types. Valid keys are `:none`, `:topo`, and `:date`, or an array
+ # containing more than one of them. `:date` uses a combination of date and
+ # topological sorting to closer mimic git's native ordering.
+ def rugged_sort_type(sort_type)
+ @rugged_sort_types ||= {
+ none: Rugged::SORT_NONE,
+ topo: Rugged::SORT_TOPO,
+ date: Rugged::SORT_DATE | Rugged::SORT_TOPO
+ }
+
+ @rugged_sort_types.fetch(sort_type, Rugged::SORT_NONE)
+ end
end
def initialize(raw_commit, head = nil)
@@ -175,8 +243,8 @@ module Gitlab
# Shows the diff between the commit's parent and the commit.
#
# Cuts out the header and stats from #to_patch and returns only the diff.
- def to_diff(options = {})
- diff_from_parent(options).patch
+ def to_diff
+ diff_from_parent.patch
end
# Returns a diff object for the changes from this commit's first parent.
diff --git a/lib/gitlab/git/repository.rb b/lib/gitlab/git/repository.rb
index c1f942f931a..0a0c6f76cd3 100644
--- a/lib/gitlab/git/repository.rb
+++ b/lib/gitlab/git/repository.rb
@@ -494,70 +494,6 @@ module Gitlab
end
end
- # Returns commits collection
- #
- # Ex.
- # repo.find_commits(
- # ref: 'master',
- # max_count: 10,
- # skip: 5,
- # order: :date
- # )
- #
- # +options+ is a Hash of optional arguments to git
- # :ref is the ref from which to begin (SHA1 or name)
- # :contains is the commit contained by the refs from which to begin (SHA1 or name)
- # :max_count is the maximum number of commits to fetch
- # :skip is the number of commits to skip
- # :order is the commits order and allowed value is :none (default), :date,
- # :topo, or any combination of them (in an array). Commit ordering types
- # are documented here:
- # http://www.rubydoc.info/github/libgit2/rugged/Rugged#SORT_NONE-constant)
- #
- def find_commits(options = {})
- actual_options = options.dup
-
- allowed_options = [:ref, :max_count, :skip, :contains, :order]
-
- actual_options.keep_if do |key|
- allowed_options.include?(key)
- end
-
- default_options = { skip: 0 }
- actual_options = default_options.merge(actual_options)
-
- walker = Rugged::Walker.new(rugged)
-
- if actual_options[:ref]
- walker.push(rugged.rev_parse_oid(actual_options[:ref]))
- elsif actual_options[:contains]
- branches_contains(actual_options[:contains]).each do |branch|
- walker.push(branch.target_id)
- end
- else
- rugged.references.each("refs/heads/*") do |ref|
- walker.push(ref.target_id)
- end
- end
-
- sort_type = rugged_sort_type(actual_options[:order])
- walker.sorting(sort_type)
-
- commits = []
- offset = actual_options[:skip]
- limit = actual_options[:max_count]
- walker.each(offset: offset, limit: limit) do |commit|
- gitlab_commit = Gitlab::Git::Commit.decorate(commit)
- commits.push(gitlab_commit)
- end
-
- walker.reset
-
- commits
- rescue Rugged::OdbError
- []
- end
-
# Returns branch names collection that contains the special commit(SHA1
# or name)
#
@@ -1228,20 +1164,6 @@ module Gitlab
rescue GRPC::BadStatus => e
raise CommandError.new(e)
end
-
- # Returns the `Rugged` sorting type constant for one or more given
- # sort types. Valid keys are `:none`, `:topo`, and `:date`, or an array
- # containing more than one of them. `:date` uses a combination of date and
- # topological sorting to closer mimic git's native ordering.
- def rugged_sort_type(sort_type)
- @rugged_sort_types ||= {
- none: Rugged::SORT_NONE,
- topo: Rugged::SORT_TOPO,
- date: Rugged::SORT_DATE | Rugged::SORT_TOPO
- }
-
- @rugged_sort_types.fetch(sort_type, Rugged::SORT_NONE)
- end
end
end
end
diff --git a/lib/gitlab/i18n.rb b/lib/gitlab/i18n.rb
index a5ad2f952d3..db7cdf4b5c7 100644
--- a/lib/gitlab/i18n.rb
+++ b/lib/gitlab/i18n.rb
@@ -11,7 +11,8 @@ module Gitlab
'zh_CN' => '简体中文',
'zh_HK' => '繁體中文(香港)',
'zh_TW' => '繁體中文(臺灣)',
- 'bg' => 'български'
+ 'bg' => 'български',
+ 'eo' => 'Esperanto'
}.freeze
def available_locales
diff --git a/lib/gitlab/import_export/import_export.yml b/lib/gitlab/import_export/import_export.yml
index 72183e8aad4..1860352c96d 100644
--- a/lib/gitlab/import_export/import_export.yml
+++ b/lib/gitlab/import_export/import_export.yml
@@ -99,6 +99,7 @@ excluded_attributes:
- :milestone_id
merge_requests:
- :milestone_id
+ - :ref_fetched
award_emoji:
- :awardable_id
statuses:
diff --git a/lib/gitlab/ldap/access.rb b/lib/gitlab/ldap/access.rb
index 54a5b1d31cd..8779577258b 100644
--- a/lib/gitlab/ldap/access.rb
+++ b/lib/gitlab/ldap/access.rb
@@ -16,8 +16,8 @@ module Gitlab
def self.allowed?(user)
self.open(user) do |access|
if access.allowed?
- user.last_credential_check_at = Time.now
- user.save
+ Users::UpdateService.new(user, last_credential_check_a: Time.now).execute
+
true
else
false
diff --git a/lib/gitlab/o_auth/user.rb b/lib/gitlab/o_auth/user.rb
index 7307f8c2c87..b3f453e506d 100644
--- a/lib/gitlab/o_auth/user.rb
+++ b/lib/gitlab/o_auth/user.rb
@@ -32,7 +32,7 @@ module Gitlab
block_after_save = needs_blocking?
- gl_user.save!
+ Users::UpdateService.new(gl_user).execute!
gl_user.block if block_after_save
diff --git a/lib/gitlab/usage_data.rb b/lib/gitlab/usage_data.rb
index bcba2e3e1b6..38dc82493cf 100644
--- a/lib/gitlab/usage_data.rb
+++ b/lib/gitlab/usage_data.rb
@@ -27,6 +27,7 @@ module Gitlab
deploy_keys: DeployKey.count,
deployments: Deployment.count,
environments: Environment.count,
+ in_review_folder: Environment.in_review_folder.count,
groups: Group.count,
issues: Issue.count,
keys: Key.count,
diff --git a/lib/gitlab/visibility_level.rb b/lib/gitlab/visibility_level.rb
index 36e5b5041a6..48f3d950779 100644
--- a/lib/gitlab/visibility_level.rb
+++ b/lib/gitlab/visibility_level.rb
@@ -28,7 +28,7 @@ module Gitlab
def levels_for_user(user = nil)
return [PUBLIC] unless user
- if user.admin?
+ if user.full_private_access?
[PRIVATE, INTERNAL, PUBLIC]
elsif user.external?
[PUBLIC]
diff --git a/lib/system_check/simple_executor.rb b/lib/system_check/simple_executor.rb
index dc2d4643a01..e5986612908 100644
--- a/lib/system_check/simple_executor.rb
+++ b/lib/system_check/simple_executor.rb
@@ -75,6 +75,8 @@ module SystemCheck
check.show_error
end
+ rescue StandardError => e
+ $stdout.puts "Exception: #{e.message}".color(:red)
end
private
diff --git a/locale/bg/gitlab.po b/locale/bg/gitlab.po
index 43a5de65c43..370aca1f1d9 100644
--- a/locale/bg/gitlab.po
+++ b/locale/bg/gitlab.po
@@ -3,25 +3,245 @@ msgid ""
msgstr ""
"Project-Id-Version: gitlab 1.0.0\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2017-05-04 19:24-0500\n"
+"POT-Creation-Date: 2017-06-12 19:29-0500\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"PO-Revision-Date: 2017-06-05 09:40-0400\n"
+"PO-Revision-Date: 2017-06-13 04:23-0400\n"
"Last-Translator: Lyubomir Vasilev <lyubomirv@abv.bg>\n"
-"Language-Team: Bulgarian\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 "%{commit_author_link} committed %{commit_timeago}"
+msgstr "%{commit_author_link} подаде %{commit_timeago}"
+
+msgid "About auto deploy"
+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 ""
+"Добавете SSH ключ в профила си, за да можете да изтегляте или изпращате "
+"промени чрез SSH."
+
+msgid "Add new directory"
+msgstr "Добавяне на нова папка"
+
+msgid "Archived project! Repository is read-only"
+msgstr "Архивиран проект! Хранилището е само за четене"
+
+msgid "Are you sure you want to delete this pipeline schedule?"
+msgstr "Наистина ли искате да изтриете този план за схема?"
+
+msgid "Attach a file by drag &amp; drop or %{upload_link}"
+msgstr "Прикачете файл чрез влачене и пускане или %{upload_link}"
+
+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 ""
+"Клонът <strong>%{branch_name}</strong> беше създаден. За да настроите "
+"автоматичното внедряване, изберете Yaml шаблон за GitLab CI и подайте "
+"промените си. %{link_to_autodeploy_doc}"
+
+msgid "Branches"
+msgstr "Клонове"
+
+msgid "Browse files"
+msgstr "Разглеждане на файловете"
+
msgid "ByAuthor|by"
msgstr "от"
+msgid "CI configuration"
+msgstr "Конфигурация на непрекъсната интеграция"
+
+msgid "Cancel"
+msgstr "Отказ"
+
+msgid "ChangeTypeActionLabel|Pick into branch"
+msgstr "Избиране в клона"
+
+msgid "ChangeTypeActionLabel|Revert in branch"
+msgstr "Отмяна в клона"
+
+msgid "ChangeTypeAction|Cherry-pick"
+msgstr "Подбиране"
+
+msgid "ChangeType|commit"
+msgstr "подаване"
+
+msgid "ChangeType|merge request"
+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 "Commit"
msgid_plural "Commits"
msgstr[0] "Подаване"
msgstr[1] "Подавания"
+msgid "Commit message"
+msgstr "Съобщение за подаването"
+
+msgid "CommitMessage|Add %{file_name}"
+msgstr "Добавяне на „%{file_name}“"
+
+msgid "Commits"
+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 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 "Cron Timezone"
+msgstr "Часова зона за „Cron“"
+
+msgid "Cron syntax"
+msgstr "Синтаксис на „Cron“"
+
+msgid "Custom"
+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 "Cycle Analytics"
+msgstr "Анализ на циклите"
+
msgid ""
"Cycle Analytics gives an overview of how much time it takes to go from idea "
"to production in your project."
@@ -50,17 +270,97 @@ msgstr "Подготовка за издаване"
msgid "CycleAnalyticsStage|Test"
msgstr "Тестване"
+msgid "Define a custom pattern with cron syntax"
+msgstr "Задайте потребителски шаблон, използвайки синтаксиса на „Cron“"
+
+msgid "Delete"
+msgstr "Изтриване"
+
msgid "Deploy"
msgid_plural "Deploys"
msgstr[0] "Внедряване"
msgstr[1] "Внедрявания"
+msgid "Description"
+msgstr "Описание"
+
+msgid "Directory name"
+msgstr "Име на папката"
+
+msgid "Don't show again"
+msgstr "Да не се показва повече"
+
+msgid "Download"
+msgstr "Сваляне"
+
+msgid "Download tar"
+msgstr "Сваляне във формат „tar“"
+
+msgid "Download tar.bz2"
+msgstr "Сваляне във формат „tar.bz2“"
+
+msgid "Download tar.gz"
+msgstr "Сваляне във формат „tar.gz“"
+
+msgid "Download zip"
+msgstr "Сваляне във формат „zip“"
+
+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 "Редактиране на плана %{id} за схема"
+
+msgid "Every day (at 4:00am)"
+msgstr "Всеки ден (в 4 ч. сутринта)"
+
+msgid "Every month (on the 1st at 4:00am)"
+msgstr "Всеки месец (на 1-во число, в 4 ч. сутринта)"
+
+msgid "Every week (Sundays at 4:00am)"
+msgstr "Всяка седмица (в неделя, в 4 ч. сутринта)"
+
+msgid "Failed to change the owner"
+msgstr "Собственикът не може да бъде променен"
+
+msgid "Failed to remove the pipeline schedule"
+msgstr "Планът за схема не може да бъде премахнат"
+
+msgid "Files"
+msgstr "Файлове"
+
+msgid "Find by path"
+msgstr "Търсене по път"
+
+msgid "Find file"
+msgstr "Търсене на файл"
+
msgid "FirstPushedBy|First"
msgstr "Първо"
msgid "FirstPushedBy|pushed by"
msgstr "изпращане на промени от"
+msgid "Fork"
+msgid_plural "Forks"
+msgstr[0] "Разклонение"
+msgstr[1] "Разклонения"
+
+msgid "ForkedFromProjectPath|Forked from"
+msgstr "Разклонение на"
+
msgid "From issue creation until deploy to production"
msgstr "От създаването на проблема до внедряването в крайната версия"
@@ -68,50 +368,290 @@ msgid "From merge request merge until deploy to production"
msgstr ""
"От прилагането на заявката за сливане до внедряването в крайната версия"
+msgid "Go to your fork"
+msgstr "Към Вашето разклонение"
+
+msgid "GoToYourFork|Fork"
+msgstr "Разклонение"
+
+msgid "Home"
+msgstr "Начало"
+
+msgid "Housekeeping successfully started"
+msgstr "Освежаването започна успешно"
+
+msgid "Import repository"
+msgstr "Внасяне на хранилище"
+
+msgid "Interval Pattern"
+msgstr "Шаблон за интервала"
+
msgid "Introducing Cycle Analytics"
-msgstr "Представяме Ви анализът на циклите"
+msgstr "Представяме Ви анализа на циклите"
+
+msgid "LFSStatus|Disabled"
+msgstr "Изключено"
+
+msgid "LFSStatus|Enabled"
+msgstr "Включено"
msgid "Last %d day"
msgid_plural "Last %d days"
msgstr[0] "Последния %d ден"
msgstr[1] "Последните %d дни"
+msgid "Last Pipeline"
+msgstr "Последна схема"
+
+msgid "Last Update"
+msgstr "Последна промяна"
+
+msgid "Last commit"
+msgstr "Последно подаване"
+
+msgid "Learn more in the"
+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] "Ограничено до показване на последното %d събитие"
-msgstr[1] "Ограничено до показване на последните %d събития"
+msgstr[0] "Ограничено до показване на най-много %d събитие"
+msgstr[1] "Ограничено до показване на най-много %d събития"
msgid "Median"
msgstr "Медиана"
+msgid "MissingSSHKeyWarningLink|add an SSH key"
+msgstr "добавите SSH ключ"
+
msgid "New Issue"
msgid_plural "New Issues"
msgstr[0] "Нов проблем"
msgstr[1] "Нови проблема"
+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 "Няма планове"
+
msgid "Not available"
msgstr "Не е налично"
msgid "Not enough data"
msgstr "Няма достатъчно данни"
+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 "Отворен"
+msgid "Options"
+msgstr "Опции"
+
+msgid "Owner"
+msgstr "Собственик"
+
+msgid "Pipeline"
+msgstr "Схема"
+
msgid "Pipeline Health"
msgstr "Състояние"
+msgid "Pipeline Schedule"
+msgstr "План за схема"
+
+msgid "Pipeline Schedules"
+msgstr "Планове за схема"
+
+msgid "PipelineSchedules|Activated"
+msgstr "Включено"
+
+msgid "PipelineSchedules|Active"
+msgstr "Активно"
+
+msgid "PipelineSchedules|All"
+msgstr "Всички"
+
+msgid "PipelineSchedules|Inactive"
+msgstr "Неактивно"
+
+msgid "PipelineSchedules|Next Run"
+msgstr "Следващо изпълнение"
+
+msgid "PipelineSchedules|None"
+msgstr "Нищо"
+
+msgid "PipelineSchedules|Provide a short description for this pipeline"
+msgstr "Въведете кратко описание за тази схема"
+
+msgid "PipelineSchedules|Take ownership"
+msgstr "Поемане на собствеността"
+
+msgid "PipelineSchedules|Target"
+msgstr "Цел"
+
+msgid "Project '%{project_name}' queued for deletion."
+msgstr "Проектът „%{project_name}“ е добавен в опашката за изтриване."
+
+msgid "Project '%{project_name}' was successfully created."
+msgstr "Проектът „%{project_name}“ беше създаден успешно."
+
+msgid "Project '%{project_name}' was successfully updated."
+msgstr "Проектът „%{project_name}“ беше обновен успешно."
+
+msgid "Project '%{project_name}' will be deleted."
+msgstr "Проектът „%{project_name}“ ще бъде изтрит."
+
+msgid "Project access must be granted explicitly to each user."
+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 "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 "Етап"
+msgid "ProjectNetworkGraph|Graph"
+msgstr "Графика"
+
msgid "Read more"
msgstr "Прочетете повече"
+msgid "Readme"
+msgstr "ПрочетиМе"
+
+msgid "RefSwitcher|Branches"
+msgstr "Клонове"
+
+msgid "RefSwitcher|Tags"
+msgstr "Етикети"
+
msgid "Related Commits"
msgstr "Свързани подавания"
msgid "Related Deployed Jobs"
-msgstr "Свързани задачи за внедряване"
+msgstr "Свързани внедрени задачи"
msgid "Related Issues"
msgstr "Свързани проблеми"
@@ -125,11 +665,87 @@ msgstr "Свързани заявки за сливане"
msgid "Related Merged Requests"
msgstr "Свързани приложени заявки за сливане"
+msgid "Remind later"
+msgstr "Напомняне по-късно"
+
+msgid "Remove project"
+msgstr "Премахване на проекта"
+
+msgid "Request Access"
+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 target branch"
+msgstr "Изберете целеви клон"
+
+msgid "Set a password on your account to pull or push via %{protocol}"
+msgstr ""
+"Задайте парола на профила си, за да можете да изтегляте и изпращате промени "
+"чрез %{protocol}"
+
+msgid "Set up CI"
+msgstr "Настройка на НИ"
+
+msgid "Set up Koding"
+msgstr "Настройка на „Koding“"
+
+msgid "Set up auto deploy"
+msgstr "Настройка на авт. внедряване"
+
+msgid "SetPasswordToCloneLink|set a password"
+msgstr "зададете парола"
+
msgid "Showing %d event"
msgid_plural "Showing %d events"
msgstr[0] "Показване на %d събитие"
msgstr[1] "Показване на %d събития"
+msgid "Source code"
+msgstr "Изходен код"
+
+msgid "StarProject|Star"
+msgstr "Звезда"
+
+msgid "Start a <strong>new merge request</strong> with these changes"
+msgstr "Създайте <strong>нова заявка за сливане</strong> с тези промени"
+
+msgid "Switch branch/tag"
+msgstr "Преминаване към клон/етикет"
+
+msgid "Tag"
+msgid_plural "Tags"
+msgstr[0] "Етикет"
+msgstr[1] "Етикети"
+
+msgid "Tags"
+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 "
@@ -142,6 +758,9 @@ msgstr ""
msgid "The collection of events added to the data gathered for that stage."
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. "
@@ -156,6 +775,15 @@ 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 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."
@@ -170,7 +798,18 @@ msgid ""
"once you have completed the full idea to production cycle."
msgstr ""
"Етапът на издаване показва общото време, което е нужно от създаването на "
-"проблем до внедряването на кода в крайната версия."
+"проблем до внедряването на кода в крайната версия. Данните ще бъдат добавени "
+"автоматично след като завършите един пълен цикъл и превърнете първата си "
+"идея в реалност."
+
+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 "
@@ -197,8 +836,8 @@ msgid ""
"first pipeline finishes running."
msgstr ""
"Етапът на тестване показва времето, което е нужно на „Gitlab CI“ да изпълни "
-"всички задачи за свързаната заявка за сливане. Данните ще бъдат добавени "
-"автоматично след като приключи изпълнените на първата Ви такава задача."
+"всяка схема от задачи за свързаната заявка за сливане. Данните ще бъдат "
+"добавени автоматично след като приключи изпълнението на първата Ви схема."
msgid "The time taken by each data entry gathered by that stage."
msgstr "Времето, което отнема всеки запис от данни за съответния етап."
@@ -212,6 +851,13 @@ 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."
+msgstr ""
+"Това означава, че няма да можете да изпращате код, докато не създадете "
+"празно хранилище или не внесете съществуващо такова."
+
msgid "Time before an issue gets scheduled"
msgstr "Време преди един проблем да бъде планиран за работа"
@@ -225,6 +871,129 @@ msgstr ""
msgid "Time until first merge request"
msgstr "Време преди първата заявка за сливане"
+msgid "Timeago|%s days ago"
+msgstr "преди %s дни"
+
+msgid "Timeago|%s days remaining"
+msgstr "остават %s дни"
+
+msgid "Timeago|%s hours remaining"
+msgstr "остават %s часа"
+
+msgid "Timeago|%s minutes ago"
+msgstr "преди %s минути"
+
+msgid "Timeago|%s minutes remaining"
+msgstr "остават %s минути"
+
+msgid "Timeago|%s months ago"
+msgstr "преди %s месеца"
+
+msgid "Timeago|%s months remaining"
+msgstr "остават %s месеца"
+
+msgid "Timeago|%s seconds remaining"
+msgstr "остават %s секунди"
+
+msgid "Timeago|%s weeks ago"
+msgstr "преди %s седмици"
+
+msgid "Timeago|%s weeks remaining"
+msgstr "остават %s седмици"
+
+msgid "Timeago|%s years ago"
+msgstr "преди %s години"
+
+msgid "Timeago|%s years remaining"
+msgstr "остават %s години"
+
+msgid "Timeago|1 day remaining"
+msgstr "остава 1 ден"
+
+msgid "Timeago|1 hour remaining"
+msgstr "остава 1 час"
+
+msgid "Timeago|1 minute remaining"
+msgstr "остава 1 минута"
+
+msgid "Timeago|1 month remaining"
+msgstr "остава 1 месец"
+
+msgid "Timeago|1 week remaining"
+msgstr "остава 1 седмица"
+
+msgid "Timeago|1 year remaining"
+msgstr "остава 1 година"
+
+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 "преди около %s часа"
+
+msgid "Timeago|about a minute ago"
+msgstr "преди около една минута"
+
+msgid "Timeago|about an hour ago"
+msgstr "преди около един час"
+
+msgid "Timeago|in %s days"
+msgstr "след %s дни"
+
+msgid "Timeago|in %s hours"
+msgstr "след %s часа"
+
+msgid "Timeago|in %s minutes"
+msgstr "след %s минути"
+
+msgid "Timeago|in %s months"
+msgstr "след %s месеца"
+
+msgid "Timeago|in %s seconds"
+msgstr "след %s секунди"
+
+msgid "Timeago|in %s weeks"
+msgstr "след %s седмици"
+
+msgid "Timeago|in %s years"
+msgstr "след %s години"
+
+msgid "Timeago|in 1 day"
+msgstr "след 1 ден"
+
+msgid "Timeago|in 1 hour"
+msgstr "след 1 час"
+
+msgid "Timeago|in 1 minute"
+msgstr "след 1 минута"
+
+msgid "Timeago|in 1 month"
+msgstr "след 1 месец"
+
+msgid "Timeago|in 1 week"
+msgstr "след 1 седмица"
+
+msgid "Timeago|in 1 year"
+msgstr "след 1 година"
+
+msgid "Timeago|less than a minute ago"
+msgstr "преди по-малко от минута"
+
msgid "Time|hr"
msgid_plural "Time|hrs"
msgstr[0] "час"
@@ -244,20 +1013,121 @@ msgstr "Общо време"
msgid "Total test time for all commits/merges"
msgstr "Общо време за тестване на всички подавания/сливания"
+msgid "Unstar"
+msgstr "Без звезда"
+
+msgid "Upload New File"
+msgstr "Качване на нов файл"
+
+msgid "Upload file"
+msgstr "Качване на файл"
+
+msgid "Use your global notification setting"
+msgstr "Използване на глобалната Ви настройка за известията"
+
+msgid "VisibilityLevel|Internal"
+msgstr "Вътрешен"
+
+msgid "VisibilityLevel|Private"
+msgstr "Частен"
+
+msgid "VisibilityLevel|Public"
+msgstr "Публичен"
+
msgid "Want to see the data? Please ask an administrator for access."
msgstr "Искате ли да видите данните? Помолете администратор за достъп."
msgid "We don't have enough data to show this stage."
msgstr "Няма достатъчно данни за този етап."
-msgid "You have reached your project limit"
+msgid "Withdraw Access Request"
+msgstr "Оттегляне на заявката за достъп"
+
+msgid ""
+"You are going to remove %{project_name_with_namespace}.\n"
+"Removed project CANNOT be restored!\n"
+"Are you ABSOLUTELY sure?"
msgstr ""
+"На път сте да премахнете „%{project_name_with_namespace}“.\n"
+"Ако го премахнете, той НЕ може да бъде възстановен!\n"
+"НАИСТИНА ли искате това?"
+
+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 can only add files when you are on a branch"
+msgstr "Можете да добавяте файлове само когато се намирате в клон"
+
+msgid "You must sign in to star a project"
+msgstr "Трябва да се впишете, за да отбележите проект със звезда"
msgid "You need permission."
msgstr "Нуждаете се от разрешение."
+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 ""
+"Няма да можете да изтегляте или изпращате код в проекта чрез %{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 "Your name"
+msgstr "Вашето име"
+
msgid "day"
msgid_plural "days"
msgstr[0] "ден"
msgstr[1] "дни"
+msgid "notification emails"
+msgstr "известия по е-поща"
+
+msgid "parent"
+msgid_plural "parents"
+msgstr[0] "родител"
+msgstr[1] "родители"
+
+msgid "pipeline schedules documentation"
+msgstr "документацията за планирането на схеми"
+
+msgid "with stage"
+msgid_plural "with stages"
+msgstr[0] "с етап"
+msgstr[1] "с етапи"
+
diff --git a/locale/eo/gitlab.po b/locale/eo/gitlab.po
new file mode 100644
index 00000000000..3ef9e19067d
--- /dev/null
+++ b/locale/eo/gitlab.po
@@ -0,0 +1,1143 @@
+# Huang Tao <htve@outlook.com>, 2017. #zanata
+# Lyubomir Vasilev <lyubomirv@abv.bg>, 2017. #zanata
+msgid ""
+msgstr ""
+"Project-Id-Version: gitlab 1.0.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2017-06-15 21:59-0500\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"PO-Revision-Date: 2017-06-20 06:24-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 "%{commit_author_link} committed %{commit_timeago}"
+msgstr "%{commit_author_link} enmetis %{commit_timeago}"
+
+msgid "About auto deploy"
+msgstr "Pri la aŭtomata disponigado"
+
+msgid "Active"
+msgstr "Aktiva"
+
+msgid "Activity"
+msgstr "Aktiveco"
+
+msgid "Add Changelog"
+msgstr "Aldoni liston de ŝanĝoj"
+
+msgid "Add Contribution guide"
+msgstr "Aldoni gvidliniojn por kontribuado"
+
+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."
+
+msgid "Add new directory"
+msgstr "Aldoni novan dosierujon"
+
+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 "Attach a file by drag &amp; drop or %{upload_link}"
+msgstr "Alkroĉu dosieron per ŝovmetado aŭ %{upload_link}"
+
+msgid "Branch"
+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 "Branches"
+msgstr "Branĉoj"
+
+msgid "Browse files"
+msgstr "Elekti dosierojn"
+
+msgid "ByAuthor|by"
+msgstr "de"
+
+msgid "CI configuration"
+msgstr "Agordoj de seninterrompa integrado"
+
+msgid "Cancel"
+msgstr "Nuligi"
+
+msgid "ChangeTypeActionLabel|Pick into branch"
+msgstr "Elekti en branĉon"
+
+msgid "ChangeTypeActionLabel|Revert in branch"
+msgstr "Malfari en branĉo"
+
+msgid "ChangeTypeAction|Cherry-pick"
+msgstr "Precize elekti"
+
+msgid "ChangeTypeAction|Revert"
+msgstr "Malfari"
+
+msgid "Changelog"
+msgstr "Listo de ŝanĝoj"
+
+msgid "Charts"
+msgstr "Diagramoj"
+
+msgid "Cherry-pick this commit"
+msgstr "Precize elekti ĉi tiun kunmetadon"
+
+msgid "Cherry-pick this merge request"
+msgstr "Precize elekti ĉi tiun peton pri kunfando"
+
+msgid "CiStatusLabel|canceled"
+msgstr "nuligita"
+
+msgid "CiStatusLabel|created"
+msgstr "kreita"
+
+msgid "CiStatusLabel|failed"
+msgstr "malsukcesa"
+
+msgid "CiStatusLabel|manual action"
+msgstr "mana ago"
+
+msgid "CiStatusLabel|passed"
+msgstr "sukcesa"
+
+msgid "CiStatusLabel|passed with warnings"
+msgstr "sukcesa, kun avertoj"
+
+msgid "CiStatusLabel|pending"
+msgstr "okazonta"
+
+msgid "CiStatusLabel|skipped"
+msgstr "transsaltita"
+
+msgid "CiStatusLabel|waiting for manual action"
+msgstr "atendanta manan agon"
+
+msgid "CiStatusText|blocked"
+msgstr "blokita"
+
+msgid "CiStatusText|canceled"
+msgstr "nuligita"
+
+msgid "CiStatusText|created"
+msgstr "kreita"
+
+msgid "CiStatusText|failed"
+msgstr "malsukcesa"
+
+msgid "CiStatusText|manual"
+msgstr "mana"
+
+msgid "CiStatusText|passed"
+msgstr "sukcesa"
+
+msgid "CiStatusText|pending"
+msgstr "okazonta"
+
+msgid "CiStatusText|skipped"
+msgstr "transsaltita"
+
+msgid "CiStatus|running"
+msgstr "plenumiĝanta"
+
+msgid "Commit"
+msgid_plural "Commits"
+msgstr[0] "Enmetado"
+msgstr[1] "Enmetadoj"
+
+msgid "Commit message"
+msgstr "Mesaĝo pri la enmetado"
+
+msgid "CommitBoxTitle|Commit"
+msgstr "Enmeti"
+
+msgid "CommitMessage|Add %{file_name}"
+msgstr "Aldoni „%{file_name}“"
+
+msgid "Commits"
+msgstr "Enmetadoj"
+
+msgid "Commits|History"
+msgstr "Historio"
+
+msgid "Committed by"
+msgstr "Enmetita de"
+
+msgid "Compare"
+msgstr "Kompari"
+
+msgid "Contribution guide"
+msgstr "Gvidlinioj por kontribuado"
+
+msgid "Contributors"
+msgstr "Kontribuantoj"
+
+msgid "Copy URL to clipboard"
+msgstr "Kopii la adreson en la kopibufron"
+
+msgid "Copy commit SHA to clipboard"
+msgstr "Kopii la identigilon de la enmetado"
+
+msgid "Create New Directory"
+msgstr "Krei novan dosierujon"
+
+msgid "Create directory"
+msgstr "Krei dosierujon"
+
+msgid "Create empty bare repository"
+msgstr "Krei malplenan deponejon"
+
+msgid "Create merge request"
+msgstr "Krei peton pri kunfando"
+
+msgid "Create new..."
+msgstr "Krei novan…"
+
+msgid "CreateNewFork|Fork"
+msgstr "Disbranĉigi"
+
+msgid "CreateTag|Tag"
+msgstr "Etikedo"
+
+msgid "Cron Timezone"
+msgstr "Horzono por Cron"
+
+msgid "Cron syntax"
+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 "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 "CycleAnalyticsStage|Code"
+msgstr "Programado"
+
+msgid "CycleAnalyticsStage|Issue"
+msgstr "Problemo"
+
+msgid "CycleAnalyticsStage|Plan"
+msgstr "Plano"
+
+msgid "CycleAnalyticsStage|Production"
+msgstr "Eldonado"
+
+msgid "CycleAnalyticsStage|Review"
+msgstr "Kontrolo"
+
+msgid "CycleAnalyticsStage|Staging"
+msgstr "Preparo por eldono"
+
+msgid "CycleAnalyticsStage|Test"
+msgstr "Testado"
+
+msgid "Define a custom pattern with cron syntax"
+msgstr "Difini propran ŝablonon, uzante la sintakson de Cron"
+
+msgid "Delete"
+msgstr "Forigi"
+
+msgid "Deploy"
+msgid_plural "Deploys"
+msgstr[0] "Disponigado"
+msgstr[1] "Disponigadoj"
+
+msgid "Description"
+msgstr "Priskribo"
+
+msgid "Directory name"
+msgstr "Nomo de dosierujo"
+
+msgid "Don't show again"
+msgstr "Ne montru denove"
+
+msgid "Download"
+msgstr "Elŝuti"
+
+msgid "Download tar"
+msgstr "Elŝuti en formato „tar“"
+
+msgid "Download tar.bz2"
+msgstr "Elŝuti en formato „tar.bz2“"
+
+msgid "Download tar.gz"
+msgstr "Elŝuti en formato „tar.gz“"
+
+msgid "Download zip"
+msgstr "Elŝuti en formato „zip“"
+
+msgid "DownloadArtifacts|Download"
+msgstr "Elŝuti"
+
+msgid "DownloadCommit|Email Patches"
+msgstr "Sendi flikaĵojn per retpoŝto"
+
+msgid "DownloadCommit|Plain Diff"
+msgstr "Normala dosiero kun diferencoj"
+
+msgid "DownloadSource|Download"
+msgstr "Elŝuti"
+
+msgid "Edit"
+msgstr "Redakti"
+
+msgid "Edit Pipeline Schedule %{id}"
+msgstr "Redakti ĉenstablan planon %{id}"
+
+msgid "Every day (at 4:00am)"
+msgstr "Ĉiutage (je 4:00)"
+
+msgid "Every month (on the 1st at 4:00am)"
+msgstr "Ĉiumonate (en la 1a de la monato, je 4:00)"
+
+msgid "Every week (Sundays at 4:00am)"
+msgstr "Ĉiusemajne (en dimanĉo, je 4:00)"
+
+msgid "Failed to change the owner"
+msgstr "Ne eblas ŝanĝi la posedanton"
+
+msgid "Failed to remove the pipeline schedule"
+msgstr "Ne eblas forigi la ĉenstablan planon"
+
+msgid "Files"
+msgstr "Dosieroj"
+
+msgid "Find by path"
+msgstr "Trovi per dosierindiko"
+
+msgid "Find file"
+msgstr "Trovi dosieron"
+
+msgid "FirstPushedBy|First"
+msgstr "Unue"
+
+msgid "FirstPushedBy|pushed by"
+msgstr "alpuŝita de"
+
+msgid "Fork"
+msgid_plural "Forks"
+msgstr[0] "Disbranĉigo"
+msgstr[1] "Disbranĉigoj"
+
+msgid "ForkedFromProjectPath|Forked from"
+msgstr "Disbranĉigita el"
+
+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 "Go to your fork"
+msgstr "Al via disbranĉigo"
+
+msgid "GoToYourFork|Fork"
+msgstr "Disbranĉigo"
+
+msgid "Home"
+msgstr "Hejmo"
+
+msgid "Housekeeping successfully started"
+msgstr "La refreŝigo komenciĝis sukcese"
+
+msgid "Import repository"
+msgstr "Enporti deponejon"
+
+msgid "Interval Pattern"
+msgstr "Intervala ŝablono"
+
+msgid "Introducing Cycle Analytics"
+msgstr "Ni prezentas al vi la ciklan analizon"
+
+msgid "LFSStatus|Disabled"
+msgstr "Malŝaltita"
+
+msgid "LFSStatus|Enabled"
+msgstr "Ŝaltita"
+
+msgid "Last %d day"
+msgid_plural "Last %d days"
+msgstr[0] "La lasta %d tago"
+msgstr[1] "La lastaj %d tagoj"
+
+msgid "Last Pipeline"
+msgstr "Lasta ĉenstablo"
+
+msgid "Last Update"
+msgstr "Lasta ĝisdatigo"
+
+msgid "Last commit"
+msgstr "Lasta enmetado"
+
+msgid "Learn more in the"
+msgstr "Lernu pli en la"
+
+msgid "Learn more in the|pipeline schedules documentation"
+msgstr "dokumentado pri ĉenstablaj planoj"
+
+msgid "Leave group"
+msgstr "Forlasi la grupon"
+
+msgid "Leave project"
+msgstr "Forlasi la projekton"
+
+msgid "Limited to showing %d event at most"
+msgid_plural "Limited to showing %d events at most"
+msgstr[0] "Limigita al montrado de ne pli ol %d evento"
+msgstr[1] "Limigita al montrado de ne pli ol %d eventoj"
+
+msgid "Median"
+msgstr "Mediano"
+
+msgid "MissingSSHKeyWarningLink|add an SSH key"
+msgstr "aldonos SSH-ŝlosilon"
+
+msgid "New Issue"
+msgid_plural "New Issues"
+msgstr[0] "Nova problemo"
+msgstr[1] "Novaj problemoj"
+
+msgid "New Pipeline Schedule"
+msgstr "Nova ĉenstabla plano"
+
+msgid "New branch"
+msgstr "Nova branĉo"
+
+msgid "New directory"
+msgstr "Nova dosierujo"
+
+msgid "New file"
+msgstr "Nova dosiero"
+
+msgid "New issue"
+msgstr "Nova problemo"
+
+msgid "New merge request"
+msgstr "Nova peto pri kunfando"
+
+msgid "New schedule"
+msgstr "Nova plano"
+
+msgid "New snippet"
+msgstr "Nova kodaĵo"
+
+msgid "New tag"
+msgstr "Nova etikedo"
+
+msgid "No repository"
+msgstr "Ne estas deponejo"
+
+msgid "No schedules"
+msgstr "Ne estas planoj"
+
+msgid "Not available"
+msgstr "Ne disponebla"
+
+msgid "Not enough data"
+msgstr "Ne estas sufiĉe da datenoj"
+
+msgid "Notification events"
+msgstr "Sciigaj eventoj"
+
+msgid "NotificationEvent|Close issue"
+msgstr "Fermi problemon"
+
+msgid "NotificationEvent|Close merge request"
+msgstr "Fermi peton pri kunfando"
+
+msgid "NotificationEvent|Failed pipeline"
+msgstr "Malsukcesa ĉenstablo"
+
+msgid "NotificationEvent|Merge merge request"
+msgstr "Apliki peton pri kunfando"
+
+msgid "NotificationEvent|New issue"
+msgstr "Nova problemo"
+
+msgid "NotificationEvent|New merge request"
+msgstr "Nova peto pri kunfando"
+
+msgid "NotificationEvent|New note"
+msgstr "Nova noto"
+
+msgid "NotificationEvent|Reassign issue"
+msgstr "Reatribui problemon"
+
+msgid "NotificationEvent|Reassign merge request"
+msgstr "Reatribui peton pri kunfando"
+
+msgid "NotificationEvent|Reopen issue"
+msgstr "Remalfermi problemon"
+
+msgid "NotificationEvent|Successful pipeline"
+msgstr "Sukcesa ĉenstablo"
+
+msgid "NotificationLevel|Custom"
+msgstr "Propraj"
+
+msgid "NotificationLevel|Disabled"
+msgstr "Malŝaltitaj"
+
+msgid "NotificationLevel|Global"
+msgstr "Ĝeneralaj"
+
+msgid "NotificationLevel|On mention"
+msgstr "Ĉe mencio"
+
+msgid "NotificationLevel|Participate"
+msgstr "Partoprenado"
+
+msgid "NotificationLevel|Watch"
+msgstr "Rigardado"
+
+msgid "OfSearchInADropdown|Filter"
+msgstr "Filtrilo"
+
+msgid "OpenedNDaysAgo|Opened"
+msgstr "Malfermita"
+
+msgid "Options"
+msgstr "Opcioj"
+
+msgid "Owner"
+msgstr "Posedanto"
+
+msgid "Pipeline"
+msgstr "Ĉenstablo"
+
+msgid "Pipeline Health"
+msgstr "Stato"
+
+msgid "Pipeline Schedule"
+msgstr "Ĉenstabla plano"
+
+msgid "Pipeline Schedules"
+msgstr "Ĉenstablaj planoj"
+
+msgid "PipelineSchedules|Activated"
+msgstr "Ŝaltita"
+
+msgid "PipelineSchedules|Active"
+msgstr "Ŝaltitaj"
+
+msgid "PipelineSchedules|All"
+msgstr "Ĉiuj"
+
+msgid "PipelineSchedules|Inactive"
+msgstr "Malŝaltitaj"
+
+msgid "PipelineSchedules|Next Run"
+msgstr "Sekvanta plenumo"
+
+msgid "PipelineSchedules|None"
+msgstr "Nenio"
+
+msgid "PipelineSchedules|Provide a short description for this pipeline"
+msgstr "Entajpu mallongan priskribon pri ĉi tiu ĉenstablo"
+
+msgid "PipelineSchedules|Take ownership"
+msgstr "Akiri posedon"
+
+msgid "PipelineSchedules|Target"
+msgstr "Celo"
+
+msgid "PipelineSheduleIntervalPattern|Custom"
+msgstr "Propra"
+
+msgid "Pipeline|with stage"
+msgstr "kun etapo"
+
+msgid "Pipeline|with stages"
+msgstr "kun etapoj"
+
+msgid "Project '%{project_name}' queued for deletion."
+msgstr "La projekto „%{project_name}“ estis alvicigita por forigado."
+
+msgid "Project '%{project_name}' was successfully created."
+msgstr "La projekto „%{project_name}“ estis sukcese kreita."
+
+msgid "Project '%{project_name}' was successfully updated."
+msgstr "La projekto „%{project_name}“ estis sukcese ĝisdatigita."
+
+msgid "Project '%{project_name}' will be deleted."
+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 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 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."
+
+msgid "Project home"
+msgstr "Hejmo de la projekto"
+
+msgid "ProjectFeature|Disabled"
+msgstr "Malŝaltita"
+
+msgid "ProjectFeature|Everyone with access"
+msgstr "Ĉiu, kiu havas atingon"
+
+msgid "ProjectFeature|Only team members"
+msgstr "Nur skipanoj"
+
+msgid "ProjectFileTree|Name"
+msgstr "Nomo"
+
+msgid "ProjectLastActivity|Never"
+msgstr "Neniam"
+
+msgid "ProjectLifecycle|Stage"
+msgstr "Etapo"
+
+msgid "ProjectNetworkGraph|Graph"
+msgstr "Grafeo"
+
+msgid "Read more"
+msgstr "Legu pli"
+
+msgid "Readme"
+msgstr "LeguMin"
+
+msgid "RefSwitcher|Branches"
+msgstr "Branĉoj"
+
+msgid "RefSwitcher|Tags"
+msgstr "Etikedoj"
+
+msgid "Related Commits"
+msgstr "Rilataj enmetadoj"
+
+msgid "Related Deployed Jobs"
+msgstr "Rilataj disponigitaj taskoj"
+
+msgid "Related Issues"
+msgstr "Rilataj problemoj"
+
+msgid "Related Jobs"
+msgstr "Rilataj taskoj"
+
+msgid "Related Merge Requests"
+msgstr "Rilataj petoj pri kunfando"
+
+msgid "Related Merged Requests"
+msgstr "Rilataj aplikitaj petoj pri kunfando"
+
+msgid "Remind later"
+msgstr "Rememorigu denove"
+
+msgid "Remove project"
+msgstr "Forigi la projekton"
+
+msgid "Request Access"
+msgstr "Peti atingeblon"
+
+msgid "Revert this commit"
+msgstr "Malfari ĉi tiun enmetadon"
+
+msgid "Revert this merge request"
+msgstr "Malfari ĉi tiun peton pri kunfando"
+
+msgid "Save pipeline schedule"
+msgstr "Konservi ĉenstablan planon"
+
+msgid "Schedule a new pipeline"
+msgstr "Plani novan ĉenstablon"
+
+msgid "Scheduling Pipelines"
+msgstr "Planado de la ĉenstabloj"
+
+msgid "Search branches and tags"
+msgstr "Serĉu branĉon aŭ etikedon"
+
+msgid "Select Archive Format"
+msgstr "Elektu formaton de arkivo"
+
+msgid "Select a timezone"
+msgstr "Elektu horzonon"
+
+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}"
+
+msgid "Set up CI"
+msgstr "Agordi SI"
+
+msgid "Set up Koding"
+msgstr "Agordi „Koding“"
+
+msgid "Set up auto deploy"
+msgstr "Agordi aŭtomatan disponigadon"
+
+msgid "SetPasswordToCloneLink|set a password"
+msgstr "kreos pasvorton"
+
+msgid "Showing %d event"
+msgid_plural "Showing %d events"
+msgstr[0] "Estas montrata %d evento"
+msgstr[1] "Estas montrataj %d eventoj"
+
+msgid "Source code"
+msgstr "Kodo"
+
+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 "Switch branch/tag"
+msgstr "Iri al branĉo/etikedo"
+
+msgid "Tag"
+msgid_plural "Tags"
+msgstr[0] "Etikedo"
+msgstr[1] "Etikedoj"
+
+msgid "Tags"
+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."
+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."
+
+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 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 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 project can be accessed by any logged in user."
+msgstr "Ĉiu ensalutita uzanto havas atingon al la projekto"
+
+msgid "The project can be accessed without any authentication."
+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 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 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 ""
+"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"
+
+msgid "Time before an issue starts implementation"
+msgstr "Tempo antaŭ la komenco de laboro super problemo"
+
+msgid "Time between merge request creation and merge/close"
+msgstr "Tempo inter la kreado de poeto pri kunfando kaj ĝia aplikado/fermado"
+
+msgid "Time until first merge request"
+msgstr "Tempo ĝis la unua peto pri kunfando"
+
+msgid "Timeago|%s days ago"
+msgstr "antaŭ %s tagoj"
+
+msgid "Timeago|%s days remaining"
+msgstr "restas %s tagoj"
+
+msgid "Timeago|%s hours remaining"
+msgstr "restas %s horoj"
+
+msgid "Timeago|%s minutes ago"
+msgstr "antaŭ %s minutoj"
+
+msgid "Timeago|%s minutes remaining"
+msgstr "restas %s minutoj"
+
+msgid "Timeago|%s months ago"
+msgstr "antaŭ %s monatoj"
+
+msgid "Timeago|%s months remaining"
+msgstr "restas %s monatoj"
+
+msgid "Timeago|%s seconds remaining"
+msgstr "restas %s sekundoj"
+
+msgid "Timeago|%s weeks ago"
+msgstr "antaŭ %s semajnoj"
+
+msgid "Timeago|%s weeks remaining"
+msgstr "restas %s semajnoj"
+
+msgid "Timeago|%s years ago"
+msgstr "antaŭ %s jaroj"
+
+msgid "Timeago|%s years remaining"
+msgstr "restas %s jaroj"
+
+msgid "Timeago|1 day remaining"
+msgstr "restas 1 tago"
+
+msgid "Timeago|1 hour remaining"
+msgstr "restas 1 horo"
+
+msgid "Timeago|1 minute remaining"
+msgstr "restas 1 minuto"
+
+msgid "Timeago|1 month remaining"
+msgstr "restas 1 monato"
+
+msgid "Timeago|1 week remaining"
+msgstr "restas 1 semajno"
+
+msgid "Timeago|1 year remaining"
+msgstr "restas 1 jaro"
+
+msgid "Timeago|Past due"
+msgstr "Malfruiĝis"
+
+msgid "Timeago|a day ago"
+msgstr "antaŭ unu tago"
+
+msgid "Timeago|a month ago"
+msgstr "antaŭ unu monato"
+
+msgid "Timeago|a week ago"
+msgstr "antaŭ unu semajno"
+
+msgid "Timeago|a while"
+msgstr "antaŭ iom da tempo"
+
+msgid "Timeago|a year ago"
+msgstr "antaŭ unu jaro"
+
+msgid "Timeago|about %s hours ago"
+msgstr "antaŭ ĉirkaŭ %s horoj"
+
+msgid "Timeago|about a minute ago"
+msgstr "antaŭ ĉirkaŭ unu minuto"
+
+msgid "Timeago|about an hour ago"
+msgstr "antaŭ ĉirkaŭ unu horo"
+
+msgid "Timeago|in %s days"
+msgstr "post %s tagoj"
+
+msgid "Timeago|in %s hours"
+msgstr "post %s horoj"
+
+msgid "Timeago|in %s minutes"
+msgstr "post %s minutoj"
+
+msgid "Timeago|in %s months"
+msgstr "post %s monatoj"
+
+msgid "Timeago|in %s seconds"
+msgstr "post %s sekundoj"
+
+msgid "Timeago|in %s weeks"
+msgstr "post %s semajnoj"
+
+msgid "Timeago|in %s years"
+msgstr "post %s jaroj"
+
+msgid "Timeago|in 1 day"
+msgstr "post 1 tago"
+
+msgid "Timeago|in 1 hour"
+msgstr "post 1 horo"
+
+msgid "Timeago|in 1 minute"
+msgstr "post 1 minuto"
+
+msgid "Timeago|in 1 month"
+msgstr "post 1 monato"
+
+msgid "Timeago|in 1 week"
+msgstr "post 1 semajno"
+
+msgid "Timeago|in 1 year"
+msgstr "post 1 jaro"
+
+msgid "Timeago|less than a minute ago"
+msgstr "antaŭ malpli ol minuto"
+
+msgid "Time|hr"
+msgid_plural "Time|hrs"
+msgstr[0] "h"
+msgstr[1] "h"
+
+msgid "Time|min"
+msgid_plural "Time|mins"
+msgstr[0] "min"
+msgstr[1] "min"
+
+msgid "Time|s"
+msgstr "s"
+
+msgid "Total Time"
+msgstr "Totala tempo"
+
+msgid "Total test time for all commits/merges"
+msgstr "Totala tempo por la testado de ĉiuj enmetadoj/kunfandoj"
+
+msgid "Unstar"
+msgstr "Malsteligi"
+
+msgid "Upload New File"
+msgstr "Alŝuti novan dosieron"
+
+msgid "Upload file"
+msgstr "Alŝuti dosieron"
+
+msgid "Use your global notification setting"
+msgstr "Uzi vian ĝeneralan agordon pri la sciigoj"
+
+msgid "VisibilityLevel|Internal"
+msgstr "Interna"
+
+msgid "VisibilityLevel|Private"
+msgstr "Privata"
+
+msgid "VisibilityLevel|Public"
+msgstr "Publika"
+
+msgid "Want to see the data? Please ask an administrator for access."
+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."
+
+msgid "Withdraw Access Request"
+msgstr "Nuligi la peton pri atingeblo"
+
+msgid ""
+"You are going to remove %{project_name_with_namespace}.\n"
+"Removed project CANNOT be restored!\n"
+"Are you ABSOLUTELY sure?"
+msgstr ""
+"Vi forigos „%{project_name_with_namespace}“.\n"
+"Oni NE POVAS malfari la forigon de projekto!\n"
+"Ĉu vi estas ABSOLUTE certa?"
+
+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 can only add files when you are on a branch"
+msgstr "Oni povas aldoni dosierojn nur kiam oni estas en branĉo"
+
+msgid "You have reached your project limit"
+msgstr "Vi ne povas krei pliajn projektojn"
+
+msgid "You must sign in to star a project"
+msgstr "Oni devas ensaluti por steligi projekton"
+
+msgid "You need permission."
+msgstr "VI bezonas permeson."
+
+msgid "You will not get any notifications via email"
+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"
+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"
+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 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"
+
+msgid "day"
+msgid_plural "days"
+msgstr[0] "tago"
+msgstr[1] "tagoj"
+
+msgid "new merge request"
+msgstr "novan peton pri kunfando"
+
+msgid "notification emails"
+msgstr "sciigoj per retpoŝto"
+
+msgid "parent"
+msgid_plural "parents"
+msgstr[0] "patro"
+msgstr[1] "patroj"
+
diff --git a/locale/eo/gitlab.po.time_stamp b/locale/eo/gitlab.po.time_stamp
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/locale/eo/gitlab.po.time_stamp
diff --git a/locale/zh_HK/gitlab.po b/locale/zh_HK/gitlab.po
index f0a9e44daf3..4d545d27185 100644
--- a/locale/zh_HK/gitlab.po
+++ b/locale/zh_HK/gitlab.po
@@ -1,39 +1,242 @@
-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
-# This file is distributed under the same license as the gitlab package.
-# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
-#
+# Huang Tao <htve@outlook.com>, 2017. #zanata
+# Victor Wu <anonymous@domain.com>, 2017.
+# Hazel Yang <anonymous@domain.com>, 2017.
msgid ""
msgstr ""
"Project-Id-Version: gitlab 1.0.0\n"
"Report-Msgid-Bugs-To: \n"
-"PO-Revision-Date: 2017-05-04 19:24-0500\n"
-"Last-Translator: HuangTao <htve@outlook.com>, 2017\n"
-"Language-Team: Chinese (Hong Kong) (https://www.transifex.com/gitlab-zh/teams/"
-"75177/zh_HK/)\n"
+"POT-Creation-Date: 2017-06-15 21:59-0500\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"Language: zh_HK\n"
-"Plural-Forms: nplurals=1; plural=0;\n"
+"PO-Revision-Date: 2017-06-19 09:57-0400\n"
+"Last-Translator: Huang Tao <htve@outlook.com>\n"
+"Language-Team: Chinese (Hong Kong) (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 "%{commit_author_link} committed %{commit_timeago}"
+msgstr "由 %{commit_author_link} 提交於 %{commit_timeago}"
+
+msgid "About auto deploy"
+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 "新增壹個用於推送或拉取的 SSH 秘鑰到賬號中。"
+
+msgid "Add new directory"
+msgstr "添加新目錄"
+
+msgid "Archived project! Repository is read-only"
+msgstr "歸檔項目!存儲庫為只讀"
msgid "Are you sure you want to delete this pipeline schedule?"
+msgstr "確定要刪除此流水線計劃嗎?"
+
+msgid "Attach a file by drag &amp; drop or %{upload_link}"
+msgstr "拖放文件到此處或者 %{upload_link}"
+
+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 "Branches"
+msgstr "分支"
+
+msgid "Browse files"
+msgstr "瀏覽文件"
msgid "ByAuthor|by"
msgstr "作者:"
+msgid "CI configuration"
+msgstr "CI 配置"
+
msgid "Cancel"
-msgstr ""
+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 "Commit"
msgid_plural "Commits"
msgstr[0] "提交"
+msgid "Commit message"
+msgstr "提交信息"
+
+msgid "CommitBoxTitle|Commit"
+msgstr "提交"
+
+msgid "CommitMessage|Add %{file_name}"
+msgstr "添加 %{file_name}"
+
+msgid "Commits"
+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 "複製URL到剪貼板"
+
+msgid "Copy commit SHA to clipboard"
+msgstr "複製提交 SHA 到剪貼板"
+
+msgid "Create New Directory"
+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 "Cron Timezone"
+msgstr "Cron 時區"
+
+msgid "Cron syntax"
+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 "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"
@@ -57,30 +260,81 @@ msgstr "預發布"
msgid "CycleAnalyticsStage|Test"
msgstr "測試"
+msgid "Define a custom pattern with cron syntax"
+msgstr "使用 Cron 語法定義自定義模式"
+
msgid "Delete"
-msgstr ""
+msgstr "刪除"
msgid "Deploy"
msgid_plural "Deploys"
msgstr[0] "部署"
msgid "Description"
-msgstr ""
+msgstr "描述"
+
+msgid "Directory name"
+msgstr "目錄名稱"
+
+msgid "Don't show again"
+msgstr "不再顯示"
+
+msgid "Download"
+msgstr "下載"
+
+msgid "Download tar"
+msgstr "下載 tar"
+
+msgid "Download tar.bz2"
+msgstr "下載 tar.bz2"
+
+msgid "Download tar.gz"
+msgstr "下載 tar.gz"
+
+msgid "Download zip"
+msgstr "下載 zip"
+
+msgid "DownloadArtifacts|Download"
+msgstr "下載"
+
+msgid "DownloadCommit|Email Patches"
+msgstr "電子郵件補丁"
+
+msgid "DownloadCommit|Plain Diff"
+msgstr "差異文件"
+
+msgid "DownloadSource|Download"
+msgstr "下載"
msgid "Edit"
-msgstr ""
+msgstr "編輯"
msgid "Edit Pipeline Schedule %{id}"
-msgstr ""
+msgstr "編輯 %{id} 流水線計劃"
+
+msgid "Every day (at 4:00am)"
+msgstr "每日執行(淩晨 4 點)"
+
+msgid "Every month (on the 1st at 4:00am)"
+msgstr "每月執行(每月 1 日淩晨 4 點)"
+
+msgid "Every week (Sundays at 4:00am)"
+msgstr "每週執行(周日淩晨 4 點)"
msgid "Failed to change the owner"
-msgstr ""
+msgstr "無法變更所有者"
msgid "Failed to remove the pipeline schedule"
-msgstr ""
+msgstr "無法刪除流水線計劃"
-msgid "Filter"
-msgstr ""
+msgid "Files"
+msgstr "文件"
+
+msgid "Find by path"
+msgstr "按路徑查找"
+
+msgid "Find file"
+msgstr "查找文件"
msgid "FirstPushedBy|First"
msgstr "首次推送"
@@ -88,24 +342,70 @@ msgstr "首次推送"
msgid "FirstPushedBy|pushed by"
msgstr "推送者:"
+msgid "Fork"
+msgid_plural "Forks"
+msgstr[0] "派生"
+
+msgid "ForkedFromProjectPath|Forked from"
+msgstr "派生自"
+
msgid "From issue creation until deploy to production"
msgstr "從創建議題到部署到生產環境"
msgid "From merge request merge until deploy to production"
msgstr "從合併請求的合併到部署至生產環境"
+msgid "Go to your fork"
+msgstr "跳轉到派生項目"
+
+msgid "GoToYourFork|Fork"
+msgstr "跳轉到派生項目"
+
+msgid "Home"
+msgstr "首頁"
+
+msgid "Housekeeping successfully started"
+msgstr "已開始維護"
+
+msgid "Import repository"
+msgstr "導入存儲庫"
+
msgid "Interval Pattern"
-msgstr ""
+msgstr "循環週期"
msgid "Introducing Cycle Analytics"
msgstr "週期分析簡介"
+msgid "LFSStatus|Disabled"
+msgstr "停用"
+
+msgid "LFSStatus|Enabled"
+msgstr "啟用"
+
msgid "Last %d day"
msgid_plural "Last %d days"
-msgstr[0] "最後 %d 天"
+msgstr[0] "最近 %d 天"
msgid "Last Pipeline"
-msgstr ""
+msgstr "最新流水線"
+
+msgid "Last Update"
+msgstr "最後更新"
+
+msgid "Last commit"
+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"
@@ -114,15 +414,45 @@ msgstr[0] "最多顯示 %d 個事件"
msgid "Median"
msgstr "中位數"
+msgid "MissingSSHKeyWarningLink|add an SSH key"
+msgstr "添加壹個 SSH 公鑰"
+
msgid "New Issue"
msgid_plural "New Issues"
-msgstr[0] "新議題"
+msgstr[0] "新建議題"
msgid "New Pipeline Schedule"
-msgstr ""
+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 ""
+msgstr "沒有計劃"
msgid "Not available"
msgstr "不可用"
@@ -130,54 +460,185 @@ msgstr "不可用"
msgid "Not enough data"
msgstr "數據不足"
+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 "開始於"
+msgid "Options"
+msgstr "操作"
+
msgid "Owner"
-msgstr ""
+msgstr "所有者"
+
+msgid "Pipeline"
+msgstr "流水線"
msgid "Pipeline Health"
msgstr "流水線健康指標"
msgid "Pipeline Schedule"
-msgstr ""
+msgstr "流水線計劃"
msgid "Pipeline Schedules"
-msgstr ""
+msgstr "流水線計劃"
msgid "PipelineSchedules|Activated"
-msgstr ""
+msgstr "是否啟用"
msgid "PipelineSchedules|Active"
-msgstr ""
+msgstr "已啟用"
msgid "PipelineSchedules|All"
-msgstr ""
+msgstr "所有"
msgid "PipelineSchedules|Inactive"
-msgstr ""
+msgstr "未啟用"
msgid "PipelineSchedules|Next Run"
-msgstr ""
+msgstr "下次運行時間"
msgid "PipelineSchedules|None"
-msgstr ""
+msgstr "無"
msgid "PipelineSchedules|Provide a short description for this pipeline"
-msgstr ""
+msgstr "為此流水線提供簡短描述"
msgid "PipelineSchedules|Take ownership"
-msgstr ""
+msgstr "取得所有者"
msgid "PipelineSchedules|Target"
-msgstr ""
+msgstr "目標"
+
+msgid "PipelineSheduleIntervalPattern|Custom"
+msgstr "自定義"
+
+msgid "Pipeline|with stage"
+msgstr "於階段"
+
+msgid "Pipeline|with stages"
+msgstr "於階段"
+
+msgid "Project '%{project_name}' queued for deletion."
+msgstr "項目 '%{project_name}' 已進入刪除隊列。"
+
+msgid "Project '%{project_name}' was successfully created."
+msgstr "項目 '%{project_name}' 已創建成功。"
+
+msgid "Project '%{project_name}' was successfully updated."
+msgstr "項目 '%{project_name}' 已更新完成。"
+
+msgid "Project '%{project_name}' will be deleted."
+msgstr "項目 '%{project_name}' 將被刪除。"
+
+msgid "Project access must be granted explicitly to each user."
+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 "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 "項目生命週期"
+msgstr "階段"
+
+msgid "ProjectNetworkGraph|Graph"
+msgstr "分支圖"
msgid "Read more"
msgstr "了解更多"
+msgid "Readme"
+msgstr "自述文件"
+
+msgid "RefSwitcher|Branches"
+msgstr "分支"
+
+msgid "RefSwitcher|Tags"
+msgstr "標籤"
+
msgid "Related Commits"
msgstr "相關的提交"
@@ -194,59 +655,164 @@ msgid "Related Merge Requests"
msgstr "相關的合併請求"
msgid "Related Merged Requests"
-msgstr "相關已合併的合並請求"
+msgstr "相關已合併的合併請求"
+
+msgid "Remind later"
+msgstr "稍後提醒"
+
+msgid "Remove project"
+msgstr "刪除項目"
+
+msgid "Request Access"
+msgstr "申請權限"
+
+msgid "Revert this commit"
+msgstr "還原此提交"
+
+msgid "Revert this merge request"
+msgstr "還原此合併請求"
msgid "Save pipeline schedule"
-msgstr ""
+msgstr "保存流水線計劃"
msgid "Schedule a new pipeline"
-msgstr ""
+msgstr "新建流水線計劃"
+
+msgid "Scheduling Pipelines"
+msgstr "流水線計劃"
+
+msgid "Search branches and tags"
+msgstr "搜索分支和標籤"
+
+msgid "Select Archive Format"
+msgstr "選擇下載格式"
msgid "Select a timezone"
-msgstr ""
+msgstr "選擇時區"
msgid "Select target branch"
-msgstr ""
+msgstr "選擇目標分支"
+
+msgid "Set a password on your account to pull or push via %{protocol}"
+msgstr "為賬號添加壹個用於推送或拉取的 %{protocol} 密碼。"
+
+msgid "Set up CI"
+msgstr "設置 CI"
+
+msgid "Set up Koding"
+msgstr "設置 Koding"
+
+msgid "Set up auto deploy"
+msgstr "設置自動部署"
+
+msgid "SetPasswordToCloneLink|set a password"
+msgstr "設置密碼"
msgid "Showing %d event"
msgid_plural "Showing %d events"
msgstr[0] "顯示 %d 個事件"
+msgid "Source code"
+msgstr "源代碼"
+
+msgid "StarProject|Star"
+msgstr "星標"
+
+msgid "Start a %{new_merge_request} with these changes"
+msgstr "由此更改 %{new_merge_request}"
+
+msgid "Switch branch/tag"
+msgstr "切換分支/標籤"
+
+msgid "Tag"
+msgid_plural "Tags"
+msgstr[0] "標籤"
+
+msgid "Tags"
+msgstr "標籤"
+
msgid "Target Branch"
-msgstr ""
+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 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 "與該階段相關的事件。"
-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 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 phase of the development lifecycle."
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 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 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 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 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 project can be accessed by any logged in user."
+msgstr "該項目允許已登錄的用戶訪問。"
+
+msgid "The project can be accessed without any authentication."
+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 repository for this project does not exist."
+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 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 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."
+msgstr "在創建壹個空的存儲庫或導入現有存儲庫之前,您將無法推送代碼。"
msgid "Time before an issue gets scheduled"
msgstr "議題被列入日程表的時間"
@@ -255,11 +821,134 @@ 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 "創建第壹個合併請求之前的時間"
+msgid "Timeago|%s days ago"
+msgstr " %s 天前"
+
+msgid "Timeago|%s days remaining"
+msgstr "剩餘 %s 天"
+
+msgid "Timeago|%s hours remaining"
+msgstr "剩餘 %s 小時"
+
+msgid "Timeago|%s minutes ago"
+msgstr " %s 分鐘前"
+
+msgid "Timeago|%s minutes remaining"
+msgstr "剩餘 %s 分鐘"
+
+msgid "Timeago|%s months ago"
+msgstr " %s 個月前"
+
+msgid "Timeago|%s months remaining"
+msgstr "剩餘 %s 月"
+
+msgid "Timeago|%s seconds remaining"
+msgstr "剩餘 %s 秒"
+
+msgid "Timeago|%s weeks ago"
+msgstr " %s 星期前"
+
+msgid "Timeago|%s weeks remaining"
+msgstr "剩餘 %s 星期"
+
+msgid "Timeago|%s years ago"
+msgstr " %s 年前"
+
+msgid "Timeago|%s years remaining"
+msgstr "剩餘 %s 年"
+
+msgid "Timeago|1 day remaining"
+msgstr "剩餘 1 天"
+
+msgid "Timeago|1 hour remaining"
+msgstr "剩餘 1 小時"
+
+msgid "Timeago|1 minute remaining"
+msgstr "剩餘 1 分鐘"
+
+msgid "Timeago|1 month remaining"
+msgstr "剩餘 1 個月"
+
+msgid "Timeago|1 week remaining"
+msgstr "剩餘 1 星期"
+
+msgid "Timeago|1 year remaining"
+msgstr "剩餘 1 年"
+
+msgid "Timeago|Past due"
+msgstr "逾期"
+
+msgid "Timeago|a day ago"
+msgstr " 1 天前"
+
+msgid "Timeago|a month ago"
+msgstr " 1 個月前"
+
+msgid "Timeago|a week ago"
+msgstr " 1 星期前"
+
+msgid "Timeago|a while"
+msgstr " 剛剛"
+
+msgid "Timeago|a year ago"
+msgstr " 1 年前"
+
+msgid "Timeago|about %s hours ago"
+msgstr "約 %s 小時前"
+
+msgid "Timeago|about a minute ago"
+msgstr "約 1 分鐘前"
+
+msgid "Timeago|about an hour ago"
+msgstr "約 1 小時前"
+
+msgid "Timeago|in %s days"
+msgstr " %s 天後"
+
+msgid "Timeago|in %s hours"
+msgstr " %s 小時後"
+
+msgid "Timeago|in %s minutes"
+msgstr " %s 分鐘後"
+
+msgid "Timeago|in %s months"
+msgstr " %s 個月後"
+
+msgid "Timeago|in %s seconds"
+msgstr " %s 秒後"
+
+msgid "Timeago|in %s weeks"
+msgstr " %s 星期後"
+
+msgid "Timeago|in %s years"
+msgstr " %s 年後"
+
+msgid "Timeago|in 1 day"
+msgstr " 1 天後"
+
+msgid "Timeago|in 1 hour"
+msgstr " 1 小時後"
+
+msgid "Timeago|in 1 minute"
+msgstr " 1 分鐘後"
+
+msgid "Timeago|in 1 month"
+msgstr " 1 月後"
+
+msgid "Timeago|in 1 week"
+msgstr " 1 星期後"
+
+msgid "Timeago|in 1 year"
+msgstr " 1 年後"
+
+msgid "Timeago|less than a minute ago"
+msgstr "不到 1 分鐘前"
+
msgid "Time|hr"
msgid_plural "Time|hrs"
msgstr[0] "小時"
@@ -277,18 +966,108 @@ msgstr "總時間"
msgid "Total test time for all commits/merges"
msgstr "所有提交和合併的總測試時間"
+msgid "Unstar"
+msgstr "取消星標"
+
+msgid "Upload New File"
+msgstr "上傳新文件"
+
+msgid "Upload file"
+msgstr "上傳文件"
+
+msgid "Use your global notification setting"
+msgstr "使用全局通知設置"
+
+msgid "VisibilityLevel|Internal"
+msgstr "內部"
+
+msgid "VisibilityLevel|Private"
+msgstr "私有"
+
+msgid "VisibilityLevel|Public"
+msgstr "公開"
+
msgid "Want to see the data? Please ask an administrator for access."
msgstr "權限不足。如需查看相關數據,請向管理員申請權限。"
msgid "We don't have enough data to show this stage."
msgstr "該階段的數據不足,無法顯示。"
+msgid "Withdraw Access Request"
+msgstr "取消權限申请"
+
+msgid ""
+"You are going to remove %{project_name_with_namespace}.\n"
+"Removed project CANNOT be restored!\n"
+"Are you ABSOLUTELY sure?"
+msgstr "即將要刪除 %{project_name_with_namespace}。\n"
+"已刪除的項目無法恢複!\n"
+"確定繼續嗎?"
+
+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 can only add files when you are on a branch"
+msgstr "只能在分支上添加文件"
+
msgid "You have reached your project limit"
-msgstr ""
+msgstr "您已達到項目數量限制"
+
+msgid "You must sign in to star a project"
+msgstr "必須登錄才能對項目加星標"
msgid "You need permission."
-msgstr "您需要相關的權限。"
+msgstr "需要相關的權限。"
+
+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 "在賬號上 %{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"
+msgstr "在賬號中 %{add_ssh_key_link} 之前將無法通過 SSH 拉取或推送代碼。"
+
+msgid "Your name"
+msgstr "您的名字"
msgid "day"
msgid_plural "days"
msgstr[0] "天"
+
+msgid "new merge request"
+msgstr "新建合併請求"
+
+msgid "notification emails"
+msgstr "通知郵件"
+
+msgid "parent"
+msgid_plural "parents"
+msgstr[0] "父級"
+
diff --git a/qa/Dockerfile b/qa/Dockerfile
index 97ae1961e34..f3a81a7e355 100644
--- a/qa/Dockerfile
+++ b/qa/Dockerfile
@@ -1,8 +1,6 @@
FROM ruby:2.3
LABEL maintainer "Grzegorz Bizon <grzegorz@gitlab.com>"
-
-ENV CHROME_VERSION 59.0.3071.109-1
-ENV CHROME_DRIVER_VERSION 2.30
+ENV DEBIAN_FRONTEND noninteractive
##
# Update APT sources and install some dependencies
@@ -15,22 +13,17 @@ RUN apt-get update && apt-get install -y wget git unzip xvfb
#
RUN curl -sS -L https://dl.google.com/linux/linux_signing_key.pub | apt-key add -
RUN echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" > /etc/apt/sources.list.d/google.list
-RUN apt-get update -q && DEBIAN_FRONTEND=noninteractive apt-get install -y google-chrome-stable=$CHROME_VERSION
+RUN apt-get update -q && apt-get install -y google-chrome-stable && apt-get clean
##
# Install chromedriver to make it work with Selenium
#
-RUN wget -q https://chromedriver.storage.googleapis.com/$CHROME_DRIVER_VERSION/chromedriver_linux64.zip
+RUN wget -q https://chromedriver.storage.googleapis.com/$(wget -q -O - https://chromedriver.storage.googleapis.com/LATEST_RELEASE)/chromedriver_linux64.zip
RUN unzip chromedriver_linux64.zip -d /usr/local/bin
-RUN apt-get clean
-
WORKDIR /home/qa
-
COPY ./Gemfile* ./
-
RUN bundle install
-
COPY ./ ./
ENTRYPOINT ["bin/test"]
diff --git a/spec/controllers/profiles/preferences_controller_spec.rb b/spec/controllers/profiles/preferences_controller_spec.rb
index 7b3aa0491c7..a5f544b4f92 100644
--- a/spec/controllers/profiles/preferences_controller_spec.rb
+++ b/spec/controllers/profiles/preferences_controller_spec.rb
@@ -43,7 +43,8 @@ describe Profiles::PreferencesController do
dashboard: 'stars'
}.with_indifferent_access
- expect(user).to receive(:update_attributes).with(prefs)
+ expect(user).to receive(:assign_attributes).with(prefs)
+ expect(user).to receive(:save)
go params: prefs
end
@@ -51,7 +52,7 @@ describe Profiles::PreferencesController do
context 'on failed update' do
it 'sets the flash' do
- expect(user).to receive(:update_attributes).and_return(false)
+ expect(user).to receive(:save).and_return(false)
go
diff --git a/spec/features/admin/admin_runners_spec.rb b/spec/features/admin/admin_runners_spec.rb
index 5b3323fed13..6ad2d456b93 100644
--- a/spec/features/admin/admin_runners_spec.rb
+++ b/spec/features/admin/admin_runners_spec.rb
@@ -9,31 +9,54 @@ describe "Admin Runners" do
end
describe "Runners page" do
- before do
- runner = FactoryGirl.create(:ci_runner, contacted_at: Time.now)
- pipeline = FactoryGirl.create(:ci_pipeline)
- FactoryGirl.create(:ci_build, pipeline: pipeline, runner_id: runner.id)
- visit admin_runners_path
- end
+ let(:pipeline) { create(:ci_pipeline) }
+
+ context "when there are runners" do
+ before do
+ runner = FactoryGirl.create(:ci_runner, contacted_at: Time.now)
+ FactoryGirl.create(:ci_build, pipeline: pipeline, runner_id: runner.id)
+ visit admin_runners_path
+ end
+
+ it 'has all necessary texts' do
+ expect(page).to have_text "To register a new Runner"
+ expect(page).to have_text "Runners with last contact more than a minute ago: 1"
+ end
+
+ describe 'search' do
+ before do
+ FactoryGirl.create :ci_runner, description: 'runner-foo'
+ FactoryGirl.create :ci_runner, description: 'runner-bar'
+ end
+
+ it 'shows correct runner when description matches' do
+ search_form = find('#runners-search')
+ search_form.fill_in 'search', with: 'runner-foo'
+ search_form.click_button 'Search'
+
+ expect(page).to have_content("runner-foo")
+ expect(page).not_to have_content("runner-bar")
+ end
+
+ it 'shows no runner when description does not match' do
+ search_form = find('#runners-search')
+ search_form.fill_in 'search', with: 'runner-baz'
+ search_form.click_button 'Search'
- it 'has all necessary texts' do
- expect(page).to have_text "To register a new Runner"
- expect(page).to have_text "Runners with last contact more than a minute ago: 1"
+ expect(page).to have_text 'No runners found'
+ end
+ end
end
- describe 'search' do
+ context "when there are no runners" do
before do
- FactoryGirl.create :ci_runner, description: 'runner-foo'
- FactoryGirl.create :ci_runner, description: 'runner-bar'
-
- search_form = find('#runners-search')
- search_form.fill_in 'search', with: 'runner-foo'
- search_form.click_button 'Search'
+ visit admin_runners_path
end
- it 'shows correct runner' do
- expect(page).to have_content("runner-foo")
- expect(page).not_to have_content("runner-bar")
+ it 'has all necessary texts including no runner message' do
+ expect(page).to have_text "To register a new Runner"
+ expect(page).to have_text "Runners with last contact more than a minute ago: 0"
+ expect(page).to have_text 'No runners found'
end
end
end
diff --git a/spec/features/dashboard/merge_requests_spec.rb b/spec/features/dashboard/merge_requests_spec.rb
index 69d5500848e..bb1fb5b3feb 100644
--- a/spec/features/dashboard/merge_requests_spec.rb
+++ b/spec/features/dashboard/merge_requests_spec.rb
@@ -1,18 +1,24 @@
require 'spec_helper'
-describe 'Dashboard Merge Requests' do
+feature 'Dashboard Merge Requests' do
+ include FilterItemSelectHelper
+
let(:current_user) { create :user }
let(:project) { create(:empty_project) }
- let(:project_with_merge_requests_disabled) { create(:empty_project, :merge_requests_disabled) }
- before do
- [project, project_with_merge_requests_disabled].each { |project| project.team << [current_user, :master] }
+ let(:public_project) { create(:empty_project, :public, :repository) }
+ let(:forked_project) { Projects::ForkService.new(public_project, current_user).execute }
- gitlab_sign_in(current_user)
+ before do
+ project.add_master(current_user)
+ sign_in(current_user)
end
- describe 'new merge request dropdown' do
+ context 'new merge request dropdown' do
+ let(:project_with_disabled_merge_requests) { create(:empty_project, :merge_requests_disabled) }
+
before do
+ project_with_disabled_merge_requests.add_master(current_user)
visit merge_requests_dashboard_path
end
@@ -21,26 +27,87 @@ describe 'Dashboard Merge Requests' do
page.within('.select2-results') do
expect(page).to have_content(project.name_with_namespace)
- expect(page).not_to have_content(project_with_merge_requests_disabled.name_with_namespace)
+ expect(page).not_to have_content(project_with_disabled_merge_requests.name_with_namespace)
end
end
end
- it 'should show an empty state' do
- visit merge_requests_dashboard_path(assignee_id: current_user.id)
+ context 'no merge requests exist' do
+ it 'shows an empty state' do
+ visit merge_requests_dashboard_path(assignee_id: current_user.id)
- expect(page).to have_selector('.empty-state')
+ expect(page).to have_selector('.empty-state')
+ end
end
- context 'if there are merge requests' do
- before do
- create(:merge_request, assignee: current_user, source_project: project)
+ context 'merge requests exist' do
+ let!(:assigned_merge_request) do
+ create(:merge_request, assignee: current_user, target_project: project, source_project: project)
+ end
+
+ let!(:assigned_merge_request_from_fork) do
+ create(:merge_request,
+ source_branch: 'markdown', assignee: current_user,
+ target_project: public_project, source_project: forked_project
+ )
+ end
+ let!(:authored_merge_request) do
+ create(:merge_request,
+ source_branch: 'markdown', author: current_user,
+ target_project: project, source_project: project
+ )
+ end
+
+ let!(:authored_merge_request_from_fork) do
+ create(:merge_request,
+ source_branch: 'feature_conflict',
+ author: current_user,
+ target_project: public_project, source_project: forked_project
+ )
+ end
+
+ let!(:other_merge_request) do
+ create(:merge_request,
+ source_branch: 'fix',
+ target_project: project, source_project: project
+ )
+ end
+
+ before do
visit merge_requests_dashboard_path(assignee_id: current_user.id)
end
- it 'should not show an empty state' do
- expect(page).not_to have_selector('.empty-state')
+ it 'shows assigned merge requests' do
+ expect(page).to have_content(assigned_merge_request.title)
+ expect(page).to have_content(assigned_merge_request_from_fork.title)
+
+ expect(page).not_to have_content(authored_merge_request.title)
+ expect(page).not_to have_content(authored_merge_request_from_fork.title)
+ expect(page).not_to have_content(other_merge_request.title)
+ end
+
+ it 'shows authored merge requests', js: true do
+ filter_item_select('Any Assignee', '.js-assignee-search')
+ filter_item_select(current_user.to_reference, '.js-author-search')
+
+ expect(page).to have_content(authored_merge_request.title)
+ expect(page).to have_content(authored_merge_request_from_fork.title)
+
+ expect(page).not_to have_content(assigned_merge_request.title)
+ expect(page).not_to have_content(assigned_merge_request_from_fork.title)
+ expect(page).not_to have_content(other_merge_request.title)
+ end
+
+ it 'shows all merge requests', js: true do
+ filter_item_select('Any Assignee', '.js-assignee-search')
+ filter_item_select('Any Author', '.js-author-search')
+
+ expect(page).to have_content(authored_merge_request.title)
+ expect(page).to have_content(authored_merge_request_from_fork.title)
+ expect(page).to have_content(assigned_merge_request.title)
+ expect(page).to have_content(assigned_merge_request_from_fork.title)
+ expect(page).to have_content(other_merge_request.title)
end
end
end
diff --git a/spec/features/dashboard/milestone_filter_spec.rb b/spec/features/dashboard/milestone_filter_spec.rb
index 295262980a6..b0e4036f27c 100644
--- a/spec/features/dashboard/milestone_filter_spec.rb
+++ b/spec/features/dashboard/milestone_filter_spec.rb
@@ -1,10 +1,12 @@
require 'spec_helper'
-describe 'Dashboard > milestone filter', :feature, :js do
+feature 'Dashboard > milestone filter', :feature, :js do
+ include FilterItemSelectHelper
+
let(:user) { create(:user) }
let(:project) { create(:project, name: 'test', namespace: user.namespace) }
- let(:milestone) { create(:milestone, title: "v1.0", project: project) }
- let(:milestone2) { create(:milestone, title: "v2.0", project: project) }
+ let(:milestone) { create(:milestone, title: 'v1.0', project: project) }
+ let(:milestone2) { create(:milestone, title: 'v2.0', project: project) }
let!(:issue) { create :issue, author: user, project: project, milestone: milestone }
let!(:issue2) { create :issue, author: user, project: project, milestone: milestone2 }
@@ -22,17 +24,11 @@ describe 'Dashboard > milestone filter', :feature, :js do
end
context 'filtering by milestone' do
- milestone_select = '.js-milestone-select'
+ milestone_select_selector = '.js-milestone-select'
before do
- find(milestone_select).click
- wait_for_requests
-
- page.within('.dropdown-content') do
- click_link 'v1.0'
- end
-
- find(milestone_select).click
+ filter_item_select('v1.0', milestone_select_selector)
+ find(milestone_select_selector).click
wait_for_requests
end
@@ -49,7 +45,7 @@ describe 'Dashboard > milestone filter', :feature, :js do
expect(find('.milestone-filter')).not_to have_selector('.dropdown.open')
- find(milestone_select).click
+ find(milestone_select_selector).click
expect(find('.dropdown-content')).to have_selector('a.is-active', count: 1)
expect(find('.dropdown-content a.is-active')).to have_content('v1.0')
diff --git a/spec/features/dashboard/projects_spec.rb b/spec/features/dashboard/projects_spec.rb
index 2a8185ca669..f29186f368d 100644
--- a/spec/features/dashboard/projects_spec.rb
+++ b/spec/features/dashboard/projects_spec.rb
@@ -15,13 +15,25 @@ RSpec.describe 'Dashboard Projects', feature: true do
expect(page).to have_content('awesome stuff')
end
- it 'shows the last_activity_at attribute as the update date' do
- now = Time.now
- project.update_column(:last_activity_at, now)
+ context 'when last_repository_updated_at, last_activity_at and update_at are present' do
+ it 'shows the last_repository_updated_at attribute as the update date' do
+ project.update_attributes!(last_repository_updated_at: Time.now, last_activity_at: 1.hour.ago)
- visit dashboard_projects_path
+ visit dashboard_projects_path
+
+ expect(page).to have_xpath("//time[@datetime='#{project.last_repository_updated_at.getutc.iso8601}']")
+ end
+ end
- expect(page).to have_xpath("//time[@datetime='#{now.getutc.iso8601}']")
+ context 'when last_repository_updated_at and last_activity_at are missing' do
+ it 'shows the updated_at attribute as the update date' do
+ project.update_attributes!(last_repository_updated_at: nil, last_activity_at: nil)
+ project.touch
+
+ visit dashboard_projects_path
+
+ expect(page).to have_xpath("//time[@datetime='#{project.updated_at.getutc.iso8601}']")
+ end
end
context 'when on Starred projects tab' do
diff --git a/spec/features/todos/target_state_spec.rb b/spec/features/dashboard/todos/target_state_spec.rb
index 99b70b3d3a1..030a86d1c01 100644
--- a/spec/features/todos/target_state_spec.rb
+++ b/spec/features/dashboard/todos/target_state_spec.rb
@@ -1,12 +1,12 @@
require 'rails_helper'
-feature 'Todo target states', feature: true do
+feature 'Dashboard > Todo target states' do
let(:user) { create(:user) }
let(:author) { create(:user) }
- let(:project) { create(:project, visibility_level: Gitlab::VisibilityLevel::PUBLIC) }
+ let(:project) { create(:project, :public) }
before do
- gitlab_sign_in user
+ sign_in(user)
end
scenario 'on a closed issue todo has closed label' do
@@ -30,7 +30,7 @@ feature 'Todo target states', feature: true do
end
scenario 'on a merged merge request todo has merged label' do
- mr_merged = create(:merge_request, :simple, author: user, state: 'merged')
+ mr_merged = create(:merge_request, :simple, :merged, author: user)
create_todo mr_merged
visit dashboard_todos_path
@@ -40,7 +40,7 @@ feature 'Todo target states', feature: true do
end
scenario 'on a closed merge request todo has closed label' do
- mr_closed = create(:merge_request, :simple, author: user, state: 'closed')
+ mr_closed = create(:merge_request, :simple, :closed, author: user)
create_todo mr_closed
visit dashboard_todos_path
diff --git a/spec/features/todos/todos_filtering_spec.rb b/spec/features/dashboard/todos/todos_filtering_spec.rb
index 032fb479076..0a363259fe7 100644
--- a/spec/features/todos/todos_filtering_spec.rb
+++ b/spec/features/dashboard/todos/todos_filtering_spec.rb
@@ -1,6 +1,6 @@
require 'spec_helper'
-describe 'Dashboard > User filters todos', feature: true, js: true do
+feature 'Dashboard > User filters todos', js: true do
let(:user_1) { create(:user, username: 'user_1', name: 'user_1') }
let(:user_2) { create(:user, username: 'user_2', name: 'user_2') }
@@ -17,7 +17,7 @@ describe 'Dashboard > User filters todos', feature: true, js: true do
project_1.team << [user_1, :developer]
project_2.team << [user_1, :developer]
- gitlab_sign_in(user_1)
+ sign_in(user_1)
visit dashboard_todos_path
end
@@ -34,7 +34,7 @@ describe 'Dashboard > User filters todos', feature: true, js: true do
expect(page).not_to have_content project_2.name_with_namespace
end
- context "Author filter" do
+ context 'Author filter' do
it 'filters by author' do
click_button 'Author'
@@ -49,18 +49,18 @@ describe 'Dashboard > User filters todos', feature: true, js: true do
expect(find('.todos-list')).not_to have_content 'issue'
end
- it "shows only authors of existing todos" do
+ it 'shows only authors of existing todos' do
click_button 'Author'
within '.dropdown-menu-author' do
- # It should contain two users + "Any Author"
+ # It should contain two users + 'Any Author'
expect(page).to have_selector('.dropdown-menu-user-link', count: 3)
expect(page).to have_content(user_1.name)
expect(page).to have_content(user_2.name)
end
end
- it "shows only authors of existing done todos" do
+ it 'shows only authors of existing done todos' do
user_3 = create :user
user_4 = create :user
create(:todo, user: user_1, author: user_3, project: project_1, target: issue, action: 1, state: :done)
@@ -74,7 +74,7 @@ describe 'Dashboard > User filters todos', feature: true, js: true do
click_button 'Author'
within '.dropdown-menu-author' do
- # It should contain two users + "Any Author"
+ # It should contain two users + 'Any Author'
expect(page).to have_selector('.dropdown-menu-user-link', count: 3)
expect(page).to have_content(user_3.name)
expect(page).to have_content(user_4.name)
diff --git a/spec/features/todos/todos_sorting_spec.rb b/spec/features/dashboard/todos/todos_sorting_spec.rb
index 498bbac6d14..5858f4aa101 100644
--- a/spec/features/todos/todos_sorting_spec.rb
+++ b/spec/features/dashboard/todos/todos_sorting_spec.rb
@@ -1,6 +1,6 @@
require 'spec_helper'
-describe "Dashboard > User sorts todos", feature: true do
+feature 'Dashboard > User sorts todos' do
let(:user) { create(:user) }
let(:project) { create(:empty_project) }
@@ -18,7 +18,7 @@ describe "Dashboard > User sorts todos", feature: true do
let(:issue_3) { create(:issue, title: 'issue_3', project: project) }
let(:issue_4) { create(:issue, title: 'issue_4', project: project) }
- let!(:merge_request_1) { create(:merge_request, source_project: project, title: "merge_request_1") }
+ let!(:merge_request_1) { create(:merge_request, source_project: project, title: 'merge_request_1') }
before do
create(:todo, user: user, project: project, target: issue_4, created_at: 5.hours.ago)
@@ -32,41 +32,41 @@ describe "Dashboard > User sorts todos", feature: true do
issue_2.labels << label_3
issue_1.labels << label_2
- gitlab_sign_in(user)
+ sign_in(user)
visit dashboard_todos_path
end
- it "sorts with oldest created todos first" do
- click_link "Last created"
+ it 'sorts with oldest created todos first' do
+ click_link 'Last created'
results_list = page.find('.todos-list')
- expect(results_list.all('p')[0]).to have_content("merge_request_1")
- expect(results_list.all('p')[1]).to have_content("issue_1")
- expect(results_list.all('p')[2]).to have_content("issue_3")
- expect(results_list.all('p')[3]).to have_content("issue_2")
- expect(results_list.all('p')[4]).to have_content("issue_4")
+ expect(results_list.all('p')[0]).to have_content('merge_request_1')
+ expect(results_list.all('p')[1]).to have_content('issue_1')
+ expect(results_list.all('p')[2]).to have_content('issue_3')
+ expect(results_list.all('p')[3]).to have_content('issue_2')
+ expect(results_list.all('p')[4]).to have_content('issue_4')
end
- it "sorts with newest created todos first" do
- click_link "Oldest created"
+ it 'sorts with newest created todos first' do
+ click_link 'Oldest created'
results_list = page.find('.todos-list')
- expect(results_list.all('p')[0]).to have_content("issue_4")
- expect(results_list.all('p')[1]).to have_content("issue_2")
- expect(results_list.all('p')[2]).to have_content("issue_3")
- expect(results_list.all('p')[3]).to have_content("issue_1")
- expect(results_list.all('p')[4]).to have_content("merge_request_1")
+ expect(results_list.all('p')[0]).to have_content('issue_4')
+ expect(results_list.all('p')[1]).to have_content('issue_2')
+ expect(results_list.all('p')[2]).to have_content('issue_3')
+ expect(results_list.all('p')[3]).to have_content('issue_1')
+ expect(results_list.all('p')[4]).to have_content('merge_request_1')
end
- it "sorts by label priority" do
- click_link "Label priority"
+ it 'sorts by label priority' do
+ click_link 'Label priority'
results_list = page.find('.todos-list')
- expect(results_list.all('p')[0]).to have_content("issue_3")
- expect(results_list.all('p')[1]).to have_content("merge_request_1")
- expect(results_list.all('p')[2]).to have_content("issue_1")
- expect(results_list.all('p')[3]).to have_content("issue_2")
- expect(results_list.all('p')[4]).to have_content("issue_4")
+ expect(results_list.all('p')[0]).to have_content('issue_3')
+ expect(results_list.all('p')[1]).to have_content('merge_request_1')
+ expect(results_list.all('p')[2]).to have_content('issue_1')
+ expect(results_list.all('p')[3]).to have_content('issue_2')
+ expect(results_list.all('p')[4]).to have_content('issue_4')
end
end
@@ -88,12 +88,12 @@ describe "Dashboard > User sorts todos", feature: true do
end
it "doesn't mix issues and merge requests label priorities" do
- click_link "Label priority"
+ click_link 'Label priority'
results_list = page.find('.todos-list')
- expect(results_list.all('p')[0]).to have_content("issue_1")
- expect(results_list.all('p')[1]).to have_content("issue_2")
- expect(results_list.all('p')[2]).to have_content("merge_request_1")
+ expect(results_list.all('p')[0]).to have_content('issue_1')
+ expect(results_list.all('p')[1]).to have_content('issue_2')
+ expect(results_list.all('p')[2]).to have_content('merge_request_1')
end
end
end
diff --git a/spec/features/dashboard/todos/todos_spec.rb b/spec/features/dashboard/todos/todos_spec.rb
new file mode 100644
index 00000000000..24da5db305f
--- /dev/null
+++ b/spec/features/dashboard/todos/todos_spec.rb
@@ -0,0 +1,355 @@
+require 'spec_helper'
+
+feature 'Dashboard Todos' do
+ let(:user) { create(:user) }
+ let(:author) { create(:user) }
+ let(:project) { create(:project, :public) }
+ let(:issue) { create(:issue, due_date: Date.today) }
+
+ context 'User does not have todos' do
+ before do
+ sign_in(user)
+ visit dashboard_todos_path
+ end
+
+ it 'shows "All done" message' do
+ expect(page).to have_content 'Todos let you see what you should do next.'
+ end
+ end
+
+ context 'User has a todo', js: true do
+ before do
+ create(:todo, :mentioned, user: user, project: project, target: issue, author: author)
+ sign_in(user)
+
+ visit dashboard_todos_path
+ end
+
+ it 'has todo present' do
+ expect(page).to have_selector('.todos-list .todo', count: 1)
+ end
+
+ it 'shows due date as today' do
+ within first('.todo') do
+ expect(page).to have_content 'Due today'
+ end
+ end
+
+ shared_examples 'deleting the todo' do
+ before do
+ within first('.todo') do
+ click_link 'Done'
+ end
+ end
+
+ it 'is marked as done-reversible in the list' do
+ expect(page).to have_selector('.todos-list .todo.todo-pending.done-reversible')
+ end
+
+ it 'shows Undo button' do
+ expect(page).to have_selector('.js-undo-todo', visible: true)
+ expect(page).to have_selector('.js-done-todo', visible: false)
+ end
+
+ it 'updates todo count' do
+ expect(page).to have_content 'To do 0'
+ expect(page).to have_content 'Done 1'
+ end
+
+ it 'has not "All done" message' do
+ expect(page).not_to have_selector('.todos-all-done')
+ end
+ end
+
+ shared_examples 'deleting and restoring the todo' do
+ before do
+ within first('.todo') do
+ click_link 'Done'
+ wait_for_requests
+ click_link 'Undo'
+ end
+ end
+
+ it 'is marked back as pending in the list' do
+ expect(page).not_to have_selector('.todos-list .todo.todo-pending.done-reversible')
+ expect(page).to have_selector('.todos-list .todo.todo-pending')
+ end
+
+ it 'shows Done button' do
+ expect(page).to have_selector('.js-undo-todo', visible: false)
+ expect(page).to have_selector('.js-done-todo', visible: true)
+ end
+
+ it 'updates todo count' do
+ expect(page).to have_content 'To do 1'
+ expect(page).to have_content 'Done 0'
+ end
+ end
+
+ it_behaves_like 'deleting the todo'
+ it_behaves_like 'deleting and restoring the todo'
+
+ context 'todo is stale on the page' do
+ before do
+ todos = TodosFinder.new(user, state: :pending).execute
+ TodoService.new.mark_todos_as_done(todos, user)
+ end
+
+ it_behaves_like 'deleting the todo'
+ it_behaves_like 'deleting and restoring the todo'
+ end
+ end
+
+ context 'User created todos for themself' do
+ before do
+ sign_in(user)
+ end
+
+ context 'issue assigned todo' do
+ before do
+ create(:todo, :assigned, user: user, project: project, target: issue, author: user)
+ visit dashboard_todos_path
+ end
+
+ it 'shows issue assigned to yourself message' do
+ page.within('.js-todos-all') do
+ expect(page).to have_content("You assigned issue #{issue.to_reference(full: true)} to yourself")
+ end
+ end
+ end
+
+ context 'marked todo' do
+ before do
+ create(:todo, :marked, user: user, project: project, target: issue, author: user)
+ visit dashboard_todos_path
+ end
+
+ it 'shows you added a todo message' do
+ page.within('.js-todos-all') do
+ expect(page).to have_content("You added a todo for issue #{issue.to_reference(full: true)}")
+ expect(page).not_to have_content('to yourself')
+ end
+ end
+ end
+
+ context 'mentioned todo' do
+ before do
+ create(:todo, :mentioned, user: user, project: project, target: issue, author: user)
+ visit dashboard_todos_path
+ end
+
+ it 'shows you mentioned yourself message' do
+ page.within('.js-todos-all') do
+ expect(page).to have_content("You mentioned yourself on issue #{issue.to_reference(full: true)}")
+ expect(page).not_to have_content('to yourself')
+ end
+ end
+ end
+
+ context 'directly_addressed todo' do
+ before do
+ create(:todo, :directly_addressed, user: user, project: project, target: issue, author: user)
+ visit dashboard_todos_path
+ end
+
+ it 'shows you directly addressed yourself message' do
+ page.within('.js-todos-all') do
+ expect(page).to have_content("You directly addressed yourself on issue #{issue.to_reference(full: true)}")
+ expect(page).not_to have_content('to yourself')
+ end
+ end
+ end
+
+ context 'approval todo' do
+ let(:merge_request) { create(:merge_request) }
+
+ before do
+ create(:todo, :approval_required, user: user, project: project, target: merge_request, author: user)
+ visit dashboard_todos_path
+ end
+
+ it 'shows you set yourself as an approver message' do
+ page.within('.js-todos-all') do
+ expect(page).to have_content("You set yourself as an approver for merge request #{merge_request.to_reference(full: true)}")
+ expect(page).not_to have_content('to yourself')
+ end
+ end
+ end
+ end
+
+ context 'User has done todos', js: true do
+ before do
+ create(:todo, :mentioned, :done, user: user, project: project, target: issue, author: author)
+ sign_in(user)
+ visit dashboard_todos_path(state: :done)
+ end
+
+ it 'has the done todo present' do
+ expect(page).to have_selector('.todos-list .todo.todo-done', count: 1)
+ end
+
+ describe 'restoring the todo' do
+ before do
+ within first('.todo') do
+ click_link 'Add todo'
+ end
+ end
+
+ it 'is removed from the list' do
+ expect(page).not_to have_selector('.todos-list .todo.todo-done')
+ end
+
+ it 'updates todo count' do
+ expect(page).to have_content 'To do 1'
+ expect(page).to have_content 'Done 0'
+ end
+ end
+ end
+
+ context 'User has Todos with labels spanning multiple projects' do
+ before do
+ label1 = create(:label, project: project)
+ note1 = create(:note_on_issue, note: "Hello #{label1.to_reference(format: :name)}", noteable_id: issue.id, noteable_type: 'Issue', project: issue.project)
+ create(:todo, :mentioned, project: project, target: issue, user: user, note_id: note1.id)
+
+ project2 = create(:project, :public)
+ label2 = create(:label, project: project2)
+ issue2 = create(:issue, project: project2)
+ note2 = create(:note_on_issue, note: "Test #{label2.to_reference(format: :name)}", noteable_id: issue2.id, noteable_type: 'Issue', project: project2)
+ create(:todo, :mentioned, project: project2, target: issue2, user: user, note_id: note2.id)
+
+ gitlab_sign_in(user)
+ visit dashboard_todos_path
+ end
+
+ it 'shows page with two Todos' do
+ expect(page).to have_selector('.todos-list .todo', count: 2)
+ end
+ end
+
+ context 'User has multiple pages of Todos' do
+ before do
+ allow(Todo).to receive(:default_per_page).and_return(1)
+
+ # Create just enough records to cause us to paginate
+ create_list(:todo, 2, :mentioned, user: user, project: project, target: issue, author: author)
+
+ sign_in(user)
+ end
+
+ it 'is paginated' do
+ visit dashboard_todos_path
+
+ expect(page).to have_selector('.gl-pagination')
+ end
+
+ it 'is has the right number of pages' do
+ visit dashboard_todos_path
+
+ expect(page).to have_selector('.gl-pagination .page', count: 2)
+ end
+
+ describe 'mark all as done', js: true do
+ before do
+ visit dashboard_todos_path
+ find('.js-todos-mark-all').trigger('click')
+ end
+
+ it 'shows "All done" message!' do
+ expect(page).to have_content 'To do 0'
+ expect(page).to have_content "You're all done!"
+ expect(page).not_to have_selector('.gl-pagination')
+ end
+
+ it 'shows "Undo mark all as done" button' do
+ expect(page).to have_selector('.js-todos-mark-all', visible: false)
+ expect(page).to have_selector('.js-todos-undo-all', visible: true)
+ end
+ end
+
+ describe 'undo mark all as done', js: true do
+ before do
+ visit dashboard_todos_path
+ end
+
+ it 'shows the restored todo list' do
+ mark_all_and_undo
+
+ expect(page).to have_selector('.todos-list .todo', count: 1)
+ expect(page).to have_selector('.gl-pagination')
+ expect(page).not_to have_content "You're all done!"
+ end
+
+ it 'updates todo count' do
+ mark_all_and_undo
+
+ expect(page).to have_content 'To do 2'
+ expect(page).to have_content 'Done 0'
+ end
+
+ it 'shows "Mark all as done" button' do
+ mark_all_and_undo
+
+ expect(page).to have_selector('.js-todos-mark-all', visible: true)
+ expect(page).to have_selector('.js-todos-undo-all', visible: false)
+ end
+
+ context 'User has deleted a todo' do
+ before do
+ within first('.todo') do
+ click_link 'Done'
+ end
+ end
+
+ it 'shows the restored todo list with the deleted todo' do
+ mark_all_and_undo
+
+ expect(page).to have_selector('.todos-list .todo.todo-pending', count: 1)
+ end
+ end
+
+ def mark_all_and_undo
+ find('.js-todos-mark-all').trigger('click')
+ wait_for_requests
+ find('.js-todos-undo-all').trigger('click')
+ wait_for_requests
+ end
+ end
+ end
+
+ context 'User has a Todo in a project pending deletion' do
+ before do
+ deleted_project = create(:project, :public, pending_delete: true)
+ create(:todo, :mentioned, user: user, project: deleted_project, target: issue, author: author)
+ create(:todo, :mentioned, user: user, project: deleted_project, target: issue, author: author, state: :done)
+ sign_in(user)
+ visit dashboard_todos_path
+ end
+
+ it 'shows "All done" message' do
+ within('.todos-count') { expect(page).to have_content '0' }
+ expect(page).to have_content 'To do 0'
+ expect(page).to have_content 'Done 0'
+ expect(page).to have_selector('.todos-all-done', count: 1)
+ end
+ end
+
+ context 'User has a Build Failed todo' do
+ let!(:todo) { create(:todo, :build_failed, user: user, project: project, author: author) }
+
+ before do
+ sign_in(user)
+ visit dashboard_todos_path
+ end
+
+ it 'shows the todo' do
+ expect(page).to have_content 'The build failed for merge request'
+ end
+
+ it 'links to the pipelines for the merge request' do
+ href = pipelines_namespace_project_merge_request_path(project.namespace, project, todo.target)
+
+ expect(page).to have_link "merge request #{todo.target.to_reference(full: true)}", href
+ end
+ end
+end
diff --git a/spec/features/groups/group_settings_spec.rb b/spec/features/groups/group_settings_spec.rb
index 5ad777248ec..56e163ec4d0 100644
--- a/spec/features/groups/group_settings_spec.rb
+++ b/spec/features/groups/group_settings_spec.rb
@@ -18,14 +18,14 @@ feature 'Edit group settings', feature: true do
update_path(new_group_path)
visit new_group_full_path
expect(current_path).to eq(new_group_full_path)
- expect(find('h1.group-title')).to have_content(new_group_path)
+ expect(find('h1.group-title')).to have_content(group.name)
end
scenario 'the old group path redirects to the new path' do
update_path(new_group_path)
visit old_group_full_path
expect(current_path).to eq(new_group_full_path)
- expect(find('h1.group-title')).to have_content(new_group_path)
+ expect(find('h1.group-title')).to have_content(group.name)
end
context 'with a subgroup' do
@@ -37,14 +37,14 @@ feature 'Edit group settings', feature: true do
update_path(new_group_path)
visit new_subgroup_full_path
expect(current_path).to eq(new_subgroup_full_path)
- expect(find('h1.group-title')).to have_content(subgroup.path)
+ expect(find('h1.group-title')).to have_content(subgroup.name)
end
scenario 'the old subgroup path redirects to the new path' do
update_path(new_group_path)
visit old_subgroup_full_path
expect(current_path).to eq(new_subgroup_full_path)
- expect(find('h1.group-title')).to have_content(subgroup.path)
+ expect(find('h1.group-title')).to have_content(subgroup.name)
end
end
diff --git a/spec/features/groups/labels/subscription_spec.rb b/spec/features/groups/labels/subscription_spec.rb
new file mode 100644
index 00000000000..8b891c52d08
--- /dev/null
+++ b/spec/features/groups/labels/subscription_spec.rb
@@ -0,0 +1,51 @@
+require 'spec_helper'
+
+feature 'Labels subscription', feature: true do
+ let(:user) { create(:user) }
+ let(:group) { create(:group) }
+ let!(:feature) { create(:group_label, group: group, title: 'feature') }
+
+ context 'when signed in' do
+ before do
+ group.add_developer(user)
+ gitlab_sign_in user
+ end
+
+ scenario 'users can subscribe/unsubscribe to group labels', js: true do
+ visit group_labels_path(group)
+
+ expect(page).to have_content('feature')
+
+ within "#group_label_#{feature.id}" do
+ expect(page).not_to have_button 'Unsubscribe'
+
+ click_button 'Subscribe'
+
+ expect(page).not_to have_button 'Subscribe'
+ expect(page).to have_button 'Unsubscribe'
+
+ click_button 'Unsubscribe'
+
+ expect(page).to have_button 'Subscribe'
+ expect(page).not_to have_button 'Unsubscribe'
+ end
+ end
+ end
+
+ context 'when not signed in' do
+ it 'users can not subscribe/unsubscribe to labels' do
+ visit group_labels_path(group)
+
+ expect(page).to have_content 'feature'
+ expect(page).not_to have_button('Subscribe')
+ end
+ end
+
+ def click_link_on_dropdown(text)
+ find('.dropdown-group-label').click
+
+ page.within('.dropdown-group-label') do
+ find('a.js-subscribe-button', text: text).click
+ end
+ end
+end
diff --git a/spec/features/groups/members/last_owner_cannot_leave_group_spec.rb b/spec/features/groups/members/last_owner_cannot_leave_group_spec.rb
deleted file mode 100644
index 5af94e4069b..00000000000
--- a/spec/features/groups/members/last_owner_cannot_leave_group_spec.rb
+++ /dev/null
@@ -1,16 +0,0 @@
-require 'spec_helper'
-
-feature 'Groups > Members > Last owner cannot leave group', feature: true do
- let(:owner) { create(:user) }
- let(:group) { create(:group) }
-
- background do
- group.add_owner(owner)
- gitlab_sign_in(owner)
- visit group_path(group)
- end
-
- scenario 'user does not see a "Leave group" link' do
- expect(page).not_to have_content 'Leave group'
- end
-end
diff --git a/spec/features/groups/members/leave_group_spec.rb b/spec/features/groups/members/leave_group_spec.rb
new file mode 100644
index 00000000000..b438f57753c
--- /dev/null
+++ b/spec/features/groups/members/leave_group_spec.rb
@@ -0,0 +1,62 @@
+require 'spec_helper'
+
+feature 'Groups > Members > Leave group', feature: true do
+ let(:user) { create(:user) }
+ let(:other_user) { create(:user) }
+ let(:group) { create(:group) }
+
+ background do
+ gitlab_sign_in(user)
+ end
+
+ scenario 'guest leaves the group' do
+ group.add_guest(user)
+ group.add_owner(other_user)
+
+ visit group_path(group)
+ click_link 'Leave group'
+
+ expect(current_path).to eq(dashboard_groups_path)
+ expect(page).to have_content left_group_message(group)
+ expect(group.users).not_to include(user)
+ end
+
+ scenario 'guest leaves the group as last member' do
+ group.add_guest(user)
+
+ visit group_path(group)
+ click_link 'Leave group'
+
+ expect(current_path).to eq(dashboard_groups_path)
+ expect(page).to have_content left_group_message(group)
+ expect(group.users).not_to include(user)
+ end
+
+ scenario 'owner leaves the group if they is not the last owner' do
+ group.add_owner(user)
+ group.add_owner(other_user)
+
+ visit group_path(group)
+ click_link 'Leave group'
+
+ expect(current_path).to eq(dashboard_groups_path)
+ expect(page).to have_content left_group_message(group)
+ expect(group.users).not_to include(user)
+ end
+
+ scenario 'owner can not leave the group if they is a last owner' do
+ group.add_owner(user)
+
+ visit group_path(group)
+
+ expect(page).not_to have_content 'Leave group'
+
+ visit group_group_members_path(group)
+
+ expect(find(:css, '.project-members-page li', text: user.name)).not_to have_selector(:css, 'a.btn-remove')
+ end
+
+ def left_group_message(group)
+ "You left the \"#{group.name}\""
+ end
+end
diff --git a/spec/features/groups/members/list_members_spec.rb b/spec/features/groups/members/list_members_spec.rb
new file mode 100644
index 00000000000..f6493c4c50e
--- /dev/null
+++ b/spec/features/groups/members/list_members_spec.rb
@@ -0,0 +1,42 @@
+require 'spec_helper'
+
+feature 'Groups > Members > List members', feature: true do
+ include Select2Helper
+
+ let(:user1) { create(:user, name: 'John Doe') }
+ let(:user2) { create(:user, name: 'Mary Jane') }
+ let(:group) { create(:group) }
+ let(:nested_group) { create(:group, parent: group) }
+
+ background do
+ gitlab_sign_in(user1)
+ end
+
+ scenario 'show members from current group and parent', :nested_groups do
+ group.add_developer(user1)
+ nested_group.add_developer(user2)
+
+ visit group_group_members_path(nested_group)
+
+ expect(first_row.text).to include(user1.name)
+ expect(second_row.text).to include(user2.name)
+ end
+
+ scenario 'show user once if member of both current group and parent', :nested_groups do
+ group.add_developer(user1)
+ nested_group.add_developer(user1)
+
+ visit group_group_members_path(nested_group)
+
+ expect(first_row.text).to include(user1.name)
+ expect(second_row).to be_blank
+ end
+
+ def first_row
+ page.all('ul.content-list > li')[0]
+ end
+
+ def second_row
+ page.all('ul.content-list > li')[1]
+ end
+end
diff --git a/spec/features/groups/members/owner_manages_access_requests_spec.rb b/spec/features/groups/members/manage_access_requests_spec.rb
index 4e4cf12e8af..f84d8594c65 100644
--- a/spec/features/groups/members/owner_manages_access_requests_spec.rb
+++ b/spec/features/groups/members/manage_access_requests_spec.rb
@@ -1,6 +1,6 @@
require 'spec_helper'
-feature 'Groups > Members > Owner manages access requests', feature: true do
+feature 'Groups > Members > Manage access requests', feature: true do
let(:user) { create(:user) }
let(:owner) { create(:user) }
let(:group) { create(:group, :public, :access_requestable) }
@@ -17,7 +17,7 @@ feature 'Groups > Members > Owner manages access requests', feature: true do
expect_visible_access_request(group, user)
end
- scenario 'master can grant access' do
+ scenario 'owner can grant access' do
visit group_group_members_path(group)
expect_visible_access_request(group, user)
@@ -28,7 +28,7 @@ feature 'Groups > Members > Owner manages access requests', feature: true do
expect(ActionMailer::Base.deliveries.last.subject).to match "Access to the #{group.name} group was granted"
end
- scenario 'master can deny access' do
+ scenario 'owner can deny access' do
visit group_group_members_path(group)
expect_visible_access_request(group, user)
diff --git a/spec/features/groups/members/list_spec.rb b/spec/features/groups/members/manage_members.rb
index 5d00ed30c83..a9a654b20e2 100644
--- a/spec/features/groups/members/list_spec.rb
+++ b/spec/features/groups/members/manage_members.rb
@@ -1,37 +1,16 @@
require 'spec_helper'
-feature 'Groups members list', feature: true do
+feature 'Groups > Members > Manage members', feature: true do
include Select2Helper
let(:user1) { create(:user, name: 'John Doe') }
let(:user2) { create(:user, name: 'Mary Jane') }
let(:group) { create(:group) }
- let(:nested_group) { create(:group, parent: group) }
background do
gitlab_sign_in(user1)
end
- scenario 'show members from current group and parent', :nested_groups do
- group.add_developer(user1)
- nested_group.add_developer(user2)
-
- visit group_group_members_path(nested_group)
-
- expect(first_row.text).to include(user1.name)
- expect(second_row.text).to include(user2.name)
- end
-
- scenario 'show user once if member of both current group and parent', :nested_groups do
- group.add_developer(user1)
- nested_group.add_developer(user1)
-
- visit group_group_members_path(nested_group)
-
- expect(first_row.text).to include(user1.name)
- expect(second_row).to be_blank
- end
-
scenario 'update user to owner level', :js do
group.add_owner(user1)
group.add_developer(user2)
@@ -59,6 +38,18 @@ feature 'Groups members list', feature: true do
end
end
+ scenario 'remove user from group', :js do
+ group.add_owner(user1)
+ group.add_developer(user2)
+
+ visit group_group_members_path(group)
+
+ find(:css, '.project-members-page li', text: user2.name).find(:css, 'a.btn-remove').click
+
+ expect(page).not_to have_content(user2.name)
+ expect(group.users).not_to include(user2)
+ end
+
scenario 'add yourself to group when already an owner', :js do
group.add_owner(user1)
@@ -86,6 +77,23 @@ feature 'Groups members list', feature: true do
end
end
+ scenario 'guest can not manage other users' do
+ group.add_guest(user1)
+ group.add_developer(user2)
+
+ visit group_group_members_path(group)
+
+ expect(page).not_to have_button 'Add to group'
+
+ page.within(second_row) do
+ # Can not modify user2 role
+ expect(page).not_to have_button 'Developer'
+
+ # Can not remove user2
+ expect(page).not_to have_css('a.btn-remove')
+ end
+ end
+
def first_row
page.all('ul.content-list > li')[0]
end
diff --git a/spec/features/groups/members/member_cannot_request_access_to_his_project_spec.rb b/spec/features/groups/members/member_cannot_request_access_to_his_project_spec.rb
deleted file mode 100644
index 135bb3572bc..00000000000
--- a/spec/features/groups/members/member_cannot_request_access_to_his_project_spec.rb
+++ /dev/null
@@ -1,16 +0,0 @@
-require 'spec_helper'
-
-feature 'Groups > Members > Member cannot request access to his project', feature: true do
- let(:member) { create(:user) }
- let(:group) { create(:group) }
-
- background do
- group.add_developer(member)
- gitlab_sign_in(member)
- visit group_path(group)
- end
-
- scenario 'member does not see the request access button' do
- expect(page).not_to have_content 'Request Access'
- end
-end
diff --git a/spec/features/groups/members/member_leaves_group_spec.rb b/spec/features/groups/members/member_leaves_group_spec.rb
deleted file mode 100644
index 40f3b166e74..00000000000
--- a/spec/features/groups/members/member_leaves_group_spec.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-require 'spec_helper'
-
-feature 'Groups > Members > Member leaves group', feature: true do
- let(:user) { create(:user) }
- let(:owner) { create(:user) }
- let(:group) { create(:group, :public) }
-
- background do
- group.add_owner(owner)
- group.add_developer(user)
- gitlab_sign_in(user)
- visit group_path(group)
- end
-
- scenario 'user leaves group' do
- click_link 'Leave group'
-
- expect(current_path).to eq(dashboard_groups_path)
- expect(group.users.exists?(user.id)).to be_falsey
- end
-end
diff --git a/spec/features/groups/members/user_requests_access_spec.rb b/spec/features/groups/members/request_access_spec.rb
index 3813308c237..41c31b62e18 100644
--- a/spec/features/groups/members/user_requests_access_spec.rb
+++ b/spec/features/groups/members/request_access_spec.rb
@@ -1,6 +1,6 @@
require 'spec_helper'
-feature 'Groups > Members > User requests access', feature: true do
+feature 'Groups > Members > Request access', feature: true do
let(:user) { create(:user) }
let(:owner) { create(:user) }
let(:group) { create(:group, :public, :access_requestable) }
@@ -68,4 +68,11 @@ feature 'Groups > Members > User requests access', feature: true do
expect(group.requesters.exists?(user_id: user)).to be_falsey
expect(page).to have_content 'Your access request to the group has been withdrawn.'
end
+
+ scenario 'member does not see the request access button' do
+ group.add_owner(user)
+ visit group_path(group)
+
+ expect(page).not_to have_content 'Request Access'
+ end
end
diff --git a/spec/features/groups/members/sorting_spec.rb b/spec/features/groups/members/sort_members_spec.rb
index 719fa0b40b8..8ee61953844 100644
--- a/spec/features/groups/members/sorting_spec.rb
+++ b/spec/features/groups/members/sort_members_spec.rb
@@ -1,6 +1,6 @@
require 'spec_helper'
-feature 'Groups > Members > Sorting', feature: true do
+feature 'Groups > Members > Sort members', feature: true do
let(:owner) { create(:user, name: 'John Doe') }
let(:developer) { create(:user, name: 'Mary Jane', last_sign_in_at: 5.days.ago) }
let(:group) { create(:group) }
diff --git a/spec/features/login_spec.rb b/spec/features/login_spec.rb
index 53b8ba5b0f7..a8055b21cee 100644
--- a/spec/features/login_spec.rb
+++ b/spec/features/login_spec.rb
@@ -143,29 +143,8 @@ feature 'Login', feature: true do
end
context 'logging in via OAuth' do
- def saml_config
- OpenStruct.new(name: 'saml', label: 'saml', args: {
- assertion_consumer_service_url: 'https://localhost:3443/users/auth/saml/callback',
- idp_cert_fingerprint: '26:43:2C:47:AF:F0:6B:D0:07:9C:AD:A3:74:FE:5D:94:5F:4E:9E:52',
- idp_sso_target_url: 'https://idp.example.com/sso/saml',
- issuer: 'https://localhost:3443/',
- name_identifier_format: 'urn:oasis:names:tc:SAML:2.0:nameid-format:transient'
- })
- end
-
- def stub_omniauth_config(messages)
- Rails.application.env_config['devise.mapping'] = Devise.mappings[:user]
- Rails.application.routes.disable_clear_and_finalize = true
- Rails.application.routes.draw do
- post '/users/auth/saml' => 'omniauth_callbacks#saml'
- end
- allow(Gitlab::OAuth::Provider).to receive_messages(providers: [:saml], config_for: saml_config)
- allow(Gitlab.config.omniauth).to receive_messages(messages)
- expect_any_instance_of(Object).to receive(:omniauth_authorize_path).with(:user, "saml").and_return('/users/auth/saml')
- end
-
it 'shows 2FA prompt after OAuth login' do
- stub_omniauth_config(enabled: true, auto_link_saml_user: true, allow_single_sign_on: ['saml'], providers: [saml_config])
+ stub_omniauth_saml_config(enabled: true, auto_link_saml_user: true, allow_single_sign_on: ['saml'], providers: [mock_saml_config])
user = create(:omniauth_user, :two_factor, extern_uid: 'my-uid', provider: 'saml')
gitlab_sign_in_via('saml', user, 'my-uid')
diff --git a/spec/features/profiles/password_spec.rb b/spec/features/profiles/password_spec.rb
index 2d36f3d020f..86c9df5ff86 100644
--- a/spec/features/profiles/password_spec.rb
+++ b/spec/features/profiles/password_spec.rb
@@ -25,7 +25,7 @@ describe 'Profile > Password', feature: true do
end
end
- it 'does not contains the current password field after an error' do
+ it 'does not contain the current password field after an error' do
fill_passwords('mypassword', 'mypassword2')
expect(page).to have_no_field('user[current_password]')
diff --git a/spec/features/profiles/user_visits_notifications_tab_spec.rb b/spec/features/profiles/user_visits_notifications_tab_spec.rb
new file mode 100644
index 00000000000..e98cec79d87
--- /dev/null
+++ b/spec/features/profiles/user_visits_notifications_tab_spec.rb
@@ -0,0 +1,21 @@
+require 'spec_helper'
+
+feature 'User visits the notifications tab', js: true do
+ let(:project) { create(:empty_project) }
+ let(:user) { create(:user) }
+
+ before do
+ project.team << [user, :master]
+ sign_in(user)
+ visit(profile_notifications_path)
+ end
+
+ it 'changes the project notifications setting' do
+ expect(page).to have_content('Notifications')
+
+ first('#notifications-button').trigger('click')
+ click_link('On mention')
+
+ expect(page).to have_content('On mention')
+ end
+end
diff --git a/spec/features/projects/blobs/blob_line_permalink_updater_spec.rb b/spec/features/projects/blobs/blob_line_permalink_updater_spec.rb
index 53c5a52ce3a..d94204230f6 100644
--- a/spec/features/projects/blobs/blob_line_permalink_updater_spec.rb
+++ b/spec/features/projects/blobs/blob_line_permalink_updater_spec.rb
@@ -55,7 +55,7 @@ feature 'Blob button line permalinks (BlobLinePermalinkUpdater)', feature: true,
end
end
- describe 'Click "Annotate" button' do
+ describe 'Click "Blame" button' do
it 'works with no initial line number fragment hash' do
visit_blob
diff --git a/spec/features/projects/environments/environments_spec.rb b/spec/features/projects/environments/environments_spec.rb
index 83883dba0ba..cf4d996a32d 100644
--- a/spec/features/projects/environments/environments_spec.rb
+++ b/spec/features/projects/environments/environments_spec.rb
@@ -151,7 +151,7 @@ feature 'Environments page', :feature, :js do
find('.js-dropdown-play-icon-container').click
expect(page).to have_content(action.name.humanize)
- expect { find('.js-manual-action-link').click }
+ expect { find('.js-manual-action-link').trigger('click') }
.not_to change { Ci::Pipeline.count }
end
diff --git a/spec/features/projects/files/browse_files_spec.rb b/spec/features/projects/files/browse_files_spec.rb
index 2a82c3ac179..34aef958ec6 100644
--- a/spec/features/projects/files/browse_files_spec.rb
+++ b/spec/features/projects/files/browse_files_spec.rb
@@ -12,7 +12,7 @@ feature 'user browses project', feature: true, js: true do
scenario "can see blame of '.gitignore'" do
click_link ".gitignore"
- click_link 'Annotate'
+ click_link 'Blame'
expect(page).to have_content "*.rb"
expect(page).to have_content "Dmitriy Zaporozhets"
diff --git a/spec/features/projects/no_password_spec.rb b/spec/features/projects/no_password_spec.rb
new file mode 100644
index 00000000000..30a16e38e3c
--- /dev/null
+++ b/spec/features/projects/no_password_spec.rb
@@ -0,0 +1,69 @@
+require 'spec_helper'
+
+feature 'No Password Alert' do
+ let(:project) { create(:project, namespace: user.namespace) }
+
+ context 'with internal auth enabled' do
+ before do
+ sign_in(user)
+ visit namespace_project_path(project.namespace, project)
+ end
+
+ context 'when user has a password' do
+ let(:user) { create(:user) }
+
+ it 'shows no alert' do
+ expect(page).not_to have_content "You won't be able to pull or push project code via HTTP until you set a password on your account"
+ end
+ end
+
+ context 'when user has password automatically set' do
+ let(:user) { create(:user, password_automatically_set: true) }
+
+ it 'shows a password alert' do
+ expect(page).to have_content "You won't be able to pull or push project code via HTTP until you set a password on your account"
+ end
+ end
+ end
+
+ context 'with internal auth disabled' do
+ let(:user) { create(:omniauth_user, extern_uid: 'my-uid', provider: 'saml') }
+
+ before do
+ stub_application_setting(signin_enabled?: false)
+ stub_omniauth_saml_config(enabled: true, auto_link_saml_user: true, allow_single_sign_on: ['saml'], providers: [mock_saml_config])
+ end
+
+ context 'when user has no personal access tokens' do
+ it 'has a personal access token alert' do
+ gitlab_sign_in_via('saml', user, 'my-uid')
+ visit namespace_project_path(project.namespace, project)
+
+ expect(page).to have_content "You won't be able to pull or push project code via HTTP until you create a personal access token on your account"
+ end
+ end
+
+ context 'when user has a personal access token' do
+ it 'shows no alert' do
+ create(:personal_access_token, user: user)
+ gitlab_sign_in_via('saml', user, 'my-uid')
+ visit namespace_project_path(project.namespace, project)
+
+ expect(page).not_to have_content "You won't be able to pull or push project code via HTTP until you create a personal access token on your account"
+ end
+ end
+ end
+
+ context 'when user is ldap user' do
+ let(:user) { create(:omniauth_user, password_automatically_set: true) }
+
+ before do
+ sign_in(user)
+ visit namespace_project_path(project.namespace, project)
+ end
+
+ it 'shows no alert' do
+ expect(page).not_to have_content "You won't be able to pull or push project code via HTTP until you"
+ end
+ end
+end
diff --git a/spec/features/projects/services/jira_service_spec.rb b/spec/features/projects/services/jira_service_spec.rb
index 2ea50e8f672..8cd216c8fdb 100644
--- a/spec/features/projects/services/jira_service_spec.rb
+++ b/spec/features/projects/services/jira_service_spec.rb
@@ -6,7 +6,11 @@ feature 'Setup Jira service', :feature, :js do
let(:service) { project.create_jira_service }
let(:url) { 'http://jira.example.com' }
- let(:project_url) { 'http://username:password@jira.example.com/rest/api/2/project/GitLabProject' }
+
+ def stub_project_url
+ WebMock.stub_request(:get, 'http://jira.example.com/rest/api/2/project/GitLabProject')
+ .with(basic_auth: %w(username password))
+ end
def fill_form(active = true)
check 'Active' if active
@@ -28,7 +32,7 @@ feature 'Setup Jira service', :feature, :js do
describe 'user sets and activates Jira Service' do
context 'when Jira connection test succeeds' do
before do
- WebMock.stub_request(:get, project_url)
+ stub_project_url
end
it 'activates the JIRA service' do
@@ -44,7 +48,7 @@ feature 'Setup Jira service', :feature, :js do
context 'when Jira connection test fails' do
before do
- WebMock.stub_request(:get, project_url).to_return(status: 401)
+ stub_project_url.to_return(status: 401)
end
it 'shows errors when some required fields are not filled in' do
diff --git a/spec/features/snippets/notes_on_personal_snippets_spec.rb b/spec/features/snippets/notes_on_personal_snippets_spec.rb
index d310e7501ec..c7e2e3d8a34 100644
--- a/spec/features/snippets/notes_on_personal_snippets_spec.rb
+++ b/spec/features/snippets/notes_on_personal_snippets_spec.rb
@@ -33,6 +33,7 @@ describe 'Comments on personal snippets', :js, feature: true do
expect(page).to have_selector('.note-emoji-button')
end
+ find('body').click # close dropdown
open_more_actions_dropdown(snippet_notes[1])
page.within("#notes-list li#note_#{snippet_notes[1].id}") do
diff --git a/spec/features/todos/todos_spec.rb b/spec/features/todos/todos_spec.rb
deleted file mode 100644
index 41b32bdedc3..00000000000
--- a/spec/features/todos/todos_spec.rb
+++ /dev/null
@@ -1,355 +0,0 @@
-require 'spec_helper'
-
-describe 'Dashboard Todos', feature: true do
- let(:user) { create(:user) }
- let(:author) { create(:user) }
- let(:project) { create(:project, visibility_level: Gitlab::VisibilityLevel::PUBLIC) }
- let(:issue) { create(:issue, due_date: Date.today) }
-
- describe 'GET /dashboard/todos' do
- context 'User does not have todos' do
- before do
- gitlab_sign_in(user)
- visit dashboard_todos_path
- end
- it 'shows "All done" message' do
- expect(page).to have_content "Todos let you see what you should do next."
- end
- end
-
- context 'User has a todo', js: true do
- before do
- create(:todo, :mentioned, user: user, project: project, target: issue, author: author)
- gitlab_sign_in(user)
- visit dashboard_todos_path
- end
-
- it 'has todo present' do
- expect(page).to have_selector('.todos-list .todo', count: 1)
- end
-
- it 'shows due date as today' do
- within first('.todo') do
- expect(page).to have_content 'Due today'
- end
- end
-
- shared_examples 'deleting the todo' do
- before do
- within first('.todo') do
- click_link 'Done'
- end
- end
-
- it 'is marked as done-reversible in the list' do
- expect(page).to have_selector('.todos-list .todo.todo-pending.done-reversible')
- end
-
- it 'shows Undo button' do
- expect(page).to have_selector('.js-undo-todo', visible: true)
- expect(page).to have_selector('.js-done-todo', visible: false)
- end
-
- it 'updates todo count' do
- expect(page).to have_content 'To do 0'
- expect(page).to have_content 'Done 1'
- end
-
- it 'has not "All done" message' do
- expect(page).not_to have_selector('.todos-all-done')
- end
- end
-
- shared_examples 'deleting and restoring the todo' do
- before do
- within first('.todo') do
- click_link 'Done'
- wait_for_requests
- click_link 'Undo'
- end
- end
-
- it 'is marked back as pending in the list' do
- expect(page).not_to have_selector('.todos-list .todo.todo-pending.done-reversible')
- expect(page).to have_selector('.todos-list .todo.todo-pending')
- end
-
- it 'shows Done button' do
- expect(page).to have_selector('.js-undo-todo', visible: false)
- expect(page).to have_selector('.js-done-todo', visible: true)
- end
-
- it 'updates todo count' do
- expect(page).to have_content 'To do 1'
- expect(page).to have_content 'Done 0'
- end
- end
-
- it_behaves_like 'deleting the todo'
- it_behaves_like 'deleting and restoring the todo'
-
- context 'todo is stale on the page' do
- before do
- todos = TodosFinder.new(user, state: :pending).execute
- TodoService.new.mark_todos_as_done(todos, user)
- end
-
- it_behaves_like 'deleting the todo'
- it_behaves_like 'deleting and restoring the todo'
- end
- end
-
- context 'User created todos for themself' do
- before do
- gitlab_sign_in(user)
- end
-
- context 'issue assigned todo' do
- before do
- create(:todo, :assigned, user: user, project: project, target: issue, author: user)
- visit dashboard_todos_path
- end
-
- it 'shows issue assigned to yourself message' do
- page.within('.js-todos-all') do
- expect(page).to have_content("You assigned issue #{issue.to_reference(full: true)} to yourself")
- end
- end
- end
-
- context 'marked todo' do
- before do
- create(:todo, :marked, user: user, project: project, target: issue, author: user)
- visit dashboard_todos_path
- end
-
- it 'shows you added a todo message' do
- page.within('.js-todos-all') do
- expect(page).to have_content("You added a todo for issue #{issue.to_reference(full: true)}")
- expect(page).not_to have_content('to yourself')
- end
- end
- end
-
- context 'mentioned todo' do
- before do
- create(:todo, :mentioned, user: user, project: project, target: issue, author: user)
- visit dashboard_todos_path
- end
-
- it 'shows you mentioned yourself message' do
- page.within('.js-todos-all') do
- expect(page).to have_content("You mentioned yourself on issue #{issue.to_reference(full: true)}")
- expect(page).not_to have_content('to yourself')
- end
- end
- end
-
- context 'directly_addressed todo' do
- before do
- create(:todo, :directly_addressed, user: user, project: project, target: issue, author: user)
- visit dashboard_todos_path
- end
-
- it 'shows you directly addressed yourself message' do
- page.within('.js-todos-all') do
- expect(page).to have_content("You directly addressed yourself on issue #{issue.to_reference(full: true)}")
- expect(page).not_to have_content('to yourself')
- end
- end
- end
-
- context 'approval todo' do
- let(:merge_request) { create(:merge_request) }
-
- before do
- create(:todo, :approval_required, user: user, project: project, target: merge_request, author: user)
- visit dashboard_todos_path
- end
-
- it 'shows you set yourself as an approver message' do
- page.within('.js-todos-all') do
- expect(page).to have_content("You set yourself as an approver for merge request #{merge_request.to_reference(full: true)}")
- expect(page).not_to have_content('to yourself')
- end
- end
- end
- end
-
- context 'User has done todos', js: true do
- before do
- create(:todo, :mentioned, :done, user: user, project: project, target: issue, author: author)
- gitlab_sign_in(user)
- visit dashboard_todos_path(state: :done)
- end
-
- it 'has the done todo present' do
- expect(page).to have_selector('.todos-list .todo.todo-done', count: 1)
- end
-
- describe 'restoring the todo' do
- before do
- within first('.todo') do
- click_link 'Add todo'
- end
- end
-
- it 'is removed from the list' do
- expect(page).not_to have_selector('.todos-list .todo.todo-done')
- end
-
- it 'updates todo count' do
- expect(page).to have_content 'To do 1'
- expect(page).to have_content 'Done 0'
- end
- end
- end
-
- context 'User has Todos with labels spanning multiple projects' do
- before do
- label1 = create(:label, project: project)
- note1 = create(:note_on_issue, note: "Hello #{label1.to_reference(format: :name)}", noteable_id: issue.id, noteable_type: 'Issue', project: issue.project)
- create(:todo, :mentioned, project: project, target: issue, user: user, note_id: note1.id)
-
- project2 = create(:project, visibility_level: Gitlab::VisibilityLevel::PUBLIC)
- label2 = create(:label, project: project2)
- issue2 = create(:issue, project: project2)
- note2 = create(:note_on_issue, note: "Test #{label2.to_reference(format: :name)}", noteable_id: issue2.id, noteable_type: 'Issue', project: project2)
- create(:todo, :mentioned, project: project2, target: issue2, user: user, note_id: note2.id)
-
- gitlab_sign_in(user)
- visit dashboard_todos_path
- end
-
- it 'shows page with two Todos' do
- expect(page).to have_selector('.todos-list .todo', count: 2)
- end
- end
-
- context 'User has multiple pages of Todos' do
- before do
- allow(Todo).to receive(:default_per_page).and_return(1)
-
- # Create just enough records to cause us to paginate
- create_list(:todo, 2, :mentioned, user: user, project: project, target: issue, author: author)
-
- gitlab_sign_in(user)
- end
-
- it 'is paginated' do
- visit dashboard_todos_path
-
- expect(page).to have_selector('.gl-pagination')
- end
-
- it 'is has the right number of pages' do
- visit dashboard_todos_path
-
- expect(page).to have_selector('.gl-pagination .page', count: 2)
- end
-
- describe 'mark all as done', js: true do
- before do
- visit dashboard_todos_path
- find('.js-todos-mark-all').trigger('click')
- end
-
- it 'shows "All done" message!' do
- expect(page).to have_content 'To do 0'
- expect(page).to have_content "You're all done!"
- expect(page).not_to have_selector('.gl-pagination')
- end
-
- it 'shows "Undo mark all as done" button' do
- expect(page).to have_selector('.js-todos-mark-all', visible: false)
- expect(page).to have_selector('.js-todos-undo-all', visible: true)
- end
- end
-
- describe 'undo mark all as done', js: true do
- before do
- visit dashboard_todos_path
- end
-
- it 'shows the restored todo list' do
- mark_all_and_undo
-
- expect(page).to have_selector('.todos-list .todo', count: 1)
- expect(page).to have_selector('.gl-pagination')
- expect(page).not_to have_content "You're all done!"
- end
-
- it 'updates todo count' do
- mark_all_and_undo
-
- expect(page).to have_content 'To do 2'
- expect(page).to have_content 'Done 0'
- end
-
- it 'shows "Mark all as done" button' do
- mark_all_and_undo
-
- expect(page).to have_selector('.js-todos-mark-all', visible: true)
- expect(page).to have_selector('.js-todos-undo-all', visible: false)
- end
-
- context 'User has deleted a todo' do
- before do
- within first('.todo') do
- click_link 'Done'
- end
- end
-
- it 'shows the restored todo list with the deleted todo' do
- mark_all_and_undo
-
- expect(page).to have_selector('.todos-list .todo.todo-pending', count: 1)
- end
- end
-
- def mark_all_and_undo
- find('.js-todos-mark-all').trigger('click')
- wait_for_requests
- find('.js-todos-undo-all').trigger('click')
- wait_for_requests
- end
- end
- end
-
- context 'User has a Todo in a project pending deletion' do
- before do
- deleted_project = create(:project, visibility_level: Gitlab::VisibilityLevel::PUBLIC, pending_delete: true)
- create(:todo, :mentioned, user: user, project: deleted_project, target: issue, author: author)
- create(:todo, :mentioned, user: user, project: deleted_project, target: issue, author: author, state: :done)
- gitlab_sign_in(user)
- visit dashboard_todos_path
- end
-
- it 'shows "All done" message' do
- within('.todos-count') { expect(page).to have_content '0' }
- expect(page).to have_content 'To do 0'
- expect(page).to have_content 'Done 0'
- expect(page).to have_selector('.todos-all-done', count: 1)
- end
- end
-
- context 'User has a Build Failed todo' do
- let!(:todo) { create(:todo, :build_failed, user: user, project: project, author: author) }
-
- before do
- gitlab_sign_in user
- visit dashboard_todos_path
- end
-
- it 'shows the todo' do
- expect(page).to have_content 'The build failed for merge request'
- end
-
- it 'links to the pipelines for the merge request' do
- href = pipelines_namespace_project_merge_request_path(project.namespace, project, todo.target)
-
- expect(page).to have_link "merge request #{todo.target.to_reference(full: true)}", href
- end
- end
- end
-end
diff --git a/spec/helpers/button_helper_spec.rb b/spec/helpers/button_helper_spec.rb
new file mode 100644
index 00000000000..661327d4432
--- /dev/null
+++ b/spec/helpers/button_helper_spec.rb
@@ -0,0 +1,65 @@
+require 'spec_helper'
+
+describe ButtonHelper do
+ describe 'http_clone_button' do
+ let(:user) { create(:user) }
+ let(:project) { create(:project) }
+ let(:has_tooltip_class) { 'has-tooltip' }
+
+ def element
+ element = helper.http_clone_button(project)
+
+ Nokogiri::HTML::DocumentFragment.parse(element).first_element_child
+ end
+
+ before do
+ allow(helper).to receive(:current_user).and_return(user)
+ end
+
+ context 'with internal auth enabled' do
+ context 'when user has a password' do
+ it 'shows no tooltip' do
+ expect(element.attr('class')).not_to include(has_tooltip_class)
+ end
+ end
+
+ context 'when user has password automatically set' do
+ let(:user) { create(:user, password_automatically_set: true) }
+
+ it 'shows a password tooltip' do
+ expect(element.attr('class')).to include(has_tooltip_class)
+ expect(element.attr('data-title')).to eq('Set a password on your account to pull or push via HTTP.')
+ end
+ end
+ end
+
+ context 'with internal auth disabled' do
+ before do
+ stub_application_setting(signin_enabled?: false)
+ end
+
+ context 'when user has no personal access tokens' do
+ it 'has a personal access token tooltip ' do
+ expect(element.attr('class')).to include(has_tooltip_class)
+ expect(element.attr('data-title')).to eq('Create a personal access token on your account to pull or push via HTTP.')
+ end
+ end
+
+ context 'when user has a personal access token' do
+ it 'shows no tooltip' do
+ create(:personal_access_token, user: user)
+
+ expect(element.attr('class')).not_to include(has_tooltip_class)
+ end
+ end
+ end
+
+ context 'when user is ldap user' do
+ let(:user) { create(:omniauth_user, password_automatically_set: true) }
+
+ it 'shows no tooltip' do
+ expect(element.attr('class')).not_to include(has_tooltip_class)
+ end
+ end
+ end
+end
diff --git a/spec/helpers/groups_helper_spec.rb b/spec/helpers/groups_helper_spec.rb
index 84a60ce13fc..8da22dc78fa 100644
--- a/spec/helpers/groups_helper_spec.rb
+++ b/spec/helpers/groups_helper_spec.rb
@@ -84,7 +84,7 @@ describe GroupsHelper do
end
end
- describe 'group_title' do
+ describe 'group_title', :nested_groups do
let(:group) { create(:group) }
let(:nested_group) { create(:group, parent: group) }
let(:deep_nested_group) { create(:group, parent: nested_group) }
diff --git a/spec/helpers/projects_helper_spec.rb b/spec/helpers/projects_helper_spec.rb
index 9a4086725d2..487d9800707 100644
--- a/spec/helpers/projects_helper_spec.rb
+++ b/spec/helpers/projects_helper_spec.rb
@@ -115,6 +115,82 @@ describe ProjectsHelper do
end
end
+ describe '#show_no_ssh_key_message?' do
+ let(:user) { create(:user) }
+
+ before do
+ allow(helper).to receive(:current_user).and_return(user)
+ end
+
+ context 'user has no keys' do
+ it 'returns true' do
+ expect(helper.show_no_ssh_key_message?).to be_truthy
+ end
+ end
+
+ context 'user has an ssh key' do
+ it 'returns false' do
+ create(:personal_key, user: user)
+
+ expect(helper.show_no_ssh_key_message?).to be_falsey
+ end
+ end
+ end
+
+ describe '#show_no_password_message?' do
+ let(:user) { create(:user) }
+
+ before do
+ allow(helper).to receive(:current_user).and_return(user)
+ end
+
+ context 'user has password set' do
+ it 'returns false' do
+ expect(helper.show_no_password_message?).to be_falsey
+ end
+ end
+
+ context 'user requires a password' do
+ let(:user) { create(:user, password_automatically_set: true) }
+
+ it 'returns true' do
+ expect(helper.show_no_password_message?).to be_truthy
+ end
+ end
+
+ context 'user requires a personal access token' do
+ it 'returns true' do
+ stub_application_setting(signin_enabled?: false)
+
+ expect(helper.show_no_password_message?).to be_truthy
+ end
+ end
+ end
+
+ describe '#link_to_set_password' do
+ before do
+ allow(helper).to receive(:current_user).and_return(user)
+ end
+
+ context 'user requires a password' do
+ let(:user) { create(:user, password_automatically_set: true) }
+
+ it 'returns link to set a password' do
+ expect(helper.link_to_set_password).to match %r{<a href="#{edit_profile_password_path}">set a password</a>}
+ end
+ end
+
+ context 'user requires a personal access token' do
+ let(:user) { create(:user) }
+
+ it 'returns link to create a personal access token' do
+ stub_application_setting(signin_enabled?: false)
+
+ expect(helper.link_to_set_password).to match %r{<a href="#{profile_personal_access_tokens_path}">create a personal access token</a>}
+ end
+ end
+ end
+
describe 'link_to_member' do
let(:group) { create(:group) }
let(:project) { create(:empty_project, group: group) }
diff --git a/spec/javascripts/behaviors/quick_submit_spec.js b/spec/javascripts/behaviors/quick_submit_spec.js
index f56b99f8a16..6dc48f9a293 100644
--- a/spec/javascripts/behaviors/quick_submit_spec.js
+++ b/spec/javascripts/behaviors/quick_submit_spec.js
@@ -40,16 +40,29 @@ import '~/behaviors/quick_submit';
it('disables input of type submit', function() {
const submitButton = $('.js-quick-submit input[type=submit]');
this.textarea.trigger(keydownEvent());
+
expect(submitButton).toBeDisabled();
});
it('disables button of type submit', function() {
- // button doesn't exist in fixture, add it manually
- const submitButton = $('<button type="submit">Submit it</button>');
- submitButton.insertAfter(this.textarea);
-
+ const submitButton = $('.js-quick-submit input[type=submit]');
this.textarea.trigger(keydownEvent());
+
expect(submitButton).toBeDisabled();
});
+ it('only clicks one submit', function() {
+ const existingSubmit = $('.js-quick-submit input[type=submit]');
+ // Add an extra submit button
+ const newSubmit = $('<button type="submit">Submit it</button>');
+ newSubmit.insertAfter(this.textarea);
+
+ const oldClick = spyOnEvent(existingSubmit, 'click');
+ const newClick = spyOnEvent(newSubmit, 'click');
+
+ this.textarea.trigger(keydownEvent());
+
+ expect(oldClick).not.toHaveBeenTriggered();
+ expect(newClick).toHaveBeenTriggered();
+ });
// We cannot stub `navigator.userAgent` for CI's `rake karma` task, so we'll
// only run the tests that apply to the current platform
if (navigator.userAgent.match(/Macintosh/)) {
diff --git a/spec/javascripts/environments/environment_actions_spec.js b/spec/javascripts/environments/environment_actions_spec.js
index 596d812c724..ea40a1fcd4b 100644
--- a/spec/javascripts/environments/environment_actions_spec.js
+++ b/spec/javascripts/environments/environment_actions_spec.js
@@ -32,9 +32,16 @@ describe('Actions Component', () => {
}).$mount();
});
+ describe('computed', () => {
+ it('title', () => {
+ expect(component.title).toEqual('Deploy to...');
+ });
+ });
+
it('should render a dropdown button with icon and title attribute', () => {
expect(component.$el.querySelector('.fa-caret-down')).toBeDefined();
- expect(component.$el.querySelector('.dropdown-new').getAttribute('title')).toEqual('Deploy to...');
+ expect(component.$el.querySelector('.dropdown-new').getAttribute('data-original-title')).toEqual('Deploy to...');
+ expect(component.$el.querySelector('.dropdown-new').getAttribute('aria-label')).toEqual('Deploy to...');
});
it('should render a dropdown with the provided list of actions', () => {
diff --git a/spec/javascripts/environments/environment_monitoring_spec.js b/spec/javascripts/environments/environment_monitoring_spec.js
index 0f3dba66230..f8d8223967a 100644
--- a/spec/javascripts/environments/environment_monitoring_spec.js
+++ b/spec/javascripts/environments/environment_monitoring_spec.js
@@ -3,21 +3,30 @@ import monitoringComp from '~/environments/components/environment_monitoring.vue
describe('Monitoring Component', () => {
let MonitoringComponent;
+ let component;
+
+ const monitoringUrl = 'https://gitlab.com';
beforeEach(() => {
MonitoringComponent = Vue.extend(monitoringComp);
- });
- it('should render a link to environment monitoring page', () => {
- const monitoringUrl = 'https://gitlab.com';
- const component = new MonitoringComponent({
+ component = new MonitoringComponent({
propsData: {
monitoringUrl,
},
}).$mount();
+ });
+ describe('computed', () => {
+ it('title', () => {
+ expect(component.title).toEqual('Monitoring');
+ });
+ });
+
+ it('should render a link to environment monitoring page', () => {
expect(component.$el.getAttribute('href')).toEqual(monitoringUrl);
expect(component.$el.querySelector('.fa-area-chart')).toBeDefined();
- expect(component.$el.getAttribute('title')).toEqual('Monitoring');
+ expect(component.$el.getAttribute('data-original-title')).toEqual('Monitoring');
+ expect(component.$el.getAttribute('aria-label')).toEqual('Monitoring');
});
});
diff --git a/spec/javascripts/environments/environment_stop_spec.js b/spec/javascripts/environments/environment_stop_spec.js
index 8131f1e5b11..3f95faf466a 100644
--- a/spec/javascripts/environments/environment_stop_spec.js
+++ b/spec/javascripts/environments/environment_stop_spec.js
@@ -17,8 +17,15 @@ describe('Stop Component', () => {
}).$mount();
});
+ describe('computed', () => {
+ it('title', () => {
+ expect(component.title).toEqual('Stop');
+ });
+ });
+
it('should render a button to stop the environment', () => {
expect(component.$el.tagName).toEqual('BUTTON');
- expect(component.$el.getAttribute('title')).toEqual('Stop');
+ expect(component.$el.getAttribute('data-original-title')).toEqual('Stop');
+ expect(component.$el.getAttribute('aria-label')).toEqual('Stop');
});
});
diff --git a/spec/javascripts/environments/environment_terminal_button_spec.js b/spec/javascripts/environments/environment_terminal_button_spec.js
index 858472af4b6..f1576b19d1b 100644
--- a/spec/javascripts/environments/environment_terminal_button_spec.js
+++ b/spec/javascripts/environments/environment_terminal_button_spec.js
@@ -16,9 +16,16 @@ describe('Stop Component', () => {
}).$mount();
});
+ describe('computed', () => {
+ it('title', () => {
+ expect(component.title).toEqual('Terminal');
+ });
+ });
+
it('should render a link to open a web terminal with the provided path', () => {
expect(component.$el.tagName).toEqual('A');
- expect(component.$el.getAttribute('title')).toEqual('Terminal');
+ expect(component.$el.getAttribute('data-original-title')).toEqual('Terminal');
+ expect(component.$el.getAttribute('aria-label')).toEqual('Terminal');
expect(component.$el.getAttribute('href')).toEqual(terminalPath);
});
});
diff --git a/spec/javascripts/issue_show/components/fields/description_spec.js b/spec/javascripts/issue_show/components/fields/description_spec.js
index f5b35b1e8b0..df8189d9290 100644
--- a/spec/javascripts/issue_show/components/fields/description_spec.js
+++ b/spec/javascripts/issue_show/components/fields/description_spec.js
@@ -1,6 +1,8 @@
import Vue from 'vue';
+import eventHub from '~/issue_show/event_hub';
import Store from '~/issue_show/stores';
import descriptionField from '~/issue_show/components/fields/description.vue';
+import { keyboardDownEvent } from '../../helpers';
describe('Description field component', () => {
let vm;
@@ -18,6 +20,8 @@ describe('Description field component', () => {
document.body.appendChild(el);
+ spyOn(eventHub, '$emit');
+
vm = new Component({
el,
propsData: {
@@ -53,4 +57,20 @@ describe('Description field component', () => {
document.activeElement,
).toBe(vm.$refs.textarea);
});
+
+ it('triggers update with meta+enter', () => {
+ vm.$el.querySelector('.md-area textarea').dispatchEvent(keyboardDownEvent(13, true));
+
+ expect(
+ eventHub.$emit,
+ ).toHaveBeenCalled();
+ });
+
+ it('triggers update with ctrl+enter', () => {
+ vm.$el.querySelector('.md-area textarea').dispatchEvent(keyboardDownEvent(13, false, true));
+
+ expect(
+ eventHub.$emit,
+ ).toHaveBeenCalled();
+ });
});
diff --git a/spec/javascripts/issue_show/components/fields/title_spec.js b/spec/javascripts/issue_show/components/fields/title_spec.js
index 53ae038a6a2..a03b462689f 100644
--- a/spec/javascripts/issue_show/components/fields/title_spec.js
+++ b/spec/javascripts/issue_show/components/fields/title_spec.js
@@ -1,6 +1,8 @@
import Vue from 'vue';
+import eventHub from '~/issue_show/event_hub';
import Store from '~/issue_show/stores';
import titleField from '~/issue_show/components/fields/title.vue';
+import { keyboardDownEvent } from '../../helpers';
describe('Title field component', () => {
let vm;
@@ -15,6 +17,8 @@ describe('Title field component', () => {
});
store.formState.title = 'test';
+ spyOn(eventHub, '$emit');
+
vm = new Component({
propsData: {
formState: store.formState,
@@ -27,4 +31,20 @@ describe('Title field component', () => {
vm.$el.querySelector('.form-control').value,
).toBe('test');
});
+
+ it('triggers update with meta+enter', () => {
+ vm.$el.querySelector('.form-control').dispatchEvent(keyboardDownEvent(13, true));
+
+ expect(
+ eventHub.$emit,
+ ).toHaveBeenCalled();
+ });
+
+ it('triggers update with ctrl+enter', () => {
+ vm.$el.querySelector('.form-control').dispatchEvent(keyboardDownEvent(13, false, true));
+
+ expect(
+ eventHub.$emit,
+ ).toHaveBeenCalled();
+ });
});
diff --git a/spec/javascripts/issue_show/helpers.js b/spec/javascripts/issue_show/helpers.js
new file mode 100644
index 00000000000..5d2ced98ae4
--- /dev/null
+++ b/spec/javascripts/issue_show/helpers.js
@@ -0,0 +1,10 @@
+// eslint-disable-next-line import/prefer-default-export
+export const keyboardDownEvent = (code, metaKey = false, ctrlKey = false) => {
+ const e = new CustomEvent('keydown');
+
+ e.keyCode = code;
+ e.metaKey = metaKey;
+ e.ctrlKey = ctrlKey;
+
+ return e;
+};
diff --git a/spec/javascripts/pipeline_schedules/interval_pattern_input_spec.js b/spec/javascripts/pipeline_schedules/interval_pattern_input_spec.js
index 56c57d94798..040d14efed2 100644
--- a/spec/javascripts/pipeline_schedules/interval_pattern_input_spec.js
+++ b/spec/javascripts/pipeline_schedules/interval_pattern_input_spec.js
@@ -1,5 +1,8 @@
import Vue from 'vue';
-import IntervalPatternInput from '~/pipeline_schedules/components/interval_pattern_input';
+import Translate from '~/vue_shared/translate';
+import IntervalPatternInput from '~/pipeline_schedules/components/interval_pattern_input.vue';
+
+Vue.use(Translate);
const IntervalPatternInputComponent = Vue.extend(IntervalPatternInput);
const inputNameAttribute = 'schedule[cron]';
diff --git a/spec/javascripts/pipelines/stage_spec.js b/spec/javascripts/pipelines/stage_spec.js
index a4f32a1faed..1b96b2e3d51 100644
--- a/spec/javascripts/pipelines/stage_spec.js
+++ b/spec/javascripts/pipelines/stage_spec.js
@@ -83,4 +83,47 @@ describe('Pipelines stage component', () => {
}, 0);
});
});
+
+ describe('update endpoint correctly', () => {
+ const updatedInterceptor = (request, next) => {
+ if (request.url === 'bar') {
+ next(request.respondWith(JSON.stringify({ html: 'this is the updated content' }), {
+ status: 200,
+ }));
+ }
+ next();
+ };
+
+ beforeEach(() => {
+ Vue.http.interceptors.push(updatedInterceptor);
+ });
+
+ afterEach(() => {
+ Vue.http.interceptors = _.without(
+ Vue.http.interceptors, updatedInterceptor,
+ );
+ });
+
+ it('should update the stage to request the new endpoint provided', (done) => {
+ component.stage = {
+ status: {
+ group: 'running',
+ icon: 'running',
+ title: 'running',
+ },
+ dropdown_path: 'bar',
+ };
+
+ Vue.nextTick(() => {
+ component.$el.querySelector('button').click();
+
+ setTimeout(() => {
+ expect(
+ component.$el.querySelector('.js-builds-dropdown-container ul').textContent.trim(),
+ ).toEqual('this is the updated content');
+ done();
+ });
+ });
+ });
+ });
});
diff --git a/spec/javascripts/sidebar/assignee_title_spec.js b/spec/javascripts/sidebar/assignee_title_spec.js
index 5b5b1bf4140..ac93f918ce4 100644
--- a/spec/javascripts/sidebar/assignee_title_spec.js
+++ b/spec/javascripts/sidebar/assignee_title_spec.js
@@ -33,6 +33,31 @@ describe('AssigneeTitle component', () => {
});
});
+ describe('gutter toggle', () => {
+ it('does not show toggle by default', () => {
+ component = new AssigneeTitleComponent({
+ propsData: {
+ numberOfAssignees: 2,
+ editable: false,
+ },
+ }).$mount();
+
+ expect(component.$el.querySelector('.gutter-toggle')).toBeNull();
+ });
+
+ it('shows toggle when showToggle is true', () => {
+ component = new AssigneeTitleComponent({
+ propsData: {
+ numberOfAssignees: 2,
+ editable: false,
+ showToggle: true,
+ },
+ }).$mount();
+
+ expect(component.$el.querySelector('.gutter-toggle')).toEqual(jasmine.any(Object));
+ });
+ });
+
it('does not render spinner by default', () => {
component = new AssigneeTitleComponent({
propsData: {
diff --git a/spec/javascripts/test_bundle.js b/spec/javascripts/test_bundle.js
index 075b72f35b2..d4e134583c7 100644
--- a/spec/javascripts/test_bundle.js
+++ b/spec/javascripts/test_bundle.js
@@ -7,6 +7,10 @@ import '~/commons';
import Vue from 'vue';
import VueResource from 'vue-resource';
+const isHeadlessChrome = /\bHeadlessChrome\//.test(navigator.userAgent);
+Vue.config.devtools = !isHeadlessChrome;
+Vue.config.productionTip = false;
+
Vue.use(VueResource);
// enable test fixtures
diff --git a/spec/javascripts/vue_mr_widget/components/mr_widget_pipeline_spec.js b/spec/javascripts/vue_mr_widget/components/mr_widget_pipeline_spec.js
index 647b59520f8..4b6f171c8d6 100644
--- a/spec/javascripts/vue_mr_widget/components/mr_widget_pipeline_spec.js
+++ b/spec/javascripts/vue_mr_widget/components/mr_widget_pipeline_spec.js
@@ -76,6 +76,28 @@ describe('MRWidgetPipeline', () => {
el = vm.$el;
});
+ afterEach(() => {
+ vm.$destroy();
+ });
+
+ describe('without a pipeline', () => {
+ beforeEach(() => {
+ vm.mr = { pipeline: null };
+ });
+
+ it('should render message with spinner', (done) => {
+ Vue.nextTick()
+ .then(() => {
+ expect(el.querySelector('.pipeline-id')).toBe(null);
+ expect(el.innerText.trim()).toBe('Waiting for pipeline...');
+ expect(el.querySelectorAll('i.fa.fa-spinner.fa-spin').length).toBe(1);
+ done();
+ })
+ .then(done)
+ .catch(done.fail);
+ });
+ });
+
it('should render template elements correctly', () => {
expect(el.classList.contains('mr-widget-heading')).toBeTruthy();
expect(el.querySelectorAll('.ci-status-icon.ci-status-icon-success').length).toEqual(1);
@@ -93,39 +115,47 @@ describe('MRWidgetPipeline', () => {
it('should list single stage', (done) => {
pipeline.details.stages.splice(0, 1);
- Vue.nextTick(() => {
- expect(el.querySelectorAll('.stage-container button').length).toEqual(1);
- expect(el.innerText).toContain('with stage');
- done();
- });
+ Vue.nextTick()
+ .then(() => {
+ expect(el.querySelectorAll('.stage-container button').length).toEqual(1);
+ expect(el.innerText).toContain('with stage');
+ })
+ .then(done)
+ .catch(done.fail);
});
it('should not have stages when there is no stage', (done) => {
vm.mr.pipeline.details.stages = [];
- Vue.nextTick(() => {
- expect(el.querySelectorAll('.stage-container button').length).toEqual(0);
- done();
- });
+ Vue.nextTick()
+ .then(() => {
+ expect(el.querySelectorAll('.stage-container button').length).toEqual(0);
+ })
+ .then(done)
+ .catch(done.fail);
});
it('should not have coverage text when pipeline has no coverage info', (done) => {
vm.mr.pipeline.coverage = null;
- Vue.nextTick(() => {
- expect(el.querySelector('.js-mr-coverage')).toEqual(null);
- done();
- });
+ Vue.nextTick()
+ .then(() => {
+ expect(el.querySelector('.js-mr-coverage')).toEqual(null);
+ })
+ .then(done)
+ .catch(done.fail);
});
it('should show CI error when there is a CI error', (done) => {
vm.mr.ciStatus = null;
- Vue.nextTick(() => {
- expect(el.querySelectorAll('.js-ci-error').length).toEqual(1);
- expect(el.innerText).toContain('Could not connect to the CI server');
- done();
- });
+ Vue.nextTick()
+ .then(() => {
+ expect(el.querySelectorAll('.js-ci-error').length).toEqual(1);
+ expect(el.innerText).toContain('Could not connect to the CI server');
+ })
+ .then(done)
+ .catch(done.fail);
});
});
});
diff --git a/spec/javascripts/vue_shared/components/markdown/field_spec.js b/spec/javascripts/vue_shared/components/markdown/field_spec.js
index 4bbaff561fc..291e19c9f3c 100644
--- a/spec/javascripts/vue_shared/components/markdown/field_spec.js
+++ b/spec/javascripts/vue_shared/components/markdown/field_spec.js
@@ -4,47 +4,33 @@ import fieldComponent from '~/vue_shared/components/markdown/field.vue';
describe('Markdown field component', () => {
let vm;
- beforeEach(() => {
+ beforeEach((done) => {
vm = new Vue({
- render(createElement) {
- return createElement(
- fieldComponent,
- {
- props: {
- markdownPreviewUrl: '/preview',
- markdownDocs: '/docs',
- },
- },
- [
- createElement('textarea', {
- slot: 'textarea',
- }),
- ],
- );
+ data() {
+ return {
+ text: 'testing\n123',
+ };
},
- });
- });
-
- it('creates a new instance of GL form', (done) => {
- spyOn(gl, 'GLForm');
- vm.$mount();
-
- Vue.nextTick(() => {
- expect(
- gl.GLForm,
- ).toHaveBeenCalled();
-
- done();
- });
+ components: {
+ fieldComponent,
+ },
+ template: `
+ <field-component
+ marodown-preview-url="/preview"
+ markdown-docs="/docs"
+ >
+ <textarea
+ slot="textarea"
+ v-model="text">
+ </textarea>
+ </field-component>
+ `,
+ }).$mount();
+
+ Vue.nextTick(done);
});
describe('mounted', () => {
- beforeEach((done) => {
- vm.$mount();
-
- Vue.nextTick(done);
- });
-
it('renders textarea inside backdrop', () => {
expect(
vm.$el.querySelector('.zen-backdrop textarea'),
@@ -117,5 +103,52 @@ describe('Markdown field component', () => {
});
});
});
+
+ describe('markdown buttons', () => {
+ it('converts single words', (done) => {
+ const textarea = vm.$el.querySelector('textarea');
+
+ textarea.setSelectionRange(0, 7);
+ vm.$el.querySelector('.js-md').click();
+
+ Vue.nextTick(() => {
+ expect(
+ textarea.value,
+ ).toContain('**testing**');
+
+ done();
+ });
+ });
+
+ it('converts a line', (done) => {
+ const textarea = vm.$el.querySelector('textarea');
+
+ textarea.setSelectionRange(0, 0);
+ vm.$el.querySelectorAll('.js-md')[4].click();
+
+ Vue.nextTick(() => {
+ expect(
+ textarea.value,
+ ).toContain('* testing');
+
+ done();
+ });
+ });
+
+ it('converts multiple lines', (done) => {
+ const textarea = vm.$el.querySelector('textarea');
+
+ textarea.setSelectionRange(0, 50);
+ vm.$el.querySelectorAll('.js-md')[4].click();
+
+ Vue.nextTick(() => {
+ expect(
+ textarea.value,
+ ).toContain('* testing\n* 123');
+
+ done();
+ });
+ });
+ });
});
});
diff --git a/spec/javascripts/vue_shared/components/time_ago_tooltip_spec.js b/spec/javascripts/vue_shared/components/time_ago_tooltip_spec.js
index f3b4adc0b70..b4c1f70ed1e 100644
--- a/spec/javascripts/vue_shared/components/time_ago_tooltip_spec.js
+++ b/spec/javascripts/vue_shared/components/time_ago_tooltip_spec.js
@@ -22,7 +22,6 @@ describe('Time ago with tooltip component', () => {
}).$mount();
expect(vm.$el.tagName).toEqual('TIME');
- expect(vm.$el.classList.contains('js-vue-timeago')).toEqual(true);
expect(
vm.$el.getAttribute('data-original-title'),
).toEqual(gl.utils.formatDate('2017-05-08T14:57:39.781Z'));
diff --git a/spec/javascripts/vue_shared/directives/tooltip_spec.js b/spec/javascripts/vue_shared/directives/tooltip_spec.js
new file mode 100644
index 00000000000..b1b3071527b
--- /dev/null
+++ b/spec/javascripts/vue_shared/directives/tooltip_spec.js
@@ -0,0 +1,63 @@
+import Vue from 'vue';
+import tooltip from '~/vue_shared/directives/tooltip';
+
+describe('Tooltip directive', () => {
+ let vm;
+
+ afterEach(() => {
+ if (vm) {
+ vm.$destroy();
+ }
+ });
+
+ describe('with a single tooltip', () => {
+ beforeEach(() => {
+ const SomeComponent = Vue.extend({
+ directives: {
+ tooltip,
+ },
+ template: `
+ <div
+ v-tooltip
+ title="foo">
+ </div>
+ `,
+ });
+
+ vm = new SomeComponent().$mount();
+ });
+
+ it('should have tooltip plugin applied', () => {
+ expect($(vm.$el).data('bs.tooltip')).toBeDefined();
+ });
+ });
+
+ describe('with multiple tooltips', () => {
+ beforeEach(() => {
+ const SomeComponent = Vue.extend({
+ directives: {
+ tooltip,
+ },
+ template: `
+ <div>
+ <div
+ v-tooltip
+ class="js-look-for-tooltip"
+ title="foo">
+ </div>
+ <div
+ v-tooltip
+ title="bar">
+ </div>
+ </div>
+ `,
+ });
+
+ vm = new SomeComponent().$mount();
+ });
+
+ it('should have tooltip plugin applied to all instances', () => {
+ expect($(vm.$el).find('.js-look-for-tooltip').data('bs.tooltip')).toBeDefined();
+ });
+ });
+});
diff --git a/spec/lib/ci/charts_spec.rb b/spec/lib/ci/charts_spec.rb
index fb6cc398307..51cbfd2a848 100644
--- a/spec/lib/ci/charts_spec.rb
+++ b/spec/lib/ci/charts_spec.rb
@@ -1,21 +1,21 @@
require 'spec_helper'
describe Ci::Charts, lib: true do
- context "build_times" do
+ context "pipeline_times" do
let(:project) { create(:empty_project) }
- let(:chart) { Ci::Charts::BuildTime.new(project) }
+ let(:chart) { Ci::Charts::PipelineTime.new(project) }
- subject { chart.build_times }
+ subject { chart.pipeline_times }
before do
create(:ci_empty_pipeline, project: project, duration: 120)
end
- it 'returns build times in minutes' do
+ it 'returns pipeline times in minutes' do
is_expected.to contain_exactly(2)
end
- it 'handles nil build times' do
+ it 'handles nil pipeline times' do
create(:ci_empty_pipeline, project: project, duration: nil)
is_expected.to contain_exactly(2, 0)
diff --git a/spec/lib/gitlab/database_spec.rb b/spec/lib/gitlab/database_spec.rb
index 5e6206b96c7..cbf6c35356e 100644
--- a/spec/lib/gitlab/database_spec.rb
+++ b/spec/lib/gitlab/database_spec.rb
@@ -176,6 +176,10 @@ describe Gitlab::Database, lib: true do
described_class.bulk_insert('test', rows)
end
+
+ it 'handles non-UTF-8 data' do
+ expect { described_class.bulk_insert('test', [{ a: "\255" }]) }.not_to raise_error
+ end
end
describe '.create_connection_pool' do
diff --git a/spec/lib/gitlab/dependency_linker/requirements_txt_linker_spec.rb b/spec/lib/gitlab/dependency_linker/requirements_txt_linker_spec.rb
index 4da8821726c..7e32770f95d 100644
--- a/spec/lib/gitlab/dependency_linker/requirements_txt_linker_spec.rb
+++ b/spec/lib/gitlab/dependency_linker/requirements_txt_linker_spec.rb
@@ -54,6 +54,8 @@ describe Gitlab::DependencyLinker::RequirementsTxtLinker, lib: true do
Sphinx>=1.3
docutils>=0.7
markupsafe
+ pytest~=3.0
+ foop!=3.0
CONTENT
end
@@ -78,6 +80,8 @@ describe Gitlab::DependencyLinker::RequirementsTxtLinker, lib: true do
expect(subject).to include(link('Sphinx', 'https://pypi.python.org/pypi/Sphinx'))
expect(subject).to include(link('docutils', 'https://pypi.python.org/pypi/docutils'))
expect(subject).to include(link('markupsafe', 'https://pypi.python.org/pypi/markupsafe'))
+ expect(subject).to include(link('pytest', 'https://pypi.python.org/pypi/pytest'))
+ expect(subject).to include(link('foop', 'https://pypi.python.org/pypi/foop'))
end
it 'links URLs' do
diff --git a/spec/lib/gitlab/exclusive_lease_spec.rb b/spec/lib/gitlab/exclusive_lease_spec.rb
index a366d68a146..81bbd70ffb8 100644
--- a/spec/lib/gitlab/exclusive_lease_spec.rb
+++ b/spec/lib/gitlab/exclusive_lease_spec.rb
@@ -19,6 +19,19 @@ describe Gitlab::ExclusiveLease, type: :redis do
end
end
+ describe '#renew' do
+ it 'returns true when we have the existing lease' do
+ lease = described_class.new(unique_key, timeout: 3600)
+ expect(lease.try_obtain).to be_present
+ expect(lease.renew).to be_truthy
+ end
+
+ it 'returns false when we dont have a lease' do
+ lease = described_class.new(unique_key, timeout: 3600)
+ expect(lease.renew).to be_falsey
+ end
+ end
+
describe '#exists?' do
it 'returns true for an existing lease' do
lease = described_class.new(unique_key, timeout: 3600)
diff --git a/spec/lib/gitlab/git/commit_spec.rb b/spec/lib/gitlab/git/commit_spec.rb
index 3e44c577643..f20a14155dc 100644
--- a/spec/lib/gitlab/git/commit_spec.rb
+++ b/spec/lib/gitlab/git/commit_spec.rb
@@ -244,6 +244,33 @@ describe Gitlab::Git::Commit, seed_helper: true do
end
describe '.find_all' do
+ it 'should return a return a collection of commits' do
+ commits = described_class.find_all(repository)
+
+ expect(commits).not_to be_empty
+ expect(commits).to all( be_a_kind_of(Gitlab::Git::Commit) )
+ end
+
+ context 'while applying a sort order based on the `order` option' do
+ it "allows ordering topologically (no parents shown before their children)" do
+ expect_any_instance_of(Rugged::Walker).to receive(:sorting).with(Rugged::SORT_TOPO)
+
+ described_class.find_all(repository, order: :topo)
+ end
+
+ it "allows ordering by date" do
+ expect_any_instance_of(Rugged::Walker).to receive(:sorting).with(Rugged::SORT_DATE | Rugged::SORT_TOPO)
+
+ described_class.find_all(repository, order: :date)
+ end
+
+ it "applies no sorting by default" do
+ expect_any_instance_of(Rugged::Walker).to receive(:sorting).with(Rugged::SORT_NONE)
+
+ described_class.find_all(repository)
+ end
+ end
+
context 'max_count' do
subject do
commits = Gitlab::Git::Commit.find_all(
@@ -281,26 +308,6 @@ describe Gitlab::Git::Commit, seed_helper: true do
it { is_expected.to include(SeedRepo::FirstCommit::ID) }
it { is_expected.not_to include(SeedRepo::LastCommit::ID) }
end
-
- context 'contains feature + max_count' do
- subject do
- commits = Gitlab::Git::Commit.find_all(
- repository,
- contains: 'feature',
- max_count: 7
- )
-
- commits.map { |c| c.id }
- end
-
- it 'has 7 elements' do
- expect(subject.size).to eq(7)
- end
-
- it { is_expected.not_to include(SeedRepo::Commit::PARENT_ID) }
- it { is_expected.not_to include(SeedRepo::Commit::ID) }
- it { is_expected.to include(SeedRepo::BigCommit::ID) }
- end
end
end
diff --git a/spec/lib/gitlab/git/repository_spec.rb b/spec/lib/gitlab/git/repository_spec.rb
index 703b0c2c202..4894b558e03 100644
--- a/spec/lib/gitlab/git/repository_spec.rb
+++ b/spec/lib/gitlab/git/repository_spec.rb
@@ -1101,35 +1101,6 @@ describe Gitlab::Git::Repository, seed_helper: true do
end
end
- describe '#find_commits' do
- it 'should return a return a collection of commits' do
- commits = repository.find_commits
-
- expect(commits).not_to be_empty
- expect(commits).to all( be_a_kind_of(Gitlab::Git::Commit) )
- end
-
- context 'while applying a sort order based on the `order` option' do
- it "allows ordering topologically (no parents shown before their children)" do
- expect_any_instance_of(Rugged::Walker).to receive(:sorting).with(Rugged::SORT_TOPO)
-
- repository.find_commits(order: :topo)
- end
-
- it "allows ordering by date" do
- expect_any_instance_of(Rugged::Walker).to receive(:sorting).with(Rugged::SORT_DATE | Rugged::SORT_TOPO)
-
- repository.find_commits(order: :date)
- end
-
- it "applies no sorting by default" do
- expect_any_instance_of(Rugged::Walker).to receive(:sorting).with(Rugged::SORT_NONE)
-
- repository.find_commits
- end
- end
- end
-
describe '#branches with deleted branch' do
before(:each) do
ref = double()
diff --git a/spec/lib/gitlab/import_export/fork_spec.rb b/spec/lib/gitlab/import_export/fork_spec.rb
index 42f3fc59f04..70796781532 100644
--- a/spec/lib/gitlab/import_export/fork_spec.rb
+++ b/spec/lib/gitlab/import_export/fork_spec.rb
@@ -44,6 +44,8 @@ describe 'forked project import', services: true do
end
it 'can access the MR' do
- expect(project.merge_requests.first.ensure_ref_fetched.first).to include('refs/merge-requests/1/head')
+ project.merge_requests.first.ensure_ref_fetched
+
+ expect(project.repository.ref_exists?('refs/merge-requests/1/head')).to be_truthy
end
end
diff --git a/spec/lib/gitlab/usage_data_spec.rb b/spec/lib/gitlab/usage_data_spec.rb
index b47e1b56fa9..3c7c7562b46 100644
--- a/spec/lib/gitlab/usage_data_spec.rb
+++ b/spec/lib/gitlab/usage_data_spec.rb
@@ -37,6 +37,7 @@ describe Gitlab::UsageData do
deploy_keys
deployments
environments
+ in_review_folder
groups
issues
keys
diff --git a/spec/lib/gitlab/visibility_level_spec.rb b/spec/lib/gitlab/visibility_level_spec.rb
index 84d2484cc8a..db9d2807be6 100644
--- a/spec/lib/gitlab/visibility_level_spec.rb
+++ b/spec/lib/gitlab/visibility_level_spec.rb
@@ -21,7 +21,7 @@ describe Gitlab::VisibilityLevel, lib: true do
describe '.levels_for_user' do
it 'returns all levels for an admin' do
- user = double(:user, admin?: true)
+ user = build(:user, :admin)
expect(described_class.levels_for_user(user))
.to eq([Gitlab::VisibilityLevel::PRIVATE,
@@ -30,7 +30,7 @@ describe Gitlab::VisibilityLevel, lib: true do
end
it 'returns INTERNAL and PUBLIC for internal users' do
- user = double(:user, admin?: false, external?: false)
+ user = build(:user)
expect(described_class.levels_for_user(user))
.to eq([Gitlab::VisibilityLevel::INTERNAL,
@@ -38,7 +38,7 @@ describe Gitlab::VisibilityLevel, lib: true do
end
it 'returns PUBLIC for external users' do
- user = double(:user, admin?: false, external?: true)
+ user = build(:user, :external)
expect(described_class.levels_for_user(user))
.to eq([Gitlab::VisibilityLevel::PUBLIC])
diff --git a/spec/lib/system_check/simple_executor_spec.rb b/spec/lib/system_check/simple_executor_spec.rb
index a5c6170cd7d..795f11ee1f8 100644
--- a/spec/lib/system_check/simple_executor_spec.rb
+++ b/spec/lib/system_check/simple_executor_spec.rb
@@ -75,6 +75,24 @@ describe SystemCheck::SimpleExecutor, lib: true do
end
end
+ class BugousCheck < SystemCheck::BaseCheck
+ CustomError = Class.new(StandardError)
+ set_name 'my bugous check'
+
+ def check?
+ raise CustomError, 'omg'
+ end
+ end
+
+ before do
+ @rainbow = Rainbow.enabled
+ Rainbow.enabled = false
+ end
+
+ after do
+ Rainbow.enabled = @rainbow
+ end
+
describe '#component' do
it 'returns stored component name' do
expect(subject.component).to eq('Test')
@@ -219,5 +237,11 @@ describe SystemCheck::SimpleExecutor, lib: true do
end
end
end
+
+ context 'when there is an exception' do
+ it 'rescues the exception' do
+ expect{ subject.run_check(BugousCheck) }.not_to raise_exception
+ end
+ end
end
end
diff --git a/spec/models/commit_status_spec.rb b/spec/models/commit_status_spec.rb
index 9262ce08987..1e074c7ad26 100644
--- a/spec/models/commit_status_spec.rb
+++ b/spec/models/commit_status_spec.rb
@@ -284,6 +284,41 @@ describe CommitStatus, :models do
end
end
+ describe '.status' do
+ context 'when there are multiple statuses present' do
+ before do
+ create_status(status: 'running')
+ create_status(status: 'success')
+ create_status(allow_failure: true, status: 'failed')
+ end
+
+ it 'returns a correct compound status' do
+ expect(described_class.all.status).to eq 'running'
+ end
+ end
+
+ context 'when there are only allowed to fail commit statuses present' do
+ before do
+ create_status(allow_failure: true, status: 'failed')
+ end
+
+ it 'returns status that indicates success' do
+ expect(described_class.all.status).to eq 'success'
+ end
+ end
+
+ context 'when using a scope to select latest statuses' do
+ before do
+ create_status(name: 'test', retried: true, status: 'failed')
+ create_status(allow_failure: true, name: 'test', status: 'failed')
+ end
+
+ it 'returns status according to the scope' do
+ expect(described_class.latest.status).to eq 'success'
+ end
+ end
+ end
+
describe '#before_sha' do
subject { commit_status.before_sha }
diff --git a/spec/models/concerns/has_status_spec.rb b/spec/models/concerns/has_status_spec.rb
index 101567998c9..a38f2553eb1 100644
--- a/spec/models/concerns/has_status_spec.rb
+++ b/spec/models/concerns/has_status_spec.rb
@@ -48,7 +48,7 @@ describe HasStatus do
[create(type, status: :failed, allow_failure: true)]
end
- it { is_expected.to eq 'skipped' }
+ it { is_expected.to eq 'success' }
end
context 'success and canceled' do
diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb
index 1240c9745e2..bb5273074a2 100644
--- a/spec/models/merge_request_spec.rb
+++ b/spec/models/merge_request_spec.rb
@@ -1574,4 +1574,40 @@ describe MergeRequest, models: true do
end
end
end
+
+ describe '#fetch_ref' do
+ it 'sets "ref_fetched" flag to true' do
+ subject.update!(ref_fetched: nil)
+
+ subject.fetch_ref
+
+ expect(subject.reload.ref_fetched).to be_truthy
+ end
+ end
+
+ describe '#ref_fetched?' do
+ it 'does not perform git operation when value is cached' do
+ subject.ref_fetched = true
+
+ expect_any_instance_of(Repository).not_to receive(:ref_exists?)
+ expect(subject.ref_fetched?).to be_truthy
+ end
+
+ it 'caches the value when ref exists but value is not cached' do
+ subject.update!(ref_fetched: nil)
+ allow_any_instance_of(Repository).to receive(:ref_exists?)
+ .and_return(true)
+
+ expect(subject.ref_fetched?).to be_truthy
+ expect(subject.reload.ref_fetched).to be_truthy
+ end
+
+ it 'returns false when ref does not exist' do
+ subject.update!(ref_fetched: nil)
+ allow_any_instance_of(Repository).to receive(:ref_exists?)
+ .and_return(false)
+
+ expect(subject.ref_fetched?).to be_falsey
+ end
+ end
end
diff --git a/spec/models/project_services/bamboo_service_spec.rb b/spec/models/project_services/bamboo_service_spec.rb
index e62fd69e567..7b1a554d1fb 100644
--- a/spec/models/project_services/bamboo_service_spec.rb
+++ b/spec/models/project_services/bamboo_service_spec.rb
@@ -217,13 +217,13 @@ describe BambooService, models: true, caching: true do
end
def stub_request(status: 200, body: nil)
- bamboo_full_url = 'http://mic:password@gitlab.com/bamboo/rest/api/latest/result?label=123&os_authType=basic'
+ bamboo_full_url = 'http://gitlab.com/bamboo/rest/api/latest/result?label=123&os_authType=basic'
WebMock.stub_request(:get, bamboo_full_url).to_return(
status: status,
headers: { 'Content-Type' => 'application/json' },
body: body
- )
+ ).with(basic_auth: %w(mic password))
end
def bamboo_response(result_key: 42, build_state: 'success', size: 1)
diff --git a/spec/models/project_services/campfire_service_spec.rb b/spec/models/project_services/campfire_service_spec.rb
index de55627dd27..56ff3596190 100644
--- a/spec/models/project_services/campfire_service_spec.rb
+++ b/spec/models/project_services/campfire_service_spec.rb
@@ -39,21 +39,22 @@ describe CampfireService, models: true do
room: 'test-room'
)
@sample_data = Gitlab::DataBuilder::Push.build_sample(project, user)
- @rooms_url = 'https://verySecret:X@project-name.campfirenow.com/rooms.json'
+ @rooms_url = 'https://project-name.campfirenow.com/rooms.json'
+ @auth = %w(verySecret X)
@headers = { 'Content-Type' => 'application/json; charset=utf-8' }
end
it "calls Campfire API to get a list of rooms and speak in a room" do
# make sure a valid list of rooms is returned
body = File.read(Rails.root + 'spec/fixtures/project_services/campfire/rooms.json')
- WebMock.stub_request(:get, @rooms_url).to_return(
+ WebMock.stub_request(:get, @rooms_url).with(basic_auth: @auth).to_return(
body: body,
status: 200,
headers: @headers
)
# stub the speak request with the room id found in the previous request's response
- speak_url = 'https://verySecret:X@project-name.campfirenow.com/room/123/speak.json'
- WebMock.stub_request(:post, speak_url)
+ speak_url = 'https://project-name.campfirenow.com/room/123/speak.json'
+ WebMock.stub_request(:post, speak_url).with(basic_auth: @auth)
@campfire_service.execute(@sample_data)
@@ -66,7 +67,7 @@ describe CampfireService, models: true do
it "calls Campfire API to get a list of rooms but shouldn't speak in a room" do
# return a list of rooms that do not contain a room named 'test-room'
body = File.read(Rails.root + 'spec/fixtures/project_services/campfire/rooms2.json')
- WebMock.stub_request(:get, @rooms_url).to_return(
+ WebMock.stub_request(:get, @rooms_url).with(basic_auth: @auth).to_return(
body: body,
status: 200,
headers: @headers
diff --git a/spec/models/project_services/jira_service_spec.rb b/spec/models/project_services/jira_service_spec.rb
index e2b8226124f..c86f56c55eb 100644
--- a/spec/models/project_services/jira_service_spec.rb
+++ b/spec/models/project_services/jira_service_spec.rb
@@ -106,15 +106,15 @@ describe JiraService, models: true do
@jira_service.save
- project_issues_url = 'http://gitlab_jira_username:gitlab_jira_password@jira.example.com/rest/api/2/issue/JIRA-123'
- @transitions_url = 'http://gitlab_jira_username:gitlab_jira_password@jira.example.com/rest/api/2/issue/JIRA-123/transitions'
- @comment_url = 'http://gitlab_jira_username:gitlab_jira_password@jira.example.com/rest/api/2/issue/JIRA-123/comment'
- @remote_link_url = 'http://gitlab_jira_username:gitlab_jira_password@jira.example.com/rest/api/2/issue/JIRA-123/remotelink'
-
- WebMock.stub_request(:get, project_issues_url)
- WebMock.stub_request(:post, @transitions_url)
- WebMock.stub_request(:post, @comment_url)
- WebMock.stub_request(:post, @remote_link_url)
+ project_issues_url = 'http://jira.example.com/rest/api/2/issue/JIRA-123'
+ @transitions_url = 'http://jira.example.com/rest/api/2/issue/JIRA-123/transitions'
+ @comment_url = 'http://jira.example.com/rest/api/2/issue/JIRA-123/comment'
+ @remote_link_url = 'http://jira.example.com/rest/api/2/issue/JIRA-123/remotelink'
+
+ WebMock.stub_request(:get, project_issues_url).with(basic_auth: %w(gitlab_jira_username gitlab_jira_password))
+ WebMock.stub_request(:post, @transitions_url).with(basic_auth: %w(gitlab_jira_username gitlab_jira_password))
+ WebMock.stub_request(:post, @comment_url).with(basic_auth: %w(gitlab_jira_username gitlab_jira_password))
+ WebMock.stub_request(:post, @remote_link_url).with(basic_auth: %w(gitlab_jira_username gitlab_jira_password))
end
it "calls JIRA API" do
@@ -202,9 +202,9 @@ describe JiraService, models: true do
end
def test_settings(api_url)
- project_url = "http://jira_username:jira_password@#{api_url}/rest/api/2/project/GitLabProject"
+ project_url = "http://#{api_url}/rest/api/2/project/GitLabProject"
- WebMock.stub_request(:get, project_url)
+ WebMock.stub_request(:get, project_url).with(basic_auth: %w(jira_username jira_password))
jira_service.test_settings
end
diff --git a/spec/models/project_services/prometheus_service_spec.rb b/spec/models/project_services/prometheus_service_spec.rb
index c914b32f7a4..37f23b1243c 100644
--- a/spec/models/project_services/prometheus_service_spec.rb
+++ b/spec/models/project_services/prometheus_service_spec.rb
@@ -71,7 +71,7 @@ describe PrometheusService, models: true, caching: true do
end
describe '#deployment_metrics' do
- let(:deployment) { build_stubbed(:deployment)}
+ let(:deployment) { build_stubbed(:deployment) }
let(:deployment_query) { Gitlab::Prometheus::Queries::DeploymentQuery }
around do |example|
@@ -80,13 +80,16 @@ describe PrometheusService, models: true, caching: true do
context 'with valid data' do
subject { service.deployment_metrics(deployment) }
+ let(:fake_deployment_time) { 10 }
before do
stub_reactive_cache(service, prometheus_data, deployment_query, deployment.id)
end
it 'returns reactive data' do
- is_expected.to eq(prometheus_metrics_data.merge(deployment_time: deployment.created_at.to_i))
+ expect(deployment).to receive(:created_at).and_return(fake_deployment_time)
+
+ expect(subject).to eq(prometheus_metrics_data.merge(deployment_time: fake_deployment_time))
end
end
end
diff --git a/spec/models/project_services/teamcity_service_spec.rb b/spec/models/project_services/teamcity_service_spec.rb
index 7349eb4149a..6b004098510 100644
--- a/spec/models/project_services/teamcity_service_spec.rb
+++ b/spec/models/project_services/teamcity_service_spec.rb
@@ -205,10 +205,12 @@ describe TeamcityService, models: true, caching: true do
end
def stub_request(status: 200, body: nil, build_status: 'success')
- teamcity_full_url = 'http://mic:password@gitlab.com/teamcity/httpAuth/app/rest/builds/branch:unspecified:any,number:123'
+ teamcity_full_url = 'http://gitlab.com/teamcity/httpAuth/app/rest/builds/branch:unspecified:any,number:123'
+ auth = %w(mic password)
+
body ||= %Q({"build":{"status":"#{build_status}","id":"666"}})
- WebMock.stub_request(:get, teamcity_full_url).to_return(
+ WebMock.stub_request(:get, teamcity_full_url).with(basic_auth: auth).to_return(
status: status,
headers: { 'Content-Type' => 'application/json' },
body: body
diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb
index 314f8781867..8e895ec6634 100644
--- a/spec/models/user_spec.rb
+++ b/spec/models/user_spec.rb
@@ -1733,6 +1733,20 @@ describe User, models: true do
end
end
+ describe '#full_private_access?' do
+ it 'returns false for regular user' do
+ user = build(:user)
+
+ expect(user.full_private_access?).to be_falsy
+ end
+
+ it 'returns true for admin user' do
+ user = build(:user, :admin)
+
+ expect(user.full_private_access?).to be_truthy
+ end
+ end
+
describe '.ghost' do
it "creates a ghost user if one isn't already present" do
ghost = User.ghost
diff --git a/spec/requests/api/commit_statuses_spec.rb b/spec/requests/api/commit_statuses_spec.rb
index b8ca73c321c..cdb60fc0d1a 100644
--- a/spec/requests/api/commit_statuses_spec.rb
+++ b/spec/requests/api/commit_statuses_spec.rb
@@ -164,25 +164,40 @@ describe API::CommitStatuses do
context 'with all optional parameters' do
context 'when creating a commit status' do
- it 'creates commit status' do
+ subject do
post api(post_url, developer), {
state: 'success',
context: 'coverage',
- ref: 'develop',
+ ref: 'master',
description: 'test',
coverage: 80.0,
target_url: 'http://gitlab.com/status'
}
+ end
+
+ it 'creates commit status' do
+ subject
expect(response).to have_http_status(201)
expect(json_response['sha']).to eq(commit.id)
expect(json_response['status']).to eq('success')
expect(json_response['name']).to eq('coverage')
- expect(json_response['ref']).to eq('develop')
+ expect(json_response['ref']).to eq('master')
expect(json_response['coverage']).to eq(80.0)
expect(json_response['description']).to eq('test')
expect(json_response['target_url']).to eq('http://gitlab.com/status')
end
+
+ context 'when merge request exists for given branch' do
+ let!(:merge_request) { create(:merge_request, source_project: project, source_branch: 'master', target_branch: 'develop') }
+
+ it 'sets head pipeline' do
+ subject
+
+ expect(response).to have_http_status(201)
+ expect(merge_request.reload.head_pipeline).not_to be_nil
+ end
+ end
end
context 'when updatig a commit status' do
@@ -190,7 +205,7 @@ describe API::CommitStatuses do
post api(post_url, developer), {
state: 'running',
context: 'coverage',
- ref: 'develop',
+ ref: 'master',
description: 'coverage test',
coverage: 0.0,
target_url: 'http://gitlab.com/status'
@@ -199,7 +214,7 @@ describe API::CommitStatuses do
post api(post_url, developer), {
state: 'success',
name: 'coverage',
- ref: 'develop',
+ ref: 'master',
description: 'new description',
coverage: 90.0
}
@@ -210,7 +225,7 @@ describe API::CommitStatuses do
expect(json_response['sha']).to eq(commit.id)
expect(json_response['status']).to eq('success')
expect(json_response['name']).to eq('coverage')
- expect(json_response['ref']).to eq('develop')
+ expect(json_response['ref']).to eq('master')
expect(json_response['coverage']).to eq(90.0)
expect(json_response['description']).to eq('new description')
expect(json_response['target_url']).to eq('http://gitlab.com/status')
diff --git a/spec/requests/api/users_spec.rb b/spec/requests/api/users_spec.rb
index 18000d91795..c0174b304c8 100644
--- a/spec/requests/api/users_spec.rb
+++ b/spec/requests/api/users_spec.rb
@@ -364,6 +364,7 @@ describe API::Users do
it "updates user with new bio" do
put api("/users/#{user.id}", admin), { bio: 'new test bio' }
+
expect(response).to have_http_status(200)
expect(json_response['bio']).to eq('new test bio')
expect(user.reload.bio).to eq('new test bio')
@@ -396,13 +397,22 @@ describe API::Users do
it 'updates user with his own email' do
put api("/users/#{user.id}", admin), email: user.email
+
expect(response).to have_http_status(200)
expect(json_response['email']).to eq(user.email)
expect(user.reload.email).to eq(user.email)
end
+ it 'updates user with a new email' do
+ put api("/users/#{user.id}", admin), email: 'new@email.com'
+
+ expect(response).to have_http_status(200)
+ expect(user.reload.notification_email).to eq('new@email.com')
+ end
+
it 'updates user with his own username' do
put api("/users/#{user.id}", admin), username: user.username
+
expect(response).to have_http_status(200)
expect(json_response['username']).to eq(user.username)
expect(user.reload.username).to eq(user.username)
@@ -410,12 +420,14 @@ describe API::Users do
it "updates user's existing identity" do
put api("/users/#{omniauth_user.id}", admin), provider: 'ldapmain', extern_uid: '654321'
+
expect(response).to have_http_status(200)
expect(omniauth_user.reload.identities.first.extern_uid).to eq('654321')
end
it 'updates user with new identity' do
put api("/users/#{user.id}", admin), provider: 'github', extern_uid: 'john'
+
expect(response).to have_http_status(200)
expect(user.reload.identities.first.extern_uid).to eq('john')
expect(user.reload.identities.first.provider).to eq('github')
@@ -423,12 +435,14 @@ describe API::Users do
it "updates admin status" do
put api("/users/#{user.id}", admin), { admin: true }
+
expect(response).to have_http_status(200)
expect(user.reload.admin).to eq(true)
end
it "updates external status" do
put api("/users/#{user.id}", admin), { external: true }
+
expect(response.status).to eq 200
expect(json_response['external']).to eq(true)
expect(user.reload.external?).to be_truthy
@@ -436,6 +450,7 @@ describe API::Users do
it "does not update admin status" do
put api("/users/#{admin_user.id}", admin), { can_create_group: false }
+
expect(response).to have_http_status(200)
expect(admin_user.reload.admin).to eq(true)
expect(admin_user.can_create_group).to eq(false)
@@ -443,6 +458,7 @@ describe API::Users do
it "does not allow invalid update" do
put api("/users/#{user.id}", admin), { email: 'invalid email' }
+
expect(response).to have_http_status(400)
expect(user.reload.email).not_to eq('invalid email')
end
@@ -459,6 +475,7 @@ describe API::Users do
it "returns 404 for non-existing user" do
put api("/users/999999", admin), { bio: 'update should fail' }
+
expect(response).to have_http_status(404)
expect(json_response['message']).to eq('404 User Not Found')
end
@@ -509,6 +526,7 @@ describe API::Users do
it 'returns 409 conflict error if email address exists' do
put api("/users/#{@user.id}", admin), email: 'test@example.com'
+
expect(response).to have_http_status(409)
expect(@user.reload.email).to eq(@user.email)
end
@@ -516,6 +534,7 @@ describe API::Users do
it 'returns 409 conflict error if username taken' do
@user_id = User.all.last.id
put api("/users/#{@user.id}", admin), username: 'test'
+
expect(response).to have_http_status(409)
expect(@user.reload.username).to eq(@user.username)
end
diff --git a/spec/requests/api/variables_spec.rb b/spec/requests/api/variables_spec.rb
index 83673864fe7..e0975024b80 100644
--- a/spec/requests/api/variables_spec.rb
+++ b/spec/requests/api/variables_spec.rb
@@ -82,6 +82,17 @@ describe API::Variables do
expect(json_response['protected']).to be_truthy
end
+ it 'creates variable with optional attributes' do
+ expect do
+ post api("/projects/#{project.id}/variables", user), key: 'TEST_VARIABLE_2', value: 'VALUE_2'
+ end.to change{project.variables.count}.by(1)
+
+ expect(response).to have_http_status(201)
+ expect(json_response['key']).to eq('TEST_VARIABLE_2')
+ expect(json_response['value']).to eq('VALUE_2')
+ expect(json_response['protected']).to be_falsey
+ end
+
it 'does not allow to duplicate variable key' do
expect do
post api("/projects/#{project.id}/variables", user), key: variable.key, value: 'VALUE_2'
diff --git a/spec/services/ci/process_pipeline_service_spec.rb b/spec/services/ci/process_pipeline_service_spec.rb
index 1557cb3c938..efcaccc254e 100644
--- a/spec/services/ci/process_pipeline_service_spec.rb
+++ b/spec/services/ci/process_pipeline_service_spec.rb
@@ -62,6 +62,10 @@ describe Ci::ProcessPipelineService, '#execute', :services do
fail_running_or_pending
expect(builds_statuses).to eq %w(failed pending)
+
+ fail_running_or_pending
+
+ expect(pipeline.reload).to be_success
end
end
diff --git a/spec/services/emails/create_service_spec.rb b/spec/services/emails/create_service_spec.rb
new file mode 100644
index 00000000000..c1f477f551e
--- /dev/null
+++ b/spec/services/emails/create_service_spec.rb
@@ -0,0 +1,21 @@
+require 'spec_helper'
+
+describe Emails::CreateService, services: true do
+ let(:user) { create(:user) }
+ let(:opts) { { email: 'new@email.com' } }
+
+ subject(:service) { described_class.new(user, opts) }
+
+ describe '#execute' do
+ it 'creates an email with valid attributes' do
+ expect { service.execute }.to change { Email.count }.by(1)
+ expect(Email.where(opts)).not_to be_empty
+ end
+
+ it 'has the right user association' do
+ service.execute
+
+ expect(user.emails).to eq(Email.where(opts))
+ end
+ end
+end
diff --git a/spec/services/emails/destroy_service_spec.rb b/spec/services/emails/destroy_service_spec.rb
new file mode 100644
index 00000000000..5e7ab4a40af
--- /dev/null
+++ b/spec/services/emails/destroy_service_spec.rb
@@ -0,0 +1,14 @@
+require 'spec_helper'
+
+describe Emails::DestroyService, services: true do
+ let!(:user) { create(:user) }
+ let!(:email) { create(:email, user: user) }
+
+ subject(:service) { described_class.new(user, email: email.email) }
+
+ describe '#execute' do
+ it 'removes an email' do
+ expect { service.execute }.to change { user.emails.count }.by(-1)
+ end
+ end
+end
diff --git a/spec/services/projects/destroy_service_spec.rb b/spec/services/projects/destroy_service_spec.rb
index 0d6dd28e332..697dc18feb0 100644
--- a/spec/services/projects/destroy_service_spec.rb
+++ b/spec/services/projects/destroy_service_spec.rb
@@ -15,8 +15,9 @@ describe Projects::DestroyService, services: true do
shared_examples 'deleting the project' do
it 'deletes the project' do
expect(Project.unscoped.all).not_to include(project)
- expect(Dir.exist?(path)).to be_falsey
- expect(Dir.exist?(remove_path)).to be_falsey
+
+ expect(project.gitlab_shell.exists?(project.repository_storage_path, path + '.git')).to be_falsey
+ expect(project.gitlab_shell.exists?(project.repository_storage_path, remove_path + '.git')).to be_falsey
end
end
diff --git a/spec/services/users/update_service_spec.rb b/spec/services/users/update_service_spec.rb
new file mode 100644
index 00000000000..0b2f840c462
--- /dev/null
+++ b/spec/services/users/update_service_spec.rb
@@ -0,0 +1,43 @@
+require 'spec_helper'
+
+describe Users::UpdateService, services: true do
+ let(:user) { create(:user) }
+
+ describe '#execute' do
+ it 'updates the name' do
+ result = update_user(user, name: 'New Name')
+
+ expect(result).to eq(status: :success)
+ expect(user.name).to eq('New Name')
+ end
+
+ it 'returns an error result when record cannot be updated' do
+ expect do
+ update_user(user, { email: 'invalid' })
+ end.not_to change { user.reload.email }
+ end
+
+ def update_user(user, opts)
+ described_class.new(user, opts).execute
+ end
+ end
+
+ describe '#execute!' do
+ it 'updates the name' do
+ result = update_user(user, name: 'New Name')
+
+ expect(result).to be true
+ expect(user.name).to eq('New Name')
+ end
+
+ it 'raises an error when record cannot be updated' do
+ expect do
+ update_user(user, email: 'invalid')
+ end.to raise_error(ActiveRecord::RecordInvalid)
+ end
+
+ def update_user(user, opts)
+ described_class.new(user, opts).execute!
+ end
+ end
+end
diff --git a/spec/support/filter_item_select_helper.rb b/spec/support/filter_item_select_helper.rb
new file mode 100644
index 00000000000..519e84d359e
--- /dev/null
+++ b/spec/support/filter_item_select_helper.rb
@@ -0,0 +1,19 @@
+# Helper allows you to select value from filter-items
+#
+# Params
+# value - value for select
+# selector - css selector of item
+#
+# Usage:
+#
+# filter_item_select('Any Author', '.js-author-search')
+#
+module FilterItemSelectHelper
+ def filter_item_select(value, selector)
+ find(selector).click
+ wait_for_requests
+ page.within('.dropdown-content') do
+ click_link value
+ end
+ end
+end
diff --git a/spec/support/login_helpers.rb b/spec/support/login_helpers.rb
index 879386b5437..4c88958264b 100644
--- a/spec/support/login_helpers.rb
+++ b/spec/support/login_helpers.rb
@@ -89,4 +89,25 @@ module LoginHelpers
})
Rails.application.env_config['omniauth.auth'] = OmniAuth.config.mock_auth[:saml]
end
+
+ def mock_saml_config
+ OpenStruct.new(name: 'saml', label: 'saml', args: {
+ assertion_consumer_service_url: 'https://localhost:3443/users/auth/saml/callback',
+ idp_cert_fingerprint: '26:43:2C:47:AF:F0:6B:D0:07:9C:AD:A3:74:FE:5D:94:5F:4E:9E:52',
+ idp_sso_target_url: 'https://idp.example.com/sso/saml',
+ issuer: 'https://localhost:3443/',
+ name_identifier_format: 'urn:oasis:names:tc:SAML:2.0:nameid-format:transient'
+ })
+ end
+
+ def stub_omniauth_saml_config(messages)
+ Rails.application.env_config['devise.mapping'] = Devise.mappings[:user]
+ Rails.application.routes.disable_clear_and_finalize = true
+ Rails.application.routes.draw do
+ post '/users/auth/saml' => 'omniauth_callbacks#saml'
+ end
+ allow(Gitlab::OAuth::Provider).to receive_messages(providers: [:saml], config_for: mock_saml_config)
+ stub_omniauth_setting(messages)
+ expect_any_instance_of(Object).to receive(:omniauth_authorize_path).with(:user, "saml").and_return('/users/auth/saml')
+ end
end
diff --git a/spec/support/stub_env.rb b/spec/support/stub_env.rb
index 18597b5c71f..2999bcd9fb1 100644
--- a/spec/support/stub_env.rb
+++ b/spec/support/stub_env.rb
@@ -5,3 +5,11 @@ module StubENV
allow(ENV).to receive(:[]).with(key).and_return(value)
end
end
+
+# It's possible that the state of the class variables are not reset across
+# test runs.
+RSpec.configure do |config|
+ config.after(:each) do
+ @env_already_stubbed = nil
+ end
+end
diff --git a/vendor/Dockerfile/Binary-alpine.Dockerfile b/vendor/Dockerfile/Binary-alpine.Dockerfile
new file mode 100644
index 00000000000..5a9eb2b4716
--- /dev/null
+++ b/vendor/Dockerfile/Binary-alpine.Dockerfile
@@ -0,0 +1,14 @@
+# This Dockerfile installs a compiled binary into a bare system.
+# You must either commit your compiled binary into source control (not recommended)
+# or build the binary first as part of a CI/CD pipeline.
+
+FROM alpine:3.5
+
+# We'll likely need to add SSL root certificates
+RUN apk --no-cache add ca-certificates
+
+WORKDIR /usr/local/bin
+
+# Change `app` to whatever your binary is called
+Add app .
+CMD ["./app"]
diff --git a/vendor/Dockerfile/Binary-scratch.Dockerfile b/vendor/Dockerfile/Binary-scratch.Dockerfile
new file mode 100644
index 00000000000..5e2de2ead61
--- /dev/null
+++ b/vendor/Dockerfile/Binary-scratch.Dockerfile
@@ -0,0 +1,17 @@
+# This Dockerfile installs a compiled binary into an image with no system at all.
+# You must either commit your compiled binary into source control (not recommended)
+# or build the binary first as part of a CI/CD pipeline.
+# Your binary must be statically compiled with no dynamic dependencies on system libraries.
+# e.g. for Docker:
+# CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o app .
+
+FROM scratch
+
+# Since we started from scratch, we'll likely need to add SSL root certificates
+ADD /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
+
+WORKDIR /usr/local/bin
+
+# Change `app` to whatever your binary is called
+Add app .
+CMD ["./app"]
diff --git a/vendor/Dockerfile/Binary.Dockerfile b/vendor/Dockerfile/Binary.Dockerfile
new file mode 100644
index 00000000000..e7d560da9ac
--- /dev/null
+++ b/vendor/Dockerfile/Binary.Dockerfile
@@ -0,0 +1,11 @@
+# This Dockerfile installs a compiled binary into a bare system.
+# You must either commit your compiled binary into source control (not recommended)
+# or build the binary first as part of a CI/CD pipeline.
+
+FROM buildpack-deps:jessie
+
+WORKDIR /usr/local/bin
+
+# Change `app` to whatever your binary is called
+Add app .
+CMD ["./app"]
diff --git a/vendor/Dockerfile/Golang-alpine.Dockerfile b/vendor/Dockerfile/Golang-alpine.Dockerfile
new file mode 100644
index 00000000000..0287315219b
--- /dev/null
+++ b/vendor/Dockerfile/Golang-alpine.Dockerfile
@@ -0,0 +1,17 @@
+FROM golang:1.8-alpine AS builder
+
+WORKDIR /usr/src/app
+
+COPY . .
+RUN go-wrapper download
+RUN go build -v
+
+FROM alpine:3.5
+
+# We'll likely need to add SSL root certificates
+RUN apk --no-cache add ca-certificates
+
+WORKDIR /usr/local/bin
+
+COPY --from=builder /usr/src/app/app .
+CMD ["./app"]
diff --git a/vendor/Dockerfile/Golang-scratch.Dockerfile b/vendor/Dockerfile/Golang-scratch.Dockerfile
new file mode 100644
index 00000000000..9057a2d0e51
--- /dev/null
+++ b/vendor/Dockerfile/Golang-scratch.Dockerfile
@@ -0,0 +1,20 @@
+FROM golang:1.8-alpine AS builder
+
+# We'll likely need to add SSL root certificates
+RUN apk --no-cache add ca-certificates
+
+WORKDIR /usr/src/app
+
+COPY . .
+RUN go-wrapper download
+RUN CGO_ENABLED=0 GOOS=linux go build -v -a -installsuffix cgo -o app .
+
+FROM scratch
+
+# Since we started from scratch, we'll copy the SSL root certificates from the builder
+COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
+
+WORKDIR /usr/local/bin
+
+COPY --from=builder /usr/src/app/app .
+CMD ["./app"]
diff --git a/vendor/Dockerfile/Golang.Dockerfile b/vendor/Dockerfile/Golang.Dockerfile
new file mode 100644
index 00000000000..ec94914be19
--- /dev/null
+++ b/vendor/Dockerfile/Golang.Dockerfile
@@ -0,0 +1,14 @@
+FROM golang:1.8 AS builder
+
+WORKDIR /usr/src/app
+
+COPY . .
+RUN go-wrapper download
+RUN go build -v
+
+FROM buildpack-deps:jessie
+
+WORKDIR /usr/local/bin
+
+COPY --from=builder /usr/src/app/app .
+CMD ["./app"]
diff --git a/vendor/Dockerfile/Node-alpine.Dockerfile b/vendor/Dockerfile/Node-alpine.Dockerfile
new file mode 100644
index 00000000000..9776b1336b5
--- /dev/null
+++ b/vendor/Dockerfile/Node-alpine.Dockerfile
@@ -0,0 +1,14 @@
+FROM node:7.9-alpine
+
+WORKDIR /usr/src/app
+
+ARG NODE_ENV
+ENV NODE_ENV $NODE_ENV
+COPY package.json /usr/src/app/
+RUN npm install && npm cache clean
+COPY . /usr/src/app
+
+CMD [ "npm", "start" ]
+
+# replace this with your application's default port
+EXPOSE 8888
diff --git a/vendor/Dockerfile/Node.Dockerfile b/vendor/Dockerfile/Node.Dockerfile
new file mode 100644
index 00000000000..7e936d5e887
--- /dev/null
+++ b/vendor/Dockerfile/Node.Dockerfile
@@ -0,0 +1,14 @@
+FROM node:7.9
+
+WORKDIR /usr/src/app
+
+ARG NODE_ENV
+ENV NODE_ENV $NODE_ENV
+COPY package.json /usr/src/app/
+RUN npm install && npm cache clean
+COPY . /usr/src/app
+
+CMD [ "npm", "start" ]
+
+# replace this with your application's default port
+EXPOSE 8888
diff --git a/vendor/Dockerfile/Ruby-alpine.Dockerfile b/vendor/Dockerfile/Ruby-alpine.Dockerfile
new file mode 100644
index 00000000000..9db4e2130f2
--- /dev/null
+++ b/vendor/Dockerfile/Ruby-alpine.Dockerfile
@@ -0,0 +1,24 @@
+FROM ruby:2.4-alpine
+
+# Edit with nodejs, mysql-client, postgresql-client, sqlite3, etc. for your needs.
+# Or delete entirely if not needed.
+RUN apk --no-cache add nodejs postgresql-client
+
+# throw errors if Gemfile has been modified since Gemfile.lock
+RUN bundle config --global frozen 1
+
+RUN mkdir -p /usr/src/app
+WORKDIR /usr/src/app
+
+COPY Gemfile Gemfile.lock /usr/src/app/
+RUN bundle install
+
+COPY . /usr/src/app
+
+# For Sinatra
+#EXPOSE 4567
+#CMD ["ruby", "./config.rb"]
+
+# For Rails
+EXPOSE 3000
+CMD ["rails", "server"]
diff --git a/vendor/Dockerfile/Ruby.Dockerfile b/vendor/Dockerfile/Ruby.Dockerfile
new file mode 100644
index 00000000000..feb880ee4b2
--- /dev/null
+++ b/vendor/Dockerfile/Ruby.Dockerfile
@@ -0,0 +1,27 @@
+FROM ruby:2.4
+
+# Edit with nodejs, mysql-client, postgresql-client, sqlite3, etc. for your needs.
+# Or delete entirely if not needed.
+RUN apt-get update \
+ && apt-get install -y --no-install-recommends \
+ nodejs \
+ postgresql-client \
+ && rm -rf /var/lib/apt/lists/*
+
+# throw errors if Gemfile has been modified since Gemfile.lock
+RUN bundle config --global frozen 1
+
+WORKDIR /usr/src/app
+
+COPY Gemfile Gemfile.lock /usr/src/app/
+RUN bundle install -j $(nproc)
+
+COPY . /usr/src/app
+
+# For Sinatra
+#EXPOSE 4567
+#CMD ["ruby", "./config.rb"]
+
+# For Rails
+EXPOSE 3000
+CMD ["rails", "server", "-b", "0.0.0.0"]
diff --git a/vendor/gitignore/Global/Archives.gitignore b/vendor/gitignore/Global/Archives.gitignore
index f440b808d98..43fd5582f91 100644
--- a/vendor/gitignore/Global/Archives.gitignore
+++ b/vendor/gitignore/Global/Archives.gitignore
@@ -12,11 +12,11 @@
*.lzma
*.cab
-#packing-only formats
+# Packing-only formats
*.iso
*.tar
-#package management formats
+# Package management formats
*.dmg
*.xpi
*.gem
diff --git a/vendor/gitignore/Global/JEnv.gitignore b/vendor/gitignore/Global/JEnv.gitignore
new file mode 100644
index 00000000000..d838300ad5e
--- /dev/null
+++ b/vendor/gitignore/Global/JEnv.gitignore
@@ -0,0 +1,5 @@
+# JEnv local Java version configuration file
+.java-version
+
+# Used by previous versions of JEnv
+.jenv-version
diff --git a/vendor/gitignore/Global/SublimeText.gitignore b/vendor/gitignore/Global/SublimeText.gitignore
index 95ff2244c99..86c3fa455aa 100644
--- a/vendor/gitignore/Global/SublimeText.gitignore
+++ b/vendor/gitignore/Global/SublimeText.gitignore
@@ -1,16 +1,16 @@
-# cache files for sublime text
+# Cache files for Sublime Text
*.tmlanguage.cache
*.tmPreferences.cache
*.stTheme.cache
-# workspace files are user-specific
+# Workspace files are user-specific
*.sublime-workspace
-# project files should be checked into the repository, unless a significant
-# proportion of contributors will probably not be using SublimeText
+# Project files should be checked into the repository, unless a significant
+# proportion of contributors will probably not be using Sublime Text
# *.sublime-project
-# sftp configuration file
+# SFTP configuration file
sftp-config.json
# Package control specific files
diff --git a/vendor/gitignore/Global/Vagrant.gitignore b/vendor/gitignore/Global/Vagrant.gitignore
index a977916f658..93987ca00ec 100644
--- a/vendor/gitignore/Global/Vagrant.gitignore
+++ b/vendor/gitignore/Global/Vagrant.gitignore
@@ -1 +1,5 @@
+# General
.vagrant/
+
+# Log files (if you are creating logs in debug mode, uncomment this)
+# *.logs
diff --git a/vendor/gitignore/Global/Vim.gitignore b/vendor/gitignore/Global/Vim.gitignore
index 42e7afc1005..6d21783d471 100644
--- a/vendor/gitignore/Global/Vim.gitignore
+++ b/vendor/gitignore/Global/Vim.gitignore
@@ -1,12 +1,14 @@
-# swap
+# Swap
[._]*.s[a-v][a-z]
[._]*.sw[a-p]
[._]s[a-v][a-z]
[._]sw[a-p]
-# session
+
+# Session
Session.vim
-# temporary
+
+# Temporary
.netrwhist
*~
-# auto-generated tag files
+# Auto-generated tag files
tags
diff --git a/vendor/gitignore/Global/Windows.gitignore b/vendor/gitignore/Global/Windows.gitignore
index ba26afd9653..dff26a9ab70 100644
--- a/vendor/gitignore/Global/Windows.gitignore
+++ b/vendor/gitignore/Global/Windows.gitignore
@@ -3,6 +3,9 @@ Thumbs.db
ehthumbs.db
ehthumbs_vista.db
+# Dump file
+*.stackdump
+
# Folder config file
Desktop.ini
diff --git a/vendor/gitignore/Global/macOS.gitignore b/vendor/gitignore/Global/macOS.gitignore
index 5972fe50f66..9d1061e8bc4 100644
--- a/vendor/gitignore/Global/macOS.gitignore
+++ b/vendor/gitignore/Global/macOS.gitignore
@@ -1,3 +1,4 @@
+# General
*.DS_Store
.AppleDouble
.LSOverride
diff --git a/vendor/gitignore/Python.gitignore b/vendor/gitignore/Python.gitignore
index 768d5f400bb..113294a5f18 100644
--- a/vendor/gitignore/Python.gitignore
+++ b/vendor/gitignore/Python.gitignore
@@ -8,7 +8,6 @@ __pycache__/
# Distribution / packaging
.Python
-env/
build/
develop-eggs/
dist/
@@ -43,7 +42,7 @@ htmlcov/
.cache
nosetests.xml
coverage.xml
-*,cover
+*.cover
.hypothesis/
# Translations
@@ -79,11 +78,10 @@ celerybeat-schedule
# SageMath parsed files
*.sage.py
-# dotenv
+# Environments
.env
-
-# virtualenv
.venv
+env/
venv/
ENV/
diff --git a/vendor/gitignore/Qt.gitignore b/vendor/gitignore/Qt.gitignore
index 6732e72091c..5fa47c5a1f2 100644
--- a/vendor/gitignore/Qt.gitignore
+++ b/vendor/gitignore/Qt.gitignore
@@ -12,6 +12,9 @@
# Qt-es
+object_script.*.Release
+object_script.*.Debug
+*_plugin_import.cpp
/.qmake.cache
/.qmake.stash
*.pro.user
@@ -26,6 +29,11 @@ ui_*.h
Makefile*
*build-*
+
+# Qt unit tests
+target_wrapper.*
+
+
# QtCreator
*.autosave
diff --git a/vendor/gitignore/SugarCRM.gitignore b/vendor/gitignore/SugarCRM.gitignore
index e9270205fd5..6a183d1c748 100644
--- a/vendor/gitignore/SugarCRM.gitignore
+++ b/vendor/gitignore/SugarCRM.gitignore
@@ -6,7 +6,7 @@
# the misuse of the repository as backup replacement.
# For development the cache directory can be safely ignored and
# therefore it is ignored.
-/cache/
+/cache/*
!/cache/index.html
# Ignore some files and directories from the custom directory.
/custom/history/
@@ -22,6 +22,6 @@
# Logs files can safely be ignored.
*.log
# Ignore the new upload directories.
-/upload/
+/upload/*
!/upload/index.html
/upload_backup/
diff --git a/vendor/gitignore/VisualStudio.gitignore b/vendor/gitignore/VisualStudio.gitignore
index 940794e60f2..22fd88a55a3 100644
--- a/vendor/gitignore/VisualStudio.gitignore
+++ b/vendor/gitignore/VisualStudio.gitignore
@@ -42,6 +42,9 @@ TestResult.xml
[Rr]eleasePS/
dlldata.c
+# Benchmark Results
+BenchmarkDotNet.Artifacts/
+
# .NET Core
project.lock.json
project.fragment.lock.json
@@ -183,6 +186,7 @@ AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt
+*.appx
# Visual Studio cache files
# files ending in .cache can be ignored
@@ -278,6 +282,9 @@ __pycache__/
# tools/**
# !tools/packages.config
+# Tabs Studio
+*.tss
+
# Telerik's JustMock configuration file
*.jmconfig
diff --git a/vendor/gitlab-ci-yml/.gitlab-ci.yml b/vendor/gitlab-ci-yml/.gitlab-ci.yml
index 18b14554887..e2a55163682 100644
--- a/vendor/gitlab-ci-yml/.gitlab-ci.yml
+++ b/vendor/gitlab-ci-yml/.gitlab-ci.yml
@@ -1,4 +1,4 @@
-image: ruby:2.3-alpine
+image: ruby:2.4-alpine
test:
- script: ruby verify_templates.rb
+ script: ./verify_templates.rb
diff --git a/vendor/gitlab-ci-yml/Crystal.gitlab-ci.yml b/vendor/gitlab-ci-yml/Crystal.gitlab-ci.yml
index 37e44735f7c..02cfab3a5b2 100644
--- a/vendor/gitlab-ci-yml/Crystal.gitlab-ci.yml
+++ b/vendor/gitlab-ci-yml/Crystal.gitlab-ci.yml
@@ -4,7 +4,7 @@ image: "crystallang/crystal:latest"
# Pick zero or more services to be used on all builds.
# Only needed when using a docker container to run your tests in.
-# Check out: http://docs.gitlab.com/ce/ci/docker/using_docker_images.html#what-is-service
+# Check out: http://docs.gitlab.com/ce/ci/docker/using_docker_images.html#what-is-a-service
# services:
# - mysql:latest
# - redis:latest
diff --git a/vendor/gitlab-ci-yml/Django.gitlab-ci.yml b/vendor/gitlab-ci-yml/Django.gitlab-ci.yml
index 5ded2f5ce76..57afcbbe8b5 100644
--- a/vendor/gitlab-ci-yml/Django.gitlab-ci.yml
+++ b/vendor/gitlab-ci-yml/Django.gitlab-ci.yml
@@ -4,7 +4,7 @@ image: python:latest
# Pick zero or more services to be used on all builds.
# Only needed when using a docker container to run your tests in.
-# Check out: http://docs.gitlab.com/ce/ci/docker/using_docker_images.html#what-is-service
+# Check out: http://docs.gitlab.com/ce/ci/docker/using_docker_images.html#what-is-a-service
services:
- mysql:latest
- postgres:latest
diff --git a/vendor/gitlab-ci-yml/Docker.gitlab-ci.yml b/vendor/gitlab-ci-yml/Docker.gitlab-ci.yml
index 40648bcd3de..5b6af7be8c4 100644
--- a/vendor/gitlab-ci-yml/Docker.gitlab-ci.yml
+++ b/vendor/gitlab-ci-yml/Docker.gitlab-ci.yml
@@ -6,8 +6,8 @@ services:
build:
stage: build
+ before_script:
+ - docker login -u "$CI_REGISTRY_USER" -p "CI_REGISTRY_PASSWORD" $CI_REGISTRY
script:
- - export IMAGE_TAG=$(echo -en $CI_COMMIT_REF_NAME | tr -c '[:alnum:]_.-' '-')
- - docker login -u "gitlab-ci-token" -p "$CI_JOB_TOKEN" $CI_REGISTRY
- - docker build --pull -t "$CI_REGISTRY_IMAGE:$IMAGE_TAG" .
- - docker push "$CI_REGISTRY_IMAGE:$IMAGE_TAG"
+ - docker build --pull -t "$CI_REGISTRY_IMAGE:CI_COMMIT_REF_SLUG" .
+ - docker push "$CI_REGISTRY_IMAGE:CI_COMMIT_REF_SLUG"
diff --git a/vendor/gitlab-ci-yml/Elixir.gitlab-ci.yml b/vendor/gitlab-ci-yml/Elixir.gitlab-ci.yml
index 981a77497e2..cf9c731637c 100644
--- a/vendor/gitlab-ci-yml/Elixir.gitlab-ci.yml
+++ b/vendor/gitlab-ci-yml/Elixir.gitlab-ci.yml
@@ -2,7 +2,7 @@ image: elixir:latest
# Pick zero or more services to be used on all builds.
# Only needed when using a docker container to run your tests in.
-# Check out: http://docs.gitlab.com/ce/ci/docker/using_docker_images.html#what-is-service
+# Check out: http://docs.gitlab.com/ce/ci/docker/using_docker_images.html#what-is-a-service
services:
- mysql:latest
- redis:latest
diff --git a/vendor/gitlab-ci-yml/Laravel.gitlab-ci.yml b/vendor/gitlab-ci-yml/Laravel.gitlab-ci.yml
index 0d6a6eddc97..434de4f055a 100644
--- a/vendor/gitlab-ci-yml/Laravel.gitlab-ci.yml
+++ b/vendor/gitlab-ci-yml/Laravel.gitlab-ci.yml
@@ -4,7 +4,7 @@ image: php:latest
# Pick zero or more services to be used on all builds.
# Only needed when using a docker container to run your tests in.
-# Check out: http://docs.gitlab.com/ce/ci/docker/using_docker_images.html#what-is-service
+# Check out: http://docs.gitlab.com/ce/ci/docker/using_docker_images.html#what-is-a-service
services:
- mysql:latest
diff --git a/vendor/gitlab-ci-yml/Nodejs.gitlab-ci.yml b/vendor/gitlab-ci-yml/Nodejs.gitlab-ci.yml
index e5bce3503f3..41de1458582 100644
--- a/vendor/gitlab-ci-yml/Nodejs.gitlab-ci.yml
+++ b/vendor/gitlab-ci-yml/Nodejs.gitlab-ci.yml
@@ -4,7 +4,7 @@ image: node:latest
# Pick zero or more services to be used on all builds.
# Only needed when using a docker container to run your tests in.
-# Check out: http://docs.gitlab.com/ce/ci/docker/using_docker_images.html#what-is-service
+# Check out: http://docs.gitlab.com/ce/ci/docker/using_docker_images.html#what-is-a-service
services:
- mysql:latest
- redis:latest
diff --git a/vendor/gitlab-ci-yml/Pages/JBake.gitlab-ci.yml b/vendor/gitlab-ci-yml/Pages/JBake.gitlab-ci.yml
index bc36a4e6966..7abfaf53e8e 100644
--- a/vendor/gitlab-ci-yml/Pages/JBake.gitlab-ci.yml
+++ b/vendor/gitlab-ci-yml/Pages/JBake.gitlab-ci.yml
@@ -3,7 +3,7 @@
#
# JBake https://jbake.org/ is a Java based, open source, static site/blog generator for developers & designers
#
-# This yml works with jBake 2.4.0
+# This yml works with jBake 2.5.1
# Feel free to change JBAKE_VERSION version
#
# HowTo at: https://jorge.aguilera.gitlab.io/howtojbake/
@@ -11,12 +11,12 @@
image: java:8
variables:
- JBAKE_VERSION: 2.4.0
+ JBAKE_VERSION: 2.5.1
# We use SDKMan as tool for managing versions
before_script:
- - apt-get update -qq && apt-get install -y -qq unzip
+ - apt-get update -qq && apt-get install -y -qq unzip zip
- curl -sSL https://get.sdkman.io | bash
- echo sdkman_auto_answer=true > /root/.sdkman/etc/config
- source /root/.sdkman/bin/sdkman-init.sh
diff --git a/vendor/gitlab-ci-yml/Ruby.gitlab-ci.yml b/vendor/gitlab-ci-yml/Ruby.gitlab-ci.yml
index 08b57c8c0ac..4e181e85451 100644
--- a/vendor/gitlab-ci-yml/Ruby.gitlab-ci.yml
+++ b/vendor/gitlab-ci-yml/Ruby.gitlab-ci.yml
@@ -4,7 +4,7 @@ image: "ruby:2.3"
# Pick zero or more services to be used on all builds.
# Only needed when using a docker container to run your tests in.
-# Check out: http://docs.gitlab.com/ce/ci/docker/using_docker_images.html#what-is-service
+# Check out: http://docs.gitlab.com/ce/ci/docker/using_docker_images.html#what-is-a-service
services:
- mysql:latest
- redis:latest
diff --git a/vendor/gitlab-ci-yml/Rust.gitlab-ci.yml b/vendor/gitlab-ci-yml/Rust.gitlab-ci.yml
index ae3f7405ea3..7810121c350 100644
--- a/vendor/gitlab-ci-yml/Rust.gitlab-ci.yml
+++ b/vendor/gitlab-ci-yml/Rust.gitlab-ci.yml
@@ -4,7 +4,7 @@ image: "scorpil/rust:stable"
# Optional: Pick zero or more services to be used on all builds.
# Only needed when using a docker container to run your tests in.
-# Check out: http://docs.gitlab.com/ce/ci/docker/using_docker_images.html#what-is-service
+# Check out: http://docs.gitlab.com/ce/ci/docker/using_docker_images.html#what-is-a-service
#services:
# - mysql:latest
# - redis:latest
diff --git a/vendor/licenses.csv b/vendor/licenses.csv
index a8e7f5e3ea9..5dcac5947a1 100644
--- a/vendor/licenses.csv
+++ b/vendor/licenses.csv
@@ -2,7 +2,7 @@ RedCloth,4.3.2,MIT
abbrev,1.0.9,ISC
accepts,1.3.3,MIT
ace-rails-ap,4.1.2,MIT
-acorn,4.0.11,MIT
+acorn,5.0.3,MIT
acorn-dynamic-import,2.0.1,MIT
acorn-jsx,3.0.1,MIT
actionmailer,4.2.8,MIT
@@ -53,6 +53,7 @@ assert-plus,0.2.0,MIT
async,0.2.10,MIT
async-each,1.0.1,MIT
asynckit,0.4.0,MIT
+atomic,1.1.99,Apache 2.0
attr_encrypted,3.0.3,MIT
attr_required,1.0.0,MIT
autoparse,0.3.3,Apache 2.0
@@ -151,8 +152,9 @@ blob,0.0.4,unknown
block-stream,0.0.9,ISC
bluebird,3.4.7,MIT
bn.js,4.11.6,MIT
-body-parser,1.16.0,MIT
+body-parser,1.17.2,MIT
boom,2.10.1,New BSD
+bootsnap,1.0.0,MIT
bootstrap-sass,3.3.6,MIT
brace-expansion,1.1.6,MIT
braces,1.8.5,MIT
@@ -222,9 +224,10 @@ compression,1.6.2,MIT
compression-webpack-plugin,0.3.2,MIT
concat-map,0.0.1,MIT
concat-stream,1.6.0,MIT
+concurrent-ruby-ext,1.0.5,MIT
config-chain,1.1.11,MIT
configstore,1.4.0,Simplified BSD
-connect,3.5.0,MIT
+connect,3.6.2,MIT
connect-history-api-fallback,1.3.0,MIT
connection_pool,2.2.1,MIT
console-browserify,1.1.0,MIT
@@ -262,8 +265,9 @@ dashdash,1.14.1,MIT
date-now,0.1.4,MIT
de-indent,1.0.2,MIT
debug,2.6.0,MIT
+debugger-ruby_core_source,1.3.8,MIT
decamelize,1.2.0,MIT
-deckar01-task_list,1.0.6,MIT
+deckar01-task_list,2.0.0,MIT
deep-extend,0.4.1,MIT
deep-is,0.1.3,MIT
default-require-extensions,1.0.0,MIT
@@ -312,8 +316,8 @@ emojis-list,2.1.0,MIT
encodeurl,1.0.1,MIT
encryptor,3.0.0,MIT
end-of-stream,1.0.0,MIT
-engine.io,1.8.2,MIT
-engine.io-client,1.8.2,MIT
+engine.io,1.8.3,MIT
+engine.io-client,1.8.3,MIT
engine.io-parser,1.3.2,MIT
enhanced-resolve,3.1.0,MIT
ent,2.2.0,MIT
@@ -349,7 +353,8 @@ esprima,3.1.3,Simplified BSD
esrecurse,4.1.0,Simplified BSD
estraverse,4.1.1,Simplified BSD
esutils,2.0.2,BSD
-etag,1.7.0,MIT
+et-orbi,1.0.3,MIT
+etag,1.8.0,MIT
eve-raphael,0.5.0,Apache 2.0
event-emitter,0.3.4,MIT
event-stream,3.3.4,MIT
@@ -364,12 +369,11 @@ expand-braces,0.1.2,MIT
expand-brackets,0.1.5,MIT
expand-range,1.8.2,MIT
exports-loader,0.6.4,MIT
-express,4.14.1,MIT
+express,4.15.3,MIT
expression_parser,0.9.0,MIT
extend,3.0.0,MIT
extglob,0.3.2,MIT
extlib,0.9.16,MIT
-extract-zip,1.5.0,Simplified BSD
extsprintf,1.0.2,MIT
faraday,0.11.0,MIT
faraday_middleware,0.11.0.1,MIT
@@ -378,7 +382,6 @@ fast-levenshtein,2.0.6,MIT
fast_gettext,1.4.0,"MIT,ruby"
fastparse,1.1.1,MIT
faye-websocket,0.7.3,MIT
-fd-slicer,1.0.1,MIT
ffi,1.9.10,BSD
figures,1.7.0,MIT
file-entry-cache,2.0.0,MIT
@@ -387,13 +390,16 @@ filename-regex,2.0.0,MIT
fileset,2.0.3,MIT
filesize,3.3.0,New BSD
fill-range,2.2.3,MIT
-finalhandler,0.5.1,MIT
+finalhandler,1.0.3,MIT
find-cache-dir,0.1.1,MIT
find-root,0.1.2,MIT
find-up,2.1.0,MIT
flat-cache,1.2.2,MIT
flatten,1.0.2,MIT
+flipper,0.10.2,MIT
+flipper-active_record,0.10.2,MIT
flowdock,0.7.1,MIT
+fog-aliyun,0.1.0,MIT
fog-aws,0.13.0,MIT
fog-core,1.44.1,MIT
fog-google,0.5.0,MIT
@@ -409,9 +415,8 @@ forever-agent,0.6.1,Apache 2.0
form-data,2.1.2,MIT
formatador,0.2.5,MIT
forwarded,0.1.0,MIT
-fresh,0.3.0,MIT
+fresh,0.5.0,MIT
from,0.1.7,MIT
-fs-extra,1.0.0,MIT
fs.realpath,1.0.0,ISC
fsevents,,unknown
fstream,1.0.10,ISC
@@ -427,7 +432,7 @@ get_process_mem,0.2.0,MIT
getpass,0.1.6,MIT
gettext_i18n_rails,1.8.0,MIT
gettext_i18n_rails_js,1.2.0,MIT
-gitaly,0.6.0,MIT
+gitaly,0.8.0,MIT
github-linguist,4.7.6,MIT
github-markup,1.4.0,MIT
gitlab-flowdock-git-hook,1.0.1,MIT
@@ -467,7 +472,6 @@ has-flag,1.0.0,MIT
has-unicode,2.0.1,ISC
hash-sum,1.0.2,MIT
hash.js,1.0.3,MIT
-hasha,2.2.0,MIT
hashie,3.5.5,MIT
hashie-forbidden_attributes,0.1.1,MIT
hawk,3.1.3,New BSD
@@ -487,7 +491,7 @@ htmlparser2,3.9.2,MIT
http,0.9.8,MIT
http-cookie,1.0.3,MIT
http-deceiver,1.2.7,MIT
-http-errors,1.5.1,MIT
+http-errors,1.6.1,MIT
http-form_data,1.0.1,MIT
http-proxy,1.16.2,MIT
http-proxy-middleware,0.17.4,MIT
@@ -516,7 +520,7 @@ inquirer,0.12.0,MIT
interpret,1.0.1,MIT
invariant,2.2.2,New BSD
invert-kv,1.0.0,MIT
-ipaddr.js,1.2.0,MIT
+ipaddr.js,1.3.0,MIT
ipaddress,0.8.3,MIT
is-absolute,0.2.6,MIT
is-absolute-url,2.1.0,MIT
@@ -563,7 +567,7 @@ istanbul-lib-instrument,1.4.2,New BSD
istanbul-lib-report,1.0.0-alpha.3,New BSD
istanbul-lib-source-maps,1.1.0,New BSD
istanbul-reports,1.0.1,New BSD
-jasmine-core,2.5.2,MIT
+jasmine-core,2.6.3,MIT
jasmine-jquery,2.1.1,MIT
jed,1.1.1,MIT
jira-ruby,1.1.2,MIT
@@ -587,7 +591,6 @@ json-stable-stringify,1.0.1,MIT
json-stringify-safe,5.0.1,ISC
json3,3.3.2,MIT
json5,0.5.1,MIT
-jsonfile,2.4.0,MIT
jsonify,0.0.0,Public Domain
jsonpointer,4.0.1,MIT
jsprim,1.3.1,MIT
@@ -595,17 +598,14 @@ jszip,3.1.3,(MIT OR GPL-3.0)
jszip-utils,0.0.2,MIT or GPLv3
jwt,1.5.6,MIT
kaminari,0.17.0,MIT
-karma,1.4.1,MIT
+karma,1.7.0,MIT
karma-coverage-istanbul-reporter,0.2.0,MIT
karma-jasmine,1.1.0,MIT
karma-mocha-reporter,2.2.2,MIT
-karma-phantomjs-launcher,1.0.2,MIT
karma-sourcemap-loader,0.3.7,MIT
karma-webpack,2.0.2,MIT
-kew,0.7.0,Apache 2.0
kgio,2.10.0,LGPL-2.1+
kind-of,3.1.0,MIT
-klaw,1.3.1,MIT
kubeclient,2.2.0,MIT
latest-version,1.0.1,MIT
launchy,2.4.3,ISC
@@ -667,7 +667,7 @@ methods,1.1.2,MIT
micromatch,2.3.11,MIT
miller-rabin,4.0.0,MIT
mime,1.3.4,MIT
-mime-db,1.26.0,MIT
+mime-db,1.27.0,MIT
mime-types,2.99.3,"MIT,Artistic-2.0,GPL-2.0"
mimemagic,0.3.0,MIT
mini_portile2,2.1.0,MIT
@@ -675,16 +675,20 @@ minimalistic-assert,1.0.0,ISC
minimatch,3.0.3,ISC
minimist,0.0.8,MIT
mkdirp,0.5.1,MIT
+mmap2,2.2.6,ruby
moment,2.17.1,MIT
mousetrap,1.4.6,Apache 2.0
mousetrap-rails,1.4.6,"MIT,Apache"
ms,0.7.2,MIT
+msgpack,1.1.0,Apache 2.0
multi_json,1.12.1,MIT
multi_xml,0.6.0,MIT
multipart-post,2.0.0,MIT
mustermann,0.4.0,MIT
mustermann-grape,0.4.0,MIT
mute-stream,0.0.5,ISC
+mysql2,0.3.20,MIT
+name-all-modules-plugin,1.0.1,MIT
nan,2.5.1,MIT
natural-compare,1.4.0,MIT
negotiator,0.6.1,MIT
@@ -774,9 +778,16 @@ path-type,1.1.0,MIT
pause-stream,0.0.11,"MIT,Apache2"
pbkdf2,3.0.9,MIT
pdfjs-dist,1.8.252,Apache 2.0
-pend,1.2.0,MIT
+peek,1.0.1,MIT
+peek-gc,0.0.2,MIT
+peek-host,1.0.0,MIT
+peek-mysql2,1.1.0,MIT
+peek-performance_bar,1.2.1,MIT
+peek-pg,1.3.0,MIT
+peek-rblineprof,0.2.0,MIT
+peek-redis,1.2.0,MIT
+peek-sidekiq,1.0.3,MIT
pg,0.18.4,"BSD,ruby,GPL"
-phantomjs-prebuilt,2.1.14,Apache 2.0
pify,2.3.0,MIT
pikaday,1.5.1,"BSD,MIT"
pinkie,2.0.4,MIT
@@ -833,8 +844,9 @@ private,0.1.7,MIT
process,0.11.9,MIT
process-nextick-args,1.0.7,MIT
progress,1.1.8,MIT
+prometheus-client-mmap,0.7.0.beta5,Apache 2.0
proto-list,1.2.4,ISC
-proxy-addr,1.1.3,MIT
+proxy-addr,1.1.4,MIT
prr,0.0.0,MIT
ps-tree,1.1.0,MIT
pseudomap,1.0.2,ISC
@@ -843,7 +855,7 @@ punycode,1.4.1,MIT
pyu-ruby-sasl,0.0.3.3,MIT
q,1.5.0,MIT
qjobs,1.1.5,MIT
-qs,6.2.0,New BSD
+qs,6.3.0,New BSD
query-string,4.3.2,MIT
querystring,0.2.0,MIT
querystring-es3,0.2.1,MIT
@@ -868,7 +880,7 @@ randomatic,1.1.6,MIT
randombytes,2.0.3,MIT
range-parser,1.2.0,MIT
raphael,2.2.7,MIT
-raven-js,3.15.0,Simplified BSD
+raven-js,3.14.0,Simplified BSD
raw-body,2.2.0,MIT
raw-loader,0.5.1,MIT
rc,1.1.6,(BSD-2-Clause OR MIT OR Apache-2.0)
@@ -906,7 +918,6 @@ repeat-element,1.1.2,MIT
repeat-string,1.6.1,MIT
repeating,2.0.1,MIT
request,2.79.0,Apache 2.0
-request-progress,2.0.1,MIT
request_store,1.3.1,MIT
require-directory,2.1.1,MIT
require-from-string,1.2.1,MIT
@@ -924,7 +935,7 @@ rimraf,2.5.4,ISC
rinku,2.0.0,ISC
ripemd160,1.0.1,New BSD
rotp,2.1.2,MIT
-rouge,2.0.7,MIT
+rouge,2.1.0,MIT
rqrcode,0.7.0,MIT
rqrcode-rails3,0.1.7,MIT
ruby-fogbugz,0.2.1,MIT
@@ -933,7 +944,7 @@ ruby-saml,1.4.1,MIT
ruby_parser,3.8.4,MIT
rubyntlm,0.5.2,MIT
rubypants,0.2.0,BSD
-rufus-scheduler,3.1.10,MIT
+rufus-scheduler,3.4.0,MIT
rugged,0.25.1.1,MIT
run-async,0.1.0,MIT
rx-lite,3.1.2,Apache 2.0
@@ -952,20 +963,20 @@ select2,3.5.2-browserify,unknown
select2-rails,3.5.9.3,MIT
semver,5.3.0,ISC
semver-diff,2.1.0,MIT
-send,0.14.2,MIT
+send,0.15.3,MIT
sentry-raven,2.4.0,Apache 2.0
serve-index,1.8.0,MIT
-serve-static,1.11.2,MIT
+serve-static,1.12.3,MIT
set-blocking,2.0.0,ISC
set-immediate-shim,1.0.1,MIT
setimmediate,1.0.5,MIT
-setprototypeof,1.0.2,ISC
+setprototypeof,1.0.3,ISC
settingslogic,2.0.9,MIT
sexp_processor,4.8.0,MIT
sha.js,2.4.8,MIT
shelljs,0.7.6,New BSD
sidekiq,5.0.0,LGPL
-sidekiq-cron,0.4.4,MIT
+sidekiq-cron,0.6.0,MIT
sidekiq-limit_fetch,3.4.0,MIT
sigmund,1.0.1,ISC
signal-exit,3.0.2,ISC
@@ -975,9 +986,9 @@ slash,1.0.0,MIT
slice-ansi,0.0.4,MIT
slide,1.1.6,ISC
sntp,1.0.9,BSD
-socket.io,1.7.2,MIT
+socket.io,1.7.3,MIT
socket.io-adapter,0.5.0,MIT
-socket.io-client,1.7.2,MIT
+socket.io-client,1.7.3,MIT
socket.io-parser,2.3.1,MIT
sockjs,0.3.18,MIT
sockjs-client,1.0.1,MIT
@@ -1030,7 +1041,6 @@ thread_safe,0.3.6,Apache 2.0
three,0.84.0,MIT
three-orbit-controls,82.1.0,MIT
three-stl-loader,1.0.4,MIT
-throttleit,1.0.0,MIT
through,2.3.8,MIT
tilt,2.0.6,MIT
timeago.js,2.0.5,MIT
@@ -1038,7 +1048,7 @@ timed-out,2.0.0,MIT
timers-browserify,2.0.2,MIT
timfel-krb5-auth,0.8.3,LGPL
tiny-emitter,1.1.0,MIT
-tmp,0.0.28,MIT
+tmp,0.0.31,MIT
to-array,0.1.4,MIT
to-arraybuffer,1.0.1,MIT
to-fast-properties,1.0.2,MIT
@@ -1054,15 +1064,15 @@ tty-browserify,0.0.0,MIT
tunnel-agent,0.4.3,Apache 2.0
tweetnacl,0.14.5,Unlicense
type-check,0.3.2,MIT
-type-is,1.6.14,MIT
+type-is,1.6.15,MIT
typedarray,0.0.6,MIT
tzinfo,1.2.2,MIT
u2f,0.2.1,MIT
uglifier,2.7.2,MIT
-uglify-js,2.8.21,Simplified BSD
+uglify-js,2.8.27,Simplified BSD
uglify-to-browserify,1.0.2,MIT
uid-number,0.0.6,ISC
-ultron,1.0.2,MIT
+ultron,1.1.0,MIT
unc-path-regex,0.1.2,MIT
undefsafe,0.0.3,MIT / http://rem.mit-license.org
underscore,1.8.3,MIT
@@ -1081,14 +1091,14 @@ url-loader,0.5.8,MIT
url-parse,1.0.5,MIT
url_safe_base64,0.2.2,MIT
user-home,2.0.0,MIT
-useragent,2.1.12,MIT
+useragent,2.1.13,MIT
util,0.10.3,MIT
util-deprecate,1.0.2,MIT
utils-merge,1.0.0,MIT
uuid,3.0.1,MIT
validate-npm-package-license,3.0.1,Apache 2.0
validates_hostname,1.0.6,MIT
-vary,1.1.0,MIT
+vary,1.1.1,MIT
vendors,1.0.1,MIT
verror,1.3.6,MIT
version_sorter,2.1.0,MIT
@@ -1107,8 +1117,8 @@ vue-template-es2015-compiler,1.5.1,MIT
warden,1.2.6,MIT
watchpack,1.3.1,MIT
wbuf,1.7.2,MIT
-webpack,2.3.3,MIT
-webpack-bundle-analyzer,2.3.0,MIT
+webpack,2.6.1,MIT
+webpack-bundle-analyzer,2.8.2,MIT
webpack-dev-middleware,1.10.0,MIT
webpack-dev-server,2.4.2,MIT
webpack-rails,0.9.10,MIT
@@ -1127,14 +1137,14 @@ wrap-ansi,2.1.0,MIT
wrappy,1.0.2,ISC
write,0.2.1,MIT
write-file-atomic,1.3.1,ISC
-ws,1.1.1,MIT
+ws,2.3.1,MIT
wtf-8,1.0.0,MIT
xdg-basedir,2.0.0,MIT
+xml-simple,1.1.5,ruby
xmlhttprequest-ssl,1.5.3,MIT
xtend,4.0.1,MIT
y18n,3.2.1,ISC
yallist,2.1.2,ISC
yargs,3.10.0,MIT
yargs-parser,4.2.1,ISC
-yauzl,2.4.1,MIT
yeast,0.1.2,MIT