Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2022-05-26 18:08:29 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2022-05-26 18:08:29 +0300
commitcac0926ddbef9d1505c2a23ccad60fd47c7d050a (patch)
treeef6808933314a104d004528f7c84716dc472d93a
parentafd476d5fd62d31c7e0b7509691fa18e632a60df (diff)
Add latest changes from gitlab-org/gitlab@master
-rw-r--r--.gitlab/CODEOWNERS143
-rw-r--r--app/assets/javascripts/content_editor/services/hast_to_prosemirror_converter.js24
-rw-r--r--app/assets/javascripts/google_cloud/components/revoke_oauth.vue2
-rw-r--r--app/assets/javascripts/issuable/components/issuable_header_warnings.vue2
-rw-r--r--app/assets/javascripts/issuable/components/status_box.vue3
-rw-r--r--app/assets/javascripts/merge_request.js6
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/mr_widget_header.vue100
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/mr_widget_related_links.vue4
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/ready_to_merge.vue5
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue11
-rw-r--r--app/controllers/projects/merge_requests_controller.rb1
-rw-r--r--app/helpers/issues_helper.rb8
-rw-r--r--app/models/member.rb1
-rw-r--r--app/models/user.rb13
-rw-r--r--app/views/projects/merge_requests/_mr_box.html.haml12
-rw-r--r--app/views/projects/merge_requests/_mr_title.html.haml21
-rw-r--r--app/views/projects/merge_requests/show.html.haml2
-rw-r--r--app/views/projects/tags/new.html.haml8
-rw-r--r--app/views/shared/issuable/_status_box.html.haml3
-rw-r--r--config/feature_flags/development/updated_mr_header.yml8
-rw-r--r--data/deprecations/14-5-certificate-based-integration-with-kubernetes.yml2
-rw-r--r--doc/api/personal_access_tokens.md23
-rw-r--r--doc/development/application_limits.md20
-rw-r--r--doc/development/contributing/verify/index.md20
-rw-r--r--doc/update/deprecations.md2
-rw-r--r--lib/api/personal_access_tokens.rb8
-rw-r--r--lib/gitlab/ci/config/external/file/local.rb4
-rw-r--r--lib/gitlab/ci/config/external/file/project.rb4
-rw-r--r--lib/gitlab/ci/config/external/file/remote.rb4
-rw-r--r--lib/gitlab/ci/config/external/file/template.rb4
-rw-r--r--lib/gitlab/usage/service_ping_report.rb2
-rw-r--r--locale/gitlab.pot12
-rw-r--r--qa/qa/page/merge_request/show.rb5
-rw-r--r--spec/features/merge_request/user_views_user_status_on_merge_request_spec.rb10
-rw-r--r--spec/frontend/content_editor/remark_markdown_processing_spec.js90
-rw-r--r--spec/frontend/vue_mr_widget/components/mr_widget_header_spec.js176
-rw-r--r--spec/helpers/issues_helper_spec.rb93
-rw-r--r--spec/lib/gitlab/ci/config/external/mapper_spec.rb25
-rw-r--r--spec/lib/gitlab/usage/service_ping_report_spec.rb29
-rw-r--r--spec/models/user_spec.rb20
-rw-r--r--spec/requests/api/personal_access_tokens_spec.rb55
-rw-r--r--spec/requests/api/users_spec.rb20
-rw-r--r--spec/services/users/destroy_service_spec.rb21
-rw-r--r--spec/tooling/lib/tooling/find_codeowners_spec.rb107
-rw-r--r--tooling/config/CODEOWNERS.yml91
-rw-r--r--tooling/lib/tooling/find_codeowners.rb32
46 files changed, 592 insertions, 664 deletions
diff --git a/.gitlab/CODEOWNERS b/.gitlab/CODEOWNERS
index 1199016901a..89492338cfa 100644
--- a/.gitlab/CODEOWNERS
+++ b/.gitlab/CODEOWNERS
@@ -802,35 +802,35 @@ lib/gitlab/checks/** @proglottis @toon @zj-gitlab
/doc/user/workspace/index.md @fneill
[Authentication and Authorization]
-/app/assets/javascripts/access_tokens @gitlab-org/manage/authentication-and-authorization
+/app/assets/javascripts/access_tokens/ @gitlab-org/manage/authentication-and-authorization
/app/assets/javascripts/alerts_settings/graphql/mutations/reset_http_token.mutation.graphql @gitlab-org/manage/authentication-and-authorization
-/app/assets/javascripts/authentication @gitlab-org/manage/authentication-and-authorization
+/app/assets/javascripts/authentication/ @gitlab-org/manage/authentication-and-authorization
/app/assets/javascripts/ide/components/shared/tokened_input.vue @gitlab-org/manage/authentication-and-authorization
/app/assets/javascripts/invite_members/components/members_token_select.vue @gitlab-org/manage/authentication-and-authorization
-/app/assets/javascripts/logs/components/tokens @gitlab-org/manage/authentication-and-authorization
-/app/assets/javascripts/packages_and_registries/package_registry/components/list/tokens @gitlab-org/manage/authentication-and-authorization
-/app/assets/javascripts/pages/admin/impersonation_tokens @gitlab-org/manage/authentication-and-authorization
-/app/assets/javascripts/pages/groups/settings/access_tokens @gitlab-org/manage/authentication-and-authorization
-/app/assets/javascripts/pages/ldap @gitlab-org/manage/authentication-and-authorization
-/app/assets/javascripts/pages/oauth @gitlab-org/manage/authentication-and-authorization
-/app/assets/javascripts/pages/omniauth_callbacks @gitlab-org/manage/authentication-and-authorization
-/app/assets/javascripts/pages/profiles/password_prompt @gitlab-org/manage/authentication-and-authorization
-/app/assets/javascripts/pages/profiles/personal_access_tokens @gitlab-org/manage/authentication-and-authorization
-/app/assets/javascripts/pages/profiles/two_factor_auths @gitlab-org/manage/authentication-and-authorization
-/app/assets/javascripts/pages/projects/settings/access_tokens @gitlab-org/manage/authentication-and-authorization
+/app/assets/javascripts/logs/components/tokens/ @gitlab-org/manage/authentication-and-authorization
+/app/assets/javascripts/packages_and_registries/package_registry/components/list/tokens/ @gitlab-org/manage/authentication-and-authorization
+/app/assets/javascripts/pages/admin/impersonation_tokens/ @gitlab-org/manage/authentication-and-authorization
+/app/assets/javascripts/pages/groups/settings/access_tokens/ @gitlab-org/manage/authentication-and-authorization
+/app/assets/javascripts/pages/ldap/ @gitlab-org/manage/authentication-and-authorization
+/app/assets/javascripts/pages/oauth/ @gitlab-org/manage/authentication-and-authorization
+/app/assets/javascripts/pages/omniauth_callbacks/ @gitlab-org/manage/authentication-and-authorization
+/app/assets/javascripts/pages/profiles/password_prompt/ @gitlab-org/manage/authentication-and-authorization
+/app/assets/javascripts/pages/profiles/personal_access_tokens/ @gitlab-org/manage/authentication-and-authorization
+/app/assets/javascripts/pages/profiles/two_factor_auths/ @gitlab-org/manage/authentication-and-authorization
+/app/assets/javascripts/pages/projects/settings/access_tokens/ @gitlab-org/manage/authentication-and-authorization
/app/assets/javascripts/pages/sessions/new/oauth_remember_me.js @gitlab-org/manage/authentication-and-authorization
/app/assets/javascripts/pipelines/components/pipelines_list/tokens/constants.js @gitlab-org/manage/authentication-and-authorization
/app/assets/javascripts/pipelines/components/pipelines_list/tokens/pipeline_branch_name_token.vue @gitlab-org/manage/authentication-and-authorization
/app/assets/javascripts/pipelines/components/pipelines_list/tokens/pipeline_source_token.vue @gitlab-org/manage/authentication-and-authorization
/app/assets/javascripts/pipelines/components/pipelines_list/tokens/pipeline_status_token.vue @gitlab-org/manage/authentication-and-authorization
/app/assets/javascripts/pipelines/components/pipelines_list/tokens/pipeline_tag_name_token.vue @gitlab-org/manage/authentication-and-authorization
-/app/assets/javascripts/projects/settings/topics/components @gitlab-org/manage/authentication-and-authorization
+/app/assets/javascripts/projects/settings/topics/components/ @gitlab-org/manage/authentication-and-authorization
/app/assets/javascripts/related_issues/components/issue_token.vue @gitlab-org/manage/authentication-and-authorization
/app/assets/javascripts/runner/components/registration/registration_token.vue @gitlab-org/manage/authentication-and-authorization
/app/assets/javascripts/runner/components/registration/registration_token_reset_dropdown_item.vue @gitlab-org/manage/authentication-and-authorization
-/app/assets/javascripts/runner/components/search_tokens @gitlab-org/manage/authentication-and-authorization
+/app/assets/javascripts/runner/components/search_tokens/ @gitlab-org/manage/authentication-and-authorization
/app/assets/javascripts/static_site_editor/rich_content_editor/services/renderers/build_uneditable_token.js @gitlab-org/manage/authentication-and-authorization
-/app/assets/javascripts/token_access/components @gitlab-org/manage/authentication-and-authorization
+/app/assets/javascripts/token_access/components/ @gitlab-org/manage/authentication-and-authorization
/app/assets/javascripts/token_access/index.js @gitlab-org/manage/authentication-and-authorization
/app/assets/stylesheets/page_bundles/profile_two_factor_auth.scss @gitlab-org/manage/authentication-and-authorization
/app/controllers/admin/impersonation_tokens_controller.rb @gitlab-org/manage/authentication-and-authorization
@@ -845,8 +845,8 @@ lib/gitlab/checks/** @proglottis @toon @zj-gitlab
/app/controllers/concerns/snippet_authorizations.rb @gitlab-org/manage/authentication-and-authorization
/app/controllers/concerns/workhorse_authorization.rb @gitlab-org/manage/authentication-and-authorization
/app/controllers/groups/settings/access_tokens_controller.rb @gitlab-org/manage/authentication-and-authorization
-/app/controllers/ldap @gitlab-org/manage/authentication-and-authorization
-/app/controllers/oauth @gitlab-org/manage/authentication-and-authorization
+/app/controllers/ldap/ @gitlab-org/manage/authentication-and-authorization
+/app/controllers/oauth/ @gitlab-org/manage/authentication-and-authorization
/app/controllers/omniauth_callbacks_controller.rb @gitlab-org/manage/authentication-and-authorization
/app/controllers/passwords_controller.rb @gitlab-org/manage/authentication-and-authorization
/app/controllers/profiles/passwords_controller.rb @gitlab-org/manage/authentication-and-authorization
@@ -854,7 +854,7 @@ lib/gitlab/checks/** @proglottis @toon @zj-gitlab
/app/controllers/profiles/two_factor_auths_controller.rb @gitlab-org/manage/authentication-and-authorization
/app/controllers/profiles/webauthn_registrations_controller.rb @gitlab-org/manage/authentication-and-authorization
/app/controllers/projects/settings/access_tokens_controller.rb @gitlab-org/manage/authentication-and-authorization
-/app/finders/groups/projects_requiring_authorizations_refresh @gitlab-org/manage/authentication-and-authorization
+/app/finders/groups/projects_requiring_authorizations_refresh/ @gitlab-org/manage/authentication-and-authorization
/app/finders/personal_access_tokens_finder.rb @gitlab-org/manage/authentication-and-authorization
/app/helpers/access_tokens_helper.rb @gitlab-org/manage/authentication-and-authorization
/app/helpers/auth_helper.rb @gitlab-org/manage/authentication-and-authorization
@@ -863,7 +863,7 @@ lib/gitlab/checks/** @proglottis @toon @zj-gitlab
/app/models/concerns/mirror_authentication.rb @gitlab-org/manage/authentication-and-authorization
/app/models/concerns/select_for_project_authorization.rb @gitlab-org/manage/authentication-and-authorization
/app/models/concerns/token_authenticatable.rb @gitlab-org/manage/authentication-and-authorization
-/app/models/concerns/token_authenticatable_strategies @gitlab-org/manage/authentication-and-authorization
+/app/models/concerns/token_authenticatable_strategies/ @gitlab-org/manage/authentication-and-authorization
/app/models/oauth_access_grant.rb @gitlab-org/manage/authentication-and-authorization
/app/models/oauth_access_token.rb @gitlab-org/manage/authentication-and-authorization
/app/models/personal_access_token.rb @gitlab-org/manage/authentication-and-authorization
@@ -872,22 +872,22 @@ lib/gitlab/checks/** @proglottis @toon @zj-gitlab
/app/models/webauthn_registration.rb @gitlab-org/manage/authentication-and-authorization
/app/policies/personal_access_token_policy.rb @gitlab-org/manage/authentication-and-authorization
/app/services/access_token_validation_service.rb @gitlab-org/manage/authentication-and-authorization
-/app/services/auth @gitlab-org/manage/authentication-and-authorization
-/app/services/authorized_project_update @gitlab-org/manage/authentication-and-authorization
+/app/services/auth/ @gitlab-org/manage/authentication-and-authorization
+/app/services/authorized_project_update/ @gitlab-org/manage/authentication-and-authorization
/app/services/chat_names/authorize_user_service.rb @gitlab-org/manage/authentication-and-authorization
-/app/services/personal_access_tokens @gitlab-org/manage/authentication-and-authorization
+/app/services/personal_access_tokens/ @gitlab-org/manage/authentication-and-authorization
/app/services/projects/move_project_authorizations_service.rb @gitlab-org/manage/authentication-and-authorization
-/app/services/resource_access_tokens @gitlab-org/manage/authentication-and-authorization
+/app/services/resource_access_tokens/ @gitlab-org/manage/authentication-and-authorization
/app/services/todos/destroy/unauthorized_features_service.rb @gitlab-org/manage/authentication-and-authorization
/app/services/users/authorized_build_service.rb @gitlab-org/manage/authentication-and-authorization
/app/services/users/authorized_create_service.rb @gitlab-org/manage/authentication-and-authorization
/app/services/users/refresh_authorized_projects_service.rb @gitlab-org/manage/authentication-and-authorization
-/app/services/webauthn @gitlab-org/manage/authentication-and-authorization
+/app/services/webauthn/ @gitlab-org/manage/authentication-and-authorization
/app/validators/json_schemas/cluster_agent_authorization_configuration.json @gitlab-org/manage/authentication-and-authorization
/app/views/admin/application_settings/_external_authorization_service_form.html.haml @gitlab-org/manage/authentication-and-authorization
-/app/views/admin/impersonation_tokens @gitlab-org/manage/authentication-and-authorization
-/app/views/authentication @gitlab-org/manage/authentication-and-authorization
-/app/views/ci/token_access @gitlab-org/manage/authentication-and-authorization
+/app/views/admin/impersonation_tokens/ @gitlab-org/manage/authentication-and-authorization
+/app/views/authentication/ @gitlab-org/manage/authentication-and-authorization
+/app/views/ci/token_access/ @gitlab-org/manage/authentication-and-authorization
/app/views/dashboard/projects/_zero_authorized_projects.html.haml @gitlab-org/manage/authentication-and-authorization
/app/views/devise/mailer/password_change.html.haml @gitlab-org/manage/authentication-and-authorization
/app/views/devise/mailer/password_change.text.erb @gitlab-org/manage/authentication-and-authorization
@@ -895,17 +895,17 @@ lib/gitlab/checks/** @proglottis @toon @zj-gitlab
/app/views/devise/mailer/password_change_by_admin.text.erb @gitlab-org/manage/authentication-and-authorization
/app/views/devise/mailer/reset_password_instructions.html.haml @gitlab-org/manage/authentication-and-authorization
/app/views/devise/mailer/reset_password_instructions.text.erb @gitlab-org/manage/authentication-and-authorization
-/app/views/devise/passwords @gitlab-org/manage/authentication-and-authorization
+/app/views/devise/passwords/ @gitlab-org/manage/authentication-and-authorization
/app/views/devise/shared/_omniauth_box.html.haml @gitlab-org/manage/authentication-and-authorization
/app/views/devise/shared/_signup_omniauth_provider_list.haml @gitlab-org/manage/authentication-and-authorization
/app/views/devise/shared/_signup_omniauth_providers.haml @gitlab-org/manage/authentication-and-authorization
/app/views/devise/shared/_signup_omniauth_providers_top.haml @gitlab-org/manage/authentication-and-authorization
-/app/views/doorkeeper/authorizations @gitlab-org/manage/authentication-and-authorization
-/app/views/doorkeeper/authorized_applications @gitlab-org/manage/authentication-and-authorization
+/app/views/doorkeeper/authorizations/ @gitlab-org/manage/authentication-and-authorization
+/app/views/doorkeeper/authorized_applications/ @gitlab-org/manage/authentication-and-authorization
/app/views/errors/omniauth_error.html.haml @gitlab-org/manage/authentication-and-authorization
/app/views/groups/settings/_resource_access_token_creation.html.haml @gitlab-org/manage/authentication-and-authorization
/app/views/groups/settings/_two_factor_auth.html.haml @gitlab-org/manage/authentication-and-authorization
-/app/views/groups/settings/access_tokens @gitlab-org/manage/authentication-and-authorization
+/app/views/groups/settings/access_tokens/ @gitlab-org/manage/authentication-and-authorization
/app/views/layouts/oauth_error.html.haml @gitlab-org/manage/authentication-and-authorization
/app/views/notify/access_token_about_to_expire_email.html.haml @gitlab-org/manage/authentication-and-authorization
/app/views/notify/access_token_about_to_expire_email.text.erb @gitlab-org/manage/authentication-and-authorization
@@ -913,20 +913,20 @@ lib/gitlab/checks/** @proglottis @toon @zj-gitlab
/app/views/notify/access_token_created_email.text.erb @gitlab-org/manage/authentication-and-authorization
/app/views/notify/access_token_expired_email.html.haml @gitlab-org/manage/authentication-and-authorization
/app/views/notify/access_token_expired_email.text.erb @gitlab-org/manage/authentication-and-authorization
-/app/views/profiles/passwords @gitlab-org/manage/authentication-and-authorization
-/app/views/profiles/personal_access_tokens @gitlab-org/manage/authentication-and-authorization
-/app/views/profiles/two_factor_auths @gitlab-org/manage/authentication-and-authorization
+/app/views/profiles/passwords/ @gitlab-org/manage/authentication-and-authorization
+/app/views/profiles/personal_access_tokens/ @gitlab-org/manage/authentication-and-authorization
+/app/views/profiles/two_factor_auths/ @gitlab-org/manage/authentication-and-authorization
/app/views/projects/mirrors/_authentication_method.html.haml @gitlab-org/manage/authentication-and-authorization
-/app/views/projects/settings/access_tokens @gitlab-org/manage/authentication-and-authorization
+/app/views/projects/settings/access_tokens/ @gitlab-org/manage/authentication-and-authorization
/app/views/shared/_no_password.html.haml @gitlab-org/manage/authentication-and-authorization
/app/views/shared/_two_factor_auth_recovery_settings_check.html.haml @gitlab-org/manage/authentication-and-authorization
-/app/views/shared/access_tokens @gitlab-org/manage/authentication-and-authorization
+/app/views/shared/access_tokens/ @gitlab-org/manage/authentication-and-authorization
/app/views/shared/members/_two_factor_auth_badge.html.haml @gitlab-org/manage/authentication-and-authorization
-/app/views/shared/tokens @gitlab-org/manage/authentication-and-authorization
+/app/views/shared/tokens/ @gitlab-org/manage/authentication-and-authorization
/app/workers/authorized_keys_worker.rb @gitlab-org/manage/authentication-and-authorization
-/app/workers/authorized_project_update @gitlab-org/manage/authentication-and-authorization
+/app/workers/authorized_project_update/ @gitlab-org/manage/authentication-and-authorization
/app/workers/authorized_projects_worker.rb @gitlab-org/manage/authentication-and-authorization
-/app/workers/personal_access_tokens @gitlab-org/manage/authentication-and-authorization
+/app/workers/personal_access_tokens/ @gitlab-org/manage/authentication-and-authorization
/config/feature_flags/development/application_settings_tokens_optional_encryption.yml @gitlab-org/manage/authentication-and-authorization
/config/feature_flags/development/enforce_auth_checks_on_uploads.yml @gitlab-org/manage/authentication-and-authorization
/config/feature_flags/development/forti_authenticator.yml @gitlab-org/manage/authentication-and-authorization
@@ -936,6 +936,7 @@ lib/gitlab/checks/** @proglottis @toon @zj-gitlab
/config/feature_flags/development/omniauth_login_minimal_scopes.yml @gitlab-org/manage/authentication-and-authorization
/config/feature_flags/development/personal_access_tokens_scoped_to_projects.yml @gitlab-org/manage/authentication-and-authorization
/config/feature_flags/development/projects_tokens_optional_encryption.yml @gitlab-org/manage/authentication-and-authorization
+/config/feature_flags/development/refresh_authorizations_via_affected_projects_on_group_membership.yml @gitlab-org/manage/authentication-and-authorization
/config/feature_flags/development/specialized_worker_for_group_lock_update_auth_recalculation.yml @gitlab-org/manage/authentication-and-authorization
/config/feature_flags/development/webauthn.yml @gitlab-org/manage/authentication-and-authorization
/config/feature_flags/ops/block_password_auth_for_saml_users.yml @gitlab-org/manage/authentication-and-authorization
@@ -949,27 +950,27 @@ lib/gitlab/checks/** @proglottis @toon @zj-gitlab
/config/initializers/webauthn.rb @gitlab-org/manage/authentication-and-authorization
/config/initializers_before_autoloader/100_patch_omniauth_oauth2.rb @gitlab-org/manage/authentication-and-authorization
/config/initializers_before_autoloader/100_patch_omniauth_saml.rb @gitlab-org/manage/authentication-and-authorization
-/ee/app/assets/javascripts/access_tokens @gitlab-org/manage/authentication-and-authorization
-/ee/app/assets/javascripts/audit_events/components/tokens @gitlab-org/manage/authentication-and-authorization
+/ee/app/assets/javascripts/access_tokens/ @gitlab-org/manage/authentication-and-authorization
+/ee/app/assets/javascripts/audit_events/components/tokens/ @gitlab-org/manage/authentication-and-authorization
/ee/app/assets/javascripts/audit_events/token_utils.js @gitlab-org/manage/authentication-and-authorization
-/ee/app/assets/javascripts/groups/settings/components @gitlab-org/manage/authentication-and-authorization
-/ee/app/assets/javascripts/pages/groups/omniauth_callbacks @gitlab-org/manage/authentication-and-authorization
-/ee/app/assets/javascripts/pipelines/components/pipelines_list @gitlab-org/manage/authentication-and-authorization
-/ee/app/assets/javascripts/requirements/components/tokens @gitlab-org/manage/authentication-and-authorization
+/ee/app/assets/javascripts/groups/settings/components/ @gitlab-org/manage/authentication-and-authorization
+/ee/app/assets/javascripts/pages/groups/omniauth_callbacks/ @gitlab-org/manage/authentication-and-authorization
+/ee/app/assets/javascripts/pipelines/components/pipelines_list/ @gitlab-org/manage/authentication-and-authorization
+/ee/app/assets/javascripts/requirements/components/tokens/ @gitlab-org/manage/authentication-and-authorization
/ee/app/assets/javascripts/saml_providers/scim_token_service.js @gitlab-org/manage/authentication-and-authorization
-/ee/app/assets/javascripts/saml_sso/components @gitlab-org/manage/authentication-and-authorization
+/ee/app/assets/javascripts/saml_sso/components/ @gitlab-org/manage/authentication-and-authorization
/ee/app/assets/javascripts/vue_merge_request_widget/components/approvals/approvals_auth.vue @gitlab-org/manage/authentication-and-authorization
/ee/app/controllers/concerns/ee/authenticates_with_two_factor.rb @gitlab-org/manage/authentication-and-authorization
/ee/app/controllers/concerns/ee/enforces_two_factor_authentication.rb @gitlab-org/manage/authentication-and-authorization
/ee/app/controllers/concerns/saml_authorization.rb @gitlab-org/manage/authentication-and-authorization
-/ee/app/controllers/ee/ldap @gitlab-org/manage/authentication-and-authorization
+/ee/app/controllers/ee/ldap/ @gitlab-org/manage/authentication-and-authorization
/ee/app/controllers/ee/omniauth_callbacks_controller.rb @gitlab-org/manage/authentication-and-authorization
/ee/app/controllers/ee/passwords_controller.rb @gitlab-org/manage/authentication-and-authorization
/ee/app/controllers/groups/omniauth_callbacks_controller.rb @gitlab-org/manage/authentication-and-authorization
/ee/app/controllers/groups/scim_oauth_controller.rb @gitlab-org/manage/authentication-and-authorization
-/ee/app/controllers/oauth @gitlab-org/manage/authentication-and-authorization
+/ee/app/controllers/oauth/ @gitlab-org/manage/authentication-and-authorization
/ee/app/controllers/omniauth_kerberos_spnego_controller.rb @gitlab-org/manage/authentication-and-authorization
-/ee/app/finders/auth @gitlab-org/manage/authentication-and-authorization
+/ee/app/finders/auth/ @gitlab-org/manage/authentication-and-authorization
/ee/app/helpers/ee/access_tokens_helper.rb @gitlab-org/manage/authentication-and-authorization
/ee/app/helpers/ee/auth_helper.rb @gitlab-org/manage/authentication-and-authorization
/ee/app/helpers/ee/personal_access_tokens_helper.rb @gitlab-org/manage/authentication-and-authorization
@@ -977,10 +978,10 @@ lib/gitlab/checks/** @proglottis @toon @zj-gitlab
/ee/app/models/ee/project_authorization.rb @gitlab-org/manage/authentication-and-authorization
/ee/app/models/scim_oauth_access_token.rb @gitlab-org/manage/authentication-and-authorization
/ee/app/serializers/scim_oauth_access_token_entity.rb @gitlab-org/manage/authentication-and-authorization
-/ee/app/services/ee/auth @gitlab-org/manage/authentication-and-authorization
-/ee/app/services/ee/personal_access_tokens @gitlab-org/manage/authentication-and-authorization
-/ee/app/services/ee/resource_access_tokens @gitlab-org/manage/authentication-and-authorization
-/ee/app/services/personal_access_tokens @gitlab-org/manage/authentication-and-authorization
+/ee/app/services/ee/auth/ @gitlab-org/manage/authentication-and-authorization
+/ee/app/services/ee/personal_access_tokens/ @gitlab-org/manage/authentication-and-authorization
+/ee/app/services/ee/resource_access_tokens/ @gitlab-org/manage/authentication-and-authorization
+/ee/app/services/personal_access_tokens/ @gitlab-org/manage/authentication-and-authorization
/ee/app/services/security/token_revocation_service.rb @gitlab-org/manage/authentication-and-authorization
/ee/app/views/admin/application_settings/_personal_access_token_expiration_policy.html.haml @gitlab-org/manage/authentication-and-authorization
/ee/app/views/credentials_inventory_mailer/personal_access_token_revoked_email.html.haml @gitlab-org/manage/authentication-and-authorization
@@ -989,22 +990,21 @@ lib/gitlab/checks/** @proglottis @toon @zj-gitlab
/ee/app/views/groups/sso/_authorize_pane.html.haml @gitlab-org/manage/authentication-and-authorization
/ee/app/views/notify/policy_revoked_personal_access_tokens_email.html.haml @gitlab-org/manage/authentication-and-authorization
/ee/app/views/notify/policy_revoked_personal_access_tokens_email.text.erb @gitlab-org/manage/authentication-and-authorization
-/ee/app/views/oauth @gitlab-org/manage/authentication-and-authorization
+/ee/app/views/oauth/ @gitlab-org/manage/authentication-and-authorization
/ee/app/views/shared/credentials_inventory/_personal_access_tokens.html.haml @gitlab-org/manage/authentication-and-authorization
/ee/app/views/shared/credentials_inventory/_project_access_tokens.html.haml @gitlab-org/manage/authentication-and-authorization
-/ee/app/views/shared/credentials_inventory/personal_access_tokens @gitlab-org/manage/authentication-and-authorization
-/ee/app/views/shared/credentials_inventory/project_access_tokens @gitlab-org/manage/authentication-and-authorization
-/ee/app/workers/personal_access_tokens @gitlab-org/manage/authentication-and-authorization
+/ee/app/views/shared/credentials_inventory/personal_access_tokens/ @gitlab-org/manage/authentication-and-authorization
+/ee/app/views/shared/credentials_inventory/project_access_tokens/ @gitlab-org/manage/authentication-and-authorization
+/ee/app/workers/personal_access_tokens/ @gitlab-org/manage/authentication-and-authorization
/ee/config/routes/oauth.rb @gitlab-org/manage/authentication-and-authorization
-/ee/lib/ee/gitlab/auth @gitlab-org/manage/authentication-and-authorization
-/ee/lib/ee/gitlab/auth.rb @gitlab-org/manage/authentication-and-authorization
+/ee/lib/ee/gitlab/auth/ @gitlab-org/manage/authentication-and-authorization
/ee/lib/ee/gitlab/omniauth_initializer.rb @gitlab-org/manage/authentication-and-authorization
-/ee/lib/gitlab/auth @gitlab-org/manage/authentication-and-authorization
+/ee/lib/gitlab/auth/ @gitlab-org/manage/authentication-and-authorization
/ee/lib/gitlab/auth_logger.rb @gitlab-org/manage/authentication-and-authorization
/ee/lib/gitlab/authority_analyzer.rb @gitlab-org/manage/authentication-and-authorization
-/ee/lib/gitlab/geo/oauth @gitlab-org/manage/authentication-and-authorization
-/ee/lib/gitlab/kerberos @gitlab-org/manage/authentication-and-authorization
-/ee/lib/omni_auth @gitlab-org/manage/authentication-and-authorization
+/ee/lib/gitlab/geo/oauth/ @gitlab-org/manage/authentication-and-authorization
+/ee/lib/gitlab/kerberos/ @gitlab-org/manage/authentication-and-authorization
+/ee/lib/omni_auth/ @gitlab-org/manage/authentication-and-authorization
/ee/lib/system_check/geo/authorized_keys_check.rb @gitlab-org/manage/authentication-and-authorization
/ee/lib/system_check/geo/authorized_keys_flag_check.rb @gitlab-org/manage/authentication-and-authorization
/lib/api/entities/ci/reset_token_result.rb @gitlab-org/manage/authentication-and-authorization
@@ -1019,27 +1019,28 @@ lib/gitlab/checks/** @proglottis @toon @zj-gitlab
/lib/api/personal_access_tokens.rb @gitlab-org/manage/authentication-and-authorization
/lib/api/resource_access_tokens.rb @gitlab-org/manage/authentication-and-authorization
/lib/api/support/token_with_expiration.rb @gitlab-org/manage/authentication-and-authorization
-/lib/gitlab/api_authentication @gitlab-org/manage/authentication-and-authorization
-/lib/gitlab/auth @gitlab-org/manage/authentication-and-authorization
+/lib/gitlab/api_authentication/ @gitlab-org/manage/authentication-and-authorization
+/lib/gitlab/auth/ @gitlab-org/manage/authentication-and-authorization
/lib/gitlab/auth.rb @gitlab-org/manage/authentication-and-authorization
/lib/gitlab/auth_logger.rb @gitlab-org/manage/authentication-and-authorization
/lib/gitlab/authorized_keys.rb @gitlab-org/manage/authentication-and-authorization
/lib/gitlab/background_migration/encrypt_static_object_token.rb @gitlab-org/manage/authentication-and-authorization
+/lib/gitlab/background_migration/expire_o_auth_tokens.rb @gitlab-org/manage/authentication-and-authorization
/lib/gitlab/background_migration/migrate_u2f_webauthn.rb @gitlab-org/manage/authentication-and-authorization
/lib/gitlab/background_migration/update_users_where_two_factor_auth_required_from_group.rb @gitlab-org/manage/authentication-and-authorization
/lib/gitlab/chat_name_token.rb @gitlab-org/manage/authentication-and-authorization
/lib/gitlab/ci/pipeline/expression/token.rb @gitlab-org/manage/authentication-and-authorization
-/lib/gitlab/external_authorization @gitlab-org/manage/authentication-and-authorization
+/lib/gitlab/external_authorization/ @gitlab-org/manage/authentication-and-authorization
/lib/gitlab/external_authorization.rb @gitlab-org/manage/authentication-and-authorization
-/lib/gitlab/graphql/authorize @gitlab-org/manage/authentication-and-authorization
+/lib/gitlab/graphql/authorize/ @gitlab-org/manage/authentication-and-authorization
/lib/gitlab/jwt_authenticatable.rb @gitlab-org/manage/authentication-and-authorization
/lib/gitlab/jwt_token.rb @gitlab-org/manage/authentication-and-authorization
/lib/gitlab/lfs_token.rb @gitlab-org/manage/authentication-and-authorization
-/lib/gitlab/mail_room @gitlab-org/manage/authentication-and-authorization
+/lib/gitlab/mail_room/ @gitlab-org/manage/authentication-and-authorization
/lib/gitlab/omniauth_initializer.rb @gitlab-org/manage/authentication-and-authorization
/lib/gitlab/project_authorizations.rb @gitlab-org/manage/authentication-and-authorization
-/lib/json_web_token @gitlab-org/manage/authentication-and-authorization
-/lib/omni_auth @gitlab-org/manage/authentication-and-authorization
+/lib/json_web_token/ @gitlab-org/manage/authentication-and-authorization
+/lib/omni_auth/ @gitlab-org/manage/authentication-and-authorization
/lib/system_check/app/authorized_keys_permission_check.rb @gitlab-org/manage/authentication-and-authorization
/lib/system_check/incoming_email/imap_authentication_check.rb @gitlab-org/manage/authentication-and-authorization
/lib/tasks/gitlab/password.rake @gitlab-org/manage/authentication-and-authorization
diff --git a/app/assets/javascripts/content_editor/services/hast_to_prosemirror_converter.js b/app/assets/javascripts/content_editor/services/hast_to_prosemirror_converter.js
index 067965f53eb..9f8505416ba 100644
--- a/app/assets/javascripts/content_editor/services/hast_to_prosemirror_converter.js
+++ b/app/assets/javascripts/content_editor/services/hast_to_prosemirror_converter.js
@@ -63,10 +63,12 @@ function maybeMerge(a, b) {
function createSourceMapAttributes(hastNode, source) {
const { position } = hastNode;
- return {
- sourceMapKey: `${position.start.offset}:${position.end.offset}`,
- sourceMarkdown: source.substring(position.start.offset, position.end.offset),
- };
+ return position.end
+ ? {
+ sourceMapKey: `${position.start.offset}:${position.end.offset}`,
+ sourceMarkdown: source.substring(position.start.offset, position.end.offset),
+ }
+ : {};
}
/**
@@ -252,11 +254,19 @@ const createProseMirrorNodeFactories = (schema, proseMirrorFactorySpecs, source)
const factories = {
root: {
selector: 'root',
- handle: (state, hastNode) => state.openNode(schema.topNodeType, hastNode, {}),
+ handle: (state, hastNode) =>
+ state.openNode(
+ schema.topNodeType,
+ hastNode,
+ {},
+ {
+ wrapTextInParagraph: true,
+ },
+ ),
},
text: {
selector: 'text',
- handle: (state, hastNode) => {
+ handle: (state, hastNode, parent) => {
const { factorySpec } = state.top;
if (/^\s+$/.test(hastNode.value)) {
@@ -264,7 +274,7 @@ const createProseMirrorNodeFactories = (schema, proseMirrorFactorySpecs, source)
}
if (factorySpec.wrapTextInParagraph === true) {
- state.openNode(schema.nodeType('paragraph'));
+ state.openNode(schema.nodeType('paragraph'), hastNode, getAttrs({}, parent, [], source));
state.addText(schema, hastNode.value);
state.closeNode();
} else {
diff --git a/app/assets/javascripts/google_cloud/components/revoke_oauth.vue b/app/assets/javascripts/google_cloud/components/revoke_oauth.vue
index 07d966894f6..c07702ff42b 100644
--- a/app/assets/javascripts/google_cloud/components/revoke_oauth.vue
+++ b/app/assets/javascripts/google_cloud/components/revoke_oauth.vue
@@ -30,7 +30,7 @@ export default {
<p>{{ $options.i18n.description }}</p>
<gl-form :action="url" method="post">
<input :value="$options.csrf.token" type="hidden" name="authenticity_token" />
- <gl-button category="secondary" variant="warning" type="submit">
+ <gl-button category="secondary" variant="danger" type="submit">
{{ $options.i18n.title }}
</gl-button>
</gl-form>
diff --git a/app/assets/javascripts/issuable/components/issuable_header_warnings.vue b/app/assets/javascripts/issuable/components/issuable_header_warnings.vue
index 06d1a2ee233..543dca0afe1 100644
--- a/app/assets/javascripts/issuable/components/issuable_header_warnings.vue
+++ b/app/assets/javascripts/issuable/components/issuable_header_warnings.vue
@@ -27,7 +27,7 @@ export default {
return this.getNoteableData.confidential;
},
isMergeRequest() {
- return this.getNoteableData.targetType === 'merge_request' && this.glFeatures.updatedMrHeader;
+ return this.getNoteableData.targetType === 'merge_request';
},
warningIconsMeta() {
return [
diff --git a/app/assets/javascripts/issuable/components/status_box.vue b/app/assets/javascripts/issuable/components/status_box.vue
index 498dc859186..fe023b156b5 100644
--- a/app/assets/javascripts/issuable/components/status_box.vue
+++ b/app/assets/javascripts/issuable/components/status_box.vue
@@ -74,8 +74,7 @@ export default {
return [
CLASSES[this.state],
{
- 'gl-vertical-align-bottom':
- this.issuableType === IssuableType.MergeRequest && this.glFeatures.updatedMrHeader,
+ 'gl-vertical-align-bottom': this.issuableType === IssuableType.MergeRequest,
},
];
},
diff --git a/app/assets/javascripts/merge_request.js b/app/assets/javascripts/merge_request.js
index 960b25bb552..5058e5a76da 100644
--- a/app/assets/javascripts/merge_request.js
+++ b/app/assets/javascripts/merge_request.js
@@ -156,11 +156,7 @@ MergeRequest.toggleDraftStatus = function (title, isReady) {
} else {
toast(__('Marked as draft. Can only be merged when marked as ready.'));
}
- const titleEl = document.querySelector(
- `.merge-request .detail-page-${
- window.gon?.features?.updatedMrHeader ? 'header' : 'description'
- } .title`,
- );
+ const titleEl = document.querySelector(`.merge-request .detail-page-header .title`);
if (titleEl) {
titleEl.textContent = title;
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_header.vue b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_header.vue
deleted file mode 100644
index e1d88099580..00000000000
--- a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_header.vue
+++ /dev/null
@@ -1,100 +0,0 @@
-<script>
-import {
- GlLink,
- GlTooltipDirective,
- GlModalDirective,
- GlSafeHtmlDirective as SafeHtml,
- GlSprintf,
-} from '@gitlab/ui';
-import { constructWebIDEPath } from '~/lib/utils/url_utility';
-import { s__ } from '~/locale';
-import clipboardButton from '~/vue_shared/components/clipboard_button.vue';
-import TooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate/tooltip_on_truncate.vue';
-import MrWidgetIcon from './mr_widget_icon.vue';
-
-export default {
- name: 'MRWidgetHeader',
- components: {
- clipboardButton,
- TooltipOnTruncate,
- MrWidgetIcon,
- GlLink,
- GlSprintf,
- },
- directives: {
- GlTooltip: GlTooltipDirective,
- GlModalDirective,
- SafeHtml,
- },
- props: {
- mr: {
- type: Object,
- required: true,
- },
- },
- computed: {
- shouldShowCommitsBehindText() {
- return this.mr.divergedCommitsCount > 0;
- },
- branchNameClipboardData() {
- // This supports code in app/assets/javascripts/copy_to_clipboard.js that
- // works around ClipboardJS limitations to allow the context-specific
- // copy/pasting of plain text or GFM.
- return JSON.stringify({
- text: this.mr.sourceBranch,
- gfm: `\`${this.mr.sourceBranch}\``,
- });
- },
- webIdePath() {
- return constructWebIDEPath(this.mr);
- },
- isFork() {
- return this.mr.sourceProjectFullPath !== this.mr.targetProjectFullPath;
- },
- },
- i18n: {
- webIdeText: s__('mrWidget|Open in Web IDE'),
- gitpodText: s__('mrWidget|Open in Gitpod'),
- },
-};
-</script>
-<template>
- <div class="gl-display-flex mr-source-target">
- <mr-widget-icon name="git-merge" />
- <div class="git-merge-container d-flex">
- <div class="normal">
- <strong>
- {{ s__('mrWidget|Request to merge') }}
- <tooltip-on-truncate
- v-safe-html="mr.sourceBranchLink"
- :title="mr.sourceBranch"
- truncate-target="child"
- class="label-branch label-truncate js-source-branch"
- /><clipboard-button
- data-testid="mr-widget-copy-clipboard"
- :text="branchNameClipboardData"
- :title="__('Copy branch name')"
- category="tertiary"
- />
- {{ s__('mrWidget|into') }}
- <tooltip-on-truncate
- :title="mr.targetBranch"
- truncate-target="child"
- class="label-branch label-truncate"
- >
- <a :href="mr.targetBranchTreePath" class="js-target-branch"> {{ mr.targetBranch }} </a>
- </tooltip-on-truncate>
- </strong>
- <div v-if="shouldShowCommitsBehindText" class="diverged-commits-count">
- <gl-sprintf :message="s__('mrWidget|The source branch is %{link} the target branch')">
- <template #link>
- <gl-link :href="mr.targetBranchPath">{{
- n__('%d commit behind', '%d commits behind', mr.divergedCommitsCount)
- }}</gl-link>
- </template>
- </gl-sprintf>
- </div>
- </div>
- </div>
- </div>
-</template>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_related_links.vue b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_related_links.vue
index b8a1f89d232..913aa0e1e34 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_related_links.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_related_links.vue
@@ -93,9 +93,7 @@ export default {
</span>
</p>
<div
- v-if="
- divergedCommitsCount > 0 && glFeatures.updatedMrHeader && !glFeatures.restructuredMrWidget
- "
+ v-if="divergedCommitsCount > 0 && !glFeatures.restructuredMrWidget"
class="diverged-commits-count"
>
<gl-sprintf :message="s__('mrWidget|The source branch is %{link} the target branch')">
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/ready_to_merge.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/ready_to_merge.vue
index 41d35f68790..cf482410bef 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/ready_to_merge.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/ready_to_merge.vue
@@ -722,10 +722,7 @@ export default {
{{ __('Merge details') }}
</strong>
<ul class="gl-pl-4 gl-m-0">
- <li
- v-if="mr.divergedCommitsCount > 0 && glFeatures.updatedMrHeader"
- class="gl-line-height-normal"
- >
+ <li v-if="mr.divergedCommitsCount > 0" class="gl-line-height-normal">
<gl-sprintf
:message="s__('mrWidget|The source branch is %{link} the target branch')"
>
diff --git a/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue b/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue
index 8ebb7f6f159..182ec17062a 100644
--- a/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue
@@ -15,7 +15,6 @@ import SmartInterval from '~/smart_interval';
import { setFaviconOverlay } from '../lib/utils/favicon';
import Loading from './components/loading.vue';
import MrWidgetAlertMessage from './components/mr_widget_alert_message.vue';
-import WidgetHeader from './components/mr_widget_header.vue';
import MrWidgetPipelineContainer from './components/mr_widget_pipeline_container.vue';
import WidgetRelatedLinks from './components/mr_widget_related_links.vue';
import WidgetSuggestPipeline from './components/mr_widget_suggest_pipeline.vue';
@@ -59,7 +58,6 @@ export default {
components: {
Loading,
ExtensionsContainer,
- 'mr-widget-header': WidgetHeader,
'mr-widget-suggest-pipeline': WidgetSuggestPipeline,
MrWidgetPipelineContainer,
'mr-widget-related-links': WidgetRelatedLinks,
@@ -234,9 +232,6 @@ export default {
isRestructuredMrWidgetEnabled() {
return window.gon?.features?.restructuredMrWidget;
},
- isUpdatedHeaderEnabled() {
- return window.gon?.features?.updatedMrHeader;
- },
},
watch: {
'mr.machineValue': {
@@ -531,14 +526,12 @@ export default {
<template>
<div v-if="isLoaded" class="mr-state-widget gl-mt-3">
<header
- v-if="shouldRenderCollaborationStatus || !isUpdatedHeaderEnabled"
- :class="{ 'mr-widget-workflow gl-mt-0!': isUpdatedHeaderEnabled }"
- class="gl-rounded-base gl-border-solid gl-border-1 gl-border-gray-100 gl-overflow-hidden"
+ v-if="shouldRenderCollaborationStatus"
+ class="gl-rounded-base gl-border-solid gl-border-1 gl-border-gray-100 gl-overflow-hidden mr-widget-workflow gl-mt-0!"
>
<mr-widget-alert-message v-if="shouldRenderCollaborationStatus" type="info">
{{ s__('mrWidget|Members who can merge are allowed to add commits.') }}
</mr-widget-alert-message>
- <mr-widget-header v-if="!isUpdatedHeaderEnabled" :mr="mr" />
</header>
<mr-widget-suggest-pipeline
v-if="shouldSuggestPipelines"
diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb
index 458df40ece1..f5cb3a641ea 100644
--- a/app/controllers/projects/merge_requests_controller.rb
+++ b/app/controllers/projects/merge_requests_controller.rb
@@ -45,7 +45,6 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
push_frontend_feature_flag(:realtime_labels, project)
push_frontend_feature_flag(:updated_diff_expansion_buttons, project)
push_frontend_feature_flag(:mr_attention_requests, current_user)
- push_frontend_feature_flag(:updated_mr_header, project)
push_frontend_feature_flag(:remove_diff_header_icons, project)
push_frontend_feature_flag(:moved_mr_sidebar, project)
end
diff --git a/app/helpers/issues_helper.rb b/app/helpers/issues_helper.rb
index 75b20412e71..98afab554d2 100644
--- a/app/helpers/issues_helper.rb
+++ b/app/helpers/issues_helper.rb
@@ -28,18 +28,16 @@ module IssuesHelper
end
def status_box_class(item)
- updated_mr_header_enabled = Feature.enabled?(:updated_mr_header, @project)
-
if item.try(:expired?)
'gl-bg-orange-500'
elsif item.try(:merged?)
- updated_mr_header_enabled ? 'badge-info' : 'gl-bg-blue-500'
+ 'badge-info'
elsif item.closed?
- item.is_a?(MergeRequest) && updated_mr_header_enabled ? 'badge-danger' : 'gl-bg-red-500'
+ item.is_a?(MergeRequest) ? 'badge-danger' : 'gl-bg-red-500'
elsif item.try(:upcoming?)
'gl-bg-gray-500'
else
- item.is_a?(MergeRequest) && updated_mr_header_enabled ? 'badge-success' : 'gl-bg-green-500'
+ item.is_a?(MergeRequest) ? 'badge-success' : 'gl-bg-green-500'
end
end
diff --git a/app/models/member.rb b/app/models/member.rb
index a5084c8a60c..45ad47f56a4 100644
--- a/app/models/member.rb
+++ b/app/models/member.rb
@@ -170,6 +170,7 @@ class Member < ApplicationRecord
scope :owners_and_maintainers, -> { active.where(access_level: [OWNER, MAINTAINER]) }
scope :with_user, -> (user) { where(user: user) }
scope :by_access_level, -> (access_level) { active.where(access_level: access_level) }
+ scope :all_by_access_level, -> (access_level) { where(access_level: access_level) }
scope :preload_user_and_notification_settings, -> { preload(user: :notification_settings) }
diff --git a/app/models/user.rb b/app/models/user.rb
index 982398e846b..40735f85ded 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -1366,9 +1366,16 @@ class User < ApplicationRecord
end
def solo_owned_groups
- @solo_owned_groups ||= owned_groups.includes(:owners).select do |group|
- group.owners == [self]
- end
+ # For each owned group, count the owners found in self and ancestors.
+ counts = GroupMember
+ .from('unnest(namespaces.traversal_ids) AS ancestors(ancestor_id), members')
+ .where('members.source_id = ancestors.ancestor_id')
+ .all_by_access_level(GroupMember::OWNER)
+ .having('count(members.user_id) = 1')
+
+ Group
+ .from(owned_groups, :namespaces)
+ .where_exists(counts)
end
def with_defaults
diff --git a/app/views/projects/merge_requests/_mr_box.html.haml b/app/views/projects/merge_requests/_mr_box.html.haml
index 865005a9e42..04fcafd1277 100644
--- a/app/views/projects/merge_requests/_mr_box.html.haml
+++ b/app/views/projects/merge_requests/_mr_box.html.haml
@@ -1,9 +1,3 @@
-- updated_mr_header = Feature.enabled?(:updated_mr_header, @project)
-
-.detail-page-description.py-2{ class: "#{'is-merge-request' if updated_mr_header && !fluid_layout}" }
- - if updated_mr_header
- = render 'shared/issuable/status_box', issuable: @merge_request
- = merge_request_header(@project, @merge_request)
- - else
- %h2.title.mb-0{ data: { qa_selector: 'title_content' } }
- = markdown_field(@merge_request, :title)
+.detail-page-description.py-2{ class: "#{'is-merge-request' if !fluid_layout}" }
+ = render 'shared/issuable/status_box', issuable: @merge_request
+ = merge_request_header(@project, @merge_request)
diff --git a/app/views/projects/merge_requests/_mr_title.html.haml b/app/views/projects/merge_requests/_mr_title.html.haml
index 2d4d4f038e7..ed058235284 100644
--- a/app/views/projects/merge_requests/_mr_title.html.haml
+++ b/app/views/projects/merge_requests/_mr_title.html.haml
@@ -2,8 +2,7 @@
- can_update_merge_request = can?(current_user, :update_merge_request, @merge_request)
- can_reopen_merge_request = can?(current_user, :reopen_merge_request, @merge_request)
- are_close_and_open_buttons_hidden = merge_request_button_hidden?(@merge_request, true) && merge_request_button_hidden?(@merge_request, false)
-- updated_mr_header_enabled = Feature.enabled?(:updated_mr_header, @project)
-- cache_key = [@project, @merge_request, can_update_merge_request, can_reopen_merge_request, are_close_and_open_buttons_hidden, current_user&.preferred_language, "1.1-#{updated_mr_header_enabled}", moved_mr_sidebar_enabled?]
+- cache_key = [@project, @merge_request, can_update_merge_request, can_reopen_merge_request, are_close_and_open_buttons_hidden, current_user&.preferred_language, "1.1-updated_header", moved_mr_sidebar_enabled?]
= cache(cache_key, expires_in: 1.day) do
- if @merge_request.closed_or_merged_without_fork?
@@ -13,24 +12,18 @@
= c.body do
= _('The source project of this merge request has been removed.')
- .detail-page-header.border-bottom-0.pt-0.pb-0{ class: "#{'gl-display-block gl-md-display-flex!' if updated_mr_header_enabled} #{'is-merge-request' if moved_mr_sidebar_enabled? && !fluid_layout}" }
+ .detail-page-header.border-bottom-0.pt-0.pb-0.gl-display-block{ class: "gl-md-display-flex! #{'is-merge-request' if moved_mr_sidebar_enabled? && !fluid_layout}" }
.detail-page-header-body
- - unless updated_mr_header_enabled
- = render "shared/issuable/status_box", issuable: @merge_request
- .issuable-meta{ class: "#{'gl-display-flex' if updated_mr_header_enabled}" }
- - if updated_mr_header_enabled
- #js-issuable-header-warnings
- %h2.title.gl-my-0.gl-display-inline-block{ data: { qa_selector: 'title_content' } }
- = markdown_field(@merge_request, :title)
- - else
- #js-issuable-header-warnings
- = issuable_meta(@merge_request, @project)
+ .issuable-meta.gl-display-flex
+ #js-issuable-header-warnings
+ %h2.title.gl-my-0.gl-display-inline-block{ data: { qa_selector: 'title_content' } }
+ = markdown_field(@merge_request, :title)
%div
%button.gl-button.btn.btn-default.btn-icon.float-right.gl-display-block.gutter-toggle.issuable-gutter-toggle.js-sidebar-toggle{ type: 'button', class: "#{'gl-md-display-none!' if moved_mr_sidebar_enabled? } #{'gl-sm-display-none!' unless moved_mr_sidebar_enabled?}" }
= sprite_icon('chevron-double-lg-left')
- .detail-page-header-actions.js-issuable-actions{ class: "#{'gl-align-self-start is-merge-request' if updated_mr_header_enabled}" }
+ .detail-page-header-actions.gl-align-self-start.is-merge-request.js-issuable-actions
- if can_update_merge_request
= link_to _('Edit'), edit_project_merge_request_path(@project, @merge_request), class: "gl-display-none gl-md-display-block btn gl-button btn-default btn-grouped js-issuable-edit", data: { qa_selector: "edit_button" }
diff --git a/app/views/projects/merge_requests/show.html.haml b/app/views/projects/merge_requests/show.html.haml
index 4bb14018431..5ef97f2de27 100644
--- a/app/views/projects/merge_requests/show.html.haml
+++ b/app/views/projects/merge_requests/show.html.haml
@@ -21,7 +21,7 @@
.merge-request-details.issuable-details{ data: { id: @merge_request.project.id } }
= render "projects/merge_requests/mr_box"
.merge-request-tabs-holder{ class: ("js-tabs-affix" unless ENV['RAILS_ENV'] == 'test') }
- .merge-request-tabs-container{ class: "#{'is-merge-request' if Feature.enabled?(:updated_mr_header, @project) && !fluid_layout}" }
+ .merge-request-tabs-container{ class: "#{'is-merge-request' if !fluid_layout}" }
%ul.merge-request-tabs.nav-tabs.nav.nav-links
= render "projects/merge_requests/tabs/tab", class: "notes-tab", qa_selector: "notes_tab" do
= tab_link_for @merge_request, :show, force_link: @commit.present? do
diff --git a/app/views/projects/tags/new.html.haml b/app/views/projects/tags/new.html.haml
index 4281152225a..428d87c6f03 100644
--- a/app/views/projects/tags/new.html.haml
+++ b/app/views/projects/tags/new.html.haml
@@ -2,11 +2,9 @@
- default_ref = params[:ref] || @project.default_branch
- if @error
- .gl-alert.gl-alert-danger
- = sprite_icon('error', css_class: 'gl-icon gl-alert-icon gl-alert-icon-no-title')
- %button.js-close.gl-alert-dismiss{ type: 'button', 'aria-label' => _('Dismiss') }
- = sprite_icon('close', css_class: 'gl-icon')
- = @error
+ = render Pajamas::AlertComponent.new(variant: :danger, dismissible: true, close_button_class: 'gl-alert-dismiss') do |c|
+ = c.body do
+ = @error
%h3.page-title
= s_('TagsPage|New Tag')
diff --git a/app/views/shared/issuable/_status_box.html.haml b/app/views/shared/issuable/_status_box.html.haml
index 4fda1f11545..125ef921cfa 100644
--- a/app/views/shared/issuable/_status_box.html.haml
+++ b/app/views/shared/issuable/_status_box.html.haml
@@ -2,8 +2,7 @@
- badge_icon = state_name_with_icon(issuable)[1]
- badge_variant = issuable.open? ? :success : issuable.merged? ? :info : :danger
- badge_status_class = issuable.open? ? 'issuable-status-badge-open' : issuable.merged? ? 'issuable-status-badge-merged' : 'issuable-status-badge-closed'
-- updated_mr_header_enabled = Feature.enabled?(:updated_mr_header, @project) && issuable.is_a?(MergeRequest)
-- badge_classes = "js-mr-status-box issuable-status-badge gl-mr-3 #{badge_status_class} #{'gl-vertical-align-bottom' if updated_mr_header_enabled}"
+- badge_classes = "js-mr-status-box issuable-status-badge gl-mr-3 #{badge_status_class} #{'gl-vertical-align-bottom' if issuable.is_a?(MergeRequest)}"
= gl_badge_tag({ variant: badge_variant, icon: badge_icon, icon_classes: 'gl-mr-0!' }, { class: badge_classes, data: { project_path: issuable.project.path_with_namespace, iid: issuable.iid, issuable_type: 'merge_request', state: issuable.state } }) do
%span.gl-display-none.gl-sm-display-block.gl-ml-2
diff --git a/config/feature_flags/development/updated_mr_header.yml b/config/feature_flags/development/updated_mr_header.yml
deleted file mode 100644
index 7268076b587..00000000000
--- a/config/feature_flags/development/updated_mr_header.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: updated_mr_header
-introduced_by_url:
-rollout_issue_url:
-milestone: '14.10'
-type: development
-group: group::code review
-default_enabled: true
diff --git a/data/deprecations/14-5-certificate-based-integration-with-kubernetes.yml b/data/deprecations/14-5-certificate-based-integration-with-kubernetes.yml
index 6ab678c4199..43a071ff746 100644
--- a/data/deprecations/14-5-certificate-based-integration-with-kubernetes.yml
+++ b/data/deprecations/14-5-certificate-based-integration-with-kubernetes.yml
@@ -7,7 +7,7 @@
body: |
The certificate-based integration with Kubernetes [will be deprecated and removed](https://about.gitlab.com/blog/2021/11/15/deprecating-the-cert-based-kubernetes-integration/).
- As a self-managed customer, we are introducing a feature flag in GitLab 15.0 so you can keep your certificate-based integration enabled. However, the feature flag will be disabled by default, so this change is a **breaking change**.
+ As a self-managed customer, we are introducing the [feature flag](../administration/feature_flags.md#enable-or-disable-the-feature) `certificate_based_clusters` in GitLab 15.0 so you can keep your certificate-based integration enabled. However, the feature flag will be disabled by default, so this change is a **breaking change**.
In GitLab 16.0 we will remove both the feature and its related code. Until the final removal in 16.0, features built on this integration will continue to work, if you enable the feature flag. Until the feature is removed, GitLab will continue to fix security and critical issues as they arise.
diff --git a/doc/api/personal_access_tokens.md b/doc/api/personal_access_tokens.md
index c49af2a745c..46a4c674560 100644
--- a/doc/api/personal_access_tokens.md
+++ b/doc/api/personal_access_tokens.md
@@ -70,6 +70,29 @@ curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/a
]
```
+## Get single personal access token by ID
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/362239) in GitLab 15.1.
+
+Get a single personal access token by its ID. Users can get their own tokens.
+Administrators can get any token.
+
+```plaintext
+GET /personal_access_tokens/:id
+```
+
+| Attribute | Type | required | Description |
+|-----------|---------|----------|---------------------|
+| `id` | integer/string | yes | ID of personal access token |
+
+```shell
+curl --request GET --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/personal_access_tokens/<id>"
+```
+
+### Responses
+
+- `401: Unauthorized` if the user doesn't have access to the token they're requesting the ID or if the token with matching ID doesn't exist.
+
## Revoke a personal access token
Revoke a personal access token by either:
diff --git a/doc/development/application_limits.md b/doc/development/application_limits.md
index c4146b5af3e..7e77af59125 100644
--- a/doc/development/application_limits.md
+++ b/doc/development/application_limits.md
@@ -189,3 +189,23 @@ the middleware level, this can be used at the controller or API level.
See the `CheckRateLimit` concern for use in controllers. In other parts of the code
the `Gitlab::ApplicationRateLimiter` module can be called directly.
+
+## Next rate limiting architecture
+
+In May 2022 we've started working on the next iteration of our application
+limits framework using a forward looking rate limiting architecture.
+
+We are working on defining new requirements and designing the next
+architecture, so if you need new functionalities to add new limits, instead of
+building them right now, consider contributing to the
+[Rate Limiting Architecture Working Group](https://about.gitlab.com/company/team/structure/working-groups/rate-limit-architecture/)
+
+Examples of what features we might want to build into the next iteration of
+rate limiting architecture:
+
+1. Making it possible to define and override limits per namespace / per plan.
+1. Automatically generating documentation about what limits are implemented and
+ what the defaults are.
+1. Defining limits in a single place that is easy to find an explore.
+1. Soft and hard limits, with support for notifying users when a limit is
+ approaching.
diff --git a/doc/development/contributing/verify/index.md b/doc/development/contributing/verify/index.md
index 58285877b48..55ae2c75033 100644
--- a/doc/development/contributing/verify/index.md
+++ b/doc/development/contributing/verify/index.md
@@ -164,12 +164,26 @@ data from the database, file system, or object storage, you should get an extra
of eyes on your changes. When you are defining a new retention policy, you
should double check with PMs and EMs.
+### Get your design reviewed
+
+When you are designing a subsystem for pipeline processing and transitioning
+CI/CD statuses, request an additional opinion on the design from a Verify maintainer (`@gitlab-org/maintainers/cicd-verify`)
+as early as possible and hold others accountable for doing the same. Having your
+design reviewed by a Verify maintainer helps to identify any blind spots you might
+have overlooked as early as possible and possibly leads to a better solution.
+
+By having the design reviewed before any development work is started, it also helps to
+make merge request review more efficient. You would be less likely to encounter
+significantly differing opinions or change requests during the maintainer review
+if the design has been reviewed by a Verify maintainer. As a result, the merge request
+could be merged sooner.
+
### Get your changes reviewed
When your merge request is ready for reviews you must assign
reviewers and then maintainers. Depending on the complexity of a change, you
might want to involve the people that know the most about the codebase area you are
-changing. We do have many domain experts in Verify and it is absolutely acceptable to
+changing. We do have many domain experts and maintainers in Verify and it is absolutely acceptable to
ask them to review your code when you are not certain if a reviewer or
maintainer assigned by the Reviewer Roulette has enough context about the
change.
@@ -229,7 +243,3 @@ There are much more likely scenarios that
can have disastrous consequences. GitLab CI/CD is being used by companies
building medical, aviation, and automotive software. Continuous Integration is
a mission critical part of software engineering.
-
-When you are working on a subsystem for pipeline processing and transitioning
-CI/CD statuses, request an additional opinion on the design from a domain expert
-as early as possible and hold others accountable for doing the same.
diff --git a/doc/update/deprecations.md b/doc/update/deprecations.md
index 3e04018e647..44c7a781c2e 100644
--- a/doc/update/deprecations.md
+++ b/doc/update/deprecations.md
@@ -1654,7 +1654,7 @@ changes to your code, settings, or workflow.
The certificate-based integration with Kubernetes [will be deprecated and removed](https://about.gitlab.com/blog/2021/11/15/deprecating-the-cert-based-kubernetes-integration/).
-As a self-managed customer, we are introducing a feature flag in GitLab 15.0 so you can keep your certificate-based integration enabled. However, the feature flag will be disabled by default, so this change is a **breaking change**.
+As a self-managed customer, we are introducing the [feature flag](../administration/feature_flags.md#enable-or-disable-the-feature) `certificate_based_clusters` in GitLab 15.0 so you can keep your certificate-based integration enabled. However, the feature flag will be disabled by default, so this change is a **breaking change**.
In GitLab 16.0 we will remove both the feature and its related code. Until the final removal in 16.0, features built on this integration will continue to work, if you enable the feature flag. Until the feature is removed, GitLab will continue to fix security and critical issues as they arise.
diff --git a/lib/api/personal_access_tokens.rb b/lib/api/personal_access_tokens.rb
index 40e6486dae9..f8b744bb14b 100644
--- a/lib/api/personal_access_tokens.rb
+++ b/lib/api/personal_access_tokens.rb
@@ -54,6 +54,14 @@ module API
present paginate(tokens), with: Entities::PersonalAccessToken
end
+ get ':id' do
+ token = PersonalAccessToken.find_by_id(params[:id])
+
+ unauthorized! unless token && Ability.allowed?(current_user, :read_user_personal_access_tokens, token.user)
+
+ present token, with: Entities::PersonalAccessToken
+ end
+
delete 'self' do
revoke_token(access_token)
end
diff --git a/lib/gitlab/ci/config/external/file/local.rb b/lib/gitlab/ci/config/external/file/local.rb
index feb2cbb19ad..36fc5c656fc 100644
--- a/lib/gitlab/ci/config/external/file/local.rb
+++ b/lib/gitlab/ci/config/external/file/local.rb
@@ -42,7 +42,9 @@ module Gitlab
end
def fetch_local_content
- context.project.repository.blob_data_at(context.sha, location)
+ context.logger.instrument(:config_file_fetch_local_content) do
+ context.project.repository.blob_data_at(context.sha, location)
+ end
rescue GRPC::InvalidArgument
errors.push("Sha #{context.sha} is not valid!")
diff --git a/lib/gitlab/ci/config/external/file/project.rb b/lib/gitlab/ci/config/external/file/project.rb
index 09c36a1bcb6..b7fef081269 100644
--- a/lib/gitlab/ci/config/external/file/project.rb
+++ b/lib/gitlab/ci/config/external/file/project.rb
@@ -65,7 +65,9 @@ module Gitlab
return unless can_access_local_content?
return unless sha
- project.repository.blob_data_at(sha, location)
+ context.logger.instrument(:config_file_fetch_project_content) do
+ project.repository.blob_data_at(sha, location)
+ end
rescue GRPC::NotFound, GRPC::Internal
nil
end
diff --git a/lib/gitlab/ci/config/external/file/remote.rb b/lib/gitlab/ci/config/external/file/remote.rb
index 7d3a2362246..3984bf9e4f8 100644
--- a/lib/gitlab/ci/config/external/file/remote.rb
+++ b/lib/gitlab/ci/config/external/file/remote.rb
@@ -40,7 +40,9 @@ module Gitlab
def fetch_remote_content
begin
- response = Gitlab::HTTP.get(location)
+ response = context.logger.instrument(:config_file_fetch_remote_content) do
+ Gitlab::HTTP.get(location)
+ end
rescue SocketError
errors.push("Remote file `#{masked_location}` could not be fetched because of a socket error!")
rescue Timeout::Error
diff --git a/lib/gitlab/ci/config/external/file/template.rb b/lib/gitlab/ci/config/external/file/template.rb
index 58b81b259cb..5fcf7c71bdf 100644
--- a/lib/gitlab/ci/config/external/file/template.rb
+++ b/lib/gitlab/ci/config/external/file/template.rb
@@ -52,7 +52,9 @@ module Gitlab
end
def fetch_template_content
- Gitlab::Template::GitlabCiYmlTemplate.find(template_name, context.project)&.content
+ context.logger.instrument(:config_file_fetch_template_content) do
+ Gitlab::Template::GitlabCiYmlTemplate.find(template_name, context.project)&.content
+ end
end
def masked_raw
diff --git a/lib/gitlab/usage/service_ping_report.rb b/lib/gitlab/usage/service_ping_report.rb
index e73200cbd4a..1eda72ba570 100644
--- a/lib/gitlab/usage/service_ping_report.rb
+++ b/lib/gitlab/usage/service_ping_report.rb
@@ -24,7 +24,7 @@ module Gitlab
instrumented_payload = Gitlab::Usage::ServicePing::InstrumentedPayload.new(instrumented_metrics_key_paths, output_method).build
- old_payload.deep_merge(instrumented_payload)
+ old_payload.with_indifferent_access.deep_merge(instrumented_payload)
end
def all_metrics_values(cached)
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 543ed89b726..58ca895693f 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -45360,12 +45360,6 @@ msgstr ""
msgid "mrWidget|More information"
msgstr ""
-msgid "mrWidget|Open in Gitpod"
-msgstr ""
-
-msgid "mrWidget|Open in Web IDE"
-msgstr ""
-
msgid "mrWidget|Please restore it or use a different %{type} branch."
msgstr ""
@@ -45384,9 +45378,6 @@ msgstr ""
msgid "mrWidget|Remove from merge train"
msgstr ""
-msgid "mrWidget|Request to merge"
-msgstr ""
-
msgid "mrWidget|Resolve conflicts"
msgstr ""
@@ -45462,9 +45453,6 @@ msgstr ""
msgid "mrWidget|Your password"
msgstr ""
-msgid "mrWidget|into"
-msgstr ""
-
msgid "must be a Debian package"
msgstr ""
diff --git a/qa/qa/page/merge_request/show.rb b/qa/qa/page/merge_request/show.rb
index ba4e8d4f9fa..226f9fbbadb 100644
--- a/qa/qa/page/merge_request/show.rb
+++ b/qa/qa/page/merge_request/show.rb
@@ -115,12 +115,9 @@ module QA
element :description_content
end
- view 'app/views/projects/merge_requests/_mr_box.html.haml' do
- element :title_content, required: true
- end
-
view 'app/views/projects/merge_requests/_mr_title.html.haml' do
element :edit_button
+ element :title_content, required: true
end
view 'app/views/projects/merge_requests/show.html.haml' do
diff --git a/spec/features/merge_request/user_views_user_status_on_merge_request_spec.rb b/spec/features/merge_request/user_views_user_status_on_merge_request_spec.rb
index f637186ec67..b214486b3c1 100644
--- a/spec/features/merge_request/user_views_user_status_on_merge_request_spec.rb
+++ b/spec/features/merge_request/user_views_user_status_on_merge_request_spec.rb
@@ -10,16 +10,6 @@ RSpec.describe 'Project > Merge request > View user status' do
subject { visit merge_request_path(merge_request) }
- describe 'the status of the merge request author' do
- before do
- stub_feature_flags(updated_mr_header: false)
- end
-
- it_behaves_like 'showing user status' do
- let(:user_with_status) { merge_request.author }
- end
- end
-
context 'for notes', :js do
describe 'the status of the author of a note on a merge request' do
let(:note) { create(:note, noteable: merge_request, project: project, author: create(:user)) }
diff --git a/spec/frontend/content_editor/remark_markdown_processing_spec.js b/spec/frontend/content_editor/remark_markdown_processing_spec.js
index 06f109f8603..58aacd72dda 100644
--- a/spec/frontend/content_editor/remark_markdown_processing_spec.js
+++ b/spec/frontend/content_editor/remark_markdown_processing_spec.js
@@ -207,6 +207,19 @@ describe('Client side Markdown processing', () => {
),
},
{
+ markdown: `
+<i class="foo">
+ *bar*
+</i>
+ `,
+ expectedDoc: doc(
+ paragraph(
+ sourceAttrs('0:28', '<i class="foo">\n *bar*\n</i>'),
+ italic(sourceAttrs('0:28', '<i class="foo">\n *bar*\n</i>'), '\n *bar*\n'),
+ ),
+ ),
+ },
+ {
markdown: '[GitLab](https://gitlab.com "Go to GitLab")',
expectedDoc: doc(
paragraph(
@@ -342,8 +355,14 @@ two
expectedDoc: doc(
bulletList(
sourceAttrs('0:27', '- List item 1\n- List item 2'),
- listItem(sourceAttrs('0:13', '- List item 1'), paragraph('List item 1')),
- listItem(sourceAttrs('14:27', '- List item 2'), paragraph('List item 2')),
+ listItem(
+ sourceAttrs('0:13', '- List item 1'),
+ paragraph(sourceAttrs('0:13', '- List item 1'), 'List item 1'),
+ ),
+ listItem(
+ sourceAttrs('14:27', '- List item 2'),
+ paragraph(sourceAttrs('14:27', '- List item 2'), 'List item 2'),
+ ),
),
),
},
@@ -355,8 +374,14 @@ two
expectedDoc: doc(
bulletList(
sourceAttrs('0:27', '* List item 1\n* List item 2'),
- listItem(sourceAttrs('0:13', '* List item 1'), paragraph('List item 1')),
- listItem(sourceAttrs('14:27', '* List item 2'), paragraph('List item 2')),
+ listItem(
+ sourceAttrs('0:13', '* List item 1'),
+ paragraph(sourceAttrs('0:13', '* List item 1'), 'List item 1'),
+ ),
+ listItem(
+ sourceAttrs('14:27', '* List item 2'),
+ paragraph(sourceAttrs('14:27', '* List item 2'), 'List item 2'),
+ ),
),
),
},
@@ -368,8 +393,14 @@ two
expectedDoc: doc(
bulletList(
sourceAttrs('0:27', '+ List item 1\n+ List item 2'),
- listItem(sourceAttrs('0:13', '+ List item 1'), paragraph('List item 1')),
- listItem(sourceAttrs('14:27', '+ List item 2'), paragraph('List item 2')),
+ listItem(
+ sourceAttrs('0:13', '+ List item 1'),
+ paragraph(sourceAttrs('0:13', '+ List item 1'), 'List item 1'),
+ ),
+ listItem(
+ sourceAttrs('14:27', '+ List item 2'),
+ paragraph(sourceAttrs('14:27', '+ List item 2'), 'List item 2'),
+ ),
),
),
},
@@ -381,8 +412,14 @@ two
expectedDoc: doc(
orderedList(
sourceAttrs('0:29', '1. List item 1\n1. List item 2'),
- listItem(sourceAttrs('0:14', '1. List item 1'), paragraph('List item 1')),
- listItem(sourceAttrs('15:29', '1. List item 2'), paragraph('List item 2')),
+ listItem(
+ sourceAttrs('0:14', '1. List item 1'),
+ paragraph(sourceAttrs('0:14', '1. List item 1'), 'List item 1'),
+ ),
+ listItem(
+ sourceAttrs('15:29', '1. List item 2'),
+ paragraph(sourceAttrs('15:29', '1. List item 2'), 'List item 2'),
+ ),
),
),
},
@@ -394,8 +431,14 @@ two
expectedDoc: doc(
orderedList(
sourceAttrs('0:29', '1. List item 1\n2. List item 2'),
- listItem(sourceAttrs('0:14', '1. List item 1'), paragraph('List item 1')),
- listItem(sourceAttrs('15:29', '2. List item 2'), paragraph('List item 2')),
+ listItem(
+ sourceAttrs('0:14', '1. List item 1'),
+ paragraph(sourceAttrs('0:14', '1. List item 1'), 'List item 1'),
+ ),
+ listItem(
+ sourceAttrs('15:29', '2. List item 2'),
+ paragraph(sourceAttrs('15:29', '2. List item 2'), 'List item 2'),
+ ),
),
),
},
@@ -407,8 +450,14 @@ two
expectedDoc: doc(
orderedList(
sourceAttrs('0:29', '1) List item 1\n2) List item 2'),
- listItem(sourceAttrs('0:14', '1) List item 1'), paragraph('List item 1')),
- listItem(sourceAttrs('15:29', '2) List item 2'), paragraph('List item 2')),
+ listItem(
+ sourceAttrs('0:14', '1) List item 1'),
+ paragraph(sourceAttrs('0:14', '1) List item 1'), 'List item 1'),
+ ),
+ listItem(
+ sourceAttrs('15:29', '2) List item 2'),
+ paragraph(sourceAttrs('15:29', '2) List item 2'), 'List item 2'),
+ ),
),
),
},
@@ -422,10 +471,13 @@ two
sourceAttrs('0:33', '- List item 1\n - Sub list item 1'),
listItem(
sourceAttrs('0:33', '- List item 1\n - Sub list item 1'),
- paragraph('List item 1\n'),
+ paragraph(sourceAttrs('0:33', '- List item 1\n - Sub list item 1'), 'List item 1\n'),
bulletList(
sourceAttrs('16:33', '- Sub list item 1'),
- listItem(sourceAttrs('16:33', '- Sub list item 1'), paragraph('Sub list item 1')),
+ listItem(
+ sourceAttrs('16:33', '- Sub list item 1'),
+ paragraph(sourceAttrs('16:33', '- Sub list item 1'), 'Sub list item 1'),
+ ),
),
),
),
@@ -477,8 +529,14 @@ two
sourceAttrs('0:31', '> - List item 1\n> - List item 2'),
bulletList(
sourceAttrs('2:31', '- List item 1\n> - List item 2'),
- listItem(sourceAttrs('2:15', '- List item 1'), paragraph('List item 1')),
- listItem(sourceAttrs('18:31', '- List item 2'), paragraph('List item 2')),
+ listItem(
+ sourceAttrs('2:15', '- List item 1'),
+ paragraph(sourceAttrs('2:15', '- List item 1'), 'List item 1'),
+ ),
+ listItem(
+ sourceAttrs('18:31', '- List item 2'),
+ paragraph(sourceAttrs('18:31', '- List item 2'), 'List item 2'),
+ ),
),
),
),
diff --git a/spec/frontend/vue_mr_widget/components/mr_widget_header_spec.js b/spec/frontend/vue_mr_widget/components/mr_widget_header_spec.js
deleted file mode 100644
index ed6dc598845..00000000000
--- a/spec/frontend/vue_mr_widget/components/mr_widget_header_spec.js
+++ /dev/null
@@ -1,176 +0,0 @@
-import { shallowMount, mount } from '@vue/test-utils';
-import Header from '~/vue_merge_request_widget/components/mr_widget_header.vue';
-
-describe('MRWidgetHeader', () => {
- let wrapper;
-
- const createComponent = (propsData = {}) => {
- wrapper = shallowMount(Header, {
- propsData,
- });
- };
-
- afterEach(() => {
- wrapper.destroy();
- gon.relative_url_root = '';
- });
-
- const commonMrProps = {
- divergedCommitsCount: 1,
- sourceBranch: 'mr-widget-refactor',
- sourceBranchLink: '<a href="/foo/bar/mr-widget-refactor">Link</a>',
- targetBranch: 'main',
- targetBranchPath: '/foo/bar/main',
- statusPath: 'abc',
- };
-
- describe('computed', () => {
- describe('shouldShowCommitsBehindText', () => {
- it('return true when there are divergedCommitsCount', () => {
- createComponent({
- mr: {
- divergedCommitsCount: 12,
- sourceBranch: 'mr-widget-refactor',
- sourceBranchLink: '<a href="/foo/bar/mr-widget-refactor">Link</a>',
- targetBranch: 'main',
- statusPath: 'abc',
- },
- });
-
- expect(wrapper.vm.shouldShowCommitsBehindText).toBe(true);
- });
-
- it('returns false where there are no divergedComits count', () => {
- createComponent({
- mr: {
- divergedCommitsCount: 0,
- sourceBranch: 'mr-widget-refactor',
- sourceBranchLink: '<a href="/foo/bar/mr-widget-refactor">Link</a>',
- targetBranch: 'main',
- statusPath: 'abc',
- },
- });
-
- expect(wrapper.vm.shouldShowCommitsBehindText).toBe(false);
- });
- });
-
- describe('commitsBehindText', () => {
- it('returns singular when there is one commit', () => {
- wrapper = mount(Header, {
- propsData: {
- mr: commonMrProps,
- },
- });
-
- expect(wrapper.find('.diverged-commits-count').element.innerHTML).toBe(
- 'The source branch is <a href="/foo/bar/main" class="gl-link">1 commit behind</a> the target branch',
- );
- });
-
- it('returns plural when there is more than one commit', () => {
- wrapper = mount(Header, {
- propsData: {
- mr: {
- ...commonMrProps,
- divergedCommitsCount: 2,
- },
- },
- });
- expect(wrapper.find('.diverged-commits-count').element.innerHTML).toBe(
- 'The source branch is <a href="/foo/bar/main" class="gl-link">2 commits behind</a> the target branch',
- );
- });
- });
- });
-
- describe('template', () => {
- describe('common elements', () => {
- beforeEach(() => {
- createComponent({
- mr: {
- divergedCommitsCount: 12,
- sourceBranch: 'mr-widget-refactor',
- sourceBranchLink: '<a href="/foo/bar/mr-widget-refactor">mr-widget-refactor</a>',
- sourceBranchRemoved: false,
- targetBranchPath: 'foo/bar/commits-path',
- targetBranchTreePath: 'foo/bar/tree/path',
- targetBranch: 'main',
- isOpen: true,
- emailPatchesPath: '/mr/email-patches',
- plainDiffPath: '/mr/plainDiffPath',
- statusPath: 'abc',
- },
- });
- });
-
- it('renders source branch link', () => {
- expect(wrapper.find('.js-source-branch').html()).toContain(
- '<a href="/foo/bar/mr-widget-refactor">mr-widget-refactor</a>',
- );
- });
-
- it('renders clipboard button', () => {
- expect(wrapper.find('[data-testid="mr-widget-copy-clipboard"]')).not.toBe(null);
- });
-
- it('renders target branch', () => {
- expect(wrapper.find('.js-target-branch').text().trim()).toBe('main');
- });
- });
-
- describe('without diverged commits', () => {
- beforeEach(() => {
- createComponent({
- mr: {
- divergedCommitsCount: 0,
- sourceBranch: 'mr-widget-refactor',
- sourceBranchLink: '<a href="/foo/bar/mr-widget-refactor">mr-widget-refactor</a>',
- sourceBranchRemoved: false,
- targetBranchPath: 'foo/bar/commits-path',
- targetBranchTreePath: 'foo/bar/tree/path',
- targetBranch: 'main',
- isOpen: true,
- emailPatchesPath: '/mr/email-patches',
- plainDiffPath: '/mr/plainDiffPath',
- statusPath: 'abc',
- },
- });
- });
-
- it('does not render diverged commits info', () => {
- expect(wrapper.find('.diverged-commits-count').exists()).toBe(false);
- });
- });
-
- describe('with diverged commits', () => {
- beforeEach(() => {
- wrapper = mount(Header, {
- propsData: {
- mr: {
- ...commonMrProps,
- divergedCommitsCount: 12,
- sourceBranchRemoved: false,
- targetBranchPath: 'foo/bar/commits-path',
- targetBranchTreePath: 'foo/bar/tree/path',
- isOpen: true,
- emailPatchesPath: '/mr/email-patches',
- plainDiffPath: '/mr/plainDiffPath',
- },
- },
- });
- });
-
- it('renders diverged commits info', () => {
- expect(wrapper.find('.diverged-commits-count').text().trim()).toBe(
- 'The source branch is 12 commits behind the target branch',
- );
-
- expect(wrapper.find('.diverged-commits-count a').text().trim()).toBe('12 commits behind');
- expect(wrapper.find('.diverged-commits-count a').attributes('href')).toBe(
- wrapper.vm.mr.targetBranchPath,
- );
- });
- });
- });
-});
diff --git a/spec/helpers/issues_helper_spec.rb b/spec/helpers/issues_helper_spec.rb
index b55b4aaf76a..dd5e162b444 100644
--- a/spec/helpers/issues_helper_spec.rb
+++ b/spec/helpers/issues_helper_spec.rb
@@ -441,85 +441,38 @@ RSpec.describe IssuesHelper do
end
describe '#status_box_class' do
- context 'when updated_mr_header feature flag is enabled' do
- before do
- stub_feature_flags(updated_mr_header: true)
- end
-
- context 'when object is expired' do
- it 'returns orange background' do
- milestone = build(:milestone, due_date: Date.today.prev_month)
- expect(helper.status_box_class(milestone)).to eq('gl-bg-orange-500')
- end
- end
-
- context 'when object is merged' do
- it 'returns blue background' do
- merge_request = build(:merge_request, :merged)
- expect(helper.status_box_class(merge_request)).to eq('badge-info')
- end
- end
-
- context 'when object is closed' do
- it 'returns red background' do
- merge_request = build(:merge_request, :closed)
- expect(helper.status_box_class(merge_request)).to eq('badge-danger')
- end
- end
-
- context 'when object is upcoming' do
- it 'returns gray background' do
- milestone = build(:milestone, start_date: Date.today.next_month)
- expect(helper.status_box_class(milestone)).to eq('gl-bg-gray-500')
- end
- end
-
- context 'when object is opened' do
- it 'returns green background' do
- merge_request = build(:merge_request, :opened)
- expect(helper.status_box_class(merge_request)).to eq('badge-success')
- end
+ context 'when object is expired' do
+ it 'returns orange background' do
+ milestone = build(:milestone, due_date: Date.today.prev_month)
+ expect(helper.status_box_class(milestone)).to eq('gl-bg-orange-500')
end
end
- context 'when updated_mr_header feature flag is disabled' do
- before do
- stub_feature_flags(updated_mr_header: false)
- end
-
- context 'when object is expired' do
- it 'returns orange background' do
- milestone = build(:milestone, due_date: Date.today.prev_month)
- expect(helper.status_box_class(milestone)).to eq('gl-bg-orange-500')
- end
- end
-
- context 'when object is merged' do
- it 'returns blue background' do
- merge_request = build(:merge_request, :merged)
- expect(helper.status_box_class(merge_request)).to eq('gl-bg-blue-500')
- end
+ context 'when object is merged' do
+ it 'returns blue background' do
+ merge_request = build(:merge_request, :merged)
+ expect(helper.status_box_class(merge_request)).to eq('badge-info')
end
+ end
- context 'when object is closed' do
- it 'returns red background' do
- merge_request = build(:merge_request, :closed)
- expect(helper.status_box_class(merge_request)).to eq('gl-bg-red-500')
- end
+ context 'when object is closed' do
+ it 'returns red background' do
+ merge_request = build(:merge_request, :closed)
+ expect(helper.status_box_class(merge_request)).to eq('badge-danger')
end
+ end
- context 'when object is upcoming' do
- it 'returns gray background' do
- milestone = build(:milestone, start_date: Date.today.next_month)
- expect(helper.status_box_class(milestone)).to eq('gl-bg-gray-500')
- end
+ context 'when object is upcoming' do
+ it 'returns gray background' do
+ milestone = build(:milestone, start_date: Date.today.next_month)
+ expect(helper.status_box_class(milestone)).to eq('gl-bg-gray-500')
end
+ end
- context 'when object is opened' do
- it 'returns green background' do
- merge_request = build(:merge_request, :opened)
- expect(helper.status_box_class(merge_request)).to eq('gl-bg-green-500')
- end
+ context 'when object is opened' do
+ it 'returns green background' do
+ merge_request = build(:merge_request, :opened)
+ expect(helper.status_box_class(merge_request)).to eq('badge-success')
end
end
end
diff --git a/spec/lib/gitlab/ci/config/external/mapper_spec.rb b/spec/lib/gitlab/ci/config/external/mapper_spec.rb
index 2d2adf09a42..7e1b31fea6a 100644
--- a/spec/lib/gitlab/ci/config/external/mapper_spec.rb
+++ b/spec/lib/gitlab/ci/config/external/mapper_spec.rb
@@ -6,7 +6,7 @@ RSpec.describe Gitlab::Ci::Config::External::Mapper do
include StubRequests
let_it_be(:project) { create(:project, :repository) }
- let_it_be(:user) { create(:user) }
+ let_it_be(:user) { project.owner }
let(:local_file) { '/lib/gitlab/ci/templates/non-existent-file.yml' }
let(:remote_url) { 'https://gitlab.com/gitlab-org/gitlab-foss/blob/1234/.gitlab-ci-1.yml' }
@@ -34,6 +34,19 @@ RSpec.describe Gitlab::Ci::Config::External::Mapper do
describe '#process' do
subject(:process) { mapper.process }
+ shared_examples 'logging config file fetch' do |key, count|
+ it 'propagates the pipeline logger' do
+ process
+
+ fetch_content_log_count = mapper
+ .logger
+ .observations_hash
+ .dig(key, 'count')
+
+ expect(fetch_content_log_count).to eq(count)
+ end
+ end
+
context "when single 'include' keyword is defined" do
context 'when the string is a local file' do
let(:values) do
@@ -45,6 +58,8 @@ RSpec.describe Gitlab::Ci::Config::External::Mapper do
expect(subject).to contain_exactly(
an_instance_of(Gitlab::Ci::Config::External::File::Local))
end
+
+ it_behaves_like 'logging config file fetch', 'config_file_fetch_local_content_duration_s', 1
end
context 'when the key is a local file hash' do
@@ -68,6 +83,8 @@ RSpec.describe Gitlab::Ci::Config::External::Mapper do
expect(subject).to contain_exactly(
an_instance_of(Gitlab::Ci::Config::External::File::Remote))
end
+
+ it_behaves_like 'logging config file fetch', 'config_file_fetch_remote_content_duration_s', 1
end
context 'when the key is a remote file hash' do
@@ -92,6 +109,8 @@ RSpec.describe Gitlab::Ci::Config::External::Mapper do
expect(subject).to contain_exactly(
an_instance_of(Gitlab::Ci::Config::External::File::Template))
end
+
+ it_behaves_like 'logging config file fetch', 'config_file_fetch_template_content_duration_s', 1
end
context 'when the key is a hash of file and remote' do
@@ -118,6 +137,8 @@ RSpec.describe Gitlab::Ci::Config::External::Mapper do
expect(subject).to contain_exactly(
an_instance_of(Gitlab::Ci::Config::External::File::Project))
end
+
+ it_behaves_like 'logging config file fetch', 'config_file_fetch_project_content_duration_s', 1
end
context "when the key is project's files" do
@@ -131,6 +152,8 @@ RSpec.describe Gitlab::Ci::Config::External::Mapper do
an_instance_of(Gitlab::Ci::Config::External::File::Project),
an_instance_of(Gitlab::Ci::Config::External::File::Project))
end
+
+ it_behaves_like 'logging config file fetch', 'config_file_fetch_project_content_duration_s', 2
end
end
diff --git a/spec/lib/gitlab/usage/service_ping_report_spec.rb b/spec/lib/gitlab/usage/service_ping_report_spec.rb
index e7096988035..e007554df4a 100644
--- a/spec/lib/gitlab/usage/service_ping_report_spec.rb
+++ b/spec/lib/gitlab/usage/service_ping_report_spec.rb
@@ -5,7 +5,7 @@ require 'spec_helper'
RSpec.describe Gitlab::Usage::ServicePingReport, :use_clean_rails_memory_store_caching do
include UsageDataHelpers
- let(:usage_data) { { uuid: "1111", counts: { issue: 0 } } }
+ let(:usage_data) { { uuid: "1111", counts: { issue: 0 } }.deep_stringify_keys }
before do
allow_next_instance_of(Gitlab::Usage::ServicePing::PayloadKeysProcessor) do |instance|
@@ -20,7 +20,7 @@ RSpec.describe Gitlab::Usage::ServicePingReport, :use_clean_rails_memory_store_c
context 'all_metrics_values' do
it 'generates the service ping when there are no missing values' do
expect(Gitlab::UsageData).to receive(:data).and_return(usage_data)
- expect(described_class.for(output: :all_metrics_values)).to eq({ uuid: "1111", counts: { issue: 0 } })
+ expect(described_class.for(output: :all_metrics_values)).to eq({ uuid: "1111", counts: { issue: 0 } }.deep_stringify_keys)
end
it 'generates the service ping with the missing values' do
@@ -33,7 +33,24 @@ RSpec.describe Gitlab::Usage::ServicePingReport, :use_clean_rails_memory_store_c
end
expect(Gitlab::UsageData).to receive(:data).and_return(usage_data)
- expect(described_class.for(output: :all_metrics_values)).to eq({ uuid: "1111", counts: { issue: 0, boards: 1 } })
+ expect(described_class.for(output: :all_metrics_values)).to eq({ uuid: "1111", counts: { issue: 0, boards: 1 } }.deep_stringify_keys)
+ end
+
+ context 'with usage data payload with symbol keys and instrumented payload with string keys' do
+ let(:usage_data) { { uuid: "1111", counts: { issue: 0 } } }
+
+ it 'correctly merges string and symbol keys' do
+ expect_next_instance_of(Gitlab::Usage::ServicePing::PayloadKeysProcessor, usage_data) do |instance|
+ expect(instance).to receive(:missing_instrumented_metrics_key_paths).and_return(['counts.boards'])
+ end
+
+ expect_next_instance_of(Gitlab::Usage::ServicePing::InstrumentedPayload, ['counts.boards'], :with_value) do |instance|
+ expect(instance).to receive(:build).and_return({ 'counts' => { 'boards' => 1 } })
+ end
+
+ expect(Gitlab::UsageData).to receive(:data).and_return(usage_data)
+ expect(described_class.for(output: :all_metrics_values)).to eq({ uuid: "1111", counts: { issue: 0, boards: 1 } }.deep_stringify_keys)
+ end
end
end
@@ -54,9 +71,9 @@ RSpec.describe Gitlab::Usage::ServicePingReport, :use_clean_rails_memory_store_c
end
context 'when using cached' do
- context 'for cached: true' do
- let(:new_usage_data) { { uuid: "1112" } }
+ let(:new_usage_data) { { 'uuid' => '1112' } }
+ context 'for cached: true' do
it 'caches the values' do
allow(Gitlab::UsageData).to receive(:data).and_return(usage_data, new_usage_data)
@@ -78,8 +95,6 @@ RSpec.describe Gitlab::Usage::ServicePingReport, :use_clean_rails_memory_store_c
end
context 'when no caching' do
- let(:new_usage_data) { { uuid: "1112" } }
-
it 'returns fresh data' do
allow(Gitlab::UsageData).to receive(:data).and_return(usage_data, new_usage_data)
diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb
index 67d7e29627b..ac085d71761 100644
--- a/spec/models/user_spec.rb
+++ b/spec/models/user_spec.rb
@@ -3740,7 +3740,7 @@ RSpec.describe User do
end
context 'has owned groups' do
- let_it_be(:group) { create(:group) }
+ let(:group) { create(:group) }
before do
group.add_owner(user)
@@ -3749,11 +3749,23 @@ RSpec.describe User do
context 'not solo owner' do
let_it_be(:user2) { create(:user) }
- before do
- group.add_owner(user2)
+ context 'with another direct owner' do
+ before do
+ group.add_owner(user2)
+ end
+
+ it { is_expected.to be_empty }
end
- it { is_expected.to be_empty }
+ context 'with an inherited owner' do
+ let_it_be(:group) { create(:group, :nested) }
+
+ before do
+ group.parent.add_owner(user2)
+ end
+
+ it { is_expected.to be_empty }
+ end
end
context 'solo owner' do
diff --git a/spec/requests/api/personal_access_tokens_spec.rb b/spec/requests/api/personal_access_tokens_spec.rb
index 01f69f0aae2..403c646ee32 100644
--- a/spec/requests/api/personal_access_tokens_spec.rb
+++ b/spec/requests/api/personal_access_tokens_spec.rb
@@ -73,6 +73,61 @@ RSpec.describe API::PersonalAccessTokens do
end
end
+ describe 'GET /personal_access_tokens/:id' do
+ let_it_be(:user_token) { create(:personal_access_token, user: current_user) }
+ let_it_be(:user_token_path) { "/personal_access_tokens/#{user_token.id}" }
+ let_it_be(:invalid_path) { "/personal_access_tokens/#{non_existing_record_id}" }
+
+ context 'when current_user is an administrator', :enable_admin_mode do
+ let_it_be(:admin_user) { create(:admin) }
+ let_it_be(:admin_token) { create(:personal_access_token, user: admin_user) }
+ let_it_be(:admin_path) { "/personal_access_tokens/#{admin_token.id}" }
+
+ it 'returns admins own PAT by id' do
+ get api(admin_path, admin_user)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response['id']).to eq(admin_token.id)
+ end
+
+ it 'returns a different users PAT by id' do
+ get api(user_token_path, admin_user)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response['id']).to eq(user_token.id)
+ end
+
+ it 'fails to return PAT because no PAT exists with this id' do
+ get api(invalid_path, admin_user)
+
+ expect(response).to have_gitlab_http_status(:unauthorized)
+ end
+ end
+
+ context 'when current_user is not an administrator' do
+ let_it_be(:other_users_path) { "/personal_access_tokens/#{token1.id}" }
+
+ it 'returns users own PAT by id' do
+ get api(user_token_path, current_user)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response['id']).to eq(user_token.id)
+ end
+
+ it 'fails to return other users PAT by id' do
+ get api(other_users_path, current_user)
+
+ expect(response).to have_gitlab_http_status(:unauthorized)
+ end
+
+ it 'fails to return PAT because no PAT exists with this id' do
+ get api(invalid_path, current_user)
+
+ expect(response).to have_gitlab_http_status(:unauthorized)
+ end
+ end
+ end
+
describe 'DELETE /personal_access_tokens/self' do
let(:path) { '/personal_access_tokens/self' }
let(:token) { create(:personal_access_token, user: current_user) }
diff --git a/spec/requests/api/users_spec.rb b/spec/requests/api/users_spec.rb
index 040ac4f74a7..2c5a734a0e1 100644
--- a/spec/requests/api/users_spec.rb
+++ b/spec/requests/api/users_spec.rb
@@ -2098,7 +2098,7 @@ RSpec.describe API::Users do
describe "DELETE /users/:id" do
let_it_be(:issue) { create(:issue, author: user) }
- it "deletes user", :sidekiq_might_not_need_inline do
+ it "deletes user", :sidekiq_inline do
namespace_id = user.namespace.id
perform_enqueued_jobs { delete api("/users/#{user.id}", admin) }
@@ -2119,11 +2119,27 @@ RSpec.describe API::Users do
end
context "hard delete enabled" do
- it "delete user and group", :sidekiq_might_not_need_inline do
+ it "delete user and group", :sidekiq_inline do
perform_enqueued_jobs { delete api("/users/#{user.id}?hard_delete=true", admin) }
expect(response).to have_gitlab_http_status(:no_content)
expect(Group.exists?(group.id)).to be_falsy
end
+
+ context "with subgroup owning" do
+ let(:parent_group) { create(:group) }
+ let(:subgroup) { create(:group, parent: parent_group) }
+
+ before do
+ parent_group.add_owner(create(:user))
+ subgroup.add_owner(user)
+ end
+
+ it "delete only user", :sidekiq_inline do
+ perform_enqueued_jobs { delete api("/users/#{user.id}?hard_delete=true", admin) }
+ expect(response).to have_gitlab_http_status(:no_content)
+ expect(Group.exists?(subgroup.id)).to be_truthy
+ end
+ end
end
end
diff --git a/spec/services/users/destroy_service_spec.rb b/spec/services/users/destroy_service_spec.rb
index 45dbe83b496..90c4f70d749 100644
--- a/spec/services/users/destroy_service_spec.rb
+++ b/spec/services/users/destroy_service_spec.rb
@@ -215,6 +215,27 @@ RSpec.describe Users::DestroyService do
end
end
+ context 'deletions with inherited group owners' do
+ let(:group) { create(:group, :nested) }
+ let(:user) { create(:user) }
+ let(:inherited_owner) { create(:user) }
+
+ before do
+ group.parent.add_owner(inherited_owner)
+ group.add_owner(user)
+
+ service.execute(user, delete_solo_owned_groups: true)
+ end
+
+ it 'does not delete the group' do
+ expect(Group.exists?(id: group)).to be_truthy
+ end
+
+ it 'deletes the user' do
+ expect(User.exists?(id: user)).to be_falsey
+ end
+ end
+
context 'migrating associated records' do
let!(:issue) { create(:issue, author: user) }
diff --git a/spec/tooling/lib/tooling/find_codeowners_spec.rb b/spec/tooling/lib/tooling/find_codeowners_spec.rb
index b29c5f35ec9..10c2a076847 100644
--- a/spec/tooling/lib/tooling/find_codeowners_spec.rb
+++ b/spec/tooling/lib/tooling/find_codeowners_spec.rb
@@ -31,13 +31,37 @@ RSpec.describe Tooling::FindCodeowners do
end
end.to output(<<~CODEOWNERS).to_stdout
[Section name]
- /dir0/dir1 @group
+ /dir0/dir1/ @group
/file @group
CODEOWNERS
end
end
describe '#load_definitions' do
+ before do
+ allow(subject).to receive(:load_config).and_return(
+ {
+ '[Authentication and Authorization]': {
+ '@gitlab-org/manage/authentication-and-authorization': {
+ allow: {
+ keywords: %w[password auth token],
+ patterns:
+ %w[
+ /{,ee/}app/**/*%{keyword}*{,/**/*}
+ /{,ee/}config/**/*%{keyword}*{,/**/*}
+ /{,ee/}lib/**/*%{keyword}*{,/**/*}
+ ]
+ },
+ deny: {
+ keywords: %w[*author.* *author_* *authored*],
+ patterns: ['%{keyword}']
+ }
+ }
+ }
+ }
+ )
+ end
+
it 'expands the allow and deny list with keywords and patterns' do
subject.load_definitions.each do |section, group_defintions|
group_defintions.each do |group, definitions|
@@ -54,56 +78,20 @@ RSpec.describe Tooling::FindCodeowners do
expect(auth).to eq(
allow: %w[
- /{,ee/}app/**/*password*{/**/*,}
- /{,ee/}config/**/*password*{/**/*,}
- /{,ee/}lib/**/*password*{/**/*,}
- /{,ee/}app/**/*auth*{/**/*,}
- /{,ee/}config/**/*auth*{/**/*,}
- /{,ee/}lib/**/*auth*{/**/*,}
- /{,ee/}app/**/*token*{/**/*,}
- /{,ee/}config/**/*token*{/**/*,}
- /{,ee/}lib/**/*token*{/**/*,}
+ /{,ee/}app/**/*password*{,/**/*}
+ /{,ee/}config/**/*password*{,/**/*}
+ /{,ee/}lib/**/*password*{,/**/*}
+ /{,ee/}app/**/*auth*{,/**/*}
+ /{,ee/}config/**/*auth*{,/**/*}
+ /{,ee/}lib/**/*auth*{,/**/*}
+ /{,ee/}app/**/*token*{,/**/*}
+ /{,ee/}config/**/*token*{,/**/*}
+ /{,ee/}lib/**/*token*{,/**/*}
],
deny: %w[
- **/*author.*{/**/*,}
- **/*author_*{/**/*,}
- **/*authored*{/**/*,}
- **/*authoring*{/**/*,}
- **/*.png*{/**/*,}
- **/*.svg*{/**/*,}
- **/*deploy_token*{/**/*,}
- **/*runner{,s}_token*{/**/*,}
- **/*job_token*{/**/*,}
- **/*autocomplete_tokens*{/**/*,}
- **/*dast_site_token*{/**/*,}
- **/*reset_prometheus_token*{/**/*,}
- **/*reset_registration_token*{/**/*,}
- **/*runners_registration_token*{/**/*,}
- **/*terraform_registry_token*{/**/*,}
- **/*tokenizer*{/**/*,}
- **/*filtered_search*{/**/*,}
- **/*/alert_management/*{/**/*,}
- **/*/analytics/*{/**/*,}
- **/*/bitbucket/*{/**/*,}
- **/*/clusters/*{/**/*,}
- **/*/clusters_list/*{/**/*,}
- **/*/dast/*{/**/*,}
- **/*/dast_profiles/*{/**/*,}
- **/*/dast_site_tokens/*{/**/*,}
- **/*/dast_site_validation/*{/**/*,}
- **/*/dependency_proxy/*{/**/*,}
- **/*/error_tracking/*{/**/*,}
- **/*/google_api/*{/**/*,}
- **/*/google_cloud/*{/**/*,}
- **/*/jira_connect/*{/**/*,}
- **/*/kubernetes/*{/**/*,}
- **/*/protected_environments/*{/**/*,}
- **/*/config/feature_flags/development/jira_connect_*{/**/*,}
- **/*/config/metrics/*{/**/*,}
- **/*/app/controllers/groups/dependency_proxy_auth_controller.rb*{/**/*,}
- **/*/app/finders/ci/auth_job_finder.rb*{/**/*,}
- **/*/ee/config/metrics/*{/**/*,}
- **/*/lib/gitlab/conan_token.rb*{/**/*,}
+ *author.*
+ *author_*
+ *authored*
]
)
end
@@ -159,12 +147,31 @@ RSpec.describe Tooling::FindCodeowners do
expected_flags =
::File::FNM_DOTMATCH | ::File::FNM_PATHNAME | ::File::FNM_EXTGLOB
- expect(File).to receive(:fnmatch?).with(pattern, path, expected_flags)
+ expect(File).to receive(:fnmatch?)
+ .with("/**/#{pattern}", path, expected_flags)
subject.path_matches?(pattern, path)
end
end
+ describe '#normalize_pattern' do
+ it 'returns /**/* if the input is *' do
+ expect(subject.normalize_pattern('*')).to eq('/**/*')
+ end
+
+ it 'prepends /** if the input does not start with /' do
+ expect(subject.normalize_pattern('app')).to eq('/**/app')
+ end
+
+ it 'returns the pattern if the input starts with /' do
+ expect(subject.normalize_pattern('/app')).to eq('/app')
+ end
+
+ it 'appends **/* if the input ends with /' do
+ expect(subject.normalize_pattern('/app/')).to eq('/app/**/*')
+ end
+ end
+
describe '#consolidate_paths' do
before do
allow(subject).to receive(:find_dir_maxdepth_1).and_return(<<~LINES)
diff --git a/tooling/config/CODEOWNERS.yml b/tooling/config/CODEOWNERS.yml
index d867c8c22fc..4fa7338b32d 100644
--- a/tooling/config/CODEOWNERS.yml
+++ b/tooling/config/CODEOWNERS.yml
@@ -6,53 +6,52 @@
'@gitlab-org/manage/authentication-and-authorization':
allow:
keywords:
- - password
- - auth
- - token
+ - 'password'
+ - 'auth'
+ - 'token'
patterns:
- - '/{,ee/}app/**/*%{keyword}*{/**/*,}'
- - '/{,ee/}config/**/*%{keyword}*{/**/*,}'
- - '/{,ee/}lib/**/*%{keyword}*{/**/*,}'
+ - '/{,ee/}app/**/*%{keyword}*{,/**/*}'
+ - '/{,ee/}config/**/*%{keyword}*{,/**/*}'
+ - '/{,ee/}lib/**/*%{keyword}*{,/**/*}'
deny:
keywords:
- - author.
- - author_
- - authored
- - authoring
- - .png
- - .svg
- - deploy_token
- - runner{,s}_token
- - job_token
- - autocomplete_tokens
- - dast_site_token
- - reset_prometheus_token
- - reset_registration_token
- - runners_registration_token
- - terraform_registry_token
- - tokenizer
- - filtered_search
- - /alert_management/
- - /analytics/
- - /bitbucket/
- - /clusters/
- - /clusters_list/
- - /dast/
- - /dast_profiles/
- - /dast_site_tokens/
- - /dast_site_validation/
- - /dependency_proxy/
- - /error_tracking/
- - /google_api/
- - /google_cloud/
- - /jira_connect/
- - /kubernetes/
- - /protected_environments/
- - /config/feature_flags/development/jira_connect_
- - /config/metrics/
- - /app/controllers/groups/dependency_proxy_auth_controller.rb
- - /app/finders/ci/auth_job_finder.rb
- - /ee/config/metrics/
- - /lib/gitlab/conan_token.rb
+ - '*author.*'
+ - '*author_*'
+ - '*authored*'
+ - '*authoring*'
+ - '*.png'
+ - '*.svg'
+ - '*deploy_token{,s}{*,/**/*}'
+ - '*runner{,s}_token*'
+ - '*job_token{,_scope}{*,/**/*}'
+ - '*autocomplete_tokens*'
+ - 'dast_site_token*'
+ - 'reset_prometheus_token*'
+ - 'reset_registration_token*'
+ - 'runners_registration_token{*,/**/*}'
+ - 'terraform_registry_token*'
+ - 'filtered_search{_bar,}/'
+ - 'alert_management/'
+ - 'analytics/'
+ - 'bitbucket/'
+ - 'clusters/'
+ - 'clusters_list/'
+ - 'dast/'
+ - 'dast_profiles/'
+ - 'dast_site_tokens/'
+ - 'dast_site_validation/'
+ - 'dependency_proxy/'
+ - 'error_tracking/'
+ - 'google_api/'
+ - 'google_cloud/'
+ - 'jira_connect/'
+ - 'kubernetes/'
+ - 'protected_environments/'
+ - '/config/feature_flags/development/jira_connect_*'
+ - '/config/metrics/'
+ - '/app/controllers/groups/dependency_proxy_auth_controller.rb'
+ - '/app/finders/ci/auth_job_finder.rb'
+ - '/ee/config/metrics/'
+ - '/lib/gitlab/conan_token.rb'
patterns:
- - '**/*%{keyword}*{/**/*,}'
+ - '%{keyword}'
diff --git a/tooling/lib/tooling/find_codeowners.rb b/tooling/lib/tooling/find_codeowners.rb
index 35d8a9d7461..3b50b33d85c 100644
--- a/tooling/lib/tooling/find_codeowners.rb
+++ b/tooling/lib/tooling/find_codeowners.rb
@@ -31,8 +31,14 @@ module Tooling
consolidated_again = consolidate_paths(consolidated)
end
- consolidated.each do |file|
- puts "/#{file.chomp} #{group}"
+ consolidated.each do |line|
+ path = line.chomp
+
+ if File.directory?(path)
+ puts "/#{path}/ #{group}"
+ else
+ puts "/#{path} #{group}"
+ end
end
end
end
@@ -76,7 +82,27 @@ module Tooling
flags |= ::File::FNM_EXTGLOB
# END extension
- ::File.fnmatch?(pattern, path, flags)
+ ::File.fnmatch?(normalize_pattern(pattern), path, flags)
+ end
+
+ # Copied from ee/lib/gitlab/code_owners/file.rb
+ def normalize_pattern(pattern)
+ # Remove `\` when escaping `\#`
+ pattern = pattern.sub(/\A\\#/, '#')
+ # Replace all whitespace preceded by a \ with a regular whitespace
+ pattern = pattern.gsub(/\\\s+/, ' ')
+
+ return '/**/*' if pattern == '*'
+
+ unless pattern.start_with?('/')
+ pattern = "/**/#{pattern}"
+ end
+
+ if pattern.end_with?('/')
+ pattern = "#{pattern}**/*"
+ end
+
+ pattern
end
def consolidate_paths(matched_files)