Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2022-11-21 15:12:22 +00:00
parent fbc1f4ffc2
commit 5dc70663c4
39 changed files with 1296 additions and 196 deletions

View File

@ -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'

View File

@ -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'),

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -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.
## View audit events
Depending on the events you want to view, at a minimum you must have:
- 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.
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
There are two kinds of events logged:
- 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.
NOTE:
Some events are recorded and available only as [streaming audit events](audit_event_streaming.md).
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

View File

@ -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: []
---

View File

@ -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

View File

@ -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

View File

@ -176,20 +176,6 @@ Refer to [`strong_memoize.rb`](https://gitlab.com/gitlab-org/gitlab/-/blob/maste
You could write it like:
```ruby
class Find
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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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."
msgstr ""
msgid "Labels can be applied to issues and merge requests to categorize them."
msgstr ""
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 ""

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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,19 +31,23 @@ 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
# make sleep no-op
allow(daemon).to receive(:sleep).and_return(nil)
# let alive return 3 times: true, true, false
allow(daemon).to receive(:alive).and_return(true, true, false)
expect(daemon).to receive(:start)
end
load_initializer
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
context 'when run in non-Puma context, such as rails console, tests, Sidekiq' do

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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) }

View File

@ -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

View File

@ -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' }

View File

@ -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

View File

@ -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) }

View File

@ -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))

View File

@ -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

View File

@ -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

View File

@ -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])
expect(rendered).to have_content('Showing 1 - 2 of 3 issues for foo')
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).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') }