summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2019-09-18 14:14:39 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2019-09-18 14:14:39 +0000
commit1eb82b65c554f21d83447f895a6208905fabe112 (patch)
treeab12f01b3dc46f11c02afea1e470a78f06ca70c2
parent4ab54c2233e91f60a80e5b6fa2181e6899fdcc3e (diff)
downloadgitlab-ce-stable-branch-foss-test.tar.gz
Add latest changes from gitlab-org/gitlab@12-3-auto-deploy-20190916stable-branch-foss-test
-rw-r--r--.eslintrc.yml1
-rw-r--r--.gitlab-ci.yml1
-rw-r--r--.gitlab/ci/cng.gitlab-ci.yml5
-rw-r--r--.gitlab/ci/docs.gitlab-ci.yml39
-rw-r--r--.gitlab/ci/frontend.gitlab-ci.yml69
-rw-r--r--.gitlab/ci/global.gitlab-ci.yml95
-rw-r--r--.gitlab/ci/memory.gitlab-ci.yml14
-rw-r--r--.gitlab/ci/pages.gitlab-ci.yml7
-rw-r--r--.gitlab/ci/qa.gitlab-ci.yml21
-rw-r--r--.gitlab/ci/rails.gitlab-ci.yml214
-rw-r--r--.gitlab/ci/reports.gitlab-ci.yml227
-rw-r--r--.gitlab/ci/review.gitlab-ci.yml68
-rw-r--r--.gitlab/ci/setup.gitlab-ci.yml14
-rw-r--r--.gitlab/ci/test-metadata.gitlab-ci.yml30
-rw-r--r--.gitlab/ci/yaml.gitlab-ci.yml5
-rw-r--r--.gitlab/issue_templates/Problem_Validation.md41
-rw-r--r--.rubocop_todo.yml5
-rw-r--r--16790-render-xml-artifacts.yml5
-rw-r--r--GITLAB_PAGES_VERSION2
-rw-r--r--Gemfile2
-rw-r--r--Gemfile.lock4
-rw-r--r--app/assets/javascripts/blob/template_selector.js4
-rw-r--r--app/assets/javascripts/clusters/clusters_bundle.js54
-rw-r--r--app/assets/javascripts/clusters/services/clusters_service.js2
-rw-r--r--app/assets/javascripts/clusters/stores/clusters_store.js1
-rw-r--r--app/assets/javascripts/commit/image_file.js19
-rw-r--r--app/assets/javascripts/create_cluster/eks_cluster/components/cluster_form_dropdown.vue182
-rw-r--r--app/assets/javascripts/create_cluster/eks_cluster/components/eks_cluster_configuration_form.vue9
-rw-r--r--app/assets/javascripts/create_cluster/eks_cluster/components/role_name_dropdown.vue53
-rw-r--r--app/assets/javascripts/gl_dropdown.js10
-rw-r--r--app/assets/javascripts/issue.js3
-rw-r--r--app/assets/javascripts/jobs/components/log/duration_badge.vue13
-rw-r--r--app/assets/javascripts/jobs/components/log/line.vue2
-rw-r--r--app/assets/javascripts/jobs/components/log/line_header.vue16
-rw-r--r--app/assets/javascripts/jobs/components/log/line_number.vue9
-rw-r--r--app/assets/javascripts/jobs/components/log/log.vue11
-rw-r--r--app/assets/javascripts/jobs/store/utils.js35
-rw-r--r--app/assets/javascripts/label_manager.js5
-rw-r--r--app/assets/javascripts/labels_select.js25
-rw-r--r--app/assets/javascripts/lib/utils/text_markdown.js4
-rw-r--r--app/assets/javascripts/milestone_select.js8
-rw-r--r--app/assets/javascripts/monitoring/components/charts/column.vue2
-rw-r--r--app/assets/javascripts/monitoring/components/charts/empty_chart.vue2
-rw-r--r--app/assets/javascripts/monitoring/components/charts/single_stat.vue2
-rw-r--r--app/assets/javascripts/monitoring/components/charts/time_series.vue120
-rw-r--r--app/assets/javascripts/monitoring/components/dashboard.vue2
-rw-r--r--app/assets/javascripts/monitoring/components/embed.vue1
-rw-r--r--app/assets/javascripts/network/branch_graph.js12
-rw-r--r--app/assets/javascripts/notes.js44
-rw-r--r--app/assets/javascripts/notes/components/discussion_actions.vue7
-rw-r--r--app/assets/javascripts/pages/admin/application_settings/show/index.js (renamed from app/assets/javascripts/pages/admin/application_settings/general/index.js)0
-rw-r--r--app/assets/javascripts/pages/projects/graphs/show/stat_graph_contributors_util.js4
-rw-r--r--app/assets/javascripts/performance_bar/services/performance_bar_service.js9
-rw-r--r--app/assets/javascripts/profile/gl_crop.js13
-rw-r--r--app/assets/javascripts/project_find_file.js5
-rw-r--r--app/assets/javascripts/right_sidebar.js14
-rw-r--r--app/assets/javascripts/search_autocomplete.js9
-rw-r--r--app/assets/javascripts/test_utils/simulate_drag.js8
-rw-r--r--app/assets/javascripts/users_select.js7
-rw-r--r--app/assets/javascripts/zen_mode.js4
-rw-r--r--app/assets/stylesheets/framework/flash.scss6
-rw-r--r--app/assets/stylesheets/framework/job_log.scss49
-rw-r--r--app/assets/stylesheets/framework/snippets.scss4
-rw-r--r--app/assets/stylesheets/framework/sortable.scss18
-rw-r--r--app/assets/stylesheets/framework/variables.scss3
-rw-r--r--app/assets/stylesheets/pages/boards.scss14
-rw-r--r--app/assets/stylesheets/pages/issues.scss4
-rw-r--r--app/assets/stylesheets/pages/merge_requests.scss4
-rw-r--r--app/assets/stylesheets/pages/projects.scss10
-rw-r--r--app/controllers/admin/application_settings_controller.rb11
-rw-r--r--app/controllers/projects/merge_requests_controller.rb2
-rw-r--r--app/controllers/projects/pipelines_controller.rb10
-rw-r--r--app/finders/issuable_finder.rb65
-rw-r--r--app/graphql/resolvers/issues_resolver.rb19
-rw-r--r--app/graphql/types/order.rb8
-rw-r--r--app/graphql/types/sort.rb10
-rw-r--r--app/graphql/types/sort_enum.rb13
-rw-r--r--app/helpers/page_layout_helper.rb1
-rw-r--r--app/helpers/projects_helper.rb2
-rw-r--r--app/models/ci/artifact_blob.rb2
-rw-r--r--app/models/ci/build_metadata.rb46
-rw-r--r--app/models/clusters/applications/ingress.rb21
-rw-r--r--app/models/clusters/cluster.rb31
-rw-r--r--app/models/clusters/concerns/application_core.rb4
-rw-r--r--app/models/commit.rb1
-rw-r--r--app/models/concerns/routable.rb20
-rw-r--r--app/models/diff_note.rb13
-rw-r--r--app/models/merge_request.rb17
-rw-r--r--app/models/milestone.rb9
-rw-r--r--app/models/milestone_release.rb4
-rw-r--r--app/models/note_diff_file.rb6
-rw-r--r--app/models/project.rb12
-rw-r--r--app/models/project_services/bugzilla_service.rb2
-rw-r--r--app/models/project_services/custom_issue_tracker_service.rb2
-rw-r--r--app/models/project_services/data_fields.rb52
-rw-r--r--app/models/project_services/gitlab_issue_tracker_service.rb2
-rw-r--r--app/models/project_services/issue_tracker_data.rb3
-rw-r--r--app/models/project_services/issue_tracker_service.rb63
-rw-r--r--app/models/project_services/jira_service.rb33
-rw-r--r--app/models/project_services/jira_tracker_data.rb7
-rw-r--r--app/models/project_services/redmine_service.rb2
-rw-r--r--app/models/project_services/youtrack_service.rb2
-rw-r--r--app/models/protected_branch.rb5
-rw-r--r--app/models/release.rb9
-rw-r--r--app/presenters/ci/build_metadata_presenter.rb3
-rw-r--r--app/services/clusters/applications/base_service.rb4
-rw-r--r--app/services/clusters/applications/create_service.rb2
-rw-r--r--app/services/clusters/applications/destroy_service.rb2
-rw-r--r--app/services/clusters/applications/update_service.rb2
-rw-r--r--app/services/projects/create_from_template_service.rb23
-rw-r--r--app/services/releases/concerns.rb22
-rw-r--r--app/services/releases/create_service.rb4
-rw-r--r--app/services/releases/update_service.rb4
-rw-r--r--app/services/service_response.rb4
-rw-r--r--app/views/admin/application_settings/_account_and_limit.html.haml2
-rw-r--r--app/views/admin/application_settings/_diff_limits.html.haml2
-rw-r--r--app/views/admin/application_settings/_external_authorization_service_form.html.haml2
-rw-r--r--app/views/admin/application_settings/_signin.html.haml2
-rw-r--r--app/views/admin/application_settings/_signup.html.haml2
-rw-r--r--app/views/admin/application_settings/_terminal.html.haml2
-rw-r--r--app/views/admin/application_settings/_terms.html.haml2
-rw-r--r--app/views/admin/application_settings/_visibility_and_access.html.haml2
-rw-r--r--app/views/admin/application_settings/show.html.haml (renamed from app/views/admin/application_settings/general.html.haml)6
-rw-r--r--app/views/layouts/nav/sidebar/_admin.html.haml2
-rw-r--r--app/views/projects/mirrors/_mirror_repos.html.haml6
-rw-r--r--app/views/projects/protected_branches/shared/_create_protected_branch.html.haml2
-rw-r--r--app/views/projects/registry/repositories/index.html.haml2
-rw-r--r--app/views/projects/services/_form.html.haml6
-rw-r--r--app/views/shared/projects/_project.html.haml9
-rw-r--r--app/views/shared/snippets/_form.html.haml2
-rw-r--r--app/views/shared/snippets/_header.html.haml2
-rwxr-xr-xbin/changelog9
-rwxr-xr-xbin/elastic_repo_indexer101
-rw-r--r--changelogs/unreleased/29155-fix-devise-401-responses.yml5
-rw-r--r--changelogs/unreleased/32156-fix-ci_usage_warning_message-message-builder.yml5
-rw-r--r--changelogs/unreleased/64213-not_filtering.yml5
-rw-r--r--changelogs/unreleased/65192-enable-modsecurity-in-ingress.yml5
-rw-r--r--changelogs/unreleased/66986-milestone-release-many-to-many.yml5
-rw-r--r--changelogs/unreleased/backport-schedule-productivity-analytics-backfill.yml5
-rw-r--r--changelogs/unreleased/docs-document-auto-devops-docker-build-secret-forwarding.yml5
-rw-r--r--changelogs/unreleased/enabling_runners_token_for_groups.yml5
-rw-r--r--changelogs/unreleased/language-trends-over-time.yml5
-rw-r--r--changelogs/unreleased/ms-implement-build-specific-timeout.yml5
-rw-r--r--changelogs/unreleased/osw-improve-discussions-query.yml5
-rw-r--r--changelogs/unreleased/remove-vue-resource-from-performance-bar-service.yml5
-rw-r--r--config/gitlab.yml.example4
-rw-r--r--config/initializers/7_prometheus_metrics.rb6
-rw-r--r--config/initializers/8_devise.rb8
-rw-r--r--config/routes/admin.rb2
-rw-r--r--danger/changelog/Dangerfile6
-rw-r--r--danger/commit_messages/Dangerfile10
-rw-r--r--danger/only_documentation/Dangerfile24
-rw-r--r--db/migrate/20190801193427_rename_application_settings_snowplow_collector_uri_column.rb2
-rw-r--r--db/migrate/20190828170945_create_package_metadatum.rb14
-rw-r--r--db/migrate/20190828172831_create_package_tag.rb14
-rw-r--r--db/migrate/20190910125852_create_analytics_language_trend_repository_languages.rb35
-rw-r--r--db/migrate/20190910212256_add_any_approver_rule_unique_indexes.rb30
-rw-r--r--db/post_migrate/20190724091326_schedule_productivity_analytics_backfill.rb31
-rw-r--r--db/post_migrate/20190802091750_cleanup_application_settings_snowplow_collector_uri_rename.rb2
-rw-r--r--db/post_migrate/20190827102026_migrate_code_owner_approval_status_to_protected_branches_in_batches.rb46
-rw-r--r--db/post_migrate/20190904205212_remove_id_column_from_intermediate_release_milestones.rb9
-rw-r--r--db/post_migrate/20190905091812_schedule_project_any_approval_rule_migration.rb47
-rw-r--r--db/post_migrate/20190905091831_schedule_merge_request_any_approval_rule_migration.rb47
-rw-r--r--db/schema.rb36
-rw-r--r--doc/README.md14
-rw-r--r--doc/administration/auth/ldap-ee.md2
-rw-r--r--doc/administration/container_registry.md739
-rw-r--r--doc/administration/dependency_proxy.md154
-rw-r--r--doc/administration/geo/replication/docker_registry.md13
-rw-r--r--doc/administration/geo/replication/index.md6
-rw-r--r--doc/administration/gitaly/index.md2
-rw-r--r--doc/administration/index.md8
-rw-r--r--doc/administration/maven_packages.md4
-rw-r--r--doc/administration/maven_repository.md4
-rw-r--r--doc/administration/npm_registry.md4
-rw-r--r--doc/administration/packages.md179
-rw-r--r--doc/administration/packages/container_registry.md882
-rw-r--r--doc/administration/packages/dependency_proxy.md148
-rw-r--r--doc/administration/packages/index.md175
-rw-r--r--doc/api/container_registry.md2
-rw-r--r--doc/api/epics.md2
-rw-r--r--doc/api/groups.md3
-rw-r--r--doc/api/issues.md5
-rw-r--r--doc/api/packages.md2
-rw-r--r--doc/api/projects.md3
-rw-r--r--doc/api/releases/index.md173
-rw-r--r--doc/api/settings.md1
-rw-r--r--doc/ci/docker/using_docker_build.md2
-rw-r--r--doc/ci/docker/using_kaniko.md2
-rw-r--r--doc/ci/environments.md2
-rw-r--r--doc/ci/examples/laravel_with_gitlab_and_envoy/index.md4
-rw-r--r--doc/ci/introduction/img/gitlab_workflow_example_extended_11_11.pngbin0 -> 136497 bytes
-rw-r--r--doc/ci/introduction/img/gitlab_workflow_example_extended_v12_3.pngbin78448 -> 0 bytes
-rw-r--r--doc/ci/introduction/index.md8
-rw-r--r--doc/ci/jenkins/index.md4
-rw-r--r--doc/ci/triggers/README.md2
-rw-r--r--doc/ci/variables/predefined_variables.md2
-rw-r--r--doc/ci/yaml/README.md15
-rw-r--r--doc/container_registry/README.md4
-rw-r--r--doc/container_registry/troubleshooting.md4
-rw-r--r--doc/development/README.md1
-rw-r--r--doc/development/api_styleguide.md13
-rw-r--r--doc/development/architecture.md8
-rw-r--r--doc/development/changelog.md10
-rw-r--r--doc/development/documentation/index.md133
-rw-r--r--doc/development/elasticsearch.md2
-rw-r--r--doc/development/packages.md6
-rw-r--r--doc/development/pipelines.md216
-rw-r--r--doc/development/polling.md4
-rw-r--r--doc/development/testing_guide/end_to_end/index.md18
-rw-r--r--doc/development/testing_guide/end_to_end/style_guide.md38
-rw-r--r--doc/development/testing_guide/img/k9s.pngbin364038 -> 0 bytes
-rw-r--r--doc/development/testing_guide/review_apps.md46
-rw-r--r--doc/install/aws/index.md2
-rw-r--r--doc/install/google_cloud_platform/index.md2
-rw-r--r--doc/install/installation.md19
-rw-r--r--doc/integration/shibboleth.md4
-rw-r--r--doc/raketasks/backup_restore.md2
-rw-r--r--doc/raketasks/cleanup.md5
-rw-r--r--doc/topics/autodevops/index.md58
-rw-r--r--doc/topics/autodevops/quick_start_guide.md2
-rw-r--r--doc/university/support/README.md2
-rw-r--r--doc/user/application_security/container_scanning/index.md35
-rw-r--r--doc/user/application_security/dependency_scanning/index.md2
-rw-r--r--doc/user/clusters/applications.md33
-rw-r--r--doc/user/group/clusters/index.md4
-rw-r--r--doc/user/group/dependency_proxy/index.md77
-rw-r--r--doc/user/group/index.md4
-rw-r--r--doc/user/index.md4
-rw-r--r--doc/user/packages/container_registry/index.md158
-rw-r--r--doc/user/packages/dependency_proxy/img/group_dependency_proxy.pngbin40162 -> 0 bytes
-rw-r--r--doc/user/packages/dependency_proxy/index.md74
-rw-r--r--doc/user/packages/index.md19
-rw-r--r--doc/user/packages/maven_repository/img/maven_package_view.pngbin16105 -> 0 bytes
-rw-r--r--doc/user/packages/maven_repository/index.md340
-rw-r--r--doc/user/packages/npm_registry/img/npm_package_view.pngbin10349 -> 0 bytes
-rw-r--r--doc/user/packages/npm_registry/index.md147
-rw-r--r--doc/user/permissions.md4
-rw-r--r--doc/user/profile/index.md2
-rw-r--r--doc/user/profile/personal_access_tokens.md2
-rw-r--r--doc/user/project/container_registry.md320
-rw-r--r--doc/user/project/deploy_tokens/index.md2
-rw-r--r--doc/user/project/img/mitmproxy-docker.png (renamed from doc/administration/packages/img/mitmproxy-docker.png)bin142591 -> 142591 bytes
-rw-r--r--doc/user/project/index.md6
-rw-r--r--doc/user/project/issues/img/link_zoom_call_in_issue.pngbin0 -> 69554 bytes
-rw-r--r--doc/user/project/issues/img/zoom-quickaction-button.pngbin117097 -> 0 bytes
-rw-r--r--doc/user/project/issues/issue_data_and_actions.md25
-rw-r--r--doc/user/project/maven_packages.md4
-rw-r--r--doc/user/project/operations/feature_flags.md2
-rw-r--r--doc/user/project/packages/maven.md4
-rw-r--r--doc/user/project/packages/maven_packages.md4
-rw-r--r--doc/user/project/packages/maven_repository.md343
-rw-r--r--doc/user/project/packages/npm_registry.md150
-rw-r--r--doc/user/project/pipelines/job_artifacts.md6
-rw-r--r--doc/user/project/settings/index.md2
-rw-r--r--doc/user/project/wiki/img/wiki_create_new_page_modal.pngbin0 -> 5831 bytes
-rw-r--r--doc/user/project/wiki/index.md10
-rw-r--r--doc/workflow/time-tracking/time-tracking-example.pngbin0 -> 14564 bytes
-rw-r--r--doc/workflow/time-tracking/time-tracking-sidebar.png (renamed from doc/workflow/time_tracking/img/time_tracking_sidebar_v8_16.png)bin9068 -> 9068 bytes
-rw-r--r--doc/workflow/time_tracking.md20
-rw-r--r--doc/workflow/time_tracking/img/time_tracking_example_v12_2.pngbin16362 -> 0 bytes
-rw-r--r--lib/api/entities.rb10
-rw-r--r--lib/api/groups.rb3
-rw-r--r--lib/api/helpers/issues_helpers.rb6
-rw-r--r--lib/api/helpers/projects_helpers.rb8
-rw-r--r--lib/api/helpers/services_helpers.rb1
-rw-r--r--lib/api/issues.rb25
-rw-r--r--lib/api/pipelines.rb23
-rw-r--r--lib/api/projects.rb4
-rw-r--r--lib/api/releases.rb4
-rw-r--r--lib/gitlab/auth/ldap/dn.rb1
-rw-r--r--lib/gitlab/background_migration/add_gitlab_instance_administration_project.rb14
-rw-r--r--lib/gitlab/ci/config/entry/job.rb9
-rw-r--r--lib/gitlab/ci/templates/Security/Container-Scanning.gitlab-ci.yml61
-rw-r--r--lib/gitlab/ci/templates/Security/SAST.gitlab-ci.yml138
-rw-r--r--lib/gitlab/ci/yaml_processor.rb1
-rw-r--r--lib/gitlab/daemon.rb4
-rw-r--r--lib/gitlab/devise_failure.rb13
-rw-r--r--lib/gitlab/discussions_diff/file_collection.rb29
-rw-r--r--lib/gitlab/ee_compat_check.rb1
-rw-r--r--lib/gitlab/etag_caching/router.rb4
-rw-r--r--lib/gitlab/hook_data/merge_request_builder.rb1
-rw-r--r--lib/gitlab/profiler.rb1
-rw-r--r--lib/gitlab/quick_actions/issuable_actions.rb1
-rw-r--r--lib/gitlab/slash_commands/presenters/issue_move.rb1
-rw-r--r--lib/gitlab/time_tracking_formatter.rb6
-rw-r--r--lib/gitlab/usage_data.rb49
-rw-r--r--lib/gitlab_danger.rb3
-rw-r--r--locale/gitlab.pot39
-rw-r--r--package.json8
-rw-r--r--qa/qa.rb2
-rw-r--r--qa/qa/page/admin/settings/general.rb2
-rw-r--r--qa/qa/page/main/login.rb9
-rw-r--r--qa/qa/page/main/menu.rb6
-rw-r--r--qa/qa/page/project/settings/mirroring_repositories.rb10
-rw-r--r--qa/qa/page/project/settings/protected_branches.rb37
-rw-r--r--qa/qa/page/project/wiki/git_access.rb13
-rw-r--r--qa/qa/resource/group.rb11
-rw-r--r--qa/qa/resource/members.rb28
-rw-r--r--qa/qa/resource/project.rb10
-rw-r--r--qa/qa/resource/protected_branch.rb35
-rw-r--r--qa/qa/resource/repository/project_push.rb4
-rw-r--r--qa/qa/resource/repository/wiki_push.rb9
-rw-r--r--qa/qa/resource/wiki.rb9
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/repository/push_protected_branch_spec.rb20
-rwxr-xr-xscripts/review_apps/review-apps.sh12
-rw-r--r--spec/bin/changelog_spec.rb8
-rw-r--r--spec/controllers/admin/application_settings_controller_spec.rb27
-rw-r--r--spec/controllers/application_controller_spec.rb39
-rw-r--r--spec/controllers/concerns/send_file_upload_spec.rb1
-rw-r--r--spec/controllers/projects/jobs_controller_spec.rb1
-rw-r--r--spec/controllers/projects/merge_requests_controller_spec.rb6
-rw-r--r--spec/factories/services.rb74
-rw-r--r--spec/features/admin/admin_disables_git_access_protocol_spec.rb5
-rw-r--r--spec/features/admin/admin_settings_spec.rb2
-rw-r--r--spec/finders/issues_finder_spec.rb202
-rw-r--r--spec/fixtures/api/schemas/public_api/v4/release.json5
-rw-r--r--spec/frontend/clusters/clusters_bundle_spec.js34
-rw-r--r--spec/frontend/create_cluster/eks_cluster/components/cluster_form_dropdown_spec.js137
-rw-r--r--spec/frontend/create_cluster/eks_cluster/components/role_name_dropdown_spec.js43
-rw-r--r--spec/frontend/fixtures/application_settings.rb2
-rw-r--r--spec/frontend/jobs/store/utils_spec.js16
-rw-r--r--spec/frontend/notes/components/discussion_actions_spec.js36
-rw-r--r--spec/helpers/application_helper_spec.rb1
-rw-r--r--spec/helpers/defer_script_tag_helper_spec.rb1
-rw-r--r--spec/javascripts/boards/boards_store_spec.js4
-rw-r--r--spec/javascripts/jobs/components/log/duration_badge_spec.js31
-rw-r--r--spec/javascripts/jobs/components/log/line_header_spec.js11
-rw-r--r--spec/javascripts/test_bundle.js2
-rw-r--r--spec/lib/banzai/pipeline/gfm_pipeline_spec.rb6
-rw-r--r--spec/lib/container_registry/client_spec.rb1
-rw-r--r--spec/lib/gitlab/background_migration/add_gitlab_instance_administration_project_spec.rb234
-rw-r--r--spec/lib/gitlab/ci/build/step_spec.rb52
-rw-r--r--spec/lib/gitlab/ci/config/entry/job_spec.rb31
-rw-r--r--spec/lib/gitlab/ci/yaml_processor_spec.rb42
-rw-r--r--spec/lib/gitlab/discussions_diff/file_collection_spec.rb39
-rw-r--r--spec/lib/gitlab/encoding_helper_spec.rb1
-rw-r--r--spec/lib/gitlab/etag_caching/router_spec.rb9
-rw-r--r--spec/lib/gitlab/git/blame_spec.rb1
-rw-r--r--spec/lib/gitlab/git/blob_spec.rb2
-rw-r--r--spec/lib/gitlab/git/conflict/file_spec.rb1
-rw-r--r--spec/lib/gitlab/git/repository_spec.rb1
-rw-r--r--spec/lib/gitlab/git_spec.rb1
-rw-r--r--spec/lib/gitlab/hook_data/issuable_builder_spec.rb18
-rw-r--r--spec/lib/gitlab/import_export/all_models.yml8
-rw-r--r--spec/lib/gitlab/json_logger_spec.rb1
-rw-r--r--spec/lib/gitlab/path_regex_spec.rb1
-rw-r--r--spec/lib/gitlab/popen_spec.rb8
-rw-r--r--spec/lib/gitlab/project_search_results_spec.rb1
-rw-r--r--spec/lib/gitlab/regex_spec.rb1
-rw-r--r--spec/lib/gitlab/search/found_blob_spec.rb1
-rw-r--r--spec/lib/gitlab/url_blocker_spec.rb1
-rw-r--r--spec/lib/gitlab/usage_data_spec.rb16
-rw-r--r--spec/lib/gitlab_danger_spec.rb2
-rw-r--r--spec/migrations/migrate_code_owner_approval_status_to_protected_branches_in_batches_spec.rb63
-rw-r--r--spec/models/blob_spec.rb1
-rw-r--r--spec/models/ci/build_metadata_spec.rb70
-rw-r--r--spec/models/clusters/applications/ingress_spec.rb37
-rw-r--r--spec/models/concerns/routable_spec.rb20
-rw-r--r--spec/models/merge_request_spec.rb59
-rw-r--r--spec/models/milestone_release_spec.rb22
-rw-r--r--spec/models/milestone_spec.rb9
-rw-r--r--spec/models/project_services/bugzilla_service_spec.rb6
-rw-r--r--spec/models/project_services/custom_issue_tracker_service_spec.rb6
-rw-r--r--spec/models/project_services/data_fields_spec.rb138
-rw-r--r--spec/models/project_services/gitlab_issue_tracker_service_spec.rb6
-rw-r--r--spec/models/project_services/issue_tracker_data_spec.rb24
-rw-r--r--spec/models/project_services/issue_tracker_service_spec.rb2
-rw-r--r--spec/models/project_services/jira_service_spec.rb428
-rw-r--r--spec/models/project_services/jira_tracker_data_spec.rb31
-rw-r--r--spec/models/project_services/redmine_service_spec.rb16
-rw-r--r--spec/models/project_services/youtrack_service_spec.rb7
-rw-r--r--spec/models/project_spec.rb37
-rw-r--r--spec/models/release_spec.rb13
-rw-r--r--spec/models/service_spec.rb4
-rw-r--r--spec/requests/api/groups_spec.rb44
-rw-r--r--spec/requests/api/issues/get_group_issues_spec.rb4
-rw-r--r--spec/requests/api/issues/get_project_issues_spec.rb3
-rw-r--r--spec/requests/api/issues/issues_spec.rb85
-rw-r--r--spec/requests/api/pipelines_spec.rb48
-rw-r--r--spec/requests/api/projects_spec.rb32
-rw-r--r--spec/requests/api/services_spec.rb8
-rw-r--r--spec/requests/projects/merge_requests_discussions_spec.rb52
-rw-r--r--spec/services/ci/create_pipeline_service_spec.rb16
-rw-r--r--spec/services/issues/update_service_spec.rb1
-rw-r--r--spec/services/milestones/destroy_service_spec.rb2
-rw-r--r--spec/services/projects/create_from_template_service_spec.rb4
-rw-r--r--spec/services/releases/create_service_spec.rb66
-rw-r--r--spec/services/releases/destroy_service_spec.rb2
-rw-r--r--spec/services/releases/update_service_spec.rb45
-rw-r--r--spec/services/service_response_spec.rb14
-rw-r--r--spec/support/helpers/jira_service_helper.rb18
-rw-r--r--spec/support/shared_contexts/finders/issues_finder_shared_contexts.rb2
-rw-r--r--spec/support/shared_examples/controllers/application_settings_shared_examples.rb26
-rw-r--r--spec/support/shared_examples/finders/assignees_filter_shared_examples.rb12
-rw-r--r--spec/support/shared_examples/models/cluster_application_core_shared_examples.rb4
-rw-r--r--spec/support/shared_examples/requests/api/issues_shared_examples.rb21
-rw-r--r--yarn.lock44
398 files changed, 4441 insertions, 6817 deletions
diff --git a/.eslintrc.yml b/.eslintrc.yml
index 70a71baa590..95cbc602d5b 100644
--- a/.eslintrc.yml
+++ b/.eslintrc.yml
@@ -8,6 +8,7 @@ globals:
IS_EE: false
plugins:
- import
+ - html
- "@gitlab/i18n"
- "@gitlab/vue-i18n"
settings:
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 6c10c4853c4..0d573a4c214 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -1,6 +1,7 @@
image: "dev.gitlab.org:5005/gitlab/gitlab-build-images:ruby-2.6.3-golang-1.11-git-2.22-chrome-73.0-node-12.x-yarn-1.16-postgresql-9.6-graphicsmagick-1.3.33"
stages:
+ - build
- prepare
- quick-test
- test
diff --git a/.gitlab/ci/cng.gitlab-ci.yml b/.gitlab/ci/cng.gitlab-ci.yml
index 35859a1ab33..3ba3b221df0 100644
--- a/.gitlab/ci/cng.gitlab-ci.yml
+++ b/.gitlab/ci/cng.gitlab-ci.yml
@@ -11,6 +11,5 @@ cloud-native-image:
- CNG_PROJECT_PATH="gitlab-org/build/CNG" BUILD_TRIGGER_TOKEN=$CI_JOB_TOKEN ./scripts/trigger-build cng
only:
refs:
- - tags
- variables:
- - $CI_SERVER_HOST == "gitlab.com" && $CI_PROJECT_NAMESPACE == "gitlab-org"
+ - tags@gitlab-org/gitlab-foss
+ - tags@gitlab-org/gitlab
diff --git a/.gitlab/ci/docs.gitlab-ci.yml b/.gitlab/ci/docs.gitlab-ci.yml
index 87023da3c24..22e752ae0b0 100644
--- a/.gitlab/ci/docs.gitlab-ci.yml
+++ b/.gitlab/ci/docs.gitlab-ci.yml
@@ -2,12 +2,6 @@
extends:
- .default-tags
- .default-retry
- - .only-docs-changes
- only:
- refs:
- - merge_requests
- variables:
- - $CI_SERVER_HOST == "gitlab.com" && $CI_PROJECT_NAMESPACE == "gitlab-org"
image: ruby:2.6-alpine
stage: review
dependencies: []
@@ -25,32 +19,55 @@
- apk add --update openssl
- wget $CI_PROJECT_URL/raw/$CI_COMMIT_SHA/scripts/trigger-build-docs
- chmod 755 trigger-build-docs
+
+# Trigger a manual docs build in gitlab-docs only on non docs-only branches.
+# Useful to preview the docs changes live.
+review-docs-deploy-manual:
+ extends:
+ - .review-docs
+ - .except-docs-qa
+ script:
- gem install gitlab --no-document
+ - ./trigger-build-docs deploy
+ when: manual
+ only:
+ - branches@gitlab-org/gitlab-foss
+ - branches@gitlab-org/gitlab
# Always trigger a docs build in gitlab-docs only on docs-only branches.
# Useful to preview the docs changes live.
review-docs-deploy:
- extends: .review-docs
+ extends:
+ - .review-docs
+ - .except-qa
script:
+ - gem install gitlab --no-document
- ./trigger-build-docs deploy
- when: manual
+ only:
+ - /(^docs[\/-].+|.+-docs$)/@gitlab-org/gitlab-foss
+ - /(^docs[\/-].+|.+-docs$)/@gitlab-org/gitlab
# Cleanup remote environment of gitlab-docs
review-docs-cleanup:
- extends: .review-docs
+ extends:
+ - .review-docs
+ - .except-qa
environment:
name: review-docs/$CI_COMMIT_REF_SLUG
action: stop
script:
+ - gem install gitlab --no-document
- ./trigger-build-docs cleanup
when: manual
+ only:
+ - branches@gitlab-org/gitlab-foss
+ - branches@gitlab-org/gitlab
docs lint:
extends:
- .default-tags
- .default-retry
- - .default-only
- - .only-docs-changes
+ - .except-qa
image: "registry.gitlab.com/gitlab-org/gitlab-build-images:gitlab-docs-lint"
stage: test
dependencies: []
diff --git a/.gitlab/ci/frontend.gitlab-ci.yml b/.gitlab/ci/frontend.gitlab-ci.yml
index f72396e4edf..a61601597c3 100644
--- a/.gitlab/ci/frontend.gitlab-ci.yml
+++ b/.gitlab/ci/frontend.gitlab-ci.yml
@@ -9,10 +9,9 @@
extends:
- .default-tags
- .default-retry
- - .default-only
- - .default-before_script
- .assets-compile-cache
- - .only-code-qa-changes
+ - .default-before_script
+ - .except-docs
image: dev.gitlab.org:5005/gitlab/gitlab-build-images:ruby-2.6.3-git-2.22-chrome-73.0-node-12.x-yarn-1.16-graphicsmagick-1.3.33-docker-18.06.1
stage: test
dependencies: ["setup-test-env"]
@@ -46,9 +45,10 @@
- scripts/clean-old-cached-assets
- rm -f /etc/apt/sources.list.d/google*.list # We don't need to update Chrome here
only:
- variables:
- - $CI_SERVER_HOST == "gitlab.com" && $CI_PROJECT_NAMESPACE == "gitlab-org"
- - $CI_SERVER_HOST == "dev.gitlab.org"
+ - /.+/@gitlab-org/gitlab-foss
+ - /.+/@gitlab-org/gitlab
+ - /.+/@gitlab/gitlabhq
+ - /.+/@gitlab/gitlab-ee
tags:
- gitlab-org
- docker
@@ -57,7 +57,8 @@ gitlab:assets:compile:
extends: .gitlab:assets:compile-metadata
only:
refs:
- - master
+ - master@gitlab-org/gitlab-foss
+ - master@gitlab-org/gitlab
cache:
policy: pull-push
@@ -65,7 +66,9 @@ gitlab:assets:compile pull-cache:
extends: .gitlab:assets:compile-metadata
except:
refs:
- - master
+ - master@gitlab-org/gitlab-foss
+ - master@gitlab-org/gitlab
+ - /(^docs[\/-].+|.+-docs$)/
cache:
policy: pull
@@ -73,10 +76,8 @@ gitlab:assets:compile pull-cache:
extends:
- .default-tags
- .default-retry
- - .default-only
- - .default-before_script
- .assets-compile-cache
- - .only-code-qa-changes
+ - .default-before_script
- .use-pg
stage: prepare
script:
@@ -97,10 +98,12 @@ gitlab:assets:compile pull-cache:
- public/assets
compile-assets:
- extends: .compile-assets-metadata
+ extends:
+ - .compile-assets-metadata
only:
refs:
- - master
+ - master@gitlab-org/gitlab-foss
+ - master@gitlab-org/gitlab
cache:
policy: pull-push
@@ -108,23 +111,21 @@ compile-assets pull-cache:
extends: .compile-assets-metadata
except:
refs:
- - master
+ - master@gitlab-org/gitlab-foss
+ - master@gitlab-org/gitlab
+ - /(^docs[\/-].+|.+-docs$)/
cache:
policy: pull
-.only-code-frontend-job-base:
+karma:
extends:
- .default-tags
- .default-retry
- .default-cache
- - .default-only
- .default-before_script
- - .only-code-changes
- .use-pg
+ - .except-docs
dependencies: ["compile-assets", "compile-assets pull-cache", "setup-test-env"]
-
-karma:
- extends: .only-code-frontend-job-base
variables:
# we override the max_old_space_size to prevent OOM errors
NODE_OPTIONS: --max_old_space_size=3584
@@ -147,7 +148,14 @@ karma:
junit: junit_karma.xml
jest:
- extends: .only-code-frontend-job-base
+ extends:
+ - .default-tags
+ - .default-retry
+ - .default-cache
+ - .default-before_script
+ - .use-pg
+ - .except-docs-qa
+ dependencies: ["compile-assets", "compile-assets pull-cache", "setup-test-env"]
script:
- scripts/gitaly-test-spawn
- date
@@ -170,26 +178,27 @@ jest:
- tmp/jest/jest/
policy: pull-push
-.qa-job-base:
+.qa:
extends:
- .default-tags
- .default-retry
- .default-cache
- - .default-only
- - .only-code-qa-changes
+ - .except-docs
dependencies: []
stage: test
+ variables:
+ SETUP_DB: "false"
before_script:
- cd qa/
- bundle install
qa:internal:
- extends: .qa-job-base
+ extends: .qa
script:
- bundle exec rspec
qa:selectors:
- extends: .qa-job-base
+ extends: .qa
script:
- bundle exec bin/qa Test::Sanity::Selectors
@@ -198,8 +207,7 @@ qa:selectors:
- .default-tags
- .default-retry
- .default-cache
- - .default-only
- - .only-code-changes
+ - .except-docs
dependencies: []
cache:
key: "$CI_JOB_NAME"
@@ -230,9 +238,10 @@ webpack-dev-server:
- .default-tags
- .default-retry
- .default-cache
- - .only-code-changes
- dependencies: ["setup-test-env", "compile-assets", "compile-assets pull-cache"]
+ - .except-docs-qa
+ dependencies: ["compile-assets", "compile-assets pull-cache", "setup-test-env"]
variables:
+ SETUP_DB: "false"
WEBPACK_MEMORY_TEST: "true"
script:
- node --version
diff --git a/.gitlab/ci/global.gitlab-ci.yml b/.gitlab/ci/global.gitlab-ci.yml
index 94d7d2cdaa4..8287390c80e 100644
--- a/.gitlab/ci/global.gitlab-ci.yml
+++ b/.gitlab/ci/global.gitlab-ci.yml
@@ -27,83 +27,40 @@
- vendor/gitaly-ruby
policy: pull
-.default-only:
- only:
+.except-docs:
+ except:
refs:
- - master
- - /^[\d-]+-stable(-ee)?$/
- - /^\d+-\d+-auto-deploy-\d+$/
- - merge_requests
- - tags
-
-.only-code-changes:
- only:
- changes:
- - ".gitlab/ci/**/*"
- - ".{eslintignore,gitattributes,nvmrc,prettierrc,stylelintrc,yamllint}"
- - ".{codeclimate,eslintrc,gitlab-ci,haml-lint,haml-lint_todo,rubocop,rubocop_todo,scss-lint}.yml"
- - ".csscomb.json"
- - "Dangerfile"
- - "Dockerfile.assets"
- - "*_VERSION"
- - "Gemfile{,.lock}"
- - "Rakefile"
- - "{babel.config,jest.config}.js"
- - "config.ru"
- - "{package.json,yarn.lock}"
- - "{app,bin,config,danger,db,ee,fixtures,haml_lint,lib,public,rubocop,scripts,spec,symbol,vendor}/**/*"
- - "doc/README.md" # Some RSpec test rely on this file
+ - /(^docs[\/-].+|.+-docs$)/
-.only-qa-changes:
- only:
- changes:
- - ".dockerignore"
- - "qa/**/*"
+.except-qa:
+ except:
+ refs:
+ - /(^qa[\/-].*|.*-qa$)/
-.only-docs-changes:
- only:
- changes:
- - ".gitlab/route-map.yml"
- - "doc/**/*"
- - ".markdownlint.json"
+.except-docs-qa:
+ except:
+ refs:
+ - /(^docs[\/-].+|.+-docs$)/
+ - /(^qa[\/-].*|.*-qa$)/
-.only-code-qa-changes:
- only:
- changes:
- - ".gitlab/ci/**/*"
- - ".{eslintignore,gitattributes,nvmrc,prettierrc,stylelintrc,yamllint}"
- - ".{codeclimate,eslintrc,gitlab-ci,haml-lint,haml-lint_todo,rubocop,rubocop_todo,scss-lint}.yml"
- - ".csscomb.json"
- - "Dangerfile"
- - "Dockerfile.assets"
- - "*_VERSION"
- - "Gemfile{,.lock}"
- - "Rakefile"
- - "{babel.config,jest.config}.js"
- - "config.ru"
- - "{package.json,yarn.lock}"
- - "{app,bin,config,danger,db,ee,fixtures,haml_lint,lib,public,rubocop,scripts,spec,symbol,vendor}/**/*"
- - "doc/README.md" # Some RSpec test rely on this file
- - ".dockerignore"
- - "qa/**/*"
+.except-docs-qa-geo:
+ except:
+ refs:
+ - /(^docs[\/-].+|.+-docs$)/
+ - /(^qa[\/-].*|.*-qa$)/
+ - /(^geo[\/-].*|.*-geo$)/
-.only-review:
+.review-only:
only:
- variables:
- - $CI_SERVER_HOST == "gitlab.com" && $CI_PROJECT_NAMESPACE == "gitlab-org"
+ refs:
+ - branches@gitlab-org/gitlab-foss
+ - branches@gitlab-org/gitlab
kubernetes: active
except:
refs:
- master
- /^\d+-\d+-auto-deploy-\d+$/
-
-.only-review-schedules:
- only:
- refs:
- - schedules
- variables:
- - $REVIEW_APP_CLEANUP && $CI_SERVER_HOST == "gitlab.com" && $CI_PROJECT_NAMESPACE == "gitlab-org"
- kubernetes: active
+ - /(^docs[\/-].+|.+-docs$)/
.use-pg:
services:
@@ -117,9 +74,3 @@
- name: postgres:10.9
command: ["postgres", "-c", "fsync=off", "-c", "synchronous_commit=off", "-c", "full_page_writes=off"]
- name: redis:alpine
-
-.only-ee:
- only:
- variables:
- - $CI_PROJECT_NAME == "gitlab-ee"
- - $CI_PROJECT_NAME == "gitlab" # New name of gitlab-ee after the single codebase migration
diff --git a/.gitlab/ci/memory.gitlab-ci.yml b/.gitlab/ci/memory.gitlab-ci.yml
index d990c7eefa2..1936933cca4 100644
--- a/.gitlab/ci/memory.gitlab-ci.yml
+++ b/.gitlab/ci/memory.gitlab-ci.yml
@@ -1,14 +1,10 @@
-.only-code-memory-job-base:
+memory-static:
extends:
- .default-tags
- .default-retry
- .default-cache
- - .default-only
- .default-before_script
- - .only-code-changes
-
-memory-static:
- extends: .only-code-memory-job-base
+ - .except-docs
variables:
SETUP_DB: "false"
script:
@@ -35,8 +31,12 @@ memory-static:
# All tests are run without a webserver (directly using Rack::Mock by default).
memory-on-boot:
extends:
- - .only-code-memory-job-base
+ - .default-tags
+ - .default-retry
+ - .default-cache
+ - .default-before_script
- .use-pg-10
+ - .except-docs-qa
variables:
NODE_ENV: "production"
RAILS_ENV: "production"
diff --git a/.gitlab/ci/pages.gitlab-ci.yml b/.gitlab/ci/pages.gitlab-ci.yml
index 47f4117e34a..cf77ec24090 100644
--- a/.gitlab/ci/pages.gitlab-ci.yml
+++ b/.gitlab/ci/pages.gitlab-ci.yml
@@ -3,12 +3,11 @@ pages:
- .default-tags
- .default-retry
- .default-cache
- - .default-only
+ - .except-docs
only:
refs:
- - master
- variables:
- - $CI_SERVER_HOST == "gitlab.com" && $CI_PROJECT_NAMESPACE == "gitlab-org"
+ - master@gitlab-org/gitlab-foss
+ - master@gitlab-org/gitlab
stage: pages
dependencies: ["coverage", "karma", "gitlab:assets:compile"]
script:
diff --git a/.gitlab/ci/qa.gitlab-ci.yml b/.gitlab/ci/qa.gitlab-ci.yml
index e7362f913a9..a868316c353 100644
--- a/.gitlab/ci/qa.gitlab-ci.yml
+++ b/.gitlab/ci/qa.gitlab-ci.yml
@@ -1,5 +1,4 @@
.package-and-qa-base:
- extends: .default-only
image: ruby:2.6-alpine
stage: qa
dependencies: []
@@ -11,16 +10,17 @@
- install_gitlab_gem
- ./scripts/trigger-build omnibus
only:
- variables:
- - $CI_SERVER_HOST == "gitlab.com" && $CI_PROJECT_NAMESPACE == "gitlab-org"
+ refs:
+ - branches@gitlab-org/gitlab-foss
+ - branches@gitlab-org/gitlab
package-and-qa-manual:
- extends:
- - .package-and-qa-base
- - .only-code-changes
+ extends: .package-and-qa-base
except:
refs:
- master
+ - /(^docs[\/-].+|.+-docs$)/
+ - /(^qa[\/-].*|.*-qa$)/
when: manual
needs: ["build-qa-image", "gitlab:assets:compile pull-cache"]
@@ -34,11 +34,10 @@ package-and-qa-manual:master:
needs: ["build-qa-image", "gitlab:assets:compile"]
package-and-qa:
- extends:
- - .package-and-qa-base
- - .only-qa-changes
- except:
+ extends: .package-and-qa-base
+ only:
refs:
- - master
+ - /(^qa[\/-].*|.*-qa$)/@gitlab-org/gitlab-foss
+ - /(^qa[\/-].*|.*-qa$)/@gitlab-org/gitlab
needs: ["build-qa-image", "gitlab:assets:compile pull-cache"]
allow_failure: true
diff --git a/.gitlab/ci/rails.gitlab-ci.yml b/.gitlab/ci/rails.gitlab-ci.yml
index e9222c4b719..2363c0e5f8a 100644
--- a/.gitlab/ci/rails.gitlab-ci.yml
+++ b/.gitlab/ci/rails.gitlab-ci.yml
@@ -1,40 +1,36 @@
-.only-master:
+.only-schedules-master:
only:
refs:
- - master
+ - schedules@gitlab-org/gitlab-foss
+ - schedules@gitlab-org/gitlab
+ - master@gitlab-org/gitlab-foss
+ - master@gitlab-org/gitlab
+ - master@gitlab/gitlabhq
+ - master@gitlab/gitlab-ee
+
+.only-gitlab-ee:
+ only:
+ - branches@gitlab-org/gitlab
+ - tags@gitlab-org/gitlab
.rake-exec:
extends:
- .default-tags
- .default-retry
- .default-cache
- - .default-only
- .default-before_script
variables:
SETUP_DB: "false"
script:
- bundle exec rake $CI_JOB_NAME
-.only-code-rails-job-base:
- extends:
- - .default-tags
- - .default-retry
- - .default-cache
- - .default-only
- - .default-before_script
- - .only-code-changes
-
-.only-code-qa-rails-job-base:
+.rspec-base:
extends:
- .default-tags
- .default-retry
- .default-cache
- - .default-only
- .default-before_script
- - .only-code-qa-changes
-
-.rspec-base:
- extends: .only-code-rails-job-base
+ - .except-docs-qa
stage: test
script:
- JOB_NAME=( $CI_JOB_NAME )
@@ -83,8 +79,12 @@
setup-test-env:
extends:
- - .only-code-qa-rails-job-base
+ - .default-tags
+ - .default-retry
+ - .default-cache
+ - .default-before_script
- .use-pg
+ - .except-docs
stage: prepare
script:
- bundle exec ruby -Ispec -e 'require "spec_helper" ; TestEnv.init'
@@ -111,19 +111,19 @@ rspec system pg:
rspec unit pg-10:
extends:
- .rspec-base-pg-10
- - .only-master
+ - .only-schedules-master
parallel: 20
rspec integration pg-10:
extends:
- .rspec-base-pg-10
- - .only-master
+ - .only-schedules-master
parallel: 6
rspec system pg-10:
extends:
- .rspec-base-pg-10
- - .only-master
+ - .only-schedules-master
parallel: 24
rspec-fast-spec-helper:
@@ -133,8 +133,9 @@ rspec-fast-spec-helper:
rspec quarantine pg:
extends:
+ - .default-before_script
- .rspec-base-pg
- - .only-master
+ - .only-schedules-master
script:
- export NO_KNAPSACK=1 CACHE_CLASSES=true
- scripts/gitaly-test-spawn
@@ -142,7 +143,12 @@ rspec quarantine pg:
allow_failure: true
static-analysis:
- extends: .only-code-qa-rails-job-base
+ extends:
+ - .default-tags
+ - .default-retry
+ - .default-cache
+ - .default-before_script
+ - .except-docs
dependencies: ["setup-test-env", "compile-assets", "compile-assets pull-cache"]
variables:
SETUP_DB: "false"
@@ -156,48 +162,81 @@ static-analysis:
policy: pull-push
downtime_check:
- extends:
- - .rake-exec
- - .only-code-changes
+ extends: .rake-exec
except:
refs:
- master
- tags
- variables:
- - $CI_COMMIT_REF_NAME =~ /^[\d-]+-stable(-ee)?$/
+ - /^[\d-]+-stable(-ee)?$/
+ - /(^docs[\/-].+|.+-docs$)/
+ - /(^qa[\/-].*|.*-qa$)/
stage: test
dependencies: ["setup-test-env"]
needs: ["setup-test-env"]
-.db-job-base:
+ee_compat_check:
+ extends: .rake-exec
+ dependencies: []
+ except:
+ refs:
+ - master
+ - tags
+ - branches@gitlab-org/gitlab
+ - branches@gitlab/gitlab-ee
+ - /^[\d-]+-stable(-ee)?$/
+ - /(^docs[\/-].+|.+-docs$)/
+ - /^security-/
+ artifacts:
+ name: "${CI_JOB_NAME}_${CI_COMIT_REF_NAME}_${CI_COMMIT_SHA}"
+ when: always
+ expire_in: 10d
+ paths:
+ - ee_compat_check/patches/*.patch
+
+# DB migration, rollback, and seed jobs
+db:migrate:reset:
extends:
- - .only-code-rails-job-base
+ - .default-tags
+ - .default-retry
+ - .default-cache
+ - .default-before_script
- .use-pg
+ - .except-docs-qa
stage: test
dependencies: ["setup-test-env"]
needs: ["setup-test-env"]
-
-# DB migration, rollback, and seed jobs
-db:migrate:reset:
- extends: .db-job-base
script:
- bundle exec rake db:migrate:reset
db:check-schema:
- extends: .db-job-base
+ extends:
+ - .default-tags
+ - .default-retry
+ - .default-cache
+ - .default-before_script
+ - .use-pg
+ - .except-docs-qa
+ stage: test
+ dependencies: ["setup-test-env"]
+ needs: ["setup-test-env"]
script:
- source scripts/schema_changed.sh
db:migrate-from-v11.11.0:
- extends: .db-job-base
+ extends:
+ - .default-tags
+ - .default-retry
+ - .default-cache
+ - .default-before_script
+ - .use-pg
+ - .except-docs-qa
+ stage: test
+ dependencies: ["setup-test-env"]
+ needs: ["setup-test-env"]
variables:
SETUP_DB: "false"
script:
- - export PROJECT_TO_CHECKOUT="gitlab-foss"
- - export TAG_TO_CHECKOUT="v11.11.0"
- - '[[ ! -d "ee/" ]] || export PROJECT_TO_CHECKOUT="gitlab"'
- - '[[ ! -d "ee/" ]] || export TAG_TO_CHECKOUT="v11.11.0-ee"'
- - git fetch https://gitlab.com/gitlab-org/$PROJECT_TO_CHECKOUT.git $TAG_TO_CHECKOUT
+ - git fetch https://gitlab.com/gitlab-org/gitlab.git v11.11.0-ee
- git checkout -f FETCH_HEAD
- sed -i "s/gem 'oj', '~> 2.17.4'//" Gemfile
- sed -i "s/gem 'bootsnap', '~> 1.0.0'/gem 'bootsnap'/" Gemfile
@@ -215,13 +254,31 @@ db:migrate-from-v11.11.0:
- bundle exec rake db:migrate
db:rollback:
- extends: .db-job-base
+ extends:
+ - .default-tags
+ - .default-retry
+ - .default-cache
+ - .default-before_script
+ - .use-pg
+ - .except-docs-qa
+ stage: test
+ dependencies: ["setup-test-env"]
+ needs: ["setup-test-env"]
script:
- bundle exec rake db:migrate VERSION=20180101160629
- bundle exec rake db:migrate SKIP_SCHEMA_VERSION_CHECK=true
gitlab:setup:
- extends: .db-job-base
+ extends:
+ - .default-tags
+ - .default-retry
+ - .default-cache
+ - .default-before_script
+ - .use-pg
+ - .except-docs-qa
+ stage: test
+ dependencies: ["setup-test-env"]
+ needs: ["setup-test-env"]
variables:
SETUP_DB: "false"
script:
@@ -238,7 +295,14 @@ gitlab:setup:
- log/development.log
coverage:
- extends: .only-code-rails-job-base
+ # Don't include dedicated-no-docs-no-db-pull-cache-job here since we need to
+ # download artifacts from all the rspec jobs instead of from setup-test-env only
+ extends:
+ - .default-tags
+ - .default-retry
+ - .default-cache
+ - .default-before_script
+ - .except-docs-qa
cache:
policy: pull
variables:
@@ -260,7 +324,7 @@ coverage:
.rspec-base-ee:
extends:
- .rspec-base
- - .only-ee
+ - .only-gitlab-ee
script:
- JOB_NAME=( $CI_JOB_NAME )
- TEST_TOOL=${JOB_NAME[0]}
@@ -298,9 +362,10 @@ rspec system pg ee:
extends: .rspec-base-pg-ee
parallel: 5
-.rspec-base-geo:
- extends: .rspec-base-ee
- parallel: 3
+.rspec-base-pg-geo:
+ extends:
+ - .rspec-base
+ - .only-gitlab-ee
script:
- JOB_NAME=( $CI_JOB_NAME )
- TEST_TOOL=${JOB_NAME[0]}
@@ -317,37 +382,33 @@ rspec system pg ee:
rspec geo pg ee:
extends:
- - .rspec-base-geo
+ - .rspec-base-pg-geo
- .use-pg
- except:
- variables:
- - $CI_COMMIT_REF_NAME =~ /(^geo[\/-].*|.*-geo$)/
+ - .except-docs-qa-geo
+ parallel: 3
rspec geo pg-10 ee:
extends:
- - .rspec-base-geo
+ - .rspec-base-pg-geo
- .use-pg-10
- except:
- variables:
- - $CI_COMMIT_REF_NAME =~ /(^geo[\/-].*|.*-geo$)/
+ - .except-docs-qa-geo
+ parallel: 3
quick-rspec geo pg ee:
extends:
- - .rspec-base-geo
+ - .rspec-base-pg-geo
- .use-pg
stage: quick-test
only:
- variables:
- - $CI_COMMIT_REF_NAME =~ /(^geo[\/-].*|.*-geo$)/
+ - /(^geo[\/-].*|.*-geo$)/
quick-rspec geo pg-10 ee:
extends:
- - .rspec-base-geo
+ - .rspec-base-pg-geo
- .use-pg-10
stage: quick-test
only:
- variables:
- - $CI_COMMIT_REF_NAME =~ /(^geo[\/-].*|.*-geo$)/
+ - /(^geo[\/-].*|.*-geo$)/
rspec quarantine pg ee:
extends: rspec quarantine pg
@@ -356,10 +417,35 @@ rspec quarantine pg ee:
- scripts/gitaly-test-spawn
- bin/rspec --color --format documentation --format RspecJunitFormatter --out junit_rspec.xml --tag quarantine -- ee/spec/
+migration:upgrade-pg-ce-to-ee:
+ extends:
+ - .default-tags
+ - .default-retry
+ - .default-cache
+ - .default-before_script
+ - .use-pg
+ - .except-docs-qa
+ dependencies: ["setup-test-env"]
+ variables:
+ SETUP_DB: "false"
+ script:
+ - ruby -r./scripts/ee_specific_check/ee_specific_check -e'EESpecificCheck.fetch_remote_ce_branch'
+ - git checkout -f FETCH_HEAD
+ - . scripts/utils.sh
+ - . scripts/prepare_build.sh
+ - date
+ - setup_db
+ - date
+ - git checkout -f $CI_COMMIT_SHA
+ - date
+ - . scripts/prepare_build.sh
+ - date
+ - bundle exec rake db:migrate
+
db:rollback geo:
extends:
- db:rollback
- - .only-ee
+ - .only-gitlab-ee
script:
- bundle exec rake geo:db:migrate VERSION=20170627195211
- bundle exec rake geo:db:migrate
diff --git a/.gitlab/ci/reports.gitlab-ci.yml b/.gitlab/ci/reports.gitlab-ci.yml
index 38da73034d5..5622cd232ca 100644
--- a/.gitlab/ci/reports.gitlab-ci.yml
+++ b/.gitlab/ci/reports.gitlab-ci.yml
@@ -1,236 +1,39 @@
-# include:
-# - template: Code-Quality.gitlab-ci.yml
-# - template: Security/SAST.gitlab-ci.yml
-# - template: Security/Dependency-Scanning.gitlab-ci.yml
-# - template: Security/DAST.gitlab-ci.yml
+include:
+ - template: Code-Quality.gitlab-ci.yml
+ - template: Security/SAST.gitlab-ci.yml
+ - template: Security/Dependency-Scanning.gitlab-ci.yml
+ - template: Security/DAST.gitlab-ci.yml
-# We need to duplicate this job's definition because it seems it's impossible to
-# override an included `only.refs`.
-# See https://gitlab.com/gitlab-org/gitlab/issues/31371.
-code_quality:
+.reports:
extends:
- .default-retry
- - .default-only
- - .only-code-changes
- stage: test
- image: docker:stable
- allow_failure: true
- services:
- - docker:stable-dind
- variables:
- DOCKER_DRIVER: overlay2
- DOCKER_TLS_CERTDIR: ""
- script:
- - |
- if ! docker info &>/dev/null; then
- if [ -z "$DOCKER_HOST" -a "$KUBERNETES_PORT" ]; then
- export DOCKER_HOST='tcp://localhost:2375'
- fi
- fi
- - docker run
- --env SOURCE_CODE="$PWD"
- --volume "$PWD":/code
- --volume /var/run/docker.sock:/var/run/docker.sock
- "registry.gitlab.com/gitlab-org/security-products/codequality:12-0-stable" /code
- artifacts:
- reports:
- codequality: gl-code-quality-report.json
- expire_in: 1 week
- dependencies: []
- except:
- variables:
- - $CODE_QUALITY_DISABLED
+ - .except-docs
+
+code_quality:
+ extends: .reports
-# We need to duplicate this job's definition because it seems it's impossible to
-# override an included `only.refs`.
-# See https://gitlab.com/gitlab-org/gitlab/issues/31371.
sast:
- extends:
- - .default-retry
- - .default-only
- - .only-code-changes
- stage: test
- image: docker:stable
+ extends: .reports
variables:
- DOCKER_DRIVER: overlay2
- DOCKER_TLS_CERTDIR: ""
SAST_BRAKEMAN_LEVEL: 2
- SAST_EXCLUDED_PATHS: qa,spec,doc,ee/spec
- allow_failure: true
- services:
- - docker:stable-dind
- script:
- - export SAST_VERSION=${SP_VERSION:-$(echo "$CI_SERVER_VERSION" | sed 's/^\([0-9]*\)\.\([0-9]*\).*/\1-\2-stable/')}
- - |
- if ! docker info &>/dev/null; then
- if [ -z "$DOCKER_HOST" -a "$KUBERNETES_PORT" ]; then
- export DOCKER_HOST='tcp://localhost:2375'
- fi
- fi
- - | # this is required to avoid undesirable reset of Docker image ENV variables being set on build stage
- function propagate_env_vars() {
- CURRENT_ENV=$(printenv)
-
- for VAR_NAME; do
- echo $CURRENT_ENV | grep "${VAR_NAME}=" > /dev/null && echo "--env $VAR_NAME "
- done
- }
- - |
- docker run \
- $(propagate_env_vars \
- SAST_BANDIT_EXCLUDED_PATHS \
- SAST_ANALYZER_IMAGES \
- SAST_ANALYZER_IMAGE_PREFIX \
- SAST_ANALYZER_IMAGE_TAG \
- SAST_DEFAULT_ANALYZERS \
- SAST_PULL_ANALYZER_IMAGES \
- SAST_BRAKEMAN_LEVEL \
- SAST_FLAWFINDER_LEVEL \
- SAST_GITLEAKS_ENTROPY_LEVEL \
- SAST_GOSEC_LEVEL \
- SAST_EXCLUDED_PATHS \
- SAST_DOCKER_CLIENT_NEGOTIATION_TIMEOUT \
- SAST_PULL_ANALYZER_IMAGE_TIMEOUT \
- SAST_RUN_ANALYZER_TIMEOUT \
- SAST_JAVA_VERSION \
- ANT_HOME \
- ANT_PATH \
- GRADLE_PATH \
- JAVA_OPTS \
- JAVA_PATH \
- JAVA_8_VERSION \
- JAVA_11_VERSION \
- MAVEN_CLI_OPTS \
- MAVEN_PATH \
- MAVEN_REPO_PATH \
- SBT_PATH \
- FAIL_NEVER \
- ) \
- --volume "$PWD:/code" \
- --volume /var/run/docker.sock:/var/run/docker.sock \
- "registry.gitlab.com/gitlab-org/security-products/sast:$SAST_VERSION" /app/bin/run /code
+ SAST_EXCLUDED_PATHS: qa,spec,doc
artifacts:
expire_in: 7 days
paths:
- gl-sast-report.json
- reports:
- sast: gl-sast-report.json
- dependencies: []
- only:
- variables:
- - $GITLAB_FEATURES =~ /\bsast\b/
- except:
- variables:
- - $SAST_DISABLED
-# We need to duplicate this job's definition because it seems it's impossible to
-# override an included `only.refs`.
-# See https://gitlab.com/gitlab-org/gitlab/issues/31371.
dependency_scanning:
- extends:
- - .default-retry
- - .default-only
- - .only-code-changes
- stage: test
- image: docker:stable
- variables:
- DOCKER_DRIVER: overlay2
- DOCKER_TLS_CERTDIR: ""
- allow_failure: true
- services:
- - docker:stable-dind
- script:
- - export DS_VERSION=${SP_VERSION:-$(echo "$CI_SERVER_VERSION" | sed 's/^\([0-9]*\)\.\([0-9]*\).*/\1-\2-stable/')}
- - |
- if ! docker info &>/dev/null; then
- if [ -z "$DOCKER_HOST" -a "$KUBERNETES_PORT" ]; then
- export DOCKER_HOST='tcp://localhost:2375'
- fi
- fi
- - | # this is required to avoid undesirable reset of Docker image ENV variables being set on build stage
- function propagate_env_vars() {
- CURRENT_ENV=$(printenv)
+ extends: .reports
- for VAR_NAME; do
- echo $CURRENT_ENV | grep "${VAR_NAME}=" > /dev/null && echo "--env $VAR_NAME "
- done
- }
- - |
- docker run \
- $(propagate_env_vars \
- DS_ANALYZER_IMAGES \
- DS_ANALYZER_IMAGE_PREFIX \
- DS_ANALYZER_IMAGE_TAG \
- DS_DEFAULT_ANALYZERS \
- DS_EXCLUDED_PATHS \
- DEP_SCAN_DISABLE_REMOTE_CHECKS \
- DS_DOCKER_CLIENT_NEGOTIATION_TIMEOUT \
- DS_PULL_ANALYZER_IMAGE_TIMEOUT \
- DS_RUN_ANALYZER_TIMEOUT \
- DS_PYTHON_VERSION \
- DS_PIP_DEPENDENCY_PATH \
- PIP_INDEX_URL \
- PIP_EXTRA_INDEX_URL \
- ) \
- --volume "$PWD:/code" \
- --volume /var/run/docker.sock:/var/run/docker.sock \
- "registry.gitlab.com/gitlab-org/security-products/dependency-scanning:$DS_VERSION" /code
- artifacts:
- reports:
- dependency_scanning: gl-dependency-scanning-report.json
- dependencies: []
- only:
- variables:
- - $GITLAB_FEATURES =~ /\bdependency_scanning\b/
- except:
- variables:
- - $DEPENDENCY_SCANNING_DISABLED
-
-# We need to duplicate this job's definition because it seems it's impossible to
-# override an included `only.refs`.
-# See https://gitlab.com/gitlab-org/gitlab/issues/31371.
dast:
extends:
- - .default-retry
- - .default-only
- - .only-code-qa-changes
- - .only-review
+ - .reports
+ - .review-only
stage: qa
dependencies: ["review-deploy"]
before_script:
- export DAST_WEBSITE="$(cat review_app_url.txt)"
- image:
- name: "registry.gitlab.com/gitlab-org/security-products/dast:$CI_SERVER_VERSION_MAJOR-$CI_SERVER_VERSION_MINOR-stable"
- variables:
- # URL to scan:
- # DAST_WEBSITE: https://example.com/
- #
- # Time limit for target availability (scan is attempted even when timeout):
- # DAST_TARGET_AVAILABILITY_TIMEOUT: 60
- #
- # Set these variables to scan with an authenticated user:
- # DAST_AUTH_URL: https://example.com/sign-in
- # DAST_USERNAME: john.doe@example.com
- # DAST_PASSWORD: john-doe-password
- # DAST_USERNAME_FIELD: session[user] # the name of username field at the sign-in HTML form
- # DAST_PASSWORD_FIELD: session[password] # the name of password field at the sign-in HTML form
- # DAST_AUTH_EXCLUDE_URLS: http://example.com/sign-out,http://example.com/sign-out-2 # optional: URLs to skip during the authenticated scan; comma-separated, no spaces in between
- #
- # Perform ZAP Full Scan, which includes both passive and active scanning:
- # DAST_FULL_SCAN_ENABLED: "true"
- allow_failure: true
- script:
- - export DAST_WEBSITE=${DAST_WEBSITE:-$(cat environment_url.txt)}
- - /analyze -t $DAST_WEBSITE
artifacts:
expire_in: 7 days
paths:
- gl-dast-report.json
- reports:
- dast: gl-dast-report.json
- only:
- variables:
- - $GITLAB_FEATURES =~ /\bdast\b/
- except:
- variables:
- - $DAST_DISABLED
diff --git a/.gitlab/ci/review.gitlab-ci.yml b/.gitlab/ci/review.gitlab-ci.yml
index c7b79dac9dd..a269e15611f 100644
--- a/.gitlab/ci/review.gitlab-ci.yml
+++ b/.gitlab/ci/review.gitlab-ci.yml
@@ -1,10 +1,21 @@
+.review-schedules-only:
+ only:
+ refs:
+ - schedules@gitlab-org/gitlab-foss
+ - schedules@gitlab-org/gitlab
+ kubernetes: active
+ variables:
+ - $REVIEW_APP_CLEANUP
+ except:
+ refs:
+ - tags
+ - /(^docs[\/-].+|.+-docs$)/
+
.review-base:
extends:
- .default-tags
- .default-retry
- - .default-only
- - .only-review
- - .only-code-qa-changes
+ - .review-only
image: registry.gitlab.com/gitlab-org/gitlab-build-images:gitlab-charts-build-base
dependencies: []
before_script:
@@ -14,7 +25,6 @@
extends:
- .default-tags
- .default-retry
- - .default-only
image: registry.gitlab.com/gitlab-org/gitlab-build-images:gitlab-qa-alpine
services:
- docker:19.03.0-dind
@@ -24,27 +34,24 @@
variables:
DOCKER_DRIVER: overlay2
DOCKER_HOST: tcp://docker:2375
- GITLAB_EDITION: "ce"
+ LATEST_QA_IMAGE: "gitlab/${CI_PROJECT_NAME}-qa:nightly"
+ QA_IMAGE: "${CI_REGISTRY}/${CI_PROJECT_PATH}/gitlab/${CI_PROJECT_NAME}-qa:${CI_COMMIT_REF_SLUG}"
build-qa-image:
extends:
- .review-docker
- - .only-code-qa-changes
+ - .except-docs
only:
- variables:
- - $CI_SERVER_HOST == "gitlab.com" && $CI_PROJECT_NAMESPACE == "gitlab-org"
- stage: prepare
+ refs:
+ - branches@gitlab-org/gitlab-foss
+ - branches@gitlab-org/gitlab
+ stage: test
script:
- - '[[ ! -d "ee/" ]] || export GITLAB_EDITION="ee"'
- - export QA_IMAGE="${CI_REGISTRY}/${CI_PROJECT_PATH}/gitlab/gitlab-${GITLAB_EDITION}-qa:${CI_COMMIT_REF_SLUG}"
- - time docker build --cache-from gitlab/gitlab-${GITLAB_EDITION}-qa:nightly --tag ${QA_IMAGE} --file ./qa/Dockerfile ./
+ - time docker build --cache-from ${LATEST_QA_IMAGE} --tag ${QA_IMAGE} --file ./qa/Dockerfile ./
- echo "${CI_JOB_TOKEN}" | docker login --username gitlab-ci-token --password-stdin ${CI_REGISTRY}
- time docker push ${QA_IMAGE}
.review-build-cng-base:
- extends:
- - .default-only
- - .only-code-qa-changes
image: ruby:2.6-alpine
stage: review-prepare
before_script:
@@ -58,13 +65,13 @@ build-qa-image:
review-build-cng:
extends:
- .review-build-cng-base
- - .only-review
+ - .review-only
needs: ["gitlab:assets:compile pull-cache"]
schedule:review-build-cng:
extends:
- .review-build-cng-base
- - .only-review-schedules
+ - .review-schedules-only
needs: ["gitlab:assets:compile"]
.review-deploy-base:
@@ -75,13 +82,11 @@ schedule:review-build-cng:
HOST_SUFFIX: "${CI_ENVIRONMENT_SLUG}"
DOMAIN: "-${CI_ENVIRONMENT_SLUG}.${REVIEW_APPS_DOMAIN}"
GITLAB_HELM_CHART_REF: "master"
- GITLAB_EDITION: "ce"
environment:
name: review/${CI_COMMIT_REF_NAME}
url: https://gitlab-${CI_ENVIRONMENT_SLUG}.${REVIEW_APPS_DOMAIN}
on_stop: review-stop
before_script:
- - '[[ ! -d "ee/" ]] || export GITLAB_EDITION="ee"'
- export GITLAB_SHELL_VERSION=$(<GITLAB_SHELL_VERSION)
- export GITALY_VERSION=$(<GITALY_SERVER_VERSION)
- export GITLAB_WORKHORSE_VERSION=$(<GITLAB_WORKHORSE_VERSION)
@@ -110,7 +115,7 @@ review-deploy:
schedule:review-deploy:
extends:
- .review-deploy-base
- - .only-review-schedules
+ - .review-schedules-only
needs: ["schedule:review-build-cng"]
review-stop:
@@ -145,8 +150,7 @@ review-cleanup-failed-deployment:
.review-qa-base:
extends:
- .review-docker
- - .only-review
- - .only-code-qa-changes
+ - .review-only
stage: qa
variables:
QA_ARTIFACTS_DIR: "${CI_PROJECT_DIR}/qa"
@@ -165,8 +169,6 @@ review-cleanup-failed-deployment:
expire_in: 7 days
when: always
before_script:
- - '[[ ! -d "ee/" ]] || export GITLAB_EDITION="ee"'
- - export QA_IMAGE="${CI_REGISTRY}/${CI_PROJECT_PATH}/gitlab/gitlab-${GITLAB_EDITION}-qa:${CI_COMMIT_REF_SLUG}"
- export CI_ENVIRONMENT_URL="$(cat review_app_url.txt)"
- echo "${CI_ENVIRONMENT_URL}"
- echo "${QA_IMAGE}"
@@ -193,9 +195,7 @@ review-qa-all:
parallel-spec-reports:
extends:
- .default-tags
- - .default-only
- - .only-code-qa-changes
- - .only-review
+ - .except-docs
image: ruby:2.6-alpine
stage: post-test
dependencies: ["review-qa-all"]
@@ -242,14 +242,14 @@ review-performance:
schedule:review-performance:
extends:
- review-performance
- - .only-review-schedules
+ - .review-schedules-only
dependencies: ["schedule:review-deploy"]
schedule:review-cleanup:
extends:
- .review-base
- - .only-review-schedules
- stage: prepare
+ - .review-schedules-only
+ stage: build
allow_failure: true
environment:
name: review/auto-cleanup
@@ -265,7 +265,6 @@ danger-review:
- .default-tags
- .default-retry
- .default-cache
- - .default-only
image: registry.gitlab.com/gitlab-org/gitlab-build-images:danger
stage: test
dependencies: []
@@ -275,9 +274,10 @@ danger-review:
except:
refs:
- master
- variables:
- - $CI_COMMIT_REF_NAME =~ /^\d+-\d+-auto-deploy-\d+$/
- - $CI_COMMIT_REF_NAME =~ /^[\d-]+-stable(-ee)?$/
+ - /^\d+-\d+-auto-deploy-\d+$/
+ - /^[\d-]+-stable(-ee)?$/
+ - /^ce-to-ee-.*/
+ - /.*-stable(-ee)?-prepare-.*/
script:
- git version
- node --version
diff --git a/.gitlab/ci/setup.gitlab-ci.yml b/.gitlab/ci/setup.gitlab-ci.yml
index e673eb9c7f3..d29907b3683 100644
--- a/.gitlab/ci/setup.gitlab-ci.yml
+++ b/.gitlab/ci/setup.gitlab-ci.yml
@@ -6,6 +6,7 @@ cache gems:
- .default-retry
- .default-cache
- .default-before_script
+ - .except-docs
stage: test
dependencies: ["setup-test-env"]
needs: ["setup-test-env"]
@@ -18,17 +19,15 @@ cache gems:
- vendor/cache
only:
refs:
- - master
+ - master@gitlab-org/gitlab-foss
+ - master@gitlab-org/gitlab
- tags
- variables:
- - $CI_SERVER_HOST == "gitlab.com" && $CI_PROJECT_NAMESPACE == "gitlab-org"
.minimal-job:
extends:
- .default-tags
- .default-retry
- - .default-only
- - .only-code-changes
+ - .except-docs-qa
dependencies: []
gitlab_git_test:
@@ -41,6 +40,5 @@ no_ee_check:
script:
- scripts/no-ee-check
only:
- variables:
- - $CI_SERVER_HOST == "gitlab.com" && $CI_PROJECT_NAME == "gitlab-foss"
- - $CI_SERVER_HOST == "dev.gitlab.org" && $CI_PROJECT_NAME == "gitlabhq"
+ refs:
+ - branches@gitlab-org/gitlab-foss
diff --git a/.gitlab/ci/test-metadata.gitlab-ci.yml b/.gitlab/ci/test-metadata.gitlab-ci.yml
index fe3cde2bb16..14c230deb47 100644
--- a/.gitlab/ci/test-metadata.gitlab-ci.yml
+++ b/.gitlab/ci/test-metadata.gitlab-ci.yml
@@ -1,5 +1,4 @@
.tests-metadata-state:
- extends: .default-only
variables:
TESTS_METADATA_S3_BUCKET: "gitlab-ce-cache"
before_script:
@@ -14,7 +13,7 @@
retrieve-tests-metadata:
extends:
- .tests-metadata-state
- - .only-code-changes
+ - .except-docs-qa
stage: prepare
cache:
key: tests_metadata
@@ -27,8 +26,8 @@ retrieve-tests-metadata:
- mkdir -p rspec_profiling/
- wget -O $FLAKY_RSPEC_SUITE_REPORT_PATH http://${TESTS_METADATA_S3_BUCKET}.s3.amazonaws.com/$FLAKY_RSPEC_SUITE_REPORT_PATH || rm $FLAKY_RSPEC_SUITE_REPORT_PATH
- '[[ -f $FLAKY_RSPEC_SUITE_REPORT_PATH ]] || echo "{}" > ${FLAKY_RSPEC_SUITE_REPORT_PATH}'
- - '[[ ! -d "ee/" ]] || wget -O $EE_KNAPSACK_RSPEC_SUITE_REPORT_PATH http://${TESTS_METADATA_S3_BUCKET}.s3.amazonaws.com/$EE_KNAPSACK_RSPEC_SUITE_REPORT_PATH || rm $EE_KNAPSACK_RSPEC_SUITE_REPORT_PATH'
- - '[[ ! -d "ee/" ]] || [[ -f $EE_KNAPSACK_RSPEC_SUITE_REPORT_PATH ]] || echo "{}" > ${EE_KNAPSACK_RSPEC_SUITE_REPORT_PATH}'
+ - wget -O $EE_KNAPSACK_RSPEC_SUITE_REPORT_PATH http://${TESTS_METADATA_S3_BUCKET}.s3.amazonaws.com/$EE_KNAPSACK_RSPEC_SUITE_REPORT_PATH || rm $EE_KNAPSACK_RSPEC_SUITE_REPORT_PATH
+ - '[[ -f $EE_KNAPSACK_RSPEC_SUITE_REPORT_PATH ]] || echo "{}" > ${EE_KNAPSACK_RSPEC_SUITE_REPORT_PATH}'
update-tests-metadata:
extends: .tests-metadata-state
@@ -44,9 +43,9 @@ update-tests-metadata:
- echo "{}" > ${KNAPSACK_RSPEC_SUITE_REPORT_PATH}
- scripts/merge-reports ${KNAPSACK_RSPEC_SUITE_REPORT_PATH} knapsack/${CI_PROJECT_NAME}/rspec_*_pg_node_*.json
- '[[ -z ${TESTS_METADATA_S3_BUCKET} ]] || scripts/sync-reports put $TESTS_METADATA_S3_BUCKET $KNAPSACK_RSPEC_SUITE_REPORT_PATH'
- - '[[ ! -d "ee/" ]] || echo "{}" > ${EE_KNAPSACK_RSPEC_SUITE_REPORT_PATH}'
- - '[[ ! -d "ee/" ]] || scripts/merge-reports ${EE_KNAPSACK_RSPEC_SUITE_REPORT_PATH} knapsack/${CI_PROJECT_NAME}/rspec_*_pg_ee_*node_*.json'
- - '[[ ! -d "ee/" ]] || [[ -z ${TESTS_METADATA_S3_BUCKET} ]] || scripts/sync-reports put $TESTS_METADATA_S3_BUCKET $EE_KNAPSACK_RSPEC_SUITE_REPORT_PATH'
+ - echo "{}" > ${EE_KNAPSACK_RSPEC_SUITE_REPORT_PATH}
+ - scripts/merge-reports ${EE_KNAPSACK_RSPEC_SUITE_REPORT_PATH} knapsack/${CI_PROJECT_NAME}/rspec_*_pg_ee_*node_*.json
+ - '[[ -z ${TESTS_METADATA_S3_BUCKET} ]] || scripts/sync-reports put $TESTS_METADATA_S3_BUCKET $EE_KNAPSACK_RSPEC_SUITE_REPORT_PATH'
- rm -f knapsack/${CI_PROJECT_NAME}/*_node_*.json
- scripts/merge-reports ${FLAKY_RSPEC_SUITE_REPORT_PATH} rspec_flaky/all_*_*.json
- FLAKY_RSPEC_GENERATE_REPORT=1 scripts/prune-old-flaky-specs ${FLAKY_RSPEC_SUITE_REPORT_PATH}
@@ -55,17 +54,15 @@ update-tests-metadata:
- scripts/insert-rspec-profiling-data
only:
refs:
- - master
- variables:
- - $CI_SERVER_HOST == "gitlab.com" && $CI_PROJECT_NAMESPACE == "gitlab-org"
- - $CI_SERVER_HOST == "dev.gitlab.org"
+ - master@gitlab-org/gitlab-foss
+ - master@gitlab-org/gitlab
+ - master@gitlab/gitlabhq
+ - master@gitlab/gitlab-ee
flaky-examples-check:
extends:
- .default-tags
- .default-retry
- - .default-only
- - .only-code-changes
image: ruby:2.6-alpine
stage: post-test
variables:
@@ -73,7 +70,12 @@ flaky-examples-check:
allow_failure: true
only:
refs:
- - merge_requests
+ - branches
+ except:
+ refs:
+ - master
+ - /(^docs[\/-].+|.+-docs$)/
+ - /(^qa[\/-].*|.*-qa$)/
artifacts:
expire_in: 30d
paths:
diff --git a/.gitlab/ci/yaml.gitlab-ci.yml b/.gitlab/ci/yaml.gitlab-ci.yml
index 323f94b6d04..dd61cb3f035 100644
--- a/.gitlab/ci/yaml.gitlab-ci.yml
+++ b/.gitlab/ci/yaml.gitlab-ci.yml
@@ -4,10 +4,7 @@ lint-ci-gitlab:
extends:
- .default-tags
- .default-retry
- - .default-only
- only:
- changes:
- - "**/*.yml"
+ - .except-docs
image: sdesbure/yamllint:latest
dependencies: []
script:
diff --git a/.gitlab/issue_templates/Problem_Validation.md b/.gitlab/issue_templates/Problem_Validation.md
deleted file mode 100644
index d2bab21eb06..00000000000
--- a/.gitlab/issue_templates/Problem_Validation.md
+++ /dev/null
@@ -1,41 +0,0 @@
-## Problem Statement
-
-<!-- What is the problem we hope to validate and solve? -->
-
-## Reach
-
-<!-- Please describe who suffers from this problem. Consider referring to our personas, which are described at https://about.gitlab.com/handbook/marketing/product-marketing/roles-personas/ -->
-
-<!-- Please also quantify the problem's reach using the following values, considering an aggregate across GitLab.com and self-managed:
-
-10.0 = Impacts the vast majority (~80% or greater) of our users, prospects, or customers.
-6.0 = Impacts a large percentage (~50% to ~80%) of the above.
-3.0 = Significant reach (~25% to ~50%).
-1.5 = Small reach (~5% to ~25%).
-0.5 = Minimal reach (Less than ~5%). -->
-
-## Impact
-
-<!-- How do we positively impact the users above and GitLab's business by solving this problem? Please describe briefly, and provide a numerical assessment:
-
-3.0 = Massive impact
-2.0 = High impact
-1.0 = Medium impact
-0.5 = Low impact
-0.25 = Minimal impact -->
-
-## Confidence
-
-<!-- How do we know this is a problem? Please provide and link to any supporting information (e.g. data, customer verbatims) and use this basis to provide a numerical assessment on our confidence level in this problem's severity:
-
-100% = High confidence
-80% = Medium confidence
-50% = Low confidence -->
-
-## Effort
-
-<!-- How much effort do we think it will be to solve this problem? Please include all counterparts (Product, UX, Engineering, etc) in your assessment and quantify the number of person-months needed to dedicate to the effort.
-
-For example, if the solution will take a product manager, designer, and engineer two weeks of effort - you may quantify this as 1.5 (based on 0.5 months x 3 people). -->
-
-/label ~"workflow::problem backlog"
diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml
index 48b840b4af2..f1f8ff6e862 100644
--- a/.rubocop_todo.yml
+++ b/.rubocop_todo.yml
@@ -565,6 +565,11 @@ Style/EmptyLiteral:
Style/EmptyMethod:
Enabled: false
+# Offense count: 40
+# Cop supports --auto-correct.
+Style/Encoding:
+ Enabled: false
+
# Offense count: 203
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle.
diff --git a/16790-render-xml-artifacts.yml b/16790-render-xml-artifacts.yml
deleted file mode 100644
index d9cfcc04a68..00000000000
--- a/16790-render-xml-artifacts.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Render xml artifact files in GitLab
-merge_request: 16790
-author:
-type: added
diff --git a/GITLAB_PAGES_VERSION b/GITLAB_PAGES_VERSION
index f8e233b2733..a8fdfda1c78 100644
--- a/GITLAB_PAGES_VERSION
+++ b/GITLAB_PAGES_VERSION
@@ -1 +1 @@
-1.9.0
+1.8.1
diff --git a/Gemfile b/Gemfile
index 864e514ae0d..ab01b6b72da 100644
--- a/Gemfile
+++ b/Gemfile
@@ -326,7 +326,7 @@ group :metrics do
gem 'influxdb', '~> 0.2', require: false
# Prometheus
- gem 'prometheus-client-mmap', '~> 0.9.10'
+ gem 'prometheus-client-mmap', '~> 0.9.9'
gem 'raindrops', '~> 0.18'
end
diff --git a/Gemfile.lock b/Gemfile.lock
index fec34622be3..6fd74c1da78 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -715,7 +715,7 @@ GEM
parser
unparser
procto (0.0.3)
- prometheus-client-mmap (0.9.10)
+ prometheus-client-mmap (0.9.9)
pry (0.11.3)
coderay (~> 1.1.0)
method_source (~> 0.9.0)
@@ -1250,7 +1250,7 @@ DEPENDENCIES
org-ruby (~> 0.9.12)
pg (~> 1.1)
premailer-rails (~> 1.9.7)
- prometheus-client-mmap (~> 0.9.10)
+ prometheus-client-mmap (~> 0.9.9)
pry-byebug (~> 3.5.1)
pry-rails (~> 0.3.4)
puma (~> 3.12)
diff --git a/app/assets/javascripts/blob/template_selector.js b/app/assets/javascripts/blob/template_selector.js
index 9e69c7d7164..37e348d93d3 100644
--- a/app/assets/javascripts/blob/template_selector.js
+++ b/app/assets/javascripts/blob/template_selector.js
@@ -1,4 +1,4 @@
-/* eslint-disable class-methods-use-this */
+/* eslint-disable class-methods-use-this, no-unused-vars */
import $ from 'jquery';
@@ -61,7 +61,7 @@ export default class TemplateSelector {
return this.requestFile(item);
}
- requestFile() {
+ requestFile(item) {
// This `requestFile` method is an abstract method that should
// be added by all subclasses.
}
diff --git a/app/assets/javascripts/clusters/clusters_bundle.js b/app/assets/javascripts/clusters/clusters_bundle.js
index 28850710f80..d386960f3b6 100644
--- a/app/assets/javascripts/clusters/clusters_bundle.js
+++ b/app/assets/javascripts/clusters/clusters_bundle.js
@@ -111,15 +111,25 @@ export default class Clusters {
this.initApplications(clusterType);
this.initEnvironments();
- if (clusterEnvironmentsPath) {
- this.fetchEnvironments();
+ if (clusterEnvironmentsPath && this.environments) {
+ this.store.toggleFetchEnvironments(true);
+
+ this.initPolling(
+ 'fetchClusterEnvironments',
+ data => this.handleClusterEnvironmentsSuccess(data),
+ () => this.handleEnvironmentsPollError(),
+ );
}
this.updateContainer(null, this.store.state.status, this.store.state.statusReason);
this.addListeners();
if (statusPath && !this.environments) {
- this.initPolling();
+ this.initPolling(
+ 'fetchClusterStatus',
+ data => this.handleClusterStatusSuccess(data),
+ () => this.handlePollError(),
+ );
}
}
@@ -179,16 +189,9 @@ export default class Clusters {
});
}
- fetchEnvironments() {
- this.store.toggleFetchEnvironments(true);
-
- this.service
- .fetchClusterEnvironments()
- .then(data => {
- this.store.toggleFetchEnvironments(false);
- this.store.updateEnvironments(data.data);
- })
- .catch(() => Clusters.handleError());
+ handleClusterEnvironmentsSuccess(data) {
+ this.store.toggleFetchEnvironments(false);
+ this.store.updateEnvironments(data.data);
}
static initDismissableCallout() {
@@ -224,21 +227,16 @@ export default class Clusters {
eventHub.$off('uninstallApplication');
}
- initPolling() {
+ initPolling(method, successCallback, errorCallback) {
this.poll = new Poll({
resource: this.service,
- method: 'fetchData',
- successCallback: data => this.handleSuccess(data),
- errorCallback: () => Clusters.handleError(),
+ method,
+ successCallback,
+ errorCallback,
});
if (!Visibility.hidden()) {
this.poll.makeRequest();
- } else {
- this.service
- .fetchData()
- .then(data => this.handleSuccess(data))
- .catch(() => Clusters.handleError());
}
Visibility.change(() => {
@@ -250,11 +248,21 @@ export default class Clusters {
});
}
+ handlePollError() {
+ this.constructor.handleError();
+ }
+
+ handleEnvironmentsPollError() {
+ this.store.toggleFetchEnvironments(false);
+
+ this.handlePollError();
+ }
+
static handleError() {
Flash(s__('ClusterIntegration|Something went wrong on our end.'));
}
- handleSuccess(data) {
+ handleClusterStatusSuccess(data) {
const prevStatus = this.store.state.status;
const prevApplicationMap = Object.assign({}, this.store.state.applications);
diff --git a/app/assets/javascripts/clusters/services/clusters_service.js b/app/assets/javascripts/clusters/services/clusters_service.js
index 9139e0beafb..fa12802b3de 100644
--- a/app/assets/javascripts/clusters/services/clusters_service.js
+++ b/app/assets/javascripts/clusters/services/clusters_service.js
@@ -17,7 +17,7 @@ export default class ClusterService {
};
}
- fetchData() {
+ fetchClusterStatus() {
return axios.get(this.options.endpoint);
}
diff --git a/app/assets/javascripts/clusters/stores/clusters_store.js b/app/assets/javascripts/clusters/stores/clusters_store.js
index a032f589ee4..5cddb4cc098 100644
--- a/app/assets/javascripts/clusters/stores/clusters_store.js
+++ b/app/assets/javascripts/clusters/stores/clusters_store.js
@@ -218,6 +218,7 @@ export default class ClusterStore {
environmentPath: environment.environment_path,
lastDeployment: environment.last_deployment,
rolloutStatus: {
+ status: environment.rollout_status ? environment.rollout_status.status : null,
instances: environment.rollout_status ? environment.rollout_status.instances : [],
},
updatedAt: environment.updated_at,
diff --git a/app/assets/javascripts/commit/image_file.js b/app/assets/javascripts/commit/image_file.js
index 9454f760df8..bc666aef54b 100644
--- a/app/assets/javascripts/commit/image_file.js
+++ b/app/assets/javascripts/commit/image_file.js
@@ -1,4 +1,4 @@
-/* eslint-disable func-names, no-var, prefer-arrow-callback, no-else-return, consistent-return, prefer-template, one-var, no-return-assign, no-unused-expressions, no-sequences */
+/* eslint-disable func-names, no-var, prefer-arrow-callback, no-else-return, consistent-return, prefer-template, one-var, no-unused-vars, no-return-assign, no-unused-expressions, no-sequences */
import $ from 'jquery';
@@ -12,8 +12,11 @@ export default class ImageFile {
this.requestImageInfo(
$('.two-up.view .frame.deleted img', this.file),
(function(_this) {
- return function() {
- return _this.requestImageInfo($('.two-up.view .frame.added img', _this.file), function() {
+ return function(deletedWidth, deletedHeight) {
+ return _this.requestImageInfo($('.two-up.view .frame.added img', _this.file), function(
+ width,
+ height,
+ ) {
_this.initViewModes();
// Load two-up view after images are loaded
@@ -109,7 +112,7 @@ export default class ImageFile {
maxHeight = 0;
$('.frame', view)
.each(
- (function() {
+ (function(_this) {
return function(index, frame) {
var height, width;
width = $(frame).width();
@@ -193,7 +196,13 @@ export default class ImageFile {
return $('.onion-skin.view', this.file).each(
(function(_this) {
return function(index, view) {
- var $frame, $track, $dragger, $frameAdded, framePadding, ref;
+ var $frame,
+ $track,
+ $dragger,
+ $frameAdded,
+ framePadding,
+ ref,
+ dragging = false;
(ref = _this.prepareFrames(view)), ([maxWidth, maxHeight] = ref);
$frame = $('.onion-skin-frame', view);
$frameAdded = $('.frame.added', view);
diff --git a/app/assets/javascripts/create_cluster/eks_cluster/components/cluster_form_dropdown.vue b/app/assets/javascripts/create_cluster/eks_cluster/components/cluster_form_dropdown.vue
deleted file mode 100644
index f9465da6fda..00000000000
--- a/app/assets/javascripts/create_cluster/eks_cluster/components/cluster_form_dropdown.vue
+++ /dev/null
@@ -1,182 +0,0 @@
-<script>
-import DropdownSearchInput from '~/vue_shared/components/dropdown/dropdown_search_input.vue';
-import DropdownHiddenInput from '~/vue_shared/components/dropdown/dropdown_hidden_input.vue';
-import DropdownButton from '~/vue_shared/components/dropdown/dropdown_button.vue';
-
-export default {
- components: {
- DropdownButton,
- DropdownSearchInput,
- DropdownHiddenInput,
- },
- props: {
- fieldName: {
- type: String,
- required: false,
- default: '',
- },
- placeholder: {
- type: String,
- required: false,
- default: '',
- },
- defaultValue: {
- type: String,
- required: false,
- default: '',
- },
- value: {
- type: Object,
- required: false,
- default: () => null,
- },
- labelProperty: {
- type: String,
- required: false,
- default: 'name',
- },
- valueProperty: {
- type: String,
- required: false,
- default: 'value',
- },
- items: {
- type: Array,
- required: false,
- default: () => [],
- },
- loading: {
- type: Boolean,
- required: false,
- default: false,
- },
- disabled: {
- type: Boolean,
- required: false,
- default: false,
- },
- loadingText: {
- type: String,
- required: false,
- default: '',
- },
- disabledText: {
- type: String,
- required: false,
- default: '',
- },
- hasErrors: {
- type: Boolean,
- required: false,
- default: false,
- },
- errorMessage: {
- type: String,
- required: false,
- default: '',
- },
- searchFieldPlaceholder: {
- type: String,
- required: false,
- default: '',
- },
- emptyText: {
- type: String,
- required: false,
- default: '',
- },
- searchFn: {
- type: Function,
- required: false,
- default: searchQuery => item => item.name.toLowerCase().indexOf(searchQuery) > -1,
- },
- },
- data() {
- return {
- searchQuery: '',
- selectedItem: null,
- };
- },
- computed: {
- toggleText() {
- if (this.loading && this.loadingText) {
- return this.loadingText;
- }
-
- if (this.disabled && this.disabledText) {
- return this.disabledText;
- }
-
- if (!this.selectedItem) {
- return this.placeholder;
- }
-
- return this.selectedItemLabel;
- },
- results() {
- if (!this.items) {
- return [];
- }
-
- return this.items.filter(this.searchFn(this.searchQuery));
- },
- selectedItemLabel() {
- return this.selectedItem && this.selectedItem[this.labelProperty];
- },
- selectedItemValue() {
- return (this.selectedItem && this.selectedItem[this.valueProperty]) || '';
- },
- },
- methods: {
- select(item) {
- this.selectedItem = item;
- this.$emit('input', item);
- },
- },
-};
-</script>
-
-<template>
- <div>
- <div class="js-gcp-machine-type-dropdown dropdown">
- <dropdown-hidden-input :name="fieldName" :value="selectedItemValue" />
- <dropdown-button
- :class="{ 'border-danger': hasErrors }"
- :is-disabled="disabled"
- :is-loading="loading"
- :toggle-text="toggleText"
- />
- <div class="dropdown-menu dropdown-select">
- <dropdown-search-input v-model="searchQuery" :placeholder-text="searchFieldPlaceholder" />
- <div class="dropdown-content">
- <ul>
- <li v-if="!results.length">
- <span class="js-empty-text menu-item">
- {{ emptyText }}
- </span>
- </li>
- <li v-for="item in results" :key="item.id">
- <button class="js-dropdown-item" type="button" @click.prevent="select(item)">
- <slot name="item" :item="item">
- {{ item.name }}
- </slot>
- </button>
- </li>
- </ul>
- </div>
- </div>
- </div>
- <span
- v-if="hasErrors && errorMessage"
- :class="[
- 'form-text js-eks-dropdown-error-message',
- {
- 'text-danger': hasErrors,
- 'text-muted': !hasErrors,
- },
- ]"
- >
- {{ errorMessage }}
- </span>
- </div>
-</template>
diff --git a/app/assets/javascripts/create_cluster/eks_cluster/components/eks_cluster_configuration_form.vue b/app/assets/javascripts/create_cluster/eks_cluster/components/eks_cluster_configuration_form.vue
index 6e74963dcb0..1ec45c8b651 100644
--- a/app/assets/javascripts/create_cluster/eks_cluster/components/eks_cluster_configuration_form.vue
+++ b/app/assets/javascripts/create_cluster/eks_cluster/components/eks_cluster_configuration_form.vue
@@ -14,12 +14,5 @@ export default {
};
</script>
<template>
- <form name="eks-cluster-configuration-form">
- <div class="form-group">
- <label class="label-bold" name="role" for="eks-role">
- {{ s__('ClusterIntegration|Role name') }}
- </label>
- <role-name-dropdown />
- </div>
- </form>
+ <form name="eks-cluster-configuration-form"></form>
</template>
diff --git a/app/assets/javascripts/create_cluster/eks_cluster/components/role_name_dropdown.vue b/app/assets/javascripts/create_cluster/eks_cluster/components/role_name_dropdown.vue
index 70230b294ac..e69de29bb2d 100644
--- a/app/assets/javascripts/create_cluster/eks_cluster/components/role_name_dropdown.vue
+++ b/app/assets/javascripts/create_cluster/eks_cluster/components/role_name_dropdown.vue
@@ -1,53 +0,0 @@
-<script>
-import { sprintf, s__ } from '~/locale';
-
-import ClusterFormDropdown from './cluster_form_dropdown.vue';
-
-export default {
- components: {
- ClusterFormDropdown,
- },
- props: {
- roles: {
- type: Array,
- required: false,
- default: () => [],
- },
- loading: {
- type: Boolean,
- required: false,
- default: false,
- },
- },
- computed: {
- helpText() {
- return sprintf(
- s__(
- 'ClusterIntegration|Select the IAM Role to allow Amazon EKS and the Kubernetes control plane to manage AWS resources on your behalf. To use a new role name, first create one on %{startLink}Amazon Web Services%{endLink}.',
- ),
- {
- startLink:
- '<a href="https://console.aws.amazon.com/iam/home?#roles" target="_blank" rel="noopener noreferrer">',
- endLink: '</a>',
- },
- false,
- );
- },
- },
-};
-</script>
-<template>
- <div>
- <cluster-form-dropdown
- field-id="eks-role-name"
- field-name="eks-role-name"
- :items="roles"
- :loading="loading"
- :loading-text="s__('ClusterIntegration|Loading IAM Roles')"
- :placeholder="s__('ClusterIntergation|Select role name')"
- :search-field-placeholder="s__('ClusterIntegration|Search IAM Roles')"
- :empty-text="s__('ClusterIntegration|No IAM Roles found')"
- />
- <p class="form-text text-muted" v-html="helpText"></p>
- </div>
-</template>
diff --git a/app/assets/javascripts/gl_dropdown.js b/app/assets/javascripts/gl_dropdown.js
index f49246cf07b..515402fc506 100644
--- a/app/assets/javascripts/gl_dropdown.js
+++ b/app/assets/javascripts/gl_dropdown.js
@@ -1,4 +1,5 @@
-/* eslint-disable func-names, no-underscore-dangle, no-var, one-var, vars-on-top, no-shadow, no-cond-assign, prefer-arrow-callback, no-return-assign, no-else-return, camelcase, no-lonely-if, guard-for-in, no-restricted-syntax, consistent-return, prefer-template, no-param-reassign, no-loop-func */
+/* eslint-disable func-names, no-underscore-dangle, no-var, one-var, vars-on-top, no-unused-vars, no-shadow, no-cond-assign, prefer-arrow-callback, no-return-assign, no-else-return, camelcase, no-lonely-if, guard-for-in, no-restricted-syntax, consistent-return, prefer-template, no-param-reassign, no-loop-func */
+/* global fuzzaldrinPlus */
import $ from 'jquery';
import _ from 'underscore';
@@ -65,10 +66,12 @@ GitLabDropdownInput = (function() {
})();
GitLabDropdownFilter = (function() {
- var BLUR_KEYCODES, HAS_VALUE_CLASS;
+ var ARROW_KEY_CODES, BLUR_KEYCODES, HAS_VALUE_CLASS;
BLUR_KEYCODES = [27, 40];
+ ARROW_KEY_CODES = [38, 40];
+
HAS_VALUE_CLASS = 'has-value';
function GitLabDropdownFilter(input, options) {
@@ -874,8 +877,9 @@ GitLabDropdown = (function() {
};
GitLabDropdown.prototype.addArrowKeyEvent = function() {
- var ARROW_KEY_CODES, selector;
+ var $input, ARROW_KEY_CODES, selector;
ARROW_KEY_CODES = [38, 40];
+ $input = this.dropdown.find('.dropdown-input-field');
selector = SELECTABLE_CLASSES;
if (this.dropdown.find('.dropdown-toggle-page').length) {
selector = '.dropdown-page-one ' + selector;
diff --git a/app/assets/javascripts/issue.js b/app/assets/javascripts/issue.js
index a9e086fade8..db4607ca58d 100644
--- a/app/assets/javascripts/issue.js
+++ b/app/assets/javascripts/issue.js
@@ -1,9 +1,10 @@
-/* eslint-disable no-var, one-var, consistent-return */
+/* eslint-disable no-var, one-var, no-unused-vars, consistent-return */
import $ from 'jquery';
import axios from './lib/utils/axios_utils';
import { addDelimiter } from './lib/utils/text_utility';
import flash from './flash';
+import TaskList from './task_list';
import CreateMergeRequestDropdown from './create_merge_request_dropdown';
import IssuablesHelper from './helpers/issuables_helper';
import { __ } from './locale';
diff --git a/app/assets/javascripts/jobs/components/log/duration_badge.vue b/app/assets/javascripts/jobs/components/log/duration_badge.vue
deleted file mode 100644
index 83f62703d27..00000000000
--- a/app/assets/javascripts/jobs/components/log/duration_badge.vue
+++ /dev/null
@@ -1,13 +0,0 @@
-<script>
-export default {
- props: {
- duration: {
- type: String,
- required: true,
- },
- },
-};
-</script>
-<template>
- <div class="duration rounded align-self-start px-2 ml-2 flex-shrink-0">{{ duration }}</div>
-</template>
diff --git a/app/assets/javascripts/jobs/components/log/line.vue b/app/assets/javascripts/jobs/components/log/line.vue
index 336ae623f0f..86d0fcc3b74 100644
--- a/app/assets/javascripts/jobs/components/log/line.vue
+++ b/app/assets/javascripts/jobs/components/log/line.vue
@@ -21,7 +21,7 @@ export default {
<template>
<div class="line">
<line-number :line-number="line.lineNumber" :path="path" />
- <span v-for="(content, i) in line.content" :key="i" :class="content.style">{{
+ <span v-for="(content, i) in line.content" :key="i" class="line-text" :class="content.style">{{
content.text
}}</span>
</div>
diff --git a/app/assets/javascripts/jobs/components/log/line_header.vue b/app/assets/javascripts/jobs/components/log/line_header.vue
index af8de9ec0fa..4ec212d2333 100644
--- a/app/assets/javascripts/jobs/components/log/line_header.vue
+++ b/app/assets/javascripts/jobs/components/log/line_header.vue
@@ -1,13 +1,11 @@
<script>
import Icon from '~/vue_shared/components/icon.vue';
import LineNumber from './line_number.vue';
-import DurationBadge from './duration_badge.vue';
export default {
components: {
Icon,
LineNumber,
- DurationBadge,
},
props: {
line: {
@@ -22,11 +20,6 @@ export default {
type: String,
required: true,
},
- duration: {
- type: String,
- required: false,
- default: '',
- },
},
computed: {
iconName() {
@@ -42,16 +35,11 @@ export default {
</script>
<template>
- <div
- class="line collapsible-line d-flex justify-content-between"
- role="button"
- @click="handleOnClick"
- >
- <icon :name="iconName" class="arrow position-absolute" />
+ <div class="line collapsible-line" role="button" @click="handleOnClick">
+ <icon :name="iconName" class="arrow" />
<line-number :line-number="line.lineNumber" :path="path" />
<span v-for="(content, i) in line.content" :key="i" class="line-text" :class="content.style">{{
content.text
}}</span>
- <duration-badge v-if="duration" :duration="duration" />
</div>
</template>
diff --git a/app/assets/javascripts/jobs/components/log/line_number.vue b/app/assets/javascripts/jobs/components/log/line_number.vue
index 6c76bef13d3..e06836e2e97 100644
--- a/app/assets/javascripts/jobs/components/log/line_number.vue
+++ b/app/assets/javascripts/jobs/components/log/line_number.vue
@@ -46,10 +46,7 @@ export default {
};
</script>
<template>
- <gl-link
- :id="lineNumberId"
- class="d-inline-block text-right position-absolute line-number"
- :href="buildLineNumber"
- >{{ parsedLineNumber }}</gl-link
- >
+ <gl-link :id="lineNumberId" class="line-number" :href="buildLineNumber">{{
+ parsedLineNumber
+ }}</gl-link>
</template>
diff --git a/app/assets/javascripts/jobs/components/log/log.vue b/app/assets/javascripts/jobs/components/log/log.vue
index 429796aeb4e..5db866afe5a 100644
--- a/app/assets/javascripts/jobs/components/log/log.vue
+++ b/app/assets/javascripts/jobs/components/log/log.vue
@@ -9,7 +9,7 @@ export default {
LogLineHeader,
},
computed: {
- ...mapState(['traceEndpoint', 'trace', 'isTraceComplete']),
+ ...mapState(['traceEndpoint', 'trace']),
},
methods: {
...mapActions(['toggleCollapsibleLine']),
@@ -20,13 +20,12 @@ export default {
};
</script>
<template>
- <code class="job-log d-block">
+ <code class="job-log">
<template v-for="(section, index) in trace">
<template v-if="section.isHeader">
<log-line-header
:key="`collapsible-${index}`"
:line="section.line"
- :duration="section.section_duration"
:path="traceEndpoint"
:is-closed="section.isClosed"
@toggleLine="handleOnClickCollapsibleLine(section)"
@@ -42,11 +41,5 @@ export default {
</template>
<log-line v-else :key="section.offset" :line="section" :path="traceEndpoint" />
</template>
-
- <div v-if="!isTraceComplete" class="js-log-animation loader-animation pt-3 pl-3">
- <div class="dot"></div>
- <div class="dot"></div>
- <div class="dot"></div>
- </div>
</code>
</template>
diff --git a/app/assets/javascripts/jobs/store/utils.js b/app/assets/javascripts/jobs/store/utils.js
index 261ec90cd12..f6a87b9a212 100644
--- a/app/assets/javascripts/jobs/store/utils.js
+++ b/app/assets/javascripts/jobs/store/utils.js
@@ -1,21 +1,10 @@
/**
- * Adds the line number property
- * @param Object line
- * @param Number lineNumber
- */
-export const parseLine = (line = {}, lineNumber) => ({
- ...line,
- lineNumber,
-});
-
-/**
* Parses the job log content into a structure usable by the template
*
* For collaspible lines (section_header = true):
* - creates a new array to hold the lines that are collpasible,
* - adds a isClosed property to handle toggle
* - adds a isHeader property to handle template logic
- * - adds the section_duration
* For each line:
* - adds the index as lineNumber
*
@@ -25,21 +14,27 @@ export const parseLine = (line = {}, lineNumber) => ({
export const logLinesParser = (lines = [], lineNumberStart) =>
lines.reduce((acc, line, index) => {
const lineNumber = lineNumberStart ? lineNumberStart + index : index;
- const last = acc[acc.length - 1];
-
if (line.section_header) {
acc.push({
isClosed: true,
isHeader: true,
- line: parseLine(line, lineNumber),
+ line: {
+ ...line,
+ lineNumber,
+ },
+
lines: [],
});
- } else if (acc.length && last.isHeader && !line.section_duration && line.content.length) {
- last.lines.push(parseLine(line, lineNumber));
- } else if (acc.length && last.isHeader && line.section_duration) {
- last.section_duration = line.section_duration;
- } else if (line.content.length) {
- acc.push(parseLine(line, lineNumber));
+ } else if (acc.length && acc[acc.length - 1].isHeader) {
+ acc[acc.length - 1].lines.push({
+ ...line,
+ lineNumber,
+ });
+ } else {
+ acc.push({
+ ...line,
+ lineNumber,
+ });
}
return acc;
diff --git a/app/assets/javascripts/label_manager.js b/app/assets/javascripts/label_manager.js
index 5dcc719f7c3..7064731a5ea 100644
--- a/app/assets/javascripts/label_manager.js
+++ b/app/assets/javascripts/label_manager.js
@@ -1,4 +1,4 @@
-/* eslint-disable class-methods-use-this, no-underscore-dangle, no-param-reassign, func-names */
+/* eslint-disable class-methods-use-this, no-underscore-dangle, no-param-reassign, no-unused-vars, func-names */
import $ from 'jquery';
import Sortable from 'sortablejs';
@@ -50,7 +50,7 @@ export default class LabelManager {
$(e.currentTarget).tooltip('hide');
}
- toggleEmptyState() {
+ toggleEmptyState($label, $btn, action) {
this.emptyState.classList.toggle(
'hidden',
Boolean(this.prioritizedLabels[0].querySelector(':scope > li')),
@@ -61,6 +61,7 @@ export default class LabelManager {
if (persistState == null) {
persistState = true;
}
+ const _this = this;
const url = $label.find('.js-toggle-priority').data('url');
let $target = this.prioritizedLabels;
let $from = this.otherLabels;
diff --git a/app/assets/javascripts/labels_select.js b/app/assets/javascripts/labels_select.js
index 8cc3bc8373f..177aa02b8e0 100644
--- a/app/assets/javascripts/labels_select.js
+++ b/app/assets/javascripts/labels_select.js
@@ -1,4 +1,4 @@
-/* eslint-disable no-useless-return, func-names, no-var, no-underscore-dangle, prefer-arrow-callback, one-var, prefer-template, no-new, consistent-return, object-shorthand, no-shadow, no-param-reassign, vars-on-top, no-lonely-if, no-else-return, dot-notation, no-empty */
+/* eslint-disable no-useless-return, func-names, no-var, no-underscore-dangle, prefer-arrow-callback, one-var, no-unused-vars, prefer-template, no-new, consistent-return, object-shorthand, no-shadow, no-param-reassign, vars-on-top, no-lonely-if, no-else-return, dot-notation, no-empty */
/* global Issuable */
/* global ListLabel */
@@ -26,6 +26,7 @@ export default class LabelsSelect {
$els.each(function(i, dropdown) {
var $block,
+ $colorPreview,
$dropdown,
$form,
$loading,
@@ -34,6 +35,8 @@ export default class LabelsSelect {
$value,
abilityName,
defaultLabel,
+ enableLabelCreateButton,
+ issueURLSplit,
issueUpdateURL,
labelUrl,
namespacePath,
@@ -44,11 +47,16 @@ export default class LabelsSelect {
showNo,
$sidebarLabelTooltip,
initialSelected,
+ $toggleText,
fieldName,
+ useId,
+ propertyName,
showMenuAbove,
+ $container,
$dropdownContainer;
$dropdown = $(dropdown);
$dropdownContainer = $dropdown.closest('.labels-filter');
+ $toggleText = $dropdown.find('.dropdown-toggle-text');
namespacePath = $dropdown.data('namespacePath');
projectPath = $dropdown.data('projectPath');
issueUpdateURL = $dropdown.data('issueUpdate');
@@ -69,6 +77,10 @@ export default class LabelsSelect {
$value = $block.find('.value');
$loading = $block.find('.block-loading').fadeOut();
fieldName = $dropdown.data('fieldName');
+ useId = $dropdown.is(
+ '.js-issuable-form-dropdown, .js-filter-bulk-update, .js-label-sidebar-dropdown',
+ );
+ propertyName = useId ? 'id' : 'title';
initialSelected = $selectbox
.find('input[name="' + $dropdown.data('fieldName') + '"]')
.map(function() {
@@ -112,7 +124,7 @@ export default class LabelsSelect {
axios
.put(issueUpdateURL, data)
.then(({ data }) => {
- var labelCount, template, labelTooltipTitle, labelTitles;
+ var labelCount, template, labelTooltipTitle, labelTitles, formattedLabels;
$loading.fadeOut();
$dropdown.trigger('loaded.gl.dropdown');
$selectbox.hide();
@@ -234,10 +246,12 @@ export default class LabelsSelect {
renderRow: function(label) {
var linkEl,
listItemEl,
+ color,
colorEl,
indeterminate,
removesAll,
selectedClass,
+ spacing,
i,
marked,
dropdownValue;
@@ -364,7 +378,7 @@ export default class LabelsSelect {
}
},
hidden: function() {
- var isIssueIndex, isMRIndex, page;
+ var isIssueIndex, isMRIndex, page, selectedLabels;
page = $('body').attr('data-page');
isIssueIndex = page === 'projects:issues:index';
isMRIndex = page === 'projects:merge_requests:index';
@@ -381,6 +395,9 @@ export default class LabelsSelect {
}
if ($dropdown.hasClass('js-multiselect')) {
if ($dropdown.hasClass('js-filter-submit') && (isIssueIndex || isMRIndex)) {
+ selectedLabels = $dropdown
+ .closest('form')
+ .find("input:hidden[name='" + $dropdown.data('fieldName') + "']");
Issuable.filterResults($dropdown.closest('form'));
} else if ($dropdown.hasClass('js-filter-submit')) {
$dropdown.closest('form').submit();
@@ -478,7 +495,7 @@ export default class LabelsSelect {
}
}
},
- opened: function() {
+ opened: function(e) {
if ($dropdown.hasClass('js-issue-board-sidebar')) {
const previousSelection = $dropdown.attr('data-selected');
this.selected = previousSelection ? previousSelection.split(',') : [];
diff --git a/app/assets/javascripts/lib/utils/text_markdown.js b/app/assets/javascripts/lib/utils/text_markdown.js
index 7873eaf059f..b7922e29bb0 100644
--- a/app/assets/javascripts/lib/utils/text_markdown.js
+++ b/app/assets/javascripts/lib/utils/text_markdown.js
@@ -1,4 +1,4 @@
-/* eslint-disable func-names, no-var, no-param-reassign, one-var, operator-assignment, no-else-return, prefer-template, prefer-arrow-callback, consistent-return */
+/* eslint-disable func-names, no-var, no-param-reassign, one-var, operator-assignment, no-else-return, prefer-template, prefer-arrow-callback, consistent-return, no-unused-vars */
import $ from 'jquery';
import { insertText } from '~/lib/utils/common_utils';
@@ -157,7 +157,7 @@ export function insertMarkdownText({
if (tag === LINK_TAG_PATTERN) {
if (URL) {
try {
- new URL(selected); // eslint-disable-line no-new
+ const ignoredUrl = new URL(selected);
// valid url
tag = '[text]({text})';
select = 'text';
diff --git a/app/assets/javascripts/milestone_select.js b/app/assets/javascripts/milestone_select.js
index 9c0d55326ee..8f077685b07 100644
--- a/app/assets/javascripts/milestone_select.js
+++ b/app/assets/javascripts/milestone_select.js
@@ -1,4 +1,4 @@
-/* eslint-disable one-var, object-shorthand, no-else-return, no-self-compare, consistent-return, no-param-reassign, no-shadow */
+/* eslint-disable one-var, no-unused-vars, object-shorthand, no-else-return, no-self-compare, consistent-return, no-param-reassign, no-shadow */
/* global Issuable */
/* global ListMilestone */
@@ -37,6 +37,7 @@ export default class MilestoneSelect {
selectedMilestone,
selectedMilestoneDefault;
const $dropdown = $(dropdown);
+ const projectId = $dropdown.data('projectId');
const milestonesUrl = $dropdown.data('milestones');
const issueUpdateURL = $dropdown.data('issueUpdate');
const showNo = $dropdown.data('showNo');
@@ -47,6 +48,7 @@ export default class MilestoneSelect {
const useId = $dropdown.data('useId');
const defaultLabel = $dropdown.data('defaultLabel');
const defaultNo = $dropdown.data('defaultNo');
+ const issuableId = $dropdown.data('issuableId');
const abilityName = $dropdown.data('abilityName');
const $selectBox = $dropdown.closest('.selectbox');
const $block = $selectBox.closest('.block');
@@ -119,7 +121,7 @@ export default class MilestoneSelect {
fields: ['title'],
},
selectable: true,
- toggleLabel: (selected, el) => {
+ toggleLabel: (selected, el, e) => {
if (selected && 'id' in selected && $(el).hasClass('is-active')) {
return selected.title;
} else {
@@ -151,7 +153,7 @@ export default class MilestoneSelect {
},
vue: $dropdown.hasClass('js-issue-board-sidebar'),
clicked: clickEvent => {
- const { e } = clickEvent;
+ const { $el, e } = clickEvent;
let selected = clickEvent.selectedObj;
let data, modalStoreFilter;
diff --git a/app/assets/javascripts/monitoring/components/charts/column.vue b/app/assets/javascripts/monitoring/components/charts/column.vue
index ee6aaeb7dde..83136d43479 100644
--- a/app/assets/javascripts/monitoring/components/charts/column.vue
+++ b/app/assets/javascripts/monitoring/components/charts/column.vue
@@ -100,7 +100,7 @@ export default {
};
</script>
<template>
- <div class="prometheus-graph">
+ <div class="prometheus-graph col-12 col-lg-6">
<div class="prometheus-graph-header">
<h5 ref="graphTitle" class="prometheus-graph-title">{{ graphData.title }}</h5>
<div ref="graphWidgets" class="prometheus-graph-widgets"><slot></slot></div>
diff --git a/app/assets/javascripts/monitoring/components/charts/empty_chart.vue b/app/assets/javascripts/monitoring/components/charts/empty_chart.vue
index eedc5162e0c..73682adc4ee 100644
--- a/app/assets/javascripts/monitoring/components/charts/empty_chart.vue
+++ b/app/assets/javascripts/monitoring/components/charts/empty_chart.vue
@@ -27,7 +27,7 @@ export default {
};
</script>
<template>
- <div class="prometheus-graph d-flex flex-column justify-content-center">
+ <div class="prometheus-graph col-12 col-lg-6 d-flex flex-column justify-content-center">
<div class="prometheus-graph-header">
<h5 ref="graphTitle" class="prometheus-graph-title">{{ graphTitle }}</h5>
</div>
diff --git a/app/assets/javascripts/monitoring/components/charts/single_stat.vue b/app/assets/javascripts/monitoring/components/charts/single_stat.vue
index 076682820e6..7428b27a9c3 100644
--- a/app/assets/javascripts/monitoring/components/charts/single_stat.vue
+++ b/app/assets/javascripts/monitoring/components/charts/single_stat.vue
@@ -29,7 +29,7 @@ export default {
};
</script>
<template>
- <div class="prometheus-graph">
+ <div class="prometheus-graph col-12 col-lg-6">
<div class="prometheus-graph-header">
<h5 ref="graphTitle" class="prometheus-graph-title">{{ graphTitle }}</h5>
</div>
diff --git a/app/assets/javascripts/monitoring/components/charts/time_series.vue b/app/assets/javascripts/monitoring/components/charts/time_series.vue
index 5f1d742d952..02e7a7ba0a6 100644
--- a/app/assets/javascripts/monitoring/components/charts/time_series.vue
+++ b/app/assets/javascripts/monitoring/components/charts/time_series.vue
@@ -43,6 +43,11 @@ export default {
required: false,
default: '',
},
+ showBorder: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
singleEmbed: {
type: Boolean,
required: false,
@@ -267,66 +272,71 @@ export default {
</script>
<template>
- <div class="prometheus-graph">
- <div class="prometheus-graph-header">
- <h5 class="prometheus-graph-title js-graph-title">{{ graphData.title }}</h5>
- <gl-button
- v-if="exportMetricsToCsvEnabled"
- :href="downloadLink"
- :title="__('Download CSV')"
- :aria-label="__('Download CSV')"
- style="margin-left: 200px;"
- download="chart_metrics.csv"
- >
- {{ __('Download CSV') }}
- </gl-button>
- <div class="prometheus-graph-widgets js-graph-widgets">
- <slot></slot>
+ <div
+ class="prometheus-graph col-12"
+ :class="[showBorder ? 'p-2' : 'p-0', { 'col-lg-6': !singleEmbed }]"
+ >
+ <div :class="{ 'prometheus-graph-embed w-100 p-3': showBorder }">
+ <div class="prometheus-graph-header">
+ <h5 class="prometheus-graph-title js-graph-title">{{ graphData.title }}</h5>
+ <gl-button
+ v-if="exportMetricsToCsvEnabled"
+ :href="downloadLink"
+ :title="__('Download CSV')"
+ :aria-label="__('Download CSV')"
+ style="margin-left: 200px;"
+ download="chart_metrics.csv"
+ >
+ {{ __('Download CSV') }}
+ </gl-button>
+ <div class="prometheus-graph-widgets js-graph-widgets">
+ <slot></slot>
+ </div>
</div>
- </div>
- <component
- :is="glChartComponent"
- ref="chart"
- v-bind="$attrs"
- :data="chartData"
- :option="chartOptions"
- :format-tooltip-text="formatTooltipText"
- :thresholds="thresholds"
- :width="width"
- :height="height"
- @updated="onChartUpdated"
- >
- <template v-if="tooltip.isDeployment">
- <template slot="tooltipTitle">
- {{ __('Deployed') }}
- </template>
- <div slot="tooltipContent" class="d-flex align-items-center">
- <icon name="commit" class="mr-2" />
- <gl-link :href="tooltip.commitUrl">{{ tooltip.sha }}</gl-link>
- </div>
- </template>
- <template v-else>
- <template slot="tooltipTitle">
- <div class="text-nowrap">
- {{ tooltip.title }}
+ <component
+ :is="glChartComponent"
+ ref="chart"
+ v-bind="$attrs"
+ :data="chartData"
+ :option="chartOptions"
+ :format-tooltip-text="formatTooltipText"
+ :thresholds="thresholds"
+ :width="width"
+ :height="height"
+ @updated="onChartUpdated"
+ >
+ <template v-if="tooltip.isDeployment">
+ <template slot="tooltipTitle">
+ {{ __('Deployed') }}
+ </template>
+ <div slot="tooltipContent" class="d-flex align-items-center">
+ <icon name="commit" class="mr-2" />
+ <gl-link :href="tooltip.commitUrl">{{ tooltip.sha }}</gl-link>
</div>
</template>
- <template slot="tooltipContent">
- <div
- v-for="(content, key) in tooltip.content"
- :key="key"
- class="d-flex justify-content-between"
- >
- <gl-chart-series-label :color="isMultiSeries ? content.color : ''">
- {{ content.name }}
- </gl-chart-series-label>
- <div class="prepend-left-32">
- {{ content.value }}
+ <template v-else>
+ <template slot="tooltipTitle">
+ <div class="text-nowrap">
+ {{ tooltip.title }}
</div>
- </div>
+ </template>
+ <template slot="tooltipContent">
+ <div
+ v-for="(content, key) in tooltip.content"
+ :key="key"
+ class="d-flex justify-content-between"
+ >
+ <gl-chart-series-label :color="isMultiSeries ? content.color : ''">
+ {{ content.name }}
+ </gl-chart-series-label>
+ <div class="prepend-left-32">
+ {{ content.value }}
+ </div>
+ </div>
+ </template>
</template>
- </template>
- </component>
+ </component>
+ </div>
</div>
</template>
diff --git a/app/assets/javascripts/monitoring/components/dashboard.vue b/app/assets/javascripts/monitoring/components/dashboard.vue
index 7a5a3789bd6..d330ceb836c 100644
--- a/app/assets/javascripts/monitoring/components/dashboard.vue
+++ b/app/assets/javascripts/monitoring/components/dashboard.vue
@@ -456,7 +456,6 @@ export default {
<panel-type
v-for="(graphData, graphIndex) in groupData.metrics"
:key="`panel-type-${graphIndex}`"
- class="col-12 col-lg-6 pb-3"
:clipboard-text="generateLink(groupData.group, graphData.title, graphData.y_label)"
:graph-data="graphData"
:dashboard-width="elWidth"
@@ -469,7 +468,6 @@ export default {
<monitor-time-series-chart
v-for="(graphData, graphIndex) in chartsWithData(groupData.metrics)"
:key="graphIndex"
- class="col-12 col-lg-6 pb-3"
:graph-data="graphData"
:deployment-data="deploymentData"
:thresholds="getGraphAlertValues(graphData.queries)"
diff --git a/app/assets/javascripts/monitoring/components/embed.vue b/app/assets/javascripts/monitoring/components/embed.vue
index da1e88071ab..b516a82c170 100644
--- a/app/assets/javascripts/monitoring/components/embed.vue
+++ b/app/assets/javascripts/monitoring/components/embed.vue
@@ -95,7 +95,6 @@ export default {
<monitor-time-series-chart
v-for="graphData in charts"
:key="graphData.title"
- class="w-100"
:graph-data="graphData"
:container-width="elWidth"
group-id="monitor-area-chart"
diff --git a/app/assets/javascripts/network/branch_graph.js b/app/assets/javascripts/network/branch_graph.js
index fcfc2570b3d..d1fa9f5e2a2 100644
--- a/app/assets/javascripts/network/branch_graph.js
+++ b/app/assets/javascripts/network/branch_graph.js
@@ -1,8 +1,9 @@
-/* eslint-disable func-names, no-var, one-var, no-loop-func, consistent-return, prefer-template, prefer-arrow-callback, camelcase */
+/* eslint-disable func-names, no-var, one-var, no-loop-func, consistent-return, no-unused-vars, prefer-template, prefer-arrow-callback, camelcase */
import $ from 'jquery';
import { __ } from '../locale';
import axios from '../lib/utils/axios_utils';
+import flash from '../flash';
import Raphael from './raphael';
export default (function() {
@@ -103,7 +104,7 @@ export default (function() {
};
BranchGraph.prototype.buildGraph = function() {
- var cuday, cumonth, day, len, mm, ref;
+ var cuday, cumonth, day, j, len, mm, ref;
const { r } = this;
cuday = 0;
cumonth = '';
@@ -177,7 +178,7 @@ export default (function() {
return $(element).scroll(
(function(_this) {
- return function() {
+ return function(event) {
return _this.renderPartialGraph();
};
})(this),
@@ -213,7 +214,7 @@ export default (function() {
};
BranchGraph.prototype.appendLabel = function(x, y, commit) {
- var label, rect, shortrefs, text, textbox;
+ var label, rect, shortrefs, text, textbox, triangle;
if (!commit.refs) {
return;
@@ -238,8 +239,7 @@ export default (function() {
'fill-opacity': 0.5,
stroke: 'none',
});
- // Generate the triangle right of the tag box
- r.path(['M', x - 5, y, 'L', x - 15, y - 4, 'L', x - 15, y + 4, 'Z']).attr({
+ triangle = r.path(['M', x - 5, y, 'L', x - 15, y - 4, 'L', x - 15, y + 4, 'Z']).attr({
fill: '#000',
'fill-opacity': 0.5,
stroke: 'none',
diff --git a/app/assets/javascripts/notes.js b/app/assets/javascripts/notes.js
index 9cc56b34c75..9cc31e26648 100644
--- a/app/assets/javascripts/notes.js
+++ b/app/assets/javascripts/notes.js
@@ -2,9 +2,10 @@
no-unused-expressions, one-var, default-case,
prefer-template, consistent-return, no-alert, no-return-assign,
no-param-reassign, prefer-arrow-callback, no-else-return, vars-on-top,
-no-shadow, no-useless-escape, class-methods-use-this */
+no-unused-vars, no-shadow, no-useless-escape, class-methods-use-this */
/* global ResolveService */
+/* global mrRefreshWidgetUrl */
/*
old_notes_spec.js is the spec for the legacy, jQuery notes application. It has nothing to do with the new, fancy Vue notes app.
@@ -36,6 +37,7 @@ import {
isMetaKey,
isInMRPage,
} from './lib/utils/common_utils';
+import imageDiffHelper from './image_diff/helpers/index';
import { localTimeAgo } from './lib/utils/datetime_utility';
import { sprintf, s__, __ } from './locale';
@@ -681,7 +683,7 @@ export default class Notes {
);
}
- updateNoteError() {
+ updateNoteError($parentTimeline) {
// eslint-disable-next-line no-new
new Flash(
__('Your comment could not be updated! Please check your network connection and try again.'),
@@ -695,6 +697,7 @@ export default class Notes {
*/
addDiscussionNote($form, note, isNewDiffComment) {
if ($form.attr('data-resolve-all') != null) {
+ var projectPath = $form.data('projectPath');
var discussionId = $form.data('discussionId');
var mergeRequestId = $form.data('noteableIid');
@@ -743,6 +746,7 @@ export default class Notes {
if (currentContent === initialContent) {
this.removeNoteEditForm($el);
} else {
+ var $buttons = $el.find('.note-form-actions');
var isWidgetVisible = isInViewport($el.get(0));
if (!isWidgetVisible) {
@@ -762,7 +766,7 @@ export default class Notes {
* Replaces the note text with the note edit form
* Adds a data attribute to the form with the original content of the note for cancellations
*/
- showEditForm(e) {
+ showEditForm(e, scrollTo, myLastNote) {
e.preventDefault();
var $target = $(e.target);
@@ -846,11 +850,16 @@ export default class Notes {
* Removes the whole discussion if the last note is being removed.
*/
removeNote(e) {
- var noteElId, $note;
+ var noteElId, noteId, dataNoteId, $note, lineHolder;
$note = $(e.currentTarget).closest('.note');
noteElId = $note.attr('id');
+ noteId = $note.attr('data-note-id');
+ lineHolder = $(e.currentTarget)
+ .closest('.notes[data-discussion-id]')
+ .closest('.notes_holder')
+ .prev('.line_holder');
$(`.note[id="${noteElId}"]`).each(
- (function() {
+ (function(_this) {
// A same note appears in the "Discussion" and in the "Changes" tab, we have
// to remove all. Using $('.note[id='noteId']') ensure we get all the notes,
// where $('#noteId') would return only one.
@@ -1055,8 +1064,25 @@ export default class Notes {
this.setupDiscussionNoteForm($link, newForm);
}
- toggleDiffNote({ target, lineType, forceShow, showReplyInput = false }) {
- var $link, addForm, hasNotes, newForm, noteForm, replyButton, row, rowCssToAdd;
+ toggleDiffNote({
+ target,
+ lineType,
+ forceShow,
+ showReplyInput = false,
+ currentUsername,
+ currentUserAvatar,
+ currentUserFullname,
+ }) {
+ var $link,
+ addForm,
+ hasNotes,
+ newForm,
+ noteForm,
+ replyButton,
+ row,
+ rowCssToAdd,
+ targetContent,
+ isDiffCommentAvatar;
$link = $(target);
row = $link.closest('tr');
const nextRow = row.next();
@@ -1489,7 +1515,7 @@ export default class Notes {
let tempFormContent;
// Identify executed quick actions from `formContent`
- const executedCommands = availableQuickActions.filter(command => {
+ const executedCommands = availableQuickActions.filter((command, index) => {
const commandRegex = new RegExp(`/${command.name}`);
return commandRegex.test(formContent);
});
@@ -1814,6 +1840,8 @@ export default class Notes {
const $noteBody = $editingNote.find('.js-task-list-container');
const $noteBodyText = $noteBody.find('.note-text');
const { formData, formContent, formAction } = this.getFormData($form);
+ const $diffFile = $form.closest('.diff-file');
+ const $notesContainer = $form.closest('.notes');
// Cache original comment content
const cachedNoteBodyText = $noteBodyText.html();
diff --git a/app/assets/javascripts/notes/components/discussion_actions.vue b/app/assets/javascripts/notes/components/discussion_actions.vue
index e3be91a4966..6bbf2fa6ee4 100644
--- a/app/assets/javascripts/notes/components/discussion_actions.vue
+++ b/app/assets/javascripts/notes/components/discussion_actions.vue
@@ -36,10 +36,11 @@ export default {
},
},
computed: {
+ resolvableNotes() {
+ return this.discussion.notes.filter(x => x.resolvable);
+ },
userCanResolveDiscussion() {
- return this.discussion.notes.every(
- note => note.current_user && note.current_user.can_resolve,
- );
+ return this.resolvableNotes.every(note => note.current_user && note.current_user.can_resolve);
},
},
};
diff --git a/app/assets/javascripts/pages/admin/application_settings/general/index.js b/app/assets/javascripts/pages/admin/application_settings/show/index.js
index 5ec9688a6e4..5ec9688a6e4 100644
--- a/app/assets/javascripts/pages/admin/application_settings/general/index.js
+++ b/app/assets/javascripts/pages/admin/application_settings/show/index.js
diff --git a/app/assets/javascripts/pages/projects/graphs/show/stat_graph_contributors_util.js b/app/assets/javascripts/pages/projects/graphs/show/stat_graph_contributors_util.js
index ec3919dd073..988ae164955 100644
--- a/app/assets/javascripts/pages/projects/graphs/show/stat_graph_contributors_util.js
+++ b/app/assets/javascripts/pages/projects/graphs/show/stat_graph_contributors_util.js
@@ -1,4 +1,4 @@
-/* eslint-disable func-names, object-shorthand, no-var, one-var, camelcase, no-param-reassign, no-return-assign, prefer-arrow-callback, consistent-return, no-cond-assign, no-else-return */
+/* eslint-disable func-names, object-shorthand, no-var, one-var, camelcase, no-param-reassign, no-return-assign, prefer-arrow-callback, consistent-return, no-unused-vars, no-cond-assign, no-else-return */
import _ from 'underscore';
export default {
@@ -126,7 +126,7 @@ export default {
_.each(
_.omit(log_entry, 'author_name', 'author_email'),
(function(_this) {
- return function(value) {
+ return function(value, key) {
if (_this.in_range(value.date, date_range)) {
parsed_entry.dates[value.date] = value[field];
parsed_entry.commits += value.commits;
diff --git a/app/assets/javascripts/performance_bar/services/performance_bar_service.js b/app/assets/javascripts/performance_bar/services/performance_bar_service.js
index 61b35b4b8f5..d8c23c82f7f 100644
--- a/app/assets/javascripts/performance_bar/services/performance_bar_service.js
+++ b/app/assets/javascripts/performance_bar/services/performance_bar_service.js
@@ -1,6 +1,10 @@
+import Vue from 'vue';
+import _ from 'underscore';
import axios from '../../lib/utils/axios_utils';
import { parseBoolean } from '~/lib/utils/common_utils';
+let vueResourceInterceptor;
+
export default class PerformanceBarService {
static fetchRequestDetails(peekUrl, requestId) {
return axios.get(peekUrl, { params: { request_id: requestId } });
@@ -20,11 +24,16 @@ export default class PerformanceBarService {
return response;
};
+ vueResourceInterceptor = (request, next) => next(interceptor);
+
+ Vue.http.interceptors.push(vueResourceInterceptor);
+
return axios.interceptors.response.use(interceptor);
}
static removeInterceptor(interceptor) {
axios.interceptors.response.eject(interceptor);
+ Vue.http.interceptors = _.without(Vue.http.interceptors, vueResourceInterceptor);
}
static callbackParams(response, peekUrl) {
diff --git a/app/assets/javascripts/profile/gl_crop.js b/app/assets/javascripts/profile/gl_crop.js
index 6a07ccc7586..befe91c332f 100644
--- a/app/assets/javascripts/profile/gl_crop.js
+++ b/app/assets/javascripts/profile/gl_crop.js
@@ -1,10 +1,10 @@
-/* eslint-disable no-useless-escape, no-var, no-underscore-dangle, func-names, no-return-assign, object-shorthand, one-var, consistent-return, class-methods-use-this */
+/* eslint-disable no-useless-escape, no-var, no-underscore-dangle, func-names, no-unused-vars, no-return-assign, object-shorthand, one-var, consistent-return, class-methods-use-this */
import $ from 'jquery';
import 'cropper';
import _ from 'underscore';
-(() => {
+(global => {
// Matches everything but the file name
const FILENAMEREGEX = /^.*[\\\/]/;
@@ -69,7 +69,7 @@ import _ from 'underscore';
this.modalCrop.on('shown.bs.modal', this.onModalShow);
this.modalCrop.on('hidden.bs.modal', this.onModalHide);
this.uploadImageBtn.on('click', this.onUploadImageBtnClick);
- this.cropActionsBtn.on('click', function() {
+ this.cropActionsBtn.on('click', function(e) {
var btn;
btn = this;
return _this.onActionBtnClick(btn);
@@ -128,10 +128,10 @@ import _ from 'underscore';
}
onActionBtnClick(btn) {
- var data;
+ var data, result;
data = $(btn).data();
if (this.modalCropImg.data('cropper') && data.method) {
- return this.modalCropImg.cropper(data.method, data.option);
+ return (result = this.modalCropImg.cropper(data.method, data.option));
}
}
@@ -151,11 +151,12 @@ import _ from 'underscore';
}
dataURLtoBlob(dataURL) {
- var array, binary, i, len;
+ var array, binary, i, len, v;
binary = atob(dataURL.split(',')[1]);
array = [];
for (i = 0, len = binary.length; i < len; i += 1) {
+ v = binary[i];
array.push(binary.charCodeAt(i));
}
return new Blob([new Uint8Array(array)], {
diff --git a/app/assets/javascripts/project_find_file.js b/app/assets/javascripts/project_find_file.js
index e73a828c0ae..765cb868f80 100644
--- a/app/assets/javascripts/project_find_file.js
+++ b/app/assets/javascripts/project_find_file.js
@@ -1,4 +1,4 @@
-/* eslint-disable func-names, no-var, consistent-return, one-var, no-cond-assign, prefer-template, no-return-assign */
+/* eslint-disable func-names, no-var, consistent-return, one-var, no-cond-assign, prefer-template, no-unused-vars, no-return-assign */
import $ from 'jquery';
import fuzzaldrinPlus from 'fuzzaldrin-plus';
@@ -8,8 +8,9 @@ import { __ } from '~/locale';
// highlight text(awefwbwgtc -> <b>a</b>wefw<b>b</b>wgt<b>c</b> )
const highlighter = function(element, text, matches) {
- var j, lastIndex, len, matchIndex, matchedChars, unmatched;
+ var highlightText, j, lastIndex, len, matchIndex, matchedChars, unmatched;
lastIndex = 0;
+ highlightText = '';
matchedChars = [];
for (j = 0, len = matches.length; j < len; j += 1) {
matchIndex = matches[j];
diff --git a/app/assets/javascripts/right_sidebar.js b/app/assets/javascripts/right_sidebar.js
index 0cc7a22325b..40a2158de78 100644
--- a/app/assets/javascripts/right_sidebar.js
+++ b/app/assets/javascripts/right_sidebar.js
@@ -1,4 +1,4 @@
-/* eslint-disable func-names, no-var, consistent-return, one-var, prefer-template, no-else-return, no-param-reassign */
+/* eslint-disable func-names, no-var, no-unused-vars, consistent-return, one-var, prefer-template, no-else-return, no-param-reassign */
import $ from 'jquery';
import _ from 'underscore';
@@ -7,7 +7,7 @@ import flash from './flash';
import axios from './lib/utils/axios_utils';
import { sprintf, s__, __ } from './locale';
-function Sidebar() {
+function Sidebar(currentUser) {
this.toggleTodo = this.toggleTodo.bind(this);
this.sidebar = $('aside');
@@ -15,9 +15,9 @@ function Sidebar() {
this.addEventListeners();
}
-Sidebar.initialize = function() {
+Sidebar.initialize = function(currentUser) {
if (!this.instance) {
- this.instance = new Sidebar();
+ this.instance = new Sidebar(currentUser);
}
};
@@ -77,7 +77,7 @@ Sidebar.prototype.sidebarToggleClicked = function(e, triggered) {
};
Sidebar.prototype.toggleTodo = function(e) {
- var $this, ajaxType, url;
+ var $btnText, $this, $todoLoading, ajaxType, url;
$this = $(e.currentTarget);
ajaxType = $this.data('deletePath') ? 'delete' : 'post';
@@ -140,7 +140,7 @@ Sidebar.prototype.todoUpdateDone = function(data) {
});
};
-Sidebar.prototype.sidebarDropdownLoading = function() {
+Sidebar.prototype.sidebarDropdownLoading = function(e) {
var $loading, $sidebarCollapsedIcon, i, img;
$sidebarCollapsedIcon = $(this)
.closest('.block')
@@ -157,7 +157,7 @@ Sidebar.prototype.sidebarDropdownLoading = function() {
}
};
-Sidebar.prototype.sidebarDropdownLoaded = function() {
+Sidebar.prototype.sidebarDropdownLoaded = function(e) {
var $sidebarCollapsedIcon, i, img;
$sidebarCollapsedIcon = $(this)
.closest('.block')
diff --git a/app/assets/javascripts/search_autocomplete.js b/app/assets/javascripts/search_autocomplete.js
index f02c55c3d5b..510a2441924 100644
--- a/app/assets/javascripts/search_autocomplete.js
+++ b/app/assets/javascripts/search_autocomplete.js
@@ -1,10 +1,11 @@
-/* eslint-disable no-return-assign, one-var, no-var, consistent-return, object-shorthand, prefer-template, class-methods-use-this, no-lonely-if, vars-on-top */
+/* eslint-disable no-return-assign, one-var, no-var, no-unused-vars, consistent-return, object-shorthand, prefer-template, class-methods-use-this, no-lonely-if, vars-on-top */
import $ from 'jquery';
import { escape, throttle } from 'underscore';
-import { s__, __ } from '~/locale';
+import { s__, __, sprintf } from '~/locale';
import { getIdenticonBackgroundClass, getIdenticonTitle } from '~/helpers/avatar_helper';
import axios from './lib/utils/axios_utils';
+import DropdownUtils from './filtered_search/dropdown_utils';
import {
isInGroupsPage,
isInProjectPage,
@@ -141,7 +142,7 @@ export class SearchAutocomplete {
});
}
- getSearchText(selectedObject) {
+ getSearchText(selectedObject, el) {
return selectedObject.id ? selectedObject.text : '';
}
@@ -401,7 +402,7 @@ export class SearchAutocomplete {
return this.searchInput.val('').focus();
}
- onSearchInputBlur() {
+ onSearchInputBlur(e) {
this.isFocused = false;
this.wrap.removeClass('search-active');
// If input is blank then restore state
diff --git a/app/assets/javascripts/test_utils/simulate_drag.js b/app/assets/javascripts/test_utils/simulate_drag.js
index f4090de3f1e..c9bf234fcce 100644
--- a/app/assets/javascripts/test_utils/simulate_drag.js
+++ b/app/assets/javascripts/test_utils/simulate_drag.js
@@ -2,8 +2,8 @@ function simulateEvent(el, type, options = {}) {
let event;
if (!el) return null;
- if (/^(pointer|mouse)/.test(type)) {
- event = el.ownerDocument.createEvent('MouseEvent');
+ if (/^mouse/.test(type)) {
+ event = el.ownerDocument.createEvent('MouseEvents');
event.initMouseEvent(
type,
true,
@@ -125,7 +125,7 @@ export default function simulateDrag(options) {
const startTime = new Date().getTime();
const duration = options.duration || 1000;
- simulateEvent(fromEl, 'pointerdown', {
+ simulateEvent(fromEl, 'mousedown', {
button: 0,
clientX: fromRect.cx,
clientY: fromRect.cy,
@@ -146,7 +146,7 @@ export default function simulateDrag(options) {
const y = fromRect.cy + (toRect.cy - fromRect.cy) * progress;
const overEl = fromEl.ownerDocument.elementFromPoint(x, y);
- simulateEvent(overEl, 'pointermove', {
+ simulateEvent(overEl, 'mousemove', {
clientX: x,
clientY: y,
});
diff --git a/app/assets/javascripts/users_select.js b/app/assets/javascripts/users_select.js
index 4b3c42ae848..57efde7f027 100644
--- a/app/assets/javascripts/users_select.js
+++ b/app/assets/javascripts/users_select.js
@@ -1,4 +1,4 @@
-/* eslint-disable func-names, one-var, no-var, prefer-rest-params, vars-on-top, prefer-arrow-callback, consistent-return, object-shorthand, no-shadow, no-else-return, no-self-compare, prefer-template, no-unused-expressions, yoda, prefer-spread, camelcase, no-param-reassign */
+/* eslint-disable func-names, one-var, no-var, prefer-rest-params, vars-on-top, prefer-arrow-callback, consistent-return, object-shorthand, no-shadow, no-unused-vars, no-else-return, no-self-compare, prefer-template, no-unused-expressions, yoda, prefer-spread, camelcase, no-param-reassign */
/* global Issuable */
/* global emitSidebarEvent */
@@ -405,7 +405,7 @@ function UsersSelect(currentUser, els, options = {}) {
}
},
defaultLabel: defaultLabel,
- hidden: function() {
+ hidden: function(e) {
if ($dropdown.hasClass('js-multiselect')) {
emitSidebarEvent('sidebar.saveAssignees');
}
@@ -442,6 +442,7 @@ function UsersSelect(currentUser, els, options = {}) {
if (user.beforeDivider && user.name.toLowerCase() === 'unassigned') {
// Unassigned selected
previouslySelected.each((index, element) => {
+ const id = parseInt(element.value, 10);
element.remove();
});
emitSidebarEvent('sidebar.removeAllAssignees');
@@ -547,7 +548,7 @@ function UsersSelect(currentUser, els, options = {}) {
},
updateLabel: $dropdown.data('dropdownTitle'),
renderRow: function(user) {
- var avatar, img, username;
+ var avatar, img, listClosingTags, listWithName, listWithUserName, username;
username = user.username ? '@' + user.username : '';
avatar = user.avatar_url ? user.avatar_url : gon.default_avatar_url;
diff --git a/app/assets/javascripts/zen_mode.js b/app/assets/javascripts/zen_mode.js
index 5438572eadf..e98c4d7bf7a 100644
--- a/app/assets/javascripts/zen_mode.js
+++ b/app/assets/javascripts/zen_mode.js
@@ -1,4 +1,4 @@
-/* eslint-disable func-names, prefer-arrow-callback, consistent-return, camelcase, class-methods-use-this */
+/* eslint-disable func-names, prefer-arrow-callback, no-unused-vars, consistent-return, camelcase, class-methods-use-this */
// Zen Mode (full screen) textarea
//
@@ -62,7 +62,7 @@ export default class ZenMode {
$(document).on(
'zen_mode:leave',
(function(_this) {
- return function() {
+ return function(e) {
return _this.exit();
};
})(this),
diff --git a/app/assets/stylesheets/framework/flash.scss b/app/assets/stylesheets/framework/flash.scss
index af05d069f97..7e7b08797b2 100644
--- a/app/assets/stylesheets/framework/flash.scss
+++ b/app/assets/stylesheets/framework/flash.scss
@@ -131,16 +131,16 @@ $notification-box-shadow-color: rgba(0, 0, 0, 0.25);
}
}
-.with-system-header .flash-container {
+.with-system-header .flash-container.sticky {
top: $flash-container-top + $system-header-height;
}
.with-performance-bar {
- .flash-container {
+ .flash-container.sticky {
top: $flash-container-top + $performance-bar-height;
}
- &.with-system-header .flash-container {
+ &.with-system-header .flash-container.sticky {
top: $flash-container-top + $performance-bar-height + $system-header-height;
}
}
diff --git a/app/assets/stylesheets/framework/job_log.scss b/app/assets/stylesheets/framework/job_log.scss
deleted file mode 100644
index 5c2491c8233..00000000000
--- a/app/assets/stylesheets/framework/job_log.scss
+++ /dev/null
@@ -1,49 +0,0 @@
-.job-log {
- font-family: $monospace-font;
- padding: $gl-padding-8 $input-horizontal-padding;
- margin: 0 0 $gl-padding-8;
- font-size: 13px;
- word-break: break-all;
- word-wrap: break-word;
- color: $gl-text-color-inverted;
- border-radius: $border-radius-small;
- min-height: 42px;
- background-color: $builds-trace-bg;
-}
-
-.line {
- padding: 1px $gl-padding 1px $job-log-line-padding;
-}
-
-.line-number {
- color: $gl-text-color-inverted;
- padding: 0 $gl-padding-8;
- min-width: $job-line-number-width;
- margin-left: -$job-line-number-width;
- padding-right: 1em;
-
- &:hover,
- &:active,
- &:visited {
- text-decoration: underline;
- color: $gl-text-color-inverted;
- }
-}
-
-.collapsible-line {
- &:hover {
- background-color: rgba($white-light, 0.2);
- }
-
- .arrow {
- margin-left: -$job-arrow-margin;
- }
-}
-
-.duration {
- background: $gl-gray-400;
-}
-
-.loader-animation {
- @include build-loader-animation;
-}
diff --git a/app/assets/stylesheets/framework/snippets.scss b/app/assets/stylesheets/framework/snippets.scss
index f57b1d9f351..3ab83f4c8e6 100644
--- a/app/assets/stylesheets/framework/snippets.scss
+++ b/app/assets/stylesheets/framework/snippets.scss
@@ -39,6 +39,10 @@
min-height: $header-height;
}
+.snippet-edited-ago {
+ color: $gray-darkest;
+}
+
.snippet-actions {
@include media-breakpoint-up(sm) {
float: right;
diff --git a/app/assets/stylesheets/framework/sortable.scss b/app/assets/stylesheets/framework/sortable.scss
index 25868061d04..8c070200135 100644
--- a/app/assets/stylesheets/framework/sortable.scss
+++ b/app/assets/stylesheets/framework/sortable.scss
@@ -90,21 +90,3 @@
padding: 0;
}
}
-
-.is-dragging {
- // Important because plugin sets inline CSS
- opacity: 1 !important;
-
- * {
- -webkit-user-select: none;
- -moz-user-select: none;
- -ms-user-select: none;
- user-select: none;
- // !important to make sure no style can override this when dragging
- cursor: grabbing !important;
- }
-
- &.no-drop * {
- cursor: no-drop !important;
- }
-}
diff --git a/app/assets/stylesheets/framework/variables.scss b/app/assets/stylesheets/framework/variables.scss
index e77527ac130..faa0a9909d5 100644
--- a/app/assets/stylesheets/framework/variables.scss
+++ b/app/assets/stylesheets/framework/variables.scss
@@ -606,9 +606,6 @@ $blame-blue: #254e77;
*/
$builds-trace-bg: #111;
$job-log-highlight-height: 18px;
-$job-log-line-padding: 62px;
-$job-line-number-width: 40px;
-$job-arrow-margin: 50px;
/*
* Commit Page
diff --git a/app/assets/stylesheets/pages/boards.scss b/app/assets/stylesheets/pages/boards.scss
index 4bf0abccd00..e77a2d1e333 100644
--- a/app/assets/stylesheets/pages/boards.scss
+++ b/app/assets/stylesheets/pages/boards.scss
@@ -2,6 +2,20 @@
cursor: grab;
}
+.is-dragging {
+ // Important because plugin sets inline CSS
+ opacity: 1 !important;
+
+ * {
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+ // !important to make sure no style can override this when dragging
+ cursor: grabbing !important;
+ }
+}
+
.is-ghost {
opacity: 0.3;
pointer-events: none;
diff --git a/app/assets/stylesheets/pages/issues.scss b/app/assets/stylesheets/pages/issues.scss
index a37cbda8558..8359a60ec9f 100644
--- a/app/assets/stylesheets/pages/issues.scss
+++ b/app/assets/stylesheets/pages/issues.scss
@@ -29,6 +29,10 @@
.author-link {
display: inline-block;
}
+
+ .issuable-comments {
+ height: 18px;
+ }
}
.icon-merge-request-unmerged {
diff --git a/app/assets/stylesheets/pages/merge_requests.scss b/app/assets/stylesheets/pages/merge_requests.scss
index e6feded1d4f..c8d155706a9 100644
--- a/app/assets/stylesheets/pages/merge_requests.scss
+++ b/app/assets/stylesheets/pages/merge_requests.scss
@@ -461,6 +461,10 @@
.author-link {
display: inline-block;
}
+
+ .issuable-comments {
+ height: 18px;
+ }
}
.merge-request-title {
diff --git a/app/assets/stylesheets/pages/projects.scss b/app/assets/stylesheets/pages/projects.scss
index 801e9e7204c..c80beceae52 100644
--- a/app/assets/stylesheets/pages/projects.scss
+++ b/app/assets/stylesheets/pages/projects.scss
@@ -889,7 +889,11 @@ pre.light-well {
@include basic-list-stats;
display: flex;
align-items: center;
- padding: $gl-padding-12 0;
+ padding: $gl-padding 0;
+
+ @include media-breakpoint-up(lg) {
+ padding: $gl-padding 0;
+ }
&.no-description {
@include media-breakpoint-up(sm) {
@@ -905,7 +909,7 @@ pre.light-well {
}
h2 {
- font-size: $gl-font-size;
+ font-size: $gl-font-size-large;
font-weight: $gl-font-weight-bold;
margin-bottom: 0;
@@ -947,7 +951,6 @@ pre.light-well {
.description {
line-height: 1.5;
- color: $gl-text-color-secondary;
}
@include media-breakpoint-down(md) {
@@ -1093,6 +1096,7 @@ pre.light-well {
&:not(.explore) {
.forks {
display: none;
+
}
}
diff --git a/app/controllers/admin/application_settings_controller.rb b/app/controllers/admin/application_settings_controller.rb
index 03e935fceae..dc16ad80980 100644
--- a/app/controllers/admin/application_settings_controller.rb
+++ b/app/controllers/admin/application_settings_controller.rb
@@ -6,16 +6,15 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController
before_action :set_application_setting
before_action :whitelist_query_limiting, only: [:usage_data]
- VALID_SETTING_PANELS = %w(general integrations repository templates
+ VALID_SETTING_PANELS = %w(show integrations repository templates
ci_cd reporting metrics_and_profiling
network geo preferences).freeze
- VALID_SETTING_PANELS.each do |action|
- define_method(action) { perform_update if submitted? }
+ def show
end
- def show
- render :general
+ (VALID_SETTING_PANELS - %w(show)).each do |action|
+ define_method(action) { perform_update if submitted? }
end
def update
@@ -145,7 +144,7 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController
end
def render_update_error
- action = VALID_SETTING_PANELS.include?(action_name) ? action_name : :general
+ action = VALID_SETTING_PANELS.include?(action_name) ? action_name : :show
render action
end
diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb
index af87e04f9c8..0d992bb35f8 100644
--- a/app/controllers/projects/merge_requests_controller.rb
+++ b/app/controllers/projects/merge_requests_controller.rb
@@ -211,7 +211,7 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
end
def discussions
- merge_request.discussions_diffs.load_highlight
+ merge_request.preload_discussions_diff_highlight
super
end
diff --git a/app/controllers/projects/pipelines_controller.rb b/app/controllers/projects/pipelines_controller.rb
index 477ba36e9d1..28c25dbc1e6 100644
--- a/app/controllers/projects/pipelines_controller.rb
+++ b/app/controllers/projects/pipelines_controller.rb
@@ -8,9 +8,6 @@ class Projects::PipelinesController < Projects::ApplicationController
before_action :authorize_read_build!, only: [:index]
before_action :authorize_create_pipeline!, only: [:new, :create]
before_action :authorize_update_pipeline!, only: [:retry, :cancel]
- before_action do
- push_frontend_feature_flag(:hide_dismissed_vulnerabilities)
- end
around_action :allow_gitaly_ref_name_caching, only: [:index, :show]
@@ -199,7 +196,12 @@ class Projects::PipelinesController < Projects::ApplicationController
end
def latest_pipeline
- @project.latest_pipeline_for_ref(params['ref'])
+ ref = params['ref'].presence || @project.default_branch
+ sha = @project.commit(ref)&.sha
+
+ @project.ci_pipelines
+ .newest_first(ref: ref, sha: sha)
+ .first
&.present(current_user: current_user)
end
diff --git a/app/finders/issuable_finder.rb b/app/finders/issuable_finder.rb
index 2364777cdc5..8ed6ff56e2b 100644
--- a/app/finders/issuable_finder.rb
+++ b/app/finders/issuable_finder.rb
@@ -46,13 +46,10 @@ class IssuableFinder
# This is used in unassigning users
NONE = '0'
- NEGATABLE_PARAMS_HELPER_KEYS = %i[include_subgroups in].freeze
-
attr_accessor :current_user, :params
- class << self
- def scalar_params
- @scalar_params ||= %i[
+ def self.scalar_params
+ @scalar_params ||= %i[
assignee_id
assignee_username
author_id
@@ -63,30 +60,14 @@ class IssuableFinder
search
in
]
- end
-
- def array_params
- @array_params ||= { label_name: [], assignee_username: [] }
- end
-
- # This should not be used in controller strong params!
- def negatable_scalar_params
- @negatable_scalar_params ||= scalar_params + %i[project_id group_id]
- end
-
- # This should not be used in controller strong params!
- def negatable_array_params
- @negatable_array_params ||= array_params.keys.append(:iids)
- end
+ end
- # This should not be used in controller strong params!
- def negatable_params
- @negatable_params ||= negatable_scalar_params + negatable_array_params
- end
+ def self.array_params
+ @array_params ||= { label_name: [], assignee_username: [] }
+ end
- def valid_params
- @valid_params ||= scalar_params + [array_params] + [{ not: [] }]
- end
+ def self.valid_params
+ @valid_params ||= scalar_params + [array_params]
end
def initialize(current_user, params = {})
@@ -98,9 +79,6 @@ class IssuableFinder
items = init_collection
items = filter_items(items)
- # Let's see if we have to negate anything
- items = by_negation(items)
-
# This has to be last as we use a CTE as an optimization fence
# for counts by passing the force_cte param and enabling the
# attempt_group_search_optimizations feature flag
@@ -388,33 +366,6 @@ class IssuableFinder
Array(value).last.to_sym
end
- # Negates all params found in `negatable_params`
- # rubocop: disable CodeReuse/ActiveRecord
- def by_negation(items)
- not_params = params[:not].dup
- # API endpoints send in `nil` values so we test if there are any non-nil
- return items unless not_params.present? && not_params.values.any?
-
- not_params.keep_if { |_k, v| v.present? }.each do |(key, value)|
- # These aren't negatable params themselves, but rather help other searches, so we skip them.
- # They will be added into all the NOT searches.
- next if NEGATABLE_PARAMS_HELPER_KEYS.include?(key.to_sym)
- next unless self.class.negatable_params.include?(key.to_sym)
-
- # These are "helper" params that are required inside the NOT to get the right results. They usually come in
- # at the top-level params, but if they do come in inside the `:not` params, they should take precedence.
- not_helpers = params.slice(*NEGATABLE_PARAMS_HELPER_KEYS).merge(params[:not].slice(*NEGATABLE_PARAMS_HELPER_KEYS))
- not_param = { key => value }.with_indifferent_access.merge(not_helpers)
-
- items_to_negate = self.class.new(current_user, not_param).execute
-
- items = items.where.not(id: items_to_negate)
- end
-
- items
- end
- # rubocop: enable CodeReuse/ActiveRecord
-
# rubocop: disable CodeReuse/ActiveRecord
def by_scope(items)
return items.none if current_user_related? && !current_user
diff --git a/app/graphql/resolvers/issues_resolver.rb b/app/graphql/resolvers/issues_resolver.rb
index 4e71a7a9ead..b50186c5a82 100644
--- a/app/graphql/resolvers/issues_resolver.rb
+++ b/app/graphql/resolvers/issues_resolver.rb
@@ -11,32 +11,31 @@ module Resolvers
description: 'The list of IIDs of issues, e.g., [1, 2]'
argument :state, Types::IssuableStateEnum,
required: false,
- description: 'Current state of Issue'
+ description: "Current state of Issue"
argument :label_name, GraphQL::STRING_TYPE.to_list_type,
required: false,
- description: 'Labels applied to the Issue'
+ description: "Labels applied to the Issue"
argument :created_before, Types::TimeType,
required: false,
- description: 'Issues created before this date'
+ description: "Issues created before this date"
argument :created_after, Types::TimeType,
required: false,
- description: 'Issues created after this date'
+ description: "Issues created after this date"
argument :updated_before, Types::TimeType,
required: false,
- description: 'Issues updated before this date'
+ description: "Issues updated before this date"
argument :updated_after, Types::TimeType,
required: false,
- description: 'Issues updated after this date'
+ description: "Issues updated after this date"
argument :closed_before, Types::TimeType,
required: false,
- description: 'Issues closed before this date'
+ description: "Issues closed before this date"
argument :closed_after, Types::TimeType,
required: false,
- description: 'Issues closed after this date'
+ description: "Issues closed after this date"
argument :search, GraphQL::STRING_TYPE, # rubocop:disable Graphql/Descriptions
required: false
- argument :sort, Types::SortEnum,
- description: 'Sort issues by this criteria',
+ argument :sort, Types::Sort, # rubocop:disable Graphql/Descriptions
required: false,
default_value: 'created_desc'
diff --git a/app/graphql/types/order.rb b/app/graphql/types/order.rb
new file mode 100644
index 00000000000..c5e1cc406b4
--- /dev/null
+++ b/app/graphql/types/order.rb
@@ -0,0 +1,8 @@
+# frozen_string_literal: true
+
+module Types
+ class Types::Order < Types::BaseEnum
+ value "id", "Created at date"
+ value "updated_at", "Updated at date"
+ end
+end
diff --git a/app/graphql/types/sort.rb b/app/graphql/types/sort.rb
new file mode 100644
index 00000000000..1f756fdab69
--- /dev/null
+++ b/app/graphql/types/sort.rb
@@ -0,0 +1,10 @@
+# frozen_string_literal: true
+
+module Types
+ class Types::Sort < Types::BaseEnum
+ value "updated_desc", "Updated at descending order"
+ value "updated_asc", "Updated at ascending order"
+ value "created_desc", "Created at descending order"
+ value "created_asc", "Created at ascending order"
+ end
+end
diff --git a/app/graphql/types/sort_enum.rb b/app/graphql/types/sort_enum.rb
deleted file mode 100644
index 3245cb33e0d..00000000000
--- a/app/graphql/types/sort_enum.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-# frozen_string_literal: true
-
-module Types
- class SortEnum < BaseEnum
- graphql_name 'Sort'
- description 'Common sort values'
-
- value 'updated_desc', 'Updated at descending order'
- value 'updated_asc', 'Updated at ascending order'
- value 'created_desc', 'Created at descending order'
- value 'created_asc', 'Created at ascending order'
- end
-end
diff --git a/app/helpers/page_layout_helper.rb b/app/helpers/page_layout_helper.rb
index 46e2c9ce56e..ec1d8577f36 100644
--- a/app/helpers/page_layout_helper.rb
+++ b/app/helpers/page_layout_helper.rb
@@ -1,3 +1,4 @@
+# coding: utf-8
# frozen_string_literal: true
module PageLayoutHelper
diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb
index 5ed95311767..3fb39a19cf0 100644
--- a/app/helpers/projects_helper.rb
+++ b/app/helpers/projects_helper.rb
@@ -562,7 +562,7 @@ module ProjectsHelper
allowedVisibilityOptions: project_allowed_visibility_levels(project),
visibilityHelpPath: help_page_path('public_access/public_access'),
registryAvailable: Gitlab.config.registry.enabled,
- registryHelpPath: help_page_path('user/packages/container_registry/index'),
+ registryHelpPath: help_page_path('user/project/container_registry'),
lfsAvailable: Gitlab.config.lfs.enabled,
lfsHelpPath: help_page_path('workflow/lfs/manage_large_binaries_with_git_lfs'),
pagesAvailable: Gitlab.config.pages.enabled,
diff --git a/app/models/ci/artifact_blob.rb b/app/models/ci/artifact_blob.rb
index ef00ad75683..d87d6a5cb2f 100644
--- a/app/models/ci/artifact_blob.rb
+++ b/app/models/ci/artifact_blob.rb
@@ -4,7 +4,7 @@ module Ci
class ArtifactBlob
include BlobLike
- EXTENSIONS_SERVED_BY_PAGES = %w[.html .htm .txt .json .xml .log].freeze
+ EXTENSIONS_SERVED_BY_PAGES = %w[.html .htm .txt .json .log].freeze
attr_reader :entry
diff --git a/app/models/ci/build_metadata.rb b/app/models/ci/build_metadata.rb
index 3097e40dd3b..4046048be1c 100644
--- a/app/models/ci/build_metadata.rb
+++ b/app/models/ci/build_metadata.rb
@@ -4,12 +4,9 @@ module Ci
# The purpose of this class is to store Build related data that can be disposed.
# Data that should be persisted forever, should be stored with Ci::Build model.
class BuildMetadata < ApplicationRecord
- BuildTimeout = Struct.new(:value, :source)
-
extend Gitlab::Ci::Model
include Presentable
include ChronicDurationAttribute
- include Gitlab::Utils::StrongMemoize
self.table_name = 'ci_builds_metadata'
@@ -31,16 +28,17 @@ module Ci
enum timeout_source: {
unknown_timeout_source: 1,
project_timeout_source: 2,
- runner_timeout_source: 3,
- job_timeout_source: 4
+ runner_timeout_source: 3
}
def update_timeout_state
- timeout = timeout_with_highest_precedence
+ return unless build.runner.present?
- return unless timeout
+ project_timeout = project&.build_timeout
+ timeout = [project_timeout, build.runner.maximum_timeout].compact.min
+ timeout_source = timeout < project_timeout ? :runner_timeout_source : :project_timeout_source
- update(timeout: timeout.value, timeout_source: timeout.source)
+ update(timeout: timeout, timeout_source: timeout_source)
end
private
@@ -48,37 +46,5 @@ module Ci
def set_build_project
self.project_id ||= self.build.project_id
end
-
- def timeout_with_highest_precedence
- [(job_timeout || project_timeout), runner_timeout].compact.min_by { |timeout| timeout.value }
- end
-
- def project_timeout
- strong_memoize(:project_timeout) do
- BuildTimeout.new(project&.build_timeout, :project_timeout_source)
- end
- end
-
- def job_timeout
- return unless build.options
-
- strong_memoize(:job_timeout) do
- if timeout_from_options = build.options[:job_timeout]
- BuildTimeout.new(timeout_from_options, :job_timeout_source)
- end
- end
- end
-
- def runner_timeout
- return unless runner_timeout_set?
-
- strong_memoize(:runner_timeout) do
- BuildTimeout.new(build.runner.maximum_timeout, :runner_timeout_source)
- end
- end
-
- def runner_timeout_set?
- build.runner&.maximum_timeout.to_i > 0
- end
end
end
diff --git a/app/models/clusters/applications/ingress.rb b/app/models/clusters/applications/ingress.rb
index 50def3ba38c..44c66f06059 100644
--- a/app/models/clusters/applications/ingress.rb
+++ b/app/models/clusters/applications/ingress.rb
@@ -35,6 +35,10 @@ module Clusters
'stable/nginx-ingress'
end
+ def values
+ content_values.to_yaml
+ end
+
def allowed_to_uninstall?
external_ip_or_hostname? && application_jupyter_nil_or_installable?
end
@@ -67,6 +71,23 @@ module Clusters
private
+ def specification
+ return {} unless Feature.enabled?(:ingress_modsecurity)
+
+ {
+ "controller" => {
+ "config" => {
+ "enable-modsecurity" => "true",
+ "enable-owasp-modsecurity-crs" => "true"
+ }
+ }
+ }
+ end
+
+ def content_values
+ YAML.load_file(chart_values_file).deep_merge!(specification)
+ end
+
def application_jupyter_nil_or_installable?
cluster.application_jupyter.nil? || cluster.application_jupyter&.installable?
end
diff --git a/app/models/clusters/cluster.rb b/app/models/clusters/cluster.rb
index 7a61622b139..7855fb69bd6 100644
--- a/app/models/clusters/cluster.rb
+++ b/app/models/clusters/cluster.rb
@@ -37,18 +37,13 @@ module Clusters
has_one :platform_kubernetes, class_name: 'Clusters::Platforms::Kubernetes', inverse_of: :cluster, autosave: true
- def self.has_one_cluster_application(name) # rubocop:disable Naming/PredicateName
- application = APPLICATIONS[name.to_s]
- has_one application.association_name, class_name: application.to_s # rubocop:disable Rails/ReflectionClassName
- end
-
- has_one_cluster_application :helm
- has_one_cluster_application :ingress
- has_one_cluster_application :cert_manager
- has_one_cluster_application :prometheus
- has_one_cluster_application :runner
- has_one_cluster_application :jupyter
- has_one_cluster_application :knative
+ has_one :application_helm, class_name: 'Clusters::Applications::Helm'
+ has_one :application_ingress, class_name: 'Clusters::Applications::Ingress'
+ has_one :application_cert_manager, class_name: 'Clusters::Applications::CertManager'
+ has_one :application_prometheus, class_name: 'Clusters::Applications::Prometheus'
+ has_one :application_runner, class_name: 'Clusters::Applications::Runner'
+ has_one :application_jupyter, class_name: 'Clusters::Applications::Jupyter'
+ has_one :application_knative, class_name: 'Clusters::Applications::Knative'
has_many :kubernetes_namespaces
@@ -132,9 +127,15 @@ module Clusters
end
def applications
- APPLICATIONS.values.map do |application_class|
- public_send(application_class.association_name) || public_send("build_#{application_class.association_name}") # rubocop:disable GitlabSecurity/PublicSend
- end
+ [
+ application_helm || build_application_helm,
+ application_ingress || build_application_ingress,
+ application_cert_manager || build_application_cert_manager,
+ application_prometheus || build_application_prometheus,
+ application_runner || build_application_runner,
+ application_jupyter || build_application_jupyter,
+ application_knative || build_application_knative
+ ]
end
def provider
diff --git a/app/models/clusters/concerns/application_core.rb b/app/models/clusters/concerns/application_core.rb
index d1b57a21a7d..803a65726d3 100644
--- a/app/models/clusters/concerns/application_core.rb
+++ b/app/models/clusters/concerns/application_core.rb
@@ -32,10 +32,6 @@ module Clusters
self.to_s.demodulize.underscore
end
- def self.association_name
- :"application_#{application_name}"
- end
-
def name
self.class.application_name
end
diff --git a/app/models/commit.rb b/app/models/commit.rb
index a442f607fbf..1470b50f396 100644
--- a/app/models/commit.rb
+++ b/app/models/commit.rb
@@ -1,3 +1,4 @@
+# coding: utf-8
# frozen_string_literal: true
class Commit
diff --git a/app/models/concerns/routable.rb b/app/models/concerns/routable.rb
index 57118bf7a6b..8b011bca72c 100644
--- a/app/models/concerns/routable.rb
+++ b/app/models/concerns/routable.rb
@@ -33,9 +33,16 @@ module Routable
#
# Returns a single object, or nil.
def find_by_full_path(path, follow_redirects: false)
- # Case sensitive match first (it's cheaper and the usual case)
- # If we didn't have an exact match, we perform a case insensitive search
- found = includes(:route).find_by(routes: { path: path }) || where_full_path_in([path]).take
+ routable_calls_counter.increment(method: 'find_by_full_path')
+
+ if Feature.enabled?(:routable_two_step_lookup)
+ # Case sensitive match first (it's cheaper and the usual case)
+ # If we didn't have an exact match, we perform a case insensitive search
+ found = includes(:route).find_by(routes: { path: path }) || where_full_path_in([path]).take
+ else
+ order_sql = Arel.sql("(CASE WHEN routes.path = #{connection.quote(path)} THEN 0 ELSE 1 END)")
+ found = where_full_path_in([path]).reorder(order_sql).take
+ end
return found if found
@@ -54,12 +61,19 @@ module Routable
def where_full_path_in(paths)
return none if paths.empty?
+ routable_calls_counter.increment(method: 'where_full_path_in')
+
wheres = paths.map do |path|
"(LOWER(routes.path) = LOWER(#{connection.quote(path)}))"
end
includes(:route).where(wheres.join(' OR ')).references(:routes)
end
+
+ # Temporary instrumentation of method calls
+ def routable_calls_counter
+ @routable_calls_counter ||= Gitlab::Metrics.counter(:gitlab_routable_calls_total, 'Number of calls to Routable by method')
+ end
end
def full_name
diff --git a/app/models/diff_note.rb b/app/models/diff_note.rb
index aa7286a9971..0b00cf10714 100644
--- a/app/models/diff_note.rb
+++ b/app/models/diff_note.rb
@@ -108,10 +108,13 @@ class DiffNote < Note
end
def fetch_diff_file
- return note_diff_file.raw_diff_file if note_diff_file
-
file =
- if created_at_diff?(noteable.diff_refs)
+ if note_diff_file
+ diff = Gitlab::Git::Diff.new(note_diff_file.to_hash)
+ Gitlab::Diff::File.new(diff,
+ repository: repository,
+ diff_refs: original_position.diff_refs)
+ elsif created_at_diff?(noteable.diff_refs)
# We're able to use the already persisted diffs (Postgres) if we're
# presenting a "current version" of the MR discussion diff.
# So no need to make an extra Gitaly diff request for it.
@@ -123,7 +126,9 @@ class DiffNote < Note
original_position.diff_file(repository)
end
- file&.unfold_diff_lines(position)
+ # Since persisted diff files already have its content "unfolded"
+ # there's no need to make it pass through the unfolding process.
+ file&.unfold_diff_lines(position) unless note_diff_file
file
end
diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb
index ac26d29ad19..90061fe181e 100644
--- a/app/models/merge_request.rb
+++ b/app/models/merge_request.rb
@@ -454,17 +454,24 @@ class MergeRequest < ApplicationRecord
true
end
+ def preload_discussions_diff_highlight
+ preloadable_files = note_diff_files.for_commit_or_unresolved
+
+ discussions_diffs.load_highlight(preloadable_files.pluck(:id))
+ end
+
def discussions_diffs
strong_memoize(:discussions_diffs) do
- note_diff_files = NoteDiffFile
- .joins(:diff_note)
- .merge(notes.or(commit_notes))
- .includes(diff_note: :project)
-
Gitlab::DiscussionsDiff::FileCollection.new(note_diff_files.to_a)
end
end
+ def note_diff_files
+ NoteDiffFile
+ .where(diff_note: discussion_notes)
+ .includes(diff_note: :project)
+ end
+
def diff_size
# Calling `merge_request_diff.diffs.real_size` will also perform
# highlighting, which we don't need here.
diff --git a/app/models/milestone.rb b/app/models/milestone.rb
index 800c492e8e2..4b9fee2bbdf 100644
--- a/app/models/milestone.rb
+++ b/app/models/milestone.rb
@@ -27,8 +27,11 @@ class Milestone < ApplicationRecord
belongs_to :project
belongs_to :group
- has_many :milestone_releases
- has_many :releases, through: :milestone_releases
+ # A one-to-one relationship is set up here as part of a MVC: https://gitlab.com/gitlab-org/gitlab-ce/issues/62402
+ # However, on the long term, we will want a many-to-many relationship between Release and Milestone.
+ # The "has_one through" allows us today to set up this one-to-one relationship while setting up the architecture for the long-term (ie intermediate table).
+ has_one :milestone_release
+ has_one :release, through: :milestone_release
has_internal_id :iid, scope: :project, init: ->(s) { s&.project&.milestones&.maximum(:iid) }
has_internal_id :iid, scope: :group, init: ->(s) { s&.group&.milestones&.maximum(:iid) }
@@ -65,7 +68,7 @@ class Milestone < ApplicationRecord
validate :milestone_type_check
validate :start_date_should_be_less_than_due_date, if: proc { |m| m.start_date.present? && m.due_date.present? }
validate :dates_within_4_digits
- validates_associated :milestone_releases, message: -> (_, obj) { obj[:value].map(&:errors).map(&:full_messages).join(",") }
+ validates_associated :milestone_release, message: -> (_, obj) { obj[:value].errors.full_messages.join(",") }
strip_attributes :title
diff --git a/app/models/milestone_release.rb b/app/models/milestone_release.rb
index f7127df339d..c8743a8cad8 100644
--- a/app/models/milestone_release.rb
+++ b/app/models/milestone_release.rb
@@ -4,11 +4,9 @@ class MilestoneRelease < ApplicationRecord
belongs_to :milestone
belongs_to :release
+ validates :milestone_id, uniqueness: { scope: [:release_id] }
validate :same_project_between_milestone_and_release
- # Keep until 2019-11-29
- self.ignored_columns += %i[id]
-
private
def same_project_between_milestone_and_release
diff --git a/app/models/note_diff_file.rb b/app/models/note_diff_file.rb
index 67a6d5d6d6b..fcc9e2b3fd8 100644
--- a/app/models/note_diff_file.rb
+++ b/app/models/note_diff_file.rb
@@ -3,11 +3,15 @@
class NoteDiffFile < ApplicationRecord
include DiffFile
+ scope :for_commit_or_unresolved, -> do
+ joins(:diff_note).where("resolved_at IS NULL OR noteable_type = 'Commit'")
+ end
+
scope :referencing_sha, -> (oids, project_id:) do
joins(:diff_note).where(notes: { project_id: project_id, commit_id: oids })
end
- delegate :original_position, :project, :resolved_at, to: :diff_note
+ delegate :original_position, :project, to: :diff_note
belongs_to :diff_note, inverse_of: :note_diff_file
diff --git a/app/models/project.rb b/app/models/project.rb
index 57f1ca98ee2..96c715095f6 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -58,7 +58,6 @@ class Project < ApplicationRecord
ACCESS_REQUEST_APPROVERS_TO_BE_NOTIFIED_LIMIT = 10
SORTING_PREFERENCE_FIELD = :projects_sort
- MAX_BUILD_TIMEOUT = 1.month
cache_markdown_field :description, pipeline: :description
@@ -431,7 +430,7 @@ class Project < ApplicationRecord
validates :build_timeout, allow_nil: true,
numericality: { greater_than_or_equal_to: 10.minutes,
- less_than: MAX_BUILD_TIMEOUT,
+ less_than: 1.month,
only_integer: true,
message: _('needs to be between 10 minutes and 1 month') }
@@ -753,15 +752,6 @@ class Project < ApplicationRecord
latest_successful_build_for_ref(job_name, ref) || raise(ActiveRecord::RecordNotFound.new("Couldn't find job #{job_name}"))
end
- def latest_pipeline_for_ref(ref = default_branch)
- ref = ref.presence || default_branch
- sha = commit(ref)&.sha
-
- return unless sha
-
- ci_pipelines.newest_first(ref: ref, sha: sha).first
- end
-
def merge_base_commit(first_commit_id, second_commit_id)
sha = repository.merge_base(first_commit_id, second_commit_id)
commit_by(oid: sha) if sha
diff --git a/app/models/project_services/bugzilla_service.rb b/app/models/project_services/bugzilla_service.rb
index 0a498fde95a..8b79b5e9f0c 100644
--- a/app/models/project_services/bugzilla_service.rb
+++ b/app/models/project_services/bugzilla_service.rb
@@ -3,6 +3,8 @@
class BugzillaService < IssueTrackerService
validates :project_url, :issues_url, :new_issue_url, presence: true, public_url: true, if: :activated?
+ prop_accessor :project_url, :issues_url, :new_issue_url
+
def default_title
'Bugzilla'
end
diff --git a/app/models/project_services/custom_issue_tracker_service.rb b/app/models/project_services/custom_issue_tracker_service.rb
index dbc42b1b86d..535fcf6b94e 100644
--- a/app/models/project_services/custom_issue_tracker_service.rb
+++ b/app/models/project_services/custom_issue_tracker_service.rb
@@ -3,6 +3,8 @@
class CustomIssueTrackerService < IssueTrackerService
validates :project_url, :issues_url, :new_issue_url, presence: true, public_url: true, if: :activated?
+ prop_accessor :title, :description, :project_url, :issues_url, :new_issue_url
+
def default_title
'Custom Issue Tracker'
end
diff --git a/app/models/project_services/data_fields.rb b/app/models/project_services/data_fields.rb
index 0f5385f8ce2..438d85098c8 100644
--- a/app/models/project_services/data_fields.rb
+++ b/app/models/project_services/data_fields.rb
@@ -3,56 +3,8 @@
module DataFields
extend ActiveSupport::Concern
- class_methods do
- # Provide convenient accessor methods for data fields.
- # TODO: Simplify as part of https://gitlab.com/gitlab-org/gitlab-ce/issues/63084
- def data_field(*args)
- args.each do |arg|
- self.class_eval <<-RUBY, __FILE__, __LINE__ + 1
- unless method_defined?(arg)
- def #{arg}
- data_fields.send('#{arg}') || (properties && properties['#{arg}'])
- end
- end
-
- def #{arg}=(value)
- @old_data_fields ||= {}
- @old_data_fields['#{arg}'] ||= #{arg} # set only on the first assignment, IOW we remember the original value only
- data_fields.send('#{arg}=', value)
- end
-
- def #{arg}_touched?
- @old_data_fields ||= {}
- @old_data_fields.has_key?('#{arg}')
- end
-
- def #{arg}_changed?
- #{arg}_touched? && @old_data_fields['#{arg}'] != #{arg}
- end
-
- def #{arg}_was
- return unless #{arg}_touched?
- return if data_fields.persisted? # arg_was does not work for attr_encrypted
-
- legacy_properties_data['#{arg}']
- end
- RUBY
- end
- end
- end
-
included do
- has_one :issue_tracker_data, autosave: true
- has_one :jira_tracker_data, autosave: true
-
- def data_fields
- raise NotImplementedError
- end
-
- def data_fields_present?
- data_fields.persisted?
- rescue NotImplementedError
- false
- end
+ has_one :issue_tracker_data
+ has_one :jira_tracker_data
end
end
diff --git a/app/models/project_services/gitlab_issue_tracker_service.rb b/app/models/project_services/gitlab_issue_tracker_service.rb
index ec28602b5e6..51032932eab 100644
--- a/app/models/project_services/gitlab_issue_tracker_service.rb
+++ b/app/models/project_services/gitlab_issue_tracker_service.rb
@@ -5,6 +5,8 @@ class GitlabIssueTrackerService < IssueTrackerService
validates :project_url, :issues_url, :new_issue_url, presence: true, public_url: true, if: :activated?
+ prop_accessor :project_url, :issues_url, :new_issue_url
+
default_value_for :default, true
def default_title
diff --git a/app/models/project_services/issue_tracker_data.rb b/app/models/project_services/issue_tracker_data.rb
index b1d67657fe6..2c1d28ed421 100644
--- a/app/models/project_services/issue_tracker_data.rb
+++ b/app/models/project_services/issue_tracker_data.rb
@@ -6,6 +6,9 @@ class IssueTrackerData < ApplicationRecord
delegate :activated?, to: :service, allow_nil: true
validates :service, presence: true
+ validates :project_url, presence: true, public_url: { enforce_sanitization: true }, if: :activated?
+ validates :issues_url, presence: true, public_url: { enforce_sanitization: true }, if: :activated?
+ validates :new_issue_url, public_url: { enforce_sanitization: true }, if: :activated?
def self.encryption_options
{
diff --git a/app/models/project_services/issue_tracker_service.rb b/app/models/project_services/issue_tracker_service.rb
index c201bd2ea18..b6ad46513db 100644
--- a/app/models/project_services/issue_tracker_service.rb
+++ b/app/models/project_services/issue_tracker_service.rb
@@ -3,14 +3,9 @@
class IssueTrackerService < Service
validate :one_issue_tracker, if: :activated?, on: :manual_change
- # TODO: we can probably just delegate as part of
- # https://gitlab.com/gitlab-org/gitlab-ce/issues/63084
- data_field :project_url, :issues_url, :new_issue_url
-
default_value_for :category, 'issue_tracker'
- before_validation :handle_properties
- before_validation :set_default_data, on: :create
+ before_save :handle_properties
# Pattern used to extract links from comments
# Override this method on services that uses different patterns
@@ -48,31 +43,12 @@ class IssueTrackerService < Service
end
def handle_properties
- # this has been moved from initialize_properties and should be improved
- # as part of https://gitlab.com/gitlab-org/gitlab-ce/issues/63084
- return unless properties
-
- @legacy_properties_data = properties.dup
- data_values = properties.slice!('title', 'description')
- properties.each do |key, _|
+ properties.slice('title', 'description').each do |key, _|
current_value = self.properties.delete(key)
value = attribute_changed?(key) ? attribute_change(key).last : current_value
write_attribute(key, value)
end
-
- data_values.reject! { |key| data_fields.changed.include?(key) }
- data_fields.assign_attributes(data_values) if data_values.present?
-
- self.properties = {}
- end
-
- def legacy_properties_data
- @legacy_properties_data ||= {}
- end
-
- def data_fields
- issue_tracker_data || self.build_issue_tracker_data
end
def default?
@@ -80,7 +56,7 @@ class IssueTrackerService < Service
end
def issue_url(iid)
- issues_url.gsub(':id', iid.to_s)
+ self.issues_url.gsub(':id', iid.to_s)
end
def issue_tracker_path
@@ -104,22 +80,25 @@ class IssueTrackerService < Service
]
end
- def initialize_properties
- {}
- end
-
# Initialize with default properties values
- def set_default_data
- return unless issues_tracker.present?
-
- self.title ||= issues_tracker['title']
-
- # we don't want to override if we have set something
- return if project_url || issues_url || new_issue_url
-
- data_fields.project_url = issues_tracker['project_url']
- data_fields.issues_url = issues_tracker['issues_url']
- data_fields.new_issue_url = issues_tracker['new_issue_url']
+ # or receive a block with custom properties
+ def initialize_properties(&block)
+ return unless properties.nil?
+
+ if enabled_in_gitlab_config
+ if block_given?
+ yield
+ else
+ self.properties = {
+ title: issues_tracker['title'],
+ project_url: issues_tracker['project_url'],
+ issues_url: issues_tracker['issues_url'],
+ new_issue_url: issues_tracker['new_issue_url']
+ }
+ end
+ else
+ self.properties = {}
+ end
end
def self.supported_events
diff --git a/app/models/project_services/jira_service.rb b/app/models/project_services/jira_service.rb
index 61ae78a0b95..0728c83005e 100644
--- a/app/models/project_services/jira_service.rb
+++ b/app/models/project_services/jira_service.rb
@@ -17,10 +17,7 @@ class JiraService < IssueTrackerService
# Jira Cloud version is deprecating authentication via username and password.
# We should use username/password for Jira Server and email/api_token for Jira Cloud,
# for more information check: https://gitlab.com/gitlab-org/gitlab-ce/issues/49936.
-
- # TODO: we can probably just delegate as part of
- # https://gitlab.com/gitlab-org/gitlab-ce/issues/63084
- data_field :username, :password, :url, :api_url, :jira_issue_transition_id
+ prop_accessor :username, :password, :url, :api_url, :jira_issue_transition_id
before_update :reset_password
@@ -38,34 +35,24 @@ class JiraService < IssueTrackerService
end
def initialize_properties
- {}
- end
-
- def data_fields
- jira_tracker_data || self.build_jira_tracker_data
+ super do
+ self.properties = {
+ url: issues_tracker['url'],
+ api_url: issues_tracker['api_url']
+ }
+ end
end
def reset_password
- data_fields.password = nil if reset_password?
- end
-
- def set_default_data
- return unless issues_tracker.present?
-
- self.title ||= issues_tracker['title']
-
- return if url
-
- data_fields.url ||= issues_tracker['url']
- data_fields.api_url ||= issues_tracker['api_url']
+ self.password = nil if reset_password?
end
def options
url = URI.parse(client_url)
{
- username: username,
- password: password,
+ username: self.username,
+ password: self.password,
site: URI.join(url, '/').to_s, # Intended to find the root
context_path: url.path,
auth_type: :basic,
diff --git a/app/models/project_services/jira_tracker_data.rb b/app/models/project_services/jira_tracker_data.rb
index e4e0f64150a..4f528e3d81b 100644
--- a/app/models/project_services/jira_tracker_data.rb
+++ b/app/models/project_services/jira_tracker_data.rb
@@ -6,6 +6,13 @@ class JiraTrackerData < ApplicationRecord
delegate :activated?, to: :service, allow_nil: true
validates :service, presence: true
+ validates :url, public_url: { enforce_sanitization: true }, presence: true, if: :activated?
+ validates :api_url, public_url: { enforce_sanitization: true }, allow_blank: true
+ validates :username, presence: true, if: :activated?
+ validates :password, presence: true, if: :activated?
+ validates :jira_issue_transition_id,
+ format: { with: Gitlab::Regex.jira_transition_id_regex, message: s_("JiraService|transition ids can have only numbers which can be split with , or ;") },
+ allow_blank: true
def self.encryption_options
{
diff --git a/app/models/project_services/redmine_service.rb b/app/models/project_services/redmine_service.rb
index a4ca0d20669..5ca057ca833 100644
--- a/app/models/project_services/redmine_service.rb
+++ b/app/models/project_services/redmine_service.rb
@@ -3,6 +3,8 @@
class RedmineService < IssueTrackerService
validates :project_url, :issues_url, :new_issue_url, presence: true, public_url: true, if: :activated?
+ prop_accessor :project_url, :issues_url, :new_issue_url
+
def default_title
'Redmine'
end
diff --git a/app/models/project_services/youtrack_service.rb b/app/models/project_services/youtrack_service.rb
index 0416eaa5be0..f9de1f7dc49 100644
--- a/app/models/project_services/youtrack_service.rb
+++ b/app/models/project_services/youtrack_service.rb
@@ -3,6 +3,8 @@
class YoutrackService < IssueTrackerService
validates :project_url, :issues_url, presence: true, public_url: true, if: :activated?
+ prop_accessor :project_url, :issues_url
+
# {PROJECT-KEY}-{NUMBER} Examples: YT-1, PRJ-1, gl-030
def self.reference_pattern(only_long: false)
if only_long
diff --git a/app/models/protected_branch.rb b/app/models/protected_branch.rb
index 1857a59e01c..8769d3eb916 100644
--- a/app/models/protected_branch.rb
+++ b/app/models/protected_branch.rb
@@ -40,11 +40,6 @@ class ProtectedBranch < ApplicationRecord
def self.protected_refs(project)
project.protected_branches.select(:name)
end
-
- def self.branch_requires_code_owner_approval?(project, branch_name)
- # NOOP
- #
- end
end
ProtectedBranch.prepend_if_ee('EE::ProtectedBranch')
diff --git a/app/models/release.rb b/app/models/release.rb
index cd63b4d5fef..b2e65974aa0 100644
--- a/app/models/release.rb
+++ b/app/models/release.rb
@@ -12,8 +12,11 @@ class Release < ApplicationRecord
has_many :links, class_name: 'Releases::Link'
- has_many :milestone_releases
- has_many :milestones, through: :milestone_releases
+ # A one-to-one relationship is set up here as part of a MVC: https://gitlab.com/gitlab-org/gitlab-ce/issues/62402
+ # However, on the long term, we will want a many-to-many relationship between Release and Milestone.
+ # The "has_one through" allows us today to set up this one-to-one relationship while setting up the architecture for the long-term (ie intermediate table).
+ has_one :milestone_release
+ has_one :milestone, through: :milestone_release
default_value_for :released_at, allows_nil: false do
Time.zone.now
@@ -23,7 +26,7 @@ class Release < ApplicationRecord
validates :description, :project, :tag, presence: true
validates :name, presence: true, on: :create
- validates_associated :milestone_releases, message: -> (_, obj) { obj[:value].map(&:errors).map(&:full_messages).join(",") }
+ validates_associated :milestone_release, message: -> (_, obj) { obj[:value].errors.full_messages.join(",") }
scope :sorted, -> { order(released_at: :desc) }
diff --git a/app/presenters/ci/build_metadata_presenter.rb b/app/presenters/ci/build_metadata_presenter.rb
index 4871bb3a919..015b1f67db7 100644
--- a/app/presenters/ci/build_metadata_presenter.rb
+++ b/app/presenters/ci/build_metadata_presenter.rb
@@ -5,8 +5,7 @@ module Ci
TIMEOUT_SOURCES = {
unknown_timeout_source: nil,
project_timeout_source: 'project',
- runner_timeout_source: 'runner',
- job_timeout_source: 'job'
+ runner_timeout_source: 'runner'
}.freeze
presents :metadata
diff --git a/app/services/clusters/applications/base_service.rb b/app/services/clusters/applications/base_service.rb
index 67fb3ac8355..a9feb60be6e 100644
--- a/app/services/clusters/applications/base_service.rb
+++ b/app/services/clusters/applications/base_service.rb
@@ -77,10 +77,6 @@ module Clusters
params[:application]
end
- def application_class
- Clusters::Cluster::APPLICATIONS[application_name]
- end
-
def create_oauth_application(application, request)
oauth_application_params = {
name: params[:application],
diff --git a/app/services/clusters/applications/create_service.rb b/app/services/clusters/applications/create_service.rb
index 2a626a402e4..f723c42c049 100644
--- a/app/services/clusters/applications/create_service.rb
+++ b/app/services/clusters/applications/create_service.rb
@@ -10,7 +10,7 @@ module Clusters
end
def builder
- cluster.public_send(application_class.association_name) || # rubocop:disable GitlabSecurity/PublicSend
+ cluster.public_send(:"application_#{application_name}") || # rubocop:disable GitlabSecurity/PublicSend
cluster.public_send(:"build_application_#{application_name}") # rubocop:disable GitlabSecurity/PublicSend
end
end
diff --git a/app/services/clusters/applications/destroy_service.rb b/app/services/clusters/applications/destroy_service.rb
index d666682487b..f3a4c4f754a 100644
--- a/app/services/clusters/applications/destroy_service.rb
+++ b/app/services/clusters/applications/destroy_service.rb
@@ -16,7 +16,7 @@ module Clusters
private
def builder
- cluster.public_send(application_class.association_name) # rubocop:disable GitlabSecurity/PublicSend
+ cluster.public_send(:"application_#{application_name}") # rubocop:disable GitlabSecurity/PublicSend
end
end
end
diff --git a/app/services/clusters/applications/update_service.rb b/app/services/clusters/applications/update_service.rb
index 7a36401f156..0fa937da865 100644
--- a/app/services/clusters/applications/update_service.rb
+++ b/app/services/clusters/applications/update_service.rb
@@ -10,7 +10,7 @@ module Clusters
end
def builder
- cluster.public_send(application_class.association_name) # rubocop:disable GitlabSecurity/PublicSend
+ cluster.public_send(:"application_#{application_name}") # rubocop:disable GitlabSecurity/PublicSend
end
end
end
diff --git a/app/services/projects/create_from_template_service.rb b/app/services/projects/create_from_template_service.rb
index 91ece024e13..31977a7c76a 100644
--- a/app/services/projects/create_from_template_service.rb
+++ b/app/services/projects/create_from_template_service.rb
@@ -9,9 +9,7 @@ module Projects
end
def execute
- return project unless validate_template!
-
- file = built_in_template&.file
+ file = Gitlab::ProjectTemplate.find(template_name)&.file
override_params = params.dup
params[:file] = file
@@ -26,25 +24,6 @@ module Projects
params.delete(:template_name).presence
end
end
-
- private
-
- def validate_template!
- return true if built_in_template
-
- project.errors.add(:template_name, _("'%{template_name}' is unknown or invalid" % { template_name: template_name }))
- false
- end
-
- def built_in_template
- strong_memoize(:built_in_template) do
- Gitlab::ProjectTemplate.find(template_name)
- end
- end
-
- def project
- @project ||= ::Project.new(namespace_id: params[:namespace_id])
- end
end
end
diff --git a/app/services/releases/concerns.rb b/app/services/releases/concerns.rb
index a0ebaea77c8..b5412e97284 100644
--- a/app/services/releases/concerns.rb
+++ b/app/services/releases/concerns.rb
@@ -48,29 +48,25 @@ module Releases
end
end
- def milestones
- return [] unless param_for_milestone_titles_provided?
+ def milestone
+ return unless params[:milestone]
- strong_memoize(:milestones) do
+ strong_memoize(:milestone) do
MilestonesFinder.new(
project: project,
current_user: current_user,
project_ids: Array(project.id),
- state: 'all',
- title: params[:milestones]
- ).execute
+ title: params[:milestone]
+ ).execute.first
end
end
- def inexistent_milestones
- return [] unless param_for_milestone_titles_provided?
-
- existing_milestone_titles = milestones.map(&:title)
- Array(params[:milestones]) - existing_milestone_titles
+ def inexistent_milestone?
+ params[:milestone] && !params[:milestone].empty? && !milestone
end
- def param_for_milestone_titles_provided?
- params.key?(:milestones)
+ def param_for_milestone_title_provided?
+ params[:milestone].present? || params[:milestone]&.empty?
end
end
end
diff --git a/app/services/releases/create_service.rb b/app/services/releases/create_service.rb
index 9a0a876454f..c91d43084d3 100644
--- a/app/services/releases/create_service.rb
+++ b/app/services/releases/create_service.rb
@@ -7,7 +7,7 @@ module Releases
def execute
return error('Access Denied', 403) unless allowed?
return error('Release already exists', 409) if release
- return error("Milestone(s) not found: #{inexistent_milestones.join(', ')}", 400) if inexistent_milestones.any?
+ return error('Milestone does not exist', 400) if inexistent_milestone?
tag = ensure_tag
@@ -61,7 +61,7 @@ module Releases
sha: tag.dereferenced_target.sha,
released_at: released_at,
links_attributes: params.dig(:assets, 'links') || [],
- milestones: milestones
+ milestone: milestone
)
end
end
diff --git a/app/services/releases/update_service.rb b/app/services/releases/update_service.rb
index 7aa51c4a332..70acc68f747 100644
--- a/app/services/releases/update_service.rb
+++ b/app/services/releases/update_service.rb
@@ -9,9 +9,9 @@ module Releases
return error('Release does not exist', 404) unless release
return error('Access Denied', 403) unless allowed?
return error('params is empty', 400) if empty_params?
- return error("Milestone(s) not found: #{inexistent_milestones.join(', ')}", 400) if inexistent_milestones.any?
+ return error('Milestone does not exist', 400) if inexistent_milestone?
- params[:milestones] = milestones if param_for_milestone_titles_provided?
+ params[:milestone] = milestone if param_for_milestone_title_provided?
if release.update(params)
success(tag: existing_tag, release: release)
diff --git a/app/services/service_response.rb b/app/services/service_response.rb
index 08b7e9d0831..f3437ba16de 100644
--- a/app/services/service_response.rb
+++ b/app/services/service_response.rb
@@ -1,8 +1,8 @@
# frozen_string_literal: true
class ServiceResponse
- def self.success(message: nil, payload: {}, http_status: :ok)
- new(status: :success, message: message, payload: payload, http_status: http_status)
+ def self.success(message: nil, payload: {})
+ new(status: :success, message: message, payload: payload)
end
def self.error(message:, payload: {}, http_status: nil)
diff --git a/app/views/admin/application_settings/_account_and_limit.html.haml b/app/views/admin/application_settings/_account_and_limit.html.haml
index 4358365504a..9ed4bc44aae 100644
--- a/app/views/admin/application_settings/_account_and_limit.html.haml
+++ b/app/views/admin/application_settings/_account_and_limit.html.haml
@@ -1,4 +1,4 @@
-= form_for @application_setting, url: general_admin_application_settings_path(anchor: 'js-account-settings'), html: { class: 'fieldset-form' } do |f|
+= form_for @application_setting, url: admin_application_settings_path(anchor: 'js-account-settings'), html: { class: 'fieldset-form' } do |f|
= form_errors(@application_setting)
%fieldset
diff --git a/app/views/admin/application_settings/_diff_limits.html.haml b/app/views/admin/application_settings/_diff_limits.html.haml
index 137b7281e0f..408e569fe07 100644
--- a/app/views/admin/application_settings/_diff_limits.html.haml
+++ b/app/views/admin/application_settings/_diff_limits.html.haml
@@ -1,4 +1,4 @@
-= form_for @application_setting, url: general_admin_application_settings_path(anchor: 'js-merge-request-settings'), html: { class: 'fieldset-form' } do |f|
+= form_for @application_setting, url: admin_application_settings_path(anchor: 'js-merge-request-settings'), html: { class: 'fieldset-form' } do |f|
= form_errors(@application_setting)
%fieldset
diff --git a/app/views/admin/application_settings/_external_authorization_service_form.html.haml b/app/views/admin/application_settings/_external_authorization_service_form.html.haml
index 73412133979..7587ecbf9d3 100644
--- a/app/views/admin/application_settings/_external_authorization_service_form.html.haml
+++ b/app/views/admin/application_settings/_external_authorization_service_form.html.haml
@@ -8,7 +8,7 @@
= _('External Classification Policy Authorization')
.settings-content
- = form_for @application_setting, url: general_admin_application_settings_path(anchor: 'js-external-auth-settings'), html: { class: 'fieldset-form' } do |f|
+ = form_for @application_setting, url: admin_application_settings_path(anchor: 'js-external-auth-settings'), html: { class: 'fieldset-form' } do |f|
= form_errors(@application_setting)
%fieldset
diff --git a/app/views/admin/application_settings/_signin.html.haml b/app/views/admin/application_settings/_signin.html.haml
index 0e45301b598..5f36358f599 100644
--- a/app/views/admin/application_settings/_signin.html.haml
+++ b/app/views/admin/application_settings/_signin.html.haml
@@ -1,4 +1,4 @@
-= form_for @application_setting, url: general_admin_application_settings_path(anchor: 'js-signin-settings'), html: { class: 'fieldset-form' } do |f|
+= form_for @application_setting, url: admin_application_settings_path(anchor: 'js-signin-settings'), html: { class: 'fieldset-form' } do |f|
= form_errors(@application_setting)
%fieldset
diff --git a/app/views/admin/application_settings/_signup.html.haml b/app/views/admin/application_settings/_signup.html.haml
index 7c1df78f30c..a0a58b811ee 100644
--- a/app/views/admin/application_settings/_signup.html.haml
+++ b/app/views/admin/application_settings/_signup.html.haml
@@ -1,4 +1,4 @@
-= form_for @application_setting, url: general_admin_application_settings_path(anchor: 'js-signup-settings'), html: { class: 'fieldset-form' } do |f|
+= form_for @application_setting, url: admin_application_settings_path(anchor: 'js-signup-settings'), html: { class: 'fieldset-form' } do |f|
= form_errors(@application_setting)
%fieldset
diff --git a/app/views/admin/application_settings/_terminal.html.haml b/app/views/admin/application_settings/_terminal.html.haml
index 654aed54a15..49980e1e1a7 100644
--- a/app/views/admin/application_settings/_terminal.html.haml
+++ b/app/views/admin/application_settings/_terminal.html.haml
@@ -1,4 +1,4 @@
-= form_for @application_setting, url: general_admin_application_settings_path(anchor: 'js-terminal-settings'), html: { class: 'fieldset-form' } do |f|
+= form_for @application_setting, url: admin_application_settings_path(anchor: 'js-terminal-settings'), html: { class: 'fieldset-form' } do |f|
= form_errors(@application_setting)
%fieldset
diff --git a/app/views/admin/application_settings/_terms.html.haml b/app/views/admin/application_settings/_terms.html.haml
index 19e7ab7c99a..ef58e9b1128 100644
--- a/app/views/admin/application_settings/_terms.html.haml
+++ b/app/views/admin/application_settings/_terms.html.haml
@@ -1,4 +1,4 @@
-= form_for @application_setting, url: general_admin_application_settings_path(anchor: 'js-terms-settings'), html: { class: 'fieldset-form' } do |f|
+= form_for @application_setting, url: admin_application_settings_path(anchor: 'js-terms-settings'), html: { class: 'fieldset-form' } do |f|
= form_errors(@application_setting)
%fieldset
diff --git a/app/views/admin/application_settings/_visibility_and_access.html.haml b/app/views/admin/application_settings/_visibility_and_access.html.haml
index e57ef1ea18f..c07bafbe302 100644
--- a/app/views/admin/application_settings/_visibility_and_access.html.haml
+++ b/app/views/admin/application_settings/_visibility_and_access.html.haml
@@ -1,4 +1,4 @@
-= form_for @application_setting, url: general_admin_application_settings_path(anchor: 'js-visibility-settings'), html: { class: 'fieldset-form' } do |f|
+= form_for @application_setting, url: admin_application_settings_path(anchor: 'js-visibility-settings'), html: { class: 'fieldset-form' } do |f|
= form_errors(@application_setting)
%fieldset
diff --git a/app/views/admin/application_settings/general.html.haml b/app/views/admin/application_settings/show.html.haml
index b9f49fdc9de..31f18ba0d56 100644
--- a/app/views/admin/application_settings/general.html.haml
+++ b/app/views/admin/application_settings/show.html.haml
@@ -1,5 +1,5 @@
-- breadcrumb_title _("General")
-- page_title _("General")
+- breadcrumb_title _("Settings")
+- page_title _("Settings")
- @content_class = "limit-container-width" unless fluid_layout
%section.settings.as-visibility-access.no-animate#js-visibility-settings{ class: ('expanded' if expanded_by_default?) }
@@ -90,7 +90,7 @@
%p
= _('Manage Web IDE features')
.settings-content
- = form_for @application_setting, url: general_admin_application_settings_path(anchor: "#js-web-ide-settings"), html: { class: 'fieldset-form' } do |f|
+ = form_for @application_setting, url: admin_application_settings_path(anchor: "#js-web-ide-settings"), html: { class: 'fieldset-form' } do |f|
= form_errors(@application_setting)
%fieldset
diff --git a/app/views/layouts/nav/sidebar/_admin.html.haml b/app/views/layouts/nav/sidebar/_admin.html.haml
index 784fe556123..f76268bc29b 100644
--- a/app/views/layouts/nav/sidebar/_admin.html.haml
+++ b/app/views/layouts/nav/sidebar/_admin.html.haml
@@ -232,7 +232,7 @@
= _('Settings')
%li.divider.fly-out-top-item
= nav_link(path: 'application_settings#show') do
- = link_to general_admin_application_settings_path, title: _('General'), class: 'qa-admin-settings-general-item' do
+ = link_to admin_application_settings_path, title: _('General'), class: 'qa-admin-settings-general-item' do
%span
= _('General')
= nav_link(path: 'application_settings#integrations') do
diff --git a/app/views/projects/mirrors/_mirror_repos.html.haml b/app/views/projects/mirrors/_mirror_repos.html.haml
index 104c68919f0..84f0900d9c1 100644
--- a/app/views/projects/mirrors/_mirror_repos.html.haml
+++ b/app/views/projects/mirrors/_mirror_repos.html.haml
@@ -49,12 +49,12 @@
= render_if_exists 'projects/mirrors/table_pull_row'
- @project.remote_mirrors.each_with_index do |mirror, index|
- next if mirror.new_record?
- %tr.rspec-mirrored-repository-row{ class: ('bg-secondary' if mirror.disabled?), data: { qa_selector: 'mirrored_repository_row' } }
- %td{ data: { qa_selector: 'mirror_repository_url_cell' } }= mirror.safe_url || _('Invalid URL')
+ %tr.qa-mirrored-repository-row.rspec-mirrored-repository-row{ class: ('bg-secondary' if mirror.disabled?) }
+ %td.qa-mirror-repository-url= mirror.safe_url || _('Invalid URL')
%td= _('Push')
%td
= mirror.last_update_started_at.present? ? time_ago_with_tooltip(mirror.last_update_started_at) : _('Never')
- %td{ data: { qa_selector: 'mirror_last_update_at_cell' } }= mirror.last_update_at.present? ? time_ago_with_tooltip(mirror.last_update_at) : _('Never')
+ %td.qa-mirror-last-update-at= mirror.last_update_at.present? ? time_ago_with_tooltip(mirror.last_update_at) : _('Never')
%td
- if mirror.disabled?
= render 'projects/mirrors/disabled_mirror_badge'
diff --git a/app/views/projects/protected_branches/shared/_create_protected_branch.html.haml b/app/views/projects/protected_branches/shared/_create_protected_branch.html.haml
index bba4949277d..3644a623d2c 100644
--- a/app/views/projects/protected_branches/shared/_create_protected_branch.html.haml
+++ b/app/views/projects/protected_branches/shared/_create_protected_branch.html.haml
@@ -29,4 +29,4 @@
= yield :push_access_levels
.card-footer
- = f.submit 'Protect', class: 'btn-success btn', disabled: true, data: { qa_selector: 'protect_button' }
+ = f.submit 'Protect', class: 'btn-success btn', disabled: true
diff --git a/app/views/projects/registry/repositories/index.html.haml b/app/views/projects/registry/repositories/index.html.haml
index d0d06a0df7e..e34973f1f43 100644
--- a/app/views/projects/registry/repositories/index.html.haml
+++ b/app/views/projects/registry/repositories/index.html.haml
@@ -2,7 +2,7 @@
.row.registry-placeholder.prepend-bottom-10
.col-12
#js-vue-registry-images{ data: { endpoint: project_container_registry_index_path(@project, format: :json),
- "help_page_path" => help_page_path('user/packages/container_registry/index'),
+ "help_page_path" => help_page_path('user/project/container_registry'),
"no_containers_image" => image_path('illustrations/docker-empty-state.svg'),
"containers_error_image" => image_path('illustrations/docker-error-state.svg'),
"repository_url" => escape_once(@project.container_registry_url),
diff --git a/app/views/projects/services/_form.html.haml b/app/views/projects/services/_form.html.haml
index 959a2423e02..2f277e8147a 100644
--- a/app/views/projects/services/_form.html.haml
+++ b/app/views/projects/services/_form.html.haml
@@ -2,10 +2,8 @@
.col-lg-3
%h4.prepend-top-0
= @service.title
- - [true, false].each do |value|
- - hide_class = 'd-none' if @service.activated? != value
- %span.js-service-active-status{ class: hide_class, data: { value: value.to_s } }
- = boolean_to_icon value
+ = boolean_to_icon @service.activated?
+
%p= #{@service.description}.
- if @service.respond_to?(:detailed_description)
diff --git a/app/views/shared/projects/_project.html.haml b/app/views/shared/projects/_project.html.haml
index bcce7cb52fb..573ed36d7f4 100644
--- a/app/views/shared/projects/_project.html.haml
+++ b/app/views/shared/projects/_project.html.haml
@@ -60,11 +60,6 @@
.controls.d-flex.flex-sm-column.align-items-center.align-items-sm-end.flex-wrap.flex-shrink-0.text-secondary{ class: css_controls_class }
.icon-container.d-flex.align-items-center
- - if pipeline_status && can?(current_user, :read_cross_project) && project.pipeline_status.has_status? && can?(current_user, :read_build, project)
- - pipeline_path = pipelines_project_commit_path(project.pipeline_status.project, project.pipeline_status.sha, ref: project.pipeline_status.ref)
- %span.icon-wrapper.pipeline-status
- = render 'ci/status/icon', status: project.commit.last_pipeline.detailed_status(current_user), tooltip_placement: 'top', path: pipeline_path
-
- if project.archived
%span.d-flex.icon-wrapper.badge.badge-warning archived
- if stars
@@ -91,6 +86,10 @@
title: _('Issues'), data: { container: 'body', placement: 'top' } do
= sprite_icon('issues', size: 14, css_class: 'append-right-4')
= number_with_delimiter(project.open_issues_count)
+ - if pipeline_status && can?(current_user, :read_cross_project) && project.pipeline_status.has_status? && can?(current_user, :read_build, project)
+ - pipeline_path = pipelines_project_commit_path(project.pipeline_status.project, project.pipeline_status.sha, ref: project.pipeline_status.ref)
+ %span.icon-wrapper.pipeline-status
+ = render 'ci/status/icon', status: project.commit.last_pipeline.detailed_status(current_user), tooltip_placement: 'top', path: pipeline_path
.updated-note
%span
= _('Updated')
diff --git a/app/views/shared/snippets/_form.html.haml b/app/views/shared/snippets/_form.html.haml
index 73401029da4..2d2382e469a 100644
--- a/app/views/shared/snippets/_form.html.haml
+++ b/app/views/shared/snippets/_form.html.haml
@@ -22,7 +22,7 @@
= f.label :file_name, "File"
.col-sm-10
.file-holder.snippet
- .js-file-title.file-title-flex-parent
+ .js-file-title.file-title
= f.text_field :file_name, placeholder: "Optionally name this file to add code highlighting, e.g. example.rb for Ruby.", class: 'form-control snippet-file-name qa-snippet-file-name'
.file-content.code
%pre#editor= @snippet.content
diff --git a/app/views/shared/snippets/_header.html.haml b/app/views/shared/snippets/_header.html.haml
index 69481293f90..1a9ae68f53d 100644
--- a/app/views/shared/snippets/_header.html.haml
+++ b/app/views/shared/snippets/_header.html.haml
@@ -28,7 +28,7 @@
= @snippet.description
- if @snippet.updated_at != @snippet.created_at
- = edited_time_ago_with_tooltip(@snippet, placement: 'bottom', exclude_author: true)
+ = edited_time_ago_with_tooltip(@snippet, placement: 'bottom', html_class: 'snippet-edited-ago', exclude_author: true)
- if @snippet.embeddable?
.embed-snippet
diff --git a/bin/changelog b/bin/changelog
index 45b6295e331..ec068d06507 100755
--- a/bin/changelog
+++ b/bin/changelog
@@ -15,8 +15,7 @@ Options = Struct.new(
:force,
:merge_request,
:title,
- :type,
- :ee
+ :type
)
INVALID_TYPE = -1
@@ -86,10 +85,6 @@ class ChangelogOptionParser
options.type = parse_type(value)
end
- opts.on('-e', '--ee', 'Generate a changelog entry for GitLab EE') do |value|
- options.ee = value
- end
-
opts.on('-h', '--help', 'Print help message') do
$stdout.puts opts
raise Done.new
@@ -254,7 +249,7 @@ class ChangelogEntry
end
def ee?
- options.ee
+ @ee ||= File.exist?(File.expand_path('../CHANGELOG-EE.md', __dir__))
end
def branch_name
diff --git a/bin/elastic_repo_indexer b/bin/elastic_repo_indexer
new file mode 100755
index 00000000000..3dfe0c4164b
--- /dev/null
+++ b/bin/elastic_repo_indexer
@@ -0,0 +1,101 @@
+#!/usr/bin/env ruby
+
+require 'rubygems'
+require 'bundler/setup'
+require 'json'
+require 'active_model'
+require 'active_support'
+require 'active_support/core_ext'
+require 'benchmark'
+require 'charlock_holmes'
+
+$: << File.expand_path('../lib', __dir__)
+$: << File.expand_path('../ee/lib', __dir__)
+
+require 'open3'
+require 'rugged'
+
+require 'gitlab/blob_helper'
+require 'gitlab/elastic/client'
+require 'elasticsearch/model'
+require 'elasticsearch/git'
+require 'elasticsearch/git/encoder_helper'
+require 'elasticsearch/git/lite_blob'
+require 'elasticsearch/git/model'
+require 'elasticsearch/git/repository'
+
+Thread.abort_on_exception = true
+
+path_to_log_file = File.expand_path('../log/es-indexer.log', __dir__)
+LOGGER = Logger.new(path_to_log_file)
+
+PROJECT_ID = ARGV.shift
+REPO_PATH = ARGV.shift
+FROM_SHA = ENV['FROM_SHA']
+TO_SHA = ENV['TO_SHA']
+RAILS_ENV = ENV['RAILS_ENV']
+
+# Symbols get stringified when passed through JSON
+elastic = {}
+JSON.parse(ENV['ELASTIC_CONNECTION_INFO']).each { |k, v| elastic[k.to_sym] = v }
+ELASTIC_CONFIG = elastic
+
+LOGGER.info("Has been scheduled for project #{REPO_PATH} with SHA range #{FROM_SHA}:#{TO_SHA}")
+
+class Repository
+ include Elasticsearch::Git::Repository
+
+ index_name ['gitlab', RAILS_ENV].compact.join('-')
+
+ def initialize
+ self.__elasticsearch__.client = ::Gitlab::Elastic::Client.build(ELASTIC_CONFIG)
+ end
+
+ def client_for_indexing
+ self.__elasticsearch__.client
+ end
+
+ def repository_id
+ PROJECT_ID
+ end
+
+ def project_id
+ PROJECT_ID
+ end
+
+ def path_to_repo
+ REPO_PATH
+ end
+end
+
+repo = Repository.new
+
+params = { from_rev: FROM_SHA, to_rev: TO_SHA }.compact
+
+commit_thr = Thread.new do
+ LOGGER.info("Indexing commits started")
+
+ timings = Benchmark.measure do
+ indexed = 0
+ repo.index_commits(params) do |batch, total_count|
+ indexed += batch.length
+ LOGGER.info("Indexed #{indexed}/#{total_count} commits")
+ end
+ end
+
+ LOGGER.info("Commits for #{REPO_PATH} are indexed. Time elapsed: #{timings.real}")
+end
+
+LOGGER.info("Indexing blobs started")
+
+timings = Benchmark.measure do
+ indexed = 0
+ repo.index_blobs(params) do |batch, total_count|
+ indexed += batch.length
+ LOGGER.info("Indexed #{indexed}/#{total_count} blobs")
+ end
+end
+
+LOGGER.info("Blobs for #{REPO_PATH} are indexed. Time elapsed: #{timings.real}")
+
+commit_thr.join
diff --git a/changelogs/unreleased/29155-fix-devise-401-responses.yml b/changelogs/unreleased/29155-fix-devise-401-responses.yml
deleted file mode 100644
index 2c11727e3b1..00000000000
--- a/changelogs/unreleased/29155-fix-devise-401-responses.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Avoid Devise "401 Unauthorized" responses
-merge_request: 16519
-author:
-type: fixed
diff --git a/changelogs/unreleased/32156-fix-ci_usage_warning_message-message-builder.yml b/changelogs/unreleased/32156-fix-ci_usage_warning_message-message-builder.yml
new file mode 100644
index 00000000000..9bbadd94f5d
--- /dev/null
+++ b/changelogs/unreleased/32156-fix-ci_usage_warning_message-message-builder.yml
@@ -0,0 +1,5 @@
+---
+title: Prevent the user from seeing an invalid "Purchase more minutes" prompt.
+merge_request: 16979
+author:
+type: fixed
diff --git a/changelogs/unreleased/64213-not_filtering.yml b/changelogs/unreleased/64213-not_filtering.yml
deleted file mode 100644
index 3eedafa5a4c..00000000000
--- a/changelogs/unreleased/64213-not_filtering.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Add not param to Issues API endpoint
-merge_request: 16748
-author:
-type: added
diff --git a/changelogs/unreleased/65192-enable-modsecurity-in-ingress.yml b/changelogs/unreleased/65192-enable-modsecurity-in-ingress.yml
new file mode 100644
index 00000000000..56c1ba64c27
--- /dev/null
+++ b/changelogs/unreleased/65192-enable-modsecurity-in-ingress.yml
@@ -0,0 +1,5 @@
+---
+title: Enable modsecurity in nginx-ingress apps
+merge_request: 15774
+author:
+type: added
diff --git a/changelogs/unreleased/66986-milestone-release-many-to-many.yml b/changelogs/unreleased/66986-milestone-release-many-to-many.yml
deleted file mode 100644
index e814cb2cb59..00000000000
--- a/changelogs/unreleased/66986-milestone-release-many-to-many.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Switch Milestone and Release to a many-to-many relationship
-merge_request: 16517
-author:
-type: changed
diff --git a/changelogs/unreleased/backport-schedule-productivity-analytics-backfill.yml b/changelogs/unreleased/backport-schedule-productivity-analytics-backfill.yml
new file mode 100644
index 00000000000..eb80a9ae4c7
--- /dev/null
+++ b/changelogs/unreleased/backport-schedule-productivity-analytics-backfill.yml
@@ -0,0 +1,5 @@
+---
+title: Schedule productivity analytics recalculation for EE
+merge_request: 15137
+author:
+type: other
diff --git a/changelogs/unreleased/docs-document-auto-devops-docker-build-secret-forwarding.yml b/changelogs/unreleased/docs-document-auto-devops-docker-build-secret-forwarding.yml
deleted file mode 100644
index 6b7146d7acb..00000000000
--- a/changelogs/unreleased/docs-document-auto-devops-docker-build-secret-forwarding.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Document forwarding CI variables to docker build in Auto DevOps
-merge_request: 16783
-author:
-type: added
diff --git a/changelogs/unreleased/enabling_runners_token_for_groups.yml b/changelogs/unreleased/enabling_runners_token_for_groups.yml
deleted file mode 100644
index 9e55aca82de..00000000000
--- a/changelogs/unreleased/enabling_runners_token_for_groups.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Adds the runners_token of the group if the user that requests the group info is admin of it
-merge_request: 16831
-author: Ignacio Lorenzo Subirá Otal nachootal@gmail.com
-type: changed
diff --git a/changelogs/unreleased/language-trends-over-time.yml b/changelogs/unreleased/language-trends-over-time.yml
deleted file mode 100644
index f7a5cb12fa1..00000000000
--- a/changelogs/unreleased/language-trends-over-time.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Database table for tracking programming language trends over time
-merge_request: 16491
-author:
-type: added
diff --git a/changelogs/unreleased/ms-implement-build-specific-timeout.yml b/changelogs/unreleased/ms-implement-build-specific-timeout.yml
deleted file mode 100644
index bc66b0b2fba..00000000000
--- a/changelogs/unreleased/ms-implement-build-specific-timeout.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Allow specifying timeout per-job in .gitlab-ci.yml
-merge_request: 16777
-author: Michał Siwek
-type: added
diff --git a/changelogs/unreleased/osw-improve-discussions-query.yml b/changelogs/unreleased/osw-improve-discussions-query.yml
deleted file mode 100644
index a5cd6c1ea32..00000000000
--- a/changelogs/unreleased/osw-improve-discussions-query.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Considerably improve the query performance for MR discussions load
-merge_request: 16635
-author:
-type: performance
diff --git a/changelogs/unreleased/remove-vue-resource-from-performance-bar-service.yml b/changelogs/unreleased/remove-vue-resource-from-performance-bar-service.yml
deleted file mode 100644
index fcf2a0b316f..00000000000
--- a/changelogs/unreleased/remove-vue-resource-from-performance-bar-service.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Remove vue-resource from PerformanceBarService
-merge_request: 32428
-author: Lee Tickett
-type: other
diff --git a/config/gitlab.yml.example b/config/gitlab.yml.example
index 814ea551e19..92674aafa90 100644
--- a/config/gitlab.yml.example
+++ b/config/gitlab.yml.example
@@ -982,10 +982,6 @@ production: &base
# Default is '.gitlab_workhorse_secret' relative to Rails.root (i.e. root of the GitLab app).
# secret_file: /home/git/gitlab/.gitlab_workhorse_secret
- ## GitLab Elasticsearch settings
- elasticsearch:
- indexer_path: /home/git/gitlab-elasticsearch-indexer/
-
## Git settings
# CAUTION!
# Use the default values unless you really know what you are doing
diff --git a/config/initializers/7_prometheus_metrics.rb b/config/initializers/7_prometheus_metrics.rb
index 6bd2256ac0e..143b34b5368 100644
--- a/config/initializers/7_prometheus_metrics.rb
+++ b/config/initializers/7_prometheus_metrics.rb
@@ -47,12 +47,10 @@ if !Rails.env.test? && Gitlab::Metrics.prometheus_metrics_enabled?
end
Gitlab::Cluster::LifecycleEvents.on_master_start do
- ::Prometheus::Client.reinitialize_on_pid_change(force: true)
-
if defined?(::Unicorn)
- Gitlab::Metrics::Samplers::UnicornSampler.instance(Settings.monitoring.unicorn_sampler_interval).start
+ Gitlab::Metrics::Samplers::UnicornSampler.initialize_instance(Settings.monitoring.unicorn_sampler_interval).start
elsif defined?(::Puma)
- Gitlab::Metrics::Samplers::PumaSampler.instance(Settings.monitoring.puma_sampler_interval).start
+ Gitlab::Metrics::Samplers::PumaSampler.initialize_instance(Settings.monitoring.puma_sampler_interval).start
end
end
end
diff --git a/config/initializers/8_devise.rb b/config/initializers/8_devise.rb
index 8d4c5fa382c..8ef9ff6b7fc 100644
--- a/config/initializers/8_devise.rb
+++ b/config/initializers/8_devise.rb
@@ -214,9 +214,11 @@ Devise.setup do |config|
# If you want to use other strategies, that are not supported by Devise, or
# change the failure app, you can configure them inside the config.warden block.
#
- config.warden do |manager|
- manager.failure_app = Gitlab::DeviseFailure
- end
+ # config.warden do |manager|
+ # manager.failure_app = Gitlab::DeviseFailure
+ # manager.intercept_401 = false
+ # manager.default_strategies(scope: :user).unshift :some_external_strategy
+ # end
if Gitlab::Auth::LDAP::Config.enabled?
Gitlab::Auth::LDAP::Config.providers.each do |provider|
diff --git a/config/routes/admin.rb b/config/routes/admin.rb
index a003ffca270..6f9a5552564 100644
--- a/config/routes/admin.rb
+++ b/config/routes/admin.rb
@@ -110,7 +110,7 @@ namespace :admin do
put :reset_registration_token
put :reset_health_check_token
put :clear_repository_check_states
- match :general, :integrations, :repository, :templates, :ci_cd, :reporting, :metrics_and_profiling, :network, :geo, :preferences, via: [:get, :patch]
+ match :integrations, :repository, :templates, :ci_cd, :reporting, :metrics_and_profiling, :network, :geo, :preferences, via: [:get, :patch]
get :lets_encrypt_terms_of_service
end
diff --git a/danger/changelog/Dangerfile b/danger/changelog/Dangerfile
index f83dc556964..2d1ca64a9e8 100644
--- a/danger/changelog/Dangerfile
+++ b/danger/changelog/Dangerfile
@@ -12,12 +12,6 @@ You can create one with:
bin/changelog -m %<mr_iid>s "%<mr_title>s"
```
-If you want to create a changelog entry for GitLab EE, run the following instead:
-
-```
-bin/changelog --ee -m %<mr_iid>s "%<mr_title>s"
-```
-
Note: Merge requests with %<labels>s do not trigger this check.
MSG
diff --git a/danger/commit_messages/Dangerfile b/danger/commit_messages/Dangerfile
index 064b8c94805..d371ade4887 100644
--- a/danger/commit_messages/Dangerfile
+++ b/danger/commit_messages/Dangerfile
@@ -37,10 +37,6 @@ class EmojiChecker
end
end
-def gitlab_danger
- @gitlab_danger ||= GitlabDanger.new(helper.gitlab_helper)
-end
-
def fail_commit(commit, message)
fail("#{commit.sha}: #{message}")
end
@@ -60,8 +56,6 @@ def subject_starts_with_capital?(subject)
end
def ce_upstream?
- return unless gitlab_danger.ci?
-
gitlab.mr_labels.any? { |label| label == 'CE upstream' }
end
@@ -94,8 +88,8 @@ def lint_commit(commit) # rubocop:disable Metrics/AbcSize
# We ignore revert commits as they are well structured by Git already
return false if commit.message.start_with?('Revert "')
- is_squash = gitlab_danger.ci? ? gitlab.mr_json['squash'] : false
- is_wip = gitlab_danger.ci? ? gitlab.mr_json['work_in_progress'] : false
+ is_squash = gitlab.mr_json['squash']
+ is_wip = gitlab.mr_json['work_in_progress']
is_fixup = commit.message.start_with?('fixup!', 'squash!')
if is_fixup
diff --git a/danger/only_documentation/Dangerfile b/danger/only_documentation/Dangerfile
new file mode 100644
index 00000000000..ce7ede26d9a
--- /dev/null
+++ b/danger/only_documentation/Dangerfile
@@ -0,0 +1,24 @@
+# rubocop:disable Style/SignalException
+# frozen_string_literal: true
+
+has_only_docs_changes = helper.all_changed_files.all? { |file| file.start_with?('doc/', '.gitlab/ci/docs.gitlab-ci.yml', '.markdownlint.json') || file.end_with?('.md') }
+is_docs_only_branch = gitlab.branch_for_head =~ /(^docs[\/-].*|.*-docs$)/
+
+if is_docs_only_branch && !has_only_docs_changes
+ fail "It seems like your branch name has a `docs` prefix or suffix. "\
+ "The CI won't run the full pipeline, but you also have changed non-docs files. "\
+ "Please recreate this MR with a new branch name."
+end
+
+if has_only_docs_changes && !is_docs_only_branch
+ markdown(<<~MARKDOWN)
+
+ ## Documentation only changes
+
+ Hey! Seems your merge request contains only docs changes.
+ Tired of waiting 2 hours for the pipeline to finish?
+ Next time, prepend `docs-` to [your branch name](https://docs.gitlab.com/ee/development/documentation/#branch-naming)
+ and the pipeline will finish before you say GitLab (x300)!
+
+ MARKDOWN
+end
diff --git a/db/migrate/20190801193427_rename_application_settings_snowplow_collector_uri_column.rb b/db/migrate/20190801193427_rename_application_settings_snowplow_collector_uri_column.rb
index a4bd5841a46..fba9849d3eb 100644
--- a/db/migrate/20190801193427_rename_application_settings_snowplow_collector_uri_column.rb
+++ b/db/migrate/20190801193427_rename_application_settings_snowplow_collector_uri_column.rb
@@ -12,6 +12,6 @@ class RenameApplicationSettingsSnowplowCollectorUriColumn < ActiveRecord::Migrat
end
def down
- cleanup_concurrent_column_rename :application_settings, :snowplow_collector_hostname, :snowplow_collector_uri
+ undo_rename_column_concurrently :application_settings, :snowplow_collector_uri, :snowplow_collector_hostname
end
end
diff --git a/db/migrate/20190828170945_create_package_metadatum.rb b/db/migrate/20190828170945_create_package_metadatum.rb
deleted file mode 100644
index 3047b812e0e..00000000000
--- a/db/migrate/20190828170945_create_package_metadatum.rb
+++ /dev/null
@@ -1,14 +0,0 @@
-# frozen_string_literal: true
-
-class CreatePackageMetadatum < ActiveRecord::Migration[5.2]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def change
- create_table :packages_package_metadata do |t|
- t.references :package, index: { unique: true }, null: false, foreign_key: { to_table: :packages_packages, on_delete: :cascade }, type: :integer
- t.binary :metadata, null: false
- end
- end
-end
diff --git a/db/migrate/20190828172831_create_package_tag.rb b/db/migrate/20190828172831_create_package_tag.rb
deleted file mode 100644
index baf0a5cf11b..00000000000
--- a/db/migrate/20190828172831_create_package_tag.rb
+++ /dev/null
@@ -1,14 +0,0 @@
-# frozen_string_literal: true .
-
-class CreatePackageTag < ActiveRecord::Migration[5.2]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- def change
- create_table :packages_package_tags do |t|
- t.references :package, index: true, null: false, foreign_key: { to_table: :packages_packages, on_delete: :cascade }, type: :integer
- t.string :name, limit: 255, null: false
- end
- end
-end
diff --git a/db/migrate/20190910125852_create_analytics_language_trend_repository_languages.rb b/db/migrate/20190910125852_create_analytics_language_trend_repository_languages.rb
deleted file mode 100644
index 07da4c20d55..00000000000
--- a/db/migrate/20190910125852_create_analytics_language_trend_repository_languages.rb
+++ /dev/null
@@ -1,35 +0,0 @@
-# frozen_string_literal: true
-
-class CreateAnalyticsLanguageTrendRepositoryLanguages < ActiveRecord::Migration[5.2]
- DOWNTIME = false
- INDEX_PREFIX = 'analytics_repository_languages_'
-
- def change
- create_table :analytics_language_trend_repository_languages, id: false do |t|
- t.integer :file_count, null: false, default: 0
- t.references :programming_language, {
- null: false,
- foreign_key: { on_delete: :cascade },
- index: false
- }
- t.references :project, {
- null: false,
- foreign_key: { on_delete: :cascade },
- index: { name: INDEX_PREFIX + 'on_project_id' }
- }
- t.integer :loc, null: false, default: 0
- t.integer :bytes, null: false, default: 0
- # Storing percentage (with 2 decimal places), on 2 bytes.
- # 50.25% => 5025
- # Max: 100.00% => 10000 (fits smallint: 32767)
- t.integer :percentage, limit: 2, null: false, default: 0
- t.date :snapshot_date, null: false
- end
-
- add_index :analytics_language_trend_repository_languages, %I[
- programming_language_id
- project_id
- snapshot_date
- ], name: INDEX_PREFIX + 'unique_index', unique: true
- end
-end
diff --git a/db/migrate/20190910212256_add_any_approver_rule_unique_indexes.rb b/db/migrate/20190910212256_add_any_approver_rule_unique_indexes.rb
deleted file mode 100644
index e8f5b853d1d..00000000000
--- a/db/migrate/20190910212256_add_any_approver_rule_unique_indexes.rb
+++ /dev/null
@@ -1,30 +0,0 @@
-# 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 AddAnyApproverRuleUniqueIndexes < ActiveRecord::Migration[5.2]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
-
- PROJECT_RULE_UNIQUE_INDEX = 'any_approver_project_rule_type_unique_index'
- MERGE_REQUEST_RULE_UNIQUE_INDEX = 'any_approver_merge_request_rule_type_unique_index'
-
- disable_ddl_transaction!
-
- def up
- add_concurrent_index(:approval_project_rules, [:project_id],
- where: "rule_type = 3",
- name: PROJECT_RULE_UNIQUE_INDEX, unique: true)
-
- add_concurrent_index(:approval_merge_request_rules, [:merge_request_id, :rule_type],
- where: "rule_type = 4",
- name: MERGE_REQUEST_RULE_UNIQUE_INDEX, unique: true)
- end
-
- def down
- remove_concurrent_index_by_name(:approval_project_rules, PROJECT_RULE_UNIQUE_INDEX)
- remove_concurrent_index_by_name(:approval_merge_request_rules, MERGE_REQUEST_RULE_UNIQUE_INDEX)
- end
-end
diff --git a/db/post_migrate/20190724091326_schedule_productivity_analytics_backfill.rb b/db/post_migrate/20190724091326_schedule_productivity_analytics_backfill.rb
new file mode 100644
index 00000000000..3e1c77ae992
--- /dev/null
+++ b/db/post_migrate/20190724091326_schedule_productivity_analytics_backfill.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+
+class ScheduleProductivityAnalyticsBackfill < ActiveRecord::Migration[5.2]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ BATCH_SIZE = 10_000
+ INTERVAL = 3.minutes
+ MIGRATION = 'Gitlab::BackgroundMigration::RecalculateProductivityAnalytics'.freeze
+
+ disable_ddl_transaction!
+
+ def up
+ return unless Gitlab.ee?
+
+ metrics_model = Class.new(ActiveRecord::Base) do
+ self.table_name = 'merge_request_metrics'
+
+ include ::EachBatch
+ end
+
+ scope = metrics_model.where("merged_at >= ?", 3.months.ago)
+
+ queue_background_migration_jobs_by_range_at_intervals(scope, MIGRATION, INTERVAL, batch_size: BATCH_SIZE)
+ end
+
+ def down
+ # no-op
+ end
+end
diff --git a/db/post_migrate/20190802091750_cleanup_application_settings_snowplow_collector_uri_rename.rb b/db/post_migrate/20190802091750_cleanup_application_settings_snowplow_collector_uri_rename.rb
index 768ece925c6..77472585512 100644
--- a/db/post_migrate/20190802091750_cleanup_application_settings_snowplow_collector_uri_rename.rb
+++ b/db/post_migrate/20190802091750_cleanup_application_settings_snowplow_collector_uri_rename.rb
@@ -12,6 +12,6 @@ class CleanupApplicationSettingsSnowplowCollectorUriRename < ActiveRecord::Migra
end
def down
- rename_column_concurrently :application_settings, :snowplow_collector_hostname, :snowplow_collector_uri
+ undo_cleanup_concurrent_column_rename :application_settings, :snowplow_collector_uri, :snowplow_collector_hostname
end
end
diff --git a/db/post_migrate/20190827102026_migrate_code_owner_approval_status_to_protected_branches_in_batches.rb b/db/post_migrate/20190827102026_migrate_code_owner_approval_status_to_protected_branches_in_batches.rb
deleted file mode 100644
index b109f582909..00000000000
--- a/db/post_migrate/20190827102026_migrate_code_owner_approval_status_to_protected_branches_in_batches.rb
+++ /dev/null
@@ -1,46 +0,0 @@
-# frozen_string_literal: true
-
-class MigrateCodeOwnerApprovalStatusToProtectedBranchesInBatches < ActiveRecord::Migration[5.2]
- include Gitlab::Database::MigrationHelpers
-
- disable_ddl_transaction!
-
- DOWNTIME = false
- BATCH_SIZE = 200
-
- class Project < ActiveRecord::Base
- include EachBatch
-
- self.table_name = 'projects'
- self.inheritance_column = :_type_disabled
-
- has_many :protected_branches
- end
-
- class ProtectedBranch < ActiveRecord::Base
- include EachBatch
-
- self.table_name = 'protected_branches'
- self.inheritance_column = :_type_disabled
-
- belongs_to :project
- end
-
- def up
- add_concurrent_index :projects, :id, name: "temp_active_projects_with_prot_branches", where: 'archived = false and pending_delete = false and merge_requests_require_code_owner_approval = true'
-
- ProtectedBranch
- .joins(:project)
- .where(projects: { archived: false, pending_delete: false, merge_requests_require_code_owner_approval: true })
- .each_batch(of: BATCH_SIZE) do |batch|
- batch.update_all(code_owner_approval_required: true)
- end
-
- remove_concurrent_index_by_name(:projects, "temp_active_projects_with_prot_branches")
- end
-
- def down
- # noop
- #
- end
-end
diff --git a/db/post_migrate/20190904205212_remove_id_column_from_intermediate_release_milestones.rb b/db/post_migrate/20190904205212_remove_id_column_from_intermediate_release_milestones.rb
deleted file mode 100644
index e4b65d26db6..00000000000
--- a/db/post_migrate/20190904205212_remove_id_column_from_intermediate_release_milestones.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: true
-
-class RemoveIdColumnFromIntermediateReleaseMilestones < ActiveRecord::Migration[5.2]
- DOWNTIME = false
-
- def change
- remove_column :milestone_releases, :id, :bigint
- end
-end
diff --git a/db/post_migrate/20190905091812_schedule_project_any_approval_rule_migration.rb b/db/post_migrate/20190905091812_schedule_project_any_approval_rule_migration.rb
deleted file mode 100644
index ef1cb452c26..00000000000
--- a/db/post_migrate/20190905091812_schedule_project_any_approval_rule_migration.rb
+++ /dev/null
@@ -1,47 +0,0 @@
-# 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 ScheduleProjectAnyApprovalRuleMigration < ActiveRecord::Migration[5.2]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- BATCH_SIZE = 5_000
- MIGRATION = 'PopulateAnyApprovalRuleForProjects'
- DELAY_INTERVAL = 8.minutes.to_i
-
- disable_ddl_transaction!
-
- class Project < ActiveRecord::Base
- include EachBatch
-
- self.table_name = 'projects'
-
- scope :with_approvals_before_merge, -> { where('approvals_before_merge <> 0') }
- end
-
- def up
- add_concurrent_index :projects, :id,
- name: 'tmp_projects_with_approvals_before_merge',
- where: 'approvals_before_merge <> 0'
-
- say "Scheduling `#{MIGRATION}` jobs"
-
- # We currently have ~43k project records with non-zero approvals_before_merge on GitLab.com.
- # This means it'll schedule ~9 jobs (5k projects each) with a 8 minutes gap,
- # so this should take ~1 hour for all background migrations to complete.
- #
- # The approximate expected number of affected rows is: 18k
-
- queue_background_migration_jobs_by_range_at_intervals(
- ScheduleProjectAnyApprovalRuleMigration::Project.with_approvals_before_merge,
- MIGRATION, DELAY_INTERVAL, batch_size: BATCH_SIZE)
-
- remove_concurrent_index_by_name(:projects, 'tmp_projects_with_approvals_before_merge')
- end
-
- def down
- # no-op
- end
-end
diff --git a/db/post_migrate/20190905091831_schedule_merge_request_any_approval_rule_migration.rb b/db/post_migrate/20190905091831_schedule_merge_request_any_approval_rule_migration.rb
deleted file mode 100644
index 4a8398a9eea..00000000000
--- a/db/post_migrate/20190905091831_schedule_merge_request_any_approval_rule_migration.rb
+++ /dev/null
@@ -1,47 +0,0 @@
-# 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 ScheduleMergeRequestAnyApprovalRuleMigration < ActiveRecord::Migration[5.2]
- include Gitlab::Database::MigrationHelpers
-
- DOWNTIME = false
- BATCH_SIZE = 5_000
- MIGRATION = 'PopulateAnyApprovalRuleForMergeRequests'
- DELAY_INTERVAL = 8.minutes.to_i
-
- disable_ddl_transaction!
-
- class MergeRequest < ActiveRecord::Base
- include EachBatch
-
- self.table_name = 'merge_requests'
-
- scope :with_approvals_before_merge, -> { where('approvals_before_merge <> 0') }
- end
-
- def up
- add_concurrent_index :merge_requests, :id,
- name: 'tmp_merge_requests_with_approvals_before_merge',
- where: 'approvals_before_merge <> 0'
-
- say "Scheduling `#{MIGRATION}` jobs"
-
- # We currently have ~440_000 merge request records with non-zero approvals_before_merge on GitLab.com.
- # This means it'll schedule ~88 jobs (5k merge requests each) with a 8 minutes gap,
- # so this should take ~12 hours for all background migrations to complete.
- #
- # The approximate expected number of affected rows is: 190k
-
- queue_background_migration_jobs_by_range_at_intervals(
- ScheduleMergeRequestAnyApprovalRuleMigration::MergeRequest.with_approvals_before_merge,
- MIGRATION, DELAY_INTERVAL, batch_size: BATCH_SIZE)
-
- remove_concurrent_index_by_name(:merge_requests, 'tmp_merge_requests_with_approvals_before_merge')
- end
-
- def down
- # no-op
- end
-end
diff --git a/db/schema.rb b/db/schema.rb
index b821951180a..9ee4026c641 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -81,18 +81,6 @@ ActiveRecord::Schema.define(version: 2019_09_14_223900) do
t.index ["start_event_label_id"], name: "index_analytics_ca_project_stages_on_start_event_label_id"
end
- create_table "analytics_language_trend_repository_languages", id: false, force: :cascade do |t|
- t.integer "file_count", default: 0, null: false
- t.bigint "programming_language_id", null: false
- t.bigint "project_id", null: false
- t.integer "loc", default: 0, null: false
- t.integer "bytes", default: 0, null: false
- t.integer "percentage", limit: 2, default: 0, null: false
- t.date "snapshot_date", null: false
- t.index ["programming_language_id", "project_id", "snapshot_date"], name: "analytics_repository_languages_unique_index", unique: true
- t.index ["project_id"], name: "analytics_repository_languages_on_project_id"
- end
-
create_table "appearances", id: :serial, force: :cascade do |t|
t.string "title", null: false
t.text "description", null: false
@@ -331,9 +319,8 @@ ActiveRecord::Schema.define(version: 2019_09_14_223900) do
t.integer "report_type", limit: 2
t.index ["merge_request_id", "code_owner", "name"], name: "approval_rule_name_index_for_code_owners", unique: true, where: "(code_owner = true)"
t.index ["merge_request_id", "code_owner"], name: "index_approval_merge_request_rules_1"
- t.index ["merge_request_id", "name"], name: "index_approval_rule_name_for_code_owners_rule_type", unique: true, where: "(rule_type = 2)"
- t.index ["merge_request_id", "rule_type"], name: "any_approver_merge_request_rule_type_unique_index", unique: true, where: "(rule_type = 4)"
- t.index ["merge_request_id"], name: "index_approval_rules_code_owners_rule_type", where: "(rule_type = 2)"
+ t.index ["merge_request_id", "rule_type", "name"], name: "index_approval_rule_name_for_code_owners_rule_type", unique: true, where: "(rule_type = 2)"
+ t.index ["merge_request_id", "rule_type"], name: "index_approval_rules_code_owners_rule_type", where: "(rule_type = 2)"
end
create_table "approval_merge_request_rules_approved_approvers", force: :cascade do |t|
@@ -364,7 +351,6 @@ ActiveRecord::Schema.define(version: 2019_09_14_223900) do
t.integer "approvals_required", limit: 2, default: 0, null: false
t.string "name", null: false
t.integer "rule_type", limit: 2, default: 0, null: false
- t.index ["project_id"], name: "any_approver_project_rule_type_unique_index", unique: true, where: "(rule_type = 3)"
t.index ["project_id"], name: "index_approval_project_rules_on_project_id"
t.index ["rule_type"], name: "index_approval_project_rules_on_rule_type"
end
@@ -2208,7 +2194,7 @@ ActiveRecord::Schema.define(version: 2019_09_14_223900) do
t.index ["user_id"], name: "index_merge_trains_on_user_id"
end
- create_table "milestone_releases", id: false, force: :cascade do |t|
+ create_table "milestone_releases", force: :cascade do |t|
t.bigint "milestone_id", null: false
t.bigint "release_id", null: false
t.index ["milestone_id", "release_id"], name: "index_miletone_releases_on_milestone_and_release", unique: true
@@ -2498,18 +2484,6 @@ ActiveRecord::Schema.define(version: 2019_09_14_223900) do
t.index ["package_id", "file_name"], name: "index_packages_package_files_on_package_id_and_file_name"
end
- create_table "packages_package_metadata", force: :cascade do |t|
- t.integer "package_id", null: false
- t.binary "metadata", null: false
- t.index ["package_id"], name: "index_packages_package_metadata_on_package_id", unique: true
- end
-
- create_table "packages_package_tags", force: :cascade do |t|
- t.integer "package_id", null: false
- t.string "name", limit: 255, null: false
- t.index ["package_id"], name: "index_packages_package_tags_on_package_id"
- end
-
create_table "packages_packages", force: :cascade do |t|
t.integer "project_id", null: false
t.datetime_with_timezone "created_at", null: false
@@ -3786,8 +3760,6 @@ ActiveRecord::Schema.define(version: 2019_09_14_223900) do
add_foreign_key "analytics_cycle_analytics_project_stages", "labels", column: "end_event_label_id", on_delete: :cascade
add_foreign_key "analytics_cycle_analytics_project_stages", "labels", column: "start_event_label_id", on_delete: :cascade
add_foreign_key "analytics_cycle_analytics_project_stages", "projects", on_delete: :cascade
- add_foreign_key "analytics_language_trend_repository_languages", "programming_languages", on_delete: :cascade
- add_foreign_key "analytics_language_trend_repository_languages", "projects", on_delete: :cascade
add_foreign_key "application_settings", "namespaces", column: "custom_project_templates_group_id", on_delete: :nullify
add_foreign_key "application_settings", "projects", column: "file_template_project_id", name: "fk_ec757bd087", on_delete: :nullify
add_foreign_key "application_settings", "projects", column: "instance_administration_project_id", on_delete: :nullify
@@ -4035,8 +4007,6 @@ ActiveRecord::Schema.define(version: 2019_09_14_223900) do
add_foreign_key "operations_feature_flags_clients", "projects", on_delete: :cascade
add_foreign_key "packages_maven_metadata", "packages_packages", column: "package_id", name: "fk_be88aed360", on_delete: :cascade
add_foreign_key "packages_package_files", "packages_packages", column: "package_id", name: "fk_86f0f182f8", on_delete: :cascade
- add_foreign_key "packages_package_metadata", "packages_packages", column: "package_id", on_delete: :cascade
- add_foreign_key "packages_package_tags", "packages_packages", column: "package_id", on_delete: :cascade
add_foreign_key "packages_packages", "projects", on_delete: :cascade
add_foreign_key "pages_domain_acme_orders", "pages_domains", on_delete: :cascade
add_foreign_key "pages_domains", "projects", name: "fk_ea2f6dfc6f", on_delete: :cascade
diff --git a/doc/README.md b/doc/README.md
index 6e0f037bea4..c704bedc7d6 100644
--- a/doc/README.md
+++ b/doc/README.md
@@ -36,7 +36,7 @@ Have a look at some of our most popular documentation resources:
|:----------------------------------------------------------------|:-----------------------------------------------------------------|
| [Configuring `.gitlab-ci.yml`](ci/yaml/README.md) | Complete syntax documentation for configuring your CI pipelines. |
| [GitLab CI/CD examples](ci/examples/README.md) | Get up to speed quickly with common CI/CD scenarios. |
-| [GitLab Container Registry](user/packages/container_registry/index.md) | Host Docker images within GitLab. |
+| [GitLab Container Registry](user/project/container_registry.md) | Host containers within GitLab. |
| [GitLab Pages](user/project/pages/index.md) | Host static websites for your projects with GitLab. |
| [GitLab.com settings](user/gitlab_com/index.md) | Settings for GitLab.com. |
| [Kubernetes integration](user/project/clusters/index.md) | Use GitLab with Kubernetes. |
@@ -248,18 +248,16 @@ The following documentation relates to the DevOps **Verify** stage:
### Package
-GitLab Packages allows organizations to utilize GitLab as a private repository
-for a variety of common package managers. Users are able to build and publish
-packages, which can be easily consumed as a dependency in downstream projects.
+GitLab Container Registry gives you the enhanced security and access controls of
+custom Docker images without 3rd party add-ons. Easily upload and download images
+from GitLab CI/CD with full Git repository management integration.
The following documentation relates to the DevOps **Package** stage:
| Package Topics | Description |
|:----------------------------------------------------------------|:-------------------------------------------------------|
-| [Container Registry](user/packages/container_registry/index.md) | The GitLab Container Registry enables every project in GitLab to have its own space to store [Docker](https://www.docker.com/) images. |
-| [Dependency Proxy](user/packages/dependency_proxy/index.md) **(PREMIUM)** | The GitLab Dependency Proxy sets up a local proxy for frequently used upstream images/packages. |
-| [Maven Repository](user/packages/maven_repository/index.md) **(PREMIUM)** | The GitLab Maven Repository enables every project in GitLab to have its own space to store [Maven](https://maven.apache.org/) packages. |
-| [NPM Registry](user/packages/npm_registry/index.md) **(PREMIUM)** | The GitLab NPM Registry enables every project in GitLab to have its own space to store [NPM](https://www.npmjs.com/) packages. |
+| [GitLab Container Registry](user/project/container_registry.md) | Learn how to use GitLab's built-in Container Registry. |
+| [GitLab Packages](administration/packages.md) **(PREMIUM)** | Use GitLab as an NPM registry or Maven repository. |
<div align="right">
<a type="button" class="btn btn-default" href="#overview">
diff --git a/doc/administration/auth/ldap-ee.md b/doc/administration/auth/ldap-ee.md
index d9b7d8b4382..34f3cfa353f 100644
--- a/doc/administration/auth/ldap-ee.md
+++ b/doc/administration/auth/ldap-ee.md
@@ -345,7 +345,7 @@ GitLab supports LDAP groups that use member attributes:
- `memberuid`.
This means group sync supports, at least, LDAP groups with object class:
-`groupOfNames`, `posixGroup`, and `groupOfUniqueNames`.
+`groupOfNames`, `posixGroup`, and `groupOfUniqueName`.
Other object classes should work fine as long as members
are defined as one of the mentioned attributes. This also means GitLab supports
diff --git a/doc/administration/container_registry.md b/doc/administration/container_registry.md
index 7a533aa9043..f5d58db0133 100644
--- a/doc/administration/container_registry.md
+++ b/doc/administration/container_registry.md
@@ -1,5 +1,736 @@
----
-redirect_to: 'packages/container_registry.md'
----
+# GitLab Container Registry administration
-This document was moved to [another location](packages/container_registry.md).
+> - [Introduced][ce-4040] in GitLab 8.8.
+> - Container Registry manifest `v1` support was added in GitLab 8.9 to support
+> Docker versions earlier than 1.10.
+> - This document is about the admin guide. To learn how to use GitLab Container
+> Registry [user documentation](../user/project/container_registry.md).
+
+With the Container Registry integrated into GitLab, every project can have its
+own space to store its Docker images.
+
+You can read more about the Container Registry at
+<https://docs.docker.com/registry/introduction/>.
+
+## Enable the Container Registry
+
+**Omnibus GitLab installations**
+
+All you have to do is configure the domain name under which the Container
+Registry will listen to. Read
+[#container-registry-domain-configuration](#container-registry-domain-configuration)
+and pick one of the two options that fits your case.
+
+>**Note:**
+The container registry works under HTTPS by default. Using HTTP is possible
+but not recommended and out of the scope of this document.
+Read the [insecure Registry documentation][docker-insecure] if you want to
+implement this.
+
+**Installations from source**
+
+If you have installed GitLab from source:
+
+1. You will have to [install Registry][registry-deploy] by yourself.
+1. After the installation is complete, you will have to configure the Registry's
+ settings in `gitlab.yml` in order to enable it.
+1. Use the sample NGINX configuration file that is found under
+ [`lib/support/nginx/registry-ssl`][registry-ssl] and edit it to match the
+ `host`, `port` and TLS certs paths.
+
+The contents of `gitlab.yml` are:
+
+```
+registry:
+ enabled: true
+ host: registry.gitlab.example.com
+ port: 5005
+ api_url: http://localhost:5000/
+ key: config/registry.key
+ path: shared/registry
+ issuer: gitlab-issuer
+```
+
+where:
+
+| Parameter | Description |
+| --------- | ----------- |
+| `enabled` | `true` or `false`. Enables the Registry in GitLab. By default this is `false`. |
+| `host` | The host URL under which the Registry will run and the users will be able to use. |
+| `port` | The port under which the external Registry domain will listen on. |
+| `api_url` | The internal API URL under which the Registry is exposed to. It defaults to `http://localhost:5000`. |
+| `key` | The private key location that is a pair of Registry's `rootcertbundle`. Read the [token auth configuration documentation][token-config]. |
+| `path` | This should be the same directory like specified in Registry's `rootdirectory`. Read the [storage configuration documentation][storage-config]. This path needs to be readable by the GitLab user, the web-server user and the Registry user. Read more in [#container-registry-storage-path](#container-registry-storage-path). |
+| `issuer` | This should be the same value as configured in Registry's `issuer`. Read the [token auth configuration documentation][token-config]. |
+
+>**Note:**
+A Registry init file is not shipped with GitLab if you install it from source.
+Hence, [restarting GitLab][restart gitlab] will not restart the Registry should
+you modify its settings. Read the upstream documentation on how to achieve that.
+
+At the **absolute** minimum, make sure your [Registry configuration][registry-auth]
+has `container_registry` as the service and `https://gitlab.example.com/jwt/auth`
+as the realm:
+
+```
+auth:
+ token:
+ realm: https://gitlab.example.com/jwt/auth
+ service: container_registry
+ issuer: gitlab-issuer
+ rootcertbundle: /root/certs/certbundle
+```
+
+CAUTION: **Caution:**
+If `auth` is not set up, users will be able to pull docker images without authentication.
+
+## Container Registry domain configuration
+
+There are two ways you can configure the Registry's external domain.
+
+- Either [use the existing GitLab domain][existing-domain] where in that case
+ the Registry will have to listen on a port and reuse GitLab's TLS certificate,
+- or [use a completely separate domain][new-domain] with a new TLS certificate
+ for that domain.
+
+Since the container Registry requires a TLS certificate, in the end it all boils
+down to how easy or pricey is to get a new one.
+
+Please take this into consideration before configuring the Container Registry
+for the first time.
+
+### Configure Container Registry under an existing GitLab domain
+
+If the Registry is configured to use the existing GitLab domain, you can
+expose the Registry on a port so that you can reuse the existing GitLab TLS
+certificate.
+
+Assuming that the GitLab domain is `https://gitlab.example.com` and the port the
+Registry is exposed to the outside world is `4567`, here is what you need to set
+in `gitlab.rb` or `gitlab.yml` if you are using Omnibus GitLab or installed
+GitLab from source respectively.
+
+>**Note:**
+Be careful to choose a port different than the one that Registry listens to (`5000` by default),
+otherwise you will run into conflicts.
+
+**Omnibus GitLab installations**
+
+1. Your `/etc/gitlab/gitlab.rb` should contain the Registry URL as well as the
+ path to the existing TLS certificate and key used by GitLab:
+
+ ```ruby
+ registry_external_url 'https://gitlab.example.com:4567'
+ ```
+
+ Note how the `registry_external_url` is listening on HTTPS under the
+ existing GitLab URL, but on a different port.
+
+ If your TLS certificate is not in `/etc/gitlab/ssl/gitlab.example.com.crt`
+ and key not in `/etc/gitlab/ssl/gitlab.example.com.key` uncomment the lines
+ below:
+
+ ```ruby
+ registry_nginx['ssl_certificate'] = "/path/to/certificate.pem"
+ registry_nginx['ssl_certificate_key'] = "/path/to/certificate.key"
+ ```
+
+1. Save the file and [reconfigure GitLab][] for the changes to take effect.
+
+1. Validate using:
+
+ ```sh
+ openssl s_client -showcerts -servername gitlab.example.com -connect gitlab.example.com:443 > cacert.pem
+ ```
+
+NOTE: **Note:**
+If your certificate provider provides the CA Bundle certificates, append them to the TLS certificate file.
+
+**Installations from source**
+
+1. Open `/home/git/gitlab/config/gitlab.yml`, find the `registry` entry and
+ configure it with the following settings:
+
+ ```
+ registry:
+ enabled: true
+ host: gitlab.example.com
+ port: 4567
+ ```
+
+1. Save the file and [restart GitLab][] for the changes to take effect.
+1. Make the relevant changes in NGINX as well (domain, port, TLS certificates path).
+
+Users should now be able to login to the Container Registry with their GitLab
+credentials using:
+
+```bash
+docker login gitlab.example.com:4567
+```
+
+### Configure Container Registry under its own domain
+
+If the Registry is configured to use its own domain, you will need a TLS
+certificate for that specific domain (e.g., `registry.example.com`) or maybe
+a wildcard certificate if hosted under a subdomain of your existing GitLab
+domain (e.g., `registry.gitlab.example.com`).
+
+NOTE: **Note:**
+As well as manually generated SSL certificates (explained here), certificates automatically
+generated by Let's Encrypt are also [supported in Omnibus installs](https://docs.gitlab.com/omnibus/settings/ssl.html#host-services).
+
+Let's assume that you want the container Registry to be accessible at
+`https://registry.gitlab.example.com`.
+
+**Omnibus GitLab installations**
+
+1. Place your TLS certificate and key in
+ `/etc/gitlab/ssl/registry.gitlab.example.com.crt` and
+ `/etc/gitlab/ssl/registry.gitlab.example.com.key` and make sure they have
+ correct permissions:
+
+ ```bash
+ chmod 600 /etc/gitlab/ssl/registry.gitlab.example.com.*
+ ```
+
+1. Once the TLS certificate is in place, edit `/etc/gitlab/gitlab.rb` with:
+
+ ```ruby
+ registry_external_url 'https://registry.gitlab.example.com'
+ ```
+
+ Note how the `registry_external_url` is listening on HTTPS.
+
+1. Save the file and [reconfigure GitLab][] for the changes to take effect.
+
+> **Note:**
+If you have a [wildcard certificate][], you need to specify the path to the
+certificate in addition to the URL, in this case `/etc/gitlab/gitlab.rb` will
+look like:
+>
+> ```ruby
+> registry_nginx['ssl_certificate'] = "/etc/gitlab/ssl/certificate.pem"
+> registry_nginx['ssl_certificate_key'] = "/etc/gitlab/ssl/certificate.key"
+> ```
+
+**Installations from source**
+
+1. Open `/home/git/gitlab/config/gitlab.yml`, find the `registry` entry and
+ configure it with the following settings:
+
+ ```yaml
+ registry:
+ enabled: true
+ host: registry.gitlab.example.com
+ ```
+
+1. Save the file and [restart GitLab][] for the changes to take effect.
+1. Make the relevant changes in NGINX as well (domain, port, TLS certificates path).
+
+Users should now be able to login to the Container Registry using their GitLab
+credentials:
+
+```bash
+docker login registry.gitlab.example.com
+```
+
+## Disable Container Registry site-wide
+
+>**Note:**
+Disabling the Registry in the Rails GitLab application as set by the following
+steps, will not remove any existing Docker images. This is handled by the
+Registry application itself.
+
+**Omnibus GitLab**
+
+1. Open `/etc/gitlab/gitlab.rb` and set `registry['enable']` to `false`:
+
+ ```ruby
+ registry['enable'] = false
+ ```
+
+1. Save the file and [reconfigure GitLab][] for the changes to take effect.
+
+**Installations from source**
+
+1. Open `/home/git/gitlab/config/gitlab.yml`, find the `registry` entry and
+ set `enabled` to `false`:
+
+ ```yaml
+ registry:
+ enabled: false
+ ```
+
+1. Save the file and [restart GitLab][] for the changes to take effect.
+
+## Disable Container Registry for new projects site-wide
+
+If the Container Registry is enabled, then it will be available on all new
+projects. To disable this function and let the owners of a project to enable
+the Container Registry by themselves, follow the steps below.
+
+**Omnibus GitLab installations**
+
+1. Edit `/etc/gitlab/gitlab.rb` and add the following line:
+
+ ```ruby
+ gitlab_rails['gitlab_default_projects_features_container_registry'] = false
+ ```
+
+1. Save the file and [reconfigure GitLab][] for the changes to take effect.
+
+**Installations from source**
+
+1. Open `/home/git/gitlab/config/gitlab.yml`, find the `default_projects_features`
+ entry and configure it so that `container_registry` is set to `false`:
+
+ ```yaml
+ ## Default project features settings
+ default_projects_features:
+ issues: true
+ merge_requests: true
+ wiki: true
+ snippets: false
+ builds: true
+ container_registry: false
+ ```
+
+1. Save the file and [restart GitLab][] for the changes to take effect.
+
+## Container Registry storage path
+
+>**Note:**
+For configuring storage in the cloud instead of the filesystem, see the
+[storage driver configuration](#container-registry-storage-driver).
+
+If you want to store your images on the filesystem, you can change the storage
+path for the Container Registry, follow the steps below.
+
+This path is accessible to:
+
+- the user running the Container Registry daemon,
+- the user running GitLab
+
+> **Warning** You should confirm that all GitLab, Registry and web server users
+have access to this directory.
+
+**Omnibus GitLab installations**
+
+The default location where images are stored in Omnibus, is
+`/var/opt/gitlab/gitlab-rails/shared/registry`. To change it:
+
+1. Edit `/etc/gitlab/gitlab.rb`:
+
+ ```ruby
+ gitlab_rails['registry_path'] = "/path/to/registry/storage"
+ ```
+
+1. Save the file and [reconfigure GitLab][] for the changes to take effect.
+
+**Installations from source**
+
+The default location where images are stored in source installations, is
+`/home/git/gitlab/shared/registry`. To change it:
+
+1. Open `/home/git/gitlab/config/gitlab.yml`, find the `registry` entry and
+ change the `path` setting:
+
+ ```yaml
+ registry:
+ path: shared/registry
+ ```
+
+1. Save the file and [restart GitLab][] for the changes to take effect.
+
+## Container Registry storage driver
+
+You can configure the Container Registry to use a different storage backend by
+configuring a different storage driver. By default the GitLab Container Registry
+is configured to use the filesystem driver, which makes use of [storage path](#container-registry-storage-path)
+configuration.
+
+NOTE: **Note:** Enabling a storage driver other than `filesystem` would mean
+that your Docker client needs to be able to access the storage backend directly.
+In that case, you must use an address that resolves and is accessible outside GitLab server.
+
+The different supported drivers are:
+
+| Driver | Description |
+|------------|-------------------------------------|
+| filesystem | Uses a path on the local filesystem |
+| azure | Microsoft Azure Blob Storage |
+| gcs | Google Cloud Storage |
+| s3 | Amazon Simple Storage Service. Be sure to configure your storage bucket with the correct [S3 Permission Scopes](https://docs.docker.com/registry/storage-drivers/s3/#s3-permission-scopes). |
+| swift | OpenStack Swift Object Storage |
+| oss | Aliyun OSS |
+
+Read more about the individual driver's config options in the
+[Docker Registry docs][storage-config].
+
+CAUTION: **Warning:** GitLab will not backup Docker images that are not stored on the
+filesystem. Remember to enable backups with your object storage provider if
+desired.
+
+NOTE: **Note:**
+`regionendpoint` is only required when configuring an S3 compatible service such as Minio. It takes a URL such as `http://127.0.0.1:9000`.
+
+**Omnibus GitLab installations**
+
+To configure the `s3` storage driver in Omnibus:
+
+1. Edit `/etc/gitlab/gitlab.rb`:
+
+ ```ruby
+ registry['storage'] = {
+ 's3' => {
+ 'accesskey' => 's3-access-key',
+ 'secretkey' => 's3-secret-key-for-access-key',
+ 'bucket' => 'your-s3-bucket',
+ 'region' => 'your-s3-region',
+ 'regionendpoint' => 'your-s3-regionendpoint'
+ }
+ }
+ ```
+
+1. Save the file and [reconfigure GitLab][] for the changes to take effect.
+
+**Installations from source**
+
+Configuring the storage driver is done in your registry config YML file created
+when you [deployed your docker registry][registry-deploy].
+
+`s3` storage driver example:
+
+```yml
+storage:
+ s3:
+ accesskey: 'AKIAKIAKI'
+ secretkey: 'secret123'
+ bucket: 'gitlab-registry-bucket-AKIAKIAKI'
+ region: 'your-s3-region'
+ regionendpoint: 'your-s3-regionendpoint'
+ cache:
+ blobdescriptor: inmemory
+ delete:
+ enabled: true
+```
+
+## Change the registry's internal port
+
+> **Note:**
+This is not to be confused with the port that GitLab itself uses to expose
+the Registry to the world.
+
+The Registry server listens on localhost at port `5000` by default,
+which is the address for which the Registry server should accept connections.
+In the examples below we set the Registry's port to `5001`.
+
+**Omnibus GitLab**
+
+1. Open `/etc/gitlab/gitlab.rb` and set `registry['registry_http_addr']`:
+
+ ```ruby
+ registry['registry_http_addr'] = "localhost:5001"
+ ```
+
+1. Save the file and [reconfigure GitLab][] for the changes to take effect.
+
+**Installations from source**
+
+1. Open the configuration file of your Registry server and edit the
+ [`http:addr`][registry-http-config] value:
+
+ ```yaml
+ http
+ addr: localhost:5001
+ ```
+
+1. Save the file and restart the Registry server.
+
+## Disable Container Registry per project
+
+If Registry is enabled in your GitLab instance, but you don't need it for your
+project, you can disable it from your project's settings. Read the user guide
+on how to achieve that.
+
+## Disable Container Registry but use GitLab as an auth endpoint
+
+**Omnibus GitLab**
+
+You can use GitLab as an auth endpoint and use a non-bundled Container Registry.
+
+1. Open `/etc/gitlab/gitlab.rb` and set necessary configurations:
+
+ ```ruby
+ gitlab_rails['registry_enabled'] = true
+ gitlab_rails['registry_host'] = "registry.gitlab.example.com"
+ gitlab_rails['registry_port'] = "5005"
+ gitlab_rails['registry_api_url'] = "http://localhost:5000"
+ gitlab_rails['registry_path'] = "/var/opt/gitlab/gitlab-rails/shared/registry"
+ gitlab_rails['registry_issuer'] = "omnibus-gitlab-issuer"
+ ```
+
+1. A certificate keypair is required for GitLab and the Container Registry to
+ communicate securely. By default Omnibus GitLab will generate one keypair,
+ which is saved to `/var/opt/gitlab/gitlab-rails/etc/gitlab-registry.key`.
+ When using a non-bundled Container Registry, you will need to supply a
+ custom certificate key. To do that, add the following to
+ `/etc/gitlab/gitlab.rb`
+
+ ```ruby
+ gitlab_rails['registry_key_path'] = "/custom/path/to/registry-key.key"
+ # registry['internal_key'] should contain the contents of the custom key
+ # file. Line breaks in the key file should be marked using `\n` character
+ # Example:
+ registry['internal_key'] = "---BEGIN RSA PRIVATE KEY---\nMIIEpQIBAA\n"
+ ```
+
+ **Note:** The file specified at `registry_key_path` gets populated with the
+ content specified by `internal_key`, each time reconfigure is executed. If
+ no file is specified, Omnibus GitLab will default it to
+ `/var/opt/gitlab/gitlab-rails/etc/gitlab-registry.key` and will populate
+ it.
+
+1. Save the file and [reconfigure GitLab][] for the changes to take effect.
+
+**Installations from source**
+
+1. Open `/home/git/gitlab/config/gitlab.yml`, and edit the configuration settings under `registry`:
+
+ ```yaml
+ ## Container Registry
+
+ registry:
+ enabled: true
+ host: "registry.gitlab.example.com"
+ port: "5005"
+ api_url: "http://localhost:5000"
+ path: /var/opt/gitlab/gitlab-rails/shared/registry
+ key: /var/opt/gitlab/gitlab-rails/certificate.key
+ issuer: omnibus-gitlab-issuer
+ ```
+
+1. Save the file and [restart GitLab][] for the changes to take effect.
+
+## Storage limitations
+
+Currently, there is no storage limitation, which means a user can upload an
+infinite amount of Docker images with arbitrary sizes. This setting will be
+configurable in future releases.
+
+## Configure Container Registry notifications
+
+You can configure the Container Registry to send webhook notifications in
+response to events happening within the registry.
+
+Read more about the Container Registry notifications config options in the
+[Docker Registry notifications documentation][notifications-config].
+
+>**Note:**
+Multiple endpoints can be configured for the Container Registry.
+
+**Omnibus GitLab installations**
+
+To configure a notification endpoint in Omnibus:
+
+1. Edit `/etc/gitlab/gitlab.rb`:
+
+ ```ruby
+ registry['notifications'] = [
+ {
+ 'name' => 'test_endpoint',
+ 'url' => 'https://gitlab.example.com/notify',
+ 'timeout' => '500ms',
+ 'threshold' => 5,
+ 'backoff' => '1s',
+ 'headers' => {
+ "Authorization" => ["AUTHORIZATION_EXAMPLE_TOKEN"]
+ }
+ }
+ ]
+ ```
+
+1. Save the file and [reconfigure GitLab][] for the changes to take effect.
+
+**Installations from source**
+
+Configuring the notification endpoint is done in your registry config YML file created
+when you [deployed your docker registry][registry-deploy].
+
+Example:
+
+```
+notifications:
+ endpoints:
+ - name: alistener
+ disabled: false
+ url: https://my.listener.com/event
+ headers: <http.Header>
+ timeout: 500
+ threshold: 5
+ backoff: 1000
+```
+
+## Troubleshooting
+
+### Using self-signed certificates with Container Registry
+
+If you're using a self-signed certificate with your Container Registry, you
+might encounter issues during the CI jobs like the following:
+
+```
+Error response from daemon: Get registry.example.com/v1/users/: x509: certificate signed by unknown authority
+```
+
+The Docker daemon running the command expects a cert signed by a recognized CA,
+thus the error above.
+
+While GitLab doesn't support using self-signed certificates with Container Registry out of the box, it is possible to make it work by [instructing the docker-daemon to trust the self-signed certificates][docker-insecure-self-signed], mounting the docker-daemon and setting `privileged = false` in the runner's `config.toml`. Setting `privileged = true` takes precedence over the docker-daemon.
+
+```
+ [runners.docker]
+ image = "ruby:2.1"
+ privileged = false
+ volumes = ["/var/run/docker.sock:/var/run/docker.sock", "/cache"]
+```
+
+Additional information about this: [issue 18239][ce-18239].
+
+### AWS S3 with the GitLab registry error when pushing large images
+
+When using AWS S3 with the GitLab registry, an error may occur when pushing
+large images. Look in the Registry log for the following error:
+
+```
+level=error msg="response completed with error" err.code=unknown err.detail="unexpected EOF" err.message="unknown error"
+```
+
+To resolve the error specify a `chunksize` value in the Registry configuration.
+Start with a value between `25000000` (25MB) and `50000000` (50MB).
+
+**For Omnibus installations**
+
+1. Edit `/etc/gitlab/gitlab.rb`:
+
+ ```ruby
+ registry['storage'] = {
+ 's3' => {
+ 'accesskey' => 'AKIAKIAKI',
+ 'secretkey' => 'secret123',
+ 'bucket' => 'gitlab-registry-bucket-AKIAKIAKI',
+ 'chunksize' => 25000000
+ }
+ }
+ ```
+
+1. Save the file and [reconfigure GitLab][] for the changes to take effect.
+
+**For installations from source**
+
+1. Edit `config/gitlab.yml`:
+
+ ```yaml
+ storage:
+ s3:
+ accesskey: 'AKIAKIAKI'
+ secretkey: 'secret123'
+ bucket: 'gitlab-registry-bucket-AKIAKIAKI'
+ chunksize: 25000000
+ ```
+
+1. Save the file and [restart GitLab][] for the changes to take effect.
+
+### Supporting older Docker clients
+
+As of GitLab 11.9, we began shipping version 2.7.1 of the Docker container registry, which disables the schema1 manifest by default. If you are still using older Docker clients (1.9 or older), you may experience an error pushing images. See [omnibus-4145](https://gitlab.com/gitlab-org/omnibus-gitlab/issues/4145) for more details.
+
+You can add a configuration option for backwards compatibility.
+
+**For Omnibus installations**
+
+1. Edit `/etc/gitlab/gitlab.rb`:
+
+ ```ruby
+ registry['compatibility_schema1_enabled'] = true
+ ```
+
+1. Save the file and [reconfigure GitLab][] for the changes to take effect.
+
+**For installations from source**
+
+1. Edit the YML configuration file you created when you [deployed the registry][registry-deploy]. Add the following snippet:
+
+ ```yaml
+ compatibility:
+ schema1:
+ enabled: true
+ ```
+
+1. Restart the registry for the changes to take affect.
+
+### Docker connection error
+
+A Docker connection error can occur when there are special characters in either the group,
+project or branch name. Special characters can include:
+
+- Leading underscore
+- Trailing hyphen/dash
+- Double hyphen/dash
+
+To get around this, you can [change the group path](../user/group/index.md#changing-a-groups-path),
+[change the project path](../user/project/settings/index.md#renaming-a-repository) or change the
+branch name. Another option is to create a [push rule](../push_rules/push_rules.html) to prevent
+this at the instance level.
+
+### Image push errors
+
+When getting errors or "retrying" loops in an attempt to push an image but `docker login` works fine,
+there is likely an issue with the headers forwarded to the registry by NGINX. The default recommended
+NGINX configurations should handle this, but it might occur in custom setups where the SSL is
+offloaded to a third party reverse proxy.
+
+This problem was discussed in a [docker project issue][docker-image-push-issue] and a simple solution
+would be to enable relative urls in the registry.
+
+**For Omnibus installations**
+
+1. Edit `/etc/gitlab/gitlab.rb`:
+
+ ```ruby
+ registry['env'] = {
+ "REGISTRY_HTTP_RELATIVEURLS" => true
+ }
+ ```
+
+1. Save the file and [reconfigure GitLab][] for the changes to take effect.
+
+**For installations from source**
+
+1. Edit the YML configuration file you created when you [deployed the registry][registry-deploy]. Add the following snippet:
+
+ ```yaml
+ http:
+ relativeurls: true
+ ```
+
+1. Restart the registry for the changes to take affect.
+
+[ce-18239]: https://gitlab.com/gitlab-org/gitlab-ce/issues/18239
+[docker-insecure-self-signed]: https://docs.docker.com/registry/insecure/#use-self-signed-certificates
+[reconfigure gitlab]: restart_gitlab.md#omnibus-gitlab-reconfigure
+[restart gitlab]: restart_gitlab.md#installations-from-source
+[wildcard certificate]: https://en.wikipedia.org/wiki/Wildcard_certificate
+[ce-4040]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/4040
+[docker-insecure]: https://docs.docker.com/registry/insecure/
+[registry-deploy]: https://docs.docker.com/registry/deploying/
+[storage-config]: https://docs.docker.com/registry/configuration/#storage
+[registry-http-config]: https://docs.docker.com/registry/configuration/#http
+[registry-auth]: https://docs.docker.com/registry/configuration/#auth
+[token-config]: https://docs.docker.com/registry/configuration/#token
+[8-8-docs]: https://gitlab.com/gitlab-org/gitlab-ce/blob/8-8-stable/doc/administration/container_registry.md
+[registry-ssl]: https://gitlab.com/gitlab-org/gitlab-ce/blob/master/lib/support/nginx/registry-ssl
+[existing-domain]: #configure-container-registry-under-an-existing-gitlab-domain
+[new-domain]: #configure-container-registry-under-its-own-domain
+[notifications-config]: https://docs.docker.com/registry/notifications/
+[registry-notifications-config]: https://docs.docker.com/registry/configuration/#notifications
+[docker-image-push-issue]: https://github.com/docker/distribution/issues/970
diff --git a/doc/administration/dependency_proxy.md b/doc/administration/dependency_proxy.md
index 4683565998a..5153666705f 100644
--- a/doc/administration/dependency_proxy.md
+++ b/doc/administration/dependency_proxy.md
@@ -1,5 +1,151 @@
----
-redirect_to: 'packages/dependency_proxy.md'
----
+# GitLab Dependency Proxy administration **(PREMIUM ONLY)**
-This document was moved to [another location](packages/dependency_proxy.md).
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/issues/7934) in [GitLab Premium](https://about.gitlab.com/pricing/) 11.11.
+
+GitLab can be utilized as a dependency proxy for a variety of common package managers.
+
+This is the administration documentation. If you want to learn how to use the
+dependency proxies, see the [user guide](../user/group/dependency_proxy/index.md).
+
+## Enabling the Dependency Proxy feature
+
+NOTE: **Note:**
+Dependency proxy requires the Puma web server to be enabled.
+Puma support is EXPERIMENTAL at this time.
+
+To enable the Dependency proxy feature:
+
+**Omnibus GitLab installations**
+
+1. Edit `/etc/gitlab/gitlab.rb` and add the following line:
+
+ ```ruby
+ gitlab_rails['dependency_proxy_enabled'] = true
+ ```
+
+1. Save the file and [reconfigure GitLab][] for the changes to take effect.
+1. Enable the [Puma web server](https://docs.gitlab.com/omnibus/settings/puma.html).
+
+**Installations from source**
+
+1. After the installation is complete, you will have to configure the `dependency_proxy`
+ section in `config/gitlab.yml`. Set to `true` to enable it:
+
+ ```yaml
+ dependency_proxy:
+ enabled: true
+ ```
+
+1. [Restart GitLab] for the changes to take effect.
+1. Enable the [Puma web server](../install/installation.md#using-puma).
+
+## Changing the storage path
+
+By default, the dependency proxy files are stored locally, but you can change the default
+local location or even use object storage.
+
+### Changing the local storage path
+
+The dependency proxy files for Omnibus GitLab installations are stored under
+`/var/opt/gitlab/gitlab-rails/shared/dependency_proxy/` and for source
+installations under `shared/dependency_proxy/` (relative to the Git home directory).
+To change the local storage path:
+
+**Omnibus GitLab installations**
+
+1. Edit `/etc/gitlab/gitlab.rb` and add the following line:
+
+ ```ruby
+ gitlab_rails['dependency_proxy_storage_path'] = "/mnt/dependency_proxy"
+ ```
+
+1. Save the file and [reconfigure GitLab][] for the changes to take effect.
+
+**Installations from source**
+
+1. Edit the `dependency_proxy` section in `config/gitlab.yml`:
+
+ ```yaml
+ dependency_proxy:
+ enabled: true
+ storage_path: shared/dependency_proxy
+ ```
+
+1. [Restart GitLab] for the changes to take effect.
+
+### Using object storage
+
+Instead of relying on the local storage, you can use an object storage to
+upload the blobs of the dependency proxy:
+
+**Omnibus GitLab installations**
+
+1. Edit `/etc/gitlab/gitlab.rb` and add the following lines (uncomment where
+ necessary):
+
+ ```ruby
+ gitlab_rails['dependency_proxy_enabled'] = true
+ gitlab_rails['dependency_proxy_storage_path'] = "/var/opt/gitlab/gitlab-rails/shared/dependency_proxy"
+ gitlab_rails['dependency_proxy_object_store_enabled'] = true
+ gitlab_rails['dependency_proxy_object_store_remote_directory'] = "dependency_proxy" # The bucket name.
+ gitlab_rails['dependency_proxy_object_store_direct_upload'] = false # Use Object Storage directly for uploads instead of background uploads if enabled (Default: false).
+ gitlab_rails['dependency_proxy_object_store_background_upload'] = true # Temporary option to limit automatic upload (Default: true).
+ gitlab_rails['dependency_proxy_object_store_proxy_download'] = false # Passthrough all downloads via GitLab instead of using Redirects to Object Storage.
+ gitlab_rails['dependency_proxy_object_store_connection'] = {
+ ##
+ ## If the provider is AWS S3, uncomment the following
+ ##
+ #'provider' => 'AWS',
+ #'region' => 'eu-west-1',
+ #'aws_access_key_id' => 'AWS_ACCESS_KEY_ID',
+ #'aws_secret_access_key' => 'AWS_SECRET_ACCESS_KEY',
+ ##
+ ## If the provider is other than AWS (an S3-compatible one), uncomment the following
+ ##
+ #'host' => 's3.amazonaws.com',
+ #'aws_signature_version' => 4 # For creation of signed URLs. Set to 2 if provider does not support v4.
+ #'endpoint' => 'https://s3.amazonaws.com' # Useful for S3-compliant services such as DigitalOcean Spaces.
+ #'path_style' => false # If true, use 'host/bucket_name/object' instead of 'bucket_name.host/object'.
+ }
+ ```
+
+1. Save the file and [reconfigure GitLab][] for the changes to take effect.
+
+**Installations from source**
+
+1. Edit the `dependency_proxy` section in `config/gitlab.yml` (uncomment where necessary):
+
+ ```yaml
+ dependency_proxy:
+ enabled: true
+ ##
+ ## The location where build dependency_proxy are stored (default: shared/dependency_proxy).
+ ##
+ #storage_path: shared/dependency_proxy
+ object_store:
+ enabled: false
+ remote_directory: dependency_proxy # The bucket name.
+ #direct_upload: false # Use Object Storage directly for uploads instead of background uploads if enabled (Default: false).
+ #background_upload: true # Temporary option to limit automatic upload (Default: true).
+ #proxy_download: false # Passthrough all downloads via GitLab instead of using Redirects to Object Storage.
+ connection:
+ ##
+ ## If the provider is AWS S3, uncomment the following
+ ##
+ #provider: AWS
+ #region: us-east-1
+ #aws_access_key_id: AWS_ACCESS_KEY_ID
+ #aws_secret_access_key: AWS_SECRET_ACCESS_KEY
+ ##
+ ## If the provider is other than AWS (an S3-compatible one), uncomment the following
+ ##
+ #host: 's3.amazonaws.com' # default: s3.amazonaws.com.
+ #aws_signature_version: 4 # For creation of signed URLs. Set to 2 if provider does not support v4.
+ #endpoint: 'https://s3.amazonaws.com' # Useful for S3-compliant services such as DigitalOcean Spaces.
+ #path_style: false # If true, use 'host/bucket_name/object' instead of 'bucket_name.host/object'.
+ ```
+
+1. [Restart GitLab] for the changes to take effect.
+
+[reconfigure gitlab]: restart_gitlab.md#omnibus-gitlab-reconfigure "How to reconfigure Omnibus GitLab"
+[restart gitlab]: restart_gitlab.md#omnibus-gitlab-reconfigure "How to reconfigure Omnibus GitLab"
diff --git a/doc/administration/geo/replication/docker_registry.md b/doc/administration/geo/replication/docker_registry.md
index 12cd39c0213..b326717205e 100644
--- a/doc/administration/geo/replication/docker_registry.md
+++ b/doc/administration/geo/replication/docker_registry.md
@@ -11,7 +11,7 @@ Registry on the **primary** node, you can use the same storage for a **secondary
Docker Registry as well. For more information, read the
[Load balancing considerations](https://docs.docker.com/registry/deploying/#load-balancing-considerations)
when deploying the Registry, and how to set up the storage driver for GitLab's
-integrated [Container Registry](../../packages/container_registry.md#container-registry-storage-driver).
+integrated [Container Registry](../../container_registry.md#container-registry-storage-driver).
## Replicating Docker Registry
@@ -63,11 +63,6 @@ We need to make Docker Registry send notification events to the
notification secret in `registry.notification_secret` section of
`/etc/gitlab/gitlab.rb` file.
- NOTE: **Note:**
- If you use GitLab HA, you will also have to specify
- the notification secret in `registry.notification_secret` section of
- `/etc/gitlab/gitlab.rb` file for every web node.
-
1. Reconfigure the **primary** node for the change to take effect:
```sh
@@ -99,8 +94,10 @@ generate a short-lived JWT that is pull-only-capable to access the
1. Edit `/etc/gitlab/gitlab.rb`:
```ruby
- gitlab_rails['geo_registry_replication_enabled'] = true
- gitlab_rails['geo_registry_replication_primary_api_url'] = 'http://primary.example.com:5000/' # internal address to the primary registry, will be used by GitLab to directly communicate with primary registry API
+ gitlab_rails['registry_replication'] = {
+ enabled: true,
+ primary_api_url: 'http://primary.example.com:5000/' # internal address to the primary registry, will be used by GitLab to directly communicate with primary registry API
+ }
```
1. Reconfigure the **secondary** node for the change to take effect:
diff --git a/doc/administration/geo/replication/index.md b/doc/administration/geo/replication/index.md
index bbad9f455fe..1d50c924f6e 100644
--- a/doc/administration/geo/replication/index.md
+++ b/doc/administration/geo/replication/index.md
@@ -274,9 +274,9 @@ You can keep track of the progress to include the missing items in:
| [Server-side Git Hooks](../../custom_hooks.md) | No | No |
| [Elasticsearch integration](../../../integration/elasticsearch.md) | No | No |
| [GitLab Pages](../../pages/index.md) | No | No |
-| [Container Registry](../../packages/container_registry.md) | Yes | No |
-| [NPM Registry](../../../user/packages/npm_registry/index.md) | No | No |
-| [Maven Packages](../../../user/packages/maven_repository/index.md) | No | No |
+| [Container Registry](../../container_registry.md) | Yes | No |
+| [NPM Registry](../../npm_registry.md) | No | No |
+| [Maven Packages](../../maven_packages.md) | No | No |
| [External merge request diffs](../../merge_request_diffs.md) | No, if they are on-disk | No |
| Content in object storage ([track progress](https://gitlab.com/groups/gitlab-org/-/epics/1526)) | No | No |
diff --git a/doc/administration/gitaly/index.md b/doc/administration/gitaly/index.md
index 27794878cfe..53b354d2f92 100644
--- a/doc/administration/gitaly/index.md
+++ b/doc/administration/gitaly/index.md
@@ -635,7 +635,7 @@ Confirm the following are all true:
UI, it immediatley fails with a red `401 Unauthorized` banner.
- Creating a new project and [initializing it with a README](../../gitlab-basics/create-project.md#blank-projects)
successfully creates the project but doesn't create the README.
-- When [tailing the logs](https://docs.gitlab.com/omnibus/settings/logs.html#tail-logs-in-a-console-on-the-server) on an app node and reproducing the error, you get `401` errors
+- When [tailing the logs](https://docs.gitlab.com/omnibus/settings/logs.md#tail-logs-in-a-console-on-the-server) on an app node and reproducing the error, you get `401` errors
when reaching the `/api/v4/internal/allowed` endpoint:
```sh
diff --git a/doc/administration/index.md b/doc/administration/index.md
index 731c25cd3d8..df3501ae950 100644
--- a/doc/administration/index.md
+++ b/doc/administration/index.md
@@ -128,17 +128,13 @@ Learn how to install, configure, update, and maintain your GitLab instance.
## Project settings
+- [Container Registry](container_registry.md): Configure Container Registry with GitLab.
- [Issue closing pattern](issue_closing_pattern.md): Customize how to close an issue from commit messages.
- [Gitaly](gitaly/index.md): Configuring Gitaly, GitLab's Git repository storage service.
- [Default labels](../user/admin_area/labels.md): Create labels that will be automatically added to every new project.
- [Restrict the use of public or internal projects](../public_access/public_access.md#restricting-the-use-of-public-or-internal-projects): Restrict the use of visibility levels for users when they create a project or a snippet.
- [Custom project templates](../user/admin_area/custom_project_templates.md): Configure a set of projects to be used as custom templates when creating a new project. **(PREMIUM ONLY)**
-
-## Package Registry administration
-
-- [Container Registry](packages/container_registry.md): Configure Container Registry with GitLab.
-- [Package Registry](packages/index.md): Enable GitLab to act as an NPM Registry and a Maven Repository. **(PREMIUM ONLY)**
-- [Dependency Proxy](packages/dependency_proxy.md): Configure the Dependency Proxy, a local proxy for frequently used upstream images/packages. **(PREMIUM ONLY)**
+- [Packages](packages.md): Enable GitLab to act as a Maven repository or NPM registry. **(PREMIUM ONLY)**
### Repository settings
diff --git a/doc/administration/maven_packages.md b/doc/administration/maven_packages.md
index cdcce79f8f9..d8551f64ece 100644
--- a/doc/administration/maven_packages.md
+++ b/doc/administration/maven_packages.md
@@ -1,5 +1,5 @@
---
-redirect_to: 'packages/index.md'
+redirect_to: 'packages.md'
---
-This document was moved to [another location](packages/index.md).
+This document was moved to [another location](packages.md).
diff --git a/doc/administration/maven_repository.md b/doc/administration/maven_repository.md
index cdcce79f8f9..d8551f64ece 100644
--- a/doc/administration/maven_repository.md
+++ b/doc/administration/maven_repository.md
@@ -1,5 +1,5 @@
---
-redirect_to: 'packages/index.md'
+redirect_to: 'packages.md'
---
-This document was moved to [another location](packages/index.md).
+This document was moved to [another location](packages.md).
diff --git a/doc/administration/npm_registry.md b/doc/administration/npm_registry.md
index cdcce79f8f9..d8551f64ece 100644
--- a/doc/administration/npm_registry.md
+++ b/doc/administration/npm_registry.md
@@ -1,5 +1,5 @@
---
-redirect_to: 'packages/index.md'
+redirect_to: 'packages.md'
---
-This document was moved to [another location](packages/index.md).
+This document was moved to [another location](packages.md).
diff --git a/doc/administration/packages.md b/doc/administration/packages.md
index cdcce79f8f9..1628b6d6f91 100644
--- a/doc/administration/packages.md
+++ b/doc/administration/packages.md
@@ -1,5 +1,176 @@
----
-redirect_to: 'packages/index.md'
----
+# GitLab Packages administration **(PREMIUM ONLY)**
-This document was moved to [another location](packages/index.md).
+GitLab Packages allows organizations to utilize GitLab as a private repository
+for a variety of common package managers. Users are able to build and publish
+packages, which can be easily consumed as a dependency in downstream projects.
+
+The Packages feature allows GitLab to act as a repository for the following:
+
+| Software repository | Description | Available in GitLab version |
+| ------------------- | ----------- | --------------------------- |
+| [Maven Repository](../user/project/packages/maven_repository.md) | The GitLab Maven Repository enables every project in GitLab to have its own space to store [Maven](https://maven.apache.org/) packages. | 11.3+ |
+| [NPM Registry](../user/project/packages/npm_registry.md) | The GitLab NPM Registry enables every project in GitLab to have its own space to store [NPM](https://www.npmjs.com/) packages. | 11.7+ |
+
+Don't you see your package management system supported yet?
+Please consider contributing
+to GitLab. This [development documentation](../development/packages.md) will guide you through the process.
+
+## Enabling the Packages feature
+
+NOTE: **Note:**
+After the Packages feature is enabled, the repositories are available
+for all new projects by default. To enable it for existing projects, users will
+have to explicitly do so in the project's settings.
+
+To enable the Packages feature:
+
+**Omnibus GitLab installations**
+
+1. Edit `/etc/gitlab/gitlab.rb` and add the following line:
+
+ ```ruby
+ gitlab_rails['packages_enabled'] = true
+ ```
+
+1. Save the file and [reconfigure GitLab][] for the changes to take effect.
+
+**Installations from source**
+
+1. After the installation is complete, you will have to configure the `packages`
+ section in `config/gitlab.yml`. Set to `true` to enable it:
+
+ ```yaml
+ packages:
+ enabled: true
+ ```
+
+1. [Restart GitLab] for the changes to take effect.
+
+## Changing the storage path
+
+By default, the packages are stored locally, but you can change the default
+local location or even use object storage.
+
+### Changing the local storage path
+
+The packages for Omnibus GitLab installations are stored under
+`/var/opt/gitlab/gitlab-rails/shared/packages/` and for source
+installations under `shared/packages/` (relative to the Git homedir).
+To change the local storage path:
+
+**Omnibus GitLab installations**
+
+1. Edit `/etc/gitlab/gitlab.rb` and add the following line:
+
+ ```ruby
+ gitlab_rails['packages_storage_path'] = "/mnt/packages"
+ ```
+
+1. Save the file and [reconfigure GitLab][] for the changes to take effect.
+
+**Installations from source**
+
+1. Edit the `packages` section in `config/gitlab.yml`:
+
+ ```yaml
+ packages:
+ enabled: true
+ storage_path: shared/packages
+ ```
+
+1. [Restart GitLab] for the changes to take effect.
+
+### Using object storage
+
+Instead of relying on the local storage, you can use an object storage to
+upload packages:
+
+**Omnibus GitLab installations**
+
+1. Edit `/etc/gitlab/gitlab.rb` and add the following lines (uncomment where
+ necessary):
+
+ ```ruby
+ gitlab_rails['packages_enabled'] = true
+ gitlab_rails['packages_storage_path'] = "/var/opt/gitlab/gitlab-rails/shared/packages"
+ gitlab_rails['packages_object_store_enabled'] = true
+ gitlab_rails['packages_object_store_remote_directory'] = "packages" # The bucket name.
+ gitlab_rails['packages_object_store_direct_upload'] = false # Use Object Storage directly for uploads instead of background uploads if enabled (Default: false).
+ gitlab_rails['packages_object_store_background_upload'] = true # Temporary option to limit automatic upload (Default: true).
+ gitlab_rails['packages_object_store_proxy_download'] = false # Passthrough all downloads via GitLab instead of using Redirects to Object Storage.
+ gitlab_rails['packages_object_store_connection'] = {
+ ##
+ ## If the provider is AWS S3, uncomment the following
+ ##
+ #'provider' => 'AWS',
+ #'region' => 'eu-west-1',
+ #'aws_access_key_id' => 'AWS_ACCESS_KEY_ID',
+ #'aws_secret_access_key' => 'AWS_SECRET_ACCESS_KEY',
+ ##
+ ## If the provider is other than AWS (an S3-compatible one), uncomment the following
+ ##
+ #'host' => 's3.amazonaws.com',
+ #'aws_signature_version' => 4 # For creation of signed URLs. Set to 2 if provider does not support v4.
+ #'endpoint' => 'https://s3.amazonaws.com' # Useful for S3-compliant services such as DigitalOcean Spaces.
+ #'path_style' => false # If true, use 'host/bucket_name/object' instead of 'bucket_name.host/object'.
+ }
+ ```
+
+1. Save the file and [reconfigure GitLab][] for the changes to take effect.
+
+**Installations from source**
+
+1. Edit the `packages` section in `config/gitlab.yml` (uncomment where necessary):
+
+ ```yaml
+ packages:
+ enabled: true
+ ##
+ ## The location where build packages are stored (default: shared/packages).
+ ##
+ #storage_path: shared/packages
+ object_store:
+ enabled: false
+ remote_directory: packages # The bucket name.
+ #direct_upload: false # Use Object Storage directly for uploads instead of background uploads if enabled (Default: false).
+ #background_upload: true # Temporary option to limit automatic upload (Default: true).
+ #proxy_download: false # Passthrough all downloads via GitLab instead of using Redirects to Object Storage.
+ connection:
+ ##
+ ## If the provider is AWS S3, uncomment the following
+ ##
+ #provider: AWS
+ #region: us-east-1
+ #aws_access_key_id: AWS_ACCESS_KEY_ID
+ #aws_secret_access_key: AWS_SECRET_ACCESS_KEY
+ ##
+ ## If the provider is other than AWS (an S3-compatible one), uncomment the following
+ ##
+ #host: 's3.amazonaws.com' # default: s3.amazonaws.com.
+ #aws_signature_version: 4 # For creation of signed URLs. Set to 2 if provider does not support v4.
+ #endpoint: 'https://s3.amazonaws.com' # Useful for S3-compliant services such as DigitalOcean Spaces.
+ #path_style: false # If true, use 'host/bucket_name/object' instead of 'bucket_name.host/object'.
+ ```
+
+1. [Restart GitLab] for the changes to take effect.
+
+### Migrating local packages to object storage
+
+After [configuring the object storage](#using-object-storage), you may use the
+following task to migrate existing packages from the local storage to the remote one.
+The processing will be done in a background worker and requires **no downtime**.
+
+For Omnibus GitLab:
+
+```sh
+sudo gitlab-rake "gitlab:packages:migrate"
+```
+
+For installations from source:
+
+```bash
+RAILS_ENV=production sudo -u git -H bundle exec rake gitlab:packages:migrate
+```
+
+[reconfigure gitlab]: restart_gitlab.md#omnibus-gitlab-reconfigure "How to reconfigure Omnibus GitLab"
+[restart gitlab]: restart_gitlab.md#omnibus-gitlab-reconfigure "How to reconfigure Omnibus GitLab"
diff --git a/doc/administration/packages/container_registry.md b/doc/administration/packages/container_registry.md
deleted file mode 100644
index e3c793ee339..00000000000
--- a/doc/administration/packages/container_registry.md
+++ /dev/null
@@ -1,882 +0,0 @@
-# GitLab Container Registry administration
-
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/4040) in GitLab 8.8.
-> - Container Registry manifest `v1` support was added in GitLab 8.9 to support
-> Docker versions earlier than 1.10.
-
-NOTE: **Note:**
-This document is about the admin guide. To learn how to use GitLab Container
-Registry [user documentation](../../user/packages/container_registry/index.md).
-
-With the Container Registry integrated into GitLab, every project can have its
-own space to store its Docker images.
-
-You can read more about the Docker Registry at
-<https://docs.docker.com/registry/introduction/>.
-
-## Enable the Container Registry
-
-**Omnibus GitLab installations**
-
-All you have to do is configure the domain name under which the Container
-Registry will listen to. Read
-[#container-registry-domain-configuration](#container-registry-domain-configuration)
-and pick one of the two options that fits your case.
-
-NOTE: **Note:**
-The container registry works under HTTPS by default. Using HTTP is possible
-but not recommended and out of the scope of this document.
-Read the [insecure Registry documentation](https://docs.docker.com/registry/insecure/)
-if you want to implement this.
-
-**Installations from source**
-
-If you have installed GitLab from source:
-
-1. You will have to [install Registry](https://docs.docker.com/registry/deploying/) by yourself.
-1. After the installation is complete, you will have to configure the Registry's
- settings in `gitlab.yml` in order to enable it.
-1. Use the sample NGINX configuration file that is found under
- [`lib/support/nginx/registry-ssl`](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/lib/support/nginx/registry-ssl) and edit it to match the
- `host`, `port` and TLS certs paths.
-
-The contents of `gitlab.yml` are:
-
-```yaml
-registry:
- enabled: true
- host: registry.gitlab.example.com
- port: 5005
- api_url: http://localhost:5000/
- key: config/registry.key
- path: shared/registry
- issuer: gitlab-issuer
-```
-
-where:
-
-| Parameter | Description |
-| --------- | ----------- |
-| `enabled` | `true` or `false`. Enables the Registry in GitLab. By default this is `false`. |
-| `host` | The host URL under which the Registry will run and the users will be able to use. |
-| `port` | The port under which the external Registry domain will listen on. |
-| `api_url` | The internal API URL under which the Registry is exposed to. It defaults to `http://localhost:5000`. |
-| `key` | The private key location that is a pair of Registry's `rootcertbundle`. Read the [token auth configuration documentation](https://docs.docker.com/registry/configuration/#token). |
-| `path` | This should be the same directory like specified in Registry's `rootdirectory`. Read the [storage configuration documentation](https://docs.docker.com/registry/configuration/#storage). This path needs to be readable by the GitLab user, the web-server user and the Registry user. Read more in [#container-registry-storage-path](#container-registry-storage-path). |
-| `issuer` | This should be the same value as configured in Registry's `issuer`. Read the [token auth configuration documentation](https://docs.docker.com/registry/configuration/#token). |
-
-NOTE: **Note:**
-A Registry init file is not shipped with GitLab if you install it from source.
-Hence, [restarting GitLab](../restart_gitlab.md#installations-from-source) will not restart the Registry should
-you modify its settings. Read the upstream documentation on how to achieve that.
-
-At the **absolute** minimum, make sure your [Registry configuration](https://docs.docker.com/registry/configuration/#auth)
-has `container_registry` as the service and `https://gitlab.example.com/jwt/auth`
-as the realm:
-
-```yaml
-auth:
- token:
- realm: https://gitlab.example.com/jwt/auth
- service: container_registry
- issuer: gitlab-issuer
- rootcertbundle: /root/certs/certbundle
-```
-
-CAUTION: **Caution:**
-If `auth` is not set up, users will be able to pull docker images without authentication.
-
-## Container Registry domain configuration
-
-There are two ways you can configure the Registry's external domain. Either:
-
-- [Use the existing GitLab domain](#configure-container-registry-under-an-existing-gitlab-domain) where in that case
- the Registry will have to listen on a port and reuse GitLab's TLS certificate,
-- [Use a completely separate domain](#configure-container-registry-under-its-own-domain) with a new TLS certificate
- for that domain.
-
-Since the container Registry requires a TLS certificate, in the end it all boils
-down to how easy or pricey is to get a new one.
-
-Please take this into consideration before configuring the Container Registry
-for the first time.
-
-### Configure Container Registry under an existing GitLab domain
-
-If the Registry is configured to use the existing GitLab domain, you can
-expose the Registry on a port so that you can reuse the existing GitLab TLS
-certificate.
-
-Assuming that the GitLab domain is `https://gitlab.example.com` and the port the
-Registry is exposed to the outside world is `4567`, here is what you need to set
-in `gitlab.rb` or `gitlab.yml` if you are using Omnibus GitLab or installed
-GitLab from source respectively.
-
-NOTE: **Note:**
-Be careful to choose a port different than the one that Registry listens to (`5000` by default),
-otherwise you will run into conflicts.
-
-**Omnibus GitLab installations**
-
-1. Your `/etc/gitlab/gitlab.rb` should contain the Registry URL as well as the
- path to the existing TLS certificate and key used by GitLab:
-
- ```ruby
- registry_external_url 'https://gitlab.example.com:4567'
- ```
-
- Note how the `registry_external_url` is listening on HTTPS under the
- existing GitLab URL, but on a different port.
-
- If your TLS certificate is not in `/etc/gitlab/ssl/gitlab.example.com.crt`
- and key not in `/etc/gitlab/ssl/gitlab.example.com.key` uncomment the lines
- below:
-
- ```ruby
- registry_nginx['ssl_certificate'] = "/path/to/certificate.pem"
- registry_nginx['ssl_certificate_key'] = "/path/to/certificate.key"
- ```
-
-1. Save the file and [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure)
- for the changes to take effect.
-
-1. Validate using:
-
- ```sh
- openssl s_client -showcerts -servername gitlab.example.com -connect gitlab.example.com:443 > cacert.pem
- ```
-
-NOTE: **Note:**
-If your certificate provider provides the CA Bundle certificates, append them to the TLS certificate file.
-
-**Installations from source**
-
-1. Open `/home/git/gitlab/config/gitlab.yml`, find the `registry` entry and
- configure it with the following settings:
-
- ```
- registry:
- enabled: true
- host: gitlab.example.com
- port: 4567
- ```
-
-1. Save the file and [restart GitLab](../restart_gitlab.md#installations-from-source) for the changes to take effect.
-1. Make the relevant changes in NGINX as well (domain, port, TLS certificates path).
-
-Users should now be able to login to the Container Registry with their GitLab
-credentials using:
-
-```bash
-docker login gitlab.example.com:4567
-```
-
-### Configure Container Registry under its own domain
-
-If the Registry is configured to use its own domain, you will need a TLS
-certificate for that specific domain (e.g., `registry.example.com`) or maybe
-a wildcard certificate if hosted under a subdomain of your existing GitLab
-domain (e.g., `registry.gitlab.example.com`).
-
-NOTE: **Note:**
-As well as manually generated SSL certificates (explained here), certificates automatically
-generated by Let's Encrypt are also [supported in Omnibus installs](https://docs.gitlab.com/omnibus/settings/ssl.html#host-services).
-
-Let's assume that you want the container Registry to be accessible at
-`https://registry.gitlab.example.com`.
-
-**Omnibus GitLab installations**
-
-1. Place your TLS certificate and key in
- `/etc/gitlab/ssl/registry.gitlab.example.com.crt` and
- `/etc/gitlab/ssl/registry.gitlab.example.com.key` and make sure they have
- correct permissions:
-
- ```bash
- chmod 600 /etc/gitlab/ssl/registry.gitlab.example.com.*
- ```
-
-1. Once the TLS certificate is in place, edit `/etc/gitlab/gitlab.rb` with:
-
- ```ruby
- registry_external_url 'https://registry.gitlab.example.com'
- ```
-
- Note how the `registry_external_url` is listening on HTTPS.
-
-1. Save the file and [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
-
-If you have a [wildcard certificate](https://en.wikipedia.org/wiki/Wildcard_certificate), you need to specify the path to the
-certificate in addition to the URL, in this case `/etc/gitlab/gitlab.rb` will
-look like:
-
-```ruby
-registry_nginx['ssl_certificate'] = "/etc/gitlab/ssl/certificate.pem"
-registry_nginx['ssl_certificate_key'] = "/etc/gitlab/ssl/certificate.key"
-```
-
-**Installations from source**
-
-1. Open `/home/git/gitlab/config/gitlab.yml`, find the `registry` entry and
- configure it with the following settings:
-
- ```yaml
- registry:
- enabled: true
- host: registry.gitlab.example.com
- ```
-
-1. Save the file and [restart GitLab](../restart_gitlab.md#installations-from-source) for the changes to take effect.
-1. Make the relevant changes in NGINX as well (domain, port, TLS certificates path).
-
-Users should now be able to login to the Container Registry using their GitLab
-credentials:
-
-```bash
-docker login registry.gitlab.example.com
-```
-
-## Disable Container Registry site-wide
-
-NOTE: **Note:**
-Disabling the Registry in the Rails GitLab application as set by the following
-steps, will not remove any existing Docker images. This is handled by the
-Registry application itself.
-
-**Omnibus GitLab**
-
-1. Open `/etc/gitlab/gitlab.rb` and set `registry['enable']` to `false`:
-
- ```ruby
- registry['enable'] = false
- ```
-
-1. Save the file and [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
-
-**Installations from source**
-
-1. Open `/home/git/gitlab/config/gitlab.yml`, find the `registry` entry and
- set `enabled` to `false`:
-
- ```yaml
- registry:
- enabled: false
- ```
-
-1. Save the file and [restart GitLab](../restart_gitlab.md#installations-from-source) for the changes to take effect.
-
-## Disable Container Registry for new projects site-wide
-
-If the Container Registry is enabled, then it will be available on all new
-projects. To disable this function and let the owners of a project to enable
-the Container Registry by themselves, follow the steps below.
-
-**Omnibus GitLab installations**
-
-1. Edit `/etc/gitlab/gitlab.rb` and add the following line:
-
- ```ruby
- gitlab_rails['gitlab_default_projects_features_container_registry'] = false
- ```
-
-1. Save the file and [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
-
-**Installations from source**
-
-1. Open `/home/git/gitlab/config/gitlab.yml`, find the `default_projects_features`
- entry and configure it so that `container_registry` is set to `false`:
-
- ```yaml
- ## Default project features settings
- default_projects_features:
- issues: true
- merge_requests: true
- wiki: true
- snippets: false
- builds: true
- container_registry: false
- ```
-
-1. Save the file and [restart GitLab](../restart_gitlab.md#installations-from-source) for the changes to take effect.
-
-## Container Registry storage path
-
-NOTE: **Note:**
-For configuring storage in the cloud instead of the filesystem, see the
-[storage driver configuration](#container-registry-storage-driver).
-
-If you want to store your images on the filesystem, you can change the storage
-path for the Container Registry, follow the steps below.
-
-This path is accessible to:
-
-- The user running the Container Registry daemon.
-- The user running GitLab.
-
-CAUTION: **Warning** You should confirm that all GitLab, Registry and web server users
-have access to this directory.
-
-**Omnibus GitLab installations**
-
-The default location where images are stored in Omnibus, is
-`/var/opt/gitlab/gitlab-rails/shared/registry`. To change it:
-
-1. Edit `/etc/gitlab/gitlab.rb`:
-
- ```ruby
- gitlab_rails['registry_path'] = "/path/to/registry/storage"
- ```
-
-1. Save the file and [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
-
-**Installations from source**
-
-The default location where images are stored in source installations, is
-`/home/git/gitlab/shared/registry`. To change it:
-
-1. Open `/home/git/gitlab/config/gitlab.yml`, find the `registry` entry and
- change the `path` setting:
-
- ```yaml
- registry:
- path: shared/registry
- ```
-
-1. Save the file and [restart GitLab](../restart_gitlab.md#installations-from-source) for the changes to take effect.
-
-## Container Registry storage driver
-
-You can configure the Container Registry to use a different storage backend by
-configuring a different storage driver. By default the GitLab Container Registry
-is configured to use the filesystem driver, which makes use of [storage path](#container-registry-storage-path)
-configuration.
-
-NOTE: **Note:** Enabling a storage driver other than `filesystem` would mean
-that your Docker client needs to be able to access the storage backend directly.
-In that case, you must use an address that resolves and is accessible outside GitLab server.
-
-The different supported drivers are:
-
-| Driver | Description |
-|------------|-------------------------------------|
-| filesystem | Uses a path on the local filesystem |
-| azure | Microsoft Azure Blob Storage |
-| gcs | Google Cloud Storage |
-| s3 | Amazon Simple Storage Service. Be sure to configure your storage bucket with the correct [S3 Permission Scopes](https://docs.docker.com/registry/storage-drivers/s3/#s3-permission-scopes). |
-| swift | OpenStack Swift Object Storage |
-| oss | Aliyun OSS |
-
-Read more about the individual driver's config options in the
-[Docker Registry docs](https://docs.docker.com/registry/configuration/#storage).
-
-CAUTION: **Warning:** GitLab will not backup Docker images that are not stored on the
-filesystem. Remember to enable backups with your object storage provider if
-desired.
-
-NOTE: **Note:**
-`regionendpoint` is only required when configuring an S3 compatible service such as Minio. It takes a URL such as `http://127.0.0.1:9000`.
-
-**Omnibus GitLab installations**
-
-To configure the `s3` storage driver in Omnibus:
-
-1. Edit `/etc/gitlab/gitlab.rb`:
-
- ```ruby
- registry['storage'] = {
- 's3' => {
- 'accesskey' => 's3-access-key',
- 'secretkey' => 's3-secret-key-for-access-key',
- 'bucket' => 'your-s3-bucket',
- 'region' => 'your-s3-region',
- 'regionendpoint' => 'your-s3-regionendpoint'
- }
- }
- ```
-
-1. Save the file and [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
-
-**Installations from source**
-
-Configuring the storage driver is done in your registry config YML file created
-when you [deployed your docker registry](https://docs.docker.com/registry/deploying/).
-
-`s3` storage driver example:
-
-```yml
-storage:
- s3:
- accesskey: 'AKIAKIAKI'
- secretkey: 'secret123'
- bucket: 'gitlab-registry-bucket-AKIAKIAKI'
- region: 'your-s3-region'
- regionendpoint: 'your-s3-regionendpoint'
- cache:
- blobdescriptor: inmemory
- delete:
- enabled: true
-```
-
-## Change the registry's internal port
-
-NOTE: **Note:**
-This is not to be confused with the port that GitLab itself uses to expose
-the Registry to the world.
-
-The Registry server listens on localhost at port `5000` by default,
-which is the address for which the Registry server should accept connections.
-In the examples below we set the Registry's port to `5001`.
-
-**Omnibus GitLab**
-
-1. Open `/etc/gitlab/gitlab.rb` and set `registry['registry_http_addr']`:
-
- ```ruby
- registry['registry_http_addr'] = "localhost:5001"
- ```
-
-1. Save the file and [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
-
-**Installations from source**
-
-1. Open the configuration file of your Registry server and edit the
- [`http:addr`](https://docs.docker.com/registry/configuration/#http) value:
-
- ```yaml
- http
- addr: localhost:5001
- ```
-
-1. Save the file and restart the Registry server.
-
-## Disable Container Registry per project
-
-If Registry is enabled in your GitLab instance, but you don't need it for your
-project, you can disable it from your project's settings. Read the user guide
-on how to achieve that.
-
-## Disable Container Registry but use GitLab as an auth endpoint
-
-**Omnibus GitLab**
-
-You can use GitLab as an auth endpoint and use a non-bundled Container Registry.
-
-1. Open `/etc/gitlab/gitlab.rb` and set necessary configurations:
-
- ```ruby
- gitlab_rails['registry_enabled'] = true
- gitlab_rails['registry_host'] = "registry.gitlab.example.com"
- gitlab_rails['registry_port'] = "5005"
- gitlab_rails['registry_api_url'] = "http://localhost:5000"
- gitlab_rails['registry_path'] = "/var/opt/gitlab/gitlab-rails/shared/registry"
- gitlab_rails['registry_issuer'] = "omnibus-gitlab-issuer"
- ```
-
-1. A certificate keypair is required for GitLab and the Container Registry to
- communicate securely. By default Omnibus GitLab will generate one keypair,
- which is saved to `/var/opt/gitlab/gitlab-rails/etc/gitlab-registry.key`.
- When using a non-bundled Container Registry, you will need to supply a
- custom certificate key. To do that, add the following to
- `/etc/gitlab/gitlab.rb`
-
- ```ruby
- gitlab_rails['registry_key_path'] = "/custom/path/to/registry-key.key"
- # registry['internal_key'] should contain the contents of the custom key
- # file. Line breaks in the key file should be marked using `\n` character
- # Example:
- registry['internal_key'] = "---BEGIN RSA PRIVATE KEY---\nMIIEpQIBAA\n"
- ```
-
- NOTE: **Note:**
- The file specified at `registry_key_path` gets populated with the
- content specified by `internal_key`, each time reconfigure is executed. If
- no file is specified, Omnibus GitLab will default it to
- `/var/opt/gitlab/gitlab-rails/etc/gitlab-registry.key` and will populate
- it.
-
-1. Save the file and [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
-
-**Installations from source**
-
-1. Open `/home/git/gitlab/config/gitlab.yml`, and edit the configuration settings under `registry`:
-
- ```yaml
- ## Container Registry
-
- registry:
- enabled: true
- host: "registry.gitlab.example.com"
- port: "5005"
- api_url: "http://localhost:5000"
- path: /var/opt/gitlab/gitlab-rails/shared/registry
- key: /var/opt/gitlab/gitlab-rails/certificate.key
- issuer: omnibus-gitlab-issuer
- ```
-
-1. Save the file and [restart GitLab](../restart_gitlab.md#installations-from-source) for the changes to take effect.
-
-## Storage limitations
-
-Currently, there is no storage limitation, which means a user can upload an
-infinite amount of Docker images with arbitrary sizes. This setting will be
-configurable in future releases.
-
-## Configure Container Registry notifications
-
-You can configure the Container Registry to send webhook notifications in
-response to events happening within the registry.
-
-Read more about the Container Registry notifications config options in the
-[Docker Registry notifications documentation](https://docs.docker.com/registry/notifications/).
-
-NOTE: **Note:**
-Multiple endpoints can be configured for the Container Registry.
-
-**Omnibus GitLab installations**
-
-To configure a notification endpoint in Omnibus:
-
-1. Edit `/etc/gitlab/gitlab.rb`:
-
- ```ruby
- registry['notifications'] = [
- {
- 'name' => 'test_endpoint',
- 'url' => 'https://gitlab.example.com/notify',
- 'timeout' => '500ms',
- 'threshold' => 5,
- 'backoff' => '1s',
- 'headers' => {
- "Authorization" => ["AUTHORIZATION_EXAMPLE_TOKEN"]
- }
- }
- ]
- ```
-
-1. Save the file and [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
-
-**Installations from source**
-
-Configuring the notification endpoint is done in your registry config YML file created
-when you [deployed your docker registry](https://docs.docker.com/registry/deploying/).
-
-Example:
-
-```yaml
-notifications:
- endpoints:
- - name: alistener
- disabled: false
- url: https://my.listener.com/event
- headers: <http.Header>
- timeout: 500
- threshold: 5
- backoff: 1000
-```
-
-## Troubleshooting
-
-Before diving in to the following sections, here's some basic troubleshooting:
-
-1. Check to make sure that the system clock on your Docker client and GitLab server have
- been synchronized (e.g. via NTP).
-
-1. If you are using an S3-backed Registry, double check that the IAM
- permissions and the S3 credentials (including region) are correct. See [the
- sample IAM policy](https://docs.docker.com/registry/storage-drivers/s3/)
- for more details.
-
-1. Check the Registry logs (e.g. `/var/log/gitlab/registry/current`) and the GitLab production logs
- for errors (e.g. `/var/log/gitlab/gitlab-rails/production.log`). You may be able to find clues
- there.
-
-### Using self-signed certificates with Container Registry
-
-If you're using a self-signed certificate with your Container Registry, you
-might encounter issues during the CI jobs like the following:
-
-```
-Error response from daemon: Get registry.example.com/v1/users/: x509: certificate signed by unknown authority
-```
-
-The Docker daemon running the command expects a cert signed by a recognized CA,
-thus the error above.
-
-While GitLab doesn't support using self-signed certificates with Container
-Registry out of the box, it is possible to make it work by
-[instructing the docker-daemon to trust the self-signed certificates](https://docs.docker.com/registry/insecure/#use-self-signed-certificates),
-mounting the docker-daemon and setting `privileged = false` in the Runner's
-`config.toml`. Setting `privileged = true` takes precedence over the docker-daemon:
-
-```toml
- [runners.docker]
- image = "ruby:2.1"
- privileged = false
- volumes = ["/var/run/docker.sock:/var/run/docker.sock", "/cache"]
-```
-
-Additional information about this: [issue 18239](https://gitlab.com/gitlab-org/gitlab-ce/issues/18239).
-
-### AWS S3 with the GitLab registry error when pushing large images
-
-When using AWS S3 with the GitLab registry, an error may occur when pushing
-large images. Look in the Registry log for the following error:
-
-```
-level=error msg="response completed with error" err.code=unknown err.detail="unexpected EOF" err.message="unknown error"
-```
-
-To resolve the error specify a `chunksize` value in the Registry configuration.
-Start with a value between `25000000` (25MB) and `50000000` (50MB).
-
-**For Omnibus installations**
-
-1. Edit `/etc/gitlab/gitlab.rb`:
-
- ```ruby
- registry['storage'] = {
- 's3' => {
- 'accesskey' => 'AKIAKIAKI',
- 'secretkey' => 'secret123',
- 'bucket' => 'gitlab-registry-bucket-AKIAKIAKI',
- 'chunksize' => 25000000
- }
- }
- ```
-
-1. Save the file and [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
-
-**For installations from source**
-
-1. Edit `config/gitlab.yml`:
-
- ```yaml
- storage:
- s3:
- accesskey: 'AKIAKIAKI'
- secretkey: 'secret123'
- bucket: 'gitlab-registry-bucket-AKIAKIAKI'
- chunksize: 25000000
- ```
-
-1. Save the file and [restart GitLab](../restart_gitlab.md#installations-from-source) for the changes to take effect.
-
-### Supporting older Docker clients
-
-As of GitLab 11.9, we began shipping version 2.7.1 of the Docker container registry, which disables the schema1 manifest by default. If you are still using older Docker clients (1.9 or older), you may experience an error pushing images. See [omnibus-4145](https://gitlab.com/gitlab-org/omnibus-gitlab/issues/4145) for more details.
-
-You can add a configuration option for backwards compatibility.
-
-**For Omnibus installations**
-
-1. Edit `/etc/gitlab/gitlab.rb`:
-
- ```ruby
- registry['compatibility_schema1_enabled'] = true
- ```
-
-1. Save the file and [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
-
-**For installations from source**
-
-1. Edit the YML configuration file you created when you [deployed the registry](https://docs.docker.com/registry/deploying/). Add the following snippet:
-
- ```yaml
- compatibility:
- schema1:
- enabled: true
- ```
-
-1. Restart the registry for the changes to take affect.
-
-### Docker connection error
-
-A Docker connection error can occur when there are special characters in either the group,
-project or branch name. Special characters can include:
-
-- Leading underscore
-- Trailing hyphen/dash
-- Double hyphen/dash
-
-To get around this, you can [change the group path](../../user/group/index.md#changing-a-groups-path),
-[change the project path](../../user/project/settings/index.md#renaming-a-repository) or change the
-branch name. Another option is to create a [push rule](../../push_rules/push_rules.html) to prevent
-this at the instance level.
-
-### Image push errors
-
-When getting errors or "retrying" loops in an attempt to push an image but `docker login` works fine,
-there is likely an issue with the headers forwarded to the registry by NGINX. The default recommended
-NGINX configurations should handle this, but it might occur in custom setups where the SSL is
-offloaded to a third party reverse proxy.
-
-This problem was discussed in a [docker project issue](https://github.com/docker/distribution/issues/970)
-and a simple solution would be to enable relative URLs in the Registry.
-
-**For Omnibus installations**
-
-1. Edit `/etc/gitlab/gitlab.rb`:
-
- ```ruby
- registry['env'] = {
- "REGISTRY_HTTP_RELATIVEURLS" => true
- }
- ```
-
-1. Save the file and [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
-
-**For installations from source**
-
-1. Edit the YML configuration file you created when you [deployed the registry](https://docs.docker.com/registry/deploying/). Add the following snippet:
-
- ```yaml
- http:
- relativeurls: true
- ```
-
-1. Save the file and [restart GitLab](../restart_gitlab.md#installations-from-source) for the changes to take effect.
-
-### Enable the Registry debug server
-
-The optional debug server can be enabled by setting the registry debug address
-in your `gitlab.rb` configuration.
-
-```ruby
-registry['debug_addr'] = "localhost:5001"
-```
-
-After adding the setting, [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) to apply the change.
-
-Use curl to request debug output from the debug server:
-
-```bash
-curl localhost:5001/debug/health
-curl localhost:5001/debug/vars
-```
-
-### Advanced Troubleshooting
-
-NOTE: **Note:**
-The following section is only recommended for experts.
-
-Sometimes it's not obvious what is wrong, and you may need to dive deeper into
-the communication between the Docker client and the Registry to find out
-what's wrong. We will use a concrete example in the past to illustrate how to
-diagnose a problem with the S3 setup.
-
-#### Unexpected 403 error during push
-
-A user attempted to enable an S3-backed Registry. The `docker login` step went
-fine. However, when pushing an image, the output showed:
-
-```text
-The push refers to a repository [s3-testing.myregistry.com:4567/root/docker-test/docker-image]
-dc5e59c14160: Pushing [==================================================>] 14.85 kB
-03c20c1a019a: Pushing [==================================================>] 2.048 kB
-a08f14ef632e: Pushing [==================================================>] 2.048 kB
-228950524c88: Pushing 2.048 kB
-6a8ecde4cc03: Pushing [==> ] 9.901 MB/205.7 MB
-5f70bf18a086: Pushing 1.024 kB
-737f40e80b7f: Waiting
-82b57dbc5385: Waiting
-19429b698a22: Waiting
-9436069b92a3: Waiting
-error parsing HTTP 403 response body: unexpected end of JSON input: ""
-```
-
-This error is ambiguous, as it's not clear whether the 403 is coming from the
-GitLab Rails application, the Docker Registry, or something else. In this
-case, since we know that since the login succeeded, we probably need to look
-at the communication between the client and the Registry.
-
-The REST API between the Docker client and Registry is [described
-here](https://docs.docker.com/registry/spec/api/). Normally, one would just
-use Wireshark or tcpdump to capture the traffic and see where things went
-wrong. However, since all communications between Docker clients and servers
-are done over HTTPS, it's a bit difficult to decrypt the traffic quickly even
-if you know the private key. What can we do instead?
-
-One way would be to disable HTTPS by setting up an [insecure
-Registry](https://docs.docker.com/registry/insecure/). This could introduce a
-security hole and is only recommended for local testing. If you have a
-production system and can't or don't want to do this, there is another way:
-use mitmproxy, which stands for Man-in-the-Middle Proxy.
-
-#### mitmproxy
-
-[mitmproxy](https://mitmproxy.org/) allows you to place a proxy between your
-client and server to inspect all traffic. One wrinkle is that your system
-needs to trust the mitmproxy SSL certificates for this to work.
-
-The following installation instructions assume you are running Ubuntu:
-
-1. [Install mitmproxy](https://docs.mitmproxy.org/stable/overview-installation/).
-1. Run `mitmproxy --port 9000` to generate its certificates.
- Enter <kbd>CTRL</kbd>-<kbd>C</kbd> to quit.
-1. Install the certificate from `~/.mitmproxy` to your system:
-
- ```sh
- sudo cp ~/.mitmproxy/mitmproxy-ca-cert.pem /usr/local/share/ca-certificates/mitmproxy-ca-cert.crt
- sudo update-ca-certificates
- ```
-
-If successful, the output should indicate that a certificate was added:
-
-```sh
-Updating certificates in /etc/ssl/certs... 1 added, 0 removed; done.
-Running hooks in /etc/ca-certificates/update.d....done.
-```
-
-To verify that the certificates are properly installed, run:
-
-```sh
-mitmproxy --port 9000
-```
-
-This will run mitmproxy on port `9000`. In another window, run:
-
-```sh
-curl --proxy http://localhost:9000 https://httpbin.org/status/200
-```
-
-If everything is set up correctly, you will see information on the mitmproxy window and
-no errors from the curl commands.
-
-#### Running the Docker daemon with a proxy
-
-For Docker to connect through a proxy, you must start the Docker daemon with the
-proper environment variables. The easiest way is to shutdown Docker (e.g. `sudo initctl stop docker`)
-and then run Docker by hand. As root, run:
-
-```sh
-export HTTP_PROXY="http://localhost:9000"
-export HTTPS_PROXY="https://localhost:9000"
-docker daemon --debug
-```
-
-This will launch the Docker daemon and proxy all connections through mitmproxy.
-
-#### Running the Docker client
-
-Now that we have mitmproxy and Docker running, we can attempt to login and push
-a container image. You may need to run as root to do this. For example:
-
-```sh
-docker login s3-testing.myregistry.com:4567
-docker push s3-testing.myregistry.com:4567/root/docker-test/docker-image
-```
-
-In the example above, we see the following trace on the mitmproxy window:
-
-![mitmproxy output from Docker](img/mitmproxy-docker.png)
-
-The above image shows:
-
-- The initial PUT requests went through fine with a 201 status code.
-- The 201 redirected the client to the S3 bucket.
-- The HEAD request to the AWS bucket reported a 403 Unauthorized.
-
-What does this mean? This strongly suggests that the S3 user does not have the right
-[permissions to perform a HEAD request](http://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectHEAD.html).
-The solution: check the [IAM permissions again](https://docs.docker.com/registry/storage-drivers/s3/).
-Once the right permissions were set, the error will go away.
diff --git a/doc/administration/packages/dependency_proxy.md b/doc/administration/packages/dependency_proxy.md
deleted file mode 100644
index 967ba2592c3..00000000000
--- a/doc/administration/packages/dependency_proxy.md
+++ /dev/null
@@ -1,148 +0,0 @@
-# GitLab Dependency Proxy administration **(PREMIUM ONLY)**
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/issues/7934) in [GitLab Premium](https://about.gitlab.com/pricing/) 11.11.
-
-GitLab can be utilized as a dependency proxy for a variety of common package managers.
-
-This is the administration documentation. If you want to learn how to use the
-dependency proxies, see the [user guide](../../user/group/dependency_proxy/index.md).
-
-## Enabling the Dependency Proxy feature
-
-NOTE: **Note:**
-Dependency proxy requires the Puma web server to be enabled.
-Puma support is EXPERIMENTAL at this time.
-
-To enable the Dependency proxy feature:
-
-**Omnibus GitLab installations**
-
-1. Edit `/etc/gitlab/gitlab.rb` and add the following line:
-
- ```ruby
- gitlab_rails['dependency_proxy_enabled'] = true
- ```
-
-1. Save the file and [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure "How to reconfigure Omnibus GitLab") for the changes to take effect.
-1. Enable the [Puma web server](https://docs.gitlab.com/omnibus/settings/puma.html).
-
-**Installations from source**
-
-1. After the installation is complete, you will have to configure the `dependency_proxy`
- section in `config/gitlab.yml`. Set to `true` to enable it:
-
- ```yaml
- dependency_proxy:
- enabled: true
- ```
-
-1. [Restart GitLab](../restart_gitlab.md#installations-from-source "How to restart GitLab") for the changes to take effect.
-1. Enable the [Puma web server](../../install/installation.md#using-puma).
-
-## Changing the storage path
-
-By default, the dependency proxy files are stored locally, but you can change the default
-local location or even use object storage.
-
-### Changing the local storage path
-
-The dependency proxy files for Omnibus GitLab installations are stored under
-`/var/opt/gitlab/gitlab-rails/shared/dependency_proxy/` and for source
-installations under `shared/dependency_proxy/` (relative to the Git home directory).
-To change the local storage path:
-
-**Omnibus GitLab installations**
-
-1. Edit `/etc/gitlab/gitlab.rb` and add the following line:
-
- ```ruby
- gitlab_rails['dependency_proxy_storage_path'] = "/mnt/dependency_proxy"
- ```
-
-1. Save the file and [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure "How to reconfigure Omnibus GitLab") for the changes to take effect.
-
-**Installations from source**
-
-1. Edit the `dependency_proxy` section in `config/gitlab.yml`:
-
- ```yaml
- dependency_proxy:
- enabled: true
- storage_path: shared/dependency_proxy
- ```
-
-1. [Restart GitLab](../restart_gitlab.md#installations-from-source "How to restart GitLab") for the changes to take effect.
-
-### Using object storage
-
-Instead of relying on the local storage, you can use an object storage to
-upload the blobs of the dependency proxy:
-
-**Omnibus GitLab installations**
-
-1. Edit `/etc/gitlab/gitlab.rb` and add the following lines (uncomment where
- necessary):
-
- ```ruby
- gitlab_rails['dependency_proxy_enabled'] = true
- gitlab_rails['dependency_proxy_storage_path'] = "/var/opt/gitlab/gitlab-rails/shared/dependency_proxy"
- gitlab_rails['dependency_proxy_object_store_enabled'] = true
- gitlab_rails['dependency_proxy_object_store_remote_directory'] = "dependency_proxy" # The bucket name.
- gitlab_rails['dependency_proxy_object_store_direct_upload'] = false # Use Object Storage directly for uploads instead of background uploads if enabled (Default: false).
- gitlab_rails['dependency_proxy_object_store_background_upload'] = true # Temporary option to limit automatic upload (Default: true).
- gitlab_rails['dependency_proxy_object_store_proxy_download'] = false # Passthrough all downloads via GitLab instead of using Redirects to Object Storage.
- gitlab_rails['dependency_proxy_object_store_connection'] = {
- ##
- ## If the provider is AWS S3, uncomment the following
- ##
- #'provider' => 'AWS',
- #'region' => 'eu-west-1',
- #'aws_access_key_id' => 'AWS_ACCESS_KEY_ID',
- #'aws_secret_access_key' => 'AWS_SECRET_ACCESS_KEY',
- ##
- ## If the provider is other than AWS (an S3-compatible one), uncomment the following
- ##
- #'host' => 's3.amazonaws.com',
- #'aws_signature_version' => 4 # For creation of signed URLs. Set to 2 if provider does not support v4.
- #'endpoint' => 'https://s3.amazonaws.com' # Useful for S3-compliant services such as DigitalOcean Spaces.
- #'path_style' => false # If true, use 'host/bucket_name/object' instead of 'bucket_name.host/object'.
- }
- ```
-
-1. Save the file and [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure "How to reconfigure Omnibus GitLab") for the changes to take effect.
-
-**Installations from source**
-
-1. Edit the `dependency_proxy` section in `config/gitlab.yml` (uncomment where necessary):
-
- ```yaml
- dependency_proxy:
- enabled: true
- ##
- ## The location where build dependency_proxy are stored (default: shared/dependency_proxy).
- ##
- #storage_path: shared/dependency_proxy
- object_store:
- enabled: false
- remote_directory: dependency_proxy # The bucket name.
- #direct_upload: false # Use Object Storage directly for uploads instead of background uploads if enabled (Default: false).
- #background_upload: true # Temporary option to limit automatic upload (Default: true).
- #proxy_download: false # Passthrough all downloads via GitLab instead of using Redirects to Object Storage.
- connection:
- ##
- ## If the provider is AWS S3, uncomment the following
- ##
- #provider: AWS
- #region: us-east-1
- #aws_access_key_id: AWS_ACCESS_KEY_ID
- #aws_secret_access_key: AWS_SECRET_ACCESS_KEY
- ##
- ## If the provider is other than AWS (an S3-compatible one), uncomment the following
- ##
- #host: 's3.amazonaws.com' # default: s3.amazonaws.com.
- #aws_signature_version: 4 # For creation of signed URLs. Set to 2 if provider does not support v4.
- #endpoint: 'https://s3.amazonaws.com' # Useful for S3-compliant services such as DigitalOcean Spaces.
- #path_style: false # If true, use 'host/bucket_name/object' instead of 'bucket_name.host/object'.
- ```
-
-1. [Restart GitLab](../restart_gitlab.md#installations-from-source "How to restart GitLab") for the changes to take effect.
diff --git a/doc/administration/packages/index.md b/doc/administration/packages/index.md
deleted file mode 100644
index 99ec5811681..00000000000
--- a/doc/administration/packages/index.md
+++ /dev/null
@@ -1,175 +0,0 @@
-# GitLab Package Registry administration **(PREMIUM ONLY)**
-
-GitLab Packages allows organizations to utilize GitLab as a private repository
-for a variety of common package managers. Users are able to build and publish
-packages, which can be easily consumed as a dependency in downstream projects.
-
-The Packages feature allows GitLab to act as a repository for the following:
-
-| Software repository | Description | Available in GitLab version |
-| ------------------- | ----------- | --------------------------- |
-| [Maven Repository](../../user/packages/maven_repository/index.md) | The GitLab Maven Repository enables every project in GitLab to have its own space to store [Maven](https://maven.apache.org/) packages. | 11.3+ |
-| [NPM Registry](../../user/packages/npm_registry/index.md) | The GitLab NPM Registry enables every project in GitLab to have its own space to store [NPM](https://www.npmjs.com/) packages. | 11.7+ |
-
-Don't you see your package management system supported yet?
-Please consider contributing
-to GitLab. This [development documentation](../../development/packages.md) will guide you through the process.
-
-## Enabling the Packages feature
-
-NOTE: **Note:**
-After the Packages feature is enabled, the repositories are available
-for all new projects by default. To enable it for existing projects, users will
-have to explicitly do so in the project's settings.
-
-To enable the Packages feature:
-
-**Omnibus GitLab installations**
-
-1. Edit `/etc/gitlab/gitlab.rb` and add the following line:
-
- ```ruby
- gitlab_rails['packages_enabled'] = true
- ```
-
-1. Save the file and [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure "How to reconfigure Omnibus GitLab") for the changes to take effect.
-
-**Installations from source**
-
-1. After the installation is complete, you will have to configure the `packages`
- section in `config/gitlab.yml`. Set to `true` to enable it:
-
- ```yaml
- packages:
- enabled: true
- ```
-
-1. [Restart GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure "How to reconfigure Omnibus GitLab") for the changes to take effect.
-
-## Changing the storage path
-
-By default, the packages are stored locally, but you can change the default
-local location or even use object storage.
-
-### Changing the local storage path
-
-The packages for Omnibus GitLab installations are stored under
-`/var/opt/gitlab/gitlab-rails/shared/packages/` and for source
-installations under `shared/packages/` (relative to the Git homedir).
-To change the local storage path:
-
-**Omnibus GitLab installations**
-
-1. Edit `/etc/gitlab/gitlab.rb` and add the following line:
-
- ```ruby
- gitlab_rails['packages_storage_path'] = "/mnt/packages"
- ```
-
-1. Save the file and [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure)
- for the changes to take effect.
-
-**Installations from source**
-
-1. Edit the `packages` section in `config/gitlab.yml`:
-
- ```yaml
- packages:
- enabled: true
- storage_path: shared/packages
- ```
-
-1. Save the file and [restart GitLab](../restart_gitlab.md#installations-from-source) for the changes to take effect.
-
-### Using object storage
-
-Instead of relying on the local storage, you can use an object storage to
-upload packages:
-
-**Omnibus GitLab installations**
-
-1. Edit `/etc/gitlab/gitlab.rb` and add the following lines (uncomment where
- necessary):
-
- ```ruby
- gitlab_rails['packages_enabled'] = true
- gitlab_rails['packages_storage_path'] = "/var/opt/gitlab/gitlab-rails/shared/packages"
- gitlab_rails['packages_object_store_enabled'] = true
- gitlab_rails['packages_object_store_remote_directory'] = "packages" # The bucket name.
- gitlab_rails['packages_object_store_direct_upload'] = false # Use Object Storage directly for uploads instead of background uploads if enabled (Default: false).
- gitlab_rails['packages_object_store_background_upload'] = true # Temporary option to limit automatic upload (Default: true).
- gitlab_rails['packages_object_store_proxy_download'] = false # Passthrough all downloads via GitLab instead of using Redirects to Object Storage.
- gitlab_rails['packages_object_store_connection'] = {
- ##
- ## If the provider is AWS S3, uncomment the following
- ##
- #'provider' => 'AWS',
- #'region' => 'eu-west-1',
- #'aws_access_key_id' => 'AWS_ACCESS_KEY_ID',
- #'aws_secret_access_key' => 'AWS_SECRET_ACCESS_KEY',
- ##
- ## If the provider is other than AWS (an S3-compatible one), uncomment the following
- ##
- #'host' => 's3.amazonaws.com',
- #'aws_signature_version' => 4 # For creation of signed URLs. Set to 2 if provider does not support v4.
- #'endpoint' => 'https://s3.amazonaws.com' # Useful for S3-compliant services such as DigitalOcean Spaces.
- #'path_style' => false # If true, use 'host/bucket_name/object' instead of 'bucket_name.host/object'.
- }
- ```
-
-1. Save the file and [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure)
- for the changes to take effect.
-
-**Installations from source**
-
-1. Edit the `packages` section in `config/gitlab.yml` (uncomment where necessary):
-
- ```yaml
- packages:
- enabled: true
- ##
- ## The location where build packages are stored (default: shared/packages).
- ##
- #storage_path: shared/packages
- object_store:
- enabled: false
- remote_directory: packages # The bucket name.
- #direct_upload: false # Use Object Storage directly for uploads instead of background uploads if enabled (Default: false).
- #background_upload: true # Temporary option to limit automatic upload (Default: true).
- #proxy_download: false # Passthrough all downloads via GitLab instead of using Redirects to Object Storage.
- connection:
- ##
- ## If the provider is AWS S3, uncomment the following
- ##
- #provider: AWS
- #region: us-east-1
- #aws_access_key_id: AWS_ACCESS_KEY_ID
- #aws_secret_access_key: AWS_SECRET_ACCESS_KEY
- ##
- ## If the provider is other than AWS (an S3-compatible one), uncomment the following
- ##
- #host: 's3.amazonaws.com' # default: s3.amazonaws.com.
- #aws_signature_version: 4 # For creation of signed URLs. Set to 2 if provider does not support v4.
- #endpoint: 'https://s3.amazonaws.com' # Useful for S3-compliant services such as DigitalOcean Spaces.
- #path_style: false # If true, use 'host/bucket_name/object' instead of 'bucket_name.host/object'.
- ```
-
-1. Save the file and [restart GitLab](../restart_gitlab.md#installations-from-source) for the changes to take effect.
-
-### Migrating local packages to object storage
-
-After [configuring the object storage](#using-object-storage), you may use the
-following task to migrate existing packages from the local storage to the remote one.
-The processing will be done in a background worker and requires **no downtime**.
-
-For Omnibus GitLab:
-
-```sh
-sudo gitlab-rake "gitlab:packages:migrate"
-```
-
-For installations from source:
-
-```bash
-RAILS_ENV=production sudo -u git -H bundle exec rake gitlab:packages:migrate
-```
diff --git a/doc/api/container_registry.md b/doc/api/container_registry.md
index 0957b502340..bf544f64178 100644
--- a/doc/api/container_registry.md
+++ b/doc/api/container_registry.md
@@ -2,7 +2,7 @@
> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/issues/55978) in GitLab 11.8.
-This is the API docs of the [GitLab Container Registry](../user/packages/container_registry/index.md).
+This is the API docs of the [GitLab Container Registry](../user/project/container_registry.md).
## List registry repositories
diff --git a/doc/api/epics.md b/doc/api/epics.md
index d6b22c3dc54..675b88649e0 100644
--- a/doc/api/epics.md
+++ b/doc/api/epics.md
@@ -49,8 +49,6 @@ GET /groups/:id/epics?state=opened
| `created_before` | datetime | no | Return epics created on or before the given time |
| `updated_after` | datetime | no | Return epics updated on or after the given time |
| `updated_before` | datetime | no | Return epics updated on or before the given time |
-| `include_ancestor_groups` | boolean | no | Include epics from the requested group's ancestors. Default is `false` |
-| `include_descendant_groups` | boolean | no | Include epics from the requested group's descendants. Default is `true` |
```bash
curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/groups/1/epics
diff --git a/doc/api/groups.md b/doc/api/groups.md
index 18e71f488ce..8b13462b887 100644
--- a/doc/api/groups.md
+++ b/doc/api/groups.md
@@ -208,7 +208,7 @@ Example response:
## Details of a group
Get all details of a group. This endpoint can be accessed without authentication
-if the group is publicly accessible. In case the user that requests is admin of the group, it will return the `runners_token` for the group too.
+if the group is publicly accessible.
```
GET /groups/:id
@@ -240,7 +240,6 @@ Example response:
"request_access_enabled": false,
"full_name": "Twitter",
"full_path": "twitter",
- "runners_token": "ba324ca7b1c77fc20bb9",
"file_template_project_id": 1,
"parent_id": null,
"projects": [
diff --git a/doc/api/issues.md b/doc/api/issues.md
index a991baef230..a89a6e7c5cc 100644
--- a/doc/api/issues.md
+++ b/doc/api/issues.md
@@ -57,8 +57,7 @@ GET /issues?confidential=true
| `created_before` | datetime | no | Return issues created on or before the given time |
| `updated_after` | datetime | no | Return issues updated on or after the given time |
| `updated_before` | datetime | no | Return issues updated on or before the given time |
-| `confidential` | Boolean | no | Filter confidential or public issues. |
-| `not` | Hash | no | Return issues that do not match the parameters supplied. Accepts: `labels`, `milestone`, `author_id`, `author_username`, `assignee_id`, `assignee_username`, `my_reaction_emoji`, `search`, `in` |
+| `confidential` | Boolean | no | Filter confidential or public issues. |
```bash
curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/issues
@@ -207,7 +206,6 @@ GET /groups/:id/issues?confidential=true
| `updated_after` | datetime | no | Return issues updated on or after the given time |
| `updated_before` | datetime | no | Return issues updated on or before the given time |
| `confidential` | Boolean | no | Filter confidential or public issues. |
-| `not` | Hash | no | Return issues that do not match the parameters supplied. Accepts: `labels`, `milestone`, `author_id`, `author_username`, `assignee_id`, `assignee_username`, `my_reaction_emoji`, `search`, `in` |
```bash
curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/groups/4/issues
@@ -356,7 +354,6 @@ GET /projects/:id/issues?confidential=true
| `updated_after` | datetime | no | Return issues updated on or after the given time |
| `updated_before` | datetime | no | Return issues updated on or before the given time |
| `confidential` | Boolean | no | Filter confidential or public issues. |
-| `not` | Hash | no | Return issues that do not match the parameters supplied. Accepts: `labels`, `milestone`, `author_id`, `author_username`, `assignee_id`, `assignee_username`, `my_reaction_emoji`, `search`, `in` |
```bash
curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/4/issues
diff --git a/doc/api/packages.md b/doc/api/packages.md
index c852be0ad7b..ca90771b085 100644
--- a/doc/api/packages.md
+++ b/doc/api/packages.md
@@ -1,6 +1,6 @@
# Packages API **(PREMIUM)**
-This is the API docs of [GitLab Packages](../administration/packages/index.md).
+This is the API docs of [GitLab Packages](../administration/packages.md).
## List project packages
diff --git a/doc/api/projects.md b/doc/api/projects.md
index 7617620e52d..3ea1434d5ca 100644
--- a/doc/api/projects.md
+++ b/doc/api/projects.md
@@ -991,9 +991,6 @@ POST /projects/user/:user_id
| `external_authorization_classification_label` | string | no | **(PREMIUM)** The classification label for the project |
| `mirror` | boolean | no | **(STARTER)** Enables pull mirroring in a project |
| `mirror_trigger_builds` | boolean | no | **(STARTER)** Pull mirroring triggers builds |
-| `template_name` | string | no | When used without `use_custom_template`, name of a [built-in project template](../gitlab-basics/create-project.md#built-in-templates). When used with `use_custom_template`, name of a custom project template |
-| `use_custom_template` | boolean | no | **(PREMIUM)** Use either custom [instance](../user/admin_area/custom_project_templates.md) or [group](../user/group/custom_project_templates.md) (with `group_with_project_templates_id`) project template |
-| `group_with_project_templates_id` | integer | no | **(PREMIUM)** For group-level custom templates, specifies ID of group from which all the custom project templates are sourced. Leave empty for instance-level templates. Requires `use_custom_template` to be true |
NOTE: **Note:** If your HTTP repository is not publicly accessible,
add authentication information to the URL: `https://username:password@gitlab.company.com/group/project.git`
diff --git a/doc/api/releases/index.md b/doc/api/releases/index.md
index 4279821d8ed..8d5b3a65789 100644
--- a/doc/api/releases/index.md
+++ b/doc/api/releases/index.md
@@ -57,34 +57,19 @@ Example response:
"committer_email":"admin@example.com",
"committed_date":"2019-01-03T01:55:38.000Z"
},
- "milestones": [
- {
- "id":51,
- "iid":1,
- "project_id":24,
- "title":"v1.0-rc",
- "description":"Voluptate fugiat possimus quis quod aliquam expedita.",
- "state":"closed",
- "created_at":"2019-07-12T19:45:44.256Z",
- "updated_at":"2019-07-12T19:45:44.256Z",
- "due_date":"2019-08-16T11:00:00.256Z",
- "start_date":"2019-07-30T12:00:00.256Z",
- "web_url":"https://gitlab.example.com/root/awesome-app/-/milestones/1"
- },
- {
- "id":52,
- "iid":2,
- "project_id":24,
- "title":"v1.0",
- "description":"Voluptate fugiat possimus quis quod aliquam expedita.",
- "state":"closed",
- "created_at":"2019-07-16T14:00:12.256Z",
- "updated_at":"2019-07-16T14:00:12.256Z",
- "due_date":"2019-08-16T11:00:00.256Z",
- "start_date":"2019-07-30T12:00:00.256Z",
- "web_url":"https://gitlab.example.com/root/awesome-app/-/milestones/2"
- }
- ],
+ "milestone":{
+ "id":51,
+ "iid":1,
+ "project_id":24,
+ "title":"v1.0-rc",
+ "description":"Voluptate fugiat possimus quis quod aliquam expedita.",
+ "state":"closed",
+ "created_at":"2019-07-12T19:45:44.256Z",
+ "updated_at":"2019-07-12T19:45:44.256Z",
+ "due_date":"2019-08-16T11:00:00.256Z",
+ "start_date":"2019-07-30T12:00:00.256Z",
+ "web_url":"http://localhost:3000/root/awesome-app/-/milestones/1"
+ },
"assets":{
"count":6,
"sources":[
@@ -233,34 +218,19 @@ Example response:
"committer_email":"admin@example.com",
"committed_date":"2019-01-03T01:53:28.000Z"
},
- "milestones": [
- {
- "id":51,
- "iid":1,
- "project_id":24,
- "title":"v1.0-rc",
- "description":"Voluptate fugiat possimus quis quod aliquam expedita.",
- "state":"closed",
- "created_at":"2019-07-12T19:45:44.256Z",
- "updated_at":"2019-07-12T19:45:44.256Z",
- "due_date":"2019-08-16T11:00:00.256Z",
- "start_date":"2019-07-30T12:00:00.256Z",
- "web_url":"https://gitlab.example.com/root/awesome-app/-/milestones/1"
- },
- {
- "id":52,
- "iid":2,
- "project_id":24,
- "title":"v1.0",
- "description":"Voluptate fugiat possimus quis quod aliquam expedita.",
- "state":"closed",
- "created_at":"2019-07-16T14:00:12.256Z",
- "updated_at":"2019-07-16T14:00:12.256Z",
- "due_date":"2019-08-16T11:00:00.256Z",
- "start_date":"2019-07-30T12:00:00.256Z",
- "web_url":"https://gitlab.example.com/root/awesome-app/-/milestones/2"
- }
- ],
+ "milestone":{
+ "id":51,
+ "iid":1,
+ "project_id":24,
+ "title":"v1.0-rc",
+ "description":"Voluptate fugiat possimus quis quod aliquam expedita.",
+ "state":"closed",
+ "created_at":"2019-07-12T19:45:44.256Z",
+ "updated_at":"2019-07-12T19:45:44.256Z",
+ "due_date":"2019-08-16T11:00:00.256Z",
+ "start_date":"2019-07-30T12:00:00.256Z",
+ "web_url":"http://localhost:3000/root/awesome-app/-/milestones/1"
+ },
"assets":{
"count":4,
"sources":[
@@ -303,7 +273,7 @@ POST /projects/:id/releases
| `tag_name` | string | yes | The tag where the release will be created from. |
| `description` | string | yes | The description of the release. You can use [markdown](../../user/markdown.md). |
| `ref` | string | no | If `tag_name` doesn't exist, the release will be created from `ref`. It can be a commit SHA, another tag name, or a branch name. |
-| `milestones` | array of string | no | The title of each milestone the release is associated with. |
+| `milestone` | string | no | The title of the milestone the release is associated with. |
| `assets:links` | array of hash | no | An array of assets links. |
| `assets:links:name`| string | required by: `assets:links` | The name of the link. |
| `assets:links:url` | string | required by: `assets:links` | The url of the link. |
@@ -313,7 +283,7 @@ Example request:
```sh
curl --header 'Content-Type: application/json' --header "PRIVATE-TOKEN: gDybLx3yrUK_HLp3qPjS" \
- --data '{ "name": "New release", "tag_name": "v0.3", "description": "Super nice release", "milestones": ["v1.0", "v1.0-rc"], "assets": { "links": [{ "name": "hoge", "url": "https://google.com" }] } }' \
+ --data '{ "name": "New release", "tag_name": "v0.3", "description": "Super nice release", "milestone": "v1.0-rc", "assets": { "links": [{ "name": "hoge", "url": "https://google.com" }] } }' \
--request POST https://gitlab.example.com/api/v4/projects/24/releases
```
@@ -351,34 +321,19 @@ Example response:
"committer_email":"admin@example.com",
"committed_date":"2019-01-03T01:55:38.000Z"
},
- "milestones": [
- {
- "id":51,
- "iid":1,
- "project_id":24,
- "title":"v1.0-rc",
- "description":"Voluptate fugiat possimus quis quod aliquam expedita.",
- "state":"closed",
- "created_at":"2019-07-12T19:45:44.256Z",
- "updated_at":"2019-07-12T19:45:44.256Z",
- "due_date":"2019-08-16T11:00:00.256Z",
- "start_date":"2019-07-30T12:00:00.256Z",
- "web_url":"https://gitlab.example.com/root/awesome-app/-/milestones/1"
- },
- {
- "id":52,
- "iid":2,
- "project_id":24,
- "title":"v1.0",
- "description":"Voluptate fugiat possimus quis quod aliquam expedita.",
- "state":"closed",
- "created_at":"2019-07-16T14:00:12.256Z",
- "updated_at":"2019-07-16T14:00:12.256Z",
- "due_date":"2019-08-16T11:00:00.256Z",
- "start_date":"2019-07-30T12:00:00.256Z",
- "web_url":"https://gitlab.example.com/root/awesome-app/-/milestones/2"
- }
- ],
+ "milestone":{
+ "id":51,
+ "iid":1,
+ "project_id":24,
+ "title":"v1.0-rc",
+ "description":"Voluptate fugiat possimus quis quod aliquam expedita.",
+ "state":"active",
+ "created_at":"2019-07-12T19:45:44.256Z",
+ "updated_at":"2019-07-12T19:45:44.256Z",
+ "due_date":"2019-08-16T11:00:00.256Z",
+ "start_date":"2019-07-30T12:00:00.256Z",
+ "web_url":"http://localhost:3000/root/awesome-app/-/milestones/1"
+ },
"assets":{
"count":5,
"sources":[
@@ -419,19 +374,19 @@ Update a Release.
PUT /projects/:id/releases/:tag_name
```
-| Attribute | Type | Required | Description |
-| ------------- | --------------- | -------- | ----------------------------------------------------------------------------------------------------------- |
-| `id` | integer/string | yes | The ID or [URL-encoded path of the project](../README.md#namespaced-path-encoding). |
-| `tag_name` | string | yes | The tag where the release will be created from. |
-| `name` | string | no | The release name. |
-| `description` | string | no | The description of the release. You can use [markdown](../../user/markdown.md). |
-| `milestones` | array of string | no | The title of each milestone to associate with the release (`[]` to remove all milestones from the release). |
-| `released_at` | datetime | no | The date when the release will be/was ready. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`). |
+| Attribute | Type | Required | Description |
+| ------------- | -------------- | -------- | --------------------------------------------------------------------------------------------------------- |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](../README.md#namespaced-path-encoding). |
+| `tag_name` | string | yes | The tag where the release will be created from. |
+| `name` | string | no | The release name. |
+| `description` | string | no | The description of the release. You can use [markdown](../../user/markdown.md). |
+| `milestone` | string | no | The title of the milestone to associate with the release (`""` to remove the milestone from the release). |
+| `released_at` | datetime | no | The date when the release will be/was ready. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`). |
Example request:
```sh
-curl --header 'Content-Type: application/json' --request PUT --data '{"name": "new name", "milestones": ["v1.2"]}' --header "PRIVATE-TOKEN: gDybLx3yrUK_HLp3qPjS" "https://gitlab.example.com/api/v4/projects/24/releases/v0.1"
+curl --header 'Content-Type: application/json' --request PUT --data '{"name": "new name", "milestone": "v1.0"}' --header "PRIVATE-TOKEN: gDybLx3yrUK_HLp3qPjS" "https://gitlab.example.com/api/v4/projects/24/releases/v0.1"
```
Example response:
@@ -468,21 +423,19 @@ Example response:
"committer_email":"admin@example.com",
"committed_date":"2019-01-03T01:53:28.000Z"
},
- "milestones": [
- {
- "id":53,
- "iid":3,
- "project_id":24,
- "title":"v1.0",
- "description":"Voluptate fugiat possimus quis quod aliquam expedita.",
- "state":"active",
- "created_at":"2019-09-01T13:00:00.256Z",
- "updated_at":"2019-09-01T13:00:00.256Z",
- "due_date":"2019-09-20T13:00:00.256Z",
- "start_date":"2019-09-05T12:00:00.256Z",
- "web_url":"https://gitlab.example.com/root/awesome-app/-/milestones/3"
- }
- ],
+ "milestone":{
+ "id":53,
+ "iid":2,
+ "project_id":24,
+ "title":"v1.0",
+ "description":"Voluptate fugiat possimus quis quod aliquam expedita.",
+ "state":"active",
+ "created_at":"2019-09-01T13:00:00.256Z",
+ "updated_at":"2019-09-01T13:00:00.256Z",
+ "due_date":"2019-09-20T13:00:00.256Z",
+ "start_date":"2019-09-05T12:00:00.256Z",
+ "web_url":"http://localhost:3000/root/awesome-app/-/milestones/3"
+ },
"assets":{
"count":4,
"sources":[
diff --git a/doc/api/settings.md b/doc/api/settings.md
index 39fc848b272..4ad4ebdacb6 100644
--- a/doc/api/settings.md
+++ b/doc/api/settings.md
@@ -220,6 +220,7 @@ are listed in the descriptions of the relevant settings.
| `elasticsearch_aws` | boolean | no | **(PREMIUM)** Enable the use of AWS hosted Elasticsearch |
| `elasticsearch_aws_region` | string | no | **(PREMIUM)** The AWS region the elasticsearch domain is configured |
| `elasticsearch_aws_secret_access_key` | string | no | **(PREMIUM)** AWS IAM secret access key |
+| `elasticsearch_experimental_indexer` | boolean | no | **(PREMIUM)** Use the experimental elasticsearch indexer. More info: <https://gitlab.com/gitlab-org/gitlab-elasticsearch-indexer> |
| `elasticsearch_indexing` | boolean | no | **(PREMIUM)** Enable Elasticsearch indexing |
| `elasticsearch_limit_indexing` | boolean | no | **(PREMIUM)** Limit Elasticsearch to index certain namespaces and projects |
| `elasticsearch_namespace_ids` | array of integers | no | **(PREMIUM)** The namespaces to index via Elasticsearch if `elasticsearch_limit_indexing` is enabled. |
diff --git a/doc/ci/docker/using_docker_build.md b/doc/ci/docker/using_docker_build.md
index 93317d310db..4da527154ad 100644
--- a/doc/ci/docker/using_docker_build.md
+++ b/doc/ci/docker/using_docker_build.md
@@ -515,7 +515,7 @@ If you're running multiple Runners you will have to modify all configuration fil
> login to GitLab's Container Registry.
Once you've built a Docker image, you can push it up to the built-in
-[GitLab Container Registry](../../user/packages/container_registry/index.md).
+[GitLab Container Registry](../../user/project/container_registry.md).
Some things you should be aware of:
- You must [log in to the container registry](#authenticating-to-the-container-registry)
diff --git a/doc/ci/docker/using_kaniko.md b/doc/ci/docker/using_kaniko.md
index 0d78e1f6953..925653f9fdf 100644
--- a/doc/ci/docker/using_kaniko.md
+++ b/doc/ci/docker/using_kaniko.md
@@ -43,7 +43,7 @@ few important details:
In the following example, kaniko is used to:
1. Build a Docker image.
-1. Then push it to [GitLab Container Registry](../../user/packages/container_registry/index.md).
+1. Then push it to [GitLab Container Registry](../../user/project/container_registry.md).
The job will run only when a tag is pushed. A `config.json` file is created under
`/kaniko/.docker` with the needed GitLab Container Registry credentials taken from the
diff --git a/doc/ci/environments.md b/doc/ci/environments.md
index 32f9ab2205a..b41fd7971d6 100644
--- a/doc/ci/environments.md
+++ b/doc/ci/environments.md
@@ -679,7 +679,7 @@ fetch = +refs/environments/*:refs/remotes/origin/environments/*
### Scoping environments with specs
> - [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/2112) in [GitLab Premium](https://about.gitlab.com/pricing/) 9.4.
-> - [Scoping for environment variables was moved to Core](https://gitlab.com/gitlab-org/gitlab-foss/merge_requests/30779) in GitLab 12.2.
+> - [Moved](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/30779) to Core in Gitlab 12.2.
You can limit the environment scope of a variable by
defining which environments it can be available for.
diff --git a/doc/ci/examples/laravel_with_gitlab_and_envoy/index.md b/doc/ci/examples/laravel_with_gitlab_and_envoy/index.md
index d79821ff258..808e4285f2f 100644
--- a/doc/ci/examples/laravel_with_gitlab_and_envoy/index.md
+++ b/doc/ci/examples/laravel_with_gitlab_and_envoy/index.md
@@ -437,7 +437,7 @@ We used `docker-php-ext-install` (provided by the official PHP Docker image) to
#### Setting Up GitLab Container Registry
-Now that we have our `Dockerfile` let's build and push it to our [GitLab Container Registry](../../../user/packages/container_registry/index.md).
+Now that we have our `Dockerfile` let's build and push it to our [GitLab Container Registry](../../../user/project/container_registry.md).
> The registry is the place to store and tag images for later use. Developers may want to maintain their own registry for private, company images, or for throw-away images used only in testing. Using GitLab Container Registry means you don't need to set up and administer yet another service or use a public registry.
@@ -445,7 +445,7 @@ On your GitLab project repository navigate to the **Registry** tab.
![container registry page empty image](img/container_registry_page_empty_image.png)
-You may need to [enable Container Registry](../../../user/packages/container_registry/index.md#enable-the-container-registry-for-your-project) to your project to see this tab. You'll find it under your project's **Settings > General > Permissions**.
+You may need to [enable Container Registry](../../../user/project/container_registry.md#enable-the-container-registry-for-your-project) to your project to see this tab. You'll find it under your project's **Settings > General > Permissions**.
To start using Container Registry on our machine, we first need to login to the GitLab registry using our GitLab username and password:
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
new file mode 100644
index 00000000000..a0874f66eaa
--- /dev/null
+++ b/doc/ci/introduction/img/gitlab_workflow_example_extended_11_11.png
Binary files differ
diff --git a/doc/ci/introduction/img/gitlab_workflow_example_extended_v12_3.png b/doc/ci/introduction/img/gitlab_workflow_example_extended_v12_3.png
deleted file mode 100644
index 6e1066d4868..00000000000
--- a/doc/ci/introduction/img/gitlab_workflow_example_extended_v12_3.png
+++ /dev/null
Binary files differ
diff --git a/doc/ci/introduction/index.md b/doc/ci/introduction/index.md
index b15978a0aaa..366aca3442e 100644
--- a/doc/ci/introduction/index.md
+++ b/doc/ci/introduction/index.md
@@ -174,7 +174,7 @@ If we take a deeper look into the basic workflow, we can see
the features available in GitLab at each stage of the DevOps
lifecycle, as shown on the illustration below.
-![Deeper look into the basic CI/CD workflow](img/gitlab_workflow_example_extended_v12_3.png)
+![Deeper look into the basic CI/CD workflow](img/gitlab_workflow_example_extended_11_11.png)
If you look at the image from the left to the right,
you'll see some of the features available in GitLab
@@ -187,9 +187,9 @@ according to each stage (Verify, Package, Release).
- Perform a series of tests, such as [Container Scanning](../../user/application_security/container_scanning/index.md) **(ULTIMATE)**, [Dependency Scanning](../../user/application_security/dependency_scanning/index.md) **(ULTIMATE)**, and [JUnit tests](../junit_test_reports.md).
- Deploy your changes with [Review Apps](../review_apps/index.md) to preview the app changes on every branch.
1. **Package**:
- - Store Docker images with [Container Registry](../../user/packages/container_registry/index.md).
- - Store NPM packages with [NPM Registry](../../user/packages/npm_registry/index.md). **(PREMIUM)**
- - Store Maven artifacts with [Maven Repository](../../user/packages/maven_repository/index.md). **(PREMIUM)**
+ - Store Docker images with [Container Registry](../../user/project/container_registry.md).
+ - Store NPM packages with [NPM Registry](../../user/project/packages/npm_registry.md). **(PREMIUM)**
+ - Store Maven artifacts with [Maven Repository](../../user/project/packages/maven_repository.md). **(PREMIUM)**
1. **Release**:
- Continuous Deployment, automatically deploying your app to production.
- Continuous Delivery, manually click to deploy your app to production.
diff --git a/doc/ci/jenkins/index.md b/doc/ci/jenkins/index.md
index 29eba5ea928..ace1204511e 100644
--- a/doc/ci/jenkins/index.md
+++ b/doc/ci/jenkins/index.md
@@ -27,7 +27,7 @@ There are some high level differences between the products worth mentioning:
- The `.gitlab-ci.yml` file is checked in to the root of your repository, much like a Jenkinsfile, but
is in the YAML format (see [complete reference](../yaml/README.md)) instead of a Groovy DSL. It's most
analagous to the declarative Jenkinsfile format.
-- GitLab comes with a [container registry](../../user/packages/container_registry/index.md), and we recommend using
+- GitLab comes with a [container registry](../../user/project/container_registry.md), and we recommend using
container images to set up your build environment.
## Groovy vs. YAML
@@ -209,7 +209,7 @@ Because GitLab is integrated tightly with git, SCM polling options for triggers
GitLab does not support a separate `tools` directive. Our best-practice reccomendation is to use pre-built
container images, which can be cached, and can be built to already contain the tools you need for your pipelines. Pipelines can
-be set up to automatically build these images as needed and deploy them to the [container registry](../../user/packages/container_registry/index.md).
+be set up to automatically build these images as needed and deploy them to the [container registry](../../user/project/container_registry.md).
If you're not using container images with Docker/Kubernetes, for example on Mac or FreeBSD, then the `shell` executor does require you to
set up your environment either in advance or as part of the jobs. You could create a `before_script`
diff --git a/doc/ci/triggers/README.md b/doc/ci/triggers/README.md
index 4e486af9b29..f62a4660713 100644
--- a/doc/ci/triggers/README.md
+++ b/doc/ci/triggers/README.md
@@ -277,6 +277,6 @@ removed with one of the future versions of GitLab.
[ee]: https://about.gitlab.com/pricing/
[variables]: ../variables/README.md
[predef]: ../variables/README.md#predefined-environment-variables
-[registry]: ../../user/packages/container_registry/index.md
+[registry]: ../../user/project/container_registry.md
[permissions]: ../../user/permissions.md#job-permissions
[trigapi]: ../../api/pipeline_triggers.md
diff --git a/doc/ci/variables/predefined_variables.md b/doc/ci/variables/predefined_variables.md
index e3ff3385f97..5a8de3dd4d1 100644
--- a/doc/ci/variables/predefined_variables.md
+++ b/doc/ci/variables/predefined_variables.md
@@ -126,5 +126,5 @@ future GitLab releases.**
| `GITLAB_FEATURES` | 10.6 | all | The comma separated list of licensed features available for your instance and plan |
[gitlab-deploy-token]: ../../user/project/deploy_tokens/index.md#gitlab-deploy-token
-[registry]: ../../user/packages/container_registry/index.md
+[registry]: ../../user/project/container_registry.md
[dependent-repositories]: ../../user/project/new_ci_build_permissions_model.md#dependent-repositories
diff --git a/doc/ci/yaml/README.md b/doc/ci/yaml/README.md
index aa188facebd..5014d294a9a 100644
--- a/doc/ci/yaml/README.md
+++ b/doc/ci/yaml/README.md
@@ -110,7 +110,6 @@ The following table lists available parameters for jobs:
| [`dependencies`](#dependencies) | Other jobs that a job depends on so that you can pass artifacts between them. |
| [`coverage`](#coverage) | Code coverage settings for a given job. |
| [`retry`](#retry) | When and how many times a job can be auto-retried in case of a failure. |
-| [`timeout`](#timeout) | Define a custom timeout that would take precedence over the project-wide one. |
| [`parallel`](#parallel) | How many instances of a job should be run in parallel. |
| [`trigger`](#trigger-premium) | Defines a downstream pipeline trigger. |
| [`include`](#include) | Allows this job to include external YAML files. Also available: `include:local`, `include:file`, `include:template`, and `include:remote`. |
@@ -1996,20 +1995,6 @@ Possible values for `when` are:
- `missing_dependency_failure`: Retry if a dependency was missing.
- `runner_unsupported`: Retry if the runner was unsupported.
-### timeout
-
-`timeout` allows you to configure a timeout for a specific job:
-
-```yaml
-build:
- script: build.sh
- timeout: 3 hours 30 minutes
-
-test:
- script: rspec
- timeout: 3h 30m
-```
-
### `parallel`
> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/22631) in GitLab 11.5.
diff --git a/doc/container_registry/README.md b/doc/container_registry/README.md
index b98d1b51999..b31870df36d 100644
--- a/doc/container_registry/README.md
+++ b/doc/container_registry/README.md
@@ -1,5 +1,5 @@
---
-redirect_to: '../user/packages/container_registry/index.md'
+redirect_to: '../user/project/container_registry.md'
---
-This document was moved to [another location](../user/packages/container_registry/index.md).
+This document was moved to [another location](../user/project/container_registry.md).
diff --git a/doc/container_registry/troubleshooting.md b/doc/container_registry/troubleshooting.md
index 092d7831e35..c99d7011ac2 100644
--- a/doc/container_registry/troubleshooting.md
+++ b/doc/container_registry/troubleshooting.md
@@ -1,5 +1,5 @@
---
-redirect_to: '../user/packages/container_registry/index.md#troubleshooting-the-gitlab-container-registry'
+redirect_to: '../user/project/container_registry.md'
---
-This document was moved to [user/project/container_registry](../user/packages/container_registry/index.md#troubleshooting-the-gitlab-container-registry).
+This document was moved to [user/project/container_registry](../user/project/container_registry.md).
diff --git a/doc/development/README.md b/doc/development/README.md
index e8bebc79124..bbe73570f49 100644
--- a/doc/development/README.md
+++ b/doc/development/README.md
@@ -18,7 +18,6 @@ description: 'Learn how to contribute to GitLab.'
- [Generate a changelog entry with `bin/changelog`](changelog.md)
- [Code review guidelines](code_review.md) for reviewing code and having code reviewed
- [Database review guidelines](database_review.md) for reviewing database-related changes and complex SQL queries
-- [Pipelines for the GitLab project](pipelines.md)
- [Automatic CE->EE merge](automatic_ce_ee_merge.md)
- [Guidelines for implementing Enterprise Edition features](ee_features.md)
- [Security process for developers](https://gitlab.com/gitlab-org/release/docs/blob/master/general/security/developer.md#security-releases-critical-non-critical-as-a-developer)
diff --git a/doc/development/api_styleguide.md b/doc/development/api_styleguide.md
index 3f81440791e..61576236c96 100644
--- a/doc/development/api_styleguide.md
+++ b/doc/development/api_styleguide.md
@@ -92,18 +92,5 @@ For instance:
Model.create(foo: params[:foo])
```
-## Using API path helpers in GitLab Rails codebase
-
-Because we support [installing GitLab under a relative URL], one must take this
-into account when using API path helpers generated by Grape. Any such API path
-helper usage must be in wrapped into the `expose_path` helper call.
-
-For instance:
-
-```haml
-- endpoint = expose_path(api_v4_projects_issues_related_merge_requests_path(id: @project.id, issue_iid: @issue.iid))
-```
-
[Entity]: https://gitlab.com/gitlab-org/gitlab-ce/blob/master/lib/api/entities.rb
[validation, and coercion of the parameters]: https://github.com/ruby-grape/grape#parameter-validation-and-coercion
-[installing GitLab under a relative URL]: https://docs.gitlab.com/ee/install/relative_url.html
diff --git a/doc/development/architecture.md b/doc/development/architecture.md
index e30b9d27f46..147bd21e6c7 100644
--- a/doc/development/architecture.md
+++ b/doc/development/architecture.md
@@ -134,7 +134,7 @@ Component statuses are linked to configuration documentation for each component.
| [GitLab Workhorse](#gitlab-workhorse) | Smart reverse proxy, handles large HTTP requests | [✅][workhorse-omnibus] | [✅][workhorse-charts] | [✅][workhorse-charts] | [✅](https://about.gitlab.com/handbook/engineering/infrastructure/production-architecture/#service-architecture) | [⚙][workhorse-source] | ✅ | CE & EE |
| [GitLab Shell](#gitlab-shell) | Handles `git` over SSH sessions | [✅][shell-omnibus] | [✅][shell-charts] | [✅][shell-charts] | [✅](https://about.gitlab.com/handbook/engineering/infrastructure/production-architecture/#service-architecture) | [⚙][shell-source] | [✅][gitlab-yml] | CE & EE |
| [GitLab Pages](#gitlab-pages) | Hosts static websites | [⚙][pages-omnibus] | [❌][pages-charts] | [❌][pages-charts] | [✅](../user/gitlab_com/index.md#gitlab-pages) | [⚙][pages-source] | [⚙][pages-gdk] | CE & EE |
-| [Registry](#registry) | Container registry, allows pushing and pulling of images | [⚙][registry-omnibus] | [✅][registry-charts] | [✅][registry-charts] | [✅](../user/packages/container_registry/index.md#build-and-push-images) | [⤓][registry-source] | [⚙][registry-gdk] | CE & EE |
+| [Registry](#registry) | Container registry, allows pushing and pulling of images | [⚙][registry-omnibus] | [✅][registry-charts] | [✅][registry-charts] | [✅](../user/project/container_registry.md#build-and-push-images) | [⤓][registry-source] | [⚙][registry-gdk] | CE & EE |
| [Redis](#redis) | Caching service | [✅][redis-omnibus] | [✅][redis-omnibus] | [✅][redis-charts] | [✅](https://about.gitlab.com/handbook/engineering/infrastructure/production-architecture/#service-architecture) | [⤓][redis-source] | ✅ | CE & EE |
| [PostgreSQL](#postgresql) | Database | [✅][postgres-omnibus] | [✅][postgres-charts] | [✅][postgres-charts] | [✅](../user/gitlab_com/index.md#postgresql) | [⤓][postgres-source] | ✅ | CE & EE |
| [PgBouncer](#pgbouncer) | Database connection pooling, failover | [⚙][pgbouncer-omnibus] | [❌][pgbouncer-charts] | [❌][pgbouncer-charts] | [✅](https://about.gitlab.com/handbook/engineering/infrastructure/production-architecture/#database-architecture) | ❌ | ❌ | EE Only |
@@ -142,7 +142,7 @@ Component statuses are linked to configuration documentation for each component.
| [GitLab self-monitoring: Prometheus](#prometheus) | Time-series database, metrics collection, and query service | [✅][prometheus-omnibus] | [✅][prometheus-charts] | [⚙][prometheus-charts] | [✅](../user/gitlab_com/index.md#prometheus) | ❌ | ❌ | CE & EE |
| [GitLab self-monitoring: Alertmanager](#alertmanager) | Deduplicates, groups, and routes alerts from Prometheus | [⚙][alertmanager-omnibus] | [✅][alertmanager-charts] | [⚙][alertmanager-charts] | [✅](https://about.gitlab.com/handbook/engineering/monitoring/) | ❌ | ❌ | CE & EE |
| [GitLab self-monitoring: Grafana](#grafana) | Metrics dashboard | [✅][grafana-omnibus] | [⤓][grafana-charts] | [⤓][grafana-charts] | [✅](https://dashboards.gitlab.com/d/RZmbBr7mk/gitlab-triage?refresh=30s) | ❌ | ❌ | CE & EE |
-| [GitLab self-monitoring: Sentry](#sentry) | Track errors generated by the GitLab instance | [⤓][sentry-omnibus] | [❌][sentry-charts] | [❌][sentry-charts] | [✅](https://about.gitlab.com/handbook/support/workflows/500_errors.html#searching-sentry) | [⤓][gitlab-yml] | [⤓][gitlab-yml] | CE & EE |
+| [GitLab self-monitoring: Sentry](#sentry) | Track errors generated by the GitLab instance | [⤓][sentry-omnibus] | [❌][sentry-charts] | [❌][sentry-charts] | [✅](https://about.gitlab.com/handbook/support/workflows/services/gitlab_com/500_errors.html#searching-sentry) | [⤓][gitlab-yml] | [⤓][gitlab-yml] | CE & EE |
| [GitLab self-monitoring: Jaeger](#jaeger) | View traces generated by the GitLab instance | [❌][jaeger-omnibus] | [❌][jaeger-charts] | [❌][jaeger-charts] | [❌](https://gitlab.com/gitlab-org/omnibus-gitlab/issues/4104) | [⤓][jaeger-source] | [⚙][jaeger-gdk] | CE & EE |
| [Redis Exporter](#redis-exporter) | Prometheus endpoint with Redis metrics | [✅][redis-exporter-omnibus] | [✅][redis-exporter-charts] | [✅][redis-exporter-charts] | [✅](https://about.gitlab.com/handbook/engineering/monitoring/) | ❌ | ❌ | CE & EE |
| [Postgres Exporter](#postgres-exporter) | Prometheus endpoint with PostgreSQL metrics | [✅][postgres-exporter-omnibus] | [✅][postgres-exporter-charts] | [✅][postgres-exporter-charts] | [✅](https://about.gitlab.com/handbook/engineering/monitoring/) | ❌ | ❌ | CE & EE |
@@ -654,9 +654,9 @@ We've also detailed [our architecture of GitLab.com](https://about.gitlab.com/ha
[pages-charts]: https://gitlab.com/gitlab-org/charts/gitlab/issues/37
[pages-source]: ../install/installation.md#install-gitlab-pages
[pages-gdk]: https://gitlab.com/gitlab-org/gitlab-development-kit/blob/master/doc/howto/pages.md
-[registry-omnibus]: ../administration/packages/container_registry.md#container-registry-domain-configuration
+[registry-omnibus]: ../administration/container_registry.md#container-registry-domain-configuration
[registry-charts]: https://docs.gitlab.com/charts/charts/registry/
-[registry-source]: ../administration/packages/container_registry.md#enable-the-container-registry
+[registry-source]: ../administration/container_registry.md#enable-the-container-registry
[registry-gdk]: https://gitlab.com/gitlab-org/gitlab-development-kit/blob/master/doc/howto/registry.md
[redis-omnibus]: https://docs.gitlab.com/omnibus/settings/redis.html
[redis-charts]: https://docs.gitlab.com/charts/charts/redis/
diff --git a/doc/development/changelog.md b/doc/development/changelog.md
index afc18885a80..5667f58b0c3 100644
--- a/doc/development/changelog.md
+++ b/doc/development/changelog.md
@@ -102,13 +102,6 @@ Its simplest usage is to provide the value for `title`:
bin/changelog 'Hey DZ, I added a feature to GitLab!'
```
-If you want to generate a changelog entry for GitLab EE, you will need to pass
-the `--ee` option:
-
-```text
-bin/changelog --ee 'Hey DZ, I added a feature to GitLab!'
-```
-
At this point the script would ask you to select the category of the change (mapped to the `type` field in the entry):
```text
@@ -138,6 +131,9 @@ author:
type:
```
+If you're working on the GitLab EE repository, the entry will be added to
+`ee/changelogs/unreleased/` instead.
+
### Arguments
| Argument | Shorthand | Purpose |
diff --git a/doc/development/documentation/index.md b/doc/development/documentation/index.md
index 87892722d5e..c267669aa79 100644
--- a/doc/development/documentation/index.md
+++ b/doc/development/documentation/index.md
@@ -18,7 +18,7 @@ In addition to this page, the following resources can help you craft and contrib
## Source files and rendered web locations
-Documentation for GitLab, GitLab Runner, and Omnibus is published to [docs.gitlab.com](https://docs.gitlab.com). Documentation for GitLab is also published within the application at `/help` on the domain of the GitLab instance.
+Documentation for GitLab Community Edition (CE), Enterprise Edition (EE), GitLab Runner, and Omnibus is published to [docs.gitlab.com](https://docs.gitlab.com). Documentation for CE and EE is also published within the application at `/help` on the domain of the GitLab instance.
At `/help`, only help for your current edition and version is included. Help for other versions is available at docs.gitlab.com.
@@ -26,7 +26,8 @@ The source of the documentation exists within the codebase of each GitLab applic
| Project | Path |
| --- | --- |
-| [GitLab](https://gitlab.com/gitlab-org/gitlab/) | [`/doc`](https://gitlab.com/gitlab-org/gitlab/tree/master/doc) |
+| [GitLab Community Edition](https://gitlab.com/gitlab-org/gitlab-ce/) | [`/doc`](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc) |
+| [GitLab Enterprise Edition](https://gitlab.com/gitlab-org/gitlab-ee/) | [`/doc`](https://gitlab.com/gitlab-org/gitlab-ee/tree/master/doc) |
| [GitLab Runner](https://gitlab.com/gitlab-org/gitlab-runner/) | [`/docs`](https://gitlab.com/gitlab-org/gitlab-runner/tree/master/docs) |
| [Omnibus GitLab](https://gitlab.com/gitlab-org/omnibus-gitlab/) | [`/doc`](https://gitlab.com/gitlab-org/gitlab-ee/tree/master/doc) |
@@ -51,6 +52,37 @@ Adhere to the [Documentation Style Guide](styleguide.md). If a style standard is
See the [Structure](styleguide.md#structure) section of the [Documentation Style Guide](styleguide.md).
+## Single codebase
+
+We maintain two sets of docs: one in the
+[gitlab-ce](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc) repo and
+one in [gitlab-ee](https://gitlab.com/gitlab-org/gitlab-ee/tree/master/doc).
+These are identical, but they are different repositories.
+
+### CE first
+
+All merge requests for documentation must be submitted to CE. This means that:
+
+- For **EE-only docs changes**, you only have to submit an MR in the CE project.
+- For **EE-only features** that touch both the code and the docs, you have to submit
+ an EE MR containing all code changes, and a CE MR containing only the docs changes
+ and without a changelog entry.
+
+This might seem like a duplicate effort, but it's only for the short term.
+
+Since the CE and EE docs are combined, it's crucial to add the relevant
+[product badges](styleguide.md#product-badges) for all EE documentation, so that
+we can determine which features belong to which tier.
+
+### EE specific lines check
+
+There's a special test in place
+([`ee_specific_check.rb`](https://gitlab.com/gitlab-org/gitlab-ee/blob/master/scripts/ee_specific_check/ee_specific_check.rb)),
+which checks and prevents creating or editing new files or directories
+in EE under `doc/`. This should fail when changes to anything in `/doc` are submitted
+in an EE MR. To pass the test, simply remove the docs changes from the EE MR, and
+[submit them in CE](#ce-first).
+
## Changing document location
Changing a document's location requires specific steps to ensure that
@@ -83,7 +115,7 @@ For example, if you move `doc/workflow/lfs/lfs_administration.md` to
1. Find and replace any occurrences of the old location with the new one.
A quick way to find them is to use `git grep`. First go to the root directory
- where you cloned the `gitlab` repository and then do:
+ where you cloned the `gitlab-ce` repository and then do:
```sh
git grep -n "workflow/lfs/lfs_administration"
@@ -152,13 +184,28 @@ disqus_identifier: 'https://docs.gitlab.com/my-old-location/README.html'
Note: it is necessary to include the file name in the `disqus_identifier` URL,
even if it's `index.html` or `README.html`.
+## Branch naming
+
+If your contribution contains **only** documentation changes, you can speed up
+the CI process by following these branch naming conventions:
+
+| Branch name | Valid example |
+|:----------------------|:-----------------------------|
+| Starting with `docs/` | `docs/update-api-issues` |
+| Starting with `docs-` | `docs-update-api-issues` |
+| Ending in `-docs` | `123-update-api-issues-docs` |
+
+If your branch name matches any of the above, it will run only the docs
+tests. If not, the whole application test suite will run (including docs tests).
+
## Merge requests for GitLab documentation
Before getting started, make sure you read the introductory section
"[contributing to docs](#contributing-to-docs)" above and the
[documentation workflow](workflow.md).
-- Use the current [merge request description template](https://gitlab.com/gitlab-org/gitlab/blob/master/.gitlab/merge_request_templates/Documentation.md)
+- Use the current [merge request description template](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/.gitlab/merge_request_templates/Documentation.md)
+- Use the correct [branch name](#branch-naming)
- Label the MR `Documentation`
- Assign the correct milestone (see note below)
@@ -175,6 +222,30 @@ frozen or released, use the label `Pick into X.Y` to get it merged into
the correct release. Avoid picking into a past release as much as you can, as
it increases the work of the release managers.
+### Cherry-picking from CE to EE
+
+As we have the `master` branch of CE merged into EE once a day, it's common to
+run into merge conflicts. To avoid them, we [test for merge conflicts against EE](#testing)
+with the `ee-compat-check` job, and use the following method of creating equivalent
+branches for CE and EE.
+
+Follow this [method for cherry-picking from CE to EE](../automatic_ce_ee_merge.md#cherry-picking-from-ce-to-ee), with a few adjustments:
+
+- Create the [CE branch](#branch-naming) starting with `docs-`,
+ e.g.: `git checkout -b docs-example`
+- Create the EE-equivalent branch ending with `-ee`, e.g.,
+ `git checkout -b docs-example-ee`
+- Once all the jobs are passing in CE and EE, and you've addressed the
+ feedback from your own team, assign the CE MR to a technical writer for review
+- When both MRs are ready, the EE merge request will be merged first, and the
+ CE-equivalent will be merged next.
+- Note that the review will occur only in the CE MR, as the EE MR
+ contains the same commits as the CE MR.
+- If you have a few more changes that apply to the EE-version only, you can submit
+ a couple more commits to the EE branch, but ask the reviewer to review the EE merge request
+ additionally to the CE MR. If there are many EE-only changes though, start a new MR
+ to EE only.
+
## GitLab `/help`
Every GitLab instance includes the documentation, which is available at `/help`
@@ -184,7 +255,7 @@ There are [plans](https://gitlab.com/groups/gitlab-org/-/epics/693) to end this
practice and instead link out from the GitLab application to docs.gitlab.com URLs.
The documentation available online on docs.gitlab.com is continuously
-deployed every hour from the `master` branch of GitLab, Omnibus, and Runner. Therefore,
+deployed every hour from the `master` branch of CE, EE, Omnibus, and Runner. Therefore,
once a merge request gets merged, it will be available online on the same day.
However, they will be shipped (and available on `/help`) within the milestone assigned
to the MR.
@@ -264,10 +335,14 @@ You can combine one or more of the following:
### GitLab `/help` tests
-Several [rspec tests](https://gitlab.com/gitlab-org/gitlab/blob/master/spec/features/help_pages_spec.rb)
+Several [rspec tests](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/spec/features/help_pages_spec.rb)
are run to ensure GitLab documentation renders and works correctly. In particular, that [main docs landing page](../../README.md) will work correctly from `/help`.
For example, [GitLab.com's `/help`](https://gitlab.com/help).
+CAUTION: **Caution:**
+Because the rspec tests only run in a full pipeline, and not a special [docs-only pipeline](#branch-naming), it is possible
+to merge changes that will break `master` from a merge request with a successful docs-only pipeline run.
+
## Docs site architecture
See the [Docs site architecture](site_architecture/index.md) page to learn
@@ -287,12 +362,18 @@ To preview your changes to documentation locally, follow this
The live preview is currently enabled for the following projects:
-- <https://gitlab.com/gitlab-org/gitlab>
+- <https://gitlab.com/gitlab-org/gitlab-ce>
+- <https://gitlab.com/gitlab-org/gitlab-ee>
- <https://gitlab.com/gitlab-org/gitlab-runner>
-If your merge request has docs changes, you can use the manual `review-docs-deploy` job
-to deploy the docs review app for your merge request.
-You will need at least Maintainer permissions to be able to run it.
+If your branch contains only documentation changes, you can use
+[special branch names](#branch-naming) to avoid long-running pipelines.
+
+For [docs-only changes](#branch-naming), the review app is run automatically.
+For all other branches, you can use the manual `review-docs-deploy-manual` job
+in your merge request. You will need at least Maintainer permissions to be able
+to run it. In the mini pipeline graph, you should see a `>>` icon. Clicking it will
+reveal the `review-docs-deploy-manual` job. Click the play button to start the job.
![Manual trigger a docs build](img/manual_build_docs.png)
@@ -315,7 +396,7 @@ preview the changes. The docs URL can be found in two places:
triggered pipeline so that you can investigate whether something went wrong
TIP: **Tip:**
-Someone with no merge rights to the GitLab projects (think of forks from
+Someone with no merge rights to the CE/EE projects (think of forks from
contributors) cannot run the manual job. In that case, you can
ask someone from the GitLab team who has the permissions to do that for you.
@@ -341,8 +422,8 @@ In case the review app URL returns 404, follow these steps to debug:
If you want to know the in-depth details, here's what's really happening:
-1. You manually run the `review-docs-deploy` job in a merge request.
-1. The job runs the [`scripts/trigger-build-docs`](https://gitlab.com/gitlab-org/gitlab/blob/master/scripts/trigger-build-docs)
+1. You manually run the `review-docs-deploy` job in a CE/EE merge request.
+1. The job runs the [`scripts/trigger-build-docs`](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/scripts/trigger-build-docs)
script with the `deploy` flag, which in turn:
1. Takes your branch name and applies the following:
- The slug of the branch name is used to avoid special characters since
@@ -384,6 +465,18 @@ The current tests are:
[`gitlab-docs`](https://gitlab.com/gitlab-org/gitlab-docs) directory. In addition,
`docs-lint` also runs [`markdownlint`](#markdownlint) to ensure the
markdown is consistent across all documentation.
+1. [`ee_compat_check`](../automatic_ce_ee_merge.md#avoiding-ce-ee-merge-conflicts-beforehand) (runs on CE only):
+ When you submit a merge request to GitLab Community Edition (CE),
+ there is this additional job that runs against Enterprise Edition (EE)
+ and checks if your changes can apply cleanly to the EE codebase.
+ If that job fails, read the instructions in the job log for what to do next.
+ As CE is merged into EE once a day, it's important to avoid merge conflicts.
+ Submitting an EE-equivalent merge request cherry-picking all commits from CE to EE is
+ essential to avoid them.
+1. [`ee-files-location-check`/`ee-specific-lines-check`](#ee-specific-lines-check) (runs on EE only):
+ This test ensures that no new files/directories are created/changed in EE.
+ All docs should be submitted in CE instead, regardless the tier they are on.
+ This is for the [single codebase](#single-codebase) effort.
1. In a full pipeline, tests for [`/help`](#gitlab-help-tests).
### Linting
@@ -407,8 +500,8 @@ This list does not limit what other linters you can add to your local documentat
`proselint` can be used [on the command line](http://proselint.com/utility/), either on a single
Markdown file or on all Markdown files in a project. For example, to run `proselint` on all
- documentation in the [`gitlab` project](https://gitlab.com/gitlab-org/gitlab), run the
- following commands from within the `gitlab` project:
+ documentation in the [`gitlab-ce` project](https://gitlab.com/gitlab-org/gitlab-ce), run the
+ following commands from within the `gitlab-ce` project:
```sh
cd doc
@@ -450,8 +543,8 @@ documentation. This tool helps catch deviations from those guidelines.
`markdownlint` can be used [on the command line](https://github.com/igorshubovych/markdownlint-cli#markdownlint-cli--),
either on a single Markdown file or on all Markdown files in a project. For example, to run
-`markdownlint` on all documentation in the [`gitlab` project](https://gitlab.com/gitlab-org/gitlab),
-run the following commands from within your `gitlab` project root directory, which will
+`markdownlint` on all documentation in the [`gitlab-ce` project](https://gitlab.com/gitlab-org/gitlab-ce),
+run the following commands from within your `gitlab-ce` project root directory, which will
automatically detect the [`.markdownlint.json`](#markdownlint-configuration) config
file in the root of the project, and test all files in `/doc` and its subdirectories:
@@ -484,7 +577,7 @@ Each formatting issue that `markdownlint` checks has an associated
These rules are configured in the `.markdownlint.json` files located in the root of
four repos that are the sources for <https://docs.gitlab.com>:
-- <https://gitlab.com/gitlab-org/gitlab/blob/master/.markdownlint.json>
+- <https://gitlab.com/gitlab-org/gitlab-ce/blob/master/.markdownlint.json>
- <https://gitlab.com/gitlab-org/gitlab-runner/blob/master/.markdownlint.json>
- <https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/.markdownlint.json>
- <https://gitlab.com/charts/gitlab/blob/master/.markdownlint.json>
@@ -497,5 +590,5 @@ rules, and also to configure optional parameters for enabled rules as needed.
GitLab uses [Danger](https://github.com/danger/danger) for some elements in
code review. For docs changes in merge requests, whenever a change to files under `/doc`
is made, Danger Bot leaves a comment with further instructions about the documentation
-process. This is configured in the Dangerfile in the GitLab repo under
-[/danger/documentation/](https://gitlab.com/gitlab-org/gitlab/tree/master/danger/documentation).
+process. This is configured in the Dangerfile in the GitLab CE and EE repo under
+[/danger/documentation/](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/danger/documentation).
diff --git a/doc/development/elasticsearch.md b/doc/development/elasticsearch.md
index f3ea55d3d5d..f2412c249c1 100644
--- a/doc/development/elasticsearch.md
+++ b/doc/development/elasticsearch.md
@@ -59,7 +59,7 @@ Additionally, if you need large repos or multiple forks for testing, please cons
## How does it work?
-The Elasticsearch integration depends on an external indexer. We ship an [indexer written in Go](https://gitlab.com/gitlab-org/gitlab-elasticsearch-indexer). The user must trigger the initial indexing via a rake task but, after this is done, GitLab itself will trigger reindexing when required via `after_` callbacks on create, update, and destroy that are inherited from [/ee/app/models/concerns/elastic/application_search.rb](https://gitlab.com/gitlab-org/gitlab-ee/blob/master/ee/app/models/concerns/elastic/application_search.rb).
+The Elasticsearch integration depends on an external indexer. We ship a [ruby indexer](https://gitlab.com/gitlab-org/gitlab-ee/blob/master/bin/elastic_repo_indexer) by default but are also working on an [indexer written in Go](https://gitlab.com/gitlab-org/gitlab-elasticsearch-indexer). The user must trigger the initial indexing via a rake task, but after this is done GitLab itself will trigger reindexing when required via `after_` callbacks on create, update, and destroy that are inherited from [/ee/app/models/concerns/elastic/application_search.rb](https://gitlab.com/gitlab-org/gitlab-ee/blob/master/ee/app/models/concerns/elastic/application_search.rb).
All indexing after the initial one is done via `ElasticIndexerWorker` (sidekiq jobs).
diff --git a/doc/development/packages.md b/doc/development/packages.md
index 3d209c4a93c..08aa0b08525 100644
--- a/doc/development/packages.md
+++ b/doc/development/packages.md
@@ -1,8 +1,8 @@
# Packages **(PREMIUM)**
-This document will guide you through adding another [package management system](../administration/packages/index.md) support to GitLab.
+This document will guide you through adding another [package management system](../administration/packages.md) support to GitLab.
-See already supported package types in [Packages documentation](../administration/packages/index.md)
+See already supported package types in [Packages documentation](../administration/packages.md)
Since GitLab packages' UI is pretty generic, it is possible to add new
package system support by solely backend changes. This guide is superficial and does
@@ -46,7 +46,7 @@ Group-level and instance-level endpoints are good to have but are optional.
NOTE: **Note:**
To avoid name conflict for instance-level endpoints we use
-[the package naming convention](../user/packages/npm_registry/index.md#package-naming-convention)
+[the package naming convention](../user/project/packages/npm_registry.md#package-naming-convention)
## Configuration
diff --git a/doc/development/pipelines.md b/doc/development/pipelines.md
deleted file mode 100644
index 448fb0f9f5a..00000000000
--- a/doc/development/pipelines.md
+++ /dev/null
@@ -1,216 +0,0 @@
-# Pipelines for the GitLab project
-
-Pipelines for `gitlab-org/gitlab` and `gitlab-org/gitlab-foss` (as well as the
-`dev` instance's mirrors) are configured in the usual
-[`.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/blob/master/.gitlab-ci.yml)
-which itself includes files under
-[`.gitlab/ci/`](https://gitlab.com/gitlab-org/gitlab/tree/master/.gitlab/ci)
-for easier maintenance.
-
-We're striving to [dogfood](https://about.gitlab.com/handbook/engineering/#dogfooding)
-GitLab [CI/CD features and best-practices](../ci/yaml/README.md)
-as much as possible.
-
-## Stages
-
-The current stages are:
-
-- `prepare`: This stage includes jobs that prepare artifacts that are needed by
- jobs in subsequent stages.
-- `quick-test`: This stage includes test jobs that should run first and fail the
- pipeline early (currently used to run Geo tests when the branch name starts
- with `geo-`, `geo/`, or ends with `-geo`).
-- `test`: This stage includes most of the tests, DB/migration jobs, and static analysis jobs.
-- `review-prepare`: This stage includes a job that build the CNG images that are
- later used by the (Helm) Review App deployment (see
- [Review Apps](testing_guide/review_apps.md) for details).
-- `review`: This stage includes jobs that deploy the GitLab and Docs Review Apps.
-- `qa`: This stage includes jobs that perform QA tasks against the Review App
- that is deployed in the previous stage.
-- `post-test`: This stage includes jobs that build reports or gather data from
- the previous stages' jobs (e.g. coverage, Knapsack metadata etc.).
-- `pages`: This stage includes a job that deploys the various reports as
- GitLab pages (e.g. <https://gitlab-org.gitlab.io/gitlab/coverage-ruby/>,
- <https://gitlab-org.gitlab.io/gitlab/coverage-javascript/>,
- <https://gitlab-org.gitlab.io/gitlab/webpack-report/>).
-
-## Default image
-
-The default image is currently
-`dev.gitlab.org:5005/gitlab/gitlab-build-images:ruby-2.6.3-golang-1.11-git-2.22-chrome-73.0-node-12.x-yarn-1.16-postgresql-9.6-graphicsmagick-1.3.33`.
-It includes Ruby 2.6.3, Go 1.11, Git 2.22, Chrome 73, Node 12, Yarn 1.16,
-PostgreSQL 9.6, and Graphics Magick 1.3.33.
-
-The images used in our pipelines are configured in the
-[`gitlab-org/gitlab-build-images`](https://gitlab.com/gitlab-org/gitlab-build-images)
-project, which is push-mirrored to <https://dev.gitlab.org/gitlab/gitlab-build-images>
-for redundancy.
-
-The current version of the build images can be found in the
-["Used by GitLab CE/EE section"](https://gitlab.com/gitlab-org/gitlab-build-images/blob/master/.gitlab-ci.yml).
-
-## Default variables
-
-In addition to the [predefined variables](../ci/variables/predefined_variables.md),
-each pipeline includes the following [variables](../ci/variables/README.md):
-
-- `RAILS_ENV: "test"`
-- `NODE_ENV: "test"`
-- `SIMPLECOV: "true"`
-- `GIT_DEPTH: "20"`
-- `GIT_SUBMODULE_STRATEGY: "none"`
-- `GET_SOURCES_ATTEMPTS: "3"`
-- `KNAPSACK_RSPEC_SUITE_REPORT_PATH: knapsack/${CI_PROJECT_NAME}/rspec_report-master.json`
-- `EE_KNAPSACK_RSPEC_SUITE_REPORT_PATH: knapsack/${CI_PROJECT_NAME}/rspec_report-master-ee.json`
-- `FLAKY_RSPEC_SUITE_REPORT_PATH: rspec_flaky/report-suite.json`
-- `BUILD_ASSETS_IMAGE: "false"`
-- `ES_JAVA_OPTS: "-Xms256m -Xmx256m"`
-- `ELASTIC_URL: "http://elastic:changeme@docker.elastic.co-elasticsearch-elasticsearch:9200"`
-
-## Common job definitions
-
-Most of the jobs [extend from a few CI definitions](../ci/yaml/README.md#extends)
-that are scoped to a single
-[configuration parameter](../ci/yaml/README.md#configuration-parameters).
-
-These common definitions are:
-
-- `.default-tags`: Ensures a job has the `gitlab-org` tag to ensure it's using
- our dedicated runners.
-- `.default-retry`: Allows a job to retry upon `unknown_failure`, `api_failure`,
- `runner_system_failure`.
-- `.default-before_script`: Allows a job to use a default `before_script` definition
- suitable for Ruby/Rails tasks that may need a database running (e.g. tests).
-- `.default-cache`: Allows a job to use a default `cache` definition suitable for
- Ruby/Rails and frontend tasks.
-- `.default-only`: Restricts the cases where a job is created. This currently
- includes `master`, `/^[\d-]+-stable(-ee)?$/` (stable branches),
- `/^\d+-\d+-auto-deploy-\d+$/` (security branches), `merge_requests`, `tags`.
- Note that jobs won't be created for branches with this default configuration.
-- `.only-review`: Only creates a job for the `gitlab-org` namespace and if
- Kubernetes integration is available. Also, prevents a job from being created
- for `master` and auto-deploy branches.
-- `.only-review-schedules`: Same as `.only-review` but also restrict a job to
- only run for [schedules](../user/project/pipelines/schedules.md).
-- `.use-pg`: Allows a job to use the `postgres:9.6.14` and `redis:alpine` services.
-- `.use-pg-10`: Allows a job to use the `postgres:10.9` and `redis:alpine` services.
-- `.only-ee`: Only creates a job for the `gitlab` project.
-
-## Changes detection
-
-If a job extends from `.default-only` (and most of the jobs should), it can restrict
-the cases where it should be created
-[based on the changes](../ci/yaml/README.md#onlychangesexceptchanges)
-from a commit or MR by extending from the following CI definitions:
-
-- `.only-code-changes`: Allows a job to only be created upon code-related changes.
-- `.only-qa-changes`: Allows a job to only be created upon QA-related changes.
-- `.only-docs-changes`: Allows a job to only be created upon docs-related changes.
-- `.only-code-qa-changes`: Allows a job to only be created upon code-related or QA-related changes.
-
-**See <https://gitlab.com/gitlab-org/gitlab/blob/master/.gitlab/ci/global.gitlab-ci.yml>
-for the list of exact patterns.**
-
-## Directed acyclic graph
-
-We're using the [`needs:`](../ci/yaml/README.md#needs) keyword to
-execute jobs out of order for the following jobs:
-
-```mermaid
-graph RL;
- A[setup-test-env];
- B["gitlab:assets:compile<br/>(master only)"];
- C[gitlab:assets:compile pull-cache];
- D["cache gems<br/>(master and tags only)"];
- E[review-build-cng];
- F[build-qa-image];
- G[review-deploy];
- G2["schedule:review-deploy<br/>(master only)"];
- H[karma];
- I[jest];
- J["compile-assets<br/>(master only)"];
- K[compile-assets pull-cache];
- L[webpack-dev-server];
- M[coverage];
- N[pages];
- O[static-analysis];
- P["package-and-qa-manual:master<br/>(master schedule only)"];
- Q[package-and-qa];
- R[package-and-qa-manual];
-
-subgraph "`prepare` stage"
- A
- F
- J
- K
- end
-
-subgraph "`test` stage"
- B --> |needs| A;
- C --> |needs| A;
- D --> |needs| A;
- H -.-> |depends on| A;
- H -.-> |depends on| J;
- H -.-> |depends on| K;
- I -.-> |depends on| A;
- I -.-> |depends on| J;
- I -.-> |depends on| K;
- L -.-> |depends on| A;
- L -.-> |depends on| J;
- L -.-> |depends on| K;
- downtime_check --> |needs and depends on| A;
- db:* --> |needs| A;
- gitlab:setup --> |needs| A;
- O -.-> |depends on| A;
- O -.-> |depends on| B;
- O -.-> |depends on| C;
- downtime_check --> |needs and depends on| A;
- end
-
-subgraph "`review-prepare` stage"
- E --> |needs| C;
- X["schedule:review-build-cng<br/>(master schedule only)"] --> |needs| B;
- end
-
-subgraph "`review` stage"
- G --> |needs| E;
- G2 --> |needs| E;
- end
-
-subgraph "`qa` stage"
- Q --> |needs| C;
- Q --> |needs| F;
- R --> |needs| C;
- R --> |needs| F;
- P --> |needs| B;
- P --> |needs| F;
- review-qa-smoke -.-> |depends on| G;
- review-qa-all -.-> |depends on| G;
- review-qa-performance -.-> |depends on| G;
- X2["schedule:review-performance<br/>(master only)"] -.-> |depends on| G2;
- dast -.-> |depends on| G;
- end
-
-subgraph "`post-test` stage"
- M
- end
-
-subgraph "`pages` stage"
- N -.-> |depends on| B;
- N -.-> |depends on| H;
- N -.-> |depends on| M;
- end
-```
-
-## Test jobs
-
-Consult [GitLab tests in the Continuous Integration (CI) context](testing_guide/ci.md)
-for more information.
-
-## Review app jobs
-
-Consult the [Review Apps](testing_guide/review_apps.md) dedicated page for more information.
-
----
-
-[Return to Development documentation](README.md)
diff --git a/doc/development/polling.md b/doc/development/polling.md
index b664ddb9888..76bb5ae7819 100644
--- a/doc/development/polling.md
+++ b/doc/development/polling.md
@@ -11,9 +11,7 @@ Instead you should use polling mechanism with ETag caching in Redis.
## How to use it
1. Add the path of the endpoint which you want to poll to
- `Gitlab::EtagCaching::Router`.
-1. Set the polling interval header for the response with
- `Gitlab::PollingInterval.set_header`.
+ `Gitlab::EtagCaching::Middleware`.
1. Implement cache invalidation for the path of your endpoint using
`Gitlab::EtagCaching::Store`. Whenever a resource changes you
have to invalidate the ETag for the path that depends on this
diff --git a/doc/development/testing_guide/end_to_end/index.md b/doc/development/testing_guide/end_to_end/index.md
index c00be77ce8c..f6a2f642274 100644
--- a/doc/development/testing_guide/end_to_end/index.md
+++ b/doc/development/testing_guide/end_to_end/index.md
@@ -7,6 +7,24 @@ as expected across the entire software stack and architecture, including
integration of all micro-services and components that are supposed to work
together.
+## Branch naming
+
+If your contribution contains **only** changes under the
+[`qa/` folder](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/qa), you can
+speed up the CI process by following some branch naming conventions. You have
+three choices:
+
+| Branch name | Valid example |
+|:----------------------|:-----------------------------|
+| Starting with `qa/` | `qa/new-oauth-login-test` |
+| Starting with `qa-` | `qa-new-oauth-login-test` |
+| Ending in `-qa` | `123-new-oauth-login-test-qa` |
+
+If your branch name matches any of the above, it will run only the QA-related
+jobs.
+If it does not, the whole application test suite will run (including QA-related
+jobs).
+
## How do we test GitLab?
We use [Omnibus GitLab][omnibus-gitlab] to build GitLab packages and then we
diff --git a/doc/development/testing_guide/end_to_end/style_guide.md b/doc/development/testing_guide/end_to_end/style_guide.md
index 9088e9e9bfb..54ed3f34c89 100644
--- a/doc/development/testing_guide/end_to_end/style_guide.md
+++ b/doc/development/testing_guide/end_to_end/style_guide.md
@@ -101,59 +101,43 @@ end
## Block argument naming
-To have a standard on what we call pages and resources when using the `.perform` method,
-we use the name of the page object in [snake_case](https://en.wikipedia.org/wiki/Snake_case)
-(all lowercase, with words separated by an underscore). See good and bad examples below.
-
-While we prefer to follow the standard in most cases, it is also acceptable to
-use common abbreviations (e.g., mr) or other alternatives, as long as
-the name is not ambiguous. This can include appending `_page` if it helps to
-avoid confusion or make the code more readable. For example, if a page object is
-named `New`, it could be confusing to name the block argument `new` because that
-is used to instantiate objects, so `new_page` would be acceptable.
-
-We chose not to simply use `page` because that would shadow the
-Capybara DSL, potentially leading to confusion and bugs.
+To have a standard on how we call pages when using the `.perform` method, we use the name of page object being called, all lowercased, and separated by underscore, if needed (see good and bad examples below.) This also applies to resources. We chose not to simply use `page` because that would shadow the Capybara DSL, potentially leading to confusion and bugs.
### Examples
**Good**
```ruby
+# qa/specs/features/browser_ui/1_manage/project/add_project_member_spec.rb
+
Page::Project::Settings::Members.perform do |members|
members.do_something
end
```
```ruby
+# qa/specs/features/ee/browser_ui/3_create/merge_request/add_batch_comments_in_merge_request_spec.rb
+
Resource::MergeRequest.fabricate! do |merge_request|
merge_request.do_something_else
end
```
-```ruby
-Resource::MergeRequest.fabricate! do |mr|
- mr.do_something_else
-end
-```
-
-```ruby
-Page::Project::New.peform do |new_page|
- new_page.do_something
-end
-```
-
**Bad**
```ruby
+# qa/specs/features/browser_ui/1_manage/project/add_project_member_spec.rb
+
Page::Project::Settings::Members.perform do |project_settings_members_page|
project_settings_members_page.do_something
end
```
```ruby
-Page::Project::New.peform do |page|
- page.do_something
+# qa/specs/features/ee/browser_ui/3_create/merge_request/add_batch_comments_in_merge_request_spec.rb
+
+Resource::MergeRequest.fabricate! do |merge_request_page|
+ merge_request_page.do_something_else
end
```
diff --git a/doc/development/testing_guide/img/k9s.png b/doc/development/testing_guide/img/k9s.png
deleted file mode 100644
index c4b222f0b64..00000000000
--- a/doc/development/testing_guide/img/k9s.png
+++ /dev/null
Binary files differ
diff --git a/doc/development/testing_guide/review_apps.md b/doc/development/testing_guide/review_apps.md
index 8698a1e4c2d..13772cbe015 100644
--- a/doc/development/testing_guide/review_apps.md
+++ b/doc/development/testing_guide/review_apps.md
@@ -10,30 +10,24 @@ Review Apps are automatically deployed by each pipeline, both in
```mermaid
graph TD
- build-qa-image -->|once the `prepare` stage is done| gitlab:assets:compile
- gitlab:assets:compile -->|once the `gitlab:assets:compile` job is done| review-build-cng
- review-build-cng -.->|triggers a CNG-mirror pipeline and wait for it to be done| CNG-mirror
- CNG-mirror -.->|polls until completed| review-build-cng
- review-build-cng -->|once the `review-build-cng` job is done| review-deploy
- review-deploy -->|once the `review-deploy` job is done| review-qa-smoke
+ build-qa-image -.->|once the `prepare` stage is done| gitlab:assets:compile
+ review-build-cng -->|triggers a CNG-mirror pipeline and wait for it to be done| CNG-mirror
+ review-build-cng -.->|once the `test` stage is done| review-deploy
+ review-deploy -.->|once the `review` stage is done| review-qa-smoke
subgraph "1. gitlab-ce/ee `prepare` stage"
build-qa-image
end
subgraph "2. gitlab-ce/ee `test` stage"
- gitlab:assets:compile
+ gitlab:assets:compile -->|plays dependent job once done| review-build-cng
end
-subgraph "3. gitlab-ce/ee `review-prepare` stage"
- review-build-cng
- end
-
-subgraph "4. gitlab-ce/ee `review` stage"
+subgraph "3. gitlab-ce/ee `review` stage"
review-deploy["review-deploy<br><br>Helm deploys the Review App using the Cloud<br/>Native images built by the CNG-mirror pipeline.<br><br>Cloud Native images are deployed to the `review-apps-ce` or `review-apps-ee`<br>Kubernetes (GKE) cluster, in the GCP `gitlab-review-apps` project."]
end
-subgraph "5. gitlab-ce/ee `qa` stage"
+subgraph "4. gitlab-ce/ee `qa` stage"
review-qa-smoke[review-qa-smoke<br><br>gitlab-qa runs the smoke suite against the Review App.]
end
@@ -183,25 +177,6 @@ secure note named **gitlab-{ce,ee} Review App's root password**.
`review-qa-raise-e-12chm0-migrations.1-nqwtx`.
1. Click on the `Container logs` link.
-### Diagnosing unhealthy review-app releases
-
-If [Review App Stability](https://gitlab.com/gitlab-org/quality/team-tasks/issues/93) dips this may be a signal
-that the `review-apps-ce/ee` cluster is unhealthy. Leading indicators may be healthcheck failures leading to restarts or majority failure for Review App deployments.
-
-The following items may help diagnose this:
-
-- [Instance group CPU Utilization in GCP](https://console.cloud.google.com/compute/instanceGroups/details/us-central1-a/gke-review-apps-ce-preemp-n1-standard-a4c9571c-grp?project=gitlab-review-apps&tab=monitoring&graph=GCE_CPU&duration=PT12H) - helpful to identify if nodes are problematic or the entire cluster is trending towards unhealthy
-- [Instance Group size in GCP](https://console.cloud.google.com/compute/instanceGroups/details/us-central1-a/gke-review-apps-ce-preemp-n1-standard-a4c9571c-grp?project=gitlab-review-apps&tab=monitoring&graph=GCE_SIZE&duration=PT12H) - aids in identifying load spikes on the cluster. Kubernetes will add nodes up to 220 based on total resource requests.
-- `kubectl top nodes --sort-by=cpu` - can identify if node spikes are common or load on specific nodes which may get rebalanced by the Kubernetes scheduler.
-- `kubectl top pods --sort-by=cpu` -
-- [K9s] - K9s is a powerful command line dashboard which allows you to filter by labels. This can help identify trends with apps exceeding the [review-app resource requests](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/scripts/review_apps/base-config.yaml). Kubernetes will schedule pods to nodes based on resource requests and allow for CPU usage up to the limits.
- - In K9s you can sort or add filters by typing the `/` character
- - `-lrelease=<review-app-slug>` - filters down to all pods for a release. This aids in determining what is having issues in a single deployment
- - `-lapp=<app>` - filters down to all pods for a specific app. This aids in determining resource usage by app.
- - You can scroll to a Kubernetes resource and hit `d`(describe), `s`(shell), `l`(logs) for a deeper inspection
-
-![K9s](img/k9s.png)
-
### Troubleshoot a pending `dns-gitlab-review-app-external-dns` Deployment
#### Finding the problem
@@ -291,12 +266,6 @@ find a way to limit it to only us.**
## Other resources
- [Review Apps integration for CE/EE (presentation)](https://docs.google.com/presentation/d/1QPLr6FO4LduROU8pQIPkX1yfGvD13GEJIBOenqoKxR8/edit?usp=sharing)
-- [Stability issues](https://gitlab.com/gitlab-org/quality/team-tasks/issues/212)
-
-### Helpful command line tools
-
-- [K9s] - enables CLI dashboard across pods and enabling filtering by labels
-- [Stern](https://github.com/wercker/stern) - enables cross pod log tailing based on label/field selectors
[charts-1068]: https://gitlab.com/gitlab-org/charts/gitlab/issues/1068
[gitlab-pipeline]: https://gitlab.com/gitlab-org/gitlab-ce/pipelines/44362587
@@ -316,7 +285,6 @@ find a way to limit it to only us.**
[gitlab-ci-yml]: https://gitlab.com/gitlab-org/gitlab-ce/blob/master/.gitlab-ci.yml
[gitlab-k8s-integration]: ../../user/project/clusters/index.md
[password-bug]: https://gitlab.com/gitlab-org/gitlab-ce/issues/53621
-[K9s]: https://github.com/derailed/k9s
---
diff --git a/doc/install/aws/index.md b/doc/install/aws/index.md
index e47f1cb640e..ddf2b2fb738 100644
--- a/doc/install/aws/index.md
+++ b/doc/install/aws/index.md
@@ -540,7 +540,7 @@ which would otherwise take much space.
In particular, you can store in S3:
- [The Git LFS objects](../../workflow/lfs/lfs_administration.md#s3-for-omnibus-installations) ((Omnibus GitLab installations))
-- [The Container Registry images](../../administration/packages/container_registry.md#container-registry-storage-driver) (Omnibus GitLab installations)
+- [The Container Registry images](../../administration/container_registry.md#container-registry-storage-driver) (Omnibus GitLab installations)
- [The GitLab CI/CD job artifacts](../../administration/job_artifacts.md#using-object-storage) (Omnibus GitLab installations)
### Setting up a domain name
diff --git a/doc/install/google_cloud_platform/index.md b/doc/install/google_cloud_platform/index.md
index 56e5ecb3a58..be29bcc7cd7 100644
--- a/doc/install/google_cloud_platform/index.md
+++ b/doc/install/google_cloud_platform/index.md
@@ -130,7 +130,7 @@ Kerberos, etc. Here are some documents you might be interested in reading:
- [Omnibus GitLab documentation](https://docs.gitlab.com/omnibus/)
- [Integration documentation](../../integration/README.md)
- [GitLab Pages configuration](../../administration/pages/index.md)
-- [GitLab Container Registry configuration](../../administration/packages/container_registry.md)
+- [GitLab Container Registry configuration](../../administration/container_registry.md)
[freetrial]: https://console.cloud.google.com/freetrial "GCP free trial"
[ip]: https://cloud.google.com/compute/docs/configure-instance-ip-addresses#promote_ephemeral_ip "Configuring an Instance's IP Addresses"
diff --git a/doc/install/installation.md b/doc/install/installation.md
index cf084ca74a9..6039ddc45ae 100644
--- a/doc/install/installation.md
+++ b/doc/install/installation.md
@@ -585,25 +585,6 @@ You can specify a different Git repository by providing it as an extra parameter
sudo -u git -H bundle exec rake "gitlab:workhorse:install[/home/git/gitlab-workhorse,https://example.com/gitlab-workhorse.git]" RAILS_ENV=production
```
-### Install gitlab-elasticsearch-indexer
-
-GitLab-Elasticsearch-Indexer uses [GNU Make](https://www.gnu.org/software/make/). The
-following command-line will install GitLab-Elasticsearch-Indexer in `/home/git/gitlab-elasticsearch-indexer`
-which is the recommended location.
-
-```sh
-sudo -u git -H bundle exec rake "gitlab:indexer:install[/home/git/gitlab-elasticsearch-indexer]" RAILS_ENV=production
-```
-
-You can specify a different Git repository by providing it as an extra parameter:
-
-```sh
-sudo -u git -H bundle exec rake "gitlab:indexer:install[/home/git/gitlab-elasticsearch-indexer,https://example.com/gitlab-elasticsearch-indexer.git]" RAILS_ENV=production
-```
-
-The source code will first be fetched to the path specified by the first parameter. Then a binary will be built under its `bin` directory.
-You will then need to update `gitlab.yml`'s `production -> elasticsearch -> indexer_path` setting to point to that binary.
-
### Install GitLab Pages
GitLab Pages uses [GNU Make](https://www.gnu.org/software/make/). This step is optional and only needed if you wish to host static sites from within GitLab. The following commands will install GitLab Pages in `/home/git/gitlab-pages`. For additional setup steps, consult the [administration guide](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/administration/pages/source.md) for your version of GitLab as the GitLab Pages daemon can be run several different ways.
diff --git a/doc/integration/shibboleth.md b/doc/integration/shibboleth.md
index 1b4e75e0ca1..ca5a8077e73 100644
--- a/doc/integration/shibboleth.md
+++ b/doc/integration/shibboleth.md
@@ -1,8 +1,6 @@
# Shibboleth OmniAuth Provider
-NOTE: **Note:**
-The preferred approach for integrating a Shibboleth authentication system
-with Gitlab 10 or newer is to use [GitLab's SAML integration](saml.md). This documentation is for Omnibus GitLab 9.x installs or older.
+This documentation is for enabling Shibboleth with the Omnibus GitLab package.
In order to enable Shibboleth support in GitLab we need to use Apache instead of Nginx (It may be possible to use Nginx, however this is difficult to configure using the bundled Nginx provided in the Omnibus GitLab package). Apache uses mod_shib2 module for Shibboleth authentication and can pass attributes as headers to Omniauth Shibboleth provider.
diff --git a/doc/raketasks/backup_restore.md b/doc/raketasks/backup_restore.md
index bc9e429c431..c230bb413f2 100644
--- a/doc/raketasks/backup_restore.md
+++ b/doc/raketasks/backup_restore.md
@@ -992,7 +992,7 @@ and the lost data can be manually replaced.
### Container Registry push failures after restoring from a backup
-If you use the [Container Registry](../user/packages/container_registry/index.md), you
+If you use the [Container Registry](../user/project/container_registry.md), you
may see pushes to the registry fail after restoring your backup on an Omnibus
GitLab instance after restoring the registry data.
diff --git a/doc/raketasks/cleanup.md b/doc/raketasks/cleanup.md
index e2ec58be367..f84d29cca9a 100644
--- a/doc/raketasks/cleanup.md
+++ b/doc/raketasks/cleanup.md
@@ -16,11 +16,6 @@ sudo gitlab-rake gitlab:cleanup:dirs
bundle exec rake gitlab:cleanup:dirs RAILS_ENV=production
```
-DANGER: **Danger:**
-The following task does not currently work as expected.
-The use will probably mark more existing repositories as orphaned.
-For more information, see the [issue](https://gitlab.com/gitlab-org/gitlab-ee/issues/24633).
-
Rename repositories from all repository storage paths if they don't exist in GitLab database.
The repositories get a `+orphaned+TIMESTAMP` suffix so that they cannot block new repositories from being created.
diff --git a/doc/topics/autodevops/index.md b/doc/topics/autodevops/index.md
index ebeb5270884..0cbd85fc568 100644
--- a/doc/topics/autodevops/index.md
+++ b/doc/topics/autodevops/index.md
@@ -734,40 +734,6 @@ Avoid passing secrets as Docker build arguments if possible, as they may be
persisted in your image. See
[this discussion](https://github.com/moby/moby/issues/13490) for details.
-### Passing secrets to `docker build` (beta)
-
-CI environment variables can be passed as [build
-secrets](https://docs.docker.com/develop/develop-images/build_enhancements/#new-docker-build-secret-information) to the `docker build` command by listing them comma separated by name in the
-`AUTO_DEVOPS_BUILD_IMAGE_FORWARDED_CI_VARIABLES` variable. For example, in order to forward the variables `CI_COMMIT_SHA` and `CI_ENVIRONMENT_NAME`, one would set `AUTO_DEVOPS_BUILD_IMAGE_FORWARDED_CI_VARIABLES` to `CI_COMMIT_SHA,CI_ENVIRONMENT_NAME`.
-
-Unlike build arguments, these are not persisted by Docker in the final image
-(though you can still persist them yourself, so be careful).
-
-In projects:
-
-- Without a `Dockerfile`, these are available automatically as environment
- variables.
-- With a `Dockerfile`, the following is required:
-
- 1. Activate the experimental `Dockerfile` syntax by adding the following
- to the top of the file:
-
- ```docker
- # syntax = docker/dockerfile:experimental
- ```
-
- 1. To make secrets available in any `RUN $COMMAND` in the `Dockerfile`, mount
- the secret file and source it prior to running `$COMMAND`:
-
- ```docker
- RUN --mount=type=secret,id=auto-devops-build-secrets . /run/secrets/auto-devops-build-secrets && $COMMAND
- ```
-
-NOTE: **Note:**
-When `AUTO_DEVOPS_BUILD_IMAGE_FORWARDED_CI_VARIABLES` is set, Auto DevOps
-enables the experimental [Docker BuildKit](https://docs.docker.com/develop/develop-images/build_enhancements/)
-feature to use the `--secret` flag.
-
### Custom Helm Chart
Auto DevOps uses [Helm](https://helm.sh/) to deploy your application to Kubernetes.
@@ -861,7 +827,6 @@ applications.
| `ADDITIONAL_HOSTS` | Fully qualified domain names specified as a comma-separated list that are added to the ingress hosts. |
| `<ENVIRONMENT>_ADDITIONAL_HOSTS` | For a specific environment, the fully qualified domain names specified as a comma-separated list that are added to the ingress hosts. This takes precedence over `ADDITIONAL_HOSTS`. |
| `AUTO_DEVOPS_BUILD_IMAGE_EXTRA_ARGS` | Extra arguments to be passed to the `docker build` command. Note that using quotes will not prevent word splitting. [More details](#passing-arguments-to-docker-build). |
-| `AUTO_DEVOPS_BUILD_IMAGE_FORWARDED_CI_VARIABLES` | A [comma-separated list of CI variable names](#passing-secrets-to-docker-build-beta) to be passed to the `docker build` command as secrets. |
| `AUTO_DEVOPS_CHART` | Helm Chart used to deploy your apps. Defaults to the one [provided by GitLab](https://gitlab.com/gitlab-org/charts/auto-deploy-app). |
| `AUTO_DEVOPS_CHART_REPOSITORY` | Helm Chart repository used to search for charts. Defaults to `https://charts.gitlab.io`. |
| `AUTO_DEVOPS_CHART_REPOSITORY_NAME` | From Gitlab 11.11, used to set the name of the helm repository. Defaults to `gitlab`. |
@@ -1203,27 +1168,6 @@ There is no documented way of using private container registry with Auto DevOps.
We strongly advise using GitLab Container Registry with Auto DevOps in order to
simplify configuration and prevent any unforeseen issues.
-### Installing Helm behind a proxy
-
-GitLab does not yet support installing [Helm as a GitLab-managed App](../../user/clusters/applications.md#helm) when
-behind a proxy. Users who wish to do so must inject their proxy settings
-into the installation pods at runtime, for example by using a
-[`PodPreset`](https://kubernetes.io/docs/concepts/workloads/pods/podpreset/):
-
-```yml
-apiVersion: settings.k8s.io/v1alpha1
-kind: PodPreset
-metadata:
- name: gitlab-managed-apps-default-proxy
- namespace: gitlab-managed-apps
-spec:
- env:
- - name: http_proxy
- value: "PUT_YOUR_HTTP_PROXY_HERE"
- - name: https_proxy
- value: "PUT_YOUR_HTTPS_PROXY_HERE"
-```
-
## Troubleshooting
- Auto Build and Auto Test may fail in detecting your language/framework. There
@@ -1263,7 +1207,7 @@ curl --data "value=true" --header "PRIVATE-TOKEN: personal_access_token" https:/
[kubernetes-clusters]: ../../user/project/clusters/index.md
[docker-in-docker]: ../../docker/using_docker_build.md#use-docker-in-docker-executor
[review-app]: ../../ci/review_apps/index.md
-[container-registry]: ../../user/packages/container_registry/index.md
+[container-registry]: ../../user/project/container_registry.md
[postgresql]: https://www.postgresql.org/
[Auto DevOps template]: https://gitlab.com/gitlab-org/gitlab-ce/blob/master/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml
[ee]: https://about.gitlab.com/pricing/
diff --git a/doc/topics/autodevops/quick_start_guide.md b/doc/topics/autodevops/quick_start_guide.md
index d0ff149cf31..35a5aff6a60 100644
--- a/doc/topics/autodevops/quick_start_guide.md
+++ b/doc/topics/autodevops/quick_start_guide.md
@@ -152,7 +152,7 @@ The pipeline is split into 4 stages, each running a couple of jobs.
![Pipeline stages](img/guide_pipeline_stages.png)
In the **build** stage, the application is built into a Docker image and then
-uploaded to your project's [Container Registry](../../user/packages/container_registry/index.md) ([Auto Build](index.md#auto-build)).
+uploaded to your project's [Container Registry](../../user/project/container_registry.md) ([Auto Build](index.md#auto-build)).
In the **test** stage, GitLab runs various checks on the application:
diff --git a/doc/university/support/README.md b/doc/university/support/README.md
index 0634e01764f..fdeba89f9c8 100644
--- a/doc/university/support/README.md
+++ b/doc/university/support/README.md
@@ -145,7 +145,7 @@ Zendesk is our Support Centre and our main communication line with our Customers
Some tickets need specific knowledge or a deep understanding of a particular component and will need to be escalated to a Senior Service Engineer or Developer
-- Read about [Escalation](https://about.gitlab.com/handbook/support/workflows/issue_escalations.html)
+- Read about [Escalation](https://about.gitlab.com/handbook/support/workflows/shared/support_workflows/issue_escalations.html)
- Find the macros in Zendesk for ticket escalations
- Take a look at the [GitLab.com Team page](https://about.gitlab.com/team/) to find the resident experts in their fields
diff --git a/doc/user/application_security/container_scanning/index.md b/doc/user/application_security/container_scanning/index.md
index 7c24edb8558..c3f80c6a0fd 100644
--- a/doc/user/application_security/container_scanning/index.md
+++ b/doc/user/application_security/container_scanning/index.md
@@ -11,7 +11,7 @@ in [GitLab Ultimate](https://about.gitlab.com/pricing/) 10.4.
If you are using [GitLab CI/CD](../../../ci/README.md), you can check your Docker
images (or more precisely the containers) for known vulnerabilities by using
-[Clair](https://github.com/coreos/clair) and [klar](https://github.com/optiopay/klar),
+[Clair](https://github.com/coreos/clair) and [clair-scanner](https://github.com/arminc/clair-scanner),
two open source tools for Vulnerability Static Analysis for containers.
You can take advantage of Container Scanning by either [including the CI job](#configuration) in
@@ -48,7 +48,7 @@ To enable Container Scanning in your pipeline, you need:
running. If you're using the shared Runners on GitLab.com, this is already
the case.
- To [build and push](../../../ci/docker/using_docker_build.md#container-registry-examples)
- your Docker image to your project's [Container Registry](../../packages/container_registry/index.md).
+ your Docker image to your project's [Container Registry](../../project/container_registry.md).
The name of the Docker image should match the following scheme:
```text
@@ -79,7 +79,7 @@ The included template will:
1. Create a `container_scanning` job in your CI/CD pipeline.
1. Pull the already built Docker image from your project's
- [Container Registry](../../packages/container_registry/index.md) (see [requirements](#requirements))
+ [Container Registry](../../project/container_registry.md) (see [requirements](#requirements))
and scan it for possible vulnerabilities.
The results will be saved as a
@@ -90,6 +90,10 @@ artifact available. Behind the scenes, the
[GitLab Container Scanning analyzer](https://gitlab.com/gitlab-org/security-products/container-scanning)
is used and runs the scans.
+If you want to whitelist some specific vulnerabilities, you can do so by defining
+them in a YAML file named `clair-whitelist.yml`. Read more in the
+[Clair documentation](https://github.com/arminc/clair-scanner/blob/master/README.md#example-whitelist-yaml-file).
+
## Example
The following is a sample `.gitlab-ci.yml` that will build your Docker Image, push it to the container registry and run Container Scanning.
@@ -120,31 +124,6 @@ build:
- docker push $IMAGE
```
-## Vulnerability Whitelisting
-
-If you want to whitelist specific vulnerabilities, you'll need to:
-
- 1. Set `GIT_STRATEGY: fetch` in your `.gitlab-ci.yml` file by following the instructions described in the
- [overriding the Container Scanning template](#overriding-the-container-scanning-template) section of this document.
- 1. Define the whitelisted vulnerabilities in a YAML file named `clair-whitelist.yml` which must use the format described
- in the [following whitelist example file](https://github.com/arminc/clair-scanner/blob/v12/example-whitelist.yaml).
- 1. Add the `clair-whitelist.yml` file to the git repository of your project
-
-### Overriding the Container Scanning template
-
-If you want to override the job definition (for example, change properties like
-`variables`), you need to declare a `container_scanning` job after the
-template inclusion and specify any additional keys under it. For example:
-
-```yaml
-include:
- - template: Container-Scanning.gitlab-ci.yml
-
-container_scanning:
- variables:
- GIT_STRATEGY: fetch
-```
-
## Security Dashboard
The Security Dashboard is a good place to get an overview of all the security
diff --git a/doc/user/application_security/dependency_scanning/index.md b/doc/user/application_security/dependency_scanning/index.md
index 5baaa92d3d8..166a71b6fbe 100644
--- a/doc/user/application_security/dependency_scanning/index.md
+++ b/doc/user/application_security/dependency_scanning/index.md
@@ -58,7 +58,7 @@ The following languages and dependency managers are supported.
| JavaScript ([npm](https://www.npmjs.com/), [yarn](https://yarnpkg.com/en/)) | yes | [gemnasium](https://gitlab.com/gitlab-org/security-products/gemnasium), [Retire.js](https://retirejs.github.io/retire.js) |
| Go ([Golang](https://golang.org/)) | not currently ([issue](https://gitlab.com/gitlab-org/gitlab-ee/issues/7132 "Dependency Scanning for Go")) | not available |
| PHP ([Composer](https://getcomposer.org/)) | yes | [gemnasium](https://gitlab.com/gitlab-org/security-products/gemnasium) |
-| Python ([pip](https://pip.pypa.io/en/stable/)) | yes | [gemnasium](https://gitlab.com/gitlab-org/security-products/gemnasium) |
+| Python ([pip](https://pip.pypa.io/en/stable/)) (only `requirements.txt` supported) | yes | [gemnasium](https://gitlab.com/gitlab-org/security-products/gemnasium) |
| Python ([Pipfile](https://docs.pipenv.org/en/latest/basics/)) | not currently ([issue](https://gitlab.com/gitlab-org/gitlab-ee/issues/11756 "Pipfile.lock support for Dependency Scanning"))| not available |
| Python ([poetry](https://poetry.eustace.io/)) | not currently ([issue](https://gitlab.com/gitlab-org/gitlab-ee/issues/7006 "Support Poetry in Dependency Scanning")) | not available |
| Ruby ([gem](https://rubygems.org/)) | yes | [gemnasium](https://gitlab.com/gitlab-org/security-products/gemnasium), [bundler-audit](https://github.com/rubysec/bundler-audit) |
diff --git a/doc/user/clusters/applications.md b/doc/user/clusters/applications.md
index 17d430cf1f2..197a1fc61c1 100644
--- a/doc/user/clusters/applications.md
+++ b/doc/user/clusters/applications.md
@@ -67,11 +67,6 @@ required to install all the other applications. It is installed in its
own pod inside the cluster which can run the `helm` CLI in a safe
environment.
-NOTE: **Note:**
-Installing Helm as a GitLab-managed App behind a proxy is not supported,
-but a [workaround](../../topics/autodevops/index.md#installing-helm-behind-a-proxy)
-is available.
-
### Cert-Manager
> Introduced in GitLab 11.6 for project- and group-level clusters.
@@ -129,6 +124,34 @@ chart is used to install this application with a
[`values.yaml`](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/vendor/ingress/values.yaml)
file.
+#### Modsecurity Application Firewall
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/issues/65192) in GitLab 12.3 (enabled using `ingress_modsecurity` [feature flag](../../development/feature_flags/development.md#enabling-a-feature-flag-in-development)).
+
+GitLab supports
+[`modsecurity`](https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/annotations/#modsecurity)
+to check requests against [OWASP's Core Rule Set](https://www.modsecurity.org/CRS/Documentation/).
+This feature:
+
+- Runs in "Detection-only mode" unless configured otherwise.
+- Is viewable by checking your ingress controller's `modsec` log for rule violations.
+ For example:
+
+ ```sh
+ kubectl -n gitlab-managed-apps exec -it $(kubectl get pods -n gitlab-managed-apps | grep 'ingress-controller' | awk '{print $1}') -- tail -f /var/log/modsec_audit.log
+ ```
+
+There is a small performance overhead by enabling `modsecurity`. However, if this is
+considered significant for your application, you can toggle the feature flag back to
+false by running the following command within the Rails console:
+
+```ruby
+Feature.disable(:ingress_modsecurity)
+```
+
+Once disabled, you must reinstall your ingress application for the changes to
+take effect.
+
### JupyterHub
> - Introduced in GitLab 11.0 for project-level clusters.
diff --git a/doc/user/group/clusters/index.md b/doc/user/group/clusters/index.md
index d41f44f85cc..53229f5c286 100644
--- a/doc/user/group/clusters/index.md
+++ b/doc/user/group/clusters/index.md
@@ -137,6 +137,10 @@ The result will then be:
- The Staging cluster will be used for the `deploy to staging` job.
- The Production cluster will be used for the `deploy to production` job.
+## Cluster environments **(PREMIUM)**
+
+Please see the documentation for [cluster environments](../../clusters/environments.md).
+
## Security of Runners
For important information about securely configuring GitLab Runners, see
diff --git a/doc/user/group/dependency_proxy/index.md b/doc/user/group/dependency_proxy/index.md
index f735ec0214f..771468fbba8 100644
--- a/doc/user/group/dependency_proxy/index.md
+++ b/doc/user/group/dependency_proxy/index.md
@@ -1,5 +1,74 @@
----
-redirect_to: '../../packages/dependency_proxy/index.md'
----
+# Dependency Proxy **(PREMIUM)**
-This document was moved to [another location](../../packages/dependency_proxy/index.md).
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/issues/7934) in [GitLab Premium](https://about.gitlab.com/pricing/) 11.11.
+
+NOTE: **Note:**
+This is the user guide. In order to use the dependency proxy, an administrator
+must first [configure it](../../../administration/dependency_proxy.md).
+
+For many organizations, it is desirable to have a local proxy for frequently used
+upstream images/packages. In the case of CI/CD, the proxy is responsible for
+receiving a request and returning the upstream image from a registry, acting
+as a pull-through cache.
+
+The dependency proxy is available in the group level. To access it, navigate to
+a group's **Overview > Dependency Proxy**.
+
+![Dependency Proxy group page](img/group_dependency_proxy.png)
+
+## Supported dependency proxies
+
+NOTE: **Note:**
+For a list of the upcoming additions to the proxies, visit the
+[direction page](https://about.gitlab.com/direction/package/dependency_proxy/#top-vision-items).
+
+The following dependency proxies are supported.
+
+| Dependency proxy | GitLab version |
+| ---------------- | -------------- |
+| Docker | 11.11+ |
+
+## Using the Docker dependency proxy
+
+With the Docker dependency proxy, you can use GitLab as a source for a Docker image.
+To get a Docker image into the dependency proxy:
+
+1. Find the proxy URL on your group's page under **Overview > Dependency Proxy**,
+ for example `gitlab.com/groupname/dependency_proxy/containers`.
+1. Trigger GitLab to pull the Docker image you want (e.g., `alpine:latest` or
+ `linuxserver/nextcloud:latest`) and store it in the proxy storage by using
+ one of the following ways:
+
+ - Manually pulling the Docker image:
+
+ ```bash
+ docker pull gitlab.com/groupname/dependency_proxy/containers/alpine:latest
+ ```
+
+ - From a `Dockerfile`:
+
+ ```bash
+ FROM gitlab.com/groupname/dependency_proxy/containers/alpine:latest
+ ```
+
+ - In [`.gitlab-ci.yml`](../../../ci/yaml/README.md#image):
+
+ ```bash
+ image: gitlab.com/groupname/dependency_proxy/containers/alpine:latest
+ ```
+
+GitLab will then pull the Docker image from Docker Hub and will cache the blobs
+on the GitLab server. The next time you pull the same image, it will get the latest
+information about the image from Docker Hub but will serve the existing blobs
+from GitLab.
+
+The blobs are kept forever, and there is no hard limit on how much data can be
+stored.
+
+## Limitations
+
+The following limitations apply:
+
+- Only public groups are supported (authentication is not supported yet).
+- Only Docker Hub is supported.
+- This feature requires Docker Hub being available.
diff --git a/doc/user/group/index.md b/doc/user/group/index.md
index a0bdb737466..c09acd36e31 100644
--- a/doc/user/group/index.md
+++ b/doc/user/group/index.md
@@ -285,7 +285,7 @@ To change your group path:
CAUTION: **Caution:**
It is currently not possible to rename a namespace if it contains a
-project with [Container Registry](../packages/container_registry/index.md) tags,
+project with [Container Registry](../project/container_registry.md) tags,
because the project cannot be moved.
TIP: **TIP:**
@@ -461,7 +461,7 @@ With [GitLab Issues Analytics](issues_analytics/index.md), you can see a bar cha
## Dependency Proxy **(PREMIUM)**
-Use GitLab as a [dependency proxy](../packages/dependency_proxy/index.md) for upstream Docker images.
+Use GitLab as a [dependency proxy](dependency_proxy/index.md) for upstream Docker images.
<!-- ## Troubleshooting
diff --git a/doc/user/index.md b/doc/user/index.md
index e1833cab6b8..27e75189fc3 100644
--- a/doc/user/index.md
+++ b/doc/user/index.md
@@ -44,7 +44,7 @@ GitLab is a Git-based platform that integrates a great number of essential tools
branch with [Review Apps](../ci/review_apps/index.md).
- Building, testing, and deploying with built-in [Continuous Integration](../ci/README.md).
- Deploying personal and professional static websites with [GitLab Pages](project/pages/index.md).
-- Integrating with Docker by using [GitLab Container Registry](packages/container_registry/index.md).
+- Integrating with Docker by using [GitLab Container Registry](project/container_registry.md).
- Tracking the development lifecycle by using [GitLab Cycle Analytics](project/cycle_analytics.md).
With GitLab Enterprise Edition, you can also:
@@ -92,7 +92,7 @@ directly from GitLab. No third-party integrations needed.
- [Review Apps](../ci/review_apps/index.md): Live-preview the changes introduced by a merge request with Review Apps.
- [GitLab Pages](project/pages/index.md): Publish your static site directly from
GitLab with GitLab Pages. You can build, test, and deploy any Static Site Generator with Pages.
-- [GitLab Container Registry](packages/container_registry/index.md): Build and deploy Docker
+- [GitLab Container Registry](project/container_registry.md): Build and deploy Docker
images with Container Registry.
## Account
diff --git a/doc/user/packages/container_registry/index.md b/doc/user/packages/container_registry/index.md
deleted file mode 100644
index 710e7bd405b..00000000000
--- a/doc/user/packages/container_registry/index.md
+++ /dev/null
@@ -1,158 +0,0 @@
-# GitLab Container Registry
-
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/4040) in GitLab 8.8.
-> - Docker Registry manifest `v1` support was added in GitLab 8.9 to support Docker
-> versions earlier than 1.10.
-> - Starting from GitLab 8.12, if you have 2FA enabled in your account, you need
-> to pass a [personal access token](../../profile/personal_access_tokens.md) instead of your password in order to
-> login to GitLab's Container Registry.
-> - Multiple level image names support was added in GitLab 9.1.
-
-NOTE: **Note:**
-This document is the user guide. To learn how to enable GitLab Container
-Registry across your GitLab instance, visit the
-[administrator documentation](../../../administration/packages/container_registry.md).
-
-With the Docker Container Registry integrated into GitLab, every project can
-have its own space to store its Docker images.
-
-You can read more about Docker Registry at <https://docs.docker.com/registry/introduction/>.
-
-## Enable the Container Registry for your project
-
-If you cannot find the **Packages > Container Registry** entry under your
-project's sidebar, it is not enabled in your GitLab instance. Ask your
-administrator to enable GitLab Container Registry following the
-[administration documentation](../../../administration/packages/container_registry.md).
-
-If you are using GitLab.com, this is enabled by default so you can start using
-the Registry immediately. Currently there is a soft (10GB) size restriction for
-Registry on GitLab.com, as part of the [repository size limit](../../project/repository/index.md).
-
-Once enabled for your GitLab instance, to enable Container Registry for your
-project:
-
-1. Go to your project's **Settings > General** page.
-1. Expand the **Visibility, project features, permissions** section
- and enable the **Container Registry** feature on your project. For new
- projects this might be enabled by default. For existing projects
- (prior GitLab 8.8), you will have to explicitly enable it.
-1. Press **Save changes** for the changes to take effect. You should now be able
- to see the **Packages > Container Registry** link in the sidebar.
-
-## Build and push images
-
-> **Notes:**
->
-> - Moving or renaming existing container registry repositories is not supported
-> once you have pushed images because the images are signed, and the
-> signature includes the repository name.
-> - To move or rename a repository with a container registry you will have to
-> delete all existing images.
-
-If you visit the **Packages > Container Registry** link under your project's
-menu, you can see the explicit instructions to login to the Container Registry
-using your GitLab credentials.
-
-For example if the Registry's URL is `registry.example.com`, then you should be
-able to login with:
-
-```sh
-docker login registry.example.com
-```
-
-Building and publishing images should be a straightforward process. Just make
-sure that you are using the Registry URL with the namespace and project name
-that is hosted on GitLab:
-
-```sh
-docker build -t registry.example.com/group/project/image .
-docker push registry.example.com/group/project/image
-```
-
-Your image will be named after the following scheme:
-
-```text
-<registry URL>/<namespace>/<project>/<image>
-```
-
-GitLab supports up to three levels of image repository names.
-
-Following examples of image tags are valid:
-
-```text
-registry.example.com/group/project:some-tag
-registry.example.com/group/project/image:latest
-registry.example.com/group/project/my/image:rc1
-```
-
-## Use images from GitLab Container Registry
-
-To download and run a container from images hosted in GitLab Container Registry,
-use `docker run`:
-
-```sh
-docker run [options] registry.example.com/group/project/image [arguments]
-```
-
-For more information on running Docker containers, visit the
-[Docker documentation](https://docs.docker.com/engine/userguide/intro/).
-
-## Control Container Registry from within GitLab
-
-GitLab offers a simple Container Registry management panel. Go to your project
-and click **Packages > Container Registry** in the project menu.
-
-This view will show you all tags in your project and will easily allow you to
-delete them.
-
-## Build and push images using GitLab CI
-
-NOTE: **Note:**
-This feature requires GitLab 8.8 and GitLab Runner 1.2.
-
-Make sure that your GitLab Runner is configured to allow building Docker images by
-following the [Using Docker Build](../../../ci/docker/using_docker_build.md)
-and [Using the GitLab Container Registry documentation](../../../ci/docker/using_docker_build.md#using-the-gitlab-container-registry).
-Alternatively, you can [build images with Kaniko](../../../ci/docker/using_kaniko.md) if the Docker builds are not an option for you.
-
-## Using with private projects
-
-> Personal Access tokens were [introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/11845) in GitLab 9.3.
-> Project Deploy Tokens were [introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/17894) in GitLab 10.7
-
-If a project is private, credentials will need to be provided for authorization.
-There are two ways to do this:
-
-- By using a [personal access token](../../profile/personal_access_tokens.md).
-- By using a [deploy token](../../project/deploy_tokens/index.md).
-
-The minimal scope needed for both of them is `read_registry`.
-
-Example of using a token:
-
-```sh
-docker login registry.example.com -u <username> -p <token>
-```
-
-## Troubleshooting the GitLab Container Registry
-
-### Docker connection error
-
-A Docker connection error can occur when there are special characters in either the group,
-project or branch name. Special characters can include:
-
-- Leading underscore
-- Trailing hyphen/dash
-- Double hyphen/dash
-
-To get around this, you can [change the group path](../../group/index.md#changing-a-groups-path),
-[change the project path](../../project/settings/index.md#renaming-a-repository) or change the branch
-name.
-
-### Troubleshoot as a GitLab server admin
-
-Troubleshooting the GitLab Container Registry, most of the times, requires
-administration access to the GitLab server.
-
-[Read how to troubleshoot the Container Registry](../../../administration/packages/container_registry.md#troubleshooting).
diff --git a/doc/user/packages/dependency_proxy/img/group_dependency_proxy.png b/doc/user/packages/dependency_proxy/img/group_dependency_proxy.png
deleted file mode 100644
index 035aff0b6c4..00000000000
--- a/doc/user/packages/dependency_proxy/img/group_dependency_proxy.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/packages/dependency_proxy/index.md b/doc/user/packages/dependency_proxy/index.md
deleted file mode 100644
index 8c337f74dcf..00000000000
--- a/doc/user/packages/dependency_proxy/index.md
+++ /dev/null
@@ -1,74 +0,0 @@
-# Dependency Proxy **(PREMIUM)**
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/issues/7934) in [GitLab Premium](https://about.gitlab.com/pricing/) 11.11.
-
-NOTE: **Note:**
-This is the user guide. In order to use the dependency proxy, an administrator
-must first [configure it](../../../administration/packages/dependency_proxy.md).
-
-For many organizations, it is desirable to have a local proxy for frequently used
-upstream images/packages. In the case of CI/CD, the proxy is responsible for
-receiving a request and returning the upstream image from a registry, acting
-as a pull-through cache.
-
-The dependency proxy is available in the group level. To access it, navigate to
-a group's **Overview > Dependency Proxy**.
-
-![Dependency Proxy group page](img/group_dependency_proxy.png)
-
-## Supported dependency proxies
-
-NOTE: **Note:**
-For a list of the upcoming additions to the proxies, visit the
-[direction page](https://about.gitlab.com/direction/package/dependency_proxy/#top-vision-items).
-
-The following dependency proxies are supported.
-
-| Dependency proxy | GitLab version |
-| ---------------- | -------------- |
-| Docker | 11.11+ |
-
-## Using the Docker dependency proxy
-
-With the Docker dependency proxy, you can use GitLab as a source for a Docker image.
-To get a Docker image into the dependency proxy:
-
-1. Find the proxy URL on your group's page under **Overview > Dependency Proxy**,
- for example `gitlab.com/groupname/dependency_proxy/containers`.
-1. Trigger GitLab to pull the Docker image you want (e.g., `alpine:latest` or
- `linuxserver/nextcloud:latest`) and store it in the proxy storage by using
- one of the following ways:
-
- - Manually pulling the Docker image:
-
- ```bash
- docker pull gitlab.com/groupname/dependency_proxy/containers/alpine:latest
- ```
-
- - From a `Dockerfile`:
-
- ```bash
- FROM gitlab.com/groupname/dependency_proxy/containers/alpine:latest
- ```
-
- - In [`.gitlab-ci.yml`](../../../ci/yaml/README.md#image):
-
- ```bash
- image: gitlab.com/groupname/dependency_proxy/containers/alpine:latest
- ```
-
-GitLab will then pull the Docker image from Docker Hub and will cache the blobs
-on the GitLab server. The next time you pull the same image, it will get the latest
-information about the image from Docker Hub but will serve the existing blobs
-from GitLab.
-
-The blobs are kept forever, and there is no hard limit on how much data can be
-stored.
-
-## Limitations
-
-The following limitations apply:
-
-- Only public groups are supported (authentication is not supported yet).
-- Only Docker Hub is supported.
-- This feature requires Docker Hub being available.
diff --git a/doc/user/packages/index.md b/doc/user/packages/index.md
deleted file mode 100644
index 506eb5703a6..00000000000
--- a/doc/user/packages/index.md
+++ /dev/null
@@ -1,19 +0,0 @@
-# GitLab Package Registry
-
-GitLab Packages allows organizations to utilize GitLab as a private repository
-for a variety of common package managers. Users are able to build and publish
-packages, which can be easily consumed as a dependency in downstream projects.
-
-The Packages feature allows GitLab to act as a repository for the following:
-
-| Software repository | Description | Available in GitLab version |
-| ------------------- | ----------- | --------------------------- |
-| [Container Registry](container_registry/index.md) | The GitLab Container Registry enables every project in GitLab to have its own space to store [Docker](https://www.docker.com/) images. | 8.8+ |
-| [Dependency Proxy](dependency_proxy/index.md) **(PREMIUM)** | The GitLab Dependency Proxy sets up a local proxy for frequently used upstream images/packages. | 11.11+ |
-| [Maven Repository](maven_repository/index.md) **(PREMIUM)** | The GitLab Maven Repository enables every project in GitLab to have its own space to store [Maven](https://maven.apache.org/) packages. | 11.3+ |
-| [NPM Registry](npm_registry/index.md) **(PREMIUM)** | The GitLab NPM Registry enables every project in GitLab to have its own space to store [NPM](https://www.npmjs.com/) packages. | 11.7+ |
-
-TIP: **Tip:**
-Don't you see your package management system supported yet? Consider contributing
-to GitLab. This [development documentation](../../development/packages.md) will
-guide you through the process.
diff --git a/doc/user/packages/maven_repository/img/maven_package_view.png b/doc/user/packages/maven_repository/img/maven_package_view.png
deleted file mode 100644
index 2eb4b6f76b4..00000000000
--- a/doc/user/packages/maven_repository/img/maven_package_view.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/packages/maven_repository/index.md b/doc/user/packages/maven_repository/index.md
deleted file mode 100644
index 2c400653fcc..00000000000
--- a/doc/user/packages/maven_repository/index.md
+++ /dev/null
@@ -1,340 +0,0 @@
-# GitLab Maven Repository **(PREMIUM)**
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/issues/5811) in [GitLab Premium](https://about.gitlab.com/pricing/) 11.3.
-
-With the GitLab [Maven](https://maven.apache.org) Repository, every
-project can have its own space to store its Maven artifacts.
-
-![GitLab Maven Repository](img/maven_package_view.png)
-
-## Enabling the Maven Repository
-
-NOTE: **Note:**
-This option is available only if your GitLab administrator has
-[enabled support for the Maven repository](../../../administration/packages/index.md).**(PREMIUM ONLY)**
-
-After the Packages feature is enabled, the Maven Repository will be available for
-all new projects by default. To enable it for existing projects, or if you want
-to disable it:
-
-1. Navigate to your project's **Settings > General > Permissions**.
-1. Find the Packages feature and enable or disable it.
-1. Click on **Save changes** for the changes to take effect.
-
-You should then be able to see the **Packages** section on the left sidebar.
-Next, you must configure your project to authorize with the GitLab Maven
-repository.
-
-## Authenticating to the GitLab Maven Repository
-
-If a project is private or you want to upload Maven artifacts to GitLab,
-credentials will need to be provided for authorization. Support is available for
-[personal access tokens](#authenticating-with-a-personal-access-token) and
-[CI job tokens](#authenticating-with-a-ci-job-token) only.
-[Deploy tokens](../../project/deploy_tokens/index.md) and regular username/password
-credentials do not work.
-
-### Authenticating with a personal access token
-
-To authenticate with a [personal access token](../../profile/personal_access_tokens.md),
-add a corresponding section to your
-[`settings.xml`](https://maven.apache.org/settings.html) file:
-
-```xml
-<settings>
- <servers>
- <server>
- <id>gitlab-maven</id>
- <configuration>
- <httpHeaders>
- <property>
- <name>Private-Token</name>
- <value>REPLACE_WITH_YOUR_PERSONAL_ACCESS_TOKEN</value>
- </property>
- </httpHeaders>
- </configuration>
- </server>
- </servers>
-</settings>
-```
-
-You should now be able to upload Maven artifacts to your project.
-
-### Authenticating with a CI job token
-
-If you're using Maven with GitLab CI/CD, a CI job token can be used instead
-of a personal access token.
-
-To authenticate with a CI job token, add a corresponding section to your
-[`settings.xml`](https://maven.apache.org/settings.html) file:
-
-```xml
-<settings>
- <servers>
- <server>
- <id>gitlab-maven</id>
- <configuration>
- <httpHeaders>
- <property>
- <name>Job-Token</name>
- <value>${env.CI_JOB_TOKEN}</value>
- </property>
- </httpHeaders>
- </configuration>
- </server>
- </servers>
-</settings>
-```
-
-You can read more on
-[how to create Maven packages using GitLab CI/CD](#creating-maven-packages-with-gitlab-cicd).
-
-## Configuring your project to use the GitLab Maven repository URL
-
-To download and upload packages from GitLab, you need a `repository` and
-`distributionManagement` section in your `pom.xml` file.
-
-Depending on your workflow and the amount of Maven packages you have, there are
-3 ways you can configure your project to use the GitLab endpoint for Maven packages:
-
-- **Project level**: Useful when you have few Maven packages which are not under
- the same GitLab group.
-- **Group level**: Useful when you have many Maven packages under the same GitLab
- group.
-- **Instance level**: Useful when you have many Maven packages under different
- GitLab groups or on their own namespace.
-
-NOTE: **Note:**
-In all cases, you need a project specific URL for uploading a package in
-the `distributionManagement` section.
-
-### Project level Maven endpoint
-
-The example below shows how the relevant `repository` section of your `pom.xml`
-would look like:
-
-```xml
-<repositories>
- <repository>
- <id>gitlab-maven</id>
- <url>https://gitlab.com/api/v4/projects/PROJECT_ID/packages/maven</url>
- </repository>
-</repositories>
-<distributionManagement>
- <repository>
- <id>gitlab-maven</id>
- <url>https://gitlab.com/api/v4/projects/PROJECT_ID/packages/maven</url>
- </repository>
- <snapshotRepository>
- <id>gitlab-maven</id>
- <url>https://gitlab.com/api/v4/projects/PROJECT_ID/packages/maven</url>
- </snapshotRepository>
-</distributionManagement>
-```
-
-The `id` must be the same with what you
-[defined in `settings.xml`](#authenticating-to-the-gitlab-maven-repository).
-
-Replace `PROJECT_ID` with your project ID which can be found on the home page
-of your project.
-
-If you have a self-hosted GitLab installation, replace `gitlab.com` with your
-domain name.
-
-NOTE: **Note:**
-For retrieving artifacts, you can use either the
-[URL encoded](../../../api/README.md#namespaced-path-encoding) path of the project
-(e.g., `group%2Fproject`) or the project's ID (e.g., `42`). However, only the
-project's ID can be used for uploading.
-
-### Group level Maven endpoint
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/8798) in GitLab Premium 11.7.
-
-If you rely on many packages, it might be inefficient to include the `repository` section
-with a unique URL for each package. Instead, you can use the group level endpoint for
-all your Maven packages stored within one GitLab group. Only packages you have access to
-will be available for download.
-
-The group level endpoint works with any package names, which means the you
-have the flexibility of naming compared to [instance level endpoint](#instance-level-maven-endpoint).
-However, GitLab will not guarantee the uniqueness of the package names within
-the group. You can have two projects with the same package name and package
-version. As a result, GitLab will serve whichever one is more recent.
-
-The example below shows how the relevant `repository` section of your `pom.xml`
-would look like. You still need a project specific URL for uploading a package in
-the `distributionManagement` section:
-
-```xml
-<repositories>
- <repository>
- <id>gitlab-maven</id>
- <url>https://gitlab.com/api/v4/groups/my-group/-/packages/maven</url>
- </repository>
-</repositories>
-<distributionManagement>
- <repository>
- <id>gitlab-maven</id>
- <url>https://gitlab.com/api/v4/projects/PROJECT_ID/packages/maven</url>
- </repository>
- <snapshotRepository>
- <id>gitlab-maven</id>
- <url>https://gitlab.com/api/v4/projects/PROJECT_ID/packages/maven</url>
- </snapshotRepository>
-</distributionManagement>
-```
-
-The `id` must be the same with what you
-[defined in `settings.xml`](#authenticating-to-the-gitlab-maven-repository).
-
-Replace `my-group` with your group name and `PROJECT_ID` with your project ID
-which can be found on the home page of your project.
-
-If you have a self-hosted GitLab installation, replace `gitlab.com` with your
-domain name.
-
-NOTE: **Note:**
-For retrieving artifacts, you can use either the
-[URL encoded](../../../api/README.md#namespaced-path-encoding) path of the group
-(e.g., `group%2Fsubgroup`) or the group's ID (e.g., `12`).
-
-### Instance level Maven endpoint
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/8274) in GitLab Premium 11.7.
-
-If you rely on many packages, it might be inefficient to include the `repository` section
-with a unique URL for each package. Instead, you can use the instance level endpoint for
-all maven packages stored in GitLab and the packages you have access to will be available
-for download.
-
-Note that **only packages that have the same path as the project** are exposed via
-the instance level endpoint.
-
-| Project | Package | Instance level endpoint available |
-| ------- | ------- | --------------------------------- |
-| `foo/bar` | `foo/bar/1.0-SNAPSHOT` | Yes |
-| `gitlab-org/gitlab-ce` | `foo/bar/1.0-SNAPSHOT` | No |
-| `gitlab-org/gitlab-ce` | `gitlab-org/gitlab-ce/1.0-SNAPSHOT` | Yes |
-
-The example below shows how the relevant `repository` section of your `pom.xml`
-would look like. You still need a project specific URL for uploading a package in
-the `distributionManagement` section:
-
-```xml
-<repositories>
- <repository>
- <id>gitlab-maven</id>
- <url>https://gitlab.com/api/v4/packages/maven</url>
- </repository>
-</repositories>
-<distributionManagement>
- <repository>
- <id>gitlab-maven</id>
- <url>https://gitlab.com/api/v4/projects/PROJECT_ID/packages/maven</url>
- </repository>
- <snapshotRepository>
- <id>gitlab-maven</id>
- <url>https://gitlab.com/api/v4/projects/PROJECT_ID/packages/maven</url>
- </snapshotRepository>
-</distributionManagement>
-```
-
-The `id` must be the same with what you
-[defined in `settings.xml`](#authenticating-to-the-gitlab-maven-repository).
-
-Replace `PROJECT_ID` with your project ID which can be found on the home page
-of your project.
-
-If you have a self-hosted GitLab installation, replace `gitlab.com` with your
-domain name.
-
-NOTE: **Note:**
-For retrieving artifacts, you can use either the
-[URL encoded](../../../api/README.md#namespaced-path-encoding) path of the project
-(e.g., `group%2Fproject`) or the project's ID (e.g., `42`). However, only the
-project's ID can be used for uploading.
-
-## Uploading packages
-
-Once you have set up the [authentication](#authenticating-to-the-gitlab-maven-repository)
-and [configuration](#configuring-your-project-to-use-the-gitlab-maven-repository-url),
-test to upload a Maven artifact from a project of yours:
-
-```sh
-mvn deploy
-```
-
-You can then navigate to your project's **Packages** page and see the uploaded
-artifacts or even delete them.
-
-## Creating Maven packages with GitLab CI/CD
-
-Once you have your repository configured to use the GitLab Maven Repository,
-you can configure GitLab CI/CD to build new packages automatically. The example below
-shows how to create a new package each time the `master` branch is updated:
-
-1. Create a `ci_settings.xml` file that will serve as Maven's `settings.xml` file.
- Add the server section with the same id you defined in your `pom.xml` file.
- For example, in our case it's `gitlab-maven`:
-
- ```xml
- <settings xmlns="http://maven.apache.org/SETTINGS/1.1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.1.0 http://maven.apache.org/xsd/settings-1.1.0.xsd">
- <servers>
- <server>
- <id>gitlab-maven</id>
- <configuration>
- <httpHeaders>
- <property>
- <name>Job-Token</name>
- <value>${env.CI_JOB_TOKEN}</value>
- </property>
- </httpHeaders>
- </configuration>
- </server>
- </servers>
- </settings>
- ```
-
-1. Make sure your `pom.xml` file includes the following:
-
- ```xml
- <repositories>
- <repository>
- <id>gitlab-maven</id>
- <url>https://gitlab.com/api/v4/projects/${env.CI_PROJECT_ID}/packages/maven</url>
- </repository>
- </repositories>
- <distributionManagement>
- <repository>
- <id>gitlab-maven</id>
- <url>https://gitlab.com/api/v4/projects/${env.CI_PROJECT_ID}/packages/maven</url>
- </repository>
- <snapshotRepository>
- <id>gitlab-maven</id>
- <url>https://gitlab.com/api/v4/projects/${env.CI_PROJECT_ID}/packages/maven</url>
- </snapshotRepository>
- </distributionManagement>
- ```
-
- TIP: **Tip:**
- You can either let Maven utilize the CI environment variables or hardcode your project's ID.
-
-1. Add a `deploy` job to your `.gitlab-ci.yml` file:
-
- ```yaml
- deploy:
- image: maven:3.3.9-jdk-8
- script:
- - 'mvn deploy -s ci_settings.xml'
- only:
- - master
- ```
-
-1. Push those files to your repository.
-
-The next time the `deploy` job runs, it will copy `ci_settings.xml` to the
-user's home location (in this case the user is `root` since it runs in a
-Docker container), and Maven will utilize the configured CI
-[environment variables](../../../ci/variables/README.md#predefined-environment-variables).
diff --git a/doc/user/packages/npm_registry/img/npm_package_view.png b/doc/user/packages/npm_registry/img/npm_package_view.png
deleted file mode 100644
index e0634718c02..00000000000
--- a/doc/user/packages/npm_registry/img/npm_package_view.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/packages/npm_registry/index.md b/doc/user/packages/npm_registry/index.md
deleted file mode 100644
index 30de301b96a..00000000000
--- a/doc/user/packages/npm_registry/index.md
+++ /dev/null
@@ -1,147 +0,0 @@
-# GitLab NPM Registry **(PREMIUM)**
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/issues/5934) in [GitLab Premium](https://about.gitlab.com/pricing/) 11.7.
-
-With the GitLab NPM Registry, every
-project can have its own space to store NPM packages.
-
-![GitLab NPM Registry](img/npm_package_view.png)
-
-NOTE: **Note:**
-Only [scoped](https://docs.npmjs.com/misc/scope) packages are supported.
-
-## Enabling the NPM Registry
-
-NOTE: **Note:**
-This option is available only if your GitLab administrator has
-[enabled support for the NPM registry](../../../administration/packages/index.md).**(PREMIUM ONLY)**
-
-After the NPM registry is enabled, it will be available for all new projects
-by default. To enable it for existing projects, or if you want to disable it:
-
-1. Navigate to your project's **Settings > General > Permissions**.
-1. Find the Packages feature and enable or disable it.
-1. Click on **Save changes** for the changes to take effect.
-
-You should then be able to see the **Packages** section on the left sidebar.
-
-Before proceeding to authenticating with the GitLab NPM Registry, you should
-get familiar with the package naming convention.
-
-## Package naming convention
-
-**Packages must be scoped in the root namespace of the project**. The package
-name may be anything but it is preferred that the project name be used unless
-it is not possible due to a naming collision. For example:
-
-| Project | Package | Supported |
-| ---------------------- | ----------------------- | --------- |
-| `foo/bar` | `@foo/bar` | Yes |
-| `foo/bar/baz` | `@foo/baz` | Yes |
-| `foo/bar/buz` | `@foo/anything` | Yes |
-| `gitlab-org/gitlab-ce` | `@gitlab-org/gitlab-ce` | Yes |
-| `gitlab-org/gitlab-ce` | `@foo/bar` | No |
-
-Now, you can configure your project to authenticate with the GitLab NPM
-Registry.
-
-## Authenticating to the GitLab NPM Registry
-
-If a project is private or you want to upload an NPM package to GitLab,
-credentials will need to be provided for authentication. Support is available for [OAuth tokens](../../../api/oauth2.md#resource-owner-password-credentials-flow) or [personal access tokens](../../profile/personal_access_tokens.md).
-
-CAUTION: **2FA is only supported with personal access tokens:**
-If you have 2FA enabled, you need to use a [personal access token](../../profile/personal_access_tokens.md) with OAuth headers. Standard OAuth tokens won't be able to authenticate to the GitLab NPM Registry.
-
-### Authenticating with an OAuth token
-
-To authenticate with an [OAuth token](../../../api/oauth2.md#resource-owner-password-credentials-flow)
-or [personal access token](../../profile/personal_access_tokens.md), add a corresponding section to your `.npmrc` file:
-
-```ini
-; Set URL for your scoped packages.
-; For example package with name `@foo/bar` will use this URL for download
-@foo:registry=https://gitlab.com/api/v4/packages/npm/
-
-; Add the token for the scoped packages URL. This will allow you to download
-; `@foo/` packages from private projects.
-//gitlab.com/api/v4/packages/npm/:_authToken=<your_token>
-
-; Add token for uploading to the registry. Replace <your_project_id>
-; with the project you want your package to be uploaded to.
-//gitlab.com/api/v4/projects/<your_project_id>/packages/npm/:_authToken=<your_token>
-```
-
-Replace `<your_project_id>` with your project ID which can be found on the home page
-of your project and `<your_token>` with your OAuth or personal access token.
-
-If you have a self-hosted GitLab installation, replace `gitlab.com` with your
-domain name.
-
-You should now be able to download and upload NPM packages to your project.
-
-NOTE: **Note:**
-If you encounter an error message with [Yarn](https://yarnpkg.com/en/), see the
-[troubleshooting section](#troubleshooting).
-
-## Uploading packages
-
-Before you will be able to upload a package, you need to specify the registry
-for NPM. To do this, add the following section to the bottom of `package.json`:
-
-```json
- "publishConfig": {
- "@foo:registry":"https://gitlab.com/api/v4/projects/<your_project_id>/packages/npm/"
- }
-```
-
-Replace `<your_project_id>` with your project ID, which can be found on the home
-page of your project, and replace `@foo` with your own scope.
-
-If you have a self-hosted GitLab installation, replace `gitlab.com` with your
-domain name.
-
-Once you have enabled it and set up [authentication](#authenticating-to-the-gitlab-npm-registry),
-you can upload an NPM package to your project:
-
-```sh
-npm publish
-```
-
-You can then navigate to your project's **Packages** page and see the uploaded
-packages or even delete them.
-
-If you attempt to publish a package with a name that already exists within
-a given scope, you will receive a `403 Forbidden!` error.
-
-## Uploading a package with the same version twice
-
-If you upload a package with a same name and version twice, GitLab will show
-both packages in the UI, but the GitLab NPM Registry will expose the most recent
-one as it supports only one package per version for `npm install`.
-
-## Troubleshooting
-
-### Error running yarn with NPM registry
-
-If you are using [yarn](https://yarnpkg.com/en/) with the NPM registry, you may get
-an error message like:
-
-```sh
-yarn install v1.15.2
-warning package.json: No license field
-info No lockfile found.
-warning XXX: No license field
-[1/4] 🔍 Resolving packages...
-[2/4] 🚚 Fetching packages...
-error An unexpected error occurred: "https://gitlab.com/api/v4/projects/XXX/packages/npm/XXX/XXX/-/XXX/XXX-X.X.X.tgz: Request failed \"404 Not Found\"".
-info If you think this is a bug, please open a bug report with the information provided in "/Users/XXX/gitlab-migration/module-util/yarn-error.log".
-info Visit https://yarnpkg.com/en/docs/cli/install for documentation about this command
-```
-
-In this case, try adding this to your `.npmrc` file (and replace `<your_oauth_token>`
-with your with your OAuth or personal access token):
-
-```text
-//gitlab.com/api/v4/projects/:_authToken=<your_oauth_token>
-```
diff --git a/doc/user/permissions.md b/doc/user/permissions.md
index 8232ae44c68..46a3090e268 100644
--- a/doc/user/permissions.md
+++ b/doc/user/permissions.md
@@ -76,8 +76,8 @@ The following table depicts the various user permission levels in a project.
| See a list of merge requests | | ✓ | ✓ | ✓ | ✓ |
| View project statistics | | ✓ | ✓ | ✓ | ✓ |
| View Error Tracking list | | ✓ | ✓ | ✓ | ✓ |
-| Pull from [Maven repository](packages/maven_repository/index.md) or [NPM registry](packages/npm_registry/index.md) **(PREMIUM)** | | ✓ | ✓ | ✓ | ✓ |
-| Publish to [Maven repository](packages/maven_repository/index.md) or [NPM registry](packages/npm_registry/index.md) **(PREMIUM)** | | | ✓ | ✓ | ✓ |
+| Pull from [Maven repository](project/packages/maven_repository.md) or [NPM registry](project/packages/npm_registry.md) **(PREMIUM)** | | ✓ | ✓ | ✓ | ✓ |
+| Publish to [Maven repository](project/packages/maven_repository.md) or [NPM registry](project/packages/npm_registry.md) **(PREMIUM)** | | | ✓ | ✓ | ✓ |
| Upload [Design Management](project/issues/design_management.md) files **(PREMIUM)** | | | ✓ | ✓ | ✓ |
| Create new branches | | | ✓ | ✓ | ✓ |
| Push to non-protected branches | | | ✓ | ✓ | ✓ |
diff --git a/doc/user/profile/index.md b/doc/user/profile/index.md
index d9144f9b5fd..40b7294c3bb 100644
--- a/doc/user/profile/index.md
+++ b/doc/user/profile/index.md
@@ -75,7 +75,7 @@ To change your `username`:
CAUTION: **Caution:**
It is currently not possible to change your username if it contains a
-project with [Container Registry](../packages/container_registry/index.md) tags,
+project with [Container Registry](../project/container_registry.md) tags,
because the project cannot be moved.
TIP: **Tip:**
diff --git a/doc/user/profile/personal_access_tokens.md b/doc/user/profile/personal_access_tokens.md
index ffe6104698f..d556daa3460 100644
--- a/doc/user/profile/personal_access_tokens.md
+++ b/doc/user/profile/personal_access_tokens.md
@@ -53,7 +53,7 @@ the following table.
[2fa]: ../account/two_factor_authentication.md
[api]: ../../api/README.md
[ce-3749]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/3749
-[container registry]: ../packages/container_registry/index.md
+[container registry]: ../project/container_registry.md
[users]: ../../api/users.md
[usage]: ../../api/README.md#personal-access-tokens
diff --git a/doc/user/project/container_registry.md b/doc/user/project/container_registry.md
index 91c9d3171dc..c9eb81b990c 100644
--- a/doc/user/project/container_registry.md
+++ b/doc/user/project/container_registry.md
@@ -1,5 +1,317 @@
----
-redirect_to: '../packages/container_registry/index.md'
----
+# GitLab Container Registry
-This document was moved to [another location](../packages/container_registry/index.md).
+> - [Introduced][ce-4040] in GitLab 8.8.
+> - Docker Registry manifest `v1` support was added in GitLab 8.9 to support Docker
+> versions earlier than 1.10.
+> - Starting from GitLab 8.12, if you have 2FA enabled in your account, you need
+> to pass a [personal access token][pat] instead of your password in order to
+> login to GitLab's Container Registry.
+> - Multiple level image names support was added in GitLab 9.1.
+
+With the Docker Container Registry integrated into GitLab, every project can
+have its own space to store its Docker images.
+
+This document is the user guide. To learn how to enable GitLab Container
+Registry across your GitLab instance, visit the
+[administrator documentation](../../administration/container_registry.md).
+
+You can read more about Docker Registry at <https://docs.docker.com/registry/introduction/>.
+
+## Enable the Container Registry for your project
+
+If you cannot find the **Packages > Container Registry** entry under your
+project's sidebar, it is not enabled in your GitLab instance. Ask your
+administrator to enable GitLab Container Registry following the
+[administration documentation](../../administration/container_registry.md).
+
+If you are using GitLab.com, this is enabled by default so you can start using
+the Registry immediately. Currently there is a soft (10GB) size restriction for
+registry on GitLab.com, as part of the [repository size limit](repository/index.md).
+
+Once enabled for your GitLab instance, to enable Container Registry for your
+project:
+
+1. Go to your project's **Settings > General** page.
+1. Expand the **Visibility, project features, permissions** section
+ and enable the **Container Registry** feature on your project. For new
+ projects this might be enabled by default. For existing projects
+ (prior GitLab 8.8), you will have to explicitly enable it.
+1. Press **Save changes** for the changes to take effect. You should now be able
+ to see the **Packages > Container Registry** link in the sidebar.
+
+## Build and push images
+
+> **Notes:**
+>
+> - Moving or renaming existing container registry repositories is not supported
+> once you have pushed images because the images are signed, and the
+> signature includes the repository name.
+> - To move or rename a repository with a container registry you will have to
+> delete all existing images.
+
+If you visit the **Packages > Container Registry** link under your project's
+menu, you can see the explicit instructions to login to the Container Registry
+using your GitLab credentials.
+
+For example if the Registry's URL is `registry.example.com`, then you should be
+able to login with:
+
+```sh
+docker login registry.example.com
+```
+
+Building and publishing images should be a straightforward process. Just make
+sure that you are using the Registry URL with the namespace and project name
+that is hosted on GitLab:
+
+```sh
+docker build -t registry.example.com/group/project/image .
+docker push registry.example.com/group/project/image
+```
+
+Your image will be named after the following scheme:
+
+```text
+<registry URL>/<namespace>/<project>/<image>
+```
+
+GitLab supports up to three levels of image repository names.
+
+Following examples of image tags are valid:
+
+```text
+registry.example.com/group/project:some-tag
+registry.example.com/group/project/image:latest
+registry.example.com/group/project/my/image:rc1
+```
+
+## Use images from GitLab Container Registry
+
+To download and run a container from images hosted in GitLab Container Registry,
+use `docker run`:
+
+```sh
+docker run [options] registry.example.com/group/project/image [arguments]
+```
+
+For more information on running Docker containers, visit the
+[Docker documentation][docker-docs].
+
+## Control Container Registry from within GitLab
+
+GitLab offers a simple Container Registry management panel. Go to your project
+and click **Packages > Container Registry** in the project menu.
+
+This view will show you all tags in your project and will easily allow you to
+delete them.
+
+## Build and push images using GitLab CI
+
+> **Note:**
+This feature requires GitLab 8.8 and GitLab Runner 1.2.
+
+Make sure that your GitLab Runner is configured to allow building Docker images by
+following the [Using Docker Build](../../ci/docker/using_docker_build.md)
+and [Using the GitLab Container Registry documentation](../../ci/docker/using_docker_build.md#using-the-gitlab-container-registry).
+Alternatively, you can [build images with Kaniko](../../ci/docker/using_kaniko.md) if the Docker builds are not an option for you.
+
+## Using with private projects
+
+> Personal Access tokens were [introduced][ce-11845] in GitLab 9.3.
+> Project Deploy Tokens were [introduced][ce-17894] in GitLab 10.7
+
+If a project is private, credentials will need to be provided for authorization.
+There are two ways to do this:
+
+- By using a [personal access token](../profile/personal_access_tokens.md).
+- By using a [deploy token](../project/deploy_tokens/index.md).
+
+The minimal scope needed for both of them is `read_registry`.
+
+Example of using a token:
+
+```sh
+docker login registry.example.com -u <username> -p <token>
+```
+
+## Troubleshooting the GitLab Container Registry
+
+### Basic Troubleshooting
+
+1. Check to make sure that the system clock on your Docker client and GitLab server have
+ been synchronized (e.g. via NTP).
+
+1. If you are using an S3-backed Registry, double check that the IAM
+ permissions and the S3 credentials (including region) are correct. See [the
+ sample IAM policy](https://docs.docker.com/registry/storage-drivers/s3/)
+ for more details.
+
+1. Check the Registry logs (e.g. `/var/log/gitlab/registry/current`) and the GitLab production logs
+ for errors (e.g. `/var/log/gitlab/gitlab-rails/production.log`). You may be able to find clues
+ there.
+
+#### Enable the registry debug server
+
+The optional debug server can be enabled by setting the registry debug address
+in your `gitlab.rb` configuration.
+
+```ruby
+registry['debug_addr'] = "localhost:5001"
+```
+
+After adding the setting, [reconfigure] GitLab to apply the change.
+
+Use curl to request debug output from the debug server:
+
+```bash
+curl localhost:5001/debug/health
+curl localhost:5001/debug/vars
+```
+
+#### Docker connection error
+
+A Docker connection error can occur when there are special characters in either the group,
+project or branch name. Special characters can include:
+
+- Leading underscore
+- Trailing hyphen/dash
+- Double hyphen/dash
+
+To get around this, you can [change the group path](../group/index.md#changing-a-groups-path),
+[change the project path](../project/settings/index.md#renaming-a-repository) or chanage the branch
+name.
+
+### Advanced Troubleshooting
+
+NOTE: **Note:**
+The following section is only recommended for experts.
+
+Sometimes it's not obvious what is wrong, and you may need to dive deeper into
+the communication between the Docker client and the Registry to find out
+what's wrong. We will use a concrete example in the past to illustrate how to
+diagnose a problem with the S3 setup.
+
+#### Unexpected 403 error during push
+
+A user attempted to enable an S3-backed Registry. The `docker login` step went
+fine. However, when pushing an image, the output showed:
+
+```text
+The push refers to a repository [s3-testing.myregistry.com:4567/root/docker-test/docker-image]
+dc5e59c14160: Pushing [==================================================>] 14.85 kB
+03c20c1a019a: Pushing [==================================================>] 2.048 kB
+a08f14ef632e: Pushing [==================================================>] 2.048 kB
+228950524c88: Pushing 2.048 kB
+6a8ecde4cc03: Pushing [==> ] 9.901 MB/205.7 MB
+5f70bf18a086: Pushing 1.024 kB
+737f40e80b7f: Waiting
+82b57dbc5385: Waiting
+19429b698a22: Waiting
+9436069b92a3: Waiting
+error parsing HTTP 403 response body: unexpected end of JSON input: ""
+```
+
+This error is ambiguous, as it's not clear whether the 403 is coming from the
+GitLab Rails application, the Docker Registry, or something else. In this
+case, since we know that since the login succeeded, we probably need to look
+at the communication between the client and the Registry.
+
+The REST API between the Docker client and Registry is [described
+here](https://docs.docker.com/registry/spec/api/). Normally, one would just
+use Wireshark or tcpdump to capture the traffic and see where things went
+wrong. However, since all communications between Docker clients and servers
+are done over HTTPS, it's a bit difficult to decrypt the traffic quickly even
+if you know the private key. What can we do instead?
+
+One way would be to disable HTTPS by setting up an [insecure
+Registry](https://docs.docker.com/registry/insecure/). This could introduce a
+security hole and is only recommended for local testing. If you have a
+production system and can't or don't want to do this, there is another way:
+use mitmproxy, which stands for Man-in-the-Middle Proxy.
+
+#### mitmproxy
+
+[mitmproxy](https://mitmproxy.org/) allows you to place a proxy between your
+client and server to inspect all traffic. One wrinkle is that your system
+needs to trust the mitmproxy SSL certificates for this to work.
+
+The following installation instructions assume you are running Ubuntu:
+
+1. [Install mitmproxy](https://docs.mitmproxy.org/stable/overview-installation/).
+1. Run `mitmproxy --port 9000` to generate its certificates.
+ Enter <kbd>CTRL</kbd>-<kbd>C</kbd> to quit.
+1. Install the certificate from `~/.mitmproxy` to your system:
+
+ ```sh
+ sudo cp ~/.mitmproxy/mitmproxy-ca-cert.pem /usr/local/share/ca-certificates/mitmproxy-ca-cert.crt
+ sudo update-ca-certificates
+ ```
+
+If successful, the output should indicate that a certificate was added:
+
+```sh
+Updating certificates in /etc/ssl/certs... 1 added, 0 removed; done.
+Running hooks in /etc/ca-certificates/update.d....done.
+```
+
+To verify that the certificates are properly installed, run:
+
+```sh
+mitmproxy --port 9000
+```
+
+This will run mitmproxy on port `9000`. In another window, run:
+
+```sh
+curl --proxy http://localhost:9000 https://httpbin.org/status/200
+```
+
+If everything is set up correctly, you will see information on the mitmproxy window and
+no errors from the curl commands.
+
+#### Running the Docker daemon with a proxy
+
+For Docker to connect through a proxy, you must start the Docker daemon with the
+proper environment variables. The easiest way is to shutdown Docker (e.g. `sudo initctl stop docker`)
+and then run Docker by hand. As root, run:
+
+```sh
+export HTTP_PROXY="http://localhost:9000"
+export HTTPS_PROXY="https://localhost:9000"
+docker daemon --debug
+```
+
+This will launch the Docker daemon and proxy all connections through mitmproxy.
+
+#### Running the Docker client
+
+Now that we have mitmproxy and Docker running, we can attempt to login and push
+a container image. You may need to run as root to do this. For example:
+
+```sh
+docker login s3-testing.myregistry.com:4567
+docker push s3-testing.myregistry.com:4567/root/docker-test/docker-image
+```
+
+In the example above, we see the following trace on the mitmproxy window:
+
+![mitmproxy output from Docker](img/mitmproxy-docker.png)
+
+The above image shows:
+
+- The initial PUT requests went through fine with a 201 status code.
+- The 201 redirected the client to the S3 bucket.
+- The HEAD request to the AWS bucket reported a 403 Unauthorized.
+
+What does this mean? This strongly suggests that the S3 user does not have the right
+[permissions to perform a HEAD request](http://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectHEAD.html).
+The solution: check the [IAM permissions again](https://docs.docker.com/registry/storage-drivers/s3/).
+Once the right permissions were set, the error will go away.
+
+[ce-4040]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/4040
+[ce-11845]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/11845
+[ce-17894]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/17894
+[docker-docs]: https://docs.docker.com/engine/userguide/intro/
+[pat]: ../profile/personal_access_tokens.md
+[pdt]: ../project/deploy_tokens/index.md
+[reconfigure]: ../../administration/restart_gitlab.md#omnibus-gitlab-reconfigure
diff --git a/doc/user/project/deploy_tokens/index.md b/doc/user/project/deploy_tokens/index.md
index ca5b2f54e30..164d1dddff0 100644
--- a/doc/user/project/deploy_tokens/index.md
+++ b/doc/user/project/deploy_tokens/index.md
@@ -97,4 +97,4 @@ docker login -u $CI_DEPLOY_USER -p $CI_DEPLOY_PASSWORD $CI_REGISTRY
[ce-17894]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/17894
[ce-11845]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/11845
[ce-18414]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/18414
-[container registry]: ../../packages/container_registry/index.md
+[container registry]: ../container_registry.md
diff --git a/doc/administration/packages/img/mitmproxy-docker.png b/doc/user/project/img/mitmproxy-docker.png
index aa3b6a0b830..aa3b6a0b830 100644
--- a/doc/administration/packages/img/mitmproxy-docker.png
+++ b/doc/user/project/img/mitmproxy-docker.png
Binary files differ
diff --git a/doc/user/project/index.md b/doc/user/project/index.md
index 53c2194cd90..c63d5308536 100644
--- a/doc/user/project/index.md
+++ b/doc/user/project/index.md
@@ -60,7 +60,7 @@ When you create a project in GitLab, you'll have access to a large number of
**GitLab CI/CD:**
- [GitLab CI/CD](../../ci/README.md): GitLab's built-in [Continuous Integration, Delivery, and Deployment](https://about.gitlab.com/2016/08/05/continuous-integration-delivery-and-deployment-with-gitlab/) tool
- - [Container Registry](../packages/container_registry/index.md): Build and push Docker
+ - [Container Registry](container_registry.md): Build and push Docker
images out-of-the-box
- [Auto Deploy](../../ci/autodeploy/index.md): Configure GitLab CI/CD
to automatically set up your app's deployment
@@ -95,8 +95,8 @@ When you create a project in GitLab, you'll have access to a large number of
- [Releases](releases/index.md): a way to track deliverables in your project as snapshot in time of
the source, build output, and other metadata or artifacts
associated with a released version of your code.
-- [Maven packages](../packages/maven_repository/index.md): your private Maven repository in GitLab. **(PREMIUM)**
-- [NPM packages](../packages/npm_registry/index.md): your private NPM package registry in GitLab. **(PREMIUM)**
+- [Maven packages](packages/maven_repository.md): your private Maven repository in GitLab. **(PREMIUM)**
+- [NPM packages](packages/npm_registry.md): your private NPM package registry in GitLab. **(PREMIUM)**
- [Code owners](code_owners.md): specify code owners for certain files **(STARTER)**
- [License Compliance](../application_security/license_compliance/index.md): approve and blacklist licenses for projects. **(ULTIMATE)**
- [Dependency List](../application_security/dependency_list/index.md): view project dependencies. **(ULTIMATE)**
diff --git a/doc/user/project/issues/img/link_zoom_call_in_issue.png b/doc/user/project/issues/img/link_zoom_call_in_issue.png
new file mode 100644
index 00000000000..3153a0a9b07
--- /dev/null
+++ b/doc/user/project/issues/img/link_zoom_call_in_issue.png
Binary files differ
diff --git a/doc/user/project/issues/img/zoom-quickaction-button.png b/doc/user/project/issues/img/zoom-quickaction-button.png
deleted file mode 100644
index d6d691b2267..00000000000
--- a/doc/user/project/issues/img/zoom-quickaction-button.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/issues/issue_data_and_actions.md b/doc/user/project/issues/issue_data_and_actions.md
index 5313975908b..41a7ed09281 100644
--- a/doc/user/project/issues/issue_data_and_actions.md
+++ b/doc/user/project/issues/issue_data_and_actions.md
@@ -157,6 +157,19 @@ The plain text title and description of the issue fill the top center of the iss
The description fully supports [GitLab Flavored Markdown](../../markdown.md#gitlab-flavored-markdown-gfm),
allowing many formatting options.
+##### Zoom call links
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/issues/62966) in GitLab 12.0.
+
+Including a link to a [Zoom](https://zoom.us) call in the description of an issue
+results in a **Join Zoom meeting** button at the top of the issue, just under the header.
+
+For example:
+
+![Link Zoom Call in Issue](img/link_zoom_call_in_issue.png)
+
+To remove the button, edit the description and remove the Zoom call link.
+
#### 17. Mentions
You can mention a user or a group present in your GitLab instance with `@username` or
@@ -246,15 +259,3 @@ Once you write a comment, you can:
![Comment or thread](img/comment-or-discussion.png)
You can also close the issue from here, so you don't need to scroll to the top of the issue page.
-
-#### 26. Zoom Meetings
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/issues/31103) in GitLab 12.3.
-
-You can attach and remove Zoom meetings to issues using the `/zoom` and `/remove_zoom` [quick actions](../quick_actions.md) as part of
-[GitLab Flavored Markdown](../../markdown.md#gitlab-flavored-markdown-gfm).
-
-Attaching a [Zoom](https://zoom.us) call an issue
-results in a **Join Zoom meeting** button at the top of the issue, just under the header.
-
-![Link Zoom Call in Issue](img/zoom-quickaction-button.png)
diff --git a/doc/user/project/maven_packages.md b/doc/user/project/maven_packages.md
index 4679eed5433..48835a2dac7 100644
--- a/doc/user/project/maven_packages.md
+++ b/doc/user/project/maven_packages.md
@@ -1,5 +1,5 @@
---
-redirect_to: '../packages/maven_repository/index.md'
+redirect_to: 'packages/maven_repository.md'
---
-This document was moved to [another location](../packages/maven_repository/index.md).
+This document was moved to [another location](packages/maven_repository.md).
diff --git a/doc/user/project/operations/feature_flags.md b/doc/user/project/operations/feature_flags.md
index 1c9157b0f67..39ca1bd0c77 100644
--- a/doc/user/project/operations/feature_flags.md
+++ b/doc/user/project/operations/feature_flags.md
@@ -120,8 +120,6 @@ A feature flag may be enabled for a list of target users. It is implemented
using the Unleash [`userWithId`](https://unleash.github.io/docs/activation_strategy#userwithid)
activation strategy.
-The feature will always be enabled for all users in the list across all environments even if the matching environment spec **Status** is disabled.
-
![Feature flag target users](img/target_users_v12_2.png)
CAUTION: **Caution:**
diff --git a/doc/user/project/packages/maven.md b/doc/user/project/packages/maven.md
index 8378b8c78cd..266225fdb8d 100644
--- a/doc/user/project/packages/maven.md
+++ b/doc/user/project/packages/maven.md
@@ -1,5 +1,5 @@
---
-redirect_to: '../../packages/maven_repository/index.md'
+redirect_to: 'maven_repository.md'
---
-This document was moved to [another location](../../packages/maven_repository/index.md).
+This document was moved to [another location](maven_repository.md).
diff --git a/doc/user/project/packages/maven_packages.md b/doc/user/project/packages/maven_packages.md
index 8378b8c78cd..266225fdb8d 100644
--- a/doc/user/project/packages/maven_packages.md
+++ b/doc/user/project/packages/maven_packages.md
@@ -1,5 +1,5 @@
---
-redirect_to: '../../packages/maven_repository/index.md'
+redirect_to: 'maven_repository.md'
---
-This document was moved to [another location](../../packages/maven_repository/index.md).
+This document was moved to [another location](maven_repository.md).
diff --git a/doc/user/project/packages/maven_repository.md b/doc/user/project/packages/maven_repository.md
index 8378b8c78cd..491ebc0c068 100644
--- a/doc/user/project/packages/maven_repository.md
+++ b/doc/user/project/packages/maven_repository.md
@@ -1,5 +1,340 @@
----
-redirect_to: '../../packages/maven_repository/index.md'
----
+# GitLab Maven Repository **(PREMIUM)**
-This document was moved to [another location](../../packages/maven_repository/index.md).
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/issues/5811) in [GitLab Premium](https://about.gitlab.com/pricing/) 11.3.
+
+With the GitLab [Maven](https://maven.apache.org) Repository, every
+project can have its own space to store its Maven artifacts.
+
+![GitLab Maven Repository](img/maven_package_view.png)
+
+## Enabling the Maven Repository
+
+NOTE: **Note:**
+This option is available only if your GitLab administrator has
+[enabled support for the Maven repository](../../../administration/packages.md).**(PREMIUM ONLY)**
+
+After the Packages feature is enabled, the Maven Repository will be available for
+all new projects by default. To enable it for existing projects, or if you want
+to disable it:
+
+1. Navigate to your project's **Settings > General > Permissions**.
+1. Find the Packages feature and enable or disable it.
+1. Click on **Save changes** for the changes to take effect.
+
+You should then be able to see the **Packages** section on the left sidebar.
+Next, you must configure your project to authorize with the GitLab Maven
+repository.
+
+## Authenticating to the GitLab Maven Repository
+
+If a project is private or you want to upload Maven artifacts to GitLab,
+credentials will need to be provided for authorization. Support is available for
+[personal access tokens](#authenticating-with-a-personal-access-token) and
+[CI job tokens](#authenticating-with-a-ci-job-token) only.
+[Deploy tokens](../deploy_tokens/index.md) and regular username/password
+credentials do not work.
+
+### Authenticating with a personal access token
+
+To authenticate with a [personal access token](../../profile/personal_access_tokens.md),
+add a corresponding section to your
+[`settings.xml`](https://maven.apache.org/settings.html) file:
+
+```xml
+<settings>
+ <servers>
+ <server>
+ <id>gitlab-maven</id>
+ <configuration>
+ <httpHeaders>
+ <property>
+ <name>Private-Token</name>
+ <value>REPLACE_WITH_YOUR_PERSONAL_ACCESS_TOKEN</value>
+ </property>
+ </httpHeaders>
+ </configuration>
+ </server>
+ </servers>
+</settings>
+```
+
+You should now be able to upload Maven artifacts to your project.
+
+### Authenticating with a CI job token
+
+If you're using Maven with GitLab CI/CD, a CI job token can be used instead
+of a personal access token.
+
+To authenticate with a CI job token, add a corresponding section to your
+[`settings.xml`](https://maven.apache.org/settings.html) file:
+
+```xml
+<settings>
+ <servers>
+ <server>
+ <id>gitlab-maven</id>
+ <configuration>
+ <httpHeaders>
+ <property>
+ <name>Job-Token</name>
+ <value>${env.CI_JOB_TOKEN}</value>
+ </property>
+ </httpHeaders>
+ </configuration>
+ </server>
+ </servers>
+</settings>
+```
+
+You can read more on
+[how to create Maven packages using GitLab CI/CD](#creating-maven-packages-with-gitlab-cicd).
+
+## Configuring your project to use the GitLab Maven repository URL
+
+To download and upload packages from GitLab, you need a `repository` and
+`distributionManagement` section in your `pom.xml` file.
+
+Depending on your workflow and the amount of Maven packages you have, there are
+3 ways you can configure your project to use the GitLab endpoint for Maven packages:
+
+- **Project level**: Useful when you have few Maven packages which are not under
+ the same GitLab group.
+- **Group level**: Useful when you have many Maven packages under the same GitLab
+ group.
+- **Instance level**: Useful when you have many Maven packages under different
+ GitLab groups or on their own namespace.
+
+NOTE: **Note:**
+In all cases, you need a project specific URL for uploading a package in
+the `distributionManagement` section.
+
+### Project level Maven endpoint
+
+The example below shows how the relevant `repository` section of your `pom.xml`
+would look like:
+
+```xml
+<repositories>
+ <repository>
+ <id>gitlab-maven</id>
+ <url>https://gitlab.com/api/v4/projects/PROJECT_ID/packages/maven</url>
+ </repository>
+</repositories>
+<distributionManagement>
+ <repository>
+ <id>gitlab-maven</id>
+ <url>https://gitlab.com/api/v4/projects/PROJECT_ID/packages/maven</url>
+ </repository>
+ <snapshotRepository>
+ <id>gitlab-maven</id>
+ <url>https://gitlab.com/api/v4/projects/PROJECT_ID/packages/maven</url>
+ </snapshotRepository>
+</distributionManagement>
+```
+
+The `id` must be the same with what you
+[defined in `settings.xml`](#authenticating-to-the-gitlab-maven-repository).
+
+Replace `PROJECT_ID` with your project ID which can be found on the home page
+of your project.
+
+If you have a self-hosted GitLab installation, replace `gitlab.com` with your
+domain name.
+
+NOTE: **Note:**
+For retrieving artifacts, you can use either the
+[URL encoded](../../../api/README.md#namespaced-path-encoding) path of the project
+(e.g., `group%2Fproject`) or the project's ID (e.g., `42`). However, only the
+project's ID can be used for uploading.
+
+### Group level Maven endpoint
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/8798) in GitLab Premium 11.7.
+
+If you rely on many packages, it might be inefficient to include the `repository` section
+with a unique URL for each package. Instead, you can use the group level endpoint for
+all your Maven packages stored within one GitLab group. Only packages you have access to
+will be available for download.
+
+The group level endpoint works with any package names, which means the you
+have the flexibility of naming compared to [instance level endpoint](#instance-level-maven-endpoint).
+However, GitLab will not guarantee the uniqueness of the package names within
+the group. You can have two projects with the same package name and package
+version. As a result, GitLab will serve whichever one is more recent.
+
+The example below shows how the relevant `repository` section of your `pom.xml`
+would look like. You still need a project specific URL for uploading a package in
+the `distributionManagement` section:
+
+```xml
+<repositories>
+ <repository>
+ <id>gitlab-maven</id>
+ <url>https://gitlab.com/api/v4/groups/my-group/-/packages/maven</url>
+ </repository>
+</repositories>
+<distributionManagement>
+ <repository>
+ <id>gitlab-maven</id>
+ <url>https://gitlab.com/api/v4/projects/PROJECT_ID/packages/maven</url>
+ </repository>
+ <snapshotRepository>
+ <id>gitlab-maven</id>
+ <url>https://gitlab.com/api/v4/projects/PROJECT_ID/packages/maven</url>
+ </snapshotRepository>
+</distributionManagement>
+```
+
+The `id` must be the same with what you
+[defined in `settings.xml`](#authenticating-to-the-gitlab-maven-repository).
+
+Replace `my-group` with your group name and `PROJECT_ID` with your project ID
+which can be found on the home page of your project.
+
+If you have a self-hosted GitLab installation, replace `gitlab.com` with your
+domain name.
+
+NOTE: **Note:**
+For retrieving artifacts, you can use either the
+[URL encoded](../../../api/README.md#namespaced-path-encoding) path of the group
+(e.g., `group%2Fsubgroup`) or the group's ID (e.g., `12`).
+
+### Instance level Maven endpoint
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/8274) in GitLab Premium 11.7.
+
+If you rely on many packages, it might be inefficient to include the `repository` section
+with a unique URL for each package. Instead, you can use the instance level endpoint for
+all maven packages stored in GitLab and the packages you have access to will be available
+for download.
+
+Note that **only packages that have the same path as the project** are exposed via
+the instance level endpoint.
+
+| Project | Package | Instance level endpoint available |
+| ------- | ------- | --------------------------------- |
+| `foo/bar` | `foo/bar/1.0-SNAPSHOT` | Yes |
+| `gitlab-org/gitlab-ce` | `foo/bar/1.0-SNAPSHOT` | No |
+| `gitlab-org/gitlab-ce` | `gitlab-org/gitlab-ce/1.0-SNAPSHOT` | Yes |
+
+The example below shows how the relevant `repository` section of your `pom.xml`
+would look like. You still need a project specific URL for uploading a package in
+the `distributionManagement` section:
+
+```xml
+<repositories>
+ <repository>
+ <id>gitlab-maven</id>
+ <url>https://gitlab.com/api/v4/packages/maven</url>
+ </repository>
+</repositories>
+<distributionManagement>
+ <repository>
+ <id>gitlab-maven</id>
+ <url>https://gitlab.com/api/v4/projects/PROJECT_ID/packages/maven</url>
+ </repository>
+ <snapshotRepository>
+ <id>gitlab-maven</id>
+ <url>https://gitlab.com/api/v4/projects/PROJECT_ID/packages/maven</url>
+ </snapshotRepository>
+</distributionManagement>
+```
+
+The `id` must be the same with what you
+[defined in `settings.xml`](#authenticating-to-the-gitlab-maven-repository).
+
+Replace `PROJECT_ID` with your project ID which can be found on the home page
+of your project.
+
+If you have a self-hosted GitLab installation, replace `gitlab.com` with your
+domain name.
+
+NOTE: **Note:**
+For retrieving artifacts, you can use either the
+[URL encoded](../../../api/README.md#namespaced-path-encoding) path of the project
+(e.g., `group%2Fproject`) or the project's ID (e.g., `42`). However, only the
+project's ID can be used for uploading.
+
+## Uploading packages
+
+Once you have set up the [authentication](#authenticating-to-the-gitlab-maven-repository)
+and [configuration](#configuring-your-project-to-use-the-gitlab-maven-repository-url),
+test to upload a Maven artifact from a project of yours:
+
+```sh
+mvn deploy
+```
+
+You can then navigate to your project's **Packages** page and see the uploaded
+artifacts or even delete them.
+
+## Creating Maven packages with GitLab CI/CD
+
+Once you have your repository configured to use the GitLab Maven Repository,
+you can configure GitLab CI/CD to build new packages automatically. The example below
+shows how to create a new package each time the `master` branch is updated:
+
+1. Create a `ci_settings.xml` file that will serve as Maven's `settings.xml` file.
+ Add the server section with the same id you defined in your `pom.xml` file.
+ For example, in our case it's `gitlab-maven`:
+
+ ```xml
+ <settings xmlns="http://maven.apache.org/SETTINGS/1.1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.1.0 http://maven.apache.org/xsd/settings-1.1.0.xsd">
+ <servers>
+ <server>
+ <id>gitlab-maven</id>
+ <configuration>
+ <httpHeaders>
+ <property>
+ <name>Job-Token</name>
+ <value>${env.CI_JOB_TOKEN}</value>
+ </property>
+ </httpHeaders>
+ </configuration>
+ </server>
+ </servers>
+ </settings>
+ ```
+
+1. Make sure your `pom.xml` file includes the following:
+
+ ```xml
+ <repositories>
+ <repository>
+ <id>gitlab-maven</id>
+ <url>https://gitlab.com/api/v4/projects/${env.CI_PROJECT_ID}/packages/maven</url>
+ </repository>
+ </repositories>
+ <distributionManagement>
+ <repository>
+ <id>gitlab-maven</id>
+ <url>https://gitlab.com/api/v4/projects/${env.CI_PROJECT_ID}/packages/maven</url>
+ </repository>
+ <snapshotRepository>
+ <id>gitlab-maven</id>
+ <url>https://gitlab.com/api/v4/projects/${env.CI_PROJECT_ID}/packages/maven</url>
+ </snapshotRepository>
+ </distributionManagement>
+ ```
+
+ TIP: **Tip:**
+ You can either let Maven utilize the CI environment variables or hardcode your project's ID.
+
+1. Add a `deploy` job to your `.gitlab-ci.yml` file:
+
+ ```yaml
+ deploy:
+ image: maven:3.3.9-jdk-8
+ script:
+ - 'mvn deploy -s ci_settings.xml'
+ only:
+ - master
+ ```
+
+1. Push those files to your repository.
+
+The next time the `deploy` job runs, it will copy `ci_settings.xml` to the
+user's home location (in this case the user is `root` since it runs in a
+Docker container), and Maven will utilize the configured CI
+[environment variables](../../../ci/variables/README.md#predefined-environment-variables).
diff --git a/doc/user/project/packages/npm_registry.md b/doc/user/project/packages/npm_registry.md
index e94599cf33a..48186688da9 100644
--- a/doc/user/project/packages/npm_registry.md
+++ b/doc/user/project/packages/npm_registry.md
@@ -1,5 +1,147 @@
----
-redirect_to: '../../packages/npm_registry/index.md'
----
+# GitLab NPM Registry **(PREMIUM)**
-This document was moved to [another location](../../packages/npm_registry/index.md).
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/issues/5934) in [GitLab Premium](https://about.gitlab.com/pricing/) 11.7.
+
+With the GitLab NPM Registry, every
+project can have its own space to store NPM packages.
+
+![GitLab NPM Registry](img/npm_package_view.png)
+
+NOTE: **Note:**
+Only [scoped](https://docs.npmjs.com/misc/scope) packages are supported.
+
+## Enabling the NPM Registry
+
+NOTE: **Note:**
+This option is available only if your GitLab administrator has
+[enabled support for the NPM registry](../../../administration/packages.md).**(PREMIUM ONLY)**
+
+After the NPM registry is enabled, it will be available for all new projects
+by default. To enable it for existing projects, or if you want to disable it:
+
+1. Navigate to your project's **Settings > General > Permissions**.
+1. Find the Packages feature and enable or disable it.
+1. Click on **Save changes** for the changes to take effect.
+
+You should then be able to see the **Packages** section on the left sidebar.
+
+Before proceeding to authenticating with the GitLab NPM Registry, you should
+get familiar with the package naming convention.
+
+## Package naming convention
+
+**Packages must be scoped in the root namespace of the project**. The package
+name may be anything but it is preferred that the project name be used unless
+it is not possible due to a naming collision. For example:
+
+| Project | Package | Supported |
+| ---------------------- | ----------------------- | --------- |
+| `foo/bar` | `@foo/bar` | Yes |
+| `foo/bar/baz` | `@foo/baz` | Yes |
+| `foo/bar/buz` | `@foo/anything` | Yes |
+| `gitlab-org/gitlab-ce` | `@gitlab-org/gitlab-ce` | Yes |
+| `gitlab-org/gitlab-ce` | `@foo/bar` | No |
+
+Now, you can configure your project to authenticate with the GitLab NPM
+Registry.
+
+## Authenticating to the GitLab NPM Registry
+
+If a project is private or you want to upload an NPM package to GitLab,
+credentials will need to be provided for authentication. Support is available for [OAuth tokens](../../../api/oauth2.md#resource-owner-password-credentials-flow) or [personal access tokens](../../profile/personal_access_tokens.md).
+
+CAUTION: **2FA is only supported with personal access tokens:**
+If you have 2FA enabled, you need to use a [personal access token](../../profile/personal_access_tokens.md) with OAuth headers. Standard OAuth tokens won't be able to authenticate to the GitLab NPM Registry.
+
+### Authenticating with an OAuth token
+
+To authenticate with an [OAuth token](../../../api/oauth2.md#resource-owner-password-credentials-flow)
+or [personal access token](../../profile/personal_access_tokens.md), add a corresponding section to your `.npmrc` file:
+
+```ini
+; Set URL for your scoped packages.
+; For example package with name `@foo/bar` will use this URL for download
+@foo:registry=https://gitlab.com/api/v4/packages/npm/
+
+; Add the token for the scoped packages URL. This will allow you to download
+; `@foo/` packages from private projects.
+//gitlab.com/api/v4/packages/npm/:_authToken=<your_token>
+
+; Add token for uploading to the registry. Replace <your_project_id>
+; with the project you want your package to be uploaded to.
+//gitlab.com/api/v4/projects/<your_project_id>/packages/npm/:_authToken=<your_token>
+```
+
+Replace `<your_project_id>` with your project ID which can be found on the home page
+of your project and `<your_token>` with your OAuth or personal access token.
+
+If you have a self-hosted GitLab installation, replace `gitlab.com` with your
+domain name.
+
+You should now be able to download and upload NPM packages to your project.
+
+NOTE: **Note:**
+If you encounter an error message with [Yarn](https://yarnpkg.com/en/), see the
+[troubleshooting section](#troubleshooting).
+
+## Uploading packages
+
+Before you will be able to upload a package, you need to specify the registry
+for NPM. To do this, add the following section to the bottom of `package.json`:
+
+```json
+ "publishConfig": {
+ "@foo:registry":"https://gitlab.com/api/v4/projects/<your_project_id>/packages/npm/"
+ }
+```
+
+Replace `<your_project_id>` with your project ID, which can be found on the home
+page of your project, and replace `@foo` with your own scope.
+
+If you have a self-hosted GitLab installation, replace `gitlab.com` with your
+domain name.
+
+Once you have enabled it and set up [authentication](#authenticating-to-the-gitlab-npm-registry),
+you can upload an NPM package to your project:
+
+```sh
+npm publish
+```
+
+You can then navigate to your project's **Packages** page and see the uploaded
+packages or even delete them.
+
+If you attempt to publish a package with a name that already exists within
+a given scope, you will receive a `403 Forbidden!` error.
+
+## Uploading a package with the same version twice
+
+If you upload a package with a same name and version twice, GitLab will show
+both packages in the UI, but the GitLab NPM Registry will expose the most recent
+one as it supports only one package per version for `npm install`.
+
+## Troubleshooting
+
+### Error running yarn with NPM registry
+
+If you are using [yarn](https://yarnpkg.com/en/) with the NPM registry, you may get
+an error message like:
+
+```sh
+yarn install v1.15.2
+warning package.json: No license field
+info No lockfile found.
+warning XXX: No license field
+[1/4] 🔍 Resolving packages...
+[2/4] 🚚 Fetching packages...
+error An unexpected error occurred: "https://gitlab.com/api/v4/projects/XXX/packages/npm/XXX/XXX/-/XXX/XXX-X.X.X.tgz: Request failed \"404 Not Found\"".
+info If you think this is a bug, please open a bug report with the information provided in "/Users/XXX/gitlab-migration/module-util/yarn-error.log".
+info Visit https://yarnpkg.com/en/docs/cli/install for documentation about this command
+```
+
+In this case, try adding this to your `.npmrc` file (and replace `<your_oauth_token>`
+with your with your OAuth or personal access token):
+
+```text
+//gitlab.com/api/v4/projects/:_authToken=<your_oauth_token>
+```
diff --git a/doc/user/project/pipelines/job_artifacts.md b/doc/user/project/pipelines/job_artifacts.md
index 3c15d41e1ba..ef90899c512 100644
--- a/doc/user/project/pipelines/job_artifacts.md
+++ b/doc/user/project/pipelines/job_artifacts.md
@@ -9,11 +9,11 @@ type: reference, howto
> - In GitLab 8.17, builds were renamed to jobs.
> - The artifacts browser will be available only for new artifacts that are sent to GitLab using GitLab Runner version 1.0 and up. It will not be possible to browse old artifacts already uploaded to GitLab.
-Job artifacts are a list of files and directories created by a job
+Artifacts are a list of files and directories which created by a job
once it finishes. This feature is [enabled by default](../../../administration/job_artifacts.md) in all
GitLab installations.
-Job artifacts created by GitLab Runner are uploaded to GitLab and are downloadable as a single archive using the GitLab UI or the [GitLab API](../../../api/jobs.md#get-job-artifacts).
+Job artifacts that are created by GitLab Runner are uploaded to GitLab and are downloadable as a single archive using the GitLab UI.
<i class="fa fa-youtube-play youtube" aria-hidden="true"></i>
For an overview, watch the video [GitLab CI Pipeline, Artifacts, and Environments](https://www.youtube.com/watch?v=PCKDICEe10s).
@@ -78,7 +78,7 @@ one HTML file that you can view directly online when
## Downloading artifacts
If you need to download the whole archive, there are buttons in various places
-in the GitLab UI to do this:
+inside GitLab that make that possible.
1. While on the pipelines page, you can see the download icon for each job's
artifacts archive in the right corner:
diff --git a/doc/user/project/settings/index.md b/doc/user/project/settings/index.md
index 66a861faf93..e0fb5c57784 100644
--- a/doc/user/project/settings/index.md
+++ b/doc/user/project/settings/index.md
@@ -22,7 +22,7 @@ The project description also partially supports [standard markdown](../../markdo
### Sharing and permissions
-Set up your project's access, [visibility](../../../public_access/public_access.md), and enable [Container Registry](../../packages/container_registry/index.md) for your projects:
+Set up your project's access, [visibility](../../../public_access/public_access.md), and enable [Container Registry](../container_registry.md) for your projects:
![projects sharing permissions](img/sharing_and_permissions_settings.png)
diff --git a/doc/user/project/wiki/img/wiki_create_new_page_modal.png b/doc/user/project/wiki/img/wiki_create_new_page_modal.png
new file mode 100644
index 00000000000..b800508901b
--- /dev/null
+++ b/doc/user/project/wiki/img/wiki_create_new_page_modal.png
Binary files differ
diff --git a/doc/user/project/wiki/index.md b/doc/user/project/wiki/index.md
index c0159230fec..d1bab47de25 100644
--- a/doc/user/project/wiki/index.md
+++ b/doc/user/project/wiki/index.md
@@ -30,12 +30,10 @@ Requires Developer [permissions](../../permissions.md).
Create a new page by clicking the **New page** button that can be found
in all wiki pages.
-You will be asked to fill in a title for your new wiki page.
-
-You can specify a full path for the wiki page by using '/' in the
-title to indicate subdirectories. Any missing directories will be created
-automatically. For example, a title of `docs/my-page` will create a wiki
-page with a path `/wikis/docs/my-page`.
+You will be asked to fill in a title for your new wiki page. Wiki titles
+also determine the path to the wiki page. You can specify a full path
+(using "`/`" for subdirectories) for the new title and any missing
+directories will be created automatically.
Once you enter the page name, it's time to fill in its content. GitLab wikis
support Markdown, RDoc and AsciiDoc. For Markdown based pages, all the
diff --git a/doc/workflow/time-tracking/time-tracking-example.png b/doc/workflow/time-tracking/time-tracking-example.png
new file mode 100644
index 00000000000..a96e4da7f74
--- /dev/null
+++ b/doc/workflow/time-tracking/time-tracking-example.png
Binary files differ
diff --git a/doc/workflow/time_tracking/img/time_tracking_sidebar_v8_16.png b/doc/workflow/time-tracking/time-tracking-sidebar.png
index 22124afed6f..22124afed6f 100644
--- a/doc/workflow/time_tracking/img/time_tracking_sidebar_v8_16.png
+++ b/doc/workflow/time-tracking/time-tracking-sidebar.png
Binary files differ
diff --git a/doc/workflow/time_tracking.md b/doc/workflow/time_tracking.md
index 7404d9be210..3d9f015b1fe 100644
--- a/doc/workflow/time_tracking.md
+++ b/doc/workflow/time_tracking.md
@@ -1,7 +1,3 @@
----
-type: reference
----
-
# Time Tracking
> Introduced in GitLab 8.14.
@@ -11,7 +7,7 @@ requests within GitLab.
## Overview
-Time Tracking allows you:
+Time Tracking lets you:
- Record the time spent working on an issue or a merge request.
- Add an estimate of the amount of time needed to complete an issue or a merge
@@ -22,7 +18,7 @@ You don't have to indicate an estimate to enter the time spent, and vice versa.
Data about time tracking is shown on the issue/merge request sidebar, as shown
below.
-![Time tracking in the sidebar](time_tracking/img/time_tracking_sidebar_v8_16.png)
+![Time tracking in the sidebar](time-tracking/time-tracking-sidebar.png)
## How to enter data
@@ -34,7 +30,7 @@ in a comment in both an issue or a merge request.
Below is an example of how you can use those new quick actions inside a comment.
-![Time tracking example in a comment](time_tracking/img/time_tracking_example_v12_2.png)
+![Time tracking example in a comment](time-tracking/time-tracking-example.png)
Adding time entries (time spent or estimates) is limited to project members.
@@ -69,11 +65,11 @@ To remove all the time spent at once, use `/remove_time_spent`.
The following time units are available:
-- Months (mo)
-- Weeks (w)
-- Days (d)
-- Hours (h)
-- Minutes (m)
+- months (mo)
+- weeks (w)
+- days (d)
+- hours (h)
+- minutes (m)
Default conversion rates are 1mo = 4w, 1w = 5d and 1d = 8h.
diff --git a/doc/workflow/time_tracking/img/time_tracking_example_v12_2.png b/doc/workflow/time_tracking/img/time_tracking_example_v12_2.png
deleted file mode 100644
index 31d8c490ed1..00000000000
--- a/doc/workflow/time_tracking/img/time_tracking_example_v12_2.png
+++ /dev/null
Binary files differ
diff --git a/lib/api/entities.rb b/lib/api/entities.rb
index 9e820f00c42..53774d4db1a 100644
--- a/lib/api/entities.rb
+++ b/lib/api/entities.rb
@@ -400,7 +400,6 @@ module API
end
class GroupDetail < Group
- expose :runners_token, if: lambda { |group, options| options[:user_can_admin_group] }
expose :projects, using: Entities::Project do |group, options|
projects = GroupProjectsFinder.new(
group: group,
@@ -1045,12 +1044,7 @@ module API
expose :job_events
# Expose serialized properties
expose :properties do |service, options|
- # TODO: Simplify as part of https://gitlab.com/gitlab-org/gitlab-ce/issues/63084
- if service.data_fields_present?
- service.data_fields.as_json.slice(*service.api_field_names)
- else
- service.properties.slice(*service.api_field_names)
- end
+ service.properties.slice(*service.api_field_names)
end
end
@@ -1286,7 +1280,7 @@ module API
expose :author, using: Entities::UserBasic, if: -> (release, _) { release.author.present? }
expose :commit, using: Entities::Commit, if: lambda { |_, _| can_download_code? }
expose :upcoming_release?, as: :upcoming_release
- expose :milestones, using: Entities::Milestone, if: -> (release, _) { release.milestones.present? }
+ expose :milestone, using: Entities::Milestone, if: -> (release, _) { release.milestone.present? }
expose :assets do
expose :assets_count, as: :count do |release, _|
diff --git a/lib/api/groups.rb b/lib/api/groups.rb
index 9d1628de7e5..4ae9b8c70d3 100644
--- a/lib/api/groups.rb
+++ b/lib/api/groups.rb
@@ -173,8 +173,7 @@ module API
options = {
with: params[:with_projects] ? Entities::GroupDetail : Entities::Group,
- current_user: current_user,
- user_can_admin_group: can?(current_user, :admin_group, group)
+ current_user: current_user
}
group, options = with_custom_attributes(group, options)
diff --git a/lib/api/helpers/issues_helpers.rb b/lib/api/helpers/issues_helpers.rb
index e272b13f3ae..8addcd18fe3 100644
--- a/lib/api/helpers/issues_helpers.rb
+++ b/lib/api/helpers/issues_helpers.rb
@@ -11,9 +11,6 @@ module API
params :optional_issues_params_ee do
end
- params :optional_issue_not_params_ee do
- end
-
def self.update_params_at_least_one_of
[
:assignee_id,
@@ -38,11 +35,8 @@ module API
args = declared_params.merge(args)
args.delete(:id)
- args[:not] ||= {}
args[:milestone_title] ||= args.delete(:milestone)
- args[:not][:milestone_title] ||= args[:not]&.delete(:milestone)
args[:label_name] ||= args.delete(:labels)
- args[:not][:label_name] ||= args[:not]&.delete(:labels)
args[:scope] = args[:scope].underscore if args[:scope]
args[:sort] = "#{args[:order_by]}_#{args[:sort]}"
diff --git a/lib/api/helpers/projects_helpers.rb b/lib/api/helpers/projects_helpers.rb
index 07f0386d14d..f247c722c44 100644
--- a/lib/api/helpers/projects_helpers.rb
+++ b/lib/api/helpers/projects_helpers.rb
@@ -56,14 +56,6 @@ module API
use :optional_project_params_ee
end
- params :optional_create_project_params_ee do
- end
-
- params :optional_create_project_params do
- use :optional_project_params
- use :optional_create_project_params_ee
- end
-
params :optional_filter_params_ee do
end
diff --git a/lib/api/helpers/services_helpers.rb b/lib/api/helpers/services_helpers.rb
index eba4ebb4b6e..5331de3c035 100644
--- a/lib/api/helpers/services_helpers.rb
+++ b/lib/api/helpers/services_helpers.rb
@@ -1,3 +1,4 @@
+# coding: utf-8
# frozen_string_literal: true
module API
diff --git a/lib/api/issues.rb b/lib/api/issues.rb
index d06550191ad..215178478d0 100644
--- a/lib/api/issues.rb
+++ b/lib/api/issues.rb
@@ -9,35 +9,28 @@ module API
before { authenticate_non_get! }
helpers do
- params :negatable_issue_filter_params do
+ params :issues_stats_params do
optional :labels, type: Array[String], coerce_with: Validations::Types::LabelsList.coerce, desc: 'Comma-separated list of label names'
optional :milestone, type: String, desc: 'Milestone title'
+ optional :milestone, type: String, desc: 'Return issues for a specific milestone'
optional :iids, type: Array[Integer], desc: 'The IID array of issues'
optional :search, type: String, desc: 'Search issues for text present in the title, description, or any combination of these'
optional :in, type: String, desc: '`title`, `description`, or a string joining them with comma'
+ optional :created_after, type: DateTime, desc: 'Return issues created after the specified time'
+ optional :created_before, type: DateTime, desc: 'Return issues created before the specified time'
+ optional :updated_after, type: DateTime, desc: 'Return issues updated after the specified time'
+ optional :updated_before, type: DateTime, desc: 'Return issues updated before the specified time'
optional :author_id, type: Integer, desc: 'Return issues which are authored by the user with the given ID'
optional :author_username, type: String, desc: 'Return issues which are authored by the user with the given username'
mutually_exclusive :author_id, :author_username
optional :assignee_id, types: [Integer, String], integer_none_any: true,
- desc: 'Return issues which are assigned to the user with the given ID'
+ desc: 'Return issues which are assigned to the user with the given ID'
optional :assignee_username, type: Array[String], check_assignees_count: true,
- coerce_with: Validations::CheckAssigneesCount.coerce,
- desc: 'Return issues which are assigned to the user with the given username'
+ coerce_with: Validations::CheckAssigneesCount.coerce,
+ desc: 'Return issues which are assigned to the user with the given username'
mutually_exclusive :assignee_id, :assignee_username
- end
-
- params :issues_stats_params do
- use :negatable_issue_filter_params
- optional :created_after, type: DateTime, desc: 'Return issues created after the specified time'
- optional :created_before, type: DateTime, desc: 'Return issues created before the specified time'
- optional :updated_after, type: DateTime, desc: 'Return issues updated after the specified time'
- optional :updated_before, type: DateTime, desc: 'Return issues updated before the specified time'
-
- optional :not, type: Hash do
- use :negatable_issue_filter_params
- end
optional :scope, type: String, values: %w[created-by-me assigned-to-me created_by_me assigned_to_me all],
desc: 'Return issues for the given scope: `created_by_me`, `assigned_to_me` or `all`'
diff --git a/lib/api/pipelines.rb b/lib/api/pipelines.rb
index e09d226a13f..9e888368e7b 100644
--- a/lib/api/pipelines.rb
+++ b/lib/api/pipelines.rb
@@ -69,19 +69,6 @@ module API
end
# rubocop: enable CodeReuse/ActiveRecord
- desc 'Gets a the latest pipeline for the project branch' do
- detail 'This feature was introduced in GitLab 12.3'
- success Entities::Pipeline
- end
- params do
- optional :ref, type: String, desc: 'branch ref of pipeline'
- end
- get ':id/pipelines/latest' do
- authorize! :read_pipeline, latest_pipeline
-
- present latest_pipeline, with: Entities::Pipeline
- end
-
desc 'Gets a specific pipeline for the project' do
detail 'This feature was introduced in GitLab 8.11'
success Entities::Pipeline
@@ -157,15 +144,7 @@ module API
helpers do
def pipeline
- strong_memoize(:pipeline) do
- user_project.ci_pipelines.find(params[:pipeline_id])
- end
- end
-
- def latest_pipeline
- strong_memoize(:latest_pipeline) do
- user_project.latest_pipeline_for_ref(params[:ref])
- end
+ @pipeline ||= user_project.ci_pipelines.find(params[:pipeline_id])
end
end
end
diff --git a/lib/api/projects.rb b/lib/api/projects.rb
index c28b03ac6c9..74de9fcec68 100644
--- a/lib/api/projects.rb
+++ b/lib/api/projects.rb
@@ -68,8 +68,6 @@ module API
params :create_params do
optional :namespace_id, type: Integer, desc: 'Namespace ID for the new project. Default to the user namespace.'
optional :import_url, type: String, desc: 'URL from which the project is imported'
- optional :template_name, type: String, desc: "Name of template from which to create project"
- mutually_exclusive :import_url, :template_name
end
def load_projects
@@ -157,7 +155,7 @@ module API
optional :name, type: String, desc: 'The name of the project'
optional :path, type: String, desc: 'The path of the repository'
at_least_one_of :name, :path
- use :optional_create_project_params
+ use :optional_project_params
use :create_params
end
post do
diff --git a/lib/api/releases.rb b/lib/api/releases.rb
index 4238529142c..5a31581c4da 100644
--- a/lib/api/releases.rb
+++ b/lib/api/releases.rb
@@ -54,7 +54,7 @@ module API
requires :url, type: String
end
end
- optional :milestones, type: Array, desc: 'The titles of the related milestones', default: []
+ optional :milestone, type: String, desc: 'The title of the related milestone'
optional :released_at, type: DateTime, desc: 'The date when the release will be/was ready. Defaults to the current time.'
end
post ':id/releases' do
@@ -80,7 +80,7 @@ module API
optional :name, type: String, desc: 'The name of the release'
optional :description, type: String, desc: 'Release notes with markdown support'
optional :released_at, type: DateTime, desc: 'The date when the release will be/was ready.'
- optional :milestones, type: Array, desc: 'The titles of the related milestones'
+ optional :milestone, type: String, desc: 'The title of the related milestone'
end
put ':id/releases/:tag_name', requirements: RELEASE_ENDPOINT_REQUIREMENTS do
authorize_update_release!
diff --git a/lib/gitlab/auth/ldap/dn.rb b/lib/gitlab/auth/ldap/dn.rb
index 0b496da784d..5df914aa367 100644
--- a/lib/gitlab/auth/ldap/dn.rb
+++ b/lib/gitlab/auth/ldap/dn.rb
@@ -1,3 +1,4 @@
+# -*- ruby encoding: utf-8 -*-
# frozen_string_literal: true
# Based on the `ruby-net-ldap` gem's `Net::LDAP::DN`
diff --git a/lib/gitlab/background_migration/add_gitlab_instance_administration_project.rb b/lib/gitlab/background_migration/add_gitlab_instance_administration_project.rb
deleted file mode 100644
index 730f1acee98..00000000000
--- a/lib/gitlab/background_migration/add_gitlab_instance_administration_project.rb
+++ /dev/null
@@ -1,14 +0,0 @@
-# frozen_string_literal: true
-# rubocop:disable Style/Documentation
-
-module Gitlab
- module BackgroundMigration
- class AddGitlabInstanceAdministrationProject
- def perform
- Rails.logger.info("Creating Gitlab instance administration project") # rubocop:disable Gitlab/RailsLogger
-
- Gitlab::DatabaseImporters::SelfMonitoring::Project::CreateService.new.execute!
- end
- end
- end
-end
diff --git a/lib/gitlab/ci/config/entry/job.rb b/lib/gitlab/ci/config/entry/job.rb
index 5874b01ef2a..f750886a8c5 100644
--- a/lib/gitlab/ci/config/entry/job.rb
+++ b/lib/gitlab/ci/config/entry/job.rb
@@ -14,8 +14,8 @@ module Gitlab
ALLOWED_WHEN = %w[on_success on_failure always manual delayed].freeze
ALLOWED_KEYS = %i[tags script only except rules type image services
allow_failure type stage when start_in artifacts cache
- dependencies before_script needs after_script variables
- environment coverage retry parallel extends interruptible timeout].freeze
+ dependencies needs before_script after_script variables
+ environment coverage retry parallel extends interruptible].freeze
REQUIRED_BY_NEEDS = %i[stage].freeze
@@ -46,8 +46,6 @@ module Gitlab
message: "should be one of: #{ALLOWED_WHEN.join(', ')}"
}
- validates :timeout, duration: { limit: ChronicDuration.output(Project::MAX_BUILD_TIMEOUT) }
-
validates :dependencies, array_of_strings: true
validates :needs, array_of_strings: true
validates :extends, array_of_strings_or_string: true
@@ -129,7 +127,7 @@ module Gitlab
attributes :script, :tags, :allow_failure, :when, :dependencies,
:needs, :retry, :parallel, :extends, :start_in, :rules,
- :interruptible, :timeout
+ :interruptible
def self.matching?(name, config)
!name.to_s.start_with?('.') &&
@@ -220,7 +218,6 @@ module Gitlab
retry: retry_defined? ? retry_value : nil,
parallel: parallel_defined? ? parallel_value.to_i : nil,
interruptible: interruptible_defined? ? interruptible_value : nil,
- timeout: has_timeout? ? ChronicDuration.parse(timeout.to_s) : nil,
artifacts: artifacts_value,
after_script: after_script_value,
ignore: ignored?,
diff --git a/lib/gitlab/ci/templates/Security/Container-Scanning.gitlab-ci.yml b/lib/gitlab/ci/templates/Security/Container-Scanning.gitlab-ci.yml
index 7f9a7df2f31..56ce33203ad 100644
--- a/lib/gitlab/ci/templates/Security/Container-Scanning.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Security/Container-Scanning.gitlab-ci.yml
@@ -2,26 +2,57 @@
container_scanning:
stage: test
- image:
- name: registry.gitlab.com/gitlab-org/security-products/analyzers/klar:$CI_SERVER_VERSION_MAJOR-$CI_SERVER_VERSION_MINOR-stable
- entrypoint: []
+ image: docker:stable
variables:
- # By default, use the latest clair vulnerabilities database, however, allow it to be overridden here
- # with a specific version to provide consistency for integration testing purposes
- CLAIR_DB_IMAGE_TAG: latest
- # Override this variable in your `.gitlab-ci.yml` file and set it to `fetch` if you want to provide a `clair-whitelist.yaml` file.
- # See https://docs.gitlab.com/ee/user/application_security/container_scanning/index.html#overriding-the-container-scanning-template
- # for details
+ DOCKER_DRIVER: overlay2
+ DOCKER_TLS_CERTDIR: ""
+ # Defining two new variables based on GitLab's CI/CD predefined variables
+ # https://docs.gitlab.com/ee/ci/variables/#predefined-environment-variables
+ CI_APPLICATION_REPOSITORY: $CI_REGISTRY_IMAGE/$CI_COMMIT_REF_SLUG
+ CI_APPLICATION_TAG: $CI_COMMIT_SHA
+ # Prior to this, you need to have the Container Registry running for your project and setup a build job
+ # with at least the following steps:
+ #
+ # docker build -t $CI_REGISTRY_IMAGE/$CI_COMMIT_REF_SLUG .
+ # docker push $CI_REGISTRY_IMAGE/$CI_COMMIT_REF_SLUG:$CI_COMMIT_SHA
+ #
+ # Container Scanning deals with Docker images only so no need to import the project's Git repository:
GIT_STRATEGY: none
+ # Services and containers running in the same Kubernetes pod are all sharing the same localhost address
+ # https://docs.gitlab.com/runner/executors/kubernetes.html
+ DOCKER_SERVICE: docker
+ DOCKER_HOST: tcp://${DOCKER_SERVICE}:2375/
+ # https://hub.docker.com/r/arminc/clair-local-scan/tags
+ CLAIR_LOCAL_SCAN_VERSION: v2.0.8_0ed98e9ead65a51ba53f7cc53fa5e80c92169207
+ CLAIR_EXECUTABLE_VERSION: v12
+ CLAIR_EXECUTABLE_SHA: 44f2a3fdd7b0d102c98510e7586f6956edc89ab72c6943980f92f4979f7f4081
+ ## Disable the proxy for clair-local-scan, otherwise Container Scanning will
+ ## fail when a proxy is used.
+ NO_PROXY: ${DOCKER_SERVICE},localhost
allow_failure: true
services:
- - name: arminc/clair-db:$CLAIR_DB_IMAGE_TAG
- alias: clair-vulnerabilities-db
+ - docker:stable-dind
script:
- # the kubernetes executor currently ignores the Docker image entrypoint value, so the start.sh script must
- # be explicitly executed here in order for this to work with both the kubernetes and docker executors
- # see this issue for more details https://gitlab.com/gitlab-org/gitlab-runner/issues/4125
- - /container-scanner/start.sh
+ - if [[ -n "$KUBERNETES_PORT" ]]; then { export DOCKER_SERVICE="localhost" ; export DOCKER_HOST="tcp://${DOCKER_SERVICE}:2375" ; } fi
+ - |
+ if [[ -n "$CI_REGISTRY_USER" ]]; then
+ echo "Logging to GitLab Container Registry with CI credentials..."
+ docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" "$CI_REGISTRY"
+ echo ""
+ fi
+ - docker run -d --name db arminc/clair-db:latest
+ - docker run -p 6060:6060 --link db:postgres -d --name clair --restart on-failure arminc/clair-local-scan:${CLAIR_LOCAL_SCAN_VERSION}
+ - apk add -U wget ca-certificates
+ - docker pull ${CI_APPLICATION_REPOSITORY}:${CI_APPLICATION_TAG}
+ - wget https://github.com/arminc/clair-scanner/releases/download/${CLAIR_EXECUTABLE_VERSION}/clair-scanner_linux_amd64
+ - echo "${CLAIR_EXECUTABLE_SHA} clair-scanner_linux_amd64" | sha256sum -c
+ - mv clair-scanner_linux_amd64 clair-scanner
+ - chmod +x clair-scanner
+ - touch clair-whitelist.yml
+ - retries=0
+ - echo "Waiting for clair daemon to start"
+ - while( ! wget -T 10 -q -O /dev/null http://${DOCKER_SERVICE}:6060/v1/namespaces ) ; do sleep 1 ; echo -n "." ; if [ $retries -eq 10 ] ; then echo " Timeout, aborting." ; exit 1 ; fi ; retries=$(($retries+1)) ; done
+ - ./clair-scanner -c http://${DOCKER_SERVICE}:6060 --ip $(hostname -i) -r gl-container-scanning-report.json -l clair.log -w clair-whitelist.yml ${CI_APPLICATION_REPOSITORY}:${CI_APPLICATION_TAG} || true
artifacts:
reports:
container_scanning: gl-container-scanning-report.json
diff --git a/lib/gitlab/ci/templates/Security/SAST.gitlab-ci.yml b/lib/gitlab/ci/templates/Security/SAST.gitlab-ci.yml
index a61731a24b7..88f4b72044c 100644
--- a/lib/gitlab/ci/templates/Security/SAST.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Security/SAST.gitlab-ci.yml
@@ -4,13 +4,28 @@
# List of the variables: https://gitlab.com/gitlab-org/security-products/sast#settings
# How to set: https://docs.gitlab.com/ee/ci/yaml/#variables
-sast:
+.sast:
stage: test
+ allow_failure: true
+ artifacts:
+ reports:
+ sast: gl-sast-report.json
+ only:
+ refs:
+ - branches
+ variables:
+ - $GITLAB_FEATURES =~ /\bsast\b/
+
+variables:
+ SAST_ANALYZER_IMAGE_PREFIX: "registry.gitlab.com/gitlab-org/security-products/analyzers"
+ SAST_DISABLE_DIND: "false"
+
+sast:
+ extends: .sast
image: docker:stable
variables:
DOCKER_DRIVER: overlay2
DOCKER_TLS_CERTDIR: ""
- allow_failure: true
services:
- docker:stable-dind
script:
@@ -63,15 +78,116 @@ sast:
--volume "$PWD:/code" \
--volume /var/run/docker.sock:/var/run/docker.sock \
"registry.gitlab.com/gitlab-org/security-products/sast:$SAST_VERSION" /app/bin/run /code
- artifacts:
- reports:
- sast: gl-sast-report.json
- dependencies: []
- only:
- refs:
- - branches
- variables:
- - $GITLAB_FEATURES =~ /\bsast\b/
except:
variables:
- $SAST_DISABLED
+ - $SAST_DISABLE_DIND == 'true'
+
+.analyzer:
+ extends: .sast
+ except:
+ variables:
+ - $SAST_DISABLE_DIND == 'false'
+ script:
+ - /analyzer run
+
+bandit-sast:
+ extends: .analyzer
+ image:
+ name: "$SAST_ANALYZER_IMAGE_PREFIX/bandit"
+ only:
+ variables:
+ - '$CI_PROJECT_REPOSITORY_LANGUAGES =~ /python/'
+
+brakeman-sast:
+ extends: .analyzer
+ image:
+ name: "$SAST_ANALYZER_IMAGE_PREFIX/brakeman"
+ only:
+ variables:
+ - '$CI_PROJECT_REPOSITORY_LANGUAGES =~ /ruby/'
+
+eslint-sast:
+ extends: .analyzer
+ image:
+ name: "$SAST_ANALYZER_IMAGE_PREFIX/eslint"
+ only:
+ variables:
+ - '$CI_PROJECT_REPOSITORY_LANGUAGES =~ /javascript/'
+
+flawfinder-sast:
+ extends: .analyzer
+ image:
+ name: "$SAST_ANALYZER_IMAGE_PREFIX/flawfinder"
+ only:
+ variables:
+ - '$CI_PROJECT_REPOSITORY_LANGUAGES =~ /\b(c\+\+|c\b)/'
+
+gosec-sast:
+ extends: .analyzer
+ image:
+ name: "$SAST_ANALYZER_IMAGE_PREFIX/gosec"
+ only:
+ variables:
+ - '$CI_PROJECT_REPOSITORY_LANGUAGES =~ /go/'
+
+nodejs-scan-sast:
+ extends: .analyzer
+ image:
+ name: "$SAST_ANALYZER_IMAGE_PREFIX/nodejs-scan"
+ only:
+ variables:
+ - '$CI_PROJECT_REPOSITORY_LANGUAGES =~ /javascript/'
+
+phpcs-security-audit-sast:
+ extends: .analyzer
+ image:
+ name: "$SAST_ANALYZER_IMAGE_PREFIX/phpcs-security-audit"
+ only:
+ variables:
+ - '$CI_PROJECT_REPOSITORY_LANGUAGES =~ /php/'
+
+pmd-apex-sast:
+ extends: .analyzer
+ image:
+ name: "$SAST_ANALYZER_IMAGE_PREFIX/pmd-apex"
+ only:
+ variables:
+ - '$CI_PROJECT_REPOSITORY_LANGUAGES =~ /apex/'
+
+secrets-sast:
+ extends: .analyzer
+ image:
+ name: "$SAST_ANALYZER_IMAGE_PREFIX/secrets"
+
+security-code-scan-sast:
+ extends: .analyzer
+ image:
+ name: "$SAST_ANALYZER_IMAGE_PREFIX/security-code-scan"
+ only:
+ variables:
+ - '$CI_PROJECT_REPOSITORY_LANGUAGES =~ /c\#/ || $CI_PROJECT_REPOSITORY_LANGUAGES =~ /visual basic/'
+
+sobelow-sast:
+ extends: .analyzer
+ image:
+ name: "$SAST_ANALYZER_IMAGE_PREFIX/sobelow"
+ only:
+ variables:
+ - '$CI_PROJECT_REPOSITORY_LANGUAGES =~ /elixir/'
+
+spotbugs-sast:
+ extends: .analyzer
+ image:
+ name: "$SAST_ANALYZER_IMAGE_PREFIX/spotbugs"
+ only:
+ variables:
+ - '$CI_PROJECT_REPOSITORY_LANGUAGES =~ /java\b/'
+
+tslint-sast:
+ extends: .analyzer
+ image:
+ name: "$SAST_ANALYZER_IMAGE_PREFIX/tslint"
+ only:
+ variables:
+ - '$CI_PROJECT_REPOSITORY_LANGUAGES =~ /typescript/'
diff --git a/lib/gitlab/ci/yaml_processor.rb b/lib/gitlab/ci/yaml_processor.rb
index f6a3abefcfb..986605efdc3 100644
--- a/lib/gitlab/ci/yaml_processor.rb
+++ b/lib/gitlab/ci/yaml_processor.rb
@@ -49,7 +49,6 @@ module Gitlab
artifacts: job[:artifacts],
cache: job[:cache],
dependencies: job[:dependencies],
- job_timeout: job[:timeout],
before_script: job[:before_script],
script: job[:script],
after_script: job[:after_script],
diff --git a/lib/gitlab/daemon.rb b/lib/gitlab/daemon.rb
index 43c159fee27..2f4ae010e74 100644
--- a/lib/gitlab/daemon.rb
+++ b/lib/gitlab/daemon.rb
@@ -10,8 +10,8 @@ module Gitlab
@instance
end
- def self.instance(*args)
- @instance ||= initialize_instance(*args)
+ def self.instance
+ @instance ||= initialize_instance
end
attr_reader :thread
diff --git a/lib/gitlab/devise_failure.rb b/lib/gitlab/devise_failure.rb
deleted file mode 100644
index 4d27b706e1e..00000000000
--- a/lib/gitlab/devise_failure.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- class DeviseFailure < Devise::FailureApp
- # If the request format is not known, send a redirect instead of a 401
- # response, since this is the outcome we're most likely to want
- def http_auth?
- return super unless Feature.enabled?(:devise_redirect_unknown_formats, default_enabled: true)
-
- request_format && super
- end
- end
-end
diff --git a/lib/gitlab/discussions_diff/file_collection.rb b/lib/gitlab/discussions_diff/file_collection.rb
index 6692dd76438..4ab7314f509 100644
--- a/lib/gitlab/discussions_diff/file_collection.rb
+++ b/lib/gitlab/discussions_diff/file_collection.rb
@@ -4,16 +4,11 @@ module Gitlab
module DiscussionsDiff
class FileCollection
include Gitlab::Utils::StrongMemoize
- include Enumerable
def initialize(collection)
@collection = collection
end
- def each(&block)
- @collection.each(&block)
- end
-
# Returns a Gitlab::Diff::File with the given ID (`unique_identifier` in
# Gitlab::Diff::File).
def find_by_id(id)
@@ -21,12 +16,20 @@ module Gitlab
end
# Writes cache and preloads highlighted diff lines for
- # highlightable object IDs, in @collection.
+ # object IDs, in @collection.
+ #
+ # highlightable_ids - Diff file `Array` responding to ID. The ID will be used
+ # to generate the cache key.
#
# - Highlight cache is written just for uncached diff files
# - The cache content is not updated (there's no need to do so)
- def load_highlight
- ids = highlightable_collection_ids
+ def load_highlight(highlightable_ids)
+ preload_highlighted_lines(highlightable_ids)
+ end
+
+ private
+
+ def preload_highlighted_lines(ids)
cached_content = read_cache(ids)
uncached_ids = ids.select.each_with_index { |_, i| cached_content[i].nil? }
@@ -43,12 +46,6 @@ module Gitlab
end
end
- private
-
- def highlightable_collection_ids
- each.with_object([]) { |file, memo| memo << file.id unless file.resolved_at }
- end
-
def read_cache(ids)
HighlightCache.read_multiple(ids)
end
@@ -60,7 +57,9 @@ module Gitlab
end
def diff_files
- strong_memoize(:diff_files) { map(&:raw_diff_file) }
+ strong_memoize(:diff_files) do
+ @collection.map(&:raw_diff_file)
+ end
end
# Processes the diff lines highlighting for diff files matching the given
diff --git a/lib/gitlab/ee_compat_check.rb b/lib/gitlab/ee_compat_check.rb
index 5cd90814ca3..20c31e06905 100644
--- a/lib/gitlab/ee_compat_check.rb
+++ b/lib/gitlab/ee_compat_check.rb
@@ -1,3 +1,4 @@
+# coding: utf-8
# frozen_string_literal: true
# rubocop: disable Rails/Output
diff --git a/lib/gitlab/etag_caching/router.rb b/lib/gitlab/etag_caching/router.rb
index 7b921ab6199..3d14a8dde8d 100644
--- a/lib/gitlab/etag_caching/router.rb
+++ b/lib/gitlab/etag_caching/router.rb
@@ -53,6 +53,10 @@ module Gitlab
'project_build'
),
Gitlab::EtagCaching::Router::Route.new(
+ %r(#{RESERVED_WORDS_PREFIX}/clusters/\d+/environments\z),
+ 'cluster_environments'
+ ),
+ Gitlab::EtagCaching::Router::Route.new(
%r(#{RESERVED_WORDS_PREFIX}/environments\.json\z),
'environments'
),
diff --git a/lib/gitlab/hook_data/merge_request_builder.rb b/lib/gitlab/hook_data/merge_request_builder.rb
index 0678799b64b..a8e993e087e 100644
--- a/lib/gitlab/hook_data/merge_request_builder.rb
+++ b/lib/gitlab/hook_data/merge_request_builder.rb
@@ -34,7 +34,6 @@ module Gitlab
end
SAFE_HOOK_RELATIONS = %i[
- assignees
labels
total_time_spent
].freeze
diff --git a/lib/gitlab/profiler.rb b/lib/gitlab/profiler.rb
index 275151f7fc1..3f26b84be20 100644
--- a/lib/gitlab/profiler.rb
+++ b/lib/gitlab/profiler.rb
@@ -1,3 +1,4 @@
+# coding: utf-8
# frozen_string_literal: true
module Gitlab
diff --git a/lib/gitlab/quick_actions/issuable_actions.rb b/lib/gitlab/quick_actions/issuable_actions.rb
index 340ec75c5f1..5cf24823ef5 100644
--- a/lib/gitlab/quick_actions/issuable_actions.rb
+++ b/lib/gitlab/quick_actions/issuable_actions.rb
@@ -1,3 +1,4 @@
+# coding: utf-8
# frozen_string_literal: true
module Gitlab
diff --git a/lib/gitlab/slash_commands/presenters/issue_move.rb b/lib/gitlab/slash_commands/presenters/issue_move.rb
index 01f2025ee10..ca0644ede95 100644
--- a/lib/gitlab/slash_commands/presenters/issue_move.rb
+++ b/lib/gitlab/slash_commands/presenters/issue_move.rb
@@ -1,3 +1,4 @@
+# coding: utf-8
# frozen_string_literal: true
module Gitlab
diff --git a/lib/gitlab/time_tracking_formatter.rb b/lib/gitlab/time_tracking_formatter.rb
index b15cb85dde0..31883527135 100644
--- a/lib/gitlab/time_tracking_formatter.rb
+++ b/lib/gitlab/time_tracking_formatter.rb
@@ -5,7 +5,7 @@ module Gitlab
extend self
# We may want to configure it through project settings in a future version.
- CUSTOM_DAY_AND_MONTH_LENGTH = { hours_per_day: 8, days_per_month: 20 }.freeze
+ CUSTOM_DAY_AND_WEEK_LENGTH = { hours_per_day: 8, days_per_month: 20 }.freeze
def parse(string)
string = string.sub(/\A-/, '')
@@ -14,7 +14,7 @@ module Gitlab
begin
ChronicDuration.parse(
string,
- CUSTOM_DAY_AND_MONTH_LENGTH.merge(default_unit: 'hours'))
+ CUSTOM_DAY_AND_WEEK_LENGTH.merge(default_unit: 'hours'))
rescue
nil
end
@@ -26,7 +26,7 @@ module Gitlab
def output(seconds)
ChronicDuration.output(
seconds,
- CUSTOM_DAY_AND_MONTH_LENGTH.merge(
+ CUSTOM_DAY_AND_WEEK_LENGTH.merge(
format: :short,
limit_to_hours: limit_to_hours_setting,
weeks: true))
diff --git a/lib/gitlab/usage_data.rb b/lib/gitlab/usage_data.rb
index c6c2876033d..5cd54c302fc 100644
--- a/lib/gitlab/usage_data.rb
+++ b/lib/gitlab/usage_data.rb
@@ -3,7 +3,6 @@
module Gitlab
class UsageData
APPROXIMATE_COUNT_MODELS = [Label, MergeRequest, Note, Todo].freeze
- BATCH_SIZE = 100
class << self
def data(force_refresh: false)
@@ -14,10 +13,10 @@ module Gitlab
def uncached_data
license_usage_data.merge(system_usage_data)
- .merge(features_usage_data)
- .merge(components_usage_data)
- .merge(cycle_analytics_usage_data)
- .merge(usage_counters)
+ .merge(features_usage_data)
+ .merge(components_usage_data)
+ .merge(cycle_analytics_usage_data)
+ .merge(usage_counters)
end
def to_json(force_refresh: false)
@@ -97,8 +96,9 @@ module Gitlab
todos: count(Todo),
uploads: count(Upload),
web_hooks: count(WebHook)
- }.merge(services_usage)
- .merge(approximate_counts)
+ }
+ .merge(services_usage)
+ .merge(approximate_counts)
}.tap do |data|
data[:counts][:user_preferences] = user_preferences_usage
end
@@ -173,34 +173,17 @@ module Gitlab
def jira_usage
# Jira Cloud does not support custom domains as per https://jira.atlassian.com/browse/CLOUD-6999
# so we can just check for subdomains of atlassian.net
+ services = count(
+ Service.unscoped.where(type: :JiraService, active: true)
+ .group("CASE WHEN properties LIKE '%.atlassian.net%' THEN 'cloud' ELSE 'server' END"),
+ fallback: Hash.new(-1)
+ )
- results = {
- projects_jira_server_active: 0,
- projects_jira_cloud_active: 0,
- projects_jira_active: -1
+ {
+ projects_jira_server_active: services['server'] || 0,
+ projects_jira_cloud_active: services['cloud'] || 0,
+ projects_jira_active: services['server'] == -1 ? -1 : services.values.sum
}
-
- Service.unscoped
- .where(type: :JiraService, active: true)
- .includes(:jira_tracker_data)
- .find_in_batches(batch_size: BATCH_SIZE) do |services|
-
- counts = services.group_by do |service|
- # TODO: Simplify as part of https://gitlab.com/gitlab-org/gitlab-ce/issues/63084
- service_url = service.data_fields&.url || (service.properties && service.properties['url'])
- service_url&.include?('.atlassian.net') ? :cloud : :server
- end
-
- results[:projects_jira_server_active] += counts[:server].count if counts[:server]
- results[:projects_jira_cloud_active] += counts[:cloud].count if counts[:cloud]
- if results[:projects_jira_active] == -1
- results[:projects_jira_active] = count(services)
- else
- results[:projects_jira_active] += count(services)
- end
- end
-
- results
end
def user_preferences_usage
diff --git a/lib/gitlab_danger.rb b/lib/gitlab_danger.rb
index 499ae6111d7..b4768a9546d 100644
--- a/lib/gitlab_danger.rb
+++ b/lib/gitlab_danger.rb
@@ -10,17 +10,18 @@ class GitlabDanger
prettier
eslint
database
- commit_messages
].freeze
CI_ONLY_RULES ||= %w[
metadata
changelog
specs
+ commit_messages
roulette
single_codebase
gitlab_ui_wg
ce_ee_vue_templates
+ only_documentation
].freeze
MESSAGE_PREFIX = '==>'.freeze
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index bdd4805997c..9667a9b1c8e 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -391,9 +391,6 @@ msgstr ""
msgid "'%{source}' is not a import source"
msgstr ""
-msgid "'%{template_name}' is unknown or invalid"
-msgstr ""
-
msgid "(%d closed)"
msgid_plural "(%d closed)"
msgstr[0] ""
@@ -3514,9 +3511,6 @@ msgstr ""
msgid "ClusterIntegration|Let's Encrypt"
msgstr ""
-msgid "ClusterIntegration|Loading IAM Roles"
-msgstr ""
-
msgid "ClusterIntegration|Machine type"
msgstr ""
@@ -3526,9 +3520,6 @@ msgstr ""
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{link_gke}"
msgstr ""
-msgid "ClusterIntegration|No IAM Roles found"
-msgstr ""
-
msgid "ClusterIntegration|No machine types matched your search"
msgstr ""
@@ -3595,15 +3586,9 @@ msgstr ""
msgid "ClusterIntegration|Request to begin uninstalling failed"
msgstr ""
-msgid "ClusterIntegration|Role name"
-msgstr ""
-
msgid "ClusterIntegration|Save changes"
msgstr ""
-msgid "ClusterIntegration|Search IAM Roles"
-msgstr ""
-
msgid "ClusterIntegration|Search machine types"
msgstr ""
@@ -3628,9 +3613,6 @@ msgstr ""
msgid "ClusterIntegration|Select project to choose zone"
msgstr ""
-msgid "ClusterIntegration|Select the IAM Role to allow Amazon EKS and the Kubernetes control plane to manage AWS resources on your behalf. To use a new role name, first create one on %{startLink}Amazon Web Services%{endLink}."
-msgstr ""
-
msgid "ClusterIntegration|Select zone"
msgstr ""
@@ -3754,9 +3736,6 @@ msgstr ""
msgid "ClusterIntegration|sign up"
msgstr ""
-msgid "ClusterIntergation|Select role name"
-msgstr ""
-
msgid "Code"
msgstr ""
@@ -5842,9 +5821,6 @@ msgstr ""
msgid "Epics Roadmap"
msgstr ""
-msgid "Epics and Issues"
-msgstr ""
-
msgid "Epics let you manage your portfolio of projects more efficiently and with less effort"
msgstr ""
@@ -5896,9 +5872,6 @@ msgstr ""
msgid "Epics|Something went wrong while fetching group epics."
msgstr ""
-msgid "Epics|Something went wrong while ordering item."
-msgstr ""
-
msgid "Epics|Something went wrong while removing issue from epic."
msgstr ""
@@ -10358,6 +10331,9 @@ msgstr ""
msgid "None"
msgstr ""
+msgid "Not all data has been processed yet, the accuracy of the chart for the selected timeframe is limited."
+msgstr ""
+
msgid "Not available"
msgstr ""
@@ -15547,6 +15523,12 @@ msgstr ""
msgid "There is already a repository with that name on disk"
msgstr ""
+msgid "There is no data available. Please change your selection."
+msgstr ""
+
+msgid "There is no data for the selected metric. Please change your selection."
+msgstr ""
+
msgid "There was a problem communicating with your device."
msgstr ""
@@ -16382,6 +16364,9 @@ msgstr ""
msgid "TransferProject|Transfer failed, please contact an admin."
msgstr ""
+msgid "Tree"
+msgstr ""
+
msgid "Tree view"
msgstr ""
diff --git a/package.json b/package.json
index c468f7875ae..20747b910a1 100644
--- a/package.json
+++ b/package.json
@@ -37,8 +37,8 @@
"@babel/plugin-syntax-dynamic-import": "^7.2.0",
"@babel/plugin-syntax-import-meta": "^7.2.0",
"@babel/preset-env": "^7.5.5",
- "@gitlab/svgs": "^1.73.0",
- "@gitlab/ui": "5.25.2",
+ "@gitlab/svgs": "^1.72.0",
+ "@gitlab/ui": "5.21.1",
"@gitlab/visual-review-tools": "1.0.1",
"apollo-cache-inmemory": "^1.5.1",
"apollo-client": "^2.5.1",
@@ -115,7 +115,7 @@
"select2": "3.5.2-browserify",
"sha1": "^1.1.1",
"smooshpack": "^0.0.54",
- "sortablejs": "^1.10.0",
+ "sortablejs": "^1.7.0",
"sql.js": "^0.4.0",
"stickyfilljs": "^2.0.5",
"style-loader": "^0.23.1",
@@ -137,7 +137,6 @@
"vue-router": "^3.0.2",
"vue-template-compiler": "^2.6.10",
"vue-virtual-scroll-list": "^1.3.1",
- "vuedraggable": "^2.23.0",
"vuex": "^3.1.0",
"webpack": "^4.29.0",
"webpack-bundle-analyzer": "^3.3.2",
@@ -164,6 +163,7 @@
"eslint": "~5.9.0",
"eslint-import-resolver-jest": "^2.1.1",
"eslint-import-resolver-webpack": "^0.10.1",
+ "eslint-plugin-html": "5.0.0",
"eslint-plugin-import": "^2.14.0",
"eslint-plugin-jasmine": "^2.10.1",
"eslint-plugin-jest": "^22.3.0",
diff --git a/qa/qa.rb b/qa/qa.rb
index 6e87129641a..dc9ef3ac464 100644
--- a/qa/qa.rb
+++ b/qa/qa.rb
@@ -61,7 +61,6 @@ module QA
autoload :KubernetesCluster, 'qa/resource/kubernetes_cluster'
autoload :User, 'qa/resource/user'
autoload :ProjectMilestone, 'qa/resource/project_milestone'
- autoload :Members, 'qa/resource/members'
autoload :Wiki, 'qa/resource/wiki'
autoload :File, 'qa/resource/file'
autoload :Fork, 'qa/resource/fork'
@@ -275,7 +274,6 @@ module QA
autoload :Edit, 'qa/page/project/wiki/edit'
autoload :New, 'qa/page/project/wiki/new'
autoload :Show, 'qa/page/project/wiki/show'
- autoload :GitAccess, 'qa/page/project/wiki/git_access'
end
module WebIDE
diff --git a/qa/qa/page/admin/settings/general.rb b/qa/qa/page/admin/settings/general.rb
index 150775f57d2..93b290f7e03 100644
--- a/qa/qa/page/admin/settings/general.rb
+++ b/qa/qa/page/admin/settings/general.rb
@@ -7,7 +7,7 @@ module QA
class General < Page::Base
include QA::Page::Settings::Common
- view 'app/views/admin/application_settings/general.html.haml' do
+ view 'app/views/admin/application_settings/show.html.haml' do
element :account_and_limit_settings
end
diff --git a/qa/qa/page/main/login.rb b/qa/qa/page/main/login.rb
index ca93663dba2..65d83926f38 100644
--- a/qa/qa/page/main/login.rb
+++ b/qa/qa/page/main/login.rb
@@ -44,7 +44,7 @@ module QA
def sign_in_using_credentials(user = nil)
# Don't try to log-in if we're already logged-in
- return if Page::Main::Menu.perform(&:signed_in?)
+ return if Page::Main::Menu.perform { |menu| menu.has_personal_area?(wait: 0) }
using_wait_time 0 do
set_initial_password_if_present
@@ -75,7 +75,10 @@ module QA
end
def sign_in_using_ldap_credentials(user)
- Page::Main::Menu.perform(&:sign_out_if_signed_in)
+ # Log out if already logged in
+ Page::Main::Menu.perform do |menu|
+ menu.sign_out if menu.has_personal_area?(wait: 0)
+ end
using_wait_time 0 do
set_initial_password_if_present
@@ -146,7 +149,7 @@ module QA
end
def sign_out_and_sign_in_as(user:)
- Menu.perform(&:sign_out_if_signed_in)
+ Menu.perform(&:sign_out)
has_sign_in_tab?
sign_in_using_credentials(user)
end
diff --git a/qa/qa/page/main/menu.rb b/qa/qa/page/main/menu.rb
index 751b67d7695..4676dc8d077 100644
--- a/qa/qa/page/main/menu.rb
+++ b/qa/qa/page/main/menu.rb
@@ -55,10 +55,6 @@ module QA
within_top_menu { click_element :admin_area_link }
end
- def signed_in?
- has_personal_area?(wait: 0)
- end
-
def sign_out
within_user_menu do
click_element :sign_out_link
@@ -66,7 +62,7 @@ module QA
end
def sign_out_if_signed_in
- sign_out if signed_in?
+ sign_out if has_personal_area?(wait: 0)
end
def click_settings_link
diff --git a/qa/qa/page/project/settings/mirroring_repositories.rb b/qa/qa/page/project/settings/mirroring_repositories.rb
index 441235afca8..e3afaceda80 100644
--- a/qa/qa/page/project/settings/mirroring_repositories.rb
+++ b/qa/qa/page/project/settings/mirroring_repositories.rb
@@ -13,8 +13,8 @@ module QA
view 'app/views/projects/mirrors/_mirror_repos.html.haml' do
element :mirror_repository_url_input
element :mirror_repository_button
- element :mirror_repository_url_cell
- element :mirror_last_update_at_cell
+ element :mirror_repository_url
+ element :mirror_last_update_at
element :mirrored_repository_row
end
@@ -64,21 +64,21 @@ module QA
wait(interval: 1) do
within_element_by_index(:mirrored_repository_row, row_index) do
- last_update = find_element(:mirror_last_update_at_cell, wait: 0)
+ last_update = find_element(:mirror_last_update_at, wait: 0)
last_update.has_text?('just now') || last_update.has_text?('seconds')
end
end
# Fail early if the page still shows that there has been no update
within_element_by_index(:mirrored_repository_row, row_index) do
- find_element(:mirror_last_update_at_cell, wait: 0).assert_no_text('Never')
+ find_element(:mirror_last_update_at, wait: 0).assert_no_text('Never')
end
end
private
def find_repository_row_index(target_url)
- all_elements(:mirror_repository_url_cell).index do |url|
+ all_elements(:mirror_repository_url).index do |url|
# The url might be a sanitized url but the target_url won't be so
# we compare just the paths instead of the full url
URI.parse(url.text).path == target_url.path
diff --git a/qa/qa/page/project/settings/protected_branches.rb b/qa/qa/page/project/settings/protected_branches.rb
index d1d2f302013..1e707f1d315 100644
--- a/qa/qa/page/project/settings/protected_branches.rb
+++ b/qa/qa/page/project/settings/protected_branches.rb
@@ -25,10 +25,6 @@ module QA
element :protected_branches_list
end
- view 'app/views/projects/protected_branches/shared/_create_protected_branch.html.haml' do
- element :protect_button
- end
-
def select_branch(branch_name)
click_element :protected_branch_select
@@ -37,31 +33,40 @@ module QA
end
end
- def select_allowed_to_merge(allowed)
- select_allowed(:merge, allowed)
+ def allow_no_one_to_push
+ go_to_allow(:push, 'No one')
+ end
+
+ def allow_devs_and_maintainers_to_push
+ go_to_allow(:push, 'Developers + Maintainers')
end
- def select_allowed_to_push(allowed)
- select_allowed(:push, allowed)
+ # @deprecated
+ alias_method :allow_devs_and_masters_to_push, :allow_devs_and_maintainers_to_push
+
+ def allow_no_one_to_merge
+ go_to_allow(:merge, 'No one')
end
+ def allow_devs_and_maintainers_to_merge
+ go_to_allow(:merge, 'Developers + Maintainers')
+ end
+
+ # @deprecated
+ alias_method :allow_devs_and_masters_to_merge, :allow_devs_and_maintainers_to_merge
+
def protect_branch
- click_element :protect_button
+ click_on 'Protect'
end
private
- def select_allowed(action, allowed)
+ def go_to_allow(action, text)
click_element :"allowed_to_#{action}_select"
- allowed[:roles] = Resource::ProtectedBranch::Roles::NO_ONE unless allowed.key?(:roles)
-
within_element(:"allowed_to_#{action}_dropdown") do
- click_on allowed[:roles]
+ click_on text
end
-
- # Click the select element again to close the dropdown
- click_element :protected_branch_select
end
end
end
diff --git a/qa/qa/page/project/wiki/git_access.rb b/qa/qa/page/project/wiki/git_access.rb
deleted file mode 100644
index 28cb21be4e3..00000000000
--- a/qa/qa/page/project/wiki/git_access.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-# frozen_string_literal: true
-
-module QA
- module Page
- module Project
- module Wiki
- class GitAccess < Page::Base
- include Page::Component::LegacyClonePanel
- end
- end
- end
- end
-end
diff --git a/qa/qa/resource/group.rb b/qa/qa/resource/group.rb
index e11bd5728fb..b5beba64c61 100644
--- a/qa/qa/resource/group.rb
+++ b/qa/qa/resource/group.rb
@@ -3,8 +3,6 @@
module QA
module Resource
class Group < Base
- include Members
-
attr_accessor :path, :description
attribute :sandbox do
@@ -50,10 +48,19 @@ module QA
super
end
+ def add_member(user, access_level = '30')
+ # 30 = developer access
+ post Runtime::API::Request.new(api_client, api_members_path).url, { user_id: user.id, access_level: access_level }
+ end
+
def api_get_path
"/groups/#{CGI.escape("#{sandbox.path}/#{path}")}"
end
+ def api_members_path
+ "#{api_get_path}/members"
+ end
+
def api_post_path
'/groups'
end
diff --git a/qa/qa/resource/members.rb b/qa/qa/resource/members.rb
deleted file mode 100644
index d70a2907523..00000000000
--- a/qa/qa/resource/members.rb
+++ /dev/null
@@ -1,28 +0,0 @@
-# frozen_string_literal: true
-
-module QA
- module Resource
- #
- # Included in Resource::Project and Resource::Group to allow changes to
- # project/group membership
- #
- module Members
- def add_member(user, access_level = AccessLevel::DEVELOPER)
- post Runtime::API::Request.new(api_client, api_members_path).url, { user_id: user.id, access_level: access_level }
- end
-
- def api_members_path
- "#{api_get_path}/members"
- end
-
- class AccessLevel
- NO_ACCESS = 0
- GUEST = 10
- REPORTER = 20
- DEVELOPER = 30
- MAINTAINER = 40
- OWNER = 50
- end
- end
- end
-end
diff --git a/qa/qa/resource/project.rb b/qa/qa/resource/project.rb
index a0389390c83..2e49f69bd55 100644
--- a/qa/qa/resource/project.rb
+++ b/qa/qa/resource/project.rb
@@ -6,7 +6,6 @@ module QA
module Resource
class Project < Base
include Events::Project
- include Members
attr_writer :initialize_with_readme
attr_writer :visibility
@@ -76,6 +75,11 @@ module QA
super
end
+ def add_member(user, access_level = '30')
+ # 30 = developer access
+ post Runtime::API::Request.new(api_client, api_members_path).url, { user_id: user.id, access_level: access_level }
+ end
+
def api_get_path
"/projects/#{CGI.escape(path_with_namespace)}"
end
@@ -108,10 +112,6 @@ module QA
post_body
end
- def share_with_group(invitee, access_level = Resource::Members::AccessLevel::DEVELOPER)
- post Runtime::API::Request.new(api_client, "/projects/#{id}/share").url, { group_id: invitee.id, group_access: access_level }
- end
-
private
def transform_api_resource(api_resource)
diff --git a/qa/qa/resource/protected_branch.rb b/qa/qa/resource/protected_branch.rb
index f0cef624e0b..c27647cf3ce 100644
--- a/qa/qa/resource/protected_branch.rb
+++ b/qa/qa/resource/protected_branch.rb
@@ -3,7 +3,7 @@
module QA
module Resource
class ProtectedBranch < Base
- attr_accessor :branch_name, :allowed_to_push, :allowed_to_merge, :protected
+ attr_accessor :branch_name, :allow_to_push, :allow_to_merge, :protected
attribute :project do
Project.fabricate_via_api! do |resource|
@@ -25,12 +25,8 @@ module QA
def initialize
@branch_name = 'test/branch'
- @allowed_to_push = {
- roles: Resource::ProtectedBranch::Roles::DEVS_AND_MAINTAINERS
- }
- @allowed_to_merge = {
- roles: Resource::ProtectedBranch::Roles::DEVS_AND_MAINTAINERS
- }
+ @allow_to_push = true
+ @allow_to_merge = true
@protected = false
end
@@ -39,14 +35,29 @@ module QA
project.wait_for_push_new_branch @branch_name
+ # The upcoming process will make it access the Protected Branches page,
+ # select the already created branch and protect it according
+ # to `allow_to_push` variable.
+ return branch unless @protected
+
project.visit!
Page::Project::Menu.perform(&:go_to_repository_settings)
Page::Project::Settings::Repository.perform do |setting|
setting.expand_protected_branches do |page|
page.select_branch(branch_name)
- page.select_allowed_to_merge(allowed_to_merge)
- page.select_allowed_to_push(allowed_to_push)
+
+ if allow_to_push
+ page.allow_devs_and_maintainers_to_push
+ else
+ page.allow_no_one_to_push
+ end
+
+ if allow_to_merge
+ page.allow_devs_and_maintainers_to_merge
+ else
+ page.allow_no_one_to_merge
+ end
page.wait(reload: false) do
!page.first('.btn-success').disabled?
@@ -68,12 +79,6 @@ module QA
def api_delete_path
"/projects/#{@project.api_resource[:id]}/protected_branches/#{@branch_name}"
end
-
- class Roles
- NO_ONE = 'No one'
- DEVS_AND_MAINTAINERS = 'Developers + Maintainers'
- MAINTAINERS = 'Maintainers'
- end
end
end
end
diff --git a/qa/qa/resource/repository/project_push.rb b/qa/qa/resource/repository/project_push.rb
index f79bb035c46..c84ade3a140 100644
--- a/qa/qa/resource/repository/project_push.rb
+++ b/qa/qa/resource/repository/project_push.rb
@@ -4,12 +4,11 @@ module QA
module Resource
module Repository
class ProjectPush < Repository::Push
- attr_accessor :project_name
attr_writer :wait_for_push
attribute :project do
Project.fabricate! do |resource|
- resource.name = project_name
+ resource.name = 'project-with-code'
resource.description = 'Project with repository'
end
end
@@ -20,7 +19,6 @@ module QA
@commit_message = "This is a test commit"
@branch_name = 'master'
@new_branch = true
- @project_name = 'project-with-code'
@wait_for_push = true
end
diff --git a/qa/qa/resource/repository/wiki_push.rb b/qa/qa/resource/repository/wiki_push.rb
index 8edaff70ac6..06cca85cbb2 100644
--- a/qa/qa/resource/repository/wiki_push.rb
+++ b/qa/qa/resource/repository/wiki_push.rb
@@ -21,7 +21,14 @@ module QA
end
def repository_http_uri
- @repository_http_uri ||= wiki.repository_http_location.uri
+ @repository_http_uri ||= begin
+ wiki.visit!
+ Page::Project::Wiki::Show.act do
+ click_clone_repository
+ choose_repository_clone_http
+ repository_location.uri
+ end
+ end
end
def repository_ssh_uri
diff --git a/qa/qa/resource/wiki.rb b/qa/qa/resource/wiki.rb
index 6e3648dba0b..0a776f22e25 100644
--- a/qa/qa/resource/wiki.rb
+++ b/qa/qa/resource/wiki.rb
@@ -12,15 +12,6 @@ module QA
end
end
- attribute :repository_http_location do
- Page::Project::Wiki::Show.perform(&:click_clone_repository)
-
- Page::Project::Wiki::GitAccess.perform do |git_access|
- git_access.choose_repository_clone_http
- git_access.repository_location
- end
- end
-
def fabricate!
project.visit!
diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/push_protected_branch_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/push_protected_branch_spec.rb
index 5d0f4b215f4..dd80905d184 100644
--- a/qa/qa/specs/features/browser_ui/3_create/repository/push_protected_branch_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/repository/push_protected_branch_spec.rb
@@ -17,11 +17,16 @@ module QA
Page::Main::Login.perform(&:sign_in_using_credentials)
end
+ after do
+ # We need to clear localStorage because we're using it for the dropdown,
+ # and capybara doesn't do this for us.
+ # https://github.com/teamcapybara/capybara/issues/1702
+ Capybara.execute_script 'localStorage.clear()'
+ end
+
context 'when developers and maintainers are allowed to push to a protected branch' do
it 'user with push rights successfully pushes to the protected branch' do
- create_protected_branch(allowed_to_push: {
- roles: Resource::ProtectedBranch::Roles::DEVS_AND_MAINTAINERS
- })
+ create_protected_branch(allow_to_push: true)
push = push_new_file(branch_name)
@@ -31,19 +36,18 @@ module QA
context 'when developers and maintainers are not allowed to push to a protected branch' do
it 'user without push rights fails to push to the protected branch' do
- create_protected_branch(allowed_to_push: {
- roles: Resource::ProtectedBranch::Roles::NO_ONE
- })
+ create_protected_branch(allow_to_push: false)
expect { push_new_file(branch_name) }.to raise_error(QA::Git::Repository::RepositoryCommandError, /remote: GitLab: You are not allowed to push code to protected branches on this project\.([\s\S]+)\[remote rejected\] #{branch_name} -> #{branch_name} \(pre-receive hook declined\)/)
end
end
- def create_protected_branch(allowed_to_push:)
+ def create_protected_branch(allow_to_push:)
Resource::ProtectedBranch.fabricate! do |resource|
resource.branch_name = branch_name
resource.project = project
- resource.allowed_to_push = allowed_to_push
+ resource.allow_to_push = allow_to_push
+ resource.protected = true
end
end
diff --git a/scripts/review_apps/review-apps.sh b/scripts/review_apps/review-apps.sh
index a4fb4749720..8b64dd3292c 100755
--- a/scripts/review_apps/review-apps.sh
+++ b/scripts/review_apps/review-apps.sh
@@ -197,17 +197,17 @@ function download_chart() {
function deploy() {
local name="$CI_ENVIRONMENT_SLUG"
- local edition="${GITLAB_EDITION-ce}"
echoinfo "Deploying ${name}..." true
IMAGE_REPOSITORY="registry.gitlab.com/gitlab-org/build/cng-mirror"
- gitlab_migrations_image_repository="${IMAGE_REPOSITORY}/gitlab-rails-${edition}"
- gitlab_sidekiq_image_repository="${IMAGE_REPOSITORY}/gitlab-sidekiq-${edition}"
- gitlab_unicorn_image_repository="${IMAGE_REPOSITORY}/gitlab-unicorn-${edition}"
- gitlab_task_runner_image_repository="${IMAGE_REPOSITORY}/gitlab-task-runner-${edition}"
+ IMAGE_VERSION="${CI_PROJECT_NAME#gitlab-}"
+ gitlab_migrations_image_repository="${IMAGE_REPOSITORY}/gitlab-rails-${IMAGE_VERSION}"
+ gitlab_sidekiq_image_repository="${IMAGE_REPOSITORY}/gitlab-sidekiq-${IMAGE_VERSION}"
+ gitlab_unicorn_image_repository="${IMAGE_REPOSITORY}/gitlab-unicorn-${IMAGE_VERSION}"
+ gitlab_task_runner_image_repository="${IMAGE_REPOSITORY}/gitlab-task-runner-${IMAGE_VERSION}"
gitlab_gitaly_image_repository="${IMAGE_REPOSITORY}/gitaly"
gitlab_shell_image_repository="${IMAGE_REPOSITORY}/gitlab-shell"
- gitlab_workhorse_image_repository="${IMAGE_REPOSITORY}/gitlab-workhorse-${edition}"
+ gitlab_workhorse_image_repository="${IMAGE_REPOSITORY}/gitlab-workhorse-${IMAGE_VERSION}"
create_application_secret
diff --git a/spec/bin/changelog_spec.rb b/spec/bin/changelog_spec.rb
index ce7f7648c0c..c3a5abf2b7a 100644
--- a/spec/bin/changelog_spec.rb
+++ b/spec/bin/changelog_spec.rb
@@ -69,14 +69,6 @@ describe 'bin/changelog' do
end
end
- it 'parses --ee and -e' do
- %w[--ee -e].each do |flag|
- options = described_class.parse(%W[foo #{flag} security])
-
- expect(options.ee).to eq true
- end
- end
-
it 'parses -h' do
expect do
expect { described_class.parse(%w[foo -h bar]) }.to output.to_stdout
diff --git a/spec/controllers/admin/application_settings_controller_spec.rb b/spec/controllers/admin/application_settings_controller_spec.rb
index d62e0a97609..4eb0545eb6c 100644
--- a/spec/controllers/admin/application_settings_controller_spec.rb
+++ b/spec/controllers/admin/application_settings_controller_spec.rb
@@ -118,7 +118,32 @@ describe Admin::ApplicationSettingsController do
end
describe 'verify panel actions' do
- (Admin::ApplicationSettingsController::VALID_SETTING_PANELS - %w(templates geo)).each do |valid_action|
+ shared_examples 'renders correct panels' do
+ it 'renders correct action on error' do
+ expect_next_instance_of(ApplicationSettings::UpdateService) do |service|
+ allow(service).to receive(:execute).and_return(false)
+ end
+
+ patch action, params: { application_setting: { unused_param: true } }
+
+ expect(subject).to render_template(action)
+ end
+
+ it 'redirects to same panel on success' do
+ expect_next_instance_of(ApplicationSettings::UpdateService) do |service|
+ allow(service).to receive(:execute).and_return(true)
+ end
+
+ referer_path = public_send("#{action}_admin_application_settings_path")
+ request.env["HTTP_REFERER"] = referer_path
+
+ patch action, params: { application_setting: { unused_param: true } }
+
+ expect(subject).to redirect_to(referer_path)
+ end
+ end
+
+ (Admin::ApplicationSettingsController::VALID_SETTING_PANELS - %w(show templates geo)).each do |valid_action|
it_behaves_like 'renders correct panels' do
let(:action) { valid_action }
end
diff --git a/spec/controllers/application_controller_spec.rb b/spec/controllers/application_controller_spec.rb
index d7134d3d25a..0b3833e6515 100644
--- a/spec/controllers/application_controller_spec.rb
+++ b/spec/controllers/application_controller_spec.rb
@@ -1,3 +1,4 @@
+# coding: utf-8
# frozen_string_literal: true
require 'spec_helper'
@@ -170,40 +171,16 @@ describe ApplicationController do
end
describe '#route_not_found' do
- controller(described_class) do
- def index
- route_not_found
- end
- end
-
it 'renders 404 if authenticated' do
- sign_in(user)
-
- get :index
-
- expect(response).to have_gitlab_http_status(404)
- end
-
- it 'redirects to login page via authenticate_user! if not authenticated' do
- get :index
-
- expect(response).to redirect_to new_user_session_path
+ allow(controller).to receive(:current_user).and_return(user)
+ expect(controller).to receive(:not_found)
+ controller.send(:route_not_found)
end
- context 'request format is unknown' do
- it 'redirects if unauthenticated' do
- get :index, format: 'unknown'
-
- expect(response).to redirect_to new_user_session_path
- end
-
- it 'returns a 401 if the feature flag is disabled' do
- stub_feature_flags(devise_redirect_unknown_formats: false)
-
- get :index, format: 'unknown'
-
- expect(response).to have_gitlab_http_status(401)
- end
+ it 'does redirect to login page via authenticate_user! if not authenticated' do
+ allow(controller).to receive(:current_user).and_return(nil)
+ expect(controller).to receive(:authenticate_user!)
+ controller.send(:route_not_found)
end
end
diff --git a/spec/controllers/concerns/send_file_upload_spec.rb b/spec/controllers/concerns/send_file_upload_spec.rb
index 4110be721ad..3bf0ec799c7 100644
--- a/spec/controllers/concerns/send_file_upload_spec.rb
+++ b/spec/controllers/concerns/send_file_upload_spec.rb
@@ -1,3 +1,4 @@
+# coding: utf-8
# frozen_string_literal: true
require 'spec_helper'
diff --git a/spec/controllers/projects/jobs_controller_spec.rb b/spec/controllers/projects/jobs_controller_spec.rb
index 53d32665b0c..b455b55bd11 100644
--- a/spec/controllers/projects/jobs_controller_spec.rb
+++ b/spec/controllers/projects/jobs_controller_spec.rb
@@ -1,3 +1,4 @@
+# coding: utf-8
# frozen_string_literal: true
require 'spec_helper'
diff --git a/spec/controllers/projects/merge_requests_controller_spec.rb b/spec/controllers/projects/merge_requests_controller_spec.rb
index eda8c282341..e1f67054d0a 100644
--- a/spec/controllers/projects/merge_requests_controller_spec.rb
+++ b/spec/controllers/projects/merge_requests_controller_spec.rb
@@ -1289,7 +1289,7 @@ describe Projects::MergeRequestsController do
expect_next_instance_of(Gitlab::DiscussionsDiff::FileCollection) do |collection|
note_diff_file = commit_diff_note.note_diff_file
- expect(collection).to receive(:load_highlight).and_call_original
+ expect(collection).to receive(:load_highlight).with([note_diff_file.id]).and_call_original
expect(collection).to receive(:find_by_id).with(note_diff_file.id).and_call_original
end
@@ -1306,7 +1306,7 @@ describe Projects::MergeRequestsController do
expect_next_instance_of(Gitlab::DiscussionsDiff::FileCollection) do |collection|
note_diff_file = diff_note.note_diff_file
- expect(collection).to receive(:load_highlight).and_call_original
+ expect(collection).to receive(:load_highlight).with([note_diff_file.id]).and_call_original
expect(collection).to receive(:find_by_id).with(note_diff_file.id).and_call_original
end
@@ -1319,7 +1319,7 @@ describe Projects::MergeRequestsController do
expect_next_instance_of(Gitlab::DiscussionsDiff::FileCollection) do |collection|
note_diff_file = diff_note.note_diff_file
- expect(collection).to receive(:load_highlight).and_call_original
+ expect(collection).to receive(:load_highlight).with([]).and_call_original
expect(collection).to receive(:find_by_id).with(note_diff_file.id).and_call_original
end
diff --git a/spec/factories/services.rb b/spec/factories/services.rb
index c4cb3f07fe7..b2d6ada91fa 100644
--- a/spec/factories/services.rb
+++ b/spec/factories/services.rb
@@ -9,7 +9,11 @@ FactoryBot.define do
factory :custom_issue_tracker_service, class: CustomIssueTrackerService do
project
active true
- issue_tracker
+ properties(
+ project_url: 'https://project.url.com',
+ issues_url: 'https://issues.url.com',
+ new_issue_url: 'https://newissue.url.com'
+ )
end
factory :emails_on_push_service do
@@ -43,24 +47,12 @@ FactoryBot.define do
factory :jira_service do
project
active true
-
- transient do
- create_data true
- url 'https://jira.example.com'
- api_url nil
- username 'jira_username'
- password 'jira_password'
- jira_issue_transition_id '56-1'
- end
-
- after(:build) do |service, evaluator|
- if evaluator.create_data
- create(:jira_tracker_data, service: service,
- url: evaluator.url, api_url: evaluator.api_url, jira_issue_transition_id: evaluator.jira_issue_transition_id,
- username: evaluator.username, password: evaluator.password
- )
- end
- end
+ properties(
+ url: 'https://jira.example.com',
+ username: 'jira_user',
+ password: 'my-secret-password',
+ project_key: 'jira-key'
+ )
end
factory :bugzilla_service do
@@ -88,26 +80,20 @@ FactoryBot.define do
end
trait :issue_tracker do
- transient do
- create_data true
- project_url 'http://issuetracker.example.com'
- issues_url 'http://issues.example.com/issues/:id'
- new_issue_url 'http://new-issue.example.com'
- end
-
- after(:build) do |service, evaluator|
- if evaluator.create_data
- create(:issue_tracker_data, service: service,
- project_url: evaluator.project_url, issues_url: evaluator.issues_url, new_issue_url: evaluator.new_issue_url
- )
- end
- end
+ properties(
+ project_url: 'http://issue-tracker.example.com',
+ issues_url: 'http://issue-tracker.example.com/issues/:id',
+ new_issue_url: 'http://issue-tracker.example.com'
+ )
end
trait :jira_cloud_service do
- url 'https://mysite.atlassian.net'
- username 'jira_user'
- password 'my-secret-password'
+ properties(
+ url: 'https://mysite.atlassian.net',
+ username: 'jira_user',
+ password: 'my-secret-password',
+ project_key: 'jira-key'
+ )
end
factory :hipchat_service do
@@ -116,21 +102,15 @@ FactoryBot.define do
token 'test_token'
end
- # this is for testing storing values inside properties, which is deprecated and will be removed in
- # https://gitlab.com/gitlab-org/gitlab-ce/issues/63084
trait :without_properties_callback do
- jira_tracker_data nil
- issue_tracker_data nil
- create_data false
-
after(:build) do |service|
- IssueTrackerService.skip_callback(:validation, :before, :handle_properties)
+ allow(service).to receive(:handle_properties)
end
- to_create { |instance| instance.save(validate: false)}
-
- after(:create) do
- IssueTrackerService.set_callback(:validation, :before, :handle_properties)
+ after(:create) do |service|
+ # we have to remove the stub because the behaviour of
+ # handle_properties method is tested after the creation
+ allow(service).to receive(:handle_properties).and_call_original
end
end
end
diff --git a/spec/features/admin/admin_disables_git_access_protocol_spec.rb b/spec/features/admin/admin_disables_git_access_protocol_spec.rb
index bc757d72a49..4c3c0904a06 100644
--- a/spec/features/admin/admin_disables_git_access_protocol_spec.rb
+++ b/spec/features/admin/admin_disables_git_access_protocol_spec.rb
@@ -76,7 +76,6 @@ describe 'Admin disables Git access protocol', :js do
context 'with nothing disabled' do
before do
create(:personal_key, user: admin)
- allow_all_protocols
end
it 'shows default SSH url and protocol selection dropdown' do
@@ -108,10 +107,6 @@ describe 'Admin disables Git access protocol', :js do
visit project_path(project)
end
- def allow_all_protocols
- switch_git_protocol(1)
- end
-
def disable_http_protocol
switch_git_protocol(2)
end
diff --git a/spec/features/admin/admin_settings_spec.rb b/spec/features/admin/admin_settings_spec.rb
index ab58d9fb9d5..be34315118d 100644
--- a/spec/features/admin/admin_settings_spec.rb
+++ b/spec/features/admin/admin_settings_spec.rb
@@ -15,7 +15,7 @@ describe 'Admin updates settings' do
context 'General page' do
before do
- visit general_admin_application_settings_path
+ visit admin_application_settings_path
end
it 'Change visibility settings' do
diff --git a/spec/finders/issues_finder_spec.rb b/spec/finders/issues_finder_spec.rb
index a17ff1ad50d..ef8749be0be 100644
--- a/spec/finders/issues_finder_spec.rb
+++ b/spec/finders/issues_finder_spec.rb
@@ -21,28 +21,15 @@ describe IssuesFinder do
let(:expected_issuables) { [issue1, issue2] }
end
- it_behaves_like 'assignee NOT ID filter' do
- let(:params) { { not: { assignee_id: user.id } } }
- let(:expected_issuables) { [issue3, issue4] }
- end
-
- context 'filter by username' do
- set(:user3) { create(:user) }
-
+ it_behaves_like 'assignee username filter' do
before do
project2.add_developer(user3)
issue3.assignees = [user2, user3]
end
- it_behaves_like 'assignee username filter' do
- let(:params) { { assignee_username: [user2.username, user3.username] } }
- let(:expected_issuables) { [issue3] }
- end
-
- it_behaves_like 'assignee NOT username filter' do
- let(:params) { { not: { assignee_username: [user2.username, user3.username] } } }
- let(:expected_issuables) { [issue1, issue2, issue4] }
- end
+ set(:user3) { create(:user) }
+ let(:params) { { assignee_username: [user2.username, user3.username] } }
+ let(:expected_issuables) { [issue3] }
end
it_behaves_like 'no assignee filter' do
@@ -125,26 +112,6 @@ describe IssuesFinder do
end
end
- context 'filtering by NOT group_id' do
- let(:params) { { not: { group_id: group.id } } }
-
- context 'when include_subgroup param not set' do
- it 'returns all other group issues' do
- expect(issues).to contain_exactly(issue2, issue3, issue4)
- end
- end
-
- context 'when include_subgroup param is true', :nested_groups do
- before do
- params[:include_subgroups] = true
- end
-
- it 'returns all other group and subgroup issues' do
- expect(issues).to contain_exactly(issue2, issue3)
- end
- end
- end
-
context 'filtering by author ID' do
let(:params) { { author_id: user2.id } }
@@ -153,14 +120,6 @@ describe IssuesFinder do
end
end
- context 'filtering by not author ID' do
- let(:params) { { not: { author_id: user2.id } } }
-
- it 'returns issues not created by that user' do
- expect(issues).to contain_exactly(issue1, issue2, issue4)
- end
- end
-
context 'filtering by milestone' do
let(:params) { { milestone_title: milestone.title } }
@@ -169,14 +128,6 @@ describe IssuesFinder do
end
end
- context 'filtering by not milestone' do
- let(:params) { { not: { milestone_title: milestone.title } } }
-
- it 'returns issues not assigned to that milestone' do
- expect(issues).to contain_exactly(issue2, issue3, issue4)
- end
- end
-
context 'filtering by group milestone' do
let!(:group) { create(:group, :public) }
let(:group_milestone) { create(:milestone, group: group) }
@@ -192,14 +143,6 @@ describe IssuesFinder do
it 'returns issues assigned to that group milestone' do
expect(issues).to contain_exactly(issue2, issue3)
end
-
- context 'using NOT' do
- let(:params) { { not: { milestone_title: group_milestone.title } } }
-
- it 'returns issues not assigned to that group milestone' do
- expect(issues).to contain_exactly(issue1, issue4)
- end
- end
end
context 'filtering by no milestone' do
@@ -241,10 +184,10 @@ describe IssuesFinder do
let(:project_next_8_8) { create(:project, :public) }
let(:project_in_group) { create(:project, :public, namespace: group) }
- let(:yesterday) { Date.current - 1.day }
- let(:tomorrow) { Date.current + 1.day }
- let(:two_days_from_now) { Date.current + 2.days }
- let(:ten_days_from_now) { Date.current + 10.days }
+ let(:yesterday) { Date.today - 1.day }
+ let(:tomorrow) { Date.today + 1.day }
+ let(:two_days_from_now) { Date.today + 2.days }
+ let(:ten_days_from_now) { Date.today + 10.days }
let(:milestones) do
[
@@ -258,7 +201,7 @@ describe IssuesFinder do
end
before do
- @created_issues = milestones.map do |milestone|
+ milestones.each do |milestone|
create(:issue, project: milestone.project || project_in_group, milestone: milestone, author: user, assignees: [user])
end
end
@@ -267,18 +210,6 @@ describe IssuesFinder do
expect(issues.map { |issue| issue.milestone.title }).to contain_exactly('1.1', '8.8', '9.9')
expect(issues.map { |issue| issue.milestone.due_date }).to contain_exactly(tomorrow, two_days_from_now, tomorrow)
end
-
- context 'using NOT' do
- let(:params) { { not: { milestone_title: Milestone::Upcoming.name } } }
-
- it 'returns issues not in upcoming milestones for each project or group' do
- target_issues = @created_issues.reject do |issue|
- issue.milestone&.due_date && issue.milestone.due_date > Date.current
- end + @created_issues.select { |issue| issue.milestone&.title == '8.9' }
-
- expect(issues).to contain_exactly(issue1, issue2, issue3, issue4, *target_issues)
- end
- end
end
context 'filtering by started milestone' do
@@ -288,10 +219,10 @@ describe IssuesFinder do
let(:project_started_1_and_2) { create(:project, :public) }
let(:project_started_8) { create(:project, :public) }
- let(:yesterday) { Date.current - 1.day }
- let(:tomorrow) { Date.current + 1.day }
- let(:two_days_ago) { Date.current - 2.days }
- let(:three_days_ago) { Date.current - 3.days }
+ let(:yesterday) { Date.today - 1.day }
+ let(:tomorrow) { Date.today + 1.day }
+ let(:two_days_ago) { Date.today - 2.days }
+ let(:three_days_ago) { Date.today - 3.days }
let(:milestones) do
[
@@ -317,16 +248,6 @@ describe IssuesFinder do
expect(issues.map { |issue| issue.milestone.title }).to contain_exactly('1.0', '2.0', '8.0')
expect(issues.map { |issue| issue.milestone.start_date }).to contain_exactly(two_days_ago, yesterday, yesterday)
end
-
- context 'using NOT' do
- let(:params) { { not: { milestone_title: Milestone::Started.name } } }
-
- it 'returns issues not in the started milestones for each project' do
- target_issues = Issue.where.not(milestone: Milestone.started)
-
- expect(issues).to contain_exactly(issue2, issue3, issue4, *target_issues)
- end
- end
end
context 'filtering by label' do
@@ -335,33 +256,6 @@ describe IssuesFinder do
it 'returns issues with that label' do
expect(issues).to contain_exactly(issue2)
end
-
- context 'using NOT' do
- let(:params) { { not: { label_name: label.title } } }
-
- it 'returns issues that do not have that label' do
- expect(issues).to contain_exactly(issue1, issue3, issue4)
- end
-
- # IssuableFinder first filters using the outer params (the ones not inside the `not` key.)
- # Afterwards, it applies the `not` params to that resultset. This means that things inside the `not` param
- # do not take precedence over the outer params with the same name.
- context 'shadowing the same outside param' do
- let(:params) { { label_name: label2.title, not: { label_name: label.title } } }
-
- it 'does not take precedence over labels outside NOT' do
- expect(issues).to contain_exactly(issue3)
- end
- end
-
- context 'further filtering outside params' do
- let(:params) { { label_name: label2.title, not: { assignee_username: user2.username } } }
-
- it 'further filters on the returned resultset' do
- expect(issues).to be_empty
- end
- end
- end
end
context 'filtering by multiple labels' do
@@ -375,14 +269,6 @@ describe IssuesFinder do
it 'returns the unique issues with all those labels' do
expect(issues).to contain_exactly(issue2)
end
-
- context 'using NOT' do
- let(:params) { { not: { label_name: [label.title, label2.title].join(',') } } }
-
- it 'returns issues that do not have ALL labels provided' do
- expect(issues).to contain_exactly(issue1, issue3, issue4)
- end
- end
end
context 'filtering by a label that includes any or none in the title' do
@@ -390,28 +276,18 @@ describe IssuesFinder do
let(:label) { create(:label, title: 'any foo', project: project2) }
let(:label2) { create(:label, title: 'bar none', project: project2) }
- before do
+ it 'returns the unique issues with all those labels' do
create(:label_link, label: label2, target: issue2)
- end
- it 'returns the unique issues with all those labels' do
expect(issues).to contain_exactly(issue2)
end
-
- context 'using NOT' do
- let(:params) { { not: { label_name: [label.title, label2.title].join(',') } } }
-
- it 'returns issues that do not have ALL labels provided' do
- expect(issues).to contain_exactly(issue1, issue3, issue4)
- end
- end
end
context 'filtering by no label' do
let(:params) { { label_name: described_class::FILTER_NONE } }
it 'returns issues with no labels' do
- expect(issues).to contain_exactly(issue1, issue4)
+ expect(issues).to contain_exactly(issue1, issue3, issue4)
end
end
@@ -433,14 +309,6 @@ describe IssuesFinder do
it 'returns issues with title and description match for search term' do
expect(issues).to contain_exactly(issue1, issue2)
end
-
- context 'using NOT' do
- let(:params) { { not: { search: 'git' } } }
-
- it 'returns issues with no title and description match for search term' do
- expect(issues).to contain_exactly(issue3, issue4)
- end
- end
end
context 'filtering by issue term in title' do
@@ -449,14 +317,6 @@ describe IssuesFinder do
it 'returns issues with title match for search term' do
expect(issues).to contain_exactly(issue1)
end
-
- context 'using NOT' do
- let(:params) { { not: { search: 'git', in: 'title' } } }
-
- it 'returns issues with no title match for search term' do
- expect(issues).to contain_exactly(issue2, issue3, issue4)
- end
- end
end
context 'filtering by issues iids' do
@@ -465,14 +325,6 @@ describe IssuesFinder do
it 'returns issues with iids match' do
expect(issues).to contain_exactly(issue3)
end
-
- context 'using NOT' do
- let(:params) { { not: { iids: issue3.iid } } }
-
- it 'returns issues with no iids match' do
- expect(issues).to contain_exactly(issue1, issue2, issue4)
- end
- end
end
context 'filtering by state' do
@@ -614,14 +466,6 @@ describe IssuesFinder do
it 'returns issues that the user thumbsup to' do
expect(issues).to contain_exactly(issue1)
end
-
- context 'using NOT' do
- let(:params) { { not: { my_reaction_emoji: 'thumbsup' } } }
-
- it 'returns issues that the user did not thumbsup to' do
- expect(issues).to contain_exactly(issue2, issue3, issue4)
- end
- end
end
context 'user2 searches by "thumbsup" reaction' do
@@ -632,14 +476,6 @@ describe IssuesFinder do
it 'returns issues that the user2 thumbsup to' do
expect(issues).to contain_exactly(issue2)
end
-
- context 'using NOT' do
- let(:params) { { not: { my_reaction_emoji: 'thumbsup' } } }
-
- it 'returns issues that the user2 thumbsup to' do
- expect(issues).to contain_exactly(issue3)
- end
- end
end
context 'user searches by "thumbsdown" reaction' do
@@ -648,14 +484,6 @@ describe IssuesFinder do
it 'returns issues that the user thumbsdown to' do
expect(issues).to contain_exactly(issue3)
end
-
- context 'using NOT' do
- let(:params) { { not: { my_reaction_emoji: 'thumbsdown' } } }
-
- it 'returns issues that the user thumbsdown to' do
- expect(issues).to contain_exactly(issue1, issue2, issue4)
- end
- end
end
end
diff --git a/spec/fixtures/api/schemas/public_api/v4/release.json b/spec/fixtures/api/schemas/public_api/v4/release.json
index 662e61a9c06..078b1c0b982 100644
--- a/spec/fixtures/api/schemas/public_api/v4/release.json
+++ b/spec/fixtures/api/schemas/public_api/v4/release.json
@@ -15,10 +15,7 @@
"author": {
"oneOf": [{ "type": "null" }, { "$ref": "user/basic.json" }]
},
- "milestones": {
- "type": "array",
- "items": { "$ref": "milestone.json" }
- },
+ "milestone": { "type": "string" },
"assets": {
"required": ["count", "links", "sources"],
"properties": {
diff --git a/spec/frontend/clusters/clusters_bundle_spec.js b/spec/frontend/clusters/clusters_bundle_spec.js
index 80816faa5fc..517d8781600 100644
--- a/spec/frontend/clusters/clusters_bundle_spec.js
+++ b/spec/frontend/clusters/clusters_bundle_spec.js
@@ -11,6 +11,8 @@ import { loadHTMLFixture } from 'helpers/fixtures';
import { setTestTimeout } from 'helpers/timeout';
import $ from 'jquery';
+jest.mock('~/lib/utils/poll');
+
const { INSTALLING, INSTALLABLE, INSTALLED, UNINSTALLING } = APPLICATION_STATUS;
describe('Clusters', () => {
@@ -44,6 +46,17 @@ describe('Clusters', () => {
mock.restore();
});
+ describe('class constructor', () => {
+ beforeEach(() => {
+ jest.spyOn(Clusters.prototype, 'initPolling');
+ cluster = new Clusters();
+ });
+
+ it('should call initPolling on construct', () => {
+ expect(cluster.initPolling).toHaveBeenCalled();
+ });
+ });
+
describe('toggle', () => {
it('should update the button and the input field on click', done => {
const toggleButton = document.querySelector(
@@ -327,14 +340,31 @@ describe('Clusters', () => {
});
});
- describe('handleSuccess', () => {
+ describe('fetch cluster environments success', () => {
+ beforeEach(() => {
+ jest.spyOn(cluster.store, 'toggleFetchEnvironments').mockReturnThis();
+ jest.spyOn(cluster.store, 'updateEnvironments').mockReturnThis();
+
+ cluster.handleClusterEnvironmentsSuccess({ data: {} });
+ });
+
+ it('toggles the cluster environments loading icon', () => {
+ expect(cluster.store.toggleFetchEnvironments).toHaveBeenCalled();
+ });
+
+ it('updates the store when cluster environments is retrieved', () => {
+ expect(cluster.store.updateEnvironments).toHaveBeenCalled();
+ });
+ });
+
+ describe('handleClusterStatusSuccess', () => {
beforeEach(() => {
jest.spyOn(cluster.store, 'updateStateFromServer').mockReturnThis();
jest.spyOn(cluster, 'toggleIngressDomainHelpText').mockReturnThis();
jest.spyOn(cluster, 'checkForNewInstalls').mockReturnThis();
jest.spyOn(cluster, 'updateContainer').mockReturnThis();
- cluster.handleSuccess({ data: {} });
+ cluster.handleClusterStatusSuccess({ data: {} });
});
it('updates clusters store', () => {
diff --git a/spec/frontend/create_cluster/eks_cluster/components/cluster_form_dropdown_spec.js b/spec/frontend/create_cluster/eks_cluster/components/cluster_form_dropdown_spec.js
deleted file mode 100644
index e873ef0b2fa..00000000000
--- a/spec/frontend/create_cluster/eks_cluster/components/cluster_form_dropdown_spec.js
+++ /dev/null
@@ -1,137 +0,0 @@
-import { shallowMount } from '@vue/test-utils';
-
-import ClusterFormDropdown from '~/create_cluster/eks_cluster/components/cluster_form_dropdown.vue';
-import DropdownButton from '~/vue_shared/components/dropdown/dropdown_button.vue';
-import DropdownSearchInput from '~/vue_shared/components/dropdown/dropdown_search_input.vue';
-import DropdownHiddenInput from '~/vue_shared/components/dropdown/dropdown_hidden_input.vue';
-
-describe('ClusterFormDropdown', () => {
- let vm;
-
- beforeEach(() => {
- vm = shallowMount(ClusterFormDropdown);
- });
- afterEach(() => vm.destroy());
-
- describe('when no item is selected', () => {
- it('displays placeholder text', () => {
- const placeholder = 'placeholder';
-
- vm.setProps({ placeholder });
-
- expect(vm.find(DropdownButton).props('toggleText')).toEqual(placeholder);
- });
- });
-
- describe('when an item is selected', () => {
- const selectedItem = { name: 'Name', value: 'value' };
-
- beforeEach(() => {
- vm.setData({ selectedItem });
- });
-
- it('displays selected item label', () => {
- expect(vm.find(DropdownButton).props('toggleText')).toEqual(selectedItem.name);
- });
-
- it('sets selected value to dropdown hidden input', () => {
- expect(vm.find(DropdownHiddenInput).props('value')).toEqual(selectedItem.value);
- });
- });
-
- describe('when an item is selected and has a custom label property', () => {
- it('displays selected item custom label', () => {
- const labelProperty = 'customLabel';
- const selectedItem = { [labelProperty]: 'Name' };
-
- vm.setProps({ labelProperty });
- vm.setData({ selectedItem });
-
- expect(vm.find(DropdownButton).props('toggleText')).toEqual(selectedItem[labelProperty]);
- });
- });
-
- describe('when loading', () => {
- it('dropdown button isLoading', () => {
- vm.setProps({ loading: true });
-
- expect(vm.find(DropdownButton).props('isLoading')).toBe(true);
- });
- });
-
- describe('when loading and loadingText is provided', () => {
- it('uses loading text as toggle button text', () => {
- const loadingText = 'loading text';
-
- vm.setProps({ loading: true, loadingText });
-
- expect(vm.find(DropdownButton).props('toggleText')).toEqual(loadingText);
- });
- });
-
- describe('when disabled', () => {
- it('dropdown button isDisabled', () => {
- vm.setProps({ disabled: true });
-
- expect(vm.find(DropdownButton).props('isDisabled')).toBe(true);
- });
- });
-
- describe('when disabled and disabledText is provided', () => {
- it('uses disabled text as toggle button text', () => {
- const disabledText = 'disabled text';
-
- vm.setProps({ disabled: true, disabledText });
-
- expect(vm.find(DropdownButton).props('toggleText')).toBe(disabledText);
- });
- });
-
- describe('when has errors', () => {
- it('sets border-danger class selector to dropdown toggle', () => {
- vm.setProps({ hasErrors: true });
-
- expect(vm.find(DropdownButton).classes('border-danger')).toBe(true);
- });
- });
-
- describe('when has errors and an error message', () => {
- it('displays error message', () => {
- const errorMessage = 'error message';
-
- vm.setProps({ hasErrors: true, errorMessage });
-
- expect(vm.find('.js-eks-dropdown-error-message').text()).toEqual(errorMessage);
- });
- });
-
- describe('when no results are available', () => {
- it('displays empty text', () => {
- const emptyText = 'error message';
-
- vm.setProps({ items: [], emptyText });
-
- expect(vm.find('.js-empty-text').text()).toEqual(emptyText);
- });
- });
-
- it('displays search field placeholder', () => {
- const searchFieldPlaceholder = 'Placeholder';
-
- vm.setProps({ searchFieldPlaceholder });
-
- expect(vm.find(DropdownSearchInput).props('placeholderText')).toEqual(searchFieldPlaceholder);
- });
-
- it('it filters results by search query', () => {
- const secondItem = { name: 'second item' };
- const items = [{ name: 'first item' }, secondItem];
- const searchQuery = 'second';
-
- vm.setProps({ items });
- vm.setData({ searchQuery });
-
- expect(vm.findAll('.js-dropdown-item').length).toEqual(1);
- expect(vm.find('.js-dropdown-item').text()).toEqual(secondItem.name);
- });
-});
diff --git a/spec/frontend/create_cluster/eks_cluster/components/role_name_dropdown_spec.js b/spec/frontend/create_cluster/eks_cluster/components/role_name_dropdown_spec.js
deleted file mode 100644
index 657637c1b56..00000000000
--- a/spec/frontend/create_cluster/eks_cluster/components/role_name_dropdown_spec.js
+++ /dev/null
@@ -1,43 +0,0 @@
-import { shallowMount } from '@vue/test-utils';
-
-import ClusterFormDropdown from '~/create_cluster/eks_cluster/components/cluster_form_dropdown.vue';
-import RoleNameDropdown from '~/create_cluster/eks_cluster/components/role_name_dropdown.vue';
-
-describe('RoleNameDropdown', () => {
- let vm;
-
- beforeEach(() => {
- vm = shallowMount(RoleNameDropdown);
- });
- afterEach(() => vm.destroy());
-
- it('renders a cluster-form-dropdown', () => {
- expect(vm.find(ClusterFormDropdown).exists()).toBe(true);
- });
-
- it('sets roles to cluster-form-dropdown items property', () => {
- const roles = [{ name: 'basic' }];
-
- vm.setProps({ roles });
-
- expect(vm.find(ClusterFormDropdown).props('items')).toEqual(roles);
- });
-
- it('sets a loading text', () => {
- expect(vm.find(ClusterFormDropdown).props('loadingText')).toEqual('Loading IAM Roles');
- });
-
- it('sets a placeholder', () => {
- expect(vm.find(ClusterFormDropdown).props('placeholder')).toEqual('Select role name');
- });
-
- it('sets an empty results text', () => {
- expect(vm.find(ClusterFormDropdown).props('emptyText')).toEqual('No IAM Roles found');
- });
-
- it('sets a search field placeholder', () => {
- expect(vm.find(ClusterFormDropdown).props('searchFieldPlaceholder')).toEqual(
- 'Search IAM Roles',
- );
- });
-});
diff --git a/spec/frontend/fixtures/application_settings.rb b/spec/frontend/fixtures/application_settings.rb
index afe5949ed3b..38a060580c1 100644
--- a/spec/frontend/fixtures/application_settings.rb
+++ b/spec/frontend/fixtures/application_settings.rb
@@ -26,7 +26,7 @@ describe Admin::ApplicationSettingsController, '(JavaScript fixtures)', type: :c
it 'application_settings/accounts_and_limit.html' do
stub_application_setting(user_default_external: false)
- get :general
+ get :show
expect(response).to be_successful
end
diff --git a/spec/frontend/jobs/store/utils_spec.js b/spec/frontend/jobs/store/utils_spec.js
index 7b484ccfa07..1b96f95b5a5 100644
--- a/spec/frontend/jobs/store/utils_spec.js
+++ b/spec/frontend/jobs/store/utils_spec.js
@@ -28,12 +28,6 @@ describe('Jobs Store Utils', () => {
content: [{ text: 'Pulling docker image postgres:9.6.14 ...', style: 'term-fg-l-green' }],
sections: ['prepare-executor'],
},
- {
- offset: 1005,
- content: [],
- sections: ['prepare-executor'],
- section_duration: '10:00',
- },
];
let result;
@@ -64,16 +58,6 @@ describe('Jobs Store Utils', () => {
expect(result[1].lines[1].content).toEqual(mockData[3].content);
});
});
-
- describe('section duration', () => {
- it('adds the section information to the header section', () => {
- expect(result[1].section_duration).toEqual(mockData[4].section_duration);
- });
-
- it('does not add section duration as a line', () => {
- expect(result[1].lines.includes(mockData[4])).toEqual(false);
- });
- });
});
describe('updateIncrementalTrace', () => {
diff --git a/spec/frontend/notes/components/discussion_actions_spec.js b/spec/frontend/notes/components/discussion_actions_spec.js
index f582729d773..d3c8cf72376 100644
--- a/spec/frontend/notes/components/discussion_actions_spec.js
+++ b/spec/frontend/notes/components/discussion_actions_spec.js
@@ -7,6 +7,18 @@ import ResolveDiscussionButton from '~/notes/components/discussion_resolve_butto
import ResolveWithIssueButton from '~/notes/components/discussion_resolve_with_issue_button.vue';
import JumpToNextDiscussionButton from '~/notes/components/discussion_jump_to_next_button.vue';
+// NOTE: clone mock_data so that it is not accidentally mutated
+const createDiscussionMock = (props = {}) =>
+ Object.assign(JSON.parse(JSON.stringify(discussionMock)), props);
+const createNoteMock = (props = {}) =>
+ Object.assign(JSON.parse(JSON.stringify(discussionMock.notes[0])), props);
+const createResolvableNote = () =>
+ createNoteMock({ resolvable: true, current_user: { can_resolve: true } });
+const createUnresolvableNote = () =>
+ createNoteMock({ resolvable: false, current_user: { can_resolve: false } });
+const createUnallowedNote = () =>
+ createNoteMock({ resolvable: true, current_user: { can_resolve: false } });
+
describe('DiscussionActions', () => {
let wrapper;
const createComponentFactory = (shallow = true) => props => {
@@ -66,13 +78,23 @@ describe('DiscussionActions', () => {
expect(wrapper.find(JumpToNextDiscussionButton).exists()).toBe(false);
});
- it('does not renders discussion button for non-member', () => {
- const discussion = JSON.parse(JSON.stringify(discussionMock));
- discussion.notes[1].current_user.can_resolve = false;
- createComponent({ discussion });
-
- expect(wrapper.find(ResolveDiscussionButton).exists()).toBe(false);
- expect(wrapper.find(ResolveWithIssueButton).exists()).toBe(false);
+ describe.each`
+ desc | notes | shouldRender
+ ${'with no notes'} | ${[]} | ${true}
+ ${'with resolvable notes'} | ${[createResolvableNote(), createResolvableNote()]} | ${true}
+ ${'with unresolvable notes'} | ${[createResolvableNote(), createUnresolvableNote()]} | ${true}
+ ${'with unallowed note'} | ${[createResolvableNote(), createUnallowedNote()]} | ${false}
+ `('$desc', ({ notes, shouldRender }) => {
+ beforeEach(() => {
+ createComponent({
+ discussion: createDiscussionMock({ notes }),
+ });
+ });
+
+ it(shouldRender ? 'renders resolve buttons' : 'does not render resolve buttons', () => {
+ expect(wrapper.find(ResolveDiscussionButton).exists()).toBe(shouldRender);
+ expect(wrapper.find(ResolveWithIssueButton).exists()).toBe(shouldRender);
+ });
});
});
diff --git a/spec/helpers/application_helper_spec.rb b/spec/helpers/application_helper_spec.rb
index 2f481e237a7..4a3ff7e0095 100644
--- a/spec/helpers/application_helper_spec.rb
+++ b/spec/helpers/application_helper_spec.rb
@@ -1,3 +1,4 @@
+# coding: utf-8
require 'spec_helper'
describe ApplicationHelper do
diff --git a/spec/helpers/defer_script_tag_helper_spec.rb b/spec/helpers/defer_script_tag_helper_spec.rb
index 9ada3ae75ba..d10b6f134e4 100644
--- a/spec/helpers/defer_script_tag_helper_spec.rb
+++ b/spec/helpers/defer_script_tag_helper_spec.rb
@@ -1,3 +1,4 @@
+# coding: utf-8
require 'spec_helper'
describe DeferScriptTagHelper do
diff --git a/spec/javascripts/boards/boards_store_spec.js b/spec/javascripts/boards/boards_store_spec.js
index 11352140ba4..36bd7ada4f0 100644
--- a/spec/javascripts/boards/boards_store_spec.js
+++ b/spec/javascripts/boards/boards_store_spec.js
@@ -1,5 +1,7 @@
+/* eslint-disable no-unused-vars */
/* global ListIssue */
+import Vue from 'vue';
import MockAdapter from 'axios-mock-adapter';
import axios from '~/lib/utils/axios_utils';
import Cookies from 'js-cookie';
@@ -188,7 +190,7 @@ describe('Store', () => {
it('moves the position of lists', () => {
const listOne = boardsStore.addList(listObj);
- boardsStore.addList(listObjDuplicate);
+ const listTwo = boardsStore.addList(listObjDuplicate);
expect(boardsStore.state.lists.length).toBe(2);
diff --git a/spec/javascripts/jobs/components/log/duration_badge_spec.js b/spec/javascripts/jobs/components/log/duration_badge_spec.js
deleted file mode 100644
index 2ac34e78909..00000000000
--- a/spec/javascripts/jobs/components/log/duration_badge_spec.js
+++ /dev/null
@@ -1,31 +0,0 @@
-import { shallowMount } from '@vue/test-utils';
-import DurationBadge from '~/jobs/components/log/duration_badge.vue';
-
-describe('Job Log Duration Badge', () => {
- let wrapper;
-
- const data = {
- duration: '00:30:01',
- };
-
- const createComponent = (props = {}) => {
- wrapper = shallowMount(DurationBadge, {
- sync: false,
- propsData: {
- ...props,
- },
- });
- };
-
- beforeEach(() => {
- createComponent(data);
- });
-
- afterEach(() => {
- wrapper.destroy();
- });
-
- it('renders provided duration', () => {
- expect(wrapper.text()).toBe(data.duration);
- });
-});
diff --git a/spec/javascripts/jobs/components/log/line_header_spec.js b/spec/javascripts/jobs/components/log/line_header_spec.js
index 2d2f92fad9d..4efd412a6cd 100644
--- a/spec/javascripts/jobs/components/log/line_header_spec.js
+++ b/spec/javascripts/jobs/components/log/line_header_spec.js
@@ -1,7 +1,6 @@
import { mount } from '@vue/test-utils';
import LineHeader from '~/jobs/components/log/line_header.vue';
import LineNumber from '~/jobs/components/log/line_number.vue';
-import DurationBadge from '~/jobs/components/log/duration_badge.vue';
describe('Job Log Header Line', () => {
let wrapper;
@@ -82,14 +81,4 @@ describe('Job Log Header Line', () => {
expect(wrapper.emitted().toggleLine.length).toBe(1);
});
});
-
- describe('with duration', () => {
- beforeEach(() => {
- createComponent(Object.assign({}, data, { duration: '00:10' }));
- });
-
- it('renders the duration badge', () => {
- expect(wrapper.contains(DurationBadge)).toBe(true);
- });
- });
});
diff --git a/spec/javascripts/test_bundle.js b/spec/javascripts/test_bundle.js
index c0a999cfaa6..ce453d7c483 100644
--- a/spec/javascripts/test_bundle.js
+++ b/spec/javascripts/test_bundle.js
@@ -210,7 +210,7 @@ if (process.env.BABEL_ENV === 'coverage') {
'./terminal/terminal_bundle.js',
'./users/users_bundle.js',
'./issue_show/index.js',
- './pages/admin/application_settings/general/index.js',
+ './pages/admin/application_settings/show/index.js',
];
describe('Uncovered files', function() {
diff --git a/spec/lib/banzai/pipeline/gfm_pipeline_spec.rb b/spec/lib/banzai/pipeline/gfm_pipeline_spec.rb
index 47ea273ef3a..7eb63fea413 100644
--- a/spec/lib/banzai/pipeline/gfm_pipeline_spec.rb
+++ b/spec/lib/banzai/pipeline/gfm_pipeline_spec.rb
@@ -34,7 +34,7 @@ describe Banzai::Pipeline::GfmPipeline do
result = described_class.call(markdown, project: project)[:output]
link = result.css('a').first
- expect(link['href']).to eq 'http://issues.example.com/issues/12'
+ expect(link['href']).to eq 'http://issue-tracker.example.com/issues/12'
end
it 'parses cross-project references to regular issues' do
@@ -63,7 +63,7 @@ describe Banzai::Pipeline::GfmPipeline do
result = described_class.call(markdown, project: project)[:output]
link = result.css('a').first
- expect(link['href']).to eq 'http://issues.example.com/issues/12'
+ expect(link['href']).to eq 'http://issue-tracker.example.com/issues/12'
end
it 'allows to use long external reference syntax for Redmine' do
@@ -72,7 +72,7 @@ describe Banzai::Pipeline::GfmPipeline do
result = described_class.call(markdown, project: project)[:output]
link = result.css('a').first
- expect(link['href']).to eq 'http://issues.example.com/issues/12'
+ expect(link['href']).to eq 'http://issue-tracker.example.com/issues/12'
end
it 'parses cross-project references to regular issues' do
diff --git a/spec/lib/container_registry/client_spec.rb b/spec/lib/container_registry/client_spec.rb
index 6c2b338bfcd..bc5fddd12ba 100644
--- a/spec/lib/container_registry/client_spec.rb
+++ b/spec/lib/container_registry/client_spec.rb
@@ -1,3 +1,4 @@
+# coding: utf-8
# frozen_string_literal: true
require 'spec_helper'
diff --git a/spec/lib/gitlab/background_migration/add_gitlab_instance_administration_project_spec.rb b/spec/lib/gitlab/background_migration/add_gitlab_instance_administration_project_spec.rb
deleted file mode 100644
index 76062b191a8..00000000000
--- a/spec/lib/gitlab/background_migration/add_gitlab_instance_administration_project_spec.rb
+++ /dev/null
@@ -1,234 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-describe Gitlab::BackgroundMigration::AddGitlabInstanceAdministrationProject, :migration, schema: 20190725080128 do
- let(:application_settings) { table(:application_settings) }
- let(:users) { table(:users) }
- let(:projects) { table(:projects) }
- let(:namespaces) { table(:namespaces) }
- let(:members) { table(:members) }
-
- let(:service_class) do
- Gitlab::DatabaseImporters::SelfMonitoring::Project::CreateService
- end
-
- let(:prometheus_settings) do
- {
- enable: true,
- listen_address: 'localhost:9090'
- }
- end
-
- before do
- stub_env('IN_MEMORY_APPLICATION_SETTINGS', 'false')
-
- stub_config(prometheus: prometheus_settings)
- end
-
- describe 'perform' do
- context 'without application_settings' do
- it 'does not fail' do
- subject.perform
-
- expect(Project.count).to eq(0)
- end
- end
-
- context 'without admin users' do
- let!(:application_setting) { application_settings.create! }
-
- it 'does not fail' do
- subject.perform
-
- expect(Project.count).to eq(0)
- end
- end
-
- context 'with admin users' do
- let(:project) { Project.last }
- let(:group) { Group.last }
- let!(:application_setting) { application_settings.create! }
- let!(:user) { users.create!(admin: true, email: 'admin1@example.com', projects_limit: 10, state: :active) }
-
- before do
- stub_application_setting(allow_local_requests_from_web_hooks_and_services: true)
- end
-
- shared_examples 'has prometheus service' do |listen_address|
- it do
- subject.perform
-
- prometheus = project.prometheus_service
- expect(prometheus).to be_persisted
- expect(prometheus).not_to eq(nil)
- expect(prometheus.api_url).to eq(listen_address)
- expect(prometheus.active).to eq(true)
- expect(prometheus.manual_configuration).to eq(true)
- end
- end
-
- it_behaves_like 'has prometheus service', 'http://localhost:9090'
-
- it 'creates GitLab Instance Administrator group' do
- subject.perform
-
- expect(group).to be_persisted
- expect(group.name).to eq('GitLab Instance Administrators')
- expect(group.path).to start_with('gitlab-instance-administrators')
- expect(group.path.split('-').last.length).to eq(8)
- expect(group.visibility_level).to eq(service_class::VISIBILITY_LEVEL)
- end
-
- it 'creates project with internal visibility' do
- subject.perform
-
- expect(project.visibility_level).to eq(Gitlab::VisibilityLevel::INTERNAL)
- expect(project).to be_persisted
- end
-
- it 'creates project with correct name and description' do
- subject.perform
-
- path = 'administration/monitoring/gitlab_instance_administration_project/index'
- docs_path = Rails.application.routes.url_helpers.help_page_path(path)
-
- expect(project.name).to eq(service_class::PROJECT_NAME)
- expect(project.description).to eq(
- 'This project is automatically generated and will be used to help monitor this GitLab instance. ' \
- "[More information](#{docs_path})"
- )
- expect(File).to exist("doc/#{path}.md")
- end
-
- it 'adds all admins as maintainers' do
- admin1 = users.create!(admin: true, email: 'admin2@example.com', projects_limit: 10, state: :active)
- admin2 = users.create!(admin: true, email: 'admin3@example.com', projects_limit: 10, state: :active)
- users.create!(email: 'nonadmin1@example.com', projects_limit: 10, state: :active)
-
- subject.perform
-
- expect(project.owner).to eq(group)
- expect(group.members.collect(&:user).collect(&:id)).to contain_exactly(user.id, admin1.id, admin2.id)
- expect(group.members.collect(&:access_level)).to contain_exactly(
- Gitlab::Access::OWNER,
- Gitlab::Access::MAINTAINER,
- Gitlab::Access::MAINTAINER
- )
- end
-
- it 'saves the project id' do
- subject.perform
-
- application_setting.reload
- expect(application_setting.instance_administration_project_id).to eq(project.id)
- end
-
- it 'does not fail when a project already exists' do
- group = namespaces.create!(
- path: 'gitlab-instance-administrators',
- name: 'GitLab Instance Administrators',
- type: 'Group'
- )
- project = projects.create!(
- namespace_id: group.id,
- name: 'GitLab Instance Administration'
- )
-
- admin1 = users.create!(admin: true, email: 'admin4@example.com', projects_limit: 10, state: :active)
- admin2 = users.create!(admin: true, email: 'admin5@example.com', projects_limit: 10, state: :active)
-
- members.create!(
- user_id: admin1.id,
- source_id: group.id,
- source_type: 'Namespace',
- type: 'GroupMember',
- access_level: GroupMember::MAINTAINER,
- notification_level: NotificationSetting.levels[:global]
- )
- members.create!(
- user_id: admin2.id,
- source_id: group.id,
- source_type: 'Namespace',
- type: 'GroupMember',
- access_level: GroupMember::MAINTAINER,
- notification_level: NotificationSetting.levels[:global]
- )
-
- stub_application_setting(instance_administration_project: project)
-
- subject.perform
-
- expect(Project.last.id).to eq(project.id)
- expect(Group.last.id).to eq(group.id)
- end
-
- context 'when local requests from hooks and services are not allowed' do
- before do
- stub_application_setting(allow_local_requests_from_web_hooks_and_services: false)
- end
-
- it_behaves_like 'has prometheus service', 'http://localhost:9090'
-
- it 'does not overwrite the existing whitelist' do
- application_setting.update!(outbound_local_requests_whitelist: ['example.com'])
-
- subject.perform
-
- application_setting.reload
- expect(application_setting.outbound_local_requests_whitelist).to contain_exactly(
- 'example.com', 'localhost'
- )
- end
- end
-
- context 'with non default prometheus address' do
- let(:prometheus_settings) do
- {
- enable: true,
- listen_address: 'https://localhost:9090'
- }
- end
-
- it_behaves_like 'has prometheus service', 'https://localhost:9090'
- end
-
- context 'when prometheus setting is not present in gitlab.yml' do
- before do
- allow(Gitlab.config).to receive(:prometheus).and_raise(Settingslogic::MissingSetting)
- end
-
- it 'does not fail' do
- subject.perform
-
- expect(project.prometheus_service).to be_nil
- end
- end
-
- context 'when prometheus setting is disabled in gitlab.yml' do
- let(:prometheus_settings) do
- {
- enable: false,
- listen_address: 'localhost:9090'
- }
- end
-
- it 'does not configure prometheus' do
- subject.perform
-
- expect(project.prometheus_service).to be_nil
- end
- end
-
- context 'when prometheus listen address is blank in gitlab.yml' do
- let(:prometheus_settings) { { enable: true, listen_address: '' } }
-
- it 'does not configure prometheus' do
- subject.perform
-
- expect(project.prometheus_service).to be_nil
- end
- end
- end
- end
-end
diff --git a/spec/lib/gitlab/ci/build/step_spec.rb b/spec/lib/gitlab/ci/build/step_spec.rb
index 9c1a8cf5e91..84e6e0e177f 100644
--- a/spec/lib/gitlab/ci/build/step_spec.rb
+++ b/spec/lib/gitlab/ci/build/step_spec.rb
@@ -4,49 +4,39 @@ require 'spec_helper'
describe Gitlab::Ci::Build::Step do
describe '#from_commands' do
- subject { described_class.from_commands(job) }
+ shared_examples 'has correct script' do
+ subject { described_class.from_commands(job) }
- before do
- job.run!
- end
+ before do
+ job.run!
+ end
- shared_examples 'has correct script' do
it 'fabricates an object' do
expect(subject.name).to eq(:script)
expect(subject.script).to eq(script)
+ expect(subject.timeout).to eq(job.metadata_timeout)
expect(subject.when).to eq('on_success')
expect(subject.allow_failure).to be_falsey
end
end
context 'when script option is specified' do
- let(:job) { create(:ci_build, :no_options, options: { script: ["ls -la\necho aaa", "date"] }) }
- let(:script) { ["ls -la\necho aaa", 'date'] }
-
- it_behaves_like 'has correct script'
- end
-
- context 'when before and script option is specified' do
- let(:job) do
- create(:ci_build, options: {
- before_script: ["ls -la\necho aaa"],
- script: ["date"]
- })
+ it_behaves_like 'has correct script' do
+ let(:job) { create(:ci_build, :no_options, options: { script: ["ls -la\necho aaa", "date"] }) }
+ let(:script) { ["ls -la\necho aaa", 'date'] }
end
-
- let(:script) { ["ls -la\necho aaa", 'date'] }
-
- it_behaves_like 'has correct script'
end
- context 'when timeout option is specified in seconds' do
- let(:job) { create(:ci_build, options: { job_timeout: 3, script: ["ls -la\necho aaa", 'date'] }) }
- let(:script) { ["ls -la\necho aaa", 'date'] }
-
- it_behaves_like 'has correct script'
-
- it 'has job level timeout' do
- expect(subject.timeout).to eq(3)
+ context 'when before and script option is specified' do
+ it_behaves_like 'has correct script' do
+ let(:job) do
+ create(:ci_build, options: {
+ before_script: ["ls -la\necho aaa"],
+ script: ["date"]
+ })
+ end
+
+ let(:script) { ["ls -la\necho aaa", 'date'] }
end
end
end
@@ -67,12 +57,12 @@ describe Gitlab::Ci::Build::Step do
end
context 'when after_script is not empty' do
- let(:job) { create(:ci_build, options: { job_timeout: 60, script: ['bash'], after_script: ['ls -la', 'date'] }) }
+ let(:job) { create(:ci_build, options: { script: ['bash'], after_script: ['ls -la', 'date'] }) }
it 'fabricates an object' do
expect(subject.name).to eq(:after_script)
expect(subject.script).to eq(['ls -la', 'date'])
- expect(subject.timeout).to eq(60)
+ expect(subject.timeout).to eq(job.metadata_timeout)
expect(subject.when).to eq('always')
expect(subject.allow_failure).to be_truthy
end
diff --git a/spec/lib/gitlab/ci/config/entry/job_spec.rb b/spec/lib/gitlab/ci/config/entry/job_spec.rb
index 1c4887e87c4..1853efde350 100644
--- a/spec/lib/gitlab/ci/config/entry/job_spec.rb
+++ b/spec/lib/gitlab/ci/config/entry/job_spec.rb
@@ -417,37 +417,6 @@ describe Gitlab::Ci::Config::Entry::Job do
end
end
end
-
- context 'when timeout value is not correct' do
- context 'when it is higher than instance wide timeout' do
- let(:config) { { timeout: '3 months' } }
-
- it 'returns error about value too high' do
- expect(entry).not_to be_valid
- expect(entry.errors)
- .to include "job timeout should not exceed the limit"
- end
- end
-
- context 'when it is not a duration' do
- let(:config) { { timeout: 100 } }
-
- it 'returns error about wrong value' do
- expect(entry).not_to be_valid
- expect(entry.errors).to include 'job timeout should be a duration'
- end
- end
- end
-
- context 'when timeout value is correct' do
- let(:config) { { script: 'echo', timeout: '1m 1s' } }
-
- it 'returns correct timeout' do
- expect(entry).to be_valid
- expect(entry.errors).to be_empty
- expect(entry.timeout).to eq('1m 1s')
- end
- end
end
end
diff --git a/spec/lib/gitlab/ci/yaml_processor_spec.rb b/spec/lib/gitlab/ci/yaml_processor_spec.rb
index 8f2f23f6110..9d9a9ecda33 100644
--- a/spec/lib/gitlab/ci/yaml_processor_spec.rb
+++ b/spec/lib/gitlab/ci/yaml_processor_spec.rb
@@ -1134,48 +1134,6 @@ module Gitlab
end
end
- describe "Timeout" do
- let(:config) do
- {
- deploy_to_production: {
- stage: 'deploy',
- script: 'test'
- }
- }
- end
-
- let(:processor) { Gitlab::Ci::YamlProcessor.new(YAML.dump(config)) }
- let(:builds) { processor.stage_builds_attributes('deploy') }
-
- context 'when no timeout was provided' do
- it 'does not include job_timeout' do
- expect(builds.size).to eq(1)
- expect(builds.first[:options]).not_to include(:job_timeout)
- end
- end
-
- context 'when an invalid timeout was provided' do
- before do
- config[:deploy_to_production][:timeout] = 'not-a-number'
- end
-
- it 'raises an error for invalid number' do
- expect { builds }.to raise_error('jobs:deploy_to_production timeout should be a duration')
- end
- end
-
- context 'when some valid timeout was provided' do
- before do
- config[:deploy_to_production][:timeout] = '1m 3s'
- end
-
- it 'returns provided timeout value' do
- expect(builds.size).to eq(1)
- expect(builds.first[:options]).to include(job_timeout: 63)
- end
- end
- end
-
describe "Dependencies" do
let(:config) do
{
diff --git a/spec/lib/gitlab/discussions_diff/file_collection_spec.rb b/spec/lib/gitlab/discussions_diff/file_collection_spec.rb
index 6ef1e41450f..0489206458b 100644
--- a/spec/lib/gitlab/discussions_diff/file_collection_spec.rb
+++ b/spec/lib/gitlab/discussions_diff/file_collection_spec.rb
@@ -22,13 +22,11 @@ describe Gitlab::DiscussionsDiff::FileCollection do
note_diff_file_b.id => file_b_caching_content })
.and_call_original
- subject.load_highlight
+ subject.load_highlight([note_diff_file_a.id, note_diff_file_b.id])
end
it 'does not write cache for already cached file' do
- file_a_caching_content = diff_note_a.diff_file.highlighted_diff_lines.map(&:to_hash)
- Gitlab::DiscussionsDiff::HighlightCache
- .write_multiple({ note_diff_file_a.id => file_a_caching_content })
+ subject.load_highlight([note_diff_file_a.id])
file_b_caching_content = diff_note_b.diff_file.highlighted_diff_lines.map(&:to_hash)
@@ -37,42 +35,27 @@ describe Gitlab::DiscussionsDiff::FileCollection do
.with({ note_diff_file_b.id => file_b_caching_content })
.and_call_original
- subject.load_highlight
+ subject.load_highlight([note_diff_file_a.id, note_diff_file_b.id])
end
- it 'does not write cache for resolved notes' do
- diff_note_a.update_column(:resolved_at, Time.now)
-
- file_b_caching_content = diff_note_b.diff_file.highlighted_diff_lines.map(&:to_hash)
-
- expect(Gitlab::DiscussionsDiff::HighlightCache)
- .to receive(:write_multiple)
- .with({ note_diff_file_b.id => file_b_caching_content })
- .and_call_original
-
- subject.load_highlight
+ it 'does not err when given ID does not exist in @collection' do
+ expect { subject.load_highlight([999]) }.not_to raise_error
end
it 'loaded diff files have highlighted lines loaded' do
- subject.load_highlight
+ subject.load_highlight([note_diff_file_a.id])
- diff_file_a = subject.find_by_id(note_diff_file_a.id)
- diff_file_b = subject.find_by_id(note_diff_file_b.id)
+ diff_file = subject.find_by_id(note_diff_file_a.id)
- expect(diff_file_a).to be_highlight_loaded
- expect(diff_file_b).to be_highlight_loaded
+ expect(diff_file.highlight_loaded?).to be(true)
end
it 'not loaded diff files does not have highlighted lines loaded' do
- diff_note_a.update_column(:resolved_at, Time.now)
-
- subject.load_highlight
+ subject.load_highlight([note_diff_file_a.id])
- diff_file_a = subject.find_by_id(note_diff_file_a.id)
- diff_file_b = subject.find_by_id(note_diff_file_b.id)
+ diff_file = subject.find_by_id(note_diff_file_b.id)
- expect(diff_file_a).not_to be_highlight_loaded
- expect(diff_file_b).to be_highlight_loaded
+ expect(diff_file.highlight_loaded?).to be(false)
end
end
end
diff --git a/spec/lib/gitlab/encoding_helper_spec.rb b/spec/lib/gitlab/encoding_helper_spec.rb
index fc08719fb33..b24b71522ec 100644
--- a/spec/lib/gitlab/encoding_helper_spec.rb
+++ b/spec/lib/gitlab/encoding_helper_spec.rb
@@ -1,3 +1,4 @@
+# coding: utf-8
# frozen_string_literal: true
require "spec_helper"
diff --git a/spec/lib/gitlab/etag_caching/router_spec.rb b/spec/lib/gitlab/etag_caching/router_spec.rb
index fbc49d894a6..8fcd4eb3c21 100644
--- a/spec/lib/gitlab/etag_caching/router_spec.rb
+++ b/spec/lib/gitlab/etag_caching/router_spec.rb
@@ -92,6 +92,15 @@ describe Gitlab::EtagCaching::Router do
expect(result).to be_blank
end
+ it 'matches the cluster environments path' do
+ result = described_class.match(
+ '/my-group/my-project/-/clusters/47/environments'
+ )
+
+ expect(result).to be_present
+ expect(result.name).to eq 'cluster_environments'
+ end
+
it 'matches the environments path' do
result = described_class.match(
'/my-group/my-project/environments.json'
diff --git a/spec/lib/gitlab/git/blame_spec.rb b/spec/lib/gitlab/git/blame_spec.rb
index ac085e2c266..0010c0304eb 100644
--- a/spec/lib/gitlab/git/blame_spec.rb
+++ b/spec/lib/gitlab/git/blame_spec.rb
@@ -1,3 +1,4 @@
+# coding: utf-8
require "spec_helper"
describe Gitlab::Git::Blame, :seed_helper do
diff --git a/spec/lib/gitlab/git/blob_spec.rb b/spec/lib/gitlab/git/blob_spec.rb
index 7f680071969..1c24244c3a6 100644
--- a/spec/lib/gitlab/git/blob_spec.rb
+++ b/spec/lib/gitlab/git/blob_spec.rb
@@ -1,3 +1,5 @@
+# encoding: utf-8
+
require "spec_helper"
describe Gitlab::Git::Blob, :seed_helper do
diff --git a/spec/lib/gitlab/git/conflict/file_spec.rb b/spec/lib/gitlab/git/conflict/file_spec.rb
index a6cabd4966a..afed6c32af6 100644
--- a/spec/lib/gitlab/git/conflict/file_spec.rb
+++ b/spec/lib/gitlab/git/conflict/file_spec.rb
@@ -1,3 +1,4 @@
+# coding: utf-8
require 'spec_helper'
describe Gitlab::Git::Conflict::File do
diff --git a/spec/lib/gitlab/git/repository_spec.rb b/spec/lib/gitlab/git/repository_spec.rb
index e455c4c99ab..dccd50bc472 100644
--- a/spec/lib/gitlab/git/repository_spec.rb
+++ b/spec/lib/gitlab/git/repository_spec.rb
@@ -1,3 +1,4 @@
+# coding: utf-8
require "spec_helper"
describe Gitlab::Git::Repository, :seed_helper do
diff --git a/spec/lib/gitlab/git_spec.rb b/spec/lib/gitlab/git_spec.rb
index 505bc470644..6515be85ae3 100644
--- a/spec/lib/gitlab/git_spec.rb
+++ b/spec/lib/gitlab/git_spec.rb
@@ -1,3 +1,4 @@
+# coding: utf-8
require 'spec_helper'
describe Gitlab::Git do
diff --git a/spec/lib/gitlab/hook_data/issuable_builder_spec.rb b/spec/lib/gitlab/hook_data/issuable_builder_spec.rb
index 97a89b319ea..569d5dcc757 100644
--- a/spec/lib/gitlab/hook_data/issuable_builder_spec.rb
+++ b/spec/lib/gitlab/hook_data/issuable_builder_spec.rb
@@ -42,15 +42,7 @@ describe Gitlab::HookData::IssuableBuilder do
[{ id: 1, title: 'foo' }],
[{ id: 1, title: 'foo' }, { id: 2, title: 'bar' }]
],
- total_time_spent: [1, 2],
- assignees: [
- [],
- [{
- name: "Foo Bar",
- username: "foobar",
- avatar_url: "http://www.example.com/my-avatar.jpg"
- }]
- ]
+ total_time_spent: [1, 2]
}
end
let(:data) { builder.build(user: user, changes: changes) }
@@ -66,14 +58,6 @@ describe Gitlab::HookData::IssuableBuilder do
total_time_spent: {
previous: 1,
current: 2
- },
- assignees: {
- previous: [],
- current: [{
- name: "Foo Bar",
- username: "foobar",
- avatar_url: "http://www.example.com/my-avatar.jpg"
- }]
}
}))
end
diff --git a/spec/lib/gitlab/import_export/all_models.yml b/spec/lib/gitlab/import_export/all_models.yml
index d3be1e86539..6d573a4f39a 100644
--- a/spec/lib/gitlab/import_export/all_models.yml
+++ b/spec/lib/gitlab/import_export/all_models.yml
@@ -65,8 +65,8 @@ milestone:
- participants
- events
- boards
-- milestone_releases
-- releases
+- milestone_release
+- release
snippets:
- author
- project
@@ -77,8 +77,8 @@ releases:
- author
- project
- links
-- milestone_releases
-- milestones
+- milestone_release
+- milestone
links:
- release
project_members:
diff --git a/spec/lib/gitlab/json_logger_spec.rb b/spec/lib/gitlab/json_logger_spec.rb
index 3d4f9b5db86..d3d9fe9948a 100644
--- a/spec/lib/gitlab/json_logger_spec.rb
+++ b/spec/lib/gitlab/json_logger_spec.rb
@@ -1,3 +1,4 @@
+# coding: utf-8
require 'spec_helper'
describe Gitlab::JsonLogger do
diff --git a/spec/lib/gitlab/path_regex_spec.rb b/spec/lib/gitlab/path_regex_spec.rb
index 0829a2b4334..7dcdad7ff92 100644
--- a/spec/lib/gitlab/path_regex_spec.rb
+++ b/spec/lib/gitlab/path_regex_spec.rb
@@ -1,3 +1,4 @@
+# coding: utf-8
# frozen_string_literal: true
require 'spec_helper'
diff --git a/spec/lib/gitlab/popen_spec.rb b/spec/lib/gitlab/popen_spec.rb
index b398381a7e0..29afd9df74e 100644
--- a/spec/lib/gitlab/popen_spec.rb
+++ b/spec/lib/gitlab/popen_spec.rb
@@ -87,12 +87,4 @@ describe Gitlab::Popen do
it { expect(@status).to be_zero }
it { expect(@output).to eq('hello') }
end
-
- context 'when binary is absent' do
- it 'raises error' do
- expect do
- @klass.new.popen(%w[foobar])
- end.to raise_error
- end
- end
end
diff --git a/spec/lib/gitlab/project_search_results_spec.rb b/spec/lib/gitlab/project_search_results_spec.rb
index d6e50c672e6..e0b9581c75c 100644
--- a/spec/lib/gitlab/project_search_results_spec.rb
+++ b/spec/lib/gitlab/project_search_results_spec.rb
@@ -1,3 +1,4 @@
+# coding: utf-8
# frozen_string_literal: true
require 'spec_helper'
diff --git a/spec/lib/gitlab/regex_spec.rb b/spec/lib/gitlab/regex_spec.rb
index 3036e3a9754..e19210d8fbf 100644
--- a/spec/lib/gitlab/regex_spec.rb
+++ b/spec/lib/gitlab/regex_spec.rb
@@ -1,3 +1,4 @@
+# coding: utf-8
# frozen_string_literal: true
require 'spec_helper'
diff --git a/spec/lib/gitlab/search/found_blob_spec.rb b/spec/lib/gitlab/search/found_blob_spec.rb
index a575f6e2f11..3496fb29836 100644
--- a/spec/lib/gitlab/search/found_blob_spec.rb
+++ b/spec/lib/gitlab/search/found_blob_spec.rb
@@ -1,3 +1,4 @@
+# coding: utf-8
# frozen_string_literal: true
require 'spec_helper'
diff --git a/spec/lib/gitlab/url_blocker_spec.rb b/spec/lib/gitlab/url_blocker_spec.rb
index 0e66e959b24..6ce002ad70e 100644
--- a/spec/lib/gitlab/url_blocker_spec.rb
+++ b/spec/lib/gitlab/url_blocker_spec.rb
@@ -1,3 +1,4 @@
+# coding: utf-8
# frozen_string_literal: true
require 'spec_helper'
diff --git a/spec/lib/gitlab/usage_data_spec.rb b/spec/lib/gitlab/usage_data_spec.rb
index 62787c5abaf..8eb64b97d6a 100644
--- a/spec/lib/gitlab/usage_data_spec.rb
+++ b/spec/lib/gitlab/usage_data_spec.rb
@@ -3,16 +3,14 @@
require 'spec_helper'
describe Gitlab::UsageData do
- let(:projects) { create_list(:project, 4) }
+ let(:projects) { create_list(:project, 3) }
let!(:board) { create(:board, project: projects[0]) }
describe '#data' do
before do
create(:jira_service, project: projects[0])
- create(:jira_service, :without_properties_callback, project: projects[1])
+ create(:jira_service, project: projects[1])
create(:jira_service, :jira_cloud_service, project: projects[2])
- create(:jira_service, :without_properties_callback, project: projects[3],
- properties: { url: 'https://mysite.atlassian.net' })
create(:prometheus_service, project: projects[1])
create(:service, project: projects[0], type: 'SlackSlashCommandsService', active: true)
create(:service, project: projects[1], type: 'SlackService', active: true)
@@ -158,7 +156,7 @@ describe Gitlab::UsageData do
count_data = subject[:counts]
expect(count_data[:boards]).to eq(1)
- expect(count_data[:projects]).to eq(4)
+ expect(count_data[:projects]).to eq(3)
expect(count_data.keys).to include(*expected_keys)
expect(expected_keys - count_data.keys).to be_empty
end
@@ -166,14 +164,14 @@ describe Gitlab::UsageData do
it 'gathers projects data correctly' do
count_data = subject[:counts]
- expect(count_data[:projects]).to eq(4)
+ expect(count_data[:projects]).to eq(3)
expect(count_data[:projects_prometheus_active]).to eq(1)
- expect(count_data[:projects_jira_active]).to eq(4)
+ expect(count_data[:projects_jira_active]).to eq(3)
expect(count_data[:projects_jira_server_active]).to eq(2)
- expect(count_data[:projects_jira_cloud_active]).to eq(2)
+ expect(count_data[:projects_jira_cloud_active]).to eq(1)
expect(count_data[:projects_slack_notifications_active]).to eq(2)
expect(count_data[:projects_slack_slash_active]).to eq(1)
- expect(count_data[:projects_with_repositories_enabled]).to eq(3)
+ expect(count_data[:projects_with_repositories_enabled]).to eq(2)
expect(count_data[:projects_with_error_tracking_enabled]).to eq(1)
expect(count_data[:clusters_enabled]).to eq(7)
diff --git a/spec/lib/gitlab_danger_spec.rb b/spec/lib/gitlab_danger_spec.rb
index 26bf5d76756..623ac20fa7c 100644
--- a/spec/lib/gitlab_danger_spec.rb
+++ b/spec/lib/gitlab_danger_spec.rb
@@ -9,7 +9,7 @@ describe GitlabDanger do
describe '.local_warning_message' do
it 'returns an informational message with rules that can run' do
- expect(described_class.local_warning_message).to eq('==> Only the following Danger rules can be run locally: changes_size, gemfile, documentation, frozen_string, duplicate_yarn_dependencies, prettier, eslint, database, commit_messages')
+ expect(described_class.local_warning_message).to eq('==> Only the following Danger rules can be run locally: changes_size, gemfile, documentation, frozen_string, duplicate_yarn_dependencies, prettier, eslint, database')
end
end
diff --git a/spec/migrations/migrate_code_owner_approval_status_to_protected_branches_in_batches_spec.rb b/spec/migrations/migrate_code_owner_approval_status_to_protected_branches_in_batches_spec.rb
deleted file mode 100644
index 67ac40d4d39..00000000000
--- a/spec/migrations/migrate_code_owner_approval_status_to_protected_branches_in_batches_spec.rb
+++ /dev/null
@@ -1,63 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-require Rails.root.join('db', 'post_migrate', '20190827102026_migrate_code_owner_approval_status_to_protected_branches_in_batches.rb')
-
-describe MigrateCodeOwnerApprovalStatusToProtectedBranchesInBatches, :migration do
- let(:namespaces) { table(:namespaces) }
- let(:projects) { table(:projects) }
- let(:protected_branches) { table(:protected_branches) }
-
- let(:namespace) do
- namespaces.create!(
- path: 'gitlab-instance-administrators',
- name: 'GitLab Instance Administrators'
- )
- end
-
- let(:project) do
- projects.create!(
- namespace_id: namespace.id,
- name: 'GitLab Instance Administration'
- )
- end
-
- let!(:protected_branch_1) do
- protected_branches.create!(
- name: "branch name",
- project_id: project.id
- )
- end
-
- describe '#up' do
- context "when there's no projects needing approval" do
- it "doesn't change any protected branch records" do
- expect { migrate! }
- .not_to change { ProtectedBranch.where(code_owner_approval_required: true).count }
- end
- end
-
- context "when there's a project needing approval" do
- let!(:project_needing_approval) do
- projects.create!(
- namespace_id: namespace.id,
- name: 'GitLab Instance Administration',
- merge_requests_require_code_owner_approval: true
- )
- end
-
- let!(:protected_branch_2) do
- protected_branches.create!(
- name: "branch name",
- project_id: project_needing_approval.id
- )
- end
-
- it "changes N protected branch records" do
- expect { migrate! }
- .to change { ProtectedBranch.where(code_owner_approval_required: true).count }
- .by(1)
- end
- end
- end
-end
diff --git a/spec/models/blob_spec.rb b/spec/models/blob_spec.rb
index 2efab3076d8..62a75bde63b 100644
--- a/spec/models/blob_spec.rb
+++ b/spec/models/blob_spec.rb
@@ -1,3 +1,4 @@
+# encoding: utf-8
# frozen_string_literal: true
require 'spec_helper'
diff --git a/spec/models/ci/build_metadata_spec.rb b/spec/models/ci/build_metadata_spec.rb
index 67cd939b4c6..917a65ddf21 100644
--- a/spec/models/ci/build_metadata_spec.rb
+++ b/spec/models/ci/build_metadata_spec.rb
@@ -22,72 +22,42 @@ describe Ci::BuildMetadata do
describe '#update_timeout_state' do
subject { metadata }
- shared_examples 'sets timeout' do |source, timeout|
- it 'sets project_timeout_source' do
- expect { subject.update_timeout_state }.to change { subject.reload.timeout_source }.to(source)
+ context 'when runner is not assigned to the job' do
+ it "doesn't change timeout value" do
+ expect { subject.update_timeout_state }.not_to change { subject.reload.timeout }
end
- it 'sets project timeout' do
- expect { subject.update_timeout_state }.to change { subject.reload.timeout }.to(timeout)
+ it "doesn't change timeout_source value" do
+ expect { subject.update_timeout_state }.not_to change { subject.reload.timeout_source }
end
end
- context 'when project timeout is set' do
- context 'when runner is assigned to the job' do
- before do
- build.update!(runner: runner)
- end
-
- context 'when runner timeout is not set' do
- let(:runner) { create(:ci_runner, maximum_timeout: nil) }
-
- it_behaves_like 'sets timeout', 'project_timeout_source', 2000
- end
-
- context 'when runner timeout is lower than project timeout' do
- let(:runner) { create(:ci_runner, maximum_timeout: 1900) }
-
- it_behaves_like 'sets timeout', 'runner_timeout_source', 1900
- end
-
- context 'when runner timeout is higher than project timeout' do
- let(:runner) { create(:ci_runner, maximum_timeout: 2100) }
-
- it_behaves_like 'sets timeout', 'project_timeout_source', 2000
- end
+ context 'when runner is assigned to the job' do
+ before do
+ build.update(runner: runner)
end
- context 'when job timeout is set' do
- context 'when job timeout is higher than project timeout' do
- let(:build) { create(:ci_build, pipeline: pipeline, options: { job_timeout: 3000 }) }
+ context 'when runner timeout is lower than project timeout' do
+ let(:runner) { create(:ci_runner, maximum_timeout: 1900) }
- it_behaves_like 'sets timeout', 'job_timeout_source', 3000
+ it 'sets runner timeout' do
+ expect { subject.update_timeout_state }.to change { subject.reload.timeout }.to(1900)
end
- context 'when job timeout is lower than project timeout' do
- let(:build) { create(:ci_build, pipeline: pipeline, options: { job_timeout: 1000 }) }
-
- it_behaves_like 'sets timeout', 'job_timeout_source', 1000
+ it 'sets runner_timeout_source' do
+ expect { subject.update_timeout_state }.to change { subject.reload.timeout_source }.to('runner_timeout_source')
end
end
- context 'when both runner and job timeouts are set' do
- before do
- build.update(runner: runner)
- end
-
- context 'when job timeout is higher than runner timeout' do
- let(:build) { create(:ci_build, pipeline: pipeline, options: { job_timeout: 3000 }) }
- let(:runner) { create(:ci_runner, maximum_timeout: 2100) }
+ context 'when runner timeout is higher than project timeout' do
+ let(:runner) { create(:ci_runner, maximum_timeout: 2100) }
- it_behaves_like 'sets timeout', 'runner_timeout_source', 2100
+ it 'sets project timeout' do
+ expect { subject.update_timeout_state }.to change { subject.reload.timeout }.to(2000)
end
- context 'when job timeout is lower than runner timeout' do
- let(:build) { create(:ci_build, pipeline: pipeline, options: { job_timeout: 1900 }) }
- let(:runner) { create(:ci_runner, maximum_timeout: 2100) }
-
- it_behaves_like 'sets timeout', 'job_timeout_source', 1900
+ it 'sets project_timeout_source' do
+ expect { subject.update_timeout_state }.to change { subject.reload.timeout_source }.to('project_timeout_source')
end
end
end
diff --git a/spec/models/clusters/applications/ingress_spec.rb b/spec/models/clusters/applications/ingress_spec.rb
index f984f6ba0ce..d9461ee8581 100644
--- a/spec/models/clusters/applications/ingress_spec.rb
+++ b/spec/models/clusters/applications/ingress_spec.rb
@@ -131,4 +131,41 @@ describe Clusters::Applications::Ingress do
expect(values).to include('podAnnotations')
end
end
+
+ describe '#values' do
+ let(:project) { build(:project) }
+ let(:cluster) { build(:cluster, projects: [project]) }
+
+ context 'when ingress_modsecurity is enabled' do
+ before do
+ stub_feature_flags(ingress_modsecurity: true)
+
+ allow(subject).to receive(:cluster).and_return(cluster)
+ end
+
+ it 'includes modsecurity module enablement' do
+ expect(subject.values).to include("enable-modsecurity: 'true'")
+ end
+
+ it 'includes modsecurity core ruleset enablement' do
+ expect(subject.values).to include("enable-owasp-modsecurity-crs: 'true'")
+ end
+ end
+
+ context 'when ingress_modsecurity is disabled' do
+ before do
+ stub_feature_flags(ingress_modsecurity: false)
+
+ allow(subject).to receive(:cluster).and_return(cluster)
+ end
+
+ it 'excludes modsecurity module enablement' do
+ expect(subject.values).not_to include('enable-modsecurity')
+ end
+
+ it 'excludes modsecurity core ruleset enablement' do
+ expect(subject.values).not_to include('enable-owasp-modsecurity-crs')
+ end
+ end
+ end
end
diff --git a/spec/models/concerns/routable_spec.rb b/spec/models/concerns/routable_spec.rb
index f78a089bc2e..cad705ee594 100644
--- a/spec/models/concerns/routable_spec.rb
+++ b/spec/models/concerns/routable_spec.rb
@@ -58,7 +58,7 @@ describe Group, 'Routable' do
end
end
- context '.find_by_full_path' do
+ shared_examples_for '.find_by_full_path' do
let!(:nested_group) { create(:group, parent: group) }
context 'without any redirect routes' do
@@ -117,6 +117,24 @@ describe Group, 'Routable' do
end
end
+ describe '.find_by_full_path' do
+ context 'with routable_two_step_lookup feature' do
+ before do
+ stub_feature_flags(routable_two_step_lookup: true)
+ end
+
+ it_behaves_like '.find_by_full_path'
+ end
+
+ context 'without routable_two_step_lookup feature' do
+ before do
+ stub_feature_flags(routable_two_step_lookup: false)
+ end
+
+ it_behaves_like '.find_by_full_path'
+ end
+ end
+
describe '.where_full_path_in' do
context 'without any paths' do
it 'returns an empty relation' do
diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb
index 65cc1a4bd6b..fde1b096c76 100644
--- a/spec/models/merge_request_spec.rb
+++ b/spec/models/merge_request_spec.rb
@@ -650,35 +650,9 @@ describe MergeRequest do
end
end
- describe '#discussions_diffs' do
+ describe '#preload_discussions_diff_highlight' do
let(:merge_request) { create(:merge_request) }
- shared_examples 'discussions diffs collection' do
- it 'initializes Gitlab::DiscussionsDiff::FileCollection with correct data' do
- note_diff_file = diff_note.note_diff_file
-
- expect(Gitlab::DiscussionsDiff::FileCollection)
- .to receive(:new)
- .with([note_diff_file])
- .and_call_original
-
- result = merge_request.discussions_diffs
-
- expect(result).to be_a(Gitlab::DiscussionsDiff::FileCollection)
- end
-
- it 'eager loads relations' do
- result = merge_request.discussions_diffs
-
- recorder = ActiveRecord::QueryRecorder.new do
- result.first.diff_note
- result.first.diff_note.project
- end
-
- expect(recorder.count).to be_zero
- end
- end
-
context 'with commit diff note' do
let(:other_merge_request) { create(:merge_request) }
@@ -690,15 +664,40 @@ describe MergeRequest do
create(:diff_note_on_commit, project: other_merge_request.project)
end
- it_behaves_like 'discussions diffs collection'
+ it 'preloads diff highlighting' do
+ expect_next_instance_of(Gitlab::DiscussionsDiff::FileCollection) do |collection|
+ note_diff_file = diff_note.note_diff_file
+
+ expect(collection)
+ .to receive(:load_highlight)
+ .with([note_diff_file.id]).and_call_original
+ end
+
+ merge_request.preload_discussions_diff_highlight
+ end
end
context 'with merge request diff note' do
- let!(:diff_note) do
+ let!(:unresolved_diff_note) do
create(:diff_note_on_merge_request, project: merge_request.project, noteable: merge_request)
end
- it_behaves_like 'discussions diffs collection'
+ let!(:resolved_diff_note) do
+ create(:diff_note_on_merge_request, :resolved, project: merge_request.project, noteable: merge_request)
+ end
+
+ it 'preloads diff highlighting' do
+ expect_next_instance_of(Gitlab::DiscussionsDiff::FileCollection) do |collection|
+ note_diff_file = unresolved_diff_note.note_diff_file
+
+ expect(collection)
+ .to receive(:load_highlight)
+ .with([note_diff_file.id])
+ .and_call_original
+ end
+
+ merge_request.preload_discussions_diff_highlight
+ end
end
end
diff --git a/spec/models/milestone_release_spec.rb b/spec/models/milestone_release_spec.rb
index 28cec7bbc17..d6f73275977 100644
--- a/spec/models/milestone_release_spec.rb
+++ b/spec/models/milestone_release_spec.rb
@@ -14,29 +14,23 @@ describe MilestoneRelease do
it { is_expected.to belong_to(:release) }
end
- context 'when trying to create the same record in milestone_releases twice' do
- it 'is not committing on the second time' do
- create(:milestone_release, milestone: milestone, release: release)
-
- expect do
- subject.save!
- end.to raise_error(ActiveRecord::RecordNotUnique)
- end
- end
-
describe 'validations' do
- subject(:milestone_release) { build(:milestone_release, milestone: milestone, release: release) }
+ it { is_expected.to validate_uniqueness_of(:milestone_id).scoped_to(:release_id) }
context 'when milestone and release do not have the same project' do
it 'is not valid' do
- milestone_release.release = build(:release, project: create(:project))
-
+ other_project = create(:project)
+ release = build(:release, project: other_project)
+ milestone_release = described_class.new(milestone: milestone, release: release)
expect(milestone_release).not_to be_valid
end
end
context 'when milestone and release have the same project' do
- it { is_expected.to be_valid }
+ it 'is valid' do
+ milestone_release = described_class.new(milestone: milestone, release: release)
+ expect(milestone_release).to be_valid
+ end
end
end
end
diff --git a/spec/models/milestone_spec.rb b/spec/models/milestone_spec.rb
index 0c4952eebd7..64030f5b92a 100644
--- a/spec/models/milestone_spec.rb
+++ b/spec/models/milestone_spec.rb
@@ -55,20 +55,20 @@ describe Milestone do
end
end
- describe 'milestone_releases' do
+ describe 'milestone_release' do
let(:milestone) { build(:milestone, project: project) }
context 'when it is tied to a release for another project' do
it 'creates a validation error' do
other_project = create(:project)
- milestone.releases << build(:release, project: other_project)
+ milestone.release = build(:release, project: other_project)
expect(milestone).not_to be_valid
end
end
context 'when it is tied to a release for the same project' do
it 'is valid' do
- milestone.releases << build(:release, project: project)
+ milestone.release = build(:release, project: project)
expect(milestone).to be_valid
end
end
@@ -78,8 +78,7 @@ describe Milestone do
describe "Associations" do
it { is_expected.to belong_to(:project) }
it { is_expected.to have_many(:issues) }
- it { is_expected.to have_many(:releases) }
- it { is_expected.to have_many(:milestone_releases) }
+ it { is_expected.to have_one(:release) }
end
let(:project) { create(:project, :public) }
diff --git a/spec/models/project_services/bugzilla_service_spec.rb b/spec/models/project_services/bugzilla_service_spec.rb
index e25d87f61d6..74c85a13c88 100644
--- a/spec/models/project_services/bugzilla_service_spec.rb
+++ b/spec/models/project_services/bugzilla_service_spec.rb
@@ -48,7 +48,7 @@ describe BugzillaService do
create(:bugzilla_service, :without_properties_callback, properties: properties)
end
- it_behaves_like 'issue tracker fields'
+ include_examples 'issue tracker fields'
end
context 'when data are stored in separated fields' do
@@ -56,7 +56,7 @@ describe BugzillaService do
create(:bugzilla_service, title: title, description: description, properties: access_params)
end
- it_behaves_like 'issue tracker fields'
+ include_examples 'issue tracker fields'
end
context 'when data are stored in both properties and separated fields' do
@@ -65,7 +65,7 @@ describe BugzillaService do
create(:bugzilla_service, :without_properties_callback, title: title, description: description, properties: properties)
end
- it_behaves_like 'issue tracker fields'
+ include_examples 'issue tracker fields'
end
context 'when no title & description are set' do
diff --git a/spec/models/project_services/custom_issue_tracker_service_spec.rb b/spec/models/project_services/custom_issue_tracker_service_spec.rb
index 8359bc6807a..5259357a254 100644
--- a/spec/models/project_services/custom_issue_tracker_service_spec.rb
+++ b/spec/models/project_services/custom_issue_tracker_service_spec.rb
@@ -62,7 +62,7 @@ describe CustomIssueTrackerService do
create(:custom_issue_tracker_service, :without_properties_callback, properties: properties)
end
- it_behaves_like 'issue tracker fields'
+ include_examples 'issue tracker fields'
end
context 'when data are stored in separated fields' do
@@ -70,7 +70,7 @@ describe CustomIssueTrackerService do
create(:custom_issue_tracker_service, title: title, description: description, properties: access_params)
end
- it_behaves_like 'issue tracker fields'
+ include_examples 'issue tracker fields'
end
context 'when data are stored in both properties and separated fields' do
@@ -79,7 +79,7 @@ describe CustomIssueTrackerService do
create(:custom_issue_tracker_service, :without_properties_callback, title: title, description: description, properties: properties)
end
- it_behaves_like 'issue tracker fields'
+ include_examples 'issue tracker fields'
end
context 'when no title & description are set' do
diff --git a/spec/models/project_services/data_fields_spec.rb b/spec/models/project_services/data_fields_spec.rb
deleted file mode 100644
index 146db0ae227..00000000000
--- a/spec/models/project_services/data_fields_spec.rb
+++ /dev/null
@@ -1,138 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-describe DataFields do
- let(:url) { 'http://url.com' }
- let(:username) { 'username_one' }
- let(:properties) do
- { url: url, username: username }
- end
-
- shared_examples 'data fields' do
- describe '#arg' do
- it 'returns an argument correctly' do
- expect(service.url).to eq(url)
- end
- end
-
- describe '{arg}_changed?' do
- it 'returns false when the property has not been assigned a new value' do
- service.username = 'new_username'
- service.validate
- expect(service.url_changed?).to be_falsy
- end
-
- it 'returns true when the property has been assigned a different value' do
- service.url = "http://example.com"
- service.validate
- expect(service.url_changed?).to be_truthy
- end
-
- it 'returns true when the property has been assigned a different value twice' do
- service.url = "http://example.com"
- service.url = "http://example.com"
- service.validate
- expect(service.url_changed?).to be_truthy
- end
-
- it 'returns false when the property has been re-assigned the same value' do
- service.url = 'http://url.com'
- service.validate
- expect(service.url_changed?).to be_falsy
- end
- end
-
- describe '{arg}_touched?' do
- it 'returns false when the property has not been assigned a new value' do
- service.username = 'new_username'
- service.validate
- expect(service.url_changed?).to be_falsy
- end
-
- it 'returns true when the property has been assigned a different value' do
- service.url = "http://example.com"
- service.validate
- expect(service.url_changed?).to be_truthy
- end
-
- it 'returns true when the property has been assigned a different value twice' do
- service.url = "http://example.com"
- service.url = "http://example.com"
- service.validate
- expect(service.url_changed?).to be_truthy
- end
-
- it 'returns true when the property has been re-assigned the same value' do
- service.url = 'http://url.com'
- expect(service.url_touched?).to be_truthy
- end
-
- it 'returns false when the property has been re-assigned the same value' do
- service.url = 'http://url.com'
- service.validate
- expect(service.url_changed?).to be_falsy
- end
- end
- end
-
- context 'when data are stored in data_fields' do
- let(:service) do
- create(:jira_service, url: url, username: username)
- end
-
- it_behaves_like 'data fields'
-
- describe '{arg}_was?' do
- it 'returns nil' do
- service.url = 'http://example.com'
- service.validate
- expect(service.url_was).to be_nil
- end
- end
- end
-
- context 'when data are stored in properties' do
- let(:service) { create(:jira_service, :without_properties_callback, properties: properties) }
-
- it_behaves_like 'data fields'
-
- describe '{arg}_was?' do
- it 'returns nil when the property has not been assigned a new value' do
- service.username = 'new_username'
- service.validate
- expect(service.url_was).to be_nil
- end
-
- it 'returns initial value when the property has been assigned a different value' do
- service.url = 'http://example.com'
- service.validate
- expect(service.url_was).to eq('http://url.com')
- end
-
- it 'returns initial value when the property has been re-assigned the same value' do
- service.url = 'http://url.com'
- service.validate
- expect(service.url_was).to eq('http://url.com')
- end
- end
- end
-
- context 'when data are stored in both properties and data_fields' do
- let(:service) do
- create(:jira_service, :without_properties_callback, active: false, properties: properties).tap do |service|
- create(:jira_tracker_data, properties.merge(service: service))
- end
- end
-
- it_behaves_like 'data fields'
-
- describe '{arg}_was?' do
- it 'returns nil' do
- service.url = 'http://example.com'
- service.validate
- expect(service.url_was).to be_nil
- end
- end
- end
-end
diff --git a/spec/models/project_services/gitlab_issue_tracker_service_spec.rb b/spec/models/project_services/gitlab_issue_tracker_service_spec.rb
index 4f3736ca65b..0c4fc290a13 100644
--- a/spec/models/project_services/gitlab_issue_tracker_service_spec.rb
+++ b/spec/models/project_services/gitlab_issue_tracker_service_spec.rb
@@ -65,7 +65,7 @@ describe GitlabIssueTrackerService do
create(:gitlab_issue_tracker_service, :without_properties_callback, properties: properties)
end
- it_behaves_like 'issue tracker fields'
+ include_examples 'issue tracker fields'
end
context 'when data are stored in separated fields' do
@@ -73,7 +73,7 @@ describe GitlabIssueTrackerService do
create(:gitlab_issue_tracker_service, title: title, description: description, properties: access_params)
end
- it_behaves_like 'issue tracker fields'
+ include_examples 'issue tracker fields'
end
context 'when data are stored in both properties and separated fields' do
@@ -82,7 +82,7 @@ describe GitlabIssueTrackerService do
create(:gitlab_issue_tracker_service, :without_properties_callback, title: title, description: description, properties: properties)
end
- it_behaves_like 'issue tracker fields'
+ include_examples 'issue tracker fields'
end
context 'when no title & description are set' do
diff --git a/spec/models/project_services/issue_tracker_data_spec.rb b/spec/models/project_services/issue_tracker_data_spec.rb
index db617cf0abb..aaab654f874 100644
--- a/spec/models/project_services/issue_tracker_data_spec.rb
+++ b/spec/models/project_services/issue_tracker_data_spec.rb
@@ -8,4 +8,28 @@ describe IssueTrackerData do
describe 'Associations' do
it { is_expected.to belong_to :service }
end
+
+ describe 'Validations' do
+ subject { described_class.new(service: service) }
+
+ context 'url validations' do
+ context 'when service is inactive' do
+ it { is_expected.not_to validate_presence_of(:project_url) }
+ it { is_expected.not_to validate_presence_of(:issues_url) }
+ end
+
+ context 'when service is active' do
+ before do
+ service.update(active: true)
+ end
+
+ it_behaves_like 'issue tracker service URL attribute', :project_url
+ it_behaves_like 'issue tracker service URL attribute', :issues_url
+ it_behaves_like 'issue tracker service URL attribute', :new_issue_url
+
+ it { is_expected.to validate_presence_of(:project_url) }
+ it { is_expected.to validate_presence_of(:issues_url) }
+ end
+ end
+ end
end
diff --git a/spec/models/project_services/issue_tracker_service_spec.rb b/spec/models/project_services/issue_tracker_service_spec.rb
index f1cdee5c4a3..2fc4d69c2db 100644
--- a/spec/models/project_services/issue_tracker_service_spec.rb
+++ b/spec/models/project_services/issue_tracker_service_spec.rb
@@ -7,7 +7,7 @@ describe IssueTrackerService do
let(:project) { create :project }
describe 'only one issue tracker per project' do
- let(:service) { RedmineService.new(project: project, active: true, issue_tracker_data: build(:issue_tracker_data)) }
+ let(:service) { RedmineService.new(project: project, active: true) }
before do
create(:custom_issue_tracker_service, project: project)
diff --git a/spec/models/project_services/jira_service_spec.rb b/spec/models/project_services/jira_service_spec.rb
index a976745023b..02060699e9a 100644
--- a/spec/models/project_services/jira_service_spec.rb
+++ b/spec/models/project_services/jira_service_spec.rb
@@ -6,18 +6,10 @@ describe JiraService do
include Gitlab::Routing
include AssetsHelpers
- let(:title) { 'custom title' }
- let(:description) { 'custom description' }
- let(:url) { 'http://jira.example.com' }
- let(:api_url) { 'http://api-jira.example.com' }
- let(:username) { 'jira-username' }
- let(:password) { 'jira-password' }
- let(:transition_id) { 'test27' }
-
describe '#options' do
let(:service) do
- described_class.create(
- project: create(:project),
+ described_class.new(
+ project: build_stubbed(:project),
active: true,
username: 'username',
password: 'test',
@@ -40,6 +32,78 @@ describe JiraService do
describe 'Associations' do
it { is_expected.to belong_to :project }
it { is_expected.to have_one :service_hook }
+ it { is_expected.to allow_value(nil).for(:jira_issue_transition_id) }
+ it { is_expected.to allow_value('1,2,3').for(:jira_issue_transition_id) }
+ it { is_expected.to allow_value('1;2;3').for(:jira_issue_transition_id) }
+ it { is_expected.not_to allow_value('a,b,cd').for(:jira_issue_transition_id) }
+ end
+
+ describe 'Validations' do
+ context 'when service is active' do
+ before do
+ subject.active = true
+ end
+
+ it { is_expected.to validate_presence_of(:url) }
+ it_behaves_like 'issue tracker service URL attribute', :url
+ end
+
+ context 'when service is inactive' do
+ before do
+ subject.active = false
+ end
+
+ it { is_expected.not_to validate_presence_of(:url) }
+ it { is_expected.not_to validate_presence_of(:username) }
+ it { is_expected.not_to validate_presence_of(:password) }
+ end
+
+ context 'validating urls' do
+ let(:service) do
+ described_class.new(
+ project: create(:project),
+ active: true,
+ username: 'username',
+ password: 'test',
+ jira_issue_transition_id: 24,
+ url: 'http://jira.test.com'
+ )
+ end
+
+ it 'is valid when all fields have required values' do
+ expect(service).to be_valid
+ end
+
+ it 'is not valid when url is not a valid url' do
+ service.url = 'not valid'
+
+ expect(service).not_to be_valid
+ end
+
+ it 'is not valid when api url is not a valid url' do
+ service.api_url = 'not valid'
+
+ expect(service).not_to be_valid
+ end
+
+ it 'is not valid when username is missing' do
+ service.username = nil
+
+ expect(service).not_to be_valid
+ end
+
+ it 'is not valid when password is missing' do
+ service.password = nil
+
+ expect(service).not_to be_valid
+ end
+
+ it 'is valid when api url is a valid url' do
+ service.api_url = 'http://jira.test.com/api'
+
+ expect(service).to be_valid
+ end
+ end
end
describe '.reference_pattern' do
@@ -54,260 +118,55 @@ describe JiraService do
describe '#create' do
let(:params) do
{
- project: create(:project),
- title: 'custom title', description: 'custom description',
- url: url, api_url: api_url,
- username: username, password: password,
- jira_issue_transition_id: transition_id
+ project: create(:project), title: 'custom title', description: 'custom description'
}
end
subject { described_class.create(params) }
- it 'does not store data into properties' do
- expect(subject.properties).to be_nil
- end
-
- it 'sets title correctly' do
- service = subject
-
- expect(service.title).to eq('custom title')
+ it 'does not store title & description into properties' do
+ expect(subject.properties.keys).not_to include('title', 'description')
end
- it 'sets service data correctly' do
+ it 'sets title & description correctly' do
service = subject
expect(service.title).to eq('custom title')
expect(service.description).to eq('custom description')
end
-
- it 'stores data in data_fields correcty' do
- service = subject
-
- expect(service.jira_tracker_data.url).to eq(url)
- expect(service.jira_tracker_data.api_url).to eq(api_url)
- expect(service.jira_tracker_data.username).to eq(username)
- expect(service.jira_tracker_data.password).to eq(password)
- expect(service.jira_tracker_data.jira_issue_transition_id).to eq(transition_id)
- end
end
- # we need to make sure we are able to read both from properties and jira_tracker_data table
- # TODO: change this as part of #63084
context 'overriding properties' do
+ let(:url) { 'http://issue_tracker.example.com' }
let(:access_params) do
- { url: url, api_url: api_url, username: username, password: password,
- jira_issue_transition_id: transition_id }
- end
- let(:data_params) do
- {
- url: url, api_url: api_url,
- username: username, password: password,
- jira_issue_transition_id: transition_id
- }
- end
-
- shared_examples 'handles jira fields' do
- let(:data_params) do
- {
- url: url, api_url: api_url,
- username: username, password: password,
- jira_issue_transition_id: transition_id
- }
- end
-
- context 'reading data' do
- it 'reads data correctly' do
- expect(service.url).to eq(url)
- expect(service.api_url).to eq(api_url)
- expect(service.username).to eq(username)
- expect(service.password).to eq(password)
- expect(service.jira_issue_transition_id).to eq(transition_id)
- end
- end
-
- context '#update' do
- context 'basic update' do
- let(:new_username) { 'new_username' }
- let(:new_url) { 'http://jira-new.example.com' }
-
- before do
- service.update(username: new_username, url: new_url)
- end
-
- it 'leaves properties field emtpy' do
- # expect(service.reload.properties).to be_empty
- end
-
- it 'stores updated data in jira_tracker_data table' do
- data = service.jira_tracker_data.reload
-
- expect(data.url).to eq(new_url)
- expect(data.api_url).to eq(api_url)
- expect(data.username).to eq(new_username)
- expect(data.password).to eq(password)
- expect(data.jira_issue_transition_id).to eq(transition_id)
- end
- end
-
- context 'stored password invalidation' do
- context 'when a password was previously set' do
- context 'when only web url present' do
- let(:data_params) do
- {
- url: url, api_url: nil,
- username: username, password: password,
- jira_issue_transition_id: transition_id
- }
- end
-
- it 'resets password if url changed' do
- service
- service.url = 'http://jira_edited.example.com'
- service.save
-
- expect(service.reload.url).to eq('http://jira_edited.example.com')
- expect(service.password).to be_nil
- end
-
- it 'does not reset password if url "changed" to the same url as before' do
- service.title = 'aaaaaa'
- service.url = 'http://jira.example.com'
- service.save
-
- expect(service.reload.url).to eq('http://jira.example.com')
- expect(service.password).not_to be_nil
- end
-
- it 'resets password if url not changed but api url added' do
- service.api_url = 'http://jira_edited.example.com/rest/api/2'
- service.save
-
- expect(service.reload.api_url).to eq('http://jira_edited.example.com/rest/api/2')
- expect(service.password).to be_nil
- end
-
- it 'does not reset password if new url is set together with password, even if it\'s the same password' do
- service.url = 'http://jira_edited.example.com'
- service.password = password
- service.save
-
- expect(service.password).to eq(password)
- expect(service.url).to eq('http://jira_edited.example.com')
- end
-
- it 'resets password if url changed, even if setter called multiple times' do
- service.url = 'http://jira1.example.com/rest/api/2'
- service.url = 'http://jira1.example.com/rest/api/2'
- service.save
-
- expect(service.password).to be_nil
- end
-
- it 'does not reset password if username changed' do
- service.username = 'some_name'
- service.save
-
- expect(service.reload.password).to eq(password)
- end
-
- it 'does not reset password if password changed' do
- service.url = 'http://jira_edited.example.com'
- service.password = 'new_password'
- service.save
-
- expect(service.reload.password).to eq('new_password')
- end
-
- it 'does not reset password if the password is touched and same as before' do
- service.url = 'http://jira_edited.example.com'
- service.password = password
- service.save
-
- expect(service.reload.password).to eq(password)
- end
- end
-
- context 'when both web and api url present' do
- let(:data_params) do
- {
- url: url, api_url: 'http://jira.example.com/rest/api/2',
- username: username, password: password,
- jira_issue_transition_id: transition_id
- }
- end
-
- it 'resets password if api url changed' do
- service.api_url = 'http://jira_edited.example.com/rest/api/2'
- service.save
-
- expect(service.password).to be_nil
- end
-
- it 'does not reset password if url changed' do
- service.url = 'http://jira_edited.example.com'
- service.save
-
- expect(service.password).to eq(password)
- end
-
- it 'resets password if api url set to empty' do
- service.update(api_url: '')
-
- expect(service.reload.password).to be_nil
- end
- end
- end
-
- context 'when no password was previously set' do
- let(:data_params) do
- {
- url: url, username: username
- }
- end
-
- it 'saves password if new url is set together with password' do
- service.url = 'http://jira_edited.example.com/rest/api/2'
- service.password = 'password'
- service.save
- expect(service.reload.password).to eq('password')
- expect(service.reload.url).to eq('http://jira_edited.example.com/rest/api/2')
- end
- end
- end
- end
+ { url: url, username: 'username', password: 'password' }
end
# this will be removed as part of https://gitlab.com/gitlab-org/gitlab-ce/issues/63084
context 'when data are stored in properties' do
- let(:properties) { data_params.merge(title: title, description: description) }
- let!(:service) do
+ let(:properties) { access_params.merge(title: title, description: description) }
+ let(:service) do
create(:jira_service, :without_properties_callback, properties: properties)
end
- it_behaves_like 'issue tracker fields'
- it_behaves_like 'handles jira fields'
+ include_examples 'issue tracker fields'
end
context 'when data are stored in separated fields' do
let(:service) do
- create(:jira_service, data_params.merge(properties: {}, title: title, description: description))
+ create(:jira_service, title: title, description: description, properties: access_params)
end
- it_behaves_like 'issue tracker fields'
- it_behaves_like 'handles jira fields'
+ include_examples 'issue tracker fields'
end
context 'when data are stored in both properties and separated fields' do
- let(:properties) { data_params.merge(title: title, description: description) }
+ let(:properties) { access_params.merge(title: 'wrong title', description: 'wrong description') }
let(:service) do
- create(:jira_service, :without_properties_callback, active: false, properties: properties).tap do |service|
- create(:jira_tracker_data, data_params.merge(service: service))
- end
+ create(:jira_service, :without_properties_callback, title: title, description: description, properties: properties)
end
- it_behaves_like 'issue tracker fields'
- it_behaves_like 'handles jira fields'
+ include_examples 'issue tracker fields'
end
context 'when no title & description are set' do
@@ -551,6 +410,111 @@ describe JiraService do
end
end
+ describe 'Stored password invalidation' do
+ let(:project) { create(:project) }
+
+ context 'when a password was previously set' do
+ before do
+ @jira_service = described_class.create!(
+ project: project,
+ properties: {
+ url: 'http://jira.example.com/web',
+ username: 'mic',
+ password: 'password'
+ }
+ )
+ end
+
+ context 'when only web url present' do
+ it 'reset password if url changed' do
+ @jira_service.url = 'http://jira_edited.example.com/rest/api/2'
+ @jira_service.save
+
+ expect(@jira_service.password).to be_nil
+ end
+
+ it 'reset password if url not changed but api url added' do
+ @jira_service.api_url = 'http://jira_edited.example.com/rest/api/2'
+ @jira_service.save
+
+ expect(@jira_service.password).to be_nil
+ end
+ end
+
+ context 'when both web and api url present' do
+ before do
+ @jira_service.api_url = 'http://jira.example.com/rest/api/2'
+ @jira_service.password = 'password'
+
+ @jira_service.save
+ end
+ it 'reset password if api url changed' do
+ @jira_service.api_url = 'http://jira_edited.example.com/rest/api/2'
+ @jira_service.save
+
+ expect(@jira_service.password).to be_nil
+ end
+
+ it 'does not reset password if url changed' do
+ @jira_service.url = 'http://jira_edited.example.com/rweb'
+ @jira_service.save
+
+ expect(@jira_service.password).to eq('password')
+ end
+
+ it 'reset password if api url set to empty' do
+ @jira_service.api_url = ''
+ @jira_service.save
+
+ expect(@jira_service.password).to be_nil
+ end
+ end
+
+ it 'does not reset password if username changed' do
+ @jira_service.username = 'some_name'
+ @jira_service.save
+
+ expect(@jira_service.password).to eq('password')
+ end
+
+ it 'does not reset password if new url is set together with password, even if it\'s the same password' do
+ @jira_service.url = 'http://jira_edited.example.com/rest/api/2'
+ @jira_service.password = 'password'
+ @jira_service.save
+
+ expect(@jira_service.password).to eq('password')
+ expect(@jira_service.url).to eq('http://jira_edited.example.com/rest/api/2')
+ end
+
+ it 'resets password if url changed, even if setter called multiple times' do
+ @jira_service.url = 'http://jira1.example.com/rest/api/2'
+ @jira_service.url = 'http://jira1.example.com/rest/api/2'
+ @jira_service.save
+ expect(@jira_service.password).to be_nil
+ end
+ end
+
+ context 'when no password was previously set' do
+ before do
+ @jira_service = described_class.create(
+ project: project,
+ properties: {
+ url: 'http://jira.example.com/rest/api/2',
+ username: 'mic'
+ }
+ )
+ end
+
+ it 'saves password if new url is set together with password' do
+ @jira_service.url = 'http://jira_edited.example.com/rest/api/2'
+ @jira_service.password = 'password'
+ @jira_service.save
+ expect(@jira_service.password).to eq('password')
+ expect(@jira_service.url).to eq('http://jira_edited.example.com/rest/api/2')
+ end
+ end
+ end
+
describe 'description and title' do
let(:title) { 'Jira One' }
let(:description) { 'Jira One issue tracker' }
@@ -575,7 +539,7 @@ describe JiraService do
context 'when it is set in properties' do
it 'values from properties are returned' do
- service = create(:jira_service, :without_properties_callback, properties: properties)
+ service = create(:jira_service, properties: properties)
expect(service.title).to eq(title)
expect(service.description).to eq(description)
@@ -638,8 +602,8 @@ describe JiraService do
project = create(:project)
service = project.create_jira_service(active: true)
- expect(service.url).to eq('http://jira.sample/projects/project_a')
- expect(service.api_url).to eq('http://jira.sample/api')
+ expect(service.properties['url']).to eq('http://jira.sample/projects/project_a')
+ expect(service.properties['api_url']).to eq('http://jira.sample/api')
end
end
diff --git a/spec/models/project_services/jira_tracker_data_spec.rb b/spec/models/project_services/jira_tracker_data_spec.rb
index 6cd3eb33d9b..1b6ece8531b 100644
--- a/spec/models/project_services/jira_tracker_data_spec.rb
+++ b/spec/models/project_services/jira_tracker_data_spec.rb
@@ -8,4 +8,35 @@ describe JiraTrackerData do
describe 'Associations' do
it { is_expected.to belong_to(:service) }
end
+
+ describe 'Validations' do
+ subject { described_class.new(service: service) }
+
+ context 'jira_issue_transition_id' do
+ it { is_expected.to allow_value(nil).for(:jira_issue_transition_id) }
+ it { is_expected.to allow_value('1,2,3').for(:jira_issue_transition_id) }
+ it { is_expected.to allow_value('1;2;3').for(:jira_issue_transition_id) }
+ it { is_expected.not_to allow_value('a,b,cd').for(:jira_issue_transition_id) }
+ end
+
+ context 'url validations' do
+ context 'when service is inactive' do
+ it { is_expected.not_to validate_presence_of(:url) }
+ it { is_expected.not_to validate_presence_of(:username) }
+ it { is_expected.not_to validate_presence_of(:password) }
+ end
+
+ context 'when service is active' do
+ before do
+ service.update(active: true)
+ end
+
+ it_behaves_like 'issue tracker service URL attribute', :url
+
+ it { is_expected.to validate_presence_of(:url) }
+ it { is_expected.to validate_presence_of(:username) }
+ it { is_expected.to validate_presence_of(:password) }
+ end
+ end
+ end
end
diff --git a/spec/models/project_services/redmine_service_spec.rb b/spec/models/project_services/redmine_service_spec.rb
index 4ef4064d069..c1ee6546b12 100644
--- a/spec/models/project_services/redmine_service_spec.rb
+++ b/spec/models/project_services/redmine_service_spec.rb
@@ -9,15 +9,6 @@ describe RedmineService do
end
describe 'Validations' do
- # if redmine is set in setting the urls are set to defaults
- # therefore the validation passes as the values are not nil
- before do
- settings = {
- 'redmine' => {}
- }
- allow(Gitlab.config).to receive(:issues_tracker).and_return(settings)
- end
-
context 'when service is active' do
before do
subject.active = true
@@ -26,7 +17,6 @@ describe RedmineService do
it { is_expected.to validate_presence_of(:project_url) }
it { is_expected.to validate_presence_of(:issues_url) }
it { is_expected.to validate_presence_of(:new_issue_url) }
-
it_behaves_like 'issue tracker service URL attribute', :project_url
it_behaves_like 'issue tracker service URL attribute', :issues_url
it_behaves_like 'issue tracker service URL attribute', :new_issue_url
@@ -64,7 +54,7 @@ describe RedmineService do
create(:redmine_service, :without_properties_callback, properties: properties)
end
- it_behaves_like 'issue tracker fields'
+ include_examples 'issue tracker fields'
end
context 'when data are stored in separated fields' do
@@ -72,7 +62,7 @@ describe RedmineService do
create(:redmine_service, title: title, description: description, properties: access_params)
end
- it_behaves_like 'issue tracker fields'
+ include_examples 'issue tracker fields'
end
context 'when data are stored in both properties and separated fields' do
@@ -81,7 +71,7 @@ describe RedmineService do
create(:redmine_service, :without_properties_callback, title: title, description: description, properties: properties)
end
- it_behaves_like 'issue tracker fields'
+ include_examples 'issue tracker fields'
end
context 'when no title & description are set' do
diff --git a/spec/models/project_services/youtrack_service_spec.rb b/spec/models/project_services/youtrack_service_spec.rb
index eff9f451b1a..c48bf487af0 100644
--- a/spec/models/project_services/youtrack_service_spec.rb
+++ b/spec/models/project_services/youtrack_service_spec.rb
@@ -16,7 +16,6 @@ describe YoutrackService do
it { is_expected.to validate_presence_of(:project_url) }
it { is_expected.to validate_presence_of(:issues_url) }
-
it_behaves_like 'issue tracker service URL attribute', :project_url
it_behaves_like 'issue tracker service URL attribute', :issues_url
end
@@ -52,7 +51,7 @@ describe YoutrackService do
create(:youtrack_service, :without_properties_callback, properties: properties)
end
- it_behaves_like 'issue tracker fields'
+ include_examples 'issue tracker fields'
end
context 'when data are stored in separated fields' do
@@ -60,7 +59,7 @@ describe YoutrackService do
create(:youtrack_service, title: title, description: description, properties: access_params)
end
- it_behaves_like 'issue tracker fields'
+ include_examples 'issue tracker fields'
end
context 'when data are stored in both properties and separated fields' do
@@ -69,7 +68,7 @@ describe YoutrackService do
create(:youtrack_service, :without_properties_callback, title: title, description: description, properties: properties)
end
- it_behaves_like 'issue tracker fields'
+ include_examples 'issue tracker fields'
end
context 'when no title & description are set' do
diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb
index 67f64822184..5b4b9c516a0 100644
--- a/spec/models/project_spec.rb
+++ b/spec/models/project_spec.rb
@@ -2027,43 +2027,6 @@ describe Project do
end
end
- describe '#latest_pipeline_for_ref' do
- let(:project) { create(:project, :repository) }
- let(:second_branch) { project.repository.branches[2] }
-
- let!(:pipeline_for_default_branch) do
- create(:ci_empty_pipeline, project: project, sha: project.commit.id,
- ref: project.default_branch)
- end
- let!(:pipeline_for_second_branch) do
- create(:ci_empty_pipeline, project: project, sha: second_branch.target,
- ref: second_branch.name)
- end
-
- before do
- create(:ci_empty_pipeline, project: project, sha: project.commit.parent.id,
- ref: project.default_branch)
- end
-
- context 'default repository branch' do
- subject { project.latest_pipeline_for_ref(project.default_branch) }
-
- it { is_expected.to eq(pipeline_for_default_branch) }
- end
-
- context 'provided ref' do
- subject { project.latest_pipeline_for_ref(second_branch.name) }
-
- it { is_expected.to eq(pipeline_for_second_branch) }
- end
-
- context 'bad ref' do
- subject { project.latest_pipeline_for_ref(SecureRandom.uuid) }
-
- it { is_expected.to be_nil }
- end
- end
-
describe '#latest_successful_build_for_sha' do
let(:project) { create(:project, :repository) }
let(:pipeline) { create_pipeline(project) }
diff --git a/spec/models/release_spec.rb b/spec/models/release_spec.rb
index 8714c67f29d..c690390e24d 100644
--- a/spec/models/release_spec.rb
+++ b/spec/models/release_spec.rb
@@ -13,8 +13,7 @@ RSpec.describe Release do
it { is_expected.to belong_to(:project) }
it { is_expected.to belong_to(:author).class_name('User') }
it { is_expected.to have_many(:links).class_name('Releases::Link') }
- it { is_expected.to have_many(:milestones) }
- it { is_expected.to have_many(:milestone_releases) }
+ it { is_expected.to have_one(:milestone) }
end
describe 'validation' do
@@ -39,15 +38,15 @@ RSpec.describe Release do
context 'when a release is tied to a milestone for another project' do
it 'creates a validation error' do
- milestone = build(:milestone, project: create(:project))
- expect { release.milestones << milestone }.to raise_error
+ release.milestone = build(:milestone, project: create(:project))
+ expect(release).not_to be_valid
end
end
context 'when a release is tied to a milestone linked to the same project' do
- it 'successfully links this release to this milestone' do
- milestone = build(:milestone, project: project)
- expect { release.milestones << milestone }.to change { MilestoneRelease.count }.by(1)
+ it 'is valid' do
+ release.milestone = build(:milestone, project: project)
+ expect(release).to be_valid
end
end
end
diff --git a/spec/models/service_spec.rb b/spec/models/service_spec.rb
index d96e1398677..0797b9a9d83 100644
--- a/spec/models/service_spec.rb
+++ b/spec/models/service_spec.rb
@@ -257,8 +257,8 @@ describe Service do
expect(service.title).to eq('random title')
end
- it 'sets data correctly' do
- expect(service.data_fields.project_url).to eq('http://gitlab.example.com')
+ it 'creates the properties' do
+ expect(service.properties).to eq({ "project_url" => "http://gitlab.example.com" })
end
end
diff --git a/spec/requests/api/groups_spec.rb b/spec/requests/api/groups_spec.rb
index b3acf531ccb..0893dcb39b6 100644
--- a/spec/requests/api/groups_spec.rb
+++ b/spec/requests/api/groups_spec.rb
@@ -59,16 +59,6 @@ describe API::Groups do
.to satisfy_one { |group| group['name'] == group1.name }
end
- it "does not include runners_token information" do
- get api("/groups", user1)
-
- expect(response).to have_gitlab_http_status(200)
- expect(response).to include_pagination_headers
- expect(json_response).to be_an Array
- expect(json_response.length).to eq(1)
- expect(json_response.first).not_to include('runners_token')
- end
-
it "does not include statistics" do
get api("/groups", user1), params: { statistics: true }
@@ -89,16 +79,6 @@ describe API::Groups do
expect(json_response.length).to eq(2)
end
- it "does not include runners_token information" do
- get api("/groups", admin)
-
- expect(response).to have_gitlab_http_status(200)
- expect(response).to include_pagination_headers
- expect(json_response).to be_an Array
- expect(json_response.length).to eq(2)
- expect(json_response.first).not_to include('runners_token')
- end
-
it "does not include statistics by default" do
get api("/groups", admin)
@@ -312,7 +292,6 @@ describe API::Groups do
get api("/groups/#{group1.id}")
expect(response).to have_gitlab_http_status(200)
- expect(json_response).not_to include('runners_token')
end
it 'returns only public projects in the group' do
@@ -371,22 +350,6 @@ describe API::Groups do
expect(response).to have_gitlab_http_status(200)
expect(json_response['projects']).to be_nil
expect(json_response['shared_projects']).to be_nil
- expect(json_response).not_to include('runners_token')
- end
-
- it "doesn't return runners_token if the user is not the owner of the group" do
- get api("/groups/#{group1.id}", user3)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).not_to include('runners_token')
- end
-
- it "returns runners_token if the user is the owner of the group" do
- group1.add_owner(user3)
- get api("/groups/#{group1.id}", user3)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to include('runners_token')
end
it "does not return a non existing group" do
@@ -444,13 +407,6 @@ describe API::Groups do
expect(json_response['name']).to eq(group2.name)
end
- it "returns information of the runners_token for the group" do
- get api("/groups/#{group2.id}", admin)
-
- expect(response).to have_gitlab_http_status(200)
- expect(json_response).to include('runners_token')
- end
-
it "does not return a non existing group" do
get api("/groups/1328", admin)
diff --git a/spec/requests/api/issues/get_group_issues_spec.rb b/spec/requests/api/issues/get_group_issues_spec.rb
index 3ee08758f99..c487471e4a1 100644
--- a/spec/requests/api/issues/get_group_issues_spec.rb
+++ b/spec/requests/api/issues/get_group_issues_spec.rb
@@ -437,21 +437,17 @@ describe API::Issues do
end
context 'with labeled issues' do
- let(:group_issue2) { create :issue, project: group_project }
let(:label_b) { create(:label, title: 'foo', project: group_project) }
let(:label_c) { create(:label, title: 'bar', project: group_project) }
before do
- create(:label_link, label: group_label, target: group_issue2)
create(:label_link, label: label_b, target: group_issue)
- create(:label_link, label: label_b, target: group_issue2)
create(:label_link, label: label_c, target: group_issue)
get api(base_url, user), params: params
end
let(:issue) { group_issue }
- let(:issue2) { group_issue2 }
let(:label) { group_label }
it_behaves_like 'labeled issues with labels and label_name params'
diff --git a/spec/requests/api/issues/get_project_issues_spec.rb b/spec/requests/api/issues/get_project_issues_spec.rb
index c10f5b2bd58..b7aa3f93451 100644
--- a/spec/requests/api/issues/get_project_issues_spec.rb
+++ b/spec/requests/api/issues/get_project_issues_spec.rb
@@ -283,14 +283,11 @@ describe API::Issues do
end
context 'with labeled issues' do
- let(:issue2) { create :issue, project: project }
let(:label_b) { create(:label, title: 'foo', project: project) }
let(:label_c) { create(:label, title: 'bar', project: project) }
before do
- create(:label_link, label: label, target: issue2)
create(:label_link, label: label_b, target: issue)
- create(:label_link, label: label_b, target: issue2)
create(:label_link, label: label_c, target: issue)
get api('/issues', user), params: params
diff --git a/spec/requests/api/issues/issues_spec.rb b/spec/requests/api/issues/issues_spec.rb
index 61a94b682be..f19c2dcc6fe 100644
--- a/spec/requests/api/issues/issues_spec.rb
+++ b/spec/requests/api/issues/issues_spec.rb
@@ -427,12 +427,9 @@ describe API::Issues do
context 'with labeled issues' do
let(:label_b) { create(:label, title: 'foo', project: project) }
let(:label_c) { create(:label, title: 'bar', project: project) }
- let(:issue2) { create(:issue, author: user, project: project) }
before do
- create(:label_link, label: label, target: issue2)
create(:label_link, label: label_b, target: issue)
- create(:label_link, label: label_b, target: issue2)
create(:label_link, label: label_c, target: issue)
get api('/issues', user), params: params
@@ -500,74 +497,46 @@ describe API::Issues do
end
end
- context 'filter by milestone' do
- it 'returns an empty array if no issue matches milestone' do
- get api("/issues?milestone=#{empty_milestone.title}", user)
+ it 'returns an empty array if no issue matches milestone' do
+ get api("/issues?milestone=#{empty_milestone.title}", user)
- expect_paginated_array_response([])
- end
-
- it 'returns an empty array if milestone does not exist' do
- get api('/issues?milestone=foo', user)
-
- expect_paginated_array_response([])
- end
-
- it 'returns an array of issues in given milestone' do
- get api("/issues?milestone=#{milestone.title}", user)
-
- expect_paginated_array_response([issue.id, closed_issue.id])
- end
-
- it 'returns an array of issues in given milestone_title param' do
- get api("/issues?milestone_title=#{milestone.title}", user)
-
- expect_paginated_array_response([issue.id, closed_issue.id])
- end
-
- it 'returns an array of issues matching state in milestone' do
- get api("/issues?milestone=#{milestone.title}&state=closed", user)
-
- expect_paginated_array_response(closed_issue.id)
- end
+ expect_paginated_array_response([])
+ end
- it 'returns an array of issues with no milestone' do
- get api("/issues?milestone=#{no_milestone_title}", author)
+ it 'returns an empty array if milestone does not exist' do
+ get api('/issues?milestone=foo', user)
- expect_paginated_array_response(confidential_issue.id)
- end
+ expect_paginated_array_response([])
+ end
- it 'returns an array of issues with no milestone using milestone_title param' do
- get api("/issues?milestone_title=#{no_milestone_title}", author)
+ it 'returns an array of issues in given milestone' do
+ get api("/issues?milestone=#{milestone.title}", user)
- expect_paginated_array_response(confidential_issue.id)
- end
+ expect_paginated_array_response([issue.id, closed_issue.id])
+ end
- context 'negated' do
- it 'returns all issues if milestone does not exist' do
- get api('/issues?not[milestone]=foo', user)
+ it 'returns an array of issues in given milestone_title param' do
+ get api("/issues?milestone_title=#{milestone.title}", user)
- expect_paginated_array_response([issue.id, closed_issue.id])
- end
+ expect_paginated_array_response([issue.id, closed_issue.id])
+ end
- it 'returns all issues that do not belong to a milestone but have a milestone' do
- get api("/issues?not[milestone]=#{empty_milestone.title}", user)
+ it 'returns an array of issues matching state in milestone' do
+ get api("/issues?milestone=#{milestone.title}&state=closed", user)
- expect_paginated_array_response([issue.id, closed_issue.id])
- end
+ expect_paginated_array_response(closed_issue.id)
+ end
- it 'returns an array of issues with any milestone' do
- get api("/issues?not[milestone]=#{no_milestone_title}", user)
+ it 'returns an array of issues with no milestone' do
+ get api("/issues?milestone=#{no_milestone_title}", author)
- expect_paginated_array_response([issue.id, closed_issue.id])
- end
+ expect_paginated_array_response(confidential_issue.id)
+ end
- it 'returns an array of issues matching state not in milestone' do
- get api("/issues?not[milestone]=#{empty_milestone.title}&state=closed", user)
+ it 'returns an array of issues with no milestone using milestone_title param' do
+ get api("/issues?milestone_title=#{no_milestone_title}", author)
- expect_paginated_array_response(closed_issue.id)
- end
- end
+ expect_paginated_array_response(confidential_issue.id)
end
it 'returns an array of issues found by iids' do
diff --git a/spec/requests/api/pipelines_spec.rb b/spec/requests/api/pipelines_spec.rb
index 3a3f0e970a4..174b3214d13 100644
--- a/spec/requests/api/pipelines_spec.rb
+++ b/spec/requests/api/pipelines_spec.rb
@@ -459,54 +459,6 @@ describe API::Pipelines do
end
end
- describe 'GET /projects/:id/pipelines/latest' do
- context 'authorized user' do
- let(:second_branch) { project.repository.branches[2] }
-
- let!(:second_pipeline) do
- create(:ci_empty_pipeline, project: project, sha: second_branch.target,
- ref: second_branch.name, user: user)
- end
-
- before do
- create(:ci_empty_pipeline, project: project, sha: project.commit.parent.id,
- ref: project.default_branch, user: user)
- end
-
- context 'default repository branch' do
- it 'gets the latest pipleine' do
- get api("/projects/#{project.id}/pipelines/latest", user)
-
- expect(response).to have_gitlab_http_status(200)
- expect(response).to match_response_schema('public_api/v4/pipeline/detail')
- expect(json_response['ref']).to eq(project.default_branch)
- expect(json_response['sha']).to eq(project.commit.id)
- end
- end
-
- context 'ref parameter' do
- it 'gets the latest pipleine' do
- get api("/projects/#{project.id}/pipelines/latest", user), params: { ref: second_branch.name }
-
- expect(response).to have_gitlab_http_status(200)
- expect(response).to match_response_schema('public_api/v4/pipeline/detail')
- expect(json_response['ref']).to eq(second_branch.name)
- expect(json_response['sha']).to eq(second_branch.target)
- end
- end
- end
-
- context 'unauthorized user' do
- it 'does not return a project pipeline' do
- get api("/projects/#{project.id}/pipelines/#{pipeline.id}", non_member)
-
- expect(response).to have_gitlab_http_status(404)
- expect(json_response['message']).to eq '404 Project Not Found'
- expect(json_response['id']).to be nil
- end
- end
- end
-
describe 'GET /projects/:id/pipelines/:pipeline_id/variables' do
subject { get api("/projects/#{project.id}/pipelines/#{pipeline.id}/variables", api_user) }
diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb
index 2d8ef9c06dc..550c7d135a6 100644
--- a/spec/requests/api/projects_spec.rb
+++ b/spec/requests/api/projects_spec.rb
@@ -1,3 +1,4 @@
+# -*- coding: utf-8 -*-
require 'spec_helper'
shared_examples 'languages and percentages JSON response' do
@@ -630,33 +631,6 @@ describe API::Projects do
expect(project.project_feature.wiki_access_level).to eq(ProjectFeature::DISABLED)
end
- it 'creates a project using a template' do
- expect { post api('/projects', user), params: { template_name: 'rails', name: 'rails-test' } }
- .to change { Project.count }.by(1)
-
- expect(response).to have_gitlab_http_status(201)
-
- project = Project.find(json_response['id'])
- expect(project).to be_saved
- expect(project.import_type).to eq('gitlab_project')
- end
-
- it 'returns 400 for an invalid template' do
- expect { post api('/projects', user), params: { template_name: 'unknown', name: 'rails-test' } }
- .not_to change { Project.count }
-
- expect(response).to have_gitlab_http_status(400)
- expect(json_response['message']['template_name']).to eq(["'unknown' is unknown or invalid"])
- end
-
- it 'disallows creating a project with an import_url and template' do
- project_params = { import_url: 'http://example.com', template_name: 'rails', name: 'rails-test' }
- expect { post api('/projects', user), params: project_params }
- .not_to change { Project.count }
-
- expect(response).to have_gitlab_http_status(400)
- end
-
it 'sets a project as public' do
project = attributes_for(:project, visibility: 'public')
@@ -893,7 +867,7 @@ describe API::Projects do
expect { post api("/projects/user/#{user.id}", admin), params: { name: 'Foo Project' } }.to change { Project.count }.by(1)
expect(response).to have_gitlab_http_status(201)
- project = Project.find(json_response['id'])
+ project = Project.last
expect(project.name).to eq('Foo Project')
expect(project.path).to eq('foo-project')
@@ -904,7 +878,7 @@ describe API::Projects do
.to change { Project.count }.by(1)
expect(response).to have_gitlab_http_status(201)
- project = Project.find(json_response['id'])
+ project = Project.last
expect(project.name).to eq('Foo Project')
expect(project.path).to eq('path-project-Foo')
diff --git a/spec/requests/api/services_spec.rb b/spec/requests/api/services_spec.rb
index 7153fcc99d7..76a70ab6e9e 100644
--- a/spec/requests/api/services_spec.rb
+++ b/spec/requests/api/services_spec.rb
@@ -100,15 +100,9 @@ describe API::Services do
expect(json_response['properties'].keys).to match_array(service_instance.api_field_names)
end
- it "returns empty hash if properties and data fields are empty" do
+ it "returns empty hash if properties are empty" do
# deprecated services are not valid for update
initialized_service.update_attribute(:properties, {})
-
- if initialized_service.data_fields_present?
- initialized_service.data_fields.destroy
- initialized_service.reload
- end
-
get api("/projects/#{project.id}/services/#{dashed_service}", user)
expect(response).to have_gitlab_http_status(200)
diff --git a/spec/requests/projects/merge_requests_discussions_spec.rb b/spec/requests/projects/merge_requests_discussions_spec.rb
deleted file mode 100644
index 5945561aa7b..00000000000
--- a/spec/requests/projects/merge_requests_discussions_spec.rb
+++ /dev/null
@@ -1,52 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-describe 'merge requests discussions' do
- # Further tests can be found at merge_requests_controller_spec.rb
- describe 'GET /:namespace/:project/merge_requests/:iid/discussions' do
- let(:project) { create(:project, :repository) }
- let(:user) { project.owner }
- let(:merge_request) { create(:merge_request_with_diffs, target_project: project, source_project: project) }
-
- before do
- project.add_developer(user)
- login_as(user)
- end
-
- def send_request
- get discussions_namespace_project_merge_request_path(namespace_id: project.namespace, project_id: project, id: merge_request.iid)
- end
-
- it 'returns 200' do
- send_request
-
- expect(response.status).to eq(200)
- end
-
- # https://docs.gitlab.com/ee/development/query_recorder.html#use-request-specs-instead-of-controller-specs
- it 'avoids N+1 DB queries', :request_store do
- control = ActiveRecord::QueryRecorder.new { send_request }
-
- create(:diff_note_on_merge_request, noteable: merge_request,
- project: merge_request.project)
-
- expect do
- send_request
- end.not_to exceed_query_limit(control)
- end
-
- it 'limits Gitaly queries', :request_store do
- Gitlab::GitalyClient.allow_n_plus_1_calls do
- create_list(:diff_note_on_merge_request, 7, noteable: merge_request,
- project: merge_request.project)
- end
-
- # The creations above write into the Gitaly counts
- Gitlab::GitalyClient.reset_counts
-
- expect { send_request }
- .to change { Gitlab::GitalyClient.get_request_count }.by_at_most(4)
- end
- end
-end
diff --git a/spec/services/ci/create_pipeline_service_spec.rb b/spec/services/ci/create_pipeline_service_spec.rb
index 1a5fdac1c95..4cd2a12e272 100644
--- a/spec/services/ci/create_pipeline_service_spec.rb
+++ b/spec/services/ci/create_pipeline_service_spec.rb
@@ -766,22 +766,6 @@ describe Ci::CreatePipelineService do
end
end
- context 'with timeout' do
- context 'when builds with custom timeouts are configured' do
- before do
- config = YAML.dump(rspec: { script: 'rspec', timeout: '2m 3s' })
- stub_ci_pipeline_yaml_file(config)
- end
-
- it 'correctly creates builds with custom timeout value configured' do
- pipeline = execute_service
-
- expect(pipeline).to be_persisted
- expect(pipeline.builds.find_by(name: 'rspec').options[:job_timeout]).to eq 123
- end
- end
- end
-
shared_examples 'when ref is protected' do
let(:user) { create(:user) }
diff --git a/spec/services/issues/update_service_spec.rb b/spec/services/issues/update_service_spec.rb
index 55254b61ac8..fd9a63b79cc 100644
--- a/spec/services/issues/update_service_spec.rb
+++ b/spec/services/issues/update_service_spec.rb
@@ -1,3 +1,4 @@
+# coding: utf-8
# frozen_string_literal: true
require 'spec_helper'
diff --git a/spec/services/milestones/destroy_service_spec.rb b/spec/services/milestones/destroy_service_spec.rb
index 4f16421c39f..ff1e1256166 100644
--- a/spec/services/milestones/destroy_service_spec.rb
+++ b/spec/services/milestones/destroy_service_spec.rb
@@ -72,7 +72,7 @@ describe Milestones::DestroyService do
:release,
tag: 'v1.0',
project: project,
- milestones: [milestone]
+ milestone: milestone
)
expect { service.execute(milestone) }.not_to change { Release.count }
diff --git a/spec/services/projects/create_from_template_service_spec.rb b/spec/services/projects/create_from_template_service_spec.rb
index 0b4772e8f02..6c244d23877 100644
--- a/spec/services/projects/create_from_template_service_spec.rb
+++ b/spec/services/projects/create_from_template_service_spec.rb
@@ -25,7 +25,7 @@ describe Projects::CreateFromTemplateService do
subject.execute
end
- it 'returns the project that is created' do
+ it 'returns the project thats created' do
project = subject.execute
expect(project).to be_saved
@@ -37,7 +37,7 @@ describe Projects::CreateFromTemplateService do
let(:project) { subject.execute }
before do
- expect(project).not_to be_saved
+ expect(project).to be_saved
end
it 'does not set import set import type' do
diff --git a/spec/services/releases/create_service_spec.rb b/spec/services/releases/create_service_spec.rb
index b624b9475e3..5c9d6537df1 100644
--- a/spec/services/releases/create_service_spec.rb
+++ b/spec/services/releases/create_service_spec.rb
@@ -75,12 +75,10 @@ describe Releases::CreateService do
context 'when a passed-in milestone does not exist for this project' do
it 'raises an error saying the milestone is inexistent' do
- inexistent_milestone_tag = 'v111.0'
- service = described_class.new(project, user, params.merge!({ milestones: [inexistent_milestone_tag] }))
+ service = described_class.new(project, user, params.merge!({ milestone: 'v111.0' }))
result = service.execute
-
expect(result[:status]).to eq(:error)
- expect(result[:message]).to eq("Milestone(s) not found: #{inexistent_milestone_tag}")
+ expect(result[:message]).to eq('Milestone does not exist')
end
end
end
@@ -95,10 +93,10 @@ describe Releases::CreateService do
context 'when existing milestone is passed in' do
let(:title) { 'v1.0' }
let(:milestone) { create(:milestone, :active, project: project, title: title) }
- let(:params_with_milestone) { params.merge!({ milestones: [title] }) }
- let(:service) { described_class.new(milestone.project, user, params_with_milestone) }
+ let(:params_with_milestone) { params.merge!({ milestone: title }) }
it 'creates a release and ties this milestone to it' do
+ service = described_class.new(milestone.project, user, params_with_milestone)
result = service.execute
expect(project.releases.count).to eq(1)
@@ -106,66 +104,29 @@ describe Releases::CreateService do
release = project.releases.last
- expect(release.milestones).to match_array([milestone])
+ expect(release.milestone).to eq(milestone)
end
context 'when another release was previously created with that same milestone linked' do
it 'also creates another release tied to that same milestone' do
- other_release = create(:release, milestones: [milestone], project: project, tag: 'v1.0')
+ other_release = create(:release, milestone: milestone, project: project, tag: 'v1.0')
+ service = described_class.new(milestone.project, user, params_with_milestone)
service.execute
release = project.releases.last
- expect(release.milestones).to match_array([milestone])
- expect(other_release.milestones).to match_array([milestone])
+ expect(release.milestone).to eq(milestone)
+ expect(other_release.milestone).to eq(milestone)
expect(release.id).not_to eq(other_release.id)
end
end
end
- context 'when multiple existing milestone titles are passed in' do
- let(:title_1) { 'v1.0' }
- let(:title_2) { 'v1.0-rc' }
- let!(:milestone_1) { create(:milestone, :active, project: project, title: title_1) }
- let!(:milestone_2) { create(:milestone, :active, project: project, title: title_2) }
- let!(:params_with_milestones) { params.merge!({ milestones: [title_1, title_2] }) }
-
- it 'creates a release and ties it to these milestones' do
- described_class.new(project, user, params_with_milestones).execute
- release = project.releases.last
-
- expect(release.milestones.map(&:title)).to include(title_1, title_2)
- end
- end
-
- context 'when multiple miletone titles are passed in but one of them does not exist' do
- let(:title) { 'v1.0' }
- let(:inexistent_title) { 'v111.0' }
- let!(:milestone) { create(:milestone, :active, project: project, title: title) }
- let!(:params_with_milestones) { params.merge!({ milestones: [title, inexistent_title] }) }
- let(:service) { described_class.new(milestone.project, user, params_with_milestones) }
-
- it 'raises an error' do
- result = service.execute
-
- expect(result[:status]).to eq(:error)
- expect(result[:message]).to eq("Milestone(s) not found: #{inexistent_title}")
- end
-
- it 'does not create any release' do
- expect do
- service.execute
- end.not_to change(Release, :count)
- end
- end
-
context 'when no milestone is passed in' do
it 'creates a release without a milestone tied to it' do
- expect(params.key? :milestones).to be_falsey
-
+ expect(params.key? :milestone).to be_falsey
service.execute
release = project.releases.last
-
- expect(release.milestones).to be_empty
+ expect(release.milestone).to be_nil
end
it 'does not create any new MilestoneRelease object' do
@@ -175,11 +136,10 @@ describe Releases::CreateService do
context 'when an empty value is passed as a milestone' do
it 'creates a release without a milestone tied to it' do
- service = described_class.new(project, user, params.merge!({ milestones: [] }))
+ service = described_class.new(project, user, params.merge!({ milestone: '' }))
service.execute
release = project.releases.last
-
- expect(release.milestones).to be_empty
+ expect(release.milestone).to be_nil
end
end
end
diff --git a/spec/services/releases/destroy_service_spec.rb b/spec/services/releases/destroy_service_spec.rb
index 9d027767cd2..c3172e5edbc 100644
--- a/spec/services/releases/destroy_service_spec.rb
+++ b/spec/services/releases/destroy_service_spec.rb
@@ -60,7 +60,7 @@ describe Releases::DestroyService do
context 'when a milestone is tied to the release' do
let!(:milestone) { create(:milestone, :active, project: project, title: 'v1.0') }
- let!(:release) { create(:release, milestones: [milestone], project: project, tag: tag) }
+ let!(:release) { create(:release, milestone: milestone, project: project, tag: tag) }
it 'destroys the release but leave the milestone intact' do
expect { subject }.not_to change { Milestone.count }
diff --git a/spec/services/releases/update_service_spec.rb b/spec/services/releases/update_service_spec.rb
index 178bac3574f..944f3d8c9ad 100644
--- a/spec/services/releases/update_service_spec.rb
+++ b/spec/services/releases/update_service_spec.rb
@@ -50,60 +50,39 @@ describe Releases::UpdateService do
end
context 'when a milestone is passed in' do
+ let(:old_title) { 'v1.0' }
let(:new_title) { 'v2.0' }
- let(:milestone) { create(:milestone, project: project, title: 'v1.0') }
+ let(:milestone) { create(:milestone, project: project, title: old_title) }
let(:new_milestone) { create(:milestone, project: project, title: new_title) }
- let(:params_with_milestone) { params.merge!({ milestones: [new_title] }) }
- let(:service) { described_class.new(new_milestone.project, user, params_with_milestone) }
+ let(:params_with_milestone) { params.merge!({ milestone: new_title }) }
before do
- release.milestones << milestone
+ release.milestone = milestone
+ release.save!
- service.execute
+ described_class.new(new_milestone.project, user, params_with_milestone).execute
release.reload
end
it 'updates the related milestone accordingly' do
- expect(release.milestones.first.title).to eq(new_title)
+ expect(release.milestone.title).to eq(new_title)
end
end
context "when an 'empty' milestone is passed in" do
let(:milestone) { create(:milestone, project: project, title: 'v1.0') }
- let(:params_with_empty_milestone) { params.merge!({ milestones: [] }) }
+ let(:params_with_empty_milestone) { params.merge!({ milestone: '' }) }
before do
- release.milestones << milestone
+ release.milestone = milestone
+ release.save!
- service.params = params_with_empty_milestone
- service.execute
+ described_class.new(milestone.project, user, params_with_empty_milestone).execute
release.reload
end
it 'removes the old milestone and does not associate any new milestone' do
- expect(release.milestones).not_to be_present
- end
- end
-
- context "when multiple new milestones are passed in" do
- let(:new_title_1) { 'v2.0' }
- let(:new_title_2) { 'v2.0-rc' }
- let(:milestone) { create(:milestone, project: project, title: 'v1.0') }
- let(:params_with_milestones) { params.merge!({ milestones: [new_title_1, new_title_2] }) }
- let(:service) { described_class.new(project, user, params_with_milestones) }
-
- before do
- create(:milestone, project: project, title: new_title_1)
- create(:milestone, project: project, title: new_title_2)
- release.milestones << milestone
-
- service.execute
- release.reload
- end
-
- it 'removes the old milestone and update the release with the new ones' do
- milestone_titles = release.milestones.map(&:title)
- expect(milestone_titles).to match_array([new_title_1, new_title_2])
+ expect(release.milestone).to be_nil
end
end
end
diff --git a/spec/services/service_response_spec.rb b/spec/services/service_response_spec.rb
index a6567f52c6f..e790d272e61 100644
--- a/spec/services/service_response_spec.rb
+++ b/spec/services/service_response_spec.rb
@@ -23,20 +23,6 @@ describe ServiceResponse do
expect(response).to be_success
expect(response.payload).to eq(good: 'orange')
end
-
- it 'creates a successful response with default HTTP status' do
- response = described_class.success
-
- expect(response).to be_success
- expect(response.http_status).to eq(:ok)
- end
-
- it 'creates a successful response with custom HTTP status' do
- response = described_class.success(http_status: 204)
-
- expect(response).to be_success
- expect(response.http_status).to eq(204)
- end
end
describe '.error' do
diff --git a/spec/support/helpers/jira_service_helper.rb b/spec/support/helpers/jira_service_helper.rb
index c23a8d52c84..57c33c81ea3 100644
--- a/spec/support/helpers/jira_service_helper.rb
+++ b/spec/support/helpers/jira_service_helper.rb
@@ -5,16 +5,16 @@ module JiraServiceHelper
JIRA_API = JIRA_URL + "/rest/api/2"
def jira_service_settings
- title = "Jira tracker"
- url = JIRA_URL
- username = 'jira-user'
- password = 'my-secret-password'
- jira_issue_transition_id = '1'
+ properties = {
+ title: "Jira tracker",
+ url: JIRA_URL,
+ username: 'jira-user',
+ password: 'my-secret-password',
+ project_key: "JIRA",
+ jira_issue_transition_id: '1'
+ }
- jira_tracker.update(
- title: title, url: url, username: username, password: password,
- jira_issue_transition_id: jira_issue_transition_id, active: true
- )
+ jira_tracker.update(properties: properties, active: true)
end
def jira_issue_comments
diff --git a/spec/support/shared_contexts/finders/issues_finder_shared_contexts.rb b/spec/support/shared_contexts/finders/issues_finder_shared_contexts.rb
index 6c96b18d834..26ab6fbd400 100644
--- a/spec/support/shared_contexts/finders/issues_finder_shared_contexts.rb
+++ b/spec/support/shared_contexts/finders/issues_finder_shared_contexts.rb
@@ -12,7 +12,6 @@ RSpec.shared_context 'IssuesFinder context' do
set(:project3) { create(:project, group: subgroup) }
set(:milestone) { create(:milestone, project: project1) }
set(:label) { create(:label, project: project2) }
- set(:label2) { create(:label, project: project2) }
set(:issue1) { create(:issue, author: user, assignees: [user], project: project1, milestone: milestone, title: 'gitlab', created_at: 1.week.ago, updated_at: 1.week.ago) }
set(:issue2) { create(:issue, author: user, assignees: [user], project: project2, description: 'gitlab', created_at: 1.week.from_now, updated_at: 1.week.from_now) }
set(:issue3) { create(:issue, author: user2, assignees: [user2], project: project2, title: 'tanuki', description: 'tanuki', created_at: 2.weeks.from_now, updated_at: 2.weeks.from_now) }
@@ -25,7 +24,6 @@ end
RSpec.shared_context 'IssuesFinder#execute context' do
let!(:closed_issue) { create(:issue, author: user2, assignees: [user2], project: project2, state: 'closed') }
let!(:label_link) { create(:label_link, label: label, target: issue2) }
- let!(:label_link2) { create(:label_link, label: label2, target: issue3) }
let(:search_user) { user }
let(:params) { {} }
let(:issues) { described_class.new(search_user, params.reverse_merge(scope: scope, state: 'opened')).execute }
diff --git a/spec/support/shared_examples/controllers/application_settings_shared_examples.rb b/spec/support/shared_examples/controllers/application_settings_shared_examples.rb
deleted file mode 100644
index 9619451cd14..00000000000
--- a/spec/support/shared_examples/controllers/application_settings_shared_examples.rb
+++ /dev/null
@@ -1,26 +0,0 @@
-# frozen_string_literal: true
-
-shared_examples 'renders correct panels' do
- it 'renders correct action on error' do
- expect_next_instance_of(ApplicationSettings::UpdateService) do |service|
- allow(service).to receive(:execute).and_return(false)
- end
-
- patch action, params: { application_setting: { unused_param: true } }
-
- expect(subject).to render_template(action)
- end
-
- it 'redirects to same panel on success' do
- expect_next_instance_of(ApplicationSettings::UpdateService) do |service|
- allow(service).to receive(:execute).and_return(true)
- end
-
- referer_path = public_send("#{action}_admin_application_settings_path")
- request.env["HTTP_REFERER"] = referer_path
-
- patch action, params: { application_setting: { unused_param: true } }
-
- expect(subject).to redirect_to(referer_path)
- end
-end
diff --git a/spec/support/shared_examples/finders/assignees_filter_shared_examples.rb b/spec/support/shared_examples/finders/assignees_filter_shared_examples.rb
index f1df1052ef2..a931c4df99f 100644
--- a/spec/support/shared_examples/finders/assignees_filter_shared_examples.rb
+++ b/spec/support/shared_examples/finders/assignees_filter_shared_examples.rb
@@ -6,24 +6,12 @@ shared_examples 'assignee ID filter' do
end
end
-shared_examples 'assignee NOT ID filter' do
- it 'returns issuables not assigned to that user' do
- expect(issuables).to contain_exactly(*expected_issuables)
- end
-end
-
shared_examples 'assignee username filter' do
it 'returns issuables assigned to those users' do
expect(issuables).to contain_exactly(*expected_issuables)
end
end
-shared_examples 'assignee NOT username filter' do
- it 'returns issuables not assigned to those users' do
- expect(issuables).to contain_exactly(*expected_issuables)
- end
-end
-
shared_examples 'no assignee filter' do
let(:params) { { assignee_id: 'None' } }
diff --git a/spec/support/shared_examples/models/cluster_application_core_shared_examples.rb b/spec/support/shared_examples/models/cluster_application_core_shared_examples.rb
index affe88be475..8e58cc7ba22 100644
--- a/spec/support/shared_examples/models/cluster_application_core_shared_examples.rb
+++ b/spec/support/shared_examples/models/cluster_application_core_shared_examples.rb
@@ -21,8 +21,4 @@ shared_examples 'cluster application core specs' do |application_name|
expect(Clusters::Cluster::APPLICATIONS[subject.name]).to eq(described_class)
end
end
-
- describe '.association_name' do
- it { expect(described_class.association_name).to eq(:"application_#{subject.name}") }
- end
end
diff --git a/spec/support/shared_examples/requests/api/issues_shared_examples.rb b/spec/support/shared_examples/requests/api/issues_shared_examples.rb
index d22210edf99..1133e95e44e 100644
--- a/spec/support/shared_examples/requests/api/issues_shared_examples.rb
+++ b/spec/support/shared_examples/requests/api/issues_shared_examples.rb
@@ -8,13 +8,6 @@ shared_examples 'labeled issues with labels and label_name params' do
end
end
- shared_examples 'returns negated label names' do
- it 'returns label names' do
- expect_paginated_array_response(issue2.id)
- expect(json_response.first['labels']).to eq([label_b.title, label.title])
- end
- end
-
shared_examples 'returns basic label entity' do
it 'returns basic label entity' do
expect_paginated_array_response(issue.id)
@@ -35,20 +28,6 @@ shared_examples 'labeled issues with labels and label_name params' do
it_behaves_like 'returns label names'
end
- context 'negation' do
- context 'array of labeled issues when all labels match with negation' do
- let(:params) { { labels: "#{label.title},#{label_b.title}", not: { labels: "#{label_c.title}" } } }
-
- it_behaves_like 'returns negated label names'
- end
-
- context 'array of labeled issues when all labels match with negation with label params as array' do
- let(:params) { { labels: [label.title, label_b.title], not: { labels: [label_c.title] } } }
-
- it_behaves_like 'returns negated label names'
- end
- end
-
context 'when with_labels_details provided' do
context 'array of labeled issues when all labels match' do
let(:params) { { labels: "#{label.title},#{label_b.title},#{label_c.title}", with_labels_details: true } }
diff --git a/yarn.lock b/yarn.lock
index 0186f8aad61..18307d7abae 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -991,18 +991,19 @@
dependencies:
vue-eslint-parser "^6.0.4"
-"@gitlab/svgs@^1.73.0":
- version "1.73.0"
- resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-1.73.0.tgz#e44b347e4be77b94474c80cf5c2ee26ca0325c2f"
- integrity sha512-4on+l5CS8Ae8OOcrnxwkO5s2zq1kHl/YjnOrHaX7megr6jsTYsVzKGaEMe0ViMSIPXA2+QnGD6vElKMkeD2+YQ==
+"@gitlab/svgs@^1.72.0":
+ version "1.72.0"
+ resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-1.72.0.tgz#78a29fd383a5a2b31ef91670068a6fea05ba234e"
+ integrity sha512-EVKRqrXsCY6tUiVAh+lpFMJAyNXZwfEqv5NeKH5ginhALMlOunRkY5rsDllyNvgZ0DWHJS1KEKJj2oVU1ouwAg==
-"@gitlab/ui@5.25.2":
- version "5.25.2"
- resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-5.25.2.tgz#599954fefcc228d31a398dbe3c1e2287a0fcdb3e"
- integrity sha512-mwwvEhVTomnZQjG0dADD+9Kg1UHZXAIb4s5QwQxwpgTkemILYIb1r96oKWfmPe8Pl/xrzAoMUtGEPT3XbxDqYQ==
+"@gitlab/ui@5.21.1":
+ version "5.21.1"
+ resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-5.21.1.tgz#8215ab3eae4296845596d5b3a987d5460b030569"
+ integrity sha512-TjPVhex9sQGUVwebaJK5XuopDHWx4+Sh9N7yH5u8eXSFWa8vk11voR4qYVt7DZB7powAO/+iiXxYMLLNtXmC/g==
dependencies:
"@babel/standalone" "^7.0.0"
"@gitlab/vue-toasted" "^1.2.1"
+ bootstrap "4.3.1"
bootstrap-vue "2.0.0-rc.27"
copy-to-clipboard "^3.0.8"
echarts "^4.2.1"
@@ -4630,6 +4631,13 @@ eslint-plugin-filenames@^1.3.2:
lodash.snakecase "4.1.1"
lodash.upperfirst "4.3.1"
+eslint-plugin-html@5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/eslint-plugin-html/-/eslint-plugin-html-5.0.0.tgz#396e30a60dedee0122fe08f11d13c5ab22f20d32"
+ integrity sha512-f7p/7YQdgQUFVAX3nB4dnMQbrDeTalcA01PDhuvTLk0ZadCwM4Pb+639SRuqEf1zMkIxckLY+ckCr0hVP5zl6A==
+ dependencies:
+ htmlparser2 "^3.10.0"
+
eslint-plugin-import@^2.14.0, eslint-plugin-import@^2.16.0:
version "2.16.0"
resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.16.0.tgz#97ac3e75d0791c4fac0e15ef388510217be7f66f"
@@ -11122,15 +11130,10 @@ sort-keys@^2.0.0:
dependencies:
is-plain-obj "^1.0.0"
-sortablejs@^1.10.0:
- version "1.10.0"
- resolved "https://registry.yarnpkg.com/sortablejs/-/sortablejs-1.10.0.tgz#0ebc054acff2486569194a2f975b2b145dd5e7d6"
- integrity sha512-+e0YakK1BxgEZpf9l9UiFaiQ8ZOBn1p/4qkkXr8QDVmYyCrUDTyDRRGm0AgW4E4cD0wtgxJ6yzIRkSPUwqhuhg==
-
-sortablejs@^1.9.0:
- version "1.9.0"
- resolved "https://registry.yarnpkg.com/sortablejs/-/sortablejs-1.9.0.tgz#2d1e74ae6bac2cb4ad0622908f340848969eb88d"
- integrity sha512-Ot6bYJ6PoqPmpsqQYXjn1+RKrY2NWQvQt/o4jfd/UYwVWndyO5EPO8YHbnm5HIykf8ENsm4JUrdAvolPT86yYA==
+sortablejs@^1.7.0:
+ version "1.7.0"
+ resolved "https://registry.yarnpkg.com/sortablejs/-/sortablejs-1.7.0.tgz#80a2b2370abd568e1cec8c271131ef30a904fa28"
+ integrity sha1-gKKyNwq9Vo4c7IwnETHvMKkE+ig=
source-list-map@^2.0.0:
version "2.0.0"
@@ -12798,13 +12801,6 @@ vue@^2.6.10:
resolved "https://registry.yarnpkg.com/vue/-/vue-2.6.10.tgz#a72b1a42a4d82a721ea438d1b6bf55e66195c637"
integrity sha512-ImThpeNU9HbdZL3utgMCq0oiMzAkt1mcgy3/E6zWC/G6AaQoeuFdsl9nDhTDU3X1R6FK7nsIUuRACVcjI+A2GQ==
-vuedraggable@^2.23.0:
- version "2.23.0"
- resolved "https://registry.yarnpkg.com/vuedraggable/-/vuedraggable-2.23.0.tgz#1f4a5a601675a5dbf0d96ee61aebfffa43445262"
- integrity sha512-RgdH16k43WNoxyRcv/OarB/DZh9SY5TYthk9TS4YiHXpelD1DytEG0phLAXiXx5EhsmdH8ltSWxklGa4g1WTCw==
- dependencies:
- sortablejs "^1.9.0"
-
vuex@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/vuex/-/vuex-3.1.0.tgz#634b81515cf0cfe976bd1ffe9601755e51f843b9"