summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.prettierignore6
-rw-r--r--.prettierrc1
-rw-r--r--.rubocop.yml3
-rw-r--r--CHANGELOG.md209
-rw-r--r--Gemfile29
-rw-r--r--Gemfile.lock22
-rw-r--r--Gemfile.rails57
-rw-r--r--Gemfile.rails5.lock1230
-rw-r--r--Procfile1
-rw-r--r--VERSION2
-rw-r--r--app/assets/javascripts/boards/components/issue_card_inner.js4
-rw-r--r--app/assets/javascripts/groups/components/app.vue88
-rw-r--r--app/assets/javascripts/ide/components/new_dropdown/modal.vue118
-rw-r--r--app/assets/javascripts/ide/components/repo_commit_section.vue26
-rw-r--r--app/assets/javascripts/ide/components/repo_file.vue1
-rw-r--r--app/assets/javascripts/ide/ide_router.js86
-rw-r--r--app/assets/javascripts/ide/stores/workers/files_decorator_worker.js30
-rw-r--r--app/assets/javascripts/notes.js5
-rw-r--r--app/assets/javascripts/pages/admin/projects/index/components/delete_project_modal.vue8
-rw-r--r--app/assets/javascripts/pages/admin/users/components/delete_user_modal.vue8
-rw-r--r--app/assets/javascripts/pages/milestones/shared/components/delete_milestone_modal.vue8
-rw-r--r--app/assets/javascripts/performance_bar/components/detailed_metric.vue57
-rw-r--r--app/assets/javascripts/performance_bar/components/performance_bar_app.vue36
-rw-r--r--app/assets/javascripts/performance_bar/components/request_selector.vue2
-rw-r--r--app/assets/javascripts/performance_bar/components/upstream_performance_bar.vue2
-rw-r--r--app/assets/javascripts/performance_bar/index.js4
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_table.vue8
-rw-r--r--app/assets/javascripts/profile/account/components/delete_account_modal.vue8
-rw-r--r--app/assets/javascripts/sidebar/components/time_tracking/collapsed_state.js96
-rw-r--r--app/assets/javascripts/sidebar/components/time_tracking/collapsed_state.vue102
-rw-r--r--app/assets/javascripts/sidebar/components/time_tracking/time_tracker.vue4
-rw-r--r--app/assets/javascripts/vue_shared/components/deprecated_modal.vue (renamed from app/assets/javascripts/vue_shared/components/modal.vue)2
-rw-r--r--app/assets/javascripts/vue_shared/components/file_icon.vue3
-rw-r--r--app/assets/javascripts/vue_shared/components/recaptcha_modal.vue8
-rw-r--r--app/assets/stylesheets/framework/common.scss4
-rw-r--r--app/assets/stylesheets/framework/dropdowns.scss27
-rw-r--r--app/assets/stylesheets/framework/sidebar.scss1
-rw-r--r--app/assets/stylesheets/pages/boards.scss6
-rw-r--r--app/assets/stylesheets/pages/branches.scss21
-rw-r--r--app/assets/stylesheets/pages/events.scss9
-rw-r--r--app/assets/stylesheets/pages/labels.scss8
-rw-r--r--app/assets/stylesheets/pages/projects.scss50
-rw-r--r--app/assets/stylesheets/pages/search.scss2
-rw-r--r--app/assets/stylesheets/performance_bar.scss16
-rw-r--r--app/controllers/admin/application_controller.rb14
-rw-r--r--app/controllers/omniauth_callbacks_controller.rb26
-rw-r--r--app/controllers/projects/pages_controller.rb22
-rw-r--r--app/controllers/projects/pipelines_settings_controller.rb17
-rw-r--r--app/helpers/application_helper.rb7
-rw-r--r--app/helpers/application_settings_helper.rb5
-rw-r--r--app/helpers/issuables_helper.rb7
-rw-r--r--app/helpers/projects_helper.rb18
-rw-r--r--app/models/application_setting.rb3
-rw-r--r--app/models/ci/pipeline.rb2
-rw-r--r--app/models/concerns/avatarable.rb2
-rw-r--r--app/models/group.rb10
-rw-r--r--app/models/member.rb2
-rw-r--r--app/models/pages_domain.rb10
-rw-r--r--app/models/project.rb26
-rw-r--r--app/models/project_services/assembla_service.rb4
-rw-r--r--app/models/project_services/bamboo_service.rb12
-rw-r--r--app/models/project_services/buildkite_service.rb2
-rw-r--r--app/models/project_services/campfire_service.rb7
-rw-r--r--app/models/project_services/drone_ci_service.rb2
-rw-r--r--app/models/project_services/external_wiki_service.rb4
-rw-r--r--app/models/project_services/issue_tracker_service.rb4
-rw-r--r--app/models/project_services/mock_ci_service.rb2
-rw-r--r--app/models/project_services/packagist_service.rb2
-rw-r--r--app/models/project_services/pivotaltracker_service.rb4
-rw-r--r--app/models/project_services/pushover_service.rb5
-rw-r--r--app/models/project_services/teamcity_service.rb12
-rw-r--r--app/services/ci/create_pipeline_service.rb2
-rw-r--r--app/services/notification_service.rb4
-rw-r--r--app/services/projects/import_service.rb2
-rw-r--r--app/services/projects/update_pages_configuration_service.rb6
-rw-r--r--app/services/projects/update_service.rb10
-rw-r--r--app/services/submit_usage_ping_service.rb5
-rw-r--r--app/services/web_hook_service.rb16
-rw-r--r--app/validators/certificate_validator.rb2
-rw-r--r--app/validators/importable_url_validator.rb2
-rw-r--r--app/views/admin/application_settings/_form.html.haml9
-rw-r--r--app/views/import/gitlab_projects/new.html.haml6
-rw-r--r--app/views/layouts/_mailer.html.haml10
-rw-r--r--app/views/layouts/_page.html.haml1
-rw-r--r--app/views/layouts/header/_read_only_banner.html.haml7
-rw-r--r--app/views/peek/_bar.html.haml2
-rw-r--r--app/views/projects/_last_push.html.haml2
-rw-r--r--app/views/projects/_new_project_fields.html.haml4
-rw-r--r--app/views/projects/branches/_branch.html.haml141
-rw-r--r--app/views/projects/issues/_issue.html.haml8
-rw-r--r--app/views/projects/merge_requests/_merge_request.html.haml8
-rw-r--r--app/views/projects/pages/_https_only.html.haml10
-rw-r--r--app/views/projects/pages/show.html.haml3
-rw-r--r--app/views/projects/tree/_tree_header.html.haml2
-rw-r--r--app/views/shared/_issuable_meta_data.html.haml8
-rw-r--r--changelogs/unreleased/17203-add-missing-pagination-commit-diff-endpoint.yml5
-rw-r--r--changelogs/unreleased/17359-move-oauth-modules-to-auth-dir-structure.yml4
-rw-r--r--changelogs/unreleased/17500-mr-multiple-issues-oxford-comma.yml5
-rw-r--r--changelogs/unreleased/24774-clear-the-Labels-dropdown-search-filter.yml5
-rw-r--r--changelogs/unreleased/26039-Update-to-github-linguist5-3-x.yml5
-rw-r--r--changelogs/unreleased/26466-natural-sort-mrs.yml4
-rw-r--r--changelogs/unreleased/29130-api-project-export.yml5
-rw-r--r--changelogs/unreleased/29497-pages-custom-domain-dns-verification.yml5
-rw-r--r--changelogs/unreleased/30665-add-email-button-to-new-issue-by-email.yml4
-rw-r--r--changelogs/unreleased/32564-fix-double-system-closing-notes.yml5
-rw-r--r--changelogs/unreleased/32831-single-deploy-of-runner-in-k8s-cluster.yml5
-rw-r--r--changelogs/unreleased/33570-slack-notify-default-branch.yml5
-rw-r--r--changelogs/unreleased/35418-remove-underline-for-avatar.yml5
-rw-r--r--changelogs/unreleased/35530-teleporting-emoji.yml5
-rw-r--r--changelogs/unreleased/36847-update-update-toml-rb-to-1-0-0.yml5
-rw-r--r--changelogs/unreleased/37050-ext-issue-tracker.yml5
-rw-r--r--changelogs/unreleased/38587-pipelines-empty-state.yml5
-rw-r--r--changelogs/unreleased/39444-make-margin-around-dropdown-dividers-4px.yml5
-rw-r--r--changelogs/unreleased/39607-fix-avatar--vertical-align.yml5
-rw-r--r--changelogs/unreleased/40187-project-branch-dashboard-with-active-stale-branches.yml5
-rw-r--r--changelogs/unreleased/40502-osw-keep-link-when-redacting-unauthorized-objects.yml5
-rw-r--r--changelogs/unreleased/40525-listing-user-activity-timeouts.yml5
-rw-r--r--changelogs/unreleased/40552-sanitize-extra-blank-spaces-used-when-uploading-a-ssh-key.yml5
-rw-r--r--changelogs/unreleased/40623-fix-404-when-listing-archived-projects-in-a-group-where-all-projects-have-been-archived.yml4
-rw-r--r--changelogs/unreleased/40668-pages-domain-api-returns-404-when-using-a-specific-domain.yml5
-rw-r--r--changelogs/unreleased/40994-expose-features-as-ci-cd-variable.yml5
-rw-r--r--changelogs/unreleased/41616-api-issues-between-date.yml5
-rw-r--r--changelogs/unreleased/41719-mr-title-fix.yml5
-rw-r--r--changelogs/unreleased/41777-include-cycle-time-in-usage-ping.yml5
-rw-r--r--changelogs/unreleased/41851-enable-eslint-codeclimate.yml5
-rw-r--r--changelogs/unreleased/41899-api-endpoint-for-importing-a-project-export.yml5
-rw-r--r--changelogs/unreleased/41905_merge_request_and_issue_metrics.yml5
-rw-r--r--changelogs/unreleased/41949-move.yml5
-rw-r--r--changelogs/unreleased/42037-long-instance-names-group-names-covers-namespace-dropdown.yml5
-rw-r--r--changelogs/unreleased/42044-osw-add-button-to-deploy-runner-to-kubernetes.yml5
-rw-r--r--changelogs/unreleased/42274-group-request-membership-long-too.yml5
-rw-r--r--changelogs/unreleased/42314-diff-file.yml5
-rw-r--r--changelogs/unreleased/42332-actionview-template-error-366-524-out-of-range.yml5
-rw-r--r--changelogs/unreleased/42431-add-auto-devops-and-clusters-button-to-projects.yml6
-rw-r--r--changelogs/unreleased/42434-allow-commits-endpoint-to-work-over-all-commits.yml5
-rw-r--r--changelogs/unreleased/42481-remove-notification-settings-left-projects.yml5
-rw-r--r--changelogs/unreleased/42509-fix-API-PUT-projects-fails-when-only-ci_config_path-is-specified.yml5
-rw-r--r--changelogs/unreleased/42545-milestion-quick-actions-for-groups.yml5
-rw-r--r--changelogs/unreleased/42643-persist-external-ip-of-ingress-controller-gke.yml5
-rw-r--r--changelogs/unreleased/42712_api_branches_add_search_param_20180207.yml5
-rw-r--r--changelogs/unreleased/42800-change-usage-of-avatar_icon.yml6
-rw-r--r--changelogs/unreleased/42814-fix-remove-source-branch-when-mwps.yml6
-rw-r--r--changelogs/unreleased/42921-ci-charts-include-current-day.yml5
-rw-r--r--changelogs/unreleased/42922-environment-name.yml5
-rw-r--r--changelogs/unreleased/42923-close-issue.yml5
-rw-r--r--changelogs/unreleased/42929-hide-new-variable-values.yml5
-rw-r--r--changelogs/unreleased/42946-update-pipeline-cancel-tooltip-to-stop.yml5
-rw-r--r--changelogs/unreleased/43134-reduce-queries-pipelines-controller-show.yml5
-rw-r--r--changelogs/unreleased/43198-fix-settings-panel-expanding-when-fragment-hash-linked.yml5
-rw-r--r--changelogs/unreleased/43201-rename-repository-submit-button-disabled.yml5
-rw-r--r--changelogs/unreleased/43261-fix-import-from-url-name-collision-active-tab.yml6
-rw-r--r--changelogs/unreleased/43275-improve-variables-validation-message.yml5
-rw-r--r--changelogs/unreleased/43315-gpg-popover.yml5
-rw-r--r--changelogs/unreleased/43334-reply-by-email-did-not-pick-up-unsubscribe-quick-action.yml5
-rw-r--r--changelogs/unreleased/43460-track-projects-a-user-interacted-with.yml5
-rw-r--r--changelogs/unreleased/43482-enabling-auto-devops-on-an-empty-project-gives-you-wrong-information.yml5
-rw-r--r--changelogs/unreleased/43489-display-runner-ip.yml5
-rw-r--r--changelogs/unreleased/43496-error-message-for-gke-clusters-persists-in-the-next-page.yml5
-rw-r--r--changelogs/unreleased/43525-limit-number-of-failed-logins-using-ldap.yml5
-rw-r--r--changelogs/unreleased/43598-fix-duplicate-label-load-failure.yml5
-rw-r--r--changelogs/unreleased/43643-fix-mr-label-filtering.yml5
-rw-r--r--changelogs/unreleased/43771-improve-avatar-error-message.yml5
-rw-r--r--changelogs/unreleased/43780-add-a-paragraph-about-clusters-security-implications.yml5
-rw-r--r--changelogs/unreleased/43786-on-the-issuable-list-add-tooltips-to-icons.yml5
-rw-r--r--changelogs/unreleased/43793-enable-privileged-mode-for-runner.yml5
-rw-r--r--changelogs/unreleased/43802-ensure-foreign-keys-on-clusters-applications.yml5
-rw-r--r--changelogs/unreleased/43829-update-ssh-addtion-text.yml5
-rw-r--r--changelogs/unreleased/43837-error-handle-in-updating-milestone-on-issue.yml5
-rw-r--r--changelogs/unreleased/43924-breadcrumbs-on-project-tags.yml5
-rw-r--r--changelogs/unreleased/44024-fix-table-extra-column.yml5
-rw-r--r--changelogs/unreleased/44149-issue-comment-buttons.yml5
-rw-r--r--changelogs/unreleased/44330-docs-for-ingress-ip.yml5
-rw-r--r--changelogs/unreleased/44382-ui-breakdown-for-create-merge-request.yml5
-rw-r--r--changelogs/unreleased/44386-better-ux-for-long-name-branches.yml5
-rw-r--r--changelogs/unreleased/4826-create-empty-wiki-when-it-s-enabled.yml5
-rw-r--r--changelogs/unreleased/4826-geo-wikisyncservice-attempts-to-sync-projects.yml5
-rw-r--r--changelogs/unreleased/4826-github-import-wiki-fix-1.yml5
-rw-r--r--changelogs/unreleased/add-indexes-to-todos-for-heavy-users-like-sean.yml5
-rw-r--r--changelogs/unreleased/add-query-counts-to-profiler-output.yml5
-rw-r--r--changelogs/unreleased/an-network-controller-fix.yml5
-rw-r--r--changelogs/unreleased/an-workhorse-3-8-0.yml5
-rw-r--r--changelogs/unreleased/api-refs-for-commit.yml5
-rw-r--r--changelogs/unreleased/asciidoc_inter_document_cross_references.yml5
-rw-r--r--changelogs/unreleased/assignees-vue-component-missing-data-container.yml5
-rw-r--r--changelogs/unreleased/bvl-allow-maintainer-to-push.yml5
-rw-r--r--changelogs/unreleased/bvl-port-of-ee-translations.yml5
-rw-r--r--changelogs/unreleased/cache-refactor.yml5
-rw-r--r--changelogs/unreleased/ce-jej-github-project-service-for-ci.yml5
-rw-r--r--changelogs/unreleased/ce-jej-integrations-can-hide-trigger-checkboxes.yml6
-rw-r--r--changelogs/unreleased/change-strip-whitespace-from-username-input-42637.yml5
-rw-r--r--changelogs/unreleased/ci-pipeline-commit-lookup.yml5
-rw-r--r--changelogs/unreleased/discussions-api.yml5
-rw-r--r--changelogs/unreleased/dm-dont-cache-nil-root-ref.yml5
-rw-r--r--changelogs/unreleased/dm-escape-commit-message.yml5
-rw-r--r--changelogs/unreleased/dm-go-get-api-token.yml5
-rw-r--r--changelogs/unreleased/dm-stuck-import-jobs-verify.yml5
-rw-r--r--changelogs/unreleased/docs-update-vue-naming-guidelines.yml5
-rw-r--r--changelogs/unreleased/dz-namespace-id-not-null.yml5
-rw-r--r--changelogs/unreleased/dz-plugins-project-integrations.yml5
-rw-r--r--changelogs/unreleased/dz-system-hooks-plugins.yml5
-rw-r--r--changelogs/unreleased/ee-4862-verify-file-checksums.yml5
-rw-r--r--changelogs/unreleased/feature--2848-display-time-tracking-totals-milestone-page.yml5
-rw-r--r--changelogs/unreleased/feature--43691-count-diff-note-calendar-activity.yml5
-rw-r--r--changelogs/unreleased/feature-26598-clear-button-ci-lint.yml4
-rw-r--r--changelogs/unreleased/feature-edit_pages_domain.yml5
-rw-r--r--changelogs/unreleased/feature-gb-pipeline-variable-expressions.yml5
-rw-r--r--changelogs/unreleased/feature-include-custom-attributes-in-api.yml5
-rw-r--r--changelogs/unreleased/feature-oidc-groups-claim.yml4
-rw-r--r--changelogs/unreleased/feature-sm-add-check-sum-to-job-artifacts.yml5
-rw-r--r--changelogs/unreleased/fix-auth0-unsafe-login.yml5
-rw-r--r--changelogs/unreleased/fix-change-event-body-label-font-size.yml5
-rw-r--r--changelogs/unreleased/fix-dropzone-project-show.yml5
-rw-r--r--changelogs/unreleased/fix-new-project-path-input-overlapping.yml5
-rw-r--r--changelogs/unreleased/fix-squash-with-renamed-files.yml5
-rw-r--r--changelogs/unreleased/fix-template-project-visibility.yml5
-rw-r--r--changelogs/unreleased/fj-15329-services-callbacks-ssrf.yml5
-rw-r--r--changelogs/unreleased/fj-28141-redirection-loop.yml5
-rw-r--r--changelogs/unreleased/fj-41174-projects-groups-badges-api.yml5
-rw-r--r--changelogs/unreleased/fj-42910-unauthenticated-limit-via-ssh.yml5
-rw-r--r--changelogs/unreleased/fl-refresh-btn.yml5
-rw-r--r--changelogs/unreleased/group-label-page-breadcrumb.yml5
-rw-r--r--changelogs/unreleased/ide-folder-button-path.yml5
-rw-r--r--changelogs/unreleased/increase-unicorn-memory-killer-limits.yml5
-rw-r--r--changelogs/unreleased/issue-39885.yml5
-rw-r--r--changelogs/unreleased/issue_31081.yml5
-rw-r--r--changelogs/unreleased/issue_38337.yml5
-rw-r--r--changelogs/unreleased/jivl-new-modal-project-labels-milestones.yml5
-rw-r--r--changelogs/unreleased/jprovazn-issueref.yml6
-rw-r--r--changelogs/unreleased/jprovazn-scoped-limit.yml6
-rw-r--r--changelogs/unreleased/kp-label-select-vue.yml5
-rw-r--r--changelogs/unreleased/merge-requests-api-filter-by-branch.yml5
-rw-r--r--changelogs/unreleased/move-email-footer-info-to-single-line.yml5
-rw-r--r--changelogs/unreleased/mr-commit-optimization.yml5
-rw-r--r--changelogs/unreleased/oauth_generic_provider.yml4
-rw-r--r--changelogs/unreleased/osw-43951-single-batch-blob-request-to-gitaly.yml5
-rw-r--r--changelogs/unreleased/osw-stop-recalculating-merge-base-on-mr-loading.yml5
-rw-r--r--changelogs/unreleased/pages_force_https.yml5
-rw-r--r--changelogs/unreleased/proper-fix-for-artifacts-service.yml5
-rw-r--r--changelogs/unreleased/refactor-move-assignees-vue-component.yml5
-rw-r--r--changelogs/unreleased/refactor-move-board-new-issue-vue-component.yml5
-rw-r--r--changelogs/unreleased/refactor-move-filtered-search-vue-component.yml5
-rw-r--r--changelogs/unreleased/refactor-move-issuable-time-tracker-vue-component.yml5
-rw-r--r--changelogs/unreleased/refactor-move-sidebar-assignee-vue-component.yml5
-rw-r--r--changelogs/unreleased/refactor-move-time-tracking-vue-components.yml5
-rw-r--r--changelogs/unreleased/remove-unnecessary-validate-project.yml5
-rw-r--r--changelogs/unreleased/replace_redcarpet_with_cmark.yml5
-rw-r--r--changelogs/unreleased/sh-cache-column-exists.yml5
-rw-r--r--changelogs/unreleased/sh-cache-table-exists.yml5
-rw-r--r--changelogs/unreleased/sh-cleanup-after-git-gc.yml5
-rw-r--r--changelogs/unreleased/sh-dashboard-sort-fix.yml5
-rw-r--r--changelogs/unreleased/sh-fix-failure-project-destroy.yml5
-rw-r--r--changelogs/unreleased/sh-fix-geo-error-500-gpg-commit.yml5
-rw-r--r--changelogs/unreleased/sh-fix-issue-43871-system-hooks.yml5
-rw-r--r--changelogs/unreleased/sh-fix-otp-backup-code-invalidation.yml5
-rw-r--r--changelogs/unreleased/sh-make-prune-optional-in-git-fetch.yml5
-rw-r--r--changelogs/unreleased/sh-optimize-admin-projects-page.yml5
-rw-r--r--changelogs/unreleased/sh-update-loofah.yml5
-rw-r--r--changelogs/unreleased/tc-api-fix-expose_url.yml5
-rw-r--r--changelogs/unreleased/tc-re-add-read-only-banner.yml5
-rw-r--r--changelogs/unreleased/unassign-when-leaving.yml5
-rw-r--r--changelogs/unreleased/upgrade-workhorse-4-0-0.yml5
-rw-r--r--changelogs/unreleased/winh-deprecate-old-modal.yml5
-rw-r--r--changelogs/unreleased/winh-new-modal-component.yml5
-rw-r--r--changelogs/unreleased/wip-new-mr-cmd.yml5
-rw-r--r--changelogs/unreleased/zj-move-opt-out-ruby-endpoints.yml5
-rw-r--r--changelogs/unreleased/zj-version-string-grouping-ci.yml5
-rw-r--r--config.ru4
-rw-r--r--config/application.rb2
-rw-r--r--config/initializers/1_settings.rb9
-rw-r--r--config/initializers/6_validations.rb6
-rw-r--r--config/initializers/ar5_batching.rb72
-rw-r--r--config/initializers/ar5_pg_10_support.rb5
-rw-r--r--config/initializers/devise.rb46
-rw-r--r--config/routes/project.rb2
-rw-r--r--config/webpack.config.js128
-rw-r--r--db/migrate/20161124141322_migrate_process_commit_worker_jobs.rb2
-rw-r--r--db/migrate/20161220141214_remove_dot_git_from_group_names.rb2
-rw-r--r--db/migrate/20161226122833_remove_dot_git_from_usernames.rb4
-rw-r--r--db/migrate/20180102220145_add_pages_https_only_to_projects.rb9
-rw-r--r--db/migrate/20180109183319_change_default_value_for_pages_https_only.rb13
-rw-r--r--db/migrate/20180223144945_add_allow_local_requests_from_hooks_and_services_to_application_settings.rb18
-rw-r--r--db/post_migrate/20180220150310_remove_empty_extern_uid_auth0_identities.rb25
-rw-r--r--db/schema.rb2
-rw-r--r--doc/ci/README.md3
-rw-r--r--doc/ci/caching/img/clear_runners_cache.pngbin0 -> 16029 bytes
-rw-r--r--doc/ci/caching/index.md518
-rw-r--r--doc/ci/runners/README.md26
-rw-r--r--doc/ci/yaml/README.md114
-rw-r--r--doc/development/emails.md10
-rw-r--r--doc/development/i18n/proofreader.md1
-rw-r--r--doc/development/migration_style_guide.md16
-rw-r--r--doc/integration/auth0.md7
-rw-r--r--doc/user/project/pipelines/schedules.md2
-rw-r--r--lib/backup/repository.rb4
-rw-r--r--lib/banzai/filter/issuable_state_filter.rb10
-rw-r--r--lib/gitlab/database/rename_reserved_paths_migration/v1/migration_classes.rb2
-rw-r--r--lib/gitlab/git/gitlab_projects.rb2
-rw-r--r--lib/gitlab/git/repository.rb10
-rw-r--r--lib/gitlab/git/storage/checker.rb2
-rw-r--r--lib/gitlab/git/storage/circuit_breaker.rb2
-rw-r--r--lib/gitlab/git/wiki.rb3
-rw-r--r--lib/gitlab/gitaly_client/storage_settings.rb35
-rw-r--r--lib/gitlab/health_checks/fs_shards_check.rb2
-rw-r--r--lib/gitlab/http.rb11
-rw-r--r--lib/gitlab/middleware/read_only.rb2
-rw-r--r--lib/gitlab/omniauth_initializer.rb75
-rw-r--r--lib/gitlab/profiler.rb12
-rw-r--r--lib/gitlab/proxy_http_connection_adapter.rb34
-rw-r--r--lib/gitlab/repo_path.rb4
-rw-r--r--lib/gitlab/setup_helper.rb2
-rw-r--r--lib/gitlab/shell.rb6
-rw-r--r--lib/gitlab/task_helpers.rb4
-rw-r--r--lib/gitlab/url_blocker.rb23
-rw-r--r--lib/mattermost/session.rb24
-rw-r--r--lib/microsoft_teams/notifier.rb5
-rw-r--r--lib/system_check/orphans/namespace_check.rb4
-rw-r--r--lib/system_check/orphans/repository_check.rb6
-rw-r--r--lib/tasks/gitlab/check.rake8
-rw-r--r--lib/tasks/gitlab/cleanup.rake4
-rw-r--r--lib/tasks/gitlab/info.rake2
-rw-r--r--lib/tasks/haml-lint.rake9
-rw-r--r--public/robots.txt1
-rw-r--r--rubocop/cop/gitlab/httparty.rb62
-rw-r--r--rubocop/rubocop.rb1
-rw-r--r--spec/controllers/omniauth_callbacks_controller_spec.rb133
-rw-r--r--spec/controllers/projects/pages_controller_spec.rb37
-rw-r--r--spec/controllers/projects/pages_domains_controller_spec.rb4
-rw-r--r--spec/controllers/projects/pipelines_settings_controller_spec.rb28
-rw-r--r--spec/factories/pages_domains.rb48
-rw-r--r--spec/features/projects/pages_spec.rb90
-rw-r--r--spec/features/projects/tree/tree_show_spec.rb14
-rw-r--r--spec/features/read_only_spec.rb25
-rw-r--r--spec/initializers/6_validations_spec.rb14
-rw-r--r--spec/initializers/settings_spec.rb2
-rw-r--r--spec/javascripts/notes_spec.js14
-rw-r--r--spec/javascripts/performance_bar/components/detailed_metric_spec.js12
-rw-r--r--spec/javascripts/vue_shared/components/deprecated_modal_spec.js (renamed from spec/javascripts/vue_shared/components/modal_spec.js)6
-rw-r--r--spec/lib/backup/repository_spec.rb2
-rw-r--r--spec/lib/banzai/filter/issuable_state_filter_spec.rb8
-rw-r--r--spec/lib/gitlab/bare_repository_import/repository_spec.rb2
-rw-r--r--spec/lib/gitlab/health_checks/fs_shards_check_spec.rb6
-rw-r--r--spec/lib/gitlab/http_spec.rb49
-rw-r--r--spec/lib/gitlab/import_export/safe_model_attributes.yml1
-rw-r--r--spec/lib/gitlab/omniauth_initializer_spec.rb65
-rw-r--r--spec/lib/gitlab/profiler_spec.rb24
-rw-r--r--spec/lib/gitlab/repo_path_spec.rb4
-rw-r--r--spec/lib/gitlab/shell_spec.rb4
-rw-r--r--spec/lib/gitlab/url_blocker_spec.rb45
-rw-r--r--spec/lib/mattermost/command_spec.rb5
-rw-r--r--spec/lib/mattermost/session_spec.rb2
-rw-r--r--spec/lib/mattermost/team_spec.rb5
-rw-r--r--spec/migrations/remove_dot_git_from_usernames_spec.rb4
-rw-r--r--spec/migrations/remove_empty_extern_uid_auth0_identities_spec.rb22
-rw-r--r--spec/models/group_spec.rb2
-rw-r--r--spec/models/namespace_spec.rb2
-rw-r--r--spec/models/pages_domain_spec.rb146
-rw-r--r--spec/models/project_services/mattermost_slash_commands_service_spec.rb5
-rw-r--r--spec/models/project_spec.rb51
-rw-r--r--spec/models/user_spec.rb2
-rw-r--r--spec/requests/api/pages_domains_spec.rb14
-rw-r--r--spec/rubocop/cop/gitlab/httparty_spec.rb74
-rw-r--r--spec/services/ci/process_pipeline_service_spec.rb2
-rw-r--r--spec/services/projects/create_service_spec.rb2
-rw-r--r--spec/services/projects/fork_service_spec.rb2
-rw-r--r--spec/services/projects/transfer_service_spec.rb2
-rw-r--r--spec/services/projects/update_service_spec.rb23
-rw-r--r--spec/services/web_hook_service_spec.rb14
-rw-r--r--spec/spec_helper.rb16
-rw-r--r--spec/support/stored_repositories.rb2
-rw-r--r--spec/support/stub_configuration.rb8
-rw-r--r--spec/support/test_env.rb2
-rw-r--r--spec/tasks/gitlab/backup_rake_spec.rb15
-rw-r--r--spec/tasks/gitlab/cleanup_rake_spec.rb7
-rw-r--r--spec/tasks/gitlab/git_rake_spec.rb7
-rw-r--r--spec/tasks/gitlab/gitaly_rake_spec.rb10
-rw-r--r--spec/tasks/gitlab/shell_rake_spec.rb2
376 files changed, 4340 insertions, 1886 deletions
diff --git a/.prettierignore b/.prettierignore
new file mode 100644
index 00000000000..62fe6a45b95
--- /dev/null
+++ b/.prettierignore
@@ -0,0 +1,6 @@
+/config/
+/node_modules/
+/public/
+/vendor/
+karma.config.js
+webpack.config.js
diff --git a/.prettierrc b/.prettierrc
index a20502b7f06..5e2863a11f6 100644
--- a/.prettierrc
+++ b/.prettierrc
@@ -1,4 +1,5 @@
{
+ "printWidth": 100,
"singleQuote": true,
"trailingComma": "all"
}
diff --git a/.rubocop.yml b/.rubocop.yml
index 14840ddd262..0582bfe8d70 100644
--- a/.rubocop.yml
+++ b/.rubocop.yml
@@ -118,6 +118,9 @@ Gitlab/ModuleWithInstanceVariables:
- spec/support/**/*.rb
- features/steps/**/*.rb
+Gitlab/HTTParty:
+ Enabled: true
+
GitlabSecurity/PublicSend:
Enabled: true
Exclude:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8c64e68967e..e737c38e35c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,198 @@
documentation](doc/development/changelog.md) for instructions on adding your own
entry.
+## 10.6.0 (2018-03-22)
+
+### Security (4 changes)
+
+- Fixed some SSRF vulnerabilities in services, hooks and integrations. !2337
+- Ensure that OTP backup codes are always invalidated.
+- Add verification for GitLab Pages custom domains.
+- Fix GitLab Auth0 integration signing in the wrong user.
+
+### Fixed (75 changes, 17 of them are from the community)
+
+- Ensure users cannot create environments with leading or trailing slashes (Fixes #39885). !15273
+- Fix new project path input overlapping. !16755 (George Tsiolis)
+- Respect description and visibility when creating project from template. !16820 (George Tsiolis)
+- Remove user notification settings for groups and projects when user leaves. !16906 (Jacopo Beschi @jacopo-beschi)
+- Fix Teleporting Emoji. !16963 (Jared Deckard <jared.deckard@gmail.com>)
+- Fix duplicate system notes when merging a merge request. !17035
+- Fix breadcrumb on labels page for groups. !17045 (Onuwa Nnachi Isaac)
+- Fix user avatar's vertical align on the issues and merge requests pages. !17072 (Laszlo Karpati)
+- Fix settings panels not expanding when fragment hash linked. !17074
+- Fix 404 when listing archived projects in a group where all projects have been archived. !17077 (Ashley Dumaine)
+- Allow to call PUT /projects/:id API with only ci_config_path specified. !17105 (Laszlo Karpati)
+- Fix long list of recipients on group request membership email. !17121 (Jacopo Beschi @jacopo-beschi)
+- Remove duplicated error message on duplicate variable validation. !17135
+- Keep "Import project" tab/form active when validation fails trying to import "Repo by URL". !17136
+- Fixed bug with unauthenticated requests through git ssh. !17149
+- Allows project rename after validation error. !17150
+- Fix "Remove source branch" button in Merge request widget during merge when pipeline succeeds state. !17192
+- Add missing pagination on the commit diff endpoint. !17203 (Maxime Roussin-Bélanger)
+- Fix get a single pages domain when project path contains a period. !17206 (Travis Miller)
+- remove avater underline. !17219 (Ken Ding)
+- Allows the usage of /milestone quick action for group milestones. !17239 (Jacopo Beschi @jacopo-beschi)
+- Encode branch name as binary before creating a RPC request to copy attributes. !17291
+- Restart Unicorn and Sidekiq when GRPC throws 14:Endpoint read failed. !17293
+- Do not persist Google Project verification flash errors after a page reload. !17299
+- Ensure group issues and merge requests pages show results from subgroups when there are no results from the current group. !17312
+- Prevent trace artifact migration to incur data loss. !17313
+- Fixes gpg popover layout. !17323
+- Return a 404 instead of 403 if the repository does not exist on disk. !17341
+- Fix Slack/Mattermost notifications not respecting `notify_only_default_branch` setting for pushes. !17345
+- Fix Group labels load failure when there are duplicate labels present. !17353
+- Allow Prometheus application to be installed from Cluster applications. !17372
+- Fixes Prometheus admin configuration page. !17377
+- Enable filtering MR list based on clicked label in MR sidebar. !17390
+- Fix code and wiki search results pages when non-ASCII text is displayed. !17413
+- Count comments on diffs and discussions as contributions for the contributions calendar. !17418 (Riccardo Padovani)
+- Add Assignees vue component missing data container. !17426 (George Tsiolis)
+- Update tooltip on pipeline cancel to Stop (#42946). !17444
+- Removing the two factor check when the user sets a new password. !17457
+- Fix quick actions for users who cannot update issues and merge requests. !17482
+- Stop loading spinner on error of milestone update on issue. !17507 (Takuya Noguchi)
+- Set margins around dropdown dividers to 4px. !17517
+- Fix pages flaky failure by reloading stale object. !17522
+- Remove extra breadcrumb on tags. !17562 (Takuya Noguchi)
+- Fix missing uploads after group transfer. !17658
+- Fix markdown table showing extra column. !17669
+- Ensure the API returns https links when https is configured. !17681
+- Sanitize extra blank spaces used when uploading a SSH key. !40552
+- Render htmlentities correctly for links not supported by Rinku.
+- Keep link when redacting unauthorized object links.
+- Handle empty state in Pipelines page.
+- Revert Project.public_or_visible_to_user changes and only apply to snippets.
+- Release libgit2 cache and open file descriptors after `git gc` run.
+- Fix project dashboard showing the wrong timestamps.
+- Fix "Can't modify frozen hash" error when project is destroyed.
+- Fix Error 500 when viewing a commit with a GPG signature in Geo.
+- Don't error out in system hook if user has `nil` datetime columns.
+- Remove double caching of Repository#empty?.
+- Don't delete todos or unassign issues and MRs when a user leaves a project.
+- Don't cache a nil repository root ref to prevent caching issues.
+- Escape HTML entities in commit messages.
+- Verify project import status again before marking as failed.
+- [GitHub Import] Create an empty wiki if wiki import failed.
+- Create empty wiki when import from GitLab and wiki is not there.
+- Make sure wiki exists when it's enabled.
+- Fix broken loading state for close issue button.
+- Fix code and wiki search results when filename is non-ASCII.
+- Fix file upload on project show page.
+- Fix squashing when a file is renamed.
+- Show loading button inline in refresh button in MR widget.
+- Fix close button on issues not working on mobile.
+- Adds tooltip in environment names to increase readability.
+- Fixed issue edit shortcut not opening edit form.
+- Fix 500 error being shown when diff has context marker with invalid encoding.
+- Render modified icon for moved file in changes dropdown.
+- Remember assignee when moving an issue.
+
+### Changed (16 changes, 9 of them are from the community)
+
+- Allow including custom attributes in API responses. !16526 (Markus Koller)
+- Apply new default and inline label design. !16956 (George Tsiolis)
+- Remove whitespace from the username/email sign in form field. !17020 (Peter lauck)
+- CI charts now include the current day. !17032 (Dakkaron)
+- Hide CI secret variable values after saving. !17044
+- Add new modal Vue component. !17108
+- Asciidoc now support inter-document cross references between files in repository. !17125 (Turo Soisenniemi)
+- Update issue closing pattern to allow variations in punctuation. !17198 (Vicky Chijwani)
+- Add a button to deploy a runner to a Kubernetes cluster in the settings page. !17278
+- Pages custom domain: allow update of key/certificate. !17376 (rfwatson)
+- Clear the Labels dropdown search filter after a selection is made. !17393 (Andrew Torres)
+- Hook data for pipelines includes detailed_status. !17607
+- Avoid showing unnecessary Trigger checkboxes for project Integrations with only one event. !17607
+- Display a link to external issue tracker when enabled.
+- Allow token authentication on go-get request.
+- Update SSH key link to include existing keys. (Brendan O'Leary)
+
+### Performance (24 changes, 5 of them are from the community)
+
+- Add catch-up background migration to migrate pipeline stages. !15741
+- Move BoardNewIssue vue component. !16947 (George Tsiolis)
+- Move IssuableTimeTracker vue component. !16948 (George Tsiolis)
+- Move RecentSearchesDropdownContent vue component. !16951 (George Tsiolis)
+- Move Assignees vue component. !16952 (George Tsiolis)
+- Improve performance of pipeline page by reducing DB queries. !17168
+- Store sha256 checksum to job artifacts. !17354
+- Move SidebarAssignees vue component. !17398 (George Tsiolis)
+- Improve database response time for user activity listing. !17454
+- Use persisted/memoized value for MRs shas instead of doing git lookups. !17555
+- Cache MergeRequests can_be_resolved_in_ui? git operations. !17589
+- Prevent the graphs page from generating unnecessary Gitaly requests. !37602
+- Use a user object in ApplicationHelper#avatar_icon where possible to avoid N+1 queries. !42800
+- Submit a single batch blob RPC to Gitaly per HTTP request when viewing diffs.
+- Avoid re-fetching merge-base SHA from Gitaly unnecessarily.
+- Don't use ProjectsFinder in TodosFinder.
+- Adding missing indexes on taggings table.
+- Add index on section_name_id on ci_build_trace_sections table.
+- Cache column_exists? for application settings.
+- Cache table_exists?('application_settings') to reduce repeated schema reloads.
+- Make --prune a configurable parameter in fetching a git remote.
+- Fix timeouts loading /admin/projects page.
+- Add partial indexes on todos to handle users with many todos.
+- Optimize search queries on the search page by setting a limit for matching records in project scope.
+
+### Added (30 changes, 9 of them are from the community)
+
+- Add CommonMark markdown engine (experimental). !14835 (blackst0ne)
+- API: Get references a commit is pushed to. !15026 (Robert Schilling)
+- Add overview of branches and a filter for active/stale branches. !15402 (Takuya Noguchi)
+- Add project export API. !15860 (Travis Miller)
+- expose more metrics in merge requests api. !16589 (haseebeqx)
+- #28481: Display time tracking totals on milestone page. !16753 (Riccardo Padovani)
+- Add a button on the project page to set up a Kubernetes cluster and enable Auto DevOps. !16900
+- Include cycle time in usage ping data. !16973
+- Add ability to use external plugins as an alternative to system hooks. !17003
+- Add search param to Branches API. !17005 (bunufi)
+- API endpoint for importing a project export. !17025
+- Display ingress IP address in the Kubernetes page. !17052
+- Implemented badge API endpoints. !17082
+- Allow installation of GitLab Runner with a single click. !17134
+- Allow commits endpoint to work over all commits of a repository. !17182
+- Display Runner IP Address. !17286
+- Add archive feature to trace. !17314
+- Allow maintainers to push to forks of their projects when a merge request is open. !17395
+- Foreground verification of uploads and LFS objects. !17402
+- Adds updated_at filter to issues and merge_requests API. !17417 (Jacopo Beschi @jacopo-beschi)
+- Port /wip quick action command to Merge Request creation (on description). !17463 (Adam Pahlevi)
+- Add a paragraph about security implications on Cluster's page. !17486
+- Add plugins list to the system hooks page. !17518
+- Enable privileged mode for GitLab Runner. !17528
+- Expose GITLAB_FEATURES as CI/CD variable (fixes #40994).
+- Upgrade GitLab Workhorse to 4.0.0.
+- Allow CI/CD Jobs being grouped on version strings.
+- Add discussions API for Issues and Snippets.
+- Add one group board to Libre.
+- Add support for filtering by source and target branch to merge requests API.
+
+### Other (14 changes, 3 of them are from the community)
+
+- Update vue component naming guidelines. !17018 (George Tsiolis)
+- Added new design for promotion modals. !17197
+- Update to github-linguist 5.3.x. !17241 (Ken Ding)
+- update toml-rb to 1.0.0. !17259 (Ken Ding)
+- Keep track of projects a user interacted with. !17327
+- Enables eslint in codeclimate job. !17392
+- Port Labels Select dropdown to Vue. !17411
+- Add NOT NULL constraint to projects.namespace_id. !17448
+- Ensure foreign keys on clusters applications. !17488
+- Started translation into Turkish, Indonesian and Filipino. !17526
+- Add documentation for displayed K8s Ingress IP address (#44330). !17836
+- Move Ruby endpoints to OPT_OUT.
+- Upgrade Workhorse to version 3.8.0 to support structured logging.
+- Use host URL to build JIRA remote link icon.
+
+
+## 10.5.6 (2018-03-16)
+
+### Security (2 changes)
+
+- Fixed some SSRF vulnerabilities in services, hooks and integrations. !2337
+- Fix GitLab Auth0 integration signing in the wrong user.
+
+
## 10.5.5 (2018-03-15)
### Fixed (3 changes)
@@ -261,6 +453,14 @@ entry.
- Adds empty state illustration for pending job.
+## 10.4.6 (2018-03-16)
+
+### Security (2 changes)
+
+- Fixed some SSRF vulnerabilities in services, hooks and integrations. !2337
+- Fix GitLab Auth0 integration signing in the wrong user.
+
+
## 10.4.5 (2018-03-01)
### Security (1 change)
@@ -492,6 +692,15 @@ entry.
- Use a background migration for issues.closed_at.
+## 10.3.9 (2018-03-16)
+
+### Security (3 changes)
+
+- Fixed some SSRF vulnerabilities in services, hooks and integrations. !2337
+- Update nokogiri to 1.8.2. !16807
+- Fix GitLab Auth0 integration signing in the wrong user.
+
+
## 10.3.8 (2018-03-01)
### Security (1 change)
diff --git a/Gemfile b/Gemfile
index 957ceff554f..149ae1fac0d 100644
--- a/Gemfile
+++ b/Gemfile
@@ -1,6 +1,19 @@
+# --- Special code for migrating to Rails 5.0 ---
+def rails5?
+ %w[1 true].include?(ENV["RAILS5"])
+end
+
+gem_versions = {}
+gem_versions['activerecord_sane_schema_dumper'] = rails5? ? '1.0' : '0.2'
+gem_versions['default_value_for'] = rails5? ? '~> 3.0.5' : '~> 3.0.0'
+gem_versions['html-pipeline'] = rails5? ? '~> 2.6.0' : '~> 1.11.0'
+gem_versions['rails'] = rails5? ? '5.0.6' : '4.2.10'
+gem_versions['rails-i18n'] = rails5? ? '~> 5.1' : '~> 4.0.9'
+# --- The end of special code for migrating to Rails 5.0 ---
+
source 'https://rubygems.org'
-gem 'rails', '4.2.10'
+gem 'rails', gem_versions['rails']
gem 'rails-deprecated_sanitizer', '~> 1.0.3'
# Responders respond_to and respond_with
@@ -9,7 +22,7 @@ gem 'responders', '~> 2.0'
gem 'sprockets', '~> 3.7.0'
# Default values for AR models
-gem 'default_value_for', '~> 3.0.0'
+gem 'default_value_for', gem_versions['default_value_for']
# Supported DBs
gem 'mysql2', '~> 0.4.10', group: :mysql
@@ -24,8 +37,8 @@ gem 'faraday', '~> 0.12'
gem 'devise', '~> 4.2'
gem 'doorkeeper', '~> 4.3'
gem 'doorkeeper-openid_connect', '~> 1.3'
-gem 'omniauth', '~> 1.4.2'
-gem 'omniauth-auth0', '~> 1.4.1'
+gem 'omniauth', '~> 1.8'
+gem 'omniauth-auth0', '~> 2.0.0'
gem 'omniauth-azure-oauth2', '~> 0.0.9'
gem 'omniauth-cas3', '~> 1.1.4'
gem 'omniauth-facebook', '~> 4.0.0'
@@ -122,7 +135,7 @@ gem 'unf', '~> 0.1.4'
gem 'seed-fu', '~> 2.3.7'
# Markdown and HTML processing
-gem 'html-pipeline', '~> 1.11.0'
+gem 'html-pipeline', gem_versions['html-pipeline']
gem 'deckar01-task_list', '2.0.0'
gem 'gitlab-markup', '~> 1.6.2'
gem 'redcarpet', '~> 3.4'
@@ -218,7 +231,7 @@ gem 'sanitize', '~> 2.0'
gem 'babosa', '~> 1.0.2'
# Sanitizes SVG input
-gem 'loofah', '~> 2.0.3'
+gem 'loofah', '~> 2.2'
# Working with license
gem 'licensee', '~> 8.9'
@@ -266,7 +279,7 @@ gem 'premailer-rails', '~> 1.9.7'
# I18n
gem 'ruby_parser', '~> 3.8', require: false
-gem 'rails-i18n', '~> 4.0.9'
+gem 'rails-i18n', gem_versions['rails-i18n']
gem 'gettext_i18n_rails', '~> 1.8.0'
gem 'gettext_i18n_rails_js', '~> 1.3'
gem 'gettext', '~> 3.2.2', require: false, group: :development
@@ -357,7 +370,7 @@ group :development, :test do
gem 'license_finder', '~> 3.1', require: false
gem 'knapsack', '~> 1.16'
- gem 'activerecord_sane_schema_dumper', '0.2'
+ gem 'activerecord_sane_schema_dumper', gem_versions['activerecord_sane_schema_dumper']
gem 'stackprof', '~> 0.2.10', require: false
diff --git a/Gemfile.lock b/Gemfile.lock
index f063edccc66..a92843f32d8 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -143,6 +143,7 @@ GEM
connection_pool (2.2.1)
crack (0.4.3)
safe_yaml (~> 1.0.0)
+ crass (1.0.3)
creole (0.5.0)
css_parser (1.5.0)
addressable
@@ -485,7 +486,8 @@ GEM
actionpack (>= 4, < 5.2)
activesupport (>= 4, < 5.2)
railties (>= 4, < 5.2)
- loofah (2.0.3)
+ loofah (2.2.2)
+ crass (~> 1.0.2)
nokogiri (>= 1.5.9)
mail (2.7.0)
mini_mime (>= 0.1.1)
@@ -524,11 +526,11 @@ GEM
rack (>= 1.2, < 3)
octokit (4.8.0)
sawyer (~> 0.8.0, >= 0.5.3)
- omniauth (1.4.3)
- hashie (>= 1.2, < 4)
+ omniauth (1.8.1)
+ hashie (>= 3.4.6, < 3.6.0)
rack (>= 1.6.2, < 3)
- omniauth-auth0 (1.4.1)
- omniauth-oauth2 (~> 1.1)
+ omniauth-auth0 (2.0.0)
+ omniauth-oauth2 (~> 1.4)
omniauth-authentiq (0.3.1)
omniauth-oauth2 (~> 1.3, >= 1.3.1)
omniauth-azure-oauth2 (0.0.9)
@@ -679,8 +681,8 @@ GEM
activesupport (>= 4.2.0, < 5.0)
nokogiri (~> 1.6)
rails-deprecated_sanitizer (>= 1.0.1)
- rails-html-sanitizer (1.0.3)
- loofah (~> 2.0)
+ rails-html-sanitizer (1.0.4)
+ loofah (~> 2.2, >= 2.2.2)
rails-i18n (4.0.9)
i18n (~> 0.7)
railties (~> 4.0)
@@ -1093,7 +1095,7 @@ DEPENDENCIES
license_finder (~> 3.1)
licensee (~> 8.9)
lograge (~> 0.5)
- loofah (~> 2.0.3)
+ loofah (~> 2.2)
mail_room (~> 0.9.1)
method_source (~> 0.8)
minitest (~> 5.7.0)
@@ -1104,8 +1106,8 @@ DEPENDENCIES
nokogiri (~> 1.8.2)
oauth2 (~> 1.4)
octokit (~> 4.8)
- omniauth (~> 1.4.2)
- omniauth-auth0 (~> 1.4.1)
+ omniauth (~> 1.8)
+ omniauth-auth0 (~> 2.0.0)
omniauth-authentiq (~> 0.3.1)
omniauth-azure-oauth2 (~> 0.0.9)
omniauth-cas3 (~> 1.1.4)
diff --git a/Gemfile.rails5 b/Gemfile.rails5
new file mode 100644
index 00000000000..2b526b19ba0
--- /dev/null
+++ b/Gemfile.rails5
@@ -0,0 +1,7 @@
+# BUNDLE_GEMFILE=Gemfile.rails5 bundle install
+
+ENV["RAILS5"] = "true"
+
+gemfile = File.expand_path("../Gemfile", __FILE__)
+
+eval(File.read(gemfile), nil, gemfile)
diff --git a/Gemfile.rails5.lock b/Gemfile.rails5.lock
new file mode 100644
index 00000000000..85bf28ef8dd
--- /dev/null
+++ b/Gemfile.rails5.lock
@@ -0,0 +1,1230 @@
+GEM
+ remote: https://rubygems.org/
+ specs:
+ RedCloth (4.3.2)
+ abstract_type (0.0.7)
+ ace-rails-ap (4.1.4)
+ actioncable (5.0.6)
+ actionpack (= 5.0.6)
+ nio4r (>= 1.2, < 3.0)
+ websocket-driver (~> 0.6.1)
+ actionmailer (5.0.6)
+ actionpack (= 5.0.6)
+ actionview (= 5.0.6)
+ activejob (= 5.0.6)
+ mail (~> 2.5, >= 2.5.4)
+ rails-dom-testing (~> 2.0)
+ actionpack (5.0.6)
+ actionview (= 5.0.6)
+ activesupport (= 5.0.6)
+ rack (~> 2.0)
+ rack-test (~> 0.6.3)
+ rails-dom-testing (~> 2.0)
+ rails-html-sanitizer (~> 1.0, >= 1.0.2)
+ actionview (5.0.6)
+ activesupport (= 5.0.6)
+ builder (~> 3.1)
+ erubis (~> 2.7.0)
+ rails-dom-testing (~> 2.0)
+ rails-html-sanitizer (~> 1.0, >= 1.0.3)
+ activejob (5.0.6)
+ activesupport (= 5.0.6)
+ globalid (>= 0.3.6)
+ activemodel (5.0.6)
+ activesupport (= 5.0.6)
+ activerecord (5.0.6)
+ activemodel (= 5.0.6)
+ activesupport (= 5.0.6)
+ arel (~> 7.0)
+ activerecord_sane_schema_dumper (1.0)
+ rails (>= 5, < 6)
+ activesupport (5.0.6)
+ concurrent-ruby (~> 1.0, >= 1.0.2)
+ i18n (~> 0.7)
+ minitest (~> 5.1)
+ tzinfo (~> 1.1)
+ acts-as-taggable-on (4.0.0)
+ activerecord (>= 4.0)
+ adamantium (0.2.0)
+ ice_nine (~> 0.11.0)
+ memoizable (~> 0.4.0)
+ addressable (2.5.2)
+ public_suffix (>= 2.0.2, < 4.0)
+ aes_key_wrap (1.0.1)
+ akismet (2.0.0)
+ allocations (1.0.5)
+ arel (7.1.4)
+ asana (0.6.3)
+ faraday (~> 0.9)
+ faraday_middleware (~> 0.9)
+ faraday_middleware-multi_json (~> 0.0)
+ oauth2 (~> 1.0)
+ asciidoctor (1.5.6.1)
+ asciidoctor-plantuml (0.0.7)
+ asciidoctor (~> 1.5)
+ asset_sync (2.2.0)
+ activemodel (>= 4.1.0)
+ fog-core
+ mime-types (>= 2.99)
+ unf
+ ast (2.4.0)
+ atomic (1.1.100)
+ attr_encrypted (3.0.3)
+ encryptor (~> 3.0.0)
+ attr_required (1.0.1)
+ autoprefixer-rails (8.1.0.1)
+ execjs
+ awesome_print (1.2.0)
+ axiom-types (0.1.1)
+ descendants_tracker (~> 0.0.4)
+ ice_nine (~> 0.11.0)
+ thread_safe (~> 0.3, >= 0.3.1)
+ babosa (1.0.2)
+ base32 (0.3.2)
+ batch-loader (1.2.1)
+ bcrypt (3.1.11)
+ bcrypt_pbkdf (1.0.0)
+ benchmark-ips (2.3.0)
+ better_errors (2.1.1)
+ coderay (>= 1.0.0)
+ erubis (>= 2.6.6)
+ rack (>= 0.9.0)
+ bindata (2.4.3)
+ binding_of_caller (0.7.3)
+ debug_inspector (>= 0.0.1)
+ blankslate (2.1.2.4)
+ bootstrap-sass (3.3.7)
+ autoprefixer-rails (>= 5.2.1)
+ sass (>= 3.3.4)
+ bootstrap_form (2.7.0)
+ brakeman (3.6.2)
+ browser (2.5.3)
+ builder (3.2.3)
+ bullet (5.5.1)
+ activesupport (>= 3.0.0)
+ uniform_notifier (~> 1.10.0)
+ bundler-audit (0.5.0)
+ bundler (~> 1.2)
+ thor (~> 0.18)
+ byebug (9.0.6)
+ capybara (2.18.0)
+ addressable
+ mini_mime (>= 0.1.3)
+ nokogiri (>= 1.3.3)
+ rack (>= 1.0.0)
+ rack-test (>= 0.5.4)
+ xpath (>= 2.0, < 4.0)
+ capybara-screenshot (1.0.18)
+ capybara (>= 1.0, < 3)
+ launchy
+ carrierwave (1.2.2)
+ activemodel (>= 4.0.0)
+ activesupport (>= 4.0.0)
+ mime-types (>= 1.16)
+ charlock_holmes (0.7.5)
+ childprocess (0.9.0)
+ ffi (~> 1.0, >= 1.0.11)
+ chronic (0.10.2)
+ chronic_duration (0.10.6)
+ numerizer (~> 0.1.1)
+ chunky_png (1.3.10)
+ citrus (3.0.2)
+ coderay (1.1.2)
+ coercible (1.0.0)
+ descendants_tracker (~> 0.0.1)
+ colorize (0.8.1)
+ commonmarker (0.17.9)
+ ruby-enum (~> 0.5)
+ concord (0.1.5)
+ adamantium (~> 0.2.0)
+ equalizer (~> 0.0.9)
+ concurrent-ruby (1.0.5)
+ concurrent-ruby-ext (1.0.5)
+ concurrent-ruby (= 1.0.5)
+ connection_pool (2.2.1)
+ crack (0.4.3)
+ safe_yaml (~> 1.0.0)
+ creole (0.5.0)
+ css_parser (1.6.0)
+ addressable
+ d3_rails (3.5.17)
+ railties (>= 3.1.0)
+ daemons (1.2.6)
+ database_cleaner (1.5.3)
+ debug_inspector (0.0.3)
+ debugger-ruby_core_source (1.3.8)
+ deckar01-task_list (2.0.0)
+ html-pipeline
+ declarative (0.0.10)
+ declarative-option (0.1.0)
+ default_value_for (3.0.5)
+ activerecord (>= 3.2.0, < 5.2)
+ descendants_tracker (0.0.4)
+ thread_safe (~> 0.3, >= 0.3.1)
+ devise (4.4.1)
+ bcrypt (~> 3.0)
+ orm_adapter (~> 0.1)
+ railties (>= 4.1.0, < 5.2)
+ responders
+ warden (~> 1.2.3)
+ devise-two-factor (3.0.2)
+ activesupport (< 5.2)
+ attr_encrypted (>= 1.3, < 4, != 2)
+ devise (~> 4.0)
+ railties (< 5.2)
+ rotp (~> 2.0)
+ diff-lcs (1.3)
+ diffy (3.1.0)
+ docile (1.1.5)
+ domain_name (0.5.20170404)
+ unf (>= 0.0.5, < 1.0.0)
+ doorkeeper (4.2.6)
+ railties (>= 4.2)
+ doorkeeper-openid_connect (1.2.0)
+ doorkeeper (~> 4.0)
+ json-jwt (~> 1.6)
+ dropzonejs-rails (0.7.4)
+ rails (> 3.1)
+ email_reply_trimmer (0.1.10)
+ email_spec (1.6.0)
+ launchy (~> 2.1)
+ mail (~> 2.2)
+ encryptor (3.0.0)
+ equalizer (0.0.11)
+ erubis (2.7.0)
+ escape_utils (1.1.1)
+ et-orbi (1.0.9)
+ tzinfo
+ eventmachine (1.2.5)
+ excon (0.60.0)
+ execjs (2.7.0)
+ expression_parser (0.9.0)
+ factory_bot (4.8.2)
+ activesupport (>= 3.0.0)
+ factory_bot_rails (4.8.2)
+ factory_bot (~> 4.8.2)
+ railties (>= 3.0.0)
+ faraday (0.12.2)
+ multipart-post (>= 1.2, < 3)
+ faraday_middleware (0.12.2)
+ faraday (>= 0.7.4, < 1.0)
+ faraday_middleware-multi_json (0.0.6)
+ faraday_middleware
+ multi_json
+ fast_blank (1.0.0)
+ fast_gettext (1.6.0)
+ ffaker (2.8.1)
+ ffi (1.9.23)
+ flay (2.10.0)
+ erubis (~> 2.7.0)
+ path_expander (~> 1.0)
+ ruby_parser (~> 3.0)
+ sexp_processor (~> 4.0)
+ flipper (0.11.0)
+ flipper-active_record (0.11.0)
+ activerecord (>= 3.2, < 6)
+ flipper (~> 0.11.0)
+ flipper-active_support_cache_store (0.11.0)
+ activesupport (>= 3.2, < 6)
+ flipper (~> 0.11.0)
+ flowdock (0.7.1)
+ httparty (~> 0.7)
+ multi_json
+ fog-aliyun (0.2.0)
+ fog-core (~> 1.27)
+ fog-json (~> 1.0)
+ ipaddress (~> 0.8)
+ xml-simple (~> 1.1)
+ fog-aws (1.4.1)
+ fog-core (~> 1.38)
+ fog-json (~> 1.0)
+ fog-xml (~> 0.1)
+ ipaddress (~> 0.8)
+ fog-core (1.45.0)
+ builder
+ excon (~> 0.58)
+ formatador (~> 0.2)
+ fog-google (0.6.0)
+ fog-core
+ fog-json
+ fog-xml
+ fog-json (1.0.2)
+ fog-core (~> 1.0)
+ multi_json (~> 1.10)
+ fog-local (0.5.0)
+ fog-core (>= 1.27, < 3.0)
+ fog-openstack (0.1.24)
+ fog-core (~> 1.40)
+ fog-json (>= 1.0)
+ ipaddress (>= 0.8)
+ fog-rackspace (0.1.5)
+ fog-core (>= 1.35)
+ fog-json (>= 1.0)
+ fog-xml (>= 0.1)
+ ipaddress (>= 0.8)
+ fog-xml (0.1.3)
+ fog-core
+ nokogiri (>= 1.5.11, < 2.0.0)
+ font-awesome-rails (4.7.0.3)
+ railties (>= 3.2, < 5.2)
+ foreman (0.78.0)
+ thor (~> 0.19.1)
+ formatador (0.2.5)
+ fuubar (2.2.0)
+ rspec-core (~> 3.0)
+ ruby-progressbar (~> 1.4)
+ gemnasium-gitlab-service (0.2.6)
+ rugged (~> 0.21)
+ gemojione (3.3.0)
+ json
+ get_process_mem (0.2.1)
+ gettext (3.2.9)
+ locale (>= 2.0.5)
+ text (>= 1.3.0)
+ gettext_i18n_rails (1.8.0)
+ fast_gettext (>= 0.9.0)
+ gettext_i18n_rails_js (1.2.0)
+ gettext (>= 3.0.2)
+ gettext_i18n_rails (>= 0.7.1)
+ po_to_json (>= 1.0.0)
+ rails (>= 3.2.0)
+ gherkin-ruby (0.3.2)
+ gitaly-proto (0.88.0)
+ google-protobuf (~> 3.1)
+ grpc (~> 1.0)
+ github-linguist (5.3.3)
+ charlock_holmes (~> 0.7.5)
+ escape_utils (~> 1.1.0)
+ mime-types (>= 1.19)
+ rugged (>= 0.25.1)
+ github-markup (1.7.0)
+ gitlab-flowdock-git-hook (1.0.1)
+ flowdock (~> 0.7)
+ gitlab-grit (>= 2.4.1)
+ multi_json
+ gitlab-grit (2.8.2)
+ charlock_holmes (~> 0.6)
+ diff-lcs (~> 1.1)
+ mime-types (>= 1.16)
+ posix-spawn (~> 0.3)
+ gitlab-markup (1.6.3)
+ gitlab-styles (2.3.2)
+ rubocop (~> 0.51)
+ rubocop-gitlab-security (~> 0.1.0)
+ rubocop-rspec (~> 1.19)
+ gitlab_omniauth-ldap (2.0.4)
+ net-ldap (~> 0.16)
+ omniauth (~> 1.3)
+ pyu-ruby-sasl (>= 0.0.3.3, < 0.1)
+ rubyntlm (~> 0.5)
+ globalid (0.4.1)
+ activesupport (>= 4.2.0)
+ gollum-grit_adapter (1.0.1)
+ gitlab-grit (~> 2.7, >= 2.7.1)
+ gollum-lib (4.2.7)
+ gemojione (~> 3.2)
+ github-markup (~> 1.6)
+ gollum-grit_adapter (~> 1.0)
+ nokogiri (>= 1.6.1, < 2.0)
+ rouge (~> 2.1)
+ sanitize (~> 2.1)
+ stringex (~> 2.6)
+ gollum-rugged_adapter (0.4.4)
+ mime-types (>= 1.15)
+ rugged (~> 0.25)
+ gon (6.1.0)
+ actionpack (>= 3.0)
+ json
+ multi_json
+ request_store (>= 1.0)
+ google-api-client (0.13.6)
+ addressable (~> 2.5, >= 2.5.1)
+ googleauth (~> 0.5)
+ httpclient (>= 2.8.1, < 3.0)
+ mime-types (~> 3.0)
+ representable (~> 3.0)
+ retriable (>= 2.0, < 4.0)
+ google-protobuf (3.5.1)
+ googleapis-common-protos-types (1.0.1)
+ google-protobuf (~> 3.0)
+ googleauth (0.6.2)
+ faraday (~> 0.12)
+ jwt (>= 1.4, < 3.0)
+ logging (~> 2.0)
+ memoist (~> 0.12)
+ multi_json (~> 1.11)
+ os (~> 0.9)
+ signet (~> 0.7)
+ gpgme (2.0.16)
+ mini_portile2 (~> 2.3)
+ grape (1.0.2)
+ activesupport
+ builder
+ mustermann-grape (~> 1.0.0)
+ rack (>= 1.3.0)
+ rack-accept
+ virtus (>= 1.0.0)
+ grape-entity (0.6.1)
+ activesupport (>= 5.0.0)
+ multi_json (>= 1.3.2)
+ grape-route-helpers (2.1.0)
+ activesupport
+ grape (>= 0.16.0)
+ rake
+ grape_logging (1.7.0)
+ grape
+ grpc (1.10.0)
+ google-protobuf (~> 3.1)
+ googleapis-common-protos-types (~> 1.0.0)
+ googleauth (>= 0.5.1, < 0.7)
+ haml (4.0.7)
+ tilt
+ haml_lint (0.26.0)
+ haml (>= 4.0, < 5.1)
+ rainbow
+ rake (>= 10, < 13)
+ rubocop (>= 0.49.0)
+ sysexits (~> 1.1)
+ hamlit (2.6.2)
+ temple (~> 0.7.6)
+ thor
+ tilt
+ hashdiff (0.3.7)
+ hashie (3.5.7)
+ hashie-forbidden_attributes (0.1.1)
+ hashie (>= 3.0)
+ health_check (2.6.0)
+ rails (>= 4.0)
+ hipchat (1.5.4)
+ httparty
+ mimemagic
+ html-pipeline (2.6.0)
+ activesupport (>= 2)
+ nokogiri (>= 1.4)
+ html2text (0.2.1)
+ nokogiri (~> 1.6)
+ htmlentities (4.3.4)
+ http (0.9.8)
+ addressable (~> 2.3)
+ http-cookie (~> 1.0)
+ http-form_data (~> 1.0.1)
+ http_parser.rb (~> 0.6.0)
+ http-cookie (1.0.3)
+ domain_name (~> 0.5)
+ http-form_data (1.0.3)
+ http_parser.rb (0.6.0)
+ httparty (0.13.7)
+ json (~> 1.8)
+ multi_xml (>= 0.5.2)
+ httpclient (2.8.3)
+ i18n (0.9.5)
+ concurrent-ruby (~> 1.0)
+ ice_nine (0.11.2)
+ influxdb (0.5.3)
+ ipaddress (0.8.3)
+ jira-ruby (1.5.0)
+ activesupport
+ multipart-post
+ oauth (~> 0.5, >= 0.5.0)
+ jquery-atwho-rails (1.3.2)
+ jquery-rails (4.3.1)
+ rails-dom-testing (>= 1, < 3)
+ railties (>= 4.2.0)
+ thor (>= 0.14, < 2.0)
+ json (1.8.6)
+ json-jwt (1.9.2)
+ activesupport
+ aes_key_wrap
+ bindata
+ securecompare
+ url_safe_base64
+ json-schema (2.8.0)
+ addressable (>= 2.4)
+ jwt (1.5.6)
+ kaminari (1.1.1)
+ activesupport (>= 4.1.0)
+ kaminari-actionview (= 1.1.1)
+ kaminari-activerecord (= 1.1.1)
+ kaminari-core (= 1.1.1)
+ kaminari-actionview (1.1.1)
+ actionview
+ kaminari-core (= 1.1.1)
+ kaminari-activerecord (1.1.1)
+ activerecord
+ kaminari-core (= 1.1.1)
+ kaminari-core (1.1.1)
+ kgio (2.11.2)
+ knapsack (1.11.1)
+ rake
+ timecop (>= 0.1.0)
+ kubeclient (2.2.0)
+ http (= 0.9.8)
+ recursive-open-struct (= 1.0.0)
+ rest-client
+ launchy (2.4.3)
+ addressable (~> 2.3)
+ letter_opener (1.6.0)
+ launchy (~> 2.2)
+ letter_opener_web (1.3.3)
+ actionmailer (>= 3.2)
+ letter_opener (~> 1.0)
+ railties (>= 3.2)
+ license_finder (3.1.1)
+ bundler
+ httparty
+ rubyzip
+ thor
+ toml (= 0.1.2)
+ with_env (> 1.0)
+ xml-simple
+ licensee (8.7.0)
+ rugged (~> 0.24)
+ little-plugger (1.1.4)
+ locale (2.1.2)
+ logging (2.2.2)
+ little-plugger (~> 1.1)
+ multi_json (~> 1.10)
+ lograge (0.9.0)
+ actionpack (>= 4)
+ activesupport (>= 4)
+ railties (>= 4)
+ request_store (~> 1.0)
+ loofah (2.0.3)
+ nokogiri (>= 1.5.9)
+ mail (2.7.0)
+ mini_mime (>= 0.1.1)
+ mail_room (0.9.1)
+ memoist (0.16.0)
+ memoizable (0.4.2)
+ thread_safe (~> 0.3, >= 0.3.1)
+ method_source (0.9.0)
+ mime-types (3.1)
+ mime-types-data (~> 3.2015)
+ mime-types-data (3.2016.0521)
+ mimemagic (0.3.2)
+ mini_mime (1.0.0)
+ mini_portile2 (2.3.0)
+ minitest (5.7.0)
+ mousetrap-rails (1.4.6)
+ multi_json (1.13.1)
+ multi_xml (0.6.0)
+ multipart-post (2.0.0)
+ mustermann (1.0.2)
+ mustermann-grape (1.0.0)
+ mustermann (~> 1.0.0)
+ mysql2 (0.4.10)
+ net-ldap (0.16.1)
+ net-ssh (4.1.0)
+ netrc (0.11.0)
+ nio4r (2.2.0)
+ nokogiri (1.8.2)
+ mini_portile2 (~> 2.3.0)
+ numerizer (0.1.1)
+ oauth (0.5.4)
+ oauth2 (1.4.0)
+ faraday (>= 0.8, < 0.13)
+ jwt (~> 1.0)
+ multi_json (~> 1.3)
+ multi_xml (~> 0.5)
+ rack (>= 1.2, < 3)
+ octokit (4.6.2)
+ sawyer (~> 0.8.0, >= 0.5.3)
+ oj (2.17.5)
+ omniauth (1.4.3)
+ hashie (>= 1.2, < 4)
+ rack (>= 1.6.2, < 3)
+ omniauth-auth0 (1.4.2)
+ omniauth-oauth2 (~> 1.1)
+ omniauth-authentiq (0.3.1)
+ omniauth-oauth2 (~> 1.3, >= 1.3.1)
+ omniauth-azure-oauth2 (0.0.9)
+ jwt (~> 1.0)
+ omniauth (~> 1.0)
+ omniauth-oauth2 (~> 1.4)
+ omniauth-cas3 (1.1.4)
+ addressable (~> 2.3)
+ nokogiri (~> 1.7, >= 1.7.1)
+ omniauth (~> 1.2)
+ omniauth-facebook (4.0.0)
+ omniauth-oauth2 (~> 1.2)
+ omniauth-github (1.1.2)
+ omniauth (~> 1.0)
+ omniauth-oauth2 (~> 1.1)
+ omniauth-gitlab (1.0.3)
+ omniauth (~> 1.0)
+ omniauth-oauth2 (~> 1.0)
+ omniauth-google-oauth2 (0.5.3)
+ jwt (>= 1.5)
+ omniauth (>= 1.1.1)
+ omniauth-oauth2 (>= 1.5)
+ omniauth-kerberos (0.3.0)
+ omniauth-multipassword
+ timfel-krb5-auth (~> 0.8)
+ omniauth-multipassword (0.4.2)
+ omniauth (~> 1.0)
+ omniauth-oauth (1.1.0)
+ oauth
+ omniauth (~> 1.0)
+ omniauth-oauth2 (1.5.0)
+ oauth2 (~> 1.1)
+ omniauth (~> 1.2)
+ omniauth-oauth2-generic (0.2.4)
+ omniauth-oauth2 (~> 1.0)
+ omniauth-saml (1.7.0)
+ omniauth (~> 1.3)
+ ruby-saml (~> 1.4)
+ omniauth-shibboleth (1.2.1)
+ omniauth (>= 1.0.0)
+ omniauth-twitter (1.2.1)
+ json (~> 1.3)
+ omniauth-oauth (~> 1.1)
+ omniauth_crowd (2.2.3)
+ activesupport
+ nokogiri (>= 1.4.4)
+ omniauth (~> 1.0)
+ org-ruby (0.9.12)
+ rubypants (~> 0.2)
+ orm_adapter (0.5.0)
+ os (0.9.6)
+ parallel (1.12.1)
+ parser (2.5.0.4)
+ ast (~> 2.4.0)
+ parslet (1.5.0)
+ blankslate (~> 2.0)
+ path_expander (1.0.2)
+ peek (1.0.1)
+ concurrent-ruby (>= 0.9.0)
+ concurrent-ruby-ext (>= 0.9.0)
+ railties (>= 4.0.0)
+ peek-gc (0.0.2)
+ peek
+ peek-host (1.0.0)
+ peek
+ peek-mysql2 (1.1.0)
+ atomic (>= 1.0.0)
+ mysql2
+ peek
+ peek-performance_bar (1.3.1)
+ peek (>= 0.1.0)
+ peek-pg (1.3.0)
+ concurrent-ruby
+ concurrent-ruby-ext
+ peek
+ pg
+ peek-rblineprof (0.2.0)
+ peek
+ rblineprof
+ peek-redis (1.2.0)
+ atomic (>= 1.0.0)
+ peek
+ redis
+ peek-sidekiq (1.0.3)
+ atomic (>= 1.0.0)
+ peek
+ sidekiq
+ pg (0.18.4)
+ po_to_json (1.0.1)
+ json (>= 1.6.0)
+ posix-spawn (0.3.13)
+ powerpack (0.1.1)
+ premailer (1.11.1)
+ addressable
+ css_parser (>= 1.6.0)
+ htmlentities (>= 4.0.0)
+ premailer-rails (1.9.7)
+ actionmailer (>= 3, < 6)
+ premailer (~> 1.7, >= 1.7.9)
+ proc_to_ast (0.1.0)
+ coderay
+ parser
+ unparser
+ procto (0.0.3)
+ prometheus-client-mmap (0.9.1)
+ pry (0.11.3)
+ coderay (~> 1.1.0)
+ method_source (~> 0.9.0)
+ pry-byebug (3.4.3)
+ byebug (>= 9.0, < 9.1)
+ pry (~> 0.10)
+ pry-rails (0.3.6)
+ pry (>= 0.10.4)
+ public_suffix (3.0.2)
+ pyu-ruby-sasl (0.0.3.3)
+ rack (2.0.4)
+ rack-accept (0.4.5)
+ rack (>= 0.4)
+ rack-attack (4.4.1)
+ rack
+ rack-cors (1.0.2)
+ rack-oauth2 (1.2.3)
+ activesupport (>= 2.3)
+ attr_required (>= 0.0.5)
+ httpclient (>= 2.4)
+ multi_json (>= 1.3.6)
+ rack (>= 1.1)
+ rack-protection (2.0.1)
+ rack
+ rack-proxy (0.6.4)
+ rack
+ rack-test (0.6.3)
+ rack (>= 1.0)
+ rails (5.0.6)
+ actioncable (= 5.0.6)
+ actionmailer (= 5.0.6)
+ actionpack (= 5.0.6)
+ actionview (= 5.0.6)
+ activejob (= 5.0.6)
+ activemodel (= 5.0.6)
+ activerecord (= 5.0.6)
+ activesupport (= 5.0.6)
+ bundler (>= 1.3.0)
+ railties (= 5.0.6)
+ sprockets-rails (>= 2.0.0)
+ rails-deprecated_sanitizer (1.0.3)
+ activesupport (>= 4.2.0.alpha)
+ rails-dom-testing (2.0.3)
+ activesupport (>= 4.2.0)
+ nokogiri (>= 1.6)
+ rails-html-sanitizer (1.0.3)
+ loofah (~> 2.0)
+ rails-i18n (5.1.1)
+ i18n (>= 0.7, < 2)
+ railties (>= 5.0, < 6)
+ railties (5.0.6)
+ actionpack (= 5.0.6)
+ activesupport (= 5.0.6)
+ method_source
+ rake (>= 0.8.7)
+ thor (>= 0.18.1, < 2.0)
+ rainbow (2.2.2)
+ rake
+ raindrops (0.19.0)
+ rake (12.3.0)
+ rb-fsevent (0.10.3)
+ rb-inotify (0.9.10)
+ ffi (>= 0.5.0, < 2)
+ rblineprof (0.3.7)
+ debugger-ruby_core_source (~> 1.3)
+ rbnacl (4.0.2)
+ ffi
+ rbnacl-libsodium (1.0.16)
+ rbnacl (>= 3.0.1)
+ rdoc (4.3.0)
+ re2 (1.1.1)
+ recaptcha (3.4.0)
+ json
+ recursive-open-struct (1.0.0)
+ redcarpet (3.4.0)
+ redis (3.3.5)
+ redis-actionpack (5.0.2)
+ actionpack (>= 4.0, < 6)
+ redis-rack (>= 1, < 3)
+ redis-store (>= 1.1.0, < 2)
+ redis-activesupport (5.0.4)
+ activesupport (>= 3, < 6)
+ redis-store (>= 1.3, < 2)
+ redis-namespace (1.5.3)
+ redis (~> 3.0, >= 3.0.4)
+ redis-rack (2.0.4)
+ rack (>= 1.5, < 3)
+ redis-store (>= 1.2, < 2)
+ redis-rails (5.0.2)
+ redis-actionpack (>= 5.0, < 6)
+ redis-activesupport (>= 5.0, < 6)
+ redis-store (>= 1.2, < 2)
+ redis-store (1.4.1)
+ redis (>= 2.2, < 5)
+ representable (3.0.4)
+ declarative (< 0.1.0)
+ declarative-option (< 0.2.0)
+ uber (< 0.2.0)
+ request_store (1.4.0)
+ rack (>= 1.4)
+ responders (2.4.0)
+ actionpack (>= 4.2.0, < 5.3)
+ railties (>= 4.2.0, < 5.3)
+ rest-client (2.0.2)
+ http-cookie (>= 1.0.2, < 2.0)
+ mime-types (>= 1.16, < 4.0)
+ netrc (~> 0.8)
+ retriable (3.1.1)
+ rinku (2.0.4)
+ rotp (2.1.2)
+ rouge (2.2.1)
+ rqrcode (0.10.1)
+ chunky_png (~> 1.0)
+ rqrcode-rails3 (0.1.7)
+ rqrcode (>= 0.4.2)
+ rspec (3.6.0)
+ rspec-core (~> 3.6.0)
+ rspec-expectations (~> 3.6.0)
+ rspec-mocks (~> 3.6.0)
+ rspec-core (3.6.0)
+ rspec-support (~> 3.6.0)
+ rspec-expectations (3.6.0)
+ diff-lcs (>= 1.2.0, < 2.0)
+ rspec-support (~> 3.6.0)
+ rspec-mocks (3.6.0)
+ diff-lcs (>= 1.2.0, < 2.0)
+ rspec-support (~> 3.6.0)
+ rspec-parameterized (0.4.0)
+ binding_of_caller
+ parser
+ proc_to_ast
+ rspec (>= 2.13, < 4)
+ unparser
+ rspec-rails (3.6.1)
+ actionpack (>= 3.0)
+ activesupport (>= 3.0)
+ railties (>= 3.0)
+ rspec-core (~> 3.6.0)
+ rspec-expectations (~> 3.6.0)
+ rspec-mocks (~> 3.6.0)
+ rspec-support (~> 3.6.0)
+ rspec-retry (0.4.6)
+ rspec-core
+ rspec-set (0.1.3)
+ rspec-support (3.6.0)
+ rspec_profiling (0.0.5)
+ activerecord
+ pg
+ rails
+ sqlite3
+ rubocop (0.52.1)
+ parallel (~> 1.10)
+ parser (>= 2.4.0.2, < 3.0)
+ powerpack (~> 0.1)
+ rainbow (>= 2.2.2, < 4.0)
+ ruby-progressbar (~> 1.7)
+ unicode-display_width (~> 1.0, >= 1.0.1)
+ rubocop-gitlab-security (0.1.1)
+ rubocop (>= 0.51)
+ rubocop-rspec (1.22.2)
+ rubocop (>= 0.52.1)
+ ruby-enum (0.7.2)
+ i18n
+ ruby-fogbugz (0.2.1)
+ crack (~> 0.4)
+ ruby-prof (0.16.2)
+ ruby-progressbar (1.9.0)
+ ruby-saml (1.7.2)
+ nokogiri (>= 1.5.10)
+ ruby_parser (3.11.0)
+ sexp_processor (~> 4.9)
+ rubyntlm (0.6.2)
+ rubypants (0.7.0)
+ rubyzip (1.2.1)
+ rufus-scheduler (3.4.2)
+ et-orbi (~> 1.0)
+ rugged (0.26.0)
+ safe_yaml (1.0.4)
+ sanitize (2.1.0)
+ nokogiri (>= 1.4.4)
+ sass (3.5.5)
+ sass-listen (~> 4.0.0)
+ sass-listen (4.0.0)
+ rb-fsevent (~> 0.9, >= 0.9.4)
+ rb-inotify (~> 0.9, >= 0.9.7)
+ sass-rails (5.0.7)
+ railties (>= 4.0.0, < 6)
+ sass (~> 3.1)
+ sprockets (>= 2.8, < 4.0)
+ sprockets-rails (>= 2.0, < 4.0)
+ tilt (>= 1.1, < 3)
+ sawyer (0.8.1)
+ addressable (>= 2.3.5, < 2.6)
+ faraday (~> 0.8, < 1.0)
+ scss_lint (0.56.0)
+ rake (>= 0.9, < 13)
+ sass (~> 3.5.3)
+ securecompare (1.0.0)
+ seed-fu (2.3.7)
+ activerecord (>= 3.1)
+ activesupport (>= 3.1)
+ select2-rails (3.5.10)
+ thor (~> 0.14)
+ selenium-webdriver (3.11.0)
+ childprocess (~> 0.5)
+ rubyzip (~> 1.2)
+ sentry-raven (2.5.3)
+ faraday (>= 0.7.6, < 1.0)
+ settingslogic (2.0.9)
+ sexp_processor (4.10.1)
+ sham_rack (1.3.6)
+ rack
+ shoulda-matchers (3.1.2)
+ activesupport (>= 4.0.0)
+ sidekiq (5.1.1)
+ concurrent-ruby (~> 1.0)
+ connection_pool (~> 2.2, >= 2.2.0)
+ rack-protection (>= 1.5.0)
+ redis (>= 3.3.5, < 5)
+ sidekiq-cron (0.6.3)
+ rufus-scheduler (>= 3.3.0)
+ sidekiq (>= 4.2.1)
+ sidekiq-limit_fetch (3.4.0)
+ sidekiq (>= 4)
+ signet (0.8.1)
+ addressable (~> 2.3)
+ faraday (~> 0.9)
+ jwt (>= 1.5, < 3.0)
+ multi_json (~> 1.10)
+ simple_po_parser (1.1.3)
+ simplecov (0.14.1)
+ docile (~> 1.1.0)
+ json (>= 1.8, < 3)
+ simplecov-html (~> 0.10.0)
+ simplecov-html (0.10.2)
+ slack-notifier (1.5.1)
+ spinach (0.10.1)
+ colorize
+ gherkin-ruby (>= 0.3.2)
+ json
+ spinach-rails (0.2.1)
+ capybara (>= 2.0.0)
+ railties (>= 3)
+ spinach (>= 0.4)
+ spinach-rerun-reporter (0.0.2)
+ spinach (~> 0.8)
+ spring (2.0.2)
+ activesupport (>= 4.2)
+ spring-commands-rspec (1.0.4)
+ spring (>= 0.9.1)
+ spring-commands-spinach (1.1.0)
+ spring (>= 0.9.1)
+ sprockets (3.7.1)
+ concurrent-ruby (~> 1.0)
+ rack (> 1, < 3)
+ sprockets-rails (3.2.1)
+ actionpack (>= 4.0)
+ activesupport (>= 4.0)
+ sprockets (>= 3.0.0)
+ sqlite3 (1.3.13)
+ sshkey (1.9.0)
+ stackprof (0.2.11)
+ state_machines (0.5.0)
+ state_machines-activemodel (0.5.0)
+ activemodel (>= 4.1, < 5.2)
+ state_machines (>= 0.5.0)
+ state_machines-activerecord (0.4.1)
+ activerecord (>= 4.1, < 5.2)
+ state_machines-activemodel (>= 0.3.0)
+ stringex (2.8.4)
+ sys-filesystem (1.1.9)
+ ffi
+ sysexits (1.2.0)
+ temple (0.7.7)
+ test-prof (0.2.5)
+ test_after_commit (1.1.0)
+ activerecord (>= 3.2)
+ text (1.3.1)
+ thin (1.7.2)
+ daemons (~> 1.0, >= 1.0.9)
+ eventmachine (~> 1.0, >= 1.0.4)
+ rack (>= 1, < 3)
+ thor (0.19.4)
+ thread_safe (0.3.6)
+ tilt (2.0.8)
+ timecop (0.8.1)
+ timfel-krb5-auth (0.8.3)
+ toml (0.1.2)
+ parslet (~> 1.5.0)
+ toml-rb (1.0.0)
+ citrus (~> 3.0, > 3.0)
+ truncato (0.7.10)
+ htmlentities (~> 4.3.1)
+ nokogiri (~> 1.8.0, >= 1.7.0)
+ tzinfo (1.2.5)
+ thread_safe (~> 0.1)
+ u2f (0.2.1)
+ uber (0.1.0)
+ uglifier (2.7.2)
+ execjs (>= 0.3.0)
+ json (>= 1.8.0)
+ unf (0.1.4)
+ unf_ext
+ unf_ext (0.0.7.5)
+ unicode-display_width (1.3.0)
+ unicorn (5.1.0)
+ kgio (~> 2.6)
+ raindrops (~> 0.7)
+ unicorn-worker-killer (0.4.4)
+ get_process_mem (~> 0)
+ unicorn (>= 4, < 6)
+ uniform_notifier (1.10.0)
+ unparser (0.2.7)
+ abstract_type (~> 0.0.7)
+ adamantium (~> 0.2.0)
+ concord (~> 0.1.5)
+ diff-lcs (~> 1.3)
+ equalizer (~> 0.0.9)
+ parser (>= 2.3.1.2, < 2.6)
+ procto (~> 0.0.2)
+ url_safe_base64 (0.2.2)
+ validates_hostname (1.0.8)
+ activerecord (>= 3.0)
+ activesupport (>= 3.0)
+ version_sorter (2.1.0)
+ virtus (1.0.5)
+ axiom-types (~> 0.1)
+ coercible (~> 1.0)
+ descendants_tracker (~> 0.0, >= 0.0.3)
+ equalizer (~> 0.0, >= 0.0.9)
+ vmstat (2.3.0)
+ warden (1.2.7)
+ rack (>= 1.0)
+ webmock (2.3.2)
+ addressable (>= 2.3.6)
+ crack (>= 0.3.2)
+ hashdiff
+ webpack-rails (0.9.11)
+ railties (>= 3.2.0)
+ websocket-driver (0.6.5)
+ websocket-extensions (>= 0.1.0)
+ websocket-extensions (0.1.3)
+ wikicloth (0.8.1)
+ builder
+ expression_parser
+ rinku
+ with_env (1.1.0)
+ xml-simple (1.1.5)
+ xpath (3.0.0)
+ nokogiri (~> 1.8)
+
+PLATFORMS
+ ruby
+
+DEPENDENCIES
+ RedCloth (~> 4.3.2)
+ ace-rails-ap (~> 4.1.0)
+ activerecord_sane_schema_dumper (= 1.0)
+ acts-as-taggable-on (~> 4.0)
+ addressable (~> 2.5.2)
+ akismet (~> 2.0)
+ allocations (~> 1.0)
+ asana (~> 0.6.0)
+ asciidoctor (~> 1.5.2)
+ asciidoctor-plantuml (= 0.0.7)
+ asset_sync (~> 2.2.0)
+ attr_encrypted (~> 3.0.0)
+ awesome_print (~> 1.2.0)
+ babosa (~> 1.0.2)
+ base32 (~> 0.3.0)
+ batch-loader (~> 1.2.1)
+ bcrypt_pbkdf (~> 1.0)
+ benchmark-ips (~> 2.3.0)
+ better_errors (~> 2.1.0)
+ binding_of_caller (~> 0.7.2)
+ bootstrap-sass (~> 3.3.0)
+ bootstrap_form (~> 2.7.0)
+ brakeman (~> 3.6.0)
+ browser (~> 2.2)
+ bullet (~> 5.5.0)
+ bundler-audit (~> 0.5.0)
+ capybara (~> 2.15)
+ capybara-screenshot (~> 1.0.0)
+ carrierwave (~> 1.2)
+ charlock_holmes (~> 0.7.5)
+ chronic (~> 0.10.2)
+ chronic_duration (~> 0.10.6)
+ commonmarker (~> 0.17)
+ concurrent-ruby (~> 1.0.5)
+ connection_pool (~> 2.0)
+ creole (~> 0.5.0)
+ d3_rails (~> 3.5.0)
+ database_cleaner (~> 1.5.0)
+ deckar01-task_list (= 2.0.0)
+ default_value_for (~> 3.0.5)
+ devise (~> 4.2)
+ devise-two-factor (~> 3.0.0)
+ diffy (~> 3.1.0)
+ doorkeeper (~> 4.2.0)
+ doorkeeper-openid_connect (~> 1.2.0)
+ dropzonejs-rails (~> 0.7.1)
+ email_reply_trimmer (~> 0.1)
+ email_spec (~> 1.6.0)
+ factory_bot_rails (~> 4.8.2)
+ faraday (~> 0.12)
+ fast_blank
+ ffaker (~> 2.4)
+ flay (~> 2.10.0)
+ flipper (~> 0.11.0)
+ flipper-active_record (~> 0.11.0)
+ flipper-active_support_cache_store (~> 0.11.0)
+ fog-aliyun (~> 0.2.0)
+ fog-aws (~> 1.4)
+ fog-core (~> 1.44)
+ fog-google (~> 0.5)
+ fog-local (~> 0.3)
+ fog-openstack (~> 0.1)
+ fog-rackspace (~> 0.1.1)
+ font-awesome-rails (~> 4.7)
+ foreman (~> 0.78.0)
+ fuubar (~> 2.2.0)
+ gemnasium-gitlab-service (~> 0.2)
+ gemojione (~> 3.3)
+ gettext (~> 3.2.2)
+ gettext_i18n_rails (~> 1.8.0)
+ gettext_i18n_rails_js (~> 1.2.0)
+ gitaly-proto (~> 0.88.0)
+ github-linguist (~> 5.3.3)
+ gitlab-flowdock-git-hook (~> 1.0.1)
+ gitlab-markup (~> 1.6.2)
+ gitlab-styles (~> 2.3)
+ gitlab_omniauth-ldap (~> 2.0.4)
+ gollum-lib (~> 4.2)
+ gollum-rugged_adapter (~> 0.4.4)
+ gon (~> 6.1.0)
+ google-api-client (~> 0.13.6)
+ google-protobuf (= 3.5.1)
+ gpgme
+ grape (~> 1.0)
+ grape-entity (~> 0.6.0)
+ grape-route-helpers (~> 2.1.0)
+ grape_logging (~> 1.7)
+ grpc (~> 1.10.0)
+ haml_lint (~> 0.26.0)
+ hamlit (~> 2.6.1)
+ hashie-forbidden_attributes
+ health_check (~> 2.6.0)
+ hipchat (~> 1.5.0)
+ html-pipeline (~> 2.6.0)
+ html2text
+ httparty (~> 0.13.3)
+ influxdb (~> 0.2)
+ jira-ruby (~> 1.4)
+ jquery-atwho-rails (~> 1.3.2)
+ jquery-rails (~> 4.3.1)
+ json-schema (~> 2.8.0)
+ jwt (~> 1.5.6)
+ kaminari (~> 1.0)
+ knapsack (~> 1.11.0)
+ kubeclient (~> 2.2.0)
+ letter_opener_web (~> 1.3.0)
+ license_finder (~> 3.1)
+ licensee (~> 8.7.0)
+ lograge (~> 0.5)
+ loofah (~> 2.0.3)
+ mail_room (~> 0.9.1)
+ method_source (~> 0.8)
+ minitest (~> 5.7.0)
+ mousetrap-rails (~> 1.4.6)
+ mysql2 (~> 0.4.10)
+ net-ldap
+ net-ssh (~> 4.1.0)
+ nokogiri (~> 1.8.2)
+ oauth2 (~> 1.4)
+ octokit (~> 4.6.2)
+ oj (~> 2.17.4)
+ omniauth (~> 1.4.2)
+ omniauth-auth0 (~> 1.4.1)
+ omniauth-authentiq (~> 0.3.1)
+ omniauth-azure-oauth2 (~> 0.0.9)
+ omniauth-cas3 (~> 1.1.4)
+ omniauth-facebook (~> 4.0.0)
+ omniauth-github (~> 1.1.1)
+ omniauth-gitlab (~> 1.0.2)
+ omniauth-google-oauth2 (~> 0.5.2)
+ omniauth-kerberos (~> 0.3.0)
+ omniauth-oauth2-generic (~> 0.2.2)
+ omniauth-saml (~> 1.7.0)
+ omniauth-shibboleth (~> 1.2.0)
+ omniauth-twitter (~> 1.2.0)
+ omniauth_crowd (~> 2.2.0)
+ org-ruby (~> 0.9.12)
+ peek (~> 1.0.1)
+ peek-gc (~> 0.0.2)
+ peek-host (~> 1.0.0)
+ peek-mysql2 (~> 1.1.0)
+ peek-performance_bar (~> 1.3.0)
+ peek-pg (~> 1.3.0)
+ peek-rblineprof (~> 0.2.0)
+ peek-redis (~> 1.2.0)
+ peek-sidekiq (~> 1.0.3)
+ pg (~> 0.18.2)
+ premailer-rails (~> 1.9.7)
+ prometheus-client-mmap (~> 0.9.1)
+ pry-byebug (~> 3.4.1)
+ pry-rails (~> 0.3.4)
+ rack-attack (~> 4.4.1)
+ rack-cors (~> 1.0.0)
+ rack-oauth2 (~> 1.2.1)
+ rack-proxy (~> 0.6.0)
+ rails (= 5.0.6)
+ rails-deprecated_sanitizer (~> 1.0.3)
+ rails-i18n (~> 5.1)
+ rainbow (~> 2.2)
+ raindrops (~> 0.18)
+ rblineprof (~> 0.3.6)
+ rbnacl (~> 4.0)
+ rbnacl-libsodium
+ rdoc (~> 4.2)
+ re2 (~> 1.1.1)
+ recaptcha (~> 3.0)
+ redcarpet (~> 3.4)
+ redis (~> 3.2)
+ redis-namespace (~> 1.5.2)
+ redis-rails (~> 5.0.2)
+ request_store (~> 1.3)
+ responders (~> 2.0)
+ rouge (~> 2.0)
+ rqrcode-rails3 (~> 0.1.7)
+ rspec-parameterized
+ rspec-rails (~> 3.6.0)
+ rspec-retry (~> 0.4.5)
+ rspec-set (~> 0.1.3)
+ rspec_profiling (~> 0.0.5)
+ rubocop (~> 0.52.1)
+ rubocop-rspec (~> 1.22.1)
+ ruby-fogbugz (~> 0.2.1)
+ ruby-prof (~> 0.16.2)
+ ruby_parser (~> 3.8)
+ rufus-scheduler (~> 3.4)
+ rugged (~> 0.26.0)
+ sanitize (~> 2.0)
+ sass-rails (~> 5.0.6)
+ scss_lint (~> 0.56.0)
+ seed-fu (~> 2.3.7)
+ select2-rails (~> 3.5.9)
+ selenium-webdriver (~> 3.5)
+ sentry-raven (~> 2.5.3)
+ settingslogic (~> 2.0.9)
+ sham_rack (~> 1.3.6)
+ shoulda-matchers (~> 3.1.2)
+ sidekiq (~> 5.0)
+ sidekiq-cron (~> 0.6.0)
+ sidekiq-limit_fetch (~> 3.4)
+ simple_po_parser (~> 1.1.2)
+ simplecov (~> 0.14.0)
+ slack-notifier (~> 1.5.1)
+ spinach-rails (~> 0.2.1)
+ spinach-rerun-reporter (~> 0.0.2)
+ spring (~> 2.0.0)
+ spring-commands-rspec (~> 1.0.4)
+ spring-commands-spinach (~> 1.1.0)
+ sprockets (~> 3.7.0)
+ sshkey (~> 1.9.0)
+ stackprof (~> 0.2.10)
+ state_machines-activerecord (~> 0.4.0)
+ sys-filesystem (~> 1.1.6)
+ test-prof (~> 0.2.5)
+ test_after_commit (~> 1.1)
+ thin (~> 1.7.0)
+ timecop (~> 0.8.0)
+ toml-rb (~> 1.0.0)
+ truncato (~> 0.7.9)
+ u2f (~> 0.2.1)
+ uglifier (~> 2.7.2)
+ unf (~> 0.1.4)
+ unicorn (~> 5.1.0)
+ unicorn-worker-killer (~> 0.4.4)
+ validates_hostname (~> 1.0.6)
+ version_sorter (~> 2.1.0)
+ virtus (~> 1.0.1)
+ vmstat (~> 2.3.0)
+ webmock (~> 2.3.2)
+ webpack-rails (~> 0.9.10)
+ wikicloth (= 0.8.1)
+
+BUNDLED WITH
+ 1.16.1
diff --git a/Procfile b/Procfile
index cad738d4292..1776fd97942 100644
--- a/Procfile
+++ b/Procfile
@@ -4,4 +4,3 @@
#
web: RAILS_ENV=development bin/web start_foreground
worker: RAILS_ENV=development bin/background_jobs start_foreground
-# mail_room: bundle exec mail_room -q -c config/mail_room.yml
diff --git a/VERSION b/VERSION
index f860e97e4cf..7a86eda5728 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-10.6.0-pre
+10.7.0-pre
diff --git a/app/assets/javascripts/boards/components/issue_card_inner.js b/app/assets/javascripts/boards/components/issue_card_inner.js
index 7e882a57202..8aee5b23c76 100644
--- a/app/assets/javascripts/boards/components/issue_card_inner.js
+++ b/app/assets/javascripts/boards/components/issue_card_inner.js
@@ -1,6 +1,6 @@
import $ from 'jquery';
import Vue from 'vue';
-import userAvatarLink from '../../vue_shared/components/user_avatar/user_avatar_link.vue';
+import UserAvatarLink from '../../vue_shared/components/user_avatar/user_avatar_link.vue';
import eventHub from '../eventhub';
const Store = gl.issueBoards.BoardsStore;
@@ -45,7 +45,7 @@ gl.issueBoards.IssueCardInner = Vue.extend({
};
},
components: {
- userAvatarLink,
+ UserAvatarLink,
},
computed: {
numberOverLimit() {
diff --git a/app/assets/javascripts/groups/components/app.vue b/app/assets/javascripts/groups/components/app.vue
index 63bb5832bd0..22eb7bd44c5 100644
--- a/app/assets/javascripts/groups/components/app.vue
+++ b/app/assets/javascripts/groups/components/app.vue
@@ -4,7 +4,7 @@
import $ from 'jquery';
import { s__ } from '~/locale';
import loadingIcon from '~/vue_shared/components/loading_icon.vue';
-import modal from '~/vue_shared/components/modal.vue';
+import DeprecatedModal from '~/vue_shared/components/deprecated_modal.vue';
import { getParameterByName } from '~/lib/utils/common_utils';
import { mergeUrlParams } from '~/lib/utils/url_utility';
@@ -15,7 +15,7 @@ import groupsComponent from './groups.vue';
export default {
components: {
loadingIcon,
- modal,
+ DeprecatedModal,
groupsComponent,
},
props: {
@@ -52,8 +52,9 @@ export default {
},
},
created() {
- this.searchEmptyMessage = this.hideProjects ?
- COMMON_STR.GROUP_SEARCH_EMPTY : COMMON_STR.GROUP_PROJECT_SEARCH_EMPTY;
+ this.searchEmptyMessage = this.hideProjects
+ ? COMMON_STR.GROUP_SEARCH_EMPTY
+ : COMMON_STR.GROUP_PROJECT_SEARCH_EMPTY;
eventHub.$on('fetchPage', this.fetchPage);
eventHub.$on('toggleChildren', this.toggleChildren);
@@ -72,22 +73,30 @@ export default {
eventHub.$off('updateGroups', this.updateGroups);
},
methods: {
- fetchGroups({ parentId, page, filterGroupsBy, sortBy, archived, updatePagination }) {
- return this.service.getGroups(parentId, page, filterGroupsBy, sortBy, archived)
- .then((res) => {
- if (updatePagination) {
- this.updatePagination(res.headers);
- }
+ fetchGroups({
+ parentId,
+ page,
+ filterGroupsBy,
+ sortBy,
+ archived,
+ updatePagination,
+ }) {
+ return this.service
+ .getGroups(parentId, page, filterGroupsBy, sortBy, archived)
+ .then(res => {
+ if (updatePagination) {
+ this.updatePagination(res.headers);
+ }
- return res;
- })
- .then(res => res.json())
- .catch(() => {
- this.isLoading = false;
- $.scrollTo(0);
+ return res;
+ })
+ .then(res => res.json())
+ .catch(() => {
+ this.isLoading = false;
+ $.scrollTo(0);
- Flash(COMMON_STR.FAILURE);
- });
+ Flash(COMMON_STR.FAILURE);
+ });
},
fetchAllGroups() {
const page = getParameterByName('page') || null;
@@ -103,7 +112,7 @@ export default {
sortBy,
archived,
updatePagination: true,
- }).then((res) => {
+ }).then(res => {
this.isLoading = false;
this.updateGroups(res, Boolean(filterGroupsBy));
});
@@ -118,14 +127,18 @@ export default {
sortBy,
archived,
updatePagination: true,
- }).then((res) => {
+ }).then(res => {
this.isLoading = false;
$.scrollTo(0);
const currentPath = mergeUrlParams({ page }, window.location.href);
- window.history.replaceState({
- page: currentPath,
- }, document.title, currentPath);
+ window.history.replaceState(
+ {
+ page: currentPath,
+ },
+ document.title,
+ currentPath,
+ );
this.updateGroups(res);
});
@@ -138,11 +151,13 @@ export default {
// eslint-disable-next-line promise/catch-or-return
this.fetchGroups({
parentId: parentGroup.id,
- }).then((res) => {
- this.store.setGroupChildren(parentGroup, res);
- }).catch(() => {
- parentGroup.isChildrenLoading = false;
- });
+ })
+ .then(res => {
+ this.store.setGroupChildren(parentGroup, res);
+ })
+ .catch(() => {
+ parentGroup.isChildrenLoading = false;
+ });
} else {
parentGroup.isOpen = true;
}
@@ -154,7 +169,11 @@ export default {
this.targetGroup = group;
this.targetParentGroup = parentGroup;
this.showModal = true;
- this.groupLeaveConfirmationMessage = s__(`GroupsTree|Are you sure you want to leave the "${group.fullName}" group?`);
+ this.groupLeaveConfirmationMessage = s__(
+ `GroupsTree|Are you sure you want to leave the "${
+ group.fullName
+ }" group?`,
+ );
},
hideLeaveGroupModal() {
this.showModal = false;
@@ -162,14 +181,15 @@ export default {
leaveGroup() {
this.showModal = false;
this.targetGroup.isBeingRemoved = true;
- this.service.leaveGroup(this.targetGroup.leavePath)
+ this.service
+ .leaveGroup(this.targetGroup.leavePath)
.then(res => res.json())
- .then((res) => {
+ .then(res => {
$.scrollTo(0);
this.store.removeGroup(this.targetGroup, this.targetParentGroup);
Flash(res.notice, 'notice');
})
- .catch((err) => {
+ .catch(err => {
let message = COMMON_STR.FAILURE;
if (err.status === 403) {
message = COMMON_STR.LEAVE_FORBIDDEN;
@@ -208,8 +228,8 @@ export default {
:search-empty-message="searchEmptyMessage"
:page-info="pageInfo"
/>
- <modal
- v-if="showModal"
+ <deprecated-modal
+ v-show="showModal"
kind="warning"
:primary-button-label="__('Leave')"
:title="__('Are you sure?')"
diff --git a/app/assets/javascripts/ide/components/new_dropdown/modal.vue b/app/assets/javascripts/ide/components/new_dropdown/modal.vue
index 5723891d130..4b5a50785b6 100644
--- a/app/assets/javascripts/ide/components/new_dropdown/modal.vue
+++ b/app/assets/javascripts/ide/components/new_dropdown/modal.vue
@@ -1,75 +1,75 @@
<script>
- import { __ } from '~/locale';
- import modal from '~/vue_shared/components/modal.vue';
+import { __ } from '~/locale';
+import DeprecatedModal from '~/vue_shared/components/deprecated_modal.vue';
- export default {
- components: {
- modal,
+export default {
+ components: {
+ DeprecatedModal,
+ },
+ props: {
+ branchId: {
+ type: String,
+ required: true,
},
- props: {
- branchId: {
- type: String,
- required: true,
- },
- type: {
- type: String,
- required: true,
- },
- path: {
- type: String,
- required: true,
- },
+ type: {
+ type: String,
+ required: true,
},
- data() {
- return {
- entryName: this.path !== '' ? `${this.path}/` : '',
- };
+ path: {
+ type: String,
+ required: true,
},
- computed: {
- modalTitle() {
- if (this.type === 'tree') {
- return __('Create new directory');
- }
+ },
+ data() {
+ return {
+ entryName: this.path !== '' ? `${this.path}/` : '',
+ };
+ },
+ computed: {
+ modalTitle() {
+ if (this.type === 'tree') {
+ return __('Create new directory');
+ }
- return __('Create new file');
- },
- buttonLabel() {
- if (this.type === 'tree') {
- return __('Create directory');
- }
-
- return __('Create file');
- },
- formLabelName() {
- if (this.type === 'tree') {
- return __('Directory name');
- }
+ return __('Create new file');
+ },
+ buttonLabel() {
+ if (this.type === 'tree') {
+ return __('Create directory');
+ }
- return __('File name');
- },
+ return __('Create file');
},
- mounted() {
- this.$refs.fieldName.focus();
+ formLabelName() {
+ if (this.type === 'tree') {
+ return __('Directory name');
+ }
+
+ return __('File name');
},
- methods: {
- createEntryInStore() {
- this.$emit('create', {
- branchId: this.branchId,
- name: this.entryName,
- type: this.type,
- });
+ },
+ mounted() {
+ this.$refs.fieldName.focus();
+ },
+ methods: {
+ createEntryInStore() {
+ this.$emit('create', {
+ branchId: this.branchId,
+ name: this.entryName,
+ type: this.type,
+ });
- this.hideModal();
- },
- hideModal() {
- this.$emit('hide');
- },
+ this.hideModal();
+ },
+ hideModal() {
+ this.$emit('hide');
},
- };
+ },
+};
</script>
<template>
- <modal
+ <deprecated-modal
:title="modalTitle"
:primary-button-label="buttonLabel"
kind="success"
@@ -95,5 +95,5 @@
</div>
</fieldset>
</form>
- </modal>
+ </deprecated-modal>
</template>
diff --git a/app/assets/javascripts/ide/components/repo_commit_section.vue b/app/assets/javascripts/ide/components/repo_commit_section.vue
index d772cab2d0e..d885ed5e301 100644
--- a/app/assets/javascripts/ide/components/repo_commit_section.vue
+++ b/app/assets/javascripts/ide/components/repo_commit_section.vue
@@ -2,7 +2,7 @@
import { mapState, mapActions, mapGetters } from 'vuex';
import tooltip from '~/vue_shared/directives/tooltip';
import icon from '~/vue_shared/components/icon.vue';
-import modal from '~/vue_shared/components/modal.vue';
+import DeprecatedModal from '~/vue_shared/components/deprecated_modal.vue';
import LoadingButton from '~/vue_shared/components/loading_button.vue';
import commitFilesList from './commit_sidebar/list.vue';
import * as consts from '../stores/modules/commit/constants';
@@ -10,7 +10,7 @@ import Actions from './commit_sidebar/actions.vue';
export default {
components: {
- modal,
+ DeprecatedModal,
icon,
commitFilesList,
Actions,
@@ -37,23 +37,20 @@ export default {
'lastCommitMsg',
'changedFiles',
]),
- ...mapState('commit', [
- 'commitMessage',
- 'submitCommitLoading',
- ]),
+ ...mapState('commit', ['commitMessage', 'submitCommitLoading']),
...mapGetters('commit', [
'commitButtonDisabled',
'discardDraftButtonDisabled',
'branchName',
]),
statusSvg() {
- return this.lastCommitMsg ? this.committedStateSvgPath : this.noChangesStateSvgPath;
+ return this.lastCommitMsg
+ ? this.committedStateSvgPath
+ : this.noChangesStateSvgPath;
},
},
methods: {
- ...mapActions([
- 'setPanelCollapsedStatus',
- ]),
+ ...mapActions(['setPanelCollapsedStatus']),
...mapActions('commit', [
'updateCommitMessage',
'discardDraft',
@@ -67,8 +64,9 @@ export default {
});
},
forceCreateNewBranch() {
- return this.updateCommitAction(consts.COMMIT_TO_NEW_BRANCH)
- .then(() => this.commitChanges());
+ return this.updateCommitAction(consts.COMMIT_TO_NEW_BRANCH).then(() =>
+ this.commitChanges(),
+ );
},
},
};
@@ -81,7 +79,7 @@ export default {
'multi-file-commit-empty-state-container': !changedFiles.length
}"
>
- <modal
+ <deprecated-modal
id="ide-create-branch-modal"
:primary-button-label="__('Create new branch')"
kind="success"
@@ -92,7 +90,7 @@ export default {
{{ __(`This branch has changed since you started editing.
Would you like to create a new branch?`) }}
</template>
- </modal>
+ </deprecated-modal>
<commit-files-list
title="Staged"
:file-list="changedFiles"
diff --git a/app/assets/javascripts/ide/components/repo_file.vue b/app/assets/javascripts/ide/components/repo_file.vue
index 03a40096bb0..297b9c2628f 100644
--- a/app/assets/javascripts/ide/components/repo_file.vue
+++ b/app/assets/javascripts/ide/components/repo_file.vue
@@ -43,6 +43,7 @@ export default {
'file-open': this.isBlob && this.file.opened,
'file-active': this.isBlob && this.file.active,
folder: this.isTree,
+ 'is-open': this.file.opened,
};
},
},
diff --git a/app/assets/javascripts/ide/ide_router.js b/app/assets/javascripts/ide/ide_router.js
index 048d5316922..db89c1d44db 100644
--- a/app/assets/javascripts/ide/ide_router.js
+++ b/app/assets/javascripts/ide/ide_router.js
@@ -54,41 +54,61 @@ const router = new VueRouter({
router.beforeEach((to, from, next) => {
if (to.params.namespace && to.params.project) {
- store.dispatch('getProjectData', {
- namespace: to.params.namespace,
- projectId: to.params.project,
- })
- .then(() => {
- const fullProjectId = `${to.params.namespace}/${to.params.project}`;
+ store
+ .dispatch('getProjectData', {
+ namespace: to.params.namespace,
+ projectId: to.params.project,
+ })
+ .then(() => {
+ const fullProjectId = `${to.params.namespace}/${to.params.project}`;
- if (to.params.branch) {
- store.dispatch('getBranchData', {
- projectId: fullProjectId,
- branchId: to.params.branch,
- });
+ if (to.params.branch) {
+ store.dispatch('getBranchData', {
+ projectId: fullProjectId,
+ branchId: to.params.branch,
+ });
- store.dispatch('getFiles', {
- projectId: fullProjectId,
- branchId: to.params.branch,
- })
- .then(() => {
- if (to.params[0]) {
- const treeEntry = store.state.entries[to.params[0]];
- if (treeEntry) {
- store.dispatch('handleTreeEntryAction', treeEntry);
- }
- }
- })
- .catch((e) => {
- flash('Error while loading the branch files. Please try again.', 'alert', document, null, false, true);
- throw e;
- });
- }
- })
- .catch((e) => {
- flash('Error while loading the project data. Please try again.', 'alert', document, null, false, true);
- throw e;
- });
+ store
+ .dispatch('getFiles', {
+ projectId: fullProjectId,
+ branchId: to.params.branch,
+ })
+ .then(() => {
+ if (to.params[0]) {
+ const path =
+ to.params[0].slice(-1) === '/'
+ ? to.params[0].slice(0, -1)
+ : to.params[0];
+ const treeEntry = store.state.entries[path];
+ if (treeEntry) {
+ store.dispatch('handleTreeEntryAction', treeEntry);
+ }
+ }
+ })
+ .catch(e => {
+ flash(
+ 'Error while loading the branch files. Please try again.',
+ 'alert',
+ document,
+ null,
+ false,
+ true,
+ );
+ throw e;
+ });
+ }
+ })
+ .catch(e => {
+ flash(
+ 'Error while loading the project data. Please try again.',
+ 'alert',
+ document,
+ null,
+ false,
+ true,
+ );
+ throw e;
+ });
}
next();
diff --git a/app/assets/javascripts/ide/stores/workers/files_decorator_worker.js b/app/assets/javascripts/ide/stores/workers/files_decorator_worker.js
index e959130300b..a4cd1ab099f 100644
--- a/app/assets/javascripts/ide/stores/workers/files_decorator_worker.js
+++ b/app/assets/javascripts/ide/stores/workers/files_decorator_worker.js
@@ -1,10 +1,14 @@
-import {
- decorateData,
- sortTree,
-} from '../utils';
+import { decorateData, sortTree } from '../utils';
-self.addEventListener('message', (e) => {
- const { data, projectId, branchId, tempFile = false, content = '', base64 = false } = e.data;
+self.addEventListener('message', e => {
+ const {
+ data,
+ projectId,
+ branchId,
+ tempFile = false,
+ content = '',
+ base64 = false,
+ } = e.data;
const treeList = [];
let file;
@@ -15,7 +19,9 @@ self.addEventListener('message', (e) => {
if (pathSplit.length > 0) {
pathSplit.reduce((pathAcc, folderName) => {
const parentFolder = acc[pathAcc[pathAcc.length - 1]];
- const folderPath = `${(parentFolder ? `${parentFolder.path}/` : '')}${folderName}`;
+ const folderPath = `${
+ parentFolder ? `${parentFolder.path}/` : ''
+ }${folderName}`;
const foundEntry = acc[folderPath];
if (!foundEntry) {
@@ -25,9 +31,11 @@ self.addEventListener('message', (e) => {
id: folderPath,
name: folderName,
path: folderPath,
- url: `/${projectId}/tree/${branchId}/${folderPath}`,
+ url: `/${projectId}/tree/${branchId}/${folderPath}/`,
type: 'tree',
- parentTreeUrl: parentFolder ? parentFolder.url : `/${projectId}/tree/${branchId}/`,
+ parentTreeUrl: parentFolder
+ ? parentFolder.url
+ : `/${projectId}/tree/${branchId}/`,
tempFile,
changed: tempFile,
opened: tempFile,
@@ -62,7 +70,9 @@ self.addEventListener('message', (e) => {
path,
url: `/${projectId}/blob/${branchId}/${path}`,
type: 'blob',
- parentTreeUrl: fileFolder ? fileFolder.url : `/${projectId}/blob/${branchId}`,
+ parentTreeUrl: fileFolder
+ ? fileFolder.url
+ : `/${projectId}/blob/${branchId}`,
tempFile,
changed: tempFile,
content,
diff --git a/app/assets/javascripts/notes.js b/app/assets/javascripts/notes.js
index 2afa4e4c1bf..09f0ea37103 100644
--- a/app/assets/javascripts/notes.js
+++ b/app/assets/javascripts/notes.js
@@ -1727,6 +1727,7 @@ export default class Notes {
// Get Form metadata
const $submitBtn = $(e.target);
+ $submitBtn.prop('disabled', true);
let $form = $submitBtn.parents('form');
const $closeBtn = $form.find('.js-note-target-close');
const isDiscussionNote =
@@ -1761,7 +1762,6 @@ export default class Notes {
// If comment is to resolve discussion, disable submit buttons while
// comment posting is finished.
if (isDiscussionResolve) {
- $submitBtn.disable();
$form.find('.js-comment-submit-button').disable();
}
@@ -1816,6 +1816,7 @@ export default class Notes {
.then(res => {
const note = res.data;
+ $submitBtn.prop('disabled', false);
// Submission successful! remove placeholder
$notesContainer.find(`#${noteUniqueId}`).remove();
@@ -1899,7 +1900,7 @@ export default class Notes {
.catch(() => {
// Submission failed, remove placeholder note and show Flash error message
$notesContainer.find(`#${noteUniqueId}`).remove();
-
+ $submitBtn.prop('disabled', false);
const blurEvent = new CustomEvent('blur.imageDiff', {
detail: e,
});
diff --git a/app/assets/javascripts/pages/admin/projects/index/components/delete_project_modal.vue b/app/assets/javascripts/pages/admin/projects/index/components/delete_project_modal.vue
index 14315d5492e..343c65edb37 100644
--- a/app/assets/javascripts/pages/admin/projects/index/components/delete_project_modal.vue
+++ b/app/assets/javascripts/pages/admin/projects/index/components/delete_project_modal.vue
@@ -1,11 +1,11 @@
<script>
import _ from 'underscore';
- import modal from '~/vue_shared/components/modal.vue';
+ import DeprecatedModal from '~/vue_shared/components/deprecated_modal.vue';
import { s__, sprintf } from '~/locale';
export default {
components: {
- modal,
+ DeprecatedModal,
},
props: {
deleteProjectUrl: {
@@ -79,7 +79,7 @@
</script>
<template>
- <modal
+ <deprecated-modal
id="delete-project-modal"
:title="title"
:text="text"
@@ -121,5 +121,5 @@
/>
</form>
</template>
- </modal>
+ </deprecated-modal>
</template>
diff --git a/app/assets/javascripts/pages/admin/users/components/delete_user_modal.vue b/app/assets/javascripts/pages/admin/users/components/delete_user_modal.vue
index 7b5e333011e..0e3ac636661 100644
--- a/app/assets/javascripts/pages/admin/users/components/delete_user_modal.vue
+++ b/app/assets/javascripts/pages/admin/users/components/delete_user_modal.vue
@@ -1,11 +1,11 @@
<script>
import _ from 'underscore';
- import modal from '~/vue_shared/components/modal.vue';
+ import DeprecatedModal from '~/vue_shared/components/deprecated_modal.vue';
import { s__, sprintf } from '~/locale';
export default {
components: {
- modal,
+ DeprecatedModal,
},
props: {
deleteUserUrl: {
@@ -113,7 +113,7 @@
</script>
<template>
- <modal
+ <deprecated-modal
id="delete-user-modal"
:title="title"
:text="text"
@@ -170,5 +170,5 @@
{{ secondaryButtonLabel }}
</button>
</template>
- </modal>
+ </deprecated-modal>
</template>
diff --git a/app/assets/javascripts/pages/milestones/shared/components/delete_milestone_modal.vue b/app/assets/javascripts/pages/milestones/shared/components/delete_milestone_modal.vue
index c43e0a0490f..16f792d635a 100644
--- a/app/assets/javascripts/pages/milestones/shared/components/delete_milestone_modal.vue
+++ b/app/assets/javascripts/pages/milestones/shared/components/delete_milestone_modal.vue
@@ -2,14 +2,14 @@
import axios from '~/lib/utils/axios_utils';
import Flash from '~/flash';
- import modal from '~/vue_shared/components/modal.vue';
+ import DeprecatedModal from '~/vue_shared/components/deprecated_modal.vue';
import { n__, s__, sprintf } from '~/locale';
import { redirectTo } from '~/lib/utils/url_utility';
import eventHub from '../event_hub';
export default {
components: {
- modal,
+ DeprecatedModal,
},
props: {
issueCount: {
@@ -92,7 +92,7 @@ Once deleted, it cannot be undone or recovered.`),
</script>
<template>
- <modal
+ <deprecated-modal
id="delete-milestone-modal"
:title="title"
:text="text"
@@ -106,5 +106,5 @@ Once deleted, it cannot be undone or recovered.`),
<p v-html="props.text"></p>
</template>
- </modal>
+ </deprecated-modal>
</template>
diff --git a/app/assets/javascripts/performance_bar/components/detailed_metric.vue b/app/assets/javascripts/performance_bar/components/detailed_metric.vue
index 145465f4ee9..db8a0055acd 100644
--- a/app/assets/javascripts/performance_bar/components/detailed_metric.vue
+++ b/app/assets/javascripts/performance_bar/components/detailed_metric.vue
@@ -27,12 +27,21 @@ export default {
required: true,
},
},
+ computed: {
+ metricDetails() {
+ return this.currentRequest.details[this.metric];
+ },
+ detailsList() {
+ return this.metricDetails[this.details];
+ },
+ },
};
</script>
<template>
<div
:id="`peek-view-${metric}`"
class="view"
+ v-if="currentRequest.details"
>
<button
:data-target="`#modal-peek-${metric}-details`"
@@ -40,34 +49,40 @@ export default {
type="button"
data-toggle="modal"
>
- <span
- v-if="currentRequest.details"
- class="bold"
- >
- {{ currentRequest.details[metric].duration }}
- /
- {{ currentRequest.details[metric].calls }}
- </span>
+ {{ metricDetails.duration }}
+ /
+ {{ metricDetails.calls }}
</button>
<gl-modal
- v-if="currentRequest.details"
:id="`modal-peek-${metric}-details`"
:header-title-text="header"
class="performance-bar-modal"
>
- <table class="table">
- <tr
- v-for="(item, index) in currentRequest.details[metric][details]"
- :key="index"
- >
- <td><strong>{{ item.duration }}ms</strong></td>
- <td
- v-for="key in keys"
- :key="key"
+ <table
+ class="table"
+ >
+ <template v-if="detailsList.length">
+ <tr
+ v-for="(item, index) in detailsList"
+ :key="index"
>
- {{ item[key] }}
- </td>
- </tr>
+ <td><strong>{{ item.duration }}ms</strong></td>
+ <td
+ v-for="key in keys"
+ :key="key"
+ class="break-word"
+ >
+ {{ item[key] }}
+ </td>
+ </tr>
+ </template>
+ <template v-else>
+ <tr>
+ <td>
+ No {{ header.toLowerCase() }} for this request.
+ </td>
+ </tr>
+ </template>
</table>
<div slot="footer">
diff --git a/app/assets/javascripts/performance_bar/components/performance_bar_app.vue b/app/assets/javascripts/performance_bar/components/performance_bar_app.vue
index 88345cf2ad9..2fd1715ee79 100644
--- a/app/assets/javascripts/performance_bar/components/performance_bar_app.vue
+++ b/app/assets/javascripts/performance_bar/components/performance_bar_app.vue
@@ -113,27 +113,21 @@ export default {
id="js-peek"
:class="env"
>
- <request-selector
- v-if="currentRequest"
- :current-request="currentRequest"
- :requests="requests"
- @change-current-request="changeCurrentRequest"
- />
- <div
- id="peek-view-host"
- class="view prepend-left-5"
- >
- <span
- v-if="currentRequest && currentRequest.details"
- class="current-host"
- >
- {{ currentRequest.details.host.hostname }}
- </span>
- </div>
<div
v-if="currentRequest"
- class="wrapper"
+ class="container-fluid container-limited"
>
+ <div
+ id="peek-view-host"
+ class="view"
+ >
+ <span
+ v-if="currentRequest.details"
+ class="current-host"
+ >
+ {{ currentRequest.details.host.hostname }}
+ </span>
+ </div>
<upstream-performance-bar
v-if="initialRequest && currentRequest.details"
/>
@@ -186,6 +180,12 @@ export default {
gc
</span>
</div>
+ <request-selector
+ v-if="currentRequest"
+ :current-request="currentRequest"
+ :requests="requests"
+ @change-current-request="changeCurrentRequest"
+ />
</div>
</div>
</template>
diff --git a/app/assets/javascripts/performance_bar/components/request_selector.vue b/app/assets/javascripts/performance_bar/components/request_selector.vue
index 2f360ea6f6c..3ed07a4a47d 100644
--- a/app/assets/javascripts/performance_bar/components/request_selector.vue
+++ b/app/assets/javascripts/performance_bar/components/request_selector.vue
@@ -37,7 +37,7 @@ export default {
<template>
<div
id="peek-request-selector"
- class="append-right-5 pull-right"
+ class="pull-right"
>
<select v-model="currentRequestId">
<option
diff --git a/app/assets/javascripts/performance_bar/components/upstream_performance_bar.vue b/app/assets/javascripts/performance_bar/components/upstream_performance_bar.vue
index d438b1ec27b..2b5915f381f 100644
--- a/app/assets/javascripts/performance_bar/components/upstream_performance_bar.vue
+++ b/app/assets/javascripts/performance_bar/components/upstream_performance_bar.vue
@@ -5,6 +5,8 @@ export default {
.getElementById('peek-view-performance-bar')
.cloneNode(true);
+ upstreamPerformanceBar.classList.remove('hidden');
+
this.$refs.wrapper.appendChild(upstreamPerformanceBar);
},
};
diff --git a/app/assets/javascripts/performance_bar/index.js b/app/assets/javascripts/performance_bar/index.js
index fca488120f6..a0ddf36a672 100644
--- a/app/assets/javascripts/performance_bar/index.js
+++ b/app/assets/javascripts/performance_bar/index.js
@@ -4,9 +4,9 @@ import Vue from 'vue';
import performanceBarApp from './components/performance_bar_app.vue';
import PerformanceBarStore from './stores/performance_bar_store';
-export default () =>
+export default ({ container }) =>
new Vue({
- el: '#js-peek',
+ el: container,
components: {
performanceBarApp,
},
diff --git a/app/assets/javascripts/pipelines/components/pipelines_table.vue b/app/assets/javascripts/pipelines/components/pipelines_table.vue
index c9028952ddd..714aed1333e 100644
--- a/app/assets/javascripts/pipelines/components/pipelines_table.vue
+++ b/app/assets/javascripts/pipelines/components/pipelines_table.vue
@@ -1,5 +1,5 @@
<script>
- import modal from '~/vue_shared/components/modal.vue';
+ import DeprecatedModal from '~/vue_shared/components/deprecated_modal.vue';
import { s__, sprintf } from '~/locale';
import pipelinesTableRowComponent from './pipelines_table_row.vue';
import eventHub from '../event_hub';
@@ -12,7 +12,7 @@
export default {
components: {
pipelinesTableRowComponent,
- modal,
+ DeprecatedModal,
},
props: {
pipelines: {
@@ -120,7 +120,7 @@
:auto-devops-help-path="autoDevopsHelpPath"
:view-type="viewType"
/>
- <modal
+ <deprecated-modal
id="confirmation-modal"
:title="modalTitle"
:text="modalText"
@@ -134,6 +134,6 @@
>
<p v-html="props.text"></p>
</template>
- </modal>
+ </deprecated-modal>
</div>
</template>
diff --git a/app/assets/javascripts/profile/account/components/delete_account_modal.vue b/app/assets/javascripts/profile/account/components/delete_account_modal.vue
index 1ffe482d782..f50002afbf2 100644
--- a/app/assets/javascripts/profile/account/components/delete_account_modal.vue
+++ b/app/assets/javascripts/profile/account/components/delete_account_modal.vue
@@ -1,11 +1,11 @@
<script>
- import modal from '~/vue_shared/components/modal.vue';
+ import DeprecatedModal from '~/vue_shared/components/deprecated_modal.vue';
import { __, s__, sprintf } from '~/locale';
import csrf from '~/lib/utils/csrf';
export default {
components: {
- modal,
+ DeprecatedModal,
},
props: {
actionUrl: {
@@ -76,7 +76,7 @@ Once you confirm %{deleteAccount}, it cannot be undone or recovered.`),
</script>
<template>
- <modal
+ <deprecated-modal
id="delete-account-modal"
:title="s__('Profiles|Delete your account?')"
:text="text"
@@ -131,5 +131,5 @@ Once you confirm %{deleteAccount}, it cannot be undone or recovered.`),
</form>
</template>
- </modal>
+ </deprecated-modal>
</template>
diff --git a/app/assets/javascripts/sidebar/components/time_tracking/collapsed_state.js b/app/assets/javascripts/sidebar/components/time_tracking/collapsed_state.js
deleted file mode 100644
index a9fbc7f1a2f..00000000000
--- a/app/assets/javascripts/sidebar/components/time_tracking/collapsed_state.js
+++ /dev/null
@@ -1,96 +0,0 @@
-import stopwatchSvg from 'icons/_icon_stopwatch.svg';
-import { abbreviateTime } from '../../../lib/utils/pretty_time';
-
-export default {
- name: 'time-tracking-collapsed-state',
- props: {
- showComparisonState: {
- type: Boolean,
- required: true,
- },
- showSpentOnlyState: {
- type: Boolean,
- required: true,
- },
- showEstimateOnlyState: {
- type: Boolean,
- required: true,
- },
- showNoTimeTrackingState: {
- type: Boolean,
- required: true,
- },
- timeSpentHumanReadable: {
- type: String,
- required: false,
- default: '',
- },
- timeEstimateHumanReadable: {
- type: String,
- required: false,
- default: '',
- },
- },
- computed: {
- timeSpent() {
- return this.abbreviateTime(this.timeSpentHumanReadable);
- },
- timeEstimate() {
- return this.abbreviateTime(this.timeEstimateHumanReadable);
- },
- divClass() {
- if (this.showComparisonState) {
- return 'compare';
- } else if (this.showEstimateOnlyState) {
- return 'estimate-only';
- } else if (this.showSpentOnlyState) {
- return 'spend-only';
- } else if (this.showNoTimeTrackingState) {
- return 'no-tracking';
- }
-
- return '';
- },
- spanClass() {
- if (this.showComparisonState) {
- return '';
- } else if (this.showEstimateOnlyState || this.showSpentOnlyState) {
- return 'bold';
- } else if (this.showNoTimeTrackingState) {
- return 'no-value';
- }
-
- return '';
- },
- text() {
- if (this.showComparisonState) {
- return `${this.timeSpent} / ${this.timeEstimate}`;
- } else if (this.showEstimateOnlyState) {
- return `-- / ${this.timeEstimate}`;
- } else if (this.showSpentOnlyState) {
- return `${this.timeSpent} / --`;
- } else if (this.showNoTimeTrackingState) {
- return 'None';
- }
-
- return '';
- },
- },
- methods: {
- abbreviateTime(timeStr) {
- return abbreviateTime(timeStr);
- },
- },
- template: `
- <div class="sidebar-collapsed-icon">
- ${stopwatchSvg}
- <div class="time-tracking-collapsed-summary">
- <div :class="divClass">
- <span :class="spanClass">
- {{ text }}
- </span>
- </div>
- </div>
- </div>
- `,
-};
diff --git a/app/assets/javascripts/sidebar/components/time_tracking/collapsed_state.vue b/app/assets/javascripts/sidebar/components/time_tracking/collapsed_state.vue
new file mode 100644
index 00000000000..3b86f1145d1
--- /dev/null
+++ b/app/assets/javascripts/sidebar/components/time_tracking/collapsed_state.vue
@@ -0,0 +1,102 @@
+<script>
+ import icon from '../../../vue_shared/components/icon.vue';
+ import { abbreviateTime } from '../../../lib/utils/pretty_time';
+
+ export default {
+ name: 'TimeTrackingCollapsedState',
+ components: {
+ icon,
+ },
+ props: {
+ showComparisonState: {
+ type: Boolean,
+ required: true,
+ },
+ showSpentOnlyState: {
+ type: Boolean,
+ required: true,
+ },
+ showEstimateOnlyState: {
+ type: Boolean,
+ required: true,
+ },
+ showNoTimeTrackingState: {
+ type: Boolean,
+ required: true,
+ },
+ timeSpentHumanReadable: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ timeEstimateHumanReadable: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ },
+ computed: {
+ timeSpent() {
+ return this.abbreviateTime(this.timeSpentHumanReadable);
+ },
+ timeEstimate() {
+ return this.abbreviateTime(this.timeEstimateHumanReadable);
+ },
+ divClass() {
+ if (this.showComparisonState) {
+ return 'compare';
+ } else if (this.showEstimateOnlyState) {
+ return 'estimate-only';
+ } else if (this.showSpentOnlyState) {
+ return 'spend-only';
+ } else if (this.showNoTimeTrackingState) {
+ return 'no-tracking';
+ }
+
+ return '';
+ },
+ spanClass() {
+ if (this.showComparisonState) {
+ return '';
+ } else if (this.showEstimateOnlyState || this.showSpentOnlyState) {
+ return 'bold';
+ } else if (this.showNoTimeTrackingState) {
+ return 'no-value';
+ }
+
+ return '';
+ },
+ text() {
+ if (this.showComparisonState) {
+ return `${this.timeSpent} / ${this.timeEstimate}`;
+ } else if (this.showEstimateOnlyState) {
+ return `-- / ${this.timeEstimate}`;
+ } else if (this.showSpentOnlyState) {
+ return `${this.timeSpent} / --`;
+ } else if (this.showNoTimeTrackingState) {
+ return 'None';
+ }
+
+ return '';
+ },
+ },
+ methods: {
+ abbreviateTime(timeStr) {
+ return abbreviateTime(timeStr);
+ },
+ },
+ };
+</script>
+
+<template>
+ <div class="sidebar-collapsed-icon">
+ <icon name="timer" />
+ <div class="time-tracking-collapsed-summary">
+ <div :class="divClass">
+ <span :class="spanClass">
+ {{ text }}
+ </span>
+ </div>
+ </div>
+ </div>
+</template>
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 230736a56b8..28240468d2c 100644
--- a/app/assets/javascripts/sidebar/components/time_tracking/time_tracker.vue
+++ b/app/assets/javascripts/sidebar/components/time_tracking/time_tracker.vue
@@ -1,6 +1,6 @@
<script>
import timeTrackingHelpState from './help_state';
-import timeTrackingCollapsedState from './collapsed_state';
+import TimeTrackingCollapsedState from './collapsed_state.vue';
import timeTrackingSpentOnlyPane from './spent_only_pane';
import timeTrackingNoTrackingPane from './no_tracking_pane';
import timeTrackingEstimateOnlyPane from './estimate_only_pane';
@@ -11,7 +11,7 @@ import eventHub from '../../event_hub';
export default {
name: 'IssuableTimeTracker',
components: {
- 'time-tracking-collapsed-state': timeTrackingCollapsedState,
+ TimeTrackingCollapsedState,
'time-tracking-estimate-only-pane': timeTrackingEstimateOnlyPane,
'time-tracking-spent-only-pane': timeTrackingSpentOnlyPane,
'time-tracking-no-tracking-pane': timeTrackingNoTrackingPane,
diff --git a/app/assets/javascripts/vue_shared/components/modal.vue b/app/assets/javascripts/vue_shared/components/deprecated_modal.vue
index 5f1364421aa..dcf1489b37c 100644
--- a/app/assets/javascripts/vue_shared/components/modal.vue
+++ b/app/assets/javascripts/vue_shared/components/deprecated_modal.vue
@@ -1,7 +1,7 @@
<script>
/* eslint-disable vue/require-default-prop */
export default {
- name: 'Modal',
+ name: 'DeprecatedModal', // use GlModal instead
props: {
id: {
diff --git a/app/assets/javascripts/vue_shared/components/file_icon.vue b/app/assets/javascripts/vue_shared/components/file_icon.vue
index c9d7c0f4999..ee1c3498748 100644
--- a/app/assets/javascripts/vue_shared/components/file_icon.vue
+++ b/app/assets/javascripts/vue_shared/components/file_icon.vue
@@ -62,8 +62,7 @@
return `${gon.sprite_file_icons}#${iconName}`;
},
folderIconName() {
- // We don't have a open folder icon yet
- return this.opened ? 'folder' : 'folder';
+ return this.opened ? 'folder-open' : 'folder';
},
iconSizeClass() {
return this.size ? `s${this.size}` : '';
diff --git a/app/assets/javascripts/vue_shared/components/recaptcha_modal.vue b/app/assets/javascripts/vue_shared/components/recaptcha_modal.vue
index c35621c9ef3..21ffdc1dc86 100644
--- a/app/assets/javascripts/vue_shared/components/recaptcha_modal.vue
+++ b/app/assets/javascripts/vue_shared/components/recaptcha_modal.vue
@@ -1,11 +1,11 @@
<script>
- import modal from './modal.vue';
+ import DeprecatedModal from './deprecated_modal.vue';
export default {
name: 'RecaptchaModal',
components: {
- modal,
+ DeprecatedModal,
},
props: {
@@ -65,7 +65,7 @@
</script>
<template>
- <modal
+ <deprecated-modal
kind="warning"
class="recaptcha-modal js-recaptcha-modal"
:hide-footer="true"
@@ -82,5 +82,5 @@
>
</div>
</div>
- </modal>
+ </deprecated-modal>
</template>
diff --git a/app/assets/stylesheets/framework/common.scss b/app/assets/stylesheets/framework/common.scss
index 37d33320445..d0dda50a835 100644
--- a/app/assets/stylesheets/framework/common.scss
+++ b/app/assets/stylesheets/framework/common.scss
@@ -446,6 +446,10 @@ img.emoji {
opacity: .5;
}
+.break-word {
+ word-wrap: break-word;
+}
+
/** COMMON CLASSES **/
.prepend-top-0 { margin-top: 0; }
.prepend-top-5 { margin-top: 5px; }
diff --git a/app/assets/stylesheets/framework/dropdowns.scss b/app/assets/stylesheets/framework/dropdowns.scss
index 6397757bf88..cc74cb72795 100644
--- a/app/assets/stylesheets/framework/dropdowns.scss
+++ b/app/assets/stylesheets/framework/dropdowns.scss
@@ -622,7 +622,7 @@
}
.dropdown-content {
- max-height: $dropdown-max-height;
+ max-height: 252px;
overflow-y: auto;
}
@@ -699,6 +699,31 @@
border-radius: $border-radius-base;
}
+.git-revision-dropdown {
+ .dropdown-content {
+ max-height: 215px;
+ }
+}
+
+.sidebar-move-issue-dropdown {
+ .dropdown-content {
+ max-height: 160px;
+ }
+}
+
+.dropdown-menu-author {
+ .dropdown-content {
+ max-height: 215px;
+ }
+}
+
+.dropdown-menu-labels {
+ .dropdown-content {
+ max-height: 128px;
+ }
+}
+
+
.dropdown-menu-due-date {
.dropdown-content {
max-height: 230px;
diff --git a/app/assets/stylesheets/framework/sidebar.scss b/app/assets/stylesheets/framework/sidebar.scss
index d1d98270ad9..3dd4a613789 100644
--- a/app/assets/stylesheets/framework/sidebar.scss
+++ b/app/assets/stylesheets/framework/sidebar.scss
@@ -152,3 +152,4 @@
.sidebar-collapsed-icon .sidebar-collapsed-value {
font-size: 12px;
}
+
diff --git a/app/assets/stylesheets/pages/boards.scss b/app/assets/stylesheets/pages/boards.scss
index c03d4c2eebf..318d3ddaece 100644
--- a/app/assets/stylesheets/pages/boards.scss
+++ b/app/assets/stylesheets/pages/boards.scss
@@ -31,8 +31,12 @@
.dropdown-menu-issues-board-new {
width: 320px;
+ .open & {
+ max-height: 400px;
+ }
+
.dropdown-content {
- max-height: 150px;
+ max-height: 162px;
}
}
diff --git a/app/assets/stylesheets/pages/branches.scss b/app/assets/stylesheets/pages/branches.scss
index 3e2fa8ca88d..49fe50977f5 100644
--- a/app/assets/stylesheets/pages/branches.scss
+++ b/app/assets/stylesheets/pages/branches.scss
@@ -1,6 +1,17 @@
+.content-list > .branch-item,
+.branch-title {
+ display: flex;
+ align-items: center;
+}
+
+.branch-info {
+ flex: auto;
+ min-width: 0;
+ overflow: hidden;
+}
+
.divergence-graph {
- padding: 12px 12px 0 0;
- float: right;
+ padding: 0 6px;
.graph-side {
position: relative;
@@ -53,3 +64,9 @@
background-color: $divergence-graph-separator-bg;
}
}
+
+.divergence-graph,
+.branch-item .controls {
+ flex: 0 0 auto;
+ white-space: nowrap;
+}
diff --git a/app/assets/stylesheets/pages/events.scss b/app/assets/stylesheets/pages/events.scss
index 8871a069d5d..d9267f5cdf3 100644
--- a/app/assets/stylesheets/pages/events.scss
+++ b/app/assets/stylesheets/pages/events.scss
@@ -162,17 +162,14 @@
* Last push widget
*/
.event-last-push {
- overflow: auto;
width: 100%;
+ display: flex;
+ align-items: center;
.event-last-push-text {
@include str-truncated(100%);
- padding: 4px 0;
font-size: 13px;
- float: left;
- margin-right: -150px;
- padding-right: 150px;
- line-height: 20px;
+ margin-right: $gl-padding;
}
}
diff --git a/app/assets/stylesheets/pages/labels.scss b/app/assets/stylesheets/pages/labels.scss
index 0f49d15203b..b0852adb459 100644
--- a/app/assets/stylesheets/pages/labels.scss
+++ b/app/assets/stylesheets/pages/labels.scss
@@ -26,9 +26,15 @@
}
}
+.dropdown-menu-labels {
+ .dropdown-content {
+ max-height: 135px;
+ }
+}
+
.dropdown-new-label {
.dropdown-content {
- max-height: 260px;
+ max-height: 136px;
}
}
diff --git a/app/assets/stylesheets/pages/projects.scss b/app/assets/stylesheets/pages/projects.scss
index 85de0d8e70f..584b0579b72 100644
--- a/app/assets/stylesheets/pages/projects.scss
+++ b/app/assets/stylesheets/pages/projects.scss
@@ -9,7 +9,6 @@
.new_project,
.edit-project,
.import-project {
-
.help-block {
margin-bottom: 10px;
}
@@ -18,18 +17,25 @@
border-radius: $border-radius-base;
}
- .input-group > div {
+ .input-group {
+ display: flex;
- &:last-child {
- padding-right: 0;
+ .select2-container {
+ display: unset;
+ max-width: unset;
+ width: unset !important;
+ flex-grow: 1;
+ }
+
+ > div {
+ &:last-child {
+ padding-right: 0;
+ }
}
}
@media (max-width: $screen-xs-max) {
.input-group > div {
-
- margin-bottom: 14px;
-
&:last-child {
margin-bottom: 0;
}
@@ -41,17 +47,24 @@
}
.input-group-addon {
+ overflow: hidden;
+ text-overflow: ellipsis;
+ line-height: unset;
+ width: unset;
+ max-width: 50%;
+ text-align: left;
&.static-namespace {
height: 35px;
border-radius: 3px;
border: 1px solid $border-color;
+ max-width: 100%;
+ flex-grow: 1;
}
+ .select2 a,
+ .btn-default {
- border-top-left-radius: 0;
- border-bottom-left-radius: 0;
+ border-radius: 0 $border-radius-base $border-radius-base 0;
}
}
}
@@ -290,7 +303,7 @@
font-size: 13px;
font-weight: $gl-font-weight-bold;
line-height: 13px;
- letter-spacing: .4px;
+ letter-spacing: 0.4px;
padding: 6px 14px;
text-align: center;
vertical-align: middle;
@@ -443,7 +456,7 @@ a.deploy-project-label {
text-decoration: none;
&.disabled {
- opacity: .3;
+ opacity: 0.3;
cursor: not-allowed;
}
}
@@ -600,26 +613,26 @@ a.deploy-project-label {
}
.first-column {
- @media(min-width: $screen-xs-min) {
+ @media (min-width: $screen-xs-min) {
max-width: 50%;
padding-right: 30px;
}
- @media(max-width: $screen-xs-max) {
+ @media (max-width: $screen-xs-max) {
max-width: 100%;
width: 100%;
}
}
.second-column {
- @media(min-width: $screen-xs-min) {
+ @media (min-width: $screen-xs-min) {
width: 50%;
flex: 1;
padding-left: 30px;
position: relative;
}
- @media(max-width: $screen-xs-max) {
+ @media (max-width: $screen-xs-max) {
max-width: 100%;
width: 100%;
padding-left: 0;
@@ -632,7 +645,7 @@ a.deploy-project-label {
}
&::before {
- content: "OR";
+ content: 'OR';
position: absolute;
left: -10px;
top: 50%;
@@ -656,7 +669,7 @@ a.deploy-project-label {
}
&::after {
- content: "";
+ content: '';
position: absolute;
background-color: $border-color;
bottom: 0;
@@ -921,10 +934,7 @@ pre.light-well {
border-right: solid 1px transparent;
}
}
-}
-.protected-tags-list,
-.protected-branches-list {
.dropdown-menu-toggle {
width: 100%;
max-width: 300px;
diff --git a/app/assets/stylesheets/pages/search.scss b/app/assets/stylesheets/pages/search.scss
index c9363188505..dbde0720993 100644
--- a/app/assets/stylesheets/pages/search.scss
+++ b/app/assets/stylesheets/pages/search.scss
@@ -112,7 +112,7 @@ input[type="checkbox"]:hover {
}
.dropdown-content {
- max-height: 350px;
+ max-height: 302px;
}
}
diff --git a/app/assets/stylesheets/performance_bar.scss b/app/assets/stylesheets/performance_bar.scss
index 03ecf3ef3cc..45ae94abaff 100644
--- a/app/assets/stylesheets/performance_bar.scss
+++ b/app/assets/stylesheets/performance_bar.scss
@@ -47,12 +47,6 @@
}
}
- .wrapper {
- width: 80%;
- height: $performance-bar-height;
- margin: 0 auto;
- }
-
// UI Elements
.bucket {
background: $perf-bar-bucket-bg;
@@ -112,8 +106,14 @@
}
}
- .performance-bar-modal .modal-footer {
- display: none;
+ .performance-bar-modal {
+ .modal-footer {
+ display: none;
+ }
+
+ .modal-dialog {
+ width: 860px;
+ }
}
}
diff --git a/app/controllers/admin/application_controller.rb b/app/controllers/admin/application_controller.rb
index c27f2ee3c09..a4648b33cfa 100644
--- a/app/controllers/admin/application_controller.rb
+++ b/app/controllers/admin/application_controller.rb
@@ -3,23 +3,9 @@
# Automatically sets the layout and ensures an administrator is logged in
class Admin::ApplicationController < ApplicationController
before_action :authenticate_admin!
- before_action :display_read_only_information
layout 'admin'
def authenticate_admin!
render_404 unless current_user.admin?
end
-
- def display_read_only_information
- return unless Gitlab::Database.read_only?
-
- flash.now[:notice] = read_only_message
- end
-
- private
-
- # Overridden in EE
- def read_only_message
- _('You are on a read-only GitLab instance.')
- end
end
diff --git a/app/controllers/omniauth_callbacks_controller.rb b/app/controllers/omniauth_callbacks_controller.rb
index 8440945ab43..5e6676ea513 100644
--- a/app/controllers/omniauth_callbacks_controller.rb
+++ b/app/controllers/omniauth_callbacks_controller.rb
@@ -18,6 +18,18 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController
end
end
+ # Extend the standard implementation to also increment
+ # the number of failed sign in attempts
+ def failure
+ if params[:username].present? && AuthHelper.form_based_provider?(failed_strategy.name)
+ user = User.by_login(params[:username])
+
+ user&.increment_failed_attempts!
+ end
+
+ super
+ end
+
# Extend the standard message generation to accept our custom exception
def failure_message
exception = env["omniauth.error"]
@@ -95,6 +107,14 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController
handle_omniauth
end
+ def auth0
+ if oauth['uid'].blank?
+ fail_auth0_login
+ else
+ handle_omniauth
+ end
+ end
+
private
def handle_omniauth
@@ -170,6 +190,12 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController
redirect_to new_user_session_path
end
+ def fail_auth0_login
+ flash[:alert] = 'Wrong extern UID provided. Make sure Auth0 is configured correctly.'
+
+ redirect_to new_user_session_path
+ end
+
def handle_disabled_provider
label = Gitlab::Auth::OAuth::Provider.label_for(oauth['provider'])
flash[:alert] = "Signing in using #{label} has been disabled"
diff --git a/app/controllers/projects/pages_controller.rb b/app/controllers/projects/pages_controller.rb
index d421b1a8eb5..cae6e2c40b8 100644
--- a/app/controllers/projects/pages_controller.rb
+++ b/app/controllers/projects/pages_controller.rb
@@ -21,4 +21,26 @@ class Projects::PagesController < Projects::ApplicationController
end
end
end
+
+ def update
+ result = Projects::UpdateService.new(@project, current_user, project_params).execute
+
+ respond_to do |format|
+ format.html do
+ if result[:status] == :success
+ flash[:notice] = 'Your changes have been saved'
+ else
+ flash[:alert] = 'Something went wrong on our end'
+ end
+
+ redirect_to project_pages_path(@project)
+ end
+ end
+ end
+
+ private
+
+ def project_params
+ params.require(:project).permit(:pages_https_only)
+ end
end
diff --git a/app/controllers/projects/pipelines_settings_controller.rb b/app/controllers/projects/pipelines_settings_controller.rb
index 06ce7328fb5..557671ab186 100644
--- a/app/controllers/projects/pipelines_settings_controller.rb
+++ b/app/controllers/projects/pipelines_settings_controller.rb
@@ -10,10 +10,7 @@ class Projects::PipelinesSettingsController < Projects::ApplicationController
if service.execute
flash[:notice] = "Pipelines settings for '#{@project.name}' were successfully updated."
- if service.run_auto_devops_pipeline?
- CreatePipelineWorker.perform_async(project.id, current_user.id, project.default_branch, :web, ignore_skip_ci: true, save_on_errors: false)
- flash[:success] = "A new Auto DevOps pipeline has been created, go to <a href=\"#{project_pipelines_path(@project)}\">Pipelines page</a> for details".html_safe
- end
+ run_autodevops_pipeline(service)
redirect_to project_settings_ci_cd_path(@project)
else
@@ -24,6 +21,18 @@ class Projects::PipelinesSettingsController < Projects::ApplicationController
private
+ def run_autodevops_pipeline(service)
+ return unless service.run_auto_devops_pipeline?
+
+ if @project.empty_repo?
+ flash[:warning] = "This repository is currently empty. A new Auto DevOps pipeline will be created after a new file has been pushed to a branch."
+ return
+ end
+
+ CreatePipelineWorker.perform_async(project.id, current_user.id, project.default_branch, :web, ignore_skip_ci: true, save_on_errors: false)
+ flash[:success] = "A new Auto DevOps pipeline has been created, go to <a href=\"#{project_pipelines_path(@project)}\">Pipelines page</a> for details".html_safe
+ end
+
def update_params
params.require(:project).permit(
:runners_token, :builds_enabled, :build_allow_git_fetch,
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index 3ddf8eb3369..701be97ee96 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -323,4 +323,11 @@ module ApplicationHelper
def locale_path
asset_path("locale/#{Gitlab::I18n.locale}/app.js")
end
+
+ # Overridden in EE
+ def read_only_message
+ return unless Gitlab::Database.read_only?
+
+ _('You are on a read-only GitLab instance.')
+ end
end
diff --git a/app/helpers/application_settings_helper.rb b/app/helpers/application_settings_helper.rb
index 4c4d7cca8a5..b3b080e6dcf 100644
--- a/app/helpers/application_settings_helper.rb
+++ b/app/helpers/application_settings_helper.rb
@@ -96,7 +96,7 @@ module ApplicationSettingsHelper
def repository_storages_options_for_select(selected)
options = Gitlab.config.repositories.storages.map do |name, storage|
- ["#{name} - #{storage['path']}", name]
+ ["#{name} - #{storage['gitaly_address']}", name]
end
options_for_select(options, selected)
@@ -245,7 +245,8 @@ module ApplicationSettingsHelper
:usage_ping_enabled,
:user_default_external,
:user_oauth_applications,
- :version_check_enabled
+ :version_check_enabled,
+ :allow_local_requests_from_hooks_and_services
]
end
end
diff --git a/app/helpers/issuables_helper.rb b/app/helpers/issuables_helper.rb
index f6ddb6d4cfe..6d6b840f485 100644
--- a/app/helpers/issuables_helper.rb
+++ b/app/helpers/issuables_helper.rb
@@ -377,4 +377,11 @@ module IssuablesHelper
def parent
@project || @group
end
+
+ def issuable_milestone_tooltip_title(issuable)
+ if issuable.milestone
+ milestone_tooltip = milestone_tooltip_title(issuable.milestone)
+ _('Milestone') + (milestone_tooltip ? ': ' + milestone_tooltip : '')
+ end
+ end
end
diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb
index da9fe734f1c..15f48e43a28 100644
--- a/app/helpers/projects_helper.rb
+++ b/app/helpers/projects_helper.rb
@@ -531,4 +531,22 @@ module ProjectsHelper
def can_show_last_commit_in_list?(project)
can?(current_user, :read_cross_project) && project.commit
end
+
+ def pages_https_only_disabled?
+ !@project.pages_domains.all?(&:https?)
+ end
+
+ def pages_https_only_title
+ return unless pages_https_only_disabled?
+
+ "You must enable HTTPS for all your domains first"
+ end
+
+ def pages_https_only_label_class
+ if pages_https_only_disabled?
+ "list-label disabled"
+ else
+ "list-label"
+ end
+ end
end
diff --git a/app/models/application_setting.rb b/app/models/application_setting.rb
index 3cbbf8b5dfa..862933bf127 100644
--- a/app/models/application_setting.rb
+++ b/app/models/application_setting.rb
@@ -330,7 +330,8 @@ class ApplicationSetting < ActiveRecord::Base
usage_ping_enabled: Settings.gitlab['usage_ping_enabled'],
gitaly_timeout_fast: 10,
gitaly_timeout_medium: 30,
- gitaly_timeout_default: 55
+ gitaly_timeout_default: 55,
+ allow_local_requests_from_hooks_and_services: false
}
end
diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb
index f2edcdd61fd..44f9bdf111e 100644
--- a/app/models/ci/pipeline.rb
+++ b/app/models/ci/pipeline.rb
@@ -14,7 +14,7 @@ module Ci
has_many :stages
has_many :statuses, class_name: 'CommitStatus', foreign_key: :commit_id, inverse_of: :pipeline
- has_many :builds, foreign_key: :commit_id
+ has_many :builds, foreign_key: :commit_id, inverse_of: :pipeline
has_many :trigger_requests, dependent: :destroy, foreign_key: :commit_id # rubocop:disable Cop/ActiveRecordDependent
has_many :variables, class_name: 'Ci::PipelineVariable'
diff --git a/app/models/concerns/avatarable.rb b/app/models/concerns/avatarable.rb
index d35e37935fb..318df11727e 100644
--- a/app/models/concerns/avatarable.rb
+++ b/app/models/concerns/avatarable.rb
@@ -21,7 +21,7 @@ module Avatarable
def avatar_type
unless self.avatar.image?
- self.errors.add :avatar, "only images allowed"
+ errors.add :avatar, "file format is not supported. Please try one of the following supported formats: #{AvatarUploader::IMAGE_EXT.join(', ')}"
end
end
diff --git a/app/models/group.rb b/app/models/group.rb
index 8d183006c65..d99af79b5fe 100644
--- a/app/models/group.rb
+++ b/app/models/group.rb
@@ -189,12 +189,6 @@ class Group < Namespace
owners.include?(user) && owners.size == 1
end
- def avatar_type
- unless self.avatar.image?
- self.errors.add :avatar, "only images allowed"
- end
- end
-
def post_create_hook
Gitlab::AppLogger.info("Group \"#{name}\" was created")
@@ -230,13 +224,13 @@ class Group < Namespace
end
GroupMember
- .active_without_invites
+ .active_without_invites_and_requests
.where(source_id: source_ids)
end
def members_with_descendants
GroupMember
- .active_without_invites
+ .active_without_invites_and_requests
.where(source_id: self_and_descendants.reorder(nil).select(:id))
end
diff --git a/app/models/member.rb b/app/models/member.rb
index ec8156bbb01..e1a32148538 100644
--- a/app/models/member.rb
+++ b/app/models/member.rb
@@ -52,7 +52,7 @@ class Member < ActiveRecord::Base
end
# Like active, but without invites. For when a User is required.
- scope :active_without_invites, -> do
+ scope :active_without_invites_and_requests, -> do
left_join_users
.where(users: { state: 'active' })
.non_request
diff --git a/app/models/pages_domain.rb b/app/models/pages_domain.rb
index 588bd50ed77..2e478a24778 100644
--- a/app/models/pages_domain.rb
+++ b/app/models/pages_domain.rb
@@ -6,8 +6,10 @@ class PagesDomain < ActiveRecord::Base
validates :domain, hostname: { allow_numeric_hostname: true }
validates :domain, uniqueness: { case_sensitive: false }
- validates :certificate, certificate: true, allow_nil: true, allow_blank: true
- validates :key, certificate_key: true, allow_nil: true, allow_blank: true
+ validates :certificate, presence: { message: 'must be present if HTTPS-only is enabled' }, if: ->(domain) { domain.project&.pages_https_only? }
+ validates :certificate, certificate: true, if: ->(domain) { domain.certificate.present? }
+ validates :key, presence: { message: 'must be present if HTTPS-only is enabled' }, if: ->(domain) { domain.project&.pages_https_only? }
+ validates :key, certificate_key: true, if: ->(domain) { domain.key.present? }
validates :verification_code, presence: true, allow_blank: false
validate :validate_pages_domain
@@ -46,6 +48,10 @@ class PagesDomain < ActiveRecord::Base
!Gitlab::CurrentSettings.pages_domain_verification_enabled? || enabled_until.present?
end
+ def https?
+ certificate.present?
+ end
+
def to_param
domain
end
diff --git a/app/models/project.rb b/app/models/project.rb
index e5ede967668..6a420663644 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -38,6 +38,9 @@ class Project < ActiveRecord::Base
attachments: 2
}.freeze
+ # Valids ports to import from
+ VALID_IMPORT_PORTS = [22, 80, 443].freeze
+
cache_markdown_field :description, pipeline: :description
delegate :feature_available?, :builds_enabled?, :wiki_enabled?,
@@ -264,6 +267,7 @@ class Project < ActiveRecord::Base
validate :visibility_level_allowed_by_group
validate :visibility_level_allowed_as_fork
validate :check_wiki_path_conflict
+ validate :validate_pages_https_only, if: -> { changes.has_key?(:pages_https_only) }
validates :repository_storage,
presence: true,
inclusion: { in: ->(_object) { Gitlab.config.repositories.storages.keys } }
@@ -500,7 +504,7 @@ class Project < ActiveRecord::Base
end
def repository_storage_path
- Gitlab.config.repositories.storages[repository_storage].try(:[], 'path')
+ Gitlab.config.repositories.storages[repository_storage]&.legacy_disk_path
end
def team
@@ -734,6 +738,26 @@ class Project < ActiveRecord::Base
end
end
+ def pages_https_only
+ return false unless Gitlab.config.pages.external_https
+
+ super
+ end
+
+ def pages_https_only?
+ return false unless Gitlab.config.pages.external_https
+
+ super
+ end
+
+ def validate_pages_https_only
+ return unless pages_https_only?
+
+ unless pages_domains.all?(&:https?)
+ errors.add(:pages_https_only, "cannot be enabled unless all domains have TLS certificates")
+ end
+ end
+
def to_param
if persisted? && errors.include?(:path)
path_was
diff --git a/app/models/project_services/assembla_service.rb b/app/models/project_services/assembla_service.rb
index ae6af732ed4..4234b8044e5 100644
--- a/app/models/project_services/assembla_service.rb
+++ b/app/models/project_services/assembla_service.rb
@@ -1,6 +1,4 @@
class AssemblaService < Service
- include HTTParty
-
prop_accessor :token, :subdomain
validates :token, presence: true, if: :activated?
@@ -31,6 +29,6 @@ class AssemblaService < Service
return unless supported_events.include?(data[:object_kind])
url = "https://atlas.assembla.com/spaces/#{subdomain}/github_tool?secret_key=#{token}"
- AssemblaService.post(url, body: { payload: data }.to_json, headers: { 'Content-Type' => 'application/json' })
+ Gitlab::HTTP.post(url, body: { payload: data }.to_json, headers: { 'Content-Type' => 'application/json' })
end
end
diff --git a/app/models/project_services/bamboo_service.rb b/app/models/project_services/bamboo_service.rb
index 42939ea0ec8..54e4b3278db 100644
--- a/app/models/project_services/bamboo_service.rb
+++ b/app/models/project_services/bamboo_service.rb
@@ -117,14 +117,14 @@ class BambooService < CiService
url = build_url(path)
if username.blank? && password.blank?
- HTTParty.get(url, verify: false)
+ Gitlab::HTTP.get(url, verify: false)
else
url << '&os_authType=basic'
- HTTParty.get(url, verify: false,
- basic_auth: {
- username: username,
- password: password
- })
+ Gitlab::HTTP.get(url, verify: false,
+ basic_auth: {
+ username: username,
+ password: password
+ })
end
end
end
diff --git a/app/models/project_services/buildkite_service.rb b/app/models/project_services/buildkite_service.rb
index fc30f6e3365..d2aaff8817a 100644
--- a/app/models/project_services/buildkite_service.rb
+++ b/app/models/project_services/buildkite_service.rb
@@ -71,7 +71,7 @@ class BuildkiteService < CiService
end
def calculate_reactive_cache(sha, ref)
- response = HTTParty.get(commit_status_path(sha), verify: false)
+ response = Gitlab::HTTP.get(commit_status_path(sha), verify: false)
status =
if response.code == 200 && response['status']
diff --git a/app/models/project_services/campfire_service.rb b/app/models/project_services/campfire_service.rb
index 8d7a4fceb08..cb4af73807b 100644
--- a/app/models/project_services/campfire_service.rb
+++ b/app/models/project_services/campfire_service.rb
@@ -1,6 +1,4 @@
class CampfireService < Service
- include HTTParty
-
prop_accessor :token, :subdomain, :room
validates :token, presence: true, if: :activated?
@@ -31,7 +29,6 @@ class CampfireService < Service
def execute(data)
return unless supported_events.include?(data[:object_kind])
- self.class.base_uri base_uri
message = build_message(data)
speak(self.room, message, auth)
end
@@ -69,14 +66,14 @@ class CampfireService < Service
}
}
}
- res = self.class.post(path, auth.merge(body))
+ res = Gitlab::HTTP.post(path, base_uri: base_uri, **auth.merge(body))
res.code == 201 ? res : nil
end
# Returns a list of rooms, or [].
# https://github.com/basecamp/campfire-api/blob/master/sections/rooms.md#get-rooms
def rooms(auth)
- res = self.class.get("/rooms.json", auth)
+ res = Gitlab::HTTP.get("/rooms.json", base_uri: base_uri, **auth)
res.code == 200 ? res["rooms"] : []
end
diff --git a/app/models/project_services/drone_ci_service.rb b/app/models/project_services/drone_ci_service.rb
index c93f1632652..71b10fc6bc1 100644
--- a/app/models/project_services/drone_ci_service.rb
+++ b/app/models/project_services/drone_ci_service.rb
@@ -49,7 +49,7 @@ class DroneCiService < CiService
end
def calculate_reactive_cache(sha, ref)
- response = HTTParty.get(commit_status_path(sha, ref), verify: enable_ssl_verification)
+ response = Gitlab::HTTP.get(commit_status_path(sha, ref), verify: enable_ssl_verification)
status =
if response.code == 200 && response['status']
diff --git a/app/models/project_services/external_wiki_service.rb b/app/models/project_services/external_wiki_service.rb
index 720ad61162e..1553f169827 100644
--- a/app/models/project_services/external_wiki_service.rb
+++ b/app/models/project_services/external_wiki_service.rb
@@ -1,6 +1,4 @@
class ExternalWikiService < Service
- include HTTParty
-
prop_accessor :external_wiki_url
validates :external_wiki_url, presence: true, url: true, if: :activated?
@@ -24,7 +22,7 @@ class ExternalWikiService < Service
end
def execute(_data)
- @response = HTTParty.get(properties['external_wiki_url'], verify: true) rescue nil
+ @response = Gitlab::HTTP.get(properties['external_wiki_url'], verify: true) rescue nil
if @response != 200
nil
end
diff --git a/app/models/project_services/issue_tracker_service.rb b/app/models/project_services/issue_tracker_service.rb
index 5fb15c383ca..df6dcd90985 100644
--- a/app/models/project_services/issue_tracker_service.rb
+++ b/app/models/project_services/issue_tracker_service.rb
@@ -77,13 +77,13 @@ class IssueTrackerService < Service
result = false
begin
- response = HTTParty.head(self.project_url, verify: true)
+ response = Gitlab::HTTP.head(self.project_url, verify: true)
if response
message = "#{self.type} received response #{response.code} when attempting to connect to #{self.project_url}"
result = true
end
- rescue HTTParty::Error, Timeout::Error, SocketError, Errno::ECONNRESET, Errno::ECONNREFUSED, OpenSSL::SSL::SSLError => error
+ rescue Gitlab::HTTP::Error, Timeout::Error, SocketError, Errno::ECONNRESET, Errno::ECONNREFUSED, OpenSSL::SSL::SSLError => error
message = "#{self.type} had an error when trying to connect to #{self.project_url}: #{error.message}"
end
Rails.logger.info(message)
diff --git a/app/models/project_services/mock_ci_service.rb b/app/models/project_services/mock_ci_service.rb
index 72ddf9a4be3..2221459c90b 100644
--- a/app/models/project_services/mock_ci_service.rb
+++ b/app/models/project_services/mock_ci_service.rb
@@ -52,7 +52,7 @@ class MockCiService < CiService
#
#
def commit_status(sha, ref)
- response = HTTParty.get(commit_status_path(sha), verify: false)
+ response = Gitlab::HTTP.get(commit_status_path(sha), verify: false)
read_commit_status(response)
rescue Errno::ECONNREFUSED
:error
diff --git a/app/models/project_services/packagist_service.rb b/app/models/project_services/packagist_service.rb
index f68a0c1a3c3..ba62a5b7ac0 100644
--- a/app/models/project_services/packagist_service.rb
+++ b/app/models/project_services/packagist_service.rb
@@ -1,6 +1,4 @@
class PackagistService < Service
- include HTTParty
-
prop_accessor :username, :token, :server
validates :username, presence: true, if: :activated?
diff --git a/app/models/project_services/pivotaltracker_service.rb b/app/models/project_services/pivotaltracker_service.rb
index f9dfa2e91c3..3476e7d2283 100644
--- a/app/models/project_services/pivotaltracker_service.rb
+++ b/app/models/project_services/pivotaltracker_service.rb
@@ -1,6 +1,4 @@
class PivotaltrackerService < Service
- include HTTParty
-
API_ENDPOINT = 'https://www.pivotaltracker.com/services/v5/source_commits'.freeze
prop_accessor :token, :restrict_to_branch
@@ -52,7 +50,7 @@ class PivotaltrackerService < Service
'message' => commit[:message]
}
}
- PivotaltrackerService.post(
+ Gitlab::HTTP.post(
API_ENDPOINT,
body: message.to_json,
headers: {
diff --git a/app/models/project_services/pushover_service.rb b/app/models/project_services/pushover_service.rb
index e3a1ca2d45f..8777a44b72f 100644
--- a/app/models/project_services/pushover_service.rb
+++ b/app/models/project_services/pushover_service.rb
@@ -1,6 +1,5 @@
class PushoverService < Service
- include HTTParty
- base_uri 'https://api.pushover.net/1'
+ BASE_URI = 'https://api.pushover.net/1'.freeze
prop_accessor :api_key, :user_key, :device, :priority, :sound
validates :api_key, :user_key, :priority, presence: true, if: :activated?
@@ -99,6 +98,6 @@ class PushoverService < Service
pushover_data[:sound] = sound
end
- PushoverService.post('/messages.json', body: pushover_data)
+ Gitlab::HTTP.post('/messages.json', base_uri: BASE_URI, body: pushover_data)
end
end
diff --git a/app/models/project_services/teamcity_service.rb b/app/models/project_services/teamcity_service.rb
index cbe137452bd..145313b8e71 100644
--- a/app/models/project_services/teamcity_service.rb
+++ b/app/models/project_services/teamcity_service.rb
@@ -83,7 +83,7 @@ class TeamcityService < CiService
branch = Gitlab::Git.ref_name(data[:ref])
- HTTParty.post(
+ Gitlab::HTTP.post(
build_url('httpAuth/app/rest/buildQueue'),
body: "<build branchName=\"#{branch}\">"\
"<buildType id=\"#{build_type}\"/>"\
@@ -134,10 +134,10 @@ class TeamcityService < CiService
end
def get_path(path)
- HTTParty.get(build_url(path), verify: false,
- basic_auth: {
- username: username,
- password: password
- })
+ Gitlab::HTTP.get(build_url(path), verify: false,
+ basic_auth: {
+ username: username,
+ password: password
+ })
end
end
diff --git a/app/services/ci/create_pipeline_service.rb b/app/services/ci/create_pipeline_service.rb
index 3b3d9239086..ad27f320853 100644
--- a/app/services/ci/create_pipeline_service.rb
+++ b/app/services/ci/create_pipeline_service.rb
@@ -65,7 +65,7 @@ module Ci
project.pipelines
.where(ref: pipeline.ref)
.where.not(id: pipeline.id)
- .where.not(sha: project.repository.sha_from_ref(pipeline.ref))
+ .where.not(sha: project.commit(pipeline.ref).try(:id))
.created_or_pending
end
diff --git a/app/services/notification_service.rb b/app/services/notification_service.rb
index ab94db2c1e5..d7d2cde1004 100644
--- a/app/services/notification_service.rb
+++ b/app/services/notification_service.rb
@@ -208,9 +208,9 @@ class NotificationService
def new_access_request(member)
return true unless member.notifiable?(:subscription)
- recipients = member.source.members.active_without_invites.owners_and_masters
+ recipients = member.source.members.active_without_invites_and_requests.owners_and_masters
if fallback_to_group_owners_masters?(recipients, member)
- recipients = member.source.group.members.active_without_invites.owners_and_masters
+ recipients = member.source.group.members.active_without_invites_and_requests.owners_and_masters
end
recipients.each { |recipient| deliver_access_request_email(recipient, member) }
diff --git a/app/services/projects/import_service.rb b/app/services/projects/import_service.rb
index f2d676af5c3..a34024f4f80 100644
--- a/app/services/projects/import_service.rb
+++ b/app/services/projects/import_service.rb
@@ -28,7 +28,7 @@ module Projects
def add_repository_to_project
if project.external_import? && !unknown_url?
- raise Error, 'Blocked import URL.' if Gitlab::UrlBlocker.blocked_url?(project.import_url)
+ raise Error, 'Blocked import URL.' if Gitlab::UrlBlocker.blocked_url?(project.import_url, valid_ports: Project::VALID_IMPORT_PORTS)
end
# We should skip the repository for a GitHub import or GitLab project import,
diff --git a/app/services/projects/update_pages_configuration_service.rb b/app/services/projects/update_pages_configuration_service.rb
index 52ff64cc938..25017c5cbe3 100644
--- a/app/services/projects/update_pages_configuration_service.rb
+++ b/app/services/projects/update_pages_configuration_service.rb
@@ -18,7 +18,8 @@ module Projects
def pages_config
{
- domains: pages_domains_config
+ domains: pages_domains_config,
+ https_only: project.pages_https_only?
}
end
@@ -27,7 +28,8 @@ module Projects
{
domain: domain.domain,
certificate: domain.certificate,
- key: domain.key
+ key: domain.key,
+ https_only: project.pages_https_only? && domain.https?
}
end
end
diff --git a/app/services/projects/update_service.rb b/app/services/projects/update_service.rb
index 5f2615a2c01..679f4a9cb62 100644
--- a/app/services/projects/update_service.rb
+++ b/app/services/projects/update_service.rb
@@ -24,6 +24,8 @@ module Projects
system_hook_service.execute_hooks_for(project, :update)
end
+ update_pages_config if changing_pages_https_only?
+
success
else
model_errors = project.errors.full_messages.to_sentence
@@ -67,5 +69,13 @@ module Projects
log_error("Could not create wiki for #{project.full_name}")
Gitlab::Metrics.counter(:wiki_can_not_be_created_total, 'Counts the times we failed to create a wiki')
end
+
+ def update_pages_config
+ Projects::UpdatePagesConfigurationService.new(project).execute
+ end
+
+ def changing_pages_https_only?
+ project.previous_changes.include?(:pages_https_only)
+ end
end
end
diff --git a/app/services/submit_usage_ping_service.rb b/app/services/submit_usage_ping_service.rb
index 2623f253d98..ac029fad7ea 100644
--- a/app/services/submit_usage_ping_service.rb
+++ b/app/services/submit_usage_ping_service.rb
@@ -14,16 +14,17 @@ class SubmitUsagePingService
def execute
return false unless Gitlab::CurrentSettings.usage_ping_enabled?
- response = HTTParty.post(
+ response = Gitlab::HTTP.post(
URL,
body: Gitlab::UsageData.to_json(force_refresh: true),
+ allow_local_requests: true,
headers: { 'Content-type' => 'application/json' }
)
store_metrics(response)
true
- rescue HTTParty::Error => e
+ rescue Gitlab::HTTP::Error => e
Rails.logger.info "Unable to contact GitLab, Inc.: #{e}"
false
diff --git a/app/services/web_hook_service.rb b/app/services/web_hook_service.rb
index 36e589d5aa8..809ce1303d8 100644
--- a/app/services/web_hook_service.rb
+++ b/app/services/web_hook_service.rb
@@ -3,23 +3,20 @@ class WebHookService
attr_reader :body, :headers, :code
def initialize
- @headers = HTTParty::Response::Headers.new({})
+ @headers = Gitlab::HTTP::Response::Headers.new({})
@body = ''
@code = 'internal error'
end
end
- include HTTParty
-
- # HTTParty timeout
- default_timeout Gitlab.config.gitlab.webhook_timeout
-
- attr_accessor :hook, :data, :hook_name
+ attr_accessor :hook, :data, :hook_name, :request_options
def initialize(hook, data, hook_name)
@hook = hook
@data = data
@hook_name = hook_name.to_s
+ @request_options = { timeout: Gitlab.config.gitlab.webhook_timeout }
+ @request_options.merge!(allow_local_requests: true) if @hook.is_a?(SystemHook)
end
def execute
@@ -73,11 +70,12 @@ class WebHookService
end
def make_request(url, basic_auth = false)
- self.class.post(url,
+ Gitlab::HTTP.post(url,
body: data.to_json,
headers: build_headers(hook_name),
verify: hook.enable_ssl_verification,
- basic_auth: basic_auth)
+ basic_auth: basic_auth,
+ **request_options)
end
def make_request_with_auth
diff --git a/app/validators/certificate_validator.rb b/app/validators/certificate_validator.rb
index 5239e70a326..b0c9a1b92a4 100644
--- a/app/validators/certificate_validator.rb
+++ b/app/validators/certificate_validator.rb
@@ -16,8 +16,6 @@ class CertificateValidator < ActiveModel::EachValidator
private
def valid_certificate_pem?(value)
- return false unless value
-
OpenSSL::X509::Certificate.new(value).present?
rescue OpenSSL::X509::CertificateError
false
diff --git a/app/validators/importable_url_validator.rb b/app/validators/importable_url_validator.rb
index 37a314adee6..3ec1594e202 100644
--- a/app/validators/importable_url_validator.rb
+++ b/app/validators/importable_url_validator.rb
@@ -4,7 +4,7 @@
# protect against Server-side Request Forgery (SSRF).
class ImportableUrlValidator < ActiveModel::EachValidator
def validate_each(record, attribute, value)
- if Gitlab::UrlBlocker.blocked_url?(value)
+ if Gitlab::UrlBlocker.blocked_url?(value, valid_ports: Project::VALID_IMPORT_PORTS)
record.errors.add(attribute, "imports are not allowed from that URL")
end
end
diff --git a/app/views/admin/application_settings/_form.html.haml b/app/views/admin/application_settings/_form.html.haml
index 81d7db04a3c..54b39df8cf3 100644
--- a/app/views/admin/application_settings/_form.html.haml
+++ b/app/views/admin/application_settings/_form.html.haml
@@ -860,5 +860,14 @@
.col-sm-10
= f.number_field :throttle_authenticated_web_period_in_seconds, class: 'form-control'
+ %fieldset
+ %legend Outbound requests
+ .form-group
+ .col-sm-offset-2.col-sm-10
+ .checkbox
+ = f.label :allow_local_requests_from_hooks_and_services do
+ = f.check_box :allow_local_requests_from_hooks_and_services
+ Allow requests to the local network from hooks and services
+
.form-actions
= f.submit 'Save', class: 'btn btn-save'
diff --git a/app/views/import/gitlab_projects/new.html.haml b/app/views/import/gitlab_projects/new.html.haml
index df5841d1911..dec85368d10 100644
--- a/app/views/import/gitlab_projects/new.html.haml
+++ b/app/views/import/gitlab_projects/new.html.haml
@@ -13,13 +13,13 @@
.form-group
.input-group
- if current_user.can_select_namespace?
- .input-group-addon
+ .input-group-addon.has-tooltip{ title: root_url }
= root_url
= select_tag :namespace_id, namespaces_options(namespace_id_from(params) || :current_user, display_path: true, extra_group: namespace_id_from(params)), class: 'select2 js-select-namespace', tabindex: 1
- else
- .input-group-addon.static-namespace
- #{root_url}#{current_user.username}/
+ .input-group-addon.static-namespace.has-tooltip{ title: user_url(current_user.username) + '/' }
+ #{user_url(current_user.username)}/
= hidden_field_tag :namespace_id, value: current_user.namespace_id
.form-group.col-xs-12.col-sm-6.project-path
= label_tag :path, 'Project name', class: 'label-light'
diff --git a/app/views/layouts/_mailer.html.haml b/app/views/layouts/_mailer.html.haml
index b50537438a9..ddc1cdb24b5 100644
--- a/app/views/layouts/_mailer.html.haml
+++ b/app/views/layouts/_mailer.html.haml
@@ -67,12 +67,8 @@
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;padding:25px 0;font-size:13px;line-height:1.6;color:#5c5c5c;" }
%img{ alt: "GitLab", height: "33", src: image_url('mailers/gitlab_footer_logo.gif'), style: "display:block;margin:0 auto 1em;", width: "90" }/
%div
- %a{ href: profile_notifications_url, style: "color:#3777b0;text-decoration:none;" } Manage all notifications
- &middot;
- %a{ href: help_url, style: "color:#3777b0;text-decoration:none;" } Help
- %div
- You're receiving this email because of your account on
- = succeed "." do
- %a{ href: root_url, style: "color:#3777b0;text-decoration:none;" }= Gitlab.config.gitlab.host
+ - manage_notifications_link = link_to(_("Manage all notifications"), profile_notifications_url, style: "color:#3777b0;text-decoration:none;")
+ - help_link = link_to(_("Help"), help_url, style: "color:#3777b0;text-decoration:none;")
+ = _("You're receiving this email because of your account on %{host}. %{manage_notifications_link} &middot; %{help_link}").html_safe % { host: Gitlab.config.gitlab.host, manage_notifications_link: manage_notifications_link, help_link: help_link }
= yield :additional_footer
diff --git a/app/views/layouts/_page.html.haml b/app/views/layouts/_page.html.haml
index f0963cf9da8..f67a8878c80 100644
--- a/app/views/layouts/_page.html.haml
+++ b/app/views/layouts/_page.html.haml
@@ -6,6 +6,7 @@
.mobile-overlay
.alert-wrapper
= render "layouts/broadcast"
+ = render 'layouts/header/read_only_banner'
= yield :flash_message
- unless @hide_breadcrumbs
= render "layouts/nav/breadcrumbs"
diff --git a/app/views/layouts/header/_read_only_banner.html.haml b/app/views/layouts/header/_read_only_banner.html.haml
new file mode 100644
index 00000000000..f3d563c362f
--- /dev/null
+++ b/app/views/layouts/header/_read_only_banner.html.haml
@@ -0,0 +1,7 @@
+- message = read_only_message
+- if message
+ .flash-container.flash-container-page
+ .flash-notice
+ %div{ class: (container_class) }
+ %span
+ = message
diff --git a/app/views/peek/_bar.html.haml b/app/views/peek/_bar.html.haml
index 14dafa197b5..b4d86e1601c 100644
--- a/app/views/peek/_bar.html.haml
+++ b/app/views/peek/_bar.html.haml
@@ -6,7 +6,7 @@
profile_url: url_for(params.merge(lineprofiler: 'true')) },
class: Peek.env }
-#peek-view-performance-bar
+#peek-view-performance-bar.hidden
= render_server_response_time
%span#serverstats
%ul.performance-bar
diff --git a/app/views/projects/_last_push.html.haml b/app/views/projects/_last_push.html.haml
index 6f5eb828902..6a1035d2dc7 100644
--- a/app/views/projects/_last_push.html.haml
+++ b/app/views/projects/_last_push.html.haml
@@ -13,6 +13,6 @@
#{time_ago_with_tooltip(event.created_at)}
- .pull-right
+ .flex-right
= link_to new_mr_path_from_push_event(event), title: _("New merge request"), class: "btn btn-info btn-sm qa-create-merge-request" do
#{ _('Create merge request') }
diff --git a/app/views/projects/_new_project_fields.html.haml b/app/views/projects/_new_project_fields.html.haml
index f4b5ef1555e..241bc3dbca0 100644
--- a/app/views/projects/_new_project_fields.html.haml
+++ b/app/views/projects/_new_project_fields.html.haml
@@ -9,12 +9,12 @@
Project path
.input-group
- if current_user.can_select_namespace?
- .input-group-addon
+ .input-group-addon.has-tooltip{ title: root_url }
= root_url
= f.select :namespace_id, namespaces_options(namespace_id_from(params) || :current_user, display_path: true, extra_group: namespace_id_from(params)), {}, { class: 'select2 js-select-namespace qa-project-namespace-select', tabindex: 1}
- else
- .input-group-addon.static-namespace
+ .input-group-addon.static-namespace.has-tooltip{ title: user_url(current_user.username) + '/' }
#{user_url(current_user.username)}/
= f.hidden_field :namespace_id, value: current_user.namespace_id
.form-group.project-path.col-sm-6
diff --git a/app/views/projects/branches/_branch.html.haml b/app/views/projects/branches/_branch.html.haml
index 1da0e865a41..883dfb3e6c8 100644
--- a/app/views/projects/branches/_branch.html.haml
+++ b/app/views/projects/branches/_branch.html.haml
@@ -5,81 +5,82 @@
- number_commits_behind = diverging_commit_counts[:behind]
- number_commits_ahead = diverging_commit_counts[:ahead]
- merge_project = can?(current_user, :create_merge_request, @project) ? @project : (current_user && current_user.fork_of(@project))
-%li{ class: "js-branch-#{branch.name}" }
- %div
- = link_to project_tree_path(@project, branch.name), class: 'item-title str-truncated ref-name' do
- = sprite_icon('fork', size: 12)
- = branch.name
- &nbsp;
- - if branch.name == @repository.root_ref
- %span.label.label-primary default
- - elsif merged
- %span.label.label-info.has-tooltip{ title: s_('Branches|Merged into %{default_branch}') % { default_branch: @repository.root_ref } }
- = s_('Branches|merged')
+%li{ class: "branch-item js-branch-#{branch.name}" }
+ .branch-info
+ .branch-title
+ = link_to project_tree_path(@project, branch.name), class: 'item-title str-truncated-100 ref-name' do
+ = sprite_icon('fork', size: 12)
+ = branch.name
+ &nbsp;
+ - if branch.name == @repository.root_ref
+ %span.label.label-primary default
+ - elsif merged
+ %span.label.label-info.has-tooltip{ title: s_('Branches|Merged into %{default_branch}') % { default_branch: @repository.root_ref } }
+ = s_('Branches|merged')
- - if protected_branch?(@project, branch)
- %span.label.label-success
- = s_('Branches|protected')
- .controls.hidden-xs<
- - if merge_project && create_mr_button?(@repository.root_ref, branch.name)
- = link_to create_mr_path(@repository.root_ref, branch.name), class: 'btn btn-default' do
- = _('Merge request')
+ - if protected_branch?(@project, branch)
+ %span.label.label-success
+ = s_('Branches|protected')
- - if branch.name != @repository.root_ref
- = link_to project_compare_index_path(@project, from: @repository.root_ref, to: branch.name),
- class: "btn btn-default #{'prepend-left-10' unless merge_project}",
- method: :post,
- title: s_('Branches|Compare') do
- = s_('Branches|Compare')
+ .block-truncated
+ - if commit
+ = render 'projects/branches/commit', commit: commit, project: @project
+ - else
+ = s_('Branches|Cant find HEAD commit for this branch')
- = render 'projects/buttons/download', project: @project, ref: branch.name, pipeline: @refs_pipelines[branch.name]
+ - if branch.name != @repository.root_ref
+ .divergence-graph{ 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)
- - if can?(current_user, :push_code, @project)
- - if branch.name == @project.repository.root_ref
- %button{ class: "btn btn-remove remove-row js-ajax-loading-spinner has-tooltip disabled",
- disabled: true,
- title: s_('Branches|The default branch cannot be deleted') }
- = icon("trash-o")
- - elsif protected_branch?(@project, branch)
- - if can?(current_user, :delete_protected_branch, @project)
- %button{ class: "btn btn-remove remove-row js-ajax-loading-spinner has-tooltip",
- title: s_('Branches|Delete protected branch'),
- data: { toggle: "modal",
- target: "#modal-delete-branch",
- delete_path: project_branch_path(@project, branch.name),
- branch_name: branch.name,
- is_merged: ("true" if merged) } }
- = icon("trash-o")
- - else
- %button{ class: "btn btn-remove remove-row js-ajax-loading-spinner has-tooltip disabled",
- disabled: true,
- title: s_('Branches|Only a project master or owner can delete a protected branch') }
- = icon("trash-o")
- - else
- = link_to project_branch_path(@project, branch.name),
- class: "btn btn-remove remove-row js-ajax-loading-spinner has-tooltip",
- title: s_('Branches|Delete branch'),
- method: :delete,
- data: { confirm: s_("Branches|Deleting the '%{branch_name}' branch cannot be undone. Are you sure?") % { branch_name: branch.name } },
- remote: true,
- 'aria-label' => s_('Branches|Delete branch') do
- = icon("trash-o")
+ .controls.hidden-xs<
+ - if merge_project && create_mr_button?(@repository.root_ref, branch.name)
+ = link_to create_mr_path(@repository.root_ref, branch.name), class: 'btn btn-default' do
+ = _('Merge request')
- if branch.name != @repository.root_ref
- .divergence-graph{ 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)
+ = link_to project_compare_index_path(@project, from: @repository.root_ref, to: branch.name),
+ class: "btn btn-default #{'prepend-left-10' unless merge_project}",
+ method: :post,
+ title: s_('Branches|Compare') do
+ = s_('Branches|Compare')
+ = render 'projects/buttons/download', project: @project, ref: branch.name, pipeline: @refs_pipelines[branch.name]
- - if commit
- = render 'projects/branches/commit', commit: commit, project: @project
- - else
- %p
- = s_('Branches|Cant find HEAD commit for this branch')
+ - if can?(current_user, :push_code, @project)
+ - if branch.name == @project.repository.root_ref
+ %button{ class: "btn btn-remove remove-row js-ajax-loading-spinner has-tooltip disabled",
+ disabled: true,
+ title: s_('Branches|The default branch cannot be deleted') }
+ = icon("trash-o")
+ - elsif protected_branch?(@project, branch)
+ - if can?(current_user, :delete_protected_branch, @project)
+ %button{ class: "btn btn-remove remove-row js-ajax-loading-spinner has-tooltip",
+ title: s_('Branches|Delete protected branch'),
+ data: { toggle: "modal",
+ target: "#modal-delete-branch",
+ delete_path: project_branch_path(@project, branch.name),
+ branch_name: branch.name,
+ is_merged: ("true" if merged) } }
+ = icon("trash-o")
+ - else
+ %button{ class: "btn btn-remove remove-row js-ajax-loading-spinner has-tooltip disabled",
+ disabled: true,
+ title: s_('Branches|Only a project master or owner can delete a protected branch') }
+ = icon("trash-o")
+ - else
+ = link_to project_branch_path(@project, branch.name),
+ class: "btn btn-remove remove-row js-ajax-loading-spinner has-tooltip",
+ title: s_('Branches|Delete branch'),
+ method: :delete,
+ data: { confirm: s_("Branches|Deleting the '%{branch_name}' branch cannot be undone. Are you sure?") % { branch_name: branch.name } },
+ remote: true,
+ 'aria-label' => s_('Branches|Delete branch') do
+ = icon("trash-o")
diff --git a/app/views/projects/issues/_issue.html.haml b/app/views/projects/issues/_issue.html.haml
index 64c648f201b..0c58dd60e2c 100644
--- a/app/views/projects/issues/_issue.html.haml
+++ b/app/views/projects/issues/_issue.html.haml
@@ -7,7 +7,9 @@
.issue-main-info
.issue-title.title
%span.issue-title-text
- = confidential_icon(issue)
+ - if issue.confidential?
+ %span.has-tooltip{ title: _('Confidential') }
+ = confidential_icon(issue)
= link_to issue.title, issue_path(issue)
- if issue.tasks?
%span.task-status.hidden-xs
@@ -24,11 +26,11 @@
- if issue.milestone
%span.issuable-milestone.hidden-xs
&nbsp;
- = link_to project_issues_path(issue.project, milestone_title: issue.milestone.title), data: { html: 1, toggle: 'tooltip', title: milestone_tooltip_title(issue.milestone) } do
+ = link_to project_issues_path(issue.project, milestone_title: issue.milestone.title), data: { html: 1, toggle: 'tooltip', title: issuable_milestone_tooltip_title(issue) } do
= icon('clock-o')
= issue.milestone.title
- if issue.due_date
- %span.issuable-due-date.hidden-xs{ class: "#{'cred' if issue.overdue?}" }
+ %span.issuable-due-date.hidden-xs.has-tooltip{ class: "#{'cred' if issue.overdue?}", title: _('Due date') }
&nbsp;
= icon('calendar')
= issue.due_date.to_s(:medium)
diff --git a/app/views/projects/merge_requests/_merge_request.html.haml b/app/views/projects/merge_requests/_merge_request.html.haml
index f45a000833b..a94267deeb2 100644
--- a/app/views/projects/merge_requests/_merge_request.html.haml
+++ b/app/views/projects/merge_requests/_merge_request.html.haml
@@ -23,11 +23,11 @@
- if merge_request.milestone
%span.issuable-milestone.hidden-xs
&nbsp;
- = link_to project_merge_requests_path(merge_request.project, milestone_title: merge_request.milestone.title), data: { html: 1, toggle: 'tooltip', title: milestone_tooltip_title(merge_request.milestone) } do
+ = link_to project_merge_requests_path(merge_request.project, milestone_title: merge_request.milestone.title), data: { html: 1, toggle: 'tooltip', title: issuable_milestone_tooltip_title(merge_request) } do
= icon('clock-o')
= merge_request.milestone.title
- if merge_request.target_project.default_branch != merge_request.target_branch
- %span.project-ref-path
+ %span.project-ref-path.has-tooltip{ title: _('Target branch') }
&nbsp;
= link_to project_ref_path(merge_request.project, merge_request.target_branch), class: 'ref-name' do
= sprite_icon('fork', size: 12, css_class: 'fork-sprite')
@@ -51,11 +51,11 @@
= render_pipeline_status(merge_request.head_pipeline)
- if merge_request.open? && merge_request.broken?
%li.issuable-pipeline-broken.hidden-xs
- = link_to merge_request_path(merge_request), class: "has-tooltip", title: "Cannot be merged automatically", data: { container: 'body' } do
+ = link_to merge_request_path(merge_request), class: "has-tooltip", title: _('Cannot be merged automatically') do
= icon('exclamation-triangle')
- if merge_request.assignee
%li
- = link_to_member(merge_request.source_project, merge_request.assignee, name: false, title: "Assigned to :name")
+ = link_to_member(merge_request.source_project, merge_request.assignee, name: false, title: _('Assigned to :name'))
= render 'shared/issuable_meta_data', issuable: merge_request
diff --git a/app/views/projects/pages/_https_only.html.haml b/app/views/projects/pages/_https_only.html.haml
new file mode 100644
index 00000000000..6a3ffce949f
--- /dev/null
+++ b/app/views/projects/pages/_https_only.html.haml
@@ -0,0 +1,10 @@
+= form_for @project, url: namespace_project_pages_path(@project.namespace.becomes(Namespace), @project), html: { class: 'inline', title: pages_https_only_title } do |f|
+ = f.check_box :pages_https_only, class: 'pull-left', disabled: pages_https_only_disabled?
+
+ .prepend-left-20
+ = f.label :pages_https_only, class: pages_https_only_label_class do
+ %strong Force domains with SSL certificates to use HTTPS
+
+ - unless pages_https_only_disabled?
+ .prepend-top-10
+ = f.submit 'Save', class: 'btn btn-success'
diff --git a/app/views/projects/pages/show.html.haml b/app/views/projects/pages/show.html.haml
index 04e647c0dc6..f17d9d24db6 100644
--- a/app/views/projects/pages/show.html.haml
+++ b/app/views/projects/pages/show.html.haml
@@ -13,6 +13,9 @@
Combined with the power of GitLab CI and the help of GitLab Runner
you can deploy static pages for your individual projects, your user or your group.
+- if Gitlab.config.pages.external_https
+ = render 'https_only'
+
%hr.clearfix
= render 'access'
diff --git a/app/views/projects/tree/_tree_header.html.haml b/app/views/projects/tree/_tree_header.html.haml
index 67613949b7d..5ef5e9c09a2 100644
--- a/app/views/projects/tree/_tree_header.html.haml
+++ b/app/views/projects/tree/_tree_header.html.haml
@@ -77,7 +77,7 @@
= render 'projects/find_file_link'
= succeed " " do
- = link_to ide_edit_path(@project, @id), class: 'btn btn-default' do
+ = link_to ide_edit_path(@project, @id, ""), class: 'btn btn-default' do
= _('Web IDE')
= render 'projects/buttons/download', project: @project, ref: @ref
diff --git a/app/views/shared/_issuable_meta_data.html.haml b/app/views/shared/_issuable_meta_data.html.haml
index 435acbc634c..430d9a9dd76 100644
--- a/app/views/shared/_issuable_meta_data.html.haml
+++ b/app/views/shared/_issuable_meta_data.html.haml
@@ -5,21 +5,21 @@
- issuable_mr = @issuable_meta_data[issuable.id].merge_requests_count
- if issuable_mr > 0
- %li.issuable-mr.hidden-xs
+ %li.issuable-mr.hidden-xs.has-tooltip{ title: _('Related merge requests') }
= image_tag('icon-merge-request-unmerged.svg', class: 'icon-merge-request-unmerged')
= issuable_mr
- if upvotes > 0
- %li.issuable-upvotes.hidden-xs
+ %li.issuable-upvotes.hidden-xs.has-tooltip{ title: _('Upvotes') }
= icon('thumbs-up')
= upvotes
- if downvotes > 0
- %li.issuable-downvotes.hidden-xs
+ %li.issuable-downvotes.hidden-xs.has-tooltip{ title: _('Downvotes') }
= icon('thumbs-down')
= downvotes
%li.issuable-comments.hidden-xs
- = link_to issuable_url, class: ('no-comments' if note_count.zero?) do
+ = link_to issuable_url, class: ['has-tooltip', ('no-comments' if note_count.zero?)], title: _('Comments') do
= icon('comments')
= note_count
diff --git a/changelogs/unreleased/17203-add-missing-pagination-commit-diff-endpoint.yml b/changelogs/unreleased/17203-add-missing-pagination-commit-diff-endpoint.yml
deleted file mode 100644
index efd936ca104..00000000000
--- a/changelogs/unreleased/17203-add-missing-pagination-commit-diff-endpoint.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
- title: Add missing pagination on the commit diff endpoint
- merge_request: 17203
- author: Maxime Roussin-Bélanger
- type: fixed
diff --git a/changelogs/unreleased/17359-move-oauth-modules-to-auth-dir-structure.yml b/changelogs/unreleased/17359-move-oauth-modules-to-auth-dir-structure.yml
deleted file mode 100644
index ca049f9edaa..00000000000
--- a/changelogs/unreleased/17359-move-oauth-modules-to-auth-dir-structure.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Moved o_auth/saml/ldap modules under gitlab/auth
-merge_request: 17359
-author: Horatiu Eugen Vlad
diff --git a/changelogs/unreleased/17500-mr-multiple-issues-oxford-comma.yml b/changelogs/unreleased/17500-mr-multiple-issues-oxford-comma.yml
deleted file mode 100644
index a94e6153a05..00000000000
--- a/changelogs/unreleased/17500-mr-multiple-issues-oxford-comma.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Update issue closing pattern to allow variations in punctuation
-merge_request: 17198
-author: Vicky Chijwani
-type: changed
diff --git a/changelogs/unreleased/24774-clear-the-Labels-dropdown-search-filter.yml b/changelogs/unreleased/24774-clear-the-Labels-dropdown-search-filter.yml
deleted file mode 100644
index b909bb2d021..00000000000
--- a/changelogs/unreleased/24774-clear-the-Labels-dropdown-search-filter.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Clear the Labels dropdown search filter after a selection is made
-merge_request: 17393
-author: Andrew Torres
-type: changed
diff --git a/changelogs/unreleased/26039-Update-to-github-linguist5-3-x.yml b/changelogs/unreleased/26039-Update-to-github-linguist5-3-x.yml
deleted file mode 100644
index 0f1cb2fef9d..00000000000
--- a/changelogs/unreleased/26039-Update-to-github-linguist5-3-x.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Update to github-linguist 5.3.x
-merge_request: 17241
-author: Ken Ding
-type: other
diff --git a/changelogs/unreleased/26466-natural-sort-mrs.yml b/changelogs/unreleased/26466-natural-sort-mrs.yml
deleted file mode 100644
index e3bf9834f24..00000000000
--- a/changelogs/unreleased/26466-natural-sort-mrs.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Group MRs on issue page by project and namespace.
-merge_request: 8494
-author: Jeff Stubler
diff --git a/changelogs/unreleased/29130-api-project-export.yml b/changelogs/unreleased/29130-api-project-export.yml
deleted file mode 100644
index 7dee349232a..00000000000
--- a/changelogs/unreleased/29130-api-project-export.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Add project export API
-merge_request: 15860
-author: Travis Miller
-type: added
diff --git a/changelogs/unreleased/29497-pages-custom-domain-dns-verification.yml b/changelogs/unreleased/29497-pages-custom-domain-dns-verification.yml
deleted file mode 100644
index f958f3f1272..00000000000
--- a/changelogs/unreleased/29497-pages-custom-domain-dns-verification.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Add verification for GitLab Pages custom domains
-merge_request:
-author:
-type: security
diff --git a/changelogs/unreleased/30665-add-email-button-to-new-issue-by-email.yml b/changelogs/unreleased/30665-add-email-button-to-new-issue-by-email.yml
deleted file mode 100644
index 175b3103d90..00000000000
--- a/changelogs/unreleased/30665-add-email-button-to-new-issue-by-email.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Add email button to new issue by email
-merge_request: 10942
-author: Islam Wazery
diff --git a/changelogs/unreleased/32564-fix-double-system-closing-notes.yml b/changelogs/unreleased/32564-fix-double-system-closing-notes.yml
deleted file mode 100644
index e6e1ef8c76d..00000000000
--- a/changelogs/unreleased/32564-fix-double-system-closing-notes.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix duplicate system notes when merging a merge request.
-merge_request: 17035
-author:
-type: fixed
diff --git a/changelogs/unreleased/32831-single-deploy-of-runner-in-k8s-cluster.yml b/changelogs/unreleased/32831-single-deploy-of-runner-in-k8s-cluster.yml
deleted file mode 100644
index 74675992105..00000000000
--- a/changelogs/unreleased/32831-single-deploy-of-runner-in-k8s-cluster.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Allow installation of GitLab Runner with a single click
-merge_request: 17134
-author:
-type: added
diff --git a/changelogs/unreleased/33570-slack-notify-default-branch.yml b/changelogs/unreleased/33570-slack-notify-default-branch.yml
deleted file mode 100644
index 5c90ce47729..00000000000
--- a/changelogs/unreleased/33570-slack-notify-default-branch.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix Slack/Mattermost notifications not respecting `notify_only_default_branch` setting for pushes
-merge_request: 17345
-author:
-type: fixed
diff --git a/changelogs/unreleased/35418-remove-underline-for-avatar.yml b/changelogs/unreleased/35418-remove-underline-for-avatar.yml
deleted file mode 100644
index 034365e1137..00000000000
--- a/changelogs/unreleased/35418-remove-underline-for-avatar.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: remove avater underline
-merge_request: 17219
-author: Ken Ding
-type: fixed
diff --git a/changelogs/unreleased/35530-teleporting-emoji.yml b/changelogs/unreleased/35530-teleporting-emoji.yml
deleted file mode 100644
index a60a42b9e48..00000000000
--- a/changelogs/unreleased/35530-teleporting-emoji.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix Teleporting Emoji
-merge_request: 16963
-author: Jared Deckard <jared.deckard@gmail.com>
-type: fixed
diff --git a/changelogs/unreleased/36847-update-update-toml-rb-to-1-0-0.yml b/changelogs/unreleased/36847-update-update-toml-rb-to-1-0-0.yml
deleted file mode 100644
index 74eaf57c056..00000000000
--- a/changelogs/unreleased/36847-update-update-toml-rb-to-1-0-0.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: update toml-rb to 1.0.0
-merge_request: 17259
-author: Ken Ding
-type: other
diff --git a/changelogs/unreleased/37050-ext-issue-tracker.yml b/changelogs/unreleased/37050-ext-issue-tracker.yml
deleted file mode 100644
index 29bccdded02..00000000000
--- a/changelogs/unreleased/37050-ext-issue-tracker.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Display a link to external issue tracker when enabled
-merge_request:
-author:
-type: changed
diff --git a/changelogs/unreleased/38587-pipelines-empty-state.yml b/changelogs/unreleased/38587-pipelines-empty-state.yml
deleted file mode 100644
index 58ea204d394..00000000000
--- a/changelogs/unreleased/38587-pipelines-empty-state.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Handle empty state in Pipelines page
-merge_request:
-author:
-type: fixed
diff --git a/changelogs/unreleased/39444-make-margin-around-dropdown-dividers-4px.yml b/changelogs/unreleased/39444-make-margin-around-dropdown-dividers-4px.yml
deleted file mode 100644
index da65cfff799..00000000000
--- a/changelogs/unreleased/39444-make-margin-around-dropdown-dividers-4px.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Set margins around dropdown dividers to 4px
-merge_request: 17517
-author:
-type: fixed
diff --git a/changelogs/unreleased/39607-fix-avatar--vertical-align.yml b/changelogs/unreleased/39607-fix-avatar--vertical-align.yml
deleted file mode 100644
index 4d9fee12f04..00000000000
--- a/changelogs/unreleased/39607-fix-avatar--vertical-align.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: "Fix user avatar's vertical align on the issues and merge requests pages"
-merge_request: 17072
-author: Laszlo Karpati
-type: fixed
diff --git a/changelogs/unreleased/40187-project-branch-dashboard-with-active-stale-branches.yml b/changelogs/unreleased/40187-project-branch-dashboard-with-active-stale-branches.yml
deleted file mode 100644
index 3833aab42dd..00000000000
--- a/changelogs/unreleased/40187-project-branch-dashboard-with-active-stale-branches.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Add overview of branches and a filter for active/stale branches
-merge_request: 15402
-author: Takuya Noguchi
-type: added
diff --git a/changelogs/unreleased/40502-osw-keep-link-when-redacting-unauthorized-objects.yml b/changelogs/unreleased/40502-osw-keep-link-when-redacting-unauthorized-objects.yml
deleted file mode 100644
index dddd8473df5..00000000000
--- a/changelogs/unreleased/40502-osw-keep-link-when-redacting-unauthorized-objects.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Keep link when redacting unauthorized object links
-merge_request:
-author:
-type: fixed
diff --git a/changelogs/unreleased/40525-listing-user-activity-timeouts.yml b/changelogs/unreleased/40525-listing-user-activity-timeouts.yml
deleted file mode 100644
index 39ce873dba6..00000000000
--- a/changelogs/unreleased/40525-listing-user-activity-timeouts.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Improve database response time for user activity listing.
-merge_request: 17454
-author:
-type: performance
diff --git a/changelogs/unreleased/40552-sanitize-extra-blank-spaces-used-when-uploading-a-ssh-key.yml b/changelogs/unreleased/40552-sanitize-extra-blank-spaces-used-when-uploading-a-ssh-key.yml
deleted file mode 100644
index 9e4811ca308..00000000000
--- a/changelogs/unreleased/40552-sanitize-extra-blank-spaces-used-when-uploading-a-ssh-key.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Sanitize extra blank spaces used when uploading a SSH key
-merge_request: 40552
-author:
-type: fixed
diff --git a/changelogs/unreleased/40623-fix-404-when-listing-archived-projects-in-a-group-where-all-projects-have-been-archived.yml b/changelogs/unreleased/40623-fix-404-when-listing-archived-projects-in-a-group-where-all-projects-have-been-archived.yml
deleted file mode 100644
index 543fd7c5e8d..00000000000
--- a/changelogs/unreleased/40623-fix-404-when-listing-archived-projects-in-a-group-where-all-projects-have-been-archived.yml
+++ /dev/null
@@ -1,4 +0,0 @@
-title: Fix 404 when listing archived projects in a group where all projects have been archived
-merge_request: 17077
-author: Ashley Dumaine
-type: fixed
diff --git a/changelogs/unreleased/40668-pages-domain-api-returns-404-when-using-a-specific-domain.yml b/changelogs/unreleased/40668-pages-domain-api-returns-404-when-using-a-specific-domain.yml
deleted file mode 100644
index d77572d6175..00000000000
--- a/changelogs/unreleased/40668-pages-domain-api-returns-404-when-using-a-specific-domain.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix get a single pages domain when project path contains a period
-merge_request: 17206
-author: Travis Miller
-type: fixed
diff --git a/changelogs/unreleased/40994-expose-features-as-ci-cd-variable.yml b/changelogs/unreleased/40994-expose-features-as-ci-cd-variable.yml
deleted file mode 100644
index 1e377094791..00000000000
--- a/changelogs/unreleased/40994-expose-features-as-ci-cd-variable.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: 'Expose GITLAB_FEATURES as CI/CD variable (fixes #40994)'
-merge_request:
-author:
-type: added
diff --git a/changelogs/unreleased/41616-api-issues-between-date.yml b/changelogs/unreleased/41616-api-issues-between-date.yml
deleted file mode 100644
index d8a23f48699..00000000000
--- a/changelogs/unreleased/41616-api-issues-between-date.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Adds updated_at filter to issues and merge_requests API
-merge_request: 17417
-author: Jacopo Beschi @jacopo-beschi
-type: added
diff --git a/changelogs/unreleased/41719-mr-title-fix.yml b/changelogs/unreleased/41719-mr-title-fix.yml
deleted file mode 100644
index 92388f30cb2..00000000000
--- a/changelogs/unreleased/41719-mr-title-fix.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Render htmlentities correctly for links not supported by Rinku
-merge_request:
-author:
-type: fixed
diff --git a/changelogs/unreleased/41777-include-cycle-time-in-usage-ping.yml b/changelogs/unreleased/41777-include-cycle-time-in-usage-ping.yml
deleted file mode 100644
index 8d8a5dfefa3..00000000000
--- a/changelogs/unreleased/41777-include-cycle-time-in-usage-ping.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Include cycle time in usage ping data
-merge_request: 16973
-author:
-type: added
diff --git a/changelogs/unreleased/41851-enable-eslint-codeclimate.yml b/changelogs/unreleased/41851-enable-eslint-codeclimate.yml
deleted file mode 100644
index 98924f3eae8..00000000000
--- a/changelogs/unreleased/41851-enable-eslint-codeclimate.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Enables eslint in codeclimate job
-merge_request: 17392
-author:
-type: other
diff --git a/changelogs/unreleased/41899-api-endpoint-for-importing-a-project-export.yml b/changelogs/unreleased/41899-api-endpoint-for-importing-a-project-export.yml
deleted file mode 100644
index 29ab7cc7cab..00000000000
--- a/changelogs/unreleased/41899-api-endpoint-for-importing-a-project-export.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: API endpoint for importing a project export
-merge_request: 17025
-author:
-type: added
diff --git a/changelogs/unreleased/41905_merge_request_and_issue_metrics.yml b/changelogs/unreleased/41905_merge_request_and_issue_metrics.yml
deleted file mode 100644
index c9e23360e3b..00000000000
--- a/changelogs/unreleased/41905_merge_request_and_issue_metrics.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: expose more metrics in merge requests api
-merge_request: 16589
-author: haseebeqx
-type: added
diff --git a/changelogs/unreleased/41949-move.yml b/changelogs/unreleased/41949-move.yml
deleted file mode 100644
index 40ccac63a28..00000000000
--- a/changelogs/unreleased/41949-move.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Remember assignee when moving an issue
-merge_request:
-author:
-type: fixed
diff --git a/changelogs/unreleased/42037-long-instance-names-group-names-covers-namespace-dropdown.yml b/changelogs/unreleased/42037-long-instance-names-group-names-covers-namespace-dropdown.yml
new file mode 100644
index 00000000000..f7758734a6f
--- /dev/null
+++ b/changelogs/unreleased/42037-long-instance-names-group-names-covers-namespace-dropdown.yml
@@ -0,0 +1,5 @@
+---
+title: Long instance urls do not overflow anymore during project creation
+merge_request: 17717
+author:
+type: fixed
diff --git a/changelogs/unreleased/42044-osw-add-button-to-deploy-runner-to-kubernetes.yml b/changelogs/unreleased/42044-osw-add-button-to-deploy-runner-to-kubernetes.yml
deleted file mode 100644
index 6cf0de5b3fa..00000000000
--- a/changelogs/unreleased/42044-osw-add-button-to-deploy-runner-to-kubernetes.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Add a button to deploy a runner to a Kubernetes cluster in the settings page
-merge_request: 17278
-author:
-type: changed
diff --git a/changelogs/unreleased/42274-group-request-membership-long-too.yml b/changelogs/unreleased/42274-group-request-membership-long-too.yml
deleted file mode 100644
index 03efedba638..00000000000
--- a/changelogs/unreleased/42274-group-request-membership-long-too.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix long list of recipients on group request membership email
-merge_request: 17121
-author: Jacopo Beschi @jacopo-beschi
-type: fixed
diff --git a/changelogs/unreleased/42314-diff-file.yml b/changelogs/unreleased/42314-diff-file.yml
deleted file mode 100644
index 1eed5ef1a34..00000000000
--- a/changelogs/unreleased/42314-diff-file.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Render modified icon for moved file in changes dropdown
-merge_request:
-author:
-type: fixed
diff --git a/changelogs/unreleased/42332-actionview-template-error-366-524-out-of-range.yml b/changelogs/unreleased/42332-actionview-template-error-366-524-out-of-range.yml
deleted file mode 100644
index 626c761bfbd..00000000000
--- a/changelogs/unreleased/42332-actionview-template-error-366-524-out-of-range.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix 500 error being shown when diff has context marker with invalid encoding
-merge_request:
-author:
-type: fixed
diff --git a/changelogs/unreleased/42431-add-auto-devops-and-clusters-button-to-projects.yml b/changelogs/unreleased/42431-add-auto-devops-and-clusters-button-to-projects.yml
deleted file mode 100644
index 5613b2af763..00000000000
--- a/changelogs/unreleased/42431-add-auto-devops-and-clusters-button-to-projects.yml
+++ /dev/null
@@ -1,6 +0,0 @@
----
-title: Add a button on the project page to set up a Kubernetes cluster and enable
- Auto DevOps
-merge_request: 16900
-author:
-type: added
diff --git a/changelogs/unreleased/42434-allow-commits-endpoint-to-work-over-all-commits.yml b/changelogs/unreleased/42434-allow-commits-endpoint-to-work-over-all-commits.yml
deleted file mode 100644
index c596a88ba0b..00000000000
--- a/changelogs/unreleased/42434-allow-commits-endpoint-to-work-over-all-commits.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Allow commits endpoint to work over all commits of a repository
-merge_request: 17182
-author:
-type: added
diff --git a/changelogs/unreleased/42481-remove-notification-settings-left-projects.yml b/changelogs/unreleased/42481-remove-notification-settings-left-projects.yml
deleted file mode 100644
index ea99649131b..00000000000
--- a/changelogs/unreleased/42481-remove-notification-settings-left-projects.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Remove user notification settings for groups and projects when user leaves
-merge_request: 16906
-author: Jacopo Beschi @jacopo-beschi
-type: fixed
diff --git a/changelogs/unreleased/42509-fix-API-PUT-projects-fails-when-only-ci_config_path-is-specified.yml b/changelogs/unreleased/42509-fix-API-PUT-projects-fails-when-only-ci_config_path-is-specified.yml
deleted file mode 100644
index a3dc1917001..00000000000
--- a/changelogs/unreleased/42509-fix-API-PUT-projects-fails-when-only-ci_config_path-is-specified.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Allow to call PUT /projects/:id API with only ci_config_path specified
-merge_request: 17105
-author: Laszlo Karpati
-type: fixed
diff --git a/changelogs/unreleased/42545-milestion-quick-actions-for-groups.yml b/changelogs/unreleased/42545-milestion-quick-actions-for-groups.yml
deleted file mode 100644
index d29f79aaaf8..00000000000
--- a/changelogs/unreleased/42545-milestion-quick-actions-for-groups.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Allows the usage of /milestone quick action for group milestones
-merge_request: 17239
-author: Jacopo Beschi @jacopo-beschi
-type: fixed
diff --git a/changelogs/unreleased/42643-persist-external-ip-of-ingress-controller-gke.yml b/changelogs/unreleased/42643-persist-external-ip-of-ingress-controller-gke.yml
deleted file mode 100644
index 35457db82f4..00000000000
--- a/changelogs/unreleased/42643-persist-external-ip-of-ingress-controller-gke.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Display ingress IP address in the Kubernetes page
-merge_request: 17052
-author:
-type: added
diff --git a/changelogs/unreleased/42712_api_branches_add_search_param_20180207.yml b/changelogs/unreleased/42712_api_branches_add_search_param_20180207.yml
deleted file mode 100644
index 609b5ce48ef..00000000000
--- a/changelogs/unreleased/42712_api_branches_add_search_param_20180207.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Add search param to Branches API
-merge_request: 17005
-author: bunufi
-type: added
diff --git a/changelogs/unreleased/42800-change-usage-of-avatar_icon.yml b/changelogs/unreleased/42800-change-usage-of-avatar_icon.yml
deleted file mode 100644
index 00f4b7436a7..00000000000
--- a/changelogs/unreleased/42800-change-usage-of-avatar_icon.yml
+++ /dev/null
@@ -1,6 +0,0 @@
----
-title: Use a user object in ApplicationHelper#avatar_icon where possible to avoid
- N+1 queries.
-merge_request: 42800
-author:
-type: performance
diff --git a/changelogs/unreleased/42814-fix-remove-source-branch-when-mwps.yml b/changelogs/unreleased/42814-fix-remove-source-branch-when-mwps.yml
deleted file mode 100644
index 08e77ee7c3b..00000000000
--- a/changelogs/unreleased/42814-fix-remove-source-branch-when-mwps.yml
+++ /dev/null
@@ -1,6 +0,0 @@
----
-title: Fix "Remove source branch" button in Merge request widget during merge when pipeline
- succeeds state
-merge_request: 17192
-author:
-type: fixed
diff --git a/changelogs/unreleased/42921-ci-charts-include-current-day.yml b/changelogs/unreleased/42921-ci-charts-include-current-day.yml
deleted file mode 100644
index d0de6665735..00000000000
--- a/changelogs/unreleased/42921-ci-charts-include-current-day.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: CI charts now include the current day
-merge_request: 17032
-author: Dakkaron
-type: changed
diff --git a/changelogs/unreleased/42922-environment-name.yml b/changelogs/unreleased/42922-environment-name.yml
deleted file mode 100644
index 0e9544245f6..00000000000
--- a/changelogs/unreleased/42922-environment-name.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Adds tooltip in environment names to increase readability
-merge_request:
-author:
-type: fixed
diff --git a/changelogs/unreleased/42923-close-issue.yml b/changelogs/unreleased/42923-close-issue.yml
deleted file mode 100644
index e332bbf5dec..00000000000
--- a/changelogs/unreleased/42923-close-issue.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix close button on issues not working on mobile
-merge_request:
-author:
-type: fixed
diff --git a/changelogs/unreleased/42929-hide-new-variable-values.yml b/changelogs/unreleased/42929-hide-new-variable-values.yml
deleted file mode 100644
index 68decd25b5a..00000000000
--- a/changelogs/unreleased/42929-hide-new-variable-values.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Hide CI secret variable values after saving
-merge_request: 17044
-author:
-type: changed
diff --git a/changelogs/unreleased/42946-update-pipeline-cancel-tooltip-to-stop.yml b/changelogs/unreleased/42946-update-pipeline-cancel-tooltip-to-stop.yml
deleted file mode 100644
index 0e566dd0abf..00000000000
--- a/changelogs/unreleased/42946-update-pipeline-cancel-tooltip-to-stop.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Update tooltip on pipeline cancel to Stop (#42946)
-merge_request: 17444
-author:
-type: fixed
diff --git a/changelogs/unreleased/43134-reduce-queries-pipelines-controller-show.yml b/changelogs/unreleased/43134-reduce-queries-pipelines-controller-show.yml
deleted file mode 100644
index c1e9614b676..00000000000
--- a/changelogs/unreleased/43134-reduce-queries-pipelines-controller-show.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Improve performance of pipeline page by reducing DB queries
-merge_request: 17168
-author:
-type: performance
diff --git a/changelogs/unreleased/43198-fix-settings-panel-expanding-when-fragment-hash-linked.yml b/changelogs/unreleased/43198-fix-settings-panel-expanding-when-fragment-hash-linked.yml
deleted file mode 100644
index 49ba48a0fef..00000000000
--- a/changelogs/unreleased/43198-fix-settings-panel-expanding-when-fragment-hash-linked.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix settings panels not expanding when fragment hash linked
-merge_request: 17074
-author:
-type: fixed
diff --git a/changelogs/unreleased/43201-rename-repository-submit-button-disabled.yml b/changelogs/unreleased/43201-rename-repository-submit-button-disabled.yml
deleted file mode 100644
index b527000332e..00000000000
--- a/changelogs/unreleased/43201-rename-repository-submit-button-disabled.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Allows project rename after validation error
-merge_request: 17150
-author:
-type: fixed
diff --git a/changelogs/unreleased/43261-fix-import-from-url-name-collision-active-tab.yml b/changelogs/unreleased/43261-fix-import-from-url-name-collision-active-tab.yml
deleted file mode 100644
index 71073b2e214..00000000000
--- a/changelogs/unreleased/43261-fix-import-from-url-name-collision-active-tab.yml
+++ /dev/null
@@ -1,6 +0,0 @@
----
-title: Keep "Import project" tab/form active when validation fails trying to import
- "Repo by URL"
-merge_request: 17136
-author:
-type: fixed
diff --git a/changelogs/unreleased/43275-improve-variables-validation-message.yml b/changelogs/unreleased/43275-improve-variables-validation-message.yml
deleted file mode 100644
index 88ef93123a0..00000000000
--- a/changelogs/unreleased/43275-improve-variables-validation-message.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Remove duplicated error message on duplicate variable validation
-merge_request: 17135
-author:
-type: fixed
diff --git a/changelogs/unreleased/43315-gpg-popover.yml b/changelogs/unreleased/43315-gpg-popover.yml
deleted file mode 100644
index 69238aa8075..00000000000
--- a/changelogs/unreleased/43315-gpg-popover.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fixes gpg popover layout
-merge_request: 17323
-author:
-type: fixed
diff --git a/changelogs/unreleased/43334-reply-by-email-did-not-pick-up-unsubscribe-quick-action.yml b/changelogs/unreleased/43334-reply-by-email-did-not-pick-up-unsubscribe-quick-action.yml
deleted file mode 100644
index 86be5ee1804..00000000000
--- a/changelogs/unreleased/43334-reply-by-email-did-not-pick-up-unsubscribe-quick-action.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix quick actions for users who cannot update issues and merge requests
-merge_request: 17482
-author:
-type: fixed
diff --git a/changelogs/unreleased/43460-track-projects-a-user-interacted-with.yml b/changelogs/unreleased/43460-track-projects-a-user-interacted-with.yml
deleted file mode 100644
index 99b6ac76a3e..00000000000
--- a/changelogs/unreleased/43460-track-projects-a-user-interacted-with.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Keep track of projects a user interacted with.
-merge_request: 17327
-author:
-type: other
diff --git a/changelogs/unreleased/43482-enabling-auto-devops-on-an-empty-project-gives-you-wrong-information.yml b/changelogs/unreleased/43482-enabling-auto-devops-on-an-empty-project-gives-you-wrong-information.yml
new file mode 100644
index 00000000000..889fd008bad
--- /dev/null
+++ b/changelogs/unreleased/43482-enabling-auto-devops-on-an-empty-project-gives-you-wrong-information.yml
@@ -0,0 +1,5 @@
+---
+title: Add empty repo check before running AutoDevOps pipeline
+merge_request: 17605
+author:
+type: changed
diff --git a/changelogs/unreleased/43489-display-runner-ip.yml b/changelogs/unreleased/43489-display-runner-ip.yml
deleted file mode 100644
index 621c2ec709a..00000000000
--- a/changelogs/unreleased/43489-display-runner-ip.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Display Runner IP Address
-merge_request: 17286
-author:
-type: added
diff --git a/changelogs/unreleased/43496-error-message-for-gke-clusters-persists-in-the-next-page.yml b/changelogs/unreleased/43496-error-message-for-gke-clusters-persists-in-the-next-page.yml
deleted file mode 100644
index c10b0e7a3cf..00000000000
--- a/changelogs/unreleased/43496-error-message-for-gke-clusters-persists-in-the-next-page.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Do not persist Google Project verification flash errors after a page reload
-merge_request: 17299
-author:
-type: fixed
diff --git a/changelogs/unreleased/43525-limit-number-of-failed-logins-using-ldap.yml b/changelogs/unreleased/43525-limit-number-of-failed-logins-using-ldap.yml
new file mode 100644
index 00000000000..f30fea3c4a7
--- /dev/null
+++ b/changelogs/unreleased/43525-limit-number-of-failed-logins-using-ldap.yml
@@ -0,0 +1,5 @@
+---
+title: Limit the number of failed logins when using LDAP for authentication
+merge_request: 43525
+author:
+type: added
diff --git a/changelogs/unreleased/43598-fix-duplicate-label-load-failure.yml b/changelogs/unreleased/43598-fix-duplicate-label-load-failure.yml
deleted file mode 100644
index bda4ec84e5c..00000000000
--- a/changelogs/unreleased/43598-fix-duplicate-label-load-failure.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix Group labels load failure when there are duplicate labels present
-merge_request: 17353
-author:
-type: fixed
diff --git a/changelogs/unreleased/43643-fix-mr-label-filtering.yml b/changelogs/unreleased/43643-fix-mr-label-filtering.yml
deleted file mode 100644
index 32a44aef243..00000000000
--- a/changelogs/unreleased/43643-fix-mr-label-filtering.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Enable filtering MR list based on clicked label in MR sidebar
-merge_request: 17390
-author:
-type: fixed
diff --git a/changelogs/unreleased/43771-improve-avatar-error-message.yml b/changelogs/unreleased/43771-improve-avatar-error-message.yml
new file mode 100644
index 00000000000..1fae10f4d1f
--- /dev/null
+++ b/changelogs/unreleased/43771-improve-avatar-error-message.yml
@@ -0,0 +1,5 @@
+---
+title: Change avatar error message to include allowed file formats
+merge_request: 17747
+author: Fabian Schneider
+type: changed
diff --git a/changelogs/unreleased/43780-add-a-paragraph-about-clusters-security-implications.yml b/changelogs/unreleased/43780-add-a-paragraph-about-clusters-security-implications.yml
deleted file mode 100644
index 0fa21a2013c..00000000000
--- a/changelogs/unreleased/43780-add-a-paragraph-about-clusters-security-implications.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Add a paragraph about security implications on Cluster's page
-merge_request: 17486
-author:
-type: added
diff --git a/changelogs/unreleased/43786-on-the-issuable-list-add-tooltips-to-icons.yml b/changelogs/unreleased/43786-on-the-issuable-list-add-tooltips-to-icons.yml
new file mode 100644
index 00000000000..19b633daace
--- /dev/null
+++ b/changelogs/unreleased/43786-on-the-issuable-list-add-tooltips-to-icons.yml
@@ -0,0 +1,5 @@
+---
+title: Add tooltips to icons in lists of issues and merge requests
+merge_request: 17700
+author:
+type: changed
diff --git a/changelogs/unreleased/43793-enable-privileged-mode-for-runner.yml b/changelogs/unreleased/43793-enable-privileged-mode-for-runner.yml
deleted file mode 100644
index 08109632e8e..00000000000
--- a/changelogs/unreleased/43793-enable-privileged-mode-for-runner.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Enable privileged mode for GitLab Runner
-merge_request: 17528
-author:
-type: added
diff --git a/changelogs/unreleased/43802-ensure-foreign-keys-on-clusters-applications.yml b/changelogs/unreleased/43802-ensure-foreign-keys-on-clusters-applications.yml
deleted file mode 100644
index 860a8becd65..00000000000
--- a/changelogs/unreleased/43802-ensure-foreign-keys-on-clusters-applications.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Ensure foreign keys on clusters applications
-merge_request: 17488
-author:
-type: other
diff --git a/changelogs/unreleased/43829-update-ssh-addtion-text.yml b/changelogs/unreleased/43829-update-ssh-addtion-text.yml
deleted file mode 100644
index b7052bb171e..00000000000
--- a/changelogs/unreleased/43829-update-ssh-addtion-text.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Update SSH key link to include existing keys
-merge_request:
-author: Brendan O'Leary
-type: changed
diff --git a/changelogs/unreleased/43837-error-handle-in-updating-milestone-on-issue.yml b/changelogs/unreleased/43837-error-handle-in-updating-milestone-on-issue.yml
deleted file mode 100644
index 526523964c3..00000000000
--- a/changelogs/unreleased/43837-error-handle-in-updating-milestone-on-issue.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Stop loading spinner on error of milestone update on issue
-merge_request: 17507
-author: Takuya Noguchi
-type: fixed
diff --git a/changelogs/unreleased/43924-breadcrumbs-on-project-tags.yml b/changelogs/unreleased/43924-breadcrumbs-on-project-tags.yml
deleted file mode 100644
index 67c223b31c5..00000000000
--- a/changelogs/unreleased/43924-breadcrumbs-on-project-tags.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Remove extra breadcrumb on tags
-merge_request: 17562
-author: Takuya Noguchi
-type: fixed
diff --git a/changelogs/unreleased/44024-fix-table-extra-column.yml b/changelogs/unreleased/44024-fix-table-extra-column.yml
deleted file mode 100644
index 92c354a0844..00000000000
--- a/changelogs/unreleased/44024-fix-table-extra-column.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix markdown table showing extra column
-merge_request: 17669
-author:
-type: fixed
diff --git a/changelogs/unreleased/44149-issue-comment-buttons.yml b/changelogs/unreleased/44149-issue-comment-buttons.yml
deleted file mode 100644
index c874c0d3d66..00000000000
--- a/changelogs/unreleased/44149-issue-comment-buttons.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix broken loading state for close issue button
-merge_request:
-author:
-type: fixed
diff --git a/changelogs/unreleased/44330-docs-for-ingress-ip.yml b/changelogs/unreleased/44330-docs-for-ingress-ip.yml
deleted file mode 100644
index 3dfaea6e17e..00000000000
--- a/changelogs/unreleased/44330-docs-for-ingress-ip.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Add documentation for displayed K8s Ingress IP address (#44330)
-merge_request: 17836
-author:
-type: other
diff --git a/changelogs/unreleased/44382-ui-breakdown-for-create-merge-request.yml b/changelogs/unreleased/44382-ui-breakdown-for-create-merge-request.yml
new file mode 100644
index 00000000000..dd8c0b19d5f
--- /dev/null
+++ b/changelogs/unreleased/44382-ui-breakdown-for-create-merge-request.yml
@@ -0,0 +1,5 @@
+---
+title: Fix UI breakdown for Create merge request button
+merge_request: 17821
+author: Takuya Noguchi
+type: fixed
diff --git a/changelogs/unreleased/44386-better-ux-for-long-name-branches.yml b/changelogs/unreleased/44386-better-ux-for-long-name-branches.yml
new file mode 100644
index 00000000000..16712486f0f
--- /dev/null
+++ b/changelogs/unreleased/44386-better-ux-for-long-name-branches.yml
@@ -0,0 +1,5 @@
+---
+title: UX re-design branch items with flexbox
+merge_request: 17832
+author: Takuya Noguchi
+type: fixed
diff --git a/changelogs/unreleased/4826-create-empty-wiki-when-it-s-enabled.yml b/changelogs/unreleased/4826-create-empty-wiki-when-it-s-enabled.yml
deleted file mode 100644
index c0fa8e2e377..00000000000
--- a/changelogs/unreleased/4826-create-empty-wiki-when-it-s-enabled.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Make sure wiki exists when it's enabled
-merge_request:
-author:
-type: fixed
diff --git a/changelogs/unreleased/4826-geo-wikisyncservice-attempts-to-sync-projects.yml b/changelogs/unreleased/4826-geo-wikisyncservice-attempts-to-sync-projects.yml
deleted file mode 100644
index 7f1ccbfcc7e..00000000000
--- a/changelogs/unreleased/4826-geo-wikisyncservice-attempts-to-sync-projects.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Create empty wiki when import from GitLab and wiki is not there
-merge_request:
-author:
-type: fixed
diff --git a/changelogs/unreleased/4826-github-import-wiki-fix-1.yml b/changelogs/unreleased/4826-github-import-wiki-fix-1.yml
deleted file mode 100644
index 69145cb6daf..00000000000
--- a/changelogs/unreleased/4826-github-import-wiki-fix-1.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: "[GitHub Import] Create an empty wiki if wiki import failed"
-merge_request:
-author:
-type: fixed
diff --git a/changelogs/unreleased/add-indexes-to-todos-for-heavy-users-like-sean.yml b/changelogs/unreleased/add-indexes-to-todos-for-heavy-users-like-sean.yml
deleted file mode 100644
index f0e5103a9d9..00000000000
--- a/changelogs/unreleased/add-indexes-to-todos-for-heavy-users-like-sean.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Add partial indexes on todos to handle users with many todos
-merge_request:
-author:
-type: performance
diff --git a/changelogs/unreleased/add-query-counts-to-profiler-output.yml b/changelogs/unreleased/add-query-counts-to-profiler-output.yml
new file mode 100644
index 00000000000..8a90b1cbeb0
--- /dev/null
+++ b/changelogs/unreleased/add-query-counts-to-profiler-output.yml
@@ -0,0 +1,5 @@
+---
+title: Add query counts to profiler output
+merge_request:
+author:
+type: other
diff --git a/changelogs/unreleased/an-network-controller-fix.yml b/changelogs/unreleased/an-network-controller-fix.yml
deleted file mode 100644
index cb2c447b957..00000000000
--- a/changelogs/unreleased/an-network-controller-fix.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Prevent the graphs page from generating unnecessary Gitaly requests
-merge_request: 37602
-author:
-type: performance
diff --git a/changelogs/unreleased/an-workhorse-3-8-0.yml b/changelogs/unreleased/an-workhorse-3-8-0.yml
deleted file mode 100644
index 5e2a72e1eda..00000000000
--- a/changelogs/unreleased/an-workhorse-3-8-0.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Upgrade Workhorse to version 3.8.0 to support structured logging
-merge_request:
-author:
-type: other
diff --git a/changelogs/unreleased/api-refs-for-commit.yml b/changelogs/unreleased/api-refs-for-commit.yml
deleted file mode 100644
index df8a2b0eccc..00000000000
--- a/changelogs/unreleased/api-refs-for-commit.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: 'API: Get references a commit is pushed to'
-merge_request: 15026
-author: Robert Schilling
-type: added
diff --git a/changelogs/unreleased/asciidoc_inter_document_cross_references.yml b/changelogs/unreleased/asciidoc_inter_document_cross_references.yml
deleted file mode 100644
index 34b26753312..00000000000
--- a/changelogs/unreleased/asciidoc_inter_document_cross_references.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Asciidoc now support inter-document cross references between files in repository
-merge_request: 17125
-author: Turo Soisenniemi
-type: changed
diff --git a/changelogs/unreleased/assignees-vue-component-missing-data-container.yml b/changelogs/unreleased/assignees-vue-component-missing-data-container.yml
deleted file mode 100644
index 233d983b415..00000000000
--- a/changelogs/unreleased/assignees-vue-component-missing-data-container.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Add Assignees vue component missing data container
-merge_request: 17426
-author: George Tsiolis
-type: fixed
diff --git a/changelogs/unreleased/bvl-allow-maintainer-to-push.yml b/changelogs/unreleased/bvl-allow-maintainer-to-push.yml
deleted file mode 100644
index a3fefc2889a..00000000000
--- a/changelogs/unreleased/bvl-allow-maintainer-to-push.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Allow maintainers to push to forks of their projects when a merge request is open
-merge_request: 17395
-author:
-type: added
diff --git a/changelogs/unreleased/bvl-port-of-ee-translations.yml b/changelogs/unreleased/bvl-port-of-ee-translations.yml
deleted file mode 100644
index 8f232ec8da3..00000000000
--- a/changelogs/unreleased/bvl-port-of-ee-translations.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Started translation into Turkish, Indonesian and Filipino
-merge_request: 17526
-author:
-type: other
diff --git a/changelogs/unreleased/cache-refactor.yml b/changelogs/unreleased/cache-refactor.yml
deleted file mode 100644
index dec7a0392a5..00000000000
--- a/changelogs/unreleased/cache-refactor.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Cache MergeRequests can_be_resolved_in_ui? git operations
-merge_request: 17589
-author:
-type: performance
diff --git a/changelogs/unreleased/ce-jej-github-project-service-for-ci.yml b/changelogs/unreleased/ce-jej-github-project-service-for-ci.yml
deleted file mode 100644
index 6102b7ecd93..00000000000
--- a/changelogs/unreleased/ce-jej-github-project-service-for-ci.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Hook data for pipelines includes detailed_status
-merge_request: 17607
-author:
-type: changed
diff --git a/changelogs/unreleased/ce-jej-integrations-can-hide-trigger-checkboxes.yml b/changelogs/unreleased/ce-jej-integrations-can-hide-trigger-checkboxes.yml
deleted file mode 100644
index 771df06e7a6..00000000000
--- a/changelogs/unreleased/ce-jej-integrations-can-hide-trigger-checkboxes.yml
+++ /dev/null
@@ -1,6 +0,0 @@
----
-title: Avoid showing unnecessary Trigger checkboxes for project Integrations with
- only one event
-merge_request: 17607
-author:
-type: changed
diff --git a/changelogs/unreleased/change-strip-whitespace-from-username-input-42637.yml b/changelogs/unreleased/change-strip-whitespace-from-username-input-42637.yml
deleted file mode 100644
index a51781396ee..00000000000
--- a/changelogs/unreleased/change-strip-whitespace-from-username-input-42637.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Remove whitespace from the username/email sign in form field
-merge_request: 17020
-author: Peter lauck
-type: changed
diff --git a/changelogs/unreleased/ci-pipeline-commit-lookup.yml b/changelogs/unreleased/ci-pipeline-commit-lookup.yml
new file mode 100644
index 00000000000..b2a1e4c2163
--- /dev/null
+++ b/changelogs/unreleased/ci-pipeline-commit-lookup.yml
@@ -0,0 +1,5 @@
+---
+title: Use porcelain commit lookup method on CI::CreatePipelineService
+merge_request: 17911
+author:
+type: fixed
diff --git a/changelogs/unreleased/discussions-api.yml b/changelogs/unreleased/discussions-api.yml
deleted file mode 100644
index 110df3aa414..00000000000
--- a/changelogs/unreleased/discussions-api.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Add discussions API for Issues and Snippets
-merge_request:
-author:
-type: added
diff --git a/changelogs/unreleased/dm-dont-cache-nil-root-ref.yml b/changelogs/unreleased/dm-dont-cache-nil-root-ref.yml
deleted file mode 100644
index 4dab7d0ffca..00000000000
--- a/changelogs/unreleased/dm-dont-cache-nil-root-ref.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Don't cache a nil repository root ref to prevent caching issues
-merge_request:
-author:
-type: fixed
diff --git a/changelogs/unreleased/dm-escape-commit-message.yml b/changelogs/unreleased/dm-escape-commit-message.yml
deleted file mode 100644
index 89af2da3484..00000000000
--- a/changelogs/unreleased/dm-escape-commit-message.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Escape HTML entities in commit messages
-merge_request:
-author:
-type: fixed
diff --git a/changelogs/unreleased/dm-go-get-api-token.yml b/changelogs/unreleased/dm-go-get-api-token.yml
deleted file mode 100644
index ad9cfe05849..00000000000
--- a/changelogs/unreleased/dm-go-get-api-token.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Allow token authentication on go-get request
-merge_request:
-author:
-type: changed
diff --git a/changelogs/unreleased/dm-stuck-import-jobs-verify.yml b/changelogs/unreleased/dm-stuck-import-jobs-verify.yml
deleted file mode 100644
index ed2c2d30f0d..00000000000
--- a/changelogs/unreleased/dm-stuck-import-jobs-verify.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Verify project import status again before marking as failed
-merge_request:
-author:
-type: fixed
diff --git a/changelogs/unreleased/docs-update-vue-naming-guidelines.yml b/changelogs/unreleased/docs-update-vue-naming-guidelines.yml
deleted file mode 100644
index 95bfd212370..00000000000
--- a/changelogs/unreleased/docs-update-vue-naming-guidelines.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Update vue component naming guidelines
-merge_request: 17018
-author: George Tsiolis
-type: other
diff --git a/changelogs/unreleased/dz-namespace-id-not-null.yml b/changelogs/unreleased/dz-namespace-id-not-null.yml
deleted file mode 100644
index 07b32aeeb86..00000000000
--- a/changelogs/unreleased/dz-namespace-id-not-null.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Add NOT NULL constraint to projects.namespace_id
-merge_request: 17448
-author:
-type: other
diff --git a/changelogs/unreleased/dz-plugins-project-integrations.yml b/changelogs/unreleased/dz-plugins-project-integrations.yml
deleted file mode 100644
index 9dbe82f9af8..00000000000
--- a/changelogs/unreleased/dz-plugins-project-integrations.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Add plugins list to the system hooks page
-merge_request: 17518
-author:
-type: added
diff --git a/changelogs/unreleased/dz-system-hooks-plugins.yml b/changelogs/unreleased/dz-system-hooks-plugins.yml
deleted file mode 100644
index e6eb1dfb03b..00000000000
--- a/changelogs/unreleased/dz-system-hooks-plugins.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Add ability to use external plugins as an alternative to system hooks
-merge_request: 17003
-author:
-type: added
diff --git a/changelogs/unreleased/ee-4862-verify-file-checksums.yml b/changelogs/unreleased/ee-4862-verify-file-checksums.yml
deleted file mode 100644
index 392c766ab37..00000000000
--- a/changelogs/unreleased/ee-4862-verify-file-checksums.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Foreground verification of uploads and LFS objects
-merge_request: 17402
-author:
-type: added
diff --git a/changelogs/unreleased/feature--2848-display-time-tracking-totals-milestone-page.yml b/changelogs/unreleased/feature--2848-display-time-tracking-totals-milestone-page.yml
deleted file mode 100644
index ca877d32b05..00000000000
--- a/changelogs/unreleased/feature--2848-display-time-tracking-totals-milestone-page.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: "#28481: Display time tracking totals on milestone page"
-merge_request: 16753
-author: Riccardo Padovani
-type: added
diff --git a/changelogs/unreleased/feature--43691-count-diff-note-calendar-activity.yml b/changelogs/unreleased/feature--43691-count-diff-note-calendar-activity.yml
deleted file mode 100644
index d8020592897..00000000000
--- a/changelogs/unreleased/feature--43691-count-diff-note-calendar-activity.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Count comments on diffs and discussions as contributions for the contributions calendar
-merge_request: 17418
-author: Riccardo Padovani
-type: fixed
diff --git a/changelogs/unreleased/feature-26598-clear-button-ci-lint.yml b/changelogs/unreleased/feature-26598-clear-button-ci-lint.yml
deleted file mode 100644
index fcf237f20f0..00000000000
--- a/changelogs/unreleased/feature-26598-clear-button-ci-lint.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Added clear button to ci lint editor
-merge_request:
-author: Michael Robinson
diff --git a/changelogs/unreleased/feature-edit_pages_domain.yml b/changelogs/unreleased/feature-edit_pages_domain.yml
deleted file mode 100644
index bd0af53296c..00000000000
--- a/changelogs/unreleased/feature-edit_pages_domain.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: 'Pages custom domain: allow update of key/certificate'
-merge_request: 17376
-author: rfwatson
-type: changed
diff --git a/changelogs/unreleased/feature-gb-pipeline-variable-expressions.yml b/changelogs/unreleased/feature-gb-pipeline-variable-expressions.yml
deleted file mode 100644
index 28820649af3..00000000000
--- a/changelogs/unreleased/feature-gb-pipeline-variable-expressions.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Add catch-up background migration to migrate pipeline stages
-merge_request: 15741
-author:
-type: performance
diff --git a/changelogs/unreleased/feature-include-custom-attributes-in-api.yml b/changelogs/unreleased/feature-include-custom-attributes-in-api.yml
deleted file mode 100644
index f1087d7f7cc..00000000000
--- a/changelogs/unreleased/feature-include-custom-attributes-in-api.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Allow including custom attributes in API responses
-merge_request: 16526
-author: Markus Koller
-type: changed
diff --git a/changelogs/unreleased/feature-oidc-groups-claim.yml b/changelogs/unreleased/feature-oidc-groups-claim.yml
deleted file mode 100644
index bde19130114..00000000000
--- a/changelogs/unreleased/feature-oidc-groups-claim.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Add groups to OpenID Connect claims
-merge_request: 16929
-author: Hassan Zamani
diff --git a/changelogs/unreleased/feature-sm-add-check-sum-to-job-artifacts.yml b/changelogs/unreleased/feature-sm-add-check-sum-to-job-artifacts.yml
deleted file mode 100644
index 23a870d6e9f..00000000000
--- a/changelogs/unreleased/feature-sm-add-check-sum-to-job-artifacts.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Store sha256 checksum to job artifacts
-merge_request: 17354
-author:
-type: performance
diff --git a/changelogs/unreleased/fix-auth0-unsafe-login.yml b/changelogs/unreleased/fix-auth0-unsafe-login.yml
new file mode 100644
index 00000000000..01c6ea69dcc
--- /dev/null
+++ b/changelogs/unreleased/fix-auth0-unsafe-login.yml
@@ -0,0 +1,5 @@
+---
+title: Fix GitLab Auth0 integration signing in the wrong user
+merge_request:
+author:
+type: security
diff --git a/changelogs/unreleased/fix-change-event-body-label-font-size.yml b/changelogs/unreleased/fix-change-event-body-label-font-size.yml
deleted file mode 100644
index 3192a7bff92..00000000000
--- a/changelogs/unreleased/fix-change-event-body-label-font-size.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Apply new default and inline label design
-merge_request: 16956
-author: George Tsiolis
-type: changed
diff --git a/changelogs/unreleased/fix-dropzone-project-show.yml b/changelogs/unreleased/fix-dropzone-project-show.yml
deleted file mode 100644
index 660780812d8..00000000000
--- a/changelogs/unreleased/fix-dropzone-project-show.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix file upload on project show page
-merge_request:
-author:
-type: fixed
diff --git a/changelogs/unreleased/fix-new-project-path-input-overlapping.yml b/changelogs/unreleased/fix-new-project-path-input-overlapping.yml
deleted file mode 100644
index fb33ce9437a..00000000000
--- a/changelogs/unreleased/fix-new-project-path-input-overlapping.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix new project path input overlapping
-merge_request: 16755
-author: George Tsiolis
-type: fixed
diff --git a/changelogs/unreleased/fix-squash-with-renamed-files.yml b/changelogs/unreleased/fix-squash-with-renamed-files.yml
deleted file mode 100644
index f7cd3a84367..00000000000
--- a/changelogs/unreleased/fix-squash-with-renamed-files.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix squashing when a file is renamed
-merge_request:
-author:
-type: fixed
diff --git a/changelogs/unreleased/fix-template-project-visibility.yml b/changelogs/unreleased/fix-template-project-visibility.yml
deleted file mode 100644
index 6576097822b..00000000000
--- a/changelogs/unreleased/fix-template-project-visibility.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Respect description and visibility when creating project from template
-merge_request: 16820
-author: George Tsiolis
-type: fixed
diff --git a/changelogs/unreleased/fj-15329-services-callbacks-ssrf.yml b/changelogs/unreleased/fj-15329-services-callbacks-ssrf.yml
new file mode 100644
index 00000000000..7fa6f6a5874
--- /dev/null
+++ b/changelogs/unreleased/fj-15329-services-callbacks-ssrf.yml
@@ -0,0 +1,5 @@
+---
+title: Fixed some SSRF vulnerabilities in services, hooks and integrations
+merge_request: 2337
+author:
+type: security
diff --git a/changelogs/unreleased/fj-28141-redirection-loop.yml b/changelogs/unreleased/fj-28141-redirection-loop.yml
deleted file mode 100644
index db7e109a06e..00000000000
--- a/changelogs/unreleased/fj-28141-redirection-loop.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Removing the two factor check when the user sets a new password
-merge_request: 17457
-author:
-type: fixed
diff --git a/changelogs/unreleased/fj-41174-projects-groups-badges-api.yml b/changelogs/unreleased/fj-41174-projects-groups-badges-api.yml
deleted file mode 100644
index 7cb12e26332..00000000000
--- a/changelogs/unreleased/fj-41174-projects-groups-badges-api.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Implemented badge API endpoints
-merge_request: 17082
-author:
-type: added
diff --git a/changelogs/unreleased/fj-42910-unauthenticated-limit-via-ssh.yml b/changelogs/unreleased/fj-42910-unauthenticated-limit-via-ssh.yml
deleted file mode 100644
index cef339ef787..00000000000
--- a/changelogs/unreleased/fj-42910-unauthenticated-limit-via-ssh.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fixed bug with unauthenticated requests through git ssh
-merge_request: 17149
-author:
-type: fixed
diff --git a/changelogs/unreleased/fl-refresh-btn.yml b/changelogs/unreleased/fl-refresh-btn.yml
deleted file mode 100644
index 640fdda9ce7..00000000000
--- a/changelogs/unreleased/fl-refresh-btn.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Show loading button inline in refresh button in MR widget
-merge_request:
-author:
-type: fixed
diff --git a/changelogs/unreleased/group-label-page-breadcrumb.yml b/changelogs/unreleased/group-label-page-breadcrumb.yml
deleted file mode 100644
index c6cc4618c52..00000000000
--- a/changelogs/unreleased/group-label-page-breadcrumb.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix breadcrumb on labels page for groups
-merge_request: 17045
-author: Onuwa Nnachi Isaac
-type: fixed
diff --git a/changelogs/unreleased/ide-folder-button-path.yml b/changelogs/unreleased/ide-folder-button-path.yml
new file mode 100644
index 00000000000..84a122fab75
--- /dev/null
+++ b/changelogs/unreleased/ide-folder-button-path.yml
@@ -0,0 +1,5 @@
+---
+title: Fixed IDE button opening the wrong URL in tree list
+merge_request:
+author:
+type: fixed
diff --git a/changelogs/unreleased/increase-unicorn-memory-killer-limits.yml b/changelogs/unreleased/increase-unicorn-memory-killer-limits.yml
new file mode 100644
index 00000000000..6d7d2df4f4a
--- /dev/null
+++ b/changelogs/unreleased/increase-unicorn-memory-killer-limits.yml
@@ -0,0 +1,5 @@
+---
+title: Increase the memory limits used in the unicorn killer
+merge_request: 17948
+author:
+type: other
diff --git a/changelogs/unreleased/issue-39885.yml b/changelogs/unreleased/issue-39885.yml
deleted file mode 100644
index 75bf9434152..00000000000
--- a/changelogs/unreleased/issue-39885.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: 'Ensure users cannot create environments with leading or trailing slashes (Fixes #39885)'
-merge_request: 15273
-author:
-type: fixed
diff --git a/changelogs/unreleased/issue_31081.yml b/changelogs/unreleased/issue_31081.yml
deleted file mode 100644
index ac547c285db..00000000000
--- a/changelogs/unreleased/issue_31081.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Use host URL to build JIRA remote link icon
-merge_request:
-author:
-type: other
diff --git a/changelogs/unreleased/issue_38337.yml b/changelogs/unreleased/issue_38337.yml
deleted file mode 100644
index df65118b65c..00000000000
--- a/changelogs/unreleased/issue_38337.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Add one group board to Libre
-merge_request:
-author:
-type: added
diff --git a/changelogs/unreleased/jivl-new-modal-project-labels-milestones.yml b/changelogs/unreleased/jivl-new-modal-project-labels-milestones.yml
deleted file mode 100644
index 6b7e14c6cfc..00000000000
--- a/changelogs/unreleased/jivl-new-modal-project-labels-milestones.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Added new design for promotion modals
-merge_request: 17197
-author:
-type: other
diff --git a/changelogs/unreleased/jprovazn-issueref.yml b/changelogs/unreleased/jprovazn-issueref.yml
new file mode 100644
index 00000000000..ee19cac7b19
--- /dev/null
+++ b/changelogs/unreleased/jprovazn-issueref.yml
@@ -0,0 +1,6 @@
+---
+title: Display state indicator for issuable references in non-project scope (e.g.
+ when referencing issuables from group scope).
+merge_request:
+author:
+type: fixed
diff --git a/changelogs/unreleased/jprovazn-scoped-limit.yml b/changelogs/unreleased/jprovazn-scoped-limit.yml
deleted file mode 100644
index 45724bb3479..00000000000
--- a/changelogs/unreleased/jprovazn-scoped-limit.yml
+++ /dev/null
@@ -1,6 +0,0 @@
----
-title: Optimize search queries on the search page by setting a limit for matching
- records in project scope
-merge_request:
-author:
-type: performance
diff --git a/changelogs/unreleased/kp-label-select-vue.yml b/changelogs/unreleased/kp-label-select-vue.yml
deleted file mode 100644
index 1f5952f2554..00000000000
--- a/changelogs/unreleased/kp-label-select-vue.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Port Labels Select dropdown to Vue
-merge_request: 17411
-author:
-type: other
diff --git a/changelogs/unreleased/merge-requests-api-filter-by-branch.yml b/changelogs/unreleased/merge-requests-api-filter-by-branch.yml
deleted file mode 100644
index 03a7e4d0f71..00000000000
--- a/changelogs/unreleased/merge-requests-api-filter-by-branch.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Add support for filtering by source and target branch to merge requests API
-merge_request:
-author:
-type: added
diff --git a/changelogs/unreleased/move-email-footer-info-to-single-line.yml b/changelogs/unreleased/move-email-footer-info-to-single-line.yml
new file mode 100644
index 00000000000..87ed5638056
--- /dev/null
+++ b/changelogs/unreleased/move-email-footer-info-to-single-line.yml
@@ -0,0 +1,5 @@
+---
+title: Move email footer info to a single line
+merge_request: 17916
+author:
+type: changed
diff --git a/changelogs/unreleased/mr-commit-optimization.yml b/changelogs/unreleased/mr-commit-optimization.yml
deleted file mode 100644
index 522d8951b18..00000000000
--- a/changelogs/unreleased/mr-commit-optimization.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Use persisted/memoized value for MRs shas instead of doing git lookups
-merge_request: 17555
-author:
-type: performance
diff --git a/changelogs/unreleased/oauth_generic_provider.yml b/changelogs/unreleased/oauth_generic_provider.yml
deleted file mode 100644
index 3b6f8b04529..00000000000
--- a/changelogs/unreleased/oauth_generic_provider.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Make oauth provider login generic
-merge_request: 8809
-author: Horatiu Eugen Vlad \ No newline at end of file
diff --git a/changelogs/unreleased/osw-43951-single-batch-blob-request-to-gitaly.yml b/changelogs/unreleased/osw-43951-single-batch-blob-request-to-gitaly.yml
deleted file mode 100644
index 34f834298b6..00000000000
--- a/changelogs/unreleased/osw-43951-single-batch-blob-request-to-gitaly.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Submit a single batch blob RPC to Gitaly per HTTP request when viewing diffs
-merge_request:
-author:
-type: performance
diff --git a/changelogs/unreleased/osw-stop-recalculating-merge-base-on-mr-loading.yml b/changelogs/unreleased/osw-stop-recalculating-merge-base-on-mr-loading.yml
deleted file mode 100644
index 1673e1d3658..00000000000
--- a/changelogs/unreleased/osw-stop-recalculating-merge-base-on-mr-loading.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Avoid re-fetching merge-base SHA from Gitaly unnecessarily
-merge_request:
-author:
-type: performance
diff --git a/changelogs/unreleased/pages_force_https.yml b/changelogs/unreleased/pages_force_https.yml
new file mode 100644
index 00000000000..da7e29087f3
--- /dev/null
+++ b/changelogs/unreleased/pages_force_https.yml
@@ -0,0 +1,5 @@
+---
+title: Add HTTPS-only pages
+merge_request: 16273
+author: rfwatson
+type: added
diff --git a/changelogs/unreleased/proper-fix-for-artifacts-service.yml b/changelogs/unreleased/proper-fix-for-artifacts-service.yml
deleted file mode 100644
index e92e995dbf5..00000000000
--- a/changelogs/unreleased/proper-fix-for-artifacts-service.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Add archive feature to trace
-merge_request: 17314
-author:
-type: added
diff --git a/changelogs/unreleased/refactor-move-assignees-vue-component.yml b/changelogs/unreleased/refactor-move-assignees-vue-component.yml
deleted file mode 100644
index 98cfa6b4c81..00000000000
--- a/changelogs/unreleased/refactor-move-assignees-vue-component.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Move Assignees vue component
-merge_request: 16952
-author: George Tsiolis
-type: performance
diff --git a/changelogs/unreleased/refactor-move-board-new-issue-vue-component.yml b/changelogs/unreleased/refactor-move-board-new-issue-vue-component.yml
deleted file mode 100644
index 20d05530513..00000000000
--- a/changelogs/unreleased/refactor-move-board-new-issue-vue-component.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Move BoardNewIssue vue component
-merge_request: 16947
-author: George Tsiolis
-type: performance
diff --git a/changelogs/unreleased/refactor-move-filtered-search-vue-component.yml b/changelogs/unreleased/refactor-move-filtered-search-vue-component.yml
deleted file mode 100644
index d65318d7ba1..00000000000
--- a/changelogs/unreleased/refactor-move-filtered-search-vue-component.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Move RecentSearchesDropdownContent vue component
-merge_request: 16951
-author: George Tsiolis
-type: performance
diff --git a/changelogs/unreleased/refactor-move-issuable-time-tracker-vue-component.yml b/changelogs/unreleased/refactor-move-issuable-time-tracker-vue-component.yml
deleted file mode 100644
index 5ed06c61817..00000000000
--- a/changelogs/unreleased/refactor-move-issuable-time-tracker-vue-component.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Move IssuableTimeTracker vue component
-merge_request: 16948
-author: George Tsiolis
-type: performance
diff --git a/changelogs/unreleased/refactor-move-sidebar-assignee-vue-component.yml b/changelogs/unreleased/refactor-move-sidebar-assignee-vue-component.yml
deleted file mode 100644
index e77b651363e..00000000000
--- a/changelogs/unreleased/refactor-move-sidebar-assignee-vue-component.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Move SidebarAssignees vue component
-merge_request: 17398
-author: George Tsiolis
-type: performance
diff --git a/changelogs/unreleased/refactor-move-time-tracking-vue-components.yml b/changelogs/unreleased/refactor-move-time-tracking-vue-components.yml
new file mode 100644
index 00000000000..8151655250a
--- /dev/null
+++ b/changelogs/unreleased/refactor-move-time-tracking-vue-components.yml
@@ -0,0 +1,5 @@
+---
+title: Move TimeTrackingCollapsedState vue component
+merge_request: 17399
+author: George Tsiolis
+type: performance
diff --git a/changelogs/unreleased/remove-unnecessary-validate-project.yml b/changelogs/unreleased/remove-unnecessary-validate-project.yml
deleted file mode 100644
index ebc8da03dd8..00000000000
--- a/changelogs/unreleased/remove-unnecessary-validate-project.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: 'Remove unecessary validate: true from belongs_to :project'
-merge_request:
-author:
-type: fixed
diff --git a/changelogs/unreleased/replace_redcarpet_with_cmark.yml b/changelogs/unreleased/replace_redcarpet_with_cmark.yml
deleted file mode 100644
index 7ce848b0bbd..00000000000
--- a/changelogs/unreleased/replace_redcarpet_with_cmark.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Add CommonMark markdown engine (experimental)
-merge_request: 14835
-author: blackst0ne
-type: added
diff --git a/changelogs/unreleased/sh-cache-column-exists.yml b/changelogs/unreleased/sh-cache-column-exists.yml
deleted file mode 100644
index 8bc648f2b32..00000000000
--- a/changelogs/unreleased/sh-cache-column-exists.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Cache column_exists? for application settings
-merge_request:
-author:
-type: performance
diff --git a/changelogs/unreleased/sh-cache-table-exists.yml b/changelogs/unreleased/sh-cache-table-exists.yml
deleted file mode 100644
index 37407b2a005..00000000000
--- a/changelogs/unreleased/sh-cache-table-exists.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Cache table_exists?('application_settings') to reduce repeated schema reloads
-merge_request:
-author:
-type: performance
diff --git a/changelogs/unreleased/sh-cleanup-after-git-gc.yml b/changelogs/unreleased/sh-cleanup-after-git-gc.yml
deleted file mode 100644
index 4b652f4d6ce..00000000000
--- a/changelogs/unreleased/sh-cleanup-after-git-gc.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Release libgit2 cache and open file descriptors after `git gc` run
-merge_request:
-author:
-type: fixed
diff --git a/changelogs/unreleased/sh-dashboard-sort-fix.yml b/changelogs/unreleased/sh-dashboard-sort-fix.yml
deleted file mode 100644
index 6fd252f6707..00000000000
--- a/changelogs/unreleased/sh-dashboard-sort-fix.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix project dashboard showing the wrong timestamps
-merge_request:
-author:
-type: fixed
diff --git a/changelogs/unreleased/sh-fix-failure-project-destroy.yml b/changelogs/unreleased/sh-fix-failure-project-destroy.yml
deleted file mode 100644
index d5f5cd3f954..00000000000
--- a/changelogs/unreleased/sh-fix-failure-project-destroy.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix "Can't modify frozen hash" error when project is destroyed
-merge_request:
-author:
-type: fixed
diff --git a/changelogs/unreleased/sh-fix-geo-error-500-gpg-commit.yml b/changelogs/unreleased/sh-fix-geo-error-500-gpg-commit.yml
deleted file mode 100644
index 5b4bbe0dc7a..00000000000
--- a/changelogs/unreleased/sh-fix-geo-error-500-gpg-commit.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix Error 500 when viewing a commit with a GPG signature in Geo
-merge_request:
-author:
-type: fixed
diff --git a/changelogs/unreleased/sh-fix-issue-43871-system-hooks.yml b/changelogs/unreleased/sh-fix-issue-43871-system-hooks.yml
deleted file mode 100644
index 7c7ef39cb75..00000000000
--- a/changelogs/unreleased/sh-fix-issue-43871-system-hooks.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Don't error out in system hook if user has `nil` datetime columns
-merge_request:
-author:
-type: fixed
diff --git a/changelogs/unreleased/sh-fix-otp-backup-code-invalidation.yml b/changelogs/unreleased/sh-fix-otp-backup-code-invalidation.yml
deleted file mode 100644
index cedb09c9a7a..00000000000
--- a/changelogs/unreleased/sh-fix-otp-backup-code-invalidation.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Ensure that OTP backup codes are always invalidated
-merge_request:
-author:
-type: security
diff --git a/changelogs/unreleased/sh-make-prune-optional-in-git-fetch.yml b/changelogs/unreleased/sh-make-prune-optional-in-git-fetch.yml
deleted file mode 100644
index e961a23a031..00000000000
--- a/changelogs/unreleased/sh-make-prune-optional-in-git-fetch.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Make --prune a configurable parameter in fetching a git remote
-merge_request:
-author:
-type: performance
diff --git a/changelogs/unreleased/sh-optimize-admin-projects-page.yml b/changelogs/unreleased/sh-optimize-admin-projects-page.yml
deleted file mode 100644
index 242ea758dab..00000000000
--- a/changelogs/unreleased/sh-optimize-admin-projects-page.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix timeouts loading /admin/projects page
-merge_request:
-author:
-type: performance
diff --git a/changelogs/unreleased/sh-update-loofah.yml b/changelogs/unreleased/sh-update-loofah.yml
new file mode 100644
index 00000000000..6aff0f91939
--- /dev/null
+++ b/changelogs/unreleased/sh-update-loofah.yml
@@ -0,0 +1,5 @@
+---
+title: Bump rails-html-sanitizer to 1.0.4
+merge_request:
+author:
+type: security
diff --git a/changelogs/unreleased/tc-api-fix-expose_url.yml b/changelogs/unreleased/tc-api-fix-expose_url.yml
deleted file mode 100644
index c701f64d6bf..00000000000
--- a/changelogs/unreleased/tc-api-fix-expose_url.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Ensure the API returns https links when https is configured
-merge_request: 17681
-author:
-type: fixed
diff --git a/changelogs/unreleased/tc-re-add-read-only-banner.yml b/changelogs/unreleased/tc-re-add-read-only-banner.yml
new file mode 100644
index 00000000000..35bcd7e184e
--- /dev/null
+++ b/changelogs/unreleased/tc-re-add-read-only-banner.yml
@@ -0,0 +1,5 @@
+---
+title: Add read-only banner to all pages
+merge_request: 17798
+author:
+type: fixed
diff --git a/changelogs/unreleased/unassign-when-leaving.yml b/changelogs/unreleased/unassign-when-leaving.yml
deleted file mode 100644
index c00a87b1749..00000000000
--- a/changelogs/unreleased/unassign-when-leaving.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Don't delete todos or unassign issues and MRs when a user leaves a project
-merge_request:
-author:
-type: fixed
diff --git a/changelogs/unreleased/upgrade-workhorse-4-0-0.yml b/changelogs/unreleased/upgrade-workhorse-4-0-0.yml
deleted file mode 100644
index f9dbdc7fc56..00000000000
--- a/changelogs/unreleased/upgrade-workhorse-4-0-0.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Upgrade GitLab Workhorse to 4.0.0
-merge_request:
-author:
-type: added
diff --git a/changelogs/unreleased/winh-deprecate-old-modal.yml b/changelogs/unreleased/winh-deprecate-old-modal.yml
new file mode 100644
index 00000000000..4fae1fafbea
--- /dev/null
+++ b/changelogs/unreleased/winh-deprecate-old-modal.yml
@@ -0,0 +1,5 @@
+---
+title: Rename modal.vue to deprecated_modal.vue
+merge_request: 17438
+author:
+type: other
diff --git a/changelogs/unreleased/winh-new-modal-component.yml b/changelogs/unreleased/winh-new-modal-component.yml
deleted file mode 100644
index bcc0d489c88..00000000000
--- a/changelogs/unreleased/winh-new-modal-component.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Add new modal Vue component
-merge_request: 17108
-author:
-type: changed
diff --git a/changelogs/unreleased/wip-new-mr-cmd.yml b/changelogs/unreleased/wip-new-mr-cmd.yml
deleted file mode 100644
index e930758ec9d..00000000000
--- a/changelogs/unreleased/wip-new-mr-cmd.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Port /wip quick action command to Merge Request creation (on description)
-merge_request: 17463
-author: Adam Pahlevi
-type: added
diff --git a/changelogs/unreleased/zj-move-opt-out-ruby-endpoints.yml b/changelogs/unreleased/zj-move-opt-out-ruby-endpoints.yml
deleted file mode 100644
index 0ddb42bc80a..00000000000
--- a/changelogs/unreleased/zj-move-opt-out-ruby-endpoints.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Move Ruby endpoints to OPT_OUT
-merge_request:
-author:
-type: other
diff --git a/changelogs/unreleased/zj-version-string-grouping-ci.yml b/changelogs/unreleased/zj-version-string-grouping-ci.yml
deleted file mode 100644
index 04ef0f65b1e..00000000000
--- a/changelogs/unreleased/zj-version-string-grouping-ci.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Allow CI/CD Jobs being grouped on version strings
-merge_request:
-author:
-type: added
diff --git a/config.ru b/config.ru
index 7b15939c6ff..405d01863ac 100644
--- a/config.ru
+++ b/config.ru
@@ -7,8 +7,8 @@ if defined?(Unicorn)
# Unicorn self-process killer
require 'unicorn/worker_killer'
- min = (ENV['GITLAB_UNICORN_MEMORY_MIN'] || 300 * 1 << 20).to_i
- max = (ENV['GITLAB_UNICORN_MEMORY_MAX'] || 350 * 1 << 20).to_i
+ min = (ENV['GITLAB_UNICORN_MEMORY_MIN'] || 400 * 1 << 20).to_i
+ max = (ENV['GITLAB_UNICORN_MEMORY_MAX'] || 650 * 1 << 20).to_i
# Max memory size (RSS) per worker
use Unicorn::WorkerKiller::Oom, min, max
diff --git a/config/application.rb b/config/application.rb
index 0ff95e33a9c..13501d4bdb5 100644
--- a/config/application.rb
+++ b/config/application.rb
@@ -170,7 +170,7 @@ module Gitlab
ENV['GIT_TERMINAL_PROMPT'] = '0'
# Gitlab Read-only middleware support
- config.middleware.insert_after ActionDispatch::Flash, 'Gitlab::Middleware::ReadOnly'
+ config.middleware.insert_after ActionDispatch::Flash, '::Gitlab::Middleware::ReadOnly'
config.generators do |g|
g.factory_bot false
diff --git a/config/initializers/1_settings.rb b/config/initializers/1_settings.rb
index ea0dee7af53..53cf0010d8e 100644
--- a/config/initializers/1_settings.rb
+++ b/config/initializers/1_settings.rb
@@ -467,12 +467,7 @@ unless Settings.repositories.storages['default']
end
Settings.repositories.storages.each do |key, storage|
- storage = Settingslogic.new(storage)
-
- # Expand relative paths
- storage['path'] = Settings.absolute(storage['path'])
-
- Settings.repositories.storages[key] = storage
+ Settings.repositories.storages[key] = Gitlab::GitalyClient::StorageSettings.new(storage)
end
#
@@ -486,7 +481,7 @@ repositories_storages = Settings.repositories.storages.values
repository_downloads_path = Settings.gitlab['repository_downloads_path'].to_s.gsub(%r{/$}, '')
repository_downloads_full_path = File.expand_path(repository_downloads_path, Settings.gitlab['user_home'])
-if repository_downloads_path.blank? || repositories_storages.any? { |rs| [repository_downloads_path, repository_downloads_full_path].include?(rs['path'].gsub(%r{/$}, '')) }
+if repository_downloads_path.blank? || repositories_storages.any? { |rs| [repository_downloads_path, repository_downloads_full_path].include?(rs.legacy_disk_path.gsub(%r{/$}, '')) }
Settings.gitlab['repository_downloads_path'] = File.join(Settings.shared['path'], 'cache/archive')
end
diff --git a/config/initializers/6_validations.rb b/config/initializers/6_validations.rb
index f8e67ce04c9..d92cdb97766 100644
--- a/config/initializers/6_validations.rb
+++ b/config/initializers/6_validations.rb
@@ -5,7 +5,7 @@ end
def find_parent_path(name, path)
parent = Pathname.new(path).realpath.parent
Gitlab.config.repositories.storages.detect do |n, rs|
- name != n && Pathname.new(rs['path']).realpath == parent
+ name != n && Pathname.new(rs.legacy_disk_path).realpath == parent
end
rescue Errno::EIO, Errno::ENOENT => e
warning = "WARNING: couldn't verify #{path} (#{name}). "\
@@ -33,7 +33,7 @@ def validate_storages_config
"If you're using the Gitlab Development Kit, you can update your configuration running `gdk reconfigure`.\n"
end
- if !repository_storage.is_a?(Hash) || repository_storage['path'].nil?
+ if !repository_storage.is_a?(Gitlab::GitalyClient::StorageSettings) || repository_storage.legacy_disk_path.nil?
storage_validation_error("#{name} is not a valid storage, because it has no `path` key. Refer to gitlab.yml.example for an updated example")
end
@@ -50,7 +50,7 @@ end
def validate_storages_paths
Gitlab.config.repositories.storages.each do |name, repository_storage|
- parent_name, _parent_path = find_parent_path(name, repository_storage['path'])
+ parent_name, _parent_path = find_parent_path(name, repository_storage.legacy_disk_path)
if parent_name
storage_validation_error("#{name} is a nested path of #{parent_name}. Nested paths are not supported for repository storages")
end
diff --git a/config/initializers/ar5_batching.rb b/config/initializers/ar5_batching.rb
index 6ebaf8834d2..874455ce5af 100644
--- a/config/initializers/ar5_batching.rb
+++ b/config/initializers/ar5_batching.rb
@@ -1,41 +1,39 @@
-# Port ActiveRecord::Relation#in_batches from ActiveRecord 5.
-# https://github.com/rails/rails/blob/ac027338e4a165273607dccee49a3d38bc836794/activerecord/lib/active_record/relation/batches.rb#L184
-# TODO: this can be removed once we're using AR5.
-raise "Vendored ActiveRecord 5 code! Delete #{__FILE__}!" if ActiveRecord::VERSION::MAJOR >= 5
-
-module ActiveRecord
- module Batches
- # Differences from upstream: enumerator support was removed, and custom
- # order/limit clauses are ignored without a warning.
- def in_batches(of: 1000, start: nil, finish: nil, load: false)
- raise "Must provide a block" unless block_given?
-
- relation = self.reorder(batch_order).limit(of)
- relation = relation.where(arel_table[primary_key].gteq(start)) if start
- relation = relation.where(arel_table[primary_key].lteq(finish)) if finish
- batch_relation = relation
-
- loop do
- if load
- records = batch_relation.records
- ids = records.map(&:id)
- yielded_relation = self.where(primary_key => ids)
- yielded_relation.load_records(records)
- else
- ids = batch_relation.pluck(primary_key)
- yielded_relation = self.where(primary_key => ids)
+# Remove this file when upgraded to rails 5.0.
+unless Gitlab.rails5?
+ module ActiveRecord
+ module Batches
+ # Differences from upstream: enumerator support was removed, and custom
+ # order/limit clauses are ignored without a warning.
+ def in_batches(of: 1000, start: nil, finish: nil, load: false)
+ raise "Must provide a block" unless block_given?
+
+ relation = self.reorder(batch_order).limit(of)
+ relation = relation.where(arel_table[primary_key].gteq(start)) if start
+ relation = relation.where(arel_table[primary_key].lteq(finish)) if finish
+ batch_relation = relation
+
+ loop do
+ if load
+ records = batch_relation.records
+ ids = records.map(&:id)
+ yielded_relation = self.where(primary_key => ids)
+ yielded_relation.load_records(records)
+ else
+ ids = batch_relation.pluck(primary_key)
+ yielded_relation = self.where(primary_key => ids)
+ end
+
+ break if ids.empty?
+
+ primary_key_offset = ids.last
+ raise ArgumentError.new("Primary key not included in the custom select clause") unless primary_key_offset
+
+ yield yielded_relation
+
+ break if ids.length < of
+
+ batch_relation = relation.where(arel_table[primary_key].gt(primary_key_offset))
end
-
- break if ids.empty?
-
- primary_key_offset = ids.last
- raise ArgumentError.new("Primary key not included in the custom select clause") unless primary_key_offset
-
- yield yielded_relation
-
- break if ids.length < of
-
- batch_relation = relation.where(arel_table[primary_key].gt(primary_key_offset))
end
end
end
diff --git a/config/initializers/ar5_pg_10_support.rb b/config/initializers/ar5_pg_10_support.rb
index a529c74a8ce..40548290ce8 100644
--- a/config/initializers/ar5_pg_10_support.rb
+++ b/config/initializers/ar5_pg_10_support.rb
@@ -1,6 +1,5 @@
-raise "Vendored ActiveRecord 5 code! Delete #{__FILE__}!" if ActiveRecord::VERSION::MAJOR >= 5
-
-if Gitlab::Database.postgresql?
+# Remove this file when upgraded to rails 5.0.
+if !Gitlab.rails5? && Gitlab::Database.postgresql?
require 'active_record/connection_adapters/postgresql_adapter'
require 'active_record/connection_adapters/postgresql/schema_statements'
diff --git a/config/initializers/devise.rb b/config/initializers/devise.rb
index f642e6d47e0..362b9cc9a88 100644
--- a/config/initializers/devise.rb
+++ b/config/initializers/devise.rb
@@ -219,49 +219,5 @@ Devise.setup do |config|
end
end
- Gitlab.config.omniauth.providers.each do |provider|
- provider_arguments = []
-
- %w[app_id app_secret].each do |argument|
- provider_arguments << provider[argument] if provider[argument]
- end
-
- case provider['args']
- when Array
- # An Array from the configuration will be expanded.
- provider_arguments.concat provider['args']
- when Hash
- # Add procs for handling SLO
- if provider['name'] == 'cas3'
- provider['args'][:on_single_sign_out] = lambda do |request|
- ticket = request.params[:session_index]
- raise "Service Ticket not found." unless Gitlab::Auth::OAuth::Session.valid?(:cas3, ticket)
-
- Gitlab::Auth::OAuth::Session.destroy(:cas3, ticket)
- true
- end
- end
-
- if provider['name'] == 'authentiq'
- provider['args'][:remote_sign_out_handler] = lambda do |request|
- authentiq_session = request.params['sid']
- if Gitlab::Auth::OAuth::Session.valid?(:authentiq, authentiq_session)
- Gitlab::Auth::OAuth::Session.destroy(:authentiq, authentiq_session)
- true
- else
- false
- end
- end
- end
-
- if provider['name'] == 'shibboleth'
- provider['args'][:fail_with_empty_uid] = true
- end
-
- # A Hash from the configuration will be passed as is.
- provider_arguments << provider['args'].symbolize_keys
- end
-
- config.omniauth provider['name'].to_sym, *provider_arguments
- end
+ Gitlab::OmniauthInitializer.new(config).execute(Gitlab.config.omniauth.providers)
end
diff --git a/config/routes/project.rb b/config/routes/project.rb
index c803737d40b..f50b9aded8d 100644
--- a/config/routes/project.rb
+++ b/config/routes/project.rb
@@ -52,7 +52,7 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do
end
end
- resource :pages, only: [:show, :destroy] do
+ resource :pages, only: [:show, :update, :destroy] do
resources :domains, except: :index, controller: 'pages_domains', constraints: { id: %r{[^/]+} } do
member do
post :verify
diff --git a/config/webpack.config.js b/config/webpack.config.js
index f5fb7de6176..42fe4b345e1 100644
--- a/config/webpack.config.js
+++ b/config/webpack.config.js
@@ -9,14 +9,12 @@ const StatsWriterPlugin = require('webpack-stats-plugin').StatsWriterPlugin;
const CopyWebpackPlugin = require('copy-webpack-plugin');
const CompressionPlugin = require('compression-webpack-plugin');
const NameAllModulesPlugin = require('name-all-modules-plugin');
-const BundleAnalyzerPlugin = require('webpack-bundle-analyzer')
- .BundleAnalyzerPlugin;
+const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
const WatchMissingNodeModulesPlugin = require('react-dev-utils/WatchMissingNodeModulesPlugin');
const ROOT_PATH = path.resolve(__dirname, '..');
const IS_PRODUCTION = process.env.NODE_ENV === 'production';
-const IS_DEV_SERVER =
- process.argv.join(' ').indexOf('webpack-dev-server') !== -1;
+const IS_DEV_SERVER = process.argv.join(' ').indexOf('webpack-dev-server') !== -1;
const DEV_SERVER_HOST = process.env.DEV_SERVER_HOST || 'localhost';
const DEV_SERVER_PORT = parseInt(process.env.DEV_SERVER_PORT, 10) || 3808;
const DEV_SERVER_LIVERELOAD = process.env.DEV_SERVER_LIVERELOAD !== 'false';
@@ -29,10 +27,10 @@ let watchAutoEntries = [];
function generateEntries() {
// generate automatic entry points
const autoEntries = {};
- const pageEntries = glob.sync('pages/**/index.js', {
- cwd: path.join(ROOT_PATH, 'app/assets/javascripts'),
- });
- watchAutoEntries = [path.join(ROOT_PATH, 'app/assets/javascripts/pages/')];
+ const pageEntries = glob.sync('pages/**/index.js', { cwd: path.join(ROOT_PATH, 'app/assets/javascripts') });
+ watchAutoEntries = [
+ path.join(ROOT_PATH, 'app/assets/javascripts/pages/'),
+ ];
function generateAutoEntries(path, prefix = '.') {
const chunkPath = path.replace(/\/index\.js$/, '');
@@ -40,16 +38,16 @@ function generateEntries() {
autoEntries[chunkName] = `${prefix}/${path}`;
}
- pageEntries.forEach(path => generateAutoEntries(path));
+ pageEntries.forEach(( path ) => generateAutoEntries(path));
autoEntriesCount = Object.keys(autoEntries).length;
const manualEntries = {
- common: './commons/index.js',
- main: './main.js',
- raven: './raven/index.js',
- webpack_runtime: './webpack.js',
- ide: './ide/index.js',
+ common: './commons/index.js',
+ main: './main.js',
+ raven: './raven/index.js',
+ webpack_runtime: './webpack.js',
+ ide: './ide/index.js',
};
return Object.assign(manualEntries, autoEntries);
@@ -63,12 +61,8 @@ const config = {
output: {
path: path.join(ROOT_PATH, 'public/assets/webpack'),
publicPath: '/assets/webpack/',
- filename: IS_PRODUCTION
- ? '[name].[chunkhash].bundle.js'
- : '[name].bundle.js',
- chunkFilename: IS_PRODUCTION
- ? '[name].[chunkhash].chunk.js'
- : '[name].chunk.js',
+ filename: IS_PRODUCTION ? '[name].[chunkhash].bundle.js' : '[name].bundle.js',
+ chunkFilename: IS_PRODUCTION ? '[name].[chunkhash].chunk.js' : '[name].chunk.js',
},
module: {
@@ -97,8 +91,8 @@ const config = {
{
loader: 'worker-loader',
options: {
- inline: true,
- },
+ inline: true
+ }
},
{ loader: 'babel-loader' },
],
@@ -109,7 +103,7 @@ const config = {
loader: 'file-loader',
options: {
name: '[name].[hash].[ext]',
- },
+ }
},
{
test: /katex.css$/,
@@ -119,8 +113,8 @@ const config = {
{
loader: 'css-loader',
options: {
- name: '[name].[hash].[ext]',
- },
+ name: '[name].[hash].[ext]'
+ }
},
],
},
@@ -130,18 +124,15 @@ const config = {
loader: 'file-loader',
options: {
name: '[name].[hash].[ext]',
- },
+ }
},
{
test: /monaco-editor\/\w+\/vs\/loader\.js$/,
use: [
{ loader: 'exports-loader', options: 'l.global' },
- {
- loader: 'imports-loader',
- options: 'l=>{},this=>l,AMDLoader=>this,module=>undefined',
- },
+ { loader: 'imports-loader', options: 'l=>{},this=>l,AMDLoader=>this,module=>undefined' },
],
- },
+ }
],
noParse: [/monaco-editor\/\w+\/vs\//],
@@ -159,10 +150,10 @@ const config = {
source: false,
chunks: false,
modules: false,
- assets: true,
+ assets: true
});
return JSON.stringify(stats, null, 2);
- },
+ }
}),
// prevent pikaday from including moment.js
@@ -179,7 +170,7 @@ const config = {
new NameAllModulesPlugin(),
// assign deterministic chunk ids
- new webpack.NamedChunksPlugin(chunk => {
+ new webpack.NamedChunksPlugin((chunk) => {
if (chunk.name) {
return chunk.name;
}
@@ -196,12 +187,9 @@ const config = {
const pagesBase = path.join(ROOT_PATH, 'app/assets/javascripts/pages');
if (m.resource.indexOf(pagesBase) === 0) {
- moduleNames.push(
- path
- .relative(pagesBase, m.resource)
- .replace(/\/index\.[a-z]+$/, '')
- .replace(/\//g, '__'),
- );
+ moduleNames.push(path.relative(pagesBase, m.resource)
+ .replace(/\/index\.[a-z]+$/, '')
+ .replace(/\//g, '__'));
} else {
moduleNames.push(path.relative(m.context, m.resource));
}
@@ -209,8 +197,7 @@ const config = {
chunk.forEachModule(collectModuleNames);
- const hash = crypto
- .createHash('sha256')
+ const hash = crypto.createHash('sha256')
.update(moduleNames.join('_'))
.digest('hex');
@@ -222,23 +209,13 @@ const config = {
names: ['main', 'common', 'webpack_runtime'],
}),
- // enable scope hoisting
- new webpack.optimize.ModuleConcatenationPlugin(),
-
// copy pre-compiled vendor libraries verbatim
new CopyWebpackPlugin([
{
- from: path.join(
- ROOT_PATH,
- `node_modules/monaco-editor/${IS_PRODUCTION ? 'min' : 'dev'}/vs`,
- ),
+ from: path.join(ROOT_PATH, `node_modules/monaco-editor/${IS_PRODUCTION ? 'min' : 'dev'}/vs`),
to: 'monaco-editor/vs',
transform: function(content, path) {
- if (
- /\.js$/.test(path) &&
- !/worker/i.test(path) &&
- !/typescript/i.test(path)
- ) {
+ if (/\.js$/.test(path) && !/worker/i.test(path) && !/typescript/i.test(path)) {
return (
'(function(){\n' +
'var define = this.define, require = this.require;\n' +
@@ -248,23 +225,23 @@ const config = {
);
}
return content;
- },
- },
+ }
+ }
]),
],
resolve: {
extensions: ['.js'],
alias: {
- '~': path.join(ROOT_PATH, 'app/assets/javascripts'),
- emojis: path.join(ROOT_PATH, 'fixtures/emojis'),
- empty_states: path.join(ROOT_PATH, 'app/views/shared/empty_states'),
- icons: path.join(ROOT_PATH, 'app/views/shared/icons'),
- images: path.join(ROOT_PATH, 'app/assets/images'),
- vendor: path.join(ROOT_PATH, 'vendor/assets/javascripts'),
- vue$: 'vue/dist/vue.esm.js',
- spec: path.join(ROOT_PATH, 'spec/javascripts'),
- },
+ '~': path.join(ROOT_PATH, 'app/assets/javascripts'),
+ 'emojis': path.join(ROOT_PATH, 'fixtures/emojis'),
+ 'empty_states': path.join(ROOT_PATH, 'app/views/shared/empty_states'),
+ 'icons': path.join(ROOT_PATH, 'app/views/shared/icons'),
+ 'images': path.join(ROOT_PATH, 'app/assets/images'),
+ 'vendor': path.join(ROOT_PATH, 'vendor/assets/javascripts'),
+ 'vue$': 'vue/dist/vue.esm.js',
+ 'spec': path.join(ROOT_PATH, 'spec/javascripts'),
+ }
},
// sqljs requires fs
@@ -279,14 +256,15 @@ if (IS_PRODUCTION) {
new webpack.NoEmitOnErrorsPlugin(),
new webpack.LoaderOptionsPlugin({
minimize: true,
- debug: false,
+ debug: false
}),
+ new webpack.optimize.ModuleConcatenationPlugin(),
new webpack.optimize.UglifyJsPlugin({
- sourceMap: true,
+ sourceMap: true
}),
new webpack.DefinePlugin({
- 'process.env': { NODE_ENV: JSON.stringify('production') },
- }),
+ 'process.env': { NODE_ENV: JSON.stringify('production') }
+ })
);
// compression can require a lot of compute time and is disabled in CI
@@ -304,7 +282,7 @@ if (IS_DEV_SERVER) {
headers: { 'Access-Control-Allow-Origin': '*' },
stats: 'errors-only',
hot: DEV_SERVER_LIVERELOAD,
- inline: DEV_SERVER_LIVERELOAD,
+ inline: DEV_SERVER_LIVERELOAD
};
config.plugins.push(
// watch node_modules for changes if we encounter a missing module compile error
@@ -320,14 +298,12 @@ if (IS_DEV_SERVER) {
];
// report our auto-generated bundle count
- console.log(
- `${autoEntriesCount} entries from '/pages' automatically added to webpack output.`,
- );
+ console.log(`${autoEntriesCount} entries from '/pages' automatically added to webpack output.`);
callback();
- });
+ })
},
- },
+ }
);
if (DEV_SERVER_LIVERELOAD) {
config.plugins.push(new webpack.HotModuleReplacementPlugin());
@@ -342,7 +318,7 @@ if (WEBPACK_REPORT) {
openAnalyzer: false,
reportFilename: path.join(ROOT_PATH, 'webpack-report/index.html'),
statsFilename: path.join(ROOT_PATH, 'webpack-report/stats.json'),
- }),
+ })
);
}
diff --git a/db/migrate/20161124141322_migrate_process_commit_worker_jobs.rb b/db/migrate/20161124141322_migrate_process_commit_worker_jobs.rb
index bcdae272209..a96ea7d9db4 100644
--- a/db/migrate/20161124141322_migrate_process_commit_worker_jobs.rb
+++ b/db/migrate/20161124141322_migrate_process_commit_worker_jobs.rb
@@ -12,7 +12,7 @@ class MigrateProcessCommitWorkerJobs < ActiveRecord::Migration
end
def repository_storage_path
- Gitlab.config.repositories.storages[repository_storage]['path']
+ Gitlab.config.repositories.storages[repository_storage].legacy_disk_path
end
def repository_path
diff --git a/db/migrate/20161220141214_remove_dot_git_from_group_names.rb b/db/migrate/20161220141214_remove_dot_git_from_group_names.rb
index 8fb1f9d5e73..bddc234db25 100644
--- a/db/migrate/20161220141214_remove_dot_git_from_group_names.rb
+++ b/db/migrate/20161220141214_remove_dot_git_from_group_names.rb
@@ -60,7 +60,7 @@ class RemoveDotGitFromGroupNames < ActiveRecord::Migration
def move_namespace(group_id, path_was, path)
repository_storage_paths = select_all("SELECT distinct(repository_storage) FROM projects WHERE namespace_id = #{group_id}").map do |row|
- Gitlab.config.repositories.storages[row['repository_storage']]['path']
+ Gitlab.config.repositories.storages[row['repository_storage']].legacy_disk_path
end.compact
# Move the namespace directory in all storages paths used by member projects
diff --git a/db/migrate/20161226122833_remove_dot_git_from_usernames.rb b/db/migrate/20161226122833_remove_dot_git_from_usernames.rb
index 61dcc8c54f5..7c28d934c29 100644
--- a/db/migrate/20161226122833_remove_dot_git_from_usernames.rb
+++ b/db/migrate/20161226122833_remove_dot_git_from_usernames.rb
@@ -71,7 +71,7 @@ class RemoveDotGitFromUsernames < ActiveRecord::Migration
route_exists = route_exists?(path)
Gitlab.config.repositories.storages.each_value do |storage|
- if route_exists || path_exists?(path, storage['path'])
+ if route_exists || path_exists?(path, storage.legacy_disk_path)
counter += 1
path = "#{base}#{counter}"
@@ -84,7 +84,7 @@ class RemoveDotGitFromUsernames < ActiveRecord::Migration
def move_namespace(namespace_id, path_was, path)
repository_storage_paths = select_all("SELECT distinct(repository_storage) FROM projects WHERE namespace_id = #{namespace_id}").map do |row|
- Gitlab.config.repositories.storages[row['repository_storage']]['path']
+ Gitlab.config.repositories.storages[row['repository_storage']].legacy_disk_path
end.compact
# Move the namespace directory in all storages paths used by member projects
diff --git a/db/migrate/20180102220145_add_pages_https_only_to_projects.rb b/db/migrate/20180102220145_add_pages_https_only_to_projects.rb
new file mode 100644
index 00000000000..ef6bc6896c0
--- /dev/null
+++ b/db/migrate/20180102220145_add_pages_https_only_to_projects.rb
@@ -0,0 +1,9 @@
+class AddPagesHttpsOnlyToProjects < ActiveRecord::Migration
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def change
+ add_column :projects, :pages_https_only, :boolean
+ end
+end
diff --git a/db/migrate/20180109183319_change_default_value_for_pages_https_only.rb b/db/migrate/20180109183319_change_default_value_for_pages_https_only.rb
new file mode 100644
index 00000000000..c242e1b0d24
--- /dev/null
+++ b/db/migrate/20180109183319_change_default_value_for_pages_https_only.rb
@@ -0,0 +1,13 @@
+class ChangeDefaultValueForPagesHttpsOnly < ActiveRecord::Migration
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def up
+ change_column_default :projects, :pages_https_only, true
+ end
+
+ def down
+ change_column_default :projects, :pages_https_only, nil
+ end
+end
diff --git a/db/migrate/20180223144945_add_allow_local_requests_from_hooks_and_services_to_application_settings.rb b/db/migrate/20180223144945_add_allow_local_requests_from_hooks_and_services_to_application_settings.rb
new file mode 100644
index 00000000000..c994a54698b
--- /dev/null
+++ b/db/migrate/20180223144945_add_allow_local_requests_from_hooks_and_services_to_application_settings.rb
@@ -0,0 +1,18 @@
+class AddAllowLocalRequestsFromHooksAndServicesToApplicationSettings < ActiveRecord::Migration
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ add_column_with_default(:application_settings, :allow_local_requests_from_hooks_and_services,
+ :boolean,
+ default: false,
+ allow_null: false)
+ end
+
+ def down
+ remove_column(:application_settings, :allow_local_requests_from_hooks_and_services)
+ end
+end
diff --git a/db/post_migrate/20180220150310_remove_empty_extern_uid_auth0_identities.rb b/db/post_migrate/20180220150310_remove_empty_extern_uid_auth0_identities.rb
new file mode 100644
index 00000000000..2d5a8617169
--- /dev/null
+++ b/db/post_migrate/20180220150310_remove_empty_extern_uid_auth0_identities.rb
@@ -0,0 +1,25 @@
+class RemoveEmptyExternUidAuth0Identities < ActiveRecord::Migration
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ class Identity < ActiveRecord::Base
+ self.table_name = 'identities'
+ include EachBatch
+ end
+
+ def up
+ broken_auth0_identities.each_batch do |identity|
+ identity.delete_all
+ end
+ end
+
+ def broken_auth0_identities
+ Identity.where(provider: 'auth0', extern_uid: [nil, ''])
+ end
+
+ def down
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index e441ca2a1f0..1be0570f85a 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -157,6 +157,7 @@ ActiveRecord::Schema.define(version: 20180320182229) do
t.boolean "authorized_keys_enabled", default: true, null: false
t.string "auto_devops_domain"
t.boolean "pages_domain_verification_enabled", default: true, null: false
+ t.boolean "allow_local_requests_from_hooks_and_services", default: false, null: false
end
create_table "audit_events", force: :cascade do |t|
@@ -1512,6 +1513,7 @@ ActiveRecord::Schema.define(version: 20180320182229) do
t.boolean "merge_requests_ff_only_enabled", default: false
t.boolean "merge_requests_rebase_enabled", default: false, null: false
t.integer "jobs_cache_index"
+ t.boolean "pages_https_only", default: true
end
add_index "projects", ["ci_id"], name: "index_projects_on_ci_id", using: :btree
diff --git a/doc/ci/README.md b/doc/ci/README.md
index 532ae52a184..6aa0e5885db 100644
--- a/doc/ci/README.md
+++ b/doc/ci/README.md
@@ -65,7 +65,8 @@ learn how to leverage its potential even more.
environments and use them for different purposes like testing, building and
deploying
- [Job artifacts](../user/project/pipelines/job_artifacts.md)
-- [Git submodules](git_submodules.md): How to run your CI jobs when Git
+- [Caching dependencies](caching/index.md)
+- [Git submodules](git_submodules.md) - How to run your CI jobs when Git
submodules are involved
- [Use SSH keys in your build environment](ssh_keys/README.md)
- [Trigger pipelines through the GitLab API](triggers/README.md)
diff --git a/doc/ci/caching/img/clear_runners_cache.png b/doc/ci/caching/img/clear_runners_cache.png
new file mode 100644
index 00000000000..e5db4a47b3e
--- /dev/null
+++ b/doc/ci/caching/img/clear_runners_cache.png
Binary files differ
diff --git a/doc/ci/caching/index.md b/doc/ci/caching/index.md
new file mode 100644
index 00000000000..c159198d16b
--- /dev/null
+++ b/doc/ci/caching/index.md
@@ -0,0 +1,518 @@
+# Cache dependencies in GitLab CI/CD
+
+GitLab CI/CD provides a caching mechanism that can be used to save time
+when your jobs are running.
+
+Caching is about speeding the time a job is executed by reusing the same
+content of a previous job. It can be particularly useful when your are
+developing software that depends on other libraries which are fetched via the
+internet during build time.
+
+If caching is enabled, it's shared between pipelines and jobs by default,
+starting from GitLab 9.0.
+
+Make sure you read the [`cache` reference](../yaml/README.md#cache) to learn
+how it is defined in `.gitlab-ci.yml`.
+
+## Good caching practices
+
+We have the cache from the perspective of the developers (who consume a cache
+within the job) and the cache from the perspective of the Runner. Depending on
+which type of Runner you are using, cache can act differently.
+
+From the perspective of the developer, to ensure maximum availability of the
+cache, when declaring `cache` in your jobs, use one or a mix of the following:
+
+- [Tag your Runners](../runners/README.md#using-tags) and use the tag on jobs
+ that share their cache.
+- [Use sticky Runners](../runners/README.md#locking-a-specific-runner-from-being-enabled-for-other-projects)
+ that will be only available to a particular project.
+- [Use a `key`](../yaml/README.md#cache-key) that fits your workflow (e.g.,
+ different caches on each branch). For that, you can take advantage of the
+ [CI/CD predefined variables](../variables/README.md#predefined-variables-environment-variables).
+
+TIP: **Tip:**
+Using the same Runner for your pipeline, is the most simple and efficient way to
+cache files in one stage or pipeline, and pass this cache to subsequent stages
+or pipelines in a guaranteed manner.
+
+From the perspective of the Runner, in order for cache to work effectively, one
+of the following must be true:
+
+- Use a single Runner for all your jobs
+- Use multiple Runners (in autoscale mode or not) that use
+ [distributed caching](https://docs.gitlab.com/runner/configuration/autoscale.html#distributed-runners-caching),
+ where the cache is stored in S3 buckets (like shared Runners on GitLab.com)
+- Use multiple Runners (not in autoscale mode) of the same architecture that
+ share a common network-mounted directory (using NFS or something similar)
+ where the cache will be stored
+
+TIP: **Tip:**
+Read about the [availability of the cache](#availability-of-the-cache)
+to learn more about the internals and get a better idea how cache works.
+
+### Sharing caches across the same branch
+
+Define a cache with the `key: ${CI_COMMIT_REF_SLUG}` so that jobs of each
+branch always use the same cache:
+
+```yaml
+cache:
+ key: ${CI_COMMIT_REF_SLUG}
+```
+
+While this feels like it might be safe from accidentally overwriting the cache,
+it means merge requests get slow first pipelines, which might be a bad
+developer experience. The next time a new commit is pushed to the branch, the
+cache will be re-used.
+
+To enable per-job and per-branch caching:
+
+```yaml
+cache:
+ key: "$CI_JOB_NAME-$CI_COMMIT_REF_SLUG"
+```
+
+To enable per-branch and per-stage caching:
+
+```yaml
+cache:
+ key: "$CI_JOB_STAGE-$CI_COMMIT_REF_SLUG"
+```
+
+### Sharing caches across different branches
+
+If the files you are caching need to be shared across all branches and all jobs,
+you can use the same key for all of them:
+
+```yaml
+cache:
+ key: one-key-to-rull-them-all
+```
+
+To share the same cache between branches, but separate them by job:
+
+```yaml
+cache:
+ key: ${CI_JOB_NAME}
+```
+
+### Disabling cache on specific jobs
+
+If you have defined the cache globally, it means that each job will use the
+same definition. You can override this behavior per-job, and if you want to
+disable it completely, use an empty hash:
+
+```yaml
+job:
+ cache: {}
+```
+
+For more fine tuning, read also about the
+[`cache: policy`](../yaml/README.md#cache-policy).
+
+## Common use cases
+
+The most common use case of cache is to preserve contents between subsequent
+runs of jobs for things like dependencies and commonly used libraries
+(Nodejs packages, PHP packages, rubygems, python libraries, etc.),
+so they don't have to be re-fetched from the public internet.
+
+NOTE: **Note:**
+For more examples, check the [GitLab CI Yml](https://gitlab.com/gitlab-org/gitlab-ci-yml)
+project.
+
+### Caching Nodejs dependencies
+
+Assuming your project is using [npm](https://www.npmjs.com/) or
+[Yarn](https://yarnpkg.com/en/) to install the Nodejs dependencies, the
+following example defines `cache` globally so that all jobs inherit it.
+Nodejs modules are installed in `node_modules/` and are cached per-branch:
+
+```yaml
+#
+# https://gitlab.com/gitlab-org/gitlab-ci-yml/blob/master/Nodejs.gitlab-ci.yml
+#
+image: node:latest
+
+# Cache modules in between jobs
+cache:
+ key: ${CI_COMMIT_REF_SLUG}
+ paths:
+ - node_modules/
+
+before_script:
+ - npm install
+
+test_async:
+ script:
+ - node ./specs/start.js ./specs/async.spec.js
+```
+
+### Caching PHP dependencies
+
+Assuming your project is using [Composer](https://getcomposer.org/) to install
+the PHP dependencies, the following example defines `cache` globally so that
+all jobs inherit it. PHP libraries modules are installed in `vendor/` and
+are cached per-branch:
+
+```yaml
+#
+# https://gitlab.com/gitlab-org/gitlab-ci-yml/blob/master/PHP.gitlab-ci.yml
+#
+image: php:7.2
+
+# Cache libraries in between jobs
+cache:
+ key: ${CI_COMMIT_REF_SLUG}
+ paths:
+ - vendor/
+
+before_script:
+# Install and run Composer
+- curl --show-error --silent https://getcomposer.org/installer | php
+- php composer.phar install
+
+test:
+ script:
+ - vendor/bin/phpunit --configuration phpunit.xml --coverage-text --colors=never
+```
+
+### Caching Python dependencies
+
+Assuming your project is using [pip](https://pip.pypa.io/en/stable/) to install
+the python dependencies, the following example defines `cache` globally so that
+all jobs inherit it. Python libraries are installed in a virtualenv under `venv/`,
+pip's cache is defined under `.cache/pip/` and both are cached per-branch:
+
+```yaml
+#
+# https://gitlab.com/gitlab-org/gitlab-ci-yml/blob/master/Python.gitlab-ci.yml
+#
+image: python:latest
+
+# Change pip's cache directory to be inside the project directory since we can
+# only cache local items.
+variables:
+ PIP_CACHE_DIR: "$CI_PROJECT_DIR/.cache"
+
+# Pip's cache doesn't store the python packages
+# https://pip.pypa.io/en/stable/reference/pip_install/#caching
+#
+# If you want to also cache the installed packages, you have to install
+# them in a virtualenv and cache it as well.
+cache:
+ paths:
+ - .cache/
+ - venv/
+
+before_script:
+ - python -V # Print out python version for debugging
+ - pip install virtualenv
+ - virtualenv venv
+ - source venv/bin/activate
+
+test:
+ script:
+ - python setup.py test
+ - pip install flake8
+ - flake8 .
+```
+
+### Caching Ruby dependencies
+
+Assuming your project is using [Bundler](https://bundler.io) to install the
+gem dependencies, the following example defines `cache` globally so that all
+jobs inherit it. Gems are installed in `vendor/ruby/` and are cached per-branch:
+
+```yaml
+#
+# https://gitlab.com/gitlab-org/gitlab-ci-yml/blob/master/Ruby.gitlab-ci.yml
+#
+image: ruby:2.5
+
+# Cache gems in between builds
+cache:
+ key: ${CI_COMMIT_REF_SLUG}
+ paths:
+ - vendor/ruby
+
+before_script:
+ - ruby -v # Print out ruby version for debugging
+ - gem install bundler --no-ri --no-rdoc # Bundler is not installed with the image
+ - bundle install -j $(nproc) --path vendor # Install dependencies into ./vendor/ruby
+
+rspec:
+ script:
+ - rspec spec
+```
+
+## Availability of the cache
+
+Caching is an optimization, but isn't guaranteed to always work, so you need to
+be prepared to regenerate any cached files in each job that needs them.
+
+Assuming you have properly [defined `cache` in `.gitlab-ci.yml`](../yaml/README.md#cache)
+according to your workflow, the availability of the cache ultimately depends on
+how the Runner has been configured (the executor type and whether different
+Runners are used for passing the cache between jobs).
+
+### Where the caches are stored
+
+Since the Runner is the one responsible for storing the cache, it's essential
+to know **where** it's stored. All the cache paths defined under a job in
+`.gitlab-ci.yml` are archived in a single `cache.zip` file and stored in the
+Runner's configured cache location. By default, they are stored locally in the
+machine where the Runner is installed and depends on the type of the executor.
+
+| GitLab Runner executor | Default path of the cache |
+| ---------------------- | ------------------------- |
+| [Shell](https://docs.gitlab.com/runner/executors/shell.html) | Locally, stored under the `gitlab-runner` user's home directory: `/home/gitlab-runner/cache/<user>/<project>/<cache-key>/cache.zip`. |
+| [Docker](https://docs.gitlab.com/runner/executors/docker.html) | Locally, stored under [Docker volumes](https://docs.gitlab.com/runner/executors/docker.html#the-builds-and-cache-storage): `/var/lib/docker/volumes/<volume-id>/_data/<user>/<project>/<cache-key>/cache.zip`. |
+| [Docker machine](https://docs.gitlab.com/runner/executors/docker_machine.html) (autoscale Runners) | Behaves the same as the Docker executor. |
+
+### How archiving and extracting works
+
+In the most simple scenario, consider that you use only one machine where the
+Runner is installed, and all jobs of your project run on the same host.
+
+Let's see the following example of two jobs that belong to two consecutive
+stages:
+
+```yaml
+stages:
+- build
+- test
+
+before_script:
+- echo "Hello"
+
+job A:
+ stage: build
+ script:
+ - mkdir vendor/
+ - echo "build" > vendor/hello.txt
+ cache:
+ key: build-cache
+ paths:
+ - vendor/
+ after_script:
+ - echo "World"
+
+job B:
+ stage: test
+ script:
+ - cat vendor/hello.txt
+ cache:
+ key: build-cache
+```
+
+Here's what happens behind the scenes:
+
+1. Pipeline starts
+1. `job A` runs
+1. `before_script` is executed
+1. `script` is executed
+1. `after_script` is executed
+1. `cache` runs and the `vendor/` directory is zipped into `cache.zip`.
+ This file is then saved in the directory based on the
+ [Runner's setting](#where-the-caches-are-stored) and the `cache: key`.
+1. `job B` runs
+1. The cache is extracted (if found)
+1. `before_script` is executed
+1. `script` is executed
+1. Pipeline finishes
+
+By using a single Runner on a single machine, you'll not have the issue where
+`job B` might execute on a Runner different from `job A`, thus guaranteeing the
+cache between stages. That will only work if the build goes from stage `build`
+to `test` in the same Runner/machine, otherwise, you [might not have the cache
+available](#cache-mismatch).
+
+During the caching process, there's also a couple of things to consider:
+
+- If some other job, with another cache configuration had saved its
+ cache in the same zip file, it is overwritten. If the S3 based shared cache is
+ used, the file is additionally uploaded to S3 to an object based on the cache
+ key. So, two jobs with different paths, but the same cache key, will overwrite
+ their cache.
+- When extracting the cache from `cache.zip`, everything in the zip file is
+ extracted in the job's working directory (usually the repository which is
+ pulled down), and the Runner doesn't mind if the archive of `job A` overwrites
+ things in the archive of `job B`.
+
+The reason why it works this way is because the cache created for one Runner
+often will not be valid when used by a different one which can run on a
+**different architecture** (e.g., when the cache includes binary files). And
+since the different steps might be executed by Runners running on different
+machines, it is a safe default.
+
+### Cache mismatch
+
+In the following table, you can see some reasons where you might hit a cache
+mismatch and a few ideas how to fix it.
+
+| Reason of a cache mismatch | How to fix it |
+| -------------------------- | ------------- |
+| You use multiple standalone Runners (not in autoscale mode) attached to one project without a shared cache | Use only one Runner for your project or use multiple Runners with distributed cache enabled |
+| You use Runners in autoscale mode without a distributed cache enabled | Configure the autoscale Runner to use a distributed cache |
+| The machine the Runner is installed on is low on disk space or, if you've set up distributed cache, the S3 bucket where the cache is stored doesn't have enough space | Make sure you clear some space to allow new caches to be stored. Currently, there's no automatic way to do this. |
+| You use the same `key` for jobs where they cache different paths. | Use different cache keys to that the cache archive is stored to a different location and doesn't overwrite wrong caches. |
+
+Let's explore some examples.
+
+---
+
+Let's assume you have only one Runner assigned to your project, so the cache
+will be stored in the Runner's machine by default. If two jobs, A and B,
+have the same cache key, but they cache different paths, cache B would overwrite
+cache A, even if their `paths` don't match:
+
+We want `job A` and `job B` to re-use their
+cache when the pipeline is run for a second time.
+
+```yaml
+stages:
+- build
+- test
+
+job A:
+ stage: build
+ script: make build
+ cache:
+ key: same-key
+ paths:
+ - public/
+
+job B:
+ stage: test
+ script: make test
+ cache:
+ key: same-key
+ paths:
+ - vendor/
+```
+
+1. `job A` runs
+1. `public/` is cached as cache.zip
+1. `job B` runs
+1. The previous cache, if any, is unzipped
+1. `vendor/` is cached as cache.zip and overwrites the previous one
+1. The next time `job A` runs it will use the cache of `job B` which is different
+ and thus will be ineffective
+
+To fix that, use different `keys` for each job.
+
+---
+
+In another case, let's assume you have more than one Runners assigned to your
+project, but the distributed cache is not enabled. We want the second time the
+pipeline is run, `job A` and `job B` to re-use their cache (which in this case
+will be different):
+
+```yaml
+stages:
+- build
+- test
+
+job A:
+ stage: build
+ script: build
+ cache:
+ key: keyA
+ paths:
+ - vendor/
+
+job B:
+ stage: test
+ script: test
+ cache:
+ key: keyB
+ paths:
+ - vendor/
+```
+
+In that case, even if the `key` is different (no fear of overwriting), you
+might experience the cached files to "get cleaned" before each stage if the
+jobs run on different Runners in the subsequent pipelines.
+
+## Clearing the cache
+
+GitLab Runners use [cache](../yaml/README.md#cache) to speed up the execution
+of your jobs by reusing existing data. This however, can sometimes lead to an
+inconsistent behavior.
+
+To start with a fresh copy of the cache, there are two ways to do that.
+
+### Clearing the cache by changing `cache:key`
+
+All you have to do is set a new `cache: key` in your `.gitlab-ci.yml`. In the
+next run of the pipeline, the cache will be stored in a different location.
+
+### Clearing the cache manually
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/issues/41249) in GitLab 10.4.
+
+If you want to avoid editing `.gitlab-ci.yml`, you can easily clear the cache
+via GitLab's UI:
+
+1. Navigate to your project's **CI/CD > Pipelines** page
+1. Click on the **Clear Runner caches** button to clean up the cache
+
+ ![Clear Runners cache](img/clear_runners_cache.png)
+
+1. On the next push, your CI/CD job will use a new cache
+
+Behind the scenes, this works by increasing a counter in the database, and the
+value of that counter is used to create the key for the cache by appending an
+integer to it: `-1`, `-2`, etc. After a push, a new key is generated and the
+old cache is not valid anymore.
+
+## Cache vs artifacts
+
+NOTE: **Note:**
+Be careful if you use cache and artifacts to store the same path in your jobs
+as **caches are restored before artifacts** and the content would be overwritten.
+
+Don't mix the caching with passing artifacts between stages. Caching is not
+designed to pass artifacts between stages. Cache is for runtime dependencies
+needed to compile the project:
+
+- `cache` - **Use for temporary storage for project dependencies.** Not useful
+ for keeping intermediate build results, like `jar` or `apk` files.
+ Cache was designed to be used to speed up invocations of subsequent runs of a
+ given job, by keeping things like dependencies (e.g., npm packages, Go vendor
+ packages, etc.) so they don't have to be re-fetched from the public internet.
+ While the cache can be abused to pass intermediate build results between stages,
+ there may be cases where artifacts are a better fit.
+- `artifacts` - **Use for stage results that will be passed between stages.**
+ Artifacts were designed to upload some compiled/generated bits of the build,
+ and they can be fetched by any number of concurrent Runners. They are
+ guaranteed to be available and are there to pass data between jobs. They are
+ also exposed to be downloaded from the UI.
+
+It's sometimes confusing because the name artifact sounds like something that
+is only useful outside of the job, like for downloading a final image. But
+artifacts are also available in between stages within a pipeline. So if you
+build your application by downloading all the required modules, you might want
+to declare them as artifacts so that each subsequent stage can depend on them
+being there. There are some optimizations like declaring an
+[expiry time](../yaml/README.md#artifacts-expire_in) so you don't keep artifacts
+around too long, and using [dependencies](../yaml/README.md#dependencies) to
+control exactly where artifacts are passed around.
+
+So, to sum up:
+- Caches are disabled if not defined globally or per job (using `cache:`)
+- Caches are available for all jobs in your `.gitlab-ci.yml` if enabled globally
+- Caches can be used by subsequent pipelines of that very same job (a script in
+ a stage) in which the cache was created (if not defined globally).
+- Caches are stored where the Runner is installed **and** uploaded to S3 if
+ [distributed cache is enabled](https://docs.gitlab.com/runner/configuration/autoscale.html#distributed-runners-caching)
+- Caches defined per job are only used either a) for the next pipeline of that job,
+ or b) if that same cache is also defined in a subsequent job of the same pipeline
+- Artifacts are disabled if not defined per job (using `artifacts:`)
+- Artifacts can only be enabled per job, not globally
+- Artifacts are created during a pipeline and can be used by the subsequent
+ jobs of that currently active pipeline
+- Artifacts are always uploaded to GitLab (known as coordinator)
+- Artifacts can have an expiration value for controlling disk usage (30 days by default)
diff --git a/doc/ci/runners/README.md b/doc/ci/runners/README.md
index 9f2538b9c9f..7a7b50b294d 100644
--- a/doc/ci/runners/README.md
+++ b/doc/ci/runners/README.md
@@ -146,24 +146,7 @@ To protect/unprotect Runners:
## Manually clearing the Runners cache
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/issues/41249) in GitLab 10.4.
-
-GitLab Runners use [cache](../yaml/README.md#cache) to speed up the execution
-of your jobs by reusing existing data. This however, can sometimes lead to an
-inconsistent behavior.
-
-To start with a fresh copy of the cache, you can easily do it via GitLab's UI:
-
-1. Navigate to your project's **CI/CD > Pipelines** page.
-1. Click on the **Clear Runner caches** to clean up the cache.
-1. On the next push, your CI/CD job will use a new cache.
-
-That way, you don't have to change the [cache key](../yaml/README.md#cache-key)
-in your `.gitlab-ci.yml`.
-
-Behind the scenes, this works by increasing a counter in the database, and the
-value of that counter is used to create the key for the cache. After a push, a
-new key is generated and the old cache is not valid anymore.
+Read [clearing the cache](../caching/index.md#clearing-the-cache).
## How shared Runners pick jobs
@@ -227,15 +210,16 @@ that it may encounter on the projects it's shared over. This would be
problematic for large amounts of projects, if it wasn't for tags.
By tagging a Runner for the types of jobs it can handle, you can make sure
-shared Runners will only run the jobs they are equipped to run.
+shared Runners will [only run the jobs they are equipped to run](../yaml/README.md#tags).
For instance, at GitLab we have Runners tagged with "rails" if they contain
the appropriate dependencies to run Rails test suites.
### Preventing Runners with tags from picking jobs without tags
-You can configure a Runner to prevent it from picking jobs with tags when
-the Runner does not have tags assigned. This setting can be enabled the first
+You can configure a Runner to prevent it from picking
+[jobs with tags](../yaml/README.md#tags) when the Runner does not have tags
+assigned. This setting can be enabled the first
time you [register a Runner][register] and can be changed afterwards under
each Runner's settings.
diff --git a/doc/ci/yaml/README.md b/doc/ci/yaml/README.md
index accf6340398..7184f3367be 100644
--- a/doc/ci/yaml/README.md
+++ b/doc/ci/yaml/README.md
@@ -674,6 +674,10 @@ as Review Apps. You can see a simple example using Review Apps at
by default.
- From GitLab 9.2, caches are restored before [artifacts](#artifacts).
+TIP: **Learn more:**
+Read how caching works and find out some good practices in the
+[caching dependencies documentation](../caching/index.md).
+
`cache` is used to specify a list of files and directories which should be
cached between jobs. You can only use paths that are within the project
workspace.
@@ -681,35 +685,20 @@ workspace.
If `cache` is defined outside the scope of jobs, it means it is set
globally and all jobs will use that definition.
-Cache all files in `binaries` and `.config`:
-
-```yaml
-rspec:
- script: test
- cache:
- paths:
- - binaries/
- - .config
-```
-
-Cache all Git untracked files:
+### `cache:paths`
-```yaml
-rspec:
- script: test
- cache:
- untracked: true
-```
+Use the `paths` directive to choose which files or directories will be cached.
+Wildcards can be used as well.
-Cache all Git untracked files and files in `binaries`:
+Cache all files in `binaries` that end in `.apk` and the `.config` file:
```yaml
rspec:
script: test
cache:
- untracked: true
paths:
- - binaries/
+ - binaries/*.apk
+ - .config
```
Locally defined cache overrides globally defined options. The following `rspec`
@@ -723,33 +712,26 @@ cache:
rspec:
script: test
cache:
- key: rspec
paths:
- binaries/
```
-Note that since cache is shared between jobs, if you're using different
-paths for different jobs, you should also set a different **cache:key**
-otherwise cache content can be overwritten.
-
-NOTE: **Note:**
-The cache is provided on a best-effort basis, so don't expect that the cache
-will be always present.
-
### `cache:key`
> Introduced in GitLab Runner v1.0.0.
-The `key` directive allows you to define the affinity of caching
-between jobs, allowing to have a single cache for all jobs,
-cache per-job, cache per-branch or any other way that fits your needs.
+Since the cache is shared between jobs, if you're using different
+paths for different jobs, you should also set a different `cache:key`
+otherwise cache content can be overwritten.
-This way, you can fine tune caching, allowing you to cache data between
-different jobs or even different branches.
+The `key` directive allows you to define the affinity of caching between jobs,
+allowing to have a single cache for all jobs, cache per-job, cache per-branch
+or any other way that fits your workflow. This way, you can fine tune caching,
+allowing you to cache data between different jobs or even different branches.
The `cache:key` variable can use any of the
[predefined variables](../variables/README.md), and the default key, if not set,
-is set as `$CI_JOB_NAME-$CI_COMMIT_REF_NAME` which translates as "per-job and
+is `$CI_JOB_NAME-$CI_COMMIT_REF_NAME` which translates as "per-job and
per-branch". It is the default across the project, therefore everything is
shared between pipelines and jobs running on the same branch by default.
@@ -757,56 +739,56 @@ NOTE: **Note:**
The `cache:key` variable cannot contain the `/` character, or the equivalent
URI-encoded `%2F`; a value made only of dots (`.`, `%2E`) is also forbidden.
-**Example configurations**
-
-To enable per-job caching:
-
-```yaml
-cache:
- key: "$CI_JOB_NAME"
- untracked: true
-```
-
-To enable per-branch caching:
+For example, to enable per-branch caching:
```yaml
cache:
key: "$CI_COMMIT_REF_SLUG"
- untracked: true
+ paths:
+ - binaries/
```
-To enable per-job and per-branch caching:
+If you use **Windows Batch** to run your shell scripts you need to replace
+`$` with `%`:
```yaml
cache:
- key: "$CI_JOB_NAME-$CI_COMMIT_REF_SLUG"
- untracked: true
+ key: "%CI_JOB_STAGE%-%CI_COMMIT_REF_SLUG%"
+ paths:
+ - binaries/
```
-To enable per-branch and per-stage caching:
+If you use **Windows PowerShell** to run your shell scripts you need to replace
+`$` with `$env:`:
```yaml
cache:
- key: "$CI_JOB_STAGE-$CI_COMMIT_REF_SLUG"
- untracked: true
+ key: "$env:CI_JOB_STAGE-$env:CI_COMMIT_REF_SLUG"
+ paths:
+ - binaries/
```
-If you use **Windows Batch** to run your shell scripts you need to replace
-`$` with `%`:
+### `cache:untracked`
+
+Set `untracked: true` to cache all files that are untracked in your Git
+repository:
```yaml
-cache:
- key: "%CI_JOB_STAGE%-%CI_COMMIT_REF_SLUG%"
- untracked: true
+rspec:
+ script: test
+ cache:
+ untracked: true
```
-If you use **Windows PowerShell** to run your shell scripts you need to replace
-`$` with `$env:`:
+Cache all Git untracked files and files in `binaries`:
```yaml
-cache:
- key: "$env:CI_JOB_STAGE-$env:CI_COMMIT_REF_SLUG"
- untracked: true
+rspec:
+ script: test
+ cache:
+ untracked: true
+ paths:
+ - binaries/
```
### `cache:policy`
@@ -1150,7 +1132,7 @@ job1:
## `retry`
-> [Introduced][ce-3442] in GitLab 9.5.
+> [Introduced][ce-12909] in GitLab 9.5.
`retry` allows you to configure how many times a job is going to be retried in
case of a failure.
@@ -1565,5 +1547,5 @@ CI with various languages.
[variables]: ../variables/README.md
[ce-7983]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/7983
[ce-7447]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/7447
-[ce-3442]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/3442
+[ce-12909]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/12909
[schedules]: ../../user/project/pipelines/schedules.md
diff --git a/doc/development/emails.md b/doc/development/emails.md
index 677029b1295..4dbf064fd75 100644
--- a/doc/development/emails.md
+++ b/doc/development/emails.md
@@ -60,16 +60,10 @@ See the [Rails guides] for more info.
As mentioned, the part after `+` is ignored, and this will end up in the mailbox for `gitlab-incoming@gmail.com`.
-1. Uncomment the `mail_room` line in your `Procfile`:
-
- ```yaml
- mail_room: bundle exec mail_room -q -c config/mail_room.yml
- ```
-
-1. Restart GitLab:
+1. Run this command in the GitLab root directory to launch `mail_room`:
```sh
- bundle exec foreman start
+ bundle exec mail_room -q -c config/mail_room.yml
```
1. Verify that everything is configured correctly:
diff --git a/doc/development/i18n/proofreader.md b/doc/development/i18n/proofreader.md
index 960eabd5538..cf62314bc29 100644
--- a/doc/development/i18n/proofreader.md
+++ b/doc/development/i18n/proofreader.md
@@ -10,6 +10,7 @@ are very appreciative of the work done by translators and proofreaders!
- Huang Tao - [GitLab](https://gitlab.com/htve), [Crowdin](https://crowdin.com/profile/htve)
- Chinese Traditional
- Huang Tao - [GitLab](https://gitlab.com/htve), [Crowdin](https://crowdin.com/profile/htve)
+ - Weizhe Ding - [GitLab](https://gitlab.com/d.weizhe), [Crowdin](https://crowdin.com/profile/d.weizhe)
- Chinese Traditional, Hong Kong
- Huang Tao - [GitLab](https://gitlab.com/htve), [Crowdin](https://crowdin.com/profile/htve)
- Dutch
diff --git a/doc/development/migration_style_guide.md b/doc/development/migration_style_guide.md
index 1e060ffd941..a211effdfa7 100644
--- a/doc/development/migration_style_guide.md
+++ b/doc/development/migration_style_guide.md
@@ -23,10 +23,6 @@ When downtime is necessary the migration has to be approved by:
An up-to-date list of people holding these titles can be found at
<https://about.gitlab.com/team/>.
-The document ["What Requires Downtime?"](what_requires_downtime.md) specifies
-various database operations, whether they require downtime and how to
-work around that whenever possible.
-
When writing your migrations, also consider that databases might have stale data
or inconsistencies and guard for that. Try to make as few assumptions as
possible about the state of the database.
@@ -41,6 +37,18 @@ Migrations that make changes to the database schema (e.g. adding a column) can
only be added in the monthly release, patch releases may only contain data
migrations _unless_ schema changes are absolutely required to solve a problem.
+## What Requires Downtime?
+
+The document ["What Requires Downtime?"](what_requires_downtime.md) specifies
+various database operations, such as
+
+- [adding, dropping, and renaming columns](what_requires_downtime.md#adding-columns)
+- [changing column constraints and types](what_requires_downtime.md#changing-column-constraints)
+- [adding and dropping indexes, tables, and foreign keys](what_requires_downtime.md#adding-indexes)
+
+and whether they require downtime and how to work around that whenever possible.
+
+
## Downtime Tagging
Every migration must specify if it requires downtime or not, and if it should
diff --git a/doc/integration/auth0.md b/doc/integration/auth0.md
index c39d7ab57c6..a75836a915a 100644
--- a/doc/integration/auth0.md
+++ b/doc/integration/auth0.md
@@ -56,7 +56,8 @@ for initial settings.
"name" => "auth0",
"args" => { client_id: 'YOUR_AUTH0_CLIENT_ID',
client_secret: 'YOUR_AUTH0_CLIENT_SECRET',
- namespace: 'YOUR_AUTH0_DOMAIN'
+ domain: 'YOUR_AUTH0_DOMAIN',
+ scope: 'openid profile email'
}
}
]
@@ -69,8 +70,8 @@ for initial settings.
args: {
client_id: 'YOUR_AUTH0_CLIENT_ID',
client_secret: 'YOUR_AUTH0_CLIENT_SECRET',
- namespace: 'YOUR_AUTH0_DOMAIN'
- }
+ domain: 'YOUR_AUTH0_DOMAIN',
+ scope: 'openid profile email' }
}
```
diff --git a/doc/user/project/pipelines/schedules.md b/doc/user/project/pipelines/schedules.md
index 34809a2826f..a13b1b4561c 100644
--- a/doc/user/project/pipelines/schedules.md
+++ b/doc/user/project/pipelines/schedules.md
@@ -12,7 +12,7 @@ month on the 22nd for a certain branch.
In order to schedule a pipeline:
-1. Navigate to your project's **Pipelines âž” Schedules** and click the
+1. Navigate to your project's **CI / CD âž” Schedules** and click the
**New Schedule** button.
1. Fill in the form
1. Hit **Save pipeline schedule** for the changes to take effect.
diff --git a/lib/backup/repository.rb b/lib/backup/repository.rb
index 6715159a1aa..88a7f2a4235 100644
--- a/lib/backup/repository.rb
+++ b/lib/backup/repository.rb
@@ -65,7 +65,7 @@ module Backup
def restore
Gitlab.config.repositories.storages.each do |name, repository_storage|
- path = repository_storage['path']
+ path = repository_storage.legacy_disk_path
next unless File.exist?(path)
# Move repos dir to 'repositories.old' dir
@@ -200,7 +200,7 @@ module Backup
end
def repository_storage_paths_args
- Gitlab.config.repositories.storages.values.map { |rs| rs['path'] }
+ Gitlab.config.repositories.storages.values.map { |rs| rs.legacy_disk_path }
end
def progress
diff --git a/lib/banzai/filter/issuable_state_filter.rb b/lib/banzai/filter/issuable_state_filter.rb
index 77299abe324..8f541dcfdb2 100644
--- a/lib/banzai/filter/issuable_state_filter.rb
+++ b/lib/banzai/filter/issuable_state_filter.rb
@@ -17,7 +17,7 @@ module Banzai
issuables.each do |node, issuable|
next if !can_read_cross_project? && issuable.project != project
- if VISIBLE_STATES.include?(issuable.state) && node.inner_html == issuable.reference_link_text(project)
+ if VISIBLE_STATES.include?(issuable.state) && issuable_reference?(node.inner_html, issuable)
node.content += " (#{issuable.state})"
end
end
@@ -27,6 +27,10 @@ module Banzai
private
+ def issuable_reference?(text, issuable)
+ text == issuable.reference_link_text(project || group)
+ end
+
def can_read_cross_project?
Ability.allowed?(current_user, :read_cross_project)
end
@@ -38,6 +42,10 @@ module Banzai
def project
context[:project]
end
+
+ def group
+ context[:group]
+ end
end
end
end
diff --git a/lib/gitlab/database/rename_reserved_paths_migration/v1/migration_classes.rb b/lib/gitlab/database/rename_reserved_paths_migration/v1/migration_classes.rb
index fd4a8832ec2..62d4d0a92a6 100644
--- a/lib/gitlab/database/rename_reserved_paths_migration/v1/migration_classes.rb
+++ b/lib/gitlab/database/rename_reserved_paths_migration/v1/migration_classes.rb
@@ -74,7 +74,7 @@ module Gitlab
}.freeze
def repository_storage_path
- Gitlab.config.repositories.storages[repository_storage]['path']
+ Gitlab.config.repositories.storages[repository_storage].legacy_disk_path
end
# Overridden to have the correct `source_type` for the `route` relation
diff --git a/lib/gitlab/git/gitlab_projects.rb b/lib/gitlab/git/gitlab_projects.rb
index a142ed6b2ef..dc0bc8518bc 100644
--- a/lib/gitlab/git/gitlab_projects.rb
+++ b/lib/gitlab/git/gitlab_projects.rb
@@ -212,7 +212,7 @@ module Gitlab
end
def shard_name_from_shard_path(shard_path)
- Gitlab.config.repositories.storages.find { |_, info| info['path'] == shard_path }&.first ||
+ Gitlab.config.repositories.storages.find { |_, info| info.legacy_disk_path == shard_path }&.first ||
raise(ShardNameNotFoundError, "no shard found for path '#{shard_path}'")
end
diff --git a/lib/gitlab/git/repository.rb b/lib/gitlab/git/repository.rb
index 208710b0935..20b0647fce9 100644
--- a/lib/gitlab/git/repository.rb
+++ b/lib/gitlab/git/repository.rb
@@ -93,7 +93,7 @@ module Gitlab
@relative_path = relative_path
@gl_repository = gl_repository
- storage_path = Gitlab.config.repositories.storages[@storage]['path']
+ storage_path = Gitlab.config.repositories.storages[@storage].legacy_disk_path
@gitlab_projects = Gitlab::Git::GitlabProjects.new(
storage_path,
relative_path,
@@ -516,10 +516,6 @@ module Gitlab
end
end
- def sha_from_ref(ref)
- rev_parse_target(ref).oid
- end
-
# Return the object that +revspec+ points to. If +revspec+ is an
# annotated tag, then return the tag's target instead.
def rev_parse_target(revspec)
@@ -2409,6 +2405,10 @@ module Gitlab
def rev_list_param(spec)
spec == :all ? ['--all'] : spec
end
+
+ def sha_from_ref(ref)
+ rev_parse_target(ref).oid
+ end
end
end
end
diff --git a/lib/gitlab/git/storage/checker.rb b/lib/gitlab/git/storage/checker.rb
index d3c37f82101..2f611cef37b 100644
--- a/lib/gitlab/git/storage/checker.rb
+++ b/lib/gitlab/git/storage/checker.rb
@@ -35,7 +35,7 @@ module Gitlab
def initialize(storage, logger = Rails.logger)
@storage = storage
config = Gitlab.config.repositories.storages[@storage]
- @storage_path = config['path']
+ @storage_path = config.legacy_disk_path
@logger = logger
@hostname = Gitlab::Environment.hostname
diff --git a/lib/gitlab/git/storage/circuit_breaker.rb b/lib/gitlab/git/storage/circuit_breaker.rb
index 898bb1b65be..e35054466ff 100644
--- a/lib/gitlab/git/storage/circuit_breaker.rb
+++ b/lib/gitlab/git/storage/circuit_breaker.rb
@@ -25,7 +25,7 @@ module Gitlab
if !config.present?
NullCircuitBreaker.new(storage, hostname, error: Misconfiguration.new("Storage '#{storage}' is not configured"))
- elsif !config['path'].present?
+ elsif !config.legacy_disk_path.present?
NullCircuitBreaker.new(storage, hostname, error: Misconfiguration.new("Path for storage '#{storage}' is not configured"))
else
new(storage, hostname)
diff --git a/lib/gitlab/git/wiki.rb b/lib/gitlab/git/wiki.rb
index 52b44b9b3c5..8d82820915d 100644
--- a/lib/gitlab/git/wiki.rb
+++ b/lib/gitlab/git/wiki.rb
@@ -29,7 +29,6 @@ module Gitlab
@repository.gitaly_migrate(:wiki_write_page) do |is_enabled|
if is_enabled
gitaly_write_page(name, format, content, commit_details)
- gollum_wiki.clear_cache
else
gollum_write_page(name, format, content, commit_details)
end
@@ -40,7 +39,6 @@ module Gitlab
@repository.gitaly_migrate(:wiki_delete_page) do |is_enabled|
if is_enabled
gitaly_delete_page(page_path, commit_details)
- gollum_wiki.clear_cache
else
gollum_delete_page(page_path, commit_details)
end
@@ -51,7 +49,6 @@ module Gitlab
@repository.gitaly_migrate(:wiki_update_page) do |is_enabled|
if is_enabled
gitaly_update_page(page_path, title, format, content, commit_details)
- gollum_wiki.clear_cache
else
gollum_update_page(page_path, title, format, content, commit_details)
end
diff --git a/lib/gitlab/gitaly_client/storage_settings.rb b/lib/gitlab/gitaly_client/storage_settings.rb
new file mode 100644
index 00000000000..8668caf0c55
--- /dev/null
+++ b/lib/gitlab/gitaly_client/storage_settings.rb
@@ -0,0 +1,35 @@
+module Gitlab
+ module GitalyClient
+ # This is a chokepoint that is meant to help us stop remove all places
+ # where production code (app, config, db, lib) touches Git repositories
+ # directly.
+ class StorageSettings
+ DirectPathAccessError = Class.new(StandardError)
+
+ # This class will give easily recognizable NoMethodErrors
+ Deprecated = Class.new
+
+ attr_reader :legacy_disk_path
+
+ def initialize(storage)
+ raise "expected a Hash, got a #{storage.class.name}" unless storage.is_a?(Hash)
+
+ # Support a nil 'path' field because some of the circuit breaker tests use it.
+ @legacy_disk_path = File.expand_path(storage['path'], Rails.root) if storage['path']
+
+ storage['path'] = Deprecated
+ @hash = storage
+ end
+
+ def gitaly_address
+ @hash.fetch(:gitaly_address)
+ end
+
+ private
+
+ def method_missing(m, *args, &block)
+ @hash.public_send(m, *args, &block) # rubocop:disable GitlabSecurity/PublicSend
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/health_checks/fs_shards_check.rb b/lib/gitlab/health_checks/fs_shards_check.rb
index afaa59b1018..6e554383270 100644
--- a/lib/gitlab/health_checks/fs_shards_check.rb
+++ b/lib/gitlab/health_checks/fs_shards_check.rb
@@ -77,7 +77,7 @@ module Gitlab
end
def storage_path(storage_name)
- storages_paths&.dig(storage_name, 'path')
+ storages_paths[storage_name]&.legacy_disk_path
end
# All below test methods use shell commands to perform actions on storage volumes.
diff --git a/lib/gitlab/http.rb b/lib/gitlab/http.rb
new file mode 100644
index 00000000000..96558872a37
--- /dev/null
+++ b/lib/gitlab/http.rb
@@ -0,0 +1,11 @@
+# This class is used as a proxy for all outbounding http connection
+# coming from callbacks, services and hooks. The direct use of the HTTParty
+# is discouraged because it can lead to several security problems, like SSRF
+# calling internal IP or services.
+module Gitlab
+ class HTTP
+ include HTTParty # rubocop:disable Gitlab/HTTParty
+
+ connection_adapter ProxyHTTPConnectionAdapter
+ end
+end
diff --git a/lib/gitlab/middleware/read_only.rb b/lib/gitlab/middleware/read_only.rb
index d9d5f90596f..7f63e39b3aa 100644
--- a/lib/gitlab/middleware/read_only.rb
+++ b/lib/gitlab/middleware/read_only.rb
@@ -13,7 +13,7 @@ module Gitlab
end
def call(env)
- ReadOnly::Controller.new(@app, env).call
+ ::Gitlab::Middleware::ReadOnly::Controller.new(@app, env).call
end
end
end
diff --git a/lib/gitlab/omniauth_initializer.rb b/lib/gitlab/omniauth_initializer.rb
new file mode 100644
index 00000000000..35ed3a5ac05
--- /dev/null
+++ b/lib/gitlab/omniauth_initializer.rb
@@ -0,0 +1,75 @@
+module Gitlab
+ class OmniauthInitializer
+ def initialize(devise_config)
+ @devise_config = devise_config
+ end
+
+ def execute(providers)
+ providers.each do |provider|
+ add_provider(provider['name'].to_sym, *arguments_for(provider))
+ end
+ end
+
+ private
+
+ def add_provider(*args)
+ @devise_config.omniauth(*args)
+ end
+
+ def arguments_for(provider)
+ provider_arguments = []
+
+ %w[app_id app_secret].each do |argument|
+ provider_arguments << provider[argument] if provider[argument]
+ end
+
+ case provider['args']
+ when Array
+ # An Array from the configuration will be expanded.
+ provider_arguments.concat provider['args']
+ when Hash
+ hash_arguments = provider['args'].merge(provider_defaults(provider))
+
+ # A Hash from the configuration will be passed as is.
+ provider_arguments << hash_arguments.symbolize_keys
+ end
+
+ provider_arguments
+ end
+
+ def provider_defaults(provider)
+ case provider['name']
+ when 'cas3'
+ { on_single_sign_out: cas3_signout_handler }
+ when 'authentiq'
+ { remote_sign_out_handler: authentiq_signout_handler }
+ when 'shibboleth'
+ { fail_with_empty_uid: true }
+ else
+ {}
+ end
+ end
+
+ def cas3_signout_handler
+ lambda do |request|
+ ticket = request.params[:session_index]
+ raise "Service Ticket not found." unless Gitlab::Auth::OAuth::Session.valid?(:cas3, ticket)
+
+ Gitlab::Auth::OAuth::Session.destroy(:cas3, ticket)
+ true
+ end
+ end
+
+ def authentiq_signout_handler
+ lambda do |request|
+ authentiq_session = request.params['sid']
+ if Gitlab::Auth::OAuth::Session.valid?(:authentiq, authentiq_session)
+ Gitlab::Auth::OAuth::Session.destroy(:authentiq, authentiq_session)
+ true
+ else
+ false
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/profiler.rb b/lib/gitlab/profiler.rb
index 98a168b43bb..18540e64d4c 100644
--- a/lib/gitlab/profiler.rb
+++ b/lib/gitlab/profiler.rb
@@ -92,8 +92,8 @@ module Gitlab
if type && time
@load_times_by_model ||= {}
- @load_times_by_model[type] ||= 0
- @load_times_by_model[type] += time.to_f
+ @load_times_by_model[type] ||= []
+ @load_times_by_model[type] << time.to_f
end
super
@@ -135,8 +135,12 @@ module Gitlab
def self.log_load_times_by_model(logger)
return unless logger.respond_to?(:load_times_by_model)
- logger.load_times_by_model.to_a.sort_by(&:last).reverse.each do |(model, time)|
- logger.info("#{model} total: #{time.round(2)}ms")
+ summarised_load_times = logger.load_times_by_model.to_a.map do |(model, times)|
+ [model, times.count, times.sum]
+ end
+
+ summarised_load_times.sort_by(&:last).reverse.each do |(model, query_count, time)|
+ logger.info("#{model} total (#{query_count}): #{time.round(2)}ms")
end
end
end
diff --git a/lib/gitlab/proxy_http_connection_adapter.rb b/lib/gitlab/proxy_http_connection_adapter.rb
new file mode 100644
index 00000000000..c70d6f4cd84
--- /dev/null
+++ b/lib/gitlab/proxy_http_connection_adapter.rb
@@ -0,0 +1,34 @@
+# This class is part of the Gitlab::HTTP wrapper. Depending on the value
+# of the global setting allow_local_requests_from_hooks_and_services this adapter
+# will allow/block connection to internal IPs and/or urls.
+#
+# This functionality can be overriden by providing the setting the option
+# allow_local_requests = true in the request. For example:
+# Gitlab::HTTP.get('http://www.gitlab.com', allow_local_requests: true)
+#
+# This option will take precedence over the global setting.
+module Gitlab
+ class ProxyHTTPConnectionAdapter < HTTParty::ConnectionAdapter
+ def connection
+ if !allow_local_requests? && blocked_url?
+ raise URI::InvalidURIError
+ end
+
+ super
+ end
+
+ private
+
+ def blocked_url?
+ Gitlab::UrlBlocker.blocked_url?(uri, allow_private_networks: false)
+ end
+
+ def allow_local_requests?
+ options.fetch(:allow_local_requests, allow_settings_local_requests?)
+ end
+
+ def allow_settings_local_requests?
+ Gitlab::CurrentSettings.allow_local_requests_from_hooks_and_services?
+ end
+ end
+end
diff --git a/lib/gitlab/repo_path.rb b/lib/gitlab/repo_path.rb
index 79265cf952d..1fa2a19b0af 100644
--- a/lib/gitlab/repo_path.rb
+++ b/lib/gitlab/repo_path.rb
@@ -21,11 +21,11 @@ module Gitlab
result = repo_path
storage = Gitlab.config.repositories.storages.values.find do |params|
- repo_path.start_with?(params['path'])
+ repo_path.start_with?(params.legacy_disk_path)
end
if storage
- result = result.sub(storage['path'], '')
+ result = result.sub(storage.legacy_disk_path, '')
elsif fail_on_not_found
raise NotFoundError.new("No known storage path matches #{repo_path.inspect}")
end
diff --git a/lib/gitlab/setup_helper.rb b/lib/gitlab/setup_helper.rb
index 07d7c91cb5d..e5c02dd8ecc 100644
--- a/lib/gitlab/setup_helper.rb
+++ b/lib/gitlab/setup_helper.rb
@@ -24,7 +24,7 @@ module Gitlab
address = val['gitaly_address']
end
- storages << { name: key, path: val['path'] }
+ storages << { name: key, path: val.legacy_disk_path }
end
if Rails.env.test?
diff --git a/lib/gitlab/shell.rb b/lib/gitlab/shell.rb
index 3a8f5826818..c8c15b9684a 100644
--- a/lib/gitlab/shell.rb
+++ b/lib/gitlab/shell.rb
@@ -82,7 +82,7 @@ module Gitlab
repository.gitaly_repository_client.create_repository
true
else
- repo_path = File.join(Gitlab.config.repositories.storages[storage]['path'], relative_path)
+ repo_path = File.join(Gitlab.config.repositories.storages[storage].legacy_disk_path, relative_path)
Gitlab::Git::Repository.create(repo_path, bare: true, symlink_hooks_to: gitlab_shell_hooks_path)
end
end
@@ -131,7 +131,7 @@ module Gitlab
if is_enabled
repository.gitaly_repository_client.fetch_remote(remote, ssh_auth: ssh_auth, forced: forced, no_tags: no_tags, timeout: git_timeout, prune: prune)
else
- storage_path = Gitlab.config.repositories.storages[repository.storage]["path"]
+ storage_path = Gitlab.config.repositories.storages[repository.storage].legacy_disk_path
local_fetch_remote(storage_path, repository.relative_path, remote, ssh_auth: ssh_auth, forced: forced, no_tags: no_tags, prune: prune)
end
end
@@ -478,7 +478,7 @@ module Gitlab
def gitaly_namespace_client(storage_path)
storage, _value = Gitlab.config.repositories.storages.find do |storage, value|
- value['path'] == storage_path
+ value.legacy_disk_path == storage_path
end
Gitlab::GitalyClient::NamespaceService.new(storage)
diff --git a/lib/gitlab/task_helpers.rb b/lib/gitlab/task_helpers.rb
index 34bee6fecbe..42be301fd9b 100644
--- a/lib/gitlab/task_helpers.rb
+++ b/lib/gitlab/task_helpers.rb
@@ -129,7 +129,7 @@ module Gitlab
def all_repos
Gitlab.config.repositories.storages.each_value do |repository_storage|
- IO.popen(%W(find #{repository_storage['path']} -mindepth 2 -type d -name *.git)) do |find|
+ IO.popen(%W(find #{repository_storage.legacy_disk_path} -mindepth 2 -type d -name *.git)) do |find|
find.each_line do |path|
yield path.chomp
end
@@ -138,7 +138,7 @@ module Gitlab
end
def repository_storage_paths_args
- Gitlab.config.repositories.storages.values.map { |rs| rs['path'] }
+ Gitlab.config.repositories.storages.values.map { |rs| rs.legacy_disk_path }
end
def user_home
diff --git a/lib/gitlab/url_blocker.rb b/lib/gitlab/url_blocker.rb
index 13150ddab67..0f9f939e204 100644
--- a/lib/gitlab/url_blocker.rb
+++ b/lib/gitlab/url_blocker.rb
@@ -3,11 +3,7 @@ require 'resolv'
module Gitlab
class UrlBlocker
class << self
- # Used to specify what hosts and port numbers should be prohibited for project
- # imports.
- VALID_PORTS = [22, 80, 443].freeze
-
- def blocked_url?(url)
+ def blocked_url?(url, allow_private_networks: true, valid_ports: [])
return false if url.nil?
blocked_ips = ["127.0.0.1", "::1", "0.0.0.0"]
@@ -18,12 +14,15 @@ module Gitlab
# Allow imports from the GitLab instance itself but only from the configured ports
return false if internal?(uri)
- return true if blocked_port?(uri.port)
+ return true if blocked_port?(uri.port, valid_ports)
return true if blocked_user_or_hostname?(uri.user)
return true if blocked_user_or_hostname?(uri.hostname)
- server_ips = Addrinfo.getaddrinfo(uri.hostname, 80, nil, :STREAM).map(&:ip_address)
+ addrs_info = Addrinfo.getaddrinfo(uri.hostname, 80, nil, :STREAM)
+ server_ips = addrs_info.map(&:ip_address)
+
return true if (blocked_ips & server_ips).any?
+ return true if !allow_private_networks && private_network?(addrs_info)
rescue Addressable::URI::InvalidURIError
return true
rescue SocketError
@@ -35,10 +34,10 @@ module Gitlab
private
- def blocked_port?(port)
- return false if port.blank?
+ def blocked_port?(port, valid_ports)
+ return false if port.blank? || valid_ports.blank?
- port < 1024 && !VALID_PORTS.include?(port)
+ port < 1024 && !valid_ports.include?(port)
end
def blocked_user_or_hostname?(value)
@@ -61,6 +60,10 @@ module Gitlab
(uri.port.blank? || uri.port == config.gitlab_shell.ssh_port)
end
+ def private_network?(addrs_info)
+ addrs_info.any? { |addr| addr.ipv4_private? || addr.ipv6_sitelocal? }
+ end
+
def config
Gitlab.config
end
diff --git a/lib/mattermost/session.rb b/lib/mattermost/session.rb
index 65ccdb3c347..85f78e44f32 100644
--- a/lib/mattermost/session.rb
+++ b/lib/mattermost/session.rb
@@ -22,16 +22,14 @@ module Mattermost
# going.
class Session
include Doorkeeper::Helpers::Controller
- include HTTParty
LEASE_TIMEOUT = 60
- base_uri Settings.mattermost.host
-
- attr_accessor :current_resource_owner, :token
+ attr_accessor :current_resource_owner, :token, :base_uri
def initialize(current_user)
@current_resource_owner = current_user
+ @base_uri = Settings.mattermost.host
end
def with_session
@@ -73,24 +71,32 @@ module Mattermost
def get(path, options = {})
handle_exceptions do
- self.class.get(path, options.merge(headers: @headers))
+ Gitlab::HTTP.get(path, build_options(options))
end
end
def post(path, options = {})
handle_exceptions do
- self.class.post(path, options.merge(headers: @headers))
+ Gitlab::HTTP.post(path, build_options(options))
end
end
def delete(path, options = {})
handle_exceptions do
- self.class.delete(path, options.merge(headers: @headers))
+ Gitlab::HTTP.delete(path, build_options(options))
end
end
private
+ def build_options(options)
+ options.tap do |hash|
+ hash[:headers] = @headers
+ hash[:allow_local_requests] = true
+ hash[:base_uri] = base_uri if base_uri.presence
+ end
+ end
+
def create
raise Mattermost::NoSessionError unless oauth_uri
raise Mattermost::NoSessionError unless token_uri
@@ -165,14 +171,14 @@ module Mattermost
def handle_exceptions
yield
- rescue HTTParty::Error => e
+ rescue Gitlab::HTTP::Error => e
raise Mattermost::ConnectionError.new(e.message)
rescue Errno::ECONNREFUSED => e
raise Mattermost::ConnectionError.new(e.message)
end
def parse_cookie(response)
- cookie_hash = CookieHash.new
+ cookie_hash = Gitlab::HTTP::CookieHash.new
response.get_fields('Set-Cookie').each { |c| cookie_hash.add_cookies(c) }
cookie_hash
end
diff --git a/lib/microsoft_teams/notifier.rb b/lib/microsoft_teams/notifier.rb
index 3bef68a1bcb..c08d3e933a8 100644
--- a/lib/microsoft_teams/notifier.rb
+++ b/lib/microsoft_teams/notifier.rb
@@ -9,14 +9,15 @@ module MicrosoftTeams
result = false
begin
- response = HTTParty.post(
+ response = Gitlab::HTTP.post(
@webhook.to_str,
headers: @header,
+ allow_local_requests: true,
body: body(options)
)
result = true if response
- rescue HTTParty::Error, StandardError => error
+ rescue Gitlab::HTTP::Error, StandardError => error
Rails.logger.info("#{self.class.name}: Error while connecting to #{@webhook}: #{error.message}")
end
diff --git a/lib/system_check/orphans/namespace_check.rb b/lib/system_check/orphans/namespace_check.rb
index b8446300f72..b5f443abe06 100644
--- a/lib/system_check/orphans/namespace_check.rb
+++ b/lib/system_check/orphans/namespace_check.rb
@@ -6,8 +6,8 @@ module SystemCheck
def multi_check
Gitlab.config.repositories.storages.each do |storage_name, repository_storage|
$stdout.puts
- $stdout.puts "* Storage: #{storage_name} (#{repository_storage['path']})".color(:yellow)
- toplevel_namespace_dirs = disk_namespaces(repository_storage['path'])
+ $stdout.puts "* Storage: #{storage_name} (#{repository_storage.legacy_disk_path})".color(:yellow)
+ toplevel_namespace_dirs = disk_namespaces(repository_storage.legacy_disk_path)
orphans = (toplevel_namespace_dirs - existing_namespaces)
print_orphans(orphans, storage_name)
diff --git a/lib/system_check/orphans/repository_check.rb b/lib/system_check/orphans/repository_check.rb
index 9b6b2429783..5ef0b93ad08 100644
--- a/lib/system_check/orphans/repository_check.rb
+++ b/lib/system_check/orphans/repository_check.rb
@@ -6,10 +6,12 @@ module SystemCheck
def multi_check
Gitlab.config.repositories.storages.each do |storage_name, repository_storage|
+ storage_path = repository_storage.legacy_disk_path
+
$stdout.puts
- $stdout.puts "* Storage: #{storage_name} (#{repository_storage['path']})".color(:yellow)
+ $stdout.puts "* Storage: #{storage_name} (#{storage_path})".color(:yellow)
- repositories = disk_repositories(repository_storage['path'])
+ repositories = disk_repositories(storage_path)
orphans = (repositories - fetch_repositories(storage_name))
print_orphans(orphans, storage_name)
diff --git a/lib/tasks/gitlab/check.rake b/lib/tasks/gitlab/check.rake
index 2403f57f05a..abef8cd2bcc 100644
--- a/lib/tasks/gitlab/check.rake
+++ b/lib/tasks/gitlab/check.rake
@@ -61,7 +61,7 @@ namespace :gitlab do
puts "Repo base directory exists?"
Gitlab.config.repositories.storages.each do |name, repository_storage|
- repo_base_path = repository_storage['path']
+ repo_base_path = repository_storage.legacy_disk_path
print "#{name}... "
if File.exist?(repo_base_path)
@@ -86,7 +86,7 @@ namespace :gitlab do
puts "Repo storage directories are symlinks?"
Gitlab.config.repositories.storages.each do |name, repository_storage|
- repo_base_path = repository_storage['path']
+ repo_base_path = repository_storage.legacy_disk_path
print "#{name}... "
unless File.exist?(repo_base_path)
@@ -110,7 +110,7 @@ namespace :gitlab do
puts "Repo paths access is drwxrws---?"
Gitlab.config.repositories.storages.each do |name, repository_storage|
- repo_base_path = repository_storage['path']
+ repo_base_path = repository_storage.legacy_disk_path
print "#{name}... "
unless File.exist?(repo_base_path)
@@ -140,7 +140,7 @@ namespace :gitlab do
puts "Repo paths owned by #{gitlab_shell_ssh_user}:root, or #{gitlab_shell_ssh_user}:#{Gitlab.config.gitlab_shell.owner_group}?"
Gitlab.config.repositories.storages.each do |name, repository_storage|
- repo_base_path = repository_storage['path']
+ repo_base_path = repository_storage.legacy_disk_path
print "#{name}... "
unless File.exist?(repo_base_path)
diff --git a/lib/tasks/gitlab/cleanup.rake b/lib/tasks/gitlab/cleanup.rake
index 2453079911d..d6d15285489 100644
--- a/lib/tasks/gitlab/cleanup.rake
+++ b/lib/tasks/gitlab/cleanup.rake
@@ -12,7 +12,7 @@ namespace :gitlab do
namespaces = Namespace.pluck(:path)
namespaces << HASHED_REPOSITORY_NAME # add so that it will be ignored
Gitlab.config.repositories.storages.each do |name, repository_storage|
- git_base_path = repository_storage['path']
+ git_base_path = repository_storage.legacy_disk_path
all_dirs = Dir.glob(git_base_path + '/*')
puts git_base_path.color(:yellow)
@@ -54,7 +54,7 @@ namespace :gitlab do
move_suffix = "+orphaned+#{Time.now.to_i}"
Gitlab.config.repositories.storages.each do |name, repository_storage|
- repo_root = repository_storage['path']
+ repo_root = repository_storage.legacy_disk_path
# Look for global repos (legacy, depth 1) and normal repos (depth 2)
IO.popen(%W(find #{repo_root} -mindepth 1 -maxdepth 2 -name *.git)) do |find|
find.each_line do |path|
diff --git a/lib/tasks/gitlab/info.rake b/lib/tasks/gitlab/info.rake
index 45e9a1a1c72..47ed522aec3 100644
--- a/lib/tasks/gitlab/info.rake
+++ b/lib/tasks/gitlab/info.rake
@@ -68,7 +68,7 @@ namespace :gitlab do
puts "Version:\t#{gitlab_shell_version || "unknown".color(:red)}"
puts "Repository storage paths:"
Gitlab.config.repositories.storages.each do |name, repository_storage|
- puts "- #{name}: \t#{repository_storage['path']}"
+ puts "- #{name}: \t#{repository_storage.legacy_disk_path}"
end
puts "Hooks:\t\t#{Gitlab.config.gitlab_shell.hooks_path}"
puts "Git:\t\t#{Gitlab.config.git.bin_path}"
diff --git a/lib/tasks/haml-lint.rake b/lib/tasks/haml-lint.rake
index 5c0cc4990fc..ad2d034b0b4 100644
--- a/lib/tasks/haml-lint.rake
+++ b/lib/tasks/haml-lint.rake
@@ -2,14 +2,5 @@ unless Rails.env.production?
require 'haml_lint/rake_task'
require 'haml_lint/inline_javascript'
- # Workaround for warnings from parser/current
- # TODO: Remove this after we update parser gem
- task :haml_lint do
- require 'parser'
- def Parser.warn(*args)
- puts(*args) # static-analysis ignores stdout if status is 0
- end
- end
-
HamlLint::RakeTask.new
end
diff --git a/public/robots.txt b/public/robots.txt
index 123272a9834..1f9d42f4adc 100644
--- a/public/robots.txt
+++ b/public/robots.txt
@@ -20,6 +20,7 @@ Disallow: /projects/new
Disallow: /groups/new
Disallow: /groups/*/edit
Disallow: /users
+Disallow: /help
# Global snippets
User-Agent: *
diff --git a/rubocop/cop/gitlab/httparty.rb b/rubocop/cop/gitlab/httparty.rb
new file mode 100644
index 00000000000..215f18b6993
--- /dev/null
+++ b/rubocop/cop/gitlab/httparty.rb
@@ -0,0 +1,62 @@
+require_relative '../../spec_helpers'
+
+module RuboCop
+ module Cop
+ module Gitlab
+ class HTTParty < RuboCop::Cop::Cop
+ include SpecHelpers
+
+ MSG_SEND = <<~EOL.freeze
+ Avoid calling `HTTParty` directly. Instead, use the Gitlab::HTTP
+ wrapper. To allow request to localhost or the private network set
+ the option :allow_local_requests in the request call.
+ EOL
+
+ MSG_INCLUDE = <<~EOL.freeze
+ Avoid including `HTTParty` directly. Instead, use the Gitlab::HTTP
+ wrapper. To allow request to localhost or the private network set
+ the option :allow_local_requests in the request call.
+ EOL
+
+ def_node_matcher :includes_httparty?, <<~PATTERN
+ (send nil? :include (const nil? :HTTParty))
+ PATTERN
+
+ def_node_matcher :httparty_node?, <<~PATTERN
+ (send (const nil? :HTTParty)...)
+ PATTERN
+
+ def on_send(node)
+ return if in_spec?(node)
+
+ add_offense(node, location: :expression, message: MSG_SEND) if httparty_node?(node)
+ add_offense(node, location: :expression, message: MSG_INCLUDE) if includes_httparty?(node)
+ end
+
+ def autocorrect(node)
+ if includes_httparty?(node)
+ autocorrect_includes_httparty(node)
+ else
+ autocorrect_httparty_node(node)
+ end
+ end
+
+ def autocorrect_includes_httparty(node)
+ lambda do |corrector|
+ corrector.remove(node.source_range)
+ end
+ end
+
+ def autocorrect_httparty_node(node)
+ _, method_name, *arg_nodes = *node
+
+ replacement = "Gitlab::HTTP.#{method_name}(#{arg_nodes.map(&:source).join(', ')})"
+
+ lambda do |corrector|
+ corrector.replace(node.source_range, replacement)
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/rubocop/rubocop.rb b/rubocop/rubocop.rb
index b36a3f9c8a0..0b4c7d31442 100644
--- a/rubocop/rubocop.rb
+++ b/rubocop/rubocop.rb
@@ -1,6 +1,7 @@
# rubocop:disable Naming/FileName
require_relative 'cop/gitlab/module_with_instance_variables'
require_relative 'cop/gitlab/predicate_memoization'
+require_relative 'cop/gitlab/httparty'
require_relative 'cop/include_sidekiq_worker'
require_relative 'cop/line_break_around_conditional_block'
require_relative 'cop/migration/add_column'
diff --git a/spec/controllers/omniauth_callbacks_controller_spec.rb b/spec/controllers/omniauth_callbacks_controller_spec.rb
index c639ad32ec6..5f0e8c5eca9 100644
--- a/spec/controllers/omniauth_callbacks_controller_spec.rb
+++ b/spec/controllers/omniauth_callbacks_controller_spec.rb
@@ -3,72 +3,125 @@ require 'spec_helper'
describe OmniauthCallbacksController do
include LoginHelpers
- let(:user) { create(:omniauth_user, extern_uid: 'my-uid', provider: provider) }
- let(:provider) { :github }
+ let(:user) { create(:omniauth_user, extern_uid: extern_uid, provider: provider) }
before do
- mock_auth_hash(provider.to_s, 'my-uid', user.email)
+ mock_auth_hash(provider.to_s, extern_uid, user.email)
stub_omniauth_provider(provider, context: request)
end
- it 'allows sign in' do
- post provider
+ context 'when the user is on the last sign in attempt' do
+ let(:extern_uid) { 'my-uid' }
- expect(request.env['warden']).to be_authenticated
- end
+ before do
+ user.update(failed_attempts: User.maximum_attempts.pred)
+ subject.response = ActionDispatch::Response.new
+ end
- shared_context 'sign_up' do
- let(:user) { double(email: 'new@example.com') }
+ context 'when using a form based provider' do
+ let(:provider) { :ldap }
- before do
- stub_omniauth_setting(block_auto_created_users: false)
+ it 'locks the user when sign in fails' do
+ allow(subject).to receive(:params).and_return(ActionController::Parameters.new(username: user.username))
+ request.env['omniauth.error.strategy'] = OmniAuth::Strategies::LDAP.new(nil)
+
+ subject.send(:failure)
+
+ expect(user.reload).to be_access_locked
+ end
end
- end
- context 'sign up' do
- include_context 'sign_up'
+ context 'when using a button based provider' do
+ let(:provider) { :github }
- it 'is allowed' do
- post provider
+ it 'does not lock the user when sign in fails' do
+ request.env['omniauth.error.strategy'] = OmniAuth::Strategies::GitHub.new(nil)
- expect(request.env['warden']).to be_authenticated
+ subject.send(:failure)
+
+ expect(user.reload).not_to be_access_locked
+ end
end
end
- context 'when OAuth is disabled' do
- before do
- stub_env('IN_MEMORY_APPLICATION_SETTINGS', 'false')
- settings = Gitlab::CurrentSettings.current_application_settings
- settings.update(disabled_oauth_sign_in_sources: [provider.to_s])
- end
+ context 'strategies' do
+ context 'github' do
+ let(:extern_uid) { 'my-uid' }
+ let(:provider) { :github }
- it 'prevents login via POST' do
- post provider
+ it 'allows sign in' do
+ post provider
- expect(request.env['warden']).not_to be_authenticated
- end
+ expect(request.env['warden']).to be_authenticated
+ end
- it 'shows warning when attempting login' do
- post provider
+ shared_context 'sign_up' do
+ let(:user) { double(email: 'new@example.com') }
- expect(response).to redirect_to new_user_session_path
- expect(flash[:alert]).to eq('Signing in using GitHub has been disabled')
- end
+ before do
+ stub_omniauth_setting(block_auto_created_users: false)
+ end
+ end
+
+ context 'sign up' do
+ include_context 'sign_up'
+
+ it 'is allowed' do
+ post provider
+
+ expect(request.env['warden']).to be_authenticated
+ end
+ end
+
+ context 'when OAuth is disabled' do
+ before do
+ stub_env('IN_MEMORY_APPLICATION_SETTINGS', 'false')
+ settings = Gitlab::CurrentSettings.current_application_settings
+ settings.update(disabled_oauth_sign_in_sources: [provider.to_s])
+ end
+
+ it 'prevents login via POST' do
+ post provider
+
+ expect(request.env['warden']).not_to be_authenticated
+ end
- it 'allows linking the disabled provider' do
- user.identities.destroy_all
- sign_in(user)
+ it 'shows warning when attempting login' do
+ post provider
- expect { post provider }.to change { user.reload.identities.count }.by(1)
+ expect(response).to redirect_to new_user_session_path
+ expect(flash[:alert]).to eq('Signing in using GitHub has been disabled')
+ end
+
+ it 'allows linking the disabled provider' do
+ user.identities.destroy_all
+ sign_in(user)
+
+ expect { post provider }.to change { user.reload.identities.count }.by(1)
+ end
+
+ context 'sign up' do
+ include_context 'sign_up'
+
+ it 'is prevented' do
+ post provider
+
+ expect(request.env['warden']).not_to be_authenticated
+ end
+ end
+ end
end
- context 'sign up' do
- include_context 'sign_up'
+ context 'auth0' do
+ let(:extern_uid) { '' }
+ let(:provider) { :auth0 }
- it 'is prevented' do
- post provider
+ it 'does not allow sign in without extern_uid' do
+ post 'auth0'
expect(request.env['warden']).not_to be_authenticated
+ expect(response.status).to eq(302)
+ expect(controller).to set_flash[:alert].to('Wrong extern UID provided. Make sure Auth0 is configured correctly.')
end
end
end
diff --git a/spec/controllers/projects/pages_controller_spec.rb b/spec/controllers/projects/pages_controller_spec.rb
index 4705c50de7e..11f54eef531 100644
--- a/spec/controllers/projects/pages_controller_spec.rb
+++ b/spec/controllers/projects/pages_controller_spec.rb
@@ -65,4 +65,41 @@ describe Projects::PagesController do
end
end
end
+
+ describe 'PATCH update' do
+ let(:request_params) do
+ {
+ namespace_id: project.namespace,
+ project_id: project,
+ project: { pages_https_only: false }
+ }
+ end
+
+ let(:update_service) { double(execute: { status: :success }) }
+
+ before do
+ allow(Projects::UpdateService).to receive(:new) { update_service }
+ end
+
+ it 'returns 302 status' do
+ patch :update, request_params
+
+ expect(response).to have_gitlab_http_status(:found)
+ end
+
+ it 'redirects back to the pages settings' do
+ patch :update, request_params
+
+ expect(response).to redirect_to(project_pages_path(project))
+ end
+
+ it 'calls the update service' do
+ expect(Projects::UpdateService)
+ .to receive(:new)
+ .with(project, user, request_params[:project])
+ .and_return(update_service)
+
+ patch :update, request_params
+ end
+ end
end
diff --git a/spec/controllers/projects/pages_domains_controller_spec.rb b/spec/controllers/projects/pages_domains_controller_spec.rb
index 83a3799e883..d4058a5c515 100644
--- a/spec/controllers/projects/pages_domains_controller_spec.rb
+++ b/spec/controllers/projects/pages_domains_controller_spec.rb
@@ -13,7 +13,7 @@ describe Projects::PagesDomainsController do
end
let(:pages_domain_params) do
- build(:pages_domain, :with_certificate, :with_key, domain: 'my.otherdomain.com').slice(:key, :certificate, :domain)
+ build(:pages_domain, domain: 'my.otherdomain.com').slice(:key, :certificate, :domain)
end
before do
@@ -68,7 +68,7 @@ describe Projects::PagesDomainsController do
end
let(:pages_domain_params) do
- attributes_for(:pages_domain, :with_certificate, :with_key).slice(:key, :certificate)
+ attributes_for(:pages_domain).slice(:key, :certificate)
end
let(:params) do
diff --git a/spec/controllers/projects/pipelines_settings_controller_spec.rb b/spec/controllers/projects/pipelines_settings_controller_spec.rb
index 1cc488bef32..913b9bd804a 100644
--- a/spec/controllers/projects/pipelines_settings_controller_spec.rb
+++ b/spec/controllers/projects/pipelines_settings_controller_spec.rb
@@ -47,10 +47,32 @@ describe Projects::PipelinesSettingsController do
expect_any_instance_of(Projects::UpdateService).to receive(:run_auto_devops_pipeline?).and_return(true)
end
- it 'queues a CreatePipelineWorker' do
- expect(CreatePipelineWorker).to receive(:perform_async).with(project.id, user.id, project.default_branch, :web, any_args)
+ context 'when the project repository is empty' do
+ it 'sets a warning flash' do
+ expect(subject).to set_flash[:warning]
+ end
- subject
+ it 'does not queue a CreatePipelineWorker' do
+ expect(CreatePipelineWorker).not_to receive(:perform_async).with(project.id, user.id, project.default_branch, :web, any_args)
+
+ subject
+ end
+ end
+
+ context 'when the project repository is not empty' do
+ let(:project) { create(:project, :repository) }
+
+ it 'sets a success flash' do
+ allow(CreatePipelineWorker).to receive(:perform_async).with(project.id, user.id, project.default_branch, :web, any_args)
+
+ expect(subject).to set_flash[:success]
+ end
+
+ it 'queues a CreatePipelineWorker' do
+ expect(CreatePipelineWorker).to receive(:perform_async).with(project.id, user.id, project.default_branch, :web, any_args)
+
+ subject
+ end
end
end
diff --git a/spec/factories/pages_domains.rb b/spec/factories/pages_domains.rb
index 35b44e1c52e..20671da016e 100644
--- a/spec/factories/pages_domains.rb
+++ b/spec/factories/pages_domains.rb
@@ -4,25 +4,7 @@ FactoryBot.define do
verified_at { Time.now }
enabled_until { 1.week.from_now }
- trait :disabled do
- verified_at nil
- enabled_until nil
- end
-
- trait :unverified do
- verified_at nil
- end
-
- trait :reverify do
- enabled_until { 1.hour.from_now }
- end
-
- trait :expired do
- enabled_until { 1.hour.ago }
- end
-
- trait :with_certificate do
- certificate '-----BEGIN CERTIFICATE-----
+ certificate '-----BEGIN CERTIFICATE-----
MIICGzCCAYSgAwIBAgIBATANBgkqhkiG9w0BAQUFADAbMRkwFwYDVQQDExB0ZXN0
LWNlcnRpZmljYXRlMB4XDTE2MDIxMjE0MzIwMFoXDTIwMDQxMjE0MzIwMFowGzEZ
MBcGA1UEAxMQdGVzdC1jZXJ0aWZpY2F0ZTCBnzANBgkqhkiG9w0BAQEFAAOBjQAw
@@ -36,10 +18,8 @@ joZp2JHYvNlTPkRJ/J4TcXxBTJmArcQgTIuNoBtC+0A/SwdK4MfTCUY4vNWNdese
5A4K65Nb7Oh1AdQieTBHNXXCdyFsva9/ScfQGEl7p55a52jOPs0StPd7g64uvjlg
YHi2yesCrOvVXt+lgPTd
-----END CERTIFICATE-----'
- end
- trait :with_key do
- key '-----BEGIN PRIVATE KEY-----
+ key '-----BEGIN PRIVATE KEY-----
MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAKS+CfS9GcRSdYSN
SzyH5QJQBr5umRL6E+KilOV39iYFO/9oHjUdapTRWkrwnNPCp7qaeck4Jr8iv14t
PVNDfNr76eGb6/3YknOAP0QOjLWunoC8kjU+N/JHU52NrUeX3qEy8EKV9LeCDJcB
@@ -55,6 +35,30 @@ EPjGlXIT+aW2XiPmK3ZlCDcWIenE+lmtbOpI159Wpk8BGXs/s/xBAkEAlAY3ymgx
63BDJEwvOb2IaP8lDDxNsXx9XJNVvQbv5n15vNsLHbjslHfAhAbxnLQ1fLhUPqSi
nNp/xedE1YxutQ==
-----END PRIVATE KEY-----'
+
+ trait :disabled do
+ verified_at nil
+ enabled_until nil
+ end
+
+ trait :unverified do
+ verified_at nil
+ end
+
+ trait :reverify do
+ enabled_until { 1.hour.from_now }
+ end
+
+ trait :expired do
+ enabled_until { 1.hour.ago }
+ end
+
+ trait :without_certificate do
+ certificate nil
+ end
+
+ trait :without_key do
+ key nil
end
trait :with_missing_chain do
diff --git a/spec/features/projects/pages_spec.rb b/spec/features/projects/pages_spec.rb
index 233d2e67b9d..020738ae865 100644
--- a/spec/features/projects/pages_spec.rb
+++ b/spec/features/projects/pages_spec.rb
@@ -40,11 +40,6 @@ feature 'Pages' do
end
context 'when support for external domains is disabled' do
- before do
- allow(Gitlab.config.pages).to receive(:external_http).and_return(nil)
- allow(Gitlab.config.pages).to receive(:external_https).and_return(nil)
- end
-
it 'renders message that support is disabled' do
visit project_pages_path(project)
@@ -52,7 +47,9 @@ feature 'Pages' do
end
end
- context 'when pages are exposed on external HTTP address' do
+ context 'when pages are exposed on external HTTP address', :http_pages_enabled do
+ given(:project) { create(:project, pages_https_only: false) }
+
shared_examples 'adds new domain' do
it 'adds new domain' do
visit new_project_pages_domain_path(project)
@@ -64,11 +61,6 @@ feature 'Pages' do
end
end
- before do
- allow(Gitlab.config.pages).to receive(:external_http).and_return(['1.1.1.1:80'])
- allow(Gitlab.config.pages).to receive(:external_https).and_return(nil)
- end
-
it 'allows to add new domain' do
visit project_pages_path(project)
@@ -80,13 +72,13 @@ feature 'Pages' do
context 'when project in group namespace' do
it_behaves_like 'adds new domain' do
let(:group) { create :group }
- let(:project) { create :project, namespace: group }
+ let(:project) { create(:project, namespace: group, pages_https_only: false) }
end
end
context 'when pages domain is added' do
before do
- project.pages_domains.create!(domain: 'my.test.domain.com')
+ create(:pages_domain, project: project, domain: 'my.test.domain.com')
visit new_project_pages_domain_path(project)
end
@@ -104,7 +96,7 @@ feature 'Pages' do
end
end
- context 'when pages are exposed on external HTTPS address' do
+ context 'when pages are exposed on external HTTPS address', :https_pages_enabled do
let(:certificate_pem) do
<<~PEM
-----BEGIN CERTIFICATE-----
@@ -145,11 +137,6 @@ feature 'Pages' do
KEY
end
- before do
- allow(Gitlab.config.pages).to receive(:external_http).and_return(['1.1.1.1:80'])
- allow(Gitlab.config.pages).to receive(:external_https).and_return(['1.1.1.1:443'])
- end
-
it 'adds new domain with certificate' do
visit new_project_pages_domain_path(project)
@@ -163,7 +150,7 @@ feature 'Pages' do
describe 'updating the certificate for an existing domain' do
let!(:domain) do
- create(:pages_domain, :with_key, :with_certificate, project: project)
+ create(:pages_domain, project: project)
end
it 'allows the certificate to be updated' do
@@ -237,6 +224,69 @@ feature 'Pages' do
it_behaves_like 'no pages deployed'
end
+ describe 'HTTPS settings', :js, :https_pages_enabled do
+ background do
+ project.namespace.update(owner: user)
+
+ allow_any_instance_of(Project).to receive(:pages_deployed?) { true }
+ end
+
+ scenario 'tries to change the setting' do
+ visit project_pages_path(project)
+ expect(page).to have_content("Force domains with SSL certificates to use HTTPS")
+
+ uncheck :project_pages_https_only
+
+ click_button 'Save'
+
+ expect(page).to have_text('Your changes have been saved')
+ expect(page).not_to have_checked_field('project_pages_https_only')
+ end
+
+ context 'setting could not be updated' do
+ before do
+ allow_any_instance_of(Projects::UpdateService)
+ .to receive(:execute)
+ .and_return(status: :error)
+ end
+
+ scenario 'tries to change the setting' do
+ visit project_pages_path(project)
+
+ uncheck :project_pages_https_only
+
+ click_button 'Save'
+
+ expect(page).to have_text('Something went wrong on our end')
+ end
+ end
+
+ context 'non-HTTPS domain exists' do
+ given(:project) { create(:project, pages_https_only: false) }
+
+ before do
+ create(:pages_domain, :without_key, :without_certificate, project: project)
+ end
+
+ scenario 'the setting is disabled' do
+ visit project_pages_path(project)
+
+ expect(page).to have_field(:project_pages_https_only, disabled: true)
+ expect(page).not_to have_button('Save')
+ end
+ end
+
+ context 'HTTPS pages are disabled', :https_pages_disabled do
+ scenario 'the setting is unavailable' do
+ visit project_pages_path(project)
+
+ expect(page).not_to have_field(:project_pages_https_only)
+ expect(page).not_to have_content('Force domains with SSL certificates to use HTTPS')
+ expect(page).not_to have_button('Save')
+ end
+ end
+ end
+
describe 'Remove page' do
context 'when user is the owner' do
let(:project) { create :project, :repository }
diff --git a/spec/features/projects/tree/tree_show_spec.rb b/spec/features/projects/tree/tree_show_spec.rb
index c8a17871508..c4b3fb9d171 100644
--- a/spec/features/projects/tree/tree_show_spec.rb
+++ b/spec/features/projects/tree/tree_show_spec.rb
@@ -25,4 +25,18 @@ feature 'Projects tree' do
expect(page).to have_selector('.label-lfs', text: 'LFS')
end
end
+
+ context 'web IDE', :js do
+ before do
+ visit project_tree_path(project, File.join('master', 'bar'))
+
+ click_link 'Web IDE'
+
+ find('.ide-file-list')
+ end
+
+ it 'opens folder in IDE' do
+ expect(page).to have_selector('.is-open', text: 'bar')
+ end
+ end
end
diff --git a/spec/features/read_only_spec.rb b/spec/features/read_only_spec.rb
new file mode 100644
index 00000000000..8bfaf558466
--- /dev/null
+++ b/spec/features/read_only_spec.rb
@@ -0,0 +1,25 @@
+require 'rails_helper'
+
+describe 'read-only message' do
+ set(:user) { create(:user) }
+
+ before do
+ sign_in(user)
+ end
+
+ it 'shows read-only banner when database is read-only' do
+ allow(Gitlab::Database).to receive(:read_only?).and_return(true)
+
+ visit root_dashboard_path
+
+ expect(page).to have_content('You are on a read-only GitLab instance.')
+ end
+
+ it 'does not show read-only banner when database is able to read-write' do
+ allow(Gitlab::Database).to receive(:read_only?).and_return(false)
+
+ visit root_dashboard_path
+
+ expect(page).not_to have_content('You are on a read-only GitLab instance.')
+ end
+end
diff --git a/spec/initializers/6_validations_spec.rb b/spec/initializers/6_validations_spec.rb
index 83283f03940..1dc307ea922 100644
--- a/spec/initializers/6_validations_spec.rb
+++ b/spec/initializers/6_validations_spec.rb
@@ -15,7 +15,7 @@ describe '6_validations' do
describe 'validate_storages_config' do
context 'with correct settings' do
before do
- mock_storages('foo' => { 'path' => 'tmp/tests/paths/a/b/c' }, 'bar' => { 'path' => 'tmp/tests/paths/a/b/d' })
+ mock_storages('foo' => Gitlab::GitalyClient::StorageSettings.new('path' => 'tmp/tests/paths/a/b/c'), 'bar' => Gitlab::GitalyClient::StorageSettings.new('path' => 'tmp/tests/paths/a/b/d'))
end
it 'passes through' do
@@ -25,7 +25,7 @@ describe '6_validations' do
context 'when one of the settings is incorrect' do
before do
- mock_storages('foo' => { 'path' => 'tmp/tests/paths/a/b/c', 'failure_count_threshold' => 'not a number' })
+ mock_storages('foo' => Gitlab::GitalyClient::StorageSettings.new('path' => 'tmp/tests/paths/a/b/c', 'failure_count_threshold' => 'not a number'))
end
it 'throws an error' do
@@ -35,7 +35,7 @@ describe '6_validations' do
context 'with invalid storage names' do
before do
- mock_storages('name with spaces' => { 'path' => 'tmp/tests/paths/a/b/c' })
+ mock_storages('name with spaces' => Gitlab::GitalyClient::StorageSettings.new('path' => 'tmp/tests/paths/a/b/c'))
end
it 'throws an error' do
@@ -67,7 +67,7 @@ describe '6_validations' do
describe 'validate_storages_paths' do
context 'with correct settings' do
before do
- mock_storages('foo' => { 'path' => 'tmp/tests/paths/a/b/c' }, 'bar' => { 'path' => 'tmp/tests/paths/a/b/d' })
+ mock_storages('foo' => Gitlab::GitalyClient::StorageSettings.new('path' => 'tmp/tests/paths/a/b/c'), 'bar' => Gitlab::GitalyClient::StorageSettings.new('path' => 'tmp/tests/paths/a/b/d'))
end
it 'passes through' do
@@ -77,7 +77,7 @@ describe '6_validations' do
context 'with nested storage paths' do
before do
- mock_storages('foo' => { 'path' => 'tmp/tests/paths/a/b/c' }, 'bar' => { 'path' => 'tmp/tests/paths/a/b/c/d' })
+ mock_storages('foo' => Gitlab::GitalyClient::StorageSettings.new('path' => 'tmp/tests/paths/a/b/c'), 'bar' => Gitlab::GitalyClient::StorageSettings.new('path' => 'tmp/tests/paths/a/b/c/d'))
end
it 'throws an error' do
@@ -87,7 +87,7 @@ describe '6_validations' do
context 'with similar but un-nested storage paths' do
before do
- mock_storages('foo' => { 'path' => 'tmp/tests/paths/a/b/c' }, 'bar' => { 'path' => 'tmp/tests/paths/a/b/c2' })
+ mock_storages('foo' => Gitlab::GitalyClient::StorageSettings.new('path' => 'tmp/tests/paths/a/b/c'), 'bar' => Gitlab::GitalyClient::StorageSettings.new('path' => 'tmp/tests/paths/a/b/c2'))
end
it 'passes through' do
@@ -97,7 +97,7 @@ describe '6_validations' do
describe 'inaccessible storage' do
before do
- mock_storages('foo' => { 'path' => 'tmp/tests/a/path/that/does/not/exist' })
+ mock_storages('foo' => Gitlab::GitalyClient::StorageSettings.new('path' => 'tmp/tests/a/path/that/does/not/exist'))
end
it 'passes through with a warning' do
diff --git a/spec/initializers/settings_spec.rb b/spec/initializers/settings_spec.rb
index 838ca9fabef..57f5adbbc40 100644
--- a/spec/initializers/settings_spec.rb
+++ b/spec/initializers/settings_spec.rb
@@ -1,5 +1,5 @@
require 'spec_helper'
-require_relative '../../config/initializers/1_settings'
+require_relative '../../config/initializers/1_settings' unless defined?(Settings)
describe Settings do
describe '#ldap' do
diff --git a/spec/javascripts/notes_spec.js b/spec/javascripts/notes_spec.js
index 8f317b06792..1858d6b6474 100644
--- a/spec/javascripts/notes_spec.js
+++ b/spec/javascripts/notes_spec.js
@@ -549,6 +549,20 @@ import timeoutPromise from './helpers/set_timeout_promise_helper';
});
});
+ it('should disable the submit button when comment button is clicked', (done) => {
+ expect($form.find('.js-comment-submit-button').is(':disabled')).toEqual(false);
+
+ mockNotesPost();
+ $('.js-comment-button').click();
+ expect($form.find('.js-comment-submit-button').is(':disabled')).toEqual(true);
+
+ setTimeout(() => {
+ expect($form.find('.js-comment-submit-button').is(':disabled')).toEqual(false);
+
+ done();
+ });
+ });
+
it('should show actual note element when new comment is done posting', (done) => {
mockNotesPost();
diff --git a/spec/javascripts/performance_bar/components/detailed_metric_spec.js b/spec/javascripts/performance_bar/components/detailed_metric_spec.js
index eee0210a2a9..c4611dc7662 100644
--- a/spec/javascripts/performance_bar/components/detailed_metric_spec.js
+++ b/spec/javascripts/performance_bar/components/detailed_metric_spec.js
@@ -20,16 +20,8 @@ describe('detailedMetric', () => {
});
});
- it('does not display details', () => {
- expect(vm.$el.innerText).not.toContain('/');
- });
-
- it('does not display the modal', () => {
- expect(vm.$el.querySelector('.performance-bar-modal')).toBeNull();
- });
-
- it('displays the metric name', () => {
- expect(vm.$el.innerText).toContain('gitaly');
+ it('does not render the element', () => {
+ expect(vm.$el.innerHTML).toEqual(undefined);
});
});
diff --git a/spec/javascripts/vue_shared/components/modal_spec.js b/spec/javascripts/vue_shared/components/deprecated_modal_spec.js
index d01a94c25e5..59d4e549a91 100644
--- a/spec/javascripts/vue_shared/components/modal_spec.js
+++ b/spec/javascripts/vue_shared/components/deprecated_modal_spec.js
@@ -1,11 +1,11 @@
import $ from 'jquery';
import Vue from 'vue';
-import modal from '~/vue_shared/components/modal.vue';
+import DeprecatedModal from '~/vue_shared/components/deprecated_modal.vue';
import mountComponent from 'spec/helpers/vue_mount_component_helper';
-const modalComponent = Vue.extend(modal);
+const modalComponent = Vue.extend(DeprecatedModal);
-describe('Modal', () => {
+describe('DeprecatedModal', () => {
let vm;
afterEach(() => {
diff --git a/spec/lib/backup/repository_spec.rb b/spec/lib/backup/repository_spec.rb
index a9b5ed1112a..03573c304aa 100644
--- a/spec/lib/backup/repository_spec.rb
+++ b/spec/lib/backup/repository_spec.rb
@@ -33,7 +33,7 @@ describe Backup::Repository do
let(:timestamp) { Time.utc(2017, 3, 22) }
let(:temp_dirs) do
Gitlab.config.repositories.storages.map do |name, storage|
- File.join(storage['path'], '..', 'repositories.old.' + timestamp.to_i.to_s)
+ File.join(storage.legacy_disk_path, '..', 'repositories.old.' + timestamp.to_i.to_s)
end
end
diff --git a/spec/lib/banzai/filter/issuable_state_filter_spec.rb b/spec/lib/banzai/filter/issuable_state_filter_spec.rb
index 17347768a49..a5373517ac8 100644
--- a/spec/lib/banzai/filter/issuable_state_filter_spec.rb
+++ b/spec/lib/banzai/filter/issuable_state_filter_spec.rb
@@ -8,6 +8,7 @@ describe Banzai::Filter::IssuableStateFilter do
let(:context) { { current_user: user, issuable_state_filter_enabled: true } }
let(:closed_issue) { create_issue(:closed) }
let(:project) { create(:project, :public) }
+ let(:group) { create(:group) }
let(:other_project) { create(:project, :public) }
def create_link(text, data)
@@ -77,6 +78,13 @@ describe Banzai::Filter::IssuableStateFilter do
expect(doc.css('a').last.text).to eq("#{closed_issue.to_reference(other_project)} (closed)")
end
+ it 'handles references from group scopes' do
+ link = create_link(closed_issue.to_reference(other_project), issue: closed_issue.id, reference_type: 'issue')
+ doc = filter(link, context.merge(project: nil, group: group))
+
+ expect(doc.css('a').last.text).to eq("#{closed_issue.to_reference(other_project)} (closed)")
+ end
+
it 'skips cross project references if the user cannot read cross project' do
expect(Ability).to receive(:allowed?).with(user, :read_cross_project) { false }
link = create_link(closed_issue.to_reference(other_project), issue: closed_issue.id, reference_type: 'issue')
diff --git a/spec/lib/gitlab/bare_repository_import/repository_spec.rb b/spec/lib/gitlab/bare_repository_import/repository_spec.rb
index 5cb1f4deb5f..0dc3705825d 100644
--- a/spec/lib/gitlab/bare_repository_import/repository_spec.rb
+++ b/spec/lib/gitlab/bare_repository_import/repository_spec.rb
@@ -54,7 +54,7 @@ describe ::Gitlab::BareRepositoryImport::Repository do
context 'hashed storage' do
let(:gitlab_shell) { Gitlab::Shell.new }
let(:repository_storage) { 'default' }
- let(:root_path) { Gitlab.config.repositories.storages[repository_storage]['path'] }
+ let(:root_path) { Gitlab.config.repositories.storages[repository_storage].legacy_disk_path }
let(:hash) { '6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b' }
let(:hashed_path) { "@hashed/6b/86/6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b" }
let(:repo_path) { File.join(root_path, "#{hashed_path}.git") }
diff --git a/spec/lib/gitlab/health_checks/fs_shards_check_spec.rb b/spec/lib/gitlab/health_checks/fs_shards_check_spec.rb
index 4c1ca4349ea..9dcf272d25e 100644
--- a/spec/lib/gitlab/health_checks/fs_shards_check_spec.rb
+++ b/spec/lib/gitlab/health_checks/fs_shards_check_spec.rb
@@ -26,7 +26,7 @@ describe Gitlab::HealthChecks::FsShardsCheck do
let(:storages_paths) do
{
- default: { path: tmp_dir }
+ default: Gitlab::GitalyClient::StorageSettings.new('path' => tmp_dir)
}.with_indifferent_access
end
@@ -56,7 +56,7 @@ describe Gitlab::HealthChecks::FsShardsCheck do
context 'storage points to not existing folder' do
let(:storages_paths) do
{
- default: { path: 'tmp/this/path/doesnt/exist' }
+ default: Gitlab::GitalyClient::StorageSettings.new('path' => 'tmp/this/path/doesnt/exist')
}.with_indifferent_access
end
@@ -102,7 +102,7 @@ describe Gitlab::HealthChecks::FsShardsCheck do
context 'storage points to not existing folder' do
let(:storages_paths) do
{
- default: { path: 'tmp/this/path/doesnt/exist' }
+ default: Gitlab::GitalyClient::StorageSettings.new('path' => 'tmp/this/path/doesnt/exist')
}.with_indifferent_access
end
diff --git a/spec/lib/gitlab/http_spec.rb b/spec/lib/gitlab/http_spec.rb
new file mode 100644
index 00000000000..b0bc081a3c8
--- /dev/null
+++ b/spec/lib/gitlab/http_spec.rb
@@ -0,0 +1,49 @@
+require 'spec_helper'
+
+describe Gitlab::HTTP do
+ describe 'allow_local_requests_from_hooks_and_services is' do
+ before do
+ WebMock.stub_request(:get, /.*/).to_return(status: 200, body: 'Success')
+ end
+
+ context 'disabled' do
+ before do
+ allow(Gitlab::CurrentSettings).to receive(:allow_local_requests_from_hooks_and_services?).and_return(false)
+ end
+
+ it 'deny requests to localhost' do
+ expect { described_class.get('http://localhost:3003') }.to raise_error(URI::InvalidURIError)
+ end
+
+ it 'deny requests to private network' do
+ expect { described_class.get('http://192.168.1.2:3003') }.to raise_error(URI::InvalidURIError)
+ end
+
+ context 'if allow_local_requests set to true' do
+ it 'override the global value and allow requests to localhost or private network' do
+ expect { described_class.get('http://localhost:3003', allow_local_requests: true) }.not_to raise_error
+ end
+ end
+ end
+
+ context 'enabled' do
+ before do
+ allow(Gitlab::CurrentSettings).to receive(:allow_local_requests_from_hooks_and_services?).and_return(true)
+ end
+
+ it 'allow requests to localhost' do
+ expect { described_class.get('http://localhost:3003') }.not_to raise_error
+ end
+
+ it 'allow requests to private network' do
+ expect { described_class.get('http://192.168.1.2:3003') }.not_to raise_error
+ end
+
+ context 'if allow_local_requests set to false' do
+ it 'override the global value and ban requests to localhost or private network' do
+ expect { described_class.get('http://localhost:3003', allow_local_requests: false) }.to raise_error(URI::InvalidURIError)
+ end
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/import_export/safe_model_attributes.yml b/spec/lib/gitlab/import_export/safe_model_attributes.yml
index 0b938892da5..44e4c6ff94b 100644
--- a/spec/lib/gitlab/import_export/safe_model_attributes.yml
+++ b/spec/lib/gitlab/import_export/safe_model_attributes.yml
@@ -458,6 +458,7 @@ Project:
- merge_requests_ff_only_enabled
- merge_requests_rebase_enabled
- jobs_cache_index
+- pages_https_only
Author:
- name
ProjectFeature:
diff --git a/spec/lib/gitlab/omniauth_initializer_spec.rb b/spec/lib/gitlab/omniauth_initializer_spec.rb
new file mode 100644
index 00000000000..d808b4d49e0
--- /dev/null
+++ b/spec/lib/gitlab/omniauth_initializer_spec.rb
@@ -0,0 +1,65 @@
+require 'spec_helper'
+
+describe Gitlab::OmniauthInitializer do
+ let(:devise_config) { class_double(Devise) }
+
+ subject { described_class.new(devise_config) }
+
+ describe '#execute' do
+ it 'configures providers from array' do
+ generic_config = { 'name' => 'generic' }
+
+ expect(devise_config).to receive(:omniauth).with(:generic)
+
+ subject.execute([generic_config])
+ end
+
+ it 'allows "args" array for app_id and app_secret' do
+ legacy_config = { 'name' => 'legacy', 'args' => %w(123 abc) }
+
+ expect(devise_config).to receive(:omniauth).with(:legacy, '123', 'abc')
+
+ subject.execute([legacy_config])
+ end
+
+ it 'passes app_id and app_secret as additional arguments' do
+ twitter_config = { 'name' => 'twitter', 'app_id' => '123', 'app_secret' => 'abc' }
+
+ expect(devise_config).to receive(:omniauth).with(:twitter, '123', 'abc')
+
+ subject.execute([twitter_config])
+ end
+
+ it 'passes "args" hash as symbolized hash argument' do
+ hash_config = { 'name' => 'hash', 'args' => { 'custom' => 'format' } }
+
+ expect(devise_config).to receive(:omniauth).with(:hash, custom: 'format')
+
+ subject.execute([hash_config])
+ end
+
+ it 'configures fail_with_empty_uid for shibboleth' do
+ shibboleth_config = { 'name' => 'shibboleth', 'args' => {} }
+
+ expect(devise_config).to receive(:omniauth).with(:shibboleth, fail_with_empty_uid: true)
+
+ subject.execute([shibboleth_config])
+ end
+
+ it 'configures remote_sign_out_handler proc for authentiq' do
+ authentiq_config = { 'name' => 'authentiq', 'args' => {} }
+
+ expect(devise_config).to receive(:omniauth).with(:authentiq, remote_sign_out_handler: an_instance_of(Proc))
+
+ subject.execute([authentiq_config])
+ end
+
+ it 'configures on_single_sign_out proc for cas3' do
+ cas3_config = { 'name' => 'cas3', 'args' => {} }
+
+ expect(devise_config).to receive(:omniauth).with(:cas3, on_single_sign_out: an_instance_of(Proc))
+
+ subject.execute([cas3_config])
+ end
+ end
+end
diff --git a/spec/lib/gitlab/profiler_spec.rb b/spec/lib/gitlab/profiler_spec.rb
index 3d5b56cd5b8..548eb28fe4d 100644
--- a/spec/lib/gitlab/profiler_spec.rb
+++ b/spec/lib/gitlab/profiler_spec.rb
@@ -110,8 +110,8 @@ describe Gitlab::Profiler do
custom_logger.debug('User Load (1.3ms)')
custom_logger.debug('Project Load (10.4ms)')
- expect(custom_logger.load_times_by_model).to eq('User' => 2.5,
- 'Project' => 10.4)
+ expect(custom_logger.load_times_by_model).to eq('User' => [1.2, 1.3],
+ 'Project' => [10.4])
end
it 'logs the backtrace, ignoring lines as appropriate' do
@@ -164,4 +164,24 @@ describe Gitlab::Profiler do
end
end
end
+
+ describe '.log_load_times_by_model' do
+ it 'logs the model, query count, and time by slowest first' do
+ expect(null_logger).to receive(:load_times_by_model).and_return(
+ 'User' => [1.2, 1.3],
+ 'Project' => [10.4]
+ )
+
+ expect(null_logger).to receive(:info).with('Project total (1): 10.4ms')
+ expect(null_logger).to receive(:info).with('User total (2): 2.5ms')
+
+ described_class.log_load_times_by_model(null_logger)
+ end
+
+ it 'does nothing when called with a logger that does not have load times' do
+ expect(null_logger).not_to receive(:info)
+
+ expect(described_class.log_load_times_by_model(null_logger)).to be_nil
+ end
+ end
end
diff --git a/spec/lib/gitlab/repo_path_spec.rb b/spec/lib/gitlab/repo_path_spec.rb
index b67bcc77bd4..f030f371372 100644
--- a/spec/lib/gitlab/repo_path_spec.rb
+++ b/spec/lib/gitlab/repo_path_spec.rb
@@ -48,8 +48,8 @@ describe ::Gitlab::RepoPath do
describe '.strip_storage_path' do
before do
allow(Gitlab.config.repositories).to receive(:storages).and_return({
- 'storage1' => { 'path' => '/foo' },
- 'storage2' => { 'path' => '/bar' }
+ 'storage1' => Gitlab::GitalyClient::StorageSettings.new('path' => '/foo'),
+ 'storage2' => Gitlab::GitalyClient::StorageSettings.new('path' => '/bar')
})
end
diff --git a/spec/lib/gitlab/shell_spec.rb b/spec/lib/gitlab/shell_spec.rb
index 14b59c5e945..ea5ce58e34b 100644
--- a/spec/lib/gitlab/shell_spec.rb
+++ b/spec/lib/gitlab/shell_spec.rb
@@ -405,7 +405,7 @@ describe Gitlab::Shell do
describe '#create_repository' do
shared_examples '#create_repository' do
let(:repository_storage) { 'default' }
- let(:repository_storage_path) { Gitlab.config.repositories.storages[repository_storage]['path'] }
+ let(:repository_storage_path) { Gitlab.config.repositories.storages[repository_storage].legacy_disk_path }
let(:repo_name) { 'project/path' }
let(:created_path) { File.join(repository_storage_path, repo_name + '.git') }
@@ -679,7 +679,7 @@ describe Gitlab::Shell do
describe 'namespace actions' do
subject { described_class.new }
- let(:storage_path) { Gitlab.config.repositories.storages.default.path }
+ let(:storage_path) { Gitlab.config.repositories.storages.default.legacy_disk_path }
describe '#add_namespace' do
it 'creates a namespace' do
diff --git a/spec/lib/gitlab/url_blocker_spec.rb b/spec/lib/gitlab/url_blocker_spec.rb
index d9b3c2350b1..2d35b026485 100644
--- a/spec/lib/gitlab/url_blocker_spec.rb
+++ b/spec/lib/gitlab/url_blocker_spec.rb
@@ -2,6 +2,8 @@ require 'spec_helper'
describe Gitlab::UrlBlocker do
describe '#blocked_url?' do
+ let(:valid_ports) { Project::VALID_IMPORT_PORTS }
+
it 'allows imports from configured web host and port' do
import_url = "http://#{Gitlab.config.gitlab.host}:#{Gitlab.config.gitlab.port}/t.git"
expect(described_class.blocked_url?(import_url)).to be false
@@ -17,7 +19,7 @@ describe Gitlab::UrlBlocker do
end
it 'returns true for bad port' do
- expect(described_class.blocked_url?('https://gitlab.com:25/foo/foo.git')).to be true
+ expect(described_class.blocked_url?('https://gitlab.com:25/foo/foo.git', valid_ports: valid_ports)).to be true
end
it 'returns true for alternative version of 127.0.0.1 (0177.1)' do
@@ -71,6 +73,47 @@ describe Gitlab::UrlBlocker do
it 'returns false for legitimate URL' do
expect(described_class.blocked_url?('https://gitlab.com/foo/foo.git')).to be false
end
+
+ context 'when allow_private_networks is' do
+ let(:private_networks) { ['192.168.1.2', '10.0.0.2', '172.16.0.2'] }
+ let(:fake_domain) { 'www.fakedomain.fake' }
+
+ context 'true (default)' do
+ it 'does not block urls from private networks' do
+ private_networks.each do |ip|
+ stub_domain_resolv(fake_domain, ip)
+
+ expect(described_class).not_to be_blocked_url("http://#{fake_domain}")
+
+ unstub_domain_resolv
+
+ expect(described_class).not_to be_blocked_url("http://#{ip}")
+ end
+ end
+ end
+
+ context 'false' do
+ it 'blocks urls from private networks' do
+ private_networks.each do |ip|
+ stub_domain_resolv(fake_domain, ip)
+
+ expect(described_class).to be_blocked_url("http://#{fake_domain}", allow_private_networks: false)
+
+ unstub_domain_resolv
+
+ expect(described_class).to be_blocked_url("http://#{ip}", allow_private_networks: false)
+ end
+ end
+ end
+
+ def stub_domain_resolv(domain, ip)
+ allow(Addrinfo).to receive(:getaddrinfo).with(domain, any_args).and_return([double(ip_address: ip, ipv4_private?: true)])
+ end
+
+ def unstub_domain_resolv
+ allow(Addrinfo).to receive(:getaddrinfo).and_call_original
+ end
+ end
end
# Resolv does not support resolving UTF-8 domain names
diff --git a/spec/lib/mattermost/command_spec.rb b/spec/lib/mattermost/command_spec.rb
index 369e7b181b9..8ba15ae0f38 100644
--- a/spec/lib/mattermost/command_spec.rb
+++ b/spec/lib/mattermost/command_spec.rb
@@ -4,10 +4,11 @@ describe Mattermost::Command do
let(:params) { { 'token' => 'token', team_id: 'abc' } }
before do
- Mattermost::Session.base_uri('http://mattermost.example.com')
+ session = Mattermost::Session.new(nil)
+ session.base_uri = 'http://mattermost.example.com'
allow_any_instance_of(Mattermost::Client).to receive(:with_session)
- .and_yield(Mattermost::Session.new(nil))
+ .and_yield(session)
end
describe '#create' do
diff --git a/spec/lib/mattermost/session_spec.rb b/spec/lib/mattermost/session_spec.rb
index 3db19d06305..c855643c4d8 100644
--- a/spec/lib/mattermost/session_spec.rb
+++ b/spec/lib/mattermost/session_spec.rb
@@ -15,7 +15,7 @@ describe Mattermost::Session, type: :request do
it { is_expected.to respond_to(:strategy) }
before do
- described_class.base_uri(mattermost_url)
+ subject.base_uri = mattermost_url
end
describe '#with session' do
diff --git a/spec/lib/mattermost/team_spec.rb b/spec/lib/mattermost/team_spec.rb
index 3c8206031cf..2cfa6802612 100644
--- a/spec/lib/mattermost/team_spec.rb
+++ b/spec/lib/mattermost/team_spec.rb
@@ -2,10 +2,11 @@ require 'spec_helper'
describe Mattermost::Team do
before do
- Mattermost::Session.base_uri('http://mattermost.example.com')
+ session = Mattermost::Session.new(nil)
+ session.base_uri = 'http://mattermost.example.com'
allow_any_instance_of(Mattermost::Client).to receive(:with_session)
- .and_yield(Mattermost::Session.new(nil))
+ .and_yield(session)
end
describe '#all' do
diff --git a/spec/migrations/remove_dot_git_from_usernames_spec.rb b/spec/migrations/remove_dot_git_from_usernames_spec.rb
index 129374cb38c..3a88a66a476 100644
--- a/spec/migrations/remove_dot_git_from_usernames_spec.rb
+++ b/spec/migrations/remove_dot_git_from_usernames_spec.rb
@@ -29,7 +29,9 @@ describe RemoveDotGitFromUsernames do
update_namespace(user, 'test.git')
update_namespace(user2, 'test_git')
- storages = { 'default' => 'tmp/tests/custom_repositories' }
+ default_hash = Gitlab.config.repositories.storages.default.to_h
+ default_hash['path'] = 'tmp/tests/custom_repositories'
+ storages = { 'default' => Gitlab::GitalyClient::StorageSettings.new(default_hash) }
allow(Gitlab.config.repositories).to receive(:storages).and_return(storages)
allow(migration).to receive(:route_exists?).with('test_git').and_return(true)
diff --git a/spec/migrations/remove_empty_extern_uid_auth0_identities_spec.rb b/spec/migrations/remove_empty_extern_uid_auth0_identities_spec.rb
new file mode 100644
index 00000000000..441c4295a40
--- /dev/null
+++ b/spec/migrations/remove_empty_extern_uid_auth0_identities_spec.rb
@@ -0,0 +1,22 @@
+require 'spec_helper'
+require Rails.root.join('db', 'post_migrate', '20180220150310_remove_empty_extern_uid_auth0_identities.rb')
+
+describe RemoveEmptyExternUidAuth0Identities, :migration do
+ let(:identities) { table(:identities) }
+
+ before do
+ identities.create(provider: 'auth0', extern_uid: '')
+ identities.create(provider: 'auth0', extern_uid: 'valid')
+ identities.create(provider: 'github', extern_uid: '')
+
+ migrate!
+ end
+
+ it 'leaves the correct auth0 identity' do
+ expect(identities.where(provider: 'auth0').pluck(:extern_uid)).to eq(['valid'])
+ end
+
+ it 'leaves the correct github identity' do
+ expect(identities.where(provider: 'github').count).to eq(1)
+ end
+end
diff --git a/spec/models/group_spec.rb b/spec/models/group_spec.rb
index abfc0896a41..d620943693c 100644
--- a/spec/models/group_spec.rb
+++ b/spec/models/group_spec.rb
@@ -240,7 +240,7 @@ describe Group do
it "is false if avatar is html page" do
group.update_attribute(:avatar, 'uploads/avatar.html')
- expect(group.avatar_type).to eq(["only images allowed"])
+ expect(group.avatar_type).to eq(["file format is not supported. Please try one of the following supported formats: png, jpg, jpeg, gif, bmp, tiff"])
end
end
diff --git a/spec/models/namespace_spec.rb b/spec/models/namespace_spec.rb
index ee142718f7e..62e95a622eb 100644
--- a/spec/models/namespace_spec.rb
+++ b/spec/models/namespace_spec.rb
@@ -305,7 +305,7 @@ describe Namespace do
end
describe '#rm_dir', 'callback' do
- let(:repository_storage_path) { Gitlab.config.repositories.storages.default['path'] }
+ let(:repository_storage_path) { Gitlab.config.repositories.storages.default.legacy_disk_path }
let(:path_in_dir) { File.join(repository_storage_path, namespace.full_path) }
let(:deleted_path) { namespace.full_path.gsub(namespace.path, "#{namespace.full_path}+#{namespace.id}+deleted") }
let(:deleted_path_in_dir) { File.join(repository_storage_path, deleted_path) }
diff --git a/spec/models/pages_domain_spec.rb b/spec/models/pages_domain_spec.rb
index 95713d8b85b..4b85c5e8720 100644
--- a/spec/models/pages_domain_spec.rb
+++ b/spec/models/pages_domain_spec.rb
@@ -18,24 +18,63 @@ describe PagesDomain do
it { is_expected.to validate_uniqueness_of(:domain).case_insensitive }
end
- {
- 'my.domain.com' => true,
- '123.456.789' => true,
- '0x12345.com' => true,
- '0123123' => true,
- '_foo.com' => false,
- 'reserved.com' => false,
- 'a.reserved.com' => false,
- nil => false
- }.each do |value, validity|
- context "domain #{value.inspect} validity" do
- before do
- allow(Settings.pages).to receive(:host).and_return('reserved.com')
+ describe "hostname" do
+ {
+ 'my.domain.com' => true,
+ '123.456.789' => true,
+ '0x12345.com' => true,
+ '0123123' => true,
+ '_foo.com' => false,
+ 'reserved.com' => false,
+ 'a.reserved.com' => false,
+ nil => false
+ }.each do |value, validity|
+ context "domain #{value.inspect} validity" do
+ before do
+ allow(Settings.pages).to receive(:host).and_return('reserved.com')
+ end
+
+ let(:domain) { value }
+
+ it { expect(pages_domain.valid?).to eq(validity) }
+ end
+ end
+ end
+
+ describe "HTTPS-only" do
+ using RSpec::Parameterized::TableSyntax
+
+ let(:domain) { 'my.domain.com' }
+
+ let(:project) do
+ instance_double(Project, pages_https_only?: pages_https_only)
+ end
+
+ let(:pages_domain) do
+ build(:pages_domain, certificate: certificate, key: key).tap do |pd|
+ allow(pd).to receive(:project).and_return(project)
+ pd.valid?
end
+ end
- let(:domain) { value }
+ where(:pages_https_only, :certificate, :key, :errors_on) do
+ attributes = attributes_for(:pages_domain)
+ cert, key = attributes.fetch_values(:certificate, :key)
+
+ true | nil | nil | %i(certificate key)
+ true | cert | nil | %i(key)
+ true | nil | key | %i(certificate key)
+ true | cert | key | []
+ false | nil | nil | []
+ false | cert | nil | %i(key)
+ false | nil | key | %i(key)
+ false | cert | key | []
+ end
- it { expect(pages_domain.valid?).to eq(validity) }
+ with_them do
+ it "is adds the expected errors" do
+ expect(pages_domain.errors.keys).to eq errors_on
+ end
end
end
end
@@ -43,26 +82,26 @@ describe PagesDomain do
describe 'validate certificate' do
subject { domain }
- context 'when only certificate is specified' do
- let(:domain) { build(:pages_domain, :with_certificate) }
+ context 'with matching key' do
+ let(:domain) { build(:pages_domain) }
- it { is_expected.not_to be_valid }
+ it { is_expected.to be_valid }
end
- context 'when only key is specified' do
- let(:domain) { build(:pages_domain, :with_key) }
+ context 'when no certificate is specified' do
+ let(:domain) { build(:pages_domain, :without_certificate) }
it { is_expected.not_to be_valid }
end
- context 'with matching key' do
- let(:domain) { build(:pages_domain, :with_certificate, :with_key) }
+ context 'when no key is specified' do
+ let(:domain) { build(:pages_domain, :without_key) }
- it { is_expected.to be_valid }
+ it { is_expected.not_to be_valid }
end
context 'for not matching key' do
- let(:domain) { build(:pages_domain, :with_missing_chain, :with_key) }
+ let(:domain) { build(:pages_domain, :with_missing_chain) }
it { is_expected.not_to be_valid }
end
@@ -103,30 +142,26 @@ describe PagesDomain do
describe '#url' do
subject { domain.url }
- context 'without the certificate' do
- let(:domain) { build(:pages_domain, certificate: '') }
+ let(:domain) { build(:pages_domain) }
- it { is_expected.to eq("http://#{domain.domain}") }
- end
+ it { is_expected.to eq("https://#{domain.domain}") }
- context 'with a certificate' do
- let(:domain) { build(:pages_domain, :with_certificate) }
+ context 'without the certificate' do
+ let(:domain) { build(:pages_domain, :without_certificate) }
- it { is_expected.to eq("https://#{domain.domain}") }
+ it { is_expected.to eq("http://#{domain.domain}") }
end
end
describe '#has_matching_key?' do
subject { domain.has_matching_key? }
- context 'for matching key' do
- let(:domain) { build(:pages_domain, :with_certificate, :with_key) }
+ let(:domain) { build(:pages_domain) }
- it { is_expected.to be_truthy }
- end
+ it { is_expected.to be_truthy }
context 'for invalid key' do
- let(:domain) { build(:pages_domain, :with_missing_chain, :with_key) }
+ let(:domain) { build(:pages_domain, :with_missing_chain) }
it { is_expected.to be_falsey }
end
@@ -136,7 +171,7 @@ describe PagesDomain do
subject { domain.has_intermediates? }
context 'for self signed' do
- let(:domain) { build(:pages_domain, :with_certificate) }
+ let(:domain) { build(:pages_domain) }
it { is_expected.to be_truthy }
end
@@ -162,7 +197,7 @@ describe PagesDomain do
subject { domain.expired? }
context 'for valid' do
- let(:domain) { build(:pages_domain, :with_certificate) }
+ let(:domain) { build(:pages_domain) }
it { is_expected.to be_falsey }
end
@@ -175,7 +210,7 @@ describe PagesDomain do
end
describe '#subject' do
- let(:domain) { build(:pages_domain, :with_certificate) }
+ let(:domain) { build(:pages_domain) }
subject { domain.subject }
@@ -183,7 +218,7 @@ describe PagesDomain do
end
describe '#certificate_text' do
- let(:domain) { build(:pages_domain, :with_certificate) }
+ let(:domain) { build(:pages_domain) }
subject { domain.certificate_text }
@@ -191,6 +226,18 @@ describe PagesDomain do
it { is_expected.not_to be_empty }
end
+ describe "#https?" do
+ context "when a certificate is present" do
+ subject { build(:pages_domain) }
+ it { is_expected.to be_https }
+ end
+
+ context "when no certificate is present" do
+ subject { build(:pages_domain, :without_certificate) }
+ it { is_expected.not_to be_https }
+ end
+ end
+
describe '#update_daemon' do
it 'runs when the domain is created' do
domain = build(:pages_domain)
@@ -267,29 +314,30 @@ describe PagesDomain do
end
context 'TLS configuration' do
- set(:domain_with_tls) { create(:pages_domain, :with_key, :with_certificate) }
+ set(:domain_without_tls) { create(:pages_domain, :without_certificate, :without_key) }
+ set(:domain) { create(:pages_domain) }
- let(:cert1) { domain_with_tls.certificate }
+ let(:cert1) { domain.certificate }
let(:cert2) { cert1 + ' ' }
- let(:key1) { domain_with_tls.key }
+ let(:key1) { domain.key }
let(:key2) { key1 + ' ' }
it 'updates when added' do
- expect(domain).to receive(:update_daemon)
+ expect(domain_without_tls).to receive(:update_daemon)
- domain.update!(key: key1, certificate: cert1)
+ domain_without_tls.update!(key: key1, certificate: cert1)
end
it 'updates when changed' do
- expect(domain_with_tls).to receive(:update_daemon)
+ expect(domain).to receive(:update_daemon)
- domain_with_tls.update!(key: key2, certificate: cert2)
+ domain.update!(key: key2, certificate: cert2)
end
it 'updates when removed' do
- expect(domain_with_tls).to receive(:update_daemon)
+ expect(domain).to receive(:update_daemon)
- domain_with_tls.update!(key: nil, certificate: nil)
+ domain.update!(key: nil, certificate: nil)
end
end
end
diff --git a/spec/models/project_services/mattermost_slash_commands_service_spec.rb b/spec/models/project_services/mattermost_slash_commands_service_spec.rb
index a5bdf9a9337..05d33cd3874 100644
--- a/spec/models/project_services/mattermost_slash_commands_service_spec.rb
+++ b/spec/models/project_services/mattermost_slash_commands_service_spec.rb
@@ -9,10 +9,11 @@ describe MattermostSlashCommandsService do
let(:user) { create(:user) }
before do
- Mattermost::Session.base_uri("http://mattermost.example.com")
+ session = Mattermost::Session.new(nil)
+ session.base_uri = 'http://mattermost.example.com'
allow_any_instance_of(Mattermost::Client).to receive(:with_session)
- .and_yield(Mattermost::Session.new(nil))
+ .and_yield(session)
end
describe '#configure' do
diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb
index 4cf8d861595..1a7a6e035ea 100644
--- a/spec/models/project_spec.rb
+++ b/spec/models/project_spec.rb
@@ -922,7 +922,7 @@ describe Project do
it 'is false if avatar is html page' do
project.update_attribute(:avatar, 'uploads/avatar.html')
- expect(project.avatar_type).to eq(['only images allowed'])
+ expect(project.avatar_type).to eq(['file format is not supported. Please try one of the following supported formats: png, jpg, jpeg, gif, bmp, tiff'])
end
end
@@ -1101,8 +1101,8 @@ describe Project do
before do
storages = {
- 'default' => { 'path' => 'tmp/tests/repositories' },
- 'picked' => { 'path' => 'tmp/tests/repositories' }
+ 'default' => Gitlab::GitalyClient::StorageSettings.new('path' => 'tmp/tests/repositories'),
+ 'picked' => Gitlab::GitalyClient::StorageSettings.new('path' => 'tmp/tests/repositories')
}
allow(Gitlab.config.repositories).to receive(:storages).and_return(storages)
end
@@ -3479,4 +3479,49 @@ describe Project do
end
end
end
+
+ describe "#pages_https_only?" do
+ subject { build(:project) }
+
+ context "when HTTPS pages are disabled" do
+ it { is_expected.not_to be_pages_https_only }
+ end
+
+ context "when HTTPS pages are enabled", :https_pages_enabled do
+ it { is_expected.to be_pages_https_only }
+ end
+ end
+
+ describe "#pages_https_only? validation", :https_pages_enabled do
+ subject(:project) do
+ # set-up dirty object:
+ create(:project, pages_https_only: false).tap do |p|
+ p.pages_https_only = true
+ end
+ end
+
+ context "when no domains are associated" do
+ it { is_expected.to be_valid }
+ end
+
+ context "when domains including keys and certificates are associated" do
+ before do
+ allow(project)
+ .to receive(:pages_domains)
+ .and_return([instance_double(PagesDomain, https?: true)])
+ end
+
+ it { is_expected.to be_valid }
+ end
+
+ context "when domains including no keys or certificates are associated" do
+ before do
+ allow(project)
+ .to receive(:pages_domains)
+ .and_return([instance_double(PagesDomain, https?: false)])
+ end
+
+ it { is_expected.not_to be_valid }
+ end
+ end
end
diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb
index 5680eb24985..c61674fff13 100644
--- a/spec/models/user_spec.rb
+++ b/spec/models/user_spec.rb
@@ -1222,7 +1222,7 @@ describe User do
it 'is false if avatar is html page' do
user.update_attribute(:avatar, 'uploads/avatar.html')
- expect(user.avatar_type).to eq(['only images allowed'])
+ expect(user.avatar_type).to eq(['file format is not supported. Please try one of the following supported formats: png, jpg, jpeg, gif, bmp, tiff'])
end
end
diff --git a/spec/requests/api/pages_domains_spec.rb b/spec/requests/api/pages_domains_spec.rb
index dc3a116c060..a9ccbb32666 100644
--- a/spec/requests/api/pages_domains_spec.rb
+++ b/spec/requests/api/pages_domains_spec.rb
@@ -1,17 +1,17 @@
require 'rails_helper'
describe API::PagesDomains do
- set(:project) { create(:project, path: 'my.project') }
+ set(:project) { create(:project, path: 'my.project', pages_https_only: false) }
set(:user) { create(:user) }
set(:admin) { create(:admin) }
- set(:pages_domain) { create(:pages_domain, domain: 'www.domain.test', project: project) }
- set(:pages_domain_secure) { create(:pages_domain, :with_certificate, :with_key, domain: 'ssl.domain.test', project: project) }
- set(:pages_domain_expired) { create(:pages_domain, :with_expired_certificate, :with_key, domain: 'expired.domain.test', project: project) }
+ set(:pages_domain) { create(:pages_domain, :without_key, :without_certificate, domain: 'www.domain.test', project: project) }
+ set(:pages_domain_secure) { create(:pages_domain, domain: 'ssl.domain.test', project: project) }
+ set(:pages_domain_expired) { create(:pages_domain, :with_expired_certificate, domain: 'expired.domain.test', project: project) }
- let(:pages_domain_params) { build(:pages_domain, domain: 'www.other-domain.test').slice(:domain) }
- let(:pages_domain_secure_params) { build(:pages_domain, :with_certificate, :with_key, domain: 'ssl.other-domain.test', project: project).slice(:domain, :certificate, :key) }
- let(:pages_domain_secure_key_missmatch_params) {build(:pages_domain, :with_trusted_chain, :with_key, project: project).slice(:domain, :certificate, :key) }
+ let(:pages_domain_params) { build(:pages_domain, :without_key, :without_certificate, domain: 'www.other-domain.test').slice(:domain) }
+ let(:pages_domain_secure_params) { build(:pages_domain, domain: 'ssl.other-domain.test', project: project).slice(:domain, :certificate, :key) }
+ let(:pages_domain_secure_key_missmatch_params) {build(:pages_domain, :with_trusted_chain, project: project).slice(:domain, :certificate, :key) }
let(:pages_domain_secure_missing_chain_params) {build(:pages_domain, :with_missing_chain, project: project).slice(:certificate) }
let(:route) { "/projects/#{project.id}/pages/domains" }
diff --git a/spec/rubocop/cop/gitlab/httparty_spec.rb b/spec/rubocop/cop/gitlab/httparty_spec.rb
new file mode 100644
index 00000000000..510839a21d7
--- /dev/null
+++ b/spec/rubocop/cop/gitlab/httparty_spec.rb
@@ -0,0 +1,74 @@
+require 'spec_helper'
+require 'rubocop'
+require 'rubocop/rspec/support'
+require_relative '../../../../rubocop/cop/gitlab/httparty'
+
+describe RuboCop::Cop::Gitlab::HTTParty do # rubocop:disable RSpec/FilePath
+ include CopHelper
+
+ subject(:cop) { described_class.new }
+
+ shared_examples('registering include offense') do |options|
+ let(:offending_lines) { options[:offending_lines] }
+
+ it 'registers an offense when the class includes HTTParty' do
+ inspect_source(source)
+
+ aggregate_failures do
+ expect(cop.offenses.size).to eq(offending_lines.size)
+ expect(cop.offenses.map(&:line)).to eq(offending_lines)
+ end
+ end
+ end
+
+ shared_examples('registering call offense') do |options|
+ let(:offending_lines) { options[:offending_lines] }
+
+ it 'registers an offense when the class calls HTTParty' do
+ inspect_source(source)
+
+ aggregate_failures do
+ expect(cop.offenses.size).to eq(offending_lines.size)
+ expect(cop.offenses.map(&:line)).to eq(offending_lines)
+ end
+ end
+ end
+
+ context 'when source is a regular module' do
+ it_behaves_like 'registering include offense', offending_lines: [2] do
+ let(:source) do
+ <<~RUBY
+ module M
+ include HTTParty
+ end
+ RUBY
+ end
+ end
+ end
+
+ context 'when source is a regular class' do
+ it_behaves_like 'registering include offense', offending_lines: [2] do
+ let(:source) do
+ <<~RUBY
+ class Foo
+ include HTTParty
+ end
+ RUBY
+ end
+ end
+ end
+
+ context 'when HTTParty is called' do
+ it_behaves_like 'registering call offense', offending_lines: [3] do
+ let(:source) do
+ <<~RUBY
+ class Foo
+ def bar
+ HTTParty.get('http://example.com')
+ end
+ end
+ RUBY
+ end
+ end
+ end
+end
diff --git a/spec/services/ci/process_pipeline_service_spec.rb b/spec/services/ci/process_pipeline_service_spec.rb
index 0ce41e7c7ee..feb5120bc68 100644
--- a/spec/services/ci/process_pipeline_service_spec.rb
+++ b/spec/services/ci/process_pipeline_service_spec.rb
@@ -9,6 +9,8 @@ describe Ci::ProcessPipelineService, '#execute' do
end
before do
+ stub_ci_pipeline_to_return_yaml_file
+
stub_not_protect_default_branch
project.add_developer(user)
diff --git a/spec/services/projects/create_service_spec.rb b/spec/services/projects/create_service_spec.rb
index 8471467d2fa..4413c6ef83e 100644
--- a/spec/services/projects/create_service_spec.rb
+++ b/spec/services/projects/create_service_spec.rb
@@ -153,7 +153,7 @@ describe Projects::CreateService, '#execute' do
context 'when another repository already exists on disk' do
let(:repository_storage) { 'default' }
- let(:repository_storage_path) { Gitlab.config.repositories.storages[repository_storage]['path'] }
+ let(:repository_storage_path) { Gitlab.config.repositories.storages[repository_storage].legacy_disk_path }
let(:opts) do
{
diff --git a/spec/services/projects/fork_service_spec.rb b/spec/services/projects/fork_service_spec.rb
index d1011b07db6..0f7c46367d0 100644
--- a/spec/services/projects/fork_service_spec.rb
+++ b/spec/services/projects/fork_service_spec.rb
@@ -105,7 +105,7 @@ describe Projects::ForkService do
context 'repository already exists' do
let(:repository_storage) { 'default' }
- let(:repository_storage_path) { Gitlab.config.repositories.storages[repository_storage]['path'] }
+ let(:repository_storage_path) { Gitlab.config.repositories.storages[repository_storage].legacy_disk_path }
before do
gitlab_shell.create_repository(repository_storage, "#{@to_user.namespace.full_path}/#{@from_project.path}")
diff --git a/spec/services/projects/transfer_service_spec.rb b/spec/services/projects/transfer_service_spec.rb
index ce567fe3879..95a6771c59d 100644
--- a/spec/services/projects/transfer_service_spec.rb
+++ b/spec/services/projects/transfer_service_spec.rb
@@ -146,7 +146,7 @@ describe Projects::TransferService do
context 'namespace which contains orphan repository with same projects path name' do
let(:repository_storage) { 'default' }
- let(:repository_storage_path) { Gitlab.config.repositories.storages[repository_storage]['path'] }
+ let(:repository_storage_path) { Gitlab.config.repositories.storages[repository_storage].legacy_disk_path }
before do
group.add_owner(user)
diff --git a/spec/services/projects/update_service_spec.rb b/spec/services/projects/update_service_spec.rb
index f3f97b6b921..f48d466d263 100644
--- a/spec/services/projects/update_service_spec.rb
+++ b/spec/services/projects/update_service_spec.rb
@@ -190,7 +190,7 @@ describe Projects::UpdateService do
context 'when renaming a project' do
let(:repository_storage) { 'default' }
- let(:repository_storage_path) { Gitlab.config.repositories.storages[repository_storage]['path'] }
+ let(:repository_storage_path) { Gitlab.config.repositories.storages[repository_storage].legacy_disk_path }
context 'with legacy storage' do
let(:project) { create(:project, :legacy_storage, :repository, creator: user, namespace: user.namespace) }
@@ -241,6 +241,27 @@ describe Projects::UpdateService do
})
end
end
+
+ context 'when updating #pages_https_only', :https_pages_enabled do
+ subject(:call_service) do
+ update_project(project, admin, pages_https_only: false)
+ end
+
+ it 'updates the attribute' do
+ expect { call_service }
+ .to change { project.pages_https_only? }
+ .to(false)
+ end
+
+ it 'calls Projects::UpdatePagesConfigurationService' do
+ expect(Projects::UpdatePagesConfigurationService)
+ .to receive(:new)
+ .with(project)
+ .and_call_original
+
+ call_service
+ end
+ end
end
describe '#run_auto_devops_pipeline?' do
diff --git a/spec/services/web_hook_service_spec.rb b/spec/services/web_hook_service_spec.rb
index 21910e69d2e..2ef2e61babc 100644
--- a/spec/services/web_hook_service_spec.rb
+++ b/spec/services/web_hook_service_spec.rb
@@ -14,6 +14,20 @@ describe WebHookService do
end
let(:service_instance) { described_class.new(project_hook, data, :push_hooks) }
+ describe '#initialize' do
+ it 'allow_local_requests is true if hook is a SystemHook' do
+ instance = described_class.new(build(:system_hook), data, :system_hook)
+ expect(instance.request_options[:allow_local_requests]).to be_truthy
+ end
+
+ it 'allow_local_requests is false if hook is not a SystemHook' do
+ %i(project_hook service_hook web_hook_log).each do |hook|
+ instance = described_class.new(build(hook), data, hook)
+ expect(instance.request_options[:allow_local_requests]).to be_falsey
+ end
+ end
+ end
+
describe '#execute' do
before do
project.hooks << [project_hook]
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
index 9f6f0204a16..5051cd34564 100644
--- a/spec/spec_helper.rb
+++ b/spec/spec_helper.rb
@@ -197,6 +197,22 @@ RSpec.configure do |config|
Ability.allowed?(*args)
end
end
+
+ config.before(:each, :http_pages_enabled) do |_|
+ allow(Gitlab.config.pages).to receive(:external_http).and_return(['1.1.1.1:80'])
+ end
+
+ config.before(:each, :https_pages_enabled) do |_|
+ allow(Gitlab.config.pages).to receive(:external_https).and_return(['1.1.1.1:443'])
+ end
+
+ config.before(:each, :http_pages_disabled) do |_|
+ allow(Gitlab.config.pages).to receive(:external_http).and_return(false)
+ end
+
+ config.before(:each, :https_pages_disabled) do |_|
+ allow(Gitlab.config.pages).to receive(:external_https).and_return(false)
+ end
end
# add simpler way to match asset paths containing digest strings
diff --git a/spec/support/stored_repositories.rb b/spec/support/stored_repositories.rb
index 52e47ae2d34..21995c89a6e 100644
--- a/spec/support/stored_repositories.rb
+++ b/spec/support/stored_repositories.rb
@@ -4,7 +4,7 @@ RSpec.configure do |config|
end
config.before(:all, :broken_storage) do
- FileUtils.rm_rf Gitlab.config.repositories.storages.broken['path']
+ FileUtils.rm_rf Gitlab.config.repositories.storages.broken.legacy_disk_path
end
config.before(:each, :broken_storage) do
diff --git a/spec/support/stub_configuration.rb b/spec/support/stub_configuration.rb
index 9f08c139322..bad1d34df3a 100644
--- a/spec/support/stub_configuration.rb
+++ b/spec/support/stub_configuration.rb
@@ -50,8 +50,12 @@ module StubConfiguration
# Default storage is always required
messages['default'] ||= Gitlab.config.repositories.storages.default
- messages.each do |storage_name, storage_settings|
- storage_settings['path'] = TestEnv.repos_path unless storage_settings.key?('path')
+ messages.each do |storage_name, storage_hash|
+ if !storage_hash.key?('path') || storage_hash['path'] == Gitlab::GitalyClient::StorageSettings::Deprecated
+ storage_hash['path'] = TestEnv.repos_path
+ end
+
+ messages[storage_name] = Gitlab::GitalyClient::StorageSettings.new(storage_hash.to_h)
end
allow(Gitlab.config.repositories).to receive(:storages).and_return(Settingslogic.new(messages))
diff --git a/spec/support/test_env.rb b/spec/support/test_env.rb
index 01321989f01..f14e69b1041 100644
--- a/spec/support/test_env.rb
+++ b/spec/support/test_env.rb
@@ -225,7 +225,7 @@ module TestEnv
end
def repos_path
- Gitlab.config.repositories.storages.default['path']
+ Gitlab.config.repositories.storages.default.legacy_disk_path
end
def backup_path
diff --git a/spec/tasks/gitlab/backup_rake_spec.rb b/spec/tasks/gitlab/backup_rake_spec.rb
index 168facd51a6..0d24782f317 100644
--- a/spec/tasks/gitlab/backup_rake_spec.rb
+++ b/spec/tasks/gitlab/backup_rake_spec.rb
@@ -195,14 +195,23 @@ describe 'gitlab:app namespace rake task' do
end
context 'multiple repository storages' do
- let(:gitaly_address) { Gitlab.config.repositories.storages.default.gitaly_address }
+ let(:storage_default) do
+ Gitlab::GitalyClient::StorageSettings.new(@default_storage_hash.merge('path' => 'tmp/tests/default_storage'))
+ end
+ let(:test_second_storage) do
+ Gitlab::GitalyClient::StorageSettings.new(@default_storage_hash.merge('path' => 'tmp/tests/custom_storage'))
+ end
let(:storages) do
{
- 'default' => { 'path' => Settings.absolute('tmp/tests/default_storage'), 'gitaly_address' => gitaly_address },
- 'test_second_storage' => { 'path' => Settings.absolute('tmp/tests/custom_storage'), 'gitaly_address' => gitaly_address }
+ 'default' => storage_default,
+ 'test_second_storage' => test_second_storage
}
end
+ before(:all) do
+ @default_storage_hash = Gitlab.config.repositories.storages.default.to_h
+ end
+
before do
# We only need a backup of the repositories for this test
stub_env('SKIP', 'db,uploads,builds,artifacts,lfs,registry')
diff --git a/spec/tasks/gitlab/cleanup_rake_spec.rb b/spec/tasks/gitlab/cleanup_rake_spec.rb
index 9e746ceddd6..2bf873c923f 100644
--- a/spec/tasks/gitlab/cleanup_rake_spec.rb
+++ b/spec/tasks/gitlab/cleanup_rake_spec.rb
@@ -6,13 +6,16 @@ describe 'gitlab:cleanup rake tasks' do
end
describe 'cleanup' do
- let(:gitaly_address) { Gitlab.config.repositories.storages.default.gitaly_address }
let(:storages) do
{
- 'default' => { 'path' => Settings.absolute('tmp/tests/default_storage'), 'gitaly_address' => gitaly_address }
+ 'default' => Gitlab::GitalyClient::StorageSettings.new(@default_storage_hash.merge('path' => 'tmp/tests/default_storage'))
}
end
+ before(:all) do
+ @default_storage_hash = Gitlab.config.repositories.storages.default.to_h
+ end
+
before do
FileUtils.mkdir(Settings.absolute('tmp/tests/default_storage'))
allow(Gitlab.config.repositories).to receive(:storages).and_return(storages)
diff --git a/spec/tasks/gitlab/git_rake_spec.rb b/spec/tasks/gitlab/git_rake_spec.rb
index 9aebf7b0b4a..1efaecc63a5 100644
--- a/spec/tasks/gitlab/git_rake_spec.rb
+++ b/spec/tasks/gitlab/git_rake_spec.rb
@@ -1,10 +1,13 @@
require 'rake_helper'
describe 'gitlab:git rake tasks' do
+ before(:all) do
+ @default_storage_hash = Gitlab.config.repositories.storages.default.to_h
+ end
+
before do
Rake.application.rake_require 'tasks/gitlab/git'
-
- storages = { 'default' => { 'path' => Settings.absolute('tmp/tests/default_storage') } }
+ storages = { 'default' => Gitlab::GitalyClient::StorageSettings.new(@default_storage_hash.merge('path' => 'tmp/tests/default_storage')) }
FileUtils.mkdir_p(Settings.absolute('tmp/tests/default_storage/@hashed/1/2/test.git'))
allow(Gitlab.config.repositories).to receive(:storages).and_return(storages)
diff --git a/spec/tasks/gitlab/gitaly_rake_spec.rb b/spec/tasks/gitlab/gitaly_rake_spec.rb
index 1f4053ff9ad..1e507c0236e 100644
--- a/spec/tasks/gitlab/gitaly_rake_spec.rb
+++ b/spec/tasks/gitlab/gitaly_rake_spec.rb
@@ -99,14 +99,14 @@ describe 'gitlab:gitaly namespace rake task' do
describe 'storage_config' do
it 'prints storage configuration in a TOML format' do
config = {
- 'default' => {
+ 'default' => Gitlab::GitalyClient::StorageSettings.new(
'path' => '/path/to/default',
'gitaly_address' => 'unix:/path/to/my.socket'
- },
- 'nfs_01' => {
+ ),
+ 'nfs_01' => Gitlab::GitalyClient::StorageSettings.new(
'path' => '/path/to/nfs_01',
'gitaly_address' => 'unix:/path/to/my.socket'
- }
+ )
}
allow(Gitlab.config.repositories).to receive(:storages).and_return(config)
allow(Rails.env).to receive(:test?).and_return(false)
@@ -134,7 +134,7 @@ describe 'gitlab:gitaly namespace rake task' do
parsed_output = TomlRB.parse(expected_output)
config.each do |name, params|
- expect(parsed_output['storage']).to include({ 'name' => name, 'path' => params['path'] })
+ expect(parsed_output['storage']).to include({ 'name' => name, 'path' => params.legacy_disk_path })
end
end
end
diff --git a/spec/tasks/gitlab/shell_rake_spec.rb b/spec/tasks/gitlab/shell_rake_spec.rb
index 65155cb044d..4a756c5742d 100644
--- a/spec/tasks/gitlab/shell_rake_spec.rb
+++ b/spec/tasks/gitlab/shell_rake_spec.rb
@@ -11,7 +11,7 @@ describe 'gitlab:shell rake tasks' do
it 'invokes create_hooks task' do
expect(Rake::Task['gitlab:shell:create_hooks']).to receive(:invoke)
- storages = Gitlab.config.repositories.storages.values.map { |rs| rs['path'] }
+ storages = Gitlab.config.repositories.storages.values.map(&:legacy_disk_path)
expect(Kernel).to receive(:system).with('bin/install', *storages).and_call_original
expect(Kernel).to receive(:system).with('bin/compile').and_call_original