summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2021-03-29 18:09:37 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2021-03-29 18:09:37 +0000
commit5b2abea8db1916c96027ce3a48e797003316e557 (patch)
tree611bee3c604c65707a4920c051cd18f9ba4d0e0d
parent09ff71d425b83646eed07d52078111ccbd4b84a9 (diff)
downloadgitlab-ce-5b2abea8db1916c96027ce3a48e797003316e557.tar.gz
Add latest changes from gitlab-org/gitlab@master
-rw-r--r--.haml-lint.yml1
-rw-r--r--.rubocop_manual_todo.yml236
-rw-r--r--app/assets/javascripts/boards/components/board_content_sidebar.vue6
-rw-r--r--app/assets/javascripts/boards/stores/actions.js1
-rw-r--r--app/assets/javascripts/reports/components/grouped_issues_list.vue4
-rw-r--r--app/assets/javascripts/reports/components/issues_list.vue4
-rw-r--r--app/assets/javascripts/reports/components/summary_row.vue2
-rw-r--r--app/assets/javascripts/reports/grouped_test_report/components/test_issue_body.vue18
-rw-r--r--app/assets/javascripts/vue_shared/components/runner_instructions/runner_instructions.vue8
-rw-r--r--app/controllers/admin/groups_controller.rb9
-rw-r--r--app/models/namespace.rb10
-rw-r--r--app/models/namespace/admin_note.rb7
-rw-r--r--app/models/project.rb5
-rw-r--r--app/models/project_feature.rb1
-rw-r--r--app/views/admin/groups/_form.html.haml2
-rw-r--r--app/views/admin/groups/show.html.haml2
-rw-r--r--app/views/admin/users/_admin_notes.html.haml2
-rw-r--r--app/views/groups/runners/_group_runners.html.haml2
-rw-r--r--app/views/shared/admin/_admin_note.html.haml7
-rw-r--r--app/views/shared/admin/_admin_note_form.html.haml6
-rw-r--r--changelogs/unreleased/321662-validate_not_null_constraint_on_gitlab_subscriptions_namespace_id.yml5
-rw-r--r--changelogs/unreleased/323554-setting-updating-assignees-in-the-graphql-sidebar-doesn-t-update-b.yml5
-rw-r--r--changelogs/unreleased/326018-handle-missing-instruction-error.yml6
-rw-r--r--changelogs/unreleased/admin-group-notes.yml5
-rw-r--r--changelogs/unreleased/fix-mr-issues-list-padding.yml5
-rw-r--r--db/migrate/20201218194311_create_admin_notes.rb21
-rw-r--r--db/post_migrate/20210322115438_validate_not_null_constraint_on_gitlab_subscriptions_namespace_id.rb17
-rw-r--r--db/schema_migrations/202012181943111
-rw-r--r--db/schema_migrations/202103221154381
-rw-r--r--db/structure.sql34
-rw-r--r--doc/api/dora4_group_analytics.md8
-rw-r--r--doc/api/feature_flags.md5
-rw-r--r--doc/api/feature_flags_legacy.md5
-rw-r--r--doc/development/documentation/index.md3
-rw-r--r--doc/development/documentation/structure.md8
-rw-r--r--doc/development/migration_style_guide.md4
-rw-r--r--doc/install/azure/img/azure-add-inbound-sec-rule-http.pngbin16927 -> 0 bytes
-rw-r--r--doc/install/azure/img/azure-add-inbound-sec-rule-ssh.pngbin16817 -> 0 bytes
-rw-r--r--doc/install/azure/img/azure-create-virtual-machine-basics-password.pngbin24862 -> 0 bytes
-rw-r--r--doc/install/azure/img/azure-create-virtual-machine-basics.pngbin22925 -> 0 bytes
-rw-r--r--doc/install/azure/img/azure-create-virtual-machine-deployment.pngbin23707 -> 0 bytes
-rw-r--r--doc/install/azure/img/azure-create-virtual-machine-purchase.pngbin43698 -> 0 bytes
-rw-r--r--doc/install/azure/img/azure-create-virtual-machine-settings.pngbin25686 -> 0 bytes
-rw-r--r--doc/install/azure/img/azure-create-virtual-machine-size.pngbin33322 -> 0 bytes
-rw-r--r--doc/install/azure/img/azure-dashboard-highlight-nsg.pngbin34248 -> 0 bytes
-rw-r--r--doc/install/azure/img/azure-dashboard-running-resources.pngbin34306 -> 0 bytes
-rw-r--r--doc/install/azure/img/azure-dashboard.pngbin36396 -> 0 bytes
-rw-r--r--doc/install/azure/img/azure-inbound-sec-rules-list.pngbin24592 -> 0 bytes
-rw-r--r--doc/install/azure/img/azure-new-gitlab-ce.pngbin22701 -> 0 bytes
-rw-r--r--doc/install/azure/img/azure-new-search-gitlab.pngbin19034 -> 0 bytes
-rw-r--r--doc/install/azure/img/azure-nsg-inbound-sec-rules-add-highlight.pngbin22583 -> 0 bytes
-rw-r--r--doc/install/azure/img/azure-nsg-inbound-sec-rules-highlight.pngbin31485 -> 0 bytes
-rw-r--r--doc/install/azure/img/azure-vm-domain-name.pngbin23802 -> 0 bytes
-rw-r--r--doc/install/azure/img/azure-vm-management-public-ip.pngbin34991 -> 0 bytes
-rw-r--r--doc/install/azure/img/gitlab-admin-area-9.4.0.pngbin35249 -> 0 bytes
-rw-r--r--doc/install/azure/img/gitlab-admin-area.pngbin29333 -> 0 bytes
-rw-r--r--doc/install/azure/img/gitlab-change-password.pngbin24404 -> 0 bytes
-rw-r--r--doc/install/azure/img/gitlab-home.pngbin26302 -> 0 bytes
-rw-r--r--doc/install/azure/img/gitlab-login.pngbin24656 -> 0 bytes
-rw-r--r--doc/install/azure/img/gitlab-new-project.pngbin34164 -> 0 bytes
-rw-r--r--doc/install/azure/img/gitlab-project-home-empty.pngbin28375 -> 0 bytes
-rw-r--r--doc/install/azure/img/gitlab-project-home-instructions.pngbin31738 -> 0 bytes
-rw-r--r--doc/install/azure/img/gitlab-ssh-update-in-progress.pngbin32799 -> 0 bytes
-rw-r--r--doc/install/azure/index.md563
-rw-r--r--doc/subscriptions/self_managed/index.md4
-rw-r--r--doc/user/packages/container_registry/index.md4
-rw-r--r--doc/user/permissions.md2
-rw-r--r--lib/gitlab/background_migration/user_mentions/models/namespace.rb7
-rw-r--r--locale/gitlab.pot15
-rw-r--r--rubocop/cop/gitlab/feature_available_usage.rb99
-rw-r--r--spec/controllers/admin/groups_controller_spec.rb6
-rw-r--r--spec/features/admin/admin_groups_spec.rb45
-rw-r--r--spec/features/boards/sidebar_assignee_spec.rb2
-rw-r--r--spec/frontend/reports/grouped_test_report/components/test_issue_body_spec.js2
-rw-r--r--spec/frontend/vue_shared/components/runner_instructions/runner_instructions_spec.js40
-rw-r--r--spec/models/namespace/admin_note_spec.rb16
-rw-r--r--spec/models/namespace_spec.rb1
-rw-r--r--spec/rubocop/cop/gitlab/feature_available_usage_spec.rb96
78 files changed, 963 insertions, 405 deletions
diff --git a/.haml-lint.yml b/.haml-lint.yml
index 94e84462862..a6aed05d004 100644
--- a/.haml-lint.yml
+++ b/.haml-lint.yml
@@ -106,6 +106,7 @@ linters:
- Cop/LineBreakAfterGuardClauses
- Cop/LineBreakAroundConditionalBlock
- Cop/ProjectPathHelper
+ - Gitlab/FeatureAvailableUsage
- GitlabSecurity/PublicSend
- Layout/EmptyLineAfterGuardClause
- Layout/LeadingCommentSpace
diff --git a/.rubocop_manual_todo.yml b/.rubocop_manual_todo.yml
index 5a509b3caf3..d2d32691dba 100644
--- a/.rubocop_manual_todo.yml
+++ b/.rubocop_manual_todo.yml
@@ -3580,3 +3580,239 @@ Gitlab/DelegatePredicateMethods:
- 'ee/app/models/ee/namespace.rb'
- 'ee/app/models/license.rb'
- 'lib/gitlab/ci/trace/stream.rb'
+
+# Offense count: 298
+Gitlab/FeatureAvailableUsage:
+ Exclude:
+ - 'app/controllers/projects/application_controller.rb'
+ - 'app/graphql/types/project_type.rb'
+ - 'app/helpers/events_helper.rb'
+ - 'app/helpers/labels_helper.rb'
+ - 'app/policies/project_policy.rb'
+ - 'app/views/groups/issues.html.haml'
+ - 'app/views/groups/merge_requests.html.haml'
+ - 'app/views/shared/boards/_switcher.html.haml'
+ - 'ee/app/controllers/concerns/description_diff_actions.rb'
+ - 'ee/app/controllers/concerns/ee/boards_actions.rb'
+ - 'ee/app/controllers/concerns/security_dashboards_permissions.rb'
+ - 'ee/app/controllers/ee/boards/lists_controller.rb'
+ - 'ee/app/controllers/ee/groups/application_controller.rb'
+ - 'ee/app/controllers/ee/groups/group_members_controller.rb'
+ - 'ee/app/controllers/ee/projects/autocomplete_sources_controller.rb'
+ - 'ee/app/controllers/ee/projects/issues_controller.rb'
+ - 'ee/app/controllers/ee/projects/security/configuration_controller.rb'
+ - 'ee/app/controllers/ee/projects/settings/ci_cd_controller.rb'
+ - 'ee/app/controllers/ee/projects/settings/operations_controller.rb'
+ - 'ee/app/controllers/ee/projects/settings/repository_controller.rb'
+ - 'ee/app/controllers/groups/analytics/application_controller.rb'
+ - 'ee/app/controllers/groups/audit_events_controller.rb'
+ - 'ee/app/controllers/groups/bulk_update_controller.rb'
+ - 'ee/app/controllers/groups/contribution_analytics_controller.rb'
+ - 'ee/app/controllers/groups/epics_controller.rb'
+ - 'ee/app/controllers/groups/hooks_controller.rb'
+ - 'ee/app/controllers/groups/issues_analytics_controller.rb'
+ - 'ee/app/controllers/groups/iterations_controller.rb'
+ - 'ee/app/controllers/projects/analytics/issues_analytics_controller.rb'
+ - 'ee/app/controllers/projects/audit_events_controller.rb'
+ - 'ee/app/controllers/projects/cluster_agents_controller.rb'
+ - 'ee/app/controllers/projects/iterations/inherited_controller.rb'
+ - 'ee/app/controllers/projects/iterations_controller.rb'
+ - 'ee/app/controllers/projects/path_locks_controller.rb'
+ - 'ee/app/controllers/projects/subscriptions_controller.rb'
+ - 'ee/app/finders/autocomplete/vulnerabilities_autocomplete_finder.rb'
+ - 'ee/app/finders/clusters/agents_finder.rb'
+ - 'ee/app/finders/ee/alert_management/alerts_finder.rb'
+ - 'ee/app/finders/ee/alert_management/http_integrations_finder.rb'
+ - 'ee/app/finders/ee/group_projects_finder.rb'
+ - 'ee/app/graphql/ee/types/group_type.rb'
+ - 'ee/app/graphql/mutations/dast/profiles/create.rb'
+ - 'ee/app/graphql/mutations/dast/profiles/run.rb'
+ - 'ee/app/graphql/mutations/dast/profiles/update.rb'
+ - 'ee/app/graphql/mutations/instance_security_dashboard/remove_project.rb'
+ - 'ee/app/graphql/resolvers/boards/epic_boards_resolver.rb'
+ - 'ee/app/graphql/resolvers/clusters/agent_tokens_resolver.rb'
+ - 'ee/app/graphql/resolvers/epics_resolver.rb'
+ - 'ee/app/helpers/ee/analytics/navbar_helper.rb'
+ - 'ee/app/helpers/ee/application_helper.rb'
+ - 'ee/app/helpers/ee/boards_helper.rb'
+ - 'ee/app/helpers/ee/clusters_helper.rb'
+ - 'ee/app/helpers/ee/dashboard_helper.rb'
+ - 'ee/app/helpers/ee/form_helper.rb'
+ - 'ee/app/helpers/ee/graph_helper.rb'
+ - 'ee/app/helpers/ee/groups_helper.rb'
+ - 'ee/app/helpers/ee/issues_helper.rb'
+ - 'ee/app/helpers/ee/lock_helper.rb'
+ - 'ee/app/helpers/ee/operations_helper.rb'
+ - 'ee/app/helpers/ee/projects/incidents_helper.rb'
+ - 'ee/app/helpers/ee/projects_helper.rb'
+ - 'ee/app/helpers/ee/releases_helper.rb'
+ - 'ee/app/helpers/ee/search_helper.rb'
+ - 'ee/app/helpers/ee/tree_helper.rb'
+ - 'ee/app/helpers/groups/security_features_helper.rb'
+ - 'ee/app/models/approval_state.rb'
+ - 'ee/app/models/concerns/approvable.rb'
+ - 'ee/app/models/concerns/ee/project_security_scanners_information.rb'
+ - 'ee/app/models/concerns/ee/protected_ref_access.rb'
+ - 'ee/app/models/concerns/has_timelogs_report.rb'
+ - 'ee/app/models/concerns/insights_feature.rb'
+ - 'ee/app/models/ee/board.rb'
+ - 'ee/app/models/ee/ci/build.rb'
+ - 'ee/app/models/ee/ci/build_dependencies.rb'
+ - 'ee/app/models/ee/ci/pipeline.rb'
+ - 'ee/app/models/ee/group.rb'
+ - 'ee/app/models/ee/group_member.rb'
+ - 'ee/app/models/ee/issue.rb'
+ - 'ee/app/models/ee/list.rb'
+ - 'ee/app/models/ee/merge_request.rb'
+ - 'ee/app/models/ee/milestone_release.rb'
+ - 'ee/app/models/ee/namespace.rb'
+ - 'ee/app/models/ee/namespace_setting.rb'
+ - 'ee/app/models/ee/project.rb'
+ - 'ee/app/models/ee/project_ci_cd_setting.rb'
+ - 'ee/app/models/namespace_statistics.rb'
+ - 'ee/app/models/project_security_setting.rb'
+ - 'ee/app/models/saml_provider.rb'
+ - 'ee/app/policies/compliance_management/framework_policy.rb'
+ - 'ee/app/policies/compliance_management/framework_policy.rb'
+ - 'ee/app/policies/ee/group_policy.rb'
+ - 'ee/app/policies/ee/namespace_policy.rb'
+ - 'ee/app/policies/ee/project_policy.rb'
+ - 'ee/app/policies/ee/protected_branch_policy.rb'
+ - 'ee/app/presenters/ee/label_presenter.rb'
+ - 'ee/app/presenters/epic_presenter.rb'
+ - 'ee/app/presenters/merge_request_approver_presenter.rb'
+ - 'ee/app/serializers/dashboard_operations_project_entity.rb'
+ - 'ee/app/serializers/ee/environment_entity.rb'
+ - 'ee/app/serializers/ee/evidences/release_entity.rb'
+ - 'ee/app/serializers/ee/note_entity.rb'
+ - 'ee/app/services/boards/epic_boards/update_service.rb'
+ - 'ee/app/services/ci/audit_variable_change_service.rb'
+ - 'ee/app/services/clusters/agent_tokens/create_service.rb'
+ - 'ee/app/services/clusters/agents/create_service.rb'
+ - 'ee/app/services/dashboard/projects/create_service.rb'
+ - 'ee/app/services/dashboard/projects/list_service.rb'
+ - 'ee/app/services/dast/profiles/create_service.rb'
+ - 'ee/app/services/dast/profiles/update_service.rb'
+ - 'ee/app/services/dast_on_demand_scans/create_service.rb'
+ - 'ee/app/services/dast_site_tokens/create_service.rb'
+ - 'ee/app/services/dast_site_validations/create_service.rb'
+ - 'ee/app/services/dast_site_validations/revoke_service.rb'
+ - 'ee/app/services/dast_site_validations/validate_service.rb'
+ - 'ee/app/services/ee/alert_management/http_integrations/create_service.rb'
+ - 'ee/app/services/ee/audit_event_service.rb'
+ - 'ee/app/services/ee/boards/issues/list_service.rb'
+ - 'ee/app/services/ee/boards/lists/create_service.rb'
+ - 'ee/app/services/ee/boards/update_service.rb'
+ - 'ee/app/services/ee/groups/create_service.rb'
+ - 'ee/app/services/ee/ide/schemas_config_service.rb'
+ - 'ee/app/services/ee/issuable_base_service.rb'
+ - 'ee/app/services/ee/issue_links/create_service.rb'
+ - 'ee/app/services/ee/issues/build_service.rb'
+ - 'ee/app/services/ee/lfs/lock_file_service.rb'
+ - 'ee/app/services/ee/lfs/unlock_file_service.rb'
+ - 'ee/app/services/ee/merge_requests/approval_service.rb'
+ - 'ee/app/services/ee/merge_requests/build_service.rb'
+ - 'ee/app/services/ee/merge_requests/merge_base_service.rb'
+ - 'ee/app/services/ee/merge_requests/refresh_service.rb'
+ - 'ee/app/services/ee/merge_requests/update_service.rb'
+ - 'ee/app/services/ee/projects/create_service.rb'
+ - 'ee/app/services/ee/protected_branches/create_service.rb'
+ - 'ee/app/services/ee/releases/create_evidence_service.rb'
+ - 'ee/app/services/ee/search/group_service.rb'
+ - 'ee/app/services/iterations/cadences/create_service.rb'
+ - 'ee/app/services/iterations/cadences/update_service.rb'
+ - 'ee/app/services/iterations/create_service.rb'
+ - 'ee/app/services/iterations/update_service.rb'
+ - 'ee/app/services/merge_requests/sync_report_approver_approval_rules.rb'
+ - 'ee/app/services/merge_requests/update_blocks_service.rb'
+ - 'ee/app/services/projects/mark_for_deletion_service.rb'
+ - 'ee/app/services/quality_management/test_cases/create_service.rb'
+ - 'ee/app/services/requirements_management/process_test_reports_service.rb'
+ - 'ee/app/services/security/store_scans_service.rb'
+ - 'ee/app/views/groups/_templates_setting.html.haml'
+ - 'ee/app/views/groups/contribution_analytics/show.html.haml'
+ - 'ee/app/views/groups/ee/_settings_nav.html.haml'
+ - 'ee/app/views/groups/epics/index.html.haml'
+ - 'ee/app/views/groups/epics/show.html.haml'
+ - 'ee/app/views/groups/epics/show.html.haml'
+ - 'ee/app/views/groups/hooks/index.html.haml'
+ - 'ee/app/views/groups/roadmap/show.html.haml'
+ - 'ee/app/views/groups/settings/_allowed_email_domain.html.haml'
+ - 'ee/app/views/groups/settings/_ip_restriction.html.haml'
+ - 'ee/app/views/layouts/nav/_test_cases_link.html.haml'
+ - 'ee/app/views/layouts/nav/sidebar/_project_iterations_link.html.haml'
+ - 'ee/app/views/projects/_merge_request_approvals_settings.html.haml'
+ - 'ee/app/views/projects/_merge_request_settings.html.haml'
+ - 'ee/app/views/projects/_merge_request_settings_description_text.html.haml'
+ - 'ee/app/views/projects/audit_events/index.html.haml'
+ - 'ee/app/views/projects/blob/_header_file_locks.html.haml'
+ - 'ee/app/views/projects/issues/_related_issues.html.haml'
+ - 'ee/app/views/projects/merge_requests/show.html.haml'
+ - 'ee/app/views/projects/merge_requests/show.html.haml'
+ - 'ee/app/views/projects/merge_requests/show.html.haml'
+ - 'ee/app/views/projects/merge_requests/show.html.haml'
+ - 'ee/app/views/projects/merge_requests/show.html.haml'
+ - 'ee/app/views/projects/merge_requests/show.html.haml'
+ - 'ee/app/views/projects/merge_requests/show.html.haml'
+ - 'ee/app/views/projects/merge_requests/show.html.haml'
+ - 'ee/app/views/projects/merge_requests/show.html.haml'
+ - 'ee/app/views/projects/pipelines/_tabs_content.html.haml'
+ - 'ee/app/views/projects/protected_branches/ee/_code_owner_approval_form.html.haml'
+ - 'ee/app/views/projects/protected_branches/ee/_code_owner_approval_table.html.haml'
+ - 'ee/app/views/projects/protected_branches/ee/_code_owner_approval_table_head.html.haml'
+ - 'ee/app/views/projects/push_rules/_index.html.haml'
+ - 'ee/app/views/projects/settings/_default_issue_template.html.haml'
+ - 'ee/app/views/projects/settings/_marked_for_removal.html.haml'
+ - 'ee/app/views/projects/settings/_restore.html.haml'
+ - 'ee/app/views/projects/settings/ci_cd/_auto_rollback.html.haml'
+ - 'ee/app/views/projects/settings/ci_cd/_pipeline_subscriptions.html.haml'
+ - 'ee/app/views/projects/settings/operations/_status_page.html.haml'
+ - 'ee/app/views/projects/settings/repository/_protected_branches.html.haml'
+ - 'ee/app/views/projects/sidebar/_repository_locked_files.html.haml'
+ - 'ee/app/views/shared/issuable/_board_create_list_dropdown.html.haml'
+ - 'ee/app/views/shared/issuable/_board_create_list_dropdown.html.haml'
+ - 'ee/app/views/shared/issuable/_group_bulk_update_sidebar.html.haml'
+ - 'ee/app/views/shared/issuable/_iteration_select.html.haml'
+ - 'ee/app/views/shared/issuable/form/_default_templates.html.haml'
+ - 'ee/app/views/shared/labels/_create_label_help_text.html.haml'
+ - 'ee/app/views/shared/promotions/_promote_mr_features.html.haml'
+ - 'ee/app/views/shared/promotions/_promote_mr_features.html.haml'
+ - 'ee/app/views/shared/promotions/_promote_repository_features.html.haml'
+ - 'ee/app/views/shared/promotions/_promote_repository_features.html.haml'
+ - 'ee/app/views/shared/promotions/_promote_repository_features.html.haml'
+ - 'ee/app/views/shared/promotions/_promote_repository_features.html.haml'
+ - 'ee/app/views/shared/promotions/_promote_repository_features.html.haml'
+ - 'ee/app/views/shared/promotions/_promote_repository_features.html.haml'
+ - 'ee/app/workers/analytics/code_review_metrics_worker.rb'
+ - 'ee/app/workers/group_saml_group_sync_worker.rb'
+ - 'ee/lib/api/external_approval_rules.rb'
+ - 'ee/lib/api/helpers/epics_helpers.rb'
+ - 'ee/lib/api/ldap_group_links.rb'
+ - 'ee/lib/ee/api/entities/approval_state.rb'
+ - 'ee/lib/ee/api/entities/board.rb'
+ - 'ee/lib/ee/api/entities/group.rb'
+ - 'ee/lib/ee/api/entities/issue.rb'
+ - 'ee/lib/ee/api/entities/project.rb'
+ - 'ee/lib/ee/api/groups.rb'
+ - 'ee/lib/ee/api/helpers.rb'
+ - 'ee/lib/ee/api/internal/kubernetes.rb'
+ - 'ee/lib/ee/api/job_artifacts.rb'
+ - 'ee/lib/ee/api/projects.rb'
+ - 'ee/lib/ee/gitlab/alert_management/payload/generic.rb'
+ - 'ee/lib/ee/gitlab/checks/diff_check.rb'
+ - 'ee/lib/ee/gitlab/gon_helper.rb'
+ - 'ee/lib/ee/gitlab/tree_summary.rb'
+ - 'ee/lib/gitlab/alert_management.rb'
+ - 'ee/lib/gitlab/auth/group_saml/group_lookup.rb'
+ - 'ee/lib/gitlab/ci/pipeline/chain/config/content/compliance.rb'
+ - 'ee/lib/gitlab/code_owners.rb'
+ - 'ee/lib/gitlab/import_export/group/group_and_descendants_repo_restorer.rb'
+ - 'ee/lib/gitlab/incident_management.rb'
+ - 'ee/lib/gitlab/path_locks_finder.rb'
+ - 'ee/lib/incident_management/incident_sla.rb'
+ - 'ee/spec/models/ee/namespace_spec.rb'
+ - 'ee/spec/models/instance_security_dashboard_spec.rb'
+ - 'ee/spec/models/license_spec.rb'
+ - 'ee/spec/models/project_spec.rb'
+ - 'lib/api/helpers/related_resources_helpers.rb'
+ - 'spec/models/concerns/featurable_spec.rb'
diff --git a/app/assets/javascripts/boards/components/board_content_sidebar.vue b/app/assets/javascripts/boards/components/board_content_sidebar.vue
index 8e84f76ee60..d74057e99bc 100644
--- a/app/assets/javascripts/boards/components/board_content_sidebar.vue
+++ b/app/assets/javascripts/boards/components/board_content_sidebar.vue
@@ -51,10 +51,6 @@ export default {
},
methods: {
...mapActions(['toggleBoardItem', 'setAssignees']),
- updateAssignees(data) {
- const assignees = data.issueSetAssignees?.issue?.assignees?.nodes || [];
- this.setAssignees(assignees);
- },
handleClose() {
this.toggleBoardItem({ boardItem: this.activeIssue, sidebarType: this.sidebarType });
},
@@ -78,7 +74,7 @@ export default {
:full-path="fullPath"
:initial-assignees="activeIssue.assignees"
class="assignee"
- @assignees-updated="updateAssignees"
+ @assignees-updated="setAssignees"
/>
<board-sidebar-epic-select class="epic" />
<div>
diff --git a/app/assets/javascripts/boards/stores/actions.js b/app/assets/javascripts/boards/stores/actions.js
index bf67328bbe6..4763902ce86 100644
--- a/app/assets/javascripts/boards/stores/actions.js
+++ b/app/assets/javascripts/boards/stores/actions.js
@@ -69,6 +69,7 @@ export default {
'milestoneTitle',
'releaseTag',
'search',
+ 'myReactionEmoji',
]);
filterParams.not = transformNotFilters(filters);
commit(types.SET_FILTERS, filterParams);
diff --git a/app/assets/javascripts/reports/components/grouped_issues_list.vue b/app/assets/javascripts/reports/components/grouped_issues_list.vue
index 585127f901e..ca369022938 100644
--- a/app/assets/javascripts/reports/components/grouped_issues_list.vue
+++ b/app/assets/javascripts/reports/components/grouped_issues_list.vue
@@ -66,8 +66,8 @@ export default {
},
listClasses() {
return {
- 'gl-pl-7': this.nestedLevel === 1,
- 'gl-pl-9': this.nestedLevel === 2,
+ 'gl-pl-9': this.nestedLevel === 1,
+ 'gl-pl-11-5': this.nestedLevel === 2,
};
},
},
diff --git a/app/assets/javascripts/reports/components/issues_list.vue b/app/assets/javascripts/reports/components/issues_list.vue
index ea3f0d78d8c..9df0a1953b6 100644
--- a/app/assets/javascripts/reports/components/issues_list.vue
+++ b/app/assets/javascripts/reports/components/issues_list.vue
@@ -88,8 +88,8 @@ export default {
},
listClasses() {
return {
- 'gl-pl-7': this.nestedLevel === 1,
- 'gl-pl-8': this.nestedLevel === 2,
+ 'gl-pl-9': this.nestedLevel === 1,
+ 'gl-pl-11-5': this.nestedLevel === 2,
};
},
},
diff --git a/app/assets/javascripts/reports/components/summary_row.vue b/app/assets/javascripts/reports/components/summary_row.vue
index 8eb43bcf1ba..6b7d81c4878 100644
--- a/app/assets/javascripts/reports/components/summary_row.vue
+++ b/app/assets/javascripts/reports/components/summary_row.vue
@@ -51,7 +51,7 @@ export default {
if (!this.nestedSummary) {
return ['gl-px-5'];
}
- return ['gl-pl-7', 'gl-pr-5', { 'gl-bg-gray-10': this.statusIcon === ICON_WARNING }];
+ return ['gl-pl-9', 'gl-pr-5', { 'gl-bg-gray-10': this.statusIcon === ICON_WARNING }];
},
statusIconSize() {
if (!this.nestedSummary) {
diff --git a/app/assets/javascripts/reports/grouped_test_report/components/test_issue_body.vue b/app/assets/javascripts/reports/grouped_test_report/components/test_issue_body.vue
index 522245a442d..8913046d62f 100644
--- a/app/assets/javascripts/reports/grouped_test_report/components/test_issue_body.vue
+++ b/app/assets/javascripts/reports/grouped_test_report/components/test_issue_body.vue
@@ -24,7 +24,7 @@ export default {
n__(
'Reports|Failed %{count} time in %{base_branch} in the last 14 days',
'Reports|Failed %{count} times in %{base_branch} in the last 14 days',
- this.issue.recent_failures.count,
+ this.issue.recent_failures?.count,
),
this.issue.recent_failures,
);
@@ -44,20 +44,20 @@ export default {
<template>
<div class="gl-display-flex gl-mt-2 gl-mb-2">
<issue-status-icon :status="status" :status-icon-size="24" class="gl-mr-3" />
- <gl-badge
- v-if="showRecentFailures"
- variant="warning"
- class="gl-mr-2"
- data-testid="test-issue-body-recent-failures"
- >
- {{ recentFailureMessage }}
- </gl-badge>
<gl-button
button-text-classes="gl-white-space-normal! gl-word-break-all gl-text-left"
variant="link"
data-testid="test-issue-body-description"
@click="openModal({ issue })"
>
+ <gl-badge
+ v-if="showRecentFailures"
+ variant="warning"
+ class="gl-mr-2"
+ data-testid="test-issue-body-recent-failures"
+ >
+ {{ recentFailureMessage }}
+ </gl-badge>
{{ issue.name }}
</gl-button>
</div>
diff --git a/app/assets/javascripts/vue_shared/components/runner_instructions/runner_instructions.vue b/app/assets/javascripts/vue_shared/components/runner_instructions/runner_instructions.vue
index 1d6db576942..662c9f595ea 100644
--- a/app/assets/javascripts/vue_shared/components/runner_instructions/runner_instructions.vue
+++ b/app/assets/javascripts/vue_shared/components/runner_instructions/runner_instructions.vue
@@ -9,6 +9,7 @@ import {
GlDropdownItem,
GlIcon,
} from '@gitlab/ui';
+import { isEmpty } from 'lodash';
import { __, s__ } from '~/locale';
import ModalCopyButton from '~/vue_shared/components/modal_copy_button.vue';
import {
@@ -79,7 +80,7 @@ export default {
return Object.keys(this.selectedPlatform).length > 0;
},
instructionsEmpty() {
- return Object.keys(this.instructions).length === 0;
+ return isEmpty(this.instructions);
},
groupId() {
return this.group?.id ?? '';
@@ -212,10 +213,7 @@ export default {
<pre
class="gl-bg-gray gl-flex-fill-1 gl-white-space-pre-line"
data-testid="binary-instructions"
- >
-
- {{ instructions.installInstructions }}
- </pre
+ >{{ instructions.installInstructions }}</pre
>
<modal-copy-button
:title="$options.i18n.copyInstructions"
diff --git a/app/controllers/admin/groups_controller.rb b/app/controllers/admin/groups_controller.rb
index 0a1c85eef3f..a61bffec10a 100644
--- a/app/controllers/admin/groups_controller.rb
+++ b/app/controllers/admin/groups_controller.rb
@@ -30,9 +30,11 @@ class Admin::GroupsController < Admin::ApplicationController
def new
@group = Group.new
+ @group.build_admin_note
end
def edit
+ @group.build_admin_note unless @group.admin_note
end
def create
@@ -49,6 +51,8 @@ class Admin::GroupsController < Admin::ApplicationController
end
def update
+ @group.build_admin_note unless @group.admin_note
+
if @group.update(group_params)
redirect_to [:admin, @group], notice: _('Group was successfully updated.')
else
@@ -105,7 +109,10 @@ class Admin::GroupsController < Admin::ApplicationController
:require_two_factor_authentication,
:two_factor_grace_period,
:project_creation_level,
- :subgroup_creation_level
+ :subgroup_creation_level,
+ admin_note_attributes: [
+ :note
+ ]
]
end
end
diff --git a/app/models/namespace.rb b/app/models/namespace.rb
index 7b7c2ea9d7b..eaaf9e3687c 100644
--- a/app/models/namespace.rb
+++ b/app/models/namespace.rb
@@ -46,6 +46,9 @@ class Namespace < ApplicationRecord
has_one :aggregation_schedule, class_name: 'Namespace::AggregationSchedule'
has_one :package_setting_relation, inverse_of: :namespace, class_name: 'PackageSetting'
+ has_one :admin_note, inverse_of: :namespace
+ accepts_nested_attributes_for :admin_note, update_only: true
+
validates :owner, presence: true, unless: ->(n) { n.type == "Group" }
validates :name,
presence: true,
@@ -284,8 +287,13 @@ class Namespace < ApplicationRecord
false
end
+ # Deprecated, use #licensed_feature_available? instead. Remove once Namespace#feature_available? isn't used anymore.
+ def feature_available?(feature)
+ licensed_feature_available?(feature)
+ end
+
# Overridden in EE::Namespace
- def feature_available?(_feature)
+ def licensed_feature_available?(_feature)
false
end
diff --git a/app/models/namespace/admin_note.rb b/app/models/namespace/admin_note.rb
new file mode 100644
index 00000000000..3de809d60be
--- /dev/null
+++ b/app/models/namespace/admin_note.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+class Namespace::AdminNote < ApplicationRecord
+ belongs_to :namespace, inverse_of: :admin_note
+ validates :namespace, presence: true
+ validates :note, length: { maximum: 1000 }
+end
diff --git a/app/models/project.rb b/app/models/project.rb
index 61f165b9daa..b21d9818953 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -2324,6 +2324,11 @@ class Project < ApplicationRecord
.external_authorization_service_default_label
end
+ # Overridden in EE::Project
+ def licensed_feature_available?(_feature)
+ false
+ end
+
def licensed_features
[]
end
diff --git a/app/models/project_feature.rb b/app/models/project_feature.rb
index a598bf3f60c..09a20c3509f 100644
--- a/app/models/project_feature.rb
+++ b/app/models/project_feature.rb
@@ -3,6 +3,7 @@
class ProjectFeature < ApplicationRecord
include Featurable
+ # When updating this array, make sure to update rubocop/cop/gitlab/feature_available_usage.rb as well.
FEATURES = %i[
issues
forking
diff --git a/app/views/admin/groups/_form.html.haml b/app/views/admin/groups/_form.html.haml
index 15306ab7878..84a9b988d22 100644
--- a/app/views/admin/groups/_form.html.haml
+++ b/app/views/admin/groups/_form.html.haml
@@ -3,6 +3,8 @@
= render 'shared/group_form', f: f
= render 'shared/group_form_description', f: f
+ = render 'shared/admin/admin_note_form', f: f
+
= render_if_exists 'shared/old_repository_size_limit_setting', form: f, type: :group
= render_if_exists 'admin/namespace_plan', f: f
diff --git a/app/views/admin/groups/show.html.haml b/app/views/admin/groups/show.html.haml
index f8c490dd948..e7e86846df6 100644
--- a/app/views/admin/groups/show.html.haml
+++ b/app/views/admin/groups/show.html.haml
@@ -103,6 +103,8 @@
%span.monospace= project.full_path + '.git'
.col-md-6
+ = render 'shared/admin/admin_note'
+
- if can?(current_user, :admin_group_member, @group)
.card
.card-header
diff --git a/app/views/admin/users/_admin_notes.html.haml b/app/views/admin/users/_admin_notes.html.haml
index a20b2fbffc4..7c3220e2cee 100644
--- a/app/views/admin/users/_admin_notes.html.haml
+++ b/app/views/admin/users/_admin_notes.html.haml
@@ -2,6 +2,6 @@
%legend= _('Admin notes')
.form-group.row
.col-sm-2.col-form-label
- = f.label :note, s_('AdminNote|Note')
+ = f.label :note, s_('Admin|Note')
.col-sm-10
= f.text_area :note, class: 'form-control gl-form-input gl-form-textarea'
diff --git a/app/views/groups/runners/_group_runners.html.haml b/app/views/groups/runners/_group_runners.html.haml
index f60cdc9f8da..910b36770f1 100644
--- a/app/views/groups/runners/_group_runners.html.haml
+++ b/app/views/groups/runners/_group_runners.html.haml
@@ -19,5 +19,5 @@
type: 'group',
reset_token_url: reset_registration_token_group_settings_ci_cd_path,
project_path: '',
- group_path: @group.path }
+ group_path: @group.full_path }
%br
diff --git a/app/views/shared/admin/_admin_note.html.haml b/app/views/shared/admin/_admin_note.html.haml
new file mode 100644
index 00000000000..82407705885
--- /dev/null
+++ b/app/views/shared/admin/_admin_note.html.haml
@@ -0,0 +1,7 @@
+- if @group.admin_note.present?
+ - text = @group.admin_note.note
+ .card.border-info
+ .card-header.bg-info.gl-text-white
+ = s_('Admin|Admin notes')
+ .card-body
+ %p= text
diff --git a/app/views/shared/admin/_admin_note_form.html.haml b/app/views/shared/admin/_admin_note_form.html.haml
new file mode 100644
index 00000000000..0bc26f9120f
--- /dev/null
+++ b/app/views/shared/admin/_admin_note_form.html.haml
@@ -0,0 +1,6 @@
+.form-group.row
+ = f.fields_for :admin_note do |an|
+ .col-sm-2.col-form-label.gl-text-right
+ = an.label :note, s_('Admin|Admin notes')
+ .col-sm-10
+ = an.text_area :note, class: 'form-control'
diff --git a/changelogs/unreleased/321662-validate_not_null_constraint_on_gitlab_subscriptions_namespace_id.yml b/changelogs/unreleased/321662-validate_not_null_constraint_on_gitlab_subscriptions_namespace_id.yml
new file mode 100644
index 00000000000..780c7849eb1
--- /dev/null
+++ b/changelogs/unreleased/321662-validate_not_null_constraint_on_gitlab_subscriptions_namespace_id.yml
@@ -0,0 +1,5 @@
+---
+title: Validate NOT NULL constraint on gitlab_subscriptions namespace_id
+merge_request: 57113
+author:
+type: other
diff --git a/changelogs/unreleased/323554-setting-updating-assignees-in-the-graphql-sidebar-doesn-t-update-b.yml b/changelogs/unreleased/323554-setting-updating-assignees-in-the-graphql-sidebar-doesn-t-update-b.yml
new file mode 100644
index 00000000000..8cd506d5100
--- /dev/null
+++ b/changelogs/unreleased/323554-setting-updating-assignees-in-the-graphql-sidebar-doesn-t-update-b.yml
@@ -0,0 +1,5 @@
+---
+title: Fix updating GraphQL boards cards on assignees update
+merge_request: 57687
+author:
+type: fixed
diff --git a/changelogs/unreleased/326018-handle-missing-instruction-error.yml b/changelogs/unreleased/326018-handle-missing-instruction-error.yml
new file mode 100644
index 00000000000..8a30e030ac3
--- /dev/null
+++ b/changelogs/unreleased/326018-handle-missing-instruction-error.yml
@@ -0,0 +1,6 @@
+---
+title: Display error message when runner installation instructions modal cannot be
+ loaded correctly
+merge_request: 57588
+author:
+type: fixed
diff --git a/changelogs/unreleased/admin-group-notes.yml b/changelogs/unreleased/admin-group-notes.yml
new file mode 100644
index 00000000000..dda7628336c
--- /dev/null
+++ b/changelogs/unreleased/admin-group-notes.yml
@@ -0,0 +1,5 @@
+---
+title: Allow admin users to define admin notes on groups.
+merge_request: 47825
+author:
+type: added
diff --git a/changelogs/unreleased/fix-mr-issues-list-padding.yml b/changelogs/unreleased/fix-mr-issues-list-padding.yml
new file mode 100644
index 00000000000..046526b94e1
--- /dev/null
+++ b/changelogs/unreleased/fix-mr-issues-list-padding.yml
@@ -0,0 +1,5 @@
+---
+title: Fix test report merge request widget summary and issues alignment
+merge_request: 56768
+author:
+type: fixed
diff --git a/db/migrate/20201218194311_create_admin_notes.rb b/db/migrate/20201218194311_create_admin_notes.rb
new file mode 100644
index 00000000000..32f5818cdfb
--- /dev/null
+++ b/db/migrate/20201218194311_create_admin_notes.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+class CreateAdminNotes < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def up
+ create_table_with_constraints :namespace_admin_notes do |t|
+ t.timestamps_with_timezone
+ t.references :namespace, null: false, foreign_key: { on_delete: :cascade }
+ t.text :note
+
+ t.text_limit :note, 1000
+ end
+ end
+
+ def down
+ drop_table :namespace_admin_notes
+ end
+end
diff --git a/db/post_migrate/20210322115438_validate_not_null_constraint_on_gitlab_subscriptions_namespace_id.rb b/db/post_migrate/20210322115438_validate_not_null_constraint_on_gitlab_subscriptions_namespace_id.rb
new file mode 100644
index 00000000000..96d9f383406
--- /dev/null
+++ b/db/post_migrate/20210322115438_validate_not_null_constraint_on_gitlab_subscriptions_namespace_id.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+class ValidateNotNullConstraintOnGitlabSubscriptionsNamespaceId < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ validate_not_null_constraint :gitlab_subscriptions, :namespace_id
+ end
+
+ def down
+ # no-op
+ end
+end
diff --git a/db/schema_migrations/20201218194311 b/db/schema_migrations/20201218194311
new file mode 100644
index 00000000000..f9beba74a8c
--- /dev/null
+++ b/db/schema_migrations/20201218194311
@@ -0,0 +1 @@
+7c33bd30af66ebb9a837c72e2ced107f015d4a22c7b6393554a9299bf3907cc0 \ No newline at end of file
diff --git a/db/schema_migrations/20210322115438 b/db/schema_migrations/20210322115438
new file mode 100644
index 00000000000..94db65a9a8a
--- /dev/null
+++ b/db/schema_migrations/20210322115438
@@ -0,0 +1 @@
+e177c2cc0b59eea54de10417445b391cea7dd308547077aea34054fac22b9e40 \ No newline at end of file
diff --git a/db/structure.sql b/db/structure.sql
index f8a6ddc9f61..be155891f23 100644
--- a/db/structure.sql
+++ b/db/structure.sql
@@ -13147,7 +13147,8 @@ CREATE TABLE gitlab_subscriptions (
auto_renew boolean,
seats_in_use integer DEFAULT 0 NOT NULL,
seats_owed integer DEFAULT 0 NOT NULL,
- trial_extension_type smallint
+ trial_extension_type smallint,
+ CONSTRAINT check_77fea3f0e7 CHECK ((namespace_id IS NOT NULL))
);
CREATE SEQUENCE gitlab_subscriptions_id_seq
@@ -14640,6 +14641,24 @@ CREATE SEQUENCE milestones_id_seq
ALTER SEQUENCE milestones_id_seq OWNED BY milestones.id;
+CREATE TABLE namespace_admin_notes (
+ id bigint NOT NULL,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ namespace_id bigint NOT NULL,
+ note text,
+ CONSTRAINT check_e9d2e71b5d CHECK ((char_length(note) <= 1000))
+);
+
+CREATE SEQUENCE namespace_admin_notes_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE namespace_admin_notes_id_seq OWNED BY namespace_admin_notes.id;
+
CREATE TABLE namespace_aggregation_schedules (
namespace_id integer NOT NULL
);
@@ -19510,6 +19529,8 @@ ALTER TABLE ONLY metrics_users_starred_dashboards ALTER COLUMN id SET DEFAULT ne
ALTER TABLE ONLY milestones ALTER COLUMN id SET DEFAULT nextval('milestones_id_seq'::regclass);
+ALTER TABLE ONLY namespace_admin_notes ALTER COLUMN id SET DEFAULT nextval('namespace_admin_notes_id_seq'::regclass);
+
ALTER TABLE ONLY namespace_statistics ALTER COLUMN id SET DEFAULT nextval('namespace_statistics_id_seq'::regclass);
ALTER TABLE ONLY namespaces ALTER COLUMN id SET DEFAULT nextval('namespaces_id_seq'::regclass);
@@ -20238,9 +20259,6 @@ ALTER TABLE ONLY chat_teams
ALTER TABLE vulnerability_scanners
ADD CONSTRAINT check_37608c9db5 CHECK ((char_length(vendor) <= 255)) NOT VALID;
-ALTER TABLE gitlab_subscriptions
- ADD CONSTRAINT check_77fea3f0e7 CHECK ((namespace_id IS NOT NULL)) NOT VALID;
-
ALTER TABLE sprints
ADD CONSTRAINT check_ccd8a1eae0 CHECK ((start_date IS NOT NULL)) NOT VALID;
@@ -20895,6 +20913,9 @@ ALTER TABLE ONLY milestone_releases
ALTER TABLE ONLY milestones
ADD CONSTRAINT milestones_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY namespace_admin_notes
+ ADD CONSTRAINT namespace_admin_notes_pkey PRIMARY KEY (id);
+
ALTER TABLE ONLY namespace_aggregation_schedules
ADD CONSTRAINT namespace_aggregation_schedules_pkey PRIMARY KEY (namespace_id);
@@ -23122,6 +23143,8 @@ CREATE INDEX index_mr_metrics_on_target_project_id_merged_at_nulls_last ON merge
CREATE INDEX index_mr_metrics_on_target_project_id_merged_at_time_to_merge ON merge_request_metrics USING btree (target_project_id, merged_at, created_at) WHERE (merged_at > created_at);
+CREATE INDEX index_namespace_admin_notes_on_namespace_id ON namespace_admin_notes USING btree (namespace_id);
+
CREATE UNIQUE INDEX index_namespace_aggregation_schedules_on_namespace_id ON namespace_aggregation_schedules USING btree (namespace_id);
CREATE UNIQUE INDEX index_namespace_root_storage_statistics_on_namespace_id ON namespace_root_storage_statistics USING btree (namespace_id);
@@ -25964,6 +25987,9 @@ ALTER TABLE ONLY approval_merge_request_rules_approved_approvers
ALTER TABLE ONLY operations_feature_flags_clients
ADD CONSTRAINT fk_rails_6650ed902c FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY namespace_admin_notes
+ ADD CONSTRAINT fk_rails_666166ea7b FOREIGN KEY (namespace_id) REFERENCES namespaces(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY web_hook_logs
ADD CONSTRAINT fk_rails_666826e111 FOREIGN KEY (web_hook_id) REFERENCES web_hooks(id) ON DELETE CASCADE;
diff --git a/doc/api/dora4_group_analytics.md b/doc/api/dora4_group_analytics.md
index 7504d18a5de..0938a9c22c8 100644
--- a/doc/api/dora4_group_analytics.md
+++ b/doc/api/dora4_group_analytics.md
@@ -8,10 +8,10 @@ type: reference, api
# DORA4 Analytics Group API **(ULTIMATE SELF)**
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/291747) in GitLab 13.9.
-> - It's [deployed behind a feature flag](../user/feature_flags.md), disabled by default.
-> - It's disabled on GitLab.com.
-> - It's not recommended for production use.
-> - To use it in GitLab self-managed instances, ask a GitLab administrator to [enable it](#enable-or-disable-dora4-analytics-group-api). **(ULTIMATE SELF)**
+> - [Deployed behind a feature flag](../user/feature_flags.md), disabled by default.
+> - Disabled on GitLab.com.
+> - Not recommended for production use.
+> - To use in GitLab self-managed instances, ask a GitLab administrator to [enable it](#enable-or-disable-dora4-analytics-group-api).
WARNING:
This feature might not be available to you. Check the **version history** note above for details.
diff --git a/doc/api/feature_flags.md b/doc/api/feature_flags.md
index 59f20e66ae8..fa5481b12a7 100644
--- a/doc/api/feature_flags.md
+++ b/doc/api/feature_flags.md
@@ -6,9 +6,8 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Feature Flags API **(FREE)**
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/9566) in [GitLab Premium](https://about.gitlab.com/pricing/) 12.5.
-> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/212318) to [GitLab Starter](https://about.gitlab.com/pricing/) in 13.4.
-> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/212318) to [GitLab Free](https://about.gitlab.com/pricing/) in 13.5.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/9566) in GitLab Premium 12.5.
+> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/212318) to GitLab Free in 13.5.
API for accessing resources of [GitLab Feature Flags](../operations/feature_flags.md).
diff --git a/doc/api/feature_flags_legacy.md b/doc/api/feature_flags_legacy.md
index 33ea2727fb9..6e0763b6015 100644
--- a/doc/api/feature_flags_legacy.md
+++ b/doc/api/feature_flags_legacy.md
@@ -6,9 +6,8 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Legacy Feature Flags API **(FREE)**
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/9566) in [GitLab Premium](https://about.gitlab.com/pricing/) 12.5.
-> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/212318) to [GitLab Starter](https://about.gitlab.com/pricing/) in 13.4.
-> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/212318) to [GitLab Free](https://about.gitlab.com/pricing/) in 13.5.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/9566) in GitLab Premium 12.5.
+> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/212318) to GitLab Free in 13.5.
WARNING:
This API is deprecated and [scheduled for removal in GitLab 14.0](https://gitlab.com/gitlab-org/gitlab/-/issues/213369). Use [this API](feature_flags.md) instead.
diff --git a/doc/development/documentation/index.md b/doc/development/documentation/index.md
index fe60c963f7f..4337af1db36 100644
--- a/doc/development/documentation/index.md
+++ b/doc/development/documentation/index.md
@@ -463,7 +463,8 @@ The following GitLab features are used among others:
## Testing
-For more information on documentation testing, see [Documentation testing](testing.md)
+For more information about documentation testing, see the [Documentation testing](testing.md)
+guide.
## Danger Bot
diff --git a/doc/development/documentation/structure.md b/doc/development/documentation/structure.md
index 90cbc9693b1..8d564078ea2 100644
--- a/doc/development/documentation/structure.md
+++ b/doc/development/documentation/structure.md
@@ -153,6 +153,14 @@ This issue occurs when...
The workaround is...
```
+For the topic title:
+
+- Consider including at least a partial error message in the title.
+- Use fewer than 70 characters.
+
+Remember to include the complete error message in the topics content if it is
+not complete in the title.
+
## Other information on a topic
Topics include other information.
diff --git a/doc/development/migration_style_guide.md b/doc/development/migration_style_guide.md
index ce078f78db3..30fea9b0960 100644
--- a/doc/development/migration_style_guide.md
+++ b/doc/development/migration_style_guide.md
@@ -1038,7 +1038,7 @@ To identify a high-traffic table for GitLab.com the following measures are consi
Note that the metrics linked here are GitLab-internal only:
- [Read operations](https://thanos.gitlab.net/graph?g0.range_input=2h&g0.max_source_resolution=0s&g0.expr=topk(500%2C%20sum%20by%20(relname)%20(rate(pg_stat_user_tables_seq_tup_read%7Benvironment%3D%22gprd%22%7D%5B12h%5D)%20%2B%20rate(pg_stat_user_tables_idx_scan%7Benvironment%3D%22gprd%22%7D%5B12h%5D)%20%2B%20rate(pg_stat_user_tables_idx_tup_fetch%7Benvironment%3D%22gprd%22%7D%5B12h%5D)))&g0.tab=1)
-- [Number of records](https://thanos.gitlab.net/graph?g0.range_input=2h&g0.max_source_resolution=0s&g0.expr=topk(500%2C%20sum%20by%20(relname)%20(rate(pg_stat_user_tables_n_live_tup%7Benvironment%3D%22gprd%22%7D%5B12h%5D)))&g0.tab=1)
-- [Size](https://thanos.gitlab.net/graph?g0.range_input=2h&g0.max_source_resolution=0s&g0.expr=topk(500%2C%20sum%20by%20(relname)%20(rate(pg_total_relation_size_bytes%7Benvironment%3D%22gprd%22%7D%5B12h%5D)))&g0.tab=1) is greater than 10 GB
+- [Number of records](https://thanos.gitlab.net/graph?g0.range_input=2h&g0.max_source_resolution=0s&g0.expr=topk(500%2C%20max%20by%20(relname)%20(pg_stat_user_tables_n_live_tup%7Benvironment%3D%22gprd%22%7D))&g0.tab=1)
+- [Size](https://thanos.gitlab.net/graph?g0.range_input=2h&g0.max_source_resolution=0s&g0.expr=topk(500%2C%20max%20by%20(relname)%20(pg_total_relation_size_bytes%7Benvironment%3D%22gprd%22%7D))&g0.tab=1) is greater than 10 GB
Any table which has some high read operation compared to current [high-traffic tables](https://gitlab.com/gitlab-org/gitlab/-/blob/master/rubocop/rubocop-migrations.yml#L4) might be a good candidate.
diff --git a/doc/install/azure/img/azure-add-inbound-sec-rule-http.png b/doc/install/azure/img/azure-add-inbound-sec-rule-http.png
deleted file mode 100644
index abf500cb63a..00000000000
--- a/doc/install/azure/img/azure-add-inbound-sec-rule-http.png
+++ /dev/null
Binary files differ
diff --git a/doc/install/azure/img/azure-add-inbound-sec-rule-ssh.png b/doc/install/azure/img/azure-add-inbound-sec-rule-ssh.png
deleted file mode 100644
index f7a8a04dfa7..00000000000
--- a/doc/install/azure/img/azure-add-inbound-sec-rule-ssh.png
+++ /dev/null
Binary files differ
diff --git a/doc/install/azure/img/azure-create-virtual-machine-basics-password.png b/doc/install/azure/img/azure-create-virtual-machine-basics-password.png
deleted file mode 100644
index 80bf39ecb48..00000000000
--- a/doc/install/azure/img/azure-create-virtual-machine-basics-password.png
+++ /dev/null
Binary files differ
diff --git a/doc/install/azure/img/azure-create-virtual-machine-basics.png b/doc/install/azure/img/azure-create-virtual-machine-basics.png
deleted file mode 100644
index 229c073fe17..00000000000
--- a/doc/install/azure/img/azure-create-virtual-machine-basics.png
+++ /dev/null
Binary files differ
diff --git a/doc/install/azure/img/azure-create-virtual-machine-deployment.png b/doc/install/azure/img/azure-create-virtual-machine-deployment.png
deleted file mode 100644
index 5cfdd973a58..00000000000
--- a/doc/install/azure/img/azure-create-virtual-machine-deployment.png
+++ /dev/null
Binary files differ
diff --git a/doc/install/azure/img/azure-create-virtual-machine-purchase.png b/doc/install/azure/img/azure-create-virtual-machine-purchase.png
deleted file mode 100644
index f4de62299f1..00000000000
--- a/doc/install/azure/img/azure-create-virtual-machine-purchase.png
+++ /dev/null
Binary files differ
diff --git a/doc/install/azure/img/azure-create-virtual-machine-settings.png b/doc/install/azure/img/azure-create-virtual-machine-settings.png
deleted file mode 100644
index 20097921660..00000000000
--- a/doc/install/azure/img/azure-create-virtual-machine-settings.png
+++ /dev/null
Binary files differ
diff --git a/doc/install/azure/img/azure-create-virtual-machine-size.png b/doc/install/azure/img/azure-create-virtual-machine-size.png
deleted file mode 100644
index a408394151f..00000000000
--- a/doc/install/azure/img/azure-create-virtual-machine-size.png
+++ /dev/null
Binary files differ
diff --git a/doc/install/azure/img/azure-dashboard-highlight-nsg.png b/doc/install/azure/img/azure-dashboard-highlight-nsg.png
deleted file mode 100644
index 025efd33977..00000000000
--- a/doc/install/azure/img/azure-dashboard-highlight-nsg.png
+++ /dev/null
Binary files differ
diff --git a/doc/install/azure/img/azure-dashboard-running-resources.png b/doc/install/azure/img/azure-dashboard-running-resources.png
deleted file mode 100644
index 7e661a6aa65..00000000000
--- a/doc/install/azure/img/azure-dashboard-running-resources.png
+++ /dev/null
Binary files differ
diff --git a/doc/install/azure/img/azure-dashboard.png b/doc/install/azure/img/azure-dashboard.png
deleted file mode 100644
index 375ec8622b8..00000000000
--- a/doc/install/azure/img/azure-dashboard.png
+++ /dev/null
Binary files differ
diff --git a/doc/install/azure/img/azure-inbound-sec-rules-list.png b/doc/install/azure/img/azure-inbound-sec-rules-list.png
deleted file mode 100644
index 1667671b21d..00000000000
--- a/doc/install/azure/img/azure-inbound-sec-rules-list.png
+++ /dev/null
Binary files differ
diff --git a/doc/install/azure/img/azure-new-gitlab-ce.png b/doc/install/azure/img/azure-new-gitlab-ce.png
deleted file mode 100644
index 88949f69a94..00000000000
--- a/doc/install/azure/img/azure-new-gitlab-ce.png
+++ /dev/null
Binary files differ
diff --git a/doc/install/azure/img/azure-new-search-gitlab.png b/doc/install/azure/img/azure-new-search-gitlab.png
deleted file mode 100644
index f96ed577d62..00000000000
--- a/doc/install/azure/img/azure-new-search-gitlab.png
+++ /dev/null
Binary files differ
diff --git a/doc/install/azure/img/azure-nsg-inbound-sec-rules-add-highlight.png b/doc/install/azure/img/azure-nsg-inbound-sec-rules-add-highlight.png
deleted file mode 100644
index c9a08b87ce6..00000000000
--- a/doc/install/azure/img/azure-nsg-inbound-sec-rules-add-highlight.png
+++ /dev/null
Binary files differ
diff --git a/doc/install/azure/img/azure-nsg-inbound-sec-rules-highlight.png b/doc/install/azure/img/azure-nsg-inbound-sec-rules-highlight.png
deleted file mode 100644
index 6423625ca8b..00000000000
--- a/doc/install/azure/img/azure-nsg-inbound-sec-rules-highlight.png
+++ /dev/null
Binary files differ
diff --git a/doc/install/azure/img/azure-vm-domain-name.png b/doc/install/azure/img/azure-vm-domain-name.png
deleted file mode 100644
index 01c03004b24..00000000000
--- a/doc/install/azure/img/azure-vm-domain-name.png
+++ /dev/null
Binary files differ
diff --git a/doc/install/azure/img/azure-vm-management-public-ip.png b/doc/install/azure/img/azure-vm-management-public-ip.png
deleted file mode 100644
index ef313641db8..00000000000
--- a/doc/install/azure/img/azure-vm-management-public-ip.png
+++ /dev/null
Binary files differ
diff --git a/doc/install/azure/img/gitlab-admin-area-9.4.0.png b/doc/install/azure/img/gitlab-admin-area-9.4.0.png
deleted file mode 100644
index b7ee4598731..00000000000
--- a/doc/install/azure/img/gitlab-admin-area-9.4.0.png
+++ /dev/null
Binary files differ
diff --git a/doc/install/azure/img/gitlab-admin-area.png b/doc/install/azure/img/gitlab-admin-area.png
deleted file mode 100644
index 028f0b0a0eb..00000000000
--- a/doc/install/azure/img/gitlab-admin-area.png
+++ /dev/null
Binary files differ
diff --git a/doc/install/azure/img/gitlab-change-password.png b/doc/install/azure/img/gitlab-change-password.png
deleted file mode 100644
index 7350d604d56..00000000000
--- a/doc/install/azure/img/gitlab-change-password.png
+++ /dev/null
Binary files differ
diff --git a/doc/install/azure/img/gitlab-home.png b/doc/install/azure/img/gitlab-home.png
deleted file mode 100644
index 7c935805ea2..00000000000
--- a/doc/install/azure/img/gitlab-home.png
+++ /dev/null
Binary files differ
diff --git a/doc/install/azure/img/gitlab-login.png b/doc/install/azure/img/gitlab-login.png
deleted file mode 100644
index 95fe5aec1e0..00000000000
--- a/doc/install/azure/img/gitlab-login.png
+++ /dev/null
Binary files differ
diff --git a/doc/install/azure/img/gitlab-new-project.png b/doc/install/azure/img/gitlab-new-project.png
deleted file mode 100644
index 3b6b9a81682..00000000000
--- a/doc/install/azure/img/gitlab-new-project.png
+++ /dev/null
Binary files differ
diff --git a/doc/install/azure/img/gitlab-project-home-empty.png b/doc/install/azure/img/gitlab-project-home-empty.png
deleted file mode 100644
index 54d0b36a251..00000000000
--- a/doc/install/azure/img/gitlab-project-home-empty.png
+++ /dev/null
Binary files differ
diff --git a/doc/install/azure/img/gitlab-project-home-instructions.png b/doc/install/azure/img/gitlab-project-home-instructions.png
deleted file mode 100644
index fd040d33e95..00000000000
--- a/doc/install/azure/img/gitlab-project-home-instructions.png
+++ /dev/null
Binary files differ
diff --git a/doc/install/azure/img/gitlab-ssh-update-in-progress.png b/doc/install/azure/img/gitlab-ssh-update-in-progress.png
deleted file mode 100644
index 8a686ebde26..00000000000
--- a/doc/install/azure/img/gitlab-ssh-update-in-progress.png
+++ /dev/null
Binary files differ
diff --git a/doc/install/azure/index.md b/doc/install/azure/index.md
index 0c0a4457413..8fb400c796e 100644
--- a/doc/install/azure/index.md
+++ b/doc/install/azure/index.md
@@ -8,443 +8,316 @@ type: howto
# Install GitLab on Microsoft Azure **(FREE SELF)**
-WARNING:
-This guide is deprecated and pending an update. For the time being, use the GitLab
-[image in the Azure Marketplace](https://azuremarketplace.microsoft.com/en-us/marketplace/apps/gitlabinc1586447921813.gitlabee?tab=Overview).
-
-Azure is Microsoft's business cloud and GitLab is a pre-configured offering on
-the Azure Marketplace. Hopefully, you aren't surprised to hear that Microsoft
-and Azure have embraced open source software like Ubuntu, Red Hat Enterprise Linux,
-and of course - GitLab! This means that you can spin up a pre-configured
-GitLab VM and have your very own private GitLab up and running in around 30
-minutes. Let's get started.
-
-## Getting started
-
-First, you'll need an account on Azure. There are three ways to do this:
-
-- If your company (or you) already has an account, then you are ready to go!
-- You can also open your own Azure account for free. _At time of writing_, you get $200
- of credit to spend on Azure services for 30 days. You can use this credit to try out paid Azure
- services, exploring Microsoft's cloud for free. Even after the first 30 days, you never have to pay
- anything unless you decide to transition to paid services with a Pay-As-You-Go Azure subscription.
- This is a great way to try out Azure and cloud computing, and you can
- [read more in their comprehensive FAQ](https://azure.microsoft.com/en-us/free/free-account-faq/).
-- If you have an MSDN subscription, you can activate your Azure subscriber benefits. Your MSDN
- subscription gives you recurring Azure credits every month, so why not put those credits to use and
- try out GitLab right now?
-
-## Working with Azure
-
-Once you have an Azure account, you can get started. [Log in to Azure](https://portal.azure.com)
-and the first thing you will see is the Dashboard:
-
-![Azure Dashboard](img/azure-dashboard.png)
-
-The Dashboard gives you a quick overview of Azure resources, and from here you can build VMs,
-create SQL Databases, author websites, and perform lots of other cloud tasks.
-
-## Create New VM
-
-The [Azure Marketplace](https://azuremarketplace.microsoft.com/en-us/marketplace/) is an online store for pre-configured applications and
-services which have been optimized for the cloud by software vendors like GitLab,
-available on the Azure Marketplace as pre-configured solutions. In this tutorial
-we will install GitLab Community Edition.
-
-To begin creating a new GitLab VM, click on the **+ New** icon, type "GitLab" into the search
-box, and then click the **"GitLab Community Edition"** search result:
-
-![Azure - New - Search for 'GitLab'](img/azure-new-search-gitlab.png)
-
-A new "blade" window will pop-out, where you can read more about the **"GitLab Community Edition"**
-offering which is freely available under the MIT Expat License:
-
-![Azure - New - Select 'GitLab Community Edition'](img/azure-new-gitlab-ce.png)
-
-Click **"Create"** and you will be presented with the "Create virtual machine" blade:
-
-![Azure - Create Virtual Machine - Basics](img/azure-create-virtual-machine-basics.png)
-
-## Basics
-
-The first items we need to configure are the basic settings of the underlying virtual machine:
-
-1. Enter a `Name` for the VM - e.g. **"GitLab-CE"**
-1. Select a `VM disk type` - either **HDD** _(slower, lower cost)_ or **SSD** _(faster, higher cost)_
-1. Enter a `User name` - e.g. `gitlab-admin`
-1. Select an `Authentication type`, either **SSH public key** or **Password**:
-
- NOTE:
- If you're unsure which authentication type to use, select **Password**
+For users of the Microsoft Azure business cloud, GitLab has a pre-configured offering in
+the [Azure Marketplace](https://azuremarketplace.microsoft.com/en-us/marketplace/).
+This tutorial describes installing GitLab
+Enterprise Edition in a single Virtual Machine (VM).
- 1. If you chose **SSH public key** - enter your `SSH public key` into the field provided
- _(read the [SSH documentation](../../ssh/README.md) to learn more about how to set up SSH
- public keys)_
- 1. If you chose **Password** - enter the password you wish to use _(this is the password that you
- will use later in this tutorial to [SSH](https://en.wikipedia.org/wiki/Secure_Shell) into the VM, so make sure it's a strong password/passphrase)_
+## Prerequisite
-1. Choose the appropriate `Subscription` tier for your Azure account
-1. Choose an existing `Resource Group` or create a new one - e.g. **"GitLab-CE-Azure"**
+You'll need an account on Azure. Use of the following methods to obtain an account:
- NOTE:
- A "Resource group" is a way to group related resources together for easier administration.
- We chose "GitLab-CE-Azure", but your resource group can have the same name as your VM.
-
-1. Choose a `Location` - if you're unsure, select the default location
-
-Here are the settings we've used:
-
-![Azure - Create Virtual Machine - Basics Completed](img/azure-create-virtual-machine-basics-password.png)
-
-Check the settings you have entered, and then click **"OK"** when you're ready to proceed.
-
-## Size
+- If you or your company already have an account with a subscription, use that account.
+ If not, you can [open your own Azure account for free](https://azure.microsoft.com/en-us/free/).
+ Azure's free trial gives you $200 credit to explore Azure for 30 days.
+ [Read more in Azure's comprehensive FAQ](https://azure.microsoft.com/en-us/free/free-account-faq/).
+- If you have an MSDN subscription, you can activate your Azure subscriber benefits. Your MSDN
+ subscription gives you recurring Azure credits every month, so you can use
+ those credits and try out GitLab.
-Next, you need to choose the size of your VM - selecting features such as the number of CPU cores,
-the amount of RAM, the size of storage (and its speed), etc.
+## Deploy and configure GitLab
-NOTE:
-In common with other cloud vendors, Azure operates a resource/usage pricing model, i.e.
-the more resources your VM consumes the more it will cost you to run, so make your selection
-carefully. You'll see that Azure provides an _estimated_ monthly cost beneath each VM Size to help
-guide your selection.
+Because GitLab is already installed in a pre-configured image, all you have to do is
+create a new VM:
-The default size - the lowest cost **"DS1_V2 Standard"** VM - meets the minimum system requirements
-to run a small GitLab environment for testing and evaluation purposes, and so we're going to go
-ahead and select this one, but please choose the size which best meets your own requirements:
+1. [Visit the GitLab offering in the marketplace](https://azuremarketplace.microsoft.com/en-us/marketplace/apps/gitlabinc1586447921813.gitlabee?tab=Overview)
+1. Select **Get it now** and you will be presented with the **Create this app in Azure** window.
+ Select **Continue**.
+1. Select one of the following options from the Azure portal:
+ - Select **Create** to create a VM from scratch.
+ - Select **Start with a pre-set configuration** to get started with some
+ pre-configured options. You can modify these configurations at any time.
-![Azure - Create Virtual Machine - Size](img/azure-create-virtual-machine-size.png)
+For the sake of this guide, we'll create the VM from scratch, so
+select **Create**.
NOTE:
-Be aware that while your VM is active (known as "allocated"), it will incur
-"compute charges" which, ultimately, you will be billed for. So, even if you're using the
-free trial credits, you'll likely want to learn
+Be aware that while your VM is active (known as "allocated"), it incurs
+compute charges for which you'll be billed. Even if you're using the
+free trial credits, you'll want to know
[how to properly shutdown an Azure VM to save money](https://build5nines.com/properly-shutdown-azure-vm-to-save-money/).
+See the [Azure pricing calculator](https://azure.microsoft.com/en-us/pricing/calculator/)
+to learn how much resources can cost.
-Go ahead and click your chosen size, then click **"Select"** when you're ready to proceed to the
-next step.
+After you create the virtual machine, use the information in the following
+sections to configure it.
-## Settings
+### Configure the Basics tab
-On the next blade, you're asked to configure the Storage, Network and Extension settings.
-We've gone with the default settings as they're sufficient for test-driving GitLab, but please
-choose the settings which best meet your own requirements:
+The first items you need to configure are the basic settings of the underlying virtual machine:
-![Azure - Create Virtual Machine - Settings](img/azure-create-virtual-machine-settings.png)
+1. Select the subscription model and a resource group (create a new one if it
+ doesn't exist).
+1. Enter a name for the VM, for example `GitLab`.
+1. Select a region.
+1. In **Availability options**, select **Availability zone** and set it to `1`.
+ Read more about the [availability zones](https://docs.microsoft.com/en-us/azure/virtual-machines/availability).
+1. Ensure the selected image is set to **GitLab - Gen1**.
+1. Select the VM size based on the [hardware requirements](../requirements.md#hardware-requirements).
+ Because the minimum system requirements to run a GitLab environment for up to 500 users
+ is covered by the `D4s_v3` size, select that option.
+1. Set the authentication type to **SSH public key**.
+1. Enter a user name or leave the one that is automatically created. This is
+ the user you'll use to connect to the VM through SSH. By default, the user
+ has root access.
+1. Determine if you want to provide your own SSH key or let Azure create one for you.
+ Read the [SSH documentation](../../ssh/README.md) to learn more about how to set up SSH
+ public keys.
-Review the settings and then click **"OK"** when you're ready to proceed to the last step.
+Review your entered settings, and then proceed to the Disks tab.
-## Purchase
+### Configure the Disks tab
-The Purchase page is the last step and here you will be presented with the price per hour for your
-new VM. You'll be billed only for the VM itself (e.g. "Standard DS1 v2") because the
-**"GitLab Community Edition"** marketplace solution is free to use at 0 USD/hr:
+For the disks:
-![Azure - Create Virtual Machine - Purchase](img/azure-create-virtual-machine-purchase.png)
+1. For the OS disk type, select **Premium SSD**.
+1. Select the default encryption.
-NOTE:
-At this stage, you can review and modify the any of the settings you have made during all
-previous steps, just click on any of the four steps to re-open them.
+[Read more about the types of disks](https://docs.microsoft.com/en-us/azure/virtual-machines/managed-disks-overview) that Azure provides.
-When you have read and agreed to the terms of use and are ready to proceed, click **"Purchase"**.
+Review your settings, and then proceed to the Networking tab.
-## Deployment
+### Configure the Networking tab
-At this point, Azure will begin deploying your new VM. The deployment process will take a few
-minutes to complete, with progress displayed on the **"Deployment"** blade:
+Use this tab to define the network connectivity for your
+virtual machine, by configuring network interface card (NIC) settings.
+You can leave them at their default settings.
-![Azure - Create Virtual Machine - Deployment](img/azure-create-virtual-machine-deployment.png)
+Azure creates a security group by default and the VM is assigned to it.
+The GitLab image in the marketplace has the following ports open by default:
-Once the deployment process is complete, the new VM and its associated resources will be displayed
-on the Azure Dashboard (you may need to refresh the page):
+| Port | Description |
+|------|-------------|
+| 80 | Enable the VM to respond to HTTP requests, allowing public access. |
+| 443 | Enable our VM to respond to HTTPS requests, allowing public access. |
+| 22 | Enable our VM to respond to SSH connection requests, allowing public access (with authentication) to remote terminal sessions. |
-![Azure - Dashboard - All resources](img/azure-dashboard-running-resources.png)
+If you want to change the ports or add any rules, you can do it
+after the VM is created by going to the Networking settings in the left sidebar,
+while in the VM dashboard.
-The new VM can also be accessed by clicking the `All resources` or `Virtual machines` icons in the
-Azure Portal sidebar navigation menu.
+### Configure the Management tab
-## Set up a domain name
+Use this tab to configure monitoring and management options
+for your VM. You don't need to change the default settings.
-The VM will have a public IP address (static by default), but Azure allows us to assign a friendly
-DNS name to the VM, so let's go ahead and do that.
+### Configure the Advanced tab
-From the Dashboard, click on the **"GitLab-CE"** tile to open the management blade for the new VM.
-The public IP address that the VM uses is shown in the 'Essentials' section:
+Use this tab to add additional configuration, agents, scripts
+or applications through virtual machine extensions or `cloud-init`. You don't
+need to change the default settings.
-![Azure - VM - Management - Public IP Address](img/azure-vm-management-public-ip.png)
+### Configure the Tags tab
-Click on the public IP address - which should open the **"Public IP address - Configuration"** blade,
-then click on **"Configuration"** (under "Settings"). Now enter a friendly DNS name for your instance
-in the `DNS name label` field:
+Use this tab to add name/value pairs that enable you to categorize
+resources. You don't need to change the default settings.
-![Azure - VM - Domain Name](img/azure-vm-domain-name.png)
+### Review and create the VM
-In the screenshot above, you'll see that we've set the `DNS name label` to `gitlab-ce-test`.
-This will make our VM accessible at `gitlab-ce-test.centralus.cloudapp.azure.com`
-_(the full domain name of your own VM will be different, of course)_.
+The final tab presents you with all of your selected options,
+where you can review and modify your choices from the
+previous steps. Azure will run validation tests in the background,
+and if you provided all of the required settings, you can
+create the VM.
-Click **"Save"** for the changes to take effect.
+After you select **Create**, if you had opted for Azure to create an SSH key pair
+for you, you'll be asked to download the private SSH key. Download the key, as you'll
+need it to SSH into the VM.
-NOTE:
-If you want to use your own domain name, you will need to add a DNS `A` record at your
-domain registrar which points to the public IP address of your Azure VM. If you do this, you'll need
-to make sure your VM is configured to use a _static_ public IP address (i.e. not a _dynamic_ one)
-or you will have to reconfigure the DNS `A` record each time Azure reassigns your VM a new public IP
-address. Read [Public IP addresses](https://docs.microsoft.com/en-us/azure/virtual-network/public-ip-addresses) to learn more.
-
-## Let's open some ports
-
-At this stage you should have a running and fully operational VM. However, none of the services on
-your VM (e.g. GitLab) will be publicly accessible via the internet until you have opened up the
-necessary ports to enable access to those services.
-
-Ports are opened by adding _security rules_ to the **"Network security group"** (NSG) which our VM
-has been assigned to. If you followed the process above, then Azure will have automatically created
-an NSG named `GitLab-CE-nsg` and assigned the `GitLab-CE` VM to it.
+After you download the key, the deployment begins.
-NOTE:
-If you gave your VM a different name then the NSG automatically created by Azure will
-also have a different name - the name you have your VM, with `-nsg` appended to it.
+### Finish deployment
-You can navigate to the NSG settings via many different routes in the Azure Portal, but one of the
-simplest ways is to go to the Azure Dashboard, and then click on the Network Security Group listed
-in the **"All resources"** tile:
+At this point, Azure begins to deploy your new VM. The deployment process
+takes a few minutes to complete. After it's complete, the new VM and its
+associated resources are displayed on the Azure Dashboard.
+Select **Go to resource** to visit the dashboard of the VM.
-![Azure - Dashboard - All resources - Network security group](img/azure-dashboard-highlight-nsg.png)
+GitLab is now deployed and ready to be used. Before doing so, however,
+you need to set up the domain name and configure GitLab to use it.
-With the **"Network security group"** blade open, click on **"Inbound security rules"** under
-**"Settings"**:
+### Set up a domain name
-![Azure - Network security group - Inbound security rules](img/azure-nsg-inbound-sec-rules-highlight.png)
+The VM has a public IP address (static by default), but Azure allows you
+to assign a descriptive DNS name to the VM:
-Next, click **"Add"**:
+1. From the VM dashboard, select **Configure** under **DNS name**.
+1. Enter a descriptive DNS name for your instance in the **DNS name label** field,
+ for example `gitlab-prod`. This will make the VM accessible at
+ `gitlab-prod.eastus.cloudapp.azure.com`.
+1. Select **Save** for the changes to take effect.
-![Azure - Network security group - Inbound security rules - Add](img/azure-nsg-inbound-sec-rules-add-highlight.png)
+Eventually, you'll want to use your own domain name. To do this, you need to add a DNS `A` record
+with your domain registrar that points to the public IP address of your Azure VM.
+You can use [Azure's DNS](https://docs.microsoft.com/en-us/azure/dns/dns-delegate-domain-azure-dns)
+or some [other registrar](https://docs.gitlab.com/omnibus/settings/dns.html).
-### Which ports to open?
+### Change the GitLab external URL
-Like all servers, our VM will be running many services. However, we want to open up the correct
-ports to enable public internet access to two services in particular:
+GitLab uses `external_url` in its configuration file to set up the domain name.
+If you don't set this up, when you visit the Azure friendly name, you'll
+instead be redirected to the public IP.
-1. **HTTP** (port 80) - opening port 80 will enable our VM to respond to HTTP requests, allowing
- public access to the instance of GitLab running on our VM.
-1. **SSH** (port 22) - opening port 22 will enable our VM to respond to SSH connection requests,
- allowing public access (with authentication) to remote terminal sessions
- _(you'll see why we need [SSH](https://en.wikipedia.org/wiki/Secure_Shell) access to our VM [later on in this tutorial](#maintaining-your-gitlab-instance))_
+To set up the GitLab external URL:
-### Open HTTP on Port 80
+1. Connect to GitLab through SSH by going to **Settings > Connect** from the VM
+ dashboard, and follow the instructions. Remember to sign in with the username
+ and SSH key you specified when you [created the VM](#configure-the-basics-tab).
+ The Azure VM domain name will be the one you
+ [set up previously](#set-up-a-domain-name). If you didn't set up a domain name for
+ your VM, you can use the IP address in its place.
-In the **"Add inbound security rule"** blade, let's open port 80 so that our VM will accept HTTP
-connections:
+ In the case of our example:
-![Azure - Add inbound security rules - HTTP](img/azure-add-inbound-sec-rule-http.png)
+ ```shell
+ ssh -i <private key path> gitlab-azure@gitlab-prod.eastus.cloudapp.azure.com
+ ```
-1. Enter **"HTTP"** in the `Name` field
-1. Select **HTTP** from the options in the `Service` dropdown list
-1. Make sure the `Action` is set to **Allow**
-1. Click **"OK"**
+ NOTE:
+ If you need to reset your credentials, read
+ [how to reset SSH credentials for a user on an Azure VM](https://docs.microsoft.com/en-us/troubleshoot/azure/virtual-machines/troubleshoot-ssh-connection#reset-ssh-credentials-for-a-user).
-### Open SSH on Port 22
+1. Open `/etc/gitlab/gitlab.rb` with your editor.
+1. Find `external_url` and replace it with your own domain name. For the sake
+ of this example, we'll use the friendly domain name that Azure set up.
+ If you use `https` in the URL, Let's Encrypt will be
+ [automatically enabled](https://docs.gitlab.com/omnibus/settings/ssl.html#lets-encrypt-integration),
+ and you'll have HTTPS by default:
-Repeat the above process, adding a second Inbound security rule to open port 22, enabling our VM to
-accept [SSH](https://en.wikipedia.org/wiki/Secure_Shell) connections:
+ ```ruby
+ external_url 'https://gitlab-prod.eastus.cloudapp.azure.com'
+ ```
-![Azure - Add inbound security rules - SSH](img/azure-add-inbound-sec-rule-ssh.png)
+1. Find the following settings and comment them out, so that GitLab doesn't
+ pick up the wrong certificates:
-1. Enter **"SSH"** in the `Name` field
-1. Select **SSH** from the options in the `Service` dropdown list
-1. Make sure the `Action` is set to **Allow**
-1. Click **"OK"**
+ ```ruby
+ # nginx['redirect_http_to_https'] = true
+ # nginx['ssl_certificate'] = "/etc/gitlab/ssl/server.crt"
+ # nginx['ssl_certificate_key'] = "/etc/gitlab/ssl/server.key"
+ ```
-It will take a moment for Azure to add each new Inbound Security Rule (and you may need to click on
-**"Inbound security rules"** to refresh the list), but once completed, you should see the two new
-rules in the list:
+1. Reconfigure GitLab for the changes to take effect. Run the
+ following command every time you make changes to `/etc/gitlab/gitlab.rb`:
-![Azure - Inbound security rules - List](img/azure-inbound-sec-rules-list.png)
+ ```shell
+ sudo gitlab-ctl reconfigure
+ ```
-## Connecting to GitLab
+You can now visit GitLab with your browser at the new external URL.
-Use the domain name you set up earlier (or the public IP address) to visit your new GitLab instance
-in your browser. If everything has gone according to plan you should be presented with the
-following page, asking you to set a _new_ password for the administrator account automatically
-created by GitLab:
+### Visit GitLab for the first time
-![GitLab - Change Password](img/gitlab-change-password.png)
+Use the domain name you set up earlier to visit your new GitLab instance
+in your browser. In this example, it's `https://gitlab-prod.eastus.cloudapp.azure.com`.
-Enter your _new_ password into both form fields, and then click **"Change your password"**.
+The first thing you'll see is the sign-in page. GitLab creates an admin user by default.
+The credentials are:
-Once you have changed the password you will be redirected to the GitLab login page. Use `root` as
-the username, enter the new password you set in the previous step, and then click **"Sign in"**:
+- Username: `root`
+- Password: the password is automatically created, and there are [two ways to
+ find it](https://docs.bitnami.com/azure/faq/get-started/find-credentials).
-![GitLab - Login](img/gitlab-login.png)
+After signing in, be sure to immediately [change the password](../../user/profile/index.md#change-your-password).
-### Success?
+## Maintain your GitLab instance
-After signing in successfully, you should see the GitLab Projects page displaying a
-**"Welcome to GitLab!"** message:
+It's important to keep your GitLab environment up-to-date. The GitLab team is constantly making
+enhancements and occasionally you may need to update for security reasons. Use the information
+in this section whenever you need to update GitLab.
-![GitLab - Projects Page](img/gitlab-home.png)
+### Check the current version
-If so, you now have a working GitLab instance on your own private Azure VM. **Congratulations!**
+To determine the version of GitLab you're currently running,
+go to the **{admin}** **Admin Area**, and you will find the version
+under the **Components** table.
-## Creating your first GitLab project
+If there's a newer available version of GitLab that contains one or more
+security fixes, GitLab displays an **Update asap** notification message that
+encourages you to [update](#update-gitlab).
-You can skip this section if you are familiar with Git and GitLab. Otherwise, let's create our first
-project. From the Welcome page, click **"New Project"**.
+### Update GitLab
-Let's give our project a name and a description, and then accept the default values for everything
-else:
+To update GitLab to the latest version:
-1. Enter **"demo"** into the `Project path` project name field
-1. Enter a `description`, e.g. **"My awesome demo project!"**
-1. Click **"Create project"**
+1. Connect to the VM through SSH.
+1. Update GitLab:
-![GitLab - New Project](img/gitlab-new-project.png)
+ ```shell
+ sudo apt update
+ sudo apt install gitlab-ee
+ ```
-Once the new project has been created (which should only take a moment), you'll be redirected to
-homepage for the project:
+ This command updates GitLab and its associated components to the latest versions,
+ and can take time to complete. You'll see various update tasks being
+ completed in your terminal.
-![GitLab - Empty Project](img/gitlab-project-home-empty.png)
+ NOTE:
+ If you get an error like
+ `E: The repository 'https://packages.gitlab.com/gitlab/gitlab-ee/debian buster InRelease' is not signed.`,
+ see the [troubleshooting section](#update-the-gpg-key-for-the-gitlab-repositories).
-If you scroll further down the project's home page, you'll see some basic instructions on how to
-set up a local clone of your new repository and push and pull from it:
+1. After the update process is complete, you'll see a message like the
+ following:
-![GitLab - Empty Project - Basic Instructions](img/gitlab-project-home-instructions.png)
+ ```plaintext
+ Upgrade complete! If your GitLab server is misbehaving try running
-**That's it! You now have your own private GitLab environment installed and running in the cloud!**
+ sudo gitlab-ctl restart
-## Maintaining your GitLab instance
+ before anything else.
+ ```
-It's important to keep your GitLab environment up-to-date. The GitLab team is constantly making
-enhancements and occasionally you may need to update for security reasons. So let's review how to
-update GitLab.
+Refresh your GitLab instance in the browser and go to the Admin Area. You should now have an
+up-to-date GitLab instance.
-### Checking our current version
+## Next steps and further configuration
-To check which version of GitLab we're currently running, click on the "Admin Area" link - it's the
-the wrench icon displayed in the top-right, next to the search box.
+Now that you have a functional GitLab instance, follow the
+[next steps](../index.md#next-steps) to learn what more you can do with your
+new installation.
-In the following screenshot you can see an **"update asap"** notification message in the top-right.
-This particular message indicates that there is a newer version of GitLab available which contains
-one or more security fixes:
+## Troubleshooting
-![GitLab - update asap](img/gitlab-admin-area.png)
+This section describes common errors you can encounter.
-Under the **"Components"** section, we can see that our VM is currently running version `8.6.5` of
-GitLab. This is the version of GitLab which was contained in the Azure Marketplace
-**"GitLab Community Edition"** offering we used to build the VM when we wrote this tutorial.
+### Update the GPG key for the GitLab repositories
NOTE:
-The version of GitLab in your own VM instance may well be different, but the update
-process will still be the same.
-
-### Connect via SSH
-
-To perform an update, we need to connect directly to our Azure VM instance and run some commands
-from the terminal. Our Azure VM is actually a server running Linux (Ubuntu), so we'll need to
-connect to it using SSH ([Secure Shell](https://en.wikipedia.org/wiki/Secure_Shell)).
-
-If you're running Windows, you'll need to connect using [PuTTY](https://www.putty.org) or an equivalent Windows SSH client.
-If you're running Linux or macOS, then you already have an SSH client installed.
+This is a temporary fix until the GitLab image is updated with the new
+GPG key.
-Remember to sign in with the username and password you specified when you
-[created your Azure VM](#basics).
+The pre-configured GitLab image in Azure (provided by Bitnami) uses
+a GPG key [deprecated in April 2020](https://about.gitlab.com/blog/2020/03/30/gpg-key-for-gitlab-package-repositories-metadata-changing/).
-If you need to reset your VM password, read
-[how to reset SSH credentials for a user on an Azure VM](https://docs.microsoft.com/en-us/troubleshoot/azure/virtual-machines/troubleshoot-ssh-connection).
+If you try to update the repositories, you'll get the following error:
-#### SSH from the command-line
+<!-- vale gitlab.ReferenceLinks = NO -->
-If you're running [SSH](https://en.wikipedia.org/wiki/Secure_Shell) from the command-line (terminal), then type in the following command to
-connect to your VM, substituting `username` and `your-azure-domain-name.com` for the correct values.
-
-Again, remember that your Azure VM domain name will be the one you
-[set up previously in the tutorial](#set-up-a-domain-name). If you didn't set up a domain name for
-your VM, you can use the IP address in its place in the following command:
-
-```shell
-ssh username@your-azure-domain-name.com
+```plaintext
+[ 21.023494] apt-setup[1198]: W: GPG error: https://packages.gitlab.com/gitlab/gitlab-ee/debian buster InRelease: The following signatures couldn't be verified because the public key is not available: NO_PUBKEY 3F01618A51312F3F
+[ 21.024033] apt-setup[1198]: E: The repository 'https://packages.gitlab.com/gitlab/gitlab-ee/debian buster InRelease' is not signed.
```
-Provide your password at the prompt to authenticate.
+<!-- vale gitlab.ReferenceLinks = YES -->
-#### SSH from Windows (PuTTY)
-
-If you're using [PuTTY](https://www.putty.org) in Windows as your [SSH](https://en.wikipedia.org/wiki/Secure_Shell) client, then you might want to take a quick
-read on [using PuTTY in Windows](https://mediatemple.net/community/products/dv/204404604/using-ssh-in-putty-).
-
-### Updating GitLab
-
-After signing in by using SSH, enter the following command to update GitLab to
-the latest version:
+To fix this, fetch the new GPG key:
```shell
-sudo apt-get update && sudo apt-get install gitlab-ce
-```
-
-This command updates GitLab and its associated components to the latest versions,
-so it will take a little time to complete. You'll see various update tasks being
-completed in your SSH terminal window:
-
-![GitLab updating](img/gitlab-ssh-update-in-progress.png)
-
-After the update process is complete, you'll see a message like this:
-
-```plaintext
-Upgrade complete! If your GitLab server is misbehaving try running
-
- sudo gitlab-ctl restart
-
-before anything else.
+sudo apt install gpg-agent
+curl "https://gitlab-org.gitlab.io/omnibus-gitlab/gitlab_new_gpg.key" --output /tmp/omnibus_gitlab_gpg.key
+sudo apt-key add /tmp/omnibus_gitlab_gpg.key
```
-#### Check out your updated GitLab
-
-Refresh your GitLab instance in the browser and navigate to the Admin Area. You should now have an
-up-to-date GitLab instance.
-
-When we wrote this tutorial our Azure VM GitLab instance was updated to the latest version at time
-of writing (`9.4.0`). You can see that the message which was previously displaying **"update asap"**
-is now showing **"up-to-date"**:
-
-![GitLab up to date](img/gitlab-admin-area-9.4.0.png)
-
-## Conclusion
-
-Naturally, we believe that GitLab is a great Git repository tool. However, GitLab is a whole lot
-more than that too. GitLab unifies issues, code review, CI and CD into a single UI, helping you to
-move faster from idea to production, and in this tutorial we showed you how quick and easy it is to
-set up and run your own instance of GitLab on Azure, Microsoft's cloud service.
-
-Azure is a great way to experiment with GitLab, and if you decide (as we hope) that GitLab is for
-you, you can continue to use Azure as your secure, scalable cloud provider or of course run GitLab
-on any cloud service you choose.
-
-## Where to next?
-
-Check out our other [Technical Articles](../../topics/index.md) or browse the [GitLab Documentation](../../README.md) to learn more about GitLab.
-
-### Useful links
-
-- [GitLab Community Edition](https://about.gitlab.com/features/)
-- [GitLab Enterprise Edition](https://about.gitlab.com/features/#ee)
-- [Microsoft Azure](https://azure.microsoft.com/en-us/)
- - [Azure - Free Account FAQ](https://azure.microsoft.com/en-us/free/free-account-faq/)
- - [Azure - Marketplace](https://azuremarketplace.microsoft.com/en-us/marketplace/)
- - [Azure Portal](https://portal.azure.com)
- - [Azure - Pricing Calculator](https://azure.microsoft.com/en-us/pricing/calculator/)
- - [Azure - Troubleshoot SSH Connections to an Azure Linux VM](https://docs.microsoft.com/en-us/troubleshoot/azure/virtual-machines/troubleshoot-ssh-connection)
- - [Azure - Properly Shutdown an Azure VM](https://build5nines.com/properly-shutdown-azure-vm-to-save-money/)
-- [SSH](https://en.wikipedia.org/wiki/Secure_Shell), [PuTTY](https://www.putty.org) and [Using SSH in PuTTY](https://mediatemple.net/community/products/dv/204404604/using-ssh-in-putty-)
-
-<!-- ## Troubleshooting
-
-Include any troubleshooting steps that you can foresee. If you know beforehand what issues
-one might have when setting this up, or when something is changed, or on upgrading, it's
-important to describe those, too. Think of things that may go wrong and include them here.
-This is important to minimize requests for support and to avoid doc comments with
-questions that you know someone might ask.
-
-Each scenario can be a third-level heading, e.g. `### Getting error message X`.
-If you have none to add when creating a doc, leave this section in place
-but commented out to help encourage others to add to it in the future. -->
+You can now [update GitLab](#update-gitlab). For more information, read about the
+[packages signatures](https://docs.gitlab.com/omnibus/update/package_signatures.html).
diff --git a/doc/subscriptions/self_managed/index.md b/doc/subscriptions/self_managed/index.md
index 67f53020a8e..d0fc0ff62b9 100644
--- a/doc/subscriptions/self_managed/index.md
+++ b/doc/subscriptions/self_managed/index.md
@@ -200,7 +200,7 @@ An invoice is generated for the renewal and available for viewing or download on
### Seat Link
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/208832) in [GitLab Starter](https://about.gitlab.com/pricing/) 12.9.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/208832) in GitLab 12.9.
Seat Link allows GitLab Inc. to provide our GitLab self-managed customers with prorated charges for user growth throughout the year using a quarterly reconciliation process.
@@ -269,7 +269,7 @@ You can view the exact JSON payload in the administration panel. To view the pay
#### Disable Seat Link
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/212375) in [GitLab Starter](https://about.gitlab.com/pricing/) 12.10.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/212375) in GitLab 12.10.
Seat Link is enabled by default.
diff --git a/doc/user/packages/container_registry/index.md b/doc/user/packages/container_registry/index.md
index 30811a46b25..fe6da524241 100644
--- a/doc/user/packages/container_registry/index.md
+++ b/doc/user/packages/container_registry/index.md
@@ -670,8 +670,8 @@ and stored by Docker, it is not possible for GitLab to parse this data and meet
## Limitations
- 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
+once you have pushed images, because the images are stored in a path that matches
+the repository path. To move or rename a repository with a
Container Registry, you must delete all existing images.
- Prior to GitLab 12.10, any tags that use the same image ID as the `latest` tag
are not deleted by the cleanup policy.
diff --git a/doc/user/permissions.md b/doc/user/permissions.md
index 4ecf9cc0832..2fe9df9f29f 100644
--- a/doc/user/permissions.md
+++ b/doc/user/permissions.md
@@ -93,7 +93,6 @@ The following table depicts the various user permission levels in a project.
| View Code Review analytics **(STARTER)** | | ✓ | ✓ | ✓ | ✓ |
| View Repository analytics | | ✓ | ✓ | ✓ | ✓ |
| View Error Tracking list | | ✓ | ✓ | ✓ | ✓ |
-| Create new merge request | | ✓ | ✓ | ✓ | ✓ |
| View metrics dashboard annotations | | ✓ | ✓ | ✓ | ✓ |
| Archive/reopen requirements **(ULTIMATE)** | | ✓ | ✓ | ✓ | ✓ |
| Create/edit requirements **(ULTIMATE)** | | ✓ | ✓ | ✓ | ✓ |
@@ -108,6 +107,7 @@ The following table depicts the various user permission levels in a project.
| Upload [Design Management](project/issues/design_management.md) files | | | ✓ | ✓ | ✓ |
| Create/edit [releases](project/releases/index.md)| | | ✓ | ✓ | ✓ |
| Delete [releases](project/releases/index.md)| | | | ✓ | ✓ |
+| Create new merge request | | | ✓ | ✓ | ✓ |
| Create new branches | | | ✓ | ✓ | ✓ |
| Push to non-protected branches | | | ✓ | ✓ | ✓ |
| Force push to non-protected branches | | | ✓ | ✓ | ✓ |
diff --git a/lib/gitlab/background_migration/user_mentions/models/namespace.rb b/lib/gitlab/background_migration/user_mentions/models/namespace.rb
index 6587417d048..a2b50c41f4a 100644
--- a/lib/gitlab/background_migration/user_mentions/models/namespace.rb
+++ b/lib/gitlab/background_migration/user_mentions/models/namespace.rb
@@ -23,8 +23,13 @@ module Gitlab
parent_id.present? || parent.present?
end
+ # Deprecated, use #licensed_feature_available? instead. Remove once Namespace#feature_available? isn't used anymore.
+ def feature_available?(feature)
+ licensed_feature_available?(feature)
+ end
+
# Overridden in EE::Namespace
- def feature_available?(_feature)
+ def licensed_feature_available?(_feature)
false
end
end
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 09bdf1bfa60..63eb1869460 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -2238,9 +2238,6 @@ msgstr ""
msgid "AdminDashboard|Error loading the statistics. Please try again"
msgstr ""
-msgid "AdminNote|Note"
-msgstr ""
-
msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources including issues, merge requests, etc.. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr ""
@@ -2676,6 +2673,12 @@ msgstr ""
msgid "Admin|Additional users must be reviewed and approved by a system administrator. Learn more about %{help_link_start}usage caps%{help_link_end}."
msgstr ""
+msgid "Admin|Admin notes"
+msgstr ""
+
+msgid "Admin|Note"
+msgstr ""
+
msgid "Admin|View pending user approvals"
msgstr ""
@@ -8642,6 +8645,12 @@ msgstr ""
msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
+msgid "CorpusManagement|New corpus"
+msgstr ""
+
+msgid "CorpusManagement|Total Size: %{totalSize}"
+msgstr ""
+
msgid "Could not add admins as members"
msgstr ""
diff --git a/rubocop/cop/gitlab/feature_available_usage.rb b/rubocop/cop/gitlab/feature_available_usage.rb
new file mode 100644
index 00000000000..b50bdd8ca43
--- /dev/null
+++ b/rubocop/cop/gitlab/feature_available_usage.rb
@@ -0,0 +1,99 @@
+# frozen_string_literal: true
+
+module RuboCop
+ module Cop
+ module Gitlab
+ # Cop that checks for correct calling of #feature_available?
+ class FeatureAvailableUsage < RuboCop::Cop::Cop
+ OBSERVED_METHOD = :feature_available?
+ LICENSED_FEATURE_LITERAL_ARG_MSG = '`feature_available?` should not be called for features that can be licensed (`%s` given), use `licensed_feature_available?(feature)` instead.'
+ LICENSED_FEATURE_DYNAMIC_ARG_MSG = "`feature_available?` should not be called for features that can be licensed (`%s` isn't a literal so we cannot say if it's legit or not), using `licensed_feature_available?(feature)` may be more appropriate."
+ NOT_ENOUGH_ARGS_MSG = '`feature_available?` should be called with two arguments: `feature` and `user`.'
+ FEATURES = %i[
+ issues
+ forking
+ merge_requests
+ wiki
+ snippets
+ builds
+ repository
+ pages
+ metrics_dashboard
+ analytics
+ operations
+ security_and_compliance
+ container_registry
+ ].freeze
+ EE_FEATURES = %i[requirements].freeze
+ ALL_FEATURES = (FEATURES + EE_FEATURES).freeze
+ SPECIAL_CLASS = %w[License].freeze
+
+ def on_send(node)
+ return unless method_name(node) == OBSERVED_METHOD
+ return if caller_is_special_case?(node)
+ return if feature_name(node).nil?
+ return if ALL_FEATURES.include?(feature_name(node)) && args_count(node) == 2
+
+ if !ALL_FEATURES.include?(feature_name(node))
+ add_offense(node, location: :expression, message: licensed_feature_message(node))
+ elsif args_count(node) < 2
+ add_offense(node, location: :expression, message: NOT_ENOUGH_ARGS_MSG)
+ end
+ end
+
+ def licensed_feature_message(node)
+ message_template = dynamic_feature?(node) ? LICENSED_FEATURE_DYNAMIC_ARG_MSG : LICENSED_FEATURE_LITERAL_ARG_MSG
+
+ message_template % feature_arg_name(node)
+ end
+
+ private
+
+ def method_name(node)
+ node.children[1]
+ end
+
+ def class_caller(node)
+ node.children[0]&.const_name.to_s
+ end
+
+ def caller_is_special_case?(node)
+ SPECIAL_CLASS.include?(class_caller(node))
+ end
+
+ def feature_arg(node)
+ node.children[2]
+ end
+
+ def dynamic_feature?(node)
+ feature = feature_arg(node)
+ return false unless feature
+
+ !feature.literal?
+ end
+
+ def feature_name(node)
+ feature = feature_arg(node)
+ return unless feature
+ return feature.children.compact.join('.') if dynamic_feature?(node)
+ return feature.value if feature.respond_to?(:value)
+
+ feature.type
+ end
+
+ def feature_arg_name(node)
+ feature = feature_arg(node)
+ return unless feature
+ return feature.children.compact.join('.') if dynamic_feature?(node)
+ return feature.children[0].inspect if feature.literal?
+
+ feature.type
+ end
+
+ def args_count(node)
+ node.children[2..].size
+ end
+ end
+ end
+ end
+end
diff --git a/spec/controllers/admin/groups_controller_spec.rb b/spec/controllers/admin/groups_controller_spec.rb
index 38f4ce54e5c..8441a52b454 100644
--- a/spec/controllers/admin/groups_controller_spec.rb
+++ b/spec/controllers/admin/groups_controller_spec.rb
@@ -37,6 +37,12 @@ RSpec.describe Admin::GroupsController do
post :create, params: { group: { path: 'test', name: 'test' } }
end.to change { NamespaceSetting.count }.by(1)
end
+
+ it 'creates admin_note for group' do
+ expect do
+ post :create, params: { group: { path: 'test', name: 'test', admin_note_attributes: { note: 'test' } } }
+ end.to change { Namespace::AdminNote.count }.by(1)
+ end
end
describe 'PUT #members_update' do
diff --git a/spec/features/admin/admin_groups_spec.rb b/spec/features/admin/admin_groups_spec.rb
index bbdf2f7f4a9..e7634f4e020 100644
--- a/spec/features/admin/admin_groups_spec.rb
+++ b/spec/features/admin/admin_groups_spec.rb
@@ -35,6 +35,7 @@ RSpec.describe 'Admin Groups' do
expect(page).to have_field('group_path')
expect(page).to have_field('group_visibility_level_0')
expect(page).to have_field('description')
+ expect(page).to have_field('group_admin_note_attributes_note')
end
end
@@ -47,10 +48,12 @@ RSpec.describe 'Admin Groups' do
path_component = 'gitlab'
group_name = 'GitLab group name'
group_description = 'Description of group for GitLab'
+ group_admin_note = 'A note about this group by an admin'
fill_in 'group_path', with: path_component
fill_in 'group_name', with: group_name
fill_in 'group_description', with: group_description
+ fill_in 'group_admin_note_attributes_note', with: group_admin_note
click_button "Create group"
expect(current_path).to eq admin_group_path(Group.find_by(path: path_component))
@@ -61,6 +64,8 @@ RSpec.describe 'Admin Groups' do
expect(li_texts).to match group_name
expect(li_texts).to match path_component
expect(li_texts).to match group_description
+ p_texts = content.all('p').collect(&:text).join('/n')
+ expect(p_texts).to match group_admin_note
end
it 'shows the visibility level radio populated with the default value' do
@@ -116,6 +121,16 @@ RSpec.describe 'Admin Groups' do
expect(page).to have_link(group.name, href: group_path(group))
end
+
+ it 'has a note if one is available' do
+ group = create(:group, :private)
+ note_text = 'A group administrator note'
+ group.update!(admin_note_attributes: { note: note_text })
+
+ visit admin_group_path(group)
+
+ expect(page).to have_text(note_text)
+ end
end
describe 'group edit' do
@@ -145,6 +160,36 @@ RSpec.describe 'Admin Groups' do
expect(name_field.value).to eq original_name
end
+
+ it 'adding an admin note to group without one' do
+ group = create(:group, :private)
+ expect(group.admin_note).to be_nil
+
+ visit admin_group_edit_path(group)
+ admin_note_text = 'A note by an administrator'
+
+ fill_in 'group_admin_note_attributes_note', with: admin_note_text
+ click_button 'Save changes'
+
+ expect(page).to have_content(admin_note_text)
+ end
+
+ it 'editing an existing group admin note' do
+ admin_note_text = 'A note by an administrator'
+ new_admin_note_text = 'A new note by an administrator'
+ group = create(:group, :private)
+ group.create_admin_note(note: admin_note_text)
+
+ visit admin_group_edit_path(group)
+
+ admin_note_field = find('#group_admin_note_attributes_note')
+ expect(admin_note_field.value).to eq(admin_note_text)
+
+ fill_in 'group_admin_note_attributes_note', with: new_admin_note_text
+ click_button 'Save changes'
+
+ expect(page).to have_content(new_admin_note_text)
+ end
end
describe 'add user into a group', :js do
diff --git a/spec/features/boards/sidebar_assignee_spec.rb b/spec/features/boards/sidebar_assignee_spec.rb
index 6835721bb4d..82383ece2d3 100644
--- a/spec/features/boards/sidebar_assignee_spec.rb
+++ b/spec/features/boards/sidebar_assignee_spec.rb
@@ -17,8 +17,6 @@ RSpec.describe 'Project issue boards sidebar assignee', :js do
let(:card) { find('.board:nth-child(2)').first('.board-card') }
before do
- stub_feature_flags(graphql_board_lists: false)
-
project.add_maintainer(user)
sign_in(user)
diff --git a/spec/frontend/reports/grouped_test_report/components/test_issue_body_spec.js b/spec/frontend/reports/grouped_test_report/components/test_issue_body_spec.js
index e03a52aad8d..2f6f62ca1d3 100644
--- a/spec/frontend/reports/grouped_test_report/components/test_issue_body_spec.js
+++ b/spec/frontend/reports/grouped_test_report/components/test_issue_body_spec.js
@@ -52,7 +52,7 @@ describe('Test issue body', () => {
});
it('renders issue name', () => {
- expect(findDescription().text()).toBe(failedIssue.name);
+ expect(findDescription().text()).toContain(failedIssue.name);
});
it('renders failed status icon', () => {
diff --git a/spec/frontend/vue_shared/components/runner_instructions/runner_instructions_spec.js b/spec/frontend/vue_shared/components/runner_instructions/runner_instructions_spec.js
index 48db60bfd33..4446c3cd88f 100644
--- a/spec/frontend/vue_shared/components/runner_instructions/runner_instructions_spec.js
+++ b/spec/frontend/vue_shared/components/runner_instructions/runner_instructions_spec.js
@@ -1,3 +1,4 @@
+import { GlAlert } from '@gitlab/ui';
import { shallowMount, createLocalVue } from '@vue/test-utils';
import VueApollo from 'vue-apollo';
import createMockApollo from 'helpers/mock_apollo_helper';
@@ -14,7 +15,10 @@ localVue.use(VueApollo);
describe('RunnerInstructions component', () => {
let wrapper;
let fakeApollo;
+ let runnerPlatformsHandler;
+ let runnerSetupInstructionsHandler;
+ const findAlert = () => wrapper.findComponent(GlAlert);
const findModalButton = () => wrapper.find('[data-testid="show-modal-button"]');
const findPlatformButtons = () => wrapper.findAll('[data-testid="platform-button"]');
const findArchitectureDropdownItems = () =>
@@ -22,10 +26,10 @@ describe('RunnerInstructions component', () => {
const findBinaryInstructionsSection = () => wrapper.find('[data-testid="binary-instructions"]');
const findRunnerInstructionsSection = () => wrapper.find('[data-testid="runner-instructions"]');
- beforeEach(async () => {
+ const createComponent = () => {
const requestHandlers = [
- [getRunnerPlatforms, jest.fn().mockResolvedValue(mockGraphqlRunnerPlatforms)],
- [getRunnerSetupInstructions, jest.fn().mockResolvedValue(mockGraphqlInstructions)],
+ [getRunnerPlatforms, runnerPlatformsHandler],
+ [getRunnerSetupInstructions, runnerSetupInstructionsHandler],
];
fakeApollo = createMockApollo(requestHandlers);
@@ -37,6 +41,13 @@ describe('RunnerInstructions component', () => {
localVue,
apolloProvider: fakeApollo,
});
+ };
+
+ beforeEach(async () => {
+ runnerPlatformsHandler = jest.fn().mockResolvedValue(mockGraphqlRunnerPlatforms);
+ runnerSetupInstructionsHandler = jest.fn().mockResolvedValue(mockGraphqlInstructions);
+
+ createComponent();
await wrapper.vm.$nextTick();
});
@@ -46,6 +57,10 @@ describe('RunnerInstructions component', () => {
wrapper = null;
});
+ it('should not show alert', () => {
+ expect(findAlert().exists()).toBe(false);
+ });
+
it('should show the "Show Runner installation instructions" button', () => {
const button = findModalButton();
@@ -110,4 +125,23 @@ describe('RunnerInstructions component', () => {
expect(runner.text()).toMatch(mockGraphqlInstructions.data.runnerSetup.registerInstructions);
});
+
+ describe('when instructions cannot be loaded', () => {
+ beforeEach(async () => {
+ runnerSetupInstructionsHandler.mockRejectedValue();
+
+ createComponent();
+
+ await wrapper.vm.$nextTick();
+ });
+
+ it('should show alert', () => {
+ expect(findAlert().exists()).toBe(true);
+ });
+
+ it('should not show instructions', () => {
+ expect(findBinaryInstructionsSection().exists()).toBe(false);
+ expect(findRunnerInstructionsSection().exists()).toBe(false);
+ });
+ });
});
diff --git a/spec/models/namespace/admin_note_spec.rb b/spec/models/namespace/admin_note_spec.rb
new file mode 100644
index 00000000000..65ba1f61416
--- /dev/null
+++ b/spec/models/namespace/admin_note_spec.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Namespace::AdminNote, type: :model do
+ let!(:namespace) { create(:namespace) }
+
+ describe 'associations' do
+ it { is_expected.to belong_to :namespace }
+ end
+
+ describe 'validations' do
+ it { is_expected.to validate_presence_of(:namespace) }
+ it { is_expected.to validate_length_of(:note).is_at_most(1000) }
+ end
+end
diff --git a/spec/models/namespace_spec.rb b/spec/models/namespace_spec.rb
index 351486ae801..ce29181dab8 100644
--- a/spec/models/namespace_spec.rb
+++ b/spec/models/namespace_spec.rb
@@ -21,6 +21,7 @@ RSpec.describe Namespace do
it { is_expected.to have_many :custom_emoji }
it { is_expected.to have_one :package_setting_relation }
it { is_expected.to have_one :onboarding_progress }
+ it { is_expected.to have_one :admin_note }
end
describe 'validations' do
diff --git a/spec/rubocop/cop/gitlab/feature_available_usage_spec.rb b/spec/rubocop/cop/gitlab/feature_available_usage_spec.rb
new file mode 100644
index 00000000000..514ef357785
--- /dev/null
+++ b/spec/rubocop/cop/gitlab/feature_available_usage_spec.rb
@@ -0,0 +1,96 @@
+# frozen_string_literal: true
+
+require 'fast_spec_helper'
+require 'rubocop'
+require 'rubocop/rspec/support'
+require_relative '../../../../rubocop/cop/gitlab/feature_available_usage'
+
+RSpec.describe RuboCop::Cop::Gitlab::FeatureAvailableUsage do
+ subject(:cop) { described_class.new }
+
+ context 'no arguments given' do
+ it 'does not flag the use of Gitlab::Sourcegraph.feature_available? with no arguments' do
+ expect_no_offenses('Gitlab::Sourcegraph.feature_available?')
+ expect_no_offenses('subject { described_class.feature_available? }')
+ end
+ end
+
+ context 'one argument given' do
+ it 'does not flag the use of License.feature_available?' do
+ expect_no_offenses('License.feature_available?(:push_rules)')
+ end
+
+ it 'flags the use with a dynamic feature as nil' do
+ expect_offense(<<~SOURCE)
+ feature_available?(nil)
+ ^^^^^^^^^^^^^^^^^^^^^^^ `feature_available?` should not be called for features that can be licensed (`nil` given), use `licensed_feature_available?(feature)` instead.
+ SOURCE
+ expect_offense(<<~SOURCE)
+ project.feature_available?(nil)
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `feature_available?` should not be called for features that can be licensed (`nil` given), use `licensed_feature_available?(feature)` instead.
+ SOURCE
+ end
+
+ it 'flags the use with an OSS project feature' do
+ expect_offense(<<~SOURCE)
+ project.feature_available?(:issues)
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `feature_available?` should be called with two arguments: `feature` and `user`.
+ SOURCE
+ expect_offense(<<~SOURCE)
+ feature_available?(:issues)
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `feature_available?` should be called with two arguments: `feature` and `user`.
+ SOURCE
+ end
+
+ it 'flags the use with a feature that is not a project feature' do
+ expect_offense(<<~SOURCE)
+ feature_available?(:foo)
+ ^^^^^^^^^^^^^^^^^^^^^^^^ `feature_available?` should not be called for features that can be licensed (`:foo` given), use `licensed_feature_available?(feature)` instead.
+ SOURCE
+ expect_offense(<<~SOURCE)
+ project.feature_available?(:foo)
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `feature_available?` should not be called for features that can be licensed (`:foo` given), use `licensed_feature_available?(feature)` instead.
+ SOURCE
+ expect_offense(<<~SOURCE)
+ feature_available?(foo)
+ ^^^^^^^^^^^^^^^^^^^^^^^ `feature_available?` should not be called for features that can be licensed (`foo` isn't a literal so we cannot say if it's legit or not), using `licensed_feature_available?(feature)` may be more appropriate.
+ SOURCE
+ expect_offense(<<~SOURCE)
+ foo = :feature
+ feature_available?(foo)
+ ^^^^^^^^^^^^^^^^^^^^^^^ `feature_available?` should not be called for features that can be licensed (`foo` isn't a literal so we cannot say if it's legit or not), using `licensed_feature_available?(feature)` may be more appropriate.
+ SOURCE
+ end
+ end
+
+ context 'two arguments given' do
+ it 'does not flag the use with an OSS project feature' do
+ expect_no_offenses('feature_available?(:issues, user)')
+ expect_no_offenses('project.feature_available?(:issues, user)')
+ end
+
+ it 'does not flag the use with an EE project feature' do
+ expect_no_offenses('feature_available?(:requirements, user)')
+ expect_no_offenses('project.feature_available?(:requirements, user)')
+ end
+
+ it 'flags the use with a dynamic feature as a method call with two args' do
+ expect_offense(<<~SOURCE)
+ feature_available?(:foo, current_user)
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `feature_available?` should not be called for features that can be licensed (`:foo` given), use `licensed_feature_available?(feature)` instead.
+ SOURCE
+ expect_offense(<<~SOURCE)
+ project.feature_available?(:foo, current_user)
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `feature_available?` should not be called for features that can be licensed (`:foo` given), use `licensed_feature_available?(feature)` instead.
+ SOURCE
+ expect_offense(<<~SOURCE)
+ feature_available?(foo, current_user)
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `feature_available?` should not be called for features that can be licensed (`foo` isn't a literal so we cannot say if it's legit or not), using `licensed_feature_available?(feature)` may be more appropriate.
+ SOURCE
+ expect_offense(<<~SOURCE)
+ project.feature_available?(foo, current_user)
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `feature_available?` should not be called for features that can be licensed (`foo` isn't a literal so we cannot say if it's legit or not), using `licensed_feature_available?(feature)` may be more appropriate.
+ SOURCE
+ end
+ end
+end