summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitlab/ci/docs.gitlab-ci.yml4
-rw-r--r--.gitlab/ci/frontend.gitlab-ci.yml1
-rw-r--r--.gitlab/ci/global.gitlab-ci.yml14
-rw-r--r--.gitlab/ci/reports.gitlab-ci.yml88
-rw-r--r--CHANGELOG.md314
-rw-r--r--GITALY_SERVER_VERSION2
-rw-r--r--Gemfile4
-rw-r--r--Gemfile.lock2
-rw-r--r--VERSION2
-rw-r--r--app/assets/javascripts/boards/components/board_sidebar.js1
-rw-r--r--app/assets/javascripts/boards/components/issue_time_estimate.vue10
-rw-r--r--app/assets/javascripts/boards/index.js1
-rw-r--r--app/assets/javascripts/boards/stores/boards_store.js7
-rw-r--r--app/assets/javascripts/branches/components/divergence_graph.vue72
-rw-r--r--app/assets/javascripts/branches/components/graph_bar.vue69
-rw-r--r--app/assets/javascripts/branches/constants.js6
-rw-r--r--app/assets/javascripts/branches/divergence_graph.js23
-rw-r--r--app/assets/javascripts/environments/components/container.vue1
-rw-r--r--app/assets/javascripts/environments/components/environments_app.vue6
-rw-r--r--app/assets/javascripts/environments/components/environments_table.vue7
-rw-r--r--app/assets/javascripts/environments/index.js2
-rw-r--r--app/assets/javascripts/environments/mixins/container_mixin.js5
-rw-r--r--app/assets/javascripts/gfm_auto_complete.js4
-rw-r--r--app/assets/javascripts/groups/components/group_item.vue77
-rw-r--r--app/assets/javascripts/groups/components/item_actions.vue28
-rw-r--r--app/assets/javascripts/groups/components/item_caret.vue2
-rw-r--r--app/assets/javascripts/groups/components/item_stats.vue8
-rw-r--r--app/assets/javascripts/groups/components/item_type_icon.vue2
-rw-r--r--app/assets/javascripts/groups_select.js4
-rw-r--r--app/assets/javascripts/ide/stores/modules/commit/actions.js8
-rw-r--r--app/assets/javascripts/issue_show/components/edit_actions.vue4
-rw-r--r--app/assets/javascripts/issue_show/components/fields/description.vue6
-rw-r--r--app/assets/javascripts/issue_show/components/fields/description_template.vue25
-rw-r--r--app/assets/javascripts/issue_show/components/fields/title.vue6
-rw-r--r--app/assets/javascripts/issue_show/components/locked_warning.vue7
-rw-r--r--app/assets/javascripts/jobs/components/environments_block.vue4
-rw-r--r--app/assets/javascripts/jobs/components/job_log_controllers.vue8
-rw-r--r--app/assets/javascripts/jobs/components/sidebar.vue5
-rw-r--r--app/assets/javascripts/lib/utils/datetime_utility.js17
-rw-r--r--app/assets/javascripts/monitoring/components/charts/area.vue3
-rw-r--r--app/assets/javascripts/monitoring/components/charts/column.vue131
-rw-r--r--app/assets/javascripts/monitoring/components/empty_state.vue50
-rw-r--r--app/assets/javascripts/notes.js4
-rw-r--r--app/assets/javascripts/notes/components/diff_with_note.vue7
-rw-r--r--app/assets/javascripts/notes/components/noteable_discussion.vue2
-rw-r--r--app/assets/javascripts/pages/profiles/two_factor_auths/index.js4
-rw-r--r--app/assets/javascripts/pages/projects/branches/index/index.js2
-rw-r--r--app/assets/javascripts/pages/projects/pages_domains/form.js16
-rw-r--r--app/assets/javascripts/pipelines/components/pipeline_url.vue2
-rw-r--r--app/assets/javascripts/registry/components/app.vue4
-rw-r--r--app/assets/javascripts/registry/components/collapsible_container.vue31
-rw-r--r--app/assets/javascripts/registry/components/table_registry.vue58
-rw-r--r--app/assets/javascripts/registry/stores/actions.js6
-rw-r--r--app/assets/javascripts/releases/components/release_block.vue26
-rw-r--r--app/assets/javascripts/sidebar/components/time_tracking/comparison_pane.vue7
-rw-r--r--app/assets/javascripts/sidebar/components/time_tracking/sidebar_time_tracking.vue1
-rw-r--r--app/assets/javascripts/sidebar/components/time_tracking/time_tracker.vue5
-rw-r--r--app/assets/javascripts/sidebar/mount_milestone_sidebar.js4
-rw-r--r--app/assets/javascripts/sidebar/stores/sidebar_store.js3
-rw-r--r--app/assets/javascripts/vue_shared/components/modal_copy_button.vue6
-rw-r--r--app/assets/javascripts/vue_shared/components/paginated_list.vue35
-rw-r--r--app/assets/javascripts/vue_shared/components/pagination/constants.js4
-rw-r--r--app/assets/javascripts/vue_shared/components/project_avatar/image.vue21
-rw-r--r--app/assets/stylesheets/components/popover.scss6
-rw-r--r--app/assets/stylesheets/framework/lists.scss1
-rw-r--r--app/assets/stylesheets/framework/mixins.scss2
-rw-r--r--app/assets/stylesheets/pages/branches.scss36
-rw-r--r--app/assets/stylesheets/pages/groups.scss80
-rw-r--r--app/assets/stylesheets/pages/projects.scss5
-rw-r--r--app/controllers/dashboard/todos_controller.rb1
-rw-r--r--app/controllers/projects/issues_controller.rb16
-rw-r--r--app/controllers/projects/merge_requests_controller.rb8
-rw-r--r--app/controllers/projects/pages_domains_controller.rb8
-rw-r--r--app/finders/autocomplete/acts_as_taggable_on/tags_finder.rb3
-rw-r--r--app/finders/environments_finder.rb29
-rw-r--r--app/helpers/appearances_helper.rb5
-rw-r--r--app/helpers/application_settings_helper.rb1
-rw-r--r--app/helpers/boards_helper.rb3
-rw-r--r--app/helpers/issuables_helper.rb3
-rw-r--r--app/helpers/issues_helper.rb14
-rw-r--r--app/helpers/todos_helper.rb2
-rw-r--r--app/mailers/emails/notes.rb2
-rw-r--r--app/models/application_setting_implementation.rb1
-rw-r--r--app/models/ci/pipeline_schedule.rb23
-rw-r--r--app/models/clusters/platforms/kubernetes.rb9
-rw-r--r--app/models/concerns/service_push_data_validations.rb43
-rw-r--r--app/models/deployment.rb11
-rw-r--r--app/models/environment.rb4
-rw-r--r--app/models/issue.rb4
-rw-r--r--app/models/merge_request.rb36
-rw-r--r--app/models/pages_domain.rb40
-rw-r--r--app/models/project.rb2
-rw-r--r--app/models/project_services/drone_ci_service.rb20
-rw-r--r--app/models/project_services/teamcity_service.rb74
-rw-r--r--app/models/todo.rb2
-rw-r--r--app/services/boards/issues/move_service.rb6
-rw-r--r--app/services/clusters/gcp/finalize_creation_service.rb3
-rw-r--r--app/services/clusters/gcp/kubernetes/fetch_kubernetes_token_service.rb19
-rw-r--r--app/services/issues/reorder_service.rb48
-rw-r--r--app/services/issues/update_service.rb1
-rw-r--r--app/services/merge_requests/merge_to_ref_service.rb20
-rw-r--r--app/services/merge_requests/mergeability_check_service.rb120
-rw-r--r--app/services/pages_domains/obtain_lets_encrypt_certificate_service.rb2
-rw-r--r--app/services/service_response.rb15
-rw-r--r--app/views/admin/application_settings/_localization.html.haml7
-rw-r--r--app/views/admin/users/show.html.haml5
-rw-r--r--app/views/layouts/header/_new_dropdown.haml2
-rw-r--r--app/views/layouts/nav/sidebar/_group.html.haml3
-rw-r--r--app/views/layouts/nav/sidebar/_project.html.haml16
-rw-r--r--app/views/notify/_note_email.html.haml30
-rw-r--r--app/views/notify/_note_email.text.erb26
-rw-r--r--app/views/notify/new_issue_email.html.haml5
-rw-r--r--app/views/notify/new_issue_email.text.erb12
-rw-r--r--app/views/notify/new_merge_request_email.html.haml18
-rw-r--r--app/views/notify/new_merge_request_email.text.erb6
-rw-r--r--app/views/projects/branches/_branch.html.haml21
-rw-r--r--app/views/projects/commits/_commit.html.haml4
-rw-r--r--app/views/projects/environments/index.html.haml1
-rw-r--r--app/views/projects/issues/_issue.html.haml2
-rw-r--r--app/views/projects/issues/_new_branch.html.haml8
-rw-r--r--app/views/projects/issues/show.html.haml2
-rw-r--r--app/views/projects/merge_requests/_merge_request.html.haml2
-rw-r--r--app/views/projects/pages_domains/_form.html.haml26
-rw-r--r--app/views/projects/services/_form.html.haml2
-rw-r--r--app/views/search/results/_wiki_blob.html.haml2
-rw-r--r--app/views/shared/boards/components/sidebar/_time_tracker.html.haml1
-rw-r--r--app/views/shared/milestones/_sidebar.html.haml6
-rw-r--r--app/workers/all_queues.yml2
-rw-r--r--app/workers/build_success_worker.rb12
-rw-r--r--app/workers/cluster_provision_worker.rb2
-rw-r--r--app/workers/pages_domain_ssl_renewal_cron_worker.rb14
-rw-r--r--app/workers/pages_domain_ssl_renewal_worker.rb13
-rw-r--r--changelogs/add-name-parameter-to-project-environments-api.yml5
-rw-r--r--changelogs/unreleased/10088-move-code-differences-EE-to-CE.yml5
-rw-r--r--changelogs/unreleased/10795-add-epic-tree-BE-CE-epic-graphql-support.yml5
-rw-r--r--changelogs/unreleased/10798-remove-dind-req-for-dast.yml5
-rw-r--r--changelogs/unreleased/10842-add-missing-environments-variable-to-the-sast-analyzer-docker-container.yml5
-rw-r--r--changelogs/unreleased/11105-fix-cs-with-proxy.yml5
-rw-r--r--changelogs/unreleased/11204-turn-off-mask-by-default.yml5
-rw-r--r--changelogs/unreleased/11609-geo-remove-support-for-using-geo-with-an-installation-from-source-docs.yml5
-rw-r--r--changelogs/unreleased/12106-sp-ce.yml5
-rw-r--r--changelogs/unreleased/1340-request-job-with-age.yml5
-rw-r--r--changelogs/unreleased/13453_minimal_atom_fix.yml5
-rw-r--r--changelogs/unreleased/17690-Protect-TeamCity-builds-for-triggering-when-a-branch-is-deleted-And-add-MR-option.yml5
-rw-r--r--changelogs/unreleased/19569-include-information-if-issue-was-closed-via-mr.yml5
-rw-r--r--changelogs/unreleased/237-style-toast-component.yml5
-rw-r--r--changelogs/unreleased/27987-use-findorcreateservice-to-create-labels.yml5
-rw-r--r--changelogs/unreleased/28757-remove-docker-pull-prefix-when-copying-a-tag-from-the-registry.yml5
-rw-r--r--changelogs/unreleased/28996-create-mvc-ui-in-haml.yml5
-rw-r--r--changelogs/unreleased/30138-display-cycle-analytics-issue-logic-fixes.yml5
-rw-r--r--changelogs/unreleased/30138-display-cycle-analytics-issue.yml5
-rw-r--r--changelogs/unreleased/30355-use-hours-only-for-time-tracking.yml5
-rw-r--r--changelogs/unreleased/33064-add-labels-to-note-event-payload.yml5
-rw-r--r--changelogs/unreleased/35428-docker-registry-date-not-accurate.yml6
-rw-r--r--changelogs/unreleased/37495.yml5
-rw-r--r--changelogs/unreleased/38105-pre-release-tag.yml5
-rw-r--r--changelogs/unreleased/38561-border-radii.yml5
-rw-r--r--changelogs/unreleased/39304-broadcast-message-buttons.yml5
-rw-r--r--changelogs/unreleased/42399-registry-confirm-deletion.yml5
-rw-r--r--changelogs/unreleased/45687-web-ide-empty-state.yml5
-rw-r--r--changelogs/unreleased/47846-position-is-off-when-visiting-files-with-anchors.yml5
-rw-r--r--changelogs/unreleased/49041-issue-board-input-height.yml5
-rw-r--r--changelogs/unreleased/49517-fix-notes-import-export.yml5
-rw-r--r--changelogs/unreleased/49814-display-in-admin-area-if-emails-are-verified-or-not.yml5
-rw-r--r--changelogs/unreleased/49915-fix-error-500-admin-projects-nil-storage.yml5
-rw-r--r--changelogs/unreleased/50106-hide-whitespace-changes.yml5
-rw-r--r--changelogs/unreleased/50834-change-http-status-code-when-repository-disabled.yml5
-rw-r--r--changelogs/unreleased/50850-kerrizor-extend-api-to-accept-start_project-option.yml5
-rw-r--r--changelogs/unreleased/51022-added-extended-height-to-labels-dropdown.yml5
-rw-r--r--changelogs/unreleased/51636-task-list-api-pderichs.yml5
-rw-r--r--changelogs/unreleased/51854-api-to-get-all-project-group-members-returns-duplicates.yml5
-rw-r--r--changelogs/unreleased/52366-improved-group-lists-ui.yml5
-rw-r--r--changelogs/unreleased/53134-multiple-extendes-for-a-job.yml5
-rw-r--r--changelogs/unreleased/54140-non-ar-cache-commit-markdown.yml5
-rw-r--r--changelogs/unreleased/54169-flash-warning-rebrush.yml5
-rw-r--r--changelogs/unreleased/55033-discussion-system-note-alignment.yml5
-rw-r--r--changelogs/unreleased/55125-mr-tab-scrolling.yml5
-rw-r--r--changelogs/unreleased/55253-activity-feed-ui-enhance-line-height.yml5
-rw-r--r--changelogs/unreleased/55362-refresh-blank-service-account-token.yml5
-rw-r--r--changelogs/unreleased/55447-validate-k8s-credentials.yml5
-rw-r--r--changelogs/unreleased/5615-non-admins-only-archieve-ce.yml5
-rw-r--r--changelogs/unreleased/56737-commits-and-mr-events-on-jira-api.yml5
-rw-r--r--changelogs/unreleased/56959-drop-project_auto_devops_domain.yml5
-rw-r--r--changelogs/unreleased/56959-remove-auto-devops-domain-ci-variable.yml5
-rw-r--r--changelogs/unreleased/57037-fix-mr-checkboxes-mobile-alignment.yml5
-rw-r--r--changelogs/unreleased/57189-css-label-in-forms-with-bootstrap4.yml5
-rw-r--r--changelogs/unreleased/57813-merge-request-tabs-do-not-handle-ctrl-click-correctly.yml5
-rw-r--r--changelogs/unreleased/57825-moving-an-issue-results-in-broken-image-links-in-comments.yml5
-rw-r--r--changelogs/unreleased/58065-uniform-html-txt-email.yml5
-rw-r--r--changelogs/unreleased/58269-separate-update-patch.yml5
-rw-r--r--changelogs/unreleased/58297-remove-extraneous-gitaly-calls-from-md-rendering.yml5
-rw-r--r--changelogs/unreleased/58404-set-default-max-depth-for-GraphQL.yml5
-rw-r--r--changelogs/unreleased/58433-email-notifications-do-not-work-properly-issue-due-date.yml5
-rw-r--r--changelogs/unreleased/58538-discussion-top-radius.yml5
-rw-r--r--changelogs/unreleased/58632-fix-mr-widget-padding.yml5
-rw-r--r--changelogs/unreleased/58941-use-gitlab-serverless-with-existing-knative-installation.yml5
-rw-r--r--changelogs/unreleased/58984-doc-missing-milestones-and-labels-links.yml5
-rw-r--r--changelogs/unreleased/59023-fix-web-ide-creating-branches-off-new-commits.yml5
-rw-r--r--changelogs/unreleased/59026-replace-favicon.yml5
-rw-r--r--changelogs/unreleased/59028-fix-extra-plus-in-diffs.yml5
-rw-r--r--changelogs/unreleased/59105-padding-unclickable-pipeline-job.yml5
-rw-r--r--changelogs/unreleased/59376-Report-abuse-to-GitLab-should-be-Report-abuse-in-non-gitlab-com-instances.yml5
-rw-r--r--changelogs/unreleased/59587-add-graphql-logging.yml5
-rw-r--r--changelogs/unreleased/59651-remove-unnecessary-decimal-places-on-chart-axes.yml5
-rw-r--r--changelogs/unreleased/59987-move-sign-in-2fa-on-users-sign_in-above-intro-content-on-mobile.yml5
-rw-r--r--changelogs/unreleased/60034-default-web-ide-s-merge-request-checkbox-to-true.yml5
-rw-r--r--changelogs/unreleased/60180-jira-service-fix-nil-on-find-call.yml5
-rw-r--r--changelogs/unreleased/60250-remove-mr_push_options-flag.yml5
-rw-r--r--changelogs/unreleased/60303-replace-sidekiq-mtail-metrics.yml5
-rw-r--r--changelogs/unreleased/60323-inline-validation-for-users-name-and-username-length.yml5
-rw-r--r--changelogs/unreleased/60379-remove-ci-preparing-state-feature-flag.yml5
-rw-r--r--changelogs/unreleased/60425-fix-500-when-accessing-charts-with-anonymous-user.yml5
-rw-r--r--changelogs/unreleased/60617-allow-switching-from-gitlab-managed-to-unmanaged-clusters.yml5
-rw-r--r--changelogs/unreleased/60617-enable-project-cluster-jit.yml5
-rw-r--r--changelogs/unreleased/60750-milestone-header.yml5
-rw-r--r--changelogs/unreleased/60818_yamllint_project_root.yml5
-rw-r--r--changelogs/unreleased/60819_yamllint_gitlabci.yml5
-rw-r--r--changelogs/unreleased/60879-fix-reports-timing-out.yml5
-rw-r--r--changelogs/unreleased/609120-ref-link.yml5
-rw-r--r--changelogs/unreleased/60987-emoji-picker-popup.yml5
-rw-r--r--changelogs/unreleased/61024-update-resolved-icon.yml5
-rw-r--r--changelogs/unreleased/6104-ee-ce-difference.yml5
-rw-r--r--changelogs/unreleased/61045-charts-with-many-overlapping-series-display-incorrectly.yml5
-rw-r--r--changelogs/unreleased/61049-links-activity-stream.yml5
-rw-r--r--changelogs/unreleased/61072-link-to-user-profile-not-distinguishable-on-latest-commit-widget.yml5
-rw-r--r--changelogs/unreleased/61144-style-secondary-button-type-to-be-aligned-with-pattern-library.yml5
-rw-r--r--changelogs/unreleased/61157-reviewer-roulette-shouldn-t-include-the-author-as-a-possibility.yml5
-rw-r--r--changelogs/unreleased/61313-fix-dropdown-searchbar.yml5
-rw-r--r--changelogs/unreleased/61323-snippet-copy-icon-button-is-misaligned.yml5
-rw-r--r--changelogs/unreleased/61324-non-project-snippet-new-snippet-button-should-be-green-outline.yml5
-rw-r--r--changelogs/unreleased/61339-Add-underline-to-attach-a-file.yml5
-rw-r--r--changelogs/unreleased/61393-emoji-button.yml5
-rw-r--r--changelogs/unreleased/61441.yml5
-rw-r--r--changelogs/unreleased/61511-add-expand-collapse-to-project-operation-settings.yml5
-rw-r--r--changelogs/unreleased/61565-merge-request-discussion-text-jumps-when-resolved.yml5
-rw-r--r--changelogs/unreleased/61606-support-string-piwik-website-ids.yml5
-rw-r--r--changelogs/unreleased/61629-dependency-installation-error-on-fsevents-1-2-4-with-node-js-12.yml5
-rw-r--r--changelogs/unreleased/61639-flaky-spec-issue-boards-labels-creates-project-label-spec-features-boards-sidebar_spec-rb-350.yml5
-rw-r--r--changelogs/unreleased/61697-add-project-id-to-le-common-name.yml5
-rw-r--r--changelogs/unreleased/61788-predefined-colours-dont-have-descriptive-labels.yml5
-rw-r--r--changelogs/unreleased/61795-fix-error-when-moving-issues.yml5
-rw-r--r--changelogs/unreleased/61821-tooltip-consistency.yml5
-rw-r--r--changelogs/unreleased/61827-prevent-user-popover-icon-shrink.yml5
-rw-r--r--changelogs/unreleased/61880-download-btn-group.yml5
-rw-r--r--changelogs/unreleased/61914-fix-emojis-urls.yml5
-rw-r--r--changelogs/unreleased/61928-remove-throttle-from-dirty-submit.yml6
-rw-r--r--changelogs/unreleased/61960-translatable-strings-in-issue-closure-emails.yml5
-rw-r--r--changelogs/unreleased/61988-collapse-icon-on-merge-request-diff-larger-than-profile-picture.yml5
-rw-r--r--changelogs/unreleased/61990-spinner.yml5
-rw-r--r--changelogs/unreleased/62061-note-icon-color.yml5
-rw-r--r--changelogs/unreleased/62091-remove-time-windows-flag.yml5
-rw-r--r--changelogs/unreleased/62092-missing-padding-next-to-time-windows-dropdown-on-metrics-dashboard.yml5
-rw-r--r--changelogs/unreleased/62107-fix-detail-page-header-height.yml5
-rw-r--r--changelogs/unreleased/62116-performance-issue-502-errors-on-rendering-of-issues-with-heavy-markdown-contents.yml6
-rw-r--r--changelogs/unreleased/62124-new-threaded-discussion-design.yml5
-rw-r--r--changelogs/unreleased/62134-fix-non-wraping-project-description.yml5
-rw-r--r--changelogs/unreleased/62144-fix-option-dropdown-button-size.yml5
-rw-r--r--changelogs/unreleased/62154-fe-create-fix-long-branch-name-in-dropdown.yml6
-rw-r--r--changelogs/unreleased/62227-webkit-icon-overlap.yml5
-rw-r--r--changelogs/unreleased/62253-add-kubernetes-logs-to-monitoring-ui.yml5
-rw-r--r--changelogs/unreleased/62300-target-area-for-dropdown-list-items-is-too-small-on-metrics-dashboard.yml5
-rw-r--r--changelogs/unreleased/62408-dropdown-truncate.yml5
-rw-r--r--changelogs/unreleased/62418-project-default-git-depth.yml5
-rw-r--r--changelogs/unreleased/62432-fix-participants-wrapping.yml5
-rw-r--r--changelogs/unreleased/62485-label-weights.yml5
-rw-r--r--changelogs/unreleased/62487-external-policy-desc.yml5
-rw-r--r--changelogs/unreleased/62656-adjusted-dropdown-styles.yml5
-rw-r--r--changelogs/unreleased/62684-add-index-public-email-on-users.yml5
-rw-r--r--changelogs/unreleased/62685-add-index-invite-email-to-members.yml5
-rw-r--r--changelogs/unreleased/62788-clean-up-pagination.yml5
-rw-r--r--changelogs/unreleased/62788-graphql-pagination.yml5
-rw-r--r--changelogs/unreleased/62847-url-for-the-next-request-with-pagination-is-missing-port.yml5
-rw-r--r--changelogs/unreleased/62910-task-completion-status-gql-pderichs.yml5
-rw-r--r--changelogs/unreleased/62966-embed-zoom-call-in-issue-mvc.yml5
-rw-r--r--changelogs/unreleased/62974-follow-up-from-wip-align-merge-request-icons-and-text.yml5
-rw-r--r--changelogs/unreleased/63079-exclude-k8s-namespaces-with-no-service-account-token.yml6
-rw-r--r--changelogs/unreleased/63417-add-missing-class.yml5
-rw-r--r--changelogs/unreleased/63507-fix-race-condition-fetching-token.yml5
-rw-r--r--changelogs/unreleased/63513-ensure-gitlab-jsoncache-includes-the-gitlab-version-in-the-cache-key.yml5
-rw-r--r--changelogs/unreleased/63559-remove-avatar-from-sign-in.yml5
-rw-r--r--changelogs/unreleased/63656-runner-tags-search-dropdown-is-empty.yml5
-rw-r--r--changelogs/unreleased/8723-geo-remove-gitlab-lfstoken-legacyredisdevisetoken-implementation-and-usage-geo.yml5
-rw-r--r--changelogs/unreleased/9121-sort-relative-position.yml5
-rw-r--r--changelogs/unreleased/9186-implement-atmtwps-state-to-mr-widget.yml5
-rw-r--r--changelogs/unreleased/9578-adjust-milestone-completion-rate.yml5
-rw-r--r--changelogs/unreleased/9978-moved-code-differences-from-EE-to-CE.yml5
-rw-r--r--changelogs/unreleased/abstract-auto-merge.yml5
-rw-r--r--changelogs/unreleased/ac-63020-typeerror-nil-can-t-be-coerced-into-integer.yml5
-rw-r--r--changelogs/unreleased/ac-graphql-stats.yml5
-rw-r--r--changelogs/unreleased/ac-graphql-wikisize.yml5
-rw-r--r--changelogs/unreleased/ac-namespaces-stats-no-coalesce.yml5
-rw-r--r--changelogs/unreleased/add-allow_failure-to-job-api.yml5
-rw-r--r--changelogs/unreleased/add-branch-to-project-search-api.yml5
-rw-r--r--changelogs/unreleased/add-constraint-for-milestone-dates.yml5
-rw-r--r--changelogs/unreleased/add-lfs-blob-ids-to-tree-type.yml5
-rw-r--r--changelogs/unreleased/add-warning-to-backup-rake-task.yml5
-rw-r--r--changelogs/unreleased/add-wiki-size-to-statistics.yml5
-rw-r--r--changelogs/unreleased/allow-emoji-in-references.yml5
-rw-r--r--changelogs/unreleased/always-show-pipelines-must-succeed-checkbox.yml5
-rw-r--r--changelogs/unreleased/antonyliu-i18n-user-profile.yml5
-rw-r--r--changelogs/unreleased/api_make_protected_boolean_type.yml5
-rw-r--r--changelogs/unreleased/api_masked_variables.yml5
-rw-r--r--changelogs/unreleased/asciidoc-include-directive.yml5
-rw-r--r--changelogs/unreleased/auto-devops-kubernestes-bump1-11-10.yml5
-rw-r--r--changelogs/unreleased/backport-schema-changes.yml5
-rw-r--r--changelogs/unreleased/backstage-gb-improve-jobs-controller-performance.yml5
-rw-r--r--changelogs/unreleased/bump-auto-devops-helm-2-14-0.yml5
-rw-r--r--changelogs/unreleased/bvl-comments-graphql.yml5
-rw-r--r--changelogs/unreleased/bvl-graphql-multiplex.yml5
-rw-r--r--changelogs/unreleased/bvl-use-global-ids-graphql.yml5
-rw-r--r--changelogs/unreleased/cancel-auto-merge-when-branch-is-changed.yml5
-rw-r--r--changelogs/unreleased/cancel-auto-merge-when-merge-request-is-closed.yml5
-rw-r--r--changelogs/unreleased/ce-57402-add-issues-statistics-api-endpoints.yml5
-rw-r--r--changelogs/unreleased/ce-jej-fix-git-http-with-sso-enforcement.yml5
-rw-r--r--changelogs/unreleased/ce-quick-fix-58727-collapsed-sidebar-flyout-menu-items-don-t-appear-in-1200px-screen-size.yml5
-rw-r--r--changelogs/unreleased/chore-remove-circuit-breaker-api.yml5
-rw-r--r--changelogs/unreleased/ci-variable-conjunction.yml5
-rw-r--r--changelogs/unreleased/container-registry-api-perms-58271.yml5
-rw-r--r--changelogs/unreleased/copy-button-in-modals.yml5
-rw-r--r--changelogs/unreleased/db-update-geo-nodes-primary.yml5
-rw-r--r--changelogs/unreleased/dhiraj-fix-missing-deployment-rockets-in-monitoring-dashboard.yml5
-rw-r--r--changelogs/unreleased/diff-suggestions-popover.yml5
-rw-r--r--changelogs/unreleased/diff-whitespace-setting-changes.yml5
-rw-r--r--changelogs/unreleased/display-junit-classname-in-modal.yml5
-rw-r--r--changelogs/unreleased/dm-http-hostname-override.yml5
-rw-r--r--changelogs/unreleased/docs-add-chatops-request-doc.yml5
-rw-r--r--changelogs/unreleased/dz-patch-58.yml5
-rw-r--r--changelogs/unreleased/dz-scope-project-routes.yml5
-rw-r--r--changelogs/unreleased/ee-11040-added-conditional-rendering.yml5
-rw-r--r--changelogs/unreleased/ensure_namespace.yml5
-rw-r--r--changelogs/unreleased/error-pipelines-for-blocked-users.yml5
-rw-r--r--changelogs/unreleased/expose-project-git-depth-via-api.yml5
-rw-r--r--changelogs/unreleased/fe-fix-gl-dropdown-scrolling-to-top.yml5
-rw-r--r--changelogs/unreleased/feature-gb-use-gitlabktl-to-build-serverless-applications.yml5
-rw-r--r--changelogs/unreleased/feature-require-2fa-for-all-entities-in-group.yml4
-rw-r--r--changelogs/unreleased/fix-allow-lower-case-issue-ids.yml5
-rw-r--r--changelogs/unreleased/fix-autodevops-postgres-versioning.yml5
-rw-r--r--changelogs/unreleased/fix-db-migrate-is-failed-on-mysql8.yml5
-rw-r--r--changelogs/unreleased/fix-diverged-branch-locals.yml5
-rw-r--r--changelogs/unreleased/fix-flyout-navs.yml5
-rw-r--r--changelogs/unreleased/fix-format-date-safari-ff.yml5
-rw-r--r--changelogs/unreleased/fix-gb-fix-serverless-apps-deployment-template.yml5
-rw-r--r--changelogs/unreleased/fix-gb-remove-serverless-app-build-policies-from-template.yml5
-rw-r--r--changelogs/unreleased/fix-import-member-access.yml5
-rw-r--r--changelogs/unreleased/fix-import-param-ordering.yml5
-rw-r--r--changelogs/unreleased/fix-issue-mr-badge.yml5
-rw-r--r--changelogs/unreleased/fix-labels-in-hooks.yml5
-rw-r--r--changelogs/unreleased/fix-milestone-references-with-escaped-html-entities.yml5
-rw-r--r--changelogs/unreleased/fix-notes-emails-with-group-settings.yml5
-rw-r--r--changelogs/unreleased/fix-pipeline-schedule-edge-case.yml6
-rw-r--r--changelogs/unreleased/fix-pipeline-schedule-owner-is-nil.yml5
-rw-r--r--changelogs/unreleased/fix-search-dropdown-blur-close.yml5
-rw-r--r--changelogs/unreleased/fix-time-window-default.yml5
-rw-r--r--changelogs/unreleased/fix-too-many-loops-cron-error.yml5
-rw-r--r--changelogs/unreleased/generate-spans-for-sections.yml5
-rw-r--r--changelogs/unreleased/gitaly-version-v1.43.0.yml5
-rw-r--r--changelogs/unreleased/gitaly-version-v1.47.0.yml5
-rw-r--r--changelogs/unreleased/gt-externalize-profiles-preferences.yml5
-rw-r--r--changelogs/unreleased/gt-open-visibility-help-link-in-a-new-tab.yml5
-rw-r--r--changelogs/unreleased/gt-remove-tooltip-directive-on-project-avatar-image-component.yml5
-rw-r--r--changelogs/unreleased/hashed-storage-enabled-default.yml5
-rw-r--r--changelogs/unreleased/i18n-active_sessions-in-user-profile.yml5
-rw-r--r--changelogs/unreleased/i18n-chat-of-user-profile.yml5
-rw-r--r--changelogs/unreleased/i18n-email-of-user-profile.yml5
-rw-r--r--changelogs/unreleased/i18n-pgp_ssh_keys-of-user-profile.yml5
-rw-r--r--changelogs/unreleased/id-bug-suggested-changes-remove-empty-line.yml5
-rw-r--r--changelogs/unreleased/ignore-artifact-attirbutes-in-project-import-export.yml5
-rw-r--r--changelogs/unreleased/improve-email-text-part.yml5
-rw-r--r--changelogs/unreleased/increase-move-issue-dropdown-height.yml5
-rw-r--r--changelogs/unreleased/issue-58747.yml5
-rw-r--r--changelogs/unreleased/issue_49897.yml5
-rw-r--r--changelogs/unreleased/jc-migration-for-source-project-id.yml5
-rw-r--r--changelogs/unreleased/jc-omit-count-diverging-commits-max.yml5
-rw-r--r--changelogs/unreleased/jivl-migrate-dashboard-store-vuex.yml5
-rw-r--r--changelogs/unreleased/jupyter_pre_spawn_hook_v2.yml5
-rw-r--r--changelogs/unreleased/kinolaev-master-patch-13154.yml5
-rw-r--r--changelogs/unreleased/leipert-node-12-compatibility.yml5
-rw-r--r--changelogs/unreleased/make-autocomplete-faster-with-lots-of-results.yml5
-rw-r--r--changelogs/unreleased/mark-comment-resolved.yml5
-rw-r--r--changelogs/unreleased/migrate_k8s_service_integration.yml5
-rw-r--r--changelogs/unreleased/mm12935.yml5
-rw-r--r--changelogs/unreleased/osw-avoid-500-on-suggestions-check.yml5
-rw-r--r--changelogs/unreleased/osw-avoid-encoding-errors-on-merge-to-ref-service.yml5
-rw-r--r--changelogs/unreleased/osw-fix-post-dep-migration-with-timeout.yml5
-rw-r--r--changelogs/unreleased/osw-reset-merge-status-from-mergeable-mrs.yml5
-rw-r--r--changelogs/unreleased/osw-sync-merge-ref-upon-mergeability-check.yml5
-rw-r--r--changelogs/unreleased/paginate-license-management.yml5
-rw-r--r--changelogs/unreleased/patch-55.yml5
-rw-r--r--changelogs/unreleased/patch-65.yml5
-rw-r--r--changelogs/unreleased/patch-issue--56683.yml6
-rw-r--r--changelogs/unreleased/pb-update-gitaly-1-45-0.yml5
-rw-r--r--changelogs/unreleased/pipelines-email-default-branch-filter.yml5
-rw-r--r--changelogs/unreleased/readonly_k8s_integration.yml5
-rw-r--r--changelogs/unreleased/referenced-labels.yml5
-rw-r--r--changelogs/unreleased/relative-urls-for-system-notes.yml5
-rw-r--r--changelogs/unreleased/remove-grafana-dashboard-link-feature-flag.yml5
-rw-r--r--changelogs/unreleased/remove-legacy-artifacts-related-code.yml5
-rw-r--r--changelogs/unreleased/remove-mr-diff-header-height.yml5
-rw-r--r--changelogs/unreleased/revert-concurrent-pipeline-schedule-creation.yml5
-rw-r--r--changelogs/unreleased/sanitize_rake_ldap_check_output.yml5
-rw-r--r--changelogs/unreleased/search-blob-basenames.yml5
-rw-r--r--changelogs/unreleased/security-58856-persistent-xss-in-note-objects.yml5
-rw-r--r--changelogs/unreleased/security-60039.yml5
-rw-r--r--changelogs/unreleased/security-60143-address-xss-issue-in-wiki-links.yml5
-rw-r--r--changelogs/unreleased/security-fix-confidential-issue-label-visibility-master.yml5
-rw-r--r--changelogs/unreleased/security-fix-project-existence-disclosure-master.yml5
-rw-r--r--changelogs/unreleased/security-fix_milestones_search_api_leak.yml5
-rw-r--r--changelogs/unreleased/security-id-leaked-password-in-import-url-frontend.yml5
-rw-r--r--changelogs/unreleased/security-jej-prevent-web-sign-in-bypass.yml5
-rw-r--r--changelogs/unreleased/security-unsubscribing-from-issue.yml5
-rw-r--r--changelogs/unreleased/set-real-next-run-at-for-preventing-duplciate-pipeline-creations.yml5
-rw-r--r--changelogs/unreleased/sh-add-backtrace-to-sql-queries.yml5
-rw-r--r--changelogs/unreleased/sh-add-header-to-jobs-admin-page.yml5
-rw-r--r--changelogs/unreleased/sh-clean-up-bitbucket-import-errors.yml5
-rw-r--r--changelogs/unreleased/sh-default-visibility-fix.yml5
-rw-r--r--changelogs/unreleased/sh-enable-ref-name-caching-discussions.yml5
-rw-r--r--changelogs/unreleased/sh-fix-fogbugz-import.yml5
-rw-r--r--changelogs/unreleased/sh-fix-issue-55869.yml5
-rw-r--r--changelogs/unreleased/sh-fix-issue-63158.yml5
-rw-r--r--changelogs/unreleased/sh-fix-rebase-error-clearing.yml5
-rw-r--r--changelogs/unreleased/sh-fix-resolve-button-not-available.yml5
-rw-r--r--changelogs/unreleased/sh-fix-tag-push-remote-mirror.yml5
-rw-r--r--changelogs/unreleased/sh-fix-utf-8-encoding-resolve-conflicts.yml5
-rw-r--r--changelogs/unreleased/sh-omit-blocked-admins-from-notification.yml5
-rw-r--r--changelogs/unreleased/sh-optimize-todos-controller.yml5
-rw-r--r--changelogs/unreleased/sh-speed-up-commit-loading.yml5
-rw-r--r--changelogs/unreleased/sh-strong-memoize-appearances.yml5
-rw-r--r--changelogs/unreleased/sh-update-process-mem.yml5
-rw-r--r--changelogs/unreleased/sh-upgrade-ruby-2-6-3-ce.yml5
-rw-r--r--changelogs/unreleased/t1.yml5
-rw-r--r--changelogs/unreleased/thomas-nilsson-irfu-gitlab-ce-thomas-nilsson-irfu-master-patch-13137.yml5
-rw-r--r--changelogs/unreleased/update-babel-to-7-4-4.yml5
-rw-r--r--changelogs/unreleased/update-gitaly-to-v1-42-1.yml5
-rw-r--r--changelogs/unreleased/update-gitlab-runner-helm-chart-to-0-5-0.yml5
-rw-r--r--changelogs/unreleased/update-gitlab-runner-helm-chart-to-0-5-1.yml5
-rw-r--r--changelogs/unreleased/update-gitlab-runner-helm-chart-to-0-5-2.yml5
-rw-r--r--changelogs/unreleased/update-gitlab-shell-9-3-0.yml5
-rw-r--r--changelogs/unreleased/update-pages.yml5
-rw-r--r--changelogs/unreleased/update-pagination-texts.yml5
-rw-r--r--changelogs/unreleased/update-psd-doc.yml5
-rw-r--r--changelogs/unreleased/update-smileys-new.yml5
-rw-r--r--changelogs/unreleased/update-tar-to-2-2-2.yml5
-rw-r--r--changelogs/unreleased/upgrade-pages-to-v1-6-1.yml5
-rw-r--r--changelogs/unreleased/variables-boolean-type.yml5
-rw-r--r--changelogs/unreleased/visual-review-apps-fix-dropdown.yml5
-rw-r--r--changelogs/unreleased/weimeng-email-routing.yml5
-rw-r--r--changelogs/unreleased/winh-notes-error-handling.yml5
-rw-r--r--changelogs/unreleased/zj-remove-delta-island-feature-flag.yml3
-rw-r--r--changelogs/unreleased/zj-usage-ping-pool-repository.yml5
-rw-r--r--config/initializers/1_settings.rb4
-rw-r--r--config/initializers/forbid_sidekiq_in_transactions.rb2
-rw-r--r--config/routes/project.rb1
-rw-r--r--config/sidekiq_queues.yml1
-rw-r--r--db/migrate/20190607085356_add_source_to_pages_domains.rb21
-rw-r--r--db/migrate/20190607145325_add_pages_domains_ssl_renew_index.rb25
-rw-r--r--db/migrate/20190611090827_add_time_tracking_limit_to_hours_to_application_settings.rb21
-rw-r--r--db/post_migrate/20190618171120_update_geo_nodes_primary.rb20
-rw-r--r--db/post_migrate/20190620112608_enqueue_reset_merge_status_second_run.rb25
-rw-r--r--db/schema.rb7
-rw-r--r--doc/administration/auth/ldap.md35
-rw-r--r--doc/administration/auth/oidc.md22
-rw-r--r--doc/administration/geo/replication/faq.md16
-rw-r--r--doc/administration/geo/replication/troubleshooting.md112
-rw-r--r--doc/administration/high_availability/README.md6
-rw-r--r--doc/administration/high_availability/database.md25
-rw-r--r--doc/administration/high_availability/gitaly.md25
-rw-r--r--doc/administration/high_availability/gitlab.md45
-rw-r--r--doc/administration/high_availability/monitoring_node.md67
-rw-r--r--doc/administration/high_availability/redis.md28
-rw-r--r--doc/api/environments.md4
-rw-r--r--doc/api/merge_requests.md20
-rw-r--r--doc/api/search.md4
-rw-r--r--doc/api/settings.md1
-rw-r--r--doc/ci/docker/using_docker_images.md4
-rw-r--r--doc/ci/examples/test-scala-application.md6
-rw-r--r--doc/ci/variables/README.md24
-rw-r--r--doc/ci/variables/predefined_variables.md2
-rw-r--r--doc/development/api_graphql_styleguide.md6
-rw-r--r--doc/development/code_review.md3
-rw-r--r--doc/development/contributing/merge_request_workflow.md6
-rw-r--r--doc/development/documentation/index.md8
-rw-r--r--doc/development/documentation/styleguide.md4
-rw-r--r--doc/development/ee_features.md15
-rw-r--r--doc/development/elasticsearch.md35
-rw-r--r--doc/development/geo.md36
-rw-r--r--doc/development/profiling.md4
-rw-r--r--doc/development/reusing_abstractions.md36
-rw-r--r--doc/development/testing_guide/end_to_end/dynamic_element_validation.md12
-rw-r--r--doc/development/testing_guide/end_to_end/page_objects.md6
-rw-r--r--doc/integration/jenkins.md40
-rw-r--r--doc/subscriptions/index.md20
-rw-r--r--doc/user/admin_area/index.md2
-rw-r--r--doc/user/admin_area/settings/continuous_integration.md19
-rw-r--r--doc/user/admin_area/settings/terms.md2
-rw-r--r--doc/user/admin_area/settings/visibility_and_access_controls.md5
-rw-r--r--doc/user/application_security/container_scanning/index.md20
-rw-r--r--doc/user/application_security/dependency_scanning/analyzers.md133
-rw-r--r--doc/user/application_security/dependency_scanning/index.md68
-rw-r--r--doc/user/application_security/license_management/img/license_management_add_license.pngbin0 -> 87049 bytes
-rw-r--r--doc/user/application_security/license_management/img/license_management_search.pngbin0 -> 104278 bytes
-rw-r--r--doc/user/application_security/license_management/img/license_management_settings.pngbin13300 -> 171592 bytes
-rw-r--r--doc/user/application_security/license_management/index.md16
-rw-r--r--doc/user/group/contribution_analytics/index.md4
-rw-r--r--doc/user/group/epics/index.md6
-rw-r--r--doc/user/group/index.md20
-rw-r--r--doc/user/group/saml_sso/scim_setup.md32
-rw-r--r--doc/user/project/clusters/index.md9
-rw-r--r--doc/user/project/clusters/kubernetes_pod_logs.md4
-rw-r--r--doc/user/project/container_registry.md1
-rw-r--r--doc/user/project/deploy_boards.md5
-rw-r--r--doc/user/project/description_templates.md13
-rw-r--r--doc/user/project/integrations/hipchat.md2
-rw-r--r--doc/user/project/issues/index.md2
-rw-r--r--doc/user/project/merge_requests/merge_request_approvals.md8
-rw-r--r--doc/user/project/pages/getting_started_part_two.md18
-rw-r--r--doc/user/project/pages/index.md7
-rw-r--r--doc/user/project/pages/introduction.md6
-rw-r--r--doc/user/project/settings/index.md8
-rw-r--r--doc/user/project/web_ide/index.md108
-rw-r--r--doc/workflow/time_tracking.md10
-rw-r--r--lib/after_commit_queue.rb14
-rw-r--r--lib/api/branches.rb5
-rw-r--r--lib/api/commits.rb5
-rw-r--r--lib/api/entities.rb2
-rw-r--r--lib/api/environments.rb7
-rw-r--r--lib/api/helpers.rb4
-rw-r--r--lib/api/merge_requests.rb24
-rw-r--r--lib/api/pages_domains.rb15
-rw-r--r--lib/api/todos.rb2
-rw-r--r--lib/gitlab/bitbucket_import/importer.rb28
-rw-r--r--lib/gitlab/ci/build/prerequisite/kubernetes_namespace.rb3
-rw-r--r--lib/gitlab/data_builder/note.rb2
-rw-r--r--lib/gitlab/database.rb18
-rw-r--r--lib/gitlab/hook_data/issue_builder.rb2
-rw-r--r--lib/gitlab/json_cache.rb4
-rw-r--r--lib/gitlab/kubernetes.rb8
-rw-r--r--lib/gitlab/lets_encrypt.rb16
-rw-r--r--lib/gitlab/lets_encrypt/client.rb10
-rw-r--r--lib/gitlab/search/found_blob.rb9
-rw-r--r--lib/gitlab/time_tracking_formatter.rb10
-rw-r--r--lib/system_check/ldap_check.rb9
-rw-r--r--locale/gitlab.pot91
-rw-r--r--package.json6
-rw-r--r--qa/qa/page/project/pipeline/index.rb2
-rw-r--r--spec/controllers/dashboard/todos_controller_spec.rb28
-rw-r--r--spec/controllers/projects/clusters_controller_spec.rb2
-rw-r--r--spec/controllers/projects/issues_controller_spec.rb84
-rw-r--r--spec/controllers/projects/merge_requests_controller_spec.rb2
-rw-r--r--spec/controllers/projects/pages_domains_controller_spec.rb64
-rw-r--r--spec/factories/pages_domains.rb5
-rw-r--r--spec/features/admin/admin_users_spec.rb26
-rw-r--r--spec/features/boards/sidebar_spec.rb22
-rw-r--r--spec/features/container_registry_spec.rb4
-rw-r--r--spec/features/issues/user_creates_branch_and_merge_request_spec.rb13
-rw-r--r--spec/features/projects/clusters/gcp_spec.rb1
-rw-r--r--spec/features/projects/pages_lets_encrypt_spec.rb153
-rw-r--r--spec/features/projects/pages_spec.rb16
-rw-r--r--spec/features/projects/services/user_activates_jetbrains_teamcity_ci_spec.rb2
-rw-r--r--spec/features/search/user_searches_for_wiki_pages_spec.rb6
-rw-r--r--spec/finders/autocomplete/acts_as_taggable_on/tags_finder_spec.rb8
-rw-r--r--spec/frontend/branches/components/__snapshots__/divergence_graph_spec.js.snap37
-rw-r--r--spec/frontend/branches/components/divergence_graph_spec.js67
-rw-r--r--spec/frontend/branches/components/graph_bar_spec.js89
-rw-r--r--spec/frontend/lib/utils/datetime_utility_spec.js6
-rw-r--r--spec/frontend/vue_shared/components/paginated_list_spec.js56
-rw-r--r--spec/helpers/appearances_helper_spec.rb16
-rw-r--r--spec/javascripts/boards/boards_store_spec.js10
-rw-r--r--spec/javascripts/boards/components/issue_time_estimate_spec.js70
-rw-r--r--spec/javascripts/groups/components/group_item_spec.js7
-rw-r--r--spec/javascripts/groups/components/item_stats_spec.js12
-rw-r--r--spec/javascripts/jobs/components/stages_dropdown_spec.js8
-rw-r--r--spec/javascripts/monitoring/charts/column_spec.js58
-rw-r--r--spec/javascripts/notes/components/diff_with_note_spec.js13
-rw-r--r--spec/javascripts/pages/labels/components/promote_label_modal_spec.js4
-rw-r--r--spec/javascripts/pages/milestones/shared/components/promote_milestone_modal_spec.js4
-rw-r--r--spec/javascripts/registry/components/collapsible_container_spec.js22
-rw-r--r--spec/javascripts/registry/components/table_registry_spec.js30
-rw-r--r--spec/javascripts/registry/stores/actions_spec.js24
-rw-r--r--spec/javascripts/releases/components/release_block_spec.js14
-rw-r--r--spec/javascripts/sidebar/components/time_tracking/time_tracker_spec.js25
-rw-r--r--spec/javascripts/vue_mr_widget/components/mr_widget_pipeline_spec.js14
-rw-r--r--spec/javascripts/vue_shared/components/table_pagination_spec.js4
-rw-r--r--spec/lib/gitlab/bitbucket_import/importer_spec.rb27
-rw-r--r--spec/lib/gitlab/ci/build/prerequisite/kubernetes_namespace_spec.rb14
-rw-r--r--spec/lib/gitlab/ci/pipeline/seed/build_spec.rb90
-rw-r--r--spec/lib/gitlab/data_builder/note_spec.rb19
-rw-r--r--spec/lib/gitlab/highlight_spec.rb13
-rw-r--r--spec/lib/gitlab/hook_data/issue_builder_spec.rb4
-rw-r--r--spec/lib/gitlab/json_cache_spec.rb68
-rw-r--r--spec/lib/gitlab/kubernetes_spec.rb24
-rw-r--r--spec/lib/gitlab/lets_encrypt/client_spec.rb36
-rw-r--r--spec/lib/gitlab/lets_encrypt_spec.rb56
-rw-r--r--spec/lib/gitlab/search/found_blob_spec.rb39
-rw-r--r--spec/lib/gitlab/time_tracking_formatter_spec.rb43
-rw-r--r--spec/mailers/emails/pages_domains_spec.rb2
-rw-r--r--spec/mailers/notify_spec.rb58
-rw-r--r--spec/migrations/enqueue_reset_merge_status_second_run_spec.rb52
-rw-r--r--spec/models/ci/pipeline_schedule_spec.rb51
-rw-r--r--spec/models/clusters/platforms/kubernetes_spec.rb23
-rw-r--r--spec/models/deployment_spec.rb4
-rw-r--r--spec/models/issue_spec.rb9
-rw-r--r--spec/models/merge_request_spec.rb87
-rw-r--r--spec/models/pages_domain_spec.rb122
-rw-r--r--spec/models/project_services/teamcity_service_spec.rb94
-rw-r--r--spec/requests/api/branches_spec.rb10
-rw-r--r--spec/requests/api/commits_spec.rb14
-rw-r--r--spec/requests/api/environments_spec.rb41
-rw-r--r--spec/requests/api/merge_requests_spec.rb80
-rw-r--r--spec/requests/api/pages_domains_spec.rb8
-rw-r--r--spec/services/clusters/gcp/finalize_creation_service_spec.rb10
-rw-r--r--spec/services/clusters/gcp/kubernetes/fetch_kubernetes_token_service_spec.rb56
-rw-r--r--spec/services/clusters/update_service_spec.rb1
-rw-r--r--spec/services/issues/reorder_service_spec.rb88
-rw-r--r--spec/services/issues/update_service_spec.rb16
-rw-r--r--spec/services/merge_requests/merge_to_ref_service_spec.rb47
-rw-r--r--spec/services/merge_requests/mergeability_check_service_spec.rb285
-rw-r--r--spec/services/pages_domains/obtain_lets_encrypt_certificate_service_spec.rb6
-rw-r--r--spec/services/service_response_spec.rb16
-rw-r--r--spec/services/system_note_service_spec.rb24
-rw-r--r--spec/support/helpers/email_helpers.rb15
-rw-r--r--spec/support/helpers/kubernetes_helpers.rb24
-rw-r--r--spec/support/shared_examples/notify_shared_examples.rb30
-rw-r--r--spec/tasks/gitlab/check_rake_spec.rb9
-rw-r--r--spec/workers/build_success_worker_spec.rb44
-rw-r--r--spec/workers/cluster_provision_worker_spec.rb7
-rw-r--r--spec/workers/pages_domain_ssl_renewal_cron_worker_spec.rb62
-rw-r--r--spec/workers/pages_domain_ssl_renewal_worker_spec.rb46
-rw-r--r--yarn.lock70
628 files changed, 5241 insertions, 3212 deletions
diff --git a/.gitlab/ci/docs.gitlab-ci.yml b/.gitlab/ci/docs.gitlab-ci.yml
index 5aa1a856405..beab406fab7 100644
--- a/.gitlab/ci/docs.gitlab-ci.yml
+++ b/.gitlab/ci/docs.gitlab-ci.yml
@@ -66,6 +66,10 @@ docs lint:
- scripts/lint-changelog-yaml
- mv doc/ /tmp/gitlab-docs/content/$DOCS_GITLAB_REPO_SUFFIX
- cd /tmp/gitlab-docs
+ # Lint Markdown
+ # https://github.com/markdownlint/markdownlint/blob/master/docs/RULES.md
+ - bundle exec mdl content/$DOCS_GITLAB_REPO_SUFFIX/**/*.md --rules \
+ MD032
# Build HTML from Markdown
- bundle exec nanoc
# Check the internal links
diff --git a/.gitlab/ci/frontend.gitlab-ci.yml b/.gitlab/ci/frontend.gitlab-ci.yml
index 75c79bb213f..cd6953a6ac2 100644
--- a/.gitlab/ci/frontend.gitlab-ci.yml
+++ b/.gitlab/ci/frontend.gitlab-ci.yml
@@ -72,6 +72,7 @@ gitlab:assets:compile pull-cache:
except:
- master@gitlab-org/gitlab-ce
- master@gitlab-org/gitlab-ee
+ - /(^docs[\/-].*|.*-docs$)/
.compile-assets-metadata:
extends: .dedicated-runner
diff --git a/.gitlab/ci/global.gitlab-ci.yml b/.gitlab/ci/global.gitlab-ci.yml
index b7ef4b31743..eb50f08c1a7 100644
--- a/.gitlab/ci/global.gitlab-ci.yml
+++ b/.gitlab/ci/global.gitlab-ci.yml
@@ -28,11 +28,15 @@
policy: pull
stage: test
-.dedicated-no-docs-pull-cache-job:
- extends: .dedicated-pull-cache-job
+.no-docs:
except:
- /(^docs[\/-].*|.*-docs$)/
+.dedicated-no-docs-pull-cache-job:
+ extends:
+ - .dedicated-pull-cache-job
+ - .no-docs
+
.dedicated-no-docs-and-no-qa-pull-cache-job:
extends: .dedicated-pull-cache-job
except:
@@ -45,6 +49,12 @@
variables:
SETUP_DB: "false"
+# Jobs that need a dedicated runner, with no cache
+.dedicated-no-docs:
+ extends:
+ - .dedicated-runner
+ - .no-docs
+
.single-script-job-dedicated-runner:
extends: .dedicated-runner
image: ruby:2.6-alpine
diff --git a/.gitlab/ci/reports.gitlab-ci.yml b/.gitlab/ci/reports.gitlab-ci.yml
index d0e09dbf2f8..89b5ae38072 100644
--- a/.gitlab/ci/reports.gitlab-ci.yml
+++ b/.gitlab/ci/reports.gitlab-ci.yml
@@ -1,98 +1,26 @@
include:
- template: Code-Quality.gitlab-ci.yml
+ - template: Security/SAST.gitlab-ci.yml
+ - template: Security/Dependency-Scanning.gitlab-ci.yml
code_quality:
- extends: .dedicated-no-docs-no-db-pull-cache-job
+ extends: .dedicated-no-docs
# gitlab-org runners set `privileged: false` but we need to have it set to true
# since we're using Docker in Docker
tags: []
before_script: []
cache: {}
dependencies: []
- variables:
- SETUP_DB: "false"
sast:
- extends: .dedicated-no-docs-no-db-pull-cache-job
- image: docker:stable
+ extends: .dedicated-no-docs
+ before_script: []
+ tags: []
variables:
SAST_CONFIDENCE_LEVEL: 2
DOCKER_DRIVER: overlay2
- allow_failure: true
- tags: []
- before_script: []
- cache: {}
- dependencies: []
- services:
- - docker:stable-dind
- script:
- - | # this is required to avoid undesirable reset of Docker image ENV variables being set on build stage
- function propagate_env_vars() {
- CURRENT_ENV=$(printenv)
-
- for VAR_NAME; do
- echo $CURRENT_ENV | grep "${VAR_NAME}=" > /dev/null && echo "--env $VAR_NAME "
- done
- }
- - export SP_VERSION=$(echo "$CI_SERVER_VERSION" | sed 's/^\([0-9]*\)\.\([0-9]*\).*/\1-\2-stable/')
- - |
- docker run \
- $(propagate_env_vars \
- SAST_ANALYZER_IMAGES \
- SAST_ANALYZER_IMAGE_PREFIX \
- SAST_ANALYZER_IMAGE_TAG \
- SAST_DEFAULT_ANALYZERS \
- SAST_BRAKEMAN_LEVEL \
- SAST_GOSEC_LEVEL \
- SAST_FLAWFINDER_LEVEL \
- SAST_DOCKER_CLIENT_NEGOTIATION_TIMEOUT \
- SAST_PULL_ANALYZER_IMAGE_TIMEOUT \
- SAST_RUN_ANALYZER_TIMEOUT \
- ) \
- --volume "$PWD:/code" \
- --volume /var/run/docker.sock:/var/run/docker.sock \
- "registry.gitlab.com/gitlab-org/security-products/sast:$SP_VERSION" /app/bin/run /code
- artifacts:
- reports:
- sast: gl-sast-report.json
dependency_scanning:
- extends: .dedicated-no-docs-no-db-pull-cache-job
- image: docker:stable
- variables:
- DOCKER_DRIVER: overlay2
- allow_failure: true
- tags: []
before_script: []
- cache: {}
- dependencies: []
- services:
- - docker:stable-dind
- script:
- - export SP_VERSION=$(echo "$CI_SERVER_VERSION" | sed 's/^\([0-9]*\)\.\([0-9]*\).*/\1-\2-stable/')
- - | # this is required to avoid undesirable reset of Docker image ENV variables being set on build stage
- function propagate_env_vars() {
- CURRENT_ENV=$(printenv)
-
- for VAR_NAME; do
- echo $CURRENT_ENV | grep "${VAR_NAME}=" > /dev/null && echo "--env $VAR_NAME "
- done
- }
- - |
- docker run \
- $(propagate_env_vars \
- DS_ANALYZER_IMAGES \
- DS_ANALYZER_IMAGE_PREFIX \
- DS_ANALYZER_IMAGE_TAG \
- DS_DEFAULT_ANALYZERS \
- DEP_SCAN_DISABLE_REMOTE_CHECKS \
- DS_DOCKER_CLIENT_NEGOTIATION_TIMEOUT \
- DS_PULL_ANALYZER_IMAGE_TIMEOUT \
- DS_RUN_ANALYZER_TIMEOUT \
- ) \
- --volume "$PWD:/code" \
- --volume /var/run/docker.sock:/var/run/docker.sock \
- "registry.gitlab.com/gitlab-org/security-products/dependency-scanning:$SP_VERSION" /code
- artifacts:
- reports:
- dependency_scanning: gl-dependency-scanning-report.json
+ tags: []
+ extends: .dedicated-no-docs
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 623e5d0acb9..118034867ad 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,320 @@
documentation](doc/development/changelog.md) for instructions on adding your own
entry.
+## 12.0.1 (2019-06-24)
+
+- No changes.
+
+## 12.0.0 (2019-06-22)
+
+### Security (10 changes)
+
+- Hide confidential issue title on unsubscribe for anonymous users.
+- Fix url redaction for issue links.
+- Fix confidential issue label disclosure on milestone view.
+- Filter relative links in wiki for XSS.
+- Prevent XSS injection in note imports.
+- Resolve: Milestones leaked via search API.
+- Prevent bypass of restriction disabling web password sign in.
+- Add extra fields for handling basic auth on import by url page.
+- Protect Gitlab::HTTP against DNS rebinding attack.
+- Prevent invalid branch for merge request.
+
+### Removed (5 changes, 1 of them is from the community)
+
+- Remove ability for group clusters to be automatically configured on creation. !27245
+- Removes support for AUTO_DEVOPS_DOMAIN. !28460
+- Remove the circuit breaker API. !28669
+- Make Kubernetes service templates readonly. !29044
+- Remove Content-Type override for Mattermost OAuth login. (Harrison Healey)
+
+### Fixed (116 changes, 28 of them are from the community)
+
+- Fix col-sm-* in forms to keep layout. !24885 (Takuya Noguchi)
+- Avoid 500 when rendering users ATOM data. !25408
+- Fix flyout nav on small viewports. !25998
+- Fix proxy support in Container Scanning. !27246
+- preventing blocked users and their PipelineSchdules from creating new Pipelines. !27318
+- Fix yaml linting for GitLab CI inside project (.gitlab/ci) *.yml files and CI template files. !27576 (Will Hall)
+- Fix yaml linting for project root *.yml files. !27579 (Will Hall)
+- Added a content field to atom feed. !27652
+- Bring secondary button styles up to design standard. !27920
+- Use FindOrCreateService to create labels and check for existing ones. !27987 (Matt Duren)
+- Fix "too many loops" error by handling gracefully cron schedules for non existent days. !28002
+- Handle errors in successful notes reply. !28082
+- Fix 500 error when accessing charts with an anonymous user. !28091 (Diego Silva)
+- Allow user to set primary email first when 2FA is required. !28097 (Kartikey Tanna)
+- Auto-DevOps: allow to disable rollout status check. !28130 (Sergej Nikolaev <kinolaev@gmail.com>)
+- Resolved JIRA service: NoMethodError: undefined method 'find' for nil:NilClass. !28206
+- Supports Matomo/Piwik string website ID ("Protect Track ID" plugin). !28214 (DUVERGIER Claude)
+- Fix loading.. dropdown at search field. !28275 (Pavel Chausov)
+- Remove unintended error message shown when moving issues. !28317
+- Properly clear the merge error upon rebase failure. !28319
+- Upgrade dependencies for node 12 compatibility. !28323
+- Fix. `db:migrate` is failed on MySQL 8. !28351 (sue445)
+- Fix an error in projects admin when statistics are missing. !28355
+- Fix emojis URLs. !28371
+- Prevent common name collisions when requesting multiple Let's Encrypt certificates concurrently. !28373
+- Fix issue that causes "Save changes" button in project settings pages to be enabled/disabled incorrectly when changes are made to the form. !28377
+- Fix diff notes and discussion notes being exported as regular notes. !28401
+- Fix padding in MR widget. !28472
+- Updates loading icon in commits page. !28475
+- Fix border radius of discussions. !28490
+- Update broadcast message action icons. !28496 (Jarek Ostrowski @jareko)
+- Update icon color to match design system, pass accessibility. !28498 (Jarek Ostrowski @jareko)
+- Show data on Cycle Analytics page when value is less than a second. !28507
+- Fix dropdown position when loading remote data. !28526
+- Delete unauthorized Todos when project is made private. !28560
+- Change links in system notes to use relative paths. !28588 (Luke Picciau)
+- Update favicon from next. !28601 (Jarek Ostrowski @jareko)
+- Open visibility help link in a new tab. !28603 (George Tsiolis)
+- Fix issue importing members with owner access. !28636
+- Fix the height of the page headers on issues/merge request/snippets pages. !28650 (Erik van der Gaag)
+- Always show "Pipelines must succeed" checkbox. !28651
+- Resolve moving an issue results in broken image links in comments. !28654
+- Fix milestone references containing &, <, or >. !28667
+- Add hover and focus to Attach a file. !28682
+- Correctly word-wrapping project descriptions with very long words. !28695 (Erik van der Gaag)
+- Prevent icons from shrinking in User popover when contents exceed container. !28696
+- Allow removal of empty lines via suggestions. !28703
+- Throw an error when formatDate's input is invalid. !28713
+- Fix order dependency with user params during imports. !28719
+- Fix search dropdown not closing on blur if empty. !28730
+- Fixed ignored postgres version that occurs after the first autodevops deploy when specifying custom $POSTGRES_VERSION. !28735 (Brandon Dimcheff)
+- Limit milestone dates to before year 9999. !28742 (Luke Picciau)
+- Set project default visibility to max allowed. !28754
+- Cancel auto merge when merge request is closed. !28782
+- Fixes Ref link being displayed as raw HTML in the Pipelines page. !28823
+- Fix job name in graph dropdown overflowing. !28824
+- Add style to disable webkit icons for search inputs. !28833 (Jarek Ostrowski @jareko)
+- Fix email notifications for user excluded actions. !28835
+- Resolve Tooltip Consistency. !28839
+- Fix Merge Request merge checkbox alignment on mobile view. !28845
+- Add referenced-commands in no overflow list. !28858
+- Fix participants list wrapping. !28873
+- Excludes MR author from Review roulette. !28886 (Jacopo Beschi @jacopo-beschi)
+- Give labels consistent weight. !28895
+- Added padding to time window dropdown in monitor dashboard. !28897
+- Move text under p tag. !28901
+- Resolve Position is off when visiting files with anchors. !28913
+- Fix whitespace changes visibility when the related file was initially collapsed. !28950 (Ondřej Budai)
+- Fix emoji picker visibility issue. !28984
+- Resolve Merge request discussion text jumps when resolved. !28995
+- Allow lowercase prefix for Youtrack issue ids. !29057 (Matthias Baur)
+- Add support to view entirety of long branch name in dropdown instead of it being cut off. !29069
+- Fix inconsistent option dropdown button height to match adjacent button. !29096
+- Improve new user email markup unconsistency between text and html parts. !29111 (Haunui Saint-sevin)
+- Eliminate color inconsistencies in metric graphs. !29127
+- Avoid setting Gitlab::Session on sessionless requests and Git HTTP. !29146
+- Use the selected time window for metrics dashboard. !29152
+- Remove build policies from serverless app template. !29253
+- Fix serverless apps deployments by bumping 'tm' version. !29254
+- Include the port in the URLs of the API Link headers. !29267
+- Fix Fogbugz Importer not working. !29383
+- Fix GPG signature verification with recent GnuPG versions. !29388 (David Palubin)
+- Cancel Auto Merge when target branch is changed. !29416
+- Fix nil coercion updating storage size on project statistics. !29425
+- Ignore legacy artifact columns in Project Import/Export. !29427
+- Avoid DB timeouts when scheduling migrations. !29437
+- Handle encoding errors for MergeToRefService. !29440
+- Fix UTF-8 conversion issues when resolving conflicts. !29453
+- Enlarge metrics time-window dropdown links. !29458
+- Remove unnecessary decimals on Metrics chart axis. !29468
+- Fix scrolling to top on assignee change. !29500
+- Allow command/control click to open link in new tab on Merge Request tabs. !29506
+- Omit blocked admins from repository check e-mails. !29507
+- Fix diverged branch locals. !29508
+- Process up to 100 commit messages for references when pushing to a new default branch. !29511 (Fabio Papa)
+- Allow developer role to delete docker tags via container registry API. !29512
+- Fix "Resolve conflicts" button not appearing for some users. !29535
+- Fix: propagate all documented ENV vars to CI when using SAST. !29564
+- AutoDevops function ensure_namespace() now explicitly tests the namespace. !29567 (Jack Lei)
+- Fix sidebar flyout navigation. !29571
+- Fix missing deployment rockets in monitor dashboard. !29574
+- Fix inability to set visibility_level on project via API. !29578
+- Ensure a Kubernetes namespace is not used for deployments if there is no service account token associated with it. !29643
+- Refresh service_account_token for kubernetes_namespaces. !29657
+- Expose all current events properly on services API. !29736 (Zsolt Kovari)
+- Move Dropdown to Stick to MR View App Button. !29767
+- Fix IDE commit using latest ref in branch and overriding contents. !29769
+- Revert concurrent pipeline creation for pipeline schedules. !29794
+- Fix layout of group milestone header.
+- Fix remote mirrors not updating after tag push.
+- Fix padding of unclickable pipeline dropdown items to match links.
+- Change resolve button text to mark comment as resolved.
+- Align system note within discussion with other notes.
+- Fix border radii on diff files and repo files.
+- Fixed show whitespace button not refetching diff content.
+- Fix pipeline schedules when owner is nil.
+
+### Changed (35 changes, 13 of them are from the community)
+
+- Include information if issue was clossed via merge request or commit. !15610 (Michał Zając)
+- Removes duplicated members from api/projects/:id/members/all. !24005 (Jacopo Beschi @jacopo-beschi)
+- Apply the group setting "require 2FA" across all subgroup members as well when changing the group setting. !24965 (rroger)
+- Enable function features for external Knative installations. !27173
+- Remove dind from DAST template. !28083
+- Update registration form to indicate invalid name or username length on input. !28095 (Jiaan Louw)
+- Default masked to false for new variables. !28186
+- Better isolated `Docker.gitlab-ci.yml` to avoid interference with other job configurations. !28213 (lrkwz)
+- Remove the mr_push_options feature flag. !28278
+- Replace Oxygen-Sans font with Noto Sans. !28322
+- Update new smiley icons, find n replace old names with new ones. !28338 (Jarek Ostrowski)
+- Adds a text label to color pickers to improve accessibility. !28343 (Chris Toynbee)
+- Prioritize login form on mobile breakpoint. !28360
+- Move some project routes under /-/ scope. !28435
+- I18n for issue closure reason in emails. !28489 (Michał Zając)
+- Geo: Remove Gitlab::LfsToken::LegacyRedisDeviseToken implementation and usage. !28546
+- Add check circle filled icon for resolved comments. !28663
+- Update project security dashboard documentation. !28681
+- Remove `docker pull` prefix when copying a tag from the registry. !28757 (Benedikt Franke)
+- Adjust milestone completion rate to be based on issues count. !28777
+- Enhance line-height of Activity feed UI. !28856 (Jacopo Beschi @jacopo-beschi)
+- Upgrade to Gitaly v1.43.0. !28867
+- Do not display Update app button when saving Knative domain name. !28904
+- Rebrush of flash-warning according to the new design (brighter background and darker font). !28916 (Michel Engelen)
+- Added reference, web_path, and relative_position fields to GraphQL Issue. !28998
+- Change logic behind cycle analytics. !29018
+- Add documentation links for confidental and locked discussions. !29073
+- Update GITALY_SERVER_VERSION to 1.45.0. !29109
+- Allow masking if 8 or more characters in base64. !29143 (thomas-nilsson-irfu)
+- Replaces sidekiq mtail metrics with ruby instrumentation metrics. !29215
+- Allow references to labels and milestones to contain emoji. !29284
+- changed the styles on `Add List` dropdown to look more like the EE vesion. !29338 (Michel Engelen)
+- Hashed Storage is enabled by default on new installations. !29586
+- Upgrade to Gitaly v1.47.0. !29789
+- Default MR checkbox to true in most cases.
+
+### Performance (11 changes)
+
+- Improve performance of jobs controller. !28093
+- Upgrade Ruby version to 2.6.3. !28117
+- Make pipeline schedule worker resilient. !28407
+- Fix performance issue with large Markdown content in issue or merge request description. !28597
+- Improve clone performance by using delta islands. !28871
+- Reduce Gitaly calls to improve performance when rendering suggestions. !29027
+- Use Redis for CacheMarkDownField on non AR models. !29054
+- Add index on public_email for users. !29430
+- Speed up commit loads by disabling BatchLoader replace_methods. !29633
+- Add index on invite_email for members. !29768
+- Improve performance of users autocomplete when there are lots of results.
+
+### Added (47 changes, 12 of them are from the community)
+
+- Added option to filter jobs by age in the /job/request API endpoint. !1340 (Dmitry Chepurovskiy)
+- Add ability to define notification email addresses for groups you belong to. !25299
+- Add wiki size to project statistics. !25321 (Peter Marko)
+- 58404 - setup max depth for GraphQL. !25737 (Ken Ding)
+- Add auto SSL toggle option to Pages domain settings page. !26438
+- Empty project state for Web IDE. !26556
+- Add support for multiple job parents in GitLab CI YAML. !26801 (Wolphin (Nikita))
+- Pass user's identity and token from JupyterHub to user's Jupyter environment. !27314 (Amit Rathi)
+- Add issues_statistics api endpoints and extend issues search api. !27366
+- Validate Kubernetes credentials at cluster creation. !27403
+- Update the merge request widget's "Merge" button to support merge trains. !27594
+- Style the toast component according to design specs. !27734
+- Add API support for committing changes to different projects in same fork network. !27915
+- Add support for && and || to CI Pipeline Expressions. Change CI variable expression matching for Lexeme::Pattern to eagerly return tokens. !27925 (Martin Manelli)
+- Added ref querystring parameter to project search API to allow searching on branches/tags other than the default. !28069 (Lee Tickett)
+- Add notify_only_default_branch option to PipelinesEmailService. !28271 (Peter Marko)
+- Support multiplex GraphQL queries. !28273
+- Add Namespace and ProjectStatistics to GraphQL API. !28277
+- Display classname JUnit attribute in report modal. !28376
+- API: Allow to get and set "masked" attribute for variables. !28381 (Mathieu Parent)
+- Add allow_failure attribute to Job API. !28406
+- Add support for AsciiDoc include directive. !28417 (Jakub Jirutka & Guillaume Grossetie)
+- Migrate Kubernetes service integration templates to clusters. !28534
+- Allow issue list to be sorted by relative order. !28566
+- Implement borderless discussion design with new reply field. !28580
+- Add expand/collapse to error tracking settings. !28619
+- Adds collapsible sections for job log. !28642
+- Add LFS oid to GraphQL blob type. !28666
+- Allow users to specify a time range on metrics dashboard. !28670
+- Add a New Copy Button That Works in Modals. !28676
+- Add Kubernetes logs to Admin Logs UI. !28685
+- Set up git client in Jupyter installtion. !28783 (Amit Rathi)
+- Add task count and completed count to responses of Issue and MR. !28859
+- Add project level git depth CI/CD setting. !28919
+- Use global IDs when exposing GraphQL resources. !29080
+- Expose wiki_size on GraphQL API. !29123
+- Expose notes and discussions in GraphQL. !29212
+- Use to 'gitlabktl' build serverless applications. !29258
+- Adds pagination component for graphql api. !29277
+- Allow switching clusters between managed and unmanaged. !29322
+- Get and edit ci_default_git_depth via project API. !29353
+- Link to an external dashboard from metrics dashboard. !29369
+- Add labels to note event payload. !29384 (Sujay Patel)
+- Add Join meeting button to issues with Zoom links. !29454
+- Make task completion status available via GraphQL.
+- Add backtraces to Peek performance bar for SQL calls.
+- Added diff suggestion feature discovery popover.
+
+### Other (62 changes, 14 of them are from the community)
+
+- Unified EE/CS differences in repository/show.html. !13562
+- Remove legacy artifact related code. !26475
+- Backport the EE schema and migrations to CE. !26940 (Yorick Peterse)
+- Add dedicated logging for GraphQL queries. !27885
+- i18n: externalize strings from user profile settings. !28088 (Antony Liu)
+- Omit max-count for diverging_commit_counts behind feature flag. !28157
+- Fix alignment of resend button in members page. !28202
+- Update indirect dependency fsevents from 1.2.4 to 1.2.9. !28220 (Takuya Noguchi)
+- Update get_process_mem to 0.2.3. !28248
+- Add Pool repository to the usage ping. !28267
+- Forbid NULL in project_statistics.packages_size. !28400
+- Update Gitaly to v1.42.1. !28425
+- Upgrade babel to 7.4.4. !28437 (Takuya Noguchi)
+- Externalize profiles preferences. !28470 (George Tsiolis)
+- Update GitLab Runner Helm Chart to 0.5.0. !28497
+- Change collapse icon size to size of profile picture. !28512
+- Resolve Snippet icon button is misaligned. !28522
+- Bumps Kubernetes in Auto DevOps to 1.11.10. !28525
+- Bump Helm version in Auto-DevOps.gitlab-ci.yml to 2.14.0. !28527
+- Migrate the monitoring dashboard store to vuex. !28555
+- Give New Snippet button green outline. !28559
+- Removes project_auto_devops#domain column. !28574
+- Externalize strings of email page in user profile. !28587 (antony liu)
+- Externalize strings of active sessions page in user profile. !28590 (antony liu)
+- Refactor and abstract Auto Merge Processes. !28595
+- Add section to dev docs on accessing chatops. !28623
+- Externalize strings of chat page in user profile. !28632
+- Externalize strings of PGP Keys and SSH Keys page in user profile. !28653 (Antony Liu)
+- Added the `.extended-height` class to the labels-dropdown. !28659 (Michel Engelen)
+- Moved EE/CE code differences for `app/assets/javascripts/gl_dropdown.js` into CE. !28711 (Michel Engelen)
+- Update GitLab Runner Helm Chart to 0.5.1. !28720
+- Remove support for using Geo with an installation from source. !28737
+- API: change masked attribute type to Boolean. !28758
+- API: change protected attribute type to Boolean. !28766
+- Add a column header to admin/jobs page. !28837
+- Reset merge status from mergeable MRs. !28843
+- Show tooltip on truncated commit title. !28865 (Timofey Trofimov)
+- Added conditional rendering to `app/views/search/_form.html.haml` for CE/EE code base consistency. !28883 (Michel Engelen)
+- Change "Report abuse to GitLab" to more generic wording. !28884 (Marc Schwede)
+- Update GitLab Pages to v1.6.0. !29048
+- Update GitLab Runner Helm Chart to 0.5.2. !29050
+- User link styling for commits. !29150
+- Fix null source_project_id in pool_repositories. !29157
+- Add deletion protection setting column to application_settings table. !29268
+- Added code differnces from EE in file 'app/assets/javascripts/pages/projects/project.js' to CE. !29271 (Michel Engelen)
+- Update to GitLab Shell v9.3.0. !29283
+- Document when milestones and labels links are missing. !29355
+- Make margin between buttons consistent. !29378
+- Changed the 'Created' label to 'Last Updated' on the container registry table to more accurately reflect what the date represents. !29464
+- Update GitLab Pages to v1.6.1. !29559
+- Indent collapsible sections. !29804
+- Group download buttons into a .btn-group.
+- Change default color of award emoji button.
+- Use blue for activity stream links; use monospace font for commit sha.
+- Remove fixed height from MR diff headers.
+- Moves the table pagination shared component.
+- Add warning that gitlab-secrets isn't included in backup.
+- Update merge request tabs so they no longer scroll.
+- Reduce height of issue board input to align with buttons.
+- Increase height of move issue dropdown.
+- Use grid and correct border radius for status badge.
+- Moves snowplow to CE repo.
+
+
## 11.11.3 (2019-06-10)
### Fixed (5 changes)
diff --git a/GITALY_SERVER_VERSION b/GITALY_SERVER_VERSION
index 21998d3c2d9..9db5ea12f52 100644
--- a/GITALY_SERVER_VERSION
+++ b/GITALY_SERVER_VERSION
@@ -1 +1 @@
-1.47.0
+1.48.0
diff --git a/Gemfile b/Gemfile
index b9ce2422153..302f39756e8 100644
--- a/Gemfile
+++ b/Gemfile
@@ -300,6 +300,9 @@ gem 'peek-pg', '~> 1.3.0', group: :postgres
gem 'peek-rblineprof', '~> 0.2.0'
gem 'peek-redis', '~> 1.2.0'
+# Memory benchmarks
+gem 'derailed_benchmarks', require: false
+
# Metrics
group :metrics do
gem 'method_source', '~> 0.8', require: false
@@ -374,7 +377,6 @@ group :development, :test do
gem 'activerecord_sane_schema_dumper', '1.0'
gem 'stackprof', '~> 0.2.10', require: false
- gem 'derailed_benchmarks', require: false
gem 'simple_po_parser', '~> 1.1.2', require: false
diff --git a/Gemfile.lock b/Gemfile.lock
index b03bd58eacc..4881faac0e0 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -770,7 +770,7 @@ GEM
retriable (3.1.2)
rinku (2.0.0)
rotp (2.1.2)
- rouge (3.3.0)
+ rouge (3.4.1)
rqrcode (0.7.0)
chunky_png
rqrcode-rails3 (0.1.7)
diff --git a/VERSION b/VERSION
index 11bf1ec035c..6edc7fa8d35 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-12.0.0-pre
+12.1.0-pre
diff --git a/app/assets/javascripts/boards/components/board_sidebar.js b/app/assets/javascripts/boards/components/board_sidebar.js
index c587b276fa3..2ace0060c42 100644
--- a/app/assets/javascripts/boards/components/board_sidebar.js
+++ b/app/assets/javascripts/boards/components/board_sidebar.js
@@ -38,6 +38,7 @@ export default Vue.extend({
issue: {},
list: {},
loadingAssignees: false,
+ timeTrackingLimitToHours: boardsStore.timeTracking.limitToHours,
};
},
computed: {
diff --git a/app/assets/javascripts/boards/components/issue_time_estimate.vue b/app/assets/javascripts/boards/components/issue_time_estimate.vue
index 98c1d29db16..3385aad5b11 100644
--- a/app/assets/javascripts/boards/components/issue_time_estimate.vue
+++ b/app/assets/javascripts/boards/components/issue_time_estimate.vue
@@ -2,6 +2,7 @@
import { GlTooltip } from '@gitlab/ui';
import Icon from '~/vue_shared/components/icon.vue';
import { parseSeconds, stringifyTime } from '~/lib/utils/datetime_utility';
+import boardsStore from '../stores/boards_store';
export default {
components: {
@@ -14,12 +15,17 @@ export default {
required: true,
},
},
+ data() {
+ return {
+ limitToHours: boardsStore.timeTracking.limitToHours,
+ };
+ },
computed: {
title() {
- return stringifyTime(parseSeconds(this.estimate), true);
+ return stringifyTime(parseSeconds(this.estimate, { limitToHours: this.limitToHours }), true);
},
timeEstimate() {
- return stringifyTime(parseSeconds(this.estimate));
+ return stringifyTime(parseSeconds(this.estimate, { limitToHours: this.limitToHours }));
},
},
};
diff --git a/app/assets/javascripts/boards/index.js b/app/assets/javascripts/boards/index.js
index f2f37d22b97..a020765f335 100644
--- a/app/assets/javascripts/boards/index.js
+++ b/app/assets/javascripts/boards/index.js
@@ -49,6 +49,7 @@ export default () => {
}
boardsStore.create();
+ boardsStore.setTimeTrackingLimitToHours($boardApp.dataset.timeTrackingLimitToHours);
issueBoardsApp = new Vue({
el: $boardApp,
diff --git a/app/assets/javascripts/boards/stores/boards_store.js b/app/assets/javascripts/boards/stores/boards_store.js
index 4b3b44574a8..4ba4cde6bae 100644
--- a/app/assets/javascripts/boards/stores/boards_store.js
+++ b/app/assets/javascripts/boards/stores/boards_store.js
@@ -12,6 +12,9 @@ import eventHub from '../eventhub';
const boardsStore = {
disabled: false,
+ timeTracking: {
+ limitToHours: false,
+ },
scopedLabels: {
helpLink: '',
enabled: false,
@@ -222,6 +225,10 @@ const boardsStore = {
setIssueDetail(issueDetail) {
this.detail.issue = issueDetail;
},
+
+ setTimeTrackingLimitToHours(limitToHours) {
+ this.timeTracking.limitToHours = parseBoolean(limitToHours);
+ },
};
BoardsStoreEE.initEESpecific(boardsStore);
diff --git a/app/assets/javascripts/branches/components/divergence_graph.vue b/app/assets/javascripts/branches/components/divergence_graph.vue
new file mode 100644
index 00000000000..36fff370ea1
--- /dev/null
+++ b/app/assets/javascripts/branches/components/divergence_graph.vue
@@ -0,0 +1,72 @@
+<script>
+import { sprintf, __ } from '~/locale';
+import GraphBar from './graph_bar.vue';
+import { MAX_COMMIT_COUNT } from '../constants';
+
+export default {
+ components: {
+ GraphBar,
+ },
+ props: {
+ defaultBranch: {
+ type: String,
+ required: true,
+ },
+ distance: {
+ type: Number,
+ required: false,
+ default: null,
+ },
+ aheadCount: {
+ type: Number,
+ required: true,
+ },
+ behindCount: {
+ type: Number,
+ required: true,
+ },
+ maxCommits: {
+ type: Number,
+ required: true,
+ },
+ },
+ computed: {
+ title() {
+ if (this.distance) {
+ return sprintf(
+ __('More than %{number_commits_distance} commits different with %{default_branch}'),
+ {
+ number_commits_distance:
+ this.distance >= MAX_COMMIT_COUNT ? `${MAX_COMMIT_COUNT - 1}+` : this.distance,
+ default_branch: this.defaultBranch,
+ },
+ );
+ }
+
+ return sprintf(
+ __(
+ '%{number_commits_behind} commits behind %{default_branch}, %{number_commits_ahead} commits ahead',
+ ),
+ {
+ number_commits_behind: this.behindCount,
+ number_commits_ahead: this.aheadCount,
+ default_branch: this.defaultBranch,
+ },
+ );
+ },
+ },
+};
+</script>
+
+<template>
+ <div :title="title" class="divergence-graph px-2 d-none d-md-block">
+ <template v-if="distance">
+ <graph-bar :count="distance" :max-commits="maxCommits" position="full" />
+ </template>
+ <template v-else>
+ <graph-bar :count="behindCount" :max-commits="maxCommits" position="left" />
+ <div class="graph-separator pull-left mt-1"></div>
+ <graph-bar :count="aheadCount" :max-commits="maxCommits" position="right" />
+ </template>
+ </div>
+</template>
diff --git a/app/assets/javascripts/branches/components/graph_bar.vue b/app/assets/javascripts/branches/components/graph_bar.vue
new file mode 100644
index 00000000000..83da41ca097
--- /dev/null
+++ b/app/assets/javascripts/branches/components/graph_bar.vue
@@ -0,0 +1,69 @@
+<script>
+import { SIDES, MAX_COMMIT_COUNT } from '../constants';
+
+export default {
+ props: {
+ position: {
+ type: String,
+ required: true,
+ },
+ count: {
+ type: Number,
+ required: true,
+ },
+ maxCommits: {
+ type: Number,
+ required: true,
+ },
+ },
+ computed: {
+ label() {
+ if (this.count >= MAX_COMMIT_COUNT) {
+ return `${MAX_COMMIT_COUNT - 1}+`;
+ }
+
+ return this.count;
+ },
+ barGraphWidthFactor() {
+ return this.maxCommits > 0 ? 100 / this.maxCommits : 0;
+ },
+ style() {
+ return {
+ width: `${this.count * this.barGraphWidthFactor}%`,
+ };
+ },
+ isFullWidth() {
+ return this.position === SIDES.full;
+ },
+ isLeftSide() {
+ return this.position === SIDES.left;
+ },
+ roundedClass() {
+ if (this.isFullWidth) return 'rounded';
+
+ return `rounded-${this.position}`;
+ },
+ textAlignmentClass() {
+ if (this.isFullWidth) return 'text-center';
+
+ return `text-${this.isLeftSide ? SIDES.right : SIDES.left}`;
+ },
+ positionSideClass() {
+ return `position-${this.isLeftSide ? SIDES.right : SIDES.left}-0`;
+ },
+ },
+};
+</script>
+
+<template>
+ <div :class="{ full: isFullWidth }" class="position-relative pull-left pt-1 graph-side h-100">
+ <div
+ :style="style"
+ :class="[roundedClass, positionSideClass]"
+ class="position-absolute bar js-graph-bar"
+ ></div>
+ <span :class="textAlignmentClass" class="d-block pt-1 pr-1 count js-graph-count">
+ {{ label }}
+ </span>
+ </div>
+</template>
diff --git a/app/assets/javascripts/branches/constants.js b/app/assets/javascripts/branches/constants.js
new file mode 100644
index 00000000000..16949e662d2
--- /dev/null
+++ b/app/assets/javascripts/branches/constants.js
@@ -0,0 +1,6 @@
+export const SIDES = {
+ full: 'full',
+ left: 'left',
+ right: 'right',
+};
+export const MAX_COMMIT_COUNT = 1000;
diff --git a/app/assets/javascripts/branches/divergence_graph.js b/app/assets/javascripts/branches/divergence_graph.js
new file mode 100644
index 00000000000..670e8e9eb60
--- /dev/null
+++ b/app/assets/javascripts/branches/divergence_graph.js
@@ -0,0 +1,23 @@
+import Vue from 'vue';
+import DivergenceGraph from './components/divergence_graph.vue';
+
+export default () => {
+ document.querySelectorAll('.js-branch-divergence-graph').forEach(el => {
+ const { distance, aheadCount, behindCount, defaultBranch, maxCommits } = el.dataset;
+
+ return new Vue({
+ el,
+ render(h) {
+ return h(DivergenceGraph, {
+ props: {
+ defaultBranch,
+ distance: distance ? parseInt(distance, 10) : null,
+ aheadCount: parseInt(aheadCount, 10),
+ behindCount: parseInt(behindCount, 10),
+ maxCommits: parseInt(maxCommits, 10),
+ },
+ });
+ },
+ });
+ });
+};
diff --git a/app/assets/javascripts/environments/components/container.vue b/app/assets/javascripts/environments/components/container.vue
index f8a637138ad..426bb63d4f7 100644
--- a/app/assets/javascripts/environments/components/container.vue
+++ b/app/assets/javascripts/environments/components/container.vue
@@ -57,6 +57,7 @@ export default {
:user-callouts-path="userCalloutsPath"
:lock-promotion-svg-path="lockPromotionSvgPath"
:help-canary-deployments-path="helpCanaryDeploymentsPath"
+ :deploy-boards-help-path="deployBoardsHelpPath"
/>
<table-pagination
diff --git a/app/assets/javascripts/environments/components/environments_app.vue b/app/assets/javascripts/environments/components/environments_app.vue
index ec78240217b..81927d18f8b 100644
--- a/app/assets/javascripts/environments/components/environments_app.vue
+++ b/app/assets/javascripts/environments/components/environments_app.vue
@@ -43,6 +43,11 @@ export default {
type: String,
required: true,
},
+ deployBoardsHelpPath: {
+ type: String,
+ required: false,
+ default: '',
+ },
},
created() {
@@ -112,6 +117,7 @@ export default {
:user-callouts-path="userCalloutsPath"
:lock-promotion-svg-path="lockPromotionSvgPath"
:help-canary-deployments-path="helpCanaryDeploymentsPath"
+ :deploy-boards-help-path="deployBoardsHelpPath"
@onChangePage="onChangePage"
>
<empty-state
diff --git a/app/assets/javascripts/environments/components/environments_table.vue b/app/assets/javascripts/environments/components/environments_table.vue
index 55613d815ce..4464f5e5578 100644
--- a/app/assets/javascripts/environments/components/environments_table.vue
+++ b/app/assets/javascripts/environments/components/environments_table.vue
@@ -22,6 +22,11 @@ export default {
required: true,
default: () => [],
},
+ deployBoardsHelpPath: {
+ type: String,
+ required: false,
+ default: '',
+ },
canReadEnvironment: {
type: Boolean,
required: false,
@@ -106,8 +111,10 @@ export default {
<div class="deploy-board-container">
<deploy-board
:deploy-board-data="model.deployBoardData"
+ :deploy-boards-help-path="deployBoardsHelpPath"
:is-loading="model.isLoadingDeployBoard"
:is-empty="model.isEmptyDeployBoard"
+ :has-legacy-app-label="model.hasLegacyAppLabel"
:logs-path="model.logs_path"
/>
</div>
diff --git a/app/assets/javascripts/environments/index.js b/app/assets/javascripts/environments/index.js
index b53d42f202b..dcdaf8731f8 100644
--- a/app/assets/javascripts/environments/index.js
+++ b/app/assets/javascripts/environments/index.js
@@ -20,6 +20,7 @@ export default () =>
endpoint: environmentsData.environmentsDataEndpoint,
newEnvironmentPath: environmentsData.newEnvironmentPath,
helpPagePath: environmentsData.helpPagePath,
+ deployBoardsHelpPath: environmentsData.deployBoardsHelpPath,
cssContainerClass: environmentsData.cssClass,
canCreateEnvironment: parseBoolean(environmentsData.canCreateEnvironment),
canReadEnvironment: parseBoolean(environmentsData.canReadEnvironment),
@@ -31,6 +32,7 @@ export default () =>
endpoint: this.endpoint,
newEnvironmentPath: this.newEnvironmentPath,
helpPagePath: this.helpPagePath,
+ deployBoardsHelpPath: this.deployBoardsHelpPath,
cssContainerClass: this.cssContainerClass,
canCreateEnvironment: this.canCreateEnvironment,
canReadEnvironment: this.canReadEnvironment,
diff --git a/app/assets/javascripts/environments/mixins/container_mixin.js b/app/assets/javascripts/environments/mixins/container_mixin.js
index f2907c120f8..abf7d33be91 100644
--- a/app/assets/javascripts/environments/mixins/container_mixin.js
+++ b/app/assets/javascripts/environments/mixins/container_mixin.js
@@ -25,5 +25,10 @@ export default {
required: false,
default: null,
},
+ deployBoardsHelpPath: {
+ type: String,
+ required: false,
+ default: '',
+ },
},
};
diff --git a/app/assets/javascripts/gfm_auto_complete.js b/app/assets/javascripts/gfm_auto_complete.js
index 0af9aabd8cf..3b73dd83c9f 100644
--- a/app/assets/javascripts/gfm_auto_complete.js
+++ b/app/assets/javascripts/gfm_auto_complete.js
@@ -201,9 +201,7 @@ class GfmAutoComplete {
const autoCompleteAvatar = m.avatar_url || m.username.charAt(0).toUpperCase();
const rectAvatarClass = m.type === GROUP_TYPE ? 'rect-avatar' : '';
- const imgAvatar = `<img src="${m.avatar_url}" alt="${
- m.username
- }" class="avatar ${rectAvatarClass} avatar-inline center s26"/>`;
+ const imgAvatar = `<img src="${m.avatar_url}" alt="${m.username}" class="avatar ${rectAvatarClass} avatar-inline center s26"/>`;
const txtAvatar = `<div class="avatar ${rectAvatarClass} center avatar-inline s26">${autoCompleteAvatar}</div>`;
return {
diff --git a/app/assets/javascripts/groups/components/group_item.vue b/app/assets/javascripts/groups/components/group_item.vue
index d5130cd331d..9909f437fc8 100644
--- a/app/assets/javascripts/groups/components/group_item.vue
+++ b/app/assets/javascripts/groups/components/group_item.vue
@@ -1,12 +1,15 @@
<script>
+import { GlLoadingIcon } from '@gitlab/ui';
import { visitUrl } from '../../lib/utils/url_utility';
import tooltip from '../../vue_shared/directives/tooltip';
import identicon from '../../vue_shared/components/identicon.vue';
import eventHub from '../event_hub';
+import { VISIBILITY_TYPE_ICON, GROUP_VISIBILITY_TYPE } from '../constants';
import itemCaret from './item_caret.vue';
import itemTypeIcon from './item_type_icon.vue';
import itemStats from './item_stats.vue';
+import itemStatsValue from './item_stats_value.vue';
import itemActions from './item_actions.vue';
export default {
@@ -14,10 +17,12 @@ export default {
tooltip,
},
components: {
+ GlLoadingIcon,
identicon,
itemCaret,
itemTypeIcon,
itemStats,
+ itemStatsValue,
itemActions,
},
props: {
@@ -57,6 +62,12 @@ export default {
isGroup() {
return this.group.type === 'group';
},
+ visibilityIcon() {
+ return VISIBILITY_TYPE_ICON[this.group.visibility];
+ },
+ visibilityTooltip() {
+ return GROUP_VISIBILITY_TYPE[this.group.visibility];
+ },
},
methods: {
onClickRowGroup(e) {
@@ -80,43 +91,61 @@ export default {
<li :id="groupDomId" :class="rowClass" class="group-row" @click.stop="onClickRowGroup">
<div
:class="{ 'project-row-contents': !isGroup }"
- class="group-row-contents d-flex justify-content-end align-items-center"
+ class="group-row-contents d-flex align-items-center"
>
<div class="folder-toggle-wrap append-right-4 d-flex align-items-center">
<item-caret :is-group-open="group.isOpen" />
<item-type-icon :item-type="group.type" :is-group-open="group.isOpen" />
</div>
+ <gl-loading-icon
+ v-if="group.isChildrenLoading"
+ size="md"
+ class="d-none d-sm-inline-flex flex-shrink-0 append-right-10"
+ />
<div
- :class="{ 'content-loading': group.isChildrenLoading }"
- class="avatar-container rect-avatar s24 d-none d-sm-flex"
+ :class="{ 'd-sm-flex': !group.isChildrenLoading }"
+ class="avatar-container rect-avatar s32 d-none flex-grow-0 flex-shrink-0 "
>
<a :href="group.relativePath" class="no-expand">
- <img v-if="hasAvatar" :src="group.avatarUrl" class="avatar s24" />
- <identicon v-else :entity-id="group.id" :entity-name="group.name" size-class="s24" />
+ <img v-if="hasAvatar" :src="group.avatarUrl" class="avatar s32" />
+ <identicon v-else :entity-id="group.id" :entity-name="group.name" size-class="s32" />
</a>
</div>
- <div class="group-text flex-grow">
- <div class="title namespace-title append-right-8">
- <a
- v-tooltip
- :href="group.relativePath"
- :title="group.fullName"
- class="no-expand"
- data-placement="bottom"
- >{{
- // ending bracket must be by closing tag to prevent
- // link hover text-decoration from over-extending
- group.name
- }}</a
- >
- <span v-if="group.permission" class="user-access-role"> {{ group.permission }} </span>
+ <div class="group-text-container d-flex flex-fill align-items-center">
+ <div class="group-text flex-grow-1 flex-shrink-1">
+ <div class="d-flex align-items-center flex-wrap title namespace-title append-right-8">
+ <a
+ v-tooltip
+ :href="group.relativePath"
+ :title="group.fullName"
+ class="no-expand prepend-top-8 append-right-8"
+ data-placement="bottom"
+ >{{
+ // ending bracket must be by closing tag to prevent
+ // link hover text-decoration from over-extending
+ group.name
+ }}</a
+ >
+ <item-stats-value
+ :icon-name="visibilityIcon"
+ :title="visibilityTooltip"
+ css-class="item-visibility d-inline-flex align-items-center prepend-top-8 append-right-4"
+ />
+ <span v-if="group.permission" class="user-access-role prepend-top-8">
+ {{ group.permission }}
+ </span>
+ </div>
+ <div v-if="group.description" class="description">
+ <span v-html="group.description"> </span>
+ </div>
</div>
- <div v-if="group.description" class="description">
- <span v-html="group.description"> </span>
+ <div
+ class="metadata align-items-md-center d-flex flex-grow-1 flex-shrink-0 flex-wrap justify-content-md-between"
+ >
+ <item-actions v-if="isGroup" :group="group" :parent-group="parentGroup" />
+ <item-stats :item="group" class="group-stats prepend-top-2 d-none d-md-flex" />
</div>
</div>
- <item-stats :item="group" class="group-stats prepend-top-2" />
- <item-actions v-if="isGroup" :group="group" :parent-group="parentGroup" />
</div>
<group-folder
v-if="group.isOpen && hasChildren"
diff --git a/app/assets/javascripts/groups/components/item_actions.vue b/app/assets/javascripts/groups/components/item_actions.vue
index a7995865c77..cafd22731b1 100644
--- a/app/assets/javascripts/groups/components/item_actions.vue
+++ b/app/assets/javascripts/groups/components/item_actions.vue
@@ -44,31 +44,31 @@ export default {
</script>
<template>
- <div class="controls">
+ <div class="controls d-flex justify-content-end">
<a
- v-if="group.canEdit"
+ v-if="group.canLeave"
v-tooltip
- :href="group.editPath"
- :title="editBtnTitle"
- :aria-label="editBtnTitle"
+ :href="group.leavePath"
+ :title="leaveBtnTitle"
+ :aria-label="leaveBtnTitle"
data-container="body"
data-placement="bottom"
- class="edit-group btn no-expand"
+ class="leave-group btn btn-xs no-expand"
+ @click.prevent="onLeaveGroup"
>
- <icon name="settings" />
+ <icon name="leave" css-classes="position-top-0" />
</a>
<a
- v-if="group.canLeave"
+ v-if="group.canEdit"
v-tooltip
- :href="group.leavePath"
- :title="leaveBtnTitle"
- :aria-label="leaveBtnTitle"
+ :href="group.editPath"
+ :title="editBtnTitle"
+ :aria-label="editBtnTitle"
data-container="body"
data-placement="bottom"
- class="leave-group btn no-expand"
- @click.prevent="onLeaveGroup"
+ class="edit-group btn btn-xs no-expand"
>
- <icon name="leave" />
+ <icon name="settings" css-classes="position-top-0" />
</a>
</div>
</template>
diff --git a/app/assets/javascripts/groups/components/item_caret.vue b/app/assets/javascripts/groups/components/item_caret.vue
index 43b9607ea8e..18ea4819878 100644
--- a/app/assets/javascripts/groups/components/item_caret.vue
+++ b/app/assets/javascripts/groups/components/item_caret.vue
@@ -21,5 +21,5 @@ export default {
</script>
<template>
- <span class="folder-caret"> <icon :size="12" :name="iconClass" /> </span>
+ <span class="folder-caret append-right-4"> <icon :size="10" :name="iconClass" /> </span>
</template>
diff --git a/app/assets/javascripts/groups/components/item_stats.vue b/app/assets/javascripts/groups/components/item_stats.vue
index bc6851ea2bf..734a9a89c72 100644
--- a/app/assets/javascripts/groups/components/item_stats.vue
+++ b/app/assets/javascripts/groups/components/item_stats.vue
@@ -48,7 +48,7 @@ export default {
:title="__('Subgroups')"
:value="item.subgroupCount"
css-class="number-subgroups"
- icon-name="folder"
+ icon-name="folder-o"
/>
<item-stats-value
v-if="isGroup"
@@ -70,12 +70,6 @@ export default {
css-class="project-stars"
icon-name="star"
/>
- <item-stats-value
- :icon-name="visibilityIcon"
- :title="visibilityTooltip"
- css-class="item-visibility"
- tooltip-placement="left"
- />
<div v-if="isProject" class="last-updated">
<time-ago-tooltip :time="item.updatedAt" tooltip-placement="bottom" />
</div>
diff --git a/app/assets/javascripts/groups/components/item_type_icon.vue b/app/assets/javascripts/groups/components/item_type_icon.vue
index e1ebd03cb5f..ae69fbd7bde 100644
--- a/app/assets/javascripts/groups/components/item_type_icon.vue
+++ b/app/assets/javascripts/groups/components/item_type_icon.vue
@@ -20,7 +20,7 @@ export default {
computed: {
iconClass() {
if (this.itemType === ITEM_TYPE.GROUP) {
- return this.isGroupOpen ? 'folder-open' : 'folder';
+ return this.isGroupOpen ? 'folder-open' : 'folder-o';
}
return 'bookmark';
},
diff --git a/app/assets/javascripts/groups_select.js b/app/assets/javascripts/groups_select.js
index a1263d1cdab..f1cc6756583 100644
--- a/app/assets/javascripts/groups_select.js
+++ b/app/assets/javascripts/groups_select.js
@@ -77,9 +77,7 @@ export default function groupsSelect() {
}
},
formatResult(object) {
- return `<div class='group-result'> <div class='group-name'>${
- object.full_name
- }</div> <div class='group-path'>${object.full_path}</div> </div>`;
+ return `<div class='group-result'> <div class='group-name'>${object.full_name}</div> <div class='group-path'>${object.full_path}</div> </div>`;
},
formatSelection(object) {
return object.full_name;
diff --git a/app/assets/javascripts/ide/stores/modules/commit/actions.js b/app/assets/javascripts/ide/stores/modules/commit/actions.js
index ff1255ce749..01ca6a6b12f 100644
--- a/app/assets/javascripts/ide/stores/modules/commit/actions.js
+++ b/app/assets/javascripts/ide/stores/modules/commit/actions.js
@@ -63,9 +63,7 @@ export const setLastCommitMessage = ({ commit, rootGetters }, data) => {
const commitMsg = sprintf(
__('Your changes have been committed. Commit %{commitId} %{commitStats}'),
{
- commitId: `<a href="${currentProject.web_url}/commit/${data.short_id}" class="commit-sha">${
- data.short_id
- }</a>`,
+ commitId: `<a href="${currentProject.web_url}/commit/${data.short_id}" class="commit-sha">${data.short_id}</a>`,
commitStats,
},
false,
@@ -215,9 +213,7 @@ export const commitChanges = ({ commit, state, getters, dispatch, rootState, roo
if (rootGetters.activeFile) {
router.push(
- `/project/${rootState.currentProjectId}/blob/${getters.branchName}/-/${
- rootGetters.activeFile.path
- }`,
+ `/project/${rootState.currentProjectId}/blob/${getters.branchName}/-/${rootGetters.activeFile.path}`,
);
}
}
diff --git a/app/assets/javascripts/issue_show/components/edit_actions.vue b/app/assets/javascripts/issue_show/components/edit_actions.vue
index 42a3de62772..b2f9296c68b 100644
--- a/app/assets/javascripts/issue_show/components/edit_actions.vue
+++ b/app/assets/javascripts/issue_show/components/edit_actions.vue
@@ -73,7 +73,9 @@ export default {
Save changes
<i v-if="formState.updateLoading" class="fa fa-spinner fa-spin" aria-hidden="true"> </i>
</button>
- <button class="btn btn-default float-right" type="button" @click="closeForm">Cancel</button>
+ <button class="btn btn-default float-right" type="button" @click="closeForm">
+ {{ __('Cancel') }}
+ </button>
<button
v-if="shouldShowDeleteButton"
:class="{ disabled: deleteLoading }"
diff --git a/app/assets/javascripts/issue_show/components/fields/description.vue b/app/assets/javascripts/issue_show/components/fields/description.vue
index d27dd873125..447d7bf21a5 100644
--- a/app/assets/javascripts/issue_show/components/fields/description.vue
+++ b/app/assets/javascripts/issue_show/components/fields/description.vue
@@ -39,7 +39,7 @@ export default {
<template>
<div class="common-note-form">
- <label class="sr-only" for="issue-description"> Description </label>
+ <label class="sr-only" for="issue-description">{{ __('Description') }}</label>
<markdown-field
:markdown-preview-path="markdownPreviewPath"
:markdown-docs-path="markdownDocsPath"
@@ -55,8 +55,8 @@ export default {
qa-description-textarea"
dir="auto"
data-supports-quick-actions="false"
- aria-label="Description"
- placeholder="Write a comment or drag your files here…"
+ :aria-label="__('Description')"
+ :placeholder="__('Write a comment or drag your files here…')"
@keydown.meta.enter="updateIssuable"
@keydown.ctrl.enter="updateIssuable"
>
diff --git a/app/assets/javascripts/issue_show/components/fields/description_template.vue b/app/assets/javascripts/issue_show/components/fields/description_template.vue
index 14f0acf6540..6f955928d8e 100644
--- a/app/assets/javascripts/issue_show/components/fields/description_template.vue
+++ b/app/assets/javascripts/issue_show/components/fields/description_template.vue
@@ -56,22 +56,31 @@ export default {
data-selected="null"
data-toggle="dropdown"
>
- <span class="dropdown-toggle-text"> Choose a template </span>
+ <span class="dropdown-toggle-text">{{ __('Choose a template') }}</span>
<i aria-hidden="true" class="fa fa-chevron-down"> </i>
</button>
<div class="dropdown-menu dropdown-select">
<div class="dropdown-title">
Choose a template
- <button class="dropdown-title-button dropdown-menu-close" aria-label="Close" type="button">
+ <button
+ class="dropdown-title-button dropdown-menu-close"
+ :aria-label="__('Close')"
+ type="button"
+ >
<i aria-hidden="true" class="fa fa-times dropdown-menu-close-icon"> </i>
</button>
</div>
<div class="dropdown-input">
- <input type="search" class="dropdown-input-field" placeholder="Filter" autocomplete="off" />
+ <input
+ type="search"
+ class="dropdown-input-field"
+ :placeholder="__('Filter')"
+ autocomplete="off"
+ />
<i aria-hidden="true" class="fa fa-search dropdown-input-search"> </i>
<i
role="button"
- aria-label="Clear templates search input"
+ :aria-label="__('Clear templates search input')"
class="fa fa-times dropdown-input-clear js-dropdown-input-clear"
>
</i>
@@ -79,8 +88,12 @@ export default {
<div class="dropdown-content"></div>
<div class="dropdown-footer">
<ul class="dropdown-footer-list">
- <li><a class="no-template"> No template </a></li>
- <li><a class="reset-template"> Reset template </a></li>
+ <li>
+ <a class="no-template">{{ __('No template') }}</a>
+ </li>
+ <li>
+ <a class="reset-template">{{ __('Reset template') }}</a>
+ </li>
</ul>
</div>
</div>
diff --git a/app/assets/javascripts/issue_show/components/fields/title.vue b/app/assets/javascripts/issue_show/components/fields/title.vue
index ce4baf17d09..34eb0451d53 100644
--- a/app/assets/javascripts/issue_show/components/fields/title.vue
+++ b/app/assets/javascripts/issue_show/components/fields/title.vue
@@ -14,7 +14,7 @@ export default {
<template>
<fieldset>
- <label class="sr-only" for="issuable-title"> Title </label>
+ <label class="sr-only" for="issuable-title">{{ __('Title') }}</label>
<input
id="issuable-title"
ref="input"
@@ -22,8 +22,8 @@ export default {
class="form-control qa-title-input"
dir="auto"
type="text"
- placeholder="Title"
- aria-label="Title"
+ :placeholder="__('Title')"
+ :aria-label="__('Title')"
@keydown.meta.enter="updateIssuable"
@keydown.ctrl.enter="updateIssuable"
/>
diff --git a/app/assets/javascripts/issue_show/components/locked_warning.vue b/app/assets/javascripts/issue_show/components/locked_warning.vue
index 639221473b1..2f3e611e089 100644
--- a/app/assets/javascripts/issue_show/components/locked_warning.vue
+++ b/app/assets/javascripts/issue_show/components/locked_warning.vue
@@ -10,8 +10,9 @@ export default {
<template>
<div class="alert alert-danger">
- Someone edited the issue at the same time you did. Please check out
- <a :href="currentPath" target="_blank" rel="nofollow">the issue</a> and make sure your changes
- will not unintentionally remove theirs.
+ {{ sprintf(__("Someone edited the issue at the same time you did. Please check out
+ %{linkStart}%the issue%{linkEnd} and make sure your changes will not unintentionally remove
+ theirs."), { linkStart: `<a href="${currentPath}" target="_blank" rel="nofollow">` linkEnd: '</a
+ >', }) }}
</div>
</template>
diff --git a/app/assets/javascripts/jobs/components/environments_block.vue b/app/assets/javascripts/jobs/components/environments_block.vue
index f7fbb9503a0..132e50e5715 100644
--- a/app/assets/javascripts/jobs/components/environments_block.vue
+++ b/app/assets/javascripts/jobs/components/environments_block.vue
@@ -86,9 +86,7 @@ export default {
return sprintf(
'%{startLink}%{name}%{endLink}',
{
- startLink: `<a href="${
- this.deploymentStatus.environment.environment_path
- }" class="js-environment-link">`,
+ startLink: `<a href="${this.deploymentStatus.environment.environment_path}" class="js-environment-link">`,
name: _.escape(this.deploymentStatus.environment.name),
endLink: '</a>',
},
diff --git a/app/assets/javascripts/jobs/components/job_log_controllers.vue b/app/assets/javascripts/jobs/components/job_log_controllers.vue
index 607b2bd1c74..156735441ca 100644
--- a/app/assets/javascripts/jobs/components/job_log_controllers.vue
+++ b/app/assets/javascripts/jobs/components/job_log_controllers.vue
@@ -3,7 +3,7 @@ import { GlTooltipDirective, GlLink, GlButton } from '@gitlab/ui';
import { polyfillSticky } from '~/lib/utils/sticky';
import Icon from '~/vue_shared/components/icon.vue';
import { numberToHumanSize } from '~/lib/utils/number_utils';
-import { sprintf } from '~/locale';
+import { __, sprintf } from '~/locale';
import scrollDown from '../svg/scroll_down.svg';
export default {
@@ -50,7 +50,7 @@ export default {
},
computed: {
jobLogSize() {
- return sprintf('Showing last %{size} of log -', {
+ return sprintf(__('Showing last %{size} of log -'), {
size: numberToHumanSize(this.size),
});
},
@@ -74,14 +74,12 @@ export default {
<div class="js-truncated-info truncated-info d-none d-sm-block float-left">
<template v-if="isTraceSizeVisible">
{{ jobLogSize }}
-
<gl-link
v-if="rawPath"
:href="rawPath"
class="js-raw-link text-plain text-underline prepend-left-5"
+ >{{ s__('Job|Complete Raw') }}</gl-link
>
- {{ s__('Job|Complete Raw') }}
- </gl-link>
</template>
</div>
<!-- eo truncate information -->
diff --git a/app/assets/javascripts/jobs/components/sidebar.vue b/app/assets/javascripts/jobs/components/sidebar.vue
index 24276c06486..e9704584c9f 100644
--- a/app/assets/javascripts/jobs/components/sidebar.vue
+++ b/app/assets/javascripts/jobs/components/sidebar.vue
@@ -1,4 +1,5 @@
<script>
+import { __, sprintf } from '~/locale';
import _ from 'underscore';
import { mapActions, mapState } from 'vuex';
import { GlLink, GlButton } from '@gitlab/ui';
@@ -63,7 +64,9 @@ export default {
let t = this.job.metadata.timeout_human_readable;
if (this.job.metadata.timeout_source !== '') {
- t += ` (from ${this.job.metadata.timeout_source})`;
+ t += sprintf(__(` (from %{timeoutSource})`), {
+ timeoutSource: this.job.metadata.timeout_source,
+ });
}
return t;
diff --git a/app/assets/javascripts/lib/utils/datetime_utility.js b/app/assets/javascripts/lib/utils/datetime_utility.js
index d521c462ad8..062d21ed247 100644
--- a/app/assets/javascripts/lib/utils/datetime_utility.js
+++ b/app/assets/javascripts/lib/utils/datetime_utility.js
@@ -479,9 +479,13 @@ export const pikadayToString = date => {
* Seconds can be negative or positive, zero or non-zero. Can be configured for any day
* or week length.
*/
-export const parseSeconds = (seconds, { daysPerWeek = 5, hoursPerDay = 8 } = {}) => {
+export const parseSeconds = (
+ seconds,
+ { daysPerWeek = 5, hoursPerDay = 8, limitToHours = false } = {},
+) => {
const DAYS_PER_WEEK = daysPerWeek;
const HOURS_PER_DAY = hoursPerDay;
+ const SECONDS_PER_MINUTE = 60;
const MINUTES_PER_HOUR = 60;
const MINUTES_PER_WEEK = DAYS_PER_WEEK * HOURS_PER_DAY * MINUTES_PER_HOUR;
const MINUTES_PER_DAY = HOURS_PER_DAY * MINUTES_PER_HOUR;
@@ -493,9 +497,18 @@ export const parseSeconds = (seconds, { daysPerWeek = 5, hoursPerDay = 8 } = {})
minutes: 1,
};
- let unorderedMinutes = Math.abs(seconds / MINUTES_PER_HOUR);
+ if (limitToHours) {
+ timePeriodConstraints.weeks = 0;
+ timePeriodConstraints.days = 0;
+ }
+
+ let unorderedMinutes = Math.abs(seconds / SECONDS_PER_MINUTE);
return _.mapObject(timePeriodConstraints, minutesPerPeriod => {
+ if (minutesPerPeriod === 0) {
+ return 0;
+ }
+
const periodCount = Math.floor(unorderedMinutes / minutesPerPeriod);
unorderedMinutes -= periodCount * minutesPerPeriod;
diff --git a/app/assets/javascripts/monitoring/components/charts/area.vue b/app/assets/javascripts/monitoring/components/charts/area.vue
index 9de4e96e4da..9a3ce5174db 100644
--- a/app/assets/javascripts/monitoring/components/charts/area.vue
+++ b/app/assets/javascripts/monitoring/components/charts/area.vue
@@ -1,4 +1,5 @@
<script>
+import { __ } from '~/locale';
import { GlAreaChart, GlChartSeriesLabel } from '@gitlab/ui/dist/charts';
import dateFormat from 'dateformat';
import { debounceByAnimationFrame, roundOffFloat } from '~/lib/utils/common_utils';
@@ -99,7 +100,7 @@ export default {
chartOptions() {
return {
xAxis: {
- name: 'Time',
+ name: __('Time'),
type: 'time',
axisLabel: {
formatter: date => dateFormat(date, 'h:MM TT'),
diff --git a/app/assets/javascripts/monitoring/components/charts/column.vue b/app/assets/javascripts/monitoring/components/charts/column.vue
new file mode 100644
index 00000000000..05a2036f4c3
--- /dev/null
+++ b/app/assets/javascripts/monitoring/components/charts/column.vue
@@ -0,0 +1,131 @@
+<script>
+import { GlColumnChart } from '@gitlab/ui/dist/charts';
+import { debounceByAnimationFrame } from '~/lib/utils/common_utils';
+import { getSvgIconPathContent } from '~/lib/utils/icon_utils';
+import { chartHeight } from '../../constants';
+import { makeDataSeries } from '~/helpers/monitor_helper';
+
+export default {
+ components: {
+ GlColumnChart,
+ },
+ inheritAttrs: false,
+ props: {
+ graphData: {
+ type: Object,
+ required: true,
+ validator(data) {
+ return (
+ Array.isArray(data.queries) &&
+ data.queries.filter(query => {
+ if (Array.isArray(query.result)) {
+ return (
+ query.result.filter(res => Array.isArray(res.values)).length === query.result.length
+ );
+ }
+ return false;
+ }).length === data.queries.length
+ );
+ },
+ containerWidth: {
+ type: Number,
+ required: true,
+ },
+ },
+ },
+ data() {
+ return {
+ width: 0,
+ height: chartHeight,
+ svgs: {},
+ debouncedResizeCallback: {},
+ };
+ },
+ computed: {
+ chartData() {
+ const queryData = this.graphData.queries.reduce((acc, query) => {
+ const series = makeDataSeries(query.result, {
+ name: this.formatLegendLabel(query),
+ });
+
+ return acc.concat(series);
+ }, []);
+
+ return {
+ values: queryData[0].data,
+ };
+ },
+ xAxisTitle() {
+ return this.graphData.queries[0].result[0].x_label !== undefined
+ ? this.graphData.queries[0].result[0].x_label
+ : '';
+ },
+ yAxisTitle() {
+ return this.graphData.queries[0].result[0].y_label !== undefined
+ ? this.graphData.queries[0].result[0].y_label
+ : '';
+ },
+ xAxisType() {
+ return this.graphData.x_type !== undefined ? this.graphData.x_type : 'category';
+ },
+ dataZoomConfig() {
+ const handleIcon = this.svgs['scroll-handle'];
+
+ return handleIcon ? { handleIcon } : {};
+ },
+ chartOptions() {
+ return {
+ dataZoom: this.dataZoomConfig,
+ };
+ },
+ },
+ watch: {
+ containerWidth: 'onResize',
+ },
+ beforeDestroy() {
+ window.removeEventListener('resize', this.debouncedResizeCallback);
+ },
+ created() {
+ this.debouncedResizeCallback = debounceByAnimationFrame(this.onResize);
+ window.addEventListener('resize', this.debouncedResizeCallback);
+ this.setSvg('scroll-handle');
+ },
+ methods: {
+ formatLegendLabel(query) {
+ return `${query.label}`;
+ },
+ onResize() {
+ const { width } = this.$refs.columnChart.$el.getBoundingClientRect();
+ this.width = width;
+ },
+ setSvg(name) {
+ getSvgIconPathContent(name)
+ .then(path => {
+ if (path) {
+ this.$set(this.svgs, name, `path://${path}`);
+ }
+ })
+ .catch(() => {});
+ },
+ },
+};
+</script>
+<template>
+ <div class="prometheus-graph col-12 col-lg-6">
+ <div class="prometheus-graph-header">
+ <h5 ref="graphTitle" class="prometheus-graph-title">{{ graphData.title }}</h5>
+ <div ref="graphWidgets" class="prometheus-graph-widgets"><slot></slot></div>
+ </div>
+ <gl-column-chart
+ ref="columnChart"
+ v-bind="$attrs"
+ :data="chartData"
+ :option="chartOptions"
+ :width="width"
+ :height="height"
+ :x-axis-title="xAxisTitle"
+ :y-axis-title="yAxisTitle"
+ :x-axis-type="xAxisType"
+ />
+ </div>
+</template>
diff --git a/app/assets/javascripts/monitoring/components/empty_state.vue b/app/assets/javascripts/monitoring/components/empty_state.vue
index 0e141d02ead..a3c6de14aa4 100644
--- a/app/assets/javascripts/monitoring/components/empty_state.vue
+++ b/app/assets/javascripts/monitoring/components/empty_state.vue
@@ -1,4 +1,6 @@
<script>
+import { __ } from '~/locale';
+
export default {
props: {
documentationPath: {
@@ -41,35 +43,35 @@ export default {
states: {
gettingStarted: {
svgUrl: this.emptyGettingStartedSvgPath,
- title: 'Get started with performance monitoring',
- description: `Stay updated about the performance and health
- of your environment by configuring Prometheus to monitor your deployments.`,
- buttonText: 'Install on clusters',
+ title: __('Get started with performance monitoring'),
+ description: __(`Stay updated about the performance and health
+ of your environment by configuring Prometheus to monitor your deployments.`),
+ buttonText: __('Install on clusters'),
buttonPath: this.clustersPath,
- secondaryButtonText: 'Configure existing installation',
+ secondaryButtonText: __('Configure existing installation'),
secondaryButtonPath: this.settingsPath,
},
loading: {
svgUrl: this.emptyLoadingSvgPath,
- title: 'Waiting for performance data',
- description: `Creating graphs uses the data from the Prometheus server.
- If this takes a long time, ensure that data is available.`,
- buttonText: 'View documentation',
+ title: __('Waiting for performance data'),
+ description: __(`Creating graphs uses the data from the Prometheus server.
+ If this takes a long time, ensure that data is available.`),
+ buttonText: __('View documentation'),
buttonPath: this.documentationPath,
},
noData: {
svgUrl: this.emptyNoDataSvgPath,
- title: 'No data found',
- description: `You are connected to the Prometheus server, but there is currently
- no data to display.`,
- buttonText: 'Configure Prometheus',
+ title: __('No data found'),
+ description: __(`You are connected to the Prometheus server, but there is currently
+ no data to display.`),
+ buttonText: __('Configure Prometheus'),
buttonPath: this.settingsPath,
},
unableToConnect: {
svgUrl: this.emptyUnableToConnectSvgPath,
- title: 'Unable to connect to Prometheus server',
+ title: __('Unable to connect to Prometheus server'),
description: 'Ensure connectivity is available from the GitLab server to the ',
- buttonText: 'View documentation',
+ buttonText: __('View documentation'),
buttonPath: this.documentationPath,
},
},
@@ -90,7 +92,9 @@ export default {
<template>
<div class="row empty-state js-empty-state">
<div class="col-12">
- <div class="state-svg svg-content"><img :src="currentState.svgUrl" /></div>
+ <div class="state-svg svg-content">
+ <img :src="currentState.svgUrl" />
+ </div>
</div>
<div class="col-12">
@@ -98,20 +102,22 @@ export default {
<h4 class="state-title text-center">{{ currentState.title }}</h4>
<p class="state-description">
{{ currentState.description }}
- <a v-if="showButtonDescription" :href="settingsPath"> Prometheus server </a>
+ <a v-if="showButtonDescription" :href="settingsPath">{{ __('Prometheus server') }}</a>
</p>
<div class="text-center">
- <a v-if="currentState.buttonPath" :href="currentState.buttonPath" class="btn btn-success">
- {{ currentState.buttonText }}
- </a>
+ <a
+ v-if="currentState.buttonPath"
+ :href="currentState.buttonPath"
+ class="btn btn-success"
+ >{{ currentState.buttonText }}</a
+ >
<a
v-if="currentState.secondaryButtonPath"
:href="currentState.secondaryButtonPath"
class="btn"
+ >{{ currentState.secondaryButtonText }}</a
>
- {{ currentState.secondaryButtonText }}
- </a>
</div>
</div>
</div>
diff --git a/app/assets/javascripts/notes.js b/app/assets/javascripts/notes.js
index a7156bd2406..9cc31e26648 100644
--- a/app/assets/javascripts/notes.js
+++ b/app/assets/javascripts/notes.js
@@ -1284,9 +1284,7 @@ export default class Notes {
putConflictEditWarningInPlace(noteEntity, $note) {
if ($note.find('.js-conflict-edit-warning').length === 0) {
- const open_link = `<a href="#note_${
- noteEntity.id
- }" target="_blank" rel="noopener noreferrer">`;
+ const open_link = `<a href="#note_${noteEntity.id}" target="_blank" rel="noopener noreferrer">`;
const $alert = $(`<div class="js-conflict-edit-warning alert alert-danger">
${sprintf(
s__(
diff --git a/app/assets/javascripts/notes/components/diff_with_note.vue b/app/assets/javascripts/notes/components/diff_with_note.vue
index b95835ed10a..54c242b2fda 100644
--- a/app/assets/javascripts/notes/components/diff_with_note.vue
+++ b/app/assets/javascripts/notes/components/diff_with_note.vue
@@ -7,6 +7,8 @@ import { GlSkeletonLoading } from '@gitlab/ui';
import { getDiffMode } from '~/diffs/store/utils';
import { diffViewerModes } from '~/ide/constants';
+const FIRST_CHAR_REGEX = /^(\+|-| )/;
+
export default {
components: {
DiffFileHeader,
@@ -59,6 +61,9 @@ export default {
this.error = true;
});
},
+ trimChar(line) {
+ return line.replace(FIRST_CHAR_REGEX, '');
+ },
},
userColorSchemeClass: window.gon.user_color_scheme,
};
@@ -83,7 +88,7 @@ export default {
>
<td :class="line.type" class="diff-line-num old_line">{{ line.old_line }}</td>
<td :class="line.type" class="diff-line-num new_line">{{ line.new_line }}</td>
- <td :class="line.type" class="line_content" v-html="line.rich_text"></td>
+ <td :class="line.type" class="line_content" v-html="trimChar(line.rich_text)"></td>
</tr>
</template>
<tr v-if="!hasTruncatedDiffLines" class="line_holder line-holder-placeholder">
diff --git a/app/assets/javascripts/notes/components/noteable_discussion.vue b/app/assets/javascripts/notes/components/noteable_discussion.vue
index eb6a4a67fff..10b15a9c38c 100644
--- a/app/assets/javascripts/notes/components/noteable_discussion.vue
+++ b/app/assets/javascripts/notes/components/noteable_discussion.vue
@@ -382,7 +382,7 @@ Please check your network connection and try again.`;
class="discussion-reply-holder"
>
<user-avatar-link
- v-if="!isReplying && currentUser"
+ v-if="!isReplying && userCanReply"
:link-href="currentUser.path"
:img-src="currentUser.avatar_url"
:img-alt="currentUser.name"
diff --git a/app/assets/javascripts/pages/profiles/two_factor_auths/index.js b/app/assets/javascripts/pages/profiles/two_factor_auths/index.js
index 10cd8ecfbc9..820f0f7f12d 100644
--- a/app/assets/javascripts/pages/profiles/two_factor_auths/index.js
+++ b/app/assets/javascripts/pages/profiles/two_factor_auths/index.js
@@ -6,9 +6,7 @@ document.addEventListener('DOMContentLoaded', () => {
const twoFactorNode = document.querySelector('.js-two-factor-auth');
const skippable = parseBoolean(twoFactorNode.dataset.twoFactorSkippable);
if (skippable) {
- const button = `<a class="btn btn-sm btn-warning float-right" data-method="patch" href="${
- twoFactorNode.dataset.two_factor_skip_url
- }">Configure it later</a>`;
+ const button = `<a class="btn btn-sm btn-warning float-right" data-method="patch" href="${twoFactorNode.dataset.two_factor_skip_url}">Configure it later</a>`;
const flashAlert = document.querySelector('.flash-alert .container-fluid');
if (flashAlert) flashAlert.insertAdjacentHTML('beforeend', button);
}
diff --git a/app/assets/javascripts/pages/projects/branches/index/index.js b/app/assets/javascripts/pages/projects/branches/index/index.js
index 8fa266a37ce..29de3b7806c 100644
--- a/app/assets/javascripts/pages/projects/branches/index/index.js
+++ b/app/assets/javascripts/pages/projects/branches/index/index.js
@@ -1,7 +1,9 @@
import AjaxLoadingSpinner from '~/ajax_loading_spinner';
import DeleteModal from '~/branches/branches_delete_modal';
+import initDiverganceGraph from '~/branches/divergence_graph';
document.addEventListener('DOMContentLoaded', () => {
AjaxLoadingSpinner.init();
new DeleteModal(); // eslint-disable-line no-new
+ initDiverganceGraph();
});
diff --git a/app/assets/javascripts/pages/projects/pages_domains/form.js b/app/assets/javascripts/pages/projects/pages_domains/form.js
index 1d0dbfe0406..cef8e92610c 100644
--- a/app/assets/javascripts/pages/projects/pages_domains/form.js
+++ b/app/assets/javascripts/pages/projects/pages_domains/form.js
@@ -5,14 +5,6 @@ export default () => {
if (toggleContainer) {
const onToggleButtonClicked = isAutoSslEnabled => {
- Array.from(document.querySelectorAll('.js-shown-if-auto-ssl')).forEach(el => {
- if (isAutoSslEnabled) {
- el.classList.remove('d-none');
- } else {
- el.classList.add('d-none');
- }
- });
-
Array.from(document.querySelectorAll('.js-shown-unless-auto-ssl')).forEach(el => {
if (isAutoSslEnabled) {
el.classList.add('d-none');
@@ -21,14 +13,6 @@ export default () => {
}
});
- Array.from(document.querySelectorAll('.js-enabled-if-auto-ssl')).forEach(el => {
- if (isAutoSslEnabled) {
- el.removeAttribute('disabled');
- } else {
- el.setAttribute('disabled', 'disabled');
- }
- });
-
Array.from(document.querySelectorAll('.js-enabled-unless-auto-ssl')).forEach(el => {
if (isAutoSslEnabled) {
el.setAttribute('disabled', 'disabled');
diff --git a/app/assets/javascripts/pipelines/components/pipeline_url.vue b/app/assets/javascripts/pipelines/components/pipeline_url.vue
index c41ecab1294..65a2b61396c 100644
--- a/app/assets/javascripts/pipelines/components/pipeline_url.vue
+++ b/app/assets/javascripts/pipelines/components/pipeline_url.vue
@@ -60,7 +60,7 @@ export default {
</script>
<template>
<div class="table-section section-10 d-none d-sm-none d-md-block pipeline-tags">
- <gl-link :href="pipeline.path" class="js-pipeline-url-link">
+ <gl-link :href="pipeline.path" class="js-pipeline-url-link js-onboarding-pipeline-item">
<span class="pipeline-id">#{{ pipeline.id }}</span>
</gl-link>
<div class="label-container">
diff --git a/app/assets/javascripts/registry/components/app.vue b/app/assets/javascripts/registry/components/app.vue
index 9af5660f764..ee973017387 100644
--- a/app/assets/javascripts/registry/components/app.vue
+++ b/app/assets/javascripts/registry/components/app.vue
@@ -33,7 +33,7 @@ export default {
</script>
<template>
<div>
- <gl-loading-icon v-if="isLoading" :size="3" />
+ <gl-loading-icon v-if="isLoading" size="md" />
<collapsible-container
v-for="item in repos"
@@ -45,7 +45,7 @@ export default {
<p v-else-if="!isLoading && !repos.length">
{{
__(`No container images stored for this project.
-Add one by following the instructions above.`)
+ Add one by following the instructions above.`)
}}
</p>
</div>
diff --git a/app/assets/javascripts/registry/components/collapsible_container.vue b/app/assets/javascripts/registry/components/collapsible_container.vue
index 5451c61026c..1e266dd4ced 100644
--- a/app/assets/javascripts/registry/components/collapsible_container.vue
+++ b/app/assets/javascripts/registry/components/collapsible_container.vue
@@ -1,6 +1,6 @@
<script>
import { mapActions } from 'vuex';
-import { GlLoadingIcon, GlButton, GlTooltipDirective } from '@gitlab/ui';
+import { GlLoadingIcon, GlButton, GlTooltipDirective, GlModal, GlModalDirective } from '@gitlab/ui';
import createFlash from '../../flash';
import ClipboardButton from '../../vue_shared/components/clipboard_button.vue';
import Icon from '../../vue_shared/components/icon.vue';
@@ -16,9 +16,11 @@ export default {
GlLoadingIcon,
GlButton,
Icon,
+ GlModal,
},
directives: {
GlTooltip: GlTooltipDirective,
+ GlModal: GlModalDirective,
},
props: {
repo: {
@@ -37,7 +39,7 @@ export default {
},
},
methods: {
- ...mapActions(['fetchRepos', 'fetchList', 'deleteRepo']),
+ ...mapActions(['fetchRepos', 'fetchList', 'deleteItem']),
toggleRepo() {
this.isOpen = !this.isOpen;
@@ -46,7 +48,7 @@ export default {
}
},
handleDeleteRepository() {
- this.deleteRepo(this.repo)
+ this.deleteItem(this.repo)
.then(() => {
createFlash(__('This container registry has been scheduled for deletion.'), 'notice');
this.fetchRepos();
@@ -78,18 +80,18 @@ export default {
<gl-button
v-if="repo.canDelete"
v-gl-tooltip
+ v-gl-modal="'confirm-repo-deletion-modal'"
:title="s__('ContainerRegistry|Remove repository')"
:aria-label="s__('ContainerRegistry|Remove repository')"
class="js-remove-repo"
variant="danger"
- @click="handleDeleteRepository"
>
<icon name="remove" />
</gl-button>
</div>
</div>
- <gl-loading-icon v-if="repo.isLoading" :size="2" class="append-bottom-20" />
+ <gl-loading-icon v-if="repo.isLoading" size="md" class="append-bottom-20" />
<div v-else-if="!repo.isLoading && isOpen" class="container-image-tags">
<table-registry v-if="repo.list.length" :repo="repo" />
@@ -98,5 +100,24 @@ export default {
{{ s__('ContainerRegistry|No tags in Container Registry for this container image.') }}
</div>
</div>
+
+ <gl-modal
+ modal-id="confirm-repo-deletion-modal"
+ ok-variant="danger"
+ @ok="handleDeleteRepository"
+ >
+ <template v-slot:modal-title>{{ s__('ContainerRegistry|Remove repository') }}</template>
+ <p
+ v-html="
+ sprintf(
+ s__(
+ 'ContainerRegistry|You are about to remove repository <b>%{title}</b>. Once you confirm, this repository will be permanently deleted.',
+ ),
+ { title: repo.name },
+ )
+ "
+ ></p>
+ <template v-slot:modal-ok>{{ __('Remove') }}</template>
+ </gl-modal>
</div>
</template>
diff --git a/app/assets/javascripts/registry/components/table_registry.vue b/app/assets/javascripts/registry/components/table_registry.vue
index f535b2ae9f2..0ec5e2c7a87 100644
--- a/app/assets/javascripts/registry/components/table_registry.vue
+++ b/app/assets/javascripts/registry/components/table_registry.vue
@@ -1,6 +1,6 @@
<script>
import { mapActions } from 'vuex';
-import { GlButton, GlTooltipDirective } from '@gitlab/ui';
+import { GlButton, GlTooltipDirective, GlModal, GlModalDirective } from '@gitlab/ui';
import { n__ } from '../../locale';
import createFlash from '../../flash';
import ClipboardButton from '../../vue_shared/components/clipboard_button.vue';
@@ -16,9 +16,11 @@ export default {
TablePagination,
GlButton,
Icon,
+ GlModal,
},
directives: {
GlTooltip: GlTooltipDirective,
+ GlModal: GlModalDirective,
},
mixins: [timeagoMixin],
props: {
@@ -27,21 +29,31 @@ export default {
required: true,
},
},
+ data() {
+ return {
+ itemToBeDeleted: null,
+ };
+ },
computed: {
shouldRenderPagination() {
return this.repo.pagination.total > this.repo.pagination.perPage;
},
},
methods: {
- ...mapActions(['fetchList', 'deleteRegistry']),
+ ...mapActions(['fetchList', 'deleteItem']),
layers(item) {
return item.layers ? n__('%d layer', '%d layers', item.layers) : '';
},
formatSize(size) {
return numberToHumanSize(size);
},
- handleDeleteRegistry(registry) {
- this.deleteRegistry(registry)
+ setItemToBeDeleted(item) {
+ this.itemToBeDeleted = item;
+ },
+ handleDeleteRegistry() {
+ const { itemToBeDeleted } = this;
+ this.itemToBeDeleted = null;
+ this.deleteItem(itemToBeDeleted)
.then(() => this.fetchList({ repo: this.repo }))
.catch(() => this.showError(errorMessagesTypes.DELETE_REGISTRY));
},
@@ -80,9 +92,9 @@ export default {
/>
</td>
<td>
- <span v-gl-tooltip.bottom class="monospace" :title="item.revision">{{
- item.shortRevision
- }}</span>
+ <span v-gl-tooltip.bottom class="monospace" :title="item.revision">
+ {{ item.shortRevision }}
+ </span>
</td>
<td>
{{ formatSize(item.size) }}
@@ -93,20 +105,21 @@ export default {
</td>
<td>
- <span v-gl-tooltip.bottom :title="tooltipTitle(item.createdAt)">{{
- timeFormated(item.createdAt)
- }}</span>
+ <span v-gl-tooltip.bottom :title="tooltipTitle(item.createdAt)">
+ {{ timeFormated(item.createdAt) }}
+ </span>
</td>
<td class="content">
<gl-button
v-if="item.canDelete"
v-gl-tooltip
- :title="s__('ContainerRegistry|Remove tag')"
- :aria-label="s__('ContainerRegistry|Remove tag')"
+ v-gl-modal="'confirm-image-deletion-modal'"
+ :title="s__('ContainerRegistry|Remove image')"
+ :aria-label="s__('ContainerRegistry|Remove image')"
variant="danger"
class="js-delete-registry d-none d-sm-block float-right"
- @click="handleDeleteRegistry(item)"
+ @click="setItemToBeDeleted(item)"
>
<icon name="remove" />
</gl-button>
@@ -120,5 +133,24 @@ export default {
:change="onPageChange"
:page-info="repo.pagination"
/>
+
+ <gl-modal
+ modal-id="confirm-image-deletion-modal"
+ ok-variant="danger"
+ @ok="handleDeleteRegistry"
+ >
+ <template v-slot:modal-title>{{ s__('ContainerRegistry|Remove image') }}</template>
+ <template v-slot:modal-ok>{{ s__('ContainerRegistry|Remove image and tags') }}</template>
+ <p
+ v-html="
+ sprintf(
+ s__(
+ 'ContainerRegistry|You are about to delete the image <b>%{title}</b>. This will delete the image and all tags pointing to this image.',
+ ),
+ { title: repo.name },
+ )
+ "
+ ></p>
+ </gl-modal>
</div>
</template>
diff --git a/app/assets/javascripts/registry/stores/actions.js b/app/assets/javascripts/registry/stores/actions.js
index 51d057c62c1..0f5e9cc73a0 100644
--- a/app/assets/javascripts/registry/stores/actions.js
+++ b/app/assets/javascripts/registry/stores/actions.js
@@ -35,11 +35,7 @@ export const fetchList = ({ commit }, { repo, page }) => {
});
};
-// eslint-disable-next-line no-unused-vars
-export const deleteRepo = ({ commit }, repo) => axios.delete(repo.destroyPath);
-
-// eslint-disable-next-line no-unused-vars
-export const deleteRegistry = ({ commit }, image) => axios.delete(image.destroyPath);
+export const deleteItem = (_, item) => axios.delete(item.destroyPath);
export const setMainEndpoint = ({ commit }, data) => commit(types.SET_MAIN_ENDPOINT, data);
export const toggleLoading = ({ commit }) => commit(types.TOGGLE_MAIN_LOADING);
diff --git a/app/assets/javascripts/releases/components/release_block.vue b/app/assets/javascripts/releases/components/release_block.vue
index 0958b9fa926..f510b905a2e 100644
--- a/app/assets/javascripts/releases/components/release_block.vue
+++ b/app/assets/javascripts/releases/components/release_block.vue
@@ -1,6 +1,6 @@
<script>
import _ from 'underscore';
-import { GlTooltipDirective, GlLink } from '@gitlab/ui';
+import { GlTooltipDirective, GlLink, GlBadge } from '@gitlab/ui';
import Icon from '~/vue_shared/components/icon.vue';
import UserAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue';
import timeagoMixin from '~/vue_shared/mixins/timeago';
@@ -10,6 +10,7 @@ export default {
name: 'ReleaseBlock',
components: {
GlLink,
+ GlBadge,
Icon,
UserAvatarLink,
},
@@ -53,7 +54,12 @@ export default {
<template>
<div class="card">
<div class="card-body">
- <h2 class="card-title mt-0">{{ release.name }}</h2>
+ <h2 class="card-title mt-0">
+ {{ release.name }}
+ <gl-badge v-if="release.pre_release" variant="warning" class="align-middle">{{
+ __('Pre-release')
+ }}</gl-badge>
+ </h2>
<div class="card-subtitle d-flex flex-wrap text-secondary">
<div class="append-right-8">
@@ -68,9 +74,9 @@ export default {
<div class="append-right-4">
&bull;
- <span v-gl-tooltip.bottom :title="tooltipTitle(release.created_at)">{{
- releasedTimeAgo
- }}</span>
+ <span v-gl-tooltip.bottom :title="tooltipTitle(release.created_at)">
+ {{ releasedTimeAgo }}
+ </span>
</div>
<div v-if="hasAuthor" class="d-flex">
@@ -98,7 +104,8 @@ export default {
<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 align-text-bottom" />
- {{ link.name }} <span v-if="link.external"> {{ __('(external source)') }}</span>
+ {{ link.name }}
+ <span v-if="link.external">{{ __('(external source)') }}</span>
</gl-link>
</li>
</ul>
@@ -111,7 +118,8 @@ export default {
aria-haspopup="true"
aria-expanded="false"
>
- <icon name="doc-code" class="align-top append-right-4" /> {{ __('Source code') }}
+ <icon name="doc-code" class="align-top append-right-4" />
+ {{ __('Source code') }}
<icon name="arrow-down" />
</button>
@@ -123,7 +131,9 @@ export default {
</div>
</div>
- <div class="card-text prepend-top-default"><div v-html="release.description_html"></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/sidebar/components/time_tracking/comparison_pane.vue b/app/assets/javascripts/sidebar/components/time_tracking/comparison_pane.vue
index f4d926cd3ec..13955529cab 100644
--- a/app/assets/javascripts/sidebar/components/time_tracking/comparison_pane.vue
+++ b/app/assets/javascripts/sidebar/components/time_tracking/comparison_pane.vue
@@ -28,11 +28,16 @@ export default {
type: String,
required: true,
},
+ limitToHours: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
},
computed: {
parsedTimeRemaining() {
const diffSeconds = this.timeEstimate - this.timeSpent;
- return parseSeconds(diffSeconds);
+ return parseSeconds(diffSeconds, { limitToHours: this.limitToHours });
},
timeRemainingHumanReadable() {
return stringifyTime(this.parsedTimeRemaining);
diff --git a/app/assets/javascripts/sidebar/components/time_tracking/sidebar_time_tracking.vue b/app/assets/javascripts/sidebar/components/time_tracking/sidebar_time_tracking.vue
index 8e8b9f19b6e..018b30d2a67 100644
--- a/app/assets/javascripts/sidebar/components/time_tracking/sidebar_time_tracking.vue
+++ b/app/assets/javascripts/sidebar/components/time_tracking/sidebar_time_tracking.vue
@@ -53,6 +53,7 @@ export default {
:time-spent="store.totalTimeSpent"
:human-time-estimate="store.humanTimeEstimate"
:human-time-spent="store.humanTotalTimeSpent"
+ :limit-to-hours="store.timeTrackingLimitToHours"
:root-path="store.rootPath"
/>
</div>
diff --git a/app/assets/javascripts/sidebar/components/time_tracking/time_tracker.vue b/app/assets/javascripts/sidebar/components/time_tracking/time_tracker.vue
index d84d5344935..682ca600b6a 100644
--- a/app/assets/javascripts/sidebar/components/time_tracking/time_tracker.vue
+++ b/app/assets/javascripts/sidebar/components/time_tracking/time_tracker.vue
@@ -37,6 +37,10 @@ export default {
required: false,
default: '',
},
+ limitToHours: {
+ type: Boolean,
+ default: false,
+ },
rootPath: {
type: String,
required: true,
@@ -129,6 +133,7 @@ export default {
:time-spent="timeSpent"
:time-spent-human-readable="humanTimeSpent"
:time-estimate-human-readable="humanTimeEstimate"
+ :limit-to-hours="limitToHours"
/>
<transition name="help-state-toggle">
<time-tracking-help-state v-if="showHelpState" :root-path="rootPath" />
diff --git a/app/assets/javascripts/sidebar/mount_milestone_sidebar.js b/app/assets/javascripts/sidebar/mount_milestone_sidebar.js
index 1ebdbec7bc9..d934463382f 100644
--- a/app/assets/javascripts/sidebar/mount_milestone_sidebar.js
+++ b/app/assets/javascripts/sidebar/mount_milestone_sidebar.js
@@ -1,5 +1,6 @@
import Vue from 'vue';
import timeTracker from './components/time_tracking/time_tracker.vue';
+import { parseBoolean } from '~/lib/utils/common_utils';
export default class SidebarMilestone {
constructor() {
@@ -7,7 +8,7 @@ export default class SidebarMilestone {
if (!el) return;
- const { timeEstimate, timeSpent, humanTimeEstimate, humanTimeSpent } = el.dataset;
+ const { timeEstimate, timeSpent, humanTimeEstimate, humanTimeSpent, limitToHours } = el.dataset;
// eslint-disable-next-line no-new
new Vue({
@@ -22,6 +23,7 @@ export default class SidebarMilestone {
timeSpent: parseInt(timeSpent, 10),
humanTimeEstimate,
humanTimeSpent,
+ limitToHours: parseBoolean(limitToHours),
rootPath: '/',
},
}),
diff --git a/app/assets/javascripts/sidebar/stores/sidebar_store.js b/app/assets/javascripts/sidebar/stores/sidebar_store.js
index 7b8b4c5d856..63c4a2a3f84 100644
--- a/app/assets/javascripts/sidebar/stores/sidebar_store.js
+++ b/app/assets/javascripts/sidebar/stores/sidebar_store.js
@@ -8,7 +8,7 @@ export default class SidebarStore {
}
initSingleton(options) {
- const { currentUser, rootPath, editable } = options;
+ const { currentUser, rootPath, editable, timeTrackingLimitToHours } = options;
this.currentUser = currentUser;
this.rootPath = rootPath;
this.editable = editable;
@@ -16,6 +16,7 @@ export default class SidebarStore {
this.totalTimeSpent = 0;
this.humanTimeEstimate = '';
this.humanTimeSpent = '';
+ this.timeTrackingLimitToHours = timeTrackingLimitToHours;
this.assignees = [];
this.isFetching = {
assignees: true,
diff --git a/app/assets/javascripts/vue_shared/components/modal_copy_button.vue b/app/assets/javascripts/vue_shared/components/modal_copy_button.vue
index bf59a6abf3f..edbeab9c600 100644
--- a/app/assets/javascripts/vue_shared/components/modal_copy_button.vue
+++ b/app/assets/javascripts/vue_shared/components/modal_copy_button.vue
@@ -26,6 +26,11 @@ export default {
required: false,
default: '',
},
+ cssClasses: {
+ type: String,
+ required: false,
+ default: '',
+ },
modalId: {
type: String,
required: false,
@@ -110,6 +115,7 @@ export default {
<template>
<gl-button
v-gl-tooltip="{ placement: tooltipPlacement, container: tooltipContainer }"
+ :class="cssClasses"
:data-clipboard-target="target"
:data-clipboard-text="text"
:title="title"
diff --git a/app/assets/javascripts/vue_shared/components/paginated_list.vue b/app/assets/javascripts/vue_shared/components/paginated_list.vue
new file mode 100644
index 00000000000..e19b8510399
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/paginated_list.vue
@@ -0,0 +1,35 @@
+<script>
+import { GlPaginatedList } from '@gitlab/ui';
+import { PREV, NEXT } from '~/vue_shared/components/pagination/constants';
+
+export default {
+ components: {
+ GlPaginatedList,
+ },
+ labels: {
+ prev: PREV,
+ next: NEXT,
+ },
+};
+</script>
+
+<template>
+ <gl-paginated-list
+ v-bind="$attrs"
+ :prev-text="$options.labels.prev"
+ :next-text="$options.labels.next"
+ >
+ <!-- proxy the slots -->
+ <template #header>
+ <slot name="header"></slot>
+ </template>
+
+ <template #subheader>
+ <slot name="subheader"></slot>
+ </template>
+
+ <template #default="{ listItem, query }">
+ <slot :listItem="listItem" :query="query"></slot>
+ </template>
+ </gl-paginated-list>
+</template>
diff --git a/app/assets/javascripts/vue_shared/components/pagination/constants.js b/app/assets/javascripts/vue_shared/components/pagination/constants.js
index 748ad178c70..229132c0e33 100644
--- a/app/assets/javascripts/vue_shared/components/pagination/constants.js
+++ b/app/assets/javascripts/vue_shared/components/pagination/constants.js
@@ -3,8 +3,8 @@ import { s__ } from '~/locale';
export const PAGINATION_UI_BUTTON_LIMIT = 4;
export const UI_LIMIT = 6;
export const SPREAD = '...';
-export const PREV = s__('Pagination|Prev');
-export const NEXT = s__('Pagination|Next');
+export const PREV = s__('Pagination|‹ Prev');
+export const NEXT = s__('Pagination|Next ›');
export const FIRST = s__('Pagination|« First');
export const LAST = s__('Pagination|Last »');
export const LABEL_FIRST_PAGE = s__('Pagination|Go to first page');
diff --git a/app/assets/javascripts/vue_shared/components/project_avatar/image.vue b/app/assets/javascripts/vue_shared/components/project_avatar/image.vue
index e77b9ddc7ba..b9311d65360 100644
--- a/app/assets/javascripts/vue_shared/components/project_avatar/image.vue
+++ b/app/assets/javascripts/vue_shared/components/project_avatar/image.vue
@@ -17,13 +17,9 @@
import defaultAvatarUrl from 'images/no_avatar.png';
import { placeholderImage } from '../../../lazy_loader';
-import tooltip from '../../directives/tooltip';
export default {
name: 'ProjectAvatarImage',
- directives: {
- tooltip,
- },
props: {
lazy: {
type: Boolean,
@@ -50,16 +46,6 @@ export default {
required: false,
default: 20,
},
- tooltipText: {
- type: String,
- required: false,
- default: '',
- },
- tooltipPlacement: {
- type: String,
- required: false,
- default: 'top',
- },
},
computed: {
// API response sends null when gravatar is disabled and
@@ -71,9 +57,6 @@ export default {
resultantSrcAttribute() {
return this.lazy ? placeholderImage : this.sanitizedSource;
},
- tooltipContainer() {
- return this.tooltipText ? 'body' : null;
- },
avatarSizeClass() {
return `s${this.size}`;
},
@@ -83,7 +66,6 @@ export default {
<template>
<img
- v-tooltip
:class="{
lazy: lazy,
[avatarSizeClass]: true,
@@ -94,9 +76,6 @@ export default {
:height="size"
:alt="imgAlt"
:data-src="sanitizedSource"
- :data-container="tooltipContainer"
- :data-placement="tooltipPlacement"
- :title="tooltipText"
class="avatar"
/>
</template>
diff --git a/app/assets/stylesheets/components/popover.scss b/app/assets/stylesheets/components/popover.scss
index 58aaca93160..8c40c4adb5c 100644
--- a/app/assets/stylesheets/components/popover.scss
+++ b/app/assets/stylesheets/components/popover.scss
@@ -135,11 +135,5 @@
.popover {
min-width: auto;
max-width: 40%;
-
- .popover-body {
- padding-top: $gl-padding;
- padding-bottom: $gl-padding;
- font-size: $gl-font-size-small;
- }
}
}
diff --git a/app/assets/stylesheets/framework/lists.scss b/app/assets/stylesheets/framework/lists.scss
index 555a3fe0dc7..954551fef97 100644
--- a/app/assets/stylesheets/framework/lists.scss
+++ b/app/assets/stylesheets/framework/lists.scss
@@ -133,7 +133,6 @@ ul.content-list {
.description {
@include str-truncated;
- color: $gl-text-color-secondary;
}
.controls {
diff --git a/app/assets/stylesheets/framework/mixins.scss b/app/assets/stylesheets/framework/mixins.scss
index ad5096761cd..bf0f1da6aa3 100644
--- a/app/assets/stylesheets/framework/mixins.scss
+++ b/app/assets/stylesheets/framework/mixins.scss
@@ -65,7 +65,7 @@
.stats {
float: right;
line-height: $list-text-height;
- color: $gl-text-color;
+ color: $gl-text-color-secondary;
span {
margin-right: 15px;
diff --git a/app/assets/stylesheets/pages/branches.scss b/app/assets/stylesheets/pages/branches.scss
index ce0622b3d48..e1715b8e1bf 100644
--- a/app/assets/stylesheets/pages/branches.scss
+++ b/app/assets/stylesheets/pages/branches.scss
@@ -14,62 +14,26 @@
$graph-side-width: 80px;
$graph-separator-width: 1px;
- padding: 0 6px;
-
.graph-side {
- position: relative;
width: $graph-side-width;
- height: 22px;
- padding: 5px 0 13px;
- float: left;
&.full {
width: $graph-side-width * 2 + $graph-separator-width;
- display: flex;
- justify-content: center;
}
.bar {
- position: absolute;
height: 4px;
background-color: $gl-gray-200;
}
- .bar-behind {
- right: 0;
- border-radius: 3px 0 0 3px;
- }
-
- .bar-ahead {
- left: 0;
- border-radius: 0 3px 3px 0;
- }
-
.count {
- padding-top: 6px;
- padding-bottom: 0;
font-size: 12px;
- color: $gl-text-color;
- display: block;
- }
-
- .count-behind {
- padding-right: 4px;
- text-align: right;
- }
-
- .count-ahead {
- padding-left: 4px;
- text-align: left;
}
}
.graph-separator {
- position: relative;
width: $graph-separator-width;
height: 18px;
- margin: 5px 0 0;
- float: left;
background-color: $gl-gray-200;
}
}
diff --git a/app/assets/stylesheets/pages/groups.scss b/app/assets/stylesheets/pages/groups.scss
index 656202f4e58..cff2e274390 100644
--- a/app/assets/stylesheets/pages/groups.scss
+++ b/app/assets/stylesheets/pages/groups.scss
@@ -168,12 +168,6 @@
}
}
-.groups-listing {
- .group-list-tree .group-row:first-child {
- border-top: 0;
- }
-}
-
.card {
.shared_runners_limit_under_quota {
color: $green-500;
@@ -260,7 +254,6 @@ table.pipeline-project-metrics tr td {
color: $gl-text-color-secondary;
font-size: 12px;
line-height: 20px;
- margin: -5px 3px;
padding: 0 $label-padding;
border: 1px solid $border-color;
border-radius: $label-border-radius;
@@ -294,39 +287,6 @@ table.pipeline-project-metrics tr td {
}
.group-list-tree {
- .avatar-container.content-loading {
- position: relative;
-
- > a,
- > a .avatar {
- height: 100%;
- border-radius: 50%;
- }
-
- > a {
- padding: 2px;
-
- .avatar {
- border: 2px solid $white-normal;
-
- &.identicon {
- line-height: 15px;
- }
- }
- }
-
- &::after {
- content: '';
- position: absolute;
- height: 100%;
- width: 100%;
- background-color: transparent;
- border: 2px outset $gl-gray-200;
- border-radius: 50%;
- animation: spin-avatar 3s infinite linear;
- }
- }
-
.folder-toggle-wrap {
font-size: 0;
flex-shrink: 0;
@@ -339,13 +299,14 @@ table.pipeline-project-metrics tr td {
.folder-caret,
.item-type-icon {
display: inline-block;
+ color: $gl-text-color-secondary;
}
.folder-caret {
- width: 15px;
+ width: $gl-font-size-large;
svg {
- margin-bottom: 1px;
+ margin-bottom: 2px;
}
}
@@ -420,7 +381,7 @@ table.pipeline-project-metrics tr td {
}
.group-row-contents {
- padding: $gl-padding-top;
+ padding: $gl-padding;
&:hover {
border-color: $blue-200;
@@ -428,10 +389,15 @@ table.pipeline-project-metrics tr td {
cursor: pointer;
}
+ .group-text-container,
.group-text {
min-width: 0; // allows for truncated text within flex children
}
+ .group-text {
+ flex-basis: 100%;
+ }
+
.avatar-container {
flex-shrink: 0;
@@ -441,6 +407,21 @@ table.pipeline-project-metrics tr td {
}
}
+ .title {
+ margin-top: -$gl-padding-8; // negative margin required for flex-wrap
+ font-size: $gl-font-size-large;
+ }
+
+ .item-visibility {
+ color: $gl-text-color-secondary;
+ }
+
+ @include media-breakpoint-down(md) {
+ .title {
+ font-size: $gl-font-size;
+ }
+ }
+
&.has-more-items {
display: block;
padding: 20px 10px;
@@ -477,17 +458,18 @@ table.pipeline-project-metrics tr td {
}
.controls {
- flex-shrink: 0;
+ flex-basis: 90px;
> .btn {
- margin: 0 0 0 $btn-margin-5;
+ margin: 0 $btn-side-margin 0 0;
+ color: $gl-text-color-secondary;
}
}
- }
- @include media-breakpoint-down(xs) {
- .group-stats {
- display: none;
+ .metadata {
+ @include media-breakpoint-up(md) {
+ flex-basis: 240px;
+ }
}
}
diff --git a/app/assets/stylesheets/pages/projects.scss b/app/assets/stylesheets/pages/projects.scss
index 151af843c95..c80beceae52 100644
--- a/app/assets/stylesheets/pages/projects.scss
+++ b/app/assets/stylesheets/pages/projects.scss
@@ -889,7 +889,6 @@ pre.light-well {
@include basic-list-stats;
display: flex;
align-items: center;
- color: $gl-text-color-secondary;
padding: $gl-padding 0;
@include media-breakpoint-up(lg) {
@@ -952,10 +951,6 @@ pre.light-well {
.description {
line-height: 1.5;
-
- @include media-breakpoint-up(md) {
- color: $gl-text-color;
- }
}
@include media-breakpoint-down(md) {
diff --git a/app/controllers/dashboard/todos_controller.rb b/app/controllers/dashboard/todos_controller.rb
index f173c263474..27980466a42 100644
--- a/app/controllers/dashboard/todos_controller.rb
+++ b/app/controllers/dashboard/todos_controller.rb
@@ -10,6 +10,7 @@ class Dashboard::TodosController < Dashboard::ApplicationController
def index
@sort = params[:sort]
@todos = @todos.page(params[:page])
+ @todos = @todos.with_entity_associations
return if redirect_out_of_range(@todos)
end
diff --git a/app/controllers/projects/issues_controller.rb b/app/controllers/projects/issues_controller.rb
index b4d89db20c5..b16f3dd9d82 100644
--- a/app/controllers/projects/issues_controller.rb
+++ b/app/controllers/projects/issues_controller.rb
@@ -33,7 +33,7 @@ class Projects::IssuesController < Projects::ApplicationController
before_action :authorize_create_issue!, only: [:new, :create]
# Allow modify issue
- before_action :authorize_update_issuable!, only: [:edit, :update, :move]
+ before_action :authorize_update_issuable!, only: [:edit, :update, :move, :reorder]
# Allow create a new branch and empty WIP merge request from current issue
before_action :authorize_create_merge_request_from!, only: [:create_merge_request]
@@ -132,6 +132,16 @@ class Projects::IssuesController < Projects::ApplicationController
render_conflict_response
end
+ def reorder
+ service = Issues::ReorderService.new(project, current_user, reorder_params)
+
+ if service.execute(issue)
+ head :ok
+ else
+ head :unprocessable_entity
+ end
+ end
+
def related_branches
@related_branches = Issues::RelatedBranchesService.new(project, current_user).execute(issue)
@@ -239,6 +249,10 @@ class Projects::IssuesController < Projects::ApplicationController
] + [{ label_ids: [], assignee_ids: [], update_task: [:index, :checked, :line_number, :line_source] }]
end
+ def reorder_params
+ params.permit(:move_before_id, :move_after_id, :group_full_path)
+ end
+
def store_uri
if request.get? && !request.xhr?
store_location_for :user, request.fullpath
diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb
index 9e7e3ed5afb..fc37ce1dbc4 100644
--- a/app/controllers/projects/merge_requests_controller.rb
+++ b/app/controllers/projects/merge_requests_controller.rb
@@ -16,7 +16,7 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
before_action :authenticate_user!, only: [:assign_related_issues]
before_action :check_user_can_push_to_source_branch!, only: [:rebase]
- around_action :allow_gitaly_ref_name_caching, only: [:index, :show]
+ around_action :allow_gitaly_ref_name_caching, only: [:index, :show, :discussions]
def index
@merge_requests = @issuables
@@ -33,7 +33,7 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
def show
close_merge_request_if_no_source_project
- mark_merge_request_mergeable
+ @merge_request.check_mergeability
respond_to do |format|
format.html do
@@ -251,10 +251,6 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
@merge_request.has_no_commits? && !@merge_request.target_branch_exists?
end
- def mark_merge_request_mergeable
- @merge_request.check_if_can_be_merged
- end
-
def merge!
# Disable the CI check if auto_merge_strategy is specified since we have
# to wait until CI completes to know
diff --git a/app/controllers/projects/pages_domains_controller.rb b/app/controllers/projects/pages_domains_controller.rb
index 89f21d8dadb..c287e440db0 100644
--- a/app/controllers/projects/pages_domains_controller.rb
+++ b/app/controllers/projects/pages_domains_controller.rb
@@ -65,16 +65,14 @@ class Projects::PagesDomainsController < Projects::ApplicationController
private
def create_params
- params.require(:pages_domain).permit(:key, :certificate, :domain, :auto_ssl_enabled)
+ params.require(:pages_domain).permit(:user_provided_key, :user_provided_certificate, :domain, :auto_ssl_enabled)
end
def update_params
- params.require(:pages_domain).permit(:key, :certificate, :auto_ssl_enabled)
+ params.require(:pages_domain).permit(:user_provided_key, :user_provided_certificate, :auto_ssl_enabled)
end
- # rubocop: disable CodeReuse/ActiveRecord
def domain
- @domain ||= @project.pages_domains.find_by!(domain: params[:id].to_s)
+ @domain ||= @project.pages_domains.find_by_domain!(params[:id].to_s)
end
- # rubocop: enable CodeReuse/ActiveRecord
end
diff --git a/app/finders/autocomplete/acts_as_taggable_on/tags_finder.rb b/app/finders/autocomplete/acts_as_taggable_on/tags_finder.rb
index f38c187799c..78a17312e26 100644
--- a/app/finders/autocomplete/acts_as_taggable_on/tags_finder.rb
+++ b/app/finders/autocomplete/acts_as_taggable_on/tags_finder.rb
@@ -22,8 +22,7 @@ module Autocomplete
end
def filter_by_name(tags)
- return tags unless search
- return tags.none if search.empty?
+ return tags unless search.present?
if search.length >= Gitlab::SQL::Pattern::MIN_CHARS_FOR_PARTIAL_MATCHING
tags.named_like(search)
diff --git a/app/finders/environments_finder.rb b/app/finders/environments_finder.rb
index 419be46fafe..29c00e4b2c2 100644
--- a/app/finders/environments_finder.rb
+++ b/app/finders/environments_finder.rb
@@ -47,6 +47,19 @@ class EnvironmentsFinder
end
# rubocop: enable CodeReuse/ActiveRecord
+ # This method will eventually take the place of `#execute` as an
+ # efficient way to get relevant environment entries.
+ # Currently, `#execute` method has a serious technical debt and
+ # we will likely rework on it in the future.
+ # See more https://gitlab.com/gitlab-org/gitlab-ce/issues/63381
+ def find
+ environments = project.environments
+ environments = by_name(environments)
+ environments = by_search(environments)
+
+ environments
+ end
+
private
def ref
@@ -56,4 +69,20 @@ class EnvironmentsFinder
def commit
params[:commit]
end
+
+ def by_name(environments)
+ if params[:name].present?
+ environments.for_name(params[:name])
+ else
+ environments
+ end
+ end
+
+ def by_search(environments)
+ if params[:search].present?
+ environments.for_name_like(params[:search], limit: nil)
+ else
+ environments
+ end
+ end
end
diff --git a/app/helpers/appearances_helper.rb b/app/helpers/appearances_helper.rb
index c0db9910143..6b43d52c775 100644
--- a/app/helpers/appearances_helper.rb
+++ b/app/helpers/appearances_helper.rb
@@ -2,6 +2,7 @@
module AppearancesHelper
include MarkupHelper
+ include Gitlab::Utils::StrongMemoize
def brand_title
current_appearance&.title.presence || default_brand_title
@@ -25,7 +26,9 @@ module AppearancesHelper
end
def current_appearance
- @appearance ||= Appearance.current
+ strong_memoize(:current_appearance) do
+ Appearance.current
+ end
end
def brand_header_logo
diff --git a/app/helpers/application_settings_helper.rb b/app/helpers/application_settings_helper.rb
index 4469118f065..d837c42fd68 100644
--- a/app/helpers/application_settings_helper.rb
+++ b/app/helpers/application_settings_helper.rb
@@ -253,6 +253,7 @@ module ApplicationSettingsHelper
:throttle_unauthenticated_enabled,
:throttle_unauthenticated_period_in_seconds,
:throttle_unauthenticated_requests_per_period,
+ :time_tracking_limit_to_hours,
:two_factor_grace_period,
:unique_ips_limit_enabled,
:unique_ips_limit_per_user,
diff --git a/app/helpers/boards_helper.rb b/app/helpers/boards_helper.rb
index 1640f4fc93f..c5130b430b9 100644
--- a/app/helpers/boards_helper.rb
+++ b/app/helpers/boards_helper.rb
@@ -14,7 +14,8 @@ module BoardsHelper
issue_link_base: build_issue_link_base,
root_path: root_path,
bulk_update_path: @bulk_issues_path,
- default_avatar: image_path(default_avatar)
+ default_avatar: image_path(default_avatar),
+ time_tracking_limit_to_hours: Gitlab::CurrentSettings.time_tracking_limit_to_hours.to_s
}
end
diff --git a/app/helpers/issuables_helper.rb b/app/helpers/issuables_helper.rb
index 150f24a5d5b..045de105b77 100644
--- a/app/helpers/issuables_helper.rb
+++ b/app/helpers/issuables_helper.rb
@@ -430,7 +430,8 @@ module IssuablesHelper
editable: issuable.dig(:current_user, :can_edit),
currentUser: issuable[:current_user],
rootPath: root_path,
- fullPath: issuable[:project_full_path]
+ fullPath: issuable[:project_full_path],
+ timeTrackingLimitToHours: Gitlab::CurrentSettings.time_tracking_limit_to_hours
}
end
diff --git a/app/helpers/issues_helper.rb b/app/helpers/issues_helper.rb
index 957ab06b0ca..59332c0b100 100644
--- a/app/helpers/issues_helper.rb
+++ b/app/helpers/issues_helper.rb
@@ -135,6 +135,20 @@ module IssuesHelper
can?(current_user, :create_issue, project)
end
+ def create_confidential_merge_request_enabled?
+ Feature.enabled?(:create_confidential_merge_request, @project)
+ end
+
+ def show_new_branch_button?
+ can_create_confidential_merge_request? || !@issue.confidential?
+ end
+
+ def can_create_confidential_merge_request?
+ @issue.confidential? && !@project.private? &&
+ create_confidential_merge_request_enabled? &&
+ can?(current_user, :create_merge_request_in, @project)
+ end
+
# Required for Banzai::Filter::IssueReferenceFilter
module_function :url_for_issue
module_function :url_for_internal_issue
diff --git a/app/helpers/todos_helper.rb b/app/helpers/todos_helper.rb
index 6bd78336ed3..645160077f5 100644
--- a/app/helpers/todos_helper.rb
+++ b/app/helpers/todos_helper.rb
@@ -170,7 +170,7 @@ module TodosHelper
end
def todo_group_options
- groups = current_user.authorized_groups.map do |group|
+ groups = current_user.authorized_groups.with_route.map do |group|
{ id: group.id, text: group.full_name }
end
diff --git a/app/mailers/emails/notes.rb b/app/mailers/emails/notes.rb
index 70d296fe3b8..506c8d251b7 100644
--- a/app/mailers/emails/notes.rb
+++ b/app/mailers/emails/notes.rb
@@ -60,7 +60,7 @@ module Emails
# `note_id` is a `Note` when originating in `NotifyPreview`
@note = note_id.is_a?(Note) ? note_id : Note.find(note_id)
@project = @note.project
- @group = @note.noteable.try(:group)
+ @group = @project.try(:group) || @note.noteable.try(:group)
if (@project || @group) && @note.persisted?
@sent_notification = SentNotification.record_note(@note, recipient_id, reply_key)
diff --git a/app/models/application_setting_implementation.rb b/app/models/application_setting_implementation.rb
index 904d650ef96..cf328bcd994 100644
--- a/app/models/application_setting_implementation.rb
+++ b/app/models/application_setting_implementation.rb
@@ -82,6 +82,7 @@ module ApplicationSettingImplementation
throttle_unauthenticated_enabled: false,
throttle_unauthenticated_period_in_seconds: 3600,
throttle_unauthenticated_requests_per_period: 3600,
+ time_tracking_limit_to_hours: false,
two_factor_grace_period: 48,
unique_ips_limit_enabled: false,
unique_ips_limit_per_user: 10,
diff --git a/app/models/ci/pipeline_schedule.rb b/app/models/ci/pipeline_schedule.rb
index 6a4241c94bc..ba8cea0cea9 100644
--- a/app/models/ci/pipeline_schedule.rb
+++ b/app/models/ci/pipeline_schedule.rb
@@ -55,15 +55,20 @@ module Ci
# This way, a schedule like `*/1 * * * *` won't be triggered in a short interval
# when PipelineScheduleWorker runs irregularly by Sidekiq Memory Killer.
def set_next_run_at
- self.next_run_at = Gitlab::Ci::CronParser.new(Settings.cron_jobs['pipeline_schedule_worker']['cron'],
- Time.zone.name)
- .next_time_from(ideal_next_run_at)
+ now = Time.zone.now
+ ideal_next_run = ideal_next_run_from(now)
+
+ self.next_run_at = if ideal_next_run == cron_worker_next_run_from(now)
+ ideal_next_run
+ else
+ cron_worker_next_run_from(ideal_next_run)
+ end
end
def schedule_next_run!
save! # with set_next_run_at
rescue ActiveRecord::RecordInvalid
- update_attribute(:next_run_at, nil) # update without validation
+ update_column(:next_run_at, nil) # update without validation
end
def job_variables
@@ -72,9 +77,15 @@ module Ci
private
- def ideal_next_run_at
+ def ideal_next_run_from(start_time)
Gitlab::Ci::CronParser.new(cron, cron_timezone)
- .next_time_from(Time.zone.now)
+ .next_time_from(start_time)
+ end
+
+ def cron_worker_next_run_from(start_time)
+ Gitlab::Ci::CronParser.new(Settings.cron_jobs['pipeline_schedule_worker']['cron'],
+ Time.zone.name)
+ .next_time_from(start_time)
end
end
end
diff --git a/app/models/clusters/platforms/kubernetes.rb b/app/models/clusters/platforms/kubernetes.rb
index 2afe471d1cc..5afb193cf86 100644
--- a/app/models/clusters/platforms/kubernetes.rb
+++ b/app/models/clusters/platforms/kubernetes.rb
@@ -47,7 +47,6 @@ module Clusters
validate :prevent_modification, on: :update
after_save :clear_reactive_cache!
- after_update :update_kubernetes_namespace
alias_attribute :ca_pem, :ca_cert
@@ -210,14 +209,6 @@ module Clusters
true
end
-
- def update_kubernetes_namespace
- return unless saved_change_to_namespace?
-
- run_after_commit do
- ClusterConfigureWorker.perform_async(cluster_id)
- end
- end
end
end
end
diff --git a/app/models/concerns/service_push_data_validations.rb b/app/models/concerns/service_push_data_validations.rb
new file mode 100644
index 00000000000..defc5794142
--- /dev/null
+++ b/app/models/concerns/service_push_data_validations.rb
@@ -0,0 +1,43 @@
+# frozen_string_literal: true
+
+# This concern is used by registerd services such as TeamCityService and
+# DroneCiService and add methods to perform validations on the received
+# data.
+
+module ServicePushDataValidations
+ extend ActiveSupport::Concern
+
+ def merge_request_valid?(data)
+ data.dig(:object_attributes, :state) == 'opened' && merge_request_unchecked?(data)
+ end
+
+ def push_valid?(data)
+ data[:total_commits_count] > 0 &&
+ !branch_removed?(data) &&
+ # prefer merge request trigger over push to avoid double builds
+ !opened_merge_requests?(data)
+ end
+
+ def tag_push_valid?(data)
+ data[:total_commits_count] > 0 && !branch_removed?(data)
+ end
+
+ private
+
+ def branch_removed?(data)
+ Gitlab::Git.blank_ref?(data[:after])
+ end
+
+ def opened_merge_requests?(data)
+ project.merge_requests
+ .opened
+ .from_project(project)
+ .from_source_branches(Gitlab::Git.ref_name(data[:ref]))
+ .exists?
+ end
+
+ def merge_request_unchecked?(data)
+ MergeRequest.state_machines[:merge_status]
+ .check_state?(data.dig(:object_attributes, :merge_status))
+ end
+end
diff --git a/app/models/deployment.rb b/app/models/deployment.rb
index 92c7311014a..f0fa5974787 100644
--- a/app/models/deployment.rb
+++ b/app/models/deployment.rb
@@ -84,12 +84,9 @@ class Deployment < ApplicationRecord
Commit.truncate_sha(sha)
end
- def cluster
- platform = project.deployment_platform(environment: environment.name)
-
- if platform.present? && platform.respond_to?(:cluster)
- platform.cluster
- end
+ # Deprecated - will be replaced by a persisted cluster_id
+ def deployment_platform_cluster
+ environment.deployment_platform&.cluster
end
def execute_hooks
@@ -179,7 +176,7 @@ class Deployment < ApplicationRecord
end
def has_metrics?
- prometheus_adapter&.can_query? && success?
+ success? && prometheus_adapter&.can_query?
end
def metrics
diff --git a/app/models/environment.rb b/app/models/environment.rb
index aff20dae09b..1f7e8815c8e 100644
--- a/app/models/environment.rb
+++ b/app/models/environment.rb
@@ -155,7 +155,7 @@ class Environment < ApplicationRecord
end
def has_terminals?
- deployment_platform.present? && available? && last_deployment.present?
+ available? && deployment_platform.present? && last_deployment.present?
end
def terminals
@@ -163,7 +163,7 @@ class Environment < ApplicationRecord
end
def has_metrics?
- prometheus_adapter&.can_query? && available?
+ available? && prometheus_adapter&.can_query?
end
def metrics
diff --git a/app/models/issue.rb b/app/models/issue.rb
index 6da6fbe55cb..30e29911758 100644
--- a/app/models/issue.rb
+++ b/app/models/issue.rb
@@ -254,6 +254,10 @@ class Issue < ApplicationRecord
merge_requests_closing_issues.count
end
+ def labels_hook_attrs
+ labels.map(&:hook_attrs)
+ end
+
private
def ensure_metrics
diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb
index f07636e8f77..df2dc9c49eb 100644
--- a/app/models/merge_request.rb
+++ b/app/models/merge_request.rb
@@ -725,19 +725,16 @@ class MergeRequest < ApplicationRecord
MergeRequests::ReloadDiffsService.new(self, current_user).execute
end
- # rubocop: enable CodeReuse/ServiceClass
-
- def check_if_can_be_merged
- return unless self.class.state_machines[:merge_status].check_state?(merge_status) && Gitlab::Database.read_write?
- can_be_merged =
- !broken? && project.repository.can_be_merged?(diff_head_sha, target_branch)
+ def check_mergeability
+ MergeRequests::MergeabilityCheckService.new(self).execute
+ end
+ # rubocop: enable CodeReuse/ServiceClass
- if can_be_merged
- mark_as_mergeable
- else
- mark_as_unmergeable
- end
+ # Returns boolean indicating the merge_status should be rechecked in order to
+ # switch to either can_be_merged or cannot_be_merged.
+ def recheck_merge_status?
+ self.class.state_machines[:merge_status].check_state?(merge_status)
end
def merge_event
@@ -763,7 +760,7 @@ class MergeRequest < ApplicationRecord
def mergeable?(skip_ci_check: false)
return false unless mergeable_state?(skip_ci_check: skip_ci_check)
- check_if_can_be_merged
+ check_mergeability
can_be_merged? && !should_be_rebased?
end
@@ -778,15 +775,6 @@ class MergeRequest < ApplicationRecord
true
end
- def mergeable_to_ref?
- return false unless mergeable_state?(skip_ci_check: true, skip_discussions_check: true)
-
- # Given the `merge_ref_path` will have the same
- # state the `target_branch` would have. Ideally
- # we need to check if it can be merged to it.
- project.repository.can_be_merged?(diff_head_sha, target_branch)
- end
-
def ff_merge_possible?
project.repository.ancestor?(target_branch_sha, diff_head_sha)
end
@@ -1099,6 +1087,12 @@ class MergeRequest < ApplicationRecord
target_project.repository.fetch_source_branch!(source_project.repository, source_branch, ref_path)
end
+ # Returns the current merge-ref HEAD commit.
+ #
+ def merge_ref_head
+ project.repository.commit(merge_ref_path)
+ end
+
def ref_path
"refs/#{Repository::REF_MERGE_REQUEST}/#{iid}/head"
end
diff --git a/app/models/pages_domain.rb b/app/models/pages_domain.rb
index 524df30289e..d6d879c6d89 100644
--- a/app/models/pages_domain.rb
+++ b/app/models/pages_domain.rb
@@ -3,6 +3,9 @@
class PagesDomain < ApplicationRecord
VERIFICATION_KEY = 'gitlab-pages-verification-code'.freeze
VERIFICATION_THRESHOLD = 3.days.freeze
+ SSL_RENEWAL_THRESHOLD = 30.days.freeze
+
+ enum certificate_source: { user_provided: 0, gitlab_provided: 1 }, _prefix: :certificate
belongs_to :project
has_many :acme_orders, class_name: "PagesDomainAcmeOrder"
@@ -39,6 +42,15 @@ class PagesDomain < ApplicationRecord
where(verified_at.eq(nil).or(enabled_until.eq(nil).or(enabled_until.lt(threshold))))
end
+ scope :need_auto_ssl_renewal, -> do
+ expiring = where(certificate_valid_not_after: nil).or(
+ where(arel_table[:certificate_valid_not_after].lt(SSL_RENEWAL_THRESHOLD.from_now)))
+
+ user_provided_or_expiring = certificate_user_provided.or(expiring)
+
+ where(auto_ssl_enabled: true).merge(user_provided_or_expiring)
+ end
+
scope :for_removal, -> { where("remove_at < ?", Time.now) }
def verified?
@@ -143,6 +155,34 @@ class PagesDomain < ApplicationRecord
self.certificate_valid_not_after = x509&.not_after
end
+ def user_provided_key
+ key if certificate_user_provided?
+ end
+
+ def user_provided_key=(key)
+ self.key = key
+ self.certificate_source = 'user_provided' if key_changed?
+ end
+
+ def user_provided_certificate
+ certificate if certificate_user_provided?
+ end
+
+ def user_provided_certificate=(certificate)
+ self.certificate = certificate
+ self.certificate_source = 'user_provided' if certificate_changed?
+ end
+
+ def gitlab_provided_certificate=(certificate)
+ self.certificate = certificate
+ self.certificate_source = 'gitlab_provided' if certificate_changed?
+ end
+
+ def gitlab_provided_key=(key)
+ self.key = key
+ self.certificate_source = 'gitlab_provided' if key_changed?
+ end
+
private
def set_verification_code
diff --git a/app/models/project.rb b/app/models/project.rb
index 7851f37116c..351d08eaf63 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -55,6 +55,8 @@ class Project < ApplicationRecord
VALID_MIRROR_PORTS = [22, 80, 443].freeze
VALID_MIRROR_PROTOCOLS = %w(http https ssh git).freeze
+ ignore_column :import_status, :import_jid, :import_error
+
cache_markdown_field :description, pipeline: :description
delegate :feature_available?, :builds_enabled?, :wiki_enabled?,
diff --git a/app/models/project_services/drone_ci_service.rb b/app/models/project_services/drone_ci_service.rb
index 5ccc2f019cb..dbdc8345c93 100644
--- a/app/models/project_services/drone_ci_service.rb
+++ b/app/models/project_services/drone_ci_service.rb
@@ -2,6 +2,7 @@
class DroneCiService < CiService
include ReactiveService
+ include ServicePushDataValidations
prop_accessor :drone_url, :token
boolean_accessor :enable_ssl_verification
@@ -96,23 +97,4 @@ class DroneCiService < CiService
{ type: 'checkbox', name: 'enable_ssl_verification', title: "Enable SSL verification" }
]
end
-
- private
-
- def tag_push_valid?(data)
- data[:total_commits_count] > 0 && !Gitlab::Git.blank_ref?(data[:after])
- end
-
- def push_valid?(data)
- opened_merge_requests = project.merge_requests.opened.where(source_project_id: project.id,
- source_branch: Gitlab::Git.ref_name(data[:ref]))
-
- opened_merge_requests.empty? && data[:total_commits_count] > 0 &&
- !Gitlab::Git.blank_ref?(data[:after])
- end
-
- def merge_request_valid?(data)
- data[:object_attributes][:state] == 'opened' &&
- MergeRequest.state_machines[:merge_status].check_state?(data[:object_attributes][:merge_status])
- end
end
diff --git a/app/models/project_services/teamcity_service.rb b/app/models/project_services/teamcity_service.rb
index 3245cd22e73..68c07fa37f2 100644
--- a/app/models/project_services/teamcity_service.rb
+++ b/app/models/project_services/teamcity_service.rb
@@ -2,6 +2,7 @@
class TeamcityService < CiService
include ReactiveService
+ include ServicePushDataValidations
prop_accessor :teamcity_url, :build_type, :username, :password
@@ -19,6 +20,25 @@ class TeamcityService < CiService
after_save :compose_service_hook, if: :activated?
before_update :reset_password
+ class << self
+ def to_param
+ 'teamcity'
+ end
+
+ def supported_events
+ %w(push merge_request)
+ end
+
+ def event_description(event)
+ case event
+ when 'push', 'push_events'
+ 'TeamCity CI will be triggered after every push to the repository except branch delete'
+ when 'merge_request', 'merge_request_events'
+ 'TeamCity CI will be triggered after a merge request has been created or updated'
+ end
+ end
+ end
+
def compose_service_hook
hook = service_hook || build_service_hook
hook.save
@@ -43,10 +63,6 @@ class TeamcityService < CiService
'requests build, that setting is in the vsc root advanced settings.'
end
- def self.to_param
- 'teamcity'
- end
-
def fields
[
{ type: 'text', name: 'teamcity_url',
@@ -74,26 +90,25 @@ class TeamcityService < CiService
end
def execute(data)
- return unless supported_events.include?(data[:object_kind])
+ case data[:object_kind]
+ when 'push'
+ execute_push(data)
+ when 'merge_request'
+ execute_merge_request(data)
+ end
+ end
- auth = {
- username: username,
- password: password
- }
+ private
+ def execute_push(data)
branch = Gitlab::Git.ref_name(data[:ref])
-
- Gitlab::HTTP.post(
- build_url('httpAuth/app/rest/buildQueue'),
- body: "<build branchName=\"#{branch}\">"\
- "<buildType id=\"#{build_type}\"/>"\
- '</build>',
- headers: { 'Content-type' => 'application/xml' },
- basic_auth: auth
- )
+ post_to_build_queue(data, branch) if push_valid?(data)
end
- private
+ def execute_merge_request(data)
+ branch = data[:object_attributes][:source_branch]
+ post_to_build_queue(data, branch) if merge_request_valid?(data)
+ end
def read_build_page(response)
if response.code != 200
@@ -134,10 +149,21 @@ class TeamcityService < CiService
end
def get_path(path)
- Gitlab::HTTP.get(build_url(path), verify: false,
- basic_auth: {
- username: username,
- password: password
- })
+ Gitlab::HTTP.get(build_url(path), verify: false, basic_auth: basic_auth)
+ end
+
+ def post_to_build_queue(data, branch)
+ Gitlab::HTTP.post(
+ build_url('httpAuth/app/rest/buildQueue'),
+ body: "<build branchName=#{branch.encode(xml: :attr)}>"\
+ "<buildType id=#{build_type.encode(xml: :attr)}/>"\
+ '</build>',
+ headers: { 'Content-type' => 'application/xml' },
+ basic_auth: basic_auth
+ )
+ end
+
+ def basic_auth
+ { username: username, password: password }
end
end
diff --git a/app/models/todo.rb b/app/models/todo.rb
index f1fc5e599eb..240c91da5b6 100644
--- a/app/models/todo.rb
+++ b/app/models/todo.rb
@@ -60,7 +60,7 @@ class Todo < ApplicationRecord
scope :for_type, -> (type) { where(target_type: type) }
scope :for_target, -> (id) { where(target_id: id) }
scope :for_commit, -> (id) { where(commit_id: id) }
- scope :with_api_entity_associations, -> { preload(:target, :author, :note, group: :route, project: [:route, { namespace: :route }]) }
+ scope :with_entity_associations, -> { preload(:target, :author, :note, group: :route, project: [:route, { namespace: :route }]) }
scope :joins_issue_and_assignees, -> { left_joins(issue: :assignees) }
state_machine :state, initial: :pending do
diff --git a/app/services/boards/issues/move_service.rb b/app/services/boards/issues/move_service.rb
index 834baeb9643..e27d34dbcab 100644
--- a/app/services/boards/issues/move_service.rb
+++ b/app/services/boards/issues/move_service.rb
@@ -79,9 +79,11 @@ module Boards
# rubocop: enable CodeReuse/ActiveRecord
def move_between_ids
- return unless params[:move_after_id] || params[:move_before_id]
+ ids = [params[:move_after_id], params[:move_before_id]]
+ .map(&:to_i)
+ .map { |m| m.positive? ? m : nil }
- [params[:move_after_id], params[:move_before_id]]
+ ids.any? ? ids : nil
end
end
end
diff --git a/app/services/clusters/gcp/finalize_creation_service.rb b/app/services/clusters/gcp/finalize_creation_service.rb
index 5525c1b9b7f..2f3c1df7651 100644
--- a/app/services/clusters/gcp/finalize_creation_service.rb
+++ b/app/services/clusters/gcp/finalize_creation_service.rb
@@ -12,9 +12,6 @@ module Clusters
create_gitlab_service_account!
configure_kubernetes
cluster.save!
-
- 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)
provider.make_errored!(s_('ClusterIntegration|Failed to request to Google Cloud Platform: %{message}') % { message: e.message })
diff --git a/app/services/clusters/gcp/kubernetes/fetch_kubernetes_token_service.rb b/app/services/clusters/gcp/kubernetes/fetch_kubernetes_token_service.rb
index 4ad04ab801e..5d9bdc52d37 100644
--- a/app/services/clusters/gcp/kubernetes/fetch_kubernetes_token_service.rb
+++ b/app/services/clusters/gcp/kubernetes/fetch_kubernetes_token_service.rb
@@ -4,17 +4,30 @@ module Clusters
module Gcp
module Kubernetes
class FetchKubernetesTokenService
+ DEFAULT_TOKEN_RETRY_DELAY = 5.seconds
+ TOKEN_RETRY_LIMIT = 5
+
attr_reader :kubeclient, :service_account_token_name, :namespace
- def initialize(kubeclient, service_account_token_name, namespace)
+ def initialize(kubeclient, service_account_token_name, namespace, token_retry_delay: DEFAULT_TOKEN_RETRY_DELAY)
@kubeclient = kubeclient
@service_account_token_name = service_account_token_name
@namespace = namespace
+ @token_retry_delay = token_retry_delay
end
def execute
- token_base64 = get_secret&.dig('data', 'token')
- Base64.decode64(token_base64) if token_base64
+ # Kubernetes will create the Secret and set the token asynchronously
+ # so it is necessary to retry
+ # https://kubernetes.io/docs/reference/access-authn-authz/service-accounts-admin/#token-controller
+ TOKEN_RETRY_LIMIT.times do
+ token_base64 = get_secret&.dig('data', 'token')
+ return Base64.decode64(token_base64) if token_base64
+
+ sleep @token_retry_delay
+ end
+
+ nil
end
private
diff --git a/app/services/issues/reorder_service.rb b/app/services/issues/reorder_service.rb
new file mode 100644
index 00000000000..02c18d31b5e
--- /dev/null
+++ b/app/services/issues/reorder_service.rb
@@ -0,0 +1,48 @@
+# frozen_string_literal: true
+
+module Issues
+ class ReorderService < Issues::BaseService
+ def execute(issue)
+ return false unless can?(current_user, :update_issue, issue)
+ return false if group && !can?(current_user, :read_group, group)
+
+ attrs = issue_params(group)
+ return false if attrs.empty?
+
+ update(issue, attrs)
+ end
+
+ private
+
+ def group
+ return unless params[:group_full_path]
+
+ @group ||= Group.find_by_full_path(params[:group_full_path])
+ end
+
+ def update(issue, attrs)
+ ::Issues::UpdateService.new(project, current_user, attrs).execute(issue)
+ rescue ActiveRecord::RecordNotFound
+ false
+ end
+
+ def issue_params(group)
+ attrs = {}
+
+ if move_between_ids
+ attrs[:move_between_ids] = move_between_ids
+ attrs[:board_group_id] = group&.id
+ end
+
+ attrs
+ end
+
+ def move_between_ids
+ ids = [params[:move_after_id], params[:move_before_id]]
+ .map(&:to_i)
+ .map { |m| m.positive? ? m : nil }
+
+ ids.any? ? ids : nil
+ end
+ end
+end
diff --git a/app/services/issues/update_service.rb b/app/services/issues/update_service.rb
index cb2337d29d4..6b9f23f24cd 100644
--- a/app/services/issues/update_service.rb
+++ b/app/services/issues/update_service.rb
@@ -76,6 +76,7 @@ module Issues
issue_before = get_issue_if_allowed(before_id, board_group_id)
issue_after = get_issue_if_allowed(after_id, board_group_id)
+ raise ActiveRecord::RecordNotFound unless issue_before || issue_after
issue.move_between(issue_before, issue_after)
end
diff --git a/app/services/merge_requests/merge_to_ref_service.rb b/app/services/merge_requests/merge_to_ref_service.rb
index 87147d90c32..efe4dcd6255 100644
--- a/app/services/merge_requests/merge_to_ref_service.rb
+++ b/app/services/merge_requests/merge_to_ref_service.rb
@@ -11,6 +11,8 @@ module MergeRequests
# be executed regardless of the `target_ref` current state).
#
class MergeToRefService < MergeRequests::MergeBaseService
+ extend ::Gitlab::Utils::Override
+
def execute(merge_request)
@merge_request = merge_request
@@ -26,14 +28,18 @@ module MergeRequests
success(commit_id: commit.id,
target_id: target_id,
source_id: source_id)
- rescue MergeError => error
+ rescue MergeError, ArgumentError => error
error(error.message)
end
private
+ override :source
+ def source
+ merge_request.diff_head_sha
+ end
+
def validate!
- authorization_check!
error_check!
end
@@ -43,21 +49,13 @@ module MergeRequests
error =
if !hooks_validation_pass?(merge_request)
hooks_validation_error(merge_request)
- elsif !@merge_request.mergeable_to_ref?
- "Merge request is not mergeable to #{target_ref}"
- elsif !source
+ elsif source.blank?
'No source for merge'
end
raise_error(error) if error
end
- def authorization_check!
- unless Ability.allowed?(current_user, :admin_merge_request, project)
- raise_error("You are not allowed to merge to this ref")
- end
- end
-
def target_ref
merge_request.merge_ref_path
end
diff --git a/app/services/merge_requests/mergeability_check_service.rb b/app/services/merge_requests/mergeability_check_service.rb
new file mode 100644
index 00000000000..9fa50c9448f
--- /dev/null
+++ b/app/services/merge_requests/mergeability_check_service.rb
@@ -0,0 +1,120 @@
+# frozen_string_literal: true
+
+module MergeRequests
+ class MergeabilityCheckService < ::BaseService
+ include Gitlab::Utils::StrongMemoize
+
+ delegate :project, to: :@merge_request
+ delegate :repository, to: :project
+
+ def initialize(merge_request)
+ @merge_request = merge_request
+ end
+
+ # Updates the MR merge_status. Whenever it switches to a can_be_merged state,
+ # the merge-ref is refreshed.
+ #
+ # recheck - When given, it'll enforce a merge-ref refresh if the current merge_status is
+ # can_be_merged or cannot_be_merged and merge-ref is outdated.
+ # Given MergeRequests::RefreshService is called async, it might happen that the target
+ # branch gets updated, but the MergeRequest#merge_status lags behind. So in scenarios
+ # where we need the current state of the merge ref in repository, the `recheck`
+ # argument is required.
+ #
+ # Returns a ServiceResponse indicating merge_status is/became can_be_merged
+ # and the merge-ref is synced. Success in case of being/becoming mergeable,
+ # error otherwise.
+ def execute(recheck: false)
+ return ServiceResponse.error(message: 'Invalid argument') unless merge_request
+ return ServiceResponse.error(message: 'Unsupported operation') if Gitlab::Database.read_only?
+
+ recheck! if recheck
+ update_merge_status
+
+ unless merge_request.can_be_merged?
+ return ServiceResponse.error(message: 'Merge request is not mergeable')
+ end
+
+ unless merge_ref_auto_sync_enabled?
+ return ServiceResponse.error(message: 'Merge ref is outdated due to disabled feature')
+ end
+
+ unless payload.fetch(:merge_ref_head)
+ return ServiceResponse.error(message: 'Merge ref cannot be updated')
+ end
+
+ ServiceResponse.success(payload: payload)
+ end
+
+ private
+
+ attr_reader :merge_request
+
+ def payload
+ strong_memoize(:payload) do
+ {
+ merge_ref_head: merge_ref_head_payload
+ }
+ end
+ end
+
+ def merge_ref_head_payload
+ commit = merge_request.merge_ref_head
+
+ return unless commit
+
+ target_id, source_id = commit.parent_ids
+
+ {
+ commit_id: commit.id,
+ source_id: source_id,
+ target_id: target_id
+ }
+ end
+
+ def update_merge_status
+ return unless merge_request.recheck_merge_status?
+
+ if can_git_merge? && merge_to_ref
+ merge_request.mark_as_mergeable
+ else
+ merge_request.mark_as_unmergeable
+ end
+ end
+
+ def recheck!
+ if !merge_request.recheck_merge_status? && outdated_merge_ref?
+ merge_request.mark_as_unchecked
+ end
+ end
+
+ # Checks if the existing merge-ref is synced with the target branch.
+ #
+ # Returns true if the merge-ref does not exists or is out of sync.
+ def outdated_merge_ref?
+ return false unless merge_ref_auto_sync_enabled?
+ return false unless merge_request.open?
+
+ return true unless ref_head = merge_request.merge_ref_head
+ return true unless target_sha = merge_request.target_branch_sha
+ return true unless source_sha = merge_request.source_branch_sha
+
+ ref_head.parent_ids != [target_sha, source_sha]
+ end
+
+ def can_git_merge?
+ !merge_request.broken? && repository.can_be_merged?(merge_request.diff_head_sha, merge_request.target_branch)
+ end
+
+ def merge_to_ref
+ return true unless merge_ref_auto_sync_enabled?
+
+ result = MergeRequests::MergeToRefService.new(project, merge_request.author).execute(merge_request)
+ result[:status] == :success
+ end
+
+ def merge_ref_auto_sync_enabled?
+ Feature.enabled?(:merge_ref_auto_sync, project, default_enabled: true)
+ end
+ end
+end
diff --git a/app/services/pages_domains/obtain_lets_encrypt_certificate_service.rb b/app/services/pages_domains/obtain_lets_encrypt_certificate_service.rb
index 2dfe1a3d8ca..3413a9e4612 100644
--- a/app/services/pages_domains/obtain_lets_encrypt_certificate_service.rb
+++ b/app/services/pages_domains/obtain_lets_encrypt_certificate_service.rb
@@ -35,7 +35,7 @@ module PagesDomains
def save_certificate(private_key, api_order)
certificate = api_order.certificate
- pages_domain.update!(key: private_key, certificate: certificate)
+ pages_domain.update!(gitlab_provided_key: private_key, gitlab_provided_certificate: certificate)
end
end
end
diff --git a/app/services/service_response.rb b/app/services/service_response.rb
index 1de30e68d87..f3437ba16de 100644
--- a/app/services/service_response.rb
+++ b/app/services/service_response.rb
@@ -1,19 +1,20 @@
# frozen_string_literal: true
class ServiceResponse
- def self.success(message: nil)
- new(status: :success, message: message)
+ def self.success(message: nil, payload: {})
+ new(status: :success, message: message, payload: payload)
end
- def self.error(message:, http_status: nil)
- new(status: :error, message: message, http_status: http_status)
+ def self.error(message:, payload: {}, http_status: nil)
+ new(status: :error, message: message, payload: payload, http_status: http_status)
end
- attr_reader :status, :message, :http_status
+ attr_reader :status, :message, :http_status, :payload
- def initialize(status:, message: nil, http_status: nil)
+ def initialize(status:, message: nil, payload: {}, http_status: nil)
self.status = status
self.message = message
+ self.payload = payload
self.http_status = http_status
end
@@ -27,5 +28,5 @@ class ServiceResponse
private
- attr_writer :status, :message, :http_status
+ attr_writer :status, :message, :http_status, :payload
end
diff --git a/app/views/admin/application_settings/_localization.html.haml b/app/views/admin/application_settings/_localization.html.haml
index bb4d1fa1241..e01c123d1db 100644
--- a/app/views/admin/application_settings/_localization.html.haml
+++ b/app/views/admin/application_settings/_localization.html.haml
@@ -8,4 +8,11 @@
.form-text.text-muted
= _('Default first day of the week in calendars and date pickers.')
+ .form-group
+ = f.label :time_tracking, _('Time tracking'), class: 'label-bold'
+ .form-check
+ = f.check_box :time_tracking_limit_to_hours, class: 'form-check-input'
+ = f.label :time_tracking_limit_to_hours, class: 'form-check-label' do
+ = _('Limit display of time tracking units to hours.')
+
= f.submit _('Save changes'), class: "btn btn-success"
diff --git a/app/views/admin/users/show.html.haml b/app/views/admin/users/show.html.haml
index dcd6f7c8078..5c6131db37d 100644
--- a/app/views/admin/users/show.html.haml
+++ b/app/views/admin/users/show.html.haml
@@ -32,11 +32,12 @@
%li
%span.light Email:
%strong
- = mail_to @user.email
+ = render partial: 'shared/email_with_badge', locals: { email: mail_to(@user.email), verified: @user.confirmed? }
- @user.emails.each do |email|
%li
%span.light Secondary email:
- %strong= email.email
+ %strong
+ = render partial: 'shared/email_with_badge', locals: { email: email.email, verified: email.confirmed? }
= link_to remove_email_admin_user_path(@user, email), data: { confirm: "Are you sure you want to remove #{email.email}?" }, method: :delete, class: "btn-sm btn btn-remove float-right", title: 'Remove secondary email', id: "remove_email_#{email.id}" do
%i.fa.fa-times
%li
diff --git a/app/views/layouts/header/_new_dropdown.haml b/app/views/layouts/header/_new_dropdown.haml
index 438340464bd..1d7a501e5c2 100644
--- a/app/views/layouts/header/_new_dropdown.haml
+++ b/app/views/layouts/header/_new_dropdown.haml
@@ -1,5 +1,5 @@
%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
+ = link_to new_project_path, class: "header-new-dropdown-toggle has-tooltip qa-new-menu-toggle", id: "js-onboarding-new-project-link", 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')
.dropdown-menu.dropdown-menu-right
diff --git a/app/views/layouts/nav/sidebar/_group.html.haml b/app/views/layouts/nav/sidebar/_group.html.haml
index 0fc5ebbea7e..4b5ccc33716 100644
--- a/app/views/layouts/nav/sidebar/_group.html.haml
+++ b/app/views/layouts/nav/sidebar/_group.html.haml
@@ -45,7 +45,6 @@
= _('Contribution Analytics')
= render_if_exists 'layouts/nav/group_insights_link'
- = render_if_exists 'groups/sidebar/dependency_proxy' # EE-specific
= render_if_exists "layouts/nav/ee/epic_link", group: @group
@@ -119,6 +118,8 @@
%strong.fly-out-top-item-name
= _('Kubernetes')
+ = render_if_exists 'groups/sidebar/packages' # EE-specific
+
- if group_sidebar_link?(:group_members)
= nav_link(path: 'group_members#index') do
= link_to group_group_members_path(@group) do
diff --git a/app/views/layouts/nav/sidebar/_project.html.haml b/app/views/layouts/nav/sidebar/_project.html.haml
index 49ff976f8e8..e401488ecff 100644
--- a/app/views/layouts/nav/sidebar/_project.html.haml
+++ b/app/views/layouts/nav/sidebar/_project.html.haml
@@ -50,7 +50,7 @@
= link_to project_tree_path(@project), class: 'shortcuts-tree qa-project-menu-repo' do
.nav-icon-container
= sprite_icon('doc-text')
- %span.nav-item-name
+ %span.nav-item-name#js-onboarding-repo-link
= _('Repository')
%ul.sidebar-sub-level-items
@@ -64,11 +64,11 @@
= _('Files')
= nav_link(controller: [:commit, :commits]) do
- = link_to project_commits_path(@project, current_ref) do
+ = link_to project_commits_path(@project, current_ref), id: 'js-onboarding-commits-link' do
= _('Commits')
= nav_link(html_options: {class: branches_tab_class}) do
- = link_to project_branches_path(@project), class: 'qa-branches-link' do
+ = link_to project_branches_path(@project), class: 'qa-branches-link', id: 'js-onboarding-branches-link' do
= _('Branches')
= nav_link(controller: [:tags]) do
@@ -98,7 +98,7 @@
= link_to project_issues_path(@project), class: 'shortcuts-issues qa-issues-item' do
.nav-icon-container
= sprite_icon('issues')
- %span.nav-item-name
+ %span.nav-item-name#js-onboarding-issues-link
= _('Issues')
- if @project.issues_enabled?
%span.badge.badge-pill.count.issue_counter
@@ -153,7 +153,7 @@
= link_to project_merge_requests_path(@project), class: 'shortcuts-merge_requests qa-merge-requests-link' do
.nav-icon-container
= sprite_icon('git-merge')
- %span.nav-item-name
+ %span.nav-item-name#js-onboarding-mr-link
= _('Merge Requests')
%span.badge.badge-pill.count.merge_counter.js-merge-counter
= number_with_delimiter(@project.open_merge_requests_count)
@@ -170,7 +170,7 @@
= link_to project_pipelines_path(@project), class: 'shortcuts-pipelines qa-link-pipelines' do
.nav-icon-container
= sprite_icon('rocket')
- %span.nav-item-name
+ %span.nav-item-name#js-onboarding-pipelines-link
= _('CI / CD')
%ul.sidebar-sub-level-items
@@ -335,7 +335,7 @@
= link_to edit_project_path(@project), class: 'shortcuts-tree' do
.nav-icon-container
= sprite_icon('settings')
- %span.nav-item-name.qa-settings-item
+ %span.nav-item-name.qa-settings-item#js-onboarding-settings-link
= _('Settings')
%ul.sidebar-sub-level-items
@@ -351,7 +351,7 @@
%span
= _('General')
= nav_link(controller: :project_members) do
- = link_to project_project_members_path(@project), title: _('Members'), class: 'qa-link-members-settings' do
+ = link_to project_project_members_path(@project), title: _('Members'), class: 'qa-link-members-settings', id: 'js-onboarding-settings-members-link' do
%span
= _('Members')
- if can_edit
diff --git a/app/views/notify/_note_email.html.haml b/app/views/notify/_note_email.html.haml
index 83c7f548975..dc5529b489b 100644
--- a/app/views/notify/_note_email.html.haml
+++ b/app/views/notify/_note_email.html.haml
@@ -5,27 +5,21 @@
- discussion = note.discussion if note.part_of_discussion?
-- if discussion
- %p{ style: "color: #777777;" }
- = succeed ':' do
- = link_to note.author_name, user_url(note.author)
+%p{ style: "color: #777777;" }
+ = succeed ':' do
+ = link_to note.author_name, user_url(note.author)
+ - if discussion.nil?
+ commented
+ - else
+ - if discussion.new_discussion?
+ started a new
+ - else
+ commented on a
- if discussion&.diff_discussion?
- - if discussion.new_discussion?
- started a new discussion
- - else
- commented on a discussion
-
- on #{link_to discussion.file_path, target_url}
+ discussion on #{link_to(discussion.file_path, target_url)}
- else
- - if discussion.new_discussion?
- started a new discussion
- - else
- commented on a #{link_to 'discussion', target_url}
-
-- elsif Gitlab::CurrentSettings.email_author_in_body
- %p.details
- #{link_to note.author_name, user_url(note.author)} commented:
+ = link_to 'discussion', target_url
- if discussion&.diff_discussion? && discussion.on_text?
= content_for :head do
diff --git a/app/views/notify/_note_email.text.erb b/app/views/notify/_note_email.text.erb
index fae8fa3ccf3..a25daad8458 100644
--- a/app/views/notify/_note_email.text.erb
+++ b/app/views/notify/_note_email.text.erb
@@ -1,29 +1,25 @@
<% note = local_assigns.fetch(:note, @note) -%>
<% diff_limit = local_assigns.fetch(:diff_limit, nil) -%>
<% target_url = local_assigns.fetch(:target_url, @target_url) -%>
+<% discussion = note.discussion if note.part_of_discussion? -%>
-<% discussion = note.discussion if note.part_of_discussion? -%>
-<% if discussion && !discussion.individual_note? -%>
-<%= sanitize_name(note.author_name) -%>
+<%= sanitize_name(note.author_name) -%>
+<% if discussion.nil? -%>
+ <%= 'commented' -%>:
+<% else -%>
<% if discussion.new_discussion? -%>
-<%= " started a new discussion" -%>
+ <%= 'started a new discussion' -%>
<% else -%>
-<%= " commented on a discussion" -%>
+ <%= 'commented on a discussion' -%>
<% end -%>
<% if discussion.diff_discussion? -%>
-<%= " on #{discussion.file_path}" -%>
+ <%= "on #{discussion.file_path}" -%>
<% end -%>
-<%= ":" -%>
-<% if discussion.diff_discussion? || !discussion.new_discussion? -%>
-<%= " #{target_url}" -%>
-<% end -%>
-
-
-<% elsif Gitlab::CurrentSettings.email_author_in_body -%>
-<%= "#{sanitize_name(note.author_name)} commented:" -%>
+<%= ':' -%>
+<%= " #{target_url}" -%>
+<% end -%>
-<% end -%>
<% if discussion&.diff_discussion? && discussion.on_text? -%>
<% discussion.truncated_diff_lines(highlight: false, diff_limit: diff_limit).each do |line| -%>
<%= "> #{line.text}\n" -%>
diff --git a/app/views/notify/new_issue_email.html.haml b/app/views/notify/new_issue_email.html.haml
index 8aa7939dd0b..78afb42c9cf 100644
--- a/app/views/notify/new_issue_email.html.haml
+++ b/app/views/notify/new_issue_email.html.haml
@@ -1,6 +1,5 @@
-- if Gitlab::CurrentSettings.email_author_in_body
- %p.details
- #{link_to @issue.author_name, user_url(@issue.author)} created an issue:
+%p.details
+ #{link_to @issue.author_name, user_url(@issue.author)} created an issue:
- if @issue.assignees.any?
%p
diff --git a/app/views/notify/new_issue_email.text.erb b/app/views/notify/new_issue_email.text.erb
index ff258711b48..b93d95ef02f 100644
--- a/app/views/notify/new_issue_email.text.erb
+++ b/app/views/notify/new_issue_email.text.erb
@@ -1,7 +1,9 @@
-New Issue was created.
+<%= sanitize_name(@issue.author_name) %> <%= 'created an issue:' %>
-Issue <%= @issue.iid %>: <%= url_for(project_issue_url(@issue.project, @issue)) %>
-Author: <%= sanitize_name(@issue.author_name) %>
-<%= assignees_label(@issue) %>
+<% if @issue.assignees.any? -%>
+ <%= assignees_label(@issue) %>
+<% end %>
-<%= @issue.description %>
+<% if @issue.description -%>
+ <%= @issue.description %>
+<% end %>
diff --git a/app/views/notify/new_merge_request_email.html.haml b/app/views/notify/new_merge_request_email.html.haml
index 9ab648e2a64..2ddea0b9f16 100644
--- a/app/views/notify/new_merge_request_email.html.haml
+++ b/app/views/notify/new_merge_request_email.html.haml
@@ -1,15 +1,15 @@
-- if Gitlab::CurrentSettings.email_author_in_body
- %p.details
- #{link_to @merge_request.author_name, user_url(@merge_request.author)} created a merge request:
-
%p.details
- = merge_path_description(@merge_request, '→')
+ #{link_to @merge_request.author_name, user_url(@merge_request.author)} created a merge request:
-- if @merge_request.assignees.any?
- %p
+%p
+ .branch
+ = merge_path_description(@merge_request, 'to')
+ .author
+ Author #{@merge_request.author_name}
+ .assignee
= assignees_label(@merge_request)
-
-= render_if_exists 'notify/merge_request_approvers', presenter: @mr_presenter
+ .approvers
+ = render_if_exists 'notify/merge_request_approvers', presenter: @mr_presenter
- if @merge_request.description
%div
diff --git a/app/views/notify/new_merge_request_email.text.erb b/app/views/notify/new_merge_request_email.text.erb
index e6c42f1cf5f..c3f2902c78a 100644
--- a/app/views/notify/new_merge_request_email.text.erb
+++ b/app/views/notify/new_merge_request_email.text.erb
@@ -1,9 +1,7 @@
-New Merge Request <%= @merge_request.to_reference %>
-
-<%= url_for(project_merge_request_url(@merge_request.target_project, @merge_request)) %>
+<%= @merge_request.author_name %> <%= 'created a merge request:' %> <%= url_for(project_merge_request_url(@merge_request.target_project, @merge_request)) %>
<%= merge_path_description(@merge_request, 'to') %>
-Author: <%= @merge_request.author_name %>
+<%= 'Author' %>: <%= @merge_request.author_name %>
<%= assignees_label(@merge_request) %>
<%= render_if_exists 'notify/merge_request_approvers', presenter: @mr_presenter %>
diff --git a/app/views/projects/branches/_branch.html.haml b/app/views/projects/branches/_branch.html.haml
index a5eaae2dff4..3638334d61c 100644
--- a/app/views/projects/branches/_branch.html.haml
+++ b/app/views/projects/branches/_branch.html.haml
@@ -1,6 +1,5 @@
- merged = local_assigns.fetch(:merged, false)
- commit = @repository.commit(branch.dereferenced_target)
-- bar_graph_width_factor = @max_commits > 0 ? 100.0/@max_commits : 0
- diverging_commit_counts = @repository.diverging_commit_counts(branch)
- number_commits_distance = diverging_commit_counts[:distance]
- number_commits_behind = diverging_commit_counts[:behind]
@@ -31,23 +30,7 @@
= s_('Branches|Cant find HEAD commit for this branch')
- if branch.name != @repository.root_ref
- - if number_commits_distance.nil?
- .divergence-graph.d-none.d-md-block{ title: s_('%{number_commits_behind} commits behind %{default_branch}, %{number_commits_ahead} commits ahead') % { number_commits_behind: diverging_count_label(number_commits_behind),
- default_branch: @repository.root_ref,
- number_commits_ahead: diverging_count_label(number_commits_ahead) } }
- .graph-side
- .bar.bar-behind{ style: "width: #{number_commits_behind * bar_graph_width_factor}%" }
- %span.count.count-behind= diverging_count_label(number_commits_behind)
- .graph-separator
- .graph-side
- .bar.bar-ahead{ style: "width: #{number_commits_ahead * bar_graph_width_factor}%" }
- %span.count.count-ahead= diverging_count_label(number_commits_ahead)
- - else
- .divergence-graph.d-none.d-md-block{ title: s_('More than %{number_commits_distance} commits different with %{default_branch}') % { number_commits_distance: diverging_count_label(number_commits_distance),
- default_branch: @repository.root_ref} }
- .graph-side.full
- .bar{ style: "width: #{number_commits_distance * bar_graph_width_factor}%" }
- %span.count= diverging_count_label(number_commits_distance)
+ .js-branch-divergence-graph{ data: { distance: number_commits_distance, ahead_count: number_commits_ahead, behind_count: number_commits_behind, default_branch: @repository.root_ref, max_commits: @max_commits } }
.controls.d-none.d-md-block<
- if merge_project && create_mr_button?(@repository.root_ref, branch.name)
@@ -56,7 +39,7 @@
- if branch.name != @repository.root_ref
= link_to project_compare_path(@project, @repository.root_ref, branch.name),
- class: "btn btn-default #{'prepend-left-10' unless merge_project}",
+ class: "btn btn-default js-onboarding-compare-branches #{'prepend-left-10' unless merge_project}",
title: s_('Branches|Compare') do
= s_('Branches|Compare')
diff --git a/app/views/projects/commits/_commit.html.haml b/app/views/projects/commits/_commit.html.haml
index 87b9920e8b4..2c78e74be2f 100644
--- a/app/views/projects/commits/_commit.html.haml
+++ b/app/views/projects/commits/_commit.html.haml
@@ -20,9 +20,9 @@
.commit-detail.flex-list
.commit-content.qa-commit-content
- if view_details && merge_request
- = link_to commit.title, project_commit_path(project, commit.id, merge_request_iid: merge_request.iid), class: "commit-row-message item-title"
+ = link_to commit.title, project_commit_path(project, commit.id, merge_request_iid: merge_request.iid), class: "commit-row-message item-title js-onboarding-commit-item"
- else
- = link_to_markdown_field(commit, :title, link, class: "commit-row-message item-title")
+ = link_to_markdown_field(commit, :title, link, class: "commit-row-message item-title js-onboarding-commit-item")
%span.commit-row-message.d-inline.d-sm-none
&middot;
= commit.short_id
diff --git a/app/views/projects/environments/index.html.haml b/app/views/projects/environments/index.html.haml
index 99cbbc11acd..3ec92676cde 100644
--- a/app/views/projects/environments/index.html.haml
+++ b/app/views/projects/environments/index.html.haml
@@ -6,4 +6,5 @@
"can-create-environment" => can?(current_user, :create_environment, @project).to_s,
"new-environment-path" => new_project_environment_path(@project),
"help-page-path" => help_page_path("ci/environments"),
+ "deploy-boards-help-path" => help_page_path("user/project/deploy_boards", anchor: "enabling-deploy-boards"),
"css-class" => container_class } }
diff --git a/app/views/projects/issues/_issue.html.haml b/app/views/projects/issues/_issue.html.haml
index 9293aa1b309..4759991449e 100644
--- a/app/views/projects/issues/_issue.html.haml
+++ b/app/views/projects/issues/_issue.html.haml
@@ -6,7 +6,7 @@
.issuable-info-container
.issuable-main-info
.issue-title.title
- %span.issue-title-text{ dir: "auto" }
+ %span.issue-title-text.js-onboarding-issue-item{ dir: "auto" }
- if issue.confidential?
%span.has-tooltip{ title: _('Confidential') }
= confidential_icon(issue)
diff --git a/app/views/projects/issues/_new_branch.html.haml b/app/views/projects/issues/_new_branch.html.haml
index 457b2936278..52bb797b5b3 100644
--- a/app/views/projects/issues/_new_branch.html.haml
+++ b/app/views/projects/issues/_new_branch.html.haml
@@ -2,6 +2,7 @@
- can_create_merge_request = can?(current_user, :create_merge_request_in, @project)
- data_action = can_create_merge_request ? 'create-mr' : 'create-branch'
- value = can_create_merge_request ? 'Create merge request' : 'Create branch'
+ - value = can_create_confidential_merge_request? ? _('Create confidential merge request') : value
- can_create_path = can_create_branch_project_issue_path(@project, @issue)
- create_mr_path = create_merge_request_project_issue_path(@project, @issue, branch_name: @issue.to_branch_name, ref: @project.default_branch)
@@ -23,12 +24,15 @@
= icon('caret-down')
.droplab-dropdown
- %ul#create-merge-request-dropdown.create-merge-request-dropdown-menu.dropdown-menu.dropdown-menu-right.gl-show-field-errors{ data: { dropdown: true } }
+ %ul#create-merge-request-dropdown.create-merge-request-dropdown-menu.dropdown-menu.dropdown-menu-right.gl-show-field-errors{ class: ("create-confidential-merge-request-dropdown-menu" if can_create_confidential_merge_request?), data: { dropdown: true } }
- if can_create_merge_request
%li.droplab-item-selected{ role: 'button', data: { value: 'create-mr', text: _('Create merge request') } }
.menu-item
= icon('check', class: 'icon')
- = _('Create merge request and branch')
+ - if can_create_confidential_merge_request?
+ = _('Create confidential merge request and branch')
+ - else
+ = _('Create merge request and branch')
%li{ class: [!can_create_merge_request && 'droplab-item-selected'], role: 'button', data: { value: 'create-branch', text: _('Create branch') } }
.menu-item
diff --git a/app/views/projects/issues/show.html.haml b/app/views/projects/issues/show.html.haml
index d55afee4523..8ec07dc3bb4 100644
--- a/app/views/projects/issues/show.html.haml
+++ b/app/views/projects/issues/show.html.haml
@@ -91,7 +91,7 @@
= render 'award_emoji/awards_block', awardable: @issue, inline: true
.col-md-12.col-lg-6.new-branch-col
#js-vue-discussion-filter{ data: { default_filter: current_user&.notes_filter_for(@issue), notes_filters: UserPreference.notes_filters.to_json } }
- = render 'new_branch' unless @issue.confidential?
+ = render 'new_branch' if show_new_branch_button?
= render_if_exists 'projects/issues/discussion'
diff --git a/app/views/projects/merge_requests/_merge_request.html.haml b/app/views/projects/merge_requests/_merge_request.html.haml
index 67e5e4ca62d..eb516684e52 100644
--- a/app/views/projects/merge_requests/_merge_request.html.haml
+++ b/app/views/projects/merge_requests/_merge_request.html.haml
@@ -6,7 +6,7 @@
.issuable-info-container
.issuable-main-info
.merge-request-title.title
- %span.merge-request-title-text
+ %span.merge-request-title-text.js-onboarding-mr-item
= link_to merge_request.title, merge_request_path(merge_request)
- if merge_request.tasks?
%span.task-status.d-none.d-sm-inline-block
diff --git a/app/views/projects/pages_domains/_form.html.haml b/app/views/projects/pages_domains/_form.html.haml
index 33f2166480b..5b657966909 100644
--- a/app/views/projects/pages_domains/_form.html.haml
+++ b/app/views/projects/pages_domains/_form.html.haml
@@ -11,7 +11,7 @@
- if Gitlab.config.pages.external_https
- - auto_ssl_available = Feature.enabled?(:pages_auto_ssl)
+ - auto_ssl_available = ::Gitlab::LetsEncrypt.enabled?(@domain)
- auto_ssl_enabled = @domain.auto_ssl_enabled?
- auto_ssl_available_and_enabled = auto_ssl_available && auto_ssl_enabled
@@ -38,40 +38,24 @@
- docs_link_end = "</a>".html_safe
= _("Let's Encrypt is a free, automated, and open certificate authority (CA) that gives digital certificates in order to enable HTTPS (SSL/TLS) for websites. Learn more about Let's Encrypt configuration by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}.").html_safe % { docs_link_url: docs_link_url, docs_link_start: docs_link_start, docs_link_end: docs_link_end }
- .js-shown-if-auto-ssl{ class: ("d-none" unless auto_ssl_available_and_enabled) }
- .form-group.row
- .col-sm-2.col-form-label
- = f.label :certificate, _("Certificate (PEM)")
- .col-sm-10
- - if auto_ssl_available_and_enabled && !@domain.certificate.empty?
- = f.text_area :certificate,
- rows: 5,
- class: "form-control",
- disabled: true
- %span.help-inline.text-muted= _("This certificate is automatically managed by Let's Encrypt")
- - else
- %p.text-secondary.form-control-plaintext= _("The certificate will be shown here once it has been obtained from Let's Encrypt. This process may take up to an hour to complete.")
-
.js-shown-unless-auto-ssl{ class: ("d-none" if auto_ssl_available_and_enabled) }
.form-group.row
.col-sm-2.col-form-label
- = f.label :certificate, _("Certificate (PEM)")
+ = f.label :user_provided_certificate, _("Certificate (PEM)")
.col-sm-10
- = f.text_area :certificate,
+ = f.text_area :user_provided_certificate,
rows: 5,
class: "form-control js-enabled-unless-auto-ssl",
- value: (@domain.certificate unless auto_ssl_available_and_enabled),
disabled: auto_ssl_available_and_enabled
%span.help-inline.text-muted= _("Upload a certificate for your domain with all intermediates")
.form-group.row
.col-sm-2.col-form-label
- = f.label :key, _("Key (PEM)")
+ = f.label :user_provided_key, _("Key (PEM)")
.col-sm-10
- = f.text_area :key,
+ = f.text_area :user_provided_key,
rows: 5,
class: "form-control js-enabled-unless-auto-ssl",
- value: (@domain.key unless auto_ssl_available_and_enabled),
disabled: auto_ssl_available_and_enabled
%span.help-inline.text-muted= _("Upload a private key for your certificate")
diff --git a/app/views/projects/services/_form.html.haml b/app/views/projects/services/_form.html.haml
index aa30ebdc3b8..de1b95692d6 100644
--- a/app/views/projects/services/_form.html.haml
+++ b/app/views/projects/services/_form.html.haml
@@ -4,7 +4,7 @@
= @service.title
= boolean_to_icon @service.activated?
- %p= @service.description
+ %p= #{@service.description}.
- if @service.respond_to?(:detailed_description)
%p= @service.detailed_description
diff --git a/app/views/search/results/_wiki_blob.html.haml b/app/views/search/results/_wiki_blob.html.haml
index 5847751b268..b351ecd4edf 100644
--- a/app/views/search/results/_wiki_blob.html.haml
+++ b/app/views/search/results/_wiki_blob.html.haml
@@ -1,5 +1,5 @@
- project = find_project_for_result_blob(projects, wiki_blob)
- wiki_blob = parse_search_result(wiki_blob)
-- wiki_blob_link = project_wiki_path(project, Pathname.new(wiki_blob.filename).sub_ext(''))
+- wiki_blob_link = project_wiki_path(project, wiki_blob.basename)
= render partial: 'search/results/blob_data', locals: { blob: wiki_blob, project: project, file_name: wiki_blob.filename, blob_link: wiki_blob_link }
diff --git a/app/views/shared/boards/components/sidebar/_time_tracker.html.haml b/app/views/shared/boards/components/sidebar/_time_tracker.html.haml
index b76d44c5907..43081499920 100644
--- a/app/views/shared/boards/components/sidebar/_time_tracker.html.haml
+++ b/app/views/shared/boards/components/sidebar/_time_tracker.html.haml
@@ -3,4 +3,5 @@
":time-spent" => "issue.timeSpent || 0",
":human-time-estimate" => "issue.humanTimeEstimate",
":human-time-spent" => "issue.humanTimeSpent",
+ ":limit-to-hours" => "timeTrackingLimitToHours",
"root-path" => "#{root_url}" }
diff --git a/app/views/shared/milestones/_sidebar.html.haml b/app/views/shared/milestones/_sidebar.html.haml
index b24075c7849..ced6af50501 100644
--- a/app/views/shared/milestones/_sidebar.html.haml
+++ b/app/views/shared/milestones/_sidebar.html.haml
@@ -93,7 +93,11 @@
= milestone.issues_visible_to_user(current_user).closed.count
.block
- #issuable-time-tracker{ data: { time_estimate: @milestone.total_issue_time_estimate, time_spent: @milestone.total_issue_time_spent, human_time_estimate: @milestone.human_total_issue_time_estimate, human_time_spent: @milestone.human_total_issue_time_spent } }
+ #issuable-time-tracker{ data: { time_estimate: @milestone.total_issue_time_estimate,
+ time_spent: @milestone.total_issue_time_spent,
+ human_time_estimate: @milestone.human_total_issue_time_estimate,
+ human_time_spent: @milestone.human_total_issue_time_spent,
+ limit_to_hours: Gitlab::CurrentSettings.time_tracking_limit_to_hours.to_s } }
// Fallback while content is loading
.title.hide-collapsed
= _('Time tracking')
diff --git a/app/workers/all_queues.yml b/app/workers/all_queues.yml
index fd0cc5fb24e..e55962b629e 100644
--- a/app/workers/all_queues.yml
+++ b/app/workers/all_queues.yml
@@ -9,6 +9,7 @@
- cronjob:import_export_project_cleanup
- cronjob:pages_domain_verification_cron
- cronjob:pages_domain_removal_cron
+- cronjob:pages_domain_ssl_renewal_cron
- cronjob:pipeline_schedule
- cronjob:prune_old_events
- cronjob:remove_expired_group_links
@@ -133,6 +134,7 @@
- new_note
- pages
- pages_domain_verification
+- pages_domain_ssl_renewal
- plugin
- post_receive
- process_commit
diff --git a/app/workers/build_success_worker.rb b/app/workers/build_success_worker.rb
index 9a865fea621..ac947f3cf38 100644
--- a/app/workers/build_success_worker.rb
+++ b/app/workers/build_success_worker.rb
@@ -9,7 +9,6 @@ class BuildSuccessWorker
# rubocop: disable CodeReuse/ActiveRecord
def perform(build_id)
Ci::Build.find_by(id: build_id).try do |build|
- create_deployment(build) if build.has_environment?
stop_environment(build) if build.stops_environment?
end
end
@@ -18,17 +17,6 @@ class BuildSuccessWorker
private
##
- # Deprecated:
- # As of 11.5, we started creating a deployment record when ci_builds record is created.
- # Therefore we no longer need to create a deployment, after a build succeeded.
- # We're leaving this code for the transition period, but we can remove this code in 11.6.
- def create_deployment(build)
- build.create_deployment.try do |deployment|
- deployment.succeed
- end
- end
-
- ##
# TODO: This should be processed in DeploymentSuccessWorker once we started storing `action` value in `deployments` records
def stop_environment(build)
build.persisted_environment.fire_state_event(:stop)
diff --git a/app/workers/cluster_provision_worker.rb b/app/workers/cluster_provision_worker.rb
index 926ae2b7286..59de7903c1c 100644
--- a/app/workers/cluster_provision_worker.rb
+++ b/app/workers/cluster_provision_worker.rb
@@ -9,8 +9,6 @@ class ClusterProvisionWorker
cluster.provider.try do |provider|
Clusters::Gcp::ProvisionService.new.execute(provider) if cluster.gcp?
end
-
- ClusterConfigureWorker.perform_async(cluster.id) if cluster.user?
end
end
end
diff --git a/app/workers/pages_domain_ssl_renewal_cron_worker.rb b/app/workers/pages_domain_ssl_renewal_cron_worker.rb
new file mode 100644
index 00000000000..40c34d29970
--- /dev/null
+++ b/app/workers/pages_domain_ssl_renewal_cron_worker.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+class PagesDomainSslRenewalCronWorker
+ include ApplicationWorker
+ include CronjobQueue
+
+ def perform
+ PagesDomain.need_auto_ssl_renewal.find_each do |domain|
+ next unless ::Gitlab::LetsEncrypt.enabled?(domain)
+
+ PagesDomainSslRenewalWorker.perform_async(domain.id)
+ end
+ end
+end
diff --git a/app/workers/pages_domain_ssl_renewal_worker.rb b/app/workers/pages_domain_ssl_renewal_worker.rb
new file mode 100644
index 00000000000..b32458ca777
--- /dev/null
+++ b/app/workers/pages_domain_ssl_renewal_worker.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+class PagesDomainSslRenewalWorker
+ include ApplicationWorker
+
+ def perform(domain_id)
+ domain = PagesDomain.find_by_id(domain_id)
+ return unless domain&.enabled?
+ return unless ::Gitlab::LetsEncrypt.enabled?(domain)
+
+ ::PagesDomains::ObtainLetsEncryptCertificateService.new(domain).execute
+ end
+end
diff --git a/changelogs/add-name-parameter-to-project-environments-api.yml b/changelogs/add-name-parameter-to-project-environments-api.yml
new file mode 100644
index 00000000000..01d456eb75c
--- /dev/null
+++ b/changelogs/add-name-parameter-to-project-environments-api.yml
@@ -0,0 +1,5 @@
+---
+title: Add `name` and `search` parameters to project environments API
+merge_request: 29385
+author: Lee Tickett
+type: added
diff --git a/changelogs/unreleased/10088-move-code-differences-EE-to-CE.yml b/changelogs/unreleased/10088-move-code-differences-EE-to-CE.yml
deleted file mode 100644
index 1297e9712fa..00000000000
--- a/changelogs/unreleased/10088-move-code-differences-EE-to-CE.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: "Added code differnces from EE in file 'app/assets/javascripts/pages/projects/project.js' to CE"
-merge_request: 29271
-author: Michel Engelen
-type: other
diff --git a/changelogs/unreleased/10795-add-epic-tree-BE-CE-epic-graphql-support.yml b/changelogs/unreleased/10795-add-epic-tree-BE-CE-epic-graphql-support.yml
deleted file mode 100644
index 4c85d4f9acb..00000000000
--- a/changelogs/unreleased/10795-add-epic-tree-BE-CE-epic-graphql-support.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Added reference, web_path, and relative_position fields to GraphQL Issue
-merge_request: 28998
-author:
-type: changed
diff --git a/changelogs/unreleased/10798-remove-dind-req-for-dast.yml b/changelogs/unreleased/10798-remove-dind-req-for-dast.yml
deleted file mode 100644
index 33545fc7cfd..00000000000
--- a/changelogs/unreleased/10798-remove-dind-req-for-dast.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Remove dind from DAST template
-merge_request: 28083
-author:
-type: changed
diff --git a/changelogs/unreleased/10842-add-missing-environments-variable-to-the-sast-analyzer-docker-container.yml b/changelogs/unreleased/10842-add-missing-environments-variable-to-the-sast-analyzer-docker-container.yml
deleted file mode 100644
index 112b472aa3b..00000000000
--- a/changelogs/unreleased/10842-add-missing-environments-variable-to-the-sast-analyzer-docker-container.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: 'Fix: propagate all documented ENV vars to CI when using SAST'
-merge_request: 29564
-author:
-type: fixed
diff --git a/changelogs/unreleased/11105-fix-cs-with-proxy.yml b/changelogs/unreleased/11105-fix-cs-with-proxy.yml
deleted file mode 100644
index ee32427d20e..00000000000
--- a/changelogs/unreleased/11105-fix-cs-with-proxy.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix proxy support in Container Scanning
-merge_request: 27246
-author:
-type: fixed
diff --git a/changelogs/unreleased/11204-turn-off-mask-by-default.yml b/changelogs/unreleased/11204-turn-off-mask-by-default.yml
deleted file mode 100644
index 5c554e04d45..00000000000
--- a/changelogs/unreleased/11204-turn-off-mask-by-default.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Default masked to false for new variables
-merge_request: 28186
-author:
-type: changed
diff --git a/changelogs/unreleased/11609-geo-remove-support-for-using-geo-with-an-installation-from-source-docs.yml b/changelogs/unreleased/11609-geo-remove-support-for-using-geo-with-an-installation-from-source-docs.yml
deleted file mode 100644
index 6570cb3e2a3..00000000000
--- a/changelogs/unreleased/11609-geo-remove-support-for-using-geo-with-an-installation-from-source-docs.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Remove support for using Geo with an installation from source
-merge_request: 28737
-author:
-type: other
diff --git a/changelogs/unreleased/12106-sp-ce.yml b/changelogs/unreleased/12106-sp-ce.yml
deleted file mode 100644
index 2d073401b45..00000000000
--- a/changelogs/unreleased/12106-sp-ce.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Moves snowplow to CE repo
-merge_request:
-author:
-type: other
diff --git a/changelogs/unreleased/1340-request-job-with-age.yml b/changelogs/unreleased/1340-request-job-with-age.yml
deleted file mode 100644
index 766ac008c2e..00000000000
--- a/changelogs/unreleased/1340-request-job-with-age.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: "Added option to filter jobs by age in the /job/request API endpoint."
-merge_request: 1340
-author: Dmitry Chepurovskiy
-type: added
diff --git a/changelogs/unreleased/13453_minimal_atom_fix.yml b/changelogs/unreleased/13453_minimal_atom_fix.yml
deleted file mode 100644
index e0c18de3b1f..00000000000
--- a/changelogs/unreleased/13453_minimal_atom_fix.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Added a content field to atom feed
-merge_request: 27652
-author:
-type: fixed
diff --git a/changelogs/unreleased/17690-Protect-TeamCity-builds-for-triggering-when-a-branch-is-deleted-And-add-MR-option.yml b/changelogs/unreleased/17690-Protect-TeamCity-builds-for-triggering-when-a-branch-is-deleted-And-add-MR-option.yml
new file mode 100644
index 00000000000..741a0faf469
--- /dev/null
+++ b/changelogs/unreleased/17690-Protect-TeamCity-builds-for-triggering-when-a-branch-is-deleted-And-add-MR-option.yml
@@ -0,0 +1,5 @@
+---
+title: Protect TeamCity builds from triggering when a branch has been deleted. And a MR-option
+merge_request: 29836
+author: Nikolay Novikov, Raphael Tweitmann
+type: fixed
diff --git a/changelogs/unreleased/19569-include-information-if-issue-was-closed-via-mr.yml b/changelogs/unreleased/19569-include-information-if-issue-was-closed-via-mr.yml
deleted file mode 100644
index bb2fc9af2a1..00000000000
--- a/changelogs/unreleased/19569-include-information-if-issue-was-closed-via-mr.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Include information if issue was clossed via merge request or commit
-merge_request: 15610
-author: Michał Zając
-type: changed
diff --git a/changelogs/unreleased/237-style-toast-component.yml b/changelogs/unreleased/237-style-toast-component.yml
deleted file mode 100644
index 2420df0ee55..00000000000
--- a/changelogs/unreleased/237-style-toast-component.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Style the toast component according to design specs.
-merge_request: 27734
-author:
-type: added
diff --git a/changelogs/unreleased/27987-use-findorcreateservice-to-create-labels.yml b/changelogs/unreleased/27987-use-findorcreateservice-to-create-labels.yml
deleted file mode 100644
index 8d3501e0171..00000000000
--- a/changelogs/unreleased/27987-use-findorcreateservice-to-create-labels.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Use FindOrCreateService to create labels and check for existing ones
-merge_request: 27987
-author: Matt Duren
-type: fixed
diff --git a/changelogs/unreleased/28757-remove-docker-pull-prefix-when-copying-a-tag-from-the-registry.yml b/changelogs/unreleased/28757-remove-docker-pull-prefix-when-copying-a-tag-from-the-registry.yml
deleted file mode 100644
index e954b97f05b..00000000000
--- a/changelogs/unreleased/28757-remove-docker-pull-prefix-when-copying-a-tag-from-the-registry.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Remove `docker pull` prefix when copying a tag from the registry
-merge_request: 28757
-author: Benedikt Franke
-type: changed
diff --git a/changelogs/unreleased/28996-create-mvc-ui-in-haml.yml b/changelogs/unreleased/28996-create-mvc-ui-in-haml.yml
deleted file mode 100644
index 9c6897babb4..00000000000
--- a/changelogs/unreleased/28996-create-mvc-ui-in-haml.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Add auto SSL toggle option to Pages domain settings page
-merge_request: 26438
-author:
-type: added
diff --git a/changelogs/unreleased/30138-display-cycle-analytics-issue-logic-fixes.yml b/changelogs/unreleased/30138-display-cycle-analytics-issue-logic-fixes.yml
deleted file mode 100644
index 574995f20fa..00000000000
--- a/changelogs/unreleased/30138-display-cycle-analytics-issue-logic-fixes.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Change logic behind cycle analytics
-merge_request: 29018
-author:
-type: changed
diff --git a/changelogs/unreleased/30138-display-cycle-analytics-issue.yml b/changelogs/unreleased/30138-display-cycle-analytics-issue.yml
deleted file mode 100644
index c7faa0480bd..00000000000
--- a/changelogs/unreleased/30138-display-cycle-analytics-issue.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Show data on Cycle Analytics page when value is less than a second
-merge_request: 28507
-author:
-type: fixed
diff --git a/changelogs/unreleased/30355-use-hours-only-for-time-tracking.yml b/changelogs/unreleased/30355-use-hours-only-for-time-tracking.yml
new file mode 100644
index 00000000000..b0252f9e81b
--- /dev/null
+++ b/changelogs/unreleased/30355-use-hours-only-for-time-tracking.yml
@@ -0,0 +1,5 @@
+---
+title: Add option to limit time tracking units to hours
+merge_request: 29469
+author: Jon Kolb
+type: added
diff --git a/changelogs/unreleased/33064-add-labels-to-note-event-payload.yml b/changelogs/unreleased/33064-add-labels-to-note-event-payload.yml
deleted file mode 100644
index e0a6253e1ef..00000000000
--- a/changelogs/unreleased/33064-add-labels-to-note-event-payload.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Add labels to note event payload
-merge_request: 29384
-author: Sujay Patel
-type: added
diff --git a/changelogs/unreleased/35428-docker-registry-date-not-accurate.yml b/changelogs/unreleased/35428-docker-registry-date-not-accurate.yml
deleted file mode 100644
index f51ecdf83a6..00000000000
--- a/changelogs/unreleased/35428-docker-registry-date-not-accurate.yml
+++ /dev/null
@@ -1,6 +0,0 @@
----
-title: Changed the 'Created' label to 'Last Updated' on the container registry table
- to more accurately reflect what the date represents.
-merge_request: 29464
-author:
-type: other
diff --git a/changelogs/unreleased/37495.yml b/changelogs/unreleased/37495.yml
deleted file mode 100644
index f6d421fc45b..00000000000
--- a/changelogs/unreleased/37495.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Add documentation links for confidental and locked discussions
-merge_request: 29073
-author:
-type: changed
diff --git a/changelogs/unreleased/38105-pre-release-tag.yml b/changelogs/unreleased/38105-pre-release-tag.yml
new file mode 100644
index 00000000000..d4c5dcacd19
--- /dev/null
+++ b/changelogs/unreleased/38105-pre-release-tag.yml
@@ -0,0 +1,5 @@
+---
+title: Renders a pre-release tag for releases
+merge_request: 29797
+author:
+type: changed
diff --git a/changelogs/unreleased/38561-border-radii.yml b/changelogs/unreleased/38561-border-radii.yml
deleted file mode 100644
index 510af18d651..00000000000
--- a/changelogs/unreleased/38561-border-radii.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix border radii on diff files and repo files
-merge_request:
-author:
-type: fixed
diff --git a/changelogs/unreleased/39304-broadcast-message-buttons.yml b/changelogs/unreleased/39304-broadcast-message-buttons.yml
deleted file mode 100644
index 7eb289fca1f..00000000000
--- a/changelogs/unreleased/39304-broadcast-message-buttons.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Update broadcast message action icons
-merge_request: 28496
-author: Jarek Ostrowski @jareko
-type: fixed
diff --git a/changelogs/unreleased/42399-registry-confirm-deletion.yml b/changelogs/unreleased/42399-registry-confirm-deletion.yml
new file mode 100644
index 00000000000..4d720e16721
--- /dev/null
+++ b/changelogs/unreleased/42399-registry-confirm-deletion.yml
@@ -0,0 +1,5 @@
+---
+title: Add confirmation for registry image deletion
+merge_request: 29505
+author:
+type: added
diff --git a/changelogs/unreleased/45687-web-ide-empty-state.yml b/changelogs/unreleased/45687-web-ide-empty-state.yml
deleted file mode 100644
index 9ef148275ab..00000000000
--- a/changelogs/unreleased/45687-web-ide-empty-state.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Empty project state for Web IDE
-merge_request: 26556
-author:
-type: added
diff --git a/changelogs/unreleased/47846-position-is-off-when-visiting-files-with-anchors.yml b/changelogs/unreleased/47846-position-is-off-when-visiting-files-with-anchors.yml
deleted file mode 100644
index 21dc170f1ca..00000000000
--- a/changelogs/unreleased/47846-position-is-off-when-visiting-files-with-anchors.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Resolve Position is off when visiting files with anchors
-merge_request: 28913
-author:
-type: fixed
diff --git a/changelogs/unreleased/49041-issue-board-input-height.yml b/changelogs/unreleased/49041-issue-board-input-height.yml
deleted file mode 100644
index de3fbb2ee11..00000000000
--- a/changelogs/unreleased/49041-issue-board-input-height.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Reduce height of issue board input to align with buttons
-merge_request:
-author:
-type: other
diff --git a/changelogs/unreleased/49517-fix-notes-import-export.yml b/changelogs/unreleased/49517-fix-notes-import-export.yml
deleted file mode 100644
index a9f4d736e0b..00000000000
--- a/changelogs/unreleased/49517-fix-notes-import-export.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix diff notes and discussion notes being exported as regular notes
-merge_request: 28401
-author:
-type: fixed
diff --git a/changelogs/unreleased/49814-display-in-admin-area-if-emails-are-verified-or-not.yml b/changelogs/unreleased/49814-display-in-admin-area-if-emails-are-verified-or-not.yml
new file mode 100644
index 00000000000..db1391edd73
--- /dev/null
+++ b/changelogs/unreleased/49814-display-in-admin-area-if-emails-are-verified-or-not.yml
@@ -0,0 +1,5 @@
+---
+title: Add a verified pill next to email addresses under the admin users section.
+merge_request: 29669
+author:
+type: added
diff --git a/changelogs/unreleased/49915-fix-error-500-admin-projects-nil-storage.yml b/changelogs/unreleased/49915-fix-error-500-admin-projects-nil-storage.yml
deleted file mode 100644
index 307c2bfb49d..00000000000
--- a/changelogs/unreleased/49915-fix-error-500-admin-projects-nil-storage.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix an error in projects admin when statistics are missing
-merge_request: 28355
-author:
-type: fixed
diff --git a/changelogs/unreleased/50106-hide-whitespace-changes.yml b/changelogs/unreleased/50106-hide-whitespace-changes.yml
deleted file mode 100644
index e95953c8665..00000000000
--- a/changelogs/unreleased/50106-hide-whitespace-changes.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix whitespace changes visibility when the related file was initially collapsed
-merge_request: 28950
-author: Ondřej Budai
-type: fixed
diff --git a/changelogs/unreleased/50834-change-http-status-code-when-repository-disabled.yml b/changelogs/unreleased/50834-change-http-status-code-when-repository-disabled.yml
new file mode 100644
index 00000000000..b51079d5c74
--- /dev/null
+++ b/changelogs/unreleased/50834-change-http-status-code-when-repository-disabled.yml
@@ -0,0 +1,5 @@
+---
+title: "Changed HTTP Status Code for disabled repository on /branches and /commits to 404"
+merge_request: 29585
+author: Sam Battalio
+type: changed
diff --git a/changelogs/unreleased/50850-kerrizor-extend-api-to-accept-start_project-option.yml b/changelogs/unreleased/50850-kerrizor-extend-api-to-accept-start_project-option.yml
deleted file mode 100644
index 45770e1012c..00000000000
--- a/changelogs/unreleased/50850-kerrizor-extend-api-to-accept-start_project-option.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Add API support for committing changes to different projects in same fork network
-merge_request: 27915
-author:
-type: added
diff --git a/changelogs/unreleased/51022-added-extended-height-to-labels-dropdown.yml b/changelogs/unreleased/51022-added-extended-height-to-labels-dropdown.yml
deleted file mode 100644
index 07bf8b04bbe..00000000000
--- a/changelogs/unreleased/51022-added-extended-height-to-labels-dropdown.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: "Added the `.extended-height` class to the labels-dropdown"
-merge_request: 28659
-author: Michel Engelen
-type: other
diff --git a/changelogs/unreleased/51636-task-list-api-pderichs.yml b/changelogs/unreleased/51636-task-list-api-pderichs.yml
deleted file mode 100644
index f18a0936ab2..00000000000
--- a/changelogs/unreleased/51636-task-list-api-pderichs.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Add task count and completed count to responses of Issue and MR
-merge_request: 28859
-author:
-type: added
diff --git a/changelogs/unreleased/51854-api-to-get-all-project-group-members-returns-duplicates.yml b/changelogs/unreleased/51854-api-to-get-all-project-group-members-returns-duplicates.yml
deleted file mode 100644
index 4e16b95ec11..00000000000
--- a/changelogs/unreleased/51854-api-to-get-all-project-group-members-returns-duplicates.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Removes duplicated members from api/projects/:id/members/all
-merge_request: 24005
-author: Jacopo Beschi @jacopo-beschi
-type: changed
diff --git a/changelogs/unreleased/52366-improved-group-lists-ui.yml b/changelogs/unreleased/52366-improved-group-lists-ui.yml
new file mode 100644
index 00000000000..99e5b67a56c
--- /dev/null
+++ b/changelogs/unreleased/52366-improved-group-lists-ui.yml
@@ -0,0 +1,5 @@
+---
+title: Improve group list UI
+merge_request: 26542
+author:
+type: changed
diff --git a/changelogs/unreleased/53134-multiple-extendes-for-a-job.yml b/changelogs/unreleased/53134-multiple-extendes-for-a-job.yml
deleted file mode 100644
index e09de8ac8fc..00000000000
--- a/changelogs/unreleased/53134-multiple-extendes-for-a-job.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Add support for multiple job parents in GitLab CI YAML.
-merge_request: 26801
-author: Wolphin (Nikita)
-type: added
diff --git a/changelogs/unreleased/54140-non-ar-cache-commit-markdown.yml b/changelogs/unreleased/54140-non-ar-cache-commit-markdown.yml
deleted file mode 100644
index efda07380a4..00000000000
--- a/changelogs/unreleased/54140-non-ar-cache-commit-markdown.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Use Redis for CacheMarkDownField on non AR models
-merge_request: 29054
-author:
-type: performance
diff --git a/changelogs/unreleased/54169-flash-warning-rebrush.yml b/changelogs/unreleased/54169-flash-warning-rebrush.yml
deleted file mode 100644
index 420cc26a8cc..00000000000
--- a/changelogs/unreleased/54169-flash-warning-rebrush.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: "Rebrush of flash-warning according to the new design (brighter background and darker font)"
-merge_request: 28916
-author: Michel Engelen
-type: changed
diff --git a/changelogs/unreleased/55033-discussion-system-note-alignment.yml b/changelogs/unreleased/55033-discussion-system-note-alignment.yml
deleted file mode 100644
index 27072ec7e12..00000000000
--- a/changelogs/unreleased/55033-discussion-system-note-alignment.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Align system note within discussion with other notes
-merge_request:
-author:
-type: fixed
diff --git a/changelogs/unreleased/55125-mr-tab-scrolling.yml b/changelogs/unreleased/55125-mr-tab-scrolling.yml
deleted file mode 100644
index e03ff6c5060..00000000000
--- a/changelogs/unreleased/55125-mr-tab-scrolling.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Update merge request tabs so they no longer scroll
-merge_request:
-author:
-type: other
diff --git a/changelogs/unreleased/55253-activity-feed-ui-enhance-line-height.yml b/changelogs/unreleased/55253-activity-feed-ui-enhance-line-height.yml
deleted file mode 100644
index f7dd8c59a7c..00000000000
--- a/changelogs/unreleased/55253-activity-feed-ui-enhance-line-height.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Enhance line-height of Activity feed UI
-merge_request: 28856
-author: Jacopo Beschi @jacopo-beschi
-type: changed
diff --git a/changelogs/unreleased/55362-refresh-blank-service-account-token.yml b/changelogs/unreleased/55362-refresh-blank-service-account-token.yml
deleted file mode 100644
index 3189de97e8b..00000000000
--- a/changelogs/unreleased/55362-refresh-blank-service-account-token.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Refresh service_account_token for kubernetes_namespaces
-merge_request: 29657
-author:
-type: fixed
diff --git a/changelogs/unreleased/55447-validate-k8s-credentials.yml b/changelogs/unreleased/55447-validate-k8s-credentials.yml
deleted file mode 100644
index 81f0efdb325..00000000000
--- a/changelogs/unreleased/55447-validate-k8s-credentials.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Validate Kubernetes credentials at cluster creation
-merge_request: 27403
-author:
-type: added
diff --git a/changelogs/unreleased/5615-non-admins-only-archieve-ce.yml b/changelogs/unreleased/5615-non-admins-only-archieve-ce.yml
deleted file mode 100644
index ac1aa249b82..00000000000
--- a/changelogs/unreleased/5615-non-admins-only-archieve-ce.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Add deletion protection setting column to application_settings table
-merge_request: 29268
-author:
-type: other
diff --git a/changelogs/unreleased/56737-commits-and-mr-events-on-jira-api.yml b/changelogs/unreleased/56737-commits-and-mr-events-on-jira-api.yml
deleted file mode 100644
index ee2ce8acaeb..00000000000
--- a/changelogs/unreleased/56737-commits-and-mr-events-on-jira-api.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Expose all current events properly on services API
-merge_request: 29736
-author: Zsolt Kovari
-type: fixed
diff --git a/changelogs/unreleased/56959-drop-project_auto_devops_domain.yml b/changelogs/unreleased/56959-drop-project_auto_devops_domain.yml
deleted file mode 100644
index c529749670d..00000000000
--- a/changelogs/unreleased/56959-drop-project_auto_devops_domain.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Removes project_auto_devops#domain column
-merge_request: 28574
-author:
-type: other
diff --git a/changelogs/unreleased/56959-remove-auto-devops-domain-ci-variable.yml b/changelogs/unreleased/56959-remove-auto-devops-domain-ci-variable.yml
deleted file mode 100644
index c1c1708f935..00000000000
--- a/changelogs/unreleased/56959-remove-auto-devops-domain-ci-variable.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Removes support for AUTO_DEVOPS_DOMAIN
-merge_request: 28460
-author:
-type: removed
diff --git a/changelogs/unreleased/57037-fix-mr-checkboxes-mobile-alignment.yml b/changelogs/unreleased/57037-fix-mr-checkboxes-mobile-alignment.yml
deleted file mode 100644
index a2de6cd6d45..00000000000
--- a/changelogs/unreleased/57037-fix-mr-checkboxes-mobile-alignment.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix Merge Request merge checkbox alignment on mobile view
-merge_request: 28845
-author:
-type: fixed
diff --git a/changelogs/unreleased/57189-css-label-in-forms-with-bootstrap4.yml b/changelogs/unreleased/57189-css-label-in-forms-with-bootstrap4.yml
deleted file mode 100644
index 86b6bb20253..00000000000
--- a/changelogs/unreleased/57189-css-label-in-forms-with-bootstrap4.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix col-sm-* in forms to keep layout
-merge_request: 24885
-author: Takuya Noguchi
-type: fixed
diff --git a/changelogs/unreleased/57813-merge-request-tabs-do-not-handle-ctrl-click-correctly.yml b/changelogs/unreleased/57813-merge-request-tabs-do-not-handle-ctrl-click-correctly.yml
deleted file mode 100644
index 272faa67fcf..00000000000
--- a/changelogs/unreleased/57813-merge-request-tabs-do-not-handle-ctrl-click-correctly.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Allow command/control click to open link in new tab on Merge Request tabs
-merge_request: 29506
-author:
-type: fixed
diff --git a/changelogs/unreleased/57825-moving-an-issue-results-in-broken-image-links-in-comments.yml b/changelogs/unreleased/57825-moving-an-issue-results-in-broken-image-links-in-comments.yml
deleted file mode 100644
index faa1784ea21..00000000000
--- a/changelogs/unreleased/57825-moving-an-issue-results-in-broken-image-links-in-comments.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Resolve moving an issue results in broken image links in comments
-merge_request: 28654
-author:
-type: fixed
diff --git a/changelogs/unreleased/58065-uniform-html-txt-email.yml b/changelogs/unreleased/58065-uniform-html-txt-email.yml
new file mode 100644
index 00000000000..be34e93ff83
--- /dev/null
+++ b/changelogs/unreleased/58065-uniform-html-txt-email.yml
@@ -0,0 +1,5 @@
+---
+title: Always shows author of created issue/started discussion/comment in HTML body and text of email
+merge_request: 29886
+author: Frank van Rest
+type: fixed
diff --git a/changelogs/unreleased/58269-separate-update-patch.yml b/changelogs/unreleased/58269-separate-update-patch.yml
deleted file mode 100644
index e9b44257b07..00000000000
--- a/changelogs/unreleased/58269-separate-update-patch.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Do not display Update app button when saving Knative domain name
-merge_request: 28904
-author:
-type: changed
diff --git a/changelogs/unreleased/58297-remove-extraneous-gitaly-calls-from-md-rendering.yml b/changelogs/unreleased/58297-remove-extraneous-gitaly-calls-from-md-rendering.yml
deleted file mode 100644
index 25cc973159f..00000000000
--- a/changelogs/unreleased/58297-remove-extraneous-gitaly-calls-from-md-rendering.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Reduce Gitaly calls to improve performance when rendering suggestions
-merge_request: 29027
-author:
-type: performance
diff --git a/changelogs/unreleased/58404-set-default-max-depth-for-GraphQL.yml b/changelogs/unreleased/58404-set-default-max-depth-for-GraphQL.yml
deleted file mode 100644
index 7e95158a0e0..00000000000
--- a/changelogs/unreleased/58404-set-default-max-depth-for-GraphQL.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: 58404 - setup max depth for GraphQL
-merge_request: 25737
-author: Ken Ding
-type: added
diff --git a/changelogs/unreleased/58433-email-notifications-do-not-work-properly-issue-due-date.yml b/changelogs/unreleased/58433-email-notifications-do-not-work-properly-issue-due-date.yml
deleted file mode 100644
index 4579721446a..00000000000
--- a/changelogs/unreleased/58433-email-notifications-do-not-work-properly-issue-due-date.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix email notifications for user excluded actions
-merge_request: 28835
-author:
-type: fixed
diff --git a/changelogs/unreleased/58538-discussion-top-radius.yml b/changelogs/unreleased/58538-discussion-top-radius.yml
deleted file mode 100644
index 0fb16055623..00000000000
--- a/changelogs/unreleased/58538-discussion-top-radius.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix border radius of discussions
-merge_request: 28490
-author:
-type: fixed
diff --git a/changelogs/unreleased/58632-fix-mr-widget-padding.yml b/changelogs/unreleased/58632-fix-mr-widget-padding.yml
deleted file mode 100644
index fb4e1791359..00000000000
--- a/changelogs/unreleased/58632-fix-mr-widget-padding.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix padding in MR widget
-merge_request: 28472
-author:
-type: fixed
diff --git a/changelogs/unreleased/58941-use-gitlab-serverless-with-existing-knative-installation.yml b/changelogs/unreleased/58941-use-gitlab-serverless-with-existing-knative-installation.yml
deleted file mode 100644
index 53be008816d..00000000000
--- a/changelogs/unreleased/58941-use-gitlab-serverless-with-existing-knative-installation.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Enable function features for external Knative installations
-merge_request: 27173
-author:
-type: changed
diff --git a/changelogs/unreleased/58984-doc-missing-milestones-and-labels-links.yml b/changelogs/unreleased/58984-doc-missing-milestones-and-labels-links.yml
deleted file mode 100644
index 6b74303c16e..00000000000
--- a/changelogs/unreleased/58984-doc-missing-milestones-and-labels-links.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Document when milestones and labels links are missing
-merge_request: 29355
-author:
-type: other
diff --git a/changelogs/unreleased/59023-fix-web-ide-creating-branches-off-new-commits.yml b/changelogs/unreleased/59023-fix-web-ide-creating-branches-off-new-commits.yml
deleted file mode 100644
index f7e0ee333aa..00000000000
--- a/changelogs/unreleased/59023-fix-web-ide-creating-branches-off-new-commits.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix IDE commit using latest ref in branch and overriding contents
-merge_request: 29769
-author:
-type: fixed
diff --git a/changelogs/unreleased/59026-replace-favicon.yml b/changelogs/unreleased/59026-replace-favicon.yml
deleted file mode 100644
index 34228bb8438..00000000000
--- a/changelogs/unreleased/59026-replace-favicon.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Update favicon from next
-merge_request: 28601
-author: Jarek Ostrowski @jareko
-type: fixed
diff --git a/changelogs/unreleased/59028-fix-extra-plus-in-diffs.yml b/changelogs/unreleased/59028-fix-extra-plus-in-diffs.yml
new file mode 100644
index 00000000000..0786f4dbc10
--- /dev/null
+++ b/changelogs/unreleased/59028-fix-extra-plus-in-diffs.yml
@@ -0,0 +1,5 @@
+---
+title: Remove duplicate trailing +/- char in merge request discussions
+merge_request: 29518
+author:
+type: fixed
diff --git a/changelogs/unreleased/59105-padding-unclickable-pipeline-job.yml b/changelogs/unreleased/59105-padding-unclickable-pipeline-job.yml
deleted file mode 100644
index 95f08af3cb1..00000000000
--- a/changelogs/unreleased/59105-padding-unclickable-pipeline-job.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix padding of unclickable pipeline dropdown items to match links
-merge_request:
-author:
-type: fixed
diff --git a/changelogs/unreleased/59376-Report-abuse-to-GitLab-should-be-Report-abuse-in-non-gitlab-com-instances.yml b/changelogs/unreleased/59376-Report-abuse-to-GitLab-should-be-Report-abuse-in-non-gitlab-com-instances.yml
deleted file mode 100644
index 0904f788b6f..00000000000
--- a/changelogs/unreleased/59376-Report-abuse-to-GitLab-should-be-Report-abuse-in-non-gitlab-com-instances.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Change "Report abuse to GitLab" to more generic wording
-merge_request: 28884
-author: Marc Schwede
-type: other
diff --git a/changelogs/unreleased/59587-add-graphql-logging.yml b/changelogs/unreleased/59587-add-graphql-logging.yml
deleted file mode 100644
index 74c2a734f37..00000000000
--- a/changelogs/unreleased/59587-add-graphql-logging.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Add dedicated logging for GraphQL queries
-merge_request: 27885
-author:
-type: other
diff --git a/changelogs/unreleased/59651-remove-unnecessary-decimal-places-on-chart-axes.yml b/changelogs/unreleased/59651-remove-unnecessary-decimal-places-on-chart-axes.yml
deleted file mode 100644
index fea34099135..00000000000
--- a/changelogs/unreleased/59651-remove-unnecessary-decimal-places-on-chart-axes.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Remove unnecessary decimals on Metrics chart axis
-merge_request: 29468
-author:
-type: fixed
diff --git a/changelogs/unreleased/59987-move-sign-in-2fa-on-users-sign_in-above-intro-content-on-mobile.yml b/changelogs/unreleased/59987-move-sign-in-2fa-on-users-sign_in-above-intro-content-on-mobile.yml
deleted file mode 100644
index 7863f1f7bbe..00000000000
--- a/changelogs/unreleased/59987-move-sign-in-2fa-on-users-sign_in-above-intro-content-on-mobile.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Prioritize login form on mobile breakpoint
-merge_request: 28360
-author:
-type: changed
diff --git a/changelogs/unreleased/60034-default-web-ide-s-merge-request-checkbox-to-true.yml b/changelogs/unreleased/60034-default-web-ide-s-merge-request-checkbox-to-true.yml
deleted file mode 100644
index fdf80c660f7..00000000000
--- a/changelogs/unreleased/60034-default-web-ide-s-merge-request-checkbox-to-true.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Default MR checkbox to true in most cases
-merge_request: !28665
-author:
-type: changed
diff --git a/changelogs/unreleased/60180-jira-service-fix-nil-on-find-call.yml b/changelogs/unreleased/60180-jira-service-fix-nil-on-find-call.yml
deleted file mode 100644
index 6891a9ca83c..00000000000
--- a/changelogs/unreleased/60180-jira-service-fix-nil-on-find-call.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: 'Resolved JIRA service: NoMethodError: undefined method ''find'' for nil:NilClass'
-merge_request: 28206
-author:
-type: fixed
diff --git a/changelogs/unreleased/60250-remove-mr_push_options-flag.yml b/changelogs/unreleased/60250-remove-mr_push_options-flag.yml
deleted file mode 100644
index b429d83dcc7..00000000000
--- a/changelogs/unreleased/60250-remove-mr_push_options-flag.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Remove the mr_push_options feature flag
-merge_request: 28278
-author:
-type: changed
diff --git a/changelogs/unreleased/60303-replace-sidekiq-mtail-metrics.yml b/changelogs/unreleased/60303-replace-sidekiq-mtail-metrics.yml
deleted file mode 100644
index 90b72ec05c7..00000000000
--- a/changelogs/unreleased/60303-replace-sidekiq-mtail-metrics.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Replaces sidekiq mtail metrics with ruby instrumentation metrics
-merge_request: 29215
-author:
-type: changed
diff --git a/changelogs/unreleased/60323-inline-validation-for-users-name-and-username-length.yml b/changelogs/unreleased/60323-inline-validation-for-users-name-and-username-length.yml
deleted file mode 100644
index 83b7bd3433e..00000000000
--- a/changelogs/unreleased/60323-inline-validation-for-users-name-and-username-length.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Update registration form to indicate invalid name or username length on input
-merge_request: 28095
-author: Jiaan Louw
-type: changed
diff --git a/changelogs/unreleased/60379-remove-ci-preparing-state-feature-flag.yml b/changelogs/unreleased/60379-remove-ci-preparing-state-feature-flag.yml
deleted file mode 100644
index a9b7aeb3024..00000000000
--- a/changelogs/unreleased/60379-remove-ci-preparing-state-feature-flag.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Remove ability for group clusters to be automatically configured on creation
-merge_request: 27245
-author:
-type: removed
diff --git a/changelogs/unreleased/60425-fix-500-when-accessing-charts-with-anonymous-user.yml b/changelogs/unreleased/60425-fix-500-when-accessing-charts-with-anonymous-user.yml
deleted file mode 100644
index 4274dc5918c..00000000000
--- a/changelogs/unreleased/60425-fix-500-when-accessing-charts-with-anonymous-user.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: "Fix 500 error when accessing charts with an anonymous user"
-merge_request: 28091
-author: Diego Silva
-type: fixed
diff --git a/changelogs/unreleased/60617-allow-switching-from-gitlab-managed-to-unmanaged-clusters.yml b/changelogs/unreleased/60617-allow-switching-from-gitlab-managed-to-unmanaged-clusters.yml
deleted file mode 100644
index 1127dde4fcf..00000000000
--- a/changelogs/unreleased/60617-allow-switching-from-gitlab-managed-to-unmanaged-clusters.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Allow switching clusters between managed and unmanaged
-merge_request: 29322
-author:
-type: added
diff --git a/changelogs/unreleased/60617-enable-project-cluster-jit.yml b/changelogs/unreleased/60617-enable-project-cluster-jit.yml
new file mode 100644
index 00000000000..b7d745d4385
--- /dev/null
+++ b/changelogs/unreleased/60617-enable-project-cluster-jit.yml
@@ -0,0 +1,5 @@
+---
+title: Enable just-in-time Kubernetes resource creation for project-level clusters
+merge_request: 29515
+author:
+type: changed
diff --git a/changelogs/unreleased/60750-milestone-header.yml b/changelogs/unreleased/60750-milestone-header.yml
deleted file mode 100644
index 62cfdaf6ea7..00000000000
--- a/changelogs/unreleased/60750-milestone-header.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix layout of group milestone header
-merge_request:
-author:
-type: fixed
diff --git a/changelogs/unreleased/60818_yamllint_project_root.yml b/changelogs/unreleased/60818_yamllint_project_root.yml
deleted file mode 100644
index b34a50e6a9c..00000000000
--- a/changelogs/unreleased/60818_yamllint_project_root.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix yaml linting for project root *.yml files
-merge_request: 27579
-author: Will Hall
-type: fixed
diff --git a/changelogs/unreleased/60819_yamllint_gitlabci.yml b/changelogs/unreleased/60819_yamllint_gitlabci.yml
deleted file mode 100644
index aba3b206f7e..00000000000
--- a/changelogs/unreleased/60819_yamllint_gitlabci.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix yaml linting for GitLab CI inside project (.gitlab/ci) *.yml files and CI template files
-merge_request: 27576
-author: Will Hall
-type: fixed
diff --git a/changelogs/unreleased/60879-fix-reports-timing-out.yml b/changelogs/unreleased/60879-fix-reports-timing-out.yml
new file mode 100644
index 00000000000..845162fe10f
--- /dev/null
+++ b/changelogs/unreleased/60879-fix-reports-timing-out.yml
@@ -0,0 +1,5 @@
+---
+title: Fix reports jobs timing out because of cache
+merge_request: 29780
+author:
+type: fixed
diff --git a/changelogs/unreleased/609120-ref-link.yml b/changelogs/unreleased/609120-ref-link.yml
deleted file mode 100644
index 97c93b7ff53..00000000000
--- a/changelogs/unreleased/609120-ref-link.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fixes Ref link being displayed as raw HTML in the Pipelines page
-merge_request: 28823
-author:
-type: fixed
diff --git a/changelogs/unreleased/60987-emoji-picker-popup.yml b/changelogs/unreleased/60987-emoji-picker-popup.yml
deleted file mode 100644
index 3bccec8e164..00000000000
--- a/changelogs/unreleased/60987-emoji-picker-popup.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix emoji picker visibility issue
-merge_request: 28984
-author:
-type: fixed
diff --git a/changelogs/unreleased/61024-update-resolved-icon.yml b/changelogs/unreleased/61024-update-resolved-icon.yml
deleted file mode 100644
index 4a4de9eb13a..00000000000
--- a/changelogs/unreleased/61024-update-resolved-icon.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Add check circle filled icon for resolved comments
-merge_request: 28663
-author:
-type: changed
diff --git a/changelogs/unreleased/6104-ee-ce-difference.yml b/changelogs/unreleased/6104-ee-ce-difference.yml
deleted file mode 100644
index 59d31daf0eb..00000000000
--- a/changelogs/unreleased/6104-ee-ce-difference.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Unified EE/CS differences in repository/show.html
-merge_request: 13562
-author:
-type: other
diff --git a/changelogs/unreleased/61045-charts-with-many-overlapping-series-display-incorrectly.yml b/changelogs/unreleased/61045-charts-with-many-overlapping-series-display-incorrectly.yml
deleted file mode 100644
index 53cc0a15417..00000000000
--- a/changelogs/unreleased/61045-charts-with-many-overlapping-series-display-incorrectly.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Eliminate color inconsistencies in metric graphs
-merge_request: 29127
-author:
-type: fixed
diff --git a/changelogs/unreleased/61049-links-activity-stream.yml b/changelogs/unreleased/61049-links-activity-stream.yml
deleted file mode 100644
index 3aac84adc31..00000000000
--- a/changelogs/unreleased/61049-links-activity-stream.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Use blue for activity stream links; use monospace font for commit sha
-merge_request:
-author:
-type: other
diff --git a/changelogs/unreleased/61072-link-to-user-profile-not-distinguishable-on-latest-commit-widget.yml b/changelogs/unreleased/61072-link-to-user-profile-not-distinguishable-on-latest-commit-widget.yml
deleted file mode 100644
index 5285ac767cc..00000000000
--- a/changelogs/unreleased/61072-link-to-user-profile-not-distinguishable-on-latest-commit-widget.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: User link styling for commits
-merge_request: 29150
-author:
-type: other
diff --git a/changelogs/unreleased/61144-style-secondary-button-type-to-be-aligned-with-pattern-library.yml b/changelogs/unreleased/61144-style-secondary-button-type-to-be-aligned-with-pattern-library.yml
deleted file mode 100644
index ed4cf0507c7..00000000000
--- a/changelogs/unreleased/61144-style-secondary-button-type-to-be-aligned-with-pattern-library.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Bring secondary button styles up to design standard
-merge_request: 27920
-author:
-type: fixed
diff --git a/changelogs/unreleased/61157-reviewer-roulette-shouldn-t-include-the-author-as-a-possibility.yml b/changelogs/unreleased/61157-reviewer-roulette-shouldn-t-include-the-author-as-a-possibility.yml
deleted file mode 100644
index 8d1a38b3db5..00000000000
--- a/changelogs/unreleased/61157-reviewer-roulette-shouldn-t-include-the-author-as-a-possibility.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Excludes MR author from Review roulette
-merge_request: 28886
-author: Jacopo Beschi @jacopo-beschi
-type: fixed
diff --git a/changelogs/unreleased/61313-fix-dropdown-searchbar.yml b/changelogs/unreleased/61313-fix-dropdown-searchbar.yml
deleted file mode 100644
index ba191a89da2..00000000000
--- a/changelogs/unreleased/61313-fix-dropdown-searchbar.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix loading.. dropdown at search field
-merge_request: 28275
-author: Pavel Chausov
-type: fixed
diff --git a/changelogs/unreleased/61323-snippet-copy-icon-button-is-misaligned.yml b/changelogs/unreleased/61323-snippet-copy-icon-button-is-misaligned.yml
deleted file mode 100644
index 94666ac12ec..00000000000
--- a/changelogs/unreleased/61323-snippet-copy-icon-button-is-misaligned.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Resolve Snippet icon button is misaligned
-merge_request: 28522
-author:
-type: other
diff --git a/changelogs/unreleased/61324-non-project-snippet-new-snippet-button-should-be-green-outline.yml b/changelogs/unreleased/61324-non-project-snippet-new-snippet-button-should-be-green-outline.yml
deleted file mode 100644
index a7f5706058d..00000000000
--- a/changelogs/unreleased/61324-non-project-snippet-new-snippet-button-should-be-green-outline.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Give New Snippet button green outline
-merge_request: 28559
-author:
-type: other
diff --git a/changelogs/unreleased/61339-Add-underline-to-attach-a-file.yml b/changelogs/unreleased/61339-Add-underline-to-attach-a-file.yml
deleted file mode 100644
index e446459ffc8..00000000000
--- a/changelogs/unreleased/61339-Add-underline-to-attach-a-file.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Add hover and focus to Attach a file
-merge_request: 28682
-author:
-type: fixed
diff --git a/changelogs/unreleased/61393-emoji-button.yml b/changelogs/unreleased/61393-emoji-button.yml
deleted file mode 100644
index 2bcfde308db..00000000000
--- a/changelogs/unreleased/61393-emoji-button.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Change default color of award emoji button
-merge_request:
-author:
-type: other
diff --git a/changelogs/unreleased/61441.yml b/changelogs/unreleased/61441.yml
deleted file mode 100644
index 2ad0c6f62d3..00000000000
--- a/changelogs/unreleased/61441.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Allow user to set primary email first when 2FA is required
-merge_request: 28097
-author: Kartikey Tanna
-type: fixed
diff --git a/changelogs/unreleased/61511-add-expand-collapse-to-project-operation-settings.yml b/changelogs/unreleased/61511-add-expand-collapse-to-project-operation-settings.yml
deleted file mode 100644
index 1a3a019e1f4..00000000000
--- a/changelogs/unreleased/61511-add-expand-collapse-to-project-operation-settings.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Add expand/collapse to error tracking settings
-merge_request: 28619
-author:
-type: added
diff --git a/changelogs/unreleased/61565-merge-request-discussion-text-jumps-when-resolved.yml b/changelogs/unreleased/61565-merge-request-discussion-text-jumps-when-resolved.yml
deleted file mode 100644
index 718604c9ceb..00000000000
--- a/changelogs/unreleased/61565-merge-request-discussion-text-jumps-when-resolved.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Resolve Merge request discussion text jumps when resolved
-merge_request: 28995
-author:
-type: fixed
diff --git a/changelogs/unreleased/61606-support-string-piwik-website-ids.yml b/changelogs/unreleased/61606-support-string-piwik-website-ids.yml
deleted file mode 100644
index 5c525294132..00000000000
--- a/changelogs/unreleased/61606-support-string-piwik-website-ids.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: "Supports Matomo/Piwik string website ID (\"Protect Track ID\" plugin)"
-merge_request: 28214
-author: DUVERGIER Claude
-type: fixed \ No newline at end of file
diff --git a/changelogs/unreleased/61629-dependency-installation-error-on-fsevents-1-2-4-with-node-js-12.yml b/changelogs/unreleased/61629-dependency-installation-error-on-fsevents-1-2-4-with-node-js-12.yml
deleted file mode 100644
index bbe43760953..00000000000
--- a/changelogs/unreleased/61629-dependency-installation-error-on-fsevents-1-2-4-with-node-js-12.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Update indirect dependency fsevents from 1.2.4 to 1.2.9
-merge_request: 28220
-author: Takuya Noguchi
-type: other
diff --git a/changelogs/unreleased/61639-flaky-spec-issue-boards-labels-creates-project-label-spec-features-boards-sidebar_spec-rb-350.yml b/changelogs/unreleased/61639-flaky-spec-issue-boards-labels-creates-project-label-spec-features-boards-sidebar_spec-rb-350.yml
deleted file mode 100644
index 9b4f13353f5..00000000000
--- a/changelogs/unreleased/61639-flaky-spec-issue-boards-labels-creates-project-label-spec-features-boards-sidebar_spec-rb-350.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix dropdown position when loading remote data
-merge_request: 28526
-author:
-type: fixed
diff --git a/changelogs/unreleased/61697-add-project-id-to-le-common-name.yml b/changelogs/unreleased/61697-add-project-id-to-le-common-name.yml
deleted file mode 100644
index 8ffa8d0a51a..00000000000
--- a/changelogs/unreleased/61697-add-project-id-to-le-common-name.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Prevent common name collisions when requesting multiple Let's Encrypt certificates concurrently
-merge_request: 28373
-author:
-type: fixed
diff --git a/changelogs/unreleased/61788-predefined-colours-dont-have-descriptive-labels.yml b/changelogs/unreleased/61788-predefined-colours-dont-have-descriptive-labels.yml
deleted file mode 100644
index 25c83d24007..00000000000
--- a/changelogs/unreleased/61788-predefined-colours-dont-have-descriptive-labels.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Adds a text label to color pickers to improve accessibility.
-merge_request: 28343
-author: Chris Toynbee
-type: changed
diff --git a/changelogs/unreleased/61795-fix-error-when-moving-issues.yml b/changelogs/unreleased/61795-fix-error-when-moving-issues.yml
deleted file mode 100644
index 6812baa07c3..00000000000
--- a/changelogs/unreleased/61795-fix-error-when-moving-issues.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Remove unintended error message shown when moving issues
-merge_request: 28317
-author:
-type: fixed
diff --git a/changelogs/unreleased/61821-tooltip-consistency.yml b/changelogs/unreleased/61821-tooltip-consistency.yml
deleted file mode 100644
index 9b131907ebf..00000000000
--- a/changelogs/unreleased/61821-tooltip-consistency.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Resolve Tooltip Consistency
-merge_request: 28839
-author:
-type: fixed
diff --git a/changelogs/unreleased/61827-prevent-user-popover-icon-shrink.yml b/changelogs/unreleased/61827-prevent-user-popover-icon-shrink.yml
deleted file mode 100644
index 4d6464eed52..00000000000
--- a/changelogs/unreleased/61827-prevent-user-popover-icon-shrink.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Prevent icons from shrinking in User popover when contents exceed container
-merge_request: 28696
-author:
-type: fixed
diff --git a/changelogs/unreleased/61880-download-btn-group.yml b/changelogs/unreleased/61880-download-btn-group.yml
deleted file mode 100644
index c1f6b2767c6..00000000000
--- a/changelogs/unreleased/61880-download-btn-group.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Group download buttons into a .btn-group
-merge_request:
-author:
-type: other
diff --git a/changelogs/unreleased/61914-fix-emojis-urls.yml b/changelogs/unreleased/61914-fix-emojis-urls.yml
deleted file mode 100644
index 578edf4a063..00000000000
--- a/changelogs/unreleased/61914-fix-emojis-urls.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix emojis URLs
-merge_request: 28371
-author:
-type: fixed
diff --git a/changelogs/unreleased/61928-remove-throttle-from-dirty-submit.yml b/changelogs/unreleased/61928-remove-throttle-from-dirty-submit.yml
deleted file mode 100644
index f8ef5dbb53b..00000000000
--- a/changelogs/unreleased/61928-remove-throttle-from-dirty-submit.yml
+++ /dev/null
@@ -1,6 +0,0 @@
----
-title: Fix issue that causes "Save changes" button in project settings pages to be
- enabled/disabled incorrectly when changes are made to the form
-merge_request: 28377
-author:
-type: fixed
diff --git a/changelogs/unreleased/61960-translatable-strings-in-issue-closure-emails.yml b/changelogs/unreleased/61960-translatable-strings-in-issue-closure-emails.yml
deleted file mode 100644
index 50b3efba0a5..00000000000
--- a/changelogs/unreleased/61960-translatable-strings-in-issue-closure-emails.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: I18n for issue closure reason in emails
-merge_request: 28489
-author: Michał Zając
-type: changed
diff --git a/changelogs/unreleased/61988-collapse-icon-on-merge-request-diff-larger-than-profile-picture.yml b/changelogs/unreleased/61988-collapse-icon-on-merge-request-diff-larger-than-profile-picture.yml
deleted file mode 100644
index 4d2f73ce2ff..00000000000
--- a/changelogs/unreleased/61988-collapse-icon-on-merge-request-diff-larger-than-profile-picture.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Change collapse icon size to size of profile picture
-merge_request: 28512
-author:
-type: other
diff --git a/changelogs/unreleased/61990-spinner.yml b/changelogs/unreleased/61990-spinner.yml
deleted file mode 100644
index 27d35e56cc9..00000000000
--- a/changelogs/unreleased/61990-spinner.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Updates loading icon in commits page
-merge_request: 28475
-author:
-type: fixed
diff --git a/changelogs/unreleased/62061-note-icon-color.yml b/changelogs/unreleased/62061-note-icon-color.yml
deleted file mode 100644
index 5bfea1a9ed3..00000000000
--- a/changelogs/unreleased/62061-note-icon-color.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Update icon color to match design system, pass accessibility
-merge_request: 28498
-author: Jarek Ostrowski @jareko
-type: fixed
diff --git a/changelogs/unreleased/62091-remove-time-windows-flag.yml b/changelogs/unreleased/62091-remove-time-windows-flag.yml
deleted file mode 100644
index c6c11328312..00000000000
--- a/changelogs/unreleased/62091-remove-time-windows-flag.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Allow users to specify a time range on metrics dashboard
-merge_request: 28670
-author:
-type: added
diff --git a/changelogs/unreleased/62092-missing-padding-next-to-time-windows-dropdown-on-metrics-dashboard.yml b/changelogs/unreleased/62092-missing-padding-next-to-time-windows-dropdown-on-metrics-dashboard.yml
deleted file mode 100644
index 3317d505924..00000000000
--- a/changelogs/unreleased/62092-missing-padding-next-to-time-windows-dropdown-on-metrics-dashboard.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Added padding to time window dropdown in monitor dashboard
-merge_request: 28897
-author:
-type: fixed
diff --git a/changelogs/unreleased/62107-fix-detail-page-header-height.yml b/changelogs/unreleased/62107-fix-detail-page-header-height.yml
deleted file mode 100644
index 3723f323bcc..00000000000
--- a/changelogs/unreleased/62107-fix-detail-page-header-height.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix the height of the page headers on issues/merge request/snippets pages
-merge_request: 28650
-author: Erik van der Gaag
-type: fixed
diff --git a/changelogs/unreleased/62116-performance-issue-502-errors-on-rendering-of-issues-with-heavy-markdown-contents.yml b/changelogs/unreleased/62116-performance-issue-502-errors-on-rendering-of-issues-with-heavy-markdown-contents.yml
deleted file mode 100644
index 9596f487116..00000000000
--- a/changelogs/unreleased/62116-performance-issue-502-errors-on-rendering-of-issues-with-heavy-markdown-contents.yml
+++ /dev/null
@@ -1,6 +0,0 @@
----
-title: Fix performance issue with large Markdown content in issue or merge request
- description
-merge_request: 28597
-author:
-type: performance
diff --git a/changelogs/unreleased/62124-new-threaded-discussion-design.yml b/changelogs/unreleased/62124-new-threaded-discussion-design.yml
deleted file mode 100644
index 6614e05be74..00000000000
--- a/changelogs/unreleased/62124-new-threaded-discussion-design.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Implement borderless discussion design with new reply field
-merge_request: 28580
-author:
-type: added
diff --git a/changelogs/unreleased/62134-fix-non-wraping-project-description.yml b/changelogs/unreleased/62134-fix-non-wraping-project-description.yml
deleted file mode 100644
index 8c734c526fe..00000000000
--- a/changelogs/unreleased/62134-fix-non-wraping-project-description.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Correctly word-wrapping project descriptions with very long words
-merge_request: 28695
-author: Erik van der Gaag
-type: fixed
diff --git a/changelogs/unreleased/62144-fix-option-dropdown-button-size.yml b/changelogs/unreleased/62144-fix-option-dropdown-button-size.yml
deleted file mode 100644
index 86d8f4536f9..00000000000
--- a/changelogs/unreleased/62144-fix-option-dropdown-button-size.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix inconsistent option dropdown button height to match adjacent button
-merge_request: 29096
-author:
-type: fixed
diff --git a/changelogs/unreleased/62154-fe-create-fix-long-branch-name-in-dropdown.yml b/changelogs/unreleased/62154-fe-create-fix-long-branch-name-in-dropdown.yml
deleted file mode 100644
index 1d951c1dc24..00000000000
--- a/changelogs/unreleased/62154-fe-create-fix-long-branch-name-in-dropdown.yml
+++ /dev/null
@@ -1,6 +0,0 @@
----
-title: Add support to view entirety of long branch name in dropdown instead of it
- being cut off
-merge_request: 29069
-author:
-type: fixed
diff --git a/changelogs/unreleased/62227-webkit-icon-overlap.yml b/changelogs/unreleased/62227-webkit-icon-overlap.yml
deleted file mode 100644
index 47d7583f4c2..00000000000
--- a/changelogs/unreleased/62227-webkit-icon-overlap.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Add style to disable webkit icons for search inputs
-merge_request: 28833
-author: Jarek Ostrowski @jareko
-type: fixed
diff --git a/changelogs/unreleased/62253-add-kubernetes-logs-to-monitoring-ui.yml b/changelogs/unreleased/62253-add-kubernetes-logs-to-monitoring-ui.yml
deleted file mode 100644
index c01106a15ec..00000000000
--- a/changelogs/unreleased/62253-add-kubernetes-logs-to-monitoring-ui.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Add Kubernetes logs to Admin Logs UI
-merge_request: 28685
-author:
-type: added
diff --git a/changelogs/unreleased/62300-target-area-for-dropdown-list-items-is-too-small-on-metrics-dashboard.yml b/changelogs/unreleased/62300-target-area-for-dropdown-list-items-is-too-small-on-metrics-dashboard.yml
deleted file mode 100644
index 7944e6faa27..00000000000
--- a/changelogs/unreleased/62300-target-area-for-dropdown-list-items-is-too-small-on-metrics-dashboard.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Enlarge metrics time-window dropdown links
-merge_request: 29458
-author:
-type: fixed
diff --git a/changelogs/unreleased/62408-dropdown-truncate.yml b/changelogs/unreleased/62408-dropdown-truncate.yml
deleted file mode 100644
index 7204016efdf..00000000000
--- a/changelogs/unreleased/62408-dropdown-truncate.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix job name in graph dropdown overflowing
-merge_request: 28824
-author:
-type: fixed
diff --git a/changelogs/unreleased/62418-project-default-git-depth.yml b/changelogs/unreleased/62418-project-default-git-depth.yml
deleted file mode 100644
index b5647cd0859..00000000000
--- a/changelogs/unreleased/62418-project-default-git-depth.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Add project level git depth CI/CD setting
-merge_request: 28919
-author:
-type: added
diff --git a/changelogs/unreleased/62432-fix-participants-wrapping.yml b/changelogs/unreleased/62432-fix-participants-wrapping.yml
deleted file mode 100644
index a7e4bd372de..00000000000
--- a/changelogs/unreleased/62432-fix-participants-wrapping.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix participants list wrapping
-merge_request: 28873
-author:
-type: fixed
diff --git a/changelogs/unreleased/62485-label-weights.yml b/changelogs/unreleased/62485-label-weights.yml
deleted file mode 100644
index 354b18be11e..00000000000
--- a/changelogs/unreleased/62485-label-weights.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Give labels consistent weight
-merge_request: 28895
-author:
-type: fixed
diff --git a/changelogs/unreleased/62487-external-policy-desc.yml b/changelogs/unreleased/62487-external-policy-desc.yml
deleted file mode 100644
index 2e787b89db1..00000000000
--- a/changelogs/unreleased/62487-external-policy-desc.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Move text under p tag
-merge_request: 28901
-author:
-type: fixed
diff --git a/changelogs/unreleased/62656-adjusted-dropdown-styles.yml b/changelogs/unreleased/62656-adjusted-dropdown-styles.yml
deleted file mode 100644
index 36f14ae2741..00000000000
--- a/changelogs/unreleased/62656-adjusted-dropdown-styles.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: "changed the styles on `Add List` dropdown to look more like the EE vesion"
-merge_request: 29338
-author: Michel Engelen
-type: changed
diff --git a/changelogs/unreleased/62684-add-index-public-email-on-users.yml b/changelogs/unreleased/62684-add-index-public-email-on-users.yml
deleted file mode 100644
index 56b5f91da21..00000000000
--- a/changelogs/unreleased/62684-add-index-public-email-on-users.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Add index on public_email for users
-merge_request: 29430
-author:
-type: performance
diff --git a/changelogs/unreleased/62685-add-index-invite-email-to-members.yml b/changelogs/unreleased/62685-add-index-invite-email-to-members.yml
deleted file mode 100644
index 80bb05e1709..00000000000
--- a/changelogs/unreleased/62685-add-index-invite-email-to-members.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Add index on invite_email for members
-merge_request: 29768
-author:
-type: performance
diff --git a/changelogs/unreleased/62788-clean-up-pagination.yml b/changelogs/unreleased/62788-clean-up-pagination.yml
deleted file mode 100644
index 05e3a4527b8..00000000000
--- a/changelogs/unreleased/62788-clean-up-pagination.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Moves the table pagination shared component
-merge_request:
-author:
-type: other
diff --git a/changelogs/unreleased/62788-graphql-pagination.yml b/changelogs/unreleased/62788-graphql-pagination.yml
deleted file mode 100644
index a7bc317a08f..00000000000
--- a/changelogs/unreleased/62788-graphql-pagination.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Adds pagination component for graphql api
-merge_request: 29277
-author:
-type: added
diff --git a/changelogs/unreleased/62847-url-for-the-next-request-with-pagination-is-missing-port.yml b/changelogs/unreleased/62847-url-for-the-next-request-with-pagination-is-missing-port.yml
deleted file mode 100644
index fca92a0d4dc..00000000000
--- a/changelogs/unreleased/62847-url-for-the-next-request-with-pagination-is-missing-port.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Include the port in the URLs of the API Link headers
-merge_request: 29267
-author:
-type: fixed
diff --git a/changelogs/unreleased/62910-task-completion-status-gql-pderichs.yml b/changelogs/unreleased/62910-task-completion-status-gql-pderichs.yml
deleted file mode 100644
index dcbfa7c185d..00000000000
--- a/changelogs/unreleased/62910-task-completion-status-gql-pderichs.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Make task completion status available via GraphQL
-merge_request:
-author:
-type: added
diff --git a/changelogs/unreleased/62966-embed-zoom-call-in-issue-mvc.yml b/changelogs/unreleased/62966-embed-zoom-call-in-issue-mvc.yml
deleted file mode 100644
index a41873f671e..00000000000
--- a/changelogs/unreleased/62966-embed-zoom-call-in-issue-mvc.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Add Join meeting button to issues with Zoom links
-merge_request: 29454
-author:
-type: added
diff --git a/changelogs/unreleased/62974-follow-up-from-wip-align-merge-request-icons-and-text.yml b/changelogs/unreleased/62974-follow-up-from-wip-align-merge-request-icons-and-text.yml
deleted file mode 100644
index 811986e6857..00000000000
--- a/changelogs/unreleased/62974-follow-up-from-wip-align-merge-request-icons-and-text.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: 'Make margin between buttons consistent'
-merge_request: 29378
-author:
-type: other
diff --git a/changelogs/unreleased/63079-exclude-k8s-namespaces-with-no-service-account-token.yml b/changelogs/unreleased/63079-exclude-k8s-namespaces-with-no-service-account-token.yml
deleted file mode 100644
index 9dc99c8a62f..00000000000
--- a/changelogs/unreleased/63079-exclude-k8s-namespaces-with-no-service-account-token.yml
+++ /dev/null
@@ -1,6 +0,0 @@
----
-title: Ensure a Kubernetes namespace is not used for deployments if there is no service
- account token associated with it
-merge_request: 29643
-author:
-type: fixed
diff --git a/changelogs/unreleased/63417-add-missing-class.yml b/changelogs/unreleased/63417-add-missing-class.yml
deleted file mode 100644
index 3030f5c57e4..00000000000
--- a/changelogs/unreleased/63417-add-missing-class.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Indent collapsible sections
-merge_request: 29804
-author:
-type: other
diff --git a/changelogs/unreleased/63507-fix-race-condition-fetching-token.yml b/changelogs/unreleased/63507-fix-race-condition-fetching-token.yml
new file mode 100644
index 00000000000..7f2b59fc9eb
--- /dev/null
+++ b/changelogs/unreleased/63507-fix-race-condition-fetching-token.yml
@@ -0,0 +1,5 @@
+---
+title: Retry fetching Kubernetes Secret#token (#63507)
+merge_request: 29922
+author:
+type: fixed
diff --git a/changelogs/unreleased/63513-ensure-gitlab-jsoncache-includes-the-gitlab-version-in-the-cache-key.yml b/changelogs/unreleased/63513-ensure-gitlab-jsoncache-includes-the-gitlab-version-in-the-cache-key.yml
new file mode 100644
index 00000000000..b5715902630
--- /dev/null
+++ b/changelogs/unreleased/63513-ensure-gitlab-jsoncache-includes-the-gitlab-version-in-the-cache-key.yml
@@ -0,0 +1,5 @@
+---
+title: Include the GitLab version in the cache key for Gitlab::JsonCache
+merge_request: 29938
+author:
+type: fixed
diff --git a/changelogs/unreleased/63559-remove-avatar-from-sign-in.yml b/changelogs/unreleased/63559-remove-avatar-from-sign-in.yml
new file mode 100644
index 00000000000..3f7a8e19de5
--- /dev/null
+++ b/changelogs/unreleased/63559-remove-avatar-from-sign-in.yml
@@ -0,0 +1,5 @@
+---
+title: Resolve Avatar in Please sign in pattern too large
+merge_request: 29944
+author:
+type: fixed
diff --git a/changelogs/unreleased/63656-runner-tags-search-dropdown-is-empty.yml b/changelogs/unreleased/63656-runner-tags-search-dropdown-is-empty.yml
new file mode 100644
index 00000000000..08c415f4a1c
--- /dev/null
+++ b/changelogs/unreleased/63656-runner-tags-search-dropdown-is-empty.yml
@@ -0,0 +1,5 @@
+---
+title: Fix runner tags search dropdown being empty when there are tags
+merge_request: 29985
+author:
+type: fixed
diff --git a/changelogs/unreleased/8723-geo-remove-gitlab-lfstoken-legacyredisdevisetoken-implementation-and-usage-geo.yml b/changelogs/unreleased/8723-geo-remove-gitlab-lfstoken-legacyredisdevisetoken-implementation-and-usage-geo.yml
deleted file mode 100644
index 173c7d9383e..00000000000
--- a/changelogs/unreleased/8723-geo-remove-gitlab-lfstoken-legacyredisdevisetoken-implementation-and-usage-geo.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: 'Geo: Remove Gitlab::LfsToken::LegacyRedisDeviseToken implementation and usage'
-merge_request: 28546
-author:
-type: changed
diff --git a/changelogs/unreleased/9121-sort-relative-position.yml b/changelogs/unreleased/9121-sort-relative-position.yml
deleted file mode 100644
index adc9e87e5bb..00000000000
--- a/changelogs/unreleased/9121-sort-relative-position.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Allow issue list to be sorted by relative order
-merge_request: 28566
-author:
-type: added
diff --git a/changelogs/unreleased/9186-implement-atmtwps-state-to-mr-widget.yml b/changelogs/unreleased/9186-implement-atmtwps-state-to-mr-widget.yml
deleted file mode 100644
index 2c1d56f197e..00000000000
--- a/changelogs/unreleased/9186-implement-atmtwps-state-to-mr-widget.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Update the merge request widget's "Merge" button to support merge trains
-merge_request: 27594
-author:
-type: added
diff --git a/changelogs/unreleased/9578-adjust-milestone-completion-rate.yml b/changelogs/unreleased/9578-adjust-milestone-completion-rate.yml
deleted file mode 100644
index 0694e1462cf..00000000000
--- a/changelogs/unreleased/9578-adjust-milestone-completion-rate.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Adjust milestone completion rate to be based on issues count.
-merge_request: 28777
-author:
-type: changed
diff --git a/changelogs/unreleased/9978-moved-code-differences-from-EE-to-CE.yml b/changelogs/unreleased/9978-moved-code-differences-from-EE-to-CE.yml
deleted file mode 100644
index 821e5d70dca..00000000000
--- a/changelogs/unreleased/9978-moved-code-differences-from-EE-to-CE.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: "Moved EE/CE code differences for `app/assets/javascripts/gl_dropdown.js` into CE"
-merge_request: 28711
-author: Michel Engelen
-type: other
diff --git a/changelogs/unreleased/abstract-auto-merge.yml b/changelogs/unreleased/abstract-auto-merge.yml
deleted file mode 100644
index d3069a3e500..00000000000
--- a/changelogs/unreleased/abstract-auto-merge.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Refactor and abstract Auto Merge Processes
-merge_request: 28595
-author:
-type: other
diff --git a/changelogs/unreleased/ac-63020-typeerror-nil-can-t-be-coerced-into-integer.yml b/changelogs/unreleased/ac-63020-typeerror-nil-can-t-be-coerced-into-integer.yml
deleted file mode 100644
index 51ac2358fba..00000000000
--- a/changelogs/unreleased/ac-63020-typeerror-nil-can-t-be-coerced-into-integer.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix nil coercion updating storage size on project statistics
-merge_request: 29425
-author:
-type: fixed
diff --git a/changelogs/unreleased/ac-graphql-stats.yml b/changelogs/unreleased/ac-graphql-stats.yml
deleted file mode 100644
index 8837dce4d89..00000000000
--- a/changelogs/unreleased/ac-graphql-stats.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Add Namespace and ProjectStatistics to GraphQL API
-merge_request: 28277
-author:
-type: added
diff --git a/changelogs/unreleased/ac-graphql-wikisize.yml b/changelogs/unreleased/ac-graphql-wikisize.yml
deleted file mode 100644
index be9c347ec21..00000000000
--- a/changelogs/unreleased/ac-graphql-wikisize.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Expose wiki_size on GraphQL API
-merge_request: 29123
-author:
-type: added
diff --git a/changelogs/unreleased/ac-namespaces-stats-no-coalesce.yml b/changelogs/unreleased/ac-namespaces-stats-no-coalesce.yml
deleted file mode 100644
index bd005206d4e..00000000000
--- a/changelogs/unreleased/ac-namespaces-stats-no-coalesce.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Forbid NULL in project_statistics.packages_size
-merge_request: 28400
-author:
-type: other
diff --git a/changelogs/unreleased/add-allow_failure-to-job-api.yml b/changelogs/unreleased/add-allow_failure-to-job-api.yml
deleted file mode 100644
index 5dd2b9708c5..00000000000
--- a/changelogs/unreleased/add-allow_failure-to-job-api.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Add allow_failure attribute to Job API
-merge_request: 28406
-author:
-type: added
diff --git a/changelogs/unreleased/add-branch-to-project-search-api.yml b/changelogs/unreleased/add-branch-to-project-search-api.yml
deleted file mode 100644
index 74cff94ab76..00000000000
--- a/changelogs/unreleased/add-branch-to-project-search-api.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Added ref querystring parameter to project search API to allow searching on branches/tags other than the default
-merge_request: 28069
-author: Lee Tickett
-type: added
diff --git a/changelogs/unreleased/add-constraint-for-milestone-dates.yml b/changelogs/unreleased/add-constraint-for-milestone-dates.yml
deleted file mode 100644
index 485149cf62e..00000000000
--- a/changelogs/unreleased/add-constraint-for-milestone-dates.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Limit milestone dates to before year 9999
-merge_request: 28742
-author: Luke Picciau
-type: fixed
diff --git a/changelogs/unreleased/add-lfs-blob-ids-to-tree-type.yml b/changelogs/unreleased/add-lfs-blob-ids-to-tree-type.yml
deleted file mode 100644
index 14a5ef1cef3..00000000000
--- a/changelogs/unreleased/add-lfs-blob-ids-to-tree-type.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Add LFS oid to GraphQL blob type
-merge_request: 28666
-author:
-type: added
diff --git a/changelogs/unreleased/add-warning-to-backup-rake-task.yml b/changelogs/unreleased/add-warning-to-backup-rake-task.yml
deleted file mode 100644
index 7ddeae3f9fd..00000000000
--- a/changelogs/unreleased/add-warning-to-backup-rake-task.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Add warning that gitlab-secrets isn't included in backup
-merge_request:
-author:
-type: other
diff --git a/changelogs/unreleased/add-wiki-size-to-statistics.yml b/changelogs/unreleased/add-wiki-size-to-statistics.yml
deleted file mode 100644
index 85b6d7a1774..00000000000
--- a/changelogs/unreleased/add-wiki-size-to-statistics.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Add wiki size to project statistics
-merge_request: 25321
-author: Peter Marko
-type: added
diff --git a/changelogs/unreleased/allow-emoji-in-references.yml b/changelogs/unreleased/allow-emoji-in-references.yml
deleted file mode 100644
index 3116b346c00..00000000000
--- a/changelogs/unreleased/allow-emoji-in-references.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Allow references to labels and milestones to contain emoji
-merge_request: 29284
-author:
-type: changed
diff --git a/changelogs/unreleased/always-show-pipelines-must-succeed-checkbox.yml b/changelogs/unreleased/always-show-pipelines-must-succeed-checkbox.yml
deleted file mode 100644
index d60dd65be8a..00000000000
--- a/changelogs/unreleased/always-show-pipelines-must-succeed-checkbox.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Always show "Pipelines must succeed" checkbox
-merge_request: 28651
-author:
-type: fixed
diff --git a/changelogs/unreleased/antonyliu-i18n-user-profile.yml b/changelogs/unreleased/antonyliu-i18n-user-profile.yml
deleted file mode 100644
index f9065ee5697..00000000000
--- a/changelogs/unreleased/antonyliu-i18n-user-profile.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: 'i18n: externalize strings from user profile settings'
-merge_request: 28088
-author: Antony Liu
-type: other
diff --git a/changelogs/unreleased/api_make_protected_boolean_type.yml b/changelogs/unreleased/api_make_protected_boolean_type.yml
deleted file mode 100644
index 765edea6427..00000000000
--- a/changelogs/unreleased/api_make_protected_boolean_type.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: 'API: change protected attribute type to Boolean'
-merge_request: 28766
-author:
-type: other
diff --git a/changelogs/unreleased/api_masked_variables.yml b/changelogs/unreleased/api_masked_variables.yml
deleted file mode 100644
index 3605339cb91..00000000000
--- a/changelogs/unreleased/api_masked_variables.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: 'API: Allow to get and set "masked" attribute for variables'
-merge_request: 28381
-author: Mathieu Parent
-type: added
diff --git a/changelogs/unreleased/asciidoc-include-directive.yml b/changelogs/unreleased/asciidoc-include-directive.yml
deleted file mode 100644
index 58fe3666727..00000000000
--- a/changelogs/unreleased/asciidoc-include-directive.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Add support for AsciiDoc include directive
-merge_request: 28417
-author: "Jakub Jirutka & Guillaume Grossetie"
-type: added
diff --git a/changelogs/unreleased/auto-devops-kubernestes-bump1-11-10.yml b/changelogs/unreleased/auto-devops-kubernestes-bump1-11-10.yml
deleted file mode 100644
index 9ba55719bdf..00000000000
--- a/changelogs/unreleased/auto-devops-kubernestes-bump1-11-10.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Bumps Kubernetes in Auto DevOps to 1.11.10
-merge_request: 28525
-author:
-type: other
diff --git a/changelogs/unreleased/backport-schema-changes.yml b/changelogs/unreleased/backport-schema-changes.yml
deleted file mode 100644
index 58f3ca72b0b..00000000000
--- a/changelogs/unreleased/backport-schema-changes.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Backport the EE schema and migrations to CE
-merge_request: 26940
-author: Yorick Peterse
-type: other
diff --git a/changelogs/unreleased/backstage-gb-improve-jobs-controller-performance.yml b/changelogs/unreleased/backstage-gb-improve-jobs-controller-performance.yml
deleted file mode 100644
index 2b5a3592775..00000000000
--- a/changelogs/unreleased/backstage-gb-improve-jobs-controller-performance.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Improve performance of jobs controller
-merge_request: 28093
-author:
-type: performance
diff --git a/changelogs/unreleased/bump-auto-devops-helm-2-14-0.yml b/changelogs/unreleased/bump-auto-devops-helm-2-14-0.yml
deleted file mode 100644
index ecfbc97a8c5..00000000000
--- a/changelogs/unreleased/bump-auto-devops-helm-2-14-0.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Bump Helm version in Auto-DevOps.gitlab-ci.yml to 2.14.0
-merge_request: 28527
-author:
-type: other
diff --git a/changelogs/unreleased/bvl-comments-graphql.yml b/changelogs/unreleased/bvl-comments-graphql.yml
deleted file mode 100644
index 9f510a910a3..00000000000
--- a/changelogs/unreleased/bvl-comments-graphql.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Expose notes and discussions in GraphQL
-merge_request: 29212
-author:
-type: added
diff --git a/changelogs/unreleased/bvl-graphql-multiplex.yml b/changelogs/unreleased/bvl-graphql-multiplex.yml
deleted file mode 100644
index 56d39e447a5..00000000000
--- a/changelogs/unreleased/bvl-graphql-multiplex.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Support multiplex GraphQL queries
-merge_request: 28273
-author:
-type: added
diff --git a/changelogs/unreleased/bvl-use-global-ids-graphql.yml b/changelogs/unreleased/bvl-use-global-ids-graphql.yml
deleted file mode 100644
index 34cb65e6001..00000000000
--- a/changelogs/unreleased/bvl-use-global-ids-graphql.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Use global IDs when exposing GraphQL resources
-merge_request: 29080
-author:
-type: added
diff --git a/changelogs/unreleased/cancel-auto-merge-when-branch-is-changed.yml b/changelogs/unreleased/cancel-auto-merge-when-branch-is-changed.yml
deleted file mode 100644
index c3c6e4322a2..00000000000
--- a/changelogs/unreleased/cancel-auto-merge-when-branch-is-changed.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Cancel Auto Merge when target branch is changed
-merge_request: 29416
-author:
-type: fixed
diff --git a/changelogs/unreleased/cancel-auto-merge-when-merge-request-is-closed.yml b/changelogs/unreleased/cancel-auto-merge-when-merge-request-is-closed.yml
deleted file mode 100644
index d38046ebcbf..00000000000
--- a/changelogs/unreleased/cancel-auto-merge-when-merge-request-is-closed.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Cancel auto merge when merge request is closed
-merge_request: 28782
-author:
-type: fixed
diff --git a/changelogs/unreleased/ce-57402-add-issues-statistics-api-endpoints.yml b/changelogs/unreleased/ce-57402-add-issues-statistics-api-endpoints.yml
deleted file mode 100644
index a626193dc27..00000000000
--- a/changelogs/unreleased/ce-57402-add-issues-statistics-api-endpoints.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Add issues_statistics api endpoints and extend issues search api
-merge_request: 27366
-author:
-type: added
diff --git a/changelogs/unreleased/ce-jej-fix-git-http-with-sso-enforcement.yml b/changelogs/unreleased/ce-jej-fix-git-http-with-sso-enforcement.yml
deleted file mode 100644
index a795e33b00d..00000000000
--- a/changelogs/unreleased/ce-jej-fix-git-http-with-sso-enforcement.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Avoid setting Gitlab::Session on sessionless requests and Git HTTP
-merge_request: 29146
-author:
-type: fixed
diff --git a/changelogs/unreleased/ce-quick-fix-58727-collapsed-sidebar-flyout-menu-items-don-t-appear-in-1200px-screen-size.yml b/changelogs/unreleased/ce-quick-fix-58727-collapsed-sidebar-flyout-menu-items-don-t-appear-in-1200px-screen-size.yml
deleted file mode 100644
index 332105bb269..00000000000
--- a/changelogs/unreleased/ce-quick-fix-58727-collapsed-sidebar-flyout-menu-items-don-t-appear-in-1200px-screen-size.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix flyout nav on small viewports
-merge_request: 25998
-author:
-type: fixed
diff --git a/changelogs/unreleased/chore-remove-circuit-breaker-api.yml b/changelogs/unreleased/chore-remove-circuit-breaker-api.yml
deleted file mode 100644
index f9532be04c8..00000000000
--- a/changelogs/unreleased/chore-remove-circuit-breaker-api.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Remove the circuit breaker API
-merge_request: 28669
-author:
-type: removed
diff --git a/changelogs/unreleased/ci-variable-conjunction.yml b/changelogs/unreleased/ci-variable-conjunction.yml
deleted file mode 100644
index 839c4285f3a..00000000000
--- a/changelogs/unreleased/ci-variable-conjunction.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Add support for && and || to CI Pipeline Expressions. Change CI variable expression matching for Lexeme::Pattern to eagerly return tokens.
-merge_request: 27925
-author: Martin Manelli
-type: added
diff --git a/changelogs/unreleased/container-registry-api-perms-58271.yml b/changelogs/unreleased/container-registry-api-perms-58271.yml
deleted file mode 100644
index 0d1036a7788..00000000000
--- a/changelogs/unreleased/container-registry-api-perms-58271.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Allow developer role to delete docker tags via container registry API
-merge_request: 29512
-author:
-type: fixed
diff --git a/changelogs/unreleased/copy-button-in-modals.yml b/changelogs/unreleased/copy-button-in-modals.yml
deleted file mode 100644
index bc18eb9ab26..00000000000
--- a/changelogs/unreleased/copy-button-in-modals.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Add a New Copy Button That Works in Modals
-merge_request: 28676
-author:
-type: added
diff --git a/changelogs/unreleased/db-update-geo-nodes-primary.yml b/changelogs/unreleased/db-update-geo-nodes-primary.yml
new file mode 100644
index 00000000000..7c5203353ac
--- /dev/null
+++ b/changelogs/unreleased/db-update-geo-nodes-primary.yml
@@ -0,0 +1,5 @@
+---
+title: Disallow `NULL` values for `geo_nodes.primary` column
+merge_request: 29818
+author: Arun Kumar Mohan
+type: other
diff --git a/changelogs/unreleased/dhiraj-fix-missing-deployment-rockets-in-monitoring-dashboard.yml b/changelogs/unreleased/dhiraj-fix-missing-deployment-rockets-in-monitoring-dashboard.yml
deleted file mode 100644
index 12a21e818b4..00000000000
--- a/changelogs/unreleased/dhiraj-fix-missing-deployment-rockets-in-monitoring-dashboard.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix missing deployment rockets in monitor dashboard
-merge_request: 29574
-author:
-type: fixed
diff --git a/changelogs/unreleased/diff-suggestions-popover.yml b/changelogs/unreleased/diff-suggestions-popover.yml
deleted file mode 100644
index fdb94e6e2a7..00000000000
--- a/changelogs/unreleased/diff-suggestions-popover.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Added diff suggestion feature discovery popover
-merge_request:
-author:
-type: added
diff --git a/changelogs/unreleased/diff-whitespace-setting-changes.yml b/changelogs/unreleased/diff-whitespace-setting-changes.yml
deleted file mode 100644
index 640e9e589df..00000000000
--- a/changelogs/unreleased/diff-whitespace-setting-changes.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fixed show whitespace button not refetching diff content
-merge_request:
-author:
-type: fixed
diff --git a/changelogs/unreleased/display-junit-classname-in-modal.yml b/changelogs/unreleased/display-junit-classname-in-modal.yml
deleted file mode 100644
index c5140456e4e..00000000000
--- a/changelogs/unreleased/display-junit-classname-in-modal.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Display classname JUnit attribute in report modal
-merge_request: 28376
-author:
-type: added
diff --git a/changelogs/unreleased/dm-http-hostname-override.yml b/changelogs/unreleased/dm-http-hostname-override.yml
deleted file mode 100644
index f84f36a0010..00000000000
--- a/changelogs/unreleased/dm-http-hostname-override.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Protect Gitlab::HTTP against DNS rebinding attack
-merge_request:
-author:
-type: security
diff --git a/changelogs/unreleased/docs-add-chatops-request-doc.yml b/changelogs/unreleased/docs-add-chatops-request-doc.yml
deleted file mode 100644
index 85ba86a73af..00000000000
--- a/changelogs/unreleased/docs-add-chatops-request-doc.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Add section to dev docs on accessing chatops
-merge_request: 28623
-author:
-type: other
diff --git a/changelogs/unreleased/dz-patch-58.yml b/changelogs/unreleased/dz-patch-58.yml
deleted file mode 100644
index 97ceadd303d..00000000000
--- a/changelogs/unreleased/dz-patch-58.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Replace Oxygen-Sans font with Noto Sans
-merge_request: 28322
-author:
-type: changed
diff --git a/changelogs/unreleased/dz-scope-project-routes.yml b/changelogs/unreleased/dz-scope-project-routes.yml
deleted file mode 100644
index 66eb5d928f0..00000000000
--- a/changelogs/unreleased/dz-scope-project-routes.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Move some project routes under /-/ scope
-merge_request: 28435
-author:
-type: changed
diff --git a/changelogs/unreleased/ee-11040-added-conditional-rendering.yml b/changelogs/unreleased/ee-11040-added-conditional-rendering.yml
deleted file mode 100644
index 7b06e43830f..00000000000
--- a/changelogs/unreleased/ee-11040-added-conditional-rendering.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: "Added conditional rendering to `app/views/search/_form.html.haml` for CE/EE code base consistency"
-merge_request: 28883
-author: Michel Engelen
-type: other
diff --git a/changelogs/unreleased/ensure_namespace.yml b/changelogs/unreleased/ensure_namespace.yml
deleted file mode 100644
index ce2a615af1f..00000000000
--- a/changelogs/unreleased/ensure_namespace.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: AutoDevops function ensure_namespace() now explicitly tests the namespace
-merge_request: 29567
-author: Jack Lei
-type: fixed
diff --git a/changelogs/unreleased/error-pipelines-for-blocked-users.yml b/changelogs/unreleased/error-pipelines-for-blocked-users.yml
deleted file mode 100644
index 3ace28b6cfd..00000000000
--- a/changelogs/unreleased/error-pipelines-for-blocked-users.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: preventing blocked users and their PipelineSchdules from creating new Pipelines
-merge_request: 27318
-author:
-type: fixed
diff --git a/changelogs/unreleased/expose-project-git-depth-via-api.yml b/changelogs/unreleased/expose-project-git-depth-via-api.yml
deleted file mode 100644
index e9d158fda16..00000000000
--- a/changelogs/unreleased/expose-project-git-depth-via-api.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Get and edit ci_default_git_depth via project API
-merge_request: 29353
-author:
-type: added
diff --git a/changelogs/unreleased/fe-fix-gl-dropdown-scrolling-to-top.yml b/changelogs/unreleased/fe-fix-gl-dropdown-scrolling-to-top.yml
deleted file mode 100644
index 4125b4241e6..00000000000
--- a/changelogs/unreleased/fe-fix-gl-dropdown-scrolling-to-top.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix scrolling to top on assignee change
-merge_request: 29500
-author:
-type: fixed
diff --git a/changelogs/unreleased/feature-gb-use-gitlabktl-to-build-serverless-applications.yml b/changelogs/unreleased/feature-gb-use-gitlabktl-to-build-serverless-applications.yml
deleted file mode 100644
index 443fff92f55..00000000000
--- a/changelogs/unreleased/feature-gb-use-gitlabktl-to-build-serverless-applications.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Use to 'gitlabktl' build serverless applications
-merge_request: 29258
-author:
-type: added
diff --git a/changelogs/unreleased/feature-require-2fa-for-all-entities-in-group.yml b/changelogs/unreleased/feature-require-2fa-for-all-entities-in-group.yml
deleted file mode 100644
index 0abe777fb69..00000000000
--- a/changelogs/unreleased/feature-require-2fa-for-all-entities-in-group.yml
+++ /dev/null
@@ -1,4 +0,0 @@
-title: Apply the group setting "require 2FA" across all subgroup members as well when changing the group setting
-merge_request: 24965
-author: rroger
-type: changed
diff --git a/changelogs/unreleased/fix-allow-lower-case-issue-ids.yml b/changelogs/unreleased/fix-allow-lower-case-issue-ids.yml
deleted file mode 100644
index 46fa90ccda0..00000000000
--- a/changelogs/unreleased/fix-allow-lower-case-issue-ids.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Allow lowercase prefix for Youtrack issue ids
-merge_request: 29057
-author: Matthias Baur
-type: fixed
diff --git a/changelogs/unreleased/fix-autodevops-postgres-versioning.yml b/changelogs/unreleased/fix-autodevops-postgres-versioning.yml
deleted file mode 100644
index 8ddc70f6314..00000000000
--- a/changelogs/unreleased/fix-autodevops-postgres-versioning.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fixed ignored postgres version that occurs after the first autodevops deploy when specifying custom $POSTGRES_VERSION
-merge_request: 28735
-author: Brandon Dimcheff
-type: fixed
diff --git a/changelogs/unreleased/fix-db-migrate-is-failed-on-mysql8.yml b/changelogs/unreleased/fix-db-migrate-is-failed-on-mysql8.yml
deleted file mode 100644
index 63f134808e3..00000000000
--- a/changelogs/unreleased/fix-db-migrate-is-failed-on-mysql8.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix. `db:migrate` is failed on MySQL 8
-merge_request: 28351
-author: sue445
-type: fixed
diff --git a/changelogs/unreleased/fix-diverged-branch-locals.yml b/changelogs/unreleased/fix-diverged-branch-locals.yml
deleted file mode 100644
index 719d669fad3..00000000000
--- a/changelogs/unreleased/fix-diverged-branch-locals.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix diverged branch locals
-merge_request: 29508
-author:
-type: fixed
diff --git a/changelogs/unreleased/fix-flyout-navs.yml b/changelogs/unreleased/fix-flyout-navs.yml
deleted file mode 100644
index c21f1037f09..00000000000
--- a/changelogs/unreleased/fix-flyout-navs.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix sidebar flyout navigation
-merge_request: 29571
-author:
-type: fixed
diff --git a/changelogs/unreleased/fix-format-date-safari-ff.yml b/changelogs/unreleased/fix-format-date-safari-ff.yml
deleted file mode 100644
index e71ea2867f3..00000000000
--- a/changelogs/unreleased/fix-format-date-safari-ff.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Throw an error when formatDate's input is invalid
-merge_request: 28713
-author:
-type: fixed
diff --git a/changelogs/unreleased/fix-gb-fix-serverless-apps-deployment-template.yml b/changelogs/unreleased/fix-gb-fix-serverless-apps-deployment-template.yml
deleted file mode 100644
index 88656b7ef4c..00000000000
--- a/changelogs/unreleased/fix-gb-fix-serverless-apps-deployment-template.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix serverless apps deployments by bumping 'tm' version
-merge_request: 29254
-author:
-type: fixed
diff --git a/changelogs/unreleased/fix-gb-remove-serverless-app-build-policies-from-template.yml b/changelogs/unreleased/fix-gb-remove-serverless-app-build-policies-from-template.yml
deleted file mode 100644
index f51ec273a57..00000000000
--- a/changelogs/unreleased/fix-gb-remove-serverless-app-build-policies-from-template.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Remove build policies from serverless app template
-merge_request: 29253
-author:
-type: fixed
diff --git a/changelogs/unreleased/fix-import-member-access.yml b/changelogs/unreleased/fix-import-member-access.yml
deleted file mode 100644
index 5dc4ae738f8..00000000000
--- a/changelogs/unreleased/fix-import-member-access.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix issue importing members with owner access
-merge_request: 28636
-author:
-type: fixed
diff --git a/changelogs/unreleased/fix-import-param-ordering.yml b/changelogs/unreleased/fix-import-param-ordering.yml
deleted file mode 100644
index 47e32cda977..00000000000
--- a/changelogs/unreleased/fix-import-param-ordering.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix order dependency with user params during imports
-merge_request: 28719
-author:
-type: fixed
diff --git a/changelogs/unreleased/fix-issue-mr-badge.yml b/changelogs/unreleased/fix-issue-mr-badge.yml
deleted file mode 100644
index e777f52f173..00000000000
--- a/changelogs/unreleased/fix-issue-mr-badge.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Use grid and correct border radius for status badge
-merge_request:
-author:
-type: other
diff --git a/changelogs/unreleased/fix-labels-in-hooks.yml b/changelogs/unreleased/fix-labels-in-hooks.yml
new file mode 100644
index 00000000000..c0904a860c5
--- /dev/null
+++ b/changelogs/unreleased/fix-labels-in-hooks.yml
@@ -0,0 +1,5 @@
+---
+title: Fix label serialization in issue and note hooks
+merge_request: 29850
+author:
+type: fixed
diff --git a/changelogs/unreleased/fix-milestone-references-with-escaped-html-entities.yml b/changelogs/unreleased/fix-milestone-references-with-escaped-html-entities.yml
deleted file mode 100644
index 1041943f9c4..00000000000
--- a/changelogs/unreleased/fix-milestone-references-with-escaped-html-entities.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix milestone references containing &, <, or >
-merge_request: 28667
-author:
-type: fixed
diff --git a/changelogs/unreleased/fix-notes-emails-with-group-settings.yml b/changelogs/unreleased/fix-notes-emails-with-group-settings.yml
new file mode 100644
index 00000000000..77dae8418a8
--- /dev/null
+++ b/changelogs/unreleased/fix-notes-emails-with-group-settings.yml
@@ -0,0 +1,5 @@
+---
+title: Fix comment emails not respecting group-level notification email
+merge_request:
+author:
+type: fixed
diff --git a/changelogs/unreleased/fix-pipeline-schedule-edge-case.yml b/changelogs/unreleased/fix-pipeline-schedule-edge-case.yml
new file mode 100644
index 00000000000..2b7e3611567
--- /dev/null
+++ b/changelogs/unreleased/fix-pipeline-schedule-edge-case.yml
@@ -0,0 +1,6 @@
+---
+title: Fix pipeline schedule does not run correctly when it's scheduled at the same
+ time with the cron worker
+merge_request: 29848
+author:
+type: fixed
diff --git a/changelogs/unreleased/fix-pipeline-schedule-owner-is-nil.yml b/changelogs/unreleased/fix-pipeline-schedule-owner-is-nil.yml
deleted file mode 100644
index 5c8644d2860..00000000000
--- a/changelogs/unreleased/fix-pipeline-schedule-owner-is-nil.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix pipeline schedules when owner is nil
-merge_request:
-author:
-type: fixed
diff --git a/changelogs/unreleased/fix-search-dropdown-blur-close.yml b/changelogs/unreleased/fix-search-dropdown-blur-close.yml
deleted file mode 100644
index 1ac9dc674fe..00000000000
--- a/changelogs/unreleased/fix-search-dropdown-blur-close.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix search dropdown not closing on blur if empty
-merge_request: 28730
-author:
-type: fixed
diff --git a/changelogs/unreleased/fix-time-window-default.yml b/changelogs/unreleased/fix-time-window-default.yml
deleted file mode 100644
index 147f82eb6c9..00000000000
--- a/changelogs/unreleased/fix-time-window-default.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Use the selected time window for metrics dashboard
-merge_request: 29152
-author:
-type: fixed
diff --git a/changelogs/unreleased/fix-too-many-loops-cron-error.yml b/changelogs/unreleased/fix-too-many-loops-cron-error.yml
deleted file mode 100644
index a9b5b761439..00000000000
--- a/changelogs/unreleased/fix-too-many-loops-cron-error.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix "too many loops" error by handling gracefully cron schedules for non existent days
-merge_request: 28002
-author:
-type: fixed
diff --git a/changelogs/unreleased/generate-spans-for-sections.yml b/changelogs/unreleased/generate-spans-for-sections.yml
deleted file mode 100644
index e167d66490f..00000000000
--- a/changelogs/unreleased/generate-spans-for-sections.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Adds collapsible sections for job log
-merge_request: 28642
-author:
-type: added
diff --git a/changelogs/unreleased/gitaly-version-v1.43.0.yml b/changelogs/unreleased/gitaly-version-v1.43.0.yml
deleted file mode 100644
index 67acd2725e1..00000000000
--- a/changelogs/unreleased/gitaly-version-v1.43.0.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Upgrade to Gitaly v1.43.0
-merge_request: 28867
-author:
-type: changed
diff --git a/changelogs/unreleased/gitaly-version-v1.47.0.yml b/changelogs/unreleased/gitaly-version-v1.47.0.yml
deleted file mode 100644
index b369506b336..00000000000
--- a/changelogs/unreleased/gitaly-version-v1.47.0.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Upgrade to Gitaly v1.47.0
-merge_request: 29789
-author:
-type: changed
diff --git a/changelogs/unreleased/gt-externalize-profiles-preferences.yml b/changelogs/unreleased/gt-externalize-profiles-preferences.yml
deleted file mode 100644
index 1a72e92a241..00000000000
--- a/changelogs/unreleased/gt-externalize-profiles-preferences.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Externalize profiles preferences
-merge_request: 28470
-author: George Tsiolis
-type: other
diff --git a/changelogs/unreleased/gt-open-visibility-help-link-in-a-new-tab.yml b/changelogs/unreleased/gt-open-visibility-help-link-in-a-new-tab.yml
deleted file mode 100644
index 35515c9d639..00000000000
--- a/changelogs/unreleased/gt-open-visibility-help-link-in-a-new-tab.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Open visibility help link in a new tab
-merge_request: 28603
-author: George Tsiolis
-type: fixed
diff --git a/changelogs/unreleased/gt-remove-tooltip-directive-on-project-avatar-image-component.yml b/changelogs/unreleased/gt-remove-tooltip-directive-on-project-avatar-image-component.yml
new file mode 100644
index 00000000000..d9ca20d9d4d
--- /dev/null
+++ b/changelogs/unreleased/gt-remove-tooltip-directive-on-project-avatar-image-component.yml
@@ -0,0 +1,5 @@
+---
+title: Remove tooltip directive on project avatar image component
+merge_request: 29631
+author: George Tsiolis
+type: performance
diff --git a/changelogs/unreleased/hashed-storage-enabled-default.yml b/changelogs/unreleased/hashed-storage-enabled-default.yml
deleted file mode 100644
index 9a34505785c..00000000000
--- a/changelogs/unreleased/hashed-storage-enabled-default.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Hashed Storage is enabled by default on new installations
-merge_request: 29586
-author:
-type: changed
diff --git a/changelogs/unreleased/i18n-active_sessions-in-user-profile.yml b/changelogs/unreleased/i18n-active_sessions-in-user-profile.yml
deleted file mode 100644
index fe6eb3a2bf7..00000000000
--- a/changelogs/unreleased/i18n-active_sessions-in-user-profile.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Externalize strings of active sessions page in user profile
-merge_request: 28590
-author: antony liu
-type: other
diff --git a/changelogs/unreleased/i18n-chat-of-user-profile.yml b/changelogs/unreleased/i18n-chat-of-user-profile.yml
deleted file mode 100644
index 663b4ffc1a1..00000000000
--- a/changelogs/unreleased/i18n-chat-of-user-profile.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Externalize strings of chat page in user profile
-merge_request: 28632
-author:
-type: other
diff --git a/changelogs/unreleased/i18n-email-of-user-profile.yml b/changelogs/unreleased/i18n-email-of-user-profile.yml
deleted file mode 100644
index 6cb718843d5..00000000000
--- a/changelogs/unreleased/i18n-email-of-user-profile.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Externalize strings of email page in user profile
-merge_request: 28587
-author: antony liu
-type: other
diff --git a/changelogs/unreleased/i18n-pgp_ssh_keys-of-user-profile.yml b/changelogs/unreleased/i18n-pgp_ssh_keys-of-user-profile.yml
deleted file mode 100644
index 4dc45b35976..00000000000
--- a/changelogs/unreleased/i18n-pgp_ssh_keys-of-user-profile.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Externalize strings of PGP Keys and SSH Keys page in user profile
-merge_request: 28653
-author: Antony Liu
-type: other
diff --git a/changelogs/unreleased/id-bug-suggested-changes-remove-empty-line.yml b/changelogs/unreleased/id-bug-suggested-changes-remove-empty-line.yml
deleted file mode 100644
index eae2d5f9b2a..00000000000
--- a/changelogs/unreleased/id-bug-suggested-changes-remove-empty-line.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Allow removal of empty lines via suggestions
-merge_request: 28703
-author:
-type: fixed
diff --git a/changelogs/unreleased/ignore-artifact-attirbutes-in-project-import-export.yml b/changelogs/unreleased/ignore-artifact-attirbutes-in-project-import-export.yml
deleted file mode 100644
index 536aae03f59..00000000000
--- a/changelogs/unreleased/ignore-artifact-attirbutes-in-project-import-export.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Ignore legacy artifact columns in Project Import/Export
-merge_request: 29427
-author:
-type: fixed
diff --git a/changelogs/unreleased/improve-email-text-part.yml b/changelogs/unreleased/improve-email-text-part.yml
deleted file mode 100644
index ce506cb1507..00000000000
--- a/changelogs/unreleased/improve-email-text-part.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Improve new user email markup unconsistency between text and html parts
-merge_request: 29111
-author: Haunui Saint-sevin
-type: fixed
diff --git a/changelogs/unreleased/increase-move-issue-dropdown-height.yml b/changelogs/unreleased/increase-move-issue-dropdown-height.yml
deleted file mode 100644
index bb67e9341b2..00000000000
--- a/changelogs/unreleased/increase-move-issue-dropdown-height.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Increase height of move issue dropdown
-merge_request:
-author:
-type: other
diff --git a/changelogs/unreleased/issue-58747.yml b/changelogs/unreleased/issue-58747.yml
deleted file mode 100644
index 01b610576f7..00000000000
--- a/changelogs/unreleased/issue-58747.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix GPG signature verification with recent GnuPG versions
-merge_request: 29388
-author: David Palubin
-type: fixed
diff --git a/changelogs/unreleased/issue_49897.yml b/changelogs/unreleased/issue_49897.yml
deleted file mode 100644
index b630b5143c6..00000000000
--- a/changelogs/unreleased/issue_49897.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Delete unauthorized Todos when project is made private
-merge_request: 28560
-author:
-type: fixed
diff --git a/changelogs/unreleased/jc-migration-for-source-project-id.yml b/changelogs/unreleased/jc-migration-for-source-project-id.yml
deleted file mode 100644
index 3e2e8ebfcc5..00000000000
--- a/changelogs/unreleased/jc-migration-for-source-project-id.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix null source_project_id in pool_repositories
-merge_request: 29157
-author:
-type: other
diff --git a/changelogs/unreleased/jc-omit-count-diverging-commits-max.yml b/changelogs/unreleased/jc-omit-count-diverging-commits-max.yml
deleted file mode 100644
index 23235060a98..00000000000
--- a/changelogs/unreleased/jc-omit-count-diverging-commits-max.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Omit max-count for diverging_commit_counts behind feature flag
-merge_request: 28157
-author:
-type: other
diff --git a/changelogs/unreleased/jivl-migrate-dashboard-store-vuex.yml b/changelogs/unreleased/jivl-migrate-dashboard-store-vuex.yml
deleted file mode 100644
index dc4edbc058f..00000000000
--- a/changelogs/unreleased/jivl-migrate-dashboard-store-vuex.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Migrate the monitoring dashboard store to vuex
-merge_request: 28555
-author:
-type: other
diff --git a/changelogs/unreleased/jupyter_pre_spawn_hook_v2.yml b/changelogs/unreleased/jupyter_pre_spawn_hook_v2.yml
deleted file mode 100644
index c5918df8193..00000000000
--- a/changelogs/unreleased/jupyter_pre_spawn_hook_v2.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Pass user's identity and token from JupyterHub to user's Jupyter environment
-merge_request: 27314
-author: Amit Rathi
-type: added
diff --git a/changelogs/unreleased/kinolaev-master-patch-13154.yml b/changelogs/unreleased/kinolaev-master-patch-13154.yml
deleted file mode 100644
index 3292ff797e2..00000000000
--- a/changelogs/unreleased/kinolaev-master-patch-13154.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: 'Auto-DevOps: allow to disable rollout status check'
-merge_request: 28130
-author: Sergej Nikolaev <kinolaev@gmail.com>
-type: fixed
diff --git a/changelogs/unreleased/leipert-node-12-compatibility.yml b/changelogs/unreleased/leipert-node-12-compatibility.yml
deleted file mode 100644
index 18025d33a6d..00000000000
--- a/changelogs/unreleased/leipert-node-12-compatibility.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Upgrade dependencies for node 12 compatibility
-merge_request: 28323
-author:
-type: fixed
diff --git a/changelogs/unreleased/make-autocomplete-faster-with-lots-of-results.yml b/changelogs/unreleased/make-autocomplete-faster-with-lots-of-results.yml
deleted file mode 100644
index daeefd3ffd7..00000000000
--- a/changelogs/unreleased/make-autocomplete-faster-with-lots-of-results.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Improve performance of users autocomplete when there are lots of results
-merge_request:
-author:
-type: performance
diff --git a/changelogs/unreleased/mark-comment-resolved.yml b/changelogs/unreleased/mark-comment-resolved.yml
deleted file mode 100644
index 3343d18d16f..00000000000
--- a/changelogs/unreleased/mark-comment-resolved.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Change resolve button text to mark comment as resolved
-merge_request:
-author:
-type: fixed
diff --git a/changelogs/unreleased/migrate_k8s_service_integration.yml b/changelogs/unreleased/migrate_k8s_service_integration.yml
deleted file mode 100644
index 57f03e6bdab..00000000000
--- a/changelogs/unreleased/migrate_k8s_service_integration.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Migrate Kubernetes service integration templates to clusters
-merge_request: 28534
-author:
-type: added
diff --git a/changelogs/unreleased/mm12935.yml b/changelogs/unreleased/mm12935.yml
deleted file mode 100644
index 782586c514e..00000000000
--- a/changelogs/unreleased/mm12935.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Remove Content-Type override for Mattermost OAuth login
-merge_request:
-author: Harrison Healey
-type: removed
diff --git a/changelogs/unreleased/osw-avoid-500-on-suggestions-check.yml b/changelogs/unreleased/osw-avoid-500-on-suggestions-check.yml
deleted file mode 100644
index d0a09385d4c..00000000000
--- a/changelogs/unreleased/osw-avoid-500-on-suggestions-check.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Avoid 500 when rendering users ATOM data
-merge_request: 25408
-author:
-type: fixed
diff --git a/changelogs/unreleased/osw-avoid-encoding-errors-on-merge-to-ref-service.yml b/changelogs/unreleased/osw-avoid-encoding-errors-on-merge-to-ref-service.yml
deleted file mode 100644
index 176c8bf36f7..00000000000
--- a/changelogs/unreleased/osw-avoid-encoding-errors-on-merge-to-ref-service.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Handle encoding errors for MergeToRefService
-merge_request: 29440
-author:
-type: fixed
diff --git a/changelogs/unreleased/osw-fix-post-dep-migration-with-timeout.yml b/changelogs/unreleased/osw-fix-post-dep-migration-with-timeout.yml
deleted file mode 100644
index 6b37bb11ad5..00000000000
--- a/changelogs/unreleased/osw-fix-post-dep-migration-with-timeout.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Avoid DB timeouts when scheduling migrations
-merge_request: 29437
-author:
-type: fixed
diff --git a/changelogs/unreleased/osw-reset-merge-status-from-mergeable-mrs.yml b/changelogs/unreleased/osw-reset-merge-status-from-mergeable-mrs.yml
deleted file mode 100644
index 6b5f97f24b3..00000000000
--- a/changelogs/unreleased/osw-reset-merge-status-from-mergeable-mrs.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Reset merge status from mergeable MRs
-merge_request: 28843
-author:
-type: other
diff --git a/changelogs/unreleased/osw-sync-merge-ref-upon-mergeability-check.yml b/changelogs/unreleased/osw-sync-merge-ref-upon-mergeability-check.yml
new file mode 100644
index 00000000000..d2744cddebd
--- /dev/null
+++ b/changelogs/unreleased/osw-sync-merge-ref-upon-mergeability-check.yml
@@ -0,0 +1,5 @@
+---
+title: Sync merge ref upon mergeability check
+merge_request: 29569
+author:
+type: added
diff --git a/changelogs/unreleased/paginate-license-management.yml b/changelogs/unreleased/paginate-license-management.yml
new file mode 100644
index 00000000000..c5134978612
--- /dev/null
+++ b/changelogs/unreleased/paginate-license-management.yml
@@ -0,0 +1,5 @@
+---
+title: Backport and Docs for Paginate license management and add license search
+merge_request: 27602
+author:
+type: changed
diff --git a/changelogs/unreleased/patch-55.yml b/changelogs/unreleased/patch-55.yml
deleted file mode 100644
index 7a6d6bfed2f..00000000000
--- a/changelogs/unreleased/patch-55.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Better isolated `Docker.gitlab-ci.yml` to avoid interference with other job configurations.
-merge_request: 28213
-author: lrkwz
-type: changed
diff --git a/changelogs/unreleased/patch-65.yml b/changelogs/unreleased/patch-65.yml
deleted file mode 100644
index 9ce628a6541..00000000000
--- a/changelogs/unreleased/patch-65.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Show tooltip on truncated commit title
-merge_request: 28865
-author: Timofey Trofimov
-type: other
diff --git a/changelogs/unreleased/patch-issue--56683.yml b/changelogs/unreleased/patch-issue--56683.yml
deleted file mode 100644
index 9b82c6c1459..00000000000
--- a/changelogs/unreleased/patch-issue--56683.yml
+++ /dev/null
@@ -1,6 +0,0 @@
----
-title: Process up to 100 commit messages for references when pushing to a new default
- branch
-merge_request: 29511
-author: Fabio Papa
-type: fixed
diff --git a/changelogs/unreleased/pb-update-gitaly-1-45-0.yml b/changelogs/unreleased/pb-update-gitaly-1-45-0.yml
deleted file mode 100644
index eaad7a8378b..00000000000
--- a/changelogs/unreleased/pb-update-gitaly-1-45-0.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Update GITALY_SERVER_VERSION to 1.45.0
-merge_request: 29109
-author:
-type: changed
diff --git a/changelogs/unreleased/pipelines-email-default-branch-filter.yml b/changelogs/unreleased/pipelines-email-default-branch-filter.yml
deleted file mode 100644
index 4c2a54af0bf..00000000000
--- a/changelogs/unreleased/pipelines-email-default-branch-filter.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Add notify_only_default_branch option to PipelinesEmailService
-merge_request: 28271
-author: Peter Marko
-type: added
diff --git a/changelogs/unreleased/readonly_k8s_integration.yml b/changelogs/unreleased/readonly_k8s_integration.yml
deleted file mode 100644
index 718705e8750..00000000000
--- a/changelogs/unreleased/readonly_k8s_integration.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Make Kubernetes service templates readonly
-merge_request: 29044
-author:
-type: removed
diff --git a/changelogs/unreleased/referenced-labels.yml b/changelogs/unreleased/referenced-labels.yml
deleted file mode 100644
index c39ef4c2478..00000000000
--- a/changelogs/unreleased/referenced-labels.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Add referenced-commands in no overflow list
-merge_request: 28858
-author:
-type: fixed
diff --git a/changelogs/unreleased/relative-urls-for-system-notes.yml b/changelogs/unreleased/relative-urls-for-system-notes.yml
deleted file mode 100644
index ec834e9f277..00000000000
--- a/changelogs/unreleased/relative-urls-for-system-notes.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Change links in system notes to use relative paths
-merge_request: 28588
-author: Luke Picciau
-type: fixed
diff --git a/changelogs/unreleased/remove-grafana-dashboard-link-feature-flag.yml b/changelogs/unreleased/remove-grafana-dashboard-link-feature-flag.yml
deleted file mode 100644
index 24b5fb50e40..00000000000
--- a/changelogs/unreleased/remove-grafana-dashboard-link-feature-flag.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Link to an external dashboard from metrics dashboard
-merge_request: 29369
-author:
-type: added
diff --git a/changelogs/unreleased/remove-legacy-artifacts-related-code.yml b/changelogs/unreleased/remove-legacy-artifacts-related-code.yml
deleted file mode 100644
index acde65af2d4..00000000000
--- a/changelogs/unreleased/remove-legacy-artifacts-related-code.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Remove legacy artifact related code
-merge_request: 26475
-author:
-type: other
diff --git a/changelogs/unreleased/remove-mr-diff-header-height.yml b/changelogs/unreleased/remove-mr-diff-header-height.yml
deleted file mode 100644
index c06c7281c58..00000000000
--- a/changelogs/unreleased/remove-mr-diff-header-height.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Remove fixed height from MR diff headers
-merge_request:
-author:
-type: other
diff --git a/changelogs/unreleased/revert-concurrent-pipeline-schedule-creation.yml b/changelogs/unreleased/revert-concurrent-pipeline-schedule-creation.yml
deleted file mode 100644
index 77423463d22..00000000000
--- a/changelogs/unreleased/revert-concurrent-pipeline-schedule-creation.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Revert concurrent pipeline creation for pipeline schedules
-merge_request: 29794
-author:
-type: fixed
diff --git a/changelogs/unreleased/sanitize_rake_ldap_check_output.yml b/changelogs/unreleased/sanitize_rake_ldap_check_output.yml
new file mode 100644
index 00000000000..92824d1dd48
--- /dev/null
+++ b/changelogs/unreleased/sanitize_rake_ldap_check_output.yml
@@ -0,0 +1,5 @@
+---
+title: Sanitize LDAP output in Rake tasks
+merge_request: 28427
+author:
+type: fixed
diff --git a/changelogs/unreleased/search-blob-basenames.yml b/changelogs/unreleased/search-blob-basenames.yml
new file mode 100644
index 00000000000..48ad1130e3f
--- /dev/null
+++ b/changelogs/unreleased/search-blob-basenames.yml
@@ -0,0 +1,5 @@
+---
+title: Build correct basenames for title search results
+merge_request: 29898
+author:
+type: fixed
diff --git a/changelogs/unreleased/security-58856-persistent-xss-in-note-objects.yml b/changelogs/unreleased/security-58856-persistent-xss-in-note-objects.yml
deleted file mode 100644
index d9ad5af256a..00000000000
--- a/changelogs/unreleased/security-58856-persistent-xss-in-note-objects.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Prevent XSS injection in note imports
-merge_request:
-author:
-type: security
diff --git a/changelogs/unreleased/security-60039.yml b/changelogs/unreleased/security-60039.yml
deleted file mode 100644
index 5edbf32ec97..00000000000
--- a/changelogs/unreleased/security-60039.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Prevent invalid branch for merge request
-merge_request:
-author:
-type: security
diff --git a/changelogs/unreleased/security-60143-address-xss-issue-in-wiki-links.yml b/changelogs/unreleased/security-60143-address-xss-issue-in-wiki-links.yml
deleted file mode 100644
index 5b79258af54..00000000000
--- a/changelogs/unreleased/security-60143-address-xss-issue-in-wiki-links.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Filter relative links in wiki for XSS
-merge_request:
-author:
-type: security
diff --git a/changelogs/unreleased/security-fix-confidential-issue-label-visibility-master.yml b/changelogs/unreleased/security-fix-confidential-issue-label-visibility-master.yml
deleted file mode 100644
index adfd8e1298f..00000000000
--- a/changelogs/unreleased/security-fix-confidential-issue-label-visibility-master.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix confidential issue label disclosure on milestone view
-merge_request:
-author:
-type: security
diff --git a/changelogs/unreleased/security-fix-project-existence-disclosure-master.yml b/changelogs/unreleased/security-fix-project-existence-disclosure-master.yml
deleted file mode 100644
index 084439c71d9..00000000000
--- a/changelogs/unreleased/security-fix-project-existence-disclosure-master.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix url redaction for issue links
-merge_request:
-author:
-type: security
diff --git a/changelogs/unreleased/security-fix_milestones_search_api_leak.yml b/changelogs/unreleased/security-fix_milestones_search_api_leak.yml
deleted file mode 100644
index 5691550b602..00000000000
--- a/changelogs/unreleased/security-fix_milestones_search_api_leak.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: 'Resolve: Milestones leaked via search API'
-merge_request:
-author:
-type: security
diff --git a/changelogs/unreleased/security-id-leaked-password-in-import-url-frontend.yml b/changelogs/unreleased/security-id-leaked-password-in-import-url-frontend.yml
deleted file mode 100644
index df636ec37fb..00000000000
--- a/changelogs/unreleased/security-id-leaked-password-in-import-url-frontend.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Add extra fields for handling basic auth on import by url page
-merge_request:
-author:
-type: security
diff --git a/changelogs/unreleased/security-jej-prevent-web-sign-in-bypass.yml b/changelogs/unreleased/security-jej-prevent-web-sign-in-bypass.yml
deleted file mode 100644
index 02773fa1d7c..00000000000
--- a/changelogs/unreleased/security-jej-prevent-web-sign-in-bypass.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Prevent bypass of restriction disabling web password sign in
-merge_request:
-author:
-type: security
diff --git a/changelogs/unreleased/security-unsubscribing-from-issue.yml b/changelogs/unreleased/security-unsubscribing-from-issue.yml
deleted file mode 100644
index 3a33a457c69..00000000000
--- a/changelogs/unreleased/security-unsubscribing-from-issue.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Hide confidential issue title on unsubscribe for anonymous users
-merge_request:
-author:
-type: security
diff --git a/changelogs/unreleased/set-real-next-run-at-for-preventing-duplciate-pipeline-creations.yml b/changelogs/unreleased/set-real-next-run-at-for-preventing-duplciate-pipeline-creations.yml
deleted file mode 100644
index 04eb035b157..00000000000
--- a/changelogs/unreleased/set-real-next-run-at-for-preventing-duplciate-pipeline-creations.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Make pipeline schedule worker resilient
-merge_request: 28407
-author:
-type: performance
diff --git a/changelogs/unreleased/sh-add-backtrace-to-sql-queries.yml b/changelogs/unreleased/sh-add-backtrace-to-sql-queries.yml
deleted file mode 100644
index d4ca027d1b9..00000000000
--- a/changelogs/unreleased/sh-add-backtrace-to-sql-queries.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Add backtraces to Peek performance bar for SQL calls
-merge_request:
-author:
-type: added
diff --git a/changelogs/unreleased/sh-add-header-to-jobs-admin-page.yml b/changelogs/unreleased/sh-add-header-to-jobs-admin-page.yml
deleted file mode 100644
index b089e6e4f37..00000000000
--- a/changelogs/unreleased/sh-add-header-to-jobs-admin-page.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Add a column header to admin/jobs page
-merge_request: 28837
-author:
-type: other
diff --git a/changelogs/unreleased/sh-clean-up-bitbucket-import-errors.yml b/changelogs/unreleased/sh-clean-up-bitbucket-import-errors.yml
new file mode 100644
index 00000000000..e4c9de74e6a
--- /dev/null
+++ b/changelogs/unreleased/sh-clean-up-bitbucket-import-errors.yml
@@ -0,0 +1,5 @@
+---
+title: Avoid storing backtraces from Bitbucket Cloud imports in the database
+merge_request: 29862
+author:
+type: performance
diff --git a/changelogs/unreleased/sh-default-visibility-fix.yml b/changelogs/unreleased/sh-default-visibility-fix.yml
deleted file mode 100644
index 8308f310150..00000000000
--- a/changelogs/unreleased/sh-default-visibility-fix.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Set project default visibility to max allowed
-merge_request: 28754
-author:
-type: fixed
diff --git a/changelogs/unreleased/sh-enable-ref-name-caching-discussions.yml b/changelogs/unreleased/sh-enable-ref-name-caching-discussions.yml
new file mode 100644
index 00000000000..12f4a5a499d
--- /dev/null
+++ b/changelogs/unreleased/sh-enable-ref-name-caching-discussions.yml
@@ -0,0 +1,5 @@
+---
+title: Enable Gitaly ref name caching for discussions.json
+merge_request: 29951
+author:
+type: performance
diff --git a/changelogs/unreleased/sh-fix-fogbugz-import.yml b/changelogs/unreleased/sh-fix-fogbugz-import.yml
deleted file mode 100644
index 1ac730fca24..00000000000
--- a/changelogs/unreleased/sh-fix-fogbugz-import.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix Fogbugz Importer not working
-merge_request: 29383
-author:
-type: fixed
diff --git a/changelogs/unreleased/sh-fix-issue-55869.yml b/changelogs/unreleased/sh-fix-issue-55869.yml
deleted file mode 100644
index 7935cffc13b..00000000000
--- a/changelogs/unreleased/sh-fix-issue-55869.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix alignment of resend button in members page
-merge_request: 28202
-author:
-type: other
diff --git a/changelogs/unreleased/sh-fix-issue-63158.yml b/changelogs/unreleased/sh-fix-issue-63158.yml
deleted file mode 100644
index 1a79166b6a2..00000000000
--- a/changelogs/unreleased/sh-fix-issue-63158.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix inability to set visibility_level on project via API
-merge_request: 29578
-author:
-type: fixed
diff --git a/changelogs/unreleased/sh-fix-rebase-error-clearing.yml b/changelogs/unreleased/sh-fix-rebase-error-clearing.yml
deleted file mode 100644
index 4f5f2779e7f..00000000000
--- a/changelogs/unreleased/sh-fix-rebase-error-clearing.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Properly clear the merge error upon rebase failure
-merge_request: 28319
-author:
-type: fixed
diff --git a/changelogs/unreleased/sh-fix-resolve-button-not-available.yml b/changelogs/unreleased/sh-fix-resolve-button-not-available.yml
deleted file mode 100644
index 85a9007f570..00000000000
--- a/changelogs/unreleased/sh-fix-resolve-button-not-available.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix "Resolve conflicts" button not appearing for some users
-merge_request: 29535
-author:
-type: fixed
diff --git a/changelogs/unreleased/sh-fix-tag-push-remote-mirror.yml b/changelogs/unreleased/sh-fix-tag-push-remote-mirror.yml
deleted file mode 100644
index 7f33ab28e3d..00000000000
--- a/changelogs/unreleased/sh-fix-tag-push-remote-mirror.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix remote mirrors not updating after tag push
-merge_request:
-author:
-type: fixed
diff --git a/changelogs/unreleased/sh-fix-utf-8-encoding-resolve-conflicts.yml b/changelogs/unreleased/sh-fix-utf-8-encoding-resolve-conflicts.yml
deleted file mode 100644
index 31039099788..00000000000
--- a/changelogs/unreleased/sh-fix-utf-8-encoding-resolve-conflicts.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix UTF-8 conversion issues when resolving conflicts
-merge_request: 29453
-author:
-type: fixed
diff --git a/changelogs/unreleased/sh-omit-blocked-admins-from-notification.yml b/changelogs/unreleased/sh-omit-blocked-admins-from-notification.yml
deleted file mode 100644
index 82c5505892f..00000000000
--- a/changelogs/unreleased/sh-omit-blocked-admins-from-notification.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Omit blocked admins from repository check e-mails
-merge_request: 29507
-author:
-type: fixed
diff --git a/changelogs/unreleased/sh-optimize-todos-controller.yml b/changelogs/unreleased/sh-optimize-todos-controller.yml
new file mode 100644
index 00000000000..181ddd1b3bc
--- /dev/null
+++ b/changelogs/unreleased/sh-optimize-todos-controller.yml
@@ -0,0 +1,5 @@
+---
+title: Eliminate N+1 queries in Dashboard::TodosController
+merge_request: 29954
+author:
+type: performance
diff --git a/changelogs/unreleased/sh-speed-up-commit-loading.yml b/changelogs/unreleased/sh-speed-up-commit-loading.yml
deleted file mode 100644
index db408708385..00000000000
--- a/changelogs/unreleased/sh-speed-up-commit-loading.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Speed up commit loads by disabling BatchLoader replace_methods
-merge_request: 29633
-author:
-type: performance
diff --git a/changelogs/unreleased/sh-strong-memoize-appearances.yml b/changelogs/unreleased/sh-strong-memoize-appearances.yml
new file mode 100644
index 00000000000..dc4fe1c4d8e
--- /dev/null
+++ b/changelogs/unreleased/sh-strong-memoize-appearances.yml
@@ -0,0 +1,5 @@
+---
+title: Memoize non-existent custom appearances
+merge_request: 29957
+author:
+type: performance
diff --git a/changelogs/unreleased/sh-update-process-mem.yml b/changelogs/unreleased/sh-update-process-mem.yml
deleted file mode 100644
index 51b22fb0f00..00000000000
--- a/changelogs/unreleased/sh-update-process-mem.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Update get_process_mem to 0.2.3
-merge_request: 28248
-author:
-type: other
diff --git a/changelogs/unreleased/sh-upgrade-ruby-2-6-3-ce.yml b/changelogs/unreleased/sh-upgrade-ruby-2-6-3-ce.yml
deleted file mode 100644
index 9ad5c9ebb64..00000000000
--- a/changelogs/unreleased/sh-upgrade-ruby-2-6-3-ce.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Upgrade Ruby version to 2.6.3
-merge_request: 28117
-author:
-type: performance
diff --git a/changelogs/unreleased/t1.yml b/changelogs/unreleased/t1.yml
deleted file mode 100644
index 6740375485d..00000000000
--- a/changelogs/unreleased/t1.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Set up git client in Jupyter installtion
-merge_request: 28783
-author: Amit Rathi
-type: added
diff --git a/changelogs/unreleased/thomas-nilsson-irfu-gitlab-ce-thomas-nilsson-irfu-master-patch-13137.yml b/changelogs/unreleased/thomas-nilsson-irfu-gitlab-ce-thomas-nilsson-irfu-master-patch-13137.yml
deleted file mode 100644
index 3391fcc9537..00000000000
--- a/changelogs/unreleased/thomas-nilsson-irfu-gitlab-ce-thomas-nilsson-irfu-master-patch-13137.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Allow masking if 8 or more characters in base64.
-merge_request: 29143
-author: thomas-nilsson-irfu
-type: changed
diff --git a/changelogs/unreleased/update-babel-to-7-4-4.yml b/changelogs/unreleased/update-babel-to-7-4-4.yml
deleted file mode 100644
index 0d4b4700bb2..00000000000
--- a/changelogs/unreleased/update-babel-to-7-4-4.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Upgrade babel to 7.4.4
-merge_request: 28437
-author: Takuya Noguchi
-type: other
diff --git a/changelogs/unreleased/update-gitaly-to-v1-42-1.yml b/changelogs/unreleased/update-gitaly-to-v1-42-1.yml
deleted file mode 100644
index ff42bdd9c0b..00000000000
--- a/changelogs/unreleased/update-gitaly-to-v1-42-1.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: "Update Gitaly to v1.42.1"
-merge_request: 28425
-author:
-type: other
diff --git a/changelogs/unreleased/update-gitlab-runner-helm-chart-to-0-5-0.yml b/changelogs/unreleased/update-gitlab-runner-helm-chart-to-0-5-0.yml
deleted file mode 100644
index 494331158fb..00000000000
--- a/changelogs/unreleased/update-gitlab-runner-helm-chart-to-0-5-0.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Update GitLab Runner Helm Chart to 0.5.0
-merge_request: 28497
-author:
-type: other
diff --git a/changelogs/unreleased/update-gitlab-runner-helm-chart-to-0-5-1.yml b/changelogs/unreleased/update-gitlab-runner-helm-chart-to-0-5-1.yml
deleted file mode 100644
index dd71aa7d461..00000000000
--- a/changelogs/unreleased/update-gitlab-runner-helm-chart-to-0-5-1.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Update GitLab Runner Helm Chart to 0.5.1
-merge_request: 28720
-author:
-type: other
diff --git a/changelogs/unreleased/update-gitlab-runner-helm-chart-to-0-5-2.yml b/changelogs/unreleased/update-gitlab-runner-helm-chart-to-0-5-2.yml
deleted file mode 100644
index 9ca6d18c2a8..00000000000
--- a/changelogs/unreleased/update-gitlab-runner-helm-chart-to-0-5-2.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Update GitLab Runner Helm Chart to 0.5.2
-merge_request: 29050
-author:
-type: other
diff --git a/changelogs/unreleased/update-gitlab-shell-9-3-0.yml b/changelogs/unreleased/update-gitlab-shell-9-3-0.yml
deleted file mode 100644
index 781ff31c7d8..00000000000
--- a/changelogs/unreleased/update-gitlab-shell-9-3-0.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Update to GitLab Shell v9.3.0
-merge_request: 29283
-author:
-type: other
diff --git a/changelogs/unreleased/update-pages.yml b/changelogs/unreleased/update-pages.yml
deleted file mode 100644
index 97a20b6b8fa..00000000000
--- a/changelogs/unreleased/update-pages.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Update GitLab Pages to v1.6.0
-merge_request: 29048
-author:
-type: other
diff --git a/changelogs/unreleased/update-pagination-texts.yml b/changelogs/unreleased/update-pagination-texts.yml
new file mode 100644
index 00000000000..6a398e26242
--- /dev/null
+++ b/changelogs/unreleased/update-pagination-texts.yml
@@ -0,0 +1,5 @@
+---
+title: Update pagination prev and next texts
+merge_request: 29911
+author:
+type: other
diff --git a/changelogs/unreleased/update-psd-doc.yml b/changelogs/unreleased/update-psd-doc.yml
deleted file mode 100644
index 38c8d1c0d68..00000000000
--- a/changelogs/unreleased/update-psd-doc.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Update project security dashboard documentation
-merge_request: 28681
-author:
-type: changed
diff --git a/changelogs/unreleased/update-smileys-new.yml b/changelogs/unreleased/update-smileys-new.yml
deleted file mode 100644
index 0e3f606c81b..00000000000
--- a/changelogs/unreleased/update-smileys-new.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Update new smiley icons, find n replace old names with new ones
-merge_request: 28338
-author: Jarek Ostrowski
-type: changed
diff --git a/changelogs/unreleased/update-tar-to-2-2-2.yml b/changelogs/unreleased/update-tar-to-2-2-2.yml
new file mode 100644
index 00000000000..f142fe59448
--- /dev/null
+++ b/changelogs/unreleased/update-tar-to-2-2-2.yml
@@ -0,0 +1,5 @@
+---
+title: Update tar to 2.2.2
+merge_request: 29949
+author: Takuya Noguchi
+type: security
diff --git a/changelogs/unreleased/upgrade-pages-to-v1-6-1.yml b/changelogs/unreleased/upgrade-pages-to-v1-6-1.yml
deleted file mode 100644
index 0ab58bb50d8..00000000000
--- a/changelogs/unreleased/upgrade-pages-to-v1-6-1.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Update GitLab Pages to v1.6.1
-merge_request: 29559
-author:
-type: other
diff --git a/changelogs/unreleased/variables-boolean-type.yml b/changelogs/unreleased/variables-boolean-type.yml
deleted file mode 100644
index 7776657f60a..00000000000
--- a/changelogs/unreleased/variables-boolean-type.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: 'API: change masked attribute type to Boolean'
-merge_request: 28758
-author:
-type: other
diff --git a/changelogs/unreleased/visual-review-apps-fix-dropdown.yml b/changelogs/unreleased/visual-review-apps-fix-dropdown.yml
deleted file mode 100644
index ade68c26df9..00000000000
--- a/changelogs/unreleased/visual-review-apps-fix-dropdown.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Move Dropdown to Stick to MR View App Button
-merge_request: 29767
-author:
-type: fixed
diff --git a/changelogs/unreleased/weimeng-email-routing.yml b/changelogs/unreleased/weimeng-email-routing.yml
deleted file mode 100644
index 6536433bd03..00000000000
--- a/changelogs/unreleased/weimeng-email-routing.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Add ability to define notification email addresses for groups you belong to.
-merge_request: 25299
-author:
-type: added
diff --git a/changelogs/unreleased/winh-notes-error-handling.yml b/changelogs/unreleased/winh-notes-error-handling.yml
deleted file mode 100644
index 6f23dd459d4..00000000000
--- a/changelogs/unreleased/winh-notes-error-handling.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Handle errors in successful notes reply
-merge_request: 28082
-author:
-type: fixed
diff --git a/changelogs/unreleased/zj-remove-delta-island-feature-flag.yml b/changelogs/unreleased/zj-remove-delta-island-feature-flag.yml
deleted file mode 100644
index e752e01b701..00000000000
--- a/changelogs/unreleased/zj-remove-delta-island-feature-flag.yml
+++ /dev/null
@@ -1,3 +0,0 @@
-merge_request: 28871
-title: Improve clone performance by using delta islands
-type: performance
diff --git a/changelogs/unreleased/zj-usage-ping-pool-repository.yml b/changelogs/unreleased/zj-usage-ping-pool-repository.yml
deleted file mode 100644
index 62044a933d0..00000000000
--- a/changelogs/unreleased/zj-usage-ping-pool-repository.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Add Pool repository to the usage ping
-merge_request: 28267
-author:
-type: other
diff --git a/config/initializers/1_settings.rb b/config/initializers/1_settings.rb
index 6cca7a3b75f..4b0bb86e42a 100644
--- a/config/initializers/1_settings.rb
+++ b/config/initializers/1_settings.rb
@@ -367,6 +367,10 @@ Settings.cron_jobs['pages_domain_removal_cron_worker'] ||= Settingslogic.new({})
Settings.cron_jobs['pages_domain_removal_cron_worker']['cron'] ||= '47 0 * * *'
Settings.cron_jobs['pages_domain_removal_cron_worker']['job_class'] = 'PagesDomainRemovalCronWorker'
+Settings.cron_jobs['pages_domain_ssl_renewal_cron_worker'] ||= Settingslogic.new({})
+Settings.cron_jobs['pages_domain_ssl_renewal_cron_worker']['cron'] ||= '*/5 * * * *'
+Settings.cron_jobs['pages_domain_ssl_renewal_cron_worker']['job_class'] = 'PagesDomainSslRenewalCronWorker'
+
Settings.cron_jobs['issue_due_scheduler_worker'] ||= Settingslogic.new({})
Settings.cron_jobs['issue_due_scheduler_worker']['cron'] ||= '50 00 * * *'
Settings.cron_jobs['issue_due_scheduler_worker']['job_class'] = 'IssueDueSchedulerWorker'
diff --git a/config/initializers/forbid_sidekiq_in_transactions.rb b/config/initializers/forbid_sidekiq_in_transactions.rb
index deb94d7dbce..a69f1ba090e 100644
--- a/config/initializers/forbid_sidekiq_in_transactions.rb
+++ b/config/initializers/forbid_sidekiq_in_transactions.rb
@@ -17,7 +17,7 @@ module Sidekiq
module NoEnqueueingFromTransactions
%i(perform_async perform_at perform_in).each do |name|
define_method(name) do |*args|
- if !Sidekiq::Worker.skip_transaction_check && AfterCommitQueue.inside_transaction?
+ if !Sidekiq::Worker.skip_transaction_check && Gitlab::Database.inside_transaction?
begin
raise Sidekiq::Worker::EnqueueFromTransactionError, <<~MSG
`#{self}.#{name}` cannot be called inside a transaction as this can lead to
diff --git a/config/routes/project.rb b/config/routes/project.rb
index a1e769f6ca3..0e8e089c78a 100644
--- a/config/routes/project.rb
+++ b/config/routes/project.rb
@@ -406,6 +406,7 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do
post :toggle_subscription
post :mark_as_spam
post :move
+ put :reorder
get :related_branches
get :can_create_branch
get :realtime_changes
diff --git a/config/sidekiq_queues.yml b/config/sidekiq_queues.yml
index 4fda9d69077..25fd65d8644 100644
--- a/config/sidekiq_queues.yml
+++ b/config/sidekiq_queues.yml
@@ -72,6 +72,7 @@
- [project_rollback_hashed_storage, 1]
- [hashed_storage, 1]
- [pages_domain_verification, 1]
+ - [pages_domain_ssl_renewal, 1]
- [object_storage_upload, 1]
- [object_storage, 1]
- [plugin, 1]
diff --git a/db/migrate/20190607085356_add_source_to_pages_domains.rb b/db/migrate/20190607085356_add_source_to_pages_domains.rb
new file mode 100644
index 00000000000..0a845d7d11f
--- /dev/null
+++ b/db/migrate/20190607085356_add_source_to_pages_domains.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+# See http://doc.gitlab.com/ce/development/migration_style_guide.html
+# for more information on how to write migrations for GitLab.
+
+class AddSourceToPagesDomains < ActiveRecord::Migration[5.1]
+ include Gitlab::Database::MigrationHelpers
+
+ # Set this constant to true if this migration requires downtime.
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ add_column_with_default(:pages_domains, :certificate_source, :smallint, default: 0)
+ end
+
+ def down
+ remove_column(:pages_domains, :certificate_source)
+ end
+end
diff --git a/db/migrate/20190607145325_add_pages_domains_ssl_renew_index.rb b/db/migrate/20190607145325_add_pages_domains_ssl_renew_index.rb
new file mode 100644
index 00000000000..7167accbf1e
--- /dev/null
+++ b/db/migrate/20190607145325_add_pages_domains_ssl_renew_index.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+# See http://doc.gitlab.com/ce/development/migration_style_guide.html
+# for more information on how to write migrations for GitLab.
+
+class AddPagesDomainsSslRenewIndex < ActiveRecord::Migration[5.1]
+ include Gitlab::Database::MigrationHelpers
+
+ # Set this constant to true if this migration requires downtime.
+ DOWNTIME = false
+
+ INDEX_NAME = 'index_pages_domains_need_auto_ssl_renewal'
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index(:pages_domains, [:certificate_source, :certificate_valid_not_after],
+ where: "auto_ssl_enabled = #{::Gitlab::Database.true_value}", name: INDEX_NAME)
+ end
+
+ def down
+ remove_concurrent_index(:pages_domains, [:certificate_source, :certificate_valid_not_after],
+ where: "auto_ssl_enabled = #{::Gitlab::Database.true_value}", name: INDEX_NAME)
+ end
+end
diff --git a/db/migrate/20190611090827_add_time_tracking_limit_to_hours_to_application_settings.rb b/db/migrate/20190611090827_add_time_tracking_limit_to_hours_to_application_settings.rb
new file mode 100644
index 00000000000..a5f8925c1db
--- /dev/null
+++ b/db/migrate/20190611090827_add_time_tracking_limit_to_hours_to_application_settings.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+# See http://doc.gitlab.com/ce/development/migration_style_guide.html
+# for more information on how to write migrations for GitLab.
+
+class AddTimeTrackingLimitToHoursToApplicationSettings < ActiveRecord::Migration[5.1]
+ include Gitlab::Database::MigrationHelpers
+
+ # Set this constant to true if this migration requires downtime.
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ add_column_with_default :application_settings, :time_tracking_limit_to_hours, :boolean, default: false, allow_null: false
+ end
+
+ def down
+ remove_column :application_settings, :time_tracking_limit_to_hours
+ end
+end
diff --git a/db/post_migrate/20190618171120_update_geo_nodes_primary.rb b/db/post_migrate/20190618171120_update_geo_nodes_primary.rb
new file mode 100644
index 00000000000..dc9cfbda177
--- /dev/null
+++ b/db/post_migrate/20190618171120_update_geo_nodes_primary.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+# See http://doc.gitlab.com/ce/development/migration_style_guide.html
+# for more information on how to write migrations for GitLab.
+
+class UpdateGeoNodesPrimary < ActiveRecord::Migration[5.1]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def up
+ change_column_default(:geo_nodes, :primary, false)
+ change_column_null(:geo_nodes, :primary, false, false)
+ end
+
+ def down
+ change_column_default(:geo_nodes, :primary, nil)
+ change_column_null(:geo_nodes, :primary, true)
+ end
+end
diff --git a/db/post_migrate/20190620112608_enqueue_reset_merge_status_second_run.rb b/db/post_migrate/20190620112608_enqueue_reset_merge_status_second_run.rb
new file mode 100644
index 00000000000..2d096a2a39c
--- /dev/null
+++ b/db/post_migrate/20190620112608_enqueue_reset_merge_status_second_run.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+# See http://doc.gitlab.com/ce/development/migration_style_guide.html
+# for more information on how to write migrations for GitLab.
+
+class EnqueueResetMergeStatusSecondRun < ActiveRecord::Migration[5.1]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+ BATCH_SIZE = 10_000
+ MIGRATION = 'ResetMergeStatus'
+ DELAY_INTERVAL = 5.minutes.to_i
+
+ disable_ddl_transaction!
+
+ def up
+ say 'Scheduling `ResetMergeStatus` jobs'
+
+ # We currently have more than ~5_000_000 merge request records on GitLab.com.
+ # This means it'll schedule ~500 jobs (10k MRs each) with a 5 minutes gap,
+ # so this should take ~41 hours for all background migrations to complete.
+ # ((5_000_000 / 10_000) * 5) / 60 => 41.6666..
+ queue_background_migration_jobs_by_range_at_intervals(MergeRequest, MIGRATION, DELAY_INTERVAL, batch_size: BATCH_SIZE)
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 4e333633a8b..44213fddd86 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: 20190619175843) do
+ActiveRecord::Schema.define(version: 20190620112608) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
@@ -229,6 +229,7 @@ ActiveRecord::Schema.define(version: 20190619175843) do
t.integer "custom_project_templates_group_id"
t.boolean "elasticsearch_limit_indexing", default: false, null: false
t.string "geo_node_allowed_ips", default: "0.0.0.0/0, ::/0"
+ t.boolean "time_tracking_limit_to_hours", default: false, null: false
t.index ["custom_project_templates_group_id"], name: "index_application_settings_on_custom_project_templates_group_id", using: :btree
t.index ["file_template_project_id"], name: "index_application_settings_on_file_template_project_id", using: :btree
t.index ["usage_stats_set_by_user_id"], name: "index_application_settings_on_usage_stats_set_by_user_id", using: :btree
@@ -1391,7 +1392,7 @@ ActiveRecord::Schema.define(version: 20190619175843) do
end
create_table "geo_nodes", id: :serial, force: :cascade do |t|
- t.boolean "primary"
+ t.boolean "primary", default: false, null: false
t.integer "oauth_application_id"
t.boolean "enabled", default: true, null: false
t.string "access_key"
@@ -2333,6 +2334,8 @@ ActiveRecord::Schema.define(version: 20190619175843) do
t.boolean "auto_ssl_enabled", default: false, null: false
t.datetime_with_timezone "certificate_valid_not_before"
t.datetime_with_timezone "certificate_valid_not_after"
+ t.integer "certificate_source", limit: 2, default: 0, null: false
+ t.index ["certificate_source", "certificate_valid_not_after"], name: "index_pages_domains_need_auto_ssl_renewal", where: "(auto_ssl_enabled = true)", using: :btree
t.index ["domain"], name: "index_pages_domains_on_domain", unique: true, using: :btree
t.index ["project_id", "enabled_until"], name: "index_pages_domains_on_project_id_and_enabled_until", using: :btree
t.index ["project_id"], name: "index_pages_domains_on_project_id", using: :btree
diff --git a/doc/administration/auth/ldap.md b/doc/administration/auth/ldap.md
index 54279897e04..1f2961ea39a 100644
--- a/doc/administration/auth/ldap.md
+++ b/doc/administration/auth/ldap.md
@@ -396,21 +396,34 @@ omniauth-ldap.
### Escaping special characters
-If the `user_filter` DN contains special characters. For example, a comma:
+The `user_filter` DN can contain special characters. For example:
-```
-OU=GitLab, Inc,DC=gitlab,DC=com
-```
+- A comma:
-This character needs to be escaped as documented in [RFC 4515](https://tools.ietf.org/search/rfc4515).
+ ```
+ OU=GitLab, Inc,DC=gitlab,DC=com
+ ```
-Due to the way the string is parsed, the special character needs to be converted
-to hex and `\\5C\\` (`5C` = `\` in hex) added before it.
-As an example the above DN would look like
+- Open and close brackets:
-```
-OU=GitLab\\5C\\2C Inc,DC=gitlab,DC=com
-```
+ ```
+ OU=Gitlab (Inc),DC=gitlab,DC=com
+ ```
+
+ These characters must be escaped as documented in
+ [RFC 4515](https://tools.ietf.org/search/rfc4515).
+
+- Escape commas with `\2C`. For example:
+
+ ```
+ OU=GitLab\2C Inc,DC=gitlab,DC=com
+ ```
+
+- Escape open and close brackets with `\28` and `\29`, respectively. For example:
+
+ ```
+ OU=Gitlab \28Inc\29,DC=gitlab,DC=com
+ ```
## Enabling LDAP sign-in for existing GitLab users
diff --git a/doc/administration/auth/oidc.md b/doc/administration/auth/oidc.md
index 00422ec347c..6e48add6930 100644
--- a/doc/administration/auth/oidc.md
+++ b/doc/administration/auth/oidc.md
@@ -144,20 +144,20 @@ for more details:
If you're having trouble, here are some tips:
1. Ensure `discovery` is set to `true`. Setting it to `false` requires
-specifying all the URLs and keys required to make OpenID work.
+ specifying all the URLs and keys required to make OpenID work.
1. Check your system clock to ensure the time is synchronized properly.
1. As mentioned in [the
-documentation](https://github.com/m0n9oose/omniauth_openid_connect),
-make sure `issuer` corresponds to the base URL of the Discovery URL. For
-example, `https://accounts.google.com` is used for the URL
-`https://accounts.google.com/.well-known/openid-configuration`.
+ documentation](https://github.com/m0n9oose/omniauth_openid_connect),
+ make sure `issuer` corresponds to the base URL of the Discovery URL. For
+ example, `https://accounts.google.com` is used for the URL
+ `https://accounts.google.com/.well-known/openid-configuration`.
1. The OpenID Connect client uses HTTP Basic Authentication to send the
-OAuth2 access token. For example, if you are seeing 401 errors upon
-retrieving the `userinfo` endpoint, you may want to check your OpenID
-Web server configuration. For example, for
-[oauth2-server-php](https://github.com/bshaffer/oauth2-server-php), you
-may need to [add a configuration parameter to
-Apache](https://github.com/bshaffer/oauth2-server-php/issues/926#issuecomment-387502778).
+ OAuth2 access token. For example, if you are seeing 401 errors upon
+ retrieving the `userinfo` endpoint, you may want to check your OpenID
+ Web server configuration. For example, for
+ [oauth2-server-php](https://github.com/bshaffer/oauth2-server-php), you
+ may need to [add a configuration parameter to
+ Apache](https://github.com/bshaffer/oauth2-server-php/issues/926#issuecomment-387502778).
diff --git a/doc/administration/geo/replication/faq.md b/doc/administration/geo/replication/faq.md
index dd1af0dbf9c..c527248bc72 100644
--- a/doc/administration/geo/replication/faq.md
+++ b/doc/administration/geo/replication/faq.md
@@ -6,8 +6,8 @@ The requirements are listed [on the index page](index.md#requirements-for-runnin
## How does Geo know which projects to sync?
-On each **secondary** node, there is a read-only replicated copy of the GitLab database.
-A **secondary** node also has a tracking database where it stores which projects have been synced.
+On each **secondary** node, there is a read-only replicated copy of the GitLab database.
+A **secondary** node also has a tracking database where it stores which projects have been synced.
Geo compares the two databases to find projects that are not yet tracked.
At the start, this tracking database is empty, so Geo will start trying to update from every project that it can see in the GitLab database.
@@ -15,19 +15,19 @@ At the start, this tracking database is empty, so Geo will start trying to updat
For each project to sync:
1. Geo will issue a `git fetch geo --mirror` to get the latest information from the **primary** node.
-If there are no changes, the sync will be fast and end quickly. Otherwise, it will pull the latest commits.
+ If there are no changes, the sync will be fast and end quickly. Otherwise, it will pull the latest commits.
1. The **secondary** node will update the tracking database to store the fact that it has synced projects A, B, C, etc.
1. Repeat until all projects are synced.
-When someone pushes a commit to the **primary** node, it generates an event in the GitLab database that the repository has changed.
+When someone pushes a commit to the **primary** node, it generates an event in the GitLab database that the repository has changed.
The **secondary** node sees this event, marks the project in question as dirty, and schedules the project to be resynced.
To ensure that problems with pipelines (for example, syncs failing too many times or jobs being lost) don't permanently stop projects syncing, Geo also periodically checks the tracking database for projects that are marked as dirty. This check happens when
-the number of concurrent syncs falls below `repos_max_capacity` and there are no new projects waiting to be synced.
+the number of concurrent syncs falls below `repos_max_capacity` and there are no new projects waiting to be synced.
-Geo also has a checksum feature which runs a SHA256 sum across all the Git references to the SHA values.
-If the refs don't match between the **primary** node and the **secondary** node, then the **secondary** node will mark that project as dirty and try to resync it.
-So even if we have an outdated tracking database, the validation should activate and find discrepancies in the repository state and resync.
+Geo also has a checksum feature which runs a SHA256 sum across all the Git references to the SHA values.
+If the refs don't match between the **primary** node and the **secondary** node, then the **secondary** node will mark that project as dirty and try to resync it.
+So even if we have an outdated tracking database, the validation should activate and find discrepancies in the repository state and resync.
## Can I use Geo in a disaster recovery situation?
diff --git a/doc/administration/geo/replication/troubleshooting.md b/doc/administration/geo/replication/troubleshooting.md
index c5bdd36ba70..5394e6dd763 100644
--- a/doc/administration/geo/replication/troubleshooting.md
+++ b/doc/administration/geo/replication/troubleshooting.md
@@ -1,15 +1,23 @@
# Geo Troubleshooting **[PREMIUM ONLY]**
-NOTE: **Note:**
-This list is an attempt to document all the moving parts that can go wrong.
-We are working into getting all this steps verified automatically in a
-rake task in the future.
-
Setting up Geo requires careful attention to details and sometimes it's easy to
-miss a step. Here is a list of questions you should ask to try to detect
-what you need to fix (all commands and path locations are for Omnibus installs):
+miss a step.
+
+Here is a list of steps you should take to attempt to fix problem:
+
+- Perform [basic troubleshooting](#basic-troubleshooting).
+- Fix any [replication errors](#fixing-replication-errors).
+- Fix any [Foreign Data Wrapper](#fixing-foreign-data-wrapper-errors) errors.
+- Fix any [common](#fixing-common-errors) errors.
-## First check the health of the **secondary** node
+## Basic troubleshooting
+
+Before attempting more advanced troubleshooting:
+
+- Check [the health of the **secondary** node](#check-the-health-of-the-secondary-node).
+- Check [if PostgreSQL replication is working](#check-if-postgresql-replication-is-working).
+
+### Check the health of the **secondary** node
Visit the **primary** node's **Admin Area > Geo** (`/admin/geo/nodes`) in
your browser. We perform the following health checks on each **secondary** node
@@ -23,10 +31,12 @@ to help identify if something is wrong:
![Geo health check](img/geo_node_healthcheck.png)
-For information on how to resolve common errors reported from the UI, see [common errors](#common-errors).
+For information on how to resolve common errors reported from the UI, see
+[Fixing Common Errors](#fixing-common-errors).
If the UI is not working, or you are unable to log in, you can run the Geo
health check manually to get this information as well as a few more details.
+
This rake task can be run on an app node in the **primary** or **secondary**
Geo nodes:
@@ -36,7 +46,7 @@ sudo gitlab-rake gitlab:geo:check
Example output:
-```
+```text
Checking Geo ...
GitLab Geo is available ... yes
@@ -68,7 +78,7 @@ sudo gitlab-rake geo:status
Example output:
-```
+```text
http://secondary.example.com/
-----------------------------------------------------
GitLab Version: 11.10.4-ee
@@ -89,16 +99,21 @@ http://secondary.example.com/
Last status report was: 2 minutes ago
```
-## Is Postgres replication working?
+### Check if PostgreSQL replication is working
+
+To check if PostgreSQL replication is working, check if:
+
+- [Nodes are pointing to the correct database instance](#are-nodes-pointing-to-the-correct-database-instance).
+- [Geo can detect the current node correctly](#can-geo-detect-the-current-node-correctly).
-### Are my nodes pointing to the correct database instance?
+#### Are nodes pointing to the correct database instance?
You should make sure your **primary** Geo node points to the instance with
writing permissions.
Any **secondary** nodes should point only to read-only instances.
-### Can Geo detect my current node correctly?
+#### Can Geo detect the current node correctly?
Geo uses the defined node from the **Admin Area > Geo** screen, and tries to match
it with the value defined in the `/etc/gitlab/gitlab.rb` configuration file.
@@ -112,29 +127,38 @@ sudo gitlab-rails runner "puts Gitlab::Geo.current_node.inspect"
and expect something like:
-```
+```ruby
#<GeoNode id: 2, schema: "https", host: "gitlab.example.com", port: 443, relative_url_root: "", primary: false, ...>
```
By running the command above, `primary` should be `true` when executed in
the **primary** node, and `false` on any **secondary** node.
-## How do I fix the message, "ERROR: replication slots can only be used if max_replication_slots > 0"?
+## Fixing replication errors
+
+The following sections outline troubleshooting steps for fixing replication
+errors.
+
+### Message: "ERROR: replication slots can only be used if max_replication_slots > 0"?
This means that the `max_replication_slots` PostgreSQL variable needs to
be set on the **primary** database. In GitLab 9.4, we have made this setting
default to 1. You may need to increase this value if you have more
-**secondary** nodes. Be sure to restart PostgreSQL for this to take
+**secondary** nodes.
+
+Be sure to restart PostgreSQL for this to take
effect. See the [PostgreSQL replication
setup][database-pg-replication] guide for more details.
-## How do I fix the message, "FATAL: could not start WAL streaming: ERROR: replication slot "geo_secondary_my_domain_com" does not exist"?
+### Message: "FATAL: could not start WAL streaming: ERROR: replication slot "geo_secondary_my_domain_com" does not exist"?
This occurs when PostgreSQL does not have a replication slot for the
-**secondary** node by that name. You may want to rerun the [replication
+**secondary** node by that name.
+
+You may want to rerun the [replication
process](database.md) on the **secondary** node .
-## How do I fix the message, "Command exceeded allowed execution time" when setting up replication?
+### Message: "Command exceeded allowed execution time" when setting up replication?
This may happen while [initiating the replication process][database-start-replication] on the **secondary** node,
and indicates that your initial dataset is too large to be replicated in the default timeout (30 minutes).
@@ -153,7 +177,7 @@ sudo gitlab-ctl \
This will give the initial replication up to six hours to complete, rather than
the default thirty minutes. Adjust as required for your installation.
-## How do I fix the message, "PANIC: could not write to file 'pg_xlog/xlogtemp.123': No space left on device"
+### Message: "PANIC: could not write to file 'pg_xlog/xlogtemp.123': No space left on device"
Determine if you have any unused replication slots in the **primary** database. This can cause large amounts of
log data to build up in `pg_xlog`. Removing the unused slots can reduce the amount of space used in the `pg_xlog`.
@@ -184,11 +208,12 @@ Slots where `active` is `f` are not active.
SELECT pg_drop_replication_slot('<name_of_extra_slot>');
```
-## Very large repositories never successfully synchronize on the **secondary** node
+### Very large repositories never successfully synchronize on the **secondary** node
GitLab places a timeout on all repository clones, including project imports
and Geo synchronization operations. If a fresh `git clone` of a repository
on the primary takes more than a few minutes, you may be affected by this.
+
To increase the timeout, add the following line to `/etc/gitlab/gitlab.rb`
on the **secondary** node:
@@ -205,7 +230,7 @@ sudo gitlab-ctl reconfigure
This will increase the timeout to three hours (10800 seconds). Choose a time
long enough to accommodate a full clone of your largest repositories.
-## How to reset Geo **secondary** node replication
+### Reseting Geo **secondary** node replication
If you get a **secondary** node in a broken state and want to reset the replication state,
to start again from scratch, there are a few steps that can help you:
@@ -289,12 +314,16 @@ to start again from scratch, there are a few steps that can help you:
gitlab-ctl start
```
-## How do I fix a "Foreign Data Wrapper (FDW) is not configured" error?
+## Fixing Foreign Data Wrapper errors
+
+This section documents ways to fix potential Foreign Data Wrapper errors.
+
+### "Foreign Data Wrapper (FDW) is not configured" error
When setting up Geo, you might see this warning in the `gitlab-rake
gitlab:geo:check` output:
-```
+```text
GitLab Geo tracking database Foreign Data Wrapper schema is up-to-date? ... foreign data wrapper is not configured
```
@@ -302,12 +331,12 @@ There are a few key points to remember:
1. The FDW settings are configured on the Geo **tracking** database.
1. The configured foreign server enables a login to the Geo
-**secondary**, read-only database.
+ **secondary**, read-only database.
By default, the Geo secondary and tracking database are running on the
same host on different ports. That is, 5432 and 5431 respectively.
-### Checking configuration
+#### Checking configuration
NOTE: **Note:**
The following steps are for Omnibus installs only. Using Geo with source-based installs was **deprecated** in GitLab 11.5.
@@ -321,7 +350,7 @@ To check the configuration:
```
1. Check whether any tables are present. If everything is working, you
-should see something like this:
+ should see something like this:
```sql
gitlabhq_geo_production=# SELECT * from information_schema.foreign_tables;
@@ -419,7 +448,7 @@ should see something like this:
- `geo_postgresql['fdw_external_user']`
- `geo_postgresql['fdw_external_password']`
-### Manual reload of FDW schema
+#### Manual reload of FDW schema
If you're still unable to get FDW working, you may want to try a manual
reload of the FDW schema. To manually reload the FDW schema:
@@ -459,9 +488,25 @@ reload of the FDW schema. To manually reload the FDW schema:
[database-start-replication]: database.md#step-3-initiate-the-replication-process
[database-pg-replication]: database.md#postgresql-replication
-## Common errors
+### "Geo database has an outdated FDW remote schema" error
+
+GitLab can error with a `Geo database has an outdated FDW remote schema` message.
+
+For example:
-This section documents common errors reported in the admin UI and how to fix them.
+```text
+Geo database has an outdated FDW remote schema. It contains 229 of 236 expected tables. Please refer to Geo Troubleshooting.
+```
+
+To resolve this, run the following command:
+
+```sh
+sudo gitlab-rake geo:db:refresh_foreign_tables
+```
+
+## Fixing common errors
+
+This section documents common errors reported in the Admin UI and how to fix them.
### Geo database configuration file is missing
@@ -470,7 +515,6 @@ GitLab cannot find or doesn't have permission to access the `database_geo.yml` c
In an Omnibus GitLab installation, the file should be in `/var/opt/gitlab/gitlab-rails/etc`.
If it doesn't exist or inadvertent changes have been made to it, run `sudo gitlab-ctl reconfigure` to restore it to its correct state.
-
If this path is mounted on a remote volume, please check your volume configuration and that it has correct permissions.
### Geo node has a database that is writable which is an indication it is not configured for replication with the primary node.
@@ -503,7 +547,7 @@ Make sure you follow the [Geo database replication](database.md) instructions fo
If you are using GitLab Omnibus installation, something might have failed during upgrade. You can:
-- Run `sudo gitlab-ctl reconfigure`.
+- Run `sudo gitlab-ctl reconfigure`.
- Manually trigger the database migration by running: `sudo gitlab-rake geo:db:migrate` as root on the **secondary** node.
### Geo database is not configured to use Foreign Data Wrapper
@@ -511,4 +555,4 @@ If you are using GitLab Omnibus installation, something might have failed during
This error means the Geo Tracking Database doesn't have the FDW server and credentials
configured.
-See [How do I fix a "Foreign Data Wrapper (FDW) is not configured" error?](#how-do-i-fix-a-foreign-data-wrapper-fdw-is-not-configured-error).
+See ["Foreign Data Wrapper (FDW) is not configured" error?](#foreign-data-wrapper-fdw-is-not-configured-error).
diff --git a/doc/administration/high_availability/README.md b/doc/administration/high_availability/README.md
index d9c80b1ec59..0c4f926c579 100644
--- a/doc/administration/high_availability/README.md
+++ b/doc/administration/high_availability/README.md
@@ -65,6 +65,7 @@ larger one.
- 1 Redis node
- 1 NFS/Gitaly storage server
- 2 or more GitLab application nodes (Unicorn, Workhorse, Sidekiq)
+- 1 Monitoring node (Prometheus, Grafana)
#### Installation Instructions
@@ -76,6 +77,7 @@ you can continue with the next step.
1. [Redis](redis.md#redis-in-a-scaled-environment)
1. [Gitaly](gitaly.md) (recommended) or [NFS](nfs.md)
1. [GitLab application nodes](gitlab.md)
+1. [Monitoring node (Prometheus and Grafana)](monitoring_node.md)
### Full Scaling
@@ -90,6 +92,7 @@ in size, indicating that there is contention or not enough resources.
- 2 or more NFS/Gitaly storage servers
- 2 or more Sidekiq nodes
- 2 or more GitLab application nodes (Unicorn, Workhorse)
+- 1 Monitoring node (Prometheus, Grafana)
## High Availability Architecture Examples
@@ -133,6 +136,7 @@ the contention.
- 3 Consul/Sentinel nodes
- 2 or more GitLab application nodes (Unicorn, Workhorse, Sidekiq, PGBouncer)
- 1 NFS/Gitaly server
+- 1 Monitoring node (Prometheus, Grafana)
![Horizontal architecture diagram](img/horizontal.png)
@@ -192,6 +196,7 @@ with the added complexity of many more nodes to configure, manage and monitor.
- 2 or more API nodes (All requests to `/api`)
- 2 or more Web nodes (All other web requests)
- 2 or more NFS/Gitaly servers
+- 1 Monitoring node (Prometheus, Grafana)
![Fully Distributed architecture diagram](img/fully-distributed.png)
@@ -205,4 +210,5 @@ separately:
1. [NFS Client and Host setup](nfs_host_client_setup.md)
1. [Configure the GitLab application servers](gitlab.md)
1. [Configure the load balancers](load_balancer.md)
+1. [Monitoring node (Prometheus and Grafana)](monitoring_node.md)
diff --git a/doc/administration/high_availability/database.md b/doc/administration/high_availability/database.md
index 2c051b660ee..20bbfdb2603 100644
--- a/doc/administration/high_availability/database.md
+++ b/doc/administration/high_availability/database.md
@@ -82,6 +82,7 @@ deploy the bundled PostgreSQL.
1. Note the PostgreSQL node's IP address or hostname, port, and
plain text password. These will be necessary when configuring the GitLab
application servers later.
+1. [Enable monitoring](#enable-monitoring)
Advanced configuration options are supported and can be added if
needed.
@@ -203,9 +204,9 @@ Few notes on the service itself:
- The service runs under a system account, by default `gitlab-consul`.
- If you are using a different username, you will have to specify it. We
-will refer to it with `CONSUL_USERNAME`,
+ will refer to it with `CONSUL_USERNAME`,
- There will be a database user created with read only access to the repmgr
-database
+ database
- Passwords will be stored in the following locations:
- `/etc/gitlab/gitlab.rb`: hashed
- `/var/opt/gitlab/pgbouncer/pg_auth`: hashed
@@ -399,6 +400,7 @@ check the [Troubleshooting section](#troubleshooting) before proceeding.
```
1. [Reconfigure GitLab] for the changes to take effect.
+1. [Enable Monitoring](#enable-monitoring)
> Please note:
>
@@ -1086,6 +1088,25 @@ the previous section:
the `gitlab` database user
1. [Reconfigure GitLab] for the changes to take effect
+## Enable Monitoring
+
+> [Introduced](https://gitlab.com/gitlab-org/omnibus-gitlab/issues/3786) in GitLab 12.0.
+
+If you enable Monitoring, it must be enabled on **all** database servers.
+
+1. Create/edit `/etc/gitlab/gitlab.rb` and add the following configuration:
+
+ ```ruby
+ # Enable service discovery for Prometheus
+ consul['monitoring_service_discovery'] = true
+
+ # Set the network addresses that the exporters will listen on
+ node_exporter['listen_address'] = '0.0.0.0:9100'
+ postgres_exporter['listen_address'] = '0.0.0.0:9187'
+ ```
+
+1. Run `sudo gitlab-ctl reconfigure` to compile the configuration.
+
## Troubleshooting
#### Consul and PostgreSQL changes not taking effect.
diff --git a/doc/administration/high_availability/gitaly.md b/doc/administration/high_availability/gitaly.md
index 1d8e6c999cb..90e5f71d835 100644
--- a/doc/administration/high_availability/gitaly.md
+++ b/doc/administration/high_availability/gitaly.md
@@ -19,3 +19,28 @@ Continue configuration of other components by going back to:
- [Scaled Architectures](README.md#scalable-architecture-examples)
- [High Availability Architectures](README.md#high-availability-architecture-examples)
+
+## Enable Monitoring
+
+> [Introduced](https://gitlab.com/gitlab-org/omnibus-gitlab/issues/3786) in GitLab 12.0.
+
+ 1. Create/edit `/etc/gitlab/gitlab.rb` and add the following configuration:
+
+ ```ruby
+ # Enable service discovery for Prometheus
+ consul['enable'] = true
+ consul['monitoring_service_discovery'] = true
+
+ # Replace placeholders
+ # Y.Y.Y.Y consul1.gitlab.example.com Z.Z.Z.Z
+ # with the addresses of the Consul server nodes
+ consul['configuration'] = {
+ retry_join: %w(Y.Y.Y.Y consul1.gitlab.example.com Z.Z.Z.Z),
+ }
+
+ # Set the network addresses that the exporters will listen on
+ node_exporter['listen_address'] = '0.0.0.0:9100'
+ gitaly['prometheus_listen_addr'] = "0.0.0.0:9236"
+ ```
+
+ 1. Run `sudo gitlab-ctl reconfigure` to compile the configuration.
diff --git a/doc/administration/high_availability/gitlab.md b/doc/administration/high_availability/gitlab.md
index 7e3ff741071..0e655e49922 100644
--- a/doc/administration/high_availability/gitlab.md
+++ b/doc/administration/high_availability/gitlab.md
@@ -76,6 +76,8 @@
registry['gid'] = 9002
```
+1. [Enable monitoring](#enable-monitoring)
+
> **Note:** To maintain uniformity of links across HA clusters, the `external_url`
on the first application server as well as the additional application
servers should point to the external url that users will use to access GitLab.
@@ -88,7 +90,8 @@
[Nginx documentation](https://docs.gitlab.com/omnibus/settings/nginx.html#enable-https)
for more information.
>
- > **Note:** It is best to set the `uid` and `gid`s prior to the initial reconfigure of GitLab. Omnibus will not recursively `chown` directories if set after the initial reconfigure.
+ > **Note:** It is best to set the `uid` and `gid`s prior to the initial reconfigure
+ of GitLab. Omnibus will not recursively `chown` directories if set after the initial reconfigure.
## First GitLab application server
@@ -129,6 +132,46 @@ need some extra configuration.
1. Run `sudo gitlab-ctl reconfigure` to compile the configuration.
+## Enable Monitoring
+
+> [Introduced](https://gitlab.com/gitlab-org/omnibus-gitlab/issues/3786) in GitLab 12.0.
+
+If you enable Monitoring, it must be enabled on **all** GitLab servers.
+
+1. Create/edit `/etc/gitlab/gitlab.rb` and add the following configuration:
+
+ ```ruby
+ # Enable service discovery for Prometheus
+ consul['enable'] = true
+ consul['monitoring_service_discovery'] = true
+
+ # Replace placeholders
+ # Y.Y.Y.Y consul1.gitlab.example.com Z.Z.Z.Z
+ # with the addresses of the Consul server nodes
+ consul['configuration'] = {
+ retry_join: %w(Y.Y.Y.Y consul1.gitlab.example.com Z.Z.Z.Z),
+ }
+
+ # Set the network addresses that the exporters will listen on
+ node_exporter['listen_address'] = '0.0.0.0:9100'
+ gitlab_workhorse['prometheus_listen_addr'] = '0.0.0.0:9229'
+ sidekiq['listen_address'] = "0.0.0.0"
+ unicorn['listen'] = '0.0.0.0'
+
+ # Add the monitoring node's IP address to the monitoring whitelist and allow it to scrape the NGINX metrics
+ # Replace placeholder
+ # monitoring.gitlab.example.com
+ # with the addresses gathered for the monitoring node
+ gitlab_rails['monitoring_whitelist'] = ['monitoring.gitlab.example.com']
+ nginx['status']['options']['allow'] = ['monitoring.gitlab.example.com']
+ ```
+
+1. Run `sudo gitlab-ctl reconfigure` to compile the configuration.
+
+> **Warning:** After changing `unicorn['listen']` in `gitlab.rb`, and running `sudo gitlab-ctl reconfigure`,
+ it can take an extended period of time for unicorn to complete reloading after receiving a `HUP`.
+ For more information, see the [issue](https://gitlab.com/gitlab-org/omnibus-gitlab/issues/4401).
+
## Troubleshooting
- `mount: wrong fs type, bad option, bad superblock on`
diff --git a/doc/administration/high_availability/monitoring_node.md b/doc/administration/high_availability/monitoring_node.md
new file mode 100644
index 00000000000..d16bf7dc0f0
--- /dev/null
+++ b/doc/administration/high_availability/monitoring_node.md
@@ -0,0 +1,67 @@
+# Configuring a Monitoring node for Scaling and High Availability
+
+> [Introduced](https://gitlab.com/gitlab-org/omnibus-gitlab/issues/3786) in GitLab 12.0.
+
+## Standalone Monitoring node using GitLab Omnibus
+
+The GitLab Omnibus package can be used to configure a standalone Monitoring node running Prometheus and Grafana.
+The monitoring node is not highly available. See [Scaling and High Availability](README.md)
+for an overview of GitLab scaling and high availability options.
+
+The steps below are the minimum necessary to configure a Monitoring node running Prometheus and Grafana with
+Omnibus:
+
+1. SSH into the Monitoring node.
+1. [Download/install](https://about.gitlab.com/installation) the Omnibus GitLab
+ package you want using **steps 1 and 2** from the GitLab downloads page.
+ - Do not complete any other steps on the download page.
+
+1. Edit `/etc/gitlab/gitlab.rb` and add the contents:
+
+ ```ruby
+ external_url 'http://gitlab.example.com'
+
+ # Enable Prometheus
+ prometheus['enable'] = true
+ prometheus['listen_address'] = '0.0.0.0:9090'
+ prometheus['monitor_kubernetes'] = false
+
+ # Enable Grafana
+ grafana['enable'] = true
+ grafana['admin_password'] = 'toomanysecrets'
+
+ # Enable service discovery for Prometheus
+ consul['enable'] = true
+ consul['monitoring_service_discovery'] = true
+
+ # Replace placeholders
+ # Y.Y.Y.Y consul1.gitlab.example.com Z.Z.Z.Z
+ # with the addresses of the Consul server nodes
+ consul['configuration'] = {
+ retry_join: %w(Y.Y.Y.Y consul1.gitlab.example.com Z.Z.Z.Z),
+ }
+
+ # Disable all other services
+ gitlab_rails['auto_migrate'] = false
+ alertmanager['enable'] = false
+ gitaly['enable'] = false
+ gitlab_monitor['enable'] = false
+ gitlab_workhorse['enable'] = false
+ nginx['enable'] = true
+ postgres_exporter['enable'] = false
+ postgresql['enable'] = false
+ redis['enable'] = false
+ redis_exporter['enable'] = false
+ sidekiq['enable'] = false
+ unicorn['enable'] = false
+ node_exporter['enable'] = false
+ ```
+
+1. Run `sudo gitlab-ctl reconfigure` to compile the configuration.
+
+## Migrating to Service Discovery
+
+Once monitoring using Service Discovery is enabled with `consul['monitoring_service_discovery'] = true`,
+ensure that `prometheus['scrape_configs']` is not set in `/etc/gitlab/gitlab.rb`. Setting both
+`consul['monitoring_service_discovery'] = true` and `prometheus['scrape_configs']` in `/etc/gitlab/gitlab.rb`
+will result in errors.
diff --git a/doc/administration/high_availability/redis.md b/doc/administration/high_availability/redis.md
index 1aaa709fc8f..f61a8834af3 100644
--- a/doc/administration/high_availability/redis.md
+++ b/doc/administration/high_availability/redis.md
@@ -74,6 +74,7 @@ Omnibus:
1. Note the Redis node's IP address or hostname, port, and
Redis password. These will be necessary when configuring the GitLab
application servers later.
+1. [Enable Monitoring](#enable-monitoring)
Advanced configuration options are supported and can be added if
needed.
@@ -749,6 +750,33 @@ gitlab_rails['redis_sentinels'] = [
[Reconfigure Omnibus GitLab][reconfigure] for the changes to take effect.
+## Enable Monitoring
+
+> [Introduced](https://gitlab.com/gitlab-org/omnibus-gitlab/issues/3786) in GitLab 12.0.
+
+ If you enable Monitoring, it must be enabled on **all** Redis servers.
+
+ 1. Create/edit `/etc/gitlab/gitlab.rb` and add the following configuration:
+
+ ```ruby
+ # Enable service discovery for Prometheus
+ consul['enable'] = true
+ consul['monitoring_service_discovery'] = true
+
+ # Replace placeholders
+ # Y.Y.Y.Y consul1.gitlab.example.com Z.Z.Z.Z
+ # with the addresses of the Consul server nodes
+ consul['configuration'] = {
+ retry_join: %w(Y.Y.Y.Y consul1.gitlab.example.com Z.Z.Z.Z),
+ }
+
+ # Set the network addresses that the exporters will listen on
+ node_exporter['listen_address'] = '0.0.0.0:9100'
+ redis_exporter['listen_address'] = '0.0.0.0:9121'
+ ```
+
+ 1. Run `sudo gitlab-ctl reconfigure` to compile the configuration.
+
## Advanced configuration
Omnibus GitLab configures some things behind the curtains to make the sysadmins'
diff --git a/doc/api/environments.md b/doc/api/environments.md
index ebcdc546d08..44f86861ff7 100644
--- a/doc/api/environments.md
+++ b/doc/api/environments.md
@@ -11,9 +11,11 @@ GET /projects/:id/environments
| 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 |
+| `name` | string | no | Return the environment with this name. Mutually exclusive with `search` |
+| `search` | string | no | Return list of environments matching the search criteria. Mutually exclusive with `name` |
```bash
-curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/1/environments
+curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/1/environments?name=review%2Ffix-foo
```
Example response:
diff --git a/doc/api/merge_requests.md b/doc/api/merge_requests.md
index dd7810c3403..7b58aa3100e 100644
--- a/doc/api/merge_requests.md
+++ b/doc/api/merge_requests.md
@@ -1191,33 +1191,29 @@ Parameters:
}
```
-## Merge to default merge ref path
+## Returns the up to date merge-ref HEAD commit
Merge the changes between the merge request source and target branches into `refs/merge-requests/:iid/merge`
-ref, of the target project repository. This ref will have the state the target branch would have if
+ref, of the target project repository, if possible. This ref will have the state the target branch would have if
a regular merge action was taken.
-This is not a regular merge action given it doesn't change the merge request state in any manner.
+This is not a regular merge action given it doesn't change the merge request target branch state in any manner.
-This ref (`refs/merge-requests/:iid/merge`) is **always** overwritten when submitting
-requests to this API, so none of its state is kept or used in the process.
+This ref (`refs/merge-requests/:iid/merge`) isn't necessarily overwritten when submitting
+requests to this API, though it'll make sure the ref has the latest possible state.
-If the merge request has conflicts, is empty or already merged,
-you'll get a `400` and a descriptive error message. If you don't have permissions to do so,
-you'll get a `403`.
+If the merge request has conflicts, is empty or already merged, you'll get a `400` and a descriptive error message.
-It returns the HEAD commit of `refs/merge-requests/:iid/merge` in the response body in
-case of `200`.
+It returns the HEAD commit of `refs/merge-requests/:iid/merge` in the response body in case of `200`.
```
-PUT /projects/:id/merge_requests/:merge_request_iid/merge_to_ref
+GET /projects/:id/merge_requests/:merge_request_iid/merge_ref
```
Parameters:
- `id` (required) - The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user
- `merge_request_iid` (required) - Internal ID of MR
-- `merge_commit_message` (optional) - Custom merge commit message
```json
{
diff --git a/doc/api/search.md b/doc/api/search.md
index da81c8321c9..abb77ae05dc 100644
--- a/doc/api/search.md
+++ b/doc/api/search.md
@@ -285,7 +285,7 @@ Example response:
### Scope: wiki_blobs **[STARTER]**
-This scope is available only if [Elasticsearch](../integration/elasticsearch.md) is enabled.
+This scope is available only if [Elasticsearch](../integration/elasticsearch.md) is enabled.
```bash
curl --request GET --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/search?scope=wiki_blobs&search=bye
@@ -346,6 +346,7 @@ Example response:
This scope is available only if [Elasticsearch](../integration/elasticsearch.md) is enabled.
Filters are available for this scope:
+
- filename
- path
- extension
@@ -679,6 +680,7 @@ Example response:
This scope is available only if [Elasticsearch](../integration/elasticsearch.md) is enabled.
Filters are available for this scope:
+
- filename
- path
- extension
diff --git a/doc/api/settings.md b/doc/api/settings.md
index c2a1f7feefd..eb3f39e6670 100644
--- a/doc/api/settings.md
+++ b/doc/api/settings.md
@@ -231,6 +231,7 @@ are listed in the descriptions of the relevant settings.
| `throttle_unauthenticated_enabled` | boolean | no | (**If enabled, requires:** `throttle_unauthenticated_period_in_seconds` and `throttle_unauthenticated_requests_per_period`) Enable unauthenticated request rate limit. Helps reduce request volume (e.g. from crawlers or abusive bots). |
| `throttle_unauthenticated_period_in_seconds` | integer | required by: `throttle_unauthenticated_enabled` | Rate limit period in seconds. |
| `throttle_unauthenticated_requests_per_period` | integer | required by: `throttle_unauthenticated_enabled` | Max requests per period per IP. |
+| `time_tracking_limit_to_hours` | boolean | no | Limit display of time tracking units to hours. Default is `false`. |
| `two_factor_grace_period` | integer | required by: `require_two_factor_authentication` | Amount of time (in hours) that users are allowed to skip forced configuration of two-factor authentication. |
| `unique_ips_limit_enabled` | boolean | no | (**If enabled, requires:** `unique_ips_limit_per_user` and `unique_ips_limit_time_window`) Limit sign in from multiple ips. |
| `unique_ips_limit_per_user` | integer | required by: `unique_ips_limit_enabled` | Maximum number of ips per user. |
diff --git a/doc/ci/docker/using_docker_images.md b/doc/ci/docker/using_docker_images.md
index e4dc289dbdb..f752f942e24 100644
--- a/doc/ci/docker/using_docker_images.md
+++ b/doc/ci/docker/using_docker_images.md
@@ -489,6 +489,7 @@ it's provided as an environment variable. This is because GitLab Runnner uses **
runtime.
### Using statically-defined credentials
+
As an example, let's assume that you want to use the `registry.example.com:5000/private/image:latest`
image which is private and requires you to login into a private container registry.
@@ -566,7 +567,6 @@ for the Runner to match the `DOCKER_AUTH_CONFIG`. For example, if
then the `DOCKER_AUTH_CONFIG` must also specify `registry.example.com:5000`.
Specifying only `registry.example.com` will not work.
-
### Using Credentials Store
> Support for using Credentials Store was added in GitLab Runner 9.5.
@@ -574,7 +574,7 @@ Specifying only `registry.example.com` will not work.
To configure credentials store, follow these steps:
1. To use a credentials store, you need an external helper program to interact with a specific keychain or external store.
-Make sure helper program is available in GitLab Runner `$PATH`.
+ Make sure helper program is available in GitLab Runner `$PATH`.
1. Make GitLab Runner use it. There are two ways to accomplish this. Either:
- Create a
diff --git a/doc/ci/examples/test-scala-application.md b/doc/ci/examples/test-scala-application.md
index 0e33a1ba060..bd899240307 100644
--- a/doc/ci/examples/test-scala-application.md
+++ b/doc/ci/examples/test-scala-application.md
@@ -47,10 +47,10 @@ deploy:
In the above configuration:
- The `before_script` installs [SBT](http://www.scala-sbt.org/) and
-displays the version that is being used.
+ displays the version that is being used.
- The `test` stage executes SBT to compile and test the project.
- - [sbt-scoverage](https://github.com/scoverage/sbt-scoverage) is used as an SBT
-plugin to measure test coverage.
+ - [sbt-scoverage](https://github.com/scoverage/sbt-scoverage) is used as an SBT
+ plugin to measure test coverage.
- The `deploy` stage automatically deploys the project to Heroku using dpl.
You can use other versions of Scala and SBT by defining them in
diff --git a/doc/ci/variables/README.md b/doc/ci/variables/README.md
index df455857dee..1b50273eca2 100644
--- a/doc/ci/variables/README.md
+++ b/doc/ci/variables/README.md
@@ -27,8 +27,7 @@ CI/CD's pipelines. Using variables means no hardcoded values.
### Predefined environment variables
-GitLab CI/CD has a default set of
-[predefined variables](predefined_variables.md)
+GitLab CI/CD has a [default set of predefined variables](predefined_variables.md)
which can be used without any specification needed.
You can call issues numbers, user names, branch names,
pipeline and commit IDs, and much more.
@@ -36,7 +35,7 @@ pipeline and commit IDs, and much more.
Predefined environment variables are the ones that GitLab
provides out of the box for the local environment of the Runner.
-GitLab reads the .gitlab-ci.yml file, sends the information
+GitLab reads the `.gitlab-ci.yml` file, sends the information
to the Runner (which runs the script commands), under which
the variables are exposed.
@@ -44,6 +43,9 @@ For example, two jobs under the same pipeline can share the same
`CI_PIPELINE_ID` variable, but each one has its own `CI_JOB_ID`
variable.
+NOTE: **Note:**
+Find here the full [**predefined variables reference table**](predefined_variables.md).
+
### Custom environment variables
When your use case requires a specific variable, you can
@@ -337,7 +339,7 @@ Group-level variables can be added by:
1. Navigating to your group's **Settings > CI/CD** page.
1. Inputing variable types, keys, and values in the **Variables** section.
-Any variables of [subgroups](../../user/group/subgroups/index.md) will be inherited recursively.
+ Any variables of [subgroups](../../user/group/subgroups/index.md) will be inherited recursively.
Once you set them, they will be available for all subsequent pipelines.
@@ -480,7 +482,7 @@ Below you can find supported syntax reference:
> Example: `$VARIABLE == "some value"`
- > Example: `$VARIABLE != "some value"` _(added in 11.11)_
+ > Example: `$VARIABLE != "some value"` (introduced in GitLab 11.11)
You can use equality operator `==` or `!=` to compare a variable content to a
string. We support both, double quotes and single quotes to define a string
@@ -491,7 +493,7 @@ Below you can find supported syntax reference:
> Example: `$VARIABLE == null`
- > Example: `$VARIABLE != null` _(added in 11.11)_
+ > Example: `$VARIABLE != null` (introduced in GitLab 11.11)
It sometimes happens that you want to check whether a variable is defined
or not. To do that, you can compare a variable to `null` keyword, like
@@ -502,7 +504,7 @@ Below you can find supported syntax reference:
> Example: `$VARIABLE == ""`
- > Example: `$VARIABLE != ""` _(added in 11.11)_
+ > Example: `$VARIABLE != ""` (introduced in GitLab 11.11)
If you want to check whether a variable is defined, but is empty, you can
simply compare it against an empty string, like `$VAR == ''` or non-empty
@@ -512,7 +514,7 @@ Below you can find supported syntax reference:
> Example: `$VARIABLE_1 == $VARIABLE_2`
- > Example: `$VARIABLE_1 != $VARIABLE_2` _(added in 11.11)_
+ > Example: `$VARIABLE_1 != $VARIABLE_2` (introduced in GitLab 11.11)
It is possible to compare two variables. This is going to compare values
of these variables.
@@ -528,11 +530,11 @@ Below you can find supported syntax reference:
`$STAGING` value needs to a string, with length higher than zero.
Variable that contains only whitespace characters is not an empty variable.
-1. Pattern matching _(added in 11.0)_
+1. Pattern matching (introduced in GitLab 11.0)
> Example: `$VARIABLE =~ /^content.*/`
- > Example: `$VARIABLE_1 !~ /^content.*/` _(added in 11.11)_
+ > Example: `$VARIABLE_1 !~ /^content.*/` (introduced in GitLab 11.11)
It is possible perform pattern matching against a variable and regular
expression. Expression like this evaluates to truth if matches are found
@@ -541,7 +543,7 @@ Below you can find supported syntax reference:
Pattern matching is case-sensitive by default. Use `i` flag modifier, like
`/pattern/i` to make a pattern case-insensitive.
-1. Conjunction / Disjunction
+1. Conjunction / Disjunction ([introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/27925) in GitLab 12.0)
> Example: `$VARIABLE1 =~ /^content.*/ && $VARIABLE2 == "something"`
diff --git a/doc/ci/variables/predefined_variables.md b/doc/ci/variables/predefined_variables.md
index 4655eec51de..7dbb9af2869 100644
--- a/doc/ci/variables/predefined_variables.md
+++ b/doc/ci/variables/predefined_variables.md
@@ -30,7 +30,7 @@ future GitLab releases.**
| `CI_BUILDS_DIR` | all | 11.10 | Top-level directory where builds are executed. |
| `CI_CONCURRENT_ID` | all | 11.10 | Unique ID of build execution within a single executor. |
| `CI_CONCURRENT_PROJECT_ID` | all | 11.10 | Unique ID of build execution within a single executor and project. |
-| `CI_COMMIT_BEFORE_SHA` | 11.2 | all | The previous latest commit present on a branch before a push request. |
+| `CI_COMMIT_BEFORE_SHA` | 11.2 | all | The previous latest commit present on a branch before a push request. Only populated when there is a merge request associated with the pipeline. |
| `CI_COMMIT_DESCRIPTION` | 10.8 | all | The description of the commit: the message without first line, if the title is shorter than 100 characters; full message in other case. |
| `CI_COMMIT_MESSAGE` | 10.8 | all | The full commit message. |
| `CI_COMMIT_REF_NAME` | 9.0 | all | The branch or tag name for which project is built |
diff --git a/doc/development/api_graphql_styleguide.md b/doc/development/api_graphql_styleguide.md
index f7f36901fe1..2ed2a905db7 100644
--- a/doc/development/api_graphql_styleguide.md
+++ b/doc/development/api_graphql_styleguide.md
@@ -198,9 +198,9 @@ abilities as in the Rails app.
If the:
- Currently authenticated user fails the authorization, the authorized
-resource will be returned as `null`.
+ resource will be returned as `null`.
- Resource is part of a collection, the collection will be filtered to
-exclude the objects that the user's authorization checks failed against.
+ exclude the objects that the user's authorization checks failed against.
TIP: **Tip:**
Try to load only what the currently authenticated user is allowed to
@@ -496,4 +496,4 @@ it 'returns a successful response' do
expect(response).to have_gitlab_http_status(:success)
expect(graphql_mutation_response(:merge_request_set_wip)['errors']).to be_empty
end
-``` \ No newline at end of file
+```
diff --git a/doc/development/code_review.md b/doc/development/code_review.md
index 29e2aa1a581..6123f9f845a 100644
--- a/doc/development/code_review.md
+++ b/doc/development/code_review.md
@@ -60,6 +60,8 @@ from teams other than your own.
1. If your merge request includes backend changes [^1], it must be
**approved by a [backend maintainer](https://about.gitlab.com/handbook/engineering/projects/#gitlab-ce_maintainers_backend)**.
+ 1. If your merge request includes database migrations or changes to expensive queries [^2], it must be
+ **approved by a [database maintainer](https://about.gitlab.com/handbook/engineering/projects/#gitlab-ce_maintainers_database)**.
1. If your merge request includes frontend changes [^1], it must be
**approved by a [frontend maintainer](https://about.gitlab.com/handbook/engineering/projects/#gitlab-ce_maintainers_frontend)**.
1. If your merge request includes UX changes [^1], it must be
@@ -377,3 +379,4 @@ Largely based on the [thoughtbot code review guide].
[team]: https://about.gitlab.com/team/
[build handbook]: https://about.gitlab.com/handbook/build/handbook/build#how-to-work-with-build
[^1]: Please note that specs other than JavaScript specs are considered backend code.
+[^2]: We encourage you to seek guidance from a database maintainer if your merge request is potentially introducing expensive queries. It is most efficient to comment on the line of code in question with the SQL queries so they can give their advice.
diff --git a/doc/development/contributing/merge_request_workflow.md b/doc/development/contributing/merge_request_workflow.md
index 8a4aa5dfa7f..6064f59ed10 100644
--- a/doc/development/contributing/merge_request_workflow.md
+++ b/doc/development/contributing/merge_request_workflow.md
@@ -126,16 +126,16 @@ When writing commit messages, please follow the guidelines below:
- The commit subject must contain at least 3 words.
- The commit subject should ideally contain up to 50 characters,
-and must not be longer than 72 characters.
+ and must not be longer than 72 characters.
- The commit subject must start with a capital letter.
- The commit subject must not end with a period.
- The commit subject and body must be separated by a blank line.
- The commit body must not contain more than 72 characters per line.
- Commits that change 30 or more lines across at least 3 files must
-describe these changes in the commit body.
+ describe these changes in the commit body.
- The commit subject or body must not contain Emojis.
- Use issues and merge requests' full URLs instead of short references,
-as they are displayed as plain text outside of GitLab.
+ as they are displayed as plain text outside of GitLab.
- The merge request must not contain more than 10 commit messages.
If the guidelines are not met, the MR will not pass the
diff --git a/doc/development/documentation/index.md b/doc/development/documentation/index.md
index c7fa40af930..418e58b22d5 100644
--- a/doc/development/documentation/index.md
+++ b/doc/development/documentation/index.md
@@ -76,10 +76,10 @@ After a given documentation path is aligned across CE and EE, all merge requests
affecting that path must be submitted to CE, regardless of the content it has.
This means that:
-* For **EE-only docs changes**, you only have to submit a CE MR.
-* For **EE-only features** that touch both the code and the docs, you have to submit
-an EE MR containing all changes, and a CE MR containing only the docs changes
-and without a changelog entry.
+- For **EE-only docs changes**, you only have to submit a CE MR.
+- For **EE-only features** that touch both the code and the docs, you have to submit
+ an EE MR containing all changes, and a CE MR containing only the docs changes
+ and without a changelog entry.
This might seem like a duplicate effort, but it's only for the short term.
A list of the already aligned docs can be found in
diff --git a/doc/development/documentation/styleguide.md b/doc/development/documentation/styleguide.md
index b8506a72666..23d52a33881 100644
--- a/doc/development/documentation/styleguide.md
+++ b/doc/development/documentation/styleguide.md
@@ -165,8 +165,8 @@ The table below shows what kind of documentation goes where.
`doc/topics/topic-name/subtopic-name/index.md` when subtopics become necessary.
General user- and admin- related documentation, should be placed accordingly.
1. The directories `/workflow/`, `/university/`, and `/articles/` have
-been **deprecated** and the majority their docs have been moved to their correct location
-in small iterations.
+ been **deprecated** and the majority their docs have been moved to their correct location
+ in small iterations.
If you are unsure where a document or a content addition should live, this should
not stop you from authoring and contributing. You can use your best judgment and
diff --git a/doc/development/ee_features.md b/doc/development/ee_features.md
index cca52706ddc..6b416cf588c 100644
--- a/doc/development/ee_features.md
+++ b/doc/development/ee_features.md
@@ -909,11 +909,12 @@ import bundle from 'ee_else_ce/protected_branches/protected_branches_bundle.js';
See the frontend guide [performance section](fe_guide/performance.md) for
information on managing page-specific javascript within EE.
-
## Vue code in `assets/javascript`
+
### script tag
#### Child Component only used in EE
+
To separate Vue template differences we should [async import the components](https://vuejs.org/v2/guide/components-dynamic-async.html#Async-Components).
Doing this allows for us to load the correct component in EE whilst in CE
@@ -937,10 +938,12 @@ export default {
```
#### For JS code that is EE only, like props, computed properties, methods, etc, we will keep the current approach
- - Since we [can't async load a mixin](https://github.com/vuejs/vue-loader/issues/418#issuecomment-254032223) we will use the [`ee_else_ce`](../development/ee_features.md#javascript-code-in-assetsjavascripts) alias we already have for webpack.
+
+- Since we [can't async load a mixin](https://github.com/vuejs/vue-loader/issues/418#issuecomment-254032223) we will use the [`ee_else_ce`](../development/ee_features.md#javascript-code-in-assetsjavascripts) alias we already have for webpack.
- This means all the EE specific props, computed properties, methods, etc that are EE only should be in a mixin in the `ee/` folder and we need to create a CE counterpart of the mixin
##### Example:
+
```javascript
import mixin from 'ee_else_ce/path/mixin';
@@ -955,6 +958,7 @@ import mixin from 'ee_else_ce/path/mixin';
- You can see an MR with an example [here](https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/9762)
#### `template` tag
+
* **EE Child components**
- Since we are using the async loading to check which component to load, we'd still use the component's name, check [this example](#child-component-only-used-in-ee).
@@ -962,11 +966,12 @@ import mixin from 'ee_else_ce/path/mixin';
- For the templates that have extra HTML in EE we should move it into a new component and use the `ee_else_ce` dynamic import
### Non Vue Files
+
For regular JS files, the approach is similar.
1. We will keep using the [`ee_else_ce`](../development/ee_features.md#javascript-code-in-assetsjavascripts) helper, this means that EE only code should be inside the `ee/` folder.
- 1. An EE file should be created with the EE only code, and it should extend the CE counterpart.
- 1. For code inside functions that can't be extended, the code should be moved into a new file and we should use `ee_else_ce` helper:
+ 1. An EE file should be created with the EE only code, and it should extend the CE counterpart.
+ 1. For code inside functions that can't be extended, the code should be moved into a new file and we should use `ee_else_ce` helper:
##### Example:
@@ -996,6 +1001,7 @@ to isolate such ruleset from rest of CE rules (along with adding comment describ
to avoid conflicts during CE to EE merge.
#### Bad
+
```scss
.section-body {
.section-title {
@@ -1011,6 +1017,7 @@ to avoid conflicts during CE to EE merge.
```
#### Good
+
```scss
.section-body {
.section-title {
diff --git a/doc/development/elasticsearch.md b/doc/development/elasticsearch.md
index c8c70fa7216..94b3796f6e9 100644
--- a/doc/development/elasticsearch.md
+++ b/doc/development/elasticsearch.md
@@ -64,20 +64,25 @@ All indexing after the initial one is done via `ElasticIndexerWorker` (sidekiq j
Search queries are generated by the concerns found in [ee/app/models/concerns/elastic](https://gitlab.com/gitlab-org/gitlab-ee/tree/master/ee/app/models/concerns/elastic). These concerns are also in charge of access control, and have been a historic source of security bugs so please pay close attention to them!
## Existing Analyzers/Tokenizers/Filters
+
These are all defined in https://gitlab.com/gitlab-org/gitlab-ee/blob/master/ee/lib/elasticsearch/git/model.rb
### Analyzers
+
#### `path_analyzer`
+
Used when indexing blobs' paths. Uses the `path_tokenizer` and the `lowercase` and `asciifolding` filters.
Please see the `path_tokenizer` explanation below for an example.
#### `sha_analyzer`
+
Used in blobs and commits. Uses the `sha_tokenizer` and the `lowercase` and `asciifolding` filters.
Please see the `sha_tokenizer` explanation later below for an example.
#### `code_analyzer`
+
Used when indexing a blob's filename and content. Uses the `whitespace` tokenizer and the filters: `code`, `edgeNGram_filter`, `lowercase`, and `asciifolding`
The `whitespace` tokenizer was selected in order to have more control over how tokens are split. For example the string `Foo::bar(4)` needs to generate tokens like `Foo` and `bar(4)` in order to be properly searched.
@@ -85,15 +90,19 @@ The `whitespace` tokenizer was selected in order to have more control over how t
Please see the `code` filter for an explanation on how tokens are split.
#### `code_search_analyzer`
+
Not directly used for indexing, but rather used to transform a search input. Uses the `whitespace` tokenizer and the `lowercase` and `asciifolding` filters.
### Tokenizers
+
#### `sha_tokenizer`
+
This is a custom tokenizer that uses the [`edgeNGram` tokenizer](https://www.elastic.co/guide/en/elasticsearch/reference/5.5/analysis-edgengram-tokenizer.html) to allow SHAs to be searcheable by any sub-set of it (minimum of 5 chars).
-example:
+Example:
`240c29dc7e` becomes:
+
- `240c2`
- `240c29`
- `240c29d`
@@ -102,21 +111,26 @@ example:
- `240c29dc7e`
#### `path_tokenizer`
+
This is a custom tokenizer that uses the [`path_hierarchy` tokenizer](https://www.elastic.co/guide/en/elasticsearch/reference/5.5/analysis-pathhierarchy-tokenizer.html) with `reverse: true` in order to allow searches to find paths no matter how much or how little of the path is given as input.
-example:
+Example:
`'/some/path/application.js'` becomes:
+
- `'/some/path/application.js'`
- `'some/path/application.js'`
- `'path/application.js'`
- `'application.js'`
### Filters
+
#### `code`
-Uses a [Pattern Capture token filter](https://www.elastic.co/guide/en/elasticsearch/reference/5.5/analysis-pattern-capture-tokenfilter.html) to split tokens into more easily searched versions of themselves.
+
+Uses a [Pattern Capture token filter](https://www.elastic.co/guide/en/elasticsearch/reference/5.5/analysis-pattern-capture-tokenfilter.html) to split tokens into more easily searched versions of themselves.
Patterns:
+
- `"(\\p{Ll}+|\\p{Lu}\\p{Ll}+|\\p{Lu}+)"`: captures CamelCased and lowedCameCased strings as separate tokens
- `"(\\d+)"`: extracts digits
- `"(?=([\\p{Lu}]+[\\p{L}]+))"`: captures CamelCased strings recursively. Ex: `ThisIsATest` => `[ThisIsATest, IsATest, ATest, Test]`
@@ -126,6 +140,7 @@ Patterns:
- `'\/?([^\/]+)(?=\/|\b)'`: separate path terms `like/this/one`
#### `edgeNGram_filter`
+
Uses an [Edge NGram token filter](https://www.elastic.co/guide/en/elasticsearch/reference/5.5/analysis-edgengram-tokenfilter.html) to allow inputs with only parts of a token to find the token. For example it would turn `glasses` into permutations starting with `gl` and ending with `glasses`, which would allow a search for "`glass`" to find the original token `glasses`
## Gotchas
@@ -140,13 +155,13 @@ Uses an [Edge NGram token filter](https://www.elastic.co/guide/en/elasticsearch/
You might get an error such as
```
-[2018-10-31T15:54:19,762][WARN ][o.e.c.r.a.DiskThresholdMonitor] [pval5Ct]
- flood stage disk watermark [95%] exceeded on
- [pval5Ct7SieH90t5MykM5w][pval5Ct][/usr/local/var/lib/elasticsearch/nodes/0] free: 56.2gb[3%],
+[2018-10-31T15:54:19,762][WARN ][o.e.c.r.a.DiskThresholdMonitor] [pval5Ct]
+ flood stage disk watermark [95%] exceeded on
+ [pval5Ct7SieH90t5MykM5w][pval5Ct][/usr/local/var/lib/elasticsearch/nodes/0] free: 56.2gb[3%],
all indices on this node will be marked read-only
```
-This is because you've exceeded the disk space threshold - it thinks you don't have enough disk space left, based on the default 95% threshold.
+This is because you've exceeded the disk space threshold - it thinks you don't have enough disk space left, based on the default 95% threshold.
In addition, the `read_only_allow_delete` setting will be set to `true`. It will block indexing, `forcemerge`, etc
@@ -158,16 +173,16 @@ Add this to your `elasticsearch.yml` file:
```
# turn off the disk allocator
-cluster.routing.allocation.disk.threshold_enabled: false
+cluster.routing.allocation.disk.threshold_enabled: false
```
_or_
```
# set your own limits
-cluster.routing.allocation.disk.threshold_enabled: true
+cluster.routing.allocation.disk.threshold_enabled: true
cluster.routing.allocation.disk.watermark.flood_stage: 5gb # ES 6.x only
-cluster.routing.allocation.disk.watermark.low: 15gb
+cluster.routing.allocation.disk.watermark.low: 15gb
cluster.routing.allocation.disk.watermark.high: 10gb
```
diff --git a/doc/development/geo.md b/doc/development/geo.md
index 6e59fab34c7..a10f13b069f 100644
--- a/doc/development/geo.md
+++ b/doc/development/geo.md
@@ -14,10 +14,10 @@ Geo handles replication for different components:
- [Database](#database-replication): includes the entire application, except cache and jobs.
- [Git repositories](#repository-replication): includes both projects and wikis.
- [Uploaded blobs](#uploads-replication): includes anything from images attached on issues
-to raw logs and assets from CI.
+ to raw logs and assets from CI.
With the exception of the Database replication, on a *secondary* node, everything is coordinated
-by the [Geo Log Cursor](#geo-log-cursor).
+by the [Geo Log Cursor](#geo-log-cursor).
### Geo Log Cursor daemon
@@ -31,8 +31,8 @@ picks the event up and schedules a `Geo::ProjectSyncWorker` job which will
use the `Geo::RepositorySyncService` and `Geo::WikiSyncService` classes
to update the repository and the wiki respectively.
-The Geo Log Cursor daemon can operate in High Availability mode automatically.
-The daemon will try to acquire a lock from time to time and once acquired, it
+The Geo Log Cursor daemon can operate in High Availability mode automatically.
+The daemon will try to acquire a lock from time to time and once acquired, it
will behave as the *active* daemon.
Any additional running daemons on the same node, will be in standby
@@ -164,20 +164,20 @@ The Git Push Proxy exists as a functionality built inside the `gitlab-shell` com
It is active on a **secondary** node only. It allows the user that has cloned a repository
from the secondary node to push to the same URL.
-Git `push` requests directed to a **secondary** node will be sent over to the **primary** node,
+Git `push` requests directed to a **secondary** node will be sent over to the **primary** node,
while `pull` requests will continue to be served by the **secondary** node for maximum efficiency.
HTTPS and SSH requests are handled differently:
- With HTTPS, we will give the user a `HTTP 302 Redirect` pointing to the project on the **primary** node.
-The git client is wise enough to understand that status code and process the redirection.
+ The git client is wise enough to understand that status code and process the redirection.
- With SSH, because there is no equivalent way to perform a redirect, we have to proxy the request.
-This is done inside [`gitlab-shell`](https://gitlab.com/gitlab-org/gitlab-shell), by first translating the request
-to the HTTP protocol, and then proxying it to the **primary** node.
+ This is done inside [`gitlab-shell`](https://gitlab.com/gitlab-org/gitlab-shell), by first translating the request
+ to the HTTP protocol, and then proxying it to the **primary** node.
-The [`gitlab-shell`](https://gitlab.com/gitlab-org/gitlab-shell) daemon knows when to proxy based on the response
-from `/api/v4/allowed`. A special `HTTP 300` status code is returned and we execute a "custom action",
-specified in the response body. The response contains additional data that allows the proxied `push` operation
+The [`gitlab-shell`](https://gitlab.com/gitlab-org/gitlab-shell) daemon knows when to proxy based on the response
+from `/api/v4/allowed`. A special `HTTP 300` status code is returned and we execute a "custom action",
+specified in the response body. The response contains additional data that allows the proxied `push` operation
to happen on the **primary** node.
## Using the Tracking Database
@@ -229,17 +229,17 @@ named `gitlab_secondary`. This configuration exists within the database's user
context only. To access the `gitlab_secondary`, GitLab needs to use the
same database user that had previously been configured.
-The Geo Tracking Database accesses the readonly database replica via FDW as a regular user,
-limited by its own restrictions. The credentials are configured as a
-`USER MAPPING` associated with the `SERVER` mapped previously
+The Geo Tracking Database accesses the readonly database replica via FDW as a regular user,
+limited by its own restrictions. The credentials are configured as a
+`USER MAPPING` associated with the `SERVER` mapped previously
(`gitlab_secondary`).
FDW configuration and credentials definition are managed automatically by the
-Omnibus GitLab `gitlab-ctl reconfigure` command.
+Omnibus GitLab `gitlab-ctl reconfigure` command.
#### Refeshing the Foreign Tables
-Whenever a new Geo node is configured or the database schema changes on the
+Whenever a new Geo node is configured or the database schema changes on the
**primary** node, you must refresh the foreign tables on the **secondary** node
by running the following:
@@ -279,11 +279,11 @@ on the Tracking Database:
SELECT project_registry.*
FROM project_registry
JOIN gitlab_secondary.projects
- ON (project_registry.project_id = gitlab_secondary.projects.id
+ ON (project_registry.project_id = gitlab_secondary.projects.id
AND gitlab_secondary.projects.archived IS FALSE)
```
-At the ActiveRecord level, we have additional Models that represent the
+At the ActiveRecord level, we have additional Models that represent the
foreign tables. They must be mapped in a slightly different way, and they are read-only.
Check the existing FDW models in `ee/app/models/geo/fdw` for reference.
diff --git a/doc/development/profiling.md b/doc/development/profiling.md
index b2f3a105b23..795523b82aa 100644
--- a/doc/development/profiling.md
+++ b/doc/development/profiling.md
@@ -38,10 +38,6 @@ For routes that require authorization you will need to provide a user to
Gitlab::Profiler.profile('/gitlab-org/gitlab-test', user: User.first)
```
-The user you provide will need to have a [personal access
-token](https://docs.gitlab.com/ce/user/profile/personal_access_tokens.html) in
-the GitLab instance.
-
Passing a `logger:` keyword argument to `Gitlab::Profiler.profile` will send
ActiveRecord and ActionController log output to that logger. Further options are
documented with the method source.
diff --git a/doc/development/reusing_abstractions.md b/doc/development/reusing_abstractions.md
index 01cedf734fb..59da02ed6fd 100644
--- a/doc/development/reusing_abstractions.md
+++ b/doc/development/reusing_abstractions.md
@@ -127,6 +127,42 @@ Everything in `lib/api`.
Everything that resides in `app/services`.
+#### ServiceResponse
+
+Service classes usually have an `execute` method, which can return a
+`ServiceResponse`. You can use `ServiceResponse.success` and
+`ServiceResponse.error` to return a response in `execute` method.
+
+In a successful case:
+
+``` ruby
+response = ServiceResponse.success(message: 'Branch was deleted')
+
+response.success? # => true
+response.error? # => false
+response.status # => :success
+response.message # => 'Branch was deleted'
+```
+
+In a failed case:
+
+``` ruby
+response = ServiceResponse.error(message: 'Unsupported operation')
+
+response.success? # => false
+response.error? # => true
+response.status # => :error
+response.message # => 'Unsupported operation'
+```
+
+An additional payload can also be attached:
+
+``` ruby
+response = ServiceResponse.success(payload: { issue: issue })
+
+response.payload[:issue] # => issue
+```
+
### Finders
Everything in `app/finders`, typically used for retrieving data from a database.
diff --git a/doc/development/testing_guide/end_to_end/dynamic_element_validation.md b/doc/development/testing_guide/end_to_end/dynamic_element_validation.md
index f7b3ca8bc89..aec0a3ede5a 100644
--- a/doc/development/testing_guide/end_to_end/dynamic_element_validation.md
+++ b/doc/development/testing_guide/end_to_end/dynamic_element_validation.md
@@ -5,8 +5,8 @@ We devised a solution to solve common test automation problems such as the dread
Other problems that dynamic element validations solve are...
- When we perform an action with the mouse, we expect something to occur.
-- When our test is navigating to (or from) a page, we ensure that we are on the page we expect before
-test continuation.
+- When our test is navigating to (or from) a page, we ensure that we are on the page we expect before
+ test continuation.
## How it works
@@ -19,7 +19,7 @@ We interpret user actions on the page to have some sort of effect. These actions
When a page is navigated to, there are elements that will always appear on the page unconditionally.
-Dynamic element validation is instituted when using
+Dynamic element validation is instituted when using
```ruby
Runtime::Browser.visit(:gitlab, Some::Page)
@@ -27,7 +27,7 @@ Runtime::Browser.visit(:gitlab, Some::Page)
### Clicks
-When we perform a click within our tests, we expect something to occur. That something could be a component to now
+When we perform a click within our tests, we expect something to occur. That something could be a component to now
appear on the webpage, or the test to navigate away from the page entirely.
Dynamic element validation is instituted when using
@@ -71,7 +71,7 @@ class MyPage < Page::Base
element :another_element, required: true
element :conditional_element
end
-
+
def open_layer
click_element :my_element, Layer::MyLayer
end
@@ -95,7 +95,7 @@ execute_stuff
```
will invoke GitLab QA to scan `MyPage` for `my_element` and `another_element` to be on the page before continuing to
-`execute_stuff`
+`execute_stuff`
### Clicking
diff --git a/doc/development/testing_guide/end_to_end/page_objects.md b/doc/development/testing_guide/end_to_end/page_objects.md
index 73e1fd862c1..05cb03eb4bd 100644
--- a/doc/development/testing_guide/end_to_end/page_objects.md
+++ b/doc/development/testing_guide/end_to_end/page_objects.md
@@ -82,7 +82,7 @@ module Page
end
# ...
- end
+ end
end
end
```
@@ -134,7 +134,7 @@ for each element defined.
In our case, `qa-login-field`, `qa-password-field` and `qa-sign-in-button`
-**app/views/my/view.html.haml**
+**app/views/my/view.html.haml**
```haml
= f.text_field :login, class: "form-control top qa-login-field", autofocus: "autofocus", autocapitalize: "off", autocorrect: "off", required: true, title: "This field is required."
@@ -146,7 +146,7 @@ Things to note:
- The CSS class must be `kebab-cased` (separated with hyphens "`-`")
- If the element appears on the page unconditionally, add `required: true` to the element. See
-[Dynamic element validation](dynamic_element_validation.md)
+ [Dynamic element validation](dynamic_element_validation.md)
## Running the test locally
diff --git a/doc/integration/jenkins.md b/doc/integration/jenkins.md
index 5950737b964..e6496ae3a2e 100644
--- a/doc/integration/jenkins.md
+++ b/doc/integration/jenkins.md
@@ -25,22 +25,22 @@ and [Migrating from Jenkins to GitLab](https://www.youtube.com/watch?v=RlEVGOpYF
## Use cases
- Suppose you are new to GitLab, and want to keep using Jenkins until you prepare
-your projects to build with [GitLab CI/CD](../ci/README.md). You set up the
-integration between GitLab and Jenkins, then you migrate to GitLab CI later. While
-you organize yourself and your team to onboard GitLab, you keep your pipelines
-running with Jenkins, but view the results in your project's repository in GitLab.
+ your projects to build with [GitLab CI/CD](../ci/README.md). You set up the
+ integration between GitLab and Jenkins, then you migrate to GitLab CI later. While
+ you organize yourself and your team to onboard GitLab, you keep your pipelines
+ running with Jenkins, but view the results in your project's repository in GitLab.
- Your team uses [Jenkins Plugins](https://plugins.jenkins.io/) for other proceedings,
-therefore, you opt for keep using Jenkins to build your apps. Show the results of your
-pipelines directly in GitLab.
+ therefore, you opt for keep using Jenkins to build your apps. Show the results of your
+ pipelines directly in GitLab.
For a real use case, read the blog post [Continuous integration: From Jenkins to GitLab using Docker](https://about.gitlab.com/2017/07/27/docker-my-precious/).
## Requirements
-* [Jenkins GitLab Plugin](https://wiki.jenkins.io/display/JENKINS/GitLab+Plugin)
-* [Jenkins Git Plugin](https://wiki.jenkins.io/display/JENKINS/Git+Plugin)
-* Git clone access for Jenkins from the GitLab repository
-* GitLab API access to report build status
+- [Jenkins GitLab Plugin](https://wiki.jenkins.io/display/JENKINS/GitLab+Plugin)
+- [Jenkins Git Plugin](https://wiki.jenkins.io/display/JENKINS/Git+Plugin)
+- Git clone access for Jenkins from the GitLab repository
+- GitLab API access to report build status
## Configure GitLab users
@@ -65,7 +65,7 @@ Go to Manage Jenkins -> Configure System and scroll down to the 'GitLab' section
Enter the GitLab server URL in the 'GitLab host URL' field and paste the API token
copied earlier in the 'API Token' field.
-For more information, see GitLab Plugin documentation about
+For more information, see GitLab Plugin documentation about
[Jenkins-to-GitLab authentication](https://github.com/jenkinsci/gitlab-plugin#jenkins-to-gitlab-authentication)
![Jenkins GitLab plugin configuration](img/jenkins_gitlab_plugin_config.png)
@@ -76,8 +76,8 @@ Follow the GitLab Plugin documentation about [Jenkins Job Configuration](https:/
NOTE: **Note:**
Be sure to include the steps about [Build status configuration](https://github.com/jenkinsci/gitlab-plugin#build-status-configuration).
-The 'Publish build status to GitLab' post-build step is required to view
-Jenkins build status in GitLab Merge Requests.
+The 'Publish build status to GitLab' post-build step is required to view
+Jenkins build status in GitLab Merge Requests.
## Configure a GitLab project
@@ -114,21 +114,21 @@ and storing build status for Commits and Merge Requests.
All steps are implemented using AJAX requests on the merge request page.
1. In order to display the build status in a merge request you must create a project service in GitLab.
-2. Your project service will do a (JSON) query to a URL of the CI tool with the SHA1 of the commit.
-3. The project service builds this URL and payload based on project service settings and knowledge of the CI tool.
-4. The response is parsed to give a response in GitLab (success/failed/pending).
+1. Your project service will do a (JSON) query to a URL of the CI tool with the SHA1 of the commit.
+1. The project service builds this URL and payload based on project service settings and knowledge of the CI tool.
+1. The response is parsed to give a response in GitLab (success/failed/pending).
## Troubleshooting
### Error in merge requests - "Could not connect to the CI server"
This integration relies on Jenkins reporting the build status back to GitLab via
-the [Commit Status API](../api/commits.md#commit-status).
+the [Commit Status API](../api/commits.md#commit-status).
The error 'Could not connect to the CI server' usually means that GitLab did not
receive a build status update via the API. Either Jenkins was not properly
-configured or there was an error reporting the status via the API.
+configured or there was an error reporting the status via the API.
1. [Configure the Jenkins server](#configure-the-jenkins-server) for GitLab API access
-2. [Configure a Jenkins project](#configure-a-jenkins-project), including the
- 'Publish build status to GitLab' post-build action.
+1. [Configure a Jenkins project](#configure-a-jenkins-project), including the
+ 'Publish build status to GitLab' post-build action.
diff --git a/doc/subscriptions/index.md b/doc/subscriptions/index.md
index 37051f6b10f..1e9c53b9811 100644
--- a/doc/subscriptions/index.md
+++ b/doc/subscriptions/index.md
@@ -14,7 +14,7 @@ Learn how GitLab helps you in the stages of the DevOps lifecycle by learning mor
### Self-managed: Install GitLab
-Take a look at [installing GitLab](https://about.gitlab.com/install/) and our [administrator documentation](../administration/index.md). Then, follow the instructions below under [Your subscription](#your-subscription) to apply your license file.
+Take a look at [installing GitLab](https://about.gitlab.com/install/) and our [administrator documentation](../administration/index.md). Then, follow the instructions below under [Your subscription](#your-subscription) to apply your license file.
### GitLab.com: Create a user and group
@@ -74,11 +74,11 @@ Please note that you need to be a group owner to associate a group to your subsc
To see the status of your GitLab.com subscription, you can click on the Billings
section of the relevant namespace:
-* For individuals, this is located at https://gitlab.com/profile/billings under
-in your Settings,
-* For groups, this is located under the group's Settings dropdown, under Billing.
+- For individuals, this is located at https://gitlab.com/profile/billings under
+ in your Settings,
+- For groups, this is located under the group's Settings dropdown, under Billing.
-For groups, you can see details of your subscription - including your current
+For groups, you can see details of your subscription - including your current
plan - in the included table:
![Billing table](billing_table.png)
@@ -86,11 +86,11 @@ plan - in the included table:
| Field | Description |
| ------ | ------ |
| Seats in subscription | If this is a paid plan, this represents the number of seats you've paid to support in your group. |
-| Seats currently in use | The number of active seats currently in use. |
-| Max seats used | The highest number of seats you've used. If this exceeds the seats in subscription, you may owe an additional fee for the additional users. |
-| Seats owed | If your max seats used exceeds the seats in your subscription, you'll owe an additional fee for the users you've added. |
-| Subscription start date | The date your subscription started. If this is for a Free plan, this is the date you transitioned off your group's paid plan. |
-| Subscription end date | The date your current subscription will end. This does not apply to Free plans. |
+| Seats currently in use | The number of active seats currently in use. |
+| Max seats used | The highest number of seats you've used. If this exceeds the seats in subscription, you may owe an additional fee for the additional users. |
+| Seats owed | If your max seats used exceeds the seats in your subscription, you'll owe an additional fee for the users you've added. |
+| Subscription start date | The date your subscription started. If this is for a Free plan, this is the date you transitioned off your group's paid plan. |
+| Subscription end date | The date your current subscription will end. This does not apply to Free plans. |
### Subscription changes and your data
diff --git a/doc/user/admin_area/index.md b/doc/user/admin_area/index.md
index add5971e01c..fa60ee96cf7 100644
--- a/doc/user/admin_area/index.md
+++ b/doc/user/admin_area/index.md
@@ -186,7 +186,7 @@ the sort order to *Last Contacted* from the dropdown beside the search field.
To search Runners' descriptions:
1. In the **Search or filter results...** field, type the description of the Runner you want to
-find.
+ find.
1. Press Enter.
You can also filter Runners by status, type, and tag. To filter:
diff --git a/doc/user/admin_area/settings/continuous_integration.md b/doc/user/admin_area/settings/continuous_integration.md
index fde7d1aeaf7..5768a97e727 100644
--- a/doc/user/admin_area/settings/continuous_integration.md
+++ b/doc/user/admin_area/settings/continuous_integration.md
@@ -94,7 +94,6 @@ a group in the **Usage Quotas** page available to the group page settings list.
![Group pipelines quota](img/group_pipelines_quota.png)
-
## Extra Shared Runners pipeline minutes quota
NOTE: **Note:**
@@ -110,27 +109,27 @@ In order to purchase additional minutes, you should follow these steps:
![Buy additional minutes](img/buy_btn.png)
1. Locate the subscription card that is linked to your group on GitLab.com,
-click on **Buy more CI minutes**, and complete the details about the transaction.
+ click on **Buy more CI minutes**, and complete the details about the transaction.
![Buy additional minutes](img/buy_minutes_card.png)
1. Once we have processed your payment, the extra CI minutes
-will be synced to your Group and you can visualize it from the
-**Group > Settings > Pipelines quota** page:
+ will be synced to your Group and you can visualize it from the
+ **Group > Settings > Pipelines quota** page:
![Additional minutes](img/additional_minutes.png)
Be aware that:
1. If you have purchased extra CI minutes before the purchase of a paid plan,
-we will calculate a pro-rated charge for your paid plan. That means you may
-be charged for less than one year since your subscription was previously
-created with the extra CI minutes.
+ we will calculate a pro-rated charge for your paid plan. That means you may
+ be charged for less than one year since your subscription was previously
+ created with the extra CI minutes.
1. Once the extra CI minutes has been assigned to a Group they cannot be transferred
-to a different Group.
+ to a different Group.
1. If you have some minutes used over your default quota, these minutes will
-be deducted from your Additional Minutes quota immediately after your purchase of additional
-minutes.
+ be deducted from your Additional Minutes quota immediately after your purchase of additional
+ minutes.
## What happens when my CI minutes quota run out
diff --git a/doc/user/admin_area/settings/terms.md b/doc/user/admin_area/settings/terms.md
index a5f8d05f662..a1bce5a6c69 100644
--- a/doc/user/admin_area/settings/terms.md
+++ b/doc/user/admin_area/settings/terms.md
@@ -17,7 +17,7 @@ To enforce acceptance of a Terms of Service and Privacy Policy:
1. Go to **Admin Area > Settings > General**.
1. Expand the **Terms of Service and Privacy Policy** section.
1. Check the **Require all users to accept Terms of Service and Privacy Policy when they access
-GitLab.** checkbox.
+ GitLab.** checkbox.
1. Input the text of the **Terms of Service and Privacy Policy**. Markdown formatting can be used in this input box.
1. Click **Save changes**.
1. When you are presented with the **Terms of Service** statement, click **Accept terms**.
diff --git a/doc/user/admin_area/settings/visibility_and_access_controls.md b/doc/user/admin_area/settings/visibility_and_access_controls.md
index a1229484388..63879935fd8 100644
--- a/doc/user/admin_area/settings/visibility_and_access_controls.md
+++ b/doc/user/admin_area/settings/visibility_and_access_controls.md
@@ -4,12 +4,15 @@ type: reference
# Visibility and access controls
-GitLab allows admins to:
+GitLab allows administrators to:
- Control access and visibility to GitLab resources including branches and projects.
- Select from which hosting sites code can be imported into GitLab.
- Select the protocols permitted to access GitLab.
- Enable or disable repository mirroring.
+- Prevent non-administrators from deleting projects
+ ([introduced](https://gitlab.com/gitlab-org/gitlab-ee/issues/5615) in GitLab 12.0).
+ **[PREMIUM ONLY]**
To access the visibility and access control options:
diff --git a/doc/user/application_security/container_scanning/index.md b/doc/user/application_security/container_scanning/index.md
index a24374dff1d..4a2fb1d7190 100644
--- a/doc/user/application_security/container_scanning/index.md
+++ b/doc/user/application_security/container_scanning/index.md
@@ -40,6 +40,9 @@ To enable Container Scanning in your pipeline, you need:
[`kubernetes`](https://docs.gitlab.com/runner/install/kubernetes.html#running-privileged-containers-for-the-runners)
executor running in privileged mode. If you're using the shared Runners on GitLab.com,
this is enabled by default.
+- Docker `18.09.03` or higher installed on the machine where the Runners are
+ running. If you're using the shared Runners on GitLab.com, this is already
+ the case.
- To [build and push](../../../ci/docker/using_docker_build.md#container-registry-examples)
your Docker image to your project's [Container Registry](../../project/container_registry.md).
The name of the Docker image should match the following scheme:
@@ -202,3 +205,20 @@ vulnerabilities in your groups and projects. Read more about the
Once a vulnerability is found, you can interact with it. Read more on how to
[interact with the vulnerabilities](../index.md#interacting-with-the-vulnerabilities).
+
+## Troubleshooting
+
+### docker: Error response from daemon: failed to copy xattrs
+
+When the GitLab Runner uses the Docker executor and NFS is used
+(e.g., `/var/lib/docker` is on an NFS mount), Container Scanning might fail with
+an error like the following:
+
+```
+docker: Error response from daemon: failed to copy xattrs: failed to set xattr "security.selinux" on /path/to/file: operation not supported.
+```
+
+This is a result of a bug in Docker which is now [fixed](https://github.com/containerd/continuity/pull/138 "fs: add WithAllowXAttrErrors CopyOpt").
+To prevent the error, ensure the Docker version that the Runner is using is
+`18.09.03` or higher. For more information, see
+[issue #10241](https://gitlab.com/gitlab-org/gitlab-ee/issues/10241 "Investigate why Container Scanning is not working with NFS mounts").
diff --git a/doc/user/application_security/dependency_scanning/analyzers.md b/doc/user/application_security/dependency_scanning/analyzers.md
new file mode 100644
index 00000000000..937ded287e5
--- /dev/null
+++ b/doc/user/application_security/dependency_scanning/analyzers.md
@@ -0,0 +1,133 @@
+# Dependency Scanning Analyzers **[ULTIMATE]**
+
+Dependency Scanning relies on underlying third party tools that are wrapped into
+what we call "Analyzers". An analyzer is a
+[dedicated project](https://gitlab.com/gitlab-org/security-products/analyzers)
+that wraps a particular tool to:
+
+- Expose its detection logic.
+- Handle its execution.
+- Convert its output to the common format.
+
+This is achieved by implementing the [common API](https://gitlab.com/gitlab-org/security-products/analyzers/common).
+
+Dependency Scanning supports the following official analyzers:
+
+- [`bundler-audit`](https://gitlab.com/gitlab-org/security-products/analyzers/bundler-audit)
+- [`gemnasium`](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium)
+- [`gemnasium-maven`](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium-maven)
+- [`gemnasium-python`](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium-python)
+- [`retire.js`](https://gitlab.com/gitlab-org/security-products/analyzers/retire.js)
+
+The analyzers are published as Docker images that Dependency Scanning will use
+to launch dedicated containers for each analysis.
+
+Dependency Scanning is pre-configured with a set of **default images** that are
+maintained by GitLab, but users can also integrate their own **custom images**.
+
+## Official default analyzers
+
+Any custom change to the official analyzers can be achieved by using an
+[environment variable in your `.gitlab-ci.yml`](index.md#customizing-the-dependency-scanning-settings).
+
+### Using a custom Docker mirror
+
+You can switch to a custom Docker registry that provides the official analyzer
+images under a different prefix. For instance, the following instructs Dependency
+Scanning to pull `my-docker-registry/gl-images/gemnasium`
+instead of `registry.gitlab.com/gitlab-org/security-products/analyzers/gemnasium`.
+In `.gitlab-ci.yml` define:
+
+```yaml
+include:
+ template: Dependency-Scanning.gitlab-ci.yml
+
+variables:
+ DS_ANALYZER_IMAGE_PREFIX: my-docker-registry/gl-images
+```
+
+This configuration requires that your custom registry provides images for all
+the official analyzers.
+
+### Selecting specific analyzers
+
+You can select the official analyzers you want to run. Here's how to enable
+`bundler-audit` and `gemnasium` while disabling all the other default ones.
+In `.gitlab-ci.yml` define:
+
+```yaml
+include:
+ template: Dependency-Scanning.gitlab-ci.yml
+
+variables:
+ DS_DEFAULT_ANALYZERS: "bundler-audit,gemnasium"
+```
+
+`bundler-audit` runs first. When merging the reports, Dependency Scanning will
+remove the duplicates and will keep the `bundler-audit` entries.
+
+### Disabling default analyzers
+
+Setting `DS_DEFAULT_ANALYZERS` to an empty string will disable all the official
+default analyzers. In `.gitlab-ci.yml` define:
+
+```yaml
+include:
+ template: Dependency-Scanning.gitlab-ci.yml
+
+variables:
+ DS_DEFAULT_ANALYZERS: ""
+```
+
+That's needed when one totally relies on [custom analyzers](#custom-analyzers).
+
+## Custom analyzers
+
+You can provide your own analyzers as a comma separated list of Docker images.
+Here's how to add `analyzers/nugget` and `analyzers/perl` to the default images.
+In `.gitlab-ci.yml` define:
+
+```yaml
+include:
+ template: Dependency-Scanning.gitlab-ci.yml
+
+variables:
+ DS_ANALYZER_IMAGES: "my-docker-registry/analyzers/nugget,amy-docker-registry/nalyzers/perl"
+```
+
+The values must be the full path to the container registry images,
+like what you would feed to the `docker pull` command.
+
+NOTE: **Note:**
+This configuration doesn't benefit from the integrated detection step. Dependency
+Scanning has to fetch and spawn each Docker image to establish whether the
+custom analyzer can scan the source code.
+
+## Analyzers data
+
+The following table lists the data available for each official analyzer.
+
+| Property \ Tool | Gemnasium | bundler-audit | Retire.js |
+|---------------------------------------|:------------------:|:------------------:|:------------------:|
+| Severity | 𐄂 | ✓ | ✓ |
+| Title | ✓ | ✓ | ✓ |
+| File | ✓ | ⚠ | ✓ |
+| Start line | 𐄂 | 𐄂 | 𐄂 |
+| End line | 𐄂 | 𐄂 | 𐄂 |
+| External ID (e.g., CVE) | ✓ | ✓ | ⚠ |
+| URLs | ✓ | ✓ | ✓ |
+| Internal doc/explanation | ✓ | 𐄂 | 𐄂 |
+| Solution | ✓ | ✓ | 𐄂 |
+| Confidence | 𐄂 | 𐄂 | 𐄂 |
+| Affected item (e.g. class or package) | ✓ | ✓ | ✓ |
+| Source code extract | 𐄂 | 𐄂 | 𐄂 |
+| Internal ID | ✓ | 𐄂 | 𐄂 |
+| Date | ✓ | 𐄂 | 𐄂 |
+| Credits | ✓ | 𐄂 | 𐄂 |
+
+- ✓ => we have that data
+- ⚠ => we have that data but it's partially reliable, or we need to extract that data from unstructured content
+- 𐄂 => we don't have that data or it would need to develop specific or inefficient/unreliable logic to obtain it.
+
+The values provided by these tools are heterogeneous so they are sometimes
+normalized into common values (e.g., `severity`, `confidence`, etc).
diff --git a/doc/user/application_security/dependency_scanning/index.md b/doc/user/application_security/dependency_scanning/index.md
index 34d4507210e..dc86e66cb4f 100644
--- a/doc/user/application_security/dependency_scanning/index.md
+++ b/doc/user/application_security/dependency_scanning/index.md
@@ -54,9 +54,22 @@ The following languages and dependency managers are supported.
| Java ([Maven](https://maven.apache.org/)) | [gemnasium](https://gitlab.com/gitlab-org/security-products/gemnasium/general) |
| PHP ([Composer](https://getcomposer.org/)) | [gemnasium](https://gitlab.com/gitlab-org/security-products/gemnasium/general) |
-Some scanners require to send a list of project dependencies to GitLab's central
-servers to check for vulnerabilities. To learn more about this or to disable it,
-refer to the [GitLab Dependency Scanning tool documentation](https://gitlab.com/gitlab-org/security-products/dependency-scanning#remote-checks).
+## Remote checks
+
+While some tools pull a local database to check vulnerabilities, some others
+like Gemnasium require sending data to GitLab central servers to analyze them:
+
+1. Gemnasium scans the dependencies of your project locally and sends a list of
+ packages to GitLab central servers.
+1. The servers return the list of known vulnerabilities for all versions of
+ these packages.
+1. The client picks up the relevant vulnerabilities by comparing with the versions
+ of the packages that are used by the project.
+
+The Gemnasium client does **NOT** send the exact package versions your project relies on.
+
+You can disable the remote checks by [using](#customizing-the-dependency-scanning-settings)
+the `DS_DISABLE_REMOTE_CHECKS` environment variable and setting it to `true`.
## Configuring Dependency Scanning
@@ -97,17 +110,10 @@ The report will be saved as a
that you can later download and analyze. Due to implementation limitations, we
always take the latest Dependency Scanning artifact available.
-Some security scanners require to send a list of project dependencies to GitLab
-central servers to check for vulnerabilities. To learn more about this or to
-disable it, check the
-[GitLab Dependency Scanning tool documentation](https://gitlab.com/gitlab-org/security-products/dependency-scanning#remote-checks).
-
#### Customizing the Dependency Scanning settings
-The Dependency Scanning settings can be changed through environment variables by using the
+The Dependency Scanning settings can be changed through [environment variables](#available-variables) by using the
[`variables`](../../../ci/yaml/README.md#variables) parameter in `.gitlab-ci.yml`.
-These variables are documented in the
-[Dependency Scanning tool documentation](https://gitlab.com/gitlab-org/security-products/dependency-scanning#settings).
For example:
@@ -116,7 +122,7 @@ include:
template: Dependency-Scanning.gitlab-ci.yml
variables:
- DEP_SCAN_DISABLE_REMOTE_CHECKS: true
+ DS_DISABLE_REMOTE_CHECKS: true
```
Because template is [evaluated before](../../../ci/yaml/README.md#include) the pipeline
@@ -137,6 +143,24 @@ dependency_scanning:
CI_DEBUG_TRACE: "true"
```
+#### Available variables
+
+Dependency Scanning can be [configured](#customizing-the-dependency-scanning-settings)
+using environment variables.
+
+| Environment variable | Function |
+|-------------------------------- |----------|
+| `DS_ANALYZER_IMAGES` | Comma separated list of custom images. The official default images are still enabled. Read more about [customizing analyzers](analyzers.md). |
+| `DS_ANALYZER_IMAGE_PREFIX` | Override the name of the Docker registry providing the official default images (proxy). Read more about [customizing analyzers](analyzers.md). |
+| `DS_ANALYZER_IMAGE_TAG` | Override the Docker tag of the official default images. Read more about [customizing analyzers](analyzers.md). |
+| `DS_DEFAULT_ANALYZERS` | Override the names of the official default images. Read more about [customizing analyzers](analyzers.md). |
+| `DS_DISABLE_REMOTE_CHECKS` | Do not send any data to GitLab. Used in the [Gemnasium analyzer](#remote-checks). |
+| `DS_PULL_ANALYZER_IMAGES` | Pull the images from the Docker registry (set to `0` to disable). |
+| `DS_EXCLUDED_PATHS` | Exclude vulnerabilities from output based on the paths. A comma-separated list of patterns. Patterns can be globs, file or folder paths. Parent directories will also match patterns. |
+| `DS_DOCKER_CLIENT_NEGOTIATION_TIMEOUT` | Time limit for Docker client negotiation. Timeouts are parsed using Go's [`ParseDuration`](https://golang.org/pkg/time/#ParseDuration). Valid time units are `ns`, `us` (or `µs`), `ms`, `s`, `m`, `h`. For example, `300ms`, `1.5h`, or `2h45m`. |
+| `DS_PULL_ANALYZER_IMAGE_TIMEOUT` | Time limit when pulling the image of an analyzer. Timeouts are parsed using Go's [`ParseDuration`](https://golang.org/pkg/time/#ParseDuration). Valid time units are `ns`, `us` (or `µs`), `ms`, `s`, `m`, `h`. For example, `300ms`, `1.5h`, or `2h45m`. |
+| `DS_RUN_ANALYZER_TIMEOUT` | Time limit when running an analyzer. Timeouts are parsed using Go's [`ParseDuration`](https://golang.org/pkg/time/#ParseDuration). Valid time units are `ns`, `us` (or `µs`), `ms`, `s`, `m`, `h`. For example, `300ms`, `1.5h`, or `2h45m`. |
+
### Manual job definition for GitLab 11.5 and later
For GitLab 11.5 and GitLab Runner 11.5 and later, the following `dependency_scanning`
@@ -171,7 +195,7 @@ dependency_scanning:
dependency_scanning: gl-dependency-scanning-report.json
```
-You can supply many other [settings variables](https://gitlab.com/gitlab-org/security-products/dependency-scanning#settings)
+You can supply many other [settings variables](#available-variables)
via `docker run --env` to customize your job execution.
### Manual job definition for GitLab 11.4 and earlier (deprecated)
@@ -346,7 +370,7 @@ the report JSON unless stated otherwise. Presence of optional fields depends on
| `vulnerabilities[].scanner` | A node that describes the analyzer used to find this vulnerability. |
| `vulnerabilities[].scanner.id` | Id of the scanner as a snake_case string. |
| `vulnerabilities[].scanner.name` | Name of the scanner, for display purposes. |
-| `vulnerabilities[].location` | A node that tells where the vulnerability is located. |
+| `vulnerabilities[].location` | A node that tells where the vulnerability is located. |
| `vulnerabilities[].location.file` | Path to the dependencies file (e.g., `yarn.lock`). Optional. |
| `vulnerabilities[].location.dependency` | A node that describes the dependency of a project where the vulnerability is located. |
| `vulnerabilities[].location.dependency.package` | A node that provides the information on the package where the vulnerability is located. |
@@ -379,17 +403,21 @@ Once a vulnerability is found, you can interact with it. Read more on how to
## Dependency List
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/issues/10075)
-in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.0.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/issues/10075) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.0.
+
+An additional benefit of Dependency Scanning is the ability to get a list of your
+project's dependencies with their versions. This list can be generated only for
+[languages and package managers](#supported-languages-and-package-managers)
+supported by Gemnasium.
-An additional benefit of Dependency Scanning is the ability to get a list of your project's dependencies with their versions.
+To see the generated dependency list, navigate to your project's **Project > Dependency List**.
-This list can be generated only for [languages and package managers](#supported-languages-and-package-managers) supported by [Gemnasium](https://gitlab.com/gitlab-org/security-products/gemnasium/general).
+## Versioning and release process
-To see the generated dependency list, navigate to the Dependency List page under your project's left sidebar menu **Project > Dependency List**.
+Please check the [Release Process documentation](https://gitlab.com/gitlab-org/security-products/release/blob/master/docs/release_process.md).
## Contributing to the vulnerability database
You can search the [gemnasium-db](https://gitlab.com/gitlab-org/security-products/gemnasium-db) project
to find a vulnerability in the Gemnasium database.
-You can also [submit new vulnerabilities](https://gitlab.com/gitlab-org/security-products/gemnasium-db/blob/master/CONTRIBUTING.md). \ No newline at end of file
+You can also [submit new vulnerabilities](https://gitlab.com/gitlab-org/security-products/gemnasium-db/blob/master/CONTRIBUTING.md).
diff --git a/doc/user/application_security/license_management/img/license_management_add_license.png b/doc/user/application_security/license_management/img/license_management_add_license.png
new file mode 100644
index 00000000000..1e1a698515b
--- /dev/null
+++ b/doc/user/application_security/license_management/img/license_management_add_license.png
Binary files differ
diff --git a/doc/user/application_security/license_management/img/license_management_search.png b/doc/user/application_security/license_management/img/license_management_search.png
new file mode 100644
index 00000000000..7b6006cef9d
--- /dev/null
+++ b/doc/user/application_security/license_management/img/license_management_search.png
Binary files differ
diff --git a/doc/user/application_security/license_management/img/license_management_settings.png b/doc/user/application_security/license_management/img/license_management_settings.png
index b5490e59074..1a2bfa78a03 100644
--- a/doc/user/application_security/license_management/img/license_management_settings.png
+++ b/doc/user/application_security/license_management/img/license_management_settings.png
Binary files differ
diff --git a/doc/user/application_security/license_management/index.md b/doc/user/application_security/license_management/index.md
index 7a583016586..957c4ede981 100644
--- a/doc/user/application_security/license_management/index.md
+++ b/doc/user/application_security/license_management/index.md
@@ -262,6 +262,8 @@ To approve or blacklist a license:
navigate to the project's **Settings > CI/CD** and expand the
**License Management** section.
1. Click the **Add a license** button.
+
+ ![License Management Add License](img/license_management_add_license.png)
1. In the **License name** dropdown, either:
- Select one of the available licenses. You can search for licenses in the field
at the top of the list.
@@ -270,8 +272,22 @@ To approve or blacklist a license:
1. Select the **Approve** or **Blacklist** radio button to approve or blacklist respectively
the selected license.
+
+
+To modify an existing license:
+
+1. In the **License Management** list, click the **Approved/Declined** dropdown to change it to the desired status.
+
![License Management Settings](img/license_management_settings.png)
+Searching for Licenses:
+
+1. Use the **Search** box to search for a specific license.
+
+ ![License Management Search](img/license_management_search.png)
+
+
+
## License Management report under pipelines
> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/issues/5491)
diff --git a/doc/user/group/contribution_analytics/index.md b/doc/user/group/contribution_analytics/index.md
index 7e6cb24a51e..0da131ab7bd 100644
--- a/doc/user/group/contribution_analytics/index.md
+++ b/doc/user/group/contribution_analytics/index.md
@@ -21,9 +21,9 @@ page.
## Use cases
- Analyze your team's contributions over a period of time, and offer a bonus for the top
-contributors.
+ contributors.
- Identify opportunities for improvement with group members who may benefit from additional
-support.
+ support.
## Using Contribution Analytics
diff --git a/doc/user/group/epics/index.md b/doc/user/group/epics/index.md
index 2e4106f55e5..f53c1dd95d7 100644
--- a/doc/user/group/epics/index.md
+++ b/doc/user/group/epics/index.md
@@ -202,8 +202,8 @@ You may also consult the [group permissions table][permissions].
## Thread
- Comments: collaborate on that epic by posting comments in its thread.
-These text fields also fully support
-[GitLab Flavored Markdown](../../markdown.md#gitlab-flavored-markdown-gfm).
+ These text fields also fully support
+ [GitLab Flavored Markdown](../../markdown.md#gitlab-flavored-markdown-gfm).
## Comment, or start a discussion
@@ -216,7 +216,7 @@ Once you wrote your comment, you can either:
- You can [award an emoji](../../award_emojis.md) to that epic or its comments.
-## Notifications
+## Notifications
- [Receive notifications](../../../workflow/notifications.md) for epic events.
diff --git a/doc/user/group/index.md b/doc/user/group/index.md
index abd95eddf63..183b12b1c73 100644
--- a/doc/user/group/index.md
+++ b/doc/user/group/index.md
@@ -41,12 +41,13 @@ You can create groups for numerous reasons. To name a couple:
- Make it easier to `@mention` all of your team at once in issues and merge requests by creating a group and including the appropriate members.
For example, you could create a group for your company members, and create a [subgroup](subgroups/index.md) for each individual team. Let's say you create a group called `company-team`, and you create subgroups in this group for the individual teams `backend-team`, `frontend-team`, and `production-team`.
- - When you start a new implementation from an issue, you add a comment:
- _"`@company-team`, let's do it! `@company-team/backend-team` you're good to go!"_
- - When your backend team needs help from frontend, they add a comment:
- _"`@company-team/frontend-team` could you help us here please?"_
- - When the frontend team completes their implementation, they comment:
- _"`@company-team/backend-team`, it's done! Let's ship it `@company-team/production-team`!"_
+
+- When you start a new implementation from an issue, you add a comment:
+ _"`@company-team`, let's do it! `@company-team/backend-team` you're good to go!"_
+- When your backend team needs help from frontend, they add a comment:
+ _"`@company-team/frontend-team` could you help us here please?"_
+- When the frontend team completes their implementation, they comment:
+ _"`@company-team/backend-team`, it's done! Let's ship it `@company-team/production-team`!"_
## Namespaces
@@ -268,9 +269,10 @@ be unique.
To change your group path:
-1. Navigate to your group's **Settings > General**.
-1. Enter a new name under **Group path**.
-1. Click **Save group**.
+1. Navigate to your group's **Settings > General** page.
+1. Expand the **Path, transfer, remove** section.
+1. Enter a new name under **Change group path**.
+1. Click **Change group path**.
CAUTION: **Caution:**
It is currently not possible to rename a namespace if it contains a
diff --git a/doc/user/group/saml_sso/scim_setup.md b/doc/user/group/saml_sso/scim_setup.md
index 96cc523f4ec..5aef463d782 100644
--- a/doc/user/group/saml_sso/scim_setup.md
+++ b/doc/user/group/saml_sso/scim_setup.md
@@ -24,27 +24,27 @@ The following identity providers are supported:
## Requirements
-- [Group SSO](index.md) needs to be configured.
+- [Group SSO](index.md) needs to be configured.
- The `scim_group` feature flag must be enabled:
Run the following commands in a Rails console:
-
+
```sh
# Omnibus GitLab
gitlab-rails console
-
+
# Installation from source
cd /home/git/gitlab
sudo -u git -H bin/rails console RAILS_ENV=production
```
-
+
To enable SCIM for a group named `group_name`:
-
+
```ruby
group = Group.find_by_full_path('group_name')
Feature.enable(:group_scim, group)
```
-
+
### GitLab configuration
Once [Single sign-on](index.md) has been configured, we can:
@@ -53,7 +53,7 @@ Once [Single sign-on](index.md) has been configured, we can:
1. Click on the **Generate a SCIM token** button.
1. Save the token and URL so they can be used in the next step.
-![SCIM token configuration](img/scim_token.png)
+![SCIM token configuration](img/scim_token.png)
## SCIM IdP configuration
@@ -63,15 +63,15 @@ In the [Single sign-on](index.md) configuration for the group, make sure
that the **Name identifier value** (NameID) points to a unique identifier, such
as the `user.objectid`. This will match the `extern_uid` used on GitLab.
-The GitLab app in Azure needs to be configured following
+The GitLab app in Azure needs to be configured following
[Azure's SCIM setup](https://docs.microsoft.com/en-us/azure/active-directory/manage-apps/use-scim-to-provision-users-and-groups#getting-started).
Note the following:
- The `Tenant URL` and `secret token` are the ones retrieved in the
-[previous step](#gitlab-configuration).
+ [previous step](#gitlab-configuration).
- Should there be any problems with the availability of GitLab or similar
-errors, the notification email set will get those.
+ errors, the notification email set will get those.
- For mappings, we will only leave `Synchronize Azure Active Directory Users to AppName` enabled.
You can then test the connection clicking on `Test Connection`.
@@ -79,14 +79,14 @@ You can then test the connection clicking on `Test Connection`.
### Synchronize Azure Active Directory users
1. Click on `Synchronize Azure Active Directory Users to AppName`, to configure
-the attribute mapping.
+ the attribute mapping.
1. Select the unique identifier (in the example `objectId`) as the `id` and `externalId`,
-and enable the `Create`, `Update`, and `Delete` actions.
+ and enable the `Create`, `Update`, and `Delete` actions.
1. Map the `userPricipalName` to `emails[type eq "work"].value` and `mailNickname` to
-`userName`.
+ `userName`.
Example configuration:
-
+
![Azure's attribute mapping configuration](img/scim_attribute_mapping.png)
1. Click on **Show advanced options > Edit attribute list for AppName**.
@@ -95,11 +95,11 @@ and enable the `Create`, `Update`, and `Delete` actions.
NOTE: **Note:**
`username` should neither be primary nor required as we don't support
that field on GitLab SCIM yet.
-
+
![Azure's attribute advanced configuration](img/scim_advanced.png)
1. Save all the screens and, in the **Provisioning** step, set
-the `Provisioning Status` to `ON`.
+ the `Provisioning Status` to `ON`.
NOTE: **Note:**
You can control what is actually synced by selecting the `Scope`. For example,
diff --git a/doc/user/project/clusters/index.md b/doc/user/project/clusters/index.md
index 547a0c36108..97d2dfc0f7e 100644
--- a/doc/user/project/clusters/index.md
+++ b/doc/user/project/clusters/index.md
@@ -519,10 +519,11 @@ service account of the cluster integration.
### Troubleshooting failed deployment jobs
-GitLab will create a namespace and service account specifically for your
-deployment jobs. On project level clusters, this happens when the cluster
-is created. On group level clusters, resources are created immediately
-before the deployment job starts.
+Before the deployment jobs starts, GitLab creates the following specifically for
+the deployment job:
+
+- A namespace.
+- A service account.
However, sometimes GitLab can not create them. In such instances, your job will fail with the message:
diff --git a/doc/user/project/clusters/kubernetes_pod_logs.md b/doc/user/project/clusters/kubernetes_pod_logs.md
index 368031070c1..25d8abebf07 100644
--- a/doc/user/project/clusters/kubernetes_pod_logs.md
+++ b/doc/user/project/clusters/kubernetes_pod_logs.md
@@ -12,9 +12,9 @@ By displaying the logs directly in GitLab, developers can avoid having to manage
1. Go to **Operations > Environments** and find the environment which contains the desired pod, like `production`.
1. On the **Environments** page, you should see the status of the environment's pods with [Deploy Boards](../deploy_boards.md).
1. When mousing over the list of pods, a tooltip will appear with the exact pod name and status.
-![Deploy Boards pod list](img/pod_logs_deploy_board.png)
+ ![Deploy Boards pod list](img/pod_logs_deploy_board.png)
1. Click on the desired pod to bring up the logs view, which will contain the last 500 lines for that pod. Support for pods with multiple containers is coming [in a future release](https://gitlab.com/gitlab-org/gitlab-ee/issues/6502).
-![Deploy Boards pod list](img/kubernetes_pod_logs.png)
+ ![Deploy Boards pod list](img/kubernetes_pod_logs.png)
## Requirements
diff --git a/doc/user/project/container_registry.md b/doc/user/project/container_registry.md
index 58b7fe33906..fdf9ce3e225 100644
--- a/doc/user/project/container_registry.md
+++ b/doc/user/project/container_registry.md
@@ -113,6 +113,7 @@ This feature requires GitLab 8.8 and GitLab Runner 1.2.
Make sure that your GitLab Runner is configured to allow building Docker images by
following the [Using Docker Build](../../ci/docker/using_docker_build.md)
and [Using the GitLab Container Registry documentation](../../ci/docker/using_docker_build.md#using-the-gitlab-container-registry).
+Alternatively, you can [build images with Kaniko](../../ci/docker/using_kaniko.md) if the Docker builds are not an option for you.
## Using with private projects
diff --git a/doc/user/project/deploy_boards.md b/doc/user/project/deploy_boards.md
index 2aef369c087..175384bc985 100644
--- a/doc/user/project/deploy_boards.md
+++ b/doc/user/project/deploy_boards.md
@@ -88,7 +88,10 @@ To display the Deploy Boards for a specific [environment] you should:
Kubernetes.
NOTE: **Note:**
- Matching based on the Kubernetes `app` label was removed in [GitLab 12.1](https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/14020)
+ Matching based on the Kubernetes `app` label was removed in [GitLab
+ 12.1](https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/14020).
+ To migrate, please apply the required annotations (see above) and
+ re-deploy your application.
![Deploy Boards Kubernetes Label](img/deploy_boards_kubernetes_label.png)
diff --git a/doc/user/project/description_templates.md b/doc/user/project/description_templates.md
index a8c5d4d95b5..7520237251a 100644
--- a/doc/user/project/description_templates.md
+++ b/doc/user/project/description_templates.md
@@ -25,14 +25,14 @@ templates of the default branch will be taken into account.
## Use-cases
- Add a template to be used in every issue for a specific project,
-giving instructions and guidelines, requiring for information specific to that subject.
-For example, if you have a project for tracking new blog posts, you can require the
-title, outlines, author name, author social media information, etc.
+ giving instructions and guidelines, requiring for information specific to that subject.
+ For example, if you have a project for tracking new blog posts, you can require the
+ title, outlines, author name, author social media information, etc.
- Following the previous example, you can make a template for every MR submitted
-with a new blog post, requiring information about the post date, frontmatter data,
-images guidelines, link to the related issue, reviewer name, etc.
+ with a new blog post, requiring information about the post date, frontmatter data,
+ images guidelines, link to the related issue, reviewer name, etc.
- You can also create issues and merge request templates for different
-stages of your workflow, e.g., feature proposal, feature improvement, bug report, etc.
+ stages of your workflow, e.g., feature proposal, feature improvement, bug report, etc.
## Creating issue templates
@@ -58,6 +58,7 @@ changes you made after picking the template and return it to its initial status.
## Setting a default template for issues and merge requests **[STARTER]**
> **Notes:**
+>
> - This feature was introduced before [description templates](#overview) and is
> available in [GitLab Starter][products]. It can be enabled
> in the project's settings.
diff --git a/doc/user/project/integrations/hipchat.md b/doc/user/project/integrations/hipchat.md
index 0fd847d415f..7a0540aa9e3 100644
--- a/doc/user/project/integrations/hipchat.md
+++ b/doc/user/project/integrations/hipchat.md
@@ -23,7 +23,7 @@ allow GitLab to send messages only to *one* room.
1. Find "Build Your Own!" and click "Create".
1. Select the desired room, name the integration "GitLab", and click "Create".
1. In the "Send messages to this room by posting this URL" column, you should
-see a URL in the format:
+ see a URL in the format:
```
https://api.hipchat.com/v2/room/<room>/notification?auth_token=<token>
diff --git a/doc/user/project/issues/index.md b/doc/user/project/issues/index.md
index 76dc6e49bce..4acbb4cc3f6 100644
--- a/doc/user/project/issues/index.md
+++ b/doc/user/project/issues/index.md
@@ -134,4 +134,4 @@ For more information, see [Crosslinking issues](crosslinking_issues.md).
- [Export issues](csv_export.md) **[STARTER]**
- [Issues API](../../../api/issues.md)
- Configure an [external issue tracker](../../../integration/external-issue-tracker.md) such as Jira, Redmine,
-or Bugzilla.
+ or Bugzilla.
diff --git a/doc/user/project/merge_requests/merge_request_approvals.md b/doc/user/project/merge_requests/merge_request_approvals.md
index fd151a6df45..8e8ec26daf2 100644
--- a/doc/user/project/merge_requests/merge_request_approvals.md
+++ b/doc/user/project/merge_requests/merge_request_approvals.md
@@ -12,9 +12,9 @@ to approve a merge request before it can be unblocked for merging.
## Use cases
1. Enforcing review of all code that gets merged into a repository.
-2. Specifying code maintainers for an entire repository.
-3. Specifying reviewers for a given proposed code change.
-4. Specifying categories of reviewers, such as BE, FE, QA, DB, etc., for all proposed code changes.
+1. Specifying code maintainers for an entire repository.
+1. Specifying reviewers for a given proposed code change.
+1. Specifying categories of reviewers, such as BE, FE, QA, DB, etc., for all proposed code changes.
## Enabling the new approvals interface
@@ -246,7 +246,7 @@ restrictions (compared to [GitLab Starter](#overriding-the-merge-request-approva
- Approval rules can be added to an MR with no restriction.
- For project sourced approval rules, editing and removing approvers is not allowed.
- The approvals required of all approval rules is configurable, but if a rule is backed by a project rule, then it is restricted
-to the minimum approvals required set in the project's corresponding rule.
+ to the minimum approvals required set in the project's corresponding rule.
## Resetting approvals on push
diff --git a/doc/user/project/pages/getting_started_part_two.md b/doc/user/project/pages/getting_started_part_two.md
index 3e50cd4887c..fe92d19567d 100644
--- a/doc/user/project/pages/getting_started_part_two.md
+++ b/doc/user/project/pages/getting_started_part_two.md
@@ -77,10 +77,10 @@ containing the most popular SSGs templates to get you started.
1. [Fork](../../../gitlab-basics/fork-project.md) a sample project from the [GitLab Pages examples](https://gitlab.com/pages) group.
1. From the left sidebar, navigate to your project's **CI/CD > Pipelines**
-and click **Run pipeline** to trigger GitLab CI/CD to build and deploy your
-site to the server.
+ and click **Run pipeline** to trigger GitLab CI/CD to build and deploy your
+ site to the server.
1. Once the pipeline has finished successfully, find the link to visit your
-website from your project's **Settings > Pages**.
+ website from your project's **Settings > Pages**.
You can also take some **optional** further steps:
@@ -89,14 +89,14 @@ You can also take some **optional** further steps:
![remove fork relationship](img/remove_fork_relationship.png)
- _Make it a user or group website._ To turn a **project website** forked
-from the Pages group into a **user/group** website, you'll need to:
+ from the Pages group into a **user/group** website, you'll need to:
- Rename it to `namespace.gitlab.io`: go to your project's
- **Settings > General** and expand **Advanced**. Scroll down to
- **Rename repository** and change the path to `namespace.gitlab.io`.
+ **Settings > General** and expand **Advanced**. Scroll down to
+ **Rename repository** and change the path to `namespace.gitlab.io`.
- Adjust your SSG's [base URL](#urls-and-baseurls) from `"project-name"` to
- `""`. This setting will be at a different place for each SSG, as each of them
- have their own structure and file tree. Most likely, it will be in the SSG's
- config file.
+ `""`. This setting will be at a different place for each SSG, as each of them
+ have their own structure and file tree. Most likely, it will be in the SSG's
+ config file.
### Create a project from scratch
diff --git a/doc/user/project/pages/index.md b/doc/user/project/pages/index.md
index 04bda212128..fa79c393b72 100644
--- a/doc/user/project/pages/index.md
+++ b/doc/user/project/pages/index.md
@@ -12,7 +12,6 @@ type: index, reference
> - Support for subgroup project's websites was [introduced](https://gitlab.com/gitlab-org/gitlab-ce/issues/30548) in GitLab 11.8.
> - Bundled project templates were [introduced](https://gitlab.com/gitlab-org/gitlab-ce/issues/47857) in GitLab 11.8.
-
**GitLab Pages is a feature that allows you to publish static websites
directly from a repository in GitLab.**
@@ -105,10 +104,10 @@ To get started with GitLab Pages, you can either:
![Project templates for Pages](img/pages_project_templates_11-8.png)
1. From the left sidebar, navigate to your project's **CI/CD > Pipelines**
-and click **Run pipeline** to trigger GitLab CI/CD to build and deploy your
-site to the server.
+ and click **Run pipeline** to trigger GitLab CI/CD to build and deploy your
+ site to the server.
1. Once the pipeline has finished successfully, find the link to visit your
-website from your project's **Settings > Pages**.
+ website from your project's **Settings > Pages**.
Your website is then visible on your domain, and you can modify yourfiles
as you wish. For every modification pushed to your repository, GitLab CI/CD
diff --git a/doc/user/project/pages/introduction.md b/doc/user/project/pages/introduction.md
index 4fab7f79e0c..4ea3bd9be9b 100644
--- a/doc/user/project/pages/introduction.md
+++ b/doc/user/project/pages/introduction.md
@@ -13,17 +13,17 @@ To familiarize yourself with GitLab Pages first:
- Read an [introduction to GitLab Pages](index.md#overview).
- Learn [how to get started with Pages](index.md#getting-started).
- Learn how to enable GitLab Pages
-across your GitLab instance on the [administrator documentation](../../../administration/pages/index.md).
+ across your GitLab instance on the [administrator documentation](../../../administration/pages/index.md).
## GitLab Pages requirements
In brief, this is what you need to upload your website in GitLab Pages:
1. Domain of the instance: domain name that is used for GitLab Pages
-(ask your administrator).
+ (ask your administrator).
1. GitLab CI/CD: a `.gitlab-ci.yml` file with a specific job named [`pages`][pages] in the root directory of your repository.
1. A directory called `public` in your site's repo containing the content
-to be published.
+ to be published.
1. GitLab Runner enabled for the project.
## GitLab Pages on GitLab.com
diff --git a/doc/user/project/settings/index.md b/doc/user/project/settings/index.md
index ba890c5ac01..be4215b1934 100644
--- a/doc/user/project/settings/index.md
+++ b/doc/user/project/settings/index.md
@@ -26,10 +26,10 @@ Set up your project's access, [visibility](../../../public_access/public_access.
![projects sharing permissions](img/sharing_and_permissions_settings.png)
-If Issues are disabled, or you can't access Issues because you're not a project member, then Lables and Milestones
+If Issues are disabled, or you can't access Issues because you're not a project member, then Lables and Milestones
links will be missing from the sidebar UI.
-You can still access them with direct links if you can access Merge Requests. This is deliberate, if you can see
+You can still access them with direct links if you can access Merge Requests. This is deliberate, if you can see
Issues or Merge Requests, both of which use Labels and Milestones, then you shouldn't be denied access to Labels and Milestones pages.
### Issue settings
@@ -109,8 +109,8 @@ You can transfer an existing project into a [group](../../group/index.md) if:
1. You have at least **Maintainer** [permissions] to that group.
1. The project is in a subgroup you own.
1. You are at least a **Maintainer** of the project under your personal namespace.
-Similarly, if you are an owner of a group, you can transfer any of its projects
-under your own user.
+ Similarly, if you are an owner of a group, you can transfer any of its projects
+ under your own user.
To transfer a project:
diff --git a/doc/user/project/web_ide/index.md b/doc/user/project/web_ide/index.md
index ef4eb45de66..7d85f4adfed 100644
--- a/doc/user/project/web_ide/index.md
+++ b/doc/user/project/web_ide/index.md
@@ -67,8 +67,8 @@ shows you a preview of the merge request diff if you commit your changes.
> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/19279) in [GitLab Core][ce] 11.0.
-You can use the Web IDE to quickly fix failing tests by opening
-the branch or merge request in the Web IDE and opening the logs of the failed
+You can use the Web IDE to quickly fix failing tests by opening
+the branch or merge request in the Web IDE and opening the logs of the failed
job. You can access the status of all jobs for the most recent pipeline and job
traces for the current commit by clicking the **Pipelines** button in the top
right.
@@ -80,8 +80,8 @@ left.
> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/19318) in [GitLab Core][ce] 11.0.
-To switch between your authored and assigned merge requests, click the
-dropdown in the top of the sidebar to open a list of merge requests. You will
+To switch between your authored and assigned merge requests, click the
+dropdown in the top of the sidebar to open a list of merge requests. You will
need to commit or discard all your changes before switching to a different merge
request.
@@ -89,9 +89,9 @@ request.
> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/20850) in [GitLab Core][ce] 11.2.
-To switch between branches of the current project repository, click the dropdown
-in the top of the sidebar to open a list of branches.
-You will need to commit or discard all your changes before switching to a
+To switch between branches of the current project repository, click the dropdown
+in the top of the sidebar to open a list of branches.
+You will need to commit or discard all your changes before switching to a
different branch.
## Client Side Evaluation
@@ -117,7 +117,7 @@ GitLab.com
![Admin Client Side Evaluation setting](img/admin_clientside_evaluation.png)
Once you have done that, you can preview projects with a `package.json` file and
-a `main` entry point inside the Web IDE. An example `package.json` is shown
+a `main` entry point inside the Web IDE. An example `package.json` is shown
below.
```json
@@ -135,24 +135,20 @@ below.
CAUTION: **Warning:**
Interactive Web Terminals for the Web IDE is currently in **Beta**.
+Shared Runners [do not yet support Interactive Web Terminals](https://gitlab.com/gitlab-org/gitlab-ce/issues/52611),
+so you would need to use your own private Runner(s) to make use of this feature.
-[Interactive web terminals](../../../ci/interactive_web_terminal/index.md)
-give the user access to a terminal to interact with the Runner directly from
+[Interactive Web Terminals](../../../ci/interactive_web_terminal/index.md)
+give the project [Maintainers](../../permissions.md#project-members-permissions)
+user access to a terminal to interact with the Runner directly from
GitLab, including through the Web IDE.
-Only project [**maintainers**](../../permissions.md#project-members-permissions)
-can run Interactive Web Terminals through the Web IDE.
-
-CAUTION: **Warning:**
-GitLab.com [does not support Interactive Web Terminals yet](https://gitlab.com/gitlab-org/gitlab-ce/issues/52611).
-Shared Runners in private instances are not supported either.
-
### Runner configuration
Some things need to be configured in the runner for the interactive web terminal
to work:
-- The Runner needs to have
+- The Runner needs to have
[`[session_server]` configured properly](https://docs.gitlab.com/runner/configuration/advanced-configuration.html#the-session_server-section).
- If you are using a reverse proxy with your GitLab instance, web terminals need to be
[enabled](../../../administration/integration/terminal.md#enabling-and-disabling-terminal-support). **[ULTIMATE ONLY]**
@@ -175,13 +171,13 @@ syntax but with some restrictions:
- No global blocks can be defined (ie: `before_script` or `after_script`)
- Only one job named `terminal` can be added to this file.
- Only the keywords `image`, `services`, `tags`, `before_script`, `script`, and
-`variables` are allowed to be used to configure the job.
+ `variables` are allowed to be used to configure the job.
- To connect to the interactive terminal, the `terminal` job must be still alive
-and running, otherwise the terminal won't be able to connect to the job's session.
-By default the `script` keyword has the value `sleep 60` to prevent
-the job from ending and giving the Web IDE enough time to connect. This means
-that, if you override the default `script` value, you'll have to add a command
-which would keep the job running, like `sleep`.
+ and running, otherwise the terminal won't be able to connect to the job's session.
+ By default the `script` keyword has the value `sleep 60` to prevent
+ the job from ending and giving the Web IDE enough time to connect. This means
+ that, if you override the default `script` value, you'll have to add a command
+ which would keep the job running, like `sleep`.
In the code below there is an example of this configuration file:
@@ -204,7 +200,7 @@ the selected branch of the Web IDE.
If there is no configuration file in a branch, an error message will be shown.
-### Running Interactive Terminals in the Web IDE
+### Running interactive terminals in the Web IDE
If Interactive Terminals are available for the current user, the **Terminal** button
will be visible in the right sidebar of the Web IDE. Click this button to open
@@ -212,7 +208,7 @@ or close the terminal tab.
Once open, the tab will show the **Start Web Terminal** button. This button may
be disabled if the environment is not configured correctly. If so, a status
-message will describe the issue. Here are some reasons why **Start Web Terminal**
+message will describe the issue. Here are some reasons why **Start Web Terminal**
may be disabled:
- `.gitlab/.gitlab-webide.yml` does not exist or is set up incorrectly.
@@ -231,45 +227,27 @@ While the terminal is running, it can be stopped by clicking **Stop Terminal**.
This will disconnect the terminal and stop the runner's terminal job. From here,
click **Restart Terminal** to start a new terminal session.
-### File Syncing to Web Terminal
+### File syncing to web terminal
> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/issues/5276) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.0.
-File changes in the Web IDE can be synced to a running Web Terminal.
+File changes in the Web IDE can be synced to a running web terminal.
This enables users to test their code changes in a preconfigured terminal
environment.
NOTE: **Note:**
Only file changes in the Web IDE are synced to the terminal.
Changes made in the terminal are **not** synced to the Web IDE.
+This feature is only available for Kubernetes Runners.
-Once you have [configured the Web Terminal for File Syncing](#configuring-file-syncing),
-then when the Web terminal is started, a **Terminal** status will be visible
-in the status bar.
-
-![Web IDE Client Side Evaluation](img/terminal_status.png)
-
-Changes made to your files via the Web IDE will sync to the running terminal
-when:
-
-- <kbd>Ctrl</kbd> + <kbd>S</kbd> (or <kbd>Cmd</kbd> + <kbd>S</kbd> on Mac)
- is pressed while editing a file.
-- Anything outside the file editor is clicked after editing a file.
-- A file or folder is created, deleted, or renamed.
-
-### Configuring File Syncing
-
-NOTE: **Note:**
-This feature is only available for Kubernetes runners.
-
-To enable file syncing to the Web Terminal, the `.gitlab/.gitlab-webide.yml`
-file needs to have a `webide-file-sync` service configured. Here is an example
+To enable file syncing to the web terminal, the `.gitlab/.gitlab-webide.yml`
+file needs to have a `webide-file-sync` service configured. Here is an example
configuration for a Node JS project which uses this service:
```yaml
terminal:
# This can be any image that has the necessary runtime environment for your project.
- image:
+ image:
name: node:10-alpine
services:
- name: registry.gitlab.com/gitlab-org/webide-file-sync:latest
@@ -281,18 +259,30 @@ terminal:
- number: 3000
```
-> **Notes:**
-> - For now, the `webide-file-sync` executable must start **after** the project
-> directory is available. This is why we need to add `sleep 5` to the `command`.
-> See [this issue](https://gitlab.com/gitlab-org/webide-file-sync/issues/7) for
-> more info.
-> - `$CI_PROJECT_DIR` is a
-> [predefined environment variable](../../../ci/variables/predefined_variables.md)
-> for GitLab Runners. This is where your project's repository will be.
+- The `webide-file-sync` executable must start **after** the project
+ directory is available. This is why we need to add `sleep 5` to the `command`.
+ See [this issue](https://gitlab.com/gitlab-org/webide-file-sync/issues/7) for
+ more info.
+- `$CI_PROJECT_DIR` is a
+ [predefined environment variable](../../../ci/variables/predefined_variables.md)
+ for GitLab Runners. This is where your project's repository will be.
+
+Once you have configured the web terminal for file syncing, then when the web
+terminal is started, a **Terminal** status will be visible in the status bar.
+
+![Web IDE Client Side Evaluation](img/terminal_status.png)
+
+Changes made to your files via the Web IDE will sync to the running terminal
+when:
+
+- <kbd>Ctrl</kbd> + <kbd>S</kbd> (or <kbd>Cmd</kbd> + <kbd>S</kbd> on Mac)
+ is pressed while editing a file.
+- Anything outside the file editor is clicked after editing a file.
+- A file or folder is created, deleted, or renamed.
### Limitations
-Interactive Terminals is in a beta phase and will continue to be improved upon in upcoming
+Interactive Terminals is in a beta phase and will continue to be improved upon in upcoming
releases. In the meantime, please note that the user is limited to having only one
active terminal at a time.
diff --git a/doc/workflow/time_tracking.md b/doc/workflow/time_tracking.md
index c03dffa967d..4286a3625a2 100644
--- a/doc/workflow/time_tracking.md
+++ b/doc/workflow/time_tracking.md
@@ -73,7 +73,15 @@ The following time units are available:
Default conversion rates are 1mo = 4w, 1w = 5d and 1d = 8h.
-Other interesting links:
+### Limit displayed units to hours
+
+> Introduced in GitLab 12.0.
+
+The display of time units can be limited to hours through the option in **Admin Area > Settings > Preferences** under 'Localization'.
+
+With this option enabled, `75h` is displayed instead of `1w 4d 3h`.
+
+## Other interesting links
- [Time Tracking landing page on about.gitlab.com](https://about.gitlab.com/solutions/time-tracking/)
diff --git a/lib/after_commit_queue.rb b/lib/after_commit_queue.rb
index 6fb7985f955..6a180fdf338 100644
--- a/lib/after_commit_queue.rb
+++ b/lib/after_commit_queue.rb
@@ -15,7 +15,7 @@ module AfterCommitQueue
end
def run_after_commit_or_now(&block)
- if AfterCommitQueue.inside_transaction?
+ if Gitlab::Database.inside_transaction?
if ActiveRecord::Base.connection.current_transaction.records.include?(self)
run_after_commit(&block)
else
@@ -32,18 +32,6 @@ module AfterCommitQueue
true
end
- def self.open_transactions_baseline
- if ::Rails.env.test?
- return DatabaseCleaner.connections.count { |conn| conn.strategy.is_a?(DatabaseCleaner::ActiveRecord::Transaction) }
- end
-
- 0
- end
-
- def self.inside_transaction?
- ActiveRecord::Base.connection.open_transactions > open_transactions_baseline
- end
-
protected
def _run_after_commit_queue
diff --git a/lib/api/branches.rb b/lib/api/branches.rb
index 65d7f68bbf9..c3821630b6b 100644
--- a/lib/api/branches.rb
+++ b/lib/api/branches.rb
@@ -8,7 +8,10 @@ module API
BRANCH_ENDPOINT_REQUIREMENTS = API::NAMESPACE_OR_PROJECT_REQUIREMENTS.merge(branch: API::NO_SLASH_URL_PART_REGEX)
- before { authorize! :download_code, user_project }
+ before do
+ require_repository_enabled!
+ authorize! :download_code, user_project
+ end
helpers do
params :filter_params do
diff --git a/lib/api/commits.rb b/lib/api/commits.rb
index 80913f4ca07..eebded87ebc 100644
--- a/lib/api/commits.rb
+++ b/lib/api/commits.rb
@@ -6,7 +6,10 @@ module API
class Commits < Grape::API
include PaginationParams
- before { authorize! :download_code, user_project }
+ before do
+ require_repository_enabled!
+ authorize! :download_code, user_project
+ end
helpers do
def user_access
diff --git a/lib/api/entities.rb b/lib/api/entities.rb
index 25e9fdd5fce..ead01dc53f7 100644
--- a/lib/api/entities.rb
+++ b/lib/api/entities.rb
@@ -703,7 +703,7 @@ module API
# See https://gitlab.com/gitlab-org/gitlab-ce/issues/42344 for more
# information.
expose :merge_status do |merge_request|
- merge_request.check_if_can_be_merged
+ merge_request.check_mergeability
merge_request.merge_status
end
expose :diff_head_sha, as: :sha
diff --git a/lib/api/environments.rb b/lib/api/environments.rb
index 6cd43923559..ec58b3b7bb9 100644
--- a/lib/api/environments.rb
+++ b/lib/api/environments.rb
@@ -18,11 +18,16 @@ module API
end
params do
use :pagination
+ optional :name, type: String, desc: 'Returns the environment with this name'
+ optional :search, type: String, desc: 'Returns list of environments matching the search criteria'
+ mutually_exclusive :name, :search, message: 'cannot be used together'
end
get ':id/environments' do
authorize! :read_environment, user_project
- present paginate(user_project.environments), with: Entities::Environment, current_user: current_user
+ environments = ::EnvironmentsFinder.new(user_project, current_user, params).find
+
+ present paginate(environments), with: Entities::Environment, current_user: current_user
end
desc 'Creates a new environment' do
diff --git a/lib/api/helpers.rb b/lib/api/helpers.rb
index 6382d295f79..8ae42c6dadd 100644
--- a/lib/api/helpers.rb
+++ b/lib/api/helpers.rb
@@ -250,6 +250,10 @@ module API
authorize! :update_build, user_project
end
+ def require_repository_enabled!(subject = :global)
+ not_found!("Repository") unless user_project.feature_available?(:repository, current_user)
+ end
+
def require_gitlab_workhorse!
unless env['HTTP_GITLAB_WORKHORSE'].present?
forbidden!('Request should be executed via GitLab Workhorse')
diff --git a/lib/api/merge_requests.rb b/lib/api/merge_requests.rb
index 955624404f1..bf87e9ec2ff 100644
--- a/lib/api/merge_requests.rb
+++ b/lib/api/merge_requests.rb
@@ -397,28 +397,16 @@ module API
present merge_request, with: Entities::MergeRequest, current_user: current_user, project: user_project
end
- desc 'Merge a merge request to its default temporary merge ref path'
- params do
- optional :merge_commit_message, type: String, desc: 'Custom merge commit message'
- end
- put ':id/merge_requests/:merge_request_iid/merge_to_ref' do
+ desc 'Returns the up to date merge-ref HEAD commit'
+ get ':id/merge_requests/:merge_request_iid/merge_ref' do
merge_request = find_project_merge_request(params[:merge_request_iid])
- authorize! :admin_merge_request, user_project
-
- merge_params = {
- commit_message: params[:merge_commit_message]
- }
-
- result = ::MergeRequests::MergeToRefService
- .new(merge_request.target_project, current_user, merge_params)
- .execute(merge_request)
+ result = ::MergeRequests::MergeabilityCheckService.new(merge_request).execute(recheck: true)
- if result[:status] == :success
- present result.slice(:commit_id), 200
+ if result.success?
+ present :commit_id, result.payload.dig(:merge_ref_head, :commit_id)
else
- http_status = result[:http_status] || 400
- render_api_error!(result[:message], http_status)
+ render_api_error!(result.message, 400)
end
end
diff --git a/lib/api/pages_domains.rb b/lib/api/pages_domains.rb
index 78442f465bd..4227a106a95 100644
--- a/lib/api/pages_domains.rb
+++ b/lib/api/pages_domains.rb
@@ -90,14 +90,15 @@ module API
end
params do
requires :domain, type: String, desc: 'The domain'
- optional :certificate, allow_blank: false, types: [File, String], desc: 'The certificate'
- optional :key, allow_blank: false, types: [File, String], desc: 'The key'
- all_or_none_of :certificate, :key
+ optional :certificate, allow_blank: false, types: [File, String], desc: 'The certificate', as: :user_provided_certificate
+ optional :key, allow_blank: false, types: [File, String], desc: 'The key', as: :user_provided_key
+ all_or_none_of :user_provided_certificate, :user_provided_key
end
post ":id/pages/domains" do
authorize! :update_pages, user_project
pages_domain_params = declared(params, include_parent_namespaces: false)
+
pages_domain = user_project.pages_domains.create(pages_domain_params)
if pages_domain.persisted?
@@ -110,8 +111,8 @@ module API
desc 'Updates a pages domain'
params do
requires :domain, type: String, desc: 'The domain'
- optional :certificate, allow_blank: false, types: [File, String], desc: 'The certificate'
- optional :key, allow_blank: false, types: [File, String], desc: 'The key'
+ optional :certificate, allow_blank: false, types: [File, String], desc: 'The certificate', as: :user_provided_certificate
+ optional :key, allow_blank: false, types: [File, String], desc: 'The key', as: :user_provided_key
end
put ":id/pages/domains/:domain", requirements: PAGES_DOMAINS_ENDPOINT_REQUIREMENTS do
authorize! :update_pages, user_project
@@ -119,8 +120,8 @@ module API
pages_domain_params = declared(params, include_parent_namespaces: false)
# Remove empty private key if certificate is not empty.
- if pages_domain_params[:certificate] && !pages_domain_params[:key]
- pages_domain_params.delete(:key)
+ if pages_domain_params[:user_provided_certificate] && !pages_domain_params[:user_provided_key]
+ pages_domain_params.delete(:user_provided_key)
end
if pages_domain.update(pages_domain_params)
diff --git a/lib/api/todos.rb b/lib/api/todos.rb
index d2196f05173..871eaabc887 100644
--- a/lib/api/todos.rb
+++ b/lib/api/todos.rb
@@ -77,7 +77,7 @@ module API
use :pagination
end
get do
- todos = paginate(find_todos.with_api_entity_associations)
+ todos = paginate(find_todos.with_entity_associations)
options = { with: Entities::Todo, current_user: current_user }
batch_load_issuable_metadata(todos, options)
diff --git a/lib/gitlab/bitbucket_import/importer.rb b/lib/gitlab/bitbucket_import/importer.rb
index c9f0ed66a54..8047ef4fa15 100644
--- a/lib/gitlab/bitbucket_import/importer.rb
+++ b/lib/gitlab/bitbucket_import/importer.rb
@@ -11,6 +11,7 @@ module Gitlab
{ title: 'task', color: '#7F8C8D' }].freeze
attr_reader :project, :client, :errors, :users
+ attr_accessor :logger
def initialize(project)
@project = project
@@ -19,6 +20,7 @@ module Gitlab
@labels = {}
@errors = []
@users = {}
+ @logger = Gitlab::Import::Logger.build
end
def execute
@@ -41,6 +43,18 @@ module Gitlab
}.to_json)
end
+ def store_pull_request_error(pull_request, ex)
+ backtrace = Gitlab::Profiler.clean_backtrace(ex.backtrace)
+ error = { type: :pull_request, iid: pull_request.iid, errors: ex.message, trace: backtrace, raw_response: pull_request.raw }
+
+ log_error(error)
+ # Omit the details from the database to avoid blowing up usage in the error column
+ error.delete(:trace)
+ error.delete(:raw_response)
+
+ errors << error
+ end
+
def gitlab_user_id(project, username)
find_user_id(username) || project.creator_id
end
@@ -176,7 +190,7 @@ module Gitlab
import_pull_request_comments(pull_request, merge_request) if merge_request.persisted?
rescue StandardError => e
- errors << { type: :pull_request, iid: pull_request.iid, errors: e.message, trace: e.backtrace.join("\n"), raw_response: pull_request.raw }
+ store_pull_request_error(pull_request, e)
end
end
@@ -254,6 +268,18 @@ module Gitlab
updated_at: comment.updated_at
}
end
+
+ def log_error(details)
+ logger.error(log_base_data.merge(details))
+ end
+
+ def log_base_data
+ {
+ class: self.class.name,
+ project_id: project.id,
+ project_path: project.full_path
+ }
+ end
end
end
end
diff --git a/lib/gitlab/ci/build/prerequisite/kubernetes_namespace.rb b/lib/gitlab/ci/build/prerequisite/kubernetes_namespace.rb
index 531c9ce4256..49c680605ea 100644
--- a/lib/gitlab/ci/build/prerequisite/kubernetes_namespace.rb
+++ b/lib/gitlab/ci/build/prerequisite/kubernetes_namespace.rb
@@ -8,7 +8,6 @@ module Gitlab
def unmet?
deployment_cluster.present? &&
deployment_cluster.managed? &&
- !deployment_cluster.project_type? &&
(kubernetes_namespace.new_record? || kubernetes_namespace.service_account_token.blank?)
end
@@ -21,7 +20,7 @@ module Gitlab
private
def deployment_cluster
- build.deployment&.cluster
+ build.deployment&.deployment_platform_cluster
end
def kubernetes_namespace
diff --git a/lib/gitlab/data_builder/note.rb b/lib/gitlab/data_builder/note.rb
index 16e62622ed4..2c4ef73a688 100644
--- a/lib/gitlab/data_builder/note.rb
+++ b/lib/gitlab/data_builder/note.rb
@@ -44,7 +44,7 @@ module Gitlab
data[:commit] = build_data_for_commit(project, user, note)
elsif note.for_issue?
data[:issue] = note.noteable.hook_attrs
- data[:issue][:labels] = note.noteable.labels(&:hook_attrs)
+ data[:issue][:labels] = note.noteable.labels_hook_attrs
elsif note.for_merge_request?
data[:merge_request] = note.noteable.hook_attrs
elsif note.for_snippet?
diff --git a/lib/gitlab/database.rb b/lib/gitlab/database.rb
index 8da98cc3909..e4d4779ba9a 100644
--- a/lib/gitlab/database.rb
+++ b/lib/gitlab/database.rb
@@ -234,6 +234,7 @@ module Gitlab
def self.connection
ActiveRecord::Base.connection
end
+ private_class_method :connection
def self.cached_column_exists?(table_name, column_name)
connection.schema_cache.columns_hash(table_name).has_key?(column_name.to_s)
@@ -243,8 +244,6 @@ module Gitlab
connection.schema_cache.data_source_exists?(table_name)
end
- private_class_method :connection
-
def self.database_version
row = connection.execute("SELECT VERSION()").first
@@ -272,5 +271,20 @@ module Gitlab
end
end
end
+
+ # inside_transaction? will return true if the caller is running within a transaction. Handles special cases
+ # when running inside a test environment, in which the entire test is running with a DatabaseCleaner transaction
+ def self.inside_transaction?
+ ActiveRecord::Base.connection.open_transactions > open_transactions_baseline
+ end
+
+ def self.open_transactions_baseline
+ if ::Rails.env.test?
+ return DatabaseCleaner.connections.count { |conn| conn.strategy.is_a?(DatabaseCleaner::ActiveRecord::Transaction) }
+ end
+
+ 0
+ end
+ private_class_method :open_transactions_baseline
end
end
diff --git a/lib/gitlab/hook_data/issue_builder.rb b/lib/gitlab/hook_data/issue_builder.rb
index cfc9ebe4f92..e5f86ca02b5 100644
--- a/lib/gitlab/hook_data/issue_builder.rb
+++ b/lib/gitlab/hook_data/issue_builder.rb
@@ -45,7 +45,7 @@ module Gitlab
human_time_estimate: issue.human_time_estimate,
assignee_ids: issue.assignee_ids,
assignee_id: issue.assignee_ids.first, # This key is deprecated
- labels: issue.labels
+ labels: issue.labels_hook_attrs
}
issue.attributes.with_indifferent_access.slice(*self.class.safe_hook_attributes)
diff --git a/lib/gitlab/json_cache.rb b/lib/gitlab/json_cache.rb
index 9a0b2b35112..d01183d7845 100644
--- a/lib/gitlab/json_cache.rb
+++ b/lib/gitlab/json_cache.rb
@@ -22,10 +22,10 @@ module Gitlab
expanded_cache_key = [namespace, key].compact
if cache_key_with_version
- expanded_cache_key << Rails.version
+ expanded_cache_key << [Gitlab::VERSION, Rails.version]
end
- expanded_cache_key.join(':')
+ expanded_cache_key.flatten.join(':').freeze
end
def expire(key)
diff --git a/lib/gitlab/kubernetes.rb b/lib/gitlab/kubernetes.rb
index 1103a4eed1d..22bd00751bc 100644
--- a/lib/gitlab/kubernetes.rb
+++ b/lib/gitlab/kubernetes.rb
@@ -43,6 +43,14 @@ module Gitlab
})
end
+ def filter_by_legacy_label(items, app, env)
+ legacy_items = filter_by_label(items, { app: env })
+
+ non_legacy_items = filter_by_project_environment(legacy_items, app, env)
+
+ legacy_items - non_legacy_items
+ end
+
# Converts a pod (as returned by the kubernetes API) into a terminal
def terminals_for_pod(api_url, namespace, pod)
metadata = pod.fetch("metadata", {})
diff --git a/lib/gitlab/lets_encrypt.rb b/lib/gitlab/lets_encrypt.rb
new file mode 100644
index 00000000000..cdf24f24647
--- /dev/null
+++ b/lib/gitlab/lets_encrypt.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module LetsEncrypt
+ def self.enabled?(pages_domain = nil)
+ return false unless Gitlab::CurrentSettings.lets_encrypt_terms_of_service_accepted
+
+ return false unless Feature.enabled?(:pages_auto_ssl)
+
+ # If no domain is passed, just check whether we're enabled globally
+ return true unless pages_domain
+
+ !!pages_domain.project && Feature.enabled?(:pages_auto_ssl_for_project, pages_domain.project)
+ end
+ end
+end
diff --git a/lib/gitlab/lets_encrypt/client.rb b/lib/gitlab/lets_encrypt/client.rb
index 66aea137012..ad2921ed555 100644
--- a/lib/gitlab/lets_encrypt/client.rb
+++ b/lib/gitlab/lets_encrypt/client.rb
@@ -34,14 +34,6 @@ module Gitlab
acme_client.terms_of_service
end
- def enabled?
- return false unless Feature.enabled?(:pages_auto_ssl)
-
- return false unless private_key
-
- Gitlab::CurrentSettings.lets_encrypt_terms_of_service_accepted
- end
-
private
def acme_client
@@ -65,7 +57,7 @@ module Gitlab
end
def ensure_account
- raise 'Acme integration is disabled' unless enabled?
+ raise 'Acme integration is disabled' unless ::Gitlab::LetsEncrypt.enabled?
@acme_account ||= acme_client.new_account(contact: contact, terms_of_service_agreed: true)
end
diff --git a/lib/gitlab/search/found_blob.rb b/lib/gitlab/search/found_blob.rb
index a62ab1521a7..01ce90c85f7 100644
--- a/lib/gitlab/search/found_blob.rb
+++ b/lib/gitlab/search/found_blob.rb
@@ -93,7 +93,7 @@ module Gitlab
data = {
id: blob.id,
binary_filename: blob.path,
- binary_basename: File.basename(blob.path, File.extname(blob.path)),
+ binary_basename: path_without_extension(blob.path),
ref: ref,
startline: 1,
binary_data: blob.data,
@@ -111,6 +111,10 @@ module Gitlab
content_match.match(FILENAME_REGEXP) { |matches| matches[:filename] }
end
+ def path_without_extension(path)
+ Pathname.new(path).sub_ext('').to_s
+ end
+
def parsed_content
strong_memoize(:parsed_content) do
if content_match
@@ -137,8 +141,7 @@ module Gitlab
filename = matches[:filename]
startline = matches[:startline]
startline = startline.to_i - index
- extname = Regexp.escape(File.extname(filename))
- basename = filename.sub(/#{extname}$/, '')
+ basename = path_without_extension(filename)
end
data << line.sub(prefix.to_s, '')
diff --git a/lib/gitlab/time_tracking_formatter.rb b/lib/gitlab/time_tracking_formatter.rb
index cc206010e74..302da91328a 100644
--- a/lib/gitlab/time_tracking_formatter.rb
+++ b/lib/gitlab/time_tracking_formatter.rb
@@ -6,7 +6,7 @@ module Gitlab
def parse(string)
with_custom_config do
- string.sub!(/\A-/, '')
+ string = string.sub(/\A-/, '')
seconds = ChronicDuration.parse(string, default_unit: 'hours') rescue nil
seconds *= -1 if seconds && Regexp.last_match
@@ -16,10 +16,12 @@ module Gitlab
def output(seconds)
with_custom_config do
- ChronicDuration.output(seconds, format: :short, limit_to_hours: false, weeks: true) rescue nil
+ ChronicDuration.output(seconds, format: :short, limit_to_hours: limit_to_hours_setting, weeks: true) rescue nil
end
end
+ private
+
def with_custom_config
# We may want to configure it through project settings in a future version.
ChronicDuration.hours_per_day = 8
@@ -32,5 +34,9 @@ module Gitlab
result
end
+
+ def limit_to_hours_setting
+ Gitlab::CurrentSettings.time_tracking_limit_to_hours
+ end
end
end
diff --git a/lib/system_check/ldap_check.rb b/lib/system_check/ldap_check.rb
index 619fb3cccb8..938026424ed 100644
--- a/lib/system_check/ldap_check.rb
+++ b/lib/system_check/ldap_check.rb
@@ -33,8 +33,13 @@ module SystemCheck
$stdout.puts "LDAP users with access to your GitLab server (only showing the first #{limit} results)"
users = adapter.users(adapter.config.uid, '*', limit)
- users.each do |user|
- $stdout.puts "\tDN: #{user.dn}\t #{adapter.config.uid}: #{user.uid}"
+
+ if should_sanitize?
+ $stdout.puts "\tUser output sanitized. Found #{users.length} users of #{limit} limit."
+ else
+ users.each do |user|
+ $stdout.puts "\tDN: #{user.dn}\t #{adapter.config.uid}: #{user.uid}"
+ end
end
end
rescue Net::LDAP::ConnectionRefusedError, Errno::ECONNREFUSED => e
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 8f010b2184c..fd6d3ed624c 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -16,6 +16,9 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n"
+msgid " (from %{timeoutSource})"
+msgstr ""
+
msgid " Please sign in."
msgstr ""
@@ -2061,6 +2064,9 @@ msgstr ""
msgid "Clear search input"
msgstr ""
+msgid "Clear templates search input"
+msgstr ""
+
msgid "Click any <strong>project name</strong> in the project list below to navigate to the project milestone."
msgstr ""
@@ -2786,9 +2792,15 @@ msgstr ""
msgid "Configure Let's Encrypt"
msgstr ""
+msgid "Configure Prometheus"
+msgstr ""
+
msgid "Configure automatic git checks and housekeeping on repositories."
msgstr ""
+msgid "Configure existing installation"
+msgstr ""
+
msgid "Configure limits for web and API requests."
msgstr ""
@@ -2849,10 +2861,13 @@ msgstr ""
msgid "ContainerRegistry|Once you log in, you&rsquo;re free to create and upload a container image using the common %{build} and %{push} commands"
msgstr ""
-msgid "ContainerRegistry|Remove repository"
+msgid "ContainerRegistry|Remove image"
+msgstr ""
+
+msgid "ContainerRegistry|Remove image and tags"
msgstr ""
-msgid "ContainerRegistry|Remove tag"
+msgid "ContainerRegistry|Remove repository"
msgstr ""
msgid "ContainerRegistry|Size"
@@ -2870,6 +2885,12 @@ msgstr ""
msgid "ContainerRegistry|With the Docker Container Registry integrated into GitLab, every project can have its own space to store its Docker images."
msgstr ""
+msgid "ContainerRegistry|You are about to delete the image <b>%{title}</b>. This will delete the image and all tags pointing to this image."
+msgstr ""
+
+msgid "ContainerRegistry|You are about to remove repository <b>%{title}</b>. Once you confirm, this repository will be permanently deleted."
+msgstr ""
+
msgid "ContainerRegistry|You can also use a %{deploy_token} for read-only access to the registry images."
msgstr ""
@@ -3047,6 +3068,12 @@ msgstr ""
msgid "Create commit"
msgstr ""
+msgid "Create confidential merge request"
+msgstr ""
+
+msgid "Create confidential merge request and branch"
+msgstr ""
+
msgid "Create directory"
msgstr ""
@@ -3128,6 +3155,9 @@ msgstr ""
msgid "Creates branch '%{branch_name}' and a merge request to resolve this issue"
msgstr ""
+msgid "Creating graphs uses the data from the Prometheus server. If this takes a long time, ensure that data is available."
+msgstr ""
+
msgid "Cron Timezone"
msgstr ""
@@ -4638,6 +4668,9 @@ msgstr ""
msgid "Get started with error tracking"
msgstr ""
+msgid "Get started with performance monitoring"
+msgstr ""
+
msgid "Getting started with releases"
msgstr ""
@@ -5315,6 +5348,9 @@ msgstr ""
msgid "Install a soft token authenticator like %{free_otp_link} or Google Authenticator from your application repository and scan this QR code. More information is available in the %{help_link_start}documentation%{help_link_end}."
msgstr ""
+msgid "Install on clusters"
+msgstr ""
+
msgid "Installed"
msgstr ""
@@ -5821,6 +5857,9 @@ msgstr ""
msgid "Let's Encrypt is a free, automated, and open certificate authority (CA) that gives digital certificates in order to enable HTTPS (SSL/TLS) for websites. Learn more about Let's Encrypt configuration by following the %{docs_link_start}documentation on GitLab Pages%{docs_link_end}."
msgstr ""
+msgid "Limit display of time tracking units to hours."
+msgstr ""
+
msgid "Limited to showing %d event at most"
msgid_plural "Limited to showing %d events at most"
msgstr[0] ""
@@ -6566,6 +6605,9 @@ msgstr ""
msgid "No contributions were found"
msgstr ""
+msgid "No data found"
+msgstr ""
+
msgid "No details available"
msgstr ""
@@ -6629,6 +6671,9 @@ msgstr ""
msgid "No schedules"
msgstr ""
+msgid "No template"
+msgstr ""
+
msgid "No, directly import the existing email addresses and usernames."
msgstr ""
@@ -6934,13 +6979,13 @@ msgstr ""
msgid "Pagination|Last »"
msgstr ""
-msgid "Pagination|Next"
+msgid "Pagination|Next ›"
msgstr ""
-msgid "Pagination|Prev"
+msgid "Pagination|« First"
msgstr ""
-msgid "Pagination|« First"
+msgid "Pagination|‹ Prev"
msgstr ""
msgid "Parameter"
@@ -7327,6 +7372,9 @@ msgstr ""
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr ""
+msgid "Pre-release"
+msgstr ""
+
msgid "Preferences"
msgstr ""
@@ -8050,6 +8098,9 @@ msgstr ""
msgid "ProjectsDropdown|This feature requires browser localStorage support"
msgstr ""
+msgid "Prometheus server"
+msgstr ""
+
msgid "PrometheusService|%{exporters} with %{metrics} were found"
msgstr ""
@@ -8520,6 +8571,9 @@ msgstr ""
msgid "Reset runners registration token"
msgstr ""
+msgid "Reset template"
+msgstr ""
+
msgid "Resolve all discussions in new issue"
msgstr ""
@@ -9163,6 +9217,9 @@ msgid_plural "Showing %d events"
msgstr[0] ""
msgstr[1] ""
+msgid "Showing last %{size} of log -"
+msgstr ""
+
msgid "Side-by-side"
msgstr ""
@@ -9568,6 +9625,9 @@ msgstr ""
msgid "Status:"
msgstr ""
+msgid "Stay updated about the performance and health of your environment by configuring Prometheus to monitor your deployments."
+msgstr ""
+
msgid "Stop environment"
msgstr ""
@@ -9942,9 +10002,6 @@ msgstr ""
msgid "The X509 Certificate to use when mutual TLS is required to communicate with the external authorization service. If left blank, the server certificate is still validated when accessing over HTTPS."
msgstr ""
-msgid "The certificate will be shown here once it has been obtained from Let's Encrypt. This process may take up to an hour to complete."
-msgstr ""
-
msgid "The character highlighter helps you keep the subject line to %{titleLength} characters and wrap the body at %{bodyLength} so they are readable in git."
msgstr ""
@@ -10278,9 +10335,6 @@ msgstr ""
msgid "This branch has changed since you started editing. Would you like to create a new branch?"
msgstr ""
-msgid "This certificate is automatically managed by Let's Encrypt"
-msgstr ""
-
msgid "This commit is part of merge request %{link_to_merge_request}. Comments created here will be created in the context of that merge request."
msgstr ""
@@ -10485,6 +10539,9 @@ msgstr ""
msgid "Thursday"
msgstr ""
+msgid "Time"
+msgstr ""
+
msgid "Time based: Yes"
msgstr ""
@@ -10930,6 +10987,9 @@ msgstr ""
msgid "U2F only works with HTTPS-enabled websites. Contact your administrator for more details."
msgstr ""
+msgid "Unable to connect to Prometheus server"
+msgstr ""
+
msgid "Unable to connect to server: %{error}"
msgstr ""
@@ -11335,6 +11395,9 @@ msgstr ""
msgid "View details: %{details_url}"
msgstr ""
+msgid "View documentation"
+msgstr ""
+
msgid "View file @ "
msgstr ""
@@ -11410,6 +11473,9 @@ msgstr ""
msgid "Wait for the source to load to copy it to the clipboard"
msgstr ""
+msgid "Waiting for performance data"
+msgstr ""
+
msgid "Want to see the data? Please ask an administrator for access."
msgstr ""
@@ -11667,6 +11733,9 @@ msgstr ""
msgid "You are attempting to update a file that has changed since you started editing it."
msgstr ""
+msgid "You are connected to the Prometheus server, but there is currently no data to display."
+msgstr ""
+
msgid "You are going to remove %{group_name}, this will also remove all of its subgroups and projects. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
msgstr ""
diff --git a/package.json b/package.json
index 38b07610296..577967d23b9 100644
--- a/package.json
+++ b/package.json
@@ -46,7 +46,7 @@
"apollo-upload-client": "^10.0.0",
"at.js": "^1.5.4",
"autosize": "^4.0.0",
- "axios": "^0.17.1",
+ "axios": "^0.19.0",
"babel-loader": "^8.0.5",
"bootstrap": "4.3.1",
"brace-expansion": "^1.1.8",
@@ -87,7 +87,7 @@
"imports-loader": "^0.8.0",
"jed": "^1.1.1",
"jest-transform-graphql": "^2.1.0",
- "jquery": "^3.2.1",
+ "jquery": "^3.4.1",
"jquery-ujs": "1.2.2",
"jquery.caret": "^0.3.1",
"jquery.waitforimages": "^2.2.0",
@@ -191,7 +191,7 @@
"nodemon": "^1.18.9",
"pixelmatch": "^4.0.2",
"postcss": "^7.0.14",
- "prettier": "1.16.4",
+ "prettier": "1.18.2",
"stylelint": "^9.10.1",
"stylelint-config-recommended": "^2.1.0",
"stylelint-scss": "^3.5.4",
diff --git a/qa/qa/page/project/pipeline/index.rb b/qa/qa/page/project/pipeline/index.rb
index 68850d989b1..fae7818f871 100644
--- a/qa/qa/page/project/pipeline/index.rb
+++ b/qa/qa/page/project/pipeline/index.rb
@@ -4,7 +4,7 @@ module QA::Page
module Project::Pipeline
class Index < QA::Page::Base
view 'app/assets/javascripts/pipelines/components/pipeline_url.vue' do
- element :pipeline_link, 'class="js-pipeline-url-link"' # rubocop:disable QA/ElementWithPattern
+ element :pipeline_link, 'class="js-pipeline-url-link' # rubocop:disable QA/ElementWithPattern
end
def click_on_latest_pipeline
diff --git a/spec/controllers/dashboard/todos_controller_spec.rb b/spec/controllers/dashboard/todos_controller_spec.rb
index 6243ddc03c0..9a3fbfaac51 100644
--- a/spec/controllers/dashboard/todos_controller_spec.rb
+++ b/spec/controllers/dashboard/todos_controller_spec.rb
@@ -44,6 +44,34 @@ describe Dashboard::TodosController do
end
end
+ context "with render_views" do
+ render_views
+
+ it 'avoids N+1 queries', :request_store do
+ merge_request = create(:merge_request, source_project: project)
+ create(:todo, project: project, author: author, user: user, target: merge_request)
+ create(:issue, project: project, assignees: [user])
+
+ group = create(:group)
+ group.add_owner(user)
+
+ get :index
+
+ control = ActiveRecord::QueryRecorder.new { get :index }
+
+ create(:issue, project: project, assignees: [user])
+ group_2 = create(:group)
+ group_2.add_owner(user)
+ project_2 = create(:project)
+ project_2.add_developer(user)
+ merge_request_2 = create(:merge_request, source_project: project_2)
+ create(:todo, project: project, author: author, user: user, target: merge_request_2)
+
+ expect { get :index }.not_to exceed_query_limit(control)
+ expect(response.status).to eq(200)
+ end
+ end
+
context 'group authorization' do
it 'renders 404 when user does not have read access on given group' do
unauthorized_group = create(:group, :private)
diff --git a/spec/controllers/projects/clusters_controller_spec.rb b/spec/controllers/projects/clusters_controller_spec.rb
index fa49438287f..35cbab57037 100644
--- a/spec/controllers/projects/clusters_controller_spec.rb
+++ b/spec/controllers/projects/clusters_controller_spec.rb
@@ -340,7 +340,6 @@ describe Projects::ClustersController do
describe 'security' do
before do
- allow(ClusterConfigureWorker).to receive(:perform_async)
stub_kubeclient_get_namespace('https://kubernetes.example.com', namespace: 'my-namespace')
end
@@ -438,7 +437,6 @@ describe Projects::ClustersController do
end
before do
- allow(ClusterConfigureWorker).to receive(:perform_async)
stub_kubeclient_get_namespace('https://kubernetes.example.com', namespace: 'my-namespace')
end
diff --git a/spec/controllers/projects/issues_controller_spec.rb b/spec/controllers/projects/issues_controller_spec.rb
index 32607fc5f56..f82e3c8c7dc 100644
--- a/spec/controllers/projects/issues_controller_spec.rb
+++ b/spec/controllers/projects/issues_controller_spec.rb
@@ -320,6 +320,90 @@ describe Projects::IssuesController do
end
end
+ describe 'PUT #reorder' do
+ let(:group) { create(:group, projects: [project]) }
+ let!(:issue1) { create(:issue, project: project, relative_position: 10) }
+ let!(:issue2) { create(:issue, project: project, relative_position: 20) }
+ let!(:issue3) { create(:issue, project: project, relative_position: 30) }
+
+ before do
+ sign_in(user)
+ end
+
+ context 'when user has access' do
+ before do
+ project.add_developer(user)
+ end
+
+ context 'with valid params' do
+ it 'reorders issues and returns a successful 200 response' do
+ reorder_issue(issue1,
+ move_after_id: issue2.id,
+ move_before_id: issue3.id,
+ group_full_path: group.full_path)
+
+ [issue1, issue2, issue3].map(&:reload)
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(issue1.relative_position)
+ .to be_between(issue2.relative_position, issue3.relative_position)
+ end
+ end
+
+ context 'with invalid params' do
+ it 'returns a unprocessable entity 422 response for invalid move ids' do
+ reorder_issue(issue1, move_after_id: 99, move_before_id: 999)
+
+ expect(response).to have_gitlab_http_status(422)
+ end
+
+ it 'returns a not found 404 response for invalid issue id' do
+ reorder_issue(object_double(issue1, iid: 999),
+ move_after_id: issue2.id,
+ move_before_id: issue3.id)
+
+ expect(response).to have_gitlab_http_status(404)
+ end
+
+ it 'returns a unprocessable entity 422 response for issues not in group' do
+ another_group = create(:group)
+
+ reorder_issue(issue1,
+ move_after_id: issue2.id,
+ move_before_id: issue3.id,
+ group_full_path: another_group.full_path)
+
+ expect(response).to have_gitlab_http_status(422)
+ end
+ end
+ end
+
+ context 'with unauthorized user' do
+ before do
+ project.add_guest(user)
+ end
+
+ it 'responds with 404' do
+ reorder_issue(issue1, move_after_id: issue2.id, move_before_id: issue3.id)
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+
+ def reorder_issue(issue, move_after_id: nil, move_before_id: nil, group_full_path: nil)
+ put :reorder,
+ params: {
+ namespace_id: project.namespace.to_param,
+ project_id: project,
+ id: issue.iid,
+ move_after_id: move_after_id,
+ move_before_id: move_before_id,
+ group_full_path: group_full_path
+ },
+ format: :json
+ end
+ end
+
describe 'PUT #update' do
subject do
put :update,
diff --git a/spec/controllers/projects/merge_requests_controller_spec.rb b/spec/controllers/projects/merge_requests_controller_spec.rb
index 34cbf0c8723..0eca663a683 100644
--- a/spec/controllers/projects/merge_requests_controller_spec.rb
+++ b/spec/controllers/projects/merge_requests_controller_spec.rb
@@ -1001,6 +1001,8 @@ describe Projects::MergeRequestsController do
before do
project.add_developer(user)
sign_in(user)
+
+ expect(::Gitlab::GitalyClient).to receive(:allow_ref_name_caching).and_call_original
end
it 'returns 200' do
diff --git a/spec/controllers/projects/pages_domains_controller_spec.rb b/spec/controllers/projects/pages_domains_controller_spec.rb
index ff3afd51cd8..032f4f1418f 100644
--- a/spec/controllers/projects/pages_domains_controller_spec.rb
+++ b/spec/controllers/projects/pages_domains_controller_spec.rb
@@ -15,7 +15,10 @@ describe Projects::PagesDomainsController do
end
let(:pages_domain_params) do
- build(:pages_domain, domain: 'my.otherdomain.com').slice(:key, :certificate, :domain)
+ attributes_for(:pages_domain, domain: 'my.otherdomain.com').slice(:key, :certificate, :domain).tap do |params|
+ params[:user_provided_key] = params.delete(:key)
+ params[:user_provided_certificate] = params.delete(:certificate)
+ end
end
before do
@@ -84,48 +87,59 @@ describe Projects::PagesDomainsController do
controller.instance_variable_set(:@domain, pages_domain)
end
- let(:pages_domain_params) do
- attributes_for(:pages_domain).slice(:key, :certificate)
- end
-
let(:params) do
request_params.merge(id: pages_domain.domain, pages_domain: pages_domain_params)
end
- it 'updates the domain' do
- expect(pages_domain)
- .to receive(:update)
- .with(ActionController::Parameters.new(pages_domain_params).permit!)
- .and_return(true)
+ context 'with valid params' do
+ let(:pages_domain_params) do
+ attributes_for(:pages_domain, :with_trusted_chain).slice(:key, :certificate).tap do |params|
+ params[:user_provided_key] = params.delete(:key)
+ params[:user_provided_certificate] = params.delete(:certificate)
+ end
+ end
+
+ it 'updates the domain' do
+ expect do
+ patch(:update, params: params)
+ end.to change { pages_domain.reload.certificate }.to(pages_domain_params[:user_provided_certificate])
+ end
+
+ it 'redirects to the project page' do
+ patch(:update, params: params)
- patch(:update, params: params)
+ expect(flash[:notice]).to eq 'Domain was updated'
+ expect(response).to redirect_to(project_pages_path(project))
+ end
end
- it 'redirects to the project page' do
- patch(:update, params: params)
+ context 'with key parameter' do
+ before do
+ pages_domain.update!(key: nil, certificate: nil, certificate_source: 'gitlab_provided')
+ end
- expect(flash[:notice]).to eq 'Domain was updated'
- expect(response).to redirect_to(project_pages_path(project))
+ it 'marks certificate as provided by user' do
+ expect do
+ patch(:update, params: params)
+ end.to change { pages_domain.reload.certificate_source }.from('gitlab_provided').to('user_provided')
+ end
end
context 'the domain is invalid' do
- it 'renders the edit action' do
- allow(pages_domain).to receive(:update).and_return(false)
+ let(:pages_domain_params) { { user_provided_certificate: 'blabla' } }
+ it 'renders the edit action' do
patch(:update, params: params)
expect(response).to render_template('edit')
end
end
- context 'the parameters include the domain' do
- it 'renders 400 Bad Request' do
- expect(pages_domain)
- .to receive(:update)
- .with(hash_not_including(:domain))
- .and_return(true)
-
- patch(:update, params: params.deep_merge(pages_domain: { domain: 'abc' }))
+ context 'when parameters include the domain' do
+ it 'does not update domain' do
+ expect do
+ patch(:update, params: params.deep_merge(pages_domain: { domain: 'abc' }))
+ end.not_to change { pages_domain.reload.domain }
end
end
end
diff --git a/spec/factories/pages_domains.rb b/spec/factories/pages_domains.rb
index db8384877b0..3e0baab04ce 100644
--- a/spec/factories/pages_domains.rb
+++ b/spec/factories/pages_domains.rb
@@ -180,5 +180,10 @@ Iy6oRpHaCF/2obZdIdgf9rlyz0fkqyHJc9GkioSoOhJZxEV2SgAkap8yS0sX2tJ9
ZDXgrA==
-----END CERTIFICATE-----'
end
+
+ trait :letsencrypt do
+ auto_ssl_enabled { true }
+ certificate_source { :gitlab_provided }
+ end
end
end
diff --git a/spec/features/admin/admin_users_spec.rb b/spec/features/admin/admin_users_spec.rb
index 29545779a34..dafec29dfcc 100644
--- a/spec/features/admin/admin_users_spec.rb
+++ b/spec/features/admin/admin_users_spec.rb
@@ -419,6 +419,32 @@ describe "Admin::Users" do
end
end
end
+
+ describe 'Email verification status' do
+ let!(:secondary_email) do
+ create :email, email: 'secondary@example.com', user: user
+ end
+
+ it 'displays the correct status for an unverified email address' do
+ user.update(confirmed_at: nil, unconfirmed_email: user.email)
+ visit admin_user_path(user)
+
+ expect(page).to have_content("#{user.email} Unverified")
+
+ expect(page).to have_content("#{secondary_email.email} Unverified")
+ end
+
+ it 'displays the correct status for a verified email address' do
+ visit admin_user_path(user)
+ expect(page).to have_content("#{user.email} Verified")
+
+ secondary_email.confirm
+ expect(secondary_email.confirmed?).to be_truthy
+
+ visit admin_user_path(user)
+ expect(page).to have_content("#{secondary_email.email} Verified")
+ end
+ end
end
describe "GET /admin/users/:id/edit" do
diff --git a/spec/features/boards/sidebar_spec.rb b/spec/features/boards/sidebar_spec.rb
index b1798c11361..6c9ae343e01 100644
--- a/spec/features/boards/sidebar_spec.rb
+++ b/spec/features/boards/sidebar_spec.rb
@@ -16,7 +16,9 @@ describe 'Issue Boards', :js do
let!(:issue2) { create(:labeled_issue, project: project, labels: [development, stretch], relative_position: 1) }
let(:board) { create(:board, project: project) }
let!(:list) { create(:list, board: board, label: development, position: 0) }
- let(:card) { find('.board:nth-child(2)').first('.board-card') }
+ let(:card) { find('.board:nth-child(2)').first('.board-card') }
+
+ let(:application_settings) { {} }
around do |example|
Timecop.freeze { example.run }
@@ -27,6 +29,8 @@ describe 'Issue Boards', :js do
sign_in(user)
+ stub_application_setting(application_settings)
+
visit project_board_path(project, board)
wait_for_requests
end
@@ -223,16 +227,24 @@ describe 'Issue Boards', :js do
end
context 'time tracking' do
+ let(:compare_meter_tooltip) { find('.time-tracking .time-tracking-content .compare-meter')['data-original-title'] }
+
before do
issue2.timelogs.create(time_spent: 14400, user: user)
- issue2.update!(time_estimate: 28800)
+ issue2.update!(time_estimate: 128800)
+
+ click_card(card)
end
it 'shows time tracking progress bar' do
- click_card(card)
+ expect(compare_meter_tooltip).to eq('Time remaining: 3d 7h 46m')
+ end
+
+ context 'when time_tracking_limit_to_hours is true' do
+ let(:application_settings) { { time_tracking_limit_to_hours: true } }
- page.within('.time-tracking') do
- expect(find('.time-tracking-content .compare-meter')['data-original-title']).to eq('Time remaining: 4h')
+ it 'shows time tracking progress bar' do
+ expect(compare_meter_tooltip).to eq('Time remaining: 31h 46m')
end
end
end
diff --git a/spec/features/container_registry_spec.rb b/spec/features/container_registry_spec.rb
index 6f9901815e1..21d97aba0c5 100644
--- a/spec/features/container_registry_spec.rb
+++ b/spec/features/container_registry_spec.rb
@@ -42,6 +42,8 @@ describe "Container Registry", :js do
.to receive(:delete_tags!).and_return(true)
click_on(class: 'js-remove-repo')
+ expect(find('.modal .modal-title')).to have_content 'Remove repository'
+ find('.modal .modal-footer .btn-danger').click
end
it 'user removes a specific tag from container repository' do
@@ -54,6 +56,8 @@ describe "Container Registry", :js do
.to receive(:delete).and_return(true)
click_on(class: 'js-delete-registry')
+ expect(find('.modal .modal-title')).to have_content 'Remove image'
+ find('.modal .modal-footer .btn-danger').click
end
end
diff --git a/spec/features/issues/user_creates_branch_and_merge_request_spec.rb b/spec/features/issues/user_creates_branch_and_merge_request_spec.rb
index b69fba0db00..f9103d83ba0 100644
--- a/spec/features/issues/user_creates_branch_and_merge_request_spec.rb
+++ b/spec/features/issues/user_creates_branch_and_merge_request_spec.rb
@@ -3,7 +3,7 @@ require 'rails_helper'
describe 'User creates branch and merge request on issue page', :js do
let(:membership_level) { :developer }
let(:user) { create(:user) }
- let!(:project) { create(:project, :repository) }
+ let!(:project) { create(:project, :repository, :public) }
let(:issue) { create(:issue, project: project, title: 'Cherry-Coloured Funk') }
context 'when signed out' do
@@ -163,10 +163,21 @@ describe 'User creates branch and merge request on issue page', :js do
let(:issue) { create(:issue, :confidential, project: project) }
it 'disables the create branch button' do
+ stub_feature_flags(create_confidential_merge_request: false)
+
visit project_issue_path(project, issue)
expect(page).not_to have_css('.create-mr-dropdown-wrap')
end
+
+ it 'enables the create branch button when feature flag is enabled' do
+ stub_feature_flags(create_confidential_merge_request: true)
+
+ visit project_issue_path(project, issue)
+
+ expect(page).to have_css('.create-mr-dropdown-wrap')
+ expect(page).to have_button('Create confidential merge request')
+ end
end
context 'when related branch exists' do
diff --git a/spec/features/projects/clusters/gcp_spec.rb b/spec/features/projects/clusters/gcp_spec.rb
index e4a3a1a8c92..974e0f84681 100644
--- a/spec/features/projects/clusters/gcp_spec.rb
+++ b/spec/features/projects/clusters/gcp_spec.rb
@@ -118,7 +118,6 @@ describe 'Gcp Cluster', :js do
context 'when user changes cluster parameters' do
before do
- 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/pages_lets_encrypt_spec.rb b/spec/features/projects/pages_lets_encrypt_spec.rb
index baa217cbe58..a5f8702302c 100644
--- a/spec/features/projects/pages_lets_encrypt_spec.rb
+++ b/spec/features/projects/pages_lets_encrypt_spec.rb
@@ -2,124 +2,119 @@
require 'spec_helper'
describe "Pages with Let's Encrypt", :https_pages_enabled do
+ include LetsEncryptHelpers
+
let(:project) { create(:project) }
let(:user) { create(:user) }
let(:role) { :maintainer }
- let(:certificate_pem) do
- <<~PEM
- -----BEGIN CERTIFICATE-----
- MIICGzCCAYSgAwIBAgIBATANBgkqhkiG9w0BAQUFADAbMRkwFwYDVQQDExB0ZXN0
- LWNlcnRpZmljYXRlMB4XDTE2MDIxMjE0MzIwMFoXDTIwMDQxMjE0MzIwMFowGzEZ
- MBcGA1UEAxMQdGVzdC1jZXJ0aWZpY2F0ZTCBnzANBgkqhkiG9w0BAQEFAAOBjQAw
- gYkCgYEApL4J9L0ZxFJ1hI1LPIflAlAGvm6ZEvoT4qKU5Xf2JgU7/2geNR1qlNFa
- SvCc08Knupp5yTgmvyK/Xi09U0N82vvp4Zvr/diSc4A/RA6Mta6egLySNT438kdT
- nY2tR5feoTLwQpX0t4IMlwGQGT5h6Of2fKmDxzuwuyffcIHqLdsCAwEAAaNvMG0w
- DAYDVR0TAQH/BAIwADAdBgNVHQ4EFgQUxl9WSxBprB0z0ibJs3rXEk0+95AwCwYD
- VR0PBAQDAgXgMBEGCWCGSAGG+EIBAQQEAwIGQDAeBglghkgBhvhCAQ0EERYPeGNh
- IGNlcnRpZmljYXRlMA0GCSqGSIb3DQEBBQUAA4GBAGC4T8SlFHK0yPSa+idGLQFQ
- joZp2JHYvNlTPkRJ/J4TcXxBTJmArcQgTIuNoBtC+0A/SwdK4MfTCUY4vNWNdese
- 5A4K65Nb7Oh1AdQieTBHNXXCdyFsva9/ScfQGEl7p55a52jOPs0StPd7g64uvjlg
- YHi2yesCrOvVXt+lgPTd
- -----END CERTIFICATE-----
- PEM
- end
+ let(:certificate_pem) { attributes_for(:pages_domain)[:certificate] }
- let(:certificate_key) do
- <<~KEY
- -----BEGIN PRIVATE KEY-----
- MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAKS+CfS9GcRSdYSN
- SzyH5QJQBr5umRL6E+KilOV39iYFO/9oHjUdapTRWkrwnNPCp7qaeck4Jr8iv14t
- PVNDfNr76eGb6/3YknOAP0QOjLWunoC8kjU+N/JHU52NrUeX3qEy8EKV9LeCDJcB
- kBk+Yejn9nypg8c7sLsn33CB6i3bAgMBAAECgYA2D26w80T7WZvazYr86BNMePpd
- j2mIAqx32KZHzt/lhh40J/SRtX9+Kl0Y7nBoRR5Ja9u/HkAIxNxLiUjwg9r6cpg/
- uITEF5nMt7lAk391BuI+7VOZZGbJDsq2ulPd6lO+C8Kq/PI/e4kXcIjeH6KwQsuR
- 5vrXfBZ3sQfflaiN4QJBANBt8JY2LIGQF8o89qwUpRL5vbnKQ4IzZ5+TOl4RLR7O
- AQpJ81tGuINghO7aunctb6rrcKJrxmEH1whzComybrMCQQDKV49nOBudRBAIgG4K
- EnLzsRKISUHMZSJiYTYnablof8cKw1JaQduw7zgrUlLwnroSaAGX88+Jw1f5n2Lh
- Vlg5AkBDdUGnrDLtYBCDEQYZHblrkc7ZAeCllDOWjxUV+uMqlCv8A4Ey6omvY57C
- m6I8DkWVAQx8VPtozhvHjUw80rZHAkB55HWHAM3h13axKG0htCt7klhPsZHpx6MH
- EPjGlXIT+aW2XiPmK3ZlCDcWIenE+lmtbOpI159Wpk8BGXs/s/xBAkEAlAY3ymgx
- 63BDJEwvOb2IaP8lDDxNsXx9XJNVvQbv5n15vNsLHbjslHfAhAbxnLQ1fLhUPqSi
- nNp/xedE1YxutQ==
- -----END PRIVATE KEY-----
- KEY
- end
+ let(:certificate_key) { attributes_for(:pages_domain)[:key] }
before do
allow(Gitlab.config.pages).to receive(:enabled).and_return(true)
+ stub_lets_encrypt_settings
+
project.add_role(user, role)
sign_in(user)
project.namespace.update(owner: user)
allow_any_instance_of(Project).to receive(:pages_deployed?) { true }
end
- context 'when the page_auto_ssl feature flag is enabled' do
- before do
- stub_feature_flags(pages_auto_ssl: true)
+ context 'when the auto SSL management is initially disabled' do
+ let(:domain) do
+ create(:pages_domain, auto_ssl_enabled: false, project: project)
end
- context 'when the auto SSL management is initially disabled' do
- let(:domain) do
- create(:pages_domain, auto_ssl_enabled: false, project: project)
- end
+ it 'enables auto SSL and dynamically updates the form accordingly', :js do
+ visit edit_project_pages_domain_path(project, domain)
- it 'enables auto SSL and dynamically updates the form accordingly', :js do
- visit edit_project_pages_domain_path(project, domain)
+ expect(domain.auto_ssl_enabled).to eq false
- expect(domain.auto_ssl_enabled).to eq false
+ expect(find("#pages_domain_auto_ssl_enabled", visible: false).value).to eq 'false'
+ expect(page).to have_field 'Certificate (PEM)', type: 'textarea'
+ expect(page).to have_field 'Key (PEM)', type: 'textarea'
- expect(find("#pages_domain_auto_ssl_enabled", visible: false).value).to eq 'false'
- expect(page).to have_field 'Certificate (PEM)', type: 'textarea'
- expect(page).to have_field 'Key (PEM)', type: 'textarea'
+ find('.js-auto-ssl-toggle-container .project-feature-toggle').click
- find('.js-auto-ssl-toggle-container .project-feature-toggle').click
+ expect(find("#pages_domain_auto_ssl_enabled", visible: false).value).to eq 'true'
+ expect(page).not_to have_field 'Certificate (PEM)', type: 'textarea'
+ expect(page).not_to have_field 'Key (PEM)', type: 'textarea'
- expect(find("#pages_domain_auto_ssl_enabled", visible: false).value).to eq 'true'
- expect(page).not_to have_field 'Certificate (PEM)', type: 'textarea'
- expect(page).not_to have_field 'Key (PEM)', type: 'textarea'
- expect(page).to have_content "The certificate will be shown here once it has been obtained from Let's Encrypt. This process may take up to an hour to complete."
+ click_on 'Save Changes'
- click_on 'Save Changes'
+ expect(domain.reload.auto_ssl_enabled).to eq true
+ end
+ end
- expect(domain.reload.auto_ssl_enabled).to eq true
- end
+ context 'when the auto SSL management is initially enabled' do
+ let(:domain) do
+ create(:pages_domain, :letsencrypt, auto_ssl_enabled: true, project: project)
end
- context 'when the auto SSL management is initially enabled' do
- let(:domain) do
- create(:pages_domain, auto_ssl_enabled: true, project: project)
- end
+ it 'disables auto SSL and dynamically updates the form accordingly', :js do
+ visit edit_project_pages_domain_path(project, domain)
- it 'disables auto SSL and dynamically updates the form accordingly', :js do
- visit edit_project_pages_domain_path(project, domain)
+ expect(find("#pages_domain_auto_ssl_enabled", visible: false).value).to eq 'true'
+ expect(page).not_to have_field 'Certificate (PEM)', type: 'textarea'
+ expect(page).not_to have_field 'Key (PEM)', type: 'textarea'
- expect(find("#pages_domain_auto_ssl_enabled", visible: false).value).to eq 'true'
- expect(page).to have_field 'Certificate (PEM)', type: 'textarea', disabled: true
- expect(page).not_to have_field 'Key (PEM)', type: 'textarea'
+ find('.js-auto-ssl-toggle-container .project-feature-toggle').click
- find('.js-auto-ssl-toggle-container .project-feature-toggle').click
+ expect(find("#pages_domain_auto_ssl_enabled", visible: false).value).to eq 'false'
+ expect(page).to have_field 'Certificate (PEM)', type: 'textarea'
+ expect(page).to have_field 'Key (PEM)', type: 'textarea'
- expect(find("#pages_domain_auto_ssl_enabled", visible: false).value).to eq 'false'
- expect(page).to have_field 'Certificate (PEM)', type: 'textarea'
- expect(page).to have_field 'Key (PEM)', type: 'textarea'
+ fill_in 'Certificate (PEM)', with: certificate_pem
+ fill_in 'Key (PEM)', with: certificate_key
- fill_in 'Certificate (PEM)', with: certificate_pem
- fill_in 'Key (PEM)', with: certificate_key
+ click_on 'Save Changes'
- click_on 'Save Changes'
+ expect(domain.reload.auto_ssl_enabled).to eq false
+ end
+ end
- expect(domain.reload.auto_ssl_enabled).to eq false
+ shared_examples 'user sees private keys only for user provided certificate' do
+ before do
+ visit edit_project_pages_domain_path(project, domain)
+ end
+
+ shared_examples 'user do not see private key' do
+ it 'user do not see private key' do
+ expect(find_field('Key (PEM)', visible: :all, disabled: :all).value).to be_blank
+ end
+ end
+
+ context 'when auto_ssl is enabled for domain' do
+ let(:domain) { create(:pages_domain, :letsencrypt, project: project, auto_ssl_enabled: true) }
+
+ include_examples 'user do not see private key'
+ end
+
+ context 'when auto_ssl is disabled for domain' do
+ let(:domain) { create(:pages_domain, :letsencrypt, project: project) }
+
+ include_examples 'user do not see private key'
+ end
+
+ context 'when certificate is provided by user' do
+ let(:domain) { create(:pages_domain, project: project) }
+
+ it 'user sees private key' do
+ expect(find_field('Key (PEM)').value).not_to be_blank
end
end
end
- context 'when the page_auto_ssl feature flag is disabled' do
+ include_examples 'user sees private keys only for user provided certificate'
+
+ context 'when letsencrypt is disabled' do
let(:domain) do
create(:pages_domain, auto_ssl_enabled: false, project: project)
end
before do
- stub_feature_flags(pages_auto_ssl: false)
+ stub_application_setting(lets_encrypt_terms_of_service_accepted: false)
visit edit_project_pages_domain_path(project, domain)
end
@@ -127,5 +122,7 @@ describe "Pages with Let's Encrypt", :https_pages_enabled do
it "does not render the Let's Encrypt field", :js do
expect(page).not_to have_selector '.js-auto-ssl-toggle-container'
end
+
+ include_examples 'user sees private keys only for user provided certificate'
end
end
diff --git a/spec/features/projects/pages_spec.rb b/spec/features/projects/pages_spec.rb
index 9bb0ba81ef5..c4b3ddb2088 100644
--- a/spec/features/projects/pages_spec.rb
+++ b/spec/features/projects/pages_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-shared_examples 'pages domain editing' do
+shared_examples 'pages settings editing' do
let(:project) { create(:project) }
let(:user) { create(:user) }
let(:role) { :maintainer }
@@ -321,19 +321,15 @@ shared_examples 'pages domain editing' do
end
describe 'Pages' do
- context 'when pages_auto_ssl feature flag is disabled' do
- before do
- stub_feature_flags(pages_auto_ssl: false)
- end
+ include LetsEncryptHelpers
- include_examples 'pages domain editing'
- end
+ include_examples 'pages settings editing'
- context 'when pages_auto_ssl feature flag is enabled' do
+ context 'when letsencrypt support is enabled' do
before do
- stub_feature_flags(pages_auto_ssl: true)
+ stub_lets_encrypt_settings
end
- include_examples 'pages domain editing'
+ include_examples 'pages settings editing'
end
end
diff --git a/spec/features/projects/services/user_activates_jetbrains_teamcity_ci_spec.rb b/spec/features/projects/services/user_activates_jetbrains_teamcity_ci_spec.rb
index 28d83a8b961..c50fd93e4cb 100644
--- a/spec/features/projects/services/user_activates_jetbrains_teamcity_ci_spec.rb
+++ b/spec/features/projects/services/user_activates_jetbrains_teamcity_ci_spec.rb
@@ -15,6 +15,8 @@ describe 'User activates JetBrains TeamCity CI' do
it 'activates service' do
check('Active')
+ check('Push')
+ check('Merge request')
fill_in('Teamcity url', with: 'http://teamcity.example.com')
fill_in('Build type', with: 'GitlabTest_Build')
fill_in('Username', with: 'user')
diff --git a/spec/features/search/user_searches_for_wiki_pages_spec.rb b/spec/features/search/user_searches_for_wiki_pages_spec.rb
index 6d4facd0649..ee43755262e 100644
--- a/spec/features/search/user_searches_for_wiki_pages_spec.rb
+++ b/spec/features/search/user_searches_for_wiki_pages_spec.rb
@@ -3,7 +3,7 @@ require 'spec_helper'
describe 'User searches for wiki pages', :js do
let(:user) { create(:user) }
let(:project) { create(:project, :repository, :wiki_repo, namespace: user.namespace) }
- let!(:wiki_page) { create(:wiki_page, wiki: project.wiki, attrs: { title: 'test_wiki', content: 'Some Wiki content' }) }
+ let!(:wiki_page) { create(:wiki_page, wiki: project.wiki, attrs: { title: 'directory/title', content: 'Some Wiki content' }) }
before do
project.add_maintainer(user)
@@ -22,7 +22,7 @@ describe 'User searches for wiki pages', :js do
click_link(project.full_name)
end
- fill_in('dashboard_search', with: 'content')
+ fill_in('dashboard_search', with: search_term)
find('.btn-search').click
page.within('.search-filter') do
@@ -43,7 +43,7 @@ describe 'User searches for wiki pages', :js do
context 'when searching by title' do
it_behaves_like 'search wiki blobs' do
- let(:search_term) { 'test_wiki' }
+ let(:search_term) { 'title' }
end
end
end
diff --git a/spec/finders/autocomplete/acts_as_taggable_on/tags_finder_spec.rb b/spec/finders/autocomplete/acts_as_taggable_on/tags_finder_spec.rb
index 79d2f9cdb45..c4e6c9cc9f5 100644
--- a/spec/finders/autocomplete/acts_as_taggable_on/tags_finder_spec.rb
+++ b/spec/finders/autocomplete/acts_as_taggable_on/tags_finder_spec.rb
@@ -17,13 +17,13 @@ describe Autocomplete::ActsAsTaggableOn::TagsFinder do
context 'filter by search' do
context 'with an empty search term' do
- it 'returns an empty collection' do
- ActsAsTaggableOn::Tag.create!(name: 'tag1')
- ActsAsTaggableOn::Tag.create!(name: 'tag2')
+ it 'returns all tags' do
+ tag1 = ActsAsTaggableOn::Tag.create!(name: 'tag1')
+ tag2 = ActsAsTaggableOn::Tag.create!(name: 'tag2')
tags = described_class.new(params: { search: '' }).execute
- expect(tags).to be_empty
+ expect(tags).to match_array [tag1, tag2]
end
end
diff --git a/spec/frontend/branches/components/__snapshots__/divergence_graph_spec.js.snap b/spec/frontend/branches/components/__snapshots__/divergence_graph_spec.js.snap
new file mode 100644
index 00000000000..511c027dbc2
--- /dev/null
+++ b/spec/frontend/branches/components/__snapshots__/divergence_graph_spec.js.snap
@@ -0,0 +1,37 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`Branch divergence graph component renders ahead and behind count 1`] = `
+<div
+ class="divergence-graph px-2 d-none d-md-block"
+ title="10 commits behind master, 10 commits ahead"
+>
+ <graphbar-stub
+ count="10"
+ maxcommits="100"
+ position="left"
+ />
+
+ <div
+ class="graph-separator pull-left mt-1"
+ />
+
+ <graphbar-stub
+ count="10"
+ maxcommits="100"
+ position="right"
+ />
+</div>
+`;
+
+exports[`Branch divergence graph component renders distance count 1`] = `
+<div
+ class="divergence-graph px-2 d-none d-md-block"
+ title="More than 900 commits different with master"
+>
+ <graphbar-stub
+ count="900"
+ maxcommits="100"
+ position="full"
+ />
+</div>
+`;
diff --git a/spec/frontend/branches/components/divergence_graph_spec.js b/spec/frontend/branches/components/divergence_graph_spec.js
new file mode 100644
index 00000000000..b54b2ceb233
--- /dev/null
+++ b/spec/frontend/branches/components/divergence_graph_spec.js
@@ -0,0 +1,67 @@
+import { shallowMount } from '@vue/test-utils';
+import DivergenceGraph from '~/branches/components/divergence_graph.vue';
+import GraphBar from '~/branches/components/graph_bar.vue';
+
+let vm;
+
+function factory(propsData = {}) {
+ vm = shallowMount(DivergenceGraph, { propsData });
+}
+
+describe('Branch divergence graph component', () => {
+ afterEach(() => {
+ vm.destroy();
+ });
+
+ it('renders ahead and behind count', () => {
+ factory({
+ defaultBranch: 'master',
+ aheadCount: 10,
+ behindCount: 10,
+ maxCommits: 100,
+ });
+
+ expect(vm.findAll(GraphBar).length).toBe(2);
+ expect(vm.element).toMatchSnapshot();
+ });
+
+ it('sets title for ahead and behind count', () => {
+ factory({
+ defaultBranch: 'master',
+ aheadCount: 10,
+ behindCount: 10,
+ maxCommits: 100,
+ });
+
+ expect(vm.attributes('title')).toBe('10 commits behind master, 10 commits ahead');
+ });
+
+ it('renders distance count', () => {
+ factory({
+ defaultBranch: 'master',
+ aheadCount: 0,
+ behindCount: 0,
+ distance: 900,
+ maxCommits: 100,
+ });
+
+ expect(vm.findAll(GraphBar).length).toBe(1);
+ expect(vm.element).toMatchSnapshot();
+ });
+
+ it.each`
+ distance | titleText
+ ${900} | ${'900'}
+ ${1100} | ${'999+'}
+ `('sets title for $distance as $titleText', ({ distance, titleText }) => {
+ factory({
+ defaultBranch: 'master',
+ aheadCount: 0,
+ behindCount: 0,
+ distance,
+ maxCommits: 100,
+ });
+
+ expect(vm.attributes('title')).toBe(`More than ${titleText} commits different with master`);
+ });
+});
diff --git a/spec/frontend/branches/components/graph_bar_spec.js b/spec/frontend/branches/components/graph_bar_spec.js
new file mode 100644
index 00000000000..61c051b49c6
--- /dev/null
+++ b/spec/frontend/branches/components/graph_bar_spec.js
@@ -0,0 +1,89 @@
+import { shallowMount } from '@vue/test-utils';
+import GraphBar from '~/branches/components/graph_bar.vue';
+
+let vm;
+
+function factory(propsData = {}) {
+ vm = shallowMount(GraphBar, { propsData });
+}
+
+describe('Branch divergence graph bar component', () => {
+ afterEach(() => {
+ vm.destroy();
+ });
+
+ it.each`
+ position | positionClass
+ ${'left'} | ${'position-right-0'}
+ ${'right'} | ${'position-left-0'}
+ ${'full'} | ${'position-left-0'}
+ `(
+ 'sets position class as $positionClass for position $position',
+ ({ position, positionClass }) => {
+ factory({
+ position,
+ count: 10,
+ maxCommits: 100,
+ });
+
+ expect(vm.find('.js-graph-bar').classes()).toContain(positionClass);
+ },
+ );
+
+ it.each`
+ position | textAlignmentClass
+ ${'left'} | ${'text-right'}
+ ${'right'} | ${'text-left'}
+ ${'full'} | ${'text-center'}
+ `(
+ 'sets text alignment class as $textAlignmentClass for position $position',
+ ({ position, textAlignmentClass }) => {
+ factory({
+ position,
+ count: 10,
+ maxCommits: 100,
+ });
+
+ expect(vm.find('.js-graph-count').classes()).toContain(textAlignmentClass);
+ },
+ );
+
+ it.each`
+ position | roundedClass
+ ${'left'} | ${'rounded-left'}
+ ${'right'} | ${'rounded-right'}
+ ${'full'} | ${'rounded'}
+ `('sets rounded class as $roundedClass for position $position', ({ position, roundedClass }) => {
+ factory({
+ position,
+ count: 10,
+ maxCommits: 100,
+ });
+
+ expect(vm.find('.js-graph-bar').classes()).toContain(roundedClass);
+ });
+
+ it.each`
+ count | label
+ ${100} | ${'100'}
+ ${1000} | ${'999+'}
+ `('renders label as $roundedClass for $count', ({ count, label }) => {
+ factory({
+ position: 'left',
+ count,
+ maxCommits: 1000,
+ });
+
+ expect(vm.find('.js-graph-count').text()).toContain(label);
+ });
+
+ it('sets width of bar', () => {
+ factory({
+ position: 'left',
+ count: 100,
+ maxCommits: 1000,
+ });
+
+ expect(vm.find('.js-graph-bar').attributes('style')).toEqual('width: 10%;');
+ });
+});
diff --git a/spec/frontend/lib/utils/datetime_utility_spec.js b/spec/frontend/lib/utils/datetime_utility_spec.js
index 9f49e68cfe8..751fb5e1b94 100644
--- a/spec/frontend/lib/utils/datetime_utility_spec.js
+++ b/spec/frontend/lib/utils/datetime_utility_spec.js
@@ -334,6 +334,12 @@ describe('prettyTime methods', () => {
assertTimeUnits(aboveOneDay, 33, 2, 2, 0);
assertTimeUnits(aboveOneWeek, 26, 0, 1, 9);
});
+
+ it('should correctly parse values when limitedToHours is true', () => {
+ const twoDays = datetimeUtility.parseSeconds(173000, { limitToHours: true });
+
+ assertTimeUnits(twoDays, 3, 48, 0, 0);
+ });
});
describe('stringifyTime', () => {
diff --git a/spec/frontend/vue_shared/components/paginated_list_spec.js b/spec/frontend/vue_shared/components/paginated_list_spec.js
new file mode 100644
index 00000000000..31ac362d35f
--- /dev/null
+++ b/spec/frontend/vue_shared/components/paginated_list_spec.js
@@ -0,0 +1,56 @@
+import PaginatedList from '~/vue_shared/components/paginated_list.vue';
+import { PREV, NEXT } from '~/vue_shared/components/pagination/constants';
+import { mount } from '@vue/test-utils';
+
+describe('Pagination links component', () => {
+ let wrapper;
+ let glPaginatedList;
+
+ const template = `
+ <div class="slot" slot-scope="{ listItem }">
+ <span class="item">Item Name: {{listItem.id}}</span>
+ </div>
+ `;
+
+ const props = {
+ prevText: PREV,
+ nextText: NEXT,
+ };
+
+ beforeEach(() => {
+ wrapper = mount(PaginatedList, {
+ scopedSlots: {
+ default: template,
+ },
+ propsData: {
+ list: [{ id: 'foo' }, { id: 'bar' }],
+ props,
+ },
+ });
+
+ [glPaginatedList] = wrapper.vm.$children;
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ describe('Paginated List Component', () => {
+ describe('props', () => {
+ // We test attrs and not props because we pass through to child component using v-bind:"$attrs"
+ it('should pass prevText to GitLab UI paginated list', () => {
+ expect(glPaginatedList.$attrs['prev-text']).toBe(props.prevText);
+ });
+ it('should pass nextText to GitLab UI paginated list', () => {
+ expect(glPaginatedList.$attrs['next-text']).toBe(props.nextText);
+ });
+ });
+
+ describe('rendering', () => {
+ it('it renders the gl-paginated-list', () => {
+ expect(wrapper.contains('ul.list-group')).toBe(true);
+ expect(wrapper.findAll('li.list-group-item').length).toBe(2);
+ });
+ });
+ });
+});
diff --git a/spec/helpers/appearances_helper_spec.rb b/spec/helpers/appearances_helper_spec.rb
index a3511e078ce..ed3e31b3c53 100644
--- a/spec/helpers/appearances_helper_spec.rb
+++ b/spec/helpers/appearances_helper_spec.rb
@@ -8,6 +8,22 @@ describe AppearancesHelper do
allow(helper).to receive(:current_user).and_return(user)
end
+ describe '.current_appearance' do
+ it 'memoizes empty appearance' do
+ expect(Appearance).to receive(:current).once
+
+ 2.times { helper.current_appearance }
+ end
+
+ it 'memoizes custom appearance' do
+ create(:appearance)
+
+ expect(Appearance).to receive(:current).once.and_call_original
+
+ 2.times { helper.current_appearance }
+ end
+ end
+
describe '#header_message' do
it 'returns nil when header message field is not set' do
create(:appearance)
diff --git a/spec/javascripts/boards/boards_store_spec.js b/spec/javascripts/boards/boards_store_spec.js
index e81115e10c9..5266b1bdbfc 100644
--- a/spec/javascripts/boards/boards_store_spec.js
+++ b/spec/javascripts/boards/boards_store_spec.js
@@ -355,4 +355,14 @@ describe('Store', () => {
expect(boardsStore.moving.list).toEqual(dummyList);
});
});
+
+ describe('setTimeTrackingLimitToHours', () => {
+ it('sets the timeTracking.LimitToHours option', () => {
+ boardsStore.timeTracking.limitToHours = false;
+
+ boardsStore.setTimeTrackingLimitToHours('true');
+
+ expect(boardsStore.timeTracking.limitToHours).toEqual(true);
+ });
+ });
});
diff --git a/spec/javascripts/boards/components/issue_time_estimate_spec.js b/spec/javascripts/boards/components/issue_time_estimate_spec.js
index ba65d3287da..de48e3f6091 100644
--- a/spec/javascripts/boards/components/issue_time_estimate_spec.js
+++ b/spec/javascripts/boards/components/issue_time_estimate_spec.js
@@ -1,40 +1,70 @@
import Vue from 'vue';
import IssueTimeEstimate from '~/boards/components/issue_time_estimate.vue';
+import boardsStore from '~/boards/stores/boards_store';
import mountComponent from '../../helpers/vue_mount_component_helper';
-describe('Issue Tine Estimate component', () => {
+describe('Issue Time Estimate component', () => {
let vm;
beforeEach(() => {
- const Component = Vue.extend(IssueTimeEstimate);
- vm = mountComponent(Component, {
- estimate: 374460,
- });
+ boardsStore.create();
});
afterEach(() => {
vm.$destroy();
});
- it('renders the correct time estimate', () => {
- expect(vm.$el.querySelector('time').textContent.trim()).toEqual('2w 3d 1m');
- });
+ describe('when limitToHours is false', () => {
+ beforeEach(() => {
+ boardsStore.timeTracking.limitToHours = false;
+
+ const Component = Vue.extend(IssueTimeEstimate);
+ vm = mountComponent(Component, {
+ estimate: 374460,
+ });
+ });
+
+ it('renders the correct time estimate', () => {
+ expect(vm.$el.querySelector('time').textContent.trim()).toEqual('2w 3d 1m');
+ });
+
+ it('renders expanded time estimate in tooltip', () => {
+ expect(vm.$el.querySelector('.js-issue-time-estimate').textContent).toContain(
+ '2 weeks 3 days 1 minute',
+ );
+ });
+
+ it('prevents tooltip xss', done => {
+ const alertSpy = spyOn(window, 'alert');
+ vm.estimate = 'Foo <script>alert("XSS")</script>';
- it('renders expanded time estimate in tooltip', () => {
- expect(vm.$el.querySelector('.js-issue-time-estimate').textContent).toContain(
- '2 weeks 3 days 1 minute',
- );
+ vm.$nextTick(() => {
+ expect(alertSpy).not.toHaveBeenCalled();
+ expect(vm.$el.querySelector('time').textContent.trim()).toEqual('0m');
+ expect(vm.$el.querySelector('.js-issue-time-estimate').textContent).toContain('0m');
+ done();
+ });
+ });
});
- it('prevents tooltip xss', done => {
- const alertSpy = spyOn(window, 'alert');
- vm.estimate = 'Foo <script>alert("XSS")</script>';
+ describe('when limitToHours is true', () => {
+ beforeEach(() => {
+ boardsStore.timeTracking.limitToHours = true;
+
+ const Component = Vue.extend(IssueTimeEstimate);
+ vm = mountComponent(Component, {
+ estimate: 374460,
+ });
+ });
+
+ it('renders the correct time estimate', () => {
+ expect(vm.$el.querySelector('time').textContent.trim()).toEqual('104h 1m');
+ });
- vm.$nextTick(() => {
- expect(alertSpy).not.toHaveBeenCalled();
- expect(vm.$el.querySelector('time').textContent.trim()).toEqual('0m');
- expect(vm.$el.querySelector('.js-issue-time-estimate').textContent).toContain('0m');
- done();
+ it('renders expanded time estimate in tooltip', () => {
+ expect(vm.$el.querySelector('.js-issue-time-estimate').textContent).toContain(
+ '104 hours 1 minute',
+ );
});
});
});
diff --git a/spec/javascripts/groups/components/group_item_spec.js b/spec/javascripts/groups/components/group_item_spec.js
index 4d6d0c895b6..cc88a7ac6c1 100644
--- a/spec/javascripts/groups/components/group_item_spec.js
+++ b/spec/javascripts/groups/components/group_item_spec.js
@@ -156,6 +156,8 @@ describe('GroupItemComponent', () => {
describe('template', () => {
it('should render component template correctly', () => {
+ const visibilityIconEl = vm.$el.querySelector('.item-visibility');
+
expect(vm.$el.getAttribute('id')).toBe('group-55');
expect(vm.$el.classList.contains('group-row')).toBeTruthy();
@@ -173,6 +175,11 @@ describe('GroupItemComponent', () => {
expect(vm.$el.querySelector('.title')).toBeDefined();
expect(vm.$el.querySelector('.title a.no-expand')).toBeDefined();
+
+ expect(visibilityIconEl).not.toBe(null);
+ expect(visibilityIconEl.dataset.originalTitle).toBe(vm.visibilityTooltip);
+ expect(visibilityIconEl.querySelectorAll('svg').length).toBeGreaterThan(0);
+
expect(vm.$el.querySelector('.access-type')).toBeDefined();
expect(vm.$el.querySelector('.description')).toBeDefined();
diff --git a/spec/javascripts/groups/components/item_stats_spec.js b/spec/javascripts/groups/components/item_stats_spec.js
index 00d6a4817d7..b2441babf3f 100644
--- a/spec/javascripts/groups/components/item_stats_spec.js
+++ b/spec/javascripts/groups/components/item_stats_spec.js
@@ -108,18 +108,6 @@ describe('ItemStatsComponent', () => {
vm.$destroy();
});
- it('renders item visibility icon and tooltip correctly', () => {
- const vm = createComponent();
-
- const visibilityIconEl = vm.$el.querySelector('.item-visibility');
-
- expect(visibilityIconEl).not.toBe(null);
- expect(visibilityIconEl.dataset.originalTitle).toBe(vm.visibilityTooltip);
- expect(visibilityIconEl.querySelectorAll('svg').length).toBeGreaterThan(0);
-
- vm.$destroy();
- });
-
it('renders start count and last updated information for project item correctly', () => {
const item = Object.assign({}, mockParentGroupItem, {
type: ITEM_TYPE.PROJECT,
diff --git a/spec/javascripts/jobs/components/stages_dropdown_spec.js b/spec/javascripts/jobs/components/stages_dropdown_spec.js
index 52bb5161123..86b7a8d7848 100644
--- a/spec/javascripts/jobs/components/stages_dropdown_spec.js
+++ b/spec/javascripts/jobs/components/stages_dropdown_spec.js
@@ -101,9 +101,7 @@ describe('Stages Dropdown', () => {
});
it(`renders the pipeline info text like "Pipeline #123 for !456 with source_branch into target_branch"`, () => {
- const expected = `Pipeline #${pipeline.id} for !${pipeline.merge_request.iid} with ${
- pipeline.merge_request.source_branch
- } into ${pipeline.merge_request.target_branch}`;
+ const expected = `Pipeline #${pipeline.id} for !${pipeline.merge_request.iid} with ${pipeline.merge_request.source_branch} into ${pipeline.merge_request.target_branch}`;
const actual = trimText(vm.$el.querySelector('.js-pipeline-info').innerText);
expect(actual).toBe(expected);
@@ -144,9 +142,7 @@ describe('Stages Dropdown', () => {
});
it(`renders the pipeline info like "Pipeline #123 for !456 with source_branch"`, () => {
- const expected = `Pipeline #${pipeline.id} for !${pipeline.merge_request.iid} with ${
- pipeline.merge_request.source_branch
- }`;
+ const expected = `Pipeline #${pipeline.id} for !${pipeline.merge_request.iid} with ${pipeline.merge_request.source_branch}`;
const actual = trimText(vm.$el.querySelector('.js-pipeline-info').innerText);
expect(actual).toBe(expected);
diff --git a/spec/javascripts/monitoring/charts/column_spec.js b/spec/javascripts/monitoring/charts/column_spec.js
new file mode 100644
index 00000000000..d8ac68b9484
--- /dev/null
+++ b/spec/javascripts/monitoring/charts/column_spec.js
@@ -0,0 +1,58 @@
+import { shallowMount } from '@vue/test-utils';
+import { GlColumnChart } from '@gitlab/ui/dist/charts';
+import ColumnChart from '~/monitoring/components/charts/column.vue';
+
+describe('Column component', () => {
+ let columnChart;
+
+ beforeEach(() => {
+ columnChart = shallowMount(ColumnChart, {
+ propsData: {
+ graphData: {
+ queries: [
+ {
+ x_label: 'Time',
+ y_label: 'Usage',
+ result: [
+ {
+ metric: {},
+ values: [
+ [1495700554.925, '8.0390625'],
+ [1495700614.925, '8.0390625'],
+ [1495700674.925, '8.0390625'],
+ ],
+ },
+ ],
+ },
+ ],
+ },
+ containerWidth: 100,
+ },
+ });
+ });
+
+ afterEach(() => {
+ columnChart.destroy();
+ });
+
+ describe('wrapped components', () => {
+ describe('GitLab UI column chart', () => {
+ let glColumnChart;
+
+ beforeEach(() => {
+ glColumnChart = columnChart.find(GlColumnChart);
+ });
+
+ it('is a Vue instance', () => {
+ expect(glColumnChart.isVueInstance()).toBe(true);
+ });
+
+ it('receives data properties needed for proper chart render', () => {
+ const props = glColumnChart.props();
+
+ expect(props.data).toBe(columnChart.vm.chartData);
+ expect(props.option).toBe(columnChart.vm.chartOptions);
+ });
+ });
+ });
+});
diff --git a/spec/javascripts/notes/components/diff_with_note_spec.js b/spec/javascripts/notes/components/diff_with_note_spec.js
index 0752bd05904..f849fe9d8bb 100644
--- a/spec/javascripts/notes/components/diff_with_note_spec.js
+++ b/spec/javascripts/notes/components/diff_with_note_spec.js
@@ -47,6 +47,19 @@ describe('diff_with_note', () => {
vm = mountComponentWithStore(Component, { props, store });
});
+ it('removes trailing "+" char', () => {
+ const richText = vm.$el.querySelectorAll('.line_holder')[4].querySelector('.line_content')
+ .textContent[0];
+
+ expect(richText).not.toEqual('+');
+ });
+
+ it('removes trailing "-" char', () => {
+ const richText = vm.$el.querySelector('#LC13').parentNode.textContent[0];
+
+ expect(richText).not.toEqual('-');
+ });
+
it('shows text diff', () => {
expect(selectors.container).toHaveClass('text-file');
expect(selectors.diffTable).toExist();
diff --git a/spec/javascripts/pages/labels/components/promote_label_modal_spec.js b/spec/javascripts/pages/labels/components/promote_label_modal_spec.js
index 08a8362797b..75912612255 100644
--- a/spec/javascripts/pages/labels/components/promote_label_modal_spec.js
+++ b/spec/javascripts/pages/labels/components/promote_label_modal_spec.js
@@ -26,9 +26,7 @@ describe('Promote label modal', () => {
it('contains the proper description', () => {
expect(vm.text).toContain(
- `Promoting ${labelMockData.labelTitle} will make it available for all projects inside ${
- labelMockData.groupName
- }`,
+ `Promoting ${labelMockData.labelTitle} will make it available for all projects inside ${labelMockData.groupName}`,
);
});
diff --git a/spec/javascripts/pages/milestones/shared/components/promote_milestone_modal_spec.js b/spec/javascripts/pages/milestones/shared/components/promote_milestone_modal_spec.js
index 2ac73ef3024..3d25a278cef 100644
--- a/spec/javascripts/pages/milestones/shared/components/promote_milestone_modal_spec.js
+++ b/spec/javascripts/pages/milestones/shared/components/promote_milestone_modal_spec.js
@@ -24,9 +24,7 @@ describe('Promote milestone modal', () => {
it('contains the proper description', () => {
expect(vm.text).toContain(
- `Promoting ${
- milestoneMockData.milestoneTitle
- } will make it available for all projects inside ${milestoneMockData.groupName}.`,
+ `Promoting ${milestoneMockData.milestoneTitle} will make it available for all projects inside ${milestoneMockData.groupName}.`,
);
});
diff --git a/spec/javascripts/registry/components/collapsible_container_spec.js b/spec/javascripts/registry/components/collapsible_container_spec.js
index a3f7ff76dc7..9ed4b04324a 100644
--- a/spec/javascripts/registry/components/collapsible_container_spec.js
+++ b/spec/javascripts/registry/components/collapsible_container_spec.js
@@ -12,6 +12,8 @@ describe('collapsible registry container', () => {
let mock;
const Component = Vue.extend(collapsibleComponent);
+ const findDeleteBtn = () => vm.$el.querySelector('.js-remove-repo');
+
beforeEach(() => {
mock = new MockAdapter(axios);
@@ -67,7 +69,25 @@ describe('collapsible registry container', () => {
describe('delete repo', () => {
it('should be possible to delete a repo', () => {
- expect(vm.$el.querySelector('.js-remove-repo')).not.toBeNull();
+ expect(findDeleteBtn()).not.toBeNull();
+ });
+
+ describe('clicked on delete', () => {
+ beforeEach(done => {
+ findDeleteBtn().click();
+ Vue.nextTick(done);
+ });
+
+ it('should open confirmation modal', () => {
+ expect(vm.$el.querySelector('#confirm-repo-deletion-modal')).not.toBeNull();
+ });
+
+ it('should call deleteItem when confirming deletion', () => {
+ spyOn(vm, 'deleteItem').and.returnValue(Promise.resolve());
+ vm.$el.querySelector('#confirm-repo-deletion-modal .btn-danger').click();
+
+ expect(vm.deleteItem).toHaveBeenCalledWith(vm.repo);
+ });
});
});
});
diff --git a/spec/javascripts/registry/components/table_registry_spec.js b/spec/javascripts/registry/components/table_registry_spec.js
index 7f5252a7d6c..d366c67a1b9 100644
--- a/spec/javascripts/registry/components/table_registry_spec.js
+++ b/spec/javascripts/registry/components/table_registry_spec.js
@@ -3,10 +3,14 @@ import tableRegistry from '~/registry/components/table_registry.vue';
import store from '~/registry/stores';
import { repoPropsData } from '../mock_data';
+const [firstImage] = repoPropsData.list;
+
describe('table registry', () => {
let vm;
let Component;
+ const findDeleteBtn = () => vm.$el.querySelector('.js-delete-registry');
+
beforeEach(() => {
Component = Vue.extend(tableRegistry);
vm = new Component({
@@ -37,8 +41,30 @@ describe('table registry', () => {
expect(textRendered).toContain(repoPropsData.list[0].size);
});
- it('should be possible to delete a registry', () => {
- expect(vm.$el.querySelector('.table tbody tr .js-delete-registry')).toBeDefined();
+ describe('delete registry', () => {
+ it('should be possible to delete a registry', () => {
+ expect(findDeleteBtn()).toBeDefined();
+ });
+
+ describe('clicked on delete', () => {
+ beforeEach(done => {
+ findDeleteBtn().click();
+ Vue.nextTick(done);
+ });
+
+ it('should open confirmation modal and set itemToBeDeleted properly', () => {
+ expect(vm.itemToBeDeleted).toEqual(firstImage);
+ expect(vm.$el.querySelector('#confirm-image-deletion-modal')).not.toBeNull();
+ });
+
+ it('should call deleteItem and reset itemToBeDeleted when confirming deletion', () => {
+ spyOn(vm, 'deleteItem').and.returnValue(Promise.resolve());
+ vm.$el.querySelector('#confirm-image-deletion-modal .btn-danger').click();
+
+ expect(vm.deleteItem).toHaveBeenCalledWith(firstImage);
+ expect(vm.itemToBeDeleted).toBeNull();
+ });
+ });
});
describe('pagination', () => {
diff --git a/spec/javascripts/registry/stores/actions_spec.js b/spec/javascripts/registry/stores/actions_spec.js
index c9aa82dba90..0613ec8e0f1 100644
--- a/spec/javascripts/registry/stores/actions_spec.js
+++ b/spec/javascripts/registry/stores/actions_spec.js
@@ -105,4 +105,28 @@ describe('Actions Registry Store', () => {
);
});
});
+
+ describe('deleteItem', () => {
+ it('should perform DELETE request on destroyPath', done => {
+ const destroyPath = `${TEST_HOST}/mygroup/myproject/container_registry/1.json`;
+ let deleted = false;
+ mock.onDelete(destroyPath).replyOnce(() => {
+ deleted = true;
+ return [200];
+ });
+ testAction(
+ actions.deleteItem,
+ {
+ destroyPath,
+ },
+ mockedState,
+ )
+ .then(() => {
+ expect(mock.history.delete.length).toBe(1);
+ expect(deleted).toBe(true);
+ done();
+ })
+ .catch(done.fail);
+ });
+ });
});
diff --git a/spec/javascripts/releases/components/release_block_spec.js b/spec/javascripts/releases/components/release_block_spec.js
index 36b181f24ef..e98c665f99d 100644
--- a/spec/javascripts/releases/components/release_block_spec.js
+++ b/spec/javascripts/releases/components/release_block_spec.js
@@ -78,8 +78,10 @@ describe('Release block', () => {
};
let vm;
+ const factory = props => mountComponent(Component, { release: props });
+
beforeEach(() => {
- vm = mountComponent(Component, { release });
+ vm = factory(release);
});
afterEach(() => {
@@ -149,4 +151,14 @@ describe('Release block', () => {
);
});
});
+
+ describe('with pre_release flag', () => {
+ beforeEach(() => {
+ vm = factory(Object.assign({}, release, { pre_release: true }));
+ });
+
+ it('renders pre-release badge', () => {
+ expect(vm.$el.textContent).toContain('Pre-release');
+ });
+ });
});
diff --git a/spec/javascripts/sidebar/components/time_tracking/time_tracker_spec.js b/spec/javascripts/sidebar/components/time_tracking/time_tracker_spec.js
index 4c3dd713589..2e1863cff86 100644
--- a/spec/javascripts/sidebar/components/time_tracking/time_tracker_spec.js
+++ b/spec/javascripts/sidebar/components/time_tracking/time_tracker_spec.js
@@ -13,6 +13,7 @@ describe('Issuable Time Tracker', () => {
timeSpent,
timeEstimateHumanReadable,
timeSpentHumanReadable,
+ limitToHours,
}) => {
setFixtures(`
<div>
@@ -25,6 +26,7 @@ describe('Issuable Time Tracker', () => {
timeSpent,
humanTimeEstimate: timeEstimateHumanReadable,
humanTimeSpent: timeSpentHumanReadable,
+ limitToHours: Boolean(limitToHours),
rootPath: '/',
};
@@ -128,6 +130,29 @@ describe('Issuable Time Tracker', () => {
});
});
+ describe('Comparison pane when limitToHours is true', () => {
+ beforeEach(() => {
+ initTimeTrackingComponent({
+ timeEstimate: 100000, // 1d 3h
+ timeSpent: 5000, // 1h 23m
+ timeEstimateHumanReadable: '',
+ timeSpentHumanReadable: '',
+ limitToHours: true,
+ });
+ });
+
+ it('should show the correct tooltip text', done => {
+ Vue.nextTick(() => {
+ expect(vm.showComparisonState).toBe(true);
+ const $title = vm.$el.querySelector('.time-tracking-content .compare-meter').dataset
+ .originalTitle;
+
+ expect($title).toBe('Time remaining: 26h 23m');
+ done();
+ });
+ });
+ });
+
describe('Estimate only pane', () => {
beforeEach(() => {
initTimeTrackingComponent({
diff --git a/spec/javascripts/vue_mr_widget/components/mr_widget_pipeline_spec.js b/spec/javascripts/vue_mr_widget/components/mr_widget_pipeline_spec.js
index 75017d20473..fe831094ecf 100644
--- a/spec/javascripts/vue_mr_widget/components/mr_widget_pipeline_spec.js
+++ b/spec/javascripts/vue_mr_widget/components/mr_widget_pipeline_spec.js
@@ -222,9 +222,7 @@ describe('MRWidgetPipeline', () => {
sourceBranchLink: mockCopy.source_branch_link,
});
- const expected = `Pipeline #${pipeline.id} ${pipeline.details.status.label} for ${
- pipeline.commit.short_id
- } on ${mockCopy.source_branch_link}`;
+ const expected = `Pipeline #${pipeline.id} ${pipeline.details.status.label} for ${pipeline.commit.short_id} on ${mockCopy.source_branch_link}`;
const actual = trimText(vm.$el.querySelector('.js-pipeline-info-container').innerText);
@@ -247,11 +245,7 @@ describe('MRWidgetPipeline', () => {
sourceBranchLink: mockCopy.source_branch_link,
});
- const expected = `Pipeline #${pipeline.id} ${pipeline.details.status.label} for ${
- pipeline.commit.short_id
- } on !${pipeline.merge_request.iid} with ${pipeline.merge_request.source_branch} into ${
- pipeline.merge_request.target_branch
- }`;
+ const expected = `Pipeline #${pipeline.id} ${pipeline.details.status.label} for ${pipeline.commit.short_id} on !${pipeline.merge_request.iid} with ${pipeline.merge_request.source_branch} into ${pipeline.merge_request.target_branch}`;
const actual = trimText(vm.$el.querySelector('.js-pipeline-info-container').innerText);
@@ -274,9 +268,7 @@ describe('MRWidgetPipeline', () => {
sourceBranchLink: mockCopy.source_branch_link,
});
- const expected = `Pipeline #${pipeline.id} ${pipeline.details.status.label} for ${
- pipeline.commit.short_id
- } on !${pipeline.merge_request.iid} with ${pipeline.merge_request.source_branch}`;
+ const expected = `Pipeline #${pipeline.id} ${pipeline.details.status.label} for ${pipeline.commit.short_id} on !${pipeline.merge_request.iid} with ${pipeline.merge_request.source_branch}`;
const actual = trimText(vm.$el.querySelector('.js-pipeline-info-container').innerText);
diff --git a/spec/javascripts/vue_shared/components/table_pagination_spec.js b/spec/javascripts/vue_shared/components/table_pagination_spec.js
index 42abb4d83f0..258530f32f7 100644
--- a/spec/javascripts/vue_shared/components/table_pagination_spec.js
+++ b/spec/javascripts/vue_shared/components/table_pagination_spec.js
@@ -217,7 +217,7 @@ describe('Pagination component', () => {
change: spy,
});
- expect(component.$el.querySelector('.js-next-button').textContent.trim()).toEqual('Next');
+ expect(component.$el.querySelector('.js-next-button').textContent.trim()).toEqual('Next ›');
component.$el.querySelector('.js-next-button .page-link').click();
@@ -237,7 +237,7 @@ describe('Pagination component', () => {
change: spy,
});
- expect(component.$el.querySelector('.js-next-button').textContent.trim()).toEqual('Next');
+ expect(component.$el.querySelector('.js-next-button').textContent.trim()).toEqual('Next ›');
component.$el.querySelector('.js-next-button .page-link').click();
diff --git a/spec/lib/gitlab/bitbucket_import/importer_spec.rb b/spec/lib/gitlab/bitbucket_import/importer_spec.rb
index 2e90f6c7f71..35700e0b588 100644
--- a/spec/lib/gitlab/bitbucket_import/importer_spec.rb
+++ b/spec/lib/gitlab/bitbucket_import/importer_spec.rb
@@ -98,12 +98,8 @@ describe Gitlab::BitbucketImport::Importer do
describe '#import_pull_requests' do
let(:source_branch_sha) { sample.commits.last }
let(:target_branch_sha) { sample.commits.first }
-
- before do
- allow(subject).to receive(:import_wiki)
- allow(subject).to receive(:import_issues)
-
- pull_request = instance_double(
+ let(:pull_request) do
+ instance_double(
Bitbucket::Representation::PullRequest,
iid: 10,
source_branch_sha: source_branch_sha,
@@ -116,6 +112,11 @@ describe Gitlab::BitbucketImport::Importer do
author: 'other',
created_at: Time.now,
updated_at: Time.now)
+ end
+
+ before do
+ allow(subject).to receive(:import_wiki)
+ allow(subject).to receive(:import_issues)
# https://gitlab.com/gitlab-org/gitlab-test/compare/c1acaa58bbcbc3eafe538cb8274ba387047b69f8...5937ac0a7beb003549fc5fd26fc247ad
@inline_note = instance_double(
@@ -167,6 +168,20 @@ describe Gitlab::BitbucketImport::Importer do
expect(reply_note.note).to eq(@reply.note)
end
+ context 'when importing a pull request throws an exception' do
+ before do
+ allow(pull_request).to receive(:raw).and_return('hello world')
+ allow(subject.client).to receive(:pull_request_comments).and_raise(HTTParty::Error)
+ end
+
+ it 'logs an error without the backtrace' do
+ subject.execute
+
+ expect(subject.errors.count).to eq(1)
+ expect(subject.errors.first.keys).to match_array(%i(type iid errors))
+ end
+ end
+
context "when branches' sha is not found in the repository" do
let(:source_branch_sha) { 'a' * Commit::MIN_SHA_LENGTH }
let(:target_branch_sha) { 'b' * Commit::MIN_SHA_LENGTH }
diff --git a/spec/lib/gitlab/ci/build/prerequisite/kubernetes_namespace_spec.rb b/spec/lib/gitlab/ci/build/prerequisite/kubernetes_namespace_spec.rb
index 5ac5122e800..51e16c99688 100644
--- a/spec/lib/gitlab/ci/build/prerequisite/kubernetes_namespace_spec.rb
+++ b/spec/lib/gitlab/ci/build/prerequisite/kubernetes_namespace_spec.rb
@@ -23,7 +23,7 @@ describe Gitlab::Ci::Build::Prerequisite::KubernetesNamespace do
let(:cluster) { create(:cluster, :group) }
before do
- allow(build.deployment).to receive(:cluster).and_return(cluster)
+ allow(build.deployment).to receive(:deployment_platform_cluster).and_return(cluster)
end
it { is_expected.to be_truthy }
@@ -45,17 +45,11 @@ describe Gitlab::Ci::Build::Prerequisite::KubernetesNamespace do
it { is_expected.to be_truthy }
end
end
-
- context 'and cluster is project type' do
- let(:cluster) { create(:cluster, :project) }
-
- it { is_expected.to be_falsey }
- end
end
context 'and no cluster to deploy to' do
before do
- expect(deployment.cluster).to be_nil
+ expect(deployment.deployment_platform_cluster).to be_nil
end
it { is_expected.to be_falsey }
@@ -73,7 +67,7 @@ describe Gitlab::Ci::Build::Prerequisite::KubernetesNamespace do
let(:cluster) { create(:cluster, :group) }
before do
- allow(build.deployment).to receive(:cluster).and_return(cluster)
+ allow(build.deployment).to receive(:deployment_platform_cluster).and_return(cluster)
end
it 'creates a kubernetes namespace' do
@@ -90,7 +84,7 @@ describe Gitlab::Ci::Build::Prerequisite::KubernetesNamespace do
context 'completion is not required' do
before do
- expect(deployment.cluster).to be_nil
+ expect(deployment.deployment_platform_cluster).to be_nil
end
it 'does not create a namespace' do
diff --git a/spec/lib/gitlab/ci/pipeline/seed/build_spec.rb b/spec/lib/gitlab/ci/pipeline/seed/build_spec.rb
index fae8add6453..7991e2f48b5 100644
--- a/spec/lib/gitlab/ci/pipeline/seed/build_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/seed/build_spec.rb
@@ -153,76 +153,72 @@ describe Gitlab::Ci::Pipeline::Seed::Build do
end
end
- context 'when keywords and pipeline source policy matches' do
- possibilities = [%w[pushes push],
- %w[web web],
- %w[triggers trigger],
- %w[schedules schedule],
- %w[api api],
- %w[external external]]
-
- context 'when using only' do
- possibilities.each do |keyword, source|
- context "when using keyword `#{keyword}` and source `#{source}`" do
- let(:pipeline) do
- build(:ci_empty_pipeline, ref: 'deploy', tag: false, source: source)
- end
+ context 'with source-keyword policy' do
+ using RSpec::Parameterized
+
+ let(:pipeline) { build(:ci_empty_pipeline, ref: 'deploy', tag: false, source: source) }
+
+ context 'matches' do
+ where(:keyword, :source) do
+ [
+ %w(pushes push),
+ %w(web web),
+ %w(triggers trigger),
+ %w(schedules schedule),
+ %w(api api),
+ %w(external external)
+ ]
+ end
+ with_them do
+ context 'using an only policy' do
let(:attributes) { { name: 'rspec', only: { refs: [keyword] } } }
it { is_expected.to be_included }
end
- end
- end
-
- context 'when using except' do
- possibilities.each do |keyword, source|
- context "when using keyword `#{keyword}` and source `#{source}`" do
- let(:pipeline) do
- build(:ci_empty_pipeline, ref: 'deploy', tag: false, source: source)
- end
+ context 'using an except policy' do
let(:attributes) { { name: 'rspec', except: { refs: [keyword] } } }
it { is_expected.not_to be_included }
end
+
+ context 'using both only and except policies' do
+ let(:attributes) { { name: 'rspec', only: { refs: [keyword] }, except: { refs: [keyword] } } }
+
+ it { is_expected.not_to be_included }
+ end
end
end
- end
- context 'when keywords and pipeline source does not match' do
- possibilities = [%w[pushes web],
- %w[web push],
- %w[triggers schedule],
- %w[schedules external],
- %w[api trigger],
- %w[external api]]
-
- context 'when using only' do
- possibilities.each do |keyword, source|
- context "when using keyword `#{keyword}` and source `#{source}`" do
- let(:pipeline) do
- build(:ci_empty_pipeline, ref: 'deploy', tag: false, source: source)
- end
+ context 'non-matches' do
+ where(:keyword, :source) do
+ %w(web trigger schedule api external).map { |source| ['pushes', source] } +
+ %w(push trigger schedule api external).map { |source| ['web', source] } +
+ %w(push web schedule api external).map { |source| ['triggers', source] } +
+ %w(push web trigger api external).map { |source| ['schedules', source] } +
+ %w(push web trigger schedule external).map { |source| ['api', source] } +
+ %w(push web trigger schedule api).map { |source| ['external', source] }
+ end
+ with_them do
+ context 'using an only policy' do
let(:attributes) { { name: 'rspec', only: { refs: [keyword] } } }
it { is_expected.not_to be_included }
end
- end
- end
-
- context 'when using except' do
- possibilities.each do |keyword, source|
- context "when using keyword `#{keyword}` and source `#{source}`" do
- let(:pipeline) do
- build(:ci_empty_pipeline, ref: 'deploy', tag: false, source: source)
- end
+ context 'using an except policy' do
let(:attributes) { { name: 'rspec', except: { refs: [keyword] } } }
it { is_expected.to be_included }
end
+
+ context 'using both only and except policies' do
+ let(:attributes) { { name: 'rspec', only: { refs: [keyword] }, except: { refs: [keyword] } } }
+
+ it { is_expected.not_to be_included }
+ end
end
end
end
diff --git a/spec/lib/gitlab/data_builder/note_spec.rb b/spec/lib/gitlab/data_builder/note_spec.rb
index ed9a1e23529..1b5dd2538e0 100644
--- a/spec/lib/gitlab/data_builder/note_spec.rb
+++ b/spec/lib/gitlab/data_builder/note_spec.rb
@@ -38,9 +38,11 @@ describe Gitlab::DataBuilder::Note do
end
describe 'When asking for a note on issue' do
+ let(:label) { create(:label, project: project) }
+
let(:issue) do
- create(:issue, created_at: fixed_time, updated_at: fixed_time,
- project: project)
+ create(:labeled_issue, created_at: fixed_time, updated_at: fixed_time,
+ project: project, labels: [label])
end
let(:note) do
@@ -48,13 +50,16 @@ describe Gitlab::DataBuilder::Note do
end
it 'returns the note and issue-specific data' do
+ without_timestamps = lambda { |label| label.except('created_at', 'updated_at') }
+ hook_attrs = issue.reload.hook_attrs
+
expect(data).to have_key(:issue)
- expect(data[:issue].except('updated_at'))
- .to eq(issue.reload.hook_attrs.except('updated_at'))
+ expect(data[:issue].except('updated_at', 'labels'))
+ .to eq(hook_attrs.except('updated_at', 'labels'))
expect(data[:issue]['updated_at'])
- .to be >= issue.hook_attrs['updated_at']
- expect(data[:issue]['labels'])
- .to eq(issue.hook_attrs['labels'])
+ .to be >= hook_attrs['updated_at']
+ expect(data[:issue]['labels'].map(&without_timestamps))
+ .to eq(hook_attrs['labels'].map(&without_timestamps))
end
context 'with confidential issue' do
diff --git a/spec/lib/gitlab/highlight_spec.rb b/spec/lib/gitlab/highlight_spec.rb
index fe0e9702f8a..4676db6b8d8 100644
--- a/spec/lib/gitlab/highlight_spec.rb
+++ b/spec/lib/gitlab/highlight_spec.rb
@@ -18,9 +18,10 @@ describe Gitlab::Highlight do
end
describe '#highlight' do
+ let(:plain_text_file_name) { "test.txt" }
+ let(:plain_text_content) { "plain text contents" }
let(:file_name) { 'test.lisp' }
- let(:no_context_content) { ":type \"assem\"))" }
- let(:content) { "(make-pathname :defaults name\n#{no_context_content}" }
+ let(:content) { "(make-pathname :defaults name\n:type \"assem\")" }
let(:multiline_content) do
%q(
def test(input):
@@ -32,22 +33,22 @@ describe Gitlab::Highlight do
it 'highlights' do
expected = %Q[<span id="LC1" class="line" lang="common_lisp"><span class="p">(</span><span class="nb">make-pathname</span> <span class="ss">:defaults</span> <span class="nv">name</span></span>
-<span id="LC2" class="line" lang="common_lisp"><span class="ss">:type</span> <span class="s">"assem"</span><span class="p">))</span></span>]
+<span id="LC2" class="line" lang="common_lisp"><span class="ss">:type</span> <span class="s">"assem"</span><span class="p">)</span></span>]
expect(described_class.highlight(file_name, content)).to eq(expected)
end
it 'returns plain version for unknown lexer context' do
- result = described_class.highlight(file_name, no_context_content)
+ result = described_class.highlight(plain_text_file_name, plain_text_content)
- expect(result).to eq(%[<span id="LC1" class="line" lang="">:type "assem"))</span>])
+ expect(result).to eq(%[<span id="LC1" class="line" lang="plaintext">plain text contents</span>])
end
it 'returns plain version for long content' do
stub_const('Gitlab::Highlight::MAXIMUM_TEXT_HIGHLIGHT_SIZE', 1)
result = described_class.highlight(file_name, content)
- expect(result).to eq(%[<span id="LC1" class="line" lang="">(make-pathname :defaults name</span>\n<span id="LC2" class="line" lang="">:type "assem"))</span>])
+ expect(result).to eq(%[<span id="LC1" class="line" lang="">(make-pathname :defaults name</span>\n<span id="LC2" class="line" lang="">:type "assem")</span>])
end
it 'highlights multi-line comments' do
diff --git a/spec/lib/gitlab/hook_data/issue_builder_spec.rb b/spec/lib/gitlab/hook_data/issue_builder_spec.rb
index f066c0e3813..b06d05c1c7f 100644
--- a/spec/lib/gitlab/hook_data/issue_builder_spec.rb
+++ b/spec/lib/gitlab/hook_data/issue_builder_spec.rb
@@ -1,7 +1,8 @@
require 'spec_helper'
describe Gitlab::HookData::IssueBuilder do
- set(:issue) { create(:issue) }
+ set(:label) { create(:label) }
+ set(:issue) { create(:labeled_issue, labels: [label], project: label.project) }
let(:builder) { described_class.new(issue) }
describe '#build' do
@@ -39,6 +40,7 @@ describe Gitlab::HookData::IssueBuilder do
expect(data).to include(:human_time_estimate)
expect(data).to include(:human_total_time_spent)
expect(data).to include(:assignee_ids)
+ expect(data).to include('labels' => [label.hook_attrs])
end
context 'when the issue has an image in the description' do
diff --git a/spec/lib/gitlab/json_cache_spec.rb b/spec/lib/gitlab/json_cache_spec.rb
index c6a6042c65c..59160741c45 100644
--- a/spec/lib/gitlab/json_cache_spec.rb
+++ b/spec/lib/gitlab/json_cache_spec.rb
@@ -6,7 +6,7 @@ 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(:expanded_key) { "#{namespace}:#{key}:#{Gitlab::VERSION}:#{Rails.version}" }
set(:broadcast_message) { create(:broadcast_message) }
subject(:cache) { described_class.new(namespace: namespace, backend: backend) }
@@ -35,42 +35,68 @@ describe Gitlab::JsonCache do
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)
+ context 'when cache_key_with_version is true' do
+ it 'expands out the key with GitLab, and Rails versions' do
+ cache = described_class.new(cache_key_with_version: true)
- cache_key = cache.cache_key(key)
+ cache_key = cache.cache_key(key)
- expect(cache_key).to eq("#{key}:#{Rails.version}")
+ expect(cache_key).to eq("#{key}:#{Gitlab::VERSION}:#{Rails.version}")
+ end
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)
+ context 'when 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)
+ cache_key = cache.cache_key(key)
- expect(cache_key).to eq("#{namespace}:#{key}:#{Rails.version}")
+ expect(cache_key).to eq(key)
+ end
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)
+ context 'when namespace is nil' do
+ context 'when cache_key_with_version is true' do
+ it 'expands out the key with GitLab, and Rails versions' do
+ cache = described_class.new(cache_key_with_version: true)
- cache_key = cache.cache_key(key)
+ cache_key = cache.cache_key(key)
- expect(cache_key).to eq("#{namespace}:#{key}")
+ expect(cache_key).to eq("#{key}:#{Gitlab::VERSION}:#{Rails.version}")
+ end
+ end
+
+ context 'when 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
- 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)
+ context 'when namespace is set' do
+ 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)
- cache_key = cache.cache_key(key)
+ expect(cache_key).to eq("#{namespace}:#{key}:#{Gitlab::VERSION}:#{Rails.version}")
+ end
+ end
- expect(cache_key).to eq(key)
+ 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
end
end
diff --git a/spec/lib/gitlab/kubernetes_spec.rb b/spec/lib/gitlab/kubernetes_spec.rb
index 45369b91ed6..a7ea942960b 100644
--- a/spec/lib/gitlab/kubernetes_spec.rb
+++ b/spec/lib/gitlab/kubernetes_spec.rb
@@ -67,6 +67,30 @@ describe Gitlab::Kubernetes do
end
end
+ describe '#filter_by_legacy_label' do
+ let(:non_matching_pod) { kube_pod(environment_slug: 'production', project_slug: 'my-cool-app') }
+
+ let(:non_matching_pod_2) do
+ kube_pod(environment_slug: 'production', project_slug: 'my-cool-app').tap do |pod|
+ pod['metadata']['labels']['app'] = 'production'
+ end
+ end
+
+ let(:matching_pod) do
+ kube_pod.tap do |pod|
+ pod['metadata']['annotations'].delete('app.gitlab.com/env')
+ pod['metadata']['annotations'].delete('app.gitlab.com/app')
+ pod['metadata']['labels']['app'] = 'production'
+ end
+ end
+
+ it 'returns matching labels' do
+ items = [non_matching_pod, non_matching_pod_2, matching_pod]
+
+ expect(filter_by_legacy_label(items, 'my-cool-app', 'production')).to contain_exactly(matching_pod)
+ end
+ end
+
describe '#to_kubeconfig' do
let(:token) { 'TOKEN' }
let(:ca_pem) { 'PEM' }
diff --git a/spec/lib/gitlab/lets_encrypt/client_spec.rb b/spec/lib/gitlab/lets_encrypt/client_spec.rb
index 5454d9c1af4..cbb862cb0c9 100644
--- a/spec/lib/gitlab/lets_encrypt/client_spec.rb
+++ b/spec/lib/gitlab/lets_encrypt/client_spec.rb
@@ -116,42 +116,6 @@ describe ::Gitlab::LetsEncrypt::Client do
end
end
- describe '#enabled?' do
- subject { client.enabled? }
-
- context 'when terms of service are accepted' do
- it { is_expected.to eq(true) }
-
- context "when private_key isn't present and database is read only" do
- before do
- allow(::Gitlab::Database).to receive(:read_only?).and_return(true)
- end
-
- it 'returns false' do
- expect(::Gitlab::CurrentSettings.lets_encrypt_private_key).to eq(nil)
-
- is_expected.to eq(false)
- end
- end
-
- context 'when feature flag is disabled' do
- before do
- stub_feature_flags(pages_auto_ssl: false)
- end
-
- it { is_expected.to eq(false) }
- end
- end
-
- context 'when terms of service are not accepted' do
- before do
- stub_application_setting(lets_encrypt_terms_of_service_accepted: false)
- end
-
- it { is_expected.to eq(false) }
- end
- end
-
describe '#terms_of_service_url' do
subject { client.terms_of_service_url }
diff --git a/spec/lib/gitlab/lets_encrypt_spec.rb b/spec/lib/gitlab/lets_encrypt_spec.rb
new file mode 100644
index 00000000000..674b114e9d3
--- /dev/null
+++ b/spec/lib/gitlab/lets_encrypt_spec.rb
@@ -0,0 +1,56 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe ::Gitlab::LetsEncrypt do
+ include LetsEncryptHelpers
+
+ before do
+ stub_lets_encrypt_settings
+ end
+
+ describe '.enabled?' do
+ let(:project) { create(:project) }
+ let(:pages_domain) { create(:pages_domain, project: project) }
+
+ subject { described_class.enabled?(pages_domain) }
+
+ context 'when terms of service are accepted' do
+ it { is_expected.to eq(true) }
+
+ context 'when feature flag is disabled' do
+ before do
+ stub_feature_flags(pages_auto_ssl: false)
+ end
+
+ it { is_expected.to eq(false) }
+ end
+ end
+
+ context 'when terms of service are not accepted' do
+ before do
+ stub_application_setting(lets_encrypt_terms_of_service_accepted: false)
+ end
+
+ it { is_expected.to eq(false) }
+ end
+
+ context 'when feature flag for project is disabled' do
+ before do
+ stub_feature_flags(pages_auto_ssl_for_project: false)
+ end
+
+ it 'returns false' do
+ is_expected.to eq(false)
+ end
+ end
+
+ context 'when domain has not project' do
+ let(:pages_domain) { create(:pages_domain) }
+
+ it 'returns false' do
+ is_expected.to eq(false)
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/search/found_blob_spec.rb b/spec/lib/gitlab/search/found_blob_spec.rb
index 74157e5c67c..da263bc7523 100644
--- a/spec/lib/gitlab/search/found_blob_spec.rb
+++ b/spec/lib/gitlab/search/found_blob_spec.rb
@@ -3,14 +3,15 @@
require 'spec_helper'
describe Gitlab::Search::FoundBlob do
- describe 'parsing results' do
- let(:project) { create(:project, :public, :repository) }
+ let(:project) { create(:project, :public, :repository) }
+
+ describe 'parsing content results' do
let(:results) { project.repository.search_files_by_content('feature', 'master') }
let(:search_result) { results.first }
subject { described_class.new(content_match: search_result, project: project) }
- it "returns a valid FoundBlob" do
+ it 'returns a valid FoundBlob' do
is_expected.to be_an described_class
expect(subject.id).to be_nil
expect(subject.path).to eq('CHANGELOG')
@@ -21,13 +22,13 @@ describe Gitlab::Search::FoundBlob do
expect(subject.data.lines[2]).to eq(" - Feature: Replace teams with group membership\n")
end
- it "doesn't parses content if not needed" do
+ it 'does not parse content if not needed' do
expect(subject).not_to receive(:parse_search_result)
expect(subject.project_id).to eq(project.id)
expect(subject.binary_filename).to eq('CHANGELOG')
end
- it "parses content only once when needed" do
+ it 'parses content only once when needed' do
expect(subject).to receive(:parse_search_result).once.and_call_original
expect(subject.filename).to eq('CHANGELOG')
expect(subject.startline).to eq(188)
@@ -119,7 +120,7 @@ describe Gitlab::Search::FoundBlob do
end
end
- context "when filename has extension" do
+ context 'when filename has extension' do
let(:search_result) { "master:CONTRIBUTE.md\x005\x00- [Contribute to GitLab](#contribute-to-gitlab)\n" }
it { expect(subject.path).to eq('CONTRIBUTE.md') }
@@ -127,7 +128,7 @@ describe Gitlab::Search::FoundBlob do
it { expect(subject.basename).to eq('CONTRIBUTE') }
end
- context "when file under directory" do
+ context 'when file is under directory' do
let(:search_result) { "master:a/b/c.md\x005\x00a b c\n" }
it { expect(subject.path).to eq('a/b/c.md') }
@@ -135,4 +136,28 @@ describe Gitlab::Search::FoundBlob do
it { expect(subject.basename).to eq('a/b/c') }
end
end
+
+ describe 'parsing title results' do
+ context 'when file is under directory' do
+ let(:path) { 'a/b/c.md' }
+
+ subject { described_class.new(blob_filename: path, project: project, ref: 'master') }
+
+ before do
+ allow(Gitlab::Git::Blob).to receive(:batch).and_return([
+ Gitlab::Git::Blob.new(path: path)
+ ])
+ end
+
+ it { expect(subject.path).to eq('a/b/c.md') }
+ it { expect(subject.filename).to eq('a/b/c.md') }
+ it { expect(subject.basename).to eq('a/b/c') }
+
+ context 'when filename has multiple extensions' do
+ let(:path) { 'a/b/c.whatever.md' }
+
+ it { expect(subject.basename).to eq('a/b/c.whatever') }
+ end
+ end
+ end
end
diff --git a/spec/lib/gitlab/time_tracking_formatter_spec.rb b/spec/lib/gitlab/time_tracking_formatter_spec.rb
new file mode 100644
index 00000000000..a85d418777f
--- /dev/null
+++ b/spec/lib/gitlab/time_tracking_formatter_spec.rb
@@ -0,0 +1,43 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Gitlab::TimeTrackingFormatter do
+ describe '#parse' do
+ subject { described_class.parse(duration_string) }
+
+ context 'positive durations' do
+ let(:duration_string) { '3h 20m' }
+
+ it { expect(subject).to eq(12_000) }
+ end
+
+ context 'negative durations' do
+ let(:duration_string) { '-3h 20m' }
+
+ it { expect(subject).to eq(-12_000) }
+ end
+ end
+
+ describe '#output' do
+ let(:num_seconds) { 178_800 }
+
+ subject { described_class.output(num_seconds) }
+
+ context 'time_tracking_limit_to_hours setting is true' do
+ before do
+ stub_application_setting(time_tracking_limit_to_hours: true)
+ end
+
+ it { expect(subject).to eq('49h 40m') }
+ end
+
+ context 'time_tracking_limit_to_hours setting is false' do
+ before do
+ stub_application_setting(time_tracking_limit_to_hours: false)
+ end
+
+ it { expect(subject).to eq('1w 1d 1h 40m') }
+ end
+ end
+end
diff --git a/spec/mailers/emails/pages_domains_spec.rb b/spec/mailers/emails/pages_domains_spec.rb
index 2f594dbf9d1..eae83cd64d3 100644
--- a/spec/mailers/emails/pages_domains_spec.rb
+++ b/spec/mailers/emails/pages_domains_spec.rb
@@ -9,7 +9,7 @@ describe Emails::PagesDomains do
set(:user) { project.creator }
shared_examples 'a pages domain email' do
- let(:test_recipient) { user }
+ let(:recipient) { user }
it_behaves_like 'an email sent to a user'
it_behaves_like 'an email sent from GitLab'
diff --git a/spec/mailers/notify_spec.rb b/spec/mailers/notify_spec.rb
index cbbb22ad78c..fa1343fe759 100644
--- a/spec/mailers/notify_spec.rb
+++ b/spec/mailers/notify_spec.rb
@@ -45,7 +45,7 @@ describe Notify do
context 'for a project' do
shared_examples 'an assignee email' do
- let(:test_recipient) { assignee }
+ let(:recipient) { assignee }
it_behaves_like 'an email sent to a user'
@@ -55,7 +55,7 @@ describe Notify do
aggregate_failures do
expect(sender.display_name).to eq(current_user.name)
expect(sender.address).to eq(gitlab_sender)
- expect(subject).to deliver_to(assignee.email)
+ expect(subject).to deliver_to(recipient.notification_email)
end
end
end
@@ -99,15 +99,9 @@ describe Notify do
end
end
- context 'when enabled email_author_in_body' do
- before do
- stub_application_setting(email_author_in_body: true)
- end
-
- it 'contains a link to note author' do
- is_expected.to have_body_text(issue.author_name)
- is_expected.to have_body_text 'created an issue:'
- end
+ it 'contains a link to issue author' do
+ is_expected.to have_body_text(issue.author_name)
+ is_expected.to have_body_text 'created an issue:'
end
end
@@ -314,15 +308,9 @@ describe Notify do
end
end
- context 'when enabled email_author_in_body' do
- before do
- stub_application_setting(email_author_in_body: true)
- end
-
- it 'contains a link to note author' do
- is_expected.to have_body_text merge_request.author_name
- is_expected.to have_body_text 'created a merge request:'
- end
+ it 'contains a link to merge request author' do
+ is_expected.to have_body_text merge_request.author_name
+ is_expected.to have_body_text 'created a merge request:'
end
end
@@ -559,12 +547,13 @@ describe Notify do
let(:host) { Gitlab.config.gitlab.host }
context 'in discussion' do
- set(:first_note) { create(:discussion_note_on_issue) }
- set(:second_note) { create(:discussion_note_on_issue, in_reply_to: first_note) }
- set(:third_note) { create(:discussion_note_on_issue, in_reply_to: second_note) }
+ set(:first_note) { create(:discussion_note_on_issue, project: project) }
+ set(:second_note) { create(:discussion_note_on_issue, in_reply_to: first_note, project: project) }
+ set(:third_note) { create(:discussion_note_on_issue, in_reply_to: second_note, project: project) }
subject { described_class.note_issue_email(recipient.id, third_note.id) }
+ it_behaves_like 'an email sent to a user'
it_behaves_like 'appearance header and footer enabled'
it_behaves_like 'appearance header and footer not enabled'
@@ -584,10 +573,11 @@ describe Notify do
end
context 'individual issue comments' do
- set(:note) { create(:note_on_issue) }
+ set(:note) { create(:note_on_issue, project: project) }
subject { described_class.note_issue_email(recipient.id, note.id) }
+ it_behaves_like 'an email sent to a user'
it_behaves_like 'appearance header and footer enabled'
it_behaves_like 'appearance header and footer not enabled'
@@ -616,13 +606,13 @@ describe Notify do
it_behaves_like 'a user cannot unsubscribe through footer link'
it 'has the correct subject and body' do
- is_expected.to have_referable_subject(project_snippet, reply: true)
+ is_expected.to have_referable_subject(project_snippet, include_group: true, reply: true)
is_expected.to have_body_text project_snippet_note.note
end
end
describe 'project was moved' do
- let(:test_recipient) { user }
+ let(:recipient) { user }
subject { described_class.project_was_moved_email(project.id, user.id, "gitlab/gitlab") }
it_behaves_like 'an email sent to a user'
@@ -823,7 +813,7 @@ describe Notify do
it 'has the correct subject and body' do
aggregate_failures do
- is_expected.to have_subject("Re: #{project.name} | #{commit.title} (#{commit.short_id})")
+ is_expected.to have_subject("Re: #{project.name} | #{project.group.name} | #{commit.title} (#{commit.short_id})")
is_expected.to have_body_text(commit.short_id)
end
end
@@ -849,7 +839,7 @@ describe Notify do
it 'has the correct subject and body' do
aggregate_failures do
- is_expected.to have_referable_subject(merge_request, reply: true)
+ is_expected.to have_referable_subject(merge_request, include_group: true, reply: true)
is_expected.to have_body_text note_on_merge_request_path
end
end
@@ -875,7 +865,7 @@ describe Notify do
it 'has the correct subject and body' do
aggregate_failures do
- is_expected.to have_referable_subject(issue, reply: true)
+ is_expected.to have_referable_subject(issue, include_group: true, reply: true)
is_expected.to have_body_text(note_on_issue_path)
end
end
@@ -907,7 +897,9 @@ describe Notify do
end
it 'contains an introduction' do
- is_expected.to have_body_text 'started a new discussion'
+ issuable_url = "project_#{note.noteable_type.underscore}_url"
+
+ is_expected.to have_body_text "started a new <a href=\"#{public_send(issuable_url, project, note.noteable, anchor: "note_#{note.id}")}\">discussion</a>"
end
context 'when a comment on an existing discussion' do
@@ -939,7 +931,7 @@ describe Notify do
it_behaves_like 'appearance header and footer not enabled'
it 'has the correct subject' do
- is_expected.to have_subject "Re: #{project.name} | #{commit.title} (#{commit.short_id})"
+ is_expected.to have_subject "Re: #{project.name} | #{project.group.name} | #{commit.title} (#{commit.short_id})"
end
it 'contains a link to the commit' do
@@ -967,7 +959,7 @@ describe Notify do
it_behaves_like 'appearance header and footer not enabled'
it 'has the correct subject' do
- is_expected.to have_referable_subject(merge_request, reply: true)
+ is_expected.to have_referable_subject(merge_request, include_group: true, reply: true)
end
it 'contains a link to the merge request note' do
@@ -995,7 +987,7 @@ describe Notify do
it_behaves_like 'appearance header and footer not enabled'
it 'has the correct subject' do
- is_expected.to have_referable_subject(issue, reply: true)
+ is_expected.to have_referable_subject(issue, include_group: true, reply: true)
end
it 'contains a link to the issue note' do
diff --git a/spec/migrations/enqueue_reset_merge_status_second_run_spec.rb b/spec/migrations/enqueue_reset_merge_status_second_run_spec.rb
new file mode 100644
index 00000000000..3c880c6f5fd
--- /dev/null
+++ b/spec/migrations/enqueue_reset_merge_status_second_run_spec.rb
@@ -0,0 +1,52 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require Rails.root.join('db', 'post_migrate', '20190620112608_enqueue_reset_merge_status_second_run.rb')
+
+describe EnqueueResetMergeStatusSecondRun, :migration, :sidekiq do
+ let(:namespaces) { table(:namespaces) }
+ let(:projects) { table(:projects) }
+ let(:namespace) { namespaces.create(name: 'gitlab', path: 'gitlab-org') }
+ let(:project) { projects.create(namespace_id: namespace.id, name: 'foo') }
+ let(:merge_requests) { table(:merge_requests) }
+
+ def create_merge_request(id, extra_params = {})
+ params = {
+ id: id,
+ target_project_id: project.id,
+ target_branch: 'master',
+ source_project_id: project.id,
+ source_branch: 'mr name',
+ title: "mr name#{id}"
+ }.merge(extra_params)
+
+ merge_requests.create!(params)
+ end
+
+ it 'correctly schedules background migrations' do
+ create_merge_request(1, state: 'opened', merge_status: 'can_be_merged')
+ create_merge_request(2, state: 'opened', merge_status: 'can_be_merged')
+ create_merge_request(3, state: 'opened', merge_status: 'can_be_merged')
+ create_merge_request(4, state: 'merged', merge_status: 'can_be_merged')
+ create_merge_request(5, state: 'opened', merge_status: 'unchecked')
+
+ stub_const("#{described_class.name}::BATCH_SIZE", 2)
+
+ Sidekiq::Testing.fake! do
+ Timecop.freeze do
+ migrate!
+
+ expect(described_class::MIGRATION)
+ .to be_scheduled_delayed_migration(5.minutes, 1, 2)
+
+ expect(described_class::MIGRATION)
+ .to be_scheduled_delayed_migration(10.minutes, 3, 4)
+
+ expect(described_class::MIGRATION)
+ .to be_scheduled_delayed_migration(15.minutes, 5, 5)
+
+ expect(BackgroundMigrationWorker.jobs.size).to eq(3)
+ end
+ end
+ end
+end
diff --git a/spec/models/ci/pipeline_schedule_spec.rb b/spec/models/ci/pipeline_schedule_spec.rb
index d7b81caddf5..aee43025288 100644
--- a/spec/models/ci/pipeline_schedule_spec.rb
+++ b/spec/models/ci/pipeline_schedule_spec.rb
@@ -88,23 +88,8 @@ describe Ci::PipelineSchedule do
describe '#set_next_run_at' do
let(:pipeline_schedule) { create(:ci_pipeline_schedule, :nightly) }
- let(:ideal_next_run_at) { pipeline_schedule.send(:ideal_next_run_at) }
-
- let(:expected_next_run_at) do
- Gitlab::Ci::CronParser.new(Settings.cron_jobs['pipeline_schedule_worker']['cron'], Time.zone.name)
- .next_time_from(ideal_next_run_at)
- end
-
- let(:cron_worker_next_run_at) do
- Gitlab::Ci::CronParser.new(Settings.cron_jobs['pipeline_schedule_worker']['cron'], Time.zone.name)
- .next_time_from(Time.zone.now)
- end
-
- context 'when creates new pipeline schedule' do
- it 'updates next_run_at automatically' do
- expect(pipeline_schedule.next_run_at).to eq(expected_next_run_at)
- end
- end
+ let(:ideal_next_run_at) { pipeline_schedule.send(:ideal_next_run_from, Time.zone.now) }
+ let(:cron_worker_next_run_at) { pipeline_schedule.send(:cron_worker_next_run_from, Time.zone.now) }
context 'when PipelineScheduleWorker runs at a specific interval' do
before do
@@ -129,7 +114,7 @@ describe Ci::PipelineSchedule do
let(:pipeline_schedule) { create(:ci_pipeline_schedule, :every_minute) }
it "updates next_run_at to the sidekiq worker's execution time" do
- Timecop.freeze(2019, 06, 19, 12, 00) do
+ Timecop.freeze(Time.parse("2019-06-01 12:18:00+0000")) do
expect(pipeline_schedule.next_run_at).to eq(cron_worker_next_run_at)
end
end
@@ -157,9 +142,8 @@ describe Ci::PipelineSchedule do
let(:new_cron) { '0 0 1 1 *' }
it 'updates next_run_at automatically' do
- pipeline_schedule.update!(cron: new_cron)
-
- expect(pipeline_schedule.next_run_at).to eq(expected_next_run_at)
+ expect { pipeline_schedule.update!(cron: new_cron) }
+ .to change { pipeline_schedule.next_run_at }
end
end
end
@@ -167,21 +151,24 @@ describe Ci::PipelineSchedule do
describe '#schedule_next_run!' do
let!(:pipeline_schedule) { create(:ci_pipeline_schedule, :nightly) }
- context 'when reschedules after 10 days from now' do
- let(:future_time) { 10.days.from_now }
- let(:ideal_next_run_at) { pipeline_schedule.send(:ideal_next_run_at) }
+ before do
+ pipeline_schedule.update_column(:next_run_at, nil)
+ end
- let(:expected_next_run_at) do
- Gitlab::Ci::CronParser.new(Settings.cron_jobs['pipeline_schedule_worker']['cron'], Time.zone.name)
- .next_time_from(ideal_next_run_at)
+ it 'updates next_run_at' do
+ expect { pipeline_schedule.schedule_next_run! }
+ .to change { pipeline_schedule.next_run_at }
+ end
+
+ context 'when record is invalid' do
+ before do
+ allow(pipeline_schedule).to receive(:save!) { raise ActiveRecord::RecordInvalid.new(pipeline_schedule) }
end
- it 'points to proper next_run_at' do
- Timecop.freeze(future_time) do
- pipeline_schedule.schedule_next_run!
+ it 'nullifies the next run at' do
+ pipeline_schedule.schedule_next_run!
- expect(pipeline_schedule.next_run_at).to eq(expected_next_run_at)
- end
+ expect(pipeline_schedule.next_run_at).to be_nil
end
end
end
diff --git a/spec/models/clusters/platforms/kubernetes_spec.rb b/spec/models/clusters/platforms/kubernetes_spec.rb
index 0fa5d031736..05b3035e591 100644
--- a/spec/models/clusters/platforms/kubernetes_spec.rb
+++ b/spec/models/clusters/platforms/kubernetes_spec.rb
@@ -484,27 +484,4 @@ describe Clusters::Platforms::Kubernetes, :use_clean_rails_memory_store_caching
it { is_expected.to include(pods: []) }
end
end
-
- describe '#update_kubernetes_namespace' do
- let(:cluster) { create(:cluster, :provided_by_gcp) }
- let(:platform) { cluster.platform }
-
- context 'when namespace is updated' do
- it 'calls ConfigureWorker' do
- expect(ClusterConfigureWorker).to receive(:perform_async).with(cluster.id).once
-
- platform.namespace = 'new-namespace'
- platform.save
- end
- end
-
- context 'when namespace is not updated' do
- it 'does not call ConfigureWorker' do
- expect(ClusterConfigureWorker).not_to receive(:perform_async)
-
- platform.username = "new-username"
- platform.save
- end
- end
- end
end
diff --git a/spec/models/deployment_spec.rb b/spec/models/deployment_spec.rb
index 1dceef3fc00..a433878f3bc 100644
--- a/spec/models/deployment_spec.rb
+++ b/spec/models/deployment_spec.rb
@@ -380,12 +380,12 @@ describe Deployment do
end
end
- describe '#cluster' do
+ describe '#deployment_platform_cluster' do
let(:deployment) { create(:deployment) }
let(:project) { deployment.project }
let(:environment) { deployment.environment }
- subject { deployment.cluster }
+ subject { deployment.deployment_platform_cluster }
before do
expect(project).to receive(:deployment_platform)
diff --git a/spec/models/issue_spec.rb b/spec/models/issue_spec.rb
index a5c7e9db2a1..d5b016dc8f6 100644
--- a/spec/models/issue_spec.rb
+++ b/spec/models/issue_spec.rb
@@ -862,4 +862,13 @@ describe Issue do
end
end
end
+
+ describe "#labels_hook_attrs" do
+ let(:label) { create(:label) }
+ let(:issue) { create(:labeled_issue, labels: [label]) }
+
+ it "returns a list of label hook attributes" do
+ expect(issue.labels_hook_attrs).to eq([label.hook_attrs])
+ end
+ end
end
diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb
index c6251326c22..fc28c216b21 100644
--- a/spec/models/merge_request_spec.rb
+++ b/spec/models/merge_request_spec.rb
@@ -1996,57 +1996,6 @@ describe MergeRequest do
end
end
- describe '#check_if_can_be_merged' do
- let(:project) { create(:project, only_allow_merge_if_pipeline_succeeds: true) }
-
- shared_examples 'checking if can be merged' do
- context 'when it is not broken and has no conflicts' do
- before do
- allow(subject).to receive(:broken?) { false }
- allow(project.repository).to receive(:can_be_merged?).and_return(true)
- end
-
- it 'is marked as mergeable' do
- expect { subject.check_if_can_be_merged }.to change { subject.merge_status }.to('can_be_merged')
- end
- end
-
- context 'when broken' do
- before do
- allow(subject).to receive(:broken?) { true }
- allow(project.repository).to receive(:can_be_merged?).and_return(false)
- end
-
- it 'becomes unmergeable' do
- expect { subject.check_if_can_be_merged }.to change { subject.merge_status }.to('cannot_be_merged')
- end
- end
-
- context 'when it has conflicts' do
- before do
- allow(subject).to receive(:broken?) { false }
- allow(project.repository).to receive(:can_be_merged?).and_return(false)
- end
-
- it 'becomes unmergeable' do
- expect { subject.check_if_can_be_merged }.to change { subject.merge_status }.to('cannot_be_merged')
- end
- end
- end
-
- context 'when merge_status is unchecked' do
- subject { create(:merge_request, source_project: project, merge_status: :unchecked) }
-
- it_behaves_like 'checking if can be merged'
- end
-
- context 'when merge_status is unchecked' do
- subject { create(:merge_request, source_project: project, merge_status: :cannot_be_merged_recheck) }
-
- it_behaves_like 'checking if can be merged'
- end
- end
-
describe '#mergeable?' do
let(:project) { create(:project) }
@@ -2060,7 +2009,7 @@ describe MergeRequest do
it 'return true if #mergeable_state? is true and the MR #can_be_merged? is true' do
allow(subject).to receive(:mergeable_state?) { true }
- expect(subject).to receive(:check_if_can_be_merged)
+ expect(subject).to receive(:check_mergeability)
expect(subject).to receive(:can_be_merged?) { true }
expect(subject.mergeable?).to be_truthy
@@ -2074,7 +2023,7 @@ describe MergeRequest do
it 'checks if merge request can be merged' do
allow(subject).to receive(:mergeable_ci_state?) { true }
- expect(subject).to receive(:check_if_can_be_merged)
+ expect(subject).to receive(:check_mergeability)
subject.mergeable?
end
@@ -3142,38 +3091,6 @@ describe MergeRequest do
end
end
- describe '#mergeable_to_ref?' do
- it 'returns true when merge request is mergeable' do
- subject = create(:merge_request)
-
- expect(subject.mergeable_to_ref?).to be(true)
- end
-
- it 'returns false when merge request is already merged' do
- subject = create(:merge_request, :merged)
-
- expect(subject.mergeable_to_ref?).to be(false)
- end
-
- it 'returns false when merge request is closed' do
- subject = create(:merge_request, :closed)
-
- expect(subject.mergeable_to_ref?).to be(false)
- end
-
- it 'returns false when merge request is work in progress' do
- subject = create(:merge_request, title: 'WIP: The feature')
-
- expect(subject.mergeable_to_ref?).to be(false)
- end
-
- it 'returns false when merge request has no commits' do
- subject = create(:merge_request, source_branch: 'empty-branch', target_branch: 'master')
-
- expect(subject.mergeable_to_ref?).to be(false)
- end
- end
-
describe '#merge_participants' do
it 'contains author' do
expect(subject.merge_participants).to eq([subject.author])
diff --git a/spec/models/pages_domain_spec.rb b/spec/models/pages_domain_spec.rb
index fdc81359d34..661957cf08b 100644
--- a/spec/models/pages_domain_spec.rb
+++ b/spec/models/pages_domain_spec.rb
@@ -356,6 +356,102 @@ describe PagesDomain do
end
end
+ describe '#user_provided_key' do
+ subject { domain.user_provided_key }
+
+ context 'when certificate is provided by user' do
+ let(:domain) { create(:pages_domain) }
+
+ it 'returns key' do
+ is_expected.to eq(domain.key)
+ end
+ end
+
+ context 'when certificate is provided by gitlab' do
+ let(:domain) { create(:pages_domain, :letsencrypt) }
+
+ it 'returns nil' do
+ is_expected.to be_nil
+ end
+ end
+ end
+
+ describe '#user_provided_certificate' do
+ subject { domain.user_provided_certificate }
+
+ context 'when certificate is provided by user' do
+ let(:domain) { create(:pages_domain) }
+
+ it 'returns key' do
+ is_expected.to eq(domain.certificate)
+ end
+ end
+
+ context 'when certificate is provided by gitlab' do
+ let(:domain) { create(:pages_domain, :letsencrypt) }
+
+ it 'returns nil' do
+ is_expected.to be_nil
+ end
+ end
+ end
+
+ shared_examples 'certificate setter' do |attribute, setter_name, old_certificate_source, new_certificate_source|
+ let(:domain) do
+ create(:pages_domain, certificate_source: old_certificate_source)
+ end
+
+ let(:old_value) { domain.public_send(attribute) }
+
+ subject { domain.public_send(setter_name, new_value) }
+
+ context 'when value has been changed' do
+ let(:new_value) { 'new_value' }
+
+ it "assignes new value to #{attribute}" do
+ expect do
+ subject
+ end.to change { domain.public_send(attribute) }.from(old_value).to('new_value')
+ end
+
+ it 'changes certificate source' do
+ expect do
+ subject
+ end.to change { domain.certificate_source }.from(old_certificate_source).to(new_certificate_source)
+ end
+ end
+
+ context 'when value has not been not changed' do
+ let(:new_value) { old_value }
+
+ it 'does not change certificate source' do
+ expect do
+ subject
+ end.not_to change { domain.certificate_source }.from(old_certificate_source)
+ end
+ end
+ end
+
+ describe '#user_provided_key=' do
+ include_examples('certificate setter', 'key', 'user_provided_key=',
+ 'gitlab_provided', 'user_provided')
+ end
+
+ describe '#gitlab_provided_key=' do
+ include_examples('certificate setter', 'key', 'gitlab_provided_key=',
+ 'user_provided', 'gitlab_provided')
+ end
+
+ describe '#user_provided_certificate=' do
+ include_examples('certificate setter', 'certificate', 'user_provided_certificate=',
+ 'gitlab_provided', 'user_provided')
+ end
+
+ describe '#gitlab_provided_certificate=' do
+ include_examples('certificate setter', 'certificate', 'gitlab_provided_certificate=',
+ 'user_provided', 'gitlab_provided')
+ end
+
describe '.for_removal' do
subject { described_class.for_removal }
@@ -383,4 +479,30 @@ describe PagesDomain do
end
end
end
+
+ describe '.need_auto_ssl_renewal' do
+ subject { described_class.need_auto_ssl_renewal }
+
+ let!(:domain_with_user_provided_certificate) { create(:pages_domain) }
+ let!(:domain_with_expired_user_provided_certificate) do
+ create(:pages_domain, :with_expired_certificate)
+ end
+ let!(:domain_with_user_provided_certificate_and_auto_ssl) do
+ create(:pages_domain, auto_ssl_enabled: true)
+ end
+
+ let!(:domain_with_gitlab_provided_certificate) { create(:pages_domain, :letsencrypt) }
+ let!(:domain_with_expired_gitlab_provided_certificate) do
+ create(:pages_domain, :letsencrypt, :with_expired_certificate)
+ end
+
+ it 'contains only domains needing verification' do
+ is_expected.to(
+ contain_exactly(
+ domain_with_user_provided_certificate_and_auto_ssl,
+ domain_with_expired_gitlab_provided_certificate
+ )
+ )
+ end
+ end
end
diff --git a/spec/models/project_services/teamcity_service_spec.rb b/spec/models/project_services/teamcity_service_spec.rb
index 1c434b25205..3d875bc49e7 100644
--- a/spec/models/project_services/teamcity_service_spec.rb
+++ b/spec/models/project_services/teamcity_service_spec.rb
@@ -7,10 +7,11 @@ describe TeamcityService, :use_clean_rails_memory_store_caching do
include StubRequests
let(:teamcity_url) { 'http://gitlab.com/teamcity' }
+ let(:project) { create(:project) }
subject(:service) do
described_class.create(
- project: create(:project),
+ project: project,
properties: {
teamcity_url: teamcity_url,
username: 'mic',
@@ -207,6 +208,97 @@ describe TeamcityService, :use_clean_rails_memory_store_caching do
end
end
+ describe '#execute' do
+ context 'when push' do
+ let(:data) do
+ {
+ object_kind: 'push',
+ ref: 'refs/heads/dev-123_branch',
+ after: '0220c11b9a3e6c69dc8fd35321254ca9a7b98f7e',
+ total_commits_count: 1
+ }
+ end
+
+ it 'handles push request correctly' do
+ stub_post_to_build_queue(branch: 'dev-123_branch')
+
+ expect(service.execute(data)).to include('Ok')
+ end
+
+ it 'returns nil when ref is blank' do
+ data[:after] = Gitlab::Git::BLANK_SHA
+
+ expect(service.execute(data)).to be_nil
+ end
+
+ it 'returns nil when there is no content' do
+ data[:total_commits_count] = 0
+
+ expect(service.execute(data)).to be_nil
+ end
+
+ it 'returns nil when a merge request is opened for the same ref' do
+ create(:merge_request, source_project: project, source_branch: 'dev-123_branch')
+
+ expect(service.execute(data)).to be_nil
+ end
+ end
+
+ context 'when merge_request' do
+ let(:data) do
+ {
+ object_kind: 'merge_request',
+ ref: 'refs/heads/dev-123_branch',
+ after: '0220c11b9a3e6c69dc8fd35321254ca9a7b98f7e',
+ total_commits_count: 1,
+ object_attributes: {
+ state: 'opened',
+ source_branch: 'dev-123_branch',
+ merge_status: 'unchecked'
+ }
+ }
+ end
+
+ it 'handles merge request correctly' do
+ stub_post_to_build_queue(branch: 'dev-123_branch')
+
+ expect(service.execute(data)).to include('Ok')
+ end
+
+ it 'returns nil when merge request is not opened' do
+ data[:object_attributes][:state] = 'closed'
+
+ expect(service.execute(data)).to be_nil
+ end
+
+ it 'returns nil unless merge request is marked as unchecked' do
+ data[:object_attributes][:merge_status] = 'can_be_merged'
+
+ expect(service.execute(data)).to be_nil
+ end
+ end
+
+ it 'returns nil when event is not supported' do
+ data = { object_kind: 'foo' }
+
+ expect(service.execute(data)).to be_nil
+ end
+ end
+
+ def stub_post_to_build_queue(branch:)
+ teamcity_full_url = 'http://gitlab.com/teamcity/httpAuth/app/rest/buildQueue'
+ body ||= %Q(<build branchName=\"#{branch}\"><buildType id=\"foo\"/></build>)
+ auth = %w(mic password)
+
+ stub_full_request(teamcity_full_url, method: :post).with(
+ basic_auth: auth,
+ body: body,
+ headers: {
+ 'Content-Type' => 'application/xml'
+ }
+ ).to_return(status: 200, body: 'Ok', headers: {})
+ end
+
def stub_request(status: 200, body: nil, build_status: 'success')
teamcity_full_url = 'http://gitlab.com/teamcity/httpAuth/app/rest/builds/branch:unspecified:any,revision:123'
auth = %w(mic password)
diff --git a/spec/requests/api/branches_spec.rb b/spec/requests/api/branches_spec.rb
index 8b503777443..f9c8b42afa8 100644
--- a/spec/requests/api/branches_spec.rb
+++ b/spec/requests/api/branches_spec.rb
@@ -65,7 +65,7 @@ describe API::Branches do
context 'when repository is disabled' do
include_context 'disabled repository'
- it_behaves_like '403 response' do
+ it_behaves_like '404 response' do
let(:request) { get api(route, current_user) }
end
end
@@ -175,7 +175,7 @@ describe API::Branches do
context 'when repository is disabled' do
include_context 'disabled repository'
- it_behaves_like '403 response' do
+ it_behaves_like '404 response' do
let(:request) { get api(route, current_user) }
end
end
@@ -337,7 +337,7 @@ describe API::Branches do
context 'when repository is disabled' do
include_context 'disabled repository'
- it_behaves_like '403 response' do
+ it_behaves_like '404 response' do
let(:request) { put api(route, current_user) }
end
end
@@ -471,7 +471,7 @@ describe API::Branches do
context 'when repository is disabled' do
include_context 'disabled repository'
- it_behaves_like '403 response' do
+ it_behaves_like '404 response' do
let(:request) { put api(route, current_user) }
end
end
@@ -547,7 +547,7 @@ describe API::Branches do
context 'when repository is disabled' do
include_context 'disabled repository'
- it_behaves_like '403 response' do
+ it_behaves_like '404 response' do
let(:request) { post api(route, current_user) }
end
end
diff --git a/spec/requests/api/commits_spec.rb b/spec/requests/api/commits_spec.rb
index f104da6ebba..3df5d9412f8 100644
--- a/spec/requests/api/commits_spec.rb
+++ b/spec/requests/api/commits_spec.rb
@@ -736,7 +736,7 @@ describe API::Commits do
context 'when repository is disabled' do
include_context 'disabled repository'
- it_behaves_like '403 response' do
+ it_behaves_like '404 response' do
let(:request) { get api(route, current_user) }
end
end
@@ -825,7 +825,7 @@ describe API::Commits do
context 'when repository is disabled' do
include_context 'disabled repository'
- it_behaves_like '403 response' do
+ it_behaves_like '404 response' do
let(:request) { get api(route, current_user) }
end
end
@@ -968,7 +968,7 @@ describe API::Commits do
context 'when repository is disabled' do
include_context 'disabled repository'
- it_behaves_like '403 response' do
+ it_behaves_like '404 response' do
let(:request) { get api(route, current_user) }
end
end
@@ -1067,7 +1067,7 @@ describe API::Commits do
context 'when repository is disabled' do
include_context 'disabled repository'
- it_behaves_like '403 response' do
+ it_behaves_like '404 response' do
let(:request) { get api(route, current_user) }
end
end
@@ -1169,7 +1169,7 @@ describe API::Commits do
context 'when repository is disabled' do
include_context 'disabled repository'
- it_behaves_like '403 response' do
+ it_behaves_like '404 response' do
let(:request) { post api(route, current_user), params: { branch: 'master' } }
end
end
@@ -1324,7 +1324,7 @@ describe API::Commits do
context 'when repository is disabled' do
include_context 'disabled repository'
- it_behaves_like '403 response' do
+ it_behaves_like '404 response' do
let(:request) { post api(route, current_user), params: { branch: branch } }
end
end
@@ -1435,7 +1435,7 @@ describe API::Commits do
context 'when repository is disabled' do
include_context 'disabled repository'
- it_behaves_like '403 response' do
+ it_behaves_like '404 response' do
let(:request) { post api(route, current_user), params: { note: 'My comment' } }
end
end
diff --git a/spec/requests/api/environments_spec.rb b/spec/requests/api/environments_spec.rb
index 8fc7fdc8632..745f3c55ac8 100644
--- a/spec/requests/api/environments_spec.rb
+++ b/spec/requests/api/environments_spec.rb
@@ -34,6 +34,47 @@ describe API::Environments do
expect(json_response.first['project'].keys).to contain_exactly(*project_data_keys)
expect(json_response.first).not_to have_key("last_deployment")
end
+
+ context 'when filtering' do
+ let!(:environment2) { create(:environment, project: project) }
+
+ it 'returns environment by name' do
+ get api("/projects/#{project.id}/environments?name=#{environment.name}", user)
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(response).to include_pagination_headers
+ expect(json_response).to be_an Array
+ expect(json_response.size).to eq(1)
+ expect(json_response.first['name']).to eq(environment.name)
+ end
+
+ it 'returns no environment by non-existent name' do
+ get api("/projects/#{project.id}/environments?name=test", user)
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(response).to include_pagination_headers
+ expect(json_response).to be_an Array
+ expect(json_response.size).to eq(0)
+ end
+
+ it 'returns environments by name_like' do
+ get api("/projects/#{project.id}/environments?search=envir", user)
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(response).to include_pagination_headers
+ expect(json_response).to be_an Array
+ expect(json_response.size).to eq(2)
+ end
+
+ it 'returns no environment by non-existent name_like' do
+ get api("/projects/#{project.id}/environments?search=test", user)
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(response).to include_pagination_headers
+ expect(json_response).to be_an Array
+ expect(json_response.size).to eq(0)
+ end
+ end
end
context 'as non member' do
diff --git a/spec/requests/api/merge_requests_spec.rb b/spec/requests/api/merge_requests_spec.rb
index 9f9180bc8c9..76d093e0774 100644
--- a/spec/requests/api/merge_requests_spec.rb
+++ b/spec/requests/api/merge_requests_spec.rb
@@ -1546,52 +1546,80 @@ describe API::MergeRequests do
end
end
- describe "PUT /projects/:id/merge_requests/:merge_request_iid/merge_to_ref" do
- let(:pipeline) { create(:ci_pipeline_without_jobs) }
+ describe "GET /projects/:id/merge_requests/:merge_request_iid/merge_ref" do
+ before do
+ merge_request.mark_as_unchecked!
+ end
+
+ let(:merge_request_iid) { merge_request.iid }
+
let(:url) do
- "/projects/#{project.id}/merge_requests/#{merge_request.iid}/merge_to_ref"
+ "/projects/#{project.id}/merge_requests/#{merge_request_iid}/merge_ref"
end
it 'returns the generated ID from the merge service in case of success' do
- put api(url, user), params: { merge_commit_message: 'Custom message' }
-
- commit = project.commit(json_response['commit_id'])
+ get api(url, user)
expect(response).to have_gitlab_http_status(200)
- expect(json_response['commit_id']).to be_present
- expect(commit.message).to eq('Custom message')
+ expect(json_response['commit_id']).to eq(merge_request.merge_ref_head.sha)
end
- it "returns 400 if branch can't be merged" do
- merge_request.update!(state: 'merged')
+ context 'when merge-ref is not synced with merge status' do
+ before do
+ merge_request.update!(merge_status: 'cannot_be_merged')
+ end
- put api(url, user)
+ it 'returns 200 if MR can be merged' do
+ get api(url, user)
- expect(response).to have_gitlab_http_status(400)
- expect(json_response['message'])
- .to eq("Merge request is not mergeable to #{merge_request.merge_ref_path}")
+ expect(response).to have_gitlab_http_status(200)
+ expect(json_response['commit_id']).to eq(merge_request.merge_ref_head.sha)
+ end
+
+ it 'returns 400 if MR cannot be merged' do
+ expect_next_instance_of(MergeRequests::MergeToRefService) do |merge_request|
+ expect(merge_request).to receive(:execute) { { status: :failed } }
+ end
+
+ get api(url, user)
+
+ expect(response).to have_gitlab_http_status(400)
+ expect(json_response['message']).to eq('Merge request is not mergeable')
+ end
end
- it 'returns 403 if user has no permissions to merge to the ref' do
- user2 = create(:user)
- project.add_reporter(user2)
+ context 'when user has no access to the MR' do
+ let(:project) { create(:project, :private) }
+ let(:merge_request) { create(:merge_request, source_project: project, target_project: project) }
- put api(url, user2)
+ it 'returns 404' do
+ project.add_guest(user)
- expect(response).to have_gitlab_http_status(403)
- expect(json_response['message']).to eq('403 Forbidden')
+ get api(url, user)
+
+ expect(response).to have_gitlab_http_status(404)
+ expect(json_response['message']).to eq('404 Not found')
+ end
end
- it 'returns 404 for an invalid merge request IID' do
- put api("/projects/#{project.id}/merge_requests/12345/merge_to_ref", user)
+ context 'when invalid merge request IID' do
+ let(:merge_request_iid) { '12345' }
- expect(response).to have_gitlab_http_status(404)
+ it 'returns 404' do
+ get api(url, user)
+
+ expect(response).to have_gitlab_http_status(404)
+ end
end
- it "returns 404 if the merge request id is used instead of iid" do
- put api("/projects/#{project.id}/merge_requests/#{merge_request.id}/merge", user)
+ context 'when merge request ID is used instead IID' do
+ let(:merge_request_iid) { merge_request.id }
- expect(response).to have_gitlab_http_status(404)
+ it 'returns 404' do
+ get api(url, user)
+
+ expect(response).to have_gitlab_http_status(404)
+ end
end
end
diff --git a/spec/requests/api/pages_domains_spec.rb b/spec/requests/api/pages_domains_spec.rb
index 3eb68a6abb6..449032b95b7 100644
--- a/spec/requests/api/pages_domains_spec.rb
+++ b/spec/requests/api/pages_domains_spec.rb
@@ -359,6 +359,14 @@ describe API::PagesDomains do
expect(pages_domain_secure.certificate).to eq(params_secure_nokey[:certificate])
end
+ it 'updates certificate source to user_provided if is changed' do
+ pages_domain.update!(certificate_source: 'gitlab_provided')
+
+ expect do
+ put api(route_domain, user), params: params_secure
+ end.to change { pages_domain.reload.certificate_source }.from('gitlab_provided').to('user_provided')
+ end
+
it 'fails to update pages domain adding certificate without key' do
put api(route_domain, user), params: params_secure_nokey
diff --git a/spec/services/clusters/gcp/finalize_creation_service_spec.rb b/spec/services/clusters/gcp/finalize_creation_service_spec.rb
index 2664649df47..5f91acb8e84 100644
--- a/spec/services/clusters/gcp/finalize_creation_service_spec.rb
+++ b/spec/services/clusters/gcp/finalize_creation_service_spec.rb
@@ -19,10 +19,6 @@ describe Clusters::Gcp::FinalizeCreationService, '#execute' do
subject { described_class.new.execute(provider) }
- before do
- allow(ClusterConfigureWorker).to receive(:perform_async)
- end
-
shared_examples 'success' do
it 'configures provider and kubernetes' do
subject
@@ -42,12 +38,6 @@ describe Clusters::Gcp::FinalizeCreationService, '#execute' do
expect(platform.password).to eq(password)
expect(platform.token).to eq(token)
end
-
- it 'calls ClusterConfigureWorker in a ascync fashion' do
- expect(ClusterConfigureWorker).to receive(:perform_async).with(cluster.id)
-
- subject
- end
end
shared_examples 'error' do
diff --git a/spec/services/clusters/gcp/kubernetes/fetch_kubernetes_token_service_spec.rb b/spec/services/clusters/gcp/kubernetes/fetch_kubernetes_token_service_spec.rb
index a5806559b14..93c0dc37ade 100644
--- a/spec/services/clusters/gcp/kubernetes/fetch_kubernetes_token_service_spec.rb
+++ b/spec/services/clusters/gcp/kubernetes/fetch_kubernetes_token_service_spec.rb
@@ -17,7 +17,7 @@ describe Clusters::Gcp::Kubernetes::FetchKubernetesTokenService do
)
end
- subject { described_class.new(kubeclient, service_account_token_name, namespace).execute }
+ subject { described_class.new(kubeclient, service_account_token_name, namespace, token_retry_delay: 0).execute }
before do
stub_kubeclient_discover(api_url)
@@ -26,8 +26,7 @@ describe Clusters::Gcp::Kubernetes::FetchKubernetesTokenService do
context 'when params correct' do
let(:decoded_token) { 'xxx.token.xxx' }
let(:token) { Base64.encode64(decoded_token) }
-
- context 'when gitlab-token exists' do
+ context 'when the secret exists' do
before do
stub_kubeclient_get_secret(
api_url,
@@ -50,13 +49,62 @@ describe Clusters::Gcp::Kubernetes::FetchKubernetesTokenService do
it { expect { subject }.to raise_error(Kubeclient::HttpError) }
end
- context 'when gitlab-token does not exist' do
+ context 'when the secret does not exist on the first try' do
+ before do
+ stub_kubeclient_get_secret_not_found_then_found(
+ api_url,
+ {
+ metadata_name: service_account_token_name,
+ namespace: namespace,
+ token: token
+ }
+ )
+ end
+
+ it 'retries and finds the token' do
+ expect(subject).to eq(decoded_token)
+ end
+ end
+
+ context 'when the secret permanently does not exist' do
before do
stub_kubeclient_get_secret_error(api_url, service_account_token_name, namespace: namespace, status: 404)
end
it { is_expected.to be_nil }
end
+
+ context 'when the secret is missing a token on the first try' do
+ before do
+ stub_kubeclient_get_secret_missing_token_then_with_token(
+ api_url,
+ {
+ metadata_name: service_account_token_name,
+ namespace: namespace,
+ token: token
+ }
+ )
+ end
+
+ it 'retries and finds the token' do
+ expect(subject).to eq(decoded_token)
+ end
+ end
+
+ context 'when the secret is permanently missing a token' do
+ before do
+ stub_kubeclient_get_secret(
+ api_url,
+ {
+ metadata_name: service_account_token_name,
+ namespace: namespace,
+ token: nil
+ }
+ )
+ end
+
+ it { is_expected.to be_nil }
+ end
end
end
end
diff --git a/spec/services/clusters/update_service_spec.rb b/spec/services/clusters/update_service_spec.rb
index 21b37f88fd8..3ee45375dca 100644
--- a/spec/services/clusters/update_service_spec.rb
+++ b/spec/services/clusters/update_service_spec.rb
@@ -39,7 +39,6 @@ describe Clusters::UpdateService do
end
before do
- allow(ClusterConfigureWorker).to receive(:perform_async)
stub_kubeclient_get_namespace('https://kubernetes.example.com', namespace: 'my-namespace')
end
diff --git a/spec/services/issues/reorder_service_spec.rb b/spec/services/issues/reorder_service_spec.rb
new file mode 100644
index 00000000000..b147cdf4e64
--- /dev/null
+++ b/spec/services/issues/reorder_service_spec.rb
@@ -0,0 +1,88 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Issues::ReorderService do
+ set(:user) { create(:user) }
+ set(:project) { create(:project) }
+ set(:group) { create(:group) }
+
+ shared_examples 'issues reorder service' do
+ context 'when reordering issues' do
+ it 'returns false with no params' do
+ expect(service({}).execute(issue1)).to be_falsey
+ end
+
+ it 'returns false with both invalid params' do
+ params = { move_after_id: nil, move_before_id: 1 }
+
+ expect(service(params).execute(issue1)).to be_falsey
+ end
+
+ it 'sorts issues' do
+ params = { move_after_id: issue2.id, move_before_id: issue3.id }
+
+ service(params).execute(issue1)
+
+ expect(issue1.relative_position)
+ .to be_between(issue2.relative_position, issue3.relative_position)
+ end
+ end
+ end
+
+ describe '#execute' do
+ let(:issue1) { create(:issue, project: project, relative_position: 10) }
+ let(:issue2) { create(:issue, project: project, relative_position: 20) }
+ let(:issue3) { create(:issue, project: project, relative_position: 30) }
+
+ context 'when ordering issues in a project' do
+ let(:parent) { project }
+
+ before do
+ parent.add_developer(user)
+ end
+
+ it_behaves_like 'issues reorder service'
+ end
+
+ context 'when ordering issues in a group' do
+ let(:project) { create(:project, namespace: group) }
+
+ before do
+ group.add_developer(user)
+ end
+
+ it_behaves_like 'issues reorder service'
+
+ context 'when ordering in a group issue list' do
+ let(:params) { { move_after_id: issue2.id, move_before_id: issue3.id, group_full_path: group.full_path } }
+
+ subject { service(params) }
+
+ it 'sends the board_group_id parameter' do
+ match_params = { move_between_ids: [issue2.id, issue3.id], board_group_id: group.id }
+
+ expect(Issues::UpdateService)
+ .to receive(:new).with(project, user, match_params)
+ .and_return(double(execute: build(:issue)))
+
+ subject.execute(issue1)
+ end
+
+ it 'sorts issues' do
+ project2 = create(:project, namespace: group)
+ issue4 = create(:issue, project: project2)
+
+ subject.execute(issue4)
+
+ expect(issue4.relative_position)
+ .to be_between(issue2.relative_position, issue3.relative_position)
+ end
+ end
+ end
+ end
+
+ def service(params)
+ described_class.new(project, user, params)
+ end
+end
diff --git a/spec/services/issues/update_service_spec.rb b/spec/services/issues/update_service_spec.rb
index 22f5607cb9c..28fa5d12d9c 100644
--- a/spec/services/issues/update_service_spec.rb
+++ b/spec/services/issues/update_service_spec.rb
@@ -687,6 +687,22 @@ describe Issues::UpdateService, :mailer do
end
end
+ context 'when moving an issue ', :nested_groups do
+ it 'raises an error for invalid move ids within a project' do
+ opts = { move_between_ids: [9000, 9999] }
+
+ expect { described_class.new(issue.project, user, opts).execute(issue) }
+ .to raise_error(ActiveRecord::RecordNotFound)
+ end
+
+ it 'raises an error for invalid move ids within a group' do
+ opts = { move_between_ids: [9000, 9999], board_group_id: create(:group).id }
+
+ expect { described_class.new(issue.project, user, opts).execute(issue) }
+ .to raise_error(ActiveRecord::RecordNotFound)
+ end
+ end
+
include_examples 'issuable update service' do
let(:open_issuable) { issue }
let(:closed_issuable) { create(:closed_issue, project: project) }
diff --git a/spec/services/merge_requests/merge_to_ref_service_spec.rb b/spec/services/merge_requests/merge_to_ref_service_spec.rb
index 0ac23050caf..61f99f82a76 100644
--- a/spec/services/merge_requests/merge_to_ref_service_spec.rb
+++ b/spec/services/merge_requests/merge_to_ref_service_spec.rb
@@ -72,10 +72,6 @@ describe MergeRequests::MergeToRefService do
let(:merge_request) { create(:merge_request, :simple) }
let(:project) { merge_request.project }
- before do
- project.add_maintainer(user)
- end
-
describe '#execute' do
let(:service) do
described_class.new(project, user, commit_message: 'Awesome message',
@@ -92,6 +88,12 @@ describe MergeRequests::MergeToRefService do
it_behaves_like 'successfully evaluates pre-condition checks'
context 'commit history comparison with regular MergeService' do
+ before do
+ # The merge service needs an authorized user while merge-to-ref
+ # doesn't.
+ project.add_maintainer(user)
+ end
+
let(:merge_ref_service) do
described_class.new(project, user, {})
end
@@ -104,12 +106,18 @@ describe MergeRequests::MergeToRefService do
it_behaves_like 'MergeService for target ref'
end
- context 'when merge commit with squash', :quarantine do
+ context 'when merge commit with squash' do
before do
- merge_request.update!(squash: true, source_branch: 'master', target_branch: 'feature')
+ merge_request.update!(squash: true)
end
it_behaves_like 'MergeService for target ref'
+
+ it 'does not squash before merging' do
+ expect(MergeRequests::SquashService).not_to receive(:new)
+
+ process_merge_to_ref
+ end
end
end
@@ -136,9 +144,9 @@ describe MergeRequests::MergeToRefService do
let(:merge_method) { :merge }
it 'returns error' do
- allow(merge_request).to receive(:mergeable_to_ref?) { false }
+ allow(project).to receive_message_chain(:repository, :merge_to_ref) { nil }
- error_message = "Merge request is not mergeable to #{merge_request.merge_ref_path}"
+ error_message = 'Conflicts detected during merge'
result = service.execute(merge_request)
@@ -170,28 +178,5 @@ describe MergeRequests::MergeToRefService do
it { expect(todo).not_to be_done }
end
-
- context 'when merge request is WIP state' do
- it 'fails to merge' do
- merge_request = create(:merge_request, title: 'WIP: The feature')
-
- result = service.execute(merge_request)
-
- expect(result[:status]).to eq(:error)
- expect(result[:message]).to eq("Merge request is not mergeable to #{merge_request.merge_ref_path}")
- end
- end
-
- it 'returns error when user has no authorization to admin the merge request' do
- unauthorized_user = create(:user)
- project.add_reporter(unauthorized_user)
-
- service = described_class.new(project, unauthorized_user)
-
- result = service.execute(merge_request)
-
- expect(result[:status]).to eq(:error)
- expect(result[:message]).to eq('You are not allowed to merge to this ref')
- end
end
end
diff --git a/spec/services/merge_requests/mergeability_check_service_spec.rb b/spec/services/merge_requests/mergeability_check_service_spec.rb
new file mode 100644
index 00000000000..6efece64092
--- /dev/null
+++ b/spec/services/merge_requests/mergeability_check_service_spec.rb
@@ -0,0 +1,285 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe MergeRequests::MergeabilityCheckService do
+ shared_examples_for 'unmergeable merge request' do
+ it 'updates or keeps merge status as cannot_be_merged' do
+ subject
+
+ expect(merge_request.merge_status).to eq('cannot_be_merged')
+ end
+
+ it 'does not change the merge ref HEAD' do
+ expect { subject }.not_to change(merge_request, :merge_ref_head)
+ end
+
+ it 'returns ServiceResponse.error' do
+ result = subject
+
+ expect(result).to be_a(ServiceResponse)
+ expect(result).to be_error
+ end
+ end
+
+ shared_examples_for 'mergeable merge request' do
+ it 'updates or keeps merge status as can_be_merged' do
+ subject
+
+ expect(merge_request.merge_status).to eq('can_be_merged')
+ end
+
+ it 'updates the merge ref' do
+ expect { subject }.to change(merge_request, :merge_ref_head).from(nil)
+ end
+
+ it 'returns ServiceResponse.success' do
+ result = subject
+
+ expect(result).to be_a(ServiceResponse)
+ expect(result).to be_success
+ end
+
+ it 'ServiceResponse has merge_ref_head payload' do
+ result = subject
+
+ expect(result.payload.keys).to contain_exactly(:merge_ref_head)
+ expect(result.payload[:merge_ref_head].keys)
+ .to contain_exactly(:commit_id, :target_id, :source_id)
+ end
+ end
+
+ describe '#execute' do
+ let(:project) { create(:project, :repository) }
+ let(:merge_request) { create(:merge_request, merge_status: :unchecked, source_project: project, target_project: project) }
+ let(:repo) { project.repository }
+
+ subject { described_class.new(merge_request).execute }
+
+ before do
+ project.add_developer(merge_request.author)
+ end
+
+ it_behaves_like 'mergeable merge request'
+
+ context 'when multiple calls to the service' do
+ it 'returns success' do
+ subject
+ result = subject
+
+ expect(result).to be_a(ServiceResponse)
+ expect(result.success?).to be(true)
+ end
+
+ it 'second call does not change the merge-ref' do
+ expect { subject }.to change(merge_request, :merge_ref_head).from(nil)
+ expect { subject }.not_to change(merge_request, :merge_ref_head)
+ end
+ end
+
+ context 'disabled merge ref sync feature flag' do
+ before do
+ stub_feature_flags(merge_ref_auto_sync: false)
+ end
+
+ it 'returns error and no payload' do
+ result = subject
+
+ expect(result).to be_a(ServiceResponse)
+ expect(result.error?).to be(true)
+ expect(result.message).to eq('Merge ref is outdated due to disabled feature')
+ expect(result.payload).to be_empty
+ end
+
+ it 'ignores merge-ref and updates merge status' do
+ expect { subject }.to change(merge_request, :merge_status).from('unchecked').to('can_be_merged')
+ end
+ end
+
+ context 'when broken' do
+ before do
+ allow(merge_request).to receive(:broken?) { true }
+ allow(project.repository).to receive(:can_be_merged?) { false }
+ end
+
+ it_behaves_like 'unmergeable merge request'
+
+ it 'returns ServiceResponse.error' do
+ result = subject
+
+ expect(result).to be_a(ServiceResponse)
+ expect(result.error?).to be(true)
+ expect(result.message).to eq('Merge request is not mergeable')
+ end
+ end
+
+ context 'when it has conflicts' do
+ before do
+ allow(merge_request).to receive(:broken?) { false }
+ allow(project.repository).to receive(:can_be_merged?) { false }
+ end
+
+ it_behaves_like 'unmergeable merge request'
+
+ it 'returns ServiceResponse.error' do
+ result = subject
+
+ expect(result).to be_a(ServiceResponse)
+ expect(result.error?).to be(true)
+ expect(result.message).to eq('Merge request is not mergeable')
+ end
+ end
+
+ context 'when MR cannot be merged and has no merge ref' do
+ before do
+ merge_request.mark_as_unmergeable!
+ end
+
+ it_behaves_like 'unmergeable merge request'
+
+ it 'returns ServiceResponse.error' do
+ result = subject
+
+ expect(result).to be_a(ServiceResponse)
+ expect(result.error?).to be(true)
+ expect(result.message).to eq('Merge request is not mergeable')
+ end
+ end
+
+ context 'when MR cannot be merged and has outdated merge ref' do
+ before do
+ MergeRequests::MergeToRefService.new(project, merge_request.author).execute(merge_request)
+ merge_request.mark_as_unmergeable!
+ end
+
+ it_behaves_like 'unmergeable merge request'
+
+ it 'returns ServiceResponse.error' do
+ result = subject
+
+ expect(result).to be_a(ServiceResponse)
+ expect(result.error?).to be(true)
+ expect(result.message).to eq('Merge request is not mergeable')
+ end
+ end
+
+ context 'when merge request is not given' do
+ subject { described_class.new(nil).execute }
+
+ it 'returns ServiceResponse.error' do
+ result = subject
+
+ expect(result).to be_a(ServiceResponse)
+ expect(result.message).to eq('Invalid argument')
+ end
+ end
+
+ context 'when read only DB' do
+ it 'returns ServiceResponse.error' do
+ allow(Gitlab::Database).to receive(:read_only?) { true }
+
+ result = subject
+
+ expect(result).to be_a(ServiceResponse)
+ expect(result.message).to eq('Unsupported operation')
+ end
+ end
+
+ context 'when fails to update the merge-ref' do
+ before do
+ expect_next_instance_of(MergeRequests::MergeToRefService) do |merge_to_ref|
+ expect(merge_to_ref).to receive(:execute).and_return(status: :failed)
+ end
+ end
+
+ it_behaves_like 'unmergeable merge request'
+
+ it 'returns ServiceResponse.error' do
+ result = subject
+
+ expect(result).to be_a(ServiceResponse)
+ expect(result.error?).to be(true)
+ expect(result.message).to eq('Merge request is not mergeable')
+ end
+ end
+
+ context 'recheck enforced' do
+ subject { described_class.new(merge_request).execute(recheck: true) }
+
+ context 'when MR is mergeable and merge-ref auto-sync is disabled' do
+ before do
+ stub_feature_flags(merge_ref_auto_sync: false)
+ merge_request.mark_as_mergeable!
+ end
+
+ it 'returns ServiceResponse.error' do
+ result = subject
+
+ expect(result).to be_a(ServiceResponse)
+ expect(result.error?).to be(true)
+ expect(result.message).to eq('Merge ref is outdated due to disabled feature')
+ expect(result.payload).to be_empty
+ end
+
+ it 'merge status is not changed' do
+ subject
+
+ expect(merge_request.merge_status).to eq('can_be_merged')
+ end
+ end
+
+ context 'when MR is marked as mergeable, but repo is not mergeable and MR is not opened' do
+ before do
+ # Making sure that we don't touch the merge-status after
+ # the MR is not opened any longer. Source branch might
+ # have been removed, etc.
+ allow(merge_request).to receive(:broken?) { true }
+ merge_request.mark_as_mergeable!
+ merge_request.close!
+ end
+
+ it 'returns ServiceResponse.error' do
+ result = subject
+
+ expect(result).to be_a(ServiceResponse)
+ expect(result.error?).to be(true)
+ expect(result.message).to eq('Merge ref cannot be updated')
+ expect(result.payload).to be_empty
+ end
+
+ it 'does not change the merge status' do
+ expect { subject }.not_to change(merge_request, :merge_status).from('can_be_merged')
+ end
+ end
+
+ context 'when MR is mergeable but merge-ref does not exists' do
+ before do
+ merge_request.mark_as_mergeable!
+ end
+
+ it_behaves_like 'mergeable merge request'
+ end
+
+ context 'when MR is mergeable but merge-ref is already updated' do
+ before do
+ MergeRequests::MergeToRefService.new(project, merge_request.author).execute(merge_request)
+ merge_request.mark_as_mergeable!
+ end
+
+ it 'returns ServiceResponse.success' do
+ result = subject
+
+ expect(result).to be_a(ServiceResponse)
+ expect(result).to be_success
+ expect(result.payload[:merge_ref_head]).to be_present
+ end
+
+ it 'does not recreate the merge-ref' do
+ expect(MergeRequests::MergeToRefService).not_to receive(:new)
+
+ subject
+ end
+ end
+ end
+ end
+end
diff --git a/spec/services/pages_domains/obtain_lets_encrypt_certificate_service_spec.rb b/spec/services/pages_domains/obtain_lets_encrypt_certificate_service_spec.rb
index 6d7be27939c..d5f77f3354b 100644
--- a/spec/services/pages_domains/obtain_lets_encrypt_certificate_service_spec.rb
+++ b/spec/services/pages_domains/obtain_lets_encrypt_certificate_service_spec.rb
@@ -137,6 +137,12 @@ describe PagesDomains::ObtainLetsEncryptCertificateService do
expect(pages_domain.certificate).to eq(certificate)
end
+ it 'marks certificate as gitlab_provided' do
+ service.execute
+
+ expect(pages_domain.certificate_source).to eq("gitlab_provided")
+ end
+
it 'removes order from database' do
service.execute
diff --git a/spec/services/service_response_spec.rb b/spec/services/service_response_spec.rb
index 30bd4d6820b..e790d272e61 100644
--- a/spec/services/service_response_spec.rb
+++ b/spec/services/service_response_spec.rb
@@ -16,6 +16,13 @@ describe ServiceResponse do
expect(response).to be_success
expect(response.message).to eq('Good orange')
end
+
+ it 'creates a successful response with payload' do
+ response = described_class.success(payload: { good: 'orange' })
+
+ expect(response).to be_success
+ expect(response.payload).to eq(good: 'orange')
+ end
end
describe '.error' do
@@ -33,6 +40,15 @@ describe ServiceResponse do
expect(response.message).to eq('Bad apple')
expect(response.http_status).to eq(400)
end
+
+ it 'creates a failed response with payload' do
+ response = described_class.error(message: 'Bad apple',
+ payload: { bad: 'apple' })
+
+ expect(response).to be_error
+ expect(response.message).to eq('Bad apple')
+ expect(response.payload).to eq(bad: 'apple')
+ end
end
describe '#success?' do
diff --git a/spec/services/system_note_service_spec.rb b/spec/services/system_note_service_spec.rb
index 2420817e1f7..30a867fa7ba 100644
--- a/spec/services/system_note_service_spec.rb
+++ b/spec/services/system_note_service_spec.rb
@@ -946,6 +946,18 @@ describe SystemNoteService do
expect(subject.note).to eq "changed time estimate to 1w 4d 5h"
end
+
+ context 'when time_tracking_limit_to_hours setting is true' do
+ before do
+ stub_application_setting(time_tracking_limit_to_hours: true)
+ end
+
+ it 'sets the note text' do
+ noteable.update_attribute(:time_estimate, 277200)
+
+ expect(subject.note).to eq "changed time estimate to 77h"
+ end
+ end
end
context 'without a time estimate' do
@@ -1022,6 +1034,18 @@ describe SystemNoteService do
end
end
+ context 'when time_tracking_limit_to_hours setting is true' do
+ before do
+ stub_application_setting(time_tracking_limit_to_hours: true)
+ end
+
+ it 'sets the note text' do
+ spend_time!(277200)
+
+ expect(subject.note).to eq "added 77h of time spent"
+ end
+ end
+
def spend_time!(seconds)
noteable.spend_time(duration: seconds, user_id: author.id)
noteable.save!
diff --git a/spec/support/helpers/email_helpers.rb b/spec/support/helpers/email_helpers.rb
index ed049daba80..a7175491fa0 100644
--- a/spec/support/helpers/email_helpers.rb
+++ b/spec/support/helpers/email_helpers.rb
@@ -37,8 +37,19 @@ module EmailHelpers
ActionMailer::Base.deliveries.find { |d| d.to.include?(user.notification_email) }
end
- def have_referable_subject(referable, include_project: true, reply: false)
- prefix = (include_project && referable.project ? "#{referable.project.name} | " : '').freeze
+ def have_referable_subject(referable, include_project: true, include_group: false, reply: false)
+ context = []
+
+ context << referable.project.name if include_project && referable.project
+ context << referable.project.group.name if include_group && referable.project.group
+
+ prefix =
+ if context.any?
+ context.join(' | ') + ' | '
+ else
+ ''
+ end
+
prefix = "Re: #{prefix}" if reply
suffix = "#{referable.title} (#{referable.to_reference})"
diff --git a/spec/support/helpers/kubernetes_helpers.rb b/spec/support/helpers/kubernetes_helpers.rb
index 011c4df0fe5..3c7bcba2b42 100644
--- a/spec/support/helpers/kubernetes_helpers.rb
+++ b/spec/support/helpers/kubernetes_helpers.rb
@@ -104,6 +104,26 @@ module KubernetesHelpers
.to_return(status: [status, "Internal Server Error"])
end
+ def stub_kubeclient_get_secret_not_found_then_found(api_url, **options)
+ options[:metadata_name] ||= "default-token-1"
+ options[:namespace] ||= "default"
+
+ WebMock.stub_request(:get, api_url + "/api/v1/namespaces/#{options[:namespace]}/secrets/#{options[:metadata_name]}")
+ .to_return(status: [404, "Not Found"])
+ .then
+ .to_return(kube_response(kube_v1_secret_body(options)))
+ end
+
+ def stub_kubeclient_get_secret_missing_token_then_with_token(api_url, **options)
+ options[:metadata_name] ||= "default-token-1"
+ options[:namespace] ||= "default"
+
+ WebMock.stub_request(:get, api_url + "/api/v1/namespaces/#{options[:namespace]}/secrets/#{options[:metadata_name]}")
+ .to_return(kube_response(kube_v1_secret_body(options.merge(token: nil))))
+ .then
+ .to_return(kube_response(kube_v1_secret_body(options)))
+ end
+
def stub_kubeclient_get_service_account(api_url, name, namespace: 'default')
WebMock.stub_request(:get, api_url + "/api/v1/namespaces/#{namespace}/serviceaccounts/#{name}")
.to_return(kube_response({}))
@@ -184,11 +204,11 @@ module KubernetesHelpers
"kind" => "SecretList",
"apiVersion": "v1",
"metadata": {
- "name": options[:metadata_name] || "default-token-1",
+ "name": options.fetch(:metadata_name, "default-token-1"),
"namespace": "kube-system"
},
"data": {
- "token": options[:token] || Base64.encode64('token-sample-123')
+ "token": options.fetch(:token, Base64.encode64('token-sample-123'))
}
}
end
diff --git a/spec/support/shared_examples/notify_shared_examples.rb b/spec/support/shared_examples/notify_shared_examples.rb
index 897c9106d77..e64c7e37a0c 100644
--- a/spec/support/shared_examples/notify_shared_examples.rb
+++ b/spec/support/shared_examples/notify_shared_examples.rb
@@ -45,18 +45,18 @@ shared_examples 'an email sent to a user' do
let(:group_notification_email) { 'user+group@example.com' }
it 'is sent to user\'s global notification email address' do
- expect(subject).to deliver_to(test_recipient.notification_email)
+ expect(subject).to deliver_to(recipient.notification_email)
end
context 'that is part of a project\'s group' do
it 'is sent to user\'s group notification email address when set' do
- create(:notification_setting, user: test_recipient, source: project.group, notification_email: group_notification_email)
+ create(:notification_setting, user: recipient, source: project.group, notification_email: group_notification_email)
expect(subject).to deliver_to(group_notification_email)
end
it 'is sent to user\'s global notification email address when no group email set' do
- create(:notification_setting, user: test_recipient, source: project.group, notification_email: '')
- expect(subject).to deliver_to(test_recipient.notification_email)
+ create(:notification_setting, user: recipient, source: project.group, notification_email: '')
+ expect(subject).to deliver_to(recipient.notification_email)
end
end
@@ -67,17 +67,17 @@ shared_examples 'an email sent to a user' do
it 'is sent to user\'s subgroup notification email address when set' do
# Set top-level group notification email address to make sure it doesn't get selected
- create(:notification_setting, user: test_recipient, source: group, notification_email: group_notification_email)
+ create(:notification_setting, user: recipient, source: group, notification_email: group_notification_email)
subgroup_notification_email = 'user+subgroup@example.com'
- create(:notification_setting, user: test_recipient, source: subgroup, notification_email: subgroup_notification_email)
+ create(:notification_setting, user: recipient, source: subgroup, notification_email: subgroup_notification_email)
expect(subject).to deliver_to(subgroup_notification_email)
end
it 'is sent to user\'s group notification email address when set and subgroup email address not set' do
- create(:notification_setting, user: test_recipient, source: subgroup, notification_email: '')
- expect(subject).to deliver_to(test_recipient.notification_email)
+ create(:notification_setting, user: recipient, source: subgroup, notification_email: '')
+ expect(subject).to deliver_to(recipient.notification_email)
end
end
end
@@ -281,18 +281,8 @@ shared_examples 'a note email' do
is_expected.to have_body_text note.note
end
- it 'does not contain note author' do
- is_expected.not_to have_body_text note.author_name
- end
-
- context 'when enabled email_author_in_body' do
- before do
- stub_application_setting(email_author_in_body: true)
- end
-
- it 'contains a link to note author' do
- is_expected.to have_body_text note.author_name
- end
+ it 'contains a link to note author' do
+ is_expected.to have_body_text note.author_name
end
end
diff --git a/spec/tasks/gitlab/check_rake_spec.rb b/spec/tasks/gitlab/check_rake_spec.rb
index 06525e3c771..0fcb9b269f3 100644
--- a/spec/tasks/gitlab/check_rake_spec.rb
+++ b/spec/tasks/gitlab/check_rake_spec.rb
@@ -96,6 +96,15 @@ describe 'check.rake' do
subject
end
+
+ it 'sanitizes output' do
+ user = double(dn: 'uid=fake_user1', uid: 'fake_user1')
+ allow(adapter).to receive(:users).and_return([user])
+ stub_env('SANITIZE', 'true')
+
+ expect { subject }.to output(/User output sanitized/).to_stdout
+ expect { subject }.not_to output('fake_user1').to_stdout
+ end
end
end
end
diff --git a/spec/workers/build_success_worker_spec.rb b/spec/workers/build_success_worker_spec.rb
index ffe8796ded9..f4ff8cb15f8 100644
--- a/spec/workers/build_success_worker_spec.rb
+++ b/spec/workers/build_success_worker_spec.rb
@@ -6,51 +6,7 @@ describe BuildSuccessWorker do
describe '#perform' do
subject { described_class.new.perform(build.id) }
- before do
- allow_any_instance_of(Deployment).to receive(:create_ref)
- end
-
context 'when build exists' do
- context 'when deployment was not created with the build creation' do # An edge case during the transition period
- let!(:build) { create(:ci_build, :deploy_to_production) }
-
- before do
- allow(Deployments::FinishedWorker).to receive(:perform_async)
- Deployment.delete_all
- build.reload
- end
-
- it 'creates a successful deployment' do
- expect(build).not_to be_has_deployment
-
- subject
-
- build.reload
- expect(build).to be_has_deployment
- expect(build.deployment).to be_success
- end
- end
-
- context 'when deployment was created with the build creation' do # Counter part of the above edge case
- let!(:build) { create(:ci_build, :deploy_to_production) }
-
- it 'does not create a new deployment' do
- expect(build).to be_has_deployment
-
- expect { subject }.not_to change { Deployment.count }
- end
- end
-
- context 'when build is not associated with project' do
- let!(:build) { create(:ci_build, project: nil) }
-
- it 'does not create deployment' do
- subject
-
- expect(build.reload).not_to be_has_deployment
- end
- end
-
context 'when the build will stop an environment' do
let!(:build) { create(:ci_build, :stop_review_app, environment: environment.name, project: environment.project) }
let(:environment) { create(:environment, state: :available) }
diff --git a/spec/workers/cluster_provision_worker_spec.rb b/spec/workers/cluster_provision_worker_spec.rb
index 9cc2ad12bfc..3f69962f25d 100644
--- a/spec/workers/cluster_provision_worker_spec.rb
+++ b/spec/workers/cluster_provision_worker_spec.rb
@@ -23,18 +23,11 @@ describe ClusterProvisionWorker do
described_class.new.perform(cluster.id)
end
-
- it 'configures kubernetes platform' do
- expect(ClusterConfigureWorker).to receive(:perform_async).with(cluster.id)
-
- described_class.new.perform(cluster.id)
- end
end
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(ClusterConfigureWorker).not_to receive(:perform_async)
described_class.new.perform(123)
end
diff --git a/spec/workers/pages_domain_ssl_renewal_cron_worker_spec.rb b/spec/workers/pages_domain_ssl_renewal_cron_worker_spec.rb
new file mode 100644
index 00000000000..08a3511f70b
--- /dev/null
+++ b/spec/workers/pages_domain_ssl_renewal_cron_worker_spec.rb
@@ -0,0 +1,62 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe PagesDomainSslRenewalCronWorker do
+ include LetsEncryptHelpers
+
+ subject(:worker) { described_class.new }
+
+ before do
+ stub_lets_encrypt_settings
+ end
+
+ describe '#perform' do
+ let(:project) { create :project }
+ let!(:domain) { create(:pages_domain, project: project) }
+ let!(:domain_with_enabled_auto_ssl) { create(:pages_domain, project: project, auto_ssl_enabled: true) }
+ let!(:domain_with_obtained_letsencrypt) do
+ create(:pages_domain, :letsencrypt, project: project, auto_ssl_enabled: true)
+ end
+ let!(:domain_without_auto_certificate) do
+ create(:pages_domain, :without_certificate, :without_key, project: project, auto_ssl_enabled: true)
+ end
+
+ let!(:domain_with_expired_auto_ssl) do
+ create(:pages_domain, :letsencrypt, :with_expired_certificate, project: project)
+ end
+
+ it 'enqueues a PagesDomainSslRenewalWorker for domains needing renewal' do
+ [domain_without_auto_certificate,
+ domain_with_enabled_auto_ssl,
+ domain_with_expired_auto_ssl].each do |domain|
+ expect(PagesDomainSslRenewalWorker).to receive(:perform_async).with(domain.id)
+ end
+
+ [domain,
+ domain_with_obtained_letsencrypt].each do |domain|
+ expect(PagesDomainVerificationWorker).not_to receive(:perform_async).with(domain.id)
+ end
+
+ worker.perform
+ end
+
+ shared_examples 'does nothing' do
+ it 'does nothing' do
+ expect(PagesDomainSslRenewalWorker).not_to receive(:perform_async)
+
+ worker.perform
+ end
+ end
+
+ context 'when letsencrypt integration is disabled' do
+ before do
+ stub_application_setting(
+ lets_encrypt_terms_of_service_accepted: false
+ )
+ end
+
+ include_examples 'does nothing'
+ end
+ end
+end
diff --git a/spec/workers/pages_domain_ssl_renewal_worker_spec.rb b/spec/workers/pages_domain_ssl_renewal_worker_spec.rb
new file mode 100644
index 00000000000..3552ff0823a
--- /dev/null
+++ b/spec/workers/pages_domain_ssl_renewal_worker_spec.rb
@@ -0,0 +1,46 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe PagesDomainSslRenewalWorker do
+ include LetsEncryptHelpers
+
+ subject(:worker) { described_class.new }
+
+ let(:project) { create(:project) }
+ let(:domain) { create(:pages_domain, project: project) }
+
+ before do
+ stub_lets_encrypt_settings
+ end
+
+ describe '#perform' do
+ it 'delegates to ObtainLetsEncryptCertificateService' do
+ service = double(:service)
+ expect(::PagesDomains::ObtainLetsEncryptCertificateService).to receive(:new).with(domain).and_return(service)
+ expect(service).to receive(:execute)
+
+ worker.perform(domain.id)
+ end
+
+ shared_examples 'does nothing' do
+ it 'does nothing' do
+ expect(::PagesDomains::ObtainLetsEncryptCertificateService).not_to receive(:new)
+ end
+ end
+
+ context 'when domain was deleted' do
+ before do
+ domain.destroy!
+ end
+
+ include_examples 'does nothing'
+ end
+
+ context 'when domain is disabled' do
+ let(:domain) { create(:pages_domain, :disabled) }
+
+ include_examples 'does nothing'
+ end
+ end
+end
diff --git a/yarn.lock b/yarn.lock
index 2e46217ae50..bbab157d4c7 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1686,13 +1686,13 @@ axios-mock-adapter@^1.15.0:
dependencies:
deep-equal "^1.0.1"
-axios@^0.17.1:
- version "0.17.1"
- resolved "https://registry.yarnpkg.com/axios/-/axios-0.17.1.tgz#2d8e3e5d0bdbd7327f91bc814f5c57660f81824d"
- integrity sha1-LY4+XQvb1zJ/kbyBT1xXZg+Bgk0=
+axios@^0.19.0:
+ version "0.19.0"
+ resolved "https://registry.yarnpkg.com/axios/-/axios-0.19.0.tgz#8e09bff3d9122e133f7b8101c8fbdd00ed3d2ab8"
+ integrity sha512-1uvKqKQta3KBxIz14F2v06AEHZ/dIoeKfbTRkK1E5oqjDnuEerLmYTgJB5AiQZHJcljpg1TuRzdjDR06qNk0DQ==
dependencies:
- follow-redirects "^1.2.5"
- is-buffer "^1.1.5"
+ follow-redirects "1.5.10"
+ is-buffer "^2.0.2"
babel-code-frame@^6.26.0:
version "6.26.0"
@@ -3410,6 +3410,13 @@ debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.8, debug@^2.6.9:
dependencies:
ms "2.0.0"
+debug@=3.1.0, debug@~3.1.0:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261"
+ integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==
+ dependencies:
+ ms "2.0.0"
+
debug@^3.1.0, debug@^3.2.5, debug@^3.2.6:
version "3.2.6"
resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b"
@@ -3424,13 +3431,6 @@ debug@^4.0.0, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1:
dependencies:
ms "^2.1.1"
-debug@~3.1.0:
- version "3.1.0"
- resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261"
- integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==
- dependencies:
- ms "2.0.0"
-
decamelize-keys@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/decamelize-keys/-/decamelize-keys-1.1.0.tgz#d171a87933252807eb3cb61dc1c1445d078df2d9"
@@ -4731,12 +4731,12 @@ flush-write-stream@^1.0.0:
inherits "^2.0.1"
readable-stream "^2.0.4"
-follow-redirects@^1.2.5:
- version "1.2.6"
- resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.2.6.tgz#4dcdc7e4ab3dd6765a97ff89c3b4c258117c79bf"
- integrity sha512-FrMqZ/FONtHnbqO651UPpfRUVukIEwJhXMfdr/JWAmrDbeYBu773b1J6gdWDyRIj4hvvzQEHoEOTrdR8o6KLYA==
+follow-redirects@1.5.10:
+ version "1.5.10"
+ resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.5.10.tgz#7b7a9f9aea2fdff36786a94ff643ed07f4ff5e2a"
+ integrity sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ==
dependencies:
- debug "^3.1.0"
+ debug "=3.1.0"
for-in@^1.0.2:
version "1.0.2"
@@ -4829,10 +4829,10 @@ fsevents@^1.2.2, fsevents@^1.2.7:
nan "^2.12.1"
node-pre-gyp "^0.12.0"
-fstream@^1.0.0, fstream@^1.0.2:
- version "1.0.11"
- resolved "https://registry.yarnpkg.com/fstream/-/fstream-1.0.11.tgz#5c1fb1f117477114f0632a0eb4b71b3cb0fd3171"
- integrity sha1-XB+x8RdHcRTwYyoOtLcbPLD9MXE=
+fstream@^1.0.0, fstream@^1.0.12:
+ version "1.0.12"
+ resolved "https://registry.yarnpkg.com/fstream/-/fstream-1.0.12.tgz#4e8ba8ee2d48be4f7d0de505455548eae5932045"
+ integrity sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==
dependencies:
graceful-fs "^4.1.2"
inherits "~2.0.0"
@@ -5734,7 +5734,7 @@ is-buffer@^1.1.5, is-buffer@~1.1.1:
resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be"
integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==
-is-buffer@^2.0.0:
+is-buffer@^2.0.0, is-buffer@^2.0.2:
version "2.0.3"
resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.3.tgz#4ecf3fcf749cbd1e472689e109ac66261a25e725"
integrity sha512-U15Q7MXTuZlrbymiz95PJpZxu8IlipAp4dtS3wOdgPXx3mqBnslrWU14kxfHB+Py/+2PVKSr37dMAgM2A4uArw==
@@ -6566,10 +6566,10 @@ jquery.waitforimages@^2.2.0:
resolved "https://registry.yarnpkg.com/jquery.waitforimages/-/jquery.waitforimages-2.2.0.tgz#63f23131055a1b060dc913e6d874bcc9b9e6b16b"
integrity sha1-Y/IxMQVaGwYNyRPm2HS8ybnmsWs=
-"jquery@>= 1.9.1", jquery@>=1.8.0, jquery@^3.2.1:
- version "3.3.1"
- resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.3.1.tgz#958ce29e81c9790f31be7792df5d4d95fc57fbca"
- integrity sha512-Ubldcmxp5np52/ENotGxlLe6aGMvmF4R8S6tZjsP6Knsaxd/xp3Zrh50cG93lR6nPXyUFwzN3ZSOQI0wRJNdGg==
+"jquery@>= 1.9.1", jquery@>=1.8.0, jquery@^3.4.1:
+ version "3.4.1"
+ resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.4.1.tgz#714f1f8d9dde4bdfa55764ba37ef214630d80ef2"
+ integrity sha512-36+AdBzCL+y6qjw5Tx7HgzeGCzC81MDDgaUP8ld2zhx58HdqXGoBd+tHdrBMiyjGQs0Hxs/MLZTu/eHNJJuWPw==
js-base64@^2.1.8:
version "2.5.1"
@@ -8699,10 +8699,10 @@ prettier@1.16.3:
resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.16.3.tgz#8c62168453badef702f34b45b6ee899574a6a65d"
integrity sha512-kn/GU6SMRYPxUakNXhpP0EedT/KmaPzr0H5lIsDogrykbaxOpOfAFfk5XA7DZrJyMAv1wlMV3CPcZruGXVVUZw==
-prettier@1.16.4:
- version "1.16.4"
- resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.16.4.tgz#73e37e73e018ad2db9c76742e2647e21790c9717"
- integrity sha512-ZzWuos7TI5CKUeQAtFd6Zhm2s6EpAD/ZLApIhsF9pRvRtM1RFo61dM/4MSRUA0SuLugA/zgrZD8m0BaY46Og7g==
+prettier@1.18.2:
+ version "1.18.2"
+ resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.18.2.tgz#6823e7c5900017b4bd3acf46fe9ac4b4d7bda9ea"
+ integrity sha512-OeHeMc0JhFE9idD4ZdtNibzY0+TPHSpSSb9h8FqtP+YnoZZ1sl8Vc9b1sasjfymH3SonAF4QcA2+mzHPhMvIiw==
pretty-format@^24.8.0:
version "24.8.0"
@@ -10537,12 +10537,12 @@ tapable@^1.0.0, tapable@^1.1.0:
integrity sha512-IlqtmLVaZA2qab8epUXbVWRn3aB1imbDMJtjB3nu4X0NqPkcY/JH9ZtCBWKHWPxs8Svi9tyo8w2dBoi07qZbBA==
tar@^2.0.0:
- version "2.2.1"
- resolved "https://registry.yarnpkg.com/tar/-/tar-2.2.1.tgz#8e4d2a256c0e2185c6b18ad694aec968b83cb1d1"
- integrity sha1-jk0qJWwOIYXGsYrWlK7JaLg8sdE=
+ version "2.2.2"
+ resolved "https://registry.yarnpkg.com/tar/-/tar-2.2.2.tgz#0ca8848562c7299b8b446ff6a4d60cdbb23edc40"
+ integrity sha512-FCEhQ/4rE1zYv9rYXJw/msRqsnmlje5jHP6huWeBZ704jUTy02c5AZyWujpMR1ax6mVw9NyJMfuK2CMDWVIfgA==
dependencies:
block-stream "*"
- fstream "^1.0.2"
+ fstream "^1.0.12"
inherits "2"
tar@^4: