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

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2022-11-21 18:12:22 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2022-11-21 18:12:22 +0300
commit5dc70663c4ff1feb215428ce50673b5b646f9809 (patch)
tree944bde8a8350ac8ee64335cc5b98d1c60ba9c3c5
parentfbc1f4ffc29ae99f438b07872c3c00fbe7651caa (diff)
Add latest changes from gitlab-org/gitlab@master
-rw-r--r--.rubocop_todo/gitlab/strong_memoize_attr.yml730
-rw-r--r--app/assets/javascripts/projects/new/constants.js2
-rw-r--r--app/helpers/labels_helper.rb6
-rw-r--r--app/models/issue.rb2
-rw-r--r--app/services/incident_management/incidents/create_service.rb2
-rw-r--r--app/services/issues/close_service.rb11
-rw-r--r--app/views/groups/labels/index.html.haml2
-rw-r--r--config/initializers/diagnostic_reports.rb4
-rw-r--r--db/structure.sql2
-rw-r--r--doc/administration/audit_events.md88
-rw-r--r--doc/architecture/blueprints/ci_pipeline_components/index.md2
-rw-r--r--doc/development/caching.md4
-rw-r--r--doc/development/secure_coding_guidelines.md11
-rw-r--r--doc/development/utilities.md14
-rw-r--r--doc/update/index.md2
-rw-r--r--lib/gitlab/memory/reports/heap_dump.rb45
-rw-r--r--lib/gitlab/memory/watchdog.rb14
-rw-r--r--lib/gitlab/memory/watchdog/configuration.rb6
-rw-r--r--lib/gitlab/memory/watchdog/configurator.rb14
-rw-r--r--lib/gitlab/utils/strong_memoize.rb10
-rw-r--r--locale/gitlab.pot13
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/pages/new_static_page_spec.rb10
-rw-r--r--rubocop/cop/gitlab/strong_memoize_attr.rb39
-rw-r--r--spec/controllers/projects_controller_spec.rb16
-rw-r--r--spec/helpers/labels_helper_spec.rb23
-rw-r--r--spec/initializers/diagnostic_reports_spec.rb19
-rw-r--r--spec/lib/gitlab/memory/reports/heap_dump_spec.rb23
-rw-r--r--spec/lib/gitlab/memory/watchdog/configurator_spec.rb42
-rw-r--r--spec/lib/gitlab/memory/watchdog_spec.rb29
-rw-r--r--spec/lib/gitlab/utils/strong_memoize_spec.rb2
-rw-r--r--spec/models/issue_spec.rb2
-rw-r--r--spec/requests/api/graphql/project/issues_spec.rb2
-rw-r--r--spec/requests/search_controller_spec.rb83
-rw-r--r--spec/rubocop/cop/gitlab/strong_memoize_attr_spec.rb72
-rw-r--r--spec/services/incident_management/incidents/create_service_spec.rb24
-rw-r--r--spec/services/issues/close_service_spec.rb34
-rw-r--r--spec/services/projects/transfer_service_spec.rb14
-rw-r--r--spec/support/helpers/search_helpers.rb2
-rw-r--r--spec/views/search/_results.html.haml_spec.rb66
39 files changed, 1293 insertions, 193 deletions
diff --git a/.rubocop_todo/gitlab/strong_memoize_attr.yml b/.rubocop_todo/gitlab/strong_memoize_attr.yml
new file mode 100644
index 00000000000..d2824550042
--- /dev/null
+++ b/.rubocop_todo/gitlab/strong_memoize_attr.yml
@@ -0,0 +1,730 @@
+---
+# Cop supports --autocorrect.
+Gitlab/StrongMemoizeAttr:
+ Details: grace period
+ Exclude:
+ - 'app/components/pajamas/avatar_component.rb'
+ - 'app/controllers/application_controller.rb'
+ - 'app/controllers/concerns/boards_actions.rb'
+ - 'app/controllers/concerns/creates_commit.rb'
+ - 'app/controllers/concerns/find_snippet.rb'
+ - 'app/controllers/concerns/impersonation.rb'
+ - 'app/controllers/concerns/issuable_actions.rb'
+ - 'app/controllers/concerns/issuable_collections.rb'
+ - 'app/controllers/concerns/known_sign_in.rb'
+ - 'app/controllers/concerns/lfs_request.rb'
+ - 'app/controllers/concerns/notes_actions.rb'
+ - 'app/controllers/concerns/snippets/blobs_actions.rb'
+ - 'app/controllers/concerns/uploads_actions.rb'
+ - 'app/controllers/concerns/wiki_actions.rb'
+ - 'app/controllers/google_api/authorizations_controller.rb'
+ - 'app/controllers/groups/boards_controller.rb'
+ - 'app/controllers/groups/dependency_proxy_for_containers_controller.rb'
+ - 'app/controllers/ide_controller.rb'
+ - 'app/controllers/import/github_controller.rb'
+ - 'app/controllers/invites_controller.rb'
+ - 'app/controllers/jira_connect/application_controller.rb'
+ - 'app/controllers/jwt_controller.rb'
+ - 'app/controllers/oauth/authorizations_controller.rb'
+ - 'app/controllers/projects/analytics/cycle_analytics/stages_controller.rb'
+ - 'app/controllers/projects/boards_controller.rb'
+ - 'app/controllers/projects/compare_controller.rb'
+ - 'app/controllers/projects/forks_controller.rb'
+ - 'app/controllers/projects/import/jira_controller.rb'
+ - 'app/controllers/projects/incidents_controller.rb'
+ - 'app/controllers/projects/merge_requests_controller.rb'
+ - 'app/controllers/projects/metrics_dashboard_controller.rb'
+ - 'app/controllers/projects/milestones_controller.rb'
+ - 'app/controllers/projects/pipelines/application_controller.rb'
+ - 'app/controllers/projects/pipelines_controller.rb'
+ - 'app/controllers/projects/todos_controller.rb'
+ - 'app/controllers/repositories/git_http_client_controller.rb'
+ - 'app/controllers/repositories/lfs_api_controller.rb'
+ - 'app/controllers/sessions_controller.rb'
+ - 'app/controllers/whats_new_controller.rb'
+ - 'app/finders/autocomplete/users_finder.rb'
+ - 'app/finders/ci/commit_statuses_finder.rb'
+ - 'app/finders/ci/pipelines_for_merge_request_finder.rb'
+ - 'app/finders/cluster_ancestors_finder.rb'
+ - 'app/finders/clusters/knative_services_finder.rb'
+ - 'app/finders/concerns/finder_with_group_hierarchy.rb'
+ - 'app/finders/crm/contacts_finder.rb'
+ - 'app/finders/crm/organizations_finder.rb'
+ - 'app/finders/groups/accepting_group_transfers_finder.rb'
+ - 'app/finders/issuable_finder.rb'
+ - 'app/finders/issuable_finder/params.rb'
+ - 'app/finders/issuables/label_filter.rb'
+ - 'app/finders/issues_finder/params.rb'
+ - 'app/finders/license_template_finder.rb'
+ - 'app/finders/merge_requests_finder/params.rb'
+ - 'app/finders/projects/members/effective_access_level_finder.rb'
+ - 'app/finders/releases/evidence_pipeline_finder.rb'
+ - 'app/finders/releases_finder.rb'
+ - 'app/finders/snippets_finder.rb'
+ - 'app/finders/todos_finder.rb'
+ - 'app/graphql/resolvers/issue_status_counts_resolver.rb'
+ - 'app/graphql/resolvers/issues/base_parent_resolver.rb'
+ - 'app/graphql/resolvers/namespace_projects_resolver.rb'
+ - 'app/graphql/resolvers/work_items_resolver.rb'
+ - 'app/graphql/types/board_list_type.rb'
+ - 'app/helpers/appearances_helper.rb'
+ - 'app/helpers/operations_helper.rb'
+ - 'app/helpers/page_layout_helper.rb'
+ - 'app/helpers/projects_helper.rb'
+ - 'app/helpers/sessions_helper.rb'
+ - 'app/helpers/timeboxes_helper.rb'
+ - 'app/models/alert_management/alert.rb'
+ - 'app/models/application_setting_implementation.rb'
+ - 'app/models/blob_viewer/go_mod.rb'
+ - 'app/models/blob_viewer/metrics_dashboard_yml.rb'
+ - 'app/models/bulk_imports/export.rb'
+ - 'app/models/bulk_imports/export_status.rb'
+ - 'app/models/bulk_imports/file_transfer/base_config.rb'
+ - 'app/models/ci/bridge.rb'
+ - 'app/models/ci/build.rb'
+ - 'app/models/ci/build_dependencies.rb'
+ - 'app/models/ci/build_metadata.rb'
+ - 'app/models/ci/commit_with_pipeline.rb'
+ - 'app/models/ci/group.rb'
+ - 'app/models/ci/job_artifact.rb'
+ - 'app/models/ci/pipeline.rb'
+ - 'app/models/ci/processable.rb'
+ - 'app/models/ci/runner.rb'
+ - 'app/models/clusters/cluster.rb'
+ - 'app/models/clusters/providers/aws.rb'
+ - 'app/models/commit.rb'
+ - 'app/models/commit_collection.rb'
+ - 'app/models/compare.rb'
+ - 'app/models/concerns/analytics/cycle_analytics/stage.rb'
+ - 'app/models/concerns/avatarable.rb'
+ - 'app/models/concerns/cascading_namespace_setting_attribute.rb'
+ - 'app/models/concerns/ci/contextable.rb'
+ - 'app/models/concerns/discussion_on_diff.rb'
+ - 'app/models/concerns/has_repository.rb'
+ - 'app/models/concerns/has_wiki.rb'
+ - 'app/models/concerns/has_wiki_page_meta_attributes.rb'
+ - 'app/models/concerns/redis_cacheable.rb'
+ - 'app/models/concerns/require_email_verification.rb'
+ - 'app/models/concerns/resolvable_discussion.rb'
+ - 'app/models/concerns/security/latest_pipeline_information.rb'
+ - 'app/models/container_registry/event.rb'
+ - 'app/models/container_repository.rb'
+ - 'app/models/customer_relations/contact_state_counts.rb'
+ - 'app/models/deploy_token.rb'
+ - 'app/models/deployment.rb'
+ - 'app/models/deployment_metrics.rb'
+ - 'app/models/design_management/design.rb'
+ - 'app/models/design_management/design_at_version.rb'
+ - 'app/models/design_management/version.rb'
+ - 'app/models/diff_note.rb'
+ - 'app/models/draft_note.rb'
+ - 'app/models/environment.rb'
+ - 'app/models/environment_status.rb'
+ - 'app/models/error_tracking/project_error_tracking_setting.rb'
+ - 'app/models/event.rb'
+ - 'app/models/event_collection.rb'
+ - 'app/models/group.rb'
+ - 'app/models/incident_management/project_incident_management_setting.rb'
+ - 'app/models/integrations/jira.rb'
+ - 'app/models/internal_id.rb'
+ - 'app/models/member.rb'
+ - 'app/models/merge_request.rb'
+ - 'app/models/merge_request_diff.rb'
+ - 'app/models/namespace.rb'
+ - 'app/models/note.rb'
+ - 'app/models/onboarding/completion.rb'
+ - 'app/models/packages/go/module.rb'
+ - 'app/models/packages/go/module_version.rb'
+ - 'app/models/packages/package.rb'
+ - 'app/models/pages/lookup_path.rb'
+ - 'app/models/project.rb'
+ - 'app/models/release.rb'
+ - 'app/models/resource_event.rb'
+ - 'app/models/service_desk_setting.rb'
+ - 'app/models/snippet.rb'
+ - 'app/models/snippet_input_action_collection.rb'
+ - 'app/models/state_note.rb'
+ - 'app/models/tree.rb'
+ - 'app/models/user.rb'
+ - 'app/models/wiki_page.rb'
+ - 'app/models/work_item.rb'
+ - 'app/policies/application_setting/term_policy.rb'
+ - 'app/policies/note_policy.rb'
+ - 'app/presenters/blobs/unfold_presenter.rb'
+ - 'app/presenters/ci/build_runner_presenter.rb'
+ - 'app/presenters/ci/pipeline_artifacts/code_coverage_presenter.rb'
+ - 'app/presenters/ci/pipeline_artifacts/code_quality_mr_diff_presenter.rb'
+ - 'app/presenters/ci/pipeline_presenter.rb'
+ - 'app/presenters/clusters/cluster_presenter.rb'
+ - 'app/presenters/merge_request_presenter.rb'
+ - 'app/presenters/packages/nuget/packages_metadata_presenter.rb'
+ - 'app/presenters/packages/nuget/search_results_presenter.rb'
+ - 'app/presenters/project_presenter.rb'
+ - 'app/presenters/projects/settings/deploy_keys_presenter.rb'
+ - 'app/serializers/ci/pipeline_entity.rb'
+ - 'app/serializers/concerns/diff_file_conflict_type.rb'
+ - 'app/serializers/diff_file_base_entity.rb'
+ - 'app/serializers/integrations/field_entity.rb'
+ - 'app/serializers/linked_project_issue_entity.rb'
+ - 'app/serializers/suggestion_entity.rb'
+ - 'app/services/alert_management/alerts/update_service.rb'
+ - 'app/services/alert_management/create_alert_issue_service.rb'
+ - 'app/services/alert_management/process_prometheus_alert_service.rb'
+ - 'app/services/auth/dependency_proxy_authentication_service.rb'
+ - 'app/services/authorized_project_update/project_recalculate_service.rb'
+ - 'app/services/auto_merge/base_service.rb'
+ - 'app/services/award_emojis/add_service.rb'
+ - 'app/services/base_project_service.rb'
+ - 'app/services/boards/base_items_list_service.rb'
+ - 'app/services/boards/lists/base_create_service.rb'
+ - 'app/services/ci/create_downstream_pipeline_service.rb'
+ - 'app/services/ci/create_web_ide_terminal_service.rb'
+ - 'app/services/ci/job_artifacts/destroy_batch_service.rb'
+ - 'app/services/ci/parse_dotenv_artifact_service.rb'
+ - 'app/services/ci/pipeline_artifacts/coverage_report_service.rb'
+ - 'app/services/ci/pipeline_artifacts/create_code_quality_mr_diff_report_service.rb'
+ - 'app/services/ci/pipeline_artifacts/destroy_all_expired_service.rb'
+ - 'app/services/ci/pipeline_processing/atomic_processing_service/status_collection.rb'
+ - 'app/services/ci/pipeline_schedules/calculate_next_run_service.rb'
+ - 'app/services/ci/pipeline_trigger_service.rb'
+ - 'app/services/ci/pipelines/hook_service.rb'
+ - 'app/services/ci/queue/build_queue_service.rb'
+ - 'app/services/ci/update_build_state_service.rb'
+ - 'app/services/clusters/agents/refresh_authorization_service.rb'
+ - 'app/services/clusters/aws/finalize_creation_service.rb'
+ - 'app/services/clusters/integrations/prometheus_health_check_service.rb'
+ - 'app/services/concerns/alert_management/alert_processing.rb'
+ - 'app/services/concerns/incident_management/settings.rb'
+ - 'app/services/concerns/issues/resolve_discussions.rb'
+ - 'app/services/concerns/suggestible.rb'
+ - 'app/services/concerns/update_repository_storage_methods.rb'
+ - 'app/services/container_expiration_policies/update_service.rb'
+ - 'app/services/dependency_proxy/image_ttl_group_policies/update_service.rb'
+ - 'app/services/discussions/resolve_service.rb'
+ - 'app/services/error_tracking/collect_error_service.rb'
+ - 'app/services/error_tracking/issue_details_service.rb'
+ - 'app/services/feature_flags/base_service.rb'
+ - 'app/services/git/base_hooks_service.rb'
+ - 'app/services/git/branch_hooks_service.rb'
+ - 'app/services/git/branch_push_service.rb'
+ - 'app/services/git/tag_hooks_service.rb'
+ - 'app/services/git/wiki_push_service/change.rb'
+ - 'app/services/groups/open_issues_count_service.rb'
+ - 'app/services/import/github_service.rb'
+ - 'app/services/import/gitlab_projects/file_acquisition_strategies/remote_file_s3.rb'
+ - 'app/services/incident_management/issuable_escalation_statuses/prepare_update_service.rb'
+ - 'app/services/incident_management/pager_duty/process_webhook_service.rb'
+ - 'app/services/integrations/test/project_service.rb'
+ - 'app/services/issues/reorder_service.rb'
+ - 'app/services/jira_connect_subscriptions/create_service.rb'
+ - 'app/services/jira_import/users_mapper_service.rb'
+ - 'app/services/lfs/push_service.rb'
+ - 'app/services/markdown_content_rewriter_service.rb'
+ - 'app/services/members/invitation_reminder_email_service.rb'
+ - 'app/services/merge_requests/build_service.rb'
+ - 'app/services/merge_requests/merge_base_service.rb'
+ - 'app/services/merge_requests/mergeability/detailed_merge_status_service.rb'
+ - 'app/services/merge_requests/mergeability/logger.rb'
+ - 'app/services/merge_requests/mergeability/run_checks_service.rb'
+ - 'app/services/merge_requests/mergeability_check_service.rb'
+ - 'app/services/merge_requests/outdated_discussion_diff_lines_service.rb'
+ - 'app/services/merge_requests/pushed_branches_service.rb'
+ - 'app/services/merge_requests/refresh_service.rb'
+ - 'app/services/metrics/dashboard/clone_dashboard_service.rb'
+ - 'app/services/metrics/dashboard/custom_metric_embed_service.rb'
+ - 'app/services/metrics/dashboard/dynamic_embed_service.rb'
+ - 'app/services/metrics/dashboard/gitlab_alert_embed_service.rb'
+ - 'app/services/namespaces/package_settings/update_service.rb'
+ - 'app/services/packages/cleanup/execute_policy_service.rb'
+ - 'app/services/packages/cleanup/update_policy_service.rb'
+ - 'app/services/packages/composer/create_package_service.rb'
+ - 'app/services/packages/debian/extract_changes_metadata_service.rb'
+ - 'app/services/packages/debian/extract_metadata_service.rb'
+ - 'app/services/packages/debian/find_or_create_package_service.rb'
+ - 'app/services/packages/debian/generate_distribution_key_service.rb'
+ - 'app/services/packages/debian/generate_distribution_service.rb'
+ - 'app/services/packages/debian/process_changes_service.rb'
+ - 'app/services/packages/helm/process_file_service.rb'
+ - 'app/services/packages/maven/metadata/base_create_xml_service.rb'
+ - 'app/services/packages/maven/metadata/create_plugins_xml_service.rb'
+ - 'app/services/packages/maven/metadata/create_versions_xml_service.rb'
+ - 'app/services/packages/maven/metadata/sync_service.rb'
+ - 'app/services/packages/npm/create_package_service.rb'
+ - 'app/services/packages/npm/create_tag_service.rb'
+ - 'app/services/packages/nuget/metadata_extraction_service.rb'
+ - 'app/services/packages/nuget/search_service.rb'
+ - 'app/services/packages/nuget/sync_metadatum_service.rb'
+ - 'app/services/packages/nuget/update_package_from_metadata_service.rb'
+ - 'app/services/packages/pypi/create_package_service.rb'
+ - 'app/services/packages/rpm/parse_package_service.rb'
+ - 'app/services/packages/rubygems/dependency_resolver_service.rb'
+ - 'app/services/packages/rubygems/process_gem_service.rb'
+ - 'app/services/packages/terraform_module/create_package_service.rb'
+ - 'app/services/packages/update_tags_service.rb'
+ - 'app/services/projects/container_repository/cleanup_tags_base_service.rb'
+ - 'app/services/projects/container_repository/third_party/cleanup_tags_service.rb'
+ - 'app/services/projects/create_from_template_service.rb'
+ - 'app/services/projects/gitlab_projects_import_service.rb'
+ - 'app/services/projects/open_issues_count_service.rb'
+ - 'app/services/projects/record_target_platforms_service.rb'
+ - 'app/services/projects/update_remote_mirror_service.rb'
+ - 'app/services/projects/update_statistics_service.rb'
+ - 'app/services/prometheus/proxy_service.rb'
+ - 'app/services/quick_actions/interpret_service.rb'
+ - 'app/services/releases/base_service.rb'
+ - 'app/services/resource_access_tokens/revoke_service.rb'
+ - 'app/services/resource_events/base_synthetic_notes_builder_service.rb'
+ - 'app/services/search/global_service.rb'
+ - 'app/services/search/project_service.rb'
+ - 'app/services/search_service.rb'
+ - 'app/services/security/ci_configuration/sast_parser_service.rb'
+ - 'app/services/test_hooks/project_service.rb'
+ - 'app/services/test_hooks/system_service.rb'
+ - 'app/uploaders/file_mover.rb'
+ - 'app/uploaders/object_storage/cdn.rb'
+ - 'app/uploaders/object_storage/cdn/google_cdn.rb'
+ - 'app/workers/concerns/each_shard_worker.rb'
+ - 'app/workers/concerns/limited_capacity/worker.rb'
+ - 'app/workers/concerns/packages/cleanup_artifact_worker.rb'
+ - 'app/workers/container_expiration_policies/cleanup_container_repository_worker.rb'
+ - 'app/workers/container_registry/delete_container_repository_worker.rb'
+ - 'app/workers/container_registry/migration/enqueuer_worker.rb'
+ - 'app/workers/database/batched_background_migration/execution_worker.rb'
+ - 'app/workers/database/batched_background_migration/single_database_worker.rb'
+ - 'app/workers/error_tracking_issue_link_worker.rb'
+ - 'app/workers/merge_request_cleanup_refs_worker.rb'
+ - 'app/workers/packages/cleanup/execute_policy_worker.rb'
+ - 'app/workers/packages/debian/generate_distribution_worker.rb'
+ - 'app/workers/packages/debian/process_changes_worker.rb'
+ - 'app/workers/packages/maven/metadata/sync_worker.rb'
+ - 'app/workers/projects/inactive_projects_deletion_cron_worker.rb'
+ - 'ee/app/controllers/admin/audit_logs_controller.rb'
+ - 'ee/app/controllers/concerns/description_diff_actions.rb'
+ - 'ee/app/controllers/concerns/ee/lfs_request.rb'
+ - 'ee/app/controllers/concerns/ee/routable_actions/sso_enforcement_redirect.rb'
+ - 'ee/app/controllers/concerns/epic_relations.rb'
+ - 'ee/app/controllers/ee/admin/health_check_controller.rb'
+ - 'ee/app/controllers/ee/groups/settings/repository_controller.rb'
+ - 'ee/app/controllers/ee/groups_controller.rb'
+ - 'ee/app/controllers/ee/registrations/welcome_controller.rb'
+ - 'ee/app/controllers/ee/repositories/git_http_controller.rb'
+ - 'ee/app/controllers/groups/audit_events_controller.rb'
+ - 'ee/app/controllers/groups/epic_boards_controller.rb'
+ - 'ee/app/controllers/groups/push_rules_controller.rb'
+ - 'ee/app/controllers/groups/todos_controller.rb'
+ - 'ee/app/controllers/projects/audit_events_controller.rb'
+ - 'ee/app/controllers/projects/subscriptions_controller.rb'
+ - 'ee/app/controllers/subscriptions_controller.rb'
+ - 'ee/app/finders/approval_rules/group_finder.rb'
+ - 'ee/app/finders/concerns/epics/with_access_check.rb'
+ - 'ee/app/finders/ee/issues_finder.rb'
+ - 'ee/app/finders/epics_finder.rb'
+ - 'ee/app/finders/incident_management/oncall_users_finder.rb'
+ - 'ee/app/finders/requirements_management/requirements_finder.rb'
+ - 'ee/app/finders/security/pipeline_vulnerabilities_finder.rb'
+ - 'ee/app/finders/security/training_providers/base_url_finder.rb'
+ - 'ee/app/graphql/resolvers/epics_resolver.rb'
+ - 'ee/app/graphql/resolvers/vulnerabilities_base_resolver.rb'
+ - 'ee/app/helpers/admin/emails_helper.rb'
+ - 'ee/app/helpers/auditor_user_helper.rb'
+ - 'ee/app/helpers/billing_plans_helper.rb'
+ - 'ee/app/helpers/ee/ci/runners_helper.rb'
+ - 'ee/app/helpers/ee/preferences_helper.rb'
+ - 'ee/app/helpers/ee/registrations_helper.rb'
+ - 'ee/app/helpers/ee/timeboxes_helper.rb'
+ - 'ee/app/helpers/ee/trial_helper.rb'
+ - 'ee/app/helpers/ee/welcome_helper.rb'
+ - 'ee/app/helpers/license_monitoring_helper.rb'
+ - 'ee/app/helpers/paid_feature_callout_helper.rb'
+ - 'ee/app/helpers/trial_status_widget_helper.rb'
+ - 'ee/app/models/approval_merge_request_rule.rb'
+ - 'ee/app/models/approval_state.rb'
+ - 'ee/app/models/approval_wrapped_any_approver_rule.rb'
+ - 'ee/app/models/approval_wrapped_code_owner_rule.rb'
+ - 'ee/app/models/approval_wrapped_rule.rb'
+ - 'ee/app/models/approvals/scan_finding_wrapped_rule_set.rb'
+ - 'ee/app/models/approvals/wrapped_rule_set.rb'
+ - 'ee/app/models/ci/minutes/limit.rb'
+ - 'ee/app/models/concerns/deprecated_approvals_before_merge.rb'
+ - 'ee/app/models/concerns/ee/approvable.rb'
+ - 'ee/app/models/concerns/ee/issue_available_features.rb'
+ - 'ee/app/models/concerns/insights_feature.rb'
+ - 'ee/app/models/concerns/security/scan_execution_policy.rb'
+ - 'ee/app/models/deployments/approval_summary.rb'
+ - 'ee/app/models/ee/audit_event.rb'
+ - 'ee/app/models/ee/ci/bridge.rb'
+ - 'ee/app/models/ee/ci/build.rb'
+ - 'ee/app/models/ee/ci/build_dependencies.rb'
+ - 'ee/app/models/ee/ci/job_artifact.rb'
+ - 'ee/app/models/ee/ci/runner.rb'
+ - 'ee/app/models/ee/deployment.rb'
+ - 'ee/app/models/ee/environment.rb'
+ - 'ee/app/models/ee/group.rb'
+ - 'ee/app/models/ee/integrations/jira.rb'
+ - 'ee/app/models/ee/list.rb'
+ - 'ee/app/models/ee/merge_request.rb'
+ - 'ee/app/models/ee/namespace.rb'
+ - 'ee/app/models/ee/namespace/storage/notification.rb'
+ - 'ee/app/models/ee/project.rb'
+ - 'ee/app/models/ee/snippet.rb'
+ - 'ee/app/models/ee/user.rb'
+ - 'ee/app/models/ee/work_item.rb'
+ - 'ee/app/models/gitlab/seat_link_data.rb'
+ - 'ee/app/models/gitlab_subscription.rb'
+ - 'ee/app/models/issuables_analytics.rb'
+ - 'ee/app/models/license.rb'
+ - 'ee/app/models/namespaces/storage/root_excess_size.rb'
+ - 'ee/app/models/sca/license_compliance.rb'
+ - 'ee/app/models/security/orchestration_policy_configuration.rb'
+ - 'ee/app/models/security/orchestration_policy_rule_schedule.rb'
+ - 'ee/app/models/vulnerabilities/finding.rb'
+ - 'ee/app/presenters/approval_rule_presenter.rb'
+ - 'ee/app/presenters/ci/minutes/usage_presenter.rb'
+ - 'ee/app/presenters/merge_request_approver_presenter.rb'
+ - 'ee/app/serializers/dashboard_operations_project_entity.rb'
+ - 'ee/app/serializers/ee/member_user_entity.rb'
+ - 'ee/app/services/app_sec/dast/pipelines/find_latest_service.rb'
+ - 'ee/app/services/app_sec/dast/scan_configs/build_service.rb'
+ - 'ee/app/services/approval_rules/params_filtering_service.rb'
+ - 'ee/app/services/boards/epics/position_create_service.rb'
+ - 'ee/app/services/ci/compare_license_scanning_reports_collapsed_service.rb'
+ - 'ee/app/services/ci/minutes/update_project_and_namespace_usage_service.rb'
+ - 'ee/app/services/ci/subscribe_bridge_service.rb'
+ - 'ee/app/services/ci/sync_reports_to_approval_rules_service.rb'
+ - 'ee/app/services/deployments/approval_service.rb'
+ - 'ee/app/services/ee/allowed_email_domains/update_service.rb'
+ - 'ee/app/services/ee/auto_merge_service.rb'
+ - 'ee/app/services/ee/boards/lists/create_service.rb'
+ - 'ee/app/services/ee/ci/retry_pipeline_service.rb'
+ - 'ee/app/services/ee/incident_management/issuable_escalation_statuses/prepare_update_service.rb'
+ - 'ee/app/services/ee/integrations/test/project_service.rb'
+ - 'ee/app/services/ee/ip_restrictions/update_service.rb'
+ - 'ee/app/services/ee/issuable_base_service.rb'
+ - 'ee/app/services/ee/issues/export_csv_service.rb'
+ - 'ee/app/services/ee/merge_requests/merge_base_service.rb'
+ - 'ee/app/services/ee/post_receive_service.rb'
+ - 'ee/app/services/ee/projects/create_from_template_service.rb'
+ - 'ee/app/services/ee/projects/gitlab_projects_import_service.rb'
+ - 'ee/app/services/ee/protected_branches/create_service.rb'
+ - 'ee/app/services/ee/search/global_service.rb'
+ - 'ee/app/services/ee/search_service.rb'
+ - 'ee/app/services/ee/users/build_service.rb'
+ - 'ee/app/services/ee/users/update_service.rb'
+ - 'ee/app/services/elastic/cluster_reindexing_service.rb'
+ - 'ee/app/services/epic_issues/list_service.rb'
+ - 'ee/app/services/epics/descendant_count_service.rb'
+ - 'ee/app/services/epics/related_epic_links/destroy_service.rb'
+ - 'ee/app/services/geo/container_repository_sync.rb'
+ - 'ee/app/services/geo/event_service.rb'
+ - 'ee/app/services/geo/file_registry_removal_service.rb'
+ - 'ee/app/services/geo/repository_destroy_service.rb'
+ - 'ee/app/services/gitlab_subscriptions/activate_service.rb'
+ - 'ee/app/services/gitlab_subscriptions/create_service.rb'
+ - 'ee/app/services/gitlab_subscriptions/fetch_purchase_eligible_namespaces_service.rb'
+ - 'ee/app/services/gitlab_subscriptions/reconciliations/calculate_seat_count_data_service.rb'
+ - 'ee/app/services/groups/sync_service.rb'
+ - 'ee/app/services/incident_management/escalation_policies/update_service.rb'
+ - 'ee/app/services/incident_management/pending_escalations/process_service.rb'
+ - 'ee/app/services/iterations/create_service.rb'
+ - 'ee/app/services/merge_commits/export_csv_service.rb'
+ - 'ee/app/services/merge_requests/update_blocks_service.rb'
+ - 'ee/app/services/projects/restore_service.rb'
+ - 'ee/app/services/projects/update_mirror_service.rb'
+ - 'ee/app/services/protected_environments/base_service.rb'
+ - 'ee/app/services/security/ingestion/tasks/ingest_vulnerabilities/mark_resolved_as_detected.rb'
+ - 'ee/app/services/security/report_fetch_service.rb'
+ - 'ee/app/services/security/report_summary_service.rb'
+ - 'ee/app/services/security/security_orchestration_policies/on_demand_scan_pipeline_configuration_service.rb'
+ - 'ee/app/services/security/security_orchestration_policies/operational_vulnerabilities_configuration_service.rb'
+ - 'ee/app/services/security/security_orchestration_policies/validate_policy_service.rb'
+ - 'ee/app/services/status_page/publish_attachments_service.rb'
+ - 'ee/app/services/status_page/publish_base_service.rb'
+ - 'ee/app/services/status_page/publish_service.rb'
+ - 'ee/app/services/status_page/trigger_publish_service.rb'
+ - 'ee/app/services/timebox_report_service.rb'
+ - 'ee/app/services/vulnerabilities/create_service.rb'
+ - 'ee/app/services/vulnerability_feedback/create_service.rb'
+ - 'ee/app/services/vulnerability_feedback/destroy_service.rb'
+ - 'ee/app/workers/auth/saml_group_sync_worker.rb'
+ - 'ee/app/workers/geo/repository_cleanup_worker.rb'
+ - 'ee/app/workers/group_saml_group_sync_worker.rb'
+ - 'ee/app/workers/status_page/publish_worker.rb'
+ - 'ee/lib/api/analytics/project_deployment_frequency.rb'
+ - 'ee/lib/api/epic_links.rb'
+ - 'ee/lib/api/geo_nodes.rb'
+ - 'ee/lib/api/vulnerability_exports.rb'
+ - 'ee/lib/api/vulnerability_findings.rb'
+ - 'ee/lib/ee/api/geo.rb'
+ - 'ee/lib/ee/banzai/filter/references/reference_cache.rb'
+ - 'ee/lib/ee/container_registry/client.rb'
+ - 'ee/lib/ee/gitlab/alert_management/payload/generic.rb'
+ - 'ee/lib/ee/gitlab/analytics/cycle_analytics/data_collector.rb'
+ - 'ee/lib/ee/gitlab/analytics/cycle_analytics/stage_events.rb'
+ - 'ee/lib/ee/gitlab/auth/o_auth/auth_hash.rb'
+ - 'ee/lib/ee/gitlab/background_migration/backfill_project_statistics_container_repository_size.rb'
+ - 'ee/lib/ee/gitlab/background_migration/migrate_approver_to_approval_rules.rb'
+ - 'ee/lib/ee/gitlab/background_migration/populate_resolved_on_default_branch_column.rb'
+ - 'ee/lib/ee/gitlab/checks/base_checker.rb'
+ - 'ee/lib/ee/gitlab/checks/diff_check.rb'
+ - 'ee/lib/ee/gitlab/ci/matching/runner_matcher.rb'
+ - 'ee/lib/ee/gitlab/ci/pipeline/chain/validate/external.rb'
+ - 'ee/lib/ee/gitlab/ci/pipeline/quota/activity.rb'
+ - 'ee/lib/ee/gitlab/ci/pipeline/quota/size.rb'
+ - 'ee/lib/ee/gitlab/etag_caching/router/rails.rb'
+ - 'ee/lib/ee/gitlab/git_access.rb'
+ - 'ee/lib/ee/gitlab/gitaly_client/with_feature_flag_actors.rb'
+ - 'ee/lib/ee/gitlab/import_export/after_export_strategies/custom_template_export_import_strategy.rb'
+ - 'ee/lib/ee/gitlab/issuable_metadata.rb'
+ - 'ee/lib/ee/gitlab/scim/deprovision_service.rb'
+ - 'ee/lib/ee/gitlab/scim/provisioning_service.rb'
+ - 'ee/lib/ee/gitlab/security/scan_configuration.rb'
+ - 'ee/lib/ee/gitlab/web_hooks/rate_limiter.rb'
+ - 'ee/lib/ee/sidebars/groups/menus/issues_menu.rb'
+ - 'ee/lib/ee/sidebars/groups/menus/settings_menu.rb'
+ - 'ee/lib/elastic/multi_version_util.rb'
+ - 'ee/lib/gitlab/auth/group_saml/auth_hash.rb'
+ - 'ee/lib/gitlab/auth/group_saml/membership_updater.rb'
+ - 'ee/lib/gitlab/auth/group_saml/user.rb'
+ - 'ee/lib/gitlab/auth/saml/membership_updater.rb'
+ - 'ee/lib/gitlab/auth/smartcard/certificate.rb'
+ - 'ee/lib/gitlab/ci/minutes/build_consumption.rb'
+ - 'ee/lib/gitlab/ci/minutes/cached_quota.rb'
+ - 'ee/lib/gitlab/ci/minutes/gitlab_contribution_cost_factor.rb'
+ - 'ee/lib/gitlab/ci/minutes/runners_availability.rb'
+ - 'ee/lib/gitlab/ci/parsers/security/container_scanning.rb'
+ - 'ee/lib/gitlab/ci/project_config/compliance.rb'
+ - 'ee/lib/gitlab/ci/reports/license_scanning/reports_comparer.rb'
+ - 'ee/lib/gitlab/ci/reports/metrics/reports_comparer.rb'
+ - 'ee/lib/gitlab/code_owners/entry.rb'
+ - 'ee/lib/gitlab/code_owners/loader.rb'
+ - 'ee/lib/gitlab/custom_file_templates.rb'
+ - 'ee/lib/gitlab/elastic/document_reference.rb'
+ - 'ee/lib/gitlab/elastic/indexer.rb'
+ - 'ee/lib/gitlab/elastic/search_results.rb'
+ - 'ee/lib/gitlab/expiring_subscription_message.rb'
+ - 'ee/lib/gitlab/geo/health_check.rb'
+ - 'ee/lib/gitlab/geo/jwt_request_decoder.rb'
+ - 'ee/lib/gitlab/geo/oauth/logout_state.rb'
+ - 'ee/lib/gitlab/geo/oauth/logout_token.rb'
+ - 'ee/lib/gitlab/geo/oauth/session.rb'
+ - 'ee/lib/gitlab/geo/replication/blob_retriever.rb'
+ - 'ee/lib/gitlab/graphql/aggregations/epics/epic_node.rb'
+ - 'ee/lib/gitlab/ingestion/bulk_insertable_task.rb'
+ - 'ee/lib/gitlab/ingestion/bulk_updatable_task.rb'
+ - 'ee/lib/gitlab/insights/finders/issuable_finder.rb'
+ - 'ee/lib/gitlab/insights/finders/projects_finder.rb'
+ - 'ee/lib/gitlab/manual_quarterly_co_term_banner.rb'
+ - 'ee/lib/gitlab/return_to_location.rb'
+ - 'ee/lib/gitlab_subscriptions/upcoming_reconciliation_entity.rb'
+ - 'ee/lib/incident_management/oncall_shift_generator.rb'
+ - 'ee/lib/sidebars/groups/menus/analytics_menu.rb'
+ - 'ee/lib/sidebars/groups/menus/epics_menu.rb'
+ - 'ee/lib/world.rb'
+ - 'lib/api/api_guard.rb'
+ - 'lib/api/ci/helpers/runner.rb'
+ - 'lib/api/ci/pipelines.rb'
+ - 'lib/api/commit_statuses.rb'
+ - 'lib/api/composer_packages.rb'
+ - 'lib/api/container_repositories.rb'
+ - 'lib/api/entities/basic_project_details.rb'
+ - 'lib/api/helpers/packages/basic_auth_helpers.rb'
+ - 'lib/api/helpers/packages/conan/api_helpers.rb'
+ - 'lib/api/helpers/packages/npm.rb'
+ - 'lib/api/helpers/packages_helpers.rb'
+ - 'lib/api/terraform/modules/v1/packages.rb'
+ - 'lib/api/unleash.rb'
+ - 'lib/atlassian/jira_connect/jwt/asymmetric.rb'
+ - 'lib/atlassian/jira_connect/jwt/symmetric.rb'
+ - 'lib/banzai/filter/base_sanitization_filter.rb'
+ - 'lib/banzai/filter/custom_emoji_filter.rb'
+ - 'lib/banzai/filter/inline_metrics_redactor_filter.rb'
+ - 'lib/banzai/filter/issuable_reference_expansion_filter.rb'
+ - 'lib/banzai/filter/references/reference_cache.rb'
+ - 'lib/banzai/filter/repository_link_filter.rb'
+ - 'lib/bulk_imports/clients/http.rb'
+ - 'lib/bulk_imports/pipeline.rb'
+ - 'lib/bulk_imports/users_mapper.rb'
+ - 'lib/container_registry/client.rb'
+ - 'lib/container_registry/gitlab_api_client.rb'
+ - 'lib/container_registry/tag.rb'
+ - 'lib/flowdock/git/builder.rb'
+ - 'lib/gitlab/alert_management/alert_status_counts.rb'
+ - 'lib/gitlab/alert_management/payload/base.rb'
+ - 'lib/gitlab/alert_management/payload/managed_prometheus.rb'
+ - 'lib/gitlab/analytics/cycle_analytics/aggregated/data_collector.rb'
+ - 'lib/gitlab/analytics/cycle_analytics/aggregated/records_fetcher.rb'
+ - 'lib/gitlab/analytics/cycle_analytics/average.rb'
+ - 'lib/gitlab/analytics/cycle_analytics/data_collector.rb'
+ - 'lib/gitlab/analytics/cycle_analytics/records_fetcher.rb'
+ - 'lib/gitlab/application_context.rb'
+ - 'lib/gitlab/auth/atlassian/identity_linker.rb'
+ - 'lib/gitlab/auth/auth_finders.rb'
+ - 'lib/gitlab/auth/ip_rate_limiter.rb'
+ - 'lib/gitlab/auth/key_status_checker.rb'
+ - 'lib/gitlab/auth/otp/strategies/forti_token_cloud.rb'
+ - 'lib/gitlab/auth/request_authenticator.rb'
+ - 'lib/gitlab/background_migration/legacy_upload_mover.rb'
+ - 'lib/gitlab/bare_repository_import/repository.rb'
+ - 'lib/gitlab/blob_helper.rb'
+ - 'lib/gitlab/cache/ci/project_pipeline_status.rb'
+ - 'lib/gitlab/chat/command.rb'
+ - 'lib/gitlab/checks/changes_access.rb'
+ - 'lib/gitlab/checks/diff_check.rb'
+ - 'lib/gitlab/ci/artifacts/metrics.rb'
+ - 'lib/gitlab/ci/build/auto_retry.rb'
+ - 'lib/gitlab/ci/build/cache.rb'
+ - 'lib/gitlab/ci/build/context/base.rb'
+ - 'lib/gitlab/ci/build/context/build.rb'
+ - 'lib/gitlab/ci/build/context/global.rb'
+ - 'lib/gitlab/ci/build/prerequisite/kubernetes_namespace.rb'
+ - 'lib/gitlab/ci/build/rules/rule/clause/changes.rb'
+ - 'lib/gitlab/ci/config/entry/product/matrix.rb'
+ - 'lib/gitlab/ci/config/entry/root.rb'
+ - 'lib/gitlab/ci/config/extendable/entry.rb'
+ - 'lib/gitlab/ci/config/external/context.rb'
+ - 'lib/gitlab/ci/config/external/file/artifact.rb'
+ - 'lib/gitlab/ci/config/external/file/base.rb'
+ - 'lib/gitlab/ci/config/external/file/local.rb'
+ - 'lib/gitlab/ci/config/external/file/project.rb'
+ - 'lib/gitlab/ci/config/external/file/remote.rb'
+ - 'lib/gitlab/ci/config/external/file/template.rb'
+ - 'lib/gitlab/ci/config/normalizer.rb'
+ - 'lib/gitlab/ci/config/normalizer/factory.rb'
+ - 'lib/gitlab/ci/pipeline/chain/command.rb'
+ - 'lib/gitlab/ci/pipeline/chain/config/content.rb'
+ - 'lib/gitlab/ci/pipeline/chain/create.rb'
+ - 'lib/gitlab/ci/pipeline/chain/evaluate_workflow_rules.rb'
+ - 'lib/gitlab/ci/pipeline/chain/limit/active_jobs.rb'
+ - 'lib/gitlab/ci/pipeline/chain/limit/rate_limit.rb'
+ - 'lib/gitlab/ci/pipeline/chain/seed.rb'
+ - 'lib/gitlab/ci/pipeline/expression/lexer.rb'
+ - 'lib/gitlab/ci/pipeline/logger.rb'
+ - 'lib/gitlab/ci/pipeline/quota/deployments.rb'
+ - 'lib/gitlab/ci/pipeline/seed/build.rb'
+ - 'lib/gitlab/ci/pipeline/seed/pipeline.rb'
+ - 'lib/gitlab/ci/pipeline/seed/processable/resource_group.rb'
+ - 'lib/gitlab/ci/pipeline/seed/stage.rb'
+ - 'lib/gitlab/ci/project_config/auto_devops.rb'
+ - 'lib/gitlab/ci/project_config/external_project.rb'
+ - 'lib/gitlab/ci/project_config/parameter.rb'
+ - 'lib/gitlab/ci/project_config/remote.rb'
+ - 'lib/gitlab/ci/project_config/repository.rb'
+ - 'lib/gitlab/ci/project_config/source.rb'
+ - 'lib/gitlab/ci/reports/accessibility_reports_comparer.rb'
+ - 'lib/gitlab/ci/reports/codequality_reports_comparer.rb'
+ - 'lib/gitlab/ci/reports/security/locations/base.rb'
+ - 'lib/gitlab/ci/reports/security/vulnerability_reports_comparer.rb'
+ - 'lib/gitlab/ci/reports/test_reports_comparer.rb'
+ - 'lib/gitlab/ci/reports/test_suite_comparer.rb'
+ - 'lib/gitlab/ci/reports/test_suite_summary.rb'
+ - 'lib/gitlab/ci/tags/bulk_insert.rb'
+ - 'lib/gitlab/ci/trace.rb'
+ - 'lib/gitlab/ci/trace/archive.rb'
+ - 'lib/gitlab/ci/trace/checksum.rb'
+ - 'lib/gitlab/ci/trace/remote_checksum.rb'
+ - 'lib/gitlab/ci/variables/builder.rb'
+ - 'lib/gitlab/ci/variables/builder/group.rb'
+ - 'lib/gitlab/ci/variables/builder/release.rb'
+ - 'lib/gitlab/ci/variables/collection/item.rb'
+ - 'lib/gitlab/ci/variables/collection/sort.rb'
+ - 'lib/gitlab/cleanup/orphan_job_artifact_files.rb'
+ - 'lib/gitlab/cleanup/orphan_job_artifact_files_batch.rb'
+ - 'lib/gitlab/code_navigation_path.rb'
+ - 'lib/gitlab/config/entry/composable_array.rb'
+ - 'lib/gitlab/config/loader/yaml.rb'
+ - 'lib/gitlab/conflict/file.rb'
+ - 'lib/gitlab/database/background_migration/health_status/indicators/write_ahead_log.rb'
+ - 'lib/gitlab/database/bulk_update.rb'
+ - 'lib/gitlab/database/load_balancing/srv_resolver.rb'
+ - 'lib/gitlab/database/metrics.rb'
+ - 'lib/gitlab/database/postgres_index.rb'
+ - 'lib/gitlab/diff/char_diff.rb'
+ - 'lib/gitlab/diff/file.rb'
+ - 'lib/gitlab/diff/file_collection/base.rb'
+ - 'lib/gitlab/diff/file_collection/merge_request_diff_base.rb'
+ - 'lib/gitlab/diff/file_collection/merge_request_diff_batch.rb'
+ - 'lib/gitlab/diff/highlight_cache.rb'
+ - 'lib/gitlab/diff/lines_unfolder.rb'
+ - 'lib/gitlab/diff/rendered/notebook/diff_file.rb'
+ - 'lib/gitlab/diff/stats_cache.rb'
+ - 'lib/gitlab/diff/suggestion.rb'
+ - 'lib/gitlab/discussions_diff/file_collection.rb'
+ - 'lib/gitlab/email/handler/service_desk_handler.rb'
+ - 'lib/gitlab/email/receiver.rb'
+ - 'lib/gitlab/external_authorization/response.rb'
+ - 'lib/gitlab/gfm/reference_rewriter.rb'
+ - 'lib/gitlab/gfm/uploads_rewriter.rb'
+ - 'lib/gitlab/git/commit.rb'
+ - 'lib/gitlab/git/diff_stats_collection.rb'
+ - 'lib/gitlab/git/push.rb'
+ - 'lib/gitlab/git/repository.rb'
+ - 'lib/gitlab/git/wiki_page_version.rb'
+ - 'lib/gitlab/git_access.rb'
+ - 'lib/gitlab/git_access_project.rb'
+ - 'lib/gitlab/gitaly_client/with_feature_flag_actors.rb'
+ - 'lib/gitlab/github_import/client.rb'
+ - 'lib/gitlab/github_import/importer/repository_importer.rb'
+ - 'lib/gitlab/github_import/representation/diff_note.rb'
+ - 'lib/gitlab/github_import/representation/diff_notes/suggestion_formatter.rb'
+ - 'lib/gitlab/gl_repository/identifier.rb'
+ - 'lib/gitlab/gpg/commit.rb'
+ - 'lib/gitlab/graphql/lazy.rb'
+ - 'lib/gitlab/graphql/pagination/keyset/connection.rb'
+ - 'lib/gitlab/import_export/base/relation_factory.rb'
+ - 'lib/gitlab/import_export/base/relation_object_saver.rb'
+ - 'lib/gitlab/import_export/decompressed_archive_size_validator.rb'
+ - 'lib/gitlab/import_export/fast_hash_serializer.rb'
+ - 'lib/gitlab/import_export/group/legacy_tree_restorer.rb'
+ - 'lib/gitlab/import_export/group/tree_restorer.rb'
+ - 'lib/gitlab/import_export/importer.rb'
+ - 'lib/gitlab/import_export/json/legacy_reader.rb'
+ - 'lib/gitlab/import_export/lfs_restorer.rb'
+ - 'lib/gitlab/import_export/project/sample/date_calculator.rb'
+ - 'lib/gitlab/import_export/project/tree_restorer.rb'
+ - 'lib/gitlab/inactive_projects_deletion_warning_tracker.rb'
+ - 'lib/gitlab/instrumentation/redis_base.rb'
+ - 'lib/gitlab/instrumentation/redis_payload.rb'
+ - 'lib/gitlab/issuable_metadata.rb'
+ - 'lib/gitlab/jwt_authenticatable.rb'
+ - 'lib/gitlab/kubernetes/deployment.rb'
+ - 'lib/gitlab/kubernetes/ingress.rb'
+ - 'lib/gitlab/kubernetes/rollout_instances.rb'
+ - 'lib/gitlab/lets_encrypt/client.rb'
+ - 'lib/gitlab/metrics/dashboard/stages/grafana_formatter.rb'
+ - 'lib/gitlab/metrics/dashboard/url.rb'
+ - 'lib/gitlab/metrics/prometheus.rb'
+ - 'lib/gitlab/pages/cache_control.rb'
+ - 'lib/gitlab/prometheus_client.rb'
+ - 'lib/gitlab/rack_attack/request.rb'
+ - 'lib/gitlab/redis/multi_store.rb'
+ - 'lib/gitlab/relative_positioning/ending_at.rb'
+ - 'lib/gitlab/relative_positioning/item_context.rb'
+ - 'lib/gitlab/relative_positioning/starting_from.rb'
+ - 'lib/gitlab/request_context.rb'
+ - 'lib/gitlab/search/found_blob.rb'
+ - 'lib/gitlab/serverless/service.rb'
+ - 'lib/gitlab/sidekiq_middleware/duplicate_jobs/strategies/deduplicates_when_scheduling.rb'
+ - 'lib/gitlab/sidekiq_queue.rb'
+ - 'lib/gitlab/signed_commit.rb'
+ - 'lib/gitlab/ssh/signature.rb'
+ - 'lib/gitlab/suggestions/file_suggestion.rb'
+ - 'lib/gitlab/task_helpers.rb'
+ - 'lib/gitlab/template/gitlab_ci_yml_template.rb'
+ - 'lib/gitlab/tracking/destinations/snowplow_micro.rb'
+ - 'lib/gitlab/usage_data.rb'
+ - 'lib/gitlab/web_hooks/rate_limiter.rb'
+ - 'lib/gitlab/web_ide/config/entry/terminal.rb'
+ - 'lib/gitlab/webpack/graphql_known_operations.rb'
+ - 'lib/gitlab/wiki_pages/front_matter_parser.rb'
+ - 'lib/gitlab/x509/signature.rb'
+ - 'lib/gitlab/x509/tag.rb'
+ - 'lib/grafana/time_window.rb'
+ - 'lib/object_storage/direct_upload.rb'
+ - 'lib/safe_zip/extract_params.rb'
+ - 'lib/sidebars/groups/menus/issues_menu.rb'
+ - 'lib/sidebars/groups/menus/merge_requests_menu.rb'
+ - 'lib/sidebars/projects/menus/analytics_menu.rb'
+ - 'lib/sidebars/projects/menus/issues_menu.rb'
+ - 'lib/sidebars/projects/menus/learn_gitlab_menu.rb'
+ - 'lib/unnested_in_filters/rewriter.rb'
+ - 'tooling/graphql/docs/helper.rb'
diff --git a/app/assets/javascripts/projects/new/constants.js b/app/assets/javascripts/projects/new/constants.js
index e52a84dc07e..7b6b2cfc7ca 100644
--- a/app/assets/javascripts/projects/new/constants.js
+++ b/app/assets/javascripts/projects/new/constants.js
@@ -12,6 +12,8 @@ export const DEPLOYMENT_TARGET_SELECTIONS = [
s__('DeploymentTarget|Registry (package or container)'),
s__('DeploymentTarget|Infrastructure provider (Terraform, Cloudformation, and so on)'),
s__('DeploymentTarget|Serverless backend (Lambda, Cloud functions)'),
+ s__('DeploymentTarget|Edge Computing (e.g. Cloudflare Workers)'),
+ s__('DeploymentTarget|Web Deployment Platform (Netlify, Vercel, Gatsby)'),
s__('DeploymentTarget|GitLab Pages'),
s__('DeploymentTarget|Other hosting service'),
s__('DeploymentTarget|No deployment planned'),
diff --git a/app/helpers/labels_helper.rb b/app/helpers/labels_helper.rb
index 0123eb68c9a..8c069bc828b 100644
--- a/app/helpers/labels_helper.rb
+++ b/app/helpers/labels_helper.rb
@@ -159,7 +159,7 @@ module LabelsHelper
end
def label_subscription_toggle_button_text(label, project = nil)
- label.subscribed?(current_user, project) ? 'Unsubscribe' : 'Subscribe'
+ label.subscribed?(current_user, project) ? _('Unsubscribe') : _('Subscribe')
end
def create_label_title(subject)
@@ -219,8 +219,8 @@ module LabelsHelper
}.merge(opts)
end
- def issuable_types
- ['issues', 'merge requests']
+ def labels_function_introduction
+ _('Labels can be applied to issues and merge requests. Group labels are available for any project within the group.')
end
def show_labels_full_path?(project, group)
diff --git a/app/models/issue.rb b/app/models/issue.rb
index fc083002c41..bf8e714f460 100644
--- a/app/models/issue.rb
+++ b/app/models/issue.rb
@@ -91,7 +91,7 @@ class Issue < ApplicationRecord
has_one :incident_management_issuable_escalation_status, class_name: 'IncidentManagement::IssuableEscalationStatus'
has_and_belongs_to_many :self_managed_prometheus_alert_events, join_table: :issues_self_managed_prometheus_alert_events # rubocop: disable Rails/HasAndBelongsToMany
has_and_belongs_to_many :prometheus_alert_events, join_table: :issues_prometheus_alert_events # rubocop: disable Rails/HasAndBelongsToMany
- has_many :alert_management_alerts, class_name: 'AlertManagement::Alert', inverse_of: :issue
+ has_many :alert_management_alerts, class_name: 'AlertManagement::Alert', inverse_of: :issue, validate: false
has_many :prometheus_alerts, through: :prometheus_alert_events
has_many :issue_customer_relations_contacts, class_name: 'CustomerRelations::IssueContact', inverse_of: :issue
has_many :customer_relations_contacts, through: :issue_customer_relations_contacts, source: :contact, class_name: 'CustomerRelations::Contact', inverse_of: :issues
diff --git a/app/services/incident_management/incidents/create_service.rb b/app/services/incident_management/incidents/create_service.rb
index f44842650b7..49019278871 100644
--- a/app/services/incident_management/incidents/create_service.rb
+++ b/app/services/incident_management/incidents/create_service.rb
@@ -23,7 +23,7 @@ module IncidentManagement
description: description,
issue_type: ISSUE_TYPE,
severity: severity,
- alert_management_alert: alert
+ alert_management_alerts: [alert].compact
},
spam_params: nil
).execute
diff --git a/app/services/issues/close_service.rb b/app/services/issues/close_service.rb
index da888386e0a..9f7da012c5c 100644
--- a/app/services/issues/close_service.rb
+++ b/app/services/issues/close_service.rb
@@ -56,7 +56,7 @@ module Issues
end
def perform_incident_management_actions(issue)
- resolve_alert(issue)
+ resolve_alerts(issue)
resolve_incident(issue)
end
@@ -71,10 +71,15 @@ module Issues
SystemNoteService.change_status(issue, issue.project, current_user, issue.state, current_commit)
end
- def resolve_alert(issue)
- return unless alert = issue.alert_management_alert
+ def resolve_alerts(issue)
+ issue.alert_management_alerts.each { |alert| resolve_alert(alert) }
+ end
+
+ def resolve_alert(alert)
return if alert.resolved?
+ issue = alert.issue
+
if alert.resolve
SystemNoteService.change_alert_status(alert, current_user, " by closing incident #{issue.to_reference(project)}")
else
diff --git a/app/views/groups/labels/index.html.haml b/app/views/groups/labels/index.html.haml
index 8187dda5471..a03c406acc6 100644
--- a/app/views/groups/labels/index.html.haml
+++ b/app/views/groups/labels/index.html.haml
@@ -11,7 +11,7 @@
.labels-container.gl-mt-5
- if @labels.any?
.text-muted.gl-mb-5
- = _('Labels can be applied to %{features}. Group labels are available for any project within the group.') % { features: issuable_types.to_sentence }
+ = labels_function_introduction
.other-labels
%h4= _('Labels')
%ul.manage-labels-list.js-other-labels
diff --git a/config/initializers/diagnostic_reports.rb b/config/initializers/diagnostic_reports.rb
index 47266f99f2d..7e96c266b23 100644
--- a/config/initializers/diagnostic_reports.rb
+++ b/config/initializers/diagnostic_reports.rb
@@ -7,3 +7,7 @@ return unless Gitlab::Runtime.puma?
Gitlab::Cluster::LifecycleEvents.on_worker_start do
Gitlab::Memory::ReportsDaemon.instance.start
end
+
+Gitlab::Cluster::LifecycleEvents.on_worker_stop do
+ Gitlab::Memory::Reports::HeapDump.write_conditionally
+end
diff --git a/db/structure.sql b/db/structure.sql
index 504a7522feb..26d55c94b8e 100644
--- a/db/structure.sql
+++ b/db/structure.sql
@@ -30332,7 +30332,7 @@ CREATE UNIQUE INDEX index_project_repository_states_on_project_id ON project_rep
CREATE INDEX index_project_repository_storage_moves_on_project_id ON project_repository_storage_moves USING btree (project_id);
-CREATE INDEX index_project_settings_on_legacy_os_license_project_id ON project_settings USING btree (legacy_open_source_license_available, project_id) WHERE (legacy_open_source_license_available = true);
+CREATE INDEX index_project_settings_on_legacy_os_license_project_id ON project_settings USING btree (project_id) WHERE (legacy_open_source_license_available = true);
CREATE INDEX index_project_settings_on_project_id_partially ON project_settings USING btree (project_id) WHERE (has_vulnerabilities IS TRUE);
diff --git a/doc/administration/audit_events.md b/doc/administration/audit_events.md
index 0aa0d163972..d10c1616eaf 100644
--- a/doc/administration/audit_events.md
+++ b/doc/administration/audit_events.md
@@ -21,17 +21,46 @@ NOTE:
You can't configure a retention policy for audit events, but epic
[7917](https://gitlab.com/groups/gitlab-org/-/epics/7917) proposes to change this.
-## List of events
+## View audit events
-There are two kinds of events logged:
+Depending on the events you want to view, at a minimum you must have:
-- Events scoped to the group or project, used by group and project managers
- to look up who made a change.
-- Instance events scoped to the whole GitLab instance, used by your Compliance team to
- perform formal audits.
+- For group audit events of all users in the group, the Owner role for the group.
+- For project audit events of all users in the project, the Maintainer role for the project.
+- For group and project audit events based on your own actions, the Developer role for the group or project.
+- [Auditor users](auditor_users.md) can see group and project events for all users.
-NOTE:
-Some events are recorded and available only as [streaming audit events](audit_event_streaming.md).
+You can view audit events scoped to a group or project.
+
+To view a group's audit events:
+
+1. Go to the group.
+1. On the left sidebar, select **Security & Compliance > Audit Events**.
+
+Group events do not include project audit events. Group events can also be accessed using the
+[Group Audit Events API](../api/audit_events.md#group-audit-events). Group event queries are limited to a maximum of 30
+days.
+
+To view a project's audit events:
+
+1. Go to the project.
+1. On the left sidebar, select **Security & Compliance > Audit Events**.
+
+Project events can also be accessed using the [Project Audit Events API](../api/audit_events.md#project-audit-events).
+Project event queries are limited to a maximum of 30 days.
+
+### View instance audit events **(PREMIUM SELF)**
+
+You can view audit events from user actions across an entire GitLab instance.
+
+To view instance audit events:
+
+1. On the top bar, select **Main menu > Admin**.
+1. On the left sidebar, select **Monitoring > Audit Events**.
+
+## List of events
+
+You can view different events depending on the version of GitLab you have.
### Impersonation data
@@ -51,19 +80,7 @@ When a user is being [impersonated](../user/admin_area/index.md#user-impersonati
### Group events
-A user with:
-
-- Owner role (or above) can retrieve group audit events of all users.
-- Developer or Maintainer role is limited to group audit events based on their individual actions.
-
-Group events do not include project audit events.
-
-To view a group's audit events:
-
-1. Go to the group.
-1. On the left sidebar, select **Security & Compliance > Audit Events**.
-
-From there, you can see the following actions:
+The following actions on groups generate group audit events:
- Group name or path changed.
- Group repository size limit changed.
@@ -111,19 +128,9 @@ From there, you can see the following actions:
- Changes to streaming audit destination custom HTTP headers. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/366350) in GitLab 15.3.
- Group had a security policy project linked, changed, or unlinked. ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/377877) in GitLab 15.6)
-Group events can also be accessed via the [Group Audit Events API](../api/audit_events.md#group-audit-events)
-
### Project events
-A user with a Maintainer role (or above) can retrieve project audit events of all users.
-A user with a Developer role is limited to project audit events based on their individual actions.
-
-To view a project's audit events:
-
-1. Go to the project.
-1. On the left sidebar, select **Security & Compliance > Audit Events**.
-
-From there, you can see the following actions:
+The following actions on projects generate project audit events:
- Added or removed deploy keys
- Project created, deleted, renamed, moved (transferred), changed path
@@ -182,24 +189,9 @@ From there, you can see the following actions:
- Project was scheduled for deletion due to inactivity ([introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/85689) in GitLab 15.0)
- Project had a security policy project linked, changed, or unlinked ([introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/377877) in GitLab 15.6)
-Project events can also be accessed via the [Project Audit Events API](../api/audit_events.md#project-audit-events).
-
-Project event queries are limited to a maximum of 30 days.
-
### Instance events **(PREMIUM SELF)**
-Server-wide audit events introduce the ability to observe user actions across
-the entire instance of your GitLab server, making it easy to understand who
-changed what and when for audit purposes.
-
-Instance events do not include group or project audit events.
-
-To view the server-wide audit events:
-
-1. On the top bar, select **Main menu > Admin**.
-1. On the left sidebar, select **Monitoring > Audit Events**.
-
-The following user actions are recorded:
+The following user actions on a GitLab instance generate instance audit events:
- Sign-in events and the authentication type (such as standard, LDAP, or OmniAuth)
- Failed sign-ins
diff --git a/doc/architecture/blueprints/ci_pipeline_components/index.md b/doc/architecture/blueprints/ci_pipeline_components/index.md
index e8fbc15a376..f98a82dfe5b 100644
--- a/doc/architecture/blueprints/ci_pipeline_components/index.md
+++ b/doc/architecture/blueprints/ci_pipeline_components/index.md
@@ -3,7 +3,7 @@ status: proposed
creation-date: "2022-09-14"
authors: [ "@fabio", "@grzesiek" ]
coach: "@kamil"
-approvers: [ "@dov" ]
+approvers: [ "@dhershkovitch" ]
owning-stage: "~devops::verify"
participating-stages: []
---
diff --git a/doc/development/caching.md b/doc/development/caching.md
index 36fbfc7010e..4c91e8eba6e 100644
--- a/doc/development/caching.md
+++ b/doc/development/caching.md
@@ -166,7 +166,7 @@ Is the cache being added "worthy"? This can be hard to measure, but you can cons
- Calling the same method multiple times but only calculating the value once.
- Stored in Ruby memory.
- `@article ||= Article.find(params[:id])`
- - `strong_memoize { Article.find(params[:id]) }`
+ - `strong_memoize_attr :method_name`
1. Request caching:
- Return the same value for a key for the duration of a web request.
- `Gitlab::SafeRequestStore.fetch`
@@ -252,7 +252,7 @@ All the time!
### When to use method caching
-- Using instance variables, or [strong_memoize](utilities.md#strongmemoize) is something we all tend to do anyway.
+- Use instance variables, or [`StrongMemoize`](utilities.md#strongmemoize).
- Useful when the same value is needed multiple times in a request.
- Can be used to prevent multiple cache calls for the same key.
- Can cause issues with ActiveRecord objects where a value doesn't change until you call
diff --git a/doc/development/secure_coding_guidelines.md b/doc/development/secure_coding_guidelines.md
index e99926663dd..0dc950cbc4c 100644
--- a/doc/development/secure_coding_guidelines.md
+++ b/doc/development/secure_coding_guidelines.md
@@ -718,13 +718,12 @@ There are some cases where `users` passed in the code is actually referring to a
```ruby
def find_user_from_sources
- strong_memoize(:find_user_from_sources) do
- deploy_token_from_request ||
- find_user_from_bearer_token ||
- find_user_from_job_token ||
- user_from_warden
- end
+ deploy_token_from_request ||
+ find_user_from_bearer_token ||
+ find_user_from_job_token ||
+ user_from_warden
end
+ strong_memoize_attr :find_user_from_sources
```
### Past Vulnerable Code
diff --git a/doc/development/utilities.md b/doc/development/utilities.md
index 551834670b3..a7f0500fd71 100644
--- a/doc/development/utilities.md
+++ b/doc/development/utilities.md
@@ -181,20 +181,6 @@ Refer to [`strong_memoize.rb`](https://gitlab.com/gitlab-org/gitlab/-/blob/maste
include Gitlab::Utils::StrongMemoize
def result
- strong_memoize(:result) do
- search
- end
- end
- end
- ```
-
- Alternatively, use the `strong_memoize_attr` helper to memoize the method for you:
-
- ```ruby
- class Find
- include Gitlab::Utils::StrongMemoize
-
- def result
search
end
strong_memoize_attr :result
diff --git a/doc/update/index.md b/doc/update/index.md
index e810c63a7ea..31df17c4138 100644
--- a/doc/update/index.md
+++ b/doc/update/index.md
@@ -565,6 +565,8 @@ and [Helm Chart deployments](https://docs.gitlab.com/charts/). They come with ap
than `<custom_hooks_dir>/<hook_name>`.
- [Incorrect deletion of object storage files on Geo secondary sites](https://gitlab.com/gitlab-org/gitlab/-/issues/371397) can occur in certain situations. See [Geo: Incorrect object storage LFS file deletion on secondary site issue in GitLab 15.0.0 to 15.3.2](#geo-incorrect-object-storage-lfs-file-deletion-on-secondary-sites-in-gitlab-1500-to-1532).
- The `FF_GITLAB_REGISTRY_HELPER_IMAGE` [feature flag](../administration/feature_flags.md#enable-or-disable-the-feature) is removed and helper images are always pulled from GitLab Registry.
+- The `AES256-GCM-SHA384` SSL cipher is no longer allowed by NGINX.
+ See how you can [add the cipher back](https://docs.gitlab.com/omnibus/update/gitlab_15_changes.html#aes256-gcm-sha384-ssl-cipher-no-longer-allowed-by-default-by-nginx) to the allow list.
### 14.10.0
diff --git a/lib/gitlab/memory/reports/heap_dump.rb b/lib/gitlab/memory/reports/heap_dump.rb
new file mode 100644
index 00000000000..b81464ed5cf
--- /dev/null
+++ b/lib/gitlab/memory/reports/heap_dump.rb
@@ -0,0 +1,45 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Memory
+ module Reports
+ class HeapDump
+ class << self
+ def enqueue!
+ log_event('enqueue')
+ @write_heap_dump = true
+ end
+
+ # This is a no-op currently and will be implemented at a later time in
+ # https://gitlab.com/gitlab-org/gitlab/-/issues/370077
+ def write_conditionally
+ return false unless enqueued?
+
+ log_event('write')
+
+ true
+ end
+
+ private
+
+ def enqueued?
+ !!@write_heap_dump
+ end
+
+ def log_event(message)
+ Gitlab::AppLogger.info(
+ message: message,
+ pid: $$,
+ worker_id: worker_id,
+ perf_report: 'heap_dump'
+ )
+ end
+
+ def worker_id
+ ::Prometheus::PidProvider.worker_id
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/memory/watchdog.rb b/lib/gitlab/memory/watchdog.rb
index 19dfc640b5d..435b416e7e9 100644
--- a/lib/gitlab/memory/watchdog.rb
+++ b/lib/gitlab/memory/watchdog.rb
@@ -55,16 +55,8 @@ module Gitlab
end
##
- # Configuration for Watchdog, use like:
- #
- # watchdog.configure do |config|
- # config.handler = Gitlab::Memory::Watchdog::TermProcessHandler
- # config.sleep_time_seconds = 60
- # config.logger = Gitlab::AppLogger
- # config.monitors do |stack|
- # stack.push MyMonitorClass, args*, max_strikes:, kwargs**, &block
- # end
- # end
+ # Configuration for Watchdog, see Gitlab::Memory::Watchdog::Configurator
+ # for examples.
def configure
yield @configuration
end
@@ -106,6 +98,8 @@ module Gitlab
logger.warn(all_labels)
@counter_violations_handled.increment(reason: monitor_name)
+ Gitlab::Memory::Reports::HeapDump.enqueue! if @configuration.write_heap_dumps?
+
handler.call
end
diff --git a/lib/gitlab/memory/watchdog/configuration.rb b/lib/gitlab/memory/watchdog/configuration.rb
index 793f75adf59..4bad9475531 100644
--- a/lib/gitlab/memory/watchdog/configuration.rb
+++ b/lib/gitlab/memory/watchdog/configuration.rb
@@ -39,7 +39,7 @@ module Gitlab
DEFAULT_SLEEP_TIME_SECONDS = 60
- attr_writer :logger, :handler, :sleep_time_seconds
+ attr_writer :logger, :handler, :sleep_time_seconds, :write_heap_dumps
def monitors
@monitor_stack ||= MonitorStack.new
@@ -59,6 +59,10 @@ module Gitlab
def sleep_time_seconds
@sleep_time_seconds ||= DEFAULT_SLEEP_TIME_SECONDS
end
+
+ def write_heap_dumps?
+ !!@write_heap_dumps
+ end
end
end
end
diff --git a/lib/gitlab/memory/watchdog/configurator.rb b/lib/gitlab/memory/watchdog/configurator.rb
index 6d6f97dc8ba..da3733731a7 100644
--- a/lib/gitlab/memory/watchdog/configurator.rb
+++ b/lib/gitlab/memory/watchdog/configurator.rb
@@ -7,26 +7,32 @@ module Gitlab
class << self
def configure_for_puma
lambda do |config|
- sleep_time_seconds = ENV.fetch('GITLAB_MEMWD_SLEEP_TIME_SEC', 60).to_i
config.logger = Gitlab::AppLogger
config.handler = Gitlab::Memory::Watchdog::PumaHandler.new
- config.sleep_time_seconds = sleep_time_seconds
+ config.write_heap_dumps = write_heap_dumps?
+ config.sleep_time_seconds = ENV.fetch('GITLAB_MEMWD_SLEEP_TIME_SEC', 60).to_i
config.monitors(&configure_monitors_for_puma)
end
end
def configure_for_sidekiq
lambda do |config|
- sleep_time_seconds = [ENV.fetch('SIDEKIQ_MEMORY_KILLER_CHECK_INTERVAL', 3).to_i, 2].max
config.logger = Sidekiq.logger
config.handler = Gitlab::Memory::Watchdog::TermProcessHandler.new
- config.sleep_time_seconds = sleep_time_seconds
+ config.write_heap_dumps = write_heap_dumps?
+ config.sleep_time_seconds = [
+ ENV.fetch('SIDEKIQ_MEMORY_KILLER_CHECK_INTERVAL', 3).to_i, 2
+ ].max
config.monitors(&configure_monitors_for_sidekiq)
end
end
private
+ def write_heap_dumps?
+ Gitlab::Utils.to_boolean(ENV['GITLAB_MEMWD_DUMP_HEAP'], default: false)
+ end
+
def configure_monitors_for_puma
lambda do |stack|
max_strikes = ENV.fetch('GITLAB_MEMWD_MAX_STRIKES', 5).to_i
diff --git a/lib/gitlab/utils/strong_memoize.rb b/lib/gitlab/utils/strong_memoize.rb
index 6456ad08924..306180ded6a 100644
--- a/lib/gitlab/utils/strong_memoize.rb
+++ b/lib/gitlab/utils/strong_memoize.rb
@@ -16,16 +16,6 @@ module Gitlab
# include Gitlab::Utils::StrongMemoize
#
# def trigger_from_token
- # strong_memoize(:trigger) do
- # Ci::Trigger.find_by_token(params[:token].to_s)
- # end
- # end
- #
- # Or like:
- #
- # include Gitlab::Utils::StrongMemoize
- #
- # def trigger_from_token
# Ci::Trigger.find_by_token(params[:token].to_s)
# end
# strong_memoize_attr :trigger_from_token
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 5d7d8c15904..4e76c16d295 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -13591,6 +13591,9 @@ msgstr ""
msgid "DeploymentApproval|Rejected by you %{time}"
msgstr ""
+msgid "DeploymentTarget|Edge Computing (e.g. Cloudflare Workers)"
+msgstr ""
+
msgid "DeploymentTarget|GitLab Pages"
msgstr ""
@@ -13627,6 +13630,9 @@ msgstr ""
msgid "DeploymentTarget|Virtual machine (for example, EC2)"
msgstr ""
+msgid "DeploymentTarget|Web Deployment Platform (Netlify, Vercel, Gatsby)"
+msgstr ""
+
msgid "Deployments"
msgstr ""
@@ -23815,15 +23821,18 @@ msgstr ""
msgid "Labels"
msgstr ""
-msgid "Labels can be applied to %{features}. Group labels are available for any project within the group."
+msgid "Labels can be applied to issues and merge requests to categorize them."
msgstr ""
-msgid "Labels can be applied to issues and merge requests to categorize them."
+msgid "Labels can be applied to issues and merge requests. Group labels are available for any project within the group."
msgstr ""
msgid "Labels can be applied to issues and merge requests. Star a label to make it a priority label."
msgstr ""
+msgid "Labels can be applied to issues, merge requests, and epics. Group labels are available for any project within the group."
+msgstr ""
+
msgid "Labels with no issues in this iteration:"
msgstr ""
diff --git a/qa/qa/specs/features/browser_ui/3_create/pages/new_static_page_spec.rb b/qa/qa/specs/features/browser_ui/3_create/pages/new_static_page_spec.rb
index b344e5f7b1f..449bffe61e0 100644
--- a/qa/qa/specs/features/browser_ui/3_create/pages/new_static_page_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/pages/new_static_page_spec.rb
@@ -1,7 +1,15 @@
# frozen_string_literal: true
module QA
- RSpec.describe 'Create', :gitlab_pages, :orchestrated, except: { job: 'review-qa-*' } do
+ RSpec.describe 'Create',
+ :gitlab_pages,
+ :orchestrated,
+ except: { job: 'review-qa-*' },
+ quarantine: {
+ issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/383215',
+ type: :test_environment,
+ only: { subdomain: 'staging-ref' }
+ } do
# TODO: Convert back to :smoke once proved to be stable. Related issue: https://gitlab.com/gitlab-org/gitlab/-/issues/300906
describe 'Pages', product_group: :editor do
let!(:project) do
diff --git a/rubocop/cop/gitlab/strong_memoize_attr.rb b/rubocop/cop/gitlab/strong_memoize_attr.rb
new file mode 100644
index 00000000000..2da7f71b920
--- /dev/null
+++ b/rubocop/cop/gitlab/strong_memoize_attr.rb
@@ -0,0 +1,39 @@
+# frozen_string_literal: true
+
+module RuboCop
+ module Cop
+ module Gitlab
+ # Cop that disallows functions that contain only a call to `strong_memoize()`, in favor
+ # of `strong_memoize_attr()`.
+ class StrongMemoizeAttr < RuboCop::Cop::Base
+ extend RuboCop::Cop::AutoCorrector
+
+ MSG = 'Use `strong_memoize_attr`, instead of using `strong_memoize` directly'
+
+ def_node_matcher :strong_memoize?, <<~PATTERN
+ (def $_ _
+ (block
+ $(send nil? :strong_memoize
+ (sym $_)
+ )
+ (args)
+ $_
+ )
+ )
+ PATTERN
+
+ def on_def(node)
+ method_name, send_node, attr_name, body = strong_memoize?(node)
+ return unless method_name
+
+ add_offense(send_node) do |corrector|
+ attr_suffix = ", :#{attr_name}" if attr_name != method_name
+
+ corrector.insert_after(node, "\n#{indent(node)}strong_memoize_attr :#{method_name}#{attr_suffix}")
+ corrector.replace(node.body, body.source)
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/spec/controllers/projects_controller_spec.rb b/spec/controllers/projects_controller_spec.rb
index 446e5e38865..f80feed6c33 100644
--- a/spec/controllers/projects_controller_spec.rb
+++ b/spec/controllers/projects_controller_spec.rb
@@ -702,16 +702,12 @@ RSpec.describe ProjectsController do
skip unless project.hashed_storage?(:repository)
hashed_storage_path = ::Storage::Hashed.new(project).disk_path
- original_repository_path = Gitlab::GitalyClient::StorageSettings.allow_disk_access do
- project.repository.path
- end
+ original_repository_path = project.repository.relative_path
expect { update_project path: 'renamed_path' }.to change { project.reload.path }
expect(project.path).to include 'renamed_path'
- assign_repository_path = Gitlab::GitalyClient::StorageSettings.allow_disk_access do
- assigns(:repository).path
- end
+ assign_repository_path = assigns(:repository).relative_path
expect(original_repository_path).to include(hashed_storage_path)
expect(assign_repository_path).to include(hashed_storage_path)
@@ -721,16 +717,12 @@ RSpec.describe ProjectsController do
skip if project.hashed_storage?(:repository)
hashed_storage_path = Storage::Hashed.new(project).disk_path
- original_repository_path = Gitlab::GitalyClient::StorageSettings.allow_disk_access do
- project.repository.path
- end
+ original_repository_path = project.repository.relative_path
expect { update_project path: 'renamed_path' }.to change { project.reload.path }
expect(project.path).to include 'renamed_path'
- assign_repository_path = Gitlab::GitalyClient::StorageSettings.allow_disk_access do
- assigns(:repository).path
- end
+ assign_repository_path = assigns(:repository).relative_path
expect(original_repository_path).not_to include(hashed_storage_path)
expect(assign_repository_path).to include(hashed_storage_path)
diff --git a/spec/helpers/labels_helper_spec.rb b/spec/helpers/labels_helper_spec.rb
index 85420d4afda..e8e981251e3 100644
--- a/spec/helpers/labels_helper_spec.rb
+++ b/spec/helpers/labels_helper_spec.rb
@@ -321,4 +321,27 @@ RSpec.describe LabelsHelper do
expect(wrap_label_html('xss', label: xss_label, small: false)).not_to include('color:')
end
end
+
+ describe '#label_subscription_toggle_button_text' do
+ let(:label) { instance_double(Label) }
+ let(:current_user) { instance_double(User) }
+
+ subject { label_subscription_toggle_button_text(label) }
+
+ context 'when the label is subscribed' do
+ before do
+ allow(label).to receive(:subscribed?).and_return(true)
+ end
+
+ it { is_expected.to eq(_('Unsubscribe')) }
+ end
+
+ context 'when the label is not subscribed' do
+ before do
+ allow(label).to receive(:subscribed?).and_return(false)
+ end
+
+ it { is_expected.to eq(_('Subscribe')) }
+ end
+ end
end
diff --git a/spec/initializers/diagnostic_reports_spec.rb b/spec/initializers/diagnostic_reports_spec.rb
index 01b1ed9b7b5..2022076072b 100644
--- a/spec/initializers/diagnostic_reports_spec.rb
+++ b/spec/initializers/diagnostic_reports_spec.rb
@@ -10,6 +10,7 @@ RSpec.describe 'diagnostic reports' do
shared_examples 'does not modify worker startup hooks' do
it do
expect(Gitlab::Cluster::LifecycleEvents).not_to receive(:on_worker_start)
+ expect(Gitlab::Cluster::LifecycleEvents).not_to receive(:on_worker_stop)
expect(Gitlab::Memory::ReportsDaemon).not_to receive(:instance)
load_initializer
@@ -30,18 +31,22 @@ RSpec.describe 'diagnostic reports' do
it 'modifies worker startup hooks, starts Gitlab::Memory::ReportsDaemon' do
expect(Gitlab::Cluster::LifecycleEvents).to receive(:on_worker_start).and_call_original
-
+ expect(Gitlab::Cluster::LifecycleEvents).to receive(:on_worker_stop)
expect_next_instance_of(Gitlab::Memory::ReportsDaemon) do |daemon|
- expect(daemon).to receive(:start).and_call_original
+ expect(daemon).to receive(:start)
+ end
- # make sleep no-op
- allow(daemon).to receive(:sleep).and_return(nil)
+ load_initializer
+ end
- # let alive return 3 times: true, true, false
- allow(daemon).to receive(:alive).and_return(true, true, false)
- end
+ it 'writes scheduled heap dumps in on_worker_stop' do
+ expect(Gitlab::Cluster::LifecycleEvents).to receive(:on_worker_start)
+ expect(Gitlab::Cluster::LifecycleEvents).to receive(:on_worker_stop).and_call_original
+ expect(Gitlab::Memory::Reports::HeapDump).to receive(:write_conditionally)
load_initializer
+ # This is necessary because this hook normally fires during worker shutdown.
+ Gitlab::Cluster::LifecycleEvents.do_worker_stop
end
end
diff --git a/spec/lib/gitlab/memory/reports/heap_dump_spec.rb b/spec/lib/gitlab/memory/reports/heap_dump_spec.rb
new file mode 100644
index 00000000000..2532b8c5295
--- /dev/null
+++ b/spec/lib/gitlab/memory/reports/heap_dump_spec.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Memory::Reports::HeapDump do
+ describe '.write_conditionally' do
+ subject(:call) { described_class.write_conditionally }
+
+ context 'when no heap dump is enqueued' do
+ it 'does nothing and returns false' do
+ expect(call).to be(false)
+ end
+ end
+
+ context 'when a heap dump is enqueued' do
+ it 'does nothing and returns true' do
+ described_class.enqueue!
+
+ expect(call).to be(true)
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/memory/watchdog/configurator_spec.rb b/spec/lib/gitlab/memory/watchdog/configurator_spec.rb
index e6f2d57e9e6..0d3a6eab48c 100644
--- a/spec/lib/gitlab/memory/watchdog/configurator_spec.rb
+++ b/spec/lib/gitlab/memory/watchdog/configurator_spec.rb
@@ -19,6 +19,12 @@ RSpec.describe Gitlab::Memory::Watchdog::Configurator do
expect(configuration.logger).to eq(logger)
end
+ it 'does not enable writing heap dumps by default' do
+ configurator.call(configuration)
+
+ expect(configuration.write_heap_dumps?).to be(false)
+ end
+
context 'when sleep_time_seconds is not passed through the environment' do
let(:sleep_time_seconds) { sleep_time }
@@ -42,6 +48,42 @@ RSpec.describe Gitlab::Memory::Watchdog::Configurator do
expect(configuration.sleep_time_seconds).to eq(sleep_time_seconds)
end
end
+
+ context 'when GITLAB_MEMWD_DUMP_HEAP is set' do
+ before do
+ stub_env('GITLAB_MEMWD_DUMP_HEAP', env_var)
+ end
+
+ context 'with null value' do
+ let(:env_var) { nil }
+
+ it 'does not enable writing heap dumps' do
+ configurator.call(configuration)
+
+ expect(configuration.write_heap_dumps?).to be(false)
+ end
+ end
+
+ context 'with falsey value' do
+ let(:env_var) { '0' }
+
+ it 'does not enable writing heap dumps' do
+ configurator.call(configuration)
+
+ expect(configuration.write_heap_dumps?).to be(false)
+ end
+ end
+
+ context 'with truthy value' do
+ let(:env_var) { '1' }
+
+ it 'enables writing heap dumps' do
+ configurator.call(configuration)
+
+ expect(configuration.write_heap_dumps?).to be(true)
+ end
+ end
+ end
end
shared_examples 'as monitor configurator' do
diff --git a/spec/lib/gitlab/memory/watchdog_spec.rb b/spec/lib/gitlab/memory/watchdog_spec.rb
index 5d9599d6eab..8703bf8b00b 100644
--- a/spec/lib/gitlab/memory/watchdog_spec.rb
+++ b/spec/lib/gitlab/memory/watchdog_spec.rb
@@ -8,6 +8,7 @@ RSpec.describe Gitlab::Memory::Watchdog, :aggregate_failures do
let(:handler) { instance_double(described_class::NullHandler) }
let(:logger) { instance_double(::Logger) }
let(:sleep_time_seconds) { 60 }
+ let(:write_heap_dumps) { false }
let(:threshold_violated) { false }
let(:violations_counter) { instance_double(::Prometheus::Client::Counter) }
let(:violations_handled_counter) { instance_double(::Prometheus::Client::Counter) }
@@ -69,6 +70,7 @@ RSpec.describe Gitlab::Memory::Watchdog, :aggregate_failures do
config.handler = handler
config.logger = logger
config.sleep_time_seconds = sleep_time_seconds
+ config.write_heap_dumps = write_heap_dumps
config.monitors.push monitor_class, threshold_violated, payload, max_strikes: max_strikes
end
@@ -154,6 +156,16 @@ RSpec.describe Gitlab::Memory::Watchdog, :aggregate_failures do
watchdog.call
end
+
+ context 'and heap dumps are enabled' do
+ let(:write_heap_dumps) { true }
+
+ it 'does not schedule a heap dump' do
+ expect(Gitlab::Memory::Reports::HeapDump).not_to receive(:enqueue!)
+
+ watchdog.call
+ end
+ end
end
context 'when monitor exceeds the allowed number of strikes' do
@@ -186,6 +198,16 @@ RSpec.describe Gitlab::Memory::Watchdog, :aggregate_failures do
watchdog.call
end
+ context 'and heap dumps are enabled' do
+ let(:write_heap_dumps) { true }
+
+ it 'schedules a heap dump' do
+ expect(Gitlab::Memory::Reports::HeapDump).to receive(:enqueue!)
+
+ watchdog.call
+ end
+ end
+
context 'when enforce_memory_watchdog ops toggle is off' do
before do
stub_feature_flags(enforce_memory_watchdog: false)
@@ -255,6 +277,10 @@ RSpec.describe Gitlab::Memory::Watchdog, :aggregate_failures do
subject(:handler) { described_class::TermProcessHandler.new(42) }
describe '#call' do
+ before do
+ allow(Process).to receive(:kill)
+ end
+
it 'sends SIGTERM to the current process' do
expect(Process).to receive(:kill).with(:TERM, 42)
@@ -274,11 +300,12 @@ RSpec.describe Gitlab::Memory::Watchdog, :aggregate_failures do
before do
stub_const('::Puma::Cluster::WorkerHandle', puma_worker_handle_class)
+ allow(puma_worker_handle_class).to receive(:new).and_return(puma_worker_handle)
+ allow(puma_worker_handle).to receive(:term)
end
describe '#call' do
it 'invokes orderly termination via Puma API' do
- expect(puma_worker_handle_class).to receive(:new).and_return(puma_worker_handle)
expect(puma_worker_handle).to receive(:term)
expect(handler.call).to be(true)
diff --git a/spec/lib/gitlab/utils/strong_memoize_spec.rb b/spec/lib/gitlab/utils/strong_memoize_spec.rb
index 236b6d29ba7..6a09a8da58e 100644
--- a/spec/lib/gitlab/utils/strong_memoize_spec.rb
+++ b/spec/lib/gitlab/utils/strong_memoize_spec.rb
@@ -23,7 +23,7 @@ RSpec.describe Gitlab::Utils::StrongMemoize do
end
def method_name
- strong_memoize(:method_name) do
+ strong_memoize(:method_name) do # rubocop: disable Gitlab/StrongMemoizeAttr
trace << value
value
end
diff --git a/spec/models/issue_spec.rb b/spec/models/issue_spec.rb
index aea8bdaf343..a4c52714458 100644
--- a/spec/models/issue_spec.rb
+++ b/spec/models/issue_spec.rb
@@ -25,7 +25,7 @@ RSpec.describe Issue do
it { is_expected.to have_many(:design_versions) }
it { is_expected.to have_one(:sentry_issue) }
it { is_expected.to have_one(:alert_management_alert) }
- it { is_expected.to have_many(:alert_management_alerts) }
+ it { is_expected.to have_many(:alert_management_alerts).validate(false) }
it { is_expected.to have_many(:resource_milestone_events) }
it { is_expected.to have_many(:resource_state_events) }
it { is_expected.to have_and_belong_to_many(:prometheus_alert_events) }
diff --git a/spec/requests/api/graphql/project/issues_spec.rb b/spec/requests/api/graphql/project/issues_spec.rb
index 214165cb171..14ca2e439bf 100644
--- a/spec/requests/api/graphql/project/issues_spec.rb
+++ b/spec/requests/api/graphql/project/issues_spec.rb
@@ -360,7 +360,7 @@ RSpec.describe 'getting an issue list for a project' do
post_graphql(query, current_user: current_user)
alert_titles = issues_data.map { |issue| issue.dig('alertManagementAlert', 'title') }
- expected_titles = issues.map { |issue| issue.alert_management_alert&.title }
+ expected_titles = issues.map { |issue| issue.alert_management_alerts.first&.title }
expect(alert_titles).to contain_exactly(*expected_titles)
end
diff --git a/spec/requests/search_controller_spec.rb b/spec/requests/search_controller_spec.rb
index 613732c19ea..ff66023e37d 100644
--- a/spec/requests/search_controller_spec.rb
+++ b/spec/requests/search_controller_spec.rb
@@ -6,6 +6,7 @@ RSpec.describe SearchController, type: :request do
let_it_be(:user) { create(:user) }
let_it_be(:group) { create(:group) }
let_it_be(:project) { create(:project, :public, :repository, :wiki_repo, name: 'awesome project', group: group) }
+ let_it_be(:projects) { create_list(:project, 5, :public, :repository, :wiki_repo) }
before do
login_as(user)
@@ -20,9 +21,16 @@ RSpec.describe SearchController, type: :request do
create(object, *creation_traits, creation_args)
control = ActiveRecord::QueryRecorder.new(skip_cached: false) { send_search_request(params) }
- create_list(object, 3, *creation_traits, creation_args)
+ expect(response.body).to include('search-results') # Confirm there are search results to prevent false positives
+
+ projects.each do |project|
+ creation_args[:source_project] = project if creation_args.key?(:source_project)
+ creation_args[:project] = project if creation_args.key?(:project)
+ create(object, *creation_traits, creation_args)
+ end
expect { send_search_request(params) }.not_to exceed_all_query_limit(control).with_threshold(threshold)
+ expect(response.body).to include('search-results') # Confirm there are search results to prevent false positives
end
end
@@ -33,26 +41,26 @@ RSpec.describe SearchController, type: :request do
let(:object) { :issue }
let(:creation_args) { { project: project, title: 'foo' } }
let(:params) { { search: 'foo', scope: 'issues' } }
- # there are 4 additional queries run for the logged in user:
- # (1) geo_nodes, (1) users, (2) broadcast_messages
- let(:threshold) { 4 }
+ # some N+1 queries still exist
+ # each issue runs an extra query for group namespaces
+ let(:threshold) { 1 }
it_behaves_like 'an efficient database result'
end
- context 'for merge_request scope' do
+ context 'for merge_requests scope' do
let(:creation_traits) { [:unique_branches] }
let(:object) { :merge_request }
let(:creation_args) { { source_project: project, title: 'bar' } }
let(:params) { { search: 'bar', scope: 'merge_requests' } }
- # there are 4 additional queries run for the logged in user:
- # - (1) geo_nodes, (1) users, (2) broadcast_messages
+ # some N+1 queries still exist
+ # each merge request runs an extra query for project routes
let(:threshold) { 4 }
it_behaves_like 'an efficient database result'
end
- context 'for project scope' do
+ context 'for projects scope' do
let(:creation_traits) { [:public] }
let(:object) { :project }
let(:creation_args) { { name: 'project' } }
@@ -63,12 +71,67 @@ RSpec.describe SearchController, type: :request do
# - one count for open MRs
# - one count for open Issues
# there are 4 additional queries run for the logged in user:
- # (1) geo_nodes, (1) users, (2) broadcast_messages
- let(:threshold) { 13 }
+ # (1) user preferences, (1) user statuses, (1) user details, (1) users
+ let(:threshold) { 17 }
+
+ it_behaves_like 'an efficient database result'
+ end
+
+ context 'for milestones scope' do
+ let(:object) { :milestone }
+ let(:creation_args) { { project: project } }
+ let(:params) { { search: 'title', scope: 'milestones' } }
+ let(:threshold) { 0 }
+
+ it_behaves_like 'an efficient database result'
+ end
+
+ context 'for users scope' do
+ let(:object) { :user }
+ let(:creation_args) { { name: 'georgia' } }
+ let(:params) { { search: 'georgia', scope: 'users' } }
+ let(:threshold) { 0 }
it_behaves_like 'an efficient database result'
end
+ context 'for notes scope' do
+ let(:creation_traits) { [:on_commit] }
+ let(:object) { :note }
+ let(:creation_args) { { project: project, note: 'hello world' } }
+ let(:params) { { search: 'hello world', scope: 'notes', project_id: project.id } }
+ let(:threshold) { 0 }
+
+ it_behaves_like 'an efficient database result'
+ end
+
+ context 'for blobs scope' do
+ # blobs are enabled for project search only in basic search
+ let(:params_for_one) { { search: 'test', project_id: project.id, scope: 'blobs', per_page: 1 } }
+ let(:params_for_many) { { search: 'test', project_id: project.id, scope: 'blobs', per_page: 5 } }
+
+ it 'avoids N+1 database queries' do
+ control = ActiveRecord::QueryRecorder.new { send_search_request(params_for_one) }
+ expect(response.body).to include('search-results') # Confirm search results to prevent false positives
+
+ expect { send_search_request(params_for_many) }.not_to exceed_query_limit(control.count)
+ expect(response.body).to include('search-results') # Confirm search results to prevent false positives
+ end
+ end
+
+ context 'for commits scope' do
+ let(:params_for_one) { { search: 'test', project_id: project.id, scope: 'commits', per_page: 1 } }
+ let(:params_for_many) { { search: 'test', project_id: project.id, scope: 'commits', per_page: 5 } }
+
+ it 'avoids N+1 database queries' do
+ control = ActiveRecord::QueryRecorder.new { send_search_request(params_for_one) }
+ expect(response.body).to include('search-results') # Confirm search results to prevent false positives
+
+ expect { send_search_request(params_for_many) }.not_to exceed_query_limit(control.count)
+ expect(response.body).to include('search-results') # Confirm search results to prevent false positives
+ end
+ end
+
context 'when searching by SHA' do
let(:sha) { '6d394385cf567f80a8fd85055db1ab4c5295806f' }
diff --git a/spec/rubocop/cop/gitlab/strong_memoize_attr_spec.rb b/spec/rubocop/cop/gitlab/strong_memoize_attr_spec.rb
new file mode 100644
index 00000000000..20dd0f89f53
--- /dev/null
+++ b/spec/rubocop/cop/gitlab/strong_memoize_attr_spec.rb
@@ -0,0 +1,72 @@
+# frozen_string_literal: true
+
+require 'rubocop_spec_helper'
+require_relative '../../../../rubocop/cop/gitlab/strong_memoize_attr'
+
+RSpec.describe RuboCop::Cop::Gitlab::StrongMemoizeAttr do
+ context 'when strong_memoize() is the entire body of a method' do
+ context 'when the memoization name is the same as the method name' do
+ it 'registers an offense and autocorrects' do
+ expect_offense(<<~RUBY)
+ class Foo
+ def memoized_method
+ strong_memoize(:memoized_method) do
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use `strong_memoize_attr`, instead of using `strong_memoize` directly
+ 'This is a memoized method'
+ end
+ end
+ end
+ RUBY
+
+ expect_correction(<<~RUBY)
+ class Foo
+ def memoized_method
+ 'This is a memoized method'
+ end
+ strong_memoize_attr :memoized_method
+ end
+ RUBY
+ end
+ end
+
+ context 'when the memoization name is different from the method name' do
+ it 'registers an offense and autocorrects' do
+ expect_offense(<<~RUBY)
+ class Foo
+ def enabled?
+ strong_memoize(:enabled) do
+ ^^^^^^^^^^^^^^^^^^^^^^^^ Use `strong_memoize_attr`, instead of using `strong_memoize` directly
+ true
+ end
+ end
+ end
+ RUBY
+
+ expect_correction(<<~RUBY)
+ class Foo
+ def enabled?
+ true
+ end
+ strong_memoize_attr :enabled?, :enabled
+ end
+ RUBY
+ end
+ end
+ end
+
+ context 'when strong_memoize() is not the entire body of the method' do
+ it 'does not register an offense or autocorrect' do
+ expect_no_offenses(<<~RUBY)
+ class Foo
+ def memoized_method
+ msg = 'This is a memoized method'
+
+ strong_memoize(:memoized_method) do
+ msg
+ end
+ end
+ end
+ RUBY
+ end
+ end
+end
diff --git a/spec/services/incident_management/incidents/create_service_spec.rb b/spec/services/incident_management/incidents/create_service_spec.rb
index 851b21e1227..7db762b9c5b 100644
--- a/spec/services/incident_management/incidents/create_service_spec.rb
+++ b/spec/services/incident_management/incidents/create_service_spec.rb
@@ -66,6 +66,26 @@ RSpec.describe IncidentManagement::Incidents::CreateService do
end
end
end
+
+ context 'with an alert' do
+ subject(:create_incident) { described_class.new(project, user, title: title, description: description, alert: alert).execute }
+
+ context 'when the alert is valid' do
+ let(:alert) { create(:alert_management_alert, project: project) }
+
+ it 'associates the alert with the incident' do
+ expect(create_incident[:issue].reload.alert_management_alerts).to match_array([alert])
+ end
+ end
+
+ context 'when the alert is not valid' do
+ let(:alert) { create(:alert_management_alert, :with_validation_errors, project: project) }
+
+ it 'does not associate the alert with the incident' do
+ expect(create_incident[:issue].reload.alert_management_alerts).to be_empty
+ end
+ end
+ end
end
context 'when incident has no title' do
@@ -89,10 +109,6 @@ RSpec.describe IncidentManagement::Incidents::CreateService do
subject(:create_incident) { described_class.new(project, user, title: title, description: description, alert: alert).execute }
- it 'associates the alert with the incident' do
- expect(create_incident[:issue].alert_management_alert).to eq(alert)
- end
-
context 'the alert prevents the issue from saving' do
let(:alert) { create(:alert_management_alert, :with_validation_errors, project: project) }
diff --git a/spec/services/issues/close_service_spec.rb b/spec/services/issues/close_service_spec.rb
index ef92b6984d5..dcb17c95f3b 100644
--- a/spec/services/issues/close_service_spec.rb
+++ b/spec/services/issues/close_service_spec.rb
@@ -346,31 +346,29 @@ RSpec.describe Issues::CloseService do
context 'when there is an associated Alert Management Alert' do
context 'when alert can be resolved' do
- let!(:alert) { create(:alert_management_alert, issue: issue, project: project) }
-
it 'resolves an alert and sends a system note' do
+ alert = create(:alert_management_alert, issue: issue, project: project)
+
expect_any_instance_of(SystemNoteService) do |notes_service|
expect(notes_service).to receive(:change_alert_status).with(
- alert,
- current_user,
- " by closing issue #{issue.to_reference(project)}"
+ alert, current_user, " by closing issue #{issue.to_reference(project)}"
)
end
close_issue
- expect(alert.reload.resolved?).to eq(true)
+ expect(alert.reload).to be_resolved
end
end
context 'when alert cannot be resolved' do
- let!(:alert) { create(:alert_management_alert, :with_validation_errors, issue: issue, project: project) }
-
before do
allow(Gitlab::AppLogger).to receive(:warn).and_call_original
end
it 'writes a warning into the log' do
+ alert = create(:alert_management_alert, :with_validation_errors, issue: issue, project: project)
+
close_issue
expect(Gitlab::AppLogger).to have_received(:warn).with(
@@ -383,6 +381,26 @@ RSpec.describe Issues::CloseService do
end
end
+ context 'when there are several associated Alert Management Alerts' do
+ context 'when alerts can be resolved' do
+ it 'resolves an alert and sends a system note', :aggregate_failures do
+ alerts = create_list(:alert_management_alert, 2, issue: issue, project: project)
+
+ alerts.each do |alert|
+ expect_any_instance_of(SystemNoteService) do |notes_service|
+ expect(notes_service).to receive(:change_alert_status).with(
+ alert, current_user, " by closing issue #{issue.to_reference(project)}"
+ )
+ end
+ end
+
+ close_issue
+
+ expect(alerts.map(&:reload)).to all(be_resolved)
+ end
+ end
+ end
+
it 'deletes milestone issue counters cache' do
issue.update!(milestone: create(:milestone, project: project))
diff --git a/spec/services/projects/transfer_service_spec.rb b/spec/services/projects/transfer_service_spec.rb
index 8f505c31c5a..7fd8ab555f7 100644
--- a/spec/services/projects/transfer_service_spec.rb
+++ b/spec/services/projects/transfer_service_spec.rb
@@ -263,7 +263,7 @@ RSpec.describe Projects::TransferService do
end
context 'when transfer fails' do
- let!(:original_path) { project_path(project) }
+ let!(:original_path) { project.repository.relative_path }
def attempt_project_transfer(&block)
expect do
@@ -277,21 +277,11 @@ RSpec.describe Projects::TransferService do
expect_any_instance_of(Labels::TransferService).to receive(:execute).and_raise(ActiveRecord::StatementInvalid, "PG ERROR")
end
- def project_path(project)
- Gitlab::GitalyClient::StorageSettings.allow_disk_access do
- project.repository.path_to_repo
- end
- end
-
- def current_path
- project_path(project)
- end
-
it 'rolls back repo location' do
attempt_project_transfer
expect(project.repository.raw.exists?).to be(true)
- expect(original_path).to eq current_path
+ expect(original_path).to eq project.repository.relative_path
end
it 'rolls back project full path in gitaly' do
diff --git a/spec/support/helpers/search_helpers.rb b/spec/support/helpers/search_helpers.rb
index 7d0f8c09933..eab30be9243 100644
--- a/spec/support/helpers/search_helpers.rb
+++ b/spec/support/helpers/search_helpers.rb
@@ -35,6 +35,8 @@ module SearchHelpers
def select_search_scope(scope)
page.within '[data-testid="search-filter"]' do
click_link scope
+
+ wait_for_all_requests
end
end
diff --git a/spec/views/search/_results.html.haml_spec.rb b/spec/views/search/_results.html.haml_spec.rb
index 2149c394320..e81462ee518 100644
--- a/spec/views/search/_results.html.haml_spec.rb
+++ b/spec/views/search/_results.html.haml_spec.rb
@@ -3,36 +3,60 @@
require 'spec_helper'
RSpec.describe 'search/_results' do
- let(:user) { create(:user) }
+ using RSpec::Parameterized::TableSyntax
+
+ let_it_be(:user) { create(:user) }
+
let(:search_objects) { Issue.page(1).per(2) }
let(:scope) { 'issues' }
let(:term) { 'foo' }
+ let(:search_results) { instance_double('Gitlab::SearchResults', { formatted_count: 10, current_user: user } ) }
+ let(:search_service) { class_double(SearchServicePresenter, scope: scope, search: term, current_user: user) }
before do
controller.params[:action] = 'show'
controller.params[:search] = term
- allow(self).to receive(:current_user).and_return(user)
- allow(@search_results).to receive(:formatted_count).with(scope).and_return(10)
- allow(self).to receive(:search_count_path).with(any_args).and_return("test count link")
- allow(self).to receive(:search_path).with(any_args).and_return("link test")
-
- stub_feature_flags(search_page_vertical_nav: false)
-
create_list(:issue, 3)
- @search_objects = search_objects
- @scope = scope
- @search_term = term
- @search_service = SearchServicePresenter.new(SearchService.new(user, search: term, scope: scope))
+ allow(view).to receive(:current_user) { user }
+ assign(:search_count_path, 'test count link')
+ assign(:search_path, 'link test')
+ assign(:search_results, search_results)
+ assign(:search_objects, search_objects)
+ assign(:search_term, term)
+ assign(:scope, scope)
+ @search_service = SearchServicePresenter.new(SearchService.new(user, search: term, scope: scope))
allow(@search_service).to receive(:search_objects).and_return(search_objects)
end
- it 'displays the page size' do
- render
+ where(search_page_vertical_nav_enabled: [true, false])
+
+ with_them do
+ describe 'page size' do
+ before do
+ stub_feature_flags(search_page_vertical_nav: search_page_vertical_nav_enabled)
+ end
+
+ context 'when search results have a count' do
+ it 'displays the page size' do
+ render
+
+ expect(rendered).to have_content('Showing 1 - 2 of 3 issues for foo')
+ end
+ end
+
+ context 'when search results do not have a count' do
+ let(:search_objects) { Issue.page(1).per(2).without_count }
+
+ it 'does not display the page size' do
+ render
- expect(rendered).to have_content('Showing 1 - 2 of 3 issues for foo')
+ expect(rendered).not_to have_content(/Showing .* of .*/)
+ end
+ end
+ end
end
context 'when searching notes which contain quotes in markdown' do
@@ -51,18 +75,6 @@ RSpec.describe 'search/_results' do
end
end
- context 'when search results do not have a count' do
- before do
- @search_objects = @search_objects.without_count
- end
-
- it 'does not display the page size' do
- render
-
- expect(rendered).not_to have_content(/Showing .* of .*/)
- end
- end
-
context 'rendering all types of search results' do
let_it_be(:project) { create(:project, :repository, :wiki_repo) }
let_it_be(:issue) { create(:issue, project: project, title: 'testing') }