From 0125f11d6bf7af5817dce9d87a116e2ed6bd1917 Mon Sep 17 00:00:00 2001 From: GitLab Bot Date: Thu, 7 Dec 2023 09:11:28 +0000 Subject: Add latest changes from gitlab-org/gitlab@master --- .gitlab/CODEOWNERS | 2 +- .gitlab/ci/test-on-gdk/main.gitlab-ci.yml | 3 + .rubocop_todo/rspec/feature_category.yml | 1 - app/assets/javascripts/diffs/components/app.vue | 2 +- .../clusters/agents/dashboard_controller.rb | 6 +- .../analytics/cycle_analytics/stages_resolver.rb | 17 +- .../analytics/cycle_analytics/stageable.rb | 1 + app/models/concerns/ci/deployable.rb | 8 - .../clusters/agents/dashboard/index.html.haml | 12 ++ app/workers/environments/auto_stop_cron_worker.rb | 1 - ...204142552_service_desk_custom_email_enabled.yml | 21 +++ config/routes.rb | 1 + .../backfill_design_management_repositories.yml | 1 + ...ervice_desk_settings_on_custom_email_enabled.rb | 17 ++ ...lize_backfill_design_management_repositories.rb | 21 +++ db/schema_migrations/20231204144300 | 1 + db/schema_migrations/20231206145911 | 1 + db/structure.sql | 2 + doc/user/project/members/index.md | 173 +++++++++++---------- .../importers/pull_request_notes_importer.rb | 23 ++- ...unt_service_desk_custom_email_enabled_metric.rb | 17 ++ locale/gitlab.pot | 17 +- .../importers/pull_request_notes_importer_spec.rb | 19 ++- ...ervice_desk_custom_email_enabled_metric_spec.rb | 16 ++ .../clusters/agents/dashboard_controller_spec.rb | 28 +++- spec/support/rspec_order_todo.yml | 1 - .../ci/deployable_shared_examples.rb | 22 --- .../cycle_analytics_stage_shared_examples.rb | 13 ++ .../environments/auto_stop_cron_worker_spec.rb | 8 - 29 files changed, 311 insertions(+), 144 deletions(-) create mode 100644 app/views/clusters/agents/dashboard/index.html.haml create mode 100644 config/metrics/counts_all/20231204142552_service_desk_custom_email_enabled.yml create mode 100644 db/migrate/20231204144300_add_index_service_desk_settings_on_custom_email_enabled.rb create mode 100644 db/post_migrate/20231206145911_finalize_backfill_design_management_repositories.rb create mode 100644 db/schema_migrations/20231204144300 create mode 100644 db/schema_migrations/20231206145911 create mode 100644 lib/gitlab/usage/metrics/instrumentations/count_service_desk_custom_email_enabled_metric.rb create mode 100644 spec/lib/gitlab/usage/metrics/instrumentations/count_service_desk_custom_email_enabled_metric_spec.rb 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 Enter. -### 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 Enter. ### 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 -- cgit v1.2.3