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

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2023-12-07 12:11:28 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2023-12-07 12:11:28 +0300
commit0125f11d6bf7af5817dce9d87a116e2ed6bd1917 (patch)
tree0eb487e65b56a8f0e672b423c0d63948e1e5cb69
parentc6d5d2148e1e1446c175b5f9a22a4b8c4fd62819 (diff)
Add latest changes from gitlab-org/gitlab@master
-rw-r--r--.gitlab/CODEOWNERS2
-rw-r--r--.gitlab/ci/test-on-gdk/main.gitlab-ci.yml3
-rw-r--r--.rubocop_todo/rspec/feature_category.yml1
-rw-r--r--app/assets/javascripts/diffs/components/app.vue2
-rw-r--r--app/controllers/clusters/agents/dashboard_controller.rb6
-rw-r--r--app/graphql/resolvers/analytics/cycle_analytics/stages_resolver.rb17
-rw-r--r--app/models/concerns/analytics/cycle_analytics/stageable.rb1
-rw-r--r--app/models/concerns/ci/deployable.rb8
-rw-r--r--app/views/clusters/agents/dashboard/index.html.haml12
-rw-r--r--app/workers/environments/auto_stop_cron_worker.rb1
-rw-r--r--config/metrics/counts_all/20231204142552_service_desk_custom_email_enabled.yml21
-rw-r--r--config/routes.rb1
-rw-r--r--db/docs/batched_background_migrations/backfill_design_management_repositories.yml1
-rw-r--r--db/migrate/20231204144300_add_index_service_desk_settings_on_custom_email_enabled.rb17
-rw-r--r--db/post_migrate/20231206145911_finalize_backfill_design_management_repositories.rb21
-rw-r--r--db/schema_migrations/202312041443001
-rw-r--r--db/schema_migrations/202312061459111
-rw-r--r--db/structure.sql2
-rw-r--r--doc/user/project/members/index.md173
-rw-r--r--lib/gitlab/bitbucket_server_import/importers/pull_request_notes_importer.rb23
-rw-r--r--lib/gitlab/usage/metrics/instrumentations/count_service_desk_custom_email_enabled_metric.rb17
-rw-r--r--locale/gitlab.pot17
-rw-r--r--spec/lib/gitlab/bitbucket_server_import/importers/pull_request_notes_importer_spec.rb19
-rw-r--r--spec/lib/gitlab/usage/metrics/instrumentations/count_service_desk_custom_email_enabled_metric_spec.rb16
-rw-r--r--spec/requests/clusters/agents/dashboard_controller_spec.rb28
-rw-r--r--spec/support/rspec_order_todo.yml1
-rw-r--r--spec/support/shared_examples/ci/deployable_shared_examples.rb22
-rw-r--r--spec/support/shared_examples/models/cycle_analytics_stage_shared_examples.rb13
-rw-r--r--spec/workers/environments/auto_stop_cron_worker_spec.rb8
29 files changed, 311 insertions, 144 deletions
diff --git a/.gitlab/CODEOWNERS b/.gitlab/CODEOWNERS
index 06b045c84a7..20780999698 100644
--- a/.gitlab/CODEOWNERS
+++ b/.gitlab/CODEOWNERS
@@ -968,6 +968,7 @@ lib/gitlab/checks/**
/config/initializers/declarative_policy_cached_attributes.rb
/app/policies/
/ee/app/policies/
+/ee/app/models/members/member_role.rb
/ee/app/services/member_roles/
/ee/app/graphql/types/member_roles/
/ee/app/graphql/mutations/member_roles/
@@ -1148,7 +1149,6 @@ lib/gitlab/checks/**
/ee/app/models/concerns/password_complexity.rb
/ee/app/models/ee/personal_access_token.rb
/ee/app/models/ee/project_authorization.rb
-/ee/app/models/members/member_role.rb
/ee/app/models/scim_oauth_access_token.rb
/ee/app/serializers/scim_oauth_access_token_entity.rb
/ee/app/services/arkose/token_verification_service.rb
diff --git a/.gitlab/ci/test-on-gdk/main.gitlab-ci.yml b/.gitlab/ci/test-on-gdk/main.gitlab-ci.yml
index 5493391971f..73bd2838182 100644
--- a/.gitlab/ci/test-on-gdk/main.gitlab-ci.yml
+++ b/.gitlab/ci/test-on-gdk/main.gitlab-ci.yml
@@ -62,6 +62,9 @@ include:
GDK_URL: http://gdk.test:3000
KNAPSACK_TEST_FILE_PATTERN: "qa/specs/features/**/*_spec.rb"
QA_SUITE_STATUS_ENV_FILE: "$CI_PROJECT_DIR/suite_status.env"
+ # Workaround to avoid enabling feature flags unintentionally
+ # See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/137890#note_1681217315
+ QA_FEATURE_FLAGS: ""
before_script:
- echo "SUITE_RAN=true" > "$QA_SUITE_STATUS_ENV_FILE"
- echo -e "\e[0Ksection_start:`date +%s`:pull_image[collapsed=true]\r\e[0KPull GDK QA image"
diff --git a/.rubocop_todo/rspec/feature_category.yml b/.rubocop_todo/rspec/feature_category.yml
index 346e259b4dd..20f9cd77113 100644
--- a/.rubocop_todo/rspec/feature_category.yml
+++ b/.rubocop_todo/rspec/feature_category.yml
@@ -1200,7 +1200,6 @@ RSpec/FeatureCategory:
- 'ee/spec/presenters/project_member_presenter_spec.rb'
- 'ee/spec/presenters/security/scan_presenter_spec.rb'
- 'ee/spec/presenters/subscription_presenter_spec.rb'
- - 'ee/spec/presenters/subscriptions/new_plan_presenter_spec.rb'
- 'ee/spec/presenters/vulnerability_presenter_spec.rb'
- 'ee/spec/presenters/web_hooks/group/hook_presenter_spec.rb'
- 'ee/spec/requests/admin/credentials_controller_spec.rb'
diff --git a/app/assets/javascripts/diffs/components/app.vue b/app/assets/javascripts/diffs/components/app.vue
index f51f00591f0..33931f81a6d 100644
--- a/app/assets/javascripts/diffs/components/app.vue
+++ b/app/assets/javascripts/diffs/components/app.vue
@@ -440,7 +440,7 @@ export default {
fetchScannerFindingsError() {
this.hasScannerError = true;
createAlert({
- message: __('Something went wrong fetching the Scanner Findings. Please try again.'),
+ message: __('Something went wrong fetching the scanner findings. Please try again.'),
});
},
subscribeToEvents() {
diff --git a/app/controllers/clusters/agents/dashboard_controller.rb b/app/controllers/clusters/agents/dashboard_controller.rb
index 6299b1740c3..7016ebacfba 100644
--- a/app/controllers/clusters/agents/dashboard_controller.rb
+++ b/app/controllers/clusters/agents/dashboard_controller.rb
@@ -6,12 +6,14 @@ module Clusters
include KasCookie
before_action :check_feature_flag!
- before_action :find_agent
- before_action :authorize_read_cluster_agent!
+ before_action :find_agent, only: [:show], if: -> { current_user }
+ before_action :authorize_read_cluster_agent!, only: [:show], if: -> { current_user }
before_action :set_kas_cookie, only: [:show], if: -> { current_user }
feature_category :deployment_management
+ def index; end
+
def show; end
private
diff --git a/app/graphql/resolvers/analytics/cycle_analytics/stages_resolver.rb b/app/graphql/resolvers/analytics/cycle_analytics/stages_resolver.rb
index d14aae7002e..7f82c3dbada 100644
--- a/app/graphql/resolvers/analytics/cycle_analytics/stages_resolver.rb
+++ b/app/graphql/resolvers/analytics/cycle_analytics/stages_resolver.rb
@@ -7,14 +7,17 @@ module Resolvers
type [Types::Analytics::CycleAnalytics::ValueStreams::StageType], null: true
def resolve
- response =
- ::Analytics::CycleAnalytics::Stages::ListService.new(
- parent: namespace,
- current_user: current_user,
- params: { value_stream: object }
- ).execute
+ list_stages({ value_stream: object })
+ end
+
+ private
- response[:stages]
+ def list_stages(list_service_params)
+ ::Analytics::CycleAnalytics::Stages::ListService.new(
+ parent: namespace,
+ current_user: current_user,
+ params: list_service_params
+ ).execute[:stages]
end
def namespace
diff --git a/app/models/concerns/analytics/cycle_analytics/stageable.rb b/app/models/concerns/analytics/cycle_analytics/stageable.rb
index d1dd46883e3..5cdfa32b796 100644
--- a/app/models/concerns/analytics/cycle_analytics/stageable.rb
+++ b/app/models/concerns/analytics/cycle_analytics/stageable.rb
@@ -31,6 +31,7 @@ module Analytics
scope :with_preloaded_labels, -> { includes(:start_event_label, :end_event_label) }
scope :for_list, -> { with_preloaded_labels.ordered }
scope :by_value_stream, ->(value_stream) { where(value_stream_id: value_stream.id) }
+ scope :by_value_streams_ids, ->(value_stream_ids) { where(value_stream_id: value_stream_ids) }
before_save :ensure_stage_event_hash_id
after_commit :cleanup_old_stage_event_hash
diff --git a/app/models/concerns/ci/deployable.rb b/app/models/concerns/ci/deployable.rb
index 844c8a1fa7d..e8c4f10f1ca 100644
--- a/app/models/concerns/ci/deployable.rb
+++ b/app/models/concerns/ci/deployable.rb
@@ -18,14 +18,6 @@ module Ci
end
end
- after_transition any => [:failed] do |job|
- next unless job.stops_environment?
-
- job.run_after_commit do
- Environments::StopJobFailedWorker.perform_async(id)
- end
- end
-
# Synchronize Deployment Status
# Please note that the data integrity is not assured because we can't use
# a database transaction due to DB decomposition.
diff --git a/app/views/clusters/agents/dashboard/index.html.haml b/app/views/clusters/agents/dashboard/index.html.haml
new file mode 100644
index 00000000000..00382166469
--- /dev/null
+++ b/app/views/clusters/agents/dashboard/index.html.haml
@@ -0,0 +1,12 @@
+- breadcrumb_title s_('KubernetesDashboard|Kubernetes Dashboard')
+- page_title s_('KubernetesDashboard|Kubernetes Dashboard')
+
+= render Pajamas::EmptyStateComponent.new(svg_path: 'illustrations/empty-state/empty-search-md.svg',
+ title: s_("KubernetesDashboard|No agent selected"),
+ primary_button_text: s_("KubernetesDashboard|View projects"),
+ primary_button_link: dashboard_projects_path,
+ secondary_button_text: s_("KubernetesDashboard|Learn more"),
+ secondary_button_link: help_page_path('ci/environments/kubernetes_dashboard')) do |c|
+
+ - c.with_description do
+ = s_("KubernetesDashboard|You can select an agent from a project's environment page.")
diff --git a/app/workers/environments/auto_stop_cron_worker.rb b/app/workers/environments/auto_stop_cron_worker.rb
index 26b18c406e5..4d6453a85e7 100644
--- a/app/workers/environments/auto_stop_cron_worker.rb
+++ b/app/workers/environments/auto_stop_cron_worker.rb
@@ -13,7 +13,6 @@ module Environments
def perform
AutoStopService.new.execute
- AutoRecoverService.new.execute
end
end
end
diff --git a/config/metrics/counts_all/20231204142552_service_desk_custom_email_enabled.yml b/config/metrics/counts_all/20231204142552_service_desk_custom_email_enabled.yml
new file mode 100644
index 00000000000..d577c3b5b9f
--- /dev/null
+++ b/config/metrics/counts_all/20231204142552_service_desk_custom_email_enabled.yml
@@ -0,0 +1,21 @@
+---
+key_path: counts.service_desk_custom_email_enabled
+description: "Number of projects that have Service Desk custom email enabled"
+product_section: seg
+product_stage: service management
+product_group: respond
+value_type: number
+status: active
+milestone: "16.7"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/138662
+time_frame: all
+data_source: database
+data_category: optional
+instrumentation_class: CountServiceDeskCustomEmailEnabledMetric
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/routes.rb b/config/routes.rb
index fc6a7a37715..18c3e257f8e 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -110,6 +110,7 @@ InitializerConnections.raise_if_new_database_connection do
scope module: 'clusters' do
scope module: 'agents' do
+ get '/kubernetes', to: 'dashboard#index', as: 'kubernetes_dashboard_index'
get '/kubernetes/:agent_id(/*vueroute)', to: 'dashboard#show', as: 'kubernetes_dashboard'
end
end
diff --git a/db/docs/batched_background_migrations/backfill_design_management_repositories.yml b/db/docs/batched_background_migrations/backfill_design_management_repositories.yml
index cc4bf593f47..0bca97d9868 100644
--- a/db/docs/batched_background_migrations/backfill_design_management_repositories.yml
+++ b/db/docs/batched_background_migrations/backfill_design_management_repositories.yml
@@ -4,3 +4,4 @@ description: Backfills the new table with project ids
feature_category: geo_replication
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/116975
milestone: '15.11'
+finalized_by: '20231206145911'
diff --git a/db/migrate/20231204144300_add_index_service_desk_settings_on_custom_email_enabled.rb b/db/migrate/20231204144300_add_index_service_desk_settings_on_custom_email_enabled.rb
new file mode 100644
index 00000000000..22c8c196234
--- /dev/null
+++ b/db/migrate/20231204144300_add_index_service_desk_settings_on_custom_email_enabled.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+class AddIndexServiceDeskSettingsOnCustomEmailEnabled < Gitlab::Database::Migration[2.2]
+ milestone '16.7'
+
+ disable_ddl_transaction!
+
+ INDEX_NAME = 'index_service_desk_settings_on_custom_email_enabled'
+
+ def up
+ add_concurrent_index :service_desk_settings, :custom_email_enabled, name: INDEX_NAME
+ end
+
+ def down
+ remove_concurrent_index_by_name :service_desk_settings, INDEX_NAME
+ end
+end
diff --git a/db/post_migrate/20231206145911_finalize_backfill_design_management_repositories.rb b/db/post_migrate/20231206145911_finalize_backfill_design_management_repositories.rb
new file mode 100644
index 00000000000..74e8f8d0831
--- /dev/null
+++ b/db/post_migrate/20231206145911_finalize_backfill_design_management_repositories.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+class FinalizeBackfillDesignManagementRepositories < Gitlab::Database::Migration[2.2]
+ milestone '16.7'
+
+ disable_ddl_transaction!
+
+ restrict_gitlab_migration gitlab_schema: :gitlab_main_cell
+
+ def up
+ ensure_batched_background_migration_is_finished(
+ job_class_name: 'BackfillDesignManagementRepositories',
+ table_name: :projects,
+ column_name: :id,
+ job_arguments: [],
+ finalize: true
+ )
+ end
+
+ def down; end
+end
diff --git a/db/schema_migrations/20231204144300 b/db/schema_migrations/20231204144300
new file mode 100644
index 00000000000..a69b0278d5a
--- /dev/null
+++ b/db/schema_migrations/20231204144300
@@ -0,0 +1 @@
+385471e69c2099130d0758d2fe6ac27b9211204759de04f3fc0a79b84b5a1633 \ No newline at end of file
diff --git a/db/schema_migrations/20231206145911 b/db/schema_migrations/20231206145911
new file mode 100644
index 00000000000..52eccecb3b0
--- /dev/null
+++ b/db/schema_migrations/20231206145911
@@ -0,0 +1 @@
+85f2275f2b6d0dedfdd0b53b1a6e757f059db73ffe07ae7e5a35c70f9a6194f5 \ No newline at end of file
diff --git a/db/structure.sql b/db/structure.sql
index e70b76c9ae4..624e48560c4 100644
--- a/db/structure.sql
+++ b/db/structure.sql
@@ -34579,6 +34579,8 @@ CREATE INDEX index_service_desk_custom_email_verifications_on_triggerer_id ON se
CREATE INDEX index_service_desk_enabled_projects_on_id_creator_id_created_at ON projects USING btree (id, creator_id, created_at) WHERE (service_desk_enabled = true);
+CREATE INDEX index_service_desk_settings_on_custom_email_enabled ON service_desk_settings USING btree (custom_email_enabled);
+
CREATE INDEX index_service_desk_settings_on_file_template_project_id ON service_desk_settings USING btree (file_template_project_id);
CREATE UNIQUE INDEX index_shards_on_name ON shards USING btree (name);
diff --git a/doc/user/project/members/index.md b/doc/user/project/members/index.md
index effe9efa918..c1a73e63e29 100644
--- a/doc/user/project/members/index.md
+++ b/doc/user/project/members/index.md
@@ -17,9 +17,9 @@ Users can become members of a group or project in different ways, which define t
| Membership type | Membership process |
| --------------------------------------------- | ------------------ |
| [Direct](#add-users-to-a-project) | The user is added directly to the current group or project. |
-| [Inherited](#inherited-membership) | The user is a member of an ancestor group or project that is added to the current group or project. |
+| [Inherited](#inherited-membership) | The user is a member of a parent group that contains the current group or project. |
| [Direct shared](share_project_with_groups.md) | The user is a member of a group or project that is shared into the current group or project. |
-| [Inherited shared](../../group/manage.md#share-a-group-with-another-group) | The user is a member of an ancestor of a group or project that is shared into the current group or project. |
+| [Inherited shared](../../group/manage.md#share-a-group-with-another-group) | The user is a member of a parent of a group or project that is shared into the current group or project. |
```mermaid
flowchart RL
@@ -45,64 +45,6 @@ flowchart RL
G-->|Group C shared with Project A|E
```
-### Inherited membership
-
-When your project belongs to a group, project members inherit their role
-from the group.
-
-![Project members page](img/project_members_v14_4.png)
-
-In this example:
-
-- Three members have access to the project.
-- **User 0** is a Reporter and has inherited their role in the project from the **demo** group,
- which contains the project.
-- **User 1** belongs directly to the project. In the **Source** column, they are listed
- as a **Direct member**.
-- **Administrator** is the [Owner](../../permissions.md) and member of all groups.
- They have inherited their role in the project from the **demo** group.
-
-If a user is:
-
-- A direct member of a project, the **Expiration** and **Max role** fields can be updated directly on the project.
-- An inherited member from a parent group, the **Expiration** and **Max role** fields must be updated on the parent group.
-
-### Membership and visibility rights
-
-Depending on their membership type, members of groups or projects are granted different [visibility levels](../../../user/public_access.md)
-and rights into the group or project.
-
-| Action | Direct group member | Inherited group member | Direct shared group member | Inherited shared group member |
-| --- | ------------------- | ---------------------- | -------------------------- | ----------------------------- |
-| Generate boards | ✓ | ✓ | ✓ | ✓ |
-| View issues of groups higher in the hierarchy | ✓ | ✓ | ✓ | ✓ |
-| View labels of groups higher in the hierarchy | ✓ | ✓ | ✓ | ✓ |
-| View milestones of groups higher in the hierarchy | ✓ | ✓ | ✓ | ✓ |
-| Be shared into other groups | ✓ | | | |
-| Be shared into other projects | ✓ | ✓ | ✓ | ✓ |
-| Share the group with other members | ✓ | ✓ | ✓ | ✓ |
-
-In the following example, `User` is a:
-
-- Direct member of `subgroup`.
-- Inherited member of `subsubgroup`.
-- Indirect member of `subgroup-2` and `subgroup-3`.
-- Indirect inherited member of `subsubgroup-2` and `subsubgroup-3`.
-
-```mermaid
-graph TD
- classDef user stroke:green,color:green;
-
- root --> subgroup --> subsubgroup
- root-2 --> subgroup-2 --> subsubgroup-2
- root-3 --> subgroup-3 --> subsubgroup-3
- subgroup -. shared .-> subgroup-2 -. shared .-> subgroup-3
-
- User-. member .- subgroup
-
- class User user
-```
-
## Add users to a project
> - [Changed](https://gitlab.com/gitlab-org/gitlab/-/issues/247208) in GitLab 13.11 from a form to a modal window [with a flag](../../feature_flags.md). Disabled by default.
@@ -159,6 +101,28 @@ role for the group. For example, the maximum role you can set is:
In GitLab 14.8 and earlier, direct members of a project have a maximum role of Maintainer.
The Owner [role](../../permissions.md#project-members-permissions) can be added for the group only.
+## Inherited membership
+
+When your project belongs to a group, project members inherit their role
+from the group.
+
+![Project members page](img/project_members_v14_4.png)
+
+In this example:
+
+- Three members have access to the project.
+- **User 0** is a Reporter and has inherited their role in the project from the **demo** group,
+ which contains the project.
+- **User 1** has been added directly to the project. In the **Source** column, they are listed
+ as a **Direct member**.
+- **Administrator** is the [Owner](../../permissions.md) and member of all groups.
+ They have inherited their role in the project from the **demo** group.
+
+If a user is:
+
+- A direct member of a project, the **Expiration** and **Max role** fields can be updated directly on the project.
+- An inherited member from a parent group, the **Expiration** and **Max role** fields must be updated on the parent group that the member originates from.
+
## Add groups to a project
> - [Changed](https://gitlab.com/gitlab-org/gitlab/-/issues/247208) in GitLab 13.11 from a form to a modal window [with a flag](../../feature_flags.md). Disabled by default.
@@ -190,18 +154,26 @@ To add a group to a project:
From that date onward, the group can no longer access the project.
1. Select **Invite**.
-The members of the invited group are not displayed on the **Members** tab.
+The invited group is displayed on the **Groups** tab.
Private groups are masked from unauthorized users.
+The members of the invited group are not displayed on the **Members** tab.
The **Members** tab shows:
-- Members who are directly assigned to the project.
-- If the project was created in a group [namespace](../../namespace/index.md), members of that group.
+- Members who were directly added to the project.
+- Inherited members of the group [namespace](../../namespace/index.md) that the project was added to.
+
+## Share a project with a group
+
+Instead of adding users one by one, you can [share a project with an entire group](share_project_with_groups.md).
## Import members from another project
-You can import another project's members to your own project.
+You can import another project's direct members to your own project.
Imported project members retain the same permissions as the project you import them from.
+NOTE:
+Only direct members of a project are imported. Inherited or shared members of a project are not imported.
+
Prerequisites:
- You must have the Maintainer or Owner role.
@@ -220,7 +192,7 @@ To import a project's members:
1. Select **Import project members**.
If the import is successful, a success message is displayed.
-To view the imported members, refresh the page.
+To view the imported members on the **Members** tab, refresh the page.
## Remove a member from a project
@@ -274,18 +246,18 @@ To avoid this problem, GitLab administrators can:
You can filter and sort members in a project.
-### Display inherited members
+### Display direct members
1. On the left sidebar, select **Search or go to** and find your project.
1. Select **Manage > Members**.
-1. In the **Filter members** box, select `Membership` `=` `Inherited`.
+1. In the **Filter members** box, select `Membership` `=` `Direct`.
1. Press <kbd>Enter</kbd>.
-### Display direct members
+### Display inherited members
1. On the left sidebar, select **Search or go to** and find your project.
1. Select **Manage > Members**.
-1. In the **Filter members** box, select `Membership` `=` `Direct`.
+1. In the **Filter members** box, select `Membership` `=` `Inherited`.
1. Press <kbd>Enter</kbd>.
### Search for members in a project
@@ -323,13 +295,13 @@ GitLab users can request to become a member of a project.
![Request access button](img/request_access_button.png)
-An email is sent to the most recently active project maintainers or owners.
-Up to ten project maintainers or owners are notified.
-Any project owner or maintainer can approve or decline the request.
-Project maintainers cannot approve Owner role access requests.
+An email is sent to the most recently active project Maintainers or Owners.
+Up to ten project Maintainers or Owners are notified.
+Any project Owner or Maintainer can approve or decline the request.
+Project Maintainers cannot approve Owner role access requests.
-If a project does not have any direct owners or maintainers, the notification is sent to the
-most recently active owners of the project's group.
+If a project does not have any direct Owners or Maintainers, the notification is sent to the
+most recently active Owners of the project's parent group.
### Withdraw an access request to a project
@@ -345,7 +317,7 @@ You can prevent users from requesting access to a project.
Prerequisites:
-- You must be the project owner.
+- You must have the Owner role for the project.
1. On the left sidebar, select **Search or go to** and find your project.
1. Select **Settings > General**.
@@ -353,6 +325,51 @@ Prerequisites:
1. Under **Project visibility**, select **Users can request access**.
1. Select **Save changes**.
-## Share a project with a group
+## Membership and visibility rights
-Instead of adding users one by one, you can [share a project with an entire group](share_project_with_groups.md).
+Depending on their membership type, members of groups or projects are granted different [visibility levels](../../../user/public_access.md)
+and rights into the group or project.
+
+The following table lists the membership and visibility rights of project members.
+
+| Action | Direct project member | Inherited project member | Direct shared project member | Inherited shared project member |
+| --- | ------------------- | ---------------------- | -------------------------- | ----------------------------- |
+| Generate boards | **{check-circle}** Yes | **{check-circle}** Yes | **{check-circle}** Yes | **{check-circle}** Yes |
+| View issues of parent groups | **{check-circle}** Yes | **{check-circle}** Yes | **{check-circle}** Yes | **{check-circle}** Yes |
+| View labels of parent groups | **{check-circle}** Yes | **{check-circle}** Yes | **{check-circle}** Yes | **{check-circle}** Yes |
+| View milestones of parent groups | **{check-circle}** Yes | **{check-circle}** Yes | **{check-circle}** Yes | **{check-circle}** Yes |
+| Be shared into other groups | **{check-circle}** Yes | **{dotted-circle}** No | **{dotted-circle}** No | **{dotted-circle}** No|
+| Be imported into other projects | **{check-circle}** Yes | **{dotted-circle}** No | **{dotted-circle}** No | **{dotted-circle}** No |
+| Share the project with other members | **{check-circle}** Yes | **{check-circle}** Yes | **{check-circle}** Yes | **{check-circle}** Yes |
+
+The following table lists the membership and visibility rights of group members.
+
+| Action | Direct group member | Inherited group member | Direct shared group member | Inherited shared group member |
+| --- | ------------------- | ---------------------- | -------------------------- | ----------------------------- |
+| Generate boards | **{check-circle}** Yes | **{check-circle}** Yes | **{check-circle}** Yes | **{check-circle}** Yes |
+| View issues of parent groups | **{check-circle}** Yes | **{check-circle}** Yes | **{check-circle}** Yes | **{check-circle}** Yes |
+| View labels of parent groups | **{check-circle}** Yes | **{check-circle}** Yes | **{check-circle}** Yes | **{check-circle}** Yes |
+| View milestones of parent groups | **{check-circle}** Yes | **{check-circle}** Yes | **{check-circle}** Yes | **{check-circle}** Yes |
+| Be shared into other groups | **{check-circle}** Yes | **{dotted-circle}** No | **{dotted-circle}** No | **{dotted-circle}** No |
+| Be shared into other projects | **{check-circle}** Yes | **{check-circle}** Yes | **{check-circle}** Yes | **{check-circle}** Yes |
+| Share the group with other members | **{check-circle}** Yes | **{check-circle}** Yes | **{check-circle}** Yes | **{check-circle}** Yes |
+
+In the following example, `User` is a:
+
+- Direct member of `subgroup`.
+- Inherited member of `subsubgroup`.
+- Indirect member of `subgroup-2` and `subgroup-3`.
+- Indirect inherited member of `subsubgroup-2` and `subsubgroup-3`.
+
+```mermaid
+graph TD
+ classDef user stroke:green,color:green;
+
+ root --> subgroup --> subsubgroup
+ root-2 --> subgroup-2 --> subsubgroup-2
+ root-3 --> subgroup-3 --> subsubgroup-3
+ subgroup -. shared .-> subgroup-2 -. shared .-> subgroup-3
+
+ User-. member .- subgroup
+
+ class User user
diff --git a/lib/gitlab/bitbucket_server_import/importers/pull_request_notes_importer.rb b/lib/gitlab/bitbucket_server_import/importers/pull_request_notes_importer.rb
index fdd3b50036f..aa54f19315a 100644
--- a/lib/gitlab/bitbucket_server_import/importers/pull_request_notes_importer.rb
+++ b/lib/gitlab/bitbucket_server_import/importers/pull_request_notes_importer.rb
@@ -9,17 +9,14 @@ module Gitlab
def initialize(project, hash)
@project = project
- @formatter = Gitlab::ImportFormatter.new
- @client = BitbucketServer::Client.new(project.import_data.credentials)
- @project_key = project.import_data.data['project_key']
- @repository_slug = project.import_data.data['repo_slug']
@user_finder = UserFinder.new(project)
-
- # TODO: Convert object into a object instead of using it as a hash
+ @formatter = Gitlab::ImportFormatter.new
@object = hash.with_indifferent_access
end
def execute
+ return unless project.import_data
+
log_info(import_stage: 'import_pull_request_notes', message: 'starting', iid: object[:iid])
merge_request = project.merge_requests.find_by(iid: object[:iid]) # rubocop: disable CodeReuse/ActiveRecord
@@ -46,7 +43,7 @@ module Gitlab
private
- attr_reader :object, :project, :formatter, :client, :project_key, :repository_slug, :user_finder
+ attr_reader :object, :project, :formatter, :user_finder
# rubocop: disable CodeReuse/ActiveRecord
def import_merge_event(merge_request, merge_event)
@@ -207,6 +204,18 @@ module Gitlab
updated_at: comment.updated_at
}
end
+
+ def client
+ BitbucketServer::Client.new(project.import_data.credentials)
+ end
+
+ def project_key
+ project.import_data.data['project_key']
+ end
+
+ def repository_slug
+ project.import_data.data['repo_slug']
+ end
end
end
end
diff --git a/lib/gitlab/usage/metrics/instrumentations/count_service_desk_custom_email_enabled_metric.rb b/lib/gitlab/usage/metrics/instrumentations/count_service_desk_custom_email_enabled_metric.rb
new file mode 100644
index 00000000000..85f59f36941
--- /dev/null
+++ b/lib/gitlab/usage/metrics/instrumentations/count_service_desk_custom_email_enabled_metric.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Usage
+ module Metrics
+ module Instrumentations
+ class CountServiceDeskCustomEmailEnabledMetric < DatabaseMetric
+ operation :count
+
+ relation do
+ ServiceDeskSetting.where(custom_email_enabled: true)
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index b8e2a0d39f2..34567a47cbe 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -27826,15 +27826,24 @@ msgstr ""
msgid "KubernetesDashboard|Kind"
msgstr ""
+msgid "KubernetesDashboard|Kubernetes Dashboard"
+msgstr ""
+
msgid "KubernetesDashboard|Labels"
msgstr ""
+msgid "KubernetesDashboard|Learn more"
+msgstr ""
+
msgid "KubernetesDashboard|Name"
msgstr ""
msgid "KubernetesDashboard|Namespace"
msgstr ""
+msgid "KubernetesDashboard|No agent selected"
+msgstr ""
+
msgid "KubernetesDashboard|Pending"
msgstr ""
@@ -27856,6 +27865,12 @@ msgstr ""
msgid "KubernetesDashboard|Succeeded"
msgstr ""
+msgid "KubernetesDashboard|View projects"
+msgstr ""
+
+msgid "KubernetesDashboard|You can select an agent from a project's environment page."
+msgstr ""
+
msgid "LDAP"
msgstr ""
@@ -45934,7 +45949,7 @@ msgstr ""
msgid "Something went wrong"
msgstr ""
-msgid "Something went wrong fetching the Scanner Findings. Please try again."
+msgid "Something went wrong fetching the scanner findings. Please try again."
msgstr ""
msgid "Something went wrong on our end"
diff --git a/spec/lib/gitlab/bitbucket_server_import/importers/pull_request_notes_importer_spec.rb b/spec/lib/gitlab/bitbucket_server_import/importers/pull_request_notes_importer_spec.rb
index ef0cf2a01fa..f063545a44c 100644
--- a/spec/lib/gitlab/bitbucket_server_import/importers/pull_request_notes_importer_spec.rb
+++ b/spec/lib/gitlab/bitbucket_server_import/importers/pull_request_notes_importer_spec.rb
@@ -79,9 +79,22 @@ RSpec.describe Gitlab::BitbucketServerImport::Importers::PullRequestNotesImporte
.to receive(:info).with(include(import_stage: stage, message: message))
end
- subject(:importer) { described_class.new(project, pull_request.to_hash) }
+ subject(:importer) { described_class.new(project.reload, pull_request.to_hash) }
+
+ describe '#execute' do
+ context 'when the project has been marked as failed' do
+ before do
+ project.import_state.mark_as_failed('error')
+ end
+
+ it 'does not log and does not import notes' do
+ expect(Gitlab::BitbucketServerImport::Logger)
+ .not_to receive(:info).with(include(import_stage: 'import_pull_request_notes', message: 'starting'))
+
+ expect { importer.execute }.not_to change { Note.count }
+ end
+ end
- describe '#execute', :clean_gitlab_redis_cache do
context 'when a matching merge request is not found' do
it 'does nothing' do
expect { importer.execute }.not_to change { Note.count }
@@ -95,7 +108,7 @@ RSpec.describe Gitlab::BitbucketServerImport::Importers::PullRequestNotesImporte
end
end
- context 'when a matching merge request is found' do
+ context 'when a matching merge request is found', :clean_gitlab_redis_cache do
let_it_be(:merge_request) { create(:merge_request, iid: pull_request.iid, source_project: project) }
it 'logs its progress' do
diff --git a/spec/lib/gitlab/usage/metrics/instrumentations/count_service_desk_custom_email_enabled_metric_spec.rb b/spec/lib/gitlab/usage/metrics/instrumentations/count_service_desk_custom_email_enabled_metric_spec.rb
new file mode 100644
index 00000000000..6d10052ff66
--- /dev/null
+++ b/spec/lib/gitlab/usage/metrics/instrumentations/count_service_desk_custom_email_enabled_metric_spec.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Usage::Metrics::Instrumentations::CountServiceDeskCustomEmailEnabledMetric, feature_category: :service_ping do
+ let_it_be(:project) { create(:project) }
+ let_it_be(:credential) { create(:service_desk_custom_email_credential, project: project) }
+ let_it_be(:verification) { create(:service_desk_custom_email_verification, :finished, project: project) }
+ let_it_be(:setting) do
+ create(:service_desk_setting, project: project, custom_email: 'support@example.com', custom_email_enabled: true)
+ end
+
+ let(:expected_value) { 1 }
+
+ it_behaves_like 'a correct instrumented metric value', { time_frame: 'all', data_source: 'database' }
+end
diff --git a/spec/requests/clusters/agents/dashboard_controller_spec.rb b/spec/requests/clusters/agents/dashboard_controller_spec.rb
index c3c16d9b385..bc7c964d47b 100644
--- a/spec/requests/clusters/agents/dashboard_controller_spec.rb
+++ b/spec/requests/clusters/agents/dashboard_controller_spec.rb
@@ -3,13 +3,35 @@
require 'spec_helper'
RSpec.describe Clusters::Agents::DashboardController, feature_category: :deployment_management do
+ let(:user) { create(:user) }
+ let(:stub_ff) { true }
+
+ describe 'GET index' do
+ before do
+ allow(::Gitlab::Kas).to receive(:enabled?).and_return(true)
+ stub_feature_flags(k8s_dashboard: stub_ff)
+ sign_in(user)
+ get kubernetes_dashboard_index_path
+ end
+
+ it 'returns ok and renders view' do
+ expect(response).to have_gitlab_http_status(:ok)
+ end
+
+ context 'with k8s_dashboard feature flag disabled' do
+ let(:stub_ff) { false }
+
+ it 'returns not found' do
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+ end
+
describe 'GET show' do
let_it_be(:organization) { create(:group) }
let_it_be(:agent_management_project) { create(:project, group: organization) }
let_it_be(:agent) { create(:cluster_agent, project: agent_management_project) }
let_it_be(:deployment_project) { create(:project, group: organization) }
- let(:user) { create(:user) }
- let(:stub_ff) { true }
before do
allow(::Gitlab::Kas).to receive(:enabled?).and_return(true)
@@ -37,7 +59,7 @@ RSpec.describe Clusters::Agents::DashboardController, feature_category: :deploym
).to be_present
end
- it 'returns not found' do
+ it 'returns ok' do
expect(response).to have_gitlab_http_status(:ok)
end
diff --git a/spec/support/rspec_order_todo.yml b/spec/support/rspec_order_todo.yml
index 3d86f726865..d6fa1d60dad 100644
--- a/spec/support/rspec_order_todo.yml
+++ b/spec/support/rspec_order_todo.yml
@@ -1884,7 +1884,6 @@
- './ee/spec/presenters/project_member_presenter_spec.rb'
- './ee/spec/presenters/security/scan_presenter_spec.rb'
- './ee/spec/presenters/subscription_presenter_spec.rb'
-- './ee/spec/presenters/subscriptions/new_plan_presenter_spec.rb'
- './ee/spec/presenters/vulnerabilities/finding_presenter_spec.rb'
- './ee/spec/presenters/vulnerability_presenter_spec.rb'
- './ee/spec/presenters/web_hooks/group/hook_presenter_spec.rb'
diff --git a/spec/support/shared_examples/ci/deployable_shared_examples.rb b/spec/support/shared_examples/ci/deployable_shared_examples.rb
index 0781eec1b4b..4f43d38e604 100644
--- a/spec/support/shared_examples/ci/deployable_shared_examples.rb
+++ b/spec/support/shared_examples/ci/deployable_shared_examples.rb
@@ -166,28 +166,6 @@ RSpec.shared_examples 'a deployable job' do
expect(deployment).to be_failed
end
-
- context 'when the job is a stop job' do
- before do
- job.update!(environment: 'review', options: { environment: { action: 'stop' } })
- end
-
- it 'enqueues Environments::StopJobFailedWorker' do
- expect(Environments::StopJobFailedWorker)
- .to receive(:perform_async)
-
- subject
- end
- end
-
- context 'when the job is not a stop job' do
- it 'does not enqueue Environments::StopJobFailedWorker' do
- expect(Environments::StopJobFailedWorker)
- .not_to receive(:perform_async)
-
- subject
- end
- end
end
context 'when transits to skipped' do
diff --git a/spec/support/shared_examples/models/cycle_analytics_stage_shared_examples.rb b/spec/support/shared_examples/models/cycle_analytics_stage_shared_examples.rb
index 3f532629961..9da130d2750 100644
--- a/spec/support/shared_examples/models/cycle_analytics_stage_shared_examples.rb
+++ b/spec/support/shared_examples/models/cycle_analytics_stage_shared_examples.rb
@@ -59,7 +59,9 @@ RSpec.shared_examples 'value stream analytics stage' do
it { expect(stage).not_to be_valid }
end
+ end
+ describe 'scopes' do
# rubocop: disable Rails/SaveBang
describe '.by_value_stream' do
it 'finds stages by value stream' do
@@ -71,6 +73,17 @@ RSpec.shared_examples 'value stream analytics stage' do
expect(result).to eq([stage1])
end
end
+
+ describe '.by_value_stream_ids' do
+ it 'finds stages by array of value streams ids' do
+ stages = create_list(factory, 2)
+ create(factory) # To be left out of the results
+
+ result = described_class.by_value_streams_ids(stages.map(&:value_stream_id))
+
+ expect(result).to match_array(stages)
+ end
+ end
# rubocop: enable Rails/SaveBang
end
diff --git a/spec/workers/environments/auto_stop_cron_worker_spec.rb b/spec/workers/environments/auto_stop_cron_worker_spec.rb
index 14a74022a1f..ad44cf97e07 100644
--- a/spec/workers/environments/auto_stop_cron_worker_spec.rb
+++ b/spec/workers/environments/auto_stop_cron_worker_spec.rb
@@ -14,12 +14,4 @@ RSpec.describe Environments::AutoStopCronWorker, feature_category: :continuous_d
subject
end
-
- it 'executes Environments::AutoRecoverService' do
- expect_next_instance_of(Environments::AutoRecoverService) do |service|
- expect(service).to receive(:execute)
- end
-
- subject
- end
end