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:
-rw-r--r--.gitlab-ci.yml6
-rw-r--r--.gitlab/ci/cng/main.gitlab-ci.yml2
-rw-r--r--.gitlab/ci/qa.gitlab-ci.yml5
-rw-r--r--app/assets/javascripts/branches/components/graph_bar.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/source_viewer/queries/blame_data.query.graphql10
-rw-r--r--app/assets/javascripts/vue_shared/components/source_viewer/source_viewer_new.vue1
-rw-r--r--app/models/integrations/mattermost_slash_commands.rb2
-rw-r--r--app/models/member.rb12
-rw-r--r--app/models/members/group_member.rb6
-rw-r--r--app/models/members/project_member.rb18
-rw-r--r--app/services/event_create_service.rb6
-rw-r--r--app/services/notification_service.rb25
-rw-r--r--doc/api/container_registry.md10
-rw-r--r--doc/api/graphql/reference/index.md20
-rw-r--r--doc/ci/runners/saas/macos_saas_runner.md5
-rw-r--r--doc/development/contributing/design.md4
-rw-r--r--doc/development/database/avoiding_downtime_in_migrations.md28
-rw-r--r--doc/development/database/efficient_in_operator_queries.md24
-rw-r--r--doc/development/database/iterating_tables_in_batches.md12
-rw-r--r--doc/development/database/loose_foreign_keys.md30
-rw-r--r--doc/development/database/maintenance_operations.md2
-rw-r--r--doc/development/database/rename_database_tables.md14
-rw-r--r--doc/development/database/strings_and_the_text_data_type.md4
-rw-r--r--doc/development/database/table_partitioning.md10
-rw-r--r--doc/development/fe_guide/content_editor.md2
-rw-r--r--doc/development/fe_guide/customizable_dashboards.md2
-rw-r--r--doc/development/fe_guide/graphql.md14
-rw-r--r--doc/development/fe_guide/haml.md4
-rw-r--r--doc/development/fe_guide/storybook.md2
-rw-r--r--doc/development/fe_guide/style/vue.md24
-rw-r--r--doc/development/fe_guide/vue.md6
-rw-r--r--doc/development/packages/cleanup_policies.md21
-rw-r--r--doc/development/testing_guide/testing_levels.md2
-rw-r--r--doc/index.md12
-rw-r--r--doc/topics/autodevops/customize.md4
-rw-r--r--doc/user/application_security/continuous_vulnerability_scanning/index.md2
-rw-r--r--doc/user/clusters/management_project.md4
-rw-r--r--doc/user/infrastructure/clusters/connect/new_gke_cluster.md10
-rw-r--r--doc/user/infrastructure/iac/index.md8
-rw-r--r--doc/user/packages/conan_repository/index.md6
-rw-r--r--doc/user/packages/container_registry/reduce_container_registry_storage.md22
-rw-r--r--doc/user/packages/maven_repository/index.md12
-rw-r--r--doc/user/project/clusters/add_existing_cluster.md8
-rw-r--r--doc/user/project/clusters/add_remove_clusters.md2
-rw-r--r--doc/user/project/repository/code_suggestions/index.md4
-rw-r--r--doc/user/project/repository/code_suggestions/self_managed.md4
-rw-r--r--doc/user/project/repository/reducing_the_repo_size_using_git.md2
-rw-r--r--gems/gitlab-utils/lib/gitlab/utils.rb14
-rw-r--r--gems/gitlab-utils/spec/gitlab/utils_spec.rb20
-rw-r--r--lib/api/helpers/integrations_helpers.rb9
-rw-r--r--lib/gitlab/error_tracking.rb8
-rw-r--r--locale/gitlab.pot3
-rw-r--r--package.json4
-rw-r--r--spec/frontend/vue_shared/components/source_viewer/source_viewer_new_spec.js18
-rw-r--r--spec/lib/gitlab/error_tracking_spec.rb32
-rw-r--r--spec/lib/gitlab/http_spec.rb15
-rw-r--r--spec/models/member_spec.rb80
-rw-r--r--spec/models/members/group_member_spec.rb14
-rw-r--r--spec/services/event_create_service_spec.rb34
-rw-r--r--spec/services/notification_service_spec.rb99
-rw-r--r--spec/support/helpers/features/invite_members_modal_helpers.rb1
-rw-r--r--spec/support/helpers/stub_configuration.rb4
-rw-r--r--spec/support/shared_examples/models/members_notifications_shared_example.rb12
-rw-r--r--yarn.lock16
64 files changed, 480 insertions, 338 deletions
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 490d3b3f487..6acf982fd55 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -29,15 +29,15 @@ default:
.old-ruby-variables: &old-ruby-variables
RUBY_VERSION: "3.0"
- CACHE_EDITION: "GITLAB_RUBY3_0"
+ OMNIBUS_GITLAB_CACHE_EDITION: "GITLAB_RUBY3_0"
.default-ruby-variables: &default-ruby-variables
RUBY_VERSION: "3.1"
- CACHE_EDITION: "GITLAB_RUBY3_1"
+ OMNIBUS_GITLAB_CACHE_EDITION: "GITLAB_RUBY3_1"
.next-ruby-variables: &next-ruby-variables
RUBY_VERSION: "3.2"
- CACHE_EDITION: "GITLAB_RUBY3_2"
+ OMNIBUS_GITLAB_CACHE_EDITION: "GITLAB_RUBY3_2"
.default-branch-pipeline-failure-variables: &default-branch-pipeline-failure-variables
CREATE_RAILS_TEST_FAILURE_ISSUES: "true"
diff --git a/.gitlab/ci/cng/main.gitlab-ci.yml b/.gitlab/ci/cng/main.gitlab-ci.yml
index 1ecbbbd47ad..d27a4ef4b08 100644
--- a/.gitlab/ci/cng/main.gitlab-ci.yml
+++ b/.gitlab/ci/cng/main.gitlab-ci.yml
@@ -54,8 +54,6 @@ include:
GITLAB_WORKHORSE_VERSION: "${GITLAB_WORKHORSE_VERSION}"
GITALY_SERVER_VERSION: "${GITALY_SERVER_VERSION}"
RUBY_VERSION: "${FULL_RUBY_VERSION}"
- NEXT_RUBY_CACHE_KEY: "${RUBY_VERSION}"
- NEXT_RUBY_VERSION: "${FULL_RUBY_VERSION}"
trigger:
project: ${CI_PROJECT_NAMESPACE}/build/CNG-mirror
branch: $TRIGGER_BRANCH
diff --git a/.gitlab/ci/qa.gitlab-ci.yml b/.gitlab/ci/qa.gitlab-ci.yml
index b7716fc280e..a77a8bfd252 100644
--- a/.gitlab/ci/qa.gitlab-ci.yml
+++ b/.gitlab/ci/qa.gitlab-ci.yml
@@ -90,8 +90,9 @@ trigger-omnibus:
TOP_UPSTREAM_SOURCE_PROJECT: $CI_PROJECT_PATH
SECURITY_SOURCES: $SECURITY_SOURCES
CACHE_UPDATE: $OMNIBUS_GITLAB_CACHE_UPDATE
- CACHE_EDITION: $CACHE_EDITION
- NEXT_RUBY_VERSION: $FULL_RUBY_VERSION
+ CACHE_EDITION: $OMNIBUS_GITLAB_CACHE_EDITION
+ USE_SPECIFIED_RUBY_VERSION: "true"
+ RUBY_VERSION: $FULL_RUBY_VERSION
BUILD_ON_ALL_OS: $OMNIBUS_GITLAB_BUILD_ON_ALL_OS
SKIP_QA_TEST: "true"
ee: $EE
diff --git a/app/assets/javascripts/branches/components/graph_bar.vue b/app/assets/javascripts/branches/components/graph_bar.vue
index 21cbcac820a..885db7651a1 100644
--- a/app/assets/javascripts/branches/components/graph_bar.vue
+++ b/app/assets/javascripts/branches/components/graph_bar.vue
@@ -62,7 +62,7 @@ export default {
:class="[roundedClass, positionSideClass]"
class="position-absolute bar js-graph-bar"
></div>
- <span :class="textAlignmentClass" class="d-block pt-1 pr-1 count js-graph-count">
+ <span :class="textAlignmentClass" class="gl-display-block gl-pt-1 gl-px-1 count js-graph-count">
{{ label }}
</span>
</div>
diff --git a/app/assets/javascripts/vue_shared/components/source_viewer/queries/blame_data.query.graphql b/app/assets/javascripts/vue_shared/components/source_viewer/queries/blame_data.query.graphql
index c497224cde3..0067a0ca0d9 100644
--- a/app/assets/javascripts/vue_shared/components/source_viewer/queries/blame_data.query.graphql
+++ b/app/assets/javascripts/vue_shared/components/source_viewer/queries/blame_data.query.graphql
@@ -1,10 +1,16 @@
#import "~/graphql_shared/fragments/author.fragment.graphql"
-query getBlameData($fullPath: ID!, $filePath: String!, $fromLine: Int, $toLine: Int) {
+query getBlameData(
+ $fullPath: ID!
+ $filePath: String!
+ $fromLine: Int
+ $toLine: Int
+ $ref: String!
+) {
project(fullPath: $fullPath) {
id
repository {
- blobs(paths: [$filePath]) {
+ blobs(ref: $ref, paths: [$filePath]) {
nodes {
id
blame(fromLine: $fromLine, toLine: $toLine) {
diff --git a/app/assets/javascripts/vue_shared/components/source_viewer/source_viewer_new.vue b/app/assets/javascripts/vue_shared/components/source_viewer/source_viewer_new.vue
index bc46f11ab2d..e62f38d9ca3 100644
--- a/app/assets/javascripts/vue_shared/components/source_viewer/source_viewer_new.vue
+++ b/app/assets/javascripts/vue_shared/components/source_viewer/source_viewer_new.vue
@@ -118,6 +118,7 @@ export default {
const { data } = await this.$apollo.query({
query: blameDataQuery,
variables: {
+ ref: this.currentRef,
fullPath: this.projectPath,
filePath: this.blob.path,
fromLine: chunk.startingFrom + 1,
diff --git a/app/models/integrations/mattermost_slash_commands.rb b/app/models/integrations/mattermost_slash_commands.rb
index 9554dec4168..3a1f7329699 100644
--- a/app/models/integrations/mattermost_slash_commands.rb
+++ b/app/models/integrations/mattermost_slash_commands.rb
@@ -6,8 +6,10 @@ module Integrations
field :token,
type: :password,
+ description: -> { _('The Mattermost token.') },
non_empty_password_title: -> { s_('ProjectService|Enter new token') },
non_empty_password_help: -> { s_('ProjectService|Leave blank to use your current token.') },
+ required: true,
placeholder: ''
def testable?
diff --git a/app/models/member.rb b/app/models/member.rb
index 2db2df91cbe..f64f6c67cc0 100644
--- a/app/models/member.rb
+++ b/app/models/member.rb
@@ -522,6 +522,14 @@ class Member < ApplicationRecord
end
def post_create_hook
+ # The creator of a personal project gets added as a `ProjectMember`
+ # with `OWNER` access during creation of a personal project,
+ # but we do not want to trigger notifications to the same person who created the personal project.
+ unless source.is_a?(Project) && source.personal_namespace_holder?(user)
+ event_service.join_source(source, user)
+ run_after_commit_or_now { notification_service.new_member(self) }
+ end
+
system_hook_service.execute_hooks_for(self, :create)
end
@@ -631,6 +639,10 @@ class Member < ApplicationRecord
error = StandardError.new("Invitation token is present but invite was already accepted!")
Gitlab::ErrorTracking.track_exception(error, attributes.slice(%w["invite_accepted_at created_at source_type source_id user_id id"]))
end
+
+ def event_service
+ EventCreateService.new # rubocop:todo CodeReuse/ServiceClass -- Legacy, convert to value object eventually
+ end
end
Member.prepend_mod_with('Member')
diff --git a/app/models/members/group_member.rb b/app/models/members/group_member.rb
index 3f1fcfe8339..ed2317b64d0 100644
--- a/app/models/members/group_member.rb
+++ b/app/models/members/group_member.rb
@@ -88,12 +88,6 @@ class GroupMember < Member
super
end
- def post_create_hook
- run_after_commit_or_now { notification_service.new_group_member(self) }
-
- super
- end
-
def after_accept_invite
run_after_commit_or_now do
notification_service.accept_group_invite(self)
diff --git a/app/models/members/project_member.rb b/app/models/members/project_member.rb
index 3540e7a043a..15a5b1b1fce 100644
--- a/app/models/members/project_member.rb
+++ b/app/models/members/project_member.rb
@@ -116,18 +116,6 @@ class ProjectMember < Member
self.member_namespace_id = project&.project_namespace_id
end
- def post_create_hook
- # The creator of a personal project gets added as a `ProjectMember`
- # with `OWNER` access during creation of a personal project,
- # but we do not want to trigger notifications to the same person who created the personal project.
- unless project.personal_namespace_holder?(user)
- event_service.join_project(self.project, self.user)
- run_after_commit_or_now { notification_service.new_project_member(self) }
- end
-
- super
- end
-
def post_destroy_hook
if expired?
event_service.expired_leave_project(self.project, self.user)
@@ -145,12 +133,6 @@ class ProjectMember < Member
super
end
-
- # rubocop: disable CodeReuse/ServiceClass
- def event_service
- EventCreateService.new
- end
- # rubocop: enable CodeReuse/ServiceClass
end
ProjectMember.prepend_mod_with('ProjectMember')
diff --git a/app/services/event_create_service.rb b/app/services/event_create_service.rb
index b755f512772..1a4e691a059 100644
--- a/app/services/event_create_service.rb
+++ b/app/services/event_create_service.rb
@@ -100,8 +100,10 @@ class EventCreateService
end
end
- def join_project(project, current_user)
- create_event(project, current_user, :joined)
+ def join_source(source, current_user)
+ return unless source.is_a?(Project)
+
+ create_event(source, current_user, :joined)
end
def leave_project(project, current_user)
diff --git a/app/services/notification_service.rb b/app/services/notification_service.rb
index ff712d78c8b..14fddba1cc0 100644
--- a/app/services/notification_service.rb
+++ b/app/services/notification_service.rb
@@ -526,6 +526,19 @@ class NotificationService
mailer.member_invited_email(member.real_source_type, member.id, token).deliver_later
end
+ def new_member(member)
+ notifiable_options = case member.source
+ when Group
+ {}
+ when Project
+ { skip_read_ability: true }
+ end
+
+ return true unless member.notifiable?(:mention, notifiable_options)
+
+ mailer.member_access_granted_email(member.real_source_type, member.id).deliver_later
+ end
+
def accept_project_invite(project_member)
return true unless project_member.notifiable?(:subscription)
@@ -545,12 +558,6 @@ class NotificationService
mailer.member_expiration_date_updated_email(member.real_source_type, member.id).deliver_later
end
- def new_project_member(project_member)
- return true unless project_member.notifiable?(:mention, skip_read_ability: true)
-
- mailer.member_access_granted_email(project_member.real_source_type, project_member.id).deliver_later
- end
-
def member_about_to_expire(member)
return true unless member.notifiable?(:mention)
@@ -565,12 +572,6 @@ class NotificationService
mailer.member_invite_accepted_email(group_member.real_source_type, group_member.id).deliver_later
end
- def new_group_member(group_member)
- return true unless group_member.notifiable?(:mention)
-
- mailer.member_access_granted_email(group_member.real_source_type, group_member.id).deliver_later
- end
-
def project_was_moved(project, old_path_with_namespace)
recipients = project_moved_recipients(project)
recipients = notifiable_users(recipients, :custom, custom_action: :moved_project, project: project)
diff --git a/doc/api/container_registry.md b/doc/api/container_registry.md
index eef90fc512e..9ad52fa3c3a 100644
--- a/doc/api/container_registry.md
+++ b/doc/api/container_registry.md
@@ -33,13 +33,11 @@ PUT /projects/:id/
Descriptions of the possible values for `container_registry_access_level`:
- **enabled** (Default): The container registry is visible to everyone with access to the project.
-If the project is public, the container registry is also public. If the project is internal or
-private, the container registry is also internal or private.
-
+ If the project is public, the container registry is also public. If the project is internal or
+ private, the container registry is also internal or private.
- **private**: The container registry is visible only to project members with Reporter role or
-higher. This behavior is similar to that of a private project with container registry visibility set
-to **enabled**.
-
+ higher. This behavior is similar to that of a private project with container registry visibility set
+ to **enabled**.
- **disabled**: The container registry is disabled.
See the [container registry visibility permissions](../user/packages/container_registry/index.md#container-registry-visibility-permissions)
diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md
index aaa1a7c559b..6669ed071e0 100644
--- a/doc/api/graphql/reference/index.md
+++ b/doc/api/graphql/reference/index.md
@@ -5383,22 +5383,12 @@ Input type: `MemberRoleCreateInput`
| Name | Type | Description |
| ---- | ---- | ----------- |
-| <a id="mutationmemberrolecreateadmingroupmember"></a>`adminGroupMember` | [`Boolean`](#boolean) | Permission to admin group members. |
-| <a id="mutationmemberrolecreateadminmergerequest"></a>`adminMergeRequest` | [`Boolean`](#boolean) | Permission to admin merge requests. |
-| <a id="mutationmemberrolecreateadminvulnerability"></a>`adminVulnerability` | [`Boolean`](#boolean) | Permission to admin vulnerability. |
-| <a id="mutationmemberrolecreatearchiveproject"></a>`archiveProject` | [`Boolean`](#boolean) | Permission to archive projects. |
| <a id="mutationmemberrolecreatebaseaccesslevel"></a>`baseAccessLevel` | [`MemberAccessLevel!`](#memberaccesslevel) | Base access level for the custom role. |
| <a id="mutationmemberrolecreateclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
| <a id="mutationmemberrolecreatedescription"></a>`description` | [`String`](#string) | Description of the member role. |
| <a id="mutationmemberrolecreategrouppath"></a>`groupPath` | [`ID`](#id) | Group the member role to mutate is in. Required for SaaS. |
-| <a id="mutationmemberrolecreatemanagegroupaccesstokens"></a>`manageGroupAccessTokens` | [`Boolean`](#boolean) | Permission to admin group access tokens. |
-| <a id="mutationmemberrolecreatemanageprojectaccesstokens"></a>`manageProjectAccessTokens` | [`Boolean`](#boolean) | Permission to admin project access tokens. |
| <a id="mutationmemberrolecreatename"></a>`name` | [`String`](#string) | Name of the member role. |
| <a id="mutationmemberrolecreatepermissions"></a>`permissions` | [`[MemberRolePermission!]`](#memberrolepermission) | List of all customizable permissions. |
-| <a id="mutationmemberrolecreatereadcode"></a>`readCode` | [`Boolean`](#boolean) | Permission to read code. |
-| <a id="mutationmemberrolecreatereaddependency"></a>`readDependency` | [`Boolean`](#boolean) | Permission to read dependency. |
-| <a id="mutationmemberrolecreatereadvulnerability"></a>`readVulnerability` | [`Boolean`](#boolean) | Permission to read vulnerability. |
-| <a id="mutationmemberrolecreateremoveproject"></a>`removeProject` | [`Boolean`](#boolean) | Permission to delete projects. |
#### Fields
@@ -21485,22 +21475,12 @@ Represents a member role.
| Name | Type | Description |
| ---- | ---- | ----------- |
-| <a id="memberroleadmingroupmember"></a>`adminGroupMember` **{warning-solid}** | [`Boolean`](#boolean) | **Introduced** in 16.5. This feature is an Experiment. It can be changed or removed at any time. Permission to admin group members. |
-| <a id="memberroleadminmergerequest"></a>`adminMergeRequest` **{warning-solid}** | [`Boolean`](#boolean) | **Introduced** in 16.5. This feature is an Experiment. It can be changed or removed at any time. Permission to admin merge requests. |
-| <a id="memberroleadminvulnerability"></a>`adminVulnerability` **{warning-solid}** | [`Boolean`](#boolean) | **Introduced** in 16.5. This feature is an Experiment. It can be changed or removed at any time. Permission to admin vulnerability. |
-| <a id="memberrolearchiveproject"></a>`archiveProject` **{warning-solid}** | [`Boolean`](#boolean) | **Introduced** in 16.6. This feature is an Experiment. It can be changed or removed at any time. Permission to archive projects. |
| <a id="memberrolebaseaccesslevel"></a>`baseAccessLevel` **{warning-solid}** | [`AccessLevel!`](#accesslevel) | **Introduced** in 16.5. This feature is an Experiment. It can be changed or removed at any time. Base access level for the custom role. |
| <a id="memberroledescription"></a>`description` | [`String`](#string) | Description of the member role. |
| <a id="memberroleenabledpermissions"></a>`enabledPermissions` **{warning-solid}** | [`[MemberRolePermission!]`](#memberrolepermission) | **Introduced** in 16.5. This feature is an Experiment. It can be changed or removed at any time. Array of all permissions enabled for the custom role. |
| <a id="memberroleid"></a>`id` | [`MemberRoleID!`](#memberroleid) | ID of the member role. |
-| <a id="memberrolemanagegroupaccesstokens"></a>`manageGroupAccessTokens` **{warning-solid}** | [`Boolean`](#boolean) | **Introduced** in 16.8. This feature is an Experiment. It can be changed or removed at any time. Permission to admin group access tokens. |
-| <a id="memberrolemanageprojectaccesstokens"></a>`manageProjectAccessTokens` **{warning-solid}** | [`Boolean`](#boolean) | **Introduced** in 16.5. This feature is an Experiment. It can be changed or removed at any time. Permission to admin project access tokens. |
| <a id="memberrolememberscount"></a>`membersCount` **{warning-solid}** | [`Int!`](#int) | **Introduced** in 16.7. This feature is an Experiment. It can be changed or removed at any time. Total number of members with the custom role. |
| <a id="memberrolename"></a>`name` | [`String!`](#string) | Name of the member role. |
-| <a id="memberrolereadcode"></a>`readCode` **{warning-solid}** | [`Boolean`](#boolean) | **Introduced** in 16.5. This feature is an Experiment. It can be changed or removed at any time. Permission to read code. |
-| <a id="memberrolereaddependency"></a>`readDependency` **{warning-solid}** | [`Boolean`](#boolean) | **Introduced** in 16.5. This feature is an Experiment. It can be changed or removed at any time. Permission to read dependency. |
-| <a id="memberrolereadvulnerability"></a>`readVulnerability` **{warning-solid}** | [`Boolean`](#boolean) | **Introduced** in 16.5. This feature is an Experiment. It can be changed or removed at any time. Permission to read vulnerability. |
-| <a id="memberroleremoveproject"></a>`removeProject` **{warning-solid}** | [`Boolean`](#boolean) | **Introduced** in 16.8. This feature is an Experiment. It can be changed or removed at any time. Permission to delete projects. |
### `MergeAccessLevel`
diff --git a/doc/ci/runners/saas/macos_saas_runner.md b/doc/ci/runners/saas/macos_saas_runner.md
index 03c23680c1c..0251c523864 100644
--- a/doc/ci/runners/saas/macos_saas_runner.md
+++ b/doc/ci/runners/saas/macos_saas_runner.md
@@ -21,8 +21,7 @@ You can follow our work towards this goal in the
## Machine types available for macOS
-GitLab SaaS provides macOS build machines on Apple silicon (M1) chips.
-Intel x86-64 runners were deprecated in favor of Apple silicon. To build for an x86-64 target, use Rosetta 2 to emulate an Intel x86-64 build environment.
+GitLab SaaS provides macOS build machines on Apple silicon (M1) chips. To build for an x86-64 target, you can use Rosetta 2 to emulate an Intel x86-64 build environment.
| Runner Tag | vCPUS | Memory | Storage |
| ---------------------- | ----- | ------ | ------- |
@@ -40,7 +39,7 @@ in your `.gitlab-ci.yml` file. Each image runs a specific version of macOS and X
|----------------------------|--------|--------------|
| `macos-12-xcode-14` | `GA` | |
| `macos-13-xcode-14` | `GA` | [Preinstalled Software](https://gitlab.com/gitlab-org/ci-cd/shared-runners/images/job-images/-/blob/main/toolchain/macos-13.yml) |
-| `macos-14-xcode-15` | `Beta` | [Preinstalled Software](https://gitlab.com/gitlab-org/ci-cd/shared-runners/images/job-images/-/blob/main/toolchain/macos-14.yml) |
+| `macos-14-xcode-15` | `GA` | [Preinstalled Software](https://gitlab.com/gitlab-org/ci-cd/shared-runners/images/job-images/-/blob/main/toolchain/macos-14.yml) |
If no image is specified, the macOS runner uses `macos-13-xcode-14`.
diff --git a/doc/development/contributing/design.md b/doc/development/contributing/design.md
index 0e922550856..a0888006937 100644
--- a/doc/development/contributing/design.md
+++ b/doc/development/contributing/design.md
@@ -41,10 +41,10 @@ Check these aspects both when _designing_ and _reviewing_ UI changes.
### Writing
-- Follow [Pajamas](https://design.gitlab.com/content/punctuation/) as the primary
+- Follow [Pajamas](https://design.gitlab.com/content/ui-text/) as the primary
guidelines for UI text and [documentation style guide](../documentation/styleguide/index.md)
as the secondary.
-- Use clear and consistent [terminology](https://design.gitlab.com/content/terminology/).
+- Use clear and consistent terminology.
- Check grammar and spelling.
- Consider help content and follow its [guidelines](https://design.gitlab.com/usability/contextual-help).
- Request review from the [appropriate Technical Writer](https://handbook.gitlab.com/handbook/product/ux/technical-writing/#assignments),
diff --git a/doc/development/database/avoiding_downtime_in_migrations.md b/doc/development/database/avoiding_downtime_in_migrations.md
index bf75b7c2ab2..57c71cbaec6 100644
--- a/doc/development/database/avoiding_downtime_in_migrations.md
+++ b/doc/development/database/avoiding_downtime_in_migrations.md
@@ -588,27 +588,27 @@ swap the columns. Swapping is done with post-deployment migration. The exact pro
table being converted, but in general it's done in the following steps:
1. Using the provided `ensure_batched_background_migration_is_finished` helper, make sure the batched
-migration has finished ([see an example](https://gitlab.com/gitlab-org/gitlab/-/blob/41fbe34a4725a4e357a83fda66afb382828767b2/db/post_migrate/20210707210916_finalize_ci_stages_bigint_conversion.rb#L13-18)).
-If the migration has not completed, the subsequent steps fail anyway. By checking in advance we
-aim to have more helpful error message.
+ migration has finished ([see an example](https://gitlab.com/gitlab-org/gitlab/-/blob/41fbe34a4725a4e357a83fda66afb382828767b2/db/post_migrate/20210707210916_finalize_ci_stages_bigint_conversion.rb#L13-18)).
+ If the migration has not completed, the subsequent steps fail anyway. By checking in advance we
+ aim to have more helpful error message.
1. Use the `add_bigint_column_indexes` helper method from `Gitlab::Database::MigrationHelpers::ConvertToBigint` module
to create indexes with the `bigint` columns that match the existing indexes using the `integer` column.
- The helper method is expected to create all required `bigint` indexes, but it's advised to recheck to make sure
we are not missing any of the existing indexes. More information about the helper can be
found in merge request [135781](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/135781).
1. Create foreign keys (FK) using the `bigint` columns that match the existing FK using the
-`integer` column. Do this both for FK referencing other tables, and FK that reference the table
-that is being migrated ([see an example](https://gitlab.com/gitlab-org/gitlab/-/blob/41fbe34a4725a4e357a83fda66afb382828767b2/db/post_migrate/20210707210916_finalize_ci_stages_bigint_conversion.rb#L36-43)).
+ `integer` column. Do this both for FK referencing other tables, and FK that reference the table
+ that is being migrated ([see an example](https://gitlab.com/gitlab-org/gitlab/-/blob/41fbe34a4725a4e357a83fda66afb382828767b2/db/post_migrate/20210707210916_finalize_ci_stages_bigint_conversion.rb#L36-43)).
1. Inside a transaction, swap the columns:
- 1. Lock the tables involved. To reduce the chance of hitting a deadlock, we recommended to do this in parent to child order ([see an example](https://gitlab.com/gitlab-org/gitlab/-/blob/41fbe34a4725a4e357a83fda66afb382828767b2/db/post_migrate/20210707210916_finalize_ci_stages_bigint_conversion.rb#L47)).
- 1. Rename the columns to swap names ([see an example](https://gitlab.com/gitlab-org/gitlab/-/blob/41fbe34a4725a4e357a83fda66afb382828767b2/db/post_migrate/20210707210916_finalize_ci_stages_bigint_conversion.rb#L49-54))
- 1. Reset the trigger function ([see an example](https://gitlab.com/gitlab-org/gitlab/-/blob/41fbe34a4725a4e357a83fda66afb382828767b2/db/post_migrate/20210707210916_finalize_ci_stages_bigint_conversion.rb#L56-57)).
- 1. Swap the defaults ([see an example](https://gitlab.com/gitlab-org/gitlab/-/blob/41fbe34a4725a4e357a83fda66afb382828767b2/db/post_migrate/20210707210916_finalize_ci_stages_bigint_conversion.rb#L59-62)).
- 1. Swap the PK constraint (if any) ([see an example](https://gitlab.com/gitlab-org/gitlab/-/blob/41fbe34a4725a4e357a83fda66afb382828767b2/db/post_migrate/20210707210916_finalize_ci_stages_bigint_conversion.rb#L64-68)).
- 1. Remove old indexes and rename new ones ([see an example](https://gitlab.com/gitlab-org/gitlab/-/blob/41fbe34a4725a4e357a83fda66afb382828767b2/db/post_migrate/20210707210916_finalize_ci_stages_bigint_conversion.rb#L70-72)).
- - Names of the `bigint` indexes created using `add_bigint_column_indexes` helper can be retrieved by calling
- `bigint_index_name` from `Gitlab::Database::MigrationHelpers::ConvertToBigint` module.
- 1. Remove old foreign keys (if still present) and rename new ones ([see an example](https://gitlab.com/gitlab-org/gitlab/-/blob/41fbe34a4725a4e357a83fda66afb382828767b2/db/post_migrate/20210707210916_finalize_ci_stages_bigint_conversion.rb#L74)).
+ 1. Lock the tables involved. To reduce the chance of hitting a deadlock, we recommended to do this in parent to child order ([see an example](https://gitlab.com/gitlab-org/gitlab/-/blob/41fbe34a4725a4e357a83fda66afb382828767b2/db/post_migrate/20210707210916_finalize_ci_stages_bigint_conversion.rb#L47)).
+ 1. Rename the columns to swap names ([see an example](https://gitlab.com/gitlab-org/gitlab/-/blob/41fbe34a4725a4e357a83fda66afb382828767b2/db/post_migrate/20210707210916_finalize_ci_stages_bigint_conversion.rb#L49-54))
+ 1. Reset the trigger function ([see an example](https://gitlab.com/gitlab-org/gitlab/-/blob/41fbe34a4725a4e357a83fda66afb382828767b2/db/post_migrate/20210707210916_finalize_ci_stages_bigint_conversion.rb#L56-57)).
+ 1. Swap the defaults ([see an example](https://gitlab.com/gitlab-org/gitlab/-/blob/41fbe34a4725a4e357a83fda66afb382828767b2/db/post_migrate/20210707210916_finalize_ci_stages_bigint_conversion.rb#L59-62)).
+ 1. Swap the PK constraint (if any) ([see an example](https://gitlab.com/gitlab-org/gitlab/-/blob/41fbe34a4725a4e357a83fda66afb382828767b2/db/post_migrate/20210707210916_finalize_ci_stages_bigint_conversion.rb#L64-68)).
+ 1. Remove old indexes and rename new ones ([see an example](https://gitlab.com/gitlab-org/gitlab/-/blob/41fbe34a4725a4e357a83fda66afb382828767b2/db/post_migrate/20210707210916_finalize_ci_stages_bigint_conversion.rb#L70-72)).
+ - Names of the `bigint` indexes created using `add_bigint_column_indexes` helper can be retrieved by calling
+ `bigint_index_name` from `Gitlab::Database::MigrationHelpers::ConvertToBigint` module.
+ 1. Remove old foreign keys (if still present) and rename new ones ([see an example](https://gitlab.com/gitlab-org/gitlab/-/blob/41fbe34a4725a4e357a83fda66afb382828767b2/db/post_migrate/20210707210916_finalize_ci_stages_bigint_conversion.rb#L74)).
See example [merge request](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/66088), and [migration](https://gitlab.com/gitlab-org/gitlab/-/blob/41fbe34a4725a4e357a83fda66afb382828767b2/db/post_migrate/20210707210916_finalize_ci_stages_bigint_conversion.rb).
diff --git a/doc/development/database/efficient_in_operator_queries.md b/doc/development/database/efficient_in_operator_queries.md
index 8e334e5bb5c..e1a7b56e35e 100644
--- a/doc/development/database/efficient_in_operator_queries.md
+++ b/doc/development/database/efficient_in_operator_queries.md
@@ -916,16 +916,16 @@ Here's an outline of the steps we take in the recursive CTE query
1. Sort the initial `resultset` according to the `ORDER BY` clause.
1. Pick the top cursor to fetch the record, this is our first record. In the example,
-this cursor would be (`2020-01-05`, `3`) for `project_id=9`.
+ this cursor would be (`2020-01-05`, `3`) for `project_id=9`.
1. We can use (`2020-01-05`, `3`) to fetch the next issue respecting the `ORDER BY` clause
-`project_id=9` filter. This produces an updated `resultset`.
+ `project_id=9` filter. This produces an updated `resultset`.
- | `project_ids` | `created_at_values` | `id_values` |
- | ------------- | ------------------- | ----------- |
- | 2 | 2020-01-10 | 5 |
- | 5 | 2020-01-05 | 4 |
- | 10 | 2020-01-15 | 7 |
- | **9** | **2020-01-06** | **6** |
+ | `project_ids` | `created_at_values` | `id_values` |
+ | ------------- | ------------------- | ----------- |
+ | 2 | 2020-01-10 | 5 |
+ | 5 | 2020-01-05 | 4 |
+ | 10 | 2020-01-15 | 7 |
+ | **9** | **2020-01-06** | **6** |
1. Repeat 1 to 3 with the updated `resultset` until we have fetched `N=20` records.
@@ -944,9 +944,9 @@ Example initializer row:
| `NULL::issues` | `[9, 2, 5, 10]` | `[...]` | `[...]` | `0` | `NULL` |
- The `records` column contains our sorted database records, and the initializer query sets the
-first value to `NULL`, which is filtered out later.
+ first value to `NULL`, which is filtered out later.
- The `count` column tracks the number of records found. We use this column to filter out the
-initializer row from the result set.
+ initializer row from the result set.
### Recursive portion of the CTE query
@@ -1016,7 +1016,7 @@ As the final step, we need to produce a new row by manipulating the initializer
(`data_collector_query` method). Two things happen here:
- Read the full row from the DB and return it in the `records` columns. (`result_collector_columns`
-method)
+ method)
- Replace the cursor values at the current position with the results from the keyset query.
Reading the full row from the database is only one index scan by the primary key. We use the
@@ -1091,7 +1091,7 @@ in the PostgreSQL's buffer cache.
The optimized `IN` query reads maximum 519 entries (cursor values) from the index:
- 500 index-only scans for populating the arrays for each project. The cursor values of the first
-record is here.
+ record is here.
- Maximum 19 additional index-only scans for the consecutive records.
The optimized `IN` query sorts the array (cursor values per project array) 20 times, which
diff --git a/doc/development/database/iterating_tables_in_batches.md b/doc/development/database/iterating_tables_in_batches.md
index 802b7622592..7192a84508e 100644
--- a/doc/development/database/iterating_tables_in_batches.md
+++ b/doc/development/database/iterating_tables_in_batches.md
@@ -414,12 +414,12 @@ the queries, where the `issues` table is batched first.
When to use `JOINS`:
- When there's a 1:1 or 1:N relationship between the tables where we know that the joined record
-(almost) always exists. This works well for "extension-like" tables:
+ (almost) always exists. This works well for "extension-like" tables:
- `projects` - `project_settings`
- `users` - `user_details`
- `users` - `user_statuses`
- `LEFT JOIN` works well in this case. Conditions on the joined table need to go to the yielded
-relation so the iteration is not affected by the data distribution in the joined table.
+ relation so the iteration is not affected by the data distribution in the joined table.
Example:
@@ -555,7 +555,7 @@ table or a range of rows. The scaling and performance characteristics are very s
Examples:
- Iterate over the table in a specific order (timestamp columns) in combination with a tie-breaker
-if column user to sort by does not contain unique values.
+ if column user to sort by does not contain unique values.
- Iterate over the table with composite primary keys.
### Iterate over the issues in a project by creation date
@@ -619,8 +619,8 @@ To keep the iteration stable and predictable, avoid updating the columns in the
### Iterate over the `merge_request_diff_commits` table
-The `merge_request_diff_commits` table uses a composite primary key (`merge_request_diff_id,
-relative_order`), which makes `EachBatch` impossible to use efficiently.
+The `merge_request_diff_commits` table uses a composite primary key (`merge_request_diff_id, relative_order`),
+which makes `EachBatch` impossible to use efficiently.
To paginate over the `merge_request_diff_commits` table, you can use the following snippet:
@@ -654,7 +654,7 @@ end
### Order object configuration
Keyset pagination works well with simple `ActiveRecord` `order` scopes
-([first example](#iterate-over-the-issues-in-a-project-by-creation-date).
+([first example](#iterate-over-the-issues-in-a-project-by-creation-date)).
However, in special cases, you need to describe the columns in the `ORDER BY` clause (second example)
for the underlying keyset pagination library. When the `ORDER BY` configuration cannot be
automatically determined by the keyset pagination library, an error is raised.
diff --git a/doc/development/database/loose_foreign_keys.md b/doc/development/database/loose_foreign_keys.md
index 3003ee970ce..9ecc70c06bc 100644
--- a/doc/development/database/loose_foreign_keys.md
+++ b/doc/development/database/loose_foreign_keys.md
@@ -499,7 +499,7 @@ cron job where the schedule depends on the configuration of the GitLab instance.
- Non-decomposed GitLab (1 database): invoked every minute.
- Decomposed GitLab (2 databases, CI and Main): invoked every minute, cleaning up one database
-at a time. For example, the cleanup worker for the main database runs every two minutes.
+ at a time. For example, the cleanup worker for the main database runs every two minutes.
To avoid lock contention and the processing of the same database rows, the worker does not run
parallel. This behavior is ensured with a Redis lock.
@@ -509,13 +509,13 @@ parallel. This behavior is ensured with a Redis lock.
1. Acquire the Redis lock.
1. Determine which database to clean up.
1. Collect all database tables where the deletions are tracked (parent tables).
- - This is achieved by reading the `config/gitlab_loose_foreign_keys.yml` file.
- - A table is considered "tracked" when a loose foreign key definition exists for the table and
- the `DELETE` trigger is installed.
+ - This is achieved by reading the `config/gitlab_loose_foreign_keys.yml` file.
+ - A table is considered "tracked" when a loose foreign key definition exists for the table and
+ the `DELETE` trigger is installed.
1. Cycle through the tables with an infinite loop.
1. For each table, load a batch of deleted parent records to clean up.
1. Depending on the YAML configuration, build `DELETE` or `UPDATE` (nullify) queries for the
-referenced child tables.
+ referenced child tables.
1. Invoke the queries.
1. Repeat until all child records are cleaned up or the maximum limit is reached.
1. Remove the deleted parent records when all child records are cleaned up.
@@ -530,13 +530,13 @@ The inserted record stores the following information about the deleted record:
- `fully_qualified_table_name`: name of the database table where the record was located.
- `primary_key_value`: the ID of the record, the value is present in the child tables as
-the foreign key value. At the moment, composite primary keys are not supported, the parent table
-must have an `id` column.
+ the foreign key value. At the moment, composite primary keys are not supported, the parent table
+ must have an `id` column.
- `status`: defaults to pending, represents the status of the cleanup process.
- `consume_after`: defaults to the current time.
- `cleanup_attempts`: defaults to 0. The number of times the worker tried to clean up this record.
-A non-zero number would mean that this record has many child records and cleaning it up requires
-several runs.
+ A non-zero number would mean that this record has many child records and cleaning it up requires
+ several runs.
#### Database decomposition
@@ -692,7 +692,7 @@ The loop-based batch processing is preferred over `EachBatch` for the following
- The records in the batch are modified, so the next batch contains different records.
- There is always an index on the foreign key column however, the column is usually not unique.
-`EachBatch` requires a unique column for the iteration.
+ `EachBatch` requires a unique column for the iteration.
- The record order doesn't matter for the cleanup.
Notice that we have two loops. The initial loop processes records with the `SKIP LOCKED` clause.
@@ -747,23 +747,23 @@ For example, a project with millions of `ci_builds` records is deleted. The `ci_
is deleted by the loose foreign keys feature.
1. The cleanup worker is scheduled and picks up a batch of deleted `projects` records. The large
-project is part of the batch.
+ project is part of the batch.
1. Deletion of the orphaned `ci_builds` rows has started.
1. The time limit is reached, but the cleanup is not complete.
1. The `cleanup_attempts` column is incremented for the deleted records.
1. Go to step 1. The next cleanup worker continues the cleanup.
1. When the `cleanup_attempts` reaches 3, the batch is re-scheduled 10 minutes later by updating
-the `consume_after` column.
+ the `consume_after` column.
1. The next cleanup worker processes a different batch.
We have Prometheus metrics in place to monitor the deleted record cleanup:
- `loose_foreign_key_processed_deleted_records`: Number of processed deleted records. When large
-cleanup happens, this number would decrease.
+ cleanup happens, this number would decrease.
- `loose_foreign_key_incremented_deleted_records`: Number of deleted records which were not
-finished processing. The `cleanup_attempts` column was incremented.
+ finished processing. The `cleanup_attempts` column was incremented.
- `loose_foreign_key_rescheduled_deleted_records`: Number of deleted records that had to be
-rescheduled at a later time after 3 cleanup attempts.
+ rescheduled at a later time after 3 cleanup attempts.
Example Thanos query:
diff --git a/doc/development/database/maintenance_operations.md b/doc/development/database/maintenance_operations.md
index 2701c228b74..fcdf132aa09 100644
--- a/doc/development/database/maintenance_operations.md
+++ b/doc/development/database/maintenance_operations.md
@@ -18,7 +18,7 @@ There are certain situations in which you might want to disable an index before
To disable an index before removing it:
1. Open a [production infrastructure issue](https://gitlab.com/gitlab-com/gl-infra/production/-/issues/new)
-and use the "Production Change" template.
+ and use the "Production Change" template.
1. Inform the database team in the issue `@gl-database` or in Slack `#database`.
1. Add a step to verify the index is used (this would likely be an `EXPLAIN` command known to use the index).
1. Add the step to disable the index:
diff --git a/doc/development/database/rename_database_tables.md b/doc/development/database/rename_database_tables.md
index ad641797496..babd51f91a0 100644
--- a/doc/development/database/rename_database_tables.md
+++ b/doc/development/database/rename_database_tables.md
@@ -78,18 +78,18 @@ Execute a standard migration (not a post-migration):
- Add a note in the Engineering Week-in-Review document: `table_name` is going to be renamed in N.M. Modifications to this table are not allowed in release N.M and N.M+1.
- The helper method uses the standard `rename_table` helper from Rails for renaming the table.
- The helper renames the sequence and the indexes. Sometimes it diverges from the standard Rails convention
-when naming indexes, so there is a possibility that not all indexes are properly renamed. After running
-the migration locally, check if there are inconsistently named indexes (`db/structure.sql`). Those can be
-renamed manually in a separate migration, which can be also part of the release M.N+1.
+ when naming indexes, so there is a possibility that not all indexes are properly renamed. After running
+ the migration locally, check if there are inconsistently named indexes (`db/structure.sql`). Those can be
+ renamed manually in a separate migration, which can be also part of the release M.N+1.
- Foreign key columns might still contain the old table name. For smaller tables, follow our
[standard column rename process](avoiding_downtime_in_migrations.md#renaming-columns)
- Avoid renaming database tables which are using with triggers.
- Table modifications (add or remove columns) are not allowed during the rename process. Make sure that all changes to the table happen before the rename migration is started (or in the next release).
- As the index names might change, verify that the model does not use bulk insert
-(for example, `insert_all` and `upsert_all`) with the `unique_by: index_name` option.
-Renaming an index while using these methods may break functionality.
+ (for example, `insert_all` and `upsert_all`) with the `unique_by: index_name` option.
+ Renaming an index while using these methods may break functionality.
- Modify the model code to point to the new database table. Do this by
-renaming the model directly or setting the `self.table_name` variable.
+ renaming the model directly or setting the `self.table_name` variable.
At this point, we don't have applications using the old database table name in their queries.
@@ -107,7 +107,7 @@ At this point, we don't have applications using the old database table name in t
1. Additionally the table definition from `TABLES_TO_BE_RENAMED` **must** be removed.
-To do so, edit the `TABLES_TO_BE_RENAMED` constant in `lib/gitlab/database.rb`:
+ To do so, edit the `TABLES_TO_BE_RENAMED` constant in `lib/gitlab/database.rb`:
From:
diff --git a/doc/development/database/strings_and_the_text_data_type.md b/doc/development/database/strings_and_the_text_data_type.md
index 70d59603e0c..50188dba14e 100644
--- a/doc/development/database/strings_and_the_text_data_type.md
+++ b/doc/development/database/strings_and_the_text_data_type.md
@@ -12,8 +12,8 @@ When adding new columns to store strings or other textual information:
1. We always use the `text` data type instead of the `string` data type.
1. `text` columns should always have a limit set, either by using the `create_table` with
-the `#text ... limit: 100` helper (see below) when creating a table, or by using the `add_text_limit`
-when altering an existing table.
+ the `#text ... limit: 100` helper (see below) when creating a table, or by using the `add_text_limit`
+ when altering an existing table.
The standard Rails `text` column type cannot be defined with a limit, but we extend `create_table` to
add a `limit: 255` option. Outside of `create_table`, `add_text_limit` can be used to add a [check constraint](https://www.postgresql.org/docs/11/ddl-constraints.html)
diff --git a/doc/development/database/table_partitioning.md b/doc/development/database/table_partitioning.md
index 4d3101b40fb..2b805e964c7 100644
--- a/doc/development/database/table_partitioning.md
+++ b/doc/development/database/table_partitioning.md
@@ -19,15 +19,15 @@ table. If the application is designed to work with partitioning in mind,
there can be multiple benefits, such as:
- Query performance can be improved greatly, because the database can
-cheaply eliminate much of the data from the search space, while still
-providing full SQL capabilities.
+ cheaply eliminate much of the data from the search space, while still
+ providing full SQL capabilities.
- Bulk deletes can be achieved with minimal impact on the database by
-dropping entire partitions. This is a natural fit for features that need
-to periodically delete data that falls outside the retention window.
+ dropping entire partitions. This is a natural fit for features that need
+ to periodically delete data that falls outside the retention window.
- Administrative tasks like `VACUUM` and index rebuilds can operate on
-individual partitions, rather than across a single massive table.
+ individual partitions, rather than across a single massive table.
Unfortunately, not all models fit a partitioning scheme, and there are
significant drawbacks if implemented incorrectly. Additionally, tables
diff --git a/doc/development/fe_guide/content_editor.md b/doc/development/fe_guide/content_editor.md
index 7a76b39edbc..64cf7de75ab 100644
--- a/doc/development/fe_guide/content_editor.md
+++ b/doc/development/fe_guide/content_editor.md
@@ -46,7 +46,7 @@ export default {
The rich text editor requires two properties:
- `renderMarkdown` is an asynchronous function that returns the response (String) of invoking the
-[Markdown API](../../api/markdown.md).
+ [Markdown API](../../api/markdown.md).
- `uploadsPath` is a URL that points to a [GitLab upload service](../uploads/index.md)
with `multipart/form-data` support.
diff --git a/doc/development/fe_guide/customizable_dashboards.md b/doc/development/fe_guide/customizable_dashboards.md
index 93b5b20b047..9ba0d4bb40c 100644
--- a/doc/development/fe_guide/customizable_dashboards.md
+++ b/doc/development/fe_guide/customizable_dashboards.md
@@ -98,7 +98,7 @@ export const pageViewsOverTime = {
To add a new visualization render type:
1. Create a new Vue component that accepts `data` and `options` properties.
-See [`line_chart.vue`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/app/assets/javascripts/analytics/analytics_dashboards/components/visualizations/line_chart.vue) as an example.
+ See [`line_chart.vue`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/app/assets/javascripts/analytics/analytics_dashboards/components/visualizations/line_chart.vue) as an example.
1. Add your component to the list of conditional imports in [`panel_base.vue`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/app/assets/javascripts/vue_shared/components/customizable_dashboard/panels_base.vue#L13).
1. Add your component to the schema's list of `AnalyticsVisualization` types in [`analytics_visualizations.json`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/app/validators/json_schemas/analytics_visualization.json).
diff --git a/doc/development/fe_guide/graphql.md b/doc/development/fe_guide/graphql.md
index 22b977519be..bd35d8f237f 100644
--- a/doc/development/fe_guide/graphql.md
+++ b/doc/development/fe_guide/graphql.md
@@ -1671,7 +1671,7 @@ When [using Vuex](#using-with-vuex), disable the cache when:
- The data is being cached elsewhere
- The use case does not need caching
-if the data is being cached elsewhere, or if there is no need for it for the given use case.
+ if the data is being cached elsewhere, or if there is no need for it for the given use case.
```javascript
import createDefaultClient from '~/lib/graphql';
@@ -1767,12 +1767,12 @@ To improve performance, sometimes we want to make initial GraphQL queries early.
```
- Add startup calls with correct variables to the HAML file that serves as a view
-for your application. To add GraphQL startup calls, we use
-`add_page_startup_graphql_call` helper where the first parameter is a path to the
-query, the second one is an object containing query variables. Path to the query is
-relative to `app/graphql/queries` folder: for example, if we need a
-`app/graphql/queries/repository/files.query.graphql` query, the path is
-`repository/files`.
+ for your application. To add GraphQL startup calls, we use
+ `add_page_startup_graphql_call` helper where the first parameter is a path to the
+ query, the second one is an object containing query variables. Path to the query is
+ relative to `app/graphql/queries` folder: for example, if we need a
+ `app/graphql/queries/repository/files.query.graphql` query, the path is
+ `repository/files`.
## Troubleshooting
diff --git a/doc/development/fe_guide/haml.md b/doc/development/fe_guide/haml.md
index 88f4a785a70..4a6b349bbc8 100644
--- a/doc/development/fe_guide/haml.md
+++ b/doc/development/fe_guide/haml.md
@@ -20,8 +20,8 @@ used in HAML:
- Some of the Pajamas components are available as a [ViewComponent](view_component.md#pajamas-components). Use these when possible.
- If no ViewComponent exists, why not go ahead and create it? Talk to the Foundations team if you need help.
- As a fallback, this can be done by applying the correct CSS classes to the elements.
-- A custom
-[Ruby on Rails form builder](https://gitlab.com/gitlab-org/gitlab/-/blob/7c108df101e86d8a27d69df2b5b1ff1fc24133c5/lib/gitlab/form_builders/gitlab_ui_form_builder.rb) exists to help use GitLab UI components in HAML forms.
+- A custom [Ruby on Rails form builder](https://gitlab.com/gitlab-org/gitlab/-/blob/7c108df101e86d8a27d69df2b5b1ff1fc24133c5/lib/gitlab/form_builders/gitlab_ui_form_builder.rb)
+ exists to help use GitLab UI components in HAML forms.
### Use the GitLab UI form builder
diff --git a/doc/development/fe_guide/storybook.md b/doc/development/fe_guide/storybook.md
index 05d4397933f..f0233f71ad2 100644
--- a/doc/development/fe_guide/storybook.md
+++ b/doc/development/fe_guide/storybook.md
@@ -68,7 +68,7 @@ To add a story with API access:
If you test against `gitlab.com`, make sure to use a token with `read_api` if possible and to make the token short-lived.
1. Create an `.env` file in the `storybook` directory. Use the `storybook/.env.template` file as
-a starting point.
+ a starting point.
1. Set the `API_ACCESS_TOKEN` variable to the access token that you created.
diff --git a/doc/development/fe_guide/style/vue.md b/doc/development/fe_guide/style/vue.md
index 83d725d453b..870a4c51915 100644
--- a/doc/development/fe_guide/style/vue.md
+++ b/doc/development/fe_guide/style/vue.md
@@ -123,7 +123,7 @@ Check the [rules](https://github.com/vuejs/eslint-plugin-vue#bulb-rules) for mor
## Naming
1. **Extensions**: Use `.vue` extension for Vue components. Do not use `.js` as file extension
-([#34371](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/34371)).
+ ([#34371](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/34371)).
1. **Reference Naming**: Use PascalCase for their default imports:
```javascript
@@ -142,7 +142,7 @@ Check the [rules](https://github.com/vuejs/eslint-plugin-vue#bulb-rules) for mor
};
```
-1. **Props Naming:** Avoid using DOM component prop names.
+1. **Props Naming:** Avoid using DOM component prop names.
1. **Props Naming:** Use kebab-case instead of camelCase to provide props in templates.
```html
@@ -582,8 +582,8 @@ describe('MyComponent', () => {
### Setting component state
1. Avoid using [`setProps`](https://v1.test-utils.vuejs.org/api/wrapper/#setprops) to set
-component state wherever possible. Instead, set the component's
-[`propsData`](https://v1.test-utils.vuejs.org/api/options.html#propsdata) when mounting the component:
+ component state wherever possible. Instead, set the component's
+ [`propsData`](https://v1.test-utils.vuejs.org/api/options.html#propsdata) when mounting the component:
```javascript
// bad
@@ -603,7 +603,7 @@ component state wherever possible. Instead, set the component's
### Accessing component state
1. When accessing props or attributes, prefer the `wrapper.props('myProp')` syntax over
-`wrapper.props().myProp` or `wrapper.vm.myProp`:
+ `wrapper.props().myProp` or `wrapper.vm.myProp`:
```javascript
// good
@@ -616,7 +616,7 @@ component state wherever possible. Instead, set the component's
```
1. When asserting multiple props, check the deep equality of the `props()` object with
-[`toEqual`](https://jestjs.io/docs/expect#toequalvalue):
+ [`toEqual`](https://jestjs.io/docs/expect#toequalvalue):
```javascript
// good
@@ -633,8 +633,8 @@ component state wherever possible. Instead, set the component's
```
1. If you are only interested in some of the props, you can use
-[`toMatchObject`](https://jestjs.io/docs/expect#tomatchobjectobject). Prefer `toMatchObject`
-over [`expect.objectContaining`](https://jestjs.io/docs/expect#expectobjectcontainingobject):
+ [`toMatchObject`](https://jestjs.io/docs/expect#tomatchobjectobject). Prefer `toMatchObject`
+ over [`expect.objectContaining`](https://jestjs.io/docs/expect#expectobjectcontainingobject):
```javascript
// good
@@ -652,7 +652,7 @@ over [`expect.objectContaining`](https://jestjs.io/docs/expect#expectobjectconta
### Testing props validation
-1. When checking component props use `assertProps` helper. Props validation failures will be thrown as errors
+When checking component props use `assertProps` helper. Props validation failures will be thrown as errors:
```javascript
import { assertProps } from 'helpers/assert_props'
@@ -668,12 +668,12 @@ The goal of this accord is to make sure we are all on the same page.
1. When writing Vue, you may not use jQuery in your application.
1. If you need to grab data from the DOM, you may query the DOM 1 time while bootstrapping your
- application to grab data attributes using `dataset`. You can do this without jQuery.
+ application to grab data attributes using `dataset`. You can do this without jQuery.
1. You may use a jQuery dependency in Vue.js following [this example from the docs](https://vuejs.org/v2/examples/select2.html).
1. If an outside jQuery Event needs to be listen to inside the Vue application, you may use
- jQuery event listeners.
+ jQuery event listeners.
1. We avoid adding new jQuery events when they are not required. Instead of adding new jQuery
- events take a look at [different methods to do the same task](https://v2.vuejs.org/v2/api/#vm-emit).
+ events take a look at [different methods to do the same task](https://v2.vuejs.org/v2/api/#vm-emit).
1. You may query the `window` object one time, while bootstrapping your application for application
specific data (for example, `scrollTo` is ok to access anytime). Do this access during the
bootstrapping of your application.
diff --git a/doc/development/fe_guide/vue.md b/doc/development/fe_guide/vue.md
index 69967a5a2be..cf7659d0fc0 100644
--- a/doc/development/fe_guide/vue.md
+++ b/doc/development/fe_guide/vue.md
@@ -543,7 +543,7 @@ Based on the Vue guidance:
- **Do not** use or create a JavaScript class in your [data function](https://v2.vuejs.org/v2/api/#data).
- **Do not** add new JavaScript class implementations.
- **Do** use [GraphQL](../api_graphql_styleguide.md), [Vuex](vuex.md) or a set of components if
-cannot use primitives or objects.
+ cannot use primitives or objects.
- **Do** maintain existing implementations using such approaches.
- **Do** Migrate components to a pure object model when there are substantial changes to it.
- **Do** add business logic to helpers or utilities, so you can test them separately from your component.
@@ -555,7 +555,7 @@ Additional reasons why having a JavaScript class presents maintainability issues
- After a class is created, it can be extended in a way that can infringe Vue reactivity and best practices.
- A class adds a layer of abstraction, which makes the component API and its inner workings less clear.
- It makes it harder to test. Because the class is instantiated by the component data function, it is
-harder to 'manage' component and class separately.
+ harder to 'manage' component and class separately.
- Adding Object Oriented Principles (OOP) to a functional codebase adds another way of writing code, reducing consistency and clarity.
## Style guide
@@ -831,7 +831,7 @@ describe('~/todos/app.vue', () => {
1. Test any directive that defines if/how child component is rendered (for example, `v-if` and `v-for`).
1. Test any props we are passing to child components (especially if the prop is calculated in the
-component under test, with the `computed` property, for example). Remember to use `.props()` and not `.vm.someProp`.
+ component under test, with the `computed` property, for example). Remember to use `.props()` and not `.vm.someProp`.
1. Test we react correctly to any events emitted from child components:
```javascript
diff --git a/doc/development/packages/cleanup_policies.md b/doc/development/packages/cleanup_policies.md
index bbec6ce0623..789bb408dd7 100644
--- a/doc/development/packages/cleanup_policies.md
+++ b/doc/development/packages/cleanup_policies.md
@@ -27,7 +27,7 @@ The parameters are split into two groups:
- The parameters that define tags to destroy:
- `older_than`. Destroy tags older than this timestamp.
- `name_regex`. Destroy tags matching this regular expression.
-
+
The remaining parameters impact when the policy is executed:
- `enabled`. Defines if the policy is enabled or not.
@@ -41,8 +41,7 @@ follows this design.
- Policy executions are limited in time.
- Policy executions are either complete or partial.
-- The background jobs will consider the next job to be executed based on two
-priorities:
+- The background jobs will consider the next job to be executed based on two priorities:
- Policy with a `next_run_at` in the past.
- Partially executed policies.
@@ -54,7 +53,7 @@ Background jobs for this execution are organized on:
- A cron background job that runs every hour.
- A set of background jobs that will loop on container repositories that need
-a policy execution.
+ a policy execution.
#### The cron background job
@@ -63,7 +62,7 @@ is quite simple.
Its main tasks are:
1. Check if there are any container repositories in need of a cleanup. If any,
-enqueue as many limited capacity jobs as necessary, up to a limit.
+ enqueue as many limited capacity jobs as necessary, up to a limit.
1. Compute metrics for cleanup policies and log them.
#### The limited capacity job
@@ -97,14 +96,14 @@ flowchart TD
```
- [`ContainerExpirationPolicies::CleanupService`](https://gitlab.com/gitlab-org/gitlab/-/blob/6546ffc6fe4e9b447a1b7f050edddb8926fe4a3d/app/services/container_expiration_policies/cleanup_service.rb).
-This service mainly deals with container repository `expiration_policy_cleanup_status`
-updates and will call the cleanup tags service.
+ This service mainly deals with container repository `expiration_policy_cleanup_status`
+ updates and will call the cleanup tags service.
- [`Projects::ContainerRepository::CleanupTagsService`](https://gitlab.com/gitlab-org/gitlab/-/blob/f23d70b7d638c38d71af102cfd32a3f6751596f9/app/services/projects/container_repository/cleanup_tags_service.rb).
-This service receives the policy parameters and builds the list of tags to
-destroy on the container registry.
+ This service receives the policy parameters and builds the list of tags to
+ destroy on the container registry.
- [`Projects::ContainerRepository::DeleteTagsService`](https://gitlab.com/gitlab-org/gitlab/-/blob/f23d70b7d638c38d71af102cfd32a3f6751596f9/app/services/projects/container_repository/delete_tags_service.rb).
-This service receives a list of tags and loops on that list. For each tag,
-the service will call the container registry API endpoint to destroy the target tag.
+ This service receives a list of tags and loops on that list. For each tag,
+ the service will call the container registry API endpoint to destroy the target tag.
The cleanup tags service uses a very specific [execution order](../../user/packages/container_registry/reduce_container_registry_storage.md#how-the-cleanup-policy-works)
to build the list of tags to destroy.
diff --git a/doc/development/testing_guide/testing_levels.md b/doc/development/testing_guide/testing_levels.md
index 81399c7ce05..99852645914 100644
--- a/doc/development/testing_guide/testing_levels.md
+++ b/doc/development/testing_guide/testing_levels.md
@@ -349,7 +349,7 @@ possible).
| Tests path | Testing engine | Notes |
| ---------- | -------------- | ----- |
-| `spec/features/` | [Capybara](https://github.com/teamcapybara/capybara) + [RSpec](https://github.com/rspec/rspec-rails#feature-specs) | If your test has the `:js` metadata, the browser driver is [Poltergeist](https://github.com/teamcapybara/capybara#poltergeist), otherwise it's using [RackTest](https://github.com/teamcapybara/capybara#racktest). |
+| `spec/features/` | [Capybara](https://github.com/teamcapybara/capybara) + [RSpec](https://github.com/rspec/rspec-rails#feature-specs) | If your test has the `:js` metadata, the browser driver is [Selenium](https://github.com/teamcapybara/capybara#selenium), otherwise it's using [RackTest](https://github.com/teamcapybara/capybara#racktest). |
### Frontend feature tests
diff --git a/doc/index.md b/doc/index.md
index 617ed547f77..5fdb2386771 100644
--- a/doc/index.md
+++ b/doc/index.md
@@ -37,14 +37,14 @@ Have a look at some of our most popular topics:
|:-------------------------------------------------------------------------------------------|:------------|
| [Two-factor authentication](user/profile/account/two_factor_authentication.md) | Improve the security of your GitLab account. |
| [GitLab groups](user/group/index.md) | Manage projects together. |
-| [Keyword reference for the `.gitlab-ci.yml` file](ci/yaml/index.md) | Available configuration options for `.gitlab-ci.yml` files. |
-| [Activate GitLab EE with a license](administration/license.md) | Activate GitLab Enterprise Edition functionality with a license. |
-| [Back up and restore GitLab](administration/backup_restore/index.md) | Backing up and restoring GitLab self-managed instances. |
+| [CI/CD YAML syntax reference](ci/yaml/index.md) | Available configuration options for `.gitlab-ci.yml` files. |
+| [Activate GitLab EE with a license](administration/license.md) | Activate GitLab Enterprise Edition functionality with a license. |
+| [Back up and restore GitLab](administration/backup_restore/index.md) | Backing up and restoring GitLab self-managed instances. |
| [GitLab release and maintenance policy](policy/maintenance.md) | Policies for version naming and cadence, and also upgrade recommendations. |
| [Elasticsearch integration](integration/advanced_search/elasticsearch.md) | Integrate Elasticsearch with GitLab to enable advanced search. |
-| [Database settings for Linux package installations](https://docs.gitlab.com/omnibus/settings/database.html) | Database settings for self-managed instances installed using Linux packages. |
-| [NGINX settings for Linux package installations](https://docs.gitlab.com/omnibus/settings/nginx.html) | NGINX settings for self-managed instances installed using Linux packages. |
-| [SSL configuration for Linux package installations](https://docs.gitlab.com/omnibus/settings/ssl/index.html) | SSL settings for self-managed instances installed using Linux packages. |
+| [Database settings for Linux package installations](https://docs.gitlab.com/omnibus/settings/database.html) | Database settings for self-managed instances installed using Linux packages. |
+| [NGINX settings for Linux package installations](https://docs.gitlab.com/omnibus/settings/nginx.html) | NGINX settings for self-managed instances installed using Linux packages. |
+| [SSL configuration for Linux package installations](https://docs.gitlab.com/omnibus/settings/ssl/index.html) | SSL settings for self-managed instances installed using Linux packages. |
| [GitLab.com settings](user/gitlab_com/index.md) | Settings used for GitLab.com. |
## User account
diff --git a/doc/topics/autodevops/customize.md b/doc/topics/autodevops/customize.md
index 630123510a9..dc7bc225e39 100644
--- a/doc/topics/autodevops/customize.md
+++ b/doc/topics/autodevops/customize.md
@@ -266,12 +266,12 @@ To add custom behaviors to the CI/CD pipeline used by Auto DevOps:
```
1. Add your changes to the `.gitlab-ci.yml` file. Your changes are merged with the Auto DevOps template. For more information about
-how `include` merges your changes, see [the `include` documentation](../../ci/yaml/index.md#include).
+ how `include` merges your changes, see [the `include` documentation](../../ci/yaml/index.md#include).
To remove behaviors from the Auto DevOps pipeline:
1. Copy the [Auto DevOps template](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml)
-into your project.
+ into your project.
1. Edit your copy of the template as needed.
### Use individual components of Auto DevOps
diff --git a/doc/user/application_security/continuous_vulnerability_scanning/index.md b/doc/user/application_security/continuous_vulnerability_scanning/index.md
index 4d6d48012ae..7d083ea1846 100644
--- a/doc/user/application_security/continuous_vulnerability_scanning/index.md
+++ b/doc/user/application_security/continuous_vulnerability_scanning/index.md
@@ -10,7 +10,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
> - [Generally available](https://gitlab.com/gitlab-org/gitlab/-/issues/427424) in GitLab 16.7 with an additional feature flag named `global_dependency_scanning_on_advisory_ingestion`. Enabled by default.
FLAG:
-On self-managed GitLab, by default this feature is available. To hide the feature, an administrator can [disable the feature flags](../../feature_flags.md) named `dependency_scanning_on_advisory_ingestion` and `package_metadata_advisory_sync`.
+On self-managed GitLab, by default this feature is available. To hide the feature, an administrator can [disable the feature flags](../../feature_flags.md) named `dependency_scanning_on_advisory_ingestion`.
On GitLab.com, this feature is available.
Continuous Vulnerability Scanning detects new vulnerabilities outside a pipeline.
diff --git a/doc/user/clusters/management_project.md b/doc/user/clusters/management_project.md
index 178f1bd7705..391541d98af 100644
--- a/doc/user/clusters/management_project.md
+++ b/doc/user/clusters/management_project.md
@@ -47,7 +47,7 @@ Management projects are restricted to the following:
To use a cluster management project to manage your cluster:
1. Create a new project to serve as the cluster management project
-for your cluster.
+ for your cluster.
1. [Associate the cluster with the management project](#associate-the-cluster-management-project-with-the-cluster).
1. [Configure your cluster's pipelines](#configuring-your-pipeline).
1. [Set the environment scope](#setting-the-environment-scope).
@@ -66,7 +66,7 @@ To associate a cluster management project with your cluster:
1. Select **Kubernetes**.
1. Expand **Advanced settings**.
1. From the **Cluster management project** dropdown list, select the cluster management project
-you created in the previous step.
+ you created in the previous step.
### Configuring your pipeline
diff --git a/doc/user/infrastructure/clusters/connect/new_gke_cluster.md b/doc/user/infrastructure/clusters/connect/new_gke_cluster.md
index 3b20125ff03..839bce217b7 100644
--- a/doc/user/infrastructure/clusters/connect/new_gke_cluster.md
+++ b/doc/user/infrastructure/clusters/connect/new_gke_cluster.md
@@ -52,7 +52,7 @@ To import the project:
This project provides you with:
- A [cluster on Google Cloud Platform (GCP)](https://gitlab.com/gitlab-org/configure/examples/gitlab-terraform-gke/-/blob/master/gke.tf)
-with defaults for name, location, node count, and Kubernetes version.
+ with defaults for name, location, node count, and Kubernetes version.
- The [GitLab agent for Kubernetes](https://gitlab.com/gitlab-org/configure/examples/gitlab-terraform-gke/-/blob/master/agent.tf) installed in the cluster.
## Register the agent
@@ -73,10 +73,10 @@ To create a GitLab agent for Kubernetes:
To set up your project to communicate to GCP and the GitLab API:
1. To authenticate GCP with GitLab, create a [GCP service account](https://cloud.google.com/docs/authentication#service-accounts)
-with following roles: `Compute Network Viewer`, `Kubernetes Engine Admin`, `Service Account User`, and `Service Account Admin`. Both User and Admin
-service accounts are necessary. The User role impersonates the [default service account](https://cloud.google.com/compute/docs/access/service-accounts#default_service_account)
-when [creating the node pool](https://registry.terraform.io/providers/hashicorp/google/latest/docs/guides/using_gke_with_terraform#node-pool-management).
-The Admin role creates a service account in the `kube-system` namespace.
+ with following roles: `Compute Network Viewer`, `Kubernetes Engine Admin`, `Service Account User`, and `Service Account Admin`. Both User and Admin
+ service accounts are necessary. The User role impersonates the [default service account](https://cloud.google.com/compute/docs/access/service-accounts#default_service_account)
+ when [creating the node pool](https://registry.terraform.io/providers/hashicorp/google/latest/docs/guides/using_gke_with_terraform#node-pool-management).
+ The Admin role creates a service account in the `kube-system` namespace.
1. Download the JSON file with the service account key you created in the previous step.
1. On your computer, encode the JSON file to `base64` (replace `/path/to/sa-key.json` to the path to your key):
diff --git a/doc/user/infrastructure/iac/index.md b/doc/user/infrastructure/iac/index.md
index d76f5dd736a..616e15dc230 100644
--- a/doc/user/infrastructure/iac/index.md
+++ b/doc/user/infrastructure/iac/index.md
@@ -84,13 +84,13 @@ To use a Terraform template:
```yaml
variables:
- TF_STATE_NAME: default
- # If your terraform files are in a subdirectory, set TF_ROOT accordingly. For example:
- # TF_ROOT: terraform/production
+ TF_STATE_NAME: default
+ # If your terraform files are in a subdirectory, set TF_ROOT accordingly. For example:
+ # TF_ROOT: terraform/production
```
1. Optional. Override in your `.gitlab-ci.yml` file the attributes present
-in the template you fetched to customize your configuration.
+ in the template you fetched to customize your configuration.
### Terraform template recipes
diff --git a/doc/user/packages/conan_repository/index.md b/doc/user/packages/conan_repository/index.md
index 56ea4fe74b4..72f36ca4e80 100644
--- a/doc/user/packages/conan_repository/index.md
+++ b/doc/user/packages/conan_repository/index.md
@@ -318,11 +318,11 @@ To search by full or partial package name, or by exact recipe, run the
The scope of your search depends on your Conan remote configuration:
- If you have a remote configured for your [instance](#add-a-remote-for-your-instance), your search includes
-all projects you have permission to access. This includes your private projects
- as well as all public projects.
+ all projects you have permission to access. This includes your private projects
+ as well as all public projects.
- If you have a remote configured for a [project](#add-a-remote-for-your-project), your search includes all
-packages in the target project, as long as you have permission to access it.
+ packages in the target project, as long as you have permission to access it.
NOTE:
The limit of the search results is 500 packages, and the results are sorted by the most recently published packages.
diff --git a/doc/user/packages/container_registry/reduce_container_registry_storage.md b/doc/user/packages/container_registry/reduce_container_registry_storage.md
index 614639c705f..de24f2618d5 100644
--- a/doc/user/packages/container_registry/reduce_container_registry_storage.md
+++ b/doc/user/packages/container_registry/reduce_container_registry_storage.md
@@ -191,14 +191,14 @@ To create a cleanup policy in the UI:
1. In the **Cleanup policies** section, select **Set cleanup rules**.
1. Complete the fields:
- | Field | Description |
- |----------------------------|-------------------------------------------------|
- | **Toggle** | Turn the policy on or off. |
- | **Run cleanup** | How often the policy should run. |
- | **Keep the most recent** | How many tags to _always_ keep for each image. |
+ | Field | Description |
+ |----------------------------|-------------|
+ | **Toggle** | Turn the policy on or off. |
+ | **Run cleanup** | How often the policy should run. |
+ | **Keep the most recent** | How many tags to _always_ keep for each image. |
| **Keep tags matching** | A regex pattern that determines which tags to preserve. The `latest` tag is always preserved. For all tags, use `.*`. See other [regex pattern examples](#regex-pattern-examples). |
- | **Remove tags older than** | Remove only tags older than X days. |
- | **Remove tags matching** | A regex pattern that determines which tags to remove. This value cannot be blank. For all tags, use `.*`. See other [regex pattern examples](#regex-pattern-examples). |
+ | **Remove tags older than** | Remove only tags older than X days. |
+ | **Remove tags matching** | A regex pattern that determines which tags to remove. This value cannot be blank. For all tags, use `.*`. See other [regex pattern examples](#regex-pattern-examples). |
1. Select **Save**.
@@ -275,9 +275,9 @@ You can use the following application settings to prevent server resource starva
For self-managed instances, those settings can be updated in the [Rails console](../../../administration/operations/rails_console.md#starting-a-rails-console-session):
- ```ruby
- ApplicationSetting.last.update(container_registry_expiration_policies_worker_capacity: 3)
- ```
+```ruby
+ApplicationSetting.last.update(container_registry_expiration_policies_worker_capacity: 3)
+```
They are also available in the [administrator area](../../../administration/admin_area.md):
@@ -292,7 +292,7 @@ You can set, update, and disable the cleanup policies using the GitLab API.
Examples:
- Select all tags, keep at least 1 tag per image, clean up any tag older than 14 days, run once a month, preserve
-any images with the name `main`, and the policy is enabled:
+ any images with the name `main`, and the policy is enabled:
```shell
curl --request PUT --header 'Content-Type: application/json;charset=UTF-8' --header "PRIVATE-TOKEN: <your_access_token>" \
diff --git a/doc/user/packages/maven_repository/index.md b/doc/user/packages/maven_repository/index.md
index 8f702183adc..118be200a4f 100644
--- a/doc/user/packages/maven_repository/index.md
+++ b/doc/user/packages/maven_repository/index.md
@@ -255,9 +255,9 @@ credentials += Credentials("GitLab Packages Registry", "<host>", "<name>", "<tok
In this example:
- `<endpoint url>` is the [endpoint URL](#endpoint-urls).
-Example: `https://gitlab.example.com/api/v4/projects/<project_id>/packages/maven`.
+ Example: `https://gitlab.example.com/api/v4/projects/<project_id>/packages/maven`.
- `<host>` is the host present in the `<endpoint url>` without the protocol
-scheme or the port. Example: `gitlab.example.com`.
+ scheme or the port. Example: `gitlab.example.com`.
- `<name>` and `<token>` are explained in the table above.
::EndTabs
@@ -289,11 +289,11 @@ For the instance-level endpoint, ensure the relevant section of your `pom.xml` i
#### Endpoint URLs
-| Endpoint | Endpoint URL for `pom.xml` | Additional information |
-| -------- | ------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------- |
+| Endpoint | Endpoint URL for `pom.xml` | Additional information |
+|----------|--------------------------------------------------------------------------|------------------------|
| Project | `https://gitlab.example.com/api/v4/projects/<project_id>/packages/maven` | Replace `gitlab.example.com` with your domain name. Replace `<project_id>` with your project ID, found on your project's homepage. |
-| Group | `https://gitlab.example.com/api/v4/groups/<group_id>/-/packages/maven` | Replace `gitlab.example.com` with your domain name. Replace `<group_id>` with your group ID, found on your group's homepage. |
-| Instance | `https://gitlab.example.com/api/v4/packages/maven` | Replace `gitlab.example.com` with your domain name. |
+| Group | `https://gitlab.example.com/api/v4/groups/<group_id>/-/packages/maven` | Replace `gitlab.example.com` with your domain name. Replace `<group_id>` with your group ID, found on your group's homepage. |
+| Instance | `https://gitlab.example.com/api/v4/packages/maven` | Replace `gitlab.example.com` with your domain name. |
### Edit the configuration file for publishing
diff --git a/doc/user/project/clusters/add_existing_cluster.md b/doc/user/project/clusters/add_existing_cluster.md
index 161a698a48c..ea4c345a592 100644
--- a/doc/user/project/clusters/add_existing_cluster.md
+++ b/doc/user/project/clusters/add_existing_cluster.md
@@ -25,7 +25,7 @@ See the prerequisites below to add existing clusters to GitLab.
To add any cluster to GitLab, you need:
- Either a GitLab.com account or an account for a self-managed installation
-running GitLab 12.5 or later.
+ running GitLab 12.5 or later.
- The Maintainer role for group-level and project-level clusters.
- Access to the Admin Area for instance-level clusters.
- A Kubernetes cluster.
@@ -48,7 +48,7 @@ To add an existing **EKS** cluster, you need:
- An Amazon EKS cluster with worker nodes properly configured.
- `kubectl` [installed and configured](https://docs.aws.amazon.com/eks/latest/userguide/getting-started.html#get-started-kubectl)
-for access to the EKS cluster.
+ for access to the EKS cluster.
- Ensure the token of the account has administrator privileges for the cluster.
### GKE clusters
@@ -56,8 +56,8 @@ for access to the EKS cluster.
To add an existing **GKE** cluster, you need:
- The `container.clusterRoleBindings.create` permission to create a cluster
-role binding. You can follow the [Google Cloud documentation](https://cloud.google.com/iam/docs/granting-changing-revoking-access)
-to grant access.
+ role binding. You can follow the [Google Cloud documentation](https://cloud.google.com/iam/docs/granting-changing-revoking-access)
+ to grant access.
## How to add an existing cluster
diff --git a/doc/user/project/clusters/add_remove_clusters.md b/doc/user/project/clusters/add_remove_clusters.md
index 940561d70d0..7d18ef0d1e4 100644
--- a/doc/user/project/clusters/add_remove_clusters.md
+++ b/doc/user/project/clusters/add_remove_clusters.md
@@ -39,7 +39,7 @@ When removing a cluster integration, you have two options:
- **Remove integration**: remove only the Kubernetes integration.
- **Remove integration and resources**: remove the cluster integration and
-all GitLab cluster-related resources such as namespaces, roles, and bindings.
+ all GitLab cluster-related resources such as namespaces, roles, and bindings.
To remove the Kubernetes cluster integration:
diff --git a/doc/user/project/repository/code_suggestions/index.md b/doc/user/project/repository/code_suggestions/index.md
index 6a1d8fbe66e..2315778e0f2 100644
--- a/doc/user/project/repository/code_suggestions/index.md
+++ b/doc/user/project/repository/code_suggestions/index.md
@@ -13,7 +13,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
Write code more efficiently by using generative AI to suggest code while you're developing.
-With Code Suggestions, you get:
+With [GitLab Duo Code Suggestions](https://about.gitlab.com/solutions/code-suggestions/), you get:
- Code Completion, which suggests completions to the current line you are typing. These suggestions are usually low latency.
- Code Generation, which generates code based on a natural language code
@@ -26,7 +26,7 @@ With Code Suggestions, you get:
GitLab Duo Code Suggestions are available:
-- On [self-managed](self_managed.md) and [SaaS](saas.md). View these pages to get started.
+- In the Premium and Ultimate tier for [self-managed](self_managed.md), and across all tiers for [SaaS](saas.md). View these pages to get started.
- In VS Code, Microsoft Visual Studio, JetBrains IDEs, and Neovim. You must have the corresponding GitLab extension installed.
- In the GitLab Web IDE.
diff --git a/doc/user/project/repository/code_suggestions/self_managed.md b/doc/user/project/repository/code_suggestions/self_managed.md
index f16b1b05abb..5688985ab49 100644
--- a/doc/user/project/repository/code_suggestions/self_managed.md
+++ b/doc/user/project/repository/code_suggestions/self_managed.md
@@ -4,7 +4,7 @@ group: Code Creation
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://handbook.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
-# Code Suggestions on self-managed GitLab **(SELF)**
+# Code Suggestions on self-managed GitLab **(PREMIUM SELF)**
> - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/10653) in GitLab 16.1 as [Beta](../../../../policy/experiment-beta-support.md#beta) on self-managed GitLab.
> - [Introduced support for Google Vertex AI Codey APIs](https://gitlab.com/groups/gitlab-org/-/epics/10562) in GitLab 16.1.
@@ -41,7 +41,7 @@ version of GitLab. This setting is visible only in self-managed GitLab instances
::Tabs
-:::TabTitle GitLab 16.3 and later **(PREMIUM)**
+:::TabTitle GitLab 16.3 and later
Prerequisites:
diff --git a/doc/user/project/repository/reducing_the_repo_size_using_git.md b/doc/user/project/repository/reducing_the_repo_size_using_git.md
index a060973d89f..528e9eefa44 100644
--- a/doc/user/project/repository/reducing_the_repo_size_using_git.md
+++ b/doc/user/project/repository/reducing_the_repo_size_using_git.md
@@ -190,7 +190,7 @@ no longer being available.
To clean up a repository:
-1. Go to the project for the repository.
+1. On the left sidebar, select **Search or go to** and find your project.
1. Go to **Settings > Repository**.
1. Upload a list of objects. For example, a `commit-map` file created by `git filter-repo` which is located in the
`filter-repo` directory.
diff --git a/gems/gitlab-utils/lib/gitlab/utils.rb b/gems/gitlab-utils/lib/gitlab/utils.rb
index b7cb63210ee..d5a514bfae8 100644
--- a/gems/gitlab-utils/lib/gitlab/utils.rb
+++ b/gems/gitlab-utils/lib/gitlab/utils.rb
@@ -261,6 +261,8 @@ module Gitlab
end
end
+ # Use this method to set the `restrict_within_concurrent_ruby` to `true` for the block.
+ # `raise_if_concurrent_ruby!` will use this flag to raise an error if it's set to `true`.
def restrict_within_concurrent_ruby
previous = Thread.current[:restrict_within_concurrent_ruby]
Thread.current[:restrict_within_concurrent_ruby] = true
@@ -270,6 +272,18 @@ module Gitlab
Thread.current[:restrict_within_concurrent_ruby] = previous
end
+ # Use this method to disable the `restrict_within_concurrent_ruby` for the block.
+ # It is mainly used to prevent infinite loop when `ConcurrentRubyThreadIsUsedError` is rescued and sent to Sentry.
+ # More info: https://gitlab.com/gitlab-org/gitlab/-/issues/432145#note_1671305713
+ def allow_within_concurrent_ruby
+ previous = Thread.current[:restrict_within_concurrent_ruby]
+ Thread.current[:restrict_within_concurrent_ruby] = false
+
+ yield
+ ensure
+ Thread.current[:restrict_within_concurrent_ruby] = previous
+ end
+
# Running external methods can allocate I/O bound resources (like PostgreSQL connection or Gitaly)
# This is forbidden when running within a concurrent Ruby thread, for example `async` HTTP requests
# provided by the `gitlab-http` gem.
diff --git a/gems/gitlab-utils/spec/gitlab/utils_spec.rb b/gems/gitlab-utils/spec/gitlab/utils_spec.rb
index 69531225eef..02d288acedf 100644
--- a/gems/gitlab-utils/spec/gitlab/utils_spec.rb
+++ b/gems/gitlab-utils/spec/gitlab/utils_spec.rb
@@ -489,6 +489,26 @@ RSpec.describe Gitlab::Utils, feature_category: :shared do
end
end
+ describe '.allow_within_concurrent_ruby' do
+ it 'assigns restrict_within_concurrent_ruby false to the current thread and ensures it restores' do
+ expect(Thread.current[:restrict_within_concurrent_ruby]).to be_nil
+
+ described_class.allow_within_concurrent_ruby do
+ expect(Thread.current[:restrict_within_concurrent_ruby]).to be(false)
+ end
+
+ expect(Thread.current[:restrict_within_concurrent_ruby]).to be_nil
+ end
+
+ it 'overrides the value of restrict_within_concurrent_ruby' do
+ described_class.restrict_within_concurrent_ruby do
+ described_class.allow_within_concurrent_ruby do
+ expect(Thread.current[:restrict_within_concurrent_ruby]).to be(false)
+ end
+ end
+ end
+ end
+
describe '.raise_if_concurrent_ruby!' do
subject(:raise_if_concurrent_ruby!) { described_class.raise_if_concurrent_ruby!('test') }
diff --git a/lib/api/helpers/integrations_helpers.rb b/lib/api/helpers/integrations_helpers.rb
index cb8e3697e6d..6025ffddc33 100644
--- a/lib/api/helpers/integrations_helpers.rb
+++ b/lib/api/helpers/integrations_helpers.rb
@@ -418,14 +418,7 @@ module API
desc: 'Enable comments inside Jira issues on each GitLab event (commit / merge request)'
}
],
- 'mattermost-slash-commands' => [
- {
- required: true,
- name: :token,
- type: String,
- desc: 'The Mattermost token'
- }
- ],
+ 'mattermost-slash-commands' => ::Integrations::MattermostSlashCommands.api_fields,
'slack-slash-commands' => [
{
required: true,
diff --git a/lib/gitlab/error_tracking.rb b/lib/gitlab/error_tracking.rb
index 239aee97378..c66edfdda10 100644
--- a/lib/gitlab/error_tracking.rb
+++ b/lib/gitlab/error_tracking.rb
@@ -158,10 +158,12 @@ module Gitlab
end
def process_exception(exception, extra:, tags: {}, trackers: default_trackers)
- context_payload = Gitlab::ErrorTracking::ContextPayloadGenerator.generate(exception, extra, tags)
+ Gitlab::Utils.allow_within_concurrent_ruby do
+ context_payload = Gitlab::ErrorTracking::ContextPayloadGenerator.generate(exception, extra, tags)
- trackers.each do |tracker|
- tracker.capture_exception(exception, **context_payload)
+ trackers.each do |tracker|
+ tracker.capture_exception(exception, **context_payload)
+ end
end
end
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 121d87af164..3a0a7680f41 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -48787,6 +48787,9 @@ msgstr ""
msgid "The Issue Tracker is the place to add things that need to be improved or solved in a project. You can register or sign in to create issues for this project."
msgstr ""
+msgid "The Mattermost token."
+msgstr ""
+
msgid "The Slack notifications integration is deprecated and will be removed in a future release. To continue to receive notifications from Slack, use the GitLab for Slack app instead. %{learn_more_link_start}Learn more%{link_end}."
msgstr ""
diff --git a/package.json b/package.json
index b337175f824..0c3f12f8b7a 100644
--- a/package.json
+++ b/package.json
@@ -60,7 +60,7 @@
"@gitlab/favicon-overlay": "2.0.0",
"@gitlab/fonts": "^1.3.0",
"@gitlab/svgs": "3.74.0",
- "@gitlab/ui": "^72.3.0",
+ "@gitlab/ui": "^72.3.1",
"@gitlab/visual-review-tools": "1.7.3",
"@gitlab/web-ide": "^0.0.1-dev-20231211152737",
"@mattiasbuelens/web-streams-adapter": "^0.1.0",
@@ -124,7 +124,7 @@
"clipboard": "^2.0.8",
"compression-webpack-plugin": "^5.0.2",
"copy-webpack-plugin": "^6.4.1",
- "core-js": "^3.34.0",
+ "core-js": "^3.35.0",
"cron-validator": "^1.1.1",
"cronstrue": "^1.122.0",
"cropperjs": "^1.6.1",
diff --git a/spec/frontend/vue_shared/components/source_viewer/source_viewer_new_spec.js b/spec/frontend/vue_shared/components/source_viewer/source_viewer_new_spec.js
index 86dc9afaacc..745886161ce 100644
--- a/spec/frontend/vue_shared/components/source_viewer/source_viewer_new_spec.js
+++ b/spec/frontend/vue_shared/components/source_viewer/source_viewer_new_spec.js
@@ -42,6 +42,8 @@ describe('Source Viewer component', () => {
let wrapper;
let fakeApollo;
const CHUNKS_MOCK = [CHUNK_1, CHUNK_2];
+ const projectPath = 'test';
+ const currentRef = 'main';
const hash = '#L142';
const blameDataQueryHandlerSuccess = jest.fn().mockResolvedValue(BLAME_DATA_QUERY_RESPONSE_MOCK);
@@ -57,8 +59,8 @@ describe('Source Viewer component', () => {
propsData: {
blob: { ...blob, ...BLOB_DATA_MOCK },
chunks: CHUNKS_MOCK,
- projectPath: 'test',
- currentRef: 'main',
+ projectPath,
+ currentRef,
showBlame,
},
});
@@ -116,6 +118,18 @@ describe('Source Viewer component', () => {
expect(findBlameComponents().at(0).props()).toMatchObject({ blameInfo });
});
+ it('calls the blame data query', async () => {
+ await triggerChunkAppear();
+
+ expect(blameDataQueryHandlerSuccess).toHaveBeenCalledWith(
+ expect.objectContaining({
+ filePath: BLOB_DATA_MOCK.path,
+ fullPath: projectPath,
+ ref: currentRef,
+ }),
+ );
+ });
+
it('calls the query only once per chunk', async () => {
// We trigger the `appear` event multiple times here in order to simulate the user scrolling past the chunk more than once.
// In this scenario we only want to query the backend once.
diff --git a/spec/lib/gitlab/error_tracking_spec.rb b/spec/lib/gitlab/error_tracking_spec.rb
index c9b2e21d934..7b2c5ca27cb 100644
--- a/spec/lib/gitlab/error_tracking_spec.rb
+++ b/spec/lib/gitlab/error_tracking_spec.rb
@@ -173,6 +173,20 @@ RSpec.describe Gitlab::ErrorTracking, feature_category: :shared do
)
end.to raise_error(RuntimeError)
end
+
+ it 'processes the exception even it is called within a `restrict_within_concurrent_ruby` block' do
+ expect(Gitlab::ErrorTracking::Logger).to receive(:error).with(logger_payload)
+
+ expect do
+ Gitlab::Utils.restrict_within_concurrent_ruby do
+ described_class.track_and_raise_exception(
+ exception,
+ issue_url: issue_url,
+ some_other_info: 'info'
+ )
+ end
+ end.to raise_error(RuntimeError, /boom/)
+ end
end
describe '.log_and_raise_exception' do
@@ -188,6 +202,16 @@ RSpec.describe Gitlab::ErrorTracking, feature_category: :shared do
expect { log_and_raise_exception }.to raise_error(RuntimeError)
end
+ it 'processes the exception even it is called within a `restrict_within_concurrent_ruby` block' do
+ expect(Gitlab::ErrorTracking::Logger).to receive(:error).with(logger_payload)
+
+ expect do
+ Gitlab::Utils.restrict_within_concurrent_ruby do
+ log_and_raise_exception
+ end
+ end.to raise_error(RuntimeError)
+ end
+
context 'when extra details are provided' do
let(:extra) { { test: 1, my_token: 'test' } }
@@ -230,6 +254,14 @@ RSpec.describe Gitlab::ErrorTracking, feature_category: :shared do
expect(Gitlab::ErrorTracking::Logger).to have_received(:error).with(logger_payload)
end
+ it 'processes the exception even it is called within a `restrict_within_concurrent_ruby` block' do
+ Gitlab::Utils.restrict_within_concurrent_ruby do
+ track_exception
+ end
+
+ expect(Gitlab::ErrorTracking::Logger).to have_received(:error).with(logger_payload)
+ end
+
context 'with tags' do
let(:tags) { { 'mytag' => 2 } }
diff --git a/spec/lib/gitlab/http_spec.rb b/spec/lib/gitlab/http_spec.rb
index 402790616b6..c23f4ea8ffa 100644
--- a/spec/lib/gitlab/http_spec.rb
+++ b/spec/lib/gitlab/http_spec.rb
@@ -55,8 +55,19 @@ RSpec.describe Gitlab::HTTP, feature_category: :shared do
end
context 'when there is a DB call in the concurrent thread' do
- it 'raises Gitlab::Utils::ConcurrentRubyThreadIsUsedError error',
- quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/432145' do
+ before do
+ # Simulating Sentry is active and configured.
+ # More info: https://gitlab.com/gitlab-org/gitlab/-/issues/432145#note_1671305713
+ stub_sentry_settings
+ allow(Gitlab::ErrorTracking).to receive(:sentry_configurable?).and_return(true)
+ Gitlab::ErrorTracking.configure
+ end
+
+ after do
+ clear_sentry_settings
+ end
+
+ it 'raises Gitlab::Utils::ConcurrentRubyThreadIsUsedError error' do
stub_request(:get, 'http://example.org').to_return(status: 200, body: 'hello world')
result = described_class.get('http://example.org', async: true) do |_fragment|
diff --git a/spec/models/member_spec.rb b/spec/models/member_spec.rb
index 38b1cf35bbf..9ebff2a8886 100644
--- a/spec/models/member_spec.rb
+++ b/spec/models/member_spec.rb
@@ -1121,6 +1121,86 @@ RSpec.describe Member, feature_category: :groups_and_projects do
end
end
+ context 'when after_create :post_create_hook' do
+ include NotificationHelpers
+
+ let_it_be(:source) { create(:group) }
+ let(:member) { create(:group_member, source: source) }
+
+ subject(:create_member) { member }
+
+ shared_examples_for 'invokes a notification' do
+ it 'enqueues an email to user' do
+ create_member
+
+ expect_delivery_jobs_count(1)
+ expect_enqueud_email(member.real_source_type, member.id, mail: 'member_access_granted_email')
+ end
+ end
+
+ shared_examples_for 'performs all the common hooks' do
+ it_behaves_like 'invokes a notification'
+
+ it 'creates an event' do
+ expect { create_member }.to change { Event.count }.by(1)
+ end
+ end
+
+ it 'calls the system hook service' do
+ expect_next_instance_of(SystemHooksService) do |instance|
+ expect(instance).to receive(:execute_hooks_for).with(an_instance_of(GroupMember), :create)
+ end
+
+ create_member
+ end
+
+ context 'when source is a group' do
+ it_behaves_like 'invokes a notification'
+
+ it 'does not create an event' do
+ expect { create_member }.not_to change { Event.count }
+ end
+ end
+
+ context 'when source is a project' do
+ context 'when source is a personal project' do
+ let_it_be(:namespace) { create(:namespace) }
+
+ context 'when member is the owner of the namespace' do
+ subject(:create_member) { create(:project, namespace: namespace) }
+
+ it 'does not enqueue an email' do
+ create_member
+
+ expect_delivery_jobs_count(0)
+ end
+
+ it 'does not create an event' do
+ expect { create_member }.not_to change { Event.count }
+ end
+ end
+
+ context 'when member is not the namespace owner' do
+ let_it_be(:project) { create(:project, namespace: namespace) }
+ let(:member) { create(:project_member, source: project) }
+
+ subject(:create_member) { member }
+
+ it_behaves_like 'performs all the common hooks'
+ end
+ end
+
+ context 'when source is not a personal project' do
+ let_it_be(:project) { create(:project, namespace: create(:group)) }
+ let(:member) { create(:project_member, source: project) }
+
+ subject(:create_member) { member }
+
+ it_behaves_like 'performs all the common hooks'
+ end
+ end
+ end
+
describe 'log_invitation_token_cleanup' do
let_it_be(:project) { create :project }
diff --git a/spec/models/members/group_member_spec.rb b/spec/models/members/group_member_spec.rb
index a7508f0e616..4df0b1e6af5 100644
--- a/spec/models/members/group_member_spec.rb
+++ b/spec/models/members/group_member_spec.rb
@@ -276,18 +276,4 @@ RSpec.describe GroupMember, feature_category: :cell do
it_behaves_like 'calls AuthorizedProjectsWorker inline to recalculate authorizations'
end
end
-
- context 'group member welcome email', :sidekiq_inline, :saas do
- let_it_be(:group) { create(:group) }
-
- let(:user) { create(:user) }
-
- it 'schedules plain welcome to the group email' do
- expect_next_instance_of(NotificationService) do |notification|
- expect(notification).to receive(:new_group_member)
- end
-
- group.add_developer(user)
- end
- end
end
diff --git a/spec/services/event_create_service_spec.rb b/spec/services/event_create_service_spec.rb
index 6a4769d77d5..f7041fb818e 100644
--- a/spec/services/event_create_service_spec.rb
+++ b/spec/services/event_create_service_spec.rb
@@ -364,19 +364,37 @@ RSpec.describe EventCreateService, :clean_gitlab_redis_cache, :clean_gitlab_redi
end
end
- describe 'Project' do
- describe '#join_project' do
- subject { service.join_project(project, user) }
+ describe '#join_source' do
+ let(:source) { project }
+ subject(:join_source) { service.join_source(source, user) }
+
+ context 'when source is a group' do
+ let_it_be(:source) { create(:group) }
+
+ it { is_expected.to be_falsey }
+
+ specify do
+ expect { join_source }.not_to change { Event.count }
+ end
+ end
+
+ context 'when source is a project' do
it { is_expected.to be_truthy }
- it { expect { subject }.to change { Event.count }.from(0).to(1) }
+
+ specify do
+ expect { join_source }.to change { Event.count }.from(0).to(1)
+ end
end
+ end
- describe '#expired_leave_project' do
- subject { service.expired_leave_project(project, user) }
+ describe '#expired_leave_project' do
+ subject(:expired_leave_project) { service.expired_leave_project(project, user) }
- it { is_expected.to be_truthy }
- it { expect { subject }.to change { Event.count }.from(0).to(1) }
+ it { is_expected.to be_truthy }
+
+ specify do
+ expect { expired_leave_project }.to change { Event.count }.from(0).to(1)
end
end
diff --git a/spec/services/notification_service_spec.rb b/spec/services/notification_service_spec.rb
index 910e1d85a6b..15e7f794795 100644
--- a/spec/services/notification_service_spec.rb
+++ b/spec/services/notification_service_spec.rb
@@ -3294,31 +3294,6 @@ RSpec.describe NotificationService, :mailer, feature_category: :team_planning do
let(:source) { group }
end
end
-
- describe '#new_group_member' do
- let(:group) { create(:group) }
-
- it 'sends a notification' do
- group.add_guest(added_user)
- should_only_email(added_user)
- end
-
- describe 'when notifications are disabled' do
- before do
- create_global_setting_for(added_user, :disabled)
- end
-
- it 'does not send a notification' do
- group.add_guest(added_user)
- should_not_email_anyone
- end
- end
-
- it_behaves_like 'group emails are disabled' do
- let(:notification_target) { group }
- let(:notification_trigger) { group.add_guest(added_user) }
- end
- end
end
describe 'ProjectMember', :deliver_mails_inline do
@@ -3448,29 +3423,6 @@ RSpec.describe NotificationService, :mailer, feature_category: :team_planning do
end
end
- describe '#new_project_member' do
- it do
- create_member!
- should_only_email(added_user)
- end
-
- it_behaves_like 'project emails are disabled' do
- let(:notification_target) { project }
- let(:notification_trigger) { create_member! }
- end
-
- context 'when notifications are disabled' do
- before do
- create_global_setting_for(added_user, :disabled)
- end
-
- it do
- create_member!
- should_not_email_anyone
- end
- end
- end
-
describe '#member_about_to_expire' do
let_it_be(:group_member) { create(:group_member, expires_at: 7.days.from_now.to_date) }
let_it_be(:project_member) { create(:project_member, expires_at: 7.days.from_now.to_date) }
@@ -3491,9 +3443,56 @@ RSpec.describe NotificationService, :mailer, feature_category: :team_planning do
end
end
end
+ end
+
+ describe '#new_member', :deliver_mails_inline do
+ let_it_be(:source) { create(:group) }
+ let_it_be(:added_user) { create(:user) }
+
+ subject(:new_member) { notification.new_member(member) }
+
+ shared_examples_for 'new member added' do |source_type|
+ it 'triggers a notification about about the added access', deliver_mails_inline: false do
+ new_member
- def create_member!
- create(:project_member, user: added_user, project: project)
+ expect_delivery_jobs_count(1)
+ expect_enqueud_email(source_type, member.id, mail: 'member_access_granted_email')
+ end
+ end
+
+ context 'when source is a Group' do
+ it_behaves_like 'new member added', 'Group' do
+ let_it_be(:member) { create(:group_member, source: source) }
+ end
+
+ it_behaves_like 'group emails are disabled' do
+ let(:notification_target) { source }
+ let(:notification_trigger) { notification_target.add_guest(added_user) }
+ end
+ end
+
+ context 'when source is a Project' do
+ let_it_be(:source) { create(:project) }
+
+ it_behaves_like 'new member added', 'Project' do
+ let_it_be(:member) { create(:project_member, source: project) }
+ end
+
+ it_behaves_like 'project emails are disabled' do
+ let_it_be(:notification_target) { source }
+ let(:notification_trigger) { source.add_guest(added_user) }
+ end
+ end
+
+ context 'when notifications are disabled' do
+ before do
+ create_global_setting_for(added_user, :disabled)
+ end
+
+ it 'does not send a notification' do
+ source.add_guest(added_user)
+ should_not_email_anyone
+ end
end
end
diff --git a/spec/support/helpers/features/invite_members_modal_helpers.rb b/spec/support/helpers/features/invite_members_modal_helpers.rb
index c40e060bc8e..fd37abd7381 100644
--- a/spec/support/helpers/features/invite_members_modal_helpers.rb
+++ b/spec/support/helpers/features/invite_members_modal_helpers.rb
@@ -66,6 +66,7 @@ module Features
def choose_options(role, expires_at)
page.within role_dropdown_selector do
+ wait_for_requests
toggle_listbox
select_listbox_item(role, exact_text: true)
end
diff --git a/spec/support/helpers/stub_configuration.rb b/spec/support/helpers/stub_configuration.rb
index e043d1249b9..f76a208fee3 100644
--- a/spec/support/helpers/stub_configuration.rb
+++ b/spec/support/helpers/stub_configuration.rb
@@ -120,6 +120,10 @@ module StubConfiguration
.to receive(:sentry_clientside_dsn) { clientside_dsn }
end
+ def clear_sentry_settings
+ Sentry.get_current_scope.clear
+ end
+
def stub_microsoft_graph_mailer_setting(messages)
allow(Gitlab.config.microsoft_graph_mailer).to receive_messages(to_settings(messages))
end
diff --git a/spec/support/shared_examples/models/members_notifications_shared_example.rb b/spec/support/shared_examples/models/members_notifications_shared_example.rb
index 17dc927f3cc..58ce3daec40 100644
--- a/spec/support/shared_examples/models/members_notifications_shared_example.rb
+++ b/spec/support/shared_examples/models/members_notifications_shared_example.rb
@@ -9,16 +9,6 @@ RSpec.shared_examples 'members notifications' do |entity_type|
allow(member).to receive(:notification_service).and_return(notification_service)
end
- describe "#after_create" do
- let(:member) { build(:"#{entity_type}_member", "#{entity_type}": create(entity_type.to_s), user: user) }
-
- it "sends email to user" do
- expect(notification_service).to receive(:"new_#{entity_type}_member").with(member)
-
- member.save!
- end
- end
-
describe '#after_commit' do
context 'on creation of a member requesting access' do
let(:member) do
@@ -37,7 +27,7 @@ RSpec.shared_examples 'members notifications' do |entity_type|
let(:member) { create(:"#{entity_type}_member", :access_request) }
it "calls NotificationService.new_#{entity_type}_member" do
- expect(notification_service).to receive(:"new_#{entity_type}_member").with(member)
+ expect(notification_service).to receive(:new_member).with(member)
member.accept_request(create(:user))
end
diff --git a/yarn.lock b/yarn.lock
index e08e84f60ce..d53728d3b1b 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1274,10 +1274,10 @@
resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-3.74.0.tgz#b6b41be65b9e70378c0cef0435f96edd5467e759"
integrity sha512-eHoywPSLrYb+I/IYGapei2Tum5vLtgWkFxN0fxmUUAnBnxFSA+67aheI33kQVV3WjANuZGkglfPBX3QAmN8BLA==
-"@gitlab/ui@^72.3.0":
- version "72.3.0"
- resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-72.3.0.tgz#8c5ab2f5ab3386c2a9b2800f498677e486133754"
- integrity sha512-E8Fbi9PAdy1UEdnyv2kO4997MINkp17PRCNpRvgzIYgiGCZsfiuFab4q2m3UOLe29z25neiTKk5YYABrpQLxWg==
+"@gitlab/ui@^72.3.1":
+ version "72.3.1"
+ resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-72.3.1.tgz#da3d3fcde275d30f98e913d2068f69ae559b0216"
+ integrity sha512-BBeVIF1TlM0br16CPspaFg8p9WDF7DwpwM44N8VYXMLe5wTF3AgKh8bk0qJurHF9D+KNco1yqbX+6oB4tIN4sQ==
dependencies:
"@floating-ui/dom" "1.2.9"
bootstrap-vue "2.23.1"
@@ -4582,10 +4582,10 @@ core-js-pure@^3.0.0:
resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.6.5.tgz#c79e75f5e38dbc85a662d91eea52b8256d53b813"
integrity sha512-lacdXOimsiD0QyNf9BC/mxivNJ/ybBGJXQFKzRekp1WTHoVUWsUHEn+2T8GJAzzIhyOuXA+gOxCVN3l+5PLPUA==
-core-js@^3.29.1, core-js@^3.34.0, core-js@^3.6.5:
- version "3.34.0"
- resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.34.0.tgz#5705e6ad5982678612e96987d05b27c6c7c274a5"
- integrity sha512-aDdvlDder8QmY91H88GzNi9EtQi2TjvQhpCX6B1v/dAZHU1AuLgHvRh54RiOerpEhEW46Tkf+vgAViB/CWC0ag==
+core-js@^3.29.1, core-js@^3.35.0, core-js@^3.6.5:
+ version "3.35.0"
+ resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.35.0.tgz#58e651688484f83c34196ca13f099574ee53d6b4"
+ integrity sha512-ntakECeqg81KqMueeGJ79Q5ZgQNR+6eaE8sxGCx62zMbAIj65q+uYvatToew3m6eAGdU4gNZwpZ34NMe4GYswg==
core-util-is@~1.0.0:
version "1.0.3"