summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEugenia Grieff <egrieff@gitlab.com>2019-08-07 12:18:37 +0100
committerEugenia Grieff <egrieff@gitlab.com>2019-08-07 12:18:37 +0100
commite8619bbdd904cbd10cc0a92f44f2044ad572bc10 (patch)
tree58ee3a0f48608cae55e618b41e01fae276dbdb79
parent90dc8b77b75564915eb14df9fe346f90f0ddf880 (diff)
parent84e7bc765c42643e8d1b30e4030172694f33901a (diff)
downloadgitlab-ce-7250-group-bulk-edit-issues-mrs-epics-change-label-ce.tar.gz
-rw-r--r--.gitlab/CODEOWNERS4
-rw-r--r--.gitlab/ci/review.gitlab-ci.yml2
-rw-r--r--Gemfile1
-rw-r--r--Gemfile.lock5
-rw-r--r--app/assets/javascripts/behaviors/preview_markdown.js4
-rw-r--r--app/assets/javascripts/lib/utils/common_utils.js7
-rw-r--r--app/assets/javascripts/monitoring/components/dashboard.vue51
-rw-r--r--app/assets/javascripts/monitoring/components/panel_type.vue41
-rw-r--r--app/assets/javascripts/performance_bar/components/performance_bar_app.vue6
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_actions.vue25
-rw-r--r--app/assets/javascripts/pipelines/mixins/pipelines.js2
-rw-r--r--app/assets/javascripts/vue_shared/components/commit.vue22
-rw-r--r--app/assets/javascripts/vue_shared/components/content_viewer/viewers/image_viewer.vue3
-rw-r--r--app/assets/stylesheets/framework/responsive_tables.scss2
-rw-r--r--app/controllers/concerns/issuable_collections.rb5
-rw-r--r--app/finders/clusters/knative_services_finder.rb16
-rw-r--r--app/finders/clusters/kubernetes_namespace_finder.rb36
-rw-r--r--app/finders/projects/serverless/functions_finder.rb70
-rw-r--r--app/models/active_session.rb6
-rw-r--r--app/models/clusters/applications/prometheus.rb2
-rw-r--r--app/models/clusters/cluster.rb52
-rw-r--r--app/models/clusters/kubernetes_namespace.rb31
-rw-r--r--app/models/clusters/platforms/kubernetes.rb32
-rw-r--r--app/models/concerns/maskable.rb5
-rw-r--r--app/models/concerns/prometheus_adapter.rb6
-rw-r--r--app/models/deploy_key.rb6
-rw-r--r--app/models/deploy_keys_project.rb3
-rw-r--r--app/models/environment.rb9
-rw-r--r--app/models/list.rb3
-rw-r--r--app/models/merge_request_diff.rb6
-rw-r--r--app/models/project.rb19
-rw-r--r--app/models/project_services/mock_deployment_service.rb2
-rw-r--r--app/models/project_services/prometheus_service.rb9
-rw-r--r--app/models/user.rb11
-rw-r--r--app/presenters/blob_presenter.rb19
-rw-r--r--app/presenters/blobs/unfold_presenter.rb23
-rw-r--r--app/presenters/projects/settings/deploy_keys_presenter.rb40
-rw-r--r--app/serializers/deploy_key_entity.rb7
-rw-r--r--app/services/clusters/build_kubernetes_namespace_service.rb35
-rw-r--r--app/services/clusters/create_service.rb7
-rw-r--r--app/services/clusters/gcp/kubernetes/create_or_update_namespace_service.rb5
-rw-r--r--app/services/projects/destroy_service.rb1
-rw-r--r--app/services/prometheus/proxy_service.rb2
-rw-r--r--app/views/layouts/_google_analytics.html.haml20
-rw-r--r--app/views/layouts/_head.html.haml3
-rw-r--r--app/views/layouts/_init_auto_complete.html.haml10
-rw-r--r--app/views/layouts/_init_client_detection_flags.html.haml8
-rw-r--r--app/views/layouts/_piwik.html.haml28
-rw-r--r--app/views/layouts/errors.html.haml16
-rw-r--r--app/views/layouts/group.html.haml6
-rw-r--r--app/views/layouts/nav/_dashboard.html.haml5
-rw-r--r--app/views/layouts/project.html.haml6
-rw-r--r--app/views/layouts/snippets.html.haml6
-rw-r--r--app/views/projects/_export.html.haml1
-rw-r--r--app/views/projects/merge_requests/show.html.haml12
-rw-r--r--changelogs/unreleased/31434-make-issue-boards-importable.yml5
-rw-r--r--changelogs/unreleased/43080-speed-up-deploy-keys.yml5
-rw-r--r--changelogs/unreleased/52494-separate-namespace-per-project-environment-slug.yml5
-rw-r--r--changelogs/unreleased/64608-double-tooltips.yml5
-rw-r--r--changelogs/unreleased/65152-selective-highlight.yml5
-rw-r--r--changelogs/unreleased/65263-manual-action.yml5
-rw-r--r--changelogs/unreleased/65660-update-karma-to-4-2-0.yml5
-rw-r--r--changelogs/unreleased/65671-update-mini_magick-to-4-9-5.yml5
-rw-r--r--changelogs/unreleased/khair1-master-patch-79459.yml5
-rw-r--r--changelogs/unreleased/mc-feature-add-at-colon-variable-masking.yml5
-rw-r--r--changelogs/unreleased/remove-peek-gc.yml5
-rw-r--r--changelogs/unreleased/sh-disable-registry-delete.yml5
-rw-r--r--changelogs/unreleased/sh-support-csp-nonce.yml5
-rw-r--r--config/gitlab.yml.example23
-rw-r--r--config/initializers/1_settings.rb1
-rw-r--r--config/initializers/content_security_policy.rb15
-rw-r--r--config/initializers/peek.rb5
-rw-r--r--db/migrate/20190627100221_add_mr_productivity_metrics.rb14
-rw-r--r--db/migrate/20190712040400_add_environment_id_to_clusters_kubernetes_namespaces.rb10
-rw-r--r--db/migrate/20190712040412_index_clusters_kubernetes_namespaces_on_environment_id.rb18
-rw-r--r--db/migrate/20190712064021_add_namespace_per_environment_flag_to_clusters.rb20
-rw-r--r--db/post_migrate/20190802235445_add_index_on_id_and_type_and_public_to_keys.rb23
-rw-r--r--db/schema.rb14
-rw-r--r--doc/administration/auth/img/google_secure_ldap_add_step_1.pngbin28849 -> 9083 bytes
-rw-r--r--doc/administration/auth/img/google_secure_ldap_add_step_2.pngbin82115 -> 27207 bytes
-rw-r--r--doc/administration/auth/img/google_secure_ldap_client_settings.pngbin63959 -> 21302 bytes
-rw-r--r--doc/administration/geo/disaster_recovery/img/checksum-differences-admin-project-page.pngbin202130 -> 74553 bytes
-rw-r--r--doc/administration/geo/disaster_recovery/img/checksum-differences-admin-projects.pngbin85997 -> 28817 bytes
-rw-r--r--doc/administration/geo/replication/img/geo_architecture.pngbin116506 -> 53225 bytes
-rw-r--r--doc/administration/gitaly/index.md7
-rw-r--r--doc/administration/high_availability/img/fully-distributed.pngbin46918 -> 46691 bytes
-rw-r--r--doc/administration/high_availability/img/horizontal.pngbin18660 -> 18179 bytes
-rw-r--r--doc/administration/high_availability/img/hybrid.pngbin20698 -> 20693 bytes
-rw-r--r--doc/administration/high_availability/monitoring_node.md2
-rw-r--r--doc/administration/high_availability/nfs.md5
-rw-r--r--doc/administration/img/custom_hooks_error_msg.pngbin80442 -> 31281 bytes
-rw-r--r--doc/administration/monitoring/performance/grafana_configuration.md2
-rw-r--r--doc/administration/monitoring/performance/img/performance_bar.pngbin113617 -> 33642 bytes
-rw-r--r--doc/administration/monitoring/performance/img/performance_bar_gitaly_calls.pngbin203373 -> 83212 bytes
-rw-r--r--doc/administration/monitoring/performance/img/performance_bar_redis_calls.pngbin191734 -> 70859 bytes
-rw-r--r--doc/administration/monitoring/performance/img/performance_bar_rugged_calls.pngbin274852 -> 105305 bytes
-rw-r--r--doc/administration/monitoring/performance/img/performance_bar_sql_queries.pngbin338952 -> 143074 bytes
-rw-r--r--doc/administration/monitoring/performance/img/request_profile_result.pngbin33920 -> 11451 bytes
-rw-r--r--doc/administration/monitoring/performance/performance_bar.md1
-rw-r--r--doc/administration/operations/img/sidekiq-cluster.pngbin61923 -> 22576 bytes
-rw-r--r--doc/administration/pages/img/lets_encrypt_integration_v12_1.pngbin98409 -> 33137 bytes
-rw-r--r--doc/administration/troubleshooting/elasticsearch.md28
-rw-r--r--doc/api/README.md4
-rw-r--r--doc/api/merge_request_approvals.md18
-rw-r--r--doc/api/releases/img/upcoming_release_v12_1.pngbin22635 -> 7407 bytes
-rw-r--r--doc/ci/docker/using_docker_build.md204
-rw-r--r--doc/ci/examples/end_to_end_testing_webdriverio/img/deployed_dependency_update.pngbin67788 -> 26301 bytes
-rw-r--r--doc/ci/img/collapsible_log.pngbin174697 -> 60771 bytes
-rw-r--r--doc/ci/img/deployments_view.pngbin58498 -> 23501 bytes
-rw-r--r--doc/ci/img/environments_available.pngbin20410 -> 8582 bytes
-rw-r--r--doc/ci/img/environments_mr_review_app.pngbin30140 -> 13474 bytes
-rw-r--r--doc/ci/img/manual_job_variables.pngbin429891 -> 111239 bytes
-rw-r--r--doc/ci/introduction/img/gitlab_workflow_example_11_9.pngbin71292 -> 70061 bytes
-rw-r--r--doc/ci/introduction/img/gitlab_workflow_example_extended_11_11.pngbin139184 -> 136497 bytes
-rw-r--r--doc/ci/merge_request_pipelines/img/merge_request.pngbin14044 -> 5292 bytes
-rw-r--r--doc/ci/merge_request_pipelines/pipelines_for_merged_results/img/merge_request_pipeline.pngbin10152 -> 4394 bytes
-rw-r--r--doc/ci/merge_request_pipelines/pipelines_for_merged_results/img/merge_request_pipeline_config.pngbin10889 -> 5296 bytes
-rw-r--r--doc/ci/merge_request_pipelines/pipelines_for_merged_results/merge_trains/img/merge_train_cancel_v12_0.pngbin19577 -> 7654 bytes
-rw-r--r--doc/ci/merge_request_pipelines/pipelines_for_merged_results/merge_trains/img/merge_train_config_v12_0.pngbin24267 -> 9012 bytes
-rw-r--r--doc/ci/merge_request_pipelines/pipelines_for_merged_results/merge_trains/img/merge_train_failure.pngbin63661 -> 23899 bytes
-rw-r--r--doc/ci/merge_request_pipelines/pipelines_for_merged_results/merge_trains/img/merge_train_immediate_merge.pngbin30760 -> 13038 bytes
-rw-r--r--doc/ci/merge_request_pipelines/pipelines_for_merged_results/merge_trains/img/merge_train_position_v12_0.pngbin18121 -> 6152 bytes
-rw-r--r--doc/ci/merge_request_pipelines/pipelines_for_merged_results/merge_trains/img/merge_train_start_v12_0.pngbin8365 -> 3548 bytes
-rw-r--r--doc/ci/merge_request_pipelines/pipelines_for_merged_results/merge_trains/img/merge_train_start_when_pipeline_succeeds_v12_0.pngbin10323 -> 4337 bytes
-rw-r--r--doc/ci/review_apps/img/review_button.pngbin58187 -> 16524 bytes
-rw-r--r--doc/ci/variables/README.md2
-rw-r--r--doc/ci/variables/img/custom_variables_output.pngbin89185 -> 32344 bytes
-rw-r--r--doc/ci/variables/img/new_custom_variables_example.pngbin216497 -> 68252 bytes
-rw-r--r--doc/ci/variables/img/override_variable_manual_pipeline.pngbin41714 -> 13885 bytes
-rw-r--r--doc/ci/variables/img/variable_types_usage_example.pngbin67003 -> 21983 bytes
-rw-r--r--doc/customization/branded_login_page.md35
-rw-r--r--doc/customization/branded_page_and_email_header.md34
-rw-r--r--doc/customization/favicon.md31
-rw-r--r--doc/customization/help_message.md37
-rw-r--r--doc/customization/help_message/help_text.pngbin86118 -> 38521 bytes
-rw-r--r--doc/customization/index.md20
-rw-r--r--doc/customization/libravatar.md65
-rw-r--r--doc/customization/new_project_page.md36
-rw-r--r--doc/customization/system_header_and_footer_messages/appearance.pngbin124214 -> 32295 bytes
-rw-r--r--doc/development/fe_guide/architecture.md2
-rw-r--r--doc/development/fe_guide/graphql.md3
-rw-r--r--doc/development/fe_guide/style_guide_js.md6
-rw-r--r--doc/development/img/architecture_simplified.pngbin61590 -> 34330 bytes
-rw-r--r--doc/development/img/distributed_tracing_jaeger_ui.pngbin1032713 -> 546331 bytes
-rw-r--r--doc/development/img/distributed_tracing_performance_bar.pngbin108809 -> 34370 bytes
-rw-r--r--doc/development/new_fe_guide/development/performance.md2
-rw-r--r--doc/development/new_fe_guide/development/testing.md2
-rw-r--r--doc/development/ux_guide/animation.md4
-rw-r--r--doc/development/ux_guide/illustrations.md4
-rw-r--r--doc/install/docker.md2
-rw-r--r--doc/integration/img/limit_namespace_filter.pngbin12777 -> 4531 bytes
-rw-r--r--doc/integration/img/limit_namespaces_projects_options.pngbin22650 -> 7850 bytes
-rw-r--r--doc/integration/img/salesforce_app_details.pngbin116022 -> 33688 bytes
-rw-r--r--doc/integration/img/salesforce_app_secret_details.pngbin199643 -> 56921 bytes
-rw-r--r--doc/integration/img/salesforce_oauth_app_details.pngbin171542 -> 50259 bytes
-rw-r--r--doc/security/img/outbound_requests_section_v12_2.pngbin21108 -> 6303 bytes
-rw-r--r--doc/security/rack_attack.md26
-rw-r--r--doc/topics/authentication/index.md2
-rw-r--r--doc/topics/git/useful_git_commands.md6
-rw-r--r--doc/user/admin_area/img/abuse_report_blocked_user.pngbin13821 -> 7393 bytes
-rw-r--r--doc/user/admin_area/img/abuse_reports_page.pngbin215813 -> 86180 bytes
-rw-r--r--doc/user/admin_area/img/broadcast_messages.pngbin68535 -> 21458 bytes
-rw-r--r--doc/user/admin_area/img/license_details.pngbin119290 -> 65130 bytes
-rw-r--r--doc/user/admin_area/settings/email.md11
-rw-r--r--doc/user/admin_area/settings/img/additional_minutes.pngbin32045 -> 12668 bytes
-rw-r--r--doc/user/admin_area/settings/img/admin_required_pipeline.pngbin64548 -> 22587 bytes
-rw-r--r--doc/user/admin_area/settings/img/buy_btn.pngbin26960 -> 10917 bytes
-rw-r--r--doc/user/admin_area/settings/img/buy_minutes_card.pngbin29329 -> 11875 bytes
-rw-r--r--doc/user/admin_area/settings/img/email_confirmation.pngbin14260 -> 5239 bytes
-rw-r--r--doc/user/admin_area/settings/img/email_settings.pngbin53267 -> 0 bytes
-rw-r--r--doc/user/admin_area/settings/img/user_and_ip_rate_limits.pngbin232777 -> 64725 bytes
-rw-r--r--doc/user/application_security/img/create_issue_with_list_hover.pngbin106954 -> 36833 bytes
-rw-r--r--doc/user/application_security/img/dismissed_info.pngbin20244 -> 7847 bytes
-rw-r--r--doc/user/application_security/img/interactive_reports.pngbin93910 -> 29814 bytes
-rw-r--r--doc/user/application_security/img/vulnerability_solution.pngbin3421 -> 3419 bytes
-rw-r--r--doc/user/application_security/license_management/img/license_management_add_license.pngbin87049 -> 24247 bytes
-rw-r--r--doc/user/application_security/license_management/img/license_management_decision.pngbin5981 -> 5975 bytes
-rw-r--r--doc/user/application_security/license_management/img/license_management_search.pngbin104278 -> 28237 bytes
-rw-r--r--doc/user/application_security/license_management/img/license_management_settings.pngbin171592 -> 44790 bytes
-rw-r--r--doc/user/application_security/security_dashboard/img/group_security_dashboard.pngbin226261 -> 68332 bytes
-rw-r--r--doc/user/application_security/security_dashboard/img/project_security_dashboard.pngbin166559 -> 73425 bytes
-rw-r--r--doc/user/clusters/applications.md34
-rw-r--r--doc/user/clusters/img/jupyter-gitclone.pngbin64120 -> 22862 bytes
-rw-r--r--doc/user/discussions/img/automatically_resolve_outdated_discussions.pngbin57642 -> 21735 bytes
-rw-r--r--doc/user/discussions/img/btn_new_issue_for_all_threads.pngbin19431 -> 6716 bytes
-rw-r--r--doc/user/discussions/img/commit_comment_mr_context.pngbin365956 -> 103558 bytes
-rw-r--r--doc/user/discussions/img/commit_comment_mr_discussions_tab.pngbin276385 -> 76927 bytes
-rw-r--r--doc/user/discussions/img/discussion_comment.pngbin60561 -> 18323 bytes
-rw-r--r--doc/user/discussions/img/image_resolved_discussion.pngbin199539 -> 55713 bytes
-rw-r--r--doc/user/discussions/img/merge_request_commits_tab.pngbin169010 -> 54318 bytes
-rw-r--r--doc/user/discussions/img/mr_review_resolve.pngbin247868 -> 63623 bytes
-rw-r--r--doc/user/discussions/img/mr_review_resolve2.pngbin232589 -> 62012 bytes
-rw-r--r--doc/user/discussions/img/mr_review_second_comment.pngbin183733 -> 50468 bytes
-rw-r--r--doc/user/discussions/img/mr_review_second_comment_added.pngbin161924 -> 46448 bytes
-rw-r--r--doc/user/discussions/img/mr_review_start.pngbin274186 -> 80651 bytes
-rw-r--r--doc/user/discussions/img/mr_review_unresolve.pngbin298513 -> 78767 bytes
-rw-r--r--doc/user/discussions/img/mr_review_unresolve2.pngbin8976 -> 8971 bytes
-rw-r--r--doc/user/discussions/img/multi-line-suggestion-preview.pngbin61692 -> 16919 bytes
-rw-r--r--doc/user/discussions/img/multi-line-suggestion-syntax.pngbin29753 -> 8831 bytes
-rw-r--r--doc/user/discussions/img/new_issue_for_thread.pngbin21119 -> 6725 bytes
-rw-r--r--doc/user/discussions/img/onion_skin_view.pngbin95809 -> 29955 bytes
-rw-r--r--doc/user/discussions/img/only_allow_merge_if_all_threads_are_resolved.pngbin53804 -> 18257 bytes
-rw-r--r--doc/user/discussions/img/pending_review_comment.pngbin247865 -> 75625 bytes
-rw-r--r--doc/user/discussions/img/preview_issue_for_thread.pngbin119608 -> 33240 bytes
-rw-r--r--doc/user/discussions/img/preview_issue_for_threads.pngbin131506 -> 36192 bytes
-rw-r--r--doc/user/discussions/img/reply_to_comment_button.pngbin17224 -> 7602 bytes
-rw-r--r--doc/user/discussions/img/resolve_comment_button.pngbin11680 -> 3784 bytes
-rw-r--r--doc/user/discussions/img/resolve_thread_button.pngbin34562 -> 9842 bytes
-rw-r--r--doc/user/discussions/img/resolve_thread_issue_notice.pngbin44429 -> 13845 bytes
-rw-r--r--doc/user/discussions/img/resolve_thread_open_issue.pngbin57089 -> 21576 bytes
-rw-r--r--doc/user/discussions/img/review_comment_quickactions.pngbin270228 -> 78891 bytes
-rw-r--r--doc/user/discussions/img/review_preview.pngbin84789 -> 27664 bytes
-rw-r--r--doc/user/discussions/img/swipe_view.pngbin71076 -> 20840 bytes
-rw-r--r--doc/user/discussions/img/thread_view.pngbin556169 -> 162019 bytes
-rw-r--r--doc/user/discussions/img/threads_resolved.pngbin12667 -> 3976 bytes
-rw-r--r--doc/user/discussions/img/two_up_view.pngbin118688 -> 34612 bytes
-rw-r--r--doc/user/gitlab_com/index.md9
-rw-r--r--doc/user/group/epics/img/button_reopen_epic.pngbin14153 -> 14148 bytes
-rw-r--r--doc/user/group/epics/img/containing_epic.pngbin159939 -> 159919 bytes
-rw-r--r--doc/user/group/epics/img/epic_view.pngbin176759 -> 176740 bytes
-rw-r--r--doc/user/group/img/group_file_template_dropdown.pngbin9519 -> 9516 bytes
-rw-r--r--doc/user/group/img/group_file_template_settings.pngbin6217 -> 6210 bytes
-rw-r--r--doc/user/group/insights/img/insights_example_stacked_bar_chart.pngbin86062 -> 40798 bytes
-rw-r--r--doc/user/group/insights/img/insights_group_configuration.pngbin24107 -> 14125 bytes
-rw-r--r--doc/user/group/insights/img/insights_sidebar_link.pngbin18826 -> 12327 bytes
-rw-r--r--doc/user/group/roadmap/img/roadmap_view.pngbin49774 -> 49757 bytes
-rw-r--r--doc/user/group/saml_sso/img/group_saml_configuration_information.pngbin50435 -> 16489 bytes
-rw-r--r--doc/user/group/saml_sso/img/group_saml_settings.pngbin140408 -> 50300 bytes
-rw-r--r--doc/user/group/saml_sso/img/scim_advanced.pngbin21568 -> 6920 bytes
-rw-r--r--doc/user/group/saml_sso/img/scim_attribute_mapping.pngbin113191 -> 34642 bytes
-rw-r--r--doc/user/group/saml_sso/img/scim_name_identifier_mapping.pngbin175281 -> 59409 bytes
-rw-r--r--doc/user/group/saml_sso/img/scim_provisioning_status.pngbin23006 -> 7756 bytes
-rw-r--r--doc/user/group/saml_sso/img/scim_token.pngbin154318 -> 57095 bytes
-rw-r--r--doc/user/group/saml_sso/img/unlink_group_saml.pngbin27077 -> 9399 bytes
-rw-r--r--doc/user/operations_dashboard/img/index_operations_dashboard_top_bar_icon.pngbin3948 -> 3922 bytes
-rw-r--r--doc/user/operations_dashboard/img/index_operations_dashboard_with_projects.pngbin30837 -> 30826 bytes
-rw-r--r--doc/user/profile/img/active_sessions_list.pngbin19360 -> 18633 bytes
-rw-r--r--doc/user/project/clusters/img/k8s_cluster_monitoring.pngbin43150 -> 43141 bytes
-rw-r--r--doc/user/project/clusters/index.md57
-rw-r--r--doc/user/project/clusters/serverless/img/dns-entry.pngbin66116 -> 21299 bytes
-rw-r--r--doc/user/project/clusters/serverless/img/function-details-loaded.pngbin93515 -> 34302 bytes
-rw-r--r--doc/user/project/clusters/serverless/img/function-endpoint.pngbin42436 -> 14641 bytes
-rw-r--r--doc/user/project/clusters/serverless/img/function-execution.pngbin223762 -> 73788 bytes
-rw-r--r--doc/user/project/clusters/serverless/img/install-knative.pngbin86225 -> 27104 bytes
-rw-r--r--doc/user/project/clusters/serverless/img/serverless-page.pngbin191568 -> 50711 bytes
-rw-r--r--doc/user/project/clusters/serverless/index.md2
-rw-r--r--doc/user/project/deploy_tokens/img/deploy_tokens.pngbin218635 -> 62979 bytes
-rw-r--r--doc/user/project/img/cycle_analytics_landing_page.pngbin184131 -> 64872 bytes
-rw-r--r--doc/user/project/img/deploy_boards_kubernetes_label.pngbin43978 -> 13750 bytes
-rw-r--r--doc/user/project/img/file_lock.pngbin46281 -> 20461 bytes
-rw-r--r--doc/user/project/img/file_lock_merge_request_error_message.pngbin16254 -> 8219 bytes
-rw-r--r--doc/user/project/img/file_lock_repository_view.pngbin17644 -> 9805 bytes
-rw-r--r--doc/user/project/img/issue_boards_multiple.pngbin68373 -> 21635 bytes
-rw-r--r--doc/user/project/img/labels_default_v12_1.pngbin207994 -> 58694 bytes
-rw-r--r--doc/user/project/img/labels_delete_v12_1.pngbin29186 -> 9531 bytes
-rw-r--r--doc/user/project/img/labels_epic_sidebar_v12_1.pngbin318960 -> 102375 bytes
-rw-r--r--doc/user/project/img/labels_generate_default_v12_1.pngbin244739 -> 69038 bytes
-rw-r--r--doc/user/project/img/labels_group_issues_v12_1.pngbin391121 -> 118770 bytes
-rw-r--r--doc/user/project/img/labels_key_value_v12_1.pngbin332077 -> 102912 bytes
-rw-r--r--doc/user/project/img/labels_list_v12_1.pngbin360298 -> 104907 bytes
-rw-r--r--doc/user/project/img/labels_prioritized_v12_1.pngbin178652 -> 51751 bytes
-rw-r--r--doc/user/project/img/labels_promotion_v12_1.pngbin29215 -> 9600 bytes
-rw-r--r--doc/user/project/img/labels_subscriptions_v12_1.pngbin138684 -> 48037 bytes
-rw-r--r--doc/user/project/img/service_desk_disabled.pngbin18654 -> 11708 bytes
-rw-r--r--doc/user/project/img/service_desk_enabled.pngbin33243 -> 21514 bytes
-rw-r--r--doc/user/project/img/service_desk_issue_tracker.pngbin95087 -> 60824 bytes
-rw-r--r--doc/user/project/import/tfs.md2
-rw-r--r--doc/user/project/insights/img/insights_example_bar_chart.pngbin21767 -> 12118 bytes
-rw-r--r--doc/user/project/insights/img/insights_example_bar_time_series_chart.pngbin34068 -> 21060 bytes
-rw-r--r--doc/user/project/insights/img/insights_example_line_chart.pngbin120678 -> 50808 bytes
-rw-r--r--doc/user/project/insights/img/insights_example_pie_chart.pngbin10889 -> 6985 bytes
-rw-r--r--doc/user/project/insights/img/insights_example_stacked_bar_chart.pngbin81587 -> 37751 bytes
-rw-r--r--doc/user/project/insights/img/insights_sidebar_link.pngbin21463 -> 13776 bytes
-rw-r--r--doc/user/project/insights/img/project_insights.pngbin41210 -> 26534 bytes
-rw-r--r--doc/user/project/integrations/img/github_configuration.pngbin12515 -> 12258 bytes
-rw-r--r--doc/user/project/integrations/img/jira_add_user_to_group.pngbin266180 -> 83799 bytes
-rw-r--r--doc/user/project/integrations/img/jira_added_user_to_group.pngbin82473 -> 21646 bytes
-rw-r--r--doc/user/project/integrations/img/jira_api_token.pngbin21318 -> 7407 bytes
-rw-r--r--doc/user/project/integrations/img/jira_api_token_menu.pngbin41876 -> 14353 bytes
-rw-r--r--doc/user/project/integrations/img/jira_create_new_group.pngbin262453 -> 70535 bytes
-rw-r--r--doc/user/project/integrations/img/jira_create_new_user.pngbin173516 -> 40275 bytes
-rw-r--r--doc/user/project/integrations/img/jira_group_access.pngbin112706 -> 32162 bytes
-rw-r--r--doc/user/project/integrations/img/jira_issue_reference.pngbin64064 -> 19583 bytes
-rw-r--r--doc/user/project/integrations/img/jira_merge_request_close.pngbin64305 -> 21130 bytes
-rw-r--r--doc/user/project/integrations/img/jira_service_page.pngbin70807 -> 22464 bytes
-rw-r--r--doc/user/project/integrations/img/jira_user_management_link.pngbin206155 -> 57628 bytes
-rw-r--r--doc/user/project/integrations/img/mattermost_configuration.pngbin67672 -> 20459 bytes
-rw-r--r--doc/user/project/integrations/img/prometheus_dashboard_area_panel_type.pngbin65101 -> 19349 bytes
-rw-r--r--doc/user/project/integrations/img/prometheus_dashboard_single_stat_panel_type.pngbin26781 -> 6871 bytes
-rw-r--r--doc/user/project/integrations/img/prometheus_service_alerts.pngbin40727 -> 16084 bytes
-rw-r--r--doc/user/project/integrations/img/slack_configuration.pngbin64873 -> 19812 bytes
-rw-r--r--doc/user/project/issues/design_management.md13
-rw-r--r--doc/user/project/issues/img/adding_note_to_design_1.pngbin0 -> 486937 bytes
-rw-r--r--doc/user/project/issues/img/adding_note_to_design_2.pngbin0 -> 495888 bytes
-rw-r--r--doc/user/project/issues/img/comment-or-discussion.pngbin8378 -> 4530 bytes
-rw-r--r--doc/user/project/issues/img/confidential_mr_branch_dropdown_v12_1.pngbin121644 -> 38985 bytes
-rw-r--r--doc/user/project/issues/img/confidential_mr_dropdown_v12_1.pngbin128156 -> 40672 bytes
-rw-r--r--doc/user/project/issues/img/create_mr_from_issue.pngbin21286 -> 8632 bytes
-rw-r--r--doc/user/project/issues/img/design_management_v12_2.pngbin344504 -> 115179 bytes
-rw-r--r--doc/user/project/issues/img/issues_main_view_numbered.pngbin278285 -> 107528 bytes
-rw-r--r--doc/user/project/issues/img/reopen-issue.pngbin2522 -> 1230 bytes
-rw-r--r--doc/user/project/issues/img/report-abuse.pngbin1620 -> 1255 bytes
-rw-r--r--doc/user/project/issues/img/show-all-activity.pngbin8119 -> 4501 bytes
-rw-r--r--doc/user/project/labels.md6
-rw-r--r--doc/user/project/merge_requests/img/allow_collaboration.pngbin11028 -> 10806 bytes
-rw-r--r--doc/user/project/merge_requests/img/allow_collaboration_after_save.pngbin5415 -> 5410 bytes
-rw-r--r--doc/user/project/merge_requests/img/approvals_premium_mr_widget.pngbin76524 -> 22175 bytes
-rw-r--r--doc/user/project/merge_requests/img/approvals_premium_project_edit.pngbin47371 -> 14507 bytes
-rw-r--r--doc/user/project/merge_requests/img/approvals_starter_project_edit.pngbin52442 -> 16217 bytes
-rw-r--r--doc/user/project/merge_requests/img/approvals_starter_project_empty.pngbin50820 -> 16982 bytes
-rw-r--r--doc/user/project/merge_requests/img/approve.pngbin19329 -> 6655 bytes
-rw-r--r--doc/user/project/merge_requests/img/approve_additionally.pngbin22700 -> 7803 bytes
-rw-r--r--doc/user/project/merge_requests/img/create_from_email.pngbin112256 -> 69480 bytes
-rw-r--r--doc/user/project/merge_requests/img/edit_blocking_merge_requests.pngbin9926 -> 4369 bytes
-rw-r--r--doc/user/project/merge_requests/img/edit_blocking_merge_requests_inaccessible.pngbin10867 -> 4749 bytes
-rw-r--r--doc/user/project/merge_requests/img/filter_approver_merge_requests.pngbin90764 -> 30525 bytes
-rw-r--r--doc/user/project/merge_requests/img/filter_wip_merge_requests.pngbin28572 -> 11017 bytes
-rw-r--r--doc/user/project/merge_requests/img/merge_when_pipeline_succeeds_only_if_succeeds_settings.pngbin19986 -> 7433 bytes
-rw-r--r--doc/user/project/merge_requests/img/multiple_assignees_for_merge_requests_sidebar.pngbin20867 -> 7479 bytes
-rw-r--r--doc/user/project/merge_requests/img/remove_approval.pngbin21902 -> 7533 bytes
-rw-r--r--doc/user/project/merge_requests/img/show_blocking_merge_requests_in_mr_widget.pngbin27089 -> 9999 bytes
-rw-r--r--doc/user/project/merge_requests/img/squash_mr_message.pngbin150302 -> 37675 bytes
-rw-r--r--doc/user/project/merge_requests/img/wip_blocked_accept_button.pngbin7141 -> 4970 bytes
-rw-r--r--doc/user/project/operations/img/error_tracking_list.pngbin230740 -> 60762 bytes
-rw-r--r--doc/user/project/operations/img/external_dashboard_link.pngbin63282 -> 20192 bytes
-rw-r--r--doc/user/project/operations/img/external_dashboard_settings.pngbin103474 -> 33248 bytes
-rw-r--r--doc/user/project/operations/img/feature_flags_list.pngbin14963 -> 5922 bytes
-rw-r--r--doc/user/project/operations/img/specs_list.pngbin43574 -> 16889 bytes
-rw-r--r--doc/user/project/packages/img/npm_package_view.pngbin24443 -> 10349 bytes
-rw-r--r--doc/user/project/pages/custom_domains_ssl_tls_certification/img/get_domain_verification_code_v12_0.pngbin194433 -> 56899 bytes
-rw-r--r--doc/user/project/pages/custom_domains_ssl_tls_certification/img/lets_encrypt_integration_v12_1.pngbin35040 -> 11642 bytes
-rw-r--r--doc/user/project/pages/custom_domains_ssl_tls_certification/img/retry_domain_verification_v12_0.pngbin191712 -> 59544 bytes
-rw-r--r--doc/user/project/pages/custom_domains_ssl_tls_certification/ssl_tls_concepts.md2
-rw-r--r--doc/user/project/pages/img/pages_project_templates_v11_8.pngbin69702 -> 69675 bytes
-rw-r--r--doc/user/project/pages/img/remove_pages.pngbin58035 -> 12954 bytes
-rw-r--r--doc/user/project/pipelines/img/pipeline_schedule_variables.pngbin17292 -> 6300 bytes
-rw-r--r--doc/user/project/pipelines/img/pipeline_schedules_new_form.pngbin62141 -> 20090 bytes
-rw-r--r--doc/user/project/releases/img/releases.pngbin126093 -> 43776 bytes
-rw-r--r--doc/user/project/repository/img/download_source_code.pngbin61467 -> 19577 bytes
-rw-r--r--doc/user/project/settings/img/general_settings.pngbin154764 -> 46077 bytes
-rw-r--r--doc/user/project/settings/img/import_export_download_export.pngbin25905 -> 14867 bytes
-rw-r--r--doc/user/project/settings/img/import_export_export_button.pngbin25102 -> 14530 bytes
-rw-r--r--doc/user/project/settings/img/import_export_mail_link.pngbin7561 -> 6307 bytes
-rw-r--r--doc/user/project/settings/img/import_export_new_project.pngbin13202 -> 8011 bytes
-rw-r--r--doc/user/project/settings/img/import_export_select_file.pngbin20580 -> 11254 bytes
-rw-r--r--doc/user/project/settings/import_export.md1
-rw-r--r--doc/user/project/web_ide/img/terminal_status.pngbin8129 -> 3709 bytes
-rw-r--r--doc/workflow/img/notification_global_settings.pngbin118914 -> 67652 bytes
-rw-r--r--lib/gitlab/ci/build/prerequisite/kubernetes_namespace.rb30
-rw-r--r--lib/gitlab/ci/templates/Packer.gitlab-ci.yml2
-rw-r--r--lib/gitlab/content_security_policy/config_loader.rb43
-rw-r--r--lib/gitlab/highlight.rb11
-rw-r--r--lib/gitlab/import_export/import_export.yml6
-rw-r--r--lib/gitlab/kubernetes/default_namespace.rb58
-rw-r--r--lib/gitlab/prometheus/query_variables.rb5
-rw-r--r--lib/gitlab/prometheus_client.rb82
-rw-r--r--lib/rouge/formatters/html_gitlab.rb4
-rw-r--r--lib/sentry/client.rb2
-rw-r--r--locale/gitlab.pot6
-rw-r--r--package.json8
-rw-r--r--qa/qa/runtime/env.rb2
-rw-r--r--spec/controllers/metrics_controller_spec.rb9
-rw-r--r--spec/controllers/projects/serverless/functions_controller_spec.rb19
-rw-r--r--spec/factories/clusters/clusters.rb5
-rw-r--r--spec/factories/clusters/kubernetes_namespaces.rb13
-rw-r--r--spec/features/projects/serverless/functions_spec.rb12
-rw-r--r--spec/features/projects/services/user_activates_issue_tracker_spec.rb2
-rw-r--r--spec/features/projects/services/user_activates_youtrack_spec.rb2
-rw-r--r--spec/finders/clusters/knative_services_finder_spec.rb22
-rw-r--r--spec/finders/clusters/kubernetes_namespace_finder_spec.rb110
-rw-r--r--spec/finders/projects/serverless/functions_finder_spec.rb25
-rw-r--r--spec/frontend/test_setup.js15
-rw-r--r--spec/helpers/dashboard_helper_spec.rb2
-rw-r--r--spec/javascripts/ci_variable_list/ajax_variable_list_spec.js2
-rw-r--r--spec/javascripts/ci_variable_list/ci_variable_list_spec.js2
-rw-r--r--spec/javascripts/pipelines/pipelines_actions_spec.js42
-rw-r--r--spec/lib/gitlab/bitbucket_import/importer_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/build/prerequisite/kubernetes_namespace_spec.rb81
-rw-r--r--spec/lib/gitlab/content_security_policy/config_loader_spec.rb59
-rw-r--r--spec/lib/gitlab/highlight_spec.rb8
-rw-r--r--spec/lib/gitlab/import_export/all_models.yml14
-rw-r--r--spec/lib/gitlab/import_export/project.json60
-rw-r--r--spec/lib/gitlab/import_export/project_tree_restorer_spec.rb10
-rw-r--r--spec/lib/gitlab/import_export/project_tree_saver_spec.rb7
-rw-r--r--spec/lib/gitlab/import_export/safe_model_attributes.yml25
-rw-r--r--spec/lib/gitlab/kubernetes/default_namespace_spec.rb85
-rw-r--r--spec/lib/gitlab/prometheus/query_variables_spec.rb6
-rw-r--r--spec/lib/gitlab/prometheus_client_spec.rb47
-rw-r--r--spec/lib/sentry/client_spec.rb2
-rw-r--r--spec/models/clusters/applications/prometheus_spec.rb15
-rw-r--r--spec/models/clusters/cluster_spec.rb76
-rw-r--r--spec/models/clusters/kubernetes_namespace_spec.rb84
-rw-r--r--spec/models/clusters/platforms/kubernetes_spec.rb211
-rw-r--r--spec/models/concerns/prometheus_adapter_spec.rb4
-rw-r--r--spec/models/environment_spec.rb59
-rw-r--r--spec/models/merge_request_diff_spec.rb8
-rw-r--r--spec/models/project_services/prometheus_service_spec.rb4
-rw-r--r--spec/models/project_spec.rb83
-rw-r--r--spec/models/user_spec.rb18
-rw-r--r--spec/presenters/blob_presenter_spec.rb52
-rw-r--r--spec/presenters/projects/settings/deploy_keys_presenter_spec.rb8
-rw-r--r--spec/requests/api/project_clusters_spec.rb1
-rw-r--r--spec/services/clusters/build_kubernetes_namespace_service_spec.rb57
-rw-r--r--spec/services/clusters/gcp/kubernetes/create_or_update_namespace_service_spec.rb14
-rw-r--r--spec/services/projects/destroy_service_spec.rb12
-rw-r--r--spec/services/projects/lfs_pointers/lfs_download_link_list_service_spec.rb4
-rw-r--r--spec/services/prometheus/proxy_service_spec.rb2
-rw-r--r--spec/support/matchers/be_url.rb4
-rw-r--r--spec/support/prometheus/additional_metrics_shared_examples.rb2
-rw-r--r--spec/support/services/clusters/create_service_shared.rb67
-rw-r--r--yarn.lock404
411 files changed, 2584 insertions, 1251 deletions
diff --git a/.gitlab/CODEOWNERS b/.gitlab/CODEOWNERS
index cb3bc544132..dae3c349ff4 100644
--- a/.gitlab/CODEOWNERS
+++ b/.gitlab/CODEOWNERS
@@ -6,8 +6,8 @@
/doc/ @axil @marcia @eread @mikelewis
# Frontend maintainers should see everything in `app/assets/`
-app/assets/ @ClemMakesApps @fatihacet @filipa @iamphill @mikegreiling @timzallmann @kushalpandya @pslaughter
-*.scss @annabeldunstone @ClemMakesApps @fatihacet @filipa @iamphill @mikegreiling @timzallmann @kushalpandya @pslaughter
+app/assets/ @ClemMakesApps @fatihacet @filipa @mikegreiling @timzallmann @kushalpandya @pslaughter
+*.scss @annabeldunstone @ClemMakesApps @fatihacet @filipa @mikegreiling @timzallmann @kushalpandya @pslaughter
# Maintainers from the Database team should review changes in `db/`
db/ @gl-database
diff --git a/.gitlab/ci/review.gitlab-ci.yml b/.gitlab/ci/review.gitlab-ci.yml
index ed6690c1023..4a9269ffd82 100644
--- a/.gitlab/ci/review.gitlab-ci.yml
+++ b/.gitlab/ci/review.gitlab-ci.yml
@@ -7,6 +7,7 @@
except:
refs:
- master
+ - /^\d+-\d+-auto-deploy-\d+$/
- /(^docs[\/-].+|.+-docs$)/
.review-schedules-only: &review-schedules-only
@@ -264,6 +265,7 @@ danger-review:
except:
refs:
- master
+ - /^\d+-\d+-auto-deploy-\d+$/
- /^[\d-]+-stable(-ee)?$/
variables:
- $CI_COMMIT_REF_NAME =~ /^ce-to-ee-.*/
diff --git a/Gemfile b/Gemfile
index ef277336859..22746f9c5ae 100644
--- a/Gemfile
+++ b/Gemfile
@@ -296,7 +296,6 @@ gem 'batch-loader', '~> 1.4.0'
# Perf bar
gem 'peek', '~> 1.0.1'
-gem 'peek-gc', '~> 0.0.2'
# Memory benchmarks
gem 'derailed_benchmarks', require: false
diff --git a/Gemfile.lock b/Gemfile.lock
index 368cbef4577..80f36a9457c 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -522,7 +522,7 @@ GEM
mime-types-data (~> 3.2015)
mime-types-data (3.2019.0331)
mimemagic (0.3.2)
- mini_magick (4.8.0)
+ mini_magick (4.9.5)
mini_mime (1.0.1)
mini_portile2 (2.4.0)
minitest (5.11.3)
@@ -641,8 +641,6 @@ GEM
concurrent-ruby (>= 0.9.0)
concurrent-ruby-ext (>= 0.9.0)
railties (>= 4.0.0)
- peek-gc (0.0.2)
- peek
pg (1.1.4)
po_to_json (1.0.1)
json (>= 1.6.0)
@@ -1173,7 +1171,6 @@ DEPENDENCIES
omniauth_openid_connect (~> 0.3.1)
org-ruby (~> 0.9.12)
peek (~> 1.0.1)
- peek-gc (~> 0.0.2)
pg (~> 1.1)
premailer-rails (~> 1.9.7)
prometheus-client-mmap (~> 0.9.8)
diff --git a/app/assets/javascripts/behaviors/preview_markdown.js b/app/assets/javascripts/behaviors/preview_markdown.js
index 35874140bf9..b2571fb840c 100644
--- a/app/assets/javascripts/behaviors/preview_markdown.js
+++ b/app/assets/javascripts/behaviors/preview_markdown.js
@@ -36,6 +36,10 @@ MarkdownPreview.prototype.showPreview = function($form) {
mdText = $form.find('textarea.markdown-area').val();
+ if (mdText === undefined) {
+ return;
+ }
+
if (mdText.trim().length === 0) {
preview.text(this.emptyMessage);
this.hideReferencedUsers($form);
diff --git a/app/assets/javascripts/lib/utils/common_utils.js b/app/assets/javascripts/lib/utils/common_utils.js
index 5e90893b684..31c4a920bbe 100644
--- a/app/assets/javascripts/lib/utils/common_utils.js
+++ b/app/assets/javascripts/lib/utils/common_utils.js
@@ -44,6 +44,11 @@ export const isInIssuePage = () => checkPageAndAction('issues', 'show');
export const isInMRPage = () => checkPageAndAction('merge_requests', 'show');
export const isInEpicPage = () => checkPageAndAction('epics', 'show');
+export const getCspNonceValue = () => {
+ const metaTag = document.querySelector('meta[name=csp-nonce]');
+ return metaTag && metaTag.content;
+};
+
export const ajaxGet = url =>
axios
.get(url, {
@@ -51,7 +56,7 @@ export const ajaxGet = url =>
responseType: 'text',
})
.then(({ data }) => {
- $.globalEval(data);
+ $.globalEval(data, { nonce: getCspNonceValue() });
});
export const rstrip = val => {
diff --git a/app/assets/javascripts/monitoring/components/dashboard.vue b/app/assets/javascripts/monitoring/components/dashboard.vue
index 45543ef2cc8..2feb545199b 100644
--- a/app/assets/javascripts/monitoring/components/dashboard.vue
+++ b/app/assets/javascripts/monitoring/components/dashboard.vue
@@ -1,5 +1,12 @@
<script>
-import { GlButton, GlDropdown, GlDropdownItem, GlModal, GlModalDirective } from '@gitlab/ui';
+import {
+ GlButton,
+ GlDropdown,
+ GlDropdownItem,
+ GlModal,
+ GlModalDirective,
+ GlTooltipDirective,
+} from '@gitlab/ui';
import _ from 'underscore';
import { mapActions, mapState } from 'vuex';
import { s__ } from '~/locale';
@@ -30,7 +37,8 @@ export default {
GlModal,
},
directives: {
- GlModalDirective,
+ GlModal: GlModalDirective,
+ GlTooltip: GlTooltipDirective,
},
props: {
externalDashboardUrl: {
@@ -328,7 +336,7 @@ export default {
<div class="d-flex">
<div v-if="addingMetricsAvailable">
<gl-button
- v-gl-modal-directive="$options.addMetric.modalId"
+ v-gl-modal="$options.addMetric.modalId"
class="js-add-metric-button text-success border-success"
>{{ $options.addMetric.title }}</gl-button
>
@@ -395,14 +403,35 @@ export default {
:project-path="projectPath"
group-id="monitor-area-chart"
>
- <alert-widget
- v-if="alertWidgetAvailable && graphData"
- :alerts-endpoint="alertsEndpoint"
- :relevant-queries="graphData.queries"
- :alerts-to-manage="getGraphAlerts(graphData.queries)"
- :modal-id="`alert-modal-${index}-${graphIndex}`"
- @setAlerts="setAlerts"
- />
+ <div class="d-flex align-items-center">
+ <alert-widget
+ v-if="alertWidgetAvailable && graphData"
+ :modal-id="`alert-modal-${index}-${graphIndex}`"
+ :alerts-endpoint="alertsEndpoint"
+ :relevant-queries="graphData.queries"
+ :alerts-to-manage="getGraphAlerts(graphData.queries)"
+ @setAlerts="setAlerts"
+ />
+ <gl-dropdown
+ v-if="alertWidgetAvailable"
+ v-gl-tooltip
+ class="mx-2"
+ toggle-class="btn btn-transparent border-0"
+ :right="true"
+ :no-caret="true"
+ :title="__('More actions')"
+ >
+ <template slot="button-content">
+ <icon name="ellipsis_v" class="text-secondary" />
+ </template>
+ <gl-dropdown-item
+ v-if="alertWidgetAvailable"
+ v-gl-modal="`alert-modal-${index}-${graphIndex}`"
+ >
+ {{ __('Alerts') }}
+ </gl-dropdown-item>
+ </gl-dropdown>
+ </div>
</monitor-area-chart>
</template>
</graph-group>
diff --git a/app/assets/javascripts/monitoring/components/panel_type.vue b/app/assets/javascripts/monitoring/components/panel_type.vue
index f1f02964a29..295c0851f12 100644
--- a/app/assets/javascripts/monitoring/components/panel_type.vue
+++ b/app/assets/javascripts/monitoring/components/panel_type.vue
@@ -1,6 +1,7 @@
<script>
import { mapState } from 'vuex';
import _ from 'underscore';
+import { GlDropdown, GlDropdownItem, GlModal, GlModalDirective } from '@gitlab/ui';
import MonitorAreaChart from './charts/area.vue';
import MonitorSingleStatChart from './charts/single_stat.vue';
import MonitorEmptyChart from './charts/empty_chart.vue';
@@ -10,6 +11,12 @@ export default {
MonitorAreaChart,
MonitorSingleStatChart,
MonitorEmptyChart,
+ GlDropdown,
+ GlDropdownItem,
+ GlModal,
+ },
+ directives: {
+ GlModal: GlModalDirective,
},
props: {
graphData: {
@@ -64,14 +71,32 @@ export default {
:container-width="dashboardWidth"
group-id="monitor-area-chart"
>
- <alert-widget
- v-if="alertWidgetAvailable"
- :alerts-endpoint="alertsEndpoint"
- :relevant-queries="graphData.queries"
- :alerts-to-manage="getGraphAlerts(graphData.queries)"
- :modal-id="`alert-modal-${index}`"
- @setAlerts="setAlerts"
- />
+ <div class="d-flex align-items-center">
+ <alert-widget
+ v-if="alertWidgetAvailable && graphData"
+ :modal-id="`alert-modal-${index}`"
+ :alerts-endpoint="alertsEndpoint"
+ :relevant-queries="graphData.queries"
+ :alerts-to-manage="getGraphAlerts(graphData.queries)"
+ @setAlerts="setAlerts"
+ />
+ <gl-dropdown
+ v-if="alertWidgetAvailable"
+ v-gl-tooltip
+ class="mx-2"
+ toggle-class="btn btn-transparent border-0"
+ :right="true"
+ :no-caret="true"
+ :title="__('More actions')"
+ >
+ <template slot="button-content">
+ <icon name="ellipsis_v" class="text-secondary" />
+ </template>
+ <gl-dropdown-item v-if="alertWidgetAvailable" v-gl-modal="`alert-modal-${index}`">
+ {{ __('Alerts') }}
+ </gl-dropdown-item>
+ </gl-dropdown>
+ </div>
</monitor-area-chart>
<monitor-empty-chart v-else :graph-title="graphData.title" />
</template>
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 c0ea42ad1a2..13aa8844172 100644
--- a/app/assets/javascripts/performance_bar/components/performance_bar_app.vue
+++ b/app/assets/javascripts/performance_bar/components/performance_bar_app.vue
@@ -112,12 +112,6 @@ export default {
:header="metric.header"
:keys="metric.keys"
/>
- <div id="peek-view-gc" class="view">
- <span v-if="currentRequest.details" class="bold">
- <span title="Invoke Time">{{ currentRequest.details.gc.gc_time }}</span
- >ms / <span title="Invoke Count">{{ currentRequest.details.gc.invokes }}</span> gc
- </span>
- </div>
<div
v-if="currentRequest.details && currentRequest.details.tracing"
id="peek-view-trace"
diff --git a/app/assets/javascripts/pipelines/components/pipelines_actions.vue b/app/assets/javascripts/pipelines/components/pipelines_actions.vue
index 244d332f38f..4b2d816c6a0 100644
--- a/app/assets/javascripts/pipelines/components/pipelines_actions.vue
+++ b/app/assets/javascripts/pipelines/components/pipelines_actions.vue
@@ -1,9 +1,11 @@
<script>
import { GlButton, GlTooltipDirective, GlLoadingIcon } from '@gitlab/ui';
-import { s__, sprintf } from '~/locale';
+import axios from '~/lib/utils/axios_utils';
+import flash from '~/flash';
+import { s__, __, sprintf } from '~/locale';
import GlCountdown from '~/vue_shared/components/gl_countdown.vue';
+import Icon from '~/vue_shared/components/icon.vue';
import eventHub from '../event_hub';
-import Icon from '../../vue_shared/components/icon.vue';
export default {
directives: {
@@ -44,7 +46,24 @@ export default {
this.isLoading = true;
- eventHub.$emit('postAction', action.path);
+ /**
+ * Ideally, the component would not make an api call directly.
+ * However, in order to use the eventhub and know when to
+ * toggle back the `isLoading` property we'd need an ID
+ * to track the request with a wacther - since this component
+ * is rendered at least 20 times in the same page, moving the
+ * api call directly here is the most performant solution
+ */
+ axios
+ .post(`${action.path}.json`)
+ .then(() => {
+ this.isLoading = false;
+ eventHub.$emit('updateTable');
+ })
+ .catch(() => {
+ this.isLoading = false;
+ flash(__('An error occurred while making the request.'));
+ });
},
isActionDisabled(action) {
diff --git a/app/assets/javascripts/pipelines/mixins/pipelines.js b/app/assets/javascripts/pipelines/mixins/pipelines.js
index a6243366375..126a9a47a2b 100644
--- a/app/assets/javascripts/pipelines/mixins/pipelines.js
+++ b/app/assets/javascripts/pipelines/mixins/pipelines.js
@@ -60,12 +60,14 @@ export default {
eventHub.$on('postAction', this.postAction);
eventHub.$on('retryPipeline', this.postAction);
eventHub.$on('clickedDropdown', this.updateTable);
+ eventHub.$on('updateTable', this.updateTable);
eventHub.$on('refreshPipelinesTable', this.fetchPipelines);
},
beforeDestroy() {
eventHub.$off('postAction', this.postAction);
eventHub.$off('retryPipeline', this.postAction);
eventHub.$off('clickedDropdown', this.updateTable);
+ eventHub.$off('updateTable', this.updateTable);
eventHub.$off('refreshPipelinesTable', this.fetchPipelines);
},
destroyed() {
diff --git a/app/assets/javascripts/vue_shared/components/commit.vue b/app/assets/javascripts/vue_shared/components/commit.vue
index ae9b013d980..f7c508c4e23 100644
--- a/app/assets/javascripts/vue_shared/components/commit.vue
+++ b/app/assets/javascripts/vue_shared/components/commit.vue
@@ -152,37 +152,35 @@ export default {
:href="mergeRequestRef.path"
:title="mergeRequestRef.title"
class="ref-name"
+ >{{ mergeRequestRef.iid }}</gl-link
>
- {{ mergeRequestRef.iid }}
- </gl-link>
<gl-link
v-else
v-gl-tooltip
:href="commitRef.ref_url"
:title="commitRef.name"
class="ref-name"
+ >{{ commitRef.name }}</gl-link
>
- {{ commitRef.name }}
- </gl-link>
</template>
<icon name="commit" class="commit-icon js-commit-icon" />
- <gl-link :href="commitUrl" class="commit-sha mr-0"> {{ shortSha }} </gl-link>
+ <gl-link :href="commitUrl" class="commit-sha mr-0">{{ shortSha }}</gl-link>
- <div class="commit-title flex-truncate-parent">
- <tooltip-on-truncate v-if="title" class="flex-truncate-child" :title="title">
+ <div class="commit-title">
+ <span v-if="title" class="flex-truncate-parent">
<user-avatar-link
v-if="hasAuthor"
:link-href="author.path"
:img-src="author.avatar_url"
:img-alt="userImageAltDescription"
:tooltip-text="author.username"
- class="avatar-image-container"
+ class="avatar-image-container text-decoration-none"
/>
- <gl-link :href="commitUrl" class="commit-row-message cgray">
- {{ title }}
- </gl-link>
- </tooltip-on-truncate>
+ <tooltip-on-truncate :title="title" class="flex-truncate-child">
+ <gl-link :href="commitUrl" class="commit-row-message cgray">{{ title }}</gl-link>
+ </tooltip-on-truncate>
+ </span>
<span v-else>{{ __("Can't find HEAD commit for this branch") }}</span>
</div>
</div>
diff --git a/app/assets/javascripts/vue_shared/components/content_viewer/viewers/image_viewer.vue b/app/assets/javascripts/vue_shared/components/content_viewer/viewers/image_viewer.vue
index fc6a45b957e..6a4a834337a 100644
--- a/app/assets/javascripts/vue_shared/components/content_viewer/viewers/image_viewer.vue
+++ b/app/assets/javascripts/vue_shared/components/content_viewer/viewers/image_viewer.vue
@@ -27,7 +27,6 @@ export default {
return {
width: 0,
height: 0,
- isLoaded: false,
};
},
computed: {
@@ -63,8 +62,6 @@ export default {
this.height = contentImg.naturalHeight;
this.$nextTick(() => {
- this.isLoaded = true;
-
this.$emit('imgLoaded', {
width: this.width,
height: this.height,
diff --git a/app/assets/stylesheets/framework/responsive_tables.scss b/app/assets/stylesheets/framework/responsive_tables.scss
index 6bd44ee19bd..fd6f80e26cb 100644
--- a/app/assets/stylesheets/framework/responsive_tables.scss
+++ b/app/assets/stylesheets/framework/responsive_tables.scss
@@ -155,7 +155,7 @@
text-overflow: ellipsis;
@include media-breakpoint-up(md) {
- flex: 0 0 90%;
+ flex: 0 0 85%;
}
.avatar {
diff --git a/app/controllers/concerns/issuable_collections.rb b/app/controllers/concerns/issuable_collections.rb
index 21b3949e361..3489ea78b77 100644
--- a/app/controllers/concerns/issuable_collections.rb
+++ b/app/controllers/concerns/issuable_collections.rb
@@ -194,10 +194,9 @@ module IssuableCollections
end
def collection_type
- @collection_type ||= case finder_type.name
- when 'IssuesFinder'
+ @collection_type ||= if finder_type <= IssuesFinder
'Issue'
- when 'MergeRequestsFinder'
+ elsif finder_type <= MergeRequestsFinder
'MergeRequest'
end
end
diff --git a/app/finders/clusters/knative_services_finder.rb b/app/finders/clusters/knative_services_finder.rb
index 7d3b53ef663..71cebe4495e 100644
--- a/app/finders/clusters/knative_services_finder.rb
+++ b/app/finders/clusters/knative_services_finder.rb
@@ -13,11 +13,11 @@ module Clusters
self.reactive_cache_key = ->(finder) { finder.model_name }
self.reactive_cache_worker_finder = ->(_id, *cache_args) { from_cache(*cache_args) }
- attr_reader :cluster, :project
+ attr_reader :cluster, :environment
- def initialize(cluster, project)
+ def initialize(cluster, environment)
@cluster = cluster
- @project = project
+ @environment = environment
end
def with_reactive_cache_memoized(*cache_args, &block)
@@ -30,11 +30,11 @@ module Clusters
clear_reactive_cache!(*cache_args)
end
- def self.from_cache(cluster_id, project_id)
+ def self.from_cache(cluster_id, environment_id)
cluster = Clusters::Cluster.find(cluster_id)
- project = ::Project.find(project_id)
+ environment = Environment.find(environment_id)
- new(cluster, project)
+ new(cluster, environment)
end
def calculate_reactive_cache(*)
@@ -56,7 +56,7 @@ module Clusters
end
def cache_args
- [cluster.id, project.id]
+ [cluster.id, environment.id]
end
def service_pod_details(service)
@@ -84,7 +84,7 @@ module Clusters
private
def search_namespace
- @search_namespace ||= cluster.kubernetes_namespace_for(project)
+ @search_namespace ||= cluster.kubernetes_namespace_for(environment)
end
def knative_client
diff --git a/app/finders/clusters/kubernetes_namespace_finder.rb b/app/finders/clusters/kubernetes_namespace_finder.rb
new file mode 100644
index 00000000000..e947796c1e7
--- /dev/null
+++ b/app/finders/clusters/kubernetes_namespace_finder.rb
@@ -0,0 +1,36 @@
+# frozen_string_literal: true
+
+module Clusters
+ class KubernetesNamespaceFinder
+ attr_reader :cluster, :project, :environment_slug
+
+ def initialize(cluster, project:, environment_slug:, allow_blank_token: false)
+ @cluster = cluster
+ @project = project
+ @environment_slug = environment_slug
+ @allow_blank_token = allow_blank_token
+ end
+
+ def execute
+ find_namespace(with_environment: cluster.namespace_per_environment?)
+ end
+
+ private
+
+ attr_reader :allow_blank_token
+
+ def find_namespace(with_environment:)
+ relation = with_environment ? namespaces.with_environment_slug(environment_slug) : namespaces
+
+ relation.find_by_project_id(project.id)
+ end
+
+ def namespaces
+ if allow_blank_token
+ cluster.kubernetes_namespaces
+ else
+ cluster.kubernetes_namespaces.has_service_account_token
+ end
+ end
+ end
+end
diff --git a/app/finders/projects/serverless/functions_finder.rb b/app/finders/projects/serverless/functions_finder.rb
index ebe50806ca1..e8c50ef1a88 100644
--- a/app/finders/projects/serverless/functions_finder.rb
+++ b/app/finders/projects/serverless/functions_finder.rb
@@ -3,10 +3,11 @@
module Projects
module Serverless
class FunctionsFinder
+ include Gitlab::Utils::StrongMemoize
+
attr_reader :project
def initialize(project)
- @clusters = project.clusters
@project = project
end
@@ -16,9 +17,8 @@ module Projects
# Possible return values: Clusters::KnativeServicesFinder::KNATIVE_STATE
def knative_installed
- states = @clusters.map do |cluster|
- cluster.application_knative
- cluster.knative_services_finder(project).knative_detected.tap do |state|
+ states = services_finders.map do |finder|
+ finder.knative_detected.tap do |state|
return state if state == ::Clusters::KnativeServicesFinder::KNATIVE_STATES['checking'] # rubocop:disable Cop/AvoidReturnFromBlocks
end
end
@@ -31,66 +31,70 @@ module Projects
end
def invocation_metrics(environment_scope, name)
- return unless prometheus_adapter&.can_query?
+ environment = finders_for_scope(environment_scope).first&.environment
- cluster = @clusters.find do |c|
- environment_scope == c.environment_scope
+ if environment.present? && environment.prometheus_adapter&.can_query?
+ func = ::Serverless::Function.new(project, name, environment.deployment_namespace)
+ environment.prometheus_adapter.query(:knative_invocation, func)
end
-
- func = ::Serverless::Function.new(project, name, cluster.kubernetes_namespace_for(project))
- prometheus_adapter.query(:knative_invocation, func)
end
def has_prometheus?(environment_scope)
- @clusters.any? do |cluster|
- environment_scope == cluster.environment_scope && cluster.application_prometheus_available?
+ finders_for_scope(environment_scope).any? do |finder|
+ finder.cluster.application_prometheus_available?
end
end
private
def knative_service(environment_scope, name)
- @clusters.map do |cluster|
- next if environment_scope != cluster.environment_scope
-
- services = cluster
- .knative_services_finder(project)
+ finders_for_scope(environment_scope).map do |finder|
+ services = finder
.services
.select { |svc| svc["metadata"]["name"] == name }
- add_metadata(cluster, services).first unless services.nil?
+ add_metadata(finder, services).first unless services.nil?
end
end
def knative_services
- @clusters.map do |cluster|
- services = cluster
- .knative_services_finder(project)
- .services
+ services_finders.map do |finder|
+ services = finder.services
- add_metadata(cluster, services) unless services.nil?
+ add_metadata(finder, services) unless services.nil?
end
end
- def add_metadata(cluster, services)
+ def add_metadata(finder, services)
+ add_pod_count = services.one?
+
services.each do |s|
- s["environment_scope"] = cluster.environment_scope
- s["cluster_id"] = cluster.id
+ s["environment_scope"] = finder.cluster.environment_scope
+ s["cluster_id"] = finder.cluster.id
- if services.length == 1
- s["podcount"] = cluster
- .knative_services_finder(project)
+ if add_pod_count
+ s["podcount"] = finder
.service_pod_details(s["metadata"]["name"])
.length
end
end
end
- # rubocop: disable CodeReuse/ServiceClass
- def prometheus_adapter
- @prometheus_adapter ||= ::Prometheus::AdapterService.new(project).prometheus_adapter
+ def services_finders
+ strong_memoize(:services_finders) do
+ available_environments.map(&:knative_services_finder).compact
+ end
+ end
+
+ def available_environments
+ @project.environments.available.preload_cluster
+ end
+
+ def finders_for_scope(environment_scope)
+ services_finders.select do |finder|
+ environment_scope == finder.cluster.environment_scope
+ end
end
- # rubocop: enable CodeReuse/ServiceClass
end
end
end
diff --git a/app/models/active_session.rb b/app/models/active_session.rb
index fdd210f0fba..00192b1da59 100644
--- a/app/models/active_session.rb
+++ b/app/models/active_session.rb
@@ -136,8 +136,10 @@ class ActiveSession
# only the single key entries are automatically expired by redis, the
# lookup entries in the set need to be removed manually.
session_ids_and_entries = session_ids.zip(entries)
- session_ids_and_entries.reject { |_session_id, entry| entry }.each do |session_id, _entry|
- redis.srem(lookup_key_name(user.id), session_id)
+ redis.pipelined do
+ session_ids_and_entries.reject { |_session_id, entry| entry }.each do |session_id, _entry|
+ redis.srem(lookup_key_name(user.id), session_id)
+ end
end
entries.compact
diff --git a/app/models/clusters/applications/prometheus.rb b/app/models/clusters/applications/prometheus.rb
index 5eb535cab58..08e52f32bb3 100644
--- a/app/models/clusters/applications/prometheus.rb
+++ b/app/models/clusters/applications/prometheus.rb
@@ -83,7 +83,7 @@ module Clusters
# ensures headers containing auth data are appended to original k8s client options
options = kube_client.rest_client.options.merge(headers: kube_client.headers)
- RestClient::Resource.new(proxy_url, options)
+ Gitlab::PrometheusClient.new(proxy_url, options)
rescue Kubeclient::HttpError
# If users have mistakenly set parameters or removed the depended clusters,
# `proxy_url` could raise an exception because gitlab can not communicate with the cluster.
diff --git a/app/models/clusters/cluster.rb b/app/models/clusters/cluster.rb
index 8bb44b0ce40..97d39491b73 100644
--- a/app/models/clusters/cluster.rb
+++ b/app/models/clusters/cluster.rb
@@ -53,6 +53,7 @@ module Clusters
validates :name, cluster_name: true
validates :cluster_type, presence: true
validates :domain, allow_blank: true, hostname: { allow_numeric_hostname: true }
+ validates :namespace_per_environment, inclusion: { in: [true, false] }
validate :restrict_modification, on: :update
validate :no_groups, unless: :group_type?
@@ -100,16 +101,6 @@ module Clusters
scope :default_environment, -> { where(environment_scope: DEFAULT_ENVIRONMENT) }
- scope :with_knative_installed, -> { joins(:application_knative).merge(Clusters::Applications::Knative.available) }
-
- scope :preload_knative, -> {
- preload(
- :kubernetes_namespaces,
- :platform_kubernetes,
- :application_knative
- )
- }
-
def self.ancestor_clusters_for_clusterable(clusterable, hierarchy_order: :asc)
return [] if clusterable.is_a?(Instance)
@@ -177,36 +168,15 @@ module Clusters
platform_kubernetes.kubeclient if kubernetes?
end
- ##
- # This is subtly different to #find_or_initialize_kubernetes_namespace_for_project
- # below because it will ignore any namespaces that have not got a service account
- # token. This provides a guarantee that any namespace selected here can be used
- # for cluster operations - a namespace needs to have a service account configured
- # before it it can be used.
- #
- # This is used for selecting a namespace to use when querying a cluster, or
- # generating variables to pass to CI.
- def kubernetes_namespace_for(project)
- find_or_initialize_kubernetes_namespace_for_project(
- project, scope: kubernetes_namespaces.has_service_account_token
- ).namespace
- end
-
- ##
- # This is subtly different to #kubernetes_namespace_for because it will include
- # namespaces that have yet to receive a service account token. This allows
- # the namespace configuration process to be repeatable - if a namespace has
- # already been created without a token we don't need to create another
- # record entirely, just set the token on the pre-existing namespace.
- #
- # This is used for configuring cluster namespaces.
- def find_or_initialize_kubernetes_namespace_for_project(project, scope: kubernetes_namespaces)
- attributes = { project: project }
- attributes[:cluster_project] = cluster_project if project_type?
+ def kubernetes_namespace_for(environment)
+ project = environment.project
+ persisted_namespace = Clusters::KubernetesNamespaceFinder.new(
+ self,
+ project: project,
+ environment_slug: environment.slug
+ ).execute
- scope.find_or_initialize_by(attributes).tap do |namespace|
- namespace.set_defaults
- end
+ persisted_namespace&.namespace || Gitlab::Kubernetes::DefaultNamespace.new(self, project: project).from_environment_slug(environment.slug)
end
def allow_user_defined_namespace?
@@ -225,10 +195,6 @@ module Clusters
end
end
- def knative_services_finder(project)
- @knative_services_finder ||= KnativeServicesFinder.new(self, project)
- end
-
private
def instance_domain
diff --git a/app/models/clusters/kubernetes_namespace.rb b/app/models/clusters/kubernetes_namespace.rb
index b0c4900546e..69a2b99fcb6 100644
--- a/app/models/clusters/kubernetes_namespace.rb
+++ b/app/models/clusters/kubernetes_namespace.rb
@@ -9,12 +9,12 @@ module Clusters
belongs_to :cluster_project, class_name: 'Clusters::Project'
belongs_to :cluster, class_name: 'Clusters::Cluster'
belongs_to :project, class_name: '::Project'
+ belongs_to :environment, optional: true
has_one :platform_kubernetes, through: :cluster
- before_validation :set_defaults
-
validates :namespace, presence: true
validates :namespace, uniqueness: { scope: :cluster_id }
+ validates :environment_id, uniqueness: { scope: [:cluster_id, :project_id] }, allow_nil: true
validates :service_account_name, presence: true
@@ -27,6 +27,7 @@ module Clusters
algorithm: 'aes-256-cbc'
scope :has_service_account_token, -> { where.not(encrypted_service_account_token: nil) }
+ scope :with_environment_slug, -> (slug) { joins(:environment).where(environments: { slug: slug }) }
def token_name
"#{namespace}-token"
@@ -42,34 +43,8 @@ module Clusters
end
end
- def set_defaults
- self.namespace ||= default_platform_kubernetes_namespace
- self.namespace ||= default_project_namespace
- self.service_account_name ||= default_service_account_name
- end
-
private
- def default_service_account_name
- return unless namespace
-
- "#{namespace}-service-account"
- end
-
- def default_platform_kubernetes_namespace
- platform_kubernetes&.namespace.presence
- end
-
- def default_project_namespace
- Gitlab::NamespaceSanitizer.sanitize(project_slug) if project_slug
- end
-
- def project_slug
- return unless project
-
- "#{project.path}-#{project.id}".downcase
- end
-
def kubeconfig
to_kubeconfig(
url: api_url,
diff --git a/app/models/clusters/platforms/kubernetes.rb b/app/models/clusters/platforms/kubernetes.rb
index 9296c28776b..37614fbe3ca 100644
--- a/app/models/clusters/platforms/kubernetes.rb
+++ b/app/models/clusters/platforms/kubernetes.rb
@@ -51,11 +51,6 @@ module Clusters
delegate :provided_by_user?, to: :cluster, allow_nil: true
delegate :allow_user_defined_namespace?, to: :cluster, allow_nil: true
- # This is just to maintain compatibility with KubernetesService, which
- # will be removed in https://gitlab.com/gitlab-org/gitlab-ce/issues/39217.
- # It can be removed once KubernetesService is gone.
- delegate :kubernetes_namespace_for, to: :cluster, allow_nil: true
-
alias_method :active?, :enabled?
enum_with_nil authorization_type: {
@@ -66,7 +61,7 @@ module Clusters
default_value_for :authorization_type, :rbac
- def predefined_variables(project:)
+ def predefined_variables(project:, environment_name:)
Gitlab::Ci::Variables::Collection.new.tap do |variables|
variables.append(key: 'KUBE_URL', value: api_url)
@@ -77,15 +72,14 @@ module Clusters
end
if !cluster.managed?
- project_namespace = namespace.presence || "#{project.path}-#{project.id}".downcase
+ namespace = Gitlab::Kubernetes::DefaultNamespace.new(cluster, project: project).from_environment_name(environment_name)
variables
- .append(key: 'KUBE_URL', value: api_url)
.append(key: 'KUBE_TOKEN', value: token, public: false, masked: true)
- .append(key: 'KUBE_NAMESPACE', value: project_namespace)
- .append(key: 'KUBECONFIG', value: kubeconfig(project_namespace), public: false, file: true)
+ .append(key: 'KUBE_NAMESPACE', value: namespace)
+ .append(key: 'KUBECONFIG', value: kubeconfig(namespace), public: false, file: true)
- elsif kubernetes_namespace = cluster.kubernetes_namespaces.has_service_account_token.find_by(project: project)
+ elsif kubernetes_namespace = find_persisted_namespace(project, environment_name: environment_name)
variables.concat(kubernetes_namespace.predefined_variables)
end
@@ -111,6 +105,22 @@ module Clusters
private
+ ##
+ # Environment slug can be predicted given an environment
+ # name, so even if the environment isn't persisted yet we
+ # still know what to look for.
+ def environment_slug(name)
+ Gitlab::Slug::Environment.new(name).generate
+ end
+
+ def find_persisted_namespace(project, environment_name:)
+ Clusters::KubernetesNamespaceFinder.new(
+ cluster,
+ project: project,
+ environment_slug: environment_slug(environment_name)
+ ).execute
+ end
+
def kubeconfig(namespace)
to_kubeconfig(
url: api_url,
diff --git a/app/models/concerns/maskable.rb b/app/models/concerns/maskable.rb
index e0f2c41b836..d70e47bc4ff 100644
--- a/app/models/concerns/maskable.rb
+++ b/app/models/concerns/maskable.rb
@@ -7,9 +7,10 @@ module Maskable
# * No escape characters
# * No variables
# * No spaces
- # * Minimal length of 8 characters from the Base64 alphabets (RFC4648)
+ # * Minimal length of 8 characters
+ # * Characters must be from the Base64 alphabet (RFC4648) with the addition of @ and :
# * Absolutely no fun is allowed
- REGEX = /\A[a-zA-Z0-9_+=\/-]{8,}\z/.freeze
+ REGEX = /\A[a-zA-Z0-9_+=\/@:-]{8,}\z/.freeze
included do
validates :masked, inclusion: { in: [true, false] }
diff --git a/app/models/concerns/prometheus_adapter.rb b/app/models/concerns/prometheus_adapter.rb
index c2542dbe743..9ac4722c6b1 100644
--- a/app/models/concerns/prometheus_adapter.rb
+++ b/app/models/concerns/prometheus_adapter.rb
@@ -14,10 +14,6 @@ module PrometheusAdapter
raise NotImplementedError
end
- def prometheus_client_wrapper
- Gitlab::PrometheusClient.new(prometheus_client)
- end
-
def can_query?
prometheus_client.present?
end
@@ -35,7 +31,7 @@ module PrometheusAdapter
def calculate_reactive_cache(query_class_name, *args)
return unless prometheus_client
- data = Object.const_get(query_class_name, false).new(prometheus_client_wrapper).query(*args)
+ data = Object.const_get(query_class_name, false).new(prometheus_client).query(*args)
{
success: true,
data: data,
diff --git a/app/models/deploy_key.rb b/app/models/deploy_key.rb
index db501b4b506..0bd90bd28e3 100644
--- a/app/models/deploy_key.rb
+++ b/app/models/deploy_key.rb
@@ -2,12 +2,14 @@
class DeployKey < Key
include IgnorableColumn
+ include FromUnion
has_many :deploy_keys_projects, inverse_of: :deploy_key, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent
has_many :projects, through: :deploy_keys_projects
scope :in_projects, ->(projects) { joins(:deploy_keys_projects).where('deploy_keys_projects.project_id in (?)', projects) }
scope :are_public, -> { where(public: true) }
+ scope :with_projects, -> { includes(deploy_keys_projects: { project: [:route, :namespace] }) }
ignore_column :can_push
@@ -22,7 +24,7 @@ class DeployKey < Key
end
def almost_orphaned?
- self.deploy_keys_projects.length == 1
+ self.deploy_keys_projects.count == 1
end
def destroyed_when_orphaned?
@@ -46,6 +48,6 @@ class DeployKey < Key
end
def projects_with_write_access
- Project.preload(:route).where(id: deploy_keys_projects.with_write_access.select(:project_id))
+ Project.with_route.where(id: deploy_keys_projects.with_write_access.select(:project_id))
end
end
diff --git a/app/models/deploy_keys_project.rb b/app/models/deploy_keys_project.rb
index 15906ed8e06..40c66d5bc4c 100644
--- a/app/models/deploy_keys_project.rb
+++ b/app/models/deploy_keys_project.rb
@@ -1,9 +1,8 @@
# frozen_string_literal: true
class DeployKeysProject < ApplicationRecord
- belongs_to :project
+ belongs_to :project, inverse_of: :deploy_keys_projects
belongs_to :deploy_key, inverse_of: :deploy_keys_projects
-
scope :without_project_deleted, -> { joins(:project).where(projects: { pending_delete: false }) }
scope :in_project, ->(project) { where(project: project) }
scope :with_write_access, -> { where(can_push: true) }
diff --git a/app/models/environment.rb b/app/models/environment.rb
index 513427ac2c5..1b53c4b45f9 100644
--- a/app/models/environment.rb
+++ b/app/models/environment.rb
@@ -48,6 +48,7 @@ class Environment < ApplicationRecord
end
scope :in_review_folder, -> { where(environment_type: "review") }
scope :for_name, -> (name) { where(name: name) }
+ scope :preload_cluster, -> { preload(last_deployment: :cluster) }
##
# Search environments which have names like the given query.
@@ -170,7 +171,7 @@ class Environment < ApplicationRecord
def deployment_namespace
strong_memoize(:kubernetes_namespace) do
- deployment_platform&.kubernetes_namespace_for(project)
+ deployment_platform.cluster.kubernetes_namespace_for(self) if deployment_platform
end
end
@@ -233,6 +234,12 @@ class Environment < ApplicationRecord
end
end
+ def knative_services_finder
+ if last_deployment&.cluster
+ Clusters::KnativeServicesFinder.new(last_deployment.cluster, self)
+ end
+ end
+
private
def generate_slug
diff --git a/app/models/list.rb b/app/models/list.rb
index d28a9bda82d..ccadd39bda2 100644
--- a/app/models/list.rb
+++ b/app/models/list.rb
@@ -3,10 +3,11 @@
class List < ApplicationRecord
belongs_to :board
belongs_to :label
+ include Importable
enum list_type: { backlog: 0, label: 1, closed: 2, assignee: 3, milestone: 4 }
- validates :board, :list_type, presence: true
+ validates :board, :list_type, presence: true, unless: :importing?
validates :label, :position, presence: true, if: :label?
validates :label_id, uniqueness: { scope: :board_id }, if: :label?
validates :position, numericality: { only_integer: true, greater_than_or_equal_to: 0 }, if: :movable?
diff --git a/app/models/merge_request_diff.rb b/app/models/merge_request_diff.rb
index f45bd0e03de..2c9dbf2585c 100644
--- a/app/models/merge_request_diff.rb
+++ b/app/models/merge_request_diff.rb
@@ -196,6 +196,12 @@ class MergeRequestDiff < ApplicationRecord
real_size.presence || raw_diffs.size
end
+ def lines_count
+ strong_memoize(:lines_count) do
+ diffs.diff_files.sum(&:line_count)
+ end
+ end
+
def raw_diffs(options = {})
if options[:ignore_whitespace_change]
@diffs_no_whitespace ||= compare.diffs(options)
diff --git a/app/models/project.rb b/app/models/project.rb
index 8f234fba04f..960795b73cb 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -214,7 +214,7 @@ class Project < ApplicationRecord
as: :source, class_name: 'ProjectMember', dependent: :delete_all # rubocop:disable Cop/ActiveRecordDependent
has_many :members_and_requesters, as: :source, class_name: 'ProjectMember'
- has_many :deploy_keys_projects
+ has_many :deploy_keys_projects, inverse_of: :project
has_many :deploy_keys, through: :deploy_keys_projects
has_many :users_star_projects
has_many :starrers, through: :users_star_projects, source: :user
@@ -1487,6 +1487,9 @@ class Project < ApplicationRecord
end
def pipeline_for(ref, sha = nil, id = nil)
+ sha ||= commit(ref).try(:sha)
+ return unless sha
+
if id.present?
pipelines_for(ref, sha).find_by(id: id)
else
@@ -1494,11 +1497,7 @@ class Project < ApplicationRecord
end
end
- def pipelines_for(ref, sha = nil)
- sha ||= commit(ref).try(:sha)
-
- return unless sha
-
+ def pipelines_for(ref, sha)
ci_pipelines.order(id: :desc).where(sha: sha, ref: ref)
end
@@ -1856,8 +1855,12 @@ class Project < ApplicationRecord
end
end
- def deployment_variables(environment: nil)
- deployment_platform(environment: environment)&.predefined_variables(project: self) || []
+ def deployment_variables(environment:)
+ platform = deployment_platform(environment: environment)
+
+ return [] unless platform.present?
+
+ platform.predefined_variables(project: self, environment_name: environment)
end
def auto_devops_variables
diff --git a/app/models/project_services/mock_deployment_service.rb b/app/models/project_services/mock_deployment_service.rb
index 1103cb11e73..6f2b0f7747f 100644
--- a/app/models/project_services/mock_deployment_service.rb
+++ b/app/models/project_services/mock_deployment_service.rb
@@ -24,7 +24,7 @@ class MockDeploymentService < Service
%w()
end
- def predefined_variables(project:)
+ def predefined_variables(project:, environment_name:)
[]
end
diff --git a/app/models/project_services/prometheus_service.rb b/app/models/project_services/prometheus_service.rb
index c68a9d923c8..6eff2ea2e3a 100644
--- a/app/models/project_services/prometheus_service.rb
+++ b/app/models/project_services/prometheus_service.rb
@@ -63,15 +63,16 @@ class PrometheusService < MonitoringService
# Check we can connect to the Prometheus API
def test(*args)
- Gitlab::PrometheusClient.new(prometheus_client).ping
-
+ prometheus_client.ping
{ success: true, result: 'Checked API endpoint' }
rescue Gitlab::PrometheusClient::Error => err
{ success: false, result: err }
end
def prometheus_client
- RestClient::Resource.new(api_url, max_redirects: 0) if should_return_client?
+ return unless should_return_client?
+
+ Gitlab::PrometheusClient.new(api_url)
end
def prometheus_available?
@@ -84,7 +85,7 @@ class PrometheusService < MonitoringService
private
def should_return_client?
- api_url && manual_configuration? && active? && valid?
+ api_url.present? && manual_configuration? && active? && valid?
end
def synchronize_service_state
diff --git a/app/models/user.rb b/app/models/user.rb
index b439d1c0c16..4630552e02e 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -933,7 +933,7 @@ class User < ApplicationRecord
end
def project_deploy_keys
- DeployKey.unscoped.in_projects(authorized_projects.pluck(:id)).distinct(:id)
+ DeployKey.in_projects(authorized_projects.select(:id)).distinct(:id)
end
def highest_role
@@ -941,11 +941,10 @@ class User < ApplicationRecord
end
def accessible_deploy_keys
- @accessible_deploy_keys ||= begin
- key_ids = project_deploy_keys.pluck(:id)
- key_ids.push(*DeployKey.are_public.pluck(:id))
- DeployKey.where(id: key_ids)
- end
+ DeployKey.from_union([
+ DeployKey.where(id: project_deploy_keys.select(:deploy_key_id)),
+ DeployKey.are_public
+ ])
end
def created_by
diff --git a/app/presenters/blob_presenter.rb b/app/presenters/blob_presenter.rb
index 2cf3278d240..f85c1a237a6 100644
--- a/app/presenters/blob_presenter.rb
+++ b/app/presenters/blob_presenter.rb
@@ -3,12 +3,13 @@
class BlobPresenter < Gitlab::View::Presenter::Delegated
presents :blob
- def highlight(plain: nil)
+ def highlight(since: nil, to: nil, plain: nil)
load_all_blob_data
Gitlab::Highlight.highlight(
blob.path,
- blob.data,
+ limited_blob_data(since: since, to: to),
+ since: since,
language: blob.language_from_gitattributes,
plain: plain
)
@@ -23,4 +24,18 @@ class BlobPresenter < Gitlab::View::Presenter::Delegated
def load_all_blob_data
blob.load_all_data! if blob.respond_to?(:load_all_data!)
end
+
+ def limited_blob_data(since: nil, to: nil)
+ return blob.data if since.blank? || to.blank?
+
+ limited_blob_lines(since, to).join
+ end
+
+ def limited_blob_lines(since, to)
+ all_lines[since - 1..to - 1]
+ end
+
+ def all_lines
+ @all_lines ||= blob.data.lines
+ end
end
diff --git a/app/presenters/blobs/unfold_presenter.rb b/app/presenters/blobs/unfold_presenter.rb
index 21a1e1309e0..f4672d22fc9 100644
--- a/app/presenters/blobs/unfold_presenter.rb
+++ b/app/presenters/blobs/unfold_presenter.rb
@@ -21,20 +21,19 @@ module Blobs
load_all_blob_data
@subject = blob
- @all_lines = blob.data.lines
super(params)
if full?
- self.attributes = { since: 1, to: @all_lines.size, bottom: false, unfold: false, offset: 0, indent: 0 }
+ self.attributes = { since: 1, to: all_lines.size, bottom: false, unfold: false, offset: 0, indent: 0 }
end
end
# Returns an array of Gitlab::Diff::Line with match line added
def diff_lines
- diff_lines = lines.map.with_index do |line, index|
- full_line = limited_blob_lines[index].delete("\n")
+ diff_lines = limited_blob_lines(since, to).map.with_index do |line, index|
+ full_line = line.delete("\n")
- Gitlab::Diff::Line.new(full_line, nil, nil, nil, nil, rich_text: line)
+ Gitlab::Diff::Line.new(full_line, nil, nil, nil, nil, rich_text: lines[index])
end
add_match_line(diff_lines)
@@ -43,7 +42,7 @@ module Blobs
end
def lines
- @lines ||= limit(highlight.lines).map(&:html_safe)
+ @lines ||= highlight(since: since, to: to).lines.map(&:html_safe)
end
def match_line_text
@@ -59,7 +58,7 @@ module Blobs
def add_match_line(diff_lines)
return unless unfold?
- if bottom? && to < @all_lines.size
+ if bottom? && to < all_lines.size
old_pos = to - offset
new_pos = to
elsif since != 1
@@ -73,15 +72,5 @@ module Blobs
bottom? ? diff_lines.push(match_line) : diff_lines.unshift(match_line)
end
-
- def limited_blob_lines
- @limited_blob_lines ||= limit(@all_lines)
- end
-
- def limit(lines)
- return lines if full?
-
- lines[since - 1..to - 1]
- end
end
end
diff --git a/app/presenters/projects/settings/deploy_keys_presenter.rb b/app/presenters/projects/settings/deploy_keys_presenter.rb
index 85518c9a3a4..6f8c4e1f902 100644
--- a/app/presenters/projects/settings/deploy_keys_presenter.rb
+++ b/app/presenters/projects/settings/deploy_keys_presenter.rb
@@ -12,48 +12,38 @@ module Projects
@key ||= DeployKey.new.tap { |dk| dk.deploy_keys_projects.build }
end
- # rubocop: disable CodeReuse/ActiveRecord
def enabled_keys
- @enabled_keys ||= project.deploy_keys.includes(:projects)
- end
- # rubocop: enable CodeReuse/ActiveRecord
-
- def any_keys_enabled?
- enabled_keys.any?
+ project.deploy_keys
end
def available_keys
- @available_keys ||= current_user.accessible_deploy_keys - enabled_keys
+ current_user
+ .accessible_deploy_keys
+ .id_not_in(enabled_keys.select(:id))
+ .with_projects
end
- # rubocop: disable CodeReuse/ActiveRecord
def available_project_keys
- @available_project_keys ||= current_user.project_deploy_keys.includes(:projects) - enabled_keys
- end
- # rubocop: enable CodeReuse/ActiveRecord
-
- def key_available?(deploy_key)
- available_keys.include?(deploy_key)
+ current_user
+ .project_deploy_keys
+ .id_not_in(enabled_keys.select(:id))
+ .with_projects
end
- # rubocop: disable CodeReuse/ActiveRecord
def available_public_keys
- return @available_public_keys if defined?(@available_public_keys)
-
- @available_public_keys ||= DeployKey.are_public.includes(:projects) - enabled_keys
-
- # Public keys that are already used by another accessible project are already
- # in @available_project_keys.
- @available_public_keys -= available_project_keys
+ DeployKey
+ .are_public
+ .id_not_in(enabled_keys.select(:id))
+ .id_not_in(available_project_keys.select(:id))
+ .with_projects
end
- # rubocop: enable CodeReuse/ActiveRecord
def as_json
serializer = DeployKeySerializer.new # rubocop: disable CodeReuse/Serializer
opts = { user: current_user }
{
- enabled_keys: serializer.represent(enabled_keys, opts),
+ enabled_keys: serializer.represent(enabled_keys.with_projects, opts),
available_project_keys: serializer.represent(available_project_keys, opts),
public_keys: serializer.represent(available_public_keys, opts)
}
diff --git a/app/serializers/deploy_key_entity.rb b/app/serializers/deploy_key_entity.rb
index 54bf030aba1..e47d6454780 100644
--- a/app/serializers/deploy_key_entity.rb
+++ b/app/serializers/deploy_key_entity.rb
@@ -10,9 +10,10 @@ class DeployKeyEntity < Grape::Entity
expose :created_at
expose :updated_at
expose :deploy_keys_projects, using: DeployKeysProjectEntity do |deploy_key|
- deploy_key.deploy_keys_projects
- .without_project_deleted
- .select { |deploy_key_project| Ability.allowed?(options[:user], :read_project, deploy_key_project.project) }
+ deploy_key.deploy_keys_projects.select do |deploy_key_project|
+ !deploy_key_project.project&.pending_delete? &&
+ Ability.allowed?(options[:user], :read_project, deploy_key_project.project)
+ end
end
expose :can_edit
diff --git a/app/services/clusters/build_kubernetes_namespace_service.rb b/app/services/clusters/build_kubernetes_namespace_service.rb
new file mode 100644
index 00000000000..2574f77bbf9
--- /dev/null
+++ b/app/services/clusters/build_kubernetes_namespace_service.rb
@@ -0,0 +1,35 @@
+# frozen_string_literal: true
+
+module Clusters
+ class BuildKubernetesNamespaceService
+ attr_reader :cluster, :environment
+
+ def initialize(cluster, environment:)
+ @cluster = cluster
+ @environment = environment
+ end
+
+ def execute
+ cluster.kubernetes_namespaces.build(attributes)
+ end
+
+ private
+
+ def attributes
+ attributes = {
+ project: environment.project,
+ namespace: namespace,
+ service_account_name: "#{namespace}-service-account"
+ }
+
+ attributes[:cluster_project] = cluster.cluster_project if cluster.project_type?
+ attributes[:environment] = environment if cluster.namespace_per_environment?
+
+ attributes
+ end
+
+ def namespace
+ Gitlab::Kubernetes::DefaultNamespace.new(cluster, project: environment.project).from_environment_slug(environment.slug)
+ end
+ end
+end
diff --git a/app/services/clusters/create_service.rb b/app/services/clusters/create_service.rb
index 5fb5e15c32d..e5a5b73321a 100644
--- a/app/services/clusters/create_service.rb
+++ b/app/services/clusters/create_service.rb
@@ -11,7 +11,8 @@ module Clusters
def execute(access_token: nil)
raise ArgumentError, 'Unknown clusterable provided' unless clusterable
- cluster_params = params.merge(user: current_user).merge(clusterable_params)
+ cluster_params = params.merge(global_params).merge(clusterable_params)
+
cluster_params[:provider_gcp_attributes].try do |provider|
provider[:access_token] = access_token
end
@@ -35,6 +36,10 @@ module Clusters
@clusterable ||= params.delete(:clusterable)
end
+ def global_params
+ { user: current_user, namespace_per_environment: Feature.enabled?(:kubernetes_namespace_per_environment, default_enabled: true) }
+ end
+
def clusterable_params
case clusterable
when ::Project
diff --git a/app/services/clusters/gcp/kubernetes/create_or_update_namespace_service.rb b/app/services/clusters/gcp/kubernetes/create_or_update_namespace_service.rb
index 806f320381d..c45dac7b273 100644
--- a/app/services/clusters/gcp/kubernetes/create_or_update_namespace_service.rb
+++ b/app/services/clusters/gcp/kubernetes/create_or_update_namespace_service.rb
@@ -11,7 +11,6 @@ module Clusters
end
def execute
- configure_kubernetes_namespace
create_project_service_account
configure_kubernetes_token
@@ -22,10 +21,6 @@ module Clusters
attr_reader :cluster, :kubernetes_namespace, :platform
- def configure_kubernetes_namespace
- kubernetes_namespace.set_defaults
- end
-
def create_project_service_account
Clusters::Gcp::Kubernetes::CreateOrUpdateServiceAccountService.namespace_creator(
platform.kubeclient,
diff --git a/app/services/projects/destroy_service.rb b/app/services/projects/destroy_service.rb
index a1279bfb3a3..5893b8eedff 100644
--- a/app/services/projects/destroy_service.rb
+++ b/app/services/projects/destroy_service.rb
@@ -173,6 +173,7 @@ module Projects
end
def remove_registry_tags
+ return true unless Gitlab.config.registry.enabled
return false unless remove_legacy_registry_tags
project.container_repositories.find_each do |container_repository|
diff --git a/app/services/prometheus/proxy_service.rb b/app/services/prometheus/proxy_service.rb
index c5d2b84878b..a62eb76b8ce 100644
--- a/app/services/prometheus/proxy_service.rb
+++ b/app/services/prometheus/proxy_service.rb
@@ -98,7 +98,7 @@ module Prometheus
end
def prometheus_client_wrapper
- prometheus_adapter&.prometheus_client_wrapper
+ prometheus_adapter&.prometheus_client
end
def can_query?
diff --git a/app/views/layouts/_google_analytics.html.haml b/app/views/layouts/_google_analytics.html.haml
index 98ea96b0b77..e8a5359e791 100644
--- a/app/views/layouts/_google_analytics.html.haml
+++ b/app/views/layouts/_google_analytics.html.haml
@@ -1,11 +1,11 @@
--# haml-lint:disable InlineJavaScript
-:javascript
- var _gaq = _gaq || [];
- _gaq.push(['_setAccount', '#{extra_config.google_analytics_id}']);
- _gaq.push(['_trackPageview']);
+= javascript_tag nonce: true do
+ :plain
+ var _gaq = _gaq || [];
+ _gaq.push(['_setAccount', '#{extra_config.google_analytics_id}']);
+ _gaq.push(['_trackPageview']);
- (function() {
- var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
- ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
- var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
- })();
+ (function() {
+ var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
+ ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
+ var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
+ })();
diff --git a/app/views/layouts/_head.html.haml b/app/views/layouts/_head.html.haml
index ac774803f95..271b73326fa 100644
--- a/app/views/layouts/_head.html.haml
+++ b/app/views/layouts/_head.html.haml
@@ -40,7 +40,7 @@
= stylesheet_link_tag "highlight/themes/#{user_color_scheme}", media: "all"
- = Gon::Base.render_data
+ = Gon::Base.render_data(nonce: content_security_policy_nonce)
- if content_for?(:library_javascripts)
= yield :library_javascripts
@@ -56,6 +56,7 @@
= yield :project_javascripts
= csrf_meta_tags
+ = csp_meta_tag
- unless browser.safari?
%meta{ name: 'referrer', content: 'origin-when-cross-origin' }
diff --git a/app/views/layouts/_init_auto_complete.html.haml b/app/views/layouts/_init_auto_complete.html.haml
index 240e03a5d53..82ec92988eb 100644
--- a/app/views/layouts/_init_auto_complete.html.haml
+++ b/app/views/layouts/_init_auto_complete.html.haml
@@ -4,8 +4,8 @@
- datasources = autocomplete_data_sources(object, noteable_type)
- if object
- -# haml-lint:disable InlineJavaScript
- :javascript
- gl = window.gl || {};
- gl.GfmAutoComplete = gl.GfmAutoComplete || {};
- gl.GfmAutoComplete.dataSources = #{datasources.to_json};
+ = javascript_tag nonce: true do
+ :plain
+ gl = window.gl || {};
+ gl.GfmAutoComplete = gl.GfmAutoComplete || {};
+ gl.GfmAutoComplete.dataSources = #{datasources.to_json};
diff --git a/app/views/layouts/_init_client_detection_flags.html.haml b/app/views/layouts/_init_client_detection_flags.html.haml
index c729f8aa696..6537b86085f 100644
--- a/app/views/layouts/_init_client_detection_flags.html.haml
+++ b/app/views/layouts/_init_client_detection_flags.html.haml
@@ -1,7 +1,7 @@
- client = client_js_flags
- if client
- -# haml-lint:disable InlineJavaScript
- :javascript
- gl = window.gl || {};
- gl.client = #{client.to_json};
+ = javascript_tag nonce: true do
+ :plain
+ gl = window.gl || {};
+ gl.client = #{client.to_json};
diff --git a/app/views/layouts/_piwik.html.haml b/app/views/layouts/_piwik.html.haml
index 473b14ce626..2cb2e23433d 100644
--- a/app/views/layouts/_piwik.html.haml
+++ b/app/views/layouts/_piwik.html.haml
@@ -1,15 +1,15 @@
<!-- Piwik -->
--# haml-lint:disable InlineJavaScript
-:javascript
- var _paq = _paq || [];
- _paq.push(['trackPageView']);
- _paq.push(['enableLinkTracking']);
- (function() {
- var u="//#{extra_config.piwik_url}/";
- _paq.push(['setTrackerUrl', u+'piwik.php']);
- _paq.push(['setSiteId', "#{extra_config.piwik_site_id}"]);
- var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];
- g.type='text/javascript'; g.async=true; g.defer=true; g.src=u+'piwik.js'; s.parentNode.insertBefore(g,s);
- })();
-<noscript><p><img src="//#{extra_config.piwik_url}/piwik.php?idsite=#{extra_config.piwik_site_id}" style="border:0;" alt="" /></p></noscript>
-<!-- End Piwik Code -->
+= javascript_tag nonce: true do
+ :plain
+ var _paq = _paq || [];
+ _paq.push(['trackPageView']);
+ _paq.push(['enableLinkTracking']);
+ (function() {
+ var u="//#{extra_config.piwik_url}/";
+ _paq.push(['setTrackerUrl', u+'piwik.php']);
+ _paq.push(['setSiteId', "#{extra_config.piwik_site_id}"]);
+ var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];
+ g.type='text/javascript'; g.async=true; g.defer=true; g.src=u+'piwik.js'; s.parentNode.insertBefore(g,s);
+ })();
+ <noscript><p><img src="//#{extra_config.piwik_url}/piwik.php?idsite=#{extra_config.piwik_site_id}" style="border:0;" alt="" /></p></noscript>
+ <!-- End Piwik Code -->
diff --git a/app/views/layouts/errors.html.haml b/app/views/layouts/errors.html.haml
index 06069a72951..74484005b48 100644
--- a/app/views/layouts/errors.html.haml
+++ b/app/views/layouts/errors.html.haml
@@ -8,12 +8,12 @@
%body
.page-container
= yield
- -# haml-lint:disable InlineJavaScript
- :javascript
- (function(){
- var goBackElement = document.querySelector('.js-go-back');
+ = javascript_tag nonce: true do
+ :plain
+ (function(){
+ var goBackElement = document.querySelector('.js-go-back');
- if (goBackElement && history.length > 1) {
- goBackElement.style.display = 'block';
- }
- }());
+ if (goBackElement && history.length > 1) {
+ goBackElement.style.display = 'block';
+ }
+ }());
diff --git a/app/views/layouts/group.html.haml b/app/views/layouts/group.html.haml
index 1d40b78fa83..49de821f1c2 100644
--- a/app/views/layouts/group.html.haml
+++ b/app/views/layouts/group.html.haml
@@ -6,8 +6,8 @@
- content_for :page_specific_javascripts do
- if current_user
- -# haml-lint:disable InlineJavaScript
- :javascript
- window.uploads_path = "#{group_uploads_path(@group)}";
+ = javascript_tag nonce: true do
+ :plain
+ window.uploads_path = "#{group_uploads_path(@group)}";
= render template: "layouts/application"
diff --git a/app/views/layouts/nav/_dashboard.html.haml b/app/views/layouts/nav/_dashboard.html.haml
index cbe713b7468..ff0c5b241b2 100644
--- a/app/views/layouts/nav/_dashboard.html.haml
+++ b/app/views/layouts/nav/_dashboard.html.haml
@@ -32,6 +32,8 @@
= link_to dashboard_snippets_path, class: 'dashboard-shortcuts-snippets qa-snippets-link' do
= _('Snippets')
+ = render_if_exists 'layouts/nav/sidebar/analytics_link'
+
- if any_dashboard_nav_link?([:groups, :milestones, :activity, :snippets])
%li.header-more.dropdown.d-xl-none{ class: ('d-lg-none' unless has_extra_nav_icons?) }
%a{ href: "#", data: { toggle: "dropdown" } }
@@ -53,6 +55,9 @@
= nav_link(controller: 'dashboard/snippets') do
= link_to dashboard_snippets_path, class: 'dashboard-shortcuts-snippets' do
= _('Snippets')
+
+ = render_if_exists 'layouts/nav/sidebar/analytics_more_link'
+
%li.dropdown.d-lg-none
= render_if_exists 'dashboard/operations/nav_link_list'
- if can?(current_user, :read_instance_statistics)
diff --git a/app/views/layouts/project.html.haml b/app/views/layouts/project.html.haml
index 6b51483810e..b8ef38272fc 100644
--- a/app/views/layouts/project.html.haml
+++ b/app/views/layouts/project.html.haml
@@ -7,8 +7,8 @@
- content_for :project_javascripts do
- project = @target_project || @project
- if current_user
- -# haml-lint:disable InlineJavaScript
- :javascript
- window.uploads_path = "#{project_uploads_path(project)}";
+ = javascript_tag nonce: true do
+ :plain
+ window.uploads_path = "#{project_uploads_path(project)}";
= render template: "layouts/application"
diff --git a/app/views/layouts/snippets.html.haml b/app/views/layouts/snippets.html.haml
index 841b2a5e79c..cde2b467392 100644
--- a/app/views/layouts/snippets.html.haml
+++ b/app/views/layouts/snippets.html.haml
@@ -3,8 +3,8 @@
- content_for :page_specific_javascripts do
- if snippets_upload_path
- -# haml-lint:disable InlineJavaScript
- :javascript
- window.uploads_path = "#{snippets_upload_path}";
+ = javascript_tag nonce: true do
+ :plain
+ window.uploads_path = "#{snippets_upload_path}";
= render template: "layouts/application"
diff --git a/app/views/projects/_export.html.haml b/app/views/projects/_export.html.haml
index 1056977886a..e42772c2dd9 100644
--- a/app/views/projects/_export.html.haml
+++ b/app/views/projects/_export.html.haml
@@ -15,6 +15,7 @@
%li= _('Project configuration, including services')
%li= _('Issues with comments, merge requests with diffs and comments, labels, milestones, snippets, and other project entities')
%li= _('LFS objects')
+ %li= _('Issue Boards')
%p= _('The following items will NOT be exported:')
%ul
%li= _('Job traces and artifacts')
diff --git a/app/views/projects/merge_requests/show.html.haml b/app/views/projects/merge_requests/show.html.haml
index 2c5c5141bf0..af3bd8dcd69 100644
--- a/app/views/projects/merge_requests/show.html.haml
+++ b/app/views/projects/merge_requests/show.html.haml
@@ -16,13 +16,13 @@
- if @merge_request.source_branch_exists?
= render "projects/merge_requests/how_to_merge"
- -# haml-lint:disable InlineJavaScript
- :javascript
- window.gl = window.gl || {};
- window.gl.mrWidgetData = #{serialize_issuable(@merge_request, serializer: 'widget', issues_links: true)}
+ = javascript_tag nonce: true do
+ :plain
+ window.gl = window.gl || {};
+ window.gl.mrWidgetData = #{serialize_issuable(@merge_request, serializer: 'widget', issues_links: true)}
- window.gl.mrWidgetData.squash_before_merge_help_path = '#{help_page_path("user/project/merge_requests/squash_and_merge")}';
- window.gl.mrWidgetData.troubleshooting_docs_path = '#{help_page_path('user/project/merge_requests/index.md', anchor: 'troubleshooting')}';
+ window.gl.mrWidgetData.squash_before_merge_help_path = '#{help_page_path("user/project/merge_requests/squash_and_merge")}';
+ window.gl.mrWidgetData.troubleshooting_docs_path = '#{help_page_path('user/project/merge_requests/index.md', anchor: 'troubleshooting')}';
#js-vue-mr-widget.mr-widget
diff --git a/changelogs/unreleased/31434-make-issue-boards-importable.yml b/changelogs/unreleased/31434-make-issue-boards-importable.yml
new file mode 100644
index 00000000000..fd270a236dc
--- /dev/null
+++ b/changelogs/unreleased/31434-make-issue-boards-importable.yml
@@ -0,0 +1,5 @@
+---
+title: Make issue boards importable
+merge_request: 31434
+author: Jason Colyer
+type: changed
diff --git a/changelogs/unreleased/43080-speed-up-deploy-keys.yml b/changelogs/unreleased/43080-speed-up-deploy-keys.yml
new file mode 100644
index 00000000000..73c9a9e5f82
--- /dev/null
+++ b/changelogs/unreleased/43080-speed-up-deploy-keys.yml
@@ -0,0 +1,5 @@
+---
+title: Speed up loading and filtering deploy keys and their projects
+merge_request: 31384
+author:
+type: performance
diff --git a/changelogs/unreleased/52494-separate-namespace-per-project-environment-slug.yml b/changelogs/unreleased/52494-separate-namespace-per-project-environment-slug.yml
new file mode 100644
index 00000000000..645c92127a3
--- /dev/null
+++ b/changelogs/unreleased/52494-separate-namespace-per-project-environment-slug.yml
@@ -0,0 +1,5 @@
+---
+title: Use separate Kubernetes namespaces per environment
+merge_request: 30711
+author:
+type: added
diff --git a/changelogs/unreleased/64608-double-tooltips.yml b/changelogs/unreleased/64608-double-tooltips.yml
new file mode 100644
index 00000000000..f6cb1944d26
--- /dev/null
+++ b/changelogs/unreleased/64608-double-tooltips.yml
@@ -0,0 +1,5 @@
+---
+title: Prevents showing 2 tooltips in pipelines table
+merge_request:
+author:
+type: fixed
diff --git a/changelogs/unreleased/65152-selective-highlight.yml b/changelogs/unreleased/65152-selective-highlight.yml
new file mode 100644
index 00000000000..371dbbd5924
--- /dev/null
+++ b/changelogs/unreleased/65152-selective-highlight.yml
@@ -0,0 +1,5 @@
+---
+title: Support selective highlighting of lines
+merge_request: 31361
+author:
+type: performance
diff --git a/changelogs/unreleased/65263-manual-action.yml b/changelogs/unreleased/65263-manual-action.yml
new file mode 100644
index 00000000000..47b2a2ed329
--- /dev/null
+++ b/changelogs/unreleased/65263-manual-action.yml
@@ -0,0 +1,5 @@
+---
+title: Hides loading spinner in pipelines actions after request has been fullfiled
+merge_request:
+author:
+type: fixed
diff --git a/changelogs/unreleased/65660-update-karma-to-4-2-0.yml b/changelogs/unreleased/65660-update-karma-to-4-2-0.yml
new file mode 100644
index 00000000000..c0cb40ce169
--- /dev/null
+++ b/changelogs/unreleased/65660-update-karma-to-4-2-0.yml
@@ -0,0 +1,5 @@
+---
+title: Update karma to 4.2.0
+merge_request: 31495
+author: Takuya Noguchi
+type: other
diff --git a/changelogs/unreleased/65671-update-mini_magick-to-4-9-5.yml b/changelogs/unreleased/65671-update-mini_magick-to-4-9-5.yml
new file mode 100644
index 00000000000..a6f8576ae0b
--- /dev/null
+++ b/changelogs/unreleased/65671-update-mini_magick-to-4-9-5.yml
@@ -0,0 +1,5 @@
+---
+title: Update mini_magick to 4.9.5
+merge_request: 31505
+author: Takuya Noguchi
+type: security
diff --git a/changelogs/unreleased/khair1-master-patch-79459.yml b/changelogs/unreleased/khair1-master-patch-79459.yml
new file mode 100644
index 00000000000..22b0877336d
--- /dev/null
+++ b/changelogs/unreleased/khair1-master-patch-79459.yml
@@ -0,0 +1,5 @@
+---
+title: Update Packer.gitlab-ci.yml to use latest image
+merge_request:
+author: Kelly Hair
+type: other
diff --git a/changelogs/unreleased/mc-feature-add-at-colon-variable-masking.yml b/changelogs/unreleased/mc-feature-add-at-colon-variable-masking.yml
new file mode 100644
index 00000000000..9b8eff8e043
--- /dev/null
+++ b/changelogs/unreleased/mc-feature-add-at-colon-variable-masking.yml
@@ -0,0 +1,5 @@
+---
+title: 'Allows masking @ and : characters.'
+merge_request: 31065
+author:
+type: changed
diff --git a/changelogs/unreleased/remove-peek-gc.yml b/changelogs/unreleased/remove-peek-gc.yml
new file mode 100644
index 00000000000..9412cd7c9a6
--- /dev/null
+++ b/changelogs/unreleased/remove-peek-gc.yml
@@ -0,0 +1,5 @@
+---
+title: Remove GC metrics from performance bar
+merge_request:
+author:
+type: removed
diff --git a/changelogs/unreleased/sh-disable-registry-delete.yml b/changelogs/unreleased/sh-disable-registry-delete.yml
new file mode 100644
index 00000000000..180b983e07c
--- /dev/null
+++ b/changelogs/unreleased/sh-disable-registry-delete.yml
@@ -0,0 +1,5 @@
+---
+title: Don't attempt to contact registry if it is disabled
+merge_request: 31553
+author:
+type: fixed
diff --git a/changelogs/unreleased/sh-support-csp-nonce.yml b/changelogs/unreleased/sh-support-csp-nonce.yml
new file mode 100644
index 00000000000..3e6ac1e4a32
--- /dev/null
+++ b/changelogs/unreleased/sh-support-csp-nonce.yml
@@ -0,0 +1,5 @@
+---
+title: Add support for Content-Security-Policy
+merge_request: 31402
+author:
+type: added
diff --git a/config/gitlab.yml.example b/config/gitlab.yml.example
index 39b719a5978..226f2ec3722 100644
--- a/config/gitlab.yml.example
+++ b/config/gitlab.yml.example
@@ -47,6 +47,29 @@ production: &base
#
# relative_url_root: /gitlab
+ # Content Security Policy
+ # See https://guides.rubyonrails.org/security.html#content-security-policy
+ content_security_policy:
+ enabled: false
+ report_only: false
+ directives:
+ base_uri:
+ child_src:
+ connect_src: "'self' http://localhost:3808 ws://localhost:3808 wss://localhost:3000"
+ default_src: "'self'"
+ font_src:
+ form_action:
+ frame_ancestors: "'self'"
+ frame_src: "'self' https://www.google.com/recaptcha/ https://www.recaptcha.net/ https://content.googleapis.com https://content-compute.googleapis.com https://content-cloudbilling.googleapis.com https://content-cloudresourcemanager.googleapis.com"
+ img_src: "* data: blob"
+ manifest_src:
+ media_src:
+ object_src: "'self' http://localhost:3808 'unsafe-inline' 'unsafe-eval' https://www.google.com/recaptcha/ https://www.recaptcha.net/ https://www.gstatic.com/recaptcha/ https://apis.google.com"
+ script_src:
+ style_src: "'self' 'unsafe-inline'"
+ worker_src: "http://localhost:3000 blob:"
+ report_uri:
+
# Trusted Proxies
# Customize if you have GitLab behind a reverse proxy which is running on a different machine.
# Add the IP address for your reverse proxy to the list, otherwise users will appear signed in from that address.
diff --git a/config/initializers/1_settings.rb b/config/initializers/1_settings.rb
index 659801f787d..828732126b6 100644
--- a/config/initializers/1_settings.rb
+++ b/config/initializers/1_settings.rb
@@ -200,6 +200,7 @@ Settings.gitlab.default_projects_features['visibility_level'] = Settings.__sen
Settings.gitlab['domain_whitelist'] ||= []
Settings.gitlab['import_sources'] ||= Gitlab::ImportSources.values
Settings.gitlab['trusted_proxies'] ||= []
+Settings.gitlab['content_security_policy'] ||= Gitlab::ContentSecurityPolicy::ConfigLoader.default_settings_hash
Settings.gitlab['no_todos_messages'] ||= YAML.load_file(Rails.root.join('config', 'no_todos_messages.yml'))
Settings.gitlab['impersonation_enabled'] ||= true if Settings.gitlab['impersonation_enabled'].nil?
Settings.gitlab['usage_ping_enabled'] = true if Settings.gitlab['usage_ping_enabled'].nil?
diff --git a/config/initializers/content_security_policy.rb b/config/initializers/content_security_policy.rb
new file mode 100644
index 00000000000..608d0401a96
--- /dev/null
+++ b/config/initializers/content_security_policy.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+csp_settings = Settings.gitlab.content_security_policy
+
+if csp_settings['enabled']
+ # See https://guides.rubyonrails.org/security.html#content-security-policy
+ Rails.application.config.content_security_policy do |policy|
+ directives = csp_settings.fetch('directives', {})
+ loader = ::Gitlab::ContentSecurityPolicy::ConfigLoader.new(directives)
+ loader.load(policy)
+ end
+
+ Rails.application.config.content_security_policy_report_only = csp_settings['report_only']
+ Rails.application.config.content_security_policy_nonce_generator = ->(request) { SecureRandom.base64(16) }
+end
diff --git a/config/initializers/peek.rb b/config/initializers/peek.rb
index b6c7f1ff4fc..f9055285e5c 100644
--- a/config/initializers/peek.rb
+++ b/config/initializers/peek.rb
@@ -10,9 +10,4 @@ Peek.into Peek::Views::Gitaly
Peek.into Peek::Views::RedisDetailed
Peek.into Peek::Views::Rugged
-# `Peek::Views::GC` is currently disabled in production, as it runs with every request
-# even if PerformanceBar is inactive and clears `GC::Profiler` reports we need for metrics.
-# Check https://gitlab.com/gitlab-org/gitlab-ce/issues/65455
-Peek.into Peek::Views::GC if Rails.env.development?
-
Peek.into Peek::Views::Tracing if Labkit::Tracing.tracing_url_enabled?
diff --git a/db/migrate/20190627100221_add_mr_productivity_metrics.rb b/db/migrate/20190627100221_add_mr_productivity_metrics.rb
new file mode 100644
index 00000000000..b6f1520cb2d
--- /dev/null
+++ b/db/migrate/20190627100221_add_mr_productivity_metrics.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+class AddMrProductivityMetrics < ActiveRecord::Migration[5.1]
+ DOWNTIME = false
+
+ def change
+ add_column :merge_request_metrics, :first_comment_at, :datetime_with_timezone
+ add_column :merge_request_metrics, :first_commit_at, :datetime_with_timezone
+ add_column :merge_request_metrics, :last_commit_at, :datetime_with_timezone
+ add_column :merge_request_metrics, :diff_size, :integer
+ add_column :merge_request_metrics, :modified_paths_size, :integer
+ add_column :merge_request_metrics, :commits_count, :integer
+ end
+end
diff --git a/db/migrate/20190712040400_add_environment_id_to_clusters_kubernetes_namespaces.rb b/db/migrate/20190712040400_add_environment_id_to_clusters_kubernetes_namespaces.rb
new file mode 100644
index 00000000000..5ab5a9ba2f8
--- /dev/null
+++ b/db/migrate/20190712040400_add_environment_id_to_clusters_kubernetes_namespaces.rb
@@ -0,0 +1,10 @@
+# frozen_string_literal: true
+
+class AddEnvironmentIdToClustersKubernetesNamespaces < ActiveRecord::Migration[5.1]
+ DOWNTIME = false
+
+ def change
+ add_reference :clusters_kubernetes_namespaces, :environment,
+ index: true, type: :bigint, foreign_key: { on_delete: :nullify }
+ end
+end
diff --git a/db/migrate/20190712040412_index_clusters_kubernetes_namespaces_on_environment_id.rb b/db/migrate/20190712040412_index_clusters_kubernetes_namespaces_on_environment_id.rb
new file mode 100644
index 00000000000..23082492091
--- /dev/null
+++ b/db/migrate/20190712040412_index_clusters_kubernetes_namespaces_on_environment_id.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+class IndexClustersKubernetesNamespacesOnEnvironmentId < ActiveRecord::Migration[5.1]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+ INDEX_NAME = 'index_kubernetes_namespaces_on_cluster_project_environment_id'
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index :clusters_kubernetes_namespaces, [:cluster_id, :project_id, :environment_id], unique: true, name: INDEX_NAME
+ end
+
+ def down
+ remove_concurrent_index :clusters_kubernetes_namespaces, name: INDEX_NAME
+ end
+end
diff --git a/db/migrate/20190712064021_add_namespace_per_environment_flag_to_clusters.rb b/db/migrate/20190712064021_add_namespace_per_environment_flag_to_clusters.rb
new file mode 100644
index 00000000000..4c8a0ab3def
--- /dev/null
+++ b/db/migrate/20190712064021_add_namespace_per_environment_flag_to_clusters.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+# See http://doc.gitlab.com/ce/development/migration_style_guide.html
+# for more information on how to write migrations for GitLab.
+
+class AddNamespacePerEnvironmentFlagToClusters < ActiveRecord::Migration[5.1]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ add_column_with_default :clusters, :namespace_per_environment, :boolean, default: false
+ end
+
+ def down
+ remove_column :clusters, :namespace_per_environment
+ end
+end
diff --git a/db/post_migrate/20190802235445_add_index_on_id_and_type_and_public_to_keys.rb b/db/post_migrate/20190802235445_add_index_on_id_and_type_and_public_to_keys.rb
new file mode 100644
index 00000000000..9b4d74b4bea
--- /dev/null
+++ b/db/post_migrate/20190802235445_add_index_on_id_and_type_and_public_to_keys.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+class AddIndexOnIdAndTypeAndPublicToKeys < ActiveRecord::Migration[5.2]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ INDEX_NAME = "index_on_deploy_keys_id_and_type_and_public"
+
+ def up
+ add_concurrent_index(:keys,
+ [:id, :type],
+ where: "public = 't'",
+ unique: true,
+ name: INDEX_NAME)
+ end
+
+ def down
+ remove_concurrent_index_by_name(:keys, INDEX_NAME)
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index a9b7c1930e3..828e36aa96c 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
-ActiveRecord::Schema.define(version: 2019_08_02_012622) do
+ActiveRecord::Schema.define(version: 2019_08_02_235445) do
# These are extensions that must be enabled in order to support this database
enable_extension "pg_trgm"
@@ -880,6 +880,7 @@ ActiveRecord::Schema.define(version: 2019_08_02_012622) do
t.integer "cluster_type", limit: 2, default: 3, null: false
t.string "domain"
t.boolean "managed", default: true, null: false
+ t.boolean "namespace_per_environment", default: false, null: false
t.index ["enabled"], name: "index_clusters_on_enabled"
t.index ["user_id"], name: "index_clusters_on_user_id"
end
@@ -984,9 +985,12 @@ ActiveRecord::Schema.define(version: 2019_08_02_012622) do
t.string "encrypted_service_account_token_iv"
t.string "namespace", null: false
t.string "service_account_name"
+ t.bigint "environment_id"
t.index ["cluster_id", "namespace"], name: "kubernetes_namespaces_cluster_and_namespace", unique: true
+ t.index ["cluster_id", "project_id", "environment_id"], name: "index_kubernetes_namespaces_on_cluster_project_environment_id", unique: true
t.index ["cluster_id"], name: "index_clusters_kubernetes_namespaces_on_cluster_id"
t.index ["cluster_project_id"], name: "index_clusters_kubernetes_namespaces_on_cluster_project_id"
+ t.index ["environment_id"], name: "index_clusters_kubernetes_namespaces_on_environment_id"
t.index ["project_id"], name: "index_clusters_kubernetes_namespaces_on_project_id"
end
@@ -1770,6 +1774,7 @@ ActiveRecord::Schema.define(version: 2019_08_02_012622) do
t.boolean "public", default: false, null: false
t.datetime "last_used_at"
t.index ["fingerprint"], name: "index_keys_on_fingerprint", unique: true
+ t.index ["id", "type"], name: "index_on_deploy_keys_id_and_type_and_public", unique: true, where: "(public = true)"
t.index ["user_id"], name: "index_keys_on_user_id"
end
@@ -1979,6 +1984,12 @@ ActiveRecord::Schema.define(version: 2019_08_02_012622) do
t.integer "merged_by_id"
t.integer "latest_closed_by_id"
t.datetime_with_timezone "latest_closed_at"
+ t.datetime_with_timezone "first_comment_at"
+ t.datetime_with_timezone "first_commit_at"
+ t.datetime_with_timezone "last_commit_at"
+ t.integer "diff_size"
+ t.integer "modified_paths_size"
+ t.integer "commits_count"
t.index ["first_deployed_to_production_at"], name: "index_merge_request_metrics_on_first_deployed_to_production_at"
t.index ["latest_closed_at"], name: "index_merge_request_metrics_on_latest_closed_at", where: "(latest_closed_at IS NOT NULL)"
t.index ["latest_closed_by_id"], name: "index_merge_request_metrics_on_latest_closed_by_id"
@@ -3704,6 +3715,7 @@ ActiveRecord::Schema.define(version: 2019_08_02_012622) do
add_foreign_key "clusters_applications_runners", "clusters", on_delete: :cascade
add_foreign_key "clusters_kubernetes_namespaces", "cluster_projects", on_delete: :nullify
add_foreign_key "clusters_kubernetes_namespaces", "clusters", on_delete: :cascade
+ add_foreign_key "clusters_kubernetes_namespaces", "environments", on_delete: :nullify
add_foreign_key "clusters_kubernetes_namespaces", "projects", on_delete: :nullify
add_foreign_key "container_repositories", "projects"
add_foreign_key "dependency_proxy_blobs", "namespaces", column: "group_id", name: "fk_db58bbc5d7", on_delete: :cascade
diff --git a/doc/administration/auth/img/google_secure_ldap_add_step_1.png b/doc/administration/auth/img/google_secure_ldap_add_step_1.png
index fd254443d75..bee9c602a14 100644
--- a/doc/administration/auth/img/google_secure_ldap_add_step_1.png
+++ b/doc/administration/auth/img/google_secure_ldap_add_step_1.png
Binary files differ
diff --git a/doc/administration/auth/img/google_secure_ldap_add_step_2.png b/doc/administration/auth/img/google_secure_ldap_add_step_2.png
index 611a21ae03c..b127410cb8c 100644
--- a/doc/administration/auth/img/google_secure_ldap_add_step_2.png
+++ b/doc/administration/auth/img/google_secure_ldap_add_step_2.png
Binary files differ
diff --git a/doc/administration/auth/img/google_secure_ldap_client_settings.png b/doc/administration/auth/img/google_secure_ldap_client_settings.png
index 3c0b3f3d4bd..868e6645f56 100644
--- a/doc/administration/auth/img/google_secure_ldap_client_settings.png
+++ b/doc/administration/auth/img/google_secure_ldap_client_settings.png
Binary files differ
diff --git a/doc/administration/geo/disaster_recovery/img/checksum-differences-admin-project-page.png b/doc/administration/geo/disaster_recovery/img/checksum-differences-admin-project-page.png
index fd51523104b..0a7b841897b 100644
--- a/doc/administration/geo/disaster_recovery/img/checksum-differences-admin-project-page.png
+++ b/doc/administration/geo/disaster_recovery/img/checksum-differences-admin-project-page.png
Binary files differ
diff --git a/doc/administration/geo/disaster_recovery/img/checksum-differences-admin-projects.png b/doc/administration/geo/disaster_recovery/img/checksum-differences-admin-projects.png
index b2a6da69d3d..85759d903a4 100644
--- a/doc/administration/geo/disaster_recovery/img/checksum-differences-admin-projects.png
+++ b/doc/administration/geo/disaster_recovery/img/checksum-differences-admin-projects.png
Binary files differ
diff --git a/doc/administration/geo/replication/img/geo_architecture.png b/doc/administration/geo/replication/img/geo_architecture.png
index d318cd5d0f4..aac63be41ff 100644
--- a/doc/administration/geo/replication/img/geo_architecture.png
+++ b/doc/administration/geo/replication/img/geo_architecture.png
Binary files differ
diff --git a/doc/administration/gitaly/index.md b/doc/administration/gitaly/index.md
index 432056d48c7..150494c47e5 100644
--- a/doc/administration/gitaly/index.md
+++ b/doc/administration/gitaly/index.md
@@ -36,13 +36,18 @@ installations will be better served with the default configuration
used by Omnibus and the GitLab source installation guide.
Starting with GitLab 11.4, Gitaly is able to serve all Git requests without
-needed a shared NFS mount for Git repository data.
+requiring a shared NFS mount for Git repository data.
Between 11.4 and 11.8 the exception was the
[Elasticsearch indexer](https://gitlab.com/gitlab-org/gitlab-elasticsearch-indexer).
But since 11.8 the indexer uses Gitaly for data access as well. NFS can still
be leveraged for redudancy on block level of the Git data. But only has to
be mounted on the Gitaly server.
+Starting with GitLab 11.8, it is possible to use ElasticSearch in conjunction with
+a Gitaly setup that isn't utilising NFS. In order to use ElasticSearch in this
+scenario, the [new repository indexer](../../integration/elasticsearch.md#elasticsearch-repository-indexer-beta)
+needs to be enabled in your GitLab configuration.
+
NOTE: **Note:** While Gitaly can be used as a replacement for NFS, it's not recommended
to use EFS as it may impact GitLab's performance. Review the [relevant documentation](../high_availability/nfs.md#avoid-using-awss-elastic-file-system-efs)
for more details.
diff --git a/doc/administration/high_availability/img/fully-distributed.png b/doc/administration/high_availability/img/fully-distributed.png
index ad23207134e..c3cd2bf24f0 100644
--- a/doc/administration/high_availability/img/fully-distributed.png
+++ b/doc/administration/high_availability/img/fully-distributed.png
Binary files differ
diff --git a/doc/administration/high_availability/img/horizontal.png b/doc/administration/high_availability/img/horizontal.png
index c3bd489d96f..75d08e1097a 100644
--- a/doc/administration/high_availability/img/horizontal.png
+++ b/doc/administration/high_availability/img/horizontal.png
Binary files differ
diff --git a/doc/administration/high_availability/img/hybrid.png b/doc/administration/high_availability/img/hybrid.png
index 7d4a56bf0ea..8dd9923e597 100644
--- a/doc/administration/high_availability/img/hybrid.png
+++ b/doc/administration/high_availability/img/hybrid.png
Binary files differ
diff --git a/doc/administration/high_availability/monitoring_node.md b/doc/administration/high_availability/monitoring_node.md
index b91a994d01e..b2750603c74 100644
--- a/doc/administration/high_availability/monitoring_node.md
+++ b/doc/administration/high_availability/monitoring_node.md
@@ -18,7 +18,7 @@ The steps below are the minimum necessary to configure a Monitoring node running
Omnibus:
1. SSH into the Monitoring node.
-1. [Download/install](https://about.gitlab.com/install) the Omnibus GitLab
+1. [Download/install](https://about.gitlab.com/install/) the Omnibus GitLab
package you want using **steps 1 and 2** from the GitLab downloads page.
- Do not complete any other steps on the download page.
diff --git a/doc/administration/high_availability/nfs.md b/doc/administration/high_availability/nfs.md
index 294f0e969d5..274bd32299b 100644
--- a/doc/administration/high_availability/nfs.md
+++ b/doc/administration/high_availability/nfs.md
@@ -71,6 +71,11 @@ bug](https://bugzilla.redhat.com/show_bug.cgi?id=1552203) that may be fixed in
[more recent kernels with this
commit](https://github.com/torvalds/linux/commit/95da1b3a5aded124dd1bda1e3cdb876184813140).
+NOTE: **Note** Red Hat Enterprise 7 [shipped a kernel
+update](https://access.redhat.com/errata/RHSA-2019:2029) on August 6,
+2019 that may have resolved this problem. The following instructions may
+not be needed if the latest kernel is updated properly.
+
GitLab recommends all NFS users disable the NFS server
delegation feature. To disable NFS server delegations
on an Linux NFS server, do the following:
diff --git a/doc/administration/img/custom_hooks_error_msg.png b/doc/administration/img/custom_hooks_error_msg.png
index 4f25c471908..e7d5c157d08 100644
--- a/doc/administration/img/custom_hooks_error_msg.png
+++ b/doc/administration/img/custom_hooks_error_msg.png
Binary files differ
diff --git a/doc/administration/monitoring/performance/grafana_configuration.md b/doc/administration/monitoring/performance/grafana_configuration.md
index 4dd0bbbe937..6778c339922 100644
--- a/doc/administration/monitoring/performance/grafana_configuration.md
+++ b/doc/administration/monitoring/performance/grafana_configuration.md
@@ -1,6 +1,6 @@
# Grafana Configuration
-[Grafana](https://grafana.org/) is a tool that allows you to visualize time
+[Grafana](https://grafana.com/) is a tool that allows you to visualize time
series metrics through graphs and dashboards. It supports several backend
data stores, including InfluxDB. GitLab writes performance data to InfluxDB
and Grafana will allow you to query to display useful graphs.
diff --git a/doc/administration/monitoring/performance/img/performance_bar.png b/doc/administration/monitoring/performance/img/performance_bar.png
index 89b09054d46..d1187fd879a 100644
--- a/doc/administration/monitoring/performance/img/performance_bar.png
+++ b/doc/administration/monitoring/performance/img/performance_bar.png
Binary files differ
diff --git a/doc/administration/monitoring/performance/img/performance_bar_gitaly_calls.png b/doc/administration/monitoring/performance/img/performance_bar_gitaly_calls.png
index 265178729c4..2c43201cbd0 100644
--- a/doc/administration/monitoring/performance/img/performance_bar_gitaly_calls.png
+++ b/doc/administration/monitoring/performance/img/performance_bar_gitaly_calls.png
Binary files differ
diff --git a/doc/administration/monitoring/performance/img/performance_bar_redis_calls.png b/doc/administration/monitoring/performance/img/performance_bar_redis_calls.png
index 78dd7594adf..ecb2dffbf8d 100644
--- a/doc/administration/monitoring/performance/img/performance_bar_redis_calls.png
+++ b/doc/administration/monitoring/performance/img/performance_bar_redis_calls.png
Binary files differ
diff --git a/doc/administration/monitoring/performance/img/performance_bar_rugged_calls.png b/doc/administration/monitoring/performance/img/performance_bar_rugged_calls.png
index f4068268137..210f80a713d 100644
--- a/doc/administration/monitoring/performance/img/performance_bar_rugged_calls.png
+++ b/doc/administration/monitoring/performance/img/performance_bar_rugged_calls.png
Binary files differ
diff --git a/doc/administration/monitoring/performance/img/performance_bar_sql_queries.png b/doc/administration/monitoring/performance/img/performance_bar_sql_queries.png
index dab323eb066..6b571f4e85c 100644
--- a/doc/administration/monitoring/performance/img/performance_bar_sql_queries.png
+++ b/doc/administration/monitoring/performance/img/performance_bar_sql_queries.png
Binary files differ
diff --git a/doc/administration/monitoring/performance/img/request_profile_result.png b/doc/administration/monitoring/performance/img/request_profile_result.png
index 3b34f207974..9176a0b49fd 100644
--- a/doc/administration/monitoring/performance/img/request_profile_result.png
+++ b/doc/administration/monitoring/performance/img/request_profile_result.png
Binary files differ
diff --git a/doc/administration/monitoring/performance/performance_bar.md b/doc/administration/monitoring/performance/performance_bar.md
index 2cc78ccc03c..02f4b78bd60 100644
--- a/doc/administration/monitoring/performance/performance_bar.md
+++ b/doc/administration/monitoring/performance/performance_bar.md
@@ -16,7 +16,6 @@ It allows you to see (from left to right):
![Rugged profiling using the Performance Bar](img/performance_bar_rugged_calls.png)
- time taken and number of Redis calls, click through for details of these calls
![Redis profiling using the Performance Bar](img/performance_bar_redis_calls.png)
-- time taken and number of Ruby GC calls
On the far right is a request selector that allows you to view the same metrics
(excluding the page timing and line profiler) for any requests made while the
diff --git a/doc/administration/operations/img/sidekiq-cluster.png b/doc/administration/operations/img/sidekiq-cluster.png
index 4eb1849010e..3899385eb8f 100644
--- a/doc/administration/operations/img/sidekiq-cluster.png
+++ b/doc/administration/operations/img/sidekiq-cluster.png
Binary files differ
diff --git a/doc/administration/pages/img/lets_encrypt_integration_v12_1.png b/doc/administration/pages/img/lets_encrypt_integration_v12_1.png
index 5ab63074e12..0f3ca25ce55 100644
--- a/doc/administration/pages/img/lets_encrypt_integration_v12_1.png
+++ b/doc/administration/pages/img/lets_encrypt_integration_v12_1.png
Binary files differ
diff --git a/doc/administration/troubleshooting/elasticsearch.md b/doc/administration/troubleshooting/elasticsearch.md
index d54dd758d29..c4a7ba01fae 100644
--- a/doc/administration/troubleshooting/elasticsearch.md
+++ b/doc/administration/troubleshooting/elasticsearch.md
@@ -5,17 +5,17 @@ Troubleshooting ElasticSearch requires:
- Knowledge of common terms.
- Establishing within which category the problem fits.
-## Common Terminology
+## Common terminology
- **Lucene**: A full-text search library written in Java.
- **Near Realtime (NRT)**: Refers to the slight latency from the time to index a
document to the time when it becomes searchable.
-- **Cluster**: A collection of one or more nodes that work together to hold all
+- **Cluster**: A collection of one or more nodes that work together to hold all
the data, providing indexing and search capabilities.
- **Node**: A single server that works as part of a cluster.
- **Index**: A collection of documents that have somewhat similar characteristics.
- **Document**: A basic unit of information that can be indexed.
-- **Shards**: Fully-functional and independent subdivisions of indices. Each shard is actually
+- **Shards**: Fully-functional and independent subdivisions of indices. Each shard is actually
a Lucene index.
- **Replicas**: Failover mechanisms that duplicate indices.
@@ -138,7 +138,7 @@ graph TD;
F7(Escalate to<br>GitLab support.)
```
-## Troubleshooting Walkthrough
+## Troubleshooting walkthrough
Most ElasticSearch troubleshooting can be broken down into 4 categories:
@@ -150,7 +150,7 @@ Most ElasticSearch troubleshooting can be broken down into 4 categories:
Generally speaking, if it does not fall into those four categories, it is either:
- Something GitLab support needs to look into.
-- Not a true ElasticSearch issue.
+- Not a true ElasticSearch issue.
Exercise caution. Issues that appear to be ElasticSearch problems can be OS-level issues.
@@ -186,12 +186,12 @@ Moving past that, it is best to attempt the same search using the [ElasticSearch
If the results:
-- Sync up, then there is not a technical "issue" per se. Instead, it might be a problem
- with the ElasticSearch filters we are using. This can be complicated, so it is best to
- escalate to GitLab support to check these and guide you on the potential on whether or
+- Sync up, then there is not a technical "issue" per se. Instead, it might be a problem
+ with the ElasticSearch filters we are using. This can be complicated, so it is best to
+ escalate to GitLab support to check these and guide you on the potential on whether or
not a feature request is needed.
- Do not match up, this indicates a problem with the documents generated from the
- project. It is best to re-index that project and proceed with
+ project. It is best to re-index that project and proceed with
[Troubleshooting indexing](#troubleshooting-indexing).
### Troubleshooting indexing
@@ -200,13 +200,13 @@ Troubleshooting indexing issues can be tricky. It can pretty quickly go to eithe
support or your ElasticSearch admin.
The best place to start is to determine if the issue is with creating an empty index.
-If it is, check on the ElasticSearch side to determine if the `gitlab-production` (the
+If it is, check on the ElasticSearch side to determine if the `gitlab-production` (the
name for the GitLab index) exists. If it exists, manually delete it on the ElasticSearch
-side and attempt to recreate it from the
-[`create_empty_index`](../../integration/elasticsearch.md#gitlab-elasticsearch-rake-tasks)
+side and attempt to recreate it from the
+[`create_empty_index`](../../integration/elasticsearch.md#gitlab-elasticsearch-rake-tasks)
rake task.
-If you still encounter issues, try creating an index manually on the ElasticSearch
+If you still encounter issues, try creating an index manually on the ElasticSearch
instance. The details of the index aren't important here, as we want to test if indices
can be made. If the indices:
@@ -317,7 +317,7 @@ dig further into these.
Feel free to reach out to GitLab support, but this is likely to be something a skilled
ElasticSearch admin has more experience with.
-## Common Issues
+## Common issues
All common issues [should be documented](../../integration/elasticsearch.md#troubleshooting). If not,
feel free to update that page with issues you encounter and solutions.
diff --git a/doc/api/README.md b/doc/api/README.md
index 6cd89e34921..9f23af3f723 100644
--- a/doc/api/README.md
+++ b/doc/api/README.md
@@ -697,10 +697,10 @@ programming languages. Visit the [GitLab website] for a complete list.
## Rate limits
-For administrator documentation on rate limit settings, check out
+For administrator documentation on rate limit settings, see
[Rate limits](../security/rate_limits.md). To find the settings that are
specifically used by GitLab.com, see
-[GitLab.com-specific rate limits](../user/gitlab_com/index.md).
+[GitLab.com-specific rate limits](../user/gitlab_com/index.md#gitlabcom-specific-rate-limits).
[GitLab website]: https://about.gitlab.com/applications/#api-clients "Clients using the GitLab API"
[lib-api-url]: https://gitlab.com/gitlab-org/gitlab-ce/tree/master/lib/api/api.rb
diff --git a/doc/api/merge_request_approvals.md b/doc/api/merge_request_approvals.md
index c211916464a..cc95689a65f 100644
--- a/doc/api/merge_request_approvals.md
+++ b/doc/api/merge_request_approvals.md
@@ -72,13 +72,14 @@ POST /projects/:id/approvals
**Parameters:**
-| Attribute | Type | Required | Description |
-| ------------------------------------------------ | ------- | -------- | ---------------------------------------------------------- |
-| `id` | integer | yes | The ID of a project |
-| `approvals_before_merge` | integer | no | How many approvals are required before an MR can be merged |
-| `reset_approvals_on_push` | boolean | no | Reset approvals on a new push |
-| `disable_overriding_approvers_per_merge_request` | boolean | no | Allow/Disallow overriding approvers per MR |
-| `merge_requests_author_approval` | boolean | no | Allow/Disallow authors be able to self approve merge requests |
+| Attribute | Type | Required | Description |
+| ------------------------------------------------ | ------- | -------- | --------------------------------------------------------------------------------------------------- |
+| `id` | integer | yes | The ID of a project |
+| `approvals_before_merge` | integer | no | How many approvals are required before an MR can be merged |
+| `reset_approvals_on_push` | boolean | no | Reset approvals on a new push |
+| `disable_overriding_approvers_per_merge_request` | boolean | no | Allow/Disallow overriding approvers per MR |
+| `merge_requests_author_approval` | boolean | no | Allow/Disallow authors from self approving merge requests; `true` means authors cannot self approve |
+| `merge_requests_disable_committers_approval` | boolean | no | Allow/Disallow committers from self approving merge requests |
```json
{
@@ -115,7 +116,8 @@ POST /projects/:id/approvals
"approvals_before_merge": 2,
"reset_approvals_on_push": true,
"disable_overriding_approvers_per_merge_request": false,
- "merge_requests_author_approval": false
+ "merge_requests_author_approval": false,
+ "merge_requests_disable_committers_approval": false
}
```
diff --git a/doc/api/releases/img/upcoming_release_v12_1.png b/doc/api/releases/img/upcoming_release_v12_1.png
index 8bd8573ce84..cc3070fd19d 100644
--- a/doc/api/releases/img/upcoming_release_v12_1.png
+++ b/doc/api/releases/img/upcoming_release_v12_1.png
Binary files differ
diff --git a/doc/ci/docker/using_docker_build.md b/doc/ci/docker/using_docker_build.md
index 278a0d6e934..2cbad5f101c 100644
--- a/doc/ci/docker/using_docker_build.md
+++ b/doc/ci/docker/using_docker_build.md
@@ -98,9 +98,62 @@ The second approach is to use the special docker-in-docker (dind)
(`docker`) and run the job script in context of that
image in privileged mode.
-NOTE: **Note:** `docker-compose` is not part of docker-in-docker (dind). In case you'd like to use `docker-compose` in your CI builds, please follow the [installation instructions for docker-compose](https://docs.docker.com/compose/install/) provided by docker.
+NOTE: **Note:**
+`docker-compose` is not part of docker-in-docker (dind). To use `docker-compose` in your
+CI builds, follow the `docker-compose`
+[installation instructions](https://docs.docker.com/compose/install/).
-In order to do that, follow the steps:
+DANGER: **Danger:**
+By enabling `--docker-privileged`, you are effectively disabling all of
+the security mechanisms of containers and exposing your host to privilege
+escalation which can lead to container breakout. For more information, check
+out the official Docker documentation on
+[Runtime privilege and Linux capabilities][docker-cap].
+
+Docker-in-Docker works well, and is the recommended configuration, but it is
+not without its own challenges:
+
+- When using docker-in-docker, each job is in a clean environment without the past
+ history. Concurrent jobs work fine because every build gets it's own
+ instance of Docker engine so they won't conflict with each other. But this
+ also means jobs can be slower because there's no caching of layers.
+- By default, `docker:dind` uses `--storage-driver vfs` which is the slowest
+ form offered. To use a different driver, see
+ [Using the overlayfs driver](#using-the-overlayfs-driver).
+- Since the `docker:dind` container and the runner container don't share their
+ root filesystem, the job's working directory can be used as a mount point for
+ child containers. For example, if you have files you want to share with a
+ child container, you may create a subdirectory under `/builds/$CI_PROJECT_PATH`
+ and use it as your mount point (for a more thorough explanation, check [issue
+ #41227](https://gitlab.com/gitlab-org/gitlab-ce/issues/41227)):
+
+ ```yaml
+ variables:
+ MOUNT_POINT: /builds/$CI_PROJECT_PATH/mnt
+
+ script:
+ - mkdir -p "$MOUNT_POINT"
+ - docker run -v "$MOUNT_POINT:/mnt" my-docker-image
+ ```
+
+An example project using this approach can be found here: <https://gitlab.com/gitlab-examples/docker>.
+
+In the examples below, we are using Docker images tags to specify a
+specific version, such as `docker:19.03.1`. If tags like `docker:stable`
+are used, you have no control over what version is going to be used and this
+can lead to unpredictable behavior, especially when new versions are
+released.
+
+#### TLS enabled
+
+NOTE: **Note**
+This requires GitLab Runner 11.11 or higher.
+
+The Docker daemon supports connection over TLS and it's done by default
+for Docker 19.03.1 or higher. This is the **suggested** way to use the
+docker-in-docker service and
+[GitLab.com Shared Runners](../../user/gitlab_com/index.html#shared-runners)
+support this.
1. Install [GitLab Runner](https://docs.gitlab.com/runner/install).
@@ -113,22 +166,21 @@ In order to do that, follow the steps:
--registration-token REGISTRATION_TOKEN \
--executor docker \
--description "My Docker Runner" \
- --docker-image "docker:stable" \
- --docker-privileged
+ --docker-image "docker:19.03.1" \
+ --docker-privileged \
+ --docker-volumes "/certs/client"
```
The above command will register a new Runner to use the special
- `docker:stable` image which is provided by Docker. **Notice that it's using
- the `privileged` mode to start the build and service containers.** If you
- want to use [docker-in-docker] mode, you always have to use `privileged = true`
- in your Docker containers.
+ `docker:19.03.1` image, which is provided by Docker. **Notice that it's
+ using the `privileged` mode to start the build and service
+ containers.** If you want to use [docker-in-docker] mode, you always
+ have to use `privileged = true` in your Docker containers.
- DANGER: **Danger:**
- By enabling `--docker-privileged`, you are effectively disabling all of
- the security mechanisms of containers and exposing your host to privilege
- escalation which can lead to container breakout. For more information, check
- out the official Docker documentation on
- [Runtime privilege and Linux capabilities][docker-cap].
+ This will also mount `/certs/client` for the service and build
+ container, which is needed for the docker client to use the
+ certificates inside of that directory. For more information how
+ Docker with TLS works check <https://hub.docker.com/_/docker/#tls>.
The above command will create a `config.toml` entry similar to this:
@@ -139,41 +191,48 @@ In order to do that, follow the steps:
executor = "docker"
[runners.docker]
tls_verify = false
- image = "docker:stable"
+ image = "docker:19.03.1"
privileged = true
disable_cache = false
- volumes = ["/cache"]
+ volumes = ["/certs/client", "/cache"]
[runners.cache]
- Insecure = false
- ```
+ [runners.cache.s3]
+ [runners.cache.gcs]
+ ```
1. You can now use `docker` in the build script (note the inclusion of the
- `docker:dind` service):
+ `docker:19.03.1-dind` service):
```yaml
- image: docker:stable
+ image: docker:19.03.1
variables:
- # When using dind service we need to instruct docker, to talk with the
- # daemon started inside of the service. The daemon is available with
- # a network connection instead of the default /var/run/docker.sock socket.
+ # When using dind service, we need to instruct docker, to talk with
+ # the daemon started inside of the service. The daemon is available
+ # with a network connection instead of the default
+ # /var/run/docker.sock socket. docker:19.03.1 does this automatically
+ # by setting the DOCKER_HOST in
+ # https://github.com/docker-library/docker/blob/d45051476babc297257df490d22cbd806f1b11e4/19.03.1/docker-entrypoint.sh#L23-L29
#
# The 'docker' hostname is the alias of the service container as described at
- # https://docs.gitlab.com/ee/ci/docker/using_docker_images.html#accessing-the-services
+ # https://docs.gitlab.com/ee/ci/docker/using_docker_images.html#accessing-the-services.
#
- # Note that if you're using the Kubernetes executor, the variable should be set to
- # tcp://localhost:2375/ because of how the Kubernetes executor connects services
- # to the job container
- # DOCKER_HOST: tcp://localhost:2375/
+ # Note that if you're using the Kubernetes executor, the variable
+ # should be set to tcp://localhost:2376/ because of how the
+ # Kubernetes executor connects services to the job container
+ # DOCKER_HOST: tcp://localhost:2376/
#
- # For non-Kubernetes executors, we use tcp://docker:2375/
- DOCKER_HOST: tcp://docker:2375/
# When using dind, it's wise to use the overlayfs driver for
# improved performance.
DOCKER_DRIVER: overlay2
+ # Specify to Docker where to create the certificates, Docker will
+ # create them automatically on boot, and will create
+ # `/certs/client` that will be shared between the service and job
+ # container, thanks to volume mount from config.toml
+ DOCKER_TLS_CERTDIR: "/certs"
services:
- - docker:dind
+ - docker:19.03.1-dind
before_script:
- docker info
@@ -185,33 +244,70 @@ In order to do that, follow the steps:
- docker run my-docker-image /script/to/run/tests
```
-Docker-in-Docker works well, and is the recommended configuration, but it is
-not without its own challenges:
+#### TLS disabled
-- When using docker-in-docker, each job is in a clean environment without the past
- history. Concurrent jobs work fine because every build gets it's own
- instance of Docker engine so they won't conflict with each other. But this
- also means jobs can be slower because there's no caching of layers.
-- By default, `docker:dind` uses `--storage-driver vfs` which is the slowest
- form offered. To use a different driver, see
- [Using the overlayfs driver](#using-the-overlayfs-driver).
-- Since the `docker:dind` container and the runner container don't share their
- root filesystem, the job's working directory can be used as a mount point for
- children containers. For example, if you have files you want to share with a
- child container, you may create a subdirectory under `/builds/$CI_PROJECT_PATH`
- and use it as your mount point (for a more thorough explanation, check [issue
- #41227](https://gitlab.com/gitlab-org/gitlab-ce/issues/41227)):
+Sometimes there are legitimate reasons why you might want to disable TLS.
+For example, you have no control over the GitLab Runner configuration
+that you are using.
- ```yaml
- variables:
- MOUNT_POINT: /builds/$CI_PROJECT_PATH/mnt
+Assuming that the Runner `config.toml` is similar to:
- script:
- - mkdir -p "$MOUNT_POINT"
- - docker run -v "$MOUNT_POINT:/mnt" my-docker-image
- ```
+```toml
+[[runners]]
+ url = "https://gitlab.com/"
+ token = TOKEN
+ executor = "docker"
+ [runners.docker]
+ tls_verify = false
+ image = "docker:19.03.1"
+ privileged = true
+ disable_cache = false
+ volumes = ["/cache"]
+ [runners.cache]
+ [runners.cache.s3]
+ [runners.cache.gcs]
+```
-An example project using this approach can be found here: <https://gitlab.com/gitlab-examples/docker>.
+You can now use `docker` in the build script (note the inclusion of the
+`docker:19.03.1-dind` service):
+
+```yaml
+image: docker:19.03.1
+
+variables:
+ # When using dind service we need to instruct docker, to talk with the
+ # daemon started inside of the service. The daemon is available with
+ # a network connection instead of the default /var/run/docker.sock socket.
+ #
+ # The 'docker' hostname is the alias of the service container as described at
+ # https://docs.gitlab.com/ee/ci/docker/using_docker_images.html#accessing-the-services
+ #
+ # Note that if you're using the Kubernetes executor, the variable should be set to
+ # tcp://localhost:2375/ because of how the Kubernetes executor connects services
+ # to the job container
+ # DOCKER_HOST: tcp://localhost:2375/
+ #
+ # For non-Kubernetes executors, we use tcp://docker:2375/
+ DOCKER_HOST: tcp://docker:2375/
+ # When using dind, it's wise to use the overlayfs driver for
+ # improved performance.
+ DOCKER_DRIVER: overlay2
+ #
+ # This will instruct Docker not to start over TLS.
+ DOCKER_TLS_CERTDIR: ""
+
+services:
+ - docker:19.03.1-dind
+
+before_script:
+ - docker info
+
+build:
+ stage: build
+ script:
+ - docker build -t my-docker-image .
+ - docker run my-docker-image /script/to/run/tests
+```
### Use Docker socket binding
diff --git a/doc/ci/examples/end_to_end_testing_webdriverio/img/deployed_dependency_update.png b/doc/ci/examples/end_to_end_testing_webdriverio/img/deployed_dependency_update.png
index c45d70d7f7a..9fe1739f37e 100644
--- a/doc/ci/examples/end_to_end_testing_webdriverio/img/deployed_dependency_update.png
+++ b/doc/ci/examples/end_to_end_testing_webdriverio/img/deployed_dependency_update.png
Binary files differ
diff --git a/doc/ci/img/collapsible_log.png b/doc/ci/img/collapsible_log.png
index 2785033b349..d2a570e246e 100644
--- a/doc/ci/img/collapsible_log.png
+++ b/doc/ci/img/collapsible_log.png
Binary files differ
diff --git a/doc/ci/img/deployments_view.png b/doc/ci/img/deployments_view.png
index 12090434bef..9e2b7e89577 100644
--- a/doc/ci/img/deployments_view.png
+++ b/doc/ci/img/deployments_view.png
Binary files differ
diff --git a/doc/ci/img/environments_available.png b/doc/ci/img/environments_available.png
index 48fc6effc2d..6c64e9398f7 100644
--- a/doc/ci/img/environments_available.png
+++ b/doc/ci/img/environments_available.png
Binary files differ
diff --git a/doc/ci/img/environments_mr_review_app.png b/doc/ci/img/environments_mr_review_app.png
index 6a7b7ce5679..86c20d8d3b6 100644
--- a/doc/ci/img/environments_mr_review_app.png
+++ b/doc/ci/img/environments_mr_review_app.png
Binary files differ
diff --git a/doc/ci/img/manual_job_variables.png b/doc/ci/img/manual_job_variables.png
index c7d62477cdd..a5ed351fdcd 100644
--- a/doc/ci/img/manual_job_variables.png
+++ b/doc/ci/img/manual_job_variables.png
Binary files differ
diff --git a/doc/ci/introduction/img/gitlab_workflow_example_11_9.png b/doc/ci/introduction/img/gitlab_workflow_example_11_9.png
index 204e9c462e5..f3fb9444b55 100644
--- a/doc/ci/introduction/img/gitlab_workflow_example_11_9.png
+++ b/doc/ci/introduction/img/gitlab_workflow_example_11_9.png
Binary files differ
diff --git a/doc/ci/introduction/img/gitlab_workflow_example_extended_11_11.png b/doc/ci/introduction/img/gitlab_workflow_example_extended_11_11.png
index 5089a1088c5..a0874f66eaa 100644
--- a/doc/ci/introduction/img/gitlab_workflow_example_extended_11_11.png
+++ b/doc/ci/introduction/img/gitlab_workflow_example_extended_11_11.png
Binary files differ
diff --git a/doc/ci/merge_request_pipelines/img/merge_request.png b/doc/ci/merge_request_pipelines/img/merge_request.png
index d03fdc6a885..bb64e17cc91 100644
--- a/doc/ci/merge_request_pipelines/img/merge_request.png
+++ b/doc/ci/merge_request_pipelines/img/merge_request.png
Binary files differ
diff --git a/doc/ci/merge_request_pipelines/pipelines_for_merged_results/img/merge_request_pipeline.png b/doc/ci/merge_request_pipelines/pipelines_for_merged_results/img/merge_request_pipeline.png
index 58d5581f628..6d4b66824e1 100644
--- a/doc/ci/merge_request_pipelines/pipelines_for_merged_results/img/merge_request_pipeline.png
+++ b/doc/ci/merge_request_pipelines/pipelines_for_merged_results/img/merge_request_pipeline.png
Binary files differ
diff --git a/doc/ci/merge_request_pipelines/pipelines_for_merged_results/img/merge_request_pipeline_config.png b/doc/ci/merge_request_pipelines/pipelines_for_merged_results/img/merge_request_pipeline_config.png
index 0a84e61d284..3ee9d8ec93b 100644
--- a/doc/ci/merge_request_pipelines/pipelines_for_merged_results/img/merge_request_pipeline_config.png
+++ b/doc/ci/merge_request_pipelines/pipelines_for_merged_results/img/merge_request_pipeline_config.png
Binary files differ
diff --git a/doc/ci/merge_request_pipelines/pipelines_for_merged_results/merge_trains/img/merge_train_cancel_v12_0.png b/doc/ci/merge_request_pipelines/pipelines_for_merged_results/merge_trains/img/merge_train_cancel_v12_0.png
index 1561fdcc7a5..d7720ac1143 100644
--- a/doc/ci/merge_request_pipelines/pipelines_for_merged_results/merge_trains/img/merge_train_cancel_v12_0.png
+++ b/doc/ci/merge_request_pipelines/pipelines_for_merged_results/merge_trains/img/merge_train_cancel_v12_0.png
Binary files differ
diff --git a/doc/ci/merge_request_pipelines/pipelines_for_merged_results/merge_trains/img/merge_train_config_v12_0.png b/doc/ci/merge_request_pipelines/pipelines_for_merged_results/merge_trains/img/merge_train_config_v12_0.png
index fb0af43556e..9da959ad440 100644
--- a/doc/ci/merge_request_pipelines/pipelines_for_merged_results/merge_trains/img/merge_train_config_v12_0.png
+++ b/doc/ci/merge_request_pipelines/pipelines_for_merged_results/merge_trains/img/merge_train_config_v12_0.png
Binary files differ
diff --git a/doc/ci/merge_request_pipelines/pipelines_for_merged_results/merge_trains/img/merge_train_failure.png b/doc/ci/merge_request_pipelines/pipelines_for_merged_results/merge_trains/img/merge_train_failure.png
index a8916e5721c..8a795fff432 100644
--- a/doc/ci/merge_request_pipelines/pipelines_for_merged_results/merge_trains/img/merge_train_failure.png
+++ b/doc/ci/merge_request_pipelines/pipelines_for_merged_results/merge_trains/img/merge_train_failure.png
Binary files differ
diff --git a/doc/ci/merge_request_pipelines/pipelines_for_merged_results/merge_trains/img/merge_train_immediate_merge.png b/doc/ci/merge_request_pipelines/pipelines_for_merged_results/merge_trains/img/merge_train_immediate_merge.png
index 65ff7e3d674..03bc61129ba 100644
--- a/doc/ci/merge_request_pipelines/pipelines_for_merged_results/merge_trains/img/merge_train_immediate_merge.png
+++ b/doc/ci/merge_request_pipelines/pipelines_for_merged_results/merge_trains/img/merge_train_immediate_merge.png
Binary files differ
diff --git a/doc/ci/merge_request_pipelines/pipelines_for_merged_results/merge_trains/img/merge_train_position_v12_0.png b/doc/ci/merge_request_pipelines/pipelines_for_merged_results/merge_trains/img/merge_train_position_v12_0.png
index 70916bc0e00..ec4b157d428 100644
--- a/doc/ci/merge_request_pipelines/pipelines_for_merged_results/merge_trains/img/merge_train_position_v12_0.png
+++ b/doc/ci/merge_request_pipelines/pipelines_for_merged_results/merge_trains/img/merge_train_position_v12_0.png
Binary files differ
diff --git a/doc/ci/merge_request_pipelines/pipelines_for_merged_results/merge_trains/img/merge_train_start_v12_0.png b/doc/ci/merge_request_pipelines/pipelines_for_merged_results/merge_trains/img/merge_train_start_v12_0.png
index f20108157d2..a4d0c8cf0e6 100644
--- a/doc/ci/merge_request_pipelines/pipelines_for_merged_results/merge_trains/img/merge_train_start_v12_0.png
+++ b/doc/ci/merge_request_pipelines/pipelines_for_merged_results/merge_trains/img/merge_train_start_v12_0.png
Binary files differ
diff --git a/doc/ci/merge_request_pipelines/pipelines_for_merged_results/merge_trains/img/merge_train_start_when_pipeline_succeeds_v12_0.png b/doc/ci/merge_request_pipelines/pipelines_for_merged_results/merge_trains/img/merge_train_start_when_pipeline_succeeds_v12_0.png
index 62c2f2f5ff5..45762b8e85e 100644
--- a/doc/ci/merge_request_pipelines/pipelines_for_merged_results/merge_trains/img/merge_train_start_when_pipeline_succeeds_v12_0.png
+++ b/doc/ci/merge_request_pipelines/pipelines_for_merged_results/merge_trains/img/merge_train_start_when_pipeline_succeeds_v12_0.png
Binary files differ
diff --git a/doc/ci/review_apps/img/review_button.png b/doc/ci/review_apps/img/review_button.png
index 0b231c50858..4f1cf4d7cfd 100644
--- a/doc/ci/review_apps/img/review_button.png
+++ b/doc/ci/review_apps/img/review_button.png
Binary files differ
diff --git a/doc/ci/variables/README.md b/doc/ci/variables/README.md
index c63b1e104ed..01edd873a8d 100644
--- a/doc/ci/variables/README.md
+++ b/doc/ci/variables/README.md
@@ -94,7 +94,7 @@ This means that the value of the variable will be hidden in job logs,
though it must match certain requirements to do so:
- The value must be in a single line.
-- The value must only consist of characters from the Base64 alphabet, defined in [RFC4648](https://tools.ietf.org/html/rfc4648).
+- The value must only consist of characters from the Base64 alphabet ([RFC4648](https://tools.ietf.org/html/rfc4648)) with the addition of `@` and `:`.
- The value must be at least 8 characters long.
- The value must not use variables.
diff --git a/doc/ci/variables/img/custom_variables_output.png b/doc/ci/variables/img/custom_variables_output.png
index 29f5c63b3d9..797e9ec07b9 100644
--- a/doc/ci/variables/img/custom_variables_output.png
+++ b/doc/ci/variables/img/custom_variables_output.png
Binary files differ
diff --git a/doc/ci/variables/img/new_custom_variables_example.png b/doc/ci/variables/img/new_custom_variables_example.png
index efe104efe4c..bb60e6bab21 100644
--- a/doc/ci/variables/img/new_custom_variables_example.png
+++ b/doc/ci/variables/img/new_custom_variables_example.png
Binary files differ
diff --git a/doc/ci/variables/img/override_variable_manual_pipeline.png b/doc/ci/variables/img/override_variable_manual_pipeline.png
index 3c8c59720cf..c77c5cb7764 100644
--- a/doc/ci/variables/img/override_variable_manual_pipeline.png
+++ b/doc/ci/variables/img/override_variable_manual_pipeline.png
Binary files differ
diff --git a/doc/ci/variables/img/variable_types_usage_example.png b/doc/ci/variables/img/variable_types_usage_example.png
index 0e8bde891fe..c2ae32fd048 100644
--- a/doc/ci/variables/img/variable_types_usage_example.png
+++ b/doc/ci/variables/img/variable_types_usage_example.png
Binary files differ
diff --git a/doc/customization/branded_login_page.md b/doc/customization/branded_login_page.md
index b892f59d777..afcc2b71284 100644
--- a/doc/customization/branded_login_page.md
+++ b/doc/customization/branded_login_page.md
@@ -1,19 +1,38 @@
-# Changing the appearance of the login page
+---
+type: howto
+---
-GitLab offers a way to put your company's identity on the login page of your GitLab server and make it a branded login page.
+# Changing the logo and description on the login page
-By default, the page shows the GitLab logo and description.
+You can customize the login page of your GitLab server to show the logo and
+description of your organization.
+
+By default, the page shows the GitLab logo and description:
![default_login_page](branded_login_page/default_login_page.png)
-## Changing the appearance of the login page
+To customize the login page:
-Navigate to the **Admin** area and go to the **Appearance** page.
+1. Navigate to the **Admin** area and go to the **Appearance** page.
+1. Fill in your desired Title and Description. You can also choose an image file
+ of the logo for your organization.
-Fill in the required details like Title, Description and upload the company logo.
+ ![appearance](branded_login_page/appearance.png)
-![appearance](branded_login_page/appearance.png)
+1. Save your changes.
-After saving the page, your GitLab login page will have the details you filled in:
+Your GitLab login page will display the details you provided:
![company_login_page](branded_login_page/custom_sign_in.png)
+
+<!-- ## Troubleshooting
+
+Include any troubleshooting steps that you can foresee. If you know beforehand what issues
+one might have when setting this up, or when something is changed, or on upgrading, it's
+important to describe those, too. Think of things that may go wrong and include them here.
+This is important to minimize requests for support, and to avoid doc comments with
+questions that you know someone might ask.
+
+Each scenario can be a third-level heading, e.g. `### Getting error message X`.
+If you have none to add when creating a doc, leave this section in place
+but commented out to help encourage others to add to it in the future. -->
diff --git a/doc/customization/branded_page_and_email_header.md b/doc/customization/branded_page_and_email_header.md
index 9a0f0b382fa..370c1461d30 100644
--- a/doc/customization/branded_page_and_email_header.md
+++ b/doc/customization/branded_page_and_email_header.md
@@ -1,15 +1,37 @@
-# Changing the logo on the overall page and email header
+---
+type: howto
+---
-Navigate to the **Admin** area and go to the **Appearance** page.
+# Changing the navigation bar and email header logo
-Upload the custom logo (**Header logo**) in the section **Navigation bar**.
+You can customize the logo that appears in email headers and in the navigation
+bar on pages that are displayed by your GitLab server.
-![appearance](branded_page_and_email_header/appearance.png)
+1. Navigate to the **Admin** area and go to the **Appearance** page, then locate
+ the **Navigation bar** section.
+1. For the **Header Logo**, choose an image file of the logo for your
+ organization.
-After saving the page, your GitLab navigation bar will contain the custom logo:
+ ![appearance](branded_page_and_email_header/appearance.png)
+
+1. Save your changes.
+
+Your GitLab navigation bar will display the custom logo:
![custom_brand_header](branded_page_and_email_header/custom_brand_header.png)
-The GitLab pipeline emails will also have the custom logo:
+The GitLab pipeline emails will also display the custom logo:
![custom_email_header](branded_page_and_email_header/custom_email_header.png)
+
+<!-- ## Troubleshooting
+
+Include any troubleshooting steps that you can foresee. If you know beforehand what issues
+one might have when setting this up, or when something is changed, or on upgrading, it's
+important to describe those, too. Think of things that may go wrong and include them here.
+This is important to minimize requests for support, and to avoid doc comments with
+questions that you know someone might ask.
+
+Each scenario can be a third-level heading, e.g. `### Getting error message X`.
+If you have none to add when creating a doc, leave this section in place
+but commented out to help encourage others to add to it in the future. -->
diff --git a/doc/customization/favicon.md b/doc/customization/favicon.md
index 45a18159b5e..dbde6e8c03b 100644
--- a/doc/customization/favicon.md
+++ b/doc/customization/favicon.md
@@ -1,16 +1,37 @@
+---
+type: howto
+---
+
# Changing the favicon
> [Introduced][ce-14497] in GitLab 11.0.
[ce-14497]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/14497
-Navigate to the **Admin** area and go to the **Appearance** page.
+You can customize the favicon (the icon displayed in your web browser's
+address bar and web page tabs) for your GitLab server.
+
+1. Navigate to the **Admin** area and go to the **Appearance** page, then
+ locate the **Favicon** section.
+1. Upload an image file of your favicon.
-Upload the custom favicon (**Favicon**) in the section **Favicon**.
+ ![appearance](favicon/appearance.png)
-![appearance](favicon/appearance.png)
+1. Save your changes.
-After saving the page, the new favicon will be shown in the browser. The main
-favicon as well as the CI status icons will show the custom icon:
+Your new favicon will display in the browser. The main favicon and the CI
+status icons will show the custom icon:
![custom_favicon](favicon/custom_favicon.png)
+
+<!-- ## Troubleshooting
+
+Include any troubleshooting steps that you can foresee. If you know beforehand what issues
+one might have when setting this up, or when something is changed, or on upgrading, it's
+important to describe those, too. Think of things that may go wrong and include them here.
+This is important to minimize requests for support, and to avoid doc comments with
+questions that you know someone might ask.
+
+Each scenario can be a third-level heading, e.g. `### Getting error message X`.
+If you have none to add when creating a doc, leave this section in place
+but commented out to help encourage others to add to it in the future. -->
diff --git a/doc/customization/help_message.md b/doc/customization/help_message.md
index c2e592d03bf..a4d8f295750 100644
--- a/doc/customization/help_message.md
+++ b/doc/customization/help_message.md
@@ -1,13 +1,36 @@
-# GitLab Help custom text
+---
+type: howto
+---
-In larger organizations it is useful to have information about who has the responsibility of maintaining the company GitLab server.
+# Customizing the 'Help' and login page messages
-1. Navigate to the admin area, click on **Preferences** and expand **Help page**.
+In large organizations, it is useful to have information about who maintains
+the company GitLab server. You can customize and display this information on
+the GitLab login page and on the GitLab server's `/help` page.
-1. Under **Help text** fill in the required information about the person(s) administering GitLab or any other information relevant to your needs.
+1. Navigate to the **Admin** area, then click on **Preferences** and expand
+ **Help page**.
+1. Under **Help page text**, fill in the required information about the
+ person(s) administering GitLab. This text can also contain any other
+ information that you wish to display to users.
- ![help message](help_message/help_text.png)
+ ![help message](help_message/help_text.png)
-1. After saving the page this information will be shown on the GitLab login page and on the GitLab `/help` page (e.g., <https://gitlab.com/help>).
+1. Save your changes.
- ![help text on help page](help_message/help_text_on_help_page.png)
+The information you entered will be shown on the GitLab login page and on the
+GitLab `/help` page (e.g., <https://gitlab.com/help>).
+
+![help text on help page](help_message/help_text_on_help_page.png)
+
+<!-- ## Troubleshooting
+
+Include any troubleshooting steps that you can foresee. If you know beforehand what issues
+one might have when setting this up, or when something is changed, or on upgrading, it's
+important to describe those, too. Think of things that may go wrong and include them here.
+This is important to minimize requests for support, and to avoid doc comments with
+questions that you know someone might ask.
+
+Each scenario can be a third-level heading, e.g. `### Getting error message X`.
+If you have none to add when creating a doc, leave this section in place
+but commented out to help encourage others to add to it in the future. -->
diff --git a/doc/customization/help_message/help_text.png b/doc/customization/help_message/help_text.png
index 99697a106bf..5fcabcdb757 100644
--- a/doc/customization/help_message/help_text.png
+++ b/doc/customization/help_message/help_text.png
Binary files differ
diff --git a/doc/customization/index.md b/doc/customization/index.md
index 0198059297f..f17a2d80e2c 100644
--- a/doc/customization/index.md
+++ b/doc/customization/index.md
@@ -1,18 +1,18 @@
---
+type: index
description: Learn how to customize GitLab's appearance for self-managed installations.
---
# Customizing GitLab's appearance **(CORE ONLY)**
-For GitLab self-managed instances, it's possible to customize
-a few pages.
+For GitLab self-managed instances, you can customize the page logo,
+email headers, favicon, and several other aspects of GitLab's appearance.
-Read through the following documents to adjust GitLab's
-look and feel to meet your needs:
+The following pages explain how to customize the appearance of your instance:
-- [Custom login page](branded_login_page.md)
-- [Custom header and email logo](branded_page_and_email_header.md)
-- [Custom favicon](favicon.md)
-- [Libravatar](libravatar.md)
-- [New project page](new_project_page.md)
-- [Custom `/help` message](help_message.md) \ No newline at end of file
+- [Changing the logo and description on the login page](branded_login_page.md)
+- [Changing the navigation bar and email header logo](branded_page_and_email_header.md)
+- [Changing the favicon](favicon.md)
+- [Customizing the new project page](new_project_page.md)
+- [Customizing the `/help` and login page messages](help_message.md)
+- [Using the Libravatar service with GitLab](libravatar.md)
diff --git a/doc/customization/libravatar.md b/doc/customization/libravatar.md
index e618f3be2fe..1c3bf877fa1 100644
--- a/doc/customization/libravatar.md
+++ b/doc/customization/libravatar.md
@@ -1,14 +1,20 @@
-# Use Libravatar service with GitLab
+---
+type: howto
+---
-GitLab by default supports [Gravatar](https://gravatar.com) avatar service.
-Libravatar is a service which delivers your avatar (profile picture) to other websites and their API is
-[heavily based on gravatar](https://wiki.libravatar.org/api/).
+# Using the Libravatar service with GitLab
-This means that it is not complicated to switch to Libravatar avatar service or even self hosted Libravatar server.
+GitLab by default supports the [Gravatar](https://gravatar.com) avatar service.
+
+Libravatar is another service that delivers your avatar (profile picture) to
+other websites. The Libravatar API is
+[heavily based on gravatar](https://wiki.libravatar.org/api/), so you can
+easily switch to the Libravatar avatar service or even a self-hosted Libravatar
+server.
## Configuration
-In [gitlab.yml gravatar section](https://gitlab.com/gitlab-org/gitlab-ce/blob/672bd3902d86b78d730cea809fce312ec49d39d7/config/gitlab.yml.example#L122) set
+In the [gitlab.yml gravatar section](https://gitlab.com/gitlab-org/gitlab-ce/blob/672bd3902d86b78d730cea809fce312ec49d39d7/config/gitlab.yml.example#L122), set
the configuration options as follows:
### For HTTP
@@ -29,12 +35,14 @@ the configuration options as follows:
ssl_url: "https://seccdn.libravatar.org/avatar/%{hash}?s=%{size}&d=identicon"
```
-### Self-hosted
+### Self-hosted Libravatar server
-If you are [running your own libravatar service](https://wiki.libravatar.org/running_your_own/) the URL will be different in the configuration
-but the important part is to provide the same placeholders so GitLab can parse the URL correctly.
+If you are [running your own libravatar service](https://wiki.libravatar.org/running_your_own/),
+the URL will be different in the configuration, but you must provide the same
+placeholders so GitLab can parse the URL correctly.
-For example, you host a service on `http://libravatar.example.com` the `plain_url` you need to supply in `gitlab.yml` is
+For example, you host a service on `http://libravatar.example.com` and the
+`plain_url` you need to supply in `gitlab.yml` is
`http://libravatar.example.com/avatar/%{hash}?s=%{size}&d=identicon`
@@ -42,37 +50,52 @@ For example, you host a service on `http://libravatar.example.com` the `plain_ur
In `/etc/gitlab/gitlab.rb`:
-#### For http
+#### For HTTP
```ruby
gitlab_rails['gravatar_enabled'] = true
gitlab_rails['gravatar_plain_url'] = "http://cdn.libravatar.org/avatar/%{hash}?s=%{size}&d=identicon"
```
-#### For https
+#### For HTTPS
```ruby
gitlab_rails['gravatar_enabled'] = true
gitlab_rails['gravatar_ssl_url'] = "https://seccdn.libravatar.org/avatar/%{hash}?s=%{size}&d=identicon"
```
-Run `sudo gitlab-ctl reconfigure` for changes to take effect.
+Then run `sudo gitlab-ctl reconfigure` for the changes to take effect.
## Default URL for missing images
-[Libravatar supports different sets](https://wiki.libravatar.org/api/) of `missing images` for emails not found on the Libravatar service.
-
-In order to use a different set other than `identicon`, replace `&d=identicon` portion of the URL with another supported set.
-For example, you can use `retro` set in which case the URL would look like: `plain_url: "http://cdn.libravatar.org/avatar/%{hash}?s=%{size}&d=retro"`
+[Libravatar supports different sets](https://wiki.libravatar.org/api/) of
+missing images for user email addresses that are not found on the Libravatar
+service.
-## Usage examples
+In order to use a set other than `identicon`, replace the `&d=identicon`
+portion of the URL with another supported set.
+For example, you can use the `retro` set, in which case the URL would look like:
+`plain_url: "http://cdn.libravatar.org/avatar/%{hash}?s=%{size}&d=retro"`
-### For Microsoft Office 365
+## Usage examples for Microsoft Office 365
-If your users are Office 365-users, the "GetPersonaPhoto" service can be used. Note that this service requires login, so this use case is
-most useful in a corporate installation, where all users have access to Office 365.
+If your users are Office 365 users, the `GetPersonaPhoto` service can be used.
+Note that this service requires a login, so this use case is most useful in a
+corporate installation where all users have access to Office 365.
```ruby
gitlab_rails['gravatar_plain_url'] = 'http://outlook.office365.com/owa/service.svc/s/GetPersonaPhoto?email=%{email}&size=HR120x120'
gitlab_rails['gravatar_ssl_url'] = 'https://outlook.office365.com/owa/service.svc/s/GetPersonaPhoto?email=%{email}&size=HR120x120'
```
+
+<!-- ## Troubleshooting
+
+Include any troubleshooting steps that you can foresee. If you know beforehand what issues
+one might have when setting this up, or when something is changed, or on upgrading, it's
+important to describe those, too. Think of things that may go wrong and include them here.
+This is important to minimize requests for support, and to avoid doc comments with
+questions that you know someone might ask.
+
+Each scenario can be a third-level heading, e.g. `### Getting error message X`.
+If you have none to add when creating a doc, leave this section in place
+but commented out to help encourage others to add to it in the future. -->
diff --git a/doc/customization/new_project_page.md b/doc/customization/new_project_page.md
index 148bf9512c6..43b95a76d08 100644
--- a/doc/customization/new_project_page.md
+++ b/doc/customization/new_project_page.md
@@ -1,20 +1,38 @@
+---
+type: howto
+---
+
# Customizing the new project page
-It is possible to add a markdown-formatted message to your GitLab
-new project page.
+You can add a markdown-formatted message to your GitLab new project page.
By default, the new project page shows a sidebar with general information:
-![](new_project_page/default_new_project_page.png)
+![default_new_project_page](new_project_page/default_new_project_page.png)
+
+To customize the information in the sidebar:
+
+1. Navigate to the **Admin** area and go to the **Appearance** page, then
+ locate the **New project pages** section.
+1. Fill in your new project project guidelines:
+
+ ![appearance_settings](new_project_page/appearance_settings.png)
-## Changing the appearance of the new project page
+1. Save the page.
-Navigate to the **Admin** area and go to the **Appearance** page.
+Your new project page will show the customized guidelines in the sidebar, below
+the general information:
-Fill in your project guidelines:
+![custom_new_project_page](new_project_page/custom_new_project_page.png)
-![](new_project_page/appearance_settings.png)
+<!-- ## Troubleshooting
-After saving the page, your new project page will show the guidelines in the sidebar, below the general information:
+Include any troubleshooting steps that you can foresee. If you know beforehand what issues
+one might have when setting this up, or when something is changed, or on upgrading, it's
+important to describe those, too. Think of things that may go wrong and include them here.
+This is important to minimize requests for support, and to avoid doc comments with
+questions that you know someone might ask.
-![](new_project_page/custom_new_project_page.png)
+Each scenario can be a third-level heading, e.g. `### Getting error message X`.
+If you have none to add when creating a doc, leave this section in place
+but commented out to help encourage others to add to it in the future. -->
diff --git a/doc/customization/system_header_and_footer_messages/appearance.png b/doc/customization/system_header_and_footer_messages/appearance.png
index fd315bb6c07..d5a66bcb9f1 100644
--- a/doc/customization/system_header_and_footer_messages/appearance.png
+++ b/doc/customization/system_header_and_footer_messages/appearance.png
Binary files differ
diff --git a/doc/development/fe_guide/architecture.md b/doc/development/fe_guide/architecture.md
index 49b74b5ebcf..3d27f67a8a6 100644
--- a/doc/development/fe_guide/architecture.md
+++ b/doc/development/fe_guide/architecture.md
@@ -11,7 +11,7 @@ Architectural decisions should be accessible to everyone, so please document
them in the relevant Merge Request discussion or by updating our documentation
when appropriate.
-You can find the Frontend Architecture experts on the [team page](https://about.gitlab.com/company/team).
+You can find the Frontend Architecture experts on the [team page](https://about.gitlab.com/company/team/).
## Examples
diff --git a/doc/development/fe_guide/graphql.md b/doc/development/fe_guide/graphql.md
index 55b719227e5..4fc5dfc8c3d 100644
--- a/doc/development/fe_guide/graphql.md
+++ b/doc/development/fe_guide/graphql.md
@@ -47,7 +47,7 @@ new Vue({
});
```
-Read more about [Vue Apollo][vue-apollo] in the [Vue Apollo documentation][vue-apollo-docs].
+Read more about [Vue Apollo][vue-apollo] in the [Vue Apollo documentation](https://vue-apollo.netlify.com/guide/).
### Local state with Apollo
@@ -118,7 +118,6 @@ Read more about the [Apollo] client in the [Apollo documentation](https://www.ap
[Apollo]: https://www.apollographql.com/
[vue-apollo]: https://github.com/Akryum/vue-apollo/
-[vue-apollo-docs]: https://akryum.github.io/vue-apollo/
[feature-flags]: ../feature_flags.md
[default-client]: https://gitlab.com/gitlab-org/gitlab-ce/blob/master/app/assets/javascripts/lib/graphql.js
[vue-test-utils]: https://vue-test-utils.vuejs.org/
diff --git a/doc/development/fe_guide/style_guide_js.md b/doc/development/fe_guide/style_guide_js.md
index b0bbb4cc4b2..d3fa350b847 100644
--- a/doc/development/fe_guide/style_guide_js.md
+++ b/doc/development/fe_guide/style_guide_js.md
@@ -49,8 +49,8 @@ See [our current .eslintrc](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/
```
1. There are few rules that we need to disable due to technical debt. Which are:
- 1. [no-new][eslint-new]
- 1. [class-methods-use-this][eslint-this]
+ 1. [no-new](https://eslint.org/docs/rules/no-new)
+ 1. [class-methods-use-this](https://eslint.org/docs/rules/class-methods-use-this)
1. When they are needed _always_ place ESlint directive comment blocks on the first line of a script,
followed by any global declarations, then a blank newline prior to any imports or code.
@@ -714,8 +714,6 @@ The goal of this accord is to make sure we are all on the same page.
[airbnb-js-style-guide]: https://github.com/airbnb/javascript
[eslintrc]: https://gitlab.com/gitlab-org/gitlab-ce/blob/master/.eslintrc
-[eslint-this]: http://eslint.org/docs/rules/class-methods-use-this
-[eslint-new]: http://eslint.org/docs/rules/no-new
[eslint-plugin-vue]: https://github.com/vuejs/eslint-plugin-vue
[eslint-plugin-vue-rules]: https://github.com/vuejs/eslint-plugin-vue#bulb-rules
[vue-order]: https://github.com/vuejs/eslint-plugin-vue/blob/master/docs/rules/order-in-components.md
diff --git a/doc/development/img/architecture_simplified.png b/doc/development/img/architecture_simplified.png
index 1698c167c5e..1ad57b65468 100644
--- a/doc/development/img/architecture_simplified.png
+++ b/doc/development/img/architecture_simplified.png
Binary files differ
diff --git a/doc/development/img/distributed_tracing_jaeger_ui.png b/doc/development/img/distributed_tracing_jaeger_ui.png
index 57517dacced..dcd18b1ec9f 100644
--- a/doc/development/img/distributed_tracing_jaeger_ui.png
+++ b/doc/development/img/distributed_tracing_jaeger_ui.png
Binary files differ
diff --git a/doc/development/img/distributed_tracing_performance_bar.png b/doc/development/img/distributed_tracing_performance_bar.png
index c9998cedd2d..8c819045104 100644
--- a/doc/development/img/distributed_tracing_performance_bar.png
+++ b/doc/development/img/distributed_tracing_performance_bar.png
Binary files differ
diff --git a/doc/development/new_fe_guide/development/performance.md b/doc/development/new_fe_guide/development/performance.md
index c54b8305991..d41239693bf 100644
--- a/doc/development/new_fe_guide/development/performance.md
+++ b/doc/development/new_fe_guide/development/performance.md
@@ -5,7 +5,7 @@
We have a performance dashboard available in one of our [grafana instances](https://dashboards.gitlab.net/d/1EBTz3Dmz/sitespeed-page-summary?orgId=1). This dashboard automatically aggregates metric data from [sitespeed.io](https://www.sitespeed.io/) every 6 hours. These changes are displayed after a set number of pages are aggregated.
These pages can be found inside a text file in the gitlab-build-images [repository](https://gitlab.com/gitlab-org/gitlab-build-images) called [gitlab.txt](https://gitlab.com/gitlab-org/gitlab-build-images/blob/master/scripts/gitlab.txt)
-Any frontend engineer can contribute to this dashboard. They can contribute by adding or removing urls of pages from this text file. Please have a [frontend monitoring expert](https://about.gitlab.com/company/team) review your changes before assigning to a maintainer of the `gitlab-build-images` project. The changes will go live on the next scheduled run after the changes are merged into `master`.
+Any frontend engineer can contribute to this dashboard. They can contribute by adding or removing urls of pages from this text file. Please have a [frontend monitoring expert](https://about.gitlab.com/company/team/) review your changes before assigning to a maintainer of the `gitlab-build-images` project. The changes will go live on the next scheduled run after the changes are merged into `master`.
There are 3 recommended high impact metrics to review on each page:
diff --git a/doc/development/new_fe_guide/development/testing.md b/doc/development/new_fe_guide/development/testing.md
index 2b62c2a41fe..f7ea496d935 100644
--- a/doc/development/new_fe_guide/development/testing.md
+++ b/doc/development/new_fe_guide/development/testing.md
@@ -261,7 +261,7 @@ scenario 'successfully', :js do
end
```
-The steps of each test are written using capybara methods ([documentation](https://www.rubydoc.info/gems/capybara/2.15.1)).
+The steps of each test are written using capybara methods ([documentation](https://www.rubydoc.info/gems/capybara)).
Bear in mind <abbr title="XMLHttpRequest">XHR</abbr> calls might require you to use `wait_for_requests` in between steps, like so:
diff --git a/doc/development/ux_guide/animation.md b/doc/development/ux_guide/animation.md
index 583ff19bc69..a998ab74a96 100644
--- a/doc/development/ux_guide/animation.md
+++ b/doc/development/ux_guide/animation.md
@@ -1,5 +1,5 @@
---
-redirect_to: 'https://design.gitlab.com/foundations/motion'
+redirect_to: 'https://design.gitlab.com/product-foundations/motion'
---
-The content of this document was moved into the [GitLab Design System](https://design.gitlab.com).
+The content of this document was moved into the [GitLab Design System](https://design.gitlab.com/product-foundations/motion).
diff --git a/doc/development/ux_guide/illustrations.md b/doc/development/ux_guide/illustrations.md
index ed072b6515f..3592d25c95d 100644
--- a/doc/development/ux_guide/illustrations.md
+++ b/doc/development/ux_guide/illustrations.md
@@ -1,5 +1,5 @@
---
-redirect_to: 'https://design.gitlab.com/foundations/illustration/'
+redirect_to: 'https://design.gitlab.com/product-foundations/illustration'
---
-The content of this document was moved into the [GitLab Design System](https://design.gitlab.com/).
+The content of this document was moved into the [GitLab Design System](https://design.gitlab.com/product-foundations/illustration).
diff --git a/doc/install/docker.md b/doc/install/docker.md
index 06da65189ba..e0cef71a4d8 100644
--- a/doc/install/docker.md
+++ b/doc/install/docker.md
@@ -10,7 +10,7 @@ GitLab provides official Docker images allowing you to easily take advantage of
## Omnibus GitLab based images
-GitLab maintains a set of [official Docker images](https://hub.docker.com/r/gitlab) based on our [Omnibus GitLab package](https://docs.gitlab.com/omnibus/README.html). These images include:
+GitLab maintains a set of [official Docker images](https://hub.docker.com/u/gitlab) based on our [Omnibus GitLab package](https://docs.gitlab.com/omnibus/README.html). These images include:
- [GitLab Community Edition](https://hub.docker.com/r/gitlab/gitlab-ce/)
- [GitLab Enterprise Edition](https://hub.docker.com/r/gitlab/gitlab-ee/)
diff --git a/doc/integration/img/limit_namespace_filter.png b/doc/integration/img/limit_namespace_filter.png
index 88f5caa41db..437aecad467 100644
--- a/doc/integration/img/limit_namespace_filter.png
+++ b/doc/integration/img/limit_namespace_filter.png
Binary files differ
diff --git a/doc/integration/img/limit_namespaces_projects_options.png b/doc/integration/img/limit_namespaces_projects_options.png
index 488341f7e92..fa666c7491e 100644
--- a/doc/integration/img/limit_namespaces_projects_options.png
+++ b/doc/integration/img/limit_namespaces_projects_options.png
Binary files differ
diff --git a/doc/integration/img/salesforce_app_details.png b/doc/integration/img/salesforce_app_details.png
index 00e66f07282..c7a4084102e 100644
--- a/doc/integration/img/salesforce_app_details.png
+++ b/doc/integration/img/salesforce_app_details.png
Binary files differ
diff --git a/doc/integration/img/salesforce_app_secret_details.png b/doc/integration/img/salesforce_app_secret_details.png
index fad2a4a1f97..8734a7a5cbb 100644
--- a/doc/integration/img/salesforce_app_secret_details.png
+++ b/doc/integration/img/salesforce_app_secret_details.png
Binary files differ
diff --git a/doc/integration/img/salesforce_oauth_app_details.png b/doc/integration/img/salesforce_oauth_app_details.png
index a5fb680cca6..e29c55df656 100644
--- a/doc/integration/img/salesforce_oauth_app_details.png
+++ b/doc/integration/img/salesforce_oauth_app_details.png
Binary files differ
diff --git a/doc/security/img/outbound_requests_section_v12_2.png b/doc/security/img/outbound_requests_section_v12_2.png
index 4fd3c7d9fce..3dc99868a35 100644
--- a/doc/security/img/outbound_requests_section_v12_2.png
+++ b/doc/security/img/outbound_requests_section_v12_2.png
Binary files differ
diff --git a/doc/security/rack_attack.md b/doc/security/rack_attack.md
index c772f783f71..b99bfb16829 100644
--- a/doc/security/rack_attack.md
+++ b/doc/security/rack_attack.md
@@ -20,9 +20,9 @@ For more information on how to use these options see the [Rack Attack README](ht
NOTE: **Note:** See
[User and IP rate limits](../user/admin_area/settings/user_and_ip_rate_limits.md)
-for simpler throttles that are configured in UI.
+for simpler limits that are configured in the UI.
-NOTE: **Note:** Starting with 11.2, Rack Attack is disabled by default. If your
+NOTE: **Note:** Starting with GitLab 11.2, Rack Attack is disabled by default. If your
instance is not exposed to the public internet, it is recommended that you leave
Rack Attack disabled.
@@ -31,13 +31,13 @@ Rack Attack disabled.
If set up as described in the [Settings](#settings) section below, two behaviors
will be enabled:
-- Protected paths will be throttled
-- Failed authentications for Git and container registry requests will trigger a temporary IP ban
+- Protected paths will be throttled.
+- Failed authentications for Git and container registry requests will trigger a temporary IP ban.
### Protected paths throttle
-GitLab responds with HTTP status code 429 to POST requests at protected paths
-over 10 requests per minute per IP address.
+GitLab responds with HTTP status code `429` to POST requests at protected paths
+that exceed 10 requests per minute per IP address.
By default, protected paths are:
@@ -62,16 +62,16 @@ Retry-After: 60
For example, the following are limited to a maximum 10 requests per minute:
-- user sign-in
-- user sign-up (if enabled)
-- user password reset
+- User sign-in
+- User sign-up (if enabled)
+- User password reset
-After trying for 10 times, the client will
-have to wait a minute before to be able to try again.
+After 10 requests, the client must wait a minute before it can
+try again.
### Git and container registry failed authentication ban
-GitLab responds with HTTP status code 403 for 1 hour, if 30 failed
+GitLab responds with HTTP status code `403` for 1 hour, if 30 failed
authentication requests were received in a 3-minute period from a single IP address.
This applies only to Git requests and container registry (`/jwt/auth`) requests
@@ -145,7 +145,7 @@ If you want more restrictive/relaxed throttle rules, edit
For example, more relaxed throttle rules will be if you set
`limit: 3` and `period: 1.seconds` (this will allow 3 requests per second).
You can also add other paths to the protected list by adding to `paths_to_be_protected`
-variable. If you change any of these settings do not forget to restart your
+variable. If you change any of these settings you must restart your
GitLab instance.
## Remove blocked IPs from Rack Attack via Redis
diff --git a/doc/topics/authentication/index.md b/doc/topics/authentication/index.md
index 8b4a2f1630b..ad196e27f53 100644
--- a/doc/topics/authentication/index.md
+++ b/doc/topics/authentication/index.md
@@ -23,7 +23,7 @@ This page gathers all the resources for the topic **Authentication** within GitL
- [How to Configure LDAP with GitLab CE](../../administration/auth/how_to_configure_ldap_gitlab_ce/index.md)
- [How to Configure LDAP with GitLab EE](../../administration/auth/how_to_configure_ldap_gitlab_ee/index.md) **(STARTER)**
- [Feature Highlight: LDAP Integration](https://about.gitlab.com/2014/07/10/feature-highlight-ldap-sync/)
- - [Debugging LDAP](https://about.gitlab.com/handbook/support/workflows/support-engineering/ldap/debugging_ldap.html)
+ - [Debugging LDAP](https://about.gitlab.com/handbook/support/workflows/debugging_ldap.html)
- **Integrations:**
- [OmniAuth](../../integration/omniauth.md)
- [Authentiq OmniAuth Provider](../../administration/auth/authentiq.md#authentiq-omniauth-provider)
diff --git a/doc/topics/git/useful_git_commands.md b/doc/topics/git/useful_git_commands.md
index 84406805350..030e62f485a 100644
--- a/doc/topics/git/useful_git_commands.md
+++ b/doc/topics/git/useful_git_commands.md
@@ -149,7 +149,7 @@ gitk --follow <file>
### Use a custom SSH key for a git command
-```text
+```sh
GIT_SSH_COMMAND="ssh -i ~/.ssh/gitlabadmin" git <command>
```
@@ -157,13 +157,13 @@ GIT_SSH_COMMAND="ssh -i ~/.ssh/gitlabadmin" git <command>
With SSH:
-```text
+```sh
GIT_SSH_COMMAND="ssh -vvv" git clone <git@url>
```
With HTTPS:
-```text
+```sh
GIT_TRACE_PACKET=1 GIT_TRACE=2 GIT_CURL_VERBOSE=1 git clone <url>
```
diff --git a/doc/user/admin_area/img/abuse_report_blocked_user.png b/doc/user/admin_area/img/abuse_report_blocked_user.png
index 0cb4c7bb8ac..435d8dfe821 100644
--- a/doc/user/admin_area/img/abuse_report_blocked_user.png
+++ b/doc/user/admin_area/img/abuse_report_blocked_user.png
Binary files differ
diff --git a/doc/user/admin_area/img/abuse_reports_page.png b/doc/user/admin_area/img/abuse_reports_page.png
index 81dbe976cda..30e932211cb 100644
--- a/doc/user/admin_area/img/abuse_reports_page.png
+++ b/doc/user/admin_area/img/abuse_reports_page.png
Binary files differ
diff --git a/doc/user/admin_area/img/broadcast_messages.png b/doc/user/admin_area/img/broadcast_messages.png
index 926d38ae049..f0ae92f8c17 100644
--- a/doc/user/admin_area/img/broadcast_messages.png
+++ b/doc/user/admin_area/img/broadcast_messages.png
Binary files differ
diff --git a/doc/user/admin_area/img/license_details.png b/doc/user/admin_area/img/license_details.png
index 2085bb437ad..3e980d9316d 100644
--- a/doc/user/admin_area/img/license_details.png
+++ b/doc/user/admin_area/img/license_details.png
Binary files differ
diff --git a/doc/user/admin_area/settings/email.md b/doc/user/admin_area/settings/email.md
index 1f07a4dfdc6..77c9d097283 100644
--- a/doc/user/admin_area/settings/email.md
+++ b/doc/user/admin_area/settings/email.md
@@ -17,11 +17,10 @@ The logo in the header of some emails can be customized, see the [logo customiza
The additional text will appear at the bottom of any email and can be used for
legal/auditing/compliance reasons.
-1. Go to **Admin area > Settings** (`/admin/application_settings`).
-1. Under the **Email** section, change the **Additional text** field.
-1. Hit **Save** for the changes to take effect.
-
-![Admin email settings](img/email_settings.png)
+1. Go to **Admin Area > Settings > Preferences** (`/admin/application_settings/preferences`).
+1. Expand the **Email** section.
+1. Enter your text in the **Additional text** field.
+1. Click **Save**.
[ee-5031]: https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/5031
[eep]: https://about.gitlab.com/pricing/
@@ -53,4 +52,4 @@ questions that you know someone might ask.
Each scenario can be a third-level heading, e.g. `### Getting error message X`.
If you have none to add when creating a doc, leave this section in place
-but commented out to help encourage others to add to it in the future. --> \ No newline at end of file
+but commented out to help encourage others to add to it in the future. -->
diff --git a/doc/user/admin_area/settings/img/additional_minutes.png b/doc/user/admin_area/settings/img/additional_minutes.png
index d148ed79b92..b159b98c9ce 100644
--- a/doc/user/admin_area/settings/img/additional_minutes.png
+++ b/doc/user/admin_area/settings/img/additional_minutes.png
Binary files differ
diff --git a/doc/user/admin_area/settings/img/admin_required_pipeline.png b/doc/user/admin_area/settings/img/admin_required_pipeline.png
index 58488674d51..501b1e3ba0a 100644
--- a/doc/user/admin_area/settings/img/admin_required_pipeline.png
+++ b/doc/user/admin_area/settings/img/admin_required_pipeline.png
Binary files differ
diff --git a/doc/user/admin_area/settings/img/buy_btn.png b/doc/user/admin_area/settings/img/buy_btn.png
index 0cc88b8a48f..4fd05c0fba7 100644
--- a/doc/user/admin_area/settings/img/buy_btn.png
+++ b/doc/user/admin_area/settings/img/buy_btn.png
Binary files differ
diff --git a/doc/user/admin_area/settings/img/buy_minutes_card.png b/doc/user/admin_area/settings/img/buy_minutes_card.png
index cf4ad34ead7..cab098300cd 100644
--- a/doc/user/admin_area/settings/img/buy_minutes_card.png
+++ b/doc/user/admin_area/settings/img/buy_minutes_card.png
Binary files differ
diff --git a/doc/user/admin_area/settings/img/email_confirmation.png b/doc/user/admin_area/settings/img/email_confirmation.png
index 4d888da3416..987aa10c3ce 100644
--- a/doc/user/admin_area/settings/img/email_confirmation.png
+++ b/doc/user/admin_area/settings/img/email_confirmation.png
Binary files differ
diff --git a/doc/user/admin_area/settings/img/email_settings.png b/doc/user/admin_area/settings/img/email_settings.png
deleted file mode 100644
index ed0a80d10ce..00000000000
--- a/doc/user/admin_area/settings/img/email_settings.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/admin_area/settings/img/user_and_ip_rate_limits.png b/doc/user/admin_area/settings/img/user_and_ip_rate_limits.png
index 2bd85a2fd96..53dc0e4ac87 100644
--- a/doc/user/admin_area/settings/img/user_and_ip_rate_limits.png
+++ b/doc/user/admin_area/settings/img/user_and_ip_rate_limits.png
Binary files differ
diff --git a/doc/user/application_security/img/create_issue_with_list_hover.png b/doc/user/application_security/img/create_issue_with_list_hover.png
index 7d70e8299f5..4c38862e68f 100644
--- a/doc/user/application_security/img/create_issue_with_list_hover.png
+++ b/doc/user/application_security/img/create_issue_with_list_hover.png
Binary files differ
diff --git a/doc/user/application_security/img/dismissed_info.png b/doc/user/application_security/img/dismissed_info.png
index 64d5cf26ed2..b4470b664d2 100644
--- a/doc/user/application_security/img/dismissed_info.png
+++ b/doc/user/application_security/img/dismissed_info.png
Binary files differ
diff --git a/doc/user/application_security/img/interactive_reports.png b/doc/user/application_security/img/interactive_reports.png
index 373b39104db..1b2ef0d3da9 100644
--- a/doc/user/application_security/img/interactive_reports.png
+++ b/doc/user/application_security/img/interactive_reports.png
Binary files differ
diff --git a/doc/user/application_security/img/vulnerability_solution.png b/doc/user/application_security/img/vulnerability_solution.png
index 7443b9b6eea..d86b89a5f99 100644
--- a/doc/user/application_security/img/vulnerability_solution.png
+++ b/doc/user/application_security/img/vulnerability_solution.png
Binary files differ
diff --git a/doc/user/application_security/license_management/img/license_management_add_license.png b/doc/user/application_security/license_management/img/license_management_add_license.png
index 1e1a698515b..c9a5dc14c57 100644
--- a/doc/user/application_security/license_management/img/license_management_add_license.png
+++ b/doc/user/application_security/license_management/img/license_management_add_license.png
Binary files differ
diff --git a/doc/user/application_security/license_management/img/license_management_decision.png b/doc/user/application_security/license_management/img/license_management_decision.png
index 0763130c375..fbf90bec7fd 100644
--- a/doc/user/application_security/license_management/img/license_management_decision.png
+++ b/doc/user/application_security/license_management/img/license_management_decision.png
Binary files differ
diff --git a/doc/user/application_security/license_management/img/license_management_search.png b/doc/user/application_security/license_management/img/license_management_search.png
index 7b6006cef9d..b3ffd8d95a1 100644
--- a/doc/user/application_security/license_management/img/license_management_search.png
+++ b/doc/user/application_security/license_management/img/license_management_search.png
Binary files differ
diff --git a/doc/user/application_security/license_management/img/license_management_settings.png b/doc/user/application_security/license_management/img/license_management_settings.png
index 1a2bfa78a03..2e3e8888e93 100644
--- a/doc/user/application_security/license_management/img/license_management_settings.png
+++ b/doc/user/application_security/license_management/img/license_management_settings.png
Binary files differ
diff --git a/doc/user/application_security/security_dashboard/img/group_security_dashboard.png b/doc/user/application_security/security_dashboard/img/group_security_dashboard.png
index 40689861e2a..85ab124f74c 100644
--- a/doc/user/application_security/security_dashboard/img/group_security_dashboard.png
+++ b/doc/user/application_security/security_dashboard/img/group_security_dashboard.png
Binary files differ
diff --git a/doc/user/application_security/security_dashboard/img/project_security_dashboard.png b/doc/user/application_security/security_dashboard/img/project_security_dashboard.png
index 89b310895d3..baa136fd885 100644
--- a/doc/user/application_security/security_dashboard/img/project_security_dashboard.png
+++ b/doc/user/application_security/security_dashboard/img/project_security_dashboard.png
Binary files differ
diff --git a/doc/user/clusters/applications.md b/doc/user/clusters/applications.md
index c0106b2cb9e..096730f800c 100644
--- a/doc/user/clusters/applications.md
+++ b/doc/user/clusters/applications.md
@@ -1,11 +1,13 @@
# GitLab Managed Apps
GitLab provides **GitLab Managed Apps**, a one-click install for various applications which can
-be added directly to your configured cluster. These applications are
-needed for [Review Apps](../../ci/review_apps/index.md) and
-[deployments](../../ci/environments.md) when using [Auto DevOps](../../topics/autodevops/index.md).
+be added directly to your configured cluster.
+
+These applications are needed for [Review Apps](../../ci/review_apps/index.md)
+and [deployments](../../ci/environments.md) when using [Auto DevOps](../../topics/autodevops/index.md).
+
You can install them after you
-[create a cluster](../project/clusters/index.md#add-new-gke-cluster).
+[create a cluster](../project/clusters/index.md#adding-and-removing-clusters).
## Installing applications
@@ -20,8 +22,10 @@ This namespace:
To see a list of available applications to install:
1. For a:
- - Project-level cluster, navigate to your project's **Operations > Kubernetes**.
- - Group-level cluster, navigate to your group's **Kubernetes** page.
+ - [Project-level cluster](../project/clusters/index.md),
+ navigate to your project's **Operations > Kubernetes**.
+ - [Group-level cluster](../group/clusters/index.md),
+ navigate to your group's **Kubernetes** page.
Install Helm first as it's used to install other applications.
@@ -160,9 +164,9 @@ file.
When installing JupyterHub onto your Kubernetes cluster, [JupyterLab's Git extension](https://github.com/jupyterlab/jupyterlab-git)
is automatically provisioned and configured using the authenticated user's:
-- Name
-- Email
-- Newly created access token
+- Name.
+- Email.
+- Newly created access token.
JupyterLab's Git extension enables full version control of your notebooks as well as issuance of Git commands within Jupyter.
Git commands can be issued via the **Git** tab on the left panel or via Jupyter's command line prompt.
@@ -233,8 +237,10 @@ The applications below can be upgraded.
To upgrade an application:
1. For a:
- - Project-level cluster, navigate to your project's **Operations > Kubernetes**.
- - Group-level cluster, navigate to your group's **Kubernetes** page.
+ - [Project-level cluster](../project/clusters/index.md),
+ navigate to your project's **Operations > Kubernetes**.
+ - [Group-level cluster](../group/clusters/index.md),
+ navigate to your group's **Kubernetes** page.
1. Select your cluster.
1. If an upgrade is available, the **Upgrade** button is displayed. Click the button to upgrade.
@@ -263,8 +269,10 @@ The applications below can be uninstalled.
To uninstall an application:
1. For a:
- - Project-level cluster, navigate to your project's **Operations > Kubernetes**.
- - Group-level cluster, navigate to your group's **Kubernetes** page.
+ - [Project-level cluster](../project/clusters/index.md),
+ navigate to your project's **Operations > Kubernetes**.
+ - [Group-level cluster](../group/clusters/index.md),
+ navigate to your group's **Kubernetes** page.
1. Select your cluster.
1. Click the **Uninstall** button for the application.
diff --git a/doc/user/clusters/img/jupyter-gitclone.png b/doc/user/clusters/img/jupyter-gitclone.png
index 41d467f806a..aff194dea43 100644
--- a/doc/user/clusters/img/jupyter-gitclone.png
+++ b/doc/user/clusters/img/jupyter-gitclone.png
Binary files differ
diff --git a/doc/user/discussions/img/automatically_resolve_outdated_discussions.png b/doc/user/discussions/img/automatically_resolve_outdated_discussions.png
index d31216a7e2e..a6fc4b0aef1 100644
--- a/doc/user/discussions/img/automatically_resolve_outdated_discussions.png
+++ b/doc/user/discussions/img/automatically_resolve_outdated_discussions.png
Binary files differ
diff --git a/doc/user/discussions/img/btn_new_issue_for_all_threads.png b/doc/user/discussions/img/btn_new_issue_for_all_threads.png
index f24c84a2348..5d86e0ca016 100644
--- a/doc/user/discussions/img/btn_new_issue_for_all_threads.png
+++ b/doc/user/discussions/img/btn_new_issue_for_all_threads.png
Binary files differ
diff --git a/doc/user/discussions/img/commit_comment_mr_context.png b/doc/user/discussions/img/commit_comment_mr_context.png
index 7b87d6e44d7..68f58a57757 100644
--- a/doc/user/discussions/img/commit_comment_mr_context.png
+++ b/doc/user/discussions/img/commit_comment_mr_context.png
Binary files differ
diff --git a/doc/user/discussions/img/commit_comment_mr_discussions_tab.png b/doc/user/discussions/img/commit_comment_mr_discussions_tab.png
index 4798ff4b658..d88f08eae26 100644
--- a/doc/user/discussions/img/commit_comment_mr_discussions_tab.png
+++ b/doc/user/discussions/img/commit_comment_mr_discussions_tab.png
Binary files differ
diff --git a/doc/user/discussions/img/discussion_comment.png b/doc/user/discussions/img/discussion_comment.png
index 685c30e5004..3fec5962363 100644
--- a/doc/user/discussions/img/discussion_comment.png
+++ b/doc/user/discussions/img/discussion_comment.png
Binary files differ
diff --git a/doc/user/discussions/img/image_resolved_discussion.png b/doc/user/discussions/img/image_resolved_discussion.png
index 9feded27c92..f6e5a3b66ae 100644
--- a/doc/user/discussions/img/image_resolved_discussion.png
+++ b/doc/user/discussions/img/image_resolved_discussion.png
Binary files differ
diff --git a/doc/user/discussions/img/merge_request_commits_tab.png b/doc/user/discussions/img/merge_request_commits_tab.png
index 065d4be61f0..267f3a720dc 100644
--- a/doc/user/discussions/img/merge_request_commits_tab.png
+++ b/doc/user/discussions/img/merge_request_commits_tab.png
Binary files differ
diff --git a/doc/user/discussions/img/mr_review_resolve.png b/doc/user/discussions/img/mr_review_resolve.png
index fc6299961a5..ced33682459 100644
--- a/doc/user/discussions/img/mr_review_resolve.png
+++ b/doc/user/discussions/img/mr_review_resolve.png
Binary files differ
diff --git a/doc/user/discussions/img/mr_review_resolve2.png b/doc/user/discussions/img/mr_review_resolve2.png
index 1794b682911..2f0be3b6d06 100644
--- a/doc/user/discussions/img/mr_review_resolve2.png
+++ b/doc/user/discussions/img/mr_review_resolve2.png
Binary files differ
diff --git a/doc/user/discussions/img/mr_review_second_comment.png b/doc/user/discussions/img/mr_review_second_comment.png
index 204cc840d9e..f345c52e941 100644
--- a/doc/user/discussions/img/mr_review_second_comment.png
+++ b/doc/user/discussions/img/mr_review_second_comment.png
Binary files differ
diff --git a/doc/user/discussions/img/mr_review_second_comment_added.png b/doc/user/discussions/img/mr_review_second_comment_added.png
index aa15ca7fb98..61b45431c9e 100644
--- a/doc/user/discussions/img/mr_review_second_comment_added.png
+++ b/doc/user/discussions/img/mr_review_second_comment_added.png
Binary files differ
diff --git a/doc/user/discussions/img/mr_review_start.png b/doc/user/discussions/img/mr_review_start.png
index 0f52bee7d89..08b4c6bb82b 100644
--- a/doc/user/discussions/img/mr_review_start.png
+++ b/doc/user/discussions/img/mr_review_start.png
Binary files differ
diff --git a/doc/user/discussions/img/mr_review_unresolve.png b/doc/user/discussions/img/mr_review_unresolve.png
index 3441efc1572..4bef38f7808 100644
--- a/doc/user/discussions/img/mr_review_unresolve.png
+++ b/doc/user/discussions/img/mr_review_unresolve.png
Binary files differ
diff --git a/doc/user/discussions/img/mr_review_unresolve2.png b/doc/user/discussions/img/mr_review_unresolve2.png
index a824b806e4a..79da61bb556 100644
--- a/doc/user/discussions/img/mr_review_unresolve2.png
+++ b/doc/user/discussions/img/mr_review_unresolve2.png
Binary files differ
diff --git a/doc/user/discussions/img/multi-line-suggestion-preview.png b/doc/user/discussions/img/multi-line-suggestion-preview.png
index 4288d0ba034..476c50b9098 100644
--- a/doc/user/discussions/img/multi-line-suggestion-preview.png
+++ b/doc/user/discussions/img/multi-line-suggestion-preview.png
Binary files differ
diff --git a/doc/user/discussions/img/multi-line-suggestion-syntax.png b/doc/user/discussions/img/multi-line-suggestion-syntax.png
index df0c99b84ef..80424d1f056 100644
--- a/doc/user/discussions/img/multi-line-suggestion-syntax.png
+++ b/doc/user/discussions/img/multi-line-suggestion-syntax.png
Binary files differ
diff --git a/doc/user/discussions/img/new_issue_for_thread.png b/doc/user/discussions/img/new_issue_for_thread.png
index 2264da0b5b5..28b76adf7fe 100644
--- a/doc/user/discussions/img/new_issue_for_thread.png
+++ b/doc/user/discussions/img/new_issue_for_thread.png
Binary files differ
diff --git a/doc/user/discussions/img/onion_skin_view.png b/doc/user/discussions/img/onion_skin_view.png
index 9bb4428184e..81bb4a2c85a 100644
--- a/doc/user/discussions/img/onion_skin_view.png
+++ b/doc/user/discussions/img/onion_skin_view.png
Binary files differ
diff --git a/doc/user/discussions/img/only_allow_merge_if_all_threads_are_resolved.png b/doc/user/discussions/img/only_allow_merge_if_all_threads_are_resolved.png
index 9314e3a6490..bd0aaca79b2 100644
--- a/doc/user/discussions/img/only_allow_merge_if_all_threads_are_resolved.png
+++ b/doc/user/discussions/img/only_allow_merge_if_all_threads_are_resolved.png
Binary files differ
diff --git a/doc/user/discussions/img/pending_review_comment.png b/doc/user/discussions/img/pending_review_comment.png
index 812e4ac966a..70a66b3f4f0 100644
--- a/doc/user/discussions/img/pending_review_comment.png
+++ b/doc/user/discussions/img/pending_review_comment.png
Binary files differ
diff --git a/doc/user/discussions/img/preview_issue_for_thread.png b/doc/user/discussions/img/preview_issue_for_thread.png
index 1517902c61c..a9d7ab598be 100644
--- a/doc/user/discussions/img/preview_issue_for_thread.png
+++ b/doc/user/discussions/img/preview_issue_for_thread.png
Binary files differ
diff --git a/doc/user/discussions/img/preview_issue_for_threads.png b/doc/user/discussions/img/preview_issue_for_threads.png
index 8359ab3143c..8757decb178 100644
--- a/doc/user/discussions/img/preview_issue_for_threads.png
+++ b/doc/user/discussions/img/preview_issue_for_threads.png
Binary files differ
diff --git a/doc/user/discussions/img/reply_to_comment_button.png b/doc/user/discussions/img/reply_to_comment_button.png
index d362b19785c..d327d1c3e27 100644
--- a/doc/user/discussions/img/reply_to_comment_button.png
+++ b/doc/user/discussions/img/reply_to_comment_button.png
Binary files differ
diff --git a/doc/user/discussions/img/resolve_comment_button.png b/doc/user/discussions/img/resolve_comment_button.png
index 0319ec999fd..0a3ed03a69c 100644
--- a/doc/user/discussions/img/resolve_comment_button.png
+++ b/doc/user/discussions/img/resolve_comment_button.png
Binary files differ
diff --git a/doc/user/discussions/img/resolve_thread_button.png b/doc/user/discussions/img/resolve_thread_button.png
index 873c302f570..ca0a3e50550 100644
--- a/doc/user/discussions/img/resolve_thread_button.png
+++ b/doc/user/discussions/img/resolve_thread_button.png
Binary files differ
diff --git a/doc/user/discussions/img/resolve_thread_issue_notice.png b/doc/user/discussions/img/resolve_thread_issue_notice.png
index c2a8fdebee7..30a65b8fbd4 100644
--- a/doc/user/discussions/img/resolve_thread_issue_notice.png
+++ b/doc/user/discussions/img/resolve_thread_issue_notice.png
Binary files differ
diff --git a/doc/user/discussions/img/resolve_thread_open_issue.png b/doc/user/discussions/img/resolve_thread_open_issue.png
index be2a4365297..2dd4ea3cb1b 100644
--- a/doc/user/discussions/img/resolve_thread_open_issue.png
+++ b/doc/user/discussions/img/resolve_thread_open_issue.png
Binary files differ
diff --git a/doc/user/discussions/img/review_comment_quickactions.png b/doc/user/discussions/img/review_comment_quickactions.png
index df5c4dd0fcc..276def6381f 100644
--- a/doc/user/discussions/img/review_comment_quickactions.png
+++ b/doc/user/discussions/img/review_comment_quickactions.png
Binary files differ
diff --git a/doc/user/discussions/img/review_preview.png b/doc/user/discussions/img/review_preview.png
index 1b91506b477..e69a58dbb91 100644
--- a/doc/user/discussions/img/review_preview.png
+++ b/doc/user/discussions/img/review_preview.png
Binary files differ
diff --git a/doc/user/discussions/img/swipe_view.png b/doc/user/discussions/img/swipe_view.png
index 287d52a0811..e6f5e5053af 100644
--- a/doc/user/discussions/img/swipe_view.png
+++ b/doc/user/discussions/img/swipe_view.png
Binary files differ
diff --git a/doc/user/discussions/img/thread_view.png b/doc/user/discussions/img/thread_view.png
index 8c1fd9d5acf..e2db44aa604 100644
--- a/doc/user/discussions/img/thread_view.png
+++ b/doc/user/discussions/img/thread_view.png
Binary files differ
diff --git a/doc/user/discussions/img/threads_resolved.png b/doc/user/discussions/img/threads_resolved.png
index 6ac815cf874..ffb1233f2ee 100644
--- a/doc/user/discussions/img/threads_resolved.png
+++ b/doc/user/discussions/img/threads_resolved.png
Binary files differ
diff --git a/doc/user/discussions/img/two_up_view.png b/doc/user/discussions/img/two_up_view.png
index 062a96723dd..3b6ddfbe1be 100644
--- a/doc/user/discussions/img/two_up_view.png
+++ b/doc/user/discussions/img/two_up_view.png
Binary files differ
diff --git a/doc/user/gitlab_com/index.md b/doc/user/gitlab_com/index.md
index e6c27c33654..928950126da 100644
--- a/doc/user/gitlab_com/index.md
+++ b/doc/user/gitlab_com/index.md
@@ -316,7 +316,8 @@ with details, such as the affected IP address.
### HAProxy API throttle
-GitLab.com responds with HTTP status code 429 to API requests over 10 requests
+GitLab.com responds with HTTP status code `429` to API requests that exceed 10
+requests
per second per IP address.
The following example headers are included for all API requests:
@@ -335,10 +336,12 @@ Source:
### Rack Attack initializer
+Details of rate limits enforced by [Rack Attack](../../security/rack_attack.md).
+
#### Protected paths throttle
-GitLab.com responds with HTTP status code 429 to POST requests at protected
-paths over 10 requests per **minute** per IP address.
+GitLab.com responds with HTTP status code `429` to POST requests at protected
+paths that exceed 10 requests per **minute** per IP address.
See the source below for which paths are protected. This includes user creation,
user confirmation, user sign in, and password reset.
diff --git a/doc/user/group/epics/img/button_reopen_epic.png b/doc/user/group/epics/img/button_reopen_epic.png
index 7a953189270..9d1be88549d 100644
--- a/doc/user/group/epics/img/button_reopen_epic.png
+++ b/doc/user/group/epics/img/button_reopen_epic.png
Binary files differ
diff --git a/doc/user/group/epics/img/containing_epic.png b/doc/user/group/epics/img/containing_epic.png
index 5ed693e6d6a..dc13d55e2bc 100644
--- a/doc/user/group/epics/img/containing_epic.png
+++ b/doc/user/group/epics/img/containing_epic.png
Binary files differ
diff --git a/doc/user/group/epics/img/epic_view.png b/doc/user/group/epics/img/epic_view.png
index dbda98e4351..c55d302ec29 100644
--- a/doc/user/group/epics/img/epic_view.png
+++ b/doc/user/group/epics/img/epic_view.png
Binary files differ
diff --git a/doc/user/group/img/group_file_template_dropdown.png b/doc/user/group/img/group_file_template_dropdown.png
index d9caae1a223..f0586772218 100644
--- a/doc/user/group/img/group_file_template_dropdown.png
+++ b/doc/user/group/img/group_file_template_dropdown.png
Binary files differ
diff --git a/doc/user/group/img/group_file_template_settings.png b/doc/user/group/img/group_file_template_settings.png
index ca42f7726db..5e07974bc86 100644
--- a/doc/user/group/img/group_file_template_settings.png
+++ b/doc/user/group/img/group_file_template_settings.png
Binary files differ
diff --git a/doc/user/group/insights/img/insights_example_stacked_bar_chart.png b/doc/user/group/insights/img/insights_example_stacked_bar_chart.png
index 791d0e4bcdf..0e338b99e4c 100644
--- a/doc/user/group/insights/img/insights_example_stacked_bar_chart.png
+++ b/doc/user/group/insights/img/insights_example_stacked_bar_chart.png
Binary files differ
diff --git a/doc/user/group/insights/img/insights_group_configuration.png b/doc/user/group/insights/img/insights_group_configuration.png
index 0af0073e448..d181a1e94c3 100644
--- a/doc/user/group/insights/img/insights_group_configuration.png
+++ b/doc/user/group/insights/img/insights_group_configuration.png
Binary files differ
diff --git a/doc/user/group/insights/img/insights_sidebar_link.png b/doc/user/group/insights/img/insights_sidebar_link.png
index 64bbd1fc4d3..f7b0c2daae3 100644
--- a/doc/user/group/insights/img/insights_sidebar_link.png
+++ b/doc/user/group/insights/img/insights_sidebar_link.png
Binary files differ
diff --git a/doc/user/group/roadmap/img/roadmap_view.png b/doc/user/group/roadmap/img/roadmap_view.png
index ff41a2e0441..2be3849ba1b 100644
--- a/doc/user/group/roadmap/img/roadmap_view.png
+++ b/doc/user/group/roadmap/img/roadmap_view.png
Binary files differ
diff --git a/doc/user/group/saml_sso/img/group_saml_configuration_information.png b/doc/user/group/saml_sso/img/group_saml_configuration_information.png
index 98b83d0cb0f..e03c50ceb01 100644
--- a/doc/user/group/saml_sso/img/group_saml_configuration_information.png
+++ b/doc/user/group/saml_sso/img/group_saml_configuration_information.png
Binary files differ
diff --git a/doc/user/group/saml_sso/img/group_saml_settings.png b/doc/user/group/saml_sso/img/group_saml_settings.png
index 8c5dbe36f98..487be4faeba 100644
--- a/doc/user/group/saml_sso/img/group_saml_settings.png
+++ b/doc/user/group/saml_sso/img/group_saml_settings.png
Binary files differ
diff --git a/doc/user/group/saml_sso/img/scim_advanced.png b/doc/user/group/saml_sso/img/scim_advanced.png
index 3b70e3fbe83..c9e095dc89a 100644
--- a/doc/user/group/saml_sso/img/scim_advanced.png
+++ b/doc/user/group/saml_sso/img/scim_advanced.png
Binary files differ
diff --git a/doc/user/group/saml_sso/img/scim_attribute_mapping.png b/doc/user/group/saml_sso/img/scim_attribute_mapping.png
index dad459d8c28..933d8fb6f36 100644
--- a/doc/user/group/saml_sso/img/scim_attribute_mapping.png
+++ b/doc/user/group/saml_sso/img/scim_attribute_mapping.png
Binary files differ
diff --git a/doc/user/group/saml_sso/img/scim_name_identifier_mapping.png b/doc/user/group/saml_sso/img/scim_name_identifier_mapping.png
index 85e5648816e..f9c63970f16 100644
--- a/doc/user/group/saml_sso/img/scim_name_identifier_mapping.png
+++ b/doc/user/group/saml_sso/img/scim_name_identifier_mapping.png
Binary files differ
diff --git a/doc/user/group/saml_sso/img/scim_provisioning_status.png b/doc/user/group/saml_sso/img/scim_provisioning_status.png
index 4b8887b5418..41466ec9276 100644
--- a/doc/user/group/saml_sso/img/scim_provisioning_status.png
+++ b/doc/user/group/saml_sso/img/scim_provisioning_status.png
Binary files differ
diff --git a/doc/user/group/saml_sso/img/scim_token.png b/doc/user/group/saml_sso/img/scim_token.png
index 7eb52bf6ea2..bf9347716e9 100644
--- a/doc/user/group/saml_sso/img/scim_token.png
+++ b/doc/user/group/saml_sso/img/scim_token.png
Binary files differ
diff --git a/doc/user/group/saml_sso/img/unlink_group_saml.png b/doc/user/group/saml_sso/img/unlink_group_saml.png
index 0561443b5f4..9d53a9bf407 100644
--- a/doc/user/group/saml_sso/img/unlink_group_saml.png
+++ b/doc/user/group/saml_sso/img/unlink_group_saml.png
Binary files differ
diff --git a/doc/user/operations_dashboard/img/index_operations_dashboard_top_bar_icon.png b/doc/user/operations_dashboard/img/index_operations_dashboard_top_bar_icon.png
index 9d6a509ea72..d4db5e88672 100644
--- a/doc/user/operations_dashboard/img/index_operations_dashboard_top_bar_icon.png
+++ b/doc/user/operations_dashboard/img/index_operations_dashboard_top_bar_icon.png
Binary files differ
diff --git a/doc/user/operations_dashboard/img/index_operations_dashboard_with_projects.png b/doc/user/operations_dashboard/img/index_operations_dashboard_with_projects.png
index ee33eee8134..7dbec81c18a 100644
--- a/doc/user/operations_dashboard/img/index_operations_dashboard_with_projects.png
+++ b/doc/user/operations_dashboard/img/index_operations_dashboard_with_projects.png
Binary files differ
diff --git a/doc/user/profile/img/active_sessions_list.png b/doc/user/profile/img/active_sessions_list.png
index 1e242ac4710..41173c7eee5 100644
--- a/doc/user/profile/img/active_sessions_list.png
+++ b/doc/user/profile/img/active_sessions_list.png
Binary files differ
diff --git a/doc/user/project/clusters/img/k8s_cluster_monitoring.png b/doc/user/project/clusters/img/k8s_cluster_monitoring.png
index e449893a606..0a8c5043c65 100644
--- a/doc/user/project/clusters/img/k8s_cluster_monitoring.png
+++ b/doc/user/project/clusters/img/k8s_cluster_monitoring.png
Binary files differ
diff --git a/doc/user/project/clusters/index.md b/doc/user/project/clusters/index.md
index f0d80dad94f..7dfd0d04637 100644
--- a/doc/user/project/clusters/index.md
+++ b/doc/user/project/clusters/index.md
@@ -384,13 +384,9 @@ NOTE: **Note:**
[RBAC](#rbac-cluster-resources) is recommended and the GitLab default.
GitLab creates the necessary service accounts and privileges to install and run
-[GitLab managed applications](#installing-applications). When GitLab creates the cluster:
-
-- A `gitlab` service account with `cluster-admin` privileges is created in the `default` namespace
- to manage the newly created cluster.
-- A project service account with [`edit`
- privileges](https://kubernetes.io/docs/reference/access-authn-authz/rbac/#user-facing-roles)
- is created in the GitLab-created project namespace for [deployment jobs](#deployment-variables).
+[GitLab managed applications](#installing-applications). When GitLab creates the cluster,
+a `gitlab` service account with `cluster-admin` privileges is created in the `default` namespace
+to manage the newly created cluster.
NOTE: **Note:**
Restricted service account for deployment was [introduced](https://gitlab.com/gitlab-org/gitlab-ce/issues/51716) in GitLab 11.5.
@@ -412,32 +408,37 @@ The resources created by GitLab differ depending on the type of cluster.
GitLab creates the following resources for ABAC clusters.
-| Name | Type | Details | Created when |
-|:------------------|:---------------------|:----------------------------------|:---------------------------|
-| `gitlab` | `ServiceAccount` | `default` namespace | Creating a new GKE Cluster |
-| `gitlab-token` | `Secret` | Token for `gitlab` ServiceAccount | Creating a new GKE Cluster |
-| `tiller` | `ServiceAccount` | `gitlab-managed-apps` namespace | Installing Helm Tiller |
-| `tiller-admin` | `ClusterRoleBinding` | `cluster-admin` roleRef | Installing Helm Tiller |
-| Project namespace | `ServiceAccount` | Uses namespace of Project | Deploying to a cluster |
-| Project namespace | `Secret` | Token for project ServiceAccount | Deploying to a cluster |
+| Name | Type | Details | Created when |
+|:----------------------|:---------------------|:-------------------------------------|:---------------------------|
+| `gitlab` | `ServiceAccount` | `default` namespace | Creating a new GKE Cluster |
+| `gitlab-token` | `Secret` | Token for `gitlab` ServiceAccount | Creating a new GKE Cluster |
+| `tiller` | `ServiceAccount` | `gitlab-managed-apps` namespace | Installing Helm Tiller |
+| `tiller-admin` | `ClusterRoleBinding` | `cluster-admin` roleRef | Installing Helm Tiller |
+| Environment namespace | `Namespace` | Contains all environment-specific resources | Deploying to a cluster |
+| Environment namespace | `ServiceAccount` | Uses namespace of environment | Deploying to a cluster |
+| Environment namespace | `Secret` | Token for environment ServiceAccount | Deploying to a cluster |
#### RBAC cluster resources
GitLab creates the following resources for RBAC clusters.
-| Name | Type | Details | Created when |
-|:------------------|:---------------------|:-----------------------------------------------------------------------------------------------------------|:---------------------------|
-| `gitlab` | `ServiceAccount` | `default` namespace | Creating a new GKE Cluster |
-| `gitlab-admin` | `ClusterRoleBinding` | [`cluster-admin`](https://kubernetes.io/docs/reference/access-authn-authz/rbac/#user-facing-roles) roleRef | Creating a new GKE Cluster |
-| `gitlab-token` | `Secret` | Token for `gitlab` ServiceAccount | Creating a new GKE Cluster |
-| `tiller` | `ServiceAccount` | `gitlab-managed-apps` namespace | Installing Helm Tiller |
-| `tiller-admin` | `ClusterRoleBinding` | `cluster-admin` roleRef | Installing Helm Tiller |
-| Project namespace | `ServiceAccount` | Uses namespace of Project | Deploying to a cluster |
-| Project namespace | `Secret` | Token for project ServiceAccount | Deploying to a cluster |
-| Project namespace | `RoleBinding` | [`edit`](https://kubernetes.io/docs/reference/access-authn-authz/rbac/#user-facing-roles) roleRef | Deploying to a cluster |
+| Name | Type | Details | Created when |
+|:----------------------|:---------------------|:-----------------------------------------------------------------------------------------------------------|:---------------------------|
+| `gitlab` | `ServiceAccount` | `default` namespace | Creating a new GKE Cluster |
+| `gitlab-admin` | `ClusterRoleBinding` | [`cluster-admin`](https://kubernetes.io/docs/reference/access-authn-authz/rbac/#user-facing-roles) roleRef | Creating a new GKE Cluster |
+| `gitlab-token` | `Secret` | Token for `gitlab` ServiceAccount | Creating a new GKE Cluster |
+| `tiller` | `ServiceAccount` | `gitlab-managed-apps` namespace | Installing Helm Tiller |
+| `tiller-admin` | `ClusterRoleBinding` | `cluster-admin` roleRef | Installing Helm Tiller |
+| Environment namespace | `Namespace` | Contains all environment-specific resources | Deploying to a cluster |
+| Environment namespace | `ServiceAccount` | Uses namespace of environment | Deploying to a cluster |
+| Environment namespace | `Secret` | Token for environment ServiceAccount | Deploying to a cluster |
+| Environment namespace | `RoleBinding` | [`edit`](https://kubernetes.io/docs/reference/access-authn-authz/rbac/#user-facing-roles) roleRef | Deploying to a cluster |
+
+NOTE: **Note:**
+Environment-specific resources are only created if your cluster is [managed by GitLab](#gitlab-managed-clusters).
NOTE: **Note:**
-Project-specific resources are only created if your cluster is [managed by GitLab](#gitlab-managed-clusters).
+If your project was created before GitLab 12.2 it will use a single namespace for all project environments.
#### Security of GitLab Runners
@@ -640,8 +641,8 @@ GitLab CI/CD build environment.
| Variable | Description |
| -------- | ----------- |
| `KUBE_URL` | Equal to the API URL. |
-| `KUBE_TOKEN` | The Kubernetes token of the [project service account](#access-controls). |
-| `KUBE_NAMESPACE` | The Kubernetes namespace is auto-generated if not specified. The default value is `<project_name>-<project_id>`. You can overwrite it to use different one if needed, otherwise the `KUBE_NAMESPACE` variable will receive the default value. |
+| `KUBE_TOKEN` | The Kubernetes token of the [environment service account](#access-controls). |
+| `KUBE_NAMESPACE` | The Kubernetes namespace is auto-generated if not specified. The default value is `<project_name>-<project_id>-<environment>`. You can overwrite it to use different one if needed, otherwise the `KUBE_NAMESPACE` variable will receive the default value. |
| `KUBE_CA_PEM_FILE` | Path to a file containing PEM data. Only present if a custom CA bundle was specified. |
| `KUBE_CA_PEM` | (**deprecated**) Raw PEM data. Only if a custom CA bundle was specified. |
| `KUBECONFIG` | Path to a file containing `kubeconfig` for this deployment. CA bundle would be embedded if specified. This config also embeds the same token defined in `KUBE_TOKEN` so you likely will only need this variable. This variable name is also automatically picked up by `kubectl` so you won't actually need to reference it explicitly if using `kubectl`. |
diff --git a/doc/user/project/clusters/serverless/img/dns-entry.png b/doc/user/project/clusters/serverless/img/dns-entry.png
index 351e40b77d5..7b5d6497f0e 100644
--- a/doc/user/project/clusters/serverless/img/dns-entry.png
+++ b/doc/user/project/clusters/serverless/img/dns-entry.png
Binary files differ
diff --git a/doc/user/project/clusters/serverless/img/function-details-loaded.png b/doc/user/project/clusters/serverless/img/function-details-loaded.png
index 34465c5c087..2f0d61f8032 100644
--- a/doc/user/project/clusters/serverless/img/function-details-loaded.png
+++ b/doc/user/project/clusters/serverless/img/function-details-loaded.png
Binary files differ
diff --git a/doc/user/project/clusters/serverless/img/function-endpoint.png b/doc/user/project/clusters/serverless/img/function-endpoint.png
index f3c7ae7a00d..a38fe2cb6c2 100644
--- a/doc/user/project/clusters/serverless/img/function-endpoint.png
+++ b/doc/user/project/clusters/serverless/img/function-endpoint.png
Binary files differ
diff --git a/doc/user/project/clusters/serverless/img/function-execution.png b/doc/user/project/clusters/serverless/img/function-execution.png
index 93b0b6d802d..f60dd277081 100644
--- a/doc/user/project/clusters/serverless/img/function-execution.png
+++ b/doc/user/project/clusters/serverless/img/function-execution.png
Binary files differ
diff --git a/doc/user/project/clusters/serverless/img/install-knative.png b/doc/user/project/clusters/serverless/img/install-knative.png
index ecc2f8fb481..1dc830848f2 100644
--- a/doc/user/project/clusters/serverless/img/install-knative.png
+++ b/doc/user/project/clusters/serverless/img/install-knative.png
Binary files differ
diff --git a/doc/user/project/clusters/serverless/img/serverless-page.png b/doc/user/project/clusters/serverless/img/serverless-page.png
index a872fda7740..8dce3cb1f70 100644
--- a/doc/user/project/clusters/serverless/img/serverless-page.png
+++ b/doc/user/project/clusters/serverless/img/serverless-page.png
Binary files differ
diff --git a/doc/user/project/clusters/serverless/index.md b/doc/user/project/clusters/serverless/index.md
index 92ad49e9448..bcf9a677a40 100644
--- a/doc/user/project/clusters/serverless/index.md
+++ b/doc/user/project/clusters/serverless/index.md
@@ -434,7 +434,7 @@ The instructions below relate to installing and running Certbot on a Linux serve
./certbot-auto certonly --manual --preferred-challenges dns -d '*.<namespace>.example.com'
```
- Where `<namespace>` is the namespace created by GitLab for your serverless project (composed of `<projectname+id>`) and
+ Where `<namespace>` is the namespace created by GitLab for your serverless project (composed of `<project_name>-<project_id>-<environment>`) and
`example.com` is the domain being used for your project. If you are unsure what the namespace of your project is, navigate
to the **Operations > Serverless** page of your project and inspect
the endpoint provided for your function/app.
diff --git a/doc/user/project/deploy_tokens/img/deploy_tokens.png b/doc/user/project/deploy_tokens/img/deploy_tokens.png
index 421aa1ab3e5..493de8e0fce 100644
--- a/doc/user/project/deploy_tokens/img/deploy_tokens.png
+++ b/doc/user/project/deploy_tokens/img/deploy_tokens.png
Binary files differ
diff --git a/doc/user/project/img/cycle_analytics_landing_page.png b/doc/user/project/img/cycle_analytics_landing_page.png
index cf46098b9a4..c0c07e84a82 100644
--- a/doc/user/project/img/cycle_analytics_landing_page.png
+++ b/doc/user/project/img/cycle_analytics_landing_page.png
Binary files differ
diff --git a/doc/user/project/img/deploy_boards_kubernetes_label.png b/doc/user/project/img/deploy_boards_kubernetes_label.png
index 19785c74d07..130ff2caa8a 100644
--- a/doc/user/project/img/deploy_boards_kubernetes_label.png
+++ b/doc/user/project/img/deploy_boards_kubernetes_label.png
Binary files differ
diff --git a/doc/user/project/img/file_lock.png b/doc/user/project/img/file_lock.png
index 82699a12ffd..e881442630b 100644
--- a/doc/user/project/img/file_lock.png
+++ b/doc/user/project/img/file_lock.png
Binary files differ
diff --git a/doc/user/project/img/file_lock_merge_request_error_message.png b/doc/user/project/img/file_lock_merge_request_error_message.png
index 4ef04b15bef..64bcc86ac0d 100644
--- a/doc/user/project/img/file_lock_merge_request_error_message.png
+++ b/doc/user/project/img/file_lock_merge_request_error_message.png
Binary files differ
diff --git a/doc/user/project/img/file_lock_repository_view.png b/doc/user/project/img/file_lock_repository_view.png
index a2cab0decab..ced14198da9 100644
--- a/doc/user/project/img/file_lock_repository_view.png
+++ b/doc/user/project/img/file_lock_repository_view.png
Binary files differ
diff --git a/doc/user/project/img/issue_boards_multiple.png b/doc/user/project/img/issue_boards_multiple.png
index 4b1a8356dc9..e6183360610 100644
--- a/doc/user/project/img/issue_boards_multiple.png
+++ b/doc/user/project/img/issue_boards_multiple.png
Binary files differ
diff --git a/doc/user/project/img/labels_default_v12_1.png b/doc/user/project/img/labels_default_v12_1.png
index 4a0a6ba9ce0..b36b5dac80b 100644
--- a/doc/user/project/img/labels_default_v12_1.png
+++ b/doc/user/project/img/labels_default_v12_1.png
Binary files differ
diff --git a/doc/user/project/img/labels_delete_v12_1.png b/doc/user/project/img/labels_delete_v12_1.png
index 2e0ea934519..566e0519fbe 100644
--- a/doc/user/project/img/labels_delete_v12_1.png
+++ b/doc/user/project/img/labels_delete_v12_1.png
Binary files differ
diff --git a/doc/user/project/img/labels_epic_sidebar_v12_1.png b/doc/user/project/img/labels_epic_sidebar_v12_1.png
index 7e05c6d1ce4..13fbab33e26 100644
--- a/doc/user/project/img/labels_epic_sidebar_v12_1.png
+++ b/doc/user/project/img/labels_epic_sidebar_v12_1.png
Binary files differ
diff --git a/doc/user/project/img/labels_generate_default_v12_1.png b/doc/user/project/img/labels_generate_default_v12_1.png
index 48adc9a5699..cbdda2ab4dd 100644
--- a/doc/user/project/img/labels_generate_default_v12_1.png
+++ b/doc/user/project/img/labels_generate_default_v12_1.png
Binary files differ
diff --git a/doc/user/project/img/labels_group_issues_v12_1.png b/doc/user/project/img/labels_group_issues_v12_1.png
index bfe425f20ac..3f8f93c1dfd 100644
--- a/doc/user/project/img/labels_group_issues_v12_1.png
+++ b/doc/user/project/img/labels_group_issues_v12_1.png
Binary files differ
diff --git a/doc/user/project/img/labels_key_value_v12_1.png b/doc/user/project/img/labels_key_value_v12_1.png
index 81d5c416c95..52906b7b458 100644
--- a/doc/user/project/img/labels_key_value_v12_1.png
+++ b/doc/user/project/img/labels_key_value_v12_1.png
Binary files differ
diff --git a/doc/user/project/img/labels_list_v12_1.png b/doc/user/project/img/labels_list_v12_1.png
index c414ab42fbc..47359d05f7f 100644
--- a/doc/user/project/img/labels_list_v12_1.png
+++ b/doc/user/project/img/labels_list_v12_1.png
Binary files differ
diff --git a/doc/user/project/img/labels_prioritized_v12_1.png b/doc/user/project/img/labels_prioritized_v12_1.png
index 8ea69949d8e..512c5d59a5a 100644
--- a/doc/user/project/img/labels_prioritized_v12_1.png
+++ b/doc/user/project/img/labels_prioritized_v12_1.png
Binary files differ
diff --git a/doc/user/project/img/labels_promotion_v12_1.png b/doc/user/project/img/labels_promotion_v12_1.png
index 238d50981ae..7cd8ff24e02 100644
--- a/doc/user/project/img/labels_promotion_v12_1.png
+++ b/doc/user/project/img/labels_promotion_v12_1.png
Binary files differ
diff --git a/doc/user/project/img/labels_subscriptions_v12_1.png b/doc/user/project/img/labels_subscriptions_v12_1.png
index 57c437ac8a4..fa83b7db414 100644
--- a/doc/user/project/img/labels_subscriptions_v12_1.png
+++ b/doc/user/project/img/labels_subscriptions_v12_1.png
Binary files differ
diff --git a/doc/user/project/img/service_desk_disabled.png b/doc/user/project/img/service_desk_disabled.png
index 3ae64dcbe96..edae7e76986 100644
--- a/doc/user/project/img/service_desk_disabled.png
+++ b/doc/user/project/img/service_desk_disabled.png
Binary files differ
diff --git a/doc/user/project/img/service_desk_enabled.png b/doc/user/project/img/service_desk_enabled.png
index 329348e4b52..9c143ff58cd 100644
--- a/doc/user/project/img/service_desk_enabled.png
+++ b/doc/user/project/img/service_desk_enabled.png
Binary files differ
diff --git a/doc/user/project/img/service_desk_issue_tracker.png b/doc/user/project/img/service_desk_issue_tracker.png
index 485751fab0a..02d18c9debb 100644
--- a/doc/user/project/img/service_desk_issue_tracker.png
+++ b/doc/user/project/img/service_desk_issue_tracker.png
Binary files differ
diff --git a/doc/user/project/import/tfs.md b/doc/user/project/import/tfs.md
index b4597a4da60..01bbb7e6ffd 100644
--- a/doc/user/project/import/tfs.md
+++ b/doc/user/project/import/tfs.md
@@ -1,6 +1,6 @@
# Migrating from TFS
-[TFS](https://visualstudio.microsoft.com/tfs/) is a set of tools developed by Microsoft
+[TFS](https://azure.microsoft.com/en-us/services/devops/server/) is a set of tools developed by Microsoft
which also includes a centralized version control system (TFVC) similar to Git.
In this document, we emphasize on the TFVC to Git migration.
diff --git a/doc/user/project/insights/img/insights_example_bar_chart.png b/doc/user/project/insights/img/insights_example_bar_chart.png
index eb96eb4a90f..5fd24265b32 100644
--- a/doc/user/project/insights/img/insights_example_bar_chart.png
+++ b/doc/user/project/insights/img/insights_example_bar_chart.png
Binary files differ
diff --git a/doc/user/project/insights/img/insights_example_bar_time_series_chart.png b/doc/user/project/insights/img/insights_example_bar_time_series_chart.png
index 28aa81939d8..2e32df3e2b1 100644
--- a/doc/user/project/insights/img/insights_example_bar_time_series_chart.png
+++ b/doc/user/project/insights/img/insights_example_bar_time_series_chart.png
Binary files differ
diff --git a/doc/user/project/insights/img/insights_example_line_chart.png b/doc/user/project/insights/img/insights_example_line_chart.png
index 131dbedd35e..9460b104339 100644
--- a/doc/user/project/insights/img/insights_example_line_chart.png
+++ b/doc/user/project/insights/img/insights_example_line_chart.png
Binary files differ
diff --git a/doc/user/project/insights/img/insights_example_pie_chart.png b/doc/user/project/insights/img/insights_example_pie_chart.png
index 518ed7338f9..3480bce6738 100644
--- a/doc/user/project/insights/img/insights_example_pie_chart.png
+++ b/doc/user/project/insights/img/insights_example_pie_chart.png
Binary files differ
diff --git a/doc/user/project/insights/img/insights_example_stacked_bar_chart.png b/doc/user/project/insights/img/insights_example_stacked_bar_chart.png
index aafec4b394e..a3fb50488f5 100644
--- a/doc/user/project/insights/img/insights_example_stacked_bar_chart.png
+++ b/doc/user/project/insights/img/insights_example_stacked_bar_chart.png
Binary files differ
diff --git a/doc/user/project/insights/img/insights_sidebar_link.png b/doc/user/project/insights/img/insights_sidebar_link.png
index aadb5745992..9fc449baf68 100644
--- a/doc/user/project/insights/img/insights_sidebar_link.png
+++ b/doc/user/project/insights/img/insights_sidebar_link.png
Binary files differ
diff --git a/doc/user/project/insights/img/project_insights.png b/doc/user/project/insights/img/project_insights.png
index 2d0292dda54..83674c94110 100644
--- a/doc/user/project/insights/img/project_insights.png
+++ b/doc/user/project/insights/img/project_insights.png
Binary files differ
diff --git a/doc/user/project/integrations/img/github_configuration.png b/doc/user/project/integrations/img/github_configuration.png
index 9f2d47921c7..5798b826681 100644
--- a/doc/user/project/integrations/img/github_configuration.png
+++ b/doc/user/project/integrations/img/github_configuration.png
Binary files differ
diff --git a/doc/user/project/integrations/img/jira_add_user_to_group.png b/doc/user/project/integrations/img/jira_add_user_to_group.png
index d8cf541a81e..b63a851a987 100644
--- a/doc/user/project/integrations/img/jira_add_user_to_group.png
+++ b/doc/user/project/integrations/img/jira_add_user_to_group.png
Binary files differ
diff --git a/doc/user/project/integrations/img/jira_added_user_to_group.png b/doc/user/project/integrations/img/jira_added_user_to_group.png
index b3e29a65d6e..f5120a8d42e 100644
--- a/doc/user/project/integrations/img/jira_added_user_to_group.png
+++ b/doc/user/project/integrations/img/jira_added_user_to_group.png
Binary files differ
diff --git a/doc/user/project/integrations/img/jira_api_token.png b/doc/user/project/integrations/img/jira_api_token.png
index 29689271bf7..d9d37713a4d 100644
--- a/doc/user/project/integrations/img/jira_api_token.png
+++ b/doc/user/project/integrations/img/jira_api_token.png
Binary files differ
diff --git a/doc/user/project/integrations/img/jira_api_token_menu.png b/doc/user/project/integrations/img/jira_api_token_menu.png
index 1aca1d78f36..a10a59a243d 100644
--- a/doc/user/project/integrations/img/jira_api_token_menu.png
+++ b/doc/user/project/integrations/img/jira_api_token_menu.png
Binary files differ
diff --git a/doc/user/project/integrations/img/jira_create_new_group.png b/doc/user/project/integrations/img/jira_create_new_group.png
index 84be3a94a45..4ab7a5eae4e 100644
--- a/doc/user/project/integrations/img/jira_create_new_group.png
+++ b/doc/user/project/integrations/img/jira_create_new_group.png
Binary files differ
diff --git a/doc/user/project/integrations/img/jira_create_new_user.png b/doc/user/project/integrations/img/jira_create_new_user.png
index 8460dc98ef9..c74933298e3 100644
--- a/doc/user/project/integrations/img/jira_create_new_user.png
+++ b/doc/user/project/integrations/img/jira_create_new_user.png
Binary files differ
diff --git a/doc/user/project/integrations/img/jira_group_access.png b/doc/user/project/integrations/img/jira_group_access.png
index 58cf114bd55..e33f2eed242 100644
--- a/doc/user/project/integrations/img/jira_group_access.png
+++ b/doc/user/project/integrations/img/jira_group_access.png
Binary files differ
diff --git a/doc/user/project/integrations/img/jira_issue_reference.png b/doc/user/project/integrations/img/jira_issue_reference.png
index a3e80c1b054..db8bc4f0bb9 100644
--- a/doc/user/project/integrations/img/jira_issue_reference.png
+++ b/doc/user/project/integrations/img/jira_issue_reference.png
Binary files differ
diff --git a/doc/user/project/integrations/img/jira_merge_request_close.png b/doc/user/project/integrations/img/jira_merge_request_close.png
index 1c089c94207..9a176daf5f4 100644
--- a/doc/user/project/integrations/img/jira_merge_request_close.png
+++ b/doc/user/project/integrations/img/jira_merge_request_close.png
Binary files differ
diff --git a/doc/user/project/integrations/img/jira_service_page.png b/doc/user/project/integrations/img/jira_service_page.png
index 80dd65ea24e..76fd5f4641c 100644
--- a/doc/user/project/integrations/img/jira_service_page.png
+++ b/doc/user/project/integrations/img/jira_service_page.png
Binary files differ
diff --git a/doc/user/project/integrations/img/jira_user_management_link.png b/doc/user/project/integrations/img/jira_user_management_link.png
index 43ef18da6c8..caecd1d71fc 100644
--- a/doc/user/project/integrations/img/jira_user_management_link.png
+++ b/doc/user/project/integrations/img/jira_user_management_link.png
Binary files differ
diff --git a/doc/user/project/integrations/img/mattermost_configuration.png b/doc/user/project/integrations/img/mattermost_configuration.png
index 75ef0310f2d..6abf5c5c8d6 100644
--- a/doc/user/project/integrations/img/mattermost_configuration.png
+++ b/doc/user/project/integrations/img/mattermost_configuration.png
Binary files differ
diff --git a/doc/user/project/integrations/img/prometheus_dashboard_area_panel_type.png b/doc/user/project/integrations/img/prometheus_dashboard_area_panel_type.png
index 7260b11f07b..9fdb6dfddac 100644
--- a/doc/user/project/integrations/img/prometheus_dashboard_area_panel_type.png
+++ b/doc/user/project/integrations/img/prometheus_dashboard_area_panel_type.png
Binary files differ
diff --git a/doc/user/project/integrations/img/prometheus_dashboard_single_stat_panel_type.png b/doc/user/project/integrations/img/prometheus_dashboard_single_stat_panel_type.png
index ce4c54f909d..2d7dfb27b49 100644
--- a/doc/user/project/integrations/img/prometheus_dashboard_single_stat_panel_type.png
+++ b/doc/user/project/integrations/img/prometheus_dashboard_single_stat_panel_type.png
Binary files differ
diff --git a/doc/user/project/integrations/img/prometheus_service_alerts.png b/doc/user/project/integrations/img/prometheus_service_alerts.png
index a81dfe7da14..609c5e5196c 100644
--- a/doc/user/project/integrations/img/prometheus_service_alerts.png
+++ b/doc/user/project/integrations/img/prometheus_service_alerts.png
Binary files differ
diff --git a/doc/user/project/integrations/img/slack_configuration.png b/doc/user/project/integrations/img/slack_configuration.png
index a14d2969488..10d2cda6dc7 100644
--- a/doc/user/project/integrations/img/slack_configuration.png
+++ b/doc/user/project/integrations/img/slack_configuration.png
Binary files differ
diff --git a/doc/user/project/issues/design_management.md b/doc/user/project/issues/design_management.md
index 2327fa84998..bffbcb544e3 100644
--- a/doc/user/project/issues/design_management.md
+++ b/doc/user/project/issues/design_management.md
@@ -3,7 +3,7 @@
> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/660) in [GitLab Premium](https://about.gitlab.com/pricing/) 12.2.
CAUTION: **Warning:**
-This an __alpha__ feature and is subject to change at any time without
+This an **alpha** feature and is subject to change at any time without
prior notice.
## Overview
@@ -56,3 +56,14 @@ of the design, and will replace the previous version.
Images on the Design Management page can be enlarged by clicking on them.
+## Adding annotations to designs
+
+When a design image is displayed, you can add annotations to it by clicking on
+the image. A badge is added to the image and a form is displayed to start a new
+discussion. For example:
+
+![Starting a new discussion on design](img/adding_note_to_design_1.png)
+
+When submitted, the form saves a badge linked to the discussion on the image. Different discussions have different badge numbers. For example:
+
+![Discussions on design annotations](img/adding_note_to_design_2.png)
diff --git a/doc/user/project/issues/img/adding_note_to_design_1.png b/doc/user/project/issues/img/adding_note_to_design_1.png
new file mode 100644
index 00000000000..aa50bbb69ce
--- /dev/null
+++ b/doc/user/project/issues/img/adding_note_to_design_1.png
Binary files differ
diff --git a/doc/user/project/issues/img/adding_note_to_design_2.png b/doc/user/project/issues/img/adding_note_to_design_2.png
new file mode 100644
index 00000000000..37cefeb1a15
--- /dev/null
+++ b/doc/user/project/issues/img/adding_note_to_design_2.png
Binary files differ
diff --git a/doc/user/project/issues/img/comment-or-discussion.png b/doc/user/project/issues/img/comment-or-discussion.png
index ccecc9fa39f..a29014c984c 100644
--- a/doc/user/project/issues/img/comment-or-discussion.png
+++ b/doc/user/project/issues/img/comment-or-discussion.png
Binary files differ
diff --git a/doc/user/project/issues/img/confidential_mr_branch_dropdown_v12_1.png b/doc/user/project/issues/img/confidential_mr_branch_dropdown_v12_1.png
index 7c24226a6c4..1f4ad5c42bb 100644
--- a/doc/user/project/issues/img/confidential_mr_branch_dropdown_v12_1.png
+++ b/doc/user/project/issues/img/confidential_mr_branch_dropdown_v12_1.png
Binary files differ
diff --git a/doc/user/project/issues/img/confidential_mr_dropdown_v12_1.png b/doc/user/project/issues/img/confidential_mr_dropdown_v12_1.png
index d6d391c6dd9..7b7bd599a71 100644
--- a/doc/user/project/issues/img/confidential_mr_dropdown_v12_1.png
+++ b/doc/user/project/issues/img/confidential_mr_dropdown_v12_1.png
Binary files differ
diff --git a/doc/user/project/issues/img/create_mr_from_issue.png b/doc/user/project/issues/img/create_mr_from_issue.png
index 680c42b5df0..d05a678cd17 100644
--- a/doc/user/project/issues/img/create_mr_from_issue.png
+++ b/doc/user/project/issues/img/create_mr_from_issue.png
Binary files differ
diff --git a/doc/user/project/issues/img/design_management_v12_2.png b/doc/user/project/issues/img/design_management_v12_2.png
index 6da747a3f21..ad803df4e63 100644
--- a/doc/user/project/issues/img/design_management_v12_2.png
+++ b/doc/user/project/issues/img/design_management_v12_2.png
Binary files differ
diff --git a/doc/user/project/issues/img/issues_main_view_numbered.png b/doc/user/project/issues/img/issues_main_view_numbered.png
index 16cb6b497b0..92b9df44972 100644
--- a/doc/user/project/issues/img/issues_main_view_numbered.png
+++ b/doc/user/project/issues/img/issues_main_view_numbered.png
Binary files differ
diff --git a/doc/user/project/issues/img/reopen-issue.png b/doc/user/project/issues/img/reopen-issue.png
index 1749be31239..fc48742afe0 100644
--- a/doc/user/project/issues/img/reopen-issue.png
+++ b/doc/user/project/issues/img/reopen-issue.png
Binary files differ
diff --git a/doc/user/project/issues/img/report-abuse.png b/doc/user/project/issues/img/report-abuse.png
index f189cbf1d36..f8cef22da03 100644
--- a/doc/user/project/issues/img/report-abuse.png
+++ b/doc/user/project/issues/img/report-abuse.png
Binary files differ
diff --git a/doc/user/project/issues/img/show-all-activity.png b/doc/user/project/issues/img/show-all-activity.png
index c43ba75ce25..55c6f5ab5db 100644
--- a/doc/user/project/issues/img/show-all-activity.png
+++ b/doc/user/project/issues/img/show-all-activity.png
Binary files differ
diff --git a/doc/user/project/labels.md b/doc/user/project/labels.md
index a00c1c980d2..cc1274faa2c 100644
--- a/doc/user/project/labels.md
+++ b/doc/user/project/labels.md
@@ -93,8 +93,10 @@ GitLab will add the following default labels to the project:
To create a **group label**, navigate to **Issues > Labels** in the **group** and create
it from there. This page only shows group labels in this group.
-Alternatively, you can create group labels from the Epic sidebar. Please note that the
-created label will belong to the immediate group to which the epic belongs. **(ULTIMATE)**
+Alternatively, you can create group labels from the Epic sidebar. **(ULTIMATE)**
+
+Please note that the created label will belong to the immediate group to which the
+epic belongs.
![Create Labels from Epic](img/labels_epic_sidebar_v12_1.png)
diff --git a/doc/user/project/merge_requests/img/allow_collaboration.png b/doc/user/project/merge_requests/img/allow_collaboration.png
index e40e8a6b11c..cc13493646d 100644
--- a/doc/user/project/merge_requests/img/allow_collaboration.png
+++ b/doc/user/project/merge_requests/img/allow_collaboration.png
Binary files differ
diff --git a/doc/user/project/merge_requests/img/allow_collaboration_after_save.png b/doc/user/project/merge_requests/img/allow_collaboration_after_save.png
index 4ba4c84c8c5..bc7678b21ec 100644
--- a/doc/user/project/merge_requests/img/allow_collaboration_after_save.png
+++ b/doc/user/project/merge_requests/img/allow_collaboration_after_save.png
Binary files differ
diff --git a/doc/user/project/merge_requests/img/approvals_premium_mr_widget.png b/doc/user/project/merge_requests/img/approvals_premium_mr_widget.png
index b6dc86f312e..2598cc71c33 100644
--- a/doc/user/project/merge_requests/img/approvals_premium_mr_widget.png
+++ b/doc/user/project/merge_requests/img/approvals_premium_mr_widget.png
Binary files differ
diff --git a/doc/user/project/merge_requests/img/approvals_premium_project_edit.png b/doc/user/project/merge_requests/img/approvals_premium_project_edit.png
index b6f6188b9cd..6a09412533f 100644
--- a/doc/user/project/merge_requests/img/approvals_premium_project_edit.png
+++ b/doc/user/project/merge_requests/img/approvals_premium_project_edit.png
Binary files differ
diff --git a/doc/user/project/merge_requests/img/approvals_starter_project_edit.png b/doc/user/project/merge_requests/img/approvals_starter_project_edit.png
index 868b9d58740..4c554d846cc 100644
--- a/doc/user/project/merge_requests/img/approvals_starter_project_edit.png
+++ b/doc/user/project/merge_requests/img/approvals_starter_project_edit.png
Binary files differ
diff --git a/doc/user/project/merge_requests/img/approvals_starter_project_empty.png b/doc/user/project/merge_requests/img/approvals_starter_project_empty.png
index 7375820224c..fc88a59a745 100644
--- a/doc/user/project/merge_requests/img/approvals_starter_project_empty.png
+++ b/doc/user/project/merge_requests/img/approvals_starter_project_empty.png
Binary files differ
diff --git a/doc/user/project/merge_requests/img/approve.png b/doc/user/project/merge_requests/img/approve.png
index e68259ac5c2..e2641f48c7a 100644
--- a/doc/user/project/merge_requests/img/approve.png
+++ b/doc/user/project/merge_requests/img/approve.png
Binary files differ
diff --git a/doc/user/project/merge_requests/img/approve_additionally.png b/doc/user/project/merge_requests/img/approve_additionally.png
index 3db5a9159e5..bab0cd4e041 100644
--- a/doc/user/project/merge_requests/img/approve_additionally.png
+++ b/doc/user/project/merge_requests/img/approve_additionally.png
Binary files differ
diff --git a/doc/user/project/merge_requests/img/create_from_email.png b/doc/user/project/merge_requests/img/create_from_email.png
index 5cb2afaf976..14eef473e27 100644
--- a/doc/user/project/merge_requests/img/create_from_email.png
+++ b/doc/user/project/merge_requests/img/create_from_email.png
Binary files differ
diff --git a/doc/user/project/merge_requests/img/edit_blocking_merge_requests.png b/doc/user/project/merge_requests/img/edit_blocking_merge_requests.png
index 0fe26d602e3..98345f2f0d1 100644
--- a/doc/user/project/merge_requests/img/edit_blocking_merge_requests.png
+++ b/doc/user/project/merge_requests/img/edit_blocking_merge_requests.png
Binary files differ
diff --git a/doc/user/project/merge_requests/img/edit_blocking_merge_requests_inaccessible.png b/doc/user/project/merge_requests/img/edit_blocking_merge_requests_inaccessible.png
index a1003c41c22..b19cf1db94b 100644
--- a/doc/user/project/merge_requests/img/edit_blocking_merge_requests_inaccessible.png
+++ b/doc/user/project/merge_requests/img/edit_blocking_merge_requests_inaccessible.png
Binary files differ
diff --git a/doc/user/project/merge_requests/img/filter_approver_merge_requests.png b/doc/user/project/merge_requests/img/filter_approver_merge_requests.png
index 9c386391a4f..4c28ee17f47 100644
--- a/doc/user/project/merge_requests/img/filter_approver_merge_requests.png
+++ b/doc/user/project/merge_requests/img/filter_approver_merge_requests.png
Binary files differ
diff --git a/doc/user/project/merge_requests/img/filter_wip_merge_requests.png b/doc/user/project/merge_requests/img/filter_wip_merge_requests.png
index 8df6a3c9a29..0989b41e2a4 100644
--- a/doc/user/project/merge_requests/img/filter_wip_merge_requests.png
+++ b/doc/user/project/merge_requests/img/filter_wip_merge_requests.png
Binary files differ
diff --git a/doc/user/project/merge_requests/img/merge_when_pipeline_succeeds_only_if_succeeds_settings.png b/doc/user/project/merge_requests/img/merge_when_pipeline_succeeds_only_if_succeeds_settings.png
index ea3aff59aa1..ed374b11fbd 100644
--- a/doc/user/project/merge_requests/img/merge_when_pipeline_succeeds_only_if_succeeds_settings.png
+++ b/doc/user/project/merge_requests/img/merge_when_pipeline_succeeds_only_if_succeeds_settings.png
Binary files differ
diff --git a/doc/user/project/merge_requests/img/multiple_assignees_for_merge_requests_sidebar.png b/doc/user/project/merge_requests/img/multiple_assignees_for_merge_requests_sidebar.png
index 9ae6e350798..dde2680ed74 100644
--- a/doc/user/project/merge_requests/img/multiple_assignees_for_merge_requests_sidebar.png
+++ b/doc/user/project/merge_requests/img/multiple_assignees_for_merge_requests_sidebar.png
Binary files differ
diff --git a/doc/user/project/merge_requests/img/remove_approval.png b/doc/user/project/merge_requests/img/remove_approval.png
index 6083e1745ef..b178d26cf85 100644
--- a/doc/user/project/merge_requests/img/remove_approval.png
+++ b/doc/user/project/merge_requests/img/remove_approval.png
Binary files differ
diff --git a/doc/user/project/merge_requests/img/show_blocking_merge_requests_in_mr_widget.png b/doc/user/project/merge_requests/img/show_blocking_merge_requests_in_mr_widget.png
index a1241f9e38c..3f4fcc5781d 100644
--- a/doc/user/project/merge_requests/img/show_blocking_merge_requests_in_mr_widget.png
+++ b/doc/user/project/merge_requests/img/show_blocking_merge_requests_in_mr_widget.png
Binary files differ
diff --git a/doc/user/project/merge_requests/img/squash_mr_message.png b/doc/user/project/merge_requests/img/squash_mr_message.png
index 8734cab29aa..8c7dc7886f7 100644
--- a/doc/user/project/merge_requests/img/squash_mr_message.png
+++ b/doc/user/project/merge_requests/img/squash_mr_message.png
Binary files differ
diff --git a/doc/user/project/merge_requests/img/wip_blocked_accept_button.png b/doc/user/project/merge_requests/img/wip_blocked_accept_button.png
index b6d38d85165..ab2c8425b83 100644
--- a/doc/user/project/merge_requests/img/wip_blocked_accept_button.png
+++ b/doc/user/project/merge_requests/img/wip_blocked_accept_button.png
Binary files differ
diff --git a/doc/user/project/operations/img/error_tracking_list.png b/doc/user/project/operations/img/error_tracking_list.png
index aa0f9867fdb..194c7b440a4 100644
--- a/doc/user/project/operations/img/error_tracking_list.png
+++ b/doc/user/project/operations/img/error_tracking_list.png
Binary files differ
diff --git a/doc/user/project/operations/img/external_dashboard_link.png b/doc/user/project/operations/img/external_dashboard_link.png
index 4fb8bce7cd0..82c5e05e467 100644
--- a/doc/user/project/operations/img/external_dashboard_link.png
+++ b/doc/user/project/operations/img/external_dashboard_link.png
Binary files differ
diff --git a/doc/user/project/operations/img/external_dashboard_settings.png b/doc/user/project/operations/img/external_dashboard_settings.png
index 8dc380f01e2..e1b7fa56a1c 100644
--- a/doc/user/project/operations/img/external_dashboard_settings.png
+++ b/doc/user/project/operations/img/external_dashboard_settings.png
Binary files differ
diff --git a/doc/user/project/operations/img/feature_flags_list.png b/doc/user/project/operations/img/feature_flags_list.png
index 5313a163fec..9a7af78d8a2 100644
--- a/doc/user/project/operations/img/feature_flags_list.png
+++ b/doc/user/project/operations/img/feature_flags_list.png
Binary files differ
diff --git a/doc/user/project/operations/img/specs_list.png b/doc/user/project/operations/img/specs_list.png
index 9630c907cfc..da17ef0e959 100644
--- a/doc/user/project/operations/img/specs_list.png
+++ b/doc/user/project/operations/img/specs_list.png
Binary files differ
diff --git a/doc/user/project/packages/img/npm_package_view.png b/doc/user/project/packages/img/npm_package_view.png
index 8baf7d0ef9f..e0634718c02 100644
--- a/doc/user/project/packages/img/npm_package_view.png
+++ b/doc/user/project/packages/img/npm_package_view.png
Binary files differ
diff --git a/doc/user/project/pages/custom_domains_ssl_tls_certification/img/get_domain_verification_code_v12_0.png b/doc/user/project/pages/custom_domains_ssl_tls_certification/img/get_domain_verification_code_v12_0.png
index b4dcdc9bb60..3b93572a8f1 100644
--- a/doc/user/project/pages/custom_domains_ssl_tls_certification/img/get_domain_verification_code_v12_0.png
+++ b/doc/user/project/pages/custom_domains_ssl_tls_certification/img/get_domain_verification_code_v12_0.png
Binary files differ
diff --git a/doc/user/project/pages/custom_domains_ssl_tls_certification/img/lets_encrypt_integration_v12_1.png b/doc/user/project/pages/custom_domains_ssl_tls_certification/img/lets_encrypt_integration_v12_1.png
index 2e825e84d92..5eab04a61a9 100644
--- a/doc/user/project/pages/custom_domains_ssl_tls_certification/img/lets_encrypt_integration_v12_1.png
+++ b/doc/user/project/pages/custom_domains_ssl_tls_certification/img/lets_encrypt_integration_v12_1.png
Binary files differ
diff --git a/doc/user/project/pages/custom_domains_ssl_tls_certification/img/retry_domain_verification_v12_0.png b/doc/user/project/pages/custom_domains_ssl_tls_certification/img/retry_domain_verification_v12_0.png
index db8f25bc6c3..5f2f100e883 100644
--- a/doc/user/project/pages/custom_domains_ssl_tls_certification/img/retry_domain_verification_v12_0.png
+++ b/doc/user/project/pages/custom_domains_ssl_tls_certification/img/retry_domain_verification_v12_0.png
Binary files differ
diff --git a/doc/user/project/pages/custom_domains_ssl_tls_certification/ssl_tls_concepts.md b/doc/user/project/pages/custom_domains_ssl_tls_certification/ssl_tls_concepts.md
index 2470e78819f..ee0550bfca2 100644
--- a/doc/user/project/pages/custom_domains_ssl_tls_certification/ssl_tls_concepts.md
+++ b/doc/user/project/pages/custom_domains_ssl_tls_certification/ssl_tls_concepts.md
@@ -67,7 +67,7 @@ There are some certificate authorities that
offer free certificates, aiming to make the internet more secure
to everyone. The most popular is [Let's Encrypt](https://letsencrypt.org/),
which issues certificates trusted by most of browsers, it's open
-source, and free to use. See our tutorial on [how to secure your GitLab Pages website with Let's Encrypt](../lets_encrypt_for_gitlab_pages.md).
+source, and free to use. See [GitLab Pages integration with Let's Encrypt](../custom_domains_ssl_tls_certification/lets_encrypt_integration.md) to enable HTTPS on your custom domain.
Similarly popular are [certificates issued by CloudFlare](https://www.cloudflare.com/ssl/),
which also offers a [free CDN service](https://blog.cloudflare.com/cloudflares-free-cdn-and-you/).
diff --git a/doc/user/project/pages/img/pages_project_templates_v11_8.png b/doc/user/project/pages/img/pages_project_templates_v11_8.png
index a645d28260b..61cae88b5a8 100644
--- a/doc/user/project/pages/img/pages_project_templates_v11_8.png
+++ b/doc/user/project/pages/img/pages_project_templates_v11_8.png
Binary files differ
diff --git a/doc/user/project/pages/img/remove_pages.png b/doc/user/project/pages/img/remove_pages.png
index 60f76f15f93..d6c37ef30cd 100644
--- a/doc/user/project/pages/img/remove_pages.png
+++ b/doc/user/project/pages/img/remove_pages.png
Binary files differ
diff --git a/doc/user/project/pipelines/img/pipeline_schedule_variables.png b/doc/user/project/pipelines/img/pipeline_schedule_variables.png
index 29846206491..ce3c3dc6af1 100644
--- a/doc/user/project/pipelines/img/pipeline_schedule_variables.png
+++ b/doc/user/project/pipelines/img/pipeline_schedule_variables.png
Binary files differ
diff --git a/doc/user/project/pipelines/img/pipeline_schedules_new_form.png b/doc/user/project/pipelines/img/pipeline_schedules_new_form.png
index e135dd51070..993fbf8ca00 100644
--- a/doc/user/project/pipelines/img/pipeline_schedules_new_form.png
+++ b/doc/user/project/pipelines/img/pipeline_schedules_new_form.png
Binary files differ
diff --git a/doc/user/project/releases/img/releases.png b/doc/user/project/releases/img/releases.png
index f8b1b7305ad..da5bcd9d913 100644
--- a/doc/user/project/releases/img/releases.png
+++ b/doc/user/project/releases/img/releases.png
Binary files differ
diff --git a/doc/user/project/repository/img/download_source_code.png b/doc/user/project/repository/img/download_source_code.png
index 17f2cb4b3e8..56808061980 100644
--- a/doc/user/project/repository/img/download_source_code.png
+++ b/doc/user/project/repository/img/download_source_code.png
Binary files differ
diff --git a/doc/user/project/settings/img/general_settings.png b/doc/user/project/settings/img/general_settings.png
index 4ff6fff5ca3..f88a158d2be 100644
--- a/doc/user/project/settings/img/general_settings.png
+++ b/doc/user/project/settings/img/general_settings.png
Binary files differ
diff --git a/doc/user/project/settings/img/import_export_download_export.png b/doc/user/project/settings/img/import_export_download_export.png
index ab81c87bf5f..c7ab7565fc7 100644
--- a/doc/user/project/settings/img/import_export_download_export.png
+++ b/doc/user/project/settings/img/import_export_download_export.png
Binary files differ
diff --git a/doc/user/project/settings/img/import_export_export_button.png b/doc/user/project/settings/img/import_export_export_button.png
index 9e368739695..6933e3edfcc 100644
--- a/doc/user/project/settings/img/import_export_export_button.png
+++ b/doc/user/project/settings/img/import_export_export_button.png
Binary files differ
diff --git a/doc/user/project/settings/img/import_export_mail_link.png b/doc/user/project/settings/img/import_export_mail_link.png
index 985c37650d3..1bd9a071178 100644
--- a/doc/user/project/settings/img/import_export_mail_link.png
+++ b/doc/user/project/settings/img/import_export_mail_link.png
Binary files differ
diff --git a/doc/user/project/settings/img/import_export_new_project.png b/doc/user/project/settings/img/import_export_new_project.png
index fc1f73c5d6e..0e2365ecb68 100644
--- a/doc/user/project/settings/img/import_export_new_project.png
+++ b/doc/user/project/settings/img/import_export_new_project.png
Binary files differ
diff --git a/doc/user/project/settings/img/import_export_select_file.png b/doc/user/project/settings/img/import_export_select_file.png
index e3e1a5ef980..90a3e8d5c4e 100644
--- a/doc/user/project/settings/img/import_export_select_file.png
+++ b/doc/user/project/settings/img/import_export_select_file.png
Binary files differ
diff --git a/doc/user/project/settings/import_export.md b/doc/user/project/settings/import_export.md
index 35d5320c0b1..9c1a31fb7c3 100644
--- a/doc/user/project/settings/import_export.md
+++ b/doc/user/project/settings/import_export.md
@@ -66,6 +66,7 @@ The following items will be exported:
- Issues with comments, merge requests with diffs and comments, labels, milestones, snippets,
and other project entities
- LFS objects
+- Issue boards
The following items will NOT be exported:
diff --git a/doc/user/project/web_ide/img/terminal_status.png b/doc/user/project/web_ide/img/terminal_status.png
index c37aa02b07a..91c341a9854 100644
--- a/doc/user/project/web_ide/img/terminal_status.png
+++ b/doc/user/project/web_ide/img/terminal_status.png
Binary files differ
diff --git a/doc/workflow/img/notification_global_settings.png b/doc/workflow/img/notification_global_settings.png
index 72f7418f1f8..699f726c442 100644
--- a/doc/workflow/img/notification_global_settings.png
+++ b/doc/workflow/img/notification_global_settings.png
Binary files differ
diff --git a/lib/gitlab/ci/build/prerequisite/kubernetes_namespace.rb b/lib/gitlab/ci/build/prerequisite/kubernetes_namespace.rb
index e6e0aaab60b..6ab4fca3854 100644
--- a/lib/gitlab/ci/build/prerequisite/kubernetes_namespace.rb
+++ b/lib/gitlab/ci/build/prerequisite/kubernetes_namespace.rb
@@ -8,31 +8,51 @@ module Gitlab
def unmet?
deployment_cluster.present? &&
deployment_cluster.managed? &&
- (kubernetes_namespace.new_record? || kubernetes_namespace.service_account_token.blank?)
+ missing_namespace?
end
def complete!
return unless unmet?
- create_or_update_namespace
+ create_namespace
end
private
+ def missing_namespace?
+ kubernetes_namespace.nil? || kubernetes_namespace.service_account_token.blank?
+ end
+
def deployment_cluster
build.deployment&.cluster
end
+ def environment
+ build.deployment.environment
+ end
+
def kubernetes_namespace
strong_memoize(:kubernetes_namespace) do
- deployment_cluster.find_or_initialize_kubernetes_namespace_for_project(build.project)
+ Clusters::KubernetesNamespaceFinder.new(
+ deployment_cluster,
+ project: environment.project,
+ environment_slug: environment.slug,
+ allow_blank_token: true
+ ).execute
end
end
- def create_or_update_namespace
+ def create_namespace
Clusters::Gcp::Kubernetes::CreateOrUpdateNamespaceService.new(
cluster: deployment_cluster,
- kubernetes_namespace: kubernetes_namespace
+ kubernetes_namespace: kubernetes_namespace || build_namespace_record
+ ).execute
+ end
+
+ def build_namespace_record
+ Clusters::BuildKubernetesNamespaceService.new(
+ deployment_cluster,
+ environment: environment
).execute
end
end
diff --git a/lib/gitlab/ci/templates/Packer.gitlab-ci.yml b/lib/gitlab/ci/templates/Packer.gitlab-ci.yml
index 83e179f37c3..0a3cf3dcf77 100644
--- a/lib/gitlab/ci/templates/Packer.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Packer.gitlab-ci.yml
@@ -1,5 +1,5 @@
image:
- name: hashicorp/packer:1.0.4
+ name: hashicorp/packer:latest
entrypoint:
- '/usr/bin/env'
- 'PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin'
diff --git a/lib/gitlab/content_security_policy/config_loader.rb b/lib/gitlab/content_security_policy/config_loader.rb
new file mode 100644
index 00000000000..b2f3345d33a
--- /dev/null
+++ b/lib/gitlab/content_security_policy/config_loader.rb
@@ -0,0 +1,43 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module ContentSecurityPolicy
+ class ConfigLoader
+ DIRECTIVES = %w(base_uri child_src connect_src default_src font_src
+ form_action frame_ancestors frame_src img_src manifest_src
+ media_src object_src script_src style_src worker_src).freeze
+
+ def self.default_settings_hash
+ {
+ 'enabled' => false,
+ 'report_only' => false,
+ 'directives' => DIRECTIVES.each_with_object({}) { |directive, hash| hash[directive] = nil }
+ }
+ end
+
+ def initialize(csp_directives)
+ @csp_directives = HashWithIndifferentAccess.new(csp_directives)
+ end
+
+ def load(policy)
+ DIRECTIVES.each do |directive|
+ arguments = arguments_for(directive)
+
+ next unless arguments.present?
+
+ policy.public_send(directive, *arguments) # rubocop:disable GitlabSecurity/PublicSend
+ end
+ end
+
+ private
+
+ def arguments_for(directive)
+ arguments = @csp_directives[directive.to_s]
+
+ return unless arguments.present? && arguments.is_a?(String)
+
+ arguments.strip.split(' ').map(&:strip)
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/highlight.rb b/lib/gitlab/highlight.rb
index 381f1dd4e55..1f49a26f0a2 100644
--- a/lib/gitlab/highlight.rb
+++ b/lib/gitlab/highlight.rb
@@ -6,15 +6,16 @@ module Gitlab
TIMEOUT_FOREGROUND = 3.seconds
MAXIMUM_TEXT_HIGHLIGHT_SIZE = 1.megabyte
- def self.highlight(blob_name, blob_content, language: nil, plain: false)
- new(blob_name, blob_content, language: language)
+ def self.highlight(blob_name, blob_content, since: nil, language: nil, plain: false)
+ new(blob_name, blob_content, since: since, language: language)
.highlight(blob_content, continue: false, plain: plain)
end
attr_reader :blob_name
- def initialize(blob_name, blob_content, language: nil)
+ def initialize(blob_name, blob_content, since: nil, language: nil)
@formatter = Rouge::Formatters::HTMLGitlab
+ @since = since
@language = language
@blob_name = blob_name
@blob_content = blob_content
@@ -53,13 +54,13 @@ module Gitlab
end
def highlight_plain(text)
- @formatter.format(Rouge::Lexers::PlainText.lex(text)).html_safe
+ @formatter.format(Rouge::Lexers::PlainText.lex(text), since: @since).html_safe
end
def highlight_rich(text, continue: true)
tag = lexer.tag
tokens = lexer.lex(text, continue: continue)
- Timeout.timeout(timeout_time) { @formatter.format(tokens, tag: tag).html_safe }
+ Timeout.timeout(timeout_time) { @formatter.format(tokens, tag: tag, since: @since).html_safe }
rescue Timeout::Error => e
Gitlab::Sentry.track_exception(e)
highlight_plain(text)
diff --git a/lib/gitlab/import_export/import_export.yml b/lib/gitlab/import_export/import_export.yml
index 01437c67fa9..f3888857bb6 100644
--- a/lib/gitlab/import_export/import_export.yml
+++ b/lib/gitlab/import_export/import_export.yml
@@ -80,6 +80,10 @@ project_tree:
- :ci_cd_settings
- :error_tracking_setting
- :metrics_setting
+ - boards:
+ - lists:
+ - label:
+ - :priorities
# Only include the following attributes for the models specified.
included_attributes:
@@ -216,6 +220,8 @@ methods:
- :action
project_badges:
- :type
+ lists:
+ - :list_type
# EE specific relationships and settings to include. All of this will be merged
# into the previous structures if EE is used.
diff --git a/lib/gitlab/kubernetes/default_namespace.rb b/lib/gitlab/kubernetes/default_namespace.rb
new file mode 100644
index 00000000000..c95362b024b
--- /dev/null
+++ b/lib/gitlab/kubernetes/default_namespace.rb
@@ -0,0 +1,58 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Kubernetes
+ class DefaultNamespace
+ attr_reader :cluster, :project
+
+ delegate :platform_kubernetes, to: :cluster
+
+ ##
+ # Ideally we would just use an environment record here instead of
+ # passing a project and name/slug separately, but we need to be able
+ # to look up namespaces before the environment has been persisted.
+ def initialize(cluster, project:)
+ @cluster = cluster
+ @project = project
+ end
+
+ def from_environment_name(name)
+ from_environment_slug(generate_slug(name))
+ end
+
+ def from_environment_slug(slug)
+ default_platform_namespace(slug) || default_project_namespace(slug)
+ end
+
+ private
+
+ def default_platform_namespace(slug)
+ return unless platform_kubernetes&.namespace.present?
+
+ if cluster.managed? && cluster.namespace_per_environment?
+ "#{platform_kubernetes.namespace}-#{slug}"
+ else
+ platform_kubernetes.namespace
+ end
+ end
+
+ def default_project_namespace(slug)
+ namespace_slug = "#{project.path}-#{project.id}".downcase
+
+ if cluster.namespace_per_environment?
+ namespace_slug += "-#{slug}"
+ end
+
+ Gitlab::NamespaceSanitizer.sanitize(namespace_slug)
+ end
+
+ ##
+ # Environment slug can be predicted given an environment
+ # name, so even if the environment isn't persisted yet we
+ # still know what to look for.
+ def generate_slug(name)
+ Gitlab::Slug::Environment.new(name).generate
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/prometheus/query_variables.rb b/lib/gitlab/prometheus/query_variables.rb
index 9cc21129547..ba2d33ee1c1 100644
--- a/lib/gitlab/prometheus/query_variables.rb
+++ b/lib/gitlab/prometheus/query_variables.rb
@@ -4,12 +4,9 @@ module Gitlab
module Prometheus
module QueryVariables
def self.call(environment)
- deployment_platform = environment.deployment_platform
- namespace = deployment_platform&.kubernetes_namespace_for(environment.project) || ''
-
{
ci_environment_slug: environment.slug,
- kube_namespace: namespace,
+ kube_namespace: environment.deployment_namespace || '',
environment_filter: %{container_name!="POD",environment="#{environment.slug}"}
}
end
diff --git a/lib/gitlab/prometheus_client.rb b/lib/gitlab/prometheus_client.rb
index f13156f898e..9fefffefcde 100644
--- a/lib/gitlab/prometheus_client.rb
+++ b/lib/gitlab/prometheus_client.rb
@@ -3,6 +3,7 @@
module Gitlab
# Helper methods to interact with Prometheus network services & resources
class PrometheusClient
+ include Gitlab::Utils::StrongMemoize
Error = Class.new(StandardError)
QueryError = Class.new(Gitlab::PrometheusClient::Error)
@@ -14,10 +15,17 @@ module Gitlab
# Minimal value of the `step` parameter for `query_range` in seconds.
QUERY_RANGE_MIN_STEP = 60
- attr_reader :rest_client, :headers
+ # Key translation between RestClient and Gitlab::HTTP (HTTParty)
+ RESTCLIENT_GITLAB_HTTP_KEYMAP = {
+ ssl_cert_store: :cert_store
+ }.freeze
- def initialize(rest_client)
- @rest_client = rest_client
+ attr_reader :api_url, :options
+ private :api_url, :options
+
+ def initialize(api_url, options = {})
+ @api_url = api_url.chomp('/')
+ @options = options
end
def ping
@@ -27,14 +35,10 @@ module Gitlab
def proxy(type, args)
path = api_path(type)
get(path, args)
- rescue RestClient::ExceptionWithResponse => ex
- if ex.response
- ex.response
- else
- raise PrometheusClient::Error, "Network connection error"
- end
- rescue RestClient::Exception
- raise PrometheusClient::Error, "Network connection error"
+ rescue Gitlab::HTTP::ResponseError => ex
+ raise PrometheusClient::Error, "Network connection error" unless ex.response && ex.response.try(:code)
+
+ handle_response(ex.response)
end
def query(query, time: Time.now)
@@ -78,50 +82,58 @@ module Gitlab
private
def api_path(type)
- ['api', 'v1', type].join('/')
+ [api_url, 'api', 'v1', type].join('/')
end
def json_api_get(type, args = {})
path = api_path(type)
response = get(path, args)
handle_response(response)
- rescue RestClient::ExceptionWithResponse => ex
- if ex.response
- handle_exception_response(ex.response)
- else
- raise PrometheusClient::Error, "Network connection error"
+ rescue Gitlab::HTTP::ResponseError => ex
+ raise PrometheusClient::Error, "Network connection error" unless ex.response && ex.response.try(:code)
+
+ handle_response(ex.response)
+ end
+
+ def gitlab_http_key(key)
+ RESTCLIENT_GITLAB_HTTP_KEYMAP[key] || key
+ end
+
+ def mapped_options
+ options.keys.map { |k| [gitlab_http_key(k), options[k]] }.to_h
+ end
+
+ def http_options
+ strong_memoize(:http_options) do
+ { follow_redirects: false }.merge(mapped_options)
end
- rescue RestClient::Exception
- raise PrometheusClient::Error, "Network connection error"
end
def get(path, args)
- rest_client[path].get(params: args)
+ Gitlab::HTTP.get(path, { query: args }.merge(http_options) )
rescue SocketError
- raise PrometheusClient::Error, "Can't connect to #{rest_client.url}"
+ raise PrometheusClient::Error, "Can't connect to #{api_url}"
rescue OpenSSL::SSL::SSLError
- raise PrometheusClient::Error, "#{rest_client.url} contains invalid SSL data"
+ raise PrometheusClient::Error, "#{api_url} contains invalid SSL data"
rescue Errno::ECONNREFUSED
raise PrometheusClient::Error, 'Connection refused'
end
def handle_response(response)
- json_data = parse_json(response.body)
- if response.code == 200 && json_data['status'] == 'success'
- json_data['data'] || {}
- else
- raise PrometheusClient::Error, "#{response.code} - #{response.body}"
- end
- end
+ response_code = response.try(:code)
+ response_body = response.try(:body)
+
+ raise PrometheusClient::Error, "#{response_code} - #{response_body}" unless response_code
+
+ json_data = parse_json(response_body) if [200, 400].include?(response_code)
- def handle_exception_response(response)
- if response.code == 200 && response['status'] == 'success'
- response['data'] || {}
- elsif response.code == 400
- json_data = parse_json(response.body)
+ case response_code
+ when 200
+ json_data['data'] if response['status'] == 'success'
+ when 400
raise PrometheusClient::QueryError, json_data['error'] || 'Bad data received'
else
- raise PrometheusClient::Error, "#{response.code} - #{response.body}"
+ raise PrometheusClient::Error, "#{response_code} - #{response_body}"
end
end
diff --git a/lib/rouge/formatters/html_gitlab.rb b/lib/rouge/formatters/html_gitlab.rb
index e2a7d3ef5ba..0d4ac504428 100644
--- a/lib/rouge/formatters/html_gitlab.rb
+++ b/lib/rouge/formatters/html_gitlab.rb
@@ -8,8 +8,8 @@ module Rouge
# Creates a new <tt>Rouge::Formatter::HTMLGitlab</tt> instance.
#
# [+tag+] The tag (language) of the lexer used to generate the formatted tokens
- def initialize(tag: nil)
- @line_number = 1
+ def initialize(tag: nil, since: nil)
+ @line_number = since || 1
@tag = tag
end
diff --git a/lib/sentry/client.rb b/lib/sentry/client.rb
index 4022e8ff946..07cca1c8d1e 100644
--- a/lib/sentry/client.rb
+++ b/lib/sentry/client.rb
@@ -67,7 +67,7 @@ module Sentry
def handle_request_exceptions
yield
- rescue HTTParty::Error => e
+ rescue Gitlab::HTTP::Error => e
Gitlab::Sentry.track_acceptable_exception(e)
raise_error 'Error when connecting to Sentry'
rescue Net::OpenTimeout
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 8cf70014256..86317dd887f 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -900,6 +900,9 @@ msgstr ""
msgid "After a successful password update, you will be redirected to the login page where you can log in with your new password."
msgstr ""
+msgid "Alerts"
+msgstr ""
+
msgid "All"
msgstr ""
@@ -6868,6 +6871,9 @@ msgstr ""
msgid "More"
msgstr ""
+msgid "More actions"
+msgstr ""
+
msgid "More information"
msgstr ""
diff --git a/package.json b/package.json
index 4ff99f29e24..c368cf7c8e4 100644
--- a/package.json
+++ b/package.json
@@ -176,14 +176,14 @@
"jest-util": "^24.0.0",
"jsdoc": "^3.5.5",
"jsdoc-vue": "^1.0.0",
- "karma": "^3.0.0",
- "karma-chrome-launcher": "^2.2.0",
- "karma-coverage-istanbul-reporter": "^2.0.4",
+ "karma": "^4.2.0",
+ "karma-chrome-launcher": "^3.0.0",
+ "karma-coverage-istanbul-reporter": "^2.1.0",
"karma-jasmine": "^1.1.2",
"karma-junit-reporter": "^1.2.0",
"karma-mocha-reporter": "^2.2.5",
"karma-sourcemap-loader": "^0.3.7",
- "karma-webpack": "^4.0.0-beta.0",
+ "karma-webpack": "^4.0.2",
"md5": "^2.2.1",
"node-sass": "^4.12.0",
"nodemon": "^1.18.9",
diff --git a/qa/qa/runtime/env.rb b/qa/qa/runtime/env.rb
index 4e5610d69b7..b184eeb1701 100644
--- a/qa/qa/runtime/env.rb
+++ b/qa/qa/runtime/env.rb
@@ -182,7 +182,7 @@ module QA
end
def gcloud_num_nodes
- ENV.fetch('GCLOUD_NUM_NODES', 3)
+ ENV.fetch('GCLOUD_NUM_NODES', 1)
end
def has_gcloud_credentials?
diff --git a/spec/controllers/metrics_controller_spec.rb b/spec/controllers/metrics_controller_spec.rb
index 84027119491..7fb3578cd0a 100644
--- a/spec/controllers/metrics_controller_spec.rb
+++ b/spec/controllers/metrics_controller_spec.rb
@@ -5,12 +5,19 @@ require 'spec_helper'
describe MetricsController do
include StubENV
- let(:metrics_multiproc_dir) { Dir.mktmpdir }
+ let(:metrics_multiproc_dir) { @metrics_multiproc_dir }
let(:whitelisted_ip) { '127.0.0.1' }
let(:whitelisted_ip_range) { '10.0.0.0/24' }
let(:ip_in_whitelisted_range) { '10.0.0.1' }
let(:not_whitelisted_ip) { '10.0.1.1' }
+ around do |example|
+ Dir.mktmpdir do |path|
+ @metrics_multiproc_dir = path
+ example.run
+ end
+ end
+
before do
stub_env('IN_MEMORY_APPLICATION_SETTINGS', 'false')
allow(Prometheus::Client.configuration).to receive(:multiprocess_files_dir).and_return(metrics_multiproc_dir)
diff --git a/spec/controllers/projects/serverless/functions_controller_spec.rb b/spec/controllers/projects/serverless/functions_controller_spec.rb
index 18c594acae0..9f1ef3a4be8 100644
--- a/spec/controllers/projects/serverless/functions_controller_spec.rb
+++ b/spec/controllers/projects/serverless/functions_controller_spec.rb
@@ -10,12 +10,16 @@ describe Projects::Serverless::FunctionsController do
let(:cluster) { create(:cluster, :project, :provided_by_gcp) }
let(:service) { cluster.platform_kubernetes }
let(:project) { cluster.project }
+ let(:environment) { create(:environment, project: project) }
+ let!(:deployment) { create(:deployment, :success, environment: environment, cluster: cluster) }
+ let(:knative_services_finder) { environment.knative_services_finder }
let(:namespace) do
create(:cluster_kubernetes_namespace,
cluster: cluster,
cluster_project: cluster.cluster_project,
- project: cluster.cluster_project.project)
+ project: cluster.cluster_project.project,
+ environment: environment)
end
before do
@@ -47,12 +51,11 @@ describe Projects::Serverless::FunctionsController do
end
context 'when cache is ready' do
- let(:knative_services_finder) { project.clusters.first.knative_services_finder(project) }
let(:knative_state) { true }
before do
- allow_any_instance_of(Clusters::Cluster)
- .to receive(:knative_services_finder)
+ allow(Clusters::KnativeServicesFinder)
+ .to receive(:new)
.and_return(knative_services_finder)
synchronous_reactive_cache(knative_services_finder)
stub_kubeclient_service_pods(
@@ -107,12 +110,12 @@ describe Projects::Serverless::FunctionsController do
context 'valid data', :use_clean_rails_memory_store_caching do
before do
stub_kubeclient_service_pods
- stub_reactive_cache(cluster.knative_services_finder(project),
+ stub_reactive_cache(knative_services_finder,
{
services: kube_knative_services_body(namespace: namespace.namespace, name: cluster.project.name)["items"],
pods: kube_knative_pods_body(cluster.project.name, namespace.namespace)["items"]
},
- *cluster.knative_services_finder(project).cache_args)
+ *knative_services_finder.cache_args)
end
it 'has a valid function name' do
@@ -140,12 +143,12 @@ describe Projects::Serverless::FunctionsController do
describe 'GET #index with data', :use_clean_rails_memory_store_caching do
before do
stub_kubeclient_service_pods
- stub_reactive_cache(cluster.knative_services_finder(project),
+ stub_reactive_cache(knative_services_finder,
{
services: kube_knative_services_body(namespace: namespace.namespace, name: cluster.project.name)["items"],
pods: kube_knative_pods_body(cluster.project.name, namespace.namespace)["items"]
},
- *cluster.knative_services_finder(project).cache_args)
+ *knative_services_finder.cache_args)
end
it 'has data' do
diff --git a/spec/factories/clusters/clusters.rb b/spec/factories/clusters/clusters.rb
index b0d14b672f4..d294e6d055e 100644
--- a/spec/factories/clusters/clusters.rb
+++ b/spec/factories/clusters/clusters.rb
@@ -6,6 +6,7 @@ FactoryBot.define do
name 'test-cluster'
cluster_type :project_type
managed true
+ namespace_per_environment true
factory :cluster_for_group, traits: [:provided_by_gcp, :group]
@@ -29,6 +30,10 @@ FactoryBot.define do
end
end
+ trait :namespace_per_environment_disabled do
+ namespace_per_environment false
+ end
+
trait :provided_by_user do
provider_type :user
platform_type :kubernetes
diff --git a/spec/factories/clusters/kubernetes_namespaces.rb b/spec/factories/clusters/kubernetes_namespaces.rb
index 042be7b4c4a..8d6ad1b9f79 100644
--- a/spec/factories/clusters/kubernetes_namespaces.rb
+++ b/spec/factories/clusters/kubernetes_namespaces.rb
@@ -5,12 +5,21 @@ FactoryBot.define do
association :cluster, :project, :provided_by_gcp
after(:build) do |kubernetes_namespace|
- if kubernetes_namespace.cluster.project_type?
- cluster_project = kubernetes_namespace.cluster.cluster_project
+ cluster = kubernetes_namespace.cluster
+
+ if cluster.project_type?
+ cluster_project = cluster.cluster_project
kubernetes_namespace.project = cluster_project.project
kubernetes_namespace.cluster_project = cluster_project
end
+
+ kubernetes_namespace.namespace ||=
+ Gitlab::Kubernetes::DefaultNamespace.new(
+ cluster,
+ project: kubernetes_namespace.project
+ ).from_environment_slug(kubernetes_namespace.environment&.slug)
+ kubernetes_namespace.service_account_name ||= "#{kubernetes_namespace.namespace}-service-account"
end
trait :with_token do
diff --git a/spec/features/projects/serverless/functions_spec.rb b/spec/features/projects/serverless/functions_spec.rb
index 9865dbbfb3c..e82e5b81021 100644
--- a/spec/features/projects/serverless/functions_spec.rb
+++ b/spec/features/projects/serverless/functions_spec.rb
@@ -39,17 +39,19 @@ describe 'Functions', :js do
let(:cluster) { create(:cluster, :project, :provided_by_gcp) }
let(:service) { cluster.platform_kubernetes }
let(:project) { cluster.project }
- let(:knative_services_finder) { project.clusters.first.knative_services_finder(project) }
+ let(:environment) { create(:environment, project: project) }
+ let!(:deployment) { create(:deployment, :success, cluster: cluster, environment: environment) }
+ let(:knative_services_finder) { environment.knative_services_finder }
let(:namespace) do
create(:cluster_kubernetes_namespace,
cluster: cluster,
- cluster_project: cluster.cluster_project,
- project: cluster.cluster_project.project)
+ project: cluster.cluster_project.project,
+ environment: environment)
end
before do
- allow_any_instance_of(Clusters::Cluster)
- .to receive(:knative_services_finder)
+ allow(Clusters::KnativeServicesFinder)
+ .to receive(:new)
.and_return(knative_services_finder)
synchronous_reactive_cache(knative_services_finder)
stub_kubeclient_knative_services(stub_get_services_options)
diff --git a/spec/features/projects/services/user_activates_issue_tracker_spec.rb b/spec/features/projects/services/user_activates_issue_tracker_spec.rb
index 5803500a4d2..5f3bb794b48 100644
--- a/spec/features/projects/services/user_activates_issue_tracker_spec.rb
+++ b/spec/features/projects/services/user_activates_issue_tracker_spec.rb
@@ -61,7 +61,7 @@ describe 'User activates issue tracker', :js do
context 'when the connection test fails' do
it 'activates the service' do
- stub_request(:head, url).to_raise(HTTParty::Error)
+ stub_request(:head, url).to_raise(Gitlab::HTTP::Error)
click_link(tracker)
diff --git a/spec/features/projects/services/user_activates_youtrack_spec.rb b/spec/features/projects/services/user_activates_youtrack_spec.rb
index 67f0aa214e2..8fdeddfdfb4 100644
--- a/spec/features/projects/services/user_activates_youtrack_spec.rb
+++ b/spec/features/projects/services/user_activates_youtrack_spec.rb
@@ -48,7 +48,7 @@ describe 'User activates issue tracker', :js do
context 'when the connection test fails' do
it 'activates the service' do
- stub_request(:head, url).to_raise(HTTParty::Error)
+ stub_request(:head, url).to_raise(Gitlab::HTTP::Error)
click_link(tracker)
fill_form
diff --git a/spec/finders/clusters/knative_services_finder_spec.rb b/spec/finders/clusters/knative_services_finder_spec.rb
index b731c2bd6bf..159724b3c1f 100644
--- a/spec/finders/clusters/knative_services_finder_spec.rb
+++ b/spec/finders/clusters/knative_services_finder_spec.rb
@@ -7,15 +7,19 @@ describe Clusters::KnativeServicesFinder do
include ReactiveCachingHelpers
let(:cluster) { create(:cluster, :project, :provided_by_gcp) }
- let(:service) { cluster.platform_kubernetes }
+ let(:service) { environment.deployment_platform }
let(:project) { cluster.cluster_project.project }
+ let(:environment) { create(:environment, project: project) }
+ let!(:deployment) { create(:deployment, :success, environment: environment, cluster: cluster) }
let(:namespace) do
create(:cluster_kubernetes_namespace,
cluster: cluster,
- cluster_project: cluster.cluster_project,
- project: project)
+ project: project,
+ environment: environment)
end
+ let(:finder) { described_class.new(cluster, environment) }
+
before do
stub_kubeclient_knative_services(namespace: namespace.namespace)
stub_kubeclient_service_pods(
@@ -35,7 +39,7 @@ describe Clusters::KnativeServicesFinder do
context 'when using synchronous reactive cache' do
before do
- synchronous_reactive_cache(cluster.knative_services_finder(project))
+ synchronous_reactive_cache(finder)
end
context 'when there are functions for cluster namespace' do
@@ -60,21 +64,21 @@ describe Clusters::KnativeServicesFinder do
end
describe '#service_pod_details' do
- subject { cluster.knative_services_finder(project).service_pod_details(project.name) }
+ subject { finder.service_pod_details(project.name) }
it_behaves_like 'a cached data'
end
describe '#services' do
- subject { cluster.knative_services_finder(project).services }
+ subject { finder.services }
it_behaves_like 'a cached data'
end
describe '#knative_detected' do
- subject { cluster.knative_services_finder(project).knative_detected }
+ subject { finder.knative_detected }
before do
- synchronous_reactive_cache(cluster.knative_services_finder(project))
+ synchronous_reactive_cache(finder)
end
context 'when knative is installed' do
@@ -85,7 +89,7 @@ describe Clusters::KnativeServicesFinder do
it { is_expected.to be_truthy }
it "discovers knative installation" do
expect { subject }
- .to change { cluster.kubeclient.knative_client.discovered }
+ .to change { finder.cluster.kubeclient.knative_client.discovered }
.from(false)
.to(true)
end
diff --git a/spec/finders/clusters/kubernetes_namespace_finder_spec.rb b/spec/finders/clusters/kubernetes_namespace_finder_spec.rb
new file mode 100644
index 00000000000..8beba0b99a4
--- /dev/null
+++ b/spec/finders/clusters/kubernetes_namespace_finder_spec.rb
@@ -0,0 +1,110 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Clusters::KubernetesNamespaceFinder do
+ let(:finder) do
+ described_class.new(
+ cluster,
+ project: project,
+ environment_slug: 'production',
+ allow_blank_token: allow_blank_token
+ )
+ end
+
+ def create_namespace(environment, with_token: true)
+ create(:cluster_kubernetes_namespace,
+ (with_token ? :with_token : :without_token),
+ cluster: cluster,
+ project: project,
+ environment: environment
+ )
+ end
+
+ describe '#execute' do
+ let(:production) { create(:environment, project: project, slug: 'production') }
+ let(:staging) { create(:environment, project: project, slug: 'staging') }
+
+ let(:cluster) { create(:cluster, :group, :provided_by_user) }
+ let(:project) { create(:project) }
+ let(:allow_blank_token) { false }
+
+ subject { finder.execute }
+
+ before do
+ allow(cluster).to receive(:namespace_per_environment?).and_return(namespace_per_environment)
+ end
+
+ context 'cluster supports separate namespaces per environment' do
+ let(:namespace_per_environment) { true }
+
+ context 'no persisted namespace is present' do
+ it { is_expected.to be_nil }
+ end
+
+ context 'a namespace with an environment is present' do
+ context 'environment matches' do
+ let!(:namespace_with_environment) { create_namespace(production) }
+
+ it { is_expected.to eq namespace_with_environment }
+
+ context 'project cluster' do
+ let(:cluster) { create(:cluster, :project, :provided_by_user, projects: [project]) }
+
+ it { is_expected.to eq namespace_with_environment }
+ end
+
+ context 'service account token is blank' do
+ let!(:namespace_with_environment) { create_namespace(production, with_token: false) }
+
+ it { is_expected.to be_nil }
+
+ context 'allow_blank_token is true' do
+ let(:allow_blank_token) { true }
+
+ it { is_expected.to eq namespace_with_environment }
+ end
+ end
+ end
+
+ context 'environment does not match' do
+ let!(:namespace_with_environment) { create_namespace(staging) }
+
+ it { is_expected.to be_nil }
+ end
+ end
+ end
+
+ context 'cluster does not support separate namespaces per environment' do
+ let(:namespace_per_environment) { false }
+
+ context 'no persisted namespace is present' do
+ it { is_expected.to be_nil }
+ end
+
+ context 'a legacy namespace with no environment is present' do
+ let!(:legacy_namespace) { create_namespace(nil) }
+
+ it { is_expected.to eq legacy_namespace }
+
+ context 'project cluster' do
+ let(:cluster) { create(:cluster, :project, :provided_by_user, projects: [project]) }
+
+ it { is_expected.to eq legacy_namespace }
+ end
+
+ context 'service account token is blank' do
+ let!(:legacy_namespace) { create_namespace(nil, with_token: false) }
+
+ it { is_expected.to be_nil }
+
+ context 'allow_blank_token is true' do
+ let(:allow_blank_token) { true }
+
+ it { is_expected.to eq legacy_namespace }
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/spec/finders/projects/serverless/functions_finder_spec.rb b/spec/finders/projects/serverless/functions_finder_spec.rb
index 8aea45b457c..589e4000d46 100644
--- a/spec/finders/projects/serverless/functions_finder_spec.rb
+++ b/spec/finders/projects/serverless/functions_finder_spec.rb
@@ -11,12 +11,15 @@ describe Projects::Serverless::FunctionsFinder do
let(:cluster) { create(:cluster, :project, :provided_by_gcp) }
let(:service) { cluster.platform_kubernetes }
let(:project) { cluster.project }
+ let(:environment) { create(:environment, project: project) }
+ let!(:deployment) { create(:deployment, :success, environment: environment, cluster: cluster) }
+ let(:knative_services_finder) { environment.knative_services_finder }
let(:namespace) do
create(:cluster_kubernetes_namespace,
cluster: cluster,
- cluster_project: cluster.cluster_project,
- project: cluster.cluster_project.project)
+ project: project,
+ environment: environment)
end
before do
@@ -29,11 +32,9 @@ describe Projects::Serverless::FunctionsFinder do
end
context 'when reactive_caching has finished' do
- let(:knative_services_finder) { project.clusters.first.knative_services_finder(project) }
-
before do
- allow_any_instance_of(Clusters::Cluster)
- .to receive(:knative_services_finder)
+ allow(Clusters::KnativeServicesFinder)
+ .to receive(:new)
.and_return(knative_services_finder)
synchronous_reactive_cache(knative_services_finder)
end
@@ -47,8 +48,6 @@ describe Projects::Serverless::FunctionsFinder do
end
context 'reactive_caching is finished and knative is installed' do
- let(:knative_services_finder) { project.clusters.first.knative_services_finder(project) }
-
it 'returns true' do
stub_kubeclient_knative_services(namespace: namespace.namespace)
stub_kubeclient_service_pods(nil, namespace: namespace.namespace)
@@ -74,24 +73,24 @@ describe Projects::Serverless::FunctionsFinder do
it 'there are functions', :use_clean_rails_memory_store_caching do
stub_kubeclient_service_pods
- stub_reactive_cache(cluster.knative_services_finder(project),
+ stub_reactive_cache(knative_services_finder,
{
services: kube_knative_services_body(namespace: namespace.namespace, name: cluster.project.name)["items"],
pods: kube_knative_pods_body(cluster.project.name, namespace.namespace)["items"]
},
- *cluster.knative_services_finder(project).cache_args)
+ *knative_services_finder.cache_args)
expect(finder.execute).not_to be_empty
end
it 'has a function', :use_clean_rails_memory_store_caching do
stub_kubeclient_service_pods
- stub_reactive_cache(cluster.knative_services_finder(project),
+ stub_reactive_cache(knative_services_finder,
{
services: kube_knative_services_body(namespace: namespace.namespace, name: cluster.project.name)["items"],
pods: kube_knative_pods_body(cluster.project.name, namespace.namespace)["items"]
},
- *cluster.knative_services_finder(project).cache_args)
+ *knative_services_finder.cache_args)
result = finder.service(cluster.environment_scope, cluster.project.name)
expect(result).not_to be_empty
@@ -109,7 +108,7 @@ describe Projects::Serverless::FunctionsFinder do
let(:finder) { described_class.new(project) }
before do
- allow(finder).to receive(:prometheus_adapter).and_return(prometheus_adapter)
+ allow(Prometheus::AdapterService).to receive(:new).and_return(double(prometheus_adapter: prometheus_adapter))
allow(prometheus_adapter).to receive(:query).and_return(prometheus_empty_body('matrix'))
end
diff --git a/spec/frontend/test_setup.js b/spec/frontend/test_setup.js
index e4d62b044ca..8b6f7802b15 100644
--- a/spec/frontend/test_setup.js
+++ b/spec/frontend/test_setup.js
@@ -75,3 +75,18 @@ global.MutationObserver = () => ({
disconnect: () => {},
observe: () => {},
});
+
+Object.assign(global, {
+ requestIdleCallback(cb) {
+ const start = Date.now();
+ return setTimeout(() => {
+ cb({
+ didTimeout: false,
+ timeRemaining: () => Math.max(0, 50 - (Date.now() - start)),
+ });
+ });
+ },
+ cancelIdleCallback(id) {
+ clearTimeout(id);
+ },
+});
diff --git a/spec/helpers/dashboard_helper_spec.rb b/spec/helpers/dashboard_helper_spec.rb
index 49e23366355..059ae128d93 100644
--- a/spec/helpers/dashboard_helper_spec.rb
+++ b/spec/helpers/dashboard_helper_spec.rb
@@ -12,7 +12,7 @@ describe DashboardHelper do
it 'has all the expected links by default' do
menu_items = [:projects, :groups, :activity, :milestones, :snippets]
- expect(helper.dashboard_nav_links).to contain_exactly(*menu_items)
+ expect(helper.dashboard_nav_links).to include(*menu_items)
end
it 'does not contain cross project elements when the user cannot read cross project' do
diff --git a/spec/javascripts/ci_variable_list/ajax_variable_list_spec.js b/spec/javascripts/ci_variable_list/ajax_variable_list_spec.js
index e6a969bd855..b2fe315f6c6 100644
--- a/spec/javascripts/ci_variable_list/ajax_variable_list_spec.js
+++ b/spec/javascripts/ci_variable_list/ajax_variable_list_spec.js
@@ -224,7 +224,7 @@ describe('AjaxFormVariableList', () => {
describe('maskableRegex', () => {
it('takes in the regex provided by the data attribute', () => {
- expect(container.dataset.maskableRegex).toBe('^[a-zA-Z0-9_+=/-]{8,}$');
+ expect(container.dataset.maskableRegex).toBe('^[a-zA-Z0-9_+=/@:-]{8,}$');
expect(ajaxVariableList.maskableRegex).toBe(container.dataset.maskableRegex);
});
});
diff --git a/spec/javascripts/ci_variable_list/ci_variable_list_spec.js b/spec/javascripts/ci_variable_list/ci_variable_list_spec.js
index 064113e879a..c8d6f789ed0 100644
--- a/spec/javascripts/ci_variable_list/ci_variable_list_spec.js
+++ b/spec/javascripts/ci_variable_list/ci_variable_list_spec.js
@@ -162,7 +162,7 @@ describe('VariableList', () => {
});
it('has a regex provided via a data attribute', () => {
- expect($wrapper.attr('data-maskable-regex')).toBe('^[a-zA-Z0-9_+=/-]{8,}$');
+ expect($wrapper.attr('data-maskable-regex')).toBe('^[a-zA-Z0-9_+=/@:-]{8,}$');
});
it('allows values that are 8 characters long', done => {
diff --git a/spec/javascripts/pipelines/pipelines_actions_spec.js b/spec/javascripts/pipelines/pipelines_actions_spec.js
index a7dcd532f4f..953a42b9d15 100644
--- a/spec/javascripts/pipelines/pipelines_actions_spec.js
+++ b/spec/javascripts/pipelines/pipelines_actions_spec.js
@@ -1,5 +1,6 @@
import Vue from 'vue';
-import eventHub from '~/pipelines/event_hub';
+import MockAdapter from 'axios-mock-adapter';
+import axios from '~/lib/utils/axios_utils';
import PipelinesActions from '~/pipelines/components/pipelines_actions.vue';
import mountComponent from 'spec/helpers/vue_mount_component_helper';
import { TEST_HOST } from 'spec/test_constants';
@@ -7,9 +8,15 @@ import { TEST_HOST } from 'spec/test_constants';
describe('Pipelines Actions dropdown', () => {
const Component = Vue.extend(PipelinesActions);
let vm;
+ let mock;
afterEach(() => {
vm.$destroy();
+ mock.restore();
+ });
+
+ beforeEach(() => {
+ mock = new MockAdapter(axios);
});
describe('manual actions', () => {
@@ -40,6 +47,22 @@ describe('Pipelines Actions dropdown', () => {
expect(dropdownItem).toBeDisabled();
});
+
+ describe('on click', () => {
+ it('makes a request and toggles the loading state', done => {
+ mock.onPost(actions.path).reply(200);
+
+ vm.$el.querySelector('.dropdown-menu li button').click();
+
+ expect(vm.isLoading).toEqual(true);
+
+ setTimeout(() => {
+ expect(vm.isLoading).toEqual(false);
+
+ done();
+ });
+ });
+ });
});
describe('scheduled jobs', () => {
@@ -71,26 +94,27 @@ describe('Pipelines Actions dropdown', () => {
.catch(done.fail);
});
- it('emits postAction event after confirming', () => {
- const emitSpy = jasmine.createSpy('emit');
- eventHub.$on('postAction', emitSpy);
+ it('makes post request after confirming', done => {
+ mock.onPost(scheduledJobAction.path).reply(200);
spyOn(window, 'confirm').and.callFake(() => true);
findDropdownItem(scheduledJobAction).click();
expect(window.confirm).toHaveBeenCalled();
- expect(emitSpy).toHaveBeenCalledWith(scheduledJobAction.path);
+ setTimeout(() => {
+ expect(mock.history.post.length).toBe(1);
+ done();
+ });
});
- it('does not emit postAction event if confirmation is cancelled', () => {
- const emitSpy = jasmine.createSpy('emit');
- eventHub.$on('postAction', emitSpy);
+ it('does not make post request if confirmation is cancelled', () => {
+ mock.onPost(scheduledJobAction.path).reply(200);
spyOn(window, 'confirm').and.callFake(() => false);
findDropdownItem(scheduledJobAction).click();
expect(window.confirm).toHaveBeenCalled();
- expect(emitSpy).not.toHaveBeenCalled();
+ expect(mock.history.post.length).toBe(0);
});
it('displays the remaining time in the dropdown', () => {
diff --git a/spec/lib/gitlab/bitbucket_import/importer_spec.rb b/spec/lib/gitlab/bitbucket_import/importer_spec.rb
index 62b688d4d3e..280941ff601 100644
--- a/spec/lib/gitlab/bitbucket_import/importer_spec.rb
+++ b/spec/lib/gitlab/bitbucket_import/importer_spec.rb
@@ -173,7 +173,7 @@ describe Gitlab::BitbucketImport::Importer do
context 'when importing a pull request throws an exception' do
before do
allow(pull_request).to receive(:raw).and_return('hello world')
- allow(subject.client).to receive(:pull_request_comments).and_raise(HTTParty::Error)
+ allow(subject.client).to receive(:pull_request_comments).and_raise(Gitlab::HTTP::Error)
end
it 'logs an error without the backtrace' do
diff --git a/spec/lib/gitlab/ci/build/prerequisite/kubernetes_namespace_spec.rb b/spec/lib/gitlab/ci/build/prerequisite/kubernetes_namespace_spec.rb
index d88a2097ba2..775550f2acc 100644
--- a/spec/lib/gitlab/ci/build/prerequisite/kubernetes_namespace_spec.rb
+++ b/spec/lib/gitlab/ci/build/prerequisite/kubernetes_namespace_spec.rb
@@ -3,9 +3,9 @@
require 'spec_helper'
describe Gitlab::Ci::Build::Prerequisite::KubernetesNamespace do
- let(:build) { create(:ci_build) }
-
describe '#unmet?' do
+ let(:build) { create(:ci_build) }
+
subject { described_class.new(build).unmet? }
context 'build has no deployment' do
@@ -18,7 +18,6 @@ describe Gitlab::Ci::Build::Prerequisite::KubernetesNamespace do
context 'build has a deployment' do
let!(:deployment) { create(:deployment, deployable: build, cluster: cluster) }
- let(:cluster) { nil }
context 'and a cluster to deploy to' do
let(:cluster) { create(:cluster, :group) }
@@ -32,12 +31,17 @@ describe Gitlab::Ci::Build::Prerequisite::KubernetesNamespace do
end
context 'and a namespace is already created for this project' do
- let!(:kubernetes_namespace) { create(:cluster_kubernetes_namespace, :with_token, cluster: cluster, project: build.project) }
+ let(:kubernetes_namespace) { instance_double(Clusters::KubernetesNamespace, service_account_token: 'token') }
+
+ before do
+ allow(Clusters::KubernetesNamespaceFinder).to receive(:new)
+ .and_return(double(execute: kubernetes_namespace))
+ end
it { is_expected.to be_falsey }
context 'and the service_account_token is blank' do
- let!(:kubernetes_namespace) { create(:cluster_kubernetes_namespace, :without_token, cluster: cluster, project: build.project) }
+ let(:kubernetes_namespace) { instance_double(Clusters::KubernetesNamespace, service_account_token: nil) }
it { is_expected.to be_truthy }
end
@@ -45,34 +49,79 @@ describe Gitlab::Ci::Build::Prerequisite::KubernetesNamespace do
end
context 'and no cluster to deploy to' do
+ let(:cluster) { nil }
+
it { is_expected.to be_falsey }
end
end
end
describe '#complete!' do
- let!(:deployment) { create(:deployment, deployable: build, cluster: cluster) }
- let(:service) { double(execute: true) }
- let(:cluster) { nil }
+ let(:build) { create(:ci_build) }
+ let(:prerequisite) { described_class.new(build) }
- subject { described_class.new(build).complete! }
+ subject { prerequisite.complete! }
context 'completion is required' do
let(:cluster) { create(:cluster, :group) }
+ let(:deployment) { create(:deployment, cluster: cluster) }
+ let(:service) { double(execute: true) }
+ let(:kubernetes_namespace) { double }
+
+ before do
+ allow(prerequisite).to receive(:unmet?).and_return(true)
+ allow(build).to receive(:deployment).and_return(deployment)
+ end
+
+ context 'kubernetes namespace does not exist' do
+ let(:namespace_builder) { double(execute: kubernetes_namespace)}
- it 'creates a kubernetes namespace' do
- expect(Clusters::Gcp::Kubernetes::CreateOrUpdateNamespaceService)
- .to receive(:new)
- .with(cluster: cluster, kubernetes_namespace: instance_of(Clusters::KubernetesNamespace))
- .and_return(service)
+ before do
+ allow(Clusters::KubernetesNamespaceFinder).to receive(:new)
+ .and_return(double(execute: nil))
+ end
- expect(service).to receive(:execute).once
+ it 'creates a namespace using a new record' do
+ expect(Clusters::BuildKubernetesNamespaceService)
+ .to receive(:new)
+ .with(cluster, environment: deployment.environment)
+ .and_return(namespace_builder)
- subject
+ expect(Clusters::Gcp::Kubernetes::CreateOrUpdateNamespaceService)
+ .to receive(:new)
+ .with(cluster: cluster, kubernetes_namespace: kubernetes_namespace)
+ .and_return(service)
+
+ expect(service).to receive(:execute).once
+
+ subject
+ end
+ end
+
+ context 'kubernetes namespace exists (but has no service_account_token)' do
+ before do
+ allow(Clusters::KubernetesNamespaceFinder).to receive(:new)
+ .and_return(double(execute: kubernetes_namespace))
+ end
+
+ it 'creates a namespace using the tokenless record' do
+ expect(Clusters::BuildKubernetesNamespaceService).not_to receive(:new)
+
+ expect(Clusters::Gcp::Kubernetes::CreateOrUpdateNamespaceService)
+ .to receive(:new)
+ .with(cluster: cluster, kubernetes_namespace: kubernetes_namespace)
+ .and_return(service)
+
+ subject
+ end
end
end
context 'completion is not required' do
+ before do
+ allow(prerequisite).to receive(:unmet?).and_return(false)
+ end
+
it 'does not create a namespace' do
expect(Clusters::Gcp::Kubernetes::CreateOrUpdateNamespaceService).not_to receive(:new)
diff --git a/spec/lib/gitlab/content_security_policy/config_loader_spec.rb b/spec/lib/gitlab/content_security_policy/config_loader_spec.rb
new file mode 100644
index 00000000000..e7670c9d523
--- /dev/null
+++ b/spec/lib/gitlab/content_security_policy/config_loader_spec.rb
@@ -0,0 +1,59 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Gitlab::ContentSecurityPolicy::ConfigLoader do
+ let(:policy) { ActionDispatch::ContentSecurityPolicy.new }
+ let(:csp_config) do
+ {
+ enabled: true,
+ report_only: false,
+ directives: {
+ base_uri: 'http://example.com',
+ child_src: "'self' https://child.example.com",
+ default_src: "'self' https://other.example.com",
+ script_src: "'self' https://script.exammple.com ",
+ worker_src: "data: https://worker.example.com"
+ }
+ }
+ end
+
+ context '.default_settings_hash' do
+ it 'returns empty defaults' do
+ settings = described_class.default_settings_hash
+
+ expect(settings['enabled']).to be_falsey
+ expect(settings['report_only']).to be_falsey
+
+ described_class::DIRECTIVES.each do |directive|
+ expect(settings['directives'].has_key?(directive)).to be_truthy
+ expect(settings['directives'][directive]).to be_nil
+ end
+ end
+ end
+
+ context '#load' do
+ subject { described_class.new(csp_config[:directives]) }
+
+ def expected_config(directive)
+ csp_config[:directives][directive].split(' ').map(&:strip)
+ end
+
+ it 'sets the policy properly' do
+ subject.load(policy)
+
+ expect(policy.directives['base-uri']).to eq([csp_config[:directives][:base_uri]])
+ expect(policy.directives['default-src']).to eq(expected_config(:default_src))
+ expect(policy.directives['child-src']).to eq(expected_config(:child_src))
+ expect(policy.directives['worker-src']).to eq(expected_config(:worker_src))
+ end
+
+ it 'ignores malformed policy statements' do
+ csp_config[:directives][:base_uri] = 123
+
+ subject.load(policy)
+
+ expect(policy.directives['base-uri']).to be_nil
+ end
+ end
+end
diff --git a/spec/lib/gitlab/highlight_spec.rb b/spec/lib/gitlab/highlight_spec.rb
index 4676db6b8d8..a410e4eab45 100644
--- a/spec/lib/gitlab/highlight_spec.rb
+++ b/spec/lib/gitlab/highlight_spec.rb
@@ -62,6 +62,14 @@ describe Gitlab::Highlight do
expect(lines[2].text).to eq(' """')
end
+ context 'since param is present' do
+ it 'highlights with the LC starting from "since" param' do
+ lines = described_class.highlight(file_name, content, since: 2).lines
+
+ expect(lines[0]).to include('LC2')
+ end
+ end
+
context 'diff highlighting' do
let(:file_name) { 'test.diff' }
let(:content) { "+aaa\n+bbb\n- ccc\n ddd\n"}
diff --git a/spec/lib/gitlab/import_export/all_models.yml b/spec/lib/gitlab/import_export/all_models.yml
index 929b6222900..ada8c649ff6 100644
--- a/spec/lib/gitlab/import_export/all_models.yml
+++ b/spec/lib/gitlab/import_export/all_models.yml
@@ -469,3 +469,17 @@ incident_management_setting:
merge_trains:
- project
- merge_request
+boards:
+- group
+- lists
+- destroyable_lists
+- milestone
+- board_labels
+- board_assignee
+- assignee
+- labels
+lists:
+- user
+- milestone
+- board
+- label
diff --git a/spec/lib/gitlab/import_export/project.json b/spec/lib/gitlab/import_export/project.json
index 9e54ca28e58..6d70b147666 100644
--- a/spec/lib/gitlab/import_export/project.json
+++ b/spec/lib/gitlab/import_export/project.json
@@ -7147,5 +7147,65 @@
"link_url": "http://www.example.com",
"image_url": "http://www.example.com"
}
+ ],
+ "boards": [
+ {
+ "id": 29,
+ "project_id": 49,
+ "created_at": "2019-06-06T14:01:06.204Z",
+ "updated_at": "2019-06-06T14:22:37.045Z",
+ "name": "TestBoardABC",
+ "milestone_id": null,
+ "group_id": null,
+ "weight": null,
+ "lists": [
+ {
+ "id": 59,
+ "board_id": 29,
+ "label_id": null,
+ "list_type": "backlog",
+ "position": null,
+ "created_at": "2019-06-06T14:01:06.214Z",
+ "updated_at": "2019-06-06T14:01:06.214Z",
+ "user_id": null,
+ "milestone_id": null
+ },
+ {
+ "id": 61,
+ "board_id": 29,
+ "label_id": 20,
+ "list_type": "label",
+ "position": 0,
+ "created_at": "2019-06-06T14:01:43.197Z",
+ "updated_at": "2019-06-06T14:01:43.197Z",
+ "user_id": null,
+ "milestone_id": null,
+ "label": {
+ "id": 20,
+ "title": "testlabel",
+ "color": "#0033CC",
+ "project_id": 49,
+ "created_at": "2019-06-06T14:01:19.698Z",
+ "updated_at": "2019-06-06T14:01:19.698Z",
+ "template": false,
+ "description": null,
+ "group_id": null,
+ "type": "ProjectLabel",
+ "priorities": []
+ }
+ },
+ {
+ "id": 60,
+ "board_id": 29,
+ "label_id": null,
+ "list_type": "closed",
+ "position": null,
+ "created_at": "2019-06-06T14:01:06.221Z",
+ "updated_at": "2019-06-06T14:01:06.221Z",
+ "user_id": null,
+ "milestone_id": null
+ }
+ ]
+ }
]
}
diff --git a/spec/lib/gitlab/import_export/project_tree_restorer_spec.rb b/spec/lib/gitlab/import_export/project_tree_restorer_spec.rb
index b9f6595762b..baec24590b4 100644
--- a/spec/lib/gitlab/import_export/project_tree_restorer_spec.rb
+++ b/spec/lib/gitlab/import_export/project_tree_restorer_spec.rb
@@ -160,13 +160,21 @@ describe Gitlab::ImportExport::ProjectTreeRestorer do
end
it 'has project labels' do
- expect(ProjectLabel.count).to eq(2)
+ expect(ProjectLabel.count).to eq(3)
end
it 'has no group labels' do
expect(GroupLabel.count).to eq(0)
end
+ it 'has issue boards' do
+ expect(Project.find_by_path('project').boards.count).to eq(1)
+ end
+
+ it 'has lists associated with the issue board' do
+ expect(Project.find_by_path('project').boards.find_by_name('TestBoardABC').lists.count).to eq(3)
+ end
+
it 'has a project feature' do
expect(@project.project_feature).not_to be_nil
end
diff --git a/spec/lib/gitlab/import_export/project_tree_saver_spec.rb b/spec/lib/gitlab/import_export/project_tree_saver_spec.rb
index 1ff2eb9210f..fefbed93316 100644
--- a/spec/lib/gitlab/import_export/project_tree_saver_spec.rb
+++ b/spec/lib/gitlab/import_export/project_tree_saver_spec.rb
@@ -272,6 +272,10 @@ describe Gitlab::ImportExport::ProjectTreeSaver do
expect(saved_project_json).not_to include("runners_token" => 'token')
end
end
+
+ it 'has a board and a list' do
+ expect(saved_project_json['boards'].first['lists']).not_to be_empty
+ end
end
end
@@ -327,6 +331,9 @@ describe Gitlab::ImportExport::ProjectTreeSaver do
create(:project_badge, project: project)
create(:project_badge, project: project)
+ board = create(:board, project: project, name: 'TestBoard')
+ create(:list, board: board, position: 0, label: project_label)
+
project
end
diff --git a/spec/lib/gitlab/import_export/safe_model_attributes.yml b/spec/lib/gitlab/import_export/safe_model_attributes.yml
index 28b187c3676..f0545176a90 100644
--- a/spec/lib/gitlab/import_export/safe_model_attributes.yml
+++ b/spec/lib/gitlab/import_export/safe_model_attributes.yml
@@ -235,6 +235,12 @@ MergeRequest::Metrics:
- latest_build_started_at
- latest_build_finished_at
- first_deployed_to_production_at
+- first_comment_at
+- first_commit_at
+- last_commit_at
+- diff_size
+- modified_paths_size
+- commits_count
Ci::Pipeline:
- id
- project_id
@@ -687,3 +693,22 @@ ProjectMetricsSetting:
- external_dashboard_url
- created_at
- updated_at
+Board:
+- id
+- project_id
+- created_at
+- updated_at
+- group_id
+- milestone_id
+- weight
+- name
+List:
+- id
+- board_id
+- label_id
+- list_type
+- position
+- created_at
+- updated_at
+- milestone_id
+- user_id
diff --git a/spec/lib/gitlab/kubernetes/default_namespace_spec.rb b/spec/lib/gitlab/kubernetes/default_namespace_spec.rb
new file mode 100644
index 00000000000..1fda547f35c
--- /dev/null
+++ b/spec/lib/gitlab/kubernetes/default_namespace_spec.rb
@@ -0,0 +1,85 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Gitlab::Kubernetes::DefaultNamespace do
+ let(:generator) { described_class.new(cluster, project: environment.project) }
+
+ describe '#from_environment_name' do
+ let(:cluster) { create(:cluster) }
+ let(:environment) { create(:environment) }
+
+ subject { generator.from_environment_name(environment.name) }
+
+ it 'generates a slug and passes it to #from_environment_slug' do
+ expect(Gitlab::Slug::Environment).to receive(:new)
+ .with(environment.name)
+ .and_return(double(generate: environment.slug))
+
+ expect(generator).to receive(:from_environment_slug)
+ .with(environment.slug)
+ .and_return(:mock_namespace)
+
+ expect(subject).to eq :mock_namespace
+ end
+ end
+
+ describe '#from_environment_slug' do
+ let(:platform) { create(:cluster_platform_kubernetes, namespace: platform_namespace) }
+ let(:cluster) { create(:cluster, platform_kubernetes: platform) }
+ let(:project) { create(:project, path: "Path-With-Capitals") }
+ let(:environment) { create(:environment, project: project) }
+
+ subject { generator.from_environment_slug(environment.slug) }
+
+ context 'namespace per environment is enabled' do
+ context 'platform namespace is specified' do
+ let(:platform_namespace) { 'platform-namespace' }
+
+ it { is_expected.to eq "#{platform_namespace}-#{environment.slug}" }
+
+ context 'cluster is unmanaged' do
+ let(:cluster) { create(:cluster, :not_managed, platform_kubernetes: platform) }
+
+ it { is_expected.to eq platform_namespace }
+ end
+ end
+
+ context 'platform namespace is blank' do
+ let(:platform_namespace) { nil }
+ let(:mock_namespace) { 'mock-namespace' }
+
+ it 'constructs a namespace from the project and environment' do
+ expect(Gitlab::NamespaceSanitizer).to receive(:sanitize)
+ .with("#{project.path}-#{project.id}-#{environment.slug}".downcase)
+ .and_return(mock_namespace)
+
+ expect(subject).to eq mock_namespace
+ end
+ end
+ end
+
+ context 'namespace per environment is disabled' do
+ let(:cluster) { create(:cluster, :namespace_per_environment_disabled, platform_kubernetes: platform) }
+
+ context 'platform namespace is specified' do
+ let(:platform_namespace) { 'platform-namespace' }
+
+ it { is_expected.to eq platform_namespace }
+ end
+
+ context 'platform namespace is blank' do
+ let(:platform_namespace) { nil }
+ let(:mock_namespace) { 'mock-namespace' }
+
+ it 'constructs a namespace from the project and environment' do
+ expect(Gitlab::NamespaceSanitizer).to receive(:sanitize)
+ .with("#{project.path}-#{project.id}".downcase)
+ .and_return(mock_namespace)
+
+ expect(subject).to eq mock_namespace
+ end
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/prometheus/query_variables_spec.rb b/spec/lib/gitlab/prometheus/query_variables_spec.rb
index 6dc99ef26ec..3f9b245a3fb 100644
--- a/spec/lib/gitlab/prometheus/query_variables_spec.rb
+++ b/spec/lib/gitlab/prometheus/query_variables_spec.rb
@@ -23,7 +23,7 @@ describe Gitlab::Prometheus::QueryVariables do
context 'with deployment platform' do
context 'with project cluster' do
- let(:kube_namespace) { environment.deployment_platform.cluster.kubernetes_namespace_for(project) }
+ let(:kube_namespace) { environment.deployment_namespace }
before do
create(:cluster, :project, :provided_by_user, projects: [project])
@@ -38,8 +38,8 @@ describe Gitlab::Prometheus::QueryVariables do
let(:project2) { create(:project) }
let(:kube_namespace) { k8s_ns.namespace }
- let!(:k8s_ns) { create(:cluster_kubernetes_namespace, cluster: cluster, project: project) }
- let!(:k8s_ns2) { create(:cluster_kubernetes_namespace, cluster: cluster, project: project2) }
+ let!(:k8s_ns) { create(:cluster_kubernetes_namespace, cluster: cluster, project: project, environment: environment) }
+ let!(:k8s_ns2) { create(:cluster_kubernetes_namespace, cluster: cluster, project: project2, environment: environment) }
before do
group.projects << project
diff --git a/spec/lib/gitlab/prometheus_client_spec.rb b/spec/lib/gitlab/prometheus_client_spec.rb
index f15ae83a02c..0a4e8dbced5 100644
--- a/spec/lib/gitlab/prometheus_client_spec.rb
+++ b/spec/lib/gitlab/prometheus_client_spec.rb
@@ -3,7 +3,7 @@ require 'spec_helper'
describe Gitlab::PrometheusClient do
include PrometheusHelpers
- subject { described_class.new(RestClient::Resource.new('https://prometheus.example.com')) }
+ subject { described_class.new('https://prometheus.example.com') }
describe '#ping' do
it 'issues a "query" request to the API endpoint' do
@@ -79,8 +79,16 @@ describe Gitlab::PrometheusClient do
expect(req_stub).to have_been_requested
end
- it 'raises a Gitlab::PrometheusClient::Error error when a RestClient::Exception is rescued' do
- req_stub = stub_prometheus_request_with_exception(prometheus_url, RestClient::Exception)
+ it 'raises a Gitlab::PrometheusClient::Error error when a Gitlab::HTTP::ResponseError is rescued' do
+ req_stub = stub_prometheus_request_with_exception(prometheus_url, Gitlab::HTTP::ResponseError)
+
+ expect { subject }
+ .to raise_error(Gitlab::PrometheusClient::Error, "Network connection error")
+ expect(req_stub).to have_been_requested
+ end
+
+ it 'raises a Gitlab::PrometheusClient::Error error when a Gitlab::HTTP::ResponseError with a code is rescued' do
+ req_stub = stub_prometheus_request_with_exception(prometheus_url, Gitlab::HTTP::ResponseError.new(code: 400))
expect { subject }
.to raise_error(Gitlab::PrometheusClient::Error, "Network connection error")
@@ -89,13 +97,13 @@ describe Gitlab::PrometheusClient do
end
context 'ping' do
- subject { described_class.new(RestClient::Resource.new(prometheus_url)).ping }
+ subject { described_class.new(prometheus_url).ping }
it_behaves_like 'exceptions are raised'
end
context 'proxy' do
- subject { described_class.new(RestClient::Resource.new(prometheus_url)).proxy('query', { query: '1' }) }
+ subject { described_class.new(prometheus_url).proxy('query', { query: '1' }) }
it_behaves_like 'exceptions are raised'
end
@@ -310,15 +318,32 @@ describe Gitlab::PrometheusClient do
end
end
- context 'when RestClient::Exception is raised' do
+ context 'when Gitlab::HTTP::ResponseError is raised' do
before do
- stub_prometheus_request_with_exception(query_url, RestClient::Exception)
+ stub_prometheus_request_with_exception(query_url, response_error)
+ end
+
+ context "without response code" do
+ let(:response_error) { Gitlab::HTTP::ResponseError }
+ it 'raises PrometheusClient::Error' do
+ expect { subject.proxy('query', { query: prometheus_query }) }.to(
+ raise_error(Gitlab::PrometheusClient::Error, 'Network connection error')
+ )
+ end
end
- it 'raises PrometheusClient::Error' do
- expect { subject.proxy('query', { query: prometheus_query }) }.to(
- raise_error(Gitlab::PrometheusClient::Error, 'Network connection error')
- )
+ context "with response code" do
+ let(:response_error) do
+ response = Net::HTTPResponse.new(1.1, 400, '{}sumpthin')
+ allow(response).to receive(:body) { '{}' }
+ Gitlab::HTTP::ResponseError.new(response)
+ end
+
+ it 'raises Gitlab::PrometheusClient::QueryError' do
+ expect { subject.proxy('query', { query: prometheus_query }) }.to(
+ raise_error(Gitlab::PrometheusClient::QueryError, 'Bad data received')
+ )
+ end
end
end
end
diff --git a/spec/lib/sentry/client_spec.rb b/spec/lib/sentry/client_spec.rb
index cb14204b99a..ca2b17b44e0 100644
--- a/spec/lib/sentry/client_spec.rb
+++ b/spec/lib/sentry/client_spec.rb
@@ -63,7 +63,7 @@ describe Sentry::Client do
shared_examples 'maps exceptions' do
exceptions = {
- HTTParty::Error => 'Error when connecting to Sentry',
+ Gitlab::HTTP::Error => 'Error when connecting to Sentry',
Net::OpenTimeout => 'Connection to Sentry timed out',
SocketError => 'Received SocketError when trying to connect to Sentry',
OpenSSL::SSL::SSLError => 'Sentry returned invalid SSL data',
diff --git a/spec/models/clusters/applications/prometheus_spec.rb b/spec/models/clusters/applications/prometheus_spec.rb
index d9f31c46f59..eb6ccba5584 100644
--- a/spec/models/clusters/applications/prometheus_spec.rb
+++ b/spec/models/clusters/applications/prometheus_spec.rb
@@ -86,16 +86,15 @@ describe Clusters::Applications::Prometheus do
project: cluster.cluster_project.project)
end
- it 'creates proxy prometheus rest client' do
- expect(subject.prometheus_client).to be_instance_of(RestClient::Resource)
+ it 'creates proxy prometheus_client' do
+ expect(subject.prometheus_client).to be_instance_of(Gitlab::PrometheusClient)
end
- it 'creates proper url' do
- expect(subject.prometheus_client.url).to eq("#{kubernetes_url}/api/v1/namespaces/gitlab-managed-apps/services/prometheus-prometheus-server:80/proxy")
- end
-
- it 'copies options and headers from kube client to proxy client' do
- expect(subject.prometheus_client.options).to eq(kube_client.rest_client.options.merge(headers: kube_client.headers))
+ it 'copies proxy_url, options and headers from kube client to prometheus_client' do
+ expect(Gitlab::PrometheusClient)
+ .to(receive(:new))
+ .with(a_valid_url, kube_client.rest_client.options.merge(headers: kube_client.headers))
+ subject.prometheus_client
end
context 'when cluster is not reachable' do
diff --git a/spec/models/clusters/cluster_spec.rb b/spec/models/clusters/cluster_spec.rb
index 96212d0c864..9afbe6328ca 100644
--- a/spec/models/clusters/cluster_spec.rb
+++ b/spec/models/clusters/cluster_spec.rb
@@ -38,11 +38,6 @@ describe Clusters::Cluster, :use_clean_rails_memory_store_caching do
it { is_expected.to respond_to :project }
- it do
- expect(subject.knative_services_finder(subject.project))
- .to be_instance_of(Clusters::KnativeServicesFinder)
- end
-
describe '.enabled' do
subject { described_class.enabled }
@@ -534,60 +529,39 @@ describe Clusters::Cluster, :use_clean_rails_memory_store_caching do
end
end
- describe '#find_or_initialize_kubernetes_namespace_for_project' do
- let(:cluster) { create(:cluster, :project, :provided_by_gcp) }
- let(:project) { cluster.projects.first }
-
- subject { cluster.find_or_initialize_kubernetes_namespace_for_project(project) }
-
- context 'kubernetes namespace exists' do
- context 'with no service account token' do
- let!(:kubernetes_namespace) { create(:cluster_kubernetes_namespace, project: project, cluster: cluster) }
-
- it { is_expected.to eq kubernetes_namespace }
- end
+ describe '#kubernetes_namespace_for' do
+ let(:cluster) { create(:cluster, :group) }
+ let(:environment) { create(:environment) }
- context 'with a service account token' do
- let!(:kubernetes_namespace) { create(:cluster_kubernetes_namespace, :with_token, project: project, cluster: cluster) }
+ subject { cluster.kubernetes_namespace_for(environment) }
- it { is_expected.to eq kubernetes_namespace }
- end
- end
-
- context 'kubernetes namespace does not exist' do
- it 'initializes a new namespace and sets default values' do
- expect(subject).to be_new_record
- expect(subject.project).to eq project
- expect(subject.cluster).to eq cluster
- expect(subject.namespace).to be_present
- expect(subject.service_account_name).to be_present
- end
+ before do
+ expect(Clusters::KubernetesNamespaceFinder).to receive(:new)
+ .with(cluster, project: environment.project, environment_slug: environment.slug)
+ .and_return(double(execute: persisted_namespace))
end
- context 'a custom scope is provided' do
- let(:scope) { cluster.kubernetes_namespaces.has_service_account_token }
-
- subject { cluster.find_or_initialize_kubernetes_namespace_for_project(project, scope: scope) }
-
- context 'kubernetes namespace exists' do
- context 'with no service account token' do
- let!(:kubernetes_namespace) { create(:cluster_kubernetes_namespace, project: project, cluster: cluster) }
+ context 'a persisted namespace exists' do
+ let(:persisted_namespace) { create(:cluster_kubernetes_namespace) }
- it 'initializes a new namespace and sets default values' do
- expect(subject).to be_new_record
- expect(subject.project).to eq project
- expect(subject.cluster).to eq cluster
- expect(subject.namespace).to be_present
- expect(subject.service_account_name).to be_present
- end
- end
+ it { is_expected.to eq persisted_namespace.namespace }
+ end
- context 'with a service account token' do
- let!(:kubernetes_namespace) { create(:cluster_kubernetes_namespace, :with_token, project: project, cluster: cluster) }
+ context 'no persisted namespace exists' do
+ let(:persisted_namespace) { nil }
+ let(:namespace_generator) { double }
+ let(:default_namespace) { 'a-default-namespace' }
- it { is_expected.to eq kubernetes_namespace }
- end
+ before do
+ expect(Gitlab::Kubernetes::DefaultNamespace).to receive(:new)
+ .with(cluster, project: environment.project)
+ .and_return(namespace_generator)
+ expect(namespace_generator).to receive(:from_environment_slug)
+ .with(environment.slug)
+ .and_return(default_namespace)
end
+
+ it { is_expected.to eq default_namespace }
end
end
diff --git a/spec/models/clusters/kubernetes_namespace_spec.rb b/spec/models/clusters/kubernetes_namespace_spec.rb
index b5cba80b806..d4e3a0ac84d 100644
--- a/spec/models/clusters/kubernetes_namespace_spec.rb
+++ b/spec/models/clusters/kubernetes_namespace_spec.rb
@@ -24,70 +24,60 @@ RSpec.describe Clusters::KubernetesNamespace, type: :model do
end
end
- describe 'namespace uniqueness validation' do
- let(:cluster_project) { create(:cluster_project) }
- let(:kubernetes_namespace) { build(:cluster_kubernetes_namespace, namespace: 'my-namespace') }
+ describe '.with_environment_slug' do
+ let(:cluster) { create(:cluster, :group) }
+ let(:environment) { create(:environment, slug: slug) }
- subject { kubernetes_namespace }
+ let(:slug) { 'production' }
- context 'when cluster is using the namespace' do
- before do
- create(:cluster_kubernetes_namespace,
- cluster: kubernetes_namespace.cluster,
- namespace: 'my-namespace')
- end
+ subject { described_class.with_environment_slug(slug) }
- it { is_expected.not_to be_valid }
- end
+ context 'there is no associated environment' do
+ let!(:namespace) { create(:cluster_kubernetes_namespace, cluster: cluster, project: environment.project) }
- context 'when cluster is not using the namespace' do
- it { is_expected.to be_valid }
+ it { is_expected.to be_empty }
end
- end
- describe '#set_defaults' do
- let(:kubernetes_namespace) { build(:cluster_kubernetes_namespace) }
- let(:cluster) { kubernetes_namespace.cluster }
- let(:platform) { kubernetes_namespace.platform_kubernetes }
-
- subject { kubernetes_namespace.set_defaults }
-
- describe '#namespace' do
- before do
- platform.update_column(:namespace, namespace)
+ context 'there is an assicated environment' do
+ let!(:namespace) do
+ create(
+ :cluster_kubernetes_namespace,
+ cluster: cluster,
+ project: environment.project,
+ environment: environment
+ )
end
- context 'when platform has a namespace assigned' do
- let(:namespace) { 'platform-namespace' }
-
- it 'copies the namespace' do
- subject
-
- expect(kubernetes_namespace.namespace).to eq('platform-namespace')
- end
+ context 'with a matching slug' do
+ it { is_expected.to eq [namespace] }
end
- context 'when platform does not have namespace assigned' do
- let(:project) { kubernetes_namespace.project }
- let(:namespace) { nil }
- let(:project_slug) { "#{project.path}-#{project.id}" }
-
- it 'fallbacks to project namespace' do
- subject
+ context 'without a matching slug' do
+ let(:environment) { create(:environment, slug: 'staging') }
- expect(kubernetes_namespace.namespace).to eq(project_slug)
- end
+ it { is_expected.to be_empty }
end
end
+ end
- describe '#service_account_name' do
- let(:service_account_name) { "#{kubernetes_namespace.namespace}-service-account" }
+ describe 'namespace uniqueness validation' do
+ let(:kubernetes_namespace) { build(:cluster_kubernetes_namespace, namespace: 'my-namespace') }
- it 'sets a service account name based on namespace' do
- subject
+ subject { kubernetes_namespace }
- expect(kubernetes_namespace.service_account_name).to eq(service_account_name)
+ context 'when cluster is using the namespace' do
+ before do
+ create(:cluster_kubernetes_namespace,
+ cluster: kubernetes_namespace.cluster,
+ environment: kubernetes_namespace.environment,
+ namespace: 'my-namespace')
end
+
+ it { is_expected.not_to be_valid }
+ end
+
+ context 'when cluster is not using the namespace' do
+ it { is_expected.to be_valid }
end
end
diff --git a/spec/models/clusters/platforms/kubernetes_spec.rb b/spec/models/clusters/platforms/kubernetes_spec.rb
index 5811016ea4d..0c4cf291d20 100644
--- a/spec/models/clusters/platforms/kubernetes_spec.rb
+++ b/spec/models/clusters/platforms/kubernetes_spec.rb
@@ -205,192 +205,77 @@ describe Clusters::Platforms::Kubernetes do
it { is_expected.to be_truthy }
end
- describe '#kubernetes_namespace_for' do
- let(:cluster) { create(:cluster, :project) }
- let(:project) { cluster.project }
-
- let(:platform) do
- create(:cluster_platform_kubernetes,
- cluster: cluster,
- namespace: namespace)
- end
-
- subject { platform.kubernetes_namespace_for(project) }
-
- context 'with a namespace assigned' do
- let(:namespace) { 'namespace-123' }
-
- it { is_expected.to eq(namespace) }
-
- context 'kubernetes namespace is present but has no service account token' do
- let!(:kubernetes_namespace) { create(:cluster_kubernetes_namespace, cluster: cluster) }
-
- it { is_expected.to eq(namespace) }
- end
- end
-
- context 'with no namespace assigned' do
- let(:namespace) { nil }
-
- context 'when kubernetes namespace is present' do
- let(:kubernetes_namespace) { create(:cluster_kubernetes_namespace, :with_token, cluster: cluster) }
-
- before do
- kubernetes_namespace
- end
-
- it { is_expected.to eq(kubernetes_namespace.namespace) }
-
- context 'kubernetes namespace has no service account token' do
- before do
- kubernetes_namespace.update!(namespace: 'old-namespace', service_account_token: nil)
- end
+ describe '#predefined_variables' do
+ let(:project) { create(:project) }
+ let(:cluster) { create(:cluster, :group, platform_kubernetes: platform) }
+ let(:platform) { create(:cluster_platform_kubernetes) }
+ let(:persisted_namespace) { create(:cluster_kubernetes_namespace, project: project, cluster: cluster) }
- it { is_expected.to eq("#{project.path}-#{project.id}") }
- end
- end
+ let(:environment_name) { 'env/production' }
+ let(:environment_slug) { Gitlab::Slug::Environment.new(environment_name).generate }
- context 'when kubernetes namespace is not present' do
- it { is_expected.to eq("#{project.path}-#{project.id}") }
- end
- end
- end
+ subject { platform.predefined_variables(project: project, environment_name: environment_name) }
- describe '#predefined_variables' do
- let!(:cluster) { create(:cluster, :project, platform_kubernetes: kubernetes) }
- let(:kubernetes) { create(:cluster_platform_kubernetes, api_url: api_url, ca_cert: ca_pem) }
- let(:api_url) { 'https://kube.domain.com' }
- let(:ca_pem) { File.read(Rails.root.join('spec/fixtures/clusters/sample_cert.pem')) }
-
- subject { kubernetes.predefined_variables(project: cluster.project) }
-
- shared_examples 'setting variables' do
- it 'sets the variables' do
- expect(subject).to include(
- { key: 'KUBE_URL', value: api_url, public: true },
- { key: 'KUBE_CA_PEM', value: ca_pem, public: true },
- { key: 'KUBE_CA_PEM_FILE', value: ca_pem, public: true, file: true }
- )
- end
+ before do
+ allow(Clusters::KubernetesNamespaceFinder).to receive(:new)
+ .with(cluster, project: project, environment_slug: environment_slug)
+ .and_return(double(execute: persisted_namespace))
end
- context 'kubernetes namespace is created with no service account token' do
- let!(:kubernetes_namespace) { create(:cluster_kubernetes_namespace, cluster: cluster) }
+ it { is_expected.to include(key: 'KUBE_URL', value: platform.api_url, public: true) }
- it_behaves_like 'setting variables'
+ context 'platform has a CA certificate' do
+ let(:ca_pem) { File.read(Rails.root.join('spec/fixtures/clusters/sample_cert.pem')) }
+ let(:platform) { create(:cluster_platform_kubernetes, ca_cert: ca_pem) }
- it 'does not set KUBE_TOKEN' do
- expect(subject).not_to include(
- { key: 'KUBE_TOKEN', value: kubernetes.token, public: false, masked: true }
- )
- end
+ it { is_expected.to include(key: 'KUBE_CA_PEM', value: ca_pem, public: true) }
+ it { is_expected.to include(key: 'KUBE_CA_PEM_FILE', value: ca_pem, public: true, file: true) }
end
- context 'kubernetes namespace is created with service account token' do
- let!(:kubernetes_namespace) { create(:cluster_kubernetes_namespace, :with_token, cluster: cluster) }
-
- it_behaves_like 'setting variables'
+ context 'kubernetes namespace exists' do
+ let(:variable) { Hash(key: :fake_key, value: 'fake_value') }
+ let(:namespace_variables) { Gitlab::Ci::Variables::Collection.new([variable]) }
- it 'sets KUBE_TOKEN' do
- expect(subject).to include(
- { key: 'KUBE_TOKEN', value: kubernetes_namespace.service_account_token, public: false, masked: true }
- )
+ before do
+ expect(persisted_namespace).to receive(:predefined_variables).and_return(namespace_variables)
end
- context 'the cluster has been set to unmanaged after the namespace was created' do
- before do
- cluster.update!(managed: false)
- end
-
- it_behaves_like 'setting variables'
-
- it 'sets KUBE_TOKEN from the platform' do
- expect(subject).to include(
- { key: 'KUBE_TOKEN', value: kubernetes.token, public: false, masked: true }
- )
- end
-
- context 'the platform has a custom namespace set' do
- before do
- kubernetes.update!(namespace: 'custom-namespace')
- end
-
- it 'sets KUBE_NAMESPACE from the platform' do
- expect(subject).to include(
- { key: 'KUBE_NAMESPACE', value: kubernetes.namespace, public: true, masked: false }
- )
- end
- end
-
- context 'there is no namespace specified on the platform' do
- let(:project) { cluster.project }
-
- before do
- kubernetes.update!(namespace: nil)
- end
-
- it 'sets KUBE_NAMESPACE to a default for the project' do
- expect(subject).to include(
- { key: 'KUBE_NAMESPACE', value: "#{project.path}-#{project.id}", public: true, masked: false }
- )
- end
- end
- end
+ it { is_expected.to include(variable) }
end
- context 'group level cluster' do
- let!(:cluster) { create(:cluster, :group, platform_kubernetes: kubernetes) }
-
- let(:project) { create(:project, group: cluster.group) }
-
- subject { kubernetes.predefined_variables(project: project) }
-
- context 'no kubernetes namespace for the project' do
- it_behaves_like 'setting variables'
-
- it 'does not return KUBE_TOKEN' do
- expect(subject).not_to include(
- { key: 'KUBE_TOKEN', value: kubernetes.token, public: false }
- )
- end
-
- context 'the cluster is not managed' do
- let!(:cluster) { create(:cluster, :group, :not_managed, platform_kubernetes: kubernetes) }
+ context 'kubernetes namespace does not exist' do
+ let(:persisted_namespace) { nil }
+ let(:namespace) { 'kubernetes-namespace' }
+ let(:kubeconfig) { 'kubeconfig' }
- it_behaves_like 'setting variables'
-
- it 'sets KUBE_TOKEN' do
- expect(subject).to include(
- { key: 'KUBE_TOKEN', value: kubernetes.token, public: false, masked: true }
- )
- end
- end
+ before do
+ allow(Gitlab::Kubernetes::DefaultNamespace).to receive(:new)
+ .with(cluster, project: project).and_return(double(from_environment_name: namespace))
+ allow(platform).to receive(:kubeconfig).with(namespace).and_return(kubeconfig)
end
- context 'kubernetes namespace exists for the project' do
- let!(:kubernetes_namespace) { create(:cluster_kubernetes_namespace, :with_token, cluster: cluster, project: project) }
+ it { is_expected.not_to include(key: 'KUBE_TOKEN', value: platform.token, public: false, masked: true) }
+ it { is_expected.not_to include(key: 'KUBE_NAMESPACE', value: namespace) }
+ it { is_expected.not_to include(key: 'KUBECONFIG', value: kubeconfig, public: false, file: true) }
- it_behaves_like 'setting variables'
+ context 'cluster is unmanaged' do
+ let(:cluster) { create(:cluster, :group, :not_managed, platform_kubernetes: platform) }
- it 'sets KUBE_TOKEN' do
- expect(subject).to include(
- { key: 'KUBE_TOKEN', value: kubernetes_namespace.service_account_token, public: false, masked: true }
- )
- end
+ it { is_expected.to include(key: 'KUBE_TOKEN', value: platform.token, public: false, masked: true) }
+ it { is_expected.to include(key: 'KUBE_NAMESPACE', value: namespace) }
+ it { is_expected.to include(key: 'KUBECONFIG', value: kubeconfig, public: false, file: true) }
end
end
- context 'with a domain' do
- let!(:cluster) do
- create(:cluster, :provided_by_gcp, :with_domain,
- platform_kubernetes: kubernetes)
- end
+ context 'cluster variables' do
+ let(:variable) { Hash(key: :fake_key, value: 'fake_value') }
+ let(:cluster_variables) { Gitlab::Ci::Variables::Collection.new([variable]) }
- it 'sets KUBE_INGRESS_BASE_DOMAIN' do
- expect(subject).to include(
- { key: 'KUBE_INGRESS_BASE_DOMAIN', value: cluster.domain, public: true }
- )
+ before do
+ expect(cluster).to receive(:predefined_variables).and_return(cluster_variables)
end
+
+ it { is_expected.to include(variable) }
end
end
@@ -410,7 +295,7 @@ describe Clusters::Platforms::Kubernetes do
end
context 'with valid pods' do
- let(:pod) { kube_pod(environment_slug: environment.slug, namespace: cluster.kubernetes_namespace_for(project), project_slug: project.full_path_slug) }
+ let(:pod) { kube_pod(environment_slug: environment.slug, namespace: cluster.kubernetes_namespace_for(environment), project_slug: project.full_path_slug) }
let(:pod_with_no_terminal) { kube_pod(environment_slug: environment.slug, project_slug: project.full_path_slug, status: "Pending") }
let(:terminals) { kube_terminals(service, pod) }
let(:pods) { [pod, pod, pod_with_no_terminal, kube_pod(environment_slug: "should-be-filtered-out")] }
diff --git a/spec/models/concerns/prometheus_adapter_spec.rb b/spec/models/concerns/prometheus_adapter_spec.rb
index 25a2d290f76..3d26ba95192 100644
--- a/spec/models/concerns/prometheus_adapter_spec.rb
+++ b/spec/models/concerns/prometheus_adapter_spec.rb
@@ -40,13 +40,13 @@ describe PrometheusAdapter, :use_clean_rails_memory_store_caching do
describe 'matched_metrics' do
let(:matched_metrics_query) { Gitlab::Prometheus::Queries::MatchedMetricQuery }
- let(:prometheus_client_wrapper) { double(:prometheus_client_wrapper, label_values: nil) }
+ let(:prometheus_client) { double(:prometheus_client, label_values: nil) }
context 'with valid data' do
subject { service.query(:matched_metrics) }
before do
- allow(service).to receive(:prometheus_client_wrapper).and_return(prometheus_client_wrapper)
+ allow(service).to receive(:prometheus_client).and_return(prometheus_client)
synchronous_reactive_cache(service)
end
diff --git a/spec/models/environment_spec.rb b/spec/models/environment_spec.rb
index d2e0bed721e..521c4704c87 100644
--- a/spec/models/environment_spec.rb
+++ b/spec/models/environment_spec.rb
@@ -575,6 +575,34 @@ describe Environment, :use_clean_rails_memory_store_caching do
end
end
+ describe '#deployment_namespace' do
+ let(:environment) { create(:environment) }
+
+ subject { environment.deployment_namespace }
+
+ before do
+ allow(environment).to receive(:deployment_platform).and_return(deployment_platform)
+ end
+
+ context 'no deployment platform available' do
+ let(:deployment_platform) { nil }
+
+ it { is_expected.to be_nil }
+ end
+
+ context 'deployment platform is available' do
+ let(:cluster) { create(:cluster, :provided_by_user, :project, projects: [environment.project]) }
+ let(:deployment_platform) { cluster.platform }
+
+ it 'retrieves a namespace from the cluster' do
+ expect(cluster).to receive(:kubernetes_namespace_for)
+ .with(environment).and_return('mock-namespace')
+
+ expect(subject).to eq 'mock-namespace'
+ end
+ end
+ end
+
describe '#terminals' do
subject { environment.terminals }
@@ -823,4 +851,35 @@ describe Environment, :use_clean_rails_memory_store_caching do
subject.prometheus_adapter
end
end
+
+ describe '#knative_services_finder' do
+ let(:environment) { create(:environment) }
+
+ subject { environment.knative_services_finder }
+
+ context 'environment has no deployments' do
+ it { is_expected.to be_nil }
+ end
+
+ context 'environment has a deployment' do
+ let!(:deployment) { create(:deployment, :success, environment: environment, cluster: cluster) }
+
+ context 'with no cluster associated' do
+ let(:cluster) { nil }
+
+ it { is_expected.to be_nil }
+ end
+
+ context 'with a cluster associated' do
+ let(:cluster) { create(:cluster) }
+
+ it 'calls the service finder' do
+ expect(Clusters::KnativeServicesFinder).to receive(:new)
+ .with(cluster, environment).and_return(:finder)
+
+ is_expected.to eq :finder
+ end
+ end
+ end
+ end
end
diff --git a/spec/models/merge_request_diff_spec.rb b/spec/models/merge_request_diff_spec.rb
index a53add67066..e7dd7287a75 100644
--- a/spec/models/merge_request_diff_spec.rb
+++ b/spec/models/merge_request_diff_spec.rb
@@ -484,4 +484,12 @@ describe MergeRequestDiff do
end
end
end
+
+ describe '#lines_count' do
+ subject { diff_with_commits }
+
+ it 'returns sum of all changed lines count in diff files' do
+ expect(subject.lines_count).to eq 109
+ end
+ end
end
diff --git a/spec/models/project_services/prometheus_service_spec.rb b/spec/models/project_services/prometheus_service_spec.rb
index e9c7c94ad70..e5ac6ca65d6 100644
--- a/spec/models/project_services/prometheus_service_spec.rb
+++ b/spec/models/project_services/prometheus_service_spec.rb
@@ -105,10 +105,6 @@ describe PrometheusService, :use_clean_rails_memory_store_caching do
context 'manual configuration is enabled' do
let(:manual_configuration) { true }
- it 'returns rest client from api_url' do
- expect(service.prometheus_client.url).to eq(api_url)
- end
-
it 'calls valid?' do
allow(service).to receive(:valid?).and_call_original
diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb
index 157103123ad..dde766c3813 100644
--- a/spec/models/project_spec.rb
+++ b/spec/models/project_spec.rb
@@ -1156,7 +1156,6 @@ describe Project do
describe '#pipeline_for' do
let(:project) { create(:project, :repository) }
- let!(:pipeline) { create_pipeline(project) }
shared_examples 'giving the correct pipeline' do
it { is_expected.to eq(pipeline) }
@@ -1168,24 +1167,34 @@ describe Project do
end
end
- context 'with explicit sha' do
- subject { project.pipeline_for('master', pipeline.sha) }
+ context 'with a matching pipeline' do
+ let!(:pipeline) { create_pipeline(project) }
+
+ context 'with explicit sha' do
+ subject { project.pipeline_for('master', pipeline.sha) }
+
+ it_behaves_like 'giving the correct pipeline'
- it_behaves_like 'giving the correct pipeline'
+ context 'with supplied id' do
+ let!(:other_pipeline) { create_pipeline(project) }
- context 'with supplied id' do
- let!(:other_pipeline) { create_pipeline(project) }
+ subject { project.pipeline_for('master', pipeline.sha, other_pipeline.id) }
+
+ it { is_expected.to eq(other_pipeline) }
+ end
+ end
- subject { project.pipeline_for('master', pipeline.sha, other_pipeline.id) }
+ context 'with implicit sha' do
+ subject { project.pipeline_for('master') }
- it { is_expected.to eq(other_pipeline) }
+ it_behaves_like 'giving the correct pipeline'
end
end
- context 'with implicit sha' do
+ context 'when there is no matching pipeline' do
subject { project.pipeline_for('master') }
- it_behaves_like 'giving the correct pipeline'
+ it { is_expected.to be_nil }
end
end
@@ -1194,11 +1203,9 @@ describe Project do
let!(:pipeline) { create_pipeline(project) }
let!(:other_pipeline) { create_pipeline(project) }
- context 'with implicit sha' do
- subject { project.pipelines_for('master') }
+ subject { project.pipelines_for(project.default_branch, project.commit.sha) }
- it { is_expected.to contain_exactly(pipeline, other_pipeline) }
- end
+ it { is_expected.to contain_exactly(pipeline, other_pipeline) }
end
describe '#builds_enabled' do
@@ -2587,45 +2594,33 @@ describe Project do
end
describe '#deployment_variables' do
- context 'when project has no deployment service' do
- let(:project) { create(:project) }
+ let(:project) { create(:project) }
+ let(:environment) { 'production' }
- it 'returns an empty array' do
- expect(project.deployment_variables).to eq []
- end
+ subject { project.deployment_variables(environment: environment) }
+
+ before do
+ expect(project).to receive(:deployment_platform).with(environment: environment)
+ .and_return(deployment_platform)
end
- context 'when project uses mock deployment service' do
- let(:project) { create(:mock_deployment_project) }
+ context 'when project has no deployment platform' do
+ let(:deployment_platform) { nil }
- it 'returns an empty array' do
- expect(project.deployment_variables).to eq []
- end
+ it { is_expected.to eq [] }
end
- context 'when project has a deployment service' do
- context 'when user configured kubernetes from CI/CD > Clusters and KubernetesNamespace migration has not been executed' do
- let!(:cluster) { create(:cluster, :project, :provided_by_gcp) }
- let(:project) { cluster.project }
+ context 'when project has a deployment platform' do
+ let(:platform_variables) { %w(platform variables) }
+ let(:deployment_platform) { double }
- it 'does not return variables from this service' do
- expect(project.deployment_variables).not_to include(
- { key: 'KUBE_TOKEN', value: project.deployment_platform.token, public: false, masked: true }
- )
- end
+ before do
+ expect(deployment_platform).to receive(:predefined_variables)
+ .with(project: project, environment_name: environment)
+ .and_return(platform_variables)
end
- context 'when user configured kubernetes from CI/CD > Clusters and KubernetesNamespace migration has been executed' do
- let!(:kubernetes_namespace) { create(:cluster_kubernetes_namespace, :with_token) }
- let!(:cluster) { kubernetes_namespace.cluster }
- let(:project) { kubernetes_namespace.project }
-
- it 'returns token from kubernetes namespace' do
- expect(project.deployment_variables).to include(
- { key: 'KUBE_TOKEN', value: kubernetes_namespace.service_account_token, public: false, masked: true }
- )
- end
- end
+ it { is_expected.to eq platform_variables }
end
end
diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb
index 35c335c5b5c..46b86e8393d 100644
--- a/spec/models/user_spec.rb
+++ b/spec/models/user_spec.rb
@@ -794,6 +794,24 @@ describe User do
end
end
+ describe '#accessible_deploy_keys' do
+ let(:user) { create(:user) }
+ let(:project) { create(:project) }
+ let!(:private_deploy_keys_project) { create(:deploy_keys_project) }
+ let!(:public_deploy_keys_project) { create(:deploy_keys_project) }
+ let!(:accessible_deploy_keys_project) { create(:deploy_keys_project, project: project) }
+
+ before do
+ public_deploy_keys_project.deploy_key.update(public: true)
+ project.add_developer(user)
+ end
+
+ it 'user can only see deploy keys accessible to right projects' do
+ expect(user.accessible_deploy_keys).to match_array([public_deploy_keys_project.deploy_key,
+ accessible_deploy_keys_project.deploy_key])
+ end
+ end
+
describe '#deploy_keys' do
include_context 'user keys'
diff --git a/spec/presenters/blob_presenter_spec.rb b/spec/presenters/blob_presenter_spec.rb
index eacf383be7d..95db2ba6a0d 100644
--- a/spec/presenters/blob_presenter_spec.rb
+++ b/spec/presenters/blob_presenter_spec.rb
@@ -28,24 +28,70 @@ describe BlobPresenter, :seed_helper do
subject { described_class.new(blob) }
it 'returns highlighted content' do
- expect(Gitlab::Highlight).to receive(:highlight).with('files/ruby/regex.rb', git_blob.data, plain: nil, language: nil)
+ expect(Gitlab::Highlight)
+ .to receive(:highlight)
+ .with(
+ 'files/ruby/regex.rb',
+ git_blob.data,
+ since: nil,
+ plain: nil,
+ language: nil
+ )
subject.highlight
end
it 'returns plain content when :plain is true' do
- expect(Gitlab::Highlight).to receive(:highlight).with('files/ruby/regex.rb', git_blob.data, plain: true, language: nil)
+ expect(Gitlab::Highlight)
+ .to receive(:highlight)
+ .with(
+ 'files/ruby/regex.rb',
+ git_blob.data,
+ since: nil,
+ plain: true,
+ language: nil
+ )
subject.highlight(plain: true)
end
+ context '"since" and "to" are present' do
+ before do
+ allow(git_blob)
+ .to receive(:data)
+ .and_return("line one\nline two\nline 3\nline 4")
+ end
+
+ it 'returns limited highlighted content' do
+ expect(Gitlab::Highlight)
+ .to receive(:highlight)
+ .with(
+ 'files/ruby/regex.rb',
+ "line two\nline 3\n",
+ since: 2,
+ language: nil,
+ plain: nil
+ )
+
+ subject.highlight(since: 2, to: 3)
+ end
+ end
+
context 'gitlab-language contains a match' do
before do
allow(blob).to receive(:language_from_gitattributes).and_return('ruby')
end
it 'passes language to inner call' do
- expect(Gitlab::Highlight).to receive(:highlight).with('files/ruby/regex.rb', git_blob.data, plain: nil, language: 'ruby')
+ expect(Gitlab::Highlight)
+ .to receive(:highlight)
+ .with(
+ 'files/ruby/regex.rb',
+ git_blob.data,
+ since: nil,
+ plain: nil,
+ language: 'ruby'
+ )
subject.highlight
end
diff --git a/spec/presenters/projects/settings/deploy_keys_presenter_spec.rb b/spec/presenters/projects/settings/deploy_keys_presenter_spec.rb
index 001545bb5df..b4bf39f3cdb 100644
--- a/spec/presenters/projects/settings/deploy_keys_presenter_spec.rb
+++ b/spec/presenters/projects/settings/deploy_keys_presenter_spec.rb
@@ -29,10 +29,6 @@ describe Projects::Settings::DeployKeysPresenter do
it 'returns the enabled_keys size' do
expect(presenter.enabled_keys_size).to eq(1)
end
-
- it 'returns true if there is any enabled_keys' do
- expect(presenter.any_keys_enabled?).to eq(true)
- end
end
describe '#available_keys/#available_project_keys' do
@@ -54,9 +50,5 @@ describe Projects::Settings::DeployKeysPresenter do
it 'returns the available_project_keys size' do
expect(presenter.available_project_keys_size).to eq(1)
end
-
- it 'shows if there is an available key' do
- expect(presenter.key_available?(deploy_key)).to eq(false)
- end
end
end
diff --git a/spec/requests/api/project_clusters_spec.rb b/spec/requests/api/project_clusters_spec.rb
index e8ed016db69..a7b919de2ef 100644
--- a/spec/requests/api/project_clusters_spec.rb
+++ b/spec/requests/api/project_clusters_spec.rb
@@ -336,7 +336,6 @@ describe API::ProjectClusters do
it 'does not update cluster attributes' do
expect(cluster.domain).not_to eq('new_domain.com')
expect(cluster.platform_kubernetes.namespace).not_to eq('invalid_namespace')
- expect(cluster.kubernetes_namespace_for(project)).not_to eq('invalid_namespace')
end
it 'returns validation errors' do
diff --git a/spec/services/clusters/build_kubernetes_namespace_service_spec.rb b/spec/services/clusters/build_kubernetes_namespace_service_spec.rb
new file mode 100644
index 00000000000..36c05469542
--- /dev/null
+++ b/spec/services/clusters/build_kubernetes_namespace_service_spec.rb
@@ -0,0 +1,57 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Clusters::BuildKubernetesNamespaceService do
+ let(:cluster) { create(:cluster, :project, :provided_by_gcp) }
+ let(:environment) { create(:environment) }
+ let(:project) { environment.project }
+
+ let(:namespace_generator) { double(from_environment_slug: namespace) }
+ let(:namespace) { 'namespace' }
+
+ subject { described_class.new(cluster, environment: environment).execute }
+
+ before do
+ allow(Gitlab::Kubernetes::DefaultNamespace).to receive(:new).and_return(namespace_generator)
+ end
+
+ shared_examples 'shared attributes' do
+ it 'initializes a new namespace and sets default values' do
+ expect(subject).to be_new_record
+ expect(subject.cluster).to eq cluster
+ expect(subject.project).to eq project
+ expect(subject.namespace).to eq namespace
+ expect(subject.service_account_name).to eq "#{namespace}-service-account"
+ end
+ end
+
+ include_examples 'shared attributes'
+
+ it 'sets cluster_project and environment' do
+ expect(subject.cluster_project).to eq cluster.cluster_project
+ expect(subject.environment).to eq environment
+ end
+
+ context 'namespace per environment is disabled' do
+ let(:cluster) { create(:cluster, :project, :provided_by_gcp, :namespace_per_environment_disabled) }
+
+ include_examples 'shared attributes'
+
+ it 'does not set environment' do
+ expect(subject.cluster_project).to eq cluster.cluster_project
+ expect(subject.environment).to be_nil
+ end
+ end
+
+ context 'group cluster' do
+ let(:cluster) { create(:cluster, :group, :provided_by_gcp) }
+
+ include_examples 'shared attributes'
+
+ it 'does not set cluster_project' do
+ expect(subject.cluster_project).to be_nil
+ expect(subject.environment).to eq environment
+ end
+ end
+end
diff --git a/spec/services/clusters/gcp/kubernetes/create_or_update_namespace_service_spec.rb b/spec/services/clusters/gcp/kubernetes/create_or_update_namespace_service_spec.rb
index 44407ae2793..e44cc3f5a78 100644
--- a/spec/services/clusters/gcp/kubernetes/create_or_update_namespace_service_spec.rb
+++ b/spec/services/clusters/gcp/kubernetes/create_or_update_namespace_service_spec.rb
@@ -9,8 +9,9 @@ describe Clusters::Gcp::Kubernetes::CreateOrUpdateNamespaceService, '#execute' d
let(:platform) { cluster.platform }
let(:api_url) { 'https://kubernetes.example.com' }
let(:project) { cluster.project }
+ let(:environment) { create(:environment, project: project) }
let(:cluster_project) { cluster.cluster_project }
- let(:namespace) { "#{project.path}-#{project.id}" }
+ let(:namespace) { "#{project.name}-#{project.id}-#{environment.slug}" }
subject do
described_class.new(
@@ -79,7 +80,8 @@ describe Clusters::Gcp::Kubernetes::CreateOrUpdateNamespaceService, '#execute' d
let(:kubernetes_namespace) do
build(:cluster_kubernetes_namespace,
cluster: cluster,
- project: project)
+ project: project,
+ environment: environment)
end
it_behaves_like 'successful creation of kubernetes namespace'
@@ -92,20 +94,22 @@ describe Clusters::Gcp::Kubernetes::CreateOrUpdateNamespaceService, '#execute' d
build(:cluster_kubernetes_namespace,
cluster: cluster,
project: cluster_project.project,
- cluster_project: cluster_project)
+ cluster_project: cluster_project,
+ environment: environment)
end
it_behaves_like 'successful creation of kubernetes namespace'
end
context 'when there is a Kubernetes Namespace associated' do
- let(:namespace) { 'new-namespace' }
+ let(:namespace) { "new-namespace-#{environment.slug}" }
let(:kubernetes_namespace) do
create(:cluster_kubernetes_namespace,
cluster: cluster,
project: cluster_project.project,
- cluster_project: cluster_project)
+ cluster_project: cluster_project,
+ environment: environment)
end
before do
diff --git a/spec/services/projects/destroy_service_spec.rb b/spec/services/projects/destroy_service_spec.rb
index e436af77ed4..9a6f64b825a 100644
--- a/spec/services/projects/destroy_service_spec.rb
+++ b/spec/services/projects/destroy_service_spec.rb
@@ -241,6 +241,18 @@ describe Projects::DestroyService do
expect(destroy_project(project, user)).to be false
end
end
+
+ context 'when registry is disabled' do
+ before do
+ stub_container_registry_config(enabled: false)
+ end
+
+ it 'does not attempting to remove any tags' do
+ expect(Projects::ContainerRepository::DestroyService).not_to receive(:new)
+
+ destroy_project(project, user)
+ end
+ end
end
context 'when there are tags for legacy root repository' do
diff --git a/spec/services/projects/lfs_pointers/lfs_download_link_list_service_spec.rb b/spec/services/projects/lfs_pointers/lfs_download_link_list_service_spec.rb
index 80debcd3a7a..dabfd61d3f5 100644
--- a/spec/services/projects/lfs_pointers/lfs_download_link_list_service_spec.rb
+++ b/spec/services/projects/lfs_pointers/lfs_download_link_list_service_spec.rb
@@ -33,7 +33,7 @@ describe Projects::LfsPointers::LfsDownloadLinkListService do
before do
allow(project).to receive(:lfs_enabled?).and_return(true)
- response = instance_double(HTTParty::Response)
+ response = instance_double(Gitlab::HTTP::Response)
allow(response).to receive(:body).and_return(objects_response.to_json)
allow(response).to receive(:success?).and_return(true)
allow(Gitlab::HTTP).to receive(:post).and_return(response)
@@ -95,7 +95,7 @@ describe Projects::LfsPointers::LfsDownloadLinkListService do
shared_examples 'JSON parse errors' do |body|
it 'raises error' do
- response = instance_double(HTTParty::Response)
+ response = instance_double(Gitlab::HTTP::Response)
allow(response).to receive(:body).and_return(body)
allow(response).to receive(:success?).and_return(true)
allow(Gitlab::HTTP).to receive(:post).and_return(response)
diff --git a/spec/services/prometheus/proxy_service_spec.rb b/spec/services/prometheus/proxy_service_spec.rb
index 4bdb20de4c9..03bda94e9c6 100644
--- a/spec/services/prometheus/proxy_service_spec.rb
+++ b/spec/services/prometheus/proxy_service_spec.rb
@@ -131,7 +131,7 @@ describe Prometheus::ProxyService do
allow(environment).to receive(:prometheus_adapter)
.and_return(prometheus_adapter)
allow(prometheus_adapter).to receive(:can_query?).and_return(true)
- allow(prometheus_adapter).to receive(:prometheus_client_wrapper)
+ allow(prometheus_adapter).to receive(:prometheus_client)
.and_return(prometheus_client)
end
diff --git a/spec/support/matchers/be_url.rb b/spec/support/matchers/be_url.rb
index 7bd0e7fada4..69171f53891 100644
--- a/spec/support/matchers/be_url.rb
+++ b/spec/support/matchers/be_url.rb
@@ -5,3 +5,7 @@ RSpec::Matchers.define :be_url do |_|
URI.parse(actual) rescue false
end
end
+
+# looks better when used like:
+# expect(thing).to receive(:method).with(a_valid_url)
+RSpec::Matchers.alias_matcher :a_valid_url, :be_url
diff --git a/spec/support/prometheus/additional_metrics_shared_examples.rb b/spec/support/prometheus/additional_metrics_shared_examples.rb
index 82582630dee..4e006edb7da 100644
--- a/spec/support/prometheus/additional_metrics_shared_examples.rb
+++ b/spec/support/prometheus/additional_metrics_shared_examples.rb
@@ -50,7 +50,7 @@ RSpec.shared_examples 'additional metrics query' do
let!(:cluster) { create(:cluster, :project, :provided_by_gcp) }
let(:project) { cluster.project }
let(:environment) { create(:environment, slug: 'environment-slug', project: project) }
- let(:kube_namespace) { project.deployment_platform.kubernetes_namespace_for(project) }
+ let(:kube_namespace) { environment.deployment_namespace }
it_behaves_like 'query context containing environment slug and filter'
diff --git a/spec/support/services/clusters/create_service_shared.rb b/spec/support/services/clusters/create_service_shared.rb
index 6ec8750ce87..27f6d0570b6 100644
--- a/spec/support/services/clusters/create_service_shared.rb
+++ b/spec/support/services/clusters/create_service_shared.rb
@@ -32,23 +32,56 @@ shared_context 'invalid cluster create params' do
end
shared_examples 'create cluster service success' do
- it 'creates a cluster object and performs a worker' do
- expect(ClusterProvisionWorker).to receive(:perform_async)
-
- expect { subject }
- .to change { Clusters::Cluster.count }.by(1)
- .and change { Clusters::Providers::Gcp.count }.by(1)
-
- expect(subject.name).to eq('test-cluster')
- expect(subject.user).to eq(user)
- expect(subject.project).to eq(project)
- expect(subject.provider.gcp_project_id).to eq('gcp-project')
- expect(subject.provider.zone).to eq('us-central1-a')
- expect(subject.provider.num_nodes).to eq(1)
- expect(subject.provider.machine_type).to eq('machine_type-a')
- expect(subject.provider.access_token).to eq(access_token)
- expect(subject.provider).to be_legacy_abac
- expect(subject.platform).to be_nil
+ context 'namespace per environment feature is enabled' do
+ before do
+ stub_feature_flags(kubernetes_namespace_per_environment: true)
+ end
+
+ it 'creates a cluster object and performs a worker' do
+ expect(ClusterProvisionWorker).to receive(:perform_async)
+
+ expect { subject }
+ .to change { Clusters::Cluster.count }.by(1)
+ .and change { Clusters::Providers::Gcp.count }.by(1)
+
+ expect(subject.name).to eq('test-cluster')
+ expect(subject.user).to eq(user)
+ expect(subject.project).to eq(project)
+ expect(subject.provider.gcp_project_id).to eq('gcp-project')
+ expect(subject.provider.zone).to eq('us-central1-a')
+ expect(subject.provider.num_nodes).to eq(1)
+ expect(subject.provider.machine_type).to eq('machine_type-a')
+ expect(subject.provider.access_token).to eq(access_token)
+ expect(subject.provider).to be_legacy_abac
+ expect(subject.platform).to be_nil
+ expect(subject.namespace_per_environment).to eq true
+ end
+ end
+
+ context 'namespace per environment feature is disabled' do
+ before do
+ stub_feature_flags(kubernetes_namespace_per_environment: false)
+ end
+
+ it 'creates a cluster object and performs a worker' do
+ expect(ClusterProvisionWorker).to receive(:perform_async)
+
+ expect { subject }
+ .to change { Clusters::Cluster.count }.by(1)
+ .and change { Clusters::Providers::Gcp.count }.by(1)
+
+ expect(subject.name).to eq('test-cluster')
+ expect(subject.user).to eq(user)
+ expect(subject.project).to eq(project)
+ expect(subject.provider.gcp_project_id).to eq('gcp-project')
+ expect(subject.provider.zone).to eq('us-central1-a')
+ expect(subject.provider.num_nodes).to eq(1)
+ expect(subject.provider.machine_type).to eq('machine_type-a')
+ expect(subject.provider.access_token).to eq(access_token)
+ expect(subject.provider).to be_legacy_abac
+ expect(subject.platform).to be_nil
+ expect(subject.namespace_per_environment).to eq false
+ end
end
end
diff --git a/yarn.lock b/yarn.lock
index acf1a4d8652..b35f23c2791 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1687,6 +1687,14 @@ anymatch@^2.0.0:
micromatch "^3.1.4"
normalize-path "^2.1.1"
+anymatch@^3.0.1:
+ version "3.0.3"
+ resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.0.3.tgz#2fb624fe0e84bccab00afee3d0006ed310f22f09"
+ integrity sha512-c6IvoeBECQlMVuYUjSwimnhmztImpErfxJzWZhIQinIvQWoGOnB0dLIgifbPHQt5heS6mNlaZG16f06H3C8t1g==
+ dependencies:
+ normalize-path "^3.0.0"
+ picomatch "^2.0.4"
+
apollo-cache-inmemory@^1.5.1:
version "1.5.1"
resolved "https://registry.yarnpkg.com/apollo-cache-inmemory/-/apollo-cache-inmemory-1.5.1.tgz#265d1ee67b0bf0aca9c37629d410bfae44e62953"
@@ -1857,11 +1865,6 @@ array-flatten@^2.1.0:
resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-2.1.1.tgz#426bb9da84090c1838d812c8150af20a8331e296"
integrity sha1-Qmu52oQJDBg42BLIFQryCoMx4pY=
-array-slice@^0.2.3:
- version "0.2.3"
- resolved "https://registry.yarnpkg.com/array-slice/-/array-slice-0.2.3.tgz#dd3cfb80ed7973a75117cdac69b0b99ec86186f5"
- integrity sha1-3Tz7gO15c6dRF82sabC5nshhhvU=
-
array-union@^1.0.1, array-union@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39"
@@ -1874,11 +1877,6 @@ array-uniq@^1.0.1, array-uniq@^1.0.2:
resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6"
integrity sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=
-array-unique@^0.2.1:
- version "0.2.1"
- resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.2.1.tgz#a1d97ccafcbc2625cc70fadceb36a50c58b01a53"
- integrity sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=
-
array-unique@^0.3.2:
version "0.3.2"
resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428"
@@ -1952,12 +1950,12 @@ async@^1.5.2:
resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a"
integrity sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=
-async@^2.0.0, async@^2.6.1:
- version "2.6.2"
- resolved "https://registry.yarnpkg.com/async/-/async-2.6.2.tgz#18330ea7e6e313887f5d2f2a904bac6fe4dd5381"
- integrity sha512-H1qVYh1MYhEEFLsP97cVKqCGo7KfCyTt6uEWqsTBr9SO84oK9Uwbyd/yCW+6rKJLHksBNUVWZDAjfS+Ccx0Bbg==
+async@^2.6.2:
+ version "2.6.3"
+ resolved "https://registry.yarnpkg.com/async/-/async-2.6.3.tgz#d72625e2344a3656e3a3ad4fa749fa83299d82ff"
+ integrity sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==
dependencies:
- lodash "^4.17.11"
+ lodash "^4.17.14"
asynckit@^0.4.0:
version "0.4.0"
@@ -2189,6 +2187,11 @@ binary-extensions@^1.0.0:
resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.11.0.tgz#46aa1751fb6a2f93ee5e689bb1087d4b14c6c205"
integrity sha1-RqoXUftqL5PuXmibsQh9SxTGwgU=
+binary-extensions@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.0.0.tgz#23c0df14f6a88077f5f986c0d167ec03c3d5537c"
+ integrity sha512-Phlt0plgpIIBOGTT/ehfFnbNlfsDEiqmzE2KRXoX1bLIlir4X/MR+zSyBEkL05ffWgnRSf/DXv+WrUAVr93/ow==
+
binaryextensions@2:
version "2.1.1"
resolved "https://registry.yarnpkg.com/binaryextensions/-/binaryextensions-2.1.1.tgz#3209a51ca4a4ad541a3b8d3d6a6d5b83a2485935"
@@ -2291,13 +2294,6 @@ brace-expansion@^1.1.7, brace-expansion@^1.1.8:
balanced-match "^1.0.0"
concat-map "0.0.1"
-braces@^0.1.2:
- version "0.1.5"
- resolved "https://registry.yarnpkg.com/braces/-/braces-0.1.5.tgz#c085711085291d8b75fdd74eab0f8597280711e6"
- integrity sha1-wIVxEIUpHYt1/ddOqw+FlygHEeY=
- dependencies:
- expand-range "^0.1.0"
-
braces@^2.3.0, braces@^2.3.1:
version "2.3.2"
resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729"
@@ -2314,7 +2310,7 @@ braces@^2.3.0, braces@^2.3.1:
split-string "^3.0.2"
to-regex "^3.0.1"
-braces@^3.0.1:
+braces@^3.0.1, braces@^3.0.2:
version "3.0.2"
resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107"
integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==
@@ -2735,7 +2731,7 @@ check-types@^7.3.0:
resolved "https://registry.yarnpkg.com/check-types/-/check-types-7.3.0.tgz#468f571a4435c24248f5fd0cb0e8d87c3c341e7d"
integrity sha1-Ro9XGkQ1wkJI9f0MsOjYfDw0Hn0=
-chokidar@^2.0.0, chokidar@^2.0.2, chokidar@^2.0.3, chokidar@^2.0.4:
+chokidar@^2.0.0, chokidar@^2.0.2, chokidar@^2.0.4:
version "2.0.4"
resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.0.4.tgz#356ff4e2b0e8e43e322d18a372460bbcf3accd26"
integrity sha512-z9n7yt9rOvIJrMhvDtDictKrkFHeihkNl6uWMmZlmL6tJtX9Cs+87oK+teBx+JIgzvbX3yZHT3eF8vpbDxHJXQ==
@@ -2755,6 +2751,21 @@ chokidar@^2.0.0, chokidar@^2.0.2, chokidar@^2.0.3, chokidar@^2.0.4:
optionalDependencies:
fsevents "^1.2.2"
+chokidar@^3.0.0:
+ version "3.0.2"
+ resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.0.2.tgz#0d1cd6d04eb2df0327446188cd13736a3367d681"
+ integrity sha512-c4PR2egjNjI1um6bamCQ6bUNPDiyofNQruHvKgHQ4gDUP/ITSVSzNsiI5OWtHOsX323i5ha/kk4YmOZ1Ktg7KA==
+ dependencies:
+ anymatch "^3.0.1"
+ braces "^3.0.2"
+ glob-parent "^5.0.0"
+ is-binary-path "^2.1.0"
+ is-glob "^4.0.1"
+ normalize-path "^3.0.0"
+ readdirp "^3.1.1"
+ optionalDependencies:
+ fsevents "^2.0.6"
+
chownr@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.1.tgz#54726b8b8fff4df053c42187e801fb4412df1494"
@@ -2790,11 +2801,6 @@ circular-json@^0.3.1:
resolved "https://registry.yarnpkg.com/circular-json/-/circular-json-0.3.3.tgz#815c99ea84f6809529d2f45791bdf82711352d66"
integrity sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A==
-circular-json@^0.5.5:
- version "0.5.5"
- resolved "https://registry.yarnpkg.com/circular-json/-/circular-json-0.5.5.tgz#64182ef359042d37cd8e767fc9de878b1e9447d3"
- integrity sha512-13YaR6kiz0kBNmIVM87Io8Hp7bWOo4r61vkEANy8iH9R9bc6avud/1FT0SBpqR1RpIQADOh/Q+yHZDA1iL6ysA==
-
class-utils@^0.3.5:
version "0.3.6"
resolved "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463"
@@ -2866,6 +2872,15 @@ clone-buffer@^1.0.0:
resolved "https://registry.yarnpkg.com/clone-buffer/-/clone-buffer-1.0.0.tgz#e3e25b207ac4e701af721e2cb5a16792cac3dc58"
integrity sha1-4+JbIHrE5wGvch4staFnksrD3Fg=
+clone-deep@^4.0.1:
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/clone-deep/-/clone-deep-4.0.1.tgz#c19fd9bdbbf85942b4fd979c84dcf7d5f07c2387"
+ integrity sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==
+ dependencies:
+ is-plain-object "^2.0.4"
+ kind-of "^6.0.2"
+ shallow-clone "^3.0.0"
+
clone-regexp@^2.1.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/clone-regexp/-/clone-regexp-2.2.0.tgz#7d65e00885cd8796405c35a737e7a86b7429e36f"
@@ -2968,13 +2983,6 @@ colors@^1.1.0:
resolved "https://registry.yarnpkg.com/colors/-/colors-1.3.3.tgz#39e005d546afe01e01f9c4ca8fa50f686a01205d"
integrity sha512-mmGt/1pZqYRjMxB1axhTo16/snVZ5krrKkcmMeVKxzECMMXoCgnvTPp10QgHfcbQZw8Dq2jMNG6je4JlWU0gWg==
-combine-lists@^1.0.0:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/combine-lists/-/combine-lists-1.0.1.tgz#458c07e09e0d900fc28b70a3fec2dacd1d2cb7f6"
- integrity sha1-RYwH4J4NkA/Ci3Cj/sLazR0st/Y=
- dependencies:
- lodash "^4.5.0"
-
combined-stream@^1.0.6, combined-stream@~1.0.6:
version "1.0.7"
resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.7.tgz#2d1d24317afb8abe95d6d2c0b07b57813539d828"
@@ -3002,10 +3010,10 @@ commondir@^1.0.1:
resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b"
integrity sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=
-compare-versions@^3.2.1:
- version "3.4.0"
- resolved "https://registry.yarnpkg.com/compare-versions/-/compare-versions-3.4.0.tgz#e0747df5c9cb7f054d6d3dc3e1dbc444f9e92b26"
- integrity sha512-tK69D7oNXXqUW3ZNo/z7NXTEz22TCF0pTE+YF9cxvaAM9XnkLo1fV621xCLrRR6aevJlKxExkss0vWqUCUpqdg==
+compare-versions@^3.4.0:
+ version "3.5.1"
+ resolved "https://registry.yarnpkg.com/compare-versions/-/compare-versions-3.5.1.tgz#26e1f5cf0d48a77eced5046b9f67b6b61075a393"
+ integrity sha512-9fGPIB7C6AyM18CJJBHt5EnCZDG3oiTJYy0NjfIAGjKpzv0tkxWko7TNQHF5ymqm7IH03tqmeuBxtvD+Izh6mg==
component-bind@1.0.0:
version "1.0.0"
@@ -3235,16 +3243,16 @@ core-js-pure@3.1.4:
resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.1.4.tgz#5fa17dc77002a169a3566cc48dc774d2e13e3769"
integrity sha512-uJ4Z7iPNwiu1foygbcZYJsJs1jiXrTTCvxfLDXNhI/I+NHbSIEyr548y4fcsCEyWY0XgfAG/qqaunJ1SThHenA==
-core-js@^2.2.0, core-js@~2.3.0:
- version "2.3.0"
- resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.3.0.tgz#fab83fbb0b2d8dc85fa636c4b9d34c75420c6d65"
- integrity sha1-+rg/uwstjchfpjbEudNMdUIMbWU=
-
core-js@^3.1.3:
version "3.1.3"
resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.1.3.tgz#95700bca5f248f5f78c0ec63e784eca663ec4138"
integrity sha512-PWZ+ZfuaKf178BIAg+CRsljwjIMRV8MY00CbZczkR6Zk5LfkSkjGoaab3+bqRQWVITNZxQB7TFYz+CFcyuamvA==
+core-js@~2.3.0:
+ version "2.3.0"
+ resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.3.0.tgz#fab83fbb0b2d8dc85fa636c4b9d34c75420c6d65"
+ integrity sha1-+rg/uwstjchfpjbEudNMdUIMbWU=
+
core-util-is@1.0.2, core-util-is@~1.0.0:
version "1.0.2"
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
@@ -3799,10 +3807,10 @@ data-urls@^1.0.0:
whatwg-mimetype "^2.2.0"
whatwg-url "^7.0.0"
-date-format@^1.2.0:
- version "1.2.0"
- resolved "https://registry.yarnpkg.com/date-format/-/date-format-1.2.0.tgz#615e828e233dd1ab9bb9ae0950e0ceccfa6ecad8"
- integrity sha1-YV6CjiM90aubua4JUODOzPpuytg=
+date-format@^2.0.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/date-format/-/date-format-2.1.0.tgz#31d5b5ea211cf5fd764cd38baf9d033df7e125cf"
+ integrity sha512-bYQuGLeFxhkxNOF3rcMtiZxvCBAquGzZm6oWA1oZ0g2THUzivaRhv8uOhdr19LmoobSOLoIAxeUK2RdbM8IFTA==
date-now@^0.1.4:
version "0.1.4"
@@ -4862,15 +4870,6 @@ exit@^0.1.2:
resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c"
integrity sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=
-expand-braces@^0.1.1:
- version "0.1.2"
- resolved "https://registry.yarnpkg.com/expand-braces/-/expand-braces-0.1.2.tgz#488b1d1d2451cb3d3a6b192cfc030f44c5855fea"
- integrity sha1-SIsdHSRRyz06axks/AMPRMWFX+o=
- dependencies:
- array-slice "^0.2.3"
- array-unique "^0.2.1"
- braces "^0.1.2"
-
expand-brackets@^2.1.4:
version "2.1.4"
resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622"
@@ -4884,14 +4883,6 @@ expand-brackets@^2.1.4:
snapdragon "^0.8.1"
to-regex "^3.0.1"
-expand-range@^0.1.0:
- version "0.1.1"
- resolved "https://registry.yarnpkg.com/expand-range/-/expand-range-0.1.1.tgz#4cb8eda0993ca56fa4f41fc42f3cbb4ccadff044"
- integrity sha1-TLjtoJk8pW+k9B/ELzy7TMrf8EQ=
- dependencies:
- is-number "^0.1.1"
- repeat-string "^0.2.2"
-
expand-tilde@^2.0.0, expand-tilde@^2.0.2:
version "2.0.2"
resolved "https://registry.yarnpkg.com/expand-tilde/-/expand-tilde-2.0.2.tgz#97e801aa052df02454de46b02bf621642cdc8502"
@@ -5315,12 +5306,14 @@ from2@^2.1.0, from2@^2.1.1:
inherits "^2.0.1"
readable-stream "^2.0.0"
-fs-access@^1.0.0:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/fs-access/-/fs-access-1.0.1.tgz#d6a87f262271cefebec30c553407fb995da8777a"
- integrity sha1-1qh/JiJxzv6+wwxVNAf7mV2od3o=
+fs-extra@^7.0.1:
+ version "7.0.1"
+ resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-7.0.1.tgz#4f189c44aa123b895f722804f55ea23eadc348e9"
+ integrity sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==
dependencies:
- null-check "^1.0.0"
+ graceful-fs "^4.1.2"
+ jsonfile "^4.0.0"
+ universalify "^0.1.0"
fs-minipass@^1.2.5:
version "1.2.6"
@@ -5360,6 +5353,11 @@ fsevents@^1.2.2, fsevents@^1.2.7:
nan "^2.12.1"
node-pre-gyp "^0.12.0"
+fsevents@^2.0.6:
+ version "2.0.7"
+ resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.0.7.tgz#382c9b443c6cbac4c57187cdda23aa3bf1ccfc2a"
+ integrity sha512-a7YT0SV3RB+DjYcppwVDLtn13UQnmg0SWZS7ezZD0UjnLwXmy8Zm21GMVGLaFGimIqcvyMQaOJBrop8MyOp1kQ==
+
fstream@^1.0.0, fstream@^1.0.12:
version "1.0.12"
resolved "https://registry.yarnpkg.com/fstream/-/fstream-1.0.12.tgz#4e8ba8ee2d48be4f7d0de505455548eae5932045"
@@ -5514,6 +5512,13 @@ glob-parent@^3.1.0:
is-glob "^3.1.0"
path-dirname "^1.0.0"
+glob-parent@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.0.0.tgz#1dc99f0f39b006d3e92c2c284068382f0c20e954"
+ integrity sha512-Z2RwiujPRGluePM6j699ktJYxmPpJKCfpGA13jz2hmFZC7gKetzrWvg5KN3+OsIFmydGyZ1AVwERCq1w/ZZwRg==
+ dependencies:
+ is-glob "^4.0.1"
+
glob-stream@^6.1.0:
version "6.1.0"
resolved "https://registry.yarnpkg.com/glob-stream/-/glob-stream-6.1.0.tgz#7045c99413b3eb94888d83ab46d0b404cc7bdde4"
@@ -6382,6 +6387,13 @@ is-binary-path@^1.0.0:
dependencies:
binary-extensions "^1.0.0"
+is-binary-path@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09"
+ integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==
+ dependencies:
+ binary-extensions "^2.0.0"
+
is-buffer@^1.1.4, is-buffer@^1.1.5, is-buffer@~1.1.1:
version "1.1.6"
resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be"
@@ -6541,11 +6553,6 @@ is-npm@^1.0.0:
resolved "https://registry.yarnpkg.com/is-npm/-/is-npm-1.0.0.tgz#f2fb63a65e4905b406c86072765a1a4dc793b9f4"
integrity sha1-8vtjpl5JBbQGyGBydloaTceTufQ=
-is-number@^0.1.1:
- version "0.1.1"
- resolved "https://registry.yarnpkg.com/is-number/-/is-number-0.1.1.tgz#69a7af116963d47206ec9bd9b48a14216f1e3806"
- integrity sha1-aaevEWlj1HIG7JvZtIoUIW8eOAY=
-
is-number@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195"
@@ -6741,38 +6748,38 @@ isstream@~0.1.2:
resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a"
integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=
-istanbul-api@^2.0.5:
- version "2.1.1"
- resolved "https://registry.yarnpkg.com/istanbul-api/-/istanbul-api-2.1.1.tgz#194b773f6d9cbc99a9258446848b0f988951c4d0"
- integrity sha512-kVmYrehiwyeBAk/wE71tW6emzLiHGjYIiDrc8sfyty4F8M02/lrgXSm+R1kXysmF20zArvmZXjlE/mg24TVPJw==
+istanbul-api@^2.1.6:
+ version "2.1.6"
+ resolved "https://registry.yarnpkg.com/istanbul-api/-/istanbul-api-2.1.6.tgz#d61702a9d1c66ad89d92e66d401e16b0bda4a35f"
+ integrity sha512-x0Eicp6KsShG1k1rMgBAi/1GgY7kFGEBwQpw3PXGEmu+rBcBNhqU8g2DgY9mlepAsLPzrzrbqSgCGANnki4POA==
dependencies:
- async "^2.6.1"
- compare-versions "^3.2.1"
+ async "^2.6.2"
+ compare-versions "^3.4.0"
fileset "^2.0.3"
- istanbul-lib-coverage "^2.0.3"
- istanbul-lib-hook "^2.0.3"
- istanbul-lib-instrument "^3.1.0"
- istanbul-lib-report "^2.0.4"
- istanbul-lib-source-maps "^3.0.2"
- istanbul-reports "^2.1.1"
- js-yaml "^3.12.0"
- make-dir "^1.3.0"
+ istanbul-lib-coverage "^2.0.5"
+ istanbul-lib-hook "^2.0.7"
+ istanbul-lib-instrument "^3.3.0"
+ istanbul-lib-report "^2.0.8"
+ istanbul-lib-source-maps "^3.0.6"
+ istanbul-reports "^2.2.4"
+ js-yaml "^3.13.1"
+ make-dir "^2.1.0"
minimatch "^3.0.4"
once "^1.4.0"
-istanbul-lib-coverage@^2.0.2, istanbul-lib-coverage@^2.0.3, istanbul-lib-coverage@^2.0.5:
+istanbul-lib-coverage@^2.0.2, istanbul-lib-coverage@^2.0.5:
version "2.0.5"
resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.5.tgz#675f0ab69503fad4b1d849f736baaca803344f49"
integrity sha512-8aXznuEPCJvGnMSRft4udDRDtb1V3pkQkMMI5LI+6HuQz5oQ4J2UFn1H82raA3qJtyOLkkwVqICBQkjnGtn5mA==
-istanbul-lib-hook@^2.0.3:
+istanbul-lib-hook@^2.0.7:
version "2.0.7"
resolved "https://registry.yarnpkg.com/istanbul-lib-hook/-/istanbul-lib-hook-2.0.7.tgz#c95695f383d4f8f60df1f04252a9550e15b5b133"
integrity sha512-vrRztU9VRRFDyC+aklfLoeXyNdTfga2EI3udDGn4cZ6fpSXpHLV9X6CHvfoMCPtggg8zvDDmC4b9xfu0z6/llA==
dependencies:
append-transform "^1.0.0"
-istanbul-lib-instrument@^3.0.0, istanbul-lib-instrument@^3.0.1, istanbul-lib-instrument@^3.1.0:
+istanbul-lib-instrument@^3.0.0, istanbul-lib-instrument@^3.0.1, istanbul-lib-instrument@^3.3.0:
version "3.3.0"
resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-3.3.0.tgz#a5f63d91f0bbc0c3e479ef4c5de027335ec6d630"
integrity sha512-5nnIN4vo5xQZHdXno/YDXJ0G+I3dAm4XgzfSVTPLQpj/zAV2dV6Juy0yaf10/zrJOJeHoN3fraFe+XRq2bFVZA==
@@ -6785,7 +6792,7 @@ istanbul-lib-instrument@^3.0.0, istanbul-lib-instrument@^3.0.1, istanbul-lib-ins
istanbul-lib-coverage "^2.0.5"
semver "^6.0.0"
-istanbul-lib-report@^2.0.4:
+istanbul-lib-report@^2.0.4, istanbul-lib-report@^2.0.8:
version "2.0.8"
resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-2.0.8.tgz#5a8113cd746d43c4889eba36ab10e7d50c9b4f33"
integrity sha512-fHBeG573EIihhAblwgxrSenp0Dby6tJMFR/HvlerBsrCTD5bkUuoNtn3gVh29ZCS824cGGBPn7Sg7cNk+2xUsQ==
@@ -6794,7 +6801,7 @@ istanbul-lib-report@^2.0.4:
make-dir "^2.1.0"
supports-color "^6.1.0"
-istanbul-lib-source-maps@^3.0.1, istanbul-lib-source-maps@^3.0.2:
+istanbul-lib-source-maps@^3.0.1, istanbul-lib-source-maps@^3.0.6:
version "3.0.6"
resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-3.0.6.tgz#284997c48211752ec486253da97e3879defba8c8"
integrity sha512-R47KzMtDJH6X4/YW9XTx+jrLnZnscW4VpNN+1PViSYTejLVPWv7oov+Duf8YQSPyVRUvueQqz1TcsC6mooZTXw==
@@ -6805,7 +6812,7 @@ istanbul-lib-source-maps@^3.0.1, istanbul-lib-source-maps@^3.0.2:
rimraf "^2.6.3"
source-map "^0.6.1"
-istanbul-reports@^2.1.1:
+istanbul-reports@^2.1.1, istanbul-reports@^2.2.4:
version "2.2.6"
resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-2.2.6.tgz#7b4f2660d82b29303a8fe6091f8ca4bf058da1af"
integrity sha512-SKi4rnMyLBKe0Jy2uUdx28h8oG7ph2PPuQPvIAh31d+Ci+lSiEu4C+h3oBPuJ9+mPKhOyW0M8gY4U5NM1WLeXA==
@@ -7415,6 +7422,13 @@ json5@^1.0.1:
dependencies:
minimist "^1.2.0"
+jsonfile@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb"
+ integrity sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=
+ optionalDependencies:
+ graceful-fs "^4.1.6"
+
jsonparse@^1.2.0:
version "1.3.1"
resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-1.3.1.tgz#3f4dae4a91fac315f71062f8521cc239f1366280"
@@ -7446,20 +7460,19 @@ jszip@^3.1.3:
pako "~1.0.2"
readable-stream "~2.0.6"
-karma-chrome-launcher@^2.2.0:
- version "2.2.0"
- resolved "https://registry.yarnpkg.com/karma-chrome-launcher/-/karma-chrome-launcher-2.2.0.tgz#cf1b9d07136cc18fe239327d24654c3dbc368acf"
- integrity sha512-uf/ZVpAabDBPvdPdveyk1EPgbnloPvFFGgmRhYLTDH7gEB4nZdSBk8yTU47w1g/drLSx5uMOkjKk7IWKfWg/+w==
+karma-chrome-launcher@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/karma-chrome-launcher/-/karma-chrome-launcher-3.0.0.tgz#5c3a7f877a304e90781c28fcd9a49e334a890f42"
+ integrity sha512-u/PnVgDOP97AUe/gJeABlC6Wa6aQ83MZsm0JgsJQ5bGQ9XcXON/7b2aRhl59A62Zom+q3PFveBkczc7E1RT7TA==
dependencies:
- fs-access "^1.0.0"
which "^1.2.1"
-karma-coverage-istanbul-reporter@^2.0.4:
- version "2.0.4"
- resolved "https://registry.yarnpkg.com/karma-coverage-istanbul-reporter/-/karma-coverage-istanbul-reporter-2.0.4.tgz#402ae4ed6eadb9d9dafbd408ffda17897c0d003a"
- integrity sha512-xJS7QSQIVU6VK9HuJ/ieE5yynxKhjCCkd96NLY/BX/HXsx0CskU9JJiMQbd4cHALiddMwI4OWh1IIzeWrsavJw==
+karma-coverage-istanbul-reporter@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/karma-coverage-istanbul-reporter/-/karma-coverage-istanbul-reporter-2.1.0.tgz#5f1bcc13c5e14ee1d91821ee8946861674f54c75"
+ integrity sha512-UH0mXPJFJyK5uiK7EkwGtQ8f30lCBAfqRResnZ4pzLJ04SOp4SPlYkmwbbZ6iVJ6sQFVzlDUXlntBEsLRdgZpg==
dependencies:
- istanbul-api "^2.0.5"
+ istanbul-api "^2.1.6"
minimatch "^3.0.4"
karma-jasmine@^1.1.2:
@@ -7491,38 +7504,39 @@ karma-sourcemap-loader@^0.3.7:
dependencies:
graceful-fs "^4.1.2"
-karma-webpack@^4.0.0-beta.0:
- version "4.0.0-rc.2"
- resolved "https://registry.yarnpkg.com/karma-webpack/-/karma-webpack-4.0.0-rc.2.tgz#4c194e94789842af7f0ffa0de77ee7715739c7c1"
- integrity sha512-Wuiq/xFBsbJMsHhYy5SYXxSp7Q0b8uzAG8+Siuo56ntoi5GluPE5LK3Mzl2UtD4k1leFwL6IeIE6Q+tk4F6k9Q==
+karma-webpack@^4.0.2:
+ version "4.0.2"
+ resolved "https://registry.yarnpkg.com/karma-webpack/-/karma-webpack-4.0.2.tgz#23219bd95bdda853e3073d3874d34447c77bced0"
+ integrity sha512-970/okAsdUOmiMOCY8sb17A2I8neS25Ad9uhyK3GHgmRSIFJbDcNEFE8dqqUhNe9OHiCC9k3DMrSmtd/0ymP1A==
dependencies:
- async "^2.0.0"
+ clone-deep "^4.0.1"
loader-utils "^1.1.0"
- lodash "^4.17.10"
- source-map "^0.5.6"
- webpack-dev-middleware "^3.2.0"
+ neo-async "^2.6.1"
+ schema-utils "^1.0.0"
+ source-map "^0.7.3"
+ webpack-dev-middleware "^3.7.0"
-karma@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/karma/-/karma-3.0.0.tgz#6da83461a8a28d8224575c3b5b874e271b4730c3"
- integrity sha512-ZTjyuDXVXhXsvJ1E4CnZzbCjSxD6sEdzEsFYogLuZM0yqvg/mgz+O+R1jb0J7uAQeuzdY8kJgx6hSNXLwFuHIQ==
+karma@^4.2.0:
+ version "4.2.0"
+ resolved "https://registry.yarnpkg.com/karma/-/karma-4.2.0.tgz#27e88b310cde090d016980ff5444e3a239196fca"
+ integrity sha512-fmCuxN1rwJxTdZfOXK5LjlmS4Ana/OvzNMpkyLL/TLE8hmgSkpVpMYQ7RTVa8TNKRVQDZNl5W1oF5cfKfgIMlA==
dependencies:
bluebird "^3.3.0"
body-parser "^1.16.1"
- chokidar "^2.0.3"
+ braces "^3.0.2"
+ chokidar "^3.0.0"
colors "^1.1.0"
- combine-lists "^1.0.0"
connect "^3.6.0"
- core-js "^2.2.0"
+ core-js "^3.1.3"
di "^0.0.1"
dom-serialize "^2.2.0"
- expand-braces "^0.1.1"
+ flatted "^2.0.0"
glob "^7.1.1"
graceful-fs "^4.1.2"
http-proxy "^1.13.0"
isbinaryfile "^3.0.0"
- lodash "^4.17.4"
- log4js "^3.0.0"
+ lodash "^4.17.11"
+ log4js "^4.0.0"
mime "^2.3.1"
minimatch "^3.0.2"
optimist "^0.6.1"
@@ -7533,7 +7547,7 @@ karma@^3.0.0:
socket.io "2.1.1"
source-map "^0.6.1"
tmp "0.0.33"
- useragent "2.2.1"
+ useragent "2.3.0"
katex@^0.10.0:
version "0.10.0"
@@ -7788,7 +7802,7 @@ lodash.upperfirst@4.3.1:
resolved "https://registry.yarnpkg.com/lodash.upperfirst/-/lodash.upperfirst-4.3.1.tgz#1365edf431480481ef0d1c68957a5ed99d49f7ce"
integrity sha1-E2Xt9DFIBIHvDRxolXpe2Z1J984=
-lodash@^4.0.0, lodash@^4.13.1, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.4, lodash@^4.17.5, lodash@^4.5.0, lodash@~4.17.10:
+lodash@^4.0.0, lodash@^4.13.1, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.4, lodash@^4.17.5, lodash@~4.17.10:
version "4.17.15"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548"
integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==
@@ -7807,16 +7821,16 @@ log-symbols@^3.0.0:
dependencies:
chalk "^2.4.2"
-log4js@^3.0.0:
- version "3.0.5"
- resolved "https://registry.yarnpkg.com/log4js/-/log4js-3.0.5.tgz#b80146bfebad68b430d4f3569556d8a6edfef303"
- integrity sha512-IX5c3G/7fuTtdr0JjOT2OIR12aTESVhsH6cEsijloYwKgcPRlO6DgOU72v0UFhWcoV1HN6+M3dwT89qVPLXm0w==
+log4js@^4.0.0:
+ version "4.5.1"
+ resolved "https://registry.yarnpkg.com/log4js/-/log4js-4.5.1.tgz#e543625e97d9e6f3e6e7c9fc196dd6ab2cae30b5"
+ integrity sha512-EEEgFcE9bLgaYUKuozyFfytQM2wDHtXn4tAN41pkaxpNjAykv11GVdeI4tHtmPWW4Xrgh9R/2d7XYghDVjbKKw==
dependencies:
- circular-json "^0.5.5"
- date-format "^1.2.0"
- debug "^3.1.0"
- rfdc "^1.1.2"
- streamroller "0.7.0"
+ date-format "^2.0.0"
+ debug "^4.1.1"
+ flatted "^2.0.0"
+ rfdc "^1.1.4"
+ streamroller "^1.0.6"
loglevel@^1.4.1:
version "1.4.1"
@@ -7861,15 +7875,10 @@ lowlight@^1.11.0:
fault "^1.0.2"
highlight.js "~9.13.0"
-lru-cache@2.2.x:
- version "2.2.4"
- resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-2.2.4.tgz#6c658619becf14031d0d0b594b16042ce4dc063d"
- integrity sha1-bGWGGb7PFAMdDQtZSxYELOTcBj0=
-
-lru-cache@^4.0.1, lru-cache@^4.1.2, lru-cache@^4.1.3:
- version "4.1.3"
- resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.3.tgz#a1175cf3496dfc8436c156c334b4955992bce69c"
- integrity sha512-fFEhvcgzuIoJVUF8fYr5KR0YqxD238zgObTps31YdADwPPAp82a4M8TrckkWyx7ekNlf9aBcVn81cFwwXngrJA==
+lru-cache@4.1.x, lru-cache@^4.0.1, lru-cache@^4.1.2, lru-cache@^4.1.3:
+ version "4.1.5"
+ resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.5.tgz#8bbe50ea85bed59bc9e33dcab8235ee9bcf443cd"
+ integrity sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==
dependencies:
pseudomap "^1.0.2"
yallist "^2.1.2"
@@ -7886,7 +7895,7 @@ lz-string@^1.4.4:
resolved "https://registry.yarnpkg.com/lz-string/-/lz-string-1.4.4.tgz#c0d8eaf36059f705796e1e344811cf4c498d3a26"
integrity sha1-wNjq82BZ9wV5bh40SBHPTEmNOiY=
-make-dir@^1.0.0, make-dir@^1.3.0:
+make-dir@^1.0.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-1.3.0.tgz#79c1033b80515bd6d24ec9933e860ca75ee27f0c"
integrity sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==
@@ -8072,7 +8081,7 @@ memory-fs@^0.2.0:
resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.2.0.tgz#f2bb25368bc121e391c2520de92969caee0a0290"
integrity sha1-8rslNovBIeORwlIN6Slpyu4KApA=
-memory-fs@^0.4.0, memory-fs@~0.4.1:
+memory-fs@^0.4.0, memory-fs@^0.4.1, memory-fs@~0.4.1:
version "0.4.1"
resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.4.1.tgz#3a9a20b8462523e447cfbc7e8bb80ed667bfc552"
integrity sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=
@@ -8210,7 +8219,7 @@ mime@1.4.1:
resolved "https://registry.yarnpkg.com/mime/-/mime-1.4.1.tgz#121f9ebc49e3766f311a76e1fa1c8003c4b03aa6"
integrity sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==
-mime@^2.0.3, mime@^2.2.0, mime@^2.3.1:
+mime@^2.0.3, mime@^2.2.0, mime@^2.3.1, mime@^2.4.2:
version "2.4.4"
resolved "https://registry.yarnpkg.com/mime/-/mime-2.4.4.tgz#bd7b91135fc6b01cde3e9bae33d659b63d8857e5"
integrity sha512-LRxmNwziLPT828z+4YkNzloCFC2YM4wrB99k+AV5ZbEyfGNWfG8SO1FUXLmLDBSo89NrJZ4DIWeLjy1CHGhMGA==
@@ -8457,10 +8466,10 @@ negotiator@0.6.1:
resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.1.tgz#2b327184e8992101177b28563fb5e7102acd0ca9"
integrity sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=
-neo-async@^2.5.0, neo-async@^2.6.0:
- version "2.6.0"
- resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.0.tgz#b9d15e4d71c6762908654b5183ed38b753340835"
- integrity sha512-MFh0d/Wa7vkKO3Y3LlacqAEeHK0mckVqzDieUKTT+KGxi+zIpeVsFxymkIiRpbpDziHc290Xr9A1O4Om7otoRA==
+neo-async@^2.5.0, neo-async@^2.6.0, neo-async@^2.6.1:
+ version "2.6.1"
+ resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.1.tgz#ac27ada66167fa8849a6addd837f6b189ad2081c"
+ integrity sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw==
nice-try@^1.0.4:
version "1.0.5"
@@ -8729,11 +8738,6 @@ npm-run-path@^2.0.0:
gauge "~2.7.3"
set-blocking "~2.0.0"
-null-check@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/null-check/-/null-check-1.0.0.tgz#977dffd7176012b9ec30d2a39db5cf72a0439edd"
- integrity sha1-l33/1xdgErnsMNKjnbXPcqBDnt0=
-
num2fraction@^1.2.2:
version "1.2.2"
resolved "https://registry.yarnpkg.com/num2fraction/-/num2fraction-1.2.2.tgz#6f682b6a027a4e9ddfa4564cd2589d1d4e669ede"
@@ -9288,7 +9292,7 @@ performance-now@^2.1.0:
resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b"
integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=
-picomatch@^2.0.5:
+picomatch@^2.0.4, picomatch@^2.0.5:
version "2.0.7"
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.0.7.tgz#514169d8c7cd0bdbeecc8a2609e34a7163de69f6"
integrity sha512-oLHIdio3tZ0qH76NybpeneBhYVj0QFTfXEFTc/B3zKQspYfYYkWYgFsmzo+4kvId/bQRcNkVeguI3y+CD22BtA==
@@ -9918,10 +9922,10 @@ randomfill@^1.0.3:
randombytes "^2.0.5"
safe-buffer "^5.1.0"
-range-parser@^1.0.3, range-parser@^1.2.0, range-parser@~1.2.0:
- version "1.2.0"
- resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.0.tgz#f49be6b487894ddc40dcc94a322f611092e00d5e"
- integrity sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=
+range-parser@^1.0.3, range-parser@^1.2.0, range-parser@^1.2.1, range-parser@~1.2.0:
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031"
+ integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==
raphael@^2.2.7:
version "2.2.7"
@@ -10035,7 +10039,7 @@ read-pkg@^3.0.0:
normalize-package-data "^2.3.2"
path-type "^3.0.0"
-"readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.5, readable-stream@^2.0.6, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.0, readable-stream@^2.3.3, readable-stream@^2.3.5, readable-stream@^2.3.6, readable-stream@~2.3.6:
+"readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.5, readable-stream@^2.0.6, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.3, readable-stream@^2.3.5, readable-stream@^2.3.6, readable-stream@~2.3.6:
version "2.3.6"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf"
integrity sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==
@@ -10100,6 +10104,13 @@ readdirp@^2.0.0:
readable-stream "^2.0.2"
set-immediate-shim "^1.0.1"
+readdirp@^3.1.1:
+ version "3.1.1"
+ resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.1.1.tgz#b158123ac343c8b0f31d65680269cc0fc1025db1"
+ integrity sha512-XXdSXZrQuvqoETj50+JAitxz1UPdt5dupjT6T5nVB+WvjMv2XKYj+s7hPeAVCXvmJrL36O4YYyWlIC3an2ePiQ==
+ dependencies:
+ picomatch "^2.0.4"
+
realpath-native@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/realpath-native/-/realpath-native-1.1.0.tgz#2003294fea23fb0672f2476ebe22fcf498a2d65c"
@@ -10393,11 +10404,6 @@ repeat-element@^1.1.2:
resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.3.tgz#782e0d825c0c5a3bb39731f84efee6b742e6b1ce"
integrity sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==
-repeat-string@^0.2.2:
- version "0.2.2"
- resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-0.2.2.tgz#c7a8d3236068362059a7e4651fc6884e8b1fb4ae"
- integrity sha1-x6jTI2BoNiBZp+RlH8aITosftK4=
-
repeat-string@^1.5.0, repeat-string@^1.5.4, repeat-string@^1.6.1:
version "1.6.1"
resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637"
@@ -10566,10 +10572,10 @@ ret@~0.1.10:
resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc"
integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==
-rfdc@^1.1.2:
- version "1.1.2"
- resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.1.2.tgz#e6e72d74f5dc39de8f538f65e00c36c18018e349"
- integrity sha512-92ktAgvZhBzYTIK0Mja9uen5q5J3NRVMoDkJL2VMwq6SXjVCgqvQeVP2XAaUY6HT+XpQYeLSjb3UoitBryKmdA==
+rfdc@^1.1.4:
+ version "1.1.4"
+ resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.1.4.tgz#ba72cc1367a0ccd9cf81a870b3b58bd3ad07f8c2"
+ integrity sha512-5C9HXdzK8EAqN7JDif30jqsBzavB7wLpaubisuQIGHWf2gUXSpzy6ArX/+Da8RjFpagWsCn+pIgxTMAmKw9Zug==
rimraf@2, rimraf@2.6.3, rimraf@^2.2.8, rimraf@^2.5.4, rimraf@^2.6.0, rimraf@^2.6.1, rimraf@^2.6.3:
version "2.6.3"
@@ -10878,6 +10884,13 @@ sha1@^1.1.1:
charenc ">= 0.0.1"
crypt ">= 0.0.1"
+shallow-clone@^3.0.0:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/shallow-clone/-/shallow-clone-3.0.1.tgz#8f2981ad92531f55035b01fb230769a40e02efa3"
+ integrity sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==
+ dependencies:
+ kind-of "^6.0.2"
+
shebang-command@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea"
@@ -11114,6 +11127,11 @@ source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.0, source-map@~0.6.1:
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==
+source-map@^0.7.3:
+ version "0.7.3"
+ resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.3.tgz#5302f8169031735226544092e64981f751750383"
+ integrity sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==
+
space-separated-tokens@^1.0.0:
version "1.1.4"
resolved "https://registry.yarnpkg.com/space-separated-tokens/-/space-separated-tokens-1.1.4.tgz#27910835ae00d0adfcdbd0ad7e611fb9544351fa"
@@ -11303,15 +11321,16 @@ stream-shift@^1.0.0:
resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.0.tgz#d5c752825e5367e786f78e18e445ea223a155952"
integrity sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=
-streamroller@0.7.0:
- version "0.7.0"
- resolved "https://registry.yarnpkg.com/streamroller/-/streamroller-0.7.0.tgz#a1d1b7cf83d39afb0d63049a5acbf93493bdf64b"
- integrity sha512-WREzfy0r0zUqp3lGO096wRuUp7ho1X6uo/7DJfTlEi0Iv/4gT7YHqXDjKC2ioVGBZtE8QzsQD9nx1nIuoZ57jQ==
+streamroller@^1.0.6:
+ version "1.0.6"
+ resolved "https://registry.yarnpkg.com/streamroller/-/streamroller-1.0.6.tgz#8167d8496ed9f19f05ee4b158d9611321b8cacd9"
+ integrity sha512-3QC47Mhv3/aZNFpDDVO44qQb9gwB9QggMEE0sQmkTAwBVYdBRWISdsywlkfm5II1Q5y/pmrHflti/IgmIzdDBg==
dependencies:
- date-format "^1.2.0"
- debug "^3.1.0"
- mkdirp "^0.5.1"
- readable-stream "^2.3.0"
+ async "^2.6.2"
+ date-format "^2.0.0"
+ debug "^3.2.6"
+ fs-extra "^7.0.1"
+ lodash "^4.17.14"
strict-uri-encode@^1.0.0:
version "1.1.0"
@@ -12284,6 +12303,11 @@ unist-util-visit@^1.0.0, unist-util-visit@^1.1.0, unist-util-visit@^1.3.0:
dependencies:
unist-util-visit-parents "^2.0.0"
+universalify@^0.1.0:
+ version "0.1.2"
+ resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66"
+ integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==
+
unpipe@1.0.0, unpipe@~1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec"
@@ -12394,12 +12418,12 @@ use@^3.1.0:
resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f"
integrity sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==
-useragent@2.2.1:
- version "2.2.1"
- resolved "https://registry.yarnpkg.com/useragent/-/useragent-2.2.1.tgz#cf593ef4f2d175875e8bb658ea92e18a4fd06d8e"
- integrity sha1-z1k+9PLRdYdei7ZY6pLhik/QbY4=
+useragent@2.3.0:
+ version "2.3.0"
+ resolved "https://registry.yarnpkg.com/useragent/-/useragent-2.3.0.tgz#217f943ad540cb2128658ab23fc960f6a88c9972"
+ integrity sha512-4AoH4pxuSvHCjqLO04sU6U/uE65BYza8l/KKBS0b0hnUPWi+cQ2BpeTEwejCSx9SPV5/U03nniDTrWx5NrmKdw==
dependencies:
- lru-cache "2.2.x"
+ lru-cache "4.1.x"
tmp "0.0.x"
util-deprecate@^1.0.1, util-deprecate@~1.0.1:
@@ -12781,7 +12805,7 @@ webpack-cli@^3.2.1:
v8-compile-cache "^2.0.2"
yargs "^12.0.4"
-webpack-dev-middleware@3.4.0, webpack-dev-middleware@^3.2.0:
+webpack-dev-middleware@3.4.0:
version "3.4.0"
resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-3.4.0.tgz#1132fecc9026fd90f0ecedac5cbff75d1fb45890"
integrity sha512-Q9Iyc0X9dP9bAsYskAVJ/hmIZZQwf/3Sy4xCAZgL5cUkjZmUZLt4l5HpbST/Pdgjn3u6pE7u5OdGd1apgzRujA==
@@ -12791,6 +12815,16 @@ webpack-dev-middleware@3.4.0, webpack-dev-middleware@^3.2.0:
range-parser "^1.0.3"
webpack-log "^2.0.0"
+webpack-dev-middleware@^3.7.0:
+ version "3.7.0"
+ resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-3.7.0.tgz#ef751d25f4e9a5c8a35da600c5fda3582b5c6cff"
+ integrity sha512-qvDesR1QZRIAZHOE3iQ4CXLZZSQ1lAUsSpnQmlB1PBfoN/xdRjmge3Dok0W4IdaVLJOGJy3sGI4sZHwjRU0PCA==
+ dependencies:
+ memory-fs "^0.4.1"
+ mime "^2.4.2"
+ range-parser "^1.2.1"
+ webpack-log "^2.0.0"
+
webpack-dev-server@^3.1.14:
version "3.1.14"
resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-3.1.14.tgz#60fb229b997fc5a0a1fc6237421030180959d469"