summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLin Jen-Shin <godfat@godfat.org>2018-12-26 18:03:21 +0800
committerLin Jen-Shin <godfat@godfat.org>2018-12-26 18:03:21 +0800
commit82bf55c8db3d149c27807e5646ff8ff4454a5ea7 (patch)
tree65e2523a9288ec64421b19ccf27cbce0c371c40c
parentcc06bb2c6ec1facf2b1eb50803dbedc076abe017 (diff)
parent145079b3540ca832e1d981bbc685cc8c27d47ea0 (diff)
downloadgitlab-ce-82bf55c8db3d149c27807e5646ff8ff4454a5ea7.tar.gz
Merge remote-tracking branch 'upstream/master' into 54953-error-500-viewing-merge-request-due-to-nil-commit_email_hostname
* upstream/master: (115 commits) [CE] Speed up login page usage Add new line and comments Fix the seeder 24_forks.rb cannot find public project Milestones on community contribution issues Removed Gitlab Upgrader found in /lib/gitlab/upgrader.rb Fix and move specs into admin_disables_git_access_protocol_spec.rb Fix HTTP/SSH clone panel for mobile Add spec for HTTP/SSH clone panel Fix missing Git clone button when protocol restriction setting enabled Fix deprecation: Using positional arguments in integration tests Extend override check to also check arity Update tm cli version Bump Gitaly version to v1.12.0 Add @dbalexandre to CODEOWNERS Update verbiage for clarity Change group-cluster beta to regular note Change alpha states to use note instead of warning Update registry section. Update serverless.yaml formatting Clarify obtaining application URL Add @godfat to CODEOWNERS ...
-rw-r--r--.gitlab/CODEOWNERS.disabled4
-rw-r--r--.gitlab/issue_templates/Feature proposal.md2
-rw-r--r--CHANGELOG.md291
-rw-r--r--GITALY_SERVER_VERSION2
-rw-r--r--Gemfile6
-rw-r--r--Gemfile.lock10
-rw-r--r--PROCESS.md12
-rw-r--r--VERSION2
-rw-r--r--app/assets/javascripts/api.js7
-rw-r--r--app/assets/javascripts/ci_variable_list/ci_variable_list.js4
-rw-r--r--app/assets/javascripts/diffs/components/inline_diff_view.vue2
-rw-r--r--app/assets/javascripts/diffs/components/parallel_diff_view.vue4
-rw-r--r--app/assets/javascripts/diffs/store/utils.js11
-rw-r--r--app/assets/javascripts/environments/components/environment_item.vue11
-rw-r--r--app/assets/javascripts/environments/components/environment_terminal_button.vue6
-rw-r--r--app/assets/javascripts/jobs/components/artifacts_block.vue32
-rw-r--r--app/assets/javascripts/jobs/components/commit_block.vue21
-rw-r--r--app/assets/javascripts/jobs/components/sidebar.vue35
-rw-r--r--app/assets/javascripts/jobs/components/sidebar_detail_row.vue3
-rw-r--r--app/assets/javascripts/jobs/components/stages_dropdown.vue6
-rw-r--r--app/assets/javascripts/jobs/components/trigger_block.vue17
-rw-r--r--app/assets/javascripts/lib/utils/text_markdown.js4
-rw-r--r--app/assets/javascripts/notes/components/noteable_discussion.vue39
-rw-r--r--app/assets/javascripts/pages/projects/releases/index/index.js3
-rw-r--r--app/assets/javascripts/releases/components/app.vue82
-rw-r--r--app/assets/javascripts/releases/components/release_block.vue86
-rw-r--r--app/assets/javascripts/releases/index.js24
-rw-r--r--app/assets/javascripts/releases/store/actions.js37
-rw-r--r--app/assets/javascripts/releases/store/index.js14
-rw-r--r--app/assets/javascripts/releases/store/mutation_types.js3
-rw-r--r--app/assets/javascripts/releases/store/mutations.js37
-rw-r--r--app/assets/javascripts/releases/store/state.js5
-rw-r--r--app/assets/javascripts/right_sidebar.js15
-rw-r--r--app/assets/javascripts/serverless/components/functions.vue2
-rw-r--r--app/assets/javascripts/sidebar/stores/sidebar_store.js2
-rw-r--r--app/assets/javascripts/vue_shared/components/user_popover/user_popover.vue21
-rw-r--r--app/assets/stylesheets/framework/files.scss2
-rw-r--r--app/assets/stylesheets/framework/highlight.scss7
-rw-r--r--app/assets/stylesheets/framework/modal.scss4
-rw-r--r--app/assets/stylesheets/framework/variables.scss2
-rw-r--r--app/assets/stylesheets/framework/variables_overrides.scss6
-rw-r--r--app/assets/stylesheets/pages/builds.scss6
-rw-r--r--app/controllers/application_controller.rb2
-rw-r--r--app/controllers/concerns/group_tree.rb4
-rw-r--r--app/controllers/concerns/issuable_actions.rb10
-rw-r--r--app/controllers/concerns/lfs_request.rb6
-rw-r--r--app/controllers/projects/deploy_keys_controller.rb2
-rw-r--r--app/controllers/projects/merge_requests/conflicts_controller.rb8
-rw-r--r--app/controllers/projects/merge_requests_controller.rb6
-rw-r--r--app/finders/group_descendants_finder.rb6
-rw-r--r--app/finders/groups_finder.rb4
-rw-r--r--app/helpers/application_settings_helper.rb15
-rw-r--r--app/helpers/ci_variables_helper.rb15
-rw-r--r--app/helpers/groups_helper.rb2
-rw-r--r--app/helpers/issuables_helper.rb109
-rw-r--r--app/helpers/milestones_helper.rb8
-rw-r--r--app/helpers/projects_helper.rb28
-rw-r--r--app/mailers/emails/issues.rb4
-rw-r--r--app/mailers/emails/merge_requests.rb4
-rw-r--r--app/mailers/notify.rb1
-rw-r--r--app/models/application_setting.rb3
-rw-r--r--app/models/broadcast_message.rb37
-rw-r--r--app/models/ci/runner.rb2
-rw-r--r--app/models/clusters/platforms/kubernetes.rb2
-rw-r--r--app/models/concerns/avatarable.rb13
-rw-r--r--app/models/concerns/descendant.rb11
-rw-r--r--app/models/concerns/discussion_on_diff.rb1
-rw-r--r--app/models/dashboard_group_milestone.rb1
-rw-r--r--app/models/environment.rb5
-rw-r--r--app/models/group.rb5
-rw-r--r--app/models/namespace.rb17
-rw-r--r--app/models/pool_repository.rb17
-rw-r--r--app/models/project.rb14
-rw-r--r--app/models/user.rb10
-rw-r--r--app/policies/group_policy.rb2
-rw-r--r--app/serializers/entity_date_helper.rb16
-rw-r--r--app/serializers/environment_entity.rb16
-rw-r--r--app/serializers/issuable_sidebar_basic_entity.rb106
-rw-r--r--app/serializers/issuable_sidebar_extras_entity.rb (renamed from app/serializers/issuable_sidebar_entity.rb)4
-rw-r--r--app/serializers/issuable_sidebar_todo_entity.rb11
-rw-r--r--app/serializers/issue_board_entity.rb2
-rw-r--r--app/serializers/issue_serializer.rb6
-rw-r--r--app/serializers/issue_sidebar_basic_entity.rb6
-rw-r--r--app/serializers/issue_sidebar_extras_entity.rb (renamed from app/serializers/issue_sidebar_entity.rb)2
-rw-r--r--app/serializers/merge_request_basic_entity.rb2
-rw-r--r--app/serializers/merge_request_basic_serializer.rb5
-rw-r--r--app/serializers/merge_request_serializer.rb9
-rw-r--r--app/serializers/merge_request_sidebar_basic_entity.rb11
-rw-r--r--app/services/ci/register_job_service.rb2
-rw-r--r--app/services/clusters/gcp/finalize_creation_service.rb2
-rw-r--r--app/services/deploy_keys/create_service.rb2
-rw-r--r--app/services/groups/nested_create_service.rb2
-rw-r--r--app/services/groups/transfer_service.rb2
-rw-r--r--app/services/projects/after_rename_service.rb1
-rw-r--r--app/services/projects/destroy_service.rb2
-rw-r--r--app/services/projects/transfer_service.rb7
-rw-r--r--app/services/users/refresh_authorized_projects_service.rb2
-rw-r--r--app/views/admin/application_settings/_ci_cd.html.haml7
-rw-r--r--app/views/ci/variables/_content.html.haml2
-rw-r--r--app/views/ci/variables/_header.html.haml11
-rw-r--r--app/views/ci/variables/_index.html.haml5
-rw-r--r--app/views/ci/variables/_variable_row.html.haml6
-rw-r--r--app/views/groups/settings/ci_cd/show.html.haml8
-rw-r--r--app/views/layouts/_search.html.haml2
-rw-r--r--app/views/layouts/devise.html.haml2
-rw-r--r--app/views/layouts/header/_default.html.haml2
-rw-r--r--app/views/layouts/header/_new_dropdown.haml2
-rw-r--r--app/views/layouts/nav/_dashboard.html.haml4
-rw-r--r--app/views/notify/_note_email.html.haml10
-rw-r--r--app/views/notify/_note_email.text.erb2
-rw-r--r--app/views/notify/changed_milestone_email.html.haml (renamed from app/views/notify/changed_milestone_merge_request_email.html.haml)2
-rw-r--r--app/views/notify/changed_milestone_email.text.erb1
-rw-r--r--app/views/notify/changed_milestone_issue_email.html.haml3
-rw-r--r--app/views/notify/changed_milestone_issue_email.text.erb1
-rw-r--r--app/views/notify/changed_milestone_merge_request_email.text.erb1
-rw-r--r--app/views/projects/buttons/_clone.html.haml33
-rw-r--r--app/views/projects/issues/show.html.haml2
-rw-r--r--app/views/projects/merge_requests/conflicts.html.haml36
-rw-r--r--app/views/projects/merge_requests/conflicts/show.html.haml2
-rw-r--r--app/views/projects/merge_requests/show.html.haml3
-rw-r--r--app/views/projects/releases/index.html.haml4
-rw-r--r--app/views/projects/settings/ci_cd/show.html.haml8
-rw-r--r--app/views/shared/_mobile_clone_panel.html.haml10
-rw-r--r--app/views/shared/issuable/_sidebar.html.haml165
-rw-r--r--app/views/shared/issuable/_sidebar_assignees.html.haml51
-rw-r--r--app/views/shared/issuable/_sidebar_todo.html.haml18
-rw-r--r--app/views/shared/issuable/form/_metadata.html.haml3
-rw-r--r--app/views/shared/milestones/_sidebar.html.haml2
-rw-r--r--app/views/shared/projects/_project.html.haml4
-rw-r--r--app/workers/all_queues.yml3
-rw-r--r--app/workers/cluster_configure_worker.rb (renamed from app/workers/cluster_platform_configure_worker.rb)2
-rw-r--r--app/workers/cluster_provision_worker.rb2
-rw-r--r--app/workers/object_pool/destroy_worker.rb16
-rw-r--r--app/workers/stuck_merge_jobs_worker.rb6
-rw-r--r--changelogs/unreleased/19376-post-bfg-cleanup.yml5
-rw-r--r--changelogs/unreleased/1979-redesign-mr-widget-approvals-ce.yml5
-rw-r--r--changelogs/unreleased/20422-hide-ui-variables-by-default.yml6
-rw-r--r--changelogs/unreleased/22548-reopen-error-message.yml6
-rw-r--r--changelogs/unreleased/23367-clarify-docs-allow-failure.yml5
-rw-r--r--changelogs/unreleased/33705-merge-request-rebase-api.yml5
-rw-r--r--changelogs/unreleased/34758-deployment-cluster.yml5
-rw-r--r--changelogs/unreleased/34758-group-cluster-controller.yml5
-rw-r--r--changelogs/unreleased/38495-calendar-activities-in-timezone.yml5
-rw-r--r--changelogs/unreleased/39849_controller_sorts.yml5
-rw-r--r--changelogs/unreleased/40085-add-a-create_merge_request-quick-action.yml5
-rw-r--r--changelogs/unreleased/40260-reduce-gitaly-calls-project-pipeline-status.yml5
-rw-r--r--changelogs/unreleased/40270-remove-gitlab-upgrader-completely.yml5
-rw-r--r--changelogs/unreleased/40385-prohibit_impersonation.yml5
-rw-r--r--changelogs/unreleased/41766-vuex-store.yml5
-rw-r--r--changelogs/unreleased/41875-allow-pipelines-to-be-deleted-by-project-owners.yml5
-rw-r--r--changelogs/unreleased/42125-extend-override-check-to-also-check-arity.yml5
-rw-r--r--changelogs/unreleased/44984-use-serializer-for-issuable-sidebar.yml5
-rw-r--r--changelogs/unreleased/46544-webide-ctrl-enter-commit-shortcut.yml5
-rw-r--r--changelogs/unreleased/46950-systemcheck-ruby-version.yml5
-rw-r--r--changelogs/unreleased/48475-gitlab-pages-settings-regressions.yml5
-rw-r--r--changelogs/unreleased/48496-merge-request-refactor-does-not-highlight-selected-line.yml5
-rw-r--r--changelogs/unreleased/48889-populate-merge_commit_sha.yml6
-rw-r--r--changelogs/unreleased/49479-hide-unmerged-env-perf-stats.yml5
-rw-r--r--changelogs/unreleased/49565-ssh-push-mirroring.yml5
-rw-r--r--changelogs/unreleased/49713-main-navbar-is-broken-in-certain-viewport-widths.yml5
-rw-r--r--changelogs/unreleased/49726-upgrade-helm-to-2-11.yml5
-rw-r--r--changelogs/unreleased/50157-extended-user-centric-tooltips.yml5
-rw-r--r--changelogs/unreleased/50264-add-border-around-the-repository-file-tree.yml5
-rw-r--r--changelogs/unreleased/50341-cleanup-useless-project-import-attributes.yml6
-rw-r--r--changelogs/unreleased/50626-searching-users-by-the-admin-panel-wipes-query-when-using-sort.yml5
-rw-r--r--changelogs/unreleased/50839-webide-mr-dropdown-filter.yml5
-rw-r--r--changelogs/unreleased/51029-status-emoji-currently-replaces-avatar-on-mobile.yml5
-rw-r--r--changelogs/unreleased/51061-readme-url-n-1-rpc-call-resolved.yml5
-rw-r--r--changelogs/unreleased/51083-fix-move-api.yml5
-rw-r--r--changelogs/unreleased/51101-can-add-an-existing-group-member-into-a-group-project-with-new-permissions-but-permissions-are-not-overridde.yml5
-rw-r--r--changelogs/unreleased/51122-fix-navigating-discussions.yml5
-rw-r--r--changelogs/unreleased/51138-54026-breadcrumb-subgroups-ellipsis.yml5
-rw-r--r--changelogs/unreleased/51243-further-improvements-to-project-overview-ui.yml5
-rw-r--r--changelogs/unreleased/51259-ci-cd-gitlab-ui-1.yml5
-rw-r--r--changelogs/unreleased/51259-ci-cd-tooltips.yml6
-rw-r--r--changelogs/unreleased/51606-expanding-a-diff-while-having-an-open-comment-form-will-always-scroll-down-to-the-comment.yml5
-rw-r--r--changelogs/unreleased/51668-fix-line-numbers.yml5
-rw-r--r--changelogs/unreleased/51792-dont-delete-failed-install-pods.yml5
-rw-r--r--changelogs/unreleased/51959-branch-and-tag-name-links.yml5
-rw-r--r--changelogs/unreleased/52007-frontmatter-toml-json.yml5
-rw-r--r--changelogs/unreleased/52276-jump-to-top-in-merge-request.yml5
-rw-r--r--changelogs/unreleased/52285-omniauth-jwt-ppk-support.yml5
-rw-r--r--changelogs/unreleased/52370-filter-by-none-any-for-labels-in-issues-mrs-boards.yml5
-rw-r--r--changelogs/unreleased/52371-filter-by-none-any-for-labels-in-issues-mrs-api.yml5
-rw-r--r--changelogs/unreleased/52371-removes-patially-matching-no-label-and-makes-it-case-insensitive.yml5
-rw-r--r--changelogs/unreleased/52385-search-bar-for-dashboard-list.yml5
-rw-r--r--changelogs/unreleased/52453-show-subgroups-in-group-create-issue.yml5
-rw-r--r--changelogs/unreleased/52620-fix-loader-animation-alignment.yml5
-rw-r--r--changelogs/unreleased/52712-further-ui-improvements-to-profile-overview-tab.yml5
-rw-r--r--changelogs/unreleased/52774-fix-svgs-in-ie-11.yml5
-rw-r--r--changelogs/unreleased/52828-inconsistency-in-fonts-used-for-branch-name-and-create-from-fields-when-creating-new-branch-from-ui.yml5
-rw-r--r--changelogs/unreleased/52940-fix-internal-email-pattern-not-respected.yml5
-rw-r--r--changelogs/unreleased/53289-update-haml_lint-to-0-28-0.yml5
-rw-r--r--changelogs/unreleased/53290-incorrect-project-list-order-select-default-label.yml5
-rw-r--r--changelogs/unreleased/53291-update-ffaker-to-2-10-0.yml5
-rw-r--r--changelogs/unreleased/53326-improve-issues-empty-state.yml5
-rw-r--r--changelogs/unreleased/53400-unstar-icon-button-is-misaligned.yml5
-rw-r--r--changelogs/unreleased/53578-fe-deployment-status.yml5
-rw-r--r--changelogs/unreleased/53626-update-config-map-on-install-retry.yml5
-rw-r--r--changelogs/unreleased/53640-follow-up-from-resolve-redesign-activity-feed.yml4
-rw-r--r--changelogs/unreleased/53659-use-padded-key-for-gcm-ciphers.yml5
-rw-r--r--changelogs/unreleased/53700-hashed-storagemigration.yml5
-rw-r--r--changelogs/unreleased/53728-warn-in-web-editor-when-user-navigates-away.yml5
-rw-r--r--changelogs/unreleased/53816-empty-label-menu-if-not-logged-in.yml5
-rw-r--r--changelogs/unreleased/53874-navbar-lowres.yml5
-rw-r--r--changelogs/unreleased/53933-include-dates-in-milestone-change-email.yml5
-rw-r--r--changelogs/unreleased/53988-remove-notes-index-on-updated-at.yml5
-rw-r--r--changelogs/unreleased/53992-add-events-index-on-project-id-and-created-at.yml5
-rw-r--r--changelogs/unreleased/53994-add-missing-ci_builds-partial-indices.yml5
-rw-r--r--changelogs/unreleased/54004-update-asana-to-0-8-1.yml5
-rw-r--r--changelogs/unreleased/54010-update-asciidoctor-to-1-5-8.yml5
-rw-r--r--changelogs/unreleased/54015-Markdown-Editor-improve-Cursor-placement.yml5
-rw-r--r--changelogs/unreleased/54021-empty-button.yml5
-rw-r--r--changelogs/unreleased/54032-reply-shortcut-only-discussion-text.yml5
-rw-r--r--changelogs/unreleased/54048-Line-numbers-are-misaligned-in-file-blame-view.yml5
-rw-r--r--changelogs/unreleased/54093-the-default_value_for-gem-doesn-t-handle-actioncontroller-parameters-correctly.yml7
-rw-r--r--changelogs/unreleased/54160-use-reports-syntax-for-sast-in-auto-devops.yml5
-rw-r--r--changelogs/unreleased/54201-update-rack-to-2-0-6.yml5
-rw-r--r--changelogs/unreleased/54218-fix-mergeUrlParams.yml5
-rw-r--r--changelogs/unreleased/54336-include-tags-into-pipeline-detail-view.yml5
-rw-r--r--changelogs/unreleased/54391-tag.yml5
-rw-r--r--changelogs/unreleased/54407-fix-limited-intersection-observers.yml5
-rw-r--r--changelogs/unreleased/54571-runner-tags.yml5
-rw-r--r--changelogs/unreleased/54626-able-to-download-a-single-archive-file-with-api-by-ref-name.yml5
-rw-r--r--changelogs/unreleased/54648-fix-order-by-dropdown-tablet-screens.yml5
-rw-r--r--changelogs/unreleased/54814-sidebar-styling-updates.yml5
-rw-r--r--changelogs/unreleased/54826-use-read_repository-scope-on-read-only-files-endpoints.yml5
-rw-r--r--changelogs/unreleased/54857-fix-templates-path-traversal.yml5
-rw-r--r--changelogs/unreleased/54953-fix-commit_email_hostname-accessor-in-fake_application_settings.yml5
-rw-r--r--changelogs/unreleased/54975-fix-web-hooks-rake-task.yml5
-rw-r--r--changelogs/unreleased/55103-hide-group-cluster-features.yml5
-rw-r--r--changelogs/unreleased/55104-frozenerror-can-t-modify-frozen-string.yml5
-rw-r--r--changelogs/unreleased/55116-runtimeerror-can-t-modify-frozen-string.yml5
-rw-r--r--changelogs/unreleased/55138-fix-mr-discussions-count.yml5
-rw-r--r--changelogs/unreleased/55183-frozenerror-can-t-modify-frozen-string-in-app-mailers-notify-rb.yml5
-rw-r--r--changelogs/unreleased/55293-split-bio-into-individual-line-in-extended-user-tooltips.yml5
-rw-r--r--changelogs/unreleased/55402-broken-master-karma-test-failing-in-spec-javascripts-boards-components-issue_due_date_spec-js.yml5
-rw-r--r--changelogs/unreleased/_acet-fix-flash-styling.yml5
-rw-r--r--changelogs/unreleased/ab-approximate-counts.yml5
-rw-r--r--changelogs/unreleased/added-glob-for-ci-changes-detection.yml5
-rw-r--r--changelogs/unreleased/an-gitaly-version-0-133-0.yml5
-rw-r--r--changelogs/unreleased/ashmckenzie-hmac-token-decode-and-tests.yml5
-rw-r--r--changelogs/unreleased/auto_devops_kubernetes_active.yml5
-rw-r--r--changelogs/unreleased/blackst0ne-add-discord-service.yml5
-rw-r--r--changelogs/unreleased/bump_gpgme_gem.yml5
-rw-r--r--changelogs/unreleased/bvl-use-shell-writeref.yml5
-rw-r--r--changelogs/unreleased/ce-52811-fix_namespaces_api_routing.yml5
-rw-r--r--changelogs/unreleased/ce-54109-fix_user_by_any_email.yml5
-rw-r--r--changelogs/unreleased/cert-manager-email.yml5
-rw-r--r--changelogs/unreleased/certmanager-temp.yml5
-rw-r--r--changelogs/unreleased/check-if-fetched-data-does-is-complete.yml5
-rw-r--r--changelogs/unreleased/commit-badge-style-fix.yml5
-rw-r--r--changelogs/unreleased/define-default-value-for-only-except-keys.yml5
-rw-r--r--changelogs/unreleased/depracated-migration-inheritance.yml5
-rw-r--r--changelogs/unreleased/deprecated-instance-find.yml5
-rw-r--r--changelogs/unreleased/diff-expand-commit-file.yml5
-rw-r--r--changelogs/unreleased/diff-fix-expanding.yml5
-rw-r--r--changelogs/unreleased/discussion-perf-improvement.yml5
-rw-r--r--changelogs/unreleased/dm-batch-loader-key.yml5
-rw-r--r--changelogs/unreleased/dm-note-email-image-diff-discussion.yml5
-rw-r--r--changelogs/unreleased/dm-remove-prune-web-hook-logs-worker.yml5
-rw-r--r--changelogs/unreleased/docs-minor-aws-fixes.yml5
-rw-r--r--changelogs/unreleased/document-raw-snippet-api.yml5
-rw-r--r--changelogs/unreleased/drop-default-value-status-deployments.yml5
-rw-r--r--changelogs/unreleased/drop-gcp-cluster-table.yml5
-rw-r--r--changelogs/unreleased/expose-mr-pipeline-variables.yml5
-rw-r--r--changelogs/unreleased/feature-option-to-make-variables-protected.yml5
-rw-r--r--changelogs/unreleased/fix-55448.yml5
-rw-r--r--changelogs/unreleased/fix-gb-encrypt-ci-build-token.yml5
-rw-r--r--changelogs/unreleased/fix-gb-encrypt-runners-tokens.yml5
-rw-r--r--changelogs/unreleased/fix-gb-improve-timeout-inputs-help-sections.yml5
-rw-r--r--changelogs/unreleased/fix-mr-widget-unrelated-deployment-status.yml5
-rw-r--r--changelogs/unreleased/fix-multiple-comments-shade-overlap.yml5
-rw-r--r--changelogs/unreleased/fj-47494-upgrade-git-to-2-18-0.yml5
-rw-r--r--changelogs/unreleased/fj-clean-content-headers.yml5
-rw-r--r--changelogs/unreleased/fj-force-content-disposition.yml5
-rw-r--r--changelogs/unreleased/force-reload-arguments-1.yml5
-rw-r--r--changelogs/unreleased/frozen-string-lib-gitlab-even-even-even-more.yml5
-rw-r--r--changelogs/unreleased/frozen-string-lib-gitlab-even-even-more.yml5
-rw-r--r--changelogs/unreleased/frozen-string-lib-gitlab-even-more.yml5
-rw-r--r--changelogs/unreleased/frozen-string-lib-gitlab-more.yml5
-rw-r--r--changelogs/unreleased/frozen-string-lib-rubocop.yml5
-rw-r--r--changelogs/unreleased/gt-add-top-padding-for-nested-environment-items-loading-icon.yml5
-rw-r--r--changelogs/unreleased/gt-align-issue-status-and-confidential-icon.yml5
-rw-r--r--changelogs/unreleased/gt-change-breadcrumb-title-for-contribution-charts.yml5
-rw-r--r--changelogs/unreleased/gt-change-container-width-for-project-import.yml5
-rw-r--r--changelogs/unreleased/gt-externalize-app-views-invites.yml5
-rw-r--r--changelogs/unreleased/gt-externalize-app-views-project-runners.yml5
-rw-r--r--changelogs/unreleased/gt-externalize-app-views-snippets.yml5
-rw-r--r--changelogs/unreleased/gt-fix-typo-in-notebook-props.yml5
-rw-r--r--changelogs/unreleased/gt-fix-typos-in-lib.yml5
-rw-r--r--changelogs/unreleased/gt-remove-instances-of-extend-monospace.yml5
-rw-r--r--changelogs/unreleased/gt-remove-unused-project-method.yml5
-rw-r--r--changelogs/unreleased/gt-rename-diffs-store-variable.yml5
-rw-r--r--changelogs/unreleased/gt-show-primary-button-when-all-labels-are-prioritized.yml5
-rw-r--r--changelogs/unreleased/gt-update-env-metrics-empty-state.yml5
-rw-r--r--changelogs/unreleased/gt-use-gl-tooltip-directive.yml5
-rw-r--r--changelogs/unreleased/ide-open-all-mr-files.yml5
-rw-r--r--changelogs/unreleased/ignore-failed-pipeline-creation-on-pipeline-schedule.yml5
-rw-r--r--changelogs/unreleased/improve_auto_devops_migration_debug.yml6
-rw-r--r--changelogs/unreleased/include-new-link-in-breadcrumb.yml5
-rw-r--r--changelogs/unreleased/jivl-add-empty-state-graphs-null-values.yml5
-rw-r--r--changelogs/unreleased/jupyter-tls.yml5
-rw-r--r--changelogs/unreleased/kcj-add-philosophy.yml5
-rw-r--r--changelogs/unreleased/kubernetes-http-response-code.yml5
-rw-r--r--changelogs/unreleased/legacy_fallback_for_project_clusters_only.yml5
-rw-r--r--changelogs/unreleased/lock-trace-writes.yml5
-rw-r--r--changelogs/unreleased/markdown-toolbar-btn-fix.yml (renamed from changelogs/unreleased/fix-deadlock-chunked-io.yml)2
-rw-r--r--changelogs/unreleased/mg-fix-knative-application-row.yml5
-rw-r--r--changelogs/unreleased/mk-avoid-read-only-error.yml5
-rw-r--r--changelogs/unreleased/move-group-issues-search-cte-up-the-chain.yml5
-rw-r--r--changelogs/unreleased/mr-file-tree-commit.yml5
-rw-r--r--changelogs/unreleased/mr-origin-23218.yml5
-rw-r--r--changelogs/unreleased/mr-pipelines-2.yml5
-rw-r--r--changelogs/unreleased/mr-sticky-headers.yml5
-rw-r--r--changelogs/unreleased/mr-tree-filter-path-name.yml5
-rw-r--r--changelogs/unreleased/multiple-diff-line-discussions-fix.yml5
-rw-r--r--changelogs/unreleased/non-webkit-scrollbar-fixing.yml5
-rw-r--r--changelogs/unreleased/optimise-job-request.yml5
-rw-r--r--changelogs/unreleased/order-of-notification-settings.yml5
-rw-r--r--changelogs/unreleased/osw-fallback-on-blank-refs.yml5
-rw-r--r--changelogs/unreleased/osw-fix-grouping-by-file-path.yml5
-rw-r--r--changelogs/unreleased/osw-remove-unnused-data-from-diff-discussions.yml5
-rw-r--r--changelogs/unreleased/osw-update-mr-metrics-with-events-data.yml5
-rw-r--r--changelogs/unreleased/profile-fixing.yml5
-rw-r--r--changelogs/unreleased/project_identicon_fix.yml5
-rw-r--r--changelogs/unreleased/rails5-active-record-class-value.yml5
-rw-r--r--changelogs/unreleased/rails5-deprecation-render-nothing.yml6
-rw-r--r--changelogs/unreleased/rails5-env-deprecated.yml5
-rw-r--r--changelogs/unreleased/remove-blob-search-limit.yml5
-rw-r--r--changelogs/unreleased/remove-deployment-status-hack-from-backend.yml5
-rw-r--r--changelogs/unreleased/remove-duplicate-primary-button-in-dashboard-snippets.yml5
-rw-r--r--changelogs/unreleased/render-text-deprecated.yml6
-rw-r--r--changelogs/unreleased/retryable_create_or_update_kubernetes_namespace.yml6
-rw-r--r--changelogs/unreleased/revert-1cccfca1.yml5
-rw-r--r--changelogs/unreleased/rs-cherry-pick-api.yml5
-rw-r--r--changelogs/unreleased/security-182-update-workhorse.yml5
-rw-r--r--changelogs/unreleased/security-2717-xss-username-autocomplete.yml5
-rw-r--r--changelogs/unreleased/security-2736-prometheus-ssrf.yml5
-rw-r--r--changelogs/unreleased/security-2754-fix-lfs-import.yml5
-rw-r--r--changelogs/unreleased/security-bvl-exposure-in-commits-list.yml5
-rw-r--r--changelogs/unreleased/security-email-change-notification.yml5
-rw-r--r--changelogs/unreleased/security-fix-pat-web-access.yml5
-rw-r--r--changelogs/unreleased/security-fix-uri-xss-applications.yml5
-rw-r--r--changelogs/unreleased/security-fix-webhook-ssrf-ipv6.yml5
-rw-r--r--changelogs/unreleased/security-fj-crlf-injection.yml5
-rw-r--r--changelogs/unreleased/security-guest-comments.yml5
-rw-r--r--changelogs/unreleased/security-guest-comments_2.yml5
-rw-r--r--changelogs/unreleased/security-issue_51301.yml5
-rw-r--r--changelogs/unreleased/security-mermaid-xss.yml5
-rw-r--r--changelogs/unreleased/security-pages-toctou-race.yml6
-rw-r--r--changelogs/unreleased/security-private-group.yml6
-rw-r--r--changelogs/unreleased/security-stored-xss-for-environments.yml5
-rw-r--r--changelogs/unreleased/security-xss-in-markdown-following-unrecognized-html-element.yml5
-rw-r--r--changelogs/unreleased/set-kubeconfig-nil-when-token-nil.yml5
-rw-r--r--changelogs/unreleased/sh-53180-append-path.yml5
-rw-r--r--changelogs/unreleased/sh-bump-gems-security.yml5
-rw-r--r--changelogs/unreleased/sh-bump-ruby-2-5-3.yml5
-rw-r--r--changelogs/unreleased/sh-cache-avatar-paths.yml5
-rw-r--r--changelogs/unreleased/sh-disable-autocomplete-mirror-settings.yml5
-rw-r--r--changelogs/unreleased/sh-fix-http-clone-panel.yml5
-rw-r--r--changelogs/unreleased/sh-fix-issue-38317.yml5
-rw-r--r--changelogs/unreleased/sh-fix-issue-51220.yml5
-rw-r--r--changelogs/unreleased/sh-fix-issue-53783-ce.yml5
-rw-r--r--changelogs/unreleased/sh-fix-mirrors-protected-branches.yml5
-rw-r--r--changelogs/unreleased/sh-handle-invalid-gpg-sig.yml5
-rw-r--r--changelogs/unreleased/sh-handle-string-null-bytes.yml5
-rw-r--r--changelogs/unreleased/sh-ignore-arrays-url-sanitizer.yml5
-rw-r--r--changelogs/unreleased/sh-json-serialize-broadcast-messages.yml5
-rw-r--r--changelogs/unreleased/sh-remove-local-sidekiq-admin-check.yml5
-rw-r--r--changelogs/unreleased/sh-truncate-with-periods.yml5
-rw-r--r--changelogs/unreleased/sh-use-nakayoshi-fork.yml5
-rw-r--r--changelogs/unreleased/sh-use-nokogiri-xml-backend.yml5
-rw-r--r--changelogs/unreleased/spec-positional-arguments.yml5
-rw-r--r--changelogs/unreleased/specs-positional-arguments.yml5
-rw-r--r--changelogs/unreleased/speed-up-relative-positioning.yml5
-rw-r--r--changelogs/unreleased/store-correlation-logs.yml5
-rw-r--r--changelogs/unreleased/suggest-change-to-diff-line.yml5
-rw-r--r--changelogs/unreleased/support-gitaly-tls.yml5
-rw-r--r--changelogs/unreleased/switch-rails.yml5
-rw-r--r--changelogs/unreleased/tc-backfill-full-path-config.yml5
-rw-r--r--changelogs/unreleased/tc-backfill-hashed-project_repositories.yml5
-rw-r--r--changelogs/unreleased/tc-repo-full-path-in-db.yml5
-rw-r--r--changelogs/unreleased/triggermesh-phase2-external-ip.yml5
-rw-r--r--changelogs/unreleased/triggermesh-phase2-knative-description.yml5
-rw-r--r--changelogs/unreleased/triggermesh-phase2-serverless-list.yml5
-rw-r--r--changelogs/unreleased/triggermesh-phase2-serverless.yml5
-rw-r--r--changelogs/unreleased/unicorn-monkey-patch.yml5
-rw-r--r--changelogs/unreleased/update-gitlab-runner-helm-chart-to-0-1-39.yml5
-rw-r--r--changelogs/unreleased/update-gitlab-runner-helm-chart-version.yml5
-rw-r--r--changelogs/unreleased/upgrade-to-workhorse-7-6-0.yml5
-rw-r--r--changelogs/unreleased/upgrade_kubeclient_400.yml5
-rw-r--r--changelogs/unreleased/usage-count.yml5
-rw-r--r--changelogs/unreleased/validate-foreign-keys-being-indexed.yml5
-rw-r--r--changelogs/unreleased/winh-collapse-discussions.yml5
-rw-r--r--changelogs/unreleased/winh-divider-margin.yml5
-rw-r--r--changelogs/unreleased/winh-dropdown-divider-color.yml5
-rw-r--r--changelogs/unreleased/winh-dropdown-item-padding.yml5
-rw-r--r--changelogs/unreleased/winh-issue-boards-project-dropdown-close.yml5
-rw-r--r--changelogs/unreleased/winh-markdown-preview-lists.yml5
-rw-r--r--changelogs/unreleased/winh-merge-request-commit-context.yml5
-rw-r--r--changelogs/unreleased/winh-merge-request-commit-discussion.yml5
-rw-r--r--changelogs/unreleased/winh-merge-request-diff-discussion-commit-id.yml5
-rw-r--r--changelogs/unreleased/winh-milestone-select.yml5
-rw-r--r--changelogs/unreleased/winh-resolved-discussions-reply-field.yml5
-rw-r--r--changelogs/unreleased/winh-upgrade-gitlab-ui.yml5
-rw-r--r--changelogs/unreleased/workhorse-7-3-0.yml5
-rw-r--r--changelogs/unreleased/zj-improve-gitaly-pb.yml5
-rw-r--r--changelogs/unreleased/zj-pool-repository-creation.yml5
-rw-r--r--changelogs/unreleased/zj-remove-broken-storage.yml5
-rw-r--r--config/gitlab.yml.example2
-rw-r--r--config/initializers/zz_metrics.rb (renamed from config/initializers/8_metrics.rb)3
-rw-r--r--danger/documentation/Dangerfile2
-rw-r--r--db/fixtures/development/24_forks.rb6
-rw-r--r--db/migrate/20181006004100_import_common_metrics_nginx_vts.rb2
-rw-r--r--db/migrate/20181031145139_add_protected_ci_variables_to_application_settings.rb17
-rw-r--r--db/post_migrate/20181219145520_migrate_cluster_configure_worker_sidekiq_queue.rb15
-rw-r--r--db/schema.rb3
-rw-r--r--doc/administration/gitaly/index.md84
-rw-r--r--doc/administration/index.md1
-rw-r--r--doc/api/jobs.md140
-rw-r--r--doc/ci/examples/devops_and_game_dev_with_gitlab_ci_cd/index.md2
-rw-r--r--doc/ci/merge_request_pipelines/index.md31
-rw-r--r--doc/ci/yaml/README.md19
-rw-r--r--doc/development/contributing/merge_request_workflow.md1
-rw-r--r--doc/development/instrumentation.md2
-rw-r--r--doc/install/kubernetes/gitlab_chart.md3
-rw-r--r--doc/ssh/README.md21
-rw-r--r--doc/update/upgrader.md91
-rw-r--r--doc/user/abuse_reports.md53
-rw-r--r--doc/user/admin_area/abuse_reports.md31
-rw-r--r--doc/user/admin_area/img/abuse_report_blocked_user.pngbin0 -> 13821 bytes
-rw-r--r--doc/user/admin_area/img/abuse_reports_page.pngbin0 -> 215813 bytes
-rw-r--r--doc/user/group/clusters/index.md4
-rw-r--r--doc/user/index.md1
-rw-r--r--doc/user/profile/account/delete_account.md3
-rw-r--r--doc/user/project/clusters/index.md29
-rw-r--r--doc/user/project/clusters/serverless/img/function-execution.pngbin0 -> 223762 bytes
-rw-r--r--doc/user/project/clusters/serverless/img/serverless-page.pngbin11829 -> 194708 bytes
-rw-r--r--doc/user/project/clusters/serverless/index.md107
-rw-r--r--doc/user/project/img/releases.pngbin0 -> 43612 bytes
-rw-r--r--doc/user/project/releases.md12
-rw-r--r--doc/user/project/repository/index.md2
-rw-r--r--lib/api/entities.rb2
-rw-r--r--lib/api/groups.rb2
-rw-r--r--lib/api/helpers.rb8
-rw-r--r--lib/gitlab/fake_application_settings.rb4
-rw-r--r--lib/gitlab/git/object_pool.rb2
-rw-r--r--lib/gitlab/gitaly_client.rb42
-rw-r--r--lib/gitlab/gitaly_client/object_pool_service.rb5
-rw-r--r--lib/gitlab/import_export/command_line_util.rb8
-rw-r--r--lib/gitlab/json_cache.rb87
-rw-r--r--lib/gitlab/object_hierarchy.rb (renamed from lib/gitlab/group_hierarchy.rb)52
-rw-r--r--lib/gitlab/upgrader.rb111
-rw-r--r--lib/gitlab/utils/override.rb109
-rw-r--r--lib/tasks/gitlab/storage.rake10
-rw-r--r--locale/gitlab.pot57
-rw-r--r--package.json2
-rw-r--r--qa/qa/page/base.rb8
-rw-r--r--qa/qa/page/main/login.rb12
-rw-r--r--qa/qa/page/main/menu.rb8
-rw-r--r--qa/qa/support/page/logging.rb10
-rw-r--r--qa/spec/page/logging_spec.rb7
-rw-r--r--spec/controllers/groups/group_members_controller_spec.rb10
-rw-r--r--spec/controllers/projects/clusters_controller_spec.rb4
-rw-r--r--spec/controllers/projects/deploy_keys_controller_spec.rb36
-rw-r--r--spec/controllers/projects/issues_controller_spec.rb4
-rw-r--r--spec/controllers/projects/merge_requests_controller_spec.rb31
-rw-r--r--spec/controllers/projects/project_members_controller_spec.rb18
-rw-r--r--spec/controllers/projects/refs_controller_spec.rb14
-rw-r--r--spec/controllers/projects/tags/releases_controller_spec.rb7
-rw-r--r--spec/factories/notes.rb15
-rw-r--r--spec/factories/pool_repositories.rb4
-rw-r--r--spec/features/admin/admin_disables_git_access_protocol_spec.rb59
-rw-r--r--spec/features/groups/show_spec.rb4
-rw-r--r--spec/features/issues/user_creates_issue_spec.rb6
-rw-r--r--spec/features/projects/clusters/gcp_spec.rb2
-rw-r--r--spec/features/projects/jobs_spec.rb8
-rw-r--r--spec/features/users/overview_spec.rb6
-rw-r--r--spec/fixtures/api/schemas/entities/issuable_sidebar_todo.json8
-rw-r--r--spec/fixtures/api/schemas/entities/issue_sidebar.json54
-rw-r--r--spec/fixtures/api/schemas/entities/issue_sidebar_extras.json18
-rw-r--r--spec/fixtures/api/schemas/entities/merge_request_basic.json6
-rw-r--r--spec/fixtures/api/schemas/entities/merge_request_sidebar.json56
-rw-r--r--spec/fixtures/api/schemas/entities/merge_request_sidebar_extras.json21
-rw-r--r--spec/fixtures/api/schemas/public_api/v4/milestone.json22
-rw-r--r--spec/fixtures/api/schemas/public_api/v4/milestones.json21
-rw-r--r--spec/fixtures/symlink_export.tar.gzbin0 -> 435 bytes
-rw-r--r--spec/helpers/issuables_helper_spec.rb36
-rw-r--r--spec/helpers/projects_helper_spec.rb110
-rw-r--r--spec/initializers/zz_metrics_spec.rb (renamed from spec/initializers/8_metrics_spec.rb)2
-rw-r--r--spec/javascripts/ci_variable_list/ci_variable_list_spec.js2
-rw-r--r--spec/javascripts/diffs/store/utils_spec.js20
-rw-r--r--spec/javascripts/environments/environment_terminal_button_spec.js48
-rw-r--r--spec/javascripts/fixtures/blob.rb9
-rw-r--r--spec/javascripts/fixtures/boards.rb7
-rw-r--r--spec/javascripts/fixtures/branches.rb3
-rw-r--r--spec/javascripts/fixtures/clusters.rb3
-rw-r--r--spec/javascripts/fixtures/commit.rb2
-rw-r--r--spec/javascripts/fixtures/deploy_keys.rb6
-rw-r--r--spec/javascripts/fixtures/groups.rb6
-rw-r--r--spec/javascripts/fixtures/issues.rb6
-rw-r--r--spec/javascripts/fixtures/jobs.rb13
-rw-r--r--spec/javascripts/fixtures/labels.rb12
-rw-r--r--spec/javascripts/fixtures/merge_requests.rb12
-rw-r--r--spec/javascripts/fixtures/merge_requests_diffs.rb4
-rw-r--r--spec/javascripts/fixtures/pipeline_schedules.rb6
-rw-r--r--spec/javascripts/fixtures/pipelines.rb6
-rw-r--r--spec/javascripts/fixtures/projects.rb15
-rw-r--r--spec/javascripts/fixtures/prometheus_service.rb3
-rw-r--r--spec/javascripts/fixtures/services.rb3
-rw-r--r--spec/javascripts/fixtures/snippet.rb2
-rw-r--r--spec/javascripts/fixtures/todos.rb6
-rw-r--r--spec/javascripts/fixtures/u2f.rb2
-rw-r--r--spec/javascripts/jobs/components/artifacts_block_spec.js13
-rw-r--r--spec/javascripts/jobs/components/sidebar_spec.js8
-rw-r--r--spec/javascripts/notes/components/noteable_discussion_spec.js73
-rw-r--r--spec/javascripts/releases/components/app_spec.js79
-rw-r--r--spec/javascripts/releases/components/release_block_spec.js34
-rw-r--r--spec/javascripts/releases/mock_data.js128
-rw-r--r--spec/javascripts/releases/store/actions_spec.js98
-rw-r--r--spec/javascripts/releases/store/helpers.js6
-rw-r--r--spec/javascripts/releases/store/mutations_spec.js47
-rw-r--r--spec/javascripts/sidebar/mock_data.js4
-rw-r--r--spec/javascripts/sidebar/sidebar_mediator_spec.js4
-rw-r--r--spec/javascripts/vue_shared/components/user_popover/user_popover_spec.js14
-rw-r--r--spec/lib/gitlab/bare_repository_import/importer_spec.rb2
-rw-r--r--spec/lib/gitlab/gitaly_client_spec.rb82
-rw-r--r--spec/lib/gitlab/import_export/command_line_util_spec.rb38
-rw-r--r--spec/lib/gitlab/import_export/file_importer_spec.rb13
-rw-r--r--spec/lib/gitlab/json_cache_spec.rb401
-rw-r--r--spec/lib/gitlab/object_hierarchy_spec.rb (renamed from spec/lib/gitlab/group_hierarchy_spec.rb)10
-rw-r--r--spec/lib/gitlab/project_authorizations_spec.rb4
-rw-r--r--spec/lib/gitlab/prometheus/query_variables_spec.rb4
-rw-r--r--spec/lib/gitlab/upgrader_spec.rb40
-rw-r--r--spec/lib/gitlab/utils/override_spec.rb32
-rw-r--r--spec/mailers/notify_spec.rb12
-rw-r--r--spec/migrations/migrate_cluster_configure_worker_sidekiq_queue_spec.rb68
-rw-r--r--spec/models/broadcast_message_spec.rb23
-rw-r--r--spec/models/clusters/platforms/kubernetes_spec.rb4
-rw-r--r--spec/models/concerns/avatarable_spec.rb37
-rw-r--r--spec/models/concerns/discussion_on_diff_spec.rb10
-rw-r--r--spec/models/diff_note_spec.rb17
-rw-r--r--spec/models/namespace_spec.rb54
-rw-r--r--spec/models/pool_repository_spec.rb21
-rw-r--r--spec/models/project_spec.rb77
-rw-r--r--spec/models/user_spec.rb4
-rw-r--r--spec/policies/group_policy_spec.rb8
-rw-r--r--spec/requests/api/events_spec.rb4
-rw-r--r--spec/requests/api/files_spec.rb12
-rw-r--r--spec/requests/openid_connect_spec.rb2
-rw-r--r--spec/requests/rack_attack_global_spec.rb2
-rw-r--r--spec/serializers/entity_date_helper_spec.rb12
-rw-r--r--spec/serializers/environment_entity_spec.rb30
-rw-r--r--spec/serializers/issue_serializer_spec.rb10
-rw-r--r--spec/serializers/merge_request_basic_serializer_spec.rb16
-rw-r--r--spec/serializers/merge_request_serializer_spec.rb12
-rw-r--r--spec/services/clusters/gcp/finalize_creation_service_spec.rb6
-rw-r--r--spec/services/clusters/update_service_spec.rb2
-rw-r--r--spec/services/groups/create_service_spec.rb4
-rw-r--r--spec/services/groups/nested_create_service_spec.rb2
-rw-r--r--spec/services/groups/transfer_service_spec.rb2
-rw-r--r--spec/services/notification_service_spec.rb8
-rw-r--r--spec/services/projects/after_rename_service_spec.rb20
-rw-r--r--spec/services/projects/transfer_service_spec.rb20
-rw-r--r--spec/spec_helper.rb2
-rw-r--r--spec/support/api/boards_shared_examples.rb15
-rw-r--r--spec/support/api/milestones_shared_examples.rb31
-rw-r--r--spec/support/api/scopes/read_user_shared_examples.rb2
-rw-r--r--spec/support/api/time_tracking_shared_examples.rb22
-rw-r--r--spec/support/controllers/githubish_import_controller_shared_examples.rb34
-rw-r--r--spec/support/features/variable_list_shared_examples.rb46
-rw-r--r--spec/support/helpers/git_http_helpers.rb8
-rw-r--r--spec/support/helpers/graphql_helpers.rb2
-rw-r--r--spec/support/import_export/export_file_helper.rb2
-rw-r--r--spec/support/issuables_requiring_filter_shared_examples.rb2
-rw-r--r--spec/support/shared_examples/controllers/uploads_actions_shared_examples.rb11
-rw-r--r--spec/support/shared_examples/milestone_tabs_examples.rb2
-rw-r--r--spec/support/shared_examples/requests/api/diff_discussions.rb8
-rw-r--r--spec/support/shared_examples/requests/api/discussions.rb16
-rw-r--r--spec/support/shared_examples/requests/api/merge_requests_list.rb16
-rw-r--r--spec/support/shared_examples/requests/api/notes.rb26
-rw-r--r--spec/support/shared_examples/requests/api/resolvable_discussions.rb16
-rw-r--r--spec/tasks/gitlab/storage_rake_spec.rb14
-rw-r--r--spec/views/notify/changed_milestone_email.html.haml_spec.rb35
-rw-r--r--spec/views/projects/merge_requests/show.html.haml_spec.rb5
-rw-r--r--spec/workers/cluster_configure_worker_spec.rb (renamed from spec/workers/cluster_platform_configure_worker_spec.rb)2
-rw-r--r--spec/workers/cluster_provision_worker_spec.rb4
-rw-r--r--spec/workers/object_pool/destroy_worker_spec.rb31
-rw-r--r--spec/workers/stuck_merge_jobs_worker_spec.rb3
-rw-r--r--yarn.lock17
591 files changed, 4396 insertions, 2931 deletions
diff --git a/.gitlab/CODEOWNERS.disabled b/.gitlab/CODEOWNERS.disabled
index 82e914a502f..b9f886c1d47 100644
--- a/.gitlab/CODEOWNERS.disabled
+++ b/.gitlab/CODEOWNERS.disabled
@@ -1,6 +1,6 @@
# Backend Maintainers are the default for all ruby files
-*.rb @ayufan @DouweM @dzaporozhets @grzesiek @nick.thomas @rspeicher @rymai @smcgivern
-*.rake @ayufan @DouweM @dzaporozhets @grzesiek @nick.thomas @rspeicher @rymai @smcgivern
+*.rb @ayufan @dbalexandre @DouweM @dzaporozhets @godfat @grzesiek @nick.thomas @rspeicher @rymai @smcgivern
+*.rake @ayufan @dbalexandre @DouweM @dzaporozhets @godfat @grzesiek @nick.thomas @rspeicher @rymai @smcgivern
# Technical writing team are the default reviewers for everything in `doc/`
/doc/ @axil @marcia
diff --git a/.gitlab/issue_templates/Feature proposal.md b/.gitlab/issue_templates/Feature proposal.md
index ad517f0457d..639a236631d 100644
--- a/.gitlab/issue_templates/Feature proposal.md
+++ b/.gitlab/issue_templates/Feature proposal.md
@@ -4,7 +4,7 @@
### Target audience
-<!--- For whom are we doing this? Include either a persona from https://design.gitlab.com/#/getting-started/personas or define a specific company role. e.a. "Release Manager" or "Security Analyst" -->
+<!--- For whom are we doing this? Include either a persona from https://design.gitlab.com/getting-started/personas or define a specific company role. e.a. "Release Manager" or "Security Analyst" -->
### Further details
diff --git a/CHANGELOG.md b/CHANGELOG.md
index a51ac887aed..b4fa22ad70e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,290 @@
documentation](doc/development/changelog.md) for instructions on adding your own
entry.
+## 11.6.0 (2018-12-22)
+
+### Security (24 changes, 1 of them is from the community)
+
+- Fix possible XSS attack in Markdown urls with spaces. !2599
+- Update rack to 2.0.6 (for QA environments). !23171 (Takuya Noguchi)
+- Bump nokogiri, loofah, and rack gems for security updates. !23204
+- Encrypt runners tokens. !23412
+- Encrypt CI/CD builds authentication tokens. !23436
+- Configure mermaid to not render HTML content in diagrams.
+- Fix a possible symlink time of check to time of use race condition in GitLab Pages.
+- Removed ability to see private group names when the group id is entered in the url.
+- Fix stored XSS for Environments.
+- Fix persistent symlink in project import.
+- Fixed ability of guest users to edit/delete comments on locked or confidential issues.
+- Fixed ability to comment on locked/confidential issues.
+- Fix CRLF vulnerability in Project hooks.
+- Fix SSRF in project integrations.
+- Resolve reflected XSS in Ouath authorize window.
+- Restrict Personal Access Tokens to API scope on web requests.
+- Provide email notification when a user changes their email address.
+- Don't expose confidential information in commit message list.
+- Validate LFS hrefs before downloading them.
+- Do not follow redirects in Prometheus service when making http requests to the configured api url.
+- Escape user fullname while rendering autocomplete template to prevent XSS.
+- Redact sensitive information on gitlab-workhorse log.
+- Fix milestone promotion authorization check.
+- Prevent a path traversal attack on global file templates.
+
+### Removed (1 change)
+
+- Remove obsolete gitlab_shell rake tasks. !22417
+
+### Fixed (86 changes, 13 of them are from the community)
+
+- Remove limit of 100 when searching repository code. !8671
+- Show error message when attempting to reopen an MR and there is an open MR for the same branch. !16447 (Akos Gyimesi)
+- Fix a bug where internal email pattern wasn't respected. !22516
+- Fix project selector consistency in groups issues / MRs / boards pages. !22612 (Heinrich Lee Yu)
+- Add empty state for graphs with no values. !22630
+- Fix navigating by unresolved discussions on Merge Request page. !22789
+- Fix "merged with [commit]" info for merge requests being merged automatically by other actions. !22794
+- Fixing regression issues on pages settings and details. !22821
+- Remove duplicate primary button in dashboard snippets on small viewports. !22902 (George Tsiolis)
+- Fix API::Namespaces routing to accept namepaces with dots. !22912
+- Switch kubernetes:active with checking in Auto-DevOps.gitlab-ci.yml. !22929
+- Avoid Gitaly RPC errors when fetching diff stats. !22995
+- Removes promote to group label for anonymous user. !23042 (Jacopo Beschi @jacopo-beschi)
+- Fix enabling project deploy key for admins. !23043
+- Align issue status label and confidential icon. !23046 (George Tsiolis)
+- Fix default sorting for subgroups and projects list. !23058 (Jacopo Beschi @jacopo-beschi)
+- Hashed Storage: allow migration to be retried in partially migrated projects. !23087
+- Fix line height of numbers in file blame view. !23090 (Johann Hubert Sonntagbauer)
+- Fixes an issue where default values from models would override values set in the interface (e.g. users would be set to external even though their emails matches the internal email address pattern). !23114
+- Remove display of local Sidekiq process in /admin/sidekiq. !23118
+- Fix unrelated deployment status in MR widget. !23175
+- Respect confirmed flag on secondary emails. !23181
+- Restrict member access level to be higher than that of any parent group. !23226
+- Return real deployment status to frontend. !23270
+- Handle force_remove_source_branch when creating merge request. !23281
+- Avoid creating invalid refs using rugged, shelling out for writing refs. !23286
+- Remove needless auto-capitalization on Wiki page titles. !23288
+- Modify the wording for the knative cluster application to match upstream. !23289 (Chris Baumbauer)
+- Change container width for project import. !23318 (George Tsiolis)
+- Validate chunk size when persist. !23341
+- Resolve Main navbar is broken in certain viewport widths. !23348
+- Gracefully handle references with null bytes. !23365
+- Display commit ID for commit diff discussion on merge request. !23370
+- Pass commit when posting diff discussions. !23371
+- Fix flash notice styling for fluid layout. !23382
+- Add monkey patch to unicorn to fix eof? problem. !23385
+- Commits API: Preserve file content in move operations if unspecified. !23387
+- Disable password autocomplete in mirror form fill. !23402
+- Fix "protected branches only" checkbox not set properly at init. !23409
+- Support RSA and ECDSA algorithms in Omniauth JWT provider. !23411 (Michael Tsyganov)
+- Make KUBECONFIG nil if KUBE_TOKEN is nil. !23414
+- Allow search and sort users at same time on admin users page. !23439
+- Fix: Unstar icon button is misaligned. !23444
+- Fix error when searching for group issues with priority or popularity sort. !23445
+- Fix Order By dropdown menu styling in tablet and mobile screens. !23446
+- Fix collapsing discussion replies. !23462
+- Gracefully handle unknown/invalid GPG keys. !23492
+- Fix multiple commits shade overlapping vertical discussion line. !23515
+- Use read_repository scope on read-only files API. !23534
+- Avoid 500's when serializing legacy diff notes. !23544
+- Fix web hook functionality when the database encryption key is too short. !23573
+- Hide Knative from group cluster applications until supported. !23577
+- Add top padding for nested environment items loading icon. !23580 (George Tsiolis)
+- Improve help and validation sections of maximum build timeout inputs. !23586
+- Fix milestone select in issue sidebar of issue boards. !23625
+- Fix gitlab:web_hook tasks. !23635
+- Avoid caching BroadcastMessage as an ActiveRecord object. !23662
+- Only allow strings in URL::Sanitizer.valid?. !23675
+- Fix a frozen string error in app/mailers/notify.rb. !23683
+- Fix a frozen string error in lib/gitlab/utils.rb. !23690
+- Fix MR resolved discussion counts being too low. !23710
+- Fix a potential frozen string error in app/mailers/notify.rb. !23728
+- Remove unnecessary div from MarkdownField to apply list styles correctly. !23733
+- Display reply field if resolved discussion has no replies. !23801
+- Restore kubernetes:active in Auto-DevOps.gitlab-ci.yml (reverts 22929). !23826
+- Fix mergeUrlParams with fragment URL. !54218 (Thomas Holder)
+- Fixed multiple diff line discussions not expanding.
+- Fixed diff files expanding not loading commit content.
+- Fixed styling of image comment badges on commits.
+- Resolve possible cherry pick API race condition.
+- When user clicks linenumber in MR changes, highlight that line.
+- Remove old webhook logs after 90 days, as documented, instead of after 2.
+- Add an external IP address to the knative cluster application page. (Chris Baumbauer)
+- Fixed duplicate discussions getting added to diff lines.
+- Fix deadlock on ChunkedIO.
+- Show tree collapse button for merge request commit diffs.
+- Use approximate count for big tables for usage statistics.
+- Lock writes to trace stream.
+- Ensure that SVG sprite icons are properly rendered in IE11.
+- Make new branch form fields' fonts consistent.
+- Open first 10 merge request files in IDE.
+- Prevent user from navigating away from file edit without commit.
+- Prevent empty button being rendered in empty state.
+- Adds margins between tags when a job is stuck.
+- Fix Image Lazy Loader for some older browsers.
+- Correctly styles tags in sidebar for job page.
+
+### Changed (34 changes, 9 of them are from the community)
+
+- Include new link in breadcrumb for issues, merge requests, milestones, and labels. !18515 (George Tsiolis)
+- Allow sorting issues and MRs in reverse order. !21438
+- Design improvements to project overview page. !22196
+- Remove auto deactivation when failed to create a pipeline via pipeline schedules. !22243
+- Use group clusters when deploying (DeploymentPlatform). !22308
+- Improve initial discussion rendering performance. !22607
+- removes partially matching of No Label filter and makes it case-insensitive. !22622 (Jacopo Beschi @jacopo-beschi)
+- Use search bar for filtering in dashboard issues / MRs. !22641 (Heinrich Lee Yu)
+- Show different empty state for filtered issues and MRs. !22775 (Heinrich Lee Yu)
+- Relocate JSONWebToken::HMACToken from EE. !22906
+- Resolve Add border around the repository file tree. !23018
+- Change breadcrumb title for contribution charts. !23071 (George Tsiolis)
+- Update environments metrics empty state. !23074 (George Tsiolis)
+- Refine cursor positioning in Markdown Editor for wrap tags. !23085 (Johann Hubert Sonntagbauer)
+- Use reports syntax for SAST in Auto DevOps. !23163
+- SystemCheck: Use a more reliable way to detect current Ruby version. !23291
+- Changed frontmatter filtering to support YAML, JSON, TOML, and arbitrary languages. !23331 (Travis Miller)
+- Don't remove failed install pods after installing GitLab managed applications. !23350
+- Expose merge request pipeline variables. !23398
+- Scope default MR search in WebIDE dropdown to current project. !23400
+- Show user contributions in correct timezone within user profile. !23419
+- Redesign of MR header sections (CE). !23465
+- Auto DevOps: Add echo for each branch of the deploy() function where we run helm upgrade. !23499
+- Updates service to update Kubernetes project namespaces and restricted service account if present. !23525
+- Adjust divider margin to comply with design specs. !23548
+- Adjust dropdown item and header padding to comply with design specs. !23552
+- Truncate merge request titles with periods instead of ellipsis. !23558
+- Remove close icon from projects dropdown in issue boards. !23567
+- Change dropdown divider color to gray-200 (#dfdfdf). !23592
+- Define the default value for only/except policies. !23765
+- Don't show Memory Usage for unmerged MRs.
+- reorder notification settings by noisy-ness. (C.J. Jameson)
+- Changed merge request filtering to be by path instead of name.
+- Make diff file headers sticky.
+
+### Performance (22 changes, 6 of them are from the community)
+
+- Upgrade to Ruby 2.5.3. !2806
+- Removes all the irrelevant code and columns that were migrated from the Project table over to the ProjectImportState table. !21497
+- Approximate counting strategy with TABLESAMPLE. !22650
+- Replace tooltip directive with gl-tooltip diretive in badges, cycle analytics, and diffs. !22770 (George Tsiolis)
+- Validate foreign keys being created and indexed for column with _id. !22808
+- Remove monospace extend. !23089 (George Tsiolis)
+- Use Nokogiri as the ActiveSupport XML backend. !23136
+- Improve memory performance by reducing dirty pages after fork(). !23169
+- Add partial index for ci_builds on project_id and status. !23268
+- Reduce Gitaly calls in projects dashboard. !23307
+- Batch load only data from same repository when lazy object is accessed. !23309
+- Add index for events on project_id and created_at. !23354
+- Remove index for notes on updated_at. !23356
+- Improves performance of Project#readme_url by caching the README path. !23357
+- Populate MR metrics with events table information (migration). !23564
+- Remove unused data from discussions endpoint. !23570
+- Speed up issue board lists in groups with many projects.
+- Use cached size when passing artifacts to Runner.
+- Enable even more frozen string for lib/gitlab. (gfyoung)
+- Enable even more frozen string in lib/gitlab/**/*.rb. (gfyoung)
+- Enable even more frozen string in lib/gitlab/**/*.rb. (gfyoung)
+- Enable even more frozen string for lib/gitlab. (gfyoung)
+
+### Added (32 changes, 13 of them are from the community)
+
+- Add ability to create group level clusters and install gitlab managed applications. !22450
+- Creates /create_merge_request quickaction. !22485 (Jacopo Beschi @jacopo-beschi)
+- Filter by None/Any for labels in issues/mrs API. !22622 (Jacopo Beschi @jacopo-beschi)
+- Chat message push notifications now include links back to GitLab branches. !22651 (Tony Castrogiovanni)
+- Added feature flag to signal content headers detection by Workhorse. !22667
+- Add Discord integration. !22684 (@blackst0ne)
+- Upgrade helm to 2.11.0 and upgrade on every install. !22693
+- Add knative client to kubeclient library. !22968 (cab105)
+- Allow SSH public-key authentication for push mirroring. !22982
+- Allow deleting a Pipeline via the API. !22988
+- #40635: Adds support for cert-manager. !23036 (Amit Rathi)
+- WebIDE: Pressing Ctrl-Enter while typing on the commit message now performs the commit action. !23049 (Thomas Pathier)
+- Adds Any option to label filters. !23111 (Jacopo Beschi @jacopo-beschi)
+- Added glob for CI changes detection. !23128 (Kirill Zaitsev)
+- Add model and relation to store repo full path in database. !23143
+- Add ability to render suggestions. !23147
+- Introduce Knative and Serverless Components. !23174 (Chris Baumbauer)
+- Use BFG object maps to clean projects. !23189
+- Merge request pipelines. !23217
+- Extended user centric tooltips on issue and MR page. !23231
+- Add a rebase API endpoint for merge requests. !23296
+- Add config to prohibit impersonation. !23338
+- Merge request pipeline tag, and adds tags to pipeline view. !23364
+- #52753: HTTPS for JupyterHub installation. !23479 (Amit Rathi)
+- Fill project_repositories for hashed storage projects. !23482
+- Ability to override email for cert-manager. !23503 (Amit Rathi)
+- Allow public forks to be deduplicated. !23508
+- Pipeline trigger variable values are hidden in the UI by default. Maintainers have the option to reveal them. !23518 (jhampton)
+- Add new endpoint to download single artifact file for a ref. !23538
+- Log and pass correlation-id between Unicorn, Sidekiq and Gitaly.
+- Allow user to scroll to top of tab on MR page.
+- Adds states to the deployment widget.
+
+### Other (54 changes, 30 of them are from the community)
+
+- Switch to Rails 5. !21492
+- Migration to write fullpath in all repository configs. !22322
+- Rails5: env is deprecated and will be removed from Rails 5.1. !22626 (Jasper Maes)
+- Update haml_lint to 0.28.0. !22660 (Takuya Noguchi)
+- Update ffaker to 2.10.0. !22661 (Takuya Noguchi)
+- Drop gcp_clusters table. !22713
+- Upgrade minimum required Git version to 2.18.0. !22803
+- Adds new icon size to Vue icon component. !22899
+- Make sure there's only one slash as path separator. !22954
+- Show HTTP response code for Kubernetes errors. !22964
+- Update config map for gitlab managed application if already present on install. !22969
+- Drop default value on status column in deployments table. !22971
+- UI improvements to user's profile. !22977
+- Update asana to 0.8.1. !23039 (Takuya Noguchi)
+- Update asciidoctor to 1.5.8. !23047 (Takuya Noguchi)
+- Make auto-generated icons for subgroups in the breadcrumb dropdown display as a circle. !23062 (Thomas Pathier)
+- Make reply shortcut only quote selected discussion text. !23096 (Thomas Pathier)
+- Fix typo in notebook props. !23103 (George Tsiolis)
+- Fix typos in lib. !23106 (George Tsiolis)
+- Rename diffs store variable. !23123 (George Tsiolis)
+- Fix overlapping navbar separator and overflowing navbar dropdown on small displays. !23126 (Thomas Pathier)
+- Show what RPC is called in the performance bar. !23140
+- Updated Gitaly to v0.133.0. !23148
+- Rails5: Passing a class as a value in an Active Record query is deprecated. !23164 (Jasper Maes)
+- Fix project identicon aligning Harry Kiselev. !23166 (Harry Kiselev)
+- Fix horizontal scrollbar overlapping on horizontal scrolling-tabs. !23167 (Harry Kiselev)
+- Fix bottom paddings of profile header and some markup updates of profile. !23168 (Harry Kiselev)
+- Fixes to AWS documentation spelling and grammar. !23198 (Brendan O'Leary)
+- Adds a PHILOSOPHY.md which references GitLab Product Handbook. !23200
+- Externalize strings from `/app/views/invites`. !23205 (Tao Wang)
+- Externalize strings from `/app/views/project/runners`. !23208 (Tao Wang)
+- Fix typo for scheduled pipeline. !23218 (Davy Defaud)
+- Force content disposition attachment to several endpoints. !23223
+- Upgrade kubeclient to 4.0.0. !23261 (Praveen Arimbrathodiyil @pravi)
+- Update used version of Runner Helm Chart to 0.1.38. !23304
+- render :nothing option is deprecated, Use head method to respond with empty response body. !23311 (Jasper Maes)
+- Passing an argument to force an association to reload is now deprecated. !23334 (Jasper Maes)
+- Externalize strings from `/app/views/snippets`. !23351 (Tao Wang)
+- Fix deprecation: You are passing an instance of ActiveRecord::Base to. !23369 (Jasper Maes)
+- Resolve status emoji being replaced by avatar on mobile. !23408
+- Fix deprecation: render :text is deprecated because it does not actually render a text/plain response. !23425 (Jasper Maes)
+- Fix lack of documentation on how to fetch a snippet's content using API. !23448 (Colin Leroy)
+- Upgrade GitLab Workhorse to v7.3.0. !23489
+- Fallback to admin KUBE_TOKEN for project clusters only. !23527
+- Update used version of Runner Helm Chart to 0.1.39. !23633
+- Show primary button when all labels are prioritized. !23648 (George Tsiolis)
+- Upgrade workhorse to 7.6.0. !23694
+- Upgrade Gitaly to v1.7.1 for correlation-id logging. !23732
+- Fix due date test. !23845
+- Remove unused project method. !54103 (George Tsiolis)
+- Uses new gitlab-ui components in Jobs and Pipelines components.
+- Replaces tooltip directive with the new gl-tooltip directive for consistency in some ci/cd code.
+- Bump gpgme gem version from 2.0.13 to 2.0.18. (asaparov)
+- Enable Rubocop on lib/gitlab. (gfyoung)
+
+
+## 11.5.5 (2018-12-20)
+
+### Security (1 change)
+
+- Fix persistent symlink in project import.
+
+
## 11.5.3 (2018-12-06)
### Security (1 change)
@@ -628,6 +912,13 @@ entry.
- Check frozen string in style builds. (gfyoung)
+## 11.3.14 (2018-12-20)
+
+### Security (1 change)
+
+- Fix persistent symlink in project import.
+
+
## 11.3.13 (2018-12-13)
### Security (1 change)
diff --git a/GITALY_SERVER_VERSION b/GITALY_SERVER_VERSION
index f8e233b2733..0eed1a29efd 100644
--- a/GITALY_SERVER_VERSION
+++ b/GITALY_SERVER_VERSION
@@ -1 +1 @@
-1.9.0
+1.12.0
diff --git a/Gemfile b/Gemfile
index 6ada5eede27..5ddd1f614f1 100644
--- a/Gemfile
+++ b/Gemfile
@@ -130,7 +130,7 @@ gem 'asciidoctor-plantuml', '0.0.8'
gem 'rouge', '~> 3.1'
gem 'truncato', '~> 0.7.9'
gem 'bootstrap_form', '~> 2.7.0'
-gem 'nokogiri', '~> 1.8.2'
+gem 'nokogiri', '~> 1.8.4'
gem 'escape_utils', '~> 1.1'
# Calendar rendering
@@ -165,7 +165,7 @@ gem 'acts-as-taggable-on', '~> 5.0'
gem 'sidekiq', '~> 5.2.1'
gem 'sidekiq-cron', '~> 0.6.0'
gem 'redis-namespace', '~> 1.6.0'
-gem 'gitlab-sidekiq-fetcher', '~> 0.1.0', require: 'sidekiq-reliable-fetch'
+gem 'gitlab-sidekiq-fetcher', '~> 0.4.0', require: 'sidekiq-reliable-fetch'
# Cron Parser
gem 'rufus-scheduler', '~> 3.4'
@@ -419,7 +419,7 @@ group :ed25519 do
end
# Gitaly GRPC client
-gem 'gitaly-proto', '~> 1.3.0', require: 'gitaly'
+gem 'gitaly-proto', '~> 1.5.0', require: 'gitaly'
gem 'grpc', '~> 1.15.0'
gem 'google-protobuf', '~> 3.6'
diff --git a/Gemfile.lock b/Gemfile.lock
index 6d21089c82c..f2d265d835c 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -274,13 +274,13 @@ GEM
gettext_i18n_rails (>= 0.7.1)
po_to_json (>= 1.0.0)
rails (>= 3.2.0)
- gitaly-proto (1.3.0)
+ gitaly-proto (1.5.0)
grpc (~> 1.0)
github-markup (1.7.0)
gitlab-default_value_for (3.1.1)
activerecord (>= 3.2.0, < 6.0)
gitlab-markup (1.6.5)
- gitlab-sidekiq-fetcher (0.1.0)
+ gitlab-sidekiq-fetcher (0.4.0)
sidekiq (~> 5)
gitlab-styles (2.4.1)
rubocop (~> 0.54.0)
@@ -1008,11 +1008,11 @@ DEPENDENCIES
gettext (~> 3.2.2)
gettext_i18n_rails (~> 1.8.0)
gettext_i18n_rails_js (~> 1.3)
- gitaly-proto (~> 1.3.0)
+ gitaly-proto (~> 1.5.0)
github-markup (~> 1.7.0)
gitlab-default_value_for (~> 3.1.1)
gitlab-markup (~> 1.6.5)
- gitlab-sidekiq-fetcher (~> 0.1.0)
+ gitlab-sidekiq-fetcher (~> 0.4.0)
gitlab-styles (~> 2.4)
gitlab_omniauth-ldap (~> 2.0.4)
gon (~> 6.2)
@@ -1059,7 +1059,7 @@ DEPENDENCIES
nakayoshi_fork (~> 0.0.4)
net-ldap
net-ssh (~> 5.0)
- nokogiri (~> 1.8.2)
+ nokogiri (~> 1.8.4)
oauth2 (~> 1.4)
octokit (~> 4.9)
omniauth (~> 1.8)
diff --git a/PROCESS.md b/PROCESS.md
index 800b268b2a6..5aafbd33daf 100644
--- a/PROCESS.md
+++ b/PROCESS.md
@@ -58,6 +58,18 @@ their contributions accepted by meeting our [Definition of done][done].
What you can expect from them is described at https://about.gitlab.com/roles/merge-request-coach/.
+### Milestones on community contribution issues
+
+The milestone of an issue that is currently being worked on by a community contributor
+should not be set to a named GitLab milestone (e.g. 11.7, 11.8), until the associated
+merge request is very close to being merged, and we will likely know in which named
+GitLab milestone the issue will land. There are many factors that influence when
+a community contributor finishes an issue, or even at all. So we should set this
+milestone only when we have more certainty.
+
+Note this only applies to issues currently assigned to community contributors. For
+issues assigned to GitLabbers, we are [ambitious in assigning milestones to issues](https://about.gitlab.com/direction/#how-we-plan-releases).
+
## Assigning issues
If an issue is complex and needs the attention of a specific person, assignment is a good option but assigning issues might discourage other people from contributing to that issue. We need all the contributions we can get so this should never be discouraged. Also, an assigned person might not have time for a few weeks, so others should feel free to takeover.
diff --git a/VERSION b/VERSION
index 35167c50c26..74f35bff618 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-11.6.0-pre
+11.7.0-pre
diff --git a/app/assets/javascripts/api.js b/app/assets/javascripts/api.js
index 7607c4b3b79..d1396b6c4bc 100644
--- a/app/assets/javascripts/api.js
+++ b/app/assets/javascripts/api.js
@@ -29,6 +29,7 @@ const Api = {
commitPipelinesPath: '/:project_id/commit/:sha/pipelines',
branchSinglePath: '/api/:version/projects/:id/repository/branches/:branch',
createBranchPath: '/api/:version/projects/:id/repository/branches',
+ releasesPath: '/api/:version/projects/:id/releases',
group(groupId, callback) {
const url = Api.buildUrl(Api.groupPath).replace(':id', groupId);
@@ -307,6 +308,12 @@ const Api = {
});
},
+ releases(id) {
+ const url = Api.buildUrl(this.releasesPath).replace(':id', encodeURIComponent(id));
+
+ return axios.get(url);
+ },
+
buildUrl(url) {
let urlRoot = '';
if (gon.relative_url_root != null) {
diff --git a/app/assets/javascripts/ci_variable_list/ci_variable_list.js b/app/assets/javascripts/ci_variable_list/ci_variable_list.js
index ee0f7cda189..5b20fa141cd 100644
--- a/app/assets/javascripts/ci_variable_list/ci_variable_list.js
+++ b/app/assets/javascripts/ci_variable_list/ci_variable_list.js
@@ -36,7 +36,9 @@ export default class VariableList {
},
protected: {
selector: '.js-ci-variable-input-protected',
- default: 'false',
+ // use `attr` instead of `data` as we don't want the value to be
+ // converted. we need the value as a string.
+ default: $('.js-ci-variable-input-protected').attr('data-default'),
},
environment_scope: {
// We can't use a `.js-` class here because
diff --git a/app/assets/javascripts/diffs/components/inline_diff_view.vue b/app/assets/javascripts/diffs/components/inline_diff_view.vue
index 9310e2b7ca9..e781397214d 100644
--- a/app/assets/javascripts/diffs/components/inline_diff_view.vue
+++ b/app/assets/javascripts/diffs/components/inline_diff_view.vue
@@ -49,7 +49,7 @@ export default {
:is-bottom="index + 1 === diffLinesLength"
/>
<inline-diff-comment-row
- :key="`icr-${index}`"
+ :key="`icr-${line.line_code || index}`"
:diff-file-hash="diffFile.file_hash"
:line="line"
:help-page-path="helpPagePath"
diff --git a/app/assets/javascripts/diffs/components/parallel_diff_view.vue b/app/assets/javascripts/diffs/components/parallel_diff_view.vue
index e6bc0daebb3..1bf693380db 100644
--- a/app/assets/javascripts/diffs/components/parallel_diff_view.vue
+++ b/app/assets/javascripts/diffs/components/parallel_diff_view.vue
@@ -43,14 +43,14 @@ export default {
<tbody>
<template v-for="(line, index) in diffLines">
<parallel-diff-table-row
- :key="index"
+ :key="line.line_code"
:file-hash="diffFile.file_hash"
:context-lines-path="diffFile.context_lines_path"
:line="line"
:is-bottom="index + 1 === diffLinesLength"
/>
<parallel-diff-comment-row
- :key="`dcr-${index}`"
+ :key="`dcr-${line.line_code || index}`"
:line="line"
:diff-file-hash="diffFile.file_hash"
:line-index="index"
diff --git a/app/assets/javascripts/diffs/store/utils.js b/app/assets/javascripts/diffs/store/utils.js
index cbaa0e26395..2fe20551642 100644
--- a/app/assets/javascripts/diffs/store/utils.js
+++ b/app/assets/javascripts/diffs/store/utils.js
@@ -196,6 +196,15 @@ export function trimFirstCharOfLineContent(line = {}) {
return parsedLine;
}
+function getLineCode({ left, right }, index) {
+ if (left && left.line_code) {
+ return left.line_code;
+ } else if (right && right.line_code) {
+ return right.line_code;
+ }
+ return index;
+}
+
// This prepares and optimizes the incoming diff data from the server
// by setting up incremental rendering and removing unneeded data
export function prepareDiffData(diffData) {
@@ -208,6 +217,8 @@ export function prepareDiffData(diffData) {
const linesLength = file.parallel_diff_lines.length;
for (let u = 0; u < linesLength; u += 1) {
const line = file.parallel_diff_lines[u];
+
+ line.line_code = getLineCode(line, u);
if (line.left) {
line.left = trimFirstCharOfLineContent(line.left);
line.left.hasForm = false;
diff --git a/app/assets/javascripts/environments/components/environment_item.vue b/app/assets/javascripts/environments/components/environment_item.vue
index cd2f46fd07a..f44806d82a6 100644
--- a/app/assets/javascripts/environments/components/environment_item.vue
+++ b/app/assets/javascripts/environments/components/environment_item.vue
@@ -14,6 +14,7 @@ import MonitoringButtonComponent from './environment_monitoring.vue';
import CommitComponent from '../../vue_shared/components/commit.vue';
import eventHub from '../event_hub';
import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
+import { CLUSTER_TYPE } from '~/clusters/constants';
/**
* Environment Item Component
@@ -85,6 +86,15 @@ export default {
},
/**
+ * Hide group cluster features which are not currently implemented.
+ *
+ * @returns {Boolean}
+ */
+ disableGroupClusterFeatures() {
+ return this.model && this.model.cluster_type === CLUSTER_TYPE.GROUP;
+ },
+
+ /**
* Returns whether the environment can be stopped.
*
* @returns {Boolean}
@@ -547,6 +557,7 @@ export default {
<terminal-button-component
v-if="model && model.terminal_path"
:terminal-path="model.terminal_path"
+ :disabled="disableGroupClusterFeatures"
/>
<rollback-component
diff --git a/app/assets/javascripts/environments/components/environment_terminal_button.vue b/app/assets/javascripts/environments/components/environment_terminal_button.vue
index 83727caad16..6d74d136a94 100644
--- a/app/assets/javascripts/environments/components/environment_terminal_button.vue
+++ b/app/assets/javascripts/environments/components/environment_terminal_button.vue
@@ -19,6 +19,11 @@ export default {
required: false,
default: '',
},
+ disabled: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
},
computed: {
title() {
@@ -33,6 +38,7 @@ export default {
:title="title"
:aria-label="title"
:href="terminalPath"
+ :class="{ disabled: disabled }"
class="btn terminal-button d-none d-sm-none d-md-block"
>
<icon name="terminal" />
diff --git a/app/assets/javascripts/jobs/components/artifacts_block.vue b/app/assets/javascripts/jobs/components/artifacts_block.vue
index 309b7427b9e..0bce860df91 100644
--- a/app/assets/javascripts/jobs/components/artifacts_block.vue
+++ b/app/assets/javascripts/jobs/components/artifacts_block.vue
@@ -28,27 +28,29 @@ export default {
</script>
<template>
<div class="block">
- <div class="title">{{ s__('Job|Job artifacts') }}</div>
+ <div class="title font-weight-bold">{{ s__('Job|Job artifacts') }}</div>
- <p v-if="isExpired" class="js-artifacts-removed build-detail-row">
- {{ s__('Job|The artifacts were removed') }}
+ <p
+ v-if="isExpired || willExpire"
+ :class="{
+ 'js-artifacts-removed': isExpired,
+ 'js-artifacts-will-be-removed': willExpire,
+ }"
+ class="build-detail-row"
+ >
+ <span v-if="isExpired">{{ s__('Job|The artifacts were removed') }}</span>
+ <span v-if="willExpire">{{ s__('Job|The artifacts will be removed') }}</span>
+ <timeago-tooltip v-if="artifact.expire_at" :time="artifact.expire_at" />
</p>
- <p v-else-if="willExpire" class="js-artifacts-will-be-removed build-detail-row">
- {{ s__('Job|The artifacts will be removed in') }}
- </p>
-
- <timeago-tooltip v-if="artifact.expire_at" :time="artifact.expire_at" />
-
- <div class="btn-group d-flex" role="group">
+ <div class="btn-group d-flex prepend-top-10" role="group">
<gl-link
v-if="artifact.keep_path"
:href="artifact.keep_path"
class="js-keep-artifacts btn btn-sm btn-default"
data-method="post"
+ >{{ s__('Job|Keep') }}</gl-link
>
- {{ s__('Job|Keep') }}
- </gl-link>
<gl-link
v-if="artifact.download_path"
@@ -56,17 +58,15 @@ export default {
class="js-download-artifacts btn btn-sm btn-default"
download
rel="nofollow"
+ >{{ s__('Job|Download') }}</gl-link
>
- {{ s__('Job|Download') }}
- </gl-link>
<gl-link
v-if="artifact.browse_path"
:href="artifact.browse_path"
class="js-browse-artifacts btn btn-sm btn-default"
+ >{{ s__('Job|Browse') }}</gl-link
>
- {{ s__('Job|Browse') }}
- </gl-link>
</div>
</div>
</template>
diff --git a/app/assets/javascripts/jobs/components/commit_block.vue b/app/assets/javascripts/jobs/components/commit_block.vue
index 3b9c61bd48c..e0f55518eef 100644
--- a/app/assets/javascripts/jobs/components/commit_block.vue
+++ b/app/assets/javascripts/jobs/components/commit_block.vue
@@ -31,12 +31,12 @@ export default {
block: !isLastBlock,
}"
>
- <p>
- {{ __('Commit') }}
+ <p class="append-bottom-5">
+ <span class="font-weight-bold">{{ __('Commit') }}</span>
- <gl-link :href="commit.commit_path" class="js-commit-sha commit-sha link-commit">{{
- commit.short_id
- }}</gl-link>
+ <gl-link :href="commit.commit_path" class="js-commit-sha commit-sha link-commit">
+ {{ commit.short_id }}
+ </gl-link>
<clipboard-button
:text="commit.short_id"
@@ -44,11 +44,14 @@ export default {
css-class="btn btn-clipboard btn-transparent"
/>
- <gl-link v-if="mergeRequest" :href="mergeRequest.path" class="js-link-commit link-commit"
- >!{{ mergeRequest.iid }}</gl-link
- >
+ <span v-if="mergeRequest">
+ {{ __('in') }}
+ <gl-link :href="mergeRequest.path" class="js-link-commit link-commit"
+ >!{{ mergeRequest.iid }}</gl-link
+ >
+ </span>
</p>
- <p class="build-light-text append-bottom-0">{{ commit.title }}</p>
+ <p class="append-bottom-0">{{ commit.title }}</p>
</div>
</template>
diff --git a/app/assets/javascripts/jobs/components/sidebar.vue b/app/assets/javascripts/jobs/components/sidebar.vue
index 934ecd0e3ec..ad3e7dabc79 100644
--- a/app/assets/javascripts/jobs/components/sidebar.vue
+++ b/app/assets/javascripts/jobs/components/sidebar.vue
@@ -110,22 +110,20 @@ export default {
<aside class="right-sidebar build-sidebar" data-offset-top="101" data-spy="affix">
<div class="sidebar-container">
<div class="blocks-container">
- <div class="block">
- <strong class="inline prepend-top-8"> {{ job.name }} </strong>
+ <div class="block d-flex align-items-center">
+ <h4 class="flex-grow-1 prepend-top-8 m-0">{{ job.name }}</h4>
<gl-link
v-if="job.retry_path"
:class="retryButtonClass"
:href="job.retry_path"
data-method="post"
rel="nofollow"
+ >{{ __('Retry') }}</gl-link
>
- {{ __('Retry') }}
- </gl-link>
<gl-link
v-if="job.terminal_path"
:href="job.terminal_path"
- class="js-terminal-link pull-right btn btn-primary
- btn-inverted visible-md-block visible-lg-block"
+ class="js-terminal-link pull-right btn btn-primary btn-inverted visible-md-block visible-lg-block"
target="_blank"
>
{{ __('Debug') }} <icon name="external-link" />
@@ -133,8 +131,7 @@ export default {
<gl-button
:aria-label="__('Toggle Sidebar')"
type="button"
- class="btn btn-blank gutter-toggle
- float-right d-block d-md-none js-sidebar-build-toggle"
+ class="btn btn-blank gutter-toggle float-right d-block d-md-none js-sidebar-build-toggle"
@click="toggleSidebar"
>
<i aria-hidden="true" data-hidden="true" class="fa fa-angle-double-right"></i>
@@ -145,25 +142,18 @@ export default {
v-if="job.new_issue_path"
:href="job.new_issue_path"
class="js-new-issue btn btn-success btn-inverted"
+ >{{ __('New issue') }}</gl-link
>
- {{ __('New issue') }}
- </gl-link>
<gl-link
v-if="job.retry_path"
:href="job.retry_path"
class="js-retry-job btn btn-inverted-secondary"
data-method="post"
rel="nofollow"
+ >{{ __('Retry') }}</gl-link
>
- {{ __('Retry') }}
- </gl-link>
</div>
<div :class="{ block: renderBlock }">
- <p v-if="job.merge_request" class="build-detail-row js-job-mr">
- <span class="build-light-text"> {{ __('Merge Request:') }} </span>
- <gl-link :href="job.merge_request.path"> !{{ job.merge_request.iid }} </gl-link>
- </p>
-
<detail-row
v-if="job.duration"
:value="duration"
@@ -198,10 +188,10 @@ export default {
title="Coverage"
/>
<p v-if="job.tags.length" class="build-detail-row js-job-tags">
- <span class="build-light-text"> {{ __('Tags:') }} </span>
- <span v-for="(tag, i) in job.tags" :key="i" class="badge badge-primary">
- {{ tag }}
- </span>
+ <span class="font-weight-bold">{{ __('Tags:') }}</span>
+ <span v-for="(tag, i) in job.tags" :key="i" class="badge badge-primary mr-1">{{
+ tag
+ }}</span>
</p>
<div v-if="job.cancel_path" class="btn-group prepend-top-5" role="group">
@@ -210,9 +200,8 @@ export default {
class="js-cancel-job btn btn-sm btn-default"
data-method="post"
rel="nofollow"
+ >{{ __('Cancel') }}</gl-link
>
- {{ __('Cancel') }}
- </gl-link>
</div>
</div>
diff --git a/app/assets/javascripts/jobs/components/sidebar_detail_row.vue b/app/assets/javascripts/jobs/components/sidebar_detail_row.vue
index 77be295e802..b826007ec2c 100644
--- a/app/assets/javascripts/jobs/components/sidebar_detail_row.vue
+++ b/app/assets/javascripts/jobs/components/sidebar_detail_row.vue
@@ -34,8 +34,7 @@ export default {
</script>
<template>
<p class="build-detail-row">
- <span v-if="hasTitle" class="build-light-text"> {{ title }}: </span> {{ value }}
-
+ <span v-if="hasTitle" class="font-weight-bold">{{ title }}:</span> {{ value }}
<span v-if="hasHelpURL" class="help-button float-right">
<gl-link :href="helpUrl" target="_blank" rel="noopener noreferrer nofollow">
<i class="fa fa-question-circle" aria-hidden="true"></i>
diff --git a/app/assets/javascripts/jobs/components/stages_dropdown.vue b/app/assets/javascripts/jobs/components/stages_dropdown.vue
index 90482500bbf..7f79e92067f 100644
--- a/app/assets/javascripts/jobs/components/stages_dropdown.vue
+++ b/app/assets/javascripts/jobs/components/stages_dropdown.vue
@@ -38,11 +38,11 @@ export default {
<div class="block-last dropdown">
<ci-icon :status="pipeline.details.status" class="vertical-align-middle" />
- {{ __('Pipeline') }}
- <a :href="pipeline.path" class="js-pipeline-path link-commit"> #{{ pipeline.id }} </a>
+ <span class="font-weight-bold">{{ __('Pipeline') }}</span>
+ <a :href="pipeline.path" class="js-pipeline-path link-commit">#{{ pipeline.id }}</a>
<template v-if="hasRef">
{{ __('from') }}
- <a :href="pipeline.ref.path" class="link-commit ref-name"> {{ pipeline.ref.name }} </a>
+ <a :href="pipeline.ref.path" class="link-commit ref-name">{{ pipeline.ref.name }}</a>
</template>
<button
diff --git a/app/assets/javascripts/jobs/components/trigger_block.vue b/app/assets/javascripts/jobs/components/trigger_block.vue
index 3cd3b743108..997737b3e23 100644
--- a/app/assets/javascripts/jobs/components/trigger_block.vue
+++ b/app/assets/javascripts/jobs/components/trigger_block.vue
@@ -43,23 +43,24 @@ export default {
<template>
<div class="build-widget block">
- <h4 class="title">{{ __('Trigger') }}</h4>
-
<p
v-if="trigger.short_token"
class="js-short-token"
- :class="{ 'append-bottom-0': !hasVariables }"
+ :class="{ 'append-bottom-5': hasVariables, 'append-bottom-0': !hasVariables }"
>
- <span class="build-light-text"> {{ __('Token') }} </span> {{ trigger.short_token }}
+ <span class="font-weight-bold">{{ __('Trigger token:') }}</span> {{ trigger.short_token }}
</p>
<template v-if="hasVariables">
<p class="trigger-variables-btn-container">
- <span class="build-light-text"> {{ __('Variables:') }} </span>
+ <span class="font-weight-bold">{{ __('Trigger variables:') }}</span>
- <gl-button v-if="hasValues" class="group js-reveal-variables" @click="toggleValues">
- {{ getToggleButtonText }}
- </gl-button>
+ <gl-button
+ v-if="hasValues"
+ class="btn-sm group js-reveal-variables trigger-variables-btn"
+ @click="toggleValues"
+ >{{ getToggleButtonText }}</gl-button
+ >
</p>
<table class="js-build-variables trigger-build-variables">
diff --git a/app/assets/javascripts/lib/utils/text_markdown.js b/app/assets/javascripts/lib/utils/text_markdown.js
index c095a017866..1254ec798a6 100644
--- a/app/assets/javascripts/lib/utils/text_markdown.js
+++ b/app/assets/javascripts/lib/utils/text_markdown.js
@@ -82,7 +82,7 @@ export function insertMarkdownText({
tag,
cursorOffset,
blockTag,
- selected,
+ selected = '',
wrap,
select,
}) {
@@ -212,7 +212,7 @@ export function addMarkdownListeners(form) {
blockTag: $this.data('mdBlock'),
wrap: !$this.data('mdPrepend'),
select: $this.data('mdSelect'),
- tagContent: $this.data('mdTagContent').toString(),
+ tagContent: $this.data('mdTagContent'),
});
});
}
diff --git a/app/assets/javascripts/notes/components/noteable_discussion.vue b/app/assets/javascripts/notes/components/noteable_discussion.vue
index d9dd08a7a6b..7c3f5d00308 100644
--- a/app/assets/javascripts/notes/components/noteable_discussion.vue
+++ b/app/assets/javascripts/notes/components/noteable_discussion.vue
@@ -178,31 +178,32 @@ export default {
commitId = `<span class="commit-sha">${truncateSha(commitId)}</span>`;
}
- let text = s__('MergeRequests|started a discussion');
+ const {
+ for_commit: isForCommit,
+ diff_discussion: isDiffDiscussion,
+ active: isActive,
+ } = this.discussion;
- if (this.discussion.for_commit) {
+ let text = s__('MergeRequests|started a discussion');
+ if (isForCommit) {
text = s__(
'MergeRequests|started a discussion on commit %{linkStart}%{commitId}%{linkEnd}',
);
- } else if (this.discussion.diff_discussion) {
- if (this.discussion.active) {
- text = s__('MergeRequests|started a discussion on %{linkStart}the diff%{linkEnd}');
- } else {
- text = s__(
- 'MergeRequests|started a discussion on %{linkStart}an old version of the diff%{linkEnd}',
- );
- }
+ } else if (isDiffDiscussion && commitId) {
+ text = isActive
+ ? s__('MergeRequests|started a discussion on commit %{linkStart}%{commitId}%{linkEnd}')
+ : s__(
+ 'MergeRequests|started a discussion on an outdated change in commit %{linkStart}%{commitId}%{linkEnd}',
+ );
+ } else if (isDiffDiscussion) {
+ text = isActive
+ ? s__('MergeRequests|started a discussion on %{linkStart}the diff%{linkEnd}')
+ : s__(
+ 'MergeRequests|started a discussion on %{linkStart}an old version of the diff%{linkEnd}',
+ );
}
- return sprintf(
- text,
- {
- commitId,
- linkStart,
- linkEnd,
- },
- false,
- );
+ return sprintf(text, { commitId, linkStart, linkEnd }, false);
},
diffLine() {
if (this.discussion.diff_discussion && this.discussion.truncated_diff_lines) {
diff --git a/app/assets/javascripts/pages/projects/releases/index/index.js b/app/assets/javascripts/pages/projects/releases/index/index.js
new file mode 100644
index 00000000000..c183fbb9610
--- /dev/null
+++ b/app/assets/javascripts/pages/projects/releases/index/index.js
@@ -0,0 +1,3 @@
+import initReleases from '~/releases';
+
+document.addEventListener('DOMContentLoaded', initReleases);
diff --git a/app/assets/javascripts/releases/components/app.vue b/app/assets/javascripts/releases/components/app.vue
new file mode 100644
index 00000000000..0ad5ee2915c
--- /dev/null
+++ b/app/assets/javascripts/releases/components/app.vue
@@ -0,0 +1,82 @@
+<script>
+import { mapState, mapActions } from 'vuex';
+import { GlLoadingIcon, GlEmptyState } from '@gitlab/ui';
+import ReleaseBlock from './release_block.vue';
+
+export default {
+ name: 'ReleasesApp',
+ components: {
+ GlLoadingIcon,
+ GlEmptyState,
+ ReleaseBlock,
+ },
+ props: {
+ projectId: {
+ type: String,
+ required: true,
+ },
+ documentationLink: {
+ type: String,
+ required: true,
+ },
+ illustrationPath: {
+ type: String,
+ required: true,
+ },
+ },
+ computed: {
+ ...mapState(['isLoading', 'releases', 'hasError']),
+ shouldRenderEmptyState() {
+ return !this.releases.length && !this.hasError && !this.isLoading;
+ },
+ shouldRenderSuccessState() {
+ return this.releases.length && !this.isLoading && !this.hasError;
+ },
+ },
+ created() {
+ this.fetchReleases(this.projectId);
+ },
+ methods: {
+ ...mapActions(['fetchReleases']),
+ },
+};
+</script>
+<template>
+ <div class="prepend-top-default">
+ <gl-loading-icon v-if="isLoading" :size="2" class="js-loading prepend-top-20" />
+
+ <gl-empty-state
+ v-else-if="shouldRenderEmptyState"
+ class="js-empty-state"
+ :title="__('Getting started with releases')"
+ :svg-path="illustrationPath"
+ :description="
+ __(
+ 'Releases mark specific points in a project\'s development history, communicate information about the type of change, and deliver on prepared, often compiled, versions of the software to be reused elsewhere. Currently, releases can only be created through the API.',
+ )
+ "
+ :primary-button-link="documentationLink"
+ :primary-button-text="__('Open Documentation')"
+ />
+
+ <div v-else-if="shouldRenderSuccessState" class="js-success-state">
+ <release-block
+ v-for="(release, index) in releases"
+ :key="release.tag_name"
+ :release="release"
+ :class="{ 'linked-card': releases.length > 1 && index !== releases.length - 1 }"
+ />
+ </div>
+ </div>
+</template>
+<style>
+.linked-card::after {
+ width: 1px;
+ content: ' ';
+ border: 1px solid #e5e5e5;
+ height: 17px;
+ top: 100%;
+ position: absolute;
+ left: 32px;
+}
+</style>
diff --git a/app/assets/javascripts/releases/components/release_block.vue b/app/assets/javascripts/releases/components/release_block.vue
index bd65a225d8f..34b97826cdb 100644
--- a/app/assets/javascripts/releases/components/release_block.vue
+++ b/app/assets/javascripts/releases/components/release_block.vue
@@ -1,4 +1,5 @@
<script>
+import _ from 'underscore';
import { GlTooltipDirective, GlLink } from '@gitlab/ui';
import Icon from '~/vue_shared/components/icon.vue';
import UserAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue';
@@ -17,52 +18,16 @@ export default {
},
mixins: [timeagoMixin],
props: {
- name: {
- type: String,
- required: true,
- },
- tag: {
- type: String,
- required: true,
- },
- commit: {
- type: Object,
- required: true,
- },
- description: {
- type: String,
- required: false,
- default: '',
- },
- author: {
+ release: {
type: Object,
required: true,
- },
- createdAt: {
- type: String,
- required: false,
- default: '',
- },
- assetsCount: {
- type: Number,
- required: false,
- default: 0,
- },
- sources: {
- type: Array,
- required: false,
- default: () => [],
- },
- links: {
- type: Array,
- required: false,
- default: () => [],
+ default: () => ({}),
},
},
computed: {
releasedTimeAgo() {
return sprintf('released %{time}', {
- time: this.timeFormated(this.createdAt),
+ time: this.timeFormated(this.release.created_at),
});
},
userImageAltDescription() {
@@ -70,13 +35,25 @@ export default {
? sprintf("%{username}'s avatar", { username: this.author.username })
: null;
},
+ commit() {
+ return this.release.commit || {};
+ },
+ assets() {
+ return this.release.assets || {};
+ },
+ author() {
+ return this.release.author || {};
+ },
+ hasAuthor() {
+ return _.isEmpty(this.author);
+ },
},
};
</script>
<template>
<div class="card">
<div class="card-body">
- <h2 class="card-title mt-0">{{ name }}</h2>
+ <h2 class="card-title mt-0">{{ release.name }}</h2>
<div class="card-subtitle d-flex flex-wrap text-secondary">
<div class="append-right-8">
@@ -86,15 +63,17 @@ export default {
<div class="append-right-8">
<icon name="tag" class="align-middle" />
- <span v-gl-tooltip.bottom :title="__('Tag')">{{ tag }}</span>
+ <span v-gl-tooltip.bottom :title="__('Tag')">{{ release.tag_name }}</span>
</div>
<div class="append-right-4">
&bull;
- <span v-gl-tooltip.bottom :title="tooltipTitle(createdAt)">{{ releasedTimeAgo }}</span>
+ <span v-gl-tooltip.bottom :title="tooltipTitle(release.created_at)">{{
+ releasedTimeAgo
+ }}</span>
</div>
- <div class="d-flex">
+ <div v-if="hasAuthor" class="d-flex">
by
<user-avatar-link
class="prepend-left-4"
@@ -106,20 +85,25 @@ export default {
</div>
</div>
- <div class="card-text prepend-top-default">
+ <div
+ v-if="assets.links.length || assets.sources.length"
+ Sclass="card-text prepend-top-default"
+ >
<b>
- {{ __('Assets') }} <span class="js-assets-count badge badge-pill">{{ assetsCount }}</span>
+ {{ __('Assets') }}
+ <span class="js-assets-count badge badge-pill">{{ assets.count }}</span>
</b>
- <ul class="pl-0 mb-0 prepend-top-8 list-unstyled js-assets-list">
- <li v-for="link in links" :key="link.name" class="append-bottom-8">
+ <ul v-if="assets.links.length" class="pl-0 mb-0 prepend-top-8 list-unstyled js-assets-list">
+ <li v-for="link in assets.links" :key="link.name" class="append-bottom-8">
<gl-link v-gl-tooltip.bottom :title="__('Download asset')" :href="link.url">
- <icon name="package" class="align-middle append-right-4" /> {{ link.name }}
+ <icon name="package" class="align-middle append-right-4 align-text-bottom" />
+ {{ link.name }}
</gl-link>
</li>
</ul>
- <div class="dropdown">
+ <div v-if="assets.sources.length" class="dropdown">
<button
type="button"
class="btn btn-link"
@@ -132,14 +116,14 @@ export default {
</button>
<div class="js-sources-dropdown dropdown-menu">
- <li v-for="asset in sources" :key="asset.url">
+ <li v-for="asset in assets.sources" :key="asset.url">
<gl-link :href="asset.url">{{ __('Download') }} {{ asset.format }}</gl-link>
</li>
</div>
</div>
</div>
- <div class="card-text prepend-top-default"><div v-html="description"></div></div>
+ <div class="card-text prepend-top-default"><div v-html="release.description_html"></div></div>
</div>
</div>
</template>
diff --git a/app/assets/javascripts/releases/index.js b/app/assets/javascripts/releases/index.js
new file mode 100644
index 00000000000..adbed3cb8e2
--- /dev/null
+++ b/app/assets/javascripts/releases/index.js
@@ -0,0 +1,24 @@
+import Vue from 'vue';
+import App from './components/app.vue';
+import createStore from './store';
+
+export default () => {
+ const element = document.getElementById('js-releases-page');
+
+ return new Vue({
+ el: element,
+ store: createStore(),
+ components: {
+ App,
+ },
+ render(createElement) {
+ return createElement('app', {
+ props: {
+ projectId: element.dataset.projectId,
+ documentationLink: element.dataset.documentationPath,
+ illustrationPath: element.dataset.illustrationPath,
+ },
+ });
+ },
+ });
+};
diff --git a/app/assets/javascripts/releases/store/actions.js b/app/assets/javascripts/releases/store/actions.js
new file mode 100644
index 00000000000..baa2251403e
--- /dev/null
+++ b/app/assets/javascripts/releases/store/actions.js
@@ -0,0 +1,37 @@
+import * as types from './mutation_types';
+import createFlash from '~/flash';
+import { __ } from '~/locale';
+import api from '~/api';
+
+/**
+ * Commits a mutation to update the state while the main endpoint is being requested.
+ */
+export const requestReleases = ({ commit }) => commit(types.REQUEST_RELEASES);
+
+/**
+ * Fetches the main endpoint.
+ * Will dispatch requestNamespace action before starting the request.
+ * Will dispatch receiveNamespaceSuccess if the request is successfull
+ * Will dispatch receiveNamesapceError if the request returns an error
+ *
+ * @param {String} projectId
+ */
+export const fetchReleases = ({ dispatch }, projectId) => {
+ dispatch('requestReleases');
+
+ api
+ .releases(projectId)
+ .then(({ data }) => dispatch('receiveReleasesSuccess', data))
+ .catch(() => dispatch('receiveReleasesError'));
+};
+
+export const receiveReleasesSuccess = ({ commit }, data) =>
+ commit(types.RECEIVE_RELEASES_SUCCESS, data);
+
+export const receiveReleasesError = ({ commit }) => {
+ commit(types.RECEIVE_RELEASES_ERROR);
+ createFlash(__('An error occured while fetching the releases. Please try again.'));
+};
+
+// prevent babel-plugin-rewire from generating an invalid default during karma tests
+export default () => {};
diff --git a/app/assets/javascripts/releases/store/index.js b/app/assets/javascripts/releases/store/index.js
new file mode 100644
index 00000000000..968b94f0e0d
--- /dev/null
+++ b/app/assets/javascripts/releases/store/index.js
@@ -0,0 +1,14 @@
+import Vue from 'vue';
+import Vuex from 'vuex';
+import state from './state';
+import * as actions from './actions';
+import mutations from './mutations';
+
+Vue.use(Vuex);
+
+export default () =>
+ new Vuex.Store({
+ actions,
+ mutations,
+ state: state(),
+ });
diff --git a/app/assets/javascripts/releases/store/mutation_types.js b/app/assets/javascripts/releases/store/mutation_types.js
new file mode 100644
index 00000000000..a74bf15c515
--- /dev/null
+++ b/app/assets/javascripts/releases/store/mutation_types.js
@@ -0,0 +1,3 @@
+export const REQUEST_RELEASES = 'REQUEST_RELEASES';
+export const RECEIVE_RELEASES_SUCCESS = 'RECEIVE_RELEASES_SUCCESS';
+export const RECEIVE_RELEASES_ERROR = 'RECEIVE_RELEASES_ERROR';
diff --git a/app/assets/javascripts/releases/store/mutations.js b/app/assets/javascripts/releases/store/mutations.js
new file mode 100644
index 00000000000..b97dc6cb0ab
--- /dev/null
+++ b/app/assets/javascripts/releases/store/mutations.js
@@ -0,0 +1,37 @@
+import * as types from './mutation_types';
+
+export default {
+ /**
+ * Sets isLoading to true while the request is being made.
+ * @param {Object} state
+ */
+ [types.REQUEST_RELEASES](state) {
+ state.isLoading = true;
+ },
+
+ /**
+ * Sets isLoading to false.
+ * Sets hasError to false.
+ * Sets the received data
+ * @param {Object} state
+ * @param {Object} data
+ */
+ [types.RECEIVE_RELEASES_SUCCESS](state, data) {
+ state.hasError = false;
+ state.isLoading = false;
+ state.releases = data;
+ },
+
+ /**
+ * Sets isLoading to false.
+ * Sets hasError to true.
+ * Resets the data
+ * @param {Object} state
+ * @param {Object} data
+ */
+ [types.RECEIVE_RELEASES_ERROR](state) {
+ state.isLoading = false;
+ state.releases = [];
+ state.hasError = true;
+ },
+};
diff --git a/app/assets/javascripts/releases/store/state.js b/app/assets/javascripts/releases/store/state.js
new file mode 100644
index 00000000000..bf25e651c99
--- /dev/null
+++ b/app/assets/javascripts/releases/store/state.js
@@ -0,0 +1,5 @@
+export default () => ({
+ isLoading: false,
+ hasError: false,
+ releases: [],
+});
diff --git a/app/assets/javascripts/right_sidebar.js b/app/assets/javascripts/right_sidebar.js
index 225e21ad322..9a0cdc02952 100644
--- a/app/assets/javascripts/right_sidebar.js
+++ b/app/assets/javascripts/right_sidebar.js
@@ -79,11 +79,12 @@ Sidebar.prototype.sidebarToggleClicked = function(e, triggered) {
Sidebar.prototype.toggleTodo = function(e) {
var $btnText, $this, $todoLoading, ajaxType, url;
$this = $(e.currentTarget);
- ajaxType = $this.attr('data-delete-path') ? 'delete' : 'post';
- if ($this.attr('data-delete-path')) {
- url = '' + $this.attr('data-delete-path');
+ ajaxType = $this.data('deletePath') ? 'delete' : 'post';
+
+ if ($this.data('deletePath')) {
+ url = '' + $this.data('deletePath');
} else {
- url = '' + $this.data('url');
+ url = '' + $this.data('createPath');
}
$this.tooltip('hide');
@@ -119,14 +120,14 @@ Sidebar.prototype.todoUpdateDone = function(data) {
.removeClass('is-loading')
.enable()
.attr('aria-label', $el.data(`${attrPrefix}Text`))
- .attr('data-delete-path', deletePath)
- .attr('title', $el.data(`${attrPrefix}Text`));
+ .attr('title', $el.data(`${attrPrefix}Text`))
+ .data('deletePath', deletePath);
if ($el.hasClass('has-tooltip')) {
$el.tooltip('_fixTitle');
}
- if ($el.data(`${attrPrefix}Icon`)) {
+ if (typeof $el.data('isCollapsed') !== 'undefined') {
$elText.html($el.data(`${attrPrefix}Icon`));
} else {
$elText.text($el.data(`${attrPrefix}Text`));
diff --git a/app/assets/javascripts/serverless/components/functions.vue b/app/assets/javascripts/serverless/components/functions.vue
index 7874a7b6b6a..349e14670b1 100644
--- a/app/assets/javascripts/serverless/components/functions.vue
+++ b/app/assets/javascripts/serverless/components/functions.vue
@@ -81,7 +81,7 @@ export default {
</p>
<ul>
<li>Your repository does not have a corresponding <code>serverless.yml</code> file.</li>
- <li>Your <code>gitlab-ci.yml</code> file is not properly configured.</li>
+ <li>Your <code>.gitlab-ci.yml</code> file is not properly configured.</li>
<li>
The functions listed in the <code>serverless.yml</code> file don't match the namespace
of your cluster.
diff --git a/app/assets/javascripts/sidebar/stores/sidebar_store.js b/app/assets/javascripts/sidebar/stores/sidebar_store.js
index f20cc6d8cca..7b8b4c5d856 100644
--- a/app/assets/javascripts/sidebar/stores/sidebar_store.js
+++ b/app/assets/javascripts/sidebar/stores/sidebar_store.js
@@ -71,7 +71,7 @@ export default class SidebarStore {
}
findAssignee(findAssignee) {
- return this.assignees.filter(assignee => assignee.id === findAssignee.id)[0];
+ return this.assignees.find(assignee => assignee.id === findAssignee.id);
}
removeAssignee(removeAssignee) {
diff --git a/app/assets/javascripts/vue_shared/components/user_popover/user_popover.vue b/app/assets/javascripts/vue_shared/components/user_popover/user_popover.vue
index fad1a2f3f56..d24fe1b547e 100644
--- a/app/assets/javascripts/vue_shared/components/user_popover/user_popover.vue
+++ b/app/assets/javascripts/vue_shared/components/user_popover/user_popover.vue
@@ -1,6 +1,5 @@
<script>
import { GlPopover, GlSkeletonLoading } from '@gitlab/ui';
-import { __, sprintf } from '~/locale';
import UserAvatarImage from '../user_avatar/user_avatar_image.vue';
import { glEmojiTag } from '../../../emoji';
@@ -28,23 +27,6 @@ export default {
},
},
computed: {
- jobLine() {
- if (this.user.bio && this.user.organization) {
- return sprintf(
- __('%{bio} at %{organization}'),
- {
- bio: this.user.bio,
- organization: this.user.organization,
- },
- false,
- );
- } else if (this.user.bio) {
- return this.user.bio;
- } else if (this.user.organization) {
- return this.user.organization;
- }
- return null;
- },
statusHtml() {
if (this.user.status.emoji && this.user.status.message) {
return `${glEmojiTag(this.user.status.emoji)} ${this.user.status.message}`;
@@ -86,7 +68,8 @@ export default {
<gl-skeleton-loading v-else :lines="1" class="animation-container-small mb-1" />
</div>
<div class="text-secondary">
- {{ jobLine }}
+ <div v-if="user.bio" class="js-bio">{{ user.bio }}</div>
+ <div v-if="user.organization" class="js-organization">{{ user.organization }}</div>
<gl-skeleton-loading
v-if="jobInfoIsLoading"
:lines="1"
diff --git a/app/assets/stylesheets/framework/files.scss b/app/assets/stylesheets/framework/files.scss
index 3ac7b6b704b..037a5adfb7e 100644
--- a/app/assets/stylesheets/framework/files.scss
+++ b/app/assets/stylesheets/framework/files.scss
@@ -24,7 +24,7 @@
}
}
- &:not(.use-csslab) table {
+ table {
@extend .table;
}
diff --git a/app/assets/stylesheets/framework/highlight.scss b/app/assets/stylesheets/framework/highlight.scss
index 73533571a2f..946f575ac13 100644
--- a/app/assets/stylesheets/framework/highlight.scss
+++ b/app/assets/stylesheets/framework/highlight.scss
@@ -42,7 +42,6 @@
padding: 10px;
text-align: right;
float: left;
- line-height: 1;
a {
font-family: $monospace-font;
@@ -69,3 +68,9 @@
}
}
}
+
+// Vertically aligns <table> line numbers (eg. blame view)
+// see https://gitlab.com/gitlab-org/gitlab-ce/issues/54048
+td.line-numbers {
+ line-height: 1;
+}
diff --git a/app/assets/stylesheets/framework/modal.scss b/app/assets/stylesheets/framework/modal.scss
index 7e30747963a..95291b4a9ad 100644
--- a/app/assets/stylesheets/framework/modal.scss
+++ b/app/assets/stylesheets/framework/modal.scss
@@ -25,8 +25,8 @@
&.w-100 {
// after upgrading to Bootstrap 4.2 we can use $modal-header-padding-x here
// https://github.com/twbs/bootstrap/pull/26976
- margin-right: -2rem;
- padding-right: 2rem;
+ margin-right: -28px;
+ padding-right: 28px;
}
}
diff --git a/app/assets/stylesheets/framework/variables.scss b/app/assets/stylesheets/framework/variables.scss
index ce5aaa8963c..343c09b4a3e 100644
--- a/app/assets/stylesheets/framework/variables.scss
+++ b/app/assets/stylesheets/framework/variables.scss
@@ -198,7 +198,7 @@ $well-light-text-color: #5b6169;
$gl-font-size: 14px;
$gl-font-size-xs: 11px;
$gl-font-size-small: 12px;
-$gl-font-size-medium: 1.43rem;
+$gl-font-size-medium: 20px;
$gl-font-size-large: 16px;
$gl-font-weight-normal: 400;
$gl-font-weight-bold: 600;
diff --git a/app/assets/stylesheets/framework/variables_overrides.scss b/app/assets/stylesheets/framework/variables_overrides.scss
index 5ca76bb6c5a..069f45bff49 100644
--- a/app/assets/stylesheets/framework/variables_overrides.scss
+++ b/app/assets/stylesheets/framework/variables_overrides.scss
@@ -28,3 +28,9 @@ $popover-border-width: 1px;
$popover-border-color: $border-color;
$popover-box-shadow: 0 $border-radius-small $border-radius-default 0 $shadow-color;
$popover-arrow-outer-color: $shadow-color;
+$h1-font-size: 14px * 2.5;
+$h2-font-size: 14px * 2;
+$h3-font-size: 14px * 1.75;
+$h4-font-size: 14px * 1.5;
+$h5-font-size: 14px * 1.25;
+$h6-font-size: 14px;
diff --git a/app/assets/stylesheets/pages/builds.scss b/app/assets/stylesheets/pages/builds.scss
index 57918eafd6f..09235661cea 100644
--- a/app/assets/stylesheets/pages/builds.scss
+++ b/app/assets/stylesheets/pages/builds.scss
@@ -135,6 +135,7 @@
.build-loader-animation {
@include build-loader-animation;
float: left;
+ padding-left: $gl-padding-8;
}
}
@@ -232,6 +233,11 @@
@extend .d-flex;
justify-content: space-between;
align-items: center;
+
+ .trigger-variables-btn {
+ margin-top: -5px;
+ margin-bottom: -5px;
+ }
}
.trigger-build-variables {
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index 6f0dc2a3a20..140a625d333 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -403,7 +403,7 @@ class ApplicationController < ActionController::Base
end
def manifest_import_enabled?
- Group.supports_nested_groups? && Gitlab::CurrentSettings.import_sources.include?('manifest')
+ Group.supports_nested_objects? && Gitlab::CurrentSettings.import_sources.include?('manifest')
end
# U2F (universal 2nd factor) devices need a unique identifier for the application
diff --git a/app/controllers/concerns/group_tree.rb b/app/controllers/concerns/group_tree.rb
index 4f56346832c..e9a7d6a3152 100644
--- a/app/controllers/concerns/group_tree.rb
+++ b/app/controllers/concerns/group_tree.rb
@@ -32,14 +32,14 @@ module GroupTree
def filtered_groups_with_ancestors(groups)
filtered_groups = groups.search(params[:filter]).page(params[:page])
- if Group.supports_nested_groups?
+ if Group.supports_nested_objects?
# We find the ancestors by ID of the search results here.
# Otherwise the ancestors would also have filters applied,
# which would cause them not to be preloaded.
#
# Pagination needs to be applied before loading the ancestors to
# make sure ancestors are not cut off by pagination.
- Gitlab::GroupHierarchy.new(Group.where(id: filtered_groups.select(:id)))
+ Gitlab::ObjectHierarchy.new(Group.where(id: filtered_groups.select(:id)))
.base_and_ancestors
else
filtered_groups
diff --git a/app/controllers/concerns/issuable_actions.rb b/app/controllers/concerns/issuable_actions.rb
index ad9cc0925b7..3d64ae8b775 100644
--- a/app/controllers/concerns/issuable_actions.rb
+++ b/app/controllers/concerns/issuable_actions.rb
@@ -5,7 +5,6 @@ module IssuableActions
include Gitlab::Utils::StrongMemoize
included do
- before_action :labels, only: [:show, :new, :edit]
before_action :authorize_destroy_issuable!, only: :destroy
before_action :authorize_admin_issuable!, only: :bulk_update
end
@@ -25,7 +24,10 @@ module IssuableActions
def show
respond_to do |format|
- format.html
+ format.html do
+ @issuable_sidebar = serializer.represent(issuable, serializer: 'sidebar') # rubocop:disable Gitlab/ModuleWithInstanceVariables
+ end
+
format.json do
render json: serializer.represent(issuable, serializer: params[:serializer])
end
@@ -168,10 +170,6 @@ module IssuableActions
end
end
- def labels
- @labels ||= LabelsFinder.new(current_user, project_id: @project.id).execute # rubocop:disable Gitlab/ModuleWithInstanceVariables
- end
-
def authorize_destroy_issuable!
unless can?(current_user, :"destroy_#{issuable.to_ability_name}", issuable)
return access_denied!
diff --git a/app/controllers/concerns/lfs_request.rb b/app/controllers/concerns/lfs_request.rb
index 9576eb14fdd..5572c3cee2d 100644
--- a/app/controllers/concerns/lfs_request.rb
+++ b/app/controllers/concerns/lfs_request.rb
@@ -94,6 +94,7 @@ module LfsRequest
def lfs_upload_access?
return false unless project.lfs_enabled?
return false unless has_authentication_ability?(:push_code)
+ return false if limit_exceeded?
lfs_deploy_token? || can?(user, :push_code, project)
end
@@ -121,4 +122,9 @@ module LfsRequest
def has_authentication_ability?(capability)
(authentication_abilities || []).include?(capability)
end
+
+ # Overriden in EE
+ def limit_exceeded?
+ false
+ end
end
diff --git a/app/controllers/projects/deploy_keys_controller.rb b/app/controllers/projects/deploy_keys_controller.rb
index 0a593bd35b6..6824a07dc76 100644
--- a/app/controllers/projects/deploy_keys_controller.rb
+++ b/app/controllers/projects/deploy_keys_controller.rb
@@ -24,7 +24,7 @@ class Projects::DeployKeysController < Projects::ApplicationController
end
def create
- @key = DeployKeys::CreateService.new(current_user, create_params).execute
+ @key = DeployKeys::CreateService.new(current_user, create_params).execute(project: @project)
unless @key.valid?
flash[:alert] = @key.errors.full_messages.join(', ').html_safe
diff --git a/app/controllers/projects/merge_requests/conflicts_controller.rb b/app/controllers/projects/merge_requests/conflicts_controller.rb
index ac1969adc6e..045a4e974fe 100644
--- a/app/controllers/projects/merge_requests/conflicts_controller.rb
+++ b/app/controllers/projects/merge_requests/conflicts_controller.rb
@@ -8,7 +8,7 @@ class Projects::MergeRequests::ConflictsController < Projects::MergeRequests::Ap
def show
respond_to do |format|
format.html do
- labels
+ @issuable_sidebar = serializer.represent(@merge_request, serializer: 'sidebar')
end
format.json do
@@ -60,9 +60,15 @@ class Projects::MergeRequests::ConflictsController < Projects::MergeRequests::Ap
end
end
+ private
+
def authorize_can_resolve_conflicts!
@conflicts_list = ::MergeRequests::Conflicts::ListService.new(@merge_request)
return render_404 unless @conflicts_list.can_be_resolved_by?(current_user)
end
+
+ def serializer
+ MergeRequestSerializer.new(current_user: current_user, project: project)
+ end
end
diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb
index da9316d5f22..8b8eac7ff8e 100644
--- a/app/controllers/projects/merge_requests_controller.rb
+++ b/app/controllers/projects/merge_requests_controller.rb
@@ -22,8 +22,7 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
format.html
format.json do
render json: {
- html: view_to_html_string("projects/merge_requests/_merge_requests"),
- labels: @labels.as_json(methods: :text_color)
+ html: view_to_html_string("projects/merge_requests/_merge_requests")
}
end
end
@@ -43,8 +42,7 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
@noteable = @merge_request
@commits_count = @merge_request.commits_count
-
- labels
+ @issuable_sidebar = serializer.represent(@merge_request, serializer: 'sidebar')
set_pipeline_variables
diff --git a/app/finders/group_descendants_finder.rb b/app/finders/group_descendants_finder.rb
index a9ce5be13f3..96a36db7ec8 100644
--- a/app/finders/group_descendants_finder.rb
+++ b/app/finders/group_descendants_finder.rb
@@ -112,7 +112,7 @@ class GroupDescendantsFinder
# rubocop: disable CodeReuse/ActiveRecord
def ancestors_of_groups(base_for_ancestors)
group_ids = base_for_ancestors.except(:select, :sort).select(:id)
- Gitlab::GroupHierarchy.new(Group.where(id: group_ids))
+ Gitlab::ObjectHierarchy.new(Group.where(id: group_ids))
.base_and_ancestors(upto: parent_group.id)
end
# rubocop: enable CodeReuse/ActiveRecord
@@ -132,7 +132,7 @@ class GroupDescendantsFinder
end
def subgroups
- return Group.none unless Group.supports_nested_groups?
+ return Group.none unless Group.supports_nested_objects?
# When filtering subgroups, we want to find all matches withing the tree of
# descendants to show to the user
@@ -183,7 +183,7 @@ class GroupDescendantsFinder
# rubocop: disable CodeReuse/ActiveRecord
def hierarchy_for_parent
- @hierarchy ||= Gitlab::GroupHierarchy.new(Group.where(id: parent_group.id))
+ @hierarchy ||= Gitlab::ObjectHierarchy.new(Group.where(id: parent_group.id))
end
# rubocop: enable CodeReuse/ActiveRecord
end
diff --git a/app/finders/groups_finder.rb b/app/finders/groups_finder.rb
index ea954f98220..0080123407d 100644
--- a/app/finders/groups_finder.rb
+++ b/app/finders/groups_finder.rb
@@ -46,7 +46,7 @@ class GroupsFinder < UnionFinder
return [Group.all] if current_user&.full_private_access? && all_available?
groups = []
- groups << Gitlab::GroupHierarchy.new(groups_for_ancestors, groups_for_descendants).all_groups if current_user
+ groups << Gitlab::ObjectHierarchy.new(groups_for_ancestors, groups_for_descendants).all_objects if current_user
groups << Group.unscoped.public_to_user(current_user) if include_public_groups?
groups << Group.none if groups.empty?
groups
@@ -66,7 +66,7 @@ class GroupsFinder < UnionFinder
.groups
.where('members.access_level >= ?', params[:min_access_level])
- Gitlab::GroupHierarchy
+ Gitlab::ObjectHierarchy
.new(groups)
.base_and_descendants
end
diff --git a/app/helpers/application_settings_helper.rb b/app/helpers/application_settings_helper.rb
index 086bb38ce9a..5a7c005fd06 100644
--- a/app/helpers/application_settings_helper.rb
+++ b/app/helpers/application_settings_helper.rb
@@ -26,6 +26,18 @@ module ApplicationSettingsHelper
end
end
+ def all_protocols_enabled?
+ Gitlab::CurrentSettings.enabled_git_access_protocol.blank?
+ end
+
+ def ssh_enabled?
+ all_protocols_enabled? || enabled_protocol == 'ssh'
+ end
+
+ def http_enabled?
+ all_protocols_enabled? || enabled_protocol == 'http'
+ end
+
def enabled_project_button(project, protocol)
case protocol
when 'ssh'
@@ -218,7 +230,8 @@ module ApplicationSettingsHelper
:version_check_enabled,
:web_ide_clientside_preview_enabled,
:diff_max_patch_bytes,
- :commit_email_hostname
+ :commit_email_hostname,
+ :protected_ci_variables
]
end
diff --git a/app/helpers/ci_variables_helper.rb b/app/helpers/ci_variables_helper.rb
new file mode 100644
index 00000000000..e3728804c2a
--- /dev/null
+++ b/app/helpers/ci_variables_helper.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+module CiVariablesHelper
+ def ci_variable_protected_by_default?
+ Gitlab::CurrentSettings.current_application_settings.protected_ci_variables
+ end
+
+ def ci_variable_protected?(variable, only_key_value)
+ if variable && !only_key_value
+ variable.protected
+ else
+ ci_variable_protected_by_default?
+ end
+ end
+end
diff --git a/app/helpers/groups_helper.rb b/app/helpers/groups_helper.rb
index 866fc555856..4a9ed123161 100644
--- a/app/helpers/groups_helper.rb
+++ b/app/helpers/groups_helper.rb
@@ -126,7 +126,7 @@ module GroupsHelper
end
def supports_nested_groups?
- Group.supports_nested_groups?
+ Group.supports_nested_objects?
end
private
diff --git a/app/helpers/issuables_helper.rb b/app/helpers/issuables_helper.rb
index da991458ea7..5f7147508c7 100644
--- a/app/helpers/issuables_helper.rb
+++ b/app/helpers/issuables_helper.rb
@@ -23,30 +23,41 @@ module IssuablesHelper
end
end
- def sidebar_due_date_tooltip_label(issuable)
- if issuable.due_date
- "#{_('Due date')}<br />#{due_date_remaining_days(issuable)}"
- else
- _('Due date')
- end
+ def sidebar_milestone_tooltip_label(milestone)
+ return _('Milestone') unless milestone.present?
+
+ [milestone[:title], sidebar_milestone_remaining_days(milestone) || _('Milestone')].join('<br/>')
+ end
+
+ def sidebar_milestone_remaining_days(milestone)
+ due_date_with_remaining_days(milestone[:due_date], milestone[:start_date])
+ end
+
+ def sidebar_due_date_tooltip_label(due_date)
+ [_('Due date'), due_date_with_remaining_days(due_date)].compact.join('<br/>')
end
- def due_date_remaining_days(issuable)
- remaining_days_in_words = remaining_days_in_words(issuable)
+ def due_date_with_remaining_days(due_date, start_date = nil)
+ return unless due_date
- "#{issuable.due_date.to_s(:medium)} (#{remaining_days_in_words})"
+ "#{due_date.to_s(:medium)} (#{remaining_days_in_words(due_date, start_date)})"
+ end
+
+ def sidebar_label_filter_path(base_path, label_name)
+ query_params = { label_name: [label_name] }.to_query
+
+ "#{base_path}?#{query_params}"
end
def multi_label_name(current_labels, default_label)
- if current_labels && current_labels.any?
- title = current_labels.first.try(:title)
- if current_labels.size > 1
- "#{title} +#{current_labels.size - 1} more"
- else
- title
- end
+ return default_label if current_labels.blank?
+
+ title = current_labels.first.try(:title) || current_labels.first[:title]
+
+ if current_labels.size > 1
+ "#{title} +#{current_labels.size - 1} more"
else
- default_label
+ title
end
end
@@ -197,19 +208,11 @@ module IssuablesHelper
output.join.html_safe
end
- # rubocop: disable CodeReuse/ActiveRecord
- def issuable_todo(issuable)
- if current_user
- current_user.todos.find_by(target: issuable, state: :pending)
- end
- end
- # rubocop: enable CodeReuse/ActiveRecord
-
def issuable_labels_tooltip(labels, limit: 5)
first, last = labels.partition.with_index { |_, i| i < limit }
if labels && labels.any?
- label_names = first.collect(&:name)
+ label_names = first.collect { |label| label.fetch(:title) }
label_names << "and #{last.size} more" unless last.empty?
label_names.join(', ')
@@ -356,12 +359,6 @@ module IssuablesHelper
issuable.model_name.human.downcase
end
- def selected_labels
- Array(params[:label_name]).map do |label_name|
- Label.new(title: label_name)
- end
- end
-
def has_filter_bar_param?
finder.class.scalar_params.any? { |p| params[p].present? }
end
@@ -386,19 +383,20 @@ module IssuablesHelper
params[:issuable_template] if issuable_templates(issuable).any? { |template| template[:name] == params[:issuable_template] }
end
- def issuable_todo_button_data(issuable, todo, is_collapsed)
+ def issuable_todo_button_data(issuable, is_collapsed)
{
- todo_text: "Add todo",
- mark_text: "Mark todo as done",
- todo_icon: (is_collapsed ? sprite_icon('todo-add') : nil),
- mark_icon: (is_collapsed ? sprite_icon('todo-done', css_class: 'todo-undone') : nil),
- issuable_id: issuable.id,
- issuable_type: issuable.class.name.underscore,
- url: project_todos_path(@project),
- delete_path: (dashboard_todo_path(todo) if todo),
- placement: (is_collapsed ? 'left' : nil),
- container: (is_collapsed ? 'body' : nil),
- boundary: 'viewport'
+ todo_text: _('Add todo'),
+ mark_text: _('Mark todo as done'),
+ todo_icon: sprite_icon('todo-add'),
+ mark_icon: sprite_icon('todo-done', css_class: 'todo-undone'),
+ issuable_id: issuable[:id],
+ issuable_type: issuable[:type],
+ create_path: issuable[:create_todo_path],
+ delete_path: issuable.dig(:current_user, :todo, :delete_path),
+ placement: is_collapsed ? 'left' : nil,
+ container: is_collapsed ? 'body' : nil,
+ boundary: 'viewport',
+ is_collapsed: is_collapsed
}
end
@@ -418,27 +416,20 @@ module IssuablesHelper
end
end
- def issuable_sidebar_options(issuable, can_edit_issuable)
+ def issuable_sidebar_options(issuable)
{
- endpoint: "#{issuable_json_path(issuable)}?serializer=sidebar",
- toggleSubscriptionEndpoint: toggle_subscription_path(issuable),
- moveIssueEndpoint: move_namespace_project_issue_path(namespace_id: issuable.project.namespace.to_param, project_id: issuable.project, id: issuable),
- projectsAutocompleteEndpoint: autocomplete_projects_path(project_id: @project.id),
- editable: can_edit_issuable,
- currentUser: UserSerializer.new.represent(current_user),
+ endpoint: "#{issuable[:issuable_json_path]}?serializer=sidebar_extras",
+ toggleSubscriptionEndpoint: issuable[:toggle_subscription_path],
+ moveIssueEndpoint: issuable[:move_issue_path],
+ projectsAutocompleteEndpoint: issuable[:projects_autocomplete_path],
+ editable: issuable.dig(:current_user, :can_edit),
+ currentUser: issuable[:current_user],
rootPath: root_path,
- fullPath: @project.full_path
+ fullPath: issuable[:project_full_path]
}
end
def parent
@project || @group
end
-
- def issuable_milestone_tooltip_title(issuable)
- if issuable.milestone
- milestone_tooltip = milestone_tooltip_title(issuable.milestone)
- _('Milestone') + (milestone_tooltip ? ': ' + milestone_tooltip : '')
- end
- end
end
diff --git a/app/helpers/milestones_helper.rb b/app/helpers/milestones_helper.rb
index 9666080092b..327b69e5110 100644
--- a/app/helpers/milestones_helper.rb
+++ b/app/helpers/milestones_helper.rb
@@ -114,12 +114,6 @@ module MilestonesHelper
end
end
- def milestone_tooltip_title(milestone)
- if milestone
- "#{milestone.title}<br />#{milestone_tooltip_due_date(milestone)}"
- end
- end
-
def milestone_time_for(date, date_type)
title = date_type == :start ? "Start date" : "End date"
@@ -173,7 +167,7 @@ module MilestonesHelper
def milestone_tooltip_due_date(milestone)
if milestone.due_date
- "#{milestone.due_date.to_s(:medium)} (#{remaining_days_in_words(milestone)})"
+ "#{milestone.due_date.to_s(:medium)} (#{remaining_days_in_words(milestone.due_date, milestone.start_date)})"
else
_('Milestone')
end
diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb
index aa54172e108..0cfc2db3285 100644
--- a/app/helpers/projects_helper.rb
+++ b/app/helpers/projects_helper.rb
@@ -271,6 +271,20 @@ module ProjectsHelper
params[:legacy_render] ? { markdown_engine: :redcarpet } : {}
end
+ def explore_projects_tab?
+ current_page?(explore_projects_path) ||
+ current_page?(trending_explore_projects_path) ||
+ current_page?(starred_explore_projects_path)
+ end
+
+ def show_merge_request_count?(disabled: false, compact_mode: false)
+ !disabled && !compact_mode && Feature.enabled?(:project_list_show_mr_count, default_enabled: true)
+ end
+
+ def show_issue_count?(disabled: false, compact_mode: false)
+ !disabled && !compact_mode && Feature.enabled?(:project_list_show_issue_count, default_enabled: true)
+ end
+
private
def get_project_nav_tabs(project, current_user)
@@ -515,20 +529,6 @@ module ProjectsHelper
end
end
- def explore_projects_tab?
- current_page?(explore_projects_path) ||
- current_page?(trending_explore_projects_path) ||
- current_page?(starred_explore_projects_path)
- end
-
- def show_merge_request_count?(merge_requests, compact_mode)
- merge_requests && !compact_mode && Feature.enabled?(:project_list_show_mr_count, default_enabled: true)
- end
-
- def show_issue_count?(issues, compact_mode)
- issues && !compact_mode && Feature.enabled?(:project_list_show_issue_count, default_enabled: true)
- end
-
def sidebar_projects_paths
%w[
projects#show
diff --git a/app/mailers/emails/issues.rb b/app/mailers/emails/issues.rb
index 93b51fb1774..370e6d2f90b 100644
--- a/app/mailers/emails/issues.rb
+++ b/app/mailers/emails/issues.rb
@@ -56,7 +56,9 @@ module Emails
@milestone = milestone
@milestone_url = milestone_url(@milestone)
- mail_answer_thread(@issue, issue_thread_options(updated_by_user_id, recipient_id, reason))
+ mail_answer_thread(@issue, issue_thread_options(updated_by_user_id, recipient_id, reason).merge({
+ template_name: 'changed_milestone_email'
+ }))
end
def issue_status_changed_email(recipient_id, issue_id, status, updated_by_user_id, reason = nil)
diff --git a/app/mailers/emails/merge_requests.rb b/app/mailers/emails/merge_requests.rb
index 6524d0c2087..9ba8f92fcbf 100644
--- a/app/mailers/emails/merge_requests.rb
+++ b/app/mailers/emails/merge_requests.rb
@@ -51,7 +51,9 @@ module Emails
@milestone = milestone
@milestone_url = milestone_url(@milestone)
- mail_answer_thread(@merge_request, merge_request_thread_options(updated_by_user_id, recipient_id, reason))
+ mail_answer_thread(@merge_request, merge_request_thread_options(updated_by_user_id, recipient_id, reason).merge({
+ template_name: 'changed_milestone_email'
+ }))
end
def closed_merge_request_email(recipient_id, merge_request_id, updated_by_user_id, reason = nil)
diff --git a/app/mailers/notify.rb b/app/mailers/notify.rb
index 15710bee4d4..efa1233b434 100644
--- a/app/mailers/notify.rb
+++ b/app/mailers/notify.rb
@@ -16,6 +16,7 @@ class Notify < BaseMailer
include Emails::AutoDevops
include Emails::RemoteMirrors
+ helper MilestonesHelper
helper MergeRequestsHelper
helper DiffHelper
helper BlobHelper
diff --git a/app/models/application_setting.rb b/app/models/application_setting.rb
index 86ffd198ab1..88746375c67 100644
--- a/app/models/application_setting.rb
+++ b/app/models/application_setting.rb
@@ -302,7 +302,8 @@ class ApplicationSetting < ActiveRecord::Base
user_show_add_ssh_key_message: true,
usage_stats_set_by_user_id: nil,
diff_max_patch_bytes: Gitlab::Git::Diff::DEFAULT_MAX_PATCH_BYTES,
- commit_email_hostname: default_commit_email_hostname
+ commit_email_hostname: default_commit_email_hostname,
+ protected_ci_variables: false
}
end
diff --git a/app/models/broadcast_message.rb b/app/models/broadcast_message.rb
index 277f7c2717c..2d237383e60 100644
--- a/app/models/broadcast_message.rb
+++ b/app/models/broadcast_message.rb
@@ -22,49 +22,30 @@ class BroadcastMessage < ActiveRecord::Base
after_commit :flush_redis_cache
def self.current
- raw_messages = Rails.cache.fetch(CACHE_KEY, expires_in: cache_expires_in) do
+ messages = cache.fetch(CACHE_KEY, as: BroadcastMessage, expires_in: cache_expires_in) do
remove_legacy_cache_key
- current_and_future_messages.to_json
+ current_and_future_messages
end
- messages = decode_messages(raw_messages)
-
return [] unless messages&.present?
now_or_future = messages.select(&:now_or_future?)
# If there are cached entries but none are to be displayed we'll purge the
# cache so we don't keep running this code all the time.
- Rails.cache.delete(CACHE_KEY) if now_or_future.empty?
+ cache.expire(CACHE_KEY) if now_or_future.empty?
now_or_future.select(&:now?)
end
- def self.decode_messages(raw_messages)
- return unless raw_messages&.present?
-
- message_list = ActiveSupport::JSON.decode(raw_messages)
-
- return unless message_list.is_a?(Array)
-
- valid_attr = BroadcastMessage.attribute_names
-
- message_list.map do |raw|
- BroadcastMessage.new(raw) if valid_cache_entry?(raw, valid_attr)
- end.compact
- rescue ActiveSupport::JSON.parse_error
- end
-
- def self.valid_cache_entry?(raw, valid_attr)
- return false unless raw.is_a?(Hash)
-
- (raw.keys - valid_attr).empty?
- end
-
def self.current_and_future_messages
where('ends_at > :now', now: Time.zone.now).order_id_asc
end
+ def self.cache
+ Gitlab::JsonCache.new(cache_key_with_version: false)
+ end
+
def self.cache_expires_in
nil
end
@@ -74,7 +55,7 @@ class BroadcastMessage < ActiveRecord::Base
# environment a one-shot migration would not work because the cache
# would be repopulated by a node that has not been upgraded.
def self.remove_legacy_cache_key
- Rails.cache.delete(LEGACY_CACHE_KEY)
+ cache.expire(LEGACY_CACHE_KEY)
end
def active?
@@ -102,7 +83,7 @@ class BroadcastMessage < ActiveRecord::Base
end
def flush_redis_cache
- Rails.cache.delete(CACHE_KEY)
+ self.class.cache.expire(CACHE_KEY)
self.class.remove_legacy_cache_key
end
end
diff --git a/app/models/ci/runner.rb b/app/models/ci/runner.rb
index 3e5cedf92b9..8249199e76f 100644
--- a/app/models/ci/runner.rb
+++ b/app/models/ci/runner.rb
@@ -66,7 +66,7 @@ module Ci
scope :belonging_to_parent_group_of_project, -> (project_id) {
project_groups = ::Group.joins(:projects).where(projects: { id: project_id })
- hierarchy_groups = Gitlab::GroupHierarchy.new(project_groups).base_and_ancestors
+ hierarchy_groups = Gitlab::ObjectHierarchy.new(project_groups).base_and_ancestors
joins(:groups).where(namespaces: { id: hierarchy_groups })
}
diff --git a/app/models/clusters/platforms/kubernetes.rb b/app/models/clusters/platforms/kubernetes.rb
index 867f0edcb07..6cec497b4e4 100644
--- a/app/models/clusters/platforms/kubernetes.rb
+++ b/app/models/clusters/platforms/kubernetes.rb
@@ -228,7 +228,7 @@ module Clusters
return unless namespace_changed?
run_after_commit do
- ClusterPlatformConfigureWorker.perform_async(cluster_id)
+ ClusterConfigureWorker.perform_async(cluster_id)
end
end
end
diff --git a/app/models/concerns/avatarable.rb b/app/models/concerns/avatarable.rb
index b42236c1fa2..4687ec7d166 100644
--- a/app/models/concerns/avatarable.rb
+++ b/app/models/concerns/avatarable.rb
@@ -43,7 +43,18 @@ module Avatarable
end
def avatar_path(only_path: true, size: nil)
- return unless self[:avatar].present?
+ unless self.try(:id)
+ return uncached_avatar_path(only_path: only_path, size: size)
+ end
+
+ # Cache this avatar path only within the request because avatars in
+ # object storage may be generated with time-limited, signed URLs.
+ key = "#{self.class.name}:#{self.id}:#{only_path}:#{size}"
+ Gitlab::SafeRequestStore[key] ||= uncached_avatar_path(only_path: only_path, size: size)
+ end
+
+ def uncached_avatar_path(only_path: true, size: nil)
+ return unless self.try(:avatar).present?
asset_host = ActionController::Base.asset_host
use_asset_host = asset_host.present?
diff --git a/app/models/concerns/descendant.rb b/app/models/concerns/descendant.rb
new file mode 100644
index 00000000000..4c436522122
--- /dev/null
+++ b/app/models/concerns/descendant.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+module Descendant
+ extend ActiveSupport::Concern
+
+ class_methods do
+ def supports_nested_objects?
+ Gitlab::Database.postgresql?
+ end
+ end
+end
diff --git a/app/models/concerns/discussion_on_diff.rb b/app/models/concerns/discussion_on_diff.rb
index 266c37fa3a1..86b61248534 100644
--- a/app/models/concerns/discussion_on_diff.rb
+++ b/app/models/concerns/discussion_on_diff.rb
@@ -39,6 +39,7 @@ module DiscussionOnDiff
# Returns an array of at most 16 highlighted lines above a diff note
def truncated_diff_lines(highlight: true, diff_limit: nil)
+ return [] unless on_text?
return [] if diff_line.nil? && first_note.is_a?(LegacyDiffNote)
diff_limit = [diff_limit, NUMBER_OF_TRUNCATED_DIFF_LINES].compact.min
diff --git a/app/models/dashboard_group_milestone.rb b/app/models/dashboard_group_milestone.rb
index 32e8104125c..ad0bb55f0a7 100644
--- a/app/models/dashboard_group_milestone.rb
+++ b/app/models/dashboard_group_milestone.rb
@@ -5,7 +5,6 @@ class DashboardGroupMilestone < GlobalMilestone
attr_reader :group_name
- override :initialize
def initialize(milestone)
super(milestone.title, Array(milestone))
diff --git a/app/models/environment.rb b/app/models/environment.rb
index 934828946b9..cdfe3b7c023 100644
--- a/app/models/environment.rb
+++ b/app/models/environment.rb
@@ -1,6 +1,7 @@
# frozen_string_literal: true
class Environment < ActiveRecord::Base
+ include Gitlab::Utils::StrongMemoize
# Used to generate random suffixes for the slug
LETTERS = 'a'..'z'
NUMBERS = '0'..'9'
@@ -231,7 +232,9 @@ class Environment < ActiveRecord::Base
end
def deployment_platform
- project.deployment_platform(environment: self.name)
+ strong_memoize(:deployment_platform) do
+ project.deployment_platform(environment: self.name)
+ end
end
private
diff --git a/app/models/group.rb b/app/models/group.rb
index 233747cc2c2..edac2444c4d 100644
--- a/app/models/group.rb
+++ b/app/models/group.rb
@@ -10,6 +10,7 @@ class Group < Namespace
include Referable
include SelectForProjectAuthorization
include LoadedInGroupList
+ include Descendant
include GroupDescendant
include TokenAuthenticatable
include WithUploads
@@ -63,10 +64,6 @@ class Group < Namespace
after_update :path_changed_hook, if: :path_changed?
class << self
- def supports_nested_groups?
- Gitlab::Database.postgresql?
- end
-
def sort_by_attribute(method)
if method == 'storage_size_desc'
# storage_size is a virtual column so we need to
diff --git a/app/models/namespace.rb b/app/models/namespace.rb
index 3c9b1d32a53..a0bebc5e9a2 100644
--- a/app/models/namespace.rb
+++ b/app/models/namespace.rb
@@ -175,16 +175,16 @@ class Namespace < ActiveRecord::Base
# Returns all ancestors, self, and descendants of the current namespace.
def self_and_hierarchy
- Gitlab::GroupHierarchy
+ Gitlab::ObjectHierarchy
.new(self.class.where(id: id))
- .all_groups
+ .all_objects
end
# Returns all the ancestors of the current namespaces.
def ancestors
return self.class.none unless parent_id
- Gitlab::GroupHierarchy
+ Gitlab::ObjectHierarchy
.new(self.class.where(id: parent_id))
.base_and_ancestors
end
@@ -192,27 +192,27 @@ class Namespace < ActiveRecord::Base
# returns all ancestors upto but excluding the given namespace
# when no namespace is given, all ancestors upto the top are returned
def ancestors_upto(top = nil, hierarchy_order: nil)
- Gitlab::GroupHierarchy.new(self.class.where(id: id))
+ Gitlab::ObjectHierarchy.new(self.class.where(id: id))
.ancestors(upto: top, hierarchy_order: hierarchy_order)
end
def self_and_ancestors
return self.class.where(id: id) unless parent_id
- Gitlab::GroupHierarchy
+ Gitlab::ObjectHierarchy
.new(self.class.where(id: id))
.base_and_ancestors
end
# Returns all the descendants of the current namespace.
def descendants
- Gitlab::GroupHierarchy
+ Gitlab::ObjectHierarchy
.new(self.class.where(parent_id: id))
.base_and_descendants
end
def self_and_descendants
- Gitlab::GroupHierarchy
+ Gitlab::ObjectHierarchy
.new(self.class.where(id: id))
.base_and_descendants
end
@@ -293,7 +293,7 @@ class Namespace < ActiveRecord::Base
end
def force_share_with_group_lock_on_descendants
- return unless Group.supports_nested_groups?
+ return unless Group.supports_nested_objects?
# We can't use `descendants.update_all` since Rails will throw away the WITH
# RECURSIVE statement. We also can't use WHERE EXISTS since we can't use
@@ -306,6 +306,7 @@ class Namespace < ActiveRecord::Base
def write_projects_repository_config
all_projects.find_each do |project|
project.write_repository_config
+ project.track_project_repository
end
end
end
diff --git a/app/models/pool_repository.rb b/app/models/pool_repository.rb
index 47da0209c2f..ad6a008dee8 100644
--- a/app/models/pool_repository.rb
+++ b/app/models/pool_repository.rb
@@ -18,6 +18,7 @@ class PoolRepository < ActiveRecord::Base
state :scheduled
state :ready
state :failed
+ state :obsolete
event :schedule do
transition none: :scheduled
@@ -31,6 +32,10 @@ class PoolRepository < ActiveRecord::Base
transition all => :failed
end
+ event :mark_obsolete do
+ transition all => :obsolete
+ end
+
state all - [:ready] do
def joinable?
false
@@ -54,6 +59,12 @@ class PoolRepository < ActiveRecord::Base
::ObjectPool::ScheduleJoinWorker.perform_async(pool.id)
end
end
+
+ after_transition any => :obsolete do |pool, _|
+ pool.run_after_commit do
+ ::ObjectPool::DestroyWorker.perform_async(pool.id)
+ end
+ end
end
def create_object_pool
@@ -71,10 +82,10 @@ class PoolRepository < ActiveRecord::Base
end
# This RPC can cause data loss, as not all objects are present the local repository
- # No execution path yet, will be added through:
- # https://gitlab.com/gitlab-org/gitaly/issues/1415
- def delete_repository_alternate(repository)
+ def unlink_repository(repository)
object_pool.unlink_repository(repository.raw)
+
+ mark_obsolete unless member_projects.where.not(id: repository.project.id).exists?
end
def object_pool
diff --git a/app/models/project.rb b/app/models/project.rb
index 67262ecce85..09e2a6114fe 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -256,7 +256,7 @@ class Project < ActiveRecord::Base
# other pipelines, like webide ones, that we won't retrieve
# if we use this relation.
has_many :ci_pipelines,
- -> { Feature.enabled?(:pipeline_ci_sources_only, default_enabled: true) ? ci_sources : all },
+ -> { ci_sources },
class_name: 'Ci::Pipeline',
inverse_of: :project
has_many :stages, class_name: 'Ci::Stage', inverse_of: :project
@@ -570,7 +570,7 @@ class Project < ActiveRecord::Base
# returns all ancestor-groups upto but excluding the given namespace
# when no namespace is given, all ancestors upto the top are returned
def ancestors_upto(top = nil, hierarchy_order: nil)
- Gitlab::GroupHierarchy.new(Group.where(id: namespace_id))
+ Gitlab::ObjectHierarchy.new(Group.where(id: namespace_id))
.base_and_ancestors(upto: top, hierarchy_order: hierarchy_order)
end
@@ -1244,10 +1244,8 @@ class Project < ActiveRecord::Base
end
def track_project_repository
- return unless hashed_storage?(:repository)
-
- project_repo = project_repository || build_project_repository
- project_repo.update!(shard_name: repository_storage, disk_path: disk_path)
+ repository = project_repository || build_project_repository
+ repository.update!(shard_name: repository_storage, disk_path: disk_path)
end
def create_repository(force: false)
@@ -2004,6 +2002,10 @@ class Project < ActiveRecord::Base
Feature.enabled?(:object_pools, self)
end
+ def leave_pool_repository
+ pool_repository&.unlink_repository(repository)
+ end
+
private
def create_new_pool_repository
diff --git a/app/models/user.rb b/app/models/user.rb
index f20756d1cc3..26fd2d903a1 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -709,13 +709,13 @@ class User < ActiveRecord::Base
# Returns the groups a user is a member of, either directly or through a parent group
def membership_groups
- Gitlab::GroupHierarchy.new(groups).base_and_descendants
+ Gitlab::ObjectHierarchy.new(groups).base_and_descendants
end
# Returns a relation of groups the user has access to, including their parent
# and child groups (recursively).
def all_expanded_groups
- Gitlab::GroupHierarchy.new(groups).all_groups
+ Gitlab::ObjectHierarchy.new(groups).all_objects
end
def expanded_groups_requiring_two_factor_authentication
@@ -1153,7 +1153,7 @@ class User < ActiveRecord::Base
end
def manageable_groups
- Gitlab::GroupHierarchy.new(owned_or_maintainers_groups).base_and_descendants
+ Gitlab::ObjectHierarchy.new(owned_or_maintainers_groups).base_and_descendants
end
def namespaces
@@ -1422,6 +1422,10 @@ class User < ActiveRecord::Base
todos.where(id: ids)
end
+ def pending_todo_for(target)
+ todos.find_by(target: target, state: :pending)
+ end
+
# @deprecated
alias_method :owned_or_masters_groups, :owned_or_maintainers_groups
diff --git a/app/policies/group_policy.rb b/app/policies/group_policy.rb
index d1264559438..f07bb188265 100644
--- a/app/policies/group_policy.rb
+++ b/app/policies/group_policy.rb
@@ -16,7 +16,7 @@ class GroupPolicy < BasePolicy
condition(:maintainer) { access_level >= GroupMember::MAINTAINER }
condition(:reporter) { access_level >= GroupMember::REPORTER }
- condition(:nested_groups_supported, scope: :global) { Group.supports_nested_groups? }
+ condition(:nested_groups_supported, scope: :global) { Group.supports_nested_objects? }
condition(:has_parent, scope: :subject) { @subject.has_parent? }
condition(:share_with_group_locked, scope: :subject) { @subject.share_with_group_lock? }
diff --git a/app/serializers/entity_date_helper.rb b/app/serializers/entity_date_helper.rb
index cc0c2abf863..f515abe5917 100644
--- a/app/serializers/entity_date_helper.rb
+++ b/app/serializers/entity_date_helper.rb
@@ -44,14 +44,14 @@ module EntityDateHelper
# It returns "Upcoming" for upcoming entities
# If due date is provided, it returns "# days|weeks|months remaining|ago"
# If start date is provided and elapsed, with no due date, it returns "# days elapsed"
- def remaining_days_in_words(entity)
- if entity.try(:expired?)
+ def remaining_days_in_words(due_date, start_date = nil)
+ if due_date&.past?
content_tag(:strong, 'Past due')
- elsif entity.try(:upcoming?)
+ elsif start_date&.future?
content_tag(:strong, 'Upcoming')
- elsif entity.due_date
- is_upcoming = (entity.due_date - Date.today).to_i > 0
- time_ago = time_ago_in_words(entity.due_date)
+ elsif due_date
+ is_upcoming = (due_date - Date.today).to_i > 0
+ time_ago = time_ago_in_words(due_date)
# https://gitlab.com/gitlab-org/gitlab-ce/issues/49440
#
@@ -63,8 +63,8 @@ module EntityDateHelper
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
+ elsif start_date&.past?
+ days = (Date.today - start_date).to_i
"#{content_tag(:strong, days)} #{'day'.pluralize(days)} elapsed".html_safe
end
end
diff --git a/app/serializers/environment_entity.rb b/app/serializers/environment_entity.rb
index 07a13c33b89..4a7d13915dd 100644
--- a/app/serializers/environment_entity.rb
+++ b/app/serializers/environment_entity.rb
@@ -23,6 +23,10 @@ class EnvironmentEntity < Grape::Entity
stop_project_environment_path(environment.project, environment)
end
+ expose :cluster_type, if: ->(environment, _) { cluster_platform_kubernetes? } do |environment|
+ cluster.cluster_type
+ end
+
expose :terminal_path, if: ->(*) { environment.has_terminals? && can_access_terminal? } do |environment|
terminal_project_environment_path(environment.project, environment)
end
@@ -48,4 +52,16 @@ class EnvironmentEntity < Grape::Entity
def can_access_terminal?
can?(request.current_user, :create_environment_terminal, environment)
end
+
+ def cluster_platform_kubernetes?
+ deployment_platform && deployment_platform.is_a?(Clusters::Platforms::Kubernetes)
+ end
+
+ def deployment_platform
+ environment.deployment_platform
+ end
+
+ def cluster
+ deployment_platform.cluster
+ end
end
diff --git a/app/serializers/issuable_sidebar_basic_entity.rb b/app/serializers/issuable_sidebar_basic_entity.rb
new file mode 100644
index 00000000000..61de3c93337
--- /dev/null
+++ b/app/serializers/issuable_sidebar_basic_entity.rb
@@ -0,0 +1,106 @@
+# frozen_string_literal: true
+
+class IssuableSidebarBasicEntity < Grape::Entity
+ include RequestAwareEntity
+
+ expose :id
+ expose :type do |issuable|
+ issuable.to_ability_name
+ end
+ expose :author_id
+ expose :project_id do |issuable|
+ issuable.project.id
+ end
+ expose :discussion_locked
+ expose :reference do |issuable|
+ issuable.to_reference(issuable.project, full: true)
+ end
+
+ expose :milestone, using: ::API::Entities::Milestone
+ expose :labels, using: LabelEntity
+
+ expose :current_user, if: lambda { |_issuable| current_user } do
+ expose :current_user, merge: true, using: API::Entities::UserBasic
+
+ expose :todo, using: IssuableSidebarTodoEntity do |issuable|
+ current_user.pending_todo_for(issuable)
+ end
+
+ expose :can_edit do |issuable|
+ can?(current_user, :"admin_#{issuable.to_ability_name}", issuable.project)
+ end
+
+ expose :can_move do |issuable|
+ issuable.can_move?(current_user)
+ end
+
+ expose :can_admin_label do |issuable|
+ can?(current_user, :admin_label, issuable.project)
+ end
+ end
+
+ expose :issuable_json_path do |issuable|
+ if issuable.is_a?(MergeRequest)
+ project_merge_request_path(issuable.project, issuable.iid, :json)
+ else
+ project_issue_path(issuable.project, issuable.iid, :json)
+ end
+ end
+
+ expose :namespace_path do |issuable|
+ issuable.project.namespace.full_path
+ end
+
+ expose :project_path do |issuable|
+ issuable.project.path
+ end
+
+ expose :project_full_path do |issuable|
+ issuable.project.full_path
+ end
+
+ expose :project_issuables_path do |issuable|
+ project = issuable.project
+ namespace = project.namespace
+
+ if issuable.is_a?(MergeRequest)
+ namespace_project_merge_requests_path(namespace, project)
+ else
+ namespace_project_issues_path(namespace, project)
+ end
+ end
+
+ expose :create_todo_path do |issuable|
+ project_todos_path(issuable.project)
+ end
+
+ expose :project_milestones_path do |issuable|
+ project_milestones_path(issuable.project, :json)
+ end
+
+ expose :project_labels_path do |issuable|
+ project_labels_path(issuable.project, :json, include_ancestor_groups: true)
+ end
+
+ expose :toggle_subscription_path do |issuable|
+ toggle_subscription_path(issuable)
+ end
+
+ expose :move_issue_path do |issuable|
+ move_namespace_project_issue_path(
+ namespace_id: issuable.project.namespace.to_param,
+ project_id: issuable.project,
+ id: issuable
+ )
+ end
+
+ expose :projects_autocomplete_path do |issuable|
+ autocomplete_projects_path(project_id: issuable.project.id)
+ end
+
+ private
+
+ def current_user
+ request.current_user
+ end
+end
diff --git a/app/serializers/issuable_sidebar_entity.rb b/app/serializers/issuable_sidebar_extras_entity.rb
index 773d78d324c..d60253564e1 100644
--- a/app/serializers/issuable_sidebar_entity.rb
+++ b/app/serializers/issuable_sidebar_extras_entity.rb
@@ -1,8 +1,8 @@
# frozen_string_literal: true
-class IssuableSidebarEntity < Grape::Entity
- include TimeTrackableEntity
+class IssuableSidebarExtrasEntity < Grape::Entity
include RequestAwareEntity
+ include TimeTrackableEntity
expose :participants, using: ::API::Entities::UserBasic do |issuable|
issuable.participants(request.current_user)
diff --git a/app/serializers/issuable_sidebar_todo_entity.rb b/app/serializers/issuable_sidebar_todo_entity.rb
new file mode 100644
index 00000000000..b2c98433f05
--- /dev/null
+++ b/app/serializers/issuable_sidebar_todo_entity.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+class IssuableSidebarTodoEntity < Grape::Entity
+ include Gitlab::Routing
+
+ expose :id
+
+ expose :delete_path do |todo|
+ dashboard_todo_path(todo) if todo
+ end
+end
diff --git a/app/serializers/issue_board_entity.rb b/app/serializers/issue_board_entity.rb
index e3dc43240c6..f7719447b92 100644
--- a/app/serializers/issue_board_entity.rb
+++ b/app/serializers/issue_board_entity.rb
@@ -37,7 +37,7 @@ class IssueBoardEntity < Grape::Entity
end
expose :issue_sidebar_endpoint, if: -> (issue) { issue.project } do |issue|
- project_issue_path(issue.project, issue, format: :json, serializer: 'sidebar')
+ project_issue_path(issue.project, issue, format: :json, serializer: 'sidebar_extras')
end
expose :toggle_subscription_endpoint, if: -> (issue) { issue.project } do |issue|
diff --git a/app/serializers/issue_serializer.rb b/app/serializers/issue_serializer.rb
index d66f0a5acb7..0fa76f098cd 100644
--- a/app/serializers/issue_serializer.rb
+++ b/app/serializers/issue_serializer.rb
@@ -2,13 +2,15 @@
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.
+ # to serialize the `issue` based on `serializer` key in `opts` param.
# Hence, `entity` doesn't need to be declared on the class scope.
def represent(issue, opts = {})
entity =
case opts[:serializer]
when 'sidebar'
- IssueSidebarEntity
+ IssueSidebarBasicEntity
+ when 'sidebar_extras'
+ IssueSidebarExtrasEntity
when 'board'
IssueBoardEntity
else
diff --git a/app/serializers/issue_sidebar_basic_entity.rb b/app/serializers/issue_sidebar_basic_entity.rb
new file mode 100644
index 00000000000..723875809ec
--- /dev/null
+++ b/app/serializers/issue_sidebar_basic_entity.rb
@@ -0,0 +1,6 @@
+# frozen_string_literal: true
+
+class IssueSidebarBasicEntity < IssuableSidebarBasicEntity
+ expose :due_date
+ expose :confidential
+end
diff --git a/app/serializers/issue_sidebar_entity.rb b/app/serializers/issue_sidebar_extras_entity.rb
index 349ad9d1fef..7b6e860140b 100644
--- a/app/serializers/issue_sidebar_entity.rb
+++ b/app/serializers/issue_sidebar_extras_entity.rb
@@ -1,5 +1,5 @@
# frozen_string_literal: true
-class IssueSidebarEntity < IssuableSidebarEntity
+class IssueSidebarExtrasEntity < IssuableSidebarExtrasEntity
expose :assignees, using: API::Entities::UserBasic
end
diff --git a/app/serializers/merge_request_basic_entity.rb b/app/serializers/merge_request_basic_entity.rb
index f7eb74cf392..084627f9dbe 100644
--- a/app/serializers/merge_request_basic_entity.rb
+++ b/app/serializers/merge_request_basic_entity.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class MergeRequestBasicEntity < IssuableSidebarEntity
+class MergeRequestBasicEntity < Grape::Entity
expose :assignee_id
expose :merge_status
expose :merge_error
diff --git a/app/serializers/merge_request_basic_serializer.rb b/app/serializers/merge_request_basic_serializer.rb
deleted file mode 100644
index a68b48b00db..00000000000
--- a/app/serializers/merge_request_basic_serializer.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-# frozen_string_literal: true
-
-class MergeRequestBasicSerializer < BaseSerializer
- entity MergeRequestBasicEntity
-end
diff --git a/app/serializers/merge_request_serializer.rb b/app/serializers/merge_request_serializer.rb
index 1f8c830e1aa..4cf84336aa4 100644
--- a/app/serializers/merge_request_serializer.rb
+++ b/app/serializers/merge_request_serializer.rb
@@ -7,9 +7,14 @@ class MergeRequestSerializer < BaseSerializer
def represent(merge_request, opts = {})
entity =
case opts[:serializer]
- when 'basic', 'sidebar'
+ when 'sidebar'
+ MergeRequestSidebarBasicEntity
+ when 'sidebar_extras'
+ IssuableSidebarExtrasEntity
+ when 'basic'
MergeRequestBasicEntity
- else # It's 'widget'
+ else
+ # fallback to widget for old poll requests without `serializer` set
MergeRequestWidgetEntity
end
diff --git a/app/serializers/merge_request_sidebar_basic_entity.rb b/app/serializers/merge_request_sidebar_basic_entity.rb
new file mode 100644
index 00000000000..0ae7298a7c1
--- /dev/null
+++ b/app/serializers/merge_request_sidebar_basic_entity.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+class MergeRequestSidebarBasicEntity < IssuableSidebarBasicEntity
+ expose :assignee, if: lambda { |issuable| issuable.assignee } do
+ expose :assignee, merge: true, using: API::Entities::UserBasic
+
+ expose :can_merge do |issuable|
+ issuable.can_be_merged_by?(issuable.assignee)
+ end
+ end
+end
diff --git a/app/services/ci/register_job_service.rb b/app/services/ci/register_job_service.rb
index 13321b2682e..6707a1363d0 100644
--- a/app/services/ci/register_job_service.rb
+++ b/app/services/ci/register_job_service.rb
@@ -118,7 +118,7 @@ module Ci
# Workaround for weird Rails bug, that makes `runner.groups.to_sql` to return `runner_id = NULL`
groups = ::Group.joins(:runner_namespaces).merge(runner.runner_namespaces)
- hierarchy_groups = Gitlab::GroupHierarchy.new(groups).base_and_descendants
+ hierarchy_groups = Gitlab::ObjectHierarchy.new(groups).base_and_descendants
projects = Project.where(namespace_id: hierarchy_groups)
.with_group_runners_enabled
.with_builds_enabled
diff --git a/app/services/clusters/gcp/finalize_creation_service.rb b/app/services/clusters/gcp/finalize_creation_service.rb
index a4e44d009c0..5525c1b9b7f 100644
--- a/app/services/clusters/gcp/finalize_creation_service.rb
+++ b/app/services/clusters/gcp/finalize_creation_service.rb
@@ -13,7 +13,7 @@ module Clusters
configure_kubernetes
cluster.save!
- ClusterPlatformConfigureWorker.perform_async(cluster.id)
+ ClusterConfigureWorker.perform_async(cluster.id)
rescue Google::Apis::ServerError, Google::Apis::ClientError, Google::Apis::AuthorizationError => e
log_service_error(e.class.name, provider.id, e.message)
diff --git a/app/services/deploy_keys/create_service.rb b/app/services/deploy_keys/create_service.rb
index a25e73666f8..0c935285657 100644
--- a/app/services/deploy_keys/create_service.rb
+++ b/app/services/deploy_keys/create_service.rb
@@ -2,7 +2,7 @@
module DeployKeys
class CreateService < Keys::BaseService
- def execute
+ def execute(project: nil)
DeployKey.create(params.merge(user: user))
end
end
diff --git a/app/services/groups/nested_create_service.rb b/app/services/groups/nested_create_service.rb
index 50d34d8cb91..f01f5656296 100644
--- a/app/services/groups/nested_create_service.rb
+++ b/app/services/groups/nested_create_service.rb
@@ -18,7 +18,7 @@ module Groups
return namespace
end
- if group_path.include?('/') && !Group.supports_nested_groups?
+ if group_path.include?('/') && !Group.supports_nested_objects?
raise 'Nested groups are not supported on MySQL'
end
diff --git a/app/services/groups/transfer_service.rb b/app/services/groups/transfer_service.rb
index 5efa746dfb9..f64e327416a 100644
--- a/app/services/groups/transfer_service.rb
+++ b/app/services/groups/transfer_service.rb
@@ -40,7 +40,7 @@ module Groups
def ensure_allowed_transfer
raise_transfer_error(:group_is_already_root) if group_is_already_root?
- raise_transfer_error(:database_not_supported) unless Group.supports_nested_groups?
+ raise_transfer_error(:database_not_supported) unless Group.supports_nested_objects?
raise_transfer_error(:same_parent_as_current) if same_parent?
raise_transfer_error(:invalid_policies) unless valid_policies?
raise_transfer_error(:namespace_with_same_path) if namespace_with_same_path?
diff --git a/app/services/projects/after_rename_service.rb b/app/services/projects/after_rename_service.rb
index 4131da44f5a..aa9b253eb20 100644
--- a/app/services/projects/after_rename_service.rb
+++ b/app/services/projects/after_rename_service.rb
@@ -81,6 +81,7 @@ module Projects
def update_repository_configuration
project.reload_repository!
project.write_repository_config
+ project.track_project_repository
end
def rename_transferred_documents
diff --git a/app/services/projects/destroy_service.rb b/app/services/projects/destroy_service.rb
index 210571b6b4e..336d029d330 100644
--- a/app/services/projects/destroy_service.rb
+++ b/app/services/projects/destroy_service.rb
@@ -137,6 +137,8 @@ module Projects
raise_error('Failed to remove some tags in project container registry. Please try again or contact administrator.')
end
+ project.leave_pool_repository
+
Project.transaction do
log_destroy_event
trash_repositories!
diff --git a/app/services/projects/transfer_service.rb b/app/services/projects/transfer_service.rb
index 9db3fd9cf17..5da1e39a1fb 100644
--- a/app/services/projects/transfer_service.rb
+++ b/app/services/projects/transfer_service.rb
@@ -81,7 +81,7 @@ module Projects
project.old_path_with_namespace = @old_path
- write_repository_config(@new_path)
+ update_repository_configuration(@new_path)
execute_system_hooks
end
@@ -106,8 +106,9 @@ module Projects
project.save!
end
- def write_repository_config(full_path)
+ def update_repository_configuration(full_path)
project.write_repository_config(gl_full_path: full_path)
+ project.track_project_repository
end
def refresh_permissions
@@ -123,7 +124,7 @@ module Projects
rollback_folder_move
project.reload
update_namespace_and_visibility(@old_namespace)
- write_repository_config(@old_path)
+ update_repository_configuration(@old_path)
end
def rollback_folder_move
diff --git a/app/services/users/refresh_authorized_projects_service.rb b/app/services/users/refresh_authorized_projects_service.rb
index 23b63aaabdf..fe5a82e23fa 100644
--- a/app/services/users/refresh_authorized_projects_service.rb
+++ b/app/services/users/refresh_authorized_projects_service.rb
@@ -102,7 +102,7 @@ module Users
end
def fresh_authorizations
- klass = if Group.supports_nested_groups?
+ klass = if Group.supports_nested_objects?
Gitlab::ProjectAuthorizations::WithNestedGroups
else
Gitlab::ProjectAuthorizations::WithoutNestedGroups
diff --git a/app/views/admin/application_settings/_ci_cd.html.haml b/app/views/admin/application_settings/_ci_cd.html.haml
index 0d42094fc89..fdaad1cf181 100644
--- a/app/views/admin/application_settings/_ci_cd.html.haml
+++ b/app/views/admin/application_settings/_ci_cd.html.haml
@@ -49,5 +49,12 @@
Once that time passes, the jobs will be archived and no longer able to be
retried. Make it empty to never expire jobs. It has to be no less than 1 day,
for example: <code>15 days</code>, <code>1 month</code>, <code>2 years</code>.
+ .form-group
+ .form-check
+ = f.check_box :protected_ci_variables, class: 'form-check-input'
+ = f.label :protected_ci_variables, class: 'form-check-label' do
+ = s_('AdminSettings|Environment variables are protected by default')
+ .form-text.text-muted
+ = s_('AdminSettings|When creating a new environment variable it will be protected by default.')
= f.submit 'Save changes', class: "btn btn-success"
diff --git a/app/views/ci/variables/_content.html.haml b/app/views/ci/variables/_content.html.haml
index d355e7799df..fa82611d9c1 100644
--- a/app/views/ci/variables/_content.html.haml
+++ b/app/views/ci/variables/_content.html.haml
@@ -1 +1 @@
-= _('Variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. You can use variables for passwords, secret keys, or whatever you want.')
+= _('Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. You can use environment variables for passwords, secret keys, or whatever you want.')
diff --git a/app/views/ci/variables/_header.html.haml b/app/views/ci/variables/_header.html.haml
new file mode 100644
index 00000000000..cb7779e2175
--- /dev/null
+++ b/app/views/ci/variables/_header.html.haml
@@ -0,0 +1,11 @@
+- expanded = local_assigns.fetch(:expanded)
+
+%h4
+ = _('Environment variables')
+ = link_to icon('question-circle'), help_page_path('ci/variables/README', anchor: 'variables'), target: '_blank', rel: 'noopener noreferrer'
+
+%button.btn.btn-default.js-settings-toggle{ type: 'button' }
+ = expanded ? _('Collapse') : _('Expand')
+
+%p.append-bottom-0
+ = render "ci/variables/content"
diff --git a/app/views/ci/variables/_index.html.haml b/app/views/ci/variables/_index.html.haml
index f34305e94fa..dc9ccb6cc39 100644
--- a/app/views/ci/variables/_index.html.haml
+++ b/app/views/ci/variables/_index.html.haml
@@ -1,5 +1,10 @@
- save_endpoint = local_assigns.fetch(:save_endpoint, nil)
+- if ci_variable_protected_by_default?
+ %p.settings-message.text-center
+ - link_start = '<a href="%{url}">'.html_safe % { url: help_page_path('ci/variables/README', anchor: 'protected-variables') }
+ = s_('Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default').html_safe % { link_start: link_start, link_end: '</a>'.html_safe }
+
.row
.col-lg-12.js-ci-variable-list-section{ data: { save_endpoint: save_endpoint } }
.hide.alert.alert-danger.js-ci-variable-error-box
diff --git a/app/views/ci/variables/_variable_row.html.haml b/app/views/ci/variables/_variable_row.html.haml
index 6ee55836dd2..16a7527c8ce 100644
--- a/app/views/ci/variables/_variable_row.html.haml
+++ b/app/views/ci/variables/_variable_row.html.haml
@@ -5,7 +5,8 @@
- id = variable&.id
- key = variable&.key
- value = variable&.value
-- is_protected = variable && !only_key_value ? variable.protected : false
+- is_protected_default = ci_variable_protected_by_default?
+- is_protected = ci_variable_protected?(variable, only_key_value)
- id_input_name = "#{form_field}[variables_attributes][][id]"
- destroy_input_name = "#{form_field}[variables_attributes][][_destroy]"
@@ -39,7 +40,8 @@
%input{ type: "hidden",
class: 'js-ci-variable-input-protected js-project-feature-toggle-input',
name: protected_input_name,
- value: is_protected }
+ value: is_protected,
+ data: { default: is_protected_default.to_s } }
%span.toggle-icon
= sprite_icon('status_success_borderless', size: 16, css_class: 'toggle-icon-svg toggle-status-checked')
= sprite_icon('status_failed_borderless', size: 16, css_class: 'toggle-icon-svg toggle-status-unchecked')
diff --git a/app/views/groups/settings/ci_cd/show.html.haml b/app/views/groups/settings/ci_cd/show.html.haml
index a5e6abdba52..d9332e36ef5 100644
--- a/app/views/groups/settings/ci_cd/show.html.haml
+++ b/app/views/groups/settings/ci_cd/show.html.haml
@@ -5,13 +5,7 @@
%section.settings#ci-variables.no-animate{ class: ('expanded' if expanded) }
.settings-header
- %h4
- = _('Variables')
- = link_to icon('question-circle'), help_page_path('ci/variables/README', anchor: 'variables'), target: '_blank', rel: 'noopener noreferrer'
- %button.btn.btn-default.js-settings-toggle{ type: "button" }
- = expanded ? _('Collapse') : _('Expand')
- %p.append-bottom-0
- = render "ci/variables/content"
+ = render 'ci/variables/header', expanded: expanded
.settings-content
= render 'ci/variables/index', save_endpoint: group_variables_path
diff --git a/app/views/layouts/_search.html.haml b/app/views/layouts/_search.html.haml
index a86972d8cf3..a6023a1cbb9 100644
--- a/app/views/layouts/_search.html.haml
+++ b/app/views/layouts/_search.html.haml
@@ -2,7 +2,7 @@
- group_data_attrs = { group_path: j(@group.path), name: @group.name, issues_path: issues_group_path(j(@group.path)), mr_path: merge_requests_group_path(j(@group.path)) }
- if @project && @project.persisted?
- project_data_attrs = { project_path: j(@project.path), name: j(@project.name), issues_path: project_issues_path(@project), mr_path: project_merge_requests_path(@project), issues_disabled: !@project.issues_enabled? }
-.search.search-form
+.search.search-form{ data: { track_label: "navbar_search", track_event: "activate_form_input" } }
= form_tag search_path, method: :get, class: 'form-inline' do |f|
.search-input-container
.search-input-wrap
diff --git a/app/views/layouts/devise.html.haml b/app/views/layouts/devise.html.haml
index 4f8db74382f..6003d973c88 100644
--- a/app/views/layouts/devise.html.haml
+++ b/app/views/layouts/devise.html.haml
@@ -1,7 +1,7 @@
!!! 5
%html.devise-layout-html{ class: system_message_class }
= render "layouts/head"
- %body.ui-indigo.login-page.application.navless{ data: { page: body_data_page } }
+ %body.ui-indigo.login-page.application.navless.qa-login-page{ data: { page: body_data_page } }
.page-wrap
= render "layouts/header/empty"
.login-page-broadcast
diff --git a/app/views/layouts/header/_default.html.haml b/app/views/layouts/header/_default.html.haml
index e8d0d809181..a9b85889846 100644
--- a/app/views/layouts/header/_default.html.haml
+++ b/app/views/layouts/header/_default.html.haml
@@ -60,7 +60,7 @@
.dropdown-menu.dropdown-menu-right
= render 'layouts/header/help_dropdown'
- if header_link?(:user_dropdown)
- %li.nav-item.header-user.dropdown
+ %li.nav-item.header-user.dropdown{ data: { track_label: "profile_dropdown", track_event: "click_dropdown" } }
= link_to current_user, class: user_dropdown_class, data: { toggle: "dropdown" } do
= image_tag avatar_icon_for_user(current_user, 23), width: 23, height: 23, class: "header-user-avatar qa-user-avatar"
= sprite_icon('angle-down', css_class: 'caret-down')
diff --git a/app/views/layouts/header/_new_dropdown.haml b/app/views/layouts/header/_new_dropdown.haml
index 5cb8aebadb3..e42251f9ec8 100644
--- a/app/views/layouts/header/_new_dropdown.haml
+++ b/app/views/layouts/header/_new_dropdown.haml
@@ -1,4 +1,4 @@
-%li.header-new.dropdown
+%li.header-new.dropdown{ data: { track_label: "new_dropdown", track_event: "click_dropdown" } }
= link_to new_project_path, class: "header-new-dropdown-toggle has-tooltip qa-new-menu-toggle", title: _("New..."), ref: 'tooltip', aria: { label: _("New...") }, data: { toggle: 'dropdown', placement: 'bottom', container: 'body', display: 'static' } do
= sprite_icon('plus-square', size: 16)
= sprite_icon('angle-down', css_class: 'caret-down')
diff --git a/app/views/layouts/nav/_dashboard.html.haml b/app/views/layouts/nav/_dashboard.html.haml
index 7057a5a142f..ddd30efe062 100644
--- a/app/views/layouts/nav/_dashboard.html.haml
+++ b/app/views/layouts/nav/_dashboard.html.haml
@@ -2,7 +2,7 @@
-# https://gitlab.com/gitlab-org/gitlab-ce/issues/49713 for more information.
%ul.list-unstyled.navbar-sub-nav
- if dashboard_nav_link?(:projects)
- = nav_link(path: ['root#index', 'projects#trending', 'projects#starred', 'dashboard/projects#index'], html_options: { id: 'nav-projects-dropdown', class: "home dropdown header-projects qa-projects-dropdown" }) do
+ = nav_link(path: ['root#index', 'projects#trending', 'projects#starred', 'dashboard/projects#index'], html_options: { id: 'nav-projects-dropdown', class: "home dropdown header-projects qa-projects-dropdown", data: { track_label: "projects_dropdown", track_event: "click_dropdown" } }) do
%button{ type: 'button', data: { toggle: "dropdown" } }
= _('Projects')
= sprite_icon('angle-down', css_class: 'caret-down')
@@ -10,7 +10,7 @@
= render "layouts/nav/projects_dropdown/show"
- if dashboard_nav_link?(:groups)
- = nav_link(controller: ['dashboard/groups', 'explore/groups'], html_options: { id: 'nav-groups-dropdown', class: "home dropdown header-groups qa-groups-dropdown" }) do
+ = nav_link(controller: ['dashboard/groups', 'explore/groups'], html_options: { id: 'nav-groups-dropdown', class: "home dropdown header-groups qa-groups-dropdown", data: { track_label: "groups_dropdown", track_event: "click_dropdown" } }) do
%button{ type: 'button', data: { toggle: "dropdown" } }
= _('Groups')
= sprite_icon('angle-down', css_class: 'caret-down')
diff --git a/app/views/notify/_note_email.html.haml b/app/views/notify/_note_email.html.haml
index 1fbae2f64ed..83c7f548975 100644
--- a/app/views/notify/_note_email.html.haml
+++ b/app/views/notify/_note_email.html.haml
@@ -4,17 +4,13 @@
- note_style = local_assigns.fetch(:note_style, "")
- discussion = note.discussion if note.part_of_discussion?
-- diff_discussion = discussion&.diff_discussion?
-- on_image = discussion.on_image? if diff_discussion
- if discussion
- - phrase_end_char = on_image ? "." : ":"
-
%p{ style: "color: #777777;" }
- = succeed phrase_end_char do
+ = succeed ':' do
= link_to note.author_name, user_url(note.author)
- - if diff_discussion
+ - if discussion&.diff_discussion?
- if discussion.new_discussion?
started a new discussion
- else
@@ -31,7 +27,7 @@
%p.details
#{link_to note.author_name, user_url(note.author)} commented:
-- if diff_discussion && !on_image
+- if discussion&.diff_discussion? && discussion.on_text?
= content_for :head do
= stylesheet_link_tag 'mailers/highlighted_diff_email'
diff --git a/app/views/notify/_note_email.text.erb b/app/views/notify/_note_email.text.erb
index 4bf252b6ce1..50209c46ed1 100644
--- a/app/views/notify/_note_email.text.erb
+++ b/app/views/notify/_note_email.text.erb
@@ -20,7 +20,7 @@
<% end -%>
-<% if discussion&.diff_discussion? -%>
+<% if discussion&.diff_discussion? && discussion.on_text? -%>
<% discussion.truncated_diff_lines(highlight: false, diff_limit: diff_limit).each do |line| -%>
<%= "> #{line.text}\n" -%>
<% end -%>
diff --git a/app/views/notify/changed_milestone_merge_request_email.html.haml b/app/views/notify/changed_milestone_email.html.haml
index 7d5425fc72d..01d27cac36b 100644
--- a/app/views/notify/changed_milestone_merge_request_email.html.haml
+++ b/app/views/notify/changed_milestone_email.html.haml
@@ -1,3 +1,5 @@
%p
Milestone changed to
%strong= link_to(@milestone.name, @milestone_url)
+ - if date_range = milestone_date_range(@milestone)
+ = "(#{date_range})"
diff --git a/app/views/notify/changed_milestone_email.text.erb b/app/views/notify/changed_milestone_email.text.erb
new file mode 100644
index 00000000000..a466da4eb19
--- /dev/null
+++ b/app/views/notify/changed_milestone_email.text.erb
@@ -0,0 +1 @@
+Milestone changed to <%= @milestone.name %><% if date_range = milestone_date_range(@milestone) %> (<%= date_range %>)<% end %> ( <%= @milestone_url %> )
diff --git a/app/views/notify/changed_milestone_issue_email.html.haml b/app/views/notify/changed_milestone_issue_email.html.haml
deleted file mode 100644
index 7d5425fc72d..00000000000
--- a/app/views/notify/changed_milestone_issue_email.html.haml
+++ /dev/null
@@ -1,3 +0,0 @@
-%p
- Milestone changed to
- %strong= link_to(@milestone.name, @milestone_url)
diff --git a/app/views/notify/changed_milestone_issue_email.text.erb b/app/views/notify/changed_milestone_issue_email.text.erb
deleted file mode 100644
index c5fc0b61518..00000000000
--- a/app/views/notify/changed_milestone_issue_email.text.erb
+++ /dev/null
@@ -1 +0,0 @@
-Milestone changed to <%= @milestone.name %> ( <%= @milestone_url %> )
diff --git a/app/views/notify/changed_milestone_merge_request_email.text.erb b/app/views/notify/changed_milestone_merge_request_email.text.erb
deleted file mode 100644
index c5fc0b61518..00000000000
--- a/app/views/notify/changed_milestone_merge_request_email.text.erb
+++ /dev/null
@@ -1 +0,0 @@
-Milestone changed to <%= @milestone.name %> ( <%= @milestone_url %> )
diff --git a/app/views/projects/buttons/_clone.html.haml b/app/views/projects/buttons/_clone.html.haml
index d453a3a9dac..53d427ec40a 100644
--- a/app/views/projects/buttons/_clone.html.haml
+++ b/app/views/projects/buttons/_clone.html.haml
@@ -1,25 +1,22 @@
- project = project || @project
.git-clone-holder.js-git-clone-holder.input-group
- - if allowed_protocols_present?
- .input-group-text.clone-dropdown-btn.btn
- %span.js-clone-dropdown-label
- = enabled_project_button(project, enabled_protocol)
- - else
- %a#clone-dropdown.input-group-text.btn.btn-primary.btn-xs.clone-dropdown-btn.qa-clone-dropdown{ href: '#', data: { toggle: 'dropdown' } }
- %span.append-right-4.js-clone-dropdown-label
- = _('Clone')
- = sprite_icon("arrow-down", css_class: "icon")
+ %a#clone-dropdown.input-group-text.btn.btn-primary.btn-xs.clone-dropdown-btn.qa-clone-dropdown{ href: '#', data: { toggle: 'dropdown' } }
+ %span.append-right-4.js-clone-dropdown-label
+ = _('Clone')
+ = sprite_icon("arrow-down", css_class: "icon")
%form.p-3.dropdown-menu.dropdown-menu-right.dropdown-menu-large.dropdown-menu-selectable.clone-options-dropdown.qa-clone-options
- %li.pb-2
- %label.label-bold
- = _('Clone with SSH')
- .input-group
- = text_field_tag :ssh_project_clone, project.ssh_url_to_repo, class: "js-select-on-focus form-control qa-ssh-clone-url", readonly: true, aria: { label: 'Project clone URL' }
- .input-group-append
- = clipboard_button(target: '#ssh_project_clone', title: _("Copy URL to clipboard"), class: "input-group-text btn-default btn-clipboard")
- = render_if_exists 'projects/buttons/geo'
- %li
+ - if ssh_enabled?
+ %li.pb-2
+ %label.label-bold
+ = _('Clone with SSH')
+ .input-group
+ = text_field_tag :ssh_project_clone, project.ssh_url_to_repo, class: "js-select-on-focus form-control qa-ssh-clone-url", readonly: true, aria: { label: 'Project clone URL' }
+ .input-group-append
+ = clipboard_button(target: '#ssh_project_clone', title: _("Copy URL to clipboard"), class: "input-group-text btn-default btn-clipboard")
+ = render_if_exists 'projects/buttons/geo'
+ %li
+ - if http_enabled?
%label.label-bold
= _('Clone with %{http_label}') % { http_label: gitlab_config.protocol.upcase }
.input-group
diff --git a/app/views/projects/issues/show.html.haml b/app/views/projects/issues/show.html.haml
index b50b3ca207b..8c2fe2625c7 100644
--- a/app/views/projects/issues/show.html.haml
+++ b/app/views/projects/issues/show.html.haml
@@ -88,4 +88,4 @@
%section.issuable-discussion
= render 'projects/issues/discussion'
-= render 'shared/issuable/sidebar', issuable: @issue
+= render 'shared/issuable/sidebar', issuable_sidebar: @issuable_sidebar, assignees: @issue.assignees
diff --git a/app/views/projects/merge_requests/conflicts.html.haml b/app/views/projects/merge_requests/conflicts.html.haml
deleted file mode 100644
index a6e2565a485..00000000000
--- a/app/views/projects/merge_requests/conflicts.html.haml
+++ /dev/null
@@ -1,36 +0,0 @@
-- page_title "Merge Conflicts", "#{@merge_request.title} (#{@merge_request.to_reference}", "Merge Requests"
-- content_for :page_specific_javascripts do
- = page_specific_javascript_tag('lib/ace.js')
-= render "projects/merge_requests/mr_title"
-
-.merge-request-details.issuable-details
- = render "projects/merge_requests/mr_box"
-
-= render 'shared/issuable/sidebar', issuable: @merge_request
-
-#conflicts{ "v-cloak" => "true", data: { conflicts_path: conflicts_project_merge_request_path(@merge_request.project, @merge_request, format: :json),
- resolve_conflicts_path: resolve_conflicts_project_merge_request_path(@merge_request.project, @merge_request) } }
- .loading{ "v-if" => "isLoading" }
- %i.fa.fa-spinner.fa-spin
-
- .nothing-here-block{ "v-if" => "hasError" }
- {{conflictsData.errorMessage}}
-
- = render partial: "projects/merge_requests/conflicts/commit_stats"
-
- .files-wrapper{ "v-if" => "!isLoading && !hasError" }
- .files
- .diff-file.file-holder.conflict{ "v-for" => "file in conflictsData.files" }
- .js-file-title.file-title
- %i.fa.fa-fw{ ":class" => "file.iconClass" }
- %strong {{file.filePath}}
- = render partial: 'projects/merge_requests/conflicts/file_actions'
- .diff-content.diff-wrap-lines
- .diff-wrap-lines.code.file-content.js-syntax-highlight{ "v-show" => "!isParallel && file.resolveMode === 'interactive' && file.type === 'text'" }
- = render partial: "projects/merge_requests/conflicts/components/inline_conflict_lines"
- .diff-wrap-lines.code.file-content.js-syntax-highlight{ "v-show" => "isParallel && file.resolveMode === 'interactive' && file.type === 'text'" }
- %parallel-conflict-lines{ ":file" => "file" }
- %div{ "v-show" => "file.resolveMode === 'edit' || file.type === 'text-editor'" }
- = render partial: "projects/merge_requests/conflicts/components/diff_file_editor"
-
- = render partial: "projects/merge_requests/conflicts/submit_form"
diff --git a/app/views/projects/merge_requests/conflicts/show.html.haml b/app/views/projects/merge_requests/conflicts/show.html.haml
index a6e2565a485..09aeb81671a 100644
--- a/app/views/projects/merge_requests/conflicts/show.html.haml
+++ b/app/views/projects/merge_requests/conflicts/show.html.haml
@@ -6,7 +6,7 @@
.merge-request-details.issuable-details
= render "projects/merge_requests/mr_box"
-= render 'shared/issuable/sidebar', issuable: @merge_request
+= render 'shared/issuable/sidebar', issuable_sidebar: @issuable_sidebar, assignees: @merge_request.assignees
#conflicts{ "v-cloak" => "true", data: { conflicts_path: conflicts_project_merge_request_path(@merge_request.project, @merge_request, format: :json),
resolve_conflicts_path: resolve_conflicts_project_merge_request_path(@merge_request.project, @merge_request) } }
diff --git a/app/views/projects/merge_requests/show.html.haml b/app/views/projects/merge_requests/show.html.haml
index cc9292b54d7..d6f340d0ee2 100644
--- a/app/views/projects/merge_requests/show.html.haml
+++ b/app/views/projects/merge_requests/show.html.haml
@@ -86,7 +86,8 @@
.mr-loading-status
= spinner
-= render 'shared/issuable/sidebar', issuable: @merge_request
+= render 'shared/issuable/sidebar', issuable_sidebar: @issuable_sidebar, assignees: @merge_request.assignees
+
- if @merge_request.can_be_reverted?(current_user)
= render "projects/commit/change", type: 'revert', commit: @merge_request.merge_commit, title: @merge_request.title
- if @merge_request.can_be_cherry_picked?
diff --git a/app/views/projects/releases/index.html.haml b/app/views/projects/releases/index.html.haml
index 7bc942a3c3c..f01d4e826b9 100644
--- a/app/views/projects/releases/index.html.haml
+++ b/app/views/projects/releases/index.html.haml
@@ -1,5 +1,5 @@
- @no_container = true
- page_title _('Releases')
-%div{ 'class' => container_class }
- #js-releases-page
+%div{ class: container_class }
+ #js-releases-page{ data: { project_id: @project.id, illustration_path: image_path('illustrations/releases.svg'), documentation_path: help_page_path('user/project/releases') } }
diff --git a/app/views/projects/settings/ci_cd/show.html.haml b/app/views/projects/settings/ci_cd/show.html.haml
index 98e2829ba43..6966bf96724 100644
--- a/app/views/projects/settings/ci_cd/show.html.haml
+++ b/app/views/projects/settings/ci_cd/show.html.haml
@@ -43,13 +43,7 @@
%section.qa-variables-settings.settings.no-animate{ class: ('expanded' if expanded) }
.settings-header
- %h4
- = _('Variables')
- = link_to icon('question-circle'), help_page_path('ci/variables/README', anchor: 'variables'), target: '_blank', rel: 'noopener noreferrer'
- %button.btn.js-settings-toggle{ type: 'button' }
- = expanded ? _('Collapse') : _('Expand')
- %p.append-bottom-0
- = render "ci/variables/content"
+ = render 'ci/variables/header', expanded: expanded
.settings-content
= render 'ci/variables/index', save_endpoint: project_variables_path(@project)
diff --git a/app/views/shared/_mobile_clone_panel.html.haml b/app/views/shared/_mobile_clone_panel.html.haml
index b43662947a8..6e2527bd1a1 100644
--- a/app/views/shared/_mobile_clone_panel.html.haml
+++ b/app/views/shared/_mobile_clone_panel.html.haml
@@ -7,7 +7,9 @@
%button.btn.btn-primary.dropdown-toggle.js-dropdown-toggle{ type: "button", data: { toggle: "dropdown" } }
= sprite_icon("arrow-down", css_class: "dropdown-btn-icon icon")
%ul.dropdown-menu.dropdown-menu-selectable.dropdown-menu-right.clone-options-dropdown{ data: { dropdown: true } }
- %li
- = dropdown_item_with_description(ssh_copy_label, project.ssh_url_to_repo, href: project.ssh_url_to_repo, data: { clone_type: 'ssh' }, default: true)
- %li
- = dropdown_item_with_description(http_copy_label, project.http_url_to_repo, href: project.http_url_to_repo, data: { clone_type: 'http' })
+ - if ssh_enabled?
+ %li
+ = dropdown_item_with_description(ssh_copy_label, project.ssh_url_to_repo, href: project.ssh_url_to_repo, data: { clone_type: 'ssh' }, default: true)
+ - if http_enabled?
+ %li
+ = dropdown_item_with_description(http_copy_label, project.http_url_to_repo, href: project.http_url_to_repo, data: { clone_type: 'http' })
diff --git a/app/views/shared/issuable/_sidebar.html.haml b/app/views/shared/issuable/_sidebar.html.haml
index 9eecfa39390..0520eda37a4 100644
--- a/app/views/shared/issuable/_sidebar.html.haml
+++ b/app/views/shared/issuable/_sidebar.html.haml
@@ -1,32 +1,37 @@
-- todo = issuable_todo(issuable)
+-# `assignees` is being passed in for populating selected assignee values in the select box and rendering the assignee link
+ This should be removed when this sidebar is converted to Vue since assignee data is also available in the `issuable_sidebar` hash
-%aside.right-sidebar.js-right-sidebar.js-issuable-sidebar{ data: { signed: { in: current_user.present? } }, class: sidebar_gutter_collapsed_class, 'aria-live' => 'polite' }
- .issuable-sidebar{ data: { endpoint: "#{issuable_json_path(issuable)}" } }
- - can_edit_issuable = can?(current_user, :"admin_#{issuable.to_ability_name}", @project)
+- issuable_type = issuable_sidebar[:type]
+- signed_in = !!issuable_sidebar.dig(:current_user, :id)
+- can_edit_issuable = issuable_sidebar.dig(:current_user, :can_edit)
+
+%aside.right-sidebar.js-right-sidebar.js-issuable-sidebar{ data: { signed: { in: signed_in } }, class: sidebar_gutter_collapsed_class, 'aria-live' => 'polite' }
+ .issuable-sidebar
.block.issuable-sidebar-header
- - if current_user
+ - if signed_in
%span.issuable-header-text.hide-collapsed.float-left
= _('Todo')
%a.gutter-toggle.float-right.js-sidebar-toggle.has-tooltip{ role: "button", href: "#", "aria-label" => "Toggle sidebar", title: sidebar_gutter_tooltip_text, data: { container: 'body', placement: 'left', boundary: 'viewport' } }
= sidebar_gutter_toggle_icon
- - if current_user
- = render "shared/issuable/sidebar_todo", todo: todo, issuable: issuable
+ - if signed_in
+ = render "shared/issuable/sidebar_todo", issuable_sidebar: issuable_sidebar
- = form_for [@project.namespace.becomes(Namespace), @project, issuable], remote: true, format: :json, html: { class: 'issuable-context-form inline-update js-issuable-update' } do |f|
- - if current_user
+ = form_for issuable_type, url: issuable_sidebar[:issuable_json_path], remote: true, html: { class: 'issuable-context-form inline-update js-issuable-update' } do |f|
+ - if signed_in
.block.todo.hide-expanded
- = render "shared/issuable/sidebar_todo", todo: todo, issuable: issuable, is_collapsed: true
+ = render "shared/issuable/sidebar_todo", issuable_sidebar: issuable_sidebar, is_collapsed: true
.block.assignee.qa-assignee-block
- = render "shared/issuable/sidebar_assignees", issuable: issuable, can_edit_issuable: can_edit_issuable, signed_in: current_user.present?
+ = render "shared/issuable/sidebar_assignees", issuable_sidebar: issuable_sidebar, assignees: assignees
- = render_if_exists 'shared/issuable/sidebar_item_epic', issuable: issuable
+ = render_if_exists 'shared/issuable/sidebar_item_epic', issuable_sidebar: issuable_sidebar
+ - milestone = issuable_sidebar[:milestone] || {}
.block.milestone
- .sidebar-collapsed-icon.has-tooltip{ title: milestone_tooltip_title(issuable.milestone), data: { container: 'body', html: 'true', placement: 'left', boundary: 'viewport' } }
+ .sidebar-collapsed-icon.has-tooltip{ title: sidebar_milestone_tooltip_label(milestone), data: { container: 'body', html: 'true', placement: 'left', boundary: 'viewport' } }
= icon('clock-o', 'aria-hidden': 'true')
%span.milestone-title.collapse-truncated-title
- - if issuable.milestone
- = issuable.milestone.title
+ - if milestone.present?
+ = milestone[:title]
- else
= _('None')
.title.hide-collapsed
@@ -35,49 +40,50 @@
- if can_edit_issuable
= link_to _('Edit'), '#', class: 'js-sidebar-dropdown-toggle edit-link float-right'
.value.hide-collapsed
- - if issuable.milestone
- = link_to issuable.milestone.title, milestone_path(issuable.milestone), class: "bold has-tooltip", title: milestone_tooltip_due_date(issuable.milestone), data: { container: "body", html: 'true', boundary: 'viewport' }
+ - if milestone.present?
+ = link_to milestone[:title], milestone[:web_url], class: "bold has-tooltip", title: sidebar_milestone_remaining_days(milestone), data: { container: "body", html: 'true', boundary: 'viewport' }
- else
%span.no-value
= _('None')
.selectbox.hide-collapsed
- = f.hidden_field 'milestone_id', value: issuable.milestone_id, id: nil
- = dropdown_tag('Milestone', options: { title: _('Assign milestone'), toggle_class: 'js-milestone-select js-extra-options', filter: true, dropdown_class: 'dropdown-menu-selectable', placeholder: _('Search milestones'), data: { show_no: true, field_name: "#{issuable.to_ability_name}[milestone_id]", project_id: @project.id, issuable_id: issuable.id, milestones: project_milestones_path(@project, :json), ability_name: issuable.to_ability_name, issue_update: issuable_json_path(issuable), use_id: true, default_no: true, selected: (issuable.milestone.name if issuable.milestone), null_default: true, display: 'static' }})
- - if issuable.has_attribute?(:time_estimate)
- #issuable-time-tracker.block
- // Fallback while content is loading
- .title.hide-collapsed
- = _('Time tracking')
- = icon('spinner spin', 'aria-hidden': 'true')
- - if issuable.has_attribute?(:due_date)
+ = f.hidden_field 'milestone_id', value: milestone[:id], id: nil
+ = dropdown_tag('Milestone', options: { title: _('Assign milestone'), toggle_class: 'js-milestone-select js-extra-options', filter: true, dropdown_class: 'dropdown-menu-selectable', placeholder: _('Search milestones'), data: { show_no: true, field_name: "#{issuable_type}[milestone_id]", project_id: issuable_sidebar[:project_id], issuable_id: issuable_sidebar[:id], milestones: issuable_sidebar[:project_milestones_path], ability_name: issuable_type, issue_update: issuable_sidebar[:issuable_json_path], use_id: true, default_no: true, selected: milestone[:title], null_default: true, display: 'static' }})
+
+ #issuable-time-tracker.block
+ // Fallback while content is loading
+ .title.hide-collapsed
+ = _('Time tracking')
+ = icon('spinner spin', 'aria-hidden': 'true')
+
+ - if issuable_sidebar.has_key?(:due_date)
.block.due_date
- .sidebar-collapsed-icon.has-tooltip{ data: { placement: 'left', container: 'body', html: 'true', boundary: 'viewport' }, title: sidebar_due_date_tooltip_label(issuable) }
+ .sidebar-collapsed-icon.has-tooltip{ data: { placement: 'left', container: 'body', html: 'true', boundary: 'viewport' }, title: sidebar_due_date_tooltip_label(issuable_sidebar[:due_date]) }
= icon('calendar', 'aria-hidden': 'true')
%span.js-due-date-sidebar-value
- = issuable.due_date.try(:to_s, :medium) || 'None'
+ = issuable_sidebar[:due_date].try(:to_s, :medium) || 'None'
.title.hide-collapsed
= _('Due date')
= icon('spinner spin', class: 'hidden block-loading', 'aria-hidden': 'true')
- - if can?(current_user, :"admin_#{issuable.to_ability_name}", @project)
+ - if can_edit_issuable
= link_to _('Edit'), '#', class: 'js-sidebar-dropdown-toggle edit-link float-right'
.value.hide-collapsed
%span.value-content
- - if issuable.due_date
- %span.bold= issuable.due_date.to_s(:medium)
+ - if issuable_sidebar[:due_date]
+ %span.bold= issuable_sidebar[:due_date].to_s(:medium)
- else
%span.no-value
= _('No due date')
- - if can?(current_user, :"admin_#{issuable.to_ability_name}", @project)
- %span.no-value.js-remove-due-date-holder{ class: ("hidden" if issuable.due_date.nil?) }
+ - if can_edit_issuable
+ %span.no-value.js-remove-due-date-holder{ class: ("hidden" if issuable_sidebar[:due_date].nil?) }
\-
%a.js-remove-due-date{ href: "#", role: "button" }
= _('remove due date')
- - if can?(current_user, :"admin_#{issuable.to_ability_name}", @project)
+ - if can_edit_issuable
.selectbox.hide-collapsed
- = f.hidden_field :due_date, value: issuable.due_date.try(:strftime, 'yy-mm-dd')
+ = f.hidden_field :due_date, value: issuable_sidebar[:due_date].try(:strftime, 'yy-mm-dd')
.dropdown
- %button.dropdown-menu-toggle.js-due-date-select{ type: 'button', data: { toggle: 'dropdown', field_name: "#{issuable.to_ability_name}[due_date]", ability_name: issuable.to_ability_name, issue_update: issuable_json_path(issuable), display: 'static' } }
+ %button.dropdown-menu-toggle.js-due-date-select{ type: 'button', data: { toggle: 'dropdown', field_name: "#{issuable_type}[due_date]", ability_name: issuable_type, issue_update: issuable_sidebar[:issuable_json_path], display: 'static' } }
%span.dropdown-toggle-text
= _('Due date')
= icon('chevron-down', 'aria-hidden': 'true')
@@ -86,56 +92,56 @@
= dropdown_content do
.js-due-date-calendar
- - if @labels
- - selected_labels = issuable.labels
- .block.labels
- .sidebar-collapsed-icon.js-sidebar-labels-tooltip{ title: issuable_labels_tooltip(issuable.labels_array), data: { placement: "left", container: "body", boundary: 'viewport' } }
- = icon('tags', 'aria-hidden': 'true')
- %span
- = selected_labels.size
- .title.hide-collapsed
- = _('Labels')
- = icon('spinner spin', class: 'hidden block-loading', 'aria-hidden': 'true')
- - if can_edit_issuable
- = link_to _('Edit'), '#', class: 'js-sidebar-dropdown-toggle edit-link float-right'
- .value.issuable-show-labels.dont-hide.hide-collapsed.qa-labels-block{ class: ("has-labels" if selected_labels.any?) }
- - if selected_labels.any?
- - selected_labels.each do |label|
- = link_to_label(label, subject: issuable.project, type: issuable.to_ability_name)
- - else
- %span.no-value
- = _('None')
- .selectbox.hide-collapsed
+ - selected_labels = issuable_sidebar[:labels]
+ .block.labels
+ .sidebar-collapsed-icon.js-sidebar-labels-tooltip{ title: issuable_labels_tooltip(selected_labels), data: { placement: "left", container: "body", boundary: 'viewport' } }
+ = icon('tags', 'aria-hidden': 'true')
+ %span
+ = selected_labels.size
+ .title.hide-collapsed
+ = _('Labels')
+ = icon('spinner spin', class: 'hidden block-loading', 'aria-hidden': 'true')
+ - if can_edit_issuable
+ = link_to _('Edit'), '#', class: 'js-sidebar-dropdown-toggle edit-link float-right'
+ .value.issuable-show-labels.dont-hide.hide-collapsed.qa-labels-block{ class: ("has-labels" if selected_labels.any?) }
+ - if selected_labels.any?
- selected_labels.each do |label|
- = hidden_field_tag "#{issuable.to_ability_name}[label_names][]", label.id, id: nil
- .dropdown
- %button.dropdown-menu-toggle.js-label-select.js-multiselect.js-label-sidebar-dropdown{ type: "button", data: {toggle: "dropdown", default_label: "Labels", field_name: "#{issuable.to_ability_name}[label_names][]", ability_name: issuable.to_ability_name, show_no: "true", show_any: "true", namespace_path: @project.try(:namespace).try(:full_path), project_path: @project.try(:path), issue_update: issuable_json_path(issuable), labels: (labels_filter_path_with_defaults if @project), display: 'static' } }
- %span.dropdown-toggle-text{ class: ("is-default" if selected_labels.empty?) }
- = multi_label_name(selected_labels, "Labels")
- = icon('chevron-down', 'aria-hidden': 'true')
- .dropdown-menu.dropdown-select.dropdown-menu-paging.dropdown-menu-labels.dropdown-menu-selectable
- = render partial: "shared/issuable/label_page_default"
- - if can? current_user, :admin_label, @project and @project
- = render partial: "shared/issuable/label_page_create"
-
- = render_if_exists 'shared/issuable/sidebar_weight', issuable: issuable
-
- - if issuable.has_attribute?(:confidential)
+ = link_to sidebar_label_filter_path(issuable_sidebar[:project_issuables_path], label[:title]) do
+ %span.badge.color-label.has-tooltip{ style: "background-color: #{label[:color]}; color: #{label[:text_color]}", title: label[:description], data: { container: "body" } }
+ = label[:title]
+ - else
+ %span.no-value
+ = _('None')
+ .selectbox.hide-collapsed
+ - selected_labels.each do |label|
+ = hidden_field_tag "#{issuable_type}[label_names][]", label[:id], id: nil
+ .dropdown
+ %button.dropdown-menu-toggle.js-label-select.js-multiselect.js-label-sidebar-dropdown{ type: "button", data: {toggle: "dropdown", default_label: "Labels", field_name: "#{issuable_type}[label_names][]", ability_name: issuable_type, show_no: "true", show_any: "true", namespace_path: issuable_sidebar[:namespace_path], project_path: issuable_sidebar[:project_path], issue_update: issuable_sidebar[:issuable_json_path], labels: issuable_sidebar[:project_labels_path], display: 'static' } }
+ %span.dropdown-toggle-text{ class: ("is-default" if selected_labels.empty?) }
+ = multi_label_name(selected_labels, "Labels")
+ = icon('chevron-down', 'aria-hidden': 'true')
+ .dropdown-menu.dropdown-select.dropdown-menu-paging.dropdown-menu-labels.dropdown-menu-selectable
+ = render partial: "shared/issuable/label_page_default"
+ - if issuable_sidebar.dig(:current_user, :can_admin_label)
+ = render partial: "shared/issuable/label_page_create"
+
+ = render_if_exists 'shared/issuable/sidebar_weight', issuable_sidebar: issuable_sidebar
+
+ - if issuable_sidebar.has_key?(:confidential)
-# haml-lint:disable InlineJavaScript
- %script#js-confidential-issue-data{ type: "application/json" }= { is_confidential: @issue.confidential, is_editable: can_edit_issuable }.to_json.html_safe
+ %script#js-confidential-issue-data{ type: "application/json" }= { is_confidential: issuable_sidebar[:confidential], is_editable: can_edit_issuable }.to_json.html_safe
#js-confidential-entry-point
- - if issuable.has_attribute?(:discussion_locked)
- -# haml-lint:disable InlineJavaScript
- %script#js-lock-issue-data{ type: "application/json" }= { is_locked: issuable.discussion_locked?, is_editable: can_edit_issuable }.to_json.html_safe
- #js-lock-entry-point
+ -# haml-lint:disable InlineJavaScript
+ %script#js-lock-issue-data{ type: "application/json" }= { is_locked: issuable_sidebar[:discussion_locked], is_editable: can_edit_issuable }.to_json.html_safe
+ #js-lock-entry-point
.js-sidebar-participants-entry-point
- - if current_user
+ - if signed_in
.js-sidebar-subscriptions-entry-point
- - project_ref = cross_project_reference(@project, issuable)
+ - project_ref = issuable_sidebar[:reference]
.block.project-reference
.sidebar-collapsed-icon.dont-change-state
= clipboard_button(text: project_ref, title: _('Copy reference to clipboard'), placement: "left", boundary: 'viewport')
@@ -145,7 +151,8 @@
%cite{ title: project_ref }
= project_ref
= clipboard_button(text: project_ref, title: _('Copy reference to clipboard'), placement: "left", boundary: 'viewport')
- - if current_user && issuable.can_move?(current_user)
+
+ - if issuable_sidebar.dig(:current_user, :can_move)
.block.js-sidebar-move-issue-block
.sidebar-collapsed-icon{ data: { toggle: 'tooltip', placement: 'left', container: 'body', boundary: 'viewport' }, title: _('Move issue') }
= custom_icon('icon_arrow_right')
@@ -164,4 +171,4 @@
= icon('spinner spin', class: 'sidebar-move-issue-confirmation-loading-icon')
-# haml-lint:disable InlineJavaScript
- %script.js-sidebar-options{ type: "application/json" }= issuable_sidebar_options(issuable, can_edit_issuable).to_json.html_safe
+ %script.js-sidebar-options{ type: "application/json" }= issuable_sidebar_options(issuable_sidebar).to_json.html_safe
diff --git a/app/views/shared/issuable/_sidebar_assignees.html.haml b/app/views/shared/issuable/_sidebar_assignees.html.haml
index 8a13c7a3b83..c5cce1823f0 100644
--- a/app/views/shared/issuable/_sidebar_assignees.html.haml
+++ b/app/views/shared/issuable/_sidebar_assignees.html.haml
@@ -1,12 +1,17 @@
-- if issuable.is_a?(Issue)
- #js-vue-sidebar-assignees{ data: { field: "#{issuable.to_ability_name}[assignee_ids]", signed_in: signed_in } }
+- issuable_type = issuable_sidebar[:type]
+- signed_in = !!issuable_sidebar.dig(:current_user, :id)
+- can_edit_issuable = issuable_sidebar.dig(:current_user, :can_edit)
+
+- if issuable_type == "issue"
+ #js-vue-sidebar-assignees{ data: { field: "#{issuable_type}[assignee_ids]", signed_in: signed_in } }
.title.hide-collapsed
= _('Assignee')
= icon('spinner spin')
- else
- .sidebar-collapsed-icon.sidebar-collapsed-user{ data: { toggle: "tooltip", placement: "left", container: "body", boundary: 'viewport' }, title: sidebar_assignee_tooltip_label(issuable) }
- - if issuable.assignee
- = link_to_member(@project, issuable.assignee, size: 24)
+ - assignee = assignees.first
+ .sidebar-collapsed-icon.sidebar-collapsed-user{ data: { toggle: "tooltip", placement: "left", container: "body", boundary: 'viewport' }, title: (issuable_sidebar.dig(:assignee, :name) || _('Assignee')) }
+ - if issuable_sidebar[:assignee]
+ = link_to_member(@project, assignee, size: 24)
- else
= icon('user', 'aria-hidden': 'true')
.title.hide-collapsed
@@ -18,13 +23,13 @@
%a.gutter-toggle.float-right.js-sidebar-toggle{ role: "button", href: "#", "aria-label" => _('Toggle sidebar') }
= sidebar_gutter_toggle_icon
.value.hide-collapsed
- - if issuable.assignee
- = link_to_member(@project, issuable.assignee, size: 32, extra_class: 'bold') do
- - if !issuable.can_be_merged_by?(issuable.assignee)
+ - if issuable_sidebar[:assignee]
+ = link_to_member(@project, assignee, size: 32, extra_class: 'bold') do
+ - if issuable_sidebar[:assignee][:can_merge]
%span.float-right.cannot-be-merged{ data: { toggle: 'tooltip', placement: 'left' }, title: _('Not allowed to merge') }
= icon('exclamation-triangle', 'aria-hidden': 'true')
%span.username
- = issuable.assignee.to_reference
+ @#{issuable_sidebar[:assignee][:username]}
- else
%span.assign-yourself.no-value
= _('No assignee')
@@ -34,19 +39,33 @@
= _('assign yourself')
.selectbox.hide-collapsed
- - issuable.assignees.each do |assignee|
- = hidden_field_tag "#{issuable.to_ability_name}[assignee_ids][]", assignee.id, id: nil, data: { avatar_url: assignee.avatar_url, name: assignee.name, username: assignee.username }
+ - if assignees.none?
+ = hidden_field_tag "#{issuable_type}[assignee_ids][]", 0, id: nil
+ - else
+ - assignees.each do |assignee|
+ = hidden_field_tag "#{issuable_type}[assignee_ids][]", assignee.id, id: nil, data: { avatar_url: assignee.avatar_url, name: assignee.name, username: assignee.username }
- - options = { toggle_class: 'js-user-search js-author-search', title: _('Assign to'), filter: true, dropdown_class: 'dropdown-menu-user dropdown-menu-selectable dropdown-menu-author', placeholder: _('Search users'), data: { first_user: current_user&.username, current_user: true, project_id: @project&.id, author_id: issuable.author_id, field_name: "#{issuable.to_ability_name}[assignee_ids][]", issue_update: issuable_json_path(issuable), ability_name: issuable.to_ability_name, null_user: true, display: 'static' } }
+ - options = { toggle_class: 'js-user-search js-author-search',
+ title: _('Assign to'),
+ filter: true,
+ dropdown_class: 'dropdown-menu-user dropdown-menu-selectable dropdown-menu-author',
+ placeholder: _('Search users'),
+ data: { first_user: issuable_sidebar.dig(:current_user, :username),
+ current_user: true,
+ project_id: issuable_sidebar[:project_id],
+ author_id: issuable_sidebar[:author_id],
+ field_name: "#{issuable_type}[assignee_ids][]",
+ issue_update: issuable_sidebar[:issuable_json_path],
+ ability_name: issuable_type,
+ null_user: true,
+ display: 'static' } }
- title = _('Select assignee')
- - if issuable.is_a?(Issue)
- - unless issuable.assignees.any?
- = hidden_field_tag "#{issuable.to_ability_name}[assignee_ids][]", 0, id: nil
+ - if issuable_type == "issue"
- dropdown_options = issue_assignees_dropdown_options
- title = dropdown_options[:title]
- options[:toggle_class] += ' js-multiselect js-save-user-data'
- - data = { field_name: "#{issuable.to_ability_name}[assignee_ids][]" }
+ - data = { field_name: "#{issuable_type}[assignee_ids][]" }
- data[:multi_select] = true
- data['dropdown-title'] = title
- data['dropdown-header'] = dropdown_options[:data][:'dropdown-header']
diff --git a/app/views/shared/issuable/_sidebar_todo.html.haml b/app/views/shared/issuable/_sidebar_todo.html.haml
index 660ee6d5777..de4df016cfb 100644
--- a/app/views/shared/issuable/_sidebar_todo.html.haml
+++ b/app/views/shared/issuable/_sidebar_todo.html.haml
@@ -1,15 +1,15 @@
- is_collapsed = local_assigns.fetch(:is_collapsed, false)
-- mark_content = is_collapsed ? sprite_icon('todo-done', css_class: 'todo-undone') : _('Mark todo as done')
-- todo_content = is_collapsed ? sprite_icon('todo-add') : _('Add todo')
+- has_todo = !!issuable_sidebar.dig(:current_user, :todo, :id)
+
+- todo_button_data = issuable_todo_button_data(issuable_sidebar, is_collapsed)
+- button_title = has_todo ? todo_button_data[:mark_text] : todo_button_data[:todo_text]
+- button_icon = has_todo ? todo_button_data[:mark_icon] : todo_button_data[:todo_icon]
%button.issuable-todo-btn.js-issuable-todo{ type: 'button',
class: (is_collapsed ? 'btn-blank sidebar-collapsed-icon dont-change-state has-tooltip' : 'btn btn-default issuable-header-btn float-right'),
- title: (todo.nil? ? _('Add todo') : _('Mark todo as done')),
- 'aria-label' => (todo.nil? ? _('Add todo') : _('Mark todo as done')),
- data: issuable_todo_button_data(issuable, todo, is_collapsed) }
+ title: button_title,
+ 'aria-label' => button_title,
+ data: todo_button_data }
%span.issuable-todo-inner.js-issuable-todo-inner<
- - if todo
- = mark_content
- - else
- = todo_content
+ = is_collapsed ? button_icon : button_title
= icon('spin spinner', 'aria-hidden': 'true')
diff --git a/app/views/shared/issuable/form/_metadata.html.haml b/app/views/shared/issuable/form/_metadata.html.haml
index ac8d58c0bfe..e370dff9526 100644
--- a/app/views/shared/issuable/form/_metadata.html.haml
+++ b/app/views/shared/issuable/form/_metadata.html.haml
@@ -19,10 +19,9 @@
.issuable-form-select-holder
= render "shared/issuable/milestone_dropdown", selected: issuable.milestone, name: "#{issuable.class.model_name.param_key}[milestone_id]", show_any: false, show_upcoming: false, show_started: false, extra_class: "qa-issuable-milestone-dropdown js-issuable-form-dropdown js-dropdown-keep-input", dropdown_title: "Select milestone"
.form-group.row
- - has_labels = @labels && @labels.any?
= form.label :label_ids, "Labels", class: "col-form-label #{has_due_date ? "col-md-2 col-lg-4" : "col-sm-2"}"
= form.hidden_field :label_ids, multiple: true, value: ''
- .col-sm-10{ class: "#{"col-md-8" if has_due_date} #{'issuable-form-padding-top' if !has_labels}" }
+ .col-sm-10{ class: "#{"col-md-8" if has_due_date}" }
.issuable-form-select-holder
= render "shared/issuable/label_dropdown", classes: ["js-issuable-form-dropdown"], selected: issuable.labels, data_options: { field_name: "#{issuable.class.model_name.param_key}[label_ids][]", show_any: false }, dropdown_title: "Select label"
diff --git a/app/views/shared/milestones/_sidebar.html.haml b/app/views/shared/milestones/_sidebar.html.haml
index becd1c4884e..b24075c7849 100644
--- a/app/views/shared/milestones/_sidebar.html.haml
+++ b/app/views/shared/milestones/_sidebar.html.haml
@@ -65,7 +65,7 @@
%span.bold= milestone.due_date.to_s(:medium)
- else
%span.no-value No due date
- - remaining_days = remaining_days_in_words(milestone)
+ - remaining_days = remaining_days_in_words(milestone.due_date, milestone.start_date)
- if remaining_days.present?
= surround '(', ')' do
%span.remaining-days= remaining_days
diff --git a/app/views/shared/projects/_project.html.haml b/app/views/shared/projects/_project.html.haml
index 9dde77fccef..fea7e17be3d 100644
--- a/app/views/shared/projects/_project.html.haml
+++ b/app/views/shared/projects/_project.html.haml
@@ -72,13 +72,13 @@
title: _('Forks'), data: { container: 'body', placement: 'top' } do
= sprite_icon('fork', size: 14, css_class: 'append-right-4')
= number_with_delimiter(project.forks_count)
- - if show_merge_request_count?(merge_requests, compact_mode)
+ - if show_merge_request_count?(disabled: !merge_requests, compact_mode: compact_mode)
= link_to project_merge_requests_path(project),
class: "d-none d-lg-flex align-items-center icon-wrapper merge-requests has-tooltip",
title: _('Merge Requests'), data: { container: 'body', placement: 'top' } do
= sprite_icon('git-merge', size: 14, css_class: 'append-right-4')
= number_with_delimiter(project.open_merge_requests_count)
- - if show_issue_count?(issues, compact_mode)
+ - if show_issue_count?(disabled: !issues, compact_mode: compact_mode)
= link_to project_issues_path(project),
class: "d-none d-lg-flex align-items-center icon-wrapper issues has-tooltip",
title: _('Issues'), data: { container: 'body', placement: 'top' } do
diff --git a/app/workers/all_queues.yml b/app/workers/all_queues.yml
index bc26b3f8ef2..d3cf21db335 100644
--- a/app/workers/all_queues.yml
+++ b/app/workers/all_queues.yml
@@ -27,7 +27,7 @@
- gcp_cluster:cluster_wait_for_app_installation
- gcp_cluster:wait_for_cluster_creation
- gcp_cluster:cluster_wait_for_ingress_ip_address
-- gcp_cluster:cluster_platform_configure
+- gcp_cluster:cluster_configure
- gcp_cluster:cluster_project_configure
- github_import_advance_stage
@@ -88,6 +88,7 @@
- object_pool:object_pool_create
- object_pool:object_pool_schedule_join
- object_pool:object_pool_join
+- object_pool:object_pool_destroy
- default
- mailers # ActionMailer::DeliveryJob.queue_name
diff --git a/app/workers/cluster_platform_configure_worker.rb b/app/workers/cluster_configure_worker.rb
index aa7570caa79..63e6cc147be 100644
--- a/app/workers/cluster_platform_configure_worker.rb
+++ b/app/workers/cluster_configure_worker.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class ClusterPlatformConfigureWorker
+class ClusterConfigureWorker
include ApplicationWorker
include ClusterQueue
diff --git a/app/workers/cluster_provision_worker.rb b/app/workers/cluster_provision_worker.rb
index 3d5894b73ec..926ae2b7286 100644
--- a/app/workers/cluster_provision_worker.rb
+++ b/app/workers/cluster_provision_worker.rb
@@ -10,7 +10,7 @@ class ClusterProvisionWorker
Clusters::Gcp::ProvisionService.new.execute(provider) if cluster.gcp?
end
- ClusterPlatformConfigureWorker.perform_async(cluster.id) if cluster.user?
+ ClusterConfigureWorker.perform_async(cluster.id) if cluster.user?
end
end
end
diff --git a/app/workers/object_pool/destroy_worker.rb b/app/workers/object_pool/destroy_worker.rb
new file mode 100644
index 00000000000..ca00d467d9b
--- /dev/null
+++ b/app/workers/object_pool/destroy_worker.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+module ObjectPool
+ class DestroyWorker
+ include ApplicationWorker
+ include ObjectPoolQueue
+
+ def perform(pool_repository_id)
+ pool = PoolRepository.find_by_id(pool_repository_id)
+ return unless pool&.obsolete?
+
+ pool.delete_object_pool
+ pool.destroy
+ end
+ end
+end
diff --git a/app/workers/stuck_merge_jobs_worker.rb b/app/workers/stuck_merge_jobs_worker.rb
index 98c81956cba..f34ed6c4844 100644
--- a/app/workers/stuck_merge_jobs_worker.rb
+++ b/app/workers/stuck_merge_jobs_worker.rb
@@ -4,6 +4,10 @@ class StuckMergeJobsWorker
include ApplicationWorker
include CronjobQueue
+ def self.logger
+ Rails.logger
+ end
+
# rubocop: disable CodeReuse/ActiveRecord
def perform
stuck_merge_requests.find_in_batches(batch_size: 100) do |group|
@@ -35,7 +39,7 @@ class StuckMergeJobsWorker
# We rely on state machine callbacks to update head_pipeline_id
merge_requests_to_reopen.each(&:unlock_mr)
- Rails.logger.info("Updated state of locked merge jobs. JIDs: #{completed_jids.join(', ')}")
+ self.class.logger.info("Updated state of locked merge jobs. JIDs: #{completed_jids.join(', ')}")
end
# rubocop: enable CodeReuse/ActiveRecord
diff --git a/changelogs/unreleased/19376-post-bfg-cleanup.yml b/changelogs/unreleased/19376-post-bfg-cleanup.yml
deleted file mode 100644
index fc1bcc30db9..00000000000
--- a/changelogs/unreleased/19376-post-bfg-cleanup.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Use BFG object maps to clean projects
-merge_request: 23189
-author:
-type: added
diff --git a/changelogs/unreleased/1979-redesign-mr-widget-approvals-ce.yml b/changelogs/unreleased/1979-redesign-mr-widget-approvals-ce.yml
deleted file mode 100644
index d05b6054b22..00000000000
--- a/changelogs/unreleased/1979-redesign-mr-widget-approvals-ce.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Redesign of MR header sections (CE)
-merge_request: 23465
-author:
-type: changed
diff --git a/changelogs/unreleased/20422-hide-ui-variables-by-default.yml b/changelogs/unreleased/20422-hide-ui-variables-by-default.yml
deleted file mode 100644
index 60285d49718..00000000000
--- a/changelogs/unreleased/20422-hide-ui-variables-by-default.yml
+++ /dev/null
@@ -1,6 +0,0 @@
----
-title: Pipeline trigger variable values are hidden in the UI by default. Maintainers
- have the option to reveal them.
-merge_request: 23518
-author: jhampton
-type: added
diff --git a/changelogs/unreleased/22548-reopen-error-message.yml b/changelogs/unreleased/22548-reopen-error-message.yml
deleted file mode 100644
index 79c20eccb12..00000000000
--- a/changelogs/unreleased/22548-reopen-error-message.yml
+++ /dev/null
@@ -1,6 +0,0 @@
----
-title: Show error message when attempting to reopen an MR and there is an open MR
- for the same branch
-merge_request: 16447
-author: Akos Gyimesi
-type: fixed
diff --git a/changelogs/unreleased/23367-clarify-docs-allow-failure.yml b/changelogs/unreleased/23367-clarify-docs-allow-failure.yml
new file mode 100644
index 00000000000..221d9e83ffb
--- /dev/null
+++ b/changelogs/unreleased/23367-clarify-docs-allow-failure.yml
@@ -0,0 +1,5 @@
+---
+title: Clarifies docs about CI `allow_failure`
+merge_request: 23367
+author: C.J. Jameson
+type: other
diff --git a/changelogs/unreleased/33705-merge-request-rebase-api.yml b/changelogs/unreleased/33705-merge-request-rebase-api.yml
deleted file mode 100644
index 322fe31ce87..00000000000
--- a/changelogs/unreleased/33705-merge-request-rebase-api.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Add a rebase API endpoint for merge requests
-merge_request: 23296
-author:
-type: added
diff --git a/changelogs/unreleased/34758-deployment-cluster.yml b/changelogs/unreleased/34758-deployment-cluster.yml
deleted file mode 100644
index 06374098343..00000000000
--- a/changelogs/unreleased/34758-deployment-cluster.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Use group clusters when deploying (DeploymentPlatform)
-merge_request: 22308
-author:
-type: changed
diff --git a/changelogs/unreleased/34758-group-cluster-controller.yml b/changelogs/unreleased/34758-group-cluster-controller.yml
deleted file mode 100644
index 88c4c872714..00000000000
--- a/changelogs/unreleased/34758-group-cluster-controller.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Add ability to create group level clusters and install gitlab managed applications
-merge_request: 22450
-author:
-type: added
diff --git a/changelogs/unreleased/38495-calendar-activities-in-timezone.yml b/changelogs/unreleased/38495-calendar-activities-in-timezone.yml
deleted file mode 100644
index 778d637609c..00000000000
--- a/changelogs/unreleased/38495-calendar-activities-in-timezone.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Show user contributions in correct timezone within user profile
-merge_request: 23419
-author:
-type: changed
diff --git a/changelogs/unreleased/39849_controller_sorts.yml b/changelogs/unreleased/39849_controller_sorts.yml
deleted file mode 100644
index 5fad0cb4ede..00000000000
--- a/changelogs/unreleased/39849_controller_sorts.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Allow sorting issues and MRs in reverse order
-merge_request: 21438
-author:
-type: changed
diff --git a/changelogs/unreleased/40085-add-a-create_merge_request-quick-action.yml b/changelogs/unreleased/40085-add-a-create_merge_request-quick-action.yml
deleted file mode 100644
index e1614ac7669..00000000000
--- a/changelogs/unreleased/40085-add-a-create_merge_request-quick-action.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Creates /create_merge_request quickaction
-merge_request: 22485
-author: Jacopo Beschi @jacopo-beschi
-type: added
diff --git a/changelogs/unreleased/40260-reduce-gitaly-calls-project-pipeline-status.yml b/changelogs/unreleased/40260-reduce-gitaly-calls-project-pipeline-status.yml
deleted file mode 100644
index 8ab104e95f5..00000000000
--- a/changelogs/unreleased/40260-reduce-gitaly-calls-project-pipeline-status.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Reduce Gitaly calls in projects dashboard
-merge_request: 23307
-author:
-type: performance
diff --git a/changelogs/unreleased/40270-remove-gitlab-upgrader-completely.yml b/changelogs/unreleased/40270-remove-gitlab-upgrader-completely.yml
new file mode 100644
index 00000000000..9ea2157bfb7
--- /dev/null
+++ b/changelogs/unreleased/40270-remove-gitlab-upgrader-completely.yml
@@ -0,0 +1,5 @@
+---
+title: Removes all instances of deprecated Gitlab Upgrader calls
+merge_request: 23603
+author: '@jwolen'
+type: removed
diff --git a/changelogs/unreleased/40385-prohibit_impersonation.yml b/changelogs/unreleased/40385-prohibit_impersonation.yml
deleted file mode 100644
index dd061b17939..00000000000
--- a/changelogs/unreleased/40385-prohibit_impersonation.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Add config to prohibit impersonation
-merge_request: 23338
-author:
-type: added
diff --git a/changelogs/unreleased/41766-vuex-store.yml b/changelogs/unreleased/41766-vuex-store.yml
new file mode 100644
index 00000000000..f20fc736a6f
--- /dev/null
+++ b/changelogs/unreleased/41766-vuex-store.yml
@@ -0,0 +1,5 @@
+---
+title: Creates frontend app for releases
+merge_request: 23796
+author:
+type: added
diff --git a/changelogs/unreleased/41875-allow-pipelines-to-be-deleted-by-project-owners.yml b/changelogs/unreleased/41875-allow-pipelines-to-be-deleted-by-project-owners.yml
deleted file mode 100644
index 0662ff6f523..00000000000
--- a/changelogs/unreleased/41875-allow-pipelines-to-be-deleted-by-project-owners.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Allow deleting a Pipeline via the API.
-merge_request: 22988
-author:
-type: added
diff --git a/changelogs/unreleased/42125-extend-override-check-to-also-check-arity.yml b/changelogs/unreleased/42125-extend-override-check-to-also-check-arity.yml
new file mode 100644
index 00000000000..9892466ca50
--- /dev/null
+++ b/changelogs/unreleased/42125-extend-override-check-to-also-check-arity.yml
@@ -0,0 +1,5 @@
+---
+title: Extend override check to also check arity
+merge_request: 23498
+author: Jacopo Beschi @jacopo-beschi
+type: added
diff --git a/changelogs/unreleased/44984-use-serializer-for-issuable-sidebar.yml b/changelogs/unreleased/44984-use-serializer-for-issuable-sidebar.yml
new file mode 100644
index 00000000000..ba9edc8740d
--- /dev/null
+++ b/changelogs/unreleased/44984-use-serializer-for-issuable-sidebar.yml
@@ -0,0 +1,5 @@
+---
+title: Refactor issuable sidebar to use serializer
+merge_request: 23379
+author:
+type: other
diff --git a/changelogs/unreleased/46544-webide-ctrl-enter-commit-shortcut.yml b/changelogs/unreleased/46544-webide-ctrl-enter-commit-shortcut.yml
deleted file mode 100644
index 334c9b3ec9e..00000000000
--- a/changelogs/unreleased/46544-webide-ctrl-enter-commit-shortcut.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: "WebIDE: Pressing Ctrl-Enter while typing on the commit message now performs the commit action"
-merge_request: 23049
-author: Thomas Pathier
-type: added
diff --git a/changelogs/unreleased/46950-systemcheck-ruby-version.yml b/changelogs/unreleased/46950-systemcheck-ruby-version.yml
deleted file mode 100644
index e556e14223b..00000000000
--- a/changelogs/unreleased/46950-systemcheck-ruby-version.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: 'SystemCheck: Use a more reliable way to detect current Ruby version'
-merge_request: 23291
-author:
-type: changed
diff --git a/changelogs/unreleased/48475-gitlab-pages-settings-regressions.yml b/changelogs/unreleased/48475-gitlab-pages-settings-regressions.yml
deleted file mode 100644
index f543730a57d..00000000000
--- a/changelogs/unreleased/48475-gitlab-pages-settings-regressions.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fixing regression issues on pages settings and details
-merge_request: 22821
-author:
-type: fixed
diff --git a/changelogs/unreleased/48496-merge-request-refactor-does-not-highlight-selected-line.yml b/changelogs/unreleased/48496-merge-request-refactor-does-not-highlight-selected-line.yml
deleted file mode 100644
index cfc74bef638..00000000000
--- a/changelogs/unreleased/48496-merge-request-refactor-does-not-highlight-selected-line.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: When user clicks linenumber in MR changes, highlight that line
-merge_request:
-author:
-type: fixed
diff --git a/changelogs/unreleased/48889-populate-merge_commit_sha.yml b/changelogs/unreleased/48889-populate-merge_commit_sha.yml
deleted file mode 100644
index 0e25d8ecfb0..00000000000
--- a/changelogs/unreleased/48889-populate-merge_commit_sha.yml
+++ /dev/null
@@ -1,6 +0,0 @@
----
-title: Fix "merged with [commit]" info for merge requests being merged automatically
- by other actions
-merge_request: 22794
-author:
-type: fixed
diff --git a/changelogs/unreleased/49479-hide-unmerged-env-perf-stats.yml b/changelogs/unreleased/49479-hide-unmerged-env-perf-stats.yml
deleted file mode 100644
index 5118949f8a3..00000000000
--- a/changelogs/unreleased/49479-hide-unmerged-env-perf-stats.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Don't show Memory Usage for unmerged MRs
-merge_request:
-author:
-type: changed
diff --git a/changelogs/unreleased/49565-ssh-push-mirroring.yml b/changelogs/unreleased/49565-ssh-push-mirroring.yml
deleted file mode 100644
index 2dfeffa4088..00000000000
--- a/changelogs/unreleased/49565-ssh-push-mirroring.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Allow SSH public-key authentication for push mirroring
-merge_request: 22982
-author:
-type: added
diff --git a/changelogs/unreleased/49713-main-navbar-is-broken-in-certain-viewport-widths.yml b/changelogs/unreleased/49713-main-navbar-is-broken-in-certain-viewport-widths.yml
deleted file mode 100644
index 0b5d1a6b05a..00000000000
--- a/changelogs/unreleased/49713-main-navbar-is-broken-in-certain-viewport-widths.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Resolve Main navbar is broken in certain viewport widths
-merge_request: 23348
-author:
-type: fixed
diff --git a/changelogs/unreleased/49726-upgrade-helm-to-2-11.yml b/changelogs/unreleased/49726-upgrade-helm-to-2-11.yml
deleted file mode 100644
index dd26af875f5..00000000000
--- a/changelogs/unreleased/49726-upgrade-helm-to-2-11.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Upgrade helm to 2.11.0 and upgrade on every install
-merge_request: 22693
-author:
-type: added
diff --git a/changelogs/unreleased/50157-extended-user-centric-tooltips.yml b/changelogs/unreleased/50157-extended-user-centric-tooltips.yml
deleted file mode 100644
index 3b55a867b87..00000000000
--- a/changelogs/unreleased/50157-extended-user-centric-tooltips.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Extended user centric tooltips on issue and MR page
-merge_request: 23231
-author:
-type: added
diff --git a/changelogs/unreleased/50264-add-border-around-the-repository-file-tree.yml b/changelogs/unreleased/50264-add-border-around-the-repository-file-tree.yml
deleted file mode 100644
index 6315c3e7f36..00000000000
--- a/changelogs/unreleased/50264-add-border-around-the-repository-file-tree.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Resolve Add border around the repository file tree
-merge_request: 23018
-author:
-type: changed
diff --git a/changelogs/unreleased/50341-cleanup-useless-project-import-attributes.yml b/changelogs/unreleased/50341-cleanup-useless-project-import-attributes.yml
deleted file mode 100644
index 3893f14e15c..00000000000
--- a/changelogs/unreleased/50341-cleanup-useless-project-import-attributes.yml
+++ /dev/null
@@ -1,6 +0,0 @@
----
-title: Removes all the irrelevant code and columns that were migrated from the Project
- table over to the ProjectImportState table
-merge_request: 21497
-author:
-type: performance
diff --git a/changelogs/unreleased/50626-searching-users-by-the-admin-panel-wipes-query-when-using-sort.yml b/changelogs/unreleased/50626-searching-users-by-the-admin-panel-wipes-query-when-using-sort.yml
deleted file mode 100644
index c3251fea54d..00000000000
--- a/changelogs/unreleased/50626-searching-users-by-the-admin-panel-wipes-query-when-using-sort.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Allow search and sort users at same time on admin users page
-merge_request: 23439
-author:
-type: fixed
diff --git a/changelogs/unreleased/50839-webide-mr-dropdown-filter.yml b/changelogs/unreleased/50839-webide-mr-dropdown-filter.yml
deleted file mode 100644
index 1c6c8747197..00000000000
--- a/changelogs/unreleased/50839-webide-mr-dropdown-filter.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Scope default MR search in WebIDE dropdown to current project
-merge_request: 23400
-author:
-type: changed
diff --git a/changelogs/unreleased/51029-status-emoji-currently-replaces-avatar-on-mobile.yml b/changelogs/unreleased/51029-status-emoji-currently-replaces-avatar-on-mobile.yml
deleted file mode 100644
index dc11ede5c8d..00000000000
--- a/changelogs/unreleased/51029-status-emoji-currently-replaces-avatar-on-mobile.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Resolve status emoji being replaced by avatar on mobile
-merge_request: 23408
-author:
-type: other
diff --git a/changelogs/unreleased/51061-readme-url-n-1-rpc-call-resolved.yml b/changelogs/unreleased/51061-readme-url-n-1-rpc-call-resolved.yml
deleted file mode 100644
index 86f91fcb427..00000000000
--- a/changelogs/unreleased/51061-readme-url-n-1-rpc-call-resolved.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Improves performance of Project#readme_url by caching the README path
-merge_request: 23357
-author:
-type: performance
diff --git a/changelogs/unreleased/51083-fix-move-api.yml b/changelogs/unreleased/51083-fix-move-api.yml
deleted file mode 100644
index 8838f6f267e..00000000000
--- a/changelogs/unreleased/51083-fix-move-api.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: 'Commits API: Preserve file content in move operations if unspecified'
-merge_request: 23387
-author:
-type: fixed
diff --git a/changelogs/unreleased/51101-can-add-an-existing-group-member-into-a-group-project-with-new-permissions-but-permissions-are-not-overridde.yml b/changelogs/unreleased/51101-can-add-an-existing-group-member-into-a-group-project-with-new-permissions-but-permissions-are-not-overridde.yml
deleted file mode 100644
index 96f33a72cc5..00000000000
--- a/changelogs/unreleased/51101-can-add-an-existing-group-member-into-a-group-project-with-new-permissions-but-permissions-are-not-overridde.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Restrict member access level to be higher than that of any parent group
-merge_request: 23226
-author:
-type: fixed
diff --git a/changelogs/unreleased/51122-fix-navigating-discussions.yml b/changelogs/unreleased/51122-fix-navigating-discussions.yml
deleted file mode 100644
index 94d76654589..00000000000
--- a/changelogs/unreleased/51122-fix-navigating-discussions.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix navigating by unresolved discussions on Merge Request page
-merge_request: 22789
-author:
-type: fixed
diff --git a/changelogs/unreleased/51138-54026-breadcrumb-subgroups-ellipsis.yml b/changelogs/unreleased/51138-54026-breadcrumb-subgroups-ellipsis.yml
deleted file mode 100644
index f695d5aeff8..00000000000
--- a/changelogs/unreleased/51138-54026-breadcrumb-subgroups-ellipsis.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: "Make auto-generated icons for subgroups in the breadcrumb dropdown display as a circle"
-merge_request: 23062
-author: Thomas Pathier
-type: fix \ No newline at end of file
diff --git a/changelogs/unreleased/51243-further-improvements-to-project-overview-ui.yml b/changelogs/unreleased/51243-further-improvements-to-project-overview-ui.yml
deleted file mode 100644
index ddb5eaa89d0..00000000000
--- a/changelogs/unreleased/51243-further-improvements-to-project-overview-ui.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Design improvements to project overview page
-merge_request: 22196
-author:
-type: changed
diff --git a/changelogs/unreleased/51259-ci-cd-gitlab-ui-1.yml b/changelogs/unreleased/51259-ci-cd-gitlab-ui-1.yml
deleted file mode 100644
index 1d761d6299c..00000000000
--- a/changelogs/unreleased/51259-ci-cd-gitlab-ui-1.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Uses new gitlab-ui components in Jobs and Pipelines components
-merge_request:
-author:
-type: other
diff --git a/changelogs/unreleased/51259-ci-cd-tooltips.yml b/changelogs/unreleased/51259-ci-cd-tooltips.yml
deleted file mode 100644
index fc0010dbeba..00000000000
--- a/changelogs/unreleased/51259-ci-cd-tooltips.yml
+++ /dev/null
@@ -1,6 +0,0 @@
----
-title: Replaces tooltip directive with the new gl-tooltip directive for consistency
- in some ci/cd code
-merge_request:
-author:
-type: other
diff --git a/changelogs/unreleased/51606-expanding-a-diff-while-having-an-open-comment-form-will-always-scroll-down-to-the-comment.yml b/changelogs/unreleased/51606-expanding-a-diff-while-having-an-open-comment-form-will-always-scroll-down-to-the-comment.yml
new file mode 100644
index 00000000000..a845234b42f
--- /dev/null
+++ b/changelogs/unreleased/51606-expanding-a-diff-while-having-an-open-comment-form-will-always-scroll-down-to-the-comment.yml
@@ -0,0 +1,5 @@
+---
+title: Stop autofocusing on diff comment after initial mount
+merge_request: 23849
+author:
+type: fixed
diff --git a/changelogs/unreleased/51668-fix-line-numbers.yml b/changelogs/unreleased/51668-fix-line-numbers.yml
new file mode 100644
index 00000000000..ac6e45e3cc7
--- /dev/null
+++ b/changelogs/unreleased/51668-fix-line-numbers.yml
@@ -0,0 +1,5 @@
+---
+title: Adjust line-height of blame view line numbers
+merge_request:
+author:
+type: fixed
diff --git a/changelogs/unreleased/51792-dont-delete-failed-install-pods.yml b/changelogs/unreleased/51792-dont-delete-failed-install-pods.yml
deleted file mode 100644
index 7a900cbb86e..00000000000
--- a/changelogs/unreleased/51792-dont-delete-failed-install-pods.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Don't remove failed install pods after installing GitLab managed applications
-merge_request: 23350
-author:
-type: changed
diff --git a/changelogs/unreleased/51959-branch-and-tag-name-links.yml b/changelogs/unreleased/51959-branch-and-tag-name-links.yml
deleted file mode 100644
index 64f1522c70d..00000000000
--- a/changelogs/unreleased/51959-branch-and-tag-name-links.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Chat message push notifications now include links back to GitLab branches
-merge_request: 22651
-author: Tony Castrogiovanni
-type: added
diff --git a/changelogs/unreleased/52007-frontmatter-toml-json.yml b/changelogs/unreleased/52007-frontmatter-toml-json.yml
deleted file mode 100644
index bdada19f3a7..00000000000
--- a/changelogs/unreleased/52007-frontmatter-toml-json.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Changed frontmatter filtering to support YAML, JSON, TOML, and arbitrary languages
-merge_request: 23331
-author: Travis Miller
-type: changed
diff --git a/changelogs/unreleased/52276-jump-to-top-in-merge-request.yml b/changelogs/unreleased/52276-jump-to-top-in-merge-request.yml
deleted file mode 100644
index 3dc95441eec..00000000000
--- a/changelogs/unreleased/52276-jump-to-top-in-merge-request.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Allow user to scroll to top of tab on MR page
-merge_request:
-author:
-type: added
diff --git a/changelogs/unreleased/52285-omniauth-jwt-ppk-support.yml b/changelogs/unreleased/52285-omniauth-jwt-ppk-support.yml
deleted file mode 100644
index 3ef564238c5..00000000000
--- a/changelogs/unreleased/52285-omniauth-jwt-ppk-support.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Support RSA and ECDSA algorithms in Omniauth JWT provider
-merge_request: 23411
-author: Michael Tsyganov
-type: fixed
diff --git a/changelogs/unreleased/52370-filter-by-none-any-for-labels-in-issues-mrs-boards.yml b/changelogs/unreleased/52370-filter-by-none-any-for-labels-in-issues-mrs-boards.yml
deleted file mode 100644
index 9e1ee3ede5e..00000000000
--- a/changelogs/unreleased/52370-filter-by-none-any-for-labels-in-issues-mrs-boards.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Adds Any option to label filters
-merge_request: 23111
-author: Jacopo Beschi @jacopo-beschi
-type: added
diff --git a/changelogs/unreleased/52371-filter-by-none-any-for-labels-in-issues-mrs-api.yml b/changelogs/unreleased/52371-filter-by-none-any-for-labels-in-issues-mrs-api.yml
deleted file mode 100644
index bb196af3e90..00000000000
--- a/changelogs/unreleased/52371-filter-by-none-any-for-labels-in-issues-mrs-api.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Filter by None/Any for labels in issues/mrs API
-merge_request: 22622
-author: Jacopo Beschi @jacopo-beschi
-type: added
diff --git a/changelogs/unreleased/52371-removes-patially-matching-no-label-and-makes-it-case-insensitive.yml b/changelogs/unreleased/52371-removes-patially-matching-no-label-and-makes-it-case-insensitive.yml
deleted file mode 100644
index c1fc21c641a..00000000000
--- a/changelogs/unreleased/52371-removes-patially-matching-no-label-and-makes-it-case-insensitive.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: removes partially matching of No Label filter and makes it case-insensitive
-merge_request: 22622
-author: Jacopo Beschi @jacopo-beschi
-type: changed
diff --git a/changelogs/unreleased/52385-search-bar-for-dashboard-list.yml b/changelogs/unreleased/52385-search-bar-for-dashboard-list.yml
deleted file mode 100644
index a437ae560cb..00000000000
--- a/changelogs/unreleased/52385-search-bar-for-dashboard-list.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Use search bar for filtering in dashboard issues / MRs
-merge_request: 22641
-author: Heinrich Lee Yu
-type: changed
diff --git a/changelogs/unreleased/52453-show-subgroups-in-group-create-issue.yml b/changelogs/unreleased/52453-show-subgroups-in-group-create-issue.yml
deleted file mode 100644
index d5877e96d07..00000000000
--- a/changelogs/unreleased/52453-show-subgroups-in-group-create-issue.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix project selector consistency in groups issues / MRs / boards pages
-merge_request: 22612
-author: Heinrich Lee Yu
-type: fixed
diff --git a/changelogs/unreleased/52620-fix-loader-animation-alignment.yml b/changelogs/unreleased/52620-fix-loader-animation-alignment.yml
new file mode 100644
index 00000000000..5cfb7fc019f
--- /dev/null
+++ b/changelogs/unreleased/52620-fix-loader-animation-alignment.yml
@@ -0,0 +1,5 @@
+---
+title: Aligns build loader animation with the job log
+merge_request: 23959
+author:
+type: fixed
diff --git a/changelogs/unreleased/52712-further-ui-improvements-to-profile-overview-tab.yml b/changelogs/unreleased/52712-further-ui-improvements-to-profile-overview-tab.yml
deleted file mode 100644
index 65aa9323d2e..00000000000
--- a/changelogs/unreleased/52712-further-ui-improvements-to-profile-overview-tab.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: UI improvements to user's profile
-merge_request: 22977
-author:
-type: other
diff --git a/changelogs/unreleased/52774-fix-svgs-in-ie-11.yml b/changelogs/unreleased/52774-fix-svgs-in-ie-11.yml
deleted file mode 100644
index 656a915a281..00000000000
--- a/changelogs/unreleased/52774-fix-svgs-in-ie-11.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Ensure that SVG sprite icons are properly rendered in IE11
-merge_request:
-author:
-type: fixed
diff --git a/changelogs/unreleased/52828-inconsistency-in-fonts-used-for-branch-name-and-create-from-fields-when-creating-new-branch-from-ui.yml b/changelogs/unreleased/52828-inconsistency-in-fonts-used-for-branch-name-and-create-from-fields-when-creating-new-branch-from-ui.yml
deleted file mode 100644
index 8132dde8636..00000000000
--- a/changelogs/unreleased/52828-inconsistency-in-fonts-used-for-branch-name-and-create-from-fields-when-creating-new-branch-from-ui.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Make new branch form fields' fonts consistent
-merge_request:
-author:
-type: fixed
diff --git a/changelogs/unreleased/52940-fix-internal-email-pattern-not-respected.yml b/changelogs/unreleased/52940-fix-internal-email-pattern-not-respected.yml
deleted file mode 100644
index 98e15a5cc0a..00000000000
--- a/changelogs/unreleased/52940-fix-internal-email-pattern-not-respected.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix a bug where internal email pattern wasn't respected
-merge_request: 22516
-author:
-type: fixed
diff --git a/changelogs/unreleased/53289-update-haml_lint-to-0-28-0.yml b/changelogs/unreleased/53289-update-haml_lint-to-0-28-0.yml
deleted file mode 100644
index 9a16666c416..00000000000
--- a/changelogs/unreleased/53289-update-haml_lint-to-0-28-0.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Update haml_lint to 0.28.0
-merge_request: 22660
-author: Takuya Noguchi
-type: other
diff --git a/changelogs/unreleased/53290-incorrect-project-list-order-select-default-label.yml b/changelogs/unreleased/53290-incorrect-project-list-order-select-default-label.yml
deleted file mode 100644
index d076352a27b..00000000000
--- a/changelogs/unreleased/53290-incorrect-project-list-order-select-default-label.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix default sorting for subgroups and projects list
-merge_request: 23058
-author: Jacopo Beschi @jacopo-beschi
-type: fixed
diff --git a/changelogs/unreleased/53291-update-ffaker-to-2-10-0.yml b/changelogs/unreleased/53291-update-ffaker-to-2-10-0.yml
deleted file mode 100644
index a1b95df5e32..00000000000
--- a/changelogs/unreleased/53291-update-ffaker-to-2-10-0.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Update ffaker to 2.10.0
-merge_request: 22661
-author: Takuya Noguchi
-type: other
diff --git a/changelogs/unreleased/53326-improve-issues-empty-state.yml b/changelogs/unreleased/53326-improve-issues-empty-state.yml
deleted file mode 100644
index 7632db808b5..00000000000
--- a/changelogs/unreleased/53326-improve-issues-empty-state.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Show different empty state for filtered issues and MRs
-merge_request: 22775
-author: Heinrich Lee Yu
-type: changed
diff --git a/changelogs/unreleased/53400-unstar-icon-button-is-misaligned.yml b/changelogs/unreleased/53400-unstar-icon-button-is-misaligned.yml
deleted file mode 100644
index b393795f491..00000000000
--- a/changelogs/unreleased/53400-unstar-icon-button-is-misaligned.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: 'Fix: Unstar icon button is misaligned'
-merge_request: 23444
-author:
-type: fixed
diff --git a/changelogs/unreleased/53578-fe-deployment-status.yml b/changelogs/unreleased/53578-fe-deployment-status.yml
deleted file mode 100644
index b88bd70ee2e..00000000000
--- a/changelogs/unreleased/53578-fe-deployment-status.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Adds states to the deployment widget
-merge_request:
-author:
-type: added
diff --git a/changelogs/unreleased/53626-update-config-map-on-install-retry.yml b/changelogs/unreleased/53626-update-config-map-on-install-retry.yml
deleted file mode 100644
index 38e79c06c89..00000000000
--- a/changelogs/unreleased/53626-update-config-map-on-install-retry.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Update config map for gitlab managed application if already present on install
-merge_request: 22969
-author:
-type: other
diff --git a/changelogs/unreleased/53640-follow-up-from-resolve-redesign-activity-feed.yml b/changelogs/unreleased/53640-follow-up-from-resolve-redesign-activity-feed.yml
deleted file mode 100644
index 66301329c52..00000000000
--- a/changelogs/unreleased/53640-follow-up-from-resolve-redesign-activity-feed.yml
+++ /dev/null
@@ -1,4 +0,0 @@
-title: Adds new icon size to Vue icon component
-merge_request: 22899
-author:
-type: other
diff --git a/changelogs/unreleased/53659-use-padded-key-for-gcm-ciphers.yml b/changelogs/unreleased/53659-use-padded-key-for-gcm-ciphers.yml
deleted file mode 100644
index fe9ac7b3dc7..00000000000
--- a/changelogs/unreleased/53659-use-padded-key-for-gcm-ciphers.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix web hook functionality when the database encryption key is too short
-merge_request: 23573
-author:
-type: fixed
diff --git a/changelogs/unreleased/53700-hashed-storagemigration.yml b/changelogs/unreleased/53700-hashed-storagemigration.yml
deleted file mode 100644
index 899012ffd22..00000000000
--- a/changelogs/unreleased/53700-hashed-storagemigration.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: 'Hashed Storage: allow migration to be retried in partially migrated projects'
-merge_request: 23087
-author:
-type: fixed
diff --git a/changelogs/unreleased/53728-warn-in-web-editor-when-user-navigates-away.yml b/changelogs/unreleased/53728-warn-in-web-editor-when-user-navigates-away.yml
deleted file mode 100644
index 8377fdc6133..00000000000
--- a/changelogs/unreleased/53728-warn-in-web-editor-when-user-navigates-away.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Prevent user from navigating away from file edit without commit
-merge_request:
-author:
-type: fixed
diff --git a/changelogs/unreleased/53816-empty-label-menu-if-not-logged-in.yml b/changelogs/unreleased/53816-empty-label-menu-if-not-logged-in.yml
deleted file mode 100644
index a9ca56303eb..00000000000
--- a/changelogs/unreleased/53816-empty-label-menu-if-not-logged-in.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Removes promote to group label for anonymous user
-merge_request: 23042
-author: Jacopo Beschi @jacopo-beschi
-type: fixed
diff --git a/changelogs/unreleased/53874-navbar-lowres.yml b/changelogs/unreleased/53874-navbar-lowres.yml
deleted file mode 100644
index 3b31b8f93fe..00000000000
--- a/changelogs/unreleased/53874-navbar-lowres.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: "Fix overlapping navbar separator and overflowing navbar dropdown on small displays"
-merge_request: 23126
-author: Thomas Pathier
-type: fix
diff --git a/changelogs/unreleased/53933-include-dates-in-milestone-change-email.yml b/changelogs/unreleased/53933-include-dates-in-milestone-change-email.yml
new file mode 100644
index 00000000000..5c40a1e900c
--- /dev/null
+++ b/changelogs/unreleased/53933-include-dates-in-milestone-change-email.yml
@@ -0,0 +1,5 @@
+---
+title: Add date range in milestone change email notifications
+merge_request: 23762
+author:
+type: changed
diff --git a/changelogs/unreleased/53988-remove-notes-index-on-updated-at.yml b/changelogs/unreleased/53988-remove-notes-index-on-updated-at.yml
deleted file mode 100644
index f0bbf69736d..00000000000
--- a/changelogs/unreleased/53988-remove-notes-index-on-updated-at.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Remove index for notes on updated_at
-merge_request: 23356
-author:
-type: performance
diff --git a/changelogs/unreleased/53992-add-events-index-on-project-id-and-created-at.yml b/changelogs/unreleased/53992-add-events-index-on-project-id-and-created-at.yml
deleted file mode 100644
index a2a3fa00f01..00000000000
--- a/changelogs/unreleased/53992-add-events-index-on-project-id-and-created-at.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Add index for events on project_id and created_at
-merge_request: 23354
-author:
-type: performance
diff --git a/changelogs/unreleased/53994-add-missing-ci_builds-partial-indices.yml b/changelogs/unreleased/53994-add-missing-ci_builds-partial-indices.yml
deleted file mode 100644
index 4673ba38bae..00000000000
--- a/changelogs/unreleased/53994-add-missing-ci_builds-partial-indices.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Add partial index for ci_builds on project_id and status
-merge_request: 23268
-author:
-type: performance
diff --git a/changelogs/unreleased/54004-update-asana-to-0-8-1.yml b/changelogs/unreleased/54004-update-asana-to-0-8-1.yml
deleted file mode 100644
index a47b4f3c4d9..00000000000
--- a/changelogs/unreleased/54004-update-asana-to-0-8-1.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Update asana to 0.8.1
-merge_request: 23039
-author: Takuya Noguchi
-type: other
diff --git a/changelogs/unreleased/54010-update-asciidoctor-to-1-5-8.yml b/changelogs/unreleased/54010-update-asciidoctor-to-1-5-8.yml
deleted file mode 100644
index f0b0aa0ee1c..00000000000
--- a/changelogs/unreleased/54010-update-asciidoctor-to-1-5-8.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Update asciidoctor to 1.5.8
-merge_request: 23047
-author: Takuya Noguchi
-type: other
diff --git a/changelogs/unreleased/54015-Markdown-Editor-improve-Cursor-placement.yml b/changelogs/unreleased/54015-Markdown-Editor-improve-Cursor-placement.yml
deleted file mode 100644
index 28e3fae01a9..00000000000
--- a/changelogs/unreleased/54015-Markdown-Editor-improve-Cursor-placement.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Refine cursor positioning in Markdown Editor for wrap tags
-merge_request: 23085
-author: Johann Hubert Sonntagbauer
-type: changed
diff --git a/changelogs/unreleased/54021-empty-button.yml b/changelogs/unreleased/54021-empty-button.yml
deleted file mode 100644
index 3b03665cf95..00000000000
--- a/changelogs/unreleased/54021-empty-button.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Prevent empty button being rendered in empty state
-merge_request:
-author:
-type: fixed
diff --git a/changelogs/unreleased/54032-reply-shortcut-only-discussion-text.yml b/changelogs/unreleased/54032-reply-shortcut-only-discussion-text.yml
deleted file mode 100644
index 5c1f6e74b39..00000000000
--- a/changelogs/unreleased/54032-reply-shortcut-only-discussion-text.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Make reply shortcut only quote selected discussion text
-merge_request: 23096
-author: Thomas Pathier
-type: fix
diff --git a/changelogs/unreleased/54048-Line-numbers-are-misaligned-in-file-blame-view.yml b/changelogs/unreleased/54048-Line-numbers-are-misaligned-in-file-blame-view.yml
deleted file mode 100644
index 8ceac4ec869..00000000000
--- a/changelogs/unreleased/54048-Line-numbers-are-misaligned-in-file-blame-view.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix line height of numbers in file blame view
-merge_request: 23090
-author: Johann Hubert Sonntagbauer
-type: fixed
diff --git a/changelogs/unreleased/54093-the-default_value_for-gem-doesn-t-handle-actioncontroller-parameters-correctly.yml b/changelogs/unreleased/54093-the-default_value_for-gem-doesn-t-handle-actioncontroller-parameters-correctly.yml
deleted file mode 100644
index 3d6fd2d065a..00000000000
--- a/changelogs/unreleased/54093-the-default_value_for-gem-doesn-t-handle-actioncontroller-parameters-correctly.yml
+++ /dev/null
@@ -1,7 +0,0 @@
----
-title: Fixes an issue where default values from models would override values set in
- the interface (e.g. users would be set to external even though their emails matches
- the internal email address pattern)
-merge_request: 23114
-author:
-type: fixed
diff --git a/changelogs/unreleased/54160-use-reports-syntax-for-sast-in-auto-devops.yml b/changelogs/unreleased/54160-use-reports-syntax-for-sast-in-auto-devops.yml
deleted file mode 100644
index 86c5a0c5a95..00000000000
--- a/changelogs/unreleased/54160-use-reports-syntax-for-sast-in-auto-devops.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Use reports syntax for SAST in Auto DevOps
-merge_request: 23163
-author:
-type: changed
diff --git a/changelogs/unreleased/54201-update-rack-to-2-0-6.yml b/changelogs/unreleased/54201-update-rack-to-2-0-6.yml
deleted file mode 100644
index 020b2bc0957..00000000000
--- a/changelogs/unreleased/54201-update-rack-to-2-0-6.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Update rack to 2.0.6 (for QA environments)
-merge_request: 23171
-author: Takuya Noguchi
-type: security
diff --git a/changelogs/unreleased/54218-fix-mergeUrlParams.yml b/changelogs/unreleased/54218-fix-mergeUrlParams.yml
deleted file mode 100644
index dae06b66e8e..00000000000
--- a/changelogs/unreleased/54218-fix-mergeUrlParams.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: "Fix mergeUrlParams with fragment URL"
-merge_request: 54218
-author: Thomas Holder
-type: fixed
diff --git a/changelogs/unreleased/54336-include-tags-into-pipeline-detail-view.yml b/changelogs/unreleased/54336-include-tags-into-pipeline-detail-view.yml
deleted file mode 100644
index 11f941ab9bb..00000000000
--- a/changelogs/unreleased/54336-include-tags-into-pipeline-detail-view.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Merge request pipeline tag, and adds tags to pipeline view
-merge_request: 23364
-author:
-type: added
diff --git a/changelogs/unreleased/54391-tag.yml b/changelogs/unreleased/54391-tag.yml
deleted file mode 100644
index be571c6b0c3..00000000000
--- a/changelogs/unreleased/54391-tag.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Correctly styles tags in sidebar for job page
-merge_request:
-author:
-type: fixed
diff --git a/changelogs/unreleased/54407-fix-limited-intersection-observers.yml b/changelogs/unreleased/54407-fix-limited-intersection-observers.yml
deleted file mode 100644
index 2c2bedb170b..00000000000
--- a/changelogs/unreleased/54407-fix-limited-intersection-observers.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix Image Lazy Loader for some older browsers
-merge_request:
-author:
-type: fixed
diff --git a/changelogs/unreleased/54571-runner-tags.yml b/changelogs/unreleased/54571-runner-tags.yml
deleted file mode 100644
index 1bb19d22e9c..00000000000
--- a/changelogs/unreleased/54571-runner-tags.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Adds margins between tags when a job is stuck
-merge_request:
-author:
-type: fixed
diff --git a/changelogs/unreleased/54626-able-to-download-a-single-archive-file-with-api-by-ref-name.yml b/changelogs/unreleased/54626-able-to-download-a-single-archive-file-with-api-by-ref-name.yml
deleted file mode 100644
index fa905b47ca2..00000000000
--- a/changelogs/unreleased/54626-able-to-download-a-single-archive-file-with-api-by-ref-name.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Add new endpoint to download single artifact file for a ref
-merge_request: 23538
-author:
-type: added
diff --git a/changelogs/unreleased/54648-fix-order-by-dropdown-tablet-screens.yml b/changelogs/unreleased/54648-fix-order-by-dropdown-tablet-screens.yml
deleted file mode 100644
index 671d1590991..00000000000
--- a/changelogs/unreleased/54648-fix-order-by-dropdown-tablet-screens.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix Order By dropdown menu styling in tablet and mobile screens
-merge_request: 23446
-author:
-type: fixed
diff --git a/changelogs/unreleased/54814-sidebar-styling-updates.yml b/changelogs/unreleased/54814-sidebar-styling-updates.yml
new file mode 100644
index 00000000000..98e3836ee14
--- /dev/null
+++ b/changelogs/unreleased/54814-sidebar-styling-updates.yml
@@ -0,0 +1,5 @@
+---
+title: Fix label and header styles in the job details sidebar.
+merge_request: 23816
+author: Nathan Friend
+type: changed
diff --git a/changelogs/unreleased/54826-use-read_repository-scope-on-read-only-files-endpoints.yml b/changelogs/unreleased/54826-use-read_repository-scope-on-read-only-files-endpoints.yml
deleted file mode 100644
index ef8e93fca43..00000000000
--- a/changelogs/unreleased/54826-use-read_repository-scope-on-read-only-files-endpoints.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Use read_repository scope on read-only files API
-merge_request: 23534
-author:
-type: fixed
diff --git a/changelogs/unreleased/54857-fix-templates-path-traversal.yml b/changelogs/unreleased/54857-fix-templates-path-traversal.yml
deleted file mode 100644
index 0da02432c60..00000000000
--- a/changelogs/unreleased/54857-fix-templates-path-traversal.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Prevent a path traversal attack on global file templates
-merge_request:
-author:
-type: security
diff --git a/changelogs/unreleased/54953-fix-commit_email_hostname-accessor-in-fake_application_settings.yml b/changelogs/unreleased/54953-fix-commit_email_hostname-accessor-in-fake_application_settings.yml
new file mode 100644
index 00000000000..623b3a7319c
--- /dev/null
+++ b/changelogs/unreleased/54953-fix-commit_email_hostname-accessor-in-fake_application_settings.yml
@@ -0,0 +1,5 @@
+---
+title: Fix a 500 error that could occur until all migrations are done
+merge_request: 23939
+author:
+type: fixed
diff --git a/changelogs/unreleased/54975-fix-web-hooks-rake-task.yml b/changelogs/unreleased/54975-fix-web-hooks-rake-task.yml
deleted file mode 100644
index 107a93e5b12..00000000000
--- a/changelogs/unreleased/54975-fix-web-hooks-rake-task.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix gitlab:web_hook tasks
-merge_request: 23635
-author:
-type: fixed
diff --git a/changelogs/unreleased/55103-hide-group-cluster-features.yml b/changelogs/unreleased/55103-hide-group-cluster-features.yml
new file mode 100644
index 00000000000..fbe780d6f01
--- /dev/null
+++ b/changelogs/unreleased/55103-hide-group-cluster-features.yml
@@ -0,0 +1,5 @@
+---
+title: Hide cluster features that don't work yet with Group Clusters
+merge_request: 23935
+author:
+type: fixed
diff --git a/changelogs/unreleased/55104-frozenerror-can-t-modify-frozen-string.yml b/changelogs/unreleased/55104-frozenerror-can-t-modify-frozen-string.yml
deleted file mode 100644
index 994859b1d1d..00000000000
--- a/changelogs/unreleased/55104-frozenerror-can-t-modify-frozen-string.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix a frozen string error in app/mailers/notify.rb
-merge_request: 23683
-author:
-type: fixed
diff --git a/changelogs/unreleased/55116-runtimeerror-can-t-modify-frozen-string.yml b/changelogs/unreleased/55116-runtimeerror-can-t-modify-frozen-string.yml
deleted file mode 100644
index a98e70465b2..00000000000
--- a/changelogs/unreleased/55116-runtimeerror-can-t-modify-frozen-string.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix a frozen string error in lib/gitlab/utils.rb
-merge_request: 23690
-author:
-type: fixed
diff --git a/changelogs/unreleased/55138-fix-mr-discussions-count.yml b/changelogs/unreleased/55138-fix-mr-discussions-count.yml
deleted file mode 100644
index 667e9b971d8..00000000000
--- a/changelogs/unreleased/55138-fix-mr-discussions-count.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix MR resolved discussion counts being too low
-merge_request: 23710
-author:
-type: fixed
diff --git a/changelogs/unreleased/55183-frozenerror-can-t-modify-frozen-string-in-app-mailers-notify-rb.yml b/changelogs/unreleased/55183-frozenerror-can-t-modify-frozen-string-in-app-mailers-notify-rb.yml
deleted file mode 100644
index 685a8309c72..00000000000
--- a/changelogs/unreleased/55183-frozenerror-can-t-modify-frozen-string-in-app-mailers-notify-rb.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix a potential frozen string error in app/mailers/notify.rb
-merge_request: 23728
-author:
-type: fixed
diff --git a/changelogs/unreleased/55293-split-bio-into-individual-line-in-extended-user-tooltips.yml b/changelogs/unreleased/55293-split-bio-into-individual-line-in-extended-user-tooltips.yml
new file mode 100644
index 00000000000..c6ff52b0fa1
--- /dev/null
+++ b/changelogs/unreleased/55293-split-bio-into-individual-line-in-extended-user-tooltips.yml
@@ -0,0 +1,5 @@
+---
+title: Split bio into individual line in extended user tooltips
+merge_request: 23940
+author:
+type: other
diff --git a/changelogs/unreleased/55402-broken-master-karma-test-failing-in-spec-javascripts-boards-components-issue_due_date_spec-js.yml b/changelogs/unreleased/55402-broken-master-karma-test-failing-in-spec-javascripts-boards-components-issue_due_date_spec-js.yml
deleted file mode 100644
index d2ff095ce55..00000000000
--- a/changelogs/unreleased/55402-broken-master-karma-test-failing-in-spec-javascripts-boards-components-issue_due_date_spec-js.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix due date test
-merge_request: 23845
-author:
-type: other
diff --git a/changelogs/unreleased/_acet-fix-flash-styling.yml b/changelogs/unreleased/_acet-fix-flash-styling.yml
deleted file mode 100644
index 57354c04899..00000000000
--- a/changelogs/unreleased/_acet-fix-flash-styling.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix flash notice styling for fluid layout
-merge_request: 23382
-author:
-type: fixed
diff --git a/changelogs/unreleased/ab-approximate-counts.yml b/changelogs/unreleased/ab-approximate-counts.yml
deleted file mode 100644
index 8a67239d031..00000000000
--- a/changelogs/unreleased/ab-approximate-counts.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Approximate counting strategy with TABLESAMPLE.
-merge_request: 22650
-author:
-type: performance
diff --git a/changelogs/unreleased/added-glob-for-ci-changes-detection.yml b/changelogs/unreleased/added-glob-for-ci-changes-detection.yml
deleted file mode 100644
index 887c6ef0346..00000000000
--- a/changelogs/unreleased/added-glob-for-ci-changes-detection.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Added glob for CI changes detection
-merge_request: 23128
-author: Kirill Zaitsev
-type: added
diff --git a/changelogs/unreleased/an-gitaly-version-0-133-0.yml b/changelogs/unreleased/an-gitaly-version-0-133-0.yml
deleted file mode 100644
index 4f3943ceacb..00000000000
--- a/changelogs/unreleased/an-gitaly-version-0-133-0.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Updated Gitaly to v0.133.0
-merge_request: 23148
-author:
-type: other
diff --git a/changelogs/unreleased/ashmckenzie-hmac-token-decode-and-tests.yml b/changelogs/unreleased/ashmckenzie-hmac-token-decode-and-tests.yml
deleted file mode 100644
index d15c5654d99..00000000000
--- a/changelogs/unreleased/ashmckenzie-hmac-token-decode-and-tests.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Relocate JSONWebToken::HMACToken from EE
-merge_request: 22906
-author:
-type: changed
diff --git a/changelogs/unreleased/auto_devops_kubernetes_active.yml b/changelogs/unreleased/auto_devops_kubernetes_active.yml
deleted file mode 100644
index 310d37128c9..00000000000
--- a/changelogs/unreleased/auto_devops_kubernetes_active.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Switch kubernetes:active with checking in Auto-DevOps.gitlab-ci.yml
-merge_request: 22929
-author:
-type: fixed
diff --git a/changelogs/unreleased/blackst0ne-add-discord-service.yml b/changelogs/unreleased/blackst0ne-add-discord-service.yml
deleted file mode 100644
index 85dedf6d81f..00000000000
--- a/changelogs/unreleased/blackst0ne-add-discord-service.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Add Discord integration
-merge_request: 22684
-author: "@blackst0ne"
-type: added
diff --git a/changelogs/unreleased/bump_gpgme_gem.yml b/changelogs/unreleased/bump_gpgme_gem.yml
deleted file mode 100644
index 4c0067cb824..00000000000
--- a/changelogs/unreleased/bump_gpgme_gem.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Bump gpgme gem version from 2.0.13 to 2.0.18
-merge_request:
-author: asaparov
-type: other
diff --git a/changelogs/unreleased/bvl-use-shell-writeref.yml b/changelogs/unreleased/bvl-use-shell-writeref.yml
deleted file mode 100644
index 682d428e8c5..00000000000
--- a/changelogs/unreleased/bvl-use-shell-writeref.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Avoid creating invalid refs using rugged, shelling out for writing refs
-merge_request: 23286
-author:
-type: fixed
diff --git a/changelogs/unreleased/ce-52811-fix_namespaces_api_routing.yml b/changelogs/unreleased/ce-52811-fix_namespaces_api_routing.yml
deleted file mode 100644
index b5fd99c304f..00000000000
--- a/changelogs/unreleased/ce-52811-fix_namespaces_api_routing.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix API::Namespaces routing to accept namepaces with dots
-merge_request: 22912
-author:
-type: fixed
diff --git a/changelogs/unreleased/ce-54109-fix_user_by_any_email.yml b/changelogs/unreleased/ce-54109-fix_user_by_any_email.yml
deleted file mode 100644
index eb5d2e3244c..00000000000
--- a/changelogs/unreleased/ce-54109-fix_user_by_any_email.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Respect confirmed flag on secondary emails
-merge_request: 23181
-author:
-type: fixed
diff --git a/changelogs/unreleased/cert-manager-email.yml b/changelogs/unreleased/cert-manager-email.yml
deleted file mode 100644
index 530608d9660..00000000000
--- a/changelogs/unreleased/cert-manager-email.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Ability to override email for cert-manager
-merge_request: 23503
-author: Amit Rathi
-type: added
diff --git a/changelogs/unreleased/certmanager-temp.yml b/changelogs/unreleased/certmanager-temp.yml
deleted file mode 100644
index 3f908d01c9f..00000000000
--- a/changelogs/unreleased/certmanager-temp.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: "#40635: Adds support for cert-manager"
-merge_request: 23036
-author: Amit Rathi
-type: added
diff --git a/changelogs/unreleased/check-if-fetched-data-does-is-complete.yml b/changelogs/unreleased/check-if-fetched-data-does-is-complete.yml
deleted file mode 100644
index 31c131045b9..00000000000
--- a/changelogs/unreleased/check-if-fetched-data-does-is-complete.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Validate chunk size when persist
-merge_request: 23341
-author:
-type: fixed
diff --git a/changelogs/unreleased/commit-badge-style-fix.yml b/changelogs/unreleased/commit-badge-style-fix.yml
deleted file mode 100644
index d7b37717853..00000000000
--- a/changelogs/unreleased/commit-badge-style-fix.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fixed styling of image comment badges on commits
-merge_request:
-author:
-type: fixed
diff --git a/changelogs/unreleased/define-default-value-for-only-except-keys.yml b/changelogs/unreleased/define-default-value-for-only-except-keys.yml
deleted file mode 100644
index ed0e982f0fc..00000000000
--- a/changelogs/unreleased/define-default-value-for-only-except-keys.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Define the default value for only/except policies
-merge_request: 23765
-author:
-type: changed
diff --git a/changelogs/unreleased/depracated-migration-inheritance.yml b/changelogs/unreleased/depracated-migration-inheritance.yml
new file mode 100644
index 00000000000..1ea9b2df59c
--- /dev/null
+++ b/changelogs/unreleased/depracated-migration-inheritance.yml
@@ -0,0 +1,5 @@
+---
+title: ActiveRecord::Migration -> ActiveRecord::Migration[5.0]
+merge_request: 23910
+author: Jasper Maes
+type: other
diff --git a/changelogs/unreleased/deprecated-instance-find.yml b/changelogs/unreleased/deprecated-instance-find.yml
deleted file mode 100644
index d2ba821e124..00000000000
--- a/changelogs/unreleased/deprecated-instance-find.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: 'Fix deprecation: You are passing an instance of ActiveRecord::Base to'
-merge_request: 23369
-author: Jasper Maes
-type: other
diff --git a/changelogs/unreleased/diff-expand-commit-file.yml b/changelogs/unreleased/diff-expand-commit-file.yml
deleted file mode 100644
index 8ca784d75c1..00000000000
--- a/changelogs/unreleased/diff-expand-commit-file.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fixed diff files expanding not loading commit content
-merge_request:
-author:
-type: fixed
diff --git a/changelogs/unreleased/diff-fix-expanding.yml b/changelogs/unreleased/diff-fix-expanding.yml
deleted file mode 100644
index 8ba7f87addc..00000000000
--- a/changelogs/unreleased/diff-fix-expanding.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fixed multiple diff line discussions not expanding
-merge_request:
-author:
-type: fixed
diff --git a/changelogs/unreleased/discussion-perf-improvement.yml b/changelogs/unreleased/discussion-perf-improvement.yml
deleted file mode 100644
index defff8a55f5..00000000000
--- a/changelogs/unreleased/discussion-perf-improvement.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Improve initial discussion rendering performance
-merge_request: 22607
-author:
-type: changed
diff --git a/changelogs/unreleased/dm-batch-loader-key.yml b/changelogs/unreleased/dm-batch-loader-key.yml
deleted file mode 100644
index 047fdbc4b3f..00000000000
--- a/changelogs/unreleased/dm-batch-loader-key.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Batch load only data from same repository when lazy object is accessed
-merge_request: 23309
-author:
-type: performance
diff --git a/changelogs/unreleased/dm-note-email-image-diff-discussion.yml b/changelogs/unreleased/dm-note-email-image-diff-discussion.yml
new file mode 100644
index 00000000000..6532052e132
--- /dev/null
+++ b/changelogs/unreleased/dm-note-email-image-diff-discussion.yml
@@ -0,0 +1,5 @@
+---
+title: Fix notification email for image diff notes
+merge_request:
+author:
+type: fixed
diff --git a/changelogs/unreleased/dm-remove-prune-web-hook-logs-worker.yml b/changelogs/unreleased/dm-remove-prune-web-hook-logs-worker.yml
deleted file mode 100644
index fb0c508400c..00000000000
--- a/changelogs/unreleased/dm-remove-prune-web-hook-logs-worker.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Remove old webhook logs after 90 days, as documented, instead of after 2
-merge_request:
-author:
-type: fixed
diff --git a/changelogs/unreleased/docs-minor-aws-fixes.yml b/changelogs/unreleased/docs-minor-aws-fixes.yml
deleted file mode 100644
index 64fa6b12afe..00000000000
--- a/changelogs/unreleased/docs-minor-aws-fixes.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fixes to AWS documentation spelling and grammar
-merge_request: 23198
-author: Brendan O'Leary
-type: other
diff --git a/changelogs/unreleased/document-raw-snippet-api.yml b/changelogs/unreleased/document-raw-snippet-api.yml
deleted file mode 100644
index 3b8818cea5c..00000000000
--- a/changelogs/unreleased/document-raw-snippet-api.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix lack of documentation on how to fetch a snippet's content using API
-merge_request: 23448
-author: Colin Leroy
-type: other
diff --git a/changelogs/unreleased/drop-default-value-status-deployments.yml b/changelogs/unreleased/drop-default-value-status-deployments.yml
deleted file mode 100644
index fdb826a0507..00000000000
--- a/changelogs/unreleased/drop-default-value-status-deployments.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Drop default value on status column in deployments table
-merge_request: 22971
-author:
-type: other
diff --git a/changelogs/unreleased/drop-gcp-cluster-table.yml b/changelogs/unreleased/drop-gcp-cluster-table.yml
deleted file mode 100644
index 15964ec2eaf..00000000000
--- a/changelogs/unreleased/drop-gcp-cluster-table.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Drop gcp_clusters table
-merge_request: 22713
-author:
-type: other
diff --git a/changelogs/unreleased/expose-mr-pipeline-variables.yml b/changelogs/unreleased/expose-mr-pipeline-variables.yml
deleted file mode 100644
index b77b9a69d5c..00000000000
--- a/changelogs/unreleased/expose-mr-pipeline-variables.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Expose merge request pipeline variables
-merge_request: 23398
-author:
-type: changed
diff --git a/changelogs/unreleased/feature-option-to-make-variables-protected.yml b/changelogs/unreleased/feature-option-to-make-variables-protected.yml
new file mode 100644
index 00000000000..c99c0481c35
--- /dev/null
+++ b/changelogs/unreleased/feature-option-to-make-variables-protected.yml
@@ -0,0 +1,5 @@
+---
+title: Add option to make ci variables protected by default
+merge_request: 22744
+author: Alexis Reigel
+type: added
diff --git a/changelogs/unreleased/fix-55448.yml b/changelogs/unreleased/fix-55448.yml
new file mode 100644
index 00000000000..e0bdbb6eda4
--- /dev/null
+++ b/changelogs/unreleased/fix-55448.yml
@@ -0,0 +1,5 @@
+---
+title: Remove deprecated xhr from specs
+merge_request: 23949
+author: Jasper Maes
+type: other
diff --git a/changelogs/unreleased/fix-gb-encrypt-ci-build-token.yml b/changelogs/unreleased/fix-gb-encrypt-ci-build-token.yml
deleted file mode 100644
index 04fc88bc3d3..00000000000
--- a/changelogs/unreleased/fix-gb-encrypt-ci-build-token.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Encrypt CI/CD builds authentication tokens
-merge_request: 23436
-author:
-type: security
diff --git a/changelogs/unreleased/fix-gb-encrypt-runners-tokens.yml b/changelogs/unreleased/fix-gb-encrypt-runners-tokens.yml
deleted file mode 100644
index 4ce4f96c1dd..00000000000
--- a/changelogs/unreleased/fix-gb-encrypt-runners-tokens.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Encrypt runners tokens
-merge_request: 23412
-author:
-type: security
diff --git a/changelogs/unreleased/fix-gb-improve-timeout-inputs-help-sections.yml b/changelogs/unreleased/fix-gb-improve-timeout-inputs-help-sections.yml
deleted file mode 100644
index 52b431edf2c..00000000000
--- a/changelogs/unreleased/fix-gb-improve-timeout-inputs-help-sections.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Improve help and validation sections of maximum build timeout inputs
-merge_request: 23586
-author:
-type: fixed
diff --git a/changelogs/unreleased/fix-mr-widget-unrelated-deployment-status.yml b/changelogs/unreleased/fix-mr-widget-unrelated-deployment-status.yml
deleted file mode 100644
index ab926fbd43b..00000000000
--- a/changelogs/unreleased/fix-mr-widget-unrelated-deployment-status.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix unrelated deployment status in MR widget
-merge_request: 23175
-author:
-type: fixed
diff --git a/changelogs/unreleased/fix-multiple-comments-shade-overlap.yml b/changelogs/unreleased/fix-multiple-comments-shade-overlap.yml
deleted file mode 100644
index 20005ba355e..00000000000
--- a/changelogs/unreleased/fix-multiple-comments-shade-overlap.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix multiple commits shade overlapping vertical discussion line
-merge_request: 23515
-author:
-type: fixed
diff --git a/changelogs/unreleased/fj-47494-upgrade-git-to-2-18-0.yml b/changelogs/unreleased/fj-47494-upgrade-git-to-2-18-0.yml
deleted file mode 100644
index 0f01552ff7e..00000000000
--- a/changelogs/unreleased/fj-47494-upgrade-git-to-2-18-0.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Upgrade minimum required Git version to 2.18.0
-merge_request: 22803
-author:
-type: other
diff --git a/changelogs/unreleased/fj-clean-content-headers.yml b/changelogs/unreleased/fj-clean-content-headers.yml
deleted file mode 100644
index 59e25ca6578..00000000000
--- a/changelogs/unreleased/fj-clean-content-headers.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Added feature flag to signal content headers detection by Workhorse
-merge_request: 22667
-author:
-type: added
diff --git a/changelogs/unreleased/fj-force-content-disposition.yml b/changelogs/unreleased/fj-force-content-disposition.yml
deleted file mode 100644
index d84555a489f..00000000000
--- a/changelogs/unreleased/fj-force-content-disposition.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Force content disposition attachment to several endpoints
-merge_request: 23223
-author:
-type: other
diff --git a/changelogs/unreleased/force-reload-arguments-1.yml b/changelogs/unreleased/force-reload-arguments-1.yml
deleted file mode 100644
index 29f34b8bdbe..00000000000
--- a/changelogs/unreleased/force-reload-arguments-1.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Passing an argument to force an association to reload is now deprecated
-merge_request: 23334
-author: Jasper Maes
-type: other
diff --git a/changelogs/unreleased/frozen-string-lib-gitlab-even-even-even-more.yml b/changelogs/unreleased/frozen-string-lib-gitlab-even-even-even-more.yml
deleted file mode 100644
index e718d716647..00000000000
--- a/changelogs/unreleased/frozen-string-lib-gitlab-even-even-even-more.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Enable even more frozen string for lib/gitlab
-merge_request:
-author: gfyoung
-type: performance
diff --git a/changelogs/unreleased/frozen-string-lib-gitlab-even-even-more.yml b/changelogs/unreleased/frozen-string-lib-gitlab-even-even-more.yml
deleted file mode 100644
index e718d716647..00000000000
--- a/changelogs/unreleased/frozen-string-lib-gitlab-even-even-more.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Enable even more frozen string for lib/gitlab
-merge_request:
-author: gfyoung
-type: performance
diff --git a/changelogs/unreleased/frozen-string-lib-gitlab-even-more.yml b/changelogs/unreleased/frozen-string-lib-gitlab-even-more.yml
deleted file mode 100644
index cfbc4ced635..00000000000
--- a/changelogs/unreleased/frozen-string-lib-gitlab-even-more.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Enable even more frozen string in lib/gitlab/**/*.rb
-merge_request:
-author: gfyoung
-type: performance
diff --git a/changelogs/unreleased/frozen-string-lib-gitlab-more.yml b/changelogs/unreleased/frozen-string-lib-gitlab-more.yml
deleted file mode 100644
index cfbc4ced635..00000000000
--- a/changelogs/unreleased/frozen-string-lib-gitlab-more.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Enable even more frozen string in lib/gitlab/**/*.rb
-merge_request:
-author: gfyoung
-type: performance
diff --git a/changelogs/unreleased/frozen-string-lib-rubocop.yml b/changelogs/unreleased/frozen-string-lib-rubocop.yml
deleted file mode 100644
index 9fe342e251b..00000000000
--- a/changelogs/unreleased/frozen-string-lib-rubocop.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Enable Rubocop on lib/gitlab
-merge_request:
-author: gfyoung
-type: other
diff --git a/changelogs/unreleased/gt-add-top-padding-for-nested-environment-items-loading-icon.yml b/changelogs/unreleased/gt-add-top-padding-for-nested-environment-items-loading-icon.yml
deleted file mode 100644
index 606314b5780..00000000000
--- a/changelogs/unreleased/gt-add-top-padding-for-nested-environment-items-loading-icon.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Add top padding for nested environment items loading icon
-merge_request: 23580
-author: George Tsiolis
-type: fixed
diff --git a/changelogs/unreleased/gt-align-issue-status-and-confidential-icon.yml b/changelogs/unreleased/gt-align-issue-status-and-confidential-icon.yml
deleted file mode 100644
index 481ce656dc7..00000000000
--- a/changelogs/unreleased/gt-align-issue-status-and-confidential-icon.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Align issue status label and confidential icon.
-merge_request: 23046
-author: George Tsiolis
-type: fixed
diff --git a/changelogs/unreleased/gt-change-breadcrumb-title-for-contribution-charts.yml b/changelogs/unreleased/gt-change-breadcrumb-title-for-contribution-charts.yml
deleted file mode 100644
index 233cc43117d..00000000000
--- a/changelogs/unreleased/gt-change-breadcrumb-title-for-contribution-charts.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Change breadcrumb title for contribution charts
-merge_request: 23071
-author: George Tsiolis
-type: changed
diff --git a/changelogs/unreleased/gt-change-container-width-for-project-import.yml b/changelogs/unreleased/gt-change-container-width-for-project-import.yml
deleted file mode 100644
index ec2beb15912..00000000000
--- a/changelogs/unreleased/gt-change-container-width-for-project-import.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Change container width for project import
-merge_request: 23318
-author: George Tsiolis
-type: fixed
diff --git a/changelogs/unreleased/gt-externalize-app-views-invites.yml b/changelogs/unreleased/gt-externalize-app-views-invites.yml
deleted file mode 100644
index b5a22177f9b..00000000000
--- a/changelogs/unreleased/gt-externalize-app-views-invites.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Externalize strings from `/app/views/invites`
-merge_request: 23205
-author: Tao Wang
-type: other
diff --git a/changelogs/unreleased/gt-externalize-app-views-project-runners.yml b/changelogs/unreleased/gt-externalize-app-views-project-runners.yml
deleted file mode 100644
index d7d591e2175..00000000000
--- a/changelogs/unreleased/gt-externalize-app-views-project-runners.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Externalize strings from `/app/views/project/runners`
-merge_request: 23208
-author: Tao Wang
-type: other
diff --git a/changelogs/unreleased/gt-externalize-app-views-snippets.yml b/changelogs/unreleased/gt-externalize-app-views-snippets.yml
deleted file mode 100644
index 633aa9f2534..00000000000
--- a/changelogs/unreleased/gt-externalize-app-views-snippets.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Externalize strings from `/app/views/snippets`
-merge_request: 23351
-author: Tao Wang
-type: other
diff --git a/changelogs/unreleased/gt-fix-typo-in-notebook-props.yml b/changelogs/unreleased/gt-fix-typo-in-notebook-props.yml
deleted file mode 100644
index 60603905a2d..00000000000
--- a/changelogs/unreleased/gt-fix-typo-in-notebook-props.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix typo in notebook props
-merge_request: 23103
-author: George Tsiolis
-type: other
diff --git a/changelogs/unreleased/gt-fix-typos-in-lib.yml b/changelogs/unreleased/gt-fix-typos-in-lib.yml
deleted file mode 100644
index 32ccd03b063..00000000000
--- a/changelogs/unreleased/gt-fix-typos-in-lib.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix typos in lib
-merge_request: 23106
-author: George Tsiolis
-type: other
diff --git a/changelogs/unreleased/gt-remove-instances-of-extend-monospace.yml b/changelogs/unreleased/gt-remove-instances-of-extend-monospace.yml
deleted file mode 100644
index dc41de61046..00000000000
--- a/changelogs/unreleased/gt-remove-instances-of-extend-monospace.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Remove monospace extend
-merge_request: 23089
-author: George Tsiolis
-type: performance
diff --git a/changelogs/unreleased/gt-remove-unused-project-method.yml b/changelogs/unreleased/gt-remove-unused-project-method.yml
deleted file mode 100644
index 2d60c2fe423..00000000000
--- a/changelogs/unreleased/gt-remove-unused-project-method.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Remove unused project method
-merge_request: 54103
-author: George Tsiolis
-type: other
diff --git a/changelogs/unreleased/gt-rename-diffs-store-variable.yml b/changelogs/unreleased/gt-rename-diffs-store-variable.yml
deleted file mode 100644
index 0aed49f3d60..00000000000
--- a/changelogs/unreleased/gt-rename-diffs-store-variable.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Rename diffs store variable
-merge_request: 23123
-author: George Tsiolis
-type: other
diff --git a/changelogs/unreleased/gt-show-primary-button-when-all-labels-are-prioritized.yml b/changelogs/unreleased/gt-show-primary-button-when-all-labels-are-prioritized.yml
deleted file mode 100644
index eed31950a76..00000000000
--- a/changelogs/unreleased/gt-show-primary-button-when-all-labels-are-prioritized.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Show primary button when all labels are prioritized
-merge_request: 23648
-author: George Tsiolis
-type: other
diff --git a/changelogs/unreleased/gt-update-env-metrics-empty-state.yml b/changelogs/unreleased/gt-update-env-metrics-empty-state.yml
deleted file mode 100644
index a05dc07e65c..00000000000
--- a/changelogs/unreleased/gt-update-env-metrics-empty-state.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Update environments metrics empty state
-merge_request: 23074
-author: George Tsiolis
-type: changed
diff --git a/changelogs/unreleased/gt-use-gl-tooltip-directive.yml b/changelogs/unreleased/gt-use-gl-tooltip-directive.yml
deleted file mode 100644
index 91fdb73e3c6..00000000000
--- a/changelogs/unreleased/gt-use-gl-tooltip-directive.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Replace tooltip directive with gl-tooltip diretive in badges, cycle analytics, and diffs
-merge_request: 22770
-author: George Tsiolis
-type: performance
diff --git a/changelogs/unreleased/ide-open-all-mr-files.yml b/changelogs/unreleased/ide-open-all-mr-files.yml
deleted file mode 100644
index 6a5ea8908fc..00000000000
--- a/changelogs/unreleased/ide-open-all-mr-files.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Open first 10 merge request files in IDE
-merge_request:
-author:
-type: fixed
diff --git a/changelogs/unreleased/ignore-failed-pipeline-creation-on-pipeline-schedule.yml b/changelogs/unreleased/ignore-failed-pipeline-creation-on-pipeline-schedule.yml
deleted file mode 100644
index 90f47aa12db..00000000000
--- a/changelogs/unreleased/ignore-failed-pipeline-creation-on-pipeline-schedule.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Remove auto deactivation when failed to create a pipeline via pipeline schedules
-merge_request: 22243
-author:
-type: changed
diff --git a/changelogs/unreleased/improve_auto_devops_migration_debug.yml b/changelogs/unreleased/improve_auto_devops_migration_debug.yml
deleted file mode 100644
index 96a78808361..00000000000
--- a/changelogs/unreleased/improve_auto_devops_migration_debug.yml
+++ /dev/null
@@ -1,6 +0,0 @@
----
-title: 'Auto DevOps: Add echo for each branch of the deploy() function where we run
- helm upgrade'
-merge_request: 23499
-author:
-type: changed
diff --git a/changelogs/unreleased/include-new-link-in-breadcrumb.yml b/changelogs/unreleased/include-new-link-in-breadcrumb.yml
deleted file mode 100644
index 68c808d66d7..00000000000
--- a/changelogs/unreleased/include-new-link-in-breadcrumb.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Include new link in breadcrumb for issues, merge requests, milestones, and labels
-merge_request: 18515
-author: George Tsiolis
-type: changed
diff --git a/changelogs/unreleased/jivl-add-empty-state-graphs-null-values.yml b/changelogs/unreleased/jivl-add-empty-state-graphs-null-values.yml
deleted file mode 100644
index d21254b16d0..00000000000
--- a/changelogs/unreleased/jivl-add-empty-state-graphs-null-values.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Add empty state for graphs with no values
-merge_request: 22630
-author:
-type: fixed
diff --git a/changelogs/unreleased/jupyter-tls.yml b/changelogs/unreleased/jupyter-tls.yml
deleted file mode 100644
index 4111edd34ff..00000000000
--- a/changelogs/unreleased/jupyter-tls.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: "#52753: HTTPS for JupyterHub installation"
-merge_request: 23479
-author: Amit Rathi
-type: added
diff --git a/changelogs/unreleased/kcj-add-philosophy.yml b/changelogs/unreleased/kcj-add-philosophy.yml
deleted file mode 100644
index d164ce165ea..00000000000
--- a/changelogs/unreleased/kcj-add-philosophy.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Adds a PHILOSOPHY.md which references GitLab Product Handbook
-merge_request: 23200
-author:
-type: other
diff --git a/changelogs/unreleased/kubernetes-http-response-code.yml b/changelogs/unreleased/kubernetes-http-response-code.yml
deleted file mode 100644
index 551fe2edc3c..00000000000
--- a/changelogs/unreleased/kubernetes-http-response-code.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Show HTTP response code for Kubernetes errors
-merge_request: 22964
-author:
-type: other
diff --git a/changelogs/unreleased/legacy_fallback_for_project_clusters_only.yml b/changelogs/unreleased/legacy_fallback_for_project_clusters_only.yml
deleted file mode 100644
index c8e959176d0..00000000000
--- a/changelogs/unreleased/legacy_fallback_for_project_clusters_only.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fallback to admin KUBE_TOKEN for project clusters only
-merge_request: 23527
-author:
-type: other
diff --git a/changelogs/unreleased/lock-trace-writes.yml b/changelogs/unreleased/lock-trace-writes.yml
deleted file mode 100644
index 9c5239081b9..00000000000
--- a/changelogs/unreleased/lock-trace-writes.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Lock writes to trace stream
-merge_request:
-author:
-type: fixed
diff --git a/changelogs/unreleased/fix-deadlock-chunked-io.yml b/changelogs/unreleased/markdown-toolbar-btn-fix.yml
index def7a59e86e..eefb4d19f86 100644
--- a/changelogs/unreleased/fix-deadlock-chunked-io.yml
+++ b/changelogs/unreleased/markdown-toolbar-btn-fix.yml
@@ -1,5 +1,5 @@
---
-title: Fix deadlock on ChunkedIO
+title: Fixed markdown toolbar buttons
merge_request:
author:
type: fixed
diff --git a/changelogs/unreleased/mg-fix-knative-application-row.yml b/changelogs/unreleased/mg-fix-knative-application-row.yml
deleted file mode 100644
index 95142d380a4..00000000000
--- a/changelogs/unreleased/mg-fix-knative-application-row.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Hide Knative from group cluster applications until supported
-merge_request: 23577
-author:
-type: fixed
diff --git a/changelogs/unreleased/mk-avoid-read-only-error.yml b/changelogs/unreleased/mk-avoid-read-only-error.yml
new file mode 100644
index 00000000000..8641f5db9f0
--- /dev/null
+++ b/changelogs/unreleased/mk-avoid-read-only-error.yml
@@ -0,0 +1,5 @@
+---
+title: Prevent admins from attempting hashed storage migration on read only DB
+merge_request: 23597
+author:
+type: fixed
diff --git a/changelogs/unreleased/move-group-issues-search-cte-up-the-chain.yml b/changelogs/unreleased/move-group-issues-search-cte-up-the-chain.yml
deleted file mode 100644
index 0269e7b6196..00000000000
--- a/changelogs/unreleased/move-group-issues-search-cte-up-the-chain.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix error when searching for group issues with priority or popularity sort
-merge_request: 23445
-author:
-type: fixed
diff --git a/changelogs/unreleased/mr-file-tree-commit.yml b/changelogs/unreleased/mr-file-tree-commit.yml
deleted file mode 100644
index e0d47e6e61f..00000000000
--- a/changelogs/unreleased/mr-file-tree-commit.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Show tree collapse button for merge request commit diffs
-merge_request:
-author:
-type: fixed
diff --git a/changelogs/unreleased/mr-origin-23218.yml b/changelogs/unreleased/mr-origin-23218.yml
deleted file mode 100644
index 49867f04343..00000000000
--- a/changelogs/unreleased/mr-origin-23218.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix typo for scheduled pipeline
-merge_request: 23218
-author: Davy Defaud
-type: other
diff --git a/changelogs/unreleased/mr-pipelines-2.yml b/changelogs/unreleased/mr-pipelines-2.yml
deleted file mode 100644
index 683c626c3ce..00000000000
--- a/changelogs/unreleased/mr-pipelines-2.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Merge request pipelines
-merge_request: 23217
-author:
-type: added
diff --git a/changelogs/unreleased/mr-sticky-headers.yml b/changelogs/unreleased/mr-sticky-headers.yml
deleted file mode 100644
index c20829bc2d7..00000000000
--- a/changelogs/unreleased/mr-sticky-headers.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Make diff file headers sticky
-merge_request:
-author:
-type: changed
diff --git a/changelogs/unreleased/mr-tree-filter-path-name.yml b/changelogs/unreleased/mr-tree-filter-path-name.yml
deleted file mode 100644
index 152f8a67337..00000000000
--- a/changelogs/unreleased/mr-tree-filter-path-name.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Changed merge request filtering to be by path instead of name
-merge_request:
-author:
-type: changed
diff --git a/changelogs/unreleased/multiple-diff-line-discussions-fix.yml b/changelogs/unreleased/multiple-diff-line-discussions-fix.yml
deleted file mode 100644
index 870a8ab3815..00000000000
--- a/changelogs/unreleased/multiple-diff-line-discussions-fix.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fixed duplicate discussions getting added to diff lines
-merge_request:
-author:
-type: fixed
diff --git a/changelogs/unreleased/non-webkit-scrollbar-fixing.yml b/changelogs/unreleased/non-webkit-scrollbar-fixing.yml
deleted file mode 100644
index 526a9f25486..00000000000
--- a/changelogs/unreleased/non-webkit-scrollbar-fixing.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix horizontal scrollbar overlapping on horizontal scrolling-tabs
-merge_request: 23167
-author: Harry Kiselev
-type: other
diff --git a/changelogs/unreleased/optimise-job-request.yml b/changelogs/unreleased/optimise-job-request.yml
deleted file mode 100644
index e1265841b48..00000000000
--- a/changelogs/unreleased/optimise-job-request.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Use cached size when passing artifacts to Runner
-merge_request:
-author:
-type: performance
diff --git a/changelogs/unreleased/order-of-notification-settings.yml b/changelogs/unreleased/order-of-notification-settings.yml
deleted file mode 100644
index 0f0243bcb40..00000000000
--- a/changelogs/unreleased/order-of-notification-settings.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: reorder notification settings by noisy-ness
-merge_request:
-author: C.J. Jameson
-type: changed
diff --git a/changelogs/unreleased/osw-fallback-on-blank-refs.yml b/changelogs/unreleased/osw-fallback-on-blank-refs.yml
deleted file mode 100644
index 039179f5829..00000000000
--- a/changelogs/unreleased/osw-fallback-on-blank-refs.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Avoid Gitaly RPC errors when fetching diff stats
-merge_request: 22995
-author:
-type: fixed
diff --git a/changelogs/unreleased/osw-fix-grouping-by-file-path.yml b/changelogs/unreleased/osw-fix-grouping-by-file-path.yml
deleted file mode 100644
index dff3116e7c6..00000000000
--- a/changelogs/unreleased/osw-fix-grouping-by-file-path.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Avoid 500's when serializing legacy diff notes
-merge_request: 23544
-author:
-type: fixed
diff --git a/changelogs/unreleased/osw-remove-unnused-data-from-diff-discussions.yml b/changelogs/unreleased/osw-remove-unnused-data-from-diff-discussions.yml
deleted file mode 100644
index 58d9a19d038..00000000000
--- a/changelogs/unreleased/osw-remove-unnused-data-from-diff-discussions.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Remove unused data from discussions endpoint
-merge_request: 23570
-author:
-type: performance
diff --git a/changelogs/unreleased/osw-update-mr-metrics-with-events-data.yml b/changelogs/unreleased/osw-update-mr-metrics-with-events-data.yml
deleted file mode 100644
index 09a10a86adc..00000000000
--- a/changelogs/unreleased/osw-update-mr-metrics-with-events-data.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Populate MR metrics with events table information (migration)
-merge_request: 23564
-author:
-type: performance
diff --git a/changelogs/unreleased/profile-fixing.yml b/changelogs/unreleased/profile-fixing.yml
deleted file mode 100644
index 7e255d997d8..00000000000
--- a/changelogs/unreleased/profile-fixing.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix bottom paddings of profile header and some markup updates of profile
-merge_request: 23168
-author: Harry Kiselev
-type: other
diff --git a/changelogs/unreleased/project_identicon_fix.yml b/changelogs/unreleased/project_identicon_fix.yml
deleted file mode 100644
index de4876fc4a5..00000000000
--- a/changelogs/unreleased/project_identicon_fix.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix project identicon aligning Harry Kiselev
-merge_request: 23166
-author: Harry Kiselev
-type: other
diff --git a/changelogs/unreleased/rails5-active-record-class-value.yml b/changelogs/unreleased/rails5-active-record-class-value.yml
deleted file mode 100644
index 9f9fdf10cd1..00000000000
--- a/changelogs/unreleased/rails5-active-record-class-value.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: 'Rails5: Passing a class as a value in an Active Record query is deprecated'
-merge_request: 23164
-author: Jasper Maes
-type: other
diff --git a/changelogs/unreleased/rails5-deprecation-render-nothing.yml b/changelogs/unreleased/rails5-deprecation-render-nothing.yml
deleted file mode 100644
index 32e2d5800c7..00000000000
--- a/changelogs/unreleased/rails5-deprecation-render-nothing.yml
+++ /dev/null
@@ -1,6 +0,0 @@
----
-title: render :nothing option is deprecated, Use head method to respond with empty
- response body.
-merge_request: 23311
-author: Jasper Maes
-type: other
diff --git a/changelogs/unreleased/rails5-env-deprecated.yml b/changelogs/unreleased/rails5-env-deprecated.yml
deleted file mode 100644
index 2f8573e2ff6..00000000000
--- a/changelogs/unreleased/rails5-env-deprecated.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: 'Rails5: env is deprecated and will be removed from Rails 5.1'
-merge_request: 22626
-author: Jasper Maes
-type: other
diff --git a/changelogs/unreleased/remove-blob-search-limit.yml b/changelogs/unreleased/remove-blob-search-limit.yml
deleted file mode 100644
index 5bad3a83dbb..00000000000
--- a/changelogs/unreleased/remove-blob-search-limit.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Remove limit of 100 when searching repository code.
-merge_request: 8671
-author:
-type: fixed
diff --git a/changelogs/unreleased/remove-deployment-status-hack-from-backend.yml b/changelogs/unreleased/remove-deployment-status-hack-from-backend.yml
deleted file mode 100644
index 2348bfab7d9..00000000000
--- a/changelogs/unreleased/remove-deployment-status-hack-from-backend.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Return real deployment status to frontend
-merge_request: 23270
-author:
-type: fixed
diff --git a/changelogs/unreleased/remove-duplicate-primary-button-in-dashboard-snippets.yml b/changelogs/unreleased/remove-duplicate-primary-button-in-dashboard-snippets.yml
deleted file mode 100644
index 3a8b3a0df5d..00000000000
--- a/changelogs/unreleased/remove-duplicate-primary-button-in-dashboard-snippets.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Remove duplicate primary button in dashboard snippets on small viewports
-merge_request: 22902
-author: George Tsiolis
-type: fixed
diff --git a/changelogs/unreleased/render-text-deprecated.yml b/changelogs/unreleased/render-text-deprecated.yml
deleted file mode 100644
index 7dbbd13bcef..00000000000
--- a/changelogs/unreleased/render-text-deprecated.yml
+++ /dev/null
@@ -1,6 +0,0 @@
----
-title: 'Fix deprecation: render :text is deprecated because it does not actually render
- a text/plain response'
-merge_request: 23425
-author: Jasper Maes
-type: other
diff --git a/changelogs/unreleased/retryable_create_or_update_kubernetes_namespace.yml b/changelogs/unreleased/retryable_create_or_update_kubernetes_namespace.yml
deleted file mode 100644
index 607f2709f90..00000000000
--- a/changelogs/unreleased/retryable_create_or_update_kubernetes_namespace.yml
+++ /dev/null
@@ -1,6 +0,0 @@
----
-title: Updates service to update Kubernetes project namespaces and restricted service
- account if present
-merge_request: 23525
-author:
-type: changed
diff --git a/changelogs/unreleased/revert-1cccfca1.yml b/changelogs/unreleased/revert-1cccfca1.yml
deleted file mode 100644
index c1efdaac138..00000000000
--- a/changelogs/unreleased/revert-1cccfca1.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Restore kubernetes:active in Auto-DevOps.gitlab-ci.yml (reverts 22929)
-merge_request: 23826
-author:
-type: fixed
diff --git a/changelogs/unreleased/rs-cherry-pick-api.yml b/changelogs/unreleased/rs-cherry-pick-api.yml
deleted file mode 100644
index ce844dfc939..00000000000
--- a/changelogs/unreleased/rs-cherry-pick-api.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Resolve possible cherry pick API race condition
-merge_request:
-author:
-type: fixed
diff --git a/changelogs/unreleased/security-182-update-workhorse.yml b/changelogs/unreleased/security-182-update-workhorse.yml
deleted file mode 100644
index 76850901b68..00000000000
--- a/changelogs/unreleased/security-182-update-workhorse.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Redact sensitive information on gitlab-workhorse log
-merge_request:
-author:
-type: security
diff --git a/changelogs/unreleased/security-2717-xss-username-autocomplete.yml b/changelogs/unreleased/security-2717-xss-username-autocomplete.yml
deleted file mode 100644
index d9b1015eeb4..00000000000
--- a/changelogs/unreleased/security-2717-xss-username-autocomplete.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Escape user fullname while rendering autocomplete template to prevent XSS
-merge_request:
-author:
-type: security
diff --git a/changelogs/unreleased/security-2736-prometheus-ssrf.yml b/changelogs/unreleased/security-2736-prometheus-ssrf.yml
deleted file mode 100644
index 9d0dda8a75f..00000000000
--- a/changelogs/unreleased/security-2736-prometheus-ssrf.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Do not follow redirects in Prometheus service when making http requests to the configured api url
-merge_request:
-author:
-type: security
diff --git a/changelogs/unreleased/security-2754-fix-lfs-import.yml b/changelogs/unreleased/security-2754-fix-lfs-import.yml
deleted file mode 100644
index e8e74c9c3f6..00000000000
--- a/changelogs/unreleased/security-2754-fix-lfs-import.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Validate LFS hrefs before downloading them
-merge_request:
-author:
-type: security
diff --git a/changelogs/unreleased/security-bvl-exposure-in-commits-list.yml b/changelogs/unreleased/security-bvl-exposure-in-commits-list.yml
deleted file mode 100644
index 0361fb0c041..00000000000
--- a/changelogs/unreleased/security-bvl-exposure-in-commits-list.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Don't expose confidential information in commit message list
-merge_request:
-author:
-type: security
diff --git a/changelogs/unreleased/security-email-change-notification.yml b/changelogs/unreleased/security-email-change-notification.yml
deleted file mode 100644
index 45075ff20bb..00000000000
--- a/changelogs/unreleased/security-email-change-notification.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Provide email notification when a user changes their email address
-merge_request:
-author:
-type: security
diff --git a/changelogs/unreleased/security-fix-pat-web-access.yml b/changelogs/unreleased/security-fix-pat-web-access.yml
deleted file mode 100644
index 62ffb908fe5..00000000000
--- a/changelogs/unreleased/security-fix-pat-web-access.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Restrict Personal Access Tokens to API scope on web requests
-merge_request:
-author:
-type: security
diff --git a/changelogs/unreleased/security-fix-uri-xss-applications.yml b/changelogs/unreleased/security-fix-uri-xss-applications.yml
deleted file mode 100644
index 0eaa1b1c4a3..00000000000
--- a/changelogs/unreleased/security-fix-uri-xss-applications.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Resolve reflected XSS in Ouath authorize window
-merge_request:
-author:
-type: security
diff --git a/changelogs/unreleased/security-fix-webhook-ssrf-ipv6.yml b/changelogs/unreleased/security-fix-webhook-ssrf-ipv6.yml
deleted file mode 100644
index 32c85a2a7da..00000000000
--- a/changelogs/unreleased/security-fix-webhook-ssrf-ipv6.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix SSRF in project integrations
-merge_request:
-author:
-type: security
diff --git a/changelogs/unreleased/security-fj-crlf-injection.yml b/changelogs/unreleased/security-fj-crlf-injection.yml
deleted file mode 100644
index 861167b8a6e..00000000000
--- a/changelogs/unreleased/security-fj-crlf-injection.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix CRLF vulnerability in Project hooks
-merge_request:
-author:
-type: security
diff --git a/changelogs/unreleased/security-guest-comments.yml b/changelogs/unreleased/security-guest-comments.yml
deleted file mode 100644
index 2c99512433b..00000000000
--- a/changelogs/unreleased/security-guest-comments.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fixed ability to comment on locked/confidential issues.
-merge_request:
-author:
-type: security
diff --git a/changelogs/unreleased/security-guest-comments_2.yml b/changelogs/unreleased/security-guest-comments_2.yml
deleted file mode 100644
index be6f2d6a490..00000000000
--- a/changelogs/unreleased/security-guest-comments_2.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fixed ability of guest users to edit/delete comments on locked or confidential issues.
-merge_request:
-author:
-type: security
diff --git a/changelogs/unreleased/security-issue_51301.yml b/changelogs/unreleased/security-issue_51301.yml
deleted file mode 100644
index cf8ebb54b1c..00000000000
--- a/changelogs/unreleased/security-issue_51301.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix milestone promotion authorization check
-merge_request:
-author:
-type: security
diff --git a/changelogs/unreleased/security-mermaid-xss.yml b/changelogs/unreleased/security-mermaid-xss.yml
deleted file mode 100644
index bcf93ef37ff..00000000000
--- a/changelogs/unreleased/security-mermaid-xss.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Configure mermaid to not render HTML content in diagrams
-merge_request:
-author:
-type: security
diff --git a/changelogs/unreleased/security-pages-toctou-race.yml b/changelogs/unreleased/security-pages-toctou-race.yml
deleted file mode 100644
index 1c055f6087f..00000000000
--- a/changelogs/unreleased/security-pages-toctou-race.yml
+++ /dev/null
@@ -1,6 +0,0 @@
----
-title: Fix a possible symlink time of check to time of use race condition in GitLab
- Pages
-merge_request:
-author:
-type: security
diff --git a/changelogs/unreleased/security-private-group.yml b/changelogs/unreleased/security-private-group.yml
deleted file mode 100644
index dbb7794dfed..00000000000
--- a/changelogs/unreleased/security-private-group.yml
+++ /dev/null
@@ -1,6 +0,0 @@
----
-title: Removed ability to see private group names when the group id is entered in
- the url.
-merge_request:
-author:
-type: security
diff --git a/changelogs/unreleased/security-stored-xss-for-environments.yml b/changelogs/unreleased/security-stored-xss-for-environments.yml
deleted file mode 100644
index 5d78ca00942..00000000000
--- a/changelogs/unreleased/security-stored-xss-for-environments.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix stored XSS for Environments
-merge_request:
-author:
-type: security
diff --git a/changelogs/unreleased/security-xss-in-markdown-following-unrecognized-html-element.yml b/changelogs/unreleased/security-xss-in-markdown-following-unrecognized-html-element.yml
deleted file mode 100644
index 3bd8123a346..00000000000
--- a/changelogs/unreleased/security-xss-in-markdown-following-unrecognized-html-element.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix possible XSS attack in Markdown urls with spaces
-merge_request: 2599
-author:
-type: security
diff --git a/changelogs/unreleased/set-kubeconfig-nil-when-token-nil.yml b/changelogs/unreleased/set-kubeconfig-nil-when-token-nil.yml
deleted file mode 100644
index 6eac2a0146c..00000000000
--- a/changelogs/unreleased/set-kubeconfig-nil-when-token-nil.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Make KUBECONFIG nil if KUBE_TOKEN is nil
-merge_request: 23414
-author:
-type: fixed
diff --git a/changelogs/unreleased/sh-53180-append-path.yml b/changelogs/unreleased/sh-53180-append-path.yml
deleted file mode 100644
index 64fae5522d8..00000000000
--- a/changelogs/unreleased/sh-53180-append-path.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Make sure there's only one slash as path separator
-merge_request: 22954
-author:
-type: other
diff --git a/changelogs/unreleased/sh-bump-gems-security.yml b/changelogs/unreleased/sh-bump-gems-security.yml
deleted file mode 100644
index 06489f6f979..00000000000
--- a/changelogs/unreleased/sh-bump-gems-security.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Bump nokogiri, loofah, and rack gems for security updates
-merge_request: 23204
-author:
-type: security
diff --git a/changelogs/unreleased/sh-bump-ruby-2-5-3.yml b/changelogs/unreleased/sh-bump-ruby-2-5-3.yml
deleted file mode 100644
index 13cadc73e9c..00000000000
--- a/changelogs/unreleased/sh-bump-ruby-2-5-3.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Upgrade to Ruby 2.5.3
-merge_request: 2806
-author:
-type: performance
diff --git a/changelogs/unreleased/sh-cache-avatar-paths.yml b/changelogs/unreleased/sh-cache-avatar-paths.yml
new file mode 100644
index 00000000000..b59a4db413d
--- /dev/null
+++ b/changelogs/unreleased/sh-cache-avatar-paths.yml
@@ -0,0 +1,5 @@
+---
+title: Cache avatar URLs and paths within a request
+merge_request: 23950
+author:
+type: performance
diff --git a/changelogs/unreleased/sh-disable-autocomplete-mirror-settings.yml b/changelogs/unreleased/sh-disable-autocomplete-mirror-settings.yml
deleted file mode 100644
index e42906e88f2..00000000000
--- a/changelogs/unreleased/sh-disable-autocomplete-mirror-settings.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Disable password autocomplete in mirror form fill
-merge_request: 23402
-author:
-type: fixed
diff --git a/changelogs/unreleased/sh-fix-http-clone-panel.yml b/changelogs/unreleased/sh-fix-http-clone-panel.yml
new file mode 100644
index 00000000000..ab220bd5076
--- /dev/null
+++ b/changelogs/unreleased/sh-fix-http-clone-panel.yml
@@ -0,0 +1,5 @@
+---
+title: Fix missing Git clone button when protocol restriction setting enabled
+merge_request: 24015
+author:
+type: fixed
diff --git a/changelogs/unreleased/sh-fix-issue-38317.yml b/changelogs/unreleased/sh-fix-issue-38317.yml
deleted file mode 100644
index 13fcb5b8f96..00000000000
--- a/changelogs/unreleased/sh-fix-issue-38317.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Remove needless auto-capitalization on Wiki page titles
-merge_request: 23288
-author:
-type: fixed
diff --git a/changelogs/unreleased/sh-fix-issue-51220.yml b/changelogs/unreleased/sh-fix-issue-51220.yml
deleted file mode 100644
index 048f58611cb..00000000000
--- a/changelogs/unreleased/sh-fix-issue-51220.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Handle force_remove_source_branch when creating merge request
-merge_request: 23281
-author:
-type: fixed
diff --git a/changelogs/unreleased/sh-fix-issue-53783-ce.yml b/changelogs/unreleased/sh-fix-issue-53783-ce.yml
deleted file mode 100644
index 10be1d81768..00000000000
--- a/changelogs/unreleased/sh-fix-issue-53783-ce.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix enabling project deploy key for admins
-merge_request: 23043
-author:
-type: fixed
diff --git a/changelogs/unreleased/sh-fix-mirrors-protected-branches.yml b/changelogs/unreleased/sh-fix-mirrors-protected-branches.yml
deleted file mode 100644
index 627de25650d..00000000000
--- a/changelogs/unreleased/sh-fix-mirrors-protected-branches.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix "protected branches only" checkbox not set properly at init
-merge_request: 23409
-author:
-type: fixed
diff --git a/changelogs/unreleased/sh-handle-invalid-gpg-sig.yml b/changelogs/unreleased/sh-handle-invalid-gpg-sig.yml
deleted file mode 100644
index 185e2547e16..00000000000
--- a/changelogs/unreleased/sh-handle-invalid-gpg-sig.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Gracefully handle unknown/invalid GPG keys
-merge_request: 23492
-author:
-type: fixed
diff --git a/changelogs/unreleased/sh-handle-string-null-bytes.yml b/changelogs/unreleased/sh-handle-string-null-bytes.yml
deleted file mode 100644
index edc045274e3..00000000000
--- a/changelogs/unreleased/sh-handle-string-null-bytes.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Gracefully handle references with null bytes
-merge_request: 23365
-author:
-type: fixed
diff --git a/changelogs/unreleased/sh-ignore-arrays-url-sanitizer.yml b/changelogs/unreleased/sh-ignore-arrays-url-sanitizer.yml
deleted file mode 100644
index c010bd1f540..00000000000
--- a/changelogs/unreleased/sh-ignore-arrays-url-sanitizer.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Only allow strings in URL::Sanitizer.valid?
-merge_request: 23675
-author:
-type: fixed
diff --git a/changelogs/unreleased/sh-json-serialize-broadcast-messages.yml b/changelogs/unreleased/sh-json-serialize-broadcast-messages.yml
deleted file mode 100644
index e8bee64f780..00000000000
--- a/changelogs/unreleased/sh-json-serialize-broadcast-messages.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Avoid caching BroadcastMessage as an ActiveRecord object
-merge_request: 23662
-author:
-type: fixed
diff --git a/changelogs/unreleased/sh-remove-local-sidekiq-admin-check.yml b/changelogs/unreleased/sh-remove-local-sidekiq-admin-check.yml
deleted file mode 100644
index 3ec15908fc7..00000000000
--- a/changelogs/unreleased/sh-remove-local-sidekiq-admin-check.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Remove display of local Sidekiq process in /admin/sidekiq
-merge_request: 23118
-author:
-type: fixed
diff --git a/changelogs/unreleased/sh-truncate-with-periods.yml b/changelogs/unreleased/sh-truncate-with-periods.yml
deleted file mode 100644
index b1c6b4f9cbd..00000000000
--- a/changelogs/unreleased/sh-truncate-with-periods.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Truncate merge request titles with periods instead of ellipsis
-merge_request: 23558
-author:
-type: changed
diff --git a/changelogs/unreleased/sh-use-nakayoshi-fork.yml b/changelogs/unreleased/sh-use-nakayoshi-fork.yml
deleted file mode 100644
index 5977d9b0974..00000000000
--- a/changelogs/unreleased/sh-use-nakayoshi-fork.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Improve memory performance by reducing dirty pages after fork()
-merge_request: 23169
-author:
-type: performance
diff --git a/changelogs/unreleased/sh-use-nokogiri-xml-backend.yml b/changelogs/unreleased/sh-use-nokogiri-xml-backend.yml
deleted file mode 100644
index 6a82e32c416..00000000000
--- a/changelogs/unreleased/sh-use-nokogiri-xml-backend.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Use Nokogiri as the ActiveSupport XML backend
-merge_request: 23136
-author:
-type: performance
diff --git a/changelogs/unreleased/spec-positional-arguments.yml b/changelogs/unreleased/spec-positional-arguments.yml
new file mode 100644
index 00000000000..9dc114e5595
--- /dev/null
+++ b/changelogs/unreleased/spec-positional-arguments.yml
@@ -0,0 +1,5 @@
+---
+title: 'Fix deprecation: Using positional arguments in integration tests'
+merge_request: 24009
+author: Jasper Maes
+type: other
diff --git a/changelogs/unreleased/specs-positional-arguments.yml b/changelogs/unreleased/specs-positional-arguments.yml
new file mode 100644
index 00000000000..38b831bd72c
--- /dev/null
+++ b/changelogs/unreleased/specs-positional-arguments.yml
@@ -0,0 +1,5 @@
+---
+title: convert specs in javascripts/ and support/ to new syntax
+merge_request: 23947
+author: Jasper Maes
+type: other
diff --git a/changelogs/unreleased/speed-up-relative-positioning.yml b/changelogs/unreleased/speed-up-relative-positioning.yml
deleted file mode 100644
index 3bd865fb5de..00000000000
--- a/changelogs/unreleased/speed-up-relative-positioning.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Speed up issue board lists in groups with many projects
-merge_request:
-author:
-type: performance
diff --git a/changelogs/unreleased/store-correlation-logs.yml b/changelogs/unreleased/store-correlation-logs.yml
deleted file mode 100644
index d5f6c789a17..00000000000
--- a/changelogs/unreleased/store-correlation-logs.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Log and pass correlation-id between Unicorn, Sidekiq and Gitaly
-merge_request:
-author:
-type: added
diff --git a/changelogs/unreleased/suggest-change-to-diff-line.yml b/changelogs/unreleased/suggest-change-to-diff-line.yml
deleted file mode 100644
index cb949f14e8c..00000000000
--- a/changelogs/unreleased/suggest-change-to-diff-line.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Add ability to render suggestions
-merge_request: 23147
-author:
-type: added
diff --git a/changelogs/unreleased/support-gitaly-tls.yml b/changelogs/unreleased/support-gitaly-tls.yml
new file mode 100644
index 00000000000..2a15500d6da
--- /dev/null
+++ b/changelogs/unreleased/support-gitaly-tls.yml
@@ -0,0 +1,5 @@
+---
+title: Support tls communication in gitaly
+merge_request: 22602
+author:
+type: added
diff --git a/changelogs/unreleased/switch-rails.yml b/changelogs/unreleased/switch-rails.yml
deleted file mode 100644
index 4edf709dbd4..00000000000
--- a/changelogs/unreleased/switch-rails.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Switch to Rails 5
-merge_request: 21492
-author:
-type: other
diff --git a/changelogs/unreleased/tc-backfill-full-path-config.yml b/changelogs/unreleased/tc-backfill-full-path-config.yml
deleted file mode 100644
index 4f06284d0e3..00000000000
--- a/changelogs/unreleased/tc-backfill-full-path-config.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Migration to write fullpath in all repository configs
-merge_request: 22322
-author:
-type: other
diff --git a/changelogs/unreleased/tc-backfill-hashed-project_repositories.yml b/changelogs/unreleased/tc-backfill-hashed-project_repositories.yml
deleted file mode 100644
index 90a5c8c4e2c..00000000000
--- a/changelogs/unreleased/tc-backfill-hashed-project_repositories.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fill project_repositories for hashed storage projects
-merge_request: 23482
-author:
-type: added
diff --git a/changelogs/unreleased/tc-repo-full-path-in-db.yml b/changelogs/unreleased/tc-repo-full-path-in-db.yml
deleted file mode 100644
index ead8feabeb9..00000000000
--- a/changelogs/unreleased/tc-repo-full-path-in-db.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Add model and relation to store repo full path in database
-merge_request: 23143
-author:
-type: added
diff --git a/changelogs/unreleased/triggermesh-phase2-external-ip.yml b/changelogs/unreleased/triggermesh-phase2-external-ip.yml
deleted file mode 100644
index 582c8f6df2e..00000000000
--- a/changelogs/unreleased/triggermesh-phase2-external-ip.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Add an external IP address to the knative cluster application page
-merge_request:
-author: Chris Baumbauer
-type: fixed
diff --git a/changelogs/unreleased/triggermesh-phase2-knative-description.yml b/changelogs/unreleased/triggermesh-phase2-knative-description.yml
deleted file mode 100644
index c6cee1984d5..00000000000
--- a/changelogs/unreleased/triggermesh-phase2-knative-description.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Modify the wording for the knative cluster application to match upstream
-merge_request: 23289
-author: Chris Baumbauer
-type: fixed
diff --git a/changelogs/unreleased/triggermesh-phase2-serverless-list.yml b/changelogs/unreleased/triggermesh-phase2-serverless-list.yml
deleted file mode 100644
index 22e1a35dd90..00000000000
--- a/changelogs/unreleased/triggermesh-phase2-serverless-list.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Introduce Knative and Serverless Components
-merge_request: 23174
-author: Chris Baumbauer
-type: added
diff --git a/changelogs/unreleased/triggermesh-phase2-serverless.yml b/changelogs/unreleased/triggermesh-phase2-serverless.yml
deleted file mode 100644
index bee2b5e1e2c..00000000000
--- a/changelogs/unreleased/triggermesh-phase2-serverless.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Add knative client to kubeclient library
-merge_request: 22968
-author: cab105
-type: added
diff --git a/changelogs/unreleased/unicorn-monkey-patch.yml b/changelogs/unreleased/unicorn-monkey-patch.yml
deleted file mode 100644
index 6b0e00ca291..00000000000
--- a/changelogs/unreleased/unicorn-monkey-patch.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Add monkey patch to unicorn to fix eof? problem
-merge_request: 23385
-author:
-type: fixed
diff --git a/changelogs/unreleased/update-gitlab-runner-helm-chart-to-0-1-39.yml b/changelogs/unreleased/update-gitlab-runner-helm-chart-to-0-1-39.yml
deleted file mode 100644
index dffcdb0bb5a..00000000000
--- a/changelogs/unreleased/update-gitlab-runner-helm-chart-to-0-1-39.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Update used version of Runner Helm Chart to 0.1.39
-merge_request: 23633
-author:
-type: other
diff --git a/changelogs/unreleased/update-gitlab-runner-helm-chart-version.yml b/changelogs/unreleased/update-gitlab-runner-helm-chart-version.yml
deleted file mode 100644
index 9051e4f79c8..00000000000
--- a/changelogs/unreleased/update-gitlab-runner-helm-chart-version.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Update used version of Runner Helm Chart to 0.1.38
-merge_request: 23304
-author:
-type: other
diff --git a/changelogs/unreleased/upgrade-to-workhorse-7-6-0.yml b/changelogs/unreleased/upgrade-to-workhorse-7-6-0.yml
deleted file mode 100644
index 1389693b9a9..00000000000
--- a/changelogs/unreleased/upgrade-to-workhorse-7-6-0.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Upgrade workhorse to 7.6.0
-merge_request: 23694
-author:
-type: other
diff --git a/changelogs/unreleased/upgrade_kubeclient_400.yml b/changelogs/unreleased/upgrade_kubeclient_400.yml
deleted file mode 100644
index edb38710e6a..00000000000
--- a/changelogs/unreleased/upgrade_kubeclient_400.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Upgrade kubeclient to 4.0.0
-merge_request: 23261
-author: Praveen Arimbrathodiyil @pravi
-type: other
diff --git a/changelogs/unreleased/usage-count.yml b/changelogs/unreleased/usage-count.yml
deleted file mode 100644
index efff2615ce4..00000000000
--- a/changelogs/unreleased/usage-count.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Use approximate count for big tables for usage statistics.
-merge_request:
-author:
-type: fixed
diff --git a/changelogs/unreleased/validate-foreign-keys-being-indexed.yml b/changelogs/unreleased/validate-foreign-keys-being-indexed.yml
deleted file mode 100644
index 6608a93c08f..00000000000
--- a/changelogs/unreleased/validate-foreign-keys-being-indexed.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Validate foreign keys being created and indexed for column with _id
-merge_request: 22808
-author:
-type: performance
diff --git a/changelogs/unreleased/winh-collapse-discussions.yml b/changelogs/unreleased/winh-collapse-discussions.yml
deleted file mode 100644
index 19d04506318..00000000000
--- a/changelogs/unreleased/winh-collapse-discussions.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix collapsing discussion replies
-merge_request: 23462
-author:
-type: fixed
diff --git a/changelogs/unreleased/winh-divider-margin.yml b/changelogs/unreleased/winh-divider-margin.yml
deleted file mode 100644
index db84090c15c..00000000000
--- a/changelogs/unreleased/winh-divider-margin.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Adjust divider margin to comply with design specs
-merge_request: 23548
-author:
-type: changed
diff --git a/changelogs/unreleased/winh-dropdown-divider-color.yml b/changelogs/unreleased/winh-dropdown-divider-color.yml
deleted file mode 100644
index 6b6ecd831b8..00000000000
--- a/changelogs/unreleased/winh-dropdown-divider-color.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Change dropdown divider color to gray-200 (#dfdfdf)
-merge_request: 23592
-author:
-type: changed
diff --git a/changelogs/unreleased/winh-dropdown-item-padding.yml b/changelogs/unreleased/winh-dropdown-item-padding.yml
deleted file mode 100644
index 9f18abba9d1..00000000000
--- a/changelogs/unreleased/winh-dropdown-item-padding.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Adjust dropdown item and header padding to comply with design specs
-merge_request: 23552
-author:
-type: changed
diff --git a/changelogs/unreleased/winh-issue-boards-project-dropdown-close.yml b/changelogs/unreleased/winh-issue-boards-project-dropdown-close.yml
deleted file mode 100644
index 18f7da56edb..00000000000
--- a/changelogs/unreleased/winh-issue-boards-project-dropdown-close.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Remove close icon from projects dropdown in issue boards
-merge_request: 23567
-author:
-type: changed
diff --git a/changelogs/unreleased/winh-markdown-preview-lists.yml b/changelogs/unreleased/winh-markdown-preview-lists.yml
deleted file mode 100644
index 6e47726283d..00000000000
--- a/changelogs/unreleased/winh-markdown-preview-lists.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Remove unnecessary div from MarkdownField to apply list styles correctly
-merge_request: 23733
-author:
-type: fixed
diff --git a/changelogs/unreleased/winh-merge-request-commit-context.yml b/changelogs/unreleased/winh-merge-request-commit-context.yml
new file mode 100644
index 00000000000..9e12a926af4
--- /dev/null
+++ b/changelogs/unreleased/winh-merge-request-commit-context.yml
@@ -0,0 +1,5 @@
+---
+title: Display commit ID for discussions made on merge request commits
+merge_request: 23837
+author:
+type: fixed
diff --git a/changelogs/unreleased/winh-merge-request-commit-discussion.yml b/changelogs/unreleased/winh-merge-request-commit-discussion.yml
deleted file mode 100644
index b0c6264369b..00000000000
--- a/changelogs/unreleased/winh-merge-request-commit-discussion.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Display commit ID for commit diff discussion on merge request
-merge_request: 23370
-author:
-type: fixed
diff --git a/changelogs/unreleased/winh-merge-request-diff-discussion-commit-id.yml b/changelogs/unreleased/winh-merge-request-diff-discussion-commit-id.yml
deleted file mode 100644
index 2ce16a2b6b7..00000000000
--- a/changelogs/unreleased/winh-merge-request-diff-discussion-commit-id.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Pass commit when posting diff discussions
-merge_request: 23371
-author:
-type: fixed
diff --git a/changelogs/unreleased/winh-milestone-select.yml b/changelogs/unreleased/winh-milestone-select.yml
deleted file mode 100644
index 8464fc6c541..00000000000
--- a/changelogs/unreleased/winh-milestone-select.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix milestone select in issue sidebar of issue boards
-merge_request: 23625
-author:
-type: fixed
diff --git a/changelogs/unreleased/winh-resolved-discussions-reply-field.yml b/changelogs/unreleased/winh-resolved-discussions-reply-field.yml
deleted file mode 100644
index 01cf35ae8a7..00000000000
--- a/changelogs/unreleased/winh-resolved-discussions-reply-field.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Display reply field if resolved discussion has no replies
-merge_request: 23801
-author:
-type: fixed
diff --git a/changelogs/unreleased/winh-upgrade-gitlab-ui.yml b/changelogs/unreleased/winh-upgrade-gitlab-ui.yml
new file mode 100644
index 00000000000..b312a329f5d
--- /dev/null
+++ b/changelogs/unreleased/winh-upgrade-gitlab-ui.yml
@@ -0,0 +1,5 @@
+---
+title: Upgrade @gitlab/ui to 1.16.2
+merge_request: 23946
+author:
+type: other
diff --git a/changelogs/unreleased/workhorse-7-3-0.yml b/changelogs/unreleased/workhorse-7-3-0.yml
deleted file mode 100644
index 6708b8a3cbb..00000000000
--- a/changelogs/unreleased/workhorse-7-3-0.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Upgrade GitLab Workhorse to v7.3.0
-merge_request: 23489
-author:
-type: other
diff --git a/changelogs/unreleased/zj-improve-gitaly-pb.yml b/changelogs/unreleased/zj-improve-gitaly-pb.yml
deleted file mode 100644
index 506a0303d8a..00000000000
--- a/changelogs/unreleased/zj-improve-gitaly-pb.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Show what RPC is called in the performance bar
-merge_request: 23140
-author:
-type: other
diff --git a/changelogs/unreleased/zj-pool-repository-creation.yml b/changelogs/unreleased/zj-pool-repository-creation.yml
deleted file mode 100644
index a24b96e4924..00000000000
--- a/changelogs/unreleased/zj-pool-repository-creation.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Allow public forks to be deduplicated
-merge_request: 23508
-author:
-type: added
diff --git a/changelogs/unreleased/zj-remove-broken-storage.yml b/changelogs/unreleased/zj-remove-broken-storage.yml
deleted file mode 100644
index 9df87b40e09..00000000000
--- a/changelogs/unreleased/zj-remove-broken-storage.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Remove obsolete gitlab_shell rake tasks
-merge_request: 22417
-author:
-type: removed
diff --git a/config/gitlab.yml.example b/config/gitlab.yml.example
index 1c16b999e55..7fe85f0e0d7 100644
--- a/config/gitlab.yml.example
+++ b/config/gitlab.yml.example
@@ -612,7 +612,7 @@ production: &base
storages: # You must have at least a `default` storage path.
default:
path: /home/git/repositories/
- gitaly_address: unix:/home/git/gitlab/tmp/sockets/private/gitaly.socket # TCP connections are supported too (e.g. tcp://host:port)
+ gitaly_address: unix:/home/git/gitlab/tmp/sockets/private/gitaly.socket # TCP connections are supported too (e.g. tcp://host:port). TLS connections are also supported using the system certificate pool (eg: tls://host:port).
# gitaly_token: 'special token' # Optional: override global gitaly.token for this storage.
## Backup settings
diff --git a/config/initializers/8_metrics.rb b/config/initializers/zz_metrics.rb
index 468f80939d7..462e8c811a6 100644
--- a/config/initializers/8_metrics.rb
+++ b/config/initializers/zz_metrics.rb
@@ -1,3 +1,6 @@
+# This file was prefixed with zz_ because we want to load it the last!
+# See: https://gitlab.com/gitlab-org/gitlab-ce/issues/55611
+
# Autoload all classes that we want to instrument, and instrument the methods we
# need. This takes the Gitlab::Metrics::Instrumentation module as an argument so
# that we can stub it for testing, as it is only called when metrics are
diff --git a/danger/documentation/Dangerfile b/danger/documentation/Dangerfile
index be7b301866d..52af837c261 100644
--- a/danger/documentation/Dangerfile
+++ b/danger/documentation/Dangerfile
@@ -32,7 +32,7 @@ to be reviewed.
| Tech writer | Stage(s) |
| ------------ | ------------------------------------------------------------ |
| `@marcia` | ~Create ~Release + ~"development guidelines" |
-| `@axil` | ~Distribution ~Gitaly ~Gitter ~Monitoring ~Packaging ~Secure |
+| `@axil` | ~Distribution ~Gitaly ~Gitter ~Monitoring ~Package ~Secure |
| `@eread` | ~Manage ~Configure ~Geo ~Verify |
| `@mikelewis` | ~Plan |
diff --git a/db/fixtures/development/24_forks.rb b/db/fixtures/development/24_forks.rb
index 61e39c871e6..5eb5956ec74 100644
--- a/db/fixtures/development/24_forks.rb
+++ b/db/fixtures/development/24_forks.rb
@@ -4,6 +4,12 @@ Sidekiq::Testing.inline! do
Gitlab::Seeder.quiet do
User.all.sample(10).each do |user|
source_project = Project.public_only.sample
+
+ ##
+ # 04_project.rb might not have created a public project because
+ # we use randomized approach (e.g. `Array#sample`).
+ return unless source_project
+
fork_project = Projects::ForkService.new(source_project, user, namespace: user.namespace).execute
if fork_project.valid?
diff --git a/db/migrate/20181006004100_import_common_metrics_nginx_vts.rb b/db/migrate/20181006004100_import_common_metrics_nginx_vts.rb
index 98fafed7912..5cd312837df 100644
--- a/db/migrate/20181006004100_import_common_metrics_nginx_vts.rb
+++ b/db/migrate/20181006004100_import_common_metrics_nginx_vts.rb
@@ -1,4 +1,4 @@
-class ImportCommonMetricsNginxVts < ActiveRecord::Migration
+class ImportCommonMetricsNginxVts < ActiveRecord::Migration[5.0]
include Gitlab::Database::MigrationHelpers
require Rails.root.join('db/importers/common_metrics_importer.rb')
diff --git a/db/migrate/20181031145139_add_protected_ci_variables_to_application_settings.rb b/db/migrate/20181031145139_add_protected_ci_variables_to_application_settings.rb
new file mode 100644
index 00000000000..85ee34afe1e
--- /dev/null
+++ b/db/migrate/20181031145139_add_protected_ci_variables_to_application_settings.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+class AddProtectedCiVariablesToApplicationSettings < ActiveRecord::Migration[5.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ add_column_with_default(:application_settings, :protected_ci_variables, :boolean, default: false, allow_null: false)
+ end
+
+ def down
+ remove_column(:application_settings, :protected_ci_variables)
+ end
+end
diff --git a/db/post_migrate/20181219145520_migrate_cluster_configure_worker_sidekiq_queue.rb b/db/post_migrate/20181219145520_migrate_cluster_configure_worker_sidekiq_queue.rb
new file mode 100644
index 00000000000..c37f8c039c0
--- /dev/null
+++ b/db/post_migrate/20181219145520_migrate_cluster_configure_worker_sidekiq_queue.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+class MigrateClusterConfigureWorkerSidekiqQueue < ActiveRecord::Migration[5.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def up
+ sidekiq_queue_migrate 'gcp_cluster:cluster_platform_configure', to: 'gcp_cluster:cluster_configure'
+ end
+
+ def down
+ sidekiq_queue_migrate 'gcp_cluster:cluster_configure', to: 'gcp_cluster:cluster_platform_configure'
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 604ed1cd6b0..0af185409a9 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
-ActiveRecord::Schema.define(version: 20181218192239) do
+ActiveRecord::Schema.define(version: 20181219145520) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
@@ -166,6 +166,7 @@ ActiveRecord::Schema.define(version: 20181218192239) do
t.integer "diff_max_patch_bytes", default: 102400, null: false
t.integer "archive_builds_in_seconds"
t.string "commit_email_hostname"
+ t.boolean "protected_ci_variables", default: false, null: false
t.string "runners_registration_token_encrypted"
t.index ["usage_stats_set_by_user_id"], name: "index_application_settings_on_usage_stats_set_by_user_id", using: :btree
end
diff --git a/doc/administration/gitaly/index.md b/doc/administration/gitaly/index.md
index dc6a71e2ebd..cf37eaa0b61 100644
--- a/doc/administration/gitaly/index.md
+++ b/doc/administration/gitaly/index.md
@@ -1,6 +1,6 @@
# Gitaly
-[Gitaly](https://gitlab.com/gitlab-org/gitaly) is the service that
+[Gitaly](https://gitlab.com/gitlab-org/gitaly) is the service that
provides high-level RPC access to Git repositories. Without it, no other
components can read or write Git data.
@@ -23,7 +23,7 @@ gitaly['prometheus_listen_addr'] = 'localhost:9236'
```
To change a Gitaly setting in installations from source you can edit
-`/home/git/gitaly/config.toml`. Changes will be applied when you run
+`/home/git/gitaly/config.toml`. Changes will be applied when you run
`service gitlab restart`.
```toml
@@ -91,13 +91,13 @@ documentation on configuring Gitaly
authentication](https://gitlab.com/gitlab-org/gitaly/blob/master/doc/configuration/README.md#authentication)
.
-Gitaly must trigger some callbacks to GitLab via GitLab Shell. As a result,
+Gitaly must trigger some callbacks to GitLab via GitLab Shell. As a result,
the GitLab Shell secret must be the same between the other GitLab servers and
the Gitaly server. The easiest way to accomplish this is to copy `/etc/gitlab/gitlab-secrets.json`
from an existing GitLab server to the Gitaly server. Without this shared secret,
-Git operations in GitLab will result in an API error.
+Git operations in GitLab will result in an API error.
-> **NOTE:** In most or all cases the storage paths below end in `/repositories` which is
+> **NOTE:** In most or all cases the storage paths below end in `/repositories` which is
different than `path` in `git_data_dirs` of Omnibus installations. Check the
directory layout on your Gitaly server to be sure.
@@ -133,6 +133,11 @@ gitaly['storage'] = [
{ 'name' => 'default', 'path' => '/mnt/gitlab/default/repositories' },
{ 'name' => 'storage1', 'path' => '/mnt/gitlab/storage1/repositories' },
]
+
+# To use tls for gitaly you need to add
+gitaly['tls_listen_addr'] = "0.0.0.0:9999"
+gitaly['certificate_path'] = "path/to/cert.pem"
+gitaly['key_path'] = "path/to/key.pem"
```
Source installations:
@@ -140,6 +145,11 @@ Source installations:
```toml
# /home/git/gitaly/config.toml
listen_addr = '0.0.0.0:8075'
+tls_listen_addr = '0.0.0.0:9999'
+
+[tls]
+certificate_path = /path/to/cert.pem
+key_path = /path/to/key.pem
[auth]
token = 'abc123secret'
@@ -205,6 +215,70 @@ Gitaly logs on your Gitaly server (`sudo gitlab-ctl tail gitaly` or
coming in. One sure way to trigger a Gitaly request is to clone a
repository from your GitLab server over HTTP.
+## TLS support
+
+Gitaly supports TLS credentials for GRPC authentication. To be able to communicate
+with a gitaly instance that listens for secure connections you will need to use `tls://` url
+scheme in the `gitaly_address` of the corresponding storage entry in the gitlab configuration.
+
+The admin needs to bring their own certificate as we do not provide that automatically.
+The certificate to be used needs to be installed on all gitaly nodes and on all client nodes that communicate with it following procedures described in [GitLab custom certificate configuration](https://docs.gitlab.com/omnibus/settings/ssl.html#install-custom-public-certificates)
+
+### Example TLS configuration
+
+### Omnibus installations:
+
+#### On client nodes:
+
+```ruby
+# /etc/gitlab/gitlab.rb
+git_data_dirs({
+ 'default' => { 'path' => '/mnt/gitlab/default', 'gitaly_address' => 'tls://gitaly.internal:9999' },
+ 'storage1' => { 'path' => '/mnt/gitlab/storage1', 'gitaly_address' => 'tls://gitaly.internal:9999' },
+})
+
+gitlab_rails['gitaly_token'] = 'abc123secret'
+```
+
+#### On gitaly server nodes:
+
+```ruby
+gitaly['tls_listen_addr'] = "0.0.0.0:9999"
+gitaly['certificate_path'] = "path/to/cert.pem"
+gitaly['key_path'] = "path/to/key.pem"
+```
+
+### Source installations:
+
+#### On client nodes:
+
+```yaml
+# /home/git/gitlab/config/gitlab.yml
+gitlab:
+ repositories:
+ storages:
+ default:
+ path: /mnt/gitlab/default/repositories
+ gitaly_address: tls://gitaly.internal:9999
+ storage1:
+ path: /mnt/gitlab/storage1/repositories
+ gitaly_address: tls://gitaly.internal:9999
+
+ gitaly:
+ token: 'abc123secret'
+```
+
+#### On gitaly server nodes:
+
+```toml
+# /home/git/gitaly/config.toml
+tls_listen_addr = '0.0.0.0:9999'
+
+[tls]
+certificate_path = '/path/to/cert.pem'
+key_path = '/path/to/key.pem'
+```
+
## Disabling or enabling the Gitaly service in a cluster environment
If you are running Gitaly [as a remote
diff --git a/doc/administration/index.md b/doc/administration/index.md
index 6083806af6c..89132cd95f0 100644
--- a/doc/administration/index.md
+++ b/doc/administration/index.md
@@ -95,6 +95,7 @@ created in snippets, wikis, and repos.
- [Postfix for incoming email](reply_by_email_postfix_setup.md): Set up a
basic Postfix mail server with IMAP authentication on Ubuntu for incoming
emails.
+- [Abuse reports](../user/admin_area/abuse_reports.md): View and resolve abuse reports from your users.
[reply by email]: reply_by_email.md
[issues by email]: ../user/project/issues/create_new_issue.md#new-issue-via-email
diff --git a/doc/api/jobs.md b/doc/api/jobs.md
index 589c48ee08d..d2dd9c676e3 100644
--- a/doc/api/jobs.md
+++ b/doc/api/jobs.md
@@ -8,12 +8,12 @@ Get a list of jobs in a project.
GET /projects/:id/jobs
```
-| Attribute | Type | Required | Description |
-|-----------|---------|----------|---------------------|
-| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
-| `scope` | string **or** array of strings | no | The scope of jobs to show, one or array of: `created`, `pending`, `running`, `failed`, `success`, `canceled`, `skipped`, `manual`; showing all jobs if none provided |
+| Attribute | Type | Required | Description |
+|-----------|--------------------------------|----------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user. |
+| `scope` | string **or** array of strings | no | Scope of jobs to show. Either one of or an array of the following: `created`, `pending`, `running`, `failed`, `success`, `canceled`, `skipped`, or `manual`. All jobs are returned if `scope` is not provided. |
-```
+```sh
curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" 'https://gitlab.example.com/api/v4/projects/1/jobs?scope[]=pending&scope[]=running'
```
@@ -140,13 +140,13 @@ Get a list of jobs for a pipeline.
GET /projects/:id/pipelines/:pipeline_id/jobs
```
-| Attribute | Type | Required | Description |
-|---------------|--------------------------------|----------|----------------------|
-| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
-| `pipeline_id` | integer | yes | The ID of a pipeline |
-| `scope` | string **or** array of strings | no | The scope of jobs to show, one or array of: `created`, `pending`, `running`, `failed`, `success`, `canceled`, `skipped`, `manual`; showing all jobs if none provided |
+| Attribute | Type | Required | Description |
+|---------------|--------------------------------|----------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user. |
+| `pipeline_id` | integer | yes | The ID of a pipeline. |
+| `scope` | string **or** array of strings | no | Scope of jobs to show. Either one of or an array of the following: `created`, `pending`, `running`, `failed`, `success`, `canceled`, `skipped`, or `manual`. All jobs are returned if `scope` is not provided. |
-```
+```sh
curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" 'https://gitlab.example.com/api/v4/projects/1/pipelines/6/jobs?scope[]=pending&scope[]=running'
```
@@ -273,12 +273,12 @@ Get a single job of a project
GET /projects/:id/jobs/:job_id
```
-| Attribute | Type | Required | Description |
-|------------|---------|----------|---------------------|
-| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
-| `job_id` | integer | yes | The ID of a job |
+| Attribute | Type | Required | Description |
+|-----------|----------------|----------|------------------------------------------------------------------------------------------------------------------|
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user. |
+| `job_id` | integer | yes | The ID of a job. |
-```
+```sh
curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/1/jobs/8"
```
@@ -348,18 +348,18 @@ Get job artifacts of a project.
GET /projects/:id/jobs/:job_id/artifacts
```
-| Attribute | Type | Required | Description |
-|------------|---------|----------|---------------------|
-| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
-| `job_id` | integer | yes | The ID of a job |
+| Attribute | Type | Required | Description |
+|-----------|----------------|----------|------------------------------------------------------------------------------------------------------------------|
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user. |
+| `job_id` | integer | yes | The ID of a job. |
Example requests:
-```
+```sh
curl --location --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/1/jobs/8/artifacts"
```
-Response:
+Possible response status codes:
| Status | Description |
|-----------|---------------------------------|
@@ -383,19 +383,19 @@ GET /projects/:id/jobs/artifacts/:ref_name/download?job=name
Parameters
-| Attribute | Type | Required | Description |
-|-------------|---------|----------|-------------------------- |
-| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
-| `ref_name` | string | yes | The ref from a repository (can only be branch or tag name, not HEAD or SHA) |
-| `job` | string | yes | The name of the job |
+| Attribute | Type | Required | Description |
+|------------|----------------|----------|------------------------------------------------------------------------------------------------------------------|
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user. |
+| `ref_name` | string | yes | Branch or tag name in repository. HEAD or SHA references are not supported. |
+| `job` | string | yes | The name of the job. |
Example requests:
-```
+```sh
curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/1/jobs/artifacts/master/download?job=test"
```
-Example response:
+Possible response status codes:
| Status | Description |
|-----------|---------------------------------|
@@ -408,9 +408,9 @@ Example response:
> Introduced in GitLab 10.0
-Download a single artifact file from within the job's artifacts archive.
-
-Only a single file is going to be extracted from the archive and streamed to a client.
+Download a single artifact file from a job with a specified ID from within
+the job's artifacts archive. The file is extracted from the archive and
+streamed to the client.
```
GET /projects/:id/jobs/:job_id/artifacts/*artifact_path
@@ -418,19 +418,19 @@ GET /projects/:id/jobs/:job_id/artifacts/*artifact_path
Parameters
-| Attribute | Type | Required | Description |
-|-----------------|---------|----------|-------------------------- |
-| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
-| `job_id ` | integer | yes | The unique job identifier |
-| `artifact_path` | string | yes | Path to a file inside the artifacts archive |
+| Attribute | Type | Required | Description |
+|-----------------|----------------|----------|------------------------------------------------------------------------------------------------------------------|
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user. |
+| `job_id ` | integer | yes | The unique job identifier. |
+| `artifact_path` | string | yes | Path to a file inside the artifacts archive. |
Example request:
-```
+```sh
curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/1/jobs/5/artifacts/some/release/file.pdf"
```
-Example response:
+Possible response status codes:
| Status | Description |
|-----------|--------------------------------------|
@@ -481,16 +481,16 @@ Get a trace of a specific job of a project
GET /projects/:id/jobs/:job_id/trace
```
-| Attribute | Type | Required | Description |
-|------------|---------|----------|---------------------|
-| id | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
-| job_id | integer | yes | The ID of a job |
+| Attribute | Type | Required | Description |
+|-----------|----------------|----------|------------------------------------------------------------------------------------------------------------------|
+| id | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user. |
+| job_id | integer | yes | The ID of a job. |
-```
+```sh
curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/1/jobs/8/trace"
```
-Response:
+Possible response status codes:
| Status | Description |
|-----------|-----------------------------------|
@@ -505,12 +505,12 @@ Cancel a single job of a project
POST /projects/:id/jobs/:job_id/cancel
```
-| Attribute | Type | Required | Description |
-|------------|---------|----------|---------------------|
-| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
-| `job_id` | integer | yes | The ID of a job |
+| Attribute | Type | Required | Description |
+|-----------|----------------|----------|------------------------------------------------------------------------------------------------------------------|
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user. |
+| `job_id` | integer | yes | The ID of a job. |
-```
+```sh
curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/1/jobs/1/cancel"
```
@@ -553,12 +553,12 @@ Retry a single job of a project
POST /projects/:id/jobs/:job_id/retry
```
-| Attribute | Type | Required | Description |
-|------------|---------|----------|---------------------|
-| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
-| `job_id` | integer | yes | The ID of a job |
+| Attribute | Type | Required | Description |
+|-----------|----------------|----------|------------------------------------------------------------------------------------------------------------------|
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user. |
+| `job_id` | integer | yes | The ID of a job. |
-```
+```sh
curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/1/jobs/1/retry"
```
@@ -603,14 +603,14 @@ POST /projects/:id/jobs/:job_id/erase
Parameters
-| Attribute | Type | Required | Description |
-|-------------|---------|----------|---------------------|
-| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
-| `job_id` | integer | yes | The ID of a job |
+| Attribute | Type | Required | Description |
+|-----------|----------------|----------|------------------------------------------------------------------------------------------------------------------|
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user. |
+| `job_id` | integer | yes | The ID of a job. |
Example of request
-```
+```sh
curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/1/jobs/1/erase"
```
@@ -656,14 +656,14 @@ POST /projects/:id/jobs/:job_id/artifacts/keep
Parameters
-| Attribute | Type | Required | Description |
-|-------------|---------|----------|---------------------|
-| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
-| `job_id` | integer | yes | The ID of a job |
+| Attribute | Type | Required | Description |
+|-----------|----------------|----------|------------------------------------------------------------------------------------------------------------------|
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user. |
+| `job_id` | integer | yes | The ID of a job. |
Example request:
-```
+```sh
curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/1/jobs/1/artifacts/keep"
```
@@ -707,12 +707,12 @@ Triggers a manual action to start a job.
POST /projects/:id/jobs/:job_id/play
```
-| Attribute | Type | Required | Description |
-|-----------|---------|----------|---------------------|
-| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
-| `job_id` | integer | yes | The ID of a job |
+| Attribute | Type | Required | Description |
+|-----------|----------------|----------|------------------------------------------------------------------------------------------------------------------|
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user. |
+| `job_id` | integer | yes | The ID of a job. |
-```
+```sh
curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/1/jobs/1/play"
```
diff --git a/doc/ci/examples/devops_and_game_dev_with_gitlab_ci_cd/index.md b/doc/ci/examples/devops_and_game_dev_with_gitlab_ci_cd/index.md
index cae051daa56..1e2be2e8475 100644
--- a/doc/ci/examples/devops_and_game_dev_with_gitlab_ci_cd/index.md
+++ b/doc/ci/examples/devops_and_game_dev_with_gitlab_ci_cd/index.md
@@ -254,7 +254,7 @@ To ensure our changes don't break the build and all tests still pass, we utilize
Continuous Integration (CI) to run these checks automatically for every push.
Read through this article to understand [Continuous Integration, Continuous Delivery, and Continuous Deployment](https://about.gitlab.com/2016/08/05/continuous-integration-delivery-and-deployment-with-gitlab/),
and how these methods are leveraged by GitLab.
-From the [last tutorial](https://ryanhallcs.wordpress.com/2017/03/15/devops-and-game-dev/) we already have a `gitlab-ci.yml` file set up for building our app from
+From the [last tutorial](https://ryanhallcs.wordpress.com/2017/03/15/devops-and-game-dev/) we already have a `.gitlab-ci.yml` file set up for building our app from
every push. We need to set up a new CI job for testing, which GitLab CI/CD will run after the build job using our generated artifacts from gulp.
Please read through the [documentation on CI/CD configuration](../../../ci/yaml/README.md) file to explore its contents and adjust it to your needs.
diff --git a/doc/ci/merge_request_pipelines/index.md b/doc/ci/merge_request_pipelines/index.md
index 706e83abf44..bf1e61442d4 100644
--- a/doc/ci/merge_request_pipelines/index.md
+++ b/doc/ci/merge_request_pipelines/index.md
@@ -1,11 +1,12 @@
# Pipelines for merge requests
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/issues/15310) in GitLab 11.6
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/issues/15310) in GitLab 11.6.
-Usually, when a developer creates a new merge request, a pipeline runs on the
+Usually, when you create a new merge request, a pipeline runs on the
new change and checks if it's qualified to be merged into a target branch. This
pipeline should contain only necessary jobs for checking the new changes.
-For example, unit tests, lint checks, and Review Apps are often used in this cycle.
+For example, unit tests, lint checks, and [Review Apps](../review_apps/index.md)
+are often used in this cycle.
With pipelines for merge requests, you can design a specific pipeline structure
for merge requests. All you need to do is just adding `only: [merge_requests]` to
@@ -14,10 +15,10 @@ Every time, when developers create or update merge requests, a pipeline runs on
their new commits at every push to GitLab.
NOTE: **Note**:
-If you use both this feature and the [Merge When Pipeline Succeeds](../../user/project/merge_requests/merge_when_pipeline_succeeds.md)
-feature, pipelines for merge requests take precendence over the other regular pipelines.
+If you use both this feature and [Merge When Pipeline Succeeds](../../user/project/merge_requests/merge_when_pipeline_succeeds.md),
+pipelines for merge requests take precedence over the other regular pipelines.
-For example, consider a GitLab CI/CD configuration in .gitlab-ci.yml as follows:
+For example, consider the following [`.gitlab-ci.yml`](../yaml/README.md):
```yaml
build:
@@ -39,20 +40,18 @@ deploy:
script: ./deploy
```
-After a developer updated code in a merge request with whatever methods (e.g. `git push`),
-GitLab detects that the code is updated and create a new pipeline for the merge request.
+After the merge request is updated with new commits, GitLab detects that changes
+have occurred and creates a new pipeline for the merge request.
The pipeline fetches the latest code from the source branch and run tests against it.
-In this example, the pipeline contains only `build` and `test` jobs.
-Since `deploy` job does not have the `only: [merge_requests]` rule,
+In the above example, the pipeline contains only `build` and `test` jobs.
+Since the `deploy` job doesn't have the `only: [merge_requests]` rule,
deployment jobs will not happen in the merge request.
-Consider this pipeline list viewed from the **Pipelines** tab in a merge request:
+Pipelines tagged as **merge request** indicate that they were triggered
+when a merge request was created or updated.
![Merge request page](img/merge_request.png)
-Note that pipelines tagged as **merge request** indicate that they were triggered
-when a merge request was created or updated.
-
The same tag is shown on the pipeline's details:
![Pipeline's details](img/pipeline_detail.png)
@@ -66,7 +65,7 @@ flow, external contributors follow the following steps:
1. Create a merge request from the forked project that targets the `master` branch
in the parent project.
1. A pipeline runs on the merge request.
-1. A mainatiner from the parent project checks the pipeline result, and merge
+1. A maintainer from the parent project checks the pipeline result, and merge
into a target branch if the latest pipeline has passed.
Currently, those pipelines are created in a **forked** project, not in the
@@ -77,7 +76,7 @@ by tweaking their GitLab Runner in the forked project.
There are multiple reasons about why GitLab doesn't allow those pipelines to be
created in the parent project, but one of the biggest reasons is security concern.
External users could steal secret variables from the parent project by modifying
-.gitlab-ci.yml, which could be some sort of credentials. This should not happen.
+`.gitlab-ci.yml`, which could be some sort of credentials. This should not happen.
We're discussing a secure solution of running pipelines for merge requests
that submitted from forked projects,
diff --git a/doc/ci/yaml/README.md b/doc/ci/yaml/README.md
index 4df5d8fb54a..440254e58bd 100644
--- a/doc/ci/yaml/README.md
+++ b/doc/ci/yaml/README.md
@@ -584,15 +584,17 @@ osx job:
## `allow_failure`
-`allow_failure` is used when you want to allow a job to fail without impacting
-the rest of the CI suite. Failed jobs don't contribute to the commit status.
+`allow_failure` allows a job to fail without impacting the rest of the CI
+suite.
The default value is `false`, except for [manual](#whenmanual) jobs.
-When enabled and the job fails, the pipeline will be successful/green for all
-intents and purposes, but a "CI build passed with warnings" message will be
-displayed on the merge request or commit or job page. This is to be used by
-jobs that are allowed to fail, but where failure indicates some other (manual)
-steps should be taken elsewhere.
+When enabled and the job fails, the job will show an orange warning in the UI.
+However, the logical flow of the pipeline will consider the job a
+success/passed, and is not blocked.
+
+Assuming all other jobs are successful, the job's stage and its pipeline will
+show the same orange warning. However, the associated commit will be marked
+"passed", without warnings.
In the example below, `job1` and `job2` will run in parallel, but if `job1`
fails, it will not stop the next stage from running, since it's marked with
@@ -624,7 +626,8 @@ failure.
`when` can be set to one of the following values:
1. `on_success` - execute job only when all jobs from prior stages
- succeed. This is the default.
+ succeed (or are considered succeeding because they are marked
+ `allow_failure`). This is the default.
1. `on_failure` - execute job only when at least one job from prior stages
fails.
1. `always` - execute job regardless of the status of jobs from prior stages.
diff --git a/doc/development/contributing/merge_request_workflow.md b/doc/development/contributing/merge_request_workflow.md
index 5b32b5cd46f..6bcee74a3dd 100644
--- a/doc/development/contributing/merge_request_workflow.md
+++ b/doc/development/contributing/merge_request_workflow.md
@@ -179,7 +179,6 @@ merge request:
1. Note the addition in the release blog post (create one if it doesn't exist yet) https://gitlab.com/gitlab-com/www-gitlab-com/merge_requests/
1. Upgrade guide, for example https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/update/7.5-to-7.6.md
-1. Upgrader https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/update/upgrader.md#2-run-gitlab-upgrade-tool
1. Installation guide https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/install/installation.md#1-packages-dependencies
1. GitLab Development Kit https://gitlab.com/gitlab-org/gitlab-development-kit
1. Test suite https://gitlab.com/gitlab-org/gitlab-ce/blob/master/scripts/prepare_build.sh
diff --git a/doc/development/instrumentation.md b/doc/development/instrumentation.md
index bef166f2aec..a36dc6424a7 100644
--- a/doc/development/instrumentation.md
+++ b/doc/development/instrumentation.md
@@ -35,7 +35,7 @@ Using this method is in general preferred over directly calling the various
instrumentation methods.
Method instrumentation should be added in the initializer
-`config/initializers/8_metrics.rb`.
+`config/initializers/zz_metrics.rb`.
### Examples
diff --git a/doc/install/kubernetes/gitlab_chart.md b/doc/install/kubernetes/gitlab_chart.md
index 74e2598f860..26ced45de7b 100644
--- a/doc/install/kubernetes/gitlab_chart.md
+++ b/doc/install/kubernetes/gitlab_chart.md
@@ -47,8 +47,9 @@ In order to deploy GitLab on Kubernetes, the following are required:
1. `helm` and `kubectl` [installed on your computer](preparation/tools_installation.md).
1. A Kubernetes cluster, version 1.8 or higher. 6vCPU and 16GB of RAM is recommended.
- - [Google GKE](https://cloud.google.com/kubernetes-engine/docs/how-to/creating-a-container-cluster)
- [Amazon EKS](https://docs.aws.amazon.com/eks/latest/userguide/getting-started.html)
+ - [Google GKE](https://cloud.google.com/kubernetes-engine/docs/how-to/creating-a-container-cluster)
+ - [IBM IKS](https://console.bluemix.net/docs/tutorials/scalable-webapp-kubernetes.html#create_kube_cluster)
- [Microsoft AKS](https://docs.microsoft.com/en-us/azure/aks/kubernetes-walkthrough-portal)
1. A [wildcard DNS entry and external IP address](preparation/networking.md)
1. [Authenticate and connect](preparation/connect.md) to the cluster
diff --git a/doc/ssh/README.md b/doc/ssh/README.md
index d9ae3c08172..e570627bfc1 100644
--- a/doc/ssh/README.md
+++ b/doc/ssh/README.md
@@ -185,7 +185,26 @@ your terminal (replacing `gitlab.com` with your GitLab's instance domain):
ssh -T git@gitlab.com
```
-You should receive a _Welcome to GitLab, `@username`!_ message.
+The first time you connect to GitLab via SSH, you will be asked to verify the
+authenticity of the GitLab host you are connecting to.
+For example, when connecting to GitLab.com, answer `yes` to add GitLab.com to
+the list of trusted hosts:
+
+```
+The authenticity of host 'gitlab.com (35.231.145.151)' can't be established.
+ECDSA key fingerprint is SHA256:HbW3g8zUjNSksFbqTiUWPWg2Bq1x8xdGUrliXFzSnUw.
+Are you sure you want to continue connecting (yes/no)? yes
+Warning: Permanently added 'gitlab.com' (ECDSA) to the list of known hosts.
+```
+
+NOTE: **Note:**
+For GitLab.com, consult the
+[SSH host keys fingerprints](../user/gitlab_com/index.md#ssh-host-keys-fingerprints),
+to make sure you're connecting to the correct server.
+
+Once added to the list of known hosts, you won't be asked to validate the
+authenticity of GitLab's host again. Run the above command once more, and
+you should only receive a _Welcome to GitLab, `@username`!_ message.
If the welcome message doesn't appear, run SSH's verbose mode by replacing `-T`
with `-vvvT` to understand where the error is.
diff --git a/doc/update/upgrader.md b/doc/update/upgrader.md
deleted file mode 100644
index 746d6bf93e7..00000000000
--- a/doc/update/upgrader.md
+++ /dev/null
@@ -1,91 +0,0 @@
----
-comments: false
----
-
-# GitLab Upgrader (deprecated)
-
-*DEPRECATED* We recommend to [switch to the Omnibus package and repository server](https://about.gitlab.com/update/) instead of using this script.
-
-Although deprecated, if someone wants to make this script into a gem or otherwise improve it merge requests are welcome.
-
-*Make sure you view this [upgrade guide from the 'master' branch](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/update/upgrader.md) for the most up to date instructions.*
-
-GitLab Upgrader - a ruby script that allows you easily upgrade GitLab to latest minor version.
-
-For example it can update your application from 6.4 to latest GitLab 6 version (like 6.6.1).
-
-You still need to create a backup and manually restart GitLab after running the script but all other operations are done by this upgrade script.
-
-If you have local changes to your GitLab repository the script will stash them and you need to use `git stash pop` after running the script.
-
-**GitLab Upgrader is available only for GitLab version 6.4.2 or higher.**
-
-**This script does NOT update gitlab-shell, it needs manual update. See step 5 below.**
-
-## 0. Backup
-
- cd /home/git/gitlab
- sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
-
-## 1. Stop server
-
- sudo service gitlab stop
-
-## 2. Run GitLab upgrade tool
-
-Please replace X.X.X with the [latest GitLab release](https://packages.gitlab.com/gitlab/gitlab-ce).
-
-GitLab 7.9 adds `nodejs` as a dependency. GitLab 7.6 adds `libkrb5-dev` as a dependency (installed by default on Ubuntu and OSX). GitLab 7.2 adds `pkg-config` and `cmake` as dependency. Please check the dependencies in the [installation guide.](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/install/installation.md#1-packages-dependencies)
-
- cd /home/git/gitlab
- sudo -u git -H ruby -Ilib -e 'require "gitlab/upgrader"' -e 'class Gitlab::Upgrader' -e 'def latest_version_raw' -e '"vX.X.X"' -e 'end' -e 'end' -e 'Gitlab::Upgrader.new.execute'
-
- # to perform a non-interactive install (no user input required) you can add -y
- # sudo -u git -H ruby -Ilib -e 'require "gitlab/upgrader"' -e 'class Gitlab::Upgrader' -e 'def latest_version_raw' -e '"vX.X.X"' -e 'end' -e 'end' -e 'Gitlab::Upgrader.new.execute' -- -y
-
-## 3. Start application
-
- sudo service gitlab start
- sudo service nginx restart
-
-## 4. Check application status
-
-Check if GitLab and its dependencies are configured correctly:
-
- sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
-
-If all items are green, then congratulations upgrade is complete!
-
-## 5. Upgrade GitLab Shell
-
-GitLab Shell might be outdated, running the commands below ensures you're using a compatible version:
-
-```
-cd /home/git/gitlab-shell
-sudo -u git -H git fetch
-sudo -u git -H git checkout v`cat /home/git/gitlab/GITLAB_SHELL_VERSION`
-sudo -u git -H sh -c 'if [ -x bin/compile ] ; then bin/compile ; fi'
-```
-
-## One line upgrade command
-
-You've read through the entire guide and probably already did all the steps one by one.
-
-Below is a one line command with step 1 to 5 for the next time you upgrade.
-
-Please replace X.X.X with the [latest GitLab release](https://packages.gitlab.com/gitlab/gitlab-ce).
-
-```bash
-cd /home/git/gitlab; \
- sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production; \
- sudo service gitlab stop; \
- sudo -u git -H ruby -Ilib -e 'require "gitlab/upgrader"' -e 'class Gitlab::Upgrader' -e 'def latest_version_raw' -e '"vX.X.X"' -e 'end' -e 'end' -e 'Gitlab::Upgrader.new.execute' -- -y; \
- cd /home/git/gitlab-shell; \
- sudo -u git -H git fetch; \
- sudo -u git -H git checkout v`cat /home/git/gitlab/GITLAB_SHELL_VERSION`; \
- sudo -u git -H sh -c 'if [ -x bin/compile ] ; then bin/compile ; fi'; \
- cd /home/git/gitlab; \
- sudo service gitlab start; \
- sudo service nginx restart; \
- sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
-``` \ No newline at end of file
diff --git a/doc/user/abuse_reports.md b/doc/user/abuse_reports.md
new file mode 100644
index 00000000000..1f4f598b121
--- /dev/null
+++ b/doc/user/abuse_reports.md
@@ -0,0 +1,53 @@
+# Abuse reports
+
+Report abuse from users to GitLab administrators.
+
+You can report a user through their:
+
+- [Profile](#reporting-abuse-through-a-users-profile)
+- [Comments](#reporting-abuse-through-a-users-comment)
+- [Issues and Merge requests](#reporting-abuse-through-a-users-issue-or-merge-request)
+
+## Reporting abuse through a user's profile
+
+To report abuse from a user's profile page:
+
+1. Click on the exclamation point report abuse button at the top right of the user's profile.
+1. Complete an abuse report.
+1. Click the **Send report** button.
+
+## Reporting abuse through a user's comment
+
+To report abuse from a user's comment:
+
+1. Click on the vertical ellipsis (⋮) more actions button to open the dropdown.
+1. Select **Report as abuse**.
+1. Complete an abuse report.
+1. Click the **Send report** button.
+
+
+NOTE: **Note:**
+A URL to the reported user's comment will be
+pre-filled in the abuse report's **Message** field.
+
+## Reporting abuse through a user's issue or merge request
+
+The **Report abuse** button is displayed at the top right of the issue or merge request:
+
+- When **Report abuse** is selected from the menu that appears when the **Close issue** or **Close merge request** button is clicked, for users that have permission to close the issue or merge request.
+- When viewing the issue or merge request, for users that don't have permission to close the issue or merge request.
+
+With the **Report abuse** button displayed, to submit an abuse report:
+
+1. Click the **Report abuse** button.
+1. Submit an abuse report.
+1. Click the **Send report** button.
+
+NOTE: **Note:**
+A URL to the reported user's issue or merge request will be pre-filled
+in the abuse report's **Message** field.
+
+## Managing abuse reports
+
+Admins are able to view and resolve abuse reports.
+For more information, see [abuse reports administration documentation](admin_area/abuse_reports.md).
diff --git a/doc/user/admin_area/abuse_reports.md b/doc/user/admin_area/abuse_reports.md
new file mode 100644
index 00000000000..01c2d9607f5
--- /dev/null
+++ b/doc/user/admin_area/abuse_reports.md
@@ -0,0 +1,31 @@
+# Abuse reports
+
+View and resolve abuse reports from GitLab users.
+
+Admins can view abuse reports in the admin area and are able to
+resolve the reports by removing the reported user, blocking the reported user, or removing the report.
+
+## Reporting abuse
+
+To find out more about reporting abuse, see [abuse reports user documentation](../abuse_reports.md).
+
+## Resolving abuse reports
+
+To access abuse reports, go to **Admin area > Abuse Reports**.
+
+There are 3 ways to resolve an abuse report, with a button for each method:
+
+- Remove user & report: [Deletes the reported user](../profile/account/delete_account.md) from the instance and removes the abuse report from the list.
+- Block user: Blocks the reported user from the instance and does not remove the abuse report from the list.
+- Remove report: Removes the abuse report from the list and does not restrict the access for the reported user.
+
+![abuse-reports-page-image](img/abuse_reports_page.png)
+
+## Blocked users
+
+Blocking a user will not remove the abuse report from the list.
+
+Instead, the block button will be disabled and explain that the user is "Already blocked".
+You are still able to remove the user and/or report if necessary.
+
+![abuse-report-blocked-user-image](img/abuse_report_blocked_user.png)
diff --git a/doc/user/admin_area/img/abuse_report_blocked_user.png b/doc/user/admin_area/img/abuse_report_blocked_user.png
new file mode 100644
index 00000000000..0cb4c7bb8ac
--- /dev/null
+++ b/doc/user/admin_area/img/abuse_report_blocked_user.png
Binary files differ
diff --git a/doc/user/admin_area/img/abuse_reports_page.png b/doc/user/admin_area/img/abuse_reports_page.png
new file mode 100644
index 00000000000..81dbe976cda
--- /dev/null
+++ b/doc/user/admin_area/img/abuse_reports_page.png
Binary files differ
diff --git a/doc/user/group/clusters/index.md b/doc/user/group/clusters/index.md
index 8e03d116b81..9f9b2da23e1 100644
--- a/doc/user/group/clusters/index.md
+++ b/doc/user/group/clusters/index.md
@@ -1,9 +1,7 @@
# Group-level Kubernetes clusters
> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/issues/34758) in GitLab 11.6.
-
-CAUTION: **Warning:**
-Group Cluster integration is currently in **Beta**.
+> Group Cluster integration is currently in [Beta](https://about.gitlab.com/handbook/product/#alpha-beta-ga).
## Overview
diff --git a/doc/user/index.md b/doc/user/index.md
index 08995032cb1..fc68404d0c2 100644
--- a/doc/user/index.md
+++ b/doc/user/index.md
@@ -113,6 +113,7 @@ methods available in GitLab.
user type (guest, reporter, developer, maintainer, owner).
- [Feature highlight](feature_highlight.md): Learn more about the little blue dots
around the app that explain certain features
+- [Abuse reports](abuse_reports.md): Report abuse from users to GitLab administrators
## Groups
diff --git a/doc/user/profile/account/delete_account.md b/doc/user/profile/account/delete_account.md
index 49f0ce2cd79..b497cc414af 100644
--- a/doc/user/profile/account/delete_account.md
+++ b/doc/user/profile/account/delete_account.md
@@ -25,7 +25,7 @@ Here's a list of things that will not be deleted:
Instead of being deleted, these records will be moved to a system-wide
"Ghost User", whose sole purpose is to act as a container for such records.
-When a user is deleted from an abuse report or spam log, these associated
+When a user is deleted from an [abuse report](../../admin_area/abuse_reports.md) or spam log, these associated
records are not ghosted and will be removed, along with any groups the user
is a sole owner of. Administrators can also request this behaviour when
deleting users from the [API](../../../api/users.md#user-deletion) or the
@@ -35,4 +35,3 @@ admin area.
[ce-10273]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/10273
[ce-10467]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/10467
[ce-11853]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/11853
-
diff --git a/doc/user/project/clusters/index.md b/doc/user/project/clusters/index.md
index db48388e90d..6bdafc60949 100644
--- a/doc/user/project/clusters/index.md
+++ b/doc/user/project/clusters/index.md
@@ -254,15 +254,19 @@ install it manually.
GitLab provides a one-click install for various applications which can
be added directly to your configured cluster. Those applications are
needed for [Review Apps](../../../ci/review_apps/index.md) and
-[deployments](../../../ci/environments.md).
+[deployments](../../../ci/environments.md). You can install them after you
+[create a cluster](#adding-and-creating-a-new-gke-cluster-via-gitlab).
+
+To see a list of available applications to install:
+
+1. Navigate to your project's **Operations > Kubernetes**.
+1. Select your cluster.
+
+Install Helm Tiller first because it's used to install other applications.
NOTE: **Note:**
-With the exception of Knative, the applications will be installed in a dedicated namespace called
-`gitlab-managed-apps`. In case you have added an existing Kubernetes cluster
-with Tiller already installed, you should be careful as GitLab cannot
-detect it. In this event, installing Tiller via the applications will
-result in the cluster having it twice. This can lead to confusion during
-deployments.
+As of GitLab 11.6, Helm Tiller will be upgraded to the latest version supported
+by GitLab before installing any of the applications.
| Application | GitLab version | Description | Helm Chart |
| ----------- | :------------: | ----------- | --------------- |
@@ -274,9 +278,14 @@ deployments.
| [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 a [custom Jupyter image](https://gitlab.com/gitlab-org/jupyterhub-user-image/blob/master/Dockerfile) that installs additional useful packages on top of the base Jupyter. You will also see ready-to-use DevOps Runbooks built with Nurtch's [Rubix library](https://github.com/amit1rrr/rubix). More information on creating executable runbooks can be found in [our Nurtch documentation](runbooks/index.md#nurtch-executable-runbooks). **Note**: Authentication will be enabled for any user of the GitLab server via OAuth2. HTTPS will be supported in a future release. | [jupyter/jupyterhub](https://jupyterhub.github.io/helm-chart/) |
| [Knative](https://cloud.google.com/knative) | 11.5+ | Knative provides a platform to create, deploy, and manage serverless workloads from a Kubernetes cluster. It is used in conjunction with, and includes [Istio](https://istio.io) to provide an external IP address for all programs hosted by Knative. You will be prompted to enter a wildcard domain where your applications will be exposed. Configure your DNS server to use the external IP address for that domain. For any application created and installed, they will be accessible as `<program_name>.<kubernetes_namespace>.<domain_name>`. This will require your kubernetes cluster to have [RBAC enabled](#role-based-access-control-rbac). | [knative/knative](https://storage.googleapis.com/triggermesh-charts)
-NOTE: **Note:**
-As of GitLab 11.6 Helm Tiller will be upgraded to the latest version supported
-by GitLab before installing any of the above applications.
+With the exception of Knative, the applications will be installed in a dedicated
+namespace called `gitlab-managed-apps`.
+
+CAUTION: **Caution:**
+If you have an existing Kubernetes cluster with Tiller already installed,
+you should be careful as GitLab cannot detect it. In this case, installing
+Tiller via the applications will result in the cluster having it twice, which
+can lead to confusion during deployments.
## Getting the external IP address
diff --git a/doc/user/project/clusters/serverless/img/function-execution.png b/doc/user/project/clusters/serverless/img/function-execution.png
new file mode 100644
index 00000000000..93b0b6d802d
--- /dev/null
+++ b/doc/user/project/clusters/serverless/img/function-execution.png
Binary files differ
diff --git a/doc/user/project/clusters/serverless/img/serverless-page.png b/doc/user/project/clusters/serverless/img/serverless-page.png
index 5d808fc2d4f..960d6e736d6 100644
--- a/doc/user/project/clusters/serverless/img/serverless-page.png
+++ b/doc/user/project/clusters/serverless/img/serverless-page.png
Binary files differ
diff --git a/doc/user/project/clusters/serverless/index.md b/doc/user/project/clusters/serverless/index.md
index c1f2e844362..a423212a879 100644
--- a/doc/user/project/clusters/serverless/index.md
+++ b/doc/user/project/clusters/serverless/index.md
@@ -1,9 +1,7 @@
# Serverless
> Introduced in GitLab 11.5.
-
-CAUTION: **Caution:**
-Serverless is currently in [alpha](https://about.gitlab.com/handbook/product/#alpha).
+> Serverless is currently in [alpha](https://about.gitlab.com/handbook/product/#alpha).
Run serverless workloads on Kubernetes using [Knative](https://cloud.google.com/knative/).
@@ -31,13 +29,13 @@ To run Knative on Gitlab, you will need:
external IP address for all the applications served by Knative. You will be prompted to enter a
wildcard domain where your applications will be served. Configure your DNS server to use the
external IP address for that domain.
-1. **`gitlab-ci.yml`:** GitLab uses [Kaniko](https://github.com/GoogleContainerTools/kaniko)
+1. **`.gitlab-ci.yml`:** GitLab uses [Kaniko](https://github.com/GoogleContainerTools/kaniko)
to build the application and the [TriggerMesh CLI](https://github.com/triggermesh/tm) to simplify the
deployment of knative services and functions.
-1. **`serverless.yml`** (for [functions only](#deploying-functions)): When using serverless to deploy functions, the `serverless.yml` file
+1. **`serverless.yaml`** (for [functions only](#deploying-functions)): When using serverless to deploy functions, the `serverless.yaml` file
will contain the information for all the functions being hosted in the repository as well as a reference to the
runtime being used.
-1. **`Dockerfile`:** Knative requires a `Dockerfile` in order to build your application. It should be included
+1. **`Dockerfile`** (for [applications only](#deploying-serverless-applications): Knative requires a `Dockerfile` in order to build your application. It should be included
at the root of your project's repo and expose port `8080`.
## Installing Knative via GitLab's Kubernetes integration
@@ -75,13 +73,18 @@ The minimum recommended cluster size to run Knative is 3-nodes, 6 vCPUs, and 22.
> Introduced in GitLab 11.6.
-Using functions is useful for initiating, responding, or triggering independent
+Using functions is useful for dealing with independent
events without needing to maintain a complex unified infrastructure. This allows
you to focus on a single task that can be executed/scaled automatically and independently.
-In order to deploy functions to your Knative instance, the following templates must be present:
+Currently the following [runtimes](https://gitlab.com/triggermesh/runtimes) are offered:
+
+- node.js
+- kaniko
+
+In order to deploy functions to your Knative instance, the following files must be present:
-1. `gitlab-ci.yml`: This template allows to define the stage, environment, and
+1. `.gitlab-ci.yml`: This template allows to define the stage, environment, and
image to be used for your functions. It must be included at the root of your repository:
```yaml
@@ -91,17 +94,22 @@ In order to deploy functions to your Knative instance, the following templates m
functions:
stage: deploy
environment: test
- image: gcr.io/triggermesh/tm:v0.0.6
+ image: gcr.io/triggermesh/tm:v0.0.7
script:
- tm -n "$KUBE_NAMESPACE" set registry-auth gitlab-registry --registry "$CI_REGISTRY" --username "$CI_REGISTRY_USER" --password "$CI_JOB_TOKEN"
- tm -n "$KUBE_NAMESPACE" --registry-host "$CI_REGISTRY_IMAGE" deploy --wait
```
-2. `serverless.yml`: This template contains the metadata for your functions,
- such as name, runtime, and environment. It must be included at the root of your repository:
+ The `gitlab-ci.yml` template creates a `Deploy` stage with a `functions` job that invokes the `tm` CLI with the required parameters.
+
+2. `serverless.yaml`: This file contains the metadata for your functions,
+ such as name, runtime, and environment. It must be included at the root of your repository. The following is a sample `echo` function which shows the required structure for the file.
+
+ NOTE: **Note:**
+ The file extension for the `serverless.yaml` file must be specified as `.yaml` in order to the file to be parsed properly. Specifying the extension as `.yml` will not work.
```yaml
- service: knative-test
+ service: my-functions
description: "Deploying functions from GitLab using Knative"
provider:
@@ -111,27 +119,51 @@ In order to deploy functions to your Knative instance, the following templates m
FOO: BAR
functions:
- container:
- handler: simple
- description: "knative canonical sample"
- runtime: https://gitlab.com/triggermesh/runtimes/raw/master/kaniko.yaml
+ echo:
+ handler: echo
+ runtime: https://gitlab.com/triggermesh/runtimes/raw/master/nodejs.yaml
+ description: "echo function using node.js runtime"
buildargs:
- - DIRECTORY=simple
- environment:
- SIMPLE_MSG: Hello
-
- nodejs:
- handler: nodejs
- runtime: https://gitlab.com/triggermesh/runtimes/raw/master/nodejs.yaml
- description: "nodejs fragment"
- buildargs:
- - DIRECTORY=nodejs
+ - DIRECTORY=echo
environment:
- FUNCTION: nodejs
+ FUNCTION: echo
```
-After the templates have been created, each function must be defined as a single
-file in your repository. Committing a function to your project will result in a
+
+The `serverless.yaml` file contains three sections with distinct parameters:
+
+### `service`
+
+| Parameter | Description |
+|-----------|-------------|
+| `service` | Name for the Knative service which will serve the function. |
+| `description` | A short description of the `service`. |
+
+
+### `provider`
+
+| Parameter | Description |
+|-----------|-------------|
+| `name` | Indicates which provider is used to execute the `serverless.yaml` file. In this case, the TriggerMesh `tm` CLI. |
+| `registry-secret` | Indicates which registry will be used to store docker images. The sample function is using the GitLab Registry (`gitlab-registry`). A different registry host may be specified using `registry` key in the `provider` object. If changing the default, update the permission and the secret value on the `gitlab-ci.yml` file |
+| `environment` | Includes the environment variables to be passed as part of function execution for **all** functions in the file, where `FOO` is the variable name and `BAR` are he variable contents. You may replace this with you own variables. |
+
+### `functions`
+
+In the `serverless.yaml` example above, the function name is `echo` and the subsequent lines contain the function attributes.
+
+
+| Parameter | Description |
+|-----------|-------------|
+| `handler` | The function's file name. In the example above, both the function name and the handler are the same. |
+| `runtime` | The runtime to be used to execute the function. |
+| `description` | A short description of the function. |
+| `buildargs` | Pointer to the function file in the repo. In the sample the function is located in the `echo` directory. |
+| `environment` | Sets an environment variable for the specific function only. |
+
+After the `gitlab-ci.yml` template has been added and the `serverless.yaml` file has been
+created, each function must be defined as a single file in your repository. Committing a
+function to your project will result in a
CI pipeline being executed which will deploy each function as a Knative service.
Once the deploy stage has finished, additional details for the function will
appear under **Operations > Serverless**.
@@ -149,6 +181,10 @@ The function details can be retrieved directly from Knative on the cluster:
kubectl -n "$KUBE_NAMESPACE" get services.serving.knative.dev
```
+The sample function can now be triggered from any HTTP client using a simple `POST` call.
+
+![function exection](img/function-execution.png)
+
Currently, the Serverless page presents all functions available in all clusters registered for the project with Knative installed.
## Deploying Serverless applications
@@ -190,17 +226,12 @@ deploy:
## Deploy the application with Knative
-With all the pieces in place, you can create a new CI pipeline to deploy the Knative application. Navigate to
-**CI/CD > Pipelines** and click the **Run Pipeline** button at the upper-right part of the screen. Then, on the
-Pipelines page, click **Create pipeline**.
+With all the pieces in place, the next time a CI pipeline runs, the Knative application will be deployed. Navigate to
+**CI/CD > Pipelines** and click the most recent pipeline.
## Obtain the URL for the Knative deployment
-There are two ways to obtain the URL for the Knative deployment.
-
-### Using the CI/CD deployment job output
-
-Once all the stages of the pipeline finish, click the **deploy** stage.
+Use the CI/CD deployment job output to obtain the deployment URL. Once all the stages of the pipeline finish, click the **deploy** stage.
![deploy stage](img/deploy-stage.png)
diff --git a/doc/user/project/img/releases.png b/doc/user/project/img/releases.png
new file mode 100644
index 00000000000..aec1db89a75
--- /dev/null
+++ b/doc/user/project/img/releases.png
Binary files differ
diff --git a/doc/user/project/releases.md b/doc/user/project/releases.md
new file mode 100644
index 00000000000..8dad4240c91
--- /dev/null
+++ b/doc/user/project/releases.md
@@ -0,0 +1,12 @@
+# Releases
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/issues/41766) in GitLab 11.7.
+
+Releases mark specific points in a project's development history, communicate
+information about the type of change, and deliver on prepared, often compiled,
+versions of the software to be reused elsewhere. Currently, releases can only be
+created through the API.
+
+Navigate to **Project > Releases** in order to see the list of releases of a project.
+
+![Releases list](img/releases.png)
diff --git a/doc/user/project/repository/index.md b/doc/user/project/repository/index.md
index 1710bba2fd0..fac5975a0dc 100644
--- a/doc/user/project/repository/index.md
+++ b/doc/user/project/repository/index.md
@@ -29,7 +29,7 @@ You can either use the user interface (UI), or connect your local computer
with GitLab [through the command line](../../../gitlab-basics/command-line-commands.md#start-working-on-your-project).
To configure [GitLab CI/CD](../../../ci/README.md) to build, test, and deploy
-you code, add a file called [.`gitlab-ci.yml`](../../../ci/quick_start/README.md)
+you code, add a file called [`.gitlab-ci.yml`](../../../ci/quick_start/README.md)
to your repository's root.
**From the user interface:**
diff --git a/lib/api/entities.rb b/lib/api/entities.rb
index b83a5c14190..22403664c21 100644
--- a/lib/api/entities.rb
+++ b/lib/api/entities.rb
@@ -323,7 +323,7 @@ module API
expose :request_access_enabled
expose :full_name, :full_path
- if ::Group.supports_nested_groups?
+ if ::Group.supports_nested_objects?
expose :parent_id
end
diff --git a/lib/api/groups.rb b/lib/api/groups.rb
index 626a2008dee..64958ff982a 100644
--- a/lib/api/groups.rb
+++ b/lib/api/groups.rb
@@ -113,7 +113,7 @@ module API
requires :name, type: String, desc: 'The name of the group'
requires :path, type: String, desc: 'The path of the group'
- if ::Group.supports_nested_groups?
+ if ::Group.supports_nested_objects?
optional :parent_id, type: Integer, desc: 'The parent group id for creating nested group'
end
diff --git a/lib/api/helpers.rb b/lib/api/helpers.rb
index a7d67a6300e..c3eca713712 100644
--- a/lib/api/helpers.rb
+++ b/lib/api/helpers.rb
@@ -163,9 +163,11 @@ module API
end
def find_branch!(branch_name)
- user_project.repository.find_branch(branch_name) || not_found!('Branch')
- rescue Gitlab::Git::CommandError
- render_api_error!('The branch refname is invalid', 400)
+ if Gitlab::GitRefValidator.validate(branch_name)
+ user_project.repository.find_branch(branch_name) || not_found!('Branch')
+ else
+ render_api_error!('The branch refname is invalid', 400)
+ end
end
def find_project_label(id)
diff --git a/lib/gitlab/fake_application_settings.rb b/lib/gitlab/fake_application_settings.rb
index db1aeeea8d3..bd806269bf0 100644
--- a/lib/gitlab/fake_application_settings.rb
+++ b/lib/gitlab/fake_application_settings.rb
@@ -37,5 +37,9 @@ module Gitlab
def pick_repository_storage
repository_storages.sample
end
+
+ def commit_email_hostname
+ super.presence || ApplicationSetting.default_commit_email_hostname
+ end
end
end
diff --git a/lib/gitlab/git/object_pool.rb b/lib/gitlab/git/object_pool.rb
index ba9b40b7df4..1c6242b444a 100644
--- a/lib/gitlab/git/object_pool.rb
+++ b/lib/gitlab/git/object_pool.rb
@@ -8,7 +8,7 @@ module Gitlab
GL_REPOSITORY = ""
delegate :exists?, :size, to: :repository
- delegate :delete, to: :object_pool_service
+ delegate :unlink_repository, :delete, to: :object_pool_service
attr_reader :storage, :relative_path, :source_repository
diff --git a/lib/gitlab/gitaly_client.rb b/lib/gitlab/gitaly_client.rb
index 11021ee06b3..8bf8a3b53cd 100644
--- a/lib/gitlab/gitaly_client.rb
+++ b/lib/gitlab/gitaly_client.rb
@@ -26,6 +26,7 @@ module Gitlab
end
end
+ PEM_REGEX = /\-+BEGIN CERTIFICATE\-+.+?\-+END CERTIFICATE\-+/m
SERVER_VERSION_FILE = 'GITALY_SERVER_VERSION'
MAXIMUM_GITALY_CALLS = 35
CLIENT_NAME = (Sidekiq.server? ? 'gitlab-sidekiq' : 'gitlab-web').freeze
@@ -50,11 +51,42 @@ module Gitlab
@stubs[storage][name] ||= begin
klass = stub_class(name)
addr = stub_address(storage)
- klass.new(addr, :this_channel_is_insecure)
+ creds = stub_creds(storage)
+ klass.new(addr, creds)
end
end
end
+ def self.stub_cert_paths
+ cert_paths = Dir["#{OpenSSL::X509::DEFAULT_CERT_DIR}/*"]
+ cert_paths << OpenSSL::X509::DEFAULT_CERT_FILE if File.exist? OpenSSL::X509::DEFAULT_CERT_FILE
+ cert_paths
+ end
+
+ def self.stub_certs
+ return @certs if @certs
+
+ @certs = stub_cert_paths.flat_map do |cert_file|
+ File.read(cert_file).scan(PEM_REGEX).map do |cert|
+ begin
+ OpenSSL::X509::Certificate.new(cert).to_pem
+ rescue OpenSSL::OpenSSLError => e
+ Rails.logger.error "Could not load certificate #{cert_file} #{e}"
+ Gitlab::Sentry.track_exception(e, extra: { cert_file: cert_file })
+ nil
+ end
+ end.compact
+ end.uniq.join("\n")
+ end
+
+ def self.stub_creds(storage)
+ if URI(address(storage)).scheme == 'tls'
+ GRPC::Core::ChannelCredentials.new stub_certs
+ else
+ :this_channel_is_insecure
+ end
+ end
+
def self.stub_class(name)
if name == :health_check
Grpc::Health::V1::Health::Stub
@@ -64,9 +96,7 @@ module Gitlab
end
def self.stub_address(storage)
- addr = address(storage)
- addr = addr.sub(%r{^tcp://}, '') if URI(addr).scheme == 'tcp'
- addr
+ address(storage).sub(%r{^tcp://|^tls://}, '')
end
def self.clear_stubs!
@@ -88,8 +118,8 @@ module Gitlab
raise "storage #{storage.inspect} is missing a gitaly_address"
end
- unless URI(address).scheme.in?(%w(tcp unix))
- raise "Unsupported Gitaly address: #{address.inspect} does not use URL scheme 'tcp' or 'unix'"
+ unless URI(address).scheme.in?(%w(tcp unix tls))
+ raise "Unsupported Gitaly address: #{address.inspect} does not use URL scheme 'tcp' or 'unix' or 'tls'"
end
address
diff --git a/lib/gitlab/gitaly_client/object_pool_service.rb b/lib/gitlab/gitaly_client/object_pool_service.rb
index 272ce73ad64..6e7ede5fd18 100644
--- a/lib/gitlab/gitaly_client/object_pool_service.rb
+++ b/lib/gitlab/gitaly_client/object_pool_service.rb
@@ -35,7 +35,10 @@ module Gitlab
end
def unlink_repository(repository)
- request = Gitaly::UnlinkRepositoryFromObjectPoolRequest.new(repository: repository.gitaly_repository)
+ request = Gitaly::UnlinkRepositoryFromObjectPoolRequest.new(
+ object_pool: object_pool,
+ repository: repository.gitaly_repository
+ )
GitalyClient.call(storage, :object_pool_service, :unlink_repository_from_object_pool,
request, timeout: GitalyClient.fast_timeout)
diff --git a/lib/gitlab/import_export/command_line_util.rb b/lib/gitlab/import_export/command_line_util.rb
index c9e2a6a78d9..bdecff0931c 100644
--- a/lib/gitlab/import_export/command_line_util.rb
+++ b/lib/gitlab/import_export/command_line_util.rb
@@ -3,7 +3,8 @@
module Gitlab
module ImportExport
module CommandLineUtil
- DEFAULT_MODE = 0700
+ UNTAR_MASK = 'u+rwX,go+rX,go-w'
+ DEFAULT_DIR_MODE = 0700
def tar_czf(archive:, dir:)
tar_with_options(archive: archive, dir: dir, options: 'czf')
@@ -14,8 +15,8 @@ module Gitlab
end
def mkdir_p(path)
- FileUtils.mkdir_p(path, mode: DEFAULT_MODE)
- FileUtils.chmod(DEFAULT_MODE, path)
+ FileUtils.mkdir_p(path, mode: DEFAULT_DIR_MODE)
+ FileUtils.chmod(DEFAULT_DIR_MODE, path)
end
private
@@ -41,6 +42,7 @@ module Gitlab
def untar_with_options(archive:, dir:, options:)
execute(%W(tar -#{options} #{archive} -C #{dir}))
+ execute(%W(chmod -R #{UNTAR_MASK} #{dir}))
end
def execute(cmd)
diff --git a/lib/gitlab/json_cache.rb b/lib/gitlab/json_cache.rb
new file mode 100644
index 00000000000..1adf83739ad
--- /dev/null
+++ b/lib/gitlab/json_cache.rb
@@ -0,0 +1,87 @@
+# frozen_string_literal: true
+
+module Gitlab
+ class JsonCache
+ attr_reader :backend, :cache_key_with_version, :namespace
+
+ def initialize(options = {})
+ @backend = options.fetch(:backend, Rails.cache)
+ @namespace = options.fetch(:namespace, nil)
+ @cache_key_with_version = options.fetch(:cache_key_with_version, true)
+ end
+
+ def active?
+ if backend.respond_to?(:active?)
+ backend.active?
+ else
+ true
+ end
+ end
+
+ def cache_key(key)
+ expanded_cache_key = [namespace, key].compact
+
+ if cache_key_with_version
+ expanded_cache_key << Rails.version
+ end
+
+ expanded_cache_key.join(':')
+ end
+
+ def expire(key)
+ backend.delete(cache_key(key))
+ end
+
+ def read(key, klass = nil)
+ value = backend.read(cache_key(key))
+ value = parse_value(value, klass) if value
+ value
+ end
+
+ def write(key, value, options = nil)
+ backend.write(cache_key(key), value.to_json, options)
+ end
+
+ def fetch(key, options = {}, &block)
+ klass = options.delete(:as)
+ value = read(key, klass)
+
+ return value unless value.nil?
+
+ value = yield
+
+ write(key, value, options)
+
+ value
+ end
+
+ private
+
+ def parse_value(raw, klass)
+ value = ActiveSupport::JSON.decode(raw)
+
+ case value
+ when Hash then parse_entry(value, klass)
+ when Array then parse_entries(value, klass)
+ else
+ value
+ end
+ rescue ActiveSupport::JSON.parse_error
+ nil
+ end
+
+ def parse_entry(raw, klass)
+ klass.new(raw) if valid_entry?(raw, klass)
+ end
+
+ def valid_entry?(raw, klass)
+ return false unless klass && raw.is_a?(Hash)
+
+ (raw.keys - klass.attribute_names).empty?
+ end
+
+ def parse_entries(values, klass)
+ values.map { |value| parse_entry(value, klass) }.compact
+ end
+ end
+end
diff --git a/lib/gitlab/group_hierarchy.rb b/lib/gitlab/object_hierarchy.rb
index 97cbdc6cb39..f2772c733c7 100644
--- a/lib/gitlab/group_hierarchy.rb
+++ b/lib/gitlab/object_hierarchy.rb
@@ -1,16 +1,16 @@
# frozen_string_literal: true
module Gitlab
- # Retrieving of parent or child groups based on a base ActiveRecord relation.
+ # Retrieving of parent or child objects based on a base ActiveRecord relation.
#
# This class uses recursive CTEs and as a result will only work on PostgreSQL.
- class GroupHierarchy
+ class ObjectHierarchy
attr_reader :ancestors_base, :descendants_base, :model
# ancestors_base - An instance of ActiveRecord::Relation for which to
- # get parent groups.
+ # get parent objects.
# descendants_base - An instance of ActiveRecord::Relation for which to
- # get child groups. If omitted, ancestors_base is used.
+ # get child objects. If omitted, ancestors_base is used.
def initialize(ancestors_base, descendants_base = ancestors_base)
raise ArgumentError.new("Model of ancestors_base does not match model of descendants_base") if ancestors_base.model != descendants_base.model
@@ -39,7 +39,7 @@ module Gitlab
end
# rubocop: enable CodeReuse/ActiveRecord
- # Returns a relation that includes the ancestors_base set of groups
+ # Returns a relation that includes the ancestors_base set of objects
# and all their ancestors (recursively).
#
# Passing an `upto` will stop the recursion once the specified parent_id is
@@ -47,13 +47,13 @@ module Gitlab
# included.
#
# Passing a `hierarchy_order` with either `:asc` or `:desc` will cause the
- # recursive query order from most nested group to root or from the root
- # ancestor to most nested group respectively. This uses a `depth` column
+ # recursive query order from most nested object to root or from the root
+ # ancestor to most nested object respectively. This uses a `depth` column
# where `1` is defined as the depth for the base and increment as we go up
# each parent.
# rubocop: disable CodeReuse/ActiveRecord
def base_and_ancestors(upto: nil, hierarchy_order: nil)
- return ancestors_base unless Group.supports_nested_groups?
+ return ancestors_base unless hierarchy_supported?
recursive_query = base_and_ancestors_cte(upto, hierarchy_order).apply_to(model.all)
recursive_query = recursive_query.order(depth: hierarchy_order) if hierarchy_order
@@ -62,16 +62,16 @@ module Gitlab
end
# rubocop: enable CodeReuse/ActiveRecord
- # Returns a relation that includes the descendants_base set of groups
+ # Returns a relation that includes the descendants_base set of objects
# and all their descendants (recursively).
def base_and_descendants
- return descendants_base unless Group.supports_nested_groups?
+ return descendants_base unless hierarchy_supported?
read_only(base_and_descendants_cte.apply_to(model.all))
end
- # Returns a relation that includes the base groups, their ancestors,
- # and the descendants of the base groups.
+ # Returns a relation that includes the base objects, their ancestors,
+ # and the descendants of the base objects.
#
# The resulting query will roughly look like the following:
#
@@ -91,16 +91,16 @@ module Gitlab
# Using this approach allows us to further add criteria to the relation with
# Rails thinking it's selecting data the usual way.
#
- # If nested groups are not supported, ancestors_base is returned.
+ # If nested objects are not supported, ancestors_base is returned.
# rubocop: disable CodeReuse/ActiveRecord
- def all_groups
- return ancestors_base unless Group.supports_nested_groups?
+ def all_objects
+ return ancestors_base unless hierarchy_supported?
ancestors = base_and_ancestors_cte
descendants = base_and_descendants_cte
- ancestors_table = ancestors.alias_to(groups_table)
- descendants_table = descendants.alias_to(groups_table)
+ ancestors_table = ancestors.alias_to(objects_table)
+ descendants_table = descendants.alias_to(objects_table)
relation = model
.unscoped
@@ -117,23 +117,27 @@ module Gitlab
private
+ def hierarchy_supported?
+ Gitlab::Database.postgresql?
+ end
+
# rubocop: disable CodeReuse/ActiveRecord
def base_and_ancestors_cte(stop_id = nil, hierarchy_order = nil)
cte = SQL::RecursiveCTE.new(:base_and_ancestors)
depth_column = :depth
base_query = ancestors_base.except(:order)
- base_query = base_query.select("1 as #{depth_column}", groups_table[Arel.star]) if hierarchy_order
+ base_query = base_query.select("1 as #{depth_column}", objects_table[Arel.star]) if hierarchy_order
cte << base_query
# Recursively get all the ancestors of the base set.
parent_query = model
- .from([groups_table, cte.table])
- .where(groups_table[:id].eq(cte.table[:parent_id]))
+ .from([objects_table, cte.table])
+ .where(objects_table[:id].eq(cte.table[:parent_id]))
.except(:order)
- parent_query = parent_query.select(cte.table[depth_column] + 1, groups_table[Arel.star]) if hierarchy_order
+ parent_query = parent_query.select(cte.table[depth_column] + 1, objects_table[Arel.star]) if hierarchy_order
parent_query = parent_query.where(cte.table[:parent_id].not_eq(stop_id)) if stop_id
cte << parent_query
@@ -149,15 +153,15 @@ module Gitlab
# Recursively get all the descendants of the base set.
cte << model
- .from([groups_table, cte.table])
- .where(groups_table[:parent_id].eq(cte.table[:id]))
+ .from([objects_table, cte.table])
+ .where(objects_table[:parent_id].eq(cte.table[:id]))
.except(:order)
cte
end
# rubocop: enable CodeReuse/ActiveRecord
- def groups_table
+ def objects_table
model.arel_table
end
diff --git a/lib/gitlab/upgrader.rb b/lib/gitlab/upgrader.rb
deleted file mode 100644
index ccab0e4dd73..00000000000
--- a/lib/gitlab/upgrader.rb
+++ /dev/null
@@ -1,111 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- class Upgrader
- def execute
- puts "GitLab #{current_version.major} upgrade tool"
- puts "Your version is #{current_version}"
- puts "Latest available version for GitLab #{current_version.major} is #{latest_version}"
-
- if latest_version?
- puts "You are using the latest GitLab version"
- else
- puts "Newer GitLab version is available"
-
- answer = if ARGV.first == "-y"
- "yes"
- else
- prompt("Do you want to upgrade (yes/no)? ", %w{yes no})
- end
-
- if answer == "yes"
- upgrade
- else
- exit 0
- end
- end
- end
-
- def latest_version?
- current_version >= latest_version
- end
-
- def current_version
- @current_version ||= Gitlab::VersionInfo.parse(current_version_raw)
- end
-
- def latest_version
- @latest_version ||= Gitlab::VersionInfo.parse(latest_version_raw)
- end
-
- def current_version_raw
- File.read(File.join(gitlab_path, "VERSION")).strip
- end
-
- def latest_version_raw
- git_tags = fetch_git_tags
- git_tags = git_tags.select { |version| version =~ /v\d+\.\d+\.\d+\Z/ }
- git_versions = git_tags.map { |tag| Gitlab::VersionInfo.parse(tag.match(/v\d+\.\d+\.\d+/).to_s) }
- "v#{git_versions.sort.last}"
- end
-
- def fetch_git_tags
- remote_tags, _ = Gitlab::Popen.popen(%W(#{Gitlab.config.git.bin_path} ls-remote --tags https://gitlab.com/gitlab-org/gitlab-ce.git))
- remote_tags.split("\n").grep(%r{tags/v#{current_version.major}})
- end
-
- def update_commands
- {
- "Stash changed files" => %W(#{Gitlab.config.git.bin_path} stash),
- "Get latest code" => %W(#{Gitlab.config.git.bin_path} fetch),
- "Switch to new version" => %W(#{Gitlab.config.git.bin_path} checkout v#{latest_version}),
- "Install gems" => %w(bundle),
- "Migrate DB" => %w(bundle exec rake db:migrate),
- "Recompile assets" => %w(bundle exec rake yarn:install gitlab:assets:clean gitlab:assets:compile),
- "Clear cache" => %w(bundle exec rake cache:clear)
- }
- end
-
- def env
- {
- 'RAILS_ENV' => 'production',
- 'NODE_ENV' => 'production'
- }
- end
-
- def upgrade
- update_commands.each do |title, cmd|
- puts title
- puts " -> #{cmd.join(' ')}"
-
- if system(env, *cmd)
- puts " -> OK"
- else
- puts " -> FAILED"
- puts "Failed to upgrade. Try to repeat task or proceed with upgrade manually "
- exit 1
- end
- end
-
- puts "Done"
- end
-
- def gitlab_path
- File.expand_path(File.join(File.dirname(__FILE__), '../..'))
- end
-
- # Prompt the user to input something
- #
- # message - the message to display before input
- # choices - array of strings of acceptable answers or nil for any answer
- #
- # Returns the user's answer
- def prompt(message, choices = nil)
- begin
- print(message)
- answer = STDIN.gets.chomp
- end while !choices.include?(answer)
- answer
- end
- end
-end
diff --git a/lib/gitlab/utils/override.rb b/lib/gitlab/utils/override.rb
index c412961ea3f..c87e97d0213 100644
--- a/lib/gitlab/utils/override.rb
+++ b/lib/gitlab/utils/override.rb
@@ -4,16 +4,11 @@ module Gitlab
module Utils
module Override
class Extension
- def self.verify_class!(klass, method_name)
- instance_method_defined?(klass, method_name) ||
- raise(
- NotImplementedError.new(
- "#{klass}\##{method_name} doesn't exist!"))
- end
-
- def self.instance_method_defined?(klass, name, include_super: true)
- klass.instance_methods(include_super).include?(name) ||
- klass.private_instance_methods(include_super).include?(name)
+ def self.verify_class!(klass, method_name, arity)
+ extension = new(klass)
+ parents = extension.parents_for(klass)
+ extension.verify_method!(
+ klass: klass, parents: parents, method_name: method_name, sub_method_arity: arity)
end
attr_reader :subject
@@ -22,35 +17,77 @@ module Gitlab
@subject = subject
end
- def add_method_name(method_name)
- method_names << method_name
- end
-
- def add_class(klass)
- classes << klass
+ def parents_for(klass)
+ index = klass.ancestors.index(subject)
+ klass.ancestors.drop(index + 1)
end
def verify!
classes.each do |klass|
- index = klass.ancestors.index(subject)
- parents = klass.ancestors.drop(index + 1)
-
- method_names.each do |method_name|
- parents.any? do |parent|
- self.class.instance_method_defined?(
- parent, method_name, include_super: false)
- end ||
- raise(
- NotImplementedError.new(
- "#{klass}\##{method_name} doesn't exist!"))
+ parents = parents_for(klass)
+
+ method_names.each_pair do |method_name, arity|
+ verify_method!(
+ klass: klass,
+ parents: parents,
+ method_name: method_name,
+ sub_method_arity: arity)
end
end
end
+ def verify_method!(klass:, parents:, method_name:, sub_method_arity:)
+ overridden_parent = parents.find do |parent|
+ instance_method_defined?(parent, method_name)
+ end
+
+ raise NotImplementedError.new("#{klass}\##{method_name} doesn't exist!") unless overridden_parent
+
+ super_method_arity = find_direct_method(overridden_parent, method_name).arity
+
+ unless arity_compatible?(sub_method_arity, super_method_arity)
+ raise NotImplementedError.new("#{subject}\##{method_name} has arity of #{sub_method_arity}, but #{overridden_parent}\##{method_name} has arity of #{super_method_arity}")
+ end
+ end
+
+ def add_method_name(method_name, arity = nil)
+ method_names[method_name] = arity
+ end
+
+ def add_class(klass)
+ classes << klass
+ end
+
+ def verify_override?(method_name)
+ method_names.has_key?(method_name)
+ end
+
private
+ def instance_method_defined?(klass, name)
+ klass.instance_methods(false).include?(name) ||
+ klass.private_instance_methods(false).include?(name)
+ end
+
+ def find_direct_method(klass, name)
+ method = klass.instance_method(name)
+ method = method.super_method until method && klass == method.owner
+ method
+ end
+
+ def arity_compatible?(sub_method_arity, super_method_arity)
+ if sub_method_arity >= 0 && super_method_arity >= 0
+ # Regular arguments
+ sub_method_arity == super_method_arity
+ else
+ # It's too complex to check this case, just allow sub-method having negative arity
+ # But we don't allow sub_method_arity > 0 yet super_method_arity < 0
+ sub_method_arity < 0
+ end
+ end
+
def method_names
- @method_names ||= []
+ @method_names ||= {}
end
def classes
@@ -80,11 +117,21 @@ module Gitlab
def override(method_name)
return unless ENV['STATIC_VERIFICATION']
+ Override.extensions[self] ||= Extension.new(self)
+ Override.extensions[self].add_method_name(method_name)
+ end
+
+ def method_added(method_name)
+ super
+
+ return unless ENV['STATIC_VERIFICATION']
+ return unless Override.extensions[self]&.verify_override?(method_name)
+
+ method_arity = instance_method(method_name).arity
if is_a?(Class)
- Extension.verify_class!(self, method_name)
+ Extension.verify_class!(self, method_name, method_arity)
else # We delay the check for modules
- Override.extensions[self] ||= Extension.new(self)
- Override.extensions[self].add_method_name(method_name)
+ Override.extensions[self].add_method_name(method_name, method_arity)
end
end
diff --git a/lib/tasks/gitlab/storage.rake b/lib/tasks/gitlab/storage.rake
index f539b1df955..09dc3aa9882 100644
--- a/lib/tasks/gitlab/storage.rake
+++ b/lib/tasks/gitlab/storage.rake
@@ -2,6 +2,12 @@ namespace :gitlab do
namespace :storage do
desc 'GitLab | Storage | Migrate existing projects to Hashed Storage'
task migrate_to_hashed: :environment do
+ if Gitlab::Database.read_only?
+ warn 'This task requires database write access. Exiting.'
+
+ next
+ end
+
storage_migrator = Gitlab::HashedStorage::Migrator.new
helper = Gitlab::HashedStorage::RakeHelper
@@ -9,7 +15,7 @@ namespace :gitlab do
project = Project.with_unmigrated_storage.find_by(id: helper.range_from)
unless project
- puts "There are no projects requiring storage migration with ID=#{helper.range_from}"
+ warn "There are no projects requiring storage migration with ID=#{helper.range_from}"
next
end
@@ -23,7 +29,7 @@ namespace :gitlab do
legacy_projects_count = Project.with_unmigrated_storage.count
if legacy_projects_count == 0
- puts 'There are no projects requiring storage migration. Nothing to do!'
+ warn 'There are no projects requiring storage migration. Nothing to do!'
next
end
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 61fb56d2fa2..b27efe04966 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -97,9 +97,6 @@ msgstr[1] ""
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr ""
-msgid "%{bio} at %{organization}"
-msgstr ""
-
msgid "%{commit_author_link} authored %{commit_timeago}"
msgstr ""
@@ -438,9 +435,15 @@ msgstr ""
msgid "AdminProjects|Delete project"
msgstr ""
+msgid "AdminSettings|Environment variables are protected by default"
+msgstr ""
+
msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
msgstr ""
+msgid "AdminSettings|When creating a new environment variable it will be protected by default."
+msgstr ""
+
msgid "AdminUsers|Block user"
msgstr ""
@@ -525,6 +528,9 @@ msgstr ""
msgid "An error has occurred"
msgstr ""
+msgid "An error occured while fetching the releases. Please try again."
+msgstr ""
+
msgid "An error occurred creating the new branch."
msgstr ""
@@ -2743,6 +2749,15 @@ msgstr ""
msgid "Enter the merge request title"
msgstr ""
+msgid "Environment variables"
+msgstr ""
+
+msgid "Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. You can use environment variables for passwords, secret keys, or whatever you want."
+msgstr ""
+
+msgid "Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default"
+msgstr ""
+
msgid "Environments"
msgstr ""
@@ -3172,6 +3187,9 @@ msgstr ""
msgid "Geo"
msgstr ""
+msgid "Getting started with releases"
+msgstr ""
+
msgid "Git"
msgstr ""
@@ -3756,7 +3774,7 @@ msgstr ""
msgid "Job|The artifacts were removed"
msgstr ""
-msgid "Job|The artifacts will be removed in"
+msgid "Job|The artifacts will be removed"
msgstr ""
msgid "Job|This job is stuck because the project doesn't have any runners online assigned to it."
@@ -4090,9 +4108,6 @@ msgstr ""
msgid "Merge Request"
msgstr ""
-msgid "Merge Request:"
-msgstr ""
-
msgid "Merge Requests"
msgstr ""
@@ -4132,6 +4147,9 @@ msgstr ""
msgid "MergeRequests|started a discussion on %{linkStart}the diff%{linkEnd}"
msgstr ""
+msgid "MergeRequests|started a discussion on an outdated change in commit %{linkStart}%{commitId}%{linkEnd}"
+msgstr ""
+
msgid "MergeRequests|started a discussion on commit %{linkStart}%{commitId}%{linkEnd}"
msgstr ""
@@ -4628,6 +4646,9 @@ msgstr ""
msgid "Open"
msgstr ""
+msgid "Open Documentation"
+msgstr ""
+
msgid "Open in Xcode"
msgstr ""
@@ -5527,6 +5548,9 @@ msgstr ""
msgid "Releases"
msgstr ""
+msgid "Releases mark specific points in a project's development history, communicate information about the type of change, and deliver on prepared, often compiled, versions of the software to be reused elsewhere. Currently, releases can only be created through the API."
+msgstr ""
+
msgid "Remind later"
msgstr ""
@@ -7137,10 +7161,13 @@ msgstr ""
msgid "Trending"
msgstr ""
-msgid "Trigger"
+msgid "Trigger this manual action"
msgstr ""
-msgid "Trigger this manual action"
+msgid "Trigger token:"
+msgstr ""
+
+msgid "Trigger variables:"
msgstr ""
msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
@@ -7338,15 +7365,6 @@ msgstr ""
msgid "Users requesting access to"
msgstr ""
-msgid "Variables"
-msgstr ""
-
-msgid "Variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. You can use variables for passwords, secret keys, or whatever you want."
-msgstr ""
-
-msgid "Variables:"
-msgstr ""
-
msgid "Various container registry settings."
msgstr ""
@@ -7876,6 +7894,9 @@ msgstr ""
msgid "importing"
msgstr ""
+msgid "in"
+msgstr ""
+
msgid "issue boards"
msgstr ""
diff --git a/package.json b/package.json
index 8ee31b8e57b..1dc9797c59b 100644
--- a/package.json
+++ b/package.json
@@ -27,7 +27,7 @@
"@babel/preset-env": "^7.1.0",
"@gitlab/csslab": "^1.8.0",
"@gitlab/svgs": "^1.43.0",
- "@gitlab/ui": "^1.15.0",
+ "@gitlab/ui": "^1.18.0",
"apollo-boost": "^0.1.20",
"apollo-client": "^2.4.5",
"autosize": "^4.0.0",
diff --git a/qa/qa/page/base.rb b/qa/qa/page/base.rb
index 88ade66f47d..615d17bbcfe 100644
--- a/qa/qa/page/base.rb
+++ b/qa/qa/page/base.rb
@@ -108,8 +108,12 @@ module QA
element.select value.to_s.capitalize
end
- def has_element?(name)
- has_css?(element_selector_css(name))
+ def has_element?(name, wait: Capybara.default_max_wait_time)
+ has_css?(element_selector_css(name), wait: wait)
+ end
+
+ def has_no_text?(text)
+ page.has_no_text? text
end
def within_element(name)
diff --git a/qa/qa/page/main/login.rb b/qa/qa/page/main/login.rb
index 97ffe0e5716..cb83ace20b6 100644
--- a/qa/qa/page/main/login.rb
+++ b/qa/qa/page/main/login.rb
@@ -35,13 +35,21 @@ module QA
element :saml_login_button
end
+ view 'app/views/layouts/devise.html.haml' do
+ element :login_page
+ end
+
def initialize
# The login page is usually the entry point for all the scenarios so
# we need to wait for the instance to start. That said, in some cases
# we are already logged-in so we check both cases here.
+ # Check if we're already logged in first. If we don't then we have to
+ # wait 10 seconds for the check for the login page to fail every time
+ # we use this class when we're already logged in (E.g., whenever we
+ # create a personal access token to use for API access).
wait(max: 500) do
- has_css?('.login-page') ||
- Page::Main::Menu.act { has_personal_area?(wait: 0) }
+ Page::Main::Menu.act { has_personal_area?(wait: 0) } ||
+ has_element?(:login_page)
end
end
diff --git a/qa/qa/page/main/menu.rb b/qa/qa/page/main/menu.rb
index cc2724618e9..6804cc8fb20 100644
--- a/qa/qa/page/main/menu.rb
+++ b/qa/qa/page/main/menu.rb
@@ -63,15 +63,11 @@ module QA
end
def has_personal_area?(wait: Capybara.default_max_wait_time)
- using_wait_time(wait) do
- page.has_selector?(element_selector_css(:user_avatar))
- end
+ has_element?(:user_avatar, wait: wait)
end
def has_admin_area_link?(wait: Capybara.default_max_wait_time)
- using_wait_time(wait) do
- page.has_selector?(element_selector_css(:admin_area_link))
- end
+ has_element?(:admin_area_link, wait: wait)
end
private
diff --git a/qa/qa/support/page/logging.rb b/qa/qa/support/page/logging.rb
index 43bc16d8c9a..df3b794b14b 100644
--- a/qa/qa/support/page/logging.rb
+++ b/qa/qa/support/page/logging.rb
@@ -77,7 +77,7 @@ module QA
super
end
- def has_element?(name)
+ def has_element?(name, wait: Capybara.default_max_wait_time)
found = super
log("has_element? :#{name} returned #{found}")
@@ -85,6 +85,14 @@ module QA
found
end
+ def has_no_text?(text)
+ found = super
+
+ log(%Q{has_no_text?('#{text}') returned #{found}})
+
+ found
+ end
+
def within_element(name)
log("within element :#{name}")
diff --git a/qa/spec/page/logging_spec.rb b/qa/spec/page/logging_spec.rb
index 9d56353062b..a54ff424f53 100644
--- a/qa/spec/page/logging_spec.rb
+++ b/qa/spec/page/logging_spec.rb
@@ -65,6 +65,13 @@ describe QA::Support::Page::Logging do
.to output(/has_element\? :element returned true/).to_stdout_from_any_process
end
+ it 'logs has_no_text?' do
+ allow(page).to receive(:has_no_text?).with('foo').and_return(true)
+
+ expect { subject.has_no_text? 'foo' }
+ .to output(/has_no_text\?\('foo'\) returned true/).to_stdout_from_any_process
+ end
+
it 'logs within_element' do
expect { subject.within_element(:element) }
.to output(/within element :element/).to_stdout_from_any_process
diff --git a/spec/controllers/groups/group_members_controller_spec.rb b/spec/controllers/groups/group_members_controller_spec.rb
index 00a00306ff9..ed38dadfd6b 100644
--- a/spec/controllers/groups/group_members_controller_spec.rb
+++ b/spec/controllers/groups/group_members_controller_spec.rb
@@ -78,9 +78,11 @@ describe Groups::GroupMembersController do
Gitlab::Access.options.each do |label, value|
it "can change the access level to #{label}" do
- xhr :put, :update, group_member: { access_level: value },
- group_id: group,
- id: requester
+ put :update, params: {
+ group_member: { access_level: value },
+ group_id: group,
+ id: requester
+ }, xhr: true
expect(requester.reload.human_access).to eq(label)
end
@@ -130,7 +132,7 @@ describe Groups::GroupMembersController do
end
it '[JS] removes user from members' do
- xhr :delete, :destroy, group_id: group, id: member
+ delete :destroy, params: { group_id: group, id: member }, xhr: true
expect(response).to be_success
expect(group.members).not_to include member
diff --git a/spec/controllers/projects/clusters_controller_spec.rb b/spec/controllers/projects/clusters_controller_spec.rb
index ea266384446..d94c18ddc02 100644
--- a/spec/controllers/projects/clusters_controller_spec.rb
+++ b/spec/controllers/projects/clusters_controller_spec.rb
@@ -311,7 +311,7 @@ describe Projects::ClustersController do
describe 'security' do
before do
- allow(ClusterPlatformConfigureWorker).to receive(:perform_async)
+ allow(ClusterConfigureWorker).to receive(:perform_async)
stub_kubeclient_get_namespace('https://kubernetes.example.com', namespace: 'my-namespace')
end
@@ -409,7 +409,7 @@ describe Projects::ClustersController do
end
before do
- allow(ClusterPlatformConfigureWorker).to receive(:perform_async)
+ allow(ClusterConfigureWorker).to receive(:perform_async)
stub_kubeclient_get_namespace('https://kubernetes.example.com', namespace: 'my-namespace')
end
diff --git a/spec/controllers/projects/deploy_keys_controller_spec.rb b/spec/controllers/projects/deploy_keys_controller_spec.rb
index a927d4329ef..e54cf3e8181 100644
--- a/spec/controllers/projects/deploy_keys_controller_spec.rb
+++ b/spec/controllers/projects/deploy_keys_controller_spec.rb
@@ -16,7 +16,7 @@ describe Projects::DeployKeysController do
end
context 'when html requested' do
- it 'redirects to blob' do
+ it 'redirects to project settings with the correct anchor' do
get :index, params: params
expect(response).to redirect_to(project_settings_repository_path(project, anchor: 'js-deploy-keys-settings'))
@@ -60,6 +60,40 @@ describe Projects::DeployKeysController do
end
end
+ describe 'POST create' do
+ def create_params(title = 'my-key')
+ {
+ namespace_id: project.namespace.path,
+ project_id: project.path,
+ deploy_key: {
+ title: title,
+ key: attributes_for(:deploy_key)[:key],
+ deploy_keys_projects_attributes: { '0' => { can_push: '1' } }
+ }
+ }
+ end
+
+ it 'creates a new deploy key for the project' do
+ expect { post :create, params: create_params }.to change(project.deploy_keys, :count).by(1)
+
+ expect(response).to redirect_to(project_settings_repository_path(project, anchor: 'js-deploy-keys-settings'))
+ end
+
+ it 'redirects to project settings with the correct anchor' do
+ post :create, params: create_params
+
+ expect(response).to redirect_to(project_settings_repository_path(project, anchor: 'js-deploy-keys-settings'))
+ end
+
+ context 'when the deploy key is invalid' do
+ it 'shows an alert with the validations errors' do
+ post :create, params: create_params(nil)
+
+ expect(flash[:alert]).to eq("Title can't be blank, Deploy keys projects deploy key title can't be blank")
+ end
+ end
+ end
+
describe '/enable/:id' do
let(:deploy_key) { create(:deploy_key) }
let(:project2) { create(:project) }
diff --git a/spec/controllers/projects/issues_controller_spec.rb b/spec/controllers/projects/issues_controller_spec.rb
index f9193513a6a..a239ac16c0d 100644
--- a/spec/controllers/projects/issues_controller_spec.rb
+++ b/spec/controllers/projects/issues_controller_spec.rb
@@ -206,12 +206,12 @@ describe Projects::IssuesController do
describe 'Redirect after sign in' do
context 'with an AJAX request' do
it 'does not store the visited URL' do
- xhr :get,
- :show,
+ get :show, params: {
format: :json,
namespace_id: project.namespace,
project_id: project,
id: issue.iid
+ }, xhr: true
expect(session['user_return_to']).to be_blank
end
diff --git a/spec/controllers/projects/merge_requests_controller_spec.rb b/spec/controllers/projects/merge_requests_controller_spec.rb
index 962dfb91c9f..759a4b8bdce 100644
--- a/spec/controllers/projects/merge_requests_controller_spec.rb
+++ b/spec/controllers/projects/merge_requests_controller_spec.rb
@@ -30,19 +30,6 @@ describe Projects::MergeRequestsController do
end
end
- shared_examples "loads labels" do |action|
- it "loads labels into the @labels variable" do
- get action,
- params: {
- namespace_id: project.namespace.to_param,
- project_id: project,
- id: merge_request.iid
- },
- format: 'html'
- expect(assigns(:labels)).not_to be_nil
- end
- end
-
describe "GET show" do
def go(extra_params = {})
params = {
@@ -54,8 +41,6 @@ describe Projects::MergeRequestsController do
get :show, params: params.merge(extra_params)
end
- it_behaves_like "loads labels", :show
-
describe 'as html' do
context 'when diff files were cleaned' do
render_views
@@ -333,7 +318,7 @@ describe Projects::MergeRequestsController do
before do
project.add_reporter(user)
- xhr :post, :merge, params: base_params
+ post :merge, params: base_params, xhr: true
end
it 'returns 404' do
@@ -681,13 +666,14 @@ describe Projects::MergeRequestsController do
merge_request.title = merge_request.wip_title
merge_request.save
- xhr :post, :remove_wip,
- format: :json,
+ post :remove_wip,
params: {
+ format: :json,
namespace_id: merge_request.project.namespace.to_param,
project_id: merge_request.project,
id: merge_request.iid
- }
+ },
+ xhr: true
end
it 'removes the wip status' do
@@ -701,13 +687,14 @@ describe Projects::MergeRequestsController do
describe 'POST cancel_merge_when_pipeline_succeeds' do
subject do
- xhr :post, :cancel_merge_when_pipeline_succeeds,
- format: :json,
+ post :cancel_merge_when_pipeline_succeeds,
params: {
+ format: :json,
namespace_id: merge_request.project.namespace.to_param,
project_id: merge_request.project,
id: merge_request.iid
- }
+ },
+ xhr: true
end
it 'calls MergeRequests::MergeWhenPipelineSucceedsService' do
diff --git a/spec/controllers/projects/project_members_controller_spec.rb b/spec/controllers/projects/project_members_controller_spec.rb
index 009f85903b5..3cc3fe69fba 100644
--- a/spec/controllers/projects/project_members_controller_spec.rb
+++ b/spec/controllers/projects/project_members_controller_spec.rb
@@ -82,10 +82,12 @@ describe Projects::ProjectMembersController do
Gitlab::Access.options.each do |label, value|
it "can change the access level to #{label}" do
- xhr :put, :update, project_member: { access_level: value },
- namespace_id: project.namespace,
- project_id: project,
- id: requester
+ put :update, params: {
+ project_member: { access_level: value },
+ namespace_id: project.namespace,
+ project_id: project,
+ id: requester
+ }, xhr: true
expect(requester.reload.human_access).to eq(label)
end
@@ -148,9 +150,11 @@ describe Projects::ProjectMembersController do
end
it '[JS] removes user from members' do
- xhr :delete, :destroy, namespace_id: project.namespace,
- project_id: project,
- id: member
+ delete :destroy, params: {
+ namespace_id: project.namespace,
+ project_id: project,
+ id: member
+ }, xhr: true
expect(response).to be_success
expect(project.members).not_to include member
diff --git a/spec/controllers/projects/refs_controller_spec.rb b/spec/controllers/projects/refs_controller_spec.rb
index ea299e1e8c5..62f2af947e4 100644
--- a/spec/controllers/projects/refs_controller_spec.rb
+++ b/spec/controllers/projects/refs_controller_spec.rb
@@ -22,13 +22,13 @@ describe Projects::RefsController do
end
def xhr_get(format = :html)
- xhr :get,
- :logs_tree,
- namespace_id: project.namespace.to_param,
- project_id: project,
- id: 'master',
- path: 'foo/bar/baz.html',
- format: format
+ get :logs_tree, params: {
+ namespace_id: project.namespace.to_param,
+ project_id: project,
+ id: 'master',
+ path: 'foo/bar/baz.html',
+ format: format
+ }, xhr: true
end
it 'never throws MissingTemplate' do
diff --git a/spec/controllers/projects/tags/releases_controller_spec.rb b/spec/controllers/projects/tags/releases_controller_spec.rb
index 6bf4ac65a45..29f206c574b 100644
--- a/spec/controllers/projects/tags/releases_controller_spec.rb
+++ b/spec/controllers/projects/tags/releases_controller_spec.rb
@@ -18,7 +18,7 @@ describe Projects::Tags::ReleasesController do
tag_id = release.tag
project.releases.destroy_all # rubocop: disable DestroyAll
- get :edit, namespace_id: project.namespace, project_id: project, tag_id: tag_id
+ get :edit, params: { namespace_id: project.namespace, project_id: project, tag_id: tag_id }
release = assigns(:release)
expect(release).not_to be_nil
@@ -26,7 +26,7 @@ describe Projects::Tags::ReleasesController do
end
it 'retrieves an existing release' do
- get :edit, namespace_id: project.namespace, project_id: project, tag_id: release.tag
+ get :edit, params: { namespace_id: project.namespace, project_id: project, tag_id: release.tag }
release = assigns(:release)
expect(release).not_to be_nil
@@ -48,10 +48,11 @@ describe Projects::Tags::ReleasesController do
end
def update_release(description)
- put :update,
+ put :update, params: {
namespace_id: project.namespace.to_param,
project_id: project,
tag_id: release.tag,
release: { description: description }
+ }
end
end
diff --git a/spec/factories/notes.rb b/spec/factories/notes.rb
index 2d1f48bf249..c51f2f958f9 100644
--- a/spec/factories/notes.rb
+++ b/spec/factories/notes.rb
@@ -64,6 +64,21 @@ FactoryBot.define do
resolved_at { Time.now }
resolved_by { create(:user) }
end
+
+ factory :image_diff_note_on_merge_request do
+ position do
+ Gitlab::Diff::Position.new(
+ old_path: "files/images/any_image.png",
+ new_path: "files/images/any_image.png",
+ width: 10,
+ height: 10,
+ x: 1,
+ y: 1,
+ diff_refs: diff_refs,
+ position_type: "image"
+ )
+ end
+ end
end
factory :diff_note_on_commit, traits: [:on_commit], class: DiffNote do
diff --git a/spec/factories/pool_repositories.rb b/spec/factories/pool_repositories.rb
index 265a4643f46..36e54cf44b4 100644
--- a/spec/factories/pool_repositories.rb
+++ b/spec/factories/pool_repositories.rb
@@ -15,6 +15,10 @@ FactoryBot.define do
state :failed
end
+ trait :obsolete do
+ state :obsolete
+ end
+
trait :ready do
state :ready
diff --git a/spec/features/admin/admin_disables_git_access_protocol_spec.rb b/spec/features/admin/admin_disables_git_access_protocol_spec.rb
index 91c22e7ad82..f066b088800 100644
--- a/spec/features/admin/admin_disables_git_access_protocol_spec.rb
+++ b/spec/features/admin/admin_disables_git_access_protocol_spec.rb
@@ -1,7 +1,8 @@
require 'rails_helper'
-describe 'Admin disables Git access protocol' do
+describe 'Admin disables Git access protocol', :js do
include StubENV
+ include MobileHelpers
let(:project) { create(:project, :empty_repo) }
let(:admin) { create(:admin) }
@@ -20,7 +21,24 @@ describe 'Admin disables Git access protocol' do
visit_project
expect(page).to have_content("git clone #{project.ssh_url_to_repo}")
- expect(page).not_to have_selector('#clone-dropdown')
+
+ find('.clone-dropdown-btn').click
+
+ within('.git-clone-holder') do
+ expect(page).to have_content('Clone with SSH')
+ expect(page).not_to have_content('Clone with HTTP')
+ end
+ end
+
+ context 'mobile component' do
+ it 'shows only the SSH clone information' do
+ resize_screen_xs
+ visit_project
+ find('.dropdown-toggle').click
+
+ expect(page).to have_content('Copy SSH clone URL')
+ expect(page).not_to have_content('Copy HTTP clone URL')
+ end
end
end
@@ -31,9 +49,25 @@ describe 'Admin disables Git access protocol' do
it 'shows only HTTP url' do
visit_project
+ find('.clone-dropdown-btn').click
expect(page).to have_content("git clone #{project.http_url_to_repo}")
- expect(page).not_to have_selector('#clone-dropdown')
+
+ within('.git-clone-holder') do
+ expect(page).to have_content('Clone with HTTP')
+ expect(page).not_to have_content('Clone with SSH')
+ end
+ end
+
+ context 'mobile component' do
+ it 'shows only the HTTP clone information' do
+ resize_screen_xs
+ visit_project
+ find('.dropdown-toggle').click
+
+ expect(page).to have_content('Copy HTTP clone URL')
+ expect(page).not_to have_content('Copy SSH clone URL')
+ end
end
end
@@ -46,7 +80,24 @@ describe 'Admin disables Git access protocol' do
visit_project
expect(page).to have_content("git clone #{project.ssh_url_to_repo}")
- expect(page).to have_selector('#clone-dropdown')
+
+ find('.clone-dropdown-btn').click
+
+ within('.git-clone-holder') do
+ expect(page).to have_content('Clone with SSH')
+ expect(page).to have_content('Clone with HTTP')
+ end
+ end
+
+ context 'mobile component' do
+ it 'shows both SSH and HTTP clone information' do
+ resize_screen_xs
+ visit_project
+ find('.dropdown-toggle').click
+
+ expect(page).to have_content('Copy HTTP clone URL')
+ expect(page).to have_content('Copy SSH clone URL')
+ end
end
end
diff --git a/spec/features/groups/show_spec.rb b/spec/features/groups/show_spec.rb
index 4e6f73ef58a..9671a4d8c49 100644
--- a/spec/features/groups/show_spec.rb
+++ b/spec/features/groups/show_spec.rb
@@ -65,7 +65,7 @@ describe 'Group show page' do
context 'when subgroups are supported', :js, :nested_groups do
before do
- allow(Group).to receive(:supports_nested_groups?) { true }
+ allow(Group).to receive(:supports_nested_objects?) { true }
visit path
end
@@ -76,7 +76,7 @@ describe 'Group show page' do
context 'when subgroups are not supported' do
before do
- allow(Group).to receive(:supports_nested_groups?) { false }
+ allow(Group).to receive(:supports_nested_objects?) { false }
visit path
end
diff --git a/spec/features/issues/user_creates_issue_spec.rb b/spec/features/issues/user_creates_issue_spec.rb
index 830d56035aa..e60486f6dcb 100644
--- a/spec/features/issues/user_creates_issue_spec.rb
+++ b/spec/features/issues/user_creates_issue_spec.rb
@@ -14,7 +14,7 @@ describe "User creates issue" do
visit(new_project_issue_path(project))
end
- it "creates issue" do
+ it "creates issue", :js do
page.within(".issue-form") do
expect(page).to have_no_content("Assign to")
.and have_no_content("Labels")
@@ -27,11 +27,15 @@ describe "User creates issue" do
issue_title = "500 error on profile"
fill_in("Title", with: issue_title)
+ first('.js-md').click
+ first('.qa-issuable-form-description').native.send_keys('Description')
+
click_button("Submit issue")
expect(page).to have_content(issue_title)
.and have_content(user.name)
.and have_content(project.name)
+ expect(page).to have_selector('strong', text: 'Description')
end
end
diff --git a/spec/features/projects/clusters/gcp_spec.rb b/spec/features/projects/clusters/gcp_spec.rb
index 3d17eb3a73a..06e30571336 100644
--- a/spec/features/projects/clusters/gcp_spec.rb
+++ b/spec/features/projects/clusters/gcp_spec.rb
@@ -130,7 +130,7 @@ describe 'Gcp Cluster', :js do
context 'when user changes cluster parameters' do
before do
- allow(ClusterPlatformConfigureWorker).to receive(:perform_async)
+ allow(ClusterConfigureWorker).to receive(:perform_async)
fill_in 'cluster_platform_kubernetes_attributes_namespace', with: 'my-namespace'
page.within('#js-cluster-details') { click_button 'Save changes' }
end
diff --git a/spec/features/projects/jobs_spec.rb b/spec/features/projects/jobs_spec.rb
index 651c02c7ecc..60f37f4b74a 100644
--- a/spec/features/projects/jobs_spec.rb
+++ b/spec/features/projects/jobs_spec.rb
@@ -351,8 +351,8 @@ describe 'Jobs', :clean_gitlab_redis_shared_state do
context 'when user is a maintainer' do
shared_examples 'no reveal button variables behavior' do
it 'renders a hidden value with no reveal values button', :js do
- expect(page).to have_content('Token')
- expect(page).to have_content('Variables')
+ expect(page).to have_content('Trigger token')
+ expect(page).to have_content('Trigger variables')
expect(page).not_to have_css('.js-reveal-variables')
@@ -389,8 +389,8 @@ describe 'Jobs', :clean_gitlab_redis_shared_state do
shared_examples 'reveal button variables behavior' do
it 'renders a hidden value with a reveal values button', :js do
- expect(page).to have_content('Token')
- expect(page).to have_content('Variables')
+ expect(page).to have_content('Trigger token')
+ expect(page).to have_content('Trigger variables')
expect(page).to have_css('.js-reveal-variables')
diff --git a/spec/features/users/overview_spec.rb b/spec/features/users/overview_spec.rb
index 34ed771340f..873de85708a 100644
--- a/spec/features/users/overview_spec.rb
+++ b/spec/features/users/overview_spec.rb
@@ -119,6 +119,12 @@ describe 'Overview tab on a user profile', :js do
it 'shows a link to the project list' do
expect(find('#js-overview .projects-block')).to have_selector('.js-view-all', visible: true)
end
+
+ it 'shows projects in "compact mode"' do
+ page.within('#js-overview .projects-block') do
+ expect(find('.js-projects-list-holder')).to have_selector('.compact')
+ end
+ end
end
describe 'user has more than ten personal projects' do
diff --git a/spec/fixtures/api/schemas/entities/issuable_sidebar_todo.json b/spec/fixtures/api/schemas/entities/issuable_sidebar_todo.json
new file mode 100644
index 00000000000..b77e60ece12
--- /dev/null
+++ b/spec/fixtures/api/schemas/entities/issuable_sidebar_todo.json
@@ -0,0 +1,8 @@
+{
+ "type": ["object", "null"],
+ "properties" : {
+ "id": { "type": "integer" },
+ "delete_path": { "type": "string" }
+ },
+ "additionalProperties": false
+}
diff --git a/spec/fixtures/api/schemas/entities/issue_sidebar.json b/spec/fixtures/api/schemas/entities/issue_sidebar.json
index 682e345d5f5..93adb493d1b 100644
--- a/spec/fixtures/api/schemas/entities/issue_sidebar.json
+++ b/spec/fixtures/api/schemas/entities/issue_sidebar.json
@@ -2,20 +2,46 @@
"type": "object",
"properties" : {
"id": { "type": "integer" },
- "iid": { "type": "integer" },
- "subscribed": { "type": "boolean" },
- "time_estimate": { "type": "integer" },
- "total_time_spent": { "type": "integer" },
- "human_time_estimate": { "type": ["integer", "null"] },
- "human_total_time_spent": { "type": ["integer", "null"] },
- "participants": {
- "type": "array",
- "items": { "$ref": "../public_api/v4/user/basic.json" }
+ "type": { "type": "string" },
+ "author_id": { "type": "integer" },
+ "project_id": { "type": "integer" },
+ "discussion_locked": { "type": ["boolean", "null"] },
+ "due_date": { "type": "date" },
+ "confidential": { "type": "boolean" },
+ "reference": { "type": "string" },
+ "current_user": {
+ "allOf": [
+ { "$ref": "../public_api/v4/user/basic.json" },
+ { "type": "object",
+ "properties" : {
+ "todo": { "$ref": "issuable_sidebar_todo.json" },
+ "can_edit": { "type": "boolean" },
+ "can_move": { "type": "boolean" },
+ "can_admin_label": { "type": "boolean" }
+ }
+ }
+ ]
+ },
+ "milestone": {
+ "oneOf": [
+ { "type": "null" },
+ { "$ref": "../public_api/v4/milestone.json" }
+ ]
},
- "assignees": {
+ "labels": {
"type": "array",
- "items": { "$ref": "../public_api/v4/user/basic.json" }
- }
- },
- "additionalProperties": false
+ "items": { "$ref": "label.json" }
+ },
+ "issuable_json_path": { "type": "string" },
+ "namespace_path": { "type": "string" },
+ "project_path": { "type": "string" },
+ "project_full_path": { "type": "string" },
+ "project_issuables_path": { "type": "string" },
+ "create_todo_path": { "type": "string" },
+ "project_milestones_path": { "type": "string" },
+ "project_labels_path": { "type": "string" },
+ "toggle_subscription_path": { "type": "string" },
+ "move_issue_path": { "type": "string" },
+ "projects_autocomplete_path": { "type": "string" }
+ }
}
diff --git a/spec/fixtures/api/schemas/entities/issue_sidebar_extras.json b/spec/fixtures/api/schemas/entities/issue_sidebar_extras.json
new file mode 100644
index 00000000000..11be903b083
--- /dev/null
+++ b/spec/fixtures/api/schemas/entities/issue_sidebar_extras.json
@@ -0,0 +1,18 @@
+{
+ "type": "object",
+ "properties" : {
+ "subscribed": { "type": "boolean" },
+ "time_estimate": { "type": "integer" },
+ "total_time_spent": { "type": "integer" },
+ "human_time_estimate": { "type": ["integer", "null"] },
+ "human_total_time_spent": { "type": ["integer", "null"] },
+ "participants": {
+ "type": "array",
+ "items": { "$ref": "../public_api/v4/user/basic.json" }
+ },
+ "assignees": {
+ "type": "array",
+ "items": { "$ref": "../public_api/v4/user/basic.json" }
+ }
+ }
+}
diff --git a/spec/fixtures/api/schemas/entities/merge_request_basic.json b/spec/fixtures/api/schemas/entities/merge_request_basic.json
index cf257ac00de..4c04c838cb8 100644
--- a/spec/fixtures/api/schemas/entities/merge_request_basic.json
+++ b/spec/fixtures/api/schemas/entities/merge_request_basic.json
@@ -4,15 +4,9 @@
"state": { "type": "string" },
"merge_status": { "type": "string" },
"source_branch_exists": { "type": "boolean" },
- "time_estimate": { "type": "integer" },
- "total_time_spent": { "type": "integer" },
- "human_time_estimate": { "type": ["string", "null"] },
- "human_total_time_spent": { "type": ["string", "null"] },
"merge_error": { "type": ["string", "null"] },
"rebase_in_progress": { "type": "boolean" },
"assignee_id": { "type": ["integer", "null"] },
- "subscribed": { "type": ["boolean", "null"] },
- "participants": { "type": "array" },
"allow_collaboration": { "type": "boolean"},
"allow_maintainer_to_push": { "type": "boolean"},
"assignee": {
diff --git a/spec/fixtures/api/schemas/entities/merge_request_sidebar.json b/spec/fixtures/api/schemas/entities/merge_request_sidebar.json
new file mode 100644
index 00000000000..7e9e048a9fd
--- /dev/null
+++ b/spec/fixtures/api/schemas/entities/merge_request_sidebar.json
@@ -0,0 +1,56 @@
+{
+ "type": "object",
+ "properties" : {
+ "id": { "type": "integer" },
+ "type": { "type": "string" },
+ "author_id": { "type": "integer" },
+ "project_id": { "type": "integer" },
+ "discussion_locked": { "type": ["boolean", "null"] },
+ "reference": { "type": "string" },
+ "current_user": {
+ "allOf": [
+ { "$ref": "../public_api/v4/user/basic.json" },
+ { "type": "object",
+ "properties" : {
+ "todo": { "$ref": "issuable_sidebar_todo.json" },
+ "can_edit": { "type": "boolean" },
+ "can_move": { "type": "boolean" },
+ "can_admin_label": { "type": "boolean" }
+ }
+ }
+ ]
+ },
+ "milestone": {
+ "oneOf": [
+ { "type": "null" },
+ { "$ref": "../public_api/v4/milestones.json" }
+ ]
+ },
+ "labels": {
+ "type": "array",
+ "items": { "$ref": "label.json" }
+ },
+ "assignee": {
+ "allOf": [
+ { "$ref": "../public_api/v4/user/basic.json" },
+ { "type": "object",
+ "properties" : {
+ "can_merge": { "type": "boolean" }
+ }
+ }
+ ]
+ },
+ "issuable_json_path": { "type": "string" },
+ "namespace_path": { "type": "string" },
+ "project_path": { "type": "string" },
+ "project_full_path": { "type": "string" },
+ "project_issuables_path": { "type": "string" },
+ "create_todo_path": { "type": "string" },
+ "project_milestones_path": { "type": "string" },
+ "project_labels_path": { "type": "string" },
+ "toggle_subscription_path": { "type": "string" },
+ "move_issue_path": { "type": "string" },
+ "projects_autocomplete_path": { "type": "string" }
+ },
+ "additionalProperties": false
+}
diff --git a/spec/fixtures/api/schemas/entities/merge_request_sidebar_extras.json b/spec/fixtures/api/schemas/entities/merge_request_sidebar_extras.json
new file mode 100644
index 00000000000..682e345d5f5
--- /dev/null
+++ b/spec/fixtures/api/schemas/entities/merge_request_sidebar_extras.json
@@ -0,0 +1,21 @@
+{
+ "type": "object",
+ "properties" : {
+ "id": { "type": "integer" },
+ "iid": { "type": "integer" },
+ "subscribed": { "type": "boolean" },
+ "time_estimate": { "type": "integer" },
+ "total_time_spent": { "type": "integer" },
+ "human_time_estimate": { "type": ["integer", "null"] },
+ "human_total_time_spent": { "type": ["integer", "null"] },
+ "participants": {
+ "type": "array",
+ "items": { "$ref": "../public_api/v4/user/basic.json" }
+ },
+ "assignees": {
+ "type": "array",
+ "items": { "$ref": "../public_api/v4/user/basic.json" }
+ }
+ },
+ "additionalProperties": false
+}
diff --git a/spec/fixtures/api/schemas/public_api/v4/milestone.json b/spec/fixtures/api/schemas/public_api/v4/milestone.json
new file mode 100644
index 00000000000..6ca2e88ae91
--- /dev/null
+++ b/spec/fixtures/api/schemas/public_api/v4/milestone.json
@@ -0,0 +1,22 @@
+{
+ "type": "object",
+ "properties" : {
+ "id": { "type": "integer" },
+ "iid": { "type": "integer" },
+ "project_id": { "type": ["integer", "null"] },
+ "group_id": { "type": ["integer", "null"] },
+ "title": { "type": "string" },
+ "description": { "type": ["string", "null"] },
+ "state": { "type": "string" },
+ "created_at": { "type": "date" },
+ "updated_at": { "type": "date" },
+ "start_date": { "type": "date" },
+ "due_date": { "type": "date" },
+ "web_url": { "type": "string" }
+ },
+ "required": [
+ "id", "iid", "title", "description", "state",
+ "state", "created_at", "updated_at", "start_date", "due_date"
+ ],
+ "additionalProperties": false
+}
diff --git a/spec/fixtures/api/schemas/public_api/v4/milestones.json b/spec/fixtures/api/schemas/public_api/v4/milestones.json
index 448e97d6c85..dcbc1910bfe 100644
--- a/spec/fixtures/api/schemas/public_api/v4/milestones.json
+++ b/spec/fixtures/api/schemas/public_api/v4/milestones.json
@@ -1,25 +1,6 @@
{
"type": "array",
"items": {
- "type": "object",
- "properties" : {
- "id": { "type": "integer" },
- "iid": { "type": "integer" },
- "project_id": { "type": ["integer", "null"] },
- "group_id": { "type": ["integer", "null"] },
- "title": { "type": "string" },
- "description": { "type": ["string", "null"] },
- "state": { "type": "string" },
- "created_at": { "type": "date" },
- "updated_at": { "type": "date" },
- "start_date": { "type": "date" },
- "due_date": { "type": "date" },
- "web_url": { "type": "string" }
- },
- "required": [
- "id", "iid", "title", "description", "state",
- "state", "created_at", "updated_at", "start_date", "due_date"
- ],
- "additionalProperties": false
+ "$ref": "./milestone.json"
}
}
diff --git a/spec/fixtures/symlink_export.tar.gz b/spec/fixtures/symlink_export.tar.gz
new file mode 100644
index 00000000000..f295f69c56c
--- /dev/null
+++ b/spec/fixtures/symlink_export.tar.gz
Binary files differ
diff --git a/spec/helpers/issuables_helper_spec.rb b/spec/helpers/issuables_helper_spec.rb
index 4af98bc3678..81231cca085 100644
--- a/spec/helpers/issuables_helper_spec.rb
+++ b/spec/helpers/issuables_helper_spec.rb
@@ -43,16 +43,19 @@ describe IssuablesHelper do
end
describe '#issuable_labels_tooltip' do
+ let(:label_entity) { LabelEntity.represent(label).as_json }
+ let(:label2_entity) { LabelEntity.represent(label2).as_json }
+
it 'returns label text with no labels' do
expect(issuable_labels_tooltip([])).to eq("Labels")
end
it 'returns label text with labels within max limit' do
- expect(issuable_labels_tooltip([label])).to eq(label.title)
+ expect(issuable_labels_tooltip([label_entity])).to eq(label[:title])
end
it 'returns label text with labels exceeding max limit' do
- expect(issuable_labels_tooltip([label, label2], limit: 1)).to eq("#{label.title}, and 1 more")
+ expect(issuable_labels_tooltip([label_entity, label2_entity], limit: 1)).to eq("#{label[:title]}, and 1 more")
end
end
@@ -197,33 +200,4 @@ describe IssuablesHelper do
expect(helper.issuable_initial_data(issue)).to eq(expected_data)
end
end
-
- describe '#selected_labels' do
- context 'if label_name param is a string' do
- it 'returns a new label with title' do
- allow(helper).to receive(:params)
- .and_return(ActionController::Parameters.new(label_name: 'test label'))
-
- labels = helper.selected_labels
-
- expect(labels).to be_an(Array)
- expect(labels.size).to eq(1)
- expect(labels.first.title).to eq('test label')
- end
- end
-
- context 'if label_name param is an array' do
- it 'returns a new label with title for each element' do
- allow(helper).to receive(:params)
- .and_return(ActionController::Parameters.new(label_name: ['test label 1', 'test label 2']))
-
- labels = helper.selected_labels
-
- expect(labels).to be_an(Array)
- expect(labels.size).to eq(2)
- expect(labels.first.title).to eq('test label 1')
- expect(labels.second.title).to eq('test label 2')
- end
- end
- end
end
diff --git a/spec/helpers/projects_helper_spec.rb b/spec/helpers/projects_helper_spec.rb
index 486416c3370..edd680ee1d1 100644
--- a/spec/helpers/projects_helper_spec.rb
+++ b/spec/helpers/projects_helper_spec.rb
@@ -519,4 +519,114 @@ describe ProjectsHelper do
expect(helper.legacy_render_context({})).to be_empty
end
end
+
+ describe '#explore_projects_tab?' do
+ subject { helper.explore_projects_tab? }
+
+ it 'returns true when on the "All" tab under "Explore projects"' do
+ allow(@request).to receive(:path) { explore_projects_path }
+
+ expect(subject).to be_truthy
+ end
+
+ it 'returns true when on the "Trending" tab under "Explore projects"' do
+ allow(@request).to receive(:path) { trending_explore_projects_path }
+
+ expect(subject).to be_truthy
+ end
+
+ it 'returns true when on the "Starred" tab under "Explore projects"' do
+ allow(@request).to receive(:path) { starred_explore_projects_path }
+
+ expect(subject).to be_truthy
+ end
+
+ it 'returns false when on the "Your projects" tab' do
+ allow(@request).to receive(:path) { dashboard_projects_path }
+
+ expect(subject).to be_falsey
+ end
+ end
+
+ describe '#show_merge_request_count' do
+ context 'when the feature flag is enabled' do
+ before do
+ stub_feature_flags(project_list_show_mr_count: true)
+ end
+
+ it 'returns true if compact mode is disabled' do
+ expect(helper.show_merge_request_count?).to be_truthy
+ end
+
+ it 'returns false if compact mode is enabled' do
+ expect(helper.show_merge_request_count?(compact_mode: true)).to be_falsey
+ end
+ end
+
+ context 'when the feature flag is disabled' do
+ before do
+ stub_feature_flags(project_list_show_mr_count: false)
+ end
+
+ it 'always returns false' do
+ expect(helper.show_merge_request_count?(disabled: false)).to be_falsy
+ expect(helper.show_merge_request_count?(disabled: true)).to be_falsy
+ end
+ end
+
+ context 'disabled flag' do
+ before do
+ stub_feature_flags(project_list_show_mr_count: true)
+ end
+
+ it 'returns false if disabled flag is true' do
+ expect(helper.show_merge_request_count?(disabled: true)).to be_falsey
+ end
+
+ it 'returns true if disabled flag is false' do
+ expect(helper.show_merge_request_count?).to be_truthy
+ end
+ end
+ end
+
+ describe '#show_issue_count?' do
+ context 'when the feature flag is enabled' do
+ before do
+ stub_feature_flags(project_list_show_issue_count: true)
+ end
+
+ it 'returns true if compact mode is disabled' do
+ expect(helper.show_issue_count?).to be_truthy
+ end
+
+ it 'returns false if compact mode is enabled' do
+ expect(helper.show_issue_count?(compact_mode: true)).to be_falsey
+ end
+ end
+
+ context 'when the feature flag is disabled' do
+ before do
+ stub_feature_flags(project_list_show_issue_count: false)
+ end
+
+ it 'always returns false' do
+ expect(helper.show_issue_count?(disabled: false)).to be_falsy
+ expect(helper.show_issue_count?(disabled: true)).to be_falsy
+ end
+ end
+
+ context 'disabled flag' do
+ before do
+ stub_feature_flags(project_list_show_issue_count: true)
+ end
+
+ it 'returns false if disabled flag is true' do
+ expect(helper.show_issue_count?(disabled: true)).to be_falsey
+ end
+
+ it 'returns true if disabled flag is false' do
+ expect(helper.show_issue_count?).to be_truthy
+ end
+ end
+ end
end
diff --git a/spec/initializers/8_metrics_spec.rb b/spec/initializers/zz_metrics_spec.rb
index 80c77057065..3eaccfe8d8b 100644
--- a/spec/initializers/8_metrics_spec.rb
+++ b/spec/initializers/zz_metrics_spec.rb
@@ -16,7 +16,7 @@ describe 'instrument_classes' do
end
it 'can autoload and instrument all files' do
- require_relative '../../config/initializers/8_metrics'
+ require_relative '../../config/initializers/zz_metrics'
expect { instrument_classes(config) }.not_to raise_error
end
end
diff --git a/spec/javascripts/ci_variable_list/ci_variable_list_spec.js b/spec/javascripts/ci_variable_list/ci_variable_list_spec.js
index 30b15011def..bef59b86d0c 100644
--- a/spec/javascripts/ci_variable_list/ci_variable_list_spec.js
+++ b/spec/javascripts/ci_variable_list/ci_variable_list_spec.js
@@ -118,6 +118,8 @@ describe('VariableList', () => {
loadFixtures('projects/ci_cd_settings.html.raw');
$wrapper = $('.js-ci-variable-list-section');
+ $wrapper.find('.js-ci-variable-input-protected').attr('data-default', 'false');
+
variableList = new VariableList({
container: $wrapper,
formField: 'variables',
diff --git a/spec/javascripts/diffs/store/utils_spec.js b/spec/javascripts/diffs/store/utils_spec.js
index f096638e3d6..4268634d302 100644
--- a/spec/javascripts/diffs/store/utils_spec.js
+++ b/spec/javascripts/diffs/store/utils_spec.js
@@ -294,10 +294,14 @@ describe('DiffsStoreUtils', () => {
});
describe('prepareDiffData', () => {
- it('sets the renderIt and collapsed attribute on files', () => {
- const preparedDiff = { diff_files: [getDiffFileMock()] };
+ let preparedDiff;
+
+ beforeEach(() => {
+ preparedDiff = { diff_files: [getDiffFileMock()] };
utils.prepareDiffData(preparedDiff);
+ });
+ it('sets the renderIt and collapsed attribute on files', () => {
const firstParallelDiffLine = preparedDiff.diff_files[0].parallel_diff_lines[2];
expect(firstParallelDiffLine.left.discussions.length).toBe(0);
@@ -323,6 +327,18 @@ describe('DiffsStoreUtils', () => {
expect(preparedDiff.diff_files[0].renderIt).toBeTruthy();
expect(preparedDiff.diff_files[0].collapsed).toBeFalsy();
});
+
+ it('adds line_code to all lines', () => {
+ expect(
+ preparedDiff.diff_files[0].parallel_diff_lines.filter(line => !line.line_code),
+ ).toHaveLength(0);
+ });
+
+ it('uses right line code if left has none', () => {
+ const firstLine = preparedDiff.diff_files[0].parallel_diff_lines[0];
+
+ expect(firstLine.line_code).toEqual(firstLine.right.line_code);
+ });
});
describe('isDiscussionApplicableToLine', () => {
diff --git a/spec/javascripts/environments/environment_terminal_button_spec.js b/spec/javascripts/environments/environment_terminal_button_spec.js
index f1576b19d1b..56e18db59c5 100644
--- a/spec/javascripts/environments/environment_terminal_button_spec.js
+++ b/spec/javascripts/environments/environment_terminal_button_spec.js
@@ -2,30 +2,46 @@ import Vue from 'vue';
import terminalComp from '~/environments/components/environment_terminal_button.vue';
describe('Stop Component', () => {
- let TerminalComponent;
let component;
const terminalPath = '/path';
- beforeEach(() => {
- TerminalComponent = Vue.extend(terminalComp);
-
+ const mountWithProps = props => {
+ const TerminalComponent = Vue.extend(terminalComp);
component = new TerminalComponent({
- propsData: {
- terminalPath,
- },
+ propsData: props,
}).$mount();
- });
+ };
+
+ describe('enabled', () => {
+ beforeEach(() => {
+ mountWithProps({ terminalPath });
+ });
+
+ describe('computed', () => {
+ it('title', () => {
+ expect(component.title).toEqual('Terminal');
+ });
+ });
- describe('computed', () => {
- it('title', () => {
- expect(component.title).toEqual('Terminal');
+ it('should render a link to open a web terminal with the provided path', () => {
+ expect(component.$el.tagName).toEqual('A');
+ expect(component.$el.getAttribute('data-original-title')).toEqual('Terminal');
+ expect(component.$el.getAttribute('aria-label')).toEqual('Terminal');
+ expect(component.$el.getAttribute('href')).toEqual(terminalPath);
+ });
+
+ it('should render a non-disabled button', () => {
+ expect(component.$el.classList).not.toContain('disabled');
});
});
- it('should render a link to open a web terminal with the provided path', () => {
- expect(component.$el.tagName).toEqual('A');
- expect(component.$el.getAttribute('data-original-title')).toEqual('Terminal');
- expect(component.$el.getAttribute('aria-label')).toEqual('Terminal');
- expect(component.$el.getAttribute('href')).toEqual(terminalPath);
+ describe('disabled', () => {
+ beforeEach(() => {
+ mountWithProps({ terminalPath, disabled: true });
+ });
+
+ it('should render a disabled button', () => {
+ expect(component.$el.classList).toContain('disabled');
+ });
});
});
diff --git a/spec/javascripts/fixtures/blob.rb b/spec/javascripts/fixtures/blob.rb
index 81e8a51a902..1b2a3b484bb 100644
--- a/spec/javascripts/fixtures/blob.rb
+++ b/spec/javascripts/fixtures/blob.rb
@@ -22,10 +22,11 @@ describe Projects::BlobController, '(JavaScript fixtures)', type: :controller do
end
it 'blob/show.html.raw' do |example|
- get(:show,
- namespace_id: project.namespace,
- project_id: project,
- id: 'add-ipython-files/files/ipython/basic.ipynb')
+ get(:show, params: {
+ namespace_id: project.namespace,
+ project_id: project,
+ id: 'add-ipython-files/files/ipython/basic.ipynb'
+ })
expect(response).to be_success
store_frontend_fixture(response, example.description)
diff --git a/spec/javascripts/fixtures/boards.rb b/spec/javascripts/fixtures/boards.rb
index 494c9cabdcc..1d675e008ba 100644
--- a/spec/javascripts/fixtures/boards.rb
+++ b/spec/javascripts/fixtures/boards.rb
@@ -18,9 +18,10 @@ describe Projects::BoardsController, '(JavaScript fixtures)', type: :controller
end
it 'boards/show.html.raw' do |example|
- get(:index,
- namespace_id: project.namespace,
- project_id: project)
+ get(:index, params: {
+ namespace_id: project.namespace,
+ project_id: project
+ })
expect(response).to be_success
store_frontend_fixture(response, example.description)
diff --git a/spec/javascripts/fixtures/branches.rb b/spec/javascripts/fixtures/branches.rb
index 4fc072d2585..3cc713ef90f 100644
--- a/spec/javascripts/fixtures/branches.rb
+++ b/spec/javascripts/fixtures/branches.rb
@@ -22,9 +22,10 @@ describe Projects::BranchesController, '(JavaScript fixtures)', type: :controlle
end
it 'branches/new_branch.html.raw' do |example|
- get :new,
+ get :new, params: {
namespace_id: project.namespace.to_param,
project_id: project
+ }
expect(response).to be_success
store_frontend_fixture(response, example.description)
diff --git a/spec/javascripts/fixtures/clusters.rb b/spec/javascripts/fixtures/clusters.rb
index 8e74c4f859c..69dbe54ffc2 100644
--- a/spec/javascripts/fixtures/clusters.rb
+++ b/spec/javascripts/fixtures/clusters.rb
@@ -23,10 +23,11 @@ describe Projects::ClustersController, '(JavaScript fixtures)', type: :controlle
end
it 'clusters/show_cluster.html.raw' do |example|
- get :show,
+ get :show, params: {
namespace_id: project.namespace.to_param,
project_id: project,
id: cluster
+ }
expect(response).to be_success
store_frontend_fixture(response, example.description)
diff --git a/spec/javascripts/fixtures/commit.rb b/spec/javascripts/fixtures/commit.rb
index 24ab8159a18..f0e4bb50c67 100644
--- a/spec/javascripts/fixtures/commit.rb
+++ b/spec/javascripts/fixtures/commit.rb
@@ -25,7 +25,7 @@ describe Projects::CommitController, '(JavaScript fixtures)', type: :controller
id: commit.id
}
- get :show, params
+ get :show, params: params
expect(response).to be_success
store_frontend_fixture(response, example.description)
diff --git a/spec/javascripts/fixtures/deploy_keys.rb b/spec/javascripts/fixtures/deploy_keys.rb
index 24699c3043a..efbda955972 100644
--- a/spec/javascripts/fixtures/deploy_keys.rb
+++ b/spec/javascripts/fixtures/deploy_keys.rb
@@ -33,10 +33,10 @@ describe Projects::DeployKeysController, '(JavaScript fixtures)', type: :control
create(:deploy_keys_project, project: project3, deploy_key: project_key)
create(:deploy_keys_project, project: project4, deploy_key: project_key)
- get :index,
+ get :index, params: {
namespace_id: project.namespace.to_param,
- project_id: project,
- format: :json
+ project_id: project
+ }, format: :json
expect(response).to be_success
store_frontend_fixture(response, example.description)
diff --git a/spec/javascripts/fixtures/groups.rb b/spec/javascripts/fixtures/groups.rb
index b42f442557c..f8d55fc97c3 100644
--- a/spec/javascripts/fixtures/groups.rb
+++ b/spec/javascripts/fixtures/groups.rb
@@ -19,8 +19,7 @@ describe 'Groups (JavaScript fixtures)', type: :controller do
describe GroupsController, '(JavaScript fixtures)', type: :controller do
it 'groups/edit.html.raw' do |example|
- get :edit,
- id: group
+ get :edit, params: { id: group }
expect(response).to be_success
store_frontend_fixture(response, example.description)
@@ -29,8 +28,7 @@ describe 'Groups (JavaScript fixtures)', type: :controller do
describe Groups::Settings::CiCdController, '(JavaScript fixtures)', type: :controller do
it 'groups/ci_cd_settings.html.raw' do |example|
- get :show,
- group_id: group
+ get :show, params: { group_id: group }
expect(response).to be_success
store_frontend_fixture(response, example.description)
diff --git a/spec/javascripts/fixtures/issues.rb b/spec/javascripts/fixtures/issues.rb
index 0ee2f82dfd6..18fb1bebf8b 100644
--- a/spec/javascripts/fixtures/issues.rb
+++ b/spec/javascripts/fixtures/issues.rb
@@ -43,9 +43,10 @@ describe Projects::IssuesController, '(JavaScript fixtures)', type: :controller
it 'issues/issue_list.html.raw' do |example|
create(:issue, project: project)
- get :index,
+ get :index, params: {
namespace_id: project.namespace.to_param,
project_id: project
+ }
expect(response).to be_success
store_frontend_fixture(response, example.description)
@@ -54,10 +55,11 @@ describe Projects::IssuesController, '(JavaScript fixtures)', type: :controller
private
def render_issue(fixture_file_name, issue)
- get :show,
+ get :show, params: {
namespace_id: project.namespace.to_param,
project_id: project,
id: issue.to_param
+ }
expect(response).to be_success
store_frontend_fixture(response, fixture_file_name)
diff --git a/spec/javascripts/fixtures/jobs.rb b/spec/javascripts/fixtures/jobs.rb
index 82d7a5e394e..d6b5349594d 100644
--- a/spec/javascripts/fixtures/jobs.rb
+++ b/spec/javascripts/fixtures/jobs.rb
@@ -34,21 +34,22 @@ describe Projects::JobsController, '(JavaScript fixtures)', type: :controller do
end
it 'builds/build-with-artifacts.html.raw' do |example|
- get :show,
+ get :show, params: {
namespace_id: project.namespace.to_param,
project_id: project,
id: build_with_artifacts.to_param
+ }
expect(response).to be_success
store_frontend_fixture(response, example.description)
end
it 'jobs/delayed.json' do |example|
- get :show,
- namespace_id: project.namespace.to_param,
- project_id: project,
- id: delayed_job.to_param,
- format: :json
+ get :show, params: {
+ namespace_id: project.namespace.to_param,
+ project_id: project,
+ id: delayed_job.to_param
+ }, format: :json
expect(response).to be_success
store_frontend_fixture(response, example.description)
diff --git a/spec/javascripts/fixtures/labels.rb b/spec/javascripts/fixtures/labels.rb
index b730d557e21..9420194e675 100644
--- a/spec/javascripts/fixtures/labels.rb
+++ b/spec/javascripts/fixtures/labels.rb
@@ -31,9 +31,9 @@ describe 'Labels (JavaScript fixtures)' do
end
it 'labels/group_labels.json' do |example|
- get :index,
- group_id: group,
- format: 'json'
+ get :index, params: {
+ group_id: group
+ }, format: 'json'
expect(response).to be_success
store_frontend_fixture(response, example.description)
@@ -48,10 +48,10 @@ describe 'Labels (JavaScript fixtures)' do
end
it 'labels/project_labels.json' do |example|
- get :index,
+ get :index, params: {
namespace_id: group,
- project_id: project,
- format: 'json'
+ project_id: project
+ }, format: 'json'
expect(response).to be_success
store_frontend_fixture(response, example.description)
diff --git a/spec/javascripts/fixtures/merge_requests.rb b/spec/javascripts/fixtures/merge_requests.rb
index 7257d0c8556..26e81f06c0b 100644
--- a/spec/javascripts/fixtures/merge_requests.rb
+++ b/spec/javascripts/fixtures/merge_requests.rb
@@ -112,21 +112,21 @@ describe Projects::MergeRequestsController, '(JavaScript fixtures)', type: :cont
private
def render_discussions_json(merge_request, fixture_file_name)
- get :discussions,
+ get :discussions, params: {
namespace_id: project.namespace.to_param,
project_id: project,
- id: merge_request.to_param,
- format: :json
+ id: merge_request.to_param
+ }, format: :json
store_frontend_fixture(response, fixture_file_name)
end
def render_merge_request(fixture_file_name, merge_request)
- get :show,
+ get :show, params: {
namespace_id: project.namespace.to_param,
project_id: project,
- id: merge_request.to_param,
- format: :html
+ id: merge_request.to_param
+ }, format: :html
expect(response).to be_success
store_frontend_fixture(response, fixture_file_name)
diff --git a/spec/javascripts/fixtures/merge_requests_diffs.rb b/spec/javascripts/fixtures/merge_requests_diffs.rb
index afe34b834b0..57462e74bb2 100644
--- a/spec/javascripts/fixtures/merge_requests_diffs.rb
+++ b/spec/javascripts/fixtures/merge_requests_diffs.rb
@@ -57,13 +57,13 @@ describe Projects::MergeRequests::DiffsController, '(JavaScript fixtures)', type
private
def render_merge_request(fixture_file_name, merge_request, view: 'inline', **extra_params)
- get :show,
+ get :show, params: {
namespace_id: project.namespace.to_param,
project_id: project,
id: merge_request.to_param,
- format: :json,
view: view,
**extra_params
+ }, format: :json
expect(response).to be_success
store_frontend_fixture(response, fixture_file_name)
diff --git a/spec/javascripts/fixtures/pipeline_schedules.rb b/spec/javascripts/fixtures/pipeline_schedules.rb
index 56f27ea7df1..05d79ec8de9 100644
--- a/spec/javascripts/fixtures/pipeline_schedules.rb
+++ b/spec/javascripts/fixtures/pipeline_schedules.rb
@@ -22,20 +22,22 @@ describe Projects::PipelineSchedulesController, '(JavaScript fixtures)', type: :
end
it 'pipeline_schedules/edit.html.raw' do |example|
- get :edit,
+ get :edit, params: {
namespace_id: project.namespace.to_param,
project_id: project,
id: pipeline_schedule.id
+ }
expect(response).to be_success
store_frontend_fixture(response, example.description)
end
it 'pipeline_schedules/edit_with_variables.html.raw' do |example|
- get :edit,
+ get :edit, params: {
namespace_id: project.namespace.to_param,
project_id: project,
id: pipeline_schedule_populated.id
+ }
expect(response).to be_success
store_frontend_fixture(response, example.description)
diff --git a/spec/javascripts/fixtures/pipelines.rb b/spec/javascripts/fixtures/pipelines.rb
index bb85da50f0f..42b552e81c0 100644
--- a/spec/javascripts/fixtures/pipelines.rb
+++ b/spec/javascripts/fixtures/pipelines.rb
@@ -24,10 +24,10 @@ describe Projects::PipelinesController, '(JavaScript fixtures)', type: :controll
end
it 'pipelines/pipelines.json' do |example|
- get :index,
+ get :index, params: {
namespace_id: namespace,
- project_id: project,
- format: :json
+ project_id: project
+ }, format: :json
expect(response).to be_success
store_frontend_fixture(response, example.description)
diff --git a/spec/javascripts/fixtures/projects.rb b/spec/javascripts/fixtures/projects.rb
index d98f7f55b20..9b48646f8f0 100644
--- a/spec/javascripts/fixtures/projects.rb
+++ b/spec/javascripts/fixtures/projects.rb
@@ -28,27 +28,30 @@ describe 'Projects (JavaScript fixtures)', type: :controller do
describe ProjectsController, '(JavaScript fixtures)', type: :controller do
it 'projects/dashboard.html.raw' do |example|
- get :show,
+ get :show, params: {
namespace_id: project.namespace.to_param,
id: project
+ }
expect(response).to be_success
store_frontend_fixture(response, example.description)
end
it 'projects/overview.html.raw' do |example|
- get :show,
+ get :show, params: {
namespace_id: project_with_repo.namespace.to_param,
id: project_with_repo
+ }
expect(response).to be_success
store_frontend_fixture(response, example.description)
end
it 'projects/edit.html.raw' do |example|
- get :edit,
+ get :edit, params: {
namespace_id: project.namespace.to_param,
id: project
+ }
expect(response).to be_success
store_frontend_fixture(response, example.description)
@@ -57,18 +60,20 @@ describe 'Projects (JavaScript fixtures)', type: :controller do
describe Projects::Settings::CiCdController, '(JavaScript fixtures)', type: :controller do
it 'projects/ci_cd_settings.html.raw' do |example|
- get :show,
+ get :show, params: {
namespace_id: project.namespace.to_param,
project_id: project
+ }
expect(response).to be_success
store_frontend_fixture(response, example.description)
end
it 'projects/ci_cd_settings_with_variables.html.raw' do |example|
- get :show,
+ get :show, params: {
namespace_id: project_variable_populated.namespace.to_param,
project_id: project_variable_populated
+ }
expect(response).to be_success
store_frontend_fixture(response, example.description)
diff --git a/spec/javascripts/fixtures/prometheus_service.rb b/spec/javascripts/fixtures/prometheus_service.rb
index f95f8038ffb..746fbfd66dd 100644
--- a/spec/javascripts/fixtures/prometheus_service.rb
+++ b/spec/javascripts/fixtures/prometheus_service.rb
@@ -23,10 +23,11 @@ describe Projects::ServicesController, '(JavaScript fixtures)', type: :controlle
end
it 'services/prometheus/prometheus_service.html.raw' do |example|
- get :edit,
+ get :edit, params: {
namespace_id: namespace,
project_id: project,
id: service.to_param
+ }
expect(response).to be_success
store_frontend_fixture(response, example.description)
diff --git a/spec/javascripts/fixtures/services.rb b/spec/javascripts/fixtures/services.rb
index 9280ed5a7f1..6ccd74a07ff 100644
--- a/spec/javascripts/fixtures/services.rb
+++ b/spec/javascripts/fixtures/services.rb
@@ -23,10 +23,11 @@ describe Projects::ServicesController, '(JavaScript fixtures)', type: :controlle
end
it 'services/edit_service.html.raw' do |example|
- get :edit,
+ get :edit, params: {
namespace_id: namespace,
project_id: project,
id: service.to_param
+ }
expect(response).to be_success
store_frontend_fixture(response, example.description)
diff --git a/spec/javascripts/fixtures/snippet.rb b/spec/javascripts/fixtures/snippet.rb
index 38fc963caf7..a14837e4d4a 100644
--- a/spec/javascripts/fixtures/snippet.rb
+++ b/spec/javascripts/fixtures/snippet.rb
@@ -24,7 +24,7 @@ describe SnippetsController, '(JavaScript fixtures)', type: :controller do
end
it 'snippets/show.html.raw' do |example|
- get(:show, id: snippet.to_param)
+ get(:show, params: { id: snippet.to_param })
expect(response).to be_success
store_frontend_fixture(response, example.description)
diff --git a/spec/javascripts/fixtures/todos.rb b/spec/javascripts/fixtures/todos.rb
index 426b854fe8b..b5f6620873b 100644
--- a/spec/javascripts/fixtures/todos.rb
+++ b/spec/javascripts/fixtures/todos.rb
@@ -42,12 +42,12 @@ describe 'Todos (JavaScript fixtures)' do
end
it 'todos/todos.json' do |example|
- post :create,
+ post :create, params: {
namespace_id: namespace,
project_id: project,
issuable_type: 'issue',
- issuable_id: issue_2.id,
- format: 'json'
+ issuable_id: issue_2.id
+ }, format: 'json'
expect(response).to be_success
store_frontend_fixture(response, example.description)
diff --git a/spec/javascripts/fixtures/u2f.rb b/spec/javascripts/fixtures/u2f.rb
index e3d7986f2cf..f0aa874bf75 100644
--- a/spec/javascripts/fixtures/u2f.rb
+++ b/spec/javascripts/fixtures/u2f.rb
@@ -21,7 +21,7 @@ context 'U2F' do
it 'u2f/authenticate.html.raw' do |example|
allow(controller).to receive(:find_user).and_return(user)
- post :create, user: { login: user.username, password: user.password }
+ post :create, params: { user: { login: user.username, password: user.password } }
expect(response).to be_success
store_frontend_fixture(response, example.description)
diff --git a/spec/javascripts/jobs/components/artifacts_block_spec.js b/spec/javascripts/jobs/components/artifacts_block_spec.js
index 2fa7ff653fe..27d480ef2ea 100644
--- a/spec/javascripts/jobs/components/artifacts_block_spec.js
+++ b/spec/javascripts/jobs/components/artifacts_block_spec.js
@@ -2,6 +2,7 @@ import Vue from 'vue';
import { getTimeago } from '~/lib/utils/datetime_utility';
import component from '~/jobs/components/artifacts_block.vue';
import mountComponent from '../../helpers/vue_mount_component_helper';
+import { trimText } from '../../helpers/vue_component_helper';
describe('Artifacts block', () => {
const Component = Vue.extend(component);
@@ -9,7 +10,7 @@ describe('Artifacts block', () => {
const expireAt = '2018-08-14T09:38:49.157Z';
const timeago = getTimeago();
- const formatedDate = timeago.format(expireAt);
+ const formattedDate = timeago.format(expireAt);
const expiredArtifact = {
expire_at: expireAt,
@@ -36,9 +37,8 @@ describe('Artifacts block', () => {
expect(vm.$el.querySelector('.js-artifacts-removed')).not.toBeNull();
expect(vm.$el.querySelector('.js-artifacts-will-be-removed')).toBeNull();
- expect(vm.$el.textContent).toContain(formatedDate);
- expect(vm.$el.querySelector('.js-artifacts-removed').textContent.trim()).toEqual(
- 'The artifacts were removed',
+ expect(trimText(vm.$el.querySelector('.js-artifacts-removed').textContent)).toEqual(
+ `The artifacts were removed ${formattedDate}`,
);
});
});
@@ -51,9 +51,8 @@ describe('Artifacts block', () => {
expect(vm.$el.querySelector('.js-artifacts-removed')).toBeNull();
expect(vm.$el.querySelector('.js-artifacts-will-be-removed')).not.toBeNull();
- expect(vm.$el.textContent).toContain(formatedDate);
- expect(vm.$el.querySelector('.js-artifacts-will-be-removed').textContent.trim()).toEqual(
- 'The artifacts will be removed in',
+ expect(trimText(vm.$el.querySelector('.js-artifacts-will-be-removed').textContent)).toEqual(
+ `The artifacts will be removed ${formattedDate}`,
);
});
});
diff --git a/spec/javascripts/jobs/components/sidebar_spec.js b/spec/javascripts/jobs/components/sidebar_spec.js
index 424092d2d88..b0bc16d7c64 100644
--- a/spec/javascripts/jobs/components/sidebar_spec.js
+++ b/spec/javascripts/jobs/components/sidebar_spec.js
@@ -79,14 +79,6 @@ describe('Sidebar details block', () => {
});
describe('information', () => {
- it('should render merge request link', () => {
- expect(trimText(vm.$el.querySelector('.js-job-mr').textContent)).toEqual('Merge Request: !2');
-
- expect(vm.$el.querySelector('.js-job-mr a').getAttribute('href')).toEqual(
- job.merge_request.path,
- );
- });
-
it('should render job duration', () => {
expect(trimText(vm.$el.querySelector('.js-job-duration').textContent)).toEqual(
'Duration: 6 seconds',
diff --git a/spec/javascripts/notes/components/noteable_discussion_spec.js b/spec/javascripts/notes/components/noteable_discussion_spec.js
index 106a4ac2546..3aff2dd0641 100644
--- a/spec/javascripts/notes/components/noteable_discussion_spec.js
+++ b/spec/javascripts/notes/components/noteable_discussion_spec.js
@@ -133,8 +133,10 @@ describe('noteable_discussion component', () => {
});
});
- describe('commit discussion', () => {
+ describe('action text', () => {
const commitId = 'razupaltuff';
+ const truncatedCommitId = commitId.substr(0, 8);
+ let commitElement;
beforeEach(() => {
vm.$destroy();
@@ -143,7 +145,6 @@ describe('noteable_discussion component', () => {
projectPath: 'something',
};
- vm.$destroy();
vm = new Component({
propsData: {
discussion: {
@@ -159,17 +160,73 @@ describe('noteable_discussion component', () => {
},
store,
}).$mount();
+
+ commitElement = vm.$el.querySelector('.commit-sha');
+ });
+
+ describe('for commit discussions', () => {
+ it('should display a monospace started a discussion on commit', () => {
+ expect(vm.$el).toContainText(`started a discussion on commit ${truncatedCommitId}`);
+ expect(commitElement).not.toBe(null);
+ expect(commitElement).toHaveText(truncatedCommitId);
+ });
});
- it('displays a monospace started a discussion on commit', () => {
- const truncatedCommitId = commitId.substr(0, 8);
+ describe('for diff discussion with a commit id', () => {
+ it('should display started discussion on commit header', done => {
+ vm.discussion.for_commit = false;
- expect(vm.$el).toContainText(`started a discussion on commit ${truncatedCommitId}`);
+ vm.$nextTick(() => {
+ expect(vm.$el).toContainText(`started a discussion on commit ${truncatedCommitId}`);
+ expect(commitElement).not.toBe(null);
- const commitElement = vm.$el.querySelector('.commit-sha');
+ done();
+ });
+ });
- expect(commitElement).not.toBe(null);
- expect(commitElement).toHaveText(truncatedCommitId);
+ it('should display outdated change on commit header', done => {
+ vm.discussion.for_commit = false;
+ vm.discussion.active = false;
+
+ vm.$nextTick(() => {
+ expect(vm.$el).toContainText(
+ `started a discussion on an outdated change in commit ${truncatedCommitId}`,
+ );
+
+ expect(commitElement).not.toBe(null);
+
+ done();
+ });
+ });
+ });
+
+ describe('for diff discussions without a commit id', () => {
+ it('should show started a discussion on the diff text', done => {
+ Object.assign(vm.discussion, {
+ for_commit: false,
+ commit_id: null,
+ });
+
+ vm.$nextTick(() => {
+ expect(vm.$el).toContainText('started a discussion on the diff');
+
+ done();
+ });
+ });
+
+ it('should show discussion on older version text', done => {
+ Object.assign(vm.discussion, {
+ for_commit: false,
+ commit_id: null,
+ active: false,
+ });
+
+ vm.$nextTick(() => {
+ expect(vm.$el).toContainText('started a discussion on an old version of the diff');
+
+ done();
+ });
+ });
});
});
});
diff --git a/spec/javascripts/releases/components/app_spec.js b/spec/javascripts/releases/components/app_spec.js
new file mode 100644
index 00000000000..f30c7685e34
--- /dev/null
+++ b/spec/javascripts/releases/components/app_spec.js
@@ -0,0 +1,79 @@
+import Vue from 'vue';
+import app from '~/releases/components/app.vue';
+import createStore from '~/releases/store';
+import api from '~/api';
+import { mountComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
+import { resetStore } from '../store/helpers';
+import { releases } from '../mock_data';
+
+describe('Releases App ', () => {
+ const Component = Vue.extend(app);
+ let store;
+ let vm;
+
+ const props = {
+ projectId: 'gitlab-ce',
+ documentationLink: 'help/releases',
+ illustrationPath: 'illustration/path',
+ };
+
+ beforeEach(() => {
+ store = createStore();
+ });
+
+ afterEach(() => {
+ resetStore(store);
+ vm.$destroy();
+ });
+
+ describe('while loading', () => {
+ beforeEach(() => {
+ spyOn(api, 'releases').and.returnValue(Promise.resolve({ data: [] }));
+ vm = mountComponentWithStore(Component, { props, store });
+ });
+
+ it('renders loading icon', done => {
+ expect(vm.$el.querySelector('.js-loading')).not.toBeNull();
+ expect(vm.$el.querySelector('.js-empty-state')).toBeNull();
+ expect(vm.$el.querySelector('.js-success-state')).toBeNull();
+
+ setTimeout(() => {
+ done();
+ }, 0);
+ });
+ });
+
+ describe('with successful request', () => {
+ beforeEach(() => {
+ spyOn(api, 'releases').and.returnValue(Promise.resolve({ data: releases }));
+ vm = mountComponentWithStore(Component, { props, store });
+ });
+
+ it('renders success state', done => {
+ setTimeout(() => {
+ expect(vm.$el.querySelector('.js-loading')).toBeNull();
+ expect(vm.$el.querySelector('.js-empty-state')).toBeNull();
+ expect(vm.$el.querySelector('.js-success-state')).not.toBeNull();
+
+ done();
+ }, 0);
+ });
+ });
+
+ describe('with empty request', () => {
+ beforeEach(() => {
+ spyOn(api, 'releases').and.returnValue(Promise.resolve({ data: [] }));
+ vm = mountComponentWithStore(Component, { props, store });
+ });
+
+ it('renders empty state', done => {
+ setTimeout(() => {
+ expect(vm.$el.querySelector('.js-loading')).toBeNull();
+ expect(vm.$el.querySelector('.js-empty-state')).not.toBeNull();
+ expect(vm.$el.querySelector('.js-success-state')).toBeNull();
+
+ done();
+ }, 0);
+ });
+ });
+});
diff --git a/spec/javascripts/releases/components/release_block_spec.js b/spec/javascripts/releases/components/release_block_spec.js
index c0cd15b7507..29420216bc4 100644
--- a/spec/javascripts/releases/components/release_block_spec.js
+++ b/spec/javascripts/releases/components/release_block_spec.js
@@ -15,6 +15,16 @@ describe('Release block', () => {
author_name: 'Release bot',
author_email: 'release-bot@example.com',
created_at: '2012-05-28T05:00:00-07:00',
+ author: {
+ avatar_url: 'uploads/-/system/user/avatar/johndoe/avatar.png',
+ id: 482476,
+ name: 'John Doe',
+ path: '/johndoe',
+ state: 'active',
+ status_tooltip_html: null,
+ username: 'johndoe',
+ web_url: 'https://gitlab.com/johndoe',
+ },
commit: {
id: '2695effb5807a22ff3d138d593fd856244e155e7',
short_id: '2695effb',
@@ -66,32 +76,10 @@ describe('Release block', () => {
],
},
};
-
- const props = {
- name: release.name,
- tag: release.tag_name,
- commit: release.commit,
- description: release.description_html,
- author: {
- avatar_url: 'uploads/-/system/user/avatar/johndoe/avatar.png',
- id: 482476,
- name: 'John Doe',
- path: '/johndoe',
- state: 'active',
- status_tooltip_html: null,
- username: 'johndoe',
- web_url: 'https://gitlab.com/johndoe',
- },
- createdAt: release.created_at,
- assetsCount: release.assets.count,
- sources: release.assets.sources,
- links: release.assets.links,
- };
-
let vm;
beforeEach(() => {
- vm = mountComponent(Component, props);
+ vm = mountComponent(Component, { release });
});
afterEach(() => {
diff --git a/spec/javascripts/releases/mock_data.js b/spec/javascripts/releases/mock_data.js
new file mode 100644
index 00000000000..2855eca1711
--- /dev/null
+++ b/spec/javascripts/releases/mock_data.js
@@ -0,0 +1,128 @@
+export const release = {
+ name: 'Bionic Beaver',
+ tag_name: '18.04',
+ description: '## changelog\n\n* line 1\n* line2',
+ description_html: '<div><h2>changelog</h2><ul><li>line1</li<li>line 2</li></ul></div>',
+ author_name: 'Release bot',
+ author_email: 'release-bot@example.com',
+ created_at: '2012-05-28T05:00:00-07:00',
+ commit: {
+ id: '2695effb5807a22ff3d138d593fd856244e155e7',
+ short_id: '2695effb',
+ title: 'Initial commit',
+ created_at: '2017-07-26T11:08:53.000+02:00',
+ parent_ids: ['2a4b78934375d7f53875269ffd4f45fd83a84ebe'],
+ message: 'Initial commit',
+ author: {
+ avatar_url: 'uploads/-/system/user/avatar/johndoe/avatar.png',
+ id: 482476,
+ name: 'John Doe',
+ path: '/johndoe',
+ state: 'active',
+ status_tooltip_html: null,
+ username: 'johndoe',
+ web_url: 'https://gitlab.com/johndoe',
+ },
+ authored_date: '2012-05-28T04:42:42-07:00',
+ committer_name: 'Jack Smith',
+ committer_email: 'jack@example.com',
+ committed_date: '2012-05-28T04:42:42-07:00',
+ },
+ assets: {
+ count: 6,
+ sources: [
+ {
+ format: 'zip',
+ url: 'https://gitlab.com/gitlab-org/gitlab-ce/-/archive/v11.3.12/gitlab-ce-v11.3.12.zip',
+ },
+ {
+ format: 'tar.gz',
+ url: 'https://gitlab.com/gitlab-org/gitlab-ce/-/archive/v11.3.12/gitlab-ce-v11.3.12.tar.gz',
+ },
+ {
+ format: 'tar.bz2',
+ url:
+ 'https://gitlab.com/gitlab-org/gitlab-ce/-/archive/v11.3.12/gitlab-ce-v11.3.12.tar.bz2',
+ },
+ {
+ format: 'tar',
+ url: 'https://gitlab.com/gitlab-org/gitlab-ce/-/archive/v11.3.12/gitlab-ce-v11.3.12.tar',
+ },
+ ],
+ links: [
+ {
+ name: 'release-18.04.dmg',
+ url: 'https://my-external-hosting.example.com/scrambled-url/',
+ external: true,
+ },
+ {
+ name: 'binary-linux-amd64',
+ url:
+ 'https://gitlab.com/gitlab-org/gitlab-ce/-/jobs/artifacts/v11.6.0-rc4/download?job=rspec-mysql+41%2F50',
+ external: false,
+ },
+ ],
+ },
+};
+
+export const releases = [
+ release,
+ {
+ name: 'JoJos Bizarre Adventure',
+ tag_name: '19.00',
+ description: '## changelog\n\n* line 1\n* line2',
+ description_html: '<div><h2>changelog</h2><ul><li>line1</li<li>line 2</li></ul></div>',
+ author_name: 'Release bot',
+ author_email: 'release-bot@example.com',
+ created_at: '2012-05-28T05:00:00-07:00',
+ commit: {
+ id: '2695effb5807a22ff3d138d593fd856244e155e7',
+ short_id: '2695effb',
+ title: 'Initial commit',
+ created_at: '2017-07-26T11:08:53.000+02:00',
+ parent_ids: ['2a4b78934375d7f53875269ffd4f45fd83a84ebe'],
+ message: 'Initial commit',
+ author: {
+ avatar_url: 'uploads/-/system/user/avatar/johndoe/avatar.png',
+ id: 482476,
+ name: 'John Doe',
+ path: '/johndoe',
+ state: 'active',
+ status_tooltip_html: null,
+ username: 'johndoe',
+ web_url: 'https://gitlab.com/johndoe',
+ },
+ authored_date: '2012-05-28T04:42:42-07:00',
+ committer_name: 'Jack Smith',
+ committer_email: 'jack@example.com',
+ committed_date: '2012-05-28T04:42:42-07:00',
+ },
+ assets: {
+ count: 4,
+ sources: [
+ {
+ format: 'tar.gz',
+ url:
+ 'https://gitlab.com/gitlab-org/gitlab-ce/-/archive/v11.3.12/gitlab-ce-v11.3.12.tar.gz',
+ },
+ {
+ format: 'tar.bz2',
+ url:
+ 'https://gitlab.com/gitlab-org/gitlab-ce/-/archive/v11.3.12/gitlab-ce-v11.3.12.tar.bz2',
+ },
+ {
+ format: 'tar',
+ url: 'https://gitlab.com/gitlab-org/gitlab-ce/-/archive/v11.3.12/gitlab-ce-v11.3.12.tar',
+ },
+ ],
+ links: [
+ {
+ name: 'binary-linux-amd64',
+ url:
+ 'https://gitlab.com/gitlab-org/gitlab-ce/-/jobs/artifacts/v11.6.0-rc4/download?job=rspec-mysql+41%2F50',
+ external: false,
+ },
+ ],
+ },
+ },
+];
diff --git a/spec/javascripts/releases/store/actions_spec.js b/spec/javascripts/releases/store/actions_spec.js
new file mode 100644
index 00000000000..6eb8e681be9
--- /dev/null
+++ b/spec/javascripts/releases/store/actions_spec.js
@@ -0,0 +1,98 @@
+import {
+ requestReleases,
+ fetchReleases,
+ receiveReleasesSuccess,
+ receiveReleasesError,
+} from '~/releases/store/actions';
+import state from '~/releases/store/state';
+import * as types from '~/releases/store/mutation_types';
+import api from '~/api';
+import testAction from 'spec/helpers/vuex_action_helper';
+import { releases } from '../mock_data';
+
+describe('Releases State actions', () => {
+ let mockedState;
+
+ beforeEach(() => {
+ mockedState = state();
+ });
+
+ describe('requestReleases', () => {
+ it('should commit REQUEST_RELEASES mutation', done => {
+ testAction(requestReleases, null, mockedState, [{ type: types.REQUEST_RELEASES }], [], done);
+ });
+ });
+
+ describe('fetchReleases', () => {
+ describe('success', () => {
+ it('dispatches requestReleases and receiveReleasesSuccess ', done => {
+ spyOn(api, 'releases').and.returnValue(Promise.resolve({ data: releases }));
+
+ testAction(
+ fetchReleases,
+ releases,
+ mockedState,
+ [],
+ [
+ {
+ type: 'requestReleases',
+ },
+ {
+ payload: releases,
+ type: 'receiveReleasesSuccess',
+ },
+ ],
+ done,
+ );
+ });
+ });
+
+ describe('error', () => {
+ it('dispatches requestReleases and receiveReleasesError ', done => {
+ spyOn(api, 'releases').and.returnValue(Promise.reject());
+
+ testAction(
+ fetchReleases,
+ null,
+ mockedState,
+ [],
+ [
+ {
+ type: 'requestReleases',
+ },
+ {
+ type: 'receiveReleasesError',
+ },
+ ],
+ done,
+ );
+ });
+ });
+ });
+
+ describe('receiveReleasesSuccess', () => {
+ it('should commit RECEIVE_RELEASES_SUCCESS mutation', done => {
+ testAction(
+ receiveReleasesSuccess,
+ releases,
+ mockedState,
+ [{ type: types.RECEIVE_RELEASES_SUCCESS, payload: releases }],
+ [],
+ done,
+ );
+ });
+ });
+
+ describe('receiveReleasesError', () => {
+ it('should commit RECEIVE_RELEASES_ERROR mutation', done => {
+ testAction(
+ receiveReleasesError,
+ null,
+ mockedState,
+ [{ type: types.RECEIVE_RELEASES_ERROR }],
+ [],
+ done,
+ );
+ });
+ });
+});
diff --git a/spec/javascripts/releases/store/helpers.js b/spec/javascripts/releases/store/helpers.js
new file mode 100644
index 00000000000..e962b254377
--- /dev/null
+++ b/spec/javascripts/releases/store/helpers.js
@@ -0,0 +1,6 @@
+import state from '~/releases/store/state';
+
+// eslint-disable-next-line import/prefer-default-export
+export const resetStore = store => {
+ store.replaceState(state());
+};
diff --git a/spec/javascripts/releases/store/mutations_spec.js b/spec/javascripts/releases/store/mutations_spec.js
new file mode 100644
index 00000000000..72b98529fe9
--- /dev/null
+++ b/spec/javascripts/releases/store/mutations_spec.js
@@ -0,0 +1,47 @@
+import state from '~/releases/store/state';
+import mutations from '~/releases/store/mutations';
+import * as types from '~/releases/store/mutation_types';
+import { releases } from '../mock_data';
+
+describe('Releases Store Mutations', () => {
+ let stateCopy;
+
+ beforeEach(() => {
+ stateCopy = state();
+ });
+
+ describe('REQUEST_RELEASES', () => {
+ it('sets isLoading to true', () => {
+ mutations[types.REQUEST_RELEASES](stateCopy);
+
+ expect(stateCopy.isLoading).toEqual(true);
+ });
+ });
+
+ describe('RECEIVE_RELEASES_SUCCESS', () => {
+ beforeEach(() => {
+ mutations[types.RECEIVE_RELEASES_SUCCESS](stateCopy, releases);
+ });
+
+ it('sets is loading to false', () => {
+ expect(stateCopy.isLoading).toEqual(false);
+ });
+
+ it('sets hasError to false', () => {
+ expect(stateCopy.hasError).toEqual(false);
+ });
+
+ it('sets data', () => {
+ expect(stateCopy.releases).toEqual(releases);
+ });
+ });
+
+ describe('RECEIVE_RELEASES_ERROR', () => {
+ it('resets data', () => {
+ mutations[types.RECEIVE_RELEASES_ERROR](stateCopy);
+
+ expect(stateCopy.isLoading).toEqual(false);
+ expect(stateCopy.releases).toEqual([]);
+ });
+ });
+});
diff --git a/spec/javascripts/sidebar/mock_data.js b/spec/javascripts/sidebar/mock_data.js
index fcd7bea3f6d..7f20b0da991 100644
--- a/spec/javascripts/sidebar/mock_data.js
+++ b/spec/javascripts/sidebar/mock_data.js
@@ -66,7 +66,7 @@ const RESPONSE_MAP = {
},
labels: [],
},
- '/gitlab-org/gitlab-shell/issues/5.json?serializer=sidebar': {
+ '/gitlab-org/gitlab-shell/issues/5.json?serializer=sidebar_extras': {
assignees: [
{
name: 'User 0',
@@ -181,7 +181,7 @@ const RESPONSE_MAP = {
const mockData = {
responseMap: RESPONSE_MAP,
mediator: {
- endpoint: '/gitlab-org/gitlab-shell/issues/5.json?serializer=sidebar',
+ endpoint: '/gitlab-org/gitlab-shell/issues/5.json?serializer=sidebar_extras',
toggleSubscriptionEndpoint: '/gitlab-org/gitlab-shell/issues/5/toggle_subscription',
moveIssueEndpoint: '/gitlab-org/gitlab-shell/issues/5/move',
projectsAutocompleteEndpoint: '/autocomplete/projects?project_id=15',
diff --git a/spec/javascripts/sidebar/sidebar_mediator_spec.js b/spec/javascripts/sidebar/sidebar_mediator_spec.js
index 2d853970fc4..6c69c08e733 100644
--- a/spec/javascripts/sidebar/sidebar_mediator_spec.js
+++ b/spec/javascripts/sidebar/sidebar_mediator_spec.js
@@ -37,7 +37,7 @@ describe('Sidebar mediator', function() {
it('fetches the data', done => {
const mockData =
- Mock.responseMap.GET['/gitlab-org/gitlab-shell/issues/5.json?serializer=sidebar'];
+ Mock.responseMap.GET['/gitlab-org/gitlab-shell/issues/5.json?serializer=sidebar_extras'];
spyOn(this.mediator, 'processFetchedData').and.callThrough();
this.mediator
@@ -51,7 +51,7 @@ describe('Sidebar mediator', function() {
it('processes fetched data', () => {
const mockData =
- Mock.responseMap.GET['/gitlab-org/gitlab-shell/issues/5.json?serializer=sidebar'];
+ Mock.responseMap.GET['/gitlab-org/gitlab-shell/issues/5.json?serializer=sidebar_extras'];
this.mediator.processFetchedData(mockData);
expect(this.mediator.store.assignees).toEqual(mockData.assignees);
diff --git a/spec/javascripts/vue_shared/components/user_popover/user_popover_spec.js b/spec/javascripts/vue_shared/components/user_popover/user_popover_spec.js
index e16ab156679..25b6e3b6bc8 100644
--- a/spec/javascripts/vue_shared/components/user_popover/user_popover_spec.js
+++ b/spec/javascripts/vue_shared/components/user_popover/user_popover_spec.js
@@ -89,7 +89,7 @@ describe('User Popover Component', () => {
expect(vm.$el.textContent).toContain('GitLab');
});
- it('should have full job line when we have bio and organization', () => {
+ it('should display bio and organization in separate lines', () => {
const testProps = Object.assign({}, DEFAULT_PROPS);
testProps.user.bio = 'Engineer';
testProps.user.organization = 'GitLab';
@@ -99,20 +99,24 @@ describe('User Popover Component', () => {
target: document.querySelector('.js-user-link'),
});
- expect(vm.$el.textContent).toContain('Engineer at GitLab');
+ expect(vm.$el.querySelector('.js-bio').textContent).toContain('Engineer');
+ expect(vm.$el.querySelector('.js-organization').textContent).toContain('GitLab');
});
- it('should not encode special characters when we have bio and organization', () => {
+ it('should not encode special characters in bio and organization', () => {
const testProps = Object.assign({}, DEFAULT_PROPS);
testProps.user.bio = 'Manager & Team Lead';
- testProps.user.organization = 'GitLab';
+ testProps.user.organization = 'Me & my <funky> Company';
vm = mountComponent(UserPopover, {
...DEFAULT_PROPS,
target: document.querySelector('.js-user-link'),
});
- expect(vm.$el.textContent).toContain('Manager & Team Lead at GitLab');
+ expect(vm.$el.querySelector('.js-bio').textContent).toContain('Manager & Team Lead');
+ expect(vm.$el.querySelector('.js-organization').textContent).toContain(
+ 'Me & my <funky> Company',
+ );
});
});
diff --git a/spec/lib/gitlab/bare_repository_import/importer_spec.rb b/spec/lib/gitlab/bare_repository_import/importer_spec.rb
index 3c63e601abc..f4759b69538 100644
--- a/spec/lib/gitlab/bare_repository_import/importer_spec.rb
+++ b/spec/lib/gitlab/bare_repository_import/importer_spec.rb
@@ -192,7 +192,7 @@ describe Gitlab::BareRepositoryImport::Importer, :seed_helper do
let(:project_path) { 'a-group/a-sub-group/a-project' }
before do
- expect(Group).to receive(:supports_nested_groups?) { false }
+ expect(Group).to receive(:supports_nested_objects?) { false }
end
describe '#create_project_if_needed' do
diff --git a/spec/lib/gitlab/gitaly_client_spec.rb b/spec/lib/gitlab/gitaly_client_spec.rb
index 5eda4d041a8..e41a75c37a7 100644
--- a/spec/lib/gitlab/gitaly_client_spec.rb
+++ b/spec/lib/gitlab/gitaly_client_spec.rb
@@ -3,6 +3,20 @@ require 'spec_helper'
# We stub Gitaly in `spec/support/gitaly.rb` for other tests. We don't want
# those stubs while testing the GitalyClient itself.
describe Gitlab::GitalyClient do
+ let(:sample_cert) { Rails.root.join('spec/fixtures/clusters/sample_cert.pem').to_s }
+
+ before do
+ allow(described_class)
+ .to receive(:stub_cert_paths)
+ .and_return([sample_cert])
+ end
+
+ def stub_repos_storages(address)
+ allow(Gitlab.config.repositories).to receive(:storages).and_return({
+ 'default' => { 'gitaly_address' => address }
+ })
+ end
+
describe '.stub_class' do
it 'returns the gRPC health check stub' do
expect(described_class.stub_class(:health_check)).to eq(::Grpc::Health::V1::Health::Stub)
@@ -15,12 +29,8 @@ describe Gitlab::GitalyClient do
describe '.stub_address' do
it 'returns the same result after being called multiple times' do
- address = 'localhost:9876'
- prefixed_address = "tcp://#{address}"
-
- allow(Gitlab.config.repositories).to receive(:storages).and_return({
- 'default' => { 'gitaly_address' => prefixed_address }
- })
+ address = 'tcp://localhost:9876'
+ stub_repos_storages address
2.times do
expect(described_class.stub_address('default')).to eq('localhost:9876')
@@ -28,6 +38,45 @@ describe Gitlab::GitalyClient do
end
end
+ describe '.stub_certs' do
+ it 'skips certificates if OpenSSLError is raised and report it' do
+ expect(Rails.logger).to receive(:error).at_least(:once)
+ expect(Gitlab::Sentry)
+ .to receive(:track_exception)
+ .with(
+ a_kind_of(OpenSSL::X509::CertificateError),
+ extra: { cert_file: a_kind_of(String) }).at_least(:once)
+
+ expect(OpenSSL::X509::Certificate)
+ .to receive(:new)
+ .and_raise(OpenSSL::X509::CertificateError).at_least(:once)
+
+ expect(described_class.stub_certs).to be_a(String)
+ end
+ end
+ describe '.stub_creds' do
+ it 'returns :this_channel_is_insecure if unix' do
+ address = 'unix:/tmp/gitaly.sock'
+ stub_repos_storages address
+
+ expect(described_class.stub_creds('default')).to eq(:this_channel_is_insecure)
+ end
+
+ it 'returns :this_channel_is_insecure if tcp' do
+ address = 'tcp://localhost:9876'
+ stub_repos_storages address
+
+ expect(described_class.stub_creds('default')).to eq(:this_channel_is_insecure)
+ end
+
+ it 'returns Credentials object if tls' do
+ address = 'tls://localhost:9876'
+ stub_repos_storages address
+
+ expect(described_class.stub_creds('default')).to be_a(GRPC::Core::ChannelCredentials)
+ end
+ end
+
describe '.stub' do
# Notice that this is referring to gRPC "stubs", not rspec stubs
before do
@@ -37,9 +86,19 @@ describe Gitlab::GitalyClient do
context 'when passed a UNIX socket address' do
it 'passes the address as-is to GRPC' do
address = 'unix:/tmp/gitaly.sock'
- allow(Gitlab.config.repositories).to receive(:storages).and_return({
- 'default' => { 'gitaly_address' => address }
- })
+ stub_repos_storages address
+
+ expect(Gitaly::CommitService::Stub).to receive(:new).with(address, any_args)
+
+ described_class.stub(:commit_service, 'default')
+ end
+ end
+
+ context 'when passed a TLS address' do
+ it 'strips tls:// prefix before passing it to GRPC::Core::Channel initializer' do
+ address = 'localhost:9876'
+ prefixed_address = "tls://#{address}"
+ stub_repos_storages prefixed_address
expect(Gitaly::CommitService::Stub).to receive(:new).with(address, any_args)
@@ -51,10 +110,7 @@ describe Gitlab::GitalyClient do
it 'strips tcp:// prefix before passing it to GRPC::Core::Channel initializer' do
address = 'localhost:9876'
prefixed_address = "tcp://#{address}"
-
- allow(Gitlab.config.repositories).to receive(:storages).and_return({
- 'default' => { 'gitaly_address' => prefixed_address }
- })
+ stub_repos_storages prefixed_address
expect(Gitaly::CommitService::Stub).to receive(:new).with(address, any_args)
diff --git a/spec/lib/gitlab/import_export/command_line_util_spec.rb b/spec/lib/gitlab/import_export/command_line_util_spec.rb
new file mode 100644
index 00000000000..8e5e0aefac0
--- /dev/null
+++ b/spec/lib/gitlab/import_export/command_line_util_spec.rb
@@ -0,0 +1,38 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Gitlab::ImportExport::CommandLineUtil do
+ include ExportFileHelper
+
+ let(:path) { "#{Dir.tmpdir}/symlink_test" }
+ let(:archive) { 'spec/fixtures/symlink_export.tar.gz' }
+ let(:shared) { Gitlab::ImportExport::Shared.new(nil) }
+
+ subject do
+ Class.new do
+ include Gitlab::ImportExport::CommandLineUtil
+
+ def initialize
+ @shared = Gitlab::ImportExport::Shared.new(nil)
+ end
+ end.new
+ end
+
+ before do
+ FileUtils.mkdir_p(path)
+ subject.untar_zxf(archive: archive, dir: path)
+ end
+
+ after do
+ FileUtils.rm_rf(path)
+ end
+
+ it 'has the right mask for project.json' do
+ expect(file_permissions("#{path}/project.json")).to eq(0755) # originally 777
+ end
+
+ it 'has the right mask for uploads' do
+ expect(file_permissions("#{path}/uploads")).to eq(0755) # originally 555
+ end
+end
diff --git a/spec/lib/gitlab/import_export/file_importer_spec.rb b/spec/lib/gitlab/import_export/file_importer_spec.rb
index bf34cefe18f..fbc9bcd2df5 100644
--- a/spec/lib/gitlab/import_export/file_importer_spec.rb
+++ b/spec/lib/gitlab/import_export/file_importer_spec.rb
@@ -1,6 +1,8 @@
require 'spec_helper'
describe Gitlab::ImportExport::FileImporter do
+ include ExportFileHelper
+
let(:shared) { Gitlab::ImportExport::Shared.new(nil) }
let(:storage_path) { "#{Dir.tmpdir}/file_importer_spec" }
let(:valid_file) { "#{shared.export_path}/valid.json" }
@@ -8,6 +10,7 @@ describe Gitlab::ImportExport::FileImporter do
let(:hidden_symlink_file) { "#{shared.export_path}/.hidden" }
let(:subfolder_symlink_file) { "#{shared.export_path}/subfolder/invalid.json" }
let(:evil_symlink_file) { "#{shared.export_path}/.\nevil" }
+ let(:custom_mode_symlink_file) { "#{shared.export_path}/symlink.mode" }
before do
stub_const('Gitlab::ImportExport::FileImporter::MAX_RETRIES', 0)
@@ -45,10 +48,18 @@ describe Gitlab::ImportExport::FileImporter do
expect(File.exist?(subfolder_symlink_file)).to be false
end
+ it 'removes symlinks without any file permissions' do
+ expect(File.exist?(custom_mode_symlink_file)).to be false
+ end
+
it 'does not remove a valid file' do
expect(File.exist?(valid_file)).to be true
end
+ it 'does not change a valid file permissions' do
+ expect(file_permissions(valid_file)).not_to eq(0000)
+ end
+
it 'creates the file in the right subfolder' do
expect(shared.export_path).to include('test/abcd')
end
@@ -84,5 +95,7 @@ describe Gitlab::ImportExport::FileImporter do
FileUtils.ln_s(valid_file, subfolder_symlink_file)
FileUtils.ln_s(valid_file, hidden_symlink_file)
FileUtils.ln_s(valid_file, evil_symlink_file)
+ FileUtils.ln_s(valid_file, custom_mode_symlink_file)
+ FileUtils.chmod_R(0000, custom_mode_symlink_file)
end
end
diff --git a/spec/lib/gitlab/json_cache_spec.rb b/spec/lib/gitlab/json_cache_spec.rb
new file mode 100644
index 00000000000..b52078e8556
--- /dev/null
+++ b/spec/lib/gitlab/json_cache_spec.rb
@@ -0,0 +1,401 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Gitlab::JsonCache do
+ let(:backend) { double('backend').as_null_object }
+ let(:namespace) { 'geo' }
+ let(:key) { 'foo' }
+ let(:expanded_key) { "#{namespace}:#{key}:#{Rails.version}" }
+ let(:broadcast_message) { create(:broadcast_message) }
+
+ subject(:cache) { described_class.new(namespace: namespace, backend: backend) }
+
+ describe '#active?' do
+ context 'when backend respond to active? method' do
+ it 'delegates to the underlying cache implementation' do
+ backend = double('backend', active?: false)
+
+ cache = described_class.new(namespace: namespace, backend: backend)
+
+ expect(cache.active?).to eq(false)
+ end
+ end
+
+ context 'when backend does not respond to active? method' do
+ it 'returns true' do
+ backend = double('backend')
+
+ cache = described_class.new(namespace: namespace, backend: backend)
+
+ expect(cache.active?).to eq(true)
+ end
+ end
+ end
+
+ describe '#cache_key' do
+ context 'when namespace is not defined' do
+ it 'expands out the key with Rails version' do
+ cache = described_class.new(cache_key_with_version: true)
+
+ cache_key = cache.cache_key(key)
+
+ expect(cache_key).to eq("#{key}:#{Rails.version}")
+ end
+ end
+
+ context 'when cache_key_with_version is true' do
+ it 'expands out the key with namespace and Rails version' do
+ cache = described_class.new(namespace: namespace, cache_key_with_version: true)
+
+ cache_key = cache.cache_key(key)
+
+ expect(cache_key).to eq("#{namespace}:#{key}:#{Rails.version}")
+ end
+ end
+
+ context 'when cache_key_with_version is false' do
+ it 'expands out the key with namespace' do
+ cache = described_class.new(namespace: namespace, cache_key_with_version: false)
+
+ cache_key = cache.cache_key(key)
+
+ expect(cache_key).to eq("#{namespace}:#{key}")
+ end
+ end
+
+ context 'when namespace is nil, and cache_key_with_version is false' do
+ it 'returns the key' do
+ cache = described_class.new(namespace: nil, cache_key_with_version: false)
+
+ cache_key = cache.cache_key(key)
+
+ expect(cache_key).to eq(key)
+ end
+ end
+ end
+
+ describe '#expire' do
+ it 'expires the given key from the cache' do
+ cache.expire(key)
+
+ expect(backend).to have_received(:delete).with(expanded_key)
+ end
+ end
+
+ describe '#read' do
+ it 'reads the given key from the cache' do
+ cache.read(key)
+
+ expect(backend).to have_received(:read).with(expanded_key)
+ end
+
+ it 'returns the cached value when there is data in the cache with the given key' do
+ allow(backend).to receive(:read)
+ .with(expanded_key)
+ .and_return("true")
+
+ expect(cache.read(key)).to eq(true)
+ end
+
+ it 'returns nil when there is no data in the cache with the given key' do
+ allow(backend).to receive(:read)
+ .with(expanded_key)
+ .and_return(nil)
+
+ expect(cache.read(key)).to be_nil
+ end
+
+ context 'when the cached value is a hash' do
+ it 'parses the cached value' do
+ allow(backend).to receive(:read)
+ .with(expanded_key)
+ .and_return(broadcast_message.to_json)
+
+ expect(cache.read(key, BroadcastMessage)).to eq(broadcast_message)
+ end
+
+ it 'returns nil when klass is nil' do
+ allow(backend).to receive(:read)
+ .with(expanded_key)
+ .and_return(broadcast_message.to_json)
+
+ expect(cache.read(key)).to be_nil
+ end
+
+ it 'gracefully handles bad cached entry' do
+ allow(backend).to receive(:read)
+ .with(expanded_key)
+ .and_return('{')
+
+ expect(cache.read(key, BroadcastMessage)).to be_nil
+ end
+
+ it 'gracefully handles an empty hash' do
+ allow(backend).to receive(:read)
+ .with(expanded_key)
+ .and_return('{}')
+
+ expect(cache.read(key, BroadcastMessage)).to be_a(BroadcastMessage)
+ end
+
+ it 'gracefully handles unknown attributes' do
+ allow(backend).to receive(:read)
+ .with(expanded_key)
+ .and_return(broadcast_message.attributes.merge(unknown_attribute: 1).to_json)
+
+ expect(cache.read(key, BroadcastMessage)).to be_nil
+ end
+ end
+
+ context 'when the cached value is an array' do
+ it 'parses the cached value' do
+ allow(backend).to receive(:read)
+ .with(expanded_key)
+ .and_return([broadcast_message].to_json)
+
+ expect(cache.read(key, BroadcastMessage)).to eq([broadcast_message])
+ end
+
+ it 'returns an empty array when klass is nil' do
+ allow(backend).to receive(:read)
+ .with(expanded_key)
+ .and_return([broadcast_message].to_json)
+
+ expect(cache.read(key)).to eq([])
+ end
+
+ it 'gracefully handles bad cached entry' do
+ allow(backend).to receive(:read)
+ .with(expanded_key)
+ .and_return('[')
+
+ expect(cache.read(key, BroadcastMessage)).to be_nil
+ end
+
+ it 'gracefully handles an empty array' do
+ allow(backend).to receive(:read)
+ .with(expanded_key)
+ .and_return('[]')
+
+ expect(cache.read(key, BroadcastMessage)).to eq([])
+ end
+
+ it 'gracefully handles unknown attributes' do
+ allow(backend).to receive(:read)
+ .with(expanded_key)
+ .and_return([{ unknown_attribute: 1 }, broadcast_message.attributes].to_json)
+
+ expect(cache.read(key, BroadcastMessage)).to eq([broadcast_message])
+ end
+ end
+ end
+
+ describe '#write' do
+ it 'writes value to the cache with the given key' do
+ cache.write(key, true)
+
+ expect(backend).to have_received(:write).with(expanded_key, "true", nil)
+ end
+
+ it 'writes a string containing a JSON representation of the value to the cache' do
+ cache.write(key, broadcast_message)
+
+ expect(backend).to have_received(:write)
+ .with(expanded_key, broadcast_message.to_json, nil)
+ end
+
+ it 'passes options the underlying cache implementation' do
+ cache.write(key, true, expires_in: 15.seconds)
+
+ expect(backend).to have_received(:write)
+ .with(expanded_key, "true", expires_in: 15.seconds)
+ end
+
+ it 'passes options the underlying cache implementation when options is empty' do
+ cache.write(key, true, {})
+
+ expect(backend).to have_received(:write)
+ .with(expanded_key, "true", {})
+ end
+
+ it 'passes options the underlying cache implementation when options is nil' do
+ cache.write(key, true, nil)
+
+ expect(backend).to have_received(:write)
+ .with(expanded_key, "true", nil)
+ end
+ end
+
+ describe '#fetch', :use_clean_rails_memory_store_caching do
+ let(:backend) { Rails.cache }
+
+ it 'requires a block' do
+ expect { cache.fetch(key) }.to raise_error(LocalJumpError)
+ end
+
+ it 'passes options the underlying cache implementation' do
+ expect(backend).to receive(:write)
+ .with(expanded_key, "true", expires_in: 15.seconds)
+
+ cache.fetch(key, expires_in: 15.seconds) { true }
+ end
+
+ context 'when the given key does not exist in the cache' do
+ context 'when the result of the block is truthy' do
+ it 'returns the result of the block' do
+ result = cache.fetch(key) { true }
+
+ expect(result).to eq(true)
+ end
+
+ it 'caches the value' do
+ expect(backend).to receive(:write).with(expanded_key, "true", {})
+
+ cache.fetch(key) { true }
+ end
+ end
+
+ context 'when the result of the block is false' do
+ it 'returns the result of the block' do
+ result = cache.fetch(key) { false }
+
+ expect(result).to eq(false)
+ end
+
+ it 'caches the value' do
+ expect(backend).to receive(:write).with(expanded_key, "false", {})
+
+ cache.fetch(key) { false }
+ end
+ end
+
+ context 'when the result of the block is nil' do
+ it 'returns the result of the block' do
+ result = cache.fetch(key) { nil }
+
+ expect(result).to eq(nil)
+ end
+
+ it 'caches the value' do
+ expect(backend).to receive(:write).with(expanded_key, "null", {})
+
+ cache.fetch(key) { nil }
+ end
+ end
+ end
+
+ context 'when the given key exists in the cache' do
+ context 'when the cached value is a hash' do
+ before do
+ backend.write(expanded_key, broadcast_message.to_json)
+ end
+
+ it 'parses the cached value' do
+ result = cache.fetch(key, as: BroadcastMessage) { 'block result' }
+
+ expect(result).to eq(broadcast_message)
+ end
+
+ it "returns the result of the block when 'as' option is nil" do
+ result = cache.fetch(key, as: nil) { 'block result' }
+
+ expect(result).to eq('block result')
+ end
+
+ it "returns the result of the block when 'as' option is not informed" do
+ result = cache.fetch(key) { 'block result' }
+
+ expect(result).to eq('block result')
+ end
+ end
+
+ context 'when the cached value is a array' do
+ before do
+ backend.write(expanded_key, [broadcast_message].to_json)
+ end
+
+ it 'parses the cached value' do
+ result = cache.fetch(key, as: BroadcastMessage) { 'block result' }
+
+ expect(result).to eq([broadcast_message])
+ end
+
+ it "returns an empty array when 'as' option is nil" do
+ result = cache.fetch(key, as: nil) { 'block result' }
+
+ expect(result).to eq([])
+ end
+
+ it "returns an empty array when 'as' option is not informed" do
+ result = cache.fetch(key) { 'block result' }
+
+ expect(result).to eq([])
+ end
+ end
+
+ context 'when the cached value is true' do
+ before do
+ backend.write(expanded_key, "true")
+ end
+
+ it 'returns the cached value' do
+ result = cache.fetch(key) { 'block result' }
+
+ expect(result).to eq(true)
+ end
+
+ it 'does not execute the block' do
+ expect { |block| cache.fetch(key, &block) }.not_to yield_control
+ end
+
+ it 'does not write to the cache' do
+ expect(backend).not_to receive(:write)
+
+ cache.fetch(key) { 'block result' }
+ end
+ end
+
+ context 'when the cached value is false' do
+ before do
+ backend.write(expanded_key, "false")
+ end
+
+ it 'returns the cached value' do
+ result = cache.fetch(key) { 'block result' }
+
+ expect(result).to eq(false)
+ end
+
+ it 'does not execute the block' do
+ expect { |block| cache.fetch(key, &block) }.not_to yield_control
+ end
+
+ it 'does not write to the cache' do
+ expect(backend).not_to receive(:write)
+
+ cache.fetch(key) { 'block result' }
+ end
+ end
+
+ context 'when the cached value is nil' do
+ before do
+ backend.write(expanded_key, "null")
+ end
+
+ it 'returns the result of the block' do
+ result = cache.fetch(key) { 'block result' }
+
+ expect(result).to eq('block result')
+ end
+
+ it 'writes the result of the block to the cache' do
+ expect(backend).to receive(:write)
+ .with(expanded_key, 'block result'.to_json, {})
+
+ cache.fetch(key) { 'block result' }
+ end
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/group_hierarchy_spec.rb b/spec/lib/gitlab/object_hierarchy_spec.rb
index f3de7adcec7..4700a7ad2e1 100644
--- a/spec/lib/gitlab/group_hierarchy_spec.rb
+++ b/spec/lib/gitlab/object_hierarchy_spec.rb
@@ -1,6 +1,6 @@
require 'spec_helper'
-describe Gitlab::GroupHierarchy, :postgresql do
+describe Gitlab::ObjectHierarchy, :postgresql do
let!(:parent) { create(:group) }
let!(:child1) { create(:group, parent: parent) }
let!(:child2) { create(:group, parent: child1) }
@@ -105,9 +105,9 @@ describe Gitlab::GroupHierarchy, :postgresql do
end
end
- describe '#all_groups' do
+ describe '#all_objects' do
let(:relation) do
- described_class.new(Group.where(id: child1.id)).all_groups
+ described_class.new(Group.where(id: child1.id)).all_objects
end
it 'includes the base rows' do
@@ -123,13 +123,13 @@ describe Gitlab::GroupHierarchy, :postgresql do
end
it 'uses ancestors_base #initialize argument for ancestors' do
- relation = described_class.new(Group.where(id: child1.id), Group.where(id: Group.maximum(:id).succ)).all_groups
+ relation = described_class.new(Group.where(id: child1.id), Group.where(id: Group.maximum(:id).succ)).all_objects
expect(relation).to include(parent)
end
it 'uses descendants_base #initialize argument for descendants' do
- relation = described_class.new(Group.where(id: Group.maximum(:id).succ), Group.where(id: child1.id)).all_groups
+ relation = described_class.new(Group.where(id: Group.maximum(:id).succ), Group.where(id: child1.id)).all_objects
expect(relation).to include(child2)
end
diff --git a/spec/lib/gitlab/project_authorizations_spec.rb b/spec/lib/gitlab/project_authorizations_spec.rb
index 00c62c7bf96..bd0bc2c9044 100644
--- a/spec/lib/gitlab/project_authorizations_spec.rb
+++ b/spec/lib/gitlab/project_authorizations_spec.rb
@@ -20,7 +20,7 @@ describe Gitlab::ProjectAuthorizations do
end
let(:authorizations) do
- klass = if Group.supports_nested_groups?
+ klass = if Group.supports_nested_objects?
Gitlab::ProjectAuthorizations::WithNestedGroups
else
Gitlab::ProjectAuthorizations::WithoutNestedGroups
@@ -46,7 +46,7 @@ describe Gitlab::ProjectAuthorizations do
expect(mapping[group_project.id]).to eq(Gitlab::Access::DEVELOPER)
end
- if Group.supports_nested_groups?
+ if Group.supports_nested_objects?
context 'with nested groups' do
let!(:nested_group) { create(:group, parent: group) }
let!(:nested_project) { create(:project, namespace: nested_group) }
diff --git a/spec/lib/gitlab/prometheus/query_variables_spec.rb b/spec/lib/gitlab/prometheus/query_variables_spec.rb
index 78974cadb69..78c74266c61 100644
--- a/spec/lib/gitlab/prometheus/query_variables_spec.rb
+++ b/spec/lib/gitlab/prometheus/query_variables_spec.rb
@@ -4,7 +4,7 @@ require 'spec_helper'
describe Gitlab::Prometheus::QueryVariables do
describe '.call' do
- set(:environment) { create(:environment) }
+ let(:environment) { create(:environment) }
let(:slug) { environment.slug }
subject { described_class.call(environment) }
@@ -20,7 +20,7 @@ describe Gitlab::Prometheus::QueryVariables do
it { is_expected.to include(kube_namespace: '') }
end
- context 'with deplyoment platform' do
+ context 'with deployment platform' do
let(:kube_namespace) { environment.deployment_platform.actual_namespace }
before do
diff --git a/spec/lib/gitlab/upgrader_spec.rb b/spec/lib/gitlab/upgrader_spec.rb
deleted file mode 100644
index 6106f13c774..00000000000
--- a/spec/lib/gitlab/upgrader_spec.rb
+++ /dev/null
@@ -1,40 +0,0 @@
-require 'spec_helper'
-
-describe Gitlab::Upgrader do
- let(:upgrader) { described_class.new }
- let(:current_version) { Gitlab::VERSION }
-
- describe 'current_version_raw' do
- it { expect(upgrader.current_version_raw).to eq(current_version) }
- end
-
- describe 'latest_version?' do
- it 'is true if newest version' do
- allow(upgrader).to receive(:latest_version_raw).and_return(current_version)
- expect(upgrader.latest_version?).to be_truthy
- end
- end
-
- describe 'latest_version_raw' do
- it 'is the latest version for GitLab 5' do
- allow(upgrader).to receive(:current_version_raw).and_return("5.3.0")
- expect(upgrader.latest_version_raw).to eq("v5.4.2")
- end
-
- it 'gets the latest version from tags' do
- allow(upgrader).to receive(:fetch_git_tags).and_return([
- '6f0733310546402c15d3ae6128a95052f6c8ea96 refs/tags/v7.1.1',
- 'facfec4b242ce151af224e20715d58e628aa5e74 refs/tags/v7.1.1^{}',
- 'f7068d99c79cf79befbd388030c051bb4b5e86d4 refs/tags/v7.10.4',
- '337225a4fcfa9674e2528cb6d41c46556bba9dfa refs/tags/v7.10.4^{}',
- '880e0ba0adbed95d087f61a9a17515e518fc6440 refs/tags/v7.11.1',
- '6584346b604f981f00af8011cd95472b2776d912 refs/tags/v7.11.1^{}',
- '43af3e65a486a9237f29f56d96c3b3da59c24ae0 refs/tags/v7.11.2',
- 'dac18e7728013a77410e926a1e64225703754a2d refs/tags/v7.11.2^{}',
- '0bf21fd4b46c980c26fd8c90a14b86a4d90cc950 refs/tags/v7.9.4',
- 'b10de29edbaff7219547dc506cb1468ee35065c3 refs/tags/v7.9.4^{}'
- ])
- expect(upgrader.latest_version_raw).to eq("v7.11.2")
- end
- end
-end
diff --git a/spec/lib/gitlab/utils/override_spec.rb b/spec/lib/gitlab/utils/override_spec.rb
index fc08ebcfc6d..9e7c97f8095 100644
--- a/spec/lib/gitlab/utils/override_spec.rb
+++ b/spec/lib/gitlab/utils/override_spec.rb
@@ -25,11 +25,21 @@ describe Gitlab::Utils::Override do
let(:klass) { subject }
- def good(mod)
+ def good(mod, bad_arity: false, negative_arity: false)
mod.module_eval do
override :good
- def good
- super.succ
+
+ if bad_arity
+ def good(num)
+ end
+ elsif negative_arity
+ def good(*args)
+ super.succ
+ end
+ else
+ def good
+ super.succ
+ end
end
end
@@ -56,6 +66,14 @@ describe Gitlab::Utils::Override do
described_class.verify!
end
+ it 'checks ok for overriding method using negative arity' do
+ good(subject, negative_arity: true)
+ result = instance.good
+
+ expect(result).to eq(1)
+ described_class.verify!
+ end
+
it 'raises NotImplementedError when it is not overriding anything' do
expect do
bad(subject)
@@ -63,6 +81,14 @@ describe Gitlab::Utils::Override do
described_class.verify!
end.to raise_error(NotImplementedError)
end
+
+ it 'raises NotImplementedError when overriding a method with different arity' do
+ expect do
+ good(subject, bad_arity: true)
+ instance.good(1)
+ described_class.verify!
+ end.to raise_error(NotImplementedError)
+ end
end
shared_examples 'checking as intended, nothing was overridden' do
diff --git a/spec/mailers/notify_spec.rb b/spec/mailers/notify_spec.rb
index f6e5c9d33ac..f2d99872401 100644
--- a/spec/mailers/notify_spec.rb
+++ b/spec/mailers/notify_spec.rb
@@ -890,22 +890,14 @@ describe Notify do
shared_examples 'an email for a note on a diff discussion' do |model|
let(:note) { create(model, author: note_author) }
- context 'when note is on image' do
+ context 'when note is not on text' do
before do
- allow_any_instance_of(DiffDiscussion).to receive(:on_image?).and_return(true)
+ allow_any_instance_of(DiffDiscussion).to receive(:on_text?).and_return(false)
end
it 'does not include diffs with character-level highlighting' do
is_expected.not_to have_body_text '<span class="p">}</span></span>'
end
-
- it 'ends the intro with a dot' do
- is_expected.to have_body_text "#{note.diff_file.file_path}</a>."
- end
- end
-
- it 'ends the intro with a colon' do
- is_expected.to have_body_text "#{note.diff_file.file_path}</a>:"
end
it 'includes diffs with character-level highlighting' do
diff --git a/spec/migrations/migrate_cluster_configure_worker_sidekiq_queue_spec.rb b/spec/migrations/migrate_cluster_configure_worker_sidekiq_queue_spec.rb
new file mode 100644
index 00000000000..b2d8f476bb2
--- /dev/null
+++ b/spec/migrations/migrate_cluster_configure_worker_sidekiq_queue_spec.rb
@@ -0,0 +1,68 @@
+require 'spec_helper'
+require Rails.root.join('db', 'post_migrate', '20181219145520_migrate_cluster_configure_worker_sidekiq_queue.rb')
+
+describe MigrateClusterConfigureWorkerSidekiqQueue, :sidekiq, :redis do
+ include Gitlab::Database::MigrationHelpers
+
+ context 'when there are jobs in the queue' do
+ it 'correctly migrates queue when migrating up' do
+ Sidekiq::Testing.disable! do
+ stubbed_worker(queue: 'gcp_cluster:cluster_platform_configure').perform_async('Something', [1])
+ stubbed_worker(queue: 'gcp_cluster:cluster_configure').perform_async('Something', [1])
+
+ described_class.new.up
+
+ expect(sidekiq_queue_length('gcp_cluster:cluster_platform_configure')).to eq 0
+ expect(sidekiq_queue_length('gcp_cluster:cluster_configure')).to eq 2
+ end
+ end
+
+ it 'does not affect other queues under the same namespace' do
+ Sidekiq::Testing.disable! do
+ stubbed_worker(queue: 'gcp_cluster:cluster_install_app').perform_async('Something', [1])
+ stubbed_worker(queue: 'gcp_cluster:cluster_provision').perform_async('Something', [1])
+ stubbed_worker(queue: 'gcp_cluster:cluster_wait_for_app_installation').perform_async('Something', [1])
+ stubbed_worker(queue: 'gcp_cluster:wait_for_cluster_creation').perform_async('Something', [1])
+ stubbed_worker(queue: 'gcp_cluster:cluster_wait_for_ingress_ip_address').perform_async('Something', [1])
+ stubbed_worker(queue: 'gcp_cluster:cluster_project_configure').perform_async('Something', [1])
+
+ described_class.new.up
+
+ expect(sidekiq_queue_length('gcp_cluster:cluster_install_app')).to eq 1
+ expect(sidekiq_queue_length('gcp_cluster:cluster_provision')).to eq 1
+ expect(sidekiq_queue_length('gcp_cluster:cluster_wait_for_app_installation')).to eq 1
+ expect(sidekiq_queue_length('gcp_cluster:wait_for_cluster_creation')).to eq 1
+ expect(sidekiq_queue_length('gcp_cluster:cluster_wait_for_ingress_ip_address')).to eq 1
+ expect(sidekiq_queue_length('gcp_cluster:cluster_project_configure')).to eq 1
+ end
+ end
+
+ it 'correctly migrates queue when migrating down' do
+ Sidekiq::Testing.disable! do
+ stubbed_worker(queue: 'gcp_cluster:cluster_configure').perform_async('Something', [1])
+
+ described_class.new.down
+
+ expect(sidekiq_queue_length('gcp_cluster:cluster_platform_configure')).to eq 1
+ expect(sidekiq_queue_length('gcp_cluster:cluster_configure')).to eq 0
+ end
+ end
+ end
+
+ context 'when there are no jobs in the queues' do
+ it 'does not raise error when migrating up' do
+ expect { described_class.new.up }.not_to raise_error
+ end
+
+ it 'does not raise error when migrating down' do
+ expect { described_class.new.down }.not_to raise_error
+ end
+ end
+
+ def stubbed_worker(queue:)
+ Class.new do
+ include Sidekiq::Worker
+ sidekiq_options queue: queue
+ end
+ end
+end
diff --git a/spec/models/broadcast_message_spec.rb b/spec/models/broadcast_message_spec.rb
index d6e5b557870..89839709131 100644
--- a/spec/models/broadcast_message_spec.rb
+++ b/spec/models/broadcast_message_spec.rb
@@ -49,7 +49,7 @@ describe BroadcastMessage do
it 'caches the output of the query' do
create(:broadcast_message)
- expect(described_class).to receive(:where).and_call_original.once
+ expect(described_class).to receive(:current_and_future_messages).and_call_original.once
described_class.current
@@ -93,27 +93,6 @@ describe BroadcastMessage do
expect(Rails.cache).to receive(:delete).with(described_class::LEGACY_CACHE_KEY)
expect(described_class.current.length).to eq(0)
end
-
- it 'gracefully handles bad cache entry' do
- allow(described_class).to receive(:current_and_future_messages).and_return('{')
-
- expect(described_class.current).to be_empty
- end
-
- it 'gracefully handles an empty hash' do
- allow(described_class).to receive(:current_and_future_messages).and_return('{}')
-
- expect(described_class.current).to be_empty
- end
-
- it 'gracefully handles unknown attributes' do
- message = create(:broadcast_message)
-
- allow(described_class).to receive(:current_and_future_messages)
- .and_return([{ bad_attr: 1 }, message])
-
- expect(described_class.current).to eq([message])
- end
end
describe '#active?' do
diff --git a/spec/models/clusters/platforms/kubernetes_spec.rb b/spec/models/clusters/platforms/kubernetes_spec.rb
index 062d2fd0768..f3af9d59786 100644
--- a/spec/models/clusters/platforms/kubernetes_spec.rb
+++ b/spec/models/clusters/platforms/kubernetes_spec.rb
@@ -394,7 +394,7 @@ describe Clusters::Platforms::Kubernetes, :use_clean_rails_memory_store_caching
context 'when namespace is updated' do
it 'should call ConfigureWorker' do
- expect(ClusterPlatformConfigureWorker).to receive(:perform_async).with(cluster.id).once
+ expect(ClusterConfigureWorker).to receive(:perform_async).with(cluster.id).once
platform.namespace = 'new-namespace'
platform.save
@@ -403,7 +403,7 @@ describe Clusters::Platforms::Kubernetes, :use_clean_rails_memory_store_caching
context 'when namespace is not updated' do
it 'should not call ConfigureWorker' do
- expect(ClusterPlatformConfigureWorker).not_to receive(:perform_async)
+ expect(ClusterConfigureWorker).not_to receive(:perform_async)
platform.username = "new-username"
platform.save
diff --git a/spec/models/concerns/avatarable_spec.rb b/spec/models/concerns/avatarable_spec.rb
index 7d617cb7b19..1ea7f2b9985 100644
--- a/spec/models/concerns/avatarable_spec.rb
+++ b/spec/models/concerns/avatarable_spec.rb
@@ -33,6 +33,43 @@ describe Avatarable do
end
describe '#avatar_path' do
+ context 'with caching enabled', :request_store do
+ let!(:avatar_path) { [relative_url_root, project.avatar.local_url].join }
+ let!(:avatar_url) { [gitlab_host, relative_url_root, project.avatar.local_url].join }
+
+ it 'only calls local_url once' do
+ expect(project.avatar).to receive(:local_url).once.and_call_original
+
+ 2.times do
+ expect(project.avatar_path).to eq(avatar_path)
+ end
+ end
+
+ it 'calls local_url twice for path and URLs' do
+ expect(project.avatar).to receive(:local_url).exactly(2).times.and_call_original
+
+ expect(project.avatar_path(only_path: true)).to eq(avatar_path)
+ expect(project.avatar_path(only_path: false)).to eq(avatar_url)
+ end
+
+ it 'calls local_url twice for different sizes' do
+ expect(project.avatar).to receive(:local_url).exactly(2).times.and_call_original
+
+ expect(project.avatar_path).to eq(avatar_path)
+ expect(project.avatar_path(size: 40)).to eq(avatar_path + "?width=40")
+ end
+
+ it 'handles unpersisted objects' do
+ new_project = build(:project, :with_avatar)
+ path = [relative_url_root, new_project.avatar.local_url].join
+ expect(new_project.avatar).to receive(:local_url).exactly(2).times.and_call_original
+
+ 2.times do
+ expect(new_project.avatar_path).to eq(path)
+ end
+ end
+ end
+
using RSpec::Parameterized::TableSyntax
where(:has_asset_host, :visibility_level, :only_path, :avatar_path_prefix) do
diff --git a/spec/models/concerns/discussion_on_diff_spec.rb b/spec/models/concerns/discussion_on_diff_spec.rb
index 73eb7a1160d..4b16e6e3902 100644
--- a/spec/models/concerns/discussion_on_diff_spec.rb
+++ b/spec/models/concerns/discussion_on_diff_spec.rb
@@ -50,11 +50,17 @@ describe DiscussionOnDiff do
end
context "when the diff line does not exist on a legacy diff note" do
+ subject { create(:legacy_diff_note_on_merge_request).to_discussion }
+
it "returns an empty array" do
- legacy_note = LegacyDiffNote.new
+ expect(truncated_lines).to eq([])
+ end
+ end
- allow(subject).to receive(:first_note).and_return(legacy_note)
+ context 'when the discussion is on an image' do
+ subject { create(:image_diff_note_on_merge_request).to_discussion }
+ it 'returns an empty array' do
expect(truncated_lines).to eq([])
end
end
diff --git a/spec/models/diff_note_spec.rb b/spec/models/diff_note_spec.rb
index 40ce8ab736a..fda00a693f0 100644
--- a/spec/models/diff_note_spec.rb
+++ b/spec/models/diff_note_spec.rb
@@ -337,24 +337,9 @@ describe DiffNote do
end
describe "image diff notes" do
- let(:path) { "files/images/any_image.png" }
-
- let!(:position) do
- Gitlab::Diff::Position.new(
- old_path: path,
- new_path: path,
- width: 10,
- height: 10,
- x: 1,
- y: 1,
- diff_refs: merge_request.diff_refs,
- position_type: "image"
- )
- end
+ subject { build(:image_diff_note_on_merge_request, project: project, noteable: merge_request) }
describe "validations" do
- subject { build(:diff_note_on_merge_request, project: project, position: position, noteable: merge_request) }
-
it { is_expected.not_to validate_presence_of(:line_code) }
it "does not validate diff line" do
diff --git a/spec/models/namespace_spec.rb b/spec/models/namespace_spec.rb
index 18b54cce834..475fbe56e4d 100644
--- a/spec/models/namespace_spec.rb
+++ b/spec/models/namespace_spec.rb
@@ -337,32 +337,40 @@ describe Namespace do
end
end
- it 'updates project full path in .git/config for each project inside namespace' do
- parent = create(:group, name: 'mygroup', path: 'mygroup')
- subgroup = create(:group, name: 'mysubgroup', path: 'mysubgroup', parent: parent)
- project_in_parent_group = create(:project, :legacy_storage, :repository, namespace: parent, name: 'foo1')
- hashed_project_in_subgroup = create(:project, :repository, namespace: subgroup, name: 'foo2')
- legacy_project_in_subgroup = create(:project, :legacy_storage, :repository, namespace: subgroup, name: 'foo3')
-
- parent.update(path: 'mygroup_new')
-
- # Routes are loaded when creating the projects, so we need to manually
- # reload them for the below code to be aware of the above UPDATE.
- [
- project_in_parent_group,
- hashed_project_in_subgroup,
- legacy_project_in_subgroup
- ].each do |project|
- project.route.reload
+ context 'for each project inside the namespace' do
+ let!(:parent) { create(:group, name: 'mygroup', path: 'mygroup') }
+ let!(:subgroup) { create(:group, name: 'mysubgroup', path: 'mysubgroup', parent: parent) }
+ let!(:project_in_parent_group) { create(:project, :legacy_storage, :repository, namespace: parent, name: 'foo1') }
+ let!(:hashed_project_in_subgroup) { create(:project, :repository, namespace: subgroup, name: 'foo2') }
+ let!(:legacy_project_in_subgroup) { create(:project, :legacy_storage, :repository, namespace: subgroup, name: 'foo3') }
+
+ it 'updates project full path in .git/config' do
+ parent.update(path: 'mygroup_new')
+
+ expect(project_rugged(project_in_parent_group).config['gitlab.fullpath']).to eq "mygroup_new/#{project_in_parent_group.path}"
+ expect(project_rugged(hashed_project_in_subgroup).config['gitlab.fullpath']).to eq "mygroup_new/mysubgroup/#{hashed_project_in_subgroup.path}"
+ expect(project_rugged(legacy_project_in_subgroup).config['gitlab.fullpath']).to eq "mygroup_new/mysubgroup/#{legacy_project_in_subgroup.path}"
end
- expect(project_rugged(project_in_parent_group).config['gitlab.fullpath']).to eq "mygroup_new/#{project_in_parent_group.path}"
- expect(project_rugged(hashed_project_in_subgroup).config['gitlab.fullpath']).to eq "mygroup_new/mysubgroup/#{hashed_project_in_subgroup.path}"
- expect(project_rugged(legacy_project_in_subgroup).config['gitlab.fullpath']).to eq "mygroup_new/mysubgroup/#{legacy_project_in_subgroup.path}"
- end
+ it 'updates the project storage location' do
+ repository_project_in_parent_group = create(:project_repository, project: project_in_parent_group)
+ repository_hashed_project_in_subgroup = create(:project_repository, project: hashed_project_in_subgroup)
+ repository_legacy_project_in_subgroup = create(:project_repository, project: legacy_project_in_subgroup)
+
+ parent.update(path: 'mygroup_moved')
+
+ expect(repository_project_in_parent_group.reload.disk_path).to eq "mygroup_moved/#{project_in_parent_group.path}"
+ expect(repository_hashed_project_in_subgroup.reload.disk_path).to eq hashed_project_in_subgroup.disk_path
+ expect(repository_legacy_project_in_subgroup.reload.disk_path).to eq "mygroup_moved/mysubgroup/#{legacy_project_in_subgroup.path}"
+ end
+
+ def project_rugged(project)
+ # Routes are loaded when creating the projects, so we need to manually
+ # reload them for the below code to be aware of the above UPDATE.
+ project.route.reload
- def project_rugged(project)
- rugged_repo(project.repository)
+ rugged_repo(project.repository)
+ end
end
end
diff --git a/spec/models/pool_repository_spec.rb b/spec/models/pool_repository_spec.rb
index 3d3878b8c39..112d4ab56fc 100644
--- a/spec/models/pool_repository_spec.rb
+++ b/spec/models/pool_repository_spec.rb
@@ -23,4 +23,25 @@ describe PoolRepository do
expect(pool.disk_path).to match(%r{\A@pools/\h{2}/\h{2}/\h{64}})
end
end
+
+ describe '#unlink_repository' do
+ let(:pool) { create(:pool_repository, :ready) }
+
+ context 'when the last member leaves' do
+ it 'schedules pool removal' do
+ expect(::ObjectPool::DestroyWorker).to receive(:perform_async).with(pool.id).and_call_original
+
+ pool.unlink_repository(pool.source_project.repository)
+ end
+ end
+
+ context 'when the second member leaves' do
+ it 'does not schedule pool removal' do
+ create(:project, :repository, pool_repository: pool)
+ expect(::ObjectPool::DestroyWorker).not_to receive(:perform_async).with(pool.id)
+
+ pool.unlink_repository(pool.source_project.repository)
+ end
+ end
+ end
end
diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb
index 5e63f14b720..a01f76a5bab 100644
--- a/spec/models/project_spec.rb
+++ b/spec/models/project_spec.rb
@@ -145,25 +145,10 @@ describe Project do
end
describe 'ci_pipelines association' do
- context 'when feature flag pipeline_ci_sources_only is enabled' do
- it 'returns only pipelines from ci_sources' do
- stub_feature_flags(pipeline_ci_sources_only: true)
+ it 'returns only pipelines from ci_sources' do
+ expect(Ci::Pipeline).to receive(:ci_sources).and_call_original
- expect(Ci::Pipeline).to receive(:ci_sources).and_call_original
-
- subject.ci_pipelines
- end
- end
-
- context 'when feature flag pipeline_ci_sources_only is disabled' do
- it 'returns all pipelines' do
- stub_feature_flags(pipeline_ci_sources_only: false)
-
- expect(Ci::Pipeline).not_to receive(:ci_sources).and_call_original
- expect(Ci::Pipeline).to receive(:all).and_call_original.at_least(:once)
-
- subject.ci_pipelines
- end
+ subject.ci_pipelines
end
end
end
@@ -1666,26 +1651,54 @@ describe Project do
end
describe '#track_project_repository' do
- let(:project) { create(:project, :repository) }
+ shared_examples 'tracks storage location' do
+ context 'when a project repository entry does not exist' do
+ it 'creates a new entry' do
+ expect { project.track_project_repository }.to change(project, :project_repository)
+ end
+
+ it 'tracks the project storage location' do
+ project.track_project_repository
+
+ expect(project.project_repository).to have_attributes(
+ disk_path: project.disk_path,
+ shard_name: project.repository_storage
+ )
+ end
+ end
+
+ context 'when a tracking entry exists' do
+ let!(:project_repository) { create(:project_repository, project: project) }
+ let!(:shard) { create(:shard, name: 'foo') }
+
+ it 'does not create a new entry in the database' do
+ expect { project.track_project_repository }.not_to change(project, :project_repository)
+ end
+
+ it 'updates the project storage location' do
+ allow(project).to receive(:disk_path).and_return('fancy/new/path')
+ allow(project).to receive(:repository_storage).and_return('foo')
- it 'creates a project_repository' do
- project.track_project_repository
+ project.track_project_repository
- expect(project.reload.project_repository).to be_present
- expect(project.project_repository.disk_path).to eq(project.disk_path)
- expect(project.project_repository.shard_name).to eq(project.repository_storage)
+ expect(project.project_repository).to have_attributes(
+ disk_path: 'fancy/new/path',
+ shard_name: 'foo'
+ )
+ end
+ end
end
- it 'updates the project_repository' do
- project.track_project_repository
+ context 'with projects on legacy storage' do
+ let(:project) { create(:project, :repository, :legacy_storage) }
- allow(project).to receive(:disk_path).and_return('@fancy/new/path')
+ it_behaves_like 'tracks storage location'
+ end
- expect do
- project.track_project_repository
- end.not_to change(ProjectRepository, :count)
+ context 'with projects on hashed storage' do
+ let(:project) { create(:project, :repository) }
- expect(project.reload.project_repository.disk_path).to eq(project.disk_path)
+ it_behaves_like 'tracks storage location'
end
end
@@ -3690,7 +3703,7 @@ describe Project do
expect(project.badges.count).to eq 3
end
- if Group.supports_nested_groups?
+ if Group.supports_nested_objects?
context 'with nested_groups' do
let(:parent_group) { create(:group) }
diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb
index 8b3021113bc..33842e74b92 100644
--- a/spec/models/user_spec.rb
+++ b/spec/models/user_spec.rb
@@ -1966,7 +1966,7 @@ describe User do
subject { user.membership_groups }
- if Group.supports_nested_groups?
+ if Group.supports_nested_objects?
it { is_expected.to contain_exactly parent_group, child_group }
else
it { is_expected.to contain_exactly parent_group }
@@ -2347,7 +2347,7 @@ describe User do
group.add_owner(user)
end
- if Group.supports_nested_groups?
+ if Group.supports_nested_objects?
it 'returns all groups' do
is_expected.to match_array [
group,
diff --git a/spec/policies/group_policy_spec.rb b/spec/policies/group_policy_spec.rb
index 9d0093e8159..baf21efa75c 100644
--- a/spec/policies/group_policy_spec.rb
+++ b/spec/policies/group_policy_spec.rb
@@ -147,7 +147,7 @@ describe GroupPolicy do
let(:current_user) { owner }
it do
- allow(Group).to receive(:supports_nested_groups?).and_return(true)
+ allow(Group).to receive(:supports_nested_objects?).and_return(true)
expect_allowed(*guest_permissions)
expect_allowed(*reporter_permissions)
@@ -161,7 +161,7 @@ describe GroupPolicy do
let(:current_user) { admin }
it do
- allow(Group).to receive(:supports_nested_groups?).and_return(true)
+ allow(Group).to receive(:supports_nested_objects?).and_return(true)
expect_allowed(*guest_permissions)
expect_allowed(*reporter_permissions)
@@ -173,7 +173,7 @@ describe GroupPolicy do
describe 'when nested group support feature is disabled' do
before do
- allow(Group).to receive(:supports_nested_groups?).and_return(false)
+ allow(Group).to receive(:supports_nested_objects?).and_return(false)
end
context 'admin' do
@@ -282,7 +282,7 @@ describe GroupPolicy do
let(:current_user) { owner }
it do
- allow(Group).to receive(:supports_nested_groups?).and_return(true)
+ allow(Group).to receive(:supports_nested_objects?).and_return(true)
expect_allowed(*guest_permissions)
expect_allowed(*reporter_permissions)
diff --git a/spec/requests/api/events_spec.rb b/spec/requests/api/events_spec.rb
index 8c58ba45ce9..0ac23505de7 100644
--- a/spec/requests/api/events_spec.rb
+++ b/spec/requests/api/events_spec.rb
@@ -226,7 +226,7 @@ describe API::Events do
end
it 'correctly returns the second page without inaccessible events' do
- get api("/projects/#{public_project.id}/events", user), per_page: 2, page: 2
+ get api("/projects/#{public_project.id}/events", user), params: { per_page: 2, page: 2 }
titles = json_response.map { |event| event['target_title'] }
@@ -235,7 +235,7 @@ describe API::Events do
end
it 'correctly returns the first page without inaccessible events' do
- get api("/projects/#{public_project.id}/events", user), per_page: 2, page: 1
+ get api("/projects/#{public_project.id}/events", user), params: { per_page: 2, page: 1 }
titles = json_response.map { |event| event['target_title'] }
diff --git a/spec/requests/api/files_spec.rb b/spec/requests/api/files_spec.rb
index e6d82448c0d..0ba1f2d7a2b 100644
--- a/spec/requests/api/files_spec.rb
+++ b/spec/requests/api/files_spec.rb
@@ -54,7 +54,7 @@ describe API::Files do
describe "HEAD /projects/:id/repository/files/:file_path" do
shared_examples_for 'repository files' do
it 'returns file attributes in headers' do
- head api(route(file_path), current_user), params
+ head api(route(file_path), current_user), params: params
expect(response).to have_gitlab_http_status(200)
expect(response.headers['X-Gitlab-File-Path']).to eq(CGI.unescape(file_path))
@@ -68,7 +68,7 @@ describe API::Files do
file_path = "files%2Fjs%2Fcommit%2Ejs%2Ecoffee"
params[:ref] = "6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9"
- head api(route(file_path), current_user), params
+ head api(route(file_path), current_user), params: params
expect(response).to have_gitlab_http_status(200)
expect(response.headers['X-Gitlab-File-Name']).to eq('commit.js.coffee')
@@ -87,7 +87,7 @@ describe API::Files do
it "responds with a 404 status" do
params[:ref] = 'master'
- head api(route('app%2Fmodels%2Fapplication%2Erb'), current_user), params
+ head api(route('app%2Fmodels%2Fapplication%2Erb'), current_user), params: params
expect(response).to have_gitlab_http_status(404)
end
@@ -97,7 +97,7 @@ describe API::Files do
include_context 'disabled repository'
it "responds with a 403 status" do
- head api(route(file_path), current_user), params
+ head api(route(file_path), current_user), params: params
expect(response).to have_gitlab_http_status(403)
end
@@ -115,7 +115,7 @@ describe API::Files do
it "responds with a 404 status" do
current_user = nil
- head api(route(file_path), current_user), params
+ head api(route(file_path), current_user), params: params
expect(response).to have_gitlab_http_status(404)
end
@@ -136,7 +136,7 @@ describe API::Files do
context 'when authenticated', 'as a guest' do
it_behaves_like '403 response' do
- let(:request) { head api(route(file_path), guest), params }
+ let(:request) { head api(route(file_path), guest), params: params }
end
end
end
diff --git a/spec/requests/openid_connect_spec.rb b/spec/requests/openid_connect_spec.rb
index ec546db335a..2b148c1b563 100644
--- a/spec/requests/openid_connect_spec.rb
+++ b/spec/requests/openid_connect_spec.rb
@@ -104,7 +104,7 @@ describe 'OpenID Connect requests' do
expect(json_response).to match(id_token_claims.merge(user_info_claims))
expected_groups = [group1.full_path, group3.full_path]
- expected_groups << group4.full_path if Group.supports_nested_groups?
+ expected_groups << group4.full_path if Group.supports_nested_objects?
expect(json_response['groups']).to match_array(expected_groups)
end
diff --git a/spec/requests/rack_attack_global_spec.rb b/spec/requests/rack_attack_global_spec.rb
index c27e27d3648..49021f5d1b7 100644
--- a/spec/requests/rack_attack_global_spec.rb
+++ b/spec/requests/rack_attack_global_spec.rb
@@ -345,7 +345,7 @@ describe 'Rack Attack global throttles' do
end
def api_get_args_with_token_headers(partial_url, token_headers)
- ["/api/#{API::API.version}#{partial_url}", nil, token_headers]
+ ["/api/#{API::API.version}#{partial_url}", params: nil, headers: token_headers]
end
def rss_url(user)
diff --git a/spec/serializers/entity_date_helper_spec.rb b/spec/serializers/entity_date_helper_spec.rb
index 36da8d33a44..ae0f917415c 100644
--- a/spec/serializers/entity_date_helper_spec.rb
+++ b/spec/serializers/entity_date_helper_spec.rb
@@ -50,7 +50,7 @@ describe EntityDateHelper do
end
context 'when less than 31 days remaining' do
- let(:milestone_remaining) { date_helper_class.remaining_days_in_words(build_stubbed(:milestone, due_date: 12.days.from_now.utc)) }
+ let(:milestone_remaining) { date_helper_class.remaining_days_in_words(12.days.from_now.utc.to_date) }
it 'returns days remaining' do
expect(milestone_remaining).to eq("<strong>12</strong> days remaining")
@@ -58,7 +58,7 @@ describe EntityDateHelper do
end
context 'when less than 1 year and more than 30 days remaining' do
- let(:milestone_remaining) { date_helper_class.remaining_days_in_words(build_stubbed(:milestone, due_date: 2.months.from_now.utc)) }
+ let(:milestone_remaining) { date_helper_class.remaining_days_in_words(2.months.from_now.utc.to_date) }
it 'returns months remaining' do
expect(milestone_remaining).to eq("<strong>2</strong> months remaining")
@@ -66,7 +66,7 @@ describe EntityDateHelper do
end
context 'when more than 1 year remaining' do
- let(:milestone_remaining) { date_helper_class.remaining_days_in_words(build_stubbed(:milestone, due_date: (1.year.from_now + 2.days).utc)) }
+ let(:milestone_remaining) { date_helper_class.remaining_days_in_words((1.year.from_now + 2.days).utc.to_date) }
it 'returns years remaining' do
expect(milestone_remaining).to eq("<strong>1</strong> year remaining")
@@ -74,7 +74,7 @@ describe EntityDateHelper do
end
context 'when milestone is expired' do
- let(:milestone_remaining) { date_helper_class.remaining_days_in_words(build_stubbed(:milestone, due_date: 2.days.ago.utc)) }
+ let(:milestone_remaining) { date_helper_class.remaining_days_in_words(2.days.ago.utc.to_date) }
it 'returns "Past due"' do
expect(milestone_remaining).to eq("<strong>Past due</strong>")
@@ -82,7 +82,7 @@ describe EntityDateHelper do
end
context 'when milestone has start_date in the future' do
- let(:milestone_remaining) { date_helper_class.remaining_days_in_words(build_stubbed(:milestone, start_date: 2.days.from_now.utc)) }
+ let(:milestone_remaining) { date_helper_class.remaining_days_in_words(nil, 2.days.from_now.utc.to_date) }
it 'returns "Upcoming"' do
expect(milestone_remaining).to eq("<strong>Upcoming</strong>")
@@ -90,7 +90,7 @@ describe EntityDateHelper do
end
context 'when milestone has start_date in the past' do
- let(:milestone_remaining) { date_helper_class.remaining_days_in_words(build_stubbed(:milestone, start_date: 2.days.ago.utc)) }
+ let(:milestone_remaining) { date_helper_class.remaining_days_in_words(nil, 2.days.ago.utc.to_date) }
it 'returns days elapsed' do
expect(milestone_remaining).to eq("<strong>2</strong> days elapsed")
diff --git a/spec/serializers/environment_entity_spec.rb b/spec/serializers/environment_entity_spec.rb
index b7324a26ed2..791b64dc356 100644
--- a/spec/serializers/environment_entity_spec.rb
+++ b/spec/serializers/environment_entity_spec.rb
@@ -40,4 +40,34 @@ describe EnvironmentEntity do
expect(subject).to include(:metrics_path)
end
end
+
+ context 'with deployment platform' do
+ let(:project) { create(:project, :repository) }
+ let(:environment) { create(:environment, project: project) }
+
+ context 'when deployment platform is a cluster' do
+ before do
+ create(:cluster,
+ :provided_by_gcp,
+ :project,
+ environment_scope: '*',
+ projects: [project])
+ end
+
+ it 'should include cluster_type' do
+ expect(subject).to include(:cluster_type)
+ expect(subject[:cluster_type]).to eq('project_type')
+ end
+ end
+
+ context 'when deployment platform is a Kubernetes Service' do
+ before do
+ create(:kubernetes_service, project: project)
+ end
+
+ it 'should not include cluster_type' do
+ expect(subject).not_to include(:cluster_type)
+ end
+ end
+ end
end
diff --git a/spec/serializers/issue_serializer_spec.rb b/spec/serializers/issue_serializer_spec.rb
index e8c46c0cdee..b8255e004d0 100644
--- a/spec/serializers/issue_serializer_spec.rb
+++ b/spec/serializers/issue_serializer_spec.rb
@@ -20,11 +20,19 @@ describe IssueSerializer do
context 'sidebar issue serialization' do
let(:serializer) { 'sidebar' }
- it 'matches sidebar issue json schema' do
+ it 'matches issue_sidebar json schema' do
expect(json_entity).to match_schema('entities/issue_sidebar')
end
end
+ context 'sidebar extras issue serialization' do
+ let(:serializer) { 'sidebar_extras' }
+
+ it 'matches issue_sidebar_extras json schema' do
+ expect(json_entity).to match_schema('entities/issue_sidebar_extras')
+ end
+ end
+
context 'board issue serialization' do
let(:serializer) { 'board' }
diff --git a/spec/serializers/merge_request_basic_serializer_spec.rb b/spec/serializers/merge_request_basic_serializer_spec.rb
deleted file mode 100644
index 1fad8e6bc5d..00000000000
--- a/spec/serializers/merge_request_basic_serializer_spec.rb
+++ /dev/null
@@ -1,16 +0,0 @@
-require 'spec_helper'
-
-describe MergeRequestBasicSerializer do
- let(:resource) { create(:merge_request) }
- let(:user) { create(:user) }
-
- let(:json_entity) do
- described_class.new(current_user: user)
- .represent(resource, serializer: 'basic')
- .with_indifferent_access
- end
-
- it 'matches basic merge request json' do
- expect(json_entity).to match_schema('entities/merge_request_basic')
- end
-end
diff --git a/spec/serializers/merge_request_serializer_spec.rb b/spec/serializers/merge_request_serializer_spec.rb
index b259cb92962..276e0f6ff3d 100644
--- a/spec/serializers/merge_request_serializer_spec.rb
+++ b/spec/serializers/merge_request_serializer_spec.rb
@@ -20,8 +20,16 @@ describe MergeRequestSerializer do
context 'sidebar merge request serialization' do
let(:serializer) { 'sidebar' }
- it 'matches basic merge request json schema' do
- expect(json_entity).to match_schema('entities/merge_request_basic')
+ it 'matches merge_request_sidebar json schema' do
+ expect(json_entity).to match_schema('entities/merge_request_sidebar')
+ end
+ end
+
+ context 'sidebar_extras merge request serialization' do
+ let(:serializer) { 'sidebar_extras' }
+
+ it 'matches merge_request_sidebar_extras json schema' do
+ expect(json_entity).to match_schema('entities/merge_request_sidebar_extras')
end
end
diff --git a/spec/services/clusters/gcp/finalize_creation_service_spec.rb b/spec/services/clusters/gcp/finalize_creation_service_spec.rb
index d69678c1277..2664649df47 100644
--- a/spec/services/clusters/gcp/finalize_creation_service_spec.rb
+++ b/spec/services/clusters/gcp/finalize_creation_service_spec.rb
@@ -20,7 +20,7 @@ describe Clusters::Gcp::FinalizeCreationService, '#execute' do
subject { described_class.new.execute(provider) }
before do
- allow(ClusterPlatformConfigureWorker).to receive(:perform_async)
+ allow(ClusterConfigureWorker).to receive(:perform_async)
end
shared_examples 'success' do
@@ -43,8 +43,8 @@ describe Clusters::Gcp::FinalizeCreationService, '#execute' do
expect(platform.token).to eq(token)
end
- it 'calls ClusterPlatformConfigureWorker in a ascync fashion' do
- expect(ClusterPlatformConfigureWorker).to receive(:perform_async).with(cluster.id)
+ it 'calls ClusterConfigureWorker in a ascync fashion' do
+ expect(ClusterConfigureWorker).to receive(:perform_async).with(cluster.id)
subject
end
diff --git a/spec/services/clusters/update_service_spec.rb b/spec/services/clusters/update_service_spec.rb
index 73f9be242a3..b2e6ebecd4a 100644
--- a/spec/services/clusters/update_service_spec.rb
+++ b/spec/services/clusters/update_service_spec.rb
@@ -37,7 +37,7 @@ describe Clusters::UpdateService do
end
before do
- allow(ClusterPlatformConfigureWorker).to receive(:perform_async)
+ allow(ClusterConfigureWorker).to receive(:perform_async)
stub_kubeclient_get_namespace('https://kubernetes.example.com', namespace: 'my-namespace')
end
diff --git a/spec/services/groups/create_service_spec.rb b/spec/services/groups/create_service_spec.rb
index 224e933bebc..fe6a8691ae0 100644
--- a/spec/services/groups/create_service_spec.rb
+++ b/spec/services/groups/create_service_spec.rb
@@ -55,7 +55,7 @@ describe Groups::CreateService, '#execute' do
context 'when nested groups feature is disabled' do
it 'does not save group and returns an error' do
- allow(Group).to receive(:supports_nested_groups?).and_return(false)
+ allow(Group).to receive(:supports_nested_objects?).and_return(false)
is_expected.not_to be_persisted
expect(subject.errors[:parent_id]).to include('You don’t have permission to create a subgroup in this group.')
@@ -66,7 +66,7 @@ describe Groups::CreateService, '#execute' do
context 'when nested groups feature is enabled' do
before do
- allow(Group).to receive(:supports_nested_groups?).and_return(true)
+ allow(Group).to receive(:supports_nested_objects?).and_return(true)
end
context 'as guest' do
diff --git a/spec/services/groups/nested_create_service_spec.rb b/spec/services/groups/nested_create_service_spec.rb
index 86fdd43c1e5..75d6ddb0a2c 100644
--- a/spec/services/groups/nested_create_service_spec.rb
+++ b/spec/services/groups/nested_create_service_spec.rb
@@ -30,7 +30,7 @@ describe Groups::NestedCreateService do
let(:params) { { group_path: 'a-group' } }
before do
- allow(Group).to receive(:supports_nested_groups?) { false }
+ allow(Group).to receive(:supports_nested_objects?) { false }
end
it 'creates the group' do
diff --git a/spec/services/groups/transfer_service_spec.rb b/spec/services/groups/transfer_service_spec.rb
index dd8a1cee074..6b48c993c57 100644
--- a/spec/services/groups/transfer_service_spec.rb
+++ b/spec/services/groups/transfer_service_spec.rb
@@ -9,7 +9,7 @@ describe Groups::TransferService, :postgresql do
shared_examples 'ensuring allowed transfer for a group' do
context 'with other database than PostgreSQL' do
before do
- allow(Group).to receive(:supports_nested_groups?).and_return(false)
+ allow(Group).to receive(:supports_nested_objects?).and_return(false)
end
it 'should return false' do
diff --git a/spec/services/notification_service_spec.rb b/spec/services/notification_service_spec.rb
index 68ac3a00ab0..d20e712d365 100644
--- a/spec/services/notification_service_spec.rb
+++ b/spec/services/notification_service_spec.rb
@@ -2250,7 +2250,7 @@ describe NotificationService, :mailer do
# Creates a nested group only if supported
# to avoid errors on MySQL
def create_nested_group
- if Group.supports_nested_groups?
+ if Group.supports_nested_objects?
parent_group = create(:group, :public)
child_group = create(:group, :public, parent: parent_group)
@@ -2277,7 +2277,7 @@ describe NotificationService, :mailer do
end
def add_member_for_parent_group(user, project)
- return unless Group.supports_nested_groups?
+ return unless Group.supports_nested_objects?
project.reload
@@ -2285,13 +2285,13 @@ describe NotificationService, :mailer do
end
def should_email_nested_group_user(user, times: 1, recipients: email_recipients)
- return unless Group.supports_nested_groups?
+ return unless Group.supports_nested_objects?
should_email(user, times: 1, recipients: email_recipients)
end
def should_not_email_nested_group_user(user, recipients: email_recipients)
- return unless Group.supports_nested_groups?
+ return unless Group.supports_nested_objects?
should_not_email(user, recipients: email_recipients)
end
diff --git a/spec/services/projects/after_rename_service_spec.rb b/spec/services/projects/after_rename_service_spec.rb
index b4718a07204..59c08b30f9f 100644
--- a/spec/services/projects/after_rename_service_spec.rb
+++ b/spec/services/projects/after_rename_service_spec.rb
@@ -99,6 +99,17 @@ describe Projects::AfterRenameService do
expect(rugged_config['gitlab.fullpath']).to eq(project.full_path)
end
+
+ it 'updates storage location' do
+ allow(project_storage).to receive(:rename_repo).and_return(true)
+
+ described_class.new(project).execute
+
+ expect(project.project_repository).to have_attributes(
+ disk_path: project.disk_path,
+ shard_name: project.repository_storage
+ )
+ end
end
context 'using hashed storage' do
@@ -193,6 +204,15 @@ describe Projects::AfterRenameService do
expect(rugged_config['gitlab.fullpath']).to eq(project.full_path)
end
+
+ it 'updates storage location' do
+ described_class.new(project).execute
+
+ expect(project.project_repository).to have_attributes(
+ disk_path: project.disk_path,
+ shard_name: project.repository_storage
+ )
+ end
end
end
end
diff --git a/spec/services/projects/transfer_service_spec.rb b/spec/services/projects/transfer_service_spec.rb
index 132ad9a2646..766276fdba3 100644
--- a/spec/services/projects/transfer_service_spec.rb
+++ b/spec/services/projects/transfer_service_spec.rb
@@ -63,6 +63,15 @@ describe Projects::TransferService do
expect(rugged_config['gitlab.fullpath']).to eq "#{group.full_path}/#{project.path}"
end
+ it 'updates storage location' do
+ transfer_project(project, user, group)
+
+ expect(project.project_repository).to have_attributes(
+ disk_path: "#{group.full_path}/#{project.path}",
+ shard_name: project.repository_storage
+ )
+ end
+
context 'new group has a kubernetes cluster' do
let(:group_cluster) { create(:cluster, :group, :provided_by_gcp) }
let(:group) { group_cluster.group }
@@ -139,6 +148,17 @@ describe Projects::TransferService do
expect(service).not_to receive(:execute_system_hooks)
end
end
+
+ it 'does not update storage location' do
+ create(:project_repository, project: project)
+
+ attempt_project_transfer
+
+ expect(project.project_repository).to have_attributes(
+ disk_path: project.disk_path,
+ shard_name: project.repository_storage
+ )
+ end
end
context 'namespace -> no namespace' do
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
index e8554377d77..89357056c93 100644
--- a/spec/spec_helper.rb
+++ b/spec/spec_helper.rb
@@ -228,7 +228,7 @@ RSpec.configure do |config|
end
config.around(:each, :nested_groups) do |example|
- example.run if Group.supports_nested_groups?
+ example.run if Group.supports_nested_objects?
end
config.around(:each, :postgresql) do |example|
diff --git a/spec/support/api/boards_shared_examples.rb b/spec/support/api/boards_shared_examples.rb
index 943c1f6ffd7..592962ebf7c 100644
--- a/spec/support/api/boards_shared_examples.rb
+++ b/spec/support/api/boards_shared_examples.rb
@@ -88,7 +88,7 @@ shared_examples_for 'group and project boards' do |route_definition, ee = false|
let(:url) { "#{root_url}/#{board.id}/lists" }
it 'creates a new issue board list for labels' do
- post api(url, user), label_id: ux_label.id
+ post api(url, user), params: { label_id: ux_label.id }
expect(response).to have_gitlab_http_status(201)
expect(json_response['label']['name']).to eq(ux_label.title)
@@ -96,13 +96,13 @@ shared_examples_for 'group and project boards' do |route_definition, ee = false|
end
it 'returns 400 when creating a new list if label_id is invalid' do
- post api(url, user), label_id: 23423
+ post api(url, user), params: { label_id: 23423 }
expect(response).to have_gitlab_http_status(400)
end
it 'returns 403 for members with guest role' do
- put api("#{url}/#{test_list.id}", guest), position: 1
+ put api("#{url}/#{test_list.id}", guest), params: { position: 1 }
expect(response).to have_gitlab_http_status(403)
end
@@ -112,23 +112,20 @@ shared_examples_for 'group and project boards' do |route_definition, ee = false|
let(:url) { "#{root_url}/#{board.id}/lists" }
it "updates a list" do
- put api("#{url}/#{test_list.id}", user),
- position: 1
+ put api("#{url}/#{test_list.id}", user), params: { position: 1 }
expect(response).to have_gitlab_http_status(200)
expect(json_response['position']).to eq(1)
end
it "returns 404 error if list id not found" do
- put api("#{url}/44444", user),
- position: 1
+ put api("#{url}/44444", user), params: { position: 1 }
expect(response).to have_gitlab_http_status(404)
end
it "returns 403 for members with guest role" do
- put api("#{url}/#{test_list.id}", guest),
- position: 1
+ put api("#{url}/#{test_list.id}", guest), params: { position: 1 }
expect(response).to have_gitlab_http_status(403)
end
diff --git a/spec/support/api/milestones_shared_examples.rb b/spec/support/api/milestones_shared_examples.rb
index 3bebb7aae90..5f709831ce1 100644
--- a/spec/support/api/milestones_shared_examples.rb
+++ b/spec/support/api/milestones_shared_examples.rb
@@ -45,7 +45,7 @@ shared_examples_for 'group and project milestones' do |route_definition|
it 'returns an array of milestones specified by iids' do
other_milestone = create(:milestone, project: try(:project), group: try(:group))
- get api(route, user), iids: [closed_milestone.iid, other_milestone.iid]
+ get api(route, user), params: { iids: [closed_milestone.iid, other_milestone.iid] }
expect(response).to have_gitlab_http_status(200)
expect(json_response).to be_an Array
@@ -54,7 +54,7 @@ shared_examples_for 'group and project milestones' do |route_definition|
end
it 'does not return any milestone if none found' do
- get api(route, user), iids: [Milestone.maximum(:iid).succ]
+ get api(route, user), params: { iids: [Milestone.maximum(:iid).succ] }
expect(response).to have_gitlab_http_status(200)
expect(json_response).to be_an Array
@@ -73,7 +73,7 @@ shared_examples_for 'group and project milestones' do |route_definition|
end
it 'returns a milestone by searching for title' do
- get api(route, user), search: 'version2'
+ get api(route, user), params: { search: 'version2' }
expect(response).to have_gitlab_http_status(200)
expect(response).to include_pagination_headers
@@ -83,7 +83,7 @@ shared_examples_for 'group and project milestones' do |route_definition|
end
it 'returns a milestones by searching for description' do
- get api(route, user), search: 'open'
+ get api(route, user), params: { search: 'open' }
expect(response).to have_gitlab_http_status(200)
expect(response).to include_pagination_headers
@@ -117,7 +117,7 @@ shared_examples_for 'group and project milestones' do |route_definition|
describe "POST #{route_definition}" do
it 'creates a new milestone' do
- post api(route, user), title: 'new milestone'
+ post api(route, user), params: { title: 'new milestone' }
expect(response).to have_gitlab_http_status(201)
expect(json_response['title']).to eq('new milestone')
@@ -125,8 +125,7 @@ shared_examples_for 'group and project milestones' do |route_definition|
end
it 'creates a new milestone with description and dates' do
- post api(route, user),
- title: 'new milestone', description: 'release', due_date: '2013-03-02', start_date: '2013-02-02'
+ post api(route, user), params: { title: 'new milestone', description: 'release', due_date: '2013-03-02', start_date: '2013-02-02' }
expect(response).to have_gitlab_http_status(201)
expect(json_response['description']).to eq('release')
@@ -141,14 +140,13 @@ shared_examples_for 'group and project milestones' do |route_definition|
end
it 'returns a 400 error if params are invalid (duplicate title)' do
- post api(route, user),
- title: milestone.title, description: 'release', due_date: '2013-03-02'
+ post api(route, user), params: { title: milestone.title, description: 'release', due_date: '2013-03-02' }
expect(response).to have_gitlab_http_status(400)
end
it 'creates a new milestone with reserved html characters' do
- post api(route, user), title: 'foo & bar 1.1 -> 2.2'
+ post api(route, user), params: { title: 'foo & bar 1.1 -> 2.2' }
expect(response).to have_gitlab_http_status(201)
expect(json_response['title']).to eq('foo & bar 1.1 -> 2.2')
@@ -158,8 +156,7 @@ shared_examples_for 'group and project milestones' do |route_definition|
describe "PUT #{route_definition}/:milestone_id" do
it 'updates a milestone' do
- put api(resource_route, user),
- title: 'updated title'
+ put api(resource_route, user), params: { title: 'updated title' }
expect(response).to have_gitlab_http_status(200)
expect(json_response['title']).to eq('updated title')
@@ -168,29 +165,27 @@ shared_examples_for 'group and project milestones' do |route_definition|
it 'removes a due date if nil is passed' do
milestone.update!(due_date: "2016-08-05")
- put api(resource_route, user), due_date: nil
+ put api(resource_route, user), params: { due_date: nil }
expect(response).to have_gitlab_http_status(200)
expect(json_response['due_date']).to be_nil
end
it 'returns a 404 error if milestone id not found' do
- put api("#{route}/1234", user),
- title: 'updated title'
+ put api("#{route}/1234", user), params: { title: 'updated title' }
expect(response).to have_gitlab_http_status(404)
end
it 'closes milestone' do
- put api(resource_route, user),
- state_event: 'close'
+ put api(resource_route, user), params: { state_event: 'close' }
expect(response).to have_gitlab_http_status(200)
expect(json_response['state']).to eq('closed')
end
it 'updates milestone with only start date' do
- put api(resource_route, user), start_date: Date.tomorrow
+ put api(resource_route, user), params: { start_date: Date.tomorrow }
expect(response).to have_gitlab_http_status(200)
end
diff --git a/spec/support/api/scopes/read_user_shared_examples.rb b/spec/support/api/scopes/read_user_shared_examples.rb
index d7cef137989..683234264a8 100644
--- a/spec/support/api/scopes/read_user_shared_examples.rb
+++ b/spec/support/api/scopes/read_user_shared_examples.rb
@@ -77,7 +77,7 @@ shared_examples_for 'does not allow the "read_user" scope' do
let(:token) { create(:personal_access_token, scopes: ['read_user'], user: user) }
it 'returns a "403" response' do
- post api_call.call(path, user, personal_access_token: token), attributes_for(:user, projects_limit: 3)
+ post api_call.call(path, user, personal_access_token: token), params: attributes_for(:user, projects_limit: 3)
expect(response).to have_gitlab_http_status(403)
end
diff --git a/spec/support/api/time_tracking_shared_examples.rb b/spec/support/api/time_tracking_shared_examples.rb
index fee464c15a3..e883d33f671 100644
--- a/spec/support/api/time_tracking_shared_examples.rb
+++ b/spec/support/api/time_tracking_shared_examples.rb
@@ -7,13 +7,13 @@ shared_examples 'time tracking endpoints' do |issuable_name|
describe "POST /projects/:id/#{issuable_collection_name}/:#{issuable_name}_id/time_estimate" do
context 'with an unauthorized user' do
- subject { post(api("/projects/#{project.id}/#{issuable_collection_name}/#{issuable.iid}/time_estimate", non_member), duration: '1w') }
+ subject { post(api("/projects/#{project.id}/#{issuable_collection_name}/#{issuable.iid}/time_estimate", non_member), params: { duration: '1w' }) }
it_behaves_like 'an unauthorized API user'
end
it "sets the time estimate for #{issuable_name}" do
- post api("/projects/#{project.id}/#{issuable_collection_name}/#{issuable.iid}/time_estimate", user), duration: '1w'
+ post api("/projects/#{project.id}/#{issuable_collection_name}/#{issuable.iid}/time_estimate", user), params: { duration: '1w' }
expect(response).to have_gitlab_http_status(200)
expect(json_response['human_time_estimate']).to eq('1w')
@@ -21,12 +21,12 @@ shared_examples 'time tracking endpoints' do |issuable_name|
describe 'updating the current estimate' do
before do
- post api("/projects/#{project.id}/#{issuable_collection_name}/#{issuable.iid}/time_estimate", user), duration: '1w'
+ post api("/projects/#{project.id}/#{issuable_collection_name}/#{issuable.iid}/time_estimate", user), params: { duration: '1w' }
end
context 'when duration has a bad format' do
it 'does not modify the original estimate' do
- post api("/projects/#{project.id}/#{issuable_collection_name}/#{issuable.iid}/time_estimate", user), duration: 'foo'
+ post api("/projects/#{project.id}/#{issuable_collection_name}/#{issuable.iid}/time_estimate", user), params: { duration: 'foo' }
expect(response).to have_gitlab_http_status(400)
expect(issuable.reload.human_time_estimate).to eq('1w')
@@ -35,7 +35,7 @@ shared_examples 'time tracking endpoints' do |issuable_name|
context 'with a valid duration' do
it 'updates the estimate' do
- post api("/projects/#{project.id}/#{issuable_collection_name}/#{issuable.iid}/time_estimate", user), duration: '3w1h'
+ post api("/projects/#{project.id}/#{issuable_collection_name}/#{issuable.iid}/time_estimate", user), params: { duration: '3w1h' }
expect(response).to have_gitlab_http_status(200)
expect(issuable.reload.human_time_estimate).to eq('3w 1h')
@@ -62,8 +62,7 @@ shared_examples 'time tracking endpoints' do |issuable_name|
describe "POST /projects/:id/#{issuable_collection_name}/:#{issuable_name}_id/add_spent_time" do
context 'with an unauthorized user' do
subject do
- post api("/projects/#{project.id}/#{issuable_collection_name}/#{issuable.iid}/add_spent_time", non_member),
- duration: '2h'
+ post api("/projects/#{project.id}/#{issuable_collection_name}/#{issuable.iid}/add_spent_time", non_member), params: { duration: '2h' }
end
it_behaves_like 'an unauthorized API user'
@@ -72,8 +71,7 @@ shared_examples 'time tracking endpoints' do |issuable_name|
it "add spent time for #{issuable_name}" do
Timecop.travel(1.minute.from_now) do
expect do
- post api("/projects/#{project.id}/#{issuable_collection_name}/#{issuable.iid}/add_spent_time", user),
- duration: '2h'
+ post api("/projects/#{project.id}/#{issuable_collection_name}/#{issuable.iid}/add_spent_time", user), params: { duration: '2h' }
end.to change { issuable.reload.updated_at }
end
@@ -89,8 +87,7 @@ shared_examples 'time tracking endpoints' do |issuable_name|
end.to change { issuable.reload.updated_at }
end
- post api("/projects/#{project.id}/#{issuable_collection_name}/#{issuable.iid}/add_spent_time", user),
- duration: '-1h'
+ post api("/projects/#{project.id}/#{issuable_collection_name}/#{issuable.iid}/add_spent_time", user), params: { duration: '-1h' }
expect(response).to have_gitlab_http_status(201)
expect(json_response['total_time_spent']).to eq(3600)
@@ -103,8 +100,7 @@ shared_examples 'time tracking endpoints' do |issuable_name|
Timecop.travel(1.minute.from_now) do
expect do
- post api("/projects/#{project.id}/#{issuable_collection_name}/#{issuable.iid}/add_spent_time", user),
- duration: '-1w'
+ post api("/projects/#{project.id}/#{issuable_collection_name}/#{issuable.iid}/add_spent_time", user), params: { duration: '-1w' }
end.not_to change { issuable.reload.updated_at }
end
diff --git a/spec/support/controllers/githubish_import_controller_shared_examples.rb b/spec/support/controllers/githubish_import_controller_shared_examples.rb
index 140490f2dc2..697f999e4c4 100644
--- a/spec/support/controllers/githubish_import_controller_shared_examples.rb
+++ b/spec/support/controllers/githubish_import_controller_shared_examples.rb
@@ -17,7 +17,7 @@ shared_examples 'a GitHub-ish import controller: POST personal_access_token' do
allow_any_instance_of(Gitlab::LegacyGithubImport::Client)
.to receive(:user).and_return(true)
- post :personal_access_token, personal_access_token: token
+ post :personal_access_token, params: { personal_access_token: token }
expect(session[:"#{provider}_access_token"]).to eq(token)
expect(controller).to redirect_to(status_import_url)
@@ -29,7 +29,7 @@ shared_examples 'a GitHub-ish import controller: POST personal_access_token' do
allow_any_instance_of(Gitlab::LegacyGithubImport::Client)
.to receive(:user).and_return(true)
- post :personal_access_token, personal_access_token: " #{token} "
+ post :personal_access_token, params: { personal_access_token: " #{token} " }
expect(session[:"#{provider}_access_token"]).to eq(token)
expect(controller).to redirect_to(status_import_url)
@@ -214,7 +214,7 @@ shared_examples 'a GitHub-ish import controller: POST create' do
expect(Gitlab::LegacyGithubImport::ProjectCreator)
.to receive(:new).and_return(double(execute: project))
- expect { post :create, target_namespace: provider_repo.name, format: :json }.to change(Namespace, :count).by(1)
+ expect { post :create, params: { target_namespace: provider_repo.name }, format: :json }.to change(Namespace, :count).by(1)
end
it "takes the new namespace" do
@@ -222,7 +222,7 @@ shared_examples 'a GitHub-ish import controller: POST create' do
.to receive(:new).with(provider_repo, provider_repo.name, an_instance_of(Group), user, access_params, type: provider)
.and_return(double(execute: project))
- post :create, target_namespace: provider_repo.name, format: :json
+ post :create, params: { target_namespace: provider_repo.name }, format: :json
end
end
@@ -261,7 +261,7 @@ shared_examples 'a GitHub-ish import controller: POST create' do
.to receive(:new).with(provider_repo, test_name, test_namespace, user, access_params, type: provider)
.and_return(double(execute: project))
- post :create, { target_namespace: test_namespace.name, new_name: test_name, format: :json }
+ post :create, params: { target_namespace: test_namespace.name, new_name: test_name }, format: :json
end
it 'takes the selected name and default namespace' do
@@ -269,7 +269,7 @@ shared_examples 'a GitHub-ish import controller: POST create' do
.to receive(:new).with(provider_repo, test_name, user.namespace, user, access_params, type: provider)
.and_return(double(execute: project))
- post :create, { new_name: test_name, format: :json }
+ post :create, params: { new_name: test_name }, format: :json
end
end
@@ -288,7 +288,7 @@ shared_examples 'a GitHub-ish import controller: POST create' do
.to receive(:new).with(provider_repo, test_name, nested_namespace, user, access_params, type: provider)
.and_return(double(execute: project))
- post :create, { target_namespace: nested_namespace.full_path, new_name: test_name, format: :json }
+ post :create, params: { target_namespace: nested_namespace.full_path, new_name: test_name }, format: :json
end
end
@@ -300,7 +300,7 @@ shared_examples 'a GitHub-ish import controller: POST create' do
.to receive(:new).with(provider_repo, test_name, kind_of(Namespace), user, access_params, type: provider)
.and_return(double(execute: project))
- post :create, { target_namespace: 'foo/bar', new_name: test_name, format: :json }
+ post :create, params: { target_namespace: 'foo/bar', new_name: test_name }, format: :json
end
it 'creates the namespaces' do
@@ -308,7 +308,7 @@ shared_examples 'a GitHub-ish import controller: POST create' do
.to receive(:new).with(provider_repo, test_name, kind_of(Namespace), user, access_params, type: provider)
.and_return(double(execute: project))
- expect { post :create, { target_namespace: 'foo/bar', new_name: test_name, format: :json } }
+ expect { post :create, params: { target_namespace: 'foo/bar', new_name: test_name }, format: :json }
.to change { Namespace.count }.by(2)
end
@@ -317,7 +317,7 @@ shared_examples 'a GitHub-ish import controller: POST create' do
.to receive(:new).with(provider_repo, test_name, kind_of(Namespace), user, access_params, type: provider)
.and_return(double(execute: project))
- post :create, { target_namespace: 'foo/bar', new_name: test_name, format: :json }
+ post :create, params: { target_namespace: 'foo/bar', new_name: test_name }, format: :json
expect(Namespace.find_by_path_or_name('bar').parent.path).to eq('foo')
end
@@ -336,7 +336,7 @@ shared_examples 'a GitHub-ish import controller: POST create' do
.to receive(:new).with(provider_repo, test_name, kind_of(Namespace), user, access_params, type: provider)
.and_return(double(execute: project))
- post :create, { target_namespace: 'foo/foobar/bar', new_name: test_name, format: :json }
+ post :create, params: { target_namespace: 'foo/foobar/bar', new_name: test_name }, format: :json
end
it 'creates the namespaces' do
@@ -344,7 +344,7 @@ shared_examples 'a GitHub-ish import controller: POST create' do
.to receive(:new).with(provider_repo, test_name, kind_of(Namespace), user, access_params, type: provider)
.and_return(double(execute: project))
- expect { post :create, { target_namespace: 'foo/foobar/bar', new_name: test_name, format: :json } }
+ expect { post :create, params: { target_namespace: 'foo/foobar/bar', new_name: test_name }, format: :json }
.to change { Namespace.count }.by(2)
end
@@ -353,7 +353,7 @@ shared_examples 'a GitHub-ish import controller: POST create' do
.to receive(:new).with(provider_repo, test_name, user.namespace, user, access_params, type: provider)
.and_return(double(execute: build_stubbed(:project)))
- expect { post :create, { target_namespace: "#{user.namespace_path}/test_group", new_name: test_name, format: :js } }
+ expect { post :create, params: { target_namespace: "#{user.namespace_path}/test_group", new_name: test_name }, format: :js }
.not_to change { Namespace.count }
end
end
@@ -367,7 +367,7 @@ shared_examples 'a GitHub-ish import controller: POST create' do
.to receive(:new).with(provider_repo, test_name, user.namespace, user, access_params, type: provider)
.and_return(double(execute: build_stubbed(:project)))
- post :create, { target_namespace: 'foo/foobar/bar', new_name: test_name, format: :js }
+ post :create, params: { target_namespace: 'foo/foobar/bar', new_name: test_name }, format: :js
end
it 'does not create the namespaces' do
@@ -375,7 +375,7 @@ shared_examples 'a GitHub-ish import controller: POST create' do
.to receive(:new).with(provider_repo, test_name, kind_of(Namespace), user, access_params, type: provider)
.and_return(double(execute: build_stubbed(:project)))
- expect { post :create, { target_namespace: 'foo/foobar/bar', new_name: test_name, format: :js } }
+ expect { post :create, params: { target_namespace: 'foo/foobar/bar', new_name: test_name }, format: :js }
.not_to change { Namespace.count }
end
end
@@ -392,7 +392,7 @@ shared_examples 'a GitHub-ish import controller: POST create' do
.to receive(:new).with(provider_repo, test_name, group, user, access_params, type: provider)
.and_return(double(execute: build_stubbed(:project)))
- post :create, { target_namespace: 'foo', new_name: test_name, format: :js }
+ post :create, params: { target_namespace: 'foo', new_name: test_name }, format: :js
end
end
@@ -400,7 +400,7 @@ shared_examples 'a GitHub-ish import controller: POST create' do
it 'returns 422 response' do
other_namespace = create(:group, name: 'other_namespace')
- post :create, { target_namespace: other_namespace.name, format: :json }
+ post :create, params: { target_namespace: other_namespace.name }, format: :json
expect(response).to have_gitlab_http_status(422)
end
diff --git a/spec/support/features/variable_list_shared_examples.rb b/spec/support/features/variable_list_shared_examples.rb
index bce1fb01355..0a464d77cb7 100644
--- a/spec/support/features/variable_list_shared_examples.rb
+++ b/spec/support/features/variable_list_shared_examples.rb
@@ -63,6 +63,52 @@ shared_examples 'variable list' do
end
end
+ context 'defaults to the application setting' do
+ context 'application setting is true' do
+ before do
+ stub_application_setting(protected_ci_variables: true)
+
+ visit page_path
+ end
+
+ it 'defaults to protected' do
+ page.within('.js-ci-variable-list-section .js-row:last-child') do
+ find('.js-ci-variable-input-key').set('key')
+ end
+
+ values = all('.js-ci-variable-input-protected', visible: false).map(&:value)
+
+ expect(values).to eq %w(false true true)
+ end
+
+ it 'shows a message regarding the changed default' do
+ expect(page).to have_content 'Environment variables are configured by your administrator to be protected by default'
+ end
+ end
+
+ context 'application setting is false' do
+ before do
+ stub_application_setting(protected_ci_variables: false)
+
+ visit page_path
+ end
+
+ it 'defaults to unprotected' do
+ page.within('.js-ci-variable-list-section .js-row:last-child') do
+ find('.js-ci-variable-input-key').set('key')
+ end
+
+ values = all('.js-ci-variable-input-protected', visible: false).map(&:value)
+
+ expect(values).to eq %w(false false false)
+ end
+
+ it 'does not show a message regarding the default' do
+ expect(page).not_to have_content 'Environment variables are configured by your administrator to be protected by default'
+ end
+ end
+ end
+
it 'reveals and hides variables' do
page.within('.js-ci-variable-list-section') do
expect(first('.js-ci-variable-input-key').value).to eq(variable.key)
diff --git a/spec/support/helpers/git_http_helpers.rb b/spec/support/helpers/git_http_helpers.rb
index 9a5845af90c..cd49bb148f2 100644
--- a/spec/support/helpers/git_http_helpers.rb
+++ b/spec/support/helpers/git_http_helpers.rb
@@ -1,18 +1,18 @@
module GitHttpHelpers
def clone_get(project, options = {})
- get "/#{project}/info/refs", { service: 'git-upload-pack' }, auth_env(*options.values_at(:user, :password, :spnego_request_token))
+ get "/#{project}/info/refs", params: { service: 'git-upload-pack' }, headers: auth_env(*options.values_at(:user, :password, :spnego_request_token))
end
def clone_post(project, options = {})
- post "/#{project}/git-upload-pack", {}, auth_env(*options.values_at(:user, :password, :spnego_request_token))
+ post "/#{project}/git-upload-pack", headers: auth_env(*options.values_at(:user, :password, :spnego_request_token))
end
def push_get(project, options = {})
- get "/#{project}/info/refs", { service: 'git-receive-pack' }, auth_env(*options.values_at(:user, :password, :spnego_request_token))
+ get "/#{project}/info/refs", params: { service: 'git-receive-pack' }, headers: auth_env(*options.values_at(:user, :password, :spnego_request_token))
end
def push_post(project, options = {})
- post "/#{project}/git-receive-pack", {}, auth_env(*options.values_at(:user, :password, :spnego_request_token))
+ post "/#{project}/git-receive-pack", headers: auth_env(*options.values_at(:user, :password, :spnego_request_token))
end
def download(project, user: nil, password: nil, spnego_request_token: nil)
diff --git a/spec/support/helpers/graphql_helpers.rb b/spec/support/helpers/graphql_helpers.rb
index 75827df80dc..dd32ea3985f 100644
--- a/spec/support/helpers/graphql_helpers.rb
+++ b/spec/support/helpers/graphql_helpers.rb
@@ -107,7 +107,7 @@ module GraphqlHelpers
end
def post_graphql(query, current_user: nil, variables: nil)
- post api('/', current_user, version: 'graphql'), query: query, variables: variables
+ post api('/', current_user, version: 'graphql'), params: { query: query, variables: variables }
end
def post_graphql_mutation(mutation, current_user: nil)
diff --git a/spec/support/import_export/export_file_helper.rb b/spec/support/import_export/export_file_helper.rb
index a49036c3b80..ac320934f5a 100644
--- a/spec/support/import_export/export_file_helper.rb
+++ b/spec/support/import_export/export_file_helper.rb
@@ -133,6 +133,6 @@ module ExportFileHelper
end
def file_permissions(file)
- File.stat(file).mode & 0777
+ File.lstat(file).mode & 0777
end
end
diff --git a/spec/support/issuables_requiring_filter_shared_examples.rb b/spec/support/issuables_requiring_filter_shared_examples.rb
index 439ef5ed92e..71bcc82ee58 100644
--- a/spec/support/issuables_requiring_filter_shared_examples.rb
+++ b/spec/support/issuables_requiring_filter_shared_examples.rb
@@ -10,6 +10,6 @@ shared_examples 'issuables requiring filter' do |action|
it "loads issuables if at least one filter is set" do
expect_any_instance_of(described_class).to receive(:issuables_collection).and_call_original
- get action, author_id: user.id
+ get action, params: { author_id: user.id }
end
end
diff --git a/spec/support/shared_examples/controllers/uploads_actions_shared_examples.rb b/spec/support/shared_examples/controllers/uploads_actions_shared_examples.rb
index 7088fb1e5fb..59708173716 100644
--- a/spec/support/shared_examples/controllers/uploads_actions_shared_examples.rb
+++ b/spec/support/shared_examples/controllers/uploads_actions_shared_examples.rb
@@ -8,8 +8,7 @@ shared_examples 'handle uploads' do
describe "POST #create" do
context 'when a user is not authorized to upload a file' do
it 'returns 404 status' do
- post :create, params.merge(file: jpg, format: :json)
-
+ post :create, params: params.merge(file: jpg), format: :json
expect(response.status).to eq(404)
end
end
@@ -22,7 +21,7 @@ shared_examples 'handle uploads' do
context "without params['file']" do
it "returns an error" do
- post :create, params.merge(format: :json)
+ post :create, params: params, format: :json
expect(response).to have_gitlab_http_status(422)
end
@@ -30,7 +29,7 @@ shared_examples 'handle uploads' do
context 'with valid image' do
before do
- post :create, params.merge(file: jpg, format: :json)
+ post :create, params: params.merge(file: jpg), format: :json
end
it 'returns a content with original filename, new link, and correct type.' do
@@ -54,7 +53,7 @@ shared_examples 'handle uploads' do
context 'with valid non-image file' do
before do
- post :create, params.merge(file: txt, format: :json)
+ post :create, params: params.merge(file: txt), format: :json
end
it 'returns a content with original filename, new link, and correct type.' do
@@ -67,7 +66,7 @@ shared_examples 'handle uploads' do
describe "GET #show" do
let(:show_upload) do
- get :show, params.merge(secret: secret, filename: "rails_sample.jpg")
+ get :show, params: params.merge(secret: secret, filename: "rails_sample.jpg")
end
before do
diff --git a/spec/support/shared_examples/milestone_tabs_examples.rb b/spec/support/shared_examples/milestone_tabs_examples.rb
index 70b499198bf..8b757586941 100644
--- a/spec/support/shared_examples/milestone_tabs_examples.rb
+++ b/spec/support/shared_examples/milestone_tabs_examples.rb
@@ -10,7 +10,7 @@ shared_examples 'milestone tabs' do
{ namespace_id: project.namespace.to_param, project_id: project, id: milestone.iid }
end
- get path, params.merge(extra_params)
+ get path, params: params.merge(extra_params)
end
describe '#merge_requests' do
diff --git a/spec/support/shared_examples/requests/api/diff_discussions.rb b/spec/support/shared_examples/requests/api/diff_discussions.rb
index 85a4bd8ca27..366c2955359 100644
--- a/spec/support/shared_examples/requests/api/diff_discussions.rb
+++ b/spec/support/shared_examples/requests/api/diff_discussions.rb
@@ -27,7 +27,8 @@ shared_examples 'diff discussions API' do |parent_type, noteable_type, id_name|
it "creates a new diff note" do
position = diff_note.position.to_h
- post api("/#{parent_type}/#{parent.id}/#{noteable_type}/#{noteable[id_name]}/discussions", user), body: 'hi!', position: position
+ post api("/#{parent_type}/#{parent.id}/#{noteable_type}/#{noteable[id_name]}/discussions", user),
+ params: { body: 'hi!', position: position }
expect(response).to have_gitlab_http_status(201)
expect(json_response['notes'].first['body']).to eq('hi!')
@@ -38,7 +39,8 @@ shared_examples 'diff discussions API' do |parent_type, noteable_type, id_name|
it "returns a 400 bad request error when position is invalid" do
position = diff_note.position.to_h.merge(new_line: '100000')
- post api("/#{parent_type}/#{parent.id}/#{noteable_type}/#{noteable[id_name]}/discussions", user), body: 'hi!', position: position
+ post api("/#{parent_type}/#{parent.id}/#{noteable_type}/#{noteable[id_name]}/discussions", user),
+ params: { body: 'hi!', position: position }
expect(response).to have_gitlab_http_status(400)
end
@@ -47,7 +49,7 @@ shared_examples 'diff discussions API' do |parent_type, noteable_type, id_name|
describe "POST /#{parent_type}/:id/#{noteable_type}/:noteable_id/discussions/:discussion_id/notes" do
it 'adds a new note to the diff discussion' do
post api("/#{parent_type}/#{parent.id}/#{noteable_type}/#{noteable[id_name]}/"\
- "discussions/#{diff_note.discussion_id}/notes", user), body: 'hi!'
+ "discussions/#{diff_note.discussion_id}/notes", user), params: { body: 'hi!' }
expect(response).to have_gitlab_http_status(201)
expect(json_response['body']).to eq('hi!')
diff --git a/spec/support/shared_examples/requests/api/discussions.rb b/spec/support/shared_examples/requests/api/discussions.rb
index b6aeb30d69c..e44da4faa5a 100644
--- a/spec/support/shared_examples/requests/api/discussions.rb
+++ b/spec/support/shared_examples/requests/api/discussions.rb
@@ -42,7 +42,7 @@ shared_examples 'discussions API' do |parent_type, noteable_type, id_name|
describe "POST /#{parent_type}/:id/#{noteable_type}/:noteable_id/discussions" do
it "creates a new note" do
- post api("/#{parent_type}/#{parent.id}/#{noteable_type}/#{noteable[id_name]}/discussions", user), body: 'hi!'
+ post api("/#{parent_type}/#{parent.id}/#{noteable_type}/#{noteable[id_name]}/discussions", user), params: { body: 'hi!' }
expect(response).to have_gitlab_http_status(201)
expect(json_response['notes'].first['body']).to eq('hi!')
@@ -56,7 +56,7 @@ shared_examples 'discussions API' do |parent_type, noteable_type, id_name|
end
it "returns a 401 unauthorized error if user not authenticated" do
- post api("/#{parent_type}/#{parent.id}/#{noteable_type}/#{noteable[id_name]}/discussions"), body: 'hi!'
+ post api("/#{parent_type}/#{parent.id}/#{noteable_type}/#{noteable[id_name]}/discussions"), params: { body: 'hi!' }
expect(response).to have_gitlab_http_status(401)
end
@@ -65,7 +65,7 @@ shared_examples 'discussions API' do |parent_type, noteable_type, id_name|
it 'accepts the creation date to be set' do
creation_time = 2.weeks.ago
post api("/#{parent_type}/#{parent.id}/#{noteable_type}/#{noteable[id_name]}/discussions", user),
- body: 'hi!', created_at: creation_time
+ params: { body: 'hi!', created_at: creation_time }
expect(response).to have_gitlab_http_status(201)
expect(json_response['notes'].first['body']).to eq('hi!')
@@ -81,7 +81,7 @@ shared_examples 'discussions API' do |parent_type, noteable_type, id_name|
it 'responds with 404' do
post api("/#{parent_type}/#{parent.id}/#{noteable_type}/#{noteable[id_name]}/discussions", private_user),
- body: 'Foo'
+ params: { body: 'Foo' }
expect(response).to have_gitlab_http_status(404)
end
@@ -91,7 +91,7 @@ shared_examples 'discussions API' do |parent_type, noteable_type, id_name|
describe "POST /#{parent_type}/:id/#{noteable_type}/:noteable_id/discussions/:discussion_id/notes" do
it 'adds a new note to the discussion' do
post api("/#{parent_type}/#{parent.id}/#{noteable_type}/#{noteable[id_name]}/"\
- "discussions/#{note.discussion_id}/notes", user), body: 'Hello!'
+ "discussions/#{note.discussion_id}/notes", user), params: { body: 'Hello!' }
expect(response).to have_gitlab_http_status(201)
expect(json_response['body']).to eq('Hello!')
@@ -109,7 +109,7 @@ shared_examples 'discussions API' do |parent_type, noteable_type, id_name|
note.update_attribute(:type, nil)
post api("/#{parent_type}/#{parent.id}/#{noteable_type}/#{noteable[id_name]}/"\
- "discussions/#{note.discussion_id}/notes", user), body: 'hi!'
+ "discussions/#{note.discussion_id}/notes", user), params: { body: 'hi!' }
expect(response).to have_gitlab_http_status(400)
end
@@ -118,7 +118,7 @@ shared_examples 'discussions API' do |parent_type, noteable_type, id_name|
describe "PUT /#{parent_type}/:id/#{noteable_type}/:noteable_id/discussions/:discussion_id/notes/:note_id" do
it 'returns modified note' do
put api("/#{parent_type}/#{parent.id}/#{noteable_type}/#{noteable[id_name]}/"\
- "discussions/#{note.discussion_id}/notes/#{note.id}", user), body: 'Hello!'
+ "discussions/#{note.discussion_id}/notes/#{note.id}", user), params: { body: 'Hello!' }
expect(response).to have_gitlab_http_status(200)
expect(json_response['body']).to eq('Hello!')
@@ -127,7 +127,7 @@ shared_examples 'discussions API' do |parent_type, noteable_type, id_name|
it 'returns a 404 error when note id not found' do
put api("/#{parent_type}/#{parent.id}/#{noteable_type}/#{noteable[id_name]}/"\
"discussions/#{note.discussion_id}/notes/12345", user),
- body: 'Hello!'
+ params: { body: 'Hello!' }
expect(response).to have_gitlab_http_status(404)
end
diff --git a/spec/support/shared_examples/requests/api/merge_requests_list.rb b/spec/support/shared_examples/requests/api/merge_requests_list.rb
index 92d4dd598d5..453f42251c8 100644
--- a/spec/support/shared_examples/requests/api/merge_requests_list.rb
+++ b/spec/support/shared_examples/requests/api/merge_requests_list.rb
@@ -123,7 +123,7 @@ shared_examples 'merge requests list' do
end
it 'returns an empty array if no issue matches milestone' do
- get api(endpoint_path, user), milestone: '1.0.0'
+ get api(endpoint_path, user), params: { milestone: '1.0.0' }
expect(response).to have_gitlab_http_status(200)
expect(json_response).to be_an Array
@@ -131,7 +131,7 @@ shared_examples 'merge requests list' do
end
it 'returns an empty array if milestone does not exist' do
- get api(endpoint_path, user), milestone: 'foo'
+ get api(endpoint_path, user), params: { milestone: 'foo' }
expect(response).to have_gitlab_http_status(200)
expect(json_response).to be_an Array
@@ -139,7 +139,7 @@ shared_examples 'merge requests list' do
end
it 'returns an array of merge requests in given milestone' do
- get api(endpoint_path, user), milestone: '0.9'
+ get api(endpoint_path, user), params: { milestone: '0.9' }
closed_issues = json_response.select { |mr| mr['id'] == merge_request_closed.id }
expect(closed_issues.length).to eq(1)
@@ -147,7 +147,7 @@ shared_examples 'merge requests list' do
end
it 'returns an array of merge requests matching state in milestone' do
- get api(endpoint_path, user), milestone: '0.9', state: 'closed'
+ get api(endpoint_path, user), params: { milestone: '0.9', state: 'closed' }
expect(response).to have_gitlab_http_status(200)
expect(json_response).to be_an Array
@@ -187,7 +187,7 @@ shared_examples 'merge requests list' do
end
it 'returns an array of merge requests with any label when filtering by any label' do
- get api(endpoint_path, user), labels: IssuesFinder::FILTER_ANY
+ get api(endpoint_path, user), params: { labels: IssuesFinder::FILTER_ANY }
expect_paginated_array_response
expect(json_response.length).to eq(1)
@@ -195,7 +195,7 @@ shared_examples 'merge requests list' do
end
it 'returns an array of merge requests without a label when filtering by no label' do
- get api(endpoint_path, user), labels: IssuesFinder::FILTER_NONE
+ get api(endpoint_path, user), params: { labels: IssuesFinder::FILTER_NONE }
response_ids = json_response.map { |merge_request| merge_request['id'] }
@@ -286,7 +286,7 @@ shared_examples 'merge requests list' do
context 'source_branch param' do
it 'returns merge requests with the given source branch' do
- get api(endpoint_path, user), source_branch: merge_request_closed.source_branch, state: 'all'
+ get api(endpoint_path, user), params: { source_branch: merge_request_closed.source_branch, state: 'all' }
expect_response_contain_exactly(merge_request_closed, merge_request_merged, merge_request_locked)
end
@@ -294,7 +294,7 @@ shared_examples 'merge requests list' do
context 'target_branch param' do
it 'returns merge requests with the given target branch' do
- get api(endpoint_path, user), target_branch: merge_request_closed.target_branch, state: 'all'
+ get api(endpoint_path, user), params: { target_branch: merge_request_closed.target_branch, state: 'all' }
expect_response_contain_exactly(merge_request_closed, merge_request_merged, merge_request_locked)
end
diff --git a/spec/support/shared_examples/requests/api/notes.rb b/spec/support/shared_examples/requests/api/notes.rb
index 0e20dfe0725..71499e85654 100644
--- a/spec/support/shared_examples/requests/api/notes.rb
+++ b/spec/support/shared_examples/requests/api/notes.rb
@@ -86,7 +86,7 @@ shared_examples 'noteable API' do |parent_type, noteable_type, id_name|
describe "POST /#{parent_type}/:id/#{noteable_type}/:noteable_id/notes" do
it "creates a new note" do
- post api("/#{parent_type}/#{parent.id}/#{noteable_type}/#{noteable[id_name]}/notes", user), body: 'hi!'
+ post api("/#{parent_type}/#{parent.id}/#{noteable_type}/#{noteable[id_name]}/notes", user), params: { body: 'hi!' }
expect(response).to have_gitlab_http_status(201)
expect(json_response['body']).to eq('hi!')
@@ -100,7 +100,7 @@ shared_examples 'noteable API' do |parent_type, noteable_type, id_name|
end
it "returns a 401 unauthorized error if user not authenticated" do
- post api("/#{parent_type}/#{parent.id}/#{noteable_type}/#{noteable[id_name]}/notes"), body: 'hi!'
+ post api("/#{parent_type}/#{parent.id}/#{noteable_type}/#{noteable[id_name]}/notes"), params: { body: 'hi!' }
expect(response).to have_gitlab_http_status(401)
end
@@ -108,7 +108,7 @@ shared_examples 'noteable API' do |parent_type, noteable_type, id_name|
it "creates an activity event when a note is created" do
expect(Event).to receive(:create!)
- post api("/#{parent_type}/#{parent.id}/#{noteable_type}/#{noteable[id_name]}/notes", user), body: 'hi!'
+ post api("/#{parent_type}/#{parent.id}/#{noteable_type}/#{noteable[id_name]}/notes", user), params: { body: 'hi!' }
end
context 'setting created_at' do
@@ -118,7 +118,7 @@ shared_examples 'noteable API' do |parent_type, noteable_type, id_name|
context 'by an admin' do
it 'sets the creation time on the new note' do
admin = create(:admin)
- post api("/#{parent_type}/#{parent.id}/#{noteable_type}/#{noteable[id_name]}/notes", admin), params
+ post api("/#{parent_type}/#{parent.id}/#{noteable_type}/#{noteable[id_name]}/notes", admin), params: params
expect(response).to have_gitlab_http_status(201)
expect(json_response['body']).to eq('hi!')
@@ -131,7 +131,7 @@ shared_examples 'noteable API' do |parent_type, noteable_type, id_name|
if parent_type == 'projects'
context 'by a project owner' do
it 'sets the creation time on the new note' do
- post api("/#{parent_type}/#{parent.id}/#{noteable_type}/#{noteable[id_name]}/notes", user), params
+ post api("/#{parent_type}/#{parent.id}/#{noteable_type}/#{noteable[id_name]}/notes", user), params: params
expect(response).to have_gitlab_http_status(201)
expect(json_response['body']).to eq('hi!')
@@ -149,7 +149,7 @@ shared_examples 'noteable API' do |parent_type, noteable_type, id_name|
parent.update!(namespace: group)
user2.refresh_authorized_projects
- post api("/#{parent_type}/#{parent.id}/#{noteable_type}/#{noteable[id_name]}/notes", user2), params
+ post api("/#{parent_type}/#{parent.id}/#{noteable_type}/#{noteable[id_name]}/notes", user2), params: params
expect(response).to have_gitlab_http_status(201)
expect(json_response['body']).to eq('hi!')
@@ -161,7 +161,7 @@ shared_examples 'noteable API' do |parent_type, noteable_type, id_name|
elsif parent_type == 'groups'
context 'by a group owner' do
it 'sets the creation time on the new note' do
- post api("/#{parent_type}/#{parent.id}/#{noteable_type}/#{noteable[id_name]}/notes", user), params
+ post api("/#{parent_type}/#{parent.id}/#{noteable_type}/#{noteable[id_name]}/notes", user), params: params
expect(response).to have_gitlab_http_status(201)
expect(json_response['body']).to eq('hi!')
@@ -176,7 +176,7 @@ shared_examples 'noteable API' do |parent_type, noteable_type, id_name|
it 'ignores the given creation time' do
user2 = create(:user)
parent.add_developer(user2)
- post api("/#{parent_type}/#{parent.id}/#{noteable_type}/#{noteable[id_name]}/notes", user2), params
+ post api("/#{parent_type}/#{parent.id}/#{noteable_type}/#{noteable[id_name]}/notes", user2), params: params
expect(response).to have_gitlab_http_status(201)
expect(json_response['body']).to eq('hi!')
@@ -190,7 +190,7 @@ shared_examples 'noteable API' do |parent_type, noteable_type, id_name|
context 'when the user is posting an award emoji on a noteable created by someone else' do
it 'creates a new note' do
parent.add_developer(private_user)
- post api("/#{parent_type}/#{parent.id}/#{noteable_type}/#{noteable[id_name]}/notes", private_user), body: ':+1:'
+ post api("/#{parent_type}/#{parent.id}/#{noteable_type}/#{noteable[id_name]}/notes", private_user), params: { body: ':+1:' }
expect(response).to have_gitlab_http_status(201)
expect(json_response['body']).to eq(':+1:')
@@ -199,7 +199,7 @@ shared_examples 'noteable API' do |parent_type, noteable_type, id_name|
context 'when the user is posting an award emoji on his/her own noteable' do
it 'creates a new note' do
- post api("/#{parent_type}/#{parent.id}/#{noteable_type}/#{noteable[id_name]}/notes", user), body: ':+1:'
+ post api("/#{parent_type}/#{parent.id}/#{noteable_type}/#{noteable[id_name]}/notes", user), params: { body: ':+1:' }
expect(response).to have_gitlab_http_status(201)
expect(json_response['body']).to eq(':+1:')
@@ -213,7 +213,7 @@ shared_examples 'noteable API' do |parent_type, noteable_type, id_name|
it 'responds with 404' do
post api("/#{parent_type}/#{parent.id}/#{noteable_type}/#{noteable[id_name]}/notes", private_user),
- body: 'Foo'
+ params: { body: 'Foo' }
expect(response).to have_gitlab_http_status(404)
end
@@ -223,7 +223,7 @@ shared_examples 'noteable API' do |parent_type, noteable_type, id_name|
describe "PUT /#{parent_type}/:id/#{noteable_type}/:noteable_id/notes/:note_id" do
it 'returns modified note' do
put api("/#{parent_type}/#{parent.id}/#{noteable_type}/#{noteable[id_name]}/"\
- "notes/#{note.id}", user), body: 'Hello!'
+ "notes/#{note.id}", user), params: { body: 'Hello!' }
expect(response).to have_gitlab_http_status(200)
expect(json_response['body']).to eq('Hello!')
@@ -231,7 +231,7 @@ shared_examples 'noteable API' do |parent_type, noteable_type, id_name|
it 'returns a 404 error when note id not found' do
put api("/#{parent_type}/#{parent.id}/#{noteable_type}/#{noteable[id_name]}/notes/12345", user),
- body: 'Hello!'
+ params: { body: 'Hello!' }
expect(response).to have_gitlab_http_status(404)
end
diff --git a/spec/support/shared_examples/requests/api/resolvable_discussions.rb b/spec/support/shared_examples/requests/api/resolvable_discussions.rb
index 408ad08cc48..7e2416b23f3 100644
--- a/spec/support/shared_examples/requests/api/resolvable_discussions.rb
+++ b/spec/support/shared_examples/requests/api/resolvable_discussions.rb
@@ -2,7 +2,7 @@ shared_examples 'resolvable discussions API' do |parent_type, noteable_type, id_
describe "PUT /#{parent_type}/:id/#{noteable_type}/:noteable_id/discussions/:discussion_id" do
it "resolves discussion if resolved is true" do
put api("/#{parent_type}/#{parent.id}/#{noteable_type}/#{noteable[id_name]}/"\
- "discussions/#{note.discussion_id}", user), resolved: true
+ "discussions/#{note.discussion_id}", user), params: { resolved: true }
expect(response).to have_gitlab_http_status(200)
expect(json_response['notes'].size).to eq(1)
@@ -11,7 +11,7 @@ shared_examples 'resolvable discussions API' do |parent_type, noteable_type, id_
it "unresolves discussion if resolved is false" do
put api("/#{parent_type}/#{parent.id}/#{noteable_type}/#{noteable[id_name]}/"\
- "discussions/#{note.discussion_id}", user), resolved: false
+ "discussions/#{note.discussion_id}", user), params: { resolved: false }
expect(response).to have_gitlab_http_status(200)
expect(json_response['notes'].size).to eq(1)
@@ -27,14 +27,14 @@ shared_examples 'resolvable discussions API' do |parent_type, noteable_type, id_
it "returns a 401 unauthorized error if user is not authenticated" do
put api("/#{parent_type}/#{parent.id}/#{noteable_type}/#{noteable[id_name]}/"\
- "discussions/#{note.discussion_id}"), resolved: true
+ "discussions/#{note.discussion_id}"), params: { resolved: true }
expect(response).to have_gitlab_http_status(401)
end
it "returns a 403 error if user resolves discussion of someone else" do
put api("/#{parent_type}/#{parent.id}/#{noteable_type}/#{noteable[id_name]}/"\
- "discussions/#{note.discussion_id}", private_user), resolved: true
+ "discussions/#{note.discussion_id}", private_user), params: { resolved: true }
expect(response).to have_gitlab_http_status(403)
end
@@ -46,7 +46,7 @@ shared_examples 'resolvable discussions API' do |parent_type, noteable_type, id_
it 'responds with 404' do
put api("/#{parent_type}/#{parent.id}/#{noteable_type}/#{noteable[id_name]}/"\
- "discussions/#{note.discussion_id}", private_user), resolved: true
+ "discussions/#{note.discussion_id}", private_user), params: { resolved: true }
expect(response).to have_gitlab_http_status(404)
end
@@ -56,7 +56,7 @@ shared_examples 'resolvable discussions API' do |parent_type, noteable_type, id_
describe "PUT /#{parent_type}/:id/#{noteable_type}/:noteable_id/discussions/:discussion_id/notes/:note_id" do
it 'returns resolved note when resolved parameter is true' do
put api("/#{parent_type}/#{parent.id}/#{noteable_type}/#{noteable[id_name]}/"\
- "discussions/#{note.discussion_id}/notes/#{note.id}", user), resolved: true
+ "discussions/#{note.discussion_id}/notes/#{note.id}", user), params: { resolved: true }
expect(response).to have_gitlab_http_status(200)
expect(json_response['resolved']).to eq(true)
@@ -65,7 +65,7 @@ shared_examples 'resolvable discussions API' do |parent_type, noteable_type, id_
it 'returns a 404 error when note id not found' do
put api("/#{parent_type}/#{parent.id}/#{noteable_type}/#{noteable[id_name]}/"\
"discussions/#{note.discussion_id}/notes/12345", user),
- body: 'Hello!'
+ params: { body: 'Hello!' }
expect(response).to have_gitlab_http_status(404)
end
@@ -79,7 +79,7 @@ shared_examples 'resolvable discussions API' do |parent_type, noteable_type, id_
it "returns a 403 error if user resolves note of someone else" do
put api("/#{parent_type}/#{parent.id}/#{noteable_type}/#{noteable[id_name]}/"\
- "discussions/#{note.discussion_id}/notes/#{note.id}", private_user), resolved: true
+ "discussions/#{note.discussion_id}/notes/#{note.id}", private_user), params: { resolved: true }
expect(response).to have_gitlab_http_status(403)
end
diff --git a/spec/tasks/gitlab/storage_rake_spec.rb b/spec/tasks/gitlab/storage_rake_spec.rb
index 233076ad6fa..be902d7c679 100644
--- a/spec/tasks/gitlab/storage_rake_spec.rb
+++ b/spec/tasks/gitlab/storage_rake_spec.rb
@@ -46,6 +46,16 @@ describe 'rake gitlab:storage:*' do
describe 'gitlab:storage:migrate_to_hashed' do
let(:task) { 'gitlab:storage:migrate_to_hashed' }
+ context 'read-only database' do
+ it 'does nothing' do
+ expect(Gitlab::Database).to receive(:read_only?).and_return(true)
+
+ expect(Project).not_to receive(:with_unmigrated_storage)
+
+ expect { run_rake_task(task) }.to output(/This task requires database write access. Exiting./).to_stderr
+ end
+ end
+
context '0 legacy projects' do
it 'does nothing' do
expect(StorageMigratorWorker).not_to receive(:perform_async)
@@ -92,7 +102,7 @@ describe 'rake gitlab:storage:*' do
stub_env('ID_FROM', 99999)
stub_env('ID_TO', 99999)
- expect { run_rake_task(task) }.to output(/There are no projects requiring storage migration with ID=99999/).to_stdout
+ expect { run_rake_task(task) }.to output(/There are no projects requiring storage migration with ID=99999/).to_stderr
end
it 'displays a message when project exists but its already migrated' do
@@ -100,7 +110,7 @@ describe 'rake gitlab:storage:*' do
stub_env('ID_FROM', project.id)
stub_env('ID_TO', project.id)
- expect { run_rake_task(task) }.to output(/There are no projects requiring storage migration with ID=#{project.id}/).to_stdout
+ expect { run_rake_task(task) }.to output(/There are no projects requiring storage migration with ID=#{project.id}/).to_stderr
end
it 'enqueues migration when project can be found' do
diff --git a/spec/views/notify/changed_milestone_email.html.haml_spec.rb b/spec/views/notify/changed_milestone_email.html.haml_spec.rb
new file mode 100644
index 00000000000..194b58840a3
--- /dev/null
+++ b/spec/views/notify/changed_milestone_email.html.haml_spec.rb
@@ -0,0 +1,35 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe 'notify/changed_milestone_email.html.haml' do
+ let(:milestone) { create(:milestone, title: 'some-milestone') }
+ let(:milestone_link) { milestone_url(milestone) }
+
+ before do
+ assign(:milestone, milestone)
+ assign(:milestone_url, milestone_link)
+ end
+
+ context 'milestone without start and due dates' do
+ it 'renders without date range' do
+ render
+
+ expect(rendered).to have_content('Milestone changed to some-milestone', exact: true)
+ expect(rendered).to have_link('some-milestone', href: milestone_link)
+ end
+ end
+
+ context 'milestone with start and due dates' do
+ before do
+ milestone.update(start_date: '2018-01-01', due_date: '2018-12-31')
+ end
+
+ it 'renders with date range' do
+ render
+
+ expect(rendered).to have_content('Milestone changed to some-milestone (Jan 1, 2018–Dec 31, 2018)', exact: true)
+ expect(rendered).to have_link('some-milestone', href: milestone_link)
+ end
+ end
+end
diff --git a/spec/views/projects/merge_requests/show.html.haml_spec.rb b/spec/views/projects/merge_requests/show.html.haml_spec.rb
index fa6c4ce4ac8..b0042be339c 100644
--- a/spec/views/projects/merge_requests/show.html.haml_spec.rb
+++ b/spec/views/projects/merge_requests/show.html.haml_spec.rb
@@ -32,6 +32,11 @@ describe 'projects/merge_requests/show.html.haml' do
assign(:noteable, closed_merge_request)
assign(:notes, [])
assign(:pipelines, Ci::Pipeline.none)
+ assign(
+ :issuable_sidebar,
+ MergeRequestSerializer.new(current_user: user, project: project)
+ .represent(closed_merge_request, serializer: 'sidebar')
+ )
preload_view_requirements
diff --git a/spec/workers/cluster_platform_configure_worker_spec.rb b/spec/workers/cluster_configure_worker_spec.rb
index 0eead0ab13d..6918ee3d7d8 100644
--- a/spec/workers/cluster_platform_configure_worker_spec.rb
+++ b/spec/workers/cluster_configure_worker_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-describe ClusterPlatformConfigureWorker, '#perform' do
+describe ClusterConfigureWorker, '#perform' do
let(:worker) { described_class.new }
context 'when group cluster' do
diff --git a/spec/workers/cluster_provision_worker_spec.rb b/spec/workers/cluster_provision_worker_spec.rb
index 0a2dfef36a4..da32f29fec0 100644
--- a/spec/workers/cluster_provision_worker_spec.rb
+++ b/spec/workers/cluster_provision_worker_spec.rb
@@ -23,7 +23,7 @@ describe ClusterProvisionWorker do
end
it 'configures kubernetes platform' do
- expect(ClusterPlatformConfigureWorker).to receive(:perform_async).with(cluster.id)
+ expect(ClusterConfigureWorker).to receive(:perform_async).with(cluster.id)
described_class.new.perform(cluster.id)
end
@@ -32,7 +32,7 @@ describe ClusterProvisionWorker do
context 'when cluster does not exist' do
it 'does not provision a cluster' do
expect_any_instance_of(Clusters::Gcp::ProvisionService).not_to receive(:execute)
- expect(ClusterPlatformConfigureWorker).not_to receive(:perform_async)
+ expect(ClusterConfigureWorker).not_to receive(:perform_async)
described_class.new.perform(123)
end
diff --git a/spec/workers/object_pool/destroy_worker_spec.rb b/spec/workers/object_pool/destroy_worker_spec.rb
new file mode 100644
index 00000000000..ef74f0ba87c
--- /dev/null
+++ b/spec/workers/object_pool/destroy_worker_spec.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+
+describe ObjectPool::DestroyWorker do
+ describe '#perform' do
+ context 'when no pool is in the database' do
+ it "doesn't raise an error" do
+ expect do
+ described_class.new.perform(987654321)
+ end.not_to raise_error
+ end
+ end
+
+ context 'when a pool is present' do
+ let(:pool) { create(:pool_repository, :obsolete) }
+
+ subject { described_class.new }
+
+ it 'requests Gitaly to remove the object pool' do
+ expect(Gitlab::GitalyClient).to receive(:call).with(pool.shard_name, :object_pool_service, :delete_object_pool, Object)
+
+ subject.perform(pool.id)
+ end
+
+ it 'destroys the pool' do
+ subject.perform(pool.id)
+
+ expect(PoolRepository.find_by_id(pool.id)).to be_nil
+ end
+ end
+ end
+end
diff --git a/spec/workers/stuck_merge_jobs_worker_spec.rb b/spec/workers/stuck_merge_jobs_worker_spec.rb
index c2c2a5f9121..5aaff27a6b2 100644
--- a/spec/workers/stuck_merge_jobs_worker_spec.rb
+++ b/spec/workers/stuck_merge_jobs_worker_spec.rb
@@ -38,7 +38,8 @@ describe StuckMergeJobsWorker do
create(:merge_request, :locked, merge_jid: '123')
create(:merge_request, :locked, merge_jid: '456')
- expect(Rails).to receive_message_chain(:logger, :info).with('Updated state of locked merge jobs. JIDs: 123, 456')
+ expect(described_class).to receive_message_chain(:logger, :info)
+ .with('Updated state of locked merge jobs. JIDs: 123, 456')
worker.perform
end
diff --git a/yarn.lock b/yarn.lock
index ae9975831dc..90d3d6fb7cb 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -641,10 +641,10 @@
resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-1.43.0.tgz#28dee2122d068cd3b925cd9884d97465ebaca12d"
integrity sha512-wuN3NITmyBV9bOXsFfAjtndFrjTlH6Kf3+6aqT5kHKKLe/B4w7uTU1L9H/cyR0wGD7HbOh584a05eDcuH04fPA==
-"@gitlab/ui@^1.15.0":
- version "1.15.0"
- resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-1.15.0.tgz#288e189cb99de354aeb4598f9ac8cced5f47e139"
- integrity sha512-Aiv/WABr8lBVJk0eoanSoO07Lr5Nnvuq82IjDnNzcw9enB1DAKvlstC2r9iiMfg1pVgV/uLdDeRFqH9eI1X4Rg==
+"@gitlab/ui@^1.18.0":
+ version "1.18.0"
+ resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-1.18.0.tgz#5cc591b2c7958e59fa7b1b443d4235e0e8f956c9"
+ integrity sha512-JqmiRSGYmK0DbGBQJBpjeRrcgjK25rCqG6QW6/GPTVLtRjbPPZYGvVg5PyA6nJUGAnwFoeApUZVML6X3OpnV1Q==
dependencies:
babel-standalone "^6.26.0"
bootstrap-vue "^2.0.0-rc.11"
@@ -654,7 +654,7 @@
js-beautify "^1.8.8"
lodash "^4.17.11"
url-search-params-polyfill "^5.0.0"
- vue "^2.5.16"
+ vue "^2.5.21"
vue-loader "^15.4.2"
"@sindresorhus/is@^0.7.0":
@@ -9904,11 +9904,16 @@ vue-virtual-scroll-list@^1.2.5:
resolved "https://registry.yarnpkg.com/vue-virtual-scroll-list/-/vue-virtual-scroll-list-1.2.5.tgz#bcbd010f7cdb035eba8958ebf807c6214d9a167a"
integrity sha1-vL0BD3zbA166iVjr+AfGIU2aFno=
-vue@^2.5.16, vue@^2.5.17:
+vue@^2.5.17:
version "2.5.17"
resolved "https://registry.yarnpkg.com/vue/-/vue-2.5.17.tgz#0f8789ad718be68ca1872629832ed533589c6ada"
integrity sha512-mFbcWoDIJi0w0Za4emyLiW72Jae0yjANHbCVquMKijcavBGypqlF7zHRgMa5k4sesdv7hv2rB4JPdZfR+TPfhQ==
+vue@^2.5.21:
+ version "2.5.21"
+ resolved "https://registry.yarnpkg.com/vue/-/vue-2.5.21.tgz#3d33dcd03bb813912ce894a8303ab553699c4a85"
+ integrity sha512-Aejvyyfhn0zjVeLvXd70h4hrE4zZDx1wfZqia6ekkobLmUZ+vNFQer53B4fu0EjWBSiqApxPejzkO1Znt3joxQ==
+
vuex@^3.0.1:
version "3.0.1"
resolved "https://registry.yarnpkg.com/vuex/-/vuex-3.0.1.tgz#e761352ebe0af537d4bb755a9b9dc4be3df7efd2"