From 84c62cf776dc6dab8c2675f3e4d014cf545dcc15 Mon Sep 17 00:00:00 2001 From: GitLab Bot Date: Thu, 16 Jan 2025 00:33:46 +0000 Subject: [PATCH] Add latest changes from gitlab-org/gitlab@master --- .rubocop_todo/rails/strong_params.yml | 4 - Gemfile | 2 +- Gemfile.checksum | 1 + Gemfile.lock | 18 +-- Gemfile.next.checksum | 1 + Gemfile.next.lock | 18 +-- .../components/related_issuable_item.vue | 2 +- .../components/container_registry_section.vue | 6 +- .../components/related_items_list.scss | 5 - app/assets/stylesheets/framework/sidebar.scss | 8 -- .../stylesheets/page_bundles/projects.scss | 4 +- app/assets/stylesheets/vendors/atwho.scss | 2 +- .../omniauth_callbacks_controller.rb | 4 +- .../organizations/application_controller.rb | 5 +- .../organizations/groups_controller.rb | 2 +- .../organizations/organizations_controller.rb | 14 +- .../organizations/projects_controller.rb | 6 +- .../work_items/add_closing_merge_request.rb | 4 +- app/graphql/mutations/work_items/convert.rb | 2 +- .../mutations/work_items/create_from_task.rb | 4 +- app/graphql/mutations/work_items/delete.rb | 4 +- .../mutations/work_items/hierarchy/reorder.rb | 8 +- .../mutations/work_items/linked_items/base.rb | 2 +- app/graphql/mutations/work_items/subscribe.rb | 2 +- app/graphql/mutations/work_items/update.rb | 4 +- .../work_items/shared_filter_arguments.rb | 10 +- .../work_items/ancestors_resolver.rb | 2 +- .../description_templates_resolver.rb | 2 +- .../work_items/linked_items_resolver.rb | 4 +- .../resolvers/work_items/types_resolver.rb | 4 +- .../widgets/custom_status_resolver.rb | 2 +- .../work_item_discussions_resolver.rb | 6 +- .../work_items/closing_merge_request_type.rb | 2 +- .../types/work_items/linked_item_type.rb | 6 +- .../types/work_items/related_branch_type.rb | 2 +- .../resolve_discussions_input_type.rb | 2 +- app/graphql/types/work_items/type_type.rb | 2 +- .../work_items/widget_definition_interface.rb | 2 +- .../widget_definitions/assignees_type.rb | 2 +- .../widget_definitions/custom_status_type.rb | 4 +- .../widget_definitions/generic_type.rb | 2 +- .../widget_definitions/hierarchy_type.rb | 6 +- .../types/work_items/widget_interface.rb | 2 +- .../work_items/widgets/assignees_type.rb | 4 +- .../work_items/widgets/award_emoji_type.rb | 2 +- .../work_items/widgets/crm_contacts_type.rb | 4 +- .../widgets/crm_contacts_update_input_type.rb | 4 +- .../widgets/current_user_todos_type.rb | 4 +- .../work_items/widgets/custom_status_type.rb | 4 +- .../work_items/widgets/description_type.rb | 8 +- .../types/work_items/widgets/designs_type.rb | 4 +- .../work_items/widgets/development_type.rb | 8 +- .../widgets/email_participants_type.rb | 4 +- .../work_items/widgets/hierarchy_type.rb | 2 +- .../widgets/hierarchy_update_input_type.rb | 2 +- .../types/work_items/widgets/labels_type.rb | 4 +- .../work_items/widgets/linked_items_type.rb | 4 +- .../widgets/linked_resources_type.rb | 4 +- .../widgets/milestone_input_type.rb | 2 +- .../work_items/widgets/milestone_type.rb | 2 +- .../types/work_items/widgets/notes_type.rb | 4 +- .../work_items/widgets/notifications_type.rb | 2 +- .../work_items/widgets/participants_type.rb | 4 +- .../widgets/start_and_due_date_type.rb | 6 +- .../start_and_due_date_update_input_type.rb | 4 +- .../time_tracking/time_tracking_input_type.rb | 2 +- .../time_tracking/time_tracking_type.rb | 4 +- .../time_tracking/timelog_input_type.rb | 2 +- .../widgets/time_tracking/timelog_type.rb | 10 +- .../work_item_type_counts_by_state_type.rb | 4 +- ...k_item_type_depth_limit_reached_by_type.rb | 2 +- app/helpers/auth_helper.rb | 9 ++ app/services/ci/register_job_service.rb | 30 ++++- .../ci/register_job_service/logger.rb | 99 ++++++++++++++ app/views/groups/_flash_messages.html.haml | 2 +- .../profiles/usage_quotas/index.html.haml | 3 + ...ci_register_job_instrumentation_logger.yml | 9 ++ db/docs/bulk_import_entities.yml | 7 +- db/docs/operations_scopes.yml | 1 - db/docs/operations_strategies.yml | 12 +- ...ackages_debian_group_distribution_keys.yml | 12 +- ...ution_keys_group_id_not_null_constraint.rb | 14 ++ ...rategies_project_id_not_null_constraint.rb | 14 ++ ...stics_on_traversal_ids_and_letter_grade.rb | 17 +++ db/schema_migrations/20250109061618 | 1 + db/schema_migrations/20250109065940 | 1 + db/schema_migrations/20250115095728 | 1 + db/structure.sql | 6 +- doc/administration/auth/oidc.md | 3 - .../package_information/supported_os.md | 2 +- .../neovim/neovim_troubleshooting.md | 20 +-- doc/user/analytics/ai_impact_analytics.md | 7 +- doc/user/gitlab_duo_chat/examples.md | 2 + lib/api/conan/v1/instance_packages.rb | 12 +- lib/api/conan/v1/project_packages.rb | 6 - .../packages/conan/shared_endpoints.rb | 21 +++ .../concerns/packages/conan/v1_endpoints.rb | 21 --- lib/api/helpers/packages/conan/api_helpers.rb | 4 + lib/gitlab/auth/o_auth/provider.rb | 3 +- qa/qa/page/group/runners/index.rb | 8 ++ qa/qa/page/runners/runner_managers_detail.rb | 24 ++++ .../runner/register_group_runner_spec.rb | 11 +- .../omniauth_callbacks_controller_spec.rb | 64 +++++++++ .../container_registry_section_spec.js | 16 +++ spec/helpers/auth_helper_spec.rb | 121 ++++++++++++++++++ spec/lib/gitlab/auth/o_auth/provider_spec.rb | 52 ++++++-- .../api/conan/v1/project_packages_spec.rb | 23 +--- .../api/conan/v2/project_packages_spec.rb | 14 ++ .../ci/register_job_service/logger_spec.rb | 73 +++++++++++ spec/services/ci/register_job_service_spec.rb | 36 ++++++ .../api/conan_packages_shared_examples.rb | 23 ++++ 111 files changed, 836 insertions(+), 272 deletions(-) create mode 100644 app/services/ci/register_job_service/logger.rb create mode 100644 config/feature_flags/ops/ci_register_job_instrumentation_logger.yml create mode 100644 db/post_migrate/20250109061618_add_packages_debian_group_distribution_keys_group_id_not_null_constraint.rb create mode 100644 db/post_migrate/20250109065940_add_operations_strategies_project_id_not_null_constraint.rb create mode 100644 db/post_migrate/20250115095728_idx_vulnerability_statistics_on_traversal_ids_and_letter_grade.rb create mode 100644 db/schema_migrations/20250109061618 create mode 100644 db/schema_migrations/20250109065940 create mode 100644 db/schema_migrations/20250115095728 create mode 100644 qa/qa/page/runners/runner_managers_detail.rb create mode 100644 spec/services/ci/register_job_service/logger_spec.rb diff --git a/.rubocop_todo/rails/strong_params.yml b/.rubocop_todo/rails/strong_params.yml index 6ac0578b431..cd601a9dad1 100644 --- a/.rubocop_todo/rails/strong_params.yml +++ b/.rubocop_todo/rails/strong_params.yml @@ -101,10 +101,6 @@ Rails/StrongParams: - 'app/controllers/oauth/authorizations_controller.rb' - 'app/controllers/oauth/authorized_applications_controller.rb' - 'app/controllers/omniauth_callbacks_controller.rb' - - 'app/controllers/organizations/application_controller.rb' - - 'app/controllers/organizations/groups_controller.rb' - - 'app/controllers/organizations/organizations_controller.rb' - - 'app/controllers/organizations/projects_controller.rb' - 'app/controllers/profiles/accounts_controller.rb' - 'app/controllers/profiles/chat_names_controller.rb' - 'app/controllers/profiles/emails_controller.rb' diff --git a/Gemfile b/Gemfile index 811ad8406e6..59f1f96a85c 100644 --- a/Gemfile +++ b/Gemfile @@ -59,7 +59,7 @@ end gem 'gitlab-backup-cli', path: 'gems/gitlab-backup-cli', require: 'gitlab/backup/cli', feature_category: :backup_restore -gem 'gitlab-secret_detection', path: 'gems/gitlab-secret_detection', feature_category: :secret_detection +gem 'gitlab-secret_detection', '< 1.0', feature_category: :secret_detection # Responders respond_to and respond_with gem 'responders', '~> 3.0', feature_category: :shared diff --git a/Gemfile.checksum b/Gemfile.checksum index 8c1f2f54e3e..60982ddaa46 100644 --- a/Gemfile.checksum +++ b/Gemfile.checksum @@ -239,6 +239,7 @@ {"name":"gitlab-markup","version":"1.9.0","platform":"ruby","checksum":"7eda045a08ec2d110084252fa13a8c9eac8bdac0e302035ca7db4b82bcbd7ed4"}, {"name":"gitlab-net-dns","version":"0.9.2","platform":"ruby","checksum":"f726d978479d43810819f12a45c0906d775a07e34df111bbe693fffbbef3059d"}, {"name":"gitlab-sdk","version":"0.3.1","platform":"ruby","checksum":"48ba49084f4ab92df7c7ef9f347020d9dfdf6ed9c1e782b67264e98ffe6ea710"}, +{"name":"gitlab-secret_detection","version":"0.14.2","platform":"ruby","checksum":"c6d3bc92b47cdf930ff7bf1e519a849353f33df1a2b4493078963769854850f0"}, {"name":"gitlab-security_report_schemas","version":"0.1.2.min15.0.0.max15.2.1","platform":"ruby","checksum":"300037487ec9d51a814f648514ff521cb82b94fc51d9fe53389175b36ac680ae"}, {"name":"gitlab-styles","version":"13.0.2","platform":"ruby","checksum":"e662b9334643763b55a861f9e26091096547f98179bd89b0fa8d6c6fb8cec861"}, {"name":"gitlab_chronic_duration","version":"0.12.0","platform":"ruby","checksum":"0d766944d415b5c831f176871ee8625783fc0c5bfbef2d79a3a616f207ffc16d"}, diff --git a/Gemfile.lock b/Gemfile.lock index 5bf5bac2dfe..8e04937b9b9 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -107,16 +107,6 @@ PATH diffy pg_query -PATH - remote: gems/gitlab-secret_detection - specs: - gitlab-secret_detection (0.1.1) - grpc (= 1.63.0) - grpc-tools (= 1.63.0) - parallel (~> 1.22) - re2 (~> 2.7) - toml-rb (~> 2.2) - PATH remote: gems/gitlab-utils specs: @@ -785,6 +775,12 @@ GEM activesupport (>= 5.2.0) rake (~> 13.0) snowplow-tracker (~> 0.8.0) + gitlab-secret_detection (0.14.2) + grpc (= 1.63.0) + grpc-tools (= 1.63.0) + parallel (~> 1.19) + re2 (= 2.7.0) + toml-rb (~> 2.2.0) gitlab-security_report_schemas (0.1.2.min15.0.0.max15.2.1) activesupport (>= 6, < 8) json_schemer (~> 2.3.0) @@ -2109,7 +2105,7 @@ DEPENDENCIES gitlab-safe_request_store! gitlab-schema-validation! gitlab-sdk (~> 0.3.0) - gitlab-secret_detection! + gitlab-secret_detection (< 1.0) gitlab-security_report_schemas (= 0.1.2.min15.0.0.max15.2.1) gitlab-sidekiq-fetcher! gitlab-styles (~> 13.0.2) diff --git a/Gemfile.next.checksum b/Gemfile.next.checksum index 292886709ab..da77eb94674 100644 --- a/Gemfile.next.checksum +++ b/Gemfile.next.checksum @@ -239,6 +239,7 @@ {"name":"gitlab-markup","version":"1.9.0","platform":"ruby","checksum":"7eda045a08ec2d110084252fa13a8c9eac8bdac0e302035ca7db4b82bcbd7ed4"}, {"name":"gitlab-net-dns","version":"0.9.2","platform":"ruby","checksum":"f726d978479d43810819f12a45c0906d775a07e34df111bbe693fffbbef3059d"}, {"name":"gitlab-sdk","version":"0.3.1","platform":"ruby","checksum":"48ba49084f4ab92df7c7ef9f347020d9dfdf6ed9c1e782b67264e98ffe6ea710"}, +{"name":"gitlab-secret_detection","version":"0.14.2","platform":"ruby","checksum":"c6d3bc92b47cdf930ff7bf1e519a849353f33df1a2b4493078963769854850f0"}, {"name":"gitlab-security_report_schemas","version":"0.1.2.min15.0.0.max15.2.1","platform":"ruby","checksum":"300037487ec9d51a814f648514ff521cb82b94fc51d9fe53389175b36ac680ae"}, {"name":"gitlab-styles","version":"13.0.2","platform":"ruby","checksum":"e662b9334643763b55a861f9e26091096547f98179bd89b0fa8d6c6fb8cec861"}, {"name":"gitlab_chronic_duration","version":"0.12.0","platform":"ruby","checksum":"0d766944d415b5c831f176871ee8625783fc0c5bfbef2d79a3a616f207ffc16d"}, diff --git a/Gemfile.next.lock b/Gemfile.next.lock index 9397c74ed90..575c0952334 100644 --- a/Gemfile.next.lock +++ b/Gemfile.next.lock @@ -107,16 +107,6 @@ PATH diffy pg_query -PATH - remote: gems/gitlab-secret_detection - specs: - gitlab-secret_detection (0.1.1) - grpc (= 1.63.0) - grpc-tools (= 1.63.0) - parallel (~> 1.22) - re2 (~> 2.7) - toml-rb (~> 2.2) - PATH remote: gems/gitlab-utils specs: @@ -797,6 +787,12 @@ GEM activesupport (>= 5.2.0) rake (~> 13.0) snowplow-tracker (~> 0.8.0) + gitlab-secret_detection (0.14.2) + grpc (= 1.63.0) + grpc-tools (= 1.63.0) + parallel (~> 1.19) + re2 (= 2.7.0) + toml-rb (~> 2.2.0) gitlab-security_report_schemas (0.1.2.min15.0.0.max15.2.1) activesupport (>= 6, < 8) json_schemer (~> 2.3.0) @@ -2140,7 +2136,7 @@ DEPENDENCIES gitlab-safe_request_store! gitlab-schema-validation! gitlab-sdk (~> 0.3.0) - gitlab-secret_detection! + gitlab-secret_detection (< 1.0) gitlab-security_report_schemas (= 0.1.2.min15.0.0.max15.2.1) gitlab-sidekiq-fetcher! gitlab-styles (~> 13.0.2) diff --git a/app/assets/javascripts/issuable/components/related_issuable_item.vue b/app/assets/javascripts/issuable/components/related_issuable_item.vue index d81c0e2cdc5..5a2af4dae5a 100644 --- a/app/assets/javascripts/issuable/components/related_issuable_item.vue +++ b/app/assets/javascripts/issuable/components/related_issuable_item.vue @@ -152,8 +152,8 @@ export default { v-gl-tooltip name="eye-slash" :title="__('Confidential')" - class="confidential-icon" :aria-label="__('Confidential')" + variant="warning" /> {{ title }} diff --git a/app/assets/javascripts/packages_and_registries/settings/project/components/container_registry_section.vue b/app/assets/javascripts/packages_and_registries/settings/project/components/container_registry_section.vue index 5f8f0d95a2a..8be105bc655 100644 --- a/app/assets/javascripts/packages_and_registries/settings/project/components/container_registry_section.vue +++ b/app/assets/javascripts/packages_and_registries/settings/project/components/container_registry_section.vue @@ -17,6 +17,7 @@ export default { SettingsBlock, }, mixins: [glFeatureFlagsMixin()], + inject: ['isContainerRegistryMetadataDatabaseEnabled'], props: { expanded: { type: Boolean, @@ -26,7 +27,10 @@ export default { }, computed: { showContainerProtectedTagsSettings() { - return this.glFeatures.containerRegistryProtectedTags; + return ( + this.glFeatures.containerRegistryProtectedTags && + this.isContainerRegistryMetadataDatabaseEnabled + ); }, }, containerRegistryHelpPath: helpPagePath('user/packages/container_registry/index.md'), diff --git a/app/assets/stylesheets/components/related_items_list.scss b/app/assets/stylesheets/components/related_items_list.scss index 4641f54942e..3752307942c 100644 --- a/app/assets/stylesheets/components/related_items_list.scss +++ b/app/assets/stylesheets/components/related_items_list.scss @@ -50,7 +50,6 @@ $item-remove-button-space: 42px; .issue-token-state-icon-open, .issue-token-state-icon-closed, - .confidential-icon, .item-milestone .icon, .item-weight .board-card-info-icon { min-width: $gl-padding; @@ -61,10 +60,6 @@ $item-remove-button-space: 42px; } } - .confidential-icon { - color: $orange-500; - } - .item-title { flex-basis: 100%; font-size: $gl-font-size-small; diff --git a/app/assets/stylesheets/framework/sidebar.scss b/app/assets/stylesheets/framework/sidebar.scss index 248c51ba1e0..a4474657da2 100644 --- a/app/assets/stylesheets/framework/sidebar.scss +++ b/app/assets/stylesheets/framework/sidebar.scss @@ -299,14 +299,6 @@ .assignee-grid, .reviewer-grid { - [data-css-area='attention'] { - grid-area: attention; - - button.selected svg { - fill: $orange-500; - } - } - [data-css-area='user'] { grid-area: user; } diff --git a/app/assets/stylesheets/page_bundles/projects.scss b/app/assets/stylesheets/page_bundles/projects.scss index a956a6780ba..7cd0ae0e16c 100644 --- a/app/assets/stylesheets/page_bundles/projects.scss +++ b/app/assets/stylesheets/page_bundles/projects.scss @@ -91,7 +91,7 @@ } .vs-internal { - color: var(--orange-500, $orange-500); + @apply gl-text-warning; } .vs-private { @@ -103,7 +103,7 @@ } .lfs-disabled { - color: var(--orange-500, $orange-500); + @apply gl-text-warning; } .breadcrumb.repo-breadcrumb { diff --git a/app/assets/stylesheets/vendors/atwho.scss b/app/assets/stylesheets/vendors/atwho.scss index 3ad2ee18b14..92a8907b552 100644 --- a/app/assets/stylesheets/vendors/atwho.scss +++ b/app/assets/stylesheets/vendors/atwho.scss @@ -70,7 +70,7 @@ } &.has-warning { - color: $orange-500; + @apply gl-text-warning; } } diff --git a/app/controllers/omniauth_callbacks_controller.rb b/app/controllers/omniauth_callbacks_controller.rb index bfee3c6f09d..41d200e85eb 100644 --- a/app/controllers/omniauth_callbacks_controller.rb +++ b/app/controllers/omniauth_callbacks_controller.rb @@ -32,6 +32,8 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController def handle_omniauth if ::AuthHelper.saml_providers.include?(oauth['provider'].to_sym) saml + elsif ::AuthHelper.oidc_providers.include?(oauth['provider'].to_sym) + openid_connect else omniauth_flow(Gitlab::Auth::OAuth) end @@ -43,7 +45,7 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController # overridden in EE def openid_connect - handle_omniauth + omniauth_flow(Gitlab::Auth::OAuth) end def jwt diff --git a/app/controllers/organizations/application_controller.rb b/app/controllers/organizations/application_controller.rb index 180b114370b..8e18a829130 100644 --- a/app/controllers/organizations/application_controller.rb +++ b/app/controllers/organizations/application_controller.rb @@ -10,9 +10,10 @@ module Organizations private def organization - return unless params[:organization_path] + organization_path = params.permit(:organization_path)[:organization_path] + return unless organization_path - @organization = Organizations::Organization.find_by_path(params[:organization_path]) + @organization = Organizations::Organization.find_by_path(organization_path) end strong_memoize_attr :organization diff --git a/app/controllers/organizations/groups_controller.rb b/app/controllers/organizations/groups_controller.rb index 2868cb8cf3c..3129087fb20 100644 --- a/app/controllers/organizations/groups_controller.rb +++ b/app/controllers/organizations/groups_controller.rb @@ -37,7 +37,7 @@ module Organizations private def group - @group ||= Group.in_organization(organization).find_by_full_path(params[:id]) + @group ||= Group.in_organization(organization).find_by_full_path(params.permit(:id)[:id]) end def create_group diff --git a/app/controllers/organizations/organizations_controller.rb b/app/controllers/organizations/organizations_controller.rb index 3de28f8e4e7..fb446deba38 100644 --- a/app/controllers/organizations/organizations_controller.rb +++ b/app/controllers/organizations/organizations_controller.rb @@ -56,9 +56,13 @@ module Organizations private def activity_query_limit - return params[:limit].to_i unless !params[:limit] || params[:limit].to_i > DEFAULT_ACTIVITY_EVENT_LIMIT + limit = safe_params[:limit] - DEFAULT_ACTIVITY_EVENT_LIMIT + if limit && limit.to_i <= DEFAULT_ACTIVITY_EVENT_LIMIT + limit.to_i + else + DEFAULT_ACTIVITY_EVENT_LIMIT + end end def projects @@ -77,7 +81,7 @@ module Organizations def load_events @events = EventCollection.new( projects, - offset: params[:offset].to_i, + offset: safe_params[:offset].to_i, filter: event_filter, # limit + 1 allows us to determine if we have another page. # This will be removed as part of https://gitlab.com/gitlab-org/gitlab/-/issues/382473 @@ -87,6 +91,10 @@ module Organizations Events::RenderService.new(current_user).execute(@events) end + + def safe_params + params.permit(:limit, :offset) + end end end diff --git a/app/controllers/organizations/projects_controller.rb b/app/controllers/organizations/projects_controller.rb index f84c80f69ce..ae43e45908d 100644 --- a/app/controllers/organizations/projects_controller.rb +++ b/app/controllers/organizations/projects_controller.rb @@ -12,12 +12,16 @@ module Organizations def project @project = Project.find_by_full_path( - [params[:namespace_id], '/', params[:id]].join('') + [safe_params[:namespace_id], '/', safe_params[:id]].join('') ) end def authorize_project_view_edit_page! access_denied! unless can?(current_user, :view_edit_page, project) end + + def safe_params + params.permit(:id, :namespace_id) + end end end diff --git a/app/graphql/mutations/work_items/add_closing_merge_request.rb b/app/graphql/mutations/work_items/add_closing_merge_request.rb index db12c4c9db8..ce7bda81391 100644 --- a/app/graphql/mutations/work_items/add_closing_merge_request.rb +++ b/app/graphql/mutations/work_items/add_closing_merge_request.rb @@ -22,10 +22,10 @@ module Mutations '`!1`, `project_full_path!1` or `https://gitlab.com/gitlab-org/gitlab/-/merge_requests/1`.' field :closing_merge_request, - Types::WorkItems::ClosingMergeRequestType, + ::Types::WorkItems::ClosingMergeRequestType, null: true, description: 'Closing merge request added to the work item.' - field :work_item, Types::WorkItemType, + field :work_item, ::Types::WorkItemType, null: true, description: 'Work item with new closing merge requests.' diff --git a/app/graphql/mutations/work_items/convert.rb b/app/graphql/mutations/work_items/convert.rb index 3e7030adfce..f46b5fa1fc4 100644 --- a/app/graphql/mutations/work_items/convert.rb +++ b/app/graphql/mutations/work_items/convert.rb @@ -17,7 +17,7 @@ module Mutations required: true, description: 'Global ID of the new work item type.' - field :work_item, Types::WorkItemType, + field :work_item, ::Types::WorkItemType, null: true, description: 'Updated work item.' diff --git a/app/graphql/mutations/work_items/create_from_task.rb b/app/graphql/mutations/work_items/create_from_task.rb index 6296b333fe4..dc2619b2835 100644 --- a/app/graphql/mutations/work_items/create_from_task.rb +++ b/app/graphql/mutations/work_items/create_from_task.rb @@ -19,11 +19,11 @@ module Mutations description: 'Arguments necessary to convert a task into a work item.', prepare: ->(attributes, _ctx) { attributes.to_h } - field :work_item, Types::WorkItemType, + field :work_item, ::Types::WorkItemType, null: true, description: 'Updated work item.' - field :new_work_item, Types::WorkItemType, + field :new_work_item, ::Types::WorkItemType, null: true, description: 'New work item created from task.' diff --git a/app/graphql/mutations/work_items/delete.rb b/app/graphql/mutations/work_items/delete.rb index de2c7e8be40..a6f5e8c1c45 100644 --- a/app/graphql/mutations/work_items/delete.rb +++ b/app/graphql/mutations/work_items/delete.rb @@ -12,7 +12,7 @@ module Mutations required: true, description: 'Global ID of the work item.' - field :project, Types::ProjectType, + field :project, ::Types::ProjectType, null: true, description: 'Project the deleted work item belonged to.', deprecated: { @@ -20,7 +20,7 @@ module Mutations milestone: '16.9' } - field :namespace, Types::NamespaceType, + field :namespace, ::Types::NamespaceType, null: true, description: 'Namespace the deleted work item belonged to.' diff --git a/app/graphql/mutations/work_items/hierarchy/reorder.rb b/app/graphql/mutations/work_items/hierarchy/reorder.rb index 4b9730d592e..873c02c22bc 100644 --- a/app/graphql/mutations/work_items/hierarchy/reorder.rb +++ b/app/graphql/mutations/work_items/hierarchy/reorder.rb @@ -20,17 +20,17 @@ module Mutations description: 'Global ID of the new parent work item.' argument :relative_position, - Types::RelativePositionTypeEnum, + ::Types::RelativePositionTypeEnum, required: false, description: 'Position relative to the adjacent work item. Valid values are `BEFORE` or `AFTER`.' - field :work_item, Types::WorkItemType, + field :work_item, ::Types::WorkItemType, null: true, description: 'Work item after mutation.' - field :adjacent_work_item, Types::WorkItemType, + field :adjacent_work_item, ::Types::WorkItemType, null: true, description: 'Adjacent work item after mutation.' - field :parent_work_item, Types::WorkItemType, + field :parent_work_item, ::Types::WorkItemType, null: true, description: "Work item's parent after mutation." authorize :read_work_item diff --git a/app/graphql/mutations/work_items/linked_items/base.rb b/app/graphql/mutations/work_items/linked_items/base.rb index ae7959dfb20..b54bf8212f6 100644 --- a/app/graphql/mutations/work_items/linked_items/base.rb +++ b/app/graphql/mutations/work_items/linked_items/base.rb @@ -10,7 +10,7 @@ module Mutations argument :id, ::Types::GlobalIDType[::WorkItem], required: true, description: 'Global ID of the work item.' - field :work_item, Types::WorkItemType, + field :work_item, ::Types::WorkItemType, null: true, description: 'Updated work item.' field :message, GraphQL::Types::String, diff --git a/app/graphql/mutations/work_items/subscribe.rb b/app/graphql/mutations/work_items/subscribe.rb index a29c3416c3d..4c39e5d655f 100644 --- a/app/graphql/mutations/work_items/subscribe.rb +++ b/app/graphql/mutations/work_items/subscribe.rb @@ -14,7 +14,7 @@ module Mutations required: true, description: 'Desired state of the subscription.' - field :work_item, Types::WorkItemType, + field :work_item, ::Types::WorkItemType, null: true, description: 'Work item after mutation.' diff --git a/app/graphql/mutations/work_items/update.rb b/app/graphql/mutations/work_items/update.rb index d6cadf1bb95..fdb7a59e1dc 100644 --- a/app/graphql/mutations/work_items/update.rb +++ b/app/graphql/mutations/work_items/update.rb @@ -49,7 +49,7 @@ module Mutations required: false, description: 'Input for start and due date widget.' argument :state_event, - Types::WorkItems::StateEventEnum, + ::Types::WorkItems::StateEventEnum, description: 'Close or reopen a work item.', required: false argument :time_tracking_widget, @@ -61,7 +61,7 @@ module Mutations required: false, description: copy_field_description(Types::WorkItemType, :title) - field :work_item, Types::WorkItemType, + field :work_item, ::Types::WorkItemType, null: true, description: 'Updated work item.' diff --git a/app/graphql/resolvers/concerns/work_items/shared_filter_arguments.rb b/app/graphql/resolvers/concerns/work_items/shared_filter_arguments.rb index 69f8c6c6de5..c45ac79346f 100644 --- a/app/graphql/resolvers/concerns/work_items/shared_filter_arguments.rb +++ b/app/graphql/resolvers/concerns/work_items/shared_filter_arguments.rb @@ -39,13 +39,13 @@ module WorkItems required: false, description: 'List of IIDs of work items. For example, `["1", "2"]`.' argument :state, - Types::IssuableStateEnum, + ::Types::IssuableStateEnum, required: false, description: 'Current state of the work item.', prepare: ->(state, _ctx) { return state unless state == 'locked' - raise Gitlab::Graphql::Errors::ArgumentError, Types::IssuableStateEnum::INVALID_LOCKED_MESSAGE + raise Gitlab::Graphql::Errors::ArgumentError, ::Types::IssuableStateEnum::INVALID_LOCKED_MESSAGE } argument :types, [Types::IssueTypeEnum], @@ -53,17 +53,17 @@ module WorkItems description: 'Filter work items by the given work item types.', required: false - argument :subscribed, Types::Issuables::SubscriptionStatusEnum, + argument :subscribed, ::Types::Issuables::SubscriptionStatusEnum, description: 'Work items the current user is subscribed to.', required: false - argument :not, Types::WorkItems::NegatedWorkItemFilterInputType, + argument :not, ::Types::WorkItems::NegatedWorkItemFilterInputType, description: 'Negated work item arguments.', required: false, prepare: ->(value, _ctx) { value.to_h } - argument :or, Types::WorkItems::UnionedWorkItemFilterInputType, + argument :or, ::Types::WorkItems::UnionedWorkItemFilterInputType, description: 'List of arguments with inclusive `OR`.', required: false, prepare: ->(value, _ctx) { diff --git a/app/graphql/resolvers/work_items/ancestors_resolver.rb b/app/graphql/resolvers/work_items/ancestors_resolver.rb index 2608851303c..a74df2e882d 100644 --- a/app/graphql/resolvers/work_items/ancestors_resolver.rb +++ b/app/graphql/resolvers/work_items/ancestors_resolver.rb @@ -5,7 +5,7 @@ module Resolvers class AncestorsResolver < BaseResolver prepend ::WorkItems::LookAheadPreloads - type Types::WorkItemType.connection_type, null: true + type ::Types::WorkItemType.connection_type, null: true def resolve_with_lookahead ancestors = object.ancestors diff --git a/app/graphql/resolvers/work_items/description_templates_resolver.rb b/app/graphql/resolvers/work_items/description_templates_resolver.rb index 9deca239209..ed562aab801 100644 --- a/app/graphql/resolvers/work_items/description_templates_resolver.rb +++ b/app/graphql/resolvers/work_items/description_templates_resolver.rb @@ -3,7 +3,7 @@ module Resolvers module WorkItems class DescriptionTemplatesResolver < BaseResolver - type Types::WorkItems::DescriptionTemplateType.connection_type, null: true + type ::Types::WorkItems::DescriptionTemplateType.connection_type, null: true argument :name, GraphQL::Types::String, required: false, diff --git a/app/graphql/resolvers/work_items/linked_items_resolver.rb b/app/graphql/resolvers/work_items/linked_items_resolver.rb index 8ca166f3e9a..0e01b17adb8 100644 --- a/app/graphql/resolvers/work_items/linked_items_resolver.rb +++ b/app/graphql/resolvers/work_items/linked_items_resolver.rb @@ -5,13 +5,13 @@ module Resolvers class LinkedItemsResolver < BaseResolver prepend ::WorkItems::LookAheadPreloads - argument :filter, Types::WorkItems::RelatedLinkTypeEnum, + argument :filter, ::Types::WorkItems::RelatedLinkTypeEnum, required: false, description: "Filter by link type. " \ "Supported values: #{Types::WorkItems::RelatedLinkTypeEnum.values.keys.to_sentence}. " \ 'Returns all types if omitted.' - type Types::WorkItems::LinkedItemType.connection_type, null: true + type ::Types::WorkItems::LinkedItemType.connection_type, null: true def resolve_with_lookahead(**args) apply_lookahead(related_work_items(args)) diff --git a/app/graphql/resolvers/work_items/types_resolver.rb b/app/graphql/resolvers/work_items/types_resolver.rb index a9bc1bb9a53..4eb796f7e1e 100644 --- a/app/graphql/resolvers/work_items/types_resolver.rb +++ b/app/graphql/resolvers/work_items/types_resolver.rb @@ -5,9 +5,9 @@ module Resolvers class TypesResolver < BaseResolver include LooksAhead - type Types::WorkItems::TypeType.connection_type, null: true + type ::Types::WorkItems::TypeType.connection_type, null: true - argument :name, Types::IssueTypeEnum, + argument :name, ::Types::IssueTypeEnum, description: 'Filter work item types by the given name.', required: false diff --git a/app/graphql/resolvers/work_items/widgets/custom_status_resolver.rb b/app/graphql/resolvers/work_items/widgets/custom_status_resolver.rb index 5421cba3bfc..24ac11c39f7 100644 --- a/app/graphql/resolvers/work_items/widgets/custom_status_resolver.rb +++ b/app/graphql/resolvers/work_items/widgets/custom_status_resolver.rb @@ -4,7 +4,7 @@ module Resolvers module WorkItems module Widgets class CustomStatusResolver < BaseResolver - type Types::WorkItems::Widgets::CustomStatusType.connection_type, null: true + type ::Types::WorkItems::Widgets::CustomStatusType.connection_type, null: true def resolve # Implement during https://gitlab.com/gitlab-org/gitlab/-/issues/498393 diff --git a/app/graphql/resolvers/work_items/work_item_discussions_resolver.rb b/app/graphql/resolvers/work_items/work_item_discussions_resolver.rb index 0bbd51a537e..95f88b3185c 100644 --- a/app/graphql/resolvers/work_items/work_item_discussions_resolver.rb +++ b/app/graphql/resolvers/work_items/work_item_discussions_resolver.rb @@ -13,12 +13,12 @@ module Resolvers alias_method :notes_widget, :object - argument :filter, Types::WorkItems::NotesFilterTypeEnum, + argument :filter, ::Types::WorkItems::NotesFilterTypeEnum, required: false, - default_value: Types::WorkItems::NotesFilterTypeEnum.default_value, + default_value: ::Types::WorkItems::NotesFilterTypeEnum.default_value, description: 'Type of notes collection: ALL_NOTES, ONLY_COMMENTS, ONLY_ACTIVITY.' - type Types::Notes::DiscussionType.connection_type, null: true + type ::Types::Notes::DiscussionType.connection_type, null: true def resolve(**args) finder = Issuable::DiscussionsListService.new(current_user, work_item, params(args)) diff --git a/app/graphql/types/work_items/closing_merge_request_type.rb b/app/graphql/types/work_items/closing_merge_request_type.rb index ddd18f7d980..6ba2126a006 100644 --- a/app/graphql/types/work_items/closing_merge_request_type.rb +++ b/app/graphql/types/work_items/closing_merge_request_type.rb @@ -14,7 +14,7 @@ module Types field :id, ::Types::GlobalIDType[::MergeRequestsClosingIssues], null: false, description: 'Global ID of the closing merge request association.' - field :merge_request, Types::MergeRequestType, + field :merge_request, ::Types::MergeRequestType, null: true, description: 'Related merge request.' end diff --git a/app/graphql/types/work_items/linked_item_type.rb b/app/graphql/types/work_items/linked_item_type.rb index b63d79e4ad2..911f305957f 100644 --- a/app/graphql/types/work_items/linked_item_type.rb +++ b/app/graphql/types/work_items/linked_item_type.rb @@ -7,7 +7,7 @@ module Types authorize :read_work_item - field :link_created_at, Types::TimeType, + field :link_created_at, ::Types::TimeType, description: 'Timestamp the link was created.', null: false, method: :issue_link_created_at @@ -20,10 +20,10 @@ module Types field :link_type, GraphQL::Types::String, description: 'Type of link.', null: false, method: :issue_link_type - field :link_updated_at, Types::TimeType, + field :link_updated_at, ::Types::TimeType, description: 'Timestamp the link was updated.', null: false, method: :issue_link_updated_at - field :work_item, Types::WorkItemType, + field :work_item, ::Types::WorkItemType, description: 'Linked work item.', null: true def work_item diff --git a/app/graphql/types/work_items/related_branch_type.rb b/app/graphql/types/work_items/related_branch_type.rb index f9986ef260c..3a2f3a99c69 100644 --- a/app/graphql/types/work_items/related_branch_type.rb +++ b/app/graphql/types/work_items/related_branch_type.rb @@ -16,7 +16,7 @@ module Types field :compare_path, GraphQL::Types::String, null: true, description: 'Path to comparison of branch to default branch.' - field :pipeline_status, Types::Ci::DetailedStatusType, null: true, + field :pipeline_status, ::Types::Ci::DetailedStatusType, null: true, description: 'Status of pipeline for the branch.' end # rubocop:enable Graphql/AuthorizeTypes diff --git a/app/graphql/types/work_items/resolve_discussions_input_type.rb b/app/graphql/types/work_items/resolve_discussions_input_type.rb index 480758169a5..9716995847d 100644 --- a/app/graphql/types/work_items/resolve_discussions_input_type.rb +++ b/app/graphql/types/work_items/resolve_discussions_input_type.rb @@ -8,7 +8,7 @@ module Types argument :discussion_id, GraphQL::Types::String, description: 'ID of a discussion to resolve.', required: false - argument :noteable_id, Types::GlobalIDType[::Noteable], + argument :noteable_id, ::Types::GlobalIDType[::Noteable], required: true, description: 'Global ID of the noteable where discussions will be resolved when the work item is created. ' \ 'Only `MergeRequestID` is supported at the moment.' diff --git a/app/graphql/types/work_items/type_type.rb b/app/graphql/types/work_items/type_type.rb index 452c77bdeae..f314e1006ff 100644 --- a/app/graphql/types/work_items/type_type.rb +++ b/app/graphql/types/work_items/type_type.rb @@ -10,7 +10,7 @@ module Types field :icon_name, GraphQL::Types::String, null: true, description: 'Icon name of the work item type.' - field :id, Types::GlobalIDType[::WorkItems::Type], + field :id, ::Types::GlobalIDType[::WorkItems::Type], null: false, description: 'Global ID of the work item type.' field :name, GraphQL::Types::String, diff --git a/app/graphql/types/work_items/widget_definition_interface.rb b/app/graphql/types/work_items/widget_definition_interface.rb index 8d348c0aca3..420c855621e 100644 --- a/app/graphql/types/work_items/widget_definition_interface.rb +++ b/app/graphql/types/work_items/widget_definition_interface.rb @@ -3,7 +3,7 @@ module Types module WorkItems module WidgetDefinitionInterface - include Types::BaseInterface + include ::Types::BaseInterface graphql_name 'WorkItemWidgetDefinition' diff --git a/app/graphql/types/work_items/widget_definitions/assignees_type.rb b/app/graphql/types/work_items/widget_definitions/assignees_type.rb index d6d06ae1f97..5d0b9f3b755 100644 --- a/app/graphql/types/work_items/widget_definitions/assignees_type.rb +++ b/app/graphql/types/work_items/widget_definitions/assignees_type.rb @@ -8,7 +8,7 @@ module Types graphql_name 'WorkItemWidgetDefinitionAssignees' description 'Represents an assignees widget definition' - implements Types::WorkItems::WidgetDefinitionInterface + implements ::Types::WorkItems::WidgetDefinitionInterface field :can_invite_members, GraphQL::Types::Boolean, null: false, diff --git a/app/graphql/types/work_items/widget_definitions/custom_status_type.rb b/app/graphql/types/work_items/widget_definitions/custom_status_type.rb index eb54f9c116d..502a625f75b 100644 --- a/app/graphql/types/work_items/widget_definitions/custom_status_type.rb +++ b/app/graphql/types/work_items/widget_definitions/custom_status_type.rb @@ -8,9 +8,9 @@ module Types graphql_name 'WorkItemWidgetDefinitionCustomStatus' description 'Represents an Custom Status widget definition' - implements Types::WorkItems::WidgetDefinitionInterface + implements ::Types::WorkItems::WidgetDefinitionInterface - field :allowed_custom_statuses, Types::WorkItems::Widgets::CustomStatusType.connection_type, + field :allowed_custom_statuses, ::Types::WorkItems::Widgets::CustomStatusType.connection_type, null: true, experiment: { milestone: '17.8' }, description: 'Allowed custom statuses for the work item type.', resolver: Resolvers::WorkItems::Widgets::CustomStatusResolver diff --git a/app/graphql/types/work_items/widget_definitions/generic_type.rb b/app/graphql/types/work_items/widget_definitions/generic_type.rb index f3817ade654..1789ace08b3 100644 --- a/app/graphql/types/work_items/widget_definitions/generic_type.rb +++ b/app/graphql/types/work_items/widget_definitions/generic_type.rb @@ -8,7 +8,7 @@ module Types graphql_name 'WorkItemWidgetDefinitionGeneric' description 'Represents a generic widget definition' - implements Types::WorkItems::WidgetDefinitionInterface + implements ::Types::WorkItems::WidgetDefinitionInterface end # rubocop:enable Graphql/AuthorizeTypes end diff --git a/app/graphql/types/work_items/widget_definitions/hierarchy_type.rb b/app/graphql/types/work_items/widget_definitions/hierarchy_type.rb index 758d2844da9..45581cc6191 100644 --- a/app/graphql/types/work_items/widget_definitions/hierarchy_type.rb +++ b/app/graphql/types/work_items/widget_definitions/hierarchy_type.rb @@ -9,15 +9,15 @@ module Types graphql_name 'WorkItemWidgetDefinitionHierarchy' description 'Represents a hierarchy widget definition' - implements Types::WorkItems::WidgetDefinitionInterface + implements ::Types::WorkItems::WidgetDefinitionInterface - field :allowed_child_types, Types::WorkItems::TypeType.connection_type, + field :allowed_child_types, ::Types::WorkItems::TypeType.connection_type, null: true, complexity: 5, extras: [:parent], description: 'Allowed child types for the work item type.' - field :allowed_parent_types, Types::WorkItems::TypeType.connection_type, + field :allowed_parent_types, ::Types::WorkItems::TypeType.connection_type, null: true, extras: [:parent], complexity: 5, diff --git a/app/graphql/types/work_items/widget_interface.rb b/app/graphql/types/work_items/widget_interface.rb index 223c1470952..573fff53f2e 100644 --- a/app/graphql/types/work_items/widget_interface.rb +++ b/app/graphql/types/work_items/widget_interface.rb @@ -3,7 +3,7 @@ module Types module WorkItems module WidgetInterface - include Types::BaseInterface + include ::Types::BaseInterface graphql_name 'WorkItemWidget' diff --git a/app/graphql/types/work_items/widgets/assignees_type.rb b/app/graphql/types/work_items/widgets/assignees_type.rb index 6168642b5b9..e20fc76603d 100644 --- a/app/graphql/types/work_items/widgets/assignees_type.rb +++ b/app/graphql/types/work_items/widgets/assignees_type.rb @@ -10,9 +10,9 @@ module Types graphql_name 'WorkItemWidgetAssignees' description 'Represents an assignees widget' - implements Types::WorkItems::WidgetInterface + implements ::Types::WorkItems::WidgetInterface - field :assignees, Types::UserType.connection_type, + field :assignees, ::Types::UserType.connection_type, null: true, method: :assignees_by_name_and_id, description: 'Assignees of the work item.' diff --git a/app/graphql/types/work_items/widgets/award_emoji_type.rb b/app/graphql/types/work_items/widgets/award_emoji_type.rb index ba260ada88e..cdaeb8a31d0 100644 --- a/app/graphql/types/work_items/widgets/award_emoji_type.rb +++ b/app/graphql/types/work_items/widgets/award_emoji_type.rb @@ -10,7 +10,7 @@ module Types graphql_name 'WorkItemWidgetAwardEmoji' description 'Represents the emoji reactions widget' - implements Types::WorkItems::WidgetInterface + implements ::Types::WorkItems::WidgetInterface field :award_emoji, ::Types::AwardEmojis::AwardEmojiType.connection_type, diff --git a/app/graphql/types/work_items/widgets/crm_contacts_type.rb b/app/graphql/types/work_items/widgets/crm_contacts_type.rb index 84f22f872de..3a59a343fb7 100644 --- a/app/graphql/types/work_items/widgets/crm_contacts_type.rb +++ b/app/graphql/types/work_items/widgets/crm_contacts_type.rb @@ -10,10 +10,10 @@ module Types graphql_name 'WorkItemWidgetCrmContacts' description 'Represents CRM contacts widget' - implements Types::WorkItems::WidgetInterface + implements ::Types::WorkItems::WidgetInterface field :contacts, - Types::CustomerRelations::ContactType.connection_type, + ::Types::CustomerRelations::ContactType.connection_type, null: true, description: 'Collection of CRM contacts associated with the work item.', method: :customer_relations_contacts diff --git a/app/graphql/types/work_items/widgets/crm_contacts_update_input_type.rb b/app/graphql/types/work_items/widgets/crm_contacts_update_input_type.rb index 143ffafe08d..33297ceed57 100644 --- a/app/graphql/types/work_items/widgets/crm_contacts_update_input_type.rb +++ b/app/graphql/types/work_items/widgets/crm_contacts_update_input_type.rb @@ -13,9 +13,9 @@ module Types prepare: ->(ids, _ctx) { ids.map { |gid| gid.model_id.to_i } } argument :operation_mode, - Types::MutationOperationModeEnum, + ::Types::MutationOperationModeEnum, required: false, - default_value: Types::MutationOperationModeEnum.default_mode, + default_value: ::Types::MutationOperationModeEnum.default_mode, description: 'Set the operation mode.' end end diff --git a/app/graphql/types/work_items/widgets/current_user_todos_type.rb b/app/graphql/types/work_items/widgets/current_user_todos_type.rb index 1c7cdd631e2..9b0893bdc36 100644 --- a/app/graphql/types/work_items/widgets/current_user_todos_type.rb +++ b/app/graphql/types/work_items/widgets/current_user_todos_type.rb @@ -10,8 +10,8 @@ module Types graphql_name 'WorkItemWidgetCurrentUserTodos' description 'Represents a todos widget' - implements Types::WorkItems::WidgetInterface - implements Types::CurrentUserTodos + implements ::Types::WorkItems::WidgetInterface + implements ::Types::CurrentUserTodos private diff --git a/app/graphql/types/work_items/widgets/custom_status_type.rb b/app/graphql/types/work_items/widgets/custom_status_type.rb index a10d0fea776..007a86e6c00 100644 --- a/app/graphql/types/work_items/widgets/custom_status_type.rb +++ b/app/graphql/types/work_items/widgets/custom_status_type.rb @@ -10,11 +10,11 @@ module Types graphql_name 'WorkItemWidgetCustomStatus' description 'Represents Custom Status widget' - implements Types::WorkItems::WidgetInterface + implements ::Types::WorkItems::WidgetInterface # TODO change the ID to CustomStatus model ID while implementing # https://gitlab.com/gitlab-org/gitlab/-/issues/498393 - field :id, Types::GlobalIDType[::WorkItems::Widgets::CustomStatus], + field :id, ::Types::GlobalIDType[::WorkItems::Widgets::CustomStatus], null: false, description: 'ID of the Custom Status.' diff --git a/app/graphql/types/work_items/widgets/description_type.rb b/app/graphql/types/work_items/widgets/description_type.rb index e5d838bd164..d8bf4f15b0c 100644 --- a/app/graphql/types/work_items/widgets/description_type.rb +++ b/app/graphql/types/work_items/widgets/description_type.rb @@ -10,7 +10,7 @@ module Types graphql_name 'WorkItemWidgetDescription' description 'Represents a description widget' - implements Types::WorkItems::WidgetInterface + implements ::Types::WorkItems::WidgetInterface field :description, GraphQL::Types::String, null: true, @@ -19,13 +19,13 @@ module Types null: false, description: 'Whether the description has been edited since the work item was created.', method: :edited? - field :last_edited_at, Types::TimeType, + field :last_edited_at, ::Types::TimeType, null: true, description: 'Timestamp of when the work item\'s description was last edited.' - field :last_edited_by, Types::UserType, + field :last_edited_by, ::Types::UserType, null: true, description: 'User that made the last edit to the work item\'s description.' - field :task_completion_status, Types::TaskCompletionStatus, null: false, + field :task_completion_status, ::Types::TaskCompletionStatus, null: false, description: 'Task completion status of the work item.' markdown_field :description_html, null: true, &:work_item diff --git a/app/graphql/types/work_items/widgets/designs_type.rb b/app/graphql/types/work_items/widgets/designs_type.rb index c4cf37c9cb7..4d43e0a438a 100644 --- a/app/graphql/types/work_items/widgets/designs_type.rb +++ b/app/graphql/types/work_items/widgets/designs_type.rb @@ -10,9 +10,9 @@ module Types graphql_name 'WorkItemWidgetDesigns' description 'Represents designs widget' - implements Types::WorkItems::WidgetInterface + implements ::Types::WorkItems::WidgetInterface - field :design_collection, Types::DesignManagement::DesignCollectionType, null: true, + field :design_collection, ::Types::DesignManagement::DesignCollectionType, null: true, description: 'Collection of design images associated with the issue.' end # rubocop:enable Graphql/AuthorizeTypes diff --git a/app/graphql/types/work_items/widgets/development_type.rb b/app/graphql/types/work_items/widgets/development_type.rb index e05e47d9321..3c5206ad8be 100644 --- a/app/graphql/types/work_items/widgets/development_type.rb +++ b/app/graphql/types/work_items/widgets/development_type.rb @@ -10,21 +10,21 @@ module Types graphql_name 'WorkItemWidgetDevelopment' description 'Represents a development widget' - implements Types::WorkItems::WidgetInterface + implements ::Types::WorkItems::WidgetInterface field :closing_merge_requests, - Types::WorkItems::ClosingMergeRequestType.connection_type, + ::Types::WorkItems::ClosingMergeRequestType.connection_type, null: true, description: 'Merge requests that will close the work item when merged.' field :related_branches, - Types::WorkItems::RelatedBranchType.connection_type, + ::Types::WorkItems::RelatedBranchType.connection_type, calls_gitaly: true, description: 'Branches that have referred to the work item, but do not have an associated merge request.', null: true do extension ::Gitlab::Graphql::Limit::FieldCallCount, limit: 1 end field :related_merge_requests, # rubocop:disable GraphQL/ExtractType -- no need to extract to related - Types::MergeRequestType.connection_type, + ::Types::MergeRequestType.connection_type, null: true, resolver: ::Resolvers::MergeRequests::WorkItemRelatedResolver, description: 'Merge requests where the work item has been mentioned. ' \ diff --git a/app/graphql/types/work_items/widgets/email_participants_type.rb b/app/graphql/types/work_items/widgets/email_participants_type.rb index 1ee532d612e..967fccf6c11 100644 --- a/app/graphql/types/work_items/widgets/email_participants_type.rb +++ b/app/graphql/types/work_items/widgets/email_participants_type.rb @@ -10,10 +10,10 @@ module Types graphql_name 'WorkItemWidgetEmailParticipants' description 'Represents email participants widget' - implements Types::WorkItems::WidgetInterface + implements ::Types::WorkItems::WidgetInterface field :email_participants, - Types::WorkItems::EmailParticipantType.connection_type, + ::Types::WorkItems::EmailParticipantType.connection_type, null: true, description: 'Collection of email participants associated with the work item.', method: :issue_email_participants diff --git a/app/graphql/types/work_items/widgets/hierarchy_type.rb b/app/graphql/types/work_items/widgets/hierarchy_type.rb index 774fe8399a9..bd5e1043808 100644 --- a/app/graphql/types/work_items/widgets/hierarchy_type.rb +++ b/app/graphql/types/work_items/widgets/hierarchy_type.rb @@ -10,7 +10,7 @@ module Types graphql_name 'WorkItemWidgetHierarchy' description 'Represents a hierarchy widget' - implements Types::WorkItems::WidgetInterface + implements ::Types::WorkItems::WidgetInterface field :parent, ::Types::WorkItemType, null: true, complexity: 5, diff --git a/app/graphql/types/work_items/widgets/hierarchy_update_input_type.rb b/app/graphql/types/work_items/widgets/hierarchy_update_input_type.rb index 2e0d6d12012..ed9dcbd4cf0 100644 --- a/app/graphql/types/work_items/widgets/hierarchy_update_input_type.rb +++ b/app/graphql/types/work_items/widgets/hierarchy_update_input_type.rb @@ -24,7 +24,7 @@ module Types description: 'Global ID of the parent work item. Use `null` to remove the association.' argument :relative_position, - Types::RelativePositionTypeEnum, + ::Types::RelativePositionTypeEnum, required: false, description: 'Type of switch. Valid values are `BEFORE` or `AFTER`.' end diff --git a/app/graphql/types/work_items/widgets/labels_type.rb b/app/graphql/types/work_items/widgets/labels_type.rb index ea6f8f52930..5a56548c39e 100644 --- a/app/graphql/types/work_items/widgets/labels_type.rb +++ b/app/graphql/types/work_items/widgets/labels_type.rb @@ -10,9 +10,9 @@ module Types graphql_name 'WorkItemWidgetLabels' description 'Represents the labels widget' - implements Types::WorkItems::WidgetInterface + implements ::Types::WorkItems::WidgetInterface - field :labels, Types::LabelType.connection_type, + field :labels, ::Types::LabelType.connection_type, null: true, description: 'Labels assigned to the work item.', resolver: Resolvers::BulkLabelsResolver diff --git a/app/graphql/types/work_items/widgets/linked_items_type.rb b/app/graphql/types/work_items/widgets/linked_items_type.rb index 28ba70278f1..894b732e324 100644 --- a/app/graphql/types/work_items/widgets/linked_items_type.rb +++ b/app/graphql/types/work_items/widgets/linked_items_type.rb @@ -8,9 +8,9 @@ module Types graphql_name 'WorkItemWidgetLinkedItems' description 'Represents the linked items widget' - implements Types::WorkItems::WidgetInterface + implements ::Types::WorkItems::WidgetInterface - field :linked_items, Types::WorkItems::LinkedItemType.connection_type, + field :linked_items, ::Types::WorkItems::LinkedItemType.connection_type, null: true, complexity: 5, experiment: { milestone: '16.3' }, extras: [:lookahead], diff --git a/app/graphql/types/work_items/widgets/linked_resources_type.rb b/app/graphql/types/work_items/widgets/linked_resources_type.rb index ef685f2d4a3..2da9aa39e2d 100644 --- a/app/graphql/types/work_items/widgets/linked_resources_type.rb +++ b/app/graphql/types/work_items/widgets/linked_resources_type.rb @@ -10,14 +10,14 @@ module Types graphql_name 'WorkItemWidgetLinkedResources' description 'Represents the linked resources widget' - implements Types::WorkItems::WidgetInterface + implements ::Types::WorkItems::WidgetInterface # linked_resources currently exposes zoom_meetings records associated with the work item. # The plan is to make this field more generic in the future as we already have another source # of linked_resources associated with the issues table. More details in # https://gitlab.com/gitlab-org/gitlab/-/merge_requests/174793#note_2256696898 field :linked_resources, - Types::WorkItems::LinkedResourceType.connection_type, + ::Types::WorkItems::LinkedResourceType.connection_type, null: true, description: 'Resources for the work item.', method: :zoom_meetings diff --git a/app/graphql/types/work_items/widgets/milestone_input_type.rb b/app/graphql/types/work_items/widgets/milestone_input_type.rb index b4cbf34e35a..dcd174f7e3d 100644 --- a/app/graphql/types/work_items/widgets/milestone_input_type.rb +++ b/app/graphql/types/work_items/widgets/milestone_input_type.rb @@ -7,7 +7,7 @@ module Types graphql_name 'WorkItemWidgetMilestoneInput' argument :milestone_id, - Types::GlobalIDType[::Milestone], + ::Types::GlobalIDType[::Milestone], required: :nullable, prepare: ->(id, _) { id.model_id unless id.nil? }, description: 'Milestone to assign to the work item.' diff --git a/app/graphql/types/work_items/widgets/milestone_type.rb b/app/graphql/types/work_items/widgets/milestone_type.rb index 96edda000c3..0b3ac182a38 100644 --- a/app/graphql/types/work_items/widgets/milestone_type.rb +++ b/app/graphql/types/work_items/widgets/milestone_type.rb @@ -10,7 +10,7 @@ module Types graphql_name 'WorkItemWidgetMilestone' description 'Represents a milestone widget' - implements Types::WorkItems::WidgetInterface + implements ::Types::WorkItems::WidgetInterface field :milestone, ::Types::MilestoneType, diff --git a/app/graphql/types/work_items/widgets/notes_type.rb b/app/graphql/types/work_items/widgets/notes_type.rb index 0177eb00c11..45398f82ab1 100644 --- a/app/graphql/types/work_items/widgets/notes_type.rb +++ b/app/graphql/types/work_items/widgets/notes_type.rb @@ -10,7 +10,7 @@ module Types graphql_name 'WorkItemWidgetNotes' description 'Represents a notes widget' - implements Types::WorkItems::WidgetInterface + implements ::Types::WorkItems::WidgetInterface field :discussion_locked, GraphQL::Types::Boolean, null: true, @@ -19,7 +19,7 @@ module Types # This field loads user comments, system notes and resource events as a discussion for an work item, # raising the complexity considerably. In order to discourage fetching this field as part of fetching # a list of issues we raise the complexity - field :discussions, Types::Notes::DiscussionType.connection_type, + field :discussions, ::Types::Notes::DiscussionType.connection_type, null: true, skip_type_authorization: [:read_note, :read_emoji], description: "Notes on this work item.", diff --git a/app/graphql/types/work_items/widgets/notifications_type.rb b/app/graphql/types/work_items/widgets/notifications_type.rb index 85928817d07..2d1e02c8b0e 100644 --- a/app/graphql/types/work_items/widgets/notifications_type.rb +++ b/app/graphql/types/work_items/widgets/notifications_type.rb @@ -10,7 +10,7 @@ module Types graphql_name 'WorkItemWidgetNotifications' description 'Represents the notifications widget' - implements Types::WorkItems::WidgetInterface + implements ::Types::WorkItems::WidgetInterface field :subscribed, GraphQL::Types::Boolean, null: false, diff --git a/app/graphql/types/work_items/widgets/participants_type.rb b/app/graphql/types/work_items/widgets/participants_type.rb index 0098e656eae..bd1bd3f5cd8 100644 --- a/app/graphql/types/work_items/widgets/participants_type.rb +++ b/app/graphql/types/work_items/widgets/participants_type.rb @@ -9,9 +9,9 @@ module Types graphql_name 'WorkItemWidgetParticipants' description 'Represents a participants widget' - implements Types::WorkItems::WidgetInterface + implements ::Types::WorkItems::WidgetInterface - field :participants, Types::UserType.connection_type, + field :participants, ::Types::UserType.connection_type, null: true, description: 'Participants in the work item.' diff --git a/app/graphql/types/work_items/widgets/start_and_due_date_type.rb b/app/graphql/types/work_items/widgets/start_and_due_date_type.rb index f75ebb1495d..93061befd99 100644 --- a/app/graphql/types/work_items/widgets/start_and_due_date_type.rb +++ b/app/graphql/types/work_items/widgets/start_and_due_date_type.rb @@ -9,15 +9,15 @@ module Types graphql_name 'WorkItemWidgetStartAndDueDate' description 'Represents a start and due date widget' - implements Types::WorkItems::WidgetInterface + implements ::Types::WorkItems::WidgetInterface field :due_date, - Types::DateType, + ::Types::DateType, null: true, description: 'Due date of the work item.' field :start_date, - Types::DateType, + ::Types::DateType, null: true, description: 'Start date of the work item.' diff --git a/app/graphql/types/work_items/widgets/start_and_due_date_update_input_type.rb b/app/graphql/types/work_items/widgets/start_and_due_date_update_input_type.rb index 3ae8cc77f03..1de0dcd11cb 100644 --- a/app/graphql/types/work_items/widgets/start_and_due_date_update_input_type.rb +++ b/app/graphql/types/work_items/widgets/start_and_due_date_update_input_type.rb @@ -7,12 +7,12 @@ module Types graphql_name 'WorkItemWidgetStartAndDueDateUpdateInput' argument :due_date, - Types::DateType, + ::Types::DateType, required: false, description: 'Due date for the work item.' argument :start_date, - Types::DateType, + ::Types::DateType, required: false, description: 'Start date for the work item.' end diff --git a/app/graphql/types/work_items/widgets/time_tracking/time_tracking_input_type.rb b/app/graphql/types/work_items/widgets/time_tracking/time_tracking_input_type.rb index 7e9251197a4..b07e4b6fad1 100644 --- a/app/graphql/types/work_items/widgets/time_tracking/time_tracking_input_type.rb +++ b/app/graphql/types/work_items/widgets/time_tracking/time_tracking_input_type.rb @@ -11,7 +11,7 @@ module Types required: false, description: 'Time estimate for the work item in human readable format. For example: 1h 30m.' - argument :timelog, Types::WorkItems::Widgets::TimeTracking::TimelogInputType, + argument :timelog, ::Types::WorkItems::Widgets::TimeTracking::TimelogInputType, required: false, description: 'Timelog data for time spent on the work item.' end diff --git a/app/graphql/types/work_items/widgets/time_tracking/time_tracking_type.rb b/app/graphql/types/work_items/widgets/time_tracking/time_tracking_type.rb index eea6db3a35a..22a97258222 100644 --- a/app/graphql/types/work_items/widgets/time_tracking/time_tracking_type.rb +++ b/app/graphql/types/work_items/widgets/time_tracking/time_tracking_type.rb @@ -9,7 +9,7 @@ module Types graphql_name 'WorkItemWidgetTimeTracking' description 'Represents a time tracking widget' - implements Types::WorkItems::WidgetInterface + implements ::Types::WorkItems::WidgetInterface field :time_estimate, GraphQL::Types::Int, null: true, @@ -18,7 +18,7 @@ module Types null: true, description: 'Total time (in seconds) reported as spent on the work item.' - field :timelogs, Types::WorkItems::Widgets::TimeTracking::TimelogType.connection_type, + field :timelogs, ::Types::WorkItems::Widgets::TimeTracking::TimelogType.connection_type, null: true, description: 'Timelogs on the work item.' end diff --git a/app/graphql/types/work_items/widgets/time_tracking/timelog_input_type.rb b/app/graphql/types/work_items/widgets/time_tracking/timelog_input_type.rb index 82589812b32..72d6bb2128a 100644 --- a/app/graphql/types/work_items/widgets/time_tracking/timelog_input_type.rb +++ b/app/graphql/types/work_items/widgets/time_tracking/timelog_input_type.rb @@ -11,7 +11,7 @@ module Types required: true, description: 'Amount of time spent in human readable format. For example: 1h 30m.' - argument :spent_at, Types::TimeType, + argument :spent_at, ::Types::TimeType, required: false, description: 'Timestamp of when the time tracked was spent at, ' \ 'if not provided would be set to current timestamp.' diff --git a/app/graphql/types/work_items/widgets/time_tracking/timelog_type.rb b/app/graphql/types/work_items/widgets/time_tracking/timelog_type.rb index a6a552f60f9..942542bf164 100644 --- a/app/graphql/types/work_items/widgets/time_tracking/timelog_type.rb +++ b/app/graphql/types/work_items/widgets/time_tracking/timelog_type.rb @@ -8,14 +8,14 @@ module Types class TimelogType < BaseObject graphql_name 'WorkItemTimelog' - connection_type_class Types::TimeTracking::TimelogConnectionType - expose_permissions Types::PermissionTypes::Timelog + connection_type_class ::Types::TimeTracking::TimelogConnectionType + expose_permissions ::Types::PermissionTypes::Timelog field :id, GraphQL::Types::ID, null: false, description: 'Internal ID of the timelog.' - field :spent_at, Types::TimeType, + field :spent_at, ::Types::TimeType, null: true, description: 'Timestamp of when the time tracked was spent at.' @@ -23,11 +23,11 @@ module Types null: false, description: 'Time spent displayed in seconds.' - field :user, Types::UserType, + field :user, ::Types::UserType, null: false, description: 'User that logged the time.' - field :note, Types::Notes::NoteType, + field :note, ::Types::Notes::NoteType, null: true, description: 'Note where the quick action was executed to add the logged time.' diff --git a/app/graphql/types/work_items/work_item_type_counts_by_state_type.rb b/app/graphql/types/work_items/work_item_type_counts_by_state_type.rb index 3f8d4c5fc95..ed0146ef355 100644 --- a/app/graphql/types/work_items/work_item_type_counts_by_state_type.rb +++ b/app/graphql/types/work_items/work_item_type_counts_by_state_type.rb @@ -7,10 +7,10 @@ module Types graphql_name 'WorkItemTypeCountsByState' description 'Represents work item counts for the work item type' - field :work_item_type, Types::WorkItems::TypeType, null: false, + field :work_item_type, ::Types::WorkItems::TypeType, null: false, description: 'Work item type.' - field :counts_by_state, Types::WorkItemStateCountsType, null: false, + field :counts_by_state, ::Types::WorkItemStateCountsType, null: false, description: 'Total number of work items for the represented states.' end # rubocop: enable Graphql/AuthorizeTypes diff --git a/app/graphql/types/work_items/work_item_type_depth_limit_reached_by_type.rb b/app/graphql/types/work_items/work_item_type_depth_limit_reached_by_type.rb index 9838ddf45e1..64b5e995b64 100644 --- a/app/graphql/types/work_items/work_item_type_depth_limit_reached_by_type.rb +++ b/app/graphql/types/work_items/work_item_type_depth_limit_reached_by_type.rb @@ -7,7 +7,7 @@ module Types graphql_name 'WorkItemTypeDepthLimitReachedByType' description 'Represents Depth limit reached for the allowed work item type.' - field :work_item_type, Types::WorkItems::TypeType, null: false, + field :work_item_type, ::Types::WorkItems::TypeType, null: false, description: 'Work item type.' field :depth_limit_reached, GraphQL::Types::Boolean, diff --git a/app/helpers/auth_helper.rb b/app/helpers/auth_helper.rb index c842842f023..c6375e61806 100644 --- a/app/helpers/auth_helper.rb +++ b/app/helpers/auth_helper.rb @@ -111,6 +111,15 @@ module AuthHelper providers.map(&:name).map(&:to_sym) end + def oidc_providers + providers = Gitlab.config.omniauth.providers.select do |provider| + provider.name == 'openid_connect' || provider.dig('args', + 'strategy_class') == 'OmniAuth::Strategies::OpenIDConnect' + end + + providers.map(&:name).map(&:to_sym) + end + def any_form_based_providers_enabled? form_based_providers.any? { |provider| form_enabled_for_sign_in?(provider) } end diff --git a/app/services/ci/register_job_service.rb b/app/services/ci/register_job_service.rb index 1341bfa27e2..d0c9c2c6678 100644 --- a/app/services/ci/register_job_service.rb +++ b/app/services/ci/register_job_service.rb @@ -22,6 +22,7 @@ module Ci @runner = runner @runner_manager = runner_manager @metrics = ::Gitlab::Ci::Queue::Metrics.new(runner) + @logger = ::Ci::RegisterJobService::Logger.new(runner: runner) end def execute(params = {}) @@ -30,9 +31,7 @@ module Ci @metrics.increment_queue_operation(:queue_attempt) - result = @metrics.observe_queue_time(:process, @runner.runner_type) do - process_queue(params) - end + result = process_queue_with_instrumentation(params) # Since we execute this query against replica it might lead to false-positive # We might receive the positive response: "hi, we don't have any more builds for you". @@ -47,10 +46,21 @@ module Ci else result end + + ensure + @logger.commit end private + def process_queue_with_instrumentation(params) + @metrics.observe_queue_time(:process, @runner.runner_type) do + @logger.instrument(:process_queue, once: true) do + process_queue(params) + end + end + end + def process_queue(params) valid = true depth = 0 @@ -82,12 +92,16 @@ module Ci next end - result = process_build(build, params) + result = @logger.instrument(:process_build) do + process_build(build, params) + end next unless result if result.valid? - @metrics.register_success(result.build_presented) - @metrics.observe_queue_depth(:found, depth) + @logger.instrument(:metrics_success, once: true) do + @metrics.register_success(result.build_presented) + @metrics.observe_queue_depth(:found, depth) + end return result # rubocop:disable Cop/AvoidReturnFromBlocks else @@ -147,7 +161,9 @@ module Ci ::Gitlab::Database::LoadBalancing::SessionMap.clear_session @metrics.observe_queue_time(:retrieve, @runner.runner_type) do - queue_query_proc.call + @logger.instrument(:retrieve_queue, once: true) do + queue_query_proc.call + end end end diff --git a/app/services/ci/register_job_service/logger.rb b/app/services/ci/register_job_service/logger.rb new file mode 100644 index 00000000000..6b954a3c47e --- /dev/null +++ b/app/services/ci/register_job_service/logger.rb @@ -0,0 +1,99 @@ +# frozen_string_literal: true + +module Ci + class RegisterJobService + class Logger + include ::Gitlab::Utils::StrongMemoize + + MAX_DURATION = 5.seconds + + def self.current_monotonic_time + ::Gitlab::Metrics::System.monotonic_time + end + + def initialize(runner:, destination: ::Gitlab::AppJsonLogger) + @started_at = current_monotonic_time + @runner = runner + @destination = destination + + yield(self) if block_given? + end + + def instrument(operation, once: false) + return yield unless enabled? + + raise ArgumentError, 'block not given' unless block_given? + + op_started_at = current_monotonic_time + + result = yield + + observe(:"#{operation}_duration_s", current_monotonic_time - op_started_at, once: once) + + result + end + + def commit + return unless log? + + attributes = { + class: self.class.name.to_s, + message: 'RegisterJobService exceeded maximum duration', + total_duration_s: age, + runner_id: runner.id, + runner_type: runner.runner_type + }.merge(observations_hash) + + destination.info(attributes) + end + + private + + attr_reader :runner, :destination, :started_at + + delegate :current_monotonic_time, to: :class + + def observe(operation, value, once: false) + return unless enabled? + + if once + observations[operation] = value + else + observations[operation] ||= [] + observations[operation].push(value) + end + end + + def observations_hash + observations.transform_values do |observation| + next if observation.blank? + + if observation.is_a?(Array) + { count: observation.size, max: observation.max, sum: observation.sum } + else + observation + end + end.compact + end + + def age + current_monotonic_time - started_at + end + + def log? + return false unless enabled? + + age > MAX_DURATION + end + + def enabled? + ::Feature.enabled?(:ci_register_job_instrumentation_logger, :instance) + end + strong_memoize_attr :enabled? + + def observations + @observations ||= {} + end + end + end +end diff --git a/app/views/groups/_flash_messages.html.haml b/app/views/groups/_flash_messages.html.haml index b6b409967b0..fc0d09eb563 100644 --- a/app/views/groups/_flash_messages.html.haml +++ b/app/views/groups/_flash_messages.html.haml @@ -1,2 +1,2 @@ = content_for :flash_message do - = render_if_exists 'shared/shared_runners_minutes_limit', namespace: @group, classes: [container_class] + = render_if_exists 'shared/shared_runners_minutes_limit', namespace: @group diff --git a/app/views/profiles/usage_quotas/index.html.haml b/app/views/profiles/usage_quotas/index.html.haml index 9863b8573ac..2747a928650 100644 --- a/app/views/profiles/usage_quotas/index.html.haml +++ b/app/views/profiles/usage_quotas/index.html.haml @@ -1,6 +1,9 @@ - content_for :usage_quotas_subtitle do = s_('UsageQuota|Usage of resources across your projects') +- content_for :usage_quotas_alerts do + = render 'shared/shared_runners_minutes_limit', namespace: @namespace, usage_quotas_link_hidden: true, classes: 'gl-my-3' + - content_for :usage_quotas_tabs do = render_if_exists 'shared/usage_quotas/tabs_content/pipelines' #js-storage-usage-app{ data: storage_usage_app_data(@namespace) } diff --git a/config/feature_flags/ops/ci_register_job_instrumentation_logger.yml b/config/feature_flags/ops/ci_register_job_instrumentation_logger.yml new file mode 100644 index 00000000000..b171a96e4a9 --- /dev/null +++ b/config/feature_flags/ops/ci_register_job_instrumentation_logger.yml @@ -0,0 +1,9 @@ +--- +name: ci_register_job_instrumentation_logger +feature_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/450674 +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/177414 +rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/512402 +milestone: '17.9' +group: group::pipeline authoring +type: ops +default_enabled: false diff --git a/db/docs/bulk_import_entities.yml b/db/docs/bulk_import_entities.yml index 10a1e6195eb..b9a56aff61d 100644 --- a/db/docs/bulk_import_entities.yml +++ b/db/docs/bulk_import_entities.yml @@ -7,6 +7,9 @@ feature_categories: description: Used to store and track the status of the migration of groups or projects introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/42978 milestone: '13.5' -gitlab_schema: gitlab_main -sharding_key_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/463854 +gitlab_schema: gitlab_main_cell +sharding_key: + project_id: projects + namespace_id: namespaces + organization_id: organizations table_size: small diff --git a/db/docs/operations_scopes.yml b/db/docs/operations_scopes.yml index 84e7ecc8ab9..3e4899ae079 100644 --- a/db/docs/operations_scopes.yml +++ b/db/docs/operations_scopes.yml @@ -17,5 +17,4 @@ desired_sharding_key: table: operations_strategies sharding_key: project_id belongs_to: strategy - awaiting_backfill_on_parent: true table_size: small diff --git a/db/docs/operations_strategies.yml b/db/docs/operations_strategies.yml index f4742d77f2c..9ee8095baf0 100644 --- a/db/docs/operations_strategies.yml +++ b/db/docs/operations_strategies.yml @@ -8,14 +8,6 @@ description: https://docs.gitlab.com/ee/operations/feature_flags.html#feature-fl introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/24819 milestone: '12.8' gitlab_schema: gitlab_main_cell -desired_sharding_key: - project_id: - references: projects - backfill_via: - parent: - foreign_key: feature_flag_id - table: operations_feature_flags - sharding_key: project_id - belongs_to: feature_flag -desired_sharding_key_migration_job_name: BackfillOperationsStrategiesProjectId table_size: small +sharding_key: + project_id: projects diff --git a/db/docs/packages_debian_group_distribution_keys.yml b/db/docs/packages_debian_group_distribution_keys.yml index dcb95e92af4..ff7b33e1a87 100644 --- a/db/docs/packages_debian_group_distribution_keys.yml +++ b/db/docs/packages_debian_group_distribution_keys.yml @@ -8,14 +8,6 @@ description: Debian group-level distribution keys introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/60993 milestone: '14.0' gitlab_schema: gitlab_main_cell -desired_sharding_key: - group_id: - references: namespaces - backfill_via: - parent: - foreign_key: distribution_id - table: packages_debian_group_distributions - sharding_key: group_id - belongs_to: distribution -desired_sharding_key_migration_job_name: BackfillPackagesDebianGroupDistributionKeysGroupId table_size: small +sharding_key: + group_id: namespaces diff --git a/db/post_migrate/20250109061618_add_packages_debian_group_distribution_keys_group_id_not_null_constraint.rb b/db/post_migrate/20250109061618_add_packages_debian_group_distribution_keys_group_id_not_null_constraint.rb new file mode 100644 index 00000000000..c40de0a92a4 --- /dev/null +++ b/db/post_migrate/20250109061618_add_packages_debian_group_distribution_keys_group_id_not_null_constraint.rb @@ -0,0 +1,14 @@ +# frozen_string_literal: true + +class AddPackagesDebianGroupDistributionKeysGroupIdNotNullConstraint < Gitlab::Database::Migration[2.2] + disable_ddl_transaction! + milestone '17.9' + + def up + add_not_null_constraint :packages_debian_group_distribution_keys, :group_id + end + + def down + remove_not_null_constraint :packages_debian_group_distribution_keys, :group_id + end +end diff --git a/db/post_migrate/20250109065940_add_operations_strategies_project_id_not_null_constraint.rb b/db/post_migrate/20250109065940_add_operations_strategies_project_id_not_null_constraint.rb new file mode 100644 index 00000000000..28642fd8292 --- /dev/null +++ b/db/post_migrate/20250109065940_add_operations_strategies_project_id_not_null_constraint.rb @@ -0,0 +1,14 @@ +# frozen_string_literal: true + +class AddOperationsStrategiesProjectIdNotNullConstraint < Gitlab::Database::Migration[2.2] + disable_ddl_transaction! + milestone '17.9' + + def up + add_not_null_constraint :operations_strategies, :project_id + end + + def down + remove_not_null_constraint :operations_strategies, :project_id + end +end diff --git a/db/post_migrate/20250115095728_idx_vulnerability_statistics_on_traversal_ids_and_letter_grade.rb b/db/post_migrate/20250115095728_idx_vulnerability_statistics_on_traversal_ids_and_letter_grade.rb new file mode 100644 index 00000000000..5c87bfaa2f4 --- /dev/null +++ b/db/post_migrate/20250115095728_idx_vulnerability_statistics_on_traversal_ids_and_letter_grade.rb @@ -0,0 +1,17 @@ +# frozen_string_literal: true + +class IdxVulnerabilityStatisticsOnTraversalIdsAndLetterGrade < Gitlab::Database::Migration[2.2] + disable_ddl_transaction! + milestone '17.9' + + INDEX_NAME = 'idx_vulnerability_statistics_on_traversal_ids_and_letter_grade' + + def up + add_concurrent_index :vulnerability_statistics, %i[traversal_ids letter_grade], name: INDEX_NAME, + where: 'archived = FALSE' + end + + def down + remove_concurrent_index_by_name :vulnerability_statistics, INDEX_NAME + end +end diff --git a/db/schema_migrations/20250109061618 b/db/schema_migrations/20250109061618 new file mode 100644 index 00000000000..dfc417fc0f5 --- /dev/null +++ b/db/schema_migrations/20250109061618 @@ -0,0 +1 @@ +06496ef4d857b84d9714fbd56f78634fda30f86543d0bfa5ca6460cd54a3df25 \ No newline at end of file diff --git a/db/schema_migrations/20250109065940 b/db/schema_migrations/20250109065940 new file mode 100644 index 00000000000..6adcf658de1 --- /dev/null +++ b/db/schema_migrations/20250109065940 @@ -0,0 +1 @@ +c6237c9abff3d1de38863ff439cacc5a3d9f729c4a9c9a23f315e3a657133ee6 \ No newline at end of file diff --git a/db/schema_migrations/20250115095728 b/db/schema_migrations/20250115095728 new file mode 100644 index 00000000000..bbf058d30bd --- /dev/null +++ b/db/schema_migrations/20250115095728 @@ -0,0 +1 @@ +992aaca50dcf7bd21dabd4d0cd5f534b0c514e2a6b3392ef58cc9155966632e1 \ No newline at end of file diff --git a/db/structure.sql b/db/structure.sql index ec51c6336ae..fc34acfa3d5 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -16783,7 +16783,8 @@ CREATE TABLE operations_strategies ( feature_flag_id bigint NOT NULL, name character varying(255) NOT NULL, parameters jsonb DEFAULT '{}'::jsonb NOT NULL, - project_id bigint + project_id bigint, + CONSTRAINT check_85b486853f CHECK ((project_id IS NOT NULL)) ); CREATE SEQUENCE operations_strategies_id_seq @@ -17159,6 +17160,7 @@ CREATE TABLE packages_debian_group_distribution_keys ( public_key text NOT NULL, fingerprint text NOT NULL, group_id bigint, + CONSTRAINT check_008dba9ceb CHECK ((group_id IS NOT NULL)), CONSTRAINT check_bc95dc3fbe CHECK ((char_length(fingerprint) <= 255)), CONSTRAINT check_f708183491 CHECK ((char_length(public_key) <= 524288)) ); @@ -30217,6 +30219,8 @@ CREATE INDEX idx_vulnerability_reads_for_traversal_ids_queries_srt_severity ON v CREATE INDEX idx_vulnerability_reads_project_id_scanner_id_vulnerability_id ON vulnerability_reads USING btree (project_id, scanner_id, vulnerability_id); +CREATE INDEX idx_vulnerability_statistics_on_traversal_ids_and_letter_grade ON vulnerability_statistics USING btree (traversal_ids, letter_grade) WHERE (archived = false); + CREATE UNIQUE INDEX idx_wi_type_custom_fields_on_ns_id_wi_type_id_custom_field_id ON work_item_type_custom_fields USING btree (namespace_id, work_item_type_id, custom_field_id); CREATE INDEX idx_zoekt_repositories_on_zoekt_index_id_and_state ON zoekt_repositories USING btree (zoekt_index_id, state); diff --git a/doc/administration/auth/oidc.md b/doc/administration/auth/oidc.md index 6e3e107292f..e2cd7e1a6ac 100644 --- a/doc/administration/auth/oidc.md +++ b/doc/administration/auth/oidc.md @@ -820,9 +820,6 @@ You should do this in either of the following scenarios: - [Migrating to the OpenID Connect protocol](#migrate-to-generic-openid-connect-configuration). - Offering different levels of authentication. -NOTE: -This is not compatible with [configuring users based on OIDC group membership](#configure-users-based-on-oidc-group-membership). For more information, see [issue 408248](https://gitlab.com/gitlab-org/gitlab/-/issues/408248). - The following example configurations show how to offer different levels of authentication, one option with 2FA and one without 2FA. For Linux package installations: diff --git a/doc/administration/package_information/supported_os.md b/doc/administration/package_information/supported_os.md index befa45eae44..5183377310c 100644 --- a/doc/administration/package_information/supported_os.md +++ b/doc/administration/package_information/supported_os.md @@ -54,7 +54,6 @@ These versions of openSUSE Leap and SUSE Linux Enterprise Server are supported. | Operating system version | First supported GitLab version | Architecture | Installation documentation | Operating system EOL | Details | |:--------------------------------|:-------------------------------|:--------------------|:-------------------------------------------------------------------------------------------|:---------------------|:--------| -| openSUSE Leap 15.5 | GitLab CE / GitLab EE 16.4.0 | `x86_64`, `aarch64` | [openSUSE installation documentation](https://about.gitlab.com/install/#opensuse-leap) | Dec 2024 | [openSUSE details](https://en.opensuse.org/Lifetime) | | openSUSE Leap 15.6 | GitLab CE / GitLab EE 17.6.0 | `x86_64`, `aarch64` | [openSUSE installation documentation](https://about.gitlab.com/install/#opensuse-leap) | Dec 2025 | [openSUSE details](https://en.opensuse.org/Lifetime) | | SUSE Linux Enterprise Server 12 | GitLab EE 9.0.0 | `x86_64` | [Use OpenSUSE installation documentation](https://about.gitlab.com/install/#opensuse-leap) | Oct 2027 | [SUSE Linux Enterprise Server details](https://www.suse.com/lifecycle/) | | SUSE Linux Enterprise Server 15 | GitLab EE 14.8.0 | `x86_64` | [Use OpenSUSE installation documentation](https://about.gitlab.com/install/#opensuse-leap) | Dec 2024 | [SUSE Linux Enterprise Server details](https://www.suse.com/lifecycle/) | @@ -154,6 +153,7 @@ release for them can be found below: | OpenSUSE 15.2 | [December 2021](https://en.opensuse.org/Lifetime#Discontinued_distributions) | [GitLab CE](https://packages.gitlab.com/app/gitlab/gitlab-ce/search?q=gitlab-ce-14.7&dist=opensuse%2F15.2) / [GitLab EE](https://packages.gitlab.com/app/gitlab/gitlab-ee/search?q=gitlab-ee-14.7&dist=opensuse%2F15.2) 14.7 | | OpenSUSE 15.3 | [December 2022](https://en.opensuse.org/Lifetime#Discontinued_distributions) | [GitLab CE](https://packages.gitlab.com/app/gitlab/gitlab-ce/search?q=gitlab-ce-15.10&dist=opensuse%2F15.3) / [GitLab EE](https://packages.gitlab.com/app/gitlab/gitlab-ee/search?q=gitlab-ee-15.10&dist=opensuse%2F15.3) 15.10 | | OpenSUSE 15.4 | [December 2023](https://en.opensuse.org/Lifetime#Discontinued_distributions) | [GitLab CE](https://packages.gitlab.com/app/gitlab/gitlab-ce/search?q=gitlab-ce-16.7&dist=opensuse%2F15.4) / [GitLab EE](https://packages.gitlab.com/app/gitlab/gitlab-ee/search?q=gitlab-ee-16.7&dist=opensuse%2F15.4) 16.7 | +| OpenSUSE 15.5 | [December 2024](https://en.opensuse.org/Lifetime#Discontinued_distributions) | [GitLab CE](https://packages.gitlab.com/app/gitlab/gitlab-ce/search?q=gitlab-ce-17.8&dist=opensuse%2F15.5) / [GitLab EE](https://packages.gitlab.com/app/gitlab/gitlab-ee/search?q=gitlab-ee-17.8&dist=opensuse%2F15.5) 17.8 | | Raspbian Wheezy | [May 2015](https://downloads.raspberrypi.org/raspbian/images/raspbian-2015-05-07/) | [GitLab CE](https://packages.gitlab.com/app/gitlab/raspberry-pi2/search?q=gitlab-ce_8.17&dist=debian%2Fwheezy) 8.17 | | Raspbian Jessie | [May 2017](https://downloads.raspberrypi.org/raspbian/images/raspbian-2017-07-05/) | [GitLab CE](https://packages.gitlab.com/app/gitlab/raspberry-pi2/search?q=gitlab-ce_11.7&dist=debian%2Fjessie) 11.7 | | Raspbian Stretch | [June 2020](https://downloads.raspberrypi.org/raspbian/images/raspbian-2019-04-09/) | [GitLab CE](https://packages.gitlab.com/app/gitlab/raspberry-pi2/search?q=gitlab-ce_13.3&dist=raspbian%2Fstretch) 13.3 | diff --git a/doc/editor_extensions/neovim/neovim_troubleshooting.md b/doc/editor_extensions/neovim/neovim_troubleshooting.md index e62aa4ae515..f8bd343d2a0 100644 --- a/doc/editor_extensions/neovim/neovim_troubleshooting.md +++ b/doc/editor_extensions/neovim/neovim_troubleshooting.md @@ -44,12 +44,16 @@ These checks help you identify and resolve configuration issues on your own. ## Enable debug logs -To enable more logging: +Enable debug logs to capture more information about problems. Debug logs can +contain sensitive workspace configuration, so review the output before sharing +it with others. -- Set the `vim.lsp` log level in `init.lua`: +To enable extra logging: + +- Set the `vim.lsp` log level in your current buffer: ```lua - vim.lsp.set_log_level('debug') + :lua vim.lsp.set_log_level('debug') ``` ## Reproduce the problem in a minimal project @@ -69,6 +73,8 @@ a problem with Code Suggestions: 1. Create a new file named `minimal.lua`, with these contents: ```lua + -- NOTE: Do not set this in your usual configuration, as this log level + -- could include sensitive workspace configuration. vim.lsp.set_log_level('debug') vim.opt.rtp:append('$HOME/.local/share/nvim/site/pack/gitlab/start/gitlab.vim') @@ -87,11 +93,9 @@ a problem with Code Suggestions: ``` 1. Attempt to reproduce the behavior you experienced. Adjust `minimal.lua` or other project files as needed. -1. View recent entries in `~/.local/state/nvim/lsp.log` and capture relevant output: - - ```plaintext - echo ~/.local/state/nvim/lsp.log - ``` +1. View recent entries in `~/.local/state/nvim/lsp.log` and capture relevant output. +1. Redact any references to sensitive information, such as tokens beginning with `glpat-`. +1. Remove sensitive information from any Vim registers or log files. ### Error: `GCS:unavailable` diff --git a/doc/user/analytics/ai_impact_analytics.md b/doc/user/analytics/ai_impact_analytics.md index 9370991de61..65c4ac3c08f 100644 --- a/doc/user/analytics/ai_impact_analytics.md +++ b/doc/user/analytics/ai_impact_analytics.md @@ -70,8 +70,5 @@ Prerequisites: 1. Select **Analyze > Analytics Dashboards**. 1. Select **AI impact analytics**. -To retrieve AI impact metrics, you can also use the following GraphQL APIs: - -- [`AiMetrics`](../../api/graphql/reference/index.md#aimetrics) - Requires ClickHouse -- [`AiUserMetrics`](../../api/graphql/reference/index.md#aiusermetrics) - Requires ClickHouse -- [`AiUsageData`](../../api/graphql/reference/index.md#aiusagedata) - Does not require ClickHouse +To retrieve AI impact metrics, you can also use the `AiMetrics`, `AiUserMetrics`, and `AiUsageData` [GraphQL APIs](../../api/graphql/reference/index.md). +For an overview and sample queries, see [issue 512931](https://gitlab.com/gitlab-org/gitlab/-/issues/512931). diff --git a/doc/user/gitlab_duo_chat/examples.md b/doc/user/gitlab_duo_chat/examples.md index 1135d42c147..34fbac861fc 100644 --- a/doc/user/gitlab_duo_chat/examples.md +++ b/doc/user/gitlab_duo_chat/examples.md @@ -405,6 +405,8 @@ To troubleshoot a failed CI/CD job: An analysis of the reasons for the failure and an example fix is displayed. +Provide feedback on this feature in [epic 13872](https://gitlab.com/groups/gitlab-org/-/epics/13872). + ## Explain a vulnerability DETAILS: diff --git a/lib/api/conan/v1/instance_packages.rb b/lib/api/conan/v1/instance_packages.rb index 786d3a2bad6..113f6de07d1 100644 --- a/lib/api/conan/v1/instance_packages.rb +++ b/lib/api/conan/v1/instance_packages.rb @@ -5,14 +5,14 @@ module API module Conan module V1 class InstancePackages < ::API::Base - helpers do - def search_project - nil - end - end - namespace 'packages/conan/v1' do include ::API::Concerns::Packages::Conan::V1Endpoints + + helpers do + def search_project + nil + end + end end end end diff --git a/lib/api/conan/v1/project_packages.rb b/lib/api/conan/v1/project_packages.rb index e63c7d4191a..c81cdaa724e 100644 --- a/lib/api/conan/v1/project_packages.rb +++ b/lib/api/conan/v1/project_packages.rb @@ -5,12 +5,6 @@ module API module Conan module V1 class ProjectPackages < ::API::Base - helpers do - def search_project - project - end - end - params do requires :id, types: [String, Integer], desc: 'The ID or URL-encoded path of the project' end diff --git a/lib/api/concerns/packages/conan/shared_endpoints.rb b/lib/api/concerns/packages/conan/shared_endpoints.rb index aa27061ce66..c91733fcede 100644 --- a/lib/api/concerns/packages/conan/shared_endpoints.rb +++ b/lib/api/concerns/packages/conan/shared_endpoints.rb @@ -47,6 +47,27 @@ module API not_found! if Gitlab::FIPS.enabled? require_packages_enabled! end + + desc 'Search for packages' do + detail 'This feature was introduced in GitLab 12.4' + success code: 200 + failure [ + { code: 404, message: 'Not Found' } + ] + tags %w[conan_packages] + end + + params do + requires :q, type: String, desc: 'Search query', documentation: { example: 'Hello*' } + end + + route_setting :authentication, job_token_allowed: true, basic_auth_personal_access_token: true + + get 'conans/search', urgency: :low do + service = ::Packages::Conan::SearchService.new(search_project, current_user, query: params[:q]).execute + + service.payload + end end end end diff --git a/lib/api/concerns/packages/conan/v1_endpoints.rb b/lib/api/concerns/packages/conan/v1_endpoints.rb index 06d43abd871..f50c83f2ff0 100644 --- a/lib/api/concerns/packages/conan/v1_endpoints.rb +++ b/lib/api/concerns/packages/conan/v1_endpoints.rb @@ -43,27 +43,6 @@ module API header 'X-Conan-Server-Capabilities', x_conan_server_capabilities_header.join(',') end - desc 'Search for packages' do - detail 'This feature was introduced in GitLab 12.4' - success code: 200 - failure [ - { code: 404, message: 'Not Found' } - ] - tags %w[conan_packages] - end - - params do - requires :q, type: String, desc: 'Search query', documentation: { example: 'Hello*' } - end - - route_setting :authentication, job_token_allowed: true, basic_auth_personal_access_token: true - - get 'conans/search', urgency: :low do - service = ::Packages::Conan::SearchService.new(search_project, current_user, query: params[:q]).execute - - service.payload - end - namespace 'users' do before do authenticate! diff --git a/lib/api/helpers/packages/conan/api_helpers.rb b/lib/api/helpers/packages/conan/api_helpers.rb index 9aa478756f7..e5e7442d22e 100644 --- a/lib/api/helpers/packages/conan/api_helpers.rb +++ b/lib/api/helpers/packages/conan/api_helpers.rb @@ -327,6 +327,10 @@ module API def package_scope params[:id].present? ? :project : :instance end + + def search_project + project + end end end end diff --git a/lib/gitlab/auth/o_auth/provider.rb b/lib/gitlab/auth/o_auth/provider.rb index e4fa833df73..eef3ecdb426 100644 --- a/lib/gitlab/auth/o_auth/provider.rb +++ b/lib/gitlab/auth/o_auth/provider.rb @@ -68,7 +68,8 @@ module Gitlab end else provider = Gitlab.config.omniauth.providers.find do |provider| - provider.name == name || (provider.name == 'openid_connect' && provider.dig(:args, :name) == name) + provider.name == name || + (AuthHelper.oidc_providers.include?(provider.name.to_sym) && provider.dig(:args, :name) == name) end merge_provider_args_with_defaults!(provider) diff --git a/qa/qa/page/group/runners/index.rb b/qa/qa/page/group/runners/index.rb index bfc5232cc6b..6d01a50646f 100644 --- a/qa/qa/page/group/runners/index.rb +++ b/qa/qa/page/group/runners/index.rb @@ -55,6 +55,14 @@ module QA def has_no_runner?(runner) has_no_element?("runner-row-#{runner.id}") end + + def go_to_runner_managers_page(runner) + within_element("runner-row-#{runner.id}") do + within_element("td-summary") do + find_element("a[href*='/runners/#{runner.id}']").click + end + end + end end end end diff --git a/qa/qa/page/runners/runner_managers_detail.rb b/qa/qa/page/runners/runner_managers_detail.rb new file mode 100644 index 00000000000..1195cabdb50 --- /dev/null +++ b/qa/qa/page/runners/runner_managers_detail.rb @@ -0,0 +1,24 @@ +# frozen_string_literal: true + +module QA + module Page + module Runners + class RunnerManagersDetail < Page::Base + view "app/assets/javascripts/ci/runner/components/runner_managers_detail.vue" do + element "runner-button" + end + + def expand_runners + find_element("runner-button").click + end + + def has_online_runner? + expand_runners + within_element("td-status") do + has_element?("status-active-icon") + end + end + end + end + end +end diff --git a/qa/qa/specs/features/browser_ui/4_verify/runner/register_group_runner_spec.rb b/qa/qa/specs/features/browser_ui/4_verify/runner/register_group_runner_spec.rb index ed27d02b70e..f3f3d6616c8 100644 --- a/qa/qa/specs/features/browser_ui/4_verify/runner/register_group_runner_spec.rb +++ b/qa/qa/specs/features/browser_ui/4_verify/runner/register_group_runner_spec.rb @@ -21,9 +21,14 @@ module QA Page::Group::Menu.perform(&:go_to_runners) Page::Group::Runners::Index.perform do |group_runners| - Support::Retrier.retry_on_exception(sleep_interval: 2, message: "Retry failed to verify online runner") do - expect(group_runners).to have_active_runner(runner) - end + expect { group_runners.has_active_runner?(runner) }.to eventually_be(true).within(sleep_interval: 2) + + group_runners.go_to_runner_managers_page(runner) + end + + Page::Runners::RunnerManagersDetail.perform do |runner_managers| + runner_managers.expand_runners + expect(runner_managers).to have_online_runner end end end diff --git a/spec/controllers/omniauth_callbacks_controller_spec.rb b/spec/controllers/omniauth_callbacks_controller_spec.rb index 028dffcb2e2..5ceccfca481 100644 --- a/spec/controllers/omniauth_callbacks_controller_spec.rb +++ b/spec/controllers/omniauth_callbacks_controller_spec.rb @@ -698,6 +698,70 @@ RSpec.describe OmniauthCallbacksController, type: :controller, feature_category: it_behaves_like 'omniauth sign in that remembers user with two factor enabled' end + + context 'when multiple OIDC providers are configured' do + let(:oidc_providers) do + [ + { + 'name' => 'openid_connect', + 'args' => { + 'name' => 'openid_connect', + 'strategy_class' => "OmniAuth::Strategies::OpenIDConnect", + 'client_options' => { 'gitlab' => {} } + } + }, + { + 'name' => 'openid_connect2', + 'args' => { + 'name' => 'openid_connect2', + 'strategy_class' => "OmniAuth::Strategies::OpenIDConnect", + 'client_options' => { 'gitlab' => {} } + } + } + ] + end + + let(:provider_settings) { oidc_providers.map { |provider| GitlabSettings::Options.new(provider) } } + let(:provider_names) { provider_settings.map(&:name).map(&:to_s) } + + context 'when a non-default provider is used', :aggregate_failures do + let(:provider2) { provider_names[1] } + let(:user) { create(:omniauth_user, extern_uid: "my-uid2", provider: provider2.to_sym) } + + controller(described_class) do + alias_method :openid_connect2, :handle_omniauth + end + + before do + prepare_provider_route(provider2) + allow(routes).to receive(:generate_extras).and_return(["/users/auth/#{provider2}/callback", []]) + + stub_omniauth_setting( + enabled: true, + block_auto_created_users: false, + allow_single_sign_on: provider_names, + providers: provider_settings + ) + + request.env['devise.mapping'] = Devise.mappings[:user] + request.env['omniauth.auth'] = Rails.application.env_config['omniauth.auth'] + + mock_auth_hash(provider2, "my-uid2", user.email) + stub_omniauth_provider(provider2, context: request) + end + + it 'authenticates a user with the non-default provider' do + prov_names = provider_names.map(&:to_sym) + + expect(controller).to receive(provider2.to_sym).and_call_original + expect(AuthHelper.oidc_providers).to match(prov_names) + + post provider2.to_sym + + expect(request.env['warden']).to be_authenticated + end + end + end end describe '#saml' do diff --git a/spec/frontend/packages_and_registries/settings/project/settings/components/container_registry_section_spec.js b/spec/frontend/packages_and_registries/settings/project/settings/components/container_registry_section_spec.js index b134b1945da..470b4253b44 100644 --- a/spec/frontend/packages_and_registries/settings/project/settings/components/container_registry_section_spec.js +++ b/spec/frontend/packages_and_registries/settings/project/settings/components/container_registry_section_spec.js @@ -21,6 +21,7 @@ describe('Container registry project settings section', () => { glFeatures: { containerRegistryProtectedTags: true, }, + isContainerRegistryMetadataDatabaseEnabled: true, }; const mountComponent = ({ provide = defaultProvide, props = {} } = {}) => { @@ -90,4 +91,19 @@ describe('Container registry project settings section', () => { expect(findContainerProtectionTagRules().exists()).toBe(false); }); }); + + describe('when "isContainerRegistryMetadataDatabaseEnabled" is set to false', () => { + it('container protection tag rules settings is hidden', () => { + mountComponent({ + provide: { + ...defaultProvide, + isContainerRegistryMetadataDatabaseEnabled: false, + }, + }); + + expect(findContainerExpirationPolicy().exists()).toBe(true); + expect(findContainerProtectionRepositoryRules().exists()).toBe(true); + expect(findContainerProtectionTagRules().exists()).toBe(false); + }); + }); }); diff --git a/spec/helpers/auth_helper_spec.rb b/spec/helpers/auth_helper_spec.rb index e476856b0d5..3bd9fa3c73e 100644 --- a/spec/helpers/auth_helper_spec.rb +++ b/spec/helpers/auth_helper_spec.rb @@ -448,6 +448,127 @@ RSpec.describe AuthHelper, feature_category: :system_access do end end + describe '#oidc_providers' do + subject(:oidc_providers) { helper.oidc_providers } + + let(:oidc_strategy) { 'OmniAuth::Strategies::OpenIDConnect' } + + let(:oidc_provider_1_name) { 'openid_connect' } + let(:oidc_provider_1) do + Struct.new(:name, :args).new( + oidc_provider_1_name, + {} + ) + end + + let(:oidc_provider_2_name) { 'openid_connect2' } + let(:oidc_provider_2) do + Struct.new(:name, :args).new( + oidc_provider_2_name, + 'strategy_class' => oidc_strategy + ) + end + + let(:oidc_provider_3_name) { 'openid_connect3' } + let(:oidc_provider_3) do + Struct.new(:name, :args).new( + oidc_provider_3_name, + 'strategy_class' => oidc_strategy + ) + end + + let(:ldap_provider_name) { 'ldap_provider' } + let(:ldap_strategy) { 'OmniAuth::Strategies::LDAP' } + let(:ldap_provider) do + Struct.new(:name, :args).new( + ldap_provider_name, + 'strategy_class' => ldap_strategy + ) + end + + let(:google_oauth2_provider_name) { 'google_oauth2' } + let(:google_oauth2_provider) do + Struct.new(:name, :args).new( + google_oauth2_provider_name, + 'app_id' => 'YOUR_APP_ID' + ) + end + + context 'when a default openid_connect provider is configured' do + before do + stub_omniauth_config(providers: [oidc_provider_1]) + end + + it 'returns the provider' do + expect(oidc_providers).to match_array([:openid_connect]) + end + end + + context 'when the configuration specifies no provider' do + before do + stub_omniauth_config(providers: []) + end + + it 'returns an empty list' do + expect(oidc_providers).to be_empty + end + end + + context 'when the configuration specifies a provider with an OIDC strategy_class' do + before do + stub_omniauth_config(providers: [oidc_provider_2]) + end + + it 'returns the provider' do + expect(oidc_providers).to match_array([oidc_provider_2_name.to_sym]) + end + end + + context 'when the configuration specifies 1 default oidc provider and 1 with an OIDC strategy_class' do + before do + stub_omniauth_config(providers: [oidc_provider_1, oidc_provider_2]) + end + + it 'returns the providers' do + expect(oidc_providers).to match_array([oidc_provider_1_name.to_sym, oidc_provider_2_name.to_sym]) + end + end + + context 'when the configuration specifies two providers with an OIDC strategy_class' do + before do + stub_omniauth_config(providers: [oidc_provider_2, oidc_provider_3]) + end + + it 'returns the providers' do + expect(oidc_providers).to match_array([oidc_provider_2_name.to_sym, oidc_provider_3_name.to_sym]) + end + end + + context 'when the configuration specifies a non-OIDC provider' do + before do + stub_omniauth_config(providers: [ldap_provider]) + end + + it 'returns an empty list' do + expect(oidc_providers).to be_empty + end + end + + context 'when the configuration specifies 2 non-oidc, 1 default oidc provider and 2 with an OIDC strategy_class' do + before do + stub_omniauth_config( + providers: [oidc_provider_1, ldap_provider, oidc_provider_2, google_oauth2_provider, oidc_provider_3] + ) + end + + it 'returns the providers' do + expect(oidc_providers).to match_array( + [oidc_provider_1_name.to_sym, oidc_provider_2_name.to_sym, oidc_provider_3_name.to_sym] + ) + end + end + end + describe '#delete_otp_authenticator_data' do context 'when password is required' do it 'returns data to delete the OTP authenticator' do diff --git a/spec/lib/gitlab/auth/o_auth/provider_spec.rb b/spec/lib/gitlab/auth/o_auth/provider_spec.rb index 291cfb951c3..be2a7dd52e6 100644 --- a/spec/lib/gitlab/auth/o_auth/provider_spec.rb +++ b/spec/lib/gitlab/auth/o_auth/provider_spec.rb @@ -94,19 +94,51 @@ RSpec.describe Gitlab::Auth::OAuth::Provider, feature_category: :system_access d end context 'for an OpenID Connect provider' do - before do - provider = ActiveSupport::InheritableOptions.new( - name: 'openid_connect', - args: ActiveSupport::InheritableOptions.new(name: 'custom_oidc') - ) - allow(Gitlab.config.omniauth).to receive(:providers).and_return([provider]) - end + context 'when the default oidc provider exists' do + before do + provider = ActiveSupport::InheritableOptions.new( + name: 'openid_connect', + args: ActiveSupport::InheritableOptions.new(name: 'custom_oidc') + ) + allow(Gitlab.config.omniauth).to receive(:providers).and_return([provider]) + end - context 'when the provider exists' do - subject { described_class.config_for('custom_oidc') } + subject(:config) { described_class.config_for('custom_oidc') } it 'returns the config' do - expect(subject).to be_a(ActiveSupport::InheritableOptions) + expect(config).to be_a(ActiveSupport::InheritableOptions) + expect(config.name).to eq('openid_connect') + expect(config.args.name).to eq('custom_oidc') + end + end + + context 'when an oidc provider with a strategy exists' do + before do + provider = ActiveSupport::InheritableOptions.new( + name: 'openid_connect2', + args: ActiveSupport::InheritableOptions.new( + name: 'openid_connect2_inner', + strategy_class: 'OmniAuth::Strategies::OpenIDConnect' + ) + ) + allow(Gitlab.config.omniauth).to receive(:providers).and_return([provider]) + end + + subject(:config) { described_class.config_for('openid_connect2') } + + it 'returns the config' do + expect(config).to be_a(ActiveSupport::InheritableOptions) + expect(config.name).to eq('openid_connect2') + expect(config.args.name).to eq('openid_connect2_inner') + expect(config.args.strategy_class).to eq('OmniAuth::Strategies::OpenIDConnect') + end + end + + context 'when the provider does not exist' do + subject(:config) { described_class.config_for('') } + + it 'returns nil' do + expect(config).to be_nil end end end diff --git a/spec/requests/api/conan/v1/project_packages_spec.rb b/spec/requests/api/conan/v1/project_packages_spec.rb index 3beb053037b..7883066b58f 100644 --- a/spec/requests/api/conan/v1/project_packages_spec.rb +++ b/spec/requests/api/conan/v1/project_packages_spec.rb @@ -49,28 +49,7 @@ RSpec.describe API::Conan::V1::ProjectPackages, feature_category: :package_regis subject { get api(url), params: params } end - context 'with access to package registry for everyone' do - before do - project.update!(visibility_level: Gitlab::VisibilityLevel::PRIVATE) - project.project_feature.update!(package_registry_access_level: ProjectFeature::PUBLIC) - - get api(url), params: params - end - - subject { json_response['results'] } - - context 'with a matching name' do - let(:params) { { q: package.conan_recipe } } - - it { is_expected.to contain_exactly(package.conan_recipe) } - end - - context 'with a * wildcard' do - let(:params) { { q: "#{package.name[0, 3]}*" } } - - it { is_expected.to contain_exactly(package.conan_recipe) } - end - end + it_behaves_like 'conan search endpoint with access to package registry for everyone' end describe 'GET /api/v4/projects/:id/packages/conan/v1/users/authenticate' do diff --git a/spec/requests/api/conan/v2/project_packages_spec.rb b/spec/requests/api/conan/v2/project_packages_spec.rb index 8a8de40a9ba..ae0e62af5ae 100644 --- a/spec/requests/api/conan/v2/project_packages_spec.rb +++ b/spec/requests/api/conan/v2/project_packages_spec.rb @@ -5,6 +5,20 @@ require 'spec_helper' RSpec.describe API::Conan::V2::ProjectPackages, feature_category: :package_registry do include_context 'conan api setup' + describe 'GET /api/v4/projects/:id/packages/conan/v2/conans/search' do + let(:url) { "/projects/#{project.id}/packages/conan/v2/conans/search" } + + it_behaves_like 'conan search endpoint' + + it_behaves_like 'conan FIPS mode' do + let(:params) { { q: package.conan_recipe } } + + subject { get api(url), params: params } + end + + it_behaves_like 'conan search endpoint with access to package registry for everyone' + end + describe 'GET /api/v4/projects/:id/packages/conan/v2/conans/:package_name/:package_version/:package_username/' \ ':package_channel/revisions/:recipe_revision/files/:file_name' do include_context 'conan file download endpoints' diff --git a/spec/services/ci/register_job_service/logger_spec.rb b/spec/services/ci/register_job_service/logger_spec.rb new file mode 100644 index 00000000000..65ae878f679 --- /dev/null +++ b/spec/services/ci/register_job_service/logger_spec.rb @@ -0,0 +1,73 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe ::Ci::RegisterJobService::Logger, feature_category: :continuous_integration do + let_it_be(:runner) { build_stubbed(:ci_runner) } + + subject(:logger) { described_class.new(runner: runner) } + + describe '#instrument' do + it "returns the block's value" do + expect(logger.instrument(:expensive_operation) { 123 }).to eq(123) + end + + it 'raises an error when block is not provided' do + expect { logger.instrument(:expensive_operation) } + .to raise_error(ArgumentError, 'block not given') + end + end + + describe '#commit' do + subject(:commit) { logger.commit } + + before do + freeze_time do + stub_feature_flags(ci_register_job_instrumentation_logger: flag) + allow(logger).to receive(:current_monotonic_time) { Time.current.to_i } + + logger.instrument(:process_queue, once: true) { travel(60.seconds) } + logger.instrument(:process_build) { travel(10.seconds) } + logger.instrument(:process_build) { travel(20.seconds) } + end + end + + context 'when the feature flag is enabled' do + let(:flag) { true } + + let(:expected_data) do + { + class: described_class.name.to_s, + message: 'RegisterJobService exceeded maximum duration', + runner_id: runner.id, + runner_type: runner.runner_type, + process_queue_duration_s: 60, + process_build_duration_s: { + count: 2, + max: 20, + sum: 30 + } + } + end + + it 'logs to application.json' do + expect(Gitlab::AppJsonLogger) + .to receive(:info) + .with(a_hash_including(expected_data)) + .and_call_original + + expect(commit).to be_truthy + end + + context 'when the feature flag is disabled' do + let(:flag) { false } + + it 'does not log' do + expect(Gitlab::AppJsonLogger).not_to receive(:info) + + expect(commit).to be_falsey + end + end + end + end +end diff --git a/spec/services/ci/register_job_service_spec.rb b/spec/services/ci/register_job_service_spec.rb index ff1d79f6e28..893927d313e 100644 --- a/spec/services/ci/register_job_service_spec.rb +++ b/spec/services/ci/register_job_service_spec.rb @@ -79,6 +79,42 @@ module Ci expect(build).to eq(pending_job) expect(pending_job.runner_manager).to eq(project_runner_manager) end + + context 'when logger is enabled' do + before do + stub_const('Ci::RegisterJobService::Logger::MAX_DURATION', 0) + end + + it 'logs the instrumentation' do + expect(Gitlab::AppJsonLogger).to receive(:info).once.with( + hash_including( + class: 'Ci::RegisterJobService::Logger', + message: 'RegisterJobService exceeded maximum duration', + runner_id: project_runner.id, + runner_type: project_runner.runner_type, + total_duration_s: anything, + process_queue_duration_s: anything, + metrics_success_duration_s: anything, + retrieve_queue_duration_s: anything, + process_build_duration_s: { count: 1, max: anything, sum: anything } + ) + ) + + build + end + + context 'when the FF ci_register_job_instrumentation_logger is disabled' do + before do + stub_feature_flags(ci_register_job_instrumentation_logger: false) + end + + it 'does not log the instrumentation' do + expect(Gitlab::AppJsonLogger).not_to receive(:info) + + build + end + end + end end end diff --git a/spec/support/shared_examples/requests/api/conan_packages_shared_examples.rb b/spec/support/shared_examples/requests/api/conan_packages_shared_examples.rb index 5731ca906bf..200231d4682 100644 --- a/spec/support/shared_examples/requests/api/conan_packages_shared_examples.rb +++ b/spec/support/shared_examples/requests/api/conan_packages_shared_examples.rb @@ -86,6 +86,29 @@ RSpec.shared_examples 'conan search endpoint' do end end +RSpec.shared_examples 'conan search endpoint with access to package registry for everyone' do + before do + project.update!(visibility_level: Gitlab::VisibilityLevel::PRIVATE) + project.project_feature.update!(package_registry_access_level: ProjectFeature::PUBLIC) + + get api(url), params: params + end + + subject { json_response['results'] } + + context 'with a matching name' do + let(:params) { { q: package.conan_recipe } } + + it { is_expected.to contain_exactly(package.conan_recipe) } + end + + context 'with a * wildcard' do + let(:params) { { q: "#{package.name[0, 3]}*" } } + + it { is_expected.to contain_exactly(package.conan_recipe) } + end +end + RSpec.shared_examples 'conan authenticate endpoint' do subject { get api(url), headers: headers }