From a9f80cbfe2bc0479bd543d7b9ef3a3f1abcbca2b Mon Sep 17 00:00:00 2001 From: GitLab Bot Date: Sat, 10 May 2025 00:10:35 +0000 Subject: [PATCH] Add latest changes from gitlab-org/gitlab@master --- .rubocop_todo/gitlab/bounded_contexts.yml | 1 - .../layout/line_break_after_final_mixin.yml | 24 ------------ .rubocop_todo/layout/line_length.yml | 1 - .rubocop_todo/rspec/be_eq.yml | 1 - .rubocop_todo/rspec/named_subject.yml | 1 - .../super_sidebar/components/nav_item.vue | 12 +++--- .../integrations/exclusions_resolver.rb | 1 + .../resolvers/projects/deploy_key_resolver.rb | 1 + app/models/merge_request.rb | 4 +- app/policies/project_member_policy.rb | 1 + app/serializers/cluster_serializer.rb | 1 + .../container_repositories_serializer.rb | 1 + app/serializers/feature_flag_serializer.rb | 1 + app/serializers/pipeline_serializer.rb | 1 + .../project_recalculate_service.rb | 1 + .../cleanup_scheduler_service.rb | 1 + .../create_service.rb | 1 + app/services/projects/transfer_service.rb | 1 + .../graphql/graphql_explorer/show.html.haml | 8 ++-- .../documentation/styleguide/word_list.md | 5 ++- .../documentation/topic_types/reference.md | 4 +- doc/user/application_security/_index.md | 21 ---------- .../security_report_validation.md | 38 +++++++++++++++++++ doc/user/gitlab_duo/turn_on_off.md | 6 ++- .../references/design_reference_filter.rb | 1 + lib/feature.rb | 1 + lib/gitlab/auth/current_user_mode.rb | 1 + .../auth/otp/strategies/forti_token_cloud.rb | 1 + lib/gitlab/ci/config/interpolation/config.rb | 1 + lib/gitlab/cluster/rack_timeout_observer.rb | 1 + lib/gitlab/etag_caching/router/graphql.rb | 1 + lib/sidebars/menu_item.rb | 25 +++++++++--- .../components/draft_note_spec.js | 5 +-- .../runner_list_empty_state_spec.js | 6 --- spec/frontend/diffs/components/app_spec.js | 10 +---- .../diffs/components/diff_content_spec.js | 5 +-- .../environments_detail_header_spec.js | 5 +-- .../components/members_token_select_spec.js | 3 +- .../super_sidebar/components/nav_item_spec.js | 8 +++- .../blob_viewers/simple_viewer_spec.js | 2 - spec/lib/sidebars/menu_spec.rb | 3 +- spec/models/merge_request_spec.rb | 25 ++++++++++++ .../features/invite_members_modal_helpers.rb | 4 ++ 43 files changed, 143 insertions(+), 102 deletions(-) create mode 100644 doc/user/application_security/detect/pipeline_secret_scanning/security_report_validation.md diff --git a/.rubocop_todo/gitlab/bounded_contexts.yml b/.rubocop_todo/gitlab/bounded_contexts.yml index 48ed1cf46aa..0dca1f7e83c 100644 --- a/.rubocop_todo/gitlab/bounded_contexts.yml +++ b/.rubocop_todo/gitlab/bounded_contexts.yml @@ -3292,7 +3292,6 @@ Gitlab/BoundedContexts: - 'ee/app/services/llm/resolve_vulnerability_service.rb' - 'ee/app/services/llm/review_merge_request_service.rb' - 'ee/app/services/llm/summarize_new_merge_request_service.rb' - - 'ee/app/services/member_roles/base_service.rb' - 'ee/app/services/member_roles/create_service.rb' - 'ee/app/services/member_roles/delete_service.rb' - 'ee/app/services/member_roles/update_service.rb' diff --git a/.rubocop_todo/layout/line_break_after_final_mixin.yml b/.rubocop_todo/layout/line_break_after_final_mixin.yml index e441df8820c..5d214c9845c 100644 --- a/.rubocop_todo/layout/line_break_after_final_mixin.yml +++ b/.rubocop_todo/layout/line_break_after_final_mixin.yml @@ -2,17 +2,6 @@ # Cop supports --autocorrect. Layout/LineBreakAfterFinalMixin: Exclude: - - 'app/graphql/resolvers/integrations/exclusions_resolver.rb' - - 'app/graphql/resolvers/projects/deploy_key_resolver.rb' - - 'app/policies/project_member_policy.rb' - - 'app/serializers/cluster_serializer.rb' - - 'app/serializers/container_repositories_serializer.rb' - - 'app/serializers/feature_flag_serializer.rb' - - 'app/serializers/pipeline_serializer.rb' - - 'app/services/authorized_project_update/project_recalculate_service.rb' - - 'app/services/batched_git_ref_updates/cleanup_scheduler_service.rb' - - 'app/services/jira_connect_subscriptions/create_service.rb' - - 'app/services/projects/transfer_service.rb' - 'app/workers/ci/delete_unit_tests_worker.rb' - 'app/workers/ci/pipeline_artifacts/expire_artifacts_worker.rb' - 'app/workers/ci/schedule_delete_objects_cron_worker.rb' @@ -37,12 +26,6 @@ Layout/LineBreakAfterFinalMixin: - 'app/workers/stuck_export_jobs_worker.rb' - 'app/workers/user_status_cleanup/batch_worker.rb' - 'app/workers/users/create_statistics_worker.rb' - - 'ee/app/graphql/subscriptions/ai_completion_response.rb' - - 'ee/app/services/ee/ip_restrictions/update_service.rb' - - 'ee/app/services/incident_management/oncall_rotations/edit_service.rb' - - 'ee/app/services/incident_management/oncall_rotations/remove_participant_service.rb' - - 'ee/app/services/llm/generate_description_service.rb' - - 'ee/app/services/product_analytics/initialize_stack_service.rb' - 'ee/app/workers/active_user_count_threshold_worker.rb' - 'ee/app/workers/analytics/value_stream_dashboard/count_worker.rb' - 'ee/app/workers/arkose/blocked_users_report_worker.rb' @@ -56,10 +39,3 @@ Layout/LineBreakAfterFinalMixin: - 'ee/app/workers/sync_seat_link_worker.rb' - 'ee/app/workers/vulnerabilities/historical_statistics/deletion_worker.rb' - 'ee/app/workers/vulnerabilities/statistics/schedule_worker.rb' - - 'lib/banzai/filter/references/design_reference_filter.rb' - - 'lib/feature.rb' - - 'lib/gitlab/auth/current_user_mode.rb' - - 'lib/gitlab/auth/otp/strategies/forti_token_cloud.rb' - - 'lib/gitlab/ci/config/interpolation/config.rb' - - 'lib/gitlab/cluster/rack_timeout_observer.rb' - - 'lib/gitlab/etag_caching/router/graphql.rb' diff --git a/.rubocop_todo/layout/line_length.yml b/.rubocop_todo/layout/line_length.yml index 2d18ae8f1be..2f2ae5a3f4d 100644 --- a/.rubocop_todo/layout/line_length.yml +++ b/.rubocop_todo/layout/line_length.yml @@ -2247,7 +2247,6 @@ Layout/LineLength: - 'lib/security/ci_configuration/base_build_action.rb' - 'lib/security/ci_configuration/sast_build_action.rb' - 'lib/sidebars/groups/menus/packages_registries_menu.rb' - - 'lib/sidebars/menu_item.rb' - 'lib/sidebars/projects/menus/repository_menu.rb' - 'lib/system_check/app/orphaned_group_members_check.rb' - 'lib/system_check/app/redis_version_check.rb' diff --git a/.rubocop_todo/rspec/be_eq.yml b/.rubocop_todo/rspec/be_eq.yml index ba0dbe981e2..211f4720955 100644 --- a/.rubocop_todo/rspec/be_eq.yml +++ b/.rubocop_todo/rspec/be_eq.yml @@ -182,7 +182,6 @@ RSpec/BeEq: - 'ee/spec/lib/search/elastic/task_status_spec.rb' - 'ee/spec/lib/security/scan_result_policies/policy_violation_details_spec.rb' - 'ee/spec/lib/security/security_orchestration_policies/policy_scope_checker_spec.rb' - - 'ee/spec/lib/sidebars/projects/menus/learn_gitlab_menu_spec.rb' - 'ee/spec/lib/telesign/transaction_callback_payload_spec.rb' - 'ee/spec/lib/telesign/transaction_callback_spec.rb' - 'ee/spec/lib/users/identity_verification/authorize_ci_spec.rb' diff --git a/.rubocop_todo/rspec/named_subject.yml b/.rubocop_todo/rspec/named_subject.yml index 3cfed628313..1b27de25521 100644 --- a/.rubocop_todo/rspec/named_subject.yml +++ b/.rubocop_todo/rspec/named_subject.yml @@ -432,7 +432,6 @@ RSpec/NamedSubject: - 'ee/spec/lib/repositories/project_push_rules_changes_auditor_spec.rb' - 'ee/spec/lib/sidebars/groups/menus/epics_menu_spec.rb' - 'ee/spec/lib/sidebars/groups/menus/work_item_epics_menu_spec.rb' - - 'ee/spec/lib/sidebars/projects/menus/learn_gitlab_menu_spec.rb' - 'ee/spec/lib/sidebars/user_settings/menus/profile_billing_menu_spec.rb' - 'ee/spec/lib/system_check/geo/authorized_keys_check_spec.rb' - 'ee/spec/lib/system_check/geo/authorized_keys_flag_check_spec.rb' diff --git a/app/assets/javascripts/super_sidebar/components/nav_item.vue b/app/assets/javascripts/super_sidebar/components/nav_item.vue index 88b72b483a9..19582e08360 100644 --- a/app/assets/javascripts/super_sidebar/components/nav_item.vue +++ b/app/assets/javascripts/super_sidebar/components/nav_item.vue @@ -75,6 +75,7 @@ export default { return { isMouseIn: false, canClickPinButton: false, + localPillCount: this.item.pill_count, }; }, computed: { @@ -82,6 +83,11 @@ export default { if (this.item.pill_count_field) { return this.asyncCount[this.item.pill_count_field]; } + + if (this.item.pill_count_dynamic) { + return this.localPillCount; + } + return this.item.pill_count; }, hasPill() { @@ -213,11 +219,7 @@ export default { }, updatePillValue({ value, itemId }) { if (this.item.id === itemId) { - // https://gitlab.com/gitlab-org/gitlab/-/issues/428246 - // fixing this linting issue is causing the pills not to async update for learn gitlab nav item - // - // eslint-disable-next-line vue/no-mutating-props - this.item.pill_count = value; + this.localPillCount = value; } }, }, diff --git a/app/graphql/resolvers/integrations/exclusions_resolver.rb b/app/graphql/resolvers/integrations/exclusions_resolver.rb index f5d405b578a..92205978be1 100644 --- a/app/graphql/resolvers/integrations/exclusions_resolver.rb +++ b/app/graphql/resolvers/integrations/exclusions_resolver.rb @@ -4,6 +4,7 @@ module Resolvers module Integrations class ExclusionsResolver < BaseResolver include Gitlab::Graphql::Authorize::AuthorizeResource + type Types::Integrations::ExclusionType.connection_type, null: true argument :integration_name, Types::Integrations::IntegrationTypeEnum, diff --git a/app/graphql/resolvers/projects/deploy_key_resolver.rb b/app/graphql/resolvers/projects/deploy_key_resolver.rb index 1dc6dbe2427..2514fe143db 100644 --- a/app/graphql/resolvers/projects/deploy_key_resolver.rb +++ b/app/graphql/resolvers/projects/deploy_key_resolver.rb @@ -4,6 +4,7 @@ module Resolvers module Projects class DeployKeyResolver < BaseResolver include LooksAhead + type Types::AccessLevels::DeployKeyType, null: true def resolve_with_lookahead(**args) diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index bd5003a97ff..67caa97d56d 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -1631,7 +1631,7 @@ class MergeRequest < ApplicationRecord end def visible_closing_issues_for(current_user = self.author) - strong_memoize(:visible_closing_issues_for) do + strong_memoize_with(:visible_closing_issues_for, current_user&.id) do visible_issues = if self.target_project.has_external_issue_tracker? closes_issues(current_user) else @@ -1644,7 +1644,7 @@ class MergeRequest < ApplicationRecord records: visible_issues.select { |issue| issue.is_a?(Issue) }, associations: :project ).call - # Exclude isues that have been cached but their project setting has been disabled, or they belong to a group + # Exclude issues that have been cached but their project setting has been disabled, or they belong to a group visible_issues.select do |issue| !issue.is_a?(Issue) || issue.autoclose_by_merged_closing_merge_request? end diff --git a/app/policies/project_member_policy.rb b/app/policies/project_member_policy.rb index 9d6a8c22e6d..1a7da42fc09 100644 --- a/app/policies/project_member_policy.rb +++ b/app/policies/project_member_policy.rb @@ -2,6 +2,7 @@ class ProjectMemberPolicy < BasePolicy include MemberPolicyHelpers + delegate { @subject.project } condition(:target_is_holder_of_the_personal_namespace, scope: :subject) do diff --git a/app/serializers/cluster_serializer.rb b/app/serializers/cluster_serializer.rb index a4e12e51f69..b42e403a1ef 100644 --- a/app/serializers/cluster_serializer.rb +++ b/app/serializers/cluster_serializer.rb @@ -2,6 +2,7 @@ class ClusterSerializer < BaseSerializer include WithPagination + entity ClusterEntity def represent_list(resource) diff --git a/app/serializers/container_repositories_serializer.rb b/app/serializers/container_repositories_serializer.rb index 0e9bdee187b..e30a6f20f57 100644 --- a/app/serializers/container_repositories_serializer.rb +++ b/app/serializers/container_repositories_serializer.rb @@ -2,6 +2,7 @@ class ContainerRepositoriesSerializer < BaseSerializer include WithPagination + entity ContainerRepositoryEntity def represent_read_only(resource) diff --git a/app/serializers/feature_flag_serializer.rb b/app/serializers/feature_flag_serializer.rb index e0ff33cc61a..22468f275b5 100644 --- a/app/serializers/feature_flag_serializer.rb +++ b/app/serializers/feature_flag_serializer.rb @@ -2,6 +2,7 @@ class FeatureFlagSerializer < BaseSerializer include WithPagination + entity FeatureFlagEntity def represent(resource, opts = {}) diff --git a/app/serializers/pipeline_serializer.rb b/app/serializers/pipeline_serializer.rb index e4c5e0cde89..e7dac007674 100644 --- a/app/serializers/pipeline_serializer.rb +++ b/app/serializers/pipeline_serializer.rb @@ -2,6 +2,7 @@ class PipelineSerializer < BaseSerializer include WithPagination + entity PipelineDetailsEntity # rubocop: disable CodeReuse/ActiveRecord diff --git a/app/services/authorized_project_update/project_recalculate_service.rb b/app/services/authorized_project_update/project_recalculate_service.rb index 535845b9f94..c4234259bcb 100644 --- a/app/services/authorized_project_update/project_recalculate_service.rb +++ b/app/services/authorized_project_update/project_recalculate_service.rb @@ -4,6 +4,7 @@ module AuthorizedProjectUpdate class ProjectRecalculateService # Service for refreshing all the authorizations to a particular project. include Gitlab::Utils::StrongMemoize + BATCH_SIZE = 1000 def initialize(project) diff --git a/app/services/batched_git_ref_updates/cleanup_scheduler_service.rb b/app/services/batched_git_ref_updates/cleanup_scheduler_service.rb index cf547c0e6b5..3247c648b29 100644 --- a/app/services/batched_git_ref_updates/cleanup_scheduler_service.rb +++ b/app/services/batched_git_ref_updates/cleanup_scheduler_service.rb @@ -3,6 +3,7 @@ module BatchedGitRefUpdates class CleanupSchedulerService include Gitlab::ExclusiveLeaseHelpers + MAX_PROJECTS = 10_000 BATCH_SIZE = 100 LOCK_TIMEOUT = 10.minutes diff --git a/app/services/jira_connect_subscriptions/create_service.rb b/app/services/jira_connect_subscriptions/create_service.rb index cd588387acb..583e9d364ed 100644 --- a/app/services/jira_connect_subscriptions/create_service.rb +++ b/app/services/jira_connect_subscriptions/create_service.rb @@ -3,6 +3,7 @@ module JiraConnectSubscriptions class CreateService < ::JiraConnectSubscriptions::BaseService include Gitlab::Utils::StrongMemoize + MERGE_REQUEST_SYNC_BATCH_SIZE = 20 MERGE_REQUEST_SYNC_BATCH_DELAY = 1.minute.freeze BATCH_SIZE = 1_000 diff --git a/app/services/projects/transfer_service.rb b/app/services/projects/transfer_service.rb index 6b5b30235c1..6f5aa5d3c56 100644 --- a/app/services/projects/transfer_service.rb +++ b/app/services/projects/transfer_service.rb @@ -11,6 +11,7 @@ module Projects class TransferService < BaseService include Gitlab::ShellAdapter + TransferError = Class.new(StandardError) def log_project_transfer_success(project, new_namespace) diff --git a/app/views/api/graphql/graphql_explorer/show.html.haml b/app/views/api/graphql/graphql_explorer/show.html.haml index 71241bfdc97..e73ae56593a 100644 --- a/app/views/api/graphql/graphql_explorer/show.html.haml +++ b/app/views/api/graphql/graphql_explorer/show.html.haml @@ -14,9 +14,9 @@ #performance-bar-root %template{ :shadowrootmode => "open" } = render 'peek/bar' - = universal_stylesheet_link_tag 'application' - = universal_stylesheet_link_tag 'application_utilities' - = universal_stylesheet_link_tag 'tailwind' - = universal_stylesheet_link_tag 'performance_bar' + = universal_stylesheet_link_tag 'application', crossorigin: 'anonymous' + = universal_stylesheet_link_tag 'application_utilities', crossorigin: 'anonymous' + = universal_stylesheet_link_tag 'tailwind', crossorigin: 'anonymous' + = universal_stylesheet_link_tag 'performance_bar', crossorigin: 'anonymous' = webpack_bundle_tag 'performance_bar' #graphiql-container Loading... diff --git a/doc/development/documentation/styleguide/word_list.md b/doc/development/documentation/styleguide/word_list.md index 6f046a96681..a0e5263b762 100644 --- a/doc/development/documentation/styleguide/word_list.md +++ b/doc/development/documentation/styleguide/word_list.md @@ -1527,7 +1527,10 @@ Instead of: ## limitations -Do not use **limitations**. Use **known issues** instead. +Do not use **Limitations** as a topic title. For more information, +see [reference topic titles](../topic_types/reference.md#reference-topic-titles). + +If you must, you can use the title **Known issues**. ## log in, log on diff --git a/doc/development/documentation/topic_types/reference.md b/doc/development/documentation/topic_types/reference.md index 9923de7a293..548abcc28e7 100644 --- a/doc/development/documentation/topic_types/reference.md +++ b/doc/development/documentation/topic_types/reference.md @@ -30,9 +30,11 @@ Reference topic titles are usually nouns. Avoid these topic titles: - `Important notes`. Instead, incorporate this information - closer to where it belongs. For example, this information might be a prerequisite + closer to where it belongs. This information might be a prerequisite for a task, or information about a concept. - `Limitations`. Instead, move the content near other similar information. + Content listed as limitations can often be considered prerequisite + information about how a feature works. If you must, you can use the title `Known issues`. ## Example diff --git a/doc/user/application_security/_index.md b/doc/user/application_security/_index.md index 5beb13b61b1..7e86a0b62ad 100644 --- a/doc/user/application_security/_index.md +++ b/doc/user/application_security/_index.md @@ -124,27 +124,6 @@ For GitLab Self-Managed instances, you can choose to run most of the GitLab secu GitLab Self-Managed instances can also run the security scanners on a GitLab Runner [running inside OpenShift](../../install/openshift_and_gitlab/_index.md). -## Security report validation - -GitLab 15.0 enforces validation of the security report artifacts before ingesting the vulnerabilities. -This prevents ingestion of broken vulnerability data into the database. GitLab validates the -artifacts against the [report schemas](https://gitlab.com/gitlab-org/security-products/security-report-schemas/-/tree/master/dist), -according to the schema version declared in the report. - -The pipeline's **Security** tab lists any report artifacts that failed validation, and the -validation error message. - -Validation depends on the schema version declared in the security report artifact: - -- If your security report specifies a supported schema version, GitLab uses this version to validate. -- If your security report uses a deprecated version, GitLab attempts validation against that version and adds a deprecation warning to the validation result. -- If your security report uses a supported MAJOR-MINOR version of the report schema but the PATCH version doesn't match any vendored versions, GitLab attempts to validate it against latest vendored PATCH version of the schema. - - Example: security report uses version 14.1.1 but the latest vendored version is 14.1.0. GitLab would validate against schema version 14.1.0. -- If your security report uses a version that is not supported, GitLab attempts to validate it against the earliest schema version available in your installation but doesn't ingest the report. -- If your security report does not specify a schema version, GitLab attempts to validate it against the earliest schema version available in GitLab. Because the `version` property is required, validation always fails in this case, but other validation errors may also be present. - -You can always find supported and deprecated schema versions in the [source code](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/parsers/security/validators/schema_validator.rb). - ## Security scanning configuration tips Each GitLab security scanning tool has a default diff --git a/doc/user/application_security/detect/pipeline_secret_scanning/security_report_validation.md b/doc/user/application_security/detect/pipeline_secret_scanning/security_report_validation.md new file mode 100644 index 00000000000..eef60a350ae --- /dev/null +++ b/doc/user/application_security/detect/pipeline_secret_scanning/security_report_validation.md @@ -0,0 +1,38 @@ +--- +stage: Application Security Testing +group: Static Analysis +info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://handbook.gitlab.com/handbook/product/ux/technical-writing/#assignments +title: Security report validation +--- + +{{< details >}} + +- Tier: Ultimate +- Offering: GitLab.com, GitLab Self-Managed, GitLab Dedicated + +{{< /details >}} + +Security reports are validated before their content is added to the database. This prevents +ingestion of broken vulnerability data into the database. Reports that fail validation are listed in +the pipeline's **Security** tab with the validation error message. + +Validation is done against the +[report schemas](https://gitlab.com/gitlab-org/security-products/security-report-schemas/-/tree/master/dist), +according to the schema version declared in the report: + +- If the security report specifies a supported schema version, GitLab uses this version to validate. +- If the security report uses a deprecated version, GitLab attempts validation against that version + and adds a deprecation warning to the validation result. +- If the security report uses a supported MAJOR-MINOR version of the report schema but the PATCH + version doesn't match any vendored versions, GitLab attempts to validate it against latest + vendored PATCH version of the schema. + - Example: security report uses version 14.1.1 but the latest vendored version is 14.1.0. GitLab + would validate against schema version 14.1.0. +- If the security report uses a version that is not supported, GitLab attempts to validate it + against the earliest schema version available in your installation but doesn't ingest the report. +- If the security report does not specify a schema version, GitLab attempts to validate it against + the earliest schema version available in GitLab. Because the `version` property is required, + validation always fails in this case, but other validation errors may also be present. + +For details of the supported and deprecated schema versions, view the +[schema validator source code](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/parsers/security/validators/schema_validator.rb). diff --git a/doc/user/gitlab_duo/turn_on_off.md b/doc/user/gitlab_duo/turn_on_off.md index c27ee4cfb6b..51c132da4f5 100644 --- a/doc/user/gitlab_duo/turn_on_off.md +++ b/doc/user/gitlab_duo/turn_on_off.md @@ -30,6 +30,8 @@ features: 1. Upgrade to GitLab 18.0 or later. 1. Turn on the IDE features for your group or instance. +It may take up to 10 minutes for the change to take effect. + ### For a group On GitLab.com, you can turn GitLab Duo Core on or off for a top-level group, but not for a subgroup or project. @@ -46,6 +48,8 @@ To turn GitLab Duo Core on or off for a top-level group on GitLab.com: 1. Below **GitLab Duo Core**, select or clear the **Turn on IDE features** checkbox. 1. Select **Save changes**. +It may take up to 10 minutes for the change to take effect. + ### For an instance On GitLab Self-Managed, you can turn GitLab Duo Core on or off for an instance. @@ -339,7 +343,7 @@ To turn on GitLab Duo experiment and beta features for a top-level group: 1. On the left sidebar, select **Search or go to** and find your group. 1. Select **Settings > GitLab Duo**. 1. Under **GitLab Duo** section, select **Change configuration**. -1. Select **Turn on experiment and beta GitLab Duo features**. +1. Select **Turn on experiment and beta GitLab Duo features**. 1. Select **Save changes**. {{< /tab >}} diff --git a/lib/banzai/filter/references/design_reference_filter.rb b/lib/banzai/filter/references/design_reference_filter.rb index c599d4ac73b..049110573b6 100644 --- a/lib/banzai/filter/references/design_reference_filter.rb +++ b/lib/banzai/filter/references/design_reference_filter.rb @@ -6,6 +6,7 @@ module Banzai class DesignReferenceFilter < AbstractReferenceFilter class Identifier include Comparable + attr_reader :issue_iid, :filename def initialize(issue_iid:, filename:) diff --git a/lib/feature.rb b/lib/feature.rb index f041c9b8b15..0067a5769e6 100644 --- a/lib/feature.rb +++ b/lib/feature.rb @@ -7,6 +7,7 @@ module Feature class FlipperRecord < ActiveRecord::Base # rubocop:disable Rails/ApplicationRecord -- This class perfectly replaces # Flipper::Adapters::ActiveRecord::Model, which inherits ActiveRecord::Base include DatabaseReflection + self.abstract_class = true # Bypass the load balancer by restoring the default behavior of `connection` diff --git a/lib/gitlab/auth/current_user_mode.rb b/lib/gitlab/auth/current_user_mode.rb index 695a2561f16..69c32accffa 100644 --- a/lib/gitlab/auth/current_user_mode.rb +++ b/lib/gitlab/auth/current_user_mode.rb @@ -9,6 +9,7 @@ module Gitlab # e.g. on web access require re-authentication class CurrentUserMode include Gitlab::Utils::StrongMemoize + NotRequestedError = Class.new(StandardError) NonSidekiqEnvironmentError = Class.new(StandardError) diff --git a/lib/gitlab/auth/otp/strategies/forti_token_cloud.rb b/lib/gitlab/auth/otp/strategies/forti_token_cloud.rb index 105de58b5f9..b084c6303aa 100644 --- a/lib/gitlab/auth/otp/strategies/forti_token_cloud.rb +++ b/lib/gitlab/auth/otp/strategies/forti_token_cloud.rb @@ -6,6 +6,7 @@ module Gitlab module Strategies class FortiTokenCloud < Base include Gitlab::Utils::StrongMemoize + BASE_API_URL = 'https://ftc.fortinet.com:9696/api/v1' def validate(otp_code) diff --git a/lib/gitlab/ci/config/interpolation/config.rb b/lib/gitlab/ci/config/interpolation/config.rb index cb878ad3ffe..6f258df31a5 100644 --- a/lib/gitlab/ci/config/interpolation/config.rb +++ b/lib/gitlab/ci/config/interpolation/config.rb @@ -9,6 +9,7 @@ module Gitlab # class Config include Gitlab::Utils::StrongMemoize + ## # Loading the YAML below would result in a hash having 12 nodes instead of 9, # because hash values are being counted before we recursively traverse them. diff --git a/lib/gitlab/cluster/rack_timeout_observer.rb b/lib/gitlab/cluster/rack_timeout_observer.rb index 8e9fc16c588..ad38db4b515 100644 --- a/lib/gitlab/cluster/rack_timeout_observer.rb +++ b/lib/gitlab/cluster/rack_timeout_observer.rb @@ -4,6 +4,7 @@ module Gitlab module Cluster class RackTimeoutObserver include ActionView::Helpers::SanitizeHelper + TRANSITION_STATES = %i[ready active].freeze def initialize diff --git a/lib/gitlab/etag_caching/router/graphql.rb b/lib/gitlab/etag_caching/router/graphql.rb index 50cdde88e2d..f6ab2a15c2a 100644 --- a/lib/gitlab/etag_caching/router/graphql.rb +++ b/lib/gitlab/etag_caching/router/graphql.rb @@ -5,6 +5,7 @@ module Gitlab module Router class Graphql extend EtagCaching::Router::Helpers + GRAPHQL_ETAG_RESOURCE_HEADER = 'X-GITLAB-GRAPHQL-RESOURCE-ETAG' ROUTES = [ diff --git a/lib/sidebars/menu_item.rb b/lib/sidebars/menu_item.rb index f93dd2c8dfc..c1aa73e3edb 100644 --- a/lib/sidebars/menu_item.rb +++ b/lib/sidebars/menu_item.rb @@ -4,12 +4,18 @@ module Sidebars class MenuItem include ::Sidebars::Concerns::LinkWithHtmlOptions - attr_reader :title, :link, :active_routes, :item_id, :container_html_options, :sprite_icon, :sprite_icon_html_options, :has_pill, :pill_count, :pill_count_field, :super_sidebar_parent, :avatar, :entity_id + attr_reader :title, :link, :active_routes, :item_id, :container_html_options, :sprite_icon, + :sprite_icon_html_options, :has_pill, :pill_count, :pill_count_field, :pill_count_dynamic, :super_sidebar_parent, + :avatar, :entity_id attr_accessor :render alias_method :has_pill?, :has_pill # rubocop: disable Metrics/ParameterLists - def initialize(title:, link:, active_routes:, item_id: nil, container_html_options: {}, sprite_icon: nil, sprite_icon_html_options: {}, has_pill: false, pill_count: nil, pill_count_field: nil, super_sidebar_parent: nil, avatar: nil, entity_id: nil) + def initialize( + title:, link:, active_routes:, item_id: nil, container_html_options: {}, sprite_icon: nil, + sprite_icon_html_options: {}, has_pill: false, pill_count_dynamic: false, pill_count: nil, + pill_count_field: nil, super_sidebar_parent: nil, avatar: nil, entity_id: nil + ) @title = title @link = link @active_routes = active_routes @@ -22,6 +28,7 @@ module Sidebars @has_pill = has_pill @pill_count = pill_count @pill_count_field = pill_count_field + @pill_count_dynamic = pill_count_dynamic @super_sidebar_parent = super_sidebar_parent end # rubocop: enable Metrics/ParameterLists @@ -41,15 +48,23 @@ module Sidebars entity_id: entity_id, link: link, active_routes: active_routes, - pill_count: has_pill ? pill_count : nil, - pill_count_field: has_pill ? pill_count_field : nil, link_classes: container_html_options[:class] # Check whether support is needed for the following properties, # in order to get feature parity with the HAML renderer # https://gitlab.com/gitlab-org/gitlab/-/issues/391864 # # container_html_options - }.compact + }.merge(pill_attributes).compact + end + + def pill_attributes + return {} unless has_pill? + + { + pill_count: pill_count, + pill_count_field: pill_count_field, + pill_count_dynamic: pill_count_dynamic + } end end end diff --git a/spec/frontend/batch_comments/components/draft_note_spec.js b/spec/frontend/batch_comments/components/draft_note_spec.js index d859f557b60..5f5d914a90f 100644 --- a/spec/frontend/batch_comments/components/draft_note_spec.js +++ b/spec/frontend/batch_comments/components/draft_note_spec.js @@ -37,16 +37,13 @@ describe('Batch comments draft note component', () => { }, }; - const createComponent = (propsData = { draft }, glFeatures = {}) => { + const createComponent = (propsData = { draft }) => { wrapper = shallowMount(DraftNote, { store, propsData, stubs: { NoteableNote: NoteableNoteStub, }, - provide: { - glFeatures, - }, }); jest.spyOn(store, 'dispatch').mockImplementation(); diff --git a/spec/frontend/ci/runner/components/runner_list_empty_state_spec.js b/spec/frontend/ci/runner/components/runner_list_empty_state_spec.js index 4f2c74245a7..04ec59d93aa 100644 --- a/spec/frontend/ci/runner/components/runner_list_empty_state_spec.js +++ b/spec/frontend/ci/runner/components/runner_list_empty_state_spec.js @@ -21,7 +21,6 @@ import RunnerListEmptyState from '~/ci/runner/components/runner_list_empty_state describe('RunnerListEmptyState', () => { let wrapper; - let glFeatures; const findEmptySearchResult = () => wrapper.findComponent(EmptyResult); const findEmptyState = () => wrapper.findComponent(GlEmptyState); @@ -48,14 +47,9 @@ describe('RunnerListEmptyState', () => { GlEmptyState, GlSprintf, }, - provide: { glFeatures }, }); }; - beforeEach(() => { - glFeatures = null; - }); - describe('when search is not filtered', () => { describe.each` newRunnerPath | registrationToken | expectedMessages diff --git a/spec/frontend/diffs/components/app_spec.js b/spec/frontend/diffs/components/app_spec.js index 3e86dcf8d07..51d73bddb63 100644 --- a/spec/frontend/diffs/components/app_spec.js +++ b/spec/frontend/diffs/components/app_spec.js @@ -75,18 +75,11 @@ describe('diffs/components/app', () => { const codeQualityAndSastQueryHandlerSuccess = jest.fn().mockResolvedValue({}); - const createComponent = ({ props = {}, provisions = {} } = {}) => { + const createComponent = ({ props = {} } = {}) => { fakeApollo = createMockApollo([ [getMRCodequalityAndSecurityReports, codeQualityAndSastQueryHandlerSuccess], ]); - const provide = { - ...provisions, - glFeatures: { - ...provisions.glFeatures, - }, - }; - wrapper = shallowMount(App, { apolloProvider: fakeApollo, propsData: { @@ -99,7 +92,6 @@ describe('diffs/components/app', () => { changesEmptyStateIllustration: '', ...props, }, - provide, store: createDiffsStore(), pinia, }); diff --git a/spec/frontend/diffs/components/diff_content_spec.js b/spec/frontend/diffs/components/diff_content_spec.js index 5e165f9348e..8561f9f9e19 100644 --- a/spec/frontend/diffs/components/diff_content_spec.js +++ b/spec/frontend/diffs/components/diff_content_spec.js @@ -33,16 +33,13 @@ describe('DiffContent', () => { diffFile: getDiffFileMock(), }; - const createComponent = ({ props, provide } = {}) => { - const glFeatures = provide ? { ...provide.glFeatures } : {}; - + const createComponent = ({ props } = {}) => { wrapper = shallowMount(DiffContentComponent, { propsData: { ...defaultProps, ...props, }, pinia, - provide: { glFeatures }, }); }; diff --git a/spec/frontend/environments/environments_detail_header_spec.js b/spec/frontend/environments/environments_detail_header_spec.js index 958cbd4bd6f..1d8116aefdf 100644 --- a/spec/frontend/environments/environments_detail_header_spec.js +++ b/spec/frontend/environments/environments_detail_header_spec.js @@ -38,15 +38,12 @@ describe('Environments detail header component', () => { ['Destroy', findDestroyButton], ]; - const createWrapper = ({ props, glFeatures = {} }) => { + const createWrapper = ({ props }) => { wrapper = shallowMountExtended(EnvironmentsDetailHeader, { stubs: { GlSprintf, TimeAgo, }, - provide: { - glFeatures, - }, directives: { GlTooltip: createMockDirective('gl-tooltip'), }, diff --git a/spec/frontend/invite_members/components/members_token_select_spec.js b/spec/frontend/invite_members/components/members_token_select_spec.js index d61879a437f..a83e38d3a83 100644 --- a/spec/frontend/invite_members/components/members_token_select_spec.js +++ b/spec/frontend/invite_members/components/members_token_select_spec.js @@ -17,7 +17,7 @@ const handleEnterSpy = jest.fn(); /** @type {import('helpers/vue_test_utils_helper').ExtendedWrapper} */ let wrapper; -const createComponent = ({ props = {}, glFeatures = {} } = {}) => { +const createComponent = ({ props = {} } = {}) => { wrapper = mountExtended(MembersTokenSelect, { propsData: { ariaLabelledby: label, @@ -25,7 +25,6 @@ const createComponent = ({ props = {}, glFeatures = {} } = {}) => { placeholder, ...props, }, - provide: { glFeatures }, }); }; diff --git a/spec/frontend/super_sidebar/components/nav_item_spec.js b/spec/frontend/super_sidebar/components/nav_item_spec.js index f3b0e827f7a..bf93fe081e7 100644 --- a/spec/frontend/super_sidebar/components/nav_item_spec.js +++ b/spec/frontend/super_sidebar/components/nav_item_spec.js @@ -75,7 +75,9 @@ describe('NavItem component', () => { }; it('updates the pill count', async () => { - createWrapper({ item: { id: itemIdForUpdate, pill_count: initialPillValue } }); + createWrapper({ + item: { id: itemIdForUpdate, pill_count: initialPillValue, pill_count_dynamic: true }, + }); await triggerPillValueUpdate(); @@ -83,7 +85,9 @@ describe('NavItem component', () => { }); it('does not update the pill count for non matching item id', async () => { - createWrapper({ item: { id: '_non_matching_id_', pill_count: initialPillValue } }); + createWrapper({ + item: { id: '_non_matching_id_', pill_count: initialPillValue, pill_count_dynamic: true }, + }); await triggerPillValueUpdate(); diff --git a/spec/frontend/vue_shared/components/blob_viewers/simple_viewer_spec.js b/spec/frontend/vue_shared/components/blob_viewers/simple_viewer_spec.js index 35dfc02bc78..c6b404780b6 100644 --- a/spec/frontend/vue_shared/components/blob_viewers/simple_viewer_spec.js +++ b/spec/frontend/vue_shared/components/blob_viewers/simple_viewer_spec.js @@ -31,7 +31,6 @@ describe('Blob Simple Viewer component', () => { isBlameLinkHidden = false, isRawContent = false, propsData = {}, - glFeatures = {}, } = {}) { fakeApollo = createMockApollo([[blameDataQuery, blameDataQueryHandlerSuccess]]); @@ -39,7 +38,6 @@ describe('Blob Simple Viewer component', () => { apolloProvider: fakeApollo, provide: { blobHash, - glFeatures, }, propsData: { content, diff --git a/spec/lib/sidebars/menu_spec.rb b/spec/lib/sidebars/menu_spec.rb index c9b46f92d39..f8bd5333f3f 100644 --- a/spec/lib/sidebars/menu_spec.rb +++ b/spec/lib/sidebars/menu_spec.rb @@ -71,7 +71,8 @@ RSpec.describe Sidebars::Menu, feature_category: :navigation do title: "Not active", link: "foo3", is_active: false, - pill_count: 10 + pill_count: 10, + pill_count_dynamic: false } ] }) diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb index d950fb032d0..fd224aca1bd 100644 --- a/spec/models/merge_request_spec.rb +++ b/spec/models/merge_request_spec.rb @@ -1348,6 +1348,7 @@ RSpec.describe MergeRequest, factory_default: :keep, feature_category: :code_rev subject.cache_merge_request_closes_issues! expect(subject.visible_closing_issues_for(guest)).to match_array([issue_1, issue_2]) + expect(subject.visible_closing_issues_for(nil)).to be_empty end it 'shows only allowed issues to developer' do @@ -1356,6 +1357,30 @@ RSpec.describe MergeRequest, factory_default: :keep, feature_category: :code_rev subject.cache_merge_request_closes_issues! expect(subject.visible_closing_issues_for(developer)).to match_array([issue_1, confidential_issue, issue_2]) + expect(subject.visible_closing_issues_for(nil)).to be_empty + end + + it 'isolates cache per user so each role sees its own issues' do + project.add_guest(guest) + project.add_developer(developer) + subject.cache_merge_request_closes_issues! + + # Call in one order + developer_view_first = subject.visible_closing_issues_for(developer) + guest_view_first = subject.visible_closing_issues_for(guest) + + expect(developer_view_first).to match_array([issue_1, issue_2, confidential_issue]) + expect(guest_view_first).to match_array([issue_1, issue_2]) + + # Reset memoization + subject.clear_memoization(:visible_closing_issues_for) # Specific to strong_memoize + + # Call in reverse order on the same instance after clearing memoization + guest_view_second = subject.visible_closing_issues_for(guest) + developer_view_second = subject.visible_closing_issues_for(developer) + + expect(guest_view_second).to match_array([issue_1, issue_2]) + expect(developer_view_second).to match_array([issue_1, issue_2, confidential_issue]) end context 'when external issue tracker is enabled' do diff --git a/spec/support/helpers/features/invite_members_modal_helpers.rb b/spec/support/helpers/features/invite_members_modal_helpers.rb index f3e629e417a..dc962874576 100644 --- a/spec/support/helpers/features/invite_members_modal_helpers.rb +++ b/spec/support/helpers/features/invite_members_modal_helpers.rb @@ -7,6 +7,10 @@ module Features def invite_member(names, role: 'Guest', expires_at: nil, use_exact_text_match: true) click_on 'Invite members' + invite_with_opened_modal(names, role: role, expires_at: expires_at, use_exact_text_match: use_exact_text_match) + end + + def invite_with_opened_modal(names, role: 'Guest', expires_at: nil, use_exact_text_match: true) page.within invite_modal_selector do select_members(names) choose_options(role, expires_at, use_exact_text_match)