summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitlab-ci.yml43
-rw-r--r--.gitlab/issue_templates/Test plan.md4
-rw-r--r--CHANGELOG.md14
-rw-r--r--GITALY_SERVER_VERSION2
-rw-r--r--Gemfile22
-rw-r--r--Gemfile.lock40
-rw-r--r--Gemfile.rails4.lock28
-rw-r--r--PROCESS.md6
-rw-r--r--app/assets/javascripts/badges/components/badge.vue2
-rw-r--r--app/assets/javascripts/badges/components/badge_form.vue2
-rw-r--r--app/assets/javascripts/badges/components/badge_list.vue2
-rw-r--r--app/assets/javascripts/badges/components/badge_list_row.vue2
-rw-r--r--app/assets/javascripts/boards/components/board_list.vue2
-rw-r--r--app/assets/javascripts/boards/components/board_new_issue.vue2
-rw-r--r--app/assets/javascripts/boards/components/issue_card_inner.vue4
-rw-r--r--app/assets/javascripts/boards/components/issue_due_date.vue2
-rw-r--r--app/assets/javascripts/boards/components/issue_time_estimate.vue2
-rw-r--r--app/assets/javascripts/boards/components/modal/index.vue2
-rw-r--r--app/assets/javascripts/boards/components/modal/lists_dropdown.vue2
-rw-r--r--app/assets/javascripts/boards/components/project_select.vue2
-rw-r--r--app/assets/javascripts/deploy_keys/components/action_btn.vue2
-rw-r--r--app/assets/javascripts/deploy_keys/components/app.vue2
-rw-r--r--app/assets/javascripts/diff_notes/components/jump_to_discussion.js2
-rw-r--r--app/assets/javascripts/diffs/components/app.vue2
-rw-r--r--app/assets/javascripts/diffs/components/compare_versions.vue2
-rw-r--r--app/assets/javascripts/diffs/components/diff_file.vue2
-rw-r--r--app/assets/javascripts/diffs/components/diff_gutter_avatars.vue2
-rw-r--r--app/assets/javascripts/diffs/components/tree_list.vue2
-rw-r--r--app/assets/javascripts/diffs/store/getters.js2
-rw-r--r--app/assets/javascripts/environments/components/container.vue2
-rw-r--r--app/assets/javascripts/environments/components/environment_actions.vue2
-rw-r--r--app/assets/javascripts/environments/components/environment_external_url.vue2
-rw-r--r--app/assets/javascripts/environments/components/environment_item.vue2
-rw-r--r--app/assets/javascripts/environments/components/environment_monitoring.vue2
-rw-r--r--app/assets/javascripts/environments/components/environment_rollback.vue4
-rw-r--r--app/assets/javascripts/environments/components/environment_stop.vue2
-rw-r--r--app/assets/javascripts/environments/components/environment_terminal_button.vue2
-rw-r--r--app/assets/javascripts/environments/components/environments_table.vue2
-rw-r--r--app/assets/javascripts/environments/components/stop_environment_modal.vue2
-rw-r--r--app/assets/javascripts/filtered_search/dropdown_emoji.js11
-rw-r--r--app/assets/javascripts/frequent_items/components/app.vue2
-rw-r--r--app/assets/javascripts/gfm_auto_complete.js15
-rw-r--r--app/assets/javascripts/groups/components/app.vue2
-rw-r--r--app/assets/javascripts/ide/components/branches/search_list.vue2
-rw-r--r--app/assets/javascripts/ide/components/error_message.vue2
-rw-r--r--app/assets/javascripts/ide/components/file_templates/dropdown.vue2
-rw-r--r--app/assets/javascripts/ide/components/ide_side_bar.vue2
-rw-r--r--app/assets/javascripts/ide/components/ide_tree_list.vue2
-rw-r--r--app/assets/javascripts/ide/components/jobs/list.vue2
-rw-r--r--app/assets/javascripts/ide/components/jobs/stage.vue2
-rw-r--r--app/assets/javascripts/ide/components/merge_requests/list.vue2
-rw-r--r--app/assets/javascripts/ide/components/pipelines/list.vue2
-rw-r--r--app/assets/javascripts/ide/components/preview/clientside.vue2
-rw-r--r--app/assets/javascripts/ide/components/preview/navigator.vue2
-rw-r--r--app/assets/javascripts/init_legacy_filters.js14
-rw-r--r--app/assets/javascripts/jobs/components/artifacts_block.vue2
-rw-r--r--app/assets/javascripts/jobs/components/commit_block.vue2
-rw-r--r--app/assets/javascripts/jobs/components/empty_state.vue2
-rw-r--r--app/assets/javascripts/jobs/components/erased_block.vue2
-rw-r--r--app/assets/javascripts/jobs/components/job_app.vue2
-rw-r--r--app/assets/javascripts/jobs/components/job_container_item.vue2
-rw-r--r--app/assets/javascripts/jobs/components/job_log_controllers.vue2
-rw-r--r--app/assets/javascripts/jobs/components/sidebar.vue2
-rw-r--r--app/assets/javascripts/jobs/components/sidebar_detail_row.vue2
-rw-r--r--app/assets/javascripts/jobs/components/stuck_block.vue2
-rw-r--r--app/assets/javascripts/jobs/components/trigger_block.vue2
-rw-r--r--app/assets/javascripts/lib/utils/text_markdown.js11
-rw-r--r--app/assets/javascripts/notebook/cells/output/index.vue2
-rw-r--r--app/assets/javascripts/notes.js2
-rw-r--r--app/assets/javascripts/notes/components/diff_with_note.vue2
-rw-r--r--app/assets/javascripts/notes/components/note_actions.vue2
-rw-r--r--app/assets/javascripts/pages/dashboard/issues/index.js10
-rw-r--r--app/assets/javascripts/pages/dashboard/merge_requests/index.js12
-rw-r--r--app/assets/javascripts/pages/projects/wikis/components/delete_wiki_modal.vue2
-rw-r--r--app/assets/javascripts/pages/users/user_overview_block.js5
-rw-r--r--app/assets/javascripts/pages/users/user_tabs.js110
-rw-r--r--app/assets/javascripts/pipelines/components/empty_state.vue2
-rw-r--r--app/assets/javascripts/pipelines/components/graph/action_component.vue2
-rw-r--r--app/assets/javascripts/pipelines/components/graph/graph_component.vue2
-rw-r--r--app/assets/javascripts/pipelines/components/graph/job_group_dropdown.vue2
-rw-r--r--app/assets/javascripts/pipelines/components/graph/job_item.vue2
-rw-r--r--app/assets/javascripts/pipelines/components/header_component.vue2
-rw-r--r--app/assets/javascripts/pipelines/components/nav_controls.vue2
-rw-r--r--app/assets/javascripts/pipelines/components/pipeline_url.vue2
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_actions.vue2
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_artifacts.vue2
-rw-r--r--app/assets/javascripts/pipelines/components/stage.vue2
-rw-r--r--app/assets/javascripts/pipelines/mixins/pipelines.js2
-rw-r--r--app/assets/javascripts/projects/gke_cluster_dropdowns/components/gke_dropdown_mixin.js2
-rw-r--r--app/assets/javascripts/projects/tree/components/commit_pipeline_status_component.vue2
-rw-r--r--app/assets/javascripts/registry/components/app.vue2
-rw-r--r--app/assets/javascripts/registry/components/collapsible_container.vue2
-rw-r--r--app/assets/javascripts/reports/components/summary_row.vue2
-rw-r--r--app/assets/javascripts/search_autocomplete.js9
-rw-r--r--app/assets/javascripts/set_status_modal/set_status_modal_wrapper.vue2
-rw-r--r--app/assets/javascripts/sidebar/components/participants/participants.vue2
-rw-r--r--app/assets/javascripts/sidebar/components/time_tracking/comparison_pane.vue2
-rw-r--r--app/assets/javascripts/sidebar/components/todo_toggle/todo.vue2
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/deployment.vue9
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/mr_widget_status_icon.vue2
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_auto_merge_failed.vue2
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merged.vue2
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_rebase.vue2
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/changed_file_icon.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/ci_badge_link.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/clipboard_button.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/commit.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/content_viewer/viewers/download_viewer.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/content_viewer/viewers/markdown_viewer.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/dropdown/dropdown_button.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/file_icon.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/gl_countdown.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/header_ci_component.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/loading_button.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/markdown/header.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/markdown/toolbar.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/markdown/toolbar_button.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/notes/skeleton_note.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/pagination_links.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/date_picker.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select/base.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/toggle_button.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/user_avatar/user_avatar_image.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/user_avatar/user_avatar_link.vue2
-rw-r--r--app/controllers/application_controller.rb4
-rw-r--r--app/controllers/concerns/issuable_collections.rb36
-rw-r--r--app/controllers/concerns/merge_requests_action.rb2
-rw-r--r--app/controllers/dashboard_controller.rb12
-rw-r--r--app/controllers/projects/deploy_keys_controller.rb11
-rw-r--r--app/controllers/root_controller.rb4
-rw-r--r--app/finders/events_finder.rb2
-rw-r--r--app/finders/group_descendants_finder.rb2
-rw-r--r--app/finders/issuable_finder.rb14
-rw-r--r--app/helpers/application_helper.rb12
-rw-r--r--app/helpers/auth_helper.rb17
-rw-r--r--app/helpers/dashboard_helper.rb4
-rw-r--r--app/helpers/search_helper.rb15
-rw-r--r--app/models/ci/build.rb28
-rw-r--r--app/models/clusters/kubernetes_namespace.rb37
-rw-r--r--app/models/commit.rb25
-rw-r--r--app/models/concerns/avatarable.rb2
-rw-r--r--app/models/member.rb24
-rw-r--r--app/models/project.rb2
-rw-r--r--app/models/project_services/chat_message/push_message.rb47
-rw-r--r--app/models/user.rb49
-rw-r--r--app/services/clusters/gcp/kubernetes/create_or_update_namespace_service.rb2
-rw-r--r--app/services/projects/disable_deploy_key_service.rb13
-rw-r--r--app/services/projects/enable_deploy_key_service.rb14
-rw-r--r--app/services/todos/destroy/entity_leave_service.rb2
-rw-r--r--app/services/todos/destroy/private_features_service.rb6
-rw-r--r--app/services/users/build_service.rb2
-rw-r--r--app/views/dashboard/issues.html.haml4
-rw-r--r--app/views/dashboard/merge_requests.html.haml4
-rw-r--r--app/views/devise/shared/_signin_box.html.haml6
-rw-r--r--app/views/devise/shared/_tabs_ldap.html.haml7
-rw-r--r--app/views/projects/environments/_external_url.html.haml2
-rw-r--r--app/views/projects/environments/_form.html.haml15
-rw-r--r--app/views/projects/environments/_metrics_button.html.haml4
-rw-r--r--app/views/projects/environments/edit.html.haml4
-rw-r--r--app/views/projects/environments/folder.html.haml2
-rw-r--r--app/views/projects/environments/index.html.haml4
-rw-r--r--app/views/projects/environments/metrics.html.haml2
-rw-r--r--app/views/projects/environments/new.html.haml6
-rw-r--r--app/views/projects/environments/show.html.haml22
-rw-r--r--app/views/projects/environments/terminal.html.haml4
-rw-r--r--app/views/shared/_labels_row.html.haml5
-rw-r--r--app/views/shared/issuable/_filter.html.haml32
-rw-r--r--app/views/shared/issuable/_search_bar.html.haml5
-rw-r--r--app/views/u2f/_authenticate.html.haml10
-rw-r--r--app/views/u2f/_register.html.haml22
-rw-r--r--app/views/users/_overview.html.haml40
-rw-r--r--app/views/users/show.html.haml6
-rw-r--r--changelogs/unreleased/49479-hide-unmerged-env-perf-stats.yml5
-rw-r--r--changelogs/unreleased/51959-branch-and-tag-name-links.yml5
-rw-r--r--changelogs/unreleased/52385-search-bar-for-dashboard-list.yml5
-rw-r--r--changelogs/unreleased/52712-further-ui-improvements-to-profile-overview-tab.yml5
-rw-r--r--changelogs/unreleased/53290-incorrect-project-list-order-select-default-label.yml5
-rw-r--r--changelogs/unreleased/53700-hashed-storagemigration.yml5
-rw-r--r--changelogs/unreleased/54004-update-asana-to-0-8-1.yml5
-rw-r--r--changelogs/unreleased/54010-update-asciidoctor-to-1-5-8.yml5
-rw-r--r--changelogs/unreleased/54015-Markdown-Editor-improve-Cursor-placement.yml5
-rw-r--r--changelogs/unreleased/54093-the-default_value_for-gem-doesn-t-handle-actioncontroller-parameters-correctly.yml7
-rw-r--r--changelogs/unreleased/an-gitaly-version-0-133-0.yml5
-rw-r--r--changelogs/unreleased/auto-devops-support-for-group-security-dashboard.yml5
-rw-r--r--changelogs/unreleased/drop-default-value-status-deployments.yml5
-rw-r--r--changelogs/unreleased/fix-not-render-emoji.yml5
-rw-r--r--changelogs/unreleased/frozen-string-lib-gitlab-even-even-more.yml5
-rw-r--r--changelogs/unreleased/gt-fix-typo-in-notebook-props.yml5
-rw-r--r--changelogs/unreleased/rails5-active-record-class-value.yml5
-rw-r--r--changelogs/unreleased/security-2717-xss-username-autocomplete.yml5
-rw-r--r--changelogs/unreleased/sh-bump-gems-security.yml5
-rw-r--r--changelogs/unreleased/sh-fix-issue-53783-ce.yml5
-rw-r--r--changelogs/unreleased/sh-fix-issue-54189.yml5
-rw-r--r--changelogs/unreleased/sh-use-nakayoshi-fork.yml5
-rw-r--r--changelogs/unreleased/zj-improve-gitaly-pb.yml5
-rw-r--r--config/dependency_decisions.yml7
-rw-r--r--danger/documentation/Dangerfile27
-rw-r--r--db/migrate/20181112103239_drop_default_value_on_status_deployments.rb14
-rw-r--r--db/schema.rb4
-rw-r--r--doc/administration/high_availability/redis.md2
-rw-r--r--doc/ci/pipelines.md2
-rw-r--r--doc/ci/variables/where_variables_can_be_used.md2
-rw-r--r--doc/ci/yaml/README.md14
-rw-r--r--doc/development/feature_flags.md2
-rw-r--r--doc/development/testing_guide/review_apps.md4
-rw-r--r--doc/install/requirements.md2
-rw-r--r--doc/topics/autodevops/index.md2
-rw-r--r--doc/university/bookclub/booklist.md2
-rw-r--r--doc/user/project/clusters/index.md24
-rw-r--r--doc/user/project/clusters/runbooks/img/authorize-jupyter.pngbin0 -> 126425 bytes
-rw-r--r--doc/user/project/clusters/runbooks/img/demo-runbook.pngbin0 -> 132436 bytes
-rw-r--r--doc/user/project/clusters/runbooks/img/gitlab-variables.pngbin0 -> 179611 bytes
-rw-r--r--doc/user/project/clusters/runbooks/img/helm-install.pngbin0 -> 201348 bytes
-rw-r--r--doc/user/project/clusters/runbooks/img/ingress-install.pngbin0 -> 140880 bytes
-rw-r--r--doc/user/project/clusters/runbooks/img/jupyterhub-install.pngbin0 -> 116775 bytes
-rw-r--r--doc/user/project/clusters/runbooks/img/postgres-query.pngbin0 -> 209435 bytes
-rw-r--r--doc/user/project/clusters/runbooks/img/sample-runbook.pngbin0 -> 145728 bytes
-rw-r--r--doc/user/project/clusters/runbooks/index.md94
-rw-r--r--doc/user/project/import/github.md1
-rw-r--r--doc/user/project/merge_requests/img/merge_request_diff_file_navigation.pngbin111544 -> 68704 bytes
-rw-r--r--doc/user/project/merge_requests/index.md15
-rw-r--r--doc/user/project/milestones/index.md20
-rw-r--r--doc/user/search/img/dashboard_links.pngbin0 -> 27164 bytes
-rw-r--r--doc/user/search/img/issues_assigned_to_you.pngbin49079 -> 50433 bytes
-rw-r--r--doc/user/search/img/left_menu_bar.pngbin37433 -> 0 bytes
-rw-r--r--doc/user/search/index.md16
-rw-r--r--lib/gitlab.rb4
-rw-r--r--lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml32
-rw-r--r--lib/gitlab/ci/variables/collection/item.rb4
-rw-r--r--lib/gitlab/git/blob.rb2
-rw-r--r--lib/gitlab/git/repository.rb6
-rw-r--r--lib/gitlab/gitaly_client.rb125
-rw-r--r--lib/gitlab/hook_data/base_builder.rb2
-rw-r--r--lib/gitlab/hook_data/issuable_builder.rb2
-rw-r--r--lib/gitlab/hook_data/issue_builder.rb2
-rw-r--r--lib/gitlab/hook_data/merge_request_builder.rb2
-rw-r--r--lib/gitlab/hook_data/note_builder.rb2
-rw-r--r--lib/gitlab/hook_data/wiki_page_builder.rb2
-rw-r--r--lib/gitlab/i18n/metadata_entry.rb2
-rw-r--r--lib/gitlab/i18n/po_linter.rb2
-rw-r--r--lib/gitlab/i18n/translation_entry.rb2
-rw-r--r--lib/gitlab/import/logger.rb2
-rw-r--r--lib/gitlab/import_export/after_export_strategies/base_after_export_strategy.rb2
-rw-r--r--lib/gitlab/import_export/after_export_strategies/download_notification_strategy.rb2
-rw-r--r--lib/gitlab/import_export/after_export_strategies/web_upload_strategy.rb2
-rw-r--r--lib/gitlab/import_export/after_export_strategy_builder.rb2
-rw-r--r--lib/gitlab/import_export/attribute_cleaner.rb2
-rw-r--r--lib/gitlab/import_export/attributes_finder.rb2
-rw-r--r--lib/gitlab/import_export/avatar_restorer.rb2
-rw-r--r--lib/gitlab/import_export/avatar_saver.rb2
-rw-r--r--lib/gitlab/import_export/command_line_util.rb2
-rw-r--r--lib/gitlab/import_export/error.rb2
-rw-r--r--lib/gitlab/import_export/file_importer.rb2
-rw-r--r--lib/gitlab/import_export/group_project_object_builder.rb2
-rw-r--r--lib/gitlab/import_export/hash_util.rb2
-rw-r--r--lib/gitlab/import_export/import_export.yml2
-rw-r--r--lib/gitlab/import_export/importer.rb2
-rw-r--r--lib/gitlab/import_export/json_hash_builder.rb2
-rw-r--r--lib/gitlab/import_export/lfs_restorer.rb2
-rw-r--r--lib/gitlab/import_export/lfs_saver.rb2
-rw-r--r--lib/gitlab/import_export/members_mapper.rb2
-rw-r--r--lib/gitlab/import_export/merge_request_parser.rb2
-rw-r--r--lib/gitlab/import_export/project_tree_restorer.rb2
-rw-r--r--lib/gitlab/import_export/project_tree_saver.rb2
-rw-r--r--lib/gitlab/import_export/reader.rb2
-rw-r--r--lib/gitlab/import_export/relation_factory.rb4
-rw-r--r--lib/gitlab/import_export/repo_restorer.rb2
-rw-r--r--lib/gitlab/import_export/repo_saver.rb2
-rw-r--r--lib/gitlab/import_export/saver.rb2
-rw-r--r--lib/gitlab/import_export/shared.rb2
-rw-r--r--lib/gitlab/import_export/statistics_restorer.rb2
-rw-r--r--lib/gitlab/import_export/uploads_manager.rb2
-rw-r--r--lib/gitlab/import_export/uploads_restorer.rb2
-rw-r--r--lib/gitlab/import_export/uploads_saver.rb2
-rw-r--r--lib/gitlab/import_export/version_checker.rb2
-rw-r--r--lib/gitlab/import_export/version_saver.rb2
-rw-r--r--lib/gitlab/import_export/wiki_repo_saver.rb2
-rw-r--r--lib/gitlab/import_export/wiki_restorer.rb2
-rw-r--r--lib/gitlab/kubernetes/config_map.rb2
-rw-r--r--lib/gitlab/kubernetes/helm.rb2
-rw-r--r--lib/gitlab/kubernetes/helm/api.rb2
-rw-r--r--lib/gitlab/kubernetes/helm/base_command.rb2
-rw-r--r--lib/gitlab/kubernetes/helm/client_command.rb2
-rw-r--r--lib/gitlab/kubernetes/helm/init_command.rb2
-rw-r--r--lib/gitlab/kubernetes/helm/install_command.rb2
-rw-r--r--lib/gitlab/kubernetes/helm/pod.rb2
-rw-r--r--lib/gitlab/kubernetes/namespace.rb2
-rw-r--r--lib/gitlab/kubernetes/pod.rb2
-rw-r--r--lib/gitlab/legacy_github_import/base_formatter.rb2
-rw-r--r--lib/gitlab/legacy_github_import/branch_formatter.rb2
-rw-r--r--lib/gitlab/legacy_github_import/client.rb2
-rw-r--r--lib/gitlab/legacy_github_import/comment_formatter.rb2
-rw-r--r--lib/gitlab/legacy_github_import/importer.rb2
-rw-r--r--lib/gitlab/legacy_github_import/issuable_formatter.rb2
-rw-r--r--lib/gitlab/legacy_github_import/issue_formatter.rb2
-rw-r--r--lib/gitlab/legacy_github_import/label_formatter.rb2
-rw-r--r--lib/gitlab/legacy_github_import/milestone_formatter.rb2
-rw-r--r--lib/gitlab/legacy_github_import/project_creator.rb2
-rw-r--r--lib/gitlab/legacy_github_import/pull_request_formatter.rb2
-rw-r--r--lib/gitlab/legacy_github_import/release_formatter.rb2
-rw-r--r--lib/gitlab/legacy_github_import/user_formatter.rb2
-rw-r--r--lib/gitlab/legacy_github_import/wiki_formatter.rb2
-rw-r--r--lib/gitlab/manifest_import/manifest.rb2
-rw-r--r--lib/gitlab/manifest_import/project_creator.rb2
-rw-r--r--lib/gitlab/metrics/background_transaction.rb2
-rw-r--r--lib/gitlab/metrics/delta.rb2
-rw-r--r--lib/gitlab/metrics/influx_db.rb2
-rw-r--r--lib/gitlab/metrics/instrumentation.rb2
-rw-r--r--lib/gitlab/metrics/method_call.rb2
-rw-r--r--lib/gitlab/metrics/methods.rb2
-rw-r--r--lib/gitlab/metrics/methods/metric_options.rb2
-rw-r--r--lib/gitlab/metrics/metric.rb2
-rw-r--r--lib/gitlab/metrics/null_metric.rb2
-rw-r--r--lib/gitlab/metrics/prometheus.rb2
-rw-r--r--lib/gitlab/metrics/rack_middleware.rb2
-rw-r--r--lib/gitlab/metrics/requests_rack_middleware.rb2
-rw-r--r--lib/gitlab/metrics/samplers/base_sampler.rb2
-rw-r--r--lib/gitlab/metrics/samplers/influx_sampler.rb2
-rw-r--r--lib/gitlab/metrics/samplers/ruby_sampler.rb2
-rw-r--r--lib/gitlab/metrics/samplers/unicorn_sampler.rb2
-rw-r--r--lib/gitlab/metrics/sidekiq_metrics_exporter.rb2
-rw-r--r--lib/gitlab/metrics/sidekiq_middleware.rb2
-rw-r--r--lib/gitlab/metrics/subscribers/action_view.rb2
-rw-r--r--lib/gitlab/metrics/subscribers/active_record.rb2
-rw-r--r--lib/gitlab/metrics/subscribers/rails_cache.rb2
-rw-r--r--lib/gitlab/metrics/system.rb2
-rw-r--r--lib/gitlab/metrics/transaction.rb2
-rw-r--r--lib/gitlab/metrics/web_transaction.rb4
-rw-r--r--lib/gitlab/middleware/go.rb2
-rw-r--r--lib/gitlab/middleware/multipart.rb2
-rw-r--r--lib/gitlab/middleware/rails_queue_duration.rb2
-rw-r--r--lib/gitlab/middleware/read_only.rb2
-rw-r--r--lib/gitlab/middleware/read_only/controller.rb2
-rw-r--r--lib/gitlab/middleware/release_env.rb5
-rw-r--r--lib/gitlab/middleware/static.rb2
-rw-r--r--lib/gitlab/private_commit_email.rb4
-rw-r--r--locale/gitlab.pot81
-rw-r--r--package.json4
-rw-r--r--qa/qa/resource/user.rb11
-rw-r--r--qa/qa/runtime/env.rb16
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/project/add_project_member_spec.rb2
-rw-r--r--spec/controllers/application_controller_spec.rb8
-rw-r--r--spec/controllers/concerns/issuable_collections_spec.rb15
-rw-r--r--spec/controllers/projects/deploy_keys_controller_spec.rb149
-rw-r--r--spec/controllers/root_controller_spec.rb4
-rw-r--r--spec/factories/clusters/kubernetes_namespaces.rb1
-rw-r--r--spec/features/admin/admin_users_spec.rb18
-rw-r--r--spec/features/atom/dashboard_issues_spec.rb12
-rw-r--r--spec/features/calendar_spec.rb24
-rw-r--r--spec/features/dashboard/issuables_counter_spec.rb4
-rw-r--r--spec/features/dashboard/issues_filter_spec.rb31
-rw-r--r--spec/features/dashboard/issues_spec.rb27
-rw-r--r--spec/features/dashboard/label_filter_spec.rb15
-rw-r--r--spec/features/dashboard/merge_requests_spec.rb15
-rw-r--r--spec/features/dashboard/milestone_filter_spec.rb77
-rw-r--r--spec/features/issues/filtered_search/dropdown_emoji_spec.rb2
-rw-r--r--spec/features/issues/gfm_autocomplete_spec.rb29
-rw-r--r--spec/features/issues/user_sorts_issues_spec.rb2
-rw-r--r--spec/features/merge_requests/user_sorts_merge_requests_spec.rb4
-rw-r--r--spec/features/projects/wiki/user_updates_wiki_page_spec.rb298
-rw-r--r--spec/features/projects/wiki/user_views_wiki_page_spec.rb224
-rw-r--r--spec/features/search/user_uses_header_search_field_spec.rb16
-rw-r--r--spec/features/users/login_spec.rb24
-rw-r--r--spec/features/users/overview_spec.rb8
-rw-r--r--spec/finders/group_descendants_finder_spec.rb7
-rw-r--r--spec/finders/pending_todos_finder_spec.rb2
-rw-r--r--spec/helpers/auth_helper_spec.rb10
-rw-r--r--spec/helpers/search_helper_spec.rb35
-rw-r--r--spec/javascripts/lib/utils/text_markdown_spec.js31
-rw-r--r--spec/javascripts/search_autocomplete_spec.js12
-rw-r--r--spec/javascripts/vue_mr_widget/components/deployment_spec.js27
-rw-r--r--spec/javascripts/vue_shared/components/expand_button_spec.js2
-rw-r--r--spec/lib/extracts_path_spec.rb26
-rw-r--r--spec/lib/gitlab/ci/variables/collection/item_spec.rb4
-rw-r--r--spec/lib/gitlab/diff/file_collection/merge_request_diff_spec.rb14
-rw-r--r--spec/lib/gitlab/git/blob_spec.rb12
-rw-r--r--spec/lib/gitlab/git/commit_spec.rb194
-rw-r--r--spec/lib/gitlab/git/tag_spec.rb30
-rw-r--r--spec/lib/gitlab/git/tree_spec.rb14
-rw-r--r--spec/lib/gitlab/gitaly_client_spec.rb101
-rw-r--r--spec/lib/gitlab/import_export/project.json10
-rw-r--r--spec/lib/gitlab/import_export/project.light.json22
-rw-r--r--spec/lib/gitlab/import_export/project_tree_restorer_spec.rb9
-rw-r--r--spec/lib/gitlab/private_commit_email_spec.rb24
-rw-r--r--spec/models/ci/build_spec.rb363
-rw-r--r--spec/models/clusters/kubernetes_namespace_spec.rb8
-rw-r--r--spec/models/commit_spec.rb24
-rw-r--r--spec/models/merge_request_spec.rb62
-rw-r--r--spec/models/project_services/chat_message/push_message_spec.rb65
-rw-r--r--spec/models/project_spec.rb8
-rw-r--r--spec/models/project_wiki_spec.rb250
-rw-r--r--spec/models/repository_spec.rb372
-rw-r--r--spec/models/todo_spec.rb2
-rw-r--r--spec/models/user_spec.rb37
-rw-r--r--spec/models/wiki_page_spec.rb280
-rw-r--r--spec/services/clusters/gcp/kubernetes/create_or_update_namespace_service_spec.rb2
-rw-r--r--spec/services/users/build_service_spec.rb2
-rw-r--r--spec/support/gitaly.rb16
-rw-r--r--spec/support/helpers/devise_helpers.rb9
-rw-r--r--spec/support/helpers/filter_item_select_helper.rb19
-rw-r--r--spec/support/helpers/user_login_helper.rb26
-rw-r--r--vendor/licenses.csv3
-rw-r--r--yarn.lock128
404 files changed, 2930 insertions, 2391 deletions
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index b7f18673a58..0c662f42111 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -463,19 +463,19 @@ danger-review:
rspec-pg:
<<: *rspec-metadata-pg
- parallel: 30
+ parallel: 50
rspec-mysql:
<<: *rspec-metadata-mysql
- parallel: 30
+ parallel: 50
rspec-pg-rails4:
<<: *rspec-metadata-pg-rails4
- parallel: 30
+ parallel: 50
rspec-mysql-rails4:
<<: *rspec-metadata-mysql-rails4
- parallel: 30
+ parallel: 50
static-analysis:
<<: *dedicated-no-docs-no-db-pull-cache-job
@@ -739,6 +739,39 @@ qa:selectors:
- bundle install
- bundle exec bin/qa Test::Sanity::Selectors
+.qa-frontend-node: &qa-frontend-node
+ stage: test
+ variables:
+ NODE_OPTIONS: --max_old_space_size=3584
+ cache:
+ key: "$CI_JOB_NAME"
+ paths:
+ - .yarn-cache/
+ dependencies: []
+ before_script: []
+ script:
+ - date
+ - yarn install --frozen-lockfile --cache-folder .yarn-cache
+ - date
+ - yarn run webpack-prod
+
+qa-frontend-node:6:
+ <<: *qa-frontend-node
+ image: node:6-alpine
+
+qa-frontend-node:8:
+ <<: *qa-frontend-node
+ image: node:8-alpine
+
+qa-frontend-node:10:
+ <<: *qa-frontend-node
+ image: node:10-alpine
+
+qa-frontend-node:latest:
+ <<: *qa-frontend-node
+ image: node:alpine
+ allow_failure: true
+
coverage:
# Don't include dedicated-no-docs-no-db-pull-cache-job here since we need to
# download artifacts from all the rspec jobs instead of from setup-test-env only
@@ -788,6 +821,8 @@ pages:
- mv coverage-javascript/ public/coverage-javascript/ || true
- mv eslint-report.html public/ || true
- mv webpack-report/ public/webpack-report/ || true
+ - cp .public/assets/application-*.css public/application.css || true
+ - cp .public/assets/application-*.css.gz public/application.css.gz || true
artifacts:
paths:
- public
diff --git a/.gitlab/issue_templates/Test plan.md b/.gitlab/issue_templates/Test plan.md
index db8e30c419c..a3c3f4a6509 100644
--- a/.gitlab/issue_templates/Test plan.md
+++ b/.gitlab/issue_templates/Test plan.md
@@ -64,7 +64,7 @@ Some features might be simple enough that they only involve one Component, while
more complex features could involve multiple or even all.
Example (from https://gitlab.com/gitlab-org/gitlab-ce/issues/50353):
-* Respository is
+* Repository is
* Intuitive
* It's easy to select the desired file template
* It doesn't require unnecessary actions to save the change
@@ -93,4 +93,4 @@ When adding new automated tests, please keep [testing levels](https://docs.gitla
in mind.
-->
-/label ~Quality ~"test plan" \ No newline at end of file
+/label ~Quality ~"test plan"
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 6e5296e231e..54ea014a679 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,13 @@
documentation](doc/development/changelog.md) for instructions on adding your own
entry.
+## 11.4.6 (2018-11-18)
+
+### Security (1 change)
+
+- Escape user fullname while rendering autocomplete template to prevent XSS.
+
+
## 11.4.5 (2018-11-04)
### Fixed (4 changes, 1 of them is from the community)
@@ -271,6 +278,13 @@ entry.
- Check frozen string in style builds. (gfyoung)
+## 11.3.10 (2018-11-18)
+
+### Security (1 change)
+
+- Escape user fullname while rendering autocomplete template to prevent XSS.
+
+
## 11.3.9 (2018-10-31)
### Security (1 change)
diff --git a/GITALY_SERVER_VERSION b/GITALY_SERVER_VERSION
index e491d6243c6..244fb7efb4c 100644
--- a/GITALY_SERVER_VERSION
+++ b/GITALY_SERVER_VERSION
@@ -1 +1 @@
-0.132.0
+0.133.0
diff --git a/Gemfile b/Gemfile
index 2a228b326ad..2c0eb0cbce4 100644
--- a/Gemfile
+++ b/Gemfile
@@ -4,10 +4,9 @@ def rails5?
end
gem_versions = {}
-gem_versions['activerecord_sane_schema_dumper'] = rails5? ? '1.0' : '0.2'
-gem_versions['default_value_for'] = rails5? ? '~> 3.0.5' : '~> 3.0.0'
-gem_versions['rails'] = rails5? ? '5.0.7' : '4.2.10'
-gem_versions['rails-i18n'] = rails5? ? '~> 5.1' : '~> 4.0.9'
+gem_versions['activerecord_sane_schema_dumper'] = rails5? ? '1.0' : '0.2'
+gem_versions['rails'] = rails5? ? '5.0.7' : '4.2.10'
+gem_versions['rails-i18n'] = rails5? ? '~> 5.1' : '~> 4.0.9'
# --- The end of special code for migrating to Rails 5.0 ---
source 'https://rubygems.org'
@@ -15,13 +14,20 @@ source 'https://rubygems.org'
gem 'rails', gem_versions['rails']
gem 'rails-deprecated_sanitizer', '~> 1.0.3'
+# Improves copy-on-write performance for MRI
+gem 'nakayoshi_fork', '~> 0.0.4'
+
# Responders respond_to and respond_with
gem 'responders', '~> 2.0'
gem 'sprockets', '~> 3.7.0'
# Default values for AR models
-gem 'default_value_for', gem_versions['default_value_for']
+if rails5?
+ gem 'gitlab-default_value_for', '~> 3.1.1', require: 'default_value_for'
+else
+ gem 'default_value_for', '~> 3.0.0'
+end
# Supported DBs
gem 'mysql2', '~> 0.4.10', group: :mysql
@@ -133,7 +139,7 @@ gem 'rdoc', '~> 6.0'
gem 'org-ruby', '~> 0.9.12'
gem 'creole', '~> 0.5.0'
gem 'wikicloth', '0.8.1'
-gem 'asciidoctor', '~> 1.5.6'
+gem 'asciidoctor', '~> 1.5.8'
gem 'asciidoctor-plantuml', '0.0.8'
gem 'rouge', '~> 3.1'
gem 'truncato', '~> 0.7.9'
@@ -223,7 +229,7 @@ gem 'slack-notifier', '~> 1.5.1'
gem 'hangouts-chat', '~> 0.0.5'
# Asana integration
-gem 'asana', '~> 0.6.0'
+gem 'asana', '~> 0.8.1'
# FogBugz integration
gem 'ruby-fogbugz', '~> 0.2.1'
@@ -383,7 +389,7 @@ group :test do
gem 'rails-controller-testing' if rails5? # Rails5 only gem.
gem 'test_after_commit', '~> 1.1' unless rails5? # Remove this gem when migrated to rails 5.0. It's been integrated to rails 5.0.
gem 'sham_rack', '~> 1.3.6'
- gem 'concurrent-ruby', '~> 1.0.5'
+ gem 'concurrent-ruby', '~> 1.1'
gem 'test-prof', '~> 0.2.5'
gem 'rspec_junit_formatter'
end
diff --git a/Gemfile.lock b/Gemfile.lock
index e21a1b85457..380f1dbc89f 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -53,12 +53,12 @@ GEM
aes_key_wrap (1.0.1)
akismet (2.0.0)
arel (7.1.4)
- asana (0.6.0)
+ asana (0.8.1)
faraday (~> 0.9)
faraday_middleware (~> 0.9)
faraday_middleware-multi_json (~> 0.0)
oauth2 (~> 1.0)
- asciidoctor (1.5.6.2)
+ asciidoctor (1.5.8)
asciidoctor-plantuml (0.0.8)
asciidoctor (~> 1.5)
ast (2.4.0)
@@ -128,9 +128,9 @@ GEM
concord (0.1.5)
adamantium (~> 0.2.0)
equalizer (~> 0.0.9)
- concurrent-ruby (1.0.5)
- concurrent-ruby-ext (1.0.5)
- concurrent-ruby (= 1.0.5)
+ concurrent-ruby (1.1.3)
+ concurrent-ruby-ext (1.1.3)
+ concurrent-ruby (= 1.1.3)
connection_pool (2.2.2)
crack (0.4.3)
safe_yaml (~> 1.0.0)
@@ -146,8 +146,6 @@ GEM
html-pipeline
declarative (0.0.10)
declarative-option (0.1.0)
- default_value_for (3.0.5)
- activerecord (>= 3.2.0, < 5.2)
descendants_tracker (0.0.4)
thread_safe (~> 0.3, >= 0.3.1)
device_detector (1.0.0)
@@ -277,6 +275,8 @@ GEM
gitaly-proto (0.123.0)
grpc (~> 1.0)
github-markup (1.7.0)
+ gitlab-default_value_for (3.1.1)
+ activerecord (>= 3.2.0, < 6.0)
gitlab-markup (1.6.5)
gitlab-sidekiq-fetcher (0.3.0)
sidekiq (~> 5)
@@ -379,7 +379,7 @@ GEM
json (~> 1.8)
multi_xml (>= 0.5.2)
httpclient (2.8.3)
- i18n (1.1.0)
+ i18n (1.1.1)
concurrent-ruby (~> 1.0)
icalendar (2.4.1)
ice_nine (0.11.2)
@@ -444,7 +444,7 @@ GEM
activesupport (>= 4)
railties (>= 4)
request_store (~> 1.0)
- loofah (2.2.2)
+ loofah (2.2.3)
crass (~> 1.0.2)
nokogiri (>= 1.5.9)
mail (2.7.0)
@@ -453,7 +453,7 @@ GEM
memoist (0.16.0)
memoizable (0.4.2)
thread_safe (~> 0.3, >= 0.3.1)
- method_source (0.9.0)
+ method_source (0.9.2)
mime-types (3.2.2)
mime-types-data (~> 3.2015)
mime-types-data (3.2018.0812)
@@ -470,11 +470,12 @@ GEM
mustermann-grape (1.0.0)
mustermann (~> 1.0.0)
mysql2 (0.4.10)
+ nakayoshi_fork (0.0.4)
net-ldap (0.16.0)
net-ssh (5.0.1)
netrc (0.11.0)
nio4r (2.3.1)
- nokogiri (1.8.4)
+ nokogiri (1.8.5)
mini_portile2 (~> 2.3.0)
nokogumbo (1.5.0)
nokogiri
@@ -602,7 +603,7 @@ GEM
get_process_mem (~> 0.2)
puma (>= 2.7, < 4)
pyu-ruby-sasl (0.0.3.3)
- rack (2.0.5)
+ rack (2.0.6)
rack-accept (0.4.5)
rack (>= 0.4)
rack-attack (4.4.1)
@@ -766,8 +767,8 @@ GEM
ruby-progressbar (1.9.0)
ruby-saml (1.7.2)
nokogiri (>= 1.5.10)
- ruby_parser (3.9.0)
- sexp_processor (~> 4.1)
+ ruby_parser (3.11.0)
+ sexp_processor (~> 4.9)
rubyntlm (0.6.2)
rubypants (0.2.0)
rubyzip (1.2.2)
@@ -807,7 +808,7 @@ GEM
sentry-raven (2.7.2)
faraday (>= 0.7.6, < 1.0)
settingslogic (2.0.9)
- sexp_processor (4.9.0)
+ sexp_processor (4.11.0)
sham_rack (1.3.6)
rack
shoulda-matchers (3.1.2)
@@ -941,8 +942,8 @@ DEPENDENCIES
acts-as-taggable-on (~> 5.0)
addressable (~> 2.5.2)
akismet (~> 2.0)
- asana (~> 0.6.0)
- asciidoctor (~> 1.5.6)
+ asana (~> 0.8.1)
+ asciidoctor (~> 1.5.8)
asciidoctor-plantuml (= 0.0.8)
attr_encrypted (~> 3.1.0)
awesome_print
@@ -966,12 +967,11 @@ DEPENDENCIES
chronic (~> 0.10.2)
chronic_duration (~> 0.10.6)
commonmarker (~> 0.17)
- concurrent-ruby (~> 1.0.5)
+ concurrent-ruby (~> 1.1)
connection_pool (~> 2.0)
creole (~> 0.5.0)
database_cleaner (~> 1.5.0)
deckar01-task_list (= 2.0.0)
- default_value_for (~> 3.0.5)
device_detector
devise (~> 4.4)
devise-two-factor (~> 3.0.0)
@@ -1007,6 +1007,7 @@ DEPENDENCIES
gettext_i18n_rails_js (~> 1.3)
gitaly-proto (~> 0.123.0)
github-markup (~> 1.7.0)
+ gitlab-default_value_for (~> 3.1.1)
gitlab-markup (~> 1.6.5)
gitlab-sidekiq-fetcher
gitlab-styles (~> 2.4)
@@ -1051,6 +1052,7 @@ DEPENDENCIES
mini_magick
minitest (~> 5.7.0)
mysql2 (~> 0.4.10)
+ nakayoshi_fork (~> 0.0.4)
net-ldap
net-ssh (~> 5.0)
nokogiri (~> 1.8.2)
diff --git a/Gemfile.rails4.lock b/Gemfile.rails4.lock
index fea3102b8d6..ead404c5f27 100644
--- a/Gemfile.rails4.lock
+++ b/Gemfile.rails4.lock
@@ -50,12 +50,12 @@ GEM
aes_key_wrap (1.0.1)
akismet (2.0.0)
arel (6.0.4)
- asana (0.6.0)
+ asana (0.8.1)
faraday (~> 0.9)
faraday_middleware (~> 0.9)
faraday_middleware-multi_json (~> 0.0)
oauth2 (~> 1.0)
- asciidoctor (1.5.6.2)
+ asciidoctor (1.5.8)
asciidoctor-plantuml (0.0.8)
asciidoctor (~> 1.5)
ast (2.4.0)
@@ -125,9 +125,9 @@ GEM
concord (0.1.5)
adamantium (~> 0.2.0)
equalizer (~> 0.0.9)
- concurrent-ruby (1.0.5)
- concurrent-ruby-ext (1.0.5)
- concurrent-ruby (= 1.0.5)
+ concurrent-ruby (1.1.3)
+ concurrent-ruby-ext (1.1.3)
+ concurrent-ruby (= 1.1.3)
connection_pool (2.2.2)
crack (0.4.3)
safe_yaml (~> 1.0.0)
@@ -441,7 +441,7 @@ GEM
activesupport (>= 4)
railties (>= 4)
request_store (~> 1.0)
- loofah (2.2.2)
+ loofah (2.2.3)
crass (~> 1.0.2)
nokogiri (>= 1.5.9)
mail (2.7.0)
@@ -467,10 +467,11 @@ GEM
mustermann-grape (1.0.0)
mustermann (~> 1.0.0)
mysql2 (0.4.10)
+ nakayoshi_fork (0.0.4)
net-ldap (0.16.0)
net-ssh (5.0.1)
netrc (0.11.0)
- nokogiri (1.8.4)
+ nokogiri (1.8.5)
mini_portile2 (~> 2.3.0)
nokogumbo (1.5.0)
nokogiri
@@ -758,8 +759,8 @@ GEM
ruby-progressbar (1.9.0)
ruby-saml (1.7.2)
nokogiri (>= 1.5.10)
- ruby_parser (3.9.0)
- sexp_processor (~> 4.1)
+ ruby_parser (3.11.0)
+ sexp_processor (~> 4.9)
rubyntlm (0.6.2)
rubypants (0.2.0)
rubyzip (1.2.2)
@@ -799,7 +800,7 @@ GEM
sentry-raven (2.7.2)
faraday (>= 0.7.6, < 1.0)
settingslogic (2.0.9)
- sexp_processor (4.9.0)
+ sexp_processor (4.11.0)
sham_rack (1.3.6)
rack
shoulda-matchers (3.1.2)
@@ -932,8 +933,8 @@ DEPENDENCIES
acts-as-taggable-on (~> 5.0)
addressable (~> 2.5.2)
akismet (~> 2.0)
- asana (~> 0.6.0)
- asciidoctor (~> 1.5.6)
+ asana (~> 0.8.1)
+ asciidoctor (~> 1.5.8)
asciidoctor-plantuml (= 0.0.8)
attr_encrypted (~> 3.1.0)
awesome_print
@@ -957,7 +958,7 @@ DEPENDENCIES
chronic (~> 0.10.2)
chronic_duration (~> 0.10.6)
commonmarker (~> 0.17)
- concurrent-ruby (~> 1.0.5)
+ concurrent-ruby (~> 1.1)
connection_pool (~> 2.0)
creole (~> 0.5.0)
database_cleaner (~> 1.5.0)
@@ -1042,6 +1043,7 @@ DEPENDENCIES
mini_magick
minitest (~> 5.7.0)
mysql2 (~> 0.4.10)
+ nakayoshi_fork (~> 0.0.4)
net-ldap
net-ssh (~> 5.0)
nokogiri (~> 1.8.2)
diff --git a/PROCESS.md b/PROCESS.md
index 5fc2c4cf1df..aadd6a321f0 100644
--- a/PROCESS.md
+++ b/PROCESS.md
@@ -95,6 +95,12 @@ picked into the stable branches) up to the 19th of the month. Such merge
requests should have the ~"feature flag" label assigned, and don't require a
corresponding exception request to be created.
+In order to build the final package and present the feature for self-hosted
+customers, the feature flag should be removed. This should happen before the
+22nd, ideally _at least_ 2 days before. That means MRs with feature
+flags being picked at the 19th would have a quite tight schedule, so picking
+these _earlier_ is preferable.
+
While rare, release managers may decide to reject picking a change into a stable
branch, even when feature flags are used. This might be necessary if the changes
are deemed problematic, too invasive, or there simply isn't enough time to
diff --git a/app/assets/javascripts/badges/components/badge.vue b/app/assets/javascripts/badges/components/badge.vue
index 8512bf9dd7b..ca1662313c2 100644
--- a/app/assets/javascripts/badges/components/badge.vue
+++ b/app/assets/javascripts/badges/components/badge.vue
@@ -1,7 +1,7 @@
<script>
import Icon from '~/vue_shared/components/icon.vue';
import Tooltip from '~/vue_shared/directives/tooltip';
-import { GlLoadingIcon } from '@gitlab-org/gitlab-ui';
+import { GlLoadingIcon } from '@gitlab/ui';
export default {
name: 'Badge',
diff --git a/app/assets/javascripts/badges/components/badge_form.vue b/app/assets/javascripts/badges/components/badge_form.vue
index 47e6e618219..0eff922d93c 100644
--- a/app/assets/javascripts/badges/components/badge_form.vue
+++ b/app/assets/javascripts/badges/components/badge_form.vue
@@ -4,7 +4,7 @@ import { mapActions, mapState } from 'vuex';
import createFlash from '~/flash';
import { s__, sprintf } from '~/locale';
import LoadingButton from '~/vue_shared/components/loading_button.vue';
-import { GlLoadingIcon } from '@gitlab-org/gitlab-ui';
+import { GlLoadingIcon } from '@gitlab/ui';
import createEmptyBadge from '../empty_badge';
import Badge from './badge.vue';
diff --git a/app/assets/javascripts/badges/components/badge_list.vue b/app/assets/javascripts/badges/components/badge_list.vue
index ab518820378..5b64ea1080c 100644
--- a/app/assets/javascripts/badges/components/badge_list.vue
+++ b/app/assets/javascripts/badges/components/badge_list.vue
@@ -1,6 +1,6 @@
<script>
import { mapState } from 'vuex';
-import { GlLoadingIcon } from '@gitlab-org/gitlab-ui';
+import { GlLoadingIcon } from '@gitlab/ui';
import BadgeListRow from './badge_list_row.vue';
import { GROUP_BADGE } from '../constants';
diff --git a/app/assets/javascripts/badges/components/badge_list_row.vue b/app/assets/javascripts/badges/components/badge_list_row.vue
index f28eff18f03..d01465232a7 100644
--- a/app/assets/javascripts/badges/components/badge_list_row.vue
+++ b/app/assets/javascripts/badges/components/badge_list_row.vue
@@ -2,7 +2,7 @@
import { mapActions, mapState } from 'vuex';
import { s__ } from '~/locale';
import Icon from '~/vue_shared/components/icon.vue';
-import { GlLoadingIcon } from '@gitlab-org/gitlab-ui';
+import { GlLoadingIcon } from '@gitlab/ui';
import { PROJECT_BADGE } from '../constants';
import Badge from './badge.vue';
diff --git a/app/assets/javascripts/boards/components/board_list.vue b/app/assets/javascripts/boards/components/board_list.vue
index 5e28fc396ab..a04b828e277 100644
--- a/app/assets/javascripts/boards/components/board_list.vue
+++ b/app/assets/javascripts/boards/components/board_list.vue
@@ -1,6 +1,6 @@
<script>
import Sortable from 'sortablejs';
-import { GlLoadingIcon } from '@gitlab-org/gitlab-ui';
+import { GlLoadingIcon } from '@gitlab/ui';
import boardNewIssue from './board_new_issue.vue';
import boardCard from './board_card.vue';
import eventHub from '../eventhub';
diff --git a/app/assets/javascripts/boards/components/board_new_issue.vue b/app/assets/javascripts/boards/components/board_new_issue.vue
index ee3dc38bca6..2a96d1443e1 100644
--- a/app/assets/javascripts/boards/components/board_new_issue.vue
+++ b/app/assets/javascripts/boards/components/board_new_issue.vue
@@ -1,6 +1,6 @@
<script>
import $ from 'jquery';
-import { GlButton } from '@gitlab-org/gitlab-ui';
+import { GlButton } from '@gitlab/ui';
import eventHub from '../eventhub';
import ProjectSelect from './project_select.vue';
import ListIssue from '../models/issue';
diff --git a/app/assets/javascripts/boards/components/issue_card_inner.vue b/app/assets/javascripts/boards/components/issue_card_inner.vue
index 2315a48a306..48c46ae32f1 100644
--- a/app/assets/javascripts/boards/components/issue_card_inner.vue
+++ b/app/assets/javascripts/boards/components/issue_card_inner.vue
@@ -1,5 +1,5 @@
<script>
-import { GlTooltipDirective } from '@gitlab-org/gitlab-ui';
+import { GlTooltipDirective } from '@gitlab/ui';
import { sprintf, __ } from '~/locale';
import Icon from '~/vue_shared/components/icon.vue';
import TooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate.vue';
@@ -231,7 +231,7 @@ export default {
>
<span class="js-assignee-tooltip">
<span class="bold d-block">Assignee</span>
- {{ assignee.name }}
+ {{ assignee.name }}
<span class="text-white-50">@{{ assignee.username }}</span>
</span>
</user-avatar-link>
diff --git a/app/assets/javascripts/boards/components/issue_due_date.vue b/app/assets/javascripts/boards/components/issue_due_date.vue
index 025ef7e9743..d6c87132843 100644
--- a/app/assets/javascripts/boards/components/issue_due_date.vue
+++ b/app/assets/javascripts/boards/components/issue_due_date.vue
@@ -1,6 +1,6 @@
<script>
import dateFormat from 'dateformat';
-import { GlTooltip } from '@gitlab-org/gitlab-ui';
+import { GlTooltip } from '@gitlab/ui';
import Icon from '~/vue_shared/components/icon.vue';
import { __ } from '~/locale';
import { getDayDifference, getTimeago, dateInWords } from '~/lib/utils/datetime_utility';
diff --git a/app/assets/javascripts/boards/components/issue_time_estimate.vue b/app/assets/javascripts/boards/components/issue_time_estimate.vue
index efc7daf7812..a9803c8ab5d 100644
--- a/app/assets/javascripts/boards/components/issue_time_estimate.vue
+++ b/app/assets/javascripts/boards/components/issue_time_estimate.vue
@@ -1,5 +1,5 @@
<script>
-import { GlTooltip } from '@gitlab-org/gitlab-ui';
+import { GlTooltip } from '@gitlab/ui';
import Icon from '~/vue_shared/components/icon.vue';
import { parseSeconds, stringifyTime } from '~/lib/utils/datetime_utility';
diff --git a/app/assets/javascripts/boards/components/modal/index.vue b/app/assets/javascripts/boards/components/modal/index.vue
index fdd1346d4c7..fc0e3e46b88 100644
--- a/app/assets/javascripts/boards/components/modal/index.vue
+++ b/app/assets/javascripts/boards/components/modal/index.vue
@@ -6,7 +6,7 @@ import ModalList from './list.vue';
import ModalFooter from './footer.vue';
import EmptyState from './empty_state.vue';
import ModalStore from '../../stores/modal_store';
-import { GlLoadingIcon } from '@gitlab-org/gitlab-ui';
+import { GlLoadingIcon } from '@gitlab/ui';
export default {
components: {
diff --git a/app/assets/javascripts/boards/components/modal/lists_dropdown.vue b/app/assets/javascripts/boards/components/modal/lists_dropdown.vue
index 20665f903d5..c502e32d169 100644
--- a/app/assets/javascripts/boards/components/modal/lists_dropdown.vue
+++ b/app/assets/javascripts/boards/components/modal/lists_dropdown.vue
@@ -1,5 +1,5 @@
<script>
-import { GlLink } from '@gitlab-org/gitlab-ui';
+import { GlLink } from '@gitlab/ui';
import Icon from '~/vue_shared/components/icon.vue';
import ModalStore from '../../stores/modal_store';
import boardsStore from '../../stores/boards_store';
diff --git a/app/assets/javascripts/boards/components/project_select.vue b/app/assets/javascripts/boards/components/project_select.vue
index 503417644fa..83e6e237757 100644
--- a/app/assets/javascripts/boards/components/project_select.vue
+++ b/app/assets/javascripts/boards/components/project_select.vue
@@ -2,7 +2,7 @@
import $ from 'jquery';
import _ from 'underscore';
import Icon from '~/vue_shared/components/icon.vue';
-import { GlLoadingIcon } from '@gitlab-org/gitlab-ui';
+import { GlLoadingIcon } from '@gitlab/ui';
import eventHub from '../eventhub';
import Api from '../../api';
diff --git a/app/assets/javascripts/deploy_keys/components/action_btn.vue b/app/assets/javascripts/deploy_keys/components/action_btn.vue
index ea74fd27ff6..4acd21376bf 100644
--- a/app/assets/javascripts/deploy_keys/components/action_btn.vue
+++ b/app/assets/javascripts/deploy_keys/components/action_btn.vue
@@ -1,5 +1,5 @@
<script>
-import { GlLoadingIcon } from '@gitlab-org/gitlab-ui';
+import { GlLoadingIcon } from '@gitlab/ui';
import eventHub from '../eventhub';
export default {
diff --git a/app/assets/javascripts/deploy_keys/components/app.vue b/app/assets/javascripts/deploy_keys/components/app.vue
index 631a9673b3e..1d2ac59e20a 100644
--- a/app/assets/javascripts/deploy_keys/components/app.vue
+++ b/app/assets/javascripts/deploy_keys/components/app.vue
@@ -6,7 +6,7 @@ import eventHub from '../eventhub';
import DeployKeysService from '../service';
import DeployKeysStore from '../store';
import KeysPanel from './keys_panel.vue';
-import { GlLoadingIcon } from '@gitlab-org/gitlab-ui';
+import { GlLoadingIcon } from '@gitlab/ui';
export default {
components: {
diff --git a/app/assets/javascripts/diff_notes/components/jump_to_discussion.js b/app/assets/javascripts/diff_notes/components/jump_to_discussion.js
index c0c21416275..8542a6e718a 100644
--- a/app/assets/javascripts/diff_notes/components/jump_to_discussion.js
+++ b/app/assets/javascripts/diff_notes/components/jump_to_discussion.js
@@ -112,7 +112,7 @@ const JumpToDiscussion = Vue.extend({
if (!hasDiscussionsToJumpTo) {
// If there are no discussions to jump to on the current page,
- // switch to the notes tab and jump to the first disucssion there.
+ // switch to the notes tab and jump to the first discussion there.
window.mrTabs.activateTab('show');
activeTab = 'show';
jumpToFirstDiscussion = true;
diff --git a/app/assets/javascripts/diffs/components/app.vue b/app/assets/javascripts/diffs/components/app.vue
index b885fa49365..881febedb7c 100644
--- a/app/assets/javascripts/diffs/components/app.vue
+++ b/app/assets/javascripts/diffs/components/app.vue
@@ -3,7 +3,7 @@ import { mapState, mapGetters, mapActions } from 'vuex';
import Icon from '~/vue_shared/components/icon.vue';
import { __ } from '~/locale';
import createFlash from '~/flash';
-import { GlLoadingIcon } from '@gitlab-org/gitlab-ui';
+import { GlLoadingIcon } from '@gitlab/ui';
import eventHub from '../../notes/event_hub';
import CompareVersions from './compare_versions.vue';
import DiffFile from './diff_file.vue';
diff --git a/app/assets/javascripts/diffs/components/compare_versions.vue b/app/assets/javascripts/diffs/components/compare_versions.vue
index a5b87dfc2d9..f50cb94a18f 100644
--- a/app/assets/javascripts/diffs/components/compare_versions.vue
+++ b/app/assets/javascripts/diffs/components/compare_versions.vue
@@ -1,6 +1,6 @@
<script>
import { mapActions, mapGetters, mapState } from 'vuex';
-import Tooltip from '@gitlab-org/gitlab-ui/dist/directives/tooltip';
+import Tooltip from '@gitlab/ui/dist/directives/tooltip';
import { __ } from '~/locale';
import { getParameterValues, mergeUrlParams } from '~/lib/utils/url_utility';
import Icon from '~/vue_shared/components/icon.vue';
diff --git a/app/assets/javascripts/diffs/components/diff_file.vue b/app/assets/javascripts/diffs/components/diff_file.vue
index 872131a5900..5da0bfb5bfe 100644
--- a/app/assets/javascripts/diffs/components/diff_file.vue
+++ b/app/assets/javascripts/diffs/components/diff_file.vue
@@ -3,7 +3,7 @@ import { mapActions, mapGetters, mapState } from 'vuex';
import _ from 'underscore';
import { __, sprintf } from '~/locale';
import createFlash from '~/flash';
-import { GlLoadingIcon } from '@gitlab-org/gitlab-ui';
+import { GlLoadingIcon } from '@gitlab/ui';
import DiffFileHeader from './diff_file_header.vue';
import DiffContent from './diff_content.vue';
diff --git a/app/assets/javascripts/diffs/components/diff_gutter_avatars.vue b/app/assets/javascripts/diffs/components/diff_gutter_avatars.vue
index 254bc235691..8f8c2a31c71 100644
--- a/app/assets/javascripts/diffs/components/diff_gutter_avatars.vue
+++ b/app/assets/javascripts/diffs/components/diff_gutter_avatars.vue
@@ -3,7 +3,7 @@ import { mapActions } from 'vuex';
import Icon from '~/vue_shared/components/icon.vue';
import { pluralize, truncate } from '~/lib/utils/text_utility';
import UserAvatarImage from '~/vue_shared/components/user_avatar/user_avatar_image.vue';
-import { GlTooltipDirective } from '@gitlab-org/gitlab-ui';
+import { GlTooltipDirective } from '@gitlab/ui';
import { COUNT_OF_AVATARS_IN_GUTTER, LENGTH_OF_AVATAR_TOOLTIP } from '../constants';
export default {
diff --git a/app/assets/javascripts/diffs/components/tree_list.vue b/app/assets/javascripts/diffs/components/tree_list.vue
index ff1eb23cea3..1f82eeae6cb 100644
--- a/app/assets/javascripts/diffs/components/tree_list.vue
+++ b/app/assets/javascripts/diffs/components/tree_list.vue
@@ -1,6 +1,6 @@
<script>
import { mapActions, mapGetters, mapState } from 'vuex';
-import { GlTooltipDirective } from '@gitlab-org/gitlab-ui';
+import { GlTooltipDirective } from '@gitlab/ui';
import { convertPermissionToBoolean } from '~/lib/utils/common_utils';
import Icon from '~/vue_shared/components/icon.vue';
import FileRow from '~/vue_shared/components/file_row.vue';
diff --git a/app/assets/javascripts/diffs/store/getters.js b/app/assets/javascripts/diffs/store/getters.js
index 05e32e3c1f1..6a87b712b48 100644
--- a/app/assets/javascripts/diffs/store/getters.js
+++ b/app/assets/javascripts/diffs/store/getters.js
@@ -23,7 +23,7 @@ export const diffHasAllExpandedDiscussions = (state, getters) => diff => {
};
/**
- * Checks if the diff has all discussions collpased
+ * Checks if the diff has all discussions collapsed
* @param {Object} diff
* @returns {Boolean}
*/
diff --git a/app/assets/javascripts/environments/components/container.vue b/app/assets/javascripts/environments/components/container.vue
index a48f5fcb7d6..6c0b5c1f427 100644
--- a/app/assets/javascripts/environments/components/container.vue
+++ b/app/assets/javascripts/environments/components/container.vue
@@ -1,5 +1,5 @@
<script>
-import { GlLoadingIcon } from '@gitlab-org/gitlab-ui';
+import { GlLoadingIcon } from '@gitlab/ui';
import tablePagination from '../../vue_shared/components/table_pagination.vue';
import environmentTable from '../components/environments_table.vue';
diff --git a/app/assets/javascripts/environments/components/environment_actions.vue b/app/assets/javascripts/environments/components/environment_actions.vue
index 03c3ad0401f..b849772a82e 100644
--- a/app/assets/javascripts/environments/components/environment_actions.vue
+++ b/app/assets/javascripts/environments/components/environment_actions.vue
@@ -4,7 +4,7 @@ import { formatTime } from '~/lib/utils/datetime_utility';
import Icon from '~/vue_shared/components/icon.vue';
import eventHub from '../event_hub';
import tooltip from '../../vue_shared/directives/tooltip';
-import { GlLoadingIcon } from '@gitlab-org/gitlab-ui';
+import { GlLoadingIcon } from '@gitlab/ui';
export default {
directives: {
diff --git a/app/assets/javascripts/environments/components/environment_external_url.vue b/app/assets/javascripts/environments/components/environment_external_url.vue
index 1e8a892c0b8..af537cfb991 100644
--- a/app/assets/javascripts/environments/components/environment_external_url.vue
+++ b/app/assets/javascripts/environments/components/environment_external_url.vue
@@ -1,5 +1,5 @@
<script>
-import { GlTooltipDirective } from '@gitlab-org/gitlab-ui';
+import { GlTooltipDirective } from '@gitlab/ui';
import Icon from '~/vue_shared/components/icon.vue';
import { s__ } from '~/locale';
diff --git a/app/assets/javascripts/environments/components/environment_item.vue b/app/assets/javascripts/environments/components/environment_item.vue
index 50b0e9747ee..34d94490533 100644
--- a/app/assets/javascripts/environments/components/environment_item.vue
+++ b/app/assets/javascripts/environments/components/environment_item.vue
@@ -1,7 +1,7 @@
<script>
import Timeago from 'timeago.js';
import _ from 'underscore';
-import { GlTooltipDirective } from '@gitlab-org/gitlab-ui';
+import { GlTooltipDirective } from '@gitlab/ui';
import UserAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue';
import { humanize } from '~/lib/utils/text_utility';
import Icon from '~/vue_shared/components/icon.vue';
diff --git a/app/assets/javascripts/environments/components/environment_monitoring.vue b/app/assets/javascripts/environments/components/environment_monitoring.vue
index 7c723fa8979..ae4f07a71cd 100644
--- a/app/assets/javascripts/environments/components/environment_monitoring.vue
+++ b/app/assets/javascripts/environments/components/environment_monitoring.vue
@@ -2,7 +2,7 @@
/**
* Renders the Monitoring (Metrics) link in environments table.
*/
-import { GlButton, GlTooltipDirective } from '@gitlab-org/gitlab-ui';
+import { GlButton, GlTooltipDirective } from '@gitlab/ui';
import Icon from '~/vue_shared/components/icon.vue';
export default {
diff --git a/app/assets/javascripts/environments/components/environment_rollback.vue b/app/assets/javascripts/environments/components/environment_rollback.vue
index 298469e6482..46c77dca871 100644
--- a/app/assets/javascripts/environments/components/environment_rollback.vue
+++ b/app/assets/javascripts/environments/components/environment_rollback.vue
@@ -6,7 +6,7 @@
* Makes a post request when the button is clicked.
*/
import { s__ } from '~/locale';
-import { GlTooltipDirective, GlLoadingIcon } from '@gitlab-org/gitlab-ui';
+import { GlTooltipDirective, GlLoadingIcon } from '@gitlab/ui';
import Icon from '~/vue_shared/components/icon.vue';
import eventHub from '../event_hub';
@@ -63,7 +63,7 @@ export default {
>
<icon
v-if="isLastDeployment"
- name="repeat"
+ name="repeat"
/>
<icon
v-else
diff --git a/app/assets/javascripts/environments/components/environment_stop.vue b/app/assets/javascripts/environments/components/environment_stop.vue
index 327c96a93e9..efecc128368 100644
--- a/app/assets/javascripts/environments/components/environment_stop.vue
+++ b/app/assets/javascripts/environments/components/environment_stop.vue
@@ -5,7 +5,7 @@
*/
import $ from 'jquery';
-import { GlTooltipDirective } from '@gitlab-org/gitlab-ui';
+import { GlTooltipDirective } from '@gitlab/ui';
import Icon from '~/vue_shared/components/icon.vue';
import { s__ } from '~/locale';
import eventHub from '../event_hub';
diff --git a/app/assets/javascripts/environments/components/environment_terminal_button.vue b/app/assets/javascripts/environments/components/environment_terminal_button.vue
index b8b909f350c..83727caad16 100644
--- a/app/assets/javascripts/environments/components/environment_terminal_button.vue
+++ b/app/assets/javascripts/environments/components/environment_terminal_button.vue
@@ -3,7 +3,7 @@
* Renders a terminal button to open a web terminal.
* Used in environments table.
*/
-import { GlTooltipDirective } from '@gitlab-org/gitlab-ui';
+import { GlTooltipDirective } from '@gitlab/ui';
import Icon from '~/vue_shared/components/icon.vue';
export default {
diff --git a/app/assets/javascripts/environments/components/environments_table.vue b/app/assets/javascripts/environments/components/environments_table.vue
index c03d4f29ff9..4eae4eec394 100644
--- a/app/assets/javascripts/environments/components/environments_table.vue
+++ b/app/assets/javascripts/environments/components/environments_table.vue
@@ -2,7 +2,7 @@
/**
* Render environments table.
*/
-import { GlLoadingIcon } from '@gitlab-org/gitlab-ui';
+import { GlLoadingIcon } from '@gitlab/ui';
import environmentItem from './environment_item.vue';
export default {
diff --git a/app/assets/javascripts/environments/components/stop_environment_modal.vue b/app/assets/javascripts/environments/components/stop_environment_modal.vue
index 6397f6caf1b..2ebc7b5b951 100644
--- a/app/assets/javascripts/environments/components/stop_environment_modal.vue
+++ b/app/assets/javascripts/environments/components/stop_environment_modal.vue
@@ -1,5 +1,5 @@
<script>
-import { GlTooltipDirective } from '@gitlab-org/gitlab-ui';
+import { GlTooltipDirective } from '@gitlab/ui';
import GlModal from '~/vue_shared/components/gl_modal.vue';
import { s__, sprintf } from '~/locale';
import LoadingButton from '~/vue_shared/components/loading_button.vue';
diff --git a/app/assets/javascripts/filtered_search/dropdown_emoji.js b/app/assets/javascripts/filtered_search/dropdown_emoji.js
index af7936a92fb..d9a4d06b549 100644
--- a/app/assets/javascripts/filtered_search/dropdown_emoji.js
+++ b/app/assets/javascripts/filtered_search/dropdown_emoji.js
@@ -69,10 +69,13 @@ export default class DropdownEmoji extends FilteredSearchDropdown {
// Replace empty gl-emoji tag to real content
const dropdownItems = [...this.dropdown.querySelectorAll('.filter-dropdown-item')];
dropdownItems.forEach(dropdownItem => {
- const name = dropdownItem.querySelector('.js-data-value').innerText;
- const emojiTag = this.glEmojiTag(name);
- const emojiElement = dropdownItem.querySelector('gl-emoji');
- emojiElement.outerHTML = emojiTag;
+ const valueElement = dropdownItem.querySelector('.js-data-value');
+ if (valueElement !== null) {
+ const name = valueElement.innerText;
+ const emojiTag = this.glEmojiTag(name);
+ const emojiElement = dropdownItem.querySelector('gl-emoji');
+ emojiElement.outerHTML = emojiTag;
+ }
});
}
diff --git a/app/assets/javascripts/frequent_items/components/app.vue b/app/assets/javascripts/frequent_items/components/app.vue
index 159c0bdc992..1ed8254bc58 100644
--- a/app/assets/javascripts/frequent_items/components/app.vue
+++ b/app/assets/javascripts/frequent_items/components/app.vue
@@ -1,7 +1,7 @@
<script>
import { mapState, mapActions, mapGetters } from 'vuex';
import AccessorUtilities from '~/lib/utils/accessor';
-import { GlLoadingIcon } from '@gitlab-org/gitlab-ui';
+import { GlLoadingIcon } from '@gitlab/ui';
import eventHub from '../event_hub';
import store from '../store/';
import { FREQUENT_ITEMS, STORAGE_KEY } from '../constants';
diff --git a/app/assets/javascripts/gfm_auto_complete.js b/app/assets/javascripts/gfm_auto_complete.js
index 00b3d283570..6f8b73564d0 100644
--- a/app/assets/javascripts/gfm_auto_complete.js
+++ b/app/assets/javascripts/gfm_auto_complete.js
@@ -151,10 +151,16 @@ class GfmAutoComplete {
// Team Members
$input.atwho({
at: '@',
+ alias: 'users',
displayTpl(value) {
let tmpl = GfmAutoComplete.Loading.template;
- if (value.username != null) {
- tmpl = GfmAutoComplete.Members.template;
+ const { avatarTag, username, title } = value;
+ if (username != null) {
+ tmpl = GfmAutoComplete.Members.templateFunction({
+ avatarTag,
+ username,
+ title,
+ });
}
return tmpl;
},
@@ -565,8 +571,9 @@ GfmAutoComplete.Emoji = {
};
// Team Members
GfmAutoComplete.Members = {
- // eslint-disable-next-line no-template-curly-in-string
- template: '<li>${avatarTag} ${username} <small>${title}</small></li>',
+ templateFunction({ avatarTag, username, title }) {
+ return `<li>${avatarTag} ${username} <small>${_.escape(title)}</small></li>`;
+ },
};
GfmAutoComplete.Labels = {
template:
diff --git a/app/assets/javascripts/groups/components/app.vue b/app/assets/javascripts/groups/components/app.vue
index 2a4a39436e7..29dc2d6a8a3 100644
--- a/app/assets/javascripts/groups/components/app.vue
+++ b/app/assets/javascripts/groups/components/app.vue
@@ -8,7 +8,7 @@ import { HIDDEN_CLASS } from '~/lib/utils/constants';
import { getParameterByName } from '~/lib/utils/common_utils';
import { mergeUrlParams } from '~/lib/utils/url_utility';
-import { GlLoadingIcon } from '@gitlab-org/gitlab-ui';
+import { GlLoadingIcon } from '@gitlab/ui';
import eventHub from '../event_hub';
import { COMMON_STR, CONTENT_LIST_CLASS } from '../constants';
import groupsComponent from './groups.vue';
diff --git a/app/assets/javascripts/ide/components/branches/search_list.vue b/app/assets/javascripts/ide/components/branches/search_list.vue
index 358f1153de2..600e1063f89 100644
--- a/app/assets/javascripts/ide/components/branches/search_list.vue
+++ b/app/assets/javascripts/ide/components/branches/search_list.vue
@@ -2,7 +2,7 @@
import { mapActions, mapState } from 'vuex';
import _ from 'underscore';
import Icon from '~/vue_shared/components/icon.vue';
-import { GlLoadingIcon } from '@gitlab-org/gitlab-ui';
+import { GlLoadingIcon } from '@gitlab/ui';
import Item from './item.vue';
export default {
diff --git a/app/assets/javascripts/ide/components/error_message.vue b/app/assets/javascripts/ide/components/error_message.vue
index 2d9bd99e82a..11fc15871ac 100644
--- a/app/assets/javascripts/ide/components/error_message.vue
+++ b/app/assets/javascripts/ide/components/error_message.vue
@@ -1,6 +1,6 @@
<script>
import { mapActions } from 'vuex';
-import { GlLoadingIcon } from '@gitlab-org/gitlab-ui';
+import { GlLoadingIcon } from '@gitlab/ui';
export default {
components: {
diff --git a/app/assets/javascripts/ide/components/file_templates/dropdown.vue b/app/assets/javascripts/ide/components/file_templates/dropdown.vue
index 891f7d48b4c..81d8d0b5132 100644
--- a/app/assets/javascripts/ide/components/file_templates/dropdown.vue
+++ b/app/assets/javascripts/ide/components/file_templates/dropdown.vue
@@ -2,7 +2,7 @@
import $ from 'jquery';
import { mapActions, mapState } from 'vuex';
import DropdownButton from '~/vue_shared/components/dropdown/dropdown_button.vue';
-import { GlLoadingIcon } from '@gitlab-org/gitlab-ui';
+import { GlLoadingIcon } from '@gitlab/ui';
export default {
components: {
diff --git a/app/assets/javascripts/ide/components/ide_side_bar.vue b/app/assets/javascripts/ide/components/ide_side_bar.vue
index 364ab9426e0..6b4849eb6f9 100644
--- a/app/assets/javascripts/ide/components/ide_side_bar.vue
+++ b/app/assets/javascripts/ide/components/ide_side_bar.vue
@@ -1,6 +1,6 @@
<script>
import { mapState, mapGetters } from 'vuex';
-import { GlSkeletonLoading } from '@gitlab-org/gitlab-ui';
+import { GlSkeletonLoading } from '@gitlab/ui';
import IdeTree from './ide_tree.vue';
import ResizablePanel from './resizable_panel.vue';
import ActivityBar from './activity_bar.vue';
diff --git a/app/assets/javascripts/ide/components/ide_tree_list.vue b/app/assets/javascripts/ide/components/ide_tree_list.vue
index d2ff55a4ee3..12ed7f86b3d 100644
--- a/app/assets/javascripts/ide/components/ide_tree_list.vue
+++ b/app/assets/javascripts/ide/components/ide_tree_list.vue
@@ -1,7 +1,7 @@
<script>
import { mapActions, mapGetters, mapState } from 'vuex';
import Icon from '~/vue_shared/components/icon.vue';
-import { GlSkeletonLoading } from '@gitlab-org/gitlab-ui';
+import { GlSkeletonLoading } from '@gitlab/ui';
import FileRow from '~/vue_shared/components/file_row.vue';
import NavDropdown from './nav_dropdown.vue';
import FileRowExtra from './file_row_extra.vue';
diff --git a/app/assets/javascripts/ide/components/jobs/list.vue b/app/assets/javascripts/ide/components/jobs/list.vue
index 57da8b4e2cb..e3626f60899 100644
--- a/app/assets/javascripts/ide/components/jobs/list.vue
+++ b/app/assets/javascripts/ide/components/jobs/list.vue
@@ -1,6 +1,6 @@
<script>
import { mapActions } from 'vuex';
-import { GlLoadingIcon } from '@gitlab-org/gitlab-ui';
+import { GlLoadingIcon } from '@gitlab/ui';
import Stage from './stage.vue';
export default {
diff --git a/app/assets/javascripts/ide/components/jobs/stage.vue b/app/assets/javascripts/ide/components/jobs/stage.vue
index 5644759d2f9..e4fc78afaf2 100644
--- a/app/assets/javascripts/ide/components/jobs/stage.vue
+++ b/app/assets/javascripts/ide/components/jobs/stage.vue
@@ -1,5 +1,5 @@
<script>
-import { GlLoadingIcon } from '@gitlab-org/gitlab-ui';
+import { GlLoadingIcon } from '@gitlab/ui';
import tooltip from '../../../vue_shared/directives/tooltip';
import Icon from '../../../vue_shared/components/icon.vue';
import CiIcon from '../../../vue_shared/components/ci_icon.vue';
diff --git a/app/assets/javascripts/ide/components/merge_requests/list.vue b/app/assets/javascripts/ide/components/merge_requests/list.vue
index e4000f588bd..4df29590b85 100644
--- a/app/assets/javascripts/ide/components/merge_requests/list.vue
+++ b/app/assets/javascripts/ide/components/merge_requests/list.vue
@@ -3,7 +3,7 @@ import { mapActions, mapState } from 'vuex';
import _ from 'underscore';
import { __ } from '~/locale';
import Icon from '~/vue_shared/components/icon.vue';
-import { GlLoadingIcon } from '@gitlab-org/gitlab-ui';
+import { GlLoadingIcon } from '@gitlab/ui';
import Item from './item.vue';
import TokenedInput from '../shared/tokened_input.vue';
diff --git a/app/assets/javascripts/ide/components/pipelines/list.vue b/app/assets/javascripts/ide/components/pipelines/list.vue
index 16aec1decd6..36cfcac4186 100644
--- a/app/assets/javascripts/ide/components/pipelines/list.vue
+++ b/app/assets/javascripts/ide/components/pipelines/list.vue
@@ -1,7 +1,7 @@
<script>
import { mapActions, mapGetters, mapState } from 'vuex';
import _ from 'underscore';
-import { GlLoadingIcon } from '@gitlab-org/gitlab-ui';
+import { GlLoadingIcon } from '@gitlab/ui';
import { sprintf, __ } from '../../../locale';
import Icon from '../../../vue_shared/components/icon.vue';
import CiIcon from '../../../vue_shared/components/ci_icon.vue';
diff --git a/app/assets/javascripts/ide/components/preview/clientside.vue b/app/assets/javascripts/ide/components/preview/clientside.vue
index 0bd56ff6e9b..afc0cfca7d8 100644
--- a/app/assets/javascripts/ide/components/preview/clientside.vue
+++ b/app/assets/javascripts/ide/components/preview/clientside.vue
@@ -3,7 +3,7 @@ import { mapActions, mapGetters, mapState } from 'vuex';
import _ from 'underscore';
import { Manager } from 'smooshpack';
import { listen } from 'codesandbox-api';
-import { GlLoadingIcon } from '@gitlab-org/gitlab-ui';
+import { GlLoadingIcon } from '@gitlab/ui';
import Navigator from './navigator.vue';
import { packageJsonPath } from '../../constants';
import { createPathWithExt } from '../../utils';
diff --git a/app/assets/javascripts/ide/components/preview/navigator.vue b/app/assets/javascripts/ide/components/preview/navigator.vue
index af8959186f9..cc6fc595b74 100644
--- a/app/assets/javascripts/ide/components/preview/navigator.vue
+++ b/app/assets/javascripts/ide/components/preview/navigator.vue
@@ -1,7 +1,7 @@
<script>
import { listen } from 'codesandbox-api';
import Icon from '~/vue_shared/components/icon.vue';
-import { GlLoadingIcon } from '@gitlab-org/gitlab-ui';
+import { GlLoadingIcon } from '@gitlab/ui';
export default {
components: {
diff --git a/app/assets/javascripts/init_legacy_filters.js b/app/assets/javascripts/init_legacy_filters.js
deleted file mode 100644
index b6ff97d1279..00000000000
--- a/app/assets/javascripts/init_legacy_filters.js
+++ /dev/null
@@ -1,14 +0,0 @@
-/* eslint-disable no-new */
-import LabelsSelect from './labels_select';
-import subscriptionSelect from './subscription_select';
-import UsersSelect from './users_select';
-import issueStatusSelect from './issue_status_select';
-import MilestoneSelect from './milestone_select';
-
-export default () => {
- new UsersSelect();
- new LabelsSelect();
- new MilestoneSelect();
- issueStatusSelect();
- subscriptionSelect();
-};
diff --git a/app/assets/javascripts/jobs/components/artifacts_block.vue b/app/assets/javascripts/jobs/components/artifacts_block.vue
index 93c89411b4a..932675c0fc6 100644
--- a/app/assets/javascripts/jobs/components/artifacts_block.vue
+++ b/app/assets/javascripts/jobs/components/artifacts_block.vue
@@ -1,5 +1,5 @@
<script>
-import { GlLink } from '@gitlab-org/gitlab-ui';
+import { GlLink } from '@gitlab/ui';
import TimeagoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
import timeagoMixin from '~/vue_shared/mixins/timeago';
diff --git a/app/assets/javascripts/jobs/components/commit_block.vue b/app/assets/javascripts/jobs/components/commit_block.vue
index 06fe23fedce..9373dbebc8a 100644
--- a/app/assets/javascripts/jobs/components/commit_block.vue
+++ b/app/assets/javascripts/jobs/components/commit_block.vue
@@ -1,5 +1,5 @@
<script>
-import { GlLink } from '@gitlab-org/gitlab-ui';
+import { GlLink } from '@gitlab/ui';
import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
export default {
diff --git a/app/assets/javascripts/jobs/components/empty_state.vue b/app/assets/javascripts/jobs/components/empty_state.vue
index be7425c2d25..afc4d931a68 100644
--- a/app/assets/javascripts/jobs/components/empty_state.vue
+++ b/app/assets/javascripts/jobs/components/empty_state.vue
@@ -1,5 +1,5 @@
<script>
-import { GlLink } from '@gitlab-org/gitlab-ui';
+import { GlLink } from '@gitlab/ui';
export default {
components: {
diff --git a/app/assets/javascripts/jobs/components/erased_block.vue b/app/assets/javascripts/jobs/components/erased_block.vue
index d80e905c68e..712f564b065 100644
--- a/app/assets/javascripts/jobs/components/erased_block.vue
+++ b/app/assets/javascripts/jobs/components/erased_block.vue
@@ -1,6 +1,6 @@
<script>
import _ from 'underscore';
-import { GlLink } from '@gitlab-org/gitlab-ui';
+import { GlLink } from '@gitlab/ui';
import TimeagoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
export default {
diff --git a/app/assets/javascripts/jobs/components/job_app.vue b/app/assets/javascripts/jobs/components/job_app.vue
index 90216b04e92..ecb809ca4de 100644
--- a/app/assets/javascripts/jobs/components/job_app.vue
+++ b/app/assets/javascripts/jobs/components/job_app.vue
@@ -1,7 +1,7 @@
<script>
import _ from 'underscore';
import { mapGetters, mapState, mapActions } from 'vuex';
-import { GlLoadingIcon } from '@gitlab-org/gitlab-ui';
+import { GlLoadingIcon } from '@gitlab/ui';
import { isScrolledToBottom } from '~/lib/utils/scroll_utils';
import { polyfillSticky } from '~/lib/utils/sticky';
import bp from '~/breakpoints';
diff --git a/app/assets/javascripts/jobs/components/job_container_item.vue b/app/assets/javascripts/jobs/components/job_container_item.vue
index 3ddcfd11dca..80cbed422a0 100644
--- a/app/assets/javascripts/jobs/components/job_container_item.vue
+++ b/app/assets/javascripts/jobs/components/job_container_item.vue
@@ -1,5 +1,5 @@
<script>
-import { GlLink } from '@gitlab-org/gitlab-ui';
+import { GlLink } from '@gitlab/ui';
import tooltip from '~/vue_shared/directives/tooltip';
import CiIcon from '~/vue_shared/components/ci_icon.vue';
import Icon from '~/vue_shared/components/icon.vue';
diff --git a/app/assets/javascripts/jobs/components/job_log_controllers.vue b/app/assets/javascripts/jobs/components/job_log_controllers.vue
index 8b506b124ec..5e0495bb231 100644
--- a/app/assets/javascripts/jobs/components/job_log_controllers.vue
+++ b/app/assets/javascripts/jobs/components/job_log_controllers.vue
@@ -1,5 +1,5 @@
<script>
-import { GlTooltipDirective, GlLink, GlButton } from '@gitlab-org/gitlab-ui';
+import { GlTooltipDirective, GlLink, GlButton } from '@gitlab/ui';
import { polyfillSticky } from '~/lib/utils/sticky';
import Icon from '~/vue_shared/components/icon.vue';
import { numberToHumanSize } from '~/lib/utils/number_utils';
diff --git a/app/assets/javascripts/jobs/components/sidebar.vue b/app/assets/javascripts/jobs/components/sidebar.vue
index f7b7b8f10f7..21f0a1435d7 100644
--- a/app/assets/javascripts/jobs/components/sidebar.vue
+++ b/app/assets/javascripts/jobs/components/sidebar.vue
@@ -1,7 +1,7 @@
<script>
import _ from 'underscore';
import { mapActions, mapState } from 'vuex';
-import { GlLink, GlButton } from '@gitlab-org/gitlab-ui';
+import { GlLink, GlButton } from '@gitlab/ui';
import timeagoMixin from '~/vue_shared/mixins/timeago';
import { timeIntervalInWords } from '~/lib/utils/datetime_utility';
import Icon from '~/vue_shared/components/icon.vue';
diff --git a/app/assets/javascripts/jobs/components/sidebar_detail_row.vue b/app/assets/javascripts/jobs/components/sidebar_detail_row.vue
index cfedb38e17a..d143e9f586c 100644
--- a/app/assets/javascripts/jobs/components/sidebar_detail_row.vue
+++ b/app/assets/javascripts/jobs/components/sidebar_detail_row.vue
@@ -1,5 +1,5 @@
<script>
-import { GlLink } from '@gitlab-org/gitlab-ui';
+import { GlLink } from '@gitlab/ui';
export default {
name: 'SidebarDetailRow',
diff --git a/app/assets/javascripts/jobs/components/stuck_block.vue b/app/assets/javascripts/jobs/components/stuck_block.vue
index ca4bf471363..2b2ebe4c3f7 100644
--- a/app/assets/javascripts/jobs/components/stuck_block.vue
+++ b/app/assets/javascripts/jobs/components/stuck_block.vue
@@ -1,5 +1,5 @@
<script>
-import { GlLink } from '@gitlab-org/gitlab-ui';
+import { GlLink } from '@gitlab/ui';
/**
* Renders Stuck Runners block for job's view.
*/
diff --git a/app/assets/javascripts/jobs/components/trigger_block.vue b/app/assets/javascripts/jobs/components/trigger_block.vue
index 1e62c05b4d1..4d18f76b7ea 100644
--- a/app/assets/javascripts/jobs/components/trigger_block.vue
+++ b/app/assets/javascripts/jobs/components/trigger_block.vue
@@ -1,5 +1,5 @@
<script>
-import { GlButton } from '@gitlab-org/gitlab-ui';
+import { GlButton } from '@gitlab/ui';
export default {
components: {
diff --git a/app/assets/javascripts/lib/utils/text_markdown.js b/app/assets/javascripts/lib/utils/text_markdown.js
index c52cfb806a2..3618c6af7e2 100644
--- a/app/assets/javascripts/lib/utils/text_markdown.js
+++ b/app/assets/javascripts/lib/utils/text_markdown.js
@@ -39,7 +39,7 @@ function blockTagText(text, textArea, blockTag, selected) {
}
}
-function moveCursor({ textArea, tag, wrapped, removedLastNewLine, select }) {
+function moveCursor({ textArea, tag, positionBetweenTags, removedLastNewLine, select }) {
var pos;
if (!textArea.setSelectionRange) {
return;
@@ -51,7 +51,7 @@ function moveCursor({ textArea, tag, wrapped, removedLastNewLine, select }) {
return textArea.setSelectionRange(startPosition, endPosition);
}
if (textArea.selectionStart === textArea.selectionEnd) {
- if (wrapped) {
+ if (positionBetweenTags) {
pos = textArea.selectionStart - tag.length;
} else {
pos = textArea.selectionStart;
@@ -67,7 +67,6 @@ function moveCursor({ textArea, tag, wrapped, removedLastNewLine, select }) {
export function insertMarkdownText({ textArea, text, tag, blockTag, selected, wrap, select }) {
var textToInsert,
- inserted,
selectedSplit,
startChar,
removedLastNewLine,
@@ -155,7 +154,7 @@ export function insertMarkdownText({ textArea, text, tag, blockTag, selected, wr
return moveCursor({
textArea,
tag: tag.replace(textPlaceholder, selected),
- wrap,
+ positionBetweenTags: wrap && selected.length === 0,
removedLastNewLine,
select,
});
@@ -171,10 +170,6 @@ function updateText({ textArea, tag, blockTag, wrap, select }) {
return insertMarkdownText({ textArea, text, tag, blockTag, selected, wrap, select });
}
-function replaceRange(s, start, end, substitute) {
- return s.substring(0, start) + substitute + s.substring(end);
-}
-
export function addMarkdownListeners(form) {
return $('.js-md', form)
.off('click')
diff --git a/app/assets/javascripts/notebook/cells/output/index.vue b/app/assets/javascripts/notebook/cells/output/index.vue
index d9f8604ed10..bd0bcc0d819 100644
--- a/app/assets/javascripts/notebook/cells/output/index.vue
+++ b/app/assets/javascripts/notebook/cells/output/index.vue
@@ -22,7 +22,7 @@ export default {
},
output: {
type: Object,
- requred: true,
+ required: true,
default: () => ({}),
},
},
diff --git a/app/assets/javascripts/notes.js b/app/assets/javascripts/notes.js
index 90fe339e3de..dfb53c986fc 100644
--- a/app/assets/javascripts/notes.js
+++ b/app/assets/javascripts/notes.js
@@ -16,7 +16,7 @@ import 'vendor/jquery.atwho';
import AjaxCache from '~/lib/utils/ajax_cache';
import Vue from 'vue';
import syntaxHighlight from '~/syntax_highlight';
-import { GlSkeletonLoading } from '@gitlab-org/gitlab-ui';
+import { GlSkeletonLoading } from '@gitlab/ui';
import axios from './lib/utils/axios_utils';
import { getLocationHash } from './lib/utils/url_utility';
import Flash from './flash';
diff --git a/app/assets/javascripts/notes/components/diff_with_note.vue b/app/assets/javascripts/notes/components/diff_with_note.vue
index 080161dfbba..30fcb895369 100644
--- a/app/assets/javascripts/notes/components/diff_with_note.vue
+++ b/app/assets/javascripts/notes/components/diff_with_note.vue
@@ -3,7 +3,7 @@ import { mapState, mapActions } from 'vuex';
import DiffFileHeader from '~/diffs/components/diff_file_header.vue';
import DiffViewer from '~/vue_shared/components/diff_viewer/diff_viewer.vue';
import ImageDiffOverlay from '~/diffs/components/image_diff_overlay.vue';
-import { GlSkeletonLoading } from '@gitlab-org/gitlab-ui';
+import { GlSkeletonLoading } from '@gitlab/ui';
import { trimFirstCharOfLineContent, getDiffMode } from '~/diffs/store/utils';
export default {
diff --git a/app/assets/javascripts/notes/components/note_actions.vue b/app/assets/javascripts/notes/components/note_actions.vue
index f7a61fbfcd4..0f0d7f4661a 100644
--- a/app/assets/javascripts/notes/components/note_actions.vue
+++ b/app/assets/javascripts/notes/components/note_actions.vue
@@ -2,7 +2,7 @@
import { mapGetters } from 'vuex';
import Icon from '~/vue_shared/components/icon.vue';
import tooltip from '~/vue_shared/directives/tooltip';
-import { GlLoadingIcon } from '@gitlab-org/gitlab-ui';
+import { GlLoadingIcon } from '@gitlab/ui';
export default {
name: 'NoteActions',
diff --git a/app/assets/javascripts/pages/dashboard/issues/index.js b/app/assets/javascripts/pages/dashboard/issues/index.js
index c4901dd1cb6..9055738f86e 100644
--- a/app/assets/javascripts/pages/dashboard/issues/index.js
+++ b/app/assets/javascripts/pages/dashboard/issues/index.js
@@ -1,7 +1,13 @@
import projectSelect from '~/project_select';
-import initLegacyFilters from '~/init_legacy_filters';
+import initFilteredSearch from '~/pages/search/init_filtered_search';
+import IssuableFilteredSearchTokenKeys from '~/filtered_search/issuable_filtered_search_token_keys';
+import { FILTERED_SEARCH } from '~/pages/constants';
document.addEventListener('DOMContentLoaded', () => {
+ initFilteredSearch({
+ page: FILTERED_SEARCH.ISSUES,
+ filteredSearchTokenKeys: IssuableFilteredSearchTokenKeys,
+ });
+
projectSelect();
- initLegacyFilters();
});
diff --git a/app/assets/javascripts/pages/dashboard/merge_requests/index.js b/app/assets/javascripts/pages/dashboard/merge_requests/index.js
index c4901dd1cb6..260484726f3 100644
--- a/app/assets/javascripts/pages/dashboard/merge_requests/index.js
+++ b/app/assets/javascripts/pages/dashboard/merge_requests/index.js
@@ -1,7 +1,15 @@
import projectSelect from '~/project_select';
-import initLegacyFilters from '~/init_legacy_filters';
+import initFilteredSearch from '~/pages/search/init_filtered_search';
+import IssuableFilteredSearchTokenKeys from '~/filtered_search/issuable_filtered_search_token_keys';
+import { FILTERED_SEARCH } from '~/pages/constants';
document.addEventListener('DOMContentLoaded', () => {
+ IssuableFilteredSearchTokenKeys.addExtraTokensForMergeRequests();
+
+ initFilteredSearch({
+ page: FILTERED_SEARCH.MERGE_REQUESTS,
+ filteredSearchTokenKeys: IssuableFilteredSearchTokenKeys,
+ });
+
projectSelect();
- initLegacyFilters();
});
diff --git a/app/assets/javascripts/pages/projects/wikis/components/delete_wiki_modal.vue b/app/assets/javascripts/pages/projects/wikis/components/delete_wiki_modal.vue
index f970a5ebb64..cbe85eaa590 100644
--- a/app/assets/javascripts/pages/projects/wikis/components/delete_wiki_modal.vue
+++ b/app/assets/javascripts/pages/projects/wikis/components/delete_wiki_modal.vue
@@ -1,7 +1,7 @@
<script>
import _ from 'underscore';
import { s__, sprintf } from '~/locale';
-import { GlModal, GlModalDirective } from '@gitlab-org/gitlab-ui';
+import { GlModal, GlModalDirective } from '@gitlab/ui';
export default {
components: {
diff --git a/app/assets/javascripts/pages/users/user_overview_block.js b/app/assets/javascripts/pages/users/user_overview_block.js
index 2ed177be558..eec2b5ca8e5 100644
--- a/app/assets/javascripts/pages/users/user_overview_block.js
+++ b/app/assets/javascripts/pages/users/user_overview_block.js
@@ -10,6 +10,7 @@ export default class UserOverviewBlock {
limit: DEFAULT_LIMIT,
...options.requestParams,
};
+ this.postRenderCallback = options.postRenderCallback;
this.loadData();
}
@@ -43,5 +44,9 @@ export default class UserOverviewBlock {
}
loadingEl.classList.add('hide');
+
+ if (this.postRenderCallback) {
+ this.postRenderCallback.call(this);
+ }
}
}
diff --git a/app/assets/javascripts/pages/users/user_tabs.js b/app/assets/javascripts/pages/users/user_tabs.js
index 04bcb16f036..aa537d4a43e 100644
--- a/app/assets/javascripts/pages/users/user_tabs.js
+++ b/app/assets/javascripts/pages/users/user_tabs.js
@@ -2,7 +2,8 @@ import $ from 'jquery';
import axios from '~/lib/utils/axios_utils';
import Activities from '~/activities';
import { localTimeAgo } from '~/lib/utils/datetime_utility';
-import { __, sprintf } from '~/locale';
+import AjaxCache from '~/lib/utils/ajax_cache';
+import { __ } from '~/locale';
import flash from '~/flash';
import ActivityCalendar from './activity_calendar';
import UserOverviewBlock from './user_overview_block';
@@ -62,23 +63,20 @@ import UserOverviewBlock from './user_overview_block';
* </div>
*/
-const CALENDAR_TEMPLATES = {
- activity: `
- <div class="clearfix calendar">
- <div class="js-contrib-calendar"></div>
- <div class="calendar-hint bottom-right"></div>
- </div>
- `,
- overview: `
- <div class="clearfix calendar">
- <div class="calendar-hint"></div>
- <div class="js-contrib-calendar prepend-top-20"></div>
- </div>
- `,
-};
+const CALENDAR_TEMPLATE = `
+ <div class="clearfix calendar">
+ <div class="js-contrib-calendar"></div>
+ <div class="calendar-hint bottom-right"></div>
+ </div>
+`;
const CALENDAR_PERIOD_6_MONTHS = 6;
const CALENDAR_PERIOD_12_MONTHS = 12;
+/* computation based on
+ * width = (group + 1) * this.daySizeWithSpace + this.getExtraWidthPadding(group);
+ * (see activity_calendar.js)
+ */
+const OVERVIEW_CALENDAR_BREAKPOINT = 918;
export default class UserTabs {
constructor({ defaultAction, action, parentEl }) {
@@ -105,6 +103,12 @@ export default class UserTabs {
.off('shown.bs.tab', '.nav-links a[data-toggle="tab"]')
.on('shown.bs.tab', '.nav-links a[data-toggle="tab"]', event => this.tabShown(event))
.on('click', '.gl-pagination a', event => this.changeProjectsPage(event));
+
+ window.addEventListener('resize', () => this.onResize());
+ }
+
+ onResize() {
+ this.loadActivityCalendar();
}
changeProjectsPage(e) {
@@ -167,8 +171,6 @@ export default class UserTabs {
return;
}
- this.loadActivityCalendar('activity');
-
// eslint-disable-next-line no-new
new Activities('#activity');
@@ -180,10 +182,10 @@ export default class UserTabs {
return;
}
- this.loadActivityCalendar('overview');
+ this.loadActivityCalendar();
UserTabs.renderMostRecentBlocks('#js-overview .activities-block', {
- requestParams: { limit: 5 },
+ requestParams: { limit: 10 },
});
UserTabs.renderMostRecentBlocks('#js-overview .projects-block', {
requestParams: { limit: 10, skip_pagination: true },
@@ -198,52 +200,39 @@ export default class UserTabs {
container,
url: $(`${container} .overview-content-list`).data('href'),
...options,
+ postRenderCallback: () => localTimeAgo($('.js-timeago', container)),
});
}
- loadActivityCalendar(action) {
- const monthsAgo = action === 'overview' ? CALENDAR_PERIOD_6_MONTHS : CALENDAR_PERIOD_12_MONTHS;
+ loadActivityCalendar() {
const $calendarWrap = this.$parentEl.find('.tab-pane.active .user-calendar');
const calendarPath = $calendarWrap.data('calendarPath');
+
+ AjaxCache.retrieve(calendarPath)
+ .then(data => UserTabs.renderActivityCalendar(data, $calendarWrap))
+ .catch(() => flash(__('There was an error loading users activity calendar.')));
+ }
+
+ static renderActivityCalendar(data, $calendarWrap) {
+ const monthsAgo = UserTabs.getVisibleCalendarPeriod($calendarWrap);
const calendarActivitiesPath = $calendarWrap.data('calendarActivitiesPath');
const utcOffset = $calendarWrap.data('utcOffset');
- let utcFormatted = 'UTC';
- if (utcOffset !== 0) {
- utcFormatted = `UTC${utcOffset > 0 ? '+' : ''}${utcOffset / 3600}`;
- }
+ const calendarHint = __('Issues, merge requests, pushes and comments.');
- axios
- .get(calendarPath)
- .then(({ data }) => {
- $calendarWrap.html(CALENDAR_TEMPLATES[action]);
-
- let calendarHint = '';
-
- if (action === 'activity') {
- calendarHint = sprintf(
- __(
- 'Summary of issues, merge requests, push events, and comments (Timezone: %{utcFormatted})',
- ),
- { utcFormatted },
- );
- } else if (action === 'overview') {
- calendarHint = __('Issues, merge requests, pushes and comments.');
- }
-
- $calendarWrap.find('.calendar-hint').text(calendarHint);
-
- // eslint-disable-next-line no-new
- new ActivityCalendar(
- '.tab-pane.active .js-contrib-calendar',
- '.tab-pane.active .user-calendar-activities',
- data,
- calendarActivitiesPath,
- utcOffset,
- 0,
- monthsAgo,
- );
- })
- .catch(() => flash(__('There was an error loading users activity calendar.')));
+ $calendarWrap.html(CALENDAR_TEMPLATE);
+
+ $calendarWrap.find('.calendar-hint').text(calendarHint);
+
+ // eslint-disable-next-line no-new
+ new ActivityCalendar(
+ '.tab-pane.active .js-contrib-calendar',
+ '.tab-pane.active .user-calendar-activities',
+ data,
+ calendarActivitiesPath,
+ utcOffset,
+ 0,
+ monthsAgo,
+ );
}
toggleLoading(status) {
@@ -267,4 +256,11 @@ export default class UserTabs {
getCurrentAction() {
return this.$parentEl.find('.nav-links a.active').data('action');
}
+
+ static getVisibleCalendarPeriod($calendarWrap) {
+ const width = $calendarWrap.width();
+ return width < OVERVIEW_CALENDAR_BREAKPOINT
+ ? CALENDAR_PERIOD_6_MONTHS
+ : CALENDAR_PERIOD_12_MONTHS;
+ }
}
diff --git a/app/assets/javascripts/pipelines/components/empty_state.vue b/app/assets/javascripts/pipelines/components/empty_state.vue
index 8a0259ed5a5..f756c651684 100644
--- a/app/assets/javascripts/pipelines/components/empty_state.vue
+++ b/app/assets/javascripts/pipelines/components/empty_state.vue
@@ -1,5 +1,5 @@
<script>
-import { GlButton } from '@gitlab-org/gitlab-ui';
+import { GlButton } from '@gitlab/ui';
export default {
name: 'PipelinesEmptyState',
diff --git a/app/assets/javascripts/pipelines/components/graph/action_component.vue b/app/assets/javascripts/pipelines/components/graph/action_component.vue
index f6a97236ebf..3a39dfe181d 100644
--- a/app/assets/javascripts/pipelines/components/graph/action_component.vue
+++ b/app/assets/javascripts/pipelines/components/graph/action_component.vue
@@ -1,5 +1,5 @@
<script>
-import { GlTooltipDirective, GlButton } from '@gitlab-org/gitlab-ui';
+import { GlTooltipDirective, GlButton } from '@gitlab/ui';
import axios from '~/lib/utils/axios_utils';
import { dasherize } from '~/lib/utils/text_utility';
import { __ } from '~/locale';
diff --git a/app/assets/javascripts/pipelines/components/graph/graph_component.vue b/app/assets/javascripts/pipelines/components/graph/graph_component.vue
index 4de8b3401e8..6c9a11c3829 100644
--- a/app/assets/javascripts/pipelines/components/graph/graph_component.vue
+++ b/app/assets/javascripts/pipelines/components/graph/graph_component.vue
@@ -1,6 +1,6 @@
<script>
import _ from 'underscore';
-import { GlLoadingIcon } from '@gitlab-org/gitlab-ui';
+import { GlLoadingIcon } from '@gitlab/ui';
import StageColumnComponent from './stage_column_component.vue';
export default {
diff --git a/app/assets/javascripts/pipelines/components/graph/job_group_dropdown.vue b/app/assets/javascripts/pipelines/components/graph/job_group_dropdown.vue
index 2c3cb1959b5..2670ea29db6 100644
--- a/app/assets/javascripts/pipelines/components/graph/job_group_dropdown.vue
+++ b/app/assets/javascripts/pipelines/components/graph/job_group_dropdown.vue
@@ -1,6 +1,6 @@
<script>
import $ from 'jquery';
-import { GlTooltipDirective } from '@gitlab-org/gitlab-ui';
+import { GlTooltipDirective } from '@gitlab/ui';
import CiIcon from '~/vue_shared/components/ci_icon.vue';
import JobItem from './job_item.vue';
diff --git a/app/assets/javascripts/pipelines/components/graph/job_item.vue b/app/assets/javascripts/pipelines/components/graph/job_item.vue
index 182849c6455..e6abf32decc 100644
--- a/app/assets/javascripts/pipelines/components/graph/job_item.vue
+++ b/app/assets/javascripts/pipelines/components/graph/job_item.vue
@@ -1,7 +1,7 @@
<script>
import ActionComponent from './action_component.vue';
import JobNameComponent from './job_name_component.vue';
-import { GlTooltipDirective, GlLink } from '@gitlab-org/gitlab-ui';
+import { GlTooltipDirective, GlLink } from '@gitlab/ui';
import { sprintf } from '~/locale';
import delayedJobMixin from '~/jobs/mixins/delayed_job_mixin';
diff --git a/app/assets/javascripts/pipelines/components/header_component.vue b/app/assets/javascripts/pipelines/components/header_component.vue
index 8f004b491c8..ac7fa4b195e 100644
--- a/app/assets/javascripts/pipelines/components/header_component.vue
+++ b/app/assets/javascripts/pipelines/components/header_component.vue
@@ -1,5 +1,5 @@
<script>
-import { GlLoadingIcon } from '@gitlab-org/gitlab-ui';
+import { GlLoadingIcon } from '@gitlab/ui';
import ciHeader from '../../vue_shared/components/header_ci_component.vue';
import eventHub from '../event_hub';
diff --git a/app/assets/javascripts/pipelines/components/nav_controls.vue b/app/assets/javascripts/pipelines/components/nav_controls.vue
index 0911acbb131..5104fe36b42 100644
--- a/app/assets/javascripts/pipelines/components/nav_controls.vue
+++ b/app/assets/javascripts/pipelines/components/nav_controls.vue
@@ -1,5 +1,5 @@
<script>
-import { GlLink, GlButton } from '@gitlab-org/gitlab-ui';
+import { GlLink, GlButton } from '@gitlab/ui';
import LoadingButton from '../../vue_shared/components/loading_button.vue';
export default {
diff --git a/app/assets/javascripts/pipelines/components/pipeline_url.vue b/app/assets/javascripts/pipelines/components/pipeline_url.vue
index be4b37f3c8c..249f7b9f368 100644
--- a/app/assets/javascripts/pipelines/components/pipeline_url.vue
+++ b/app/assets/javascripts/pipelines/components/pipeline_url.vue
@@ -1,5 +1,5 @@
<script>
-import { GlLink, GlTooltipDirective } from '@gitlab-org/gitlab-ui';
+import { GlLink, GlTooltipDirective } from '@gitlab/ui';
import UserAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue';
import popover from '~/vue_shared/directives/popover';
diff --git a/app/assets/javascripts/pipelines/components/pipelines_actions.vue b/app/assets/javascripts/pipelines/components/pipelines_actions.vue
index 811495c45a9..112c1559f25 100644
--- a/app/assets/javascripts/pipelines/components/pipelines_actions.vue
+++ b/app/assets/javascripts/pipelines/components/pipelines_actions.vue
@@ -1,5 +1,5 @@
<script>
-import { GlButton, GlTooltipDirective, GlLoadingIcon } from '@gitlab-org/gitlab-ui';
+import { GlButton, GlTooltipDirective, GlLoadingIcon } from '@gitlab/ui';
import { s__, sprintf } from '~/locale';
import GlCountdown from '~/vue_shared/components/gl_countdown.vue';
import eventHub from '../event_hub';
diff --git a/app/assets/javascripts/pipelines/components/pipelines_artifacts.vue b/app/assets/javascripts/pipelines/components/pipelines_artifacts.vue
index 2abb24b87b6..d7d9eb00faa 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 { GlLink, GlButton, GlTooltipDirective } from '@gitlab-org/gitlab-ui';
+import { GlLink, GlButton, GlTooltipDirective } from '@gitlab/ui';
import Icon from '~/vue_shared/components/icon.vue';
export default {
diff --git a/app/assets/javascripts/pipelines/components/stage.vue b/app/assets/javascripts/pipelines/components/stage.vue
index 587c4ffa45c..1d62472671a 100644
--- a/app/assets/javascripts/pipelines/components/stage.vue
+++ b/app/assets/javascripts/pipelines/components/stage.vue
@@ -13,7 +13,7 @@
*/
import $ from 'jquery';
-import { GlLoadingIcon, GlTooltipDirective } from '@gitlab-org/gitlab-ui';
+import { GlLoadingIcon, GlTooltipDirective } from '@gitlab/ui';
import { __ } from '../../locale';
import Flash from '../../flash';
import axios from '../../lib/utils/axios_utils';
diff --git a/app/assets/javascripts/pipelines/mixins/pipelines.js b/app/assets/javascripts/pipelines/mixins/pipelines.js
index 41bc5dcce5c..32bfa47e5f2 100644
--- a/app/assets/javascripts/pipelines/mixins/pipelines.js
+++ b/app/assets/javascripts/pipelines/mixins/pipelines.js
@@ -1,5 +1,5 @@
import Visibility from 'visibilityjs';
-import { GlLoadingIcon } from '@gitlab-org/gitlab-ui';
+import { GlLoadingIcon } from '@gitlab/ui';
import { __ } from '../../locale';
import Flash from '../../flash';
import Poll from '../../lib/utils/poll';
diff --git a/app/assets/javascripts/projects/gke_cluster_dropdowns/components/gke_dropdown_mixin.js b/app/assets/javascripts/projects/gke_cluster_dropdowns/components/gke_dropdown_mixin.js
index f5dae5ad808..5a3407693e5 100644
--- a/app/assets/javascripts/projects/gke_cluster_dropdowns/components/gke_dropdown_mixin.js
+++ b/app/assets/javascripts/projects/gke_cluster_dropdowns/components/gke_dropdown_mixin.js
@@ -2,7 +2,7 @@ import _ from 'underscore';
import DropdownSearchInput from '~/vue_shared/components/dropdown/dropdown_search_input.vue';
import DropdownHiddenInput from '~/vue_shared/components/dropdown/dropdown_hidden_input.vue';
import DropdownButton from '~/vue_shared/components/dropdown/dropdown_button.vue';
-import { GlLoadingIcon } from '@gitlab-org/gitlab-ui';
+import { GlLoadingIcon } from '@gitlab/ui';
import store from '../store';
diff --git a/app/assets/javascripts/projects/tree/components/commit_pipeline_status_component.vue b/app/assets/javascripts/projects/tree/components/commit_pipeline_status_component.vue
index 9a729ca9b91..7400b685c7e 100644
--- a/app/assets/javascripts/projects/tree/components/commit_pipeline_status_component.vue
+++ b/app/assets/javascripts/projects/tree/components/commit_pipeline_status_component.vue
@@ -5,7 +5,7 @@ import Poll from '~/lib/utils/poll';
import Flash from '~/flash';
import { s__, sprintf } from '~/locale';
import tooltip from '~/vue_shared/directives/tooltip';
-import { GlLoadingIcon } from '@gitlab-org/gitlab-ui';
+import { GlLoadingIcon } from '@gitlab/ui';
import CommitPipelineService from '../services/commit_pipeline_service';
export default {
diff --git a/app/assets/javascripts/registry/components/app.vue b/app/assets/javascripts/registry/components/app.vue
index 0a906f40f5a..6f94f5d6d2a 100644
--- a/app/assets/javascripts/registry/components/app.vue
+++ b/app/assets/javascripts/registry/components/app.vue
@@ -1,6 +1,6 @@
<script>
import { mapGetters, mapActions } from 'vuex';
-import { GlLoadingIcon } from '@gitlab-org/gitlab-ui';
+import { GlLoadingIcon } from '@gitlab/ui';
import Flash from '../../flash';
import store from '../stores';
import collapsibleContainer from './collapsible_container.vue';
diff --git a/app/assets/javascripts/registry/components/collapsible_container.vue b/app/assets/javascripts/registry/components/collapsible_container.vue
index be9816a55c4..d85de973740 100644
--- a/app/assets/javascripts/registry/components/collapsible_container.vue
+++ b/app/assets/javascripts/registry/components/collapsible_container.vue
@@ -1,6 +1,6 @@
<script>
import { mapActions } from 'vuex';
-import { GlLoadingIcon } from '@gitlab-org/gitlab-ui';
+import { GlLoadingIcon } from '@gitlab/ui';
import Flash from '../../flash';
import clipboardButton from '../../vue_shared/components/clipboard_button.vue';
import tooltip from '../../vue_shared/directives/tooltip';
diff --git a/app/assets/javascripts/reports/components/summary_row.vue b/app/assets/javascripts/reports/components/summary_row.vue
index a44ba833b63..7e73ccb6c28 100644
--- a/app/assets/javascripts/reports/components/summary_row.vue
+++ b/app/assets/javascripts/reports/components/summary_row.vue
@@ -1,7 +1,7 @@
<script>
import CiIcon from '~/vue_shared/components/ci_icon.vue';
import Popover from '~/vue_shared/components/help_popover.vue';
-import { GlLoadingIcon } from '@gitlab-org/gitlab-ui';
+import { GlLoadingIcon } from '@gitlab/ui';
/**
* Renders the summary row for each report
diff --git a/app/assets/javascripts/search_autocomplete.js b/app/assets/javascripts/search_autocomplete.js
index 17def77b2d7..0a4583b5861 100644
--- a/app/assets/javascripts/search_autocomplete.js
+++ b/app/assets/javascripts/search_autocomplete.js
@@ -253,7 +253,6 @@ export class SearchAutocomplete {
}
getCategoryContents() {
- const userId = gon.current_user_id;
const userName = gon.current_username;
const { projectOptions, groupOptions, dashboardOptions } = gl;
@@ -279,21 +278,21 @@ export class SearchAutocomplete {
const issueItems = [
{
text: s__('SearchAutocomplete|Issues assigned to me'),
- url: `${issuesPath}/?assignee_id=${userId}`,
+ url: `${issuesPath}/?assignee_username=${userName}`,
},
{
text: s__("SearchAutocomplete|Issues I've created"),
- url: `${issuesPath}/?author_id=${userId}`,
+ url: `${issuesPath}/?author_username=${userName}`,
},
];
const mergeRequestItems = [
{
text: s__('SearchAutocomplete|Merge requests assigned to me'),
- url: `${mrPath}/?assignee_id=${userId}`,
+ url: `${mrPath}/?assignee_username=${userName}`,
},
{
text: s__("SearchAutocomplete|Merge requests I've created"),
- url: `${mrPath}/?author_id=${userId}`,
+ url: `${mrPath}/?author_username=${userName}`,
},
];
diff --git a/app/assets/javascripts/set_status_modal/set_status_modal_wrapper.vue b/app/assets/javascripts/set_status_modal/set_status_modal_wrapper.vue
index 4d461baf74d..8a48eea5c89 100644
--- a/app/assets/javascripts/set_status_modal/set_status_modal_wrapper.vue
+++ b/app/assets/javascripts/set_status_modal/set_status_modal_wrapper.vue
@@ -5,7 +5,7 @@ import Icon from '~/vue_shared/components/icon.vue';
import GfmAutoComplete from '~/gfm_auto_complete';
import { __, s__ } from '~/locale';
import Api from '~/api';
-import { GlModal, GlTooltipDirective } from '@gitlab-org/gitlab-ui';
+import { GlModal, GlTooltipDirective } from '@gitlab/ui';
import eventHub from './event_hub';
import EmojiMenuInModal from './emoji_menu_in_modal';
diff --git a/app/assets/javascripts/sidebar/components/participants/participants.vue b/app/assets/javascripts/sidebar/components/participants/participants.vue
index fe73f6a0cef..43d2f754bac 100644
--- a/app/assets/javascripts/sidebar/components/participants/participants.vue
+++ b/app/assets/javascripts/sidebar/components/participants/participants.vue
@@ -2,7 +2,7 @@
import { __, n__, sprintf } from '~/locale';
import tooltip from '~/vue_shared/directives/tooltip';
import userAvatarImage from '~/vue_shared/components/user_avatar/user_avatar_image.vue';
-import { GlLoadingIcon } from '@gitlab-org/gitlab-ui';
+import { GlLoadingIcon } from '@gitlab/ui';
export default {
directives: {
diff --git a/app/assets/javascripts/sidebar/components/time_tracking/comparison_pane.vue b/app/assets/javascripts/sidebar/components/time_tracking/comparison_pane.vue
index b145e5dc5e2..87780411c26 100644
--- a/app/assets/javascripts/sidebar/components/time_tracking/comparison_pane.vue
+++ b/app/assets/javascripts/sidebar/components/time_tracking/comparison_pane.vue
@@ -1,7 +1,7 @@
<script>
import { parseSeconds, stringifyTime } from '~/lib/utils/datetime_utility';
import tooltip from '../../../vue_shared/directives/tooltip';
-import { GlProgressBar } from '@gitlab-org/gitlab-ui';
+import { GlProgressBar } from '@gitlab/ui';
export default {
name: 'TimeTrackingComparisonPane',
diff --git a/app/assets/javascripts/sidebar/components/todo_toggle/todo.vue b/app/assets/javascripts/sidebar/components/todo_toggle/todo.vue
index 913a616d9f1..7edef35461a 100644
--- a/app/assets/javascripts/sidebar/components/todo_toggle/todo.vue
+++ b/app/assets/javascripts/sidebar/components/todo_toggle/todo.vue
@@ -1,7 +1,7 @@
<script>
import { __ } from '~/locale';
import tooltip from '~/vue_shared/directives/tooltip';
-import { GlLoadingIcon } from '@gitlab-org/gitlab-ui';
+import { GlLoadingIcon } from '@gitlab/ui';
import Icon from '~/vue_shared/components/icon.vue';
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/deployment.vue b/app/assets/javascripts/vue_merge_request_widget/components/deployment.vue
index 4ec925aa8a6..fe741dc60cb 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/deployment.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/deployment.vue
@@ -33,6 +33,10 @@ export default {
type: Object,
required: true,
},
+ showMetrics: {
+ type: Boolean,
+ required: true,
+ },
},
deployedTextMap: {
running: __('Deploying to'),
@@ -74,6 +78,9 @@ export default {
shouldRenderDropdown() {
return this.deployment.changes && this.deployment.changes.length > 0;
},
+ showMemoryUsage() {
+ return this.hasMetrics && this.showMetrics;
+ },
},
methods: {
stopEnvironment() {
@@ -136,7 +143,7 @@ export default {
{{ deployTimeago }}
</span>
<memory-usage
- v-if="hasMetrics"
+ v-if="showMemoryUsage"
:metrics-url="deployment.metrics_url"
:metrics-monitoring-url="deployment.metrics_monitoring_url"
/>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_status_icon.vue b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_status_icon.vue
index b3340290ed3..060361a6516 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_status_icon.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_status_icon.vue
@@ -1,5 +1,5 @@
<script>
-import { GlLoadingIcon } from '@gitlab-org/gitlab-ui';
+import { GlLoadingIcon } from '@gitlab/ui';
import ciIcon from '../../vue_shared/components/ci_icon.vue';
export default {
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_auto_merge_failed.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_auto_merge_failed.vue
index 4bfbdcf1404..409fc2f2db4 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_auto_merge_failed.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_auto_merge_failed.vue
@@ -1,5 +1,5 @@
<script>
-import { GlLoadingIcon } from '@gitlab-org/gitlab-ui';
+import { GlLoadingIcon } from '@gitlab/ui';
import eventHub from '../../event_hub';
import statusIcon from '../mr_widget_status_icon.vue';
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merged.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merged.vue
index 7e33021e4b4..fb9ca897844 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merged.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merged.vue
@@ -6,7 +6,7 @@ import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
import MrWidgetAuthorTime from '../../components/mr_widget_author_time.vue';
import statusIcon from '../mr_widget_status_icon.vue';
import eventHub from '../../event_hub';
-import { GlLoadingIcon } from '@gitlab-org/gitlab-ui';
+import { GlLoadingIcon } from '@gitlab/ui';
export default {
name: 'MRWidgetMerged',
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_rebase.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_rebase.vue
index 0e714cc2aa1..5a7f6cc36fa 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_rebase.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_rebase.vue
@@ -1,5 +1,5 @@
<script>
-import { GlLoadingIcon } from '@gitlab-org/gitlab-ui';
+import { GlLoadingIcon } from '@gitlab/ui';
import simplePoll from '../../../lib/utils/simple_poll';
import eventHub from '../../event_hub';
import statusIcon from '../mr_widget_status_icon.vue';
diff --git a/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue b/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue
index 063d1e15544..3b840540657 100644
--- a/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue
@@ -312,6 +312,7 @@ export default {
:key="`pre-merge-deploy-${deployment.id}`"
class="js-pre-merge-deploy"
:deployment="deployment"
+ :show-metrics="false"
/>
<div class="mr-section-container">
<grouped-test-reports-app
@@ -366,6 +367,7 @@ export default {
v-for="postMergeDeployment in mr.postMergeDeployments"
:key="`post-merge-deploy-${postMergeDeployment.id}`"
:deployment="postMergeDeployment"
+ :show-metrics="true"
class="js-post-deployment"
/>
</template>
diff --git a/app/assets/javascripts/vue_shared/components/changed_file_icon.vue b/app/assets/javascripts/vue_shared/components/changed_file_icon.vue
index 766fc211bf5..c5fbaf87b00 100644
--- a/app/assets/javascripts/vue_shared/components/changed_file_icon.vue
+++ b/app/assets/javascripts/vue_shared/components/changed_file_icon.vue
@@ -1,5 +1,5 @@
<script>
-import { GlTooltipDirective } from '@gitlab-org/gitlab-ui';
+import { GlTooltipDirective } from '@gitlab/ui';
import Icon from '~/vue_shared/components/icon.vue';
import { pluralize } from '~/lib/utils/text_utility';
import { __, sprintf } from '~/locale';
diff --git a/app/assets/javascripts/vue_shared/components/ci_badge_link.vue b/app/assets/javascripts/vue_shared/components/ci_badge_link.vue
index 6780254827f..b0962684430 100644
--- a/app/assets/javascripts/vue_shared/components/ci_badge_link.vue
+++ b/app/assets/javascripts/vue_shared/components/ci_badge_link.vue
@@ -1,5 +1,5 @@
<script>
-import { GlTooltipDirective } from '@gitlab-org/gitlab-ui';
+import { GlTooltipDirective } from '@gitlab/ui';
import CiIcon from './ci_icon.vue';
/**
* Renders CI Badge link with CI icon and status text based on
diff --git a/app/assets/javascripts/vue_shared/components/clipboard_button.vue b/app/assets/javascripts/vue_shared/components/clipboard_button.vue
index 6b90a1f540e..671b4909839 100644
--- a/app/assets/javascripts/vue_shared/components/clipboard_button.vue
+++ b/app/assets/javascripts/vue_shared/components/clipboard_button.vue
@@ -12,7 +12,7 @@
* css-class="btn-transparent"
* />
*/
-import { GlButton, GlTooltipDirective } from '@gitlab-org/gitlab-ui';
+import { GlButton, GlTooltipDirective } from '@gitlab/ui';
import Icon from '../components/icon.vue';
export default {
diff --git a/app/assets/javascripts/vue_shared/components/commit.vue b/app/assets/javascripts/vue_shared/components/commit.vue
index b1139f34e41..420bd25b496 100644
--- a/app/assets/javascripts/vue_shared/components/commit.vue
+++ b/app/assets/javascripts/vue_shared/components/commit.vue
@@ -1,5 +1,5 @@
<script>
-import { GlTooltipDirective } from '@gitlab-org/gitlab-ui';
+import { GlTooltipDirective } from '@gitlab/ui';
import UserAvatarLink from './user_avatar/user_avatar_link.vue';
import Icon from '../../vue_shared/components/icon.vue';
diff --git a/app/assets/javascripts/vue_shared/components/content_viewer/viewers/download_viewer.vue b/app/assets/javascripts/vue_shared/components/content_viewer/viewers/download_viewer.vue
index c78b96695cf..97bdd9915c5 100644
--- a/app/assets/javascripts/vue_shared/components/content_viewer/viewers/download_viewer.vue
+++ b/app/assets/javascripts/vue_shared/components/content_viewer/viewers/download_viewer.vue
@@ -1,5 +1,5 @@
<script>
-import { GlLink } from '@gitlab-org/gitlab-ui';
+import { GlLink } from '@gitlab/ui';
import Icon from '../../icon.vue';
import { numberToHumanSize } from '../../../../lib/utils/number_utils';
diff --git a/app/assets/javascripts/vue_shared/components/content_viewer/viewers/markdown_viewer.vue b/app/assets/javascripts/vue_shared/components/content_viewer/viewers/markdown_viewer.vue
index 419987d2c50..a084cfdf612 100644
--- a/app/assets/javascripts/vue_shared/components/content_viewer/viewers/markdown_viewer.vue
+++ b/app/assets/javascripts/vue_shared/components/content_viewer/viewers/markdown_viewer.vue
@@ -2,7 +2,7 @@
import axios from '~/lib/utils/axios_utils';
import { __ } from '~/locale';
import $ from 'jquery';
-import { GlSkeletonLoading } from '@gitlab-org/gitlab-ui';
+import { GlSkeletonLoading } from '@gitlab/ui';
const { CancelToken } = axios;
let axiosSource;
diff --git a/app/assets/javascripts/vue_shared/components/dropdown/dropdown_button.vue b/app/assets/javascripts/vue_shared/components/dropdown/dropdown_button.vue
index 0e194eaaed5..0f4effda79f 100644
--- a/app/assets/javascripts/vue_shared/components/dropdown/dropdown_button.vue
+++ b/app/assets/javascripts/vue_shared/components/dropdown/dropdown_button.vue
@@ -1,6 +1,6 @@
<script>
import { __ } from '~/locale';
-import { GlLoadingIcon } from '@gitlab-org/gitlab-ui';
+import { GlLoadingIcon } from '@gitlab/ui';
export default {
components: {
diff --git a/app/assets/javascripts/vue_shared/components/file_icon.vue b/app/assets/javascripts/vue_shared/components/file_icon.vue
index 03818be6a69..545be568ad3 100644
--- a/app/assets/javascripts/vue_shared/components/file_icon.vue
+++ b/app/assets/javascripts/vue_shared/components/file_icon.vue
@@ -1,5 +1,5 @@
<script>
-import { GlLoadingIcon } from '@gitlab-org/gitlab-ui';
+import { GlLoadingIcon } from '@gitlab/ui';
import getIconForFile from './file_icon/file_icon_map';
import icon from '../../vue_shared/components/icon.vue';
diff --git a/app/assets/javascripts/vue_shared/components/gl_countdown.vue b/app/assets/javascripts/vue_shared/components/gl_countdown.vue
index a35986b2d03..97f7998f461 100644
--- a/app/assets/javascripts/vue_shared/components/gl_countdown.vue
+++ b/app/assets/javascripts/vue_shared/components/gl_countdown.vue
@@ -1,6 +1,6 @@
<script>
import { calculateRemainingMilliseconds, formatTime } from '~/lib/utils/datetime_utility';
-import { GlTooltipDirective } from '@gitlab-org/gitlab-ui';
+import { GlTooltipDirective } from '@gitlab/ui';
/**
* Counts down to a given end date.
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 88e95c33b9b..1a91a8b81e3 100644
--- a/app/assets/javascripts/vue_shared/components/header_ci_component.vue
+++ b/app/assets/javascripts/vue_shared/components/header_ci_component.vue
@@ -1,5 +1,5 @@
<script>
-import { GlTooltipDirective, GlLink, GlButton } from '@gitlab-org/gitlab-ui';
+import { GlTooltipDirective, GlLink, GlButton } from '@gitlab/ui';
import CiIconBadge from './ci_badge_link.vue';
import TimeagoTooltip from './time_ago_tooltip.vue';
import UserAvatarImage from './user_avatar/user_avatar_image.vue';
diff --git a/app/assets/javascripts/vue_shared/components/loading_button.vue b/app/assets/javascripts/vue_shared/components/loading_button.vue
index 69d7e5c46f5..9bae8a32a8c 100644
--- a/app/assets/javascripts/vue_shared/components/loading_button.vue
+++ b/app/assets/javascripts/vue_shared/components/loading_button.vue
@@ -1,5 +1,5 @@
<script>
-import { GlLoadingIcon } from '@gitlab-org/gitlab-ui';
+import { GlLoadingIcon } from '@gitlab/ui';
/* eslint-disable vue/require-default-prop */
/* This is a re-usable vue component for rendering a button
that will probably be sending off ajax requests and need
diff --git a/app/assets/javascripts/vue_shared/components/markdown/header.vue b/app/assets/javascripts/vue_shared/components/markdown/header.vue
index 27e3f314dd3..ca9e57a9b00 100644
--- a/app/assets/javascripts/vue_shared/components/markdown/header.vue
+++ b/app/assets/javascripts/vue_shared/components/markdown/header.vue
@@ -1,6 +1,6 @@
<script>
import $ from 'jquery';
-import { GlTooltipDirective } from '@gitlab-org/gitlab-ui';
+import { GlTooltipDirective } from '@gitlab/ui';
import ToolbarButton from './toolbar_button.vue';
import Icon from '../icon.vue';
diff --git a/app/assets/javascripts/vue_shared/components/markdown/toolbar.vue b/app/assets/javascripts/vue_shared/components/markdown/toolbar.vue
index b0a93794013..3cb48023002 100644
--- a/app/assets/javascripts/vue_shared/components/markdown/toolbar.vue
+++ b/app/assets/javascripts/vue_shared/components/markdown/toolbar.vue
@@ -1,5 +1,5 @@
<script>
-import { GlLink } from '@gitlab-org/gitlab-ui';
+import { GlLink } from '@gitlab/ui';
export default {
components: {
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 91d0bbfc21c..13af4b627de 100644
--- a/app/assets/javascripts/vue_shared/components/markdown/toolbar_button.vue
+++ b/app/assets/javascripts/vue_shared/components/markdown/toolbar_button.vue
@@ -1,5 +1,5 @@
<script>
-import { GlTooltipDirective } from '@gitlab-org/gitlab-ui';
+import { GlTooltipDirective } from '@gitlab/ui';
import Icon from '../icon.vue';
export default {
diff --git a/app/assets/javascripts/vue_shared/components/notes/skeleton_note.vue b/app/assets/javascripts/vue_shared/components/notes/skeleton_note.vue
index 8cb72afcdc0..2dcd161b4fb 100644
--- a/app/assets/javascripts/vue_shared/components/notes/skeleton_note.vue
+++ b/app/assets/javascripts/vue_shared/components/notes/skeleton_note.vue
@@ -1,5 +1,5 @@
<script>
-import { GlSkeletonLoading } from '@gitlab-org/gitlab-ui';
+import { GlSkeletonLoading } from '@gitlab/ui';
export default {
name: 'SkeletonNote',
diff --git a/app/assets/javascripts/vue_shared/components/pagination_links.vue b/app/assets/javascripts/vue_shared/components/pagination_links.vue
index 89dcf049f6e..0b44f8578cb 100644
--- a/app/assets/javascripts/vue_shared/components/pagination_links.vue
+++ b/app/assets/javascripts/vue_shared/components/pagination_links.vue
@@ -1,5 +1,5 @@
<script>
-import { GlPagination } from '@gitlab-org/gitlab-ui';
+import { GlPagination } from '@gitlab/ui';
import { s__ } from '../../locale';
export default {
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/date_picker.vue b/app/assets/javascripts/vue_shared/components/sidebar/date_picker.vue
index 5b12bb6b59e..6aa880603b9 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/date_picker.vue
+++ b/app/assets/javascripts/vue_shared/components/sidebar/date_picker.vue
@@ -1,5 +1,5 @@
<script>
-import { GlLoadingIcon } from '@gitlab-org/gitlab-ui';
+import { GlLoadingIcon } from '@gitlab/ui';
import datePicker from '../pikaday.vue';
import toggleSidebar from './toggle_sidebar.vue';
import collapsedCalendarIcon from './collapsed_calendar_icon.vue';
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select/base.vue b/app/assets/javascripts/vue_shared/components/sidebar/labels_select/base.vue
index e50d612ce36..98b8b6460fe 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select/base.vue
+++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select/base.vue
@@ -4,7 +4,7 @@ import { __ } from '~/locale';
import LabelsSelect from '~/labels_select';
import DropdownHiddenInput from '~/vue_shared/components/dropdown/dropdown_hidden_input.vue';
-import { GlLoadingIcon } from '@gitlab-org/gitlab-ui';
+import { GlLoadingIcon } from '@gitlab/ui';
import DropdownTitle from './dropdown_title.vue';
import DropdownValue from './dropdown_value.vue';
import DropdownValueCollapsed from './dropdown_value_collapsed.vue';
diff --git a/app/assets/javascripts/vue_shared/components/toggle_button.vue b/app/assets/javascripts/vue_shared/components/toggle_button.vue
index e7cb5cfac12..5d1c92c3b3d 100644
--- a/app/assets/javascripts/vue_shared/components/toggle_button.vue
+++ b/app/assets/javascripts/vue_shared/components/toggle_button.vue
@@ -1,5 +1,5 @@
<script>
-import { GlLoadingIcon } from '@gitlab-org/gitlab-ui';
+import { GlLoadingIcon } from '@gitlab/ui';
import { s__ } from '../../locale';
import icon from './icon.vue';
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 4cfb1ded0a9..c78d98ccd9e 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
@@ -15,7 +15,7 @@
*/
-import { GlTooltip } from '@gitlab-org/gitlab-ui';
+import { GlTooltip } from '@gitlab/ui';
import defaultAvatarUrl from 'images/no_avatar.png';
import { placeholderImage } from '../../../lazy_loader';
diff --git a/app/assets/javascripts/vue_shared/components/user_avatar/user_avatar_link.vue b/app/assets/javascripts/vue_shared/components/user_avatar/user_avatar_link.vue
index 351a639c6e8..6dd519ea56d 100644
--- a/app/assets/javascripts/vue_shared/components/user_avatar/user_avatar_link.vue
+++ b/app/assets/javascripts/vue_shared/components/user_avatar/user_avatar_link.vue
@@ -17,7 +17,7 @@
*/
-import { GlLink, GlTooltipDirective } from '@gitlab-org/gitlab-ui';
+import { GlLink, GlTooltipDirective } from '@gitlab/ui';
import userAvatarImage from './user_avatar_image.vue';
export default {
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index 7f4aa8244ac..b839da7770d 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -181,11 +181,11 @@ class ApplicationController < ActionController::Base
Ability.allowed?(object, action, subject)
end
- def access_denied!(message = nil)
+ def access_denied!(message = nil, status = nil)
# If we display a custom access denied message to the user, we don't want to
# hide existence of the resource, rather tell them they cannot access it using
# the provided message
- status = message.present? ? :forbidden : :not_found
+ status ||= message.present? ? :forbidden : :not_found
respond_to do |format|
format.any { head status }
diff --git a/app/controllers/concerns/issuable_collections.rb b/app/controllers/concerns/issuable_collections.rb
index 5217b4be928..34a8c50fcbd 100644
--- a/app/controllers/concerns/issuable_collections.rb
+++ b/app/controllers/concerns/issuable_collections.rb
@@ -81,36 +81,36 @@ module IssuableCollections
end
def issuable_finder_for(finder_class)
- finder_class.new(current_user, filter_params)
+ finder_class.new(current_user, finder_options)
end
# rubocop:disable Gitlab/ModuleWithInstanceVariables
- # rubocop: disable CodeReuse/ActiveRecord
- def filter_params
- set_sort_order_from_cookie
- set_default_state
+ def finder_options
+ params[:state] = default_state if params[:state].blank?
- # Skip irrelevant Rails routing params
- @filter_params = params.dup.except(:controller, :action, :namespace_id)
- @filter_params[:sort] ||= default_sort_order
+ options = {
+ scope: params[:scope],
+ state: params[:state],
+ sort: set_sort_order_from_cookie || default_sort_order
+ }
- @sort = @filter_params[:sort]
+ # Used by view to highlight active option
+ @sort = options[:sort]
if @project
- @filter_params[:project_id] = @project.id
+ options[:project_id] = @project.id
elsif @group
- @filter_params[:group_id] = @group.id
- @filter_params[:include_subgroups] = true
- @filter_params[:use_cte_for_search] = true
+ options[:group_id] = @group.id
+ options[:include_subgroups] = true
+ options[:use_cte_for_search] = true
end
- @filter_params.permit(finder_type.valid_params)
+ params.permit(finder_type.valid_params).merge(options)
end
- # rubocop: enable CodeReuse/ActiveRecord
# rubocop:enable Gitlab/ModuleWithInstanceVariables
- def set_default_state
- params[:state] = 'opened' if params[:state].blank?
+ def default_state
+ 'opened'
end
def set_sort_order_from_cookie
@@ -121,7 +121,7 @@ module IssuableCollections
sort_value = update_cookie_value(sort_param)
set_secure_cookie(remember_sorting_key, sort_value)
- params[:sort] = sort_value
+ sort_value
end
def remember_sorting_key
diff --git a/app/controllers/concerns/merge_requests_action.rb b/app/controllers/concerns/merge_requests_action.rb
index 285f2c3a8a0..ed10f32512e 100644
--- a/app/controllers/concerns/merge_requests_action.rb
+++ b/app/controllers/concerns/merge_requests_action.rb
@@ -19,7 +19,7 @@ module MergeRequestsAction
(MergeRequestsFinder if action_name == 'merge_requests')
end
- def filter_params
+ def finder_options
super.merge(non_archived: true)
end
end
diff --git a/app/controllers/dashboard_controller.rb b/app/controllers/dashboard_controller.rb
index c032fb2efb5..4ce9be44403 100644
--- a/app/controllers/dashboard_controller.rb
+++ b/app/controllers/dashboard_controller.rb
@@ -4,13 +4,6 @@ class DashboardController < Dashboard::ApplicationController
include IssuesAction
include MergeRequestsAction
- FILTER_PARAMS = [
- :author_id,
- :assignee_id,
- :milestone_title,
- :label_name
- ].freeze
-
before_action :event_filter, only: :activity
before_action :projects, only: [:issues, :merge_requests]
before_action :set_show_full_reference, only: [:issues, :merge_requests]
@@ -51,10 +44,13 @@ class DashboardController < Dashboard::ApplicationController
end
def check_filters_presence!
- @no_filters_set = FILTER_PARAMS.none? { |k| params.key?(k) }
+ @no_filters_set = finder_type.scalar_params.none? { |k| params.key?(k) }
return unless @no_filters_set
+ # Call to set selected `state` and `sort` options in view
+ finder_options
+
respond_to do |format|
format.html { render }
format.atom { head :bad_request }
diff --git a/app/controllers/projects/deploy_keys_controller.rb b/app/controllers/projects/deploy_keys_controller.rb
index 92ef10a9ef5..0a593bd35b6 100644
--- a/app/controllers/projects/deploy_keys_controller.rb
+++ b/app/controllers/projects/deploy_keys_controller.rb
@@ -46,7 +46,9 @@ class Projects::DeployKeysController < Projects::ApplicationController
end
def enable
- Projects::EnableDeployKeyService.new(@project, current_user, params).execute
+ key = Projects::EnableDeployKeyService.new(@project, current_user, params).execute
+
+ return render_404 unless key
respond_to do |format|
format.html { redirect_to_repository_settings(@project, anchor: 'js-deploy-keys-settings') }
@@ -54,19 +56,16 @@ class Projects::DeployKeysController < Projects::ApplicationController
end
end
- # rubocop: disable CodeReuse/ActiveRecord
def disable
- deploy_key_project = @project.deploy_keys_projects.find_by(deploy_key_id: params[:id])
- return render_404 unless deploy_key_project
+ deploy_key_project = Projects::DisableDeployKeyService.new(@project, current_user, params).execute
- deploy_key_project.destroy!
+ return render_404 unless deploy_key_project
respond_to do |format|
format.html { redirect_to_repository_settings(@project, anchor: 'js-deploy-keys-settings') }
format.json { head :ok }
end
end
- # rubocop: enable CodeReuse/ActiveRecord
protected
diff --git a/app/controllers/root_controller.rb b/app/controllers/root_controller.rb
index ebf70f25bda..7b6657e1196 100644
--- a/app/controllers/root_controller.rb
+++ b/app/controllers/root_controller.rb
@@ -45,9 +45,9 @@ class RootController < Dashboard::ProjectsController
when 'todos'
redirect_to(dashboard_todos_path)
when 'issues'
- redirect_to(issues_dashboard_path(assignee_id: current_user.id))
+ redirect_to(issues_dashboard_path(assignee_username: current_user.username))
when 'merge_requests'
- redirect_to(merge_requests_dashboard_path(assignee_id: current_user.id))
+ redirect_to(merge_requests_dashboard_path(assignee_username: current_user.username))
end
end
diff --git a/app/finders/events_finder.rb b/app/finders/events_finder.rb
index 2e82bda8730..8df01f1dad9 100644
--- a/app/finders/events_finder.rb
+++ b/app/finders/events_finder.rb
@@ -58,7 +58,7 @@ class EventsFinder
def by_target_type(events)
return events unless Event::TARGET_TYPES[params[:target_type]]
- events.where(target_type: Event::TARGET_TYPES[params[:target_type]])
+ events.where(target_type: Event::TARGET_TYPES[params[:target_type]].name)
end
# rubocop: enable CodeReuse/ActiveRecord
diff --git a/app/finders/group_descendants_finder.rb b/app/finders/group_descendants_finder.rb
index c96979619fd..a9ce5be13f3 100644
--- a/app/finders/group_descendants_finder.rb
+++ b/app/finders/group_descendants_finder.rb
@@ -178,7 +178,7 @@ class GroupDescendantsFinder
end
def sort
- params.fetch(:sort, 'id_asc')
+ params.fetch(:sort, 'created_desc')
end
# rubocop: disable CodeReuse/ActiveRecord
diff --git a/app/finders/issuable_finder.rb b/app/finders/issuable_finder.rb
index 93bef592c65..fdc630cbf72 100644
--- a/app/finders/issuable_finder.rb
+++ b/app/finders/issuable_finder.rb
@@ -14,7 +14,9 @@
# project_id: integer
# milestone_title: string
# author_id: integer
+# author_username: string
# assignee_id: integer or 'None' or 'Any'
+# assignee_username: string
# search: string
# label_name: string
# sort: string
@@ -49,25 +51,15 @@ class IssuableFinder
assignee_username
author_id
author_username
- authorized_only
- group_id
- iids
label_name
milestone_title
my_reaction_emoji
- non_archived
- project_id
- scope
search
- sort
- state
- include_subgroups
- use_cte_for_search
]
end
def self.array_params
- @array_params ||= { label_name: [], iids: [], assignee_username: [] }
+ @array_params ||= { label_name: [], assignee_username: [] }
end
def self.valid_params
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index 4f91e3e4117..74042f0bae8 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -173,17 +173,7 @@ module ApplicationHelper
without = options.delete(:without)
add_label = options.delete(:label)
- exist_opts = {
- state: params[:state],
- scope: params[:scope],
- milestone_title: params[:milestone_title],
- assignee_id: params[:assignee_id],
- author_id: params[:author_id],
- search: params[:search],
- label_name: params[:label_name]
- }
-
- options = exist_opts.merge(options)
+ options = request.query_parameters.merge(options)
if without.present?
without.each do |key|
diff --git a/app/helpers/auth_helper.rb b/app/helpers/auth_helper.rb
index c158cf20dd6..44f85e9c0f8 100644
--- a/app/helpers/auth_helper.rb
+++ b/app/helpers/auth_helper.rb
@@ -24,6 +24,23 @@ module AuthHelper
Gitlab::Auth::OAuth::Provider.label_for(name)
end
+ def form_based_provider_priority
+ ['crowd', /^ldap/, 'kerberos']
+ end
+
+ def form_based_provider_with_highest_priority
+ @form_based_provider_with_highest_priority ||= begin
+ form_based_provider_priority.each do |provider_regexp|
+ highest_priority = form_based_providers.find { |provider| provider.match?(provider_regexp) }
+ break highest_priority unless highest_priority.nil?
+ end
+ end
+ end
+
+ def form_based_auth_provider_has_active_class?(provider)
+ form_based_provider_with_highest_priority == provider
+ end
+
def form_based_provider?(name)
[LDAP_PROVIDER, 'crowd'].any? { |pattern| pattern === name.to_s }
end
diff --git a/app/helpers/dashboard_helper.rb b/app/helpers/dashboard_helper.rb
index 463f4145bdd..d90ef8903a7 100644
--- a/app/helpers/dashboard_helper.rb
+++ b/app/helpers/dashboard_helper.rb
@@ -2,11 +2,11 @@
module DashboardHelper
def assigned_issues_dashboard_path
- issues_dashboard_path(assignee_id: current_user.id)
+ issues_dashboard_path(assignee_username: current_user.username)
end
def assigned_mrs_dashboard_path
- merge_requests_dashboard_path(assignee_id: current_user.id)
+ merge_requests_dashboard_path(assignee_username: current_user.username)
end
def dashboard_nav_links
diff --git a/app/helpers/search_helper.rb b/app/helpers/search_helper.rb
index 4f9e1322b56..80cc568820a 100644
--- a/app/helpers/search_helper.rb
+++ b/app/helpers/search_helper.rb
@@ -163,15 +163,26 @@ module SearchHelper
if @project.present?
opts[:data]['project-id'] = @project.id
opts[:data]['base-endpoint'] = project_path(@project)
- else
- # Group context
+ elsif @group.present?
opts[:data]['group-id'] = @group.id
opts[:data]['base-endpoint'] = group_canonical_path(@group)
+ else
+ opts[:data]['base-endpoint'] = root_dashboard_path
end
opts
end
+ def search_history_storage_prefix
+ if @project.present?
+ @project.full_path
+ elsif @group.present?
+ @group.full_path
+ else
+ 'dashboard'
+ end
+ end
+
# Sanitize a HTML field for search display. Most tags are stripped out and the
# maximum length is set to 200 characters.
def search_md_sanitize(object, field)
diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb
index 889f8ce27a6..d60861dc95f 100644
--- a/app/models/ci/build.rb
+++ b/app/models/ci/build.rb
@@ -98,7 +98,7 @@ module Ci
scope :matches_tag_ids, -> (tag_ids) do
matcher = ::ActsAsTaggableOn::Tagging
- .where(taggable_type: CommitStatus)
+ .where(taggable_type: CommitStatus.name)
.where(context: 'tags')
.where('taggable_id = ci_builds.id')
.where.not(tag_id: tag_ids).select('1')
@@ -108,7 +108,7 @@ module Ci
scope :with_any_tags, -> do
matcher = ::ActsAsTaggableOn::Tagging
- .where(taggable_type: CommitStatus)
+ .where(taggable_type: CommitStatus.name)
.where(context: 'tags')
.where('taggable_id = ci_builds.id').select('1')
@@ -464,7 +464,9 @@ module Ci
end
def repo_url
- auth = "gitlab-ci-token:#{ensure_token!}@"
+ return unless token
+
+ auth = "gitlab-ci-token:#{token}@"
project.http_url_to_repo.sub(%r{^https?://}) do |prefix|
prefix + auth
end
@@ -725,7 +727,7 @@ module Ci
trace = trace.dup
Gitlab::Ci::MaskSecret.mask!(trace, project.runners_token) if project
- Gitlab::Ci::MaskSecret.mask!(trace, token)
+ Gitlab::Ci::MaskSecret.mask!(trace, token) if token
trace
end
@@ -814,12 +816,12 @@ module Ci
.concat(pipeline.persisted_variables)
.append(key: 'CI_JOB_ID', value: id.to_s)
.append(key: 'CI_JOB_URL', value: Gitlab::Routing.url_helpers.project_job_url(project, self))
- .append(key: 'CI_JOB_TOKEN', value: token, public: false)
+ .append(key: 'CI_JOB_TOKEN', value: token.to_s, public: false)
.append(key: 'CI_BUILD_ID', value: id.to_s)
- .append(key: 'CI_BUILD_TOKEN', value: token, public: false)
+ .append(key: 'CI_BUILD_TOKEN', value: token.to_s, public: false)
.append(key: 'CI_REGISTRY_USER', value: CI_REGISTRY_USER)
- .append(key: 'CI_REGISTRY_PASSWORD', value: token, public: false)
- .append(key: 'CI_REPOSITORY_URL', value: repo_url, public: false)
+ .append(key: 'CI_REGISTRY_PASSWORD', value: token.to_s, public: false)
+ .append(key: 'CI_REPOSITORY_URL', value: repo_url.to_s, public: false)
.concat(deploy_token_variables)
end
end
@@ -831,9 +833,9 @@ module Ci
variables.append(key: 'GITLAB_FEATURES', value: project.licensed_features.join(','))
variables.append(key: 'CI_SERVER_NAME', value: 'GitLab')
variables.append(key: 'CI_SERVER_VERSION', value: Gitlab::VERSION)
- variables.append(key: 'CI_SERVER_VERSION_MAJOR', value: gitlab_version_info.major.to_s)
- variables.append(key: 'CI_SERVER_VERSION_MINOR', value: gitlab_version_info.minor.to_s)
- variables.append(key: 'CI_SERVER_VERSION_PATCH', value: gitlab_version_info.patch.to_s)
+ variables.append(key: 'CI_SERVER_VERSION_MAJOR', value: Gitlab.version_info.major.to_s)
+ variables.append(key: 'CI_SERVER_VERSION_MINOR', value: Gitlab.version_info.minor.to_s)
+ variables.append(key: 'CI_SERVER_VERSION_PATCH', value: Gitlab.version_info.patch.to_s)
variables.append(key: 'CI_SERVER_REVISION', value: Gitlab.revision)
variables.append(key: 'CI_JOB_NAME', value: name)
variables.append(key: 'CI_JOB_STAGE', value: stage)
@@ -850,10 +852,6 @@ module Ci
end
end
- def gitlab_version_info
- @gitlab_version_info ||= Gitlab::VersionInfo.parse(Gitlab::VERSION)
- end
-
def legacy_variables
Gitlab::Ci::Variables::Collection.new.tap do |variables|
variables.append(key: 'CI_BUILD_REF', value: sha)
diff --git a/app/models/clusters/kubernetes_namespace.rb b/app/models/clusters/kubernetes_namespace.rb
index cbd52bfb48b..34f5e38ff79 100644
--- a/app/models/clusters/kubernetes_namespace.rb
+++ b/app/models/clusters/kubernetes_namespace.rb
@@ -11,9 +11,13 @@ module Clusters
belongs_to :project, class_name: '::Project'
has_one :platform_kubernetes, through: :cluster
+ before_validation :set_defaults
+
validates :namespace, presence: true
validates :namespace, uniqueness: { scope: :cluster_id }
+ validates :service_account_name, presence: true
+
delegate :ca_pem, to: :platform_kubernetes, allow_nil: true
delegate :api_url, to: :platform_kubernetes, allow_nil: true
@@ -28,38 +32,43 @@ module Clusters
"#{namespace}-token"
end
- def configure_predefined_credentials
- self.namespace = kubernetes_or_project_namespace
- self.service_account_name = default_service_account_name
- end
-
def predefined_variables
config = YAML.dump(kubeconfig)
Gitlab::Ci::Variables::Collection.new.tap do |variables|
variables
- .append(key: 'KUBE_SERVICE_ACCOUNT', value: service_account_name)
- .append(key: 'KUBE_NAMESPACE', value: namespace)
- .append(key: 'KUBE_TOKEN', value: service_account_token, public: false)
+ .append(key: 'KUBE_SERVICE_ACCOUNT', value: service_account_name.to_s)
+ .append(key: 'KUBE_NAMESPACE', value: namespace.to_s)
+ .append(key: 'KUBE_TOKEN', value: service_account_token.to_s, public: false)
.append(key: 'KUBECONFIG', value: config, public: false, file: true)
end
end
- private
-
- def kubernetes_or_project_namespace
- platform_kubernetes&.namespace.presence || project_namespace
+ def set_defaults
+ self.namespace ||= default_platform_kubernetes_namespace
+ self.namespace ||= default_project_namespace
+ self.service_account_name ||= default_service_account_name
end
+ private
+
def default_service_account_name
+ return unless namespace
+
"#{namespace}-service-account"
end
- def project_namespace
- Gitlab::NamespaceSanitizer.sanitize(project_slug)
+ def default_platform_kubernetes_namespace
+ platform_kubernetes&.namespace.presence
+ end
+
+ def default_project_namespace
+ Gitlab::NamespaceSanitizer.sanitize(project_slug) if project_slug
end
def project_slug
+ return unless project
+
"#{project.path}-#{project.id}".downcase
end
diff --git a/app/models/commit.rb b/app/models/commit.rb
index 9dd0cbacd9e..546fcc54a15 100644
--- a/app/models/commit.rb
+++ b/app/models/commit.rb
@@ -230,24 +230,13 @@ class Commit
def lazy_author
BatchLoader.for(author_email.downcase).batch do |emails, loader|
- # A Hash that maps user Emails to the corresponding User objects. The
- # Emails at this point are the _primary_ Emails of the Users.
- users_for_emails = User
- .by_any_email(emails)
- .each_with_object({}) { |user, hash| hash[user.email] = user }
-
- users_for_ids = users_for_emails
- .values
- .each_with_object({}) { |user, hash| hash[user.id] = user }
-
- # Some commits may have used an alternative Email address. In this case we
- # need to query the "emails" table to map those addresses to User objects.
- Email
- .where(email: emails - users_for_emails.keys)
- .pluck(:email, :user_id)
- .each { |(email, id)| users_for_emails[email] = users_for_ids[id] }
-
- users_for_emails.each { |email, user| loader.call(email, user) }
+ users = User.by_any_email(emails).includes(:emails)
+
+ emails.each do |email|
+ user = users.find { |u| u.any_email?(email) }
+
+ loader.call(email, user)
+ end
end
end
diff --git a/app/models/concerns/avatarable.rb b/app/models/concerns/avatarable.rb
index 0d5311a9985..b42236c1fa2 100644
--- a/app/models/concerns/avatarable.rb
+++ b/app/models/concerns/avatarable.rb
@@ -86,7 +86,7 @@ module Avatarable
params[:model].upload_paths(params[:identifier])
end
- Upload.where(uploader: AvatarUploader, path: paths).find_each do |upload|
+ Upload.where(uploader: AvatarUploader.name, path: paths).find_each do |upload|
model = model_class.instantiate('id' => upload.model_id)
loader.call({ model: model, identifier: File.basename(upload.path) }, upload)
diff --git a/app/models/member.rb b/app/models/member.rb
index 0696ea46c8b..bc8ac14d148 100644
--- a/app/models/member.rb
+++ b/app/models/member.rb
@@ -152,11 +152,13 @@ class Member < ActiveRecord::Base
return member unless can_update_member?(current_user, member)
- member.attributes = {
- created_by: member.created_by || current_user,
- access_level: access_level,
- expires_at: expires_at
- }
+ set_member_attributes(
+ member,
+ access_level,
+ current_user: current_user,
+ expires_at: expires_at,
+ ldap: ldap
+ )
if member.request?
::Members::ApproveAccessRequestService.new(
@@ -175,6 +177,18 @@ class Member < ActiveRecord::Base
# rubocop: enable CodeReuse/ServiceClass
end
+ # Populates the attributes of a member.
+ #
+ # This logic resides in a separate method so that EE can extend this logic,
+ # without having to patch the `add_user` method directly.
+ def set_member_attributes(member, access_level, current_user: nil, expires_at: nil, ldap: false)
+ member.attributes = {
+ created_by: member.created_by || current_user,
+ access_level: access_level,
+ expires_at: expires_at
+ }
+ end
+
def add_users(source, users, access_level, current_user: nil, expires_at: nil)
return [] unless users.present?
diff --git a/app/models/project.rb b/app/models/project.rb
index ab19190385e..4d1917b9ab2 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -1964,7 +1964,7 @@ class Project < ActiveRecord::Base
end
def migrate_to_hashed_storage!
- return if hashed_storage?(:repository)
+ return unless storage_upgradable?
update!(repository_read_only: true)
diff --git a/app/models/project_services/chat_message/push_message.rb b/app/models/project_services/chat_message/push_message.rb
index 82be33a12a1..5dd0414b7e6 100644
--- a/app/models/project_services/chat_message/push_message.rb
+++ b/app/models/project_services/chat_message/push_message.rb
@@ -26,16 +26,8 @@ module ChatMessage
end
def activity
- action = if new_branch?
- "created"
- elsif removed_branch?
- "removed"
- else
- "pushed to"
- end
-
{
- title: "#{user_combined_name} #{action} #{ref_type}",
+ title: humanized_action(short: true),
subtitle: "in #{project_link}",
text: compare_link,
image: user_avatar
@@ -44,32 +36,21 @@ module ChatMessage
private
+ def humanized_action(short: false)
+ action, ref_link, target_link = compose_action_details
+ text = [user_combined_name, action, ref_type, ref_link]
+ text << target_link unless short
+ text.join(' ')
+ end
+
def message
- if new_branch?
- new_branch_message
- elsif removed_branch?
- removed_branch_message
- else
- push_message
- end
+ humanized_action
end
def format(string)
Slack::Notifier::LinkFormatter.format(string)
end
- def new_branch_message
- "#{user_combined_name} pushed new #{ref_type} #{branch_link} to #{project_link}"
- end
-
- def removed_branch_message
- "#{user_combined_name} removed #{ref_type} #{ref} from #{project_link}"
- end
-
- def push_message
- "#{user_combined_name} pushed to #{ref_type} #{branch_link} of #{project_link} (#{compare_link})"
- end
-
def commit_messages
commits.map { |commit| compose_commit_message(commit) }.join("\n\n")
end
@@ -115,6 +96,16 @@ module ChatMessage
"[Compare changes](#{compare_url})"
end
+ def compose_action_details
+ if new_branch?
+ ['pushed new', branch_link, "to #{project_link}"]
+ elsif removed_branch?
+ ['removed', ref, "from #{project_link}"]
+ else
+ ['pushed to', branch_link, "of #{project_link} (#{compare_link})"]
+ end
+ end
+
def attachment_color
'#345'
end
diff --git a/app/models/user.rb b/app/models/user.rb
index a400058e87e..01eba7e0426 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -349,20 +349,28 @@ class User < ActiveRecord::Base
def find_by_any_email(email, confirmed: false)
return unless email
- downcased = email.downcase
-
- find_by_private_commit_email(downcased) || by_any_email(downcased, confirmed: confirmed).take
+ by_any_email(email, confirmed: confirmed).take
end
- # Returns a relation containing all the users for the given Email address
- def by_any_email(email, confirmed: false)
- users = where(email: email)
- users = users.confirmed if confirmed
+ # Returns a relation containing all the users for the given email addresses
+ #
+ # @param emails [String, Array<String>] email addresses to check
+ # @param confirmed [Boolean] Only return users where the email is confirmed
+ def by_any_email(emails, confirmed: false)
+ emails = Array(emails).map(&:downcase)
+
+ from_users = where(email: emails)
+ from_users = from_users.confirmed if confirmed
- emails = joins(:emails).where(emails: { email: email })
- emails = emails.confirmed if confirmed
+ from_emails = joins(:emails).where(emails: { email: emails })
+ from_emails = from_emails.confirmed if confirmed
- from_union([users, emails])
+ items = [from_users, from_emails]
+
+ user_ids = Gitlab::PrivateCommitEmail.user_ids_for_emails(emails)
+ items << where(id: user_ids) if user_ids.present?
+
+ from_union(items)
end
def find_by_private_commit_email(email)
@@ -1031,6 +1039,7 @@ class User < ActiveRecord::Base
def all_emails
all_emails = []
all_emails << email unless temp_oauth_email?
+ all_emails << private_commit_email
all_emails.concat(emails.map(&:email))
all_emails
end
@@ -1043,16 +1052,24 @@ class User < ActiveRecord::Base
verified_emails
end
+ def any_email?(check_email)
+ downcased = check_email.downcase
+
+ # handle the outdated private commit email case
+ return true if persisted? &&
+ id == Gitlab::PrivateCommitEmail.user_id_for_email(downcased)
+
+ all_emails.include?(check_email.downcase)
+ end
+
def verified_email?(check_email)
downcased = check_email.downcase
- if email == downcased
- primary_email_verified?
- else
- user_id = Gitlab::PrivateCommitEmail.user_id_for_email(downcased)
+ # handle the outdated private commit email case
+ return true if persisted? &&
+ id == Gitlab::PrivateCommitEmail.user_id_for_email(downcased)
- user_id == id || emails.confirmed.where(email: downcased).exists?
- end
+ verified_emails.include?(check_email.downcase)
end
def hook_attrs
diff --git a/app/services/clusters/gcp/kubernetes/create_or_update_namespace_service.rb b/app/services/clusters/gcp/kubernetes/create_or_update_namespace_service.rb
index 2b607681082..b31426556f6 100644
--- a/app/services/clusters/gcp/kubernetes/create_or_update_namespace_service.rb
+++ b/app/services/clusters/gcp/kubernetes/create_or_update_namespace_service.rb
@@ -23,7 +23,7 @@ module Clusters
attr_reader :cluster, :kubernetes_namespace, :platform
def configure_kubernetes_namespace
- kubernetes_namespace.configure_predefined_credentials
+ kubernetes_namespace.set_defaults
end
def create_project_service_account
diff --git a/app/services/projects/disable_deploy_key_service.rb b/app/services/projects/disable_deploy_key_service.rb
new file mode 100644
index 00000000000..e483c0708c4
--- /dev/null
+++ b/app/services/projects/disable_deploy_key_service.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+module Projects
+ class DisableDeployKeyService < BaseService
+ def execute
+ # rubocop: disable CodeReuse/ActiveRecord
+ deploy_key_project = project.deploy_keys_projects.find_by(deploy_key_id: params[:id])
+ # rubocop: enable CodeReuse/ActiveRecord
+
+ deploy_key_project&.destroy!
+ end
+ end
+end
diff --git a/app/services/projects/enable_deploy_key_service.rb b/app/services/projects/enable_deploy_key_service.rb
index 102088e9557..38219cacee9 100644
--- a/app/services/projects/enable_deploy_key_service.rb
+++ b/app/services/projects/enable_deploy_key_service.rb
@@ -2,9 +2,10 @@
module Projects
class EnableDeployKeyService < BaseService
- # rubocop: disable CodeReuse/ActiveRecord
def execute
- key = accessible_keys.find_by(id: params[:key_id] || params[:id])
+ key_id = params[:key_id] || params[:id]
+ key = find_accessible_key(key_id)
+
return unless key
unless project.deploy_keys.include?(key)
@@ -13,12 +14,15 @@ module Projects
key
end
- # rubocop: enable CodeReuse/ActiveRecord
private
- def accessible_keys
- current_user.accessible_deploy_keys
+ def find_accessible_key(key_id)
+ if current_user.admin?
+ DeployKey.find_by_id(key_id)
+ else
+ current_user.accessible_deploy_keys.find_by_id(key_id)
+ end
end
end
end
diff --git a/app/services/todos/destroy/entity_leave_service.rb b/app/services/todos/destroy/entity_leave_service.rb
index e8d1bcdd142..ebfb20132d0 100644
--- a/app/services/todos/destroy/entity_leave_service.rb
+++ b/app/services/todos/destroy/entity_leave_service.rb
@@ -45,7 +45,7 @@ module Todos
# rubocop: disable CodeReuse/ActiveRecord
def remove_confidential_issue_todos
Todo.where(
- target_id: confidential_issues.select(:id), target_type: Issue, user_id: user.id
+ target_id: confidential_issues.select(:id), target_type: Issue.name, user_id: user.id
).delete_all
end
# rubocop: enable CodeReuse/ActiveRecord
diff --git a/app/services/todos/destroy/private_features_service.rb b/app/services/todos/destroy/private_features_service.rb
index a8c3fe0ef5a..bd49519d694 100644
--- a/app/services/todos/destroy/private_features_service.rb
+++ b/app/services/todos/destroy/private_features_service.rb
@@ -14,9 +14,9 @@ module Todos
def execute
ProjectFeature.where(project_id: project_ids).each do |project_features|
target_types = []
- target_types << Issue if private?(project_features.issues_access_level)
- target_types << MergeRequest if private?(project_features.merge_requests_access_level)
- target_types << Commit if private?(project_features.repository_access_level)
+ target_types << Issue.name if private?(project_features.issues_access_level)
+ target_types << MergeRequest.name if private?(project_features.merge_requests_access_level)
+ target_types << Commit.name if private?(project_features.repository_access_level)
next if target_types.empty?
diff --git a/app/services/users/build_service.rb b/app/services/users/build_service.rb
index 24ac20fdd29..3f503f3da28 100644
--- a/app/services/users/build_service.rb
+++ b/app/services/users/build_service.rb
@@ -28,7 +28,7 @@ module Users
identity_attrs = params.slice(:extern_uid, :provider)
- if identity_attrs.any?
+ unless identity_attrs.empty?
user.identities.build(identity_attrs)
end
diff --git a/app/views/dashboard/issues.html.haml b/app/views/dashboard/issues.html.haml
index 832ba877558..fdd5c19d562 100644
--- a/app/views/dashboard/issues.html.haml
+++ b/app/views/dashboard/issues.html.haml
@@ -1,6 +1,6 @@
- @hide_top_links = true
- page_title _("Issues")
-- @breadcrumb_link = issues_dashboard_path(assignee_id: current_user.id)
+- @breadcrumb_link = issues_dashboard_path(assignee_username: current_user.username)
= content_for :meta_tags do
= auto_discovery_link_tag(:atom, safe_params.merge(rss_url_options).to_h, title: "#{current_user.name} issues")
@@ -16,7 +16,7 @@
.nav-controls
= render 'shared/issuable/feed_buttons'
-= render 'shared/issuable/filter', type: :issues
+= render 'shared/issuable/search_bar', type: :issues
- if current_user && @no_filters_set
= render 'shared/dashboard/no_filter_selected'
diff --git a/app/views/dashboard/merge_requests.html.haml b/app/views/dashboard/merge_requests.html.haml
index fba8d1cf667..77cfa1271df 100644
--- a/app/views/dashboard/merge_requests.html.haml
+++ b/app/views/dashboard/merge_requests.html.haml
@@ -1,6 +1,6 @@
- @hide_top_links = true
- page_title _("Merge Requests")
-- @breadcrumb_link = merge_requests_dashboard_path(assignee_id: current_user.id)
+- @breadcrumb_link = merge_requests_dashboard_path(assignee_username: current_user.username)
.page-title-holder
%h1.page-title= _('Merge Requests')
@@ -12,7 +12,7 @@
.top-area
= render 'shared/issuable/nav', type: :merge_requests, display_count: !@no_filters_set
-= render 'shared/issuable/filter', type: :merge_requests
+= render 'shared/issuable/search_bar', type: :merge_requests
- if current_user && @no_filters_set
= render 'shared/dashboard/no_filter_selected'
diff --git a/app/views/devise/shared/_signin_box.html.haml b/app/views/devise/shared/_signin_box.html.haml
index 5ddb3ece1cb..ec968e435cd 100644
--- a/app/views/devise/shared/_signin_box.html.haml
+++ b/app/views/devise/shared/_signin_box.html.haml
@@ -1,10 +1,10 @@
- if form_based_providers.any?
- if crowd_enabled?
- .login-box.tab-pane.active{ id: "crowd", role: 'tabpanel' }
+ .login-box.tab-pane{ id: "crowd", role: 'tabpanel', class: active_when(form_based_auth_provider_has_active_class?(:crowd)) }
.login-body
= render 'devise/sessions/new_crowd'
- @ldap_servers.each_with_index do |server, i|
- .login-box.tab-pane{ id: "#{server['provider_name']}", role: 'tabpanel', class: active_when(i.zero? && !crowd_enabled?) }
+ .login-box.tab-pane{ id: "#{server['provider_name']}", role: 'tabpanel', class: active_when(i.zero? && form_based_auth_provider_has_active_class?(:ldapmain)) }
.login-body
= render 'devise/sessions/new_ldap', server: server
- if password_authentication_enabled_for_web?
@@ -12,6 +12,8 @@
.login-body
= render 'devise/sessions/new_base'
+ = render_if_exists 'devise/sessions/new_smartcard'
+
- elsif password_authentication_enabled_for_web?
.login-box.tab-pane.active{ id: 'login-pane', role: 'tabpanel' }
.login-body
diff --git a/app/views/devise/shared/_tabs_ldap.html.haml b/app/views/devise/shared/_tabs_ldap.html.haml
index 7dced0942f5..aee05b6c81c 100644
--- a/app/views/devise/shared/_tabs_ldap.html.haml
+++ b/app/views/devise/shared/_tabs_ldap.html.haml
@@ -1,10 +1,13 @@
%ul.nav-links.new-session-tabs.nav-tabs.nav{ class: ('custom-provider-tabs' if form_based_providers.any?) }
- if crowd_enabled?
%li.nav-item
- = link_to "Crowd", "#crowd", class: 'nav-link active', 'data-toggle' => 'tab'
+ = link_to "Crowd", "#crowd", class: "nav-link #{active_when(form_based_auth_provider_has_active_class?(:crowd))}", 'data-toggle' => 'tab'
- @ldap_servers.each_with_index do |server, i|
%li.nav-item
- = link_to server['label'], "##{server['provider_name']}", class: "nav-link #{active_when(i.zero? && !crowd_enabled?)} qa-ldap-tab", 'data-toggle' => 'tab'
+ = link_to server['label'], "##{server['provider_name']}", class: "nav-link #{active_when(i.zero? && form_based_auth_provider_has_active_class?(:ldapmain))} qa-ldap-tab", 'data-toggle' => 'tab'
+
+ = render_if_exists 'devise/shared/tab_smartcard'
+
- if password_authentication_enabled_for_web?
%li.nav-item
= link_to 'Standard', '#login-pane', class: 'nav-link qa-standard-tab', 'data-toggle' => 'tab'
diff --git a/app/views/projects/environments/_external_url.html.haml b/app/views/projects/environments/_external_url.html.haml
index b3a82d1ef41..82567f88ccc 100644
--- a/app/views/projects/environments/_external_url.html.haml
+++ b/app/views/projects/environments/_external_url.html.haml
@@ -1,4 +1,4 @@
- if environment.external_url && can?(current_user, :read_environment, environment)
= link_to environment.external_url, target: '_blank', rel: 'noopener noreferrer', class: 'btn external-url has-tooltip qa-view-deployment', title: s_('Environments|Open live environment') do
= sprite_icon('external-link')
- View deployment
+ = _("View deployment")
diff --git a/app/views/projects/environments/_form.html.haml b/app/views/projects/environments/_form.html.haml
index f942b936037..cbd5c54cecc 100644
--- a/app/views/projects/environments/_form.html.haml
+++ b/app/views/projects/environments/_form.html.haml
@@ -1,22 +1,21 @@
.row.prepend-top-default.append-bottom-default
.col-lg-3
%h4.prepend-top-0
- Environments
+ = _("Environments")
%p
- Environments allow you to track deployments of your application
- = succeed "." do
- = link_to "Read more about environments", help_page_path("ci/environments")
+ - link_to_read_more = link_to(_("Read more about environments"), help_page_path("ci/environments"))
+ = _("Environments allow you to track deployments of your application %{link_to_read_more}.").html_safe % { link_to_read_more: link_to_read_more }
= form_for [@project.namespace.becomes(Namespace), @project, @environment], html: { class: 'col-lg-9' } do |f|
= form_errors(@environment)
.form-group
- = f.label :name, 'Name', class: 'label-bold'
+ = f.label :name, _('Name'), class: 'label-bold'
= f.text_field :name, required: true, class: 'form-control'
.form-group
- = f.label :external_url, 'External URL', class: 'label-bold'
+ = f.label :external_url, _('External URL'), class: 'label-bold'
= f.url_field :external_url, class: 'form-control'
.form-actions
- = f.submit 'Save', class: 'btn btn-success'
- = link_to 'Cancel', project_environments_path(@project), class: 'btn btn-cancel'
+ = f.submit _('Save'), class: 'btn btn-save'
+ = link_to _('Cancel'), project_environments_path(@project), class: 'btn btn-cancel'
diff --git a/app/views/projects/environments/_metrics_button.html.haml b/app/views/projects/environments/_metrics_button.html.haml
index a4b27575095..c4f19ea79e7 100644
--- a/app/views/projects/environments/_metrics_button.html.haml
+++ b/app/views/projects/environments/_metrics_button.html.haml
@@ -2,6 +2,6 @@
- return unless can?(current_user, :read_environment, environment)
-= link_to environment_metrics_path(environment), title: 'See metrics', class: 'btn metrics-button' do
+= link_to environment_metrics_path(environment), title: _('See metrics'), class: 'btn metrics-button' do
= sprite_icon('chart')
- Monitoring
+ = _("Monitoring")
diff --git a/app/views/projects/environments/edit.html.haml b/app/views/projects/environments/edit.html.haml
index d6ff3f729b4..d581bd3aeab 100644
--- a/app/views/projects/environments/edit.html.haml
+++ b/app/views/projects/environments/edit.html.haml
@@ -1,8 +1,8 @@
- @no_container = true
-- page_title "Edit", @environment.name, "Environments"
+- page_title _("Edit"), @environment.name, _("Environments")
%div{ class: container_class }
%h3.page-title
- Edit environment
+ = _('Edit environment')
%hr
= render 'form'
diff --git a/app/views/projects/environments/folder.html.haml b/app/views/projects/environments/folder.html.haml
index 1ac7dab6775..b7e1cf85cb7 100644
--- a/app/views/projects/environments/folder.html.haml
+++ b/app/views/projects/environments/folder.html.haml
@@ -1,5 +1,5 @@
- @no_container = true
-- page_title "Environments"
+- page_title _("Environments")
#environments-folder-list-view{ data: { endpoint: folder_project_environments_path(@project, @folder, format: :json),
"folder-name" => @folder,
diff --git a/app/views/projects/environments/index.html.haml b/app/views/projects/environments/index.html.haml
index 7ebe617766f..6c0ad34c486 100644
--- a/app/views/projects/environments/index.html.haml
+++ b/app/views/projects/environments/index.html.haml
@@ -1,6 +1,6 @@
- @no_container = true
-- page_title "Environments"
-- add_to_breadcrumbs("Pipelines", project_pipelines_path(@project))
+- page_title _("Environments")
+- add_to_breadcrumbs(_("Pipelines"), project_pipelines_path(@project))
#environments-list-view{ data: { environments_data: environments_list_data,
"can-create-deployment" => can?(current_user, :create_deployment, @project).to_s,
diff --git a/app/views/projects/environments/metrics.html.haml b/app/views/projects/environments/metrics.html.haml
index 4222963a754..7b847a85686 100644
--- a/app/views/projects/environments/metrics.html.haml
+++ b/app/views/projects/environments/metrics.html.haml
@@ -1,5 +1,5 @@
- @no_container = true
-- page_title "Metrics for environment", @environment.name
+- page_title _("Metrics for environment"), @environment.name
.prometheus-container{ class: container_class }
#prometheus-graphs{ data: metrics_data(@project, @environment) }
diff --git a/app/views/projects/environments/new.html.haml b/app/views/projects/environments/new.html.haml
index 62b08e85e22..c1067fdff78 100644
--- a/app/views/projects/environments/new.html.haml
+++ b/app/views/projects/environments/new.html.haml
@@ -1,9 +1,9 @@
- @no_container = true
-- breadcrumb_title "Environments"
-- page_title 'New Environment'
+- breadcrumb_title _("Environments")
+- page_title _("New Environment")
%div{ class: container_class }
%h3.page-title
- New environment
+ = _("New environment")
%hr
= render 'form'
diff --git a/app/views/projects/environments/show.html.haml b/app/views/projects/environments/show.html.haml
index 8c5b6e089ea..d59b2d4fb01 100644
--- a/app/views/projects/environments/show.html.haml
+++ b/app/views/projects/environments/show.html.haml
@@ -1,7 +1,7 @@
- @no_container = true
-- add_to_breadcrumbs "Environments", project_environments_path(@project)
+- add_to_breadcrumbs _("Environments"), project_environments_path(@project)
- breadcrumb_title @environment.name
-- page_title "Environments"
+- page_title _("Environments")
%div{ class: container_class }
- if can?(current_user, :stop_environment, @environment)
@@ -10,7 +10,7 @@
.modal-content
.modal-header
%h4.modal-title.d-flex.mw-100
- Stopping
+ = s_("Environments|Stopping")
%span.has-tooltip.text-truncate.ml-1.mr-1.flex-fill{ title: @environment.name, data: { container: '#stop-environment-modal' } }
= @environment.name
?
@@ -40,7 +40,7 @@
= render 'projects/environments/external_url', environment: @environment
= render 'projects/environments/metrics_button', environment: @environment
- if can?(current_user, :update_environment, @environment)
- = link_to 'Edit', edit_project_environment_path(@project, @environment), class: 'btn'
+ = link_to _('Edit'), edit_project_environment_path(@project, @environment), class: 'btn'
- if can?(current_user, :stop_environment, @environment)
= button_tag class: 'btn btn-danger', type: 'button', data: { toggle: 'modal',
target: '#stop-environment-modal' } do
@@ -52,21 +52,19 @@
.empty-state
.text-content
%h4.state-title
- You don't have any deployments right now.
+ = _("You don't have any deployments right now.")
%p.blank-state-text
- Define environments in the deploy stage(s) in
- %code .gitlab-ci.yml
- to track deployments here.
+ = _("Define environments in the deploy stage(s) in <code>.gitlab-ci.yml</code> to track deployments here.").html_safe
.text-center
= link_to _("Read more"), help_page_path("ci/environments"), class: "btn btn-success"
- else
.table-holder
.ci-table.environments{ role: 'grid' }
.gl-responsive-table-row.table-row-header{ role: 'row' }
- .table-section.section-10{ role: 'columnheader' } ID
- .table-section.section-30{ role: 'columnheader' } Commit
- .table-section.section-25{ role: 'columnheader' } Job
- .table-section.section-15{ role: 'columnheader' } Created
+ .table-section.section-10{ role: 'columnheader' }= _('ID')
+ .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/environments/terminal.html.haml b/app/views/projects/environments/terminal.html.haml
index e40d631a1a1..e837d3d56ac 100644
--- a/app/views/projects/environments/terminal.html.haml
+++ b/app/views/projects/environments/terminal.html.haml
@@ -1,5 +1,5 @@
- @no_container = true
-- page_title "Terminal for environment", @environment.name
+- page_title _("Terminal for environment"), @environment.name
- content_for :page_specific_javascripts do
= stylesheet_link_tag "xterm.css"
@@ -9,7 +9,7 @@
.row
.col-sm-6
%h3.page-title
- Terminal for environment
+ = _("Terminal for environment")
= @environment.name
.col-sm-6
diff --git a/app/views/shared/_labels_row.html.haml b/app/views/shared/_labels_row.html.haml
deleted file mode 100644
index 21b37a7c9ae..00000000000
--- a/app/views/shared/_labels_row.html.haml
+++ /dev/null
@@ -1,5 +0,0 @@
-- labels.each do |label|
- %span.label-row.btn-group{ role: "group", aria: { label: label.name }, style: "color: #{text_color_for_bg(label.color)}" }
- = link_to_label(label, subject: @project, css_class: 'btn btn-transparent')
- %button.btn.btn-transparent.label-remove.js-label-filter-remove{ type: "button", style: "background-color: #{label.color};", data: { label: label.title } }
- = icon("times")
diff --git a/app/views/shared/issuable/_filter.html.haml b/app/views/shared/issuable/_filter.html.haml
deleted file mode 100644
index c7037335866..00000000000
--- a/app/views/shared/issuable/_filter.html.haml
+++ /dev/null
@@ -1,32 +0,0 @@
-.issues-filters
- .issues-details-filters.row-content-block.second-block
- = form_tag page_filter_path(without: [:assignee_id, :author_id, :milestone_title, :label_name, :search]), method: :get, class: 'filter-form js-filter-form' do
- - if params[:search].present?
- = hidden_field_tag :search, params[:search]
- .issues-other-filters
- .filter-item.inline
- - if params[:author_id].present?
- = hidden_field_tag(:author_id, params[:author_id])
- = dropdown_tag(user_dropdown_label(params[:author_id], "Author"), options: { toggle_class: "js-user-search js-filter-submit js-author-search", title: "Filter by author", filter: true, dropdown_class: "dropdown-menu-user dropdown-menu-selectable dropdown-menu-author js-filter-submit",
- placeholder: "Search authors", data: { any_user: "Any Author", first_user: current_user&.username, current_user: true, project_id: @project&.id, group_id: @group&.id, selected: params[:author_id], field_name: "author_id", default_label: "Author" } })
-
- .filter-item.inline
- - if params[:assignee_id].present?
- = hidden_field_tag(:assignee_id, params[:assignee_id])
- = dropdown_tag(user_dropdown_label(params[:assignee_id], "Assignee"), options: { toggle_class: "js-user-search js-filter-submit js-assignee-search", title: "Filter by assignee", filter: true, dropdown_class: "dropdown-menu-user dropdown-menu-selectable dropdown-menu-assignee js-filter-submit",
- placeholder: "Search assignee", data: { any_user: "Any Assignee", first_user: current_user&.username, null_user: true, current_user: true, project_id: @project&.id, group_id: @group&.id, selected: params[:assignee_id], field_name: "assignee_id", default_label: "Assignee" } })
-
- .filter-item.inline.milestone-filter
- = render "shared/issuable/milestone_dropdown", selected: finder.milestones.try(:first), name: :milestone_title, show_any: true, show_upcoming: true, show_started: true
-
- .filter-item.inline.labels-filter
- = render "shared/issuable/label_dropdown", selected: selected_labels, use_id: false, selected_toggle: params[:label_name], data_options: { field_name: "label_name[]" }
-
- - unless @no_filters_set
- .float-right
- = render 'shared/sort_dropdown'
-
- - has_labels = @labels && @labels.any?
- .row-content-block.second-block.filtered-labels{ class: ("hidden" unless has_labels) }
- - if has_labels
- = render 'shared/labels_row', labels: @labels
diff --git a/app/views/shared/issuable/_search_bar.html.haml b/app/views/shared/issuable/_search_bar.html.haml
index 95f32bd0180..824bbe3524b 100644
--- a/app/views/shared/issuable/_search_bar.html.haml
+++ b/app/views/shared/issuable/_search_bar.html.haml
@@ -1,7 +1,6 @@
- type = local_assigns.fetch(:type)
- board = local_assigns.fetch(:board, nil)
- block_css_class = type != :boards_modal ? 'row-content-block second-block' : ''
-- full_path = @project.present? ? @project.full_path : @group.full_path
- user_can_admin_list = board && can?(current_user, :admin_list, board.parent)
- show_sorting_dropdown = local_assigns.fetch(:show_sorting_dropdown, true)
@@ -10,7 +9,7 @@
- if type == :boards
#js-multiple-boards-switcher.inline.boards-switcher{ "v-cloak" => true }
= render_if_exists "shared/boards/switcher", board: board
- = form_tag page_filter_path(without: [:assignee_id, :author_id, :milestone_title, :label_name, :search]), method: :get, class: 'filter-form js-filter-form' do
+ = form_tag page_filter_path, method: :get, class: 'filter-form js-filter-form' do
- if params[:search].present?
= hidden_field_tag :search, params[:search]
- if @can_bulk_update
@@ -25,7 +24,7 @@
dropdown_class: "filtered-search-history-dropdown",
content_class: "filtered-search-history-dropdown-content",
title: "Recent searches" }) do
- .js-filtered-search-history-dropdown{ data: { full_path: full_path } }
+ .js-filtered-search-history-dropdown{ data: { full_path: search_history_storage_prefix } }
.filtered-search-box-input-container.droplab-dropdown
.scroll-container
%ul.tokens-container.list-unstyled
diff --git a/app/views/u2f/_authenticate.html.haml b/app/views/u2f/_authenticate.html.haml
index 1c788b9a737..979f6862de3 100644
--- a/app/views/u2f/_authenticate.html.haml
+++ b/app/views/u2f/_authenticate.html.haml
@@ -1,18 +1,18 @@
#js-authenticate-u2f
-%a.btn.btn-block.btn-info#js-login-2fa-device{ href: '#' } Sign in via 2FA code
+%a.btn.btn-block.btn-info#js-login-2fa-device{ href: '#' }= _("Sign in via 2FA code")
-# haml-lint:disable InlineJavaScript
%script#js-authenticate-u2f-in-progress{ type: "text/template" }
- %p Trying to communicate with your device. Plug it in (if you haven't already) and press the button on the device now.
+ %p= _("Trying to communicate with your device. Plug it in (if you haven't already) and press the button on the device now.")
%script#js-authenticate-u2f-error{ type: "text/template" }
%div
- %p <%= error_message %> (error code: <%= error_code %>)
- %a.btn.btn-block.btn-warning#js-u2f-try-again Try again?
+ %p <%= error_message %> (#{_("error code:")} <%= error_code %>)
+ %a.btn.btn-block.btn-warning#js-u2f-try-again= _("Try again?")
%script#js-authenticate-u2f-authenticated{ type: "text/template" }
%div
- %p We heard back from your U2F device. You have been authenticated.
+ %p= _("We heard back from your U2F device. You have been authenticated.")
= form_tag(new_user_session_path, method: :post, id: 'js-login-u2f-form') do |f|
- resource_params = params[resource_name].presence || params
= hidden_field_tag 'user[remember_me]', resource_params.fetch(:remember_me, 0)
diff --git a/app/views/u2f/_register.html.haml b/app/views/u2f/_register.html.haml
index 39d4d82a77d..f6724f72307 100644
--- a/app/views/u2f/_register.html.haml
+++ b/app/views/u2f/_register.html.haml
@@ -2,39 +2,39 @@
-# haml-lint:disable InlineJavaScript
%script#js-register-u2f-not-supported{ type: "text/template" }
- %p Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer).
+ %p= _("Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer).")
%script#js-register-u2f-setup{ type: "text/template" }
- if current_user.two_factor_otp_enabled?
.row.append-bottom-10
.col-md-4
- %button#js-setup-u2f-device.btn.btn-info.btn-block Set up new U2F device
+ %button#js-setup-u2f-device.btn.btn-info.btn-block= _("Set up new U2F device")
.col-md-8
- %p Your U2F device needs to be set up. Plug it in (if not already) and click the button on the left.
+ %p= _("Your U2F device needs to be set up. Plug it in (if not already) and click the button on the left.")
- else
.row.append-bottom-10
.col-md-4
- %button#js-setup-u2f-device.btn.btn-info.btn-block{ disabled: true } Set up new U2F device
+ %button#js-setup-u2f-device.btn.btn-info.btn-block{ disabled: true }= _("Set up new U2F device")
.col-md-8
- %p.text-warning You need to register a two-factor authentication app before you can set up a U2F device.
+ %p.text-warning= _("You need to register a two-factor authentication app before you can set up a U2F device.")
%script#js-register-u2f-in-progress{ type: "text/template" }
- %p Trying to communicate with your device. Plug it in (if you haven't already) and press the button on the device now.
+ %p= _("Trying to communicate with your device. Plug it in (if you haven't already) and press the button on the device now.")
%script#js-register-u2f-error{ type: "text/template" }
%div
%p
- %span <%= error_message %> (error code: <%= error_code %>)
- %a.btn.btn-warning#js-u2f-try-again Try again?
+ %span <%= error_message %> (#{_("error code:")} <%= error_code %>)
+ %a.btn.btn-warning#js-u2f-try-again= _("Try again?")
%script#js-register-u2f-registered{ type: "text/template" }
.row.append-bottom-10
.col-md-12
- %p Your device was successfully set up! Give it a name and register it with the GitLab server.
+ %p= _("Your device was successfully set up! Give it a name and register it with the GitLab server.")
= form_tag(create_u2f_profile_two_factor_auth_path, method: :post) do
.row.append-bottom-10
.col-md-3
- = text_field_tag 'u2f_registration[name]', nil, class: 'form-control', placeholder: "Pick a name"
+ = text_field_tag 'u2f_registration[name]', nil, class: 'form-control', placeholder: _("Pick a name")
.col-md-3
= hidden_field_tag 'u2f_registration[device_response]', nil, class: 'form-control', required: true, id: "js-device-response"
- = submit_tag "Register U2F device", class: "btn btn-success"
+ = submit_tag _("Register U2F device"), class: "btn btn-success"
diff --git a/app/views/users/_overview.html.haml b/app/views/users/_overview.html.haml
index cf525f2bb2d..b5bc1180290 100644
--- a/app/views/users/_overview.html.haml
+++ b/app/views/users/_overview.html.haml
@@ -1,32 +1,30 @@
.row
+ .col-12
+ .calendar-block.prepend-top-default.append-bottom-default
+ .user-calendar.d-none.d-sm-block{ data: { calendar_path: user_calendar_path(@user, :json), calendar_activities_path: user_calendar_activities_path, utc_offset: Time.zone.utc_offset } }
+ %h4.center.light
+ = spinner nil, true
+ .user-calendar-activities.d-none.d-sm-block
+.row
.col-md-12.col-lg-6
- .calendar-block
- .content-block.hide-bottom-border
- %h4
- = s_('UserProfile|Activity')
- .user-calendar.d-none.d-sm-block.text-left{ data: { calendar_path: user_calendar_path(@user, :json), calendar_activities_path: user_calendar_activities_path, utc_offset: Time.zone.utc_offset } }
- %h4.center.light
- %i.fa.fa-spinner.fa-spin
- .user-calendar-activities.d-none.d-sm-block
-
- if can?(current_user, :read_cross_project)
.activities-block
- .border-bottom.prepend-top-16
- %h5
- = s_('UserProfile|Recent contributions')
+ .prepend-top-16
+ .d-flex.align-items-center.border-bottom
+ %h4.flex-grow
+ = s_('UserProfile|Activity')
+ = link_to s_('UserProfile|View all'), user_activity_path, class: "hide js-view-all"
.overview-content-list{ data: { href: user_path } }
.center.light.loading
- %i.fa.fa-spinner.fa-spin
- .prepend-top-10
- = link_to s_('UserProfile|View all'), user_activity_path, class: "hide js-view-all"
+ = spinner nil, true
.col-md-12.col-lg-6
.projects-block
- .border-bottom.prepend-top-16
- %h4
- = s_('UserProfile|Personal projects')
+ .prepend-top-16
+ .d-flex.align-items-center.border-bottom
+ %h4.flex-grow
+ = s_('UserProfile|Personal projects')
+ = link_to s_('UserProfile|View all'), user_projects_path, class: "hide js-view-all"
.overview-content-list{ data: { href: user_projects_path } }
.center.light.loading
- %i.fa.fa-spinner.fa-spin
- .prepend-top-10
- = link_to s_('UserProfile|View all'), user_projects_path, class: "hide js-view-all"
+ = spinner nil, true
diff --git a/app/views/users/show.html.haml b/app/views/users/show.html.haml
index d6c8420b744..d11476738e4 100644
--- a/app/views/users/show.html.haml
+++ b/app/views/users/show.html.haml
@@ -124,12 +124,6 @@
- if profile_tab?(:activity)
#activity.tab-pane
- .row-content-block.calendar-block.white.second-block.d-none.d-sm-block
- .user-calendar{ data: { calendar_path: user_calendar_path(@user, :json), calendar_activities_path: user_calendar_activities_path, utc_offset: Time.zone.utc_offset } }
- %h4.center.light
- %i.fa.fa-spinner.fa-spin
- .user-calendar-activities
-
- if can?(current_user, :read_cross_project)
%h4.prepend-top-20
= s_('UserProfile|Most Recent Activity')
diff --git a/changelogs/unreleased/49479-hide-unmerged-env-perf-stats.yml b/changelogs/unreleased/49479-hide-unmerged-env-perf-stats.yml
new file mode 100644
index 00000000000..5118949f8a3
--- /dev/null
+++ b/changelogs/unreleased/49479-hide-unmerged-env-perf-stats.yml
@@ -0,0 +1,5 @@
+---
+title: Don't show Memory Usage for unmerged MRs
+merge_request:
+author:
+type: changed
diff --git a/changelogs/unreleased/51959-branch-and-tag-name-links.yml b/changelogs/unreleased/51959-branch-and-tag-name-links.yml
new file mode 100644
index 00000000000..64f1522c70d
--- /dev/null
+++ b/changelogs/unreleased/51959-branch-and-tag-name-links.yml
@@ -0,0 +1,5 @@
+---
+title: Chat message push notifications now include links back to GitLab branches
+merge_request: 22651
+author: Tony Castrogiovanni
+type: added
diff --git a/changelogs/unreleased/52385-search-bar-for-dashboard-list.yml b/changelogs/unreleased/52385-search-bar-for-dashboard-list.yml
new file mode 100644
index 00000000000..a437ae560cb
--- /dev/null
+++ b/changelogs/unreleased/52385-search-bar-for-dashboard-list.yml
@@ -0,0 +1,5 @@
+---
+title: Use search bar for filtering in dashboard issues / MRs
+merge_request: 22641
+author: Heinrich Lee Yu
+type: changed
diff --git a/changelogs/unreleased/52712-further-ui-improvements-to-profile-overview-tab.yml b/changelogs/unreleased/52712-further-ui-improvements-to-profile-overview-tab.yml
new file mode 100644
index 00000000000..65aa9323d2e
--- /dev/null
+++ b/changelogs/unreleased/52712-further-ui-improvements-to-profile-overview-tab.yml
@@ -0,0 +1,5 @@
+---
+title: UI improvements to user's profile
+merge_request: 22977
+author:
+type: other
diff --git a/changelogs/unreleased/53290-incorrect-project-list-order-select-default-label.yml b/changelogs/unreleased/53290-incorrect-project-list-order-select-default-label.yml
new file mode 100644
index 00000000000..d076352a27b
--- /dev/null
+++ b/changelogs/unreleased/53290-incorrect-project-list-order-select-default-label.yml
@@ -0,0 +1,5 @@
+---
+title: Fix default sorting for subgroups and projects list
+merge_request: 23058
+author: Jacopo Beschi @jacopo-beschi
+type: fixed
diff --git a/changelogs/unreleased/53700-hashed-storagemigration.yml b/changelogs/unreleased/53700-hashed-storagemigration.yml
new file mode 100644
index 00000000000..899012ffd22
--- /dev/null
+++ b/changelogs/unreleased/53700-hashed-storagemigration.yml
@@ -0,0 +1,5 @@
+---
+title: 'Hashed Storage: allow migration to be retried in partially migrated projects'
+merge_request: 23087
+author:
+type: fixed
diff --git a/changelogs/unreleased/54004-update-asana-to-0-8-1.yml b/changelogs/unreleased/54004-update-asana-to-0-8-1.yml
new file mode 100644
index 00000000000..a47b4f3c4d9
--- /dev/null
+++ b/changelogs/unreleased/54004-update-asana-to-0-8-1.yml
@@ -0,0 +1,5 @@
+---
+title: Update asana to 0.8.1
+merge_request: 23039
+author: Takuya Noguchi
+type: other
diff --git a/changelogs/unreleased/54010-update-asciidoctor-to-1-5-8.yml b/changelogs/unreleased/54010-update-asciidoctor-to-1-5-8.yml
new file mode 100644
index 00000000000..f0b0aa0ee1c
--- /dev/null
+++ b/changelogs/unreleased/54010-update-asciidoctor-to-1-5-8.yml
@@ -0,0 +1,5 @@
+---
+title: Update asciidoctor to 1.5.8
+merge_request: 23047
+author: Takuya Noguchi
+type: other
diff --git a/changelogs/unreleased/54015-Markdown-Editor-improve-Cursor-placement.yml b/changelogs/unreleased/54015-Markdown-Editor-improve-Cursor-placement.yml
new file mode 100644
index 00000000000..28e3fae01a9
--- /dev/null
+++ b/changelogs/unreleased/54015-Markdown-Editor-improve-Cursor-placement.yml
@@ -0,0 +1,5 @@
+---
+title: Refine cursor positioning in Markdown Editor for wrap tags
+merge_request: 23085
+author: Johann Hubert Sonntagbauer
+type: changed
diff --git a/changelogs/unreleased/54093-the-default_value_for-gem-doesn-t-handle-actioncontroller-parameters-correctly.yml b/changelogs/unreleased/54093-the-default_value_for-gem-doesn-t-handle-actioncontroller-parameters-correctly.yml
new file mode 100644
index 00000000000..3d6fd2d065a
--- /dev/null
+++ b/changelogs/unreleased/54093-the-default_value_for-gem-doesn-t-handle-actioncontroller-parameters-correctly.yml
@@ -0,0 +1,7 @@
+---
+title: Fixes an issue where default values from models would override values set in
+ the interface (e.g. users would be set to external even though their emails matches
+ the internal email address pattern)
+merge_request: 23114
+author:
+type: fixed
diff --git a/changelogs/unreleased/an-gitaly-version-0-133-0.yml b/changelogs/unreleased/an-gitaly-version-0-133-0.yml
new file mode 100644
index 00000000000..4f3943ceacb
--- /dev/null
+++ b/changelogs/unreleased/an-gitaly-version-0-133-0.yml
@@ -0,0 +1,5 @@
+---
+title: Updated Gitaly to v0.133.0
+merge_request: 23148
+author:
+type: other
diff --git a/changelogs/unreleased/auto-devops-support-for-group-security-dashboard.yml b/changelogs/unreleased/auto-devops-support-for-group-security-dashboard.yml
new file mode 100644
index 00000000000..7fb11f24902
--- /dev/null
+++ b/changelogs/unreleased/auto-devops-support-for-group-security-dashboard.yml
@@ -0,0 +1,5 @@
+---
+title: Auto DevOps support for Group Security Dashboard
+merge_request: 23165
+author:
+type: fixed
diff --git a/changelogs/unreleased/drop-default-value-status-deployments.yml b/changelogs/unreleased/drop-default-value-status-deployments.yml
new file mode 100644
index 00000000000..fdb826a0507
--- /dev/null
+++ b/changelogs/unreleased/drop-default-value-status-deployments.yml
@@ -0,0 +1,5 @@
+---
+title: Drop default value on status column in deployments table
+merge_request: 22971
+author:
+type: other
diff --git a/changelogs/unreleased/fix-not-render-emoji.yml b/changelogs/unreleased/fix-not-render-emoji.yml
new file mode 100644
index 00000000000..857b97004f0
--- /dev/null
+++ b/changelogs/unreleased/fix-not-render-emoji.yml
@@ -0,0 +1,5 @@
+---
+title: Fix not render emoji in filter dropdown
+merge_request: 23112
+author: Hiroyuki Sato
+type: fixed
diff --git a/changelogs/unreleased/frozen-string-lib-gitlab-even-even-more.yml b/changelogs/unreleased/frozen-string-lib-gitlab-even-even-more.yml
new file mode 100644
index 00000000000..e718d716647
--- /dev/null
+++ b/changelogs/unreleased/frozen-string-lib-gitlab-even-even-more.yml
@@ -0,0 +1,5 @@
+---
+title: Enable even more frozen string for lib/gitlab
+merge_request:
+author: gfyoung
+type: performance
diff --git a/changelogs/unreleased/gt-fix-typo-in-notebook-props.yml b/changelogs/unreleased/gt-fix-typo-in-notebook-props.yml
new file mode 100644
index 00000000000..60603905a2d
--- /dev/null
+++ b/changelogs/unreleased/gt-fix-typo-in-notebook-props.yml
@@ -0,0 +1,5 @@
+---
+title: Fix typo in notebook props
+merge_request: 23103
+author: George Tsiolis
+type: other
diff --git a/changelogs/unreleased/rails5-active-record-class-value.yml b/changelogs/unreleased/rails5-active-record-class-value.yml
new file mode 100644
index 00000000000..9f9fdf10cd1
--- /dev/null
+++ b/changelogs/unreleased/rails5-active-record-class-value.yml
@@ -0,0 +1,5 @@
+---
+title: 'Rails5: Passing a class as a value in an Active Record query is deprecated'
+merge_request: 23164
+author: Jasper Maes
+type: other
diff --git a/changelogs/unreleased/security-2717-xss-username-autocomplete.yml b/changelogs/unreleased/security-2717-xss-username-autocomplete.yml
new file mode 100644
index 00000000000..d9b1015eeb4
--- /dev/null
+++ b/changelogs/unreleased/security-2717-xss-username-autocomplete.yml
@@ -0,0 +1,5 @@
+---
+title: Escape user fullname while rendering autocomplete template to prevent XSS
+merge_request:
+author:
+type: security
diff --git a/changelogs/unreleased/sh-bump-gems-security.yml b/changelogs/unreleased/sh-bump-gems-security.yml
new file mode 100644
index 00000000000..06489f6f979
--- /dev/null
+++ b/changelogs/unreleased/sh-bump-gems-security.yml
@@ -0,0 +1,5 @@
+---
+title: Bump nokogiri, loofah, and rack gems for security updates
+merge_request: 23204
+author:
+type: security
diff --git a/changelogs/unreleased/sh-fix-issue-53783-ce.yml b/changelogs/unreleased/sh-fix-issue-53783-ce.yml
new file mode 100644
index 00000000000..10be1d81768
--- /dev/null
+++ b/changelogs/unreleased/sh-fix-issue-53783-ce.yml
@@ -0,0 +1,5 @@
+---
+title: Fix enabling project deploy key for admins
+merge_request: 23043
+author:
+type: fixed
diff --git a/changelogs/unreleased/sh-fix-issue-54189.yml b/changelogs/unreleased/sh-fix-issue-54189.yml
new file mode 100644
index 00000000000..eee743aa5d9
--- /dev/null
+++ b/changelogs/unreleased/sh-fix-issue-54189.yml
@@ -0,0 +1,5 @@
+---
+title: Prevent templated services from being imported
+merge_request:
+author:
+type: security
diff --git a/changelogs/unreleased/sh-use-nakayoshi-fork.yml b/changelogs/unreleased/sh-use-nakayoshi-fork.yml
new file mode 100644
index 00000000000..5977d9b0974
--- /dev/null
+++ b/changelogs/unreleased/sh-use-nakayoshi-fork.yml
@@ -0,0 +1,5 @@
+---
+title: Improve memory performance by reducing dirty pages after fork()
+merge_request: 23169
+author:
+type: performance
diff --git a/changelogs/unreleased/zj-improve-gitaly-pb.yml b/changelogs/unreleased/zj-improve-gitaly-pb.yml
new file mode 100644
index 00000000000..506a0303d8a
--- /dev/null
+++ b/changelogs/unreleased/zj-improve-gitaly-pb.yml
@@ -0,0 +1,5 @@
+---
+title: Show what RPC is called in the performance bar
+merge_request: 23140
+author:
+type: other
diff --git a/config/dependency_decisions.yml b/config/dependency_decisions.yml
index 488728e26ab..84d47bd52ad 100644
--- a/config/dependency_decisions.yml
+++ b/config/dependency_decisions.yml
@@ -544,13 +544,6 @@
:why: https://github.com/xtuc/webassemblyjs/blob/master/LICENSE
:versions: []
:when: 2018-06-08 05:30:56.764116000 Z
-- - :license
- - "@gitlab-org/gitlab-ui"
- - MIT
- - :who: Clement Ho
- :why: Our own library
- :versions: []
- :when: 2018-07-17 21:02:54.529227000 Z
- - :approve
- lz-string
- :who: Phil Hughes
diff --git a/danger/documentation/Dangerfile b/danger/documentation/Dangerfile
index 1ee025f0972..87c61d6e90d 100644
--- a/danger/documentation/Dangerfile
+++ b/danger/documentation/Dangerfile
@@ -15,10 +15,10 @@ docs_paths_to_review = docs_paths_requiring_review(helper.all_changed_files)
unless docs_paths_to_review.empty?
message 'This merge request adds or changes files that require a ' \
- 'review from the docs team.'
+ 'review from the Docs team.'
markdown(<<~MARKDOWN)
-## Docs Review
+## Docs review
The following files require a review from the Documentation team:
@@ -32,24 +32,15 @@ the documentation. GitLabbers are also welcome to use the [#docs](https://gitlab
Who to ping [based on DevOps stages](https://about.gitlab.com/handbook/product/categories/#devops-stages):
-| Stage | Tech writer |
-| ------------- | ----------- |
-| ~Create | `@marcia` |
-| ~Configure | `@eread` |
-| ~Distribution | `@axil` |
-| ~Geo | `@eread` |
-| ~Gitaly | `@axil` |
-| ~Gitter | `@axil` |
-| ~Manage | `@eread` |
-| ~Monitoring | `@axil` |
-| ~Packaging | `@axil` |
-| ~Plan | `@mikelewis`|
-| ~Release | `marcia` |
-| ~Secure | `@axil` |
-| ~Verify | `@eread` |
+| Tech writer | Stage(s) |
+| ------------ | ------------------------------------------------------------ |
+| `@marcia` | ~Create ~Release |
+| `@axil` | ~Distribution ~Gitaly ~Gitter ~Monitoring ~Packaging ~Secure |
+| `@eread` | ~Manage ~Configure ~Geo ~Verify |
+| `@mikelewis` | ~Plan |
If you are not sure which category the change falls within, or the change is not
-part of one of these categories, you can mention the whole team with `@gl-docsteam`.
+part of one of these categories, you can mention one of the usernames above.
MARKDOWN
unless gitlab.mr_labels.include?('Documentation')
diff --git a/db/migrate/20181112103239_drop_default_value_on_status_deployments.rb b/db/migrate/20181112103239_drop_default_value_on_status_deployments.rb
new file mode 100644
index 00000000000..a480c15e66b
--- /dev/null
+++ b/db/migrate/20181112103239_drop_default_value_on_status_deployments.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+class DropDefaultValueOnStatusDeployments < ActiveRecord::Migration
+ DOWNTIME = false
+ DEPLOYMENT_STATUS_SUCCESS = 2 # Equivalent to Deployment.state_machine.states['success'].value
+
+ def up
+ change_column_default :deployments, :status, nil
+ end
+
+ def down
+ change_column_default :deployments, :status, DEPLOYMENT_STATUS_SUCCESS
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 8e02f43f702..cc47368c530 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
-ActiveRecord::Schema.define(version: 20181107054254) do
+ActiveRecord::Schema.define(version: 20181112103239) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
@@ -807,7 +807,7 @@ ActiveRecord::Schema.define(version: 20181107054254) do
t.datetime "created_at"
t.datetime "updated_at"
t.string "on_stop"
- t.integer "status", limit: 2, default: 2, null: false
+ t.integer "status", limit: 2, null: false
t.datetime_with_timezone "finished_at"
t.index ["created_at"], name: "index_deployments_on_created_at", using: :btree
t.index ["deployable_type", "deployable_id"], name: "index_deployments_on_deployable_type_and_deployable_id", using: :btree
diff --git a/doc/administration/high_availability/redis.md b/doc/administration/high_availability/redis.md
index 7c1ef43499d..a9ba40c870c 100644
--- a/doc/administration/high_availability/redis.md
+++ b/doc/administration/high_availability/redis.md
@@ -684,7 +684,7 @@ cache, queues, and shared_state. To make this work with Sentinel:
```
1. Note that for each persistence class, GitLab will default to using the
configuration specified in `gitlab_rails['redis_sentinels']` unless
- overriden by the settings above.
+ overridden by the settings above.
1. Be sure to include BOTH configuration options for each persistent classes. For example,
if you choose to configure a cache instance, you must specify both `gitlab_rails['redis_cache_instance']`
and `gitlab_rails['redis_cache_sentinels']` for GitLab to generate the proper configuration files.
diff --git a/doc/ci/pipelines.md b/doc/ci/pipelines.md
index 371703a12c8..c628895ee1a 100644
--- a/doc/ci/pipelines.md
+++ b/doc/ci/pipelines.md
@@ -294,7 +294,7 @@ runners will not use regular runners, they must be tagged accordingly.
[jobs]: #jobs
[jobs-yaml]: yaml/README.md#jobs
-[manual]: yaml/README.md#manual
+[manual]: yaml/README.md#whenmanual
[env-manual]: environments.md#manually-deploying-to-environments
[stages]: yaml/README.md#stages
[runners]: runners/README.html
diff --git a/doc/ci/variables/where_variables_can_be_used.md b/doc/ci/variables/where_variables_can_be_used.md
index 4e8ce10c9cb..1d98e8426fe 100644
--- a/doc/ci/variables/where_variables_can_be_used.md
+++ b/doc/ci/variables/where_variables_can_be_used.md
@@ -17,7 +17,7 @@ There are two places defined variables can be used. On the:
| Definition | Can be expanded? | Expansion place | Description |
|--------------------------------------|-------------------|-----------------|--------------|
-| `environment:url` | yes | GitLab | The variable expansion is made by GitLab's [internal variable expansion mechanism](#gitlab-internal-variable-expansion-mechanism).<ul><li>Supported: all variables defined for a job (project/group variables, variables from `.gitlab-ci.yml`, variables from triggers, variables from pipeline schedules)</li><li>Not suported: variables defined in Runner's `config.toml` and variables created in job's `script`</li></ul> |
+| `environment:url` | yes | GitLab | The variable expansion is made by GitLab's [internal variable expansion mechanism](#gitlab-internal-variable-expansion-mechanism).<ul><li>Supported: all variables defined for a job (project/group variables, variables from `.gitlab-ci.yml`, variables from triggers, variables from pipeline schedules)</li><li>Not supported: variables defined in Runner's `config.toml` and variables created in job's `script`</li></ul> |
| `environment:name` | yes | GitLab | Similar to `environment:url`, but the variables expansion doesn't support: <ul><li>variables that are based on the environment's name (`CI_ENVIRONMENT_NAME`, `CI_ENVIRONMENT_SLUG`)</li><li>any other variables related to environment (currently only `CI_ENVIRONMENT_URL`)</li><li>[persisted variables](#persisted-variables)</li></ul> |
| `variables` | yes | Runner | The variable expansion is made by GitLab Runner's [internal variable expansion mechanism](#gitlab-runner-internal-variable-expansion-mechanism) |
| `image` | yes | Runner | The variable expansion is made by GitLab Runner's [internal variable expansion mechanism](#gitlab-runner-internal-variable-expansion-mechanism) |
diff --git a/doc/ci/yaml/README.md b/doc/ci/yaml/README.md
index 2a667c985da..44eec43ef54 100644
--- a/doc/ci/yaml/README.md
+++ b/doc/ci/yaml/README.md
@@ -1604,10 +1604,11 @@ test:
## `include`
-> Introduced in [GitLab Edition Premium][ee] 10.5.
-> Available for Starter, Premium and Ultimate [versions][gitlab-versions] since 10.6.
+> Introduced in [GitLab Premium](https://about.gitlab.com/pricing/) 10.5.
+> Available for Starter, Premium and Ultimate since 10.6.
> Behaviour expanded in GitLab 10.8 to allow more flexible overriding.
-> Available for Libre since [11.4](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/21603)
+> [Moved](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/21603)
+to GitLab Core in 11.4
Using the `include` keyword, you can allow the inclusion of external YAML files.
@@ -1681,6 +1682,11 @@ include:
NOTE: **Note:**
The remote file must be publicly accessible through a simple GET request, as we don't support authentication schemas in the remote URL.
+ NOTE: **Note:**
+ In order to include files from another repository inside your local network,
+ you may need to enable the **Allow requests to the local network from hooks and services** checkbox
+ located in the **Settings > Network > Outbound requests** section within the **Admin area**.
+
---
@@ -1769,7 +1775,7 @@ stages:
production:
script:
- - install_depedencies
+ - install_dependencies
- deploy
- notify_owner
```
diff --git a/doc/development/feature_flags.md b/doc/development/feature_flags.md
index 350593cc813..1019a1fd0e2 100644
--- a/doc/development/feature_flags.md
+++ b/doc/development/feature_flags.md
@@ -33,7 +33,7 @@ You can follow the progress on that [in the issue on our issue tracker](https://
In general, it's better to have a group- or user-based gate, and you should prefer
it over the use of percentage gates. This would make debugging easier, as you
-filter for example logs and errors based on actors too. Futhermore, this allows
+filter for example logs and errors based on actors too. Furthermore, this allows
for enabling for the `gitlab-org` group first, while the rest of the users
aren't impacted.
diff --git a/doc/development/testing_guide/review_apps.md b/doc/development/testing_guide/review_apps.md
index 36d150c8a5b..1830641431e 100644
--- a/doc/development/testing_guide/review_apps.md
+++ b/doc/development/testing_guide/review_apps.md
@@ -24,7 +24,7 @@ Review Apps are automatically deployed by each pipeline, both in
[`scripts/review_apps/review-apps.sh`][review-apps.sh]
- These scripts are basically
[our official Auto DevOps scripts][Auto-DevOps.gitlab-ci.yml] where the
- default CNG images are overriden with the images built and stored in the
+ default CNG images are overridden with the images built and stored in the
[`CNG-mirror` project's registry][cng-mirror-registry].
- Since we're using [the official GitLab Helm chart][helm-chart], this means
you get a dedicated environment for your branch that's very close to what it
@@ -33,7 +33,7 @@ Review Apps are automatically deployed by each pipeline, both in
thanks to the direct link to it from the MR widget. The default username is
`root` and its password can be found in the 1Password secure note named
**gitlab-{ce,ee} Review App's root password** (note that there's currently
- [a bug where the default password seems to be overriden][password-bug]).
+ [a bug where the default password seems to be overridden][password-bug]).
**Additional notes:**
diff --git a/doc/install/requirements.md b/doc/install/requirements.md
index 97190544c3d..1b7e0d1d0ab 100644
--- a/doc/install/requirements.md
+++ b/doc/install/requirements.md
@@ -104,7 +104,7 @@ 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. Geo does [not support MySQL](https://docs.gitlab.com/ee/administration/geo/replication/database.html#mysql-replication). This means no supported Disaster Recovery solution if using MySQL. **[PREMIUM ONLY]**
-1. [Zero downtime migrations][../update/README.md#upgrading-without-downtime] do not work with MySQL.
+1. [Zero downtime migrations](../update/README.md#upgrading-without-downtime) do not work with MySQL.
1. GitLab [optimizes the loading of dashboard events](https://gitlab.com/gitlab-org/gitlab-ce/issues/31806) using [PostgreSQL LATERAL JOINs](https://blog.heapanalytics.com/postgresqls-powerful-new-join-type-lateral/).
1. In general, SQL optimized for PostgreSQL may run much slower in MySQL due to
differences in query planners. For example, subqueries that work well in PostgreSQL
diff --git a/doc/topics/autodevops/index.md b/doc/topics/autodevops/index.md
index 3647f600b21..6bb2e236dc1 100644
--- a/doc/topics/autodevops/index.md
+++ b/doc/topics/autodevops/index.md
@@ -657,6 +657,8 @@ also be customized, and you can easily use a [custom buildpack](#custom-buildpac
| `REVIEW_DISABLED` | From GitLab 11.0, this variable can be used to disable the `review` and the manual `review:stop` job. If the variable is present, these jobs will not be created. |
| `DAST_DISABLED` | From GitLab 11.0, this variable can be used to disable the `dast` job. If the variable is present, the job will not be created. |
| `PERFORMANCE_DISABLED` | From GitLab 11.0, this variable can be used to disable the `performance` job. If the variable is present, the job will not be created. |
+| `OLD_REPORTS_DISABLED` | From GitLab 11.5, this variable can be used to disable the `sast` job. If the variable is present, the job will not be created. |
+| `NEW_REPORTS_DISABLED` | From GitLab 11.5, this variable can be used to disable the `sast_dashboard` job. If the variable is present, the job will not be created. |
TIP: **Tip:**
Set up the replica variables using a
diff --git a/doc/university/bookclub/booklist.md b/doc/university/bookclub/booklist.md
index 26c3851276b..84b1f643b91 100644
--- a/doc/university/bookclub/booklist.md
+++ b/doc/university/bookclub/booklist.md
@@ -10,7 +10,7 @@ List of books and resources, that may be worth reading.
1. **The Humble Programmer**
- Edsger W. Dijkstra, 1972 ([paper](http://dl.acm.org/citation.cfm?id=361591))
+ Edsger W. Dijkstra, 1972 ([paper](https://dl.acm.org/citation.cfm?id=361591))
## Programming
diff --git a/doc/user/project/clusters/index.md b/doc/user/project/clusters/index.md
index c8003d00e73..ca262e4b76e 100644
--- a/doc/user/project/clusters/index.md
+++ b/doc/user/project/clusters/index.md
@@ -228,7 +228,7 @@ twice, which can lead to confusion during deployments.
| [Prometheus](https://prometheus.io/docs/introduction/overview/) | 10.4+ | Prometheus is an open-source monitoring and alerting system useful to supervise your deployed applications. | [stable/prometheus](https://github.com/helm/charts/tree/master/stable/prometheus) |
| [GitLab Runner](https://docs.gitlab.com/runner/) | 10.6+ | GitLab Runner is the open source project that is used to run your jobs and send the results back to GitLab. It is used in conjunction with [GitLab CI/CD](https://about.gitlab.com/features/gitlab-ci-cd/), the open-source continuous integration service included with GitLab that coordinates the jobs. When installing the GitLab Runner via the applications, it will run in **privileged mode** by default. Make sure you read the [security implications](#security-implications) before doing so. | [runner/gitlab-runner](https://gitlab.com/charts/gitlab-runner) |
| [JupyterHub](http://jupyter.org/) | 11.0+ | [JupyterHub](https://jupyterhub.readthedocs.io/en/stable/) is a multi-user service for managing notebooks across a team. [Jupyter Notebooks](https://jupyter-notebook.readthedocs.io/en/latest/) provide a web-based interactive programming environment used for data analysis, visualization, and machine learning. We use [this](https://gitlab.com/gitlab-org/jupyterhub-user-image/blob/master/Dockerfile) custom Jupyter image that installs additional useful packages on top of the base Jupyter. You will also see ready-to-use DevOps Runbooks built with Nurtch's [Rubix library](https://github.com/amit1rrr/rubix). More information on creating executable runbooks can be found at [Nurtch Documentation](http://docs.nurtch.com/en/latest). **Note**: Authentication will be enabled for any user of the GitLab server via OAuth2. HTTPS will be supported in a future release. | [jupyter/jupyterhub](https://jupyterhub.github.io/helm-chart/) |
-| [Knative](https://cloud.google.com/knative) | 0.1.2 | Knative provides a platform to create, deploy, and manage serverless workloads from a Kubernetes cluster. It is used in conjunction with, and includes [Istio](https://istio.io) to provide an external IP address for all programs hosted by Knative. You will be prompted to enter a wildcard domain where your applications will be exposed. Configure your DNS server to use the external IP address for that domain. For any application created and installed, they will be accessible as `<program_name>.<kubernetes_namespace>.<domain_name>`. **Note**: This will require your kubernetes cluster to have RBAC enabled. | [knative/knative](https://storage.googleapis.com/triggermesh-charts)
+| [Knative](https://cloud.google.com/knative) | 11.5+ | Knative provides a platform to create, deploy, and manage serverless workloads from a Kubernetes cluster. It is used in conjunction with, and includes [Istio](https://istio.io) to provide an external IP address for all programs hosted by Knative. You will be prompted to enter a wildcard domain where your applications will be exposed. Configure your DNS server to use the external IP address for that domain. For any application created and installed, they will be accessible as `<program_name>.<kubernetes_namespace>.<domain_name>`. This will require your kubernetes cluster to have [RBAC enabled](#role-based-access-control-rbac). | [knative/knative](https://storage.googleapis.com/triggermesh-charts)
NOTE: **Note:**
As of GitLab 11.6 Helm Tiller will be upgraded to the latest version supported
@@ -267,6 +267,9 @@ the `gcloud` command in a local terminal or using the **Cloud Shell**.
If the cluster is not on GKE, follow the specific instructions for your
Kubernetes provider to configure `kubectl` with the right credentials.
+The output of the following examples will show the external IP address of your
+cluster. This information can then be used to set up DNS entries and forwarding
+rules that allow external access to your deployed applications.
If you installed the Ingress [via the **Applications**](#installing-applications),
run the following command:
@@ -275,28 +278,23 @@ run the following command:
kubectl get svc --namespace=gitlab-managed-apps ingress-nginx-ingress-controller -o jsonpath='{.status.loadBalancer.ingress[0].ip} '
```
-NOTE: **Note:**
-For Istio/Knative, use the following command:
+For Istio/Knative, the command will be different:
```bash
kubectl get svc --namespace=istio-system knative-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].ip} '
```
-Otherwise, you can list the IP addresses of all load balancers:
+Some Kubernetes clusters return a hostname instead, like [Amazon EKS](https://aws.amazon.com/eks/). For these platforms, run:
```bash
-kubectl get svc --all-namespaces -o jsonpath='{range.items[?(@.status.loadBalancer.ingress)]}{.status.loadBalancer.ingress[*].ip} '
+kubectl get service ingress-nginx-ingress-controller -n gitlab-managed-apps -o jsonpath="{.status.loadBalancer.ingress[0].hostname}".
```
-> **Note**: Some Kubernetes clusters return a hostname instead, like [Amazon EKS](https://aws.amazon.com/eks/). For these platforms, run:
-
-> ```bash
-> kubectl get service ingress-nginx-ingress-controller -n gitlab-managed-apps -o jsonpath="{.status.loadBalancer.ingress[0].hostname}".
-> ```
+Otherwise, you can list the IP addresses of all load balancers:
-The output is the external IP address of your cluster. This information can then
-be used to set up DNS entries and forwarding rules that allow external access to
-your deployed applications.
+```bash
+kubectl get svc --all-namespaces -o jsonpath='{range.items[?(@.status.loadBalancer.ingress)]}{.status.loadBalancer.ingress[*].ip} '
+```
### Using a static IP
diff --git a/doc/user/project/clusters/runbooks/img/authorize-jupyter.png b/doc/user/project/clusters/runbooks/img/authorize-jupyter.png
new file mode 100644
index 00000000000..64f95ed45f0
--- /dev/null
+++ b/doc/user/project/clusters/runbooks/img/authorize-jupyter.png
Binary files differ
diff --git a/doc/user/project/clusters/runbooks/img/demo-runbook.png b/doc/user/project/clusters/runbooks/img/demo-runbook.png
new file mode 100644
index 00000000000..25c9df4126d
--- /dev/null
+++ b/doc/user/project/clusters/runbooks/img/demo-runbook.png
Binary files differ
diff --git a/doc/user/project/clusters/runbooks/img/gitlab-variables.png b/doc/user/project/clusters/runbooks/img/gitlab-variables.png
new file mode 100644
index 00000000000..f76ed21145f
--- /dev/null
+++ b/doc/user/project/clusters/runbooks/img/gitlab-variables.png
Binary files differ
diff --git a/doc/user/project/clusters/runbooks/img/helm-install.png b/doc/user/project/clusters/runbooks/img/helm-install.png
new file mode 100644
index 00000000000..e39094bcbf7
--- /dev/null
+++ b/doc/user/project/clusters/runbooks/img/helm-install.png
Binary files differ
diff --git a/doc/user/project/clusters/runbooks/img/ingress-install.png b/doc/user/project/clusters/runbooks/img/ingress-install.png
new file mode 100644
index 00000000000..093c61f2d0e
--- /dev/null
+++ b/doc/user/project/clusters/runbooks/img/ingress-install.png
Binary files differ
diff --git a/doc/user/project/clusters/runbooks/img/jupyterhub-install.png b/doc/user/project/clusters/runbooks/img/jupyterhub-install.png
new file mode 100644
index 00000000000..2115ec9745b
--- /dev/null
+++ b/doc/user/project/clusters/runbooks/img/jupyterhub-install.png
Binary files differ
diff --git a/doc/user/project/clusters/runbooks/img/postgres-query.png b/doc/user/project/clusters/runbooks/img/postgres-query.png
new file mode 100644
index 00000000000..3880438c97a
--- /dev/null
+++ b/doc/user/project/clusters/runbooks/img/postgres-query.png
Binary files differ
diff --git a/doc/user/project/clusters/runbooks/img/sample-runbook.png b/doc/user/project/clusters/runbooks/img/sample-runbook.png
new file mode 100644
index 00000000000..c12ce8990a4
--- /dev/null
+++ b/doc/user/project/clusters/runbooks/img/sample-runbook.png
Binary files differ
diff --git a/doc/user/project/clusters/runbooks/index.md b/doc/user/project/clusters/runbooks/index.md
index 3b81e439119..e1b8dc07b50 100644
--- a/doc/user/project/clusters/runbooks/index.md
+++ b/doc/user/project/clusters/runbooks/index.md
@@ -10,8 +10,8 @@ Historically, runbooks took the form of a decision tree or a detailed
step-by-step guide depending on the condition or system.
Modern implementations have introduced the concept of an "executable
-runbooks", where along with a well define process, operators can execute
-code blocks or database queries against a given environment.
+runbooks", where, along with a well-defined process, operators can execute
+pre-written code blocks or database queries against a given environment.
## Nurtch Executable Runbooks
@@ -45,5 +45,93 @@ To create an executable runbook, you will need:
Nurtch is the company behind the [Rubix library](https://github.com/Nurtch/rubix). Rubix is
an open-source python library that makes it easy to perform common DevOps tasks inside Jupyter Notebooks.
Tasks such as plotting Cloudwatch metrics and rolling your ECS/Kubernetes app are simplified
-down to a couple of lines of code. Check the [Nurtch Documentation](http://docs.nurtch.com/en/latest)
+down to a couple of lines of code. See the [Nurtch Documentation](http://docs.nurtch.com/en/latest)
for more information.
+
+## Configure an executable runbook with GitLab
+
+Follow this step-by-step guide to configure an executable runbook in GitLab using
+the components outlined above and the preloaded demo runbook.
+
+### 1. Add a Kubernetes cluster
+
+Follow the steps outlined in [Adding and creating a new GKE cluster via GitLab](https://docs.gitlab.com/ee/user/project/clusters/#adding-and-creating-a-new-gke-cluster-via-gitlab)
+to add a Kubernetes cluster to your project.
+
+### 2. Install Helm Tiller, Ingress, and JupyterHub
+
+Once the cluster has been provisioned in GKE, click the **Install** button next to the **Helm Tiller** app.
+
+![install helm](img/helm-install.png)
+
+Once Tiller has been installed successfully, click the **Install** button next to the **Ingress** app.
+
+![install ingress](img/ingress-install.png)
+
+Once Ingress has been installed successfully, click the **Install** button next to the **JupyterHub** app.
+
+![install jupyterhub](img/jupyterhub-install.png)
+
+### 3. Login to JupyterHub and start the server
+
+Once JupyterHub has been installed successfully, navigate to the displayed **Jupyter Hostname** URL and click
+**Sign in with GitLab**. Authentication is automatically enabled for any user of the GitLab instance via OAuth2. This
+will redirect to GitLab in order to authorize JupyterHub to use your GitLab account. Click **Authorize**.
+
+![authorize jupyter](img/authorize-jupyter.png)
+
+Once the application has been authorized you will taken back to the JupyterHub application. Click **Start My Server**.
+The server will take a couple of seconds to start.
+
+### 4. Configure access
+
+In order for the runbook to access your GitLab project, you will need to enter a
+[GitLab Access Token](https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html)
+as well as your Project ID in the **Setup** section of the demo runbook.
+
+Double-click the **DevOps-Runbook-Demo** folder located on the left panel.
+
+![demo runbook](img/demo-runbook.png)
+
+Double-click the "Nurtch-DevOps-Demo.ipynb" runbook.
+
+![sample runbook](img/sample-runbook.png)
+
+The contents on the runbook will be displayed on the right side of the screen. Under the "Setup" section, you will find
+entries for both your `PRIVATE_TOKEN` and your `PROJECT_ID`. Enter both these values, conserving the single quotes as follows:
+
+```sql
+PRIVATE_TOKEN = 'n671WNGecHugsdEDPsyo'
+PROJECT_ID = '1234567'
+```
+
+Update the `VARIABLE_NAME` on the last line of this section to match the name of the variable you are using for your
+access token. In this example our variable name is `PRIVATE_TOKEN`.
+
+```sql
+VARIABLE_VALUE = project.variables.get('PRIVATE_TOKEN').value
+```
+
+### 5. Configure an operation
+
+For this example we'll use the "**Run SQL queries in Notebook**" section in the sample runbook to query
+a postgres database. The first 4 lines of the section define the variables that are required for this query to function.
+
+```sql
+%env DB_USER={project.variables.get('DB_USER').value}
+%env DB_PASSWORD={project.variables.get('DB_PASSWORD').value}
+%env DB_ENDPOINT={project.variables.get('DB_ENDPOINT').value}
+%env DB_NAME={project.variables.get('DB_NAME').value}
+```
+
+Create the matching variables in your project's **Settings >> CI/CD >> Variables**
+
+![gitlab variables](img/gitlab-variables.png)
+
+Back in Jupyter, click the "Run SQL queries in Notebook" heading and the click *Run*. The results will be
+displayed in-line as follows:
+
+![postgres query](img/postgres-query.png)
+
+You can try other operations such as running shell scripts or interacting with a Kubernetes cluster. Visit the
+[Nurtch Documentation](http://docs.nurtch.com/) for more information. \ No newline at end of file
diff --git a/doc/user/project/import/github.md b/doc/user/project/import/github.md
index 3e4be043199..42da2210fab 100644
--- a/doc/user/project/import/github.md
+++ b/doc/user/project/import/github.md
@@ -17,6 +17,7 @@ the [GitHub rake task](../../../administration/raketasks/github_import.md) to im
GitHub without the constraints of a Sidekiq worker.
The following aspects of a project are imported:
+
* Repository description (GitLab.com & 7.7+)
* Git repository data (GitLab.com & 7.7+)
* Issues (GitLab.com & 7.7+)
diff --git a/doc/user/project/merge_requests/img/merge_request_diff_file_navigation.png b/doc/user/project/merge_requests/img/merge_request_diff_file_navigation.png
index 3b3bf88df31..1cdac5ef573 100644
--- a/doc/user/project/merge_requests/img/merge_request_diff_file_navigation.png
+++ b/doc/user/project/merge_requests/img/merge_request_diff_file_navigation.png
Binary files differ
diff --git a/doc/user/project/merge_requests/index.md b/doc/user/project/merge_requests/index.md
index f2f2497f0be..044bc4c575b 100644
--- a/doc/user/project/merge_requests/index.md
+++ b/doc/user/project/merge_requests/index.md
@@ -177,11 +177,11 @@ administrator to do so.
### Adding patches when creating a merge request via e-mail
-> **Note**: This feature was [implemented in GitLab 11.5](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/22723)
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/22723) in GitLab 11.5.
You can add commits to the merge request being created by adding
-patches as attachments to the email, all attachments with a filename
-ending in `.patch` will be considered patches. The patches will be processed
+patches as attachments to the email. All attachments with a filename
+ending in `.patch` will be considered patches and they will be processed
ordered by name.
The combined size of the patches can be 2MB.
@@ -194,7 +194,7 @@ branch already exists, the patches will be applied on top of it.
## Find the merge request that introduced a change
-> **Note**: this feature was [implemented in GitLab 10.5](https://gitlab.com/gitlab-org/gitlab-ce/issues/2383).
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/issues/2383) in GitLab 10.5.
When viewing the commit details page, GitLab will link to the merge request (or
merge requests, if it's in more than one) containing that commit.
@@ -231,9 +231,10 @@ have been marked as a **Work In Progress**.
## Merge request diff file navigation
-The diff view has a file tree for file navigation. As you scroll through
-diffs with a large number of files, you can easily jump to any changed file
-using the file tree.
+When reviewing changes in the **Changes** tab the diff can be navigated using
+the file tree or file list. As you scroll through large diffs with many
+changes, you can quickly jump to any changed file using the file tree or file
+list.
![Merge request diff file navigation](img/merge_request_diff_file_navigation.png)
diff --git a/doc/user/project/milestones/index.md b/doc/user/project/milestones/index.md
index 3cf46231a9d..7168fe63887 100644
--- a/doc/user/project/milestones/index.md
+++ b/doc/user/project/milestones/index.md
@@ -6,6 +6,26 @@ Milestones in GitLab are a way to track issues and merge requests created to ach
Milestones allow you to organize issues and merge requests into a cohesive group, with an optional start date and an optional due date.
+## Milestones as Agile sprints
+
+Milestones can be used as Agile sprints.
+Set the milestone start date and due date to represent
+the start and end of your Agile sprint.
+Set the milestone title to the name of your Agile sprint,
+such as `November 2018 sprint`.
+Add an issue to your Agile sprint by associating
+the milestone to the issue.
+
+## Milestones as releases
+
+Milestones can be used as releases.
+Set the milestone due date to represent the release date of your release.
+(And leave the milestone start date blank.)
+Set the the milestone title to the version of your release,
+such as `Version 9.4`.
+Add an issue to your release by associating
+the milestone to the issue.
+
## Project milestones and group milestones
- **Project milestones** can be assigned to issues or merge requests in that project only.
diff --git a/doc/user/search/img/dashboard_links.png b/doc/user/search/img/dashboard_links.png
new file mode 100644
index 00000000000..2c472c7e464
--- /dev/null
+++ b/doc/user/search/img/dashboard_links.png
Binary files differ
diff --git a/doc/user/search/img/issues_assigned_to_you.png b/doc/user/search/img/issues_assigned_to_you.png
index 36c670eedd5..d2fff5e9a67 100644
--- a/doc/user/search/img/issues_assigned_to_you.png
+++ b/doc/user/search/img/issues_assigned_to_you.png
Binary files differ
diff --git a/doc/user/search/img/left_menu_bar.png b/doc/user/search/img/left_menu_bar.png
deleted file mode 100644
index d68a71cba8e..00000000000
--- a/doc/user/search/img/left_menu_bar.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/search/index.md b/doc/user/search/index.md
index 3f9d07dacaa..78c1294346b 100644
--- a/doc/user/search/index.md
+++ b/doc/user/search/index.md
@@ -2,27 +2,27 @@
## Issues and merge requests
-To search through issues and merge requests in multiple projects, you can use the left-sidebar.
+To search through issues and merge requests in multiple projects, you can use the **Issues** or **Merge Requests** links
+in the top-right part of your screen.
-Click the menu bar, then **Issues** or **Merge Requests**, which work in the same way,
-therefore, the following notes are valid for both.
+Both of them work in the same way, therefore, the following notes are valid for both.
The number displayed on their right represents the number of issues and merge requests assigned to you.
-![menu bar - issues and MRs assigned to you](img/left_menu_bar.png)
+![issues and MRs dashboard links](img/dashboard_links.png)
When you click **Issues**, you'll see the opened issues assigned to you straight away:
![Issues assigned to you](img/issues_assigned_to_you.png)
-You can filter them by **Author**, **Assignee**, **Milestone**, and **Labels**,
-searching through **Open**, **Closed**, and **All** issues.
+You can search through **Open**, **Closed**, or **All** issues.
-Of course, you can combine all filters together.
+You can also filter the results using the search and filter field. This works in the same way as the ones found in the
+per project pages described below.
### Issues and MRs assigned to you or created by you
-You'll find a shortcut to issues and merge requests create by you or assigned to you
+You'll also find shortcuts to issues and merge requests created by you or assigned to you
on the search field on the top-right of your screen:
![shortcut to your issues and mrs](img/issues_mrs_shortcut.png)
diff --git a/lib/gitlab.rb b/lib/gitlab.rb
index 2bb09684441..2ef54658a11 100644
--- a/lib/gitlab.rb
+++ b/lib/gitlab.rb
@@ -53,4 +53,8 @@ module Gitlab
def self.pre_release?
VERSION.include?('pre')
end
+
+ def self.version_info
+ Gitlab::VersionInfo.parse(Gitlab::VERSION)
+ end
end
diff --git a/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml b/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml
index 149506ea498..c90976b2040 100644
--- a/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml
@@ -19,6 +19,15 @@
# * review: REVIEW_DISABLED
# * stop_review: REVIEW_DISABLED
#
+# The sast and sast_dashboard jobs are executed to guarantee full compatibility
+# with the group security dashboard and the security reports with old runners.
+# If you use only runners with version 11.5 or above, you can disable the sast
+# job by setting the OLD_REPORTS_DISABLED environment variable. If you use only
+# runners with version below 11.5, you can disable the sast_dashboard job by
+# setting the NEW_REPORTS_DISABLED environment variable.
+# The sast_dashboard job will be removed in the future, when the sast job will
+# use the new reports syntax.
+#
# In order to deploy, you must have a Kubernetes cluster configured either
# via a project integration, or via group/project variables.
# AUTO_DEVOPS_DOMAIN must also be set as a variable at the group or project
@@ -173,6 +182,29 @@ sast:
except:
variables:
- $SAST_DISABLED
+ - $OLD_REPORTS_DISABLED
+
+sast_dashboard:
+ stage: test
+ image: docker:stable
+ allow_failure: true
+ services:
+ - docker:stable-dind
+ script:
+ - setup_docker
+ - sast
+ artifacts:
+ reports:
+ sast: gl-sast-report.json
+ only:
+ refs:
+ - branches
+ variables:
+ - $GITLAB_FEATURES =~ /\bsast\b/
+ except:
+ variables:
+ - $SAST_DISABLED
+ - $NEW_REPORTS_DISABLED
dependency_scanning:
stage: test
diff --git a/lib/gitlab/ci/variables/collection/item.rb b/lib/gitlab/ci/variables/collection/item.rb
index fdf852e8788..cf8958e34c2 100644
--- a/lib/gitlab/ci/variables/collection/item.rb
+++ b/lib/gitlab/ci/variables/collection/item.rb
@@ -6,8 +6,8 @@ module Gitlab
class Collection
class Item
def initialize(key:, value:, public: true, file: false)
- raise ArgumentError, "`value` must be of type String, while it was: #{value.class}" unless
- value.is_a?(String) || value.nil?
+ raise ArgumentError, "`#{key}` must be of type String, while it was: #{value.class}" unless
+ value.is_a?(String)
@variable = {
key: key, value: value, public: public, file: file
diff --git a/lib/gitlab/git/blob.rb b/lib/gitlab/git/blob.rb
index 9dd1c484d59..2d25389594e 100644
--- a/lib/gitlab/git/blob.rb
+++ b/lib/gitlab/git/blob.rb
@@ -1,7 +1,5 @@
# frozen_string_literal: true
-# Gitaly note: JV: seems to be completely migrated (behind feature flags).
-
module Gitlab
module Git
class Blob
diff --git a/lib/gitlab/git/repository.rb b/lib/gitlab/git/repository.rb
index 993955d1a6b..289796ae93b 100644
--- a/lib/gitlab/git/repository.rb
+++ b/lib/gitlab/git/repository.rb
@@ -885,12 +885,6 @@ module Gitlab
Gitlab::GitalyClient::ConflictsService.new(self, our_commit_oid, their_commit_oid)
end
- def gitaly_migrate(method, status: Gitlab::GitalyClient::MigrationStatus::OPT_IN, &block)
- wrapped_gitaly_errors do
- Gitlab::GitalyClient.migrate(method, status: status, &block)
- end
- end
-
def clean_stale_repository_files
wrapped_gitaly_errors do
gitaly_repository_client.cleanup if exists?
diff --git a/lib/gitlab/gitaly_client.rb b/lib/gitlab/gitaly_client.rb
index 8b455dc7696..66666b88c15 100644
--- a/lib/gitlab/gitaly_client.rb
+++ b/lib/gitlab/gitaly_client.rb
@@ -9,11 +9,6 @@ require 'grpc/health/v1/health_services_pb'
module Gitlab
module GitalyClient
include Gitlab::Metrics::Methods
- module MigrationStatus
- DISABLED = 1
- OPT_IN = 2
- OPT_OUT = 3
- end
class TooManyInvocationsError < StandardError
attr_reader :call_site, :invocation_count, :max_call_stack
@@ -31,7 +26,7 @@ module Gitlab
end
end
- SERVER_VERSION_FILE = 'GITALY_SERVER_VERSION'.freeze
+ SERVER_VERSION_FILE = 'GITALY_SERVER_VERSION'
MAXIMUM_GITALY_CALLS = 35
CLIENT_NAME = (Sidekiq.server? ? 'gitlab-sidekiq' : 'gitlab-web').freeze
@@ -43,11 +38,6 @@ module Gitlab
self.query_time = 0
- define_histogram :gitaly_migrate_call_duration_seconds do
- docstring "Gitaly migration call execution timings"
- base_labels gitaly_enabled: nil, feature: nil
- end
-
define_histogram :gitaly_controller_action_duration_seconds do
docstring "Gitaly endpoint histogram by controller and action combination"
base_labels Gitlab::Metrics::Transaction::BASE_LABELS.merge(gitaly_service: nil, rpc: nil)
@@ -126,7 +116,6 @@ module Gitlab
def self.call(storage, service, rpc, request, remote_storage: nil, timeout: nil)
start = Gitlab::Metrics::System.monotonic_time
request_hash = request.is_a?(Google::Protobuf::MessageExts) ? request.to_h : {}
- @current_call_id ||= SecureRandom.uuid
enforce_gitaly_request_limits(:call)
@@ -145,9 +134,7 @@ module Gitlab
current_transaction_labels.merge(gitaly_service: service.to_s, rpc: rpc.to_s),
duration)
- add_call_details(id: @current_call_id, feature: service, duration: duration, request: request_hash)
-
- @current_call_id = nil
+ add_call_details(feature: "#{service}##{rpc}", duration: duration, request: request_hash, rpc: rpc)
end
def self.handle_grpc_unavailable!(ex)
@@ -222,7 +209,7 @@ module Gitlab
result
end
- SERVER_FEATURE_FLAGS = %w[gogit_findcommit].freeze
+ SERVER_FEATURE_FLAGS = %w[].freeze
def self.server_feature_flags
SERVER_FEATURE_FLAGS.map do |f|
@@ -237,82 +224,8 @@ module Gitlab
params['gitaly_token'].presence || Gitlab.config.gitaly['token']
end
- # Evaluates whether a feature toggle is on or off
- def self.feature_enabled?(feature_name, status: MigrationStatus::OPT_IN)
- # Disabled features are always off!
- return false if status == MigrationStatus::DISABLED
-
- feature = Feature.get("gitaly_#{feature_name}")
-
- # If the feature has been set, always evaluate
- if Feature.persisted?(feature)
- if feature.percentage_of_time_value > 0
- # Probabilistically enable this feature
- return Random.rand() * 100 < feature.percentage_of_time_value
- end
-
- return feature.enabled?
- end
-
- # If the feature has not been set, the default depends
- # on it's status
- case status
- when MigrationStatus::OPT_OUT
- true
- when MigrationStatus::OPT_IN
- opt_into_all_features? && !explicit_opt_in_required.include?(feature_name)
- else
- false
- end
- rescue => ex
- # During application startup feature lookups in SQL can fail
- Rails.logger.warn "exception while checking Gitaly feature status for #{feature_name}: #{ex}"
- false
- end
-
- # We have a mechanism to let GitLab automatically opt in to all Gitaly
- # features. We want to be able to exclude some features from automatic
- # opt-in. This function has an override in EE.
- def self.explicit_opt_in_required
- []
- end
-
- # opt_into_all_features? returns true when the current environment
- # is one in which we opt into features automatically
- def self.opt_into_all_features?
- Rails.env.development? || ENV["GITALY_FEATURE_DEFAULT_ON"] == "1"
- end
- private_class_method :opt_into_all_features?
-
- def self.migrate(feature, status: MigrationStatus::OPT_IN)
- # Enforce limits at both the `migrate` and `call` sites to ensure that
- # problems are not hidden by a feature being disabled
- enforce_gitaly_request_limits(:migrate)
-
- is_enabled = feature_enabled?(feature, status: status)
- metric_name = feature.to_s
- metric_name += "_gitaly" if is_enabled
-
- Gitlab::Metrics.measure(metric_name) do
- # Some migrate calls wrap other migrate calls
- allow_n_plus_1_calls do
- feature_stack = Thread.current[:gitaly_feature_stack] ||= []
- feature_stack.unshift(feature)
- begin
- start = Gitlab::Metrics::System.monotonic_time
- @current_call_id = SecureRandom.uuid
- call_details = { id: @current_call_id }
- yield is_enabled
- ensure
- total_time = Gitlab::Metrics::System.monotonic_time - start
- gitaly_migrate_call_duration_seconds.observe({ gitaly_enabled: is_enabled, feature: feature }, total_time)
- feature_stack.shift
- Thread.current[:gitaly_feature_stack] = nil if feature_stack.empty?
-
- add_call_details(call_details.merge(feature: feature, duration: total_time))
- end
- end
- end
+ def self.feature_enabled?(feature_name)
+ Feature.enabled?("gitaly_#{feature_name}")
end
# Ensures that Gitaly is not being abuse through n+1 misuse etc
@@ -368,38 +281,20 @@ module Gitlab
end
private_class_method :decrement_call_count
- # Returns an estimate of the number of Gitaly calls made for this
- # request
+ # Returns the of the number of Gitaly calls made for this request
def self.get_request_count
- return 0 unless Gitlab::SafeRequestStore.active?
-
- gitaly_migrate_count = get_call_count("gitaly_migrate_actual")
- gitaly_call_count = get_call_count("gitaly_call_actual")
-
- # Using the maximum of migrate and call_count will provide an
- # indicator of how many Gitaly calls will be made, even
- # before a feature is enabled. This provides us with a single
- # metric, but not an exact number, but this tradeoff is acceptable
- if gitaly_migrate_count > gitaly_call_count
- gitaly_migrate_count
- else
- gitaly_call_count
- end
+ get_call_count("gitaly_call_actual")
end
def self.reset_counts
return unless Gitlab::SafeRequestStore.active?
- %w[migrate call].each do |call_site|
- Gitlab::SafeRequestStore["gitaly_#{call_site}_actual"] = 0
- Gitlab::SafeRequestStore["gitaly_#{call_site}_permitted"] = 0
- end
+ Gitlab::SafeRequestStore["gitaly_call_actual"] = 0
+ Gitlab::SafeRequestStore["gitaly_call_permitted"] = 0
end
def self.add_call_details(details)
- id = details.delete(:id)
-
- return unless id && Gitlab::SafeRequestStore[:peek_enabled]
+ return unless Gitlab::SafeRequestStore[:peek_enabled]
Gitlab::SafeRequestStore['gitaly_call_details'] ||= {}
Gitlab::SafeRequestStore['gitaly_call_details'][id] ||= {}
diff --git a/lib/gitlab/hook_data/base_builder.rb b/lib/gitlab/hook_data/base_builder.rb
index 1a91301e8be..d54175bce81 100644
--- a/lib/gitlab/hook_data/base_builder.rb
+++ b/lib/gitlab/hook_data/base_builder.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module HookData
class BaseBuilder
diff --git a/lib/gitlab/hook_data/issuable_builder.rb b/lib/gitlab/hook_data/issuable_builder.rb
index 65389835ad7..0803df65632 100644
--- a/lib/gitlab/hook_data/issuable_builder.rb
+++ b/lib/gitlab/hook_data/issuable_builder.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module HookData
class IssuableBuilder < BaseBuilder
diff --git a/lib/gitlab/hook_data/issue_builder.rb b/lib/gitlab/hook_data/issue_builder.rb
index dd63db969f6..c99353b9d49 100644
--- a/lib/gitlab/hook_data/issue_builder.rb
+++ b/lib/gitlab/hook_data/issue_builder.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module HookData
class IssueBuilder < BaseBuilder
diff --git a/lib/gitlab/hook_data/merge_request_builder.rb b/lib/gitlab/hook_data/merge_request_builder.rb
index 3aa6a4f3767..ad38e26e40a 100644
--- a/lib/gitlab/hook_data/merge_request_builder.rb
+++ b/lib/gitlab/hook_data/merge_request_builder.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module HookData
class MergeRequestBuilder < BaseBuilder
diff --git a/lib/gitlab/hook_data/note_builder.rb b/lib/gitlab/hook_data/note_builder.rb
index 81873e345d5..ae30ef6364b 100644
--- a/lib/gitlab/hook_data/note_builder.rb
+++ b/lib/gitlab/hook_data/note_builder.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module HookData
class NoteBuilder < BaseBuilder
diff --git a/lib/gitlab/hook_data/wiki_page_builder.rb b/lib/gitlab/hook_data/wiki_page_builder.rb
index 59c94a61cf2..67f06b1ca46 100644
--- a/lib/gitlab/hook_data/wiki_page_builder.rb
+++ b/lib/gitlab/hook_data/wiki_page_builder.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module HookData
class WikiPageBuilder < BaseBuilder
diff --git a/lib/gitlab/i18n/metadata_entry.rb b/lib/gitlab/i18n/metadata_entry.rb
index 36fc1bcdcb7..3764e379681 100644
--- a/lib/gitlab/i18n/metadata_entry.rb
+++ b/lib/gitlab/i18n/metadata_entry.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module I18n
class MetadataEntry
diff --git a/lib/gitlab/i18n/po_linter.rb b/lib/gitlab/i18n/po_linter.rb
index d8e7269a2c2..644ef8c8589 100644
--- a/lib/gitlab/i18n/po_linter.rb
+++ b/lib/gitlab/i18n/po_linter.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module I18n
class PoLinter
diff --git a/lib/gitlab/i18n/translation_entry.rb b/lib/gitlab/i18n/translation_entry.rb
index 54adb98f42d..19c10b2e402 100644
--- a/lib/gitlab/i18n/translation_entry.rb
+++ b/lib/gitlab/i18n/translation_entry.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module I18n
class TranslationEntry
diff --git a/lib/gitlab/import/logger.rb b/lib/gitlab/import/logger.rb
index 8414954d141..ab3e822a4e9 100644
--- a/lib/gitlab/import/logger.rb
+++ b/lib/gitlab/import/logger.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Import
class Logger < ::Gitlab::JsonLogger
diff --git a/lib/gitlab/import_export/after_export_strategies/base_after_export_strategy.rb b/lib/gitlab/import_export/after_export_strategies/base_after_export_strategy.rb
index 7cbf653dd97..d39b6fe5955 100644
--- a/lib/gitlab/import_export/after_export_strategies/base_after_export_strategy.rb
+++ b/lib/gitlab/import_export/after_export_strategies/base_after_export_strategy.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module ImportExport
module AfterExportStrategies
diff --git a/lib/gitlab/import_export/after_export_strategies/download_notification_strategy.rb b/lib/gitlab/import_export/after_export_strategies/download_notification_strategy.rb
index 4371a7eff56..1b391314a74 100644
--- a/lib/gitlab/import_export/after_export_strategies/download_notification_strategy.rb
+++ b/lib/gitlab/import_export/after_export_strategies/download_notification_strategy.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module ImportExport
module AfterExportStrategies
diff --git a/lib/gitlab/import_export/after_export_strategies/web_upload_strategy.rb b/lib/gitlab/import_export/after_export_strategies/web_upload_strategy.rb
index 4f29bdcea2c..b30900f7c61 100644
--- a/lib/gitlab/import_export/after_export_strategies/web_upload_strategy.rb
+++ b/lib/gitlab/import_export/after_export_strategies/web_upload_strategy.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module ImportExport
module AfterExportStrategies
diff --git a/lib/gitlab/import_export/after_export_strategy_builder.rb b/lib/gitlab/import_export/after_export_strategy_builder.rb
index 7eabcae2380..37394f46a99 100644
--- a/lib/gitlab/import_export/after_export_strategy_builder.rb
+++ b/lib/gitlab/import_export/after_export_strategy_builder.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module ImportExport
class AfterExportStrategyBuilder
diff --git a/lib/gitlab/import_export/attribute_cleaner.rb b/lib/gitlab/import_export/attribute_cleaner.rb
index 7c9fc5c15bb..93b37b7bc5f 100644
--- a/lib/gitlab/import_export/attribute_cleaner.rb
+++ b/lib/gitlab/import_export/attribute_cleaner.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module ImportExport
class AttributeCleaner
diff --git a/lib/gitlab/import_export/attributes_finder.rb b/lib/gitlab/import_export/attributes_finder.rb
index 0c8fda07294..409243e68a5 100644
--- a/lib/gitlab/import_export/attributes_finder.rb
+++ b/lib/gitlab/import_export/attributes_finder.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module ImportExport
class AttributesFinder
diff --git a/lib/gitlab/import_export/avatar_restorer.rb b/lib/gitlab/import_export/avatar_restorer.rb
index 17796430811..be1b97bd7a7 100644
--- a/lib/gitlab/import_export/avatar_restorer.rb
+++ b/lib/gitlab/import_export/avatar_restorer.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module ImportExport
class AvatarRestorer
diff --git a/lib/gitlab/import_export/avatar_saver.rb b/lib/gitlab/import_export/avatar_saver.rb
index 6ffebf83dd2..47ca898c690 100644
--- a/lib/gitlab/import_export/avatar_saver.rb
+++ b/lib/gitlab/import_export/avatar_saver.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module ImportExport
class AvatarSaver
diff --git a/lib/gitlab/import_export/command_line_util.rb b/lib/gitlab/import_export/command_line_util.rb
index 3adc44f8044..c9e2a6a78d9 100644
--- a/lib/gitlab/import_export/command_line_util.rb
+++ b/lib/gitlab/import_export/command_line_util.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module ImportExport
module CommandLineUtil
diff --git a/lib/gitlab/import_export/error.rb b/lib/gitlab/import_export/error.rb
index 788eedf2686..454dc778b6b 100644
--- a/lib/gitlab/import_export/error.rb
+++ b/lib/gitlab/import_export/error.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module ImportExport
Error = Class.new(StandardError)
diff --git a/lib/gitlab/import_export/file_importer.rb b/lib/gitlab/import_export/file_importer.rb
index 7fd66b4e244..05432f433e7 100644
--- a/lib/gitlab/import_export/file_importer.rb
+++ b/lib/gitlab/import_export/file_importer.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module ImportExport
class FileImporter
diff --git a/lib/gitlab/import_export/group_project_object_builder.rb b/lib/gitlab/import_export/group_project_object_builder.rb
index 6c2af770119..1c62591ed5a 100644
--- a/lib/gitlab/import_export/group_project_object_builder.rb
+++ b/lib/gitlab/import_export/group_project_object_builder.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module ImportExport
# Given a class, it finds or creates a new object
diff --git a/lib/gitlab/import_export/hash_util.rb b/lib/gitlab/import_export/hash_util.rb
index d4adeeb3797..b6ce89a973b 100644
--- a/lib/gitlab/import_export/hash_util.rb
+++ b/lib/gitlab/import_export/hash_util.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module ImportExport
class HashUtil
diff --git a/lib/gitlab/import_export/import_export.yml b/lib/gitlab/import_export/import_export.yml
index 9790818ecaf..b40eac3de9a 100644
--- a/lib/gitlab/import_export/import_export.yml
+++ b/lib/gitlab/import_export/import_export.yml
@@ -154,6 +154,8 @@ excluded_attributes:
- :encrypted_token_iv
- :encrypted_url
- :encrypted_url_iv
+ services:
+ - :template
methods:
labels:
diff --git a/lib/gitlab/import_export/importer.rb b/lib/gitlab/import_export/importer.rb
index 72d5b9b830c..767f1b5de0e 100644
--- a/lib/gitlab/import_export/importer.rb
+++ b/lib/gitlab/import_export/importer.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module ImportExport
class Importer
diff --git a/lib/gitlab/import_export/json_hash_builder.rb b/lib/gitlab/import_export/json_hash_builder.rb
index b48f63bcd7e..477499e1688 100644
--- a/lib/gitlab/import_export/json_hash_builder.rb
+++ b/lib/gitlab/import_export/json_hash_builder.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module ImportExport
# Generates a hash that conforms with http://apidock.com/rails/Hash/to_json
diff --git a/lib/gitlab/import_export/lfs_restorer.rb b/lib/gitlab/import_export/lfs_restorer.rb
index b28c3c161b7..345c7880e30 100644
--- a/lib/gitlab/import_export/lfs_restorer.rb
+++ b/lib/gitlab/import_export/lfs_restorer.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module ImportExport
class LfsRestorer
diff --git a/lib/gitlab/import_export/lfs_saver.rb b/lib/gitlab/import_export/lfs_saver.rb
index 29410e2331c..954f6f00078 100644
--- a/lib/gitlab/import_export/lfs_saver.rb
+++ b/lib/gitlab/import_export/lfs_saver.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module ImportExport
class LfsSaver
diff --git a/lib/gitlab/import_export/members_mapper.rb b/lib/gitlab/import_export/members_mapper.rb
index bcbaf00e11b..6be95a16513 100644
--- a/lib/gitlab/import_export/members_mapper.rb
+++ b/lib/gitlab/import_export/members_mapper.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module ImportExport
class MembersMapper
diff --git a/lib/gitlab/import_export/merge_request_parser.rb b/lib/gitlab/import_export/merge_request_parser.rb
index 62a1833b39c..040a70d6775 100644
--- a/lib/gitlab/import_export/merge_request_parser.rb
+++ b/lib/gitlab/import_export/merge_request_parser.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module ImportExport
class MergeRequestParser
diff --git a/lib/gitlab/import_export/project_tree_restorer.rb b/lib/gitlab/import_export/project_tree_restorer.rb
index 99581eb0416..8cd4efd91cc 100644
--- a/lib/gitlab/import_export/project_tree_restorer.rb
+++ b/lib/gitlab/import_export/project_tree_restorer.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module ImportExport
class ProjectTreeRestorer
diff --git a/lib/gitlab/import_export/project_tree_saver.rb b/lib/gitlab/import_export/project_tree_saver.rb
index 5510c0b8b2f..29f2dc80813 100644
--- a/lib/gitlab/import_export/project_tree_saver.rb
+++ b/lib/gitlab/import_export/project_tree_saver.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module ImportExport
class ProjectTreeSaver
diff --git a/lib/gitlab/import_export/reader.rb b/lib/gitlab/import_export/reader.rb
index e621c40fc7a..bc0d18e03fa 100644
--- a/lib/gitlab/import_export/reader.rb
+++ b/lib/gitlab/import_export/reader.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module ImportExport
class Reader
diff --git a/lib/gitlab/import_export/relation_factory.rb b/lib/gitlab/import_export/relation_factory.rb
index 2486b1e4921..097c7653754 100644
--- a/lib/gitlab/import_export/relation_factory.rb
+++ b/lib/gitlab/import_export/relation_factory.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module ImportExport
class RelationFactory
@@ -211,7 +213,7 @@ module Gitlab
def update_note_for_missing_author(author_name)
@relation_hash['note'] = '*Blank note*' if @relation_hash['note'].blank?
- @relation_hash['note'] += missing_author_note(@relation_hash['updated_at'], author_name)
+ @relation_hash['note'] = "#{@relation_hash['note']}#{missing_author_note(@relation_hash['updated_at'], author_name)}"
end
def admin_user?
diff --git a/lib/gitlab/import_export/repo_restorer.rb b/lib/gitlab/import_export/repo_restorer.rb
index 5a9bbceac67..921a06b4023 100644
--- a/lib/gitlab/import_export/repo_restorer.rb
+++ b/lib/gitlab/import_export/repo_restorer.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module ImportExport
class RepoRestorer
diff --git a/lib/gitlab/import_export/repo_saver.rb b/lib/gitlab/import_export/repo_saver.rb
index 0c224bd1971..a60618dfcec 100644
--- a/lib/gitlab/import_export/repo_saver.rb
+++ b/lib/gitlab/import_export/repo_saver.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module ImportExport
class RepoSaver
diff --git a/lib/gitlab/import_export/saver.rb b/lib/gitlab/import_export/saver.rb
index 59a74083395..72f575db095 100644
--- a/lib/gitlab/import_export/saver.rb
+++ b/lib/gitlab/import_export/saver.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module ImportExport
class Saver
diff --git a/lib/gitlab/import_export/shared.rb b/lib/gitlab/import_export/shared.rb
index 6d7c36ce38b..c13e6c1d83b 100644
--- a/lib/gitlab/import_export/shared.rb
+++ b/lib/gitlab/import_export/shared.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module ImportExport
class Shared
diff --git a/lib/gitlab/import_export/statistics_restorer.rb b/lib/gitlab/import_export/statistics_restorer.rb
index bcdd9c12c85..3fafb01c37c 100644
--- a/lib/gitlab/import_export/statistics_restorer.rb
+++ b/lib/gitlab/import_export/statistics_restorer.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module ImportExport
class StatisticsRestorer
diff --git a/lib/gitlab/import_export/uploads_manager.rb b/lib/gitlab/import_export/uploads_manager.rb
index 8511319cb1c..474e9d45566 100644
--- a/lib/gitlab/import_export/uploads_manager.rb
+++ b/lib/gitlab/import_export/uploads_manager.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module ImportExport
class UploadsManager
diff --git a/lib/gitlab/import_export/uploads_restorer.rb b/lib/gitlab/import_export/uploads_restorer.rb
index b4313ff4cb4..5f422dcbefa 100644
--- a/lib/gitlab/import_export/uploads_restorer.rb
+++ b/lib/gitlab/import_export/uploads_restorer.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module ImportExport
class UploadsRestorer < UploadsSaver
diff --git a/lib/gitlab/import_export/uploads_saver.rb b/lib/gitlab/import_export/uploads_saver.rb
index 0275f686c5e..be1066c30b2 100644
--- a/lib/gitlab/import_export/uploads_saver.rb
+++ b/lib/gitlab/import_export/uploads_saver.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module ImportExport
class UploadsSaver
diff --git a/lib/gitlab/import_export/version_checker.rb b/lib/gitlab/import_export/version_checker.rb
index bd3c3ee3b2f..6d978d00ea5 100644
--- a/lib/gitlab/import_export/version_checker.rb
+++ b/lib/gitlab/import_export/version_checker.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module ImportExport
class VersionChecker
diff --git a/lib/gitlab/import_export/version_saver.rb b/lib/gitlab/import_export/version_saver.rb
index 7cf88298642..8230c0f1e77 100644
--- a/lib/gitlab/import_export/version_saver.rb
+++ b/lib/gitlab/import_export/version_saver.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module ImportExport
class VersionSaver
diff --git a/lib/gitlab/import_export/wiki_repo_saver.rb b/lib/gitlab/import_export/wiki_repo_saver.rb
index 2fd62c0fc7b..7303bcf61a4 100644
--- a/lib/gitlab/import_export/wiki_repo_saver.rb
+++ b/lib/gitlab/import_export/wiki_repo_saver.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module ImportExport
class WikiRepoSaver < RepoSaver
diff --git a/lib/gitlab/import_export/wiki_restorer.rb b/lib/gitlab/import_export/wiki_restorer.rb
index f33bfb332ab..28b5e7449cd 100644
--- a/lib/gitlab/import_export/wiki_restorer.rb
+++ b/lib/gitlab/import_export/wiki_restorer.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module ImportExport
class WikiRestorer < RepoRestorer
diff --git a/lib/gitlab/kubernetes/config_map.rb b/lib/gitlab/kubernetes/config_map.rb
index 9e55dae137c..0bcaaa03974 100644
--- a/lib/gitlab/kubernetes/config_map.rb
+++ b/lib/gitlab/kubernetes/config_map.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Kubernetes
class ConfigMap
diff --git a/lib/gitlab/kubernetes/helm.rb b/lib/gitlab/kubernetes/helm.rb
index 5a22b5e3364..03d38ec78fd 100644
--- a/lib/gitlab/kubernetes/helm.rb
+++ b/lib/gitlab/kubernetes/helm.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Kubernetes
module Helm
diff --git a/lib/gitlab/kubernetes/helm/api.rb b/lib/gitlab/kubernetes/helm/api.rb
index 7c026ac9e68..fd3d187cbc3 100644
--- a/lib/gitlab/kubernetes/helm/api.rb
+++ b/lib/gitlab/kubernetes/helm/api.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Kubernetes
module Helm
diff --git a/lib/gitlab/kubernetes/helm/base_command.rb b/lib/gitlab/kubernetes/helm/base_command.rb
index f2ce24fefa1..2bcb428b25d 100644
--- a/lib/gitlab/kubernetes/helm/base_command.rb
+++ b/lib/gitlab/kubernetes/helm/base_command.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Kubernetes
module Helm
diff --git a/lib/gitlab/kubernetes/helm/client_command.rb b/lib/gitlab/kubernetes/helm/client_command.rb
index 72bafc07bf0..9940272a8bf 100644
--- a/lib/gitlab/kubernetes/helm/client_command.rb
+++ b/lib/gitlab/kubernetes/helm/client_command.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Kubernetes
module Helm
diff --git a/lib/gitlab/kubernetes/helm/init_command.rb b/lib/gitlab/kubernetes/helm/init_command.rb
index 6691080deca..88ed8572ffc 100644
--- a/lib/gitlab/kubernetes/helm/init_command.rb
+++ b/lib/gitlab/kubernetes/helm/init_command.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Kubernetes
module Helm
diff --git a/lib/gitlab/kubernetes/helm/install_command.rb b/lib/gitlab/kubernetes/helm/install_command.rb
index 52700b5dc09..961485005f7 100644
--- a/lib/gitlab/kubernetes/helm/install_command.rb
+++ b/lib/gitlab/kubernetes/helm/install_command.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Kubernetes
module Helm
diff --git a/lib/gitlab/kubernetes/helm/pod.rb b/lib/gitlab/kubernetes/helm/pod.rb
index e9c621d96f0..75484f80070 100644
--- a/lib/gitlab/kubernetes/helm/pod.rb
+++ b/lib/gitlab/kubernetes/helm/pod.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Kubernetes
module Helm
diff --git a/lib/gitlab/kubernetes/namespace.rb b/lib/gitlab/kubernetes/namespace.rb
index 783c8a24741..919f19c86d7 100644
--- a/lib/gitlab/kubernetes/namespace.rb
+++ b/lib/gitlab/kubernetes/namespace.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Kubernetes
class Namespace
diff --git a/lib/gitlab/kubernetes/pod.rb b/lib/gitlab/kubernetes/pod.rb
index f3842cdf762..81317e532b2 100644
--- a/lib/gitlab/kubernetes/pod.rb
+++ b/lib/gitlab/kubernetes/pod.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Kubernetes
module Pod
diff --git a/lib/gitlab/legacy_github_import/base_formatter.rb b/lib/gitlab/legacy_github_import/base_formatter.rb
index 11d1300e51e..0b19cf742ed 100644
--- a/lib/gitlab/legacy_github_import/base_formatter.rb
+++ b/lib/gitlab/legacy_github_import/base_formatter.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module LegacyGithubImport
class BaseFormatter
diff --git a/lib/gitlab/legacy_github_import/branch_formatter.rb b/lib/gitlab/legacy_github_import/branch_formatter.rb
index 80fe1d67209..1177751457f 100644
--- a/lib/gitlab/legacy_github_import/branch_formatter.rb
+++ b/lib/gitlab/legacy_github_import/branch_formatter.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module LegacyGithubImport
class BranchFormatter < BaseFormatter
diff --git a/lib/gitlab/legacy_github_import/client.rb b/lib/gitlab/legacy_github_import/client.rb
index d8ed0ebca9d..bc952147667 100644
--- a/lib/gitlab/legacy_github_import/client.rb
+++ b/lib/gitlab/legacy_github_import/client.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module LegacyGithubImport
class Client
diff --git a/lib/gitlab/legacy_github_import/comment_formatter.rb b/lib/gitlab/legacy_github_import/comment_formatter.rb
index d2c7a8ae9f4..d83cc4f6b3c 100644
--- a/lib/gitlab/legacy_github_import/comment_formatter.rb
+++ b/lib/gitlab/legacy_github_import/comment_formatter.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module LegacyGithubImport
class CommentFormatter < BaseFormatter
diff --git a/lib/gitlab/legacy_github_import/importer.rb b/lib/gitlab/legacy_github_import/importer.rb
index c5bde681365..43695451b87 100644
--- a/lib/gitlab/legacy_github_import/importer.rb
+++ b/lib/gitlab/legacy_github_import/importer.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module LegacyGithubImport
class Importer
diff --git a/lib/gitlab/legacy_github_import/issuable_formatter.rb b/lib/gitlab/legacy_github_import/issuable_formatter.rb
index 7db4a54267e..1a0aefbbd62 100644
--- a/lib/gitlab/legacy_github_import/issuable_formatter.rb
+++ b/lib/gitlab/legacy_github_import/issuable_formatter.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module LegacyGithubImport
class IssuableFormatter < BaseFormatter
diff --git a/lib/gitlab/legacy_github_import/issue_formatter.rb b/lib/gitlab/legacy_github_import/issue_formatter.rb
index 4c8825ccf19..2f46e2e30d1 100644
--- a/lib/gitlab/legacy_github_import/issue_formatter.rb
+++ b/lib/gitlab/legacy_github_import/issue_formatter.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module LegacyGithubImport
class IssueFormatter < IssuableFormatter
diff --git a/lib/gitlab/legacy_github_import/label_formatter.rb b/lib/gitlab/legacy_github_import/label_formatter.rb
index e9663650903..89200e794d8 100644
--- a/lib/gitlab/legacy_github_import/label_formatter.rb
+++ b/lib/gitlab/legacy_github_import/label_formatter.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module LegacyGithubImport
class LabelFormatter < BaseFormatter
diff --git a/lib/gitlab/legacy_github_import/milestone_formatter.rb b/lib/gitlab/legacy_github_import/milestone_formatter.rb
index a565294384d..2fe1b4258d3 100644
--- a/lib/gitlab/legacy_github_import/milestone_formatter.rb
+++ b/lib/gitlab/legacy_github_import/milestone_formatter.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module LegacyGithubImport
class MilestoneFormatter < BaseFormatter
diff --git a/lib/gitlab/legacy_github_import/project_creator.rb b/lib/gitlab/legacy_github_import/project_creator.rb
index 5e96eb16754..ca1a1b8e9bd 100644
--- a/lib/gitlab/legacy_github_import/project_creator.rb
+++ b/lib/gitlab/legacy_github_import/project_creator.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module LegacyGithubImport
class ProjectCreator
diff --git a/lib/gitlab/legacy_github_import/pull_request_formatter.rb b/lib/gitlab/legacy_github_import/pull_request_formatter.rb
index 94c2e99066a..5b847f13d4a 100644
--- a/lib/gitlab/legacy_github_import/pull_request_formatter.rb
+++ b/lib/gitlab/legacy_github_import/pull_request_formatter.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module LegacyGithubImport
class PullRequestFormatter < IssuableFormatter
diff --git a/lib/gitlab/legacy_github_import/release_formatter.rb b/lib/gitlab/legacy_github_import/release_formatter.rb
index 3ed9d4f76da..8c0c17780ca 100644
--- a/lib/gitlab/legacy_github_import/release_formatter.rb
+++ b/lib/gitlab/legacy_github_import/release_formatter.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module LegacyGithubImport
class ReleaseFormatter < BaseFormatter
diff --git a/lib/gitlab/legacy_github_import/user_formatter.rb b/lib/gitlab/legacy_github_import/user_formatter.rb
index 3794380e2d0..ec0e221b1ff 100644
--- a/lib/gitlab/legacy_github_import/user_formatter.rb
+++ b/lib/gitlab/legacy_github_import/user_formatter.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module LegacyGithubImport
class UserFormatter
diff --git a/lib/gitlab/legacy_github_import/wiki_formatter.rb b/lib/gitlab/legacy_github_import/wiki_formatter.rb
index 27f45875c7c..ea52be5ee0f 100644
--- a/lib/gitlab/legacy_github_import/wiki_formatter.rb
+++ b/lib/gitlab/legacy_github_import/wiki_formatter.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module LegacyGithubImport
class WikiFormatter
diff --git a/lib/gitlab/manifest_import/manifest.rb b/lib/gitlab/manifest_import/manifest.rb
index b69b9ac4b64..7208fe5bbc5 100644
--- a/lib/gitlab/manifest_import/manifest.rb
+++ b/lib/gitlab/manifest_import/manifest.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# Class to parse manifest file and build a list of repositories for import
#
# <manifest>
diff --git a/lib/gitlab/manifest_import/project_creator.rb b/lib/gitlab/manifest_import/project_creator.rb
index b5967c93735..837d65e5f7c 100644
--- a/lib/gitlab/manifest_import/project_creator.rb
+++ b/lib/gitlab/manifest_import/project_creator.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module ManifestImport
class ProjectCreator
diff --git a/lib/gitlab/metrics/background_transaction.rb b/lib/gitlab/metrics/background_transaction.rb
index 5919ebb1493..fe1722b1095 100644
--- a/lib/gitlab/metrics/background_transaction.rb
+++ b/lib/gitlab/metrics/background_transaction.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Metrics
class BackgroundTransaction < Transaction
diff --git a/lib/gitlab/metrics/delta.rb b/lib/gitlab/metrics/delta.rb
index bcf28eed84d..ab2d9e46390 100644
--- a/lib/gitlab/metrics/delta.rb
+++ b/lib/gitlab/metrics/delta.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Metrics
# Class for calculating the difference between two numeric values.
diff --git a/lib/gitlab/metrics/influx_db.rb b/lib/gitlab/metrics/influx_db.rb
index ce9d3ec3de4..1359e973590 100644
--- a/lib/gitlab/metrics/influx_db.rb
+++ b/lib/gitlab/metrics/influx_db.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Metrics
module InfluxDb
diff --git a/lib/gitlab/metrics/instrumentation.rb b/lib/gitlab/metrics/instrumentation.rb
index 023e9963493..651e241362c 100644
--- a/lib/gitlab/metrics/instrumentation.rb
+++ b/lib/gitlab/metrics/instrumentation.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Metrics
# Module for instrumenting methods.
diff --git a/lib/gitlab/metrics/method_call.rb b/lib/gitlab/metrics/method_call.rb
index f3290e3149c..85438011cb9 100644
--- a/lib/gitlab/metrics/method_call.rb
+++ b/lib/gitlab/metrics/method_call.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Metrics
# Class for tracking timing information about method calls
diff --git a/lib/gitlab/metrics/methods.rb b/lib/gitlab/metrics/methods.rb
index f79eb0cd1bf..447d03bfca4 100644
--- a/lib/gitlab/metrics/methods.rb
+++ b/lib/gitlab/metrics/methods.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# rubocop:disable Style/ClassVars
module Gitlab
diff --git a/lib/gitlab/metrics/methods/metric_options.rb b/lib/gitlab/metrics/methods/metric_options.rb
index 70e122d4e15..8e6ceb74c09 100644
--- a/lib/gitlab/metrics/methods/metric_options.rb
+++ b/lib/gitlab/metrics/methods/metric_options.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Metrics
module Methods
diff --git a/lib/gitlab/metrics/metric.rb b/lib/gitlab/metrics/metric.rb
index bd0afe53c51..9e4d70a71ff 100644
--- a/lib/gitlab/metrics/metric.rb
+++ b/lib/gitlab/metrics/metric.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Metrics
# Class for storing details of a single metric (label, value, etc).
diff --git a/lib/gitlab/metrics/null_metric.rb b/lib/gitlab/metrics/null_metric.rb
index aabada5c21a..7dbd2a1f8e3 100644
--- a/lib/gitlab/metrics/null_metric.rb
+++ b/lib/gitlab/metrics/null_metric.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Metrics
# Mocks ::Prometheus::Client::Metric and all derived metrics
diff --git a/lib/gitlab/metrics/prometheus.rb b/lib/gitlab/metrics/prometheus.rb
index d41a855bff1..cab1edab48f 100644
--- a/lib/gitlab/metrics/prometheus.rb
+++ b/lib/gitlab/metrics/prometheus.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'prometheus/client'
module Gitlab
diff --git a/lib/gitlab/metrics/rack_middleware.rb b/lib/gitlab/metrics/rack_middleware.rb
index 2d45765df3f..9aa97515961 100644
--- a/lib/gitlab/metrics/rack_middleware.rb
+++ b/lib/gitlab/metrics/rack_middleware.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Metrics
# Rack middleware for tracking Rails and Grape requests.
diff --git a/lib/gitlab/metrics/requests_rack_middleware.rb b/lib/gitlab/metrics/requests_rack_middleware.rb
index 0dc19f31d03..74c956ab5af 100644
--- a/lib/gitlab/metrics/requests_rack_middleware.rb
+++ b/lib/gitlab/metrics/requests_rack_middleware.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Metrics
class RequestsRackMiddleware
diff --git a/lib/gitlab/metrics/samplers/base_sampler.rb b/lib/gitlab/metrics/samplers/base_sampler.rb
index 37f90c4673d..6a062e93f0f 100644
--- a/lib/gitlab/metrics/samplers/base_sampler.rb
+++ b/lib/gitlab/metrics/samplers/base_sampler.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'logger'
module Gitlab
diff --git a/lib/gitlab/metrics/samplers/influx_sampler.rb b/lib/gitlab/metrics/samplers/influx_sampler.rb
index ad97632e4eb..c4c38b23a55 100644
--- a/lib/gitlab/metrics/samplers/influx_sampler.rb
+++ b/lib/gitlab/metrics/samplers/influx_sampler.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Metrics
module Samplers
diff --git a/lib/gitlab/metrics/samplers/ruby_sampler.rb b/lib/gitlab/metrics/samplers/ruby_sampler.rb
index 7b2b3bedf04..232a58a7d69 100644
--- a/lib/gitlab/metrics/samplers/ruby_sampler.rb
+++ b/lib/gitlab/metrics/samplers/ruby_sampler.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'prometheus/client/support/unicorn'
module Gitlab
diff --git a/lib/gitlab/metrics/samplers/unicorn_sampler.rb b/lib/gitlab/metrics/samplers/unicorn_sampler.rb
index ea325651fbb..4c4ec026823 100644
--- a/lib/gitlab/metrics/samplers/unicorn_sampler.rb
+++ b/lib/gitlab/metrics/samplers/unicorn_sampler.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Metrics
module Samplers
diff --git a/lib/gitlab/metrics/sidekiq_metrics_exporter.rb b/lib/gitlab/metrics/sidekiq_metrics_exporter.rb
index 47b4af5d649..56e106b9612 100644
--- a/lib/gitlab/metrics/sidekiq_metrics_exporter.rb
+++ b/lib/gitlab/metrics/sidekiq_metrics_exporter.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'webrick'
require 'prometheus/client/rack/exporter'
diff --git a/lib/gitlab/metrics/sidekiq_middleware.rb b/lib/gitlab/metrics/sidekiq_middleware.rb
index df4bdf16847..0b4485feea9 100644
--- a/lib/gitlab/metrics/sidekiq_middleware.rb
+++ b/lib/gitlab/metrics/sidekiq_middleware.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Metrics
# Sidekiq middleware for tracking jobs.
diff --git a/lib/gitlab/metrics/subscribers/action_view.rb b/lib/gitlab/metrics/subscribers/action_view.rb
index b600e8a2a50..c068f8017fd 100644
--- a/lib/gitlab/metrics/subscribers/action_view.rb
+++ b/lib/gitlab/metrics/subscribers/action_view.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Metrics
module Subscribers
diff --git a/lib/gitlab/metrics/subscribers/active_record.rb b/lib/gitlab/metrics/subscribers/active_record.rb
index 04107296ae3..a02dd850582 100644
--- a/lib/gitlab/metrics/subscribers/active_record.rb
+++ b/lib/gitlab/metrics/subscribers/active_record.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Metrics
module Subscribers
diff --git a/lib/gitlab/metrics/subscribers/rails_cache.rb b/lib/gitlab/metrics/subscribers/rails_cache.rb
index 250897a79c2..f633e1a9d7c 100644
--- a/lib/gitlab/metrics/subscribers/rails_cache.rb
+++ b/lib/gitlab/metrics/subscribers/rails_cache.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Metrics
module Subscribers
diff --git a/lib/gitlab/metrics/system.rb b/lib/gitlab/metrics/system.rb
index e60e245cf89..426496855e3 100644
--- a/lib/gitlab/metrics/system.rb
+++ b/lib/gitlab/metrics/system.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Metrics
# Module for gathering system/process statistics such as the memory usage.
diff --git a/lib/gitlab/metrics/transaction.rb b/lib/gitlab/metrics/transaction.rb
index 9f903e96585..468d7cb56fc 100644
--- a/lib/gitlab/metrics/transaction.rb
+++ b/lib/gitlab/metrics/transaction.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Metrics
# Class for storing metrics information of a single transaction.
diff --git a/lib/gitlab/metrics/web_transaction.rb b/lib/gitlab/metrics/web_transaction.rb
index 723ca576aab..b2a43d46fb2 100644
--- a/lib/gitlab/metrics/web_transaction.rb
+++ b/lib/gitlab/metrics/web_transaction.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Metrics
class WebTransaction < Transaction
@@ -40,7 +42,7 @@ module Gitlab
# increasing the cardinality of our metrics, we limit the number of
# possible suffixes.
if suffix && ALLOWED_SUFFIXES.include?(suffix)
- action += ".#{suffix}"
+ action = "#{action}.#{suffix}"
end
{ controller: controller.class.name, action: action }
diff --git a/lib/gitlab/middleware/go.rb b/lib/gitlab/middleware/go.rb
index 6943567fb6d..d1a87c3b3bb 100644
--- a/lib/gitlab/middleware/go.rb
+++ b/lib/gitlab/middleware/go.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# A dumb middleware that returns a Go HTML document if the go-get=1 query string
# is used irrespective if the namespace/project exists
module Gitlab
diff --git a/lib/gitlab/middleware/multipart.rb b/lib/gitlab/middleware/multipart.rb
index 10cb1e7127e..84c2f0d5720 100644
--- a/lib/gitlab/middleware/multipart.rb
+++ b/lib/gitlab/middleware/multipart.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# Gitlab::Middleware::Multipart - a Rack::Multipart replacement
#
# Rack::Multipart leaves behind tempfiles in /tmp and uses valuable Ruby
diff --git a/lib/gitlab/middleware/rails_queue_duration.rb b/lib/gitlab/middleware/rails_queue_duration.rb
index bc70b2459ef..96c6a0a7d28 100644
--- a/lib/gitlab/middleware/rails_queue_duration.rb
+++ b/lib/gitlab/middleware/rails_queue_duration.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# This Rack middleware is intended to measure the latency between
# gitlab-workhorse forwarding a request to the Rails application and the
# time this middleware is reached.
diff --git a/lib/gitlab/middleware/read_only.rb b/lib/gitlab/middleware/read_only.rb
index 7f63e39b3aa..83c52a6c6e0 100644
--- a/lib/gitlab/middleware/read_only.rb
+++ b/lib/gitlab/middleware/read_only.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Middleware
class ReadOnly
diff --git a/lib/gitlab/middleware/read_only/controller.rb b/lib/gitlab/middleware/read_only/controller.rb
index 8dca431c005..89941a9efa0 100644
--- a/lib/gitlab/middleware/read_only/controller.rb
+++ b/lib/gitlab/middleware/read_only/controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Middleware
class ReadOnly
diff --git a/lib/gitlab/middleware/release_env.rb b/lib/gitlab/middleware/release_env.rb
index bfe8e113b5e..849cf8f759b 100644
--- a/lib/gitlab/middleware/release_env.rb
+++ b/lib/gitlab/middleware/release_env.rb
@@ -1,4 +1,7 @@
-module Gitlab # rubocop:disable Naming/FileName
+# rubocop:disable Naming/FileName
+# frozen_string_literal: true
+
+module Gitlab
module Middleware
# Some of middleware would hold env for no good reason even after the
# request had already been processed, and we could not garbage collect
diff --git a/lib/gitlab/middleware/static.rb b/lib/gitlab/middleware/static.rb
index aa1e9dc0fdb..972fed2134c 100644
--- a/lib/gitlab/middleware/static.rb
+++ b/lib/gitlab/middleware/static.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Middleware
class Static < ActionDispatch::Static
diff --git a/lib/gitlab/private_commit_email.rb b/lib/gitlab/private_commit_email.rb
index bade2248ccd..536fc9dae3a 100644
--- a/lib/gitlab/private_commit_email.rb
+++ b/lib/gitlab/private_commit_email.rb
@@ -18,6 +18,10 @@ module Gitlab
match[:id].to_i
end
+ def user_ids_for_emails(emails)
+ emails.map { |email| user_id_for_email(email) }.compact.uniq
+ end
+
def for_user(user)
hostname = Gitlab::CurrentSettings.current_application_settings.commit_email_hostname
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index f18821adb5f..c021d1aad1c 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -2211,6 +2211,9 @@ msgstr ""
msgid "Define a custom pattern with cron syntax"
msgstr ""
+msgid "Define environments in the deploy stage(s) in <code>.gitlab-ci.yml</code> to track deployments here."
+msgstr ""
+
msgid "DelayedJobs|Are you sure you want to run %{jobName} immediately? Otherwise this job will run automatically after it's timer finishes."
msgstr ""
@@ -2510,6 +2513,9 @@ msgstr ""
msgid "Edit application"
msgstr ""
+msgid "Edit environment"
+msgstr ""
+
msgid "Edit files in the editor and commit changes here"
msgstr ""
@@ -2588,6 +2594,9 @@ msgstr ""
msgid "Environments"
msgstr ""
+msgid "Environments allow you to track deployments of your application %{link_to_read_more}."
+msgstr ""
+
msgid "Environments|An error occurred while fetching the environments."
msgstr ""
@@ -2657,6 +2666,9 @@ msgstr ""
msgid "Environments|Stop environment"
msgstr ""
+msgid "Environments|Stopping"
+msgstr ""
+
msgid "Environments|Updated"
msgstr ""
@@ -2792,6 +2804,9 @@ msgstr ""
msgid "Explore public groups"
msgstr ""
+msgid "External URL"
+msgstr ""
+
msgid "Facebook"
msgstr ""
@@ -3881,6 +3896,9 @@ msgstr ""
msgid "Metrics and profiling"
msgstr ""
+msgid "Metrics for environment"
+msgstr ""
+
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
msgstr ""
@@ -4025,6 +4043,9 @@ msgstr ""
msgid "New Application"
msgstr ""
+msgid "New Environment"
+msgstr ""
+
msgid "New Group"
msgstr ""
@@ -4057,6 +4078,9 @@ msgstr ""
msgid "New directory"
msgstr ""
+msgid "New environment"
+msgstr ""
+
msgid "New file"
msgstr ""
@@ -4434,6 +4458,9 @@ msgstr ""
msgid "Personal Access Token"
msgstr ""
+msgid "Pick a name"
+msgstr ""
+
msgid "Pipeline"
msgstr ""
@@ -5130,6 +5157,9 @@ msgstr ""
msgid "Read more"
msgstr ""
+msgid "Read more about environments"
+msgstr ""
+
msgid "Read more about project permissions <strong>%{link_to_help}</strong>"
msgstr ""
@@ -5156,6 +5186,9 @@ msgstr ""
msgid "Register / Sign In"
msgstr ""
+msgid "Register U2F device"
+msgstr ""
+
msgid "Register and see your runners for this group."
msgstr ""
@@ -5503,6 +5536,9 @@ msgstr ""
msgid "Secret"
msgstr ""
+msgid "See metrics"
+msgstr ""
+
msgid "Select"
msgstr ""
@@ -5596,6 +5632,9 @@ msgstr ""
msgid "Set up a specific Runner automatically"
msgstr ""
+msgid "Set up new U2F device"
+msgstr ""
+
msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
msgstr ""
@@ -5676,6 +5715,9 @@ msgstr ""
msgid "Sign in / Register"
msgstr ""
+msgid "Sign in via 2FA code"
+msgstr ""
+
msgid "Sign out"
msgstr ""
@@ -5961,9 +6003,6 @@ msgstr ""
msgid "Subscribed"
msgstr ""
-msgid "Summary of issues, merge requests, push events, and comments (Timezone: %{utcFormatted})"
-msgstr ""
-
msgid "Switch branch/tag"
msgstr ""
@@ -6077,6 +6116,9 @@ msgstr ""
msgid "Templates"
msgstr ""
+msgid "Terminal for environment"
+msgstr ""
+
msgid "Terms of Service Agreement and Privacy Policy"
msgstr ""
@@ -6681,6 +6723,12 @@ msgstr ""
msgid "Try again"
msgstr ""
+msgid "Try again?"
+msgstr ""
+
+msgid "Trying to communicate with your device. Plug it in (if you haven't already) and press the button on the device now."
+msgstr ""
+
msgid "Twitter"
msgstr ""
@@ -6837,9 +6885,6 @@ msgstr ""
msgid "UserProfile|Personal projects"
msgstr ""
-msgid "UserProfile|Recent contributions"
-msgstr ""
-
msgid "UserProfile|Report abuse"
msgstr ""
@@ -6885,6 +6930,9 @@ msgstr ""
msgid "View app"
msgstr ""
+msgid "View deployment"
+msgstr ""
+
msgid "View file @ "
msgstr ""
@@ -6948,6 +6996,9 @@ msgstr ""
msgid "We don't have enough data to show this stage."
msgstr ""
+msgid "We heard back from your U2F device. You have been authenticated."
+msgstr ""
+
msgid "We want to be sure it is you, please confirm you are not a robot."
msgstr ""
@@ -7182,6 +7233,9 @@ msgstr ""
msgid "You don't have any authorized applications"
msgstr ""
+msgid "You don't have any deployments right now."
+msgstr ""
+
msgid "You have no permissions"
msgstr ""
@@ -7197,6 +7251,9 @@ msgstr ""
msgid "You need permission."
msgstr ""
+msgid "You need to register a two-factor authentication app before you can set up a U2F device."
+msgstr ""
+
msgid "You will loose all changes you've made to this file. This action cannot be undone."
msgstr ""
@@ -7257,12 +7314,18 @@ msgstr ""
msgid "Your Todos"
msgstr ""
+msgid "Your U2F device needs to be set up. Plug it in (if not already) and click the button on the left."
+msgstr ""
+
msgid "Your applications (%{size})"
msgstr ""
msgid "Your authorized applications"
msgstr ""
+msgid "Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer)."
+msgstr ""
+
msgid "Your changes can be committed to %{branch_name} because a merge request is open."
msgstr ""
@@ -7272,6 +7335,9 @@ msgstr ""
msgid "Your comment will not be visible to the public."
msgstr ""
+msgid "Your device was successfully set up! Give it a name and register it with the GitLab server."
+msgstr ""
+
msgid "Your groups"
msgstr ""
@@ -7325,6 +7391,9 @@ msgstr ""
msgid "enabled"
msgstr ""
+msgid "error code:"
+msgstr ""
+
msgid "estimateCommand|%{slash_command} will update the estimated time with the latest command."
msgstr ""
diff --git a/package.json b/package.json
index 2d6479fea3f..ac4b4672c86 100644
--- a/package.json
+++ b/package.json
@@ -24,8 +24,8 @@
"@babel/plugin-syntax-dynamic-import": "^7.0.0",
"@babel/plugin-syntax-import-meta": "^7.0.0",
"@babel/preset-env": "^7.1.0",
- "@gitlab-org/gitlab-ui": "^1.10.0",
- "@gitlab/svgs": "^1.35.0",
+ "@gitlab/svgs": "^1.38.0",
+ "@gitlab/ui": "^1.11.0",
"autosize": "^4.0.0",
"axios": "^0.17.1",
"babel-loader": "^8.0.4",
diff --git a/qa/qa/resource/user.rb b/qa/qa/resource/user.rb
index 16f0b311fa9..9be88ba4211 100644
--- a/qa/qa/resource/user.rb
+++ b/qa/qa/resource/user.rb
@@ -76,6 +76,17 @@ module QA
}
end
+ def self.fabricate_or_use(username, password)
+ if Runtime::Env.signup_disabled?
+ self.new.tap do |user|
+ user.username = username
+ user.password = password
+ end
+ else
+ self.fabricate!
+ end
+ end
+
private
def fetch_id(username)
diff --git a/qa/qa/runtime/env.rb b/qa/qa/runtime/env.rb
index c4500f9be90..1154eaca6a9 100644
--- a/qa/qa/runtime/env.rb
+++ b/qa/qa/runtime/env.rb
@@ -75,6 +75,22 @@ module QA
ENV['GITLAB_FORKER_PASSWORD']
end
+ def gitlab_qa_username_1
+ ENV['GITLAB_QA_USERNAME_1'] || 'gitlab-qa-user1'
+ end
+
+ def gitlab_qa_password_1
+ ENV['GITLAB_QA_PASSWORD_1']
+ end
+
+ def gitlab_qa_username_2
+ ENV['GITLAB_QA_USERNAME_2'] || 'gitlab-qa-user2'
+ end
+
+ def gitlab_qa_password_2
+ ENV['GITLAB_QA_PASSWORD_2']
+ end
+
def ldap_username
ENV['GITLAB_LDAP_USERNAME']
end
diff --git a/qa/qa/specs/features/browser_ui/1_manage/project/add_project_member_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/project/add_project_member_spec.rb
index bef89d5be24..4070a225260 100644
--- a/qa/qa/specs/features/browser_ui/1_manage/project/add_project_member_spec.rb
+++ b/qa/qa/specs/features/browser_ui/1_manage/project/add_project_member_spec.rb
@@ -7,7 +7,7 @@ module QA
Runtime::Browser.visit(:gitlab, Page::Main::Login)
Page::Main::Login.perform(&:sign_in_using_credentials)
- user = Resource::User.fabricate!
+ user = Resource::User.fabricate_or_use(Runtime::Env.gitlab_qa_username_1, Runtime::Env.gitlab_qa_password_1)
project = Resource::Project.fabricate! do |resource|
resource.name = 'add-member-project'
diff --git a/spec/controllers/application_controller_spec.rb b/spec/controllers/application_controller_spec.rb
index 4e91068ab88..efc3ce74627 100644
--- a/spec/controllers/application_controller_spec.rb
+++ b/spec/controllers/application_controller_spec.rb
@@ -650,7 +650,7 @@ describe ApplicationController do
describe '#access_denied' do
controller(described_class) do
def index
- access_denied!(params[:message])
+ access_denied!(params[:message], params[:status])
end
end
@@ -669,6 +669,12 @@ describe ApplicationController do
expect(response).to have_gitlab_http_status(403)
end
+
+ it 'renders a status passed to access denied' do
+ get :index, status: 401
+
+ expect(response).to have_gitlab_http_status(401)
+ end
end
context 'when invalid UTF-8 parameters are received' do
diff --git a/spec/controllers/concerns/issuable_collections_spec.rb b/spec/controllers/concerns/issuable_collections_spec.rb
index d16a3464495..e93c923fd39 100644
--- a/spec/controllers/concerns/issuable_collections_spec.rb
+++ b/spec/controllers/concerns/issuable_collections_spec.rb
@@ -60,7 +60,7 @@ describe IssuableCollections do
end
end
- describe '#filter_params' do
+ describe '#finder_options' do
let(:params) do
{
assignee_id: '1',
@@ -84,25 +84,20 @@ describe IssuableCollections do
}
end
- it 'filters params' do
+ it 'only allows whitelisted params' do
allow(controller).to receive(:cookies).and_return({})
- filtered_params = controller.send(:filter_params)
+ finder_options = controller.send(:finder_options)
- expect(filtered_params).to eq({
+ expect(finder_options).to eq({
'assignee_id' => '1',
'assignee_username' => 'user1',
'author_id' => '2',
'author_username' => 'user2',
- 'authorized_only' => 'true',
- 'due_date' => '2017-01-01',
- 'group_id' => '3',
- 'iids' => '4',
'label_name' => 'foo',
'milestone_title' => 'bar',
'my_reaction_emoji' => 'thumbsup',
- 'non_archived' => 'true',
- 'project_id' => '5',
+ 'due_date' => '2017-01-01',
'scope' => 'all',
'search' => 'baz',
'sort' => 'priority',
diff --git a/spec/controllers/projects/deploy_keys_controller_spec.rb b/spec/controllers/projects/deploy_keys_controller_spec.rb
index 73bf169085f..4567a51b88e 100644
--- a/spec/controllers/projects/deploy_keys_controller_spec.rb
+++ b/spec/controllers/projects/deploy_keys_controller_spec.rb
@@ -27,12 +27,8 @@ describe Projects::DeployKeysController do
let(:project2) { create(:project, :internal)}
let(:project_private) { create(:project, :private)}
- let(:deploy_key_internal) do
- create(:deploy_key, key: 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQCdMHEHyhRjbhEZVddFn6lTWdgEy5Q6Bz4nwGB76xWZI5YT/1WJOMEW+sL5zYd31kk7sd3FJ5L9ft8zWMWrr/iWXQikC2cqZK24H1xy+ZUmrRuJD4qGAaIVoyyzBL+avL+lF8J5lg6YSw8gwJY/lX64/vnJHUlWw2n5BF8IFOWhiw== dummy@gitlab.com')
- end
- let(:deploy_key_actual) do
- create(:deploy_key, key: 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDNd/UJWhPrpb+b/G5oL109y57yKuCxE+WUGJGYaj7WQKsYRJmLYh1mgjrl+KVyfsWpq4ylOxIfFSnN9xBBFN8mlb0Fma5DC7YsSsibJr3MZ19ZNBprwNcdogET7aW9I0In7Wu5f2KqI6e5W/spJHCy4JVxzVMUvk6Myab0LnJ2iQ== dummy@gitlab.com')
- end
+ let(:deploy_key_internal) { create(:deploy_key) }
+ let(:deploy_key_actual) { create(:deploy_key) }
let!(:deploy_key_public) { create(:deploy_key, public: true) }
let!(:deploy_keys_project_internal) do
@@ -63,4 +59,145 @@ describe Projects::DeployKeysController do
end
end
end
+
+ describe '/enable/:id' do
+ let(:deploy_key) { create(:deploy_key) }
+ let(:project2) { create(:project) }
+ let!(:deploy_keys_project_internal) do
+ create(:deploy_keys_project, project: project2, deploy_key: deploy_key)
+ end
+
+ context 'with anonymous user' do
+ before do
+ sign_out(:user)
+ end
+
+ it 'redirects to login' do
+ expect do
+ put :enable, id: deploy_key.id, namespace_id: project.namespace, project_id: project
+ end.not_to change { DeployKeysProject.count }
+
+ expect(response).to have_http_status(302)
+ expect(response).to redirect_to(new_user_session_path)
+ end
+ end
+
+ context 'with user with no permission' do
+ before do
+ sign_in(create(:user))
+ end
+
+ it 'returns 404' do
+ expect do
+ put :enable, id: deploy_key.id, namespace_id: project.namespace, project_id: project
+ end.not_to change { DeployKeysProject.count }
+
+ expect(response).to have_http_status(404)
+ end
+ end
+
+ context 'with user with permission' do
+ before do
+ project2.add_maintainer(user)
+ end
+
+ it 'returns 302' do
+ expect do
+ put :enable, id: deploy_key.id, namespace_id: project.namespace, project_id: project
+ end.to change { DeployKeysProject.count }.by(1)
+
+ expect(DeployKeysProject.where(project_id: project.id, deploy_key_id: deploy_key.id).count).to eq(1)
+ expect(response).to have_http_status(302)
+ expect(response).to redirect_to(namespace_project_settings_repository_path(anchor: 'js-deploy-keys-settings'))
+ end
+
+ it 'returns 404' do
+ put :enable, id: 0, namespace_id: project.namespace, project_id: project
+
+ expect(response).to have_http_status(404)
+ end
+ end
+
+ context 'with admin' do
+ before do
+ sign_in(create(:admin))
+ end
+
+ it 'returns 302' do
+ expect do
+ put :enable, id: deploy_key.id, namespace_id: project.namespace, project_id: project
+ end.to change { DeployKeysProject.count }.by(1)
+
+ expect(DeployKeysProject.where(project_id: project.id, deploy_key_id: deploy_key.id).count).to eq(1)
+ expect(response).to have_http_status(302)
+ expect(response).to redirect_to(namespace_project_settings_repository_path(anchor: 'js-deploy-keys-settings'))
+ end
+ end
+ end
+
+ describe '/disable/:id' do
+ let(:deploy_key) { create(:deploy_key) }
+ let!(:deploy_key_project) { create(:deploy_keys_project, project: project, deploy_key: deploy_key) }
+
+ context 'with anonymous user' do
+ before do
+ sign_out(:user)
+ end
+
+ it 'redirects to login' do
+ put :disable, id: deploy_key.id, namespace_id: project.namespace, project_id: project
+
+ expect(response).to have_http_status(302)
+ expect(response).to redirect_to(new_user_session_path)
+ expect(DeployKey.find(deploy_key.id)).to eq(deploy_key)
+ end
+ end
+
+ context 'with user with no permission' do
+ before do
+ sign_in(create(:user))
+ end
+
+ it 'returns 404' do
+ put :disable, id: deploy_key.id, namespace_id: project.namespace, project_id: project
+
+ expect(response).to have_http_status(404)
+ expect(DeployKey.find(deploy_key.id)).to eq(deploy_key)
+ end
+ end
+
+ context 'with user with permission' do
+ it 'returns 302' do
+ put :disable, id: deploy_key.id, namespace_id: project.namespace, project_id: project
+
+ expect(response).to have_http_status(302)
+ expect(response).to redirect_to(namespace_project_settings_repository_path(anchor: 'js-deploy-keys-settings'))
+
+ expect { DeployKey.find(deploy_key.id) }.to raise_error(ActiveRecord::RecordNotFound)
+ end
+
+ it 'returns 404' do
+ put :disable, id: 0, namespace_id: project.namespace, project_id: project
+
+ expect(response).to have_http_status(404)
+ end
+ end
+
+ context 'with admin' do
+ before do
+ sign_in(create(:admin))
+ end
+
+ it 'returns 302' do
+ expect do
+ put :disable, id: deploy_key.id, namespace_id: project.namespace, project_id: project
+ end.to change { DeployKey.count }.by(-1)
+
+ expect(response).to have_http_status(302)
+ expect(response).to redirect_to(namespace_project_settings_repository_path(anchor: 'js-deploy-keys-settings'))
+
+ expect { DeployKey.find(deploy_key.id) }.to raise_error(ActiveRecord::RecordNotFound)
+ end
+ end
+ end
end
diff --git a/spec/controllers/root_controller_spec.rb b/spec/controllers/root_controller_spec.rb
index 7688538a468..995f803d757 100644
--- a/spec/controllers/root_controller_spec.rb
+++ b/spec/controllers/root_controller_spec.rb
@@ -98,7 +98,7 @@ describe RootController do
it 'redirects to their assigned issues' do
get :index
- expect(response).to redirect_to issues_dashboard_path(assignee_id: user.id)
+ expect(response).to redirect_to issues_dashboard_path(assignee_username: user.username)
end
end
@@ -110,7 +110,7 @@ describe RootController do
it 'redirects to their assigned merge requests' do
get :index
- expect(response).to redirect_to merge_requests_dashboard_path(assignee_id: user.id)
+ expect(response).to redirect_to merge_requests_dashboard_path(assignee_username: user.username)
end
end
diff --git a/spec/factories/clusters/kubernetes_namespaces.rb b/spec/factories/clusters/kubernetes_namespaces.rb
index 3a4f5193550..6ad93fb0f45 100644
--- a/spec/factories/clusters/kubernetes_namespaces.rb
+++ b/spec/factories/clusters/kubernetes_namespaces.rb
@@ -3,7 +3,6 @@
FactoryBot.define do
factory :cluster_kubernetes_namespace, class: Clusters::KubernetesNamespace do
association :cluster, :project, :provided_by_gcp
- namespace { |n| "environment#{n}" }
after(:build) do |kubernetes_namespace|
cluster_project = kubernetes_namespace.cluster.cluster_project
diff --git a/spec/features/admin/admin_users_spec.rb b/spec/features/admin/admin_users_spec.rb
index d32f33ca1e2..f7c7a257075 100644
--- a/spec/features/admin/admin_users_spec.rb
+++ b/spec/features/admin/admin_users_spec.rb
@@ -130,7 +130,7 @@ describe "Admin::Users" do
context 'with regex to match internal user email address set', :js do
before do
stub_application_setting(user_default_external: true)
- stub_application_setting(user_default_internal_regex: '.internal@')
+ stub_application_setting(user_default_internal_regex: '\.internal@')
visit new_admin_user_path
end
@@ -169,6 +169,22 @@ describe "Admin::Users" do
expects_warning_to_be_hidden
end
+
+ it 'creates an internal user' do
+ user_name = 'tester1'
+ fill_in 'user_email', with: 'test.internal@domain.ch'
+ fill_in 'user_name', with: 'tester1 name'
+ fill_in 'user_username', with: user_name
+
+ expects_external_to_be_unchecked
+ expects_warning_to_be_shown
+
+ click_button 'Create user'
+
+ new_user = User.find_by(username: user_name)
+
+ expect(new_user.external).to be_falsy
+ end
end
end
end
diff --git a/spec/features/atom/dashboard_issues_spec.rb b/spec/features/atom/dashboard_issues_spec.rb
index bd4c00d97b1..5fa1a26f1a6 100644
--- a/spec/features/atom/dashboard_issues_spec.rb
+++ b/spec/features/atom/dashboard_issues_spec.rb
@@ -25,35 +25,35 @@ describe "Dashboard Issues Feed" do
it "renders atom feed via personal access token" do
personal_access_token = create(:personal_access_token, user: user)
- visit issues_dashboard_path(:atom, private_token: personal_access_token.token, assignee_id: user.id)
+ visit issues_dashboard_path(:atom, private_token: personal_access_token.token, assignee_username: user.username)
expect(response_headers['Content-Type']).to have_content('application/atom+xml')
expect(body).to have_selector('title', text: "#{user.name} issues")
end
it "renders atom feed via feed token" do
- visit issues_dashboard_path(:atom, feed_token: user.feed_token, assignee_id: user.id)
+ visit issues_dashboard_path(:atom, feed_token: user.feed_token, assignee_username: user.username)
expect(response_headers['Content-Type']).to have_content('application/atom+xml')
expect(body).to have_selector('title', text: "#{user.name} issues")
end
it "renders atom feed with url parameters" do
- visit issues_dashboard_path(:atom, feed_token: user.feed_token, state: 'opened', assignee_id: user.id)
+ visit issues_dashboard_path(:atom, feed_token: user.feed_token, state: 'opened', assignee_username: user.username)
link = find('link[type="application/atom+xml"]')
params = CGI.parse(URI.parse(link[:href]).query)
expect(params).to include('feed_token' => [user.feed_token])
expect(params).to include('state' => ['opened'])
- expect(params).to include('assignee_id' => [user.id.to_s])
+ expect(params).to include('assignee_username' => [user.username.to_s])
end
context "issue with basic fields" do
let!(:issue2) { create(:issue, author: user, assignees: [assignee], project: project2, description: 'test desc') }
it "renders issue fields" do
- visit issues_dashboard_path(:atom, feed_token: user.feed_token, assignee_id: assignee.id)
+ visit issues_dashboard_path(:atom, feed_token: user.feed_token, assignee_username: assignee.username)
entry = find(:xpath, "//feed/entry[contains(summary/text(),'#{issue2.title}')]")
@@ -76,7 +76,7 @@ describe "Dashboard Issues Feed" do
end
it "renders issue label and milestone info" do
- visit issues_dashboard_path(:atom, feed_token: user.feed_token, assignee_id: assignee.id)
+ visit issues_dashboard_path(:atom, feed_token: user.feed_token, assignee_username: assignee.username)
entry = find(:xpath, "//feed/entry[contains(summary/text(),'#{issue1.title}')]")
diff --git a/spec/features/calendar_spec.rb b/spec/features/calendar_spec.rb
index a1f93bd3fbd..8cb9b57a049 100644
--- a/spec/features/calendar_spec.rb
+++ b/spec/features/calendar_spec.rb
@@ -64,7 +64,7 @@ describe 'Contributions Calendar', :js do
end
def selected_day_activities(visible: true)
- find('.tab-pane#activity .user-calendar-activities', visible: visible).text
+ find('#js-overview .user-calendar-activities', visible: visible).text
end
before do
@@ -74,16 +74,16 @@ describe 'Contributions Calendar', :js do
describe 'calendar day selection' do
before do
visit user.username
- page.find('.js-activity-tab a').click
+ page.find('.js-overview-tab a').click
wait_for_requests
end
it 'displays calendar' do
- expect(find('.tab-pane#activity')).to have_css('.js-contrib-calendar')
+ expect(find('#js-overview')).to have_css('.js-contrib-calendar')
end
describe 'select calendar day' do
- let(:cells) { page.all('.tab-pane#activity .user-contrib-cell') }
+ let(:cells) { page.all('#js-overview .user-contrib-cell') }
before do
cells[0].click
@@ -109,7 +109,7 @@ describe 'Contributions Calendar', :js do
describe 'deselect calendar day' do
before do
cells[0].click
- page.find('.js-activity-tab a').click
+ page.find('.js-overview-tab a').click
wait_for_requests
end
@@ -124,7 +124,7 @@ describe 'Contributions Calendar', :js do
shared_context 'visit user page' do
before do
visit user.username
- page.find('.js-activity-tab a').click
+ page.find('.js-overview-tab a').click
wait_for_requests
end
end
@@ -133,12 +133,12 @@ describe 'Contributions Calendar', :js do
include_context 'visit user page'
it 'displays calendar activity square color for 1 contribution' do
- expect(find('.tab-pane#activity')).to have_selector(get_cell_color_selector(contribution_count), count: 1)
+ expect(find('#js-overview')).to have_selector(get_cell_color_selector(contribution_count), count: 1)
end
it 'displays calendar activity square on the correct date' do
today = Date.today.strftime(date_format)
- expect(find('.tab-pane#activity')).to have_selector(get_cell_date_selector(contribution_count, today), count: 1)
+ expect(find('#js-overview')).to have_selector(get_cell_date_selector(contribution_count, today), count: 1)
end
end
@@ -153,7 +153,7 @@ describe 'Contributions Calendar', :js do
include_context 'visit user page'
it 'displays calendar activity log' do
- expect(find('.tab-pane#activity .content_list .event-target-title')).to have_content issue_title
+ expect(find('#js-overview .overview-content-list .event-target-title')).to have_content issue_title
end
end
end
@@ -185,17 +185,17 @@ describe 'Contributions Calendar', :js do
include_context 'visit user page'
it 'displays calendar activity squares for both days' do
- expect(find('.tab-pane#activity')).to have_selector(get_cell_color_selector(1), count: 2)
+ expect(find('#js-overview')).to have_selector(get_cell_color_selector(1), count: 2)
end
it 'displays calendar activity square for yesterday' do
yesterday = Date.yesterday.strftime(date_format)
- expect(find('.tab-pane#activity')).to have_selector(get_cell_date_selector(1, yesterday), count: 1)
+ expect(find('#js-overview')).to have_selector(get_cell_date_selector(1, yesterday), count: 1)
end
it 'displays calendar activity square for today' do
today = Date.today.strftime(date_format)
- expect(find('.tab-pane#activity')).to have_selector(get_cell_date_selector(1, today), count: 1)
+ expect(find('#js-overview')).to have_selector(get_cell_date_selector(1, today), count: 1)
end
end
end
diff --git a/spec/features/dashboard/issuables_counter_spec.rb b/spec/features/dashboard/issuables_counter_spec.rb
index b431f72fcc9..fbc2e5cc3d3 100644
--- a/spec/features/dashboard/issuables_counter_spec.rb
+++ b/spec/features/dashboard/issuables_counter_spec.rb
@@ -45,11 +45,11 @@ describe 'Navigation bar counter', :use_clean_rails_memory_store_caching do
end
def issues_path
- issues_dashboard_path(assignee_id: user.id)
+ issues_dashboard_path(assignee_username: user.username)
end
def merge_requests_path
- merge_requests_dashboard_path(assignee_id: user.id)
+ merge_requests_dashboard_path(assignee_username: user.username)
end
def expect_counters(issuable_type, count)
diff --git a/spec/features/dashboard/issues_filter_spec.rb b/spec/features/dashboard/issues_filter_spec.rb
index 95e2610dd4a..c0434f767bb 100644
--- a/spec/features/dashboard/issues_filter_spec.rb
+++ b/spec/features/dashboard/issues_filter_spec.rb
@@ -2,6 +2,7 @@ require 'spec_helper'
describe 'Dashboard Issues filtering', :js do
include Spec::Support::Helpers::Features::SortingHelpers
+ include FilteredSearchHelpers
let(:user) { create(:user) }
let(:project) { create(:project) }
@@ -25,27 +26,21 @@ describe 'Dashboard Issues filtering', :js do
context 'filtering by milestone' do
it 'shows all issues with no milestone' do
- show_milestone_dropdown
-
- click_link 'No Milestone'
+ input_filtered_search("milestone:none")
expect(page).to have_issuable_counts(open: 1, closed: 0, all: 1)
expect(page).to have_selector('.issue', count: 1)
end
it 'shows all issues with the selected milestone' do
- show_milestone_dropdown
-
- page.within '.dropdown-content' do
- click_link milestone.title
- end
+ input_filtered_search("milestone:%\"#{milestone.title}\"")
expect(page).to have_issuable_counts(open: 1, closed: 0, all: 1)
expect(page).to have_selector('.issue', count: 1)
end
it 'updates atom feed link' do
- visit_issues(milestone_title: '', assignee_id: user.id)
+ visit_issues(milestone_title: '', assignee_username: user.username)
link = find('.nav-controls a[title="Subscribe to RSS feed"]')
params = CGI.parse(URI.parse(link[:href]).query)
@@ -54,10 +49,10 @@ describe 'Dashboard Issues filtering', :js do
expect(params).to include('feed_token' => [user.feed_token])
expect(params).to include('milestone_title' => [''])
- expect(params).to include('assignee_id' => [user.id.to_s])
+ expect(params).to include('assignee_username' => [user.username.to_s])
expect(auto_discovery_params).to include('feed_token' => [user.feed_token])
expect(auto_discovery_params).to include('milestone_title' => [''])
- expect(auto_discovery_params).to include('assignee_id' => [user.id.to_s])
+ expect(auto_discovery_params).to include('assignee_username' => [user.username.to_s])
end
end
@@ -66,10 +61,7 @@ describe 'Dashboard Issues filtering', :js do
let!(:label_link) { create(:label_link, label: label, target: issue) }
it 'shows all issues with the selected label' do
- page.within '.labels-filter' do
- find('.dropdown').click
- click_link label.title
- end
+ input_filtered_search("label:~#{label.title}")
page.within 'ul.content-list' do
expect(page).to have_content issue.title
@@ -80,12 +72,12 @@ describe 'Dashboard Issues filtering', :js do
context 'sorting' do
before do
- visit_issues(assignee_id: user.id)
+ visit_issues(assignee_username: user.username)
end
it 'remembers last sorting value' do
sort_by('Created date')
- visit_issues(assignee_id: user.id)
+ visit_issues(assignee_username: user.username)
expect(find('.issues-filters')).to have_content('Created date')
end
@@ -98,11 +90,6 @@ describe 'Dashboard Issues filtering', :js do
end
end
- def show_milestone_dropdown
- click_button 'Milestone'
- expect(page).to have_selector('.dropdown-content', visible: true)
- end
-
def visit_issues(*args)
visit issues_dashboard_path(*args)
end
diff --git a/spec/features/dashboard/issues_spec.rb b/spec/features/dashboard/issues_spec.rb
index 4ae062f242a..9957bec0f0b 100644
--- a/spec/features/dashboard/issues_spec.rb
+++ b/spec/features/dashboard/issues_spec.rb
@@ -1,6 +1,8 @@
require 'spec_helper'
RSpec.describe 'Dashboard Issues' do
+ include FilteredSearchHelpers
+
let(:current_user) { create :user }
let(:user) { current_user } # Shared examples depend on this being available
let!(:public_project) { create(:project, :public) }
@@ -14,7 +16,7 @@ RSpec.describe 'Dashboard Issues' do
before do
[project, project_with_issues_disabled].each { |project| project.add_maintainer(current_user) }
sign_in(current_user)
- visit issues_dashboard_path(assignee_id: current_user.id)
+ visit issues_dashboard_path(assignee_username: current_user.username)
end
describe 'issues' do
@@ -24,26 +26,9 @@ RSpec.describe 'Dashboard Issues' do
expect(page).not_to have_content(other_issue.title)
end
- it 'shows checkmark when unassigned is selected for assignee', :js do
- find('.js-assignee-search').click
- find('li', text: 'Unassigned').click
- find('.js-assignee-search').click
-
- expect(find('li[data-user-id="0"] a.is-active')).to be_visible
- end
-
it 'shows issues when current user is author', :js do
- execute_script("document.querySelector('#assignee_id').value=''")
- find('.js-author-search', match: :first).click
-
- expect(find('li[data-user-id="null"] a.is-active')).to be_visible
-
- find('.dropdown-menu-author li a', match: :first, text: current_user.to_reference).click
- find('.js-author-search', match: :first).click
-
- page.within '.dropdown-menu-user' do
- expect(find('.dropdown-menu-author li a.is-active', match: :first, text: current_user.to_reference)).to be_visible
- end
+ reset_filters
+ input_filtered_search("author:#{current_user.to_reference}")
expect(page).to have_content(authored_issue.title)
expect(page).to have_content(authored_issue_on_public_project.title)
@@ -53,7 +38,7 @@ RSpec.describe 'Dashboard Issues' do
it 'state filter tabs work' do
find('#state-closed').click
- expect(page).to have_current_path(issues_dashboard_url(assignee_id: current_user.id, state: 'closed'), url: true)
+ expect(page).to have_current_path(issues_dashboard_url(assignee_username: current_user.username, state: 'closed'), url: true)
end
it_behaves_like "it has an RSS button with current_user's feed token"
diff --git a/spec/features/dashboard/label_filter_spec.rb b/spec/features/dashboard/label_filter_spec.rb
index 6802974c2ee..2d4659d380f 100644
--- a/spec/features/dashboard/label_filter_spec.rb
+++ b/spec/features/dashboard/label_filter_spec.rb
@@ -1,6 +1,11 @@
require 'spec_helper'
describe 'Dashboard > label filter', :js do
+ include FilteredSearchHelpers
+
+ let(:filtered_search) { find('.filtered-search') }
+ let(:filter_dropdown) { find("#js-dropdown-label .filter-dropdown") }
+
let(:user) { create(:user) }
let(:project) { create(:project, name: 'test', namespace: user.namespace) }
let(:project2) { create(:project, name: 'test2', path: 'test2', namespace: user.namespace) }
@@ -13,17 +18,15 @@ describe 'Dashboard > label filter', :js do
sign_in(user)
visit issues_dashboard_path
+
+ init_label_search
end
context 'duplicate labels' do
it 'removes duplicate labels' do
- page.within('.labels-filter') do
- click_button 'Label'
- end
+ filtered_search.send_keys('bu')
- page.within('.dropdown-menu-labels') do
- expect(page).to have_selector('.dropdown-content a', text: 'bug', count: 1)
- end
+ expect(filter_dropdown).to have_selector('.filter-dropdown-item', text: 'bug', count: 1)
end
end
end
diff --git a/spec/features/dashboard/merge_requests_spec.rb b/spec/features/dashboard/merge_requests_spec.rb
index f51142f5790..282bf542e77 100644
--- a/spec/features/dashboard/merge_requests_spec.rb
+++ b/spec/features/dashboard/merge_requests_spec.rb
@@ -2,7 +2,7 @@ require 'spec_helper'
describe 'Dashboard Merge Requests' do
include Spec::Support::Helpers::Features::SortingHelpers
- include FilterItemSelectHelper
+ include FilteredSearchHelpers
include ProjectForksHelper
let(:current_user) { create :user }
@@ -36,7 +36,7 @@ describe 'Dashboard Merge Requests' do
context 'no merge requests exist' do
it 'shows an empty state' do
- visit merge_requests_dashboard_path(assignee_id: current_user.id)
+ visit merge_requests_dashboard_path(assignee_username: current_user.username)
expect(page).to have_selector('.empty-state')
end
@@ -79,7 +79,7 @@ describe 'Dashboard Merge Requests' do
end
before do
- visit merge_requests_dashboard_path(assignee_id: current_user.id)
+ visit merge_requests_dashboard_path(assignee_username: current_user.username)
end
it 'shows assigned merge requests' do
@@ -92,8 +92,8 @@ describe 'Dashboard Merge Requests' do
end
it 'shows authored merge requests', :js do
- filter_item_select('Any Assignee', '.js-assignee-search')
- filter_item_select(current_user.to_reference, '.js-author-search')
+ reset_filters
+ input_filtered_search("author:#{current_user.to_reference}")
expect(page).to have_content(authored_merge_request.title)
expect(page).to have_content(authored_merge_request_from_fork.title)
@@ -104,8 +104,7 @@ describe 'Dashboard Merge Requests' do
end
it 'shows error message without filter', :js do
- filter_item_select('Any Assignee', '.js-assignee-search')
- filter_item_select('Any Author', '.js-author-search')
+ reset_filters
expect(page).to have_content('Please select at least one filter to see results')
end
@@ -113,7 +112,7 @@ describe 'Dashboard Merge Requests' do
it 'shows sorted merge requests' do
sort_by('Created date')
- visit merge_requests_dashboard_path(assignee_id: current_user.id)
+ visit merge_requests_dashboard_path(assignee_username: current_user.username)
expect(find('.issues-filters')).to have_content('Created date')
end
diff --git a/spec/features/dashboard/milestone_filter_spec.rb b/spec/features/dashboard/milestone_filter_spec.rb
deleted file mode 100644
index 00373050aeb..00000000000
--- a/spec/features/dashboard/milestone_filter_spec.rb
+++ /dev/null
@@ -1,77 +0,0 @@
-require 'spec_helper'
-
-describe 'Dashboard > milestone filter', :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!(:issue) { create :issue, author: user, project: project, milestone: milestone }
- let!(:issue2) { create :issue, author: user, project: project, milestone: milestone2 }
-
- dropdown_toggle_button = '.js-milestone-select'
-
- before do
- sign_in(user)
- end
-
- context 'default state' do
- it 'shows issues with Any Milestone' do
- visit issues_dashboard_path(author_id: user.id)
-
- page.all('.issue-info').each do |issue_info|
- expect(issue_info.text).to match(/v\d.0/)
- end
- end
- end
-
- context 'filtering by milestone' do
- before do
- visit issues_dashboard_path(author_id: user.id)
- filter_item_select('v1.0', dropdown_toggle_button)
- find(dropdown_toggle_button).click
- wait_for_requests
- end
-
- it 'shows issues with Milestone v1.0' do
- expect(find('.issues-list')).to have_selector('.issue', count: 1)
- expect(find('.milestone-filter .dropdown-content')).to have_selector('a.is-active', count: 1)
- end
-
- it 'should not change active Milestone unless clicked' do
- page.within '.milestone-filter' do
- expect(find('.dropdown-content')).to have_selector('a.is-active', count: 1)
-
- find('.dropdown-menu-close').click
-
- expect(page).not_to have_selector('.dropdown.open')
-
- find(dropdown_toggle_button).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')
- end
- end
- end
-
- context 'with milestone filter in URL' do
- before do
- visit issues_dashboard_path(author_id: user.id, milestone_title: milestone.title)
- find(dropdown_toggle_button).click
- wait_for_requests
- end
-
- it 'has milestone selected' do
- expect(find('.milestone-filter .dropdown-content')).to have_css('.is-active', text: milestone.title)
- end
-
- it 'removes milestone filter from URL after clicking "Any Milestone"' do
- expect(current_url).to include("milestone_title=#{milestone.title}")
-
- find('.milestone-filter .dropdown-content li', text: 'Any Milestone').click
-
- expect(current_url).not_to include('milestone_title')
- end
- end
-end
diff --git a/spec/features/issues/filtered_search/dropdown_emoji_spec.rb b/spec/features/issues/filtered_search/dropdown_emoji_spec.rb
index c42fcd92a36..97dd0afd002 100644
--- a/spec/features/issues/filtered_search/dropdown_emoji_spec.rb
+++ b/spec/features/issues/filtered_search/dropdown_emoji_spec.rb
@@ -20,7 +20,7 @@ describe 'Dropdown emoji', :js do
end
def dropdown_emoji_size
- page.all('#js-dropdown-my-reaction .filter-dropdown .filter-dropdown-item').size
+ all('gl-emoji[data-name]').size
end
def click_emoji(text)
diff --git a/spec/features/issues/gfm_autocomplete_spec.rb b/spec/features/issues/gfm_autocomplete_spec.rb
index 605860b90cd..7c591dacce5 100644
--- a/spec/features/issues/gfm_autocomplete_spec.rb
+++ b/spec/features/issues/gfm_autocomplete_spec.rb
@@ -1,6 +1,10 @@
require 'rails_helper'
describe 'GFM autocomplete', :js do
+ let(:issue_xss_title) { 'This will execute alert<img src=x onerror=alert(2)&lt;img src=x onerror=alert(1)&gt;' }
+ let(:user_xss_title) { 'eve <img src=x onerror=alert(2)&lt;img src=x onerror=alert(1)&gt;' }
+
+ let(:user_xss) { create(:user, name: user_xss_title, username: 'xss.user') }
let(:user) { create(:user, name: '💃speciąl someone💃', username: 'someone.special') }
let(:project) { create(:project) }
let(:label) { create(:label, project: project, title: 'special+') }
@@ -9,6 +13,8 @@ describe 'GFM autocomplete', :js do
before do
project.add_maintainer(user)
+ project.add_maintainer(user_xss)
+
sign_in(user)
visit project_issue_path(project, issue)
@@ -35,9 +41,8 @@ describe 'GFM autocomplete', :js do
expect(page).to have_selector('.atwho-container')
end
- it 'opens autocomplete menu when field starts with text with item escaping HTML characters' do
- alert_title = 'This will execute alert<img src=x onerror=alert(2)&lt;img src=x onerror=alert(1)&gt;'
- create(:issue, project: project, title: alert_title)
+ it 'opens autocomplete menu for Issues when field starts with text with item escaping HTML characters' do
+ create(:issue, project: project, title: issue_xss_title)
page.within '.timeline-content-form' do
find('#note-body').native.send_keys('#')
@@ -46,7 +51,19 @@ describe 'GFM autocomplete', :js do
expect(page).to have_selector('.atwho-container')
page.within '.atwho-container #at-view-issues' do
- expect(page.all('li').first.text).to include(alert_title)
+ expect(page.all('li').first.text).to include(issue_xss_title)
+ end
+ end
+
+ it 'opens autocomplete menu for Username when field starts with text with item escaping HTML characters' do
+ page.within '.timeline-content-form' do
+ find('#note-body').native.send_keys('@ev')
+ end
+
+ expect(page).to have_selector('.atwho-container')
+
+ page.within '.atwho-container #at-view-users' do
+ expect(find('li').text).to have_content(user_xss.username)
end
end
@@ -107,7 +124,7 @@ describe 'GFM autocomplete', :js do
wait_for_requests
- expect(find('#at-view-64')).to have_selector('.cur:first-of-type')
+ expect(find('#at-view-users')).to have_selector('.cur:first-of-type')
end
it 'includes items for assignee dropdowns with non-ASCII characters in name' do
@@ -120,7 +137,7 @@ describe 'GFM autocomplete', :js do
wait_for_requests
- expect(find('#at-view-64')).to have_content(user.name)
+ expect(find('#at-view-users')).to have_content(user.name)
end
it 'selects the first item for non-assignee dropdowns if a query is entered' do
diff --git a/spec/features/issues/user_sorts_issues_spec.rb b/spec/features/issues/user_sorts_issues_spec.rb
index 7d261ec7dae..4771d2c6d28 100644
--- a/spec/features/issues/user_sorts_issues_spec.rb
+++ b/spec/features/issues/user_sorts_issues_spec.rb
@@ -26,7 +26,7 @@ describe "User sorts issues" do
click_link('Milestone')
end
- visit(issues_dashboard_path(assignee_id: user.id))
+ visit(issues_dashboard_path(assignee_username: user.username))
expect(find('.issues-filters a.is-active')).to have_content('Milestone')
diff --git a/spec/features/merge_requests/user_sorts_merge_requests_spec.rb b/spec/features/merge_requests/user_sorts_merge_requests_spec.rb
index 82cfe600d52..e163868e8e7 100644
--- a/spec/features/merge_requests/user_sorts_merge_requests_spec.rb
+++ b/spec/features/merge_requests/user_sorts_merge_requests_spec.rb
@@ -25,7 +25,7 @@ describe 'User sorts merge requests' do
click_link('Milestone')
end
- visit(merge_requests_dashboard_path(assignee_id: user.id))
+ visit(merge_requests_dashboard_path(assignee_username: user.username))
expect(find('.issues-filters a.is-active')).to have_content('Milestone')
@@ -41,7 +41,7 @@ describe 'User sorts merge requests' do
it 'fallbacks to issuable_sort cookie key when remembering the sorting option' do
set_cookie('issuable_sort', 'milestone')
- visit(merge_requests_dashboard_path(assignee_id: user.id))
+ visit(merge_requests_dashboard_path(assignee_username: user.username))
expect(find('.issues-filters a.is-active')).to have_content('Milestone')
end
diff --git a/spec/features/projects/wiki/user_updates_wiki_page_spec.rb b/spec/features/projects/wiki/user_updates_wiki_page_spec.rb
index 2ce5ee0e87d..7ad7fec922a 100644
--- a/spec/features/projects/wiki/user_updates_wiki_page_spec.rb
+++ b/spec/features/projects/wiki/user_updates_wiki_page_spec.rb
@@ -1,233 +1,223 @@
require 'spec_helper'
describe 'User updates wiki page' do
- shared_examples 'wiki page user update' do
- let(:user) { create(:user) }
+ let(:user) { create(:user) }
+ before do
+ project.add_maintainer(user)
+ sign_in(user)
+ end
+
+ context 'when wiki is empty' do
before do
- project.add_maintainer(user)
- sign_in(user)
+ visit(project_wikis_path(project))
+ click_link "Create your first page"
end
- context 'when wiki is empty' do
- before do
- visit(project_wikis_path(project))
- click_link "Create your first page"
- end
-
- context 'in a user namespace' do
- let(:project) { create(:project, :wiki_repo, namespace: user.namespace) }
+ context 'in a user namespace' do
+ let(:project) { create(:project, :wiki_repo) }
- it 'redirects back to the home edit page' do
- page.within(:css, '.wiki-form .form-actions') do
- click_on('Cancel')
- end
-
- expect(current_path).to eq project_wiki_path(project, :home)
+ it 'redirects back to the home edit page' do
+ page.within(:css, '.wiki-form .form-actions') do
+ click_on('Cancel')
end
- it 'updates a page that has a path', :js do
- click_on('New page')
+ expect(current_path).to eq project_wiki_path(project, :home)
+ end
- page.within('#modal-new-wiki') do
- fill_in(:new_wiki_path, with: 'one/two/three-test')
- click_on('Create page')
- end
+ it 'updates a page that has a path', :js do
+ click_on('New page')
- page.within '.wiki-form' do
- fill_in(:wiki_content, with: 'wiki content')
- click_on('Create page')
- end
+ page.within('#modal-new-wiki') do
+ fill_in(:new_wiki_path, with: 'one/two/three-test')
+ click_on('Create page')
+ end
- expect(current_path).to include('one/two/three-test')
- expect(find('.wiki-pages')).to have_content('Three')
+ page.within '.wiki-form' do
+ fill_in(:wiki_content, with: 'wiki content')
+ click_on('Create page')
+ end
- first(:link, text: 'Three').click
+ expect(current_path).to include('one/two/three-test')
+ expect(find('.wiki-pages')).to have_content('Three')
- expect(find('.nav-text')).to have_content('Three')
+ first(:link, text: 'Three').click
- click_on('Edit')
+ expect(find('.nav-text')).to have_content('Three')
- expect(current_path).to include('one/two/three-test')
- expect(page).to have_content('Edit Page')
+ click_on('Edit')
- fill_in('Content', with: 'Updated Wiki Content')
- click_on('Save changes')
+ expect(current_path).to include('one/two/three-test')
+ expect(page).to have_content('Edit Page')
- expect(page).to have_content('Updated Wiki Content')
- end
+ fill_in('Content', with: 'Updated Wiki Content')
+ click_on('Save changes')
- it_behaves_like 'wiki file attachments'
+ expect(page).to have_content('Updated Wiki Content')
end
- end
- context 'when wiki is not empty' do
- let(:project_wiki) { create(:project_wiki, project: project, user: project.creator) }
- let!(:wiki_page) { create(:wiki_page, wiki: project_wiki, attrs: { title: 'home', content: 'Home page' }) }
+ it_behaves_like 'wiki file attachments'
+ end
+ end
- before do
- visit(project_wikis_path(project))
+ context 'when wiki is not empty' do
+ let(:project_wiki) { create(:project_wiki, project: project, user: project.creator) }
+ let!(:wiki_page) { create(:wiki_page, wiki: project_wiki, attrs: { title: 'home', content: 'Home page' }) }
- click_link('Edit')
- end
+ before do
+ visit(project_wikis_path(project))
- context 'in a user namespace' do
- let(:project) { create(:project, :wiki_repo, namespace: user.namespace) }
+ click_link('Edit')
+ end
- it 'updates a page' do
- # Commit message field should have correct value.
- expect(page).to have_field('wiki[message]', with: 'Update home')
+ context 'in a user namespace' do
+ let(:project) { create(:project, :wiki_repo) }
- fill_in(:wiki_content, with: 'My awesome wiki!')
- click_button('Save changes')
+ it 'updates a page' do
+ # Commit message field should have correct value.
+ expect(page).to have_field('wiki[message]', with: 'Update home')
- expect(page).to have_content('Home')
- expect(page).to have_content("Last edited by #{user.name}")
- expect(page).to have_content('My awesome wiki!')
- end
+ fill_in(:wiki_content, with: 'My awesome wiki!')
+ click_button('Save changes')
- it 'shows a validation error message' do
- fill_in(:wiki_content, with: '')
- click_button('Save changes')
+ expect(page).to have_content('Home')
+ expect(page).to have_content("Last edited by #{user.name}")
+ expect(page).to have_content('My awesome wiki!')
+ end
- expect(page).to have_selector('.wiki-form')
- expect(page).to have_content('Edit Page')
- expect(page).to have_content('The form contains the following error:')
- expect(page).to have_content("Content can't be blank")
- expect(find('textarea#wiki_content').value).to eq('')
- end
+ it 'shows a validation error message' do
+ fill_in(:wiki_content, with: '')
+ click_button('Save changes')
- it 'shows the emoji autocompletion dropdown', :js do
- find('#wiki_content').native.send_keys('')
- fill_in(:wiki_content, with: ':')
+ expect(page).to have_selector('.wiki-form')
+ expect(page).to have_content('Edit Page')
+ expect(page).to have_content('The form contains the following error:')
+ expect(page).to have_content("Content can't be blank")
+ expect(find('textarea#wiki_content').value).to eq('')
+ end
- expect(page).to have_selector('.atwho-view')
- end
+ it 'shows the emoji autocompletion dropdown', :js do
+ find('#wiki_content').native.send_keys('')
+ fill_in(:wiki_content, with: ':')
- it 'shows the error message' do
- wiki_page.update(content: 'Update')
+ expect(page).to have_selector('.atwho-view')
+ end
- click_button('Save changes')
+ it 'shows the error message' do
+ wiki_page.update(content: 'Update')
- expect(page).to have_content('Someone edited the page the same time you did.')
- end
+ click_button('Save changes')
- it 'updates a page' do
- fill_in('Content', with: 'Updated Wiki Content')
- click_on('Save changes')
+ expect(page).to have_content('Someone edited the page the same time you did.')
+ end
- expect(page).to have_content('Updated Wiki Content')
- end
+ it 'updates a page' do
+ fill_in('Content', with: 'Updated Wiki Content')
+ click_on('Save changes')
- it 'cancels editing of a page' do
- page.within(:css, '.wiki-form .form-actions') do
- click_on('Cancel')
- end
+ expect(page).to have_content('Updated Wiki Content')
+ end
- expect(current_path).to eq(project_wiki_path(project, wiki_page))
+ it 'cancels editing of a page' do
+ page.within(:css, '.wiki-form .form-actions') do
+ click_on('Cancel')
end
- it_behaves_like 'wiki file attachments'
+ expect(current_path).to eq(project_wiki_path(project, wiki_page))
end
- context 'in a group namespace' do
- let(:project) { create(:project, :wiki_repo, namespace: create(:group, :public)) }
+ it_behaves_like 'wiki file attachments'
+ end
- it 'updates a page' do
- # Commit message field should have correct value.
- expect(page).to have_field('wiki[message]', with: 'Update home')
+ context 'in a group namespace' do
+ let(:project) { create(:project, :wiki_repo, namespace: create(:group, :public)) }
- fill_in(:wiki_content, with: 'My awesome wiki!')
+ it 'updates a page' do
+ # Commit message field should have correct value.
+ expect(page).to have_field('wiki[message]', with: 'Update home')
- click_button('Save changes')
+ fill_in(:wiki_content, with: 'My awesome wiki!')
- expect(page).to have_content('Home')
- expect(page).to have_content("Last edited by #{user.name}")
- expect(page).to have_content('My awesome wiki!')
- end
+ click_button('Save changes')
- it_behaves_like 'wiki file attachments'
+ expect(page).to have_content('Home')
+ expect(page).to have_content("Last edited by #{user.name}")
+ expect(page).to have_content('My awesome wiki!')
end
- end
- context 'when the page is in a subdir' do
- let!(:project) { create(:project, :wiki_repo, namespace: user.namespace) }
- let(:project_wiki) { create(:project_wiki, project: project, user: project.creator) }
- let(:page_name) { 'page_name' }
- let(:page_dir) { "foo/bar/#{page_name}" }
- let!(:wiki_page) { create(:wiki_page, wiki: project_wiki, attrs: { title: page_dir, content: 'Home page' }) }
+ it_behaves_like 'wiki file attachments'
+ end
+ end
- before do
- visit(project_wiki_edit_path(project, wiki_page))
- end
+ context 'when the page is in a subdir' do
+ let!(:project) { create(:project, :wiki_repo) }
+ let(:project_wiki) { create(:project_wiki, project: project, user: project.creator) }
+ let(:page_name) { 'page_name' }
+ let(:page_dir) { "foo/bar/#{page_name}" }
+ let!(:wiki_page) { create(:wiki_page, wiki: project_wiki, attrs: { title: page_dir, content: 'Home page' }) }
- it 'moves the page to the root folder', :skip_gitaly_mock do
- fill_in(:wiki_title, with: "/#{page_name}")
+ before do
+ visit(project_wiki_edit_path(project, wiki_page))
+ end
- click_button('Save changes')
+ it 'moves the page to the root folder' do
+ fill_in(:wiki_title, with: "/#{page_name}")
- expect(current_path).to eq(project_wiki_path(project, page_name))
- end
+ click_button('Save changes')
- it 'moves the page to other dir' do
- new_page_dir = "foo1/bar1/#{page_name}"
+ expect(current_path).to eq(project_wiki_path(project, page_name))
+ end
- fill_in(:wiki_title, with: new_page_dir)
+ it 'moves the page to other dir' do
+ new_page_dir = "foo1/bar1/#{page_name}"
- click_button('Save changes')
+ fill_in(:wiki_title, with: new_page_dir)
- expect(current_path).to eq(project_wiki_path(project, new_page_dir))
- end
+ click_button('Save changes')
- it 'remains in the same place if title has not changed' do
- original_path = project_wiki_path(project, wiki_page)
+ expect(current_path).to eq(project_wiki_path(project, new_page_dir))
+ end
- fill_in(:wiki_title, with: page_name)
+ it 'remains in the same place if title has not changed' do
+ original_path = project_wiki_path(project, wiki_page)
- click_button('Save changes')
+ fill_in(:wiki_title, with: page_name)
- expect(current_path).to eq(original_path)
- end
+ click_button('Save changes')
- it 'can be moved to a different dir with a different name' do
- new_page_dir = "foo1/bar1/new_page_name"
+ expect(current_path).to eq(original_path)
+ end
- fill_in(:wiki_title, with: new_page_dir)
+ it 'can be moved to a different dir with a different name' do
+ new_page_dir = "foo1/bar1/new_page_name"
- click_button('Save changes')
+ fill_in(:wiki_title, with: new_page_dir)
- expect(current_path).to eq(project_wiki_path(project, new_page_dir))
- end
+ click_button('Save changes')
- it 'can be renamed and moved to the root folder' do
- new_name = 'new_page_name'
+ expect(current_path).to eq(project_wiki_path(project, new_page_dir))
+ end
- fill_in(:wiki_title, with: "/#{new_name}")
+ it 'can be renamed and moved to the root folder' do
+ new_name = 'new_page_name'
- click_button('Save changes')
+ fill_in(:wiki_title, with: "/#{new_name}")
- expect(current_path).to eq(project_wiki_path(project, new_name))
- end
+ click_button('Save changes')
- it 'squishes the title before creating the page' do
- new_page_dir = " foo1 / bar1 / #{page_name} "
+ expect(current_path).to eq(project_wiki_path(project, new_name))
+ end
- fill_in(:wiki_title, with: new_page_dir)
+ it 'squishes the title before creating the page' do
+ new_page_dir = " foo1 / bar1 / #{page_name} "
- click_button('Save changes')
+ fill_in(:wiki_title, with: new_page_dir)
- expect(current_path).to eq(project_wiki_path(project, "foo1/bar1/#{page_name}"))
- end
+ click_button('Save changes')
- it_behaves_like 'wiki file attachments'
+ expect(current_path).to eq(project_wiki_path(project, "foo1/bar1/#{page_name}"))
end
- end
-
- context 'when Gitaly is enabled' do
- it_behaves_like 'wiki page user update'
- end
- context 'when Gitaly is disabled', :skip_gitaly_mock do
- it_behaves_like 'wiki page user update'
+ it_behaves_like 'wiki file attachments'
end
end
diff --git a/spec/features/projects/wiki/user_views_wiki_page_spec.rb b/spec/features/projects/wiki/user_views_wiki_page_spec.rb
index 4b974a3ca10..3c93d71ab00 100644
--- a/spec/features/projects/wiki/user_views_wiki_page_spec.rb
+++ b/spec/features/projects/wiki/user_views_wiki_page_spec.rb
@@ -1,174 +1,164 @@
require 'spec_helper'
describe 'User views a wiki page' do
- shared_examples 'wiki page user view' do
- include WikiHelpers
-
- let(:user) { create(:user) }
- let(:project) { create(:project, :wiki_repo, namespace: user.namespace) }
- let(:path) { 'image.png' }
- let(:wiki_page) do
- create(:wiki_page,
- wiki: project.wiki,
- attrs: { title: 'home', content: "Look at this [image](#{path})\n\n ![alt text](#{path})" })
- end
+ include WikiHelpers
+
+ let(:user) { create(:user) }
+ let(:project) { create(:project, :wiki_repo, namespace: user.namespace) }
+ let(:path) { 'image.png' }
+ let(:wiki_page) do
+ create(:wiki_page,
+ wiki: project.wiki,
+ attrs: { title: 'home', content: "Look at this [image](#{path})\n\n ![alt text](#{path})" })
+ end
- before do
- project.add_maintainer(user)
- sign_in(user)
- end
+ before do
+ project.add_maintainer(user)
+ sign_in(user)
+ end
- context 'when wiki is empty' do
- before do
- visit(project_wikis_path(project))
- click_link "Create your first page"
+ context 'when wiki is empty' do
+ before do
+ visit(project_wikis_path(project))
+ click_link "Create your first page"
- click_on('New page')
+ click_on('New page')
- page.within('#modal-new-wiki') do
- fill_in(:new_wiki_path, with: 'one/two/three-test')
- click_on('Create page')
- end
+ page.within('#modal-new-wiki') do
+ fill_in(:new_wiki_path, with: 'one/two/three-test')
+ click_on('Create page')
+ end
- page.within('.wiki-form') do
- fill_in(:wiki_content, with: 'wiki content')
- click_on('Create page')
- end
+ page.within('.wiki-form') do
+ fill_in(:wiki_content, with: 'wiki content')
+ click_on('Create page')
end
+ end
- it 'shows the history of a page that has a path', :js do
- expect(current_path).to include('one/two/three-test')
+ it 'shows the history of a page that has a path', :js do
+ expect(current_path).to include('one/two/three-test')
- first(:link, text: 'Three').click
- click_on('Page history')
+ first(:link, text: 'Three').click
+ click_on('Page history')
- expect(current_path).to include('one/two/three-test')
+ expect(current_path).to include('one/two/three-test')
- page.within(:css, '.nav-text') do
- expect(page).to have_content('History')
- end
+ page.within(:css, '.nav-text') do
+ expect(page).to have_content('History')
end
+ end
- it 'shows an old version of a page', :js do
- expect(current_path).to include('one/two/three-test')
- expect(find('.wiki-pages')).to have_content('Three')
-
- first(:link, text: 'Three').click
-
- expect(find('.nav-text')).to have_content('Three')
+ it 'shows an old version of a page', :js do
+ expect(current_path).to include('one/two/three-test')
+ expect(find('.wiki-pages')).to have_content('Three')
- click_on('Edit')
+ first(:link, text: 'Three').click
- expect(current_path).to include('one/two/three-test')
- expect(page).to have_content('Edit Page')
+ expect(find('.nav-text')).to have_content('Three')
- fill_in('Content', with: 'Updated Wiki Content')
+ click_on('Edit')
- click_on('Save changes')
- click_on('Page history')
+ expect(current_path).to include('one/two/three-test')
+ expect(page).to have_content('Edit Page')
- page.within(:css, '.nav-text') do
- expect(page).to have_content('History')
- end
+ fill_in('Content', with: 'Updated Wiki Content')
- find('a[href*="?version_id"]')
- end
- end
-
- context 'when a page does not have history' do
- before do
- visit(project_wiki_path(project, wiki_page))
- end
+ click_on('Save changes')
+ click_on('Page history')
- it 'shows all the pages' do
- expect(page).to have_content(user.name)
- expect(find('.wiki-pages')).to have_content(wiki_page.title.capitalize)
+ page.within(:css, '.nav-text') do
+ expect(page).to have_content('History')
end
- context 'shows a file stored in a page' do
- let(:path) { upload_file_to_wiki(project, user, 'dk.png') }
+ find('a[href*="?version_id"]')
+ end
+ end
- it do
- expect(page).to have_xpath("//img[@data-src='#{project.wiki.wiki_base_path}/#{path}']")
- expect(page).to have_link('image', href: "#{project.wiki.wiki_base_path}/#{path}")
+ context 'when a page does not have history' do
+ before do
+ visit(project_wiki_path(project, wiki_page))
+ end
- click_on('image')
+ it 'shows all the pages' do
+ expect(page).to have_content(user.name)
+ expect(find('.wiki-pages')).to have_content(wiki_page.title.capitalize)
+ end
- expect(current_path).to match("wikis/#{path}")
- expect(page).not_to have_xpath('/html') # Page should render the image which means there is no html involved
- end
- end
+ context 'shows a file stored in a page' do
+ let(:path) { upload_file_to_wiki(project, user, 'dk.png') }
- it 'shows the creation page if file does not exist' do
+ it do
+ expect(page).to have_xpath("//img[@data-src='#{project.wiki.wiki_base_path}/#{path}']")
expect(page).to have_link('image', href: "#{project.wiki.wiki_base_path}/#{path}")
click_on('image')
expect(current_path).to match("wikis/#{path}")
- expect(page).to have_content('New Wiki Page')
- expect(page).to have_content('Create page')
+ expect(page).not_to have_xpath('/html') # Page should render the image which means there is no html involved
end
end
- context 'when a page has history' do
- before do
- wiki_page.update(message: 'updated home', content: 'updated [some link](other-page)')
- end
+ it 'shows the creation page if file does not exist' do
+ expect(page).to have_link('image', href: "#{project.wiki.wiki_base_path}/#{path}")
- it 'shows the page history' do
- visit(project_wiki_path(project, wiki_page))
+ click_on('image')
- expect(page).to have_selector('a.btn', text: 'Edit')
+ expect(current_path).to match("wikis/#{path}")
+ expect(page).to have_content('New Wiki Page')
+ expect(page).to have_content('Create page')
+ end
+ end
- click_on('Page history')
+ context 'when a page has history' do
+ before do
+ wiki_page.update(message: 'updated home', content: 'updated [some link](other-page)')
+ end
- expect(page).to have_content(user.name)
- expect(page).to have_content("#{user.username} created page: home")
- expect(page).to have_content('updated home')
- end
+ it 'shows the page history' do
+ visit(project_wiki_path(project, wiki_page))
- it 'does not show the "Edit" button' do
- visit(project_wiki_path(project, wiki_page, version_id: wiki_page.versions.last.id))
+ expect(page).to have_selector('a.btn', text: 'Edit')
- expect(page).not_to have_selector('a.btn', text: 'Edit')
- end
+ click_on('Page history')
+
+ expect(page).to have_content(user.name)
+ expect(page).to have_content("#{user.username} created page: home")
+ expect(page).to have_content('updated home')
end
- context 'when page has invalid content encoding' do
- let(:content) { 'whatever'.force_encoding('ISO-8859-1') }
+ it 'does not show the "Edit" button' do
+ visit(project_wiki_path(project, wiki_page, version_id: wiki_page.versions.last.id))
- before do
- allow(Gitlab::EncodingHelper).to receive(:encode!).and_return(content)
+ expect(page).not_to have_selector('a.btn', text: 'Edit')
+ end
+ end
- visit(project_wiki_path(project, wiki_page))
- end
+ context 'when page has invalid content encoding' do
+ let(:content) { 'whatever'.force_encoding('ISO-8859-1') }
- it 'does not show "Edit" button' do
- expect(page).not_to have_selector('a.btn', text: 'Edit')
- end
+ before do
+ allow(Gitlab::EncodingHelper).to receive(:encode!).and_return(content)
- it 'shows error' do
- page.within(:css, '.flash-notice') do
- expect(page).to have_content('The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository.')
- end
- end
+ visit(project_wiki_path(project, wiki_page))
end
- it 'opens a default wiki page', :js do
- visit(project_path(project))
-
- find('.shortcuts-wiki').click
- click_link "Create your first page"
+ it 'does not show "Edit" button' do
+ expect(page).not_to have_selector('a.btn', text: 'Edit')
+ end
- expect(page).to have_content('Home · Create Page')
+ it 'shows error' do
+ page.within(:css, '.flash-notice') do
+ expect(page).to have_content('The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository.')
+ end
end
end
- context 'when Gitaly is enabled' do
- it_behaves_like 'wiki page user view'
- end
+ it 'opens a default wiki page', :js do
+ visit(project_path(project))
+
+ find('.shortcuts-wiki').click
+ click_link "Create your first page"
- context 'when Gitaly is disabled', :skip_gitaly_mock do
- it_behaves_like 'wiki page user view'
+ expect(page).to have_content('Home · Create Page')
end
end
diff --git a/spec/features/search/user_uses_header_search_field_spec.rb b/spec/features/search/user_uses_header_search_field_spec.rb
index af38f77c0c6..444de26733f 100644
--- a/spec/features/search/user_uses_header_search_field_spec.rb
+++ b/spec/features/search/user_uses_header_search_field_spec.rb
@@ -21,13 +21,17 @@ describe 'User uses header search field' do
it 'shows assigned issues' do
find('.search-input-container .dropdown-menu').click_link('Issues assigned to me')
- expect(find('.js-assignee-search')).to have_content(user.name)
+ expect(page).to have_selector('.filtered-search')
+ expect_tokens([assignee_token(user.name)])
+ expect_filtered_search_input_empty
end
it 'shows created issues' do
find('.search-input-container .dropdown-menu').click_link("Issues I've created")
- expect(find('.js-author-search')).to have_content(user.name)
+ expect(page).to have_selector('.filtered-search')
+ expect_tokens([author_token(user.name)])
+ expect_filtered_search_input_empty
end
end
@@ -37,13 +41,17 @@ describe 'User uses header search field' do
it 'shows assigned merge requests' do
find('.search-input-container .dropdown-menu').click_link('Merge requests assigned to me')
- expect(find('.js-assignee-search')).to have_content(user.name)
+ expect(page).to have_selector('.filtered-search')
+ expect_tokens([assignee_token(user.name)])
+ expect_filtered_search_input_empty
end
it 'shows created merge requests' do
find('.search-input-container .dropdown-menu').click_link("Merge requests I've created")
- expect(find('.js-author-search')).to have_content(user.name)
+ expect(page).to have_selector('.filtered-search')
+ expect_tokens([author_token(user.name)])
+ expect_filtered_search_input_empty
end
end
end
diff --git a/spec/features/users/login_spec.rb b/spec/features/users/login_spec.rb
index 44758f862a8..ad856bd062e 100644
--- a/spec/features/users/login_spec.rb
+++ b/spec/features/users/login_spec.rb
@@ -2,6 +2,7 @@ require 'spec_helper'
describe 'Login' do
include TermsHelper
+ include UserLoginHelper
before do
stub_authentication_activity_metrics(debug: true)
@@ -546,29 +547,6 @@ describe 'Login' do
ensure_tab_pane_correctness(false)
end
end
-
- def ensure_tab_pane_correctness(visit_path = true)
- if visit_path
- visit new_user_session_path
- end
-
- ensure_tab_pane_counts
- ensure_one_active_tab
- ensure_one_active_pane
- end
-
- def ensure_tab_pane_counts
- tabs_count = page.all('[role="tab"]').size
- expect(page).to have_selector('[role="tabpanel"]', count: tabs_count)
- end
-
- def ensure_one_active_tab
- expect(page).to have_selector('ul.new-session-tabs > li > a.active', count: 1)
- end
-
- def ensure_one_active_pane
- expect(page).to have_selector('.tab-pane.active', count: 1)
- end
end
context 'when terms are enforced' do
diff --git a/spec/features/users/overview_spec.rb b/spec/features/users/overview_spec.rb
index b0ff53f9ccb..34ed771340f 100644
--- a/spec/features/users/overview_spec.rb
+++ b/spec/features/users/overview_spec.rb
@@ -54,15 +54,15 @@ describe 'Overview tab on a user profile', :js do
end
end
- describe 'user has 10 activities' do
+ describe 'user has 11 activities' do
before do
- 10.times { push_code_contribution }
+ 11.times { push_code_contribution }
end
include_context 'visit overview tab'
- it 'displays 5 entries in the list of activities' do
- expect(find('#js-overview')).to have_selector('.event-item', count: 5)
+ it 'displays 10 entries in the list of activities' do
+ expect(find('#js-overview')).to have_selector('.event-item', count: 10)
end
it 'shows a link to the activity list' do
diff --git a/spec/finders/group_descendants_finder_spec.rb b/spec/finders/group_descendants_finder_spec.rb
index c64abdc3619..c28fd7cad11 100644
--- a/spec/finders/group_descendants_finder_spec.rb
+++ b/spec/finders/group_descendants_finder_spec.rb
@@ -74,6 +74,13 @@ describe GroupDescendantsFinder do
end
end
+ it 'sorts elements by latest created as default' do
+ project1 = create(:project, namespace: group, created_at: 1.hour.ago)
+ project2 = create(:project, namespace: group)
+
+ expect(subject.execute).to eq([project2, project1])
+ end
+
context 'sorting by name' do
let!(:project1) { create(:project, namespace: group, name: 'a', path: 'project-a') }
let!(:project2) { create(:project, namespace: group, name: 'z', path: 'project-z') }
diff --git a/spec/finders/pending_todos_finder_spec.rb b/spec/finders/pending_todos_finder_spec.rb
index 32fad5e225f..b41b1b46a93 100644
--- a/spec/finders/pending_todos_finder_spec.rb
+++ b/spec/finders/pending_todos_finder_spec.rb
@@ -46,7 +46,7 @@ describe PendingTodosFinder do
create(:todo, :pending, user: user, target: note)
- todos = described_class.new(user, target_type: issue.class).execute
+ todos = described_class.new(user, target_type: issue.class.name).execute
expect(todos).to eq([todo])
end
diff --git a/spec/helpers/auth_helper_spec.rb b/spec/helpers/auth_helper_spec.rb
index 120b23e66ac..f0c2e4768ec 100644
--- a/spec/helpers/auth_helper_spec.rb
+++ b/spec/helpers/auth_helper_spec.rb
@@ -42,6 +42,16 @@ describe AuthHelper do
end
end
+ describe 'form_based_auth_provider_has_active_class?' do
+ it 'selects main LDAP server' do
+ allow(helper).to receive(:auth_providers) { [:twitter, :ldapprimary, :ldapsecondary, :kerberos] }
+ expect(helper.form_based_auth_provider_has_active_class?(:twitter)).to be(false)
+ expect(helper.form_based_auth_provider_has_active_class?(:ldapprimary)).to be(true)
+ expect(helper.form_based_auth_provider_has_active_class?(:ldapsecondary)).to be(false)
+ expect(helper.form_based_auth_provider_has_active_class?(:kerberos)).to be(false)
+ end
+ end
+
describe 'enabled_button_based_providers' do
before do
allow(helper).to receive(:auth_providers) { [:twitter, :github] }
diff --git a/spec/helpers/search_helper_spec.rb b/spec/helpers/search_helper_spec.rb
index 8bfd520528f..4945749f524 100644
--- a/spec/helpers/search_helper_spec.rb
+++ b/spec/helpers/search_helper_spec.rb
@@ -135,5 +135,40 @@ describe SearchHelper do
expect(search_filter_input_options('')[:data]['base-endpoint']).to eq("/groups#{group_path(@group)}")
end
end
+
+ context 'dashboard' do
+ it 'does not include group-id and project-id' do
+ expect(search_filter_input_options('')[:data]['project-id']).to eq(nil)
+ expect(search_filter_input_options('')[:data]['group-id']).to eq(nil)
+ end
+
+ it 'includes dashboard base-endpoint' do
+ expect(search_filter_input_options('')[:data]['base-endpoint']).to eq("/dashboard")
+ end
+ end
+ end
+
+ describe 'search_history_storage_prefix' do
+ context 'project' do
+ it 'returns project full_path' do
+ @project = create(:project, :repository)
+
+ expect(search_history_storage_prefix).to eq(@project.full_path)
+ end
+ end
+
+ context 'group' do
+ it 'returns group full_path' do
+ @group = create(:group, :nested, name: 'group-name')
+
+ expect(search_history_storage_prefix).to eq(@group.full_path)
+ end
+ end
+
+ context 'dashboard' do
+ it 'returns dashboard' do
+ expect(search_history_storage_prefix).to eq("dashboard")
+ end
+ end
end
end
diff --git a/spec/javascripts/lib/utils/text_markdown_spec.js b/spec/javascripts/lib/utils/text_markdown_spec.js
index b9e805628f8..f71d27eb4e4 100644
--- a/spec/javascripts/lib/utils/text_markdown_spec.js
+++ b/spec/javascripts/lib/utils/text_markdown_spec.js
@@ -86,6 +86,29 @@ describe('init markdown', () => {
expect(textArea.value).toEqual(`${initialValue}* `);
});
+
+ it('places the cursor inside the tags', () => {
+ const start = 'lorem ';
+ const end = ' ipsum';
+ const tag = '*';
+
+ textArea.value = `${start}${end}`;
+ textArea.setSelectionRange(start.length, start.length);
+
+ insertMarkdownText({
+ textArea,
+ text: textArea.value,
+ tag,
+ blockTag: null,
+ selected: '',
+ wrap: true,
+ });
+
+ expect(textArea.value).toEqual(`${start}**${end}`);
+
+ // cursor placement should be between tags
+ expect(textArea.selectionStart).toBe(start.length + tag.length);
+ });
});
describe('with selection', () => {
@@ -98,16 +121,22 @@ describe('init markdown', () => {
});
it('applies the tag to the selected value', () => {
+ const selectedIndex = text.indexOf(selected);
+ const tag = '*';
+
insertMarkdownText({
textArea,
text: textArea.value,
- tag: '*',
+ tag,
blockTag: null,
selected,
wrap: true,
});
expect(textArea.value).toEqual(text.replace(selected, `*${selected}*`));
+
+ // cursor placement should be after selection + 2 tag lengths
+ expect(textArea.selectionStart).toBe(selectedIndex + selected.length + 2 * tag.length);
});
it('replaces the placeholder in the tag', () => {
diff --git a/spec/javascripts/search_autocomplete_spec.js b/spec/javascripts/search_autocomplete_spec.js
index 7530fd2a43b..7a4ca587313 100644
--- a/spec/javascripts/search_autocomplete_spec.js
+++ b/spec/javascripts/search_autocomplete_spec.js
@@ -1,4 +1,4 @@
-/* eslint-disable no-var, one-var, no-unused-expressions, consistent-return, no-param-reassign, default-case, no-return-assign, object-shorthand, prefer-template, vars-on-top */
+/* eslint-disable no-var, one-var, no-unused-expressions, consistent-return, no-param-reassign, default-case, no-return-assign, object-shorthand, vars-on-top */
import $ from 'jquery';
import '~/gl_dropdown';
@@ -109,16 +109,16 @@ describe('Search autocomplete dropdown', () => {
assertLinks = function(list, issuesPath, mrsPath) {
if (issuesPath) {
- const issuesAssignedToMeLink = `a[href="${issuesPath}/?assignee_id=${userId}"]`;
- const issuesIHaveCreatedLink = `a[href="${issuesPath}/?author_id=${userId}"]`;
+ const issuesAssignedToMeLink = `a[href="${issuesPath}/?assignee_username=${userName}"]`;
+ const issuesIHaveCreatedLink = `a[href="${issuesPath}/?author_username=${userName}"]`;
expect(list.find(issuesAssignedToMeLink).length).toBe(1);
expect(list.find(issuesAssignedToMeLink).text()).toBe('Issues assigned to me');
expect(list.find(issuesIHaveCreatedLink).length).toBe(1);
expect(list.find(issuesIHaveCreatedLink).text()).toBe("Issues I've created");
}
- const mrsAssignedToMeLink = `a[href="${mrsPath}/?assignee_id=${userId}"]`;
- const mrsIHaveCreatedLink = `a[href="${mrsPath}/?author_id=${userId}"]`;
+ const mrsAssignedToMeLink = `a[href="${mrsPath}/?assignee_username=${userName}"]`;
+ const mrsIHaveCreatedLink = `a[href="${mrsPath}/?author_username=${userName}"]`;
expect(list.find(mrsAssignedToMeLink).length).toBe(1);
expect(list.find(mrsAssignedToMeLink).text()).toBe('Merge requests assigned to me');
@@ -186,7 +186,7 @@ describe('Search autocomplete dropdown', () => {
widget.searchInput.val('help');
widget.searchInput.triggerHandler('focus');
list = widget.wrap.find('.dropdown-menu').find('ul');
- link = "a[href='" + projectIssuesPath + '/?assignee_id=' + userId + "']";
+ link = `a[href='${projectIssuesPath}/?assignee_username=${userName}']`;
expect(list.find(link).length).toBe(0);
});
diff --git a/spec/javascripts/vue_mr_widget/components/deployment_spec.js b/spec/javascripts/vue_mr_widget/components/deployment_spec.js
index ebbcaeb6f30..056b4df8fdc 100644
--- a/spec/javascripts/vue_mr_widget/components/deployment_spec.js
+++ b/spec/javascripts/vue_mr_widget/components/deployment_spec.js
@@ -41,7 +41,7 @@ describe('Deployment component', () => {
describe('', () => {
beforeEach(() => {
- vm = mountComponent(Component, { deployment: { ...deploymentMockData } });
+ vm = mountComponent(Component, { deployment: { ...deploymentMockData }, showMetrics: true });
});
describe('deployTimeago', () => {
@@ -174,11 +174,31 @@ describe('Deployment component', () => {
});
});
+ describe('with showMetrics enabled', () => {
+ beforeEach(() => {
+ vm = mountComponent(Component, { deployment: { ...deploymentMockData }, showMetrics: true });
+ });
+
+ it('shows metrics', () => {
+ expect(vm.$el).toContainElement('.js-mr-memory-usage');
+ });
+ });
+
+ describe('with showMetrics disabled', () => {
+ beforeEach(() => {
+ vm = mountComponent(Component, { deployment: { ...deploymentMockData }, showMetrics: false });
+ });
+
+ it('hides metrics', () => {
+ expect(vm.$el).not.toContainElement('.js-mr-memory-usage');
+ });
+ });
+
describe('without changes', () => {
beforeEach(() => {
delete deploymentMockData.changes;
- vm = mountComponent(Component, { deployment: { ...deploymentMockData } });
+ vm = mountComponent(Component, { deployment: { ...deploymentMockData }, showMetrics: true });
});
it('renders the link to the review app without dropdown', () => {
@@ -192,6 +212,7 @@ describe('Deployment component', () => {
beforeEach(() => {
vm = mountComponent(Component, {
deployment: Object.assign({}, deploymentMockData, { status: 'running' }),
+ showMetrics: true,
});
});
@@ -208,6 +229,7 @@ describe('Deployment component', () => {
beforeEach(() => {
vm = mountComponent(Component, {
deployment: Object.assign({}, deploymentMockData, { status: 'success' }),
+ showMetrics: true,
});
});
@@ -220,6 +242,7 @@ describe('Deployment component', () => {
beforeEach(() => {
vm = mountComponent(Component, {
deployment: Object.assign({}, deploymentMockData, { status: 'failed' }),
+ showMetrics: true,
});
});
diff --git a/spec/javascripts/vue_shared/components/expand_button_spec.js b/spec/javascripts/vue_shared/components/expand_button_spec.js
index 98fee9a74a5..2af4abc299a 100644
--- a/spec/javascripts/vue_shared/components/expand_button_spec.js
+++ b/spec/javascripts/vue_shared/components/expand_button_spec.js
@@ -18,7 +18,7 @@ describe('expand button', () => {
vm.$destroy();
});
- it('renders a collpased button', () => {
+ it('renders a collapsed button', () => {
expect(vm.$children[0].iconTestClass).toEqual('ic-ellipsis_h');
});
diff --git a/spec/lib/extracts_path_spec.rb b/spec/lib/extracts_path_spec.rb
index 8947e2ac4fb..e0691aba600 100644
--- a/spec/lib/extracts_path_spec.rb
+++ b/spec/lib/extracts_path_spec.rb
@@ -205,28 +205,18 @@ describe ExtractsPath do
end
describe '#lfs_blob_ids' do
- shared_examples '#lfs_blob_ids' do
- let(:tag) { @project.repository.add_tag(@project.owner, 'my-annotated-tag', 'master', 'test tag') }
- let(:ref) { tag.target }
- let(:params) { { ref: ref, path: 'README.md' } }
+ let(:tag) { @project.repository.add_tag(@project.owner, 'my-annotated-tag', 'master', 'test tag') }
+ let(:ref) { tag.target }
+ let(:params) { { ref: ref, path: 'README.md' } }
- before do
- @project = create(:project, :repository)
- end
-
- it 'handles annotated tags' do
- assign_ref_vars
-
- expect(lfs_blob_ids).to eq([])
- end
+ before do
+ @project = create(:project, :repository)
end
- context 'when gitaly is enabled' do
- it_behaves_like '#lfs_blob_ids'
- end
+ it 'handles annotated tags' do
+ assign_ref_vars
- context 'when gitaly is disabled', :skip_gitaly_mock do
- it_behaves_like '#lfs_blob_ids'
+ expect(lfs_blob_ids).to eq([])
end
end
end
diff --git a/spec/lib/gitlab/ci/variables/collection/item_spec.rb b/spec/lib/gitlab/ci/variables/collection/item_spec.rb
index 46874662edd..e1e0582cd11 100644
--- a/spec/lib/gitlab/ci/variables/collection/item_spec.rb
+++ b/spec/lib/gitlab/ci/variables/collection/item_spec.rb
@@ -36,7 +36,7 @@ describe Gitlab::Ci::Variables::Collection::Item do
shared_examples 'raises error for invalid type' do
it do
expect { described_class.new(key: variable_key, value: variable_value) }
- .to raise_error ArgumentError, /`value` must be of type String, while it was:/
+ .to raise_error ArgumentError, /`#{variable_key}` must be of type String, while it was:/
end
end
@@ -46,7 +46,7 @@ describe Gitlab::Ci::Variables::Collection::Item do
let(:variable_value) { nil }
let(:expected_value) { nil }
- it_behaves_like 'creates variable'
+ it_behaves_like 'raises error for invalid type'
end
context "when it's an empty string" do
diff --git a/spec/lib/gitlab/diff/file_collection/merge_request_diff_spec.rb b/spec/lib/gitlab/diff/file_collection/merge_request_diff_spec.rb
index 4578da70bfc..fbcf515281e 100644
--- a/spec/lib/gitlab/diff/file_collection/merge_request_diff_spec.rb
+++ b/spec/lib/gitlab/diff/file_collection/merge_request_diff_spec.rb
@@ -37,17 +37,7 @@ describe Gitlab::Diff::FileCollection::MergeRequestDiff do
let(:stub_path) { '.gitignore' }
end
- shared_examples 'initializes a DiffCollection' do
- it 'returns a valid instance of a DiffCollection' do
- expect(diff_files).to be_a(Gitlab::Git::DiffCollection)
- end
- end
-
- context 'with Gitaly disabled', :disable_gitaly do
- it_behaves_like 'initializes a DiffCollection'
- end
-
- context 'with Gitaly enabled' do
- it_behaves_like 'initializes a DiffCollection'
+ it 'returns a valid instance of a DiffCollection' do
+ expect(diff_files).to be_a(Gitlab::Git::DiffCollection)
end
end
diff --git a/spec/lib/gitlab/git/blob_spec.rb b/spec/lib/gitlab/git/blob_spec.rb
index b243f0dacae..80dd3dcc58e 100644
--- a/spec/lib/gitlab/git/blob_spec.rb
+++ b/spec/lib/gitlab/git/blob_spec.rb
@@ -128,7 +128,7 @@ describe Gitlab::Git::Blob, :seed_helper do
end
end
- shared_examples 'finding blobs by ID' do
+ describe '.raw' do
let(:raw_blob) { Gitlab::Git::Blob.raw(repository, SeedRepo::RubyBlob::ID) }
let(:bad_blob) { Gitlab::Git::Blob.raw(repository, SeedRepo::BigCommit::ID) }
@@ -166,16 +166,6 @@ describe Gitlab::Git::Blob, :seed_helper do
end
end
- describe '.raw' do
- context 'when the blob_raw Gitaly feature is enabled' do
- it_behaves_like 'finding blobs by ID'
- end
-
- context 'when the blob_raw Gitaly feature is disabled', :skip_gitaly_mock do
- it_behaves_like 'finding blobs by ID'
- end
- end
-
describe '.batch' do
let(:blob_references) do
[
diff --git a/spec/lib/gitlab/git/commit_spec.rb b/spec/lib/gitlab/git/commit_spec.rb
index 6be35eee0fd..74d542060d5 100644
--- a/spec/lib/gitlab/git/commit_spec.rb
+++ b/spec/lib/gitlab/git/commit_spec.rb
@@ -183,110 +183,100 @@ describe Gitlab::Git::Commit, :seed_helper do
end
end
- shared_examples '.where' do
- context 'path is empty string' do
- subject do
- commits = described_class.where(
- repo: repository,
- ref: 'master',
- path: '',
- limit: 10
- )
-
- commits.map { |c| c.id }
- end
+ context 'path is empty string' do
+ subject do
+ commits = described_class.where(
+ repo: repository,
+ ref: 'master',
+ path: '',
+ limit: 10
+ )
- it 'has 10 elements' do
- expect(subject.size).to eq(10)
- end
- it { is_expected.to include(SeedRepo::EmptyCommit::ID) }
+ commits.map { |c| c.id }
end
- context 'path is nil' do
- subject do
- commits = described_class.where(
- repo: repository,
- ref: 'master',
- path: nil,
- limit: 10
- )
-
- commits.map { |c| c.id }
- end
-
- it 'has 10 elements' do
- expect(subject.size).to eq(10)
- end
- it { is_expected.to include(SeedRepo::EmptyCommit::ID) }
+ it 'has 10 elements' do
+ expect(subject.size).to eq(10)
end
+ it { is_expected.to include(SeedRepo::EmptyCommit::ID) }
+ end
- context 'ref is branch name' do
- subject do
- commits = described_class.where(
- repo: repository,
- ref: 'master',
- path: 'files',
- limit: 3,
- offset: 1
- )
+ context 'path is nil' do
+ subject do
+ commits = described_class.where(
+ repo: repository,
+ ref: 'master',
+ path: nil,
+ limit: 10
+ )
- commits.map { |c| c.id }
- end
+ commits.map { |c| c.id }
+ end
- it 'has 3 elements' do
- expect(subject.size).to eq(3)
- end
- it { is_expected.to include("d14d6c0abdd253381df51a723d58691b2ee1ab08") }
- it { is_expected.not_to include("eb49186cfa5c4338011f5f590fac11bd66c5c631") }
+ it 'has 10 elements' do
+ expect(subject.size).to eq(10)
end
+ it { is_expected.to include(SeedRepo::EmptyCommit::ID) }
+ end
- context 'ref is commit id' do
- subject do
- commits = described_class.where(
- repo: repository,
- ref: "874797c3a73b60d2187ed6e2fcabd289ff75171e",
- path: 'files',
- limit: 3,
- offset: 1
- )
+ context 'ref is branch name' do
+ subject do
+ commits = described_class.where(
+ repo: repository,
+ ref: 'master',
+ path: 'files',
+ limit: 3,
+ offset: 1
+ )
- commits.map { |c| c.id }
- end
+ commits.map { |c| c.id }
+ end
- it 'has 3 elements' do
- expect(subject.size).to eq(3)
- end
- it { is_expected.to include("2f63565e7aac07bcdadb654e253078b727143ec4") }
- it { is_expected.not_to include(SeedRepo::Commit::ID) }
+ it 'has 3 elements' do
+ expect(subject.size).to eq(3)
end
+ it { is_expected.to include("d14d6c0abdd253381df51a723d58691b2ee1ab08") }
+ it { is_expected.not_to include("eb49186cfa5c4338011f5f590fac11bd66c5c631") }
+ end
- context 'ref is tag' do
- subject do
- commits = described_class.where(
- repo: repository,
- ref: 'v1.0.0',
- path: 'files',
- limit: 3,
- offset: 1
- )
+ context 'ref is commit id' do
+ subject do
+ commits = described_class.where(
+ repo: repository,
+ ref: "874797c3a73b60d2187ed6e2fcabd289ff75171e",
+ path: 'files',
+ limit: 3,
+ offset: 1
+ )
- commits.map { |c| c.id }
- end
+ commits.map { |c| c.id }
+ end
- it 'has 3 elements' do
- expect(subject.size).to eq(3)
- end
- it { is_expected.to include("874797c3a73b60d2187ed6e2fcabd289ff75171e") }
- it { is_expected.not_to include(SeedRepo::Commit::ID) }
+ it 'has 3 elements' do
+ expect(subject.size).to eq(3)
end
+ it { is_expected.to include("2f63565e7aac07bcdadb654e253078b727143ec4") }
+ it { is_expected.not_to include(SeedRepo::Commit::ID) }
end
- describe '.where with gitaly' do
- it_should_behave_like '.where'
- end
+ context 'ref is tag' do
+ subject do
+ commits = described_class.where(
+ repo: repository,
+ ref: 'v1.0.0',
+ path: 'files',
+ limit: 3,
+ offset: 1
+ )
- describe '.where without gitaly', :skip_gitaly_mock do
- it_should_behave_like '.where'
+ commits.map { |c| c.id }
+ end
+
+ it 'has 3 elements' do
+ expect(subject.size).to eq(3)
+ end
+ it { is_expected.to include("874797c3a73b60d2187ed6e2fcabd289ff75171e") }
+ it { is_expected.not_to include(SeedRepo::Commit::ID) }
end
describe '.between' do
@@ -508,7 +498,7 @@ describe Gitlab::Git::Commit, :seed_helper do
end
end
- shared_examples '#stats' do
+ describe '#stats' do
subject { commit.stats }
describe '#additions' do
@@ -527,14 +517,6 @@ describe Gitlab::Git::Commit, :seed_helper do
end
end
- describe '#stats with gitaly on' do
- it_should_behave_like '#stats'
- end
-
- describe '#stats with gitaly disabled', :skip_gitaly_mock do
- it_should_behave_like '#stats'
- end
-
describe '#has_zero_stats?' do
it { expect(commit.has_zero_stats?).to eq(false) }
end
@@ -577,25 +559,15 @@ describe Gitlab::Git::Commit, :seed_helper do
commit_ids.map { |id| described_class.get_message(repository, id) }
end
- shared_examples 'getting commit messages' do
- it 'gets commit messages' do
- expect(subject).to contain_exactly(
- "Added contributing guide\n\nSigned-off-by: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>\n",
- "Add submodule\n\nSigned-off-by: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>\n"
- )
- end
- end
-
- context 'when Gitaly commit_messages feature is enabled' do
- it_behaves_like 'getting commit messages'
-
- it 'gets messages in one batch', :request_store do
- expect { subject.map(&:itself) }.to change { Gitlab::GitalyClient.get_request_count }.by(1)
- end
+ it 'gets commit messages' do
+ expect(subject).to contain_exactly(
+ "Added contributing guide\n\nSigned-off-by: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>\n",
+ "Add submodule\n\nSigned-off-by: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>\n"
+ )
end
- context 'when Gitaly commit_messages feature is disabled', :disable_gitaly do
- it_behaves_like 'getting commit messages'
+ it 'gets messages in one batch', :request_store do
+ expect { subject.map(&:itself) }.to change { Gitlab::GitalyClient.get_request_count }.by(1)
end
end
diff --git a/spec/lib/gitlab/git/tag_spec.rb b/spec/lib/gitlab/git/tag_spec.rb
index c5bad062c2a..abee2822d77 100644
--- a/spec/lib/gitlab/git/tag_spec.rb
+++ b/spec/lib/gitlab/git/tag_spec.rb
@@ -3,7 +3,7 @@ require "spec_helper"
describe Gitlab::Git::Tag, :seed_helper do
let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH, '') }
- shared_examples 'Gitlab::Git::Repository#tags' do
+ describe '#tags' do
describe 'first tag' do
let(:tag) { repository.tags.first }
@@ -25,14 +25,6 @@ describe Gitlab::Git::Tag, :seed_helper do
it { expect(repository.tags.size).to eq(SeedRepo::Repo::TAGS.size) }
end
- context 'when Gitaly tags feature is enabled' do
- it_behaves_like 'Gitlab::Git::Repository#tags'
- end
-
- context 'when Gitaly tags feature is disabled', :skip_gitaly_mock do
- it_behaves_like 'Gitlab::Git::Repository#tags'
- end
-
describe '.get_message' do
let(:tag_ids) { %w[f4e6814c3e4e7a0de82a9e7cd20c626cc963a2f8 8a2a6eb295bb170b34c24c76c49ed0e9b2eaf34b] }
@@ -40,23 +32,13 @@ describe Gitlab::Git::Tag, :seed_helper do
tag_ids.map { |id| described_class.get_message(repository, id) }
end
- shared_examples 'getting tag messages' do
- it 'gets tag messages' do
- expect(subject[0]).to eq("Release\n")
- expect(subject[1]).to eq("Version 1.1.0\n")
- end
- end
-
- context 'when Gitaly tag_messages feature is enabled' do
- it_behaves_like 'getting tag messages'
-
- it 'gets messages in one batch', :request_store do
- expect { subject.map(&:itself) }.to change { Gitlab::GitalyClient.get_request_count }.by(1)
- end
+ it 'gets tag messages' do
+ expect(subject[0]).to eq("Release\n")
+ expect(subject[1]).to eq("Version 1.1.0\n")
end
- context 'when Gitaly tag_messages feature is disabled', :disable_gitaly do
- it_behaves_like 'getting tag messages'
+ it 'gets messages in one batch', :request_store do
+ expect { subject.map(&:itself) }.to change { Gitlab::GitalyClient.get_request_count }.by(1)
end
end
diff --git a/spec/lib/gitlab/git/tree_spec.rb b/spec/lib/gitlab/git/tree_spec.rb
index 3792d6bf67b..bec875fb03d 100644
--- a/spec/lib/gitlab/git/tree_spec.rb
+++ b/spec/lib/gitlab/git/tree_spec.rb
@@ -80,18 +80,8 @@ describe Gitlab::Git::Tree, :seed_helper do
end
describe '#where' do
- shared_examples '#where' do
- it 'returns an empty array when called with an invalid ref' do
- expect(described_class.where(repository, 'foobar-does-not-exist')).to eq([])
- end
- end
-
- context 'with gitaly' do
- it_behaves_like '#where'
- end
-
- context 'without gitaly', :skip_gitaly_mock do
- it_behaves_like '#where'
+ it 'returns an empty array when called with an invalid ref' do
+ expect(described_class.where(repository, 'foobar-does-not-exist')).to eq([])
end
end
end
diff --git a/spec/lib/gitlab/gitaly_client_spec.rb b/spec/lib/gitlab/gitaly_client_spec.rb
index 81bcd8c28ed..3ae319456da 100644
--- a/spec/lib/gitlab/gitaly_client_spec.rb
+++ b/spec/lib/gitlab/gitaly_client_spec.rb
@@ -2,7 +2,7 @@ require 'spec_helper'
# We stub Gitaly in `spec/support/gitaly.rb` for other tests. We don't want
# those stubs while testing the GitalyClient itself.
-describe Gitlab::GitalyClient, skip_gitaly_mock: true do
+describe Gitlab::GitalyClient do
describe '.stub_class' do
it 'returns the gRPC health check stub' do
expect(described_class.stub_class(:health_check)).to eq(::Grpc::Health::V1::Health::Stub)
@@ -191,102 +191,13 @@ describe Gitlab::GitalyClient, skip_gitaly_mock: true do
let(:feature_name) { 'my_feature' }
let(:real_feature_name) { "gitaly_#{feature_name}" }
- context 'when Gitaly is disabled' do
- before do
- allow(described_class).to receive(:enabled?).and_return(false)
- end
-
- it 'returns false' do
- expect(described_class.feature_enabled?(feature_name)).to be(false)
- end
- end
-
- context 'when the feature status is DISABLED' do
- let(:feature_status) { Gitlab::GitalyClient::MigrationStatus::DISABLED }
-
- it 'returns false' do
- expect(described_class.feature_enabled?(feature_name, status: feature_status)).to be(false)
- end
- end
-
- context 'when the feature_status is OPT_IN' do
- let(:feature_status) { Gitlab::GitalyClient::MigrationStatus::OPT_IN }
-
- context "when the feature flag hasn't been set" do
- it 'returns false' do
- expect(described_class.feature_enabled?(feature_name, status: feature_status)).to be(false)
- end
- end
-
- context "when the feature flag is set to disable" do
- before do
- Feature.get(real_feature_name).disable
- end
-
- it 'returns false' do
- expect(described_class.feature_enabled?(feature_name, status: feature_status)).to be(false)
- end
- end
-
- context "when the feature flag is set to enable" do
- before do
- Feature.get(real_feature_name).enable
- end
-
- it 'returns true' do
- expect(described_class.feature_enabled?(feature_name, status: feature_status)).to be(true)
- end
- end
-
- context "when the feature flag is set to a percentage of time" do
- before do
- Feature.get(real_feature_name).enable_percentage_of_time(70)
- end
-
- it 'bases the result on pseudo-random numbers' do
- expect(Random).to receive(:rand).and_return(0.3)
- expect(described_class.feature_enabled?(feature_name, status: feature_status)).to be(true)
-
- expect(Random).to receive(:rand).and_return(0.8)
- expect(described_class.feature_enabled?(feature_name, status: feature_status)).to be(false)
- end
- end
-
- context "when a feature is not persisted" do
- it 'returns false when opt_into_all_features is off' do
- allow(Feature).to receive(:persisted?).and_return(false)
- allow(described_class).to receive(:opt_into_all_features?).and_return(false)
-
- expect(described_class.feature_enabled?(feature_name, status: feature_status)).to be(false)
- end
-
- it 'returns true when the override is on' do
- allow(Feature).to receive(:persisted?).and_return(false)
- allow(described_class).to receive(:opt_into_all_features?).and_return(true)
-
- expect(described_class.feature_enabled?(feature_name, status: feature_status)).to be(true)
- end
- end
+ before do
+ allow(Feature).to receive(:enabled?).and_return(false)
end
- context 'when the feature_status is OPT_OUT' do
- let(:feature_status) { Gitlab::GitalyClient::MigrationStatus::OPT_OUT }
-
- context "when the feature flag hasn't been set" do
- it 'returns true' do
- expect(described_class.feature_enabled?(feature_name, status: feature_status)).to be(true)
- end
- end
-
- context "when the feature flag is set to disable" do
- before do
- Feature.get(real_feature_name).disable
- end
-
- it 'returns false' do
- expect(described_class.feature_enabled?(feature_name, status: feature_status)).to be(false)
- end
- end
+ it 'returns false' do
+ expect(Feature).to receive(:enabled?).with(real_feature_name)
+ expect(described_class.feature_enabled?(feature_name)).to be(false)
end
end
diff --git a/spec/lib/gitlab/import_export/project.json b/spec/lib/gitlab/import_export/project.json
index 3f2281f213f..58949f76bd6 100644
--- a/spec/lib/gitlab/import_export/project.json
+++ b/spec/lib/gitlab/import_export/project.json
@@ -2556,7 +2556,7 @@
"merge_request_diff_id": 27,
"relative_order": 0,
"sha": "bb5206fee213d983da88c47f9cf4cc6caf9c66dc",
- "message": "Feature conflcit added\n\nSigned-off-by: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>\n",
+ "message": "Feature conflict added\n\nSigned-off-by: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>\n",
"authored_date": "2014-08-06T08:35:52.000+02:00",
"author_name": "Dmitriy Zaporozhets",
"author_email": "dmitriy.zaporozhets@gmail.com",
@@ -3605,7 +3605,7 @@
"merge_request_diff_id": 14,
"relative_order": 8,
"sha": "08f22f255f082689c0d7d39d19205085311542bc",
- "message": "remove emtpy file.(beacase git ignore empty file)\nadd whitespace test file.\n",
+ "message": "remove empty file.(beacase git ignore empty file)\nadd whitespace test file.\n",
"authored_date": "2015-11-13T06:00:16.000+01:00",
"author_name": "윤민식",
"author_email": "minsik.yoon@samsung.com",
@@ -4290,7 +4290,7 @@
"merge_request_diff_id": 13,
"relative_order": 8,
"sha": "08f22f255f082689c0d7d39d19205085311542bc",
- "message": "remove emtpy file.(beacase git ignore empty file)\nadd whitespace test file.\n",
+ "message": "remove empty file.(beacase git ignore empty file)\nadd whitespace test file.\n",
"authored_date": "2015-11-13T06:00:16.000+01:00",
"author_name": "윤민식",
"author_email": "minsik.yoon@samsung.com",
@@ -4799,7 +4799,7 @@
"merge_request_diff_id": 12,
"relative_order": 8,
"sha": "08f22f255f082689c0d7d39d19205085311542bc",
- "message": "remove emtpy file.(beacase git ignore empty file)\nadd whitespace test file.\n",
+ "message": "remove empty file.(beacase git ignore empty file)\nadd whitespace test file.\n",
"authored_date": "2015-11-13T06:00:16.000+01:00",
"author_name": "윤민식",
"author_email": "minsik.yoon@samsung.com",
@@ -5507,7 +5507,7 @@
"merge_request_diff_id": 10,
"relative_order": 8,
"sha": "08f22f255f082689c0d7d39d19205085311542bc",
- "message": "remove emtpy file.(beacase git ignore empty file)\nadd whitespace test file.\n",
+ "message": "remove empty file.(beacase git ignore empty file)\nadd whitespace test file.\n",
"authored_date": "2015-11-13T06:00:16.000+01:00",
"author_name": "윤민식",
"author_email": "minsik.yoon@samsung.com",
diff --git a/spec/lib/gitlab/import_export/project.light.json b/spec/lib/gitlab/import_export/project.light.json
index ba2248073f5..2971ca0f0f8 100644
--- a/spec/lib/gitlab/import_export/project.light.json
+++ b/spec/lib/gitlab/import_export/project.light.json
@@ -101,6 +101,28 @@
]
}
],
+ "services": [
+ {
+ "id": 100,
+ "title": "JetBrains TeamCity CI",
+ "project_id": 5,
+ "created_at": "2016-06-14T15:01:51.315Z",
+ "updated_at": "2016-06-14T15:01:51.315Z",
+ "active": false,
+ "properties": {},
+ "template": true,
+ "push_events": true,
+ "issues_events": true,
+ "merge_requests_events": true,
+ "tag_push_events": true,
+ "note_events": true,
+ "job_events": true,
+ "type": "TeamcityService",
+ "category": "ci",
+ "default": false,
+ "wiki_page_events": true
+ }
+ ],
"snippets": [],
"hooks": []
}
diff --git a/spec/lib/gitlab/import_export/project_tree_restorer_spec.rb b/spec/lib/gitlab/import_export/project_tree_restorer_spec.rb
index 365bfae0d88..7171e12a849 100644
--- a/spec/lib/gitlab/import_export/project_tree_restorer_spec.rb
+++ b/spec/lib/gitlab/import_export/project_tree_restorer_spec.rb
@@ -297,7 +297,8 @@ describe Gitlab::ImportExport::ProjectTreeRestorer do
issues: 1,
labels: 1,
milestones: 1,
- first_issue_labels: 1
+ first_issue_labels: 1,
+ services: 1
context 'project.json file access check' do
it 'does not read a symlink' do
@@ -382,6 +383,12 @@ describe Gitlab::ImportExport::ProjectTreeRestorer do
project_tree_restorer.instance_variable_set(:@path, "spec/lib/gitlab/import_export/project.light.json")
end
+ it 'does not import any templated services' do
+ restored_project_json
+
+ expect(project.services.where(template: true).count).to eq(0)
+ end
+
it 'imports labels' do
create(:group_label, name: 'Another label', group: project.group)
diff --git a/spec/lib/gitlab/private_commit_email_spec.rb b/spec/lib/gitlab/private_commit_email_spec.rb
index bc86cd3842a..10bf624bbdd 100644
--- a/spec/lib/gitlab/private_commit_email_spec.rb
+++ b/spec/lib/gitlab/private_commit_email_spec.rb
@@ -4,6 +4,9 @@ require 'spec_helper'
describe Gitlab::PrivateCommitEmail do
let(:hostname) { Gitlab::CurrentSettings.current_application_settings.commit_email_hostname }
+ let(:id) { 1 }
+ let(:valid_email) { "#{id}-foo@#{hostname}" }
+ let(:invalid_email) { "#{id}-foo@users.noreply.bar.com" }
context '.regex' do
subject { described_class.regex }
@@ -16,18 +19,25 @@ describe Gitlab::PrivateCommitEmail do
end
context '.user_id_for_email' do
- let(:id) { 1 }
-
it 'parses user id from email' do
- email = "#{id}-foo@#{hostname}"
-
- expect(described_class.user_id_for_email(email)).to eq(id)
+ expect(described_class.user_id_for_email(valid_email)).to eq(id)
end
it 'returns nil on invalid commit email' do
- email = "#{id}-foo@users.noreply.bar.com"
+ expect(described_class.user_id_for_email(invalid_email)).to be_nil
+ end
+ end
+
+ context '.user_ids_for_email' do
+ it 'returns deduplicated user IDs for each valid email' do
+ result = described_class.user_ids_for_emails([valid_email, valid_email, invalid_email])
+
+ expect(result).to eq([id])
+ end
- expect(described_class.user_id_for_email(email)).to be_nil
+ it 'returns an empty array with no valid emails' do
+ result = described_class.user_ids_for_emails([invalid_email])
+ expect(result).to eq([])
end
end
diff --git a/spec/models/ci/build_spec.rb b/spec/models/ci/build_spec.rb
index 6849bc6db7a..d02c3a5765f 100644
--- a/spec/models/ci/build_spec.rb
+++ b/spec/models/ci/build_spec.rb
@@ -1928,12 +1928,26 @@ describe Ci::Build do
describe '#repo_url' do
subject { build.repo_url }
- it { is_expected.to be_a(String) }
- it { is_expected.to end_with(".git") }
- it { is_expected.to start_with(project.web_url[0..6]) }
- it { is_expected.to include(build.token) }
- it { is_expected.to include('gitlab-ci-token') }
- it { is_expected.to include(project.web_url[7..-1]) }
+ context 'when token is set' do
+ before do
+ build.ensure_token
+ end
+
+ it { is_expected.to be_a(String) }
+ it { is_expected.to end_with(".git") }
+ it { is_expected.to start_with(project.web_url[0..6]) }
+ it { is_expected.to include(build.token) }
+ it { is_expected.to include('gitlab-ci-token') }
+ it { is_expected.to include(project.web_url[7..-1]) }
+ end
+
+ context 'when token is empty' do
+ before do
+ build.token = nil
+ end
+
+ it { is_expected.to be_nil}
+ end
end
describe '#stuck?' do
@@ -2043,7 +2057,8 @@ describe Ci::Build do
end
context 'use from gitlab-ci.yml' do
- let(:pipeline) { create(:ci_pipeline) }
+ let(:project) { create(:project, :repository) }
+ let(:pipeline) { create(:ci_pipeline, project: project) }
before do
stub_ci_pipeline_yaml_file(config)
@@ -2085,56 +2100,6 @@ describe Ci::Build do
describe '#variables' do
let(:container_registry_enabled) { false }
- let(:gitlab_version_info) { Gitlab::VersionInfo.parse(Gitlab::VERSION) }
- let(:predefined_variables) do
- [
- { key: 'CI_PIPELINE_ID', value: pipeline.id.to_s, public: true },
- { key: 'CI_PIPELINE_URL', value: project.web_url + "/pipelines/#{pipeline.id}", public: true },
- { key: 'CI_JOB_ID', value: build.id.to_s, public: true },
- { key: 'CI_JOB_URL', value: project.web_url + "/-/jobs/#{build.id}", public: true },
- { key: 'CI_JOB_TOKEN', value: build.token, public: false },
- { key: 'CI_BUILD_ID', value: build.id.to_s, public: true },
- { key: 'CI_BUILD_TOKEN', value: build.token, public: false },
- { key: 'CI_REGISTRY_USER', value: 'gitlab-ci-token', public: true },
- { key: 'CI_REGISTRY_PASSWORD', value: build.token, public: false },
- { key: 'CI_REPOSITORY_URL', value: build.repo_url, public: false },
- { key: 'CI', value: 'true', public: true },
- { key: 'GITLAB_CI', value: 'true', public: true },
- { key: 'GITLAB_FEATURES', value: project.licensed_features.join(','), public: true },
- { key: 'CI_SERVER_NAME', value: 'GitLab', public: true },
- { key: 'CI_SERVER_VERSION', value: Gitlab::VERSION, public: true },
- { key: 'CI_SERVER_VERSION_MAJOR', value: gitlab_version_info.major.to_s, public: true },
- { key: 'CI_SERVER_VERSION_MINOR', value: gitlab_version_info.minor.to_s, public: true },
- { key: 'CI_SERVER_VERSION_PATCH', value: gitlab_version_info.patch.to_s, public: true },
- { key: 'CI_SERVER_REVISION', value: Gitlab.revision, public: true },
- { key: 'CI_JOB_NAME', value: 'test', public: true },
- { key: 'CI_JOB_STAGE', value: 'test', public: true },
- { key: 'CI_COMMIT_SHA', value: build.sha, public: true },
- { key: 'CI_COMMIT_BEFORE_SHA', value: build.before_sha, public: true },
- { key: 'CI_COMMIT_REF_NAME', value: build.ref, public: true },
- { key: 'CI_COMMIT_REF_SLUG', value: build.ref_slug, public: true },
- { key: 'CI_NODE_TOTAL', value: '1', public: true },
- { key: 'CI_BUILD_REF', value: build.sha, public: true },
- { key: 'CI_BUILD_BEFORE_SHA', value: build.before_sha, public: true },
- { key: 'CI_BUILD_REF_NAME', value: build.ref, public: true },
- { key: 'CI_BUILD_REF_SLUG', value: build.ref_slug, public: true },
- { key: 'CI_BUILD_NAME', value: 'test', public: true },
- { key: 'CI_BUILD_STAGE', value: 'test', public: true },
- { key: 'CI_PROJECT_ID', value: project.id.to_s, public: true },
- { key: 'CI_PROJECT_NAME', value: project.path, public: true },
- { key: 'CI_PROJECT_PATH', value: project.full_path, public: true },
- { key: 'CI_PROJECT_PATH_SLUG', value: project.full_path_slug, public: true },
- { key: 'CI_PROJECT_NAMESPACE', value: project.namespace.full_path, public: true },
- { key: 'CI_PROJECT_URL', value: project.web_url, public: true },
- { key: 'CI_PROJECT_VISIBILITY', value: 'private', public: true },
- { key: 'CI_PIPELINE_IID', value: pipeline.iid.to_s, public: true },
- { key: 'CI_CONFIG_PATH', value: pipeline.ci_yaml_file_path, public: true },
- { key: 'CI_PIPELINE_SOURCE', value: pipeline.source, public: true },
- { key: 'CI_COMMIT_MESSAGE', value: pipeline.git_commit_message, public: true },
- { key: 'CI_COMMIT_TITLE', value: pipeline.git_commit_title, public: true },
- { key: 'CI_COMMIT_DESCRIPTION', value: pipeline.git_commit_description, public: true }
- ]
- end
before do
stub_container_registry_config(enabled: container_registry_enabled, host_port: 'registry.example.com')
@@ -2143,11 +2108,174 @@ describe Ci::Build do
subject { build.variables }
context 'returns variables' do
+ let(:predefined_variables) do
+ [
+ { key: 'CI_PIPELINE_ID', value: pipeline.id.to_s, public: true },
+ { key: 'CI_PIPELINE_URL', value: project.web_url + "/pipelines/#{pipeline.id}", public: true },
+ { key: 'CI_JOB_ID', value: build.id.to_s, public: true },
+ { key: 'CI_JOB_URL', value: project.web_url + "/-/jobs/#{build.id}", public: true },
+ { key: 'CI_JOB_TOKEN', value: 'my-token', public: false },
+ { key: 'CI_BUILD_ID', value: build.id.to_s, public: true },
+ { key: 'CI_BUILD_TOKEN', value: 'my-token', public: false },
+ { key: 'CI_REGISTRY_USER', value: 'gitlab-ci-token', public: true },
+ { key: 'CI_REGISTRY_PASSWORD', value: 'my-token', public: false },
+ { key: 'CI_REPOSITORY_URL', value: build.repo_url, public: false },
+ { key: 'CI', value: 'true', public: true },
+ { key: 'GITLAB_CI', value: 'true', public: true },
+ { key: 'GITLAB_FEATURES', value: project.licensed_features.join(','), public: true },
+ { key: 'CI_SERVER_NAME', value: 'GitLab', public: true },
+ { key: 'CI_SERVER_VERSION', value: Gitlab::VERSION, public: true },
+ { key: 'CI_SERVER_VERSION_MAJOR', value: Gitlab.version_info.major.to_s, public: true },
+ { key: 'CI_SERVER_VERSION_MINOR', value: Gitlab.version_info.minor.to_s, public: true },
+ { key: 'CI_SERVER_VERSION_PATCH', value: Gitlab.version_info.patch.to_s, public: true },
+ { key: 'CI_SERVER_REVISION', value: Gitlab.revision, public: true },
+ { key: 'CI_JOB_NAME', value: 'test', public: true },
+ { key: 'CI_JOB_STAGE', value: 'test', public: true },
+ { key: 'CI_COMMIT_SHA', value: build.sha, public: true },
+ { key: 'CI_COMMIT_BEFORE_SHA', value: build.before_sha, public: true },
+ { key: 'CI_COMMIT_REF_NAME', value: build.ref, public: true },
+ { key: 'CI_COMMIT_REF_SLUG', value: build.ref_slug, public: true },
+ { key: 'CI_NODE_TOTAL', value: '1', public: true },
+ { key: 'CI_BUILD_REF', value: build.sha, public: true },
+ { key: 'CI_BUILD_BEFORE_SHA', value: build.before_sha, public: true },
+ { key: 'CI_BUILD_REF_NAME', value: build.ref, public: true },
+ { key: 'CI_BUILD_REF_SLUG', value: build.ref_slug, public: true },
+ { key: 'CI_BUILD_NAME', value: 'test', public: true },
+ { key: 'CI_BUILD_STAGE', value: 'test', public: true },
+ { key: 'CI_PROJECT_ID', value: project.id.to_s, public: true },
+ { key: 'CI_PROJECT_NAME', value: project.path, public: true },
+ { key: 'CI_PROJECT_PATH', value: project.full_path, public: true },
+ { key: 'CI_PROJECT_PATH_SLUG', value: project.full_path_slug, public: true },
+ { key: 'CI_PROJECT_NAMESPACE', value: project.namespace.full_path, public: true },
+ { key: 'CI_PROJECT_URL', value: project.web_url, public: true },
+ { key: 'CI_PROJECT_VISIBILITY', value: 'private', public: true },
+ { key: 'CI_PIPELINE_IID', value: pipeline.iid.to_s, public: true },
+ { key: 'CI_CONFIG_PATH', value: pipeline.ci_yaml_file_path, public: true },
+ { key: 'CI_PIPELINE_SOURCE', value: pipeline.source, public: true },
+ { key: 'CI_COMMIT_MESSAGE', value: pipeline.git_commit_message, public: true },
+ { key: 'CI_COMMIT_TITLE', value: pipeline.git_commit_title, public: true },
+ { key: 'CI_COMMIT_DESCRIPTION', value: pipeline.git_commit_description, public: true }
+ ]
+ end
+
before do
+ build.token = 'my-token'
build.yaml_variables = []
end
it { is_expected.to include(*predefined_variables) }
+
+ context 'when yaml variables are undefined' do
+ let(:pipeline) do
+ create(:ci_pipeline, project: project,
+ sha: project.commit.id,
+ ref: project.default_branch)
+ end
+
+ before do
+ build.yaml_variables = nil
+ end
+
+ context 'use from gitlab-ci.yml' do
+ before do
+ stub_ci_pipeline_yaml_file(config)
+ end
+
+ context 'when config is not found' do
+ let(:config) { nil }
+
+ it { is_expected.to include(*predefined_variables) }
+ end
+
+ context 'when config does not have a questioned job' do
+ let(:config) do
+ YAML.dump({
+ test_other: {
+ script: 'Hello World'
+ }
+ })
+ end
+
+ it { is_expected.to include(*predefined_variables) }
+ end
+
+ context 'when config has variables' do
+ let(:config) do
+ YAML.dump({
+ test: {
+ script: 'Hello World',
+ variables: {
+ KEY: 'value'
+ }
+ }
+ })
+ end
+
+ let(:variables) do
+ [{ key: 'KEY', value: 'value', public: true }]
+ end
+
+ it { is_expected.to include(*predefined_variables) }
+ it { is_expected.to include(*variables) }
+ end
+ end
+ end
+
+ describe 'variables ordering' do
+ context 'when variables hierarchy is stubbed' do
+ let(:build_pre_var) { { key: 'build', value: 'value', public: true } }
+ let(:project_pre_var) { { key: 'project', value: 'value', public: true } }
+ let(:pipeline_pre_var) { { key: 'pipeline', value: 'value', public: true } }
+ let(:build_yaml_var) { { key: 'yaml', value: 'value', public: true } }
+
+ before do
+ allow(build).to receive(:predefined_variables) { [build_pre_var] }
+ allow(build).to receive(:yaml_variables) { [build_yaml_var] }
+ allow(build).to receive(:persisted_variables) { [] }
+
+ allow_any_instance_of(Project)
+ .to receive(:predefined_variables) { [project_pre_var] }
+
+ project.variables.create!(key: 'secret', value: 'value')
+
+ allow_any_instance_of(Ci::Pipeline)
+ .to receive(:predefined_variables) { [pipeline_pre_var] }
+ end
+
+ it 'returns variables in order depending on resource hierarchy' do
+ is_expected.to eq(
+ [build_pre_var,
+ project_pre_var,
+ pipeline_pre_var,
+ build_yaml_var,
+ { key: 'secret', value: 'value', public: false }])
+ end
+ end
+
+ context 'when build has environment and user-provided variables' do
+ let(:expected_variables) do
+ predefined_variables.map { |variable| variable.fetch(:key) } +
+ %w[YAML_VARIABLE CI_ENVIRONMENT_NAME CI_ENVIRONMENT_SLUG
+ CI_ENVIRONMENT_URL]
+ end
+
+ before do
+ create(:environment, project: build.project,
+ name: 'staging')
+
+ build.yaml_variables = [{ key: 'YAML_VARIABLE',
+ value: 'var',
+ public: true }]
+ build.environment = 'staging'
+ end
+
+ it 'matches explicit variables ordering' do
+ received_variables = subject.map { |variable| variable.fetch(:key) }
+
+ expect(received_variables).to eq expected_variables
+ end
+ end
+ end
end
context 'when build has user' do
@@ -2409,75 +2537,20 @@ describe Ci::Build do
end
before do
- pipeline_schedule.pipelines << pipeline
+ pipeline_schedule.pipelines << pipeline.reload
pipeline_schedule.reload
end
it { is_expected.to include(pipeline_schedule_variable.to_runner_variable) }
end
- context 'when yaml_variables are undefined' do
- let(:pipeline) do
- create(:ci_pipeline, project: project,
- sha: project.commit.id,
- ref: project.default_branch)
- end
-
- before do
- build.yaml_variables = nil
- end
-
- context 'use from gitlab-ci.yml' do
- before do
- stub_ci_pipeline_yaml_file(config)
- end
-
- context 'when config is not found' do
- let(:config) { nil }
-
- it { is_expected.to include(*predefined_variables) }
- end
-
- context 'when config does not have a questioned job' do
- let(:config) do
- YAML.dump({
- test_other: {
- script: 'Hello World'
- }
- })
- end
-
- it { is_expected.to include(*predefined_variables) }
- end
-
- context 'when config has variables' do
- let(:config) do
- YAML.dump({
- test: {
- script: 'Hello World',
- variables: {
- KEY: 'value'
- }
- }
- })
- end
- let(:variables) do
- [{ key: 'KEY', value: 'value', public: true }]
- end
-
- it { is_expected.to include(*predefined_variables) }
- it { is_expected.to include(*variables) }
- end
- end
- end
-
context 'when container registry is enabled' do
let(:container_registry_enabled) { true }
let(:ci_registry) do
- { key: 'CI_REGISTRY', value: 'registry.example.com', public: true }
+ { key: 'CI_REGISTRY', value: 'registry.example.com', public: true }
end
let(:ci_registry_image) do
- { key: 'CI_REGISTRY_IMAGE', value: project.container_registry_url, public: true }
+ { key: 'CI_REGISTRY_IMAGE', value: project.container_registry_url, public: true }
end
context 'and is disabled for project' do
@@ -2598,66 +2671,6 @@ describe Ci::Build do
end
end
- describe 'variables ordering' do
- context 'when variables hierarchy is stubbed' do
- let(:build_pre_var) { { key: 'build', value: 'value', public: true } }
- let(:project_pre_var) { { key: 'project', value: 'value', public: true } }
- let(:pipeline_pre_var) { { key: 'pipeline', value: 'value', public: true } }
- let(:build_yaml_var) { { key: 'yaml', value: 'value', public: true } }
-
- before do
- allow(build).to receive(:predefined_variables) { [build_pre_var] }
- allow(build).to receive(:yaml_variables) { [build_yaml_var] }
- allow(build).to receive(:persisted_variables) { [] }
-
- allow_any_instance_of(Project)
- .to receive(:predefined_variables) { [project_pre_var] }
-
- allow_any_instance_of(Project)
- .to receive(:ci_variables_for)
- .with(ref: 'master', environment: nil) do
- [create(:ci_variable, key: 'secret', value: 'value')]
- end
-
- allow_any_instance_of(Ci::Pipeline)
- .to receive(:predefined_variables) { [pipeline_pre_var] }
- end
-
- it 'returns variables in order depending on resource hierarchy' do
- is_expected.to eq(
- [build_pre_var,
- project_pre_var,
- pipeline_pre_var,
- build_yaml_var,
- { key: 'secret', value: 'value', public: false }])
- end
- end
-
- context 'when build has environment and user-provided variables' do
- let(:expected_variables) do
- predefined_variables.map { |variable| variable.fetch(:key) } +
- %w[YAML_VARIABLE CI_ENVIRONMENT_NAME CI_ENVIRONMENT_SLUG
- CI_ENVIRONMENT_URL]
- end
-
- before do
- create(:environment, project: build.project,
- name: 'staging')
-
- build.yaml_variables = [{ key: 'YAML_VARIABLE',
- value: 'var',
- public: true }]
- build.environment = 'staging'
- end
-
- it 'matches explicit variables ordering' do
- received_variables = subject.map { |variable| variable.fetch(:key) }
-
- expect(received_variables).to eq expected_variables
- end
- end
- end
-
context 'when build has not been persisted yet' do
let(:build) do
described_class.new(
diff --git a/spec/models/clusters/kubernetes_namespace_spec.rb b/spec/models/clusters/kubernetes_namespace_spec.rb
index c068c4d7739..56c98d016c9 100644
--- a/spec/models/clusters/kubernetes_namespace_spec.rb
+++ b/spec/models/clusters/kubernetes_namespace_spec.rb
@@ -45,14 +45,14 @@ RSpec.describe Clusters::KubernetesNamespace, type: :model do
end
end
- describe '#configure_predefined_variables' do
+ describe '#set_defaults' do
let(:kubernetes_namespace) { build(:cluster_kubernetes_namespace) }
let(:cluster) { kubernetes_namespace.cluster }
let(:platform) { kubernetes_namespace.platform_kubernetes }
- subject { kubernetes_namespace.configure_predefined_credentials }
+ subject { kubernetes_namespace.set_defaults }
- describe 'namespace' do
+ describe '#namespace' do
before do
platform.update_column(:namespace, namespace)
end
@@ -80,7 +80,7 @@ RSpec.describe Clusters::KubernetesNamespace, type: :model do
end
end
- describe 'service_account_name' do
+ describe '#service_account_name' do
let(:service_account_name) { "#{kubernetes_namespace.namespace}-service-account" }
it 'should set a service account name based on namespace' do
diff --git a/spec/models/commit_spec.rb b/spec/models/commit_spec.rb
index ed41ff7a0fa..2a0039a0635 100644
--- a/spec/models/commit_spec.rb
+++ b/spec/models/commit_spec.rb
@@ -72,6 +72,7 @@ describe Commit do
context 'using eager loading' do
let!(:alice) { create(:user, email: 'alice@example.com') }
let!(:bob) { create(:user, email: 'hunter2@example.com') }
+ let!(:jeff) { create(:user) }
let(:alice_commit) do
described_class.new(RepoHelpers.sample_commit, project).tap do |c|
@@ -93,7 +94,14 @@ describe Commit do
end
end
- let!(:commits) { [alice_commit, bob_commit, eve_commit] }
+ let(:jeff_commit) do
+ # The commit for Jeff uses his private commit email
+ described_class.new(RepoHelpers.sample_commit, project).tap do |c|
+ c.author_email = jeff.private_commit_email
+ end
+ end
+
+ let!(:commits) { [alice_commit, bob_commit, eve_commit, jeff_commit] }
before do
create(:email, user: bob, email: 'bob@example.com')
@@ -125,6 +133,20 @@ describe Commit do
expect(bob_commit.author).to eq(bob)
end
+ it "preloads the authors for Commits using a User's private commit Email" do
+ commits.each(&:lazy_author)
+
+ expect(jeff_commit.author).to eq(jeff)
+ end
+
+ it "preloads the authors for Commits using a User's outdated private commit Email" do
+ jeff.update!(username: 'new-username')
+
+ commits.each(&:lazy_author)
+
+ expect(jeff_commit.author).to eq(jeff)
+ end
+
it 'sets the author to Nil if an author could not be found for a Commit' do
commits.each(&:lazy_author)
diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb
index a58dc8e25e8..ad55c280399 100644
--- a/spec/models/merge_request_spec.rb
+++ b/spec/models/merge_request_spec.rb
@@ -30,48 +30,38 @@ describe MergeRequest do
end
describe '#squash_in_progress?' do
- shared_examples 'checking whether a squash is in progress' do
- let(:repo_path) do
- Gitlab::GitalyClient::StorageSettings.allow_disk_access do
- subject.source_project.repository.path
- end
- end
- let(:squash_path) { File.join(repo_path, "gitlab-worktree", "squash-#{subject.id}") }
-
- before do
- system(*%W(#{Gitlab.config.git.bin_path} -C #{repo_path} worktree add --detach #{squash_path} master))
- end
-
- it 'returns true when there is a current squash directory' do
- expect(subject.squash_in_progress?).to be_truthy
+ let(:repo_path) do
+ Gitlab::GitalyClient::StorageSettings.allow_disk_access do
+ subject.source_project.repository.path
end
+ end
+ let(:squash_path) { File.join(repo_path, "gitlab-worktree", "squash-#{subject.id}") }
- it 'returns false when there is no squash directory' do
- FileUtils.rm_rf(squash_path)
+ before do
+ system(*%W(#{Gitlab.config.git.bin_path} -C #{repo_path} worktree add --detach #{squash_path} master))
+ end
- expect(subject.squash_in_progress?).to be_falsey
- end
+ it 'returns true when there is a current squash directory' do
+ expect(subject.squash_in_progress?).to be_truthy
+ end
- it 'returns false when the squash directory has expired' do
- time = 20.minutes.ago.to_time
- File.utime(time, time, squash_path)
+ it 'returns false when there is no squash directory' do
+ FileUtils.rm_rf(squash_path)
- expect(subject.squash_in_progress?).to be_falsey
- end
+ expect(subject.squash_in_progress?).to be_falsey
+ end
- it 'returns false when the source project has been removed' do
- allow(subject).to receive(:source_project).and_return(nil)
+ it 'returns false when the squash directory has expired' do
+ time = 20.minutes.ago.to_time
+ File.utime(time, time, squash_path)
- expect(subject.squash_in_progress?).to be_falsey
- end
+ expect(subject.squash_in_progress?).to be_falsey
end
- context 'when Gitaly squash_in_progress is enabled' do
- it_behaves_like 'checking whether a squash is in progress'
- end
+ it 'returns false when the source project has been removed' do
+ allow(subject).to receive(:source_project).and_return(nil)
- context 'when Gitaly squash_in_progress is disabled', :disable_gitaly do
- it_behaves_like 'checking whether a squash is in progress'
+ expect(subject.squash_in_progress?).to be_falsey
end
end
@@ -2587,14 +2577,6 @@ describe MergeRequest do
expect(subject.rebase_in_progress?).to be_falsey
end
end
-
- context 'when Gitaly rebase_in_progress is enabled' do
- it_behaves_like 'checking whether a rebase is in progress'
- end
-
- context 'when Gitaly rebase_in_progress is enabled', :disable_gitaly do
- it_behaves_like 'checking whether a rebase is in progress'
- end
end
describe '#allow_collaboration' do
diff --git a/spec/models/project_services/chat_message/push_message_spec.rb b/spec/models/project_services/chat_message/push_message_spec.rb
index 19c2862264f..973d6bdb2a0 100644
--- a/spec/models/project_services/chat_message/push_message_spec.rb
+++ b/spec/models/project_services/chat_message/push_message_spec.rb
@@ -48,12 +48,12 @@ describe ChatMessage::PushMessage do
'test.user pushed to branch [master](http://url.com/commits/master) of [project_name](http://url.com) ([Compare changes](http://url.com/compare/before...after))')
expect(subject.attachments).to eq(
"[abcdefgh](http://url1.com): message1 - author1\n\n[12345678](http://url2.com): message2 - author2")
- expect(subject.activity).to eq({
- title: 'test.user pushed to branch',
+ expect(subject.activity).to eq(
+ title: 'test.user pushed to branch [master](http://url.com/commits/master)',
subtitle: 'in [project_name](http://url.com)',
text: '[Compare changes](http://url.com/compare/before...after)',
image: 'http://someavatar.com'
- })
+ )
end
end
end
@@ -89,12 +89,53 @@ describe ChatMessage::PushMessage do
expect(subject.pretext).to eq(
'test.user pushed new tag [new_tag](http://url.com/commits/new_tag) to [project_name](http://url.com)')
expect(subject.attachments).to be_empty
- expect(subject.activity).to eq({
- title: 'test.user created tag',
+ expect(subject.activity).to eq(
+ title: 'test.user pushed new tag [new_tag](http://url.com/commits/new_tag)',
subtitle: 'in [project_name](http://url.com)',
text: '[Compare changes](http://url.com/compare/0000000000000000000000000000000000000000...after)',
image: 'http://someavatar.com'
- })
+ )
+ end
+ end
+ end
+
+ context 'removed tag' do
+ let(:args) do
+ {
+ after: Gitlab::Git::BLANK_SHA,
+ before: 'before',
+ project_name: 'project_name',
+ ref: 'refs/tags/new_tag',
+ user_name: 'test.user',
+ user_avatar: 'http://someavatar.com',
+ project_url: 'http://url.com'
+ }
+ end
+
+ context 'without markdown' do
+ it 'returns a message regarding removal of tags' do
+ expect(subject.pretext).to eq('test.user removed tag ' \
+ 'new_tag from ' \
+ '<http://url.com|project_name>')
+ expect(subject.attachments).to be_empty
+ end
+ end
+
+ context 'with markdown' do
+ before do
+ args[:markdown] = true
+ end
+
+ it 'returns a message regarding removal of tags' do
+ expect(subject.pretext).to eq(
+ 'test.user removed tag new_tag from [project_name](http://url.com)')
+ expect(subject.attachments).to be_empty
+ expect(subject.activity).to eq(
+ title: 'test.user removed tag new_tag',
+ subtitle: 'in [project_name](http://url.com)',
+ text: '[Compare changes](http://url.com/compare/before...0000000000000000000000000000000000000000)',
+ image: 'http://someavatar.com'
+ )
end
end
end
@@ -122,12 +163,12 @@ describe ChatMessage::PushMessage do
expect(subject.pretext).to eq(
'test.user pushed new branch [master](http://url.com/commits/master) to [project_name](http://url.com)')
expect(subject.attachments).to be_empty
- expect(subject.activity).to eq({
- title: 'test.user created branch',
+ expect(subject.activity).to eq(
+ title: 'test.user pushed new branch [master](http://url.com/commits/master)',
subtitle: 'in [project_name](http://url.com)',
text: '[Compare changes](http://url.com/compare/0000000000000000000000000000000000000000...after)',
image: 'http://someavatar.com'
- })
+ )
end
end
end
@@ -154,12 +195,12 @@ describe ChatMessage::PushMessage do
expect(subject.pretext).to eq(
'test.user removed branch master from [project_name](http://url.com)')
expect(subject.attachments).to be_empty
- expect(subject.activity).to eq({
- title: 'test.user removed branch',
+ expect(subject.activity).to eq(
+ title: 'test.user removed branch master',
subtitle: 'in [project_name](http://url.com)',
text: '[Compare changes](http://url.com/compare/before...0000000000000000000000000000000000000000)',
image: 'http://someavatar.com'
- })
+ )
end
end
end
diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb
index bdff68cee8b..51278836604 100644
--- a/spec/models/project_spec.rb
+++ b/spec/models/project_spec.rb
@@ -3087,6 +3087,14 @@ describe Project do
it 'does not flag as read-only' do
expect { project.migrate_to_hashed_storage! }.not_to change { project.repository_read_only }
end
+
+ context 'when partially migrated' do
+ it 'returns true' do
+ project = create(:project, storage_version: 1, skip_disk_validation: true)
+
+ expect(project.migrate_to_hashed_storage!).to be_truthy
+ end
+ end
end
end
diff --git a/spec/models/project_wiki_spec.rb b/spec/models/project_wiki_spec.rb
index cc5e34782ec..48a43801b9f 100644
--- a/spec/models/project_wiki_spec.rb
+++ b/spec/models/project_wiki_spec.rb
@@ -130,63 +130,53 @@ describe ProjectWiki do
end
describe "#find_page" do
- shared_examples 'finding a wiki page' do
- before do
- create_page("index page", "This is an awesome Gollum Wiki")
- end
-
- after do
- subject.pages.each { |page| destroy_page(page.page) }
- end
+ before do
+ create_page("index page", "This is an awesome Gollum Wiki")
+ end
- it "returns the latest version of the page if it exists" do
- page = subject.find_page("index page")
- expect(page.title).to eq("index page")
- end
+ after do
+ subject.pages.each { |page| destroy_page(page.page) }
+ end
- it "returns nil if the page does not exist" do
- expect(subject.find_page("non-existent")).to eq(nil)
- end
+ it "returns the latest version of the page if it exists" do
+ page = subject.find_page("index page")
+ expect(page.title).to eq("index page")
+ end
- it "can find a page by slug" do
- page = subject.find_page("index-page")
- expect(page.title).to eq("index page")
- end
+ it "returns nil if the page does not exist" do
+ expect(subject.find_page("non-existent")).to eq(nil)
+ end
- it "returns a WikiPage instance" do
- page = subject.find_page("index page")
- expect(page).to be_a WikiPage
- end
+ it "can find a page by slug" do
+ page = subject.find_page("index-page")
+ expect(page.title).to eq("index page")
+ end
- context 'pages with multibyte-character title' do
- before do
- create_page("autre pagé", "C'est un génial Gollum Wiki")
- end
+ it "returns a WikiPage instance" do
+ page = subject.find_page("index page")
+ expect(page).to be_a WikiPage
+ end
- it "can find a page by slug" do
- page = subject.find_page("autre pagé")
- expect(page.title).to eq("autre pagé")
- end
+ context 'pages with multibyte-character title' do
+ before do
+ create_page("autre pagé", "C'est un génial Gollum Wiki")
end
- context 'pages with invalidly-encoded content' do
- before do
- create_page("encoding is fun", "f\xFCr".b)
- end
-
- it "can find the page" do
- page = subject.find_page("encoding is fun")
- expect(page.content).to eq("fr")
- end
+ it "can find a page by slug" do
+ page = subject.find_page("autre pagé")
+ expect(page.title).to eq("autre pagé")
end
end
- context 'when Gitaly wiki_find_page is enabled' do
- it_behaves_like 'finding a wiki page'
- end
+ context 'pages with invalidly-encoded content' do
+ before do
+ create_page("encoding is fun", "f\xFCr".b)
+ end
- context 'when Gitaly wiki_find_page is disabled', :skip_gitaly_mock do
- it_behaves_like 'finding a wiki page'
+ it "can find the page" do
+ page = subject.find_page("encoding is fun")
+ expect(page.content).to eq("fr")
+ end
end
end
@@ -207,100 +197,80 @@ describe ProjectWiki do
end
describe '#find_file' do
- shared_examples 'finding a wiki file' do
- let(:image) { File.open(Rails.root.join('spec', 'fixtures', 'big-image.png')) }
-
- before do
- subject.wiki # Make sure the wiki repo exists
-
- repo_path = Gitlab::GitalyClient::StorageSettings.allow_disk_access do
- subject.repository.path_to_repo
- end
-
- BareRepoOperations.new(repo_path).commit_file(image, 'image.png')
- end
+ let(:image) { File.open(Rails.root.join('spec', 'fixtures', 'big-image.png')) }
- it 'returns the latest version of the file if it exists' do
- file = subject.find_file('image.png')
- expect(file.mime_type).to eq('image/png')
- end
+ before do
+ subject.wiki # Make sure the wiki repo exists
- it 'returns nil if the page does not exist' do
- expect(subject.find_file('non-existent')).to eq(nil)
+ repo_path = Gitlab::GitalyClient::StorageSettings.allow_disk_access do
+ subject.repository.path_to_repo
end
- it 'returns a Gitlab::Git::WikiFile instance' do
- file = subject.find_file('image.png')
- expect(file).to be_a Gitlab::Git::WikiFile
- end
+ BareRepoOperations.new(repo_path).commit_file(image, 'image.png')
+ end
- it 'returns the whole file' do
- file = subject.find_file('image.png')
- image.rewind
+ it 'returns the latest version of the file if it exists' do
+ file = subject.find_file('image.png')
+ expect(file.mime_type).to eq('image/png')
+ end
- expect(file.raw_data.b).to eq(image.read.b)
- end
+ it 'returns nil if the page does not exist' do
+ expect(subject.find_file('non-existent')).to eq(nil)
end
- context 'when Gitaly wiki_find_file is enabled' do
- it_behaves_like 'finding a wiki file'
+ it 'returns a Gitlab::Git::WikiFile instance' do
+ file = subject.find_file('image.png')
+ expect(file).to be_a Gitlab::Git::WikiFile
end
- context 'when Gitaly wiki_find_file is disabled', :skip_gitaly_mock do
- it_behaves_like 'finding a wiki file'
+ it 'returns the whole file' do
+ file = subject.find_file('image.png')
+ image.rewind
+
+ expect(file.raw_data.b).to eq(image.read.b)
end
end
describe "#create_page" do
- shared_examples 'creating a wiki page' do
- after do
- destroy_page(subject.pages.first.page)
- end
-
- it "creates a new wiki page" do
- expect(subject.create_page("test page", "this is content")).not_to eq(false)
- expect(subject.pages.count).to eq(1)
- end
-
- it "returns false when a duplicate page exists" do
- subject.create_page("test page", "content")
- expect(subject.create_page("test page", "content")).to eq(false)
- end
-
- it "stores an error message when a duplicate page exists" do
- 2.times { subject.create_page("test page", "content") }
- expect(subject.error_message).to match(/Duplicate page:/)
- end
+ after do
+ destroy_page(subject.pages.first.page)
+ end
- it "sets the correct commit message" do
- subject.create_page("test page", "some content", :markdown, "commit message")
- expect(subject.pages.first.page.version.message).to eq("commit message")
- end
+ it "creates a new wiki page" do
+ expect(subject.create_page("test page", "this is content")).not_to eq(false)
+ expect(subject.pages.count).to eq(1)
+ end
- it 'sets the correct commit email' do
- subject.create_page('test page', 'content')
+ it "returns false when a duplicate page exists" do
+ subject.create_page("test page", "content")
+ expect(subject.create_page("test page", "content")).to eq(false)
+ end
- expect(user.commit_email).not_to eq(user.email)
- expect(commit.author_email).to eq(user.commit_email)
- expect(commit.committer_email).to eq(user.commit_email)
- end
+ it "stores an error message when a duplicate page exists" do
+ 2.times { subject.create_page("test page", "content") }
+ expect(subject.error_message).to match(/Duplicate page:/)
+ end
- it 'updates project activity' do
- subject.create_page('Test Page', 'This is content')
+ it "sets the correct commit message" do
+ subject.create_page("test page", "some content", :markdown, "commit message")
+ expect(subject.pages.first.page.version.message).to eq("commit message")
+ end
- project.reload
+ it 'sets the correct commit email' do
+ subject.create_page('test page', 'content')
- expect(project.last_activity_at).to be_within(1.minute).of(Time.now)
- expect(project.last_repository_updated_at).to be_within(1.minute).of(Time.now)
- end
+ expect(user.commit_email).not_to eq(user.email)
+ expect(commit.author_email).to eq(user.commit_email)
+ expect(commit.committer_email).to eq(user.commit_email)
end
- context 'when Gitaly wiki_write_page is enabled' do
- it_behaves_like 'creating a wiki page'
- end
+ it 'updates project activity' do
+ subject.create_page('Test Page', 'This is content')
- context 'when Gitaly wiki_write_page is disabled', :skip_gitaly_mock do
- it_behaves_like 'creating a wiki page'
+ project.reload
+
+ expect(project.last_activity_at).to be_within(1.minute).of(Time.now)
+ expect(project.last_repository_updated_at).to be_within(1.minute).of(Time.now)
end
end
@@ -351,41 +321,31 @@ describe ProjectWiki do
end
describe "#delete_page" do
- shared_examples 'deleting a wiki page' do
- before do
- create_page("index", "some content")
- @page = subject.wiki.page(title: "index")
- end
-
- it "deletes the page" do
- subject.delete_page(@page)
- expect(subject.pages.count).to eq(0)
- end
-
- it 'sets the correct commit email' do
- subject.delete_page(@page)
-
- expect(user.commit_email).not_to eq(user.email)
- expect(commit.author_email).to eq(user.commit_email)
- expect(commit.committer_email).to eq(user.commit_email)
- end
+ before do
+ create_page("index", "some content")
+ @page = subject.wiki.page(title: "index")
+ end
- it 'updates project activity' do
- subject.delete_page(@page)
+ it "deletes the page" do
+ subject.delete_page(@page)
+ expect(subject.pages.count).to eq(0)
+ end
- project.reload
+ it 'sets the correct commit email' do
+ subject.delete_page(@page)
- expect(project.last_activity_at).to be_within(1.minute).of(Time.now)
- expect(project.last_repository_updated_at).to be_within(1.minute).of(Time.now)
- end
+ expect(user.commit_email).not_to eq(user.email)
+ expect(commit.author_email).to eq(user.commit_email)
+ expect(commit.committer_email).to eq(user.commit_email)
end
- context 'when Gitaly wiki_delete_page is enabled' do
- it_behaves_like 'deleting a wiki page'
- end
+ it 'updates project activity' do
+ subject.delete_page(@page)
+
+ project.reload
- context 'when Gitaly wiki_delete_page is disabled', :skip_gitaly_mock do
- it_behaves_like 'deleting a wiki page'
+ expect(project.last_activity_at).to be_within(1.minute).of(Time.now)
+ expect(project.last_repository_updated_at).to be_within(1.minute).of(Time.now)
end
end
diff --git a/spec/models/repository_spec.rb b/spec/models/repository_spec.rb
index 56edb0fd6da..187283b284b 100644
--- a/spec/models/repository_spec.rb
+++ b/spec/models/repository_spec.rb
@@ -38,49 +38,29 @@ describe Repository do
end
describe '#branch_names_contains' do
- shared_examples '#branch_names_contains' do
- set(:project) { create(:project, :repository) }
- let(:repository) { project.repository }
+ set(:project) { create(:project, :repository) }
+ let(:repository) { project.repository }
- subject { repository.branch_names_contains(sample_commit.id) }
+ subject { repository.branch_names_contains(sample_commit.id) }
- it { is_expected.to include('master') }
- it { is_expected.not_to include('feature') }
- it { is_expected.not_to include('fix') }
+ it { is_expected.to include('master') }
+ it { is_expected.not_to include('feature') }
+ it { is_expected.not_to include('fix') }
- describe 'when storage is broken', :broken_storage do
- it 'should raise a storage error' do
- expect_to_raise_storage_error do
- broken_repository.branch_names_contains(sample_commit.id)
- end
+ describe 'when storage is broken', :broken_storage do
+ it 'should raise a storage error' do
+ expect_to_raise_storage_error do
+ broken_repository.branch_names_contains(sample_commit.id)
end
end
end
-
- context 'when gitaly is enabled' do
- it_behaves_like '#branch_names_contains'
- end
-
- context 'when gitaly is disabled', :skip_gitaly_mock do
- it_behaves_like '#branch_names_contains'
- end
end
describe '#tag_names_contains' do
- shared_examples '#tag_names_contains' do
- subject { repository.tag_names_contains(sample_commit.id) }
-
- it { is_expected.to include('v1.1.0') }
- it { is_expected.not_to include('v1.0.0') }
- end
-
- context 'when gitaly is enabled' do
- it_behaves_like '#tag_names_contains'
- end
+ subject { repository.tag_names_contains(sample_commit.id) }
- context 'when gitaly is enabled', :skip_gitaly_mock do
- it_behaves_like '#tag_names_contains'
- end
+ it { is_expected.to include('v1.1.0') }
+ it { is_expected.not_to include('v1.0.0') }
end
describe 'tags_sorted_by' do
@@ -238,61 +218,41 @@ describe Repository do
end
describe '#last_commit_for_path' do
- shared_examples 'getting last commit for path' do
- subject { repository.last_commit_for_path(sample_commit.id, '.gitignore').id }
+ subject { repository.last_commit_for_path(sample_commit.id, '.gitignore').id }
- it { is_expected.to eq('c1acaa58bbcbc3eafe538cb8274ba387047b69f8') }
+ it { is_expected.to eq('c1acaa58bbcbc3eafe538cb8274ba387047b69f8') }
- describe 'when storage is broken', :broken_storage do
- it 'should raise a storage error' do
- expect_to_raise_storage_error do
- broken_repository.last_commit_id_for_path(sample_commit.id, '.gitignore')
- end
+ describe 'when storage is broken', :broken_storage do
+ it 'should raise a storage error' do
+ expect_to_raise_storage_error do
+ broken_repository.last_commit_id_for_path(sample_commit.id, '.gitignore')
end
end
end
-
- context 'when Gitaly feature last_commit_for_path is enabled' do
- it_behaves_like 'getting last commit for path'
- end
-
- context 'when Gitaly feature last_commit_for_path is disabled', :skip_gitaly_mock do
- it_behaves_like 'getting last commit for path'
- end
end
describe '#last_commit_id_for_path' do
- shared_examples 'getting last commit ID for path' do
- subject { repository.last_commit_id_for_path(sample_commit.id, '.gitignore') }
+ subject { repository.last_commit_id_for_path(sample_commit.id, '.gitignore') }
- it "returns last commit id for a given path" do
- is_expected.to eq('c1acaa58bbcbc3eafe538cb8274ba387047b69f8')
- end
+ it "returns last commit id for a given path" do
+ is_expected.to eq('c1acaa58bbcbc3eafe538cb8274ba387047b69f8')
+ end
- it "caches last commit id for a given path" do
- cache = repository.send(:cache)
- key = "last_commit_id_for_path:#{sample_commit.id}:#{Digest::SHA1.hexdigest('.gitignore')}"
+ it "caches last commit id for a given path" do
+ cache = repository.send(:cache)
+ key = "last_commit_id_for_path:#{sample_commit.id}:#{Digest::SHA1.hexdigest('.gitignore')}"
- expect(cache).to receive(:fetch).with(key).and_return('c1acaa5')
- is_expected.to eq('c1acaa5')
- end
+ expect(cache).to receive(:fetch).with(key).and_return('c1acaa5')
+ is_expected.to eq('c1acaa5')
+ end
- describe 'when storage is broken', :broken_storage do
- it 'should raise a storage error' do
- expect_to_raise_storage_error do
- broken_repository.last_commit_for_path(sample_commit.id, '.gitignore').id
- end
+ describe 'when storage is broken', :broken_storage do
+ it 'should raise a storage error' do
+ expect_to_raise_storage_error do
+ broken_repository.last_commit_for_path(sample_commit.id, '.gitignore').id
end
end
end
-
- context 'when Gitaly feature last_commit_for_path is enabled' do
- it_behaves_like 'getting last commit ID for path'
- end
-
- context 'when Gitaly feature last_commit_for_path is disabled', :skip_gitaly_mock do
- it_behaves_like 'getting last commit ID for path'
- end
end
describe '#commits' do
@@ -374,78 +334,57 @@ describe Repository do
describe '#commits_by' do
set(:project) { create(:project, :repository) }
+ let(:oids) { TestEnv::BRANCH_SHA.values }
- shared_examples 'batch commits fetching' do
- let(:oids) { TestEnv::BRANCH_SHA.values }
+ subject { project.repository.commits_by(oids: oids) }
- subject { project.repository.commits_by(oids: oids) }
+ it 'finds each commit' do
+ expect(subject).not_to include(nil)
+ expect(subject.size).to eq(oids.size)
+ end
- it 'finds each commit' do
- expect(subject).not_to include(nil)
- expect(subject.size).to eq(oids.size)
- end
+ it 'returns only Commit instances' do
+ expect(subject).to all( be_a(Commit) )
+ end
- it 'returns only Commit instances' do
- expect(subject).to all( be_a(Commit) )
+ context 'when some commits are not found ' do
+ let(:oids) do
+ ['deadbeef'] + TestEnv::BRANCH_SHA.values.first(10)
end
- context 'when some commits are not found ' do
- let(:oids) do
- ['deadbeef'] + TestEnv::BRANCH_SHA.values.first(10)
- end
-
- it 'returns only found commits' do
- expect(subject).not_to include(nil)
- expect(subject.size).to eq(10)
- end
+ it 'returns only found commits' do
+ expect(subject).not_to include(nil)
+ expect(subject.size).to eq(10)
end
+ end
- context 'when no oids are passed' do
- let(:oids) { [] }
+ context 'when no oids are passed' do
+ let(:oids) { [] }
- it 'does not call #batch_by_oid' do
- expect(Gitlab::Git::Commit).not_to receive(:batch_by_oid)
+ it 'does not call #batch_by_oid' do
+ expect(Gitlab::Git::Commit).not_to receive(:batch_by_oid)
- subject
- end
+ subject
end
end
-
- context 'when Gitaly list_commits_by_oid is enabled' do
- it_behaves_like 'batch commits fetching'
- end
-
- context 'when Gitaly list_commits_by_oid is enabled', :disable_gitaly do
- it_behaves_like 'batch commits fetching'
- end
end
describe '#find_commits_by_message' do
- shared_examples 'finding commits by message' do
- it 'returns commits with messages containing a given string' do
- commit_ids = repository.find_commits_by_message('submodule').map(&:id)
-
- expect(commit_ids).to include(
- '5937ac0a7beb003549fc5fd26fc247adbce4a52e',
- '6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9',
- 'cfe32cf61b73a0d5e9f13e774abde7ff789b1660'
- )
- expect(commit_ids).not_to include('913c66a37b4a45b9769037c55c2d238bd0942d2e')
- end
-
- it 'is case insensitive' do
- commit_ids = repository.find_commits_by_message('SUBMODULE').map(&:id)
+ it 'returns commits with messages containing a given string' do
+ commit_ids = repository.find_commits_by_message('submodule').map(&:id)
- expect(commit_ids).to include('5937ac0a7beb003549fc5fd26fc247adbce4a52e')
- end
+ expect(commit_ids).to include(
+ '5937ac0a7beb003549fc5fd26fc247adbce4a52e',
+ '6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9',
+ 'cfe32cf61b73a0d5e9f13e774abde7ff789b1660'
+ )
+ expect(commit_ids).not_to include('913c66a37b4a45b9769037c55c2d238bd0942d2e')
end
- context 'when Gitaly commits_by_message feature is enabled' do
- it_behaves_like 'finding commits by message'
- end
+ it 'is case insensitive' do
+ commit_ids = repository.find_commits_by_message('SUBMODULE').map(&:id)
- context 'when Gitaly commits_by_message feature is disabled', :skip_gitaly_mock do
- it_behaves_like 'finding commits by message'
+ expect(commit_ids).to include('5937ac0a7beb003549fc5fd26fc247adbce4a52e')
end
describe 'when storage is broken', :broken_storage do
@@ -1328,34 +1267,23 @@ describe Repository do
describe '#merge' do
let(:merge_request) { create(:merge_request, source_branch: 'feature', target_branch: 'master', source_project: project) }
-
let(:message) { 'Test \r\n\r\n message' }
- shared_examples '#merge' do
- it 'merges the code and returns the commit id' do
- expect(merge_commit).to be_present
- expect(repository.blob_at(merge_commit.id, 'files/ruby/feature.rb')).to be_present
- end
-
- it 'sets the `in_progress_merge_commit_sha` flag for the given merge request' do
- merge_commit_id = merge(repository, user, merge_request, message)
-
- expect(merge_request.in_progress_merge_commit_sha).to eq(merge_commit_id)
- end
+ it 'merges the code and returns the commit id' do
+ expect(merge_commit).to be_present
+ expect(repository.blob_at(merge_commit.id, 'files/ruby/feature.rb')).to be_present
+ end
- it 'removes carriage returns from commit message' do
- merge_commit_id = merge(repository, user, merge_request, message)
+ it 'sets the `in_progress_merge_commit_sha` flag for the given merge request' do
+ merge_commit_id = merge(repository, user, merge_request, message)
- expect(repository.commit(merge_commit_id).message).to eq(message.delete("\r"))
- end
+ expect(merge_request.in_progress_merge_commit_sha).to eq(merge_commit_id)
end
- context 'with gitaly' do
- it_behaves_like '#merge'
- end
+ it 'removes carriage returns from commit message' do
+ merge_commit_id = merge(repository, user, merge_request, message)
- context 'without gitaly', :skip_gitaly_mock do
- it_behaves_like '#merge'
+ expect(repository.commit(merge_commit_id).message).to eq(message.delete("\r"))
end
def merge(repository, user, merge_request, message)
@@ -1392,98 +1320,78 @@ describe Repository do
end
describe '#revert' do
- shared_examples 'reverting a commit' do
- let(:new_image_commit) { repository.commit('33f3729a45c02fc67d00adb1b8bca394b0e761d9') }
- let(:update_image_commit) { repository.commit('2f63565e7aac07bcdadb654e253078b727143ec4') }
- let(:message) { 'revert message' }
-
- context 'when there is a conflict' do
- it 'raises an error' do
- expect { repository.revert(user, new_image_commit, 'master', message) }.to raise_error(Gitlab::Git::Repository::CreateTreeError)
- end
- end
+ let(:new_image_commit) { repository.commit('33f3729a45c02fc67d00adb1b8bca394b0e761d9') }
+ let(:update_image_commit) { repository.commit('2f63565e7aac07bcdadb654e253078b727143ec4') }
+ let(:message) { 'revert message' }
- context 'when commit was already reverted' do
- it 'raises an error' do
- repository.revert(user, update_image_commit, 'master', message)
-
- expect { repository.revert(user, update_image_commit, 'master', message) }.to raise_error(Gitlab::Git::Repository::CreateTreeError)
- end
- end
-
- context 'when commit can be reverted' do
- it 'reverts the changes' do
- expect(repository.revert(user, update_image_commit, 'master', message)).to be_truthy
- end
+ context 'when there is a conflict' do
+ it 'raises an error' do
+ expect { repository.revert(user, new_image_commit, 'master', message) }.to raise_error(Gitlab::Git::Repository::CreateTreeError)
end
+ end
- context 'reverting a merge commit' do
- it 'reverts the changes' do
- merge_commit
- expect(repository.blob_at_branch('master', 'files/ruby/feature.rb')).to be_present
+ context 'when commit was already reverted' do
+ it 'raises an error' do
+ repository.revert(user, update_image_commit, 'master', message)
- repository.revert(user, merge_commit, 'master', message)
- expect(repository.blob_at_branch('master', 'files/ruby/feature.rb')).not_to be_present
- end
+ expect { repository.revert(user, update_image_commit, 'master', message) }.to raise_error(Gitlab::Git::Repository::CreateTreeError)
end
end
- context 'when Gitaly revert feature is enabled' do
- it_behaves_like 'reverting a commit'
+ context 'when commit can be reverted' do
+ it 'reverts the changes' do
+ expect(repository.revert(user, update_image_commit, 'master', message)).to be_truthy
+ end
end
- context 'when Gitaly revert feature is disabled', :disable_gitaly do
- it_behaves_like 'reverting a commit'
+ context 'reverting a merge commit' do
+ it 'reverts the changes' do
+ merge_commit
+ expect(repository.blob_at_branch('master', 'files/ruby/feature.rb')).to be_present
+
+ repository.revert(user, merge_commit, 'master', message)
+ expect(repository.blob_at_branch('master', 'files/ruby/feature.rb')).not_to be_present
+ end
end
end
describe '#cherry_pick' do
- shared_examples 'cherry-picking a commit' do
- let(:conflict_commit) { repository.commit('c642fe9b8b9f28f9225d7ea953fe14e74748d53b') }
- let(:pickable_commit) { repository.commit('7d3b0f7cff5f37573aea97cebfd5692ea1689924') }
- let(:pickable_merge) { repository.commit('e56497bb5f03a90a51293fc6d516788730953899') }
- let(:message) { 'cherry-pick message' }
-
- context 'when there is a conflict' do
- it 'raises an error' do
- expect { repository.cherry_pick(user, conflict_commit, 'master', message) }.to raise_error(Gitlab::Git::Repository::CreateTreeError)
- end
+ let(:conflict_commit) { repository.commit('c642fe9b8b9f28f9225d7ea953fe14e74748d53b') }
+ let(:pickable_commit) { repository.commit('7d3b0f7cff5f37573aea97cebfd5692ea1689924') }
+ let(:pickable_merge) { repository.commit('e56497bb5f03a90a51293fc6d516788730953899') }
+ let(:message) { 'cherry-pick message' }
+
+ context 'when there is a conflict' do
+ it 'raises an error' do
+ expect { repository.cherry_pick(user, conflict_commit, 'master', message) }.to raise_error(Gitlab::Git::Repository::CreateTreeError)
end
+ end
- context 'when commit was already cherry-picked' do
- it 'raises an error' do
- repository.cherry_pick(user, pickable_commit, 'master', message)
+ context 'when commit was already cherry-picked' do
+ it 'raises an error' do
+ repository.cherry_pick(user, pickable_commit, 'master', message)
- expect { repository.cherry_pick(user, pickable_commit, 'master', message) }.to raise_error(Gitlab::Git::Repository::CreateTreeError)
- end
+ expect { repository.cherry_pick(user, pickable_commit, 'master', message) }.to raise_error(Gitlab::Git::Repository::CreateTreeError)
end
+ end
- context 'when commit can be cherry-picked' do
- it 'cherry-picks the changes' do
- expect(repository.cherry_pick(user, pickable_commit, 'master', message)).to be_truthy
- end
+ context 'when commit can be cherry-picked' do
+ it 'cherry-picks the changes' do
+ expect(repository.cherry_pick(user, pickable_commit, 'master', message)).to be_truthy
end
+ end
- context 'cherry-picking a merge commit' do
- it 'cherry-picks the changes' do
- expect(repository.blob_at_branch('improve/awesome', 'foo/bar/.gitkeep')).to be_nil
+ context 'cherry-picking a merge commit' do
+ it 'cherry-picks the changes' do
+ expect(repository.blob_at_branch('improve/awesome', 'foo/bar/.gitkeep')).to be_nil
- cherry_pick_commit_sha = repository.cherry_pick(user, pickable_merge, 'improve/awesome', message)
- cherry_pick_commit_message = project.commit(cherry_pick_commit_sha).message
+ cherry_pick_commit_sha = repository.cherry_pick(user, pickable_merge, 'improve/awesome', message)
+ cherry_pick_commit_message = project.commit(cherry_pick_commit_sha).message
- expect(repository.blob_at_branch('improve/awesome', 'foo/bar/.gitkeep')).not_to be_nil
- expect(cherry_pick_commit_message).to eq(message)
- end
+ expect(repository.blob_at_branch('improve/awesome', 'foo/bar/.gitkeep')).not_to be_nil
+ expect(cherry_pick_commit_message).to eq(message)
end
end
-
- context 'when Gitaly cherry_pick feature is enabled' do
- it_behaves_like 'cherry-picking a commit'
- end
-
- context 'when Gitaly cherry_pick feature is disabled', :disable_gitaly do
- it_behaves_like 'cherry-picking a commit'
- end
end
describe '#before_delete' do
@@ -2190,33 +2098,23 @@ describe Repository do
let(:commit) { repository.commit }
let(:ancestor) { commit.parents.first }
- shared_examples '#ancestor?' do
- it 'it is an ancestor' do
- expect(repository.ancestor?(ancestor.id, commit.id)).to eq(true)
- end
-
- it 'it is not an ancestor' do
- expect(repository.ancestor?(commit.id, ancestor.id)).to eq(false)
- end
-
- it 'returns false on nil-values' do
- expect(repository.ancestor?(nil, commit.id)).to eq(false)
- expect(repository.ancestor?(ancestor.id, nil)).to eq(false)
- expect(repository.ancestor?(nil, nil)).to eq(false)
- end
+ it 'it is an ancestor' do
+ expect(repository.ancestor?(ancestor.id, commit.id)).to eq(true)
+ end
- it 'returns false for invalid commit IDs' do
- expect(repository.ancestor?(commit.id, Gitlab::Git::BLANK_SHA)).to eq(false)
- expect(repository.ancestor?( Gitlab::Git::BLANK_SHA, commit.id)).to eq(false)
- end
+ it 'it is not an ancestor' do
+ expect(repository.ancestor?(commit.id, ancestor.id)).to eq(false)
end
- context 'with Gitaly enabled' do
- it_behaves_like('#ancestor?')
+ it 'returns false on nil-values' do
+ expect(repository.ancestor?(nil, commit.id)).to eq(false)
+ expect(repository.ancestor?(ancestor.id, nil)).to eq(false)
+ expect(repository.ancestor?(nil, nil)).to eq(false)
end
- context 'with Gitaly disabled', :skip_gitaly_mock do
- it_behaves_like('#ancestor?')
+ it 'returns false for invalid commit IDs' do
+ expect(repository.ancestor?(commit.id, Gitlab::Git::BLANK_SHA)).to eq(false)
+ expect(repository.ancestor?( Gitlab::Git::BLANK_SHA, commit.id)).to eq(false)
end
end
diff --git a/spec/models/todo_spec.rb b/spec/models/todo_spec.rb
index 2c01578aaca..82ff2a002e0 100644
--- a/spec/models/todo_spec.rb
+++ b/spec/models/todo_spec.rb
@@ -226,7 +226,7 @@ describe Todo do
create(:todo, target: create(:merge_request))
- expect(described_class.for_type(Issue)).to eq([todo])
+ expect(described_class.for_type(Issue.name)).to eq([todo])
end
end
diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb
index 0ac5bd666ae..733c1c49f08 100644
--- a/spec/models/user_spec.rb
+++ b/spec/models/user_spec.rb
@@ -1174,6 +1174,22 @@ describe User do
expect(described_class.by_any_email(user.email, confirmed: true)).to eq([user])
end
+
+ it 'finds user through a private commit email' do
+ user = create(:user)
+ private_email = user.private_commit_email
+
+ expect(described_class.by_any_email(private_email)).to eq([user])
+ expect(described_class.by_any_email(private_email, confirmed: true)).to eq([user])
+ end
+
+ it 'finds user through a private commit email in an array' do
+ user = create(:user)
+ private_email = user.private_commit_email
+
+ expect(described_class.by_any_email([private_email])).to eq([user])
+ expect(described_class.by_any_email([private_email], confirmed: true)).to eq([user])
+ end
end
describe '.search' do
@@ -1501,7 +1517,12 @@ describe User do
email_unconfirmed = create :email, user: user
user.reload
- expect(user.all_emails).to match_array([user.email, email_unconfirmed.email, email_confirmed.email])
+ expect(user.all_emails).to contain_exactly(
+ user.email,
+ user.private_commit_email,
+ email_unconfirmed.email,
+ email_confirmed.email
+ )
end
end
@@ -1512,7 +1533,11 @@ describe User do
email_confirmed = create :email, user: user, confirmed_at: Time.now
create :email, user: user
- expect(user.verified_emails).to match_array([user.email, user.private_commit_email, email_confirmed.email])
+ expect(user.verified_emails).to contain_exactly(
+ user.email,
+ user.private_commit_email,
+ email_confirmed.email
+ )
end
end
@@ -1532,6 +1557,14 @@ describe User do
expect(user.verified_email?(user.private_commit_email)).to be_truthy
end
+ it 'returns true for an outdated private commit email' do
+ old_email = user.private_commit_email
+
+ user.update!(username: 'changed-username')
+
+ expect(user.verified_email?(old_email)).to be_truthy
+ end
+
it 'returns false when the email is not verified/confirmed' do
email_unconfirmed = create :email, user: user
user.reload
diff --git a/spec/models/wiki_page_spec.rb b/spec/models/wiki_page_spec.rb
index b87a2d871e5..cba22b2cc4e 100644
--- a/spec/models/wiki_page_spec.rb
+++ b/spec/models/wiki_page_spec.rb
@@ -200,180 +200,160 @@ describe WikiPage do
end
describe '#create' do
- shared_examples 'create method' do
- context 'with valid attributes' do
- it 'raises an error if a page with the same path already exists' do
- create_page('New Page', 'content')
- create_page('foo/bar', 'content')
- expect { create_page('New Page', 'other content') }.to raise_error Gitlab::Git::Wiki::DuplicatePageError
- expect { create_page('foo/bar', 'other content') }.to raise_error Gitlab::Git::Wiki::DuplicatePageError
-
- destroy_page('New Page')
- destroy_page('bar', 'foo')
- end
+ context 'with valid attributes' do
+ it 'raises an error if a page with the same path already exists' do
+ create_page('New Page', 'content')
+ create_page('foo/bar', 'content')
+ expect { create_page('New Page', 'other content') }.to raise_error Gitlab::Git::Wiki::DuplicatePageError
+ expect { create_page('foo/bar', 'other content') }.to raise_error Gitlab::Git::Wiki::DuplicatePageError
- it 'if the title is preceded by a / it is removed' do
- create_page('/New Page', 'content')
+ destroy_page('New Page')
+ destroy_page('bar', 'foo')
+ end
- expect(wiki.find_page('New Page')).not_to be_nil
+ it 'if the title is preceded by a / it is removed' do
+ create_page('/New Page', 'content')
- destroy_page('New Page')
- end
+ expect(wiki.find_page('New Page')).not_to be_nil
+
+ destroy_page('New Page')
end
end
+ end
- context 'when Gitaly is enabled' do
- it_behaves_like 'create method'
+ describe "#update" do
+ before do
+ create_page("Update", "content")
+ @page = wiki.find_page("Update")
end
- context 'when Gitaly is disabled', :skip_gitaly_mock do
- it_behaves_like 'create method'
+ after do
+ destroy_page(@page.title, @page.directory)
end
- end
- describe "#update" do
- shared_examples 'update method' do
- before do
- create_page("Update", "content")
+ context "with valid attributes" do
+ it "updates the content of the page" do
+ new_content = "new content"
+
+ @page.update(content: new_content)
@page = wiki.find_page("Update")
- end
- after do
- destroy_page(@page.title, @page.directory)
+ expect(@page.content).to eq("new content")
end
- context "with valid attributes" do
- it "updates the content of the page" do
- new_content = "new content"
-
- @page.update(content: new_content)
- @page = wiki.find_page("Update")
-
- expect(@page.content).to eq("new content")
- end
+ it "updates the title of the page" do
+ new_title = "Index v.1.2.4"
- it "updates the title of the page" do
- new_title = "Index v.1.2.4"
+ @page.update(title: new_title)
+ @page = wiki.find_page(new_title)
- @page.update(title: new_title)
- @page = wiki.find_page(new_title)
-
- expect(@page.title).to eq(new_title)
- end
+ expect(@page.title).to eq(new_title)
+ end
- it "returns true" do
- expect(@page.update(content: "more content")).to be_truthy
- end
+ it "returns true" do
+ expect(@page.update(content: "more content")).to be_truthy
end
+ end
- context 'with same last commit sha' do
- it 'returns true' do
- expect(@page.update(content: 'more content', last_commit_sha: @page.last_commit_sha)).to be_truthy
- end
+ context 'with same last commit sha' do
+ it 'returns true' do
+ expect(@page.update(content: 'more content', last_commit_sha: @page.last_commit_sha)).to be_truthy
end
+ end
- context 'with different last commit sha' do
- it 'raises exception' do
- expect { @page.update(content: 'more content', last_commit_sha: 'xxx') }.to raise_error(WikiPage::PageChangedError)
- end
+ context 'with different last commit sha' do
+ it 'raises exception' do
+ expect { @page.update(content: 'more content', last_commit_sha: 'xxx') }.to raise_error(WikiPage::PageChangedError)
end
+ end
- context 'when renaming a page' do
- it 'raises an error if the page already exists' do
- create_page('Existing Page', 'content')
+ context 'when renaming a page' do
+ it 'raises an error if the page already exists' do
+ create_page('Existing Page', 'content')
- expect { @page.update(title: 'Existing Page', content: 'new_content') }.to raise_error(WikiPage::PageRenameError)
- expect(@page.title).to eq 'Update'
- expect(@page.content).to eq 'new_content'
+ expect { @page.update(title: 'Existing Page', content: 'new_content') }.to raise_error(WikiPage::PageRenameError)
+ expect(@page.title).to eq 'Update'
+ expect(@page.content).to eq 'new_content'
- destroy_page('Existing Page')
- end
+ destroy_page('Existing Page')
+ end
- it 'updates the content and rename the file' do
- new_title = 'Renamed Page'
- new_content = 'updated content'
+ it 'updates the content and rename the file' do
+ new_title = 'Renamed Page'
+ new_content = 'updated content'
- expect(@page.update(title: new_title, content: new_content)).to be_truthy
+ expect(@page.update(title: new_title, content: new_content)).to be_truthy
- @page = wiki.find_page(new_title)
+ @page = wiki.find_page(new_title)
- expect(@page).not_to be_nil
- expect(@page.content).to eq new_content
- end
+ expect(@page).not_to be_nil
+ expect(@page.content).to eq new_content
end
+ end
- context 'when moving a page' do
- it 'raises an error if the page already exists' do
- create_page('foo/Existing Page', 'content')
-
- expect { @page.update(title: 'foo/Existing Page', content: 'new_content') }.to raise_error(WikiPage::PageRenameError)
- expect(@page.title).to eq 'Update'
- expect(@page.content).to eq 'new_content'
+ context 'when moving a page' do
+ it 'raises an error if the page already exists' do
+ create_page('foo/Existing Page', 'content')
- destroy_page('Existing Page', 'foo')
- end
+ expect { @page.update(title: 'foo/Existing Page', content: 'new_content') }.to raise_error(WikiPage::PageRenameError)
+ expect(@page.title).to eq 'Update'
+ expect(@page.content).to eq 'new_content'
- it 'updates the content and moves the file' do
- new_title = 'foo/Other Page'
- new_content = 'new_content'
-
- expect(@page.update(title: new_title, content: new_content)).to be_truthy
+ destroy_page('Existing Page', 'foo')
+ end
- page = wiki.find_page(new_title)
+ it 'updates the content and moves the file' do
+ new_title = 'foo/Other Page'
+ new_content = 'new_content'
- expect(page).not_to be_nil
- expect(page.content).to eq new_content
- end
+ expect(@page.update(title: new_title, content: new_content)).to be_truthy
- context 'in subdir' do
- before do
- create_page('foo/Existing Page', 'content')
- @page = wiki.find_page('foo/Existing Page')
- end
+ page = wiki.find_page(new_title)
- it 'moves the page to the root folder if the title is preceded by /', :skip_gitaly_mock do
- expect(@page.slug).to eq 'foo/Existing-Page'
- expect(@page.update(title: '/Existing Page', content: 'new_content')).to be_truthy
- expect(@page.slug).to eq 'Existing-Page'
- end
+ expect(page).not_to be_nil
+ expect(page.content).to eq new_content
+ end
- it 'does nothing if it has the same title' do
- original_path = @page.slug
+ context 'in subdir' do
+ before do
+ create_page('foo/Existing Page', 'content')
+ @page = wiki.find_page('foo/Existing Page')
+ end
- expect(@page.update(title: 'Existing Page', content: 'new_content')).to be_truthy
- expect(@page.slug).to eq original_path
- end
+ it 'moves the page to the root folder if the title is preceded by /' do
+ expect(@page.slug).to eq 'foo/Existing-Page'
+ expect(@page.update(title: '/Existing Page', content: 'new_content')).to be_truthy
+ expect(@page.slug).to eq 'Existing-Page'
end
- context 'in root dir' do
- it 'does nothing if the title is preceded by /' do
- original_path = @page.slug
+ it 'does nothing if it has the same title' do
+ original_path = @page.slug
- expect(@page.update(title: '/Update', content: 'new_content')).to be_truthy
- expect(@page.slug).to eq original_path
- end
+ expect(@page.update(title: 'Existing Page', content: 'new_content')).to be_truthy
+ expect(@page.slug).to eq original_path
end
end
- context "with invalid attributes" do
- it 'aborts update if title blank' do
- expect(@page.update(title: '', content: 'new_content')).to be_falsey
- expect(@page.content).to eq 'new_content'
+ context 'in root dir' do
+ it 'does nothing if the title is preceded by /' do
+ original_path = @page.slug
- page = wiki.find_page('Update')
- expect(page.content).to eq 'content'
-
- @page.title = 'Update'
+ expect(@page.update(title: '/Update', content: 'new_content')).to be_truthy
+ expect(@page.slug).to eq original_path
end
end
end
- context 'when Gitaly is enabled' do
- it_behaves_like 'update method'
- end
+ context "with invalid attributes" do
+ it 'aborts update if title blank' do
+ expect(@page.update(title: '', content: 'new_content')).to be_falsey
+ expect(@page.content).to eq 'new_content'
- context 'when Gitaly is disabled', :skip_gitaly_mock do
- it_behaves_like 'update method'
+ page = wiki.find_page('Update')
+ expect(page.content).to eq 'content'
+
+ @page.title = 'Update'
+ end
end
end
@@ -394,34 +374,24 @@ describe WikiPage do
end
describe "#versions" do
- shared_examples 'wiki page versions' do
- let(:page) { wiki.find_page("Update") }
+ let(:page) { wiki.find_page("Update") }
- before do
- create_page("Update", "content")
- end
-
- after do
- destroy_page("Update")
- end
-
- it "returns an array of all commits for the page" do
- 3.times { |i| page.update(content: "content #{i}") }
-
- expect(page.versions.count).to eq(4)
- end
+ before do
+ create_page("Update", "content")
+ end
- it 'returns instances of WikiPageVersion' do
- expect(page.versions).to all( be_a(Gitlab::Git::WikiPageVersion) )
- end
+ after do
+ destroy_page("Update")
end
- context 'when Gitaly is enabled' do
- it_behaves_like 'wiki page versions'
+ it "returns an array of all commits for the page" do
+ 3.times { |i| page.update(content: "content #{i}") }
+
+ expect(page.versions.count).to eq(4)
end
- context 'when Gitaly is disabled', :disable_gitaly do
- it_behaves_like 'wiki page versions'
+ it 'returns instances of WikiPageVersion' do
+ expect(page.versions).to all( be_a(Gitlab::Git::WikiPageVersion) )
end
end
@@ -555,23 +525,13 @@ describe WikiPage do
end
describe '#formatted_content' do
- shared_examples 'fetching page formatted content' do
- it 'returns processed content of the page' do
- subject.create({ title: "RDoc", content: "*bold*", format: "rdoc" })
- page = wiki.find_page('RDoc')
-
- expect(page.formatted_content).to eq("\n<p><strong>bold</strong></p>\n")
+ it 'returns processed content of the page' do
+ subject.create({ title: "RDoc", content: "*bold*", format: "rdoc" })
+ page = wiki.find_page('RDoc')
- destroy_page('RDoc')
- end
- end
-
- context 'when Gitaly wiki_page_formatted_data is enabled' do
- it_behaves_like 'fetching page formatted content'
- end
+ expect(page.formatted_content).to eq("\n<p><strong>bold</strong></p>\n")
- context 'when Gitaly wiki_page_formatted_data is disabled', :disable_gitaly do
- it_behaves_like 'fetching page formatted content'
+ destroy_page('RDoc')
end
end
diff --git a/spec/services/clusters/gcp/kubernetes/create_or_update_namespace_service_spec.rb b/spec/services/clusters/gcp/kubernetes/create_or_update_namespace_service_spec.rb
index fc922218ad0..661364ac765 100644
--- a/spec/services/clusters/gcp/kubernetes/create_or_update_namespace_service_spec.rb
+++ b/spec/services/clusters/gcp/kubernetes/create_or_update_namespace_service_spec.rb
@@ -44,7 +44,7 @@ describe Clusters::Gcp::Kubernetes::CreateOrUpdateNamespaceService, '#execute' d
let(:namespace) { "#{project.path}-#{project.id}" }
let(:kubernetes_namespace) do
- build(:cluster_kubernetes_namespace,
+ create(:cluster_kubernetes_namespace,
cluster: cluster,
project: cluster_project.project,
cluster_project: cluster_project)
diff --git a/spec/services/users/build_service_spec.rb b/spec/services/users/build_service_spec.rb
index 17bc880dec5..b7b9817efdb 100644
--- a/spec/services/users/build_service_spec.rb
+++ b/spec/services/users/build_service_spec.rb
@@ -8,7 +8,7 @@ describe Users::BuildService do
context 'with an admin user' do
let(:admin_user) { create(:admin) }
- let(:service) { described_class.new(admin_user, params) }
+ let(:service) { described_class.new(admin_user, ActionController::Parameters.new(params).permit!) }
it 'returns a valid user' do
expect(service.execute).to be_valid
diff --git a/spec/support/gitaly.rb b/spec/support/gitaly.rb
deleted file mode 100644
index 614aaa73693..00000000000
--- a/spec/support/gitaly.rb
+++ /dev/null
@@ -1,16 +0,0 @@
-RSpec.configure do |config|
- config.before(:each) do |example|
- if example.metadata[:disable_gitaly]
- # Use 'and_wrap_original' to make sure the arguments are valid
- allow(Gitlab::GitalyClient).to receive(:feature_enabled?).and_wrap_original { |m, *args| m.call(*args) && false }
- else
- next if example.metadata[:skip_gitaly_mock]
-
- # Use 'and_wrap_original' to make sure the arguments are valid
- allow(Gitlab::GitalyClient).to receive(:feature_enabled?).and_wrap_original do |m, *args|
- m.call(*args)
- !Gitlab::GitalyClient.explicit_opt_in_required.include?(args.first)
- end
- end
- end
-end
diff --git a/spec/support/helpers/devise_helpers.rb b/spec/support/helpers/devise_helpers.rb
index 66874e10f38..d32bc2424c0 100644
--- a/spec/support/helpers/devise_helpers.rb
+++ b/spec/support/helpers/devise_helpers.rb
@@ -8,8 +8,15 @@ module DeviseHelpers
end
def env_from_context(context)
+ # When we modify env_config, that is on the global
+ # Rails.application, and we need to stub it and allow it to be
+ # modified in-place, without polluting later tests.
if context.respond_to?(:env_config)
- context.env_config
+ context.env_config.deep_dup.tap do |env|
+ allow(context).to receive(:env_config).and_return(env)
+ end
+ # When we modify env, then the context is a request, or something
+ # else that only lives for a single spec.
elsif context.respond_to?(:env)
context.env
end
diff --git a/spec/support/helpers/filter_item_select_helper.rb b/spec/support/helpers/filter_item_select_helper.rb
deleted file mode 100644
index 519e84d359e..00000000000
--- a/spec/support/helpers/filter_item_select_helper.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# 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/helpers/user_login_helper.rb b/spec/support/helpers/user_login_helper.rb
new file mode 100644
index 00000000000..36c002f53af
--- /dev/null
+++ b/spec/support/helpers/user_login_helper.rb
@@ -0,0 +1,26 @@
+# frozen_string_literal: true
+
+module UserLoginHelper
+ def ensure_tab_pane_correctness(visit_path = true)
+ if visit_path
+ visit new_user_session_path
+ end
+
+ ensure_tab_pane_counts
+ ensure_one_active_tab
+ ensure_one_active_pane
+ end
+
+ def ensure_tab_pane_counts
+ tabs_count = page.all('[role="tab"]').size
+ expect(page).to have_selector('[role="tabpanel"]', count: tabs_count)
+ end
+
+ def ensure_one_active_tab
+ expect(page).to have_selector('ul.new-session-tabs > li > a.active', count: 1)
+ end
+
+ def ensure_one_active_pane
+ expect(page).to have_selector('.tab-pane.active', count: 1)
+ end
+end
diff --git a/vendor/licenses.csv b/vendor/licenses.csv
index ea3d3fd02f9..f6fd1efaa83 100644
--- a/vendor/licenses.csv
+++ b/vendor/licenses.csv
@@ -67,9 +67,8 @@
@babel/template,7.1.2,MIT
@babel/traverse,7.1.0,MIT
@babel/types,7.1.2,MIT
-@gitlab-org/gitlab-svgs,1.32.0,MIT
-@gitlab-org/gitlab-ui,1.10.0,MIT
@gitlab/svgs,1.35.0,MIT
+@gitlab/ui,1.11.0,MIT
@sindresorhus/is,0.7.0,MIT
@types/jquery,2.0.48,MIT
@vue/component-compiler-utils,2.2.0,MIT
diff --git a/yarn.lock b/yarn.lock
index 38e0f9d6201..3ee1b2525be 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -616,20 +616,6 @@
lodash "^4.17.10"
to-fast-properties "^2.0.0"
-"@gitlab-org/gitlab-svgs@^1.23.0":
- version "1.32.0"
- resolved "https://registry.yarnpkg.com/@gitlab-org/gitlab-svgs/-/gitlab-svgs-1.32.0.tgz#a65ab7724fa7d55be8e5cc9b2dbe3f0757432fd3"
- integrity sha512-L3o8dFUd2nSkVZBwh2hCJWzNzADJ3dTBZxamND8NLosZK9/ohNhccmsQOZGyMCUHaOzm4vifaaXkAXh04UtMKA==
-
-"@gitlab-org/gitlab-ui@^1.10.0":
- version "1.10.0"
- resolved "https://registry.yarnpkg.com/@gitlab-org/gitlab-ui/-/gitlab-ui-1.10.0.tgz#3ac54ecaa25ea558324f0b382c97fcf9e3c4f0a5"
- integrity sha512-kfoCKA+AmWZ3hf1wOS8W9mPJs/7lF+a01PK//+sw2MOLv6PlduJJmdN8drFuJ65o6cTJ1f9FMVB80R6D71XVKQ==
- dependencies:
- "@gitlab-org/gitlab-svgs" "^1.23.0"
- bootstrap-vue "^2.0.0-rc.11"
- vue "^2.5.16"
-
"@gitlab/eslint-config@^1.1.0":
version "1.1.0"
resolved "https://registry.yarnpkg.com/@gitlab/eslint-config/-/eslint-config-1.1.0.tgz#9757764b3a78b6bacfbcd9533331cb6345ffdd59"
@@ -643,10 +629,25 @@
eslint-plugin-promise "^4.0.1"
eslint-plugin-vue "^5.0.0-beta.3"
-"@gitlab/svgs@^1.35.0":
- version "1.35.0"
- resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-1.35.0.tgz#01b6a0948bb3897fbbac9f50ce23c559c514ea0e"
- integrity sha512-XKrTniSYKG5U8+8ZqDJqoW8ORahuPBfHrfsC1dHBPvo1xA/QGJxlpUdeqSFw2O19h481ut4yW1dF+OFpIa/mrw==
+"@gitlab/svgs@^1.38.0":
+ version "1.38.0"
+ resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-1.38.0.tgz#e2f6e73379d60c7c63af4df8242a94c4671a1dfe"
+ integrity sha512-Mzv6PxVbWEPvvMgXHaGxk8UE1Gard2gifca6loLgfLH7BtjXfESiZyJdQkkTSeBYp5MoqQa88Kw+vJYobwjsSw==
+
+"@gitlab/ui@^1.11.0":
+ version "1.11.0"
+ resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-1.11.0.tgz#b771c2c3d627cf9efbe98c71ee5739624f2ff51f"
+ integrity sha512-hGMHM45kcv9725R6G+n/HxvF3KfVb9oBGRNf1+4n3xAGmtXJ2NlPdIXIsDaye3EeVF9PTOtjLuaqrcp6AGNqZg==
+ dependencies:
+ babel-standalone "^6.26.0"
+ bootstrap-vue "^2.0.0-rc.11"
+ copy-to-clipboard "^3.0.8"
+ highlight.js "^9.13.1"
+ js-beautify "^1.8.8"
+ lodash "^4.17.11"
+ url-search-params-polyfill "^5.0.0"
+ vue "^2.5.16"
+ vue-loader "^15.4.2"
"@sindresorhus/is@^0.7.0":
version "0.7.0"
@@ -682,11 +683,21 @@
resolved "https://registry.yarnpkg.com/@types/node/-/node-10.5.2.tgz#f19f05314d5421fe37e74153254201a7bf00a707"
integrity sha512-m9zXmifkZsMHZBOyxZWilMwmTlpC8x5Ty360JKTiXvlXZfBWYpsg9ZZvP/Ye+iZUh+Q+MxDLjItVTWIsfwz+8Q==
+"@types/node@^10.11.7":
+ version "10.12.9"
+ resolved "https://registry.yarnpkg.com/@types/node/-/node-10.12.9.tgz#a07bfa74331471e1dc22a47eb72026843f7b95c8"
+ integrity sha512-eajkMXG812/w3w4a1OcBlaTwsFPO5F7fJ/amy+tieQxEMWBlbV1JGSjkFM+zkHNf81Cad+dfIRA+IBkvmvdAeA==
+
"@types/parse5@^5":
version "5.0.0"
resolved "https://registry.yarnpkg.com/@types/parse5/-/parse5-5.0.0.tgz#9ae2106efc443d7c1e26570aa8247828c9c80f11"
integrity sha512-J5D3z703XTDIGQFYXsnU9uRCW9e9mMEFO0Kpe6kykyiboqziru/RlZ0hM2P+PKTG4NHG1SjLrqae/NrV2iJApQ==
+"@types/semver@^5.5.0":
+ version "5.5.0"
+ resolved "https://registry.yarnpkg.com/@types/semver/-/semver-5.5.0.tgz#146c2a29ee7d3bae4bf2fcb274636e264c813c45"
+ integrity sha512-41qEJgBH/TWgo5NFSvBCJ1qkoi3Q6ONSF2avrHq1LVEZfYpdHmj0y9SuTK+u9ZhG1sYQKBL1AWXKyLWP4RaUoQ==
+
"@vue/component-compiler-utils@^2.0.0":
version "2.2.0"
resolved "https://registry.yarnpkg.com/@vue/component-compiler-utils/-/component-compiler-utils-2.2.0.tgz#bbbb7ed38a9a8a7c93abe7ef2e54a90a04b631b4"
@@ -1214,6 +1225,11 @@ babel-runtime@^6.22.0, babel-runtime@^6.26.0:
core-js "^2.4.0"
regenerator-runtime "^0.11.0"
+babel-standalone@^6.26.0:
+ version "6.26.0"
+ resolved "https://registry.yarnpkg.com/babel-standalone/-/babel-standalone-6.26.0.tgz#15fb3d35f2c456695815ebf1ed96fe7f015b6886"
+ integrity sha1-Ffs9NfLEVmlYFevx7Zb+fwFbaIY=
+
babel-template@^6.26.0:
version "6.26.0"
resolved "https://registry.yarnpkg.com/babel-template/-/babel-template-6.26.0.tgz#de03e2d16396b069f46dd9fff8521fb1a0e35e02"
@@ -1874,6 +1890,11 @@ commander@2, commander@^2.18.0:
resolved "https://registry.yarnpkg.com/commander/-/commander-2.18.0.tgz#2bf063ddee7c7891176981a2cc798e5754bc6970"
integrity sha512-6CYPa+JP2ftfRU2qkDK+UTVeQYosOg/2GbcjIcKPHfinyOLPVGXu/ovN86RP49Re5ndJK1N0kuiidFFuepc4ZQ==
+commander@^2.19.0:
+ version "2.19.0"
+ resolved "https://registry.yarnpkg.com/commander/-/commander-2.19.0.tgz#f6198aa84e5b83c46054b94ddedbfed5ee9ff12a"
+ integrity sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg==
+
commander@~2.13.0:
version "2.13.0"
resolved "https://registry.yarnpkg.com/commander/-/commander-2.13.0.tgz#6964bca67685df7c1f1430c584f07d7597885b9c"
@@ -1956,6 +1977,14 @@ concat-stream@^1.5.0:
readable-stream "^2.2.2"
typedarray "^0.0.6"
+config-chain@~1.1.5:
+ version "1.1.12"
+ resolved "https://registry.yarnpkg.com/config-chain/-/config-chain-1.1.12.tgz#0fde8d091200eb5e808caf25fe618c02f48e4efa"
+ integrity sha512-a1eOIcu8+7lUInge4Rpf/n4Krkf3Dd9lqhljRzII1/Zno/kRtUWnznPO3jOKBmTEktkt3fkxisUcivoj0ebzoA==
+ dependencies:
+ ini "^1.3.4"
+ proto-list "~1.2.1"
+
configstore@^3.0.0:
version "3.1.1"
resolved "https://registry.yarnpkg.com/configstore/-/configstore-3.1.1.tgz#094ee662ab83fad9917678de114faaea8fcdca90"
@@ -2056,6 +2085,13 @@ copy-descriptor@^0.1.0:
resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d"
integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=
+copy-to-clipboard@^3.0.8:
+ version "3.0.8"
+ resolved "https://registry.yarnpkg.com/copy-to-clipboard/-/copy-to-clipboard-3.0.8.tgz#f4e82f4a8830dce4666b7eb8ded0c9bcc313aba9"
+ integrity sha512-c3GdeY8qxCHGezVb1EFQfHYK/8NZRemgcTIzPq7PuxjHAf/raKibn2QdhHPb/y6q74PMgH6yizaDZlRmw6QyKw==
+ dependencies:
+ toggle-selection "^1.0.3"
+
core-js@^2.2.0, core-js@^2.4.0, core-js@^2.4.1:
version "2.5.7"
resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.5.7.tgz#f972608ff0cead68b841a16a932d0b183791814e"
@@ -2862,6 +2898,18 @@ editions@^1.3.3:
resolved "https://registry.yarnpkg.com/editions/-/editions-1.3.4.tgz#3662cb592347c3168eb8e498a0ff73271d67f50b"
integrity sha512-gzao+mxnYDzIysXKMQi/+M1mjy/rjestjg6OPoYTtI+3Izp23oiGZitsl9lPDPiTGXbcSIk1iJWhliSaglxnUg==
+editorconfig@^0.15.0:
+ version "0.15.2"
+ resolved "https://registry.yarnpkg.com/editorconfig/-/editorconfig-0.15.2.tgz#047be983abb9ab3c2eefe5199cb2b7c5689f0702"
+ integrity sha512-GWjSI19PVJAM9IZRGOS+YKI8LN+/sjkSjNyvxL5ucqP9/IqtYNXBaQ/6c/hkPNYQHyOHra2KoXZI/JVpuqwmcQ==
+ dependencies:
+ "@types/node" "^10.11.7"
+ "@types/semver" "^5.5.0"
+ commander "^2.19.0"
+ lru-cache "^4.1.3"
+ semver "^5.6.0"
+ sigmund "^1.0.1"
+
ee-first@1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d"
@@ -4083,6 +4131,11 @@ he@^1.1.0, he@^1.1.1:
resolved "https://registry.yarnpkg.com/he/-/he-1.1.1.tgz#93410fd21b009735151f8868c2f271f3427e23fd"
integrity sha1-k0EP0hsAlzUVH4howvJx80J+I/0=
+highlight.js@^9.13.1:
+ version "9.13.1"
+ resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-9.13.1.tgz#054586d53a6863311168488a0f58d6c505ce641e"
+ integrity sha512-Sc28JNQNDzaH6PORtRLMvif9RSn1mYuOoX3omVjnb0+HbpPygU2ALBI0R/wsiqCb4/fcp07Gdo8g+fhtFrQl6A==
+
hmac-drbg@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1"
@@ -4814,6 +4867,16 @@ jquery.waitforimages@^2.2.0:
resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.3.1.tgz#958ce29e81c9790f31be7792df5d4d95fc57fbca"
integrity sha512-Ubldcmxp5np52/ENotGxlLe6aGMvmF4R8S6tZjsP6Knsaxd/xp3Zrh50cG93lR6nPXyUFwzN3ZSOQI0wRJNdGg==
+js-beautify@^1.8.8:
+ version "1.8.8"
+ resolved "https://registry.yarnpkg.com/js-beautify/-/js-beautify-1.8.8.tgz#1eb175b73a3571a5f1ed8d98e7cf2b05bfa98471"
+ integrity sha512-qVNq7ZZ7ZbLdzorvSlRDadS0Rh5oyItaE95v6I4wbbuSiijxn7SnnsV6dvKlcXuO2jX7lK8tn9fBulx34K/Ejg==
+ dependencies:
+ config-chain "~1.1.5"
+ editorconfig "^0.15.0"
+ mkdirp "~0.5.0"
+ nopt "~4.0.1"
+
js-cookie@^2.1.3:
version "2.1.3"
resolved "https://registry.yarnpkg.com/js-cookie/-/js-cookie-2.1.3.tgz#48071625217ac9ecfab8c343a13d42ec09ff0526"
@@ -5171,7 +5234,7 @@ lodash.upperfirst@4.3.1:
resolved "https://registry.yarnpkg.com/lodash.upperfirst/-/lodash.upperfirst-4.3.1.tgz#1365edf431480481ef0d1c68957a5ed99d49f7ce"
integrity sha1-E2Xt9DFIBIHvDRxolXpe2Z1J984=
-lodash@^4.17.10, lodash@^4.17.4, lodash@^4.17.5, lodash@^4.3.0, lodash@^4.5.0:
+lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.4, lodash@^4.17.5, lodash@^4.3.0, lodash@^4.5.0:
version "4.17.11"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.11.tgz#b39ea6229ef607ecd89e2c8df12536891cac9b8d"
integrity sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==
@@ -5702,7 +5765,7 @@ nopt@3.x:
dependencies:
abbrev "1"
-nopt@^4.0.1:
+nopt@^4.0.1, nopt@~4.0.1:
version "4.0.1"
resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.1.tgz#d0d4685afd5415193c8c7505602d0d17cd64474d"
integrity sha1-0NRoWv1UFRk8jHUFYC0NF81kR00=
@@ -6394,6 +6457,11 @@ promise-inflight@^1.0.1:
resolved "https://registry.yarnpkg.com/promise-inflight/-/promise-inflight-1.0.1.tgz#98472870bf228132fcbdd868129bad12c3c029e3"
integrity sha1-mEcocL8igTL8vdhoEputEsPAKeM=
+proto-list@~1.2.1:
+ version "1.2.4"
+ resolved "https://registry.yarnpkg.com/proto-list/-/proto-list-1.2.4.tgz#212d5bfe1318306a420f6402b8e26ff39647a849"
+ integrity sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk=
+
proxy-addr@~2.0.3:
version "2.0.4"
resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.4.tgz#ecfc733bf22ff8c6f407fa275327b9ab67e48b93"
@@ -6987,6 +7055,11 @@ semver-diff@^2.0.0:
resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.1.tgz#7dfdd8814bdb7cabc7be0fb1d734cfb66c940477"
integrity sha512-PqpAxfrEhlSUWge8dwIp4tZnQ25DIOthpiaHNIthsjEFQD6EvqUKUDM7L8O2rShkFccYo1VjJR0coWfNkCubRw==
+semver@^5.6.0:
+ version "5.6.0"
+ resolved "https://registry.yarnpkg.com/semver/-/semver-5.6.0.tgz#7e74256fbaa49c75aa7c7a205cc22799cac80004"
+ integrity sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==
+
send@0.16.2:
version "0.16.2"
resolved "https://registry.yarnpkg.com/send/-/send-0.16.2.tgz#6ecca1e0f8c156d141597559848df64730a6bbc1"
@@ -7114,6 +7187,11 @@ shebang-regex@^1.0.0:
resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3"
integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=
+sigmund@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/sigmund/-/sigmund-1.0.1.tgz#3ff21f198cad2175f9f3b781853fd94d0d19b590"
+ integrity sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=
+
signal-exit@^3.0.0, signal-exit@^3.0.2:
version "3.0.2"
resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d"
@@ -7724,6 +7802,11 @@ to-regex@^3.0.1, to-regex@^3.0.2:
regex-not "^1.0.2"
safe-regex "^1.1.0"
+toggle-selection@^1.0.3:
+ version "1.0.6"
+ resolved "https://registry.yarnpkg.com/toggle-selection/-/toggle-selection-1.0.6.tgz#6e45b1263f2017fa0acc7d89d78b15b8bf77da32"
+ integrity sha1-bkWxJj8gF/oKzH2J14sVuL932jI=
+
touch@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/touch/-/touch-3.1.0.tgz#fe365f5f75ec9ed4e56825e0bb76d24ab74af83b"
@@ -7976,6 +8059,11 @@ url-parse@^1.1.8:
querystringify "~1.0.0"
requires-port "1.0.x"
+url-search-params-polyfill@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/url-search-params-polyfill/-/url-search-params-polyfill-5.0.0.tgz#09b98337c89dcf6c6a6a0bfeb096f6ba83b7526b"
+ integrity sha512-+SCD22QJp4UnqPOI5UTTR0Ljuh8cHbjEf1lIiZrZ8nHTlTixqwVsVQTSfk5vrmDz7N09/Y+ka5jQr0ff35FnQQ==
+
url-to-options@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/url-to-options/-/url-to-options-1.0.1.tgz#1505a03a289a48cbd7a434efbaeec5055f5633a9"