summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.md251
-rw-r--r--CONTRIBUTING.md13
-rw-r--r--GITALY_SERVER_VERSION2
-rw-r--r--Gemfile8
-rw-r--r--Gemfile.lock16
-rw-r--r--Gemfile.rails5.lock12
-rw-r--r--VERSION2
-rw-r--r--app/assets/javascripts/boards/components/board_new_issue.vue2
-rw-r--r--app/assets/javascripts/boards/components/project_select.vue2
-rw-r--r--app/assets/javascripts/commons/polyfills.js1
-rw-r--r--app/assets/javascripts/diffs/components/diff_discussions.vue1
-rw-r--r--app/assets/javascripts/diffs/components/diff_line_gutter_content.vue19
-rw-r--r--app/assets/javascripts/diffs/components/diff_table_cell.vue6
-rw-r--r--app/assets/javascripts/diffs/components/inline_diff_comment_row.vue11
-rw-r--r--app/assets/javascripts/diffs/components/inline_diff_table_row.vue7
-rw-r--r--app/assets/javascripts/diffs/components/inline_diff_view.vue23
-rw-r--r--app/assets/javascripts/diffs/components/parallel_diff_comment_row.vue53
-rw-r--r--app/assets/javascripts/diffs/components/parallel_diff_table_row.vue12
-rw-r--r--app/assets/javascripts/diffs/components/parallel_diff_view.vue38
-rw-r--r--app/assets/javascripts/diffs/store/getters.js63
-rw-r--r--app/assets/javascripts/gpg_badges.js31
-rw-r--r--app/assets/javascripts/ide/components/new_dropdown/modal.vue2
-rw-r--r--app/assets/javascripts/ide/ide_router.js22
-rw-r--r--app/assets/javascripts/lib/utils/poll.js11
-rw-r--r--app/assets/javascripts/notes/components/discussion_counter.vue28
-rw-r--r--app/assets/javascripts/notes/components/noteable_discussion.vue39
-rw-r--r--app/assets/javascripts/notes/mixins/discussion_navigation.js29
-rw-r--r--app/assets/javascripts/notes/stores/getters.js85
-rw-r--r--app/assets/javascripts/notes/stores/mutations.js19
-rw-r--r--app/assets/javascripts/notes/stores/utils.js9
-rw-r--r--app/assets/javascripts/pages/projects/blob/show/index.js3
-rw-r--r--app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/interval_pattern_input.vue14
-rw-r--r--app/assets/javascripts/pages/projects/shared/permissions/components/project_setting_row.vue2
-rw-r--r--app/assets/javascripts/pages/projects/show/index.js3
-rw-r--r--app/assets/javascripts/pages/projects/tree/show/index.js6
-rw-r--r--app/assets/javascripts/profile/profile.js4
-rw-r--r--app/assets/javascripts/projects/tree/components/commit_pipeline_status_component.vue162
-rw-r--r--app/assets/javascripts/reports/store/actions.js67
-rw-r--r--app/assets/javascripts/reports/store/index.js13
-rw-r--r--app/assets/javascripts/reports/store/mutation_types.js5
-rw-r--r--app/assets/javascripts/reports/store/mutations.js26
-rw-r--r--app/assets/javascripts/reports/store/state.js28
-rw-r--r--app/assets/javascripts/vue_shared/components/clipboard_button.vue13
-rw-r--r--app/assets/stylesheets/framework/buttons.scss4
-rw-r--r--app/assets/stylesheets/framework/dropdowns.scss7
-rw-r--r--app/assets/stylesheets/framework/forms.scss2
-rw-r--r--app/assets/stylesheets/pages/commits.scss6
-rw-r--r--app/assets/stylesheets/pages/reports.scss159
-rw-r--r--app/controllers/concerns/lfs_request.rb19
-rw-r--r--app/controllers/import/gitlab_controller.rb5
-rw-r--r--app/controllers/projects/raw_controller.rb3
-rw-r--r--app/controllers/sessions_controller.rb2
-rw-r--r--app/finders/groups_finder.rb16
-rw-r--r--app/finders/personal_projects_finder.rb19
-rw-r--r--app/finders/projects_finder.rb17
-rw-r--r--app/helpers/auth_helper.rb2
-rw-r--r--app/helpers/blob_helper.rb31
-rw-r--r--app/helpers/button_helper.rb2
-rw-r--r--app/helpers/ci_status_helper.rb13
-rw-r--r--app/helpers/commits_helper.rb9
-rw-r--r--app/helpers/visibility_level_helper.rb5
-rw-r--r--app/helpers/workhorse_helper.rb4
-rw-r--r--app/models/concerns/protected_ref_access.rb5
-rw-r--r--app/models/deploy_token.rb6
-rw-r--r--app/models/project.rb2
-rw-r--r--app/models/project_services/hangouts_chat_service.rb67
-rw-r--r--app/models/service.rb1
-rw-r--r--app/models/user.rb1
-rw-r--r--app/serializers/analytics_build_entity.rb2
-rw-r--r--app/serializers/analytics_build_serializer.rb2
-rw-r--r--app/serializers/analytics_commit_entity.rb2
-rw-r--r--app/serializers/analytics_commit_serializer.rb2
-rw-r--r--app/serializers/analytics_generic_serializer.rb2
-rw-r--r--app/serializers/analytics_issue_entity.rb2
-rw-r--r--app/serializers/analytics_issue_serializer.rb2
-rw-r--r--app/serializers/analytics_merge_request_entity.rb2
-rw-r--r--app/serializers/analytics_merge_request_serializer.rb2
-rw-r--r--app/serializers/analytics_stage_entity.rb2
-rw-r--r--app/serializers/analytics_stage_serializer.rb2
-rw-r--r--app/serializers/analytics_summary_entity.rb2
-rw-r--r--app/serializers/analytics_summary_serializer.rb2
-rw-r--r--app/serializers/award_emoji_entity.rb2
-rw-r--r--app/serializers/base_serializer.rb2
-rw-r--r--app/serializers/blob_entity.rb2
-rw-r--r--app/serializers/build_action_entity.rb2
-rw-r--r--app/serializers/build_artifact_entity.rb2
-rw-r--r--app/serializers/build_details_entity.rb2
-rw-r--r--app/serializers/build_metadata_entity.rb2
-rw-r--r--app/serializers/build_serializer.rb2
-rw-r--r--app/serializers/cluster_application_entity.rb2
-rw-r--r--app/serializers/cluster_entity.rb2
-rw-r--r--app/serializers/cluster_serializer.rb2
-rw-r--r--app/serializers/cohort_activity_month_entity.rb2
-rw-r--r--app/serializers/cohort_entity.rb2
-rw-r--r--app/serializers/cohorts_entity.rb2
-rw-r--r--app/serializers/cohorts_serializer.rb2
-rw-r--r--app/serializers/commit_entity.rb2
-rw-r--r--app/serializers/concerns/with_pagination.rb2
-rw-r--r--app/serializers/container_repositories_serializer.rb2
-rw-r--r--app/serializers/container_repository_entity.rb2
-rw-r--r--app/serializers/container_tag_entity.rb2
-rw-r--r--app/serializers/container_tags_serializer.rb2
-rw-r--r--app/serializers/deploy_key_entity.rb2
-rw-r--r--app/serializers/deploy_key_serializer.rb2
-rw-r--r--app/serializers/deploy_keys_project_entity.rb2
-rw-r--r--app/serializers/deployment_entity.rb2
-rw-r--r--app/serializers/deployment_serializer.rb2
-rw-r--r--app/serializers/diff_file_entity.rb2
-rw-r--r--app/serializers/diffs_entity.rb2
-rw-r--r--app/serializers/diffs_serializer.rb2
-rw-r--r--app/serializers/discussion_entity.rb2
-rw-r--r--app/serializers/discussion_serializer.rb2
-rw-r--r--app/serializers/entity_date_helper.rb23
-rw-r--r--app/serializers/entity_request.rb2
-rw-r--r--app/serializers/environment_entity.rb2
-rw-r--r--app/serializers/environment_serializer.rb2
-rw-r--r--app/serializers/group_child_entity.rb2
-rw-r--r--app/serializers/group_child_serializer.rb2
-rw-r--r--app/serializers/group_entity.rb2
-rw-r--r--app/serializers/group_serializer.rb2
-rw-r--r--app/serializers/group_variable_entity.rb2
-rw-r--r--app/serializers/group_variable_serializer.rb2
-rw-r--r--app/serializers/issuable_entity.rb2
-rw-r--r--app/serializers/issuable_sidebar_entity.rb2
-rw-r--r--app/serializers/issue_entity.rb2
-rw-r--r--app/serializers/issue_serializer.rb2
-rw-r--r--app/serializers/issue_sidebar_entity.rb2
-rw-r--r--app/serializers/job_entity.rb2
-rw-r--r--app/serializers/job_group_entity.rb2
-rw-r--r--app/serializers/label_entity.rb2
-rw-r--r--app/serializers/label_serializer.rb2
-rw-r--r--app/serializers/lfs_file_lock_entity.rb2
-rw-r--r--app/serializers/lfs_file_lock_serializer.rb2
-rw-r--r--app/serializers/merge_request_basic_entity.rb2
-rw-r--r--app/serializers/merge_request_basic_serializer.rb2
-rw-r--r--app/serializers/merge_request_create_entity.rb2
-rw-r--r--app/serializers/merge_request_create_serializer.rb2
-rw-r--r--app/serializers/merge_request_diff_entity.rb2
-rw-r--r--app/serializers/merge_request_metrics_entity.rb2
-rw-r--r--app/serializers/merge_request_serializer.rb2
-rw-r--r--app/serializers/merge_request_user_entity.rb2
-rw-r--r--app/serializers/merge_request_widget_entity.rb2
-rw-r--r--app/serializers/note_attachment_entity.rb2
-rw-r--r--app/serializers/note_entity.rb2
-rw-r--r--app/serializers/note_user_entity.rb2
-rw-r--r--app/serializers/pipeline_details_entity.rb2
-rw-r--r--app/serializers/pipeline_entity.rb2
-rw-r--r--app/serializers/pipeline_serializer.rb2
-rw-r--r--app/serializers/project_entity.rb2
-rw-r--r--app/serializers/project_mirror_entity.rb2
-rw-r--r--app/serializers/project_note_entity.rb2
-rw-r--r--app/serializers/project_note_serializer.rb2
-rw-r--r--app/serializers/project_serializer.rb2
-rw-r--r--app/serializers/request_aware_entity.rb2
-rw-r--r--app/serializers/runner_entity.rb2
-rw-r--r--app/serializers/stage_entity.rb2
-rw-r--r--app/serializers/stage_serializer.rb2
-rw-r--r--app/serializers/status_entity.rb2
-rw-r--r--app/serializers/submodule_entity.rb2
-rw-r--r--app/serializers/time_trackable_entity.rb2
-rw-r--r--app/serializers/tree_entity.rb2
-rw-r--r--app/serializers/tree_root_entity.rb2
-rw-r--r--app/serializers/tree_serializer.rb2
-rw-r--r--app/serializers/user_entity.rb2
-rw-r--r--app/serializers/user_serializer.rb2
-rw-r--r--app/serializers/variable_entity.rb2
-rw-r--r--app/serializers/variable_serializer.rb2
-rw-r--r--app/services/projects/import_service.rb4
-rw-r--r--app/services/prometheus/adapter_service.rb2
-rw-r--r--app/services/protected_branches/access_level_params.rb2
-rw-r--r--app/services/protected_branches/api_service.rb2
-rw-r--r--app/services/protected_branches/create_service.rb2
-rw-r--r--app/services/protected_branches/destroy_service.rb2
-rw-r--r--app/services/protected_branches/legacy_api_create_service.rb2
-rw-r--r--app/services/protected_branches/legacy_api_update_service.rb2
-rw-r--r--app/services/protected_branches/update_service.rb2
-rw-r--r--app/services/protected_tags/create_service.rb2
-rw-r--r--app/services/protected_tags/destroy_service.rb2
-rw-r--r--app/services/protected_tags/update_service.rb2
-rw-r--r--app/services/quick_actions/interpret_service.rb2
-rw-r--r--app/services/search/global_service.rb2
-rw-r--r--app/services/search/group_service.rb2
-rw-r--r--app/services/search/project_service.rb2
-rw-r--r--app/services/search/snippet_service.rb2
-rw-r--r--app/services/tags/create_service.rb2
-rw-r--r--app/services/tags/destroy_service.rb2
-rw-r--r--app/services/test_hooks/base_service.rb2
-rw-r--r--app/services/test_hooks/project_service.rb2
-rw-r--r--app/services/test_hooks/system_service.rb2
-rw-r--r--app/services/users/activity_service.rb22
-rw-r--r--app/services/users/build_service.rb2
-rw-r--r--app/services/users/create_service.rb2
-rw-r--r--app/services/users/destroy_service.rb2
-rw-r--r--app/services/users/last_push_event_service.rb2
-rw-r--r--app/services/users/migrate_to_ghost_user_service.rb2
-rw-r--r--app/services/users/refresh_authorized_projects_service.rb2
-rw-r--r--app/services/users/respond_to_terms_service.rb2
-rw-r--r--app/services/users/update_service.rb2
-rw-r--r--app/services/wiki_pages/base_service.rb2
-rw-r--r--app/services/wiki_pages/create_service.rb2
-rw-r--r--app/services/wiki_pages/destroy_service.rb2
-rw-r--r--app/services/wiki_pages/update_service.rb2
-rw-r--r--app/uploaders/import_export_uploader.rb2
-rw-r--r--app/views/admin/application_settings/_abuse.html.haml2
-rw-r--r--app/views/admin/application_settings/_account_and_limit.html.haml10
-rw-r--r--app/views/admin/application_settings/_background_jobs.html.haml4
-rw-r--r--app/views/admin/application_settings/_ci_cd.html.haml8
-rw-r--r--app/views/admin/application_settings/_gitaly.html.haml6
-rw-r--r--app/views/admin/application_settings/_help_page.html.haml4
-rw-r--r--app/views/admin/application_settings/_influx.html.haml14
-rw-r--r--app/views/admin/application_settings/_ip_limits.html.haml12
-rw-r--r--app/views/admin/application_settings/_koding.html.haml2
-rw-r--r--app/views/admin/application_settings/_logging.html.haml4
-rw-r--r--app/views/admin/application_settings/_pages.html.haml2
-rw-r--r--app/views/admin/application_settings/_performance_bar.html.haml2
-rw-r--r--app/views/admin/application_settings/_plantuml.html.haml2
-rw-r--r--app/views/admin/application_settings/_realtime.html.haml2
-rw-r--r--app/views/admin/application_settings/_registry.html.haml2
-rw-r--r--app/views/admin/application_settings/_repository_check.html.haml6
-rw-r--r--app/views/admin/application_settings/_repository_mirrors_form.html.haml2
-rw-r--r--app/views/admin/application_settings/_repository_storage.html.haml12
-rw-r--r--app/views/admin/application_settings/_signin.html.haml12
-rw-r--r--app/views/admin/application_settings/_signup.html.haml10
-rw-r--r--app/views/admin/application_settings/_spam.html.haml10
-rw-r--r--app/views/admin/application_settings/_terminal.html.haml2
-rw-r--r--app/views/admin/application_settings/_visibility_and_access.html.haml16
-rw-r--r--app/views/admin/dashboard/index.html.haml4
-rw-r--r--app/views/admin/hooks/_form.html.haml8
-rw-r--r--app/views/admin/runners/show.html.haml1
-rw-r--r--app/views/doorkeeper/applications/_form.html.haml6
-rw-r--r--app/views/groups/settings/_general.html.haml6
-rw-r--r--app/views/import/gitlab_projects/new.html.haml6
-rw-r--r--app/views/import/manifest/_form.html.haml4
-rw-r--r--app/views/profiles/accounts/show.html.haml2
-rw-r--r--app/views/profiles/emails/index.html.haml2
-rw-r--r--app/views/profiles/gpg_keys/_form.html.haml2
-rw-r--r--app/views/profiles/keys/_form.html.haml4
-rw-r--r--app/views/profiles/notifications/show.html.haml4
-rw-r--r--app/views/profiles/passwords/edit.html.haml6
-rw-r--r--app/views/profiles/personal_access_tokens/index.html.haml4
-rw-r--r--app/views/profiles/preferences/show.html.haml6
-rw-r--r--app/views/profiles/two_factor_auths/show.html.haml10
-rw-r--r--app/views/projects/_merge_request_merge_method_settings.html.haml2
-rw-r--r--app/views/projects/_new_project_fields.html.haml8
-rw-r--r--app/views/projects/_project_templates.html.haml2
-rw-r--r--app/views/projects/artifacts/file.html.haml2
-rw-r--r--app/views/projects/blame/show.html.haml2
-rw-r--r--app/views/projects/blob/_header.html.haml2
-rw-r--r--app/views/projects/blob/show.html.haml2
-rw-r--r--app/views/projects/buttons/_star.html.haml2
-rw-r--r--app/views/projects/clusters/gcp/_form.html.haml12
-rw-r--r--app/views/projects/clusters/user/_form.html.haml12
-rw-r--r--app/views/projects/clusters/user/_show.html.haml10
-rw-r--r--app/views/projects/commit/_change.html.haml2
-rw-r--r--app/views/projects/commit/_commit_box.html.haml2
-rw-r--r--app/views/projects/commits/_commit.html.haml2
-rw-r--r--app/views/projects/deploy_keys/_form.html.haml4
-rw-r--r--app/views/projects/deploy_tokens/_form.html.haml10
-rw-r--r--app/views/projects/edit.html.haml16
-rw-r--r--app/views/projects/environments/_form.html.haml4
-rw-r--r--app/views/projects/merge_requests/conflicts/_submit_form.html.haml2
-rw-r--r--app/views/projects/mirrors/_push.html.haml6
-rw-r--r--app/views/projects/pipeline_schedules/_form.html.haml12
-rw-r--r--app/views/projects/pipelines/_info.html.haml2
-rw-r--r--app/views/projects/pipelines/_with_tabs.html.haml3
-rw-r--r--app/views/projects/pipelines/new.html.haml2
-rw-r--r--app/views/projects/project_members/_new_project_member.html.haml6
-rw-r--r--app/views/projects/project_members/_new_shared_group.html.haml6
-rw-r--r--app/views/projects/protected_tags/_protected_tag.html.haml4
-rw-r--r--app/views/projects/protected_tags/_protected_tag_create_access_levels.haml8
-rw-r--r--app/views/projects/protected_tags/_update_protected_tag.haml5
-rw-r--r--app/views/projects/services/prometheus/_metrics.html.haml30
-rw-r--r--app/views/projects/services/prometheus/_show.html.haml33
-rw-r--r--app/views/projects/settings/ci_cd/_form.html.haml8
-rw-r--r--app/views/projects/show.html.haml4
-rw-r--r--app/views/projects/tags/index.html.haml2
-rw-r--r--app/views/projects/tree/show.html.haml3
-rw-r--r--app/views/projects/triggers/_form.html.haml4
-rw-r--r--app/views/shared/_import_form.html.haml2
-rw-r--r--app/views/shared/_personal_access_tokens_form.html.haml6
-rw-r--r--app/views/shared/tokens/_scopes_form.html.haml2
-rw-r--r--app/views/shared/web_hooks/_form.html.haml8
-rw-r--r--app/views/sherlock/queries/_general.html.haml4
-rw-r--r--app/workers/all_queues.yml2
-rw-r--r--app/workers/concerns/each_shard_worker.rb2
-rw-r--r--app/workers/delete_diff_files_worker.rb2
-rw-r--r--app/workers/emails_on_push_worker.rb8
-rw-r--r--app/workers/repository_check/dispatch_worker.rb2
-rw-r--r--app/workers/schedule_update_user_activity_worker.rb12
-rw-r--r--app/workers/update_user_activity_worker.rb27
-rw-r--r--changelogs/unreleased/18141-osw-use-monospaced-font-on-diffs-commit-ref.yml5
-rw-r--r--changelogs/unreleased/19439-api-file-sha56-and-head.yml5
-rw-r--r--changelogs/unreleased/19468-add_readme_when_creating_project.yml5
-rw-r--r--changelogs/unreleased/20357.yml5
-rw-r--r--changelogs/unreleased/23705-add-single-file-download-in-repo.yml5
-rw-r--r--changelogs/unreleased/29278-commits-page-tooltips.yml5
-rw-r--r--changelogs/unreleased/31583-osw-gfm-complete-status-indication.yml5
-rw-r--r--changelogs/unreleased/35158-snippets-api-visibility.yml5
-rw-r--r--changelogs/unreleased/36234-nav-add-groups-dropdown.yml5
-rw-r--r--changelogs/unreleased/36907-fix-new-issue-link-from-failed-job.yml5
-rw-r--r--changelogs/unreleased/37561-add-id-settings.yml5
-rw-r--r--changelogs/unreleased/39543-milestone-page-list-redesign.yml5
-rw-r--r--changelogs/unreleased/39604-update-top-right-avatar-after-changing-avatar.yml5
-rw-r--r--changelogs/unreleased/40005-u2f-unspported-browsers.yml5
-rw-r--r--changelogs/unreleased/40484-ordered-lists-copy-gfm.yml5
-rw-r--r--changelogs/unreleased/42342-teams-pipeline-notifications.yml5
-rw-r--r--changelogs/unreleased/43270-import-with-milestones-failing.yml5
-rw-r--r--changelogs/unreleased/43312-remove_user_activity_workers.yml5
-rw-r--r--changelogs/unreleased/43446-new-cluster-page-tabs.yml5
-rw-r--r--changelogs/unreleased/43472-remove-environment-scope-field-on-cluster-creation-form-for-core-starter-plans.yml5
-rw-r--r--changelogs/unreleased/44674-use-one-column-form-layout-on-admin-area-settings-page.yml5
-rw-r--r--changelogs/unreleased/44697-when-editing-a-comment-in-an-issue-the-preview-mode-is-toggled-in-the-main-textarea.yml6
-rw-r--r--changelogs/unreleased/44725-expire_correct_methods_after_change_head.yml5
-rw-r--r--changelogs/unreleased/45318-vuex-store.yml5
-rw-r--r--changelogs/unreleased/45400-automatically-created-mr-uses-wrong-target-branch-when-branching-from-tag.yml5
-rw-r--r--changelogs/unreleased/45443-unable-to-save-user-profile-update-with-safari.yml5
-rw-r--r--changelogs/unreleased/45487-slack-tag-push-notifs.yml5
-rw-r--r--changelogs/unreleased/45557-machine-type-help-links.yml6
-rw-r--r--changelogs/unreleased/45575-invalid-characters-signup.yml5
-rw-r--r--changelogs/unreleased/45703-open-web-ide-file-tree.yml5
-rw-r--r--changelogs/unreleased/45738-add-environment-drop-down-to-metrics-dashboard.yml5
-rw-r--r--changelogs/unreleased/45933-webide-fade-uneditable-area.yml5
-rw-r--r--changelogs/unreleased/46202-webide-file-states.yml5
-rw-r--r--changelogs/unreleased/46246-gitlab-project-export-should-use-object-storage.yml5
-rw-r--r--changelogs/unreleased/46396-recognise-when-a-user-is-trying-to-validate-a-private-ssh-key-part-1.yml5
-rw-r--r--changelogs/unreleased/46396-recognise-when-a-user-is-trying-to-validate-a-private-ssh-key.yml5
-rw-r--r--changelogs/unreleased/46429-creating-a-deploy-token-doesn-t-bring-back-to-the-creation-page.yml5
-rw-r--r--changelogs/unreleased/46546-do-not-pre-select-previous-user-s-when-creating-protected-branches.yml5
-rw-r--r--changelogs/unreleased/46571-webhooks-nil-password.yml5
-rw-r--r--changelogs/unreleased/46783-removed-omniauth-provider-causing-invalid-application-setting.yml5
-rw-r--r--changelogs/unreleased/46831-remove-unused-bootstrap-component-css.yml5
-rw-r--r--changelogs/unreleased/46861-issuable-title-with-longer-username.yml5
-rw-r--r--changelogs/unreleased/46869-deploy-tokens-failed-to-clone-lfs-repository.yml5
-rw-r--r--changelogs/unreleased/46963-add_readme_button_for_non_empty_project.yml5
-rw-r--r--changelogs/unreleased/47040-inconsistent-job-list-in-job-details-view.yml5
-rw-r--r--changelogs/unreleased/47050-quick-actions-case-insensitive.yml5
-rw-r--r--changelogs/unreleased/47145-quick-actions-confidential.yml5
-rw-r--r--changelogs/unreleased/47221-explain-what-groups-are-in-the-new-group-page.yml5
-rw-r--r--changelogs/unreleased/47274-help-users-find-our-contributing-page.yml5
-rw-r--r--changelogs/unreleased/47462-issues-disabled-group-page.yml6
-rw-r--r--changelogs/unreleased/47631-operations-kubernetes-option-is-always-visible-when-repository-or-builds-are-disabled.yml5
-rw-r--r--changelogs/unreleased/47794-environment-scope-cluster-page.yml6
-rw-r--r--changelogs/unreleased/47865-changelog-for-style-updates.yml5
-rw-r--r--changelogs/unreleased/48036-fix-web-ide-blob-crash.yml5
-rw-r--r--changelogs/unreleased/48050-add-full-commit-sha.yml5
-rw-r--r--changelogs/unreleased/48100-fix-branch-not-shown.yml6
-rw-r--r--changelogs/unreleased/48153-date-selection-dialog-broken-when-creating-a-new-milestone.yml5
-rw-r--r--changelogs/unreleased/48237-toggle-file-comments.yml5
-rw-r--r--changelogs/unreleased/48378-avatar-upload.yml5
-rw-r--r--changelogs/unreleased/48497-merge-request-refactor-displays-changes-dropdown-incorrectly.yml5
-rw-r--r--changelogs/unreleased/48515-sql-queries-are-not-shown-from-the-performance-bar-in-safari.yml5
-rw-r--r--changelogs/unreleased/48578-disable-gcp-free-credit-banner-at-instance-level.yml5
-rw-r--r--changelogs/unreleased/48603-merge-request-refactor-title-and-copy-to-clipboard-button-are-behind-the-action-buttons.yml5
-rw-r--r--changelogs/unreleased/48634-header-navbar-line-separator-is-missing.yml5
-rw-r--r--changelogs/unreleased/48661-node-6-and-7-compatibility-broken-by-recent-monaco-editor-upgrade.yml5
-rw-r--r--changelogs/unreleased/48670-application-settings-may-not-be-invalidated-if-migrations-are-run.yml6
-rw-r--r--changelogs/unreleased/48677-also-check-auto_sign_in_with_provider.yml5
-rw-r--r--changelogs/unreleased/48745-project-exports-fail-when-uploads-have-been-migrated-to-object-storage.yml5
-rw-r--r--changelogs/unreleased/48789-remove-event-listeners-scroll.yml6
-rw-r--r--changelogs/unreleased/48817-fix-mr-changes-discussion-navigation.yml5
-rw-r--r--changelogs/unreleased/48825-performance.yml8
-rw-r--r--changelogs/unreleased/48894-fix-rss-button-interaction.yml5
-rw-r--r--changelogs/unreleased/48932-disable-saml-if-omniauth-is-disabled.yml5
-rw-r--r--changelogs/unreleased/48951-clean-up.yml5
-rw-r--r--changelogs/unreleased/48978-fix-helm-installation-on-cluster.yml5
-rw-r--r--changelogs/unreleased/49272-sanitize-git-url-in-import-errors.yml5
-rw-r--r--changelogs/unreleased/accept-rf3-2822-compliant-addresses.yml5
-rw-r--r--changelogs/unreleased/add-missing-index-for-deployments.yml5
-rw-r--r--changelogs/unreleased/add-more-rebase-logging.yml5
-rw-r--r--changelogs/unreleased/add-title-placeholder-for-new-issues.yml5
-rw-r--r--changelogs/unreleased/add-total-time-flat-printer-for-profiling.yml6
-rw-r--r--changelogs/unreleased/an-no-healthcheck-until-brooklyn.yml5
-rw-r--r--changelogs/unreleased/api-minimal-access-level.yml5
-rw-r--r--changelogs/unreleased/author-doc-fix.yml5
-rw-r--r--changelogs/unreleased/backstage-gb-stages-position-migration-clean-up.yml5
-rw-r--r--changelogs/unreleased/bjk-48176_ruby_gc.yml5
-rw-r--r--changelogs/unreleased/blackst0ne-add-gemfile-rails5-lock-check.yml5
-rw-r--r--changelogs/unreleased/blackst0ne-bump-grape-path-helpers-gem-to-1-0-5.yml5
-rw-r--r--changelogs/unreleased/blackst0ne-fix-protect-from-forgery-in-application-controller.yml5
-rw-r--r--changelogs/unreleased/blackst0ne-rails5-activerecord-statementinvalid-mysql2-error-expression-1-of-select-list-is-not-in-group-by-clause.yml5
-rw-r--r--changelogs/unreleased/blackst0ne-rails5-expected-search-search-seed_project-got-nil.yml5
-rw-r--r--changelogs/unreleased/blackst0ne-rails5-expected-the-response-to-have-status-code-ok-but-it-was-404.yml5
-rw-r--r--changelogs/unreleased/blackst0ne-rails5-fix-blob-requests-format.yml5
-rw-r--r--changelogs/unreleased/blackst0ne-rails5-fix-data-store-spec.yml5
-rw-r--r--changelogs/unreleased/blackst0ne-rails5-fix-optimistic-lock-values.yml5
-rw-r--r--changelogs/unreleased/blackst0ne-rails5-fix-pipeline-schedules-controller-spec.yml5
-rw-r--r--changelogs/unreleased/blackst0ne-rails5-fix-snippets-finder.yml5
-rw-r--r--changelogs/unreleased/blackst0ne-rails5-found-new-routes-that-could-cause-conflicts-with-existing-namespaced-routes.yml5
-rw-r--r--changelogs/unreleased/blackst0ne-rails5-invalid-single-table-inheritance-type-group-is-not-a-subclass-of-namespace.yml6
-rw-r--r--changelogs/unreleased/blackst0ne-rails5-set-request-format-in--commits-controller.yml5
-rw-r--r--changelogs/unreleased/blackst0ne-replace-sidekiq-inline-with-perform-enqueued-jobs.yml5
-rw-r--r--changelogs/unreleased/build-chunks-on-object-storage.yml6
-rw-r--r--changelogs/unreleased/bump-carrierwave-to-1-2-3.yml5
-rw-r--r--changelogs/unreleased/bvl-fix-maintainer-push-rejected.yml6
-rw-r--r--changelogs/unreleased/bvl-graphql-nested-merge-request.yml5
-rw-r--r--changelogs/unreleased/bvl-graphql-permissions.yml5
-rw-r--r--changelogs/unreleased/bvl-graphql-pipeline-lists.yml5
-rw-r--r--changelogs/unreleased/bvl-preload-parents-after-pagination.yml5
-rw-r--r--changelogs/unreleased/bw-enable-commonmark.yml5
-rw-r--r--changelogs/unreleased/cache-doc-fix.yml5
-rw-r--r--changelogs/unreleased/ce-5024-filename-search.yml5
-rw-r--r--changelogs/unreleased/close-revoke-deploy-token-modal-on-escape-keypress.yml5
-rw-r--r--changelogs/unreleased/commits_api_with_stats.yml5
-rw-r--r--changelogs/unreleased/cr-add-locked-state-to-MR.yml5
-rw-r--r--changelogs/unreleased/cr-keep-issue-labels.yml5
-rw-r--r--changelogs/unreleased/da-port-cte-to-ce.yml5
-rw-r--r--changelogs/unreleased/db-configure-after-drop-tables.yml5
-rw-r--r--changelogs/unreleased/dm-blockquote-trailing-whitespace.yml5
-rw-r--r--changelogs/unreleased/dm-branch-api-can-push.yml5
-rw-r--r--changelogs/unreleased/dm-invalid-active-service-template.yml5
-rw-r--r--changelogs/unreleased/dm-label-reference-period.yml5
-rw-r--r--changelogs/unreleased/dm-user-without-projects-performance.yml5
-rw-r--r--changelogs/unreleased/existing-gcp-accounts.yml5
-rw-r--r--changelogs/unreleased/expose-ci-url.yml5
-rw-r--r--changelogs/unreleased/feature-oidc-subject-claim.yml5
-rw-r--r--changelogs/unreleased/fix-boards-issue-highlight.yml5
-rw-r--r--changelogs/unreleased/fix-br-decode.yml5
-rw-r--r--changelogs/unreleased/fix-filename-for-direct-uploads.yml5
-rw-r--r--changelogs/unreleased/fix-gb-fix-deserializing-ci-yaml-variables.yml5
-rw-r--r--changelogs/unreleased/fix-gitaly-mr-creation-limits.yml5
-rw-r--r--changelogs/unreleased/fix-groups-api-ordering.yml4
-rw-r--r--changelogs/unreleased/fix-last-commit-author-link-is-blue.yml5
-rw-r--r--changelogs/unreleased/fix-paragraph-line-height-for-emoji.yml5
-rw-r--r--changelogs/unreleased/fix-performance-problem-of-tags-query.yml5
-rw-r--r--changelogs/unreleased/fix-trace-archive-cron-worker-race-condition.yml5
-rw-r--r--changelogs/unreleased/fix-web-ide-disable-markdown-autocomplete.yml5
-rw-r--r--changelogs/unreleased/fj-43565-wrong-role-displayed.yml5
-rw-r--r--changelogs/unreleased/fj-46278-apply-doorkeeper-scope-patch.yml5
-rw-r--r--changelogs/unreleased/fj-46278-enable-doorkeeper-reuse-access-token.yml6
-rw-r--r--changelogs/unreleased/fj-48123-fix-gitlab-import.yml5
-rw-r--r--changelogs/unreleased/fj-49014-wiki-search-error.yml5
-rw-r--r--changelogs/unreleased/fj-bumping-gollum-lib-and-gollum-rugged-adapter.yml5
-rw-r--r--changelogs/unreleased/fj-web-terminal-ci-build.yml5
-rw-r--r--changelogs/unreleased/fl-mr-refactor-performance-improvements.yml5
-rw-r--r--changelogs/unreleased/frozen-string-app-workers.yml5
-rw-r--r--changelogs/unreleased/frozen-string-enable-app-serializers.yml5
-rw-r--r--changelogs/unreleased/frozen-string-enable-app-uploaders.yml5
-rw-r--r--changelogs/unreleased/frozen-string-enable-app-validators.yml5
-rw-r--r--changelogs/unreleased/frozen-string-enable-app-workers-2.yml5
-rw-r--r--changelogs/unreleased/frozen-string-enable-apps-services-inner-even-more.yml5
-rw-r--r--changelogs/unreleased/frozen-string-vestigial.yml5
-rw-r--r--changelogs/unreleased/gitaly-commit-count-opt-out.yml5
-rw-r--r--changelogs/unreleased/gitaly-opt-out-branch-tag.yml5
-rw-r--r--changelogs/unreleased/gitaly-serverservice-info-timeout.yml5
-rw-r--r--changelogs/unreleased/gitaly-timeouts.yml5
-rw-r--r--changelogs/unreleased/hangouts_chat_integration.yml5
-rw-r--r--changelogs/unreleased/highlight-cluster-settings-message.yml5
-rw-r--r--changelogs/unreleased/ide-commit-actions-update.yml5
-rw-r--r--changelogs/unreleased/ide-merge-request-info.yml5
-rw-r--r--changelogs/unreleased/jprovazn-delete-upload-worker.yml5
-rw-r--r--changelogs/unreleased/jprovazn-direct-upload.yml5
-rw-r--r--changelogs/unreleased/jprovazn-extra-line.yml5
-rw-r--r--changelogs/unreleased/jprovazn-fix-mr-caching.yml5
-rw-r--r--changelogs/unreleased/jprovazn-label-links-update.yml5
-rw-r--r--changelogs/unreleased/jprovazn-upload-symlink.yml5
-rw-r--r--changelogs/unreleased/jr-48133-web-ide-commit-ellipsis.yml5
-rw-r--r--changelogs/unreleased/jupyter-image.yml5
-rw-r--r--changelogs/unreleased/limit-metrics-content-type.yml5
-rw-r--r--changelogs/unreleased/more-group-api-sorting-options.yml5
-rw-r--r--changelogs/unreleased/move-boards-modal-empty-state-vue-component.yml5
-rw-r--r--changelogs/unreleased/no-multi-assign-enable.yml5
-rw-r--r--changelogs/unreleased/no-multi-assign-follow-up.yml5
-rw-r--r--changelogs/unreleased/no-restricted-globals-enable.yml5
-rw-r--r--changelogs/unreleased/osw-delete-non-latest-mr-diff-files-migration.yml5
-rw-r--r--changelogs/unreleased/osw-delete-non-latest-mr-diff-files-upon-merge.yml5
-rw-r--r--changelogs/unreleased/osw-fallback-to-collection-when-no-diff-refs.yml5
-rw-r--r--changelogs/unreleased/osw-mark-as-merged-as-first-post-merge-action.yml5
-rw-r--r--changelogs/unreleased/perf-wiki-pattern-once.yml5
-rw-r--r--changelogs/unreleased/pr-importer-io-extra-error-handling.yml5
-rw-r--r--changelogs/unreleased/prefer-destructuring-fix.yml5
-rw-r--r--changelogs/unreleased/project-dropdown-list-overflow.yml5
-rw-r--r--changelogs/unreleased/project-visibility-tooltip.yml5
-rw-r--r--changelogs/unreleased/prune-web-hook-logs.yml5
-rw-r--r--changelogs/unreleased/rails5-fix-46276.yml5
-rw-r--r--changelogs/unreleased/rails5-fix-47366.yml5
-rw-r--r--changelogs/unreleased/rails5-fix-47370.yml5
-rw-r--r--changelogs/unreleased/rails5-fix-47804.yml5
-rw-r--r--changelogs/unreleased/rails5-fix-47805.yml6
-rw-r--r--changelogs/unreleased/rails5-fix-47835.yml6
-rw-r--r--changelogs/unreleased/rails5-fix-47836.yml6
-rw-r--r--changelogs/unreleased/rails5-fix-47960.yml5
-rw-r--r--changelogs/unreleased/rails5-fix-48009.yml5
-rw-r--r--changelogs/unreleased/rails5-fix-48012.yml6
-rw-r--r--changelogs/unreleased/rails5-fix-48104.yml6
-rw-r--r--changelogs/unreleased/rails5-fix-48140.yml6
-rw-r--r--changelogs/unreleased/rails5-fix-48141.yml6
-rw-r--r--changelogs/unreleased/rails5-fix-48142.yml5
-rw-r--r--changelogs/unreleased/rails5-fix-48430.yml5
-rw-r--r--changelogs/unreleased/rails5-fix-48432.yml5
-rw-r--r--changelogs/unreleased/rails5-fix-db-check.yml5
-rw-r--r--changelogs/unreleased/rails5-fix-mysql-arel-from.yml5
-rw-r--r--changelogs/unreleased/rails5-fix-pages-controller.yml5
-rw-r--r--changelogs/unreleased/rails5-fix-revert-modal-spec.yml5
-rw-r--r--changelogs/unreleased/rd-33733-showing-created-date-instead-of-updated-date-in-project-lists.yml5
-rw-r--r--changelogs/unreleased/regen-2fa-codes.yml5
-rw-r--r--changelogs/unreleased/remove-allocations-gem.yml5
-rw-r--r--changelogs/unreleased/remove-ci_job_request_with_tags_matcher.yml5
-rw-r--r--changelogs/unreleased/remove-is-shared-from-ci-runners.yml5
-rw-r--r--changelogs/unreleased/remove-link-label-vertical-alignment-property.yml5
-rw-r--r--changelogs/unreleased/remove-small-container-width.yml5
-rw-r--r--changelogs/unreleased/remove-trace-efficiently.yml5
-rw-r--r--changelogs/unreleased/revert-merge-request-discussion-buttons-padding.yml5
-rw-r--r--changelogs/unreleased/safari-scrollbar-bug.yml5
-rw-r--r--changelogs/unreleased/security-2682-fix-xss-for-markdown-toc.yml5
-rw-r--r--changelogs/unreleased/security-fj-bumping-sanitize-gem.yml5
-rw-r--r--changelogs/unreleased/security-html_escape_branch_name.yml5
-rw-r--r--changelogs/unreleased/security-html_escape_usernames.yml5
-rw-r--r--changelogs/unreleased/security-rd-do-not-show-internal-info-in-public-feed.yml5
-rw-r--r--changelogs/unreleased/sh-bump-rugged-0-27-2.yml5
-rw-r--r--changelogs/unreleased/sh-bump-sanitize-4-6-6.yml5
-rw-r--r--changelogs/unreleased/sh-enable-frozen-literals-banzi-filters.yml5
-rw-r--r--changelogs/unreleased/sh-fix-bamboo-change-set.yml5
-rw-r--r--changelogs/unreleased/sh-freeze-banzai-filter-strings.yml5
-rw-r--r--changelogs/unreleased/sh-normalize-urls.yml5
-rw-r--r--changelogs/unreleased/sh-optimize-locks-check-ce.yml5
-rw-r--r--changelogs/unreleased/sh-remove-banzai-instrumentation.yml5
-rw-r--r--changelogs/unreleased/straight-comparision-mode.yml5
-rw-r--r--changelogs/unreleased/tc-repo-check-per-shard.yml5
-rw-r--r--changelogs/unreleased/text-expander-icon-update.yml5
-rw-r--r--changelogs/unreleased/transfer_project_api_endpoint.yml5
-rw-r--r--changelogs/unreleased/tz-diff-blob-image-viewer.yml5
-rw-r--r--changelogs/unreleased/tz-mr-refactor-memory-reduction.yml5
-rw-r--r--changelogs/unreleased/unify-views-search-results.yml5
-rw-r--r--changelogs/unreleased/update-bcrypt-to-support-libxcrypt.yml5
-rw-r--r--changelogs/unreleased/update-environments-nav-controls.yml5
-rw-r--r--changelogs/unreleased/update-external-link-icon-in-header-user-dropdown.yml5
-rw-r--r--changelogs/unreleased/update-external-link-icon-in-merge-request-widget.yml5
-rw-r--r--changelogs/unreleased/update-integrations-external-link-icons.yml5
-rw-r--r--changelogs/unreleased/update-pipeline-icon-in-web-ide-sidebar.yml5
-rw-r--r--changelogs/unreleased/upgrade-gitlab-markup.yml5
-rw-r--r--changelogs/unreleased/use-backup-custom-hooks-gitaly.yml5
-rw-r--r--changelogs/unreleased/use-tooltip-component-in-mr-widget-author-time-component.yml5
-rw-r--r--changelogs/unreleased/web-hooks-log-pagination.yml5
-rw-r--r--changelogs/unreleased/winh-new-branch-url-encode.yml5
-rw-r--r--changelogs/unreleased/winh-tree-view-gpg.yml5
-rw-r--r--changelogs/unreleased/zj-gitaly-read-write-check.yml5
-rw-r--r--config/boot.rb5
-rw-r--r--config/gitlab.yml.example16
-rw-r--r--config/initializers/1_settings.rb4
-rw-r--r--config/initializers/8_metrics.rb16
-rw-r--r--config/initializers/bootstrap_form.rb2
-rw-r--r--config/initializers/devise.rb2
-rw-r--r--config/initializers/omniauth.rb5
-rw-r--r--config/sidekiq_queues.yml2
-rw-r--r--db/migrate/20161124141322_migrate_process_commit_worker_jobs.rb54
-rw-r--r--db/migrate/20161226122833_remove_dot_git_from_usernames.rb12
-rw-r--r--doc/administration/monitoring/prometheus/gitlab_metrics.md2
-rw-r--r--doc/administration/pages/index.md45
-rw-r--r--doc/api/groups.md10
-rw-r--r--doc/api/issues.md6
-rw-r--r--doc/api/jobs.md26
-rw-r--r--doc/api/pipelines.md18
-rw-r--r--doc/api/projects.md24
-rw-r--r--doc/api/services.md48
-rw-r--r--doc/ci/variables/README.md4
-rw-r--r--doc/ci/yaml/README.md38
-rw-r--r--doc/development/README.md1
-rw-r--r--doc/development/profiling.md30
-rw-r--r--doc/development/pry_debugging.md130
-rw-r--r--doc/development/testing_guide/best_practices.md2
-rw-r--r--doc/topics/autodevops/index.md2
-rw-r--r--doc/update/mysql_to_postgresql.md18
-rw-r--r--doc/user/project/clusters/index.md2
-rw-r--r--doc/user/project/integrations/emails_on_push.md2
-rw-r--r--doc/user/project/integrations/hangouts_chat.md27
-rw-r--r--doc/user/project/integrations/img/hangouts_chat_configuration.pngbin0 -> 101788 bytes
-rw-r--r--doc/user/project/integrations/project_services.md1
-rw-r--r--doc/user/project/merge_requests/img/merge_request.pngbin67228 -> 748131 bytes
-rw-r--r--doc/user/project/milestones/img/milestones_new_group_milestone.pngbin156704 -> 276831 bytes
-rw-r--r--doc/user/project/milestones/img/milestones_new_project_milestone.pngbin173762 -> 257285 bytes
-rw-r--r--doc/user/project/milestones/img/milestones_promote_milestone.pngbin350399 -> 76864 bytes
-rw-r--r--lib/api/entities.rb10
-rw-r--r--lib/api/groups.rb3
-rw-r--r--lib/api/helpers.rb1
-rw-r--r--lib/api/jobs.rb2
-rw-r--r--lib/api/projects.rb22
-rw-r--r--lib/api/services.rb9
-rw-r--r--lib/api/users.rb1
-rw-r--r--lib/banzai/filter/absolute_link_filter.rb2
-rw-r--r--lib/banzai/filter/abstract_reference_filter.rb2
-rw-r--r--lib/banzai/filter/ascii_doc_post_processing_filter.rb2
-rw-r--r--lib/banzai/filter/autolink_filter.rb2
-rw-r--r--lib/banzai/filter/blockquote_fence_filter.rb2
-rw-r--r--lib/banzai/filter/color_filter.rb2
-rw-r--r--lib/banzai/filter/commit_range_reference_filter.rb2
-rw-r--r--lib/banzai/filter/commit_reference_filter.rb2
-rw-r--r--lib/banzai/filter/commit_trailers_filter.rb2
-rw-r--r--lib/banzai/filter/emoji_filter.rb2
-rw-r--r--lib/banzai/filter/epic_reference_filter.rb2
-rw-r--r--lib/banzai/filter/external_issue_reference_filter.rb2
-rw-r--r--lib/banzai/filter/external_link_filter.rb2
-rw-r--r--lib/banzai/filter/gollum_tags_filter.rb2
-rw-r--r--lib/banzai/filter/html_entity_filter.rb2
-rw-r--r--lib/banzai/filter/image_lazy_load_filter.rb4
-rw-r--r--lib/banzai/filter/image_link_filter.rb2
-rw-r--r--lib/banzai/filter/inline_diff_filter.rb2
-rw-r--r--lib/banzai/filter/issuable_reference_filter.rb2
-rw-r--r--lib/banzai/filter/issuable_state_filter.rb2
-rw-r--r--lib/banzai/filter/issue_reference_filter.rb2
-rw-r--r--lib/banzai/filter/label_reference_filter.rb2
-rw-r--r--lib/banzai/filter/markdown_filter.rb2
-rw-r--r--lib/banzai/filter/math_filter.rb2
-rw-r--r--lib/banzai/filter/merge_request_reference_filter.rb2
-rw-r--r--lib/banzai/filter/mermaid_filter.rb2
-rw-r--r--lib/banzai/filter/milestone_reference_filter.rb2
-rw-r--r--lib/banzai/filter/plantuml_filter.rb2
-rw-r--r--lib/banzai/filter/redactor_filter.rb2
-rw-r--r--lib/banzai/filter/reference_filter.rb2
-rw-r--r--lib/banzai/filter/relative_link_filter.rb2
-rw-r--r--lib/banzai/filter/sanitization_filter.rb2
-rw-r--r--lib/banzai/filter/set_direction_filter.rb2
-rw-r--r--lib/banzai/filter/snippet_reference_filter.rb2
-rw-r--r--lib/banzai/filter/syntax_highlight_filter.rb4
-rw-r--r--lib/banzai/filter/table_of_contents_filter.rb4
-rw-r--r--lib/banzai/filter/task_list_filter.rb2
-rw-r--r--lib/banzai/filter/user_reference_filter.rb2
-rw-r--r--lib/banzai/filter/video_link_filter.rb2
-rw-r--r--lib/banzai/filter/wiki_link_filter.rb2
-rw-r--r--lib/banzai/filter/yaml_front_matter_filter.rb2
-rw-r--r--lib/feature.rb2
-rw-r--r--lib/gitlab/auth.rb19
-rw-r--r--lib/gitlab/auth/o_auth/provider.rb2
-rw-r--r--lib/gitlab/ci/variables/collection/item.rb2
-rw-r--r--lib/gitlab/git/operation_service.rb2
-rw-r--r--lib/gitlab/git/repository.rb76
-rw-r--r--lib/gitlab/git/repository_mirroring.rb81
-rw-r--r--lib/gitlab/git_ref_validator.rb8
-rw-r--r--lib/gitlab/gitaly_client/operation_service.rb11
-rw-r--r--lib/gitlab/gitaly_client/ref_service.rb19
-rw-r--r--lib/gitlab/gitlab_import/client.rb30
-rw-r--r--lib/gitlab/import_export/merge_request_parser.rb1
-rw-r--r--lib/gitlab/json_logger.rb22
-rw-r--r--lib/gitlab/omniauth_initializer.rb30
-rw-r--r--lib/gitlab/profiler.rb6
-rw-r--r--lib/gitlab/profiler/total_time_flat_printer.rb39
-rw-r--r--lib/gitlab/project_search_results.rb19
-rw-r--r--lib/gitlab/serializer/ci/variables.rb5
-rw-r--r--lib/gitlab/url_sanitizer.rb15
-rw-r--r--lib/gitlab/usage_data.rb2
-rw-r--r--lib/gitlab/user_activities.rb34
-rw-r--r--lib/tasks/gitlab/cleanup.rake23
-rw-r--r--lib/tasks/gitlab/info.rake4
-rw-r--r--locale/gitlab.pot8
-rw-r--r--package.json1
-rwxr-xr-xscripts/lint-rugged5
-rw-r--r--spec/controllers/sessions_controller_spec.rb4
-rw-r--r--spec/features/merge_request/user_posts_diff_notes_spec.rb4
-rw-r--r--spec/features/merge_request/user_resolves_diff_notes_and_discussions_resolve_spec.rb5
-rw-r--r--spec/features/projects/commits/user_browses_commits_spec.rb1
-rw-r--r--spec/features/signed_commits_spec.rb10
-rw-r--r--spec/features/user_sees_revert_modal_spec.rb3
-rw-r--r--spec/fixtures/api/schemas/pipeline.json4
-rw-r--r--spec/fixtures/api/schemas/public_api/v4/pipeline/basic.json6
-rw-r--r--spec/fixtures/api/schemas/public_api/v4/projects.json15
-rw-r--r--spec/helpers/button_helper_spec.rb6
-rw-r--r--spec/helpers/visibility_level_helper_spec.rb23
-rw-r--r--spec/javascripts/diffs/components/diff_line_gutter_content_spec.js6
-rw-r--r--spec/javascripts/gpg_badges_spec.js76
-rw-r--r--spec/javascripts/helpers/vuex_action_helper.js12
-rw-r--r--spec/javascripts/helpers/vuex_action_helper_spec.js25
-rw-r--r--spec/javascripts/ide/components/new_dropdown/modal_spec.js2
-rw-r--r--spec/javascripts/ide/ide_router_spec.js44
-rw-r--r--spec/javascripts/notes/components/discussion_counter_spec.js2
-rw-r--r--spec/javascripts/notes/components/noteable_discussion_spec.js47
-rw-r--r--spec/javascripts/notes/mock_data.js84
-rw-r--r--spec/javascripts/notes/stores/getters_spec.js155
-rw-r--r--spec/javascripts/reports/store/actions_spec.js130
-rw-r--r--spec/javascripts/reports/store/mutations_spec.js101
-rw-r--r--spec/javascripts/vue_shared/components/clipboard_button_spec.js2
-rw-r--r--spec/lib/banzai/filter/image_lazy_load_filter_spec.rb14
-rw-r--r--spec/lib/feature_spec.rb32
-rw-r--r--spec/lib/gitlab/ci/variables/collection/item_spec.rb8
-rw-r--r--spec/lib/gitlab/git/repository_spec.rb53
-rw-r--r--spec/lib/gitlab/gitaly_client/operation_service_spec.rb134
-rw-r--r--spec/lib/gitlab/gitaly_client/ref_service_spec.rb38
-rw-r--r--spec/lib/gitlab/gitlab_import/client_spec.rb84
-rw-r--r--spec/lib/gitlab/hashed_storage/migrator_spec.rb2
-rw-r--r--spec/lib/gitlab/import_export/all_models.yml1
-rw-r--r--spec/lib/gitlab/json_logger_spec.rb29
-rw-r--r--spec/lib/gitlab/project_search_results_spec.rb53
-rw-r--r--spec/lib/gitlab/serializer/ci/variables_spec.rb6
-rw-r--r--spec/lib/gitlab/url_sanitizer_spec.rb6
-rw-r--r--spec/lib/gitlab/usage_data_spec.rb2
-rw-r--r--spec/lib/gitlab/user_activities_spec.rb127
-rw-r--r--spec/migrations/active_record/schedule_set_confidential_note_events_on_services_spec.rb2
-rw-r--r--spec/migrations/migrate_process_commit_worker_jobs_spec.rb69
-rw-r--r--spec/migrations/migrate_stage_id_reference_in_background_spec.rb2
-rw-r--r--spec/migrations/migrate_stages_statuses_spec.rb2
-rw-r--r--spec/migrations/normalize_ldap_extern_uids_spec.rb4
-rw-r--r--spec/migrations/schedule_create_gpg_key_subkeys_from_gpg_keys_spec.rb2
-rw-r--r--spec/migrations/schedule_merge_request_diff_migrations_spec.rb2
-rw-r--r--spec/migrations/schedule_merge_request_diff_migrations_take_two_spec.rb2
-rw-r--r--spec/migrations/schedule_merge_request_latest_merge_request_diff_id_migrations_spec.rb2
-rw-r--r--spec/migrations/schedule_set_confidential_note_events_on_webhooks_spec.rb2
-rw-r--r--spec/models/ci/build_spec.rb28
-rw-r--r--spec/models/ci/build_trace_chunk_spec.rb4
-rw-r--r--spec/models/deploy_token_spec.rb9
-rw-r--r--spec/models/project_services/hangouts_chat_service_spec.rb246
-rw-r--r--spec/models/project_spec.rb1
-rw-r--r--spec/models/repository_spec.rb14
-rw-r--r--spec/models/spam_log_spec.rb2
-rw-r--r--spec/requests/api/environments_spec.rb2
-rw-r--r--spec/requests/api/groups_spec.rb19
-rw-r--r--spec/requests/api/internal_spec.rb16
-rw-r--r--spec/requests/api/jobs_spec.rb1
-rw-r--r--spec/requests/api/pipelines_spec.rb3
-rw-r--r--spec/requests/api/project_import_spec.rb2
-rw-r--r--spec/requests/api/projects_spec.rb32
-rw-r--r--spec/requests/api/users_spec.rb14
-rw-r--r--spec/requests/git_http_spec.rb5
-rw-r--r--spec/requests/lfs_http_spec.rb38
-rw-r--r--spec/services/event_create_service_spec.rb4
-rw-r--r--spec/services/groups/destroy_service_spec.rb2
-rw-r--r--spec/services/projects/create_from_template_service_spec.rb2
-rw-r--r--spec/services/projects/destroy_service_spec.rb14
-rw-r--r--spec/services/projects/housekeeping_service_spec.rb2
-rw-r--r--spec/services/projects/import_service_spec.rb4
-rw-r--r--spec/services/users/activity_service_spec.rb65
-rw-r--r--spec/services/users/destroy_service_spec.rb2
-rw-r--r--spec/support/helpers/user_activities_helpers.rb7
-rw-r--r--spec/support/matchers/user_activity_matchers.rb5
-rw-r--r--spec/workers/emails_on_push_worker_spec.rb61
-rw-r--r--spec/workers/schedule_update_user_activity_worker_spec.rb25
-rw-r--r--spec/workers/storage_migrator_worker_spec.rb2
-rw-r--r--spec/workers/update_user_activity_worker_spec.rb35
-rw-r--r--vendor/jupyter/values.yaml1
-rw-r--r--yarn.lock4
727 files changed, 4279 insertions, 2661 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index e1a6a014c57..7cc047c40ed 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,257 @@
documentation](doc/development/changelog.md) for instructions on adding your own
entry.
+## 11.1.1 (2018-07-23)
+
+### Fixed (2 changes)
+
+- Add missing Gitaly branch_update nil checks. !20711
+- Fix filename for accelerated uploads.
+
+### Added (1 change)
+
+- Add uploader support to Import/Export uploads. !20484
+
+
+## 11.1.0 (2018-07-22)
+
+### Security (6 changes)
+
+- Fix XSS vulnerability for table of content generation.
+- Update sanitize gem to 4.6.5 to fix HTML injection vulnerability.
+- HTML escape branch name in project graphs page.
+- HTML escape the name of the user in ProjectsHelper#link_to_member.
+- Don't show events from internal projects for anonymous users in public feed.
+- Fix symlink vulnerability in project import.
+
+### Removed (1 change)
+
+- Remove deprecated object_storage_upload queue.
+
+### Fixed (98 changes, 52 of them are from the community)
+
+- Keep lists ordered when copying only list items. !18522 (Jan Beckmann)
+- Fix bug where maintainer would not be allowed to push to forks with merge requests that have `Allow maintainer edits` enabled. !18968
+- mergeError message has been binded using v-html directive. !19058 (Murat Dogan)
+- Set MR target branch to default branch if target branch is not valid. !19067
+- Fix CSS for buttons not to be hidden on issues/MR title. !19176 (Takuya Noguchi)
+- Use same gem versions for rails5 as for rails4 where possible. !19498 (Jasper Maes)
+- Fix extra blank line at start of rendered reStructuredText code block. !19596
+- Fix username validation order on signup, resolves #45575. !19610 (Jan Beckmann)
+- Make quick commands case insensitive. !19614 (Jan Beckmann)
+- Remove incorrect CI doc re: PowerShell. !19622 (gfyoung)
+- Fixes Microsoft Teams notifications for pipeline events. !19632 (Jeff Brown)
+- Fix branch name encoding for dropdown on issue page. !19634
+- Rails5 fix expected `issuable.reload.updated_at` to have changed. !19733 (Jasper Maes)
+- Rails5 fix stack level too deep. !19762 (Jasper Maes)
+- Rails5 ActionController::ParameterMissing: param is missing or the value is empty: application_setting. !19763 (Jasper Maes)
+- Invalidate cache with project details when repository is updated. !19774
+- Rails5 fix no implicit conversion of Hash into String. ActionController::Parameters no longer returns an hash in Rails 5. !19792 (Jasper Maes)
+- [Rails5] Fix snippets_finder arel queries. !19796 (@blackst0ne)
+- Fix fields for author & assignee in MR API docs. !19798 (gfyoung)
+- Remove scrollbar in Safari in repo settings page. !19809 (gfyoung)
+- Omits operartions and kubernetes item from project sidebar when repository or builds are disabled. !19835
+- Rails5 fix passing Group objects array into for_projects_and_groups milestone scope. !19863 (Jasper Maes)
+- Fix chat service tag notifications not sending when only default branch enabled. !19864
+- Only show new issue / new merge request on group page when issues / merge requests are enabled. !19869 (Jan Beckmann)
+- [Rails5] Explicitly set request.format for blob_controller. !19876 (@blackst0ne)
+- [Rails5] Fix optimistic lock value. !19878 (@blackst0ne)
+- Rails5 fix update_attribute usage not causing a save. !19881 (Jasper Maes)
+- Rails5 fix connection execute return integer instead of string. !19901 (Jasper Maes)
+- Rails5 fix format in uploads actions. !19907 (Jasper Maes)
+- [Rails5] Fix "-1 is not a valid data_store". !19917 (@blackst0ne)
+- [Rails5] Invalid single-table inheritance type: Group is not a subclass of Namespace. !19918 (@blackst0ne)
+- [Rails5] Fix pipeline_schedules_controller_spec. !19919 (@blackst0ne)
+- Rails5 fix passing Group objects array into for_projects_and_groups milestone scope. !19920 (Jasper Maes)
+- Rails5 update Gemfile.rails5.lock. !19921 (Jasper Maes)
+- [Rails5] Fix sessions_controller_spec. !19936 (@blackst0ne)
+- [Rails5] Set request.format for artifacts_controller. !19937 (@blackst0ne)
+- Fix webhook error when password is not present. !19945 (Jan Beckmann)
+- Fix label and milestone duplicated records and IID errors. !19961
+- Rails5 fix expected: 1 time with arguments: (97, anything, {"squash"=>false}) received: 0 times. !20004 (Jasper Maes)
+- Rails5 fix Projects::PagesController spec. !20007 (Jasper Maes)
+- [Rails5] Fix ActionCable '/cable' mountpoint conflict. !20015 (@blackst0ne)
+- Fix branches are not shown in Merge Request dropdown when preferred language is not English. !20016 (Hiroyuki Sato)
+- Rails5 fix Admin::HooksController. !20017 (Jasper Maes)
+- Rails5 fix expected: 0 times with any arguments received: 1 time with arguments: DashboardController. !20018 (Jasper Maes)
+- [Rails5] Set request.format in commits_controller. !20023 (@blackst0ne)
+- Keeps the label on an issue when the issue is moved. !20036
+- Cleanup Prometheus ruby metrics. !20039 (Ben Kochie)
+- Rails 5 fix Capybara::ElementNotFound: Unable to find visible css #modal-revert-commit and expected: "/bar" got: "/foo". !20044 (Jasper Maes)
+- [Rails5] Force the callback run first. !20055 (@blackst0ne)
+- Add readme button to non-empty project page. !20104
+- Fixed bug when editing a comment in an issue,the preview mode is toggled in the main textarea. !20112 (Constance Okoghenun)
+- Ignore unknown OAuth sources in ApplicationSetting. !20129
+- Fix paragraph line height for emoji. !20137 (George Tsiolis)
+- Fixes issue with uploading same image to Profile Avatar twice. !20161 (Chirag Bhatia)
+- Rails5 fix arel from in mysql_median_datetime_sql. !20167 (Jasper Maes)
+- Adds the `locked` state to the merge request API so that it can be used as a search filter. !20186
+- Enable Doorkeeper option to avoid generating new tokens when users login via oauth. !20200
+- Fix OAuth Application Authorization screen to appear with each access. !20216
+- Rails5 fix MySQL milliseconds problem in specs. !20221 (Jasper Maes)
+- Rails5 fix Mysql comparison failure caused by milliseconds problem. !20222 (Jasper Maes)
+- Updated last commit link color. !20234 (Constance Okoghenun)
+- Fixed Merge request changes dropdown displays incorrectly. !20237 (Constance Okoghenun)
+- Show jobs from same pipeline in sidebar in job details view. !20243
+- [Rails5] Fix milestone GROUP BY query. !20256 (@blackst0ne)
+- Line separator to the left of the 'Admin area' wrench icon had vanished. !20282 (bitsapien)
+- Check if archived trace exist before archive it. !20297
+- Load Devise with Omniauth when auto_sign_in_with_provider is configured. !20302
+- Fix link to job when creating a new issue from a failed job. !20328
+- Fix double "in" in time to artifact deletion message. !20357 (@bbodenmiller)
+- Fix wrong role badge displayed in projects dashboard. !20374
+- Stop relying on migrations in the CacheableAttributes cache key and cache attributes for 1 minute instead. !20389
+- Fixes toggle discussion button not expanding collapsed discussions. !20452
+- Resolve compatibility issues with node 6. !20461
+- Fixes base command used in Helm installations. !20471
+- Fix RSS button interaction on Dashboard, Project and Group activities. !20549
+- Use appropriate timeout on Gitaly server info checks, avoid error on timeout. !20552
+- Remove healthchecks from prometheus endpoint. !20565
+- Render MR page when diffs cannot be fetched from the database or the git repository. !20680
+- Expire correct method caches after HEAD changed.
+- Ensure MR diffs always exist in the PR importer.
+- Fix overlapping file title and file actions in MR changes tag.
+- Mark MR as merged regardless of errors when closing issues.
+- Fix performance bar modal visibility in Safari.
+- Prevent browser autocomplete for milestone date fields.
+- Limit the action suffixes in transaction metrics.
+- Add /uploads subdirectory to allowed upload paths.
+- Fix cross-project label references.
+- Invalidate merge request diffs cache if diff data change.
+- Don't show context button for diffs of deleted files.
+- Structure getters for diff Store properly and adds specs.
+- Bump rugged to 0.27.2.
+- Fix Bamboo CI status not showing for branch plans.
+- Fixed bug that allowed to remove other wiki pages if the title had wildcard characters.
+- Disabled Web IDE autocomplete suggestions for Markdown files. (Isaac Smith)
+- Fix merge request diffs when created with gitaly_diff_between enabled.
+- Properly detect label reference if followed by period or question mark.
+- Deactivate new KubernetesService created from active template to prevent project creation from failing.
+- Allow trailing whitespace on blockquote fence lines.
+
+### Deprecated (1 change)
+
+- Removes unused bootstrap 4 scss files. !19423
+
+### Changed (33 changes, 16 of them are from the community)
+
+- Change label link vertical alignment property. !18777 (George Tsiolis)
+- Updated the icon for expand buttons to ellipsis. !18793 (Constance Okoghenun)
+- Create new or add existing Kubernetes cluster from a single page. !18963
+- Use object storage as the first class persistable store for new live trace architecture. !19515
+- Hide project name if searching against a project. !19595
+- Allows you to create another deploy token dimmediately after creating one. !19639
+- Removes the environment scope field for users that cannot edit it. !19643
+- Don't hash user ID in OIDC subject claim. !19784 (Markus Koller)
+- Milestone page list redesign. !19832 (Constance Okoghenun)
+- Add environment dropdown for the metrics page. !19833
+- Allow querying a single merge request within a project. !19853
+- Update WebIDE to show file in tree on load. !19887
+- Remove small container width. !19893 (George Tsiolis)
+- Improve U2F workflow when using unsupported browsers. !19938 (Jan Beckmann)
+- Update Web IDE file tree styles. !19969
+- Highlight cluster settings message. !19996 (George Tsiolis)
+- Fade uneditable area in Web IDE. !20008
+- Update pipeline icon in web ide sidebar. !20058 (George Tsiolis)
+- Revert merge request discussion buttons padding. !20060 (George Tsiolis)
+- Fix boards issue highlight. !20063 (George Tsiolis)
+- Update external link icon in header user dropdown. !20150 (George Tsiolis)
+- Update external link icon in merge request widget. !20154 (George Tsiolis)
+- Update environments nav controls icons. !20199 (George Tsiolis)
+- Update integrations external link icons. !20205 (George Tsiolis)
+- Fixes an issue where migrations instead of schema loading were run. !20227
+- Add title placeholder for new issues. !20271 (George Tsiolis)
+- Close revoke deploy token modal on escape keypress. !20347 (George Tsiolis)
+- Change environment scope text depending on number of project clusters. Update form to only include form-groups.
+- Improve Web IDE commit flow.
+- Add machine type and pricing documentation links, add class to labels to make bold.
+- Remove remaining traces of the Allocations Gem.
+- Use one column form layout on Admin Area Settings page.
+- Add back copy for existing gcp accounts within offer banner.
+
+### Performance (16 changes, 4 of them are from the community)
+
+- Fully migrate pipeline stages position. !19369
+- Use Tooltip component in MrWidgetAuthorTime vue comonent. !19635 (George Tsiolis)
+- Move boards modal EmptyState vue component. !20068 (George Tsiolis)
+- Bump carrierwave gem verion to 1.2.3. !20287
+- Remove redundant query when removing trace. !20324
+- Improves performance of mr code, by fixing the state being mutated outside of the store in the util function trimFirstCharOfLineContent and in map operations. Avoids map operation in an empty array. Adds specs to the trimFirstCharOfLineContent function. !20380 (filipa)
+- Reduce the number of queries when searching for groups. !20398
+- Improve render performance of large wiki pages. !20465 (Peter Leitzen)
+- Improves performance on Merge Request diff tab by removing the scroll event listeners being added to every file.
+- Remove the ci_job_request_with_tags_matcher.
+- Updated Gitaly fail-fast timeout values.
+- Add index on deployable_type/id for deployments.
+- Eliminate N+1 queries in LFS file locks checks during a push.
+- Fix performance problem of accessing tag list for projects api endpoints.
+- Improve performance of listing users without projects.
+- Fixed pagination of web hook logs.
+
+### Added (29 changes, 9 of them are from the community)
+
+- Add dropdown to Groups link in top bar. !18280
+- Web IDE supports now Image + Download Diff Viewing. !18768
+- Use CommonMark syntax and rendering for new Markdown content. !19331
+- Add SHA256 and HEAD on File API. !19439 (ahmet2mir)
+- Add filename filtering to code search. !19509
+- Add CI_PIPELINE_URL and CI_JOB_URL. !19618
+- Expose visibility via Snippets API. !19620 (Jan Beckmann)
+- Fixed pagination of groups API. !19665 (Marko, Peter)
+- Added id sorting option to GET groups and subgroups API. !19665 (Marko, Peter)
+- Add a link to the contributing page in the user dropdown. !19708
+- Add Object Storage to project export. !20105
+- Change avatar image in the header when user updates their avatar. !20119 (Jamie Schembri)
+- Allow straight diff in Compare API. !20120 (Maciej Nowak)
+- Add transfer project API endpoint. !20122 (Aram Visser)
+- Expose permissions of the current user on resources in GraphQL. !20152
+- Run repository checks in parallel for each shard. !20179
+- Add pipeline lists to GraphQL. !20249
+- Add option to add README when creating a project. !20335
+- Add option to hide third party offers in admin application settings. !20379
+- Add /confidential quick action. (Jan Beckmann)
+- Support direct_upload for generic uploads.
+- Display merge request title & description in Web IDE.
+- Prune web hook logs older than 90 days.
+- Add Web Terminal for Ci Builds. (Vicky Chijwani)
+- Expose whether current user can push into a branch on branches API.
+- Present state indication on GFM preview.
+- migrate backup rake task to gitaly.
+- Add Gitlab::SQL:CTE for easily building CTE statements.
+- Added with_statsoption for GET /projects/:id/repository/commits.
+
+### Other (28 changes, 11 of them are from the community)
+
+- Move some Gitaly RPC's to opt-out. !19591
+- Bump grape-path-helpers to 1.0.5. !19604 (@blackst0ne)
+- Add CI job to check Gemfile.rails5.lock. !19605 (@blackst0ne)
+- Move Gitaly branch/tag/ref RPC's to opt-out. !19644
+- CE port gitlab-ee!6112. !19714
+- Enable no-multi-assignment in JS files. !19808 (gfyoung)
+- Enable no-restricted globals in JS files. !19877 (gfyoung)
+- Improve no-multi-assignment fixes after enabling rule. !19915 (gfyoung)
+- Enable prefer-structuring in JS files. !19943 (gfyoung)
+- Enable frozen string in app/workers/*.rb. !19944 (gfyoung)
+- Uses long sha version of the merged commit in MR widget copy to clipboard button. !19955
+- Update new group page to better explain what groups are. !19991
+- Update new SSH key page to improve copy. !19994
+- Update new SSH key page to improve key input validation. !19997
+- Gitaly metrics check for read/writeability. !20022
+- Add ellispsis to web ide commit button. !20030
+- Minor style changes to personal access token form and scope checkboxes. !20052
+- Finish enabling frozen string for app/workers/*.rb. !20197 (gfyoung)
+- Allows settings sections to expand by default when linking to them. !20211
+- Enable frozen string in apps/validators/*.rb. !20220 (gfyoung)
+- update bcrypt to also support libxcrypt. !20260 (muhammadn)
+- Enable frozen string in apps/validators/*.rb. !20382 (gfyoung)
+- Removes unused vuex code in mr refactor and removes unneeded dependencies. !20499
+- Delete non-latest merge request diff files upon merge.
+- Schedule workers to delete non-latest diffs in post-migration.
+- Remove the use of `is_shared` of `Ci::Runner`.
+- Add more detailed logging to githost.log when rebasing.
+- Use monospaced font for MR diff commit link ref on GFM.
+
+
## 11.0.4 (2018-07-17)
### Security (1 change)
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 4a1fa39b41d..ad8022e972f 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -133,7 +133,7 @@ Most issues will have labels for at least one of the following:
- Type: ~"feature proposal", ~bug, ~customer, etc.
- Subject: ~wiki, ~"container registry", ~ldap, ~api, ~frontend, etc.
-- Team: ~"CI/CD", ~Discussion, ~Quality, ~Platform, etc.
+- Team: ~"CI/CD", ~Plan, ~Manage, ~Quality, etc.
- Release Scoping: ~Deliverable, ~Stretch, ~"Next Patch Release"
- Priority: ~P1, ~P2, ~P3, ~P4
- Severity: ~S1, ~S2, ~S3, ~S4
@@ -187,13 +187,14 @@ The current team labels are:
- ~Configuration
- ~"CI/CD"
-- ~Discussion
+- ~Create
- ~Distribution
- ~Documentation
- ~Geo
- ~Gitaly
+- ~Manage
- ~Monitoring
-- ~Platform
+- ~Plan
- ~Quality
- ~Release
- ~"Security Products"
@@ -375,8 +376,14 @@ on those issues. Please select someone with relevant experience from the
[GitLab team][team]. If there is nobody mentioned with that expertise look in
the commit history for the affected files to find someone.
+We also use [GitLab Triage] to automate some triaging policies. This is
+currently setup as a [scheduled pipeline] running on the [`gl-triage`] branch.
+
[described in our handbook]: https://about.gitlab.com/handbook/engineering/issue-triage/
[issue bash events]: https://gitlab.com/gitlab-org/gitlab-ce/issues/17815
+[GitLab Triage]: https://gitlab.com/gitlab-org/gitlab-triage
+[scheduled pipeline]: https://gitlab.com/gitlab-org/gitlab-ce/pipeline_schedules/3732/edit
+[`gl-triage`]: https://gitlab.com/gitlab-org/gitlab-ce/tree/gl-triage
### Feature proposals
diff --git a/GITALY_SERVER_VERSION b/GITALY_SERVER_VERSION
index e23e3fd2982..5fea1768541 100644
--- a/GITALY_SERVER_VERSION
+++ b/GITALY_SERVER_VERSION
@@ -1 +1 @@
-0.112.0
+0.113.0
diff --git a/Gemfile b/Gemfile
index d575568adaa..47815f230d3 100644
--- a/Gemfile
+++ b/Gemfile
@@ -220,6 +220,9 @@ gem 'gemnasium-gitlab-service', '~> 0.2'
# Slack integration
gem 'slack-notifier', '~> 1.5.1'
+# Hangouts Chat integration
+gem 'hangouts-chat', '~> 0.0.5'
+
# Asana integration
gem 'asana', '~> 0.6.0'
@@ -230,7 +233,7 @@ gem 'ruby-fogbugz', '~> 0.2.1'
gem 'kubeclient', '~> 3.1.0'
# Sanitize user input
-gem 'sanitize', '~> 4.6.5'
+gem 'sanitize', '~> 4.6'
gem 'babosa', '~> 1.0.2'
# Sanitizes SVG input
@@ -323,6 +326,7 @@ group :development do
end
group :development, :test do
+ gem 'bootsnap', '~> 1.3'
gem 'bullet', '~> 5.5.0', require: !!ENV['ENABLE_BULLET']
gem 'pry-byebug', '~> 3.4.1', platform: :mri
gem 'pry-rails', '~> 0.3.4'
@@ -418,7 +422,7 @@ group :ed25519 do
end
# Gitaly GRPC client
-gem 'gitaly-proto', '~> 0.105.0', require: 'gitaly'
+gem 'gitaly-proto', '~> 0.106.0', require: 'gitaly'
gem 'grpc', '~> 1.11.0'
# Locked until https://github.com/google/protobuf/issues/4210 is closed
diff --git a/Gemfile.lock b/Gemfile.lock
index 7f9207d9dfe..22626c0071b 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -87,6 +87,8 @@ GEM
binding_of_caller (0.7.2)
debug_inspector (>= 0.0.1)
blankslate (2.1.2.4)
+ bootsnap (1.3.1)
+ msgpack (~> 1.0)
bootstrap_form (2.7.0)
brakeman (4.2.1)
browser (2.2.0)
@@ -282,7 +284,7 @@ GEM
gettext_i18n_rails (>= 0.7.1)
po_to_json (>= 1.0.0)
rails (>= 3.2.0)
- gitaly-proto (0.105.0)
+ gitaly-proto (0.106.0)
google-protobuf (~> 3.1)
grpc (~> 1.10)
github-linguist (5.3.3)
@@ -385,6 +387,7 @@ GEM
temple (>= 0.8.0)
thor
tilt
+ hangouts-chat (0.0.5)
hashdiff (0.3.4)
hashie (3.5.7)
hashie-forbidden_attributes (0.1.1)
@@ -500,6 +503,7 @@ GEM
mini_portile2 (2.3.0)
minitest (5.7.0)
mousetrap-rails (1.4.6)
+ msgpack (1.2.4)
multi_json (1.13.1)
multi_xml (0.6.0)
multipart-post (2.0.0)
@@ -510,7 +514,7 @@ GEM
net-ldap (0.16.0)
net-ssh (5.0.1)
netrc (0.11.0)
- nokogiri (1.8.3)
+ nokogiri (1.8.4)
mini_portile2 (~> 2.3.0)
nokogumbo (1.5.0)
nokogiri
@@ -804,7 +808,7 @@ GEM
et-orbi (~> 1.0)
rugged (0.27.2)
safe_yaml (1.0.4)
- sanitize (4.6.5)
+ sanitize (4.6.6)
crass (~> 1.0.2)
nokogiri (>= 1.4.4)
nokogumbo (~> 1.4)
@@ -986,6 +990,7 @@ DEPENDENCIES
benchmark-ips (~> 2.3.0)
better_errors (~> 2.1.0)
binding_of_caller (~> 0.7.2)
+ bootsnap (~> 1.3)
bootstrap_form (~> 2.7.0)
brakeman (~> 4.2)
browser (~> 2.2)
@@ -1037,7 +1042,7 @@ DEPENDENCIES
gettext (~> 3.2.2)
gettext_i18n_rails (~> 1.8.0)
gettext_i18n_rails_js (~> 1.3)
- gitaly-proto (~> 0.105.0)
+ gitaly-proto (~> 0.106.0)
github-linguist (~> 5.3.3)
gitlab-flowdock-git-hook (~> 1.0.1)
gitlab-gollum-lib (~> 4.2)
@@ -1058,6 +1063,7 @@ DEPENDENCIES
grpc (~> 1.11.0)
haml_lint (~> 0.26.0)
hamlit (~> 2.8.8)
+ hangouts-chat (~> 0.0.5)
hashie-forbidden_attributes
health_check (~> 2.6.0)
hipchat (~> 1.5.0)
@@ -1151,7 +1157,7 @@ DEPENDENCIES
ruby_parser (~> 3.8)
rufus-scheduler (~> 3.4)
rugged (~> 0.27)
- sanitize (~> 4.6.5)
+ sanitize (~> 4.6)
sass-rails (~> 5.0.6)
scss_lint (~> 0.56.0)
seed-fu (~> 2.3.7)
diff --git a/Gemfile.rails5.lock b/Gemfile.rails5.lock
index 766f2479ea5..5a0aaf05608 100644
--- a/Gemfile.rails5.lock
+++ b/Gemfile.rails5.lock
@@ -90,6 +90,8 @@ GEM
binding_of_caller (0.7.2)
debug_inspector (>= 0.0.1)
blankslate (2.1.2.4)
+ bootsnap (1.3.1)
+ msgpack (~> 1.0)
bootstrap_form (2.7.0)
brakeman (4.2.1)
browser (2.2.0)
@@ -285,7 +287,7 @@ GEM
gettext_i18n_rails (>= 0.7.1)
po_to_json (>= 1.0.0)
rails (>= 3.2.0)
- gitaly-proto (0.105.0)
+ gitaly-proto (0.106.0)
google-protobuf (~> 3.1)
grpc (~> 1.10)
github-linguist (5.3.3)
@@ -388,6 +390,7 @@ GEM
temple (>= 0.8.0)
thor
tilt
+ hangouts-chat (0.0.5)
hashdiff (0.3.4)
hashie (3.5.7)
hashie-forbidden_attributes (0.1.1)
@@ -503,6 +506,7 @@ GEM
mini_portile2 (2.3.0)
minitest (5.7.0)
mousetrap-rails (1.4.6)
+ msgpack (1.2.4)
multi_json (1.13.1)
multi_xml (0.6.0)
multipart-post (2.0.0)
@@ -996,6 +1000,7 @@ DEPENDENCIES
benchmark-ips (~> 2.3.0)
better_errors (~> 2.1.0)
binding_of_caller (~> 0.7.2)
+ bootsnap (~> 1.3)
bootstrap_form (~> 2.7.0)
brakeman (~> 4.2)
browser (~> 2.2)
@@ -1047,7 +1052,7 @@ DEPENDENCIES
gettext (~> 3.2.2)
gettext_i18n_rails (~> 1.8.0)
gettext_i18n_rails_js (~> 1.3)
- gitaly-proto (~> 0.105.0)
+ gitaly-proto (~> 0.106.0)
github-linguist (~> 5.3.3)
gitlab-flowdock-git-hook (~> 1.0.1)
gitlab-gollum-lib (~> 4.2)
@@ -1068,6 +1073,7 @@ DEPENDENCIES
grpc (~> 1.11.0)
haml_lint (~> 0.26.0)
hamlit (~> 2.8.8)
+ hangouts-chat (~> 0.0.5)
hashie-forbidden_attributes
health_check (~> 2.6.0)
hipchat (~> 1.5.0)
@@ -1162,7 +1168,7 @@ DEPENDENCIES
ruby_parser (~> 3.8)
rufus-scheduler (~> 3.4)
rugged (~> 0.27)
- sanitize (~> 4.6.5)
+ sanitize (~> 4.6)
sass-rails (~> 5.0.6)
scss_lint (~> 0.56.0)
seed-fu (~> 2.3.7)
diff --git a/VERSION b/VERSION
index 0116f5d2c81..53906da50f8 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-11.1.0-pre
+11.2.0-pre
diff --git a/app/assets/javascripts/boards/components/board_new_issue.vue b/app/assets/javascripts/boards/components/board_new_issue.vue
index ec23b1e7c11..271c6eac81a 100644
--- a/app/assets/javascripts/boards/components/board_new_issue.vue
+++ b/app/assets/javascripts/boards/components/board_new_issue.vue
@@ -105,7 +105,7 @@ export default {
</div>
<label
:for="list.id + '-title'"
- class="label-light"
+ class="label-bold"
>
Title
</label>
diff --git a/app/assets/javascripts/boards/components/project_select.vue b/app/assets/javascripts/boards/components/project_select.vue
index eb335f352d3..dc887db1e73 100644
--- a/app/assets/javascripts/boards/components/project_select.vue
+++ b/app/assets/javascripts/boards/components/project_select.vue
@@ -68,7 +68,7 @@ export default {
<template>
<div>
- <label class="label-light prepend-top-10">
+ <label class="label-bold prepend-top-10">
Project
</label>
<div
diff --git a/app/assets/javascripts/commons/polyfills.js b/app/assets/javascripts/commons/polyfills.js
index d62d3c23654..f595f3c3187 100644
--- a/app/assets/javascripts/commons/polyfills.js
+++ b/app/assets/javascripts/commons/polyfills.js
@@ -14,6 +14,7 @@ import 'core-js/es6/weak-map';
// Browser polyfills
import 'classlist-polyfill';
+import 'formdata-polyfill';
import './polyfills/custom_event';
import './polyfills/element';
import './polyfills/event';
diff --git a/app/assets/javascripts/diffs/components/diff_discussions.vue b/app/assets/javascripts/diffs/components/diff_discussions.vue
index 20483161033..e64d5511d78 100644
--- a/app/assets/javascripts/diffs/components/diff_discussions.vue
+++ b/app/assets/javascripts/diffs/components/diff_discussions.vue
@@ -30,6 +30,7 @@ export default {
:render-header="false"
:render-diff-file="false"
:always-expanded="true"
+ :discussions-by-diff-order="true"
/>
</ul>
</div>
diff --git a/app/assets/javascripts/diffs/components/diff_line_gutter_content.vue b/app/assets/javascripts/diffs/components/diff_line_gutter_content.vue
index 0fe0007057b..d184a76f038 100644
--- a/app/assets/javascripts/diffs/components/diff_line_gutter_content.vue
+++ b/app/assets/javascripts/diffs/components/diff_line_gutter_content.vue
@@ -71,6 +71,11 @@ export default {
required: false,
default: false,
},
+ discussions: {
+ type: Array,
+ required: false,
+ default: () => [],
+ },
},
computed: {
...mapState({
@@ -78,7 +83,6 @@ export default {
diffFiles: state => state.diffs.diffFiles,
}),
...mapGetters(['isLoggedIn']),
- ...mapGetters('diffs', ['discussionsByLineCode']),
lineHref() {
return this.lineCode ? `#${this.lineCode}` : '#';
},
@@ -88,24 +92,19 @@ export default {
this.showCommentButton &&
!this.isMatchLine &&
!this.isContextLine &&
- !this.hasDiscussions &&
- !this.isMetaLine
+ !this.isMetaLine &&
+ !this.hasDiscussions
);
},
- discussions() {
- return this.discussionsByLineCode[this.lineCode] || [];
- },
hasDiscussions() {
return this.discussions.length > 0;
},
shouldShowAvatarsOnGutter() {
- let render = this.hasDiscussions && this.showCommentButton;
-
if (!this.lineType && this.linePosition === LINE_POSITION_RIGHT) {
- render = false;
+ return false;
}
- return render;
+ return this.hasDiscussions && this.showCommentButton;
},
},
methods: {
diff --git a/app/assets/javascripts/diffs/components/diff_table_cell.vue b/app/assets/javascripts/diffs/components/diff_table_cell.vue
index 5962f30d9bb..e8e8ddc6c5e 100644
--- a/app/assets/javascripts/diffs/components/diff_table_cell.vue
+++ b/app/assets/javascripts/diffs/components/diff_table_cell.vue
@@ -67,6 +67,11 @@ export default {
required: false,
default: false,
},
+ discussions: {
+ type: Array,
+ required: false,
+ default: () => [],
+ },
},
computed: {
...mapGetters(['isLoggedIn']),
@@ -136,6 +141,7 @@ export default {
:is-match-line="isMatchLine"
:is-context-line="isContentLine"
:is-meta-line="isMetaLine"
+ :discussions="discussions"
/>
</td>
</template>
diff --git a/app/assets/javascripts/diffs/components/inline_diff_comment_row.vue b/app/assets/javascripts/diffs/components/inline_diff_comment_row.vue
index a6f011ff31e..1b5ae5e9f75 100644
--- a/app/assets/javascripts/diffs/components/inline_diff_comment_row.vue
+++ b/app/assets/javascripts/diffs/components/inline_diff_comment_row.vue
@@ -1,5 +1,5 @@
<script>
-import { mapState, mapGetters } from 'vuex';
+import { mapState } from 'vuex';
import diffDiscussions from './diff_discussions.vue';
import diffLineNoteForm from './diff_line_note_form.vue';
@@ -21,15 +21,16 @@ export default {
type: Number,
required: true,
},
+ discussions: {
+ type: Array,
+ required: false,
+ default: () => [],
+ },
},
computed: {
...mapState({
diffLineCommentForms: state => state.diffs.diffLineCommentForms,
}),
- ...mapGetters('diffs', ['discussionsByLineCode']),
- discussions() {
- return this.discussionsByLineCode[this.line.lineCode] || [];
- },
className() {
return this.discussions.length ? '' : 'js-temp-notes-holder';
},
diff --git a/app/assets/javascripts/diffs/components/inline_diff_table_row.vue b/app/assets/javascripts/diffs/components/inline_diff_table_row.vue
index 0e306f39a9f..32d65ff994f 100644
--- a/app/assets/javascripts/diffs/components/inline_diff_table_row.vue
+++ b/app/assets/javascripts/diffs/components/inline_diff_table_row.vue
@@ -33,6 +33,11 @@ export default {
required: false,
default: false,
},
+ discussions: {
+ type: Array,
+ required: false,
+ default: () => [],
+ },
},
data() {
return {
@@ -89,6 +94,7 @@ export default {
:is-bottom="isBottom"
:is-hover="isHover"
:show-comment-button="true"
+ :discussions="discussions"
class="diff-line-num old_line"
/>
<diff-table-cell
@@ -98,6 +104,7 @@ export default {
:line-type="newLineType"
:is-bottom="isBottom"
:is-hover="isHover"
+ :discussions="discussions"
class="diff-line-num new_line"
/>
<td
diff --git a/app/assets/javascripts/diffs/components/inline_diff_view.vue b/app/assets/javascripts/diffs/components/inline_diff_view.vue
index 8e491d293e5..5f30cc57a59 100644
--- a/app/assets/javascripts/diffs/components/inline_diff_view.vue
+++ b/app/assets/javascripts/diffs/components/inline_diff_view.vue
@@ -20,7 +20,11 @@ export default {
},
},
computed: {
- ...mapGetters('diffs', ['commitId', 'discussionsByLineCode']),
+ ...mapGetters('diffs', [
+ 'commitId',
+ 'shouldRenderInlineCommentRow',
+ 'singleDiscussionByLineCode',
+ ]),
...mapState({
diffLineCommentForms: state => state.diffs.diffLineCommentForms,
}),
@@ -34,18 +38,7 @@ export default {
return window.gon.user_color_scheme;
},
},
- methods: {
- shouldRenderCommentRow(line) {
- if (this.diffLineCommentForms[line.lineCode]) return true;
-
- const lineDiscussions = this.discussionsByLineCode[line.lineCode];
- if (lineDiscussions === undefined) {
- return false;
- }
-
- return lineDiscussions.every(discussion => discussion.expanded);
- },
- },
+ methods: {},
};
</script>
@@ -64,13 +57,15 @@ export default {
:line="line"
:is-bottom="index + 1 === diffLinesLength"
:key="line.lineCode"
+ :discussions="singleDiscussionByLineCode(line.lineCode)"
/>
<inline-diff-comment-row
- v-if="shouldRenderCommentRow(line)"
+ v-if="shouldRenderInlineCommentRow(line)"
:diff-file-hash="diffFile.fileHash"
:line="line"
:line-index="index"
:key="index"
+ :discussions="singleDiscussionByLineCode(line.lineCode)"
/>
</template>
</tbody>
diff --git a/app/assets/javascripts/diffs/components/parallel_diff_comment_row.vue b/app/assets/javascripts/diffs/components/parallel_diff_comment_row.vue
index 05e5cafc717..bb9a65c83fa 100644
--- a/app/assets/javascripts/diffs/components/parallel_diff_comment_row.vue
+++ b/app/assets/javascripts/diffs/components/parallel_diff_comment_row.vue
@@ -1,5 +1,5 @@
<script>
-import { mapState, mapGetters } from 'vuex';
+import { mapState } from 'vuex';
import diffDiscussions from './diff_discussions.vue';
import diffLineNoteForm from './diff_line_note_form.vue';
@@ -21,48 +21,51 @@ export default {
type: Number,
required: true,
},
+ leftDiscussions: {
+ type: Array,
+ required: false,
+ default: () => [],
+ },
+ rightDiscussions: {
+ type: Array,
+ required: false,
+ default: () => [],
+ },
},
computed: {
...mapState({
diffLineCommentForms: state => state.diffs.diffLineCommentForms,
}),
- ...mapGetters('diffs', ['discussionsByLineCode']),
leftLineCode() {
return this.line.left.lineCode;
},
rightLineCode() {
return this.line.right.lineCode;
},
- hasDiscussion() {
- const discussions = this.discussionsByLineCode;
-
- return discussions[this.leftLineCode] || discussions[this.rightLineCode];
- },
hasExpandedDiscussionOnLeft() {
- const discussions = this.discussionsByLineCode[this.leftLineCode];
-
+ const discussions = this.leftDiscussions;
return discussions ? discussions.every(discussion => discussion.expanded) : false;
},
hasExpandedDiscussionOnRight() {
- const discussions = this.discussionsByLineCode[this.rightLineCode];
-
+ const discussions = this.rightDiscussions;
return discussions ? discussions.every(discussion => discussion.expanded) : false;
},
hasAnyExpandedDiscussion() {
return this.hasExpandedDiscussionOnLeft || this.hasExpandedDiscussionOnRight;
},
shouldRenderDiscussionsOnLeft() {
- return this.discussionsByLineCode[this.leftLineCode] && this.hasExpandedDiscussionOnLeft;
+ return this.leftDiscussions && this.hasExpandedDiscussionOnLeft;
},
shouldRenderDiscussionsOnRight() {
- return (
- this.discussionsByLineCode[this.rightLineCode] &&
- this.hasExpandedDiscussionOnRight &&
- this.line.right.type
- );
+ return this.rightDiscussions && this.hasExpandedDiscussionOnRight && this.line.right.type;
+ },
+ showRightSideCommentForm() {
+ return this.line.right.type && this.diffLineCommentForms[this.rightLineCode];
},
className() {
- return this.hasDiscussion ? '' : 'js-temp-notes-holder';
+ return this.leftDiscussions.length > 0 || this.rightDiscussions.length > 0
+ ? ''
+ : 'js-temp-notes-holder';
},
},
};
@@ -80,13 +83,12 @@ export default {
class="content"
>
<diff-discussions
- v-if="discussionsByLineCode[leftLineCode].length"
- :discussions="discussionsByLineCode[leftLineCode]"
+ v-if="leftDiscussions.length"
+ :discussions="leftDiscussions"
/>
</div>
<diff-line-note-form
- v-if="diffLineCommentForms[leftLineCode] &&
- diffLineCommentForms[leftLineCode]"
+ v-if="diffLineCommentForms[leftLineCode]"
:diff-file-hash="diffFileHash"
:line="line.left"
:note-target-line="line.left"
@@ -100,13 +102,12 @@ export default {
class="content"
>
<diff-discussions
- v-if="discussionsByLineCode[rightLineCode].length"
- :discussions="discussionsByLineCode[rightLineCode]"
+ v-if="rightDiscussions.length"
+ :discussions="rightDiscussions"
/>
</div>
<diff-line-note-form
- v-if="diffLineCommentForms[rightLineCode] &&
- diffLineCommentForms[rightLineCode] && line.right.type"
+ v-if="showRightSideCommentForm"
:diff-file-hash="diffFileHash"
:line="line.right"
:note-target-line="line.right"
diff --git a/app/assets/javascripts/diffs/components/parallel_diff_table_row.vue b/app/assets/javascripts/diffs/components/parallel_diff_table_row.vue
index 0031cedc68f..d4e54c2bd00 100644
--- a/app/assets/javascripts/diffs/components/parallel_diff_table_row.vue
+++ b/app/assets/javascripts/diffs/components/parallel_diff_table_row.vue
@@ -36,6 +36,16 @@ export default {
required: false,
default: false,
},
+ leftDiscussions: {
+ type: Array,
+ required: false,
+ default: () => [],
+ },
+ rightDiscussions: {
+ type: Array,
+ required: false,
+ default: () => [],
+ },
},
data() {
return {
@@ -116,6 +126,7 @@ export default {
:is-hover="isLeftHover"
:show-comment-button="true"
:diff-view-type="parallelDiffViewType"
+ :discussions="leftDiscussions"
class="diff-line-num old_line"
/>
<td
@@ -136,6 +147,7 @@ export default {
:is-hover="isRightHover"
:show-comment-button="true"
:diff-view-type="parallelDiffViewType"
+ :discussions="rightDiscussions"
class="diff-line-num new_line"
/>
<td
diff --git a/app/assets/javascripts/diffs/components/parallel_diff_view.vue b/app/assets/javascripts/diffs/components/parallel_diff_view.vue
index 8f8d6bbc818..4d97cb6d15d 100644
--- a/app/assets/javascripts/diffs/components/parallel_diff_view.vue
+++ b/app/assets/javascripts/diffs/components/parallel_diff_view.vue
@@ -21,7 +21,11 @@ export default {
},
},
computed: {
- ...mapGetters('diffs', ['commitId', 'discussionsByLineCode']),
+ ...mapGetters('diffs', [
+ 'commitId',
+ 'singleDiscussionByLineCode',
+ 'shouldRenderParallelCommentRow',
+ ]),
...mapState({
diffLineCommentForms: state => state.diffs.diffLineCommentForms,
}),
@@ -51,32 +55,6 @@ export default {
return window.gon.user_color_scheme;
},
},
- methods: {
- shouldRenderCommentRow(line) {
- const leftLineCode = line.left.lineCode;
- const rightLineCode = line.right.lineCode;
- const discussions = this.discussionsByLineCode;
- const leftDiscussions = discussions[leftLineCode];
- const rightDiscussions = discussions[rightLineCode];
- const hasDiscussion = leftDiscussions || rightDiscussions;
-
- const hasExpandedDiscussionOnLeft = leftDiscussions
- ? leftDiscussions.every(discussion => discussion.expanded)
- : false;
- const hasExpandedDiscussionOnRight = rightDiscussions
- ? rightDiscussions.every(discussion => discussion.expanded)
- : false;
-
- if (hasDiscussion && (hasExpandedDiscussionOnLeft || hasExpandedDiscussionOnRight)) {
- return true;
- }
-
- const hasCommentFormOnLeft = this.diffLineCommentForms[leftLineCode];
- const hasCommentFormOnRight = this.diffLineCommentForms[rightLineCode];
-
- return hasCommentFormOnLeft || hasCommentFormOnRight;
- },
- },
};
</script>
@@ -97,13 +75,17 @@ export default {
:line="line"
:is-bottom="index + 1 === diffLinesLength"
:key="index"
+ :left-discussions="singleDiscussionByLineCode(line.left.lineCode)"
+ :right-discussions="singleDiscussionByLineCode(line.right.lineCode)"
/>
<parallel-diff-comment-row
- v-if="shouldRenderCommentRow(line)"
+ v-if="shouldRenderParallelCommentRow(line)"
:key="`dcr-${index}`"
:line="line"
:diff-file-hash="diffFile.fileHash"
:line-index="index"
+ :left-discussions="singleDiscussionByLineCode(line.left.lineCode)"
+ :right-discussions="singleDiscussionByLineCode(line.right.lineCode)"
/>
</template>
</tbody>
diff --git a/app/assets/javascripts/diffs/store/getters.js b/app/assets/javascripts/diffs/store/getters.js
index d3881fa1a0a..c7b9b1a16e6 100644
--- a/app/assets/javascripts/diffs/store/getters.js
+++ b/app/assets/javascripts/diffs/store/getters.js
@@ -75,19 +75,21 @@ export const discussionsByLineCode = (state, getters, rootState, rootGetters) =>
const isDiffDiscussion = note.diff_discussion;
const hasLineCode = note.line_code;
const isResolvable = note.resolvable;
- const diffRefs = diffRefsByLineCode[note.line_code];
- if (isDiffDiscussion && hasLineCode && isResolvable && diffRefs) {
- const refs = convertObjectPropsToCamelCase(note.position.formatter);
- const originalRefs = convertObjectPropsToCamelCase(note.original_position.formatter);
+ if (isDiffDiscussion && hasLineCode && isResolvable) {
+ const diffRefs = diffRefsByLineCode[note.line_code];
+ if (diffRefs) {
+ const refs = convertObjectPropsToCamelCase(note.position.formatter);
+ const originalRefs = convertObjectPropsToCamelCase(note.original_position.formatter);
- if (_.isEqual(refs, diffRefs) || _.isEqual(originalRefs, diffRefs)) {
- const lineCode = note.line_code;
+ if (_.isEqual(refs, diffRefs) || _.isEqual(originalRefs, diffRefs)) {
+ const lineCode = note.line_code;
- if (acc[lineCode]) {
- acc[lineCode].push(note);
- } else {
- acc[lineCode] = [note];
+ if (acc[lineCode]) {
+ acc[lineCode].push(note);
+ } else {
+ acc[lineCode] = [note];
+ }
}
}
}
@@ -96,6 +98,47 @@ export const discussionsByLineCode = (state, getters, rootState, rootGetters) =>
}, {});
};
+export const singleDiscussionByLineCode = (state, getters) => lineCode => {
+ if (!lineCode) return [];
+ const discussions = getters.discussionsByLineCode;
+ return discussions[lineCode] || [];
+};
+
+export const shouldRenderParallelCommentRow = (state, getters) => line => {
+ const leftLineCode = line.left.lineCode;
+ const rightLineCode = line.right.lineCode;
+ const leftDiscussions = getters.singleDiscussionByLineCode(leftLineCode);
+ const rightDiscussions = getters.singleDiscussionByLineCode(rightLineCode);
+ const hasDiscussion = leftDiscussions.length || rightDiscussions.length;
+
+ const hasExpandedDiscussionOnLeft = leftDiscussions.length
+ ? leftDiscussions.every(discussion => discussion.expanded)
+ : false;
+ const hasExpandedDiscussionOnRight = rightDiscussions.length
+ ? rightDiscussions.every(discussion => discussion.expanded)
+ : false;
+
+ if (hasDiscussion && (hasExpandedDiscussionOnLeft || hasExpandedDiscussionOnRight)) {
+ return true;
+ }
+
+ const hasCommentFormOnLeft = state.diffLineCommentForms[leftLineCode];
+ const hasCommentFormOnRight = state.diffLineCommentForms[rightLineCode];
+
+ return hasCommentFormOnLeft || hasCommentFormOnRight;
+};
+
+export const shouldRenderInlineCommentRow = (state, getters) => line => {
+ if (state.diffLineCommentForms[line.lineCode]) return true;
+
+ const lineDiscussions = getters.singleDiscussionByLineCode(line.lineCode);
+ if (lineDiscussions.length === 0) {
+ return false;
+ }
+
+ return lineDiscussions.every(discussion => discussion.expanded);
+};
+
// prevent babel-plugin-rewire from generating an invalid default during karma∂ tests
export const getDiffFileByHash = state => fileHash =>
state.diffFiles.find(file => file.fileHash === fileHash);
diff --git a/app/assets/javascripts/gpg_badges.js b/app/assets/javascripts/gpg_badges.js
index 029fd6a67d4..efba6fc1aff 100644
--- a/app/assets/javascripts/gpg_badges.js
+++ b/app/assets/javascripts/gpg_badges.js
@@ -1,23 +1,36 @@
import $ from 'jquery';
import { parseQueryStringIntoObject } from '~/lib/utils/common_utils';
import axios from '~/lib/utils/axios_utils';
-import flash from '~/flash';
+import createFlash from '~/flash';
import { __ } from '~/locale';
export default class GpgBadges {
static fetch() {
- const badges = $('.js-loading-gpg-badge');
const tag = $('.js-signature-container');
+ if (tag.length === 0) {
+ return Promise.resolve();
+ }
+
+ const badges = $('.js-loading-gpg-badge');
badges.html('<i class="fa fa-spinner fa-spin"></i>');
+ const displayError = () => createFlash(__('An error occurred while loading commit signatures'));
+
+ const endpoint = tag.data('signaturesPath');
+ if (!endpoint) {
+ displayError();
+ return Promise.reject(new Error('Missing commit signatures endpoint!'));
+ }
+
const params = parseQueryStringIntoObject(tag.serialize());
- return axios.get(tag.data('signaturesPath'), { params })
- .then(({ data }) => {
- data.signatures.forEach((signature) => {
- badges.filter(`[data-commit-sha="${signature.commit_sha}"]`).replaceWith(signature.html);
- });
- })
- .catch(() => flash(__('An error occurred while loading commits')));
+ return axios
+ .get(endpoint, { params })
+ .then(({ data }) => {
+ data.signatures.forEach(signature => {
+ badges.filter(`[data-commit-sha="${signature.commit_sha}"]`).replaceWith(signature.html);
+ });
+ })
+ .catch(displayError);
}
}
diff --git a/app/assets/javascripts/ide/components/new_dropdown/modal.vue b/app/assets/javascripts/ide/components/new_dropdown/modal.vue
index 1867b7980d2..833c4b027df 100644
--- a/app/assets/javascripts/ide/components/new_dropdown/modal.vue
+++ b/app/assets/javascripts/ide/components/new_dropdown/modal.vue
@@ -66,7 +66,7 @@ export default {
<div
class="form-group row"
>
- <label class="label-light col-form-label col-sm-3">
+ <label class="label-bold col-form-label col-sm-3">
{{ __('Name') }}
</label>
<div class="col-sm-9">
diff --git a/app/assets/javascripts/ide/ide_router.js b/app/assets/javascripts/ide/ide_router.js
index 44c35e9a5a5..c6d7d218e81 100644
--- a/app/assets/javascripts/ide/ide_router.js
+++ b/app/assets/javascripts/ide/ide_router.js
@@ -1,5 +1,6 @@
import Vue from 'vue';
import VueRouter from 'vue-router';
+import { join as joinPath } from 'path';
import flash from '~/flash';
import store from './stores';
import { activityBarViews } from './constants';
@@ -37,17 +38,29 @@ const router = new VueRouter({
base: `${gon.relative_url_root}/-/ide/`,
routes: [
{
- path: '/project/:namespace/:project+',
+ path: '/project/:namespace+/:project',
component: EmptyRouterComponent,
children: [
{
- path: ':targetmode(edit|tree|blob)/*',
+ path: ':targetmode(edit|tree|blob)/:branchid+/-/*',
component: EmptyRouterComponent,
},
{
+ path: ':targetmode(edit|tree|blob)/:branchid+/',
+ redirect: to => joinPath(to.path, '/-/'),
+ },
+ {
+ path: ':targetmode(edit|tree|blob)',
+ redirect: to => joinPath(to.path, '/master/-/'),
+ },
+ {
path: 'merge_requests/:mrid',
component: EmptyRouterComponent,
},
+ {
+ path: '',
+ redirect: to => joinPath(to.path, '/edit/master/-/'),
+ },
],
},
],
@@ -63,11 +76,10 @@ router.beforeEach((to, from, next) => {
.then(() => {
const fullProjectId = `${to.params.namespace}/${to.params.project}`;
- const baseSplit = (to.params[0] && to.params[0].split('/-/')) || [''];
- const branchId = baseSplit[0].slice(-1) === '/' ? baseSplit[0].slice(0, -1) : baseSplit[0];
+ const branchId = to.params.branchid;
if (branchId) {
- const basePath = baseSplit.length > 1 ? baseSplit[1] : '';
+ const basePath = to.params[0] || '';
store.dispatch('setCurrentBranchId', branchId);
diff --git a/app/assets/javascripts/lib/utils/poll.js b/app/assets/javascripts/lib/utils/poll.js
index 7fca80c2fdb..91d8c30744f 100644
--- a/app/assets/javascripts/lib/utils/poll.js
+++ b/app/assets/javascripts/lib/utils/poll.js
@@ -38,7 +38,7 @@ import { normalizeHeaders } from './common_utils';
* } else {
* poll.stop();
* }
-* });
+ * });
*
* 1. Checks for response and headers before start polling
* 2. Interval is provided by `Poll-Interval` header.
@@ -51,8 +51,8 @@ export default class Poll {
constructor(options = {}) {
this.options = options;
this.options.data = options.data || {};
- this.options.notificationCallback = options.notificationCallback ||
- function notificationCallback() {};
+ this.options.notificationCallback =
+ options.notificationCallback || function notificationCallback() {};
this.intervalHeader = 'POLL-INTERVAL';
this.timeoutID = null;
@@ -63,6 +63,7 @@ export default class Poll {
const headers = normalizeHeaders(response.headers);
const pollInterval = parseInt(headers[this.intervalHeader], 10);
if (pollInterval > 0 && response.status === httpStatusCodes.OK && this.canPoll) {
+ clearTimeout(this.timeoutID);
this.timeoutID = setTimeout(() => {
this.makeRequest();
}, pollInterval);
@@ -77,11 +78,11 @@ export default class Poll {
notificationCallback(true);
return resource[method](data)
- .then((response) => {
+ .then(response => {
this.checkConditions(response);
notificationCallback(false);
})
- .catch((error) => {
+ .catch(error => {
notificationCallback(false);
if (error.status === httpStatusCodes.ABORTED) {
return;
diff --git a/app/assets/javascripts/notes/components/discussion_counter.vue b/app/assets/javascripts/notes/components/discussion_counter.vue
index 6385b75e557..ad6e7cf501d 100644
--- a/app/assets/javascripts/notes/components/discussion_counter.vue
+++ b/app/assets/javascripts/notes/components/discussion_counter.vue
@@ -5,19 +5,20 @@ import resolvedSvg from 'icons/_icon_status_success_solid.svg';
import mrIssueSvg from 'icons/_icon_mr_issue.svg';
import nextDiscussionSvg from 'icons/_next_discussion.svg';
import { pluralize } from '../../lib/utils/text_utility';
-import { scrollToElement } from '../../lib/utils/common_utils';
+import discussionNavigation from '../mixins/discussion_navigation';
import tooltip from '../../vue_shared/directives/tooltip';
export default {
directives: {
tooltip,
},
+ mixins: [discussionNavigation],
computed: {
...mapGetters([
'getUserData',
'getNoteableData',
'discussionCount',
- 'unresolvedDiscussions',
+ 'firstUnresolvedDiscussionId',
'resolvedDiscussionCount',
]),
isLoggedIn() {
@@ -35,11 +36,6 @@ export default {
resolveAllDiscussionsIssuePath() {
return this.getNoteableData.create_issue_to_resolve_discussions_path;
},
- firstUnresolvedDiscussionId() {
- const item = this.unresolvedDiscussions[0] || {};
-
- return item.id;
- },
},
created() {
this.resolveSvg = resolveSvg;
@@ -50,22 +46,10 @@ export default {
methods: {
...mapActions(['expandDiscussion']),
jumpToFirstUnresolvedDiscussion() {
- const discussionId = this.firstUnresolvedDiscussionId;
- if (!discussionId) {
- return;
- }
-
- const el = document.querySelector(`[data-discussion-id="${discussionId}"]`);
- const activeTab = window.mrTabs.currentAction;
-
- if (activeTab === 'commits' || activeTab === 'pipelines') {
- window.mrTabs.activateTab('show');
- }
+ const diffTab = window.mrTabs.currentAction === 'diffs';
+ const discussionId = this.firstUnresolvedDiscussionId(diffTab);
- if (el) {
- this.expandDiscussion({ discussionId });
- scrollToElement(el);
- }
+ this.jumpToDiscussion(discussionId);
},
},
};
diff --git a/app/assets/javascripts/notes/components/noteable_discussion.vue b/app/assets/javascripts/notes/components/noteable_discussion.vue
index 2f1a68731c7..0fe1c16854a 100644
--- a/app/assets/javascripts/notes/components/noteable_discussion.vue
+++ b/app/assets/javascripts/notes/components/noteable_discussion.vue
@@ -1,9 +1,8 @@
<script>
-import _ from 'underscore';
import { mapActions, mapGetters } from 'vuex';
import resolveDiscussionsSvg from 'icons/_icon_mr_issue.svg';
import nextDiscussionsSvg from 'icons/_next_discussion.svg';
-import { convertObjectPropsToCamelCase, scrollToElement } from '~/lib/utils/common_utils';
+import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
import { truncateSha } from '~/lib/utils/text_utility';
import systemNote from '~/vue_shared/components/notes/system_note.vue';
import { s__ } from '~/locale';
@@ -21,6 +20,7 @@ import placeholderSystemNote from '../../vue_shared/components/notes/placeholder
import autosave from '../mixins/autosave';
import noteable from '../mixins/noteable';
import resolvable from '../mixins/resolvable';
+import discussionNavigation from '../mixins/discussion_navigation';
import tooltip from '../../vue_shared/directives/tooltip';
export default {
@@ -40,7 +40,7 @@ export default {
directives: {
tooltip,
},
- mixins: [autosave, noteable, resolvable],
+ mixins: [autosave, noteable, resolvable, discussionNavigation],
props: {
discussion: {
type: Object,
@@ -61,6 +61,11 @@ export default {
required: false,
default: false,
},
+ discussionsByDiffOrder: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
},
data() {
return {
@@ -75,7 +80,12 @@ export default {
'discussionCount',
'resolvedDiscussionCount',
'allDiscussions',
+ 'unresolvedDiscussionsIdsByDiff',
+ 'unresolvedDiscussionsIdsByDate',
'unresolvedDiscussions',
+ 'unresolvedDiscussionsIdsOrdered',
+ 'nextUnresolvedDiscussionId',
+ 'isLastUnresolvedDiscussion',
]),
transformedDiscussion() {
return {
@@ -126,6 +136,10 @@ export default {
hasMultipleUnresolvedDiscussions() {
return this.unresolvedDiscussions.length > 1;
},
+ showJumpToNextDiscussion() {
+ return this.hasMultipleUnresolvedDiscussions &&
+ !this.isLastUnresolvedDiscussion(this.discussion.id, this.discussionsByDiffOrder);
+ },
shouldRenderDiffs() {
const { diffDiscussion, diffFile } = this.transformedDiscussion;
@@ -242,21 +256,10 @@ Please check your network connection and try again.`;
});
},
jumpToNextDiscussion() {
- const discussionIds = this.allDiscussions.map(d => d.id);
- const unresolvedIds = this.unresolvedDiscussions.map(d => d.id);
- const currentIndex = discussionIds.indexOf(this.discussion.id);
- const remainingAfterCurrent = discussionIds.slice(currentIndex + 1);
- const nextIndex = _.findIndex(remainingAfterCurrent, id => unresolvedIds.indexOf(id) > -1);
-
- if (nextIndex > -1) {
- const nextId = remainingAfterCurrent[nextIndex];
- const el = document.querySelector(`[data-discussion-id="${nextId}"]`);
+ const nextId =
+ this.nextUnresolvedDiscussionId(this.discussion.id, this.discussionsByDiffOrder);
- if (el) {
- this.expandDiscussion({ discussionId: nextId });
- scrollToElement(el);
- }
- }
+ this.jumpToDiscussion(nextId);
},
},
};
@@ -398,7 +401,7 @@ Please check your network connection and try again.`;
</a>
</div>
<div
- v-if="hasMultipleUnresolvedDiscussions"
+ v-if="showJumpToNextDiscussion"
class="btn-group"
role="group">
<button
diff --git a/app/assets/javascripts/notes/mixins/discussion_navigation.js b/app/assets/javascripts/notes/mixins/discussion_navigation.js
new file mode 100644
index 00000000000..f7c4deee1f8
--- /dev/null
+++ b/app/assets/javascripts/notes/mixins/discussion_navigation.js
@@ -0,0 +1,29 @@
+import { scrollToElement } from '~/lib/utils/common_utils';
+
+export default {
+ methods: {
+ jumpToDiscussion(id) {
+ if (id) {
+ const activeTab = window.mrTabs.currentAction;
+ const selector =
+ activeTab === 'diffs'
+ ? `ul.notes[data-discussion-id="${id}"]`
+ : `div.discussion[data-discussion-id="${id}"]`;
+ const el = document.querySelector(selector);
+
+ if (activeTab === 'commits' || activeTab === 'pipelines') {
+ window.mrTabs.activateTab('show');
+ }
+
+ if (el) {
+ this.expandDiscussion({ discussionId: id });
+
+ scrollToElement(el);
+ return true;
+ }
+ }
+
+ return false;
+ },
+ },
+};
diff --git a/app/assets/javascripts/notes/stores/getters.js b/app/assets/javascripts/notes/stores/getters.js
index e9e95dd4219..0d8d197bf71 100644
--- a/app/assets/javascripts/notes/stores/getters.js
+++ b/app/assets/javascripts/notes/stores/getters.js
@@ -70,6 +70,9 @@ export const allDiscussions = (state, getters) => {
return Object.values(resolved).concat(unresolved);
};
+export const allResolvableDiscussions = (state, getters) =>
+ getters.allDiscussions.filter(d => !d.individual_note && d.resolvable);
+
export const resolvedDiscussionsById = state => {
const map = {};
@@ -86,6 +89,51 @@ export const resolvedDiscussionsById = state => {
return map;
};
+// Gets Discussions IDs ordered by the date of their initial note
+export const unresolvedDiscussionsIdsByDate = (state, getters) =>
+ getters.allResolvableDiscussions
+ .filter(d => !d.resolved)
+ .sort((a, b) => {
+ const aDate = new Date(a.notes[0].created_at);
+ const bDate = new Date(b.notes[0].created_at);
+
+ if (aDate < bDate) {
+ return -1;
+ }
+
+ return aDate === bDate ? 0 : 1;
+ })
+ .map(d => d.id);
+
+// Gets Discussions IDs ordered by their position in the diff
+//
+// Sorts the array of resolvable yet unresolved discussions by
+// comparing file names first. If file names are the same, compares
+// line numbers.
+export const unresolvedDiscussionsIdsByDiff = (state, getters) =>
+ getters.allResolvableDiscussions
+ .filter(d => !d.resolved)
+ .sort((a, b) => {
+ if (!a.diff_file || !b.diff_file) {
+ return 0;
+ }
+
+ // Get file names comparison result
+ const filenameComparison = a.diff_file.file_path.localeCompare(b.diff_file.file_path);
+
+ // Get the line numbers, to compare within the same file
+ const aLines = [a.position.formatter.new_line, a.position.formatter.old_line];
+ const bLines = [b.position.formatter.new_line, b.position.formatter.old_line];
+
+ return filenameComparison < 0 ||
+ (filenameComparison === 0 &&
+ // .max() because one of them might be zero (if removed/added)
+ Math.max(aLines[0], aLines[1]) < Math.max(bLines[0], bLines[1]))
+ ? -1
+ : 1;
+ })
+ .map(d => d.id);
+
export const resolvedDiscussionCount = (state, getters) => {
const resolvedMap = getters.resolvedDiscussionsById;
@@ -102,5 +150,42 @@ export const discussionTabCounter = state => {
return all.length;
};
+// Returns the list of discussion IDs ordered according to given parameter
+// @param {Boolean} diffOrder - is ordered by diff?
+export const unresolvedDiscussionsIdsOrdered = (state, getters) => diffOrder => {
+ if (diffOrder) {
+ return getters.unresolvedDiscussionsIdsByDiff;
+ }
+ return getters.unresolvedDiscussionsIdsByDate;
+};
+
+// Checks if a given discussion is the last in the current order (diff or date)
+// @param {Boolean} discussionId - id of the discussion
+// @param {Boolean} diffOrder - is ordered by diff?
+export const isLastUnresolvedDiscussion = (state, getters) => (discussionId, diffOrder) => {
+ const idsOrdered = getters.unresolvedDiscussionsIdsOrdered(diffOrder);
+ const lastDiscussionId = idsOrdered[idsOrdered.length - 1];
+
+ return lastDiscussionId === discussionId;
+};
+
+// Gets the ID of the discussion following the one provided, respecting order (diff or date)
+// @param {Boolean} discussionId - id of the current discussion
+// @param {Boolean} diffOrder - is ordered by diff?
+export const nextUnresolvedDiscussionId = (state, getters) => (discussionId, diffOrder) => {
+ const idsOrdered = getters.unresolvedDiscussionsIdsOrdered(diffOrder);
+ const currentIndex = idsOrdered.indexOf(discussionId);
+
+ return idsOrdered.slice(currentIndex + 1, currentIndex + 2)[0];
+};
+
+// @param {Boolean} diffOrder - is ordered by diff?
+export const firstUnresolvedDiscussionId = (state, getters) => diffOrder => {
+ if (diffOrder) {
+ return getters.unresolvedDiscussionsIdsByDiff[0];
+ }
+ return getters.unresolvedDiscussionsIdsByDate[0];
+};
+
// prevent babel-plugin-rewire from generating an invalid default during karma tests
export default () => {};
diff --git a/app/assets/javascripts/notes/stores/mutations.js b/app/assets/javascripts/notes/stores/mutations.js
index ab6a95e2601..e1b159142c9 100644
--- a/app/assets/javascripts/notes/stores/mutations.js
+++ b/app/assets/javascripts/notes/stores/mutations.js
@@ -174,27 +174,19 @@ export default {
[types.UPDATE_NOTE](state, note) {
const noteObj = utils.findNoteObjectById(state.discussions, note.discussion_id);
-
if (noteObj.individual_note) {
noteObj.notes.splice(0, 1, note);
} else {
const comment = utils.findNoteObjectById(noteObj.notes, note.id);
- noteObj.notes.splice(noteObj.notes.indexOf(comment), 1, note);
+ Object.assign(comment, note);
}
},
[types.UPDATE_DISCUSSION](state, noteData) {
const note = noteData;
- let index = 0;
-
- state.discussions.forEach((n, i) => {
- if (n.id === note.id) {
- index = i;
- }
- });
-
+ const selectedDiscussion = state.discussions.find(n => n.id === note.id);
note.expanded = true; // override expand flag to prevent collapse
- state.discussions.splice(index, 1, note);
+ Object.assign(selectedDiscussion, note);
},
[types.CLOSE_ISSUE](state) {
@@ -215,12 +207,9 @@ export default {
[types.SET_DISCUSSION_DIFF_LINES](state, { discussionId, diffLines }) {
const discussion = utils.findNoteObjectById(state.discussions, discussionId);
- const index = state.discussions.indexOf(discussion);
- const discussionWithDiffLines = Object.assign({}, discussion, {
+ Object.assign(discussion, {
truncated_diff_lines: diffLines,
});
-
- state.discussions.splice(index, 1, discussionWithDiffLines);
},
};
diff --git a/app/assets/javascripts/notes/stores/utils.js b/app/assets/javascripts/notes/stores/utils.js
index a0e096ebfaf..c4a812c5af4 100644
--- a/app/assets/javascripts/notes/stores/utils.js
+++ b/app/assets/javascripts/notes/stores/utils.js
@@ -2,13 +2,11 @@ import AjaxCache from '~/lib/utils/ajax_cache';
const REGEX_QUICK_ACTIONS = /^\/\w+.*$/gm;
-export const findNoteObjectById = (notes, id) =>
- notes.filter(n => n.id === id)[0];
+export const findNoteObjectById = (notes, id) => notes.find(n => n.id === id);
export const getQuickActionText = note => {
let text = 'Applying command';
- const quickActions =
- AjaxCache.get(gl.GfmAutoComplete.dataSources.commands) || [];
+ const quickActions = AjaxCache.get(gl.GfmAutoComplete.dataSources.commands) || [];
const executedCommands = quickActions.filter(command => {
const commandRegex = new RegExp(`/${command.name}`);
@@ -29,5 +27,4 @@ export const getQuickActionText = note => {
export const hasQuickActions = note => REGEX_QUICK_ACTIONS.test(note);
-export const stripQuickActions = note =>
- note.replace(REGEX_QUICK_ACTIONS, '').trim();
+export const stripQuickActions = note => note.replace(REGEX_QUICK_ACTIONS, '').trim();
diff --git a/app/assets/javascripts/pages/projects/blob/show/index.js b/app/assets/javascripts/pages/projects/blob/show/index.js
index 85c6862d629..84e5bb3c46e 100644
--- a/app/assets/javascripts/pages/projects/blob/show/index.js
+++ b/app/assets/javascripts/pages/projects/blob/show/index.js
@@ -2,6 +2,7 @@ import Vue from 'vue';
import commitPipelineStatus from '~/projects/tree/components/commit_pipeline_status_component.vue';
import BlobViewer from '~/blob/viewer/index';
import initBlob from '~/pages/projects/init_blob';
+import GpgBadges from '~/gpg_badges';
document.addEventListener('DOMContentLoaded', () => {
new BlobViewer(); // eslint-disable-line no-new
@@ -26,4 +27,6 @@ document.addEventListener('DOMContentLoaded', () => {
},
});
}
+
+ GpgBadges.fetch();
});
diff --git a/app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/interval_pattern_input.vue b/app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/interval_pattern_input.vue
index d0613804067..0d05668b285 100644
--- a/app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/interval_pattern_input.vue
+++ b/app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/interval_pattern_input.vue
@@ -68,7 +68,7 @@
:name="inputNameAttribute"
:value="cronInterval"
:checked="isEditable"
- class="label-light"
+ class="label-bold"
type="radio"
@click="toggleCustomInput(true)"
/>
@@ -93,13 +93,13 @@
v-model="cronInterval"
:name="inputNameAttribute"
:value="cronIntervalPresets.everyDay"
- class="label-light"
+ class="label-bold"
type="radio"
@click="toggleCustomInput(false)"
/>
<label
- class="label-light"
+ class="label-bold"
for="every-day"
>
{{ __('Every day (at 4:00am)') }}
@@ -112,13 +112,13 @@
v-model="cronInterval"
:name="inputNameAttribute"
:value="cronIntervalPresets.everyWeek"
- class="label-light"
+ class="label-bold"
type="radio"
@click="toggleCustomInput(false)"
/>
<label
- class="label-light"
+ class="label-bold"
for="every-week"
>
{{ __('Every week (Sundays at 4:00am)') }}
@@ -131,13 +131,13 @@
v-model="cronInterval"
:name="inputNameAttribute"
:value="cronIntervalPresets.everyMonth"
- class="label-light"
+ class="label-bold"
type="radio"
@click="toggleCustomInput(false)"
/>
<label
- class="label-light"
+ class="label-bold"
for="every-month"
>
{{ __('Every month (on the 1st at 4:00am)') }}
diff --git a/app/assets/javascripts/pages/projects/shared/permissions/components/project_setting_row.vue b/app/assets/javascripts/pages/projects/shared/permissions/components/project_setting_row.vue
index 17b91479ea5..83437363af5 100644
--- a/app/assets/javascripts/pages/projects/shared/permissions/components/project_setting_row.vue
+++ b/app/assets/javascripts/pages/projects/shared/permissions/components/project_setting_row.vue
@@ -24,7 +24,7 @@
<div class="project-feature-row">
<label
v-if="label"
- class="label-light"
+ class="label-bold"
>
{{ label }}
<a
diff --git a/app/assets/javascripts/pages/projects/show/index.js b/app/assets/javascripts/pages/projects/show/index.js
index 3b0f0f960b8..d2dc0c4570e 100644
--- a/app/assets/javascripts/pages/projects/show/index.js
+++ b/app/assets/javascripts/pages/projects/show/index.js
@@ -7,6 +7,7 @@ import TreeView from '~/tree';
import BlobViewer from '~/blob/viewer/index';
import Activities from '~/activities';
import { ajaxGet } from '~/lib/utils/common_utils';
+import GpgBadges from '~/gpg_badges';
import Star from '../../../star';
import notificationsDropdown from '../../../notifications_dropdown';
@@ -38,4 +39,6 @@ document.addEventListener('DOMContentLoaded', () => {
$(treeSlider).waitForImages(() => {
ajaxGet(document.querySelector('.js-tree-content').dataset.logsPath);
});
+
+ GpgBadges.fetch();
});
diff --git a/app/assets/javascripts/pages/projects/tree/show/index.js b/app/assets/javascripts/pages/projects/tree/show/index.js
index 7ad082a5e61..33d69d891d8 100644
--- a/app/assets/javascripts/pages/projects/tree/show/index.js
+++ b/app/assets/javascripts/pages/projects/tree/show/index.js
@@ -2,6 +2,7 @@ import $ from 'jquery';
import Vue from 'vue';
import initBlob from '~/blob_edit/blob_bundle';
import commitPipelineStatus from '~/projects/tree/components/commit_pipeline_status_component.vue';
+import GpgBadges from '~/gpg_badges';
import TreeView from '../../../../tree';
import ShortcutsNavigation from '../../../../shortcuts_navigation';
import BlobViewer from '../../../../blob/viewer';
@@ -14,7 +15,8 @@ document.addEventListener('DOMContentLoaded', () => {
new BlobViewer(); // eslint-disable-line no-new
new NewCommitForm($('.js-create-dir-form')); // eslint-disable-line no-new
$('#tree-slider').waitForImages(() =>
- ajaxGet(document.querySelector('.js-tree-content').dataset.logsPath));
+ ajaxGet(document.querySelector('.js-tree-content').dataset.logsPath),
+ );
initBlob();
const commitPipelineStatusEl = document.querySelector('.js-commit-pipeline-status');
@@ -36,4 +38,6 @@ document.addEventListener('DOMContentLoaded', () => {
},
});
}
+
+ GpgBadges.fetch();
});
diff --git a/app/assets/javascripts/profile/profile.js b/app/assets/javascripts/profile/profile.js
index 8cf7f2f23d0..e49c67ffb5c 100644
--- a/app/assets/javascripts/profile/profile.js
+++ b/app/assets/javascripts/profile/profile.js
@@ -49,13 +49,15 @@ export default class Profile {
saveForm() {
const self = this;
- const formData = new FormData(this.form[0]);
+ const formData = new FormData(this.form.get(0));
const avatarBlob = this.avatarGlCrop.getBlob();
if (avatarBlob != null) {
formData.append('user[avatar]', avatarBlob, 'avatar.png');
}
+ formData.delete('user[avatar]-trigger');
+
axios({
method: this.form.attr('method'),
url: this.form.attr('action'),
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 a4c7c143e56..1c1e17563a1 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
@@ -1,27 +1,27 @@
<script>
- import Visibility from 'visibilityjs';
- import ciIcon from '~/vue_shared/components/ci_icon.vue';
- import loadingIcon from '~/vue_shared/components/loading_icon.vue';
- import Poll from '~/lib/utils/poll';
- import Flash from '~/flash';
- import { s__, sprintf } from '~/locale';
- import tooltip from '~/vue_shared/directives/tooltip';
- import CommitPipelineService from '../services/commit_pipeline_service';
+import Visibility from 'visibilityjs';
+import ciIcon from '~/vue_shared/components/ci_icon.vue';
+import loadingIcon from '~/vue_shared/components/loading_icon.vue';
+import Poll from '~/lib/utils/poll';
+import Flash from '~/flash';
+import { s__, sprintf } from '~/locale';
+import tooltip from '~/vue_shared/directives/tooltip';
+import CommitPipelineService from '../services/commit_pipeline_service';
- export default {
- directives: {
- tooltip,
+export default {
+ directives: {
+ tooltip,
+ },
+ components: {
+ ciIcon,
+ loadingIcon,
+ },
+ props: {
+ endpoint: {
+ type: String,
+ required: true,
},
- components: {
- ciIcon,
- loadingIcon,
- },
- props: {
- endpoint: {
- type: String,
- required: true,
- },
- /* This prop can be used to replace some of the `render_commit_status`
+ /* This prop can be used to replace some of the `render_commit_status`
used across GitLab, this way we could use this vue component and add a
realtime status where it makes sense
realtime: {
@@ -29,76 +29,77 @@
required: false,
default: true,
}, */
+ },
+ data() {
+ return {
+ ciStatus: {},
+ isLoading: true,
+ };
+ },
+ computed: {
+ statusTitle() {
+ return sprintf(s__('Commits|Commit: %{commitText}'), { commitText: this.ciStatus.text });
},
- data() {
- return {
- ciStatus: {},
- isLoading: true,
- };
- },
- computed: {
- statusTitle() {
- return sprintf(s__('Commits|Commit: %{commitText}'), { commitText: this.ciStatus.text });
- },
+ },
+ mounted() {
+ this.service = new CommitPipelineService(this.endpoint);
+ this.initPolling();
+ },
+ methods: {
+ successCallback(res) {
+ const { pipelines } = res.data;
+ if (pipelines.length > 0) {
+ // The pipeline entity always keeps the latest pipeline info on the `details.status`
+ this.ciStatus = pipelines[0].details.status;
+ }
+ this.isLoading = false;
},
- mounted() {
- this.service = new CommitPipelineService(this.endpoint);
- this.initPolling();
+ errorCallback() {
+ this.ciStatus = {
+ text: 'not found',
+ icon: 'status_notfound',
+ group: 'notfound',
+ };
+ this.isLoading = false;
+ Flash(s__('Something went wrong on our end'));
},
- methods: {
- successCallback(res) {
- const { pipelines } = res.data;
- if (pipelines.length > 0) {
- // The pipeline entity always keeps the latest pipeline info on the `details.status`
- this.ciStatus = pipelines[0].details.status;
- }
- this.isLoading = false;
- },
- errorCallback() {
- this.ciStatus = {
- text: 'not found',
- icon: 'status_notfound',
- group: 'notfound',
- };
- this.isLoading = false;
- Flash(s__('Something went wrong on our end'));
- },
- initPolling() {
- this.poll = new Poll({
- resource: this.service,
- method: 'fetchData',
- successCallback: response => this.successCallback(response),
- errorCallback: this.errorCallback,
- });
+ initPolling() {
+ this.poll = new Poll({
+ resource: this.service,
+ method: 'fetchData',
+ successCallback: response => this.successCallback(response),
+ errorCallback: this.errorCallback,
+ });
+
+ if (!Visibility.hidden()) {
+ this.isLoading = true;
+ this.poll.makeRequest();
+ } else {
+ this.fetchPipelineCommitData();
+ }
+ Visibility.change(() => {
if (!Visibility.hidden()) {
- this.isLoading = true;
- this.poll.makeRequest();
+ this.poll.restart();
} else {
- this.fetchPipelineCommitData();
+ this.poll.stop();
}
-
- Visibility.change(() => {
- if (!Visibility.hidden()) {
- this.poll.restart();
- } else {
- this.poll.stop();
- }
- });
- },
- fetchPipelineCommitData() {
- this.service.fetchData()
- .then(this.successCallback)
- .catch(this.errorCallback);
- },
+ });
},
- destroy() {
- this.poll.stop();
+ fetchPipelineCommitData() {
+ this.service
+ .fetchData()
+ .then(this.successCallback)
+ .catch(this.errorCallback);
},
- };
+ },
+ destroy() {
+ this.poll.stop();
+ },
+};
</script>
<template>
- <div>
+ <div class="ci-status-link">
<loading-icon
v-if="isLoading"
label="Loading pipeline status"
@@ -113,6 +114,7 @@
:title="statusTitle"
:aria-label="statusTitle"
:status="ciStatus"
+ :size="24"
data-container="body"
/>
</a>
diff --git a/app/assets/javascripts/reports/store/actions.js b/app/assets/javascripts/reports/store/actions.js
new file mode 100644
index 00000000000..15c077b0fd8
--- /dev/null
+++ b/app/assets/javascripts/reports/store/actions.js
@@ -0,0 +1,67 @@
+import Visibility from 'visibilityjs';
+import axios from '../../lib/utils/axios_utils';
+import Poll from '../../lib/utils/poll';
+import * as types from './mutation_types';
+
+export const setEndpoint = ({ commit }, endpoint) => commit(types.SET_ENDPOINT, endpoint);
+
+export const requestReports = ({ commit }) => commit(types.REQUEST_REPORTS);
+
+let eTagPoll;
+
+export const clearEtagPoll = () => {
+ eTagPoll = null;
+};
+
+export const stopPolling = () => {
+ if (eTagPoll) eTagPoll.stop();
+};
+
+export const restartPolling = () => {
+ if (eTagPoll) eTagPoll.restart();
+};
+
+/**
+ * We need to poll the reports endpoint while they are being parsed in the Backend.
+ * This can take up to one minute.
+ *
+ * Poll.js will handle etag response.
+ * While http status code is 204, it means it's parsing, and we'll keep polling
+ * When http status code is 200, it means parsing is done, we can show the results & stop polling
+ * When http status code is 500, it means parsing went wrong and we stop polling
+ */
+export const fetchReports = ({ state, dispatch }) => {
+ dispatch('requestReports');
+
+ eTagPoll = new Poll({
+ resource: {
+ getReports(endpoint) {
+ return axios.get(endpoint);
+ },
+ },
+ data: state.endpoint,
+ method: 'getReports',
+ successCallback: ({ data }) => dispatch('receiveReportsSuccess', data),
+ errorCallback: () => dispatch('receiveReportsError'),
+ });
+
+ if (!Visibility.hidden()) {
+ eTagPoll.makeRequest();
+ }
+
+ Visibility.change(() => {
+ if (!Visibility.hidden()) {
+ dispatch('restartPolling');
+ } else {
+ dispatch('stopPolling');
+ }
+ });
+};
+
+export const receiveReportsSuccess = ({ commit }, response) =>
+ commit(types.RECEIVE_REPORTS_SUCCESS, response);
+
+export const receiveReportsError = ({ commit }) => commit(types.RECEIVE_REPORTS_ERROR);
+
+// prevent babel-plugin-rewire from generating an invalid default during karma tests
+export default () => {};
diff --git a/app/assets/javascripts/reports/store/index.js b/app/assets/javascripts/reports/store/index.js
new file mode 100644
index 00000000000..af4f9688fb4
--- /dev/null
+++ b/app/assets/javascripts/reports/store/index.js
@@ -0,0 +1,13 @@
+import Vue from 'vue';
+import Vuex from 'vuex';
+import * as actions from './actions';
+import mutations from './mutations';
+import state from './state';
+
+Vue.use(Vuex);
+
+export default () => new Vuex.Store({
+ actions,
+ mutations,
+ state: state(),
+});
diff --git a/app/assets/javascripts/reports/store/mutation_types.js b/app/assets/javascripts/reports/store/mutation_types.js
new file mode 100644
index 00000000000..77722974c45
--- /dev/null
+++ b/app/assets/javascripts/reports/store/mutation_types.js
@@ -0,0 +1,5 @@
+export const SET_ENDPOINT = 'SET_ENDPOINT';
+
+export const REQUEST_REPORTS = 'REQUEST_REPORTS';
+export const RECEIVE_REPORTS_SUCCESS = 'RECEIVE_REPORTS_SUCCESS';
+export const RECEIVE_REPORTS_ERROR = 'RECEIVE_REPORTS_ERROR';
diff --git a/app/assets/javascripts/reports/store/mutations.js b/app/assets/javascripts/reports/store/mutations.js
new file mode 100644
index 00000000000..d9d301826cf
--- /dev/null
+++ b/app/assets/javascripts/reports/store/mutations.js
@@ -0,0 +1,26 @@
+/* eslint-disable no-param-reassign */
+import * as types from './mutation_types';
+
+export default {
+ [types.SET_ENDPOINT](state, endpoint) {
+ state.endpoint = endpoint;
+ },
+ [types.REQUEST_REPORTS](state) {
+ state.isLoading = true;
+ },
+ [types.RECEIVE_REPORTS_SUCCESS](state, response) {
+
+ state.isLoading = false;
+
+ state.summary.total = response.summary.total;
+ state.summary.resolved = response.summary.resolved;
+ state.summary.failed = response.summary.failed;
+
+ state.reports = response.suites;
+
+ },
+ [types.RECEIVE_REPORTS_ERROR](state) {
+ state.isLoading = false;
+ state.hasError = true;
+ },
+};
diff --git a/app/assets/javascripts/reports/store/state.js b/app/assets/javascripts/reports/store/state.js
new file mode 100644
index 00000000000..97f9d0a6859
--- /dev/null
+++ b/app/assets/javascripts/reports/store/state.js
@@ -0,0 +1,28 @@
+export default () => ({
+ endpoint: null,
+
+ isLoading: false,
+ hasError: false,
+
+ summary: {
+ total: 0,
+ resolved: 0,
+ failed: 0,
+ },
+
+ /**
+ * Each report will have the following format:
+ * {
+ * name: {String},
+ * summary: {
+ * total: {Number},
+ * resolved: {Number},
+ * failed: {Number},
+ * },
+ * new_failures: {Array.<Object>},
+ * resolved_failures: {Array.<Object>},
+ * existing_failures: {Array.<Object>},
+ * }
+ */
+ reports: [],
+});
diff --git a/app/assets/javascripts/vue_shared/components/clipboard_button.vue b/app/assets/javascripts/vue_shared/components/clipboard_button.vue
index dc5760bce28..d272bf3f55f 100644
--- a/app/assets/javascripts/vue_shared/components/clipboard_button.vue
+++ b/app/assets/javascripts/vue_shared/components/clipboard_button.vue
@@ -13,12 +13,19 @@
* />
*/
import tooltip from '../directives/tooltip';
+import Icon from '../components/icon.vue';
export default {
name: 'ClipboardButton',
+
directives: {
tooltip,
},
+
+ components: {
+ Icon,
+ },
+
props: {
text: {
type: String,
@@ -58,10 +65,6 @@ export default {
type="button"
class="btn"
>
- <i
- aria-hidden="true"
- class="fa fa-clipboard"
- >
- </i>
+ <icon name="duplicate" />
</button>
</template>
diff --git a/app/assets/stylesheets/framework/buttons.scss b/app/assets/stylesheets/framework/buttons.scss
index 523fcb05a87..646cedd79ed 100644
--- a/app/assets/stylesheets/framework/buttons.scss
+++ b/app/assets/stylesheets/framework/buttons.scss
@@ -294,6 +294,10 @@
.btn-clipboard {
border: 0;
padding: 0 5px;
+
+ svg {
+ top: auto;
+ }
}
.input-group-prepend,
diff --git a/app/assets/stylesheets/framework/dropdowns.scss b/app/assets/stylesheets/framework/dropdowns.scss
index c7b5e22c33d..ec4a0f378d0 100644
--- a/app/assets/stylesheets/framework/dropdowns.scss
+++ b/app/assets/stylesheets/framework/dropdowns.scss
@@ -822,7 +822,7 @@ header.header-content .dropdown-menu.frequent-items-dropdown-menu {
display: flex;
flex-direction: row;
width: 500px;
- height: 334px;
+ height: 354px;
.frequent-items-dropdown-sidebar,
.frequent-items-dropdown-content {
@@ -868,6 +868,7 @@ header.header-content .dropdown-menu.frequent-items-dropdown-menu {
}
.frequent-items-list-container {
+ height: 304px;
padding: 8px 0;
overflow-y: auto;
@@ -897,10 +898,6 @@ header.header-content .dropdown-menu.frequent-items-dropdown-menu {
margin-top: 8px;
}
- .frequent-items-search-container {
- height: 284px;
- }
-
@include media-breakpoint-down(xs) {
.frequent-items-list-container {
width: auto;
diff --git a/app/assets/stylesheets/framework/forms.scss b/app/assets/stylesheets/framework/forms.scss
index a22454c24e2..a10ff3eecb3 100644
--- a/app/assets/stylesheets/framework/forms.scss
+++ b/app/assets/stylesheets/framework/forms.scss
@@ -31,7 +31,7 @@ label {
margin: 0;
}
- &.label-light {
+ &.label-bold {
font-weight: $gl-font-weight-bold;
}
}
diff --git a/app/assets/stylesheets/pages/commits.scss b/app/assets/stylesheets/pages/commits.scss
index f75be4e01cd..63585e26022 100644
--- a/app/assets/stylesheets/pages/commits.scss
+++ b/app/assets/stylesheets/pages/commits.scss
@@ -205,7 +205,7 @@
> .ci-status-link,
> .btn,
> .commit-sha-group {
- margin-left: $gl-padding-8;
+ margin-left: $gl-padding;
}
}
@@ -235,10 +235,6 @@
fill: $gl-text-color-secondary;
}
- .fa-clipboard {
- color: $gl-text-color-secondary;
- }
-
:first-child {
border-bottom-left-radius: $border-radius-default;
border-top-left-radius: $border-radius-default;
diff --git a/app/assets/stylesheets/pages/reports.scss b/app/assets/stylesheets/pages/reports.scss
new file mode 100644
index 00000000000..ce253ebb71f
--- /dev/null
+++ b/app/assets/stylesheets/pages/reports.scss
@@ -0,0 +1,159 @@
+.split-report-section {
+ border-bottom: 1px solid $gray-darker;
+
+ .report-block-container {
+ max-height: 500px;
+ overflow: auto;
+ }
+
+ .space-children,
+ .space-children > span {
+ display: flex;
+ align-self: center;
+ }
+
+ .media {
+ align-items: center;
+ padding: 10px;
+ line-height: 20px;
+
+ /*
+ This fixes the wrapping div of the icon in the report header.
+ Apparently the borderless status icons are half the size of the status icons with border.
+ This means we have to double the size of the wrapping div for borderless icons.
+ */
+ .space-children:first-child {
+ width: 32px;
+ height: 32px;
+ align-items: center;
+ justify-content: center;
+ margin-right: 5px;
+ margin-left: 1px;
+ }
+ }
+
+ .code-text {
+ width: 100%;
+ flex: 1;
+ }
+}
+
+.mr-widget-grouped-section {
+ .report-block-container {
+ max-height: 170px;
+ overflow: auto;
+ }
+
+ .report-block-list-issue-parent {
+ padding: $gl-padding-top $gl-padding;
+ border-top: 1px solid $border-color;
+ }
+
+ .report-block-list-icon .loading-container {
+ position: relative;
+ left: -2px;
+ // needed to make the next element align with the
+ // elements below that have a svg with 16px width
+ .fa-spinner {
+ width: 16px;
+ }
+ }
+}
+
+.report-block-container {
+ border-top: 1px solid $border-color;
+ padding: $gl-padding-top;
+ background-color: $gray-light;
+
+ // Clean MR widget CSS
+ line-height: 20px;
+}
+
+.report-block-list {
+ list-style: none;
+ padding: 0 1px;
+ margin: 0;
+
+ .license-item {
+ line-height: $gl-padding-24;
+
+ .license-dependencies {
+ color: $gl-text-color-tertiary;
+ }
+
+ .btn-show-all-packages {
+ line-height: $gl-btn-line-height;
+ margin-bottom: 2px;
+ }
+ }
+}
+
+.report-block-list-icon {
+ display: flex;
+
+ &.failed {
+ color: $red-500;
+ }
+
+ &.success {
+ color: $green-500;
+ }
+
+ &.neutral {
+ color: $theme-gray-700;
+ }
+
+ .ci-status-icon {
+ svg {
+ width: 16px;
+ height: 16px;
+ left: -2px;
+ }
+ }
+}
+
+.report-block-list-issue {
+ display: flex;
+ align-items: flex-start;
+ align-content: flex-start;
+}
+
+.is-dismissed .report-block-list-issue-description,
+.is-dismissed .vulnerability-name-button {
+ text-decoration: line-through;
+}
+
+.report-block-list-issue-description-text::after {
+ content: '\00a0';
+}
+
+.report-block-list-issue-description {
+ align-content: space-around;
+ align-items: flex-start;
+ flex-wrap: wrap;
+ display: flex;
+ align-self: center;
+}
+
+.report-block {
+ .break-link {
+ word-wrap: break-word;
+ word-break: break-all;
+ }
+}
+
+.report-block-issue-code {
+ width: 600px;
+}
+
+.modal-security-report-dast {
+ .modal-dialog {
+ width: $modal-lg;
+ max-width: $modal-lg;
+ }
+
+ // This is temporary till we get the new modals hooked up
+ &.modal-hide-footer .modal-footer {
+ display: none;
+ }
+}
diff --git a/app/controllers/concerns/lfs_request.rb b/app/controllers/concerns/lfs_request.rb
index 79ee5b2f91e..4584ff782a3 100644
--- a/app/controllers/concerns/lfs_request.rb
+++ b/app/controllers/concerns/lfs_request.rb
@@ -71,7 +71,22 @@ module LfsRequest
def lfs_download_access?
return false unless project.lfs_enabled?
- ci? || lfs_deploy_token? || user_can_download_code? || build_can_download_code?
+ ci? || lfs_deploy_token? || user_can_download_code? || build_can_download_code? || deploy_token_can_download_code?
+ end
+
+ def deploy_token_can_download_code?
+ deploy_token_present? &&
+ deploy_token.project == project &&
+ deploy_token.active? &&
+ deploy_token.read_repository?
+ end
+
+ def deploy_token_present?
+ user && user.is_a?(DeployToken)
+ end
+
+ def deploy_token
+ user
end
def lfs_upload_access?
@@ -86,7 +101,7 @@ module LfsRequest
end
def user_can_download_code?
- has_authentication_ability?(:download_code) && can?(user, :download_code, project)
+ has_authentication_ability?(:download_code) && can?(user, :download_code, project) && !deploy_token_present?
end
def build_can_download_code?
diff --git a/app/controllers/import/gitlab_controller.rb b/app/controllers/import/gitlab_controller.rb
index fccbdbca0f6..53f70446d95 100644
--- a/app/controllers/import/gitlab_controller.rb
+++ b/app/controllers/import/gitlab_controller.rb
@@ -1,4 +1,7 @@
class Import::GitlabController < Import::BaseController
+ MAX_PROJECT_PAGES = 15
+ PER_PAGE_PROJECTS = 100
+
before_action :verify_gitlab_import_enabled
before_action :gitlab_auth, except: :callback
@@ -10,7 +13,7 @@ class Import::GitlabController < Import::BaseController
end
def status
- @repos = client.projects
+ @repos = client.projects(starting_page: 1, page_limit: MAX_PROJECT_PAGES, per_page: PER_PAGE_PROJECTS)
@already_added_projects = find_already_added_projects('gitlab')
already_added_projects_names = @already_added_projects.pluck(:import_source)
diff --git a/app/controllers/projects/raw_controller.rb b/app/controllers/projects/raw_controller.rb
index 9bc774b7636..1cba0011304 100644
--- a/app/controllers/projects/raw_controller.rb
+++ b/app/controllers/projects/raw_controller.rb
@@ -10,7 +10,6 @@ class Projects::RawController < Projects::ApplicationController
def show
@blob = @repository.blob_at(@commit.id, @path)
-
if @blob
headers['X-Content-Type-Options'] = 'nosniff'
@@ -19,7 +18,7 @@ class Projects::RawController < Projects::ApplicationController
if @blob.stored_externally?
send_lfs_object
else
- send_git_blob @repository, @blob
+ send_git_blob @repository, @blob, inline: (params[:inline] != 'false')
end
else
render_404
diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb
index 9dd652206fe..4ca42e2d4a2 100644
--- a/app/controllers/sessions_controller.rb
+++ b/app/controllers/sessions_controller.rb
@@ -157,6 +157,8 @@ class SessionsController < Devise::SessionsController
end
def auto_sign_in_with_provider
+ return unless Gitlab::Auth.omniauth_enabled?
+
provider = Gitlab.config.omniauth.auto_sign_in_with_provider
return unless provider.present?
diff --git a/app/finders/groups_finder.rb b/app/finders/groups_finder.rb
index 0754123a3cf..0eeba1d2428 100644
--- a/app/finders/groups_finder.rb
+++ b/app/finders/groups_finder.rb
@@ -8,6 +8,7 @@
# owned: boolean
# parent: Group
# all_available: boolean (defaults to true)
+# min_access_level: integer
#
# Users with full private access can see all groups. The `owned` and `parent`
# params can be used to restrict the groups that are returned.
@@ -39,6 +40,7 @@ class GroupsFinder < UnionFinder
def all_groups
return [owned_groups] if params[:owned]
+ return [groups_with_min_access_level] if min_access_level?
return [Group.all] if current_user&.full_private_access? && all_available?
groups = []
@@ -56,6 +58,16 @@ class GroupsFinder < UnionFinder
current_user.groups
end
+ def groups_with_min_access_level
+ groups = current_user
+ .groups
+ .where('members.access_level >= ?', params[:min_access_level])
+
+ Gitlab::GroupHierarchy
+ .new(groups)
+ .base_and_descendants
+ end
+
def by_parent(groups)
return groups unless params[:parent]
@@ -73,4 +85,8 @@ class GroupsFinder < UnionFinder
def all_available?
params.fetch(:all_available, true)
end
+
+ def min_access_level?
+ current_user && params[:min_access_level].present?
+ end
end
diff --git a/app/finders/personal_projects_finder.rb b/app/finders/personal_projects_finder.rb
index 5aea0cb8192..18adfea747f 100644
--- a/app/finders/personal_projects_finder.rb
+++ b/app/finders/personal_projects_finder.rb
@@ -1,6 +1,7 @@
class PersonalProjectsFinder < UnionFinder
- def initialize(user)
+ def initialize(user, params = {})
@user = user
+ @params = params
end
# Finds the projects belonging to the user in "@user", limited to either
@@ -8,6 +9,8 @@ class PersonalProjectsFinder < UnionFinder
#
# current_user - When given the list of projects is limited to those only
# visible by this user.
+ # params - Optional query parameters
+ # min_access_level: integer
#
# Returns an ActiveRecord::Relation.
def execute(current_user = nil)
@@ -19,11 +22,21 @@ class PersonalProjectsFinder < UnionFinder
private
def all_projects(current_user)
- projects = []
+ return [projects_with_min_access_level(current_user)] if current_user && min_access_level?
+ projects = []
projects << @user.personal_projects.visible_to_user(current_user) if current_user
projects << @user.personal_projects.public_to_user(current_user)
-
projects
end
+
+ def projects_with_min_access_level(current_user)
+ @user
+ .personal_projects
+ .visible_to_user_and_access_level(current_user, @params[:min_access_level])
+ end
+
+ def min_access_level?
+ @params[:min_access_level].present?
+ end
end
diff --git a/app/finders/projects_finder.rb b/app/finders/projects_finder.rb
index b06595081e7..cac6643eff3 100644
--- a/app/finders/projects_finder.rb
+++ b/app/finders/projects_finder.rb
@@ -17,6 +17,7 @@
# search: string
# non_archived: boolean
# archived: 'only' or boolean
+# min_access_level: integer
#
class ProjectsFinder < UnionFinder
include CustomAttributesFilter
@@ -34,7 +35,7 @@ class ProjectsFinder < UnionFinder
user = params.delete(:user)
collection =
if user
- PersonalProjectsFinder.new(user).execute(current_user)
+ PersonalProjectsFinder.new(user, finder_params).execute(current_user)
else
init_collection
end
@@ -65,6 +66,8 @@ class ProjectsFinder < UnionFinder
def collection_with_user
if owned_projects?
current_user.owned_projects
+ elsif min_access_level?
+ current_user.authorized_projects.where('project_authorizations.access_level >= ?', params[:min_access_level])
else
if private_only?
current_user.authorized_projects
@@ -76,7 +79,7 @@ class ProjectsFinder < UnionFinder
# Builds a collection for an anonymous user.
def collection_without_user
- if private_only? || owned_projects?
+ if private_only? || owned_projects? || min_access_level?
Project.none
else
Project.public_to_user
@@ -91,6 +94,10 @@ class ProjectsFinder < UnionFinder
params[:non_public].present?
end
+ def min_access_level?
+ params[:min_access_level].present?
+ end
+
def by_ids(items)
project_ids_relation ? items.where(id: project_ids_relation) : items
end
@@ -143,4 +150,10 @@ class ProjectsFinder < UnionFinder
projects
end
end
+
+ def finder_params
+ return {} unless min_access_level?
+
+ { min_access_level: params[:min_access_level] }
+ end
end
diff --git a/app/helpers/auth_helper.rb b/app/helpers/auth_helper.rb
index d2daee22aba..18f0979fc86 100644
--- a/app/helpers/auth_helper.rb
+++ b/app/helpers/auth_helper.rb
@@ -7,7 +7,7 @@ module AuthHelper
end
def omniauth_enabled?
- Gitlab.config.omniauth.enabled
+ Gitlab::Auth.omniauth_enabled?
end
def provider_has_icon?(name)
diff --git a/app/helpers/blob_helper.rb b/app/helpers/blob_helper.rb
index 3db28fd6da3..7eb45ddd117 100644
--- a/app/helpers/blob_helper.rb
+++ b/app/helpers/blob_helper.rb
@@ -114,22 +114,22 @@ module BlobHelper
icon("#{file_type_icon_class('file', mode, name)} fw")
end
- def blob_raw_url(only_path: false)
+ def blob_raw_url(**kwargs)
if @build && @entry
- raw_project_job_artifacts_url(@project, @build, path: @entry.path, only_path: only_path)
+ raw_project_job_artifacts_url(@project, @build, path: @entry.path, **kwargs)
elsif @snippet
if @snippet.project_id
- raw_project_snippet_url(@project, @snippet, only_path: only_path)
+ raw_project_snippet_url(@project, @snippet, **kwargs)
else
- raw_snippet_url(@snippet, only_path: only_path)
+ raw_snippet_url(@snippet, **kwargs)
end
elsif @blob
- project_raw_url(@project, @id, only_path: only_path)
+ project_raw_url(@project, @id, **kwargs)
end
end
- def blob_raw_path
- blob_raw_url(only_path: true)
+ def blob_raw_path(**kwargs)
+ blob_raw_url(**kwargs, only_path: true)
end
# SVGs can contain malicious JavaScript; only include whitelisted
@@ -226,16 +226,17 @@ module BlobHelper
def open_raw_blob_button(blob)
return if blob.empty?
+ return if blob.raw_binary? || blob.stored_externally?
- if blob.raw_binary? || blob.stored_externally?
- icon = sprite_icon('download')
- title = 'Download'
- else
- icon = icon('file-code-o')
- title = 'Open raw'
- end
+ title = 'Open raw'
+ link_to icon('file-code-o'), blob_raw_path, class: 'btn btn-sm has-tooltip', target: '_blank', rel: 'noopener noreferrer', title: title, data: { container: 'body' }
+ end
+
+ def download_blob_button(blob)
+ return if blob.empty?
- link_to icon, blob_raw_path, class: 'btn btn-sm has-tooltip', target: '_blank', rel: 'noopener noreferrer', title: title, data: { container: 'body' }
+ title = 'Download'
+ link_to sprite_icon('download'), blob_raw_path(inline: false), download: @path, class: 'btn btn-sm has-tooltip', target: '_blank', rel: 'noopener noreferrer', title: title, data: { container: 'body' }
end
def blob_render_error_reason(viewer)
diff --git a/app/helpers/button_helper.rb b/app/helpers/button_helper.rb
index 3605d6a3c95..0171a880164 100644
--- a/app/helpers/button_helper.rb
+++ b/app/helpers/button_helper.rb
@@ -51,7 +51,7 @@ module ButtonHelper
}
content_tag :button, button_attributes do
- concat(icon('clipboard', 'aria-hidden': 'true')) unless hide_button_icon
+ concat(sprite_icon('duplicate')) unless hide_button_icon
concat(button_text)
end
end
diff --git a/app/helpers/ci_status_helper.rb b/app/helpers/ci_status_helper.rb
index f49b5c7b51a..330959e536d 100644
--- a/app/helpers/ci_status_helper.rb
+++ b/app/helpers/ci_status_helper.rb
@@ -56,7 +56,7 @@ module CiStatusHelper
status.humanize
end
- def ci_icon_for_status(status)
+ def ci_icon_for_status(status, size: 16)
if detailed_status?(status)
return sprite_icon(status.icon)
end
@@ -85,7 +85,7 @@ module CiStatusHelper
'status_canceled'
end
- sprite_icon(icon_name, size: 16)
+ sprite_icon(icon_name, size: size)
end
def pipeline_status_cache_key(pipeline_status)
@@ -111,7 +111,8 @@ module CiStatusHelper
'commit',
commit.status(ref),
path,
- tooltip_placement: tooltip_placement)
+ tooltip_placement: tooltip_placement,
+ icon_size: 24)
end
def render_pipeline_status(pipeline, tooltip_placement: 'left')
@@ -125,16 +126,16 @@ module CiStatusHelper
Ci::Runner.instance_type.blank?
end
- def render_status_with_link(type, status, path = nil, tooltip_placement: 'left', cssclass: '', container: 'body')
+ def render_status_with_link(type, status, path = nil, tooltip_placement: 'left', cssclass: '', container: 'body', icon_size: 16)
klass = "ci-status-link ci-status-icon-#{status.dasherize} #{cssclass}"
title = "#{type.titleize}: #{ci_label_for_status(status)}"
data = { toggle: 'tooltip', placement: tooltip_placement, container: container }
if path
- link_to ci_icon_for_status(status), path,
+ link_to ci_icon_for_status(status, size: icon_size), path,
class: klass, title: title, data: data
else
- content_tag :span, ci_icon_for_status(status),
+ content_tag :span, ci_icon_for_status(status, size: icon_size),
class: klass, title: title, data: data
end
end
diff --git a/app/helpers/commits_helper.rb b/app/helpers/commits_helper.rb
index e5c3be47801..89fe90fd801 100644
--- a/app/helpers/commits_helper.rb
+++ b/app/helpers/commits_helper.rb
@@ -145,15 +145,14 @@ module CommitsHelper
person_name
end
- options = {
- class: "commit-#{options[:source]}-link has-tooltip",
- title: source_email
+ link_options = {
+ class: "commit-#{options[:source]}-link"
}
if user.nil?
- mail_to(source_email, text, options)
+ mail_to(source_email, text, link_options)
else
- link_to(text, user_path(user), options)
+ link_to(text, user_path(user), link_options)
end
end
diff --git a/app/helpers/visibility_level_helper.rb b/app/helpers/visibility_level_helper.rb
index e395cda03d3..cf2fe5a2019 100644
--- a/app/helpers/visibility_level_helper.rb
+++ b/app/helpers/visibility_level_helper.rb
@@ -126,10 +126,9 @@ module VisibilityLevelHelper
end
def visibility_icon_description(form_model)
- case form_model
- when Project
+ if form_model.respond_to?(:visibility_level_allowed_as_fork?)
project_visibility_icon_description(form_model.visibility_level)
- when Group
+ elsif form_model.respond_to?(:visibility_level_allowed_by_sub_groups?)
group_visibility_icon_description(form_model.visibility_level)
end
end
diff --git a/app/helpers/workhorse_helper.rb b/app/helpers/workhorse_helper.rb
index a82271ce0ee..fd1d78bd9b8 100644
--- a/app/helpers/workhorse_helper.rb
+++ b/app/helpers/workhorse_helper.rb
@@ -2,9 +2,9 @@
# Workhorse will also serve files when using `send_file`.
module WorkhorseHelper
# Send a Git blob through Workhorse
- def send_git_blob(repository, blob)
+ def send_git_blob(repository, blob, inline: true)
headers.store(*Gitlab::Workhorse.send_git_blob(repository, blob))
- headers['Content-Disposition'] = 'inline'
+ headers['Content-Disposition'] = inline ? 'inline' : 'attachment'
headers['Content-Type'] = safe_content_type(blob)
render plain: ""
end
diff --git a/app/models/concerns/protected_ref_access.rb b/app/models/concerns/protected_ref_access.rb
index 71b0c3468b9..5ff7b41b82b 100644
--- a/app/models/concerns/protected_ref_access.rb
+++ b/app/models/concerns/protected_ref_access.rb
@@ -17,6 +17,11 @@ module ProtectedRefAccess
scope :master, -> { maintainer } # @deprecated
scope :maintainer, -> { where(access_level: Gitlab::Access::MAINTAINER) }
scope :developer, -> { where(access_level: Gitlab::Access::DEVELOPER) }
+ scope :by_user, -> (user) { where(user_id: user ) }
+ scope :by_group, -> (group) { where(group_id: group ) }
+ scope :for_role, -> { where(user_id: nil, group_id: nil) }
+ scope :for_user, -> { where.not(user_id: nil) }
+ scope :for_group, -> { where.not(group_id: nil) }
validates :access_level, presence: true, if: :role?, inclusion: {
in: ALLOWED_ACCESS_LEVELS
diff --git a/app/models/deploy_token.rb b/app/models/deploy_token.rb
index 5082dc45368..7ab647abe93 100644
--- a/app/models/deploy_token.rb
+++ b/app/models/deploy_token.rb
@@ -27,7 +27,7 @@ class DeployToken < ActiveRecord::Base
end
def active?
- !revoked
+ !revoked && expires_at > Date.today
end
def scopes
@@ -58,6 +58,10 @@ class DeployToken < ActiveRecord::Base
write_attribute(:expires_at, value.presence || Forever.date)
end
+ def admin?
+ false
+ end
+
private
def ensure_at_least_one_scope
diff --git a/app/models/project.rb b/app/models/project.rb
index ae0a13b17dc..f880d728839 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -154,6 +154,7 @@ class Project < ActiveRecord::Base
has_one :mock_monitoring_service
has_one :microsoft_teams_service
has_one :packagist_service
+ has_one :hangouts_chat_service
# TODO: replace these relations with the fork network versions
has_one :forked_project_link, foreign_key: "forked_to_project_id"
@@ -326,6 +327,7 @@ class Project < ActiveRecord::Base
scope :joined, ->(user) { where('namespace_id != ?', user.namespace_id) }
scope :starred_by, ->(user) { joins(:users_star_projects).where('users_star_projects.user_id': user.id) }
scope :visible_to_user, ->(user) { where(id: user.authorized_projects.select(:id).reorder(nil)) }
+ scope :visible_to_user_and_access_level, ->(user, access_level) { where(id: user.authorized_projects.where('project_authorizations.access_level >= ?', access_level).select(:id).reorder(nil)) }
scope :archived, -> { where(archived: true) }
scope :non_archived, -> { where(archived: false) }
scope :for_milestones, ->(ids) { joins(:milestones).where('milestones.id' => ids).distinct }
diff --git a/app/models/project_services/hangouts_chat_service.rb b/app/models/project_services/hangouts_chat_service.rb
new file mode 100644
index 00000000000..a8512c5f57c
--- /dev/null
+++ b/app/models/project_services/hangouts_chat_service.rb
@@ -0,0 +1,67 @@
+require 'hangouts_chat'
+
+class HangoutsChatService < ChatNotificationService
+ def title
+ 'Hangouts Chat'
+ end
+
+ def description
+ 'Receive event notifications in Google Hangouts Chat'
+ end
+
+ def self.to_param
+ 'hangouts_chat'
+ end
+
+ def help
+ 'This service sends notifications about projects events to Google Hangouts Chat room.<br />
+ To set up this service:
+ <ol>
+ <li><a href="https://developers.google.com/hangouts/chat/how-tos/webhooks">Set up an incoming webhook for your room</a>. All notifications will come to this room.</li>
+ <li>Paste the <strong>Webhook URL</strong> into the field below.</li>
+ <li>Select events below to enable notifications.</li>
+ </ol>'
+ end
+
+ def event_field(event)
+ end
+
+ def default_channel_placeholder
+ end
+
+ def webhook_placeholder
+ 'https://chat.googleapis.com/v1/spaces…'
+ end
+
+ def default_fields
+ [
+ { type: 'text', name: 'webhook', placeholder: "e.g. #{webhook_placeholder}" },
+ { type: 'checkbox', name: 'notify_only_broken_pipelines' },
+ { type: 'checkbox', name: 'notify_only_default_branch' }
+ ]
+ end
+
+ private
+
+ def notify(message, opts)
+ simple_text = parse_simple_text_message(message)
+ HangoutsChat::Sender.new(webhook).simple(simple_text)
+ end
+
+ def parse_simple_text_message(message)
+ header = message.pretext
+ return header if message.attachments.empty?
+
+ attachment = message.attachments.first
+ title = format_attachment_title(attachment)
+ body = attachment[:text]
+
+ [header, title, body].compact.join("\n")
+ end
+
+ def format_attachment_title(attachment)
+ return attachment[:title] unless attachment[:title_link]
+
+ "<#{attachment[:title_link]}|#{attachment[:title]}>"
+ end
+end
diff --git a/app/models/service.rb b/app/models/service.rb
index ad835293b46..cbfe0c6eedd 100644
--- a/app/models/service.rb
+++ b/app/models/service.rb
@@ -254,6 +254,7 @@ class Service < ActiveRecord::Base
emails_on_push
external_wiki
flowdock
+ hangouts_chat
hipchat
irker
jira
diff --git a/app/models/user.rb b/app/models/user.rb
index 4987d01aac6..58429f8d607 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -14,7 +14,6 @@ class User < ActiveRecord::Base
include IgnorableColumn
include FeatureGate
include CreatedAtFilterable
- include IgnorableColumn
include BulkMemberAccessLoad
include BlocksJsonSerialization
include WithUploads
diff --git a/app/serializers/analytics_build_entity.rb b/app/serializers/analytics_build_entity.rb
index bdc22d71202..99663c8d5eb 100644
--- a/app/serializers/analytics_build_entity.rb
+++ b/app/serializers/analytics_build_entity.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class AnalyticsBuildEntity < Grape::Entity
include RequestAwareEntity
include EntityDateHelper
diff --git a/app/serializers/analytics_build_serializer.rb b/app/serializers/analytics_build_serializer.rb
index f172d67d356..9c9f76a1c28 100644
--- a/app/serializers/analytics_build_serializer.rb
+++ b/app/serializers/analytics_build_serializer.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class AnalyticsBuildSerializer < BaseSerializer
entity AnalyticsBuildEntity
end
diff --git a/app/serializers/analytics_commit_entity.rb b/app/serializers/analytics_commit_entity.rb
index 402cecbfd08..b25c603c9f0 100644
--- a/app/serializers/analytics_commit_entity.rb
+++ b/app/serializers/analytics_commit_entity.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class AnalyticsCommitEntity < CommitEntity
include EntityDateHelper
diff --git a/app/serializers/analytics_commit_serializer.rb b/app/serializers/analytics_commit_serializer.rb
index cdbfecf2b70..0f65687a3c0 100644
--- a/app/serializers/analytics_commit_serializer.rb
+++ b/app/serializers/analytics_commit_serializer.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class AnalyticsCommitSerializer < BaseSerializer
entity AnalyticsCommitEntity
end
diff --git a/app/serializers/analytics_generic_serializer.rb b/app/serializers/analytics_generic_serializer.rb
index 9f4859e8410..10391c13034 100644
--- a/app/serializers/analytics_generic_serializer.rb
+++ b/app/serializers/analytics_generic_serializer.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class AnalyticsGenericSerializer < BaseSerializer
def represent(resource, opts = {})
resource.symbolize_keys!
diff --git a/app/serializers/analytics_issue_entity.rb b/app/serializers/analytics_issue_entity.rb
index b7d95ea020f..ab15bd0ac7a 100644
--- a/app/serializers/analytics_issue_entity.rb
+++ b/app/serializers/analytics_issue_entity.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class AnalyticsIssueEntity < Grape::Entity
include RequestAwareEntity
include EntityDateHelper
diff --git a/app/serializers/analytics_issue_serializer.rb b/app/serializers/analytics_issue_serializer.rb
index 4fb3e8f1bb4..4a1777276a4 100644
--- a/app/serializers/analytics_issue_serializer.rb
+++ b/app/serializers/analytics_issue_serializer.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class AnalyticsIssueSerializer < AnalyticsGenericSerializer
entity AnalyticsIssueEntity
end
diff --git a/app/serializers/analytics_merge_request_entity.rb b/app/serializers/analytics_merge_request_entity.rb
index 888265eaa38..b7134da9461 100644
--- a/app/serializers/analytics_merge_request_entity.rb
+++ b/app/serializers/analytics_merge_request_entity.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class AnalyticsMergeRequestEntity < AnalyticsIssueEntity
expose :state
diff --git a/app/serializers/analytics_merge_request_serializer.rb b/app/serializers/analytics_merge_request_serializer.rb
index 4622a1dd855..f0b9115d02c 100644
--- a/app/serializers/analytics_merge_request_serializer.rb
+++ b/app/serializers/analytics_merge_request_serializer.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class AnalyticsMergeRequestSerializer < AnalyticsGenericSerializer
entity AnalyticsMergeRequestEntity
end
diff --git a/app/serializers/analytics_stage_entity.rb b/app/serializers/analytics_stage_entity.rb
index 3e355a13e06..ae7c20c3bba 100644
--- a/app/serializers/analytics_stage_entity.rb
+++ b/app/serializers/analytics_stage_entity.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class AnalyticsStageEntity < Grape::Entity
include EntityDateHelper
diff --git a/app/serializers/analytics_stage_serializer.rb b/app/serializers/analytics_stage_serializer.rb
index 613cf6874d8..86786273240 100644
--- a/app/serializers/analytics_stage_serializer.rb
+++ b/app/serializers/analytics_stage_serializer.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class AnalyticsStageSerializer < BaseSerializer
entity AnalyticsStageEntity
end
diff --git a/app/serializers/analytics_summary_entity.rb b/app/serializers/analytics_summary_entity.rb
index 9c37afd53e1..39c6b4b06b2 100644
--- a/app/serializers/analytics_summary_entity.rb
+++ b/app/serializers/analytics_summary_entity.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class AnalyticsSummaryEntity < Grape::Entity
expose :value, safe: true
expose :title
diff --git a/app/serializers/analytics_summary_serializer.rb b/app/serializers/analytics_summary_serializer.rb
index c87a24aa47c..b22bd737f03 100644
--- a/app/serializers/analytics_summary_serializer.rb
+++ b/app/serializers/analytics_summary_serializer.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class AnalyticsSummarySerializer < BaseSerializer
entity AnalyticsSummaryEntity
end
diff --git a/app/serializers/award_emoji_entity.rb b/app/serializers/award_emoji_entity.rb
index 6e03cd02392..212931a2fa9 100644
--- a/app/serializers/award_emoji_entity.rb
+++ b/app/serializers/award_emoji_entity.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class AwardEmojiEntity < Grape::Entity
expose :name
expose :user, using: API::Entities::UserSafe
diff --git a/app/serializers/base_serializer.rb b/app/serializers/base_serializer.rb
index 8cade280b0c..7b65bd22f54 100644
--- a/app/serializers/base_serializer.rb
+++ b/app/serializers/base_serializer.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class BaseSerializer
attr_reader :params
diff --git a/app/serializers/blob_entity.rb b/app/serializers/blob_entity.rb
index b501fd5e964..3ac61481dea 100644
--- a/app/serializers/blob_entity.rb
+++ b/app/serializers/blob_entity.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class BlobEntity < Grape::Entity
include RequestAwareEntity
diff --git a/app/serializers/build_action_entity.rb b/app/serializers/build_action_entity.rb
index f2d76a8ad81..f9da3f63911 100644
--- a/app/serializers/build_action_entity.rb
+++ b/app/serializers/build_action_entity.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class BuildActionEntity < Grape::Entity
include RequestAwareEntity
diff --git a/app/serializers/build_artifact_entity.rb b/app/serializers/build_artifact_entity.rb
index 6e0e33bc09b..414f436e76e 100644
--- a/app/serializers/build_artifact_entity.rb
+++ b/app/serializers/build_artifact_entity.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class BuildArtifactEntity < Grape::Entity
include RequestAwareEntity
diff --git a/app/serializers/build_details_entity.rb b/app/serializers/build_details_entity.rb
index 2de9624aed4..b887b99d31c 100644
--- a/app/serializers/build_details_entity.rb
+++ b/app/serializers/build_details_entity.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class BuildDetailsEntity < JobEntity
expose :coverage, :erased_at, :duration
expose :tag_list, as: :tags
diff --git a/app/serializers/build_metadata_entity.rb b/app/serializers/build_metadata_entity.rb
index f16f3badffa..6242ee8957d 100644
--- a/app/serializers/build_metadata_entity.rb
+++ b/app/serializers/build_metadata_entity.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class BuildMetadataEntity < Grape::Entity
expose :timeout_human_readable
expose :timeout_source do |metadata|
diff --git a/app/serializers/build_serializer.rb b/app/serializers/build_serializer.rb
index bae9932847f..0649fdad6a8 100644
--- a/app/serializers/build_serializer.rb
+++ b/app/serializers/build_serializer.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class BuildSerializer < BaseSerializer
entity JobEntity
diff --git a/app/serializers/cluster_application_entity.rb b/app/serializers/cluster_application_entity.rb
index 77fc3336521..2bd17e58086 100644
--- a/app/serializers/cluster_application_entity.rb
+++ b/app/serializers/cluster_application_entity.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class ClusterApplicationEntity < Grape::Entity
expose :name
expose :status_name, as: :status
diff --git a/app/serializers/cluster_entity.rb b/app/serializers/cluster_entity.rb
index 7e5b0997878..c59f68bbc49 100644
--- a/app/serializers/cluster_entity.rb
+++ b/app/serializers/cluster_entity.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class ClusterEntity < Grape::Entity
include RequestAwareEntity
diff --git a/app/serializers/cluster_serializer.rb b/app/serializers/cluster_serializer.rb
index 2e13c1501e7..4bb4d4880d4 100644
--- a/app/serializers/cluster_serializer.rb
+++ b/app/serializers/cluster_serializer.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class ClusterSerializer < BaseSerializer
entity ClusterEntity
diff --git a/app/serializers/cohort_activity_month_entity.rb b/app/serializers/cohort_activity_month_entity.rb
index e6788a8b596..cdbc89a2dcd 100644
--- a/app/serializers/cohort_activity_month_entity.rb
+++ b/app/serializers/cohort_activity_month_entity.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class CohortActivityMonthEntity < Grape::Entity
include ActionView::Helpers::NumberHelper
diff --git a/app/serializers/cohort_entity.rb b/app/serializers/cohort_entity.rb
index 7cdba5b0484..3d0213e1038 100644
--- a/app/serializers/cohort_entity.rb
+++ b/app/serializers/cohort_entity.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class CohortEntity < Grape::Entity
include ActionView::Helpers::NumberHelper
diff --git a/app/serializers/cohorts_entity.rb b/app/serializers/cohorts_entity.rb
index 98f5995ba6f..a84d568bf30 100644
--- a/app/serializers/cohorts_entity.rb
+++ b/app/serializers/cohorts_entity.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class CohortsEntity < Grape::Entity
expose :months_included
expose :cohorts, using: CohortEntity
diff --git a/app/serializers/cohorts_serializer.rb b/app/serializers/cohorts_serializer.rb
index fe9367b13d8..ceca5e1e5a8 100644
--- a/app/serializers/cohorts_serializer.rb
+++ b/app/serializers/cohorts_serializer.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class CohortsSerializer < AnalyticsGenericSerializer
entity CohortsEntity
end
diff --git a/app/serializers/commit_entity.rb b/app/serializers/commit_entity.rb
index c8dd98cc04d..b3287c66554 100644
--- a/app/serializers/commit_entity.rb
+++ b/app/serializers/commit_entity.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class CommitEntity < API::Entities::Commit
include RequestAwareEntity
diff --git a/app/serializers/concerns/with_pagination.rb b/app/serializers/concerns/with_pagination.rb
index 89631b73fcf..c8ffae355e8 100644
--- a/app/serializers/concerns/with_pagination.rb
+++ b/app/serializers/concerns/with_pagination.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module WithPagination
attr_accessor :paginator
diff --git a/app/serializers/container_repositories_serializer.rb b/app/serializers/container_repositories_serializer.rb
index 56dc70b5687..e1ce3c7b3ae 100644
--- a/app/serializers/container_repositories_serializer.rb
+++ b/app/serializers/container_repositories_serializer.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class ContainerRepositoriesSerializer < BaseSerializer
entity ContainerRepositoryEntity
end
diff --git a/app/serializers/container_repository_entity.rb b/app/serializers/container_repository_entity.rb
index 1103cf30a07..59bf35f5aff 100644
--- a/app/serializers/container_repository_entity.rb
+++ b/app/serializers/container_repository_entity.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class ContainerRepositoryEntity < Grape::Entity
include RequestAwareEntity
diff --git a/app/serializers/container_tag_entity.rb b/app/serializers/container_tag_entity.rb
index 8f1488e6cbb..637294877f8 100644
--- a/app/serializers/container_tag_entity.rb
+++ b/app/serializers/container_tag_entity.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class ContainerTagEntity < Grape::Entity
include RequestAwareEntity
diff --git a/app/serializers/container_tags_serializer.rb b/app/serializers/container_tags_serializer.rb
index 6ff3adff135..982ce33f6e3 100644
--- a/app/serializers/container_tags_serializer.rb
+++ b/app/serializers/container_tags_serializer.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class ContainerTagsSerializer < BaseSerializer
entity ContainerTagEntity
diff --git a/app/serializers/deploy_key_entity.rb b/app/serializers/deploy_key_entity.rb
index 2678f99510c..54bf030aba1 100644
--- a/app/serializers/deploy_key_entity.rb
+++ b/app/serializers/deploy_key_entity.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class DeployKeyEntity < Grape::Entity
expose :id
expose :user_id
diff --git a/app/serializers/deploy_key_serializer.rb b/app/serializers/deploy_key_serializer.rb
index 8f849eb88b7..a1cd98b631b 100644
--- a/app/serializers/deploy_key_serializer.rb
+++ b/app/serializers/deploy_key_serializer.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class DeployKeySerializer < BaseSerializer
entity DeployKeyEntity
end
diff --git a/app/serializers/deploy_keys_project_entity.rb b/app/serializers/deploy_keys_project_entity.rb
index 568ef5ab75e..5775ad72d0d 100644
--- a/app/serializers/deploy_keys_project_entity.rb
+++ b/app/serializers/deploy_keys_project_entity.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class DeployKeysProjectEntity < Grape::Entity
expose :can_push
expose :project, using: ProjectEntity
diff --git a/app/serializers/deployment_entity.rb b/app/serializers/deployment_entity.rb
index 241c689bccd..344148a1fb7 100644
--- a/app/serializers/deployment_entity.rb
+++ b/app/serializers/deployment_entity.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class DeploymentEntity < Grape::Entity
include RequestAwareEntity
diff --git a/app/serializers/deployment_serializer.rb b/app/serializers/deployment_serializer.rb
index cba5c3f311f..04db6b88489 100644
--- a/app/serializers/deployment_serializer.rb
+++ b/app/serializers/deployment_serializer.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class DeploymentSerializer < BaseSerializer
entity DeploymentEntity
diff --git a/app/serializers/diff_file_entity.rb b/app/serializers/diff_file_entity.rb
index 61135fba97b..79844c9210a 100644
--- a/app/serializers/diff_file_entity.rb
+++ b/app/serializers/diff_file_entity.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class DiffFileEntity < Grape::Entity
include RequestAwareEntity
include BlobHelper
diff --git a/app/serializers/diffs_entity.rb b/app/serializers/diffs_entity.rb
index bb804e5347a..f75ace14d9c 100644
--- a/app/serializers/diffs_entity.rb
+++ b/app/serializers/diffs_entity.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class DiffsEntity < Grape::Entity
include DiffHelper
include RequestAwareEntity
diff --git a/app/serializers/diffs_serializer.rb b/app/serializers/diffs_serializer.rb
index 6771e10c5ac..9e5eb1699d4 100644
--- a/app/serializers/diffs_serializer.rb
+++ b/app/serializers/diffs_serializer.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class DiffsSerializer < BaseSerializer
entity DiffsEntity
end
diff --git a/app/serializers/discussion_entity.rb b/app/serializers/discussion_entity.rb
index 7505bbdeb3d..6f95e6f9ca1 100644
--- a/app/serializers/discussion_entity.rb
+++ b/app/serializers/discussion_entity.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class DiscussionEntity < Grape::Entity
include RequestAwareEntity
include NotesHelper
diff --git a/app/serializers/discussion_serializer.rb b/app/serializers/discussion_serializer.rb
index ed5e1224bb2..5be40e74175 100644
--- a/app/serializers/discussion_serializer.rb
+++ b/app/serializers/discussion_serializer.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class DiscussionSerializer < BaseSerializer
entity DiscussionEntity
end
diff --git a/app/serializers/entity_date_helper.rb b/app/serializers/entity_date_helper.rb
index 464217123b4..cc0c2abf863 100644
--- a/app/serializers/entity_date_helper.rb
+++ b/app/serializers/entity_date_helper.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module EntityDateHelper
include ActionView::Helpers::DateHelper
include ActionView::Helpers::TagHelper
@@ -50,15 +52,20 @@ module EntityDateHelper
elsif entity.due_date
is_upcoming = (entity.due_date - Date.today).to_i > 0
time_ago = time_ago_in_words(entity.due_date)
- content = time_ago.gsub(/\d+/) { |match| "<strong>#{match}</strong>" }
- content.slice!("about ")
- content << " " + (is_upcoming ? _("remaining") : _("ago"))
- content.html_safe
+
+ # https://gitlab.com/gitlab-org/gitlab-ce/issues/49440
+ #
+ # Need to improve the i18n here and do a full translation
+ # of the string instead of piecewise translations.
+ content = time_ago
+ .gsub(/\d+/) { |match| "<strong>#{match}</strong>" }
+ .remove("about ")
+ remaining_or_ago = is_upcoming ? _("remaining") : _("ago")
+
+ "#{content} #{remaining_or_ago}".html_safe
elsif entity.start_date && entity.start_date.past?
- days = entity.elapsed_days
- content = content_tag(:strong, days)
- content << " #{'day'.pluralize(days)} elapsed"
- content.html_safe
+ days = entity.elapsed_days
+ "#{content_tag(:strong, days)} #{'day'.pluralize(days)} elapsed".html_safe
end
end
end
diff --git a/app/serializers/entity_request.rb b/app/serializers/entity_request.rb
index 456ba1174c0..49e026e8c2a 100644
--- a/app/serializers/entity_request.rb
+++ b/app/serializers/entity_request.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class EntityRequest
# We use EntityRequest object to collect parameters and variables
# from the controller. Because options that are being passed to the entity
diff --git a/app/serializers/environment_entity.rb b/app/serializers/environment_entity.rb
index 83558fc6659..b18e9706db6 100644
--- a/app/serializers/environment_entity.rb
+++ b/app/serializers/environment_entity.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class EnvironmentEntity < Grape::Entity
include RequestAwareEntity
diff --git a/app/serializers/environment_serializer.rb b/app/serializers/environment_serializer.rb
index 84722f33f59..dc1686c30c4 100644
--- a/app/serializers/environment_serializer.rb
+++ b/app/serializers/environment_serializer.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class EnvironmentSerializer < BaseSerializer
include WithPagination
diff --git a/app/serializers/group_child_entity.rb b/app/serializers/group_child_entity.rb
index ee150eefd9e..f6804fe7f6a 100644
--- a/app/serializers/group_child_entity.rb
+++ b/app/serializers/group_child_entity.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class GroupChildEntity < Grape::Entity
include ActionView::Helpers::NumberHelper
include RequestAwareEntity
diff --git a/app/serializers/group_child_serializer.rb b/app/serializers/group_child_serializer.rb
index 2baef0a5703..789707c2c9b 100644
--- a/app/serializers/group_child_serializer.rb
+++ b/app/serializers/group_child_serializer.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class GroupChildSerializer < BaseSerializer
include WithPagination
diff --git a/app/serializers/group_entity.rb b/app/serializers/group_entity.rb
index 6d8466da902..c46c342ee5d 100644
--- a/app/serializers/group_entity.rb
+++ b/app/serializers/group_entity.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class GroupEntity < Grape::Entity
include ActionView::Helpers::NumberHelper
include RequestAwareEntity
diff --git a/app/serializers/group_serializer.rb b/app/serializers/group_serializer.rb
index 8cf7eb63bcf..38c5757a6c1 100644
--- a/app/serializers/group_serializer.rb
+++ b/app/serializers/group_serializer.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class GroupSerializer < BaseSerializer
include WithPagination
diff --git a/app/serializers/group_variable_entity.rb b/app/serializers/group_variable_entity.rb
index 62cf0b21e1e..0edab4a3092 100644
--- a/app/serializers/group_variable_entity.rb
+++ b/app/serializers/group_variable_entity.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class GroupVariableEntity < Grape::Entity
expose :id
expose :key
diff --git a/app/serializers/group_variable_serializer.rb b/app/serializers/group_variable_serializer.rb
index 8f8205924aa..ed20b240cce 100644
--- a/app/serializers/group_variable_serializer.rb
+++ b/app/serializers/group_variable_serializer.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class GroupVariableSerializer < BaseSerializer
entity GroupVariableEntity
end
diff --git a/app/serializers/issuable_entity.rb b/app/serializers/issuable_entity.rb
index 6f31fbd6b7c..e71bd3313fb 100644
--- a/app/serializers/issuable_entity.rb
+++ b/app/serializers/issuable_entity.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class IssuableEntity < Grape::Entity
include RequestAwareEntity
diff --git a/app/serializers/issuable_sidebar_entity.rb b/app/serializers/issuable_sidebar_entity.rb
index 29138c803df..773d78d324c 100644
--- a/app/serializers/issuable_sidebar_entity.rb
+++ b/app/serializers/issuable_sidebar_entity.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class IssuableSidebarEntity < Grape::Entity
include TimeTrackableEntity
include RequestAwareEntity
diff --git a/app/serializers/issue_entity.rb b/app/serializers/issue_entity.rb
index 840fdbcbf14..16a477c92fa 100644
--- a/app/serializers/issue_entity.rb
+++ b/app/serializers/issue_entity.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class IssueEntity < IssuableEntity
include TimeTrackableEntity
diff --git a/app/serializers/issue_serializer.rb b/app/serializers/issue_serializer.rb
index 2555595379b..37cf5e28396 100644
--- a/app/serializers/issue_serializer.rb
+++ b/app/serializers/issue_serializer.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class IssueSerializer < BaseSerializer
# This overrided method takes care of which entity should be used
# to serialize the `issue` based on `basic` key in `opts` param.
diff --git a/app/serializers/issue_sidebar_entity.rb b/app/serializers/issue_sidebar_entity.rb
index 6c823dbfe95..349ad9d1fef 100644
--- a/app/serializers/issue_sidebar_entity.rb
+++ b/app/serializers/issue_sidebar_entity.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class IssueSidebarEntity < IssuableSidebarEntity
expose :assignees, using: API::Entities::UserBasic
end
diff --git a/app/serializers/job_entity.rb b/app/serializers/job_entity.rb
index 960e7291ae6..7bc1d87dea5 100644
--- a/app/serializers/job_entity.rb
+++ b/app/serializers/job_entity.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class JobEntity < Grape::Entity
include RequestAwareEntity
diff --git a/app/serializers/job_group_entity.rb b/app/serializers/job_group_entity.rb
index 8554de55517..0941a9d36be 100644
--- a/app/serializers/job_group_entity.rb
+++ b/app/serializers/job_group_entity.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class JobGroupEntity < Grape::Entity
include RequestAwareEntity
diff --git a/app/serializers/label_entity.rb b/app/serializers/label_entity.rb
index 4452161051e..98743d62b50 100644
--- a/app/serializers/label_entity.rb
+++ b/app/serializers/label_entity.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class LabelEntity < Grape::Entity
expose :id, if: ->(label, _) { !label.is_a?(GlobalLabel) }
diff --git a/app/serializers/label_serializer.rb b/app/serializers/label_serializer.rb
index ad6ba8c46c9..25b9f7de243 100644
--- a/app/serializers/label_serializer.rb
+++ b/app/serializers/label_serializer.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class LabelSerializer < BaseSerializer
entity LabelEntity
diff --git a/app/serializers/lfs_file_lock_entity.rb b/app/serializers/lfs_file_lock_entity.rb
index 264a77adc3f..7961c4e666b 100644
--- a/app/serializers/lfs_file_lock_entity.rb
+++ b/app/serializers/lfs_file_lock_entity.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class LfsFileLockEntity < Grape::Entity
root 'locks', 'lock'
diff --git a/app/serializers/lfs_file_lock_serializer.rb b/app/serializers/lfs_file_lock_serializer.rb
index ba8fb1a461d..0367097e376 100644
--- a/app/serializers/lfs_file_lock_serializer.rb
+++ b/app/serializers/lfs_file_lock_serializer.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class LfsFileLockSerializer < BaseSerializer
entity LfsFileLockEntity
end
diff --git a/app/serializers/merge_request_basic_entity.rb b/app/serializers/merge_request_basic_entity.rb
index 1c06691026d..f7eb74cf392 100644
--- a/app/serializers/merge_request_basic_entity.rb
+++ b/app/serializers/merge_request_basic_entity.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class MergeRequestBasicEntity < IssuableSidebarEntity
expose :assignee_id
expose :merge_status
diff --git a/app/serializers/merge_request_basic_serializer.rb b/app/serializers/merge_request_basic_serializer.rb
index cc5c664c8fa..a68b48b00db 100644
--- a/app/serializers/merge_request_basic_serializer.rb
+++ b/app/serializers/merge_request_basic_serializer.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class MergeRequestBasicSerializer < BaseSerializer
entity MergeRequestBasicEntity
end
diff --git a/app/serializers/merge_request_create_entity.rb b/app/serializers/merge_request_create_entity.rb
index 11234313293..e7a93004dda 100644
--- a/app/serializers/merge_request_create_entity.rb
+++ b/app/serializers/merge_request_create_entity.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class MergeRequestCreateEntity < Grape::Entity
expose :iid
diff --git a/app/serializers/merge_request_create_serializer.rb b/app/serializers/merge_request_create_serializer.rb
index 08daf473319..b6df9ee13fc 100644
--- a/app/serializers/merge_request_create_serializer.rb
+++ b/app/serializers/merge_request_create_serializer.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class MergeRequestCreateSerializer < BaseSerializer
entity MergeRequestCreateEntity
end
diff --git a/app/serializers/merge_request_diff_entity.rb b/app/serializers/merge_request_diff_entity.rb
index 32c761b45ac..433bfe60474 100644
--- a/app/serializers/merge_request_diff_entity.rb
+++ b/app/serializers/merge_request_diff_entity.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class MergeRequestDiffEntity < Grape::Entity
include Gitlab::Routing
include GitHelper
diff --git a/app/serializers/merge_request_metrics_entity.rb b/app/serializers/merge_request_metrics_entity.rb
index 3548107ac16..1c9db08d103 100644
--- a/app/serializers/merge_request_metrics_entity.rb
+++ b/app/serializers/merge_request_metrics_entity.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class MergeRequestMetricsEntity < Grape::Entity
expose :latest_closed_at, as: :closed_at
expose :merged_at
diff --git a/app/serializers/merge_request_serializer.rb b/app/serializers/merge_request_serializer.rb
index caf193bdae3..1f8c830e1aa 100644
--- a/app/serializers/merge_request_serializer.rb
+++ b/app/serializers/merge_request_serializer.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class MergeRequestSerializer < BaseSerializer
# This overrided method takes care of which entity should be used
# to serialize the `merge_request` based on `serializer` key in `opts` param.
diff --git a/app/serializers/merge_request_user_entity.rb b/app/serializers/merge_request_user_entity.rb
index 33fc7b724d5..fd2d2897113 100644
--- a/app/serializers/merge_request_user_entity.rb
+++ b/app/serializers/merge_request_user_entity.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class MergeRequestUserEntity < UserEntity
include RequestAwareEntity
include BlobHelper
diff --git a/app/serializers/merge_request_widget_entity.rb b/app/serializers/merge_request_widget_entity.rb
index a78bd77cf7c..4fe04e4b206 100644
--- a/app/serializers/merge_request_widget_entity.rb
+++ b/app/serializers/merge_request_widget_entity.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class MergeRequestWidgetEntity < IssuableEntity
expose :state
expose :in_progress_merge_commit_sha
diff --git a/app/serializers/note_attachment_entity.rb b/app/serializers/note_attachment_entity.rb
index 1ad50568ab9..dc801e2bf4e 100644
--- a/app/serializers/note_attachment_entity.rb
+++ b/app/serializers/note_attachment_entity.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class NoteAttachmentEntity < Grape::Entity
expose :url
expose :filename
diff --git a/app/serializers/note_entity.rb b/app/serializers/note_entity.rb
index 0e1f94a9f61..daa5c24d0f5 100644
--- a/app/serializers/note_entity.rb
+++ b/app/serializers/note_entity.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class NoteEntity < API::Entities::Note
include RequestAwareEntity
include NotesHelper
diff --git a/app/serializers/note_user_entity.rb b/app/serializers/note_user_entity.rb
index 7289f3a0222..b00dfa7d353 100644
--- a/app/serializers/note_user_entity.rb
+++ b/app/serializers/note_user_entity.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class NoteUserEntity < UserEntity
unexpose :web_url
end
diff --git a/app/serializers/pipeline_details_entity.rb b/app/serializers/pipeline_details_entity.rb
index 8ba9cac53c4..3b56767f774 100644
--- a/app/serializers/pipeline_details_entity.rb
+++ b/app/serializers/pipeline_details_entity.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class PipelineDetailsEntity < PipelineEntity
expose :details do
expose :ordered_stages, as: :stages, using: StageEntity
diff --git a/app/serializers/pipeline_entity.rb b/app/serializers/pipeline_entity.rb
index f782b411b84..6cf1925adda 100644
--- a/app/serializers/pipeline_entity.rb
+++ b/app/serializers/pipeline_entity.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class PipelineEntity < Grape::Entity
include RequestAwareEntity
diff --git a/app/serializers/pipeline_serializer.rb b/app/serializers/pipeline_serializer.rb
index 17a022539bb..4a33160afa1 100644
--- a/app/serializers/pipeline_serializer.rb
+++ b/app/serializers/pipeline_serializer.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class PipelineSerializer < BaseSerializer
include WithPagination
entity PipelineDetailsEntity
diff --git a/app/serializers/project_entity.rb b/app/serializers/project_entity.rb
index b3e5fd21e97..60c4ba135d6 100644
--- a/app/serializers/project_entity.rb
+++ b/app/serializers/project_entity.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class ProjectEntity < Grape::Entity
include RequestAwareEntity
diff --git a/app/serializers/project_mirror_entity.rb b/app/serializers/project_mirror_entity.rb
index a9c08ac021a..8aba244cd11 100644
--- a/app/serializers/project_mirror_entity.rb
+++ b/app/serializers/project_mirror_entity.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class ProjectMirrorEntity < Grape::Entity
expose :id
diff --git a/app/serializers/project_note_entity.rb b/app/serializers/project_note_entity.rb
index e541bfbee8d..d7c4d0aacc6 100644
--- a/app/serializers/project_note_entity.rb
+++ b/app/serializers/project_note_entity.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class ProjectNoteEntity < NoteEntity
expose :human_access do |note|
note.project.team.human_max_access(note.author_id)
diff --git a/app/serializers/project_note_serializer.rb b/app/serializers/project_note_serializer.rb
index 763ad0bdb3f..2182904e815 100644
--- a/app/serializers/project_note_serializer.rb
+++ b/app/serializers/project_note_serializer.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class ProjectNoteSerializer < BaseSerializer
entity ProjectNoteEntity
end
diff --git a/app/serializers/project_serializer.rb b/app/serializers/project_serializer.rb
index 74de1e79a8f..23b96c2fc9e 100644
--- a/app/serializers/project_serializer.rb
+++ b/app/serializers/project_serializer.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class ProjectSerializer < BaseSerializer
entity ProjectEntity
end
diff --git a/app/serializers/request_aware_entity.rb b/app/serializers/request_aware_entity.rb
index d53fcfb8c1b..1524c1291d8 100644
--- a/app/serializers/request_aware_entity.rb
+++ b/app/serializers/request_aware_entity.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module RequestAwareEntity
extend ActiveSupport::Concern
diff --git a/app/serializers/runner_entity.rb b/app/serializers/runner_entity.rb
index db26eadab2d..04ec80e0efa 100644
--- a/app/serializers/runner_entity.rb
+++ b/app/serializers/runner_entity.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class RunnerEntity < Grape::Entity
include RequestAwareEntity
diff --git a/app/serializers/stage_entity.rb b/app/serializers/stage_entity.rb
index 2516df70ad9..00e6d32ee3a 100644
--- a/app/serializers/stage_entity.rb
+++ b/app/serializers/stage_entity.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class StageEntity < Grape::Entity
include RequestAwareEntity
diff --git a/app/serializers/stage_serializer.rb b/app/serializers/stage_serializer.rb
index 091d8e91e43..11fb0d3f852 100644
--- a/app/serializers/stage_serializer.rb
+++ b/app/serializers/stage_serializer.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class StageSerializer < BaseSerializer
include WithPagination
diff --git a/app/serializers/status_entity.rb b/app/serializers/status_entity.rb
index 47df7f9dcf9..306c30f0323 100644
--- a/app/serializers/status_entity.rb
+++ b/app/serializers/status_entity.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class StatusEntity < Grape::Entity
include RequestAwareEntity
diff --git a/app/serializers/submodule_entity.rb b/app/serializers/submodule_entity.rb
index ed1f1ae0ef0..e475a4f301f 100644
--- a/app/serializers/submodule_entity.rb
+++ b/app/serializers/submodule_entity.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class SubmoduleEntity < Grape::Entity
include RequestAwareEntity
diff --git a/app/serializers/time_trackable_entity.rb b/app/serializers/time_trackable_entity.rb
index e81cd7bec72..613d19703a4 100644
--- a/app/serializers/time_trackable_entity.rb
+++ b/app/serializers/time_trackable_entity.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module TimeTrackableEntity
extend ActiveSupport::Concern
extend Grape
diff --git a/app/serializers/tree_entity.rb b/app/serializers/tree_entity.rb
index 9f1b485347f..9b7dc80e1d9 100644
--- a/app/serializers/tree_entity.rb
+++ b/app/serializers/tree_entity.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class TreeEntity < Grape::Entity
include RequestAwareEntity
diff --git a/app/serializers/tree_root_entity.rb b/app/serializers/tree_root_entity.rb
index 496f070ddbd..f1cfcd943d8 100644
--- a/app/serializers/tree_root_entity.rb
+++ b/app/serializers/tree_root_entity.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# TODO: Inherit from TreeEntity, when `Tree` implements `id` and `name` like `Gitlab::Git::Tree`.
class TreeRootEntity < Grape::Entity
include RequestAwareEntity
diff --git a/app/serializers/tree_serializer.rb b/app/serializers/tree_serializer.rb
index 713ade23bc9..536b8ab1ae2 100644
--- a/app/serializers/tree_serializer.rb
+++ b/app/serializers/tree_serializer.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class TreeSerializer < BaseSerializer
entity TreeRootEntity
end
diff --git a/app/serializers/user_entity.rb b/app/serializers/user_entity.rb
index 876512b12dc..6236d66ff4a 100644
--- a/app/serializers/user_entity.rb
+++ b/app/serializers/user_entity.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class UserEntity < API::Entities::UserBasic
include RequestAwareEntity
diff --git a/app/serializers/user_serializer.rb b/app/serializers/user_serializer.rb
index 49a71ebac61..2111e1b5667 100644
--- a/app/serializers/user_serializer.rb
+++ b/app/serializers/user_serializer.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class UserSerializer < BaseSerializer
entity UserEntity
end
diff --git a/app/serializers/variable_entity.rb b/app/serializers/variable_entity.rb
index d576745c073..85cf367fe51 100644
--- a/app/serializers/variable_entity.rb
+++ b/app/serializers/variable_entity.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class VariableEntity < Grape::Entity
expose :id
expose :key
diff --git a/app/serializers/variable_serializer.rb b/app/serializers/variable_serializer.rb
index 32ae82ab51c..586666cad8e 100644
--- a/app/serializers/variable_serializer.rb
+++ b/app/serializers/variable_serializer.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class VariableSerializer < BaseSerializer
entity VariableEntity
end
diff --git a/app/services/projects/import_service.rb b/app/services/projects/import_service.rb
index 60f400edfce..0c426faa22d 100644
--- a/app/services/projects/import_service.rb
+++ b/app/services/projects/import_service.rb
@@ -25,7 +25,7 @@ module Projects
success
rescue => e
- error("Error importing repository #{project.import_url} into #{project.full_path} - #{e.message}")
+ error("Error importing repository #{project.safe_import_url} into #{project.full_path} - #{e.message}")
end
private
@@ -67,7 +67,7 @@ module Projects
else
gitlab_shell.import_repository(project.repository_storage, project.disk_path, project.import_url)
end
- rescue Gitlab::Shell::Error, Gitlab::Git::RepositoryMirroring::RemoteError => e
+ rescue Gitlab::Shell::Error => e
# Expire cache to prevent scenarios such as:
# 1. First import failed, but the repo was imported successfully, so +exists?+ returns true
# 2. Retried import, repo is broken or not imported but +exists?+ still returns true
diff --git a/app/services/prometheus/adapter_service.rb b/app/services/prometheus/adapter_service.rb
index 4504d2ccfe6..cbba79690c5 100644
--- a/app/services/prometheus/adapter_service.rb
+++ b/app/services/prometheus/adapter_service.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Prometheus
class AdapterService
def initialize(project, deployment_platform = nil)
diff --git a/app/services/protected_branches/access_level_params.rb b/app/services/protected_branches/access_level_params.rb
index 4658b0e850d..a7ef573ff0b 100644
--- a/app/services/protected_branches/access_level_params.rb
+++ b/app/services/protected_branches/access_level_params.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module ProtectedBranches
class AccessLevelParams
attr_reader :type, :params
diff --git a/app/services/protected_branches/api_service.rb b/app/services/protected_branches/api_service.rb
index 4b40200644b..4340d3e8260 100644
--- a/app/services/protected_branches/api_service.rb
+++ b/app/services/protected_branches/api_service.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module ProtectedBranches
class ApiService < BaseService
def create
diff --git a/app/services/protected_branches/create_service.rb b/app/services/protected_branches/create_service.rb
index 9d947f73af1..87aaf4672a4 100644
--- a/app/services/protected_branches/create_service.rb
+++ b/app/services/protected_branches/create_service.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module ProtectedBranches
class CreateService < BaseService
def execute(skip_authorization: false)
diff --git a/app/services/protected_branches/destroy_service.rb b/app/services/protected_branches/destroy_service.rb
index 8172c896e76..7190bc2001b 100644
--- a/app/services/protected_branches/destroy_service.rb
+++ b/app/services/protected_branches/destroy_service.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module ProtectedBranches
class DestroyService < BaseService
def execute(protected_branch)
diff --git a/app/services/protected_branches/legacy_api_create_service.rb b/app/services/protected_branches/legacy_api_create_service.rb
index bb7656489c5..aef99a860a0 100644
--- a/app/services/protected_branches/legacy_api_create_service.rb
+++ b/app/services/protected_branches/legacy_api_create_service.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# The branches#protect API still uses the `developers_can_push` and `developers_can_merge`
# flags for backward compatibility, and so performs translation between that format and the
# internal data model (separate access levels). The translation code is non-trivial, and so
diff --git a/app/services/protected_branches/legacy_api_update_service.rb b/app/services/protected_branches/legacy_api_update_service.rb
index 1df38de0e4a..1f6bbe72f85 100644
--- a/app/services/protected_branches/legacy_api_update_service.rb
+++ b/app/services/protected_branches/legacy_api_update_service.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# The branches#protect API still uses the `developers_can_push` and `developers_can_merge`
# flags for backward compatibility, and so performs translation between that format and the
# internal data model (separate access levels). The translation code is non-trivial, and so
diff --git a/app/services/protected_branches/update_service.rb b/app/services/protected_branches/update_service.rb
index 95e46645374..4d7d498b8ca 100644
--- a/app/services/protected_branches/update_service.rb
+++ b/app/services/protected_branches/update_service.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module ProtectedBranches
class UpdateService < BaseService
def execute(protected_branch)
diff --git a/app/services/protected_tags/create_service.rb b/app/services/protected_tags/create_service.rb
index faba7865a17..9aff55986b2 100644
--- a/app/services/protected_tags/create_service.rb
+++ b/app/services/protected_tags/create_service.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module ProtectedTags
class CreateService < BaseService
attr_reader :protected_tag
diff --git a/app/services/protected_tags/destroy_service.rb b/app/services/protected_tags/destroy_service.rb
index c868d7ad8e6..dc4a1b39848 100644
--- a/app/services/protected_tags/destroy_service.rb
+++ b/app/services/protected_tags/destroy_service.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module ProtectedTags
class DestroyService < BaseService
def execute(protected_tag)
diff --git a/app/services/protected_tags/update_service.rb b/app/services/protected_tags/update_service.rb
index aea6a48968d..3eb5f4955ee 100644
--- a/app/services/protected_tags/update_service.rb
+++ b/app/services/protected_tags/update_service.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module ProtectedTags
class UpdateService < BaseService
def execute(protected_tag)
diff --git a/app/services/quick_actions/interpret_service.rb b/app/services/quick_actions/interpret_service.rb
index 9ac8fdb4cff..cdc8514c47c 100644
--- a/app/services/quick_actions/interpret_service.rb
+++ b/app/services/quick_actions/interpret_service.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module QuickActions
class InterpretService < BaseService
include Gitlab::QuickActions::Dsl
diff --git a/app/services/search/global_service.rb b/app/services/search/global_service.rb
index 92a32e703af..cb1bf0a03a5 100644
--- a/app/services/search/global_service.rb
+++ b/app/services/search/global_service.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Search
class GlobalService
attr_accessor :current_user, :params
diff --git a/app/services/search/group_service.rb b/app/services/search/group_service.rb
index b4efba68715..34803d005e3 100644
--- a/app/services/search/group_service.rb
+++ b/app/services/search/group_service.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Search
class GroupService < Search::GlobalService
attr_accessor :group
diff --git a/app/services/search/project_service.rb b/app/services/search/project_service.rb
index 9a22abae635..f223c8be103 100644
--- a/app/services/search/project_service.rb
+++ b/app/services/search/project_service.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Search
class ProjectService
attr_accessor :project, :current_user, :params
diff --git a/app/services/search/snippet_service.rb b/app/services/search/snippet_service.rb
index 85da0be6fff..e899a36f468 100644
--- a/app/services/search/snippet_service.rb
+++ b/app/services/search/snippet_service.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Search
class SnippetService
attr_accessor :current_user, :params
diff --git a/app/services/tags/create_service.rb b/app/services/tags/create_service.rb
index 3cc88d77ba1..329722df747 100644
--- a/app/services/tags/create_service.rb
+++ b/app/services/tags/create_service.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Tags
class CreateService < BaseService
def execute(tag_name, target, message, release_description = nil)
diff --git a/app/services/tags/destroy_service.rb b/app/services/tags/destroy_service.rb
index b84b061e460..800268485a4 100644
--- a/app/services/tags/destroy_service.rb
+++ b/app/services/tags/destroy_service.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Tags
class DestroyService < BaseService
def execute(tag_name)
diff --git a/app/services/test_hooks/base_service.rb b/app/services/test_hooks/base_service.rb
index aadc1ea644b..8b5439c00bf 100644
--- a/app/services/test_hooks/base_service.rb
+++ b/app/services/test_hooks/base_service.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module TestHooks
class BaseService
attr_accessor :hook, :current_user, :trigger
diff --git a/app/services/test_hooks/project_service.rb b/app/services/test_hooks/project_service.rb
index 65183e84cce..45e0e61e5c4 100644
--- a/app/services/test_hooks/project_service.rb
+++ b/app/services/test_hooks/project_service.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module TestHooks
class ProjectService < TestHooks::BaseService
attr_writer :project
diff --git a/app/services/test_hooks/system_service.rb b/app/services/test_hooks/system_service.rb
index 9016c77b7f0..082830c5538 100644
--- a/app/services/test_hooks/system_service.rb
+++ b/app/services/test_hooks/system_service.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module TestHooks
class SystemService < TestHooks::BaseService
private
diff --git a/app/services/users/activity_service.rb b/app/services/users/activity_service.rb
index 5803404c3c8..822df6c646a 100644
--- a/app/services/users/activity_service.rb
+++ b/app/services/users/activity_service.rb
@@ -1,12 +1,21 @@
+# frozen_string_literal: true
+
module Users
class ActivityService
+ LEASE_TIMEOUT = 1.minute.to_i
+
def initialize(author, activity)
- @author = author.respond_to?(:user) ? author.user : author
+ @user = if author.respond_to?(:username)
+ author
+ elsif author.respond_to?(:user)
+ author.user
+ end
+
@activity = activity
end
def execute
- return unless @author && @author.is_a?(User)
+ return unless @user
record_activity
end
@@ -14,9 +23,14 @@ module Users
private
def record_activity
- Gitlab::UserActivities.record(@author.id) if Gitlab::Database.read_write?
+ return if Gitlab::Database.read_only?
+
+ lease = Gitlab::ExclusiveLease.new("acitvity_service:#{@user.id}",
+ timeout: LEASE_TIMEOUT)
+ return unless lease.try_obtain
- Rails.logger.debug("Recorded activity: #{@activity} for User ID: #{@author.id} (username: #{@author.username})")
+ @user.update_attribute(:last_activity_on, Date.today)
+ Rails.logger.debug("Recorded activity: #{@activity} for User ID: #{@user.id} (username: #{@user.username})")
end
end
end
diff --git a/app/services/users/build_service.rb b/app/services/users/build_service.rb
index 4fb6d221909..c69b46cab5a 100644
--- a/app/services/users/build_service.rb
+++ b/app/services/users/build_service.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Users
class BuildService < BaseService
def initialize(current_user, params = {})
diff --git a/app/services/users/create_service.rb b/app/services/users/create_service.rb
index c8a3c461d60..2ac6dfd90fa 100644
--- a/app/services/users/create_service.rb
+++ b/app/services/users/create_service.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Users
class CreateService < BaseService
include NewUserNotifier
diff --git a/app/services/users/destroy_service.rb b/app/services/users/destroy_service.rb
index 06b604dad4d..4bc78b5b64e 100644
--- a/app/services/users/destroy_service.rb
+++ b/app/services/users/destroy_service.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Users
class DestroyService
attr_accessor :current_user
diff --git a/app/services/users/last_push_event_service.rb b/app/services/users/last_push_event_service.rb
index 57e446d7f30..a9c9497520b 100644
--- a/app/services/users/last_push_event_service.rb
+++ b/app/services/users/last_push_event_service.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Users
# Service class for caching and retrieving the last push event of a user.
class LastPushEventService
diff --git a/app/services/users/migrate_to_ghost_user_service.rb b/app/services/users/migrate_to_ghost_user_service.rb
index a2833b1e051..4d47078bf43 100644
--- a/app/services/users/migrate_to_ghost_user_service.rb
+++ b/app/services/users/migrate_to_ghost_user_service.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# When a user is destroyed, some of their associated records are
# moved to a "Ghost User", to prevent these associated records from
# being destroyed.
diff --git a/app/services/users/refresh_authorized_projects_service.rb b/app/services/users/refresh_authorized_projects_service.rb
index f028f5eb0d4..23b63aaabdf 100644
--- a/app/services/users/refresh_authorized_projects_service.rb
+++ b/app/services/users/refresh_authorized_projects_service.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Users
# Service for refreshing the authorized projects of a user.
#
diff --git a/app/services/users/respond_to_terms_service.rb b/app/services/users/respond_to_terms_service.rb
index 06d660186cf..9efa3b285a8 100644
--- a/app/services/users/respond_to_terms_service.rb
+++ b/app/services/users/respond_to_terms_service.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Users
class RespondToTermsService
def initialize(user, term)
diff --git a/app/services/users/update_service.rb b/app/services/users/update_service.rb
index 15ca1a55a5b..6dadb5a4eac 100644
--- a/app/services/users/update_service.rb
+++ b/app/services/users/update_service.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Users
class UpdateService < BaseService
include NewUserNotifier
diff --git a/app/services/wiki_pages/base_service.rb b/app/services/wiki_pages/base_service.rb
index 260c04a8b94..e259f5bd1bc 100644
--- a/app/services/wiki_pages/base_service.rb
+++ b/app/services/wiki_pages/base_service.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module WikiPages
class BaseService < ::BaseService
private
diff --git a/app/services/wiki_pages/create_service.rb b/app/services/wiki_pages/create_service.rb
index 24a817c06c9..2e2e0fd9033 100644
--- a/app/services/wiki_pages/create_service.rb
+++ b/app/services/wiki_pages/create_service.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module WikiPages
class CreateService < WikiPages::BaseService
def execute
diff --git a/app/services/wiki_pages/destroy_service.rb b/app/services/wiki_pages/destroy_service.rb
index 6b93fb2f6d7..3f9343339cd 100644
--- a/app/services/wiki_pages/destroy_service.rb
+++ b/app/services/wiki_pages/destroy_service.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module WikiPages
class DestroyService < WikiPages::BaseService
def execute(page)
diff --git a/app/services/wiki_pages/update_service.rb b/app/services/wiki_pages/update_service.rb
index 93cbd9a509f..2159dd91e9c 100644
--- a/app/services/wiki_pages/update_service.rb
+++ b/app/services/wiki_pages/update_service.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module WikiPages
class UpdateService < WikiPages::BaseService
def execute(page)
diff --git a/app/uploaders/import_export_uploader.rb b/app/uploaders/import_export_uploader.rb
index 213ac5c8011..7c45ba5ca95 100644
--- a/app/uploaders/import_export_uploader.rb
+++ b/app/uploaders/import_export_uploader.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class ImportExportUploader < AttachmentUploader
EXTENSION_WHITELIST = %w[tar.gz].freeze
diff --git a/app/views/admin/application_settings/_abuse.html.haml b/app/views/admin/application_settings/_abuse.html.haml
index 91993838fc8..4e9465fc75d 100644
--- a/app/views/admin/application_settings/_abuse.html.haml
+++ b/app/views/admin/application_settings/_abuse.html.haml
@@ -3,7 +3,7 @@
%fieldset
.form-group
- = f.label :admin_notification_email, 'Abuse reports notification email', class: 'label-light'
+ = f.label :admin_notification_email, 'Abuse reports notification email', class: 'label-bold'
= f.text_field :admin_notification_email, class: 'form-control'
.form-text.text-muted
Abuse reports will be sent to this address if it is set. Abuse reports are always available in the admin area.
diff --git a/app/views/admin/application_settings/_account_and_limit.html.haml b/app/views/admin/application_settings/_account_and_limit.html.haml
index f40939747f4..ca242b0ede9 100644
--- a/app/views/admin/application_settings/_account_and_limit.html.haml
+++ b/app/views/admin/application_settings/_account_and_limit.html.haml
@@ -8,23 +8,23 @@
= f.label :gravatar_enabled, class: 'form-check-label' do
Gravatar enabled
.form-group
- = f.label :default_projects_limit, class: 'label-light'
+ = f.label :default_projects_limit, class: 'label-bold'
= f.number_field :default_projects_limit, class: 'form-control'
.form-group
- = f.label :max_attachment_size, 'Maximum attachment size (MB)', class: 'label-light'
+ = f.label :max_attachment_size, 'Maximum attachment size (MB)', class: 'label-bold'
= f.number_field :max_attachment_size, class: 'form-control'
.form-group
- = f.label :session_expire_delay, 'Session duration (minutes)', class: 'label-light'
+ = f.label :session_expire_delay, 'Session duration (minutes)', class: 'label-bold'
= f.number_field :session_expire_delay, class: 'form-control'
%span.form-text.text-muted#session_expire_delay_help_block GitLab restart is required to apply changes
.form-group
- = f.label :user_oauth_applications, 'User OAuth applications', class: 'label-light'
+ = f.label :user_oauth_applications, 'User OAuth applications', class: 'label-bold'
.form-check
= f.check_box :user_oauth_applications, class: 'form-check-input'
= f.label :user_oauth_applications, class: 'form-check-label' do
Allow users to register any application to use GitLab as an OAuth provider
.form-group
- = f.label :user_default_external, 'New users set to external', class: 'label-light'
+ = f.label :user_default_external, 'New users set to external', class: 'label-bold'
.form-check
= f.check_box :user_default_external, class: 'form-check-input'
= f.label :user_default_external, class: 'form-check-label' do
diff --git a/app/views/admin/application_settings/_background_jobs.html.haml b/app/views/admin/application_settings/_background_jobs.html.haml
index fd8e695ed49..02d761576e3 100644
--- a/app/views/admin/application_settings/_background_jobs.html.haml
+++ b/app/views/admin/application_settings/_background_jobs.html.haml
@@ -14,12 +14,12 @@
.form-text.text-muted
Limit the amount of resources slow running jobs are assigned.
.form-group
- = f.label :sidekiq_throttling_queues, 'Sidekiq queues to throttle', class: 'label-light'
+ = f.label :sidekiq_throttling_queues, 'Sidekiq queues to throttle', class: 'label-bold'
= f.select :sidekiq_throttling_queues, sidekiq_queue_options_for_select, { include_hidden: false }, multiple: true, class: 'select2 select-wide', data: { field: 'sidekiq_throttling_queues' }
.form-text.text-muted
Choose which queues you wish to throttle.
.form-group
- = f.label :sidekiq_throttling_factor, 'Throttling Factor', class: 'label-light'
+ = f.label :sidekiq_throttling_factor, 'Throttling Factor', class: 'label-bold'
= f.number_field :sidekiq_throttling_factor, class: 'form-control', min: '0.01', max: '0.99', step: '0.01'
.form-text.text-muted
The factor by which the queues should be throttled. A value between 0.0 and 1.0, exclusive.
diff --git a/app/views/admin/application_settings/_ci_cd.html.haml b/app/views/admin/application_settings/_ci_cd.html.haml
index 7c16cafe13f..7a304ef2884 100644
--- a/app/views/admin/application_settings/_ci_cd.html.haml
+++ b/app/views/admin/application_settings/_ci_cd.html.haml
@@ -11,7 +11,7 @@
It will automatically build, test, and deploy applications based on a predefined CI/CD configuration
= link_to icon('question-circle'), help_page_path('topics/autodevops/index.md')
.form-group
- = f.label :auto_devops_domain, class: 'label-light'
+ = f.label :auto_devops_domain, class: 'label-bold'
= f.text_field :auto_devops_domain, class: 'form-control', placeholder: 'domain.com'
.form-text.text-muted
= s_("AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages.")
@@ -21,17 +21,17 @@
= f.label :shared_runners_enabled, class: 'form-check-label' do
Enable shared runners for new projects
.form-group
- = f.label :shared_runners_text, class: 'label-light'
+ = f.label :shared_runners_text, class: 'label-bold'
= f.text_area :shared_runners_text, class: 'form-control', rows: 4
.form-text.text-muted Markdown enabled
.form-group
- = f.label :max_artifacts_size, 'Maximum artifacts size (MB)', class: 'label-light'
+ = f.label :max_artifacts_size, 'Maximum artifacts size (MB)', class: 'label-bold'
= f.number_field :max_artifacts_size, class: 'form-control'
.form-text.text-muted
Set the maximum file size for each job's artifacts
= link_to icon('question-circle'), help_page_path('user/admin_area/settings/continuous_integration', anchor: 'maximum-artifacts-size')
.form-group
- = f.label :default_artifacts_expire_in, 'Default artifacts expiration', class: 'label-light'
+ = f.label :default_artifacts_expire_in, 'Default artifacts expiration', class: 'label-bold'
= f.text_field :default_artifacts_expire_in, class: 'form-control'
.form-text.text-muted
Set the default expiration time for each job's artifacts.
diff --git a/app/views/admin/application_settings/_gitaly.html.haml b/app/views/admin/application_settings/_gitaly.html.haml
index 0b4001c0824..4ade9ee975a 100644
--- a/app/views/admin/application_settings/_gitaly.html.haml
+++ b/app/views/admin/application_settings/_gitaly.html.haml
@@ -3,20 +3,20 @@
%fieldset
.form-group
- = f.label :gitaly_timeout_default, 'Default Timeout Period', class: 'label-light'
+ = f.label :gitaly_timeout_default, 'Default Timeout Period', class: 'label-bold'
= f.number_field :gitaly_timeout_default, class: 'form-control'
.form-text.text-muted
Timeout for Gitaly calls from the GitLab application (in seconds). This timeout is not enforced
for git fetch/push operations or Sidekiq jobs.
.form-group
- = f.label :gitaly_timeout_fast, 'Fast Timeout Period', class: 'label-light'
+ = f.label :gitaly_timeout_fast, 'Fast Timeout Period', class: 'label-bold'
= f.number_field :gitaly_timeout_fast, class: 'form-control'
.form-text.text-muted
Fast operation timeout (in seconds). Some Gitaly operations are expected to be fast.
If they exceed this threshold, there may be a problem with a storage shard and 'failing fast'
can help maintain the stability of the GitLab instance.
.form-group
- = f.label :gitaly_timeout_medium, 'Medium Timeout Period', class: 'label-light'
+ = f.label :gitaly_timeout_medium, 'Medium Timeout Period', class: 'label-bold'
= f.number_field :gitaly_timeout_medium, class: 'form-control'
.form-text.text-muted
Medium operation timeout (in seconds). This should be a value between the Fast and the Default timeout.
diff --git a/app/views/admin/application_settings/_help_page.html.haml b/app/views/admin/application_settings/_help_page.html.haml
index 1f402fcb786..73f8d7bb77c 100644
--- a/app/views/admin/application_settings/_help_page.html.haml
+++ b/app/views/admin/application_settings/_help_page.html.haml
@@ -3,7 +3,7 @@
%fieldset
.form-group
- = f.label :help_page_text, class: 'label-light'
+ = f.label :help_page_text, class: 'label-bold'
= f.text_area :help_page_text, class: 'form-control', rows: 4
.form-text.text-muted Markdown enabled
.form-group
@@ -12,7 +12,7 @@
= f.label :help_page_hide_commercial_content, class: 'form-check-label' do
Hide marketing-related entries from help
.form-group
- = f.label :help_page_support_url, 'Support page URL', class: 'label-light'
+ = f.label :help_page_support_url, 'Support page URL', class: 'label-bold'
= f.text_field :help_page_support_url, class: 'form-control', placeholder: 'http://company.example.com/getting-help', :'aria-describedby' => 'support_help_block'
%span.form-text.text-muted#support_help_block Alternate support URL for help page
diff --git a/app/views/admin/application_settings/_influx.html.haml b/app/views/admin/application_settings/_influx.html.haml
index 61e8e3199a9..2f6d6ddf23d 100644
--- a/app/views/admin/application_settings/_influx.html.haml
+++ b/app/views/admin/application_settings/_influx.html.haml
@@ -14,10 +14,10 @@
= f.label :metrics_enabled, class: 'form-check-label' do
Enable InfluxDB Metrics
.form-group
- = f.label :metrics_host, 'InfluxDB host', class: 'label-light'
+ = f.label :metrics_host, 'InfluxDB host', class: 'label-bold'
= f.text_field :metrics_host, class: 'form-control', placeholder: 'influxdb.example.com'
.form-group
- = f.label :metrics_port, 'InfluxDB port', class: 'label-light'
+ = f.label :metrics_port, 'InfluxDB port', class: 'label-bold'
= f.text_field :metrics_port, class: 'form-control', placeholder: '8089'
.form-text.text-muted
The UDP port to use for connecting to InfluxDB. InfluxDB requires that
@@ -25,7 +25,7 @@
sending messages to this port, without it metrics data will not be
saved.
.form-group
- = f.label :metrics_pool_size, 'Connection pool size', class: 'label-light'
+ = f.label :metrics_pool_size, 'Connection pool size', class: 'label-bold'
= f.number_field :metrics_pool_size, class: 'form-control'
.form-text.text-muted
The amount of InfluxDB connections to open. Connections are opened
@@ -33,25 +33,25 @@
enough connections are available (at minimum the amount of application
server threads).
.form-group
- = f.label :metrics_timeout, 'Connection timeout', class: 'label-light'
+ = f.label :metrics_timeout, 'Connection timeout', class: 'label-bold'
= f.number_field :metrics_timeout, class: 'form-control'
.form-text.text-muted
The amount of seconds after which an InfluxDB connection will time
out.
.form-group
- = f.label :metrics_method_call_threshold, 'Method Call Threshold (ms)', class: 'label-light'
+ = f.label :metrics_method_call_threshold, 'Method Call Threshold (ms)', class: 'label-bold'
= f.number_field :metrics_method_call_threshold, class: 'form-control'
.form-text.text-muted
A method call is only tracked when it takes longer to complete than
the given amount of milliseconds.
.form-group
- = f.label :metrics_sample_interval, 'Sampler Interval (sec)', class: 'label-light'
+ = f.label :metrics_sample_interval, 'Sampler Interval (sec)', class: 'label-bold'
= f.number_field :metrics_sample_interval, class: 'form-control'
.form-text.text-muted
The sampling interval in seconds. Sampled data includes memory usage,
retained Ruby objects, file descriptors and so on.
.form-group
- = f.label :metrics_packet_size, 'Metrics per packet', class: 'label-light'
+ = f.label :metrics_packet_size, 'Metrics per packet', class: 'label-bold'
= f.number_field :metrics_packet_size, class: 'form-control'
.form-text.text-muted
The amount of points to store in a single UDP packet. More points
diff --git a/app/views/admin/application_settings/_ip_limits.html.haml b/app/views/admin/application_settings/_ip_limits.html.haml
index 73d570a5fee..44118777467 100644
--- a/app/views/admin/application_settings/_ip_limits.html.haml
+++ b/app/views/admin/application_settings/_ip_limits.html.haml
@@ -10,10 +10,10 @@
%span.form-text.text-muted
Helps reduce request volume (e.g. from crawlers or abusive bots)
.form-group
- = f.label :throttle_unauthenticated_requests_per_period, 'Max requests per period per IP', class: 'label-light'
+ = f.label :throttle_unauthenticated_requests_per_period, 'Max requests per period per IP', class: 'label-bold'
= f.number_field :throttle_unauthenticated_requests_per_period, class: 'form-control'
.form-group
- = f.label :throttle_unauthenticated_period_in_seconds, 'Rate limit period in seconds', class: 'label-light'
+ = f.label :throttle_unauthenticated_period_in_seconds, 'Rate limit period in seconds', class: 'label-bold'
= f.number_field :throttle_unauthenticated_period_in_seconds, class: 'form-control'
.form-group
.form-check
@@ -23,10 +23,10 @@
%span.form-text.text-muted
Helps reduce request volume (e.g. from crawlers or abusive bots)
.form-group
- = f.label :throttle_authenticated_api_requests_per_period, 'Max requests per period per user', class: 'label-light'
+ = f.label :throttle_authenticated_api_requests_per_period, 'Max requests per period per user', class: 'label-bold'
= f.number_field :throttle_authenticated_api_requests_per_period, class: 'form-control'
.form-group
- = f.label :throttle_authenticated_api_period_in_seconds, 'Rate limit period in seconds', class: 'label-light'
+ = f.label :throttle_authenticated_api_period_in_seconds, 'Rate limit period in seconds', class: 'label-bold'
= f.number_field :throttle_authenticated_api_period_in_seconds, class: 'form-control'
.form-group
.form-check
@@ -36,10 +36,10 @@
%span.form-text.text-muted
Helps reduce request volume (e.g. from crawlers or abusive bots)
.form-group
- = f.label :throttle_authenticated_web_requests_per_period, 'Max requests per period per user', class: 'label-light'
+ = f.label :throttle_authenticated_web_requests_per_period, 'Max requests per period per user', class: 'label-bold'
= f.number_field :throttle_authenticated_web_requests_per_period, class: 'form-control'
.form-group
- = f.label :throttle_authenticated_web_period_in_seconds, 'Rate limit period in seconds', class: 'label-light'
+ = f.label :throttle_authenticated_web_period_in_seconds, 'Rate limit period in seconds', class: 'label-bold'
= f.number_field :throttle_authenticated_web_period_in_seconds, class: 'form-control'
= f.submit 'Save changes', class: "btn btn-success"
diff --git a/app/views/admin/application_settings/_koding.html.haml b/app/views/admin/application_settings/_koding.html.haml
index ae60f68f5fe..798a061feb6 100644
--- a/app/views/admin/application_settings/_koding.html.haml
+++ b/app/views/admin/application_settings/_koding.html.haml
@@ -10,7 +10,7 @@
.form-text.text-muted
Koding integration has been deprecated since GitLab 10.0. If you disable your Koding integration, you will not be able to enable it again.
.form-group
- = f.label :koding_url, 'Koding URL', class: 'label-light'
+ = f.label :koding_url, 'Koding URL', class: 'label-bold'
= f.text_field :koding_url, class: 'form-control', placeholder: 'http://gitlab.your-koding-instance.com:8090'
.form-text.text-muted
Koding has integration enabled out of the box for the
diff --git a/app/views/admin/application_settings/_logging.html.haml b/app/views/admin/application_settings/_logging.html.haml
index a6e549cd1f0..f13df885997 100644
--- a/app/views/admin/application_settings/_logging.html.haml
+++ b/app/views/admin/application_settings/_logging.html.haml
@@ -13,7 +13,7 @@
%a{ href: 'https://getsentry.com', target: '_blank', rel: 'noopener noreferrer' } https://getsentry.com
.form-group
- = f.label :sentry_dsn, 'Sentry DSN', class: 'label-light'
+ = f.label :sentry_dsn, 'Sentry DSN', class: 'label-bold'
= f.text_field :sentry_dsn, class: 'form-control'
.form-group
@@ -26,7 +26,7 @@
%a{ href: 'https://sentry.io/for/javascript/', target: '_blank', rel: 'noopener noreferrer' } https://sentry.io/for/javascript/
.form-group
- = f.label :clientside_sentry_dsn, 'Clientside Sentry DSN', class: 'label-light'
+ = f.label :clientside_sentry_dsn, 'Clientside Sentry DSN', class: 'label-bold'
= f.text_field :clientside_sentry_dsn, class: 'form-control'
= f.submit 'Save changes', class: "btn btn-success"
diff --git a/app/views/admin/application_settings/_pages.html.haml b/app/views/admin/application_settings/_pages.html.haml
index f168ec62ffd..cf4b4c000b5 100644
--- a/app/views/admin/application_settings/_pages.html.haml
+++ b/app/views/admin/application_settings/_pages.html.haml
@@ -3,7 +3,7 @@
%fieldset
.form-group
- = f.label :max_pages_size, 'Maximum size of pages (MB)', class: 'label-light'
+ = f.label :max_pages_size, 'Maximum size of pages (MB)', class: 'label-bold'
= f.number_field :max_pages_size, class: 'form-control'
.form-text.text-muted 0 for unlimited
.form-group
diff --git a/app/views/admin/application_settings/_performance_bar.html.haml b/app/views/admin/application_settings/_performance_bar.html.haml
index ddbfcc6b77b..c4e14ffb8af 100644
--- a/app/views/admin/application_settings/_performance_bar.html.haml
+++ b/app/views/admin/application_settings/_performance_bar.html.haml
@@ -8,7 +8,7 @@
= f.label :performance_bar_enabled, class: 'form-check-label' do
Enable the Performance Bar
.form-group
- = f.label :performance_bar_allowed_group_path, 'Allowed group', class: 'label-light'
+ = f.label :performance_bar_allowed_group_path, 'Allowed group', class: 'label-bold'
= f.text_field :performance_bar_allowed_group_path, class: 'form-control', placeholder: 'my-org/my-group', value: @application_setting.performance_bar_allowed_group&.full_path
= f.submit 'Save changes', class: "btn btn-success"
diff --git a/app/views/admin/application_settings/_plantuml.html.haml b/app/views/admin/application_settings/_plantuml.html.haml
index 259f18b3b96..07ffcc9e73a 100644
--- a/app/views/admin/application_settings/_plantuml.html.haml
+++ b/app/views/admin/application_settings/_plantuml.html.haml
@@ -8,7 +8,7 @@
= f.label :plantuml_enabled, class: 'form-check-label' do
Enable PlantUML
.form-group
- = f.label :plantuml_url, 'PlantUML URL', class: 'label-light'
+ = f.label :plantuml_url, 'PlantUML URL', class: 'label-bold'
= f.text_field :plantuml_url, class: 'form-control', placeholder: 'http://gitlab.your-plantuml-instance.com:8080'
.form-text.text-muted
Allow rendering of
diff --git a/app/views/admin/application_settings/_realtime.html.haml b/app/views/admin/application_settings/_realtime.html.haml
index 120cf4909b2..4d224d7dd51 100644
--- a/app/views/admin/application_settings/_realtime.html.haml
+++ b/app/views/admin/application_settings/_realtime.html.haml
@@ -3,7 +3,7 @@
%fieldset
.form-group
- = f.label :polling_interval_multiplier, 'Polling interval multiplier', class: 'label-light'
+ = f.label :polling_interval_multiplier, 'Polling interval multiplier', class: 'label-bold'
= f.text_field :polling_interval_multiplier, class: 'form-control'
.form-text.text-muted
Change this value to influence how frequently the GitLab UI polls for updates.
diff --git a/app/views/admin/application_settings/_registry.html.haml b/app/views/admin/application_settings/_registry.html.haml
index beac70482e5..c511b1ee08a 100644
--- a/app/views/admin/application_settings/_registry.html.haml
+++ b/app/views/admin/application_settings/_registry.html.haml
@@ -3,7 +3,7 @@
%fieldset
.form-group
- = f.label :container_registry_token_expire_delay, 'Authorization token duration (minutes)', class: 'label-light'
+ = f.label :container_registry_token_expire_delay, 'Authorization token duration (minutes)', class: 'label-bold'
= f.number_field :container_registry_token_expire_delay, class: 'form-control'
= f.submit 'Save changes', class: "btn btn-success"
diff --git a/app/views/admin/application_settings/_repository_check.html.haml b/app/views/admin/application_settings/_repository_check.html.haml
index 57facc380eb..cacbcf65845 100644
--- a/app/views/admin/application_settings/_repository_check.html.haml
+++ b/app/views/admin/application_settings/_repository_check.html.haml
@@ -38,17 +38,17 @@
Creating pack file bitmaps makes housekeeping take a little longer but
bitmaps should accelerate 'git clone' performance.
.form-group
- = f.label :housekeeping_incremental_repack_period, 'Incremental repack period', class: 'label-light'
+ = f.label :housekeeping_incremental_repack_period, 'Incremental repack period', class: 'label-bold'
= f.number_field :housekeeping_incremental_repack_period, class: 'form-control'
.form-text.text-muted
Number of Git pushes after which an incremental 'git repack' is run.
.form-group
- = f.label :housekeeping_full_repack_period, 'Full repack period', class: 'label-light'
+ = f.label :housekeeping_full_repack_period, 'Full repack period', class: 'label-bold'
= f.number_field :housekeeping_full_repack_period, class: 'form-control'
.form-text.text-muted
Number of Git pushes after which a full 'git repack' is run.
.form-group
- = f.label :housekeeping_gc_period, 'Git GC period', class: 'label-light'
+ = f.label :housekeeping_gc_period, 'Git GC period', class: 'label-bold'
= f.number_field :housekeeping_gc_period, class: 'form-control'
.form-text.text-muted
Number of Git pushes after which 'git gc' is run.
diff --git a/app/views/admin/application_settings/_repository_mirrors_form.html.haml b/app/views/admin/application_settings/_repository_mirrors_form.html.haml
index beeb5169361..dbc1e9e3a71 100644
--- a/app/views/admin/application_settings/_repository_mirrors_form.html.haml
+++ b/app/views/admin/application_settings/_repository_mirrors_form.html.haml
@@ -3,7 +3,7 @@
%fieldset
.form-group
- = f.label :mirror_available, 'Enable mirror configuration', class: 'label-light'
+ = f.label :mirror_available, 'Enable mirror configuration', class: 'label-bold'
.form-check
= f.check_box :mirror_available, class: 'form-check-input'
= f.label :mirror_available, class: 'form-check-label' do
diff --git a/app/views/admin/application_settings/_repository_storage.html.haml b/app/views/admin/application_settings/_repository_storage.html.haml
index 5a303666353..685de99917e 100644
--- a/app/views/admin/application_settings/_repository_storage.html.haml
+++ b/app/views/admin/application_settings/_repository_storage.html.haml
@@ -13,7 +13,7 @@
repositories from having to be moved or renamed when the Project URL changes and may improve disk I/O performance.
%em (EXPERIMENTAL)
.form-group
- = f.label :repository_storages, 'Storage paths for new projects', class: 'label-light'
+ = f.label :repository_storages, 'Storage paths for new projects', class: 'label-bold'
= f.select :repository_storages, repository_storages_options_for_select(@application_setting.repository_storages),
{include_hidden: false}, multiple: true, class: 'form-control'
.form-text.text-muted
@@ -23,27 +23,27 @@
.sub-section
%h4 Circuit breaker
.form-group
- = f.label :circuitbreaker_check_interval, _('Check interval'), class: 'label-light'
+ = f.label :circuitbreaker_check_interval, _('Check interval'), class: 'label-bold'
= f.number_field :circuitbreaker_check_interval, class: 'form-control'
.form-text.text-muted
= circuitbreaker_check_interval_help_text
.form-group
- = f.label :circuitbreaker_access_retries, _('Number of access attempts'), class: 'label-light'
+ = f.label :circuitbreaker_access_retries, _('Number of access attempts'), class: 'label-bold'
= f.number_field :circuitbreaker_access_retries, class: 'form-control'
.form-text.text-muted
= circuitbreaker_access_retries_help_text
.form-group
- = f.label :circuitbreaker_storage_timeout, _('Seconds to wait for a storage access attempt'), class: 'label-light'
+ = f.label :circuitbreaker_storage_timeout, _('Seconds to wait for a storage access attempt'), class: 'label-bold'
= f.number_field :circuitbreaker_storage_timeout, class: 'form-control'
.form-text.text-muted
= circuitbreaker_storage_timeout_help_text
.form-group
- = f.label :circuitbreaker_failure_count_threshold, _('Maximum git storage failures'), class: 'label-light'
+ = f.label :circuitbreaker_failure_count_threshold, _('Maximum git storage failures'), class: 'label-bold'
= f.number_field :circuitbreaker_failure_count_threshold, class: 'form-control'
.form-text.text-muted
= circuitbreaker_failure_count_help_text
.form-group
- = f.label :circuitbreaker_failure_reset_time, _('Seconds before reseting failure information'), class: 'label-light'
+ = f.label :circuitbreaker_failure_reset_time, _('Seconds before reseting failure information'), class: 'label-bold'
= f.number_field :circuitbreaker_failure_reset_time, class: 'form-control'
.form-text.text-muted
= circuitbreaker_failure_reset_time_help_text
diff --git a/app/views/admin/application_settings/_signin.html.haml b/app/views/admin/application_settings/_signin.html.haml
index 69d1a43c511..344ed2339fb 100644
--- a/app/views/admin/application_settings/_signin.html.haml
+++ b/app/views/admin/application_settings/_signin.html.haml
@@ -21,31 +21,31 @@
must be used to authenticate.
- if omniauth_enabled? && button_based_providers.any?
.form-group
- = f.label :enabled_oauth_sign_in_sources, 'Enabled OAuth sign-in sources', class: 'label-light'
+ = f.label :enabled_oauth_sign_in_sources, 'Enabled OAuth sign-in sources', class: 'label-bold'
= hidden_field_tag 'application_setting[enabled_oauth_sign_in_sources][]'
.btn-group{ data: { toggle: 'buttons' } }
- oauth_providers_checkboxes.each do |source|
= source
.form-group
- = f.label :two_factor_authentication, 'Two-factor authentication', class: 'label-light'
+ = f.label :two_factor_authentication, 'Two-factor authentication', class: 'label-bold'
.form-check
= f.check_box :require_two_factor_authentication, class: 'form-check-input'
= f.label :require_two_factor_authentication, class: 'form-check-label' do
Require all users to setup Two-factor authentication
.form-group
- = f.label :two_factor_authentication, 'Two-factor grace period (hours)', class: 'label-light'
+ = f.label :two_factor_authentication, 'Two-factor grace period (hours)', class: 'label-bold'
= f.number_field :two_factor_grace_period, min: 0, class: 'form-control', placeholder: '0'
.form-text.text-muted Amount of time (in hours) that users are allowed to skip forced configuration of two-factor authentication
.form-group
- = f.label :home_page_url, 'Home page URL', class: 'label-light'
+ = f.label :home_page_url, 'Home page URL', class: 'label-bold'
= f.text_field :home_page_url, class: 'form-control', placeholder: 'http://company.example.com', :'aria-describedby' => 'home_help_block'
%span.form-text.text-muted#home_help_block We will redirect non-logged in users to this page
.form-group
- = f.label :after_sign_out_path, class: 'label-light'
+ = f.label :after_sign_out_path, class: 'label-bold'
= f.text_field :after_sign_out_path, class: 'form-control', placeholder: 'http://company.example.com', :'aria-describedby' => 'after_sign_out_path_help_block'
%span.form-text.text-muted#after_sign_out_path_help_block We will redirect users to this page after they sign out
.form-group
- = f.label :sign_in_text, class: 'label-light'
+ = f.label :sign_in_text, class: 'label-bold'
= f.text_area :sign_in_text, class: 'form-control', rows: 4
.form-text.text-muted Markdown enabled
diff --git a/app/views/admin/application_settings/_signup.html.haml b/app/views/admin/application_settings/_signup.html.haml
index b9ba9128cc9..2b5ff5a38e3 100644
--- a/app/views/admin/application_settings/_signup.html.haml
+++ b/app/views/admin/application_settings/_signup.html.haml
@@ -13,11 +13,11 @@
= f.label :send_user_confirmation_email, class: 'form-check-label' do
Send confirmation email on sign-up
.form-group
- = f.label :domain_whitelist, 'Whitelisted domains for sign-ups', class: 'label-light'
+ = f.label :domain_whitelist, 'Whitelisted domains for sign-ups', class: 'label-bold'
= f.text_area :domain_whitelist_raw, placeholder: 'domain.com', class: 'form-control', rows: 8
.form-text.text-muted ONLY users with e-mail addresses that match these domain(s) will be able to sign-up. Wildcards allowed. Use separate lines for multiple entries. Ex: domain.com, *.domain.com
.form-group
- = f.label :domain_blacklist_enabled, 'Domain Blacklist', class: 'label-light'
+ = f.label :domain_blacklist_enabled, 'Domain Blacklist', class: 'label-bold'
.form-check
= f.check_box :domain_blacklist_enabled, class: 'form-check-input'
= f.label :domain_blacklist_enabled, class: 'form-check-label' do
@@ -34,16 +34,16 @@
.option-title
Enter blacklist manually
.form-group.blacklist-file
- = f.label :domain_blacklist_file, 'Blacklist file', class: 'label-light'
+ = f.label :domain_blacklist_file, 'Blacklist file', class: 'label-bold'
= f.file_field :domain_blacklist_file, class: 'form-control', accept: '.txt,.conf'
.form-text.text-muted Users with e-mail addresses that match these domain(s) will NOT be able to sign-up. Wildcards allowed. Use separate lines or commas for multiple entries.
.form-group.blacklist-raw
- = f.label :domain_blacklist, 'Blacklisted domains for sign-ups', class: 'label-light'
+ = f.label :domain_blacklist, 'Blacklisted domains for sign-ups', class: 'label-bold'
= f.text_area :domain_blacklist_raw, placeholder: 'domain.com', class: 'form-control', rows: 8
.form-text.text-muted Users with e-mail addresses that match these domain(s) will NOT be able to sign-up. Wildcards allowed. Use separate lines for multiple entries. Ex: domain.com, *.domain.com
.form-group
- = f.label :after_sign_up_text, class: 'label-light'
+ = f.label :after_sign_up_text, class: 'label-bold'
= f.text_area :after_sign_up_text, class: 'form-control', rows: 4
.form-text.text-muted Markdown enabled
diff --git a/app/views/admin/application_settings/_spam.html.haml b/app/views/admin/application_settings/_spam.html.haml
index 8f0dce962a9..691b56e8a8e 100644
--- a/app/views/admin/application_settings/_spam.html.haml
+++ b/app/views/admin/application_settings/_spam.html.haml
@@ -10,14 +10,14 @@
%span.form-text.text-muted#recaptcha_help_block Helps prevent bots from creating accounts
.form-group
- = f.label :recaptcha_site_key, 'reCAPTCHA Site Key', class: 'label-light'
+ = f.label :recaptcha_site_key, 'reCAPTCHA Site Key', class: 'label-bold'
= f.text_field :recaptcha_site_key, class: 'form-control'
.form-text.text-muted
Generate site and private keys at
%a{ href: 'http://www.google.com/recaptcha', target: 'blank' } http://www.google.com/recaptcha
.form-group
- = f.label :recaptcha_private_key, 'reCAPTCHA Private Key', class: 'label-light'
+ = f.label :recaptcha_private_key, 'reCAPTCHA Private Key', class: 'label-bold'
= f.text_field :recaptcha_private_key, class: 'form-control'
.form-group
@@ -28,7 +28,7 @@
%span.form-text.text-muted#akismet_help_block Helps prevent bots from creating issues
.form-group
- = f.label :akismet_api_key, 'Akismet API Key', class: 'label-light'
+ = f.label :akismet_api_key, 'Akismet API Key', class: 'label-bold'
= f.text_field :akismet_api_key, class: 'form-control'
.form-text.text-muted
Generate API key at
@@ -43,13 +43,13 @@
Helps prevent malicious users hide their activity
.form-group
- = f.label :unique_ips_limit_per_user, 'IPs per user', class: 'label-light'
+ = f.label :unique_ips_limit_per_user, 'IPs per user', class: 'label-bold'
= f.number_field :unique_ips_limit_per_user, class: 'form-control'
.form-text.text-muted
Maximum number of unique IPs per user
.form-group
- = f.label :unique_ips_limit_time_window, 'IP expiration time', class: 'label-light'
+ = f.label :unique_ips_limit_time_window, 'IP expiration time', class: 'label-bold'
= f.number_field :unique_ips_limit_time_window, class: 'form-control'
.form-text.text-muted
How many seconds an IP will be counted towards the limit
diff --git a/app/views/admin/application_settings/_terminal.html.haml b/app/views/admin/application_settings/_terminal.html.haml
index 543628ff0ee..dc88a9885c8 100644
--- a/app/views/admin/application_settings/_terminal.html.haml
+++ b/app/views/admin/application_settings/_terminal.html.haml
@@ -3,7 +3,7 @@
%fieldset
.form-group
- = f.label :terminal_max_session_time, 'Max session time', class: 'label-light'
+ = f.label :terminal_max_session_time, 'Max session time', class: 'label-bold'
= f.number_field :terminal_max_session_time, class: 'form-control'
.form-text.text-muted
Maximum time for web terminal websocket connection (in seconds).
diff --git a/app/views/admin/application_settings/_visibility_and_access.html.haml b/app/views/admin/application_settings/_visibility_and_access.html.haml
index 4cc3e6a7d03..cec65f70e9d 100644
--- a/app/views/admin/application_settings/_visibility_and_access.html.haml
+++ b/app/views/admin/application_settings/_visibility_and_access.html.haml
@@ -3,19 +3,19 @@
%fieldset
.form-group
- = f.label :default_branch_protection, class: 'label-light'
+ = f.label :default_branch_protection, class: 'label-bold'
= f.select :default_branch_protection, options_for_select(Gitlab::Access.protection_options, @application_setting.default_branch_protection), {}, class: 'form-control'
.form-group.visibility-level-setting
- = f.label :default_project_visibility, class: 'label-light'
+ = f.label :default_project_visibility, class: 'label-bold'
= render('shared/visibility_radios', model_method: :default_project_visibility, form: f, selected_level: @application_setting.default_project_visibility, form_model: Project.new)
.form-group.visibility-level-setting
- = f.label :default_snippet_visibility, class: 'label-light'
+ = f.label :default_snippet_visibility, class: 'label-bold'
= render('shared/visibility_radios', model_method: :default_snippet_visibility, form: f, selected_level: @application_setting.default_snippet_visibility, form_model: ProjectSnippet.new)
.form-group.visibility-level-setting
- = f.label :default_group_visibility, class: 'label-light'
+ = f.label :default_group_visibility, class: 'label-bold'
= render('shared/visibility_radios', model_method: :default_group_visibility, form: f, selected_level: @application_setting.default_group_visibility, form_model: Group.new)
.form-group
- = f.label :restricted_visibility_levels, class: 'label-light'
+ = f.label :restricted_visibility_levels, class: 'label-bold'
- checkbox_name = 'application_setting[restricted_visibility_levels][]'
= hidden_field_tag(checkbox_name)
- restricted_level_checkboxes('restricted-visibility-help', checkbox_name, class: 'form-check-input').each do |level|
@@ -25,7 +25,7 @@
Selected levels cannot be used by non-admin users for groups, projects or snippets.
If the public level is restricted, user profiles are only visible to logged in users.
.form-group
- = f.label :import_sources, class: 'label-light'
+ = f.label :import_sources, class: 'label-bold'
= hidden_field_tag 'application_setting[import_sources][]'
- import_sources_checkboxes('import-sources-help', class: 'form-check-input').each do |source|
.form-check= source
@@ -44,7 +44,7 @@
Project export enabled
.form-group
- %label.label-light Enabled Git access protocols
+ %label.label-bold Enabled Git access protocols
= select(:application_setting, :enabled_git_access_protocol, [['Both SSH and HTTP(S)', nil], ['Only SSH', 'ssh'], ['Only HTTP(S)', 'http']], {}, class: 'form-control')
%span.form-text.text-muted#clone-protocol-help
Allow only the selected protocols to be used for Git access.
@@ -52,7 +52,7 @@
- ApplicationSetting::SUPPORTED_KEY_TYPES.each do |type|
- field_name = :"#{type}_key_restriction"
.form-group
- = f.label field_name, "#{type.upcase} SSH keys", class: 'label-light'
+ = f.label field_name, "#{type.upcase} SSH keys", class: 'label-bold'
= f.select field_name, key_restriction_options_for_select(type), {}, class: 'form-control'
= f.submit 'Save changes', class: "btn btn-success"
diff --git a/app/views/admin/dashboard/index.html.haml b/app/views/admin/dashboard/index.html.haml
index 18f2c1a509f..fac61f9d249 100644
--- a/app/views/admin/dashboard/index.html.haml
+++ b/app/views/admin/dashboard/index.html.haml
@@ -91,10 +91,10 @@
%span.light.float-right
= boolean_to_icon gravatar_enabled?
- omniauth = "OmniAuth"
- %p{ "aria-label" => "#{omniauth}: status " + (Gitlab.config.omniauth.enabled ? "on" : "off") }
+ %p{ "aria-label" => "#{omniauth}: status " + (Gitlab::Auth.omniauth_enabled? ? "on" : "off") }
= omniauth
%span.light.float-right
- = boolean_to_icon Gitlab.config.omniauth.enabled
+ = boolean_to_icon Gitlab::Auth.omniauth_enabled?
- reply_email = "Reply by email"
%p{ "aria-label" => "#{reply_email}: status " + (Gitlab::IncomingEmail.enabled? ? "on" : "off") }
= reply_email
diff --git a/app/views/admin/hooks/_form.html.haml b/app/views/admin/hooks/_form.html.haml
index 3abde755f0f..072f80b56b9 100644
--- a/app/views/admin/hooks/_form.html.haml
+++ b/app/views/admin/hooks/_form.html.haml
@@ -1,15 +1,15 @@
= form_errors(hook)
.form-group
- = form.label :url, 'URL', class: 'label-light'
+ = form.label :url, 'URL', class: 'label-bold'
= form.text_field :url, class: 'form-control'
.form-group
- = form.label :token, 'Secret Token', class: 'label-light'
+ = form.label :token, 'Secret Token', class: 'label-bold'
= form.text_field :token, class: 'form-control'
%p.form-text.text-muted
Use this token to validate received payloads
.form-group
- = form.label :url, 'Trigger', class: 'label-light'
+ = form.label :url, 'Trigger', class: 'label-bold'
%ul.list-unstyled
%li
.form-text.text-muted
@@ -45,7 +45,7 @@
%p.light
This URL will be triggered when a merge request is created/updated/merged
.form-group
- = form.label :enable_ssl_verification, 'SSL verification', class: 'label-light checkbox'
+ = form.label :enable_ssl_verification, 'SSL verification', class: 'label-bold checkbox'
.form-check
= form.check_box :enable_ssl_verification, class: 'form-check-input'
= form.label :enable_ssl_verification, class: 'form-check-label' do
diff --git a/app/views/admin/runners/show.html.haml b/app/views/admin/runners/show.html.haml
index 62b7a4cbd07..62be38e9dd2 100644
--- a/app/views/admin/runners/show.html.haml
+++ b/app/views/admin/runners/show.html.haml
@@ -11,7 +11,6 @@
- add_to_breadcrumbs _("Runners"), admin_runners_path
- breadcrumb_title "##{@runner.id}"
-- @no_container = true
- if @runner.instance_type?
.bs-callout.bs-callout-success
diff --git a/app/views/doorkeeper/applications/_form.html.haml b/app/views/doorkeeper/applications/_form.html.haml
index 1ddd0df54cd..0bc057a8864 100644
--- a/app/views/doorkeeper/applications/_form.html.haml
+++ b/app/views/doorkeeper/applications/_form.html.haml
@@ -2,11 +2,11 @@
= form_errors(application)
.form-group
- = f.label :name, class: 'label-light'
+ = f.label :name, class: 'label-bold'
= f.text_field :name, class: 'form-control', required: true
.form-group
- = f.label :redirect_uri, class: 'label-light'
+ = f.label :redirect_uri, class: 'label-bold'
= f.text_area :redirect_uri, class: 'form-control', required: true
%span.form-text.text-muted
@@ -16,7 +16,7 @@
= _('Use <code>%{native_redirect_uri}</code> for local tests').html_safe % { native_redirect_uri: Doorkeeper.configuration.native_redirect_uri }
.form-group
- = f.label :scopes, class: 'label-light'
+ = f.label :scopes, class: 'label-bold'
= render 'shared/tokens/scopes_form', prefix: 'doorkeeper_application', token: application, scopes: @scopes
.prepend-top-default
diff --git a/app/views/groups/settings/_general.html.haml b/app/views/groups/settings/_general.html.haml
index 64786d24266..ab8263533be 100644
--- a/app/views/groups/settings/_general.html.haml
+++ b/app/views/groups/settings/_general.html.haml
@@ -4,17 +4,17 @@
%fieldset
.row
.form-group.col-md-9
- = f.label :name, class: 'label-light' do
+ = f.label :name, class: 'label-bold' do
Group name
= f.text_field :name, class: 'form-control'
.form-group.col-md-3
- = f.label :id, class: 'label-light' do
+ = f.label :id, class: 'label-bold' do
Group ID
= f.text_field :id, class: 'form-control', readonly: true
.form-group
- = f.label :description, class: 'label-light' do
+ = f.label :description, class: 'label-bold' do
Group description
%span.light (optional)
= f.text_area :description, class: 'form-control', rows: 3, maxlength: 250
diff --git a/app/views/import/gitlab_projects/new.html.haml b/app/views/import/gitlab_projects/new.html.haml
index a258fc64b1e..4225ee19217 100644
--- a/app/views/import/gitlab_projects/new.html.haml
+++ b/app/views/import/gitlab_projects/new.html.haml
@@ -9,7 +9,7 @@
= form_tag import_gitlab_project_path, class: 'new_project', multipart: true do
.row
.form-group.col-12.col-sm-6
- = label_tag :namespace_id, 'Project path', class: 'label-light'
+ = label_tag :namespace_id, 'Project path', class: 'label-bold'
.form-group
.input-group
- if current_user.can_select_namespace?
@@ -24,7 +24,7 @@
#{user_url(current_user.username)}/
= hidden_field_tag :namespace_id, value: current_user.namespace_id
.form-group.col-12.col-sm-6.project-path
- = label_tag :path, _('Project name'), class: 'label-light'
+ = label_tag :path, _('Project name'), class: 'label-bold'
= text_field_tag :path, @path, placeholder: "my-awesome-project", class: "js-path-name form-control", tabindex: 2, autofocus: true, required: true
.row
@@ -33,7 +33,7 @@
.row
.form-group.col-sm-12
= hidden_field_tag :namespace_id, @namespace.id
- = label_tag :file, _('GitLab project export'), class: 'label-light'
+ = label_tag :file, _('GitLab project export'), class: 'label-bold'
.form-group
= file_field_tag :file, class: ''
.row
diff --git a/app/views/import/manifest/_form.html.haml b/app/views/import/manifest/_form.html.haml
index 763beb5958f..78c7fadb019 100644
--- a/app/views/import/manifest/_form.html.haml
+++ b/app/views/import/manifest/_form.html.haml
@@ -1,6 +1,6 @@
= form_tag upload_import_manifest_path, multipart: true do
.form-group
- = label_tag :group_id, nil, class: 'label-light' do
+ = label_tag :group_id, nil, class: 'label-bold' do
= _('Group')
.input-group
.input-group-prepend.has-tooltip{ title: root_url }
@@ -11,7 +11,7 @@
= _('Choose the top-level group for your repository imports.')
.form-group
- = label_tag :manifest, class: 'label-light' do
+ = label_tag :manifest, class: 'label-bold' do
= _('Manifest')
= file_field_tag :manifest, class: 'form-control-file', required: true
.form-text.text-muted
diff --git a/app/views/profiles/accounts/show.html.haml b/app/views/profiles/accounts/show.html.haml
index 9c95b6281ba..2220b4eee96 100644
--- a/app/views/profiles/accounts/show.html.haml
+++ b/app/views/profiles/accounts/show.html.haml
@@ -29,7 +29,7 @@
%p
Activate signin with one of the following services
.col-lg-8
- %label.label-light
+ %label.label-bold
Connected Accounts
%p Click on icon to activate signin with one of the following services
- button_based_providers.each do |provider|
diff --git a/app/views/profiles/emails/index.html.haml b/app/views/profiles/emails/index.html.haml
index a5db9dbe7f8..04a19ab14dd 100644
--- a/app/views/profiles/emails/index.html.haml
+++ b/app/views/profiles/emails/index.html.haml
@@ -12,7 +12,7 @@
Add email address
= form_for 'email', url: profile_emails_path do |f|
.form-group
- = f.label :email, class: 'label-light'
+ = f.label :email, class: 'label-bold'
= f.text_field :email, class: 'form-control'
.prepend-top-default
= f.submit 'Add email address', class: 'btn btn-create'
diff --git a/app/views/profiles/gpg_keys/_form.html.haml b/app/views/profiles/gpg_keys/_form.html.haml
index 3fcf563d970..aa9b0aad034 100644
--- a/app/views/profiles/gpg_keys/_form.html.haml
+++ b/app/views/profiles/gpg_keys/_form.html.haml
@@ -3,7 +3,7 @@
= form_errors(@gpg_key)
.form-group
- = f.label :key, class: 'label-light'
+ = f.label :key, class: 'label-bold'
= f.text_area :key, class: "form-control", rows: 8, required: true, placeholder: "Don't paste the private part of the GPG key. Paste the public part which begins with '-----BEGIN PGP PUBLIC KEY BLOCK-----'."
.prepend-top-default
diff --git a/app/views/profiles/keys/_form.html.haml b/app/views/profiles/keys/_form.html.haml
index 43a2d53b84d..5207921d6fe 100644
--- a/app/views/profiles/keys/_form.html.haml
+++ b/app/views/profiles/keys/_form.html.haml
@@ -3,11 +3,11 @@
= form_errors(@key)
.form-group
- = f.label :key, class: 'label-light'
+ = f.label :key, class: 'label-bold'
%p= _("Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key.")
= f.text_area :key, class: "form-control js-add-ssh-key-validation-input", rows: 8, required: true, placeholder: s_('Profiles|Typically starts with "ssh-rsa …"')
.form-group
- = f.label :title, class: 'label-light'
+ = f.label :title, class: 'label-bold'
= f.text_field :title, class: "form-control input-lg", required: true, placeholder: s_('Profiles|e.g. My MacBook key')
%p.form-text.text-muted= _('Name your individual key via a title')
diff --git a/app/views/profiles/notifications/show.html.haml b/app/views/profiles/notifications/show.html.haml
index 71ea625e5d5..712eb2a4573 100644
--- a/app/views/profiles/notifications/show.html.haml
+++ b/app/views/profiles/notifications/show.html.haml
@@ -23,10 +23,10 @@
= form_for @user, url: profile_notifications_path, method: :put, html: { class: 'update-notifications prepend-top-default' } do |f|
.form-group
- = f.label :notification_email, class: "label-light"
+ = f.label :notification_email, class: "label-bold"
= f.select :notification_email, @user.all_emails, { include_blank: false }, class: "select2"
- = label_tag :global_notification_level, "Global notification level", class: "label-light"
+ = label_tag :global_notification_level, "Global notification level", class: "label-bold"
%br
.clearfix
.form-group.float-left.global-notification-setting
diff --git a/app/views/profiles/passwords/edit.html.haml b/app/views/profiles/passwords/edit.html.haml
index 8a51a30191a..9c8cc9c059b 100644
--- a/app/views/profiles/passwords/edit.html.haml
+++ b/app/views/profiles/passwords/edit.html.haml
@@ -18,15 +18,15 @@
- unless @user.password_automatically_set?
.form-group
- = f.label :current_password, class: 'label-light'
+ = f.label :current_password, class: 'label-bold'
= f.password_field :current_password, required: true, class: 'form-control'
%p.form-text.text-muted
You must provide your current password in order to change it.
.form-group
- = f.label :password, 'New password', class: 'label-light'
+ = f.label :password, 'New password', class: 'label-bold'
= f.password_field :password, required: true, class: 'form-control'
.form-group
- = f.label :password_confirmation, class: 'label-light'
+ = f.label :password_confirmation, class: 'label-bold'
= f.password_field :password_confirmation, required: true, class: 'form-control'
.prepend-top-default.append-bottom-default
= f.submit 'Save password', class: "btn btn-create append-right-10"
diff --git a/app/views/profiles/personal_access_tokens/index.html.haml b/app/views/profiles/personal_access_tokens/index.html.haml
index d111113c646..c10d4ea1a4d 100644
--- a/app/views/profiles/personal_access_tokens/index.html.haml
+++ b/app/views/profiles/personal_access_tokens/index.html.haml
@@ -40,7 +40,7 @@
%p
It cannot be used to access any other data.
.col-lg-8.feed-token-reset
- = label_tag :feed_token, 'Feed token', class: "label-light"
+ = label_tag :feed_token, 'Feed token', class: "label-bold"
= text_field_tag :feed_token, current_user.feed_token, class: 'form-control', readonly: true, onclick: 'this.select()'
%p.form-text.text-muted
Keep this token secret. Anyone who gets ahold of it can read activity and issue RSS feeds or your calendar feed as if they were you.
@@ -59,7 +59,7 @@
%p
It cannot be used to access any other data.
.col-lg-8.incoming-email-token-reset
- = label_tag :incoming_email_token, 'Incoming email token', class: "label-light"
+ = label_tag :incoming_email_token, 'Incoming email token', class: "label-bold"
= text_field_tag :incoming_email_token, current_user.incoming_email_token, class: 'form-control', readonly: true, onclick: 'this.select()'
%p.form-text.text-muted
Keep this token secret. Anyone who gets ahold of it can create issues as if they were you.
diff --git a/app/views/profiles/preferences/show.html.haml b/app/views/profiles/preferences/show.html.haml
index 8f1078bd41d..fd6dd74e1c5 100644
--- a/app/views/profiles/preferences/show.html.haml
+++ b/app/views/profiles/preferences/show.html.haml
@@ -42,17 +42,17 @@
= link_to 'Learn more', help_page_path('user/profile/preferences', anchor: 'behavior'), target: '_blank'
.col-lg-8
.form-group
- = f.label :layout, class: 'label-light' do
+ = f.label :layout, class: 'label-bold' do
Layout width
= f.select :layout, layout_choices, {}, class: 'form-control'
.form-text.text-muted
Choose between fixed (max. 1200px) and fluid (100%) application layout.
.form-group
- = f.label :dashboard, class: 'label-light' do
+ = f.label :dashboard, class: 'label-bold' do
Default dashboard
= f.select :dashboard, dashboard_choices, {}, class: 'form-control'
.form-group
- = f.label :project_view, class: 'label-light' do
+ = f.label :project_view, class: 'label-bold' do
Project overview content
= f.select :project_view, project_view_choices, {}, class: 'form-control'
.form-text.text-muted
diff --git a/app/views/profiles/two_factor_auths/show.html.haml b/app/views/profiles/two_factor_auths/show.html.haml
index e35ebdea435..cd10b8758f6 100644
--- a/app/views/profiles/two_factor_auths/show.html.haml
+++ b/app/views/profiles/two_factor_auths/show.html.haml
@@ -13,10 +13,16 @@
- if current_user.two_factor_otp_enabled?
%p
You've already enabled two-factor authentication using mobile authenticator applications. In order to register a different device, you must first disable two-factor authentication.
+ %p
+ If you lose your recovery codes you can generate new ones, invalidating all previous codes.
+ %div
= link_to 'Disable two-factor authentication', profile_two_factor_auth_path,
method: :delete,
data: { confirm: "Are you sure? This will invalidate your registered applications and U2F devices." },
- class: 'btn btn-danger'
+ class: 'btn btn-danger append-right-10'
+ = form_tag codes_profile_two_factor_auth_path, {style: 'display: inline-block', method: :post} do |f|
+ = submit_tag 'Regenerate recovery codes', class: 'btn'
+
- else
%p
Download the Google Authenticator application from App Store or Google Play Store and scan this code.
@@ -43,7 +49,7 @@
.alert.alert-danger
= @error
.form-group
- = label_tag :pin_code, nil, class: "label-light"
+ = label_tag :pin_code, nil, class: "label-bold"
= text_field_tag :pin_code, nil, class: "form-control", required: true
.prepend-top-default
= submit_tag 'Register with two-factor app', class: 'btn btn-success'
diff --git a/app/views/projects/_merge_request_merge_method_settings.html.haml b/app/views/projects/_merge_request_merge_method_settings.html.haml
index 3bb220ac6d0..540e996e4d8 100644
--- a/app/views/projects/_merge_request_merge_method_settings.html.haml
+++ b/app/views/projects/_merge_request_merge_method_settings.html.haml
@@ -2,7 +2,7 @@
- project = local_assigns.fetch(:project)
.form-group
- = label_tag :merge_method_merge, class: 'label-light' do
+ = label_tag :merge_method_merge, class: 'label-bold' do
Merge method
.form-check
= form.radio_button :merge_method, :merge, class: "js-merge-method-radio form-check-input"
diff --git a/app/views/projects/_new_project_fields.html.haml b/app/views/projects/_new_project_fields.html.haml
index f4994f5459b..c78baa5dfe4 100644
--- a/app/views/projects/_new_project_fields.html.haml
+++ b/app/views/projects/_new_project_fields.html.haml
@@ -4,7 +4,7 @@
.row{ id: project_name_id }
= f.hidden_field :ci_cd_only, value: ci_cd_only
.form-group.project-path.col-sm-6
- = f.label :namespace_id, class: 'label-light' do
+ = f.label :namespace_id, class: 'label-bold' do
%span
Project path
.input-group
@@ -20,7 +20,7 @@
#{user_url(current_user.username)}/
= f.hidden_field :namespace_id, value: current_user.namespace_id
.form-group.project-path.col-sm-6
- = f.label :path, class: 'label-light' do
+ = f.label :path, class: 'label-bold' do
%span
Project name
= f.text_field :path, placeholder: "my-awesome-project", class: "form-control", tabindex: 2, autofocus: true, required: true
@@ -30,12 +30,12 @@
= link_to "Create a group", new_group_path
.form-group
- = f.label :description, class: 'label-light' do
+ = f.label :description, class: 'label-bold' do
Project description
%span (optional)
= f.text_area :description, placeholder: 'Description format', class: "form-control", rows: 3, maxlength: 250
-= f.label :visibility_level, class: 'label-light' do
+= f.label :visibility_level, class: 'label-bold' do
Visibility Level
= link_to icon('question-circle'), help_page_path("public_access/public_access"), aria: { label: 'Documentation for Visibility Level' }, target: '_blank', rel: 'noopener noreferrer'
= render 'shared/visibility_level', f: f, visibility_level: visibility_level.to_i, can_change_visibility_level: true, form_model: @project, with_label: false
diff --git a/app/views/projects/_project_templates.html.haml b/app/views/projects/_project_templates.html.haml
index d08807b5135..9d8627c9eb1 100644
--- a/app/views/projects/_project_templates.html.haml
+++ b/app/views/projects/_project_templates.html.haml
@@ -12,7 +12,7 @@
.project-fields-form
.row
.form-group.col-sm-12
- %label.label-light
+ %label.label-bold
Template
.input-group.template-input-group
.input-group-prepend
diff --git a/app/views/projects/artifacts/file.html.haml b/app/views/projects/artifacts/file.html.haml
index aac7a1870df..f7174d6b2c6 100644
--- a/app/views/projects/artifacts/file.html.haml
+++ b/app/views/projects/artifacts/file.html.haml
@@ -27,6 +27,6 @@
.btn-group{ role: "group" }<
= copy_blob_source_button(blob)
- = open_raw_blob_button(blob)
+ = download_blob_button(blob)
= render 'projects/blob/content', blob: blob
diff --git a/app/views/projects/blame/show.html.haml b/app/views/projects/blame/show.html.haml
index e90916e340d..ef6f5c76de6 100644
--- a/app/views/projects/blame/show.html.haml
+++ b/app/views/projects/blame/show.html.haml
@@ -18,7 +18,7 @@
- commit = blame_group[:commit]
%td.blame-commit{ class: age_map_class(commit.committed_date, project_duration) }
.commit
- = author_avatar(commit, size: 36)
+ = author_avatar(commit, size: 36, has_tooltip: false)
.commit-row-title
%span.item-title.str-truncated-100
= link_to_markdown commit.title, project_commit_path(@project, commit.id), class: "cdark", title: commit.title
diff --git a/app/views/projects/blob/_header.html.haml b/app/views/projects/blob/_header.html.haml
index 0a0b3ce1d6f..84ccd816d80 100644
--- a/app/views/projects/blob/_header.html.haml
+++ b/app/views/projects/blob/_header.html.haml
@@ -8,8 +8,8 @@
.btn-group{ role: "group" }<
= copy_blob_source_button(blob) unless blame
= open_raw_blob_button(blob)
+ = download_blob_button(blob)
= view_on_environment_button(@commit.sha, @path, @environment) if @environment
-
.btn-group{ role: "group" }<
= render_if_exists 'projects/blob/header_file_locks_link'
= edit_blob_button
diff --git a/app/views/projects/blob/show.html.haml b/app/views/projects/blob/show.html.haml
index efb8175398b..5edab38bd64 100644
--- a/app/views/projects/blob/show.html.haml
+++ b/app/views/projects/blob/show.html.haml
@@ -3,6 +3,8 @@
- page_title @blob.path, @ref
+.js-signature-container{ data: { 'signatures-path': namespace_project_signatures_path } }
+
%div{ class: container_class }
= render 'projects/last_push'
diff --git a/app/views/projects/buttons/_star.html.haml b/app/views/projects/buttons/_star.html.haml
index d8b4266143e..a2dc2730ecc 100644
--- a/app/views/projects/buttons/_star.html.haml
+++ b/app/views/projects/buttons/_star.html.haml
@@ -1,5 +1,5 @@
- if current_user
- %button.btn.btn-default.star-btn.toggle-star{ type: "button", data: { endpoint: toggle_star_project_path(@project, :json) } }
+ %button.btn.btn-default.star-btn.toggle-star{ type: "button", data: { endpoint: toggle_star_project_path(@project, :json) } }>
- if current_user.starred?(@project)
= sprite_icon('star')
%span.starred= _('Unstar')
diff --git a/app/views/projects/clusters/gcp/_form.html.haml b/app/views/projects/clusters/gcp/_form.html.haml
index 0a2e320556d..9133de6559d 100644
--- a/app/views/projects/clusters/gcp/_form.html.haml
+++ b/app/views/projects/clusters/gcp/_form.html.haml
@@ -15,15 +15,15 @@
= form_for @gcp_cluster, html: { class: 'js-gke-cluster-creation prepend-top-20', data: { token: token_in_session } }, url: create_gcp_namespace_project_clusters_path(@project.namespace, @project), as: :cluster do |field|
= form_errors(@gcp_cluster)
.form-group
- = field.label :name, s_('ClusterIntegration|Kubernetes cluster name'), class: 'label-light'
+ = field.label :name, s_('ClusterIntegration|Kubernetes cluster name'), class: 'label-bold'
= field.text_field :name, class: 'form-control', placeholder: s_('ClusterIntegration|Kubernetes cluster name')
.form-group
- = field.label :environment_scope, s_('ClusterIntegration|Environment scope'), class: 'label-light'
+ = field.label :environment_scope, s_('ClusterIntegration|Environment scope'), class: 'label-bold'
= field.text_field :environment_scope, class: 'form-control', readonly: !has_multiple_clusters?(@project), placeholder: s_('ClusterIntegration|Environment scope')
= field.fields_for :provider_gcp, @gcp_cluster.provider_gcp do |provider_gcp_field|
.form-group
- = provider_gcp_field.label :gcp_project_id, s_('ClusterIntegration|Google Cloud Platform project'), class: 'label-light'
+ = provider_gcp_field.label :gcp_project_id, s_('ClusterIntegration|Google Cloud Platform project'), class: 'label-bold'
.js-gcp-project-id-dropdown-entry-point{ data: { docsUrl: 'https://console.cloud.google.com/home/dashboard' } }
= provider_gcp_field.hidden_field :gcp_project_id
.dropdown
@@ -34,7 +34,7 @@
%span.form-text.text-muted &nbsp;
.form-group
- = provider_gcp_field.label :zone, s_('ClusterIntegration|Zone'), class: 'label-light'
+ = provider_gcp_field.label :zone, s_('ClusterIntegration|Zone'), class: 'label-bold'
.js-gcp-zone-dropdown-entry-point
= provider_gcp_field.hidden_field :zone
.dropdown
@@ -46,11 +46,11 @@
= s_('ClusterIntegration|Learn more about %{help_link_start}zones%{help_link_end}.').html_safe % { help_link_start: help_link_start % { url: zones_link_url }, help_link_end: help_link_end }
.form-group
- = provider_gcp_field.label :num_nodes, s_('ClusterIntegration|Number of nodes'), class: 'label-light'
+ = provider_gcp_field.label :num_nodes, s_('ClusterIntegration|Number of nodes'), class: 'label-bold'
= provider_gcp_field.text_field :num_nodes, class: 'form-control', placeholder: '3'
.form-group
- = provider_gcp_field.label :machine_type, s_('ClusterIntegration|Machine type'), class: 'label-light'
+ = provider_gcp_field.label :machine_type, s_('ClusterIntegration|Machine type'), class: 'label-bold'
.js-gcp-machine-type-dropdown-entry-point
= provider_gcp_field.hidden_field :machine_type
.dropdown
diff --git a/app/views/projects/clusters/user/_form.html.haml b/app/views/projects/clusters/user/_form.html.haml
index 3006bb5073e..e8ef0008802 100644
--- a/app/views/projects/clusters/user/_form.html.haml
+++ b/app/views/projects/clusters/user/_form.html.haml
@@ -1,28 +1,28 @@
= form_for @user_cluster, url: create_user_namespace_project_clusters_path(@project.namespace, @project), as: :cluster do |field|
= form_errors(@user_cluster)
.form-group
- = field.label :name, s_('ClusterIntegration|Kubernetes cluster name'), class: 'label-light'
+ = field.label :name, s_('ClusterIntegration|Kubernetes cluster name'), class: 'label-bold'
= field.text_field :name, class: 'form-control', placeholder: s_('ClusterIntegration|Kubernetes cluster name')
- if has_multiple_clusters?(@project)
.form-group
- = field.label :environment_scope, s_('ClusterIntegration|Environment scope'), class: 'label-light'
+ = field.label :environment_scope, s_('ClusterIntegration|Environment scope'), class: 'label-bold'
= field.text_field :environment_scope, class: 'form-control', placeholder: s_('ClusterIntegration|Environment scope')
= field.fields_for :platform_kubernetes, @user_cluster.platform_kubernetes do |platform_kubernetes_field|
.form-group
- = platform_kubernetes_field.label :api_url, s_('ClusterIntegration|API URL'), class: 'label-light'
+ = platform_kubernetes_field.label :api_url, s_('ClusterIntegration|API URL'), class: 'label-bold'
= platform_kubernetes_field.text_field :api_url, class: 'form-control', placeholder: s_('ClusterIntegration|API URL')
.form-group
- = platform_kubernetes_field.label :ca_cert, s_('ClusterIntegration|CA Certificate'), class: 'label-light'
+ = platform_kubernetes_field.label :ca_cert, s_('ClusterIntegration|CA Certificate'), class: 'label-bold'
= platform_kubernetes_field.text_area :ca_cert, class: 'form-control', placeholder: s_('ClusterIntegration|Certificate Authority bundle (PEM format)')
.form-group
- = platform_kubernetes_field.label :token, s_('ClusterIntegration|Token'), class: 'label-light'
+ = platform_kubernetes_field.label :token, s_('ClusterIntegration|Token'), class: 'label-bold'
= platform_kubernetes_field.text_field :token, class: 'form-control', placeholder: s_('ClusterIntegration|Service token'), autocomplete: 'off'
.form-group
- = platform_kubernetes_field.label :namespace, s_('ClusterIntegration|Project namespace (optional, unique)'), class: 'label-light'
+ = platform_kubernetes_field.label :namespace, s_('ClusterIntegration|Project namespace (optional, unique)'), class: 'label-bold'
= platform_kubernetes_field.text_field :namespace, class: 'form-control', placeholder: s_('ClusterIntegration|Project namespace')
.form-group
diff --git a/app/views/projects/clusters/user/_show.html.haml b/app/views/projects/clusters/user/_show.html.haml
index 4d117f435dc..20a07d6695e 100644
--- a/app/views/projects/clusters/user/_show.html.haml
+++ b/app/views/projects/clusters/user/_show.html.haml
@@ -1,20 +1,20 @@
= form_for @cluster, url: namespace_project_cluster_path(@project.namespace, @project, @cluster), as: :cluster do |field|
= form_errors(@cluster)
.form-group
- = field.label :name, s_('ClusterIntegration|Kubernetes cluster name'), class: 'label-light'
+ = field.label :name, s_('ClusterIntegration|Kubernetes cluster name'), class: 'label-bold'
= field.text_field :name, class: 'form-control', placeholder: s_('ClusterIntegration|Kubernetes cluster name')
= field.fields_for :platform_kubernetes, @cluster.platform_kubernetes do |platform_kubernetes_field|
.form-group
- = platform_kubernetes_field.label :api_url, s_('ClusterIntegration|API URL'), class: 'label-light'
+ = platform_kubernetes_field.label :api_url, s_('ClusterIntegration|API URL'), class: 'label-bold'
= platform_kubernetes_field.text_field :api_url, class: 'form-control', placeholder: s_('ClusterIntegration|API URL')
.form-group
- = platform_kubernetes_field.label :ca_cert, s_('ClusterIntegration|CA Certificate'), class: 'label-light'
+ = platform_kubernetes_field.label :ca_cert, s_('ClusterIntegration|CA Certificate'), class: 'label-bold'
= platform_kubernetes_field.text_area :ca_cert, class: 'form-control', placeholder: s_('ClusterIntegration|Certificate Authority bundle (PEM format)')
.form-group
- = platform_kubernetes_field.label :token, s_('ClusterIntegration|Token'), class: 'label-light'
+ = platform_kubernetes_field.label :token, s_('ClusterIntegration|Token'), class: 'label-bold'
.input-group
= platform_kubernetes_field.text_field :token, class: 'form-control js-cluster-token', type: 'password', placeholder: s_('ClusterIntegration|Token'), autocomplete: 'off'
%span.input-group-append.clipboard-addon
@@ -23,7 +23,7 @@
= s_('ClusterIntegration|Show')
.form-group
- = platform_kubernetes_field.label :namespace, s_('ClusterIntegration|Project namespace (optional, unique)'), class: 'label-light'
+ = platform_kubernetes_field.label :namespace, s_('ClusterIntegration|Project namespace (optional, unique)'), class: 'label-bold'
= platform_kubernetes_field.text_field :namespace, class: 'form-control', placeholder: s_('ClusterIntegration|Project namespace')
.form-group
diff --git a/app/views/projects/commit/_change.html.haml b/app/views/projects/commit/_change.html.haml
index 14a7e84394a..afd70ef5774 100644
--- a/app/views/projects/commit/_change.html.haml
+++ b/app/views/projects/commit/_change.html.haml
@@ -23,7 +23,7 @@
%p= description
= form_tag [type.underscore, @project.namespace.becomes(Namespace), @project, commit], method: :post, remote: false, class: "js-#{type}-form js-requires-input" do
.form-group.branch
- = label_tag 'start_branch', branch_label, class: 'label-light'
+ = label_tag 'start_branch', branch_label, class: 'label-bold'
= hidden_field_tag :start_branch, @project.default_branch, id: 'start_branch'
= dropdown_tag(@project.default_branch, options: { title: s_("BranchSwitcherTitle|Switch branch"), filter: true, placeholder: s_("BranchSwitcherPlaceholder|Search branches"), toggle_class: 'js-project-refs-dropdown dynamic', dropdown_class: 'dropdown-menu-selectable', data: { field_name: "start_branch", selected: @project.default_branch, start_branch: @project.default_branch, refs_url: project_branches_path(@project), submit_form_on_click: false } })
diff --git a/app/views/projects/commit/_commit_box.html.haml b/app/views/projects/commit/_commit_box.html.haml
index 886dd73c33b..78522393d4b 100644
--- a/app/views/projects/commit/_commit_box.html.haml
+++ b/app/views/projects/commit/_commit_box.html.haml
@@ -10,7 +10,7 @@
%span.d-none.d-sm-inline authored
#{time_ago_with_tooltip(@commit.authored_date)}
%span= s_('ByAuthor|by')
- = author_avatar(@commit, size: 24)
+ = author_avatar(@commit, size: 24, has_tooltip: false)
%strong
= commit_author_link(@commit, avatar: true, size: 24)
- if @commit.different_committer?
diff --git a/app/views/projects/commits/_commit.html.haml b/app/views/projects/commits/_commit.html.haml
index 90e55fd0fb0..feaf44e8c0a 100644
--- a/app/views/projects/commits/_commit.html.haml
+++ b/app/views/projects/commits/_commit.html.haml
@@ -19,7 +19,7 @@
%li.commit.flex-row.js-toggle-container{ id: "commit-#{commit.short_id}" }
.avatar-cell.d-none.d-sm-block
- = author_avatar(commit, size: 36)
+ = author_avatar(commit, size: 36, has_tooltip: false)
.commit-detail.flex-list
.commit-content.qa-commit-content
diff --git a/app/views/projects/deploy_keys/_form.html.haml b/app/views/projects/deploy_keys/_form.html.haml
index 5ad8091a02b..f8ab0c1ec54 100644
--- a/app/views/projects/deploy_keys/_form.html.haml
+++ b/app/views/projects/deploy_keys/_form.html.haml
@@ -1,10 +1,10 @@
= form_for [@project.namespace.becomes(Namespace), @project, @deploy_keys.new_key], url: namespace_project_deploy_keys_path, html: { class: "js-requires-input container" } do |f|
= form_errors(@deploy_keys.new_key)
.form-group.row
- = f.label :title, class: "label-light"
+ = f.label :title, class: "label-bold"
= f.text_field :title, class: 'form-control', required: true
.form-group.row
- = f.label :key, class: "label-light"
+ = f.label :key, class: "label-bold"
= f.text_area :key, class: "form-control", rows: 5, required: true
.form-group.row
%p.light.append-bottom-0
diff --git a/app/views/projects/deploy_tokens/_form.html.haml b/app/views/projects/deploy_tokens/_form.html.haml
index 329b9e7e562..578a9e2f74d 100644
--- a/app/views/projects/deploy_tokens/_form.html.haml
+++ b/app/views/projects/deploy_tokens/_form.html.haml
@@ -5,24 +5,24 @@
= form_errors(token)
.form-group
- = f.label :name, class: 'label-light'
+ = f.label :name, class: 'label-bold'
= f.text_field :name, class: 'form-control', required: true
.form-group
- = f.label :expires_at, class: 'label-light'
+ = f.label :expires_at, class: 'label-bold'
= f.text_field :expires_at, class: 'datepicker form-control', value: f.object.expires_at
.form-group
- = f.label :scopes, class: 'label-light'
+ = f.label :scopes, class: 'label-bold'
%fieldset.form-group.form-check
= f.check_box :read_repository, class: 'form-check-input'
- = label_tag ("deploy_token_read_repository"), 'read_repository', class: 'label-light form-check-label'
+ = label_tag ("deploy_token_read_repository"), 'read_repository', class: 'label-bold form-check-label'
.text-secondary= s_('DeployTokens|Allows read-only access to the repository')
- if container_registry_enabled?(project)
%fieldset.form-group.form-check
= f.check_box :read_registry, class: 'form-check-input'
- = label_tag ("deploy_token_read_registry"), 'read_registry', class: 'label-light form-check-label'
+ = label_tag ("deploy_token_read_registry"), 'read_registry', class: 'label-bold form-check-label'
.text-secondary= s_('DeployTokens|Allows read-only access to the registry images')
.prepend-top-default
diff --git a/app/views/projects/edit.html.haml b/app/views/projects/edit.html.haml
index c2d900cbcf7..0ff88b82ae6 100644
--- a/app/views/projects/edit.html.haml
+++ b/app/views/projects/edit.html.haml
@@ -18,17 +18,17 @@
%fieldset
.row
.form-group.col-md-9
- = f.label :name, class: 'label-light', for: 'project_name_edit' do
+ = f.label :name, class: 'label-bold', for: 'project_name_edit' do
Project name
= f.text_field :name, class: "form-control", id: "project_name_edit"
.form-group.col-md-3
- = f.label :id, class: 'label-light' do
+ = f.label :id, class: 'label-bold' do
Project ID
= f.text_field :id, class: 'form-control', readonly: true
.form-group
- = f.label :description, class: 'label-light' do
+ = f.label :description, class: 'label-bold' do
Project description
%span.light (optional)
= f.text_area :description, class: "form-control", rows: 3, maxlength: 250
@@ -37,13 +37,13 @@
- unless @project.empty_repo?
.form-group
- = f.label :default_branch, "Default Branch", class: 'label-light'
+ = f.label :default_branch, "Default Branch", class: 'label-bold'
= f.select(:default_branch, @project.repository.branch_names, {}, {class: 'select2 select-wide'})
= render_if_exists 'shared/repository_size_limit_setting', form: f, type: :project
.form-group
- = f.label :tag_list, "Tags", class: 'label-light'
+ = f.label :tag_list, "Tags", class: 'label-bold'
= f.text_field :tag_list, value: @project.tag_list.sort.join(', '), maxlength: 2000, class: "form-control"
%p.form-text.text-muted Separate tags with commas.
%fieldset.features
@@ -144,12 +144,12 @@
= render 'projects/errors'
= form_for([@project.namespace.becomes(Namespace), @project]) do |f|
.form-group.project_name_holder
- = f.label :name, class: 'label-light' do
+ = f.label :name, class: 'label-bold' do
Project name
.form-group
= f.text_field :name, class: "form-control"
.form-group
- = f.label :path, class: 'label-light' do
+ = f.label :path, class: 'label-bold' do
%span Path
.form-group
.input-group
@@ -169,7 +169,7 @@
Transfer project
= form_for([@project.namespace.becomes(Namespace), @project], url: transfer_project_path(@project), method: :put, remote: true, html: { class: 'js-project-transfer-form' } ) do |f|
.form-group
- = label_tag :new_namespace_id, nil, class: 'label-light' do
+ = label_tag :new_namespace_id, nil, class: 'label-bold' do
%span Select a new namespace
.form-group
= select_tag :new_namespace_id, namespaces_options(nil), include_blank: true, class: 'select2'
diff --git a/app/views/projects/environments/_form.html.haml b/app/views/projects/environments/_form.html.haml
index 1605f3a3351..0586dbdf0e2 100644
--- a/app/views/projects/environments/_form.html.haml
+++ b/app/views/projects/environments/_form.html.haml
@@ -11,10 +11,10 @@
= form_errors(@environment)
.form-group
- = f.label :name, 'Name', class: 'label-light'
+ = 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-light'
+ = f.label :external_url, 'External URL', class: 'label-bold'
= f.url_field :external_url, class: 'form-control'
.form-actions
diff --git a/app/views/projects/merge_requests/conflicts/_submit_form.html.haml b/app/views/projects/merge_requests/conflicts/_submit_form.html.haml
index 4d84ee2488b..8181267184a 100644
--- a/app/views/projects/merge_requests/conflicts/_submit_form.html.haml
+++ b/app/views/projects/merge_requests/conflicts/_submit_form.html.haml
@@ -9,7 +9,7 @@
.resolve-info
= translation.html_safe
.col-md-8
- %label.label-light{ "for" => "commit-message" }
+ %label.label-bold{ "for" => "commit-message" }
#{ _('Commit message') }
.commit-message-container
.max-width-marker
diff --git a/app/views/projects/mirrors/_push.html.haml b/app/views/projects/mirrors/_push.html.haml
index 2b2871a81e5..08375e09816 100644
--- a/app/views/projects/mirrors/_push.html.haml
+++ b/app/views/projects/mirrors/_push.html.haml
@@ -32,11 +32,11 @@
.form-group
= rm_form.check_box :enabled, class: "float-left"
.prepend-left-20
- = rm_form.label :enabled, "Remote mirror repository", class: "label-light append-bottom-0"
+ = rm_form.label :enabled, "Remote mirror repository", class: "label-bold append-bottom-0"
%p.light.append-bottom-0
Automatically update the remote mirror's branches, tags, and commits from this repository every time someone pushes to it.
.form-group.has-feedback
- = rm_form.label :url, "Git repository URL", class: "label-light"
+ = rm_form.label :url, "Git repository URL", class: "label-bold"
= rm_form.text_field :url, class: "form-control", placeholder: 'https://username:password@gitlab.company.com/group/project.git'
= render "projects/mirrors/instructions"
@@ -44,7 +44,7 @@
.form-group
= rm_form.check_box :only_protected_branches, class: 'float-left'
.prepend-left-20
- = rm_form.label :only_protected_branches, class: 'label-light'
+ = rm_form.label :only_protected_branches, class: 'label-bold'
= link_to icon('question-circle'), help_page_path('user/project/protected_branches')
= f.submit 'Save changes', class: 'btn btn-create', name: 'update_remote_mirror'
diff --git a/app/views/projects/pipeline_schedules/_form.html.haml b/app/views/projects/pipeline_schedules/_form.html.haml
index 1cdf981fcb4..9a981d53ab6 100644
--- a/app/views/projects/pipeline_schedules/_form.html.haml
+++ b/app/views/projects/pipeline_schedules/_form.html.haml
@@ -2,25 +2,25 @@
= form_errors(@schedule)
.form-group.row
.col-md-9
- = f.label :description, _('Description'), class: 'label-light'
+ = f.label :description, _('Description'), class: 'label-bold'
= f.text_field :description, class: 'form-control', required: true, autofocus: true, placeholder: s_('PipelineSchedules|Provide a short description for this pipeline')
.form-group.row
.col-md-9
- = f.label :cron, _('Interval Pattern'), class: 'label-light'
+ = f.label :cron, _('Interval Pattern'), class: 'label-bold'
#interval-pattern-input{ data: { initial_interval: @schedule.cron } }
.form-group.row
.col-md-9
- = f.label :cron_timezone, _('Cron Timezone'), class: 'label-light'
+ = f.label :cron_timezone, _('Cron Timezone'), class: 'label-bold'
= dropdown_tag(_("Select a timezone"), options: { toggle_class: 'btn js-timezone-dropdown', title: _("Select a timezone"), filter: true, placeholder: s_("OfSearchInADropdown|Filter"), data: { data: timezone_data } } )
= f.text_field :cron_timezone, value: @schedule.cron_timezone, id: 'schedule_cron_timezone', class: 'hidden', name: 'schedule[cron_timezone]', required: true
.form-group.row
.col-md-9
- = f.label :ref, _('Target Branch'), class: 'label-light'
+ = f.label :ref, _('Target Branch'), class: 'label-bold'
= dropdown_tag(_("Select target branch"), options: { toggle_class: 'btn js-target-branch-dropdown', dropdown_class: 'git-revision-dropdown', title: _("Select target branch"), filter: true, placeholder: s_("OfSearchInADropdown|Filter"), data: { data: @project.repository.branch_names, default_branch: @project.default_branch } } )
= f.text_field :ref, value: @schedule.ref, id: 'schedule_ref', class: 'hidden', name: 'schedule[ref]', required: true
.form-group.row.js-ci-variable-list-section
.col-md-9
- %label.label-light
+ %label.label-bold
#{ s_('PipelineSchedules|Variables') }
%ul.ci-variable-list
- @schedule.variables.each do |variable|
@@ -34,7 +34,7 @@
= n_('Reveal value', 'Reveal values', @schedule.variables.size)
.form-group.row
.col-md-9
- = f.label :active, s_('PipelineSchedules|Activated'), class: 'label-light'
+ = f.label :active, s_('PipelineSchedules|Activated'), class: 'label-bold'
%div
= f.check_box :active, required: false, value: @schedule.active?
= _('Active')
diff --git a/app/views/projects/pipelines/_info.html.haml b/app/views/projects/pipelines/_info.html.haml
index 04131a90a57..bc247460d28 100644
--- a/app/views/projects/pipelines/_info.html.haml
+++ b/app/views/projects/pipelines/_info.html.haml
@@ -33,3 +33,5 @@
%span.js-details-content.hide
= link_to @pipeline.sha, project_commit_path(@project, @pipeline.sha), class: "commit-sha commit-hash-full"
= clipboard_button(text: @pipeline.sha, title: "Copy commit SHA to clipboard")
+
+ = render_if_exists "projects/pipelines/info_extension", pipeline: @pipeline
diff --git a/app/views/projects/pipelines/_with_tabs.html.haml b/app/views/projects/pipelines/_with_tabs.html.haml
index 951f80b378d..c63ff070f70 100644
--- a/app/views/projects/pipelines/_with_tabs.html.haml
+++ b/app/views/projects/pipelines/_with_tabs.html.haml
@@ -12,6 +12,7 @@
= link_to failures_project_pipeline_path(@project, @pipeline), data: { target: '#js-tab-failures', action: 'failures', toggle: 'tab' }, class: 'failures-tab' do
= _("Failed Jobs")
%span.badge.badge-pill.js-failures-counter= @pipeline.failed_builds.count
+ = render_if_exists "projects/pipelines/tabs_holder", pipeline: @pipeline, project: @project
.tab-content
#js-tab-pipeline.tab-pane
@@ -75,4 +76,4 @@
%pre.build-trace.build-trace-rounded
%code.bash.js-build-output
= build_summary(build)
-
+ = render_if_exists "projects/pipelines/tabs_content", pipeline: @pipeline, project: @project
diff --git a/app/views/projects/pipelines/new.html.haml b/app/views/projects/pipelines/new.html.haml
index 956f8fef6b8..c13e3194340 100644
--- a/app/views/projects/pipelines/new.html.haml
+++ b/app/views/projects/pipelines/new.html.haml
@@ -10,7 +10,7 @@
= form_errors(@pipeline)
.form-group.row
.col-sm-12
- = f.label :ref, s_('Pipeline|Create for')
+ = f.label :ref, s_('Pipeline|Create for'), class: 'col-form-label'
= hidden_field_tag 'pipeline[ref]', params[:ref] || @project.default_branch
= dropdown_tag(params[:ref] || @project.default_branch,
options: { toggle_class: 'js-branch-select wide git-revision-dropdown-toggle',
diff --git a/app/views/projects/project_members/_new_project_member.html.haml b/app/views/projects/project_members/_new_project_member.html.haml
index 5064db8d5cd..6272687be1c 100644
--- a/app/views/projects/project_members/_new_project_member.html.haml
+++ b/app/views/projects/project_members/_new_project_member.html.haml
@@ -2,10 +2,10 @@
.col-sm-12
= form_for @project_member, as: :project_member, url: project_project_members_path(@project), html: { class: 'users-project-form' } do |f|
.form-group
- = label_tag :user_ids, "Select members to invite", class: "label-light"
+ = label_tag :user_ids, "Select members to invite", class: "label-bold"
= users_select_tag(:user_ids, multiple: true, class: "input-clamp", scope: :all, email_user: true, placeholder: "Search for members to update or invite")
.form-group
- = label_tag :access_level, "Choose a role permission", class: "label-light"
+ = label_tag :access_level, "Choose a role permission", class: "label-bold"
.select-wrapper
= select_tag :access_level, options_for_select(ProjectMember.access_level_roles, @project_member.access_level), class: "form-control project-access-select select-control"
= icon('chevron-down')
@@ -14,7 +14,7 @@
about role permissions
.form-group
.clearable-input
- = label_tag :expires_at, 'Access expiration date', class: 'label-light'
+ = label_tag :expires_at, 'Access expiration date', class: 'label-bold'
= text_field_tag :expires_at, nil, class: 'form-control js-access-expiration-date', placeholder: 'Expiration date'
%i.clear-icon.js-clear-input
= f.submit "Add to project", class: "btn btn-create"
diff --git a/app/views/projects/project_members/_new_shared_group.html.haml b/app/views/projects/project_members/_new_shared_group.html.haml
index 684219735e2..d7227c32833 100644
--- a/app/views/projects/project_members/_new_shared_group.html.haml
+++ b/app/views/projects/project_members/_new_shared_group.html.haml
@@ -2,10 +2,10 @@
.col-sm-12
= form_tag project_group_links_path(@project), class: 'js-requires-input', method: :post do
.form-group
- = label_tag :link_group_id, "Select a group to share with", class: "label-light"
+ = label_tag :link_group_id, "Select a group to share with", class: "label-bold"
= groups_select_tag(:link_group_id, data: { skip_groups: @skip_groups }, class: "input-clamp", required: true)
.form-group
- = label_tag :link_group_access, "Max access level", class: "label-light"
+ = label_tag :link_group_access, "Max access level", class: "label-bold"
.select-wrapper
= select_tag :link_group_access, options_for_select(ProjectGroupLink.access_options, ProjectGroupLink.default_access), class: "form-control select-control"
= icon('chevron-down')
@@ -13,7 +13,7 @@
= link_to "Read more", help_page_path("user/permissions"), class: "vlink"
about role permissions
.form-group
- = label_tag :expires_at, 'Access expiration date', class: 'label-light'
+ = label_tag :expires_at, 'Access expiration date', class: 'label-bold'
.clearable-input
= text_field_tag :expires_at, nil, class: 'form-control js-access-expiration-date-groups', placeholder: 'Expiration date', id: 'expires_at_groups'
%i.clear-icon.js-clear-input
diff --git a/app/views/projects/protected_tags/_protected_tag.html.haml b/app/views/projects/protected_tags/_protected_tag.html.haml
index da1f97c8d6a..e0912bf39c0 100644
--- a/app/views/projects/protected_tags/_protected_tag.html.haml
+++ b/app/views/projects/protected_tags/_protected_tag.html.haml
@@ -1,2 +1,4 @@
= render layout: 'projects/protected_tags/shared/protected_tag', locals: { protected_tag: protected_tag } do
- = render partial: 'projects/protected_tags/update_protected_tag', locals: { protected_tag: protected_tag }
+ %td
+ = render 'projects/protected_tags/protected_tag_create_access_levels', protected_tag: protected_tag, create_access_level: protected_tag.create_access_levels.for_role.first
+ = render_if_exists 'projects/protected_tags/protected_tag_extra_create_access_levels', protected_tag: protected_tag
diff --git a/app/views/projects/protected_tags/_protected_tag_create_access_levels.haml b/app/views/projects/protected_tags/_protected_tag_create_access_levels.haml
new file mode 100644
index 00000000000..1d4e9565156
--- /dev/null
+++ b/app/views/projects/protected_tags/_protected_tag_create_access_levels.haml
@@ -0,0 +1,8 @@
+- protected_tag = local_assigns.fetch(:protected_tag)
+- create_access_level = local_assigns.fetch(:create_access_level)
+- dropdown_label = create_access_level&.humanize || 'Select'
+
+= hidden_field_tag "allowed_to_create_#{protected_tag.id}", create_access_level&.access_level
+= dropdown_tag(dropdown_label,
+ options: { toggle_class: 'js-allowed-to-create', dropdown_class: 'dropdown-menu-selectable capitalize-header js-allowed-to-create-container',
+ data: { field_name: "allowed_to_create_#{protected_tag.id}", access_level_id: create_access_level&.id }})
diff --git a/app/views/projects/protected_tags/_update_protected_tag.haml b/app/views/projects/protected_tags/_update_protected_tag.haml
deleted file mode 100644
index cc80bd04dd0..00000000000
--- a/app/views/projects/protected_tags/_update_protected_tag.haml
+++ /dev/null
@@ -1,5 +0,0 @@
-%td
- = hidden_field_tag "allowed_to_create_#{protected_tag.id}", protected_tag.create_access_levels.first.access_level
- = dropdown_tag( (protected_tag.create_access_levels.first.humanize || 'Select') ,
- options: { toggle_class: 'js-allowed-to-create', dropdown_class: 'dropdown-menu-selectable capitalize-header js-allowed-to-create-container',
- data: { field_name: "allowed_to_create_#{protected_tag.id}", access_level_id: protected_tag.create_access_levels.first.id }})
diff --git a/app/views/projects/services/prometheus/_metrics.html.haml b/app/views/projects/services/prometheus/_metrics.html.haml
new file mode 100644
index 00000000000..98d64fafe86
--- /dev/null
+++ b/app/views/projects/services/prometheus/_metrics.html.haml
@@ -0,0 +1,30 @@
+- project = local_assigns.fetch(:project)
+
+.card.js-panel-monitored-metrics{ data: { active_metrics: active_common_project_prometheus_metrics_path(project, :json), metrics_help_path: help_page_path('user/project/integrations/prometheus_library/metrics') } }
+ .card-header
+ %h3.card-title
+ = s_('PrometheusService|Common metrics')
+ %span.badge.badge-pill.js-monitored-count 0
+ .card-body
+ .loading-metrics.js-loading-metrics
+ %p.prepend-top-10.prepend-left-10
+ = icon('spinner spin', class: 'metrics-load-spinner')
+ = s_('PrometheusService|Finding and configuring metrics...')
+ .empty-metrics.hidden.js-empty-metrics
+ %p.text-tertiary.prepend-top-10.prepend-left-10
+ = s_('PrometheusService|Waiting for your first deployment to an environment to find common metrics')
+ %ul.list-unstyled.metrics-list.hidden.js-metrics-list
+
+.card.hidden.js-panel-missing-env-vars
+ .card-header
+ %h3.card-title
+ = icon('caret-right lg fw', class: 'panel-toggle js-panel-toggle', 'aria-label' => 'Toggle panel')
+ = s_('PrometheusService|Missing environment variable')
+ %span.badge.badge-pill.js-env-var-count 0
+ .card-body.hidden
+ .flash-container
+ .flash-notice
+ .flash-text
+ = s_("PrometheusService|To set up automatic monitoring, add the environment variable %{variable} to exporter's queries." % { variable: "<code>$CI_ENVIRONMENT_SLUG</code>" }).html_safe
+ = link_to s_('PrometheusService|More information'), help_page_path('user/project/integrations/prometheus', anchor: 'metrics-and-labels')
+ %ul.list-unstyled.metrics-list.js-missing-var-metrics-list
diff --git a/app/views/projects/services/prometheus/_show.html.haml b/app/views/projects/services/prometheus/_show.html.haml
index bda597cc02b..1d0b0265bb7 100644
--- a/app/views/projects/services/prometheus/_show.html.haml
+++ b/app/views/projects/services/prometheus/_show.html.haml
@@ -3,35 +3,8 @@
%h4.prepend-top-0
= s_('PrometheusService|Metrics')
%p
- = s_('PrometheusService|Metrics are automatically configured and monitored based on a library of metrics from popular exporters.')
- = link_to s_('PrometheusService|More information'), help_page_path('user/project/integrations/prometheus')
+ = s_('PrometheusService|Common metrics are automatically monitored based on a library of metrics from popular exporters.')
+ = link_to s_('PrometheusService|More information'), help_page_path('user/project/integrations/prometheus_library/metrics'), target: '_blank', rel: "noopener noreferrer"
.col-lg-9
- .card.js-panel-monitored-metrics{ data: { active_metrics: active_common_project_prometheus_metrics_path(@project, :json), metrics_help_path: help_page_path('user/project/integrations/prometheus_library/metrics') } }
- .card-header
- %h3.card-title
- = s_('PrometheusService|Common metrics')
- %span.badge.badge-pill.js-monitored-count 0
- .card-body
- .loading-metrics.js-loading-metrics
- %p.prepend-top-10.prepend-left-10
- = icon('spinner spin', class: 'metrics-load-spinner')
- = s_('PrometheusService|Finding and configuring metrics...')
- .empty-metrics.hidden.js-empty-metrics
- %p.text-tertiary.prepend-top-10.prepend-left-10
- = s_('PrometheusService|Waiting for your first deployment to an environment to find common metrics')
- %ul.list-unstyled.metrics-list.hidden.js-metrics-list
-
- .card.hidden.js-panel-missing-env-vars
- .card-header
- %h3.card-title
- = icon('caret-right lg fw', class: 'panel-toggle js-panel-toggle', 'aria-label' => 'Toggle panel')
- = s_('PrometheusService|Missing environment variable')
- %span.badge.badge-pill.js-env-var-count 0
- .card-body.hidden
- .flash-container
- .flash-notice
- .flash-text
- = s_("PrometheusService|To set up automatic monitoring, add the environment variable %{variable} to exporter's queries." % { variable: "<code>$CI_ENVIRONMENT_SLUG</code>" }).html_safe
- = link_to s_('PrometheusService|More information'), help_page_path('user/project/integrations/prometheus', anchor: 'metrics-and-labels')
- %ul.list-unstyled.metrics-list.js-missing-var-metrics-list
+ = render 'projects/services/prometheus/metrics', project: @project
diff --git a/app/views/projects/settings/ci_cd/_form.html.haml b/app/views/projects/settings/ci_cd/_form.html.haml
index fb113aa7639..64751e5616a 100644
--- a/app/views/projects/settings/ci_cd/_form.html.haml
+++ b/app/views/projects/settings/ci_cd/_form.html.haml
@@ -4,7 +4,7 @@
= form_errors(@project)
%fieldset.builds-feature
.form-group.append-bottom-default.js-secret-runner-token
- = f.label :runners_token, _("Runner token"), class: 'label-light'
+ = f.label :runners_token, _("Runner token"), class: 'label-bold'
.form-control.js-secret-value-placeholder
= '*' * 20
= f.text_field :runners_token, class: "form-control hide js-secret-value", placeholder: 'xEeFCaDAB89'
@@ -36,7 +36,7 @@
%hr
.form-group
- = f.label :build_timeout_human_readable, _('Timeout'), class: 'label-light'
+ = f.label :build_timeout_human_readable, _('Timeout'), class: 'label-bold'
= f.text_field :build_timeout_human_readable, class: 'form-control'
%p.form-text.text-muted
= _("Per job. If a job passes this threshold, it will be marked as failed")
@@ -44,7 +44,7 @@
%hr
.form-group
- = f.label :ci_config_path, _('Custom CI config path'), class: 'label-light'
+ = f.label :ci_config_path, _('Custom CI config path'), class: 'label-bold'
= f.text_field :ci_config_path, class: 'form-control', placeholder: '.gitlab-ci.yml'
%p.form-text.text-muted
= _("The path to CI config file. Defaults to <code>.gitlab-ci.yml</code>")
@@ -83,7 +83,7 @@
%hr
.form-group
- = f.label :build_coverage_regex, _("Test coverage parsing"), class: 'label-light'
+ = f.label :build_coverage_regex, _("Test coverage parsing"), class: 'label-bold'
.input-group
%span.input-group-prepend
.input-group-text /
diff --git a/app/views/projects/show.html.haml b/app/views/projects/show.html.haml
index e28accd5b43..803ecca48f7 100644
--- a/app/views/projects/show.html.haml
+++ b/app/views/projects/show.html.haml
@@ -8,6 +8,10 @@
= render partial: 'flash_messages', locals: { project: @project }
+- if @project.repository_exists? && !@project.empty_repo?
+ - signatures_path = namespace_project_signatures_path(project_id: @project.path, id: @project.default_branch)
+ .js-signature-container{ data: { 'signatures-path': signatures_path } }
+
%div{ class: [container_class, ("limit-container-width" unless fluid_layout)] }
= render "projects/last_push"
diff --git a/app/views/projects/tags/index.html.haml b/app/views/projects/tags/index.html.haml
index 96ecac815c0..dab95ba09f2 100644
--- a/app/views/projects/tags/index.html.haml
+++ b/app/views/projects/tags/index.html.haml
@@ -26,6 +26,8 @@
= link_to new_project_tag_path(@project), class: 'btn btn-create new-tag-btn' do
= s_('TagsPage|New tag')
+ = render_if_exists 'projects/commits/mirror_status'
+
.tags
- if @tags.any?
%ul.flex-list.content-list
diff --git a/app/views/projects/tree/show.html.haml b/app/views/projects/tree/show.html.haml
index 3b4057e56d0..ace8120eeff 100644
--- a/app/views/projects/tree/show.html.haml
+++ b/app/views/projects/tree/show.html.haml
@@ -1,11 +1,14 @@
- @no_container = true
- breadcrumb_title _("Repository")
- @content_class = "limit-container-width" unless fluid_layout
+- signatures_path = namespace_project_signatures_path(namespace_id: @project.namespace.path, project_id: @project.path, id: @ref)
- page_title @path.presence || _("Files"), @ref
= content_for :meta_tags do
= auto_discovery_link_tag(:atom, project_commits_url(@project, @ref, rss_url_options), title: "#{@project.name}:#{@ref} commits")
+.js-signature-container{ data: { 'signatures-path': signatures_path } }
+
%div{ class: [(container_class), ("limit-container-width" unless fluid_layout)] }
= render 'projects/last_push'
= render 'projects/files', commit: @last_commit, project: @project, ref: @ref, content_url: project_tree_path(@project, @id)
diff --git a/app/views/projects/triggers/_form.html.haml b/app/views/projects/triggers/_form.html.haml
index 3539aea3580..1a5fc56f429 100644
--- a/app/views/projects/triggers/_form.html.haml
+++ b/app/views/projects/triggers/_form.html.haml
@@ -3,9 +3,9 @@
- if @trigger.token
.form-group
- %label.label-light Token
+ %label.label-bold Token
%p.form-control-plaintext= @trigger.token
.form-group
- = f.label :key, "Description", class: "label-light"
+ = f.label :key, "Description", class: "label-bold"
= f.text_field :description, class: "form-control", required: true, title: 'Trigger description is required.', placeholder: "Trigger description"
= f.submit btn_text, class: "btn btn-save"
diff --git a/app/views/shared/_import_form.html.haml b/app/views/shared/_import_form.html.haml
index 356e12cf9f8..7b593ca4f76 100644
--- a/app/views/shared/_import_form.html.haml
+++ b/app/views/shared/_import_form.html.haml
@@ -1,7 +1,7 @@
- ci_cd_only = local_assigns.fetch(:ci_cd_only, false)
.form-group.import-url-data
- = f.label :import_url, class: 'label-light' do
+ = f.label :import_url, class: 'label-bold' do
%span
= _('Git repository URL')
diff --git a/app/views/shared/_personal_access_tokens_form.html.haml b/app/views/shared/_personal_access_tokens_form.html.haml
index 28407b543b9..58d310fac16 100644
--- a/app/views/shared/_personal_access_tokens_form.html.haml
+++ b/app/views/shared/_personal_access_tokens_form.html.haml
@@ -11,18 +11,18 @@
.row
.form-group.col-md-6
- = f.label :name, class: 'label-light'
+ = f.label :name, class: 'label-bold'
= f.text_field :name, class: "form-control", required: true
.row
.form-group.col-md-6
- = f.label :expires_at, class: 'label-light'
+ = f.label :expires_at, class: 'label-bold'
.input-icon-wrapper
= f.text_field :expires_at, class: "datepicker form-control", placeholder: 'YYYY-MM-DD'
= icon('calendar', { class: 'input-icon-right' })
.form-group
- = f.label :scopes, class: 'label-light'
+ = f.label :scopes, class: 'label-bold'
= render 'shared/tokens/scopes_form', prefix: 'personal_access_token', token: token, scopes: scopes
.prepend-top-default
diff --git a/app/views/shared/tokens/_scopes_form.html.haml b/app/views/shared/tokens/_scopes_form.html.haml
index dcb3fca23f2..af9db5f59a8 100644
--- a/app/views/shared/tokens/_scopes_form.html.haml
+++ b/app/views/shared/tokens/_scopes_form.html.haml
@@ -5,5 +5,5 @@
- scopes.each do |scope|
%fieldset.form-group.form-check
= check_box_tag "#{prefix}[scopes][]", scope, token.scopes.include?(scope), id: "#{prefix}_scopes_#{scope}", class: 'form-check-input'
- = label_tag ("#{prefix}_scopes_#{scope}"), scope, class: 'label-light form-check-label'
+ = label_tag ("#{prefix}_scopes_#{scope}"), scope, class: 'label-bold form-check-label'
.text-secondary= t scope, scope: [:doorkeeper, :scope_desc]
diff --git a/app/views/shared/web_hooks/_form.html.haml b/app/views/shared/web_hooks/_form.html.haml
index 660769fa50d..07ebb8680d2 100644
--- a/app/views/shared/web_hooks/_form.html.haml
+++ b/app/views/shared/web_hooks/_form.html.haml
@@ -1,15 +1,15 @@
= form_errors(hook)
.form-group
- = form.label :url, 'URL', class: 'label-light'
+ = form.label :url, 'URL', class: 'label-bold'
= form.text_field :url, class: 'form-control', placeholder: 'http://example.com/trigger-ci.json'
.form-group
- = form.label :token, 'Secret Token', class: 'label-light'
+ = form.label :token, 'Secret Token', class: 'label-bold'
= form.text_field :token, class: 'form-control', placeholder: ''
%p.form-text.text-muted
Use this token to validate received payloads. It will be sent with the request in the X-Gitlab-Token HTTP header.
.form-group
- = form.label :url, 'Trigger', class: 'label-light'
+ = form.label :url, 'Trigger', class: 'label-bold'
%ul.list-unstyled.prepend-left-20
%li
= form.check_box :push_events, class: 'form-check-input'
@@ -72,7 +72,7 @@
%p.light.ml-1
This URL will be triggered when a wiki page is created/updated
.form-group
- = form.label :enable_ssl_verification, 'SSL verification', class: 'label-light checkbox'
+ = form.label :enable_ssl_verification, 'SSL verification', class: 'label-bold checkbox'
.form-check
= form.check_box :enable_ssl_verification, class: 'form-check-input'
= form.label :enable_ssl_verification, class: 'form-check-label ml-1' do
diff --git a/app/views/sherlock/queries/_general.html.haml b/app/views/sherlock/queries/_general.html.haml
index 37747faed62..ddc089b0bd7 100644
--- a/app/views/sherlock/queries/_general.html.haml
+++ b/app/views/sherlock/queries/_general.html.haml
@@ -27,7 +27,7 @@
.card-header
.float-right
%button.js-clipboard-trigger.btn.btn-sm{ title: t('sherlock.copy_to_clipboard'), type: :button }
- %i.fa.fa-clipboard
+ = sprite_icon('duplicate')
%pre.hidden
= @query.formatted_query
%strong
@@ -42,7 +42,7 @@
.card-header
.float-right
%button.js-clipboard-trigger.btn.btn-sm{ title: t('sherlock.copy_to_clipboard'), type: :button }
- %i.fa.fa-clipboard
+ = sprite_icon('duplicate')
%pre.hidden
= @query.explain
%strong
diff --git a/app/workers/all_queues.yml b/app/workers/all_queues.yml
index d4be1ccfcfa..4de35b9bd06 100644
--- a/app/workers/all_queues.yml
+++ b/app/workers/all_queues.yml
@@ -13,7 +13,6 @@
- cronjob:repository_archive_cache
- cronjob:repository_check_dispatch
- cronjob:requests_profiles
-- cronjob:schedule_update_user_activity
- cronjob:stuck_ci_jobs
- cronjob:stuck_import_jobs
- cronjob:stuck_merge_jobs
@@ -114,7 +113,6 @@
- storage_migrator
- system_hook_push
- update_merge_requests
-- update_user_activity
- upload_checksum
- web_hook
- repository_update_remote_mirror
diff --git a/app/workers/concerns/each_shard_worker.rb b/app/workers/concerns/each_shard_worker.rb
index d0a728fb495..00f589f957e 100644
--- a/app/workers/concerns/each_shard_worker.rb
+++ b/app/workers/concerns/each_shard_worker.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module EachShardWorker
extend ActiveSupport::Concern
include ::Gitlab::Utils::StrongMemoize
diff --git a/app/workers/delete_diff_files_worker.rb b/app/workers/delete_diff_files_worker.rb
index bb8fbb9c373..0874a0b75e8 100644
--- a/app/workers/delete_diff_files_worker.rb
+++ b/app/workers/delete_diff_files_worker.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class DeleteDiffFilesWorker
include ApplicationWorker
diff --git a/app/workers/emails_on_push_worker.rb b/app/workers/emails_on_push_worker.rb
index 8d0cfc73ccd..17ad1d5ab88 100644
--- a/app/workers/emails_on_push_worker.rb
+++ b/app/workers/emails_on_push_worker.rb
@@ -51,7 +51,7 @@ class EmailsOnPushWorker
end
end
- recipients.split.each do |recipient|
+ valid_recipients(recipients).each do |recipient|
begin
send_email(
recipient,
@@ -89,4 +89,10 @@ class EmailsOnPushWorker
email.header[:skip_premailer] = true if skip_premailer
email.deliver_now
end
+
+ def valid_recipients(recipients)
+ recipients.split.select do |recipient|
+ recipient.include?('@')
+ end
+ end
end
diff --git a/app/workers/repository_check/dispatch_worker.rb b/app/workers/repository_check/dispatch_worker.rb
index 96634f09a15..0a7d9a14c6a 100644
--- a/app/workers/repository_check/dispatch_worker.rb
+++ b/app/workers/repository_check/dispatch_worker.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module RepositoryCheck
class DispatchWorker
include ApplicationWorker
diff --git a/app/workers/schedule_update_user_activity_worker.rb b/app/workers/schedule_update_user_activity_worker.rb
deleted file mode 100644
index ff42fb8f0e5..00000000000
--- a/app/workers/schedule_update_user_activity_worker.rb
+++ /dev/null
@@ -1,12 +0,0 @@
-# frozen_string_literal: true
-
-class ScheduleUpdateUserActivityWorker
- include ApplicationWorker
- include CronjobQueue
-
- def perform(batch_size = 500)
- Gitlab::UserActivities.new.each_slice(batch_size) do |batch|
- UpdateUserActivityWorker.perform_async(Hash[batch])
- end
- end
-end
diff --git a/app/workers/update_user_activity_worker.rb b/app/workers/update_user_activity_worker.rb
deleted file mode 100644
index 15f01a70337..00000000000
--- a/app/workers/update_user_activity_worker.rb
+++ /dev/null
@@ -1,27 +0,0 @@
-# frozen_string_literal: true
-
-class UpdateUserActivityWorker
- include ApplicationWorker
-
- def perform(pairs)
- pairs = cast_data(pairs)
- ids = pairs.keys
- conditions = 'WHEN id = ? THEN ? ' * ids.length
-
- User.where(id: ids)
- .update_all([
- "last_activity_on = CASE #{conditions} ELSE last_activity_on END",
- *pairs.to_a.flatten
- ])
-
- Gitlab::UserActivities.new.delete(*ids)
- end
-
- private
-
- def cast_data(pairs)
- pairs.each_with_object({}) do |(key, value), new_pairs|
- new_pairs[key.to_i] = Time.at(value.to_i).to_s(:db)
- end
- end
-end
diff --git a/changelogs/unreleased/18141-osw-use-monospaced-font-on-diffs-commit-ref.yml b/changelogs/unreleased/18141-osw-use-monospaced-font-on-diffs-commit-ref.yml
deleted file mode 100644
index 43ff880a8cb..00000000000
--- a/changelogs/unreleased/18141-osw-use-monospaced-font-on-diffs-commit-ref.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Use monospaced font for MR diff commit link ref on GFM
-merge_request:
-author:
-type: other
diff --git a/changelogs/unreleased/19439-api-file-sha56-and-head.yml b/changelogs/unreleased/19439-api-file-sha56-and-head.yml
deleted file mode 100644
index 4bc1e560631..00000000000
--- a/changelogs/unreleased/19439-api-file-sha56-and-head.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Add SHA256 and HEAD on File API
-merge_request: 19439
-author: ahmet2mir
-type: added
diff --git a/changelogs/unreleased/19468-add_readme_when_creating_project.yml b/changelogs/unreleased/19468-add_readme_when_creating_project.yml
deleted file mode 100644
index f85fc773ef0..00000000000
--- a/changelogs/unreleased/19468-add_readme_when_creating_project.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Add option to add README when creating a project
-merge_request: 20335
-author:
-type: added
diff --git a/changelogs/unreleased/20357.yml b/changelogs/unreleased/20357.yml
deleted file mode 100644
index b4ce686eece..00000000000
--- a/changelogs/unreleased/20357.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix double "in" in time to artifact deletion message
-merge_request: 20357
-author: "@bbodenmiller"
-type: fixed
diff --git a/changelogs/unreleased/23705-add-single-file-download-in-repo.yml b/changelogs/unreleased/23705-add-single-file-download-in-repo.yml
new file mode 100644
index 00000000000..f156bfb1101
--- /dev/null
+++ b/changelogs/unreleased/23705-add-single-file-download-in-repo.yml
@@ -0,0 +1,5 @@
+---
+title: Add download button for single file (including raw files) in repository
+merge_request: 20480
+author: Kia Mei Somabes
+type: added
diff --git a/changelogs/unreleased/29278-commits-page-tooltips.yml b/changelogs/unreleased/29278-commits-page-tooltips.yml
new file mode 100644
index 00000000000..d54301a1cf0
--- /dev/null
+++ b/changelogs/unreleased/29278-commits-page-tooltips.yml
@@ -0,0 +1,5 @@
+---
+title: Remove tooltips from commit author avatar and name in commit lists
+merge_request: 20674
+author:
+type: other
diff --git a/changelogs/unreleased/31583-osw-gfm-complete-status-indication.yml b/changelogs/unreleased/31583-osw-gfm-complete-status-indication.yml
deleted file mode 100644
index 6f2cf275592..00000000000
--- a/changelogs/unreleased/31583-osw-gfm-complete-status-indication.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Present state indication on GFM preview
-merge_request:
-author:
-type: added
diff --git a/changelogs/unreleased/35158-snippets-api-visibility.yml b/changelogs/unreleased/35158-snippets-api-visibility.yml
deleted file mode 100644
index f06015dda46..00000000000
--- a/changelogs/unreleased/35158-snippets-api-visibility.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Expose visibility via Snippets API
-merge_request: 19620
-author: Jan Beckmann
-type: added
diff --git a/changelogs/unreleased/36234-nav-add-groups-dropdown.yml b/changelogs/unreleased/36234-nav-add-groups-dropdown.yml
deleted file mode 100644
index 86a24102665..00000000000
--- a/changelogs/unreleased/36234-nav-add-groups-dropdown.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Add dropdown to Groups link in top bar
-merge_request: 18280
-author:
-type: added
diff --git a/changelogs/unreleased/36907-fix-new-issue-link-from-failed-job.yml b/changelogs/unreleased/36907-fix-new-issue-link-from-failed-job.yml
deleted file mode 100644
index 80a50734f72..00000000000
--- a/changelogs/unreleased/36907-fix-new-issue-link-from-failed-job.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix link to job when creating a new issue from a failed job
-merge_request: 20328
-author:
-type: fixed
diff --git a/changelogs/unreleased/37561-add-id-settings.yml b/changelogs/unreleased/37561-add-id-settings.yml
deleted file mode 100644
index 122ac23cb53..00000000000
--- a/changelogs/unreleased/37561-add-id-settings.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Allows settings sections to expand by default when linking to them
-merge_request: 20211
-author:
-type: other
diff --git a/changelogs/unreleased/39543-milestone-page-list-redesign.yml b/changelogs/unreleased/39543-milestone-page-list-redesign.yml
deleted file mode 100644
index dcd73c5eddf..00000000000
--- a/changelogs/unreleased/39543-milestone-page-list-redesign.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Milestone page list redesign
-merge_request: 19832
-author: Constance Okoghenun
-type: changed
diff --git a/changelogs/unreleased/39604-update-top-right-avatar-after-changing-avatar.yml b/changelogs/unreleased/39604-update-top-right-avatar-after-changing-avatar.yml
deleted file mode 100644
index 17192673996..00000000000
--- a/changelogs/unreleased/39604-update-top-right-avatar-after-changing-avatar.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Change avatar image in the header when user updates their avatar.
-merge_request: 20119
-author: Jamie Schembri
-type: added
diff --git a/changelogs/unreleased/40005-u2f-unspported-browsers.yml b/changelogs/unreleased/40005-u2f-unspported-browsers.yml
deleted file mode 100644
index eb5ff99246e..00000000000
--- a/changelogs/unreleased/40005-u2f-unspported-browsers.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Improve U2F workflow when using unsupported browsers
-merge_request: 19938
-author: Jan Beckmann
-type: changed
diff --git a/changelogs/unreleased/40484-ordered-lists-copy-gfm.yml b/changelogs/unreleased/40484-ordered-lists-copy-gfm.yml
deleted file mode 100644
index f4b34909ae9..00000000000
--- a/changelogs/unreleased/40484-ordered-lists-copy-gfm.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Keep lists ordered when copying only list items
-merge_request: 18522
-author: Jan Beckmann
-type: fixed
diff --git a/changelogs/unreleased/42342-teams-pipeline-notifications.yml b/changelogs/unreleased/42342-teams-pipeline-notifications.yml
deleted file mode 100644
index 4ef3a35465b..00000000000
--- a/changelogs/unreleased/42342-teams-pipeline-notifications.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fixes Microsoft Teams notifications for pipeline events
-merge_request: 19632
-author: Jeff Brown
-type: fixed
diff --git a/changelogs/unreleased/43270-import-with-milestones-failing.yml b/changelogs/unreleased/43270-import-with-milestones-failing.yml
deleted file mode 100644
index 13bf8072376..00000000000
--- a/changelogs/unreleased/43270-import-with-milestones-failing.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix label and milestone duplicated records and IID errors
-merge_request: 19961
-author:
-type: fixed
diff --git a/changelogs/unreleased/43312-remove_user_activity_workers.yml b/changelogs/unreleased/43312-remove_user_activity_workers.yml
new file mode 100644
index 00000000000..6dfd018e350
--- /dev/null
+++ b/changelogs/unreleased/43312-remove_user_activity_workers.yml
@@ -0,0 +1,5 @@
+---
+title: Delete UserActivities and related workers
+merge_request: 20597
+author:
+type: performance
diff --git a/changelogs/unreleased/43446-new-cluster-page-tabs.yml b/changelogs/unreleased/43446-new-cluster-page-tabs.yml
deleted file mode 100644
index e8c73257b16..00000000000
--- a/changelogs/unreleased/43446-new-cluster-page-tabs.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Create new or add existing Kubernetes cluster from a single page
-merge_request: 18963
-author:
-type: changed
diff --git a/changelogs/unreleased/43472-remove-environment-scope-field-on-cluster-creation-form-for-core-starter-plans.yml b/changelogs/unreleased/43472-remove-environment-scope-field-on-cluster-creation-form-for-core-starter-plans.yml
deleted file mode 100644
index 7d2804f0310..00000000000
--- a/changelogs/unreleased/43472-remove-environment-scope-field-on-cluster-creation-form-for-core-starter-plans.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Removes the environment scope field for users that cannot edit it
-merge_request: 19643
-author:
-type: changed
diff --git a/changelogs/unreleased/44674-use-one-column-form-layout-on-admin-area-settings-page.yml b/changelogs/unreleased/44674-use-one-column-form-layout-on-admin-area-settings-page.yml
deleted file mode 100644
index 69733889d5a..00000000000
--- a/changelogs/unreleased/44674-use-one-column-form-layout-on-admin-area-settings-page.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Use one column form layout on Admin Area Settings page
-merge_request:
-author:
-type: changed
diff --git a/changelogs/unreleased/44697-when-editing-a-comment-in-an-issue-the-preview-mode-is-toggled-in-the-main-textarea.yml b/changelogs/unreleased/44697-when-editing-a-comment-in-an-issue-the-preview-mode-is-toggled-in-the-main-textarea.yml
deleted file mode 100644
index 750e28f1a8d..00000000000
--- a/changelogs/unreleased/44697-when-editing-a-comment-in-an-issue-the-preview-mode-is-toggled-in-the-main-textarea.yml
+++ /dev/null
@@ -1,6 +0,0 @@
----
-title: Fixed bug when editing a comment in an issue,the preview mode is toggled in
- the main textarea
-merge_request: 20112
-author: Constance Okoghenun
-type: fixed
diff --git a/changelogs/unreleased/44725-expire_correct_methods_after_change_head.yml b/changelogs/unreleased/44725-expire_correct_methods_after_change_head.yml
deleted file mode 100644
index 21a65f142c3..00000000000
--- a/changelogs/unreleased/44725-expire_correct_methods_after_change_head.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Expire correct method caches after HEAD changed
-merge_request:
-author:
-type: fixed
diff --git a/changelogs/unreleased/45318-vuex-store.yml b/changelogs/unreleased/45318-vuex-store.yml
new file mode 100644
index 00000000000..5ea89034bce
--- /dev/null
+++ b/changelogs/unreleased/45318-vuex-store.yml
@@ -0,0 +1,5 @@
+---
+title: Adds Vuex store for reports section in MR widget
+merge_request: 20709
+author:
+type: added
diff --git a/changelogs/unreleased/45400-automatically-created-mr-uses-wrong-target-branch-when-branching-from-tag.yml b/changelogs/unreleased/45400-automatically-created-mr-uses-wrong-target-branch-when-branching-from-tag.yml
deleted file mode 100644
index 5aba62435ed..00000000000
--- a/changelogs/unreleased/45400-automatically-created-mr-uses-wrong-target-branch-when-branching-from-tag.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Set MR target branch to default branch if target branch is not valid
-merge_request: 19067
-author:
-type: fixed
diff --git a/changelogs/unreleased/45443-unable-to-save-user-profile-update-with-safari.yml b/changelogs/unreleased/45443-unable-to-save-user-profile-update-with-safari.yml
new file mode 100644
index 00000000000..b18f7aec546
--- /dev/null
+++ b/changelogs/unreleased/45443-unable-to-save-user-profile-update-with-safari.yml
@@ -0,0 +1,5 @@
+---
+title: Resolve "Unable to save user profile update with Safari"
+merge_request: 20676
+author:
+type: fixed
diff --git a/changelogs/unreleased/45487-slack-tag-push-notifs.yml b/changelogs/unreleased/45487-slack-tag-push-notifs.yml
deleted file mode 100644
index 647000bd97c..00000000000
--- a/changelogs/unreleased/45487-slack-tag-push-notifs.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix chat service tag notifications not sending when only default branch enabled
-merge_request: 19864
-author:
-type: fixed
diff --git a/changelogs/unreleased/45557-machine-type-help-links.yml b/changelogs/unreleased/45557-machine-type-help-links.yml
deleted file mode 100644
index 870a650e10b..00000000000
--- a/changelogs/unreleased/45557-machine-type-help-links.yml
+++ /dev/null
@@ -1,6 +0,0 @@
----
-title: Add machine type and pricing documentation links, add class to labels to make
- bold
-merge_request:
-author:
-type: changed
diff --git a/changelogs/unreleased/45575-invalid-characters-signup.yml b/changelogs/unreleased/45575-invalid-characters-signup.yml
deleted file mode 100644
index 679bd13e59b..00000000000
--- a/changelogs/unreleased/45575-invalid-characters-signup.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: 'Fix username validation order on signup, resolves #45575'
-merge_request: 19610
-author: Jan Beckmann
-type: fixed
diff --git a/changelogs/unreleased/45703-open-web-ide-file-tree.yml b/changelogs/unreleased/45703-open-web-ide-file-tree.yml
deleted file mode 100644
index abee9cad2d5..00000000000
--- a/changelogs/unreleased/45703-open-web-ide-file-tree.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Update WebIDE to show file in tree on load
-merge_request: 19887
-author:
-type: changed
diff --git a/changelogs/unreleased/45738-add-environment-drop-down-to-metrics-dashboard.yml b/changelogs/unreleased/45738-add-environment-drop-down-to-metrics-dashboard.yml
deleted file mode 100644
index 5aaeaaf0448..00000000000
--- a/changelogs/unreleased/45738-add-environment-drop-down-to-metrics-dashboard.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Add environment dropdown for the metrics page
-merge_request: 19833
-author:
-type: changed
diff --git a/changelogs/unreleased/45933-webide-fade-uneditable-area.yml b/changelogs/unreleased/45933-webide-fade-uneditable-area.yml
deleted file mode 100644
index dfb186122e7..00000000000
--- a/changelogs/unreleased/45933-webide-fade-uneditable-area.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fade uneditable area in Web IDE
-merge_request: 20008
-author:
-type: changed
diff --git a/changelogs/unreleased/46202-webide-file-states.yml b/changelogs/unreleased/46202-webide-file-states.yml
deleted file mode 100644
index 8d697b643be..00000000000
--- a/changelogs/unreleased/46202-webide-file-states.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Update Web IDE file tree styles
-merge_request: 19969
-author:
-type: changed
diff --git a/changelogs/unreleased/46246-gitlab-project-export-should-use-object-storage.yml b/changelogs/unreleased/46246-gitlab-project-export-should-use-object-storage.yml
deleted file mode 100644
index 908c7a238fd..00000000000
--- a/changelogs/unreleased/46246-gitlab-project-export-should-use-object-storage.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Add Object Storage to project export
-merge_request: 20105
-author:
-type: added
diff --git a/changelogs/unreleased/46396-recognise-when-a-user-is-trying-to-validate-a-private-ssh-key-part-1.yml b/changelogs/unreleased/46396-recognise-when-a-user-is-trying-to-validate-a-private-ssh-key-part-1.yml
deleted file mode 100644
index d8c7d612c3d..00000000000
--- a/changelogs/unreleased/46396-recognise-when-a-user-is-trying-to-validate-a-private-ssh-key-part-1.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Update new SSH key page to improve copy
-merge_request: 19994
-author:
-type: other
diff --git a/changelogs/unreleased/46396-recognise-when-a-user-is-trying-to-validate-a-private-ssh-key.yml b/changelogs/unreleased/46396-recognise-when-a-user-is-trying-to-validate-a-private-ssh-key.yml
deleted file mode 100644
index 64bbecf3405..00000000000
--- a/changelogs/unreleased/46396-recognise-when-a-user-is-trying-to-validate-a-private-ssh-key.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Update new SSH key page to improve key input validation
-merge_request: 19997
-author:
-type: other
diff --git a/changelogs/unreleased/46429-creating-a-deploy-token-doesn-t-bring-back-to-the-creation-page.yml b/changelogs/unreleased/46429-creating-a-deploy-token-doesn-t-bring-back-to-the-creation-page.yml
deleted file mode 100644
index b564fb0174f..00000000000
--- a/changelogs/unreleased/46429-creating-a-deploy-token-doesn-t-bring-back-to-the-creation-page.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Allows you to create another deploy token dimmediately after creating one
-merge_request: 19639
-author:
-type: changed
diff --git a/changelogs/unreleased/46546-do-not-pre-select-previous-user-s-when-creating-protected-branches.yml b/changelogs/unreleased/46546-do-not-pre-select-previous-user-s-when-creating-protected-branches.yml
deleted file mode 100644
index 7d42d971022..00000000000
--- a/changelogs/unreleased/46546-do-not-pre-select-previous-user-s-when-creating-protected-branches.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: CE port gitlab-ee!6112
-merge_request: 19714
-author:
-type: other
diff --git a/changelogs/unreleased/46571-webhooks-nil-password.yml b/changelogs/unreleased/46571-webhooks-nil-password.yml
deleted file mode 100644
index 34c5f09478f..00000000000
--- a/changelogs/unreleased/46571-webhooks-nil-password.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix webhook error when password is not present
-merge_request: 19945
-author: Jan Beckmann
-type: fixed
diff --git a/changelogs/unreleased/46783-removed-omniauth-provider-causing-invalid-application-setting.yml b/changelogs/unreleased/46783-removed-omniauth-provider-causing-invalid-application-setting.yml
deleted file mode 100644
index d5ecf5163d4..00000000000
--- a/changelogs/unreleased/46783-removed-omniauth-provider-causing-invalid-application-setting.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Ignore unknown OAuth sources in ApplicationSetting
-merge_request: 20129
-author:
-type: fixed
diff --git a/changelogs/unreleased/46831-remove-unused-bootstrap-component-css.yml b/changelogs/unreleased/46831-remove-unused-bootstrap-component-css.yml
deleted file mode 100644
index e0e2b481b69..00000000000
--- a/changelogs/unreleased/46831-remove-unused-bootstrap-component-css.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Removes unused bootstrap 4 scss files
-merge_request: 19423
-author:
-type: deprecated
diff --git a/changelogs/unreleased/46861-issuable-title-with-longer-username.yml b/changelogs/unreleased/46861-issuable-title-with-longer-username.yml
deleted file mode 100644
index 9df6879deb6..00000000000
--- a/changelogs/unreleased/46861-issuable-title-with-longer-username.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix CSS for buttons not to be hidden on issues/MR title
-merge_request: 19176
-author: Takuya Noguchi
-type: fixed
diff --git a/changelogs/unreleased/46869-deploy-tokens-failed-to-clone-lfs-repository.yml b/changelogs/unreleased/46869-deploy-tokens-failed-to-clone-lfs-repository.yml
new file mode 100644
index 00000000000..d490df58144
--- /dev/null
+++ b/changelogs/unreleased/46869-deploy-tokens-failed-to-clone-lfs-repository.yml
@@ -0,0 +1,5 @@
+---
+title: Allow cloning LFS repositories through DeployTokens
+merge_request: 20729
+author:
+type: other
diff --git a/changelogs/unreleased/46963-add_readme_button_for_non_empty_project.yml b/changelogs/unreleased/46963-add_readme_button_for_non_empty_project.yml
deleted file mode 100644
index fdf41a26c4d..00000000000
--- a/changelogs/unreleased/46963-add_readme_button_for_non_empty_project.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Add readme button to non-empty project page
-merge_request: 20104
-author:
-type: fixed
diff --git a/changelogs/unreleased/47040-inconsistent-job-list-in-job-details-view.yml b/changelogs/unreleased/47040-inconsistent-job-list-in-job-details-view.yml
deleted file mode 100644
index 5629a40a1f1..00000000000
--- a/changelogs/unreleased/47040-inconsistent-job-list-in-job-details-view.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Show jobs from same pipeline in sidebar in job details view.
-merge_request: 20243
-author:
-type: fixed
diff --git a/changelogs/unreleased/47050-quick-actions-case-insensitive.yml b/changelogs/unreleased/47050-quick-actions-case-insensitive.yml
deleted file mode 100644
index 176aba627b9..00000000000
--- a/changelogs/unreleased/47050-quick-actions-case-insensitive.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Make quick commands case insensitive
-merge_request: 19614
-author: Jan Beckmann
-type: fixed
diff --git a/changelogs/unreleased/47145-quick-actions-confidential.yml b/changelogs/unreleased/47145-quick-actions-confidential.yml
deleted file mode 100644
index 7ae4e2268af..00000000000
--- a/changelogs/unreleased/47145-quick-actions-confidential.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Add /confidential quick action
-merge_request:
-author: Jan Beckmann
-type: added
diff --git a/changelogs/unreleased/47221-explain-what-groups-are-in-the-new-group-page.yml b/changelogs/unreleased/47221-explain-what-groups-are-in-the-new-group-page.yml
deleted file mode 100644
index 94c58a3863a..00000000000
--- a/changelogs/unreleased/47221-explain-what-groups-are-in-the-new-group-page.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Update new group page to better explain what groups are
-merge_request: 19991
-author:
-type: other
diff --git a/changelogs/unreleased/47274-help-users-find-our-contributing-page.yml b/changelogs/unreleased/47274-help-users-find-our-contributing-page.yml
deleted file mode 100644
index ed13c917a2e..00000000000
--- a/changelogs/unreleased/47274-help-users-find-our-contributing-page.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Add a link to the contributing page in the user dropdown
-merge_request: 19708
-author:
-type: added
diff --git a/changelogs/unreleased/47462-issues-disabled-group-page.yml b/changelogs/unreleased/47462-issues-disabled-group-page.yml
deleted file mode 100644
index c8cad608cb3..00000000000
--- a/changelogs/unreleased/47462-issues-disabled-group-page.yml
+++ /dev/null
@@ -1,6 +0,0 @@
----
-title: Only show new issue / new merge request on group page when issues / merge requests
- are enabled
-merge_request: 19869
-author: Jan Beckmann
-type: fixed
diff --git a/changelogs/unreleased/47631-operations-kubernetes-option-is-always-visible-when-repository-or-builds-are-disabled.yml b/changelogs/unreleased/47631-operations-kubernetes-option-is-always-visible-when-repository-or-builds-are-disabled.yml
deleted file mode 100644
index 5c23b3ef320..00000000000
--- a/changelogs/unreleased/47631-operations-kubernetes-option-is-always-visible-when-repository-or-builds-are-disabled.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Omits operartions and kubernetes item from project sidebar when repository or builds are disabled
-merge_request: 19835
-author:
-type: fixed
diff --git a/changelogs/unreleased/47794-environment-scope-cluster-page.yml b/changelogs/unreleased/47794-environment-scope-cluster-page.yml
deleted file mode 100644
index 75eb7ec209c..00000000000
--- a/changelogs/unreleased/47794-environment-scope-cluster-page.yml
+++ /dev/null
@@ -1,6 +0,0 @@
----
-title: Change environment scope text depending on number of project clusters. Update
- form to only include form-groups
-merge_request:
-author:
-type: changed
diff --git a/changelogs/unreleased/47865-changelog-for-style-updates.yml b/changelogs/unreleased/47865-changelog-for-style-updates.yml
deleted file mode 100644
index 2e4fbbda000..00000000000
--- a/changelogs/unreleased/47865-changelog-for-style-updates.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Minor style changes to personal access token form and scope checkboxes
-merge_request: 20052
-author:
-type: other
diff --git a/changelogs/unreleased/48036-fix-web-ide-blob-crash.yml b/changelogs/unreleased/48036-fix-web-ide-blob-crash.yml
new file mode 100644
index 00000000000..6ff209b5181
--- /dev/null
+++ b/changelogs/unreleased/48036-fix-web-ide-blob-crash.yml
@@ -0,0 +1,5 @@
+---
+title: Fix Web IDE crashing on directories named 'blob'
+merge_request: 20712
+author:
+type: fixed
diff --git a/changelogs/unreleased/48050-add-full-commit-sha.yml b/changelogs/unreleased/48050-add-full-commit-sha.yml
deleted file mode 100644
index 30376fe35e0..00000000000
--- a/changelogs/unreleased/48050-add-full-commit-sha.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Uses long sha version of the merged commit in MR widget copy to clipboard button
-merge_request: 19955
-author:
-type: other
diff --git a/changelogs/unreleased/48100-fix-branch-not-shown.yml b/changelogs/unreleased/48100-fix-branch-not-shown.yml
deleted file mode 100644
index 917c5c23f67..00000000000
--- a/changelogs/unreleased/48100-fix-branch-not-shown.yml
+++ /dev/null
@@ -1,6 +0,0 @@
----
-title: Fix branches are not shown in Merge Request dropdown when preferred language
- is not English
-merge_request: 20016
-author: Hiroyuki Sato
-type: fixed
diff --git a/changelogs/unreleased/48153-date-selection-dialog-broken-when-creating-a-new-milestone.yml b/changelogs/unreleased/48153-date-selection-dialog-broken-when-creating-a-new-milestone.yml
deleted file mode 100644
index 13ab5b0467d..00000000000
--- a/changelogs/unreleased/48153-date-selection-dialog-broken-when-creating-a-new-milestone.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Prevent browser autocomplete for milestone date fields
-merge_request:
-author:
-type: fixed
diff --git a/changelogs/unreleased/48237-toggle-file-comments.yml b/changelogs/unreleased/48237-toggle-file-comments.yml
deleted file mode 100644
index 2e893aad0b2..00000000000
--- a/changelogs/unreleased/48237-toggle-file-comments.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fixes toggle discussion button not expanding collapsed discussions
-merge_request: 20452
-author:
-type: fixed
diff --git a/changelogs/unreleased/48378-avatar-upload.yml b/changelogs/unreleased/48378-avatar-upload.yml
deleted file mode 100644
index 1e359ee72d5..00000000000
--- a/changelogs/unreleased/48378-avatar-upload.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fixes issue with uploading same image to Profile Avatar twice
-merge_request: 20161
-author: Chirag Bhatia
-type: fixed
diff --git a/changelogs/unreleased/48497-merge-request-refactor-displays-changes-dropdown-incorrectly.yml b/changelogs/unreleased/48497-merge-request-refactor-displays-changes-dropdown-incorrectly.yml
deleted file mode 100644
index 41af2f8cc4f..00000000000
--- a/changelogs/unreleased/48497-merge-request-refactor-displays-changes-dropdown-incorrectly.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fixed Merge request changes dropdown displays incorrectly
-merge_request: 20237
-author: Constance Okoghenun
-type: fixed
diff --git a/changelogs/unreleased/48515-sql-queries-are-not-shown-from-the-performance-bar-in-safari.yml b/changelogs/unreleased/48515-sql-queries-are-not-shown-from-the-performance-bar-in-safari.yml
deleted file mode 100644
index 65c59dbf31f..00000000000
--- a/changelogs/unreleased/48515-sql-queries-are-not-shown-from-the-performance-bar-in-safari.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix performance bar modal visibility in Safari
-merge_request:
-author:
-type: fixed
diff --git a/changelogs/unreleased/48578-disable-gcp-free-credit-banner-at-instance-level.yml b/changelogs/unreleased/48578-disable-gcp-free-credit-banner-at-instance-level.yml
deleted file mode 100644
index 575767df912..00000000000
--- a/changelogs/unreleased/48578-disable-gcp-free-credit-banner-at-instance-level.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Add option to hide third party offers in admin application settings
-merge_request: 20379
-author:
-type: added
diff --git a/changelogs/unreleased/48603-merge-request-refactor-title-and-copy-to-clipboard-button-are-behind-the-action-buttons.yml b/changelogs/unreleased/48603-merge-request-refactor-title-and-copy-to-clipboard-button-are-behind-the-action-buttons.yml
deleted file mode 100644
index 792c7814f7e..00000000000
--- a/changelogs/unreleased/48603-merge-request-refactor-title-and-copy-to-clipboard-button-are-behind-the-action-buttons.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix overlapping file title and file actions in MR changes tag
-merge_request:
-author:
-type: fixed
diff --git a/changelogs/unreleased/48634-header-navbar-line-separator-is-missing.yml b/changelogs/unreleased/48634-header-navbar-line-separator-is-missing.yml
deleted file mode 100644
index 92d9295982e..00000000000
--- a/changelogs/unreleased/48634-header-navbar-line-separator-is-missing.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Line separator to the left of the 'Admin area' wrench icon had vanished
-merge_request: 20282
-author: bitsapien
-type: fixed
diff --git a/changelogs/unreleased/48661-node-6-and-7-compatibility-broken-by-recent-monaco-editor-upgrade.yml b/changelogs/unreleased/48661-node-6-and-7-compatibility-broken-by-recent-monaco-editor-upgrade.yml
deleted file mode 100644
index 36a4b5f754d..00000000000
--- a/changelogs/unreleased/48661-node-6-and-7-compatibility-broken-by-recent-monaco-editor-upgrade.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Resolve compatibility issues with node 6
-merge_request: 20461
-author:
-type: fixed
diff --git a/changelogs/unreleased/48670-application-settings-may-not-be-invalidated-if-migrations-are-run.yml b/changelogs/unreleased/48670-application-settings-may-not-be-invalidated-if-migrations-are-run.yml
deleted file mode 100644
index f4267582f89..00000000000
--- a/changelogs/unreleased/48670-application-settings-may-not-be-invalidated-if-migrations-are-run.yml
+++ /dev/null
@@ -1,6 +0,0 @@
----
-title: Stop relying on migrations in the CacheableAttributes cache key and cache attributes
- for 1 minute instead
-merge_request: 20389
-author:
-type: fixed
diff --git a/changelogs/unreleased/48677-also-check-auto_sign_in_with_provider.yml b/changelogs/unreleased/48677-also-check-auto_sign_in_with_provider.yml
deleted file mode 100644
index 3021fe6b9c8..00000000000
--- a/changelogs/unreleased/48677-also-check-auto_sign_in_with_provider.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Load Devise with Omniauth when auto_sign_in_with_provider is configured
-merge_request: 20302
-author:
-type: fixed
diff --git a/changelogs/unreleased/48745-project-exports-fail-when-uploads-have-been-migrated-to-object-storage.yml b/changelogs/unreleased/48745-project-exports-fail-when-uploads-have-been-migrated-to-object-storage.yml
deleted file mode 100644
index 7552e0d3878..00000000000
--- a/changelogs/unreleased/48745-project-exports-fail-when-uploads-have-been-migrated-to-object-storage.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Add uploader support to Import/Export uploads
-merge_request: 20484
-author:
-type: added
diff --git a/changelogs/unreleased/48789-remove-event-listeners-scroll.yml b/changelogs/unreleased/48789-remove-event-listeners-scroll.yml
deleted file mode 100644
index 9cc3f7adc36..00000000000
--- a/changelogs/unreleased/48789-remove-event-listeners-scroll.yml
+++ /dev/null
@@ -1,6 +0,0 @@
----
-title: Improves performance on Merge Request diff tab by removing the scroll event
- listeners being added to every file
-merge_request:
-author:
-type: performance
diff --git a/changelogs/unreleased/48817-fix-mr-changes-discussion-navigation.yml b/changelogs/unreleased/48817-fix-mr-changes-discussion-navigation.yml
new file mode 100644
index 00000000000..ec4b843b863
--- /dev/null
+++ b/changelogs/unreleased/48817-fix-mr-changes-discussion-navigation.yml
@@ -0,0 +1,5 @@
+---
+title: Fix navigation to First and Next discussion on MR Changes tab
+merge_request: 20434
+author:
+type: fixed
diff --git a/changelogs/unreleased/48825-performance.yml b/changelogs/unreleased/48825-performance.yml
deleted file mode 100644
index 428852f6f8b..00000000000
--- a/changelogs/unreleased/48825-performance.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-title: Improves performance of mr code, by fixing the state being mutated outside
- of the store in the util function trimFirstCharOfLineContent and in map operations.
- Avoids map operation in an empty array. Adds specs to the trimFirstCharOfLineContent
- function
-merge_request: 20380
-author: filipa
-type: performance
diff --git a/changelogs/unreleased/48894-fix-rss-button-interaction.yml b/changelogs/unreleased/48894-fix-rss-button-interaction.yml
deleted file mode 100644
index 546a4233d7e..00000000000
--- a/changelogs/unreleased/48894-fix-rss-button-interaction.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix RSS button interaction on Dashboard, Project and Group activities
-merge_request: 20549
-author:
-type: fixed
diff --git a/changelogs/unreleased/48932-disable-saml-if-omniauth-is-disabled.yml b/changelogs/unreleased/48932-disable-saml-if-omniauth-is-disabled.yml
new file mode 100644
index 00000000000..0466debea65
--- /dev/null
+++ b/changelogs/unreleased/48932-disable-saml-if-omniauth-is-disabled.yml
@@ -0,0 +1,5 @@
+---
+title: Disable SAML and Bitbucket if OmniAuth is disabled
+merge_request: 20608
+author:
+type: fixed
diff --git a/changelogs/unreleased/48951-clean-up.yml b/changelogs/unreleased/48951-clean-up.yml
deleted file mode 100644
index 0102cd43f96..00000000000
--- a/changelogs/unreleased/48951-clean-up.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Removes unused vuex code in mr refactor and removes unneeded dependencies
-merge_request: 20499
-author:
-type: other
diff --git a/changelogs/unreleased/48978-fix-helm-installation-on-cluster.yml b/changelogs/unreleased/48978-fix-helm-installation-on-cluster.yml
deleted file mode 100644
index f786d9e2235..00000000000
--- a/changelogs/unreleased/48978-fix-helm-installation-on-cluster.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fixes base command used in Helm installations
-merge_request: 20471
-author:
-type: fixed
diff --git a/changelogs/unreleased/49272-sanitize-git-url-in-import-errors.yml b/changelogs/unreleased/49272-sanitize-git-url-in-import-errors.yml
new file mode 100644
index 00000000000..c757e55f1cd
--- /dev/null
+++ b/changelogs/unreleased/49272-sanitize-git-url-in-import-errors.yml
@@ -0,0 +1,5 @@
+---
+title: Sanitize git URL in import errors
+merge_request:
+author: Jamie Schembri
+type: fixed
diff --git a/changelogs/unreleased/accept-rf3-2822-compliant-addresses.yml b/changelogs/unreleased/accept-rf3-2822-compliant-addresses.yml
new file mode 100644
index 00000000000..97d017613ba
--- /dev/null
+++ b/changelogs/unreleased/accept-rf3-2822-compliant-addresses.yml
@@ -0,0 +1,5 @@
+---
+title: Emails on push recipients now accepts formats like John Doe <johndoe@example.com>
+merge_request:
+author: George Thomas
+type: added
diff --git a/changelogs/unreleased/add-missing-index-for-deployments.yml b/changelogs/unreleased/add-missing-index-for-deployments.yml
deleted file mode 100644
index 7863c0ee039..00000000000
--- a/changelogs/unreleased/add-missing-index-for-deployments.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Add index on deployable_type/id for deployments
-merge_request:
-author:
-type: performance
diff --git a/changelogs/unreleased/add-more-rebase-logging.yml b/changelogs/unreleased/add-more-rebase-logging.yml
deleted file mode 100644
index a7d1c3aa664..00000000000
--- a/changelogs/unreleased/add-more-rebase-logging.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Add more detailed logging to githost.log when rebasing
-merge_request:
-author:
-type: other
diff --git a/changelogs/unreleased/add-title-placeholder-for-new-issues.yml b/changelogs/unreleased/add-title-placeholder-for-new-issues.yml
deleted file mode 100644
index ce9e3b4ac18..00000000000
--- a/changelogs/unreleased/add-title-placeholder-for-new-issues.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Add title placeholder for new issues
-merge_request: 20271
-author: George Tsiolis
-type: changed
diff --git a/changelogs/unreleased/add-total-time-flat-printer-for-profiling.yml b/changelogs/unreleased/add-total-time-flat-printer-for-profiling.yml
new file mode 100644
index 00000000000..37a4e31896e
--- /dev/null
+++ b/changelogs/unreleased/add-total-time-flat-printer-for-profiling.yml
@@ -0,0 +1,6 @@
+---
+title: Add a Gitlab::Profiler.print_by_total_time convenience method for profiling
+ from a Rails console
+merge_request:
+author:
+type: other
diff --git a/changelogs/unreleased/an-no-healthcheck-until-brooklyn.yml b/changelogs/unreleased/an-no-healthcheck-until-brooklyn.yml
deleted file mode 100644
index 4942688d00f..00000000000
--- a/changelogs/unreleased/an-no-healthcheck-until-brooklyn.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Remove healthchecks from prometheus endpoint
-merge_request: 20565
-author:
-type: fixed
diff --git a/changelogs/unreleased/api-minimal-access-level.yml b/changelogs/unreleased/api-minimal-access-level.yml
new file mode 100644
index 00000000000..43cab246d69
--- /dev/null
+++ b/changelogs/unreleased/api-minimal-access-level.yml
@@ -0,0 +1,5 @@
+---
+title: Add filter for minimal access level in groups and projects API
+merge_request: 20478
+author: Marko, Peter
+type: added
diff --git a/changelogs/unreleased/author-doc-fix.yml b/changelogs/unreleased/author-doc-fix.yml
deleted file mode 100644
index 83521543239..00000000000
--- a/changelogs/unreleased/author-doc-fix.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix fields for author & assignee in MR API docs.
-merge_request: 19798
-author: gfyoung
-type: fixed
diff --git a/changelogs/unreleased/backstage-gb-stages-position-migration-clean-up.yml b/changelogs/unreleased/backstage-gb-stages-position-migration-clean-up.yml
deleted file mode 100644
index d2ada88870b..00000000000
--- a/changelogs/unreleased/backstage-gb-stages-position-migration-clean-up.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fully migrate pipeline stages position
-merge_request: 19369
-author:
-type: performance
diff --git a/changelogs/unreleased/bjk-48176_ruby_gc.yml b/changelogs/unreleased/bjk-48176_ruby_gc.yml
deleted file mode 100644
index 45c6338df81..00000000000
--- a/changelogs/unreleased/bjk-48176_ruby_gc.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Cleanup Prometheus ruby metrics
-merge_request: 20039
-author: Ben Kochie
-type: fixed
diff --git a/changelogs/unreleased/blackst0ne-add-gemfile-rails5-lock-check.yml b/changelogs/unreleased/blackst0ne-add-gemfile-rails5-lock-check.yml
deleted file mode 100644
index 69d49f3e3e0..00000000000
--- a/changelogs/unreleased/blackst0ne-add-gemfile-rails5-lock-check.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Add CI job to check Gemfile.rails5.lock
-merge_request: 19605
-author: "@blackst0ne"
-type: other
diff --git a/changelogs/unreleased/blackst0ne-bump-grape-path-helpers-gem-to-1-0-5.yml b/changelogs/unreleased/blackst0ne-bump-grape-path-helpers-gem-to-1-0-5.yml
deleted file mode 100644
index 9d975ff81bf..00000000000
--- a/changelogs/unreleased/blackst0ne-bump-grape-path-helpers-gem-to-1-0-5.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Bump grape-path-helpers to 1.0.5
-merge_request: 19604
-author: "@blackst0ne"
-type: other
diff --git a/changelogs/unreleased/blackst0ne-fix-protect-from-forgery-in-application-controller.yml b/changelogs/unreleased/blackst0ne-fix-protect-from-forgery-in-application-controller.yml
deleted file mode 100644
index da75ea8b09e..00000000000
--- a/changelogs/unreleased/blackst0ne-fix-protect-from-forgery-in-application-controller.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: "[Rails5] Force the callback run first"
-merge_request: 20055
-author: "@blackst0ne"
-type: fixed
diff --git a/changelogs/unreleased/blackst0ne-rails5-activerecord-statementinvalid-mysql2-error-expression-1-of-select-list-is-not-in-group-by-clause.yml b/changelogs/unreleased/blackst0ne-rails5-activerecord-statementinvalid-mysql2-error-expression-1-of-select-list-is-not-in-group-by-clause.yml
deleted file mode 100644
index d9cccc49830..00000000000
--- a/changelogs/unreleased/blackst0ne-rails5-activerecord-statementinvalid-mysql2-error-expression-1-of-select-list-is-not-in-group-by-clause.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: "[Rails5] Fix milestone GROUP BY query"
-merge_request: 20256
-author: "@blackst0ne"
-type: fixed
diff --git a/changelogs/unreleased/blackst0ne-rails5-expected-search-search-seed_project-got-nil.yml b/changelogs/unreleased/blackst0ne-rails5-expected-search-search-seed_project-got-nil.yml
deleted file mode 100644
index e7bb2703b03..00000000000
--- a/changelogs/unreleased/blackst0ne-rails5-expected-search-search-seed_project-got-nil.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: "[Rails5] Fix sessions_controller_spec"
-merge_request: 19936
-author: "@blackst0ne"
-type: fixed
diff --git a/changelogs/unreleased/blackst0ne-rails5-expected-the-response-to-have-status-code-ok-but-it-was-404.yml b/changelogs/unreleased/blackst0ne-rails5-expected-the-response-to-have-status-code-ok-but-it-was-404.yml
deleted file mode 100644
index fad15de2dd5..00000000000
--- a/changelogs/unreleased/blackst0ne-rails5-expected-the-response-to-have-status-code-ok-but-it-was-404.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: "[Rails5] Set request.format for artifacts_controller"
-merge_request: 19937
-author: "@blackst0ne"
-type: fixed
diff --git a/changelogs/unreleased/blackst0ne-rails5-fix-blob-requests-format.yml b/changelogs/unreleased/blackst0ne-rails5-fix-blob-requests-format.yml
deleted file mode 100644
index a83aa03606a..00000000000
--- a/changelogs/unreleased/blackst0ne-rails5-fix-blob-requests-format.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: "[Rails5] Explicitly set request.format for blob_controller"
-merge_request: 19876
-author: "@blackst0ne"
-type: fixed
diff --git a/changelogs/unreleased/blackst0ne-rails5-fix-data-store-spec.yml b/changelogs/unreleased/blackst0ne-rails5-fix-data-store-spec.yml
deleted file mode 100644
index 403c3764321..00000000000
--- a/changelogs/unreleased/blackst0ne-rails5-fix-data-store-spec.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: '[Rails5] Fix "-1 is not a valid data_store"'
-merge_request: 19917
-author: "@blackst0ne"
-type: fixed
diff --git a/changelogs/unreleased/blackst0ne-rails5-fix-optimistic-lock-values.yml b/changelogs/unreleased/blackst0ne-rails5-fix-optimistic-lock-values.yml
deleted file mode 100644
index 1915dff73ab..00000000000
--- a/changelogs/unreleased/blackst0ne-rails5-fix-optimistic-lock-values.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: "[Rails5] Fix optimistic lock value"
-merge_request: 19878
-author: "@blackst0ne"
-type: fixed
diff --git a/changelogs/unreleased/blackst0ne-rails5-fix-pipeline-schedules-controller-spec.yml b/changelogs/unreleased/blackst0ne-rails5-fix-pipeline-schedules-controller-spec.yml
deleted file mode 100644
index 7a2b19ad681..00000000000
--- a/changelogs/unreleased/blackst0ne-rails5-fix-pipeline-schedules-controller-spec.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: "[Rails5] Fix pipeline_schedules_controller_spec"
-merge_request: 19919
-author: "@blackst0ne"
-type: fixed
diff --git a/changelogs/unreleased/blackst0ne-rails5-fix-snippets-finder.yml b/changelogs/unreleased/blackst0ne-rails5-fix-snippets-finder.yml
deleted file mode 100644
index 597b85de26f..00000000000
--- a/changelogs/unreleased/blackst0ne-rails5-fix-snippets-finder.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: "[Rails5] Fix snippets_finder arel queries"
-merge_request: 19796
-author: "@blackst0ne"
-type: fixed
diff --git a/changelogs/unreleased/blackst0ne-rails5-found-new-routes-that-could-cause-conflicts-with-existing-namespaced-routes.yml b/changelogs/unreleased/blackst0ne-rails5-found-new-routes-that-could-cause-conflicts-with-existing-namespaced-routes.yml
deleted file mode 100644
index c8d916af824..00000000000
--- a/changelogs/unreleased/blackst0ne-rails5-found-new-routes-that-could-cause-conflicts-with-existing-namespaced-routes.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: "[Rails5] Fix ActionCable '/cable' mountpoint conflict"
-merge_request: 20015
-author: "@blackst0ne"
-type: fixed
diff --git a/changelogs/unreleased/blackst0ne-rails5-invalid-single-table-inheritance-type-group-is-not-a-subclass-of-namespace.yml b/changelogs/unreleased/blackst0ne-rails5-invalid-single-table-inheritance-type-group-is-not-a-subclass-of-namespace.yml
deleted file mode 100644
index 92e6ce35941..00000000000
--- a/changelogs/unreleased/blackst0ne-rails5-invalid-single-table-inheritance-type-group-is-not-a-subclass-of-namespace.yml
+++ /dev/null
@@ -1,6 +0,0 @@
----
-title: "[Rails5] Invalid single-table inheritance type: Group is not a subclass of
- Namespace"
-merge_request: 19918
-author: "@blackst0ne"
-type: fixed
diff --git a/changelogs/unreleased/blackst0ne-rails5-set-request-format-in--commits-controller.yml b/changelogs/unreleased/blackst0ne-rails5-set-request-format-in--commits-controller.yml
deleted file mode 100644
index 3f8f8fd5d66..00000000000
--- a/changelogs/unreleased/blackst0ne-rails5-set-request-format-in--commits-controller.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: "[Rails5] Set request.format in commits_controller"
-merge_request: 20023
-author: "@blackst0ne"
-type: fixed
diff --git a/changelogs/unreleased/blackst0ne-replace-sidekiq-inline-with-perform-enqueued-jobs.yml b/changelogs/unreleased/blackst0ne-replace-sidekiq-inline-with-perform-enqueued-jobs.yml
new file mode 100644
index 00000000000..69e6b7d815a
--- /dev/null
+++ b/changelogs/unreleased/blackst0ne-replace-sidekiq-inline-with-perform-enqueued-jobs.yml
@@ -0,0 +1,5 @@
+---
+title: Replace 'Sidekiq::Testing.inline!' with 'perform_enqueued_jobs'
+merge_request: 20768
+author: "@blackst0ne"
+type: other
diff --git a/changelogs/unreleased/build-chunks-on-object-storage.yml b/changelogs/unreleased/build-chunks-on-object-storage.yml
deleted file mode 100644
index 9f36dfee378..00000000000
--- a/changelogs/unreleased/build-chunks-on-object-storage.yml
+++ /dev/null
@@ -1,6 +0,0 @@
----
-title: Use object storage as the first class persistable store for new live trace
- architecture
-merge_request: 19515
-author:
-type: changed
diff --git a/changelogs/unreleased/bump-carrierwave-to-1-2-3.yml b/changelogs/unreleased/bump-carrierwave-to-1-2-3.yml
deleted file mode 100644
index 373ac48553e..00000000000
--- a/changelogs/unreleased/bump-carrierwave-to-1-2-3.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Bump carrierwave gem verion to 1.2.3
-merge_request: 20287
-author:
-type: performance
diff --git a/changelogs/unreleased/bvl-fix-maintainer-push-rejected.yml b/changelogs/unreleased/bvl-fix-maintainer-push-rejected.yml
deleted file mode 100644
index 54154ad2449..00000000000
--- a/changelogs/unreleased/bvl-fix-maintainer-push-rejected.yml
+++ /dev/null
@@ -1,6 +0,0 @@
----
-title: Fix bug where maintainer would not be allowed to push to forks with merge requests
- that have `Allow maintainer edits` enabled.
-merge_request: 18968
-author:
-type: fixed
diff --git a/changelogs/unreleased/bvl-graphql-nested-merge-request.yml b/changelogs/unreleased/bvl-graphql-nested-merge-request.yml
deleted file mode 100644
index f0f0488d31a..00000000000
--- a/changelogs/unreleased/bvl-graphql-nested-merge-request.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Allow querying a single merge request within a project
-merge_request: 19853
-author:
-type: changed
diff --git a/changelogs/unreleased/bvl-graphql-permissions.yml b/changelogs/unreleased/bvl-graphql-permissions.yml
deleted file mode 100644
index 42d5e24bb15..00000000000
--- a/changelogs/unreleased/bvl-graphql-permissions.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: 'Expose permissions of the current user on resources in GraphQL'
-merge_request: 20152
-author:
-type: added
diff --git a/changelogs/unreleased/bvl-graphql-pipeline-lists.yml b/changelogs/unreleased/bvl-graphql-pipeline-lists.yml
deleted file mode 100644
index be258dc12ad..00000000000
--- a/changelogs/unreleased/bvl-graphql-pipeline-lists.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Add pipeline lists to GraphQL
-merge_request: 20249
-author:
-type: added
diff --git a/changelogs/unreleased/bvl-preload-parents-after-pagination.yml b/changelogs/unreleased/bvl-preload-parents-after-pagination.yml
deleted file mode 100644
index ff3d4716d34..00000000000
--- a/changelogs/unreleased/bvl-preload-parents-after-pagination.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Reduce the number of queries when searching for groups
-merge_request: 20398
-author:
-type: performance
diff --git a/changelogs/unreleased/bw-enable-commonmark.yml b/changelogs/unreleased/bw-enable-commonmark.yml
deleted file mode 100644
index 89252e5063d..00000000000
--- a/changelogs/unreleased/bw-enable-commonmark.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Use CommonMark syntax and rendering for new Markdown content
-merge_request: 19331
-author:
-type: added
diff --git a/changelogs/unreleased/cache-doc-fix.yml b/changelogs/unreleased/cache-doc-fix.yml
deleted file mode 100644
index db4726a92e9..00000000000
--- a/changelogs/unreleased/cache-doc-fix.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: 'Remove incorrect CI doc re: PowerShell'
-merge_request: 19622
-author: gfyoung
-type: fixed
diff --git a/changelogs/unreleased/ce-5024-filename-search.yml b/changelogs/unreleased/ce-5024-filename-search.yml
deleted file mode 100644
index a8bf9b1f802..00000000000
--- a/changelogs/unreleased/ce-5024-filename-search.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Add filename filtering to code search
-merge_request: 19509
-author:
-type: added
diff --git a/changelogs/unreleased/close-revoke-deploy-token-modal-on-escape-keypress.yml b/changelogs/unreleased/close-revoke-deploy-token-modal-on-escape-keypress.yml
deleted file mode 100644
index 98316cae406..00000000000
--- a/changelogs/unreleased/close-revoke-deploy-token-modal-on-escape-keypress.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Close revoke deploy token modal on escape keypress
-merge_request: 20347
-author: George Tsiolis
-type: changed
diff --git a/changelogs/unreleased/commits_api_with_stats.yml b/changelogs/unreleased/commits_api_with_stats.yml
deleted file mode 100644
index 4357f1a6305..00000000000
--- a/changelogs/unreleased/commits_api_with_stats.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Added with_statsoption for GET /projects/:id/repository/commits
-merge_request:
-author:
-type: added
diff --git a/changelogs/unreleased/cr-add-locked-state-to-MR.yml b/changelogs/unreleased/cr-add-locked-state-to-MR.yml
deleted file mode 100644
index f290ddc0b87..00000000000
--- a/changelogs/unreleased/cr-add-locked-state-to-MR.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Adds the `locked` state to the merge request API so that it can be used as a search filter.
-merge_request: 20186
-author:
-type: fixed
diff --git a/changelogs/unreleased/cr-keep-issue-labels.yml b/changelogs/unreleased/cr-keep-issue-labels.yml
deleted file mode 100644
index 051e7faffea..00000000000
--- a/changelogs/unreleased/cr-keep-issue-labels.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Keeps the label on an issue when the issue is moved.
-merge_request: 20036
-author:
-type: fixed
diff --git a/changelogs/unreleased/da-port-cte-to-ce.yml b/changelogs/unreleased/da-port-cte-to-ce.yml
deleted file mode 100644
index 6fa759fcf7d..00000000000
--- a/changelogs/unreleased/da-port-cte-to-ce.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Add Gitlab::SQL:CTE for easily building CTE statements
-merge_request:
-author:
-type: added
diff --git a/changelogs/unreleased/db-configure-after-drop-tables.yml b/changelogs/unreleased/db-configure-after-drop-tables.yml
deleted file mode 100644
index 00844b334fa..00000000000
--- a/changelogs/unreleased/db-configure-after-drop-tables.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fixes an issue where migrations instead of schema loading were run
-merge_request: 20227
-author:
-type: changed
diff --git a/changelogs/unreleased/dm-blockquote-trailing-whitespace.yml b/changelogs/unreleased/dm-blockquote-trailing-whitespace.yml
deleted file mode 100644
index 98ecdde4f4c..00000000000
--- a/changelogs/unreleased/dm-blockquote-trailing-whitespace.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Allow trailing whitespace on blockquote fence lines
-merge_request:
-author:
-type: fixed
diff --git a/changelogs/unreleased/dm-branch-api-can-push.yml b/changelogs/unreleased/dm-branch-api-can-push.yml
deleted file mode 100644
index 3be8962089b..00000000000
--- a/changelogs/unreleased/dm-branch-api-can-push.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Expose whether current user can push into a branch on branches API
-merge_request:
-author:
-type: added
diff --git a/changelogs/unreleased/dm-invalid-active-service-template.yml b/changelogs/unreleased/dm-invalid-active-service-template.yml
deleted file mode 100644
index 8b77fac55b9..00000000000
--- a/changelogs/unreleased/dm-invalid-active-service-template.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Deactivate new KubernetesService created from active template to prevent project creation from failing
-merge_request:
-author:
-type: fixed
diff --git a/changelogs/unreleased/dm-label-reference-period.yml b/changelogs/unreleased/dm-label-reference-period.yml
deleted file mode 100644
index 9fdd590641d..00000000000
--- a/changelogs/unreleased/dm-label-reference-period.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Properly detect label reference if followed by period or question mark
-merge_request:
-author:
-type: fixed
diff --git a/changelogs/unreleased/dm-user-without-projects-performance.yml b/changelogs/unreleased/dm-user-without-projects-performance.yml
deleted file mode 100644
index e7fc0ae6d54..00000000000
--- a/changelogs/unreleased/dm-user-without-projects-performance.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Improve performance of listing users without projects
-merge_request:
-author:
-type: performance
diff --git a/changelogs/unreleased/existing-gcp-accounts.yml b/changelogs/unreleased/existing-gcp-accounts.yml
deleted file mode 100644
index ce396c70b4a..00000000000
--- a/changelogs/unreleased/existing-gcp-accounts.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Add back copy for existing gcp accounts within offer banner
-merge_request:
-author:
-type: changed
diff --git a/changelogs/unreleased/expose-ci-url.yml b/changelogs/unreleased/expose-ci-url.yml
deleted file mode 100644
index b6ad7d18e0d..00000000000
--- a/changelogs/unreleased/expose-ci-url.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Add CI_PIPELINE_URL and CI_JOB_URL
-merge_request: 19618
-author:
-type: added
diff --git a/changelogs/unreleased/feature-oidc-subject-claim.yml b/changelogs/unreleased/feature-oidc-subject-claim.yml
deleted file mode 100644
index e995ca26234..00000000000
--- a/changelogs/unreleased/feature-oidc-subject-claim.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Don't hash user ID in OIDC subject claim
-merge_request: 19784
-author: Markus Koller
-type: changed
diff --git a/changelogs/unreleased/fix-boards-issue-highlight.yml b/changelogs/unreleased/fix-boards-issue-highlight.yml
deleted file mode 100644
index 0cc3faa81ca..00000000000
--- a/changelogs/unreleased/fix-boards-issue-highlight.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix boards issue highlight
-merge_request: 20063
-author: George Tsiolis
-type: changed
diff --git a/changelogs/unreleased/fix-br-decode.yml b/changelogs/unreleased/fix-br-decode.yml
deleted file mode 100644
index 66ecc3deb35..00000000000
--- a/changelogs/unreleased/fix-br-decode.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: mergeError message has been binded using v-html directive
-merge_request: 19058
-author: Murat Dogan
-type: fixed
diff --git a/changelogs/unreleased/fix-filename-for-direct-uploads.yml b/changelogs/unreleased/fix-filename-for-direct-uploads.yml
deleted file mode 100644
index a1bbf3704c0..00000000000
--- a/changelogs/unreleased/fix-filename-for-direct-uploads.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix filename for accelerated uploads
-merge_request:
-author:
-type: fixed
diff --git a/changelogs/unreleased/fix-gb-fix-deserializing-ci-yaml-variables.yml b/changelogs/unreleased/fix-gb-fix-deserializing-ci-yaml-variables.yml
new file mode 100644
index 00000000000..80b069c9251
--- /dev/null
+++ b/changelogs/unreleased/fix-gb-fix-deserializing-ci-yaml-variables.yml
@@ -0,0 +1,5 @@
+---
+title: Fix accessing imported pipeline builds
+merge_request: 20713
+author:
+type: fixed
diff --git a/changelogs/unreleased/fix-gitaly-mr-creation-limits.yml b/changelogs/unreleased/fix-gitaly-mr-creation-limits.yml
deleted file mode 100644
index e903f2e5277..00000000000
--- a/changelogs/unreleased/fix-gitaly-mr-creation-limits.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix merge request diffs when created with gitaly_diff_between enabled
-merge_request:
-author:
-type: fixed
diff --git a/changelogs/unreleased/fix-groups-api-ordering.yml b/changelogs/unreleased/fix-groups-api-ordering.yml
deleted file mode 100644
index 3a6a7f84356..00000000000
--- a/changelogs/unreleased/fix-groups-api-ordering.yml
+++ /dev/null
@@ -1,4 +0,0 @@
-title: Fixed pagination of groups API
-merge_request: 19665
-author: Marko, Peter
-type: added
diff --git a/changelogs/unreleased/fix-last-commit-author-link-is-blue.yml b/changelogs/unreleased/fix-last-commit-author-link-is-blue.yml
deleted file mode 100644
index aaceeaecfb1..00000000000
--- a/changelogs/unreleased/fix-last-commit-author-link-is-blue.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Updated last commit link color
-merge_request: 20234
-author: Constance Okoghenun
-type: fixed
diff --git a/changelogs/unreleased/fix-paragraph-line-height-for-emoji.yml b/changelogs/unreleased/fix-paragraph-line-height-for-emoji.yml
deleted file mode 100644
index 5aaf0fac60e..00000000000
--- a/changelogs/unreleased/fix-paragraph-line-height-for-emoji.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix paragraph line height for emoji
-merge_request: 20137
-author: George Tsiolis
-type: fixed
diff --git a/changelogs/unreleased/fix-performance-problem-of-tags-query.yml b/changelogs/unreleased/fix-performance-problem-of-tags-query.yml
deleted file mode 100644
index 4649775be9c..00000000000
--- a/changelogs/unreleased/fix-performance-problem-of-tags-query.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix performance problem of accessing tag list for projects api endpoints
-merge_request:
-author:
-type: performance
diff --git a/changelogs/unreleased/fix-trace-archive-cron-worker-race-condition.yml b/changelogs/unreleased/fix-trace-archive-cron-worker-race-condition.yml
deleted file mode 100644
index ca8f4252008..00000000000
--- a/changelogs/unreleased/fix-trace-archive-cron-worker-race-condition.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Check if archived trace exist before archive it
-merge_request: 20297
-author:
-type: fixed
diff --git a/changelogs/unreleased/fix-web-ide-disable-markdown-autocomplete.yml b/changelogs/unreleased/fix-web-ide-disable-markdown-autocomplete.yml
deleted file mode 100644
index 6a4d9b6c8c4..00000000000
--- a/changelogs/unreleased/fix-web-ide-disable-markdown-autocomplete.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Disabled Web IDE autocomplete suggestions for Markdown files.
-merge_request:
-author: Isaac Smith
-type: fixed
diff --git a/changelogs/unreleased/fj-43565-wrong-role-displayed.yml b/changelogs/unreleased/fj-43565-wrong-role-displayed.yml
deleted file mode 100644
index 67ff25bc50c..00000000000
--- a/changelogs/unreleased/fj-43565-wrong-role-displayed.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix wrong role badge displayed in projects dashboard
-merge_request: 20374
-author:
-type: fixed
diff --git a/changelogs/unreleased/fj-46278-apply-doorkeeper-scope-patch.yml b/changelogs/unreleased/fj-46278-apply-doorkeeper-scope-patch.yml
deleted file mode 100644
index 1f4de2cb490..00000000000
--- a/changelogs/unreleased/fj-46278-apply-doorkeeper-scope-patch.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix OAuth Application Authorization screen to appear with each access
-merge_request: 20216
-author:
-type: fixed
diff --git a/changelogs/unreleased/fj-46278-enable-doorkeeper-reuse-access-token.yml b/changelogs/unreleased/fj-46278-enable-doorkeeper-reuse-access-token.yml
deleted file mode 100644
index 0994f4de248..00000000000
--- a/changelogs/unreleased/fj-46278-enable-doorkeeper-reuse-access-token.yml
+++ /dev/null
@@ -1,6 +0,0 @@
----
-title: Enable Doorkeeper option to avoid generating new tokens when users login via
- oauth
-merge_request: 20200
-author:
-type: fixed
diff --git a/changelogs/unreleased/fj-48123-fix-gitlab-import.yml b/changelogs/unreleased/fj-48123-fix-gitlab-import.yml
new file mode 100644
index 00000000000..896db2cdcb8
--- /dev/null
+++ b/changelogs/unreleased/fj-48123-fix-gitlab-import.yml
@@ -0,0 +1,5 @@
+---
+title: Fix GitLab project imports not loading due to API timeouts
+merge_request: 20599
+author:
+type: fixed
diff --git a/changelogs/unreleased/fj-49014-wiki-search-error.yml b/changelogs/unreleased/fj-49014-wiki-search-error.yml
new file mode 100644
index 00000000000..a76805cb7f9
--- /dev/null
+++ b/changelogs/unreleased/fj-49014-wiki-search-error.yml
@@ -0,0 +1,5 @@
+---
+title: Fixed bug with invalid repository reference using the wiki search
+merge_request: 20722
+author:
+type: fixed
diff --git a/changelogs/unreleased/fj-bumping-gollum-lib-and-gollum-rugged-adapter.yml b/changelogs/unreleased/fj-bumping-gollum-lib-and-gollum-rugged-adapter.yml
deleted file mode 100644
index 3b4d429707f..00000000000
--- a/changelogs/unreleased/fj-bumping-gollum-lib-and-gollum-rugged-adapter.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fixed bug that allowed to remove other wiki pages if the title had wildcard characters
-merge_request:
-author:
-type: fixed
diff --git a/changelogs/unreleased/fj-web-terminal-ci-build.yml b/changelogs/unreleased/fj-web-terminal-ci-build.yml
deleted file mode 100644
index c3608d4203b..00000000000
--- a/changelogs/unreleased/fj-web-terminal-ci-build.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Add Web Terminal for Ci Builds
-merge_request:
-author: Vicky Chijwani
-type: added
diff --git a/changelogs/unreleased/fl-mr-refactor-performance-improvements.yml b/changelogs/unreleased/fl-mr-refactor-performance-improvements.yml
deleted file mode 100644
index 649d1b5da67..00000000000
--- a/changelogs/unreleased/fl-mr-refactor-performance-improvements.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Structure getters for diff Store properly and adds specs
-merge_request:
-author:
-type: fixed
diff --git a/changelogs/unreleased/frozen-string-app-workers.yml b/changelogs/unreleased/frozen-string-app-workers.yml
deleted file mode 100644
index 48b50cc6ca4..00000000000
--- a/changelogs/unreleased/frozen-string-app-workers.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Enable frozen string in app/workers/*.rb
-merge_request: 19944
-author: gfyoung
-type: other
diff --git a/changelogs/unreleased/frozen-string-enable-app-serializers.yml b/changelogs/unreleased/frozen-string-enable-app-serializers.yml
new file mode 100644
index 00000000000..40c7b695d39
--- /dev/null
+++ b/changelogs/unreleased/frozen-string-enable-app-serializers.yml
@@ -0,0 +1,5 @@
+---
+title: Enable frozen string in app/serializers/**/*.rb
+merge_request: 20726
+author: gfyoung
+type: performance
diff --git a/changelogs/unreleased/frozen-string-enable-app-uploaders.yml b/changelogs/unreleased/frozen-string-enable-app-uploaders.yml
deleted file mode 100644
index d43ca8bed8c..00000000000
--- a/changelogs/unreleased/frozen-string-enable-app-uploaders.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Enable frozen string in apps/validators/*.rb
-merge_request: 20382
-author: gfyoung
-type: other
diff --git a/changelogs/unreleased/frozen-string-enable-app-validators.yml b/changelogs/unreleased/frozen-string-enable-app-validators.yml
deleted file mode 100644
index db480b06d9b..00000000000
--- a/changelogs/unreleased/frozen-string-enable-app-validators.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Enable frozen string in apps/validators/*.rb
-merge_request: 20220
-author: gfyoung
-type: other
diff --git a/changelogs/unreleased/frozen-string-enable-app-workers-2.yml b/changelogs/unreleased/frozen-string-enable-app-workers-2.yml
deleted file mode 100644
index 81de6899d76..00000000000
--- a/changelogs/unreleased/frozen-string-enable-app-workers-2.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Finish enabling frozen string for app/workers/*.rb
-merge_request: 20197
-author: gfyoung
-type: other
diff --git a/changelogs/unreleased/frozen-string-enable-apps-services-inner-even-more.yml b/changelogs/unreleased/frozen-string-enable-apps-services-inner-even-more.yml
new file mode 100644
index 00000000000..cee790a07ff
--- /dev/null
+++ b/changelogs/unreleased/frozen-string-enable-apps-services-inner-even-more.yml
@@ -0,0 +1,5 @@
+---
+title: Enable even more frozen string in app/services/**/*.rb
+merge_request: 20702
+author: gfyoung
+type: performance
diff --git a/changelogs/unreleased/frozen-string-vestigial.yml b/changelogs/unreleased/frozen-string-vestigial.yml
new file mode 100644
index 00000000000..79e92a19a7a
--- /dev/null
+++ b/changelogs/unreleased/frozen-string-vestigial.yml
@@ -0,0 +1,5 @@
+---
+title: Enable frozen string in newly added files to previously processed directories
+merge_request: 20763
+author: gfyoung
+type: performance
diff --git a/changelogs/unreleased/gitaly-commit-count-opt-out.yml b/changelogs/unreleased/gitaly-commit-count-opt-out.yml
deleted file mode 100644
index fd8298b1d7b..00000000000
--- a/changelogs/unreleased/gitaly-commit-count-opt-out.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Move some Gitaly RPC's to opt-out
-merge_request: 19591
-author:
-type: other
diff --git a/changelogs/unreleased/gitaly-opt-out-branch-tag.yml b/changelogs/unreleased/gitaly-opt-out-branch-tag.yml
deleted file mode 100644
index 750fc863eed..00000000000
--- a/changelogs/unreleased/gitaly-opt-out-branch-tag.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Move Gitaly branch/tag/ref RPC's to opt-out
-merge_request: 19644
-author:
-type: other
diff --git a/changelogs/unreleased/gitaly-serverservice-info-timeout.yml b/changelogs/unreleased/gitaly-serverservice-info-timeout.yml
deleted file mode 100644
index 7f2fe8b9c93..00000000000
--- a/changelogs/unreleased/gitaly-serverservice-info-timeout.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Use appropriate timeout on Gitaly server info checks, avoid error on timeout
-merge_request: 20552
-author:
-type: fixed
diff --git a/changelogs/unreleased/gitaly-timeouts.yml b/changelogs/unreleased/gitaly-timeouts.yml
deleted file mode 100644
index ac8008faa2d..00000000000
--- a/changelogs/unreleased/gitaly-timeouts.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Updated Gitaly fail-fast timeout values
-merge_request: !20259
-author:
-type: performance
diff --git a/changelogs/unreleased/hangouts_chat_integration.yml b/changelogs/unreleased/hangouts_chat_integration.yml
new file mode 100644
index 00000000000..bf3484a6d02
--- /dev/null
+++ b/changelogs/unreleased/hangouts_chat_integration.yml
@@ -0,0 +1,5 @@
+---
+title: Add Hangouts Chat integration
+merge_request: 20290
+author: Kukovskii Vladimir
+type: added
diff --git a/changelogs/unreleased/highlight-cluster-settings-message.yml b/changelogs/unreleased/highlight-cluster-settings-message.yml
deleted file mode 100644
index 4e029941c51..00000000000
--- a/changelogs/unreleased/highlight-cluster-settings-message.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Highlight cluster settings message
-merge_request: 19996
-author: George Tsiolis
-type: changed
diff --git a/changelogs/unreleased/ide-commit-actions-update.yml b/changelogs/unreleased/ide-commit-actions-update.yml
deleted file mode 100644
index 35bee94e156..00000000000
--- a/changelogs/unreleased/ide-commit-actions-update.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Improve Web IDE commit flow
-merge_request:
-author:
-type: changed
diff --git a/changelogs/unreleased/ide-merge-request-info.yml b/changelogs/unreleased/ide-merge-request-info.yml
deleted file mode 100644
index 104f48ae309..00000000000
--- a/changelogs/unreleased/ide-merge-request-info.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Display merge request title & description in Web IDE
-merge_request:
-author:
-type: added
diff --git a/changelogs/unreleased/jprovazn-delete-upload-worker.yml b/changelogs/unreleased/jprovazn-delete-upload-worker.yml
deleted file mode 100644
index 52916482d32..00000000000
--- a/changelogs/unreleased/jprovazn-delete-upload-worker.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Remove deprecated object_storage_upload queue.
-merge_request:
-author:
-type: removed
diff --git a/changelogs/unreleased/jprovazn-direct-upload.yml b/changelogs/unreleased/jprovazn-direct-upload.yml
deleted file mode 100644
index 57f6d1e07c3..00000000000
--- a/changelogs/unreleased/jprovazn-direct-upload.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Support direct_upload for generic uploads
-merge_request:
-author:
-type: added
diff --git a/changelogs/unreleased/jprovazn-extra-line.yml b/changelogs/unreleased/jprovazn-extra-line.yml
deleted file mode 100644
index 2628620f8ec..00000000000
--- a/changelogs/unreleased/jprovazn-extra-line.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Don't show context button for diffs of deleted files.
-merge_request:
-author:
-type: fixed
diff --git a/changelogs/unreleased/jprovazn-fix-mr-caching.yml b/changelogs/unreleased/jprovazn-fix-mr-caching.yml
deleted file mode 100644
index 7ad7ed54143..00000000000
--- a/changelogs/unreleased/jprovazn-fix-mr-caching.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Invalidate merge request diffs cache if diff data change.
-merge_request:
-author:
-type: fixed
diff --git a/changelogs/unreleased/jprovazn-label-links-update.yml b/changelogs/unreleased/jprovazn-label-links-update.yml
deleted file mode 100644
index 75fb46ede6b..00000000000
--- a/changelogs/unreleased/jprovazn-label-links-update.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix cross-project label references.
-merge_request:
-author:
-type: fixed
diff --git a/changelogs/unreleased/jprovazn-upload-symlink.yml b/changelogs/unreleased/jprovazn-upload-symlink.yml
deleted file mode 100644
index 265791d332f..00000000000
--- a/changelogs/unreleased/jprovazn-upload-symlink.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Add /uploads subdirectory to allowed upload paths.
-merge_request:
-author:
-type: fixed
diff --git a/changelogs/unreleased/jr-48133-web-ide-commit-ellipsis.yml b/changelogs/unreleased/jr-48133-web-ide-commit-ellipsis.yml
deleted file mode 100644
index ac58eaccaaf..00000000000
--- a/changelogs/unreleased/jr-48133-web-ide-commit-ellipsis.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Add ellispsis to web ide commit button
-merge_request: 20030
-author:
-type: other
diff --git a/changelogs/unreleased/jupyter-image.yml b/changelogs/unreleased/jupyter-image.yml
new file mode 100644
index 00000000000..8aeefd603d8
--- /dev/null
+++ b/changelogs/unreleased/jupyter-image.yml
@@ -0,0 +1,5 @@
+---
+title: Rubix, scikit-learn, tensorflow & other useful libraries pre-installed with JupyterHub
+merge_request: 20714
+author: Amit Rathi
+type: changed
diff --git a/changelogs/unreleased/limit-metrics-content-type.yml b/changelogs/unreleased/limit-metrics-content-type.yml
deleted file mode 100644
index 42cb4347771..00000000000
--- a/changelogs/unreleased/limit-metrics-content-type.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Limit the action suffixes in transaction metrics
-merge_request:
-author:
-type: fixed
diff --git a/changelogs/unreleased/more-group-api-sorting-options.yml b/changelogs/unreleased/more-group-api-sorting-options.yml
deleted file mode 100644
index b29f76a65a9..00000000000
--- a/changelogs/unreleased/more-group-api-sorting-options.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Added id sorting option to GET groups and subgroups API
-merge_request: 19665
-author: Marko, Peter
-type: added
diff --git a/changelogs/unreleased/move-boards-modal-empty-state-vue-component.yml b/changelogs/unreleased/move-boards-modal-empty-state-vue-component.yml
deleted file mode 100644
index 54a61d7c914..00000000000
--- a/changelogs/unreleased/move-boards-modal-empty-state-vue-component.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Move boards modal EmptyState vue component
-merge_request: 20068
-author: George Tsiolis
-type: performance
diff --git a/changelogs/unreleased/no-multi-assign-enable.yml b/changelogs/unreleased/no-multi-assign-enable.yml
deleted file mode 100644
index bb9c69b18e7..00000000000
--- a/changelogs/unreleased/no-multi-assign-enable.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Enable no-multi-assignment in JS files
-merge_request: 19808
-author: gfyoung
-type: other
diff --git a/changelogs/unreleased/no-multi-assign-follow-up.yml b/changelogs/unreleased/no-multi-assign-follow-up.yml
deleted file mode 100644
index 817760ff649..00000000000
--- a/changelogs/unreleased/no-multi-assign-follow-up.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Improve no-multi-assignment fixes after enabling rule
-merge_request: 19915
-author: gfyoung
-type: other
diff --git a/changelogs/unreleased/no-restricted-globals-enable.yml b/changelogs/unreleased/no-restricted-globals-enable.yml
deleted file mode 100644
index 1fa2eac0d03..00000000000
--- a/changelogs/unreleased/no-restricted-globals-enable.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Enable no-restricted globals in JS files
-merge_request: 19877
-author: gfyoung
-type: other
diff --git a/changelogs/unreleased/osw-delete-non-latest-mr-diff-files-migration.yml b/changelogs/unreleased/osw-delete-non-latest-mr-diff-files-migration.yml
deleted file mode 100644
index e4cbae1a109..00000000000
--- a/changelogs/unreleased/osw-delete-non-latest-mr-diff-files-migration.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Schedule workers to delete non-latest diffs in post-migration
-merge_request:
-author:
-type: other
diff --git a/changelogs/unreleased/osw-delete-non-latest-mr-diff-files-upon-merge.yml b/changelogs/unreleased/osw-delete-non-latest-mr-diff-files-upon-merge.yml
deleted file mode 100644
index 3e752125f3a..00000000000
--- a/changelogs/unreleased/osw-delete-non-latest-mr-diff-files-upon-merge.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Delete non-latest merge request diff files upon merge
-merge_request:
-author:
-type: other
diff --git a/changelogs/unreleased/osw-fallback-to-collection-when-no-diff-refs.yml b/changelogs/unreleased/osw-fallback-to-collection-when-no-diff-refs.yml
deleted file mode 100644
index 71a2d94fc55..00000000000
--- a/changelogs/unreleased/osw-fallback-to-collection-when-no-diff-refs.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Render MR page when diffs cannot be fetched from the database or the git repository
-merge_request: 20680
-author:
-type: fixed
diff --git a/changelogs/unreleased/osw-mark-as-merged-as-first-post-merge-action.yml b/changelogs/unreleased/osw-mark-as-merged-as-first-post-merge-action.yml
deleted file mode 100644
index 2049afc3d44..00000000000
--- a/changelogs/unreleased/osw-mark-as-merged-as-first-post-merge-action.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Mark MR as merged regardless of errors when closing issues
-merge_request:
-author:
-type: fixed
diff --git a/changelogs/unreleased/perf-wiki-pattern-once.yml b/changelogs/unreleased/perf-wiki-pattern-once.yml
deleted file mode 100644
index fb4085a06ae..00000000000
--- a/changelogs/unreleased/perf-wiki-pattern-once.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Improve render performance of large wiki pages
-merge_request: 20465
-author: Peter Leitzen
-type: performance
diff --git a/changelogs/unreleased/pr-importer-io-extra-error-handling.yml b/changelogs/unreleased/pr-importer-io-extra-error-handling.yml
deleted file mode 100644
index 2f7121b2840..00000000000
--- a/changelogs/unreleased/pr-importer-io-extra-error-handling.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Ensure MR diffs always exist in the PR importer
-merge_request:
-author:
-type: fixed
diff --git a/changelogs/unreleased/prefer-destructuring-fix.yml b/changelogs/unreleased/prefer-destructuring-fix.yml
deleted file mode 100644
index 452e04f553e..00000000000
--- a/changelogs/unreleased/prefer-destructuring-fix.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Enable prefer-structuring in JS files
-merge_request: 19943
-author: gfyoung
-type: other
diff --git a/changelogs/unreleased/project-dropdown-list-overflow.yml b/changelogs/unreleased/project-dropdown-list-overflow.yml
new file mode 100644
index 00000000000..9b74a68291b
--- /dev/null
+++ b/changelogs/unreleased/project-dropdown-list-overflow.yml
@@ -0,0 +1,5 @@
+---
+title: Don't overflow project/group dropdown results
+merge_request: 20704
+author: gfyoung
+type: fixed
diff --git a/changelogs/unreleased/project-visibility-tooltip.yml b/changelogs/unreleased/project-visibility-tooltip.yml
new file mode 100644
index 00000000000..806c93e493a
--- /dev/null
+++ b/changelogs/unreleased/project-visibility-tooltip.yml
@@ -0,0 +1,5 @@
+---
+title: Fix project visibility tooltip
+merge_request: 20535
+author: Jamie Schembri
+type: fixed
diff --git a/changelogs/unreleased/prune-web-hook-logs.yml b/changelogs/unreleased/prune-web-hook-logs.yml
deleted file mode 100644
index e8c805b2a92..00000000000
--- a/changelogs/unreleased/prune-web-hook-logs.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Prune web hook logs older than 90 days
-merge_request:
-author:
-type: added
diff --git a/changelogs/unreleased/rails5-fix-46276.yml b/changelogs/unreleased/rails5-fix-46276.yml
deleted file mode 100644
index cdca91a755d..00000000000
--- a/changelogs/unreleased/rails5-fix-46276.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Rails5 fix format in uploads actions
-merge_request: 19907
-author: Jasper Maes
-type: fixed
diff --git a/changelogs/unreleased/rails5-fix-47366.yml b/changelogs/unreleased/rails5-fix-47366.yml
deleted file mode 100644
index 7ea03d2b95e..00000000000
--- a/changelogs/unreleased/rails5-fix-47366.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Rails5 fix expected `issuable.reload.updated_at` to have changed
-merge_request: 19733
-author: Jasper Maes
-type: fixed
diff --git a/changelogs/unreleased/rails5-fix-47370.yml b/changelogs/unreleased/rails5-fix-47370.yml
deleted file mode 100644
index 90c19593b7d..00000000000
--- a/changelogs/unreleased/rails5-fix-47370.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Use same gem versions for rails5 as for rails4 where possible
-merge_request: 19498
-author: Jasper Maes
-type: fixed
diff --git a/changelogs/unreleased/rails5-fix-47804.yml b/changelogs/unreleased/rails5-fix-47804.yml
deleted file mode 100644
index 3332ed3bbaa..00000000000
--- a/changelogs/unreleased/rails5-fix-47804.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Rails5 fix stack level too deep
-merge_request: 19762
-author: Jasper Maes
-type: fixed
diff --git a/changelogs/unreleased/rails5-fix-47805.yml b/changelogs/unreleased/rails5-fix-47805.yml
deleted file mode 100644
index 8bd8ad5488c..00000000000
--- a/changelogs/unreleased/rails5-fix-47805.yml
+++ /dev/null
@@ -1,6 +0,0 @@
----
-title: 'Rails5 ActionController::ParameterMissing: param is missing or the value is
- empty: application_setting'
-merge_request: 19763
-author: Jasper Maes
-type: fixed
diff --git a/changelogs/unreleased/rails5-fix-47835.yml b/changelogs/unreleased/rails5-fix-47835.yml
deleted file mode 100644
index fe9cbf1a03a..00000000000
--- a/changelogs/unreleased/rails5-fix-47835.yml
+++ /dev/null
@@ -1,6 +0,0 @@
----
-title: Rails5 fix no implicit conversion of Hash into String. ActionController::Parameters
- no longer returns an hash in Rails 5
-merge_request: 19792
-author: Jasper Maes
-type: fixed
diff --git a/changelogs/unreleased/rails5-fix-47836.yml b/changelogs/unreleased/rails5-fix-47836.yml
deleted file mode 100644
index 2aef2db607a..00000000000
--- a/changelogs/unreleased/rails5-fix-47836.yml
+++ /dev/null
@@ -1,6 +0,0 @@
----
-title: Rails5 fix passing Group objects array into for_projects_and_groups milestone
- scope
-merge_request: 19863
-author: Jasper Maes
-type: fixed
diff --git a/changelogs/unreleased/rails5-fix-47960.yml b/changelogs/unreleased/rails5-fix-47960.yml
deleted file mode 100644
index 2229511ccd6..00000000000
--- a/changelogs/unreleased/rails5-fix-47960.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Rails5 fix update_attribute usage not causing a save
-merge_request: 19881
-author: Jasper Maes
-type: fixed
diff --git a/changelogs/unreleased/rails5-fix-48009.yml b/changelogs/unreleased/rails5-fix-48009.yml
deleted file mode 100644
index 7ade9ef2b7d..00000000000
--- a/changelogs/unreleased/rails5-fix-48009.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Rails5 update Gemfile.rails5.lock
-merge_request: 19921
-author: Jasper Maes
-type: fixed
diff --git a/changelogs/unreleased/rails5-fix-48012.yml b/changelogs/unreleased/rails5-fix-48012.yml
deleted file mode 100644
index 953ccbd8af7..00000000000
--- a/changelogs/unreleased/rails5-fix-48012.yml
+++ /dev/null
@@ -1,6 +0,0 @@
----
-title: Rails5 fix passing Group objects array into for_projects_and_groups milestone
- scope
-merge_request: 19920
-author: Jasper Maes
-type: fixed
diff --git a/changelogs/unreleased/rails5-fix-48104.yml b/changelogs/unreleased/rails5-fix-48104.yml
deleted file mode 100644
index 6cf519ad791..00000000000
--- a/changelogs/unreleased/rails5-fix-48104.yml
+++ /dev/null
@@ -1,6 +0,0 @@
----
-title: 'Rails5 fix expected: 1 time with arguments: (97, anything, {"squash"=>false})
- received: 0 times'
-merge_request: 20004
-author: Jasper Maes
-type: fixed
diff --git a/changelogs/unreleased/rails5-fix-48140.yml b/changelogs/unreleased/rails5-fix-48140.yml
deleted file mode 100644
index a6992803e5a..00000000000
--- a/changelogs/unreleased/rails5-fix-48140.yml
+++ /dev/null
@@ -1,6 +0,0 @@
----
-title: 'Rails 5 fix Capybara::ElementNotFound: Unable to find visible css #modal-revert-commit
- and expected: "/bar" got: "/foo"'
-merge_request: 20044
-author: Jasper Maes
-type: fixed
diff --git a/changelogs/unreleased/rails5-fix-48141.yml b/changelogs/unreleased/rails5-fix-48141.yml
deleted file mode 100644
index 5e2aa23b8fb..00000000000
--- a/changelogs/unreleased/rails5-fix-48141.yml
+++ /dev/null
@@ -1,6 +0,0 @@
----
-title: 'Rails5 fix expected: 0 times with any arguments received: 1 time with arguments:
- DashboardController'
-merge_request: 20018
-author: Jasper Maes
-type: fixed
diff --git a/changelogs/unreleased/rails5-fix-48142.yml b/changelogs/unreleased/rails5-fix-48142.yml
deleted file mode 100644
index bfd95cfbe8b..00000000000
--- a/changelogs/unreleased/rails5-fix-48142.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Rails5 fix Admin::HooksController
-merge_request: 20017
-author: Jasper Maes
-type: fixed
diff --git a/changelogs/unreleased/rails5-fix-48430.yml b/changelogs/unreleased/rails5-fix-48430.yml
deleted file mode 100644
index 16495615395..00000000000
--- a/changelogs/unreleased/rails5-fix-48430.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Rails5 fix MySQL milliseconds problem in specs
-merge_request: 20221
-author: Jasper Maes
-type: fixed
diff --git a/changelogs/unreleased/rails5-fix-48432.yml b/changelogs/unreleased/rails5-fix-48432.yml
deleted file mode 100644
index 732294447a9..00000000000
--- a/changelogs/unreleased/rails5-fix-48432.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Rails5 fix Mysql comparison failure caused by milliseconds problem
-merge_request: 20222
-author: Jasper Maes
-type: fixed
diff --git a/changelogs/unreleased/rails5-fix-db-check.yml b/changelogs/unreleased/rails5-fix-db-check.yml
deleted file mode 100644
index ccac4619ea7..00000000000
--- a/changelogs/unreleased/rails5-fix-db-check.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Rails5 fix connection execute return integer instead of string
-merge_request: 19901
-author: Jasper Maes
-type: fixed
diff --git a/changelogs/unreleased/rails5-fix-mysql-arel-from.yml b/changelogs/unreleased/rails5-fix-mysql-arel-from.yml
deleted file mode 100644
index 9883ff306f1..00000000000
--- a/changelogs/unreleased/rails5-fix-mysql-arel-from.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Rails5 fix arel from in mysql_median_datetime_sql
-merge_request: 20167
-author: Jasper Maes
-type: fixed
diff --git a/changelogs/unreleased/rails5-fix-pages-controller.yml b/changelogs/unreleased/rails5-fix-pages-controller.yml
deleted file mode 100644
index eeb3747c4eb..00000000000
--- a/changelogs/unreleased/rails5-fix-pages-controller.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Rails5 fix Projects::PagesController spec
-merge_request: 20007
-author: Jasper Maes
-type: fixed
diff --git a/changelogs/unreleased/rails5-fix-revert-modal-spec.yml b/changelogs/unreleased/rails5-fix-revert-modal-spec.yml
new file mode 100644
index 00000000000..0637e503ca9
--- /dev/null
+++ b/changelogs/unreleased/rails5-fix-revert-modal-spec.yml
@@ -0,0 +1,5 @@
+---
+title: Rails5 fix user sees revert modal spec
+merge_request: 20706
+author: Jasper Maes
+type: fixed
diff --git a/changelogs/unreleased/rd-33733-showing-created-date-instead-of-updated-date-in-project-lists.yml b/changelogs/unreleased/rd-33733-showing-created-date-instead-of-updated-date-in-project-lists.yml
deleted file mode 100644
index 3934381b0cf..00000000000
--- a/changelogs/unreleased/rd-33733-showing-created-date-instead-of-updated-date-in-project-lists.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Invalidate cache with project details when repository is updated
-merge_request: 19774
-author:
-type: fixed
diff --git a/changelogs/unreleased/regen-2fa-codes.yml b/changelogs/unreleased/regen-2fa-codes.yml
new file mode 100644
index 00000000000..596f759df0f
--- /dev/null
+++ b/changelogs/unreleased/regen-2fa-codes.yml
@@ -0,0 +1,5 @@
+---
+title: Added button to regenerate 2FA codes
+merge_request:
+author: Luke Picciau
+type: added
diff --git a/changelogs/unreleased/remove-allocations-gem.yml b/changelogs/unreleased/remove-allocations-gem.yml
deleted file mode 100644
index e809fd26701..00000000000
--- a/changelogs/unreleased/remove-allocations-gem.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Remove remaining traces of the Allocations Gem
-merge_request:
-author:
-type: changed
diff --git a/changelogs/unreleased/remove-ci_job_request_with_tags_matcher.yml b/changelogs/unreleased/remove-ci_job_request_with_tags_matcher.yml
deleted file mode 100644
index b86512445d5..00000000000
--- a/changelogs/unreleased/remove-ci_job_request_with_tags_matcher.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Remove the ci_job_request_with_tags_matcher
-merge_request:
-author:
-type: performance
diff --git a/changelogs/unreleased/remove-is-shared-from-ci-runners.yml b/changelogs/unreleased/remove-is-shared-from-ci-runners.yml
deleted file mode 100644
index a6917431a53..00000000000
--- a/changelogs/unreleased/remove-is-shared-from-ci-runners.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Remove the use of `is_shared` of `Ci::Runner`
-merge_request:
-author:
-type: other
diff --git a/changelogs/unreleased/remove-link-label-vertical-alignment-property.yml b/changelogs/unreleased/remove-link-label-vertical-alignment-property.yml
deleted file mode 100644
index 40ec3998b05..00000000000
--- a/changelogs/unreleased/remove-link-label-vertical-alignment-property.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Change label link vertical alignment property
-merge_request: 18777
-author: George Tsiolis
-type: changed
diff --git a/changelogs/unreleased/remove-small-container-width.yml b/changelogs/unreleased/remove-small-container-width.yml
deleted file mode 100644
index 1af8aafa87e..00000000000
--- a/changelogs/unreleased/remove-small-container-width.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Remove small container width
-merge_request: 19893
-author: George Tsiolis
-type: changed
diff --git a/changelogs/unreleased/remove-trace-efficiently.yml b/changelogs/unreleased/remove-trace-efficiently.yml
deleted file mode 100644
index a6ba6d28dce..00000000000
--- a/changelogs/unreleased/remove-trace-efficiently.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Remove redundant query when removing trace
-merge_request: 20324
-author:
-type: performance
diff --git a/changelogs/unreleased/revert-merge-request-discussion-buttons-padding.yml b/changelogs/unreleased/revert-merge-request-discussion-buttons-padding.yml
deleted file mode 100644
index 9f11dd3dc3f..00000000000
--- a/changelogs/unreleased/revert-merge-request-discussion-buttons-padding.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Revert merge request discussion buttons padding
-merge_request: 20060
-author: George Tsiolis
-type: changed
diff --git a/changelogs/unreleased/safari-scrollbar-bug.yml b/changelogs/unreleased/safari-scrollbar-bug.yml
deleted file mode 100644
index 792a66d1ada..00000000000
--- a/changelogs/unreleased/safari-scrollbar-bug.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Remove scrollbar in Safari in repo settings page
-merge_request: 19809
-author: gfyoung
-type: fixed
diff --git a/changelogs/unreleased/security-2682-fix-xss-for-markdown-toc.yml b/changelogs/unreleased/security-2682-fix-xss-for-markdown-toc.yml
deleted file mode 100644
index f595678c3c2..00000000000
--- a/changelogs/unreleased/security-2682-fix-xss-for-markdown-toc.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix XSS vulnerability for table of content generation
-merge_request:
-author:
-type: security
diff --git a/changelogs/unreleased/security-fj-bumping-sanitize-gem.yml b/changelogs/unreleased/security-fj-bumping-sanitize-gem.yml
deleted file mode 100644
index bec1033425d..00000000000
--- a/changelogs/unreleased/security-fj-bumping-sanitize-gem.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Update sanitize gem to 4.6.5 to fix HTML injection vulnerability
-merge_request:
-author:
-type: security
diff --git a/changelogs/unreleased/security-html_escape_branch_name.yml b/changelogs/unreleased/security-html_escape_branch_name.yml
deleted file mode 100644
index 02d1065348f..00000000000
--- a/changelogs/unreleased/security-html_escape_branch_name.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: HTML escape branch name in project graphs page
-merge_request:
-author:
-type: security
diff --git a/changelogs/unreleased/security-html_escape_usernames.yml b/changelogs/unreleased/security-html_escape_usernames.yml
deleted file mode 100644
index 7e69e4ae266..00000000000
--- a/changelogs/unreleased/security-html_escape_usernames.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: HTML escape the name of the user in ProjectsHelper#link_to_member
-merge_request:
-author:
-type: security
diff --git a/changelogs/unreleased/security-rd-do-not-show-internal-info-in-public-feed.yml b/changelogs/unreleased/security-rd-do-not-show-internal-info-in-public-feed.yml
deleted file mode 100644
index ff78c162dff..00000000000
--- a/changelogs/unreleased/security-rd-do-not-show-internal-info-in-public-feed.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Don't show events from internal projects for anonymous users in public feed
-merge_request:
-author:
-type: security
diff --git a/changelogs/unreleased/sh-bump-rugged-0-27-2.yml b/changelogs/unreleased/sh-bump-rugged-0-27-2.yml
deleted file mode 100644
index 6c519648b51..00000000000
--- a/changelogs/unreleased/sh-bump-rugged-0-27-2.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Bump rugged to 0.27.2
-merge_request:
-author:
-type: fixed
diff --git a/changelogs/unreleased/sh-bump-sanitize-4-6-6.yml b/changelogs/unreleased/sh-bump-sanitize-4-6-6.yml
new file mode 100644
index 00000000000..b9444440cb9
--- /dev/null
+++ b/changelogs/unreleased/sh-bump-sanitize-4-6-6.yml
@@ -0,0 +1,5 @@
+---
+title: Bump nokogiri to 1.8.4 and sanitize to 4.6.6 for performance
+merge_request: 20795
+author:
+type: performance
diff --git a/changelogs/unreleased/sh-enable-frozen-literals-banzi-filters.yml b/changelogs/unreleased/sh-enable-frozen-literals-banzi-filters.yml
new file mode 100644
index 00000000000..897d673e97d
--- /dev/null
+++ b/changelogs/unreleased/sh-enable-frozen-literals-banzi-filters.yml
@@ -0,0 +1,5 @@
+---
+title: Enable frozen strings in remaining lib/banzai/filter/*.rb files
+merge_request: 20777
+author:
+type: performance
diff --git a/changelogs/unreleased/sh-fix-bamboo-change-set.yml b/changelogs/unreleased/sh-fix-bamboo-change-set.yml
deleted file mode 100644
index 85e79e17dee..00000000000
--- a/changelogs/unreleased/sh-fix-bamboo-change-set.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix Bamboo CI status not showing for branch plans
-merge_request:
-author:
-type: fixed
diff --git a/changelogs/unreleased/sh-freeze-banzai-filter-strings.yml b/changelogs/unreleased/sh-freeze-banzai-filter-strings.yml
new file mode 100644
index 00000000000..37b397ea49f
--- /dev/null
+++ b/changelogs/unreleased/sh-freeze-banzai-filter-strings.yml
@@ -0,0 +1,5 @@
+---
+title: Enable frozen strings in lib/banzai/filter/*.rb
+merge_request: 20775
+author:
+type: performance
diff --git a/changelogs/unreleased/sh-normalize-urls.yml b/changelogs/unreleased/sh-normalize-urls.yml
new file mode 100644
index 00000000000..b0d1120e10b
--- /dev/null
+++ b/changelogs/unreleased/sh-normalize-urls.yml
@@ -0,0 +1,5 @@
+---
+title: Escape username and password in UrlSanitizer#full_url
+merge_request: 20684
+author:
+type: fixed
diff --git a/changelogs/unreleased/sh-optimize-locks-check-ce.yml b/changelogs/unreleased/sh-optimize-locks-check-ce.yml
deleted file mode 100644
index 933ec9b79bf..00000000000
--- a/changelogs/unreleased/sh-optimize-locks-check-ce.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Eliminate N+1 queries in LFS file locks checks during a push
-merge_request:
-author:
-type: performance
diff --git a/changelogs/unreleased/sh-remove-banzai-instrumentation.yml b/changelogs/unreleased/sh-remove-banzai-instrumentation.yml
new file mode 100644
index 00000000000..8bb3cd5942b
--- /dev/null
+++ b/changelogs/unreleased/sh-remove-banzai-instrumentation.yml
@@ -0,0 +1,5 @@
+---
+title: Remove method instrumentation for Banzai filters and reference parsers
+merge_request: 20770
+author:
+type: performance
diff --git a/changelogs/unreleased/straight-comparision-mode.yml b/changelogs/unreleased/straight-comparision-mode.yml
deleted file mode 100644
index 2f6a0c0b54d..00000000000
--- a/changelogs/unreleased/straight-comparision-mode.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Allow straight diff in Compare API
-merge_request: 20120
-author: Maciej Nowak
-type: added
diff --git a/changelogs/unreleased/tc-repo-check-per-shard.yml b/changelogs/unreleased/tc-repo-check-per-shard.yml
deleted file mode 100644
index 227b6b0b93b..00000000000
--- a/changelogs/unreleased/tc-repo-check-per-shard.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Run repository checks in parallel for each shard
-merge_request: 20179
-author:
-type: added
diff --git a/changelogs/unreleased/text-expander-icon-update.yml b/changelogs/unreleased/text-expander-icon-update.yml
deleted file mode 100644
index be9dc98728f..00000000000
--- a/changelogs/unreleased/text-expander-icon-update.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Updated the icon for expand buttons to ellipsis
-merge_request: 18793
-author: Constance Okoghenun
-type: changed \ No newline at end of file
diff --git a/changelogs/unreleased/transfer_project_api_endpoint.yml b/changelogs/unreleased/transfer_project_api_endpoint.yml
deleted file mode 100644
index 60c704c62a0..00000000000
--- a/changelogs/unreleased/transfer_project_api_endpoint.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Add transfer project API endpoint
-merge_request: 20122
-author: Aram Visser
-type: added
diff --git a/changelogs/unreleased/tz-diff-blob-image-viewer.yml b/changelogs/unreleased/tz-diff-blob-image-viewer.yml
deleted file mode 100644
index 81d87bc71f5..00000000000
--- a/changelogs/unreleased/tz-diff-blob-image-viewer.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Web IDE supports now Image + Download Diff Viewing
-merge_request: 18768
-author:
-type: added
diff --git a/changelogs/unreleased/tz-mr-refactor-memory-reduction.yml b/changelogs/unreleased/tz-mr-refactor-memory-reduction.yml
new file mode 100644
index 00000000000..16003fa9cad
--- /dev/null
+++ b/changelogs/unreleased/tz-mr-refactor-memory-reduction.yml
@@ -0,0 +1,5 @@
+---
+title: Reduces the client side memory footprint on merge requests
+merge_request: 20744
+author:
+type: performance
diff --git a/changelogs/unreleased/unify-views-search-results.yml b/changelogs/unreleased/unify-views-search-results.yml
deleted file mode 100644
index 81ad3616648..00000000000
--- a/changelogs/unreleased/unify-views-search-results.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Hide project name if searching against a project
-merge_request: 19595
-author:
-type: changed
diff --git a/changelogs/unreleased/update-bcrypt-to-support-libxcrypt.yml b/changelogs/unreleased/update-bcrypt-to-support-libxcrypt.yml
deleted file mode 100644
index c18a0f75d22..00000000000
--- a/changelogs/unreleased/update-bcrypt-to-support-libxcrypt.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: update bcrypt to also support libxcrypt
-merge_request: 20260
-author: muhammadn
-type: other
diff --git a/changelogs/unreleased/update-environments-nav-controls.yml b/changelogs/unreleased/update-environments-nav-controls.yml
deleted file mode 100644
index 639dadd0cdf..00000000000
--- a/changelogs/unreleased/update-environments-nav-controls.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Update environments nav controls icons
-merge_request: 20199
-author: George Tsiolis
-type: changed
diff --git a/changelogs/unreleased/update-external-link-icon-in-header-user-dropdown.yml b/changelogs/unreleased/update-external-link-icon-in-header-user-dropdown.yml
deleted file mode 100644
index ee769f06379..00000000000
--- a/changelogs/unreleased/update-external-link-icon-in-header-user-dropdown.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Update external link icon in header user dropdown
-merge_request: 20150
-author: George Tsiolis
-type: changed
diff --git a/changelogs/unreleased/update-external-link-icon-in-merge-request-widget.yml b/changelogs/unreleased/update-external-link-icon-in-merge-request-widget.yml
deleted file mode 100644
index c650c32f884..00000000000
--- a/changelogs/unreleased/update-external-link-icon-in-merge-request-widget.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Update external link icon in merge request widget
-merge_request: 20154
-author: George Tsiolis
-type: changed
diff --git a/changelogs/unreleased/update-integrations-external-link-icons.yml b/changelogs/unreleased/update-integrations-external-link-icons.yml
deleted file mode 100644
index 9972744bd00..00000000000
--- a/changelogs/unreleased/update-integrations-external-link-icons.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Update integrations external link icons
-merge_request: 20205
-author: George Tsiolis
-type: changed
diff --git a/changelogs/unreleased/update-pipeline-icon-in-web-ide-sidebar.yml b/changelogs/unreleased/update-pipeline-icon-in-web-ide-sidebar.yml
deleted file mode 100644
index 3f1f3c643e2..00000000000
--- a/changelogs/unreleased/update-pipeline-icon-in-web-ide-sidebar.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Update pipeline icon in web ide sidebar
-merge_request: 20058
-author: George Tsiolis
-type: changed
diff --git a/changelogs/unreleased/upgrade-gitlab-markup.yml b/changelogs/unreleased/upgrade-gitlab-markup.yml
deleted file mode 100644
index 9b0eaa7068d..00000000000
--- a/changelogs/unreleased/upgrade-gitlab-markup.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix extra blank line at start of rendered reStructuredText code block
-merge_request: 19596
-author:
-type: fixed
diff --git a/changelogs/unreleased/use-backup-custom-hooks-gitaly.yml b/changelogs/unreleased/use-backup-custom-hooks-gitaly.yml
deleted file mode 100644
index 4b9766332c3..00000000000
--- a/changelogs/unreleased/use-backup-custom-hooks-gitaly.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: migrate backup rake task to gitaly
-merge_request:
-author:
-type: added
diff --git a/changelogs/unreleased/use-tooltip-component-in-mr-widget-author-time-component.yml b/changelogs/unreleased/use-tooltip-component-in-mr-widget-author-time-component.yml
deleted file mode 100644
index 4ab9b6dadc0..00000000000
--- a/changelogs/unreleased/use-tooltip-component-in-mr-widget-author-time-component.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Use Tooltip component in MrWidgetAuthorTime vue comonent
-merge_request: 19635
-author: George Tsiolis
-type: performance
diff --git a/changelogs/unreleased/web-hooks-log-pagination.yml b/changelogs/unreleased/web-hooks-log-pagination.yml
deleted file mode 100644
index fd9e4f9ca13..00000000000
--- a/changelogs/unreleased/web-hooks-log-pagination.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fixed pagination of web hook logs
-merge_request:
-author:
-type: performance
diff --git a/changelogs/unreleased/winh-new-branch-url-encode.yml b/changelogs/unreleased/winh-new-branch-url-encode.yml
deleted file mode 100644
index f3554d0d4a1..00000000000
--- a/changelogs/unreleased/winh-new-branch-url-encode.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix branch name encoding for dropdown on issue page
-merge_request: 19634
-author:
-type: fixed
diff --git a/changelogs/unreleased/winh-tree-view-gpg.yml b/changelogs/unreleased/winh-tree-view-gpg.yml
new file mode 100644
index 00000000000..84d63814a47
--- /dev/null
+++ b/changelogs/unreleased/winh-tree-view-gpg.yml
@@ -0,0 +1,5 @@
+---
+title: Display GPG status on repository and blob pages
+merge_request: 20524
+author:
+type: changed
diff --git a/changelogs/unreleased/zj-gitaly-read-write-check.yml b/changelogs/unreleased/zj-gitaly-read-write-check.yml
deleted file mode 100644
index 43951d20e8f..00000000000
--- a/changelogs/unreleased/zj-gitaly-read-write-check.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Gitaly metrics check for read/writeability
-merge_request: 20022
-author:
-type: other
diff --git a/config/boot.rb b/config/boot.rb
index 84f390f3228..655c54ddb84 100644
--- a/config/boot.rb
+++ b/config/boot.rb
@@ -9,3 +9,8 @@ ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../#{gemfile}", __dir__)
# Set up gems listed in the Gemfile.
require 'bundler/setup' if File.exist?(ENV['BUNDLE_GEMFILE'])
+begin
+ require 'bootsnap/setup'
+rescue LoadError
+ # bootsnap is optional dependency, so if we don't have it it's fine
+end
diff --git a/config/gitlab.yml.example b/config/gitlab.yml.example
index ab109f5d04f..561ff57c9fb 100644
--- a/config/gitlab.yml.example
+++ b/config/gitlab.yml.example
@@ -78,15 +78,15 @@ production: &base
# username_changing_enabled: false # default: true - User can change her username/namespace
## Default theme ID
## 1 - Indigo
- ## 2 - Light Indigo
- ## 3 - Blue
- ## 4 - Light Blue
+ ## 2 - Dark
+ ## 3 - Light
+ ## 4 - Blue
## 5 - Green
- ## 6 - Light Green
- ## 7 - Red
- ## 8 - Light Red
- ## 9 - Dark
- ## 10 - Light
+ ## 6 - Light Indigo
+ ## 7 - Light Blue
+ ## 8 - Light Green
+ ## 9 - Red
+ ## 10 - Light Red
# default_theme: 1 # default: 1
## Automatic issue closing
diff --git a/config/initializers/1_settings.rb b/config/initializers/1_settings.rb
index 44bc72a7185..c3122827a6b 100644
--- a/config/initializers/1_settings.rb
+++ b/config/initializers/1_settings.rb
@@ -319,10 +319,6 @@ Settings.cron_jobs['gitlab_usage_ping_worker'] ||= Settingslogic.new({})
Settings.cron_jobs['gitlab_usage_ping_worker']['cron'] ||= Settings.__send__(:cron_for_usage_ping)
Settings.cron_jobs['gitlab_usage_ping_worker']['job_class'] = 'GitlabUsagePingWorker'
-Settings.cron_jobs['schedule_update_user_activity_worker'] ||= Settingslogic.new({})
-Settings.cron_jobs['schedule_update_user_activity_worker']['cron'] ||= '30 0 * * *'
-Settings.cron_jobs['schedule_update_user_activity_worker']['job_class'] = 'ScheduleUpdateUserActivityWorker'
-
Settings.cron_jobs['remove_old_web_hook_logs_worker'] ||= Settingslogic.new({})
Settings.cron_jobs['remove_old_web_hook_logs_worker']['cron'] ||= '40 0 * * *'
Settings.cron_jobs['remove_old_web_hook_logs_worker']['job_class'] = 'RemoveOldWebHookLogsWorker'
diff --git a/config/initializers/8_metrics.rb b/config/initializers/8_metrics.rb
index 8a851b89c56..4d8d35bf6cf 100644
--- a/config/initializers/8_metrics.rb
+++ b/config/initializers/8_metrics.rb
@@ -58,20 +58,6 @@ def instrument_classes(instrumentation)
instrumentation.instrument_instance_methods(const)
end
- # Instruments all Banzai filters and reference parsers
- {
- Filter: Rails.root.join('lib', 'banzai', 'filter', '*.rb'),
- ReferenceParser: Rails.root.join('lib', 'banzai', 'reference_parser', '*.rb')
- }.each do |const_name, path|
- Dir[path].each do |file|
- klass = File.basename(file, File.extname(file)).camelize
- const = Banzai.const_get(const_name).const_get(klass)
-
- instrumentation.instrument_methods(const)
- instrumentation.instrument_instance_methods(const)
- end
- end
-
instrumentation.instrument_methods(Banzai::Renderer)
instrumentation.instrument_methods(Banzai::Querying)
@@ -94,8 +80,6 @@ def instrument_classes(instrumentation)
instrumentation.instrument_instance_methods(RepositoryCheck::SingleRepositoryWorker)
- instrumentation.instrument_instance_methods(Rouge::Plugins::CommonMark)
- instrumentation.instrument_instance_methods(Rouge::Plugins::Redcarpet)
instrumentation.instrument_instance_methods(Rouge::Formatters::HTMLGitlab)
[:XML, :HTML].each do |namespace|
diff --git a/config/initializers/bootstrap_form.rb b/config/initializers/bootstrap_form.rb
index 11171b38a85..bbc1d83a63f 100644
--- a/config/initializers/bootstrap_form.rb
+++ b/config/initializers/bootstrap_form.rb
@@ -1,6 +1,6 @@
module BootstrapFormBuilderCustomization
def label_class
- "label-light"
+ "label-bold"
end
end
diff --git a/config/initializers/devise.rb b/config/initializers/devise.rb
index e5772c33307..c41b2db722c 100644
--- a/config/initializers/devise.rb
+++ b/config/initializers/devise.rb
@@ -219,7 +219,7 @@ Devise.setup do |config|
end
end
- if Gitlab::OmniauthInitializer.enabled?
+ if Gitlab::Auth.omniauth_enabled?
Gitlab::OmniauthInitializer.new(config).execute(Gitlab.config.omniauth.providers)
end
end
diff --git a/config/initializers/omniauth.rb b/config/initializers/omniauth.rb
index c558eb28ced..ef23ca065c6 100644
--- a/config/initializers/omniauth.rb
+++ b/config/initializers/omniauth.rb
@@ -16,8 +16,3 @@ OmniAuth.config.allowed_request_methods << :get if Gitlab.config.omniauth.auto_s
OmniAuth.config.before_request_phase do |env|
Gitlab::RequestForgeryProtection.call(env)
end
-
-if Gitlab::OmniauthInitializer.enabled?
- provider_names = Gitlab.config.omniauth.providers.map(&:name)
- Gitlab::Auth.omniauth_setup_providers(provider_names)
-end
diff --git a/config/sidekiq_queues.yml b/config/sidekiq_queues.yml
index 3400142db36..70b584ff9e9 100644
--- a/config/sidekiq_queues.yml
+++ b/config/sidekiq_queues.yml
@@ -62,7 +62,6 @@
- [default, 1]
- [pages, 1]
- [system_hook_push, 1]
- - [update_user_activity, 1]
- [propagate_service_template, 1]
- [background_migration, 1]
- [gcp_cluster, 1]
@@ -77,4 +76,3 @@
- [repository_remove_remote, 1]
- [create_note_diff_file, 1]
- [delete_diff_files, 1]
-
diff --git a/db/migrate/20161124141322_migrate_process_commit_worker_jobs.rb b/db/migrate/20161124141322_migrate_process_commit_worker_jobs.rb
index dc16d5c5169..1eb6a8fa5df 100644
--- a/db/migrate/20161124141322_migrate_process_commit_worker_jobs.rb
+++ b/db/migrate/20161124141322_migrate_process_commit_worker_jobs.rb
@@ -1,9 +1,19 @@
-# See http://doc.gitlab.com/ce/development/migration_style_guide.html
-# for more information on how to write migrations for GitLab.
-
class MigrateProcessCommitWorkerJobs < ActiveRecord::Migration
include Gitlab::Database::MigrationHelpers
+ class Repository
+ attr_reader :storage
+
+ def initialize(storage, relative_path)
+ @storage = storage
+ @relative_path = relative_path
+ end
+
+ def gitaly_repository
+ Gitaly::Repository.new(storage_name: @storage, relative_path: @relative_path)
+ end
+ end
+
class Project < ActiveRecord::Base
def self.find_including_path(id)
select("projects.*, CONCAT(namespaces.path, '/', projects.path) AS path_with_namespace")
@@ -11,19 +21,12 @@ class MigrateProcessCommitWorkerJobs < ActiveRecord::Migration
.find_by(id: id)
end
- def repository_storage_path
- Gitlab::GitalyClient::StorageSettings.allow_disk_access do
- Gitlab.config.repositories.storages[repository_storage].legacy_disk_path
- end
- end
-
- def repository_path
- # TODO: review if the change from Legacy storage needs to reflect here as well.
- File.join(repository_storage_path, read_attribute(:path_with_namespace) + '.git')
+ def commit(rev)
+ Gitlab::GitalyClient::CommitService.new(repository).find_commit(rev)
end
def repository
- @repository ||= Rugged::Repository.new(repository_path)
+ @repository ||= Repository.new(repository_storage, read_attribute(:path_with_namespace) + '.git')
end
end
@@ -42,22 +45,19 @@ class MigrateProcessCommitWorkerJobs < ActiveRecord::Migration
next unless project
- begin
- commit = project.repository.lookup(payload['args'][2])
- rescue Rugged::OdbError
- next
- end
+ commit = project.commit(payload['args'][2])
+ next unless commit
hash = {
- id: commit.oid,
- message: encode(commit.message),
- parent_ids: commit.parent_ids,
- authored_date: commit.author[:time],
- author_name: encode(commit.author[:name]),
- author_email: encode(commit.author[:email]),
- committed_date: commit.committer[:time],
- committer_email: encode(commit.committer[:email]),
- committer_name: encode(commit.committer[:name])
+ id: commit.id,
+ message: encode(commit.body),
+ parent_ids: commit.parent_ids.to_a,
+ authored_date: Time.at(commit.author.date.seconds).utc,
+ author_name: encode(commit.author.name),
+ author_email: encode(commit.author.email),
+ committed_date: Time.at(commit.committer.date.seconds).utc,
+ committer_email: encode(commit.committer.email),
+ committer_name: encode(commit.committer.name)
}
payload['args'][2] = hash
diff --git a/db/migrate/20161226122833_remove_dot_git_from_usernames.rb b/db/migrate/20161226122833_remove_dot_git_from_usernames.rb
index 133435523e1..db10426b483 100644
--- a/db/migrate/20161226122833_remove_dot_git_from_usernames.rb
+++ b/db/migrate/20161226122833_remove_dot_git_from_usernames.rb
@@ -1,11 +1,7 @@
-# See http://doc.gitlab.com/ce/development/migration_style_guide.html
-# for more information on how to write migrations for GitLab.
-
class RemoveDotGitFromUsernames < ActiveRecord::Migration
include Gitlab::Database::MigrationHelpers
include Gitlab::ShellAdapter
- # Set this constant to true if this migration requires downtime.
DOWNTIME = false
def up
@@ -64,16 +60,14 @@ class RemoveDotGitFromUsernames < ActiveRecord::Migration
# we rename suffix instead of removing it
path = path.sub(/\.git\z/, '_git')
- Gitlab::GitalyClient::StorageSettings.allow_disk_access do
- check_routes(path.dup, 0, path)
- end
+ check_routes(path.dup, 0, path)
end
def check_routes(base, counter, path)
route_exists = route_exists?(path)
- Gitlab.config.repositories.storages.each do |shard, storage|
- if route_exists || path_exists?(shard, storage.legacy_disk_path)
+ Gitlab.config.repositories.storages.each do |shard, _storage|
+ if route_exists || path_exists?(shard, path)
counter += 1
path = "#{base}#{counter}"
diff --git a/doc/administration/monitoring/prometheus/gitlab_metrics.md b/doc/administration/monitoring/prometheus/gitlab_metrics.md
index c0e98099e42..7bc92ae77ee 100644
--- a/doc/administration/monitoring/prometheus/gitlab_metrics.md
+++ b/doc/administration/monitoring/prometheus/gitlab_metrics.md
@@ -22,7 +22,7 @@ collect metrics from this endpoint. We recommend setting up another Prometheus
server, because the embedded server configuration is overwritten once every
[reconfigure of GitLab][reconfigure]. In the future this will not be required.
-## Metrics available
+## Unicorn Metrics available
The following metrics are available:
diff --git a/doc/administration/pages/index.md b/doc/administration/pages/index.md
index b3602bc35ab..eefa86f8e42 100644
--- a/doc/administration/pages/index.md
+++ b/doc/administration/pages/index.md
@@ -124,11 +124,6 @@ The Pages daemon doesn't listen to the outside world.
```
1. [Reconfigure GitLab][reconfigure]
-1. Restart gitlab-pages by running the following command:
-
- ```shell
- sudo gitlab-ctl restart gitlab-pages
- ```
Watch the [video tutorial][video-admin] for this configuration.
@@ -161,11 +156,6 @@ outside world.
respectively.
1. [Reconfigure GitLab][reconfigure]
-1. Restart gitlab-pages by running the following command:
-
- ```shell
- sudo gitlab-ctl restart gitlab-pages
- ```
## Advanced configuration
@@ -203,11 +193,6 @@ world. Custom domains are supported, but no TLS.
listens on. If you don't have IPv6, you can omit the IPv6 address.
1. [Reconfigure GitLab][reconfigure]
-1. Restart gitlab-pages by running the following command:
-
- ```shell
- sudo gitlab-ctl restart gitlab-pages
- ```
### Custom domains with TLS support
@@ -241,11 +226,6 @@ world. Custom domains and TLS are supported.
listens on. If you don't have IPv6, you can omit the IPv6 address.
1. [Reconfigure GitLab][reconfigure]
-1. Restart gitlab-pages by running the following command:
-
- ```shell
- sudo gitlab-ctl restart gitlab-pages
- ```
### Custom domain verification
@@ -267,7 +247,6 @@ Omnibus GitLab 11.1.
Follow the steps below to configure verbose logging of GitLab Pages daemon.
1. By default the daemon only logs with `INFO` level.
-
If you wish to make it log events with level `DEBUG` you must configure this in
`/etc/gitlab/gitlab.rb`:
@@ -291,11 +270,29 @@ are stored.
```
1. [Reconfigure GitLab][reconfigure]
-1. Restart gitlab-pages by running the following command:
+
+## Configure listener for reverse proxy requests
+
+Follow the steps below to configure the proxy listener of GitLab Pages. [Introduced](https://gitlab.com/gitlab-org/omnibus-gitlab/merge_requests/2533) in
+Omnibus GitLab 11.1.
+
+1. By default the listener is configured to listen for requests on `localhost:8090`.
+
+ If you wish to disable it you must configure this in
+ `/etc/gitlab/gitlab.rb`:
```shell
- sudo gitlab-ctl restart gitlab-pages
- ```
+ gitlab_pages['listen_proxy'] = nil
+ ```
+
+ If you wish to make it listen on a different port you must configure this also in
+ `/etc/gitlab/gitlab.rb`:
+
+ ```shell
+ gitlab_pages['listen_proxy'] = "localhost:10080"
+ ```
+
+1. [Reconfigure GitLab][reconfigure]
## Set maximum pages size
diff --git a/doc/api/groups.md b/doc/api/groups.md
index 11de75039ee..87be36cc815 100644
--- a/doc/api/groups.md
+++ b/doc/api/groups.md
@@ -10,13 +10,14 @@ Parameters:
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `skip_groups` | array of integers | no | Skip the group IDs passed |
-| `all_available` | boolean | no | Show all the groups you have access to (defaults to `false` for authenticated users, `true` for admin) |
+| `all_available` | boolean | no | Show all the groups you have access to (defaults to `false` for authenticated users, `true` for admin); Attributes `owned` and `min_access_level` have precedence |
| `search` | string | no | Return the list of authorized groups matching the search criteria |
| `order_by` | string | no | Order groups by `name`, `path` or `id`. Default is `name` |
| `sort` | string | no | Order groups in `asc` or `desc` order. Default is `asc` |
| `statistics` | boolean | no | Include group statistics (admins only) |
| `with_custom_attributes` | boolean | no | Include [custom attributes](custom_attributes.md) in response (admins only) |
-| `owned` | boolean | no | Limit to groups owned by the current user |
+| `owned` | boolean | no | Limit to groups explicitly owned by the current user |
+| `min_access_level` | integer | no | Limit to groups where current user has at least this [access level](members.md) |
```
GET /groups
@@ -94,13 +95,14 @@ Parameters:
| --------- | ---- | -------- | ----------- |
| `id` | integer/string | yes | The ID or [URL-encoded path of the group](README.md#namespaced-path-encoding) of the parent group |
| `skip_groups` | array of integers | no | Skip the group IDs passed |
-| `all_available` | boolean | no | Show all the groups you have access to (defaults to `false` for authenticated users, `true` for admin) |
+| `all_available` | boolean | no | Show all the groups you have access to (defaults to `false` for authenticated users, `true` for admin); Attributes `owned` and `min_access_level` have precedence |
| `search` | string | no | Return the list of authorized groups matching the search criteria |
| `order_by` | string | no | Order groups by `name`, `path` or `id`. Default is `name` |
| `sort` | string | no | Order groups in `asc` or `desc` order. Default is `asc` |
| `statistics` | boolean | no | Include group statistics (admins only) |
| `with_custom_attributes` | boolean | no | Include [custom attributes](custom_attributes.md) in response (admins only) |
-| `owned` | boolean | no | Limit to groups owned by the current user |
+| `owned` | boolean | no | Limit to groups explicitly owned by the current user |
+| `min_access_level` | integer | no | Limit to groups where current user has at least this [access level](members.md) |
```
GET /groups/:id/subgroups
diff --git a/doc/api/issues.md b/doc/api/issues.md
index 5613cb6d915..92fb3e9c307 100644
--- a/doc/api/issues.md
+++ b/doc/api/issues.md
@@ -37,7 +37,7 @@ GET /issues?my_reaction_emoji=star
| ------------------- | ---------------- | ---------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
| `state` | string | no | Return all issues or just those that are `opened` or `closed` |
| `labels` | string | no | Comma-separated list of label names, issues must have all labels to be returned. `No+Label` lists all issues with no labels |
-| `milestone` | string | no | The milestone title |
+| `milestone` | string | no | The milestone title. `No+Milestone` lists all issues with no milestone |
| `scope` | string | no | Return issues for the given scope: `created_by_me`, `assigned_to_me` or `all`. Defaults to `created_by_me`<br> For versions before 11.0, use the now deprecated `created-by-me` or `assigned-to-me` scopes instead.<br> _([Introduced][ce-13004] in GitLab 9.5. [Changed to snake_case][ce-18935] in GitLab 11.0)_ |
| `author_id` | integer | no | Return issues created by the given user `id`. Combine with `scope=all` or `scope=assigned_to_me`. _([Introduced][ce-13004] in GitLab 9.5)_ |
| `assignee_id` | integer | no | Return issues assigned to the given user `id` _([Introduced][ce-13004] in GitLab 9.5)_ |
@@ -151,7 +151,7 @@ GET /groups/:id/issues?my_reaction_emoji=star
| `state` | string | no | Return all issues or just those that are `opened` or `closed` |
| `labels` | string | no | Comma-separated list of label names, issues must have all labels to be returned. `No+Label` lists all issues with no labels |
| `iids[]` | Array[integer] | no | Return only the issues having the given `iid` |
-| `milestone` | string | no | The milestone title |
+| `milestone` | string | no | The milestone title. `No+Milestone` lists all issues with no milestone |
| `scope` | string | no | Return issues for the given scope: `created_by_me`, `assigned_to_me` or `all`.<br> For versions before 11.0, use the now deprecated `created-by-me` or `assigned-to-me` scopes instead.<br> _([Introduced][ce-13004] in GitLab 9.5. [Changed to snake_case][ce-18935] in GitLab 11.0)_ |
| `author_id` | integer | no | Return issues created by the given user `id` _([Introduced][ce-13004] in GitLab 9.5)_ |
| `assignee_id` | integer | no | Return issues assigned to the given user `id` _([Introduced][ce-13004] in GitLab 9.5)_ |
@@ -265,7 +265,7 @@ GET /projects/:id/issues?my_reaction_emoji=star
| `iids[]` | Array[integer] | no | Return only the milestone having the given `iid` |
| `state` | string | no | Return all issues or just those that are `opened` or `closed` |
| `labels` | string | no | Comma-separated list of label names, issues must have all labels to be returned. `No+Label` lists all issues with no labels |
-| `milestone` | string | no | The milestone title |
+| `milestone` | string | no | The milestone title. `No+Milestone` lists all issues with no milestone |
| `scope` | string | no | Return issues for the given scope: `created_by_me`, `assigned_to_me` or `all`.<br> For versions before 11.0, use the now deprecated `created-by-me` or `assigned-to-me` scopes instead.<br> _([Introduced][ce-13004] in GitLab 9.5. [Changed to snake_case][ce-18935] in GitLab 11.0)_ |
| `author_id` | integer | no | Return issues created by the given user `id` _([Introduced][ce-13004] in GitLab 9.5)_ |
| `assignee_id` | integer | no | Return issues assigned to the given user `id` _([Introduced][ce-13004] in GitLab 9.5)_ |
diff --git a/doc/api/jobs.md b/doc/api/jobs.md
index cfa5e9a3e95..9a950097675 100644
--- a/doc/api/jobs.md
+++ b/doc/api/jobs.md
@@ -50,6 +50,7 @@ Example of response
"started_at": "2015-12-24T17:54:24.729Z",
"status": "failed",
"tag": false,
+ "web_url": "https://example.com/foo/bar/-/jobs/6",
"user": {
"avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon",
"bio": null,
@@ -82,7 +83,7 @@ Example of response
"size": 1000
},
"finished_at": "2015-12-24T17:54:27.895Z",
- "artifacts_expire_at": "2016-01-23T17:54:27.895Z"
+ "artifacts_expire_at": "2016-01-23T17:54:27.895Z",
"id": 7,
"name": "teaspoon",
"pipeline": {
@@ -97,6 +98,7 @@ Example of response
"started_at": "2015-12-24T17:54:27.722Z",
"status": "failed",
"tag": false,
+ "web_url": "https://example.com/foo/bar/-/jobs/7",
"user": {
"avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon",
"bio": null,
@@ -151,7 +153,7 @@ Example of response
"created_at": "2015-12-24T15:51:21.727Z",
"artifacts_file": null,
"finished_at": "2015-12-24T17:54:24.921Z",
- "artifacts_expire_at": "2016-01-23T17:54:24.921Z"
+ "artifacts_expire_at": "2016-01-23T17:54:24.921Z",
"id": 6,
"name": "rspec:other",
"pipeline": {
@@ -166,6 +168,7 @@ Example of response
"started_at": "2015-12-24T17:54:24.729Z",
"status": "failed",
"tag": false,
+ "web_url": "https://example.com/foo/bar/-/jobs/6",
"user": {
"avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon",
"bio": null,
@@ -198,7 +201,7 @@ Example of response
"size": 1000
},
"finished_at": "2015-12-24T17:54:27.895Z",
- "artifacts_expire_at": "2016-01-23T17:54:27.895Z"
+ "artifacts_expire_at": "2016-01-23T17:54:27.895Z",
"id": 7,
"name": "teaspoon",
"pipeline": {
@@ -213,6 +216,7 @@ Example of response
"started_at": "2015-12-24T17:54:27.722Z",
"status": "failed",
"tag": false,
+ "web_url": "https://example.com/foo/bar/-/jobs/7",
"user": {
"avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon",
"bio": null,
@@ -280,6 +284,7 @@ Example of response
"started_at": "2015-12-24T17:54:30.733Z",
"status": "failed",
"tag": false,
+ "web_url": "https://example.com/foo/bar/-/jobs/8",
"user": {
"avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon",
"bio": null,
@@ -455,7 +460,7 @@ Example of response
"created_at": "2016-01-11T10:13:33.506Z",
"artifacts_file": null,
"finished_at": "2016-01-11T10:14:09.526Z",
- "id": 69,
+ "id": 42,
"name": "rubocop",
"ref": "master",
"runner": null,
@@ -463,6 +468,7 @@ Example of response
"started_at": null,
"status": "canceled",
"tag": false,
+ "web_url": "https://example.com/foo/bar/-/jobs/42",
"user": null
}
```
@@ -501,7 +507,7 @@ Example of response
"created_at": "2016-01-11T10:13:33.506Z",
"artifacts_file": null,
"finished_at": null,
- "id": 69,
+ "id": 42,
"name": "rubocop",
"ref": "master",
"runner": null,
@@ -509,6 +515,7 @@ Example of response
"started_at": null,
"status": "pending",
"tag": false,
+ "web_url": "https://example.com/foo/bar/-/jobs/42",
"user": null
}
```
@@ -549,7 +556,7 @@ Example of response
},
"coverage": null,
"download_url": null,
- "id": 69,
+ "id": 42,
"name": "rubocop",
"ref": "master",
"runner": null,
@@ -559,6 +566,7 @@ Example of response
"finished_at": "2016-01-11T10:15:10.506Z",
"status": "failed",
"tag": false,
+ "web_url": "https://example.com/foo/bar/-/jobs/42",
"user": null
}
```
@@ -599,7 +607,7 @@ Example response:
},
"coverage": null,
"download_url": null,
- "id": 69,
+ "id": 42,
"name": "rubocop",
"ref": "master",
"runner": null,
@@ -609,6 +617,7 @@ Example response:
"finished_at": "2016-01-11T10:15:10.506Z",
"status": "failed",
"tag": false,
+ "web_url": "https://example.com/foo/bar/-/jobs/42",
"user": null
}
```
@@ -647,7 +656,7 @@ Example of response
"created_at": "2016-01-11T10:13:33.506Z",
"artifacts_file": null,
"finished_at": null,
- "id": 69,
+ "id": 42,
"name": "rubocop",
"ref": "master",
"runner": null,
@@ -655,6 +664,7 @@ Example of response
"started_at": null,
"status": "started",
"tag": false,
+ "web_url": "https://example.com/foo/bar/-/jobs/42",
"user": null
}
```
diff --git a/doc/api/pipelines.md b/doc/api/pipelines.md
index 22cf9afbcd2..574be52801c 100644
--- a/doc/api/pipelines.md
+++ b/doc/api/pipelines.md
@@ -33,13 +33,15 @@ Example of response
"id": 47,
"status": "pending",
"ref": "new-pipeline",
- "sha": "a91957a858320c0e17f3a0eca7cfacbff50ea29a"
+ "sha": "a91957a858320c0e17f3a0eca7cfacbff50ea29a",
+ "web_url": "https://example.com/foo/bar/pipelines/47"
},
{
"id": 48,
"status": "pending",
"ref": "new-pipeline",
- "sha": "eb94b618fb5865b26e80fdd8ae531b7a63ad851a"
+ "sha": "eb94b618fb5865b26e80fdd8ae531b7a63ad851a",
+ "web_url": "https://example.com/foo/bar/pipelines/48"
}
]
```
@@ -86,7 +88,8 @@ Example of response
"finished_at": "2016-08-11T11:32:35.145Z",
"committed_at": null,
"duration": null,
- "coverage": "30.0"
+ "coverage": "30.0",
+ "web_url": "https://example.com/foo/bar/pipelines/46"
}
```
@@ -133,7 +136,8 @@ Example of response
"finished_at": null,
"committed_at": null,
"duration": null,
- "coverage": null
+ "coverage": null,
+ "web_url": "https://example.com/foo/bar/pipelines/61"
}
```
@@ -179,7 +183,8 @@ Response:
"finished_at": "2016-08-11T11:32:35.145Z",
"committed_at": null,
"duration": null,
- "coverage": null
+ "coverage": null,
+ "web_url": "https://example.com/foo/bar/pipelines/46"
}
```
@@ -225,7 +230,8 @@ Response:
"finished_at": "2016-08-11T11:32:35.145Z",
"committed_at": null,
"duration": null,
- "coverage": null
+ "coverage": null,
+ "web_url": "https://example.com/foo/bar/pipelines/46"
}
```
diff --git a/doc/api/projects.md b/doc/api/projects.md
index a35c2a56992..f360b49c293 100644
--- a/doc/api/projects.md
+++ b/doc/api/projects.md
@@ -48,13 +48,16 @@ GET /projects
| `sort` | string | no | Return projects sorted in `asc` or `desc` order. Default is `desc` |
| `search` | string | no | Return list of projects matching the search criteria |
| `simple` | boolean | no | Return only limited fields for each project. This is a no-op without authentication as then _only_ simple fields are returned. |
-| `owned` | boolean | no | Limit by projects owned by the current user |
+| `owned` | boolean | no | Limit by projects explicitly owned by the current user |
| `membership` | boolean | no | Limit by projects that the current user is a member of |
| `starred` | boolean | no | Limit by projects starred by the current user |
| `statistics` | boolean | no | Include project statistics |
| `with_custom_attributes` | boolean | no | Include [custom attributes](custom_attributes.md) in response (admins only) |
| `with_issues_enabled` | boolean | no | Limit by enabled issues feature |
| `with_merge_requests_enabled` | boolean | no | Limit by enabled merge requests feature |
+| `wiki_checksum_failed` | boolean | no | Limit projects where the wiki checksum calculation has failed _([Introduced][ee-6137] in [GitLab Premium][eep] 11.2)_ |
+| `repository_checksum_failed` | boolean | no | Limit projects where the repository checksum calculation has failed _([Introduced][ee-6137] in [GitLab Premium][eep] 11.2)_ |
+| `min_access_level` | integer | no | Limit by current user minimal [access level](members.md) |
When `simple=true` or the user is unauthenticated this returns something like:
@@ -271,13 +274,14 @@ GET /users/:user_id/projects
| `sort` | string | no | Return projects sorted in `asc` or `desc` order. Default is `desc` |
| `search` | string | no | Return list of projects matching the search criteria |
| `simple` | boolean | no | Return only limited fields for each project. This is a no-op without authentication as then _only_ simple fields are returned. |
-| `owned` | boolean | no | Limit by projects owned by the current user |
+| `owned` | boolean | no | Limit by projects explicitly owned by the current user |
| `membership` | boolean | no | Limit by projects that the current user is a member of |
| `starred` | boolean | no | Limit by projects starred by the current user |
| `statistics` | boolean | no | Include project statistics |
| `with_custom_attributes` | boolean | no | Include [custom attributes](custom_attributes.md) in response (admins only) |
| `with_issues_enabled` | boolean | no | Limit by enabled issues feature |
| `with_merge_requests_enabled` | boolean | no | Limit by enabled merge requests feature |
+| `min_access_level` | integer | no | Limit by current user minimal [access level](members.md) |
```json
[
@@ -571,7 +575,15 @@ If the project is a fork, and you provide a valid token to authenticate, the
"avatar_url":"https://assets.gitlab-static.net/uploads/-/system/project/avatar/13083/logo-extra-whitespace.png",
"star_count":3812,
"forks_count":3561,
- "last_activity_at":"2018-01-02T11:40:26.570Z"
+ "last_activity_at":"2018-01-02T11:40:26.570Z",
+ "namespace": {
+ "id": 72,
+ "name": "GitLab.org",
+ "path": "gitlab-org",
+ "kind": "group",
+ "full_path": "gitlab-org",
+ "parent_id": null
+ }
}
...
@@ -759,13 +771,14 @@ GET /projects/:id/forks
| `sort` | string | no | Return projects sorted in `asc` or `desc` order. Default is `desc` |
| `search` | string | no | Return list of projects matching the search criteria |
| `simple` | boolean | no | Return only limited fields for each project. This is a no-op without authentication as then _only_ simple fields are returned. |
-| `owned` | boolean | no | Limit by projects owned by the current user |
+| `owned` | boolean | no | Limit by projects explicitly owned by the current user |
| `membership` | boolean | no | Limit by projects that the current user is a member of |
| `starred` | boolean | no | Limit by projects starred by the current user |
| `statistics` | boolean | no | Include project statistics |
| `with_custom_attributes` | boolean | no | Include [custom attributes](custom_attributes.md) in response (admins only) |
| `with_issues_enabled` | boolean | no | Limit by enabled issues feature |
| `with_merge_requests_enabled` | boolean | no | Limit by enabled merge requests feature |
+| `min_access_level` | integer | no | Limit by current user minimal [access level](members.md) |
```bash
curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/5/forks"
@@ -1509,3 +1522,6 @@ GET /projects/:id/snapshot
| --------- | ---- | -------- | ----------- |
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) |
| `wiki` | boolean | no | Whether to download the wiki, rather than project, repository |
+
+[eep]: https://about.gitlab.com/pricing/ "Available only in GitLab Premium"
+[ee-6137]: https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/6137
diff --git a/doc/api/services.md b/doc/api/services.md
index aeb48ccc36c..efa173180bb 100644
--- a/doc/api/services.md
+++ b/doc/api/services.md
@@ -443,6 +443,54 @@ Get Gemnasium service settings for a project.
GET /projects/:id/services/gemnasium
```
+## Hangouts Chat
+
+Google GSuite team collaboration tool.
+
+>**Note:** This service was [introduced in v11.2](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/20290)
+
+### Create/Edit Hangouts Chat service
+
+Set Hangouts Chat service for a project.
+
+```
+PUT /projects/:id/services/hangouts_chat
+```
+
+>**Note:** Specific event parameters (e.g. `push_events` flag) were [introduced in v10.4][11435]
+
+Parameters:
+
+| Parameter | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `webhook` | string | true | The Hangouts Chat webhook. e.g. https://chat.googleapis.com/v1/spaces... |
+| `notify_only_broken_pipelines` | boolean | false | Send notifications for broken pipelines |
+| `notify_only_default_branch` | boolean | false | Send notifications only for the default branch |
+| `push_events` | boolean | false | Enable notifications for push events |
+| `issues_events` | boolean | false | Enable notifications for issue events |
+| `confidential_issues_events` | boolean | false | Enable notifications for confidential issue events |
+| `merge_requests_events` | boolean | false | Enable notifications for merge request events |
+| `tag_push_events` | boolean | false | Enable notifications for tag push events |
+| `note_events` | boolean | false | Enable notifications for note events |
+| `pipeline_events` | boolean | false | Enable notifications for pipeline events |
+| `wiki_page_events` | boolean | false | Enable notifications for wiki page events |
+
+### Delete Hangouts Chat service
+
+Delete Hangouts Chat service for a project.
+
+```
+DELETE /projects/:id/services/hangouts_chat
+```
+
+### Get Hangouts Chat service settings
+
+Get Hangouts Chat service settings for a project.
+
+```
+GET /projects/:id/services/hangouts_chat
+```
+
## HipChat
Private group chat and IM
diff --git a/doc/ci/variables/README.md b/doc/ci/variables/README.md
index 84bd64d50cd..115e6e390c9 100644
--- a/doc/ci/variables/README.md
+++ b/doc/ci/variables/README.md
@@ -64,7 +64,7 @@ future GitLab releases.**
| **CI_JOB_MANUAL** | 8.12 | all | The flag to indicate that job was manually started |
| **CI_JOB_NAME** | 9.0 | 0.5 | The name of the job as defined in `.gitlab-ci.yml` |
| **CI_JOB_STAGE** | 9.0 | 0.5 | The name of the stage as defined in `.gitlab-ci.yml` |
-| **CI_JOB_TOKEN** | 9.0 | 1.2 | Token used for authenticating with the GitLab Container Registry |
+| **CI_JOB_TOKEN** | 9.0 | 1.2 | Token used for authenticating with the [GitLab Container Registry][registry] and downloading [dependent repositories][dependent-repositories] |
| **CI_JOB_URL** | 11.1 | 0.5 | Job details URL |
| **CI_REPOSITORY_URL** | 9.0 | all | The URL to clone the Git repository |
| **CI_RUNNER_DESCRIPTION** | 8.10 | 0.5 | The description of the runner as saved in GitLab |
@@ -566,3 +566,5 @@ Below you can find supported syntax reference:
[subgroups]: ../../user/group/subgroups/index.md
[builds-policies]: ../yaml/README.md#only-and-except-complex
[gitlab-deploy-token]: ../../user/project/deploy_tokens/index.md#gitlab-deploy-token
+[registry]: ../../user/project/container_registry.md
+[dependent-repositories]: ../../user/project/new_ci_build_permissions_model.md#dependent-repositories \ No newline at end of file
diff --git a/doc/ci/yaml/README.md b/doc/ci/yaml/README.md
index 096b64eb881..d95f8c7c8cc 100644
--- a/doc/ci/yaml/README.md
+++ b/doc/ci/yaml/README.md
@@ -1411,43 +1411,6 @@ variables:
You can set it globally or per-job in the [`variables`](#variables) section.
-### Custom build directories
-
-> [Introduced][gitlab-runner-876] in Gitlab Runner 11.1
-
-NOTE: **Note:**
-This can only be used when `custom_build_dir` is set to true in the [Runner's
-configuration](https://docs.gitlab.com/runner/configuration/advanced-configuration.html).
-
-By default, GitLab Runner clones the repository in the `/builds` directory,
-but sometimes your project might require to have the code in a specific
-directory, like the GO projects for example. In that case, you can specify
-the `CI_PROJECT_DIR` variable to tell the Runner in which directory to clone
-the repository:
-
-```yml
-image: golang:1.10-alpine3.7
-
-variables:
- CI_PROJECT_DIR: /go/src/gitlab.com/namespace/project-name
-
-stages:
- - test
-
-dir:
- stage: test
- script:
- - pwd # /go/src/gitlab.com/namespace/project-name
-```
-
-The following executors may use this feature only when
-[concurrent](https://docs.gitlab.com/runner/configuration/advanced-configuration.html#the-global-section)
-is set to `1`:
-
-- `shell`
-- `ssh`
-- `docker`, `docker+machine` when the job's working directory is mounted as a host volume.
-
## Special YAML features
It's possible to use special YAML features like anchors (`&`), aliases (`*`)
@@ -1641,6 +1604,5 @@ CI with various languages.
[ce-7983]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/7983
[ce-7447]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/7447
[ce-12909]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/12909
-[gitlab-runner-876]: https://gitlab.com/gitlab-org/gitlab-runner/merge_requests/876
[schedules]: ../../user/project/pipelines/schedules.md
[variables-expressions]: ../variables/README.md#variables-expressions
diff --git a/doc/development/README.md b/doc/development/README.md
index 5d6fed5bc72..fed3903c771 100644
--- a/doc/development/README.md
+++ b/doc/development/README.md
@@ -40,6 +40,7 @@ description: 'Learn how to contribute to GitLab.'
- [View sent emails or preview mailers](emails.md)
- [Shell commands](shell_commands.md) in the GitLab codebase
- [`Gemfile` guidelines](gemfile.md)
+- [Pry debugging](pry_debugging.md)
- [Sidekiq debugging](sidekiq_debugging.md)
- [Gotchas](gotchas.md) to avoid
- [Avoid modules with instance variables](module_with_instance_variables.md) if possible
diff --git a/doc/development/profiling.md b/doc/development/profiling.md
index 11878b4009b..0ca8bb67a77 100644
--- a/doc/development/profiling.md
+++ b/doc/development/profiling.md
@@ -42,6 +42,36 @@ Passing a `logger:` keyword argument to `Gitlab::Profiler.profile` will send
ActiveRecord and ActionController log output to that logger. Further options are
documented with the method source.
+There is also a RubyProf printer available:
+`Gitlab::Profiler::TotalTimeFlatPrinter`. This acts like
+`RubyProf::FlatPrinter`, but its `min_percent` option works on the method's
+total time, not its self time. (This is because we often spend most of our time
+in library code, but this comes from calls in our application.) It also offers a
+`max_percent` option to help filter out outer calls that aren't useful (like
+`ActionDispatch::Integration::Session#process`).
+
+There is a convenience method for using this,
+`Gitlab::Profiler.print_by_total_time`:
+
+```ruby
+result = Gitlab::Profiler.profile('/my-user')
+Gitlab::Profiler.print_by_total_time(result, max_percent: 60, min_percent: 2)
+# Measure Mode: wall_time
+# Thread ID: 70005223698240
+# Fiber ID: 70004894952580
+# Total: 1.768912
+# Sort by: total_time
+#
+# %self total self wait child calls name
+# 0.00 1.017 0.000 0.000 1.017 14 *ActionView::Helpers::RenderingHelper#render
+# 0.00 1.017 0.000 0.000 1.017 14 *ActionView::Renderer#render_partial
+# 0.00 1.017 0.000 0.000 1.017 14 *ActionView::PartialRenderer#render
+# 0.00 1.007 0.000 0.000 1.007 14 *ActionView::PartialRenderer#render_partial
+# 0.00 0.930 0.000 0.000 0.930 14 Hamlit::TemplateHandler#call
+# 0.00 0.928 0.000 0.000 0.928 14 Temple::Engine#call
+# 0.02 0.865 0.000 0.000 0.864 638 *Enumerable#inject
+```
+
[GitLab-Profiler](https://gitlab.com/gitlab-com/gitlab-profiler) is a project
that builds on this to add some additional niceties, such as allowing
configuration with a single Yaml file for multiple URLs, and uploading of the
diff --git a/doc/development/pry_debugging.md b/doc/development/pry_debugging.md
new file mode 100644
index 00000000000..de5e1323e6a
--- /dev/null
+++ b/doc/development/pry_debugging.md
@@ -0,0 +1,130 @@
+# Pry debugging
+
+## Invoking pry debugging
+
+To invoke the debugger, place `binding.pry` somewhere in your
+code. When the Ruby interpreter hits that code, execution will stop,
+and you can type in commands to debug the state of the program
+
+## `byebug` vs `binding.pry`
+
+`byebug` has a very similar interface as `gdb`, but `byebug` does not
+use the powerful Pry REPL.
+
+`binding.pry` uses Pry, but lacks some of the `byebug`
+features. GitLab uses the [`pry-byebug`](https://github.com/deivid-rodriguez/pry-byebug)
+gem. This gem brings some capabilities `byebug` to `binding.pry`, so
+using that, will give you the most debugging powers.
+
+## `byebug`
+
+Check out [the docs](https://github.com/deivid-rodriguez/byebug) for the full list of commands.
+
+You can start the Pry REPL with the `pry` command.
+
+## `pry`
+
+There are **a lot** of features present in `pry`, too much to cover in
+this document, so for the full documentation head over to the [Pry wiki](https://github.com/pry/pry/wiki).
+
+Below are a few features definitely worth checking out, also run
+`help` in a pry session to see what else you can do.
+
+### State navigation
+
+With the [state navigation](https://github.com/pry/pry/wiki/State-navigation)
+you can move around in the code to discover methods and such:
+
+```ruby
+# Change context
+[1] pry(main)> cd Pry
+[2] pry(Pry):1>
+
+# Print methods
+[2] pry(Pry):1> ls -m
+
+# Find a method
+[3] pry(Pry):1> find-method to_yaml
+```
+
+### Source browsing
+
+You [look at the source code](https://github.com/pry/pry/wiki/Source-browsing)
+from your `pry` session:
+
+```ruby
+[1] pry(main)> $ Array#first
+# The above is equivalent to
+[2] pry(main)> cd Array
+[3] pry(Array):1> show-source first
+```
+
+`$` is an alias for `show-source`.
+
+### Documentation browsing
+
+Similar to source browsing, is [Documentation browsing](https://github.com/pry/pry/wiki/Documentation-browsing).
+
+```ruby
+[1] pry(main)> show-doc Array#first
+```
+
+`?` is an alias for `show-doc`.
+
+### Command history
+
+With <kdb>Ctrl+R</kbd> you can search your [command history](https://github.com/pry/pry/wiki/History).
+
+## Stepping
+
+To step through the code, you can use the following commands:
+
+- `break`: Manage breakpoints.
+- `step`: Step execution into the next line or method. Takes an
+ optional numeric argument to step multiple times.
+- `next`: Step over to the next line within the same frame. Also takes
+ an optional numeric argument to step multiple lines.
+- `finish`: Execute until current stack frame returns.
+- `continue`: Continue program execution and end the Pry session.
+
+## Callstack navigation
+
+You also can move around in the callstack with these commands:
+
+- `backtrace`: Shows the current stack. You can use the numbers on the
+ left side with the frame command to navigate the stack.
+- `up`: Moves the stack frame up. Takes an optional numeric argument
+ to move multiple frames.
+- `down`: Moves the stack frame down. Takes an optional numeric
+ argument to move multiple frames.
+- `frame <n>`: Moves to a specific frame. Called without arguments
+ will show the current frame.
+
+## Short commands
+
+When you use `binding.pry` instead of `byebug`, the short commands
+like `s`, `n`, `f`, and `c` do not work. To reinstall them, add this
+to `~/.pryrc`:
+
+```ruby
+if defined?(PryByebug)
+ Pry.commands.alias_command 's', 'step'
+ Pry.commands.alias_command 'n', 'next'
+ Pry.commands.alias_command 'f', 'finish'
+ Pry.commands.alias_command 'c', 'continue'
+end
+```
+
+## Repeat last command
+
+You can repeat the last command by just hitting the <kbd>Enter</kbd>
+key (e.g., with `step` or`next`), if you place the following snippet
+in your `~/.pryrc`:
+
+```ruby
+Pry::Commands.command /^$/, "repeat last command" do
+ _pry_.run_command Pry.history.to_a.last
+end
+```
+
+`byebug` supports this out-of-the-box.
diff --git a/doc/development/testing_guide/best_practices.md b/doc/development/testing_guide/best_practices.md
index 1a926a660f1..acbfa1850b4 100644
--- a/doc/development/testing_guide/best_practices.md
+++ b/doc/development/testing_guide/best_practices.md
@@ -101,7 +101,7 @@ CHROME_HEADLESS=0 bundle exec rspec some_spec.rb
The test will go by quickly, but this will give you an idea of what's happening.
-You can also add `byebug` or `binding.pry` to pause execution and step through
+You can also add `byebug` or `binding.pry` to pause execution and [step through](../pry_debugging.md#stepping)
the test.
#### Screenshots
diff --git a/doc/topics/autodevops/index.md b/doc/topics/autodevops/index.md
index de1d366adc3..f5574506595 100644
--- a/doc/topics/autodevops/index.md
+++ b/doc/topics/autodevops/index.md
@@ -591,7 +591,7 @@ also be customized, and you can easily use a [custom buildpack](#custom-buildpac
| `CANARY_ENABLED` | From GitLab 11.0, this variable can be used to define a [deploy policy for canary environments](#deploy-policy-for-canary-environments). |
| `INCREMENTAL_ROLLOUT_ENABLED`| From GitLab 10.8, this variable can be used to enable an [incremental rollout](#incremental-rollout-to-production) of your application for the production environment. |
| `TEST_DISABLED` | From GitLab 11.0, this variable can be used to disable the `test` job. If the variable is present, the job will not be created. |
-| `CODEQUALITY_DISABLED` | From GitLab 11.0, this variable can be used to disable the `codequality` job. If the variable is present, the job will not be created. |
+| `CODE_QUALITY_DISABLED` | From GitLab 11.0, this variable can be used to disable the `codequality` job. If the variable is present, the job will not be created. |
| `SAST_DISABLED` | From GitLab 11.0, this variable can be used to disable the `sast` job. If the variable is present, the job will not be created. |
| `DEPENDENCY_SCANNING_DISABLED` | From GitLab 11.0, this variable can be used to disable the `dependency_scanning` job. If the variable is present, the job will not be created. |
| `CONTAINER_SCANNING_DISABLED` | From GitLab 11.0, this variable can be used to disable the `sast:container` job. If the variable is present, the job will not be created. |
diff --git a/doc/update/mysql_to_postgresql.md b/doc/update/mysql_to_postgresql.md
index 44e9f6c5516..7c6a14cb104 100644
--- a/doc/update/mysql_to_postgresql.md
+++ b/doc/update/mysql_to_postgresql.md
@@ -194,12 +194,18 @@ sudo apt-get install pgloader
1. Switch database from MySQL to PostgreSQL
- ``` bash
- cd /home/git/gitlab
- sudo -u git mv config/database.yml config/database.yml.bak
- sudo -u git cp config/database.yml.postgresql config/database.yml
- sudo -u git -H chmod o-rwx config/database.yml
- ```
+ ``` bash
+ cd /home/git/gitlab
+ sudo -u git mv config/database.yml config/database.yml.bak
+ sudo -u git cp config/database.yml.postgresql config/database.yml
+ sudo -u git -H chmod o-rwx config/database.yml
+ ```
+1. Install Gems related to Postgresql
+
+ ``` bash
+ sudo -u git -H rm .bundle/config
+ sudo -u git -H bundle install --deployment --without development test mysql aws kerberos
+ ```
1. Run the following commands to prepare the schema:
diff --git a/doc/user/project/clusters/index.md b/doc/user/project/clusters/index.md
index cc1d65e4e6c..7c552103412 100644
--- a/doc/user/project/clusters/index.md
+++ b/doc/user/project/clusters/index.md
@@ -167,7 +167,7 @@ twice, which can lead to confusion during deployments.
| [Ingress](https://kubernetes.io/docs/concepts/services-networking/ingress/) | 10.2+ | Ingress can provide load balancing, SSL termination, and name-based virtual hosting. It acts as a web proxy for your applications and is useful if you want to use [Auto DevOps] or deploy your own web apps. |
| [Prometheus](https://prometheus.io/docs/introduction/overview/) | 10.4+ | Prometheus is an open-source monitoring and alerting system useful to supervise your deployed applications. |
| [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. |
-| [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. **Note**: Authentication will be enabled for any user of the GitLab server via OAuth2. HTTPS will be supported in a future release. |
+| [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. **Note**: Authentication will be enabled for any user of the GitLab server via OAuth2. HTTPS will be supported in a future release. |
## Getting the external IP address
diff --git a/doc/user/project/integrations/emails_on_push.md b/doc/user/project/integrations/emails_on_push.md
index c01da883562..b050c83fb72 100644
--- a/doc/user/project/integrations/emails_on_push.md
+++ b/doc/user/project/integrations/emails_on_push.md
@@ -6,7 +6,7 @@ every change that is pushed to your project.
Navigate to the [Integrations page](project_services.md#accessing-the-project-services)
and select the **Emails on push** service to configure it.
-In the _Recipients_ area, provide a list of emails separated by commas.
+In the _Recipients_ area, provide a list of emails separated by spaces or newlines.
You can configure any of the following settings depending on your preference.
diff --git a/doc/user/project/integrations/hangouts_chat.md b/doc/user/project/integrations/hangouts_chat.md
new file mode 100644
index 00000000000..6ab44420a10
--- /dev/null
+++ b/doc/user/project/integrations/hangouts_chat.md
@@ -0,0 +1,27 @@
+# Hangouts Chat service
+
+The Hangouts Chat service sends notifications from GitLab to the room for which the webhook was created.
+
+## On Hangouts Chat
+
+1. Open the chat room in which you want to see the notifications.
+1. From the chat room menu, select **Configure Webhooks**.
+1. Click on **ADD WEBHOOK** and fill in the name of the bot that will post the messages. Optionally define avatar.
+1. Click **SAVE** and copy the **Webhook URL** of your webhook.
+
+See also [the Hangouts Chat documentation for configuring incoming webhooks](https://developers.google.com/hangouts/chat/how-tos/webhooks)
+
+## On GitLab
+
+When you have the **Webhook URL** for your Hangouts Chat room webhook, you can setup the GitLab service.
+
+1. Navigate to the [Integrations page](project_services.md#accessing-the-project-services) in your project's settings, i.e. **Project > Settings > Integrations**.
+1. Select the **Hangouts Chat** project service to configure it.
+1. Check the **Active** checkbox to turn on the service.
+1. Check the checkboxes corresponding to the GitLab events you want to receive.
+1. Paste the **Webhook URL** that you copied from the Hangouts Chat configuration step.
+1. Configure the remaining options and click `Save changes`.
+
+Your Hangouts Chat room will now start receiving GitLab event notifications as configured.
+
+![Hangouts Chat configuration](img/hangouts_chat_configuration.png)
diff --git a/doc/user/project/integrations/img/hangouts_chat_configuration.png b/doc/user/project/integrations/img/hangouts_chat_configuration.png
new file mode 100644
index 00000000000..33fadbe6547
--- /dev/null
+++ b/doc/user/project/integrations/img/hangouts_chat_configuration.png
Binary files differ
diff --git a/doc/user/project/integrations/project_services.md b/doc/user/project/integrations/project_services.md
index 8c51eb9915e..05ee1b4e6d7 100644
--- a/doc/user/project/integrations/project_services.md
+++ b/doc/user/project/integrations/project_services.md
@@ -35,6 +35,7 @@ Click on the service links to see further configuration instructions and details
| External Wiki | Replaces the link to the internal wiki with a link to an external wiki |
| Flowdock | Flowdock is a collaboration web app for technical teams |
| Gemnasium _(Has been deprecated in GitLab 11.0)_ | Gemnasium monitors your project dependencies and alerts you about updates and security vulnerabilities |
+| [Hangouts Chat](hangouts_chat.md) | Receive events notifications in Google Hangouts Chat |
| [HipChat](hipchat.md) | Private group chat and IM |
| [Irker (IRC gateway)](irker.md) | Send IRC messages, on update, to a list of recipients through an Irker gateway |
| [JIRA](jira.md) | JIRA issue tracker |
diff --git a/doc/user/project/merge_requests/img/merge_request.png b/doc/user/project/merge_requests/img/merge_request.png
index f9ca6348953..61b61122b11 100644
--- a/doc/user/project/merge_requests/img/merge_request.png
+++ b/doc/user/project/merge_requests/img/merge_request.png
Binary files differ
diff --git a/doc/user/project/milestones/img/milestones_new_group_milestone.png b/doc/user/project/milestones/img/milestones_new_group_milestone.png
index 8780394d72e..b6defab101d 100644
--- a/doc/user/project/milestones/img/milestones_new_group_milestone.png
+++ b/doc/user/project/milestones/img/milestones_new_group_milestone.png
Binary files differ
diff --git a/doc/user/project/milestones/img/milestones_new_project_milestone.png b/doc/user/project/milestones/img/milestones_new_project_milestone.png
index ba058428dfa..9aaff7dfef1 100644
--- a/doc/user/project/milestones/img/milestones_new_project_milestone.png
+++ b/doc/user/project/milestones/img/milestones_new_project_milestone.png
Binary files differ
diff --git a/doc/user/project/milestones/img/milestones_promote_milestone.png b/doc/user/project/milestones/img/milestones_promote_milestone.png
index 99bee1240d4..5e7f94c316f 100644
--- a/doc/user/project/milestones/img/milestones_promote_milestone.png
+++ b/doc/user/project/milestones/img/milestones_promote_milestone.png
Binary files differ
diff --git a/lib/api/entities.rb b/lib/api/entities.rb
index 3f3a95ea8e6..464a31ee819 100644
--- a/lib/api/entities.rb
+++ b/lib/api/entities.rb
@@ -132,6 +132,7 @@ module API
expose :star_count, :forks_count
expose :last_activity_at
+ expose :namespace, using: 'API::Entities::NamespaceBasic'
expose :custom_attributes, using: 'API::Entities::CustomAttribute', if: :with_custom_attributes
def self.preload_relation(projects_relation, options = {})
@@ -194,7 +195,6 @@ module API
expose :shared_runners_enabled
expose :lfs_enabled?, as: :lfs_enabled
expose :creator_id
- expose :namespace, using: 'API::Entities::NamespaceBasic'
expose :forked_from_project, using: Entities::BasicProjectDetails, if: lambda { |project, options| project.forked? }
expose :import_status
expose :import_error, if: lambda { |_project, options| options[:user_can_admin_project] }
@@ -529,6 +529,10 @@ module API
class PipelineBasic < Grape::Entity
expose :id, :sha, :ref, :status
+
+ expose :web_url do |pipeline, _options|
+ Gitlab::Routing.url_helpers.project_pipeline_url(pipeline.project, pipeline)
+ end
end
class MergeRequestSimple < ProjectEntity
@@ -1069,6 +1073,10 @@ module API
expose :user, with: User
expose :commit, with: Commit
expose :pipeline, with: PipelineBasic
+
+ expose :web_url do |job, _options|
+ Gitlab::Routing.url_helpers.project_job_url(job.project, job)
+ end
end
class Job < JobBasic
diff --git a/lib/api/groups.rb b/lib/api/groups.rb
index 797b04df059..b4f441f6a4f 100644
--- a/lib/api/groups.rb
+++ b/lib/api/groups.rb
@@ -34,11 +34,12 @@ module API
optional :owned, type: Boolean, default: false, desc: 'Limit by owned by authenticated user'
optional :order_by, type: String, values: %w[name path id], default: 'name', desc: 'Order by name, path or id'
optional :sort, type: String, values: %w[asc desc], default: 'asc', desc: 'Sort by asc (ascending) or desc (descending)'
+ optional :min_access_level, type: Integer, values: Gitlab::Access.all_values, desc: 'Minimum access level of authenticated user'
use :pagination
end
def find_groups(params, parent_id = nil)
- find_params = params.slice(:all_available, :custom_attributes, :owned)
+ find_params = params.slice(:all_available, :custom_attributes, :owned, :min_access_level)
find_params[:parent] = find_group!(parent_id) if parent_id
find_params[:all_available] =
find_params.fetch(:all_available, current_user&.full_private_access?)
diff --git a/lib/api/helpers.rb b/lib/api/helpers.rb
index f7737468148..be17653dbb2 100644
--- a/lib/api/helpers.rb
+++ b/lib/api/helpers.rb
@@ -389,6 +389,7 @@ module API
finder_params[:search] = params[:search] if params[:search]
finder_params[:user] = params.delete(:user) if params[:user]
finder_params[:custom_attributes] = params[:custom_attributes] if params[:custom_attributes]
+ finder_params[:min_access_level] = params[:min_access_level] if params[:min_access_level]
finder_params
end
diff --git a/lib/api/jobs.rb b/lib/api/jobs.rb
index e95b0dd5267..10c6e565f09 100644
--- a/lib/api/jobs.rb
+++ b/lib/api/jobs.rb
@@ -54,7 +54,7 @@ module API
pipeline = user_project.pipelines.find(params[:pipeline_id])
builds = pipeline.builds
builds = filter_builds(builds, params[:scope])
- builds = builds.preload(:job_artifacts_archive)
+ builds = builds.preload(:job_artifacts_archive, project: [:namespace])
present paginate(builds), with: Entities::Job
end
diff --git a/lib/api/projects.rb b/lib/api/projects.rb
index 0888e3befac..eadde7b17bb 100644
--- a/lib/api/projects.rb
+++ b/lib/api/projects.rb
@@ -9,6 +9,21 @@ module API
before { authenticate_non_get! }
helpers do
+ params :optional_filter_params_ee do
+ # EE::API::Projects would override this helper
+ end
+
+ # EE::API::Projects would override this method
+ def apply_filters(projects)
+ projects = projects.with_issues_available_for_user(current_user) if params[:with_issues_enabled]
+ projects = projects.with_merge_requests_enabled if params[:with_merge_requests_enabled]
+ projects = projects.with_statistics if params[:statistics]
+
+ projects
+ end
+ end
+
+ helpers do
params :statistics_params do
optional :statistics, type: Boolean, default: false, desc: 'Include project statistics'
end
@@ -39,6 +54,9 @@ module API
optional :membership, type: Boolean, default: false, desc: 'Limit by projects that the current user is a member of'
optional :with_issues_enabled, type: Boolean, default: false, desc: 'Limit by enabled issues feature'
optional :with_merge_requests_enabled, type: Boolean, default: false, desc: 'Limit by enabled merge requests feature'
+ optional :min_access_level, type: Integer, values: Gitlab::Access.all_values, desc: 'Limit by minimum access level of authenticated user'
+
+ use :optional_filter_params_ee
end
params :create_params do
@@ -52,9 +70,7 @@ module API
def present_projects(projects, options = {})
projects = reorder_projects(projects)
- projects = projects.with_issues_available_for_user(current_user) if params[:with_issues_enabled]
- projects = projects.with_merge_requests_enabled if params[:with_merge_requests_enabled]
- projects = projects.with_statistics if params[:statistics]
+ projects = apply_filters(projects)
projects = paginate(projects)
projects, options = with_custom_attributes(projects, options)
diff --git a/lib/api/services.rb b/lib/api/services.rb
index 553e8dff4b9..1f2bf546cd7 100644
--- a/lib/api/services.rb
+++ b/lib/api/services.rb
@@ -368,6 +368,14 @@ module API
desc: "The project's slug on gemnasium.com"
}
],
+ 'hangouts-chat' => [
+ {
+ required: true,
+ name: :webhook,
+ type: String,
+ desc: 'The Hangouts Chat webhook. e.g. https://chat.googleapis.com/v1/spaces…'
+ }
+ ],
'hipchat' => [
{
required: true,
@@ -688,6 +696,7 @@ module API
ExternalWikiService,
FlowdockService,
GemnasiumService,
+ HangoutsChatService,
HipchatService,
IrkerService,
JiraService,
diff --git a/lib/api/users.rb b/lib/api/users.rb
index 5aaaf104dff..6da6c2b43de 100644
--- a/lib/api/users.rb
+++ b/lib/api/users.rb
@@ -42,6 +42,7 @@ module API
optional :can_create_group, type: Boolean, desc: 'Flag indicating the user can create groups'
optional :external, type: Boolean, desc: 'Flag indicating the user is an external user'
optional :avatar, type: File, desc: 'Avatar image for user'
+ optional :min_access_level, type: Integer, values: Gitlab::Access.all_values, desc: 'Limit by minimum access level of authenticated user'
all_or_none_of :extern_uid, :provider
end
diff --git a/lib/banzai/filter/absolute_link_filter.rb b/lib/banzai/filter/absolute_link_filter.rb
index 1ec6201523f..04ec568eee3 100644
--- a/lib/banzai/filter/absolute_link_filter.rb
+++ b/lib/banzai/filter/absolute_link_filter.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'uri'
module Banzai
diff --git a/lib/banzai/filter/abstract_reference_filter.rb b/lib/banzai/filter/abstract_reference_filter.rb
index b39b11009b3..ad0806df8e6 100644
--- a/lib/banzai/filter/abstract_reference_filter.rb
+++ b/lib/banzai/filter/abstract_reference_filter.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Banzai
module Filter
# Issues, Merge Requests, Snippets, Commits and Commit Ranges share
diff --git a/lib/banzai/filter/ascii_doc_post_processing_filter.rb b/lib/banzai/filter/ascii_doc_post_processing_filter.rb
index c9fcf057c5f..88439f06b5f 100644
--- a/lib/banzai/filter/ascii_doc_post_processing_filter.rb
+++ b/lib/banzai/filter/ascii_doc_post_processing_filter.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Banzai
module Filter
class AsciiDocPostProcessingFilter < HTML::Pipeline::Filter
diff --git a/lib/banzai/filter/autolink_filter.rb b/lib/banzai/filter/autolink_filter.rb
index 4a143baeef6..deda4b1872e 100644
--- a/lib/banzai/filter/autolink_filter.rb
+++ b/lib/banzai/filter/autolink_filter.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'uri'
module Banzai
diff --git a/lib/banzai/filter/blockquote_fence_filter.rb b/lib/banzai/filter/blockquote_fence_filter.rb
index 7108e828c6d..ad367cc5efe 100644
--- a/lib/banzai/filter/blockquote_fence_filter.rb
+++ b/lib/banzai/filter/blockquote_fence_filter.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Banzai
module Filter
class BlockquoteFenceFilter < HTML::Pipeline::TextFilter
diff --git a/lib/banzai/filter/color_filter.rb b/lib/banzai/filter/color_filter.rb
index 6ab29ac281f..6d9bdb9cbd3 100644
--- a/lib/banzai/filter/color_filter.rb
+++ b/lib/banzai/filter/color_filter.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Banzai
module Filter
# HTML filter that renders `color` followed by a color "chip".
diff --git a/lib/banzai/filter/commit_range_reference_filter.rb b/lib/banzai/filter/commit_range_reference_filter.rb
index 01b3b0dafb9..d6b46236a49 100644
--- a/lib/banzai/filter/commit_range_reference_filter.rb
+++ b/lib/banzai/filter/commit_range_reference_filter.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Banzai
module Filter
# HTML filter that replaces commit range references with links.
diff --git a/lib/banzai/filter/commit_reference_filter.rb b/lib/banzai/filter/commit_reference_filter.rb
index 8cd92a1adba..c3e5ac41cb8 100644
--- a/lib/banzai/filter/commit_reference_filter.rb
+++ b/lib/banzai/filter/commit_reference_filter.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Banzai
module Filter
# HTML filter that replaces commit references with links.
diff --git a/lib/banzai/filter/commit_trailers_filter.rb b/lib/banzai/filter/commit_trailers_filter.rb
index 7b55e8b36f6..f49c4b403db 100644
--- a/lib/banzai/filter/commit_trailers_filter.rb
+++ b/lib/banzai/filter/commit_trailers_filter.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Banzai
module Filter
# HTML filter that replaces users' names and emails in commit trailers
diff --git a/lib/banzai/filter/emoji_filter.rb b/lib/banzai/filter/emoji_filter.rb
index 4eccd9d5ed5..c87948a30bf 100644
--- a/lib/banzai/filter/emoji_filter.rb
+++ b/lib/banzai/filter/emoji_filter.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Banzai
module Filter
# HTML filter that replaces :emoji: and unicode with images.
diff --git a/lib/banzai/filter/epic_reference_filter.rb b/lib/banzai/filter/epic_reference_filter.rb
index 265924abe24..e06e2fb3870 100644
--- a/lib/banzai/filter/epic_reference_filter.rb
+++ b/lib/banzai/filter/epic_reference_filter.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Banzai
module Filter
# The actual filter is implemented in the EE mixin
diff --git a/lib/banzai/filter/external_issue_reference_filter.rb b/lib/banzai/filter/external_issue_reference_filter.rb
index ed01a72ff9f..b4a7a44e109 100644
--- a/lib/banzai/filter/external_issue_reference_filter.rb
+++ b/lib/banzai/filter/external_issue_reference_filter.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Banzai
module Filter
# HTML filter that replaces external issue tracker references with links.
diff --git a/lib/banzai/filter/external_link_filter.rb b/lib/banzai/filter/external_link_filter.rb
index d6327ef31cb..2e6d742de27 100644
--- a/lib/banzai/filter/external_link_filter.rb
+++ b/lib/banzai/filter/external_link_filter.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Banzai
module Filter
# HTML Filter to modify the attributes of external links
diff --git a/lib/banzai/filter/gollum_tags_filter.rb b/lib/banzai/filter/gollum_tags_filter.rb
index bb9f488cd87..0c1bbd2d250 100644
--- a/lib/banzai/filter/gollum_tags_filter.rb
+++ b/lib/banzai/filter/gollum_tags_filter.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Banzai
module Filter
# HTML Filter for parsing Gollum's tags in HTML. It's only parses the
diff --git a/lib/banzai/filter/html_entity_filter.rb b/lib/banzai/filter/html_entity_filter.rb
index e008fd428b0..406c2d3c96b 100644
--- a/lib/banzai/filter/html_entity_filter.rb
+++ b/lib/banzai/filter/html_entity_filter.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'erb'
module Banzai
diff --git a/lib/banzai/filter/image_lazy_load_filter.rb b/lib/banzai/filter/image_lazy_load_filter.rb
index 4cd9b02b76c..afaee70f351 100644
--- a/lib/banzai/filter/image_lazy_load_filter.rb
+++ b/lib/banzai/filter/image_lazy_load_filter.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Banzai
module Filter
# HTML filter that moves the value of image `src` attributes to `data-src`
@@ -5,7 +7,7 @@ module Banzai
class ImageLazyLoadFilter < HTML::Pipeline::Filter
def call
doc.xpath('descendant-or-self::img').each do |img|
- img['class'] ||= '' << 'lazy'
+ img.add_class('lazy')
img['data-src'] = img['src']
img['src'] = LazyImageTagHelper.placeholder_image
end
diff --git a/lib/banzai/filter/image_link_filter.rb b/lib/banzai/filter/image_link_filter.rb
index f318c425962..884a94fb761 100644
--- a/lib/banzai/filter/image_link_filter.rb
+++ b/lib/banzai/filter/image_link_filter.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Banzai
module Filter
# HTML filter that wraps links around inline images.
diff --git a/lib/banzai/filter/inline_diff_filter.rb b/lib/banzai/filter/inline_diff_filter.rb
index 73e82a4d7e3..e9ddc6e0e3d 100644
--- a/lib/banzai/filter/inline_diff_filter.rb
+++ b/lib/banzai/filter/inline_diff_filter.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Banzai
module Filter
class InlineDiffFilter < HTML::Pipeline::Filter
diff --git a/lib/banzai/filter/issuable_reference_filter.rb b/lib/banzai/filter/issuable_reference_filter.rb
index 7addf09be73..2963cba91e8 100644
--- a/lib/banzai/filter/issuable_reference_filter.rb
+++ b/lib/banzai/filter/issuable_reference_filter.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Banzai
module Filter
class IssuableReferenceFilter < AbstractReferenceFilter
diff --git a/lib/banzai/filter/issuable_state_filter.rb b/lib/banzai/filter/issuable_state_filter.rb
index 1a415232545..d7fe012883d 100644
--- a/lib/banzai/filter/issuable_state_filter.rb
+++ b/lib/banzai/filter/issuable_state_filter.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Banzai
module Filter
# HTML filter that appends state information to issuable links.
diff --git a/lib/banzai/filter/issue_reference_filter.rb b/lib/banzai/filter/issue_reference_filter.rb
index 6877cae8c55..f85be042999 100644
--- a/lib/banzai/filter/issue_reference_filter.rb
+++ b/lib/banzai/filter/issue_reference_filter.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Banzai
module Filter
# HTML filter that replaces issue references with links. References to
diff --git a/lib/banzai/filter/label_reference_filter.rb b/lib/banzai/filter/label_reference_filter.rb
index a5f38046a43..b92e9e55bb9 100644
--- a/lib/banzai/filter/label_reference_filter.rb
+++ b/lib/banzai/filter/label_reference_filter.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Banzai
module Filter
# HTML filter that replaces label references with links.
diff --git a/lib/banzai/filter/markdown_filter.rb b/lib/banzai/filter/markdown_filter.rb
index 944363f17d3..cdf758472c1 100644
--- a/lib/banzai/filter/markdown_filter.rb
+++ b/lib/banzai/filter/markdown_filter.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Banzai
module Filter
class MarkdownFilter < HTML::Pipeline::TextFilter
diff --git a/lib/banzai/filter/math_filter.rb b/lib/banzai/filter/math_filter.rb
index b6e784c886b..9d1bc3cf60c 100644
--- a/lib/banzai/filter/math_filter.rb
+++ b/lib/banzai/filter/math_filter.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'uri'
module Banzai
diff --git a/lib/banzai/filter/merge_request_reference_filter.rb b/lib/banzai/filter/merge_request_reference_filter.rb
index 10c40568006..7098767b583 100644
--- a/lib/banzai/filter/merge_request_reference_filter.rb
+++ b/lib/banzai/filter/merge_request_reference_filter.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Banzai
module Filter
# HTML filter that replaces merge request references with links. References
diff --git a/lib/banzai/filter/mermaid_filter.rb b/lib/banzai/filter/mermaid_filter.rb
index 65c131e08d9..7c8b165a330 100644
--- a/lib/banzai/filter/mermaid_filter.rb
+++ b/lib/banzai/filter/mermaid_filter.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Banzai
module Filter
class MermaidFilter < HTML::Pipeline::Filter
diff --git a/lib/banzai/filter/milestone_reference_filter.rb b/lib/banzai/filter/milestone_reference_filter.rb
index af8448937b3..328c8c1803b 100644
--- a/lib/banzai/filter/milestone_reference_filter.rb
+++ b/lib/banzai/filter/milestone_reference_filter.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Banzai
module Filter
# HTML filter that replaces milestone references with links.
diff --git a/lib/banzai/filter/plantuml_filter.rb b/lib/banzai/filter/plantuml_filter.rb
index 28933c78966..caba8955bac 100644
--- a/lib/banzai/filter/plantuml_filter.rb
+++ b/lib/banzai/filter/plantuml_filter.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "nokogiri"
require "asciidoctor-plantuml/plantuml"
diff --git a/lib/banzai/filter/redactor_filter.rb b/lib/banzai/filter/redactor_filter.rb
index caf11fe94c4..1f091f594f8 100644
--- a/lib/banzai/filter/redactor_filter.rb
+++ b/lib/banzai/filter/redactor_filter.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Banzai
module Filter
# HTML filter that removes references to records that the current user does
diff --git a/lib/banzai/filter/reference_filter.rb b/lib/banzai/filter/reference_filter.rb
index 2411dd2cdfc..e5164e7f72a 100644
--- a/lib/banzai/filter/reference_filter.rb
+++ b/lib/banzai/filter/reference_filter.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Banzai
module Filter
# Base class for GitLab Flavored Markdown reference filters.
diff --git a/lib/banzai/filter/relative_link_filter.rb b/lib/banzai/filter/relative_link_filter.rb
index 262458a872a..8e838d04bad 100644
--- a/lib/banzai/filter/relative_link_filter.rb
+++ b/lib/banzai/filter/relative_link_filter.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'uri'
module Banzai
diff --git a/lib/banzai/filter/sanitization_filter.rb b/lib/banzai/filter/sanitization_filter.rb
index 8275bb9e149..80b9d3d045f 100644
--- a/lib/banzai/filter/sanitization_filter.rb
+++ b/lib/banzai/filter/sanitization_filter.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Banzai
module Filter
# Sanitize HTML
diff --git a/lib/banzai/filter/set_direction_filter.rb b/lib/banzai/filter/set_direction_filter.rb
index c2976aeb7c6..45b259a2faf 100644
--- a/lib/banzai/filter/set_direction_filter.rb
+++ b/lib/banzai/filter/set_direction_filter.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Banzai
module Filter
# HTML filter that sets dir="auto" for RTL languages support
diff --git a/lib/banzai/filter/snippet_reference_filter.rb b/lib/banzai/filter/snippet_reference_filter.rb
index 881e10afb9f..f4b6edb6174 100644
--- a/lib/banzai/filter/snippet_reference_filter.rb
+++ b/lib/banzai/filter/snippet_reference_filter.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Banzai
module Filter
# HTML filter that replaces snippet references with links. References to
diff --git a/lib/banzai/filter/syntax_highlight_filter.rb b/lib/banzai/filter/syntax_highlight_filter.rb
index 6dbf0d68fe8..8a7f9045c24 100644
--- a/lib/banzai/filter/syntax_highlight_filter.rb
+++ b/lib/banzai/filter/syntax_highlight_filter.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'rouge/plugins/common_mark'
require 'rouge/plugins/redcarpet'
@@ -15,7 +17,7 @@ module Banzai
end
def highlight_node(node)
- css_classes = 'code highlight js-syntax-highlight'
+ css_classes = +'code highlight js-syntax-highlight'
lang = node.attr('lang')
retried = false
diff --git a/lib/banzai/filter/table_of_contents_filter.rb b/lib/banzai/filter/table_of_contents_filter.rb
index b32660a8341..c6d1e028eaa 100644
--- a/lib/banzai/filter/table_of_contents_filter.rb
+++ b/lib/banzai/filter/table_of_contents_filter.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Banzai
module Filter
# HTML filter that adds an anchor child element to all Headers in a
@@ -19,7 +21,7 @@ module Banzai
def call
return doc if context[:no_header_anchors]
- result[:toc] = ""
+ result[:toc] = +""
headers = Hash.new(0)
header_root = current_header = HeaderNode.new
diff --git a/lib/banzai/filter/task_list_filter.rb b/lib/banzai/filter/task_list_filter.rb
index 9fa5f589f3e..ef35a49edcb 100644
--- a/lib/banzai/filter/task_list_filter.rb
+++ b/lib/banzai/filter/task_list_filter.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'task_list/filter'
module Banzai
diff --git a/lib/banzai/filter/user_reference_filter.rb b/lib/banzai/filter/user_reference_filter.rb
index c7fa8a8119f..11960047e5b 100644
--- a/lib/banzai/filter/user_reference_filter.rb
+++ b/lib/banzai/filter/user_reference_filter.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Banzai
module Filter
# HTML filter that replaces user or group references with links.
diff --git a/lib/banzai/filter/video_link_filter.rb b/lib/banzai/filter/video_link_filter.rb
index 35cb10eae5d..0fb59c914c3 100644
--- a/lib/banzai/filter/video_link_filter.rb
+++ b/lib/banzai/filter/video_link_filter.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Banzai
module Filter
# Find every image that isn't already wrapped in an `a` tag, and that has
diff --git a/lib/banzai/filter/wiki_link_filter.rb b/lib/banzai/filter/wiki_link_filter.rb
index 269d5bf74fa..870721f895d 100644
--- a/lib/banzai/filter/wiki_link_filter.rb
+++ b/lib/banzai/filter/wiki_link_filter.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'uri'
module Banzai
diff --git a/lib/banzai/filter/yaml_front_matter_filter.rb b/lib/banzai/filter/yaml_front_matter_filter.rb
index 58e3e81209e..295964dd75d 100644
--- a/lib/banzai/filter/yaml_front_matter_filter.rb
+++ b/lib/banzai/filter/yaml_front_matter_filter.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Banzai
module Filter
class YamlFrontMatterFilter < HTML::Pipeline::Filter
diff --git a/lib/feature.rb b/lib/feature.rb
index 314ae224d90..d27b2b0e72f 100644
--- a/lib/feature.rb
+++ b/lib/feature.rb
@@ -39,7 +39,7 @@ class Feature
# Flipper creates on-memory features when asked for a not-yet-created one.
# If we want to check if a feature has been actually set, we look for it
# on the persisted features list.
- persisted_names.include?(feature.name)
+ persisted_names.include?(feature.name.to_s)
end
def enabled?(key, thing = nil)
diff --git a/lib/gitlab/auth.rb b/lib/gitlab/auth.rb
index 7de66539848..111e18b2076 100644
--- a/lib/gitlab/auth.rb
+++ b/lib/gitlab/auth.rb
@@ -14,23 +14,8 @@ module Gitlab
DEFAULT_SCOPES = [:api].freeze
class << self
- def omniauth_customized_providers
- @omniauth_customized_providers ||= %w[bitbucket jwt]
- end
-
- def omniauth_setup_providers(provider_names)
- provider_names.each do |provider|
- omniauth_setup_a_provider(provider)
- end
- end
-
- def omniauth_setup_a_provider(provider)
- case provider
- when 'kerberos'
- require 'omniauth-kerberos'
- when *omniauth_customized_providers
- require_dependency "omni_auth/strategies/#{provider}"
- end
+ def omniauth_enabled?
+ Gitlab.config.omniauth.enabled
end
def find_for_git_client(login, password, project:, ip:)
diff --git a/lib/gitlab/auth/o_auth/provider.rb b/lib/gitlab/auth/o_auth/provider.rb
index 5fb61ffe00d..e73743944a9 100644
--- a/lib/gitlab/auth/o_auth/provider.rb
+++ b/lib/gitlab/auth/o_auth/provider.rb
@@ -30,7 +30,7 @@ module Gitlab
def self.enabled?(name)
return true if name == 'database'
- providers.include?(name.to_sym)
+ Gitlab::Auth.omniauth_enabled? && providers.include?(name.to_sym)
end
def self.ldap_provider?(name)
diff --git a/lib/gitlab/ci/variables/collection/item.rb b/lib/gitlab/ci/variables/collection/item.rb
index 222aa06b800..7da6d09d440 100644
--- a/lib/gitlab/ci/variables/collection/item.rb
+++ b/lib/gitlab/ci/variables/collection/item.rb
@@ -34,7 +34,7 @@ module Gitlab
def self.fabricate(resource)
case resource
when Hash
- self.new(resource)
+ self.new(resource.symbolize_keys)
when ::HasVariable
self.new(resource.to_runner_variable)
when self
diff --git a/lib/gitlab/git/operation_service.rb b/lib/gitlab/git/operation_service.rb
index 280def182d5..57d748343be 100644
--- a/lib/gitlab/git/operation_service.rb
+++ b/lib/gitlab/git/operation_service.rb
@@ -8,6 +8,8 @@ module Gitlab
alias_method :branch_created?, :branch_created
def self.from_gitaly(branch_update)
+ return if branch_update.nil?
+
new(
branch_update.commit_id,
branch_update.repo_created,
diff --git a/lib/gitlab/git/repository.rb b/lib/gitlab/git/repository.rb
index 39fbf6e2526..7bd5927d15e 100644
--- a/lib/gitlab/git/repository.rb
+++ b/lib/gitlab/git/repository.rb
@@ -1,4 +1,3 @@
-# Gitlab::Git::Repository is a wrapper around native Rugged::Repository object
require 'tempfile'
require 'forwardable'
require "rubygems/package"
@@ -673,35 +672,17 @@ module Gitlab
# If `mirror_refmap` is present the remote is set as mirror with that mapping
def add_remote(remote_name, url, mirror_refmap: nil)
- gitaly_migrate(:remote_add_remote) do |is_enabled|
- if is_enabled
- gitaly_remote_client.add_remote(remote_name, url, mirror_refmap)
- else
- rugged_add_remote(remote_name, url, mirror_refmap)
- end
+ wrapped_gitaly_errors do
+ gitaly_remote_client.add_remote(remote_name, url, mirror_refmap)
end
end
def remove_remote(remote_name)
- gitaly_migrate(:remote_remove_remote) do |is_enabled|
- if is_enabled
- gitaly_remote_client.remove_remote(remote_name)
- else
- rugged_remove_remote(remote_name)
- end
+ wrapped_gitaly_errors do
+ gitaly_remote_client.remove_remote(remote_name)
end
end
- # Update the specified remote using the values in the +options+ hash
- #
- # Example
- # repo.update_remote("origin", url: "path/to/repo")
- def remote_update(remote_name, url:)
- # TODO: Implement other remote options
- rugged.remotes.set_url(remote_name, url)
- nil
- end
-
AUTOCRLF_VALUES = {
"true" => true,
"false" => false,
@@ -845,6 +826,10 @@ module Gitlab
end
end
+ # This method, fetch_ref, is used from within
+ # Gitlab::Git::OperationService. OperationService will eventually only
+ # exist in gitaly-ruby. When we delete OperationService from gitlab-ce
+ # we can also remove fetch_ref.
def fetch_ref(source_repository, source_ref:, target_ref:)
Gitlab::Git.check_namespace!(source_repository)
source_repository = RemoteRepository.new(source_repository) unless source_repository.is_a?(RemoteRepository)
@@ -875,12 +860,8 @@ module Gitlab
end
def fetch_repository_as_mirror(repository)
- gitaly_migrate(:remote_fetch_internal_remote) do |is_enabled|
- if is_enabled
- gitaly_remote_client.fetch_internal_remote(repository)
- else
- rugged_fetch_repository_as_mirror(repository)
- end
+ wrapped_gitaly_errors do
+ gitaly_remote_client.fetch_internal_remote(repository)
end
end
@@ -1276,47 +1257,10 @@ module Gitlab
run_git(args, env: source_repository.fetch_env)
end
- def rugged_add_remote(remote_name, url, mirror_refmap)
- rugged.remotes.create(remote_name, url)
-
- set_remote_as_mirror(remote_name, refmap: mirror_refmap) if mirror_refmap
- rescue Rugged::ConfigError
- remote_update(remote_name, url: url)
- end
-
def gitaly_delete_refs(*ref_names)
gitaly_ref_client.delete_refs(refs: ref_names) if ref_names.any?
end
- def rugged_remove_remote(remote_name)
- # When a remote is deleted all its remote refs are deleted too, but in
- # the case of mirrors we map its refs (that would usualy go under
- # [remote_name]/) to the top level namespace. We clean the mapping so
- # those don't get deleted.
- if rugged.config["remote.#{remote_name}.mirror"]
- rugged.config.delete("remote.#{remote_name}.fetch")
- end
-
- rugged.remotes.delete(remote_name)
- true
- rescue Rugged::ConfigError
- false
- end
-
- def rugged_fetch_repository_as_mirror(repository)
- remote_name = "tmp-#{SecureRandom.hex}"
- repository = RemoteRepository.new(repository) unless repository.is_a?(RemoteRepository)
-
- add_remote(remote_name, GITALY_INTERNAL_URL, mirror_refmap: :all_refs)
- fetch_remote(remote_name, env: repository.fetch_env)
- ensure
- remove_remote(remote_name)
- end
-
- def fetch_remote(remote_name = 'origin', env: nil)
- run_git(['fetch', remote_name], env: env).last.zero?
- end
-
def gitlab_projects_error
raise CommandError, @gitlab_projects.output
end
diff --git a/lib/gitlab/git/repository_mirroring.rb b/lib/gitlab/git/repository_mirroring.rb
index 9faa62be28e..8835bfb2481 100644
--- a/lib/gitlab/git/repository_mirroring.rb
+++ b/lib/gitlab/git/repository_mirroring.rb
@@ -1,49 +1,19 @@
module Gitlab
module Git
module RepositoryMirroring
- REFMAPS = {
- # With `:all_refs`, the repository is equivalent to the result of `git clone --mirror`
- all_refs: '+refs/*:refs/*',
- heads: '+refs/heads/*:refs/heads/*',
- tags: '+refs/tags/*:refs/tags/*'
- }.freeze
-
- RemoteError = Class.new(StandardError)
-
- def set_remote_as_mirror(remote_name, refmap: :all_refs)
- set_remote_refmap(remote_name, refmap)
-
- rugged.config["remote.#{remote_name}.mirror"] = true
- rugged.config["remote.#{remote_name}.prune"] = true
- end
-
- def remote_tags(remote)
- # Each line has this format: "dc872e9fa6963f8f03da6c8f6f264d0845d6b092\trefs/tags/v1.10.0\n"
- # We want to convert it to: [{ 'v1.10.0' => 'dc872e9fa6963f8f03da6c8f6f264d0845d6b092' }, ...]
- list_remote_tags(remote).map do |line|
- target, path = line.strip.split("\t")
-
- # When the remote repo does not have tags.
- if target.nil? || path.nil?
- Rails.logger.info "Empty or invalid list of tags for remote: #{remote}. Output: #{output}"
- break []
+ def remote_branches(remote_name)
+ gitaly_migrate(:ref_find_all_remote_branches) do |is_enabled|
+ if is_enabled
+ gitaly_ref_client.remote_branches(remote_name)
+ else
+ rugged_remote_branches(remote_name)
end
-
- name = path.split('/', 3).last
- # We're only interested in tag references
- # See: http://stackoverflow.com/questions/15472107/when-listing-git-ls-remote-why-theres-after-the-tag-name
- next if name =~ /\^\{\}\Z/
-
- target_commit = Gitlab::Git::Commit.find(self, target)
- Gitlab::Git::Tag.new(self, {
- name: name,
- target: target,
- target_commit: target_commit
- })
- end.compact
+ end
end
- def remote_branches(remote_name)
+ private
+
+ def rugged_remote_branches(remote_name)
branches = []
rugged.references.each("refs/remotes/#{remote_name}/*").map do |ref|
@@ -59,37 +29,6 @@ module Gitlab
branches
end
-
- private
-
- def set_remote_refmap(remote_name, refmap)
- Array(refmap).each_with_index do |refspec, i|
- refspec = REFMAPS[refspec] || refspec
-
- # We need multiple `fetch` entries, but Rugged only allows replacing a config, not adding to it.
- # To make sure we start from scratch, we set the first using rugged, and use `git` for any others
- if i == 0
- rugged.config["remote.#{remote_name}.fetch"] = refspec
- else
- run_git(%W[config --add remote.#{remote_name}.fetch #{refspec}])
- end
- end
- end
-
- def list_remote_tags(remote)
- tag_list, exit_code, error = nil
- cmd = %W(#{Gitlab.config.git.bin_path} --git-dir=#{path} ls-remote --tags #{remote})
-
- Open3.popen3(*cmd) do |stdin, stdout, stderr, wait_thr|
- tag_list = stdout.read
- error = stderr.read
- exit_code = wait_thr.value.exitstatus
- end
-
- raise RemoteError, error unless exit_code.zero?
-
- tag_list.split("\n")
- end
end
end
end
diff --git a/lib/gitlab/git_ref_validator.rb b/lib/gitlab/git_ref_validator.rb
index 2e3e4fc3f1f..40636fb204e 100644
--- a/lib/gitlab/git_ref_validator.rb
+++ b/lib/gitlab/git_ref_validator.rb
@@ -7,11 +7,11 @@ module Gitlab
#
# Returns true for a valid reference name, false otherwise
def validate(ref_name)
- return false if ref_name.start_with?('refs/heads/')
- return false if ref_name.start_with?('refs/remotes/')
+ not_allowed_prefixes = %w(refs/heads/ refs/remotes/ -)
+ return false if ref_name.start_with?(*not_allowed_prefixes)
+ return false if ref_name == 'HEAD'
- Gitlab::Utils.system_silent(
- %W(#{Gitlab.config.git.bin_path} check-ref-format --branch #{ref_name}))
+ Rugged::Reference.valid_name? "refs/heads/#{ref_name}"
end
end
end
diff --git a/lib/gitlab/gitaly_client/operation_service.rb b/lib/gitlab/gitaly_client/operation_service.rb
index 555733d1834..54c78fdb680 100644
--- a/lib/gitlab/gitaly_client/operation_service.rb
+++ b/lib/gitlab/gitaly_client/operation_service.rb
@@ -144,13 +144,14 @@ module Gitlab
branch: encode_binary(target_branch)
)
- branch_update = GitalyClient.call(
+ response = GitalyClient.call(
@repository.storage,
:operation_service,
:user_ff_branch,
request
- ).branch_update
- Gitlab::Git::OperationService::BranchUpdate.from_gitaly(branch_update)
+ )
+
+ Gitlab::Git::OperationService::BranchUpdate.from_gitaly(response.branch_update)
rescue GRPC::FailedPrecondition => e
raise Gitlab::Git::CommitError, e
end
@@ -306,9 +307,9 @@ module Gitlab
raise Gitlab::Git::CommitError, response.commit_error
elsif response.create_tree_error.presence
raise Gitlab::Git::Repository::CreateTreeError, response.create_tree_error
- else
- Gitlab::Git::OperationService::BranchUpdate.from_gitaly(response.branch_update)
end
+
+ Gitlab::Git::OperationService::BranchUpdate.from_gitaly(response.branch_update)
end
def user_commit_files_request_header(
diff --git a/lib/gitlab/gitaly_client/ref_service.rb b/lib/gitlab/gitaly_client/ref_service.rb
index 1ad6376dac7..fbe7d4ba1ae 100644
--- a/lib/gitlab/gitaly_client/ref_service.rb
+++ b/lib/gitlab/gitaly_client/ref_service.rb
@@ -17,6 +17,13 @@ module Gitlab
consume_find_all_branches_response(response)
end
+ def remote_branches(remote_name)
+ request = Gitaly::FindAllRemoteBranchesRequest.new(repository: @gitaly_repo, remote_name: remote_name)
+ response = GitalyClient.call(@repository.storage, :ref_service, :find_all_remote_branches, request)
+
+ consume_find_all_remote_branches_response(remote_name, response)
+ end
+
def merged_branches(branch_names = [])
request = Gitaly::FindAllBranchesRequest.new(
repository: @gitaly_repo,
@@ -243,6 +250,18 @@ module Gitlab
end
end
+ def consume_find_all_remote_branches_response(remote_name, response)
+ remote_name += '/' unless remote_name.ends_with?('/')
+
+ response.flat_map do |message|
+ message.branches.map do |branch|
+ target_commit = Gitlab::Git::Commit.decorate(@repository, branch.target_commit)
+ branch_name = branch.name.sub(remote_name, '')
+ Gitlab::Git::Branch.new(@repository, branch_name, branch.target_commit.id, target_commit)
+ end
+ end
+ end
+
def consume_tags_response(response)
response.flat_map do |message|
message.tags.map { |gitaly_tag| Gitlab::Git::Tag.new(@repository, gitaly_tag) }
diff --git a/lib/gitlab/gitlab_import/client.rb b/lib/gitlab/gitlab_import/client.rb
index 22719e9a003..38ef12491df 100644
--- a/lib/gitlab/gitlab_import/client.rb
+++ b/lib/gitlab/gitlab_import/client.rb
@@ -32,15 +32,15 @@ module Gitlab
api.get("/api/v4/user").parsed
end
- def issues(project_identifier)
- lazy_page_iterator(PER_PAGE) do |page|
- api.get("/api/v4/projects/#{project_identifier}/issues?per_page=#{PER_PAGE}&page=#{page}").parsed
+ def issues(project_identifier, **kwargs)
+ lazy_page_iterator(**kwargs) do |page, per_page|
+ api.get("/api/v4/projects/#{project_identifier}/issues?per_page=#{per_page}&page=#{page}").parsed
end
end
- def issue_comments(project_identifier, issue_id)
- lazy_page_iterator(PER_PAGE) do |page|
- api.get("/api/v4/projects/#{project_identifier}/issues/#{issue_id}/notes?per_page=#{PER_PAGE}&page=#{page}").parsed
+ def issue_comments(project_identifier, issue_id, **kwargs)
+ lazy_page_iterator(**kwargs) do |page, per_page|
+ api.get("/api/v4/projects/#{project_identifier}/issues/#{issue_id}/notes?per_page=#{per_page}&page=#{page}").parsed
end
end
@@ -48,23 +48,27 @@ module Gitlab
api.get("/api/v4/projects/#{id}").parsed
end
- def projects
- lazy_page_iterator(PER_PAGE) do |page|
- api.get("/api/v4/projects?per_page=#{PER_PAGE}&page=#{page}").parsed
+ def projects(**kwargs)
+ lazy_page_iterator(**kwargs) do |page, per_page|
+ api.get("/api/v4/projects?per_page=#{per_page}&page=#{page}&simple=true&membership=true").parsed
end
end
private
- def lazy_page_iterator(per_page)
+ def lazy_page_iterator(starting_page: 1, page_limit: nil, per_page: PER_PAGE)
Enumerator.new do |y|
- page = 1
+ page = starting_page
+ page_limit = (starting_page - 1) + page_limit if page_limit
+
loop do
- items = yield(page)
+ items = yield(page, per_page)
+
items.each do |item|
y << item
end
- break if items.empty? || items.size < per_page
+
+ break if items.empty? || items.size < per_page || (page_limit && page >= page_limit)
page += 1
end
diff --git a/lib/gitlab/import_export/merge_request_parser.rb b/lib/gitlab/import_export/merge_request_parser.rb
index f3d7407383c..d0527f014a7 100644
--- a/lib/gitlab/import_export/merge_request_parser.rb
+++ b/lib/gitlab/import_export/merge_request_parser.rb
@@ -25,6 +25,7 @@ module Gitlab
@project.repository.create_branch(@merge_request.target_branch, @merge_request.target_branch_sha)
end
+ # Gitaly migration: https://gitlab.com/gitlab-org/gitaly/issues/1295
def fetch_ref
@project.repository.fetch_ref(@project.repository, source_ref: @diff_head_sha, target_ref: @merge_request.source_branch)
end
diff --git a/lib/gitlab/json_logger.rb b/lib/gitlab/json_logger.rb
new file mode 100644
index 00000000000..28e258196ca
--- /dev/null
+++ b/lib/gitlab/json_logger.rb
@@ -0,0 +1,22 @@
+module Gitlab
+ class JsonLogger < ::Gitlab::Logger
+ def self.file_name_noext
+ raise NotImplementedError
+ end
+
+ def format_message(severity, timestamp, progname, message)
+ data = {}
+ data[:severity] = severity
+ data[:time] = timestamp.utc.iso8601(3)
+
+ case message
+ when String
+ data[:message] = message
+ when Hash
+ data.merge!(message)
+ end
+
+ data.to_json + "\n"
+ end
+ end
+end
diff --git a/lib/gitlab/omniauth_initializer.rb b/lib/gitlab/omniauth_initializer.rb
index a71acda8701..f33ea0880df 100644
--- a/lib/gitlab/omniauth_initializer.rb
+++ b/lib/gitlab/omniauth_initializer.rb
@@ -1,23 +1,21 @@
module Gitlab
class OmniauthInitializer
- def self.enabled?
- Gitlab.config.omniauth.enabled ||
- Gitlab.config.omniauth.auto_sign_in_with_provider.present?
- end
-
def initialize(devise_config)
@devise_config = devise_config
end
def execute(providers)
providers.each do |provider|
- add_provider(provider['name'].to_sym, *arguments_for(provider))
+ name = provider['name'].to_sym
+
+ add_provider_to_devise(name, *arguments_for(provider))
+ setup_provider(name)
end
end
private
- def add_provider(*args)
+ def add_provider_to_devise(*args)
@devise_config.omniauth(*args)
end
@@ -76,5 +74,23 @@ module Gitlab
end
end
end
+
+ def omniauth_customized_providers
+ @omniauth_customized_providers ||= build_omniauth_customized_providers
+ end
+
+ # We override this in EE
+ def build_omniauth_customized_providers
+ %i[bitbucket jwt]
+ end
+
+ def setup_provider(provider)
+ case provider
+ when :kerberos
+ require 'omniauth-kerberos'
+ when *omniauth_customized_providers
+ require_dependency "omni_auth/strategies/#{provider}"
+ end
+ end
end
end
diff --git a/lib/gitlab/profiler.rb b/lib/gitlab/profiler.rb
index ecff6ab5d5e..c5bb4648572 100644
--- a/lib/gitlab/profiler.rb
+++ b/lib/gitlab/profiler.rb
@@ -146,5 +146,11 @@ module Gitlab
logger.info("#{model} total (#{query_count}): #{time.round(2)}ms")
end
end
+
+ def self.print_by_total_time(result, options = {})
+ default_options = { sort_method: :total_time }
+
+ Gitlab::Profiler::TotalTimeFlatPrinter.new(result).print(STDOUT, default_options.merge(options))
+ end
end
end
diff --git a/lib/gitlab/profiler/total_time_flat_printer.rb b/lib/gitlab/profiler/total_time_flat_printer.rb
new file mode 100644
index 00000000000..2fd0ec10ba8
--- /dev/null
+++ b/lib/gitlab/profiler/total_time_flat_printer.rb
@@ -0,0 +1,39 @@
+module Gitlab
+ module Profiler
+ class TotalTimeFlatPrinter < RubyProf::FlatPrinter
+ def max_percent
+ @options[:max_percent] || 100
+ end
+
+ # Copied from:
+ # <https://github.com/ruby-prof/ruby-prof/blob/master/lib/ruby-prof/printers/flat_printer.rb>
+ #
+ # The changes are just to filter by total time, not self time, and add a
+ # max_percent option as well.
+ def print_methods(thread)
+ total_time = thread.total_time
+ methods = thread.methods.sort_by(&sort_method).reverse
+
+ sum = 0
+ methods.each do |method|
+ total_percent = (method.total_time / total_time) * 100
+ next if total_percent < min_percent
+ next if total_percent > max_percent
+
+ sum += method.self_time
+
+ @output << "%6.2f %9.3f %9.3f %9.3f %9.3f %8d %s%s\n" % [
+ method.self_time / total_time * 100, # %self
+ method.total_time, # total
+ method.self_time, # self
+ method.wait_time, # wait
+ method.children_time, # children
+ method.called, # calls
+ method.recursive? ? "*" : " ", # cycle
+ method_name(method) # name
+ ]
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/project_search_results.rb b/lib/gitlab/project_search_results.rb
index 38bdc61d8ab..62f9e538c04 100644
--- a/lib/gitlab/project_search_results.rb
+++ b/lib/gitlab/project_search_results.rb
@@ -5,7 +5,7 @@ module Gitlab
def initialize(current_user, project, query, repository_ref = nil, per_page: 20)
@current_user = current_user
@project = project
- @repository_ref = repository_ref.presence || project.default_branch
+ @repository_ref = repository_ref.presence
@query = query
@per_page = per_page
end
@@ -95,7 +95,7 @@ module Gitlab
def blobs
return [] unless Ability.allowed?(@current_user, :download_code, @project)
- @blobs ||= Gitlab::FileFinder.new(project, repository_ref).find(query)
+ @blobs ||= Gitlab::FileFinder.new(project, repository_project_ref).find(query)
end
def wiki_blobs
@@ -103,11 +103,8 @@ module Gitlab
@wiki_blobs ||= begin
if project.wiki_enabled? && query.present?
- project_wiki = ProjectWiki.new(project)
-
- unless project_wiki.empty?
- ref = repository_ref || project.wiki.default_branch
- Gitlab::WikiFileFinder.new(project, ref).find(query)
+ unless project.wiki.empty?
+ Gitlab::WikiFileFinder.new(project, repository_wiki_ref).find(query)
else
[]
end
@@ -150,5 +147,13 @@ module Gitlab
def project_ids_relation
project
end
+
+ def repository_project_ref
+ @repository_project_ref ||= repository_ref || project.default_branch
+ end
+
+ def repository_wiki_ref
+ @repository_wiki_ref ||= repository_ref || project.wiki.default_branch
+ end
end
end
diff --git a/lib/gitlab/serializer/ci/variables.rb b/lib/gitlab/serializer/ci/variables.rb
index c059c454eac..292c8de6229 100644
--- a/lib/gitlab/serializer/ci/variables.rb
+++ b/lib/gitlab/serializer/ci/variables.rb
@@ -13,8 +13,9 @@ module Gitlab
object = YAML.safe_load(string, [Symbol])
object.map do |variable|
- variable[:key] = variable[:key].to_s
- variable
+ variable.symbolize_keys.tap do |variable|
+ variable[:key] = variable[:key].to_s
+ end
end
end
diff --git a/lib/gitlab/url_sanitizer.rb b/lib/gitlab/url_sanitizer.rb
index de8b6ec69ce..308a95d2f09 100644
--- a/lib/gitlab/url_sanitizer.rb
+++ b/lib/gitlab/url_sanitizer.rb
@@ -71,12 +71,10 @@ module Gitlab
def generate_full_url
return @url unless valid_credentials?
- @full_url = @url.dup
-
- @full_url.password = credentials[:password] if credentials[:password].present?
- @full_url.user = credentials[:user] if credentials[:user].present?
-
- @full_url
+ @url.dup.tap do |generated|
+ generated.password = encode_percent(credentials[:password]) if credentials[:password].present?
+ generated.user = encode_percent(credentials[:user]) if credentials[:user].present?
+ end
end
def safe_url
@@ -89,5 +87,10 @@ module Gitlab
def valid_credentials?
credentials && credentials.is_a?(Hash) && credentials.any?
end
+
+ def encode_percent(string)
+ # CGI.escape converts spaces to +, but this doesn't work for git clone
+ CGI.escape(string).gsub('+', '%20')
+ end
end
end
diff --git a/lib/gitlab/usage_data.rb b/lib/gitlab/usage_data.rb
index dff0c97eeb4..22c9638ecc0 100644
--- a/lib/gitlab/usage_data.rb
+++ b/lib/gitlab/usage_data.rb
@@ -95,7 +95,7 @@ module Gitlab
gravatar_enabled: Gitlab::CurrentSettings.gravatar_enabled?,
ldap_enabled: Gitlab.config.ldap.enabled,
mattermost_enabled: Gitlab.config.mattermost.enabled,
- omniauth_enabled: Gitlab.config.omniauth.enabled,
+ omniauth_enabled: Gitlab::Auth.omniauth_enabled?,
reply_by_email_enabled: Gitlab::IncomingEmail.enabled?,
signup_enabled: Gitlab::CurrentSettings.allow_signup?
}
diff --git a/lib/gitlab/user_activities.rb b/lib/gitlab/user_activities.rb
deleted file mode 100644
index 125488536e1..00000000000
--- a/lib/gitlab/user_activities.rb
+++ /dev/null
@@ -1,34 +0,0 @@
-module Gitlab
- class UserActivities
- include Enumerable
-
- KEY = 'users:activities'.freeze
- BATCH_SIZE = 500
-
- def self.record(key, time = Time.now)
- Gitlab::Redis::SharedState.with do |redis|
- redis.hset(KEY, key, time.to_i)
- end
- end
-
- def delete(*keys)
- Gitlab::Redis::SharedState.with do |redis|
- redis.hdel(KEY, keys)
- end
- end
-
- def each
- cursor = 0
- loop do
- cursor, pairs =
- Gitlab::Redis::SharedState.with do |redis|
- redis.hscan(KEY, cursor, count: BATCH_SIZE)
- end
-
- Hash[pairs].each { |pair| yield pair }
-
- break if cursor == '0'
- end
- end
- end
-end
diff --git a/lib/tasks/gitlab/cleanup.rake b/lib/tasks/gitlab/cleanup.rake
index 52ae1330d7f..5e07b12ee1c 100644
--- a/lib/tasks/gitlab/cleanup.rake
+++ b/lib/tasks/gitlab/cleanup.rake
@@ -104,28 +104,5 @@ namespace :gitlab do
puts "To block these users run this command with BLOCK=true".color(:yellow)
end
end
-
- # This is a rake task which removes faulty refs. These refs where only
- # created in the 8.13.RC cycle, and fixed in the stable builds which were
- # released. So likely this should only be run once on gitlab.com
- # Faulty refs are moved so they are kept around, else some features break.
- desc 'GitLab | Cleanup | Remove faulty deployment refs'
- task move_faulty_deployment_refs: :gitlab_environment do
- projects = Project.where(id: Deployment.select(:project_id).distinct)
-
- projects.find_each do |project|
- rugged = project.repository.rugged
-
- max_iid = project.deployments.maximum(:iid)
-
- rugged.references.each('refs/environments/**/*') do |ref|
- id = ref.name.split('/').last.to_i
- next unless id > max_iid
-
- project.deployments.find(id).create_ref
- project.repository.delete_refs(ref)
- end
- end
- end
end
end
diff --git a/lib/tasks/gitlab/info.rake b/lib/tasks/gitlab/info.rake
index 6de739e9515..e97d77d20e0 100644
--- a/lib/tasks/gitlab/info.rake
+++ b/lib/tasks/gitlab/info.rake
@@ -54,8 +54,8 @@ namespace :gitlab do
puts "HTTP Clone URL:\t#{http_clone_url}"
puts "SSH Clone URL:\t#{ssh_clone_url}"
puts "Using LDAP:\t#{Gitlab.config.ldap.enabled ? "yes".color(:green) : "no"}"
- puts "Using Omniauth:\t#{Gitlab.config.omniauth.enabled ? "yes".color(:green) : "no"}"
- puts "Omniauth Providers: #{omniauth_providers.join(', ')}" if Gitlab.config.omniauth.enabled
+ puts "Using Omniauth:\t#{Gitlab::Auth.omniauth_enabled? ? "yes".color(:green) : "no"}"
+ puts "Omniauth Providers: #{omniauth_providers.join(', ')}" if Gitlab::Auth.omniauth_enabled?
# check Gitolite version
gitlab_shell_version_file = "#{Gitlab.config.gitlab_shell.hooks_path}/../VERSION"
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 19973f4f321..09a35b5da07 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -465,7 +465,7 @@ msgstr ""
msgid "An error occurred while importing project: ${details}"
msgstr ""
-msgid "An error occurred while loading commits"
+msgid "An error occurred while loading commit signatures"
msgstr ""
msgid "An error occurred while loading diff"
@@ -4114,6 +4114,9 @@ msgstr ""
msgid "PrometheusService|Common metrics"
msgstr ""
+msgid "PrometheusService|Common metrics are automatically monitored based on a library of metrics from popular exporters."
+msgstr ""
+
msgid "PrometheusService|Finding and configuring metrics..."
msgstr ""
@@ -4129,9 +4132,6 @@ msgstr ""
msgid "PrometheusService|Metrics"
msgstr ""
-msgid "PrometheusService|Metrics are automatically configured and monitored based on a library of metrics from popular exporters."
-msgstr ""
-
msgid "PrometheusService|Missing environment variable"
msgstr ""
diff --git a/package.json b/package.json
index e1801d4d435..256ebc1fb6e 100644
--- a/package.json
+++ b/package.json
@@ -53,6 +53,7 @@
"emoji-unicode-version": "^0.2.1",
"exports-loader": "^0.7.0",
"file-loader": "^1.1.11",
+ "formdata-polyfill": "^3.0.11",
"fuzzaldrin-plus": "^0.5.0",
"glob": "^7.1.2",
"imports-loader": "^0.8.0",
diff --git a/scripts/lint-rugged b/scripts/lint-rugged
index cabd083e9f9..d0c2c544c47 100755
--- a/scripts/lint-rugged
+++ b/scripts/lint-rugged
@@ -14,7 +14,10 @@ ALLOWED = [
'lib/tasks/gitlab/cleanup.rake',
# The only place where Rugged code is still allowed in production
- 'lib/gitlab/git/'
+ 'lib/gitlab/git/',
+
+ # Needed to avoid using the git binary to validate a branch name
+ 'lib/gitlab/git_ref_validator.rb'
].freeze
rugged_lines = IO.popen(%w[git grep -i -n rugged -- app config lib], &:read).lines
diff --git a/spec/controllers/sessions_controller_spec.rb b/spec/controllers/sessions_controller_spec.rb
index 7c00652317b..8e25b61e2f1 100644
--- a/spec/controllers/sessions_controller_spec.rb
+++ b/spec/controllers/sessions_controller_spec.rb
@@ -50,8 +50,6 @@ describe SessionsController do
end
context 'when using valid password', :clean_gitlab_redis_shared_state do
- include UserActivitiesHelpers
-
let(:user) { create(:user) }
let(:user_params) { { login: user.username, password: user.password } }
@@ -77,7 +75,7 @@ describe SessionsController do
it 'updates the user activity' do
expect do
post(:create, user: user_params)
- end.to change { user_activity(user) }
+ end.to change { user.reload.last_activity_on }.to(Date.today)
end
end
diff --git a/spec/features/merge_request/user_posts_diff_notes_spec.rb b/spec/features/merge_request/user_posts_diff_notes_spec.rb
index 02d19db3828..77261f9375c 100644
--- a/spec/features/merge_request/user_posts_diff_notes_spec.rb
+++ b/spec/features/merge_request/user_posts_diff_notes_spec.rb
@@ -185,11 +185,11 @@ describe 'Merge request > User posts diff notes', :js do
end
describe 'posting a note' do
- xit 'adds as discussion' do
+ it 'adds as discussion' do
expect(page).to have_css('.js-temp-notes-holder', count: 2)
should_allow_commenting(find('[id="6eb14e00385d2fb284765eb1cd8d420d33d63fc9_22_22"]'), asset_form_reset: false)
- expect(page).to have_css('.notes_holder .note', count: 1)
+ expect(page).to have_css('.notes_holder .note.note-discussion', count: 1)
expect(page).to have_css('.js-temp-notes-holder', count: 1)
expect(page).to have_button('Reply...')
end
diff --git a/spec/features/merge_request/user_resolves_diff_notes_and_discussions_resolve_spec.rb b/spec/features/merge_request/user_resolves_diff_notes_and_discussions_resolve_spec.rb
index bf4d5396df9..2d268ecab58 100644
--- a/spec/features/merge_request/user_resolves_diff_notes_and_discussions_resolve_spec.rb
+++ b/spec/features/merge_request/user_resolves_diff_notes_and_discussions_resolve_spec.rb
@@ -342,8 +342,9 @@ describe 'Merge request > User resolves diff notes and discussions', :js do
end
end
- it 'shows jump to next discussion button' do
- expect(page.all('.discussion-reply-holder', count: 2)).to all(have_selector('.discussion-next-btn'))
+ it 'shows jump to next discussion button, apart from the last one' do
+ expect(page).to have_selector('.discussion-reply-holder', count: 2)
+ expect(page).to have_selector('.discussion-reply-holder .discussion-next-btn', count: 1)
end
it 'displays next discussion even if hidden' do
diff --git a/spec/features/projects/commits/user_browses_commits_spec.rb b/spec/features/projects/commits/user_browses_commits_spec.rb
index 23d8d606790..534cfe1eb12 100644
--- a/spec/features/projects/commits/user_browses_commits_spec.rb
+++ b/spec/features/projects/commits/user_browses_commits_spec.rb
@@ -238,6 +238,5 @@ def check_author_link(email, author)
author_link = find('.commit-author-link')
expect(author_link['href']).to eq(user_path(author))
- expect(author_link['title']).to eq(email)
expect(find('.commit-author-name').text).to eq(author.name)
end
diff --git a/spec/features/signed_commits_spec.rb b/spec/features/signed_commits_spec.rb
index 3d05474dca2..5003eb508c2 100644
--- a/spec/features/signed_commits_spec.rb
+++ b/spec/features/signed_commits_spec.rb
@@ -7,7 +7,7 @@ describe 'GPG signed commits', :js do
user = create :user, email: 'unrelated.user@example.org'
project.add_maintainer(user)
- Sidekiq::Testing.inline! do
+ perform_enqueued_jobs do
create :gpg_key, key: GpgHelpers::User1.public_key, user: user
end
@@ -21,7 +21,7 @@ describe 'GPG signed commits', :js do
end
# user changes his email which makes the gpg key verified
- Sidekiq::Testing.inline! do
+ perform_enqueued_jobs do
user.skip_reconfirmation!
user.update!(email: GpgHelpers::User1.emails.first)
end
@@ -48,7 +48,7 @@ describe 'GPG signed commits', :js do
end
# user adds the gpg key which makes the signature valid
- Sidekiq::Testing.inline! do
+ perform_enqueued_jobs do
create :gpg_key, key: GpgHelpers::User1.public_key, user: user
end
@@ -66,7 +66,7 @@ describe 'GPG signed commits', :js do
end
let(:user_1_key) do
- Sidekiq::Testing.inline! do
+ perform_enqueued_jobs do
create :gpg_key, key: GpgHelpers::User1.public_key, user: user_1
end
end
@@ -79,7 +79,7 @@ describe 'GPG signed commits', :js do
end
let(:user_2_key) do
- Sidekiq::Testing.inline! do
+ perform_enqueued_jobs do
create :gpg_key, key: GpgHelpers::User2.public_key, user: user_2
end
end
diff --git a/spec/features/user_sees_revert_modal_spec.rb b/spec/features/user_sees_revert_modal_spec.rb
index 11a9e470f76..3b48ea4786d 100644
--- a/spec/features/user_sees_revert_modal_spec.rb
+++ b/spec/features/user_sees_revert_modal_spec.rb
@@ -9,6 +9,9 @@ describe 'Merge request > User sees revert modal', :js do
sign_in(user)
visit(project_merge_request_path(project, merge_request))
click_button('Merge')
+
+ wait_for_requests
+
visit(merge_request_path(merge_request))
click_link('Revert')
end
diff --git a/spec/fixtures/api/schemas/pipeline.json b/spec/fixtures/api/schemas/pipeline.json
index 55511d17b5e..b6e30c40f13 100644
--- a/spec/fixtures/api/schemas/pipeline.json
+++ b/spec/fixtures/api/schemas/pipeline.json
@@ -319,6 +319,10 @@
"id": "/properties/updated_at",
"type": "string"
},
+ "web_url": {
+ "id": "/properties/web_url",
+ "type": "string"
+ },
"user": {
"id": "/properties/user",
"properties": {
diff --git a/spec/fixtures/api/schemas/public_api/v4/pipeline/basic.json b/spec/fixtures/api/schemas/public_api/v4/pipeline/basic.json
index 0d127dc5297..56f86856dd4 100644
--- a/spec/fixtures/api/schemas/public_api/v4/pipeline/basic.json
+++ b/spec/fixtures/api/schemas/public_api/v4/pipeline/basic.json
@@ -4,13 +4,15 @@
"id",
"sha",
"ref",
- "status"
+ "status",
+ "web_url"
],
"properties" : {
"id": { "type": "integer" },
"sha": { "type": "string" },
"ref": { "type": "string" },
- "status": { "type": "string" }
+ "status": { "type": "string" },
+ "web_url": { "type": "string" }
},
"additionalProperties": false
}
diff --git a/spec/fixtures/api/schemas/public_api/v4/projects.json b/spec/fixtures/api/schemas/public_api/v4/projects.json
index 17ad8d8c48d..af5670ebd33 100644
--- a/spec/fixtures/api/schemas/public_api/v4/projects.json
+++ b/spec/fixtures/api/schemas/public_api/v4/projects.json
@@ -24,13 +24,24 @@
"avatar_url": { "type": ["string", "null"] },
"star_count": { "type": "integer" },
"forks_count": { "type": "integer" },
- "last_activity_at": { "type": "date" }
+ "last_activity_at": { "type": "date" },
+ "namespace": {
+ "type": "object",
+ "properties" : {
+ "id": { "type": "integer" },
+ "name": { "type": "string" },
+ "path": { "type": "string" },
+ "kind": { "type": "string" },
+ "full_path": { "type": "string" },
+ "parent_id": { "type": ["integer", "null"] }
+ }
+ }
},
"required": [
"id", "name", "name_with_namespace", "description", "path",
"path_with_namespace", "created_at", "default_branch", "tag_list",
"ssh_url_to_repo", "http_url_to_repo", "web_url", "avatar_url",
- "star_count", "last_activity_at"
+ "star_count", "last_activity_at", "namespace"
],
"additionalProperties": false
}
diff --git a/spec/helpers/button_helper_spec.rb b/spec/helpers/button_helper_spec.rb
index fee8df10129..630f3eff258 100644
--- a/spec/helpers/button_helper_spec.rb
+++ b/spec/helpers/button_helper_spec.rb
@@ -121,6 +121,8 @@ describe ButtonHelper do
end
describe 'clipboard_button' do
+ include IconsHelper
+
let(:user) { create(:user) }
let(:project) { build_stubbed(:project) }
@@ -145,7 +147,7 @@ describe ButtonHelper do
expect(element.attr('data-clipboard-text')).to eq(nil)
expect(element.inner_text).to eq("")
- expect(element).to have_selector('.fa.fa-clipboard')
+ expect(element.to_html).to include sprite_icon('duplicate')
end
end
@@ -178,7 +180,7 @@ describe ButtonHelper do
context 'with `hide_button_icon` attribute provided' do
it 'shows copy to clipboard button without tooltip support' do
- expect(element(hide_button_icon: true)).not_to have_selector('.fa.fa-clipboard')
+ expect(element(hide_button_icon: true).to_html).not_to include sprite_icon('duplicate')
end
end
end
diff --git a/spec/helpers/visibility_level_helper_spec.rb b/spec/helpers/visibility_level_helper_spec.rb
index 5077c89d7b4..a3be222b7bd 100644
--- a/spec/helpers/visibility_level_helper_spec.rb
+++ b/spec/helpers/visibility_level_helper_spec.rb
@@ -6,6 +6,29 @@ describe VisibilityLevelHelper do
let(:personal_snippet) { build(:personal_snippet) }
let(:project_snippet) { build(:project_snippet) }
+ describe 'visibility_icon_description' do
+ context 'used with a Project' do
+ it 'delegates projects to #project_visibility_icon_description' do
+ expect(visibility_icon_description(project))
+ .to match /project/i
+ end
+
+ context 'used with a ProjectPresenter' do
+ it 'delegates projects to #project_visibility_icon_description' do
+ expect(visibility_icon_description(project.present))
+ .to match /project/i
+ end
+ end
+
+ context 'used with a Group' do
+ it 'delegates groups to #group_visibility_icon_description' do
+ expect(visibility_icon_description(group))
+ .to match /group/i
+ end
+ end
+ end
+ end
+
describe 'visibility_level_description' do
context 'used with a Project' do
it 'delegates projects to #project_visibility_level_description' do
diff --git a/spec/javascripts/diffs/components/diff_line_gutter_content_spec.js b/spec/javascripts/diffs/components/diff_line_gutter_content_spec.js
index cb85d12daf2..bdc94131fc2 100644
--- a/spec/javascripts/diffs/components/diff_line_gutter_content_spec.js
+++ b/spec/javascripts/diffs/components/diff_line_gutter_content_spec.js
@@ -50,7 +50,11 @@ describe('DiffLineGutterContent', () => {
it('should return discussions for the given lineCode', () => {
const { lineCode } = getDiffFileMock().highlightedDiffLines[1];
- const component = createComponent({ lineCode, showCommentButton: true });
+ const component = createComponent({
+ lineCode,
+ showCommentButton: true,
+ discussions: getDiscussionsMockData(),
+ });
setDiscussions(component);
diff --git a/spec/javascripts/gpg_badges_spec.js b/spec/javascripts/gpg_badges_spec.js
index 97c771dcfd3..78330dd9633 100644
--- a/spec/javascripts/gpg_badges_spec.js
+++ b/spec/javascripts/gpg_badges_spec.js
@@ -1,23 +1,27 @@
import MockAdapter from 'axios-mock-adapter';
import axios from '~/lib/utils/axios_utils';
import GpgBadges from '~/gpg_badges';
+import { TEST_HOST } from 'spec/test_constants';
describe('GpgBadges', () => {
let mock;
const dummyCommitSha = 'n0m0rec0ffee';
const dummyBadgeHtml = 'dummy html';
const dummyResponse = {
- signatures: [{
- commit_sha: dummyCommitSha,
- html: dummyBadgeHtml,
- }],
+ signatures: [
+ {
+ commit_sha: dummyCommitSha,
+ html: dummyBadgeHtml,
+ },
+ ],
};
+ const dummyUrl = `${TEST_HOST}/dummy/signatures`;
beforeEach(() => {
mock = new MockAdapter(axios);
setFixtures(`
<form
- class="commits-search-form js-signature-container" data-signatures-path="/hello" action="/hello"
+ class="commits-search-form js-signature-container" data-signatures-path="${dummyUrl}" action="${dummyUrl}"
method="get">
<input name="utf8" type="hidden" value="✓">
<input type="search" name="search" id="commits-search"class="form-control search-text-input input-short">
@@ -32,25 +36,55 @@ describe('GpgBadges', () => {
mock.restore();
});
- it('displays a loading spinner', (done) => {
- mock.onGet('/hello').reply(200);
+ it('does not make a request if there is no container element', done => {
+ setFixtures('');
+ spyOn(axios, 'get');
- GpgBadges.fetch().then(() => {
- expect(document.querySelector('.js-loading-gpg-badge:empty')).toBe(null);
- const spinners = document.querySelectorAll('.js-loading-gpg-badge i.fa.fa-spinner.fa-spin');
- expect(spinners.length).toBe(1);
- done();
- }).catch(done.fail);
+ GpgBadges.fetch()
+ .then(() => {
+ expect(axios.get).not.toHaveBeenCalled();
+ })
+ .then(done)
+ .catch(done.fail);
});
- it('replaces the loading spinner', (done) => {
- mock.onGet('/hello').reply(200, dummyResponse);
+ it('throws an error if the endpoint is missing', done => {
+ setFixtures('<div class="js-signature-container"></div>');
+ spyOn(axios, 'get');
- GpgBadges.fetch().then(() => {
- expect(document.querySelector('.js-loading-gpg-badge')).toBe(null);
- const parentContainer = document.querySelector('.parent-container');
- expect(parentContainer.innerHTML.trim()).toEqual(dummyBadgeHtml);
- done();
- }).catch(done.fail);
+ GpgBadges.fetch()
+ .then(() => done.fail('Expected error to be thrown'))
+ .catch(error => {
+ expect(error.message).toBe('Missing commit signatures endpoint!');
+ expect(axios.get).not.toHaveBeenCalled();
+ })
+ .then(done)
+ .catch(done.fail);
+ });
+
+ it('displays a loading spinner', done => {
+ mock.onGet(dummyUrl).replyOnce(200);
+
+ GpgBadges.fetch()
+ .then(() => {
+ expect(document.querySelector('.js-loading-gpg-badge:empty')).toBe(null);
+ const spinners = document.querySelectorAll('.js-loading-gpg-badge i.fa.fa-spinner.fa-spin');
+ expect(spinners.length).toBe(1);
+ done();
+ })
+ .catch(done.fail);
+ });
+
+ it('replaces the loading spinner', done => {
+ mock.onGet(dummyUrl).replyOnce(200, dummyResponse);
+
+ GpgBadges.fetch()
+ .then(() => {
+ expect(document.querySelector('.js-loading-gpg-badge')).toBe(null);
+ const parentContainer = document.querySelector('.parent-container');
+ expect(parentContainer.innerHTML.trim()).toEqual(dummyBadgeHtml);
+ done();
+ })
+ .catch(done.fail);
});
});
diff --git a/spec/javascripts/helpers/vuex_action_helper.js b/spec/javascripts/helpers/vuex_action_helper.js
index 4ca7015184e..dd9174194a1 100644
--- a/spec/javascripts/helpers/vuex_action_helper.js
+++ b/spec/javascripts/helpers/vuex_action_helper.js
@@ -84,14 +84,12 @@ export default (
done();
};
- return new Promise((resolve, reject) => {
- try {
- const result = action({ commit, state, dispatch, rootState: state }, payload);
- resolve(result);
- } catch (e) {
- reject(e);
- }
+ const result = action({ commit, state, dispatch, rootState: state }, payload);
+
+ return new Promise(resolve => {
+ setImmediate(resolve);
})
+ .then(() => result)
.catch(error => {
validateResults();
throw error;
diff --git a/spec/javascripts/helpers/vuex_action_helper_spec.js b/spec/javascripts/helpers/vuex_action_helper_spec.js
index 8d6ad6750c0..09f0bd395c3 100644
--- a/spec/javascripts/helpers/vuex_action_helper_spec.js
+++ b/spec/javascripts/helpers/vuex_action_helper_spec.js
@@ -138,4 +138,29 @@ describe('VueX test helper (testAction)', () => {
});
});
});
+
+ it('should work with async actions not returning promises', done => {
+ const data = { FOO: 'BAR' };
+
+ const promiseAction = ({ commit, dispatch }) => {
+ dispatch('ACTION');
+
+ axios
+ .get(TEST_HOST)
+ .then(() => {
+ commit('SUCCESS');
+ return data;
+ })
+ .catch(error => {
+ commit('ERROR');
+ throw error;
+ });
+ };
+
+ mock.onGet(TEST_HOST).replyOnce(200, 42);
+
+ assertion = { mutations: [{ type: 'SUCCESS' }], actions: [{ type: 'ACTION' }] };
+
+ testAction(promiseAction, null, {}, assertion.mutations, assertion.actions, done);
+ });
});
diff --git a/spec/javascripts/ide/components/new_dropdown/modal_spec.js b/spec/javascripts/ide/components/new_dropdown/modal_spec.js
index 6dcc5880677..70651535e87 100644
--- a/spec/javascripts/ide/components/new_dropdown/modal_spec.js
+++ b/spec/javascripts/ide/components/new_dropdown/modal_spec.js
@@ -38,7 +38,7 @@ describe('new file modal component', () => {
});
it(`sets form label as ${type}`, () => {
- expect(vm.$el.querySelector('.label-light').textContent.trim()).toBe('Name');
+ expect(vm.$el.querySelector('.label-bold').textContent.trim()).toBe('Name');
});
describe('createEntryInStore', () => {
diff --git a/spec/javascripts/ide/ide_router_spec.js b/spec/javascripts/ide/ide_router_spec.js
new file mode 100644
index 00000000000..52ea0882bf4
--- /dev/null
+++ b/spec/javascripts/ide/ide_router_spec.js
@@ -0,0 +1,44 @@
+import router from '~/ide/ide_router';
+import store from '~/ide/stores';
+
+describe('IDE router', () => {
+ const PROJECT_NAMESPACE = 'my-group/sub-group';
+ const PROJECT_NAME = 'my-project';
+
+ afterEach(() => {
+ router.push('/');
+ });
+
+ afterAll(() => {
+ // VueRouter leaves this window.history at the "base" url. We need to clean this up.
+ window.history.replaceState({}, '', '/');
+ });
+
+ [
+ `/project/${PROJECT_NAMESPACE}/${PROJECT_NAME}/tree/master/-/src/blob/`,
+ `/project/${PROJECT_NAMESPACE}/${PROJECT_NAME}/tree/master/-/src/blob`,
+ `/project/${PROJECT_NAMESPACE}/${PROJECT_NAME}/tree/blob/-/src/blob`,
+ `/project/${PROJECT_NAMESPACE}/${PROJECT_NAME}/tree/master/-/src/tree/`,
+ `/project/${PROJECT_NAMESPACE}/${PROJECT_NAME}/tree/weird:branch/name-123/-/src/tree/`,
+ `/project/${PROJECT_NAMESPACE}/${PROJECT_NAME}/blob/master/-/src/blob`,
+ `/project/${PROJECT_NAMESPACE}/${PROJECT_NAME}/blob/master/-/src/edit`,
+ `/project/${PROJECT_NAMESPACE}/${PROJECT_NAME}/blob/master/-/src/merge_requests/2`,
+ `/project/${PROJECT_NAMESPACE}/${PROJECT_NAME}/blob/blob/-/src/blob`,
+ `/project/${PROJECT_NAMESPACE}/${PROJECT_NAME}/edit/blob/-/src/blob`,
+ `/project/${PROJECT_NAMESPACE}/${PROJECT_NAME}/merge_requests/2`,
+ `/project/${PROJECT_NAMESPACE}/${PROJECT_NAME}/tree/blob`,
+ `/project/${PROJECT_NAMESPACE}/${PROJECT_NAME}/edit`,
+ `/project/${PROJECT_NAMESPACE}/${PROJECT_NAME}`,
+ ].forEach(route => {
+ it(`finds project path when route is "${route}"`, () => {
+ spyOn(store, 'dispatch').and.returnValue(new Promise(() => {}));
+
+ router.push(route);
+
+ expect(store.dispatch).toHaveBeenCalledWith('getProjectData', {
+ namespace: PROJECT_NAMESPACE,
+ projectId: PROJECT_NAME,
+ });
+ });
+ });
+});
diff --git a/spec/javascripts/notes/components/discussion_counter_spec.js b/spec/javascripts/notes/components/discussion_counter_spec.js
index a3869cc6498..d09bc5037ef 100644
--- a/spec/javascripts/notes/components/discussion_counter_spec.js
+++ b/spec/javascripts/notes/components/discussion_counter_spec.js
@@ -46,7 +46,7 @@ describe('DiscussionCounter component', () => {
discussions,
});
setFixtures(`
- <div data-discussion-id="${firstDiscussionId}"></div>
+ <div class="discussion" data-discussion-id="${firstDiscussionId}"></div>
`);
vm.jumpToFirstUnresolvedDiscussion();
diff --git a/spec/javascripts/notes/components/noteable_discussion_spec.js b/spec/javascripts/notes/components/noteable_discussion_spec.js
index f3f50aed232..2a01bd85520 100644
--- a/spec/javascripts/notes/components/noteable_discussion_spec.js
+++ b/spec/javascripts/notes/components/noteable_discussion_spec.js
@@ -14,6 +14,7 @@ describe('noteable_discussion component', () => {
preloadFixtures(discussionWithTwoUnresolvedNotes);
beforeEach(() => {
+ window.mrTabs = {};
store = createStore();
store.dispatch('setNoteableData', noteableDataMock);
store.dispatch('setNotesData', notesDataMock);
@@ -106,33 +107,29 @@ describe('noteable_discussion component', () => {
describe('methods', () => {
describe('jumpToNextDiscussion', () => {
- it('expands next unresolved discussion', () => {
- spyOn(vm, 'expandDiscussion').and.stub();
- const discussions = [
- discussionMock,
- {
- ...discussionMock,
- id: discussionMock.id + 1,
- notes: [{ ...discussionMock.notes[0], resolvable: true, resolved: true }],
- },
- {
- ...discussionMock,
- id: discussionMock.id + 2,
- notes: [{ ...discussionMock.notes[0], resolvable: true, resolved: false }],
- },
- ];
- const nextDiscussionId = discussionMock.id + 2;
- store.replaceState({
- ...store.state,
- discussions,
- });
- setFixtures(`
- <div data-discussion-id="${nextDiscussionId}"></div>
- `);
+ it('expands next unresolved discussion', done => {
+ const discussion2 = getJSONFixture(discussionWithTwoUnresolvedNotes)[0];
+ discussion2.resolved = false;
+ discussion2.id = 'next'; // prepare this for being identified as next one (to be jumped to)
+ vm.$store.dispatch('setInitialNotes', [discussionMock, discussion2]);
+ window.mrTabs.currentAction = 'show';
+
+ Vue.nextTick()
+ .then(() => {
+ spyOn(vm, 'expandDiscussion').and.stub();
+
+ const nextDiscussionId = discussion2.id;
- vm.jumpToNextDiscussion();
+ setFixtures(`
+ <div class="discussion" data-discussion-id="${nextDiscussionId}"></div>
+ `);
- expect(vm.expandDiscussion).toHaveBeenCalledWith({ discussionId: nextDiscussionId });
+ vm.jumpToNextDiscussion();
+
+ expect(vm.expandDiscussion).toHaveBeenCalledWith({ discussionId: nextDiscussionId });
+ })
+ .then(done)
+ .catch(done.fail);
});
});
});
diff --git a/spec/javascripts/notes/mock_data.js b/spec/javascripts/notes/mock_data.js
index be2a8ba67fe..67f6a9629d9 100644
--- a/spec/javascripts/notes/mock_data.js
+++ b/spec/javascripts/notes/mock_data.js
@@ -1168,3 +1168,87 @@ export const collapsedSystemNotes = [
diff_discussion: false,
},
];
+
+export const discussion1 = {
+ id: 'abc1',
+ resolvable: true,
+ resolved: false,
+ diff_file: {
+ file_path: 'about.md',
+ },
+ position: {
+ formatter: {
+ new_line: 50,
+ old_line: null,
+ },
+ },
+ notes: [
+ {
+ created_at: '2018-07-04T16:25:41.749Z',
+ },
+ ],
+};
+
+export const resolvedDiscussion1 = {
+ id: 'abc1',
+ resolvable: true,
+ resolved: true,
+ diff_file: {
+ file_path: 'about.md',
+ },
+ position: {
+ formatter: {
+ new_line: 50,
+ old_line: null,
+ },
+ },
+ notes: [
+ {
+ created_at: '2018-07-04T16:25:41.749Z',
+ },
+ ],
+};
+
+export const discussion2 = {
+ id: 'abc2',
+ resolvable: true,
+ resolved: false,
+ diff_file: {
+ file_path: 'README.md',
+ },
+ position: {
+ formatter: {
+ new_line: null,
+ old_line: 20,
+ },
+ },
+ notes: [
+ {
+ created_at: '2018-07-04T12:05:41.749Z',
+ },
+ ],
+};
+
+export const discussion3 = {
+ id: 'abc3',
+ resolvable: true,
+ resolved: false,
+ diff_file: {
+ file_path: 'README.md',
+ },
+ position: {
+ formatter: {
+ new_line: 21,
+ old_line: null,
+ },
+ },
+ notes: [
+ {
+ created_at: '2018-07-05T17:25:41.749Z',
+ },
+ ],
+};
+
+export const unresolvableDiscussion = {
+ resolvable: false,
+};
diff --git a/spec/javascripts/notes/stores/getters_spec.js b/spec/javascripts/notes/stores/getters_spec.js
index 41599e00122..7f8ede51508 100644
--- a/spec/javascripts/notes/stores/getters_spec.js
+++ b/spec/javascripts/notes/stores/getters_spec.js
@@ -5,6 +5,11 @@ import {
noteableDataMock,
individualNote,
collapseNotesMock,
+ discussion1,
+ discussion2,
+ discussion3,
+ resolvedDiscussion1,
+ unresolvableDiscussion,
} from '../mock_data';
const discussionWithTwoUnresolvedNotes = 'merge_requests/resolved_diff_discussion.json';
@@ -109,4 +114,154 @@ describe('Getters Notes Store', () => {
expect(getters.isNotesFetched(state)).toBeFalsy();
});
});
+
+ describe('allResolvableDiscussions', () => {
+ it('should return only resolvable discussions in same order', () => {
+ const localGetters = {
+ allDiscussions: [
+ discussion3,
+ unresolvableDiscussion,
+ discussion1,
+ unresolvableDiscussion,
+ discussion2,
+ ],
+ };
+
+ expect(getters.allResolvableDiscussions(state, localGetters)).toEqual([
+ discussion3,
+ discussion1,
+ discussion2,
+ ]);
+ });
+
+ it('should return empty array if there are no resolvable discussions', () => {
+ const localGetters = {
+ allDiscussions: [unresolvableDiscussion, unresolvableDiscussion],
+ };
+
+ expect(getters.allResolvableDiscussions(state, localGetters)).toEqual([]);
+ });
+ });
+
+ describe('unresolvedDiscussionsIdsByDiff', () => {
+ it('should return all discussions IDs in diff order', () => {
+ const localGetters = {
+ allResolvableDiscussions: [discussion3, discussion1, discussion2],
+ };
+
+ expect(getters.unresolvedDiscussionsIdsByDiff(state, localGetters)).toEqual([
+ 'abc1',
+ 'abc2',
+ 'abc3',
+ ]);
+ });
+
+ it('should return empty array if all discussions have been resolved', () => {
+ const localGetters = {
+ allResolvableDiscussions: [resolvedDiscussion1],
+ };
+
+ expect(getters.unresolvedDiscussionsIdsByDiff(state, localGetters)).toEqual([]);
+ });
+ });
+
+ describe('unresolvedDiscussionsIdsByDate', () => {
+ it('should return all discussions in date ascending order', () => {
+ const localGetters = {
+ allResolvableDiscussions: [discussion3, discussion1, discussion2],
+ };
+
+ expect(getters.unresolvedDiscussionsIdsByDate(state, localGetters)).toEqual([
+ 'abc2',
+ 'abc1',
+ 'abc3',
+ ]);
+ });
+
+ it('should return empty array if all discussions have been resolved', () => {
+ const localGetters = {
+ allResolvableDiscussions: [resolvedDiscussion1],
+ };
+
+ expect(getters.unresolvedDiscussionsIdsByDate(state, localGetters)).toEqual([]);
+ });
+ });
+
+ describe('unresolvedDiscussionsIdsOrdered', () => {
+ const localGetters = {
+ unresolvedDiscussionsIdsByDate: ['123', '456'],
+ unresolvedDiscussionsIdsByDiff: ['abc', 'def'],
+ };
+
+ it('should return IDs ordered by diff when diffOrder param is true', () => {
+ expect(getters.unresolvedDiscussionsIdsOrdered(state, localGetters)(true)).toEqual([
+ 'abc',
+ 'def',
+ ]);
+ });
+
+ it('should return IDs ordered by date when diffOrder param is not true', () => {
+ expect(getters.unresolvedDiscussionsIdsOrdered(state, localGetters)(false)).toEqual([
+ '123',
+ '456',
+ ]);
+ expect(getters.unresolvedDiscussionsIdsOrdered(state, localGetters)(undefined)).toEqual([
+ '123',
+ '456',
+ ]);
+ });
+ });
+
+ describe('isLastUnresolvedDiscussion', () => {
+ const localGetters = {
+ unresolvedDiscussionsIdsOrdered: () => ['123', '456', '789'],
+ };
+
+ it('should return true if the discussion id provided is the last', () => {
+ expect(getters.isLastUnresolvedDiscussion(state, localGetters)('789')).toBe(true);
+ });
+
+ it('should return false if the discussion id provided is not the last', () => {
+ expect(getters.isLastUnresolvedDiscussion(state, localGetters)('123')).toBe(false);
+ expect(getters.isLastUnresolvedDiscussion(state, localGetters)('456')).toBe(false);
+ });
+ });
+
+ describe('nextUnresolvedDiscussionId', () => {
+ const localGetters = {
+ unresolvedDiscussionsIdsOrdered: () => ['123', '456', '789'],
+ };
+
+ it('should return the ID of the discussion after the ID provided', () => {
+ expect(getters.nextUnresolvedDiscussionId(state, localGetters)('123')).toBe('456');
+ expect(getters.nextUnresolvedDiscussionId(state, localGetters)('456')).toBe('789');
+ expect(getters.nextUnresolvedDiscussionId(state, localGetters)('789')).toBe(undefined);
+ });
+ });
+
+ describe('firstUnresolvedDiscussionId', () => {
+ const localGetters = {
+ unresolvedDiscussionsIdsByDate: ['123', '456'],
+ unresolvedDiscussionsIdsByDiff: ['abc', 'def'],
+ };
+
+ it('should return the first discussion id by diff when diffOrder param is true', () => {
+ expect(getters.firstUnresolvedDiscussionId(state, localGetters)(true)).toBe('abc');
+ });
+
+ it('should return the first discussion id by date when diffOrder param is not true', () => {
+ expect(getters.firstUnresolvedDiscussionId(state, localGetters)(false)).toBe('123');
+ expect(getters.firstUnresolvedDiscussionId(state, localGetters)(undefined)).toBe('123');
+ });
+
+ it('should be falsy if all discussions are resolved', () => {
+ const localGettersFalsy = {
+ unresolvedDiscussionsIdsByDiff: [],
+ unresolvedDiscussionsIdsByDate: [],
+ };
+
+ expect(getters.firstUnresolvedDiscussionId(state, localGettersFalsy)(true)).toBeFalsy();
+ expect(getters.firstUnresolvedDiscussionId(state, localGettersFalsy)(false)).toBeFalsy();
+ });
+ });
});
diff --git a/spec/javascripts/reports/store/actions_spec.js b/spec/javascripts/reports/store/actions_spec.js
new file mode 100644
index 00000000000..c714c5af156
--- /dev/null
+++ b/spec/javascripts/reports/store/actions_spec.js
@@ -0,0 +1,130 @@
+import MockAdapter from 'axios-mock-adapter';
+import axios from '~/lib/utils/axios_utils';
+import {
+ setEndpoint,
+ requestReports,
+ fetchReports,
+ stopPolling,
+ clearEtagPoll,
+ receiveReportsSuccess,
+ receiveReportsError,
+} from '~/reports/store/actions';
+import state from '~/reports/store/state';
+import * as types from '~/reports/store/mutation_types';
+import testAction from 'spec/helpers/vuex_action_helper';
+import { TEST_HOST } from 'spec/test_constants';
+
+describe('Reports Store Actions', () => {
+ let mockedState;
+
+ beforeEach(() => {
+ mockedState = state();
+ });
+
+ describe('setEndpoint', () => {
+ it('should commit SET_ENDPOINT mutation', done => {
+ testAction(
+ setEndpoint,
+ 'endpoint.json',
+ mockedState,
+ [{ type: types.SET_ENDPOINT, payload: 'endpoint.json' }],
+ [],
+ done,
+ );
+ });
+ });
+
+ describe('requestReports', () => {
+ it('should commit REQUEST_REPORTS mutation', done => {
+ testAction(requestReports, null, mockedState, [{ type: types.REQUEST_REPORTS }], [], done);
+ });
+ });
+
+ describe('fetchReports', () => {
+ let mock;
+
+ beforeEach(() => {
+ mockedState.endpoint = `${TEST_HOST}/endpoint.json`;
+ mock = new MockAdapter(axios);
+ });
+
+ afterEach(() => {
+ mock.restore();
+ stopPolling();
+ clearEtagPoll();
+ });
+
+ describe('success', () => {
+ it('dispatches requestReports and receiveReportsSuccess ', done => {
+ mock.onGet(`${TEST_HOST}/endpoint.json`).replyOnce(200, { summary: {}, suites: [{ name: 'rspec' }] });
+
+ testAction(
+ fetchReports,
+ null,
+ mockedState,
+ [],
+ [
+ {
+ type: 'requestReports',
+ },
+ {
+ payload: { summary: {}, suites: [{ name: 'rspec' }] },
+ type: 'receiveReportsSuccess',
+ },
+ ],
+ done,
+ );
+ });
+ });
+
+ describe('error', () => {
+ beforeEach(() => {
+ mock.onGet(`${TEST_HOST}/endpoint.json`).reply(500);
+ });
+
+ it('dispatches requestReports and receiveReportsError ', done => {
+ testAction(
+ fetchReports,
+ null,
+ mockedState,
+ [],
+ [
+ {
+ type: 'requestReports',
+ },
+ {
+ type: 'receiveReportsError',
+ },
+ ],
+ done,
+ );
+ });
+ });
+ });
+
+ describe('receiveReportsSuccess', () => {
+ it('should commit RECEIVE_REPORTS_SUCCESS mutation', done => {
+ testAction(
+ receiveReportsSuccess,
+ { summary: {} },
+ mockedState,
+ [{ type: types.RECEIVE_REPORTS_SUCCESS, payload: { summary: {} } }],
+ [],
+ done,
+ );
+ });
+ });
+
+ describe('receiveReportsError', () => {
+ it('should commit RECEIVE_REPORTS_ERROR mutation', done => {
+ testAction(
+ receiveReportsError,
+ null,
+ mockedState,
+ [{ type: types.RECEIVE_REPORTS_ERROR }],
+ [],
+ done,
+ );
+ });
+ });
+});
diff --git a/spec/javascripts/reports/store/mutations_spec.js b/spec/javascripts/reports/store/mutations_spec.js
new file mode 100644
index 00000000000..3e0b15438c3
--- /dev/null
+++ b/spec/javascripts/reports/store/mutations_spec.js
@@ -0,0 +1,101 @@
+import state from '~/reports/store/state';
+import mutations from '~/reports/store/mutations';
+import * as types from '~/reports/store/mutation_types';
+
+describe('Reports Store Mutations', () => {
+ let stateCopy;
+
+ beforeEach(() => {
+ stateCopy = state();
+ });
+
+ describe('SET_ENDPOINT', () => {
+ it('should set endpoint', () => {
+ mutations[types.SET_ENDPOINT](stateCopy, 'endpoint.json');
+ expect(stateCopy.endpoint).toEqual('endpoint.json');
+ });
+ });
+
+ describe('REQUEST_REPORTS', () => {
+ it('should set isLoading to true', () => {
+ mutations[types.REQUEST_REPORTS](stateCopy);
+ expect(stateCopy.isLoading).toEqual(true);
+ });
+ });
+
+ describe('RECEIVE_REPORTS_SUCCESS', () => {
+ const mockedResponse = {
+ summary: {
+ total: 14,
+ resolved: 0,
+ failed: 7,
+ },
+ suites: [
+ {
+ name: 'build:linux',
+ summary: {
+ total: 2,
+ resolved: 0,
+ failed: 1,
+ },
+ new_failures: [
+ {
+ name: 'StringHelper#concatenate when a is git and b is lab returns summary',
+ execution_time: 0.0092435,
+ system_output:
+ 'Failure/Error: is_expected.to eq(\'gitlab\')',
+ },
+ ],
+ resolved_failures: [
+ {
+ name: 'StringHelper#concatenate when a is git and b is lab returns summary',
+ execution_time: 0.009235,
+ system_output:
+ 'Failure/Error: is_expected.to eq(\'gitlab\')',
+ },
+ ],
+ existing_failures: [
+ {
+ name: 'StringHelper#concatenate when a is git and b is lab returns summary',
+ execution_time: 1232.08,
+ system_output:
+ 'Failure/Error: is_expected.to eq(\'gitlab\')',
+ },
+ ],
+ },
+ ],
+ };
+
+ beforeEach(() => {
+ mutations[types.RECEIVE_REPORTS_SUCCESS](stateCopy, mockedResponse);
+ });
+
+ it('should reset isLoading', () => {
+ expect(stateCopy.isLoading).toEqual(false);
+ });
+
+ it('should set summary counts', () => {
+ expect(stateCopy.summary.total).toEqual(mockedResponse.summary.total);
+ expect(stateCopy.summary.resolved).toEqual(mockedResponse.summary.resolved);
+ expect(stateCopy.summary.failed).toEqual(mockedResponse.summary.failed);
+ });
+
+ it('should set reports', () => {
+ expect(stateCopy.reports).toEqual(mockedResponse.suites);
+ });
+ });
+
+ describe('RECEIVE_REPORTS_ERROR', () => {
+ beforeEach(() => {
+ mutations[types.RECEIVE_REPORTS_ERROR](stateCopy);
+ });
+ it('should reset isLoading', () => {
+ expect(stateCopy.isLoading).toEqual(false);
+ });
+
+ it('should set hasError to true', () => {
+ expect(stateCopy.hasError).toEqual(true);
+ });
+
+ });
+});
diff --git a/spec/javascripts/vue_shared/components/clipboard_button_spec.js b/spec/javascripts/vue_shared/components/clipboard_button_spec.js
index 97f0fbb04db..e135690349e 100644
--- a/spec/javascripts/vue_shared/components/clipboard_button_spec.js
+++ b/spec/javascripts/vue_shared/components/clipboard_button_spec.js
@@ -21,7 +21,7 @@ describe('clipboard button', () => {
it('renders a button for clipboard', () => {
expect(vm.$el.tagName).toEqual('BUTTON');
expect(vm.$el.getAttribute('data-clipboard-text')).toEqual('copy me');
- expect(vm.$el.querySelector('i').className).toEqual('fa fa-clipboard');
+ expect(vm.$el).toHaveSpriteIcon('duplicate');
});
it('should have a tooltip with default values', () => {
diff --git a/spec/lib/banzai/filter/image_lazy_load_filter_spec.rb b/spec/lib/banzai/filter/image_lazy_load_filter_spec.rb
index 41f957c4e00..d06c5535309 100644
--- a/spec/lib/banzai/filter/image_lazy_load_filter_spec.rb
+++ b/spec/lib/banzai/filter/image_lazy_load_filter_spec.rb
@@ -7,6 +7,20 @@ describe Banzai::Filter::ImageLazyLoadFilter do
%(<img src="#{path}" />)
end
+ def image_with_class(path, class_attr = nil)
+ %(<img src="#{path}" class="#{class_attr}"/>)
+ end
+
+ it 'adds a class attribute' do
+ doc = filter(image('/uploads/e90decf88d8f96fe9e1389afc2e4a91f/test.jpg'))
+ expect(doc.at_css('img')['class']).to eq 'lazy'
+ end
+
+ it 'appends to the current class attribute' do
+ doc = filter(image_with_class('/uploads/e90decf88d8f96fe9e1389afc2e4a91f/test.jpg', 'test'))
+ expect(doc.at_css('img')['class']).to eq 'test lazy'
+ end
+
it 'transforms the image src to a data-src' do
doc = filter(image('/uploads/e90decf88d8f96fe9e1389afc2e4a91f/test.jpg'))
expect(doc.at_css('img')['data-src']).to eq '/uploads/e90decf88d8f96fe9e1389afc2e4a91f/test.jpg'
diff --git a/spec/lib/feature_spec.rb b/spec/lib/feature_spec.rb
index 6eb10497428..f313e675654 100644
--- a/spec/lib/feature_spec.rb
+++ b/spec/lib/feature_spec.rb
@@ -39,18 +39,36 @@ describe Feature do
end
describe '.persisted?' do
- it 'returns true for a persisted feature' do
- Feature::FlipperFeature.create!(key: 'foo')
+ context 'when the feature is persisted' do
+ it 'returns true when feature name is a string' do
+ Feature::FlipperFeature.create!(key: 'foo')
+
+ feature = double(:feature, name: 'foo')
+
+ expect(described_class.persisted?(feature)).to eq(true)
+ end
+
+ it 'returns true when feature name is a symbol' do
+ Feature::FlipperFeature.create!(key: 'foo')
- feature = double(:feature, name: 'foo')
+ feature = double(:feature, name: :foo)
- expect(described_class.persisted?(feature)).to eq(true)
+ expect(described_class.persisted?(feature)).to eq(true)
+ end
end
- it 'returns false for a feature that is not persisted' do
- feature = double(:feature, name: 'foo')
+ context 'when the feature is not persisted' do
+ it 'returns false when feature name is a string' do
+ feature = double(:feature, name: 'foo')
+
+ expect(described_class.persisted?(feature)).to eq(false)
+ end
- expect(described_class.persisted?(feature)).to eq(false)
+ it 'returns false when feature name is a symbol' do
+ feature = double(:feature, name: :bar)
+
+ expect(described_class.persisted?(feature)).to eq(false)
+ 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 adb3ff4321f..46874662edd 100644
--- a/spec/lib/gitlab/ci/variables/collection/item_spec.rb
+++ b/spec/lib/gitlab/ci/variables/collection/item_spec.rb
@@ -75,6 +75,14 @@ describe Gitlab::Ci::Variables::Collection::Item do
expect(resource).to eq variable
end
+ it 'supports using a hash with stringified values' do
+ variable = { 'key' => 'VARIABLE', 'value' => 'my value' }
+
+ resource = described_class.fabricate(variable)
+
+ expect(resource).to eq(key: 'VARIABLE', value: 'my value')
+ end
+
it 'supports using an active record resource' do
variable = create(:ci_variable, key: 'CI_VAR', value: '123')
resource = described_class.fabricate(variable)
diff --git a/spec/lib/gitlab/git/repository_spec.rb b/spec/lib/gitlab/git/repository_spec.rb
index 0365c3b20ef..62396af1ebe 100644
--- a/spec/lib/gitlab/git/repository_spec.rb
+++ b/spec/lib/gitlab/git/repository_spec.rb
@@ -527,25 +527,6 @@ describe Gitlab::Git::Repository, seed_helper: true do
end
end
- describe "#remote_update" do
- before(:all) do
- @repo = Gitlab::Git::Repository.new('default', TEST_MUTABLE_REPO_PATH, '')
- @repo.remote_update("expendable", url: TEST_NORMAL_REPO_PATH)
- end
-
- it "should add the remote" do
- rugged = Gitlab::GitalyClient::StorageSettings.allow_disk_access { @repo.rugged }
-
- expect(rugged.remotes["expendable"].url).to(
- eq(TEST_NORMAL_REPO_PATH)
- )
- end
-
- after(:all) do
- ensure_seeds
- end
- end
-
describe '#fetch_repository_as_mirror' do
let(:new_repository) do
Gitlab::Git::Repository.new('default', 'my_project.git', '')
@@ -602,40 +583,6 @@ describe Gitlab::Git::Repository, seed_helper: true do
end
end
- describe '#remote_tags' do
- let(:remote_name) { 'upstream' }
- let(:target_commit_id) { SeedRepo::Commit::ID }
- let(:tag_name) { 'v0.0.1' }
- let(:tag_message) { 'My tag' }
- let(:remote_repository) do
- Gitlab::Git::Repository.new('default', TEST_MUTABLE_REPO_PATH, '')
- end
-
- around do |example|
- Gitlab::GitalyClient::StorageSettings.allow_disk_access do
- example.run
- end
- end
-
- subject { repository.remote_tags(remote_name) }
-
- before do
- remote_repository_path = Gitlab::GitalyClient::StorageSettings.allow_disk_access { remote_repository.path }
- repository.add_remote(remote_name, remote_repository_path)
- remote_repository.add_tag(tag_name, user: user, target: target_commit_id)
- end
-
- after do
- ensure_seeds
- end
-
- it 'gets the remote tags' do
- expect(subject.first).to be_an_instance_of(Gitlab::Git::Tag)
- expect(subject.first.name).to eq(tag_name)
- expect(subject.first.dereferenced_target.id).to eq(target_commit_id)
- end
- end
-
describe "#log" do
shared_examples 'repository log' do
let(:commit_with_old_name) do
diff --git a/spec/lib/gitlab/gitaly_client/operation_service_spec.rb b/spec/lib/gitlab/gitaly_client/operation_service_spec.rb
index 031d1e87dc1..eaf64e3c9b4 100644
--- a/spec/lib/gitlab/gitaly_client/operation_service_spec.rb
+++ b/spec/lib/gitlab/gitaly_client/operation_service_spec.rb
@@ -1,10 +1,10 @@
require 'spec_helper'
describe Gitlab::GitalyClient::OperationService do
- let(:project) { create(:project) }
+ set(:project) { create(:project, :repository) }
let(:repository) { project.repository.raw }
let(:client) { described_class.new(repository) }
- let(:user) { create(:user) }
+ set(:user) { create(:user) }
let(:gitaly_user) { Gitlab::Git::User.from_gitlab(user).to_gitaly }
describe '#user_create_branch' do
@@ -151,18 +151,104 @@ describe Gitlab::GitalyClient::OperationService do
end
let(:response) { Gitaly::UserFFBranchResponse.new(branch_update: branch_update) }
- subject { client.user_ff_branch(user, source_sha, target_branch) }
-
- it 'sends a user_ff_branch message and returns a BranchUpdate object' do
+ before do
expect_any_instance_of(Gitaly::OperationService::Stub)
.to receive(:user_ff_branch).with(request, kind_of(Hash))
.and_return(response)
+ end
+ subject { client.user_ff_branch(user, source_sha, target_branch) }
+
+ it 'sends a user_ff_branch message and returns a BranchUpdate object' do
expect(subject).to be_a(Gitlab::Git::OperationService::BranchUpdate)
expect(subject.newrev).to eq(source_sha)
expect(subject.repo_created).to be(false)
expect(subject.branch_created).to be(false)
end
+
+ context 'when the response has no branch_update' do
+ let(:response) { Gitaly::UserFFBranchResponse.new }
+
+ it { expect(subject).to be_nil }
+ end
+ end
+
+ shared_examples 'cherry pick and revert errors' do
+ context 'when a pre_receive_error is present' do
+ let(:response) { response_class.new(pre_receive_error: "something failed") }
+
+ it 'raises a PreReceiveError' do
+ expect { subject }.to raise_error(Gitlab::Git::PreReceiveError, "something failed")
+ end
+ end
+
+ context 'when a commit_error is present' do
+ let(:response) { response_class.new(commit_error: "something failed") }
+
+ it 'raises a CommitError' do
+ expect { subject }.to raise_error(Gitlab::Git::CommitError, "something failed")
+ end
+ end
+
+ context 'when a create_tree_error is present' do
+ let(:response) { response_class.new(create_tree_error: "something failed") }
+
+ it 'raises a CreateTreeError' do
+ expect { subject }.to raise_error(Gitlab::Git::Repository::CreateTreeError, "something failed")
+ end
+ end
+
+ context 'when branch_update is nil' do
+ let(:response) { response_class.new }
+
+ it { expect(subject).to be_nil }
+ end
+ end
+
+ describe '#user_cherry_pick' do
+ let(:response_class) { Gitaly::UserCherryPickResponse }
+
+ subject do
+ client.user_cherry_pick(
+ user: user,
+ commit: repository.commit,
+ branch_name: 'master',
+ message: 'Cherry-pick message',
+ start_branch_name: 'master',
+ start_repository: repository
+ )
+ end
+
+ before do
+ expect_any_instance_of(Gitaly::OperationService::Stub)
+ .to receive(:user_cherry_pick).with(kind_of(Gitaly::UserCherryPickRequest), kind_of(Hash))
+ .and_return(response)
+ end
+
+ it_behaves_like 'cherry pick and revert errors'
+ end
+
+ describe '#user_revert' do
+ let(:response_class) { Gitaly::UserRevertResponse }
+
+ subject do
+ client.user_revert(
+ user: user,
+ commit: repository.commit,
+ branch_name: 'master',
+ message: 'Revert message',
+ start_branch_name: 'master',
+ start_repository: repository
+ )
+ end
+
+ before do
+ expect_any_instance_of(Gitaly::OperationService::Stub)
+ .to receive(:user_revert).with(kind_of(Gitaly::UserRevertRequest), kind_of(Hash))
+ .and_return(response)
+ end
+
+ it_behaves_like 'cherry pick and revert errors'
end
describe '#user_squash' do
@@ -203,7 +289,7 @@ describe Gitlab::GitalyClient::OperationService do
Gitaly::UserSquashResponse.new(git_error: "something failed")
end
- it "throws a PreReceive exception" do
+ it "raises a GitError exception" do
expect_any_instance_of(Gitaly::OperationService::Stub)
.to receive(:user_squash).with(request, kind_of(Hash))
.and_return(response)
@@ -212,5 +298,41 @@ describe Gitlab::GitalyClient::OperationService do
Gitlab::Git::Repository::GitError, "something failed")
end
end
+
+ describe '#user_commit_files' do
+ subject do
+ client.user_commit_files(
+ gitaly_user, 'my-branch', 'Commit files message', [], 'janedoe@example.com', 'Jane Doe',
+ 'master', repository)
+ end
+
+ before do
+ expect_any_instance_of(Gitaly::OperationService::Stub)
+ .to receive(:user_commit_files).with(kind_of(Enumerator), kind_of(Hash))
+ .and_return(response)
+ end
+
+ context 'when a pre_receive_error is present' do
+ let(:response) { Gitaly::UserCommitFilesResponse.new(pre_receive_error: "something failed") }
+
+ it 'raises a PreReceiveError' do
+ expect { subject }.to raise_error(Gitlab::Git::PreReceiveError, "something failed")
+ end
+ end
+
+ context 'when an index_error is present' do
+ let(:response) { Gitaly::UserCommitFilesResponse.new(index_error: "something failed") }
+
+ it 'raises a PreReceiveError' do
+ expect { subject }.to raise_error(Gitlab::Git::Index::IndexError, "something failed")
+ end
+ end
+
+ context 'when branch_update is nil' do
+ let(:response) { Gitaly::UserCommitFilesResponse.new }
+
+ it { expect(subject).to be_nil }
+ end
+ end
end
end
diff --git a/spec/lib/gitlab/gitaly_client/ref_service_spec.rb b/spec/lib/gitlab/gitaly_client/ref_service_spec.rb
index 257e4c50f2d..400d426c949 100644
--- a/spec/lib/gitlab/gitaly_client/ref_service_spec.rb
+++ b/spec/lib/gitlab/gitaly_client/ref_service_spec.rb
@@ -18,6 +18,44 @@ describe Gitlab::GitalyClient::RefService do
end
end
+ describe '#remote_branches' do
+ let(:remote_name) { 'my_remote' }
+ subject { client.remote_branches(remote_name) }
+
+ it 'sends a find_all_remote_branches message' do
+ expect_any_instance_of(Gitaly::RefService::Stub)
+ .to receive(:find_all_remote_branches)
+ .with(gitaly_request_with_path(storage_name, relative_path), kind_of(Hash))
+ .and_return([])
+
+ subject
+ end
+
+ it 'concantes and returns the response branches as Gitlab::Git::Branch objects' do
+ target_commits = create_list(:gitaly_commit, 4)
+ response_branches = target_commits.each_with_index.map do |gitaly_commit, i|
+ Gitaly::Branch.new(name: "#{remote_name}/#{i}", target_commit: gitaly_commit)
+ end
+ response = [
+ Gitaly::FindAllRemoteBranchesResponse.new(branches: response_branches[0, 2]),
+ Gitaly::FindAllRemoteBranchesResponse.new(branches: response_branches[2, 2])
+ ]
+
+ expect_any_instance_of(Gitaly::RefService::Stub)
+ .to receive(:find_all_remote_branches).and_return(response)
+
+ expect(subject.length).to be(response_branches.length)
+
+ response_branches.each_with_index do |gitaly_branch, i|
+ branch = subject[i]
+ commit = Gitlab::Git::Commit.new(repository, gitaly_branch.target_commit)
+
+ expect(branch.name).to eq(i.to_s) # It removes the `remote/` prefix
+ expect(branch.dereferenced_target).to eq(commit)
+ end
+ end
+ end
+
describe '#branch_names' do
it 'sends a find_all_branch_names message' do
expect_any_instance_of(Gitaly::RefService::Stub)
diff --git a/spec/lib/gitlab/gitlab_import/client_spec.rb b/spec/lib/gitlab/gitlab_import/client_spec.rb
index 50e8d7183ce..22ad88e28cb 100644
--- a/spec/lib/gitlab/gitlab_import/client_spec.rb
+++ b/spec/lib/gitlab/gitlab_import/client_spec.rb
@@ -15,4 +15,88 @@ describe Gitlab::GitlabImport::Client do
expect(key).to be_kind_of(Symbol)
end
end
+
+ it 'uses membership and simple flags' do
+ stub_request('/api/v4/projects?membership=true&page=1&per_page=100&simple=true')
+
+ expect_any_instance_of(OAuth2::Response).to receive(:parsed).and_return([])
+
+ expect(client.projects.to_a).to eq []
+ end
+
+ shared_examples 'pagination params' do
+ before do
+ allow_any_instance_of(OAuth2::Response).to receive(:parsed).and_return([])
+ end
+
+ it 'allows page_limit param' do
+ allow_any_instance_of(OAuth2::Response).to receive(:parsed).and_return(element_list)
+
+ expect(client).to receive(:lazy_page_iterator).with(hash_including(page_limit: 2)).and_call_original
+
+ client.send(method, *args, page_limit: 2, per_page: 1).to_a
+ end
+
+ it 'allows per_page param' do
+ expect(client).to receive(:lazy_page_iterator).with(hash_including(per_page: 2)).and_call_original
+
+ client.send(method, *args, per_page: 2).to_a
+ end
+
+ it 'allows starting_page param' do
+ expect(client).to receive(:lazy_page_iterator).with(hash_including(starting_page: 3)).and_call_original
+
+ client.send(method, *args, starting_page: 3).to_a
+ end
+ end
+
+ describe '#projects' do
+ subject(:method) { :projects }
+ let(:args) { [] }
+ let(:element_list) { build_list(:project, 2) }
+
+ before do
+ stub_request('/api/v4/projects?membership=true&page=1&per_page=1&simple=true')
+ stub_request('/api/v4/projects?membership=true&page=2&per_page=1&simple=true')
+ stub_request('/api/v4/projects?membership=true&page=1&per_page=2&simple=true')
+ stub_request('/api/v4/projects?membership=true&page=3&per_page=100&simple=true')
+ end
+
+ it_behaves_like 'pagination params'
+ end
+
+ describe '#issues' do
+ subject(:method) { :issues }
+ let(:args) { [1] }
+ let(:element_list) { build_list(:issue, 2) }
+
+ before do
+ stub_request('/api/v4/projects/1/issues?page=1&per_page=1')
+ stub_request('/api/v4/projects/1/issues?page=2&per_page=1')
+ stub_request('/api/v4/projects/1/issues?page=1&per_page=2')
+ stub_request('/api/v4/projects/1/issues?page=3&per_page=100')
+ end
+
+ it_behaves_like 'pagination params'
+ end
+
+ describe '#issue_comments' do
+ subject(:method) { :issue_comments }
+ let(:args) { [1, 1] }
+ let(:element_list) { build_list(:note_on_issue, 2) }
+
+ before do
+ stub_request('/api/v4/projects/1/issues/1/notes?page=1&per_page=1')
+ stub_request('/api/v4/projects/1/issues/1/notes?page=2&per_page=1')
+ stub_request('/api/v4/projects/1/issues/1/notes?page=1&per_page=2')
+ stub_request('/api/v4/projects/1/issues/1/notes?page=3&per_page=100')
+ end
+
+ it_behaves_like 'pagination params'
+ end
+
+ def stub_request(path)
+ WebMock.stub_request(:get, "https://gitlab.com#{path}")
+ .to_return(status: 200)
+ end
end
diff --git a/spec/lib/gitlab/hashed_storage/migrator_spec.rb b/spec/lib/gitlab/hashed_storage/migrator_spec.rb
index 813ae43b4d3..7eac2cacb90 100644
--- a/spec/lib/gitlab/hashed_storage/migrator_spec.rb
+++ b/spec/lib/gitlab/hashed_storage/migrator_spec.rb
@@ -65,7 +65,7 @@ describe Gitlab::HashedStorage::Migrator do
end
it 'migrate project' do
- Sidekiq::Testing.inline! do
+ perform_enqueued_jobs do
subject.migrate(project)
end
diff --git a/spec/lib/gitlab/import_export/all_models.yml b/spec/lib/gitlab/import_export/all_models.yml
index 084ce3066d6..db5aab0cd76 100644
--- a/spec/lib/gitlab/import_export/all_models.yml
+++ b/spec/lib/gitlab/import_export/all_models.yml
@@ -211,6 +211,7 @@ project:
- slack_service
- microsoft_teams_service
- mattermost_service
+- hangouts_chat_service
- buildkite_service
- bamboo_service
- teamcity_service
diff --git a/spec/lib/gitlab/json_logger_spec.rb b/spec/lib/gitlab/json_logger_spec.rb
new file mode 100644
index 00000000000..0a62785f880
--- /dev/null
+++ b/spec/lib/gitlab/json_logger_spec.rb
@@ -0,0 +1,29 @@
+# coding: utf-8
+require 'spec_helper'
+
+describe Gitlab::JsonLogger do
+ subject { described_class.new('/dev/null') }
+
+ let(:now) { Time.now }
+
+ describe '#format_message' do
+ it 'formats strings' do
+ output = subject.format_message('INFO', now, 'test', 'Hello world')
+ data = JSON.parse(output)
+
+ expect(data['severity']).to eq('INFO')
+ expect(data['time']).to eq(now.utc.iso8601(3))
+ expect(data['message']).to eq('Hello world')
+ end
+
+ it 'formats hashes' do
+ output = subject.format_message('INFO', now, 'test', { hello: 1 })
+ data = JSON.parse(output)
+
+ expect(data['severity']).to eq('INFO')
+ expect(data['time']).to eq(now.utc.iso8601(3))
+ expect(data['hello']).to eq(1)
+ expect(data['message']).to be_nil
+ end
+ end
+end
diff --git a/spec/lib/gitlab/project_search_results_spec.rb b/spec/lib/gitlab/project_search_results_spec.rb
index 767a3092c73..4a0dc3686ec 100644
--- a/spec/lib/gitlab/project_search_results_spec.rb
+++ b/spec/lib/gitlab/project_search_results_spec.rb
@@ -64,6 +64,49 @@ describe Gitlab::ProjectSearchResults do
end
end
+ shared_examples 'blob search repository ref' do |entity_type|
+ let(:query) { 'files' }
+ let(:file_finder) { double }
+ let(:project_branch) { 'project_branch' }
+
+ subject(:results) { described_class.new(user, project, query, repository_ref).objects(blob_type) }
+
+ before do
+ allow(entity).to receive(:default_branch).and_return(project_branch)
+ allow(file_finder).to receive(:find).and_return([])
+ end
+
+ context 'when repository_ref exists' do
+ let(:repository_ref) { 'ref_branch' }
+
+ it 'uses it' do
+ expect(Gitlab::FileFinder).to receive(:new).with(project, repository_ref).and_return(file_finder)
+
+ results
+ end
+ end
+
+ context 'when repository_ref is not present' do
+ let(:repository_ref) { nil }
+
+ it "uses #{entity_type} repository default reference" do
+ expect(Gitlab::FileFinder).to receive(:new).with(project, project_branch).and_return(file_finder)
+
+ results
+ end
+ end
+
+ context 'when repository_ref is blank' do
+ let(:repository_ref) { '' }
+
+ it "uses #{entity_type} repository default reference" do
+ expect(Gitlab::FileFinder).to receive(:new).with(project, project_branch).and_return(file_finder)
+
+ results
+ end
+ end
+ end
+
describe 'blob search' do
let(:project) { create(:project, :public, :repository) }
@@ -75,6 +118,11 @@ describe Gitlab::ProjectSearchResults do
let(:expected_file_by_content) { 'CHANGELOG' }
end
+ it_behaves_like 'blob search repository ref', 'project' do
+ let(:blob_type) { 'blobs' }
+ let(:entity) { project }
+ end
+
describe 'parsing results' do
let(:results) { project.repository.search_files_by_content('feature', 'master') }
let(:search_result) { results.first }
@@ -212,6 +260,11 @@ describe Gitlab::ProjectSearchResults do
let(:expected_file_by_name) { 'Files/Title.md' }
let(:expected_file_by_content) { 'CHANGELOG.md' }
end
+
+ it_behaves_like 'blob search repository ref', 'wiki' do
+ let(:blob_type) { 'wiki_blobs' }
+ let(:entity) { project.wiki }
+ end
end
it 'does not list issues on private projects' do
diff --git a/spec/lib/gitlab/serializer/ci/variables_spec.rb b/spec/lib/gitlab/serializer/ci/variables_spec.rb
index c4b7fda5dbb..1d1fd5b0763 100644
--- a/spec/lib/gitlab/serializer/ci/variables_spec.rb
+++ b/spec/lib/gitlab/serializer/ci/variables_spec.rb
@@ -1,4 +1,4 @@
-require 'spec_helper'
+require 'fast_spec_helper'
describe Gitlab::Serializer::Ci::Variables do
subject do
@@ -6,11 +6,11 @@ describe Gitlab::Serializer::Ci::Variables do
end
let(:object) do
- [{ key: :key, value: 'value', public: true },
+ [{ 'key' => :key, 'value' => 'value', 'public' => true },
{ key: 'wee', value: 1, public: false }]
end
- it 'converts keys into strings' do
+ it 'converts keys into strings and symbolizes hash' do
is_expected.to eq([
{ key: 'key', value: 'value', public: true },
{ key: 'wee', value: 1, public: false }
diff --git a/spec/lib/gitlab/url_sanitizer_spec.rb b/spec/lib/gitlab/url_sanitizer_spec.rb
index 758a9bc5a2b..b41a81a8167 100644
--- a/spec/lib/gitlab/url_sanitizer_spec.rb
+++ b/spec/lib/gitlab/url_sanitizer_spec.rb
@@ -145,6 +145,10 @@ describe Gitlab::UrlSanitizer do
'http://foo:@example.com' | 'http://foo@example.com'
'http://:bar@example.com' | :same
'http://foo:bar@example.com' | :same
+ 'http://foo:g p@example.com' | 'http://foo:g%20p@example.com'
+ 'http://foo:s/h@example.com' | 'http://foo:s%2Fh@example.com'
+ 'http://t u:a#b@example.com' | 'http://t%20u:a%23b@example.com'
+ 'http://t+u:a#b@example.com' | 'http://t%2Bu:a%23b@example.com'
end
with_them do
@@ -160,7 +164,7 @@ describe Gitlab::UrlSanitizer do
url_sanitizer = described_class.new("https://foo:b?r@github.com/me/project.git")
expect(url_sanitizer.sanitized_url).to eq("https://github.com/me/project.git")
- expect(url_sanitizer.full_url).to eq("https://foo:b?r@github.com/me/project.git")
+ expect(url_sanitizer.full_url).to eq("https://foo:b%3Fr@github.com/me/project.git")
end
end
end
diff --git a/spec/lib/gitlab/usage_data_spec.rb b/spec/lib/gitlab/usage_data_spec.rb
index 20def4fefe2..a19b3c0ba66 100644
--- a/spec/lib/gitlab/usage_data_spec.rb
+++ b/spec/lib/gitlab/usage_data_spec.rb
@@ -133,7 +133,7 @@ describe Gitlab::UsageData do
expect(subject[:signup_enabled]).to eq(Gitlab::CurrentSettings.allow_signup?)
expect(subject[:ldap_enabled]).to eq(Gitlab.config.ldap.enabled)
expect(subject[:gravatar_enabled]).to eq(Gitlab::CurrentSettings.gravatar_enabled?)
- expect(subject[:omniauth_enabled]).to eq(Gitlab.config.omniauth.enabled)
+ expect(subject[:omniauth_enabled]).to eq(Gitlab::Auth.omniauth_enabled?)
expect(subject[:reply_by_email_enabled]).to eq(Gitlab::IncomingEmail.enabled?)
expect(subject[:container_registry_enabled]).to eq(Gitlab.config.registry.enabled)
expect(subject[:gitlab_shared_runners_enabled]).to eq(Gitlab.config.gitlab_ci.shared_runners_enabled)
diff --git a/spec/lib/gitlab/user_activities_spec.rb b/spec/lib/gitlab/user_activities_spec.rb
deleted file mode 100644
index 6bce2ee13cf..00000000000
--- a/spec/lib/gitlab/user_activities_spec.rb
+++ /dev/null
@@ -1,127 +0,0 @@
-require 'spec_helper'
-
-describe Gitlab::UserActivities, :clean_gitlab_redis_shared_state do
- let(:now) { Time.now }
-
- describe '.record' do
- context 'with no time given' do
- it 'uses Time.now and records an activity in SharedState' do
- Timecop.freeze do
- now # eager-load now
- described_class.record(42)
- end
-
- Gitlab::Redis::SharedState.with do |redis|
- expect(redis.hscan(described_class::KEY, 0)).to eq(['0', [['42', now.to_i.to_s]]])
- end
- end
- end
-
- context 'with a time given' do
- it 'uses the given time and records an activity in SharedState' do
- described_class.record(42, now)
-
- Gitlab::Redis::SharedState.with do |redis|
- expect(redis.hscan(described_class::KEY, 0)).to eq(['0', [['42', now.to_i.to_s]]])
- end
- end
- end
- end
-
- describe '.delete' do
- context 'with a single key' do
- context 'and key exists' do
- it 'removes the pair from SharedState' do
- described_class.record(42, now)
-
- Gitlab::Redis::SharedState.with do |redis|
- expect(redis.hscan(described_class::KEY, 0)).to eq(['0', [['42', now.to_i.to_s]]])
- end
-
- subject.delete(42)
-
- Gitlab::Redis::SharedState.with do |redis|
- expect(redis.hscan(described_class::KEY, 0)).to eq(['0', []])
- end
- end
- end
-
- context 'and key does not exist' do
- it 'removes the pair from SharedState' do
- Gitlab::Redis::SharedState.with do |redis|
- expect(redis.hscan(described_class::KEY, 0)).to eq(['0', []])
- end
-
- subject.delete(42)
-
- Gitlab::Redis::SharedState.with do |redis|
- expect(redis.hscan(described_class::KEY, 0)).to eq(['0', []])
- end
- end
- end
- end
-
- context 'with multiple keys' do
- context 'and all keys exist' do
- it 'removes the pair from SharedState' do
- described_class.record(41, now)
- described_class.record(42, now)
-
- Gitlab::Redis::SharedState.with do |redis|
- expect(redis.hscan(described_class::KEY, 0)).to eq(['0', [['41', now.to_i.to_s], ['42', now.to_i.to_s]]])
- end
-
- subject.delete(41, 42)
-
- Gitlab::Redis::SharedState.with do |redis|
- expect(redis.hscan(described_class::KEY, 0)).to eq(['0', []])
- end
- end
- end
-
- context 'and some keys does not exist' do
- it 'removes the existing pair from SharedState' do
- described_class.record(42, now)
-
- Gitlab::Redis::SharedState.with do |redis|
- expect(redis.hscan(described_class::KEY, 0)).to eq(['0', [['42', now.to_i.to_s]]])
- end
-
- subject.delete(41, 42)
-
- Gitlab::Redis::SharedState.with do |redis|
- expect(redis.hscan(described_class::KEY, 0)).to eq(['0', []])
- end
- end
- end
- end
- end
-
- describe 'Enumerable' do
- before do
- described_class.record(40, now)
- described_class.record(41, now)
- described_class.record(42, now)
- end
-
- it 'allows to read the activities sequentially' do
- expected = { '40' => now.to_i.to_s, '41' => now.to_i.to_s, '42' => now.to_i.to_s }
-
- actual = described_class.new.each_with_object({}) do |(key, time), actual|
- actual[key] = time
- end
-
- expect(actual).to eq(expected)
- end
-
- context 'with many records' do
- before do
- 1_000.times { |i| described_class.record(i, now) }
- end
-
- it 'is possible to loop through all the records' do
- expect(described_class.new.count).to eq(1_000)
- end
- end
- end
-end
diff --git a/spec/migrations/active_record/schedule_set_confidential_note_events_on_services_spec.rb b/spec/migrations/active_record/schedule_set_confidential_note_events_on_services_spec.rb
index 4395e2f8264..5c6f213e15b 100644
--- a/spec/migrations/active_record/schedule_set_confidential_note_events_on_services_spec.rb
+++ b/spec/migrations/active_record/schedule_set_confidential_note_events_on_services_spec.rb
@@ -31,7 +31,7 @@ describe ScheduleSetConfidentialNoteEventsOnServices, :migration, :sidekiq do
end
it 'correctly processes services' do
- Sidekiq::Testing.inline! do
+ perform_enqueued_jobs do
expect(services_table.where(confidential_note_events: nil).count).to eq 4
expect(services_table.where(confidential_note_events: true).count).to eq 1
diff --git a/spec/migrations/migrate_process_commit_worker_jobs_spec.rb b/spec/migrations/migrate_process_commit_worker_jobs_spec.rb
index a30e6c23ac9..6219a67c900 100644
--- a/spec/migrations/migrate_process_commit_worker_jobs_spec.rb
+++ b/spec/migrations/migrate_process_commit_worker_jobs_spec.rb
@@ -4,14 +4,11 @@ require 'spec_helper'
require Rails.root.join('db', 'migrate', '20161124141322_migrate_process_commit_worker_jobs.rb')
describe MigrateProcessCommitWorkerJobs do
- let(:project) { create(:project, :legacy_storage, :repository) } # rubocop:disable RSpec/FactoriesInMigrationSpecs
- let(:user) { create(:user) } # rubocop:disable RSpec/FactoriesInMigrationSpecs
- let(:rugged) do
- Gitlab::GitalyClient::StorageSettings.allow_disk_access do
- project.repository.rugged
- end
+ set(:project) { create(:project, :legacy_storage, :repository) } # rubocop:disable RSpec/FactoriesInMigrationSpecs
+ set(:user) { create(:user) } # rubocop:disable RSpec/FactoriesInMigrationSpecs
+ let(:commit) do
+ Gitlab::Git::Commit.last(project.repository.raw)
end
- let(:commit) { rugged.rev_parse(project.commit.id) }
describe 'Project' do
describe 'find_including_path' do
@@ -29,32 +26,13 @@ describe MigrateProcessCommitWorkerJobs do
end
end
- describe '#repository_storage_path' do
- it 'returns the storage path for the repository' do
- migration_project = described_class::Project
- .find_including_path(project.id)
-
- expect(File.directory?(migration_project.repository_storage_path))
- .to eq(true)
- end
- end
-
- describe '#repository_path' do
- it 'returns the path to the repository' do
- migration_project = described_class::Project
- .find_including_path(project.id)
-
- expect(File.directory?(migration_project.repository_path)).to eq(true)
- end
- end
-
describe '#repository' do
- it 'returns a Rugged::Repository' do
+ it 'returns a mock implemention of ::Repository' do
migration_project = described_class::Project
.find_including_path(project.id)
- expect(migration_project.repository)
- .to be_an_instance_of(Rugged::Repository)
+ expect(migration_project.repository).to respond_to(:storage)
+ expect(migration_project.repository).to respond_to(:gitaly_repository)
end
end
end
@@ -72,7 +50,7 @@ describe MigrateProcessCommitWorkerJobs do
before do
Sidekiq.redis do |redis|
- job = JSON.dump(args: [project.id, user.id, commit.oid])
+ job = JSON.dump(args: [project.id, user.id, commit.id])
redis.lpush('queue:process_commit', job)
end
end
@@ -88,9 +66,10 @@ describe MigrateProcessCommitWorkerJobs do
end
it 'skips jobs using commits that no longer exist' do
- allow_any_instance_of(Rugged::Repository).to receive(:lookup)
- .with(commit.oid)
- .and_raise(Rugged::OdbError)
+ allow_any_instance_of(Gitlab::GitalyClient::CommitService)
+ .to receive(:find_commit)
+ .with(commit.id)
+ .and_return(nil)
migration.up
@@ -104,11 +83,7 @@ describe MigrateProcessCommitWorkerJobs do
end
it 'encodes data to UTF-8' do
- allow_any_instance_of(Rugged::Repository).to receive(:lookup)
- .with(commit.oid)
- .and_return(commit)
-
- allow(commit).to receive(:message)
+ allow(commit).to receive(:body)
.and_return('김치'.force_encoding('BINARY'))
migration.up
@@ -140,7 +115,7 @@ describe MigrateProcessCommitWorkerJobs do
end
it 'includes the commit ID' do
- expect(commit_hash['id']).to eq(commit.oid)
+ expect(commit_hash['id']).to eq(commit.id)
end
it 'includes the commit message' do
@@ -152,27 +127,27 @@ describe MigrateProcessCommitWorkerJobs do
end
it 'includes the author date' do
- expect(commit_hash['authored_date']).to eq(commit.author[:time].to_s)
+ expect(commit_hash['authored_date']).to eq(commit.authored_date.to_s)
end
it 'includes the author name' do
- expect(commit_hash['author_name']).to eq(commit.author[:name])
+ expect(commit_hash['author_name']).to eq(commit.author_name)
end
it 'includes the author Email' do
- expect(commit_hash['author_email']).to eq(commit.author[:email])
+ expect(commit_hash['author_email']).to eq(commit.author_email)
end
it 'includes the commit date' do
- expect(commit_hash['committed_date']).to eq(commit.committer[:time].to_s)
+ expect(commit_hash['committed_date']).to eq(commit.committed_date.to_s)
end
it 'includes the committer name' do
- expect(commit_hash['committer_name']).to eq(commit.committer[:name])
+ expect(commit_hash['committer_name']).to eq(commit.committer_name)
end
it 'includes the committer Email' do
- expect(commit_hash['committer_email']).to eq(commit.committer[:email])
+ expect(commit_hash['committer_email']).to eq(commit.committer_email)
end
end
end
@@ -186,7 +161,7 @@ describe MigrateProcessCommitWorkerJobs do
before do
Sidekiq.redis do |redis|
- job = JSON.dump(args: [project.id, user.id, commit.oid])
+ job = JSON.dump(args: [project.id, user.id, commit.id])
redis.lpush('queue:process_commit', job)
migration.up
@@ -215,7 +190,7 @@ describe MigrateProcessCommitWorkerJobs do
end
it 'includes the commit SHA' do
- expect(job['args'][2]).to eq(commit.oid)
+ expect(job['args'][2]).to eq(commit.id)
end
end
end
diff --git a/spec/migrations/migrate_stage_id_reference_in_background_spec.rb b/spec/migrations/migrate_stage_id_reference_in_background_spec.rb
index a837498e1b1..dd6f5325750 100644
--- a/spec/migrations/migrate_stage_id_reference_in_background_spec.rb
+++ b/spec/migrations/migrate_stage_id_reference_in_background_spec.rb
@@ -44,7 +44,7 @@ describe MigrateStageIdReferenceInBackground, :migration, :sidekiq do
end
it 'schedules background migrations' do
- Sidekiq::Testing.inline! do
+ perform_enqueued_jobs do
expect(jobs.where(stage_id: nil).count).to eq 5
migrate!
diff --git a/spec/migrations/migrate_stages_statuses_spec.rb b/spec/migrations/migrate_stages_statuses_spec.rb
index ce35276cbf5..5483e24fce7 100644
--- a/spec/migrations/migrate_stages_statuses_spec.rb
+++ b/spec/migrations/migrate_stages_statuses_spec.rb
@@ -34,7 +34,7 @@ describe MigrateStagesStatuses, :sidekiq, :migration do
end
it 'correctly migrates stages statuses' do
- Sidekiq::Testing.inline! do
+ perform_enqueued_jobs do
expect(stages.where(status: nil).count).to eq 3
migrate!
diff --git a/spec/migrations/normalize_ldap_extern_uids_spec.rb b/spec/migrations/normalize_ldap_extern_uids_spec.rb
index 56a78f52802..c6ea1e3e49e 100644
--- a/spec/migrations/normalize_ldap_extern_uids_spec.rb
+++ b/spec/migrations/normalize_ldap_extern_uids_spec.rb
@@ -38,7 +38,7 @@ describe NormalizeLdapExternUids, :migration, :sidekiq do
end
it 'migrates the LDAP identities' do
- Sidekiq::Testing.inline! do
+ perform_enqueued_jobs do
migrate!
identities.where(id: 1..4).each do |identity|
expect(identity.extern_uid).to eq("uid=foo #{identity.id},ou=people,dc=example,dc=com")
@@ -47,7 +47,7 @@ describe NormalizeLdapExternUids, :migration, :sidekiq do
end
it 'does not modify non-LDAP identities' do
- Sidekiq::Testing.inline! do
+ perform_enqueued_jobs do
migrate!
identity = identities.last
expect(identity.extern_uid).to eq(" uid = foo 5, ou = People, dc = example, dc = com ")
diff --git a/spec/migrations/schedule_create_gpg_key_subkeys_from_gpg_keys_spec.rb b/spec/migrations/schedule_create_gpg_key_subkeys_from_gpg_keys_spec.rb
index ed306fb3d62..96bef107599 100644
--- a/spec/migrations/schedule_create_gpg_key_subkeys_from_gpg_keys_spec.rb
+++ b/spec/migrations/schedule_create_gpg_key_subkeys_from_gpg_keys_spec.rb
@@ -20,7 +20,7 @@ describe ScheduleCreateGpgKeySubkeysFromGpgKeys, :migration, :sidekiq do
end
it 'schedules background migrations' do
- Sidekiq::Testing.inline! do
+ perform_enqueued_jobs do
expect(GpgKeySubkey.count).to eq(0)
migrate!
diff --git a/spec/migrations/schedule_merge_request_diff_migrations_spec.rb b/spec/migrations/schedule_merge_request_diff_migrations_spec.rb
index d230f064444..9f7e47bae0d 100644
--- a/spec/migrations/schedule_merge_request_diff_migrations_spec.rb
+++ b/spec/migrations/schedule_merge_request_diff_migrations_spec.rb
@@ -33,7 +33,7 @@ describe ScheduleMergeRequestDiffMigrations, :migration, :sidekiq do
end
it 'schedules background migrations' do
- Sidekiq::Testing.inline! do
+ perform_enqueued_jobs do
non_empty = 'st_commits IS NOT NULL OR st_diffs IS NOT NULL'
expect(merge_request_diffs.where(non_empty).count).to eq 3
diff --git a/spec/migrations/schedule_merge_request_diff_migrations_take_two_spec.rb b/spec/migrations/schedule_merge_request_diff_migrations_take_two_spec.rb
index 1aab4ae1650..5bcb923af7b 100644
--- a/spec/migrations/schedule_merge_request_diff_migrations_take_two_spec.rb
+++ b/spec/migrations/schedule_merge_request_diff_migrations_take_two_spec.rb
@@ -33,7 +33,7 @@ describe ScheduleMergeRequestDiffMigrationsTakeTwo, :migration, :sidekiq do
end
it 'migrates the data' do
- Sidekiq::Testing.inline! do
+ perform_enqueued_jobs do
non_empty = 'st_commits IS NOT NULL OR st_diffs IS NOT NULL'
expect(merge_request_diffs.where(non_empty).count).to eq 3
diff --git a/spec/migrations/schedule_merge_request_latest_merge_request_diff_id_migrations_spec.rb b/spec/migrations/schedule_merge_request_latest_merge_request_diff_id_migrations_spec.rb
index c9fdbe95d13..76fe16581ac 100644
--- a/spec/migrations/schedule_merge_request_latest_merge_request_diff_id_migrations_spec.rb
+++ b/spec/migrations/schedule_merge_request_latest_merge_request_diff_id_migrations_spec.rb
@@ -53,7 +53,7 @@ describe ScheduleMergeRequestLatestMergeRequestDiffIdMigrations, :migration, :si
end
it 'schedules background migrations' do
- Sidekiq::Testing.inline! do
+ perform_enqueued_jobs do
expect(merge_requests_table.where(latest_merge_request_diff_id: nil).count).to eq 3
migrate!
diff --git a/spec/migrations/schedule_set_confidential_note_events_on_webhooks_spec.rb b/spec/migrations/schedule_set_confidential_note_events_on_webhooks_spec.rb
index 027f4a91c90..fa4ddd5fbc7 100644
--- a/spec/migrations/schedule_set_confidential_note_events_on_webhooks_spec.rb
+++ b/spec/migrations/schedule_set_confidential_note_events_on_webhooks_spec.rb
@@ -31,7 +31,7 @@ describe ScheduleSetConfidentialNoteEventsOnWebhooks, :migration, :sidekiq do
end
it 'correctly processes web hooks' do
- Sidekiq::Testing.inline! do
+ perform_enqueued_jobs do
expect(web_hooks_table.where(confidential_note_events: nil).count).to eq 4
expect(web_hooks_table.where(confidential_note_events: true).count).to eq 1
diff --git a/spec/models/ci/build_spec.rb b/spec/models/ci/build_spec.rb
index ee923374480..67199eb6d26 100644
--- a/spec/models/ci/build_spec.rb
+++ b/spec/models/ci/build_spec.rb
@@ -2269,6 +2269,34 @@ describe Ci::Build do
end
end
+ describe '#yaml_variables' do
+ before do
+ build.update_attribute(:yaml_variables, variables)
+ end
+
+ context 'when serialized valu is a symbolized hash' do
+ let(:variables) do
+ [{ key: :VARIABLE, value: 'my value 1' }]
+ end
+
+ it 'keeps symbolizes keys and stringifies variables names' do
+ expect(build.yaml_variables)
+ .to eq [{ key: 'VARIABLE', value: 'my value 1' }]
+ end
+ end
+
+ context 'when serialized value is a hash with string keys' do
+ let(:variables) do
+ [{ 'key' => :VARIABLE, 'value' => 'my value 2' }]
+ end
+
+ it 'symblizes variables hash' do
+ expect(build.yaml_variables)
+ .to eq [{ key: 'VARIABLE', value: 'my value 2' }]
+ end
+ end
+ end
+
describe 'state transition: any => [:pending]' do
let(:build) { create(:ci_build, :created) }
diff --git a/spec/models/ci/build_trace_chunk_spec.rb b/spec/models/ci/build_trace_chunk_spec.rb
index 774a638b430..915bf134d57 100644
--- a/spec/models/ci/build_trace_chunk_spec.rb
+++ b/spec/models/ci/build_trace_chunk_spec.rb
@@ -179,7 +179,7 @@ describe Ci::BuildTraceChunk, :clean_gitlab_redis_shared_state do
end
it 'migrates data to object storage' do
- Sidekiq::Testing.inline! do
+ perform_enqueued_jobs do
subject
build_trace_chunk.reload
@@ -201,7 +201,7 @@ describe Ci::BuildTraceChunk, :clean_gitlab_redis_shared_state do
end
it 'does not migrate data to object storage' do
- Sidekiq::Testing.inline! do
+ perform_enqueued_jobs do
data_store = build_trace_chunk.data_store
subject
diff --git a/spec/models/deploy_token_spec.rb b/spec/models/deploy_token_spec.rb
index f8d51a95833..cd84a684fec 100644
--- a/spec/models/deploy_token_spec.rb
+++ b/spec/models/deploy_token_spec.rb
@@ -62,11 +62,18 @@ describe DeployToken do
end
end
- context "when it hasn't been revoked" do
+ context "when it hasn't been revoked and is not expired" do
it 'should return true' do
expect(deploy_token.active?).to be_truthy
end
end
+
+ context "when it hasn't been revoked and is expired" do
+ it 'should return true' do
+ deploy_token.update_attribute(:expires_at, Date.today - 5.days)
+ expect(deploy_token.active?).to be_falsy
+ end
+ end
end
describe '#username' do
diff --git a/spec/models/project_services/hangouts_chat_service_spec.rb b/spec/models/project_services/hangouts_chat_service_spec.rb
new file mode 100644
index 00000000000..cfa55188a64
--- /dev/null
+++ b/spec/models/project_services/hangouts_chat_service_spec.rb
@@ -0,0 +1,246 @@
+require 'spec_helper'
+
+describe HangoutsChatService do
+ describe 'Associations' do
+ it { is_expected.to belong_to :project }
+ it { is_expected.to have_one :service_hook }
+ end
+
+ describe 'Validations' do
+ context 'when service is active' do
+ before do
+ subject.active = true
+ end
+
+ it { is_expected.to validate_presence_of(:webhook) }
+ it_behaves_like 'issue tracker service URL attribute', :webhook
+ end
+
+ context 'when service is inactive' do
+ before do
+ subject.active = false
+ end
+
+ it { is_expected.not_to validate_presence_of(:webhook) }
+ end
+ end
+
+ describe '#execute' do
+ let(:user) { create(:user) }
+ let(:project) { create(:project, :repository) }
+ let(:webhook_url) { 'https://example.gitlab.com/' }
+
+ before do
+ allow(subject).to receive_messages(
+ project: project,
+ project_id: project.id,
+ service_hook: true,
+ webhook: webhook_url
+ )
+
+ WebMock.stub_request(:post, webhook_url)
+ end
+
+ shared_examples 'Hangouts Chat service' do
+ it 'calls Hangouts Chat API' do
+ subject.execute(sample_data)
+
+ expect(WebMock)
+ .to have_requested(:post, webhook_url)
+ .with { |req| req.body =~ /\A{"text":.+}\Z/ }
+ .once
+ end
+ end
+
+ context 'with push events' do
+ let(:sample_data) do
+ Gitlab::DataBuilder::Push.build_sample(project, user)
+ end
+
+ it_behaves_like 'Hangouts Chat service'
+
+ it 'specifies the webhook when it is configured' do
+ expect(HangoutsChat::Sender).to receive(:new).with(webhook_url).and_return(double(:hangouts_chat_service).as_null_object)
+
+ subject.execute(sample_data)
+ end
+
+ context 'with not default branch' do
+ let(:sample_data) do
+ Gitlab::DataBuilder::Push.build(project, user, nil, nil, 'not-the-default-branch')
+ end
+
+ context 'when notify_only_default_branch enabled' do
+ before do
+ subject.notify_only_default_branch = true
+ end
+
+ it 'does not call the Hangouts Chat API' do
+ result = subject.execute(sample_data)
+
+ expect(result).to be_falsy
+ end
+ end
+
+ context 'when notify_only_default_branch disabled' do
+ before do
+ subject.notify_only_default_branch = false
+ end
+
+ it_behaves_like 'Hangouts Chat service'
+ end
+ end
+ end
+
+ context 'with issue events' do
+ let(:opts) { { title: 'Awesome issue', description: 'please fix' } }
+ let(:sample_data) do
+ service = Issues::CreateService.new(project, user, opts)
+ issue = service.execute
+ service.hook_data(issue, 'open')
+ end
+
+ it_behaves_like 'Hangouts Chat service'
+ end
+
+ context 'with merge events' do
+ let(:opts) do
+ {
+ title: 'Awesome merge_request',
+ description: 'please fix',
+ source_branch: 'feature',
+ target_branch: 'master'
+ }
+ end
+
+ let(:sample_data) do
+ service = MergeRequests::CreateService.new(project, user, opts)
+ merge_request = service.execute
+ service.hook_data(merge_request, 'open')
+ end
+
+ before do
+ project.add_developer(user)
+ end
+
+ it_behaves_like 'Hangouts Chat service'
+ end
+
+ context 'with wiki page events' do
+ let(:opts) do
+ {
+ title: 'Awesome wiki_page',
+ content: 'Some text describing some thing or another',
+ format: 'md',
+ message: 'user created page: Awesome wiki_page'
+ }
+ end
+ let(:wiki_page) { create(:wiki_page, wiki: project.wiki, attrs: opts) }
+ let(:sample_data) { Gitlab::DataBuilder::WikiPage.build(wiki_page, user, 'create') }
+
+ it_behaves_like 'Hangouts Chat service'
+ end
+
+ context 'with note events' do
+ let(:sample_data) { Gitlab::DataBuilder::Note.build(note, user) }
+
+ context 'with commit comment' do
+ let(:note) do
+ create(:note_on_commit, author: user,
+ project: project,
+ commit_id: project.repository.commit.id,
+ note: 'a comment on a commit')
+ end
+
+ it_behaves_like 'Hangouts Chat service'
+ end
+
+ context 'with merge request comment' do
+ let(:note) do
+ create(:note_on_merge_request, project: project,
+ note: 'merge request note')
+ end
+
+ it_behaves_like 'Hangouts Chat service'
+ end
+
+ context 'with issue comment' do
+ let(:note) do
+ create(:note_on_issue, project: project, note: 'issue note')
+ end
+
+ it_behaves_like 'Hangouts Chat service'
+ end
+
+ context 'with snippet comment' do
+ let(:note) do
+ create(:note_on_project_snippet, project: project,
+ note: 'snippet note')
+ end
+
+ it_behaves_like 'Hangouts Chat service'
+ end
+ end
+
+ context 'with pipeline events' do
+ let(:pipeline) do
+ create(:ci_pipeline,
+ project: project, status: status,
+ sha: project.commit.sha, ref: project.default_branch)
+ end
+ let(:sample_data) { Gitlab::DataBuilder::Pipeline.build(pipeline) }
+
+ context 'with failed pipeline' do
+ let(:status) { 'failed' }
+
+ it_behaves_like 'Hangouts Chat service'
+ end
+
+ context 'with succeeded pipeline' do
+ let(:status) { 'success' }
+
+ context 'with default notify_only_broken_pipelines' do
+ it 'does not call Hangouts Chat API' do
+ result = subject.execute(sample_data)
+
+ expect(result).to be_falsy
+ end
+ end
+
+ context 'when notify_only_broken_pipelines is false' do
+ before do
+ subject.notify_only_broken_pipelines = false
+ end
+
+ it_behaves_like 'Hangouts Chat service'
+ end
+ end
+
+ context 'with not default branch' do
+ let(:pipeline) do
+ create(:ci_pipeline, project: project, status: 'failed', ref: 'not-the-default-branch')
+ end
+
+ context 'when notify_only_default_branch enabled' do
+ before do
+ subject.notify_only_default_branch = true
+ end
+
+ it 'does not call the Hangouts Chat API' do
+ result = subject.execute(sample_data)
+
+ expect(result).to be_falsy
+ end
+ end
+
+ context 'when notify_only_default_branch disabled' do
+ before do
+ subject.notify_only_default_branch = false
+ end
+
+ it_behaves_like 'Hangouts Chat service'
+ end
+ end
+ end
+ end
+end
diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb
index d200e5f2e42..b0ec725bf70 100644
--- a/spec/models/project_spec.rb
+++ b/spec/models/project_spec.rb
@@ -26,6 +26,7 @@ describe Project do
it { is_expected.to have_one(:slack_service) }
it { is_expected.to have_one(:microsoft_teams_service) }
it { is_expected.to have_one(:mattermost_service) }
+ it { is_expected.to have_one(:hangouts_chat_service) }
it { is_expected.to have_one(:packagist_service) }
it { is_expected.to have_one(:pushover_service) }
it { is_expected.to have_one(:asana_service) }
diff --git a/spec/models/repository_spec.rb b/spec/models/repository_spec.rb
index e65214808e1..5d64602ca56 100644
--- a/spec/models/repository_spec.rb
+++ b/spec/models/repository_spec.rb
@@ -2225,20 +2225,6 @@ describe Repository do
end
end
- describe '#remote_branches' do
- it 'returns the remote branches' do
- masterrev = repository.find_branch('master').dereferenced_target
- create_remote_branch('joe', 'remote_branch', masterrev)
- repository.add_branch(user, 'local_branch', masterrev.id)
-
- # TODO: move this test to gitaly https://gitlab.com/gitlab-org/gitaly/issues/1243
- Gitlab::GitalyClient::StorageSettings.allow_disk_access do
- expect(repository.remote_branches('joe').any? { |branch| branch.name == 'local_branch' }).to eq(false)
- expect(repository.remote_branches('joe').any? { |branch| branch.name == 'remote_branch' }).to eq(true)
- end
- end
- end
-
describe '#commit_count' do
context 'with a non-existing repository' do
it 'returns 0' do
diff --git a/spec/models/spam_log_spec.rb b/spec/models/spam_log_spec.rb
index 0d6b4384ada..90a2caaeb88 100644
--- a/spec/models/spam_log_spec.rb
+++ b/spec/models/spam_log_spec.rb
@@ -22,7 +22,7 @@ describe SpamLog do
spam_log = build(:spam_log)
user = spam_log.user
- Sidekiq::Testing.inline! do
+ perform_enqueued_jobs do
spam_log.remove_user(deleted_by: admin)
end
diff --git a/spec/requests/api/environments_spec.rb b/spec/requests/api/environments_spec.rb
index bf93555b0f0..f3db0c122a0 100644
--- a/spec/requests/api/environments_spec.rb
+++ b/spec/requests/api/environments_spec.rb
@@ -20,7 +20,7 @@ describe API::Environments do
path path_with_namespace
star_count forks_count
created_at last_activity_at
- avatar_url
+ avatar_url namespace
)
get api("/projects/#{project.id}/environments", user)
diff --git a/spec/requests/api/groups_spec.rb b/spec/requests/api/groups_spec.rb
index 65b387a2170..3a8948f8477 100644
--- a/spec/requests/api/groups_spec.rb
+++ b/spec/requests/api/groups_spec.rb
@@ -226,6 +226,25 @@ describe API::Groups do
expect(json_response.first['name']).to eq(group2.name)
end
end
+
+ context 'when using min_access_level in the request' do
+ let!(:group3) { create(:group, :private) }
+ let(:response_groups) { json_response.map { |group| group['id'] } }
+
+ before do
+ group1.add_developer(user2)
+ group3.add_master(user2)
+ end
+
+ it 'returns an array of groups the user has at least master access' do
+ get api('/groups', user2), min_access_level: 40
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(response).to include_pagination_headers
+ expect(json_response).to be_an Array
+ expect(response_groups).to eq([group2.id, group3.id])
+ end
+ end
end
describe "GET /groups/:id" do
diff --git a/spec/requests/api/internal_spec.rb b/spec/requests/api/internal_spec.rb
index a56b913198c..a2cfa706f58 100644
--- a/spec/requests/api/internal_spec.rb
+++ b/spec/requests/api/internal_spec.rb
@@ -279,7 +279,7 @@ describe API::Internal do
expect(json_response["status"]).to be_truthy
expect(json_response["repository_path"]).to eq('/')
expect(json_response["gl_repository"]).to eq("wiki-#{project.id}")
- expect(user).not_to have_an_activity_record
+ expect(user.reload.last_activity_on).to be_nil
end
end
@@ -291,7 +291,7 @@ describe API::Internal do
expect(json_response["status"]).to be_truthy
expect(json_response["repository_path"]).to eq('/')
expect(json_response["gl_repository"]).to eq("wiki-#{project.id}")
- expect(user).to have_an_activity_record
+ expect(user.reload.last_activity_on).to eql(Date.today)
end
end
@@ -309,7 +309,7 @@ describe API::Internal do
expect(json_response["gitaly"]["repository"]["relative_path"]).to eq(project.repository.gitaly_repository.relative_path)
expect(json_response["gitaly"]["address"]).to eq(Gitlab::GitalyClient.address(project.repository_storage))
expect(json_response["gitaly"]["token"]).to eq(Gitlab::GitalyClient.token(project.repository_storage))
- expect(user).to have_an_activity_record
+ expect(user.reload.last_activity_on).to eql(Date.today)
end
end
@@ -328,7 +328,7 @@ describe API::Internal do
expect(json_response["gitaly"]["repository"]["relative_path"]).to eq(project.repository.gitaly_repository.relative_path)
expect(json_response["gitaly"]["address"]).to eq(Gitlab::GitalyClient.address(project.repository_storage))
expect(json_response["gitaly"]["token"]).to eq(Gitlab::GitalyClient.token(project.repository_storage))
- expect(user).not_to have_an_activity_record
+ expect(user.reload.last_activity_on).to be_nil
end
end
end
@@ -345,7 +345,7 @@ describe API::Internal do
expect(response).to have_gitlab_http_status(200)
expect(json_response["status"]).to be_falsey
- expect(user).not_to have_an_activity_record
+ expect(user.reload.last_activity_on).to be_nil
end
end
@@ -355,7 +355,7 @@ describe API::Internal do
expect(response).to have_gitlab_http_status(200)
expect(json_response["status"]).to be_falsey
- expect(user).not_to have_an_activity_record
+ expect(user.reload.last_activity_on).to be_nil
end
end
end
@@ -373,7 +373,7 @@ describe API::Internal do
expect(response).to have_gitlab_http_status(200)
expect(json_response["status"]).to be_falsey
- expect(user).not_to have_an_activity_record
+ expect(user.reload.last_activity_on).to be_nil
end
end
@@ -383,7 +383,7 @@ describe API::Internal do
expect(response).to have_gitlab_http_status(200)
expect(json_response["status"]).to be_falsey
- expect(user).not_to have_an_activity_record
+ expect(user.reload.last_activity_on).to be_nil
end
end
end
diff --git a/spec/requests/api/jobs_spec.rb b/spec/requests/api/jobs_spec.rb
index 7d1a5c12805..8412d0383f7 100644
--- a/spec/requests/api/jobs_spec.rb
+++ b/spec/requests/api/jobs_spec.rb
@@ -220,6 +220,7 @@ describe API::Jobs do
expect(Time.parse(json_response['finished_at'])).to be_like_time(job.finished_at)
expect(Time.parse(json_response['artifacts_expire_at'])).to be_like_time(job.artifacts_expire_at)
expect(json_response['duration']).to eq(job.duration)
+ expect(json_response['web_url']).to be_present
end
it 'returns pipeline data' do
diff --git a/spec/requests/api/pipelines_spec.rb b/spec/requests/api/pipelines_spec.rb
index e2ca27f5d41..342a97b6a69 100644
--- a/spec/requests/api/pipelines_spec.rb
+++ b/spec/requests/api/pipelines_spec.rb
@@ -24,7 +24,8 @@ describe API::Pipelines do
expect(json_response).to be_an Array
expect(json_response.first['sha']).to match /\A\h{40}\z/
expect(json_response.first['id']).to eq pipeline.id
- expect(json_response.first.keys).to contain_exactly(*%w[id sha ref status])
+ expect(json_response.first['web_url']).to be_present
+ expect(json_response.first.keys).to contain_exactly(*%w[id sha ref status web_url])
end
context 'when parameter is passed' do
diff --git a/spec/requests/api/project_import_spec.rb b/spec/requests/api/project_import_spec.rb
index 41243854ebc..55332f56508 100644
--- a/spec/requests/api/project_import_spec.rb
+++ b/spec/requests/api/project_import_spec.rb
@@ -102,7 +102,7 @@ describe API::ProjectImport do
it 'correctly overrides params during the import' do
override_params = { 'description' => 'Hello world' }
- Sidekiq::Testing.inline! do
+ perform_enqueued_jobs do
post api('/projects/import', user),
path: 'test-import',
file: fixture_file_upload(file),
diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb
index f72c01561d8..71e3436fa76 100644
--- a/spec/requests/api/projects_spec.rb
+++ b/spec/requests/api/projects_spec.rb
@@ -225,7 +225,7 @@ describe API::Projects do
path path_with_namespace
star_count forks_count
created_at last_activity_at
- avatar_url
+ avatar_url namespace
)
get api('/projects?simple=true', user)
@@ -400,6 +400,22 @@ describe API::Projects do
end
end
end
+
+ context 'and with min_access_level' do
+ before do
+ project2.add_master(user2)
+ project3.add_developer(user2)
+ project4.add_reporter(user2)
+ end
+
+ it 'returns an array of groups the user has at least developer access' do
+ get api('/projects', user2), { min_access_level: 30 }
+ expect(response).to have_gitlab_http_status(200)
+ expect(response).to include_pagination_headers
+ expect(json_response).to be_an Array
+ expect(json_response.map { |project| project['id'] }).to contain_exactly(project2.id, project3.id)
+ end
+ end
end
context 'when authenticated as a different user' do
@@ -681,6 +697,20 @@ describe API::Projects do
expect(json_response).to be_an Array
expect(json_response.map { |project| project['id'] }).to contain_exactly(public_project.id)
end
+
+ it 'returns projects filetered by minimal access level' do
+ private_project1 = create(:project, :private, name: 'private_project1', creator_id: user4.id, namespace: user4.namespace)
+ private_project2 = create(:project, :private, name: 'private_project2', creator_id: user4.id, namespace: user4.namespace)
+ private_project1.add_developer(user2)
+ private_project2.add_reporter(user2)
+
+ get api("/users/#{user4.id}/projects/", user2), { min_access_level: 30 }
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(response).to include_pagination_headers
+ expect(json_response).to be_an Array
+ expect(json_response.map { |project| project['id'] }).to contain_exactly(private_project1.id)
+ end
end
describe 'POST /projects/user/:id' do
diff --git a/spec/requests/api/users_spec.rb b/spec/requests/api/users_spec.rb
index a97c3f3461a..b3079c0a77b 100644
--- a/spec/requests/api/users_spec.rb
+++ b/spec/requests/api/users_spec.rb
@@ -1067,7 +1067,7 @@ describe API::Users do
end
it "deletes user" do
- Sidekiq::Testing.inline! { delete api("/users/#{user.id}", admin) }
+ perform_enqueued_jobs { delete api("/users/#{user.id}", admin) }
expect(response).to have_gitlab_http_status(204)
expect { User.find(user.id) }.to raise_error ActiveRecord::RecordNotFound
@@ -1079,30 +1079,30 @@ describe API::Users do
end
it "does not delete for unauthenticated user" do
- Sidekiq::Testing.inline! { delete api("/users/#{user.id}") }
+ perform_enqueued_jobs { delete api("/users/#{user.id}") }
expect(response).to have_gitlab_http_status(401)
end
it "is not available for non admin users" do
- Sidekiq::Testing.inline! { delete api("/users/#{user.id}", user) }
+ perform_enqueued_jobs { delete api("/users/#{user.id}", user) }
expect(response).to have_gitlab_http_status(403)
end
it "returns 404 for non-existing user" do
- Sidekiq::Testing.inline! { delete api("/users/999999", admin) }
+ perform_enqueued_jobs { delete api("/users/999999", admin) }
expect(response).to have_gitlab_http_status(404)
expect(json_response['message']).to eq('404 User Not Found')
end
it "returns a 404 for invalid ID" do
- Sidekiq::Testing.inline! { delete api("/users/ASDF", admin) }
+ perform_enqueued_jobs { delete api("/users/ASDF", admin) }
expect(response).to have_gitlab_http_status(404)
end
context "hard delete disabled" do
it "moves contributions to the ghost user" do
- Sidekiq::Testing.inline! { delete api("/users/#{user.id}", admin) }
+ perform_enqueued_jobs { delete api("/users/#{user.id}", admin) }
expect(response).to have_gitlab_http_status(204)
expect(issue.reload).to be_persisted
@@ -1112,7 +1112,7 @@ describe API::Users do
context "hard delete enabled" do
it "removes contributions" do
- Sidekiq::Testing.inline! { delete api("/users/#{user.id}?hard_delete=true", admin) }
+ perform_enqueued_jobs { delete api("/users/#{user.id}?hard_delete=true", admin) }
expect(response).to have_gitlab_http_status(204)
expect(Issue.exists?(issue.id)).to be_falsy
diff --git a/spec/requests/git_http_spec.rb b/spec/requests/git_http_spec.rb
index b030d9862c6..0f3e7157e14 100644
--- a/spec/requests/git_http_spec.rb
+++ b/spec/requests/git_http_spec.rb
@@ -5,7 +5,6 @@ describe 'Git HTTP requests' do
include TermsHelper
include GitHttpHelpers
include WorkhorseHelpers
- include UserActivitiesHelpers
shared_examples 'pulls require Basic HTTP Authentication' do
context "when no credentials are provided" do
@@ -440,10 +439,10 @@ describe 'Git HTTP requests' do
end
it 'updates the user last activity', :clean_gitlab_redis_shared_state do
- expect(user_activity(user)).to be_nil
+ expect(user.last_activity_on).to be_nil
download(path, env) do |response|
- expect(user_activity(user)).to be_present
+ expect(user.reload.last_activity_on).to eql(Date.today)
end
end
end
diff --git a/spec/requests/lfs_http_spec.rb b/spec/requests/lfs_http_spec.rb
index de39abdb746..c2378646f89 100644
--- a/spec/requests/lfs_http_spec.rb
+++ b/spec/requests/lfs_http_spec.rb
@@ -575,6 +575,40 @@ describe 'Git LFS API and storage' do
end
end
+ context 'when using Deploy Tokens' do
+ let(:project) { create(:project, :repository) }
+ let(:authorization) { authorize_deploy_token }
+ let(:update_user_permissions) { nil }
+ let(:role) { nil }
+ let(:update_lfs_permissions) do
+ project.lfs_objects << lfs_object
+ end
+
+ context 'when Deploy Token is valid' do
+ let(:deploy_token) { create(:deploy_token, projects: [project]) }
+
+ it_behaves_like 'an authorized requests'
+ end
+
+ context 'when Deploy Token is not valid' do
+ let(:deploy_token) { create(:deploy_token, projects: [project], read_repository: false) }
+
+ it 'responds with access denied' do
+ expect(response).to have_gitlab_http_status(401)
+ end
+ end
+
+ context 'when Deploy Token is not related to the project' do
+ let(:another_project) { create(:project, :repository) }
+ let(:deploy_token) { create(:deploy_token, projects: [another_project]) }
+
+ it 'responds with access forbidden' do
+ # We render 404, to prevent data leakage about existence of the project
+ expect(response).to have_gitlab_http_status(404)
+ end
+ end
+ end
+
context 'when build is authorized as' do
let(:authorization) { authorize_ci_project }
@@ -1381,6 +1415,10 @@ describe 'Git LFS API and storage' do
ActionController::HttpAuthentication::Basic.encode_credentials(user.username, Gitlab::LfsToken.new(user).token)
end
+ def authorize_deploy_token
+ ActionController::HttpAuthentication::Basic.encode_credentials(deploy_token.username, deploy_token.token)
+ end
+
def post_lfs_json(url, body = nil, headers = nil)
post(url, body.try(:to_json), (headers || {}).merge('Content-Type' => LfsRequest::CONTENT_TYPE))
end
diff --git a/spec/services/event_create_service_spec.rb b/spec/services/event_create_service_spec.rb
index 13395a7cac3..68e310b0506 100644
--- a/spec/services/event_create_service_spec.rb
+++ b/spec/services/event_create_service_spec.rb
@@ -1,8 +1,6 @@
require 'spec_helper'
describe EventCreateService do
- include UserActivitiesHelpers
-
let(:service) { described_class.new }
describe 'Issues' do
@@ -146,7 +144,7 @@ describe EventCreateService do
it 'updates user last activity' do
expect { service.push(project, user, push_data) }
- .to change { user_activity(user) }
+ .to change { user.last_activity_on }.to(Date.today)
end
it 'caches the last push event for the user' do
diff --git a/spec/services/groups/destroy_service_spec.rb b/spec/services/groups/destroy_service_spec.rb
index a9baccd061a..b54491cf5f9 100644
--- a/spec/services/groups/destroy_service_spec.rb
+++ b/spec/services/groups/destroy_service_spec.rb
@@ -49,7 +49,7 @@ describe Groups::DestroyService do
context 'Sidekiq inline' do
before do
# Run sidekiq immediately to check that renamed dir will be removed
- Sidekiq::Testing.inline! { destroy_group(group, user, async) }
+ perform_enqueued_jobs { destroy_group(group, user, async) }
end
it 'verifies that paths have been deleted' do
diff --git a/spec/services/projects/create_from_template_service_spec.rb b/spec/services/projects/create_from_template_service_spec.rb
index 9aa9237d875..a43da01f37e 100644
--- a/spec/services/projects/create_from_template_service_spec.rb
+++ b/spec/services/projects/create_from_template_service_spec.rb
@@ -28,7 +28,7 @@ describe Projects::CreateFromTemplateService do
context 'the result project' do
before do
- Sidekiq::Testing.inline! do
+ perform_enqueued_jobs do
@project = subject.execute
end
diff --git a/spec/services/projects/destroy_service_spec.rb b/spec/services/projects/destroy_service_spec.rb
index 38660ad7a01..e428808ab68 100644
--- a/spec/services/projects/destroy_service_spec.rb
+++ b/spec/services/projects/destroy_service_spec.rb
@@ -45,18 +45,18 @@ describe Projects::DestroyService do
shared_examples 'handles errors thrown during async destroy' do |error_message|
it 'does not allow the error to bubble up' do
expect do
- Sidekiq::Testing.inline! { destroy_project(project, user, {}) }
+ perform_enqueued_jobs { destroy_project(project, user, {}) }
end.not_to raise_error
end
it 'unmarks the project as "pending deletion"' do
- Sidekiq::Testing.inline! { destroy_project(project, user, {}) }
+ perform_enqueued_jobs { destroy_project(project, user, {}) }
expect(project.reload.pending_delete).to be(false)
end
it 'stores an error message in `projects.delete_error`' do
- Sidekiq::Testing.inline! { destroy_project(project, user, {}) }
+ perform_enqueued_jobs { destroy_project(project, user, {}) }
expect(project.reload.delete_error).to be_present
expect(project.delete_error).to include(error_message)
@@ -66,7 +66,7 @@ describe Projects::DestroyService do
context 'Sidekiq inline' do
before do
# Run sidekiq immediatly to check that renamed repository will be removed
- Sidekiq::Testing.inline! { destroy_project(project, user, {}) }
+ perform_enqueued_jobs { destroy_project(project, user, {}) }
end
context 'when has remote mirrors' do
@@ -110,7 +110,7 @@ describe Projects::DestroyService do
end
it 'keeps project team intact upon an error' do
- Sidekiq::Testing.inline! do
+ perform_enqueued_jobs do
begin
destroy_project(project, user, {})
rescue ::Redis::CannotConnectError
@@ -128,7 +128,7 @@ describe Projects::DestroyService do
before do
project.project_feature.update_attribute("issues_access_level", ProjectFeature::PRIVATE)
# Run sidekiq immediately to check that renamed repository will be removed
- Sidekiq::Testing.inline! { destroy_project(project, user, {}) }
+ perform_enqueued_jobs { destroy_project(project, user, {}) }
end
it_behaves_like 'deleting the project'
@@ -172,7 +172,7 @@ describe Projects::DestroyService do
it 'allows error to bubble up and rolls back project deletion' do
expect do
- Sidekiq::Testing.inline! { destroy_project(project, user, {}) }
+ perform_enqueued_jobs { destroy_project(project, user, {}) }
end.to raise_error(Exception, 'Other error message')
expect(project.reload.pending_delete).to be(false)
diff --git a/spec/services/projects/housekeeping_service_spec.rb b/spec/services/projects/housekeeping_service_spec.rb
index 1cf373d1d72..18ecef1c0a1 100644
--- a/spec/services/projects/housekeeping_service_spec.rb
+++ b/spec/services/projects/housekeeping_service_spec.rb
@@ -35,7 +35,7 @@ describe Projects::HousekeepingService do
allow(subject).to receive(:gc_period).and_return(1)
project.increment_pushes_since_gc
- Sidekiq::Testing.inline! do
+ perform_enqueued_jobs do
expect { subject.execute }.to change { project.pushes_since_gc }.to(0)
end
end
diff --git a/spec/services/projects/import_service_spec.rb b/spec/services/projects/import_service_spec.rb
index b3815045792..e2a600d12d1 100644
--- a/spec/services/projects/import_service_spec.rb
+++ b/spec/services/projects/import_service_spec.rb
@@ -69,7 +69,7 @@ describe Projects::ImportService do
result = subject.execute
expect(result[:status]).to eq :error
- expect(result[:message]).to eq "Error importing repository #{project.import_url} into #{project.full_path} - The repository could not be created."
+ expect(result[:message]).to eq "Error importing repository #{project.safe_import_url} into #{project.full_path} - The repository could not be created."
end
context 'when repository creation succeeds' do
@@ -141,7 +141,7 @@ describe Projects::ImportService do
result = subject.execute
expect(result[:status]).to eq :error
- expect(result[:message]).to eq "Error importing repository #{project.import_url} into #{project.full_path} - Failed to import the repository"
+ expect(result[:message]).to eq "Error importing repository #{project.safe_import_url} into #{project.full_path} - Failed to import the repository"
end
context 'when repository import scheduled' do
diff --git a/spec/services/users/activity_service_spec.rb b/spec/services/users/activity_service_spec.rb
index 17eabad73be..f20849e6924 100644
--- a/spec/services/users/activity_service_spec.rb
+++ b/spec/services/users/activity_service_spec.rb
@@ -1,60 +1,61 @@
require 'spec_helper'
describe Users::ActivityService do
- include UserActivitiesHelpers
+ include ExclusiveLeaseHelpers
- let(:user) { create(:user) }
+ let(:user) { create(:user, last_activity_on: last_activity_on) }
- subject(:service) { described_class.new(user, 'type') }
+ subject { described_class.new(user, 'type') }
describe '#execute', :clean_gitlab_redis_shared_state do
context 'when last activity is nil' do
- before do
- service.execute
- end
+ let(:last_activity_on) { nil }
- it 'sets the last activity timestamp for the user' do
- expect(last_hour_user_ids).to eq([user.id])
+ it 'updates last_activity_on for the user' do
+ expect { subject.execute }
+ .to change(user, :last_activity_on).from(last_activity_on).to(Date.today)
end
+ end
- it 'updates the same user' do
- service.execute
+ context 'when last activity is in the past' do
+ let(:last_activity_on) { Date.today - 1.week }
- expect(last_hour_user_ids).to eq([user.id])
- end
-
- it 'updates the timestamp of an existing user' do
- Timecop.freeze(Date.tomorrow) do
- expect { service.execute }.to change { user_activity(user) }.to(Time.now.to_i.to_s)
- end
+ it 'updates last_activity_on for the user' do
+ expect { subject.execute }
+ .to change(user, :last_activity_on)
+ .from(last_activity_on)
+ .to(Date.today)
end
+ end
- describe 'other user' do
- it 'updates other user' do
- other_user = create(:user)
- described_class.new(other_user, 'type').execute
+ context 'when last activity is today' do
+ let(:last_activity_on) { Date.today }
- expect(last_hour_user_ids).to match_array([user.id, other_user.id])
- end
+ it 'does not update last_activity_on' do
+ expect { subject.execute }.not_to change(user, :last_activity_on)
end
end
context 'when in GitLab read-only instance' do
+ let(:last_activity_on) { nil }
+
before do
allow(Gitlab::Database).to receive(:read_only?).and_return(true)
end
- it 'does not update last_activity_at' do
- service.execute
-
- expect(last_hour_user_ids).to eq([])
+ it 'does not update last_activity_on' do
+ expect { subject.execute }.not_to change(user, :last_activity_on)
end
end
- end
- def last_hour_user_ids
- Gitlab::UserActivities.new
- .select { |k, v| v >= 1.hour.ago.to_i.to_s }
- .map { |k, _| k.to_i }
+ context 'when a lease could not be obtained' do
+ let(:last_activity_on) { nil }
+
+ it 'does not update last_activity_on' do
+ stub_exclusive_lease_taken("acitvity_service:#{user.id}", timeout: 1.minute.to_i)
+
+ expect { subject.execute }.not_to change(user, :last_activity_on)
+ end
+ end
end
end
diff --git a/spec/services/users/destroy_service_spec.rb b/spec/services/users/destroy_service_spec.rb
index f82d4b483e7..3bae8bfbd42 100644
--- a/spec/services/users/destroy_service_spec.rb
+++ b/spec/services/users/destroy_service_spec.rb
@@ -173,7 +173,7 @@ describe Users::DestroyService do
describe "user personal's repository removal" do
before do
- Sidekiq::Testing.inline! { service.execute(user) }
+ perform_enqueued_jobs { service.execute(user) }
end
context 'legacy storage' do
diff --git a/spec/support/helpers/user_activities_helpers.rb b/spec/support/helpers/user_activities_helpers.rb
deleted file mode 100644
index 44feb104644..00000000000
--- a/spec/support/helpers/user_activities_helpers.rb
+++ /dev/null
@@ -1,7 +0,0 @@
-module UserActivitiesHelpers
- def user_activity(user)
- Gitlab::UserActivities.new
- .find { |k, _| k == user.id.to_s }&.
- second
- end
-end
diff --git a/spec/support/matchers/user_activity_matchers.rb b/spec/support/matchers/user_activity_matchers.rb
deleted file mode 100644
index ce3b683b6d2..00000000000
--- a/spec/support/matchers/user_activity_matchers.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-RSpec::Matchers.define :have_an_activity_record do |expected|
- match do |user|
- expect(Gitlab::UserActivities.new.find { |k, _| k == user.id.to_s }).to be_present
- end
-end
diff --git a/spec/workers/emails_on_push_worker_spec.rb b/spec/workers/emails_on_push_worker_spec.rb
index 318aad4bc1e..f17c5ac6aac 100644
--- a/spec/workers/emails_on_push_worker_spec.rb
+++ b/spec/workers/emails_on_push_worker_spec.rb
@@ -100,10 +100,6 @@ describe EmailsOnPushWorker, :mailer do
end
context "when there are multiple recipients" do
- let(:recipients) do
- 1.upto(5).map { |i| user.email.sub('@', "+#{i}@") }.join("\n")
- end
-
before do
# This is a hack because we modify the mail object before sending, for efficency,
# but the TestMailer adapter just appends the objects to an array. To clone a mail
@@ -114,16 +110,57 @@ describe EmailsOnPushWorker, :mailer do
end
end
- it "sends the mail to each of the recipients" do
- perform
- expect(ActionMailer::Base.deliveries.count).to eq(5)
- expect(ActionMailer::Base.deliveries.map(&:to).flatten).to contain_exactly(*recipients.split)
+ context "when the recipient addresses are a list of email addresses" do
+ let(:recipients) do
+ 1.upto(5).map { |i| user.email.sub('@', "+#{i}@") }.join("\n")
+ end
+
+ it "sends the mail to each of the recipients" do
+ perform
+
+ expect(ActionMailer::Base.deliveries.count).to eq(5)
+ expect(email_recipients).to contain_exactly(*recipients.split)
+ end
+
+ it "only generates the mail once" do
+ expect(Notify).to receive(:repository_push_email).once.and_call_original
+ expect(Premailer::Rails::CustomizedPremailer).to receive(:new).once.and_call_original
+
+ perform
+ end
end
- it "only generates the mail once" do
- expect(Notify).to receive(:repository_push_email).once.and_call_original
- expect(Premailer::Rails::CustomizedPremailer).to receive(:new).once.and_call_original
- perform
+ context "when the recipient addresses contains angle brackets and are separated by spaces" do
+ let(:recipients) { "John Doe <johndoe@example.com> Jane Doe <janedoe@example.com>" }
+
+ it "accepts emails separated by whitespace" do
+ perform
+
+ expect(ActionMailer::Base.deliveries.count).to eq(2)
+ expect(email_recipients).to contain_exactly("johndoe@example.com", "janedoe@example.com")
+ end
+ end
+
+ context "when the recipient addresses contain a mix of emails with and without angle brackets" do
+ let(:recipients) { "johndoe@example.com Jane Doe <janedoe@example.com>" }
+
+ it "accepts both kind of emails" do
+ perform
+
+ expect(ActionMailer::Base.deliveries.count).to eq(2)
+ expect(email_recipients).to contain_exactly("johndoe@example.com", "janedoe@example.com")
+ end
+ end
+
+ context "when the recipient addresses contains angle brackets and are separated by newlines" do
+ let(:recipients) { "John Doe <johndoe@example.com>\nJane Doe <janedoe@example.com>" }
+
+ it "accepts emails separated by newlines" do
+ perform
+
+ expect(ActionMailer::Base.deliveries.count).to eq(2)
+ expect(email_recipients).to contain_exactly("johndoe@example.com", "janedoe@example.com")
+ end
end
end
end
diff --git a/spec/workers/schedule_update_user_activity_worker_spec.rb b/spec/workers/schedule_update_user_activity_worker_spec.rb
deleted file mode 100644
index 32c59381b01..00000000000
--- a/spec/workers/schedule_update_user_activity_worker_spec.rb
+++ /dev/null
@@ -1,25 +0,0 @@
-require 'spec_helper'
-
-describe ScheduleUpdateUserActivityWorker, :clean_gitlab_redis_shared_state do
- let(:now) { Time.now }
-
- before do
- Gitlab::UserActivities.record('1', now)
- Gitlab::UserActivities.record('2', now)
- end
-
- it 'schedules UpdateUserActivityWorker once' do
- expect(UpdateUserActivityWorker).to receive(:perform_async).with({ '1' => now.to_i.to_s, '2' => now.to_i.to_s })
-
- subject.perform
- end
-
- context 'when specifying a batch size' do
- it 'schedules UpdateUserActivityWorker twice' do
- expect(UpdateUserActivityWorker).to receive(:perform_async).with({ '1' => now.to_i.to_s })
- expect(UpdateUserActivityWorker).to receive(:perform_async).with({ '2' => now.to_i.to_s })
-
- subject.perform(1)
- end
- end
-end
diff --git a/spec/workers/storage_migrator_worker_spec.rb b/spec/workers/storage_migrator_worker_spec.rb
index 815432aacce..808084c8f7c 100644
--- a/spec/workers/storage_migrator_worker_spec.rb
+++ b/spec/workers/storage_migrator_worker_spec.rb
@@ -13,7 +13,7 @@ describe StorageMigratorWorker do
end
it 'migrates projects in the specified range' do
- Sidekiq::Testing.inline! do
+ perform_enqueued_jobs do
worker.perform(ids.min, ids.max)
end
diff --git a/spec/workers/update_user_activity_worker_spec.rb b/spec/workers/update_user_activity_worker_spec.rb
deleted file mode 100644
index 268ca1d81f2..00000000000
--- a/spec/workers/update_user_activity_worker_spec.rb
+++ /dev/null
@@ -1,35 +0,0 @@
-require 'spec_helper'
-
-describe UpdateUserActivityWorker, :clean_gitlab_redis_shared_state do
- let(:user_active_2_days_ago) { create(:user, current_sign_in_at: 10.months.ago) }
- let(:user_active_yesterday_1) { create(:user) }
- let(:user_active_yesterday_2) { create(:user) }
- let(:user_active_today) { create(:user) }
- let(:data) do
- {
- user_active_2_days_ago.id.to_s => 2.days.ago.at_midday.to_i.to_s,
- user_active_yesterday_1.id.to_s => 1.day.ago.at_midday.to_i.to_s,
- user_active_yesterday_2.id.to_s => 1.day.ago.at_midday.to_i.to_s,
- user_active_today.id.to_s => Time.now.to_i.to_s
- }
- end
-
- it 'updates users.last_activity_on' do
- subject.perform(data)
-
- aggregate_failures do
- expect(user_active_2_days_ago.reload.last_activity_on).to eq(2.days.ago.to_date)
- expect(user_active_yesterday_1.reload.last_activity_on).to eq(1.day.ago.to_date)
- expect(user_active_yesterday_2.reload.last_activity_on).to eq(1.day.ago.to_date)
- expect(user_active_today.reload.reload.last_activity_on).to eq(Date.today)
- end
- end
-
- it 'deletes the pairs from SharedState' do
- data.each { |id, time| Gitlab::UserActivities.record(id, time) }
-
- subject.perform(data)
-
- expect(Gitlab::UserActivities.new.to_a).to be_empty
- end
-end
diff --git a/vendor/jupyter/values.yaml b/vendor/jupyter/values.yaml
index 90817de0f1b..4ea5b44c59c 100644
--- a/vendor/jupyter/values.yaml
+++ b/vendor/jupyter/values.yaml
@@ -4,6 +4,7 @@ rbac:
hub:
extraEnv:
JUPYTER_ENABLE_LAB: 1
+ SINGLEUSER_IMAGE: 'registry.gitlab.com/gitlab-org/jupyterhub-user-image:latest'
extraConfig: |
c.KubeSpawner.cmd = ['jupyter-labhub']
diff --git a/yarn.lock b/yarn.lock
index 67f9aa98c74..85fdb150d34 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -3211,6 +3211,10 @@ form-data@~2.3.0, form-data@~2.3.1:
combined-stream "1.0.6"
mime-types "^2.1.12"
+formdata-polyfill@^3.0.11:
+ version "3.0.11"
+ resolved "https://registry.yarnpkg.com/formdata-polyfill/-/formdata-polyfill-3.0.11.tgz#c82b4b4bea3356c0a6752219e54ce1edb2a7fb5b"
+
forwarded@~0.1.2:
version "0.1.2"
resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.1.2.tgz#98c23dab1175657b8c0573e8ceccd91b0ff18c84"