Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
9adada1187
commit
8d9963a8e3
|
@ -11,13 +11,6 @@ Gitlab/PolicyRuleBoolean:
|
|||
Exclude:
|
||||
- 'ee/app/policies/ee/identity_provider_policy.rb'
|
||||
|
||||
# Offense count: 2352
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: Strict, EnforcedStyle, AllowedExplicitMatchers.
|
||||
# SupportedStyles: inflected, explicit
|
||||
RSpec/PredicateMatcher:
|
||||
Enabled: false
|
||||
|
||||
# Offense count: 118
|
||||
RSpec/RepeatedExampleGroupBody:
|
||||
Enabled: false
|
||||
|
|
|
@ -0,0 +1,516 @@
|
|||
---
|
||||
# Cop supports --auto-correct.
|
||||
RSpec/PredicateMatcher:
|
||||
# Offense count: 2480
|
||||
# Temporarily disabled due to too many offenses
|
||||
Enabled: false
|
||||
Exclude:
|
||||
- 'ee/spec/controllers/admin/elasticsearch_controller_spec.rb'
|
||||
- 'ee/spec/controllers/admin/geo/projects_controller_spec.rb'
|
||||
- 'ee/spec/controllers/ee/sent_notifications_controller_spec.rb'
|
||||
- 'ee/spec/controllers/groups/group_members_controller_spec.rb'
|
||||
- 'ee/spec/controllers/groups/ldaps_controller_spec.rb'
|
||||
- 'ee/spec/controllers/projects_controller_spec.rb'
|
||||
- 'ee/spec/elastic/migrate/migration_shared_examples.rb'
|
||||
- 'ee/spec/features/admin/admin_settings_spec.rb'
|
||||
- 'ee/spec/features/projects/members/member_is_removed_from_project_spec.rb'
|
||||
- 'ee/spec/features/projects/mirror_spec.rb'
|
||||
- 'ee/spec/features/signup_spec.rb'
|
||||
- 'ee/spec/graphql/resolvers/path_locks_resolver_spec.rb'
|
||||
- 'ee/spec/helpers/ee/groups_helper_spec.rb'
|
||||
- 'ee/spec/helpers/ee/issues_helper_spec.rb'
|
||||
- 'ee/spec/helpers/projects_helper_spec.rb'
|
||||
- 'ee/spec/lib/ee/gitlab/auth/ldap/sync/group_spec.rb'
|
||||
- 'ee/spec/lib/ee/gitlab/ci/pipeline/chain/validate/after_config_spec.rb'
|
||||
- 'ee/spec/lib/ee/gitlab/ci/pipeline/quota/size_spec.rb'
|
||||
- 'ee/spec/lib/ee/gitlab/database_spec.rb'
|
||||
- 'ee/spec/lib/ee/gitlab/elastic/helper_spec.rb'
|
||||
- 'ee/spec/lib/gitlab/auth/group_saml/gma_membership_enforcer_spec.rb'
|
||||
- 'ee/spec/lib/gitlab/auth/group_saml/membership_enforcer_spec.rb'
|
||||
- 'ee/spec/lib/gitlab/auth/ldap/access_spec.rb'
|
||||
- 'ee/spec/lib/gitlab/checks/diff_check_spec.rb'
|
||||
- 'ee/spec/lib/gitlab/email/handler/create_note_handler_spec.rb'
|
||||
- 'ee/spec/lib/gitlab/geo/geo_node_status_check_spec.rb'
|
||||
- 'ee/spec/lib/gitlab/geo/jwt_request_decoder_spec.rb'
|
||||
- 'ee/spec/lib/gitlab/geo/replication/base_transfer_spec.rb'
|
||||
- 'ee/spec/lib/gitlab/geo/replication/file_transfer_spec.rb'
|
||||
- 'ee/spec/lib/gitlab/geo/replicator_spec.rb'
|
||||
- 'ee/spec/lib/gitlab/geo_spec.rb'
|
||||
- 'ee/spec/lib/gitlab/mirror_spec.rb'
|
||||
- 'ee/spec/lib/gitlab/user_access_spec.rb'
|
||||
- 'ee/spec/lib/system_check/geo/authorized_keys_flag_check_spec.rb'
|
||||
- 'ee/spec/lib/system_check/geo/current_node_check_spec.rb'
|
||||
- 'ee/spec/lib/system_check/geo/http_connection_check_spec.rb'
|
||||
- 'ee/spec/models/allowed_email_domain_spec.rb'
|
||||
- 'ee/spec/models/application_setting_spec.rb'
|
||||
- 'ee/spec/models/approval_state_spec.rb'
|
||||
- 'ee/spec/models/ci/minutes/notification_spec.rb'
|
||||
- 'ee/spec/models/concerns/approval_rule_like_spec.rb'
|
||||
- 'ee/spec/models/concerns/elastic/issue_spec.rb'
|
||||
- 'ee/spec/models/concerns/elastic/note_spec.rb'
|
||||
- 'ee/spec/models/concerns/elastic/project_spec.rb'
|
||||
- 'ee/spec/models/concerns/geo/verification_state_spec.rb'
|
||||
- 'ee/spec/models/dast_site_profile_spec.rb'
|
||||
- 'ee/spec/models/ee/ci/runner_spec.rb'
|
||||
- 'ee/spec/models/ee/group_spec.rb'
|
||||
- 'ee/spec/models/ee/label_spec.rb'
|
||||
- 'ee/spec/models/ee/list_spec.rb'
|
||||
- 'ee/spec/models/ee/namespace_spec.rb'
|
||||
- 'ee/spec/models/ee/user_spec.rb'
|
||||
- 'ee/spec/models/epic_spec.rb'
|
||||
- 'ee/spec/models/geo/container_repository_registry_spec.rb'
|
||||
- 'ee/spec/models/geo/project_registry_spec.rb'
|
||||
- 'ee/spec/models/geo_node_spec.rb'
|
||||
- 'ee/spec/models/ip_restriction_spec.rb'
|
||||
- 'ee/spec/models/issue_spec.rb'
|
||||
- 'ee/spec/models/license_spec.rb'
|
||||
- 'ee/spec/models/namespace_setting_spec.rb'
|
||||
- 'ee/spec/models/note_spec.rb'
|
||||
- 'ee/spec/models/path_lock_spec.rb'
|
||||
- 'ee/spec/models/preloaders/environments/protected_environment_preloader_spec.rb'
|
||||
- 'ee/spec/models/project_import_state_spec.rb'
|
||||
- 'ee/spec/models/project_spec.rb'
|
||||
- 'ee/spec/models/saml_provider_spec.rb'
|
||||
- 'ee/spec/models/security/orchestration_policy_configuration_spec.rb'
|
||||
- 'ee/spec/presenters/ci/minutes/quota_presenter_spec.rb'
|
||||
- 'ee/spec/requests/api/boards_spec.rb'
|
||||
- 'ee/spec/requests/api/graphql/mutations/epics/set_subscription_spec.rb'
|
||||
- 'ee/spec/requests/api/groups_spec.rb'
|
||||
- 'ee/spec/requests/api/members_spec.rb'
|
||||
- 'ee/spec/requests/api/projects_spec.rb'
|
||||
- 'ee/spec/services/approval_rules/params_filtering_service_spec.rb'
|
||||
- 'ee/spec/services/audit_event_service_spec.rb'
|
||||
- 'ee/spec/services/audit_events/register_runner_audit_event_service_spec.rb'
|
||||
- 'ee/spec/services/ci/process_build_service_spec.rb'
|
||||
- 'ee/spec/services/ci/runners/register_runner_service_spec.rb'
|
||||
- 'ee/spec/services/ee/allowed_email_domains/update_service_spec.rb'
|
||||
- 'ee/spec/services/ee/ip_restrictions/update_service_spec.rb'
|
||||
- 'ee/spec/services/ee/issuable/bulk_update_service_spec.rb'
|
||||
- 'ee/spec/services/geo/container_repository_sync_service_spec.rb'
|
||||
- 'ee/spec/services/geo/event_service_spec.rb'
|
||||
- 'ee/spec/services/geo/files_expire_service_spec.rb'
|
||||
- 'ee/spec/services/geo/hashed_storage_attachments_migration_service_spec.rb'
|
||||
- 'ee/spec/services/geo/move_repository_service_spec.rb'
|
||||
- 'ee/spec/services/geo/repository_destroy_service_spec.rb'
|
||||
- 'ee/spec/services/groups/mark_for_deletion_service_spec.rb'
|
||||
- 'ee/spec/services/groups/restore_service_spec.rb'
|
||||
- 'ee/spec/services/iterations/cadences/create_service_spec.rb'
|
||||
- 'ee/spec/services/iterations/create_service_spec.rb'
|
||||
- 'ee/spec/services/jira/requests/issues/list_service_spec.rb'
|
||||
- 'ee/spec/services/milestones/promote_service_spec.rb'
|
||||
- 'ee/spec/services/protected_environments/create_service_spec.rb'
|
||||
- 'ee/spec/services/vulnerabilities/manually_create_service_spec.rb'
|
||||
- 'ee/spec/services/vulnerability_exports/export_service_spec.rb'
|
||||
- 'ee/spec/support/shared_examples/graphql/mutations/dast_on_demand_scans_shared_examples.rb'
|
||||
- 'ee/spec/support/shared_examples/lib/gitlab/geo/geo_log_cursor_event_shared_examples.rb'
|
||||
- 'ee/spec/support/shared_examples/models/concerns/elastic/limited_indexing_shared_examples.rb'
|
||||
- 'ee/spec/support/shared_examples/models/concerns/verifiable_replicator_shared_examples.rb'
|
||||
- 'ee/spec/support/shared_examples/models/geo_verifiable_registry_shared_examples.rb'
|
||||
- 'ee/spec/support/shared_examples/models/member_shared_examples.rb'
|
||||
- 'ee/spec/tasks/geo_rake_spec.rb'
|
||||
- 'ee/spec/workers/concerns/elastic/indexing_control_spec.rb'
|
||||
- 'ee/spec/workers/elastic/migration_worker_spec.rb'
|
||||
- 'ee/spec/workers/geo/batch/project_registry_worker_spec.rb'
|
||||
- 'qa/qa/specs/features/browser_ui/1_manage/project/create_project_badge_spec.rb'
|
||||
- 'qa/qa/specs/features/browser_ui/3_create/web_ide/add_file_template_spec.rb'
|
||||
- 'qa/qa/specs/features/ee/browser_ui/12_geo/database_delete_replication_spec.rb'
|
||||
- 'qa/qa/specs/features/ee/browser_ui/2_plan/epic/roadmap_spec.rb'
|
||||
- 'qa/spec/runtime/env_spec.rb'
|
||||
- 'qa/spec/runtime/feature_spec.rb'
|
||||
- 'qa/spec/specs/helpers/context_selector_spec.rb'
|
||||
- 'spec/components/diffs/overflow_warning_component_spec.rb'
|
||||
- 'spec/controllers/admin/dev_ops_report_controller_spec.rb'
|
||||
- 'spec/controllers/admin/topics/avatars_controller_spec.rb'
|
||||
- 'spec/controllers/admin/users_controller_spec.rb'
|
||||
- 'spec/controllers/application_controller_spec.rb'
|
||||
- 'spec/controllers/concerns/checks_collaboration_spec.rb'
|
||||
- 'spec/controllers/groups/avatars_controller_spec.rb'
|
||||
- 'spec/controllers/groups/clusters_controller_spec.rb'
|
||||
- 'spec/controllers/groups/group_members_controller_spec.rb'
|
||||
- 'spec/controllers/groups/settings/applications_controller_spec.rb'
|
||||
- 'spec/controllers/omniauth_callbacks_controller_spec.rb'
|
||||
- 'spec/controllers/profiles/avatars_controller_spec.rb'
|
||||
- 'spec/controllers/profiles_controller_spec.rb'
|
||||
- 'spec/controllers/projects/avatars_controller_spec.rb'
|
||||
- 'spec/controllers/projects/clusters_controller_spec.rb'
|
||||
- 'spec/controllers/projects/issues_controller_spec.rb'
|
||||
- 'spec/controllers/projects/jobs_controller_spec.rb'
|
||||
- 'spec/controllers/projects/merge_requests_controller_spec.rb'
|
||||
- 'spec/controllers/projects/pipelines_controller_spec.rb'
|
||||
- 'spec/controllers/projects/project_members_controller_spec.rb'
|
||||
- 'spec/controllers/projects_controller_spec.rb'
|
||||
- 'spec/controllers/sent_notifications_controller_spec.rb'
|
||||
- 'spec/controllers/sessions_controller_spec.rb'
|
||||
- 'spec/controllers/snippets/notes_controller_spec.rb'
|
||||
- 'spec/features/admin/admin_settings_spec.rb'
|
||||
- 'spec/features/admin/users/user_spec.rb'
|
||||
- 'spec/features/admin/users/users_spec.rb'
|
||||
- 'spec/features/groups/members/request_access_spec.rb'
|
||||
- 'spec/features/groups/share_lock_spec.rb'
|
||||
- 'spec/features/merge_request/user_interacts_with_batched_mr_diffs_spec.rb'
|
||||
- 'spec/features/password_reset_spec.rb'
|
||||
- 'spec/features/profile_spec.rb'
|
||||
- 'spec/features/profiles/emails_spec.rb'
|
||||
- 'spec/features/projects/integrations/user_activates_mattermost_slash_command_spec.rb'
|
||||
- 'spec/features/projects/jobs/user_browses_job_spec.rb'
|
||||
- 'spec/features/projects/members/member_leaves_project_spec.rb'
|
||||
- 'spec/features/projects/members/user_requests_access_spec.rb'
|
||||
- 'spec/features/projects/pages/user_edits_settings_spec.rb'
|
||||
- 'spec/features/projects/settings/forked_project_settings_spec.rb'
|
||||
- 'spec/features/unsubscribe_links_spec.rb'
|
||||
- 'spec/features/users/signup_spec.rb'
|
||||
- 'spec/finders/group_descendants_finder_spec.rb'
|
||||
- 'spec/finders/issues_finder_spec.rb'
|
||||
- 'spec/finders/merge_request_target_project_finder_spec.rb'
|
||||
- 'spec/helpers/application_helper_spec.rb'
|
||||
- 'spec/helpers/application_settings_helper_spec.rb'
|
||||
- 'spec/helpers/auth_helper_spec.rb'
|
||||
- 'spec/helpers/blob_helper_spec.rb'
|
||||
- 'spec/helpers/clusters_helper_spec.rb'
|
||||
- 'spec/helpers/groups_helper_spec.rb'
|
||||
- 'spec/helpers/issues_helper_spec.rb'
|
||||
- 'spec/helpers/projects_helper_spec.rb'
|
||||
- 'spec/helpers/recaptcha_helper_spec.rb'
|
||||
- 'spec/helpers/sessions_helper_spec.rb'
|
||||
- 'spec/lib/backup/files_spec.rb'
|
||||
- 'spec/lib/bitbucket/connection_spec.rb'
|
||||
- 'spec/lib/bitbucket/page_spec.rb'
|
||||
- 'spec/lib/bitbucket/representation/pull_request_comment_spec.rb'
|
||||
- 'spec/lib/bitbucket/representation/repo_spec.rb'
|
||||
- 'spec/lib/bitbucket_server/page_spec.rb'
|
||||
- 'spec/lib/bitbucket_server/paginator_spec.rb'
|
||||
- 'spec/lib/bitbucket_server/representation/activity_spec.rb'
|
||||
- 'spec/lib/bitbucket_server/representation/pull_request_comment_spec.rb'
|
||||
- 'spec/lib/bitbucket_server/representation/pull_request_spec.rb'
|
||||
- 'spec/lib/constraints/group_url_constrainer_spec.rb'
|
||||
- 'spec/lib/constraints/project_url_constrainer_spec.rb'
|
||||
- 'spec/lib/constraints/user_url_constrainer_spec.rb'
|
||||
- 'spec/lib/feature_spec.rb'
|
||||
- 'spec/lib/gitlab/auth/ip_rate_limiter_spec.rb'
|
||||
- 'spec/lib/gitlab/auth/ldap/access_spec.rb'
|
||||
- 'spec/lib/gitlab/auth/ldap/config_spec.rb'
|
||||
- 'spec/lib/gitlab/auth/ldap/user_spec.rb'
|
||||
- 'spec/lib/gitlab/auth/o_auth/provider_spec.rb'
|
||||
- 'spec/lib/gitlab/auth/o_auth/user_spec.rb'
|
||||
- 'spec/lib/gitlab/auth/result_spec.rb'
|
||||
- 'spec/lib/gitlab/auth/two_factor_auth_verifier_spec.rb'
|
||||
- 'spec/lib/gitlab/auth_spec.rb'
|
||||
- 'spec/lib/gitlab/authorized_keys_spec.rb'
|
||||
- 'spec/lib/gitlab/background_migration/backfill_jira_tracker_deployment_type2_spec.rb'
|
||||
- 'spec/lib/gitlab/background_migration/legacy_upload_mover_spec.rb'
|
||||
- 'spec/lib/gitlab/background_migration/legacy_uploads_migrator_spec.rb'
|
||||
- 'spec/lib/gitlab/background_migration/merge_topics_with_same_name_spec.rb'
|
||||
- 'spec/lib/gitlab/blob_helper_spec.rb'
|
||||
- 'spec/lib/gitlab/cache/ci/project_pipeline_status_spec.rb'
|
||||
- 'spec/lib/gitlab/checks/lfs_integrity_spec.rb'
|
||||
- 'spec/lib/gitlab/ci/ansi2json/line_spec.rb'
|
||||
- 'spec/lib/gitlab/ci/ansi2json/parser_spec.rb'
|
||||
- 'spec/lib/gitlab/ci/config/entry/job_spec.rb'
|
||||
- 'spec/lib/gitlab/ci/lint_spec.rb'
|
||||
- 'spec/lib/gitlab/ci/matching/build_matcher_spec.rb'
|
||||
- 'spec/lib/gitlab/ci/matching/runner_matcher_spec.rb'
|
||||
- 'spec/lib/gitlab/ci/parsers/test/junit_spec.rb'
|
||||
- 'spec/lib/gitlab/ci/pipeline/chain/limit/rate_limit_spec.rb'
|
||||
- 'spec/lib/gitlab/ci/pipeline/chain/pipeline/process_spec.rb'
|
||||
- 'spec/lib/gitlab/ci/reports/test_case_spec.rb'
|
||||
- 'spec/lib/gitlab/ci/status/build/failed_spec.rb'
|
||||
- 'spec/lib/gitlab/ci/status/build/waiting_for_approval_spec.rb'
|
||||
- 'spec/lib/gitlab/ci/templates/AWS/deploy_ecs_gitlab_ci_yaml_spec.rb'
|
||||
- 'spec/lib/gitlab/ci/trace/archive_spec.rb'
|
||||
- 'spec/lib/gitlab/ci/trace_spec.rb'
|
||||
- 'spec/lib/gitlab/ci_access_spec.rb'
|
||||
- 'spec/lib/gitlab/cleanup/orphan_job_artifact_files_batch_spec.rb'
|
||||
- 'spec/lib/gitlab/cleanup/orphan_lfs_file_references_spec.rb'
|
||||
- 'spec/lib/gitlab/cleanup/project_uploads_spec.rb'
|
||||
- 'spec/lib/gitlab/content_security_policy/config_loader_spec.rb'
|
||||
- 'spec/lib/gitlab/cross_project_access/check_collection_spec.rb'
|
||||
- 'spec/lib/gitlab/cross_project_access/check_info_spec.rb'
|
||||
- 'spec/lib/gitlab/current_settings_spec.rb'
|
||||
- 'spec/lib/gitlab/database/load_balancing/sidekiq_server_middleware_spec.rb'
|
||||
- 'spec/lib/gitlab/database/migration_helpers_spec.rb'
|
||||
- 'spec/lib/gitlab/database/migration_spec.rb'
|
||||
- 'spec/lib/gitlab/database/migrations/runner_spec.rb'
|
||||
- 'spec/lib/gitlab/database/partitioning/time_partition_spec.rb'
|
||||
- 'spec/lib/gitlab/database/postgresql_adapter/force_disconnectable_mixin_spec.rb'
|
||||
- 'spec/lib/gitlab/database/reflection_spec.rb'
|
||||
- 'spec/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_namespaces_spec.rb'
|
||||
- 'spec/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_projects_spec.rb'
|
||||
- 'spec/lib/gitlab/database_importers/self_monitoring/project/create_service_spec.rb'
|
||||
- 'spec/lib/gitlab/dependency_linker/cargo_toml_linker_spec.rb'
|
||||
- 'spec/lib/gitlab/dependency_linker/cartfile_linker_spec.rb'
|
||||
- 'spec/lib/gitlab/dependency_linker/composer_json_linker_spec.rb'
|
||||
- 'spec/lib/gitlab/dependency_linker/gemfile_linker_spec.rb'
|
||||
- 'spec/lib/gitlab/dependency_linker/gemspec_linker_spec.rb'
|
||||
- 'spec/lib/gitlab/dependency_linker/go_mod_linker_spec.rb'
|
||||
- 'spec/lib/gitlab/dependency_linker/go_sum_linker_spec.rb'
|
||||
- 'spec/lib/gitlab/dependency_linker/godeps_json_linker_spec.rb'
|
||||
- 'spec/lib/gitlab/dependency_linker/package_json_linker_spec.rb'
|
||||
- 'spec/lib/gitlab/dependency_linker/podfile_linker_spec.rb'
|
||||
- 'spec/lib/gitlab/dependency_linker/podspec_json_linker_spec.rb'
|
||||
- 'spec/lib/gitlab/dependency_linker/podspec_linker_spec.rb'
|
||||
- 'spec/lib/gitlab/dependency_linker/requirements_txt_linker_spec.rb'
|
||||
- 'spec/lib/gitlab/deploy_key_access_spec.rb'
|
||||
- 'spec/lib/gitlab/diff/custom_diff_spec.rb'
|
||||
- 'spec/lib/gitlab/diff/file_spec.rb'
|
||||
- 'spec/lib/gitlab/diff/position_spec.rb'
|
||||
- 'spec/lib/gitlab/diff/rendered/notebook/diff_file_spec.rb'
|
||||
- 'spec/lib/gitlab/email/handler/create_issue_handler_spec.rb'
|
||||
- 'spec/lib/gitlab/email/handler/create_merge_request_handler_spec.rb'
|
||||
- 'spec/lib/gitlab/email/handler/create_note_handler_spec.rb'
|
||||
- 'spec/lib/gitlab/email/handler/service_desk_handler_spec.rb'
|
||||
- 'spec/lib/gitlab/email/handler/unsubscribe_handler_spec.rb'
|
||||
- 'spec/lib/gitlab/experimentation/group_types_spec.rb'
|
||||
- 'spec/lib/gitlab/external_authorization_spec.rb'
|
||||
- 'spec/lib/gitlab/fake_application_settings_spec.rb'
|
||||
- 'spec/lib/gitlab/git/blob_spec.rb'
|
||||
- 'spec/lib/gitlab/git/branch_spec.rb'
|
||||
- 'spec/lib/gitlab/git/commit_spec.rb'
|
||||
- 'spec/lib/gitlab/git/keep_around_spec.rb'
|
||||
- 'spec/lib/gitlab/git/repository_spec.rb'
|
||||
- 'spec/lib/gitlab/git/rugged_impl/use_rugged_spec.rb'
|
||||
- 'spec/lib/gitlab/git/tag_spec.rb'
|
||||
- 'spec/lib/gitlab/git/tree_spec.rb'
|
||||
- 'spec/lib/gitlab/git_access_snippet_spec.rb'
|
||||
- 'spec/lib/gitlab/git_post_receive_spec.rb'
|
||||
- 'spec/lib/gitlab/gitaly_client/repository_service_spec.rb'
|
||||
- 'spec/lib/gitlab/gitaly_client/storage_settings_spec.rb'
|
||||
- 'spec/lib/gitlab/github_import/importer/pull_request_importer_spec.rb'
|
||||
- 'spec/lib/gitlab/gl_repository/repo_type_spec.rb'
|
||||
- 'spec/lib/gitlab/gpg/commit_spec.rb'
|
||||
- 'spec/lib/gitlab/hashed_storage/migrator_spec.rb'
|
||||
- 'spec/lib/gitlab/i18n/translation_entry_spec.rb'
|
||||
- 'spec/lib/gitlab/import_export/after_export_strategies/base_after_export_strategy_spec.rb'
|
||||
- 'spec/lib/gitlab/import_export/fork_spec.rb'
|
||||
- 'spec/lib/gitlab/import_export/group/tree_restorer_spec.rb'
|
||||
- 'spec/lib/gitlab/import_export/snippet_repo_restorer_spec.rb'
|
||||
- 'spec/lib/gitlab/import_export/snippet_repo_saver_spec.rb'
|
||||
- 'spec/lib/gitlab/import_export/snippets_repo_saver_spec.rb'
|
||||
- 'spec/lib/gitlab/kubernetes/deployment_spec.rb'
|
||||
- 'spec/lib/gitlab/kubernetes/kube_client_spec.rb'
|
||||
- 'spec/lib/gitlab/kubernetes/namespace_spec.rb'
|
||||
- 'spec/lib/gitlab/legacy_github_import/pull_request_formatter_spec.rb'
|
||||
- 'spec/lib/gitlab/mail_room/mail_room_spec.rb'
|
||||
- 'spec/lib/gitlab/markdown_cache/active_record/extension_spec.rb'
|
||||
- 'spec/lib/gitlab/markdown_cache/field_data_spec.rb'
|
||||
- 'spec/lib/gitlab/markup_helper_spec.rb'
|
||||
- 'spec/lib/gitlab/metrics/prometheus_spec.rb'
|
||||
- 'spec/lib/gitlab/null_request_store_spec.rb'
|
||||
- 'spec/lib/gitlab/pagination/cursor_based_keyset_spec.rb'
|
||||
- 'spec/lib/gitlab/pagination/keyset_spec.rb'
|
||||
- 'spec/lib/gitlab/performance_bar_spec.rb'
|
||||
- 'spec/lib/gitlab/project_transfer_spec.rb'
|
||||
- 'spec/lib/gitlab/reference_extractor_spec.rb'
|
||||
- 'spec/lib/gitlab/request_forgery_protection_spec.rb'
|
||||
- 'spec/lib/gitlab/sanitizers/svg_spec.rb'
|
||||
- 'spec/lib/gitlab/search/found_blob_spec.rb'
|
||||
- 'spec/lib/gitlab/search/found_wiki_page_spec.rb'
|
||||
- 'spec/lib/gitlab/service_desk_email_spec.rb'
|
||||
- 'spec/lib/gitlab/shard_health_cache_spec.rb'
|
||||
- 'spec/lib/gitlab/uploads_transfer_spec.rb'
|
||||
- 'spec/lib/gitlab/usage/metric_definition_spec.rb'
|
||||
- 'spec/lib/gitlab/usage/service_ping/legacy_metric_timing_decorator_spec.rb'
|
||||
- 'spec/lib/gitlab/user_access_snippet_spec.rb'
|
||||
- 'spec/lib/gitlab/user_access_spec.rb'
|
||||
- 'spec/lib/gitlab/utils/sanitize_node_link_spec.rb'
|
||||
- 'spec/lib/gitlab/view/presenter/base_spec.rb'
|
||||
- 'spec/lib/gitlab/visibility_level_spec.rb'
|
||||
- 'spec/lib/object_storage/direct_upload_spec.rb'
|
||||
- 'spec/lib/sidebars/projects/menus/external_issue_tracker_menu_spec.rb'
|
||||
- 'spec/lib/sidebars/projects/menus/external_wiki_menu_spec.rb'
|
||||
- 'spec/lib/sidebars/projects/menus/shimo_menu_spec.rb'
|
||||
- 'spec/lib/system_check/app/hashed_storage_all_projects_check_spec.rb'
|
||||
- 'spec/lib/system_check/app/hashed_storage_enabled_check_spec.rb'
|
||||
- 'spec/migrations/20210713042000_fix_ci_sources_pipelines_index_names_spec.rb'
|
||||
- 'spec/migrations/20210907211557_finalize_ci_builds_bigint_conversion_spec.rb'
|
||||
- 'spec/migrations/20220128155814_fix_approval_rules_code_owners_rule_type_index_spec.rb'
|
||||
- 'spec/migrations/20220505174658_update_index_on_alerts_to_exclude_null_fingerprints_spec.rb'
|
||||
- 'spec/models/blob_spec.rb'
|
||||
- 'spec/models/blob_viewer/base_spec.rb'
|
||||
- 'spec/models/ci/build_spec.rb'
|
||||
- 'spec/models/ci/build_trace_chunk_spec.rb'
|
||||
- 'spec/models/ci/job_artifact_spec.rb'
|
||||
- 'spec/models/ci/pipeline_spec.rb'
|
||||
- 'spec/models/ci/processable_spec.rb'
|
||||
- 'spec/models/ci/runner_spec.rb'
|
||||
- 'spec/models/clusters/agent_spec.rb'
|
||||
- 'spec/models/commit_spec.rb'
|
||||
- 'spec/models/concerns/access_requestable_spec.rb'
|
||||
- 'spec/models/concerns/awardable_spec.rb'
|
||||
- 'spec/models/concerns/chronic_duration_attribute_spec.rb'
|
||||
- 'spec/models/concerns/ci/has_deployment_name_spec.rb'
|
||||
- 'spec/models/concerns/featurable_spec.rb'
|
||||
- 'spec/models/concerns/ignorable_columns_spec.rb'
|
||||
- 'spec/models/concerns/integrations/has_data_fields_spec.rb'
|
||||
- 'spec/models/concerns/issuable_spec.rb'
|
||||
- 'spec/models/concerns/mentionable_spec.rb'
|
||||
- 'spec/models/concerns/milestoneable_spec.rb'
|
||||
- 'spec/models/concerns/resolvable_discussion_spec.rb'
|
||||
- 'spec/models/concerns/resolvable_note_spec.rb'
|
||||
- 'spec/models/concerns/routable_spec.rb'
|
||||
- 'spec/models/concerns/spammable_spec.rb'
|
||||
- 'spec/models/concerns/subscribable_spec.rb'
|
||||
- 'spec/models/container_repository_spec.rb'
|
||||
- 'spec/models/customer_relations/contact_spec.rb'
|
||||
- 'spec/models/deploy_token_spec.rb'
|
||||
- 'spec/models/diff_note_spec.rb'
|
||||
- 'spec/models/diff_viewer/base_spec.rb'
|
||||
- 'spec/models/email_spec.rb'
|
||||
- 'spec/models/event_spec.rb'
|
||||
- 'spec/models/gpg_key_spec.rb'
|
||||
- 'spec/models/group_spec.rb'
|
||||
- 'spec/models/hooks/web_hook_log_spec.rb'
|
||||
- 'spec/models/identity_spec.rb'
|
||||
- 'spec/models/integration_spec.rb'
|
||||
- 'spec/models/integrations/base_issue_tracker_spec.rb'
|
||||
- 'spec/models/integrations/base_third_party_wiki_spec.rb'
|
||||
- 'spec/models/integrations/jira_spec.rb'
|
||||
- 'spec/models/issue_spec.rb'
|
||||
- 'spec/models/members/project_member_spec.rb'
|
||||
- 'spec/models/merge_request_diff_spec.rb'
|
||||
- 'spec/models/merge_request_spec.rb'
|
||||
- 'spec/models/milestone_spec.rb'
|
||||
- 'spec/models/namespace/aggregation_schedule_spec.rb'
|
||||
- 'spec/models/namespace_setting_spec.rb'
|
||||
- 'spec/models/namespace_spec.rb'
|
||||
- 'spec/models/note_spec.rb'
|
||||
- 'spec/models/postgresql/replication_slot_spec.rb'
|
||||
- 'spec/models/project_feature_spec.rb'
|
||||
- 'spec/models/project_spec.rb'
|
||||
- 'spec/models/project_statistics_spec.rb'
|
||||
- 'spec/models/project_team_spec.rb'
|
||||
- 'spec/models/remote_mirror_spec.rb'
|
||||
- 'spec/models/repository_spec.rb'
|
||||
- 'spec/models/route_spec.rb'
|
||||
- 'spec/models/sent_notification_spec.rb'
|
||||
- 'spec/models/snippet_spec.rb'
|
||||
- 'spec/models/todo_spec.rb'
|
||||
- 'spec/models/upload_spec.rb'
|
||||
- 'spec/models/uploads/local_spec.rb'
|
||||
- 'spec/models/user_agent_detail_spec.rb'
|
||||
- 'spec/models/user_spec.rb'
|
||||
- 'spec/models/wiki_page_spec.rb'
|
||||
- 'spec/policies/project_policy_spec.rb'
|
||||
- 'spec/presenters/blob_presenter_spec.rb'
|
||||
- 'spec/presenters/ci/build_presenter_spec.rb'
|
||||
- 'spec/presenters/label_presenter_spec.rb'
|
||||
- 'spec/requests/api/admin/instance_clusters_spec.rb'
|
||||
- 'spec/requests/api/ci/jobs_spec.rb'
|
||||
- 'spec/requests/api/ci/runner/jobs_request_post_spec.rb'
|
||||
- 'spec/requests/api/ci/runners_spec.rb'
|
||||
- 'spec/requests/api/features_spec.rb'
|
||||
- 'spec/requests/api/group_clusters_spec.rb'
|
||||
- 'spec/requests/api/integrations_spec.rb'
|
||||
- 'spec/requests/api/internal/base_spec.rb'
|
||||
- 'spec/requests/api/merge_requests_spec.rb'
|
||||
- 'spec/requests/api/project_clusters_spec.rb'
|
||||
- 'spec/requests/api/project_export_spec.rb'
|
||||
- 'spec/requests/api/project_hooks_spec.rb'
|
||||
- 'spec/requests/api/project_snippets_spec.rb'
|
||||
- 'spec/requests/api/projects_spec.rb'
|
||||
- 'spec/requests/api/resource_access_tokens_spec.rb'
|
||||
- 'spec/requests/api/snippets_spec.rb'
|
||||
- 'spec/requests/api/users_spec.rb'
|
||||
- 'spec/requests/git_http_spec.rb'
|
||||
- 'spec/requests/lfs_http_spec.rb'
|
||||
- 'spec/serializers/pipeline_serializer_spec.rb'
|
||||
- 'spec/services/branches/create_service_spec.rb'
|
||||
- 'spec/services/ci/create_pipeline_service/needs_spec.rb'
|
||||
- 'spec/services/ci/create_pipeline_service/rate_limit_spec.rb'
|
||||
- 'spec/services/ci/delete_objects_service_spec.rb'
|
||||
- 'spec/services/ci/destroy_pipeline_service_spec.rb'
|
||||
- 'spec/services/ci/expire_pipeline_cache_service_spec.rb'
|
||||
- 'spec/services/ci/job_artifacts/destroy_all_expired_service_spec.rb'
|
||||
- 'spec/services/ci/job_artifacts/expire_project_build_artifacts_service_spec.rb'
|
||||
- 'spec/services/ci/runners/register_runner_service_spec.rb'
|
||||
- 'spec/services/clusters/destroy_service_spec.rb'
|
||||
- 'spec/services/concerns/exclusive_lease_guard_spec.rb'
|
||||
- 'spec/services/concerns/merge_requests/assigns_merge_params_spec.rb'
|
||||
- 'spec/services/container_expiration_policies/cleanup_service_spec.rb'
|
||||
- 'spec/services/container_expiration_policies/update_service_spec.rb'
|
||||
- 'spec/services/customer_relations/contacts/update_service_spec.rb'
|
||||
- 'spec/services/customer_relations/organizations/update_service_spec.rb'
|
||||
- 'spec/services/deployments/older_deployments_drop_service_spec.rb'
|
||||
- 'spec/services/draft_notes/publish_service_spec.rb'
|
||||
- 'spec/services/environments/schedule_to_delete_review_apps_service_spec.rb'
|
||||
- 'spec/services/groups/destroy_service_spec.rb'
|
||||
- 'spec/services/groups/group_links/create_service_spec.rb'
|
||||
- 'spec/services/groups/transfer_service_spec.rb'
|
||||
- 'spec/services/groups/update_service_spec.rb'
|
||||
- 'spec/services/issuable/bulk_update_service_spec.rb'
|
||||
- 'spec/services/jira/requests/projects/list_service_spec.rb'
|
||||
- 'spec/services/jira_import/users_importer_spec.rb'
|
||||
- 'spec/services/merge_requests/build_service_spec.rb'
|
||||
- 'spec/services/merge_requests/conflicts/list_service_spec.rb'
|
||||
- 'spec/services/merge_requests/create_from_issue_service_spec.rb'
|
||||
- 'spec/services/merge_requests/merge_service_spec.rb'
|
||||
- 'spec/services/merge_requests/refresh_service_spec.rb'
|
||||
- 'spec/services/metrics/dashboard/cluster_metrics_embed_service_spec.rb'
|
||||
- 'spec/services/metrics/dashboard/panel_preview_service_spec.rb'
|
||||
- 'spec/services/metrics/users_starred_dashboards/delete_service_spec.rb'
|
||||
- 'spec/services/milestones/promote_service_spec.rb'
|
||||
- 'spec/services/milestones/transfer_service_spec.rb'
|
||||
- 'spec/services/namespaces/package_settings/update_service_spec.rb'
|
||||
- 'spec/services/note_summary_spec.rb'
|
||||
- 'spec/services/notes/build_service_spec.rb'
|
||||
- 'spec/services/notes/quick_actions_service_spec.rb'
|
||||
- 'spec/services/packages/debian/find_or_create_incoming_service_spec.rb'
|
||||
- 'spec/services/packages/nuget/update_package_from_metadata_service_spec.rb'
|
||||
- 'spec/services/projects/after_rename_service_spec.rb'
|
||||
- 'spec/services/projects/cleanup_service_spec.rb'
|
||||
- 'spec/services/projects/create_service_spec.rb'
|
||||
- 'spec/services/projects/destroy_rollback_service_spec.rb'
|
||||
- 'spec/services/projects/destroy_service_spec.rb'
|
||||
- 'spec/services/projects/fork_service_spec.rb'
|
||||
- 'spec/services/projects/hashed_storage/base_attachment_service_spec.rb'
|
||||
- 'spec/services/projects/hashed_storage/migrate_attachments_service_spec.rb'
|
||||
- 'spec/services/projects/hashed_storage/migrate_repository_service_spec.rb'
|
||||
- 'spec/services/projects/hashed_storage/rollback_attachments_service_spec.rb'
|
||||
- 'spec/services/projects/hashed_storage/rollback_repository_service_spec.rb'
|
||||
- 'spec/services/projects/lfs_pointers/lfs_download_link_list_service_spec.rb'
|
||||
- 'spec/services/projects/lfs_pointers/lfs_object_download_list_service_spec.rb'
|
||||
- 'spec/services/projects/update_pages_service_spec.rb'
|
||||
- 'spec/services/projects/update_service_spec.rb'
|
||||
- 'spec/services/releases/create_service_spec.rb'
|
||||
- 'spec/services/repositories/destroy_rollback_service_spec.rb'
|
||||
- 'spec/services/repositories/destroy_service_spec.rb'
|
||||
- 'spec/services/repository_archive_clean_up_service_spec.rb'
|
||||
- 'spec/services/resource_access_tokens/revoke_service_spec.rb'
|
||||
- 'spec/services/snippets/create_service_spec.rb'
|
||||
- 'spec/services/snippets/destroy_service_spec.rb'
|
||||
- 'spec/services/snippets/update_service_spec.rb'
|
||||
- 'spec/services/spam/akismet_service_spec.rb'
|
||||
- 'spec/services/system_notes/issuables_service_spec.rb'
|
||||
- 'spec/services/todo_service_spec.rb'
|
||||
- 'spec/services/users/destroy_service_spec.rb'
|
||||
- 'spec/support/shared_contexts/email_shared_context.rb'
|
||||
- 'spec/support/shared_examples/ci/auto_merge_merge_requests_shared_examples.rb'
|
||||
- 'spec/support/shared_examples/lib/gitlab/ci/ci_trace_shared_examples.rb'
|
||||
- 'spec/support/shared_examples/models/application_setting_shared_examples.rb'
|
||||
- 'spec/support/shared_examples/models/cluster_application_core_shared_examples.rb'
|
||||
- 'spec/support/shared_examples/models/concerns/timebox_shared_examples.rb'
|
||||
- 'spec/support/shared_examples/models/integrations/base_slash_commands_shared_examples.rb'
|
||||
- 'spec/support/shared_examples/models/member_shared_examples.rb'
|
||||
- 'spec/support/shared_examples/models/note_access_check_shared_examples.rb'
|
||||
- 'spec/support/shared_examples/requests/access_tokens_controller_shared_examples.rb'
|
||||
- 'spec/support/shared_examples/uploaders/object_storage_shared_examples.rb'
|
||||
- 'spec/support/shared_examples/workers/batched_background_migration_worker_shared_examples.rb'
|
||||
- 'spec/tasks/gitlab/backup_rake_spec.rb'
|
||||
- 'spec/tasks/gitlab/cleanup_rake_spec.rb'
|
||||
- 'spec/uploaders/object_storage_spec.rb'
|
||||
- 'spec/validators/any_field_validator_spec.rb'
|
||||
- 'spec/validators/array_members_validator_spec.rb'
|
||||
- 'spec/validators/cron_validator_spec.rb'
|
||||
- 'spec/validators/namespace_path_validator_spec.rb'
|
||||
- 'spec/validators/project_path_validator_spec.rb'
|
||||
- 'spec/workers/bulk_imports/entity_worker_spec.rb'
|
||||
- 'spec/workers/bulk_imports/pipeline_worker_spec.rb'
|
||||
- 'spec/workers/ci/delete_objects_worker_spec.rb'
|
||||
- 'spec/workers/concerns/worker_attributes_spec.rb'
|
||||
- 'spec/workers/container_expiration_policies/cleanup_container_repository_worker_spec.rb'
|
||||
- 'spec/workers/expire_build_instance_artifacts_worker_spec.rb'
|
||||
- 'spec/workers/group_destroy_worker_spec.rb'
|
||||
- 'spec/workers/hashed_storage/migrator_worker_spec.rb'
|
||||
- 'spec/workers/hashed_storage/rollbacker_worker_spec.rb'
|
||||
- 'spec/workers/project_destroy_worker_spec.rb'
|
||||
- 'spec/workers/remote_mirror_notification_worker_spec.rb'
|
||||
- 'spec/workers/x509_issuer_crl_check_worker_spec.rb'
|
|
@ -0,0 +1,267 @@
|
|||
import { LOAD_ACTION_ATTR_SELECTOR } from './constants';
|
||||
import { dispatchSnowplowEvent } from './dispatch_snowplow_event';
|
||||
import getStandardContext from './get_standard_context';
|
||||
import {
|
||||
getEventHandlers,
|
||||
createEventPayload,
|
||||
renameKey,
|
||||
getReferrersCache,
|
||||
addReferrersCacheEntry,
|
||||
} from './utils';
|
||||
|
||||
export const Tracker = {
|
||||
nonInitializedQueue: [],
|
||||
initialized: false,
|
||||
definitionsLoaded: false,
|
||||
definitionsManifest: {},
|
||||
definitionsEventsQueue: [],
|
||||
definitions: [],
|
||||
ALLOWED_URL_HASHES: ['#diff', '#note'],
|
||||
/**
|
||||
* (Legacy) Determines if tracking is enabled at the user level.
|
||||
* https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/DNT.
|
||||
*
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
trackable() {
|
||||
return !['1', 'yes'].includes(
|
||||
window.doNotTrack || navigator.doNotTrack || navigator.msDoNotTrack,
|
||||
);
|
||||
},
|
||||
|
||||
/**
|
||||
* Determines if Snowplow is available/enabled.
|
||||
*
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
enabled() {
|
||||
return typeof window.snowplow === 'function' && Tracker.trackable();
|
||||
},
|
||||
|
||||
/**
|
||||
* Dispatches a structured event per our taxonomy:
|
||||
* https://docs.gitlab.com/ee/development/snowplow/index.html#structured-event-taxonomy.
|
||||
*
|
||||
* If the library is not initialized and events are trying to be
|
||||
* dispatched (data-attributes, load-events), they will be added
|
||||
* to a queue to be flushed afterwards.
|
||||
*
|
||||
* If there is an error when using the library, it will return ´false´
|
||||
* and ´true´ otherwise.
|
||||
*
|
||||
* @param {...any} eventData defined event taxonomy
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
event(...eventData) {
|
||||
if (!Tracker.enabled()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!Tracker.initialized) {
|
||||
Tracker.nonInitializedQueue.push(eventData);
|
||||
return false;
|
||||
}
|
||||
|
||||
return dispatchSnowplowEvent(...eventData);
|
||||
},
|
||||
|
||||
/**
|
||||
* Preloads event definitions.
|
||||
*
|
||||
* @returns {undefined}
|
||||
*/
|
||||
loadDefinitions() {
|
||||
// TODO: fetch definitions from the server and flush the queue
|
||||
// See https://gitlab.com/gitlab-org/gitlab/-/issues/358256
|
||||
Tracker.definitionsLoaded = true;
|
||||
|
||||
while (Tracker.definitionsEventsQueue.length) {
|
||||
Tracker.dispatchFromDefinition(...Tracker.definitionsEventsQueue.shift());
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Dispatches a structured event with data from its event definition.
|
||||
*
|
||||
* @param {String} basename
|
||||
* @param {Object} eventData
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
definition(basename, eventData = {}) {
|
||||
if (!Tracker.enabled()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!(basename in Tracker.definitionsManifest)) {
|
||||
throw new Error(`Missing Snowplow event definition "${basename}"`);
|
||||
}
|
||||
|
||||
return Tracker.dispatchFromDefinition(basename, eventData);
|
||||
},
|
||||
|
||||
/**
|
||||
* Builds an event with data from a valid definition and sends it to
|
||||
* Snowplow. If the definitions are not loaded, it pushes the data to a queue.
|
||||
*
|
||||
* @param {String} basename
|
||||
* @param {Object} eventData
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
dispatchFromDefinition(basename, eventData) {
|
||||
if (!Tracker.definitionsLoaded) {
|
||||
Tracker.definitionsEventsQueue.push([basename, eventData]);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
const eventDefinition = Tracker.definitions.find((definition) => definition.key === basename);
|
||||
|
||||
return Tracker.event(
|
||||
eventData.category ?? eventDefinition.category,
|
||||
eventData.action ?? eventDefinition.action,
|
||||
eventData,
|
||||
);
|
||||
},
|
||||
|
||||
/**
|
||||
* Dispatches any event emitted before initialization.
|
||||
*
|
||||
* @returns {undefined}
|
||||
*/
|
||||
flushPendingEvents() {
|
||||
Tracker.initialized = true;
|
||||
|
||||
while (Tracker.nonInitializedQueue.length) {
|
||||
dispatchSnowplowEvent(...Tracker.nonInitializedQueue.shift());
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Attaches event handlers for data-attributes powered events.
|
||||
*
|
||||
* @param {String} category - the default category for all events
|
||||
* @param {HTMLElement} parent - element containing data-attributes
|
||||
* @returns {Array}
|
||||
*/
|
||||
bindDocument(category = document.body.dataset.page, parent = document) {
|
||||
if (!Tracker.enabled() || parent.trackingBound) {
|
||||
return [];
|
||||
}
|
||||
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
parent.trackingBound = true;
|
||||
|
||||
const handlers = getEventHandlers(category, (...args) => Tracker.event(...args));
|
||||
handlers.forEach((event) => parent.addEventListener(event.name, event.func));
|
||||
|
||||
return handlers;
|
||||
},
|
||||
|
||||
/**
|
||||
* Attaches event handlers for load-events (on render).
|
||||
*
|
||||
* @param {String} category - the default category for all events
|
||||
* @param {HTMLElement} parent - element containing event targets
|
||||
* @returns {Array}
|
||||
*/
|
||||
trackLoadEvents(category = document.body.dataset.page, parent = document) {
|
||||
if (!Tracker.enabled()) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const loadEvents = parent.querySelectorAll(LOAD_ACTION_ATTR_SELECTOR);
|
||||
|
||||
loadEvents.forEach((element) => {
|
||||
const { action, data } = createEventPayload(element);
|
||||
Tracker.event(category, action, data);
|
||||
});
|
||||
|
||||
return loadEvents;
|
||||
},
|
||||
|
||||
/**
|
||||
* Enable Snowplow automatic form tracking.
|
||||
* The config param requires at least one array of either forms
|
||||
* class names, or field name attributes.
|
||||
* https://docs.gitlab.com/ee/development/snowplow/index.html#form-tracking.
|
||||
*
|
||||
* @param {Object} config
|
||||
* @param {Array} contexts
|
||||
* @returns {undefined}
|
||||
*/
|
||||
enableFormTracking(config, contexts = []) {
|
||||
if (!Tracker.enabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!Array.isArray(config?.forms?.allow) && !Array.isArray(config?.fields?.allow)) {
|
||||
// eslint-disable-next-line @gitlab/require-i18n-strings
|
||||
throw new Error('Unable to enable form event tracking without allow rules.');
|
||||
}
|
||||
|
||||
// Ignore default/standard schema
|
||||
const standardContext = getStandardContext();
|
||||
const userProvidedContexts = contexts.filter(
|
||||
(context) => context.schema !== standardContext.schema,
|
||||
);
|
||||
|
||||
const mappedConfig = {};
|
||||
if (config.forms) {
|
||||
mappedConfig.forms = renameKey(config.forms, 'allow', 'whitelist');
|
||||
}
|
||||
|
||||
if (config.fields) {
|
||||
mappedConfig.fields = renameKey(config.fields, 'allow', 'whitelist');
|
||||
}
|
||||
|
||||
const enabler = () => window.snowplow('enableFormTracking', mappedConfig, userProvidedContexts);
|
||||
|
||||
if (document.readyState === 'complete') {
|
||||
enabler();
|
||||
} else {
|
||||
document.addEventListener('readystatechange', () => {
|
||||
if (document.readyState === 'complete') {
|
||||
enabler();
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Replaces the URL and referrer for the default web context
|
||||
* if the replacements are available.
|
||||
*
|
||||
* @returns {undefined}
|
||||
*/
|
||||
setAnonymousUrls() {
|
||||
const { snowplowPseudonymizedPageUrl: pageUrl } = window.gl;
|
||||
|
||||
if (!pageUrl) {
|
||||
return;
|
||||
}
|
||||
|
||||
const referrers = getReferrersCache();
|
||||
const pageLinks = Object.seal({
|
||||
url: pageUrl,
|
||||
referrer: '',
|
||||
originalUrl: window.location.href,
|
||||
});
|
||||
|
||||
const appendHash = Tracker.ALLOWED_URL_HASHES.some((prefix) =>
|
||||
window.location.hash.startsWith(prefix),
|
||||
);
|
||||
const customUrl = `${pageUrl}${appendHash ? window.location.hash : ''}`;
|
||||
window.snowplow('setCustomUrl', customUrl);
|
||||
|
||||
if (document.referrer) {
|
||||
const node = referrers.find((links) => links.originalUrl === document.referrer);
|
||||
|
||||
if (node) {
|
||||
pageLinks.referrer = node.url;
|
||||
window.snowplow('setReferrerUrl', pageLinks.referrer);
|
||||
}
|
||||
}
|
||||
|
||||
addReferrersCacheEntry(referrers, pageLinks);
|
||||
},
|
||||
};
|
|
@ -1,271 +1,7 @@
|
|||
import { LOAD_ACTION_ATTR_SELECTOR } from './constants';
|
||||
import { dispatchSnowplowEvent } from './dispatch_snowplow_event';
|
||||
import getStandardContext from './get_standard_context';
|
||||
import {
|
||||
getEventHandlers,
|
||||
createEventPayload,
|
||||
renameKey,
|
||||
addExperimentContext,
|
||||
getReferrersCache,
|
||||
addReferrersCacheEntry,
|
||||
} from './utils';
|
||||
|
||||
const ALLOWED_URL_HASHES = ['#diff', '#note'];
|
||||
|
||||
export default class Tracking {
|
||||
static nonInitializedQueue = [];
|
||||
static initialized = false;
|
||||
static definitionsLoaded = false;
|
||||
static definitionsManifest = {};
|
||||
static definitionsEventsQueue = [];
|
||||
static definitions = [];
|
||||
|
||||
/**
|
||||
* (Legacy) Determines if tracking is enabled at the user level.
|
||||
* https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/DNT.
|
||||
*
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
static trackable() {
|
||||
return !['1', 'yes'].includes(
|
||||
window.doNotTrack || navigator.doNotTrack || navigator.msDoNotTrack,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if Snowplow is available/enabled.
|
||||
*
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
static enabled() {
|
||||
return typeof window.snowplow === 'function' && this.trackable();
|
||||
}
|
||||
|
||||
/**
|
||||
* Dispatches a structured event per our taxonomy:
|
||||
* https://docs.gitlab.com/ee/development/snowplow/index.html#structured-event-taxonomy.
|
||||
*
|
||||
* If the library is not initialized and events are trying to be
|
||||
* dispatched (data-attributes, load-events), they will be added
|
||||
* to a queue to be flushed afterwards.
|
||||
*
|
||||
* If there is an error when using the library, it will return ´false´
|
||||
* and ´true´ otherwise.
|
||||
*
|
||||
* @param {...any} eventData defined event taxonomy
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
static event(...eventData) {
|
||||
if (!this.enabled()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!this.initialized) {
|
||||
this.nonInitializedQueue.push(eventData);
|
||||
return false;
|
||||
}
|
||||
|
||||
return dispatchSnowplowEvent(...eventData);
|
||||
}
|
||||
|
||||
/**
|
||||
* Preloads event definitions.
|
||||
*
|
||||
* @returns {undefined}
|
||||
*/
|
||||
static loadDefinitions() {
|
||||
// TODO: fetch definitions from the server and flush the queue
|
||||
// See https://gitlab.com/gitlab-org/gitlab/-/issues/358256
|
||||
this.definitionsLoaded = true;
|
||||
|
||||
while (this.definitionsEventsQueue.length) {
|
||||
this.dispatchFromDefinition(...this.definitionsEventsQueue.shift());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Dispatches a structured event with data from its event definition.
|
||||
*
|
||||
* @param {String} basename
|
||||
* @param {Object} eventData
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
static definition(basename, eventData = {}) {
|
||||
if (!this.enabled()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!(basename in this.definitionsManifest)) {
|
||||
throw new Error(`Missing Snowplow event definition "${basename}"`);
|
||||
}
|
||||
|
||||
return this.dispatchFromDefinition(basename, eventData);
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds an event with data from a valid definition and sends it to
|
||||
* Snowplow. If the definitions are not loaded, it pushes the data to a queue.
|
||||
*
|
||||
* @param {String} basename
|
||||
* @param {Object} eventData
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
static dispatchFromDefinition(basename, eventData) {
|
||||
if (!this.definitionsLoaded) {
|
||||
this.definitionsEventsQueue.push([basename, eventData]);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
const eventDefinition = this.definitions.find((definition) => definition.key === basename);
|
||||
|
||||
return this.event(
|
||||
eventData.category ?? eventDefinition.category,
|
||||
eventData.action ?? eventDefinition.action,
|
||||
eventData,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Dispatches any event emitted before initialization.
|
||||
*
|
||||
* @returns {undefined}
|
||||
*/
|
||||
static flushPendingEvents() {
|
||||
this.initialized = true;
|
||||
|
||||
while (this.nonInitializedQueue.length) {
|
||||
dispatchSnowplowEvent(...this.nonInitializedQueue.shift());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Attaches event handlers for data-attributes powered events.
|
||||
*
|
||||
* @param {String} category - the default category for all events
|
||||
* @param {HTMLElement} parent - element containing data-attributes
|
||||
* @returns {Array}
|
||||
*/
|
||||
static bindDocument(category = document.body.dataset.page, parent = document) {
|
||||
if (!this.enabled() || parent.trackingBound) {
|
||||
return [];
|
||||
}
|
||||
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
parent.trackingBound = true;
|
||||
|
||||
const handlers = getEventHandlers(category, (...args) => this.event(...args));
|
||||
handlers.forEach((event) => parent.addEventListener(event.name, event.func));
|
||||
|
||||
return handlers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attaches event handlers for load-events (on render).
|
||||
*
|
||||
* @param {String} category - the default category for all events
|
||||
* @param {HTMLElement} parent - element containing event targets
|
||||
* @returns {Array}
|
||||
*/
|
||||
static trackLoadEvents(category = document.body.dataset.page, parent = document) {
|
||||
if (!this.enabled()) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const loadEvents = parent.querySelectorAll(LOAD_ACTION_ATTR_SELECTOR);
|
||||
|
||||
loadEvents.forEach((element) => {
|
||||
const { action, data } = createEventPayload(element);
|
||||
this.event(category, action, data);
|
||||
});
|
||||
|
||||
return loadEvents;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable Snowplow automatic form tracking.
|
||||
* The config param requires at least one array of either forms
|
||||
* class names, or field name attributes.
|
||||
* https://docs.gitlab.com/ee/development/snowplow/index.html#form-tracking.
|
||||
*
|
||||
* @param {Object} config
|
||||
* @param {Array} contexts
|
||||
* @returns {undefined}
|
||||
*/
|
||||
static enableFormTracking(config, contexts = []) {
|
||||
if (!this.enabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!Array.isArray(config?.forms?.allow) && !Array.isArray(config?.fields?.allow)) {
|
||||
// eslint-disable-next-line @gitlab/require-i18n-strings
|
||||
throw new Error('Unable to enable form event tracking without allow rules.');
|
||||
}
|
||||
|
||||
// Ignore default/standard schema
|
||||
const standardContext = getStandardContext();
|
||||
const userProvidedContexts = contexts.filter(
|
||||
(context) => context.schema !== standardContext.schema,
|
||||
);
|
||||
|
||||
const mappedConfig = {};
|
||||
if (config.forms) {
|
||||
mappedConfig.forms = renameKey(config.forms, 'allow', 'whitelist');
|
||||
}
|
||||
|
||||
if (config.fields) {
|
||||
mappedConfig.fields = renameKey(config.fields, 'allow', 'whitelist');
|
||||
}
|
||||
|
||||
const enabler = () => window.snowplow('enableFormTracking', mappedConfig, userProvidedContexts);
|
||||
|
||||
if (document.readyState === 'complete') {
|
||||
enabler();
|
||||
} else {
|
||||
document.addEventListener('readystatechange', () => {
|
||||
if (document.readyState === 'complete') {
|
||||
enabler();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces the URL and referrer for the default web context
|
||||
* if the replacements are available.
|
||||
*
|
||||
* @returns {undefined}
|
||||
*/
|
||||
static setAnonymousUrls() {
|
||||
const { snowplowPseudonymizedPageUrl: pageUrl } = window.gl;
|
||||
|
||||
if (!pageUrl) {
|
||||
return;
|
||||
}
|
||||
|
||||
const referrers = getReferrersCache();
|
||||
const pageLinks = Object.seal({
|
||||
url: pageUrl,
|
||||
referrer: '',
|
||||
originalUrl: window.location.href,
|
||||
});
|
||||
|
||||
const appendHash = ALLOWED_URL_HASHES.some((prefix) => window.location.hash.startsWith(prefix));
|
||||
const customUrl = `${pageUrl}${appendHash ? window.location.hash : ''}`;
|
||||
window.snowplow('setCustomUrl', customUrl);
|
||||
|
||||
if (document.referrer) {
|
||||
const node = referrers.find((links) => links.originalUrl === document.referrer);
|
||||
|
||||
if (node) {
|
||||
pageLinks.referrer = node.url;
|
||||
window.snowplow('setReferrerUrl', pageLinks.referrer);
|
||||
}
|
||||
}
|
||||
|
||||
addReferrersCacheEntry(referrers, pageLinks);
|
||||
}
|
||||
import { Tracker } from 'jh_else_ce/tracking/tracker';
|
||||
import { addExperimentContext } from './utils';
|
||||
|
||||
const Tracking = Object.assign(Tracker, {
|
||||
/**
|
||||
* Returns an implementation of this class in the form of
|
||||
* a Vue mixin.
|
||||
|
@ -273,7 +9,7 @@ export default class Tracking {
|
|||
* @param {Object} opts - default options for all events
|
||||
* @returns {Object}
|
||||
*/
|
||||
static mixin(opts = {}) {
|
||||
mixin(opts = {}) {
|
||||
return {
|
||||
computed: {
|
||||
trackingCategory() {
|
||||
|
@ -297,5 +33,7 @@ export default class Tracking {
|
|||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
export default Tracking;
|
||||
|
|
|
@ -15,6 +15,7 @@ module Projects
|
|||
feature_category :tracing
|
||||
|
||||
def show
|
||||
render_404 unless Feature.enabled?(:monitor_tracing, @project)
|
||||
end
|
||||
|
||||
private
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
# frozen_string_literal: true
|
||||
module Ci
|
||||
module SecureFilesHelper
|
||||
def show_secure_files_setting(project, user)
|
||||
return false if user.nil?
|
||||
|
||||
Feature.enabled?(:ci_secure_files, project) && user.can?(:read_secure_files, project)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -647,6 +647,7 @@ class ApplicationSetting < ApplicationRecord
|
|||
reset_memoized_terms
|
||||
end
|
||||
after_commit :expire_performance_bar_allowed_user_ids_cache, if: -> { previous_changes.key?('performance_bar_allowed_group_id') }
|
||||
after_commit :reset_deletion_warning_redis_key, if: :saved_change_to_inactive_projects_delete_after_months?
|
||||
|
||||
def validate_grafana_url
|
||||
validate_url(parsed_grafana_url, :grafana_url, GRAFANA_URL_ERROR_MESSAGE)
|
||||
|
@ -777,6 +778,10 @@ class ApplicationSetting < ApplicationRecord
|
|||
)
|
||||
end
|
||||
end
|
||||
|
||||
def reset_deletion_warning_redis_key
|
||||
Gitlab::InactiveProjectsDeletionWarningTracker.reset_all
|
||||
end
|
||||
end
|
||||
|
||||
ApplicationSetting.prepend_mod_with('ApplicationSetting')
|
||||
|
|
|
@ -357,6 +357,8 @@ class Event < ApplicationRecord
|
|||
Project.unscoped.where(id: project_id)
|
||||
.where('last_activity_at <= ?', RESET_PROJECT_ACTIVITY_INTERVAL.ago)
|
||||
.touch_all(:last_activity_at, time: created_at) # rubocop: disable Rails/SkipsModelValidations
|
||||
|
||||
Gitlab::InactiveProjectsDeletionWarningTracker.new(project.id).reset
|
||||
end
|
||||
|
||||
def authored_by?(user)
|
||||
|
|
|
@ -744,6 +744,16 @@ class Project < ApplicationRecord
|
|||
Project.with(cte.to_arel).from(cte.alias_to(Project.arel_table))
|
||||
end
|
||||
|
||||
def self.inactive
|
||||
project_statistics = ::ProjectStatistics.arel_table
|
||||
minimum_size_mb = ::Gitlab::CurrentSettings.inactive_projects_min_size_mb.megabytes
|
||||
last_activity_cutoff = ::Gitlab::CurrentSettings.inactive_projects_send_warning_email_after_months.months.ago
|
||||
|
||||
joins(:statistics)
|
||||
.where((project_statistics[:storage_size]).gt(minimum_size_mb))
|
||||
.where('last_activity_at < ?', last_activity_cutoff)
|
||||
end
|
||||
|
||||
scope :active, -> { joins(:issues, :notes, :merge_requests).order('issues.created_at, notes.created_at, merge_requests.created_at DESC') }
|
||||
scope :abandoned, -> { where('projects.last_activity_at < ?', 6.months.ago) }
|
||||
|
||||
|
|
|
@ -113,6 +113,7 @@ module Notes
|
|||
track_note_creation_usage_for_issues(note) if note.for_issue?
|
||||
track_note_creation_usage_for_merge_requests(note) if note.for_merge_request?
|
||||
track_incident_action(user, note.noteable, 'incident_comment') if note.for_issue?
|
||||
track_note_creation_in_ipynb(note)
|
||||
|
||||
if Feature.enabled?(:notes_create_service_tracking, project)
|
||||
Gitlab::Tracking.event('Notes::CreateService', 'execute', **tracking_data_for(note))
|
||||
|
@ -135,6 +136,16 @@ module Notes
|
|||
def track_note_creation_usage_for_merge_requests(note)
|
||||
Gitlab::UsageDataCounters::MergeRequestActivityUniqueCounter.track_create_comment_action(note: note)
|
||||
end
|
||||
|
||||
def should_track_ipynb_notes?(note)
|
||||
Feature.enabled?(:ipynbdiff_notes_tracker) && note.respond_to?(:diff_file) && note.diff_file&.ipynb?
|
||||
end
|
||||
|
||||
def track_note_creation_in_ipynb(note)
|
||||
return unless should_track_ipynb_notes?(note)
|
||||
|
||||
Gitlab::UsageDataCounters::IpynbDiffActivityCounter.note_created(note)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -109,3 +109,15 @@
|
|||
= link_to _('Learn more'), help_page_path('ci/jobs/ci_job_token'), target: '_blank', rel: 'noopener noreferrer'
|
||||
.settings-content
|
||||
= render 'ci/token_access/index'
|
||||
|
||||
- if show_secure_files_setting(@project, current_user)
|
||||
%section.settings
|
||||
.settings-header
|
||||
%h4.settings-title
|
||||
= _("Secure Files")
|
||||
= button_to project_ci_secure_files_path(@project), method: :get, class: 'btn gl-button btn-default' do
|
||||
= _('Manage')
|
||||
%p
|
||||
= _("Use Secure Files to store files used by your pipelines such as Android keystores, or Apple provisioning profiles and signing certificates.")
|
||||
= link_to _('Learn more'), help_page_path('ci/secure_files/index'), target: '_blank', rel: 'noopener noreferrer'
|
||||
|
||||
|
|
|
@ -15,10 +15,12 @@
|
|||
= s_('Deprecations|Feature deprecation and removal')
|
||||
.gl-alert-body
|
||||
%p
|
||||
= html_escape(s_('Deprecations|The metrics feature was deprecated in GitLab 14.7. The logs and tracing features were also deprecated in GitLab 14.7, and are %{removal_link_start} scheduled for removal %{link_end} in GitLab 15.0. For information on a possible replacement, %{opstrace_link_start} learn more about Opstrace %{link_end}.')) % {removal_link_start: removal_epic_link_start, opstrace_link_start: opstrace_link_start, link_end: link_end }
|
||||
= html_escape(s_('Deprecations|The metrics feature was deprecated in GitLab 14.7.'))
|
||||
= html_escape(s_('Deprecations|The logs and tracing features were also deprecated in GitLab 14.7, and are %{removal_link_start} scheduled for removal %{link_end} in GitLab 15.0.')) % {removal_link_start: removal_epic_link_start, link_end: link_end } if Feature.enabled?(:monitor_tracing, @project)
|
||||
= html_escape(s_('Deprecations|For information on a possible replacement, %{opstrace_link_start} learn more about Opstrace %{link_end}.')) % {opstrace_link_start: opstrace_link_start, link_end: link_end }
|
||||
|
||||
= render 'projects/settings/operations/metrics_dashboard'
|
||||
= render 'projects/settings/operations/tracing'
|
||||
= render 'projects/settings/operations/tracing' if Feature.enabled?(:monitor_tracing, @project)
|
||||
= render 'projects/settings/operations/error_tracking'
|
||||
= render 'projects/settings/operations/alert_management'
|
||||
= render 'projects/settings/operations/incidents'
|
||||
|
|
|
@ -579,6 +579,15 @@
|
|||
:weight: 1
|
||||
:idempotent:
|
||||
:tags: []
|
||||
- :name: cronjob:projects_inactive_projects_deletion_cron
|
||||
:worker_name: Projects::InactiveProjectsDeletionCronWorker
|
||||
:feature_category: :compliance_management
|
||||
:has_external_dependencies:
|
||||
:urgency: :low
|
||||
:resource_boundary: :unknown
|
||||
:weight: 1
|
||||
:idempotent: true
|
||||
:tags: []
|
||||
- :name: cronjob:projects_schedule_refresh_build_artifacts_size_statistics
|
||||
:worker_name: Projects::ScheduleRefreshBuildArtifactsSizeStatisticsWorker
|
||||
:feature_category: :build_artifacts
|
||||
|
@ -2803,6 +2812,15 @@
|
|||
:weight: 1
|
||||
:idempotent:
|
||||
:tags: []
|
||||
- :name: projects_inactive_projects_deletion_notification
|
||||
:worker_name: Projects::InactiveProjectsDeletionNotificationWorker
|
||||
:feature_category: :compliance_management
|
||||
:has_external_dependencies:
|
||||
:urgency: :low
|
||||
:resource_boundary: :unknown
|
||||
:weight: 1
|
||||
:idempotent: true
|
||||
:tags: []
|
||||
- :name: projects_post_creation
|
||||
:worker_name: Projects::PostCreationWorker
|
||||
:feature_category: :source_code_management
|
||||
|
|
|
@ -0,0 +1,73 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Projects
|
||||
class InactiveProjectsDeletionCronWorker
|
||||
include ApplicationWorker
|
||||
include Gitlab::Utils::StrongMemoize
|
||||
include CronjobQueue
|
||||
|
||||
idempotent!
|
||||
data_consistency :always
|
||||
feature_category :compliance_management
|
||||
|
||||
INTERVAL = 2.seconds.to_i
|
||||
|
||||
def perform
|
||||
return unless ::Gitlab::CurrentSettings.delete_inactive_projects?
|
||||
|
||||
admin_user = User.admins.active.first
|
||||
|
||||
return unless admin_user
|
||||
|
||||
notified_inactive_projects = Gitlab::InactiveProjectsDeletionWarningTracker.notified_projects
|
||||
|
||||
Project.inactive.without_deleted.find_each(batch_size: 100).with_index do |project, index| # rubocop: disable CodeReuse/ActiveRecord
|
||||
next unless Feature.enabled?(:inactive_projects_deletion, project.root_namespace)
|
||||
|
||||
delay = index * INTERVAL
|
||||
|
||||
with_context(project: project, user: admin_user) do
|
||||
deletion_warning_email_sent_on = notified_inactive_projects["project:#{project.id}"]
|
||||
|
||||
if send_deletion_warning_email?(deletion_warning_email_sent_on, project)
|
||||
send_notification(delay, project, admin_user)
|
||||
elsif deletion_warning_email_sent_on && delete_due_to_inactivity?(deletion_warning_email_sent_on)
|
||||
Gitlab::InactiveProjectsDeletionWarningTracker.new(project.id).reset
|
||||
delete_project(project, admin_user)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def grace_months_after_deletion_notification
|
||||
strong_memoize(:grace_months_after_deletion_notification) do
|
||||
(::Gitlab::CurrentSettings.inactive_projects_delete_after_months -
|
||||
::Gitlab::CurrentSettings.inactive_projects_send_warning_email_after_months).months
|
||||
end
|
||||
end
|
||||
|
||||
def send_deletion_warning_email?(deletion_warning_email_sent_on, project)
|
||||
deletion_warning_email_sent_on.blank?
|
||||
end
|
||||
|
||||
def delete_due_to_inactivity?(deletion_warning_email_sent_on)
|
||||
deletion_warning_email_sent_on < grace_months_after_deletion_notification.ago
|
||||
end
|
||||
|
||||
def deletion_date
|
||||
grace_months_after_deletion_notification.from_now.to_date.to_s
|
||||
end
|
||||
|
||||
def delete_project(project, user)
|
||||
::Projects::DestroyService.new(project, user, {}).async_execute
|
||||
end
|
||||
|
||||
def send_notification(delay, project, user)
|
||||
::Projects::InactiveProjectsDeletionNotificationWorker.perform_in(delay, project.id, deletion_date)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Projects::InactiveProjectsDeletionCronWorker.prepend_mod
|
|
@ -0,0 +1,31 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Projects
|
||||
class InactiveProjectsDeletionNotificationWorker
|
||||
include ApplicationWorker
|
||||
include ExceptionBacktrace
|
||||
|
||||
idempotent!
|
||||
data_consistency :sticky
|
||||
sidekiq_options retry: 3
|
||||
feature_category :compliance_management
|
||||
|
||||
def perform(project_id, deletion_date)
|
||||
return if Gitlab::InactiveProjectsDeletionWarningTracker.new(project_id).notified?
|
||||
|
||||
project = Project.find(project_id)
|
||||
|
||||
notification_service.inactive_project_deletion_warning(project, deletion_date)
|
||||
|
||||
Gitlab::InactiveProjectsDeletionWarningTracker.new(project_id).mark_notified
|
||||
rescue ActiveRecord::RecordNotFound => error
|
||||
Gitlab::ErrorTracking.log_exception(error, project_id: project_id)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def notification_service
|
||||
@notification_service ||= NotificationService.new
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,8 @@
|
|||
---
|
||||
name: inactive_projects_deletion
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/85689
|
||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/357968
|
||||
milestone: '15.0'
|
||||
type: development
|
||||
group: group::compliance
|
||||
default_enabled: false
|
|
@ -0,0 +1,8 @@
|
|||
---
|
||||
name: ipynbdiff_notes_tracker
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/85398
|
||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/362232
|
||||
milestone: '15.0'
|
||||
type: development
|
||||
group: group::incubation
|
||||
default_enabled: false
|
|
@ -0,0 +1,8 @@
|
|||
---
|
||||
name: monitor_tracing
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/85877
|
||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/359904
|
||||
milestone: '15.0'
|
||||
type: development
|
||||
group: group::respond
|
||||
default_enabled: false
|
|
@ -626,6 +626,9 @@ Settings.cron_jobs['clusters_integrations_check_prometheus_health_worker']['job_
|
|||
Settings.cron_jobs['projects_schedule_refresh_build_artifacts_size_statistics_worker'] ||= Settingslogic.new({})
|
||||
Settings.cron_jobs['projects_schedule_refresh_build_artifacts_size_statistics_worker']['cron'] ||= '2/17 * * * *'
|
||||
Settings.cron_jobs['projects_schedule_refresh_build_artifacts_size_statistics_worker']['job_class'] = 'Projects::ScheduleRefreshBuildArtifactsSizeStatisticsWorker'
|
||||
Settings.cron_jobs['inactive_projects_deletion_cron_worker'] ||= Settingslogic.new({})
|
||||
Settings.cron_jobs['inactive_projects_deletion_cron_worker']['cron'] ||= '0 1 * * *'
|
||||
Settings.cron_jobs['inactive_projects_deletion_cron_worker']['job_class'] = 'Projects::InactiveProjectsDeletionCronWorker'
|
||||
|
||||
Gitlab.ee do
|
||||
Settings.cron_jobs['analytics_devops_adoption_create_all_snapshots_worker'] ||= Settingslogic.new({})
|
||||
|
|
|
@ -75,6 +75,12 @@
|
|||
- 'i_code_review_post_merge_submit_cherry_pick_modal'
|
||||
- 'i_code_review_user_jetbrains_api_request'
|
||||
- 'i_code_review_user_gitlab_cli_api_request'
|
||||
- 'i_code_review_user_create_note_in_ipynb_diff'
|
||||
- 'i_code_review_user_create_note_in_ipynb_diff_mr'
|
||||
- 'i_code_review_user_create_note_in_ipynb_diff_commit'
|
||||
- 'i_code_review_create_note_in_ipynb_diff'
|
||||
- 'i_code_review_create_note_in_ipynb_diff_mr'
|
||||
- 'i_code_review_create_note_in_ipynb_diff_commit'
|
||||
- name: code_review_category_monthly_active_users
|
||||
operator: OR
|
||||
source: redis
|
||||
|
@ -140,6 +146,12 @@
|
|||
- 'i_code_review_post_merge_click_cherry_pick'
|
||||
- 'i_code_review_post_merge_submit_revert_modal'
|
||||
- 'i_code_review_post_merge_submit_cherry_pick_modal'
|
||||
- 'i_code_review_user_create_note_in_ipynb_diff'
|
||||
- 'i_code_review_user_create_note_in_ipynb_diff_mr'
|
||||
- 'i_code_review_user_create_note_in_ipynb_diff_commit'
|
||||
- 'i_code_review_create_note_in_ipynb_diff'
|
||||
- 'i_code_review_create_note_in_ipynb_diff_mr'
|
||||
- 'i_code_review_create_note_in_ipynb_diff_commit'
|
||||
- name: code_review_extension_category_monthly_active_users
|
||||
operator: OR
|
||||
source: redis
|
||||
|
|
|
@ -361,6 +361,8 @@
|
|||
- 1
|
||||
- - projects_git_garbage_collect
|
||||
- 1
|
||||
- - projects_inactive_projects_deletion_notification
|
||||
- 1
|
||||
- - projects_post_creation
|
||||
- 1
|
||||
- - projects_process_sync_events
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
- name: "Pseudonymizer"
|
||||
announcement_milestone: "14.7"
|
||||
announcement_date: "2022-01-22"
|
||||
removal_milestone: "15.0"
|
||||
removal_date: "2022-05-22"
|
||||
breaking_change: true
|
||||
body: | # Do not modify this line, instead modify the lines below.
|
||||
The Pseudonymizer feature is generally unused, can cause production issues with large databases, and can interfere with object storage development.
|
||||
It was removed in GitLab 15.0.
|
||||
stage: Enablement
|
||||
tiers: [Free, Premium, Ultimate]
|
||||
documentation_url: "https://docs.gitlab.com/ee/administration/pseudonymizer.html"
|
||||
issue_url: "https://gitlab.com/gitlab-org/gitlab/-/issues/219952"
|
|
@ -0,0 +1,10 @@
|
|||
- name: "SUSE Linux Enterprise Server 12 SP2"
|
||||
announcement_milestone: "14.5" # The milestone when this feature was first announced as deprecated.
|
||||
announcement_date: "2021-11-22"
|
||||
removal_milestone: "15.0" # the milestone when this feature is planned to be removed
|
||||
removal_date: "2022-05-22" # the date of the milestone release when this feature is planned to be removed
|
||||
breaking_change: true
|
||||
body: | # Do not modify this line, instead modify the lines below.
|
||||
Long term service and support (LTSS) for SUSE Linux Enterprise Server (SLES) 12 SP2 [ended on March 31, 2021](https://www.suse.com/lifecycle/). The CA certificates on SP2 include the expired DST root certificate, and it's not getting new CA certificate package updates. We have implemented some [workarounds](https://gitlab.com/gitlab-org/gitlab-omnibus-builder/-/merge_requests/191), but we will not be able to continue to keep the build running properly.
|
||||
stage: Enablement
|
||||
tiers: [Free, Premium, Ultimate]
|
|
@ -0,0 +1,12 @@
|
|||
- name: "Move `custom_hooks_dir` setting from GitLab Shell to Gitaly"
|
||||
announcement_milestone: "14.9"
|
||||
announcement_date: "2022-03-22"
|
||||
removal_milestone: "15.0"
|
||||
removal_date: "2022-05-22"
|
||||
breaking_change: true
|
||||
body: | # Do not modify this line, instead modify the lines below.
|
||||
The [`custom_hooks_dir`](https://docs.gitlab.com/ee/administration/server_hooks.html#create-a-global-server-hook-for-all-repositories) setting is now configured in Gitaly, and is removed from GitLab Shell in GitLab 15.0.
|
||||
stage: Enablement
|
||||
tiers: [Free, Premium, Ultimate]
|
||||
issue_url: https://gitlab.com/gitlab-org/omnibus-gitlab/-/merge_requests/4208
|
||||
documentation_url: https://docs.gitlab.com/ee/administration/server_hooks.html#create-a-global-server-hook-for-all-repositories
|
|
@ -0,0 +1,13 @@
|
|||
- name: "Support for `gitaly['internal_socket_dir']`"
|
||||
announcement_milestone: "14.10"
|
||||
announcement_date: "2022-04-22"
|
||||
removal_milestone: "15.0"
|
||||
removal_date: "2022-05-22"
|
||||
breaking_change: true
|
||||
body: | # Do not modify this line, instead modify the lines below.
|
||||
Gitaly introduced a new directory that holds all runtime data Gitaly requires to operate correctly. This new directory replaces the old internal socket directory, and consequentially the usage of `gitaly['internal_socket_dir']` was deprecated in favor of `gitaly['runtime_dir']`.
|
||||
|
||||
stage: Enablement
|
||||
tiers: [Free, Premium, Ultimate]
|
||||
issue_url: https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/6758
|
||||
documentation_url: https://docs.gitlab.com/omnibus/update/gitlab_15_changes.html#removing-support-for-gitalys-internal-socket-path
|
|
@ -0,0 +1,11 @@
|
|||
- name: "Move Gitaly Cluster Praefect `database_host_no_proxy` and `database_port_no_proxy configs`"
|
||||
announcement_milestone: "14.0"
|
||||
announcement_date: "2021-05-22"
|
||||
removal_milestone: "15.0"
|
||||
removal_date: "2022-05-22"
|
||||
breaking_change: true
|
||||
body: | # Do not modify this line, instead modify the lines below.
|
||||
The Gitaly Cluster configuration keys for `praefect['database_host_no_proxy']` and `praefect['database_port_no_proxy']` are replaced with `praefect['database_direct_host']` and `praefect['database_direct_port']`.
|
||||
stage: Enablement
|
||||
tiers: [Free, Premium, Ultimate]
|
||||
issue_url: https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/6150
|
|
@ -7,7 +7,6 @@ class AddIndexToVulnerabilityFeedbackFindingUuid < Gitlab::Database::Migration[2
|
|||
|
||||
# We are indexing on UUID, a hash index should be smaller and faster
|
||||
# details on https://gitlab.com/gitlab-org/gitlab/-/merge_requests/86808#note_943330140
|
||||
# rubocop:disable Migration/HashIndex
|
||||
def up
|
||||
add_concurrent_index :vulnerability_feedback, :finding_uuid, using: :hash, name: INDEX_NAME
|
||||
end
|
||||
|
@ -15,5 +14,4 @@ class AddIndexToVulnerabilityFeedbackFindingUuid < Gitlab::Database::Migration[2
|
|||
def down
|
||||
remove_concurrent_index :vulnerability_feedback, :finding_uuid, using: :hash, name: INDEX_NAME
|
||||
end
|
||||
# rubocop:enable Migration/HashIndex
|
||||
end
|
||||
|
|
|
@ -26,7 +26,7 @@ Read more about update policies and warnings in the PostgreSQL
|
|||
|
||||
| GitLab version | PostgreSQL versions | Default version for fresh installs | Default version for upgrades | Notes |
|
||||
| -------------- | --------------------- | ---------------------------------- | ---------------------------- | ----- |
|
||||
| 15.0 | 12.7, 13.3 | 13.3 | 13.3 | Users can manually upgrade to 13.3 following the [upgrade docs](https://docs.gitlab.com/omnibus/settings/database.html#gitlab-150-and-later). |
|
||||
| 15.0 | 12.10, 13.6 | 13.6 | 13.6 | Users can manually upgrade to 13.6 following the [upgrade docs](https://docs.gitlab.com/omnibus/settings/database.html#gitlab-150-and-later). |
|
||||
| 14.1 | 12.7, 13.3 | 12.7 | 12.7 | PostgreSQL 13 available for fresh installations if not using [Geo](../geo/index.md#requirements-for-running-geo) or [Patroni](../postgresql/index.md#postgresql-replication-and-failover-with-omnibus-gitlab).
|
||||
| 14.0 | 12.7 | 12.7 | 12.7 | HA installations with repmgr are no longer supported and will be prevented from upgrading to Omnibus GitLab 14.0 |
|
||||
| 13.8 | 11.9, 12.4 | 12.4 | 12.4 | Package upgrades automatically performed PostgreSQL upgrade for nodes that are not part of a Geo or HA cluster.). |
|
||||
|
|
|
@ -108,7 +108,7 @@ Group labels specify which [groups](https://about.gitlab.com/company/team/struct
|
|||
|
||||
It's highly recommended to add a group label, as it's used by our triage
|
||||
automation to
|
||||
[infer the correct stage label](https://about.gitlab.com/handbook/engineering/quality/triage-operations/#auto-labelling-of-issues).
|
||||
[infer the correct stage label](https://about.gitlab.com/handbook/engineering/quality/triage-operations/#auto-labelling-of-issues-and-merge-requests).
|
||||
|
||||
#### Naming and color convention
|
||||
|
||||
|
|
|
@ -71,9 +71,7 @@ GITLAB_TRACING=opentracing://<driver>?<param_name>=<param_value>&<param_name_2>=
|
|||
|
||||
In this example, we have the following hypothetical values:
|
||||
|
||||
- `driver`: the driver. [GitLab supports
|
||||
`jaeger`](../operations/tracing.md). In future, other
|
||||
tracing implementations may also be supported.
|
||||
- `driver`: the driver such a jaegar.
|
||||
- `param_name`, `param_value`: these are driver specific configuration values. Configuration
|
||||
parameters for Jaeger are documented [further on in this
|
||||
document](#2-configure-the-gitlab_tracing-environment-variable) they should be URL encoded.
|
||||
|
|
|
@ -4,14 +4,21 @@ group: Respond
|
|||
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
|
||||
---
|
||||
|
||||
# Tracing (DEPRECATED) **(FREE)**
|
||||
# Tracing (DEPRECATED) **(FREE SELF)**
|
||||
|
||||
> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/42645) from GitLab Ultimate to GitLab Free in 13.5.
|
||||
> - [Deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/346540) in GitLab 14.7.
|
||||
> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/359904) behind a [feature flag](../administration/feature_flags.md) named `monitor_tracing` in GitLab 15.0. Disabled by default.
|
||||
|
||||
WARNING:
|
||||
This feature is in its end-of-life process. It is [deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/346540)
|
||||
in GitLab 14.7, and is planned for removal in GitLab 15.0.
|
||||
in GitLab 14.7.
|
||||
It will be removed completely in GitLab 15.2.
|
||||
|
||||
FLAG:
|
||||
On self-managed GitLab, by default this feature is not available. To make it available, ask an administrator to [enable the feature flag](../administration/feature_flags.md) named `monitor_tracing`.
|
||||
On GitLab.com, this feature is not available.
|
||||
This feature is not recommended for production use.
|
||||
|
||||
Tracing provides insight into the performance and health of a deployed application, tracking each
|
||||
function or microservice that handles a given request. Tracing makes it easy to understand the
|
||||
|
|
|
@ -127,7 +127,9 @@ or upgrade command:
|
|||
```
|
||||
|
||||
1. Install the specific `gitlab-ee` package by using one of the following commands
|
||||
and replacing `<version>` with the version you found in the previous step:
|
||||
and replacing `<version>` with the next supported version you would like to install
|
||||
(make sure to review the [upgrade path](../index.md#upgrade-paths) to confirm the
|
||||
version you're installing is part of a supported path):
|
||||
|
||||
```shell
|
||||
# Ubuntu/Debian
|
||||
|
|
|
@ -216,6 +216,26 @@ In GitLab 13.0, we introduced new project and design replication details routes
|
|||
|
||||
We have now removed the deprecated legacy names for approval status of license policy (`blacklisted`, `approved`) in the API queries and responses. If you are using our License Compliance API you should stop using the `approved` and `blacklisted` query parameters, they are now `allowed` and `denied`. In 15.0 the responses will also stop using `approved` and `blacklisted` so you may need to adjust any of your custom tools.
|
||||
|
||||
### Move Gitaly Cluster Praefect `database_host_no_proxy` and `database_port_no_proxy configs`
|
||||
|
||||
WARNING:
|
||||
This feature was changed or removed in 15.0
|
||||
as a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
|
||||
Before updating GitLab, review the details carefully to determine if you need to make any
|
||||
changes to your code, settings, or workflow.
|
||||
|
||||
The Gitaly Cluster configuration keys for `praefect['database_host_no_proxy']` and `praefect['database_port_no_proxy']` are replaced with `praefect['database_direct_host']` and `praefect['database_direct_port']`.
|
||||
|
||||
### Move `custom_hooks_dir` setting from GitLab Shell to Gitaly
|
||||
|
||||
WARNING:
|
||||
This feature was changed or removed in 15.0
|
||||
as a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
|
||||
Before updating GitLab, review the details carefully to determine if you need to make any
|
||||
changes to your code, settings, or workflow.
|
||||
|
||||
The [`custom_hooks_dir`](https://docs.gitlab.com/ee/administration/server_hooks.html#create-a-global-server-hook-for-all-repositories) setting is now configured in Gitaly, and is removed from GitLab Shell in GitLab 15.0.
|
||||
|
||||
### OAuth implicit grant
|
||||
|
||||
WARNING:
|
||||
|
@ -261,6 +281,17 @@ changes to your code, settings, or workflow.
|
|||
Allowing expired personal access tokens to be used is unusual from a security perspective and could create unusual situations where an
|
||||
expired key is unintentionally able to be used. Unexpected behavior in a security feature is inherently dangerous and so we now do not let expired personal access tokens be used.
|
||||
|
||||
### Pseudonymizer
|
||||
|
||||
WARNING:
|
||||
This feature was changed or removed in 15.0
|
||||
as a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
|
||||
Before updating GitLab, review the details carefully to determine if you need to make any
|
||||
changes to your code, settings, or workflow.
|
||||
|
||||
The Pseudonymizer feature is generally unused, can cause production issues with large databases, and can interfere with object storage development.
|
||||
It was removed in GitLab 15.0.
|
||||
|
||||
### Remove Versions from PackageType
|
||||
|
||||
WARNING:
|
||||
|
@ -410,6 +441,16 @@ Version 3 was [announced in GitLab 14.6](https://about.gitlab.com/releases/2021/
|
|||
|
||||
If you rely on .NET 2.1 support being present in the analyzer image by default, you must take action as detailed in the [deprecation issue for this change](https://gitlab.com/gitlab-org/gitlab/-/issues/352553#breaking-change).
|
||||
|
||||
### SUSE Linux Enterprise Server 12 SP2
|
||||
|
||||
WARNING:
|
||||
This feature was changed or removed in 15.0
|
||||
as a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
|
||||
Before updating GitLab, review the details carefully to determine if you need to make any
|
||||
changes to your code, settings, or workflow.
|
||||
|
||||
Long term service and support (LTSS) for SUSE Linux Enterprise Server (SLES) 12 SP2 [ended on March 31, 2021](https://www.suse.com/lifecycle/). The CA certificates on SP2 include the expired DST root certificate, and it's not getting new CA certificate package updates. We have implemented some [workarounds](https://gitlab.com/gitlab-org/gitlab-omnibus-builder/-/merge_requests/191), but we will not be able to continue to keep the build running properly.
|
||||
|
||||
### Sidekiq configuration for metrics and health checks
|
||||
|
||||
WARNING:
|
||||
|
@ -436,6 +477,16 @@ If you installed GitLab from source, verify manually that both servers are confi
|
|||
|
||||
The Static Site Editor was deprecated in GitLab 14.7 and the feature is being removed in GitLab 15.0. Incoming requests to the Static Site Editor will be redirected and open the target file to edit in the Web IDE. Current users of the Static Site Editor can view the [documentation](https://docs.gitlab.com/ee/user/project/static_site_editor/) for more information, including how to remove the configuration files from existing projects. We will continue investing in improvements to the Markdown editing experience by [maturing the Content Editor](https://gitlab.com/groups/gitlab-org/-/epics/5401) and making it available as a way to edit content across GitLab.
|
||||
|
||||
### Support for `gitaly['internal_socket_dir']`
|
||||
|
||||
WARNING:
|
||||
This feature was changed or removed in 15.0
|
||||
as a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
|
||||
Before updating GitLab, review the details carefully to determine if you need to make any
|
||||
changes to your code, settings, or workflow.
|
||||
|
||||
Gitaly introduced a new directory that holds all runtime data Gitaly requires to operate correctly. This new directory replaces the old internal socket directory, and consequentially the usage of `gitaly['internal_socket_dir']` was deprecated in favor of `gitaly['runtime_dir']`.
|
||||
|
||||
### Support for legacy format of `config/database.yml` removed
|
||||
|
||||
WARNING:
|
||||
|
|
|
@ -85,7 +85,9 @@ This rule enforces the defined actions and schedules a scan on the provided date
|
|||
| `type` | `string` | `schedule` | The rule's type. |
|
||||
| `branches` | `array` of `string` | `*` or the branch's name | The branch the given policy applies to (supports wildcard). |
|
||||
| `cadence` | `string` | CRON expression (for example, `0 0 * * *`) | A whitespace-separated string containing five fields that represents the scheduled time. |
|
||||
| `clusters` | `object` | | The cluster where the given policy enforces running selected scans (only for `container_scanning`/`cluster_image_scanning` scans). The key of the object is the name of the Kubernetes cluster configured for your project in GitLab. In the optionally provided value of the object, you can precisely select Kubernetes resources that are scanned. |
|
||||
| `agents` | `object` | | The name of the [GitLab agents](../../clusters/agent/index.md) where [cluster image scanning](../../clusters/agent/vulnerabilities.md) will run. The key of the object is the name of the Kubernetes cluster configured for your project in GitLab. In the optionally provided value of the object, you can precisely select Kubernetes resources that are scanned. | <!--- start_remove The following content will be removed on remove_date: '2022-08-22' -->
|
||||
| `clusters` (removed) | `object` | | This field was [removed](https://gitlab.com/gitlab-org/gitlab/-/issues/356465) in 15.0. Use the `agents` field instead. The cluster where the given policy enforces running selected scans (only for `container_scanning`/`cluster_image_scanning` scans). The key of the object is the name of the Kubernetes cluster configured for your project in GitLab. In the optionally provided value of the object, you can precisely select Kubernetes resources that are scanned. |
|
||||
<!--- end_remove -->
|
||||
|
||||
GitLab supports the following types of CRON syntax for the `cadence` field:
|
||||
|
||||
|
@ -94,7 +96,20 @@ GitLab supports the following types of CRON syntax for the `cadence` field:
|
|||
|
||||
It is possible that other elements of the CRON syntax will work in the cadence field, however, GitLab does not officially test or support them.
|
||||
|
||||
### `cluster` schema
|
||||
### `agent` schema
|
||||
|
||||
Use this schema to define `agents` objects in the [`schedule` rule type](#schedule-rule-type).
|
||||
|
||||
| Field | Type | Possible values | Description |
|
||||
|--------------|---------------------|--------------------------|-------------|
|
||||
| `namespaces` | `array` of `string` | | The namespace that is scanned. If empty, all namespaces will be scanned. |
|
||||
|
||||
<!--- start_remove The following content will be removed on remove_date: '2022-08-22' -->
|
||||
|
||||
### `cluster` schema (removed)
|
||||
|
||||
This schema was [removed](https://gitlab.com/gitlab-org/gitlab/-/issues/356465) in 15.0.
|
||||
Use the [`agent` schema](#agent-schema) instead.
|
||||
|
||||
Use this schema to define `clusters` objects in the [`schedule` rule type](#schedule-rule-type).
|
||||
|
||||
|
@ -105,6 +120,8 @@ Use this schema to define `clusters` objects in the [`schedule` rule type](#sche
|
|||
| `namespaces` | `array` of `string` | | The namespace that is scanned (only the first value is currently supported). |
|
||||
| `kinds` | `array` of `string` | `deployment`/`daemonset` | The resource kind that should be scanned (only the first value is currently supported). |
|
||||
|
||||
<!--- end_remove -->
|
||||
|
||||
## `scan` action type
|
||||
|
||||
This action executes the selected `scan` with additional parameters when conditions for at least one
|
||||
|
|
|
@ -560,10 +560,6 @@ Automatically [create](../../../operations/incident_management/incidents.md#crea
|
|||
|
||||
Configure Error Tracking to discover and view [Sentry errors within GitLab](../../../operations/error_tracking.md).
|
||||
|
||||
### Jaeger tracing
|
||||
|
||||
Add the URL of a Jaeger server to allow your users to [easily access the Jaeger UI from within GitLab](../../../operations/tracing.md).
|
||||
|
||||
### Status Page **(ULTIMATE)**
|
||||
|
||||
[Add Storage credentials](../../../operations/incident_management/status_page.md#sync-incidents-to-the-status-page)
|
||||
|
|
|
@ -31,7 +31,7 @@ kics-iac-sast:
|
|||
image:
|
||||
name: "$SAST_ANALYZER_IMAGE"
|
||||
variables:
|
||||
SAST_ANALYZER_IMAGE_TAG: 1
|
||||
SAST_ANALYZER_IMAGE_TAG: 2
|
||||
SAST_ANALYZER_IMAGE: "$SECURE_ANALYZERS_PREFIX/kics:$SAST_ANALYZER_IMAGE_TAG$SAST_IMAGE_SUFFIX"
|
||||
rules:
|
||||
- if: $SAST_DISABLED
|
||||
|
|
|
@ -31,7 +31,7 @@ kics-iac-sast:
|
|||
image:
|
||||
name: "$SAST_ANALYZER_IMAGE"
|
||||
variables:
|
||||
SAST_ANALYZER_IMAGE_TAG: 1
|
||||
SAST_ANALYZER_IMAGE_TAG: 2
|
||||
SAST_ANALYZER_IMAGE: "$SECURE_ANALYZERS_PREFIX/kics:$SAST_ANALYZER_IMAGE_TAG$SAST_IMAGE_SUFFIX"
|
||||
rules:
|
||||
- if: $SAST_DISABLED
|
||||
|
|
|
@ -386,6 +386,10 @@ module Gitlab
|
|||
strong_memoize(:rendered) { Rendered::Notebook::DiffFile.new(self) }
|
||||
end
|
||||
|
||||
def ipynb?
|
||||
file_path.ends_with?('.ipynb')
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def diffable_by_attribute?
|
||||
|
@ -415,10 +419,6 @@ module Gitlab
|
|||
new_file? || deleted_file? || content_changed?
|
||||
end
|
||||
|
||||
def ipynb?
|
||||
file_path.ends_with?('.ipynb')
|
||||
end
|
||||
|
||||
# We can't use Object#try because Blob doesn't inherit from Object, but
|
||||
# from BasicObject (via SimpleDelegator).
|
||||
def try_blobs(meth)
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Gitlab
|
||||
class InactiveProjectsDeletionWarningTracker
|
||||
attr_reader :project_id
|
||||
|
||||
DELETION_TRACKING_REDIS_KEY = 'inactive_projects_deletion_warning_email_notified'
|
||||
|
||||
# Redis key 'inactive_projects_deletion_warning_email_notified' is a hash. It stores the date when the
|
||||
# deletion warning notification email was sent for an inactive project. The fields and values look like:
|
||||
# {"project:1"=>"2022-04-22", "project:5"=>"2022-04-22", "project:7"=>"2022-04-25"}
|
||||
# @return [Hash]
|
||||
def self.notified_projects
|
||||
Gitlab::Redis::SharedState.with do |redis|
|
||||
redis.hgetall(DELETION_TRACKING_REDIS_KEY)
|
||||
end
|
||||
end
|
||||
|
||||
def self.reset_all
|
||||
Gitlab::Redis::SharedState.with do |redis|
|
||||
redis.del(DELETION_TRACKING_REDIS_KEY)
|
||||
end
|
||||
end
|
||||
|
||||
def initialize(project_id)
|
||||
@project_id = project_id
|
||||
end
|
||||
|
||||
def notified?
|
||||
Gitlab::Redis::SharedState.with do |redis|
|
||||
redis.hexists(DELETION_TRACKING_REDIS_KEY, "project:#{project_id}")
|
||||
end
|
||||
end
|
||||
|
||||
def mark_notified
|
||||
Gitlab::Redis::SharedState.with do |redis|
|
||||
redis.hset(DELETION_TRACKING_REDIS_KEY, "project:#{project_id}", Date.current)
|
||||
end
|
||||
end
|
||||
|
||||
def reset
|
||||
Gitlab::Redis::SharedState.with do |redis|
|
||||
redis.hdel(DELETION_TRACKING_REDIS_KEY, "project:#{project_id}")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,36 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
# noinspection RubyConstantNamingConvention
|
||||
module Gitlab
|
||||
module UsageDataCounters
|
||||
module IpynbDiffActivityCounter
|
||||
NOTE_CREATED_IN_IPYNB_DIFF_ACTION = 'i_code_review_create_note_in_ipynb_diff'
|
||||
USER_CREATED_NOTE_IN_IPYNB_DIFF_ACTION = 'i_code_review_user_create_note_in_ipynb_diff'
|
||||
NOTE_CREATED_IN_IPYNB_DIFF_MR_ACTION = 'i_code_review_create_note_in_ipynb_diff_mr'
|
||||
USER_CREATED_NOTE_IN_IPYNB_DIFF_MR_ACTION = 'i_code_review_user_create_note_in_ipynb_diff_mr'
|
||||
NOTE_CREATED_IN_IPYNB_DIFF_COMMIT_ACTION = 'i_code_review_create_note_in_ipynb_diff_commit'
|
||||
USER_CREATED_NOTE_IN_IPYNB_DIFF_COMMIT_ACTION = 'i_code_review_user_create_note_in_ipynb_diff_commit'
|
||||
|
||||
class << self
|
||||
def note_created(note)
|
||||
return unless note.for_merge_request? || note.for_commit?
|
||||
|
||||
if note.for_merge_request?
|
||||
track(NOTE_CREATED_IN_IPYNB_DIFF_MR_ACTION, USER_CREATED_NOTE_IN_IPYNB_DIFF_MR_ACTION, note)
|
||||
else
|
||||
track(NOTE_CREATED_IN_IPYNB_DIFF_COMMIT_ACTION, USER_CREATED_NOTE_IN_IPYNB_DIFF_COMMIT_ACTION, note)
|
||||
end
|
||||
|
||||
track(NOTE_CREATED_IN_IPYNB_DIFF_ACTION, USER_CREATED_NOTE_IN_IPYNB_DIFF_ACTION, note)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def track(action, per_user_action, note)
|
||||
Gitlab::UsageDataCounters::HLLRedisCounter.track_usage_event(action, note.id)
|
||||
Gitlab::UsageDataCounters::HLLRedisCounter.track_usage_event(per_user_action, note.author_id)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -173,6 +173,30 @@
|
|||
redis_slot: code_review
|
||||
category: code_review
|
||||
aggregation: weekly
|
||||
- name: i_code_review_create_note_in_ipynb_diff
|
||||
redis_slot: code_review
|
||||
category: code_review
|
||||
aggregation: weekly
|
||||
- name: i_code_review_user_create_note_in_ipynb_diff
|
||||
redis_slot: code_review
|
||||
category: code_review
|
||||
aggregation: weekly
|
||||
- name: i_code_review_create_note_in_ipynb_diff_mr
|
||||
redis_slot: code_review
|
||||
category: code_review
|
||||
aggregation: weekly
|
||||
- name: i_code_review_user_create_note_in_ipynb_diff_mr
|
||||
redis_slot: code_review
|
||||
category: code_review
|
||||
aggregation: weekly
|
||||
- name: i_code_review_create_note_in_ipynb_diff_commit
|
||||
redis_slot: code_review
|
||||
category: code_review
|
||||
aggregation: weekly
|
||||
- name: i_code_review_user_create_note_in_ipynb_diff_commit
|
||||
redis_slot: code_review
|
||||
category: code_review
|
||||
aggregation: weekly
|
||||
# Diff settings events
|
||||
- name: i_code_review_click_diff_view_setting
|
||||
redis_slot: code_review
|
||||
|
|
|
@ -73,7 +73,8 @@ module Sidebars
|
|||
end
|
||||
|
||||
def tracing_menu_item
|
||||
if !can?(context.current_user, :read_environment, context.project) ||
|
||||
if !Feature.enabled?(:monitor_tracing, context.project) ||
|
||||
!can?(context.current_user, :read_environment, context.project) ||
|
||||
!can?(context.current_user, :admin_project, context.project)
|
||||
return ::Sidebars::NilMenuItem.new(item_id: :tracing)
|
||||
end
|
||||
|
|
|
@ -12645,6 +12645,12 @@ msgstr ""
|
|||
msgid "Deprecations|For information on a possible replacement %{epicStart} learn more about Opstrace %{epicEnd}."
|
||||
msgstr ""
|
||||
|
||||
msgid "Deprecations|For information on a possible replacement, %{opstrace_link_start} learn more about Opstrace %{link_end}."
|
||||
msgstr ""
|
||||
|
||||
msgid "Deprecations|The logs and tracing features were also deprecated in GitLab 14.7, and are %{removal_link_start} scheduled for removal %{link_end} in GitLab 15.0."
|
||||
msgstr ""
|
||||
|
||||
msgid "Deprecations|The logs and tracing features were deprecated in GitLab 14.7 and are %{epicStart} scheduled for removal %{epicEnd} in GitLab 15.0."
|
||||
msgstr ""
|
||||
|
||||
|
@ -12654,9 +12660,6 @@ msgstr ""
|
|||
msgid "Deprecations|The metrics feature was deprecated in GitLab 14.7."
|
||||
msgstr ""
|
||||
|
||||
msgid "Deprecations|The metrics feature was deprecated in GitLab 14.7. The logs and tracing features were also deprecated in GitLab 14.7, and are %{removal_link_start} scheduled for removal %{link_end} in GitLab 15.0. For information on a possible replacement, %{opstrace_link_start} learn more about Opstrace %{link_end}."
|
||||
msgstr ""
|
||||
|
||||
msgid "Deprioritize label"
|
||||
msgstr ""
|
||||
|
||||
|
@ -23156,6 +23159,9 @@ msgstr ""
|
|||
msgid "Makes this issue confidential."
|
||||
msgstr ""
|
||||
|
||||
msgid "Manage"
|
||||
msgstr ""
|
||||
|
||||
msgid "Manage %{workspace} labels"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
@ -51,6 +51,16 @@ RSpec.describe Projects::TracingsController do
|
|||
it_behaves_like 'user with read access', :public
|
||||
it_behaves_like 'user with read access', :internal
|
||||
it_behaves_like 'user with read access', :private
|
||||
|
||||
context 'feature flag disabled' do
|
||||
before do
|
||||
stub_feature_flags(monitor_tracing: false)
|
||||
end
|
||||
|
||||
it_behaves_like 'user without read access', :public
|
||||
it_behaves_like 'user without read access', :internal
|
||||
it_behaves_like 'user without read access', :private
|
||||
end
|
||||
end
|
||||
|
||||
context 'without maintainer role' do
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe 'Secure Files Settings' do
|
||||
let_it_be(:maintainer) { create(:user) }
|
||||
let_it_be(:project) { create(:project, creator_id: maintainer.id) }
|
||||
|
||||
before_all do
|
||||
project.add_maintainer(maintainer)
|
||||
end
|
||||
|
||||
context 'when the :ci_secure_files feature flag is enabled' do
|
||||
before do
|
||||
stub_feature_flags(ci_secure_files: true)
|
||||
|
||||
sign_in(user)
|
||||
visit project_settings_ci_cd_path(project)
|
||||
end
|
||||
|
||||
context 'authenticated user with admin permissions' do
|
||||
let(:user) { maintainer }
|
||||
|
||||
it 'shows the secure files settings' do
|
||||
expect(page).to have_content('Secure Files')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the :ci_secure_files feature flag is disabled' do
|
||||
before do
|
||||
stub_feature_flags(ci_secure_files: false)
|
||||
|
||||
sign_in(user)
|
||||
visit project_settings_ci_cd_path(project)
|
||||
end
|
||||
|
||||
context 'authenticated user with admin permissions' do
|
||||
let(:user) { maintainer }
|
||||
|
||||
it 'does not shows the secure files settings' do
|
||||
expect(page).not_to have_content('Secure Files')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,76 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Ci::SecureFilesHelper do
|
||||
let_it_be(:maintainer) { create(:user) }
|
||||
let_it_be(:developer) { create(:user) }
|
||||
let_it_be(:guest) { create(:user) }
|
||||
let_it_be(:anonymous) { create(:user) }
|
||||
let_it_be(:unconfirmed) { create(:user, :unconfirmed) }
|
||||
let_it_be(:project) { create(:project, creator_id: maintainer.id) }
|
||||
|
||||
before_all do
|
||||
project.add_maintainer(maintainer)
|
||||
project.add_developer(developer)
|
||||
project.add_guest(guest)
|
||||
end
|
||||
|
||||
subject { helper.show_secure_files_setting(project, user) }
|
||||
|
||||
describe '#show_secure_files_setting' do
|
||||
context 'when the :ci_secure_files feature flag is enabled' do
|
||||
before do
|
||||
stub_feature_flags(ci_secure_files: true)
|
||||
end
|
||||
|
||||
context 'authenticated user with admin permissions' do
|
||||
let(:user) { maintainer }
|
||||
|
||||
it { is_expected.to be true }
|
||||
end
|
||||
|
||||
context 'authenticated user with read permissions' do
|
||||
let(:user) { developer }
|
||||
|
||||
it { is_expected.to be true }
|
||||
end
|
||||
|
||||
context 'authenticated user with guest permissions' do
|
||||
let(:user) { guest }
|
||||
|
||||
it { is_expected.to be false }
|
||||
end
|
||||
|
||||
context 'authenticated user with no permissions' do
|
||||
let(:user) { anonymous }
|
||||
|
||||
it { is_expected.to be false }
|
||||
end
|
||||
|
||||
context 'unconfirmed user' do
|
||||
let(:user) { unconfirmed }
|
||||
|
||||
it { is_expected.to be false }
|
||||
end
|
||||
|
||||
context 'unauthenticated user' do
|
||||
let(:user) { nil }
|
||||
|
||||
it { is_expected.to be false }
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the :ci_secure_files feature flag is disabled' do
|
||||
before do
|
||||
stub_feature_flags(ci_secure_files: false)
|
||||
end
|
||||
|
||||
context 'authenticated user with admin permissions' do
|
||||
let(:user) { maintainer }
|
||||
|
||||
it { is_expected.to be false }
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -99,6 +99,22 @@ RSpec.describe Gitlab::Diff::File do
|
|||
end
|
||||
end
|
||||
|
||||
describe '#ipynb?' do
|
||||
context 'is ipynb' do
|
||||
let(:commit) { project.commit("532c837") }
|
||||
|
||||
it 'is true' do
|
||||
expect(diff_file.ipynb?).to be_truthy
|
||||
end
|
||||
end
|
||||
|
||||
context 'is not ipynb' do
|
||||
it 'is false' do
|
||||
expect(diff_file.ipynb?).to be_falsey
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#has_renderable?' do
|
||||
context 'file is ipynb' do
|
||||
let(:commit) { project.commit("532c837") }
|
||||
|
|
|
@ -0,0 +1,67 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require "spec_helper"
|
||||
|
||||
RSpec.describe Gitlab::InactiveProjectsDeletionWarningTracker do
|
||||
let_it_be(:project_id) { 1 }
|
||||
|
||||
describe '.notified_projects', :clean_gitlab_redis_shared_state do
|
||||
before do
|
||||
freeze_time do
|
||||
Gitlab::InactiveProjectsDeletionWarningTracker.new(project_id).mark_notified
|
||||
end
|
||||
end
|
||||
|
||||
it 'returns the list of projects for which deletion warning email has been sent' do
|
||||
expected_hash = { "project:1" => "#{Date.current}" }
|
||||
|
||||
expect(Gitlab::InactiveProjectsDeletionWarningTracker.notified_projects).to eq(expected_hash)
|
||||
end
|
||||
end
|
||||
|
||||
describe '.reset_all' do
|
||||
before do
|
||||
Gitlab::InactiveProjectsDeletionWarningTracker.new(project_id).mark_notified
|
||||
end
|
||||
|
||||
it 'deletes all the projects for which deletion warning email was sent' do
|
||||
Gitlab::InactiveProjectsDeletionWarningTracker.reset_all
|
||||
|
||||
expect(Gitlab::InactiveProjectsDeletionWarningTracker.notified_projects).to eq({})
|
||||
end
|
||||
end
|
||||
|
||||
describe '#notified?' do
|
||||
before do
|
||||
Gitlab::InactiveProjectsDeletionWarningTracker.new(project_id).mark_notified
|
||||
end
|
||||
|
||||
it 'returns true if the project has already been notified' do
|
||||
expect(Gitlab::InactiveProjectsDeletionWarningTracker.new(project_id).notified?).to eq(true)
|
||||
end
|
||||
|
||||
it 'returns false if the project has not been notified' do
|
||||
expect(Gitlab::InactiveProjectsDeletionWarningTracker.new(2).notified?).to eq(false)
|
||||
end
|
||||
end
|
||||
|
||||
describe '#mark_notified' do
|
||||
it 'marks the project as being notified' do
|
||||
Gitlab::InactiveProjectsDeletionWarningTracker.new(project_id).mark_notified
|
||||
|
||||
expect(Gitlab::InactiveProjectsDeletionWarningTracker.new(project_id).notified?).to eq(true)
|
||||
end
|
||||
end
|
||||
|
||||
describe '#reset' do
|
||||
before do
|
||||
Gitlab::InactiveProjectsDeletionWarningTracker.new(project_id).mark_notified
|
||||
end
|
||||
|
||||
it 'resets the project as not being notified' do
|
||||
Gitlab::InactiveProjectsDeletionWarningTracker.new(project_id).reset
|
||||
|
||||
expect(Gitlab::InactiveProjectsDeletionWarningTracker.new(project_id).notified?).to eq(false)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,107 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Gitlab::UsageDataCounters::IpynbDiffActivityCounter, :clean_gitlab_redis_shared_state do
|
||||
let(:user) { build(:user, id: 1) }
|
||||
let(:for_mr) { false }
|
||||
let(:for_commit) { false }
|
||||
let(:first_note) { build(:note, author: user, id: 1) }
|
||||
let(:second_note) { build(:note, author: user, id: 2) }
|
||||
|
||||
before do
|
||||
allow(first_note).to receive(:for_merge_request?).and_return(for_mr)
|
||||
allow(second_note).to receive(:for_merge_request?).and_return(for_mr)
|
||||
allow(first_note).to receive(:for_commit?).and_return(for_commit)
|
||||
allow(second_note).to receive(:for_commit?).and_return(for_commit)
|
||||
end
|
||||
|
||||
subject do
|
||||
described_class.note_created(first_note)
|
||||
described_class.note_created(first_note)
|
||||
described_class.note_created(second_note)
|
||||
end
|
||||
|
||||
shared_examples_for 'an action that tracks events' do
|
||||
specify do
|
||||
expect { 2.times { subject } }
|
||||
.to change { event_count(action) }.by(2)
|
||||
.and change { event_count(per_user_action) }.by(1)
|
||||
end
|
||||
end
|
||||
|
||||
shared_examples_for 'an action that does not track events' do
|
||||
specify do
|
||||
expect { 2.times { subject } }
|
||||
.to change { event_count(action) }.by(0)
|
||||
.and change { event_count(per_user_action) }.by(0)
|
||||
end
|
||||
end
|
||||
|
||||
describe '#track_note_created_in_ipynb_diff' do
|
||||
context 'note is for commit' do
|
||||
let(:for_commit) { true }
|
||||
|
||||
it_behaves_like 'an action that tracks events' do
|
||||
let(:action) {described_class::NOTE_CREATED_IN_IPYNB_DIFF_ACTION}
|
||||
let(:per_user_action) {described_class::USER_CREATED_NOTE_IN_IPYNB_DIFF_ACTION}
|
||||
end
|
||||
|
||||
it_behaves_like 'an action that tracks events' do
|
||||
let(:action) {described_class::NOTE_CREATED_IN_IPYNB_DIFF_COMMIT_ACTION}
|
||||
let(:per_user_action) {described_class::USER_CREATED_NOTE_IN_IPYNB_DIFF_COMMIT_ACTION}
|
||||
end
|
||||
|
||||
it_behaves_like 'an action that does not track events' do
|
||||
let(:action) {described_class::NOTE_CREATED_IN_IPYNB_DIFF_MR_ACTION}
|
||||
let(:per_user_action) {described_class::USER_CREATED_NOTE_IN_IPYNB_DIFF_MR_ACTION}
|
||||
end
|
||||
end
|
||||
|
||||
context 'note is for MR' do
|
||||
let(:for_mr) { true }
|
||||
|
||||
it_behaves_like 'an action that tracks events' do
|
||||
let(:action) {described_class::NOTE_CREATED_IN_IPYNB_DIFF_MR_ACTION}
|
||||
let(:per_user_action) {described_class::USER_CREATED_NOTE_IN_IPYNB_DIFF_MR_ACTION}
|
||||
end
|
||||
|
||||
it_behaves_like 'an action that tracks events' do
|
||||
let(:action) {described_class::NOTE_CREATED_IN_IPYNB_DIFF_ACTION}
|
||||
let(:per_user_action) {described_class::USER_CREATED_NOTE_IN_IPYNB_DIFF_ACTION}
|
||||
end
|
||||
|
||||
it_behaves_like 'an action that does not track events' do
|
||||
let(:action) {described_class::NOTE_CREATED_IN_IPYNB_DIFF_COMMIT_ACTION}
|
||||
let(:per_user_action) {described_class::USER_CREATED_NOTE_IN_IPYNB_DIFF_COMMIT_ACTION}
|
||||
end
|
||||
end
|
||||
|
||||
context 'note is for neither MR nor Commit' do
|
||||
it_behaves_like 'an action that does not track events' do
|
||||
let(:action) {described_class::NOTE_CREATED_IN_IPYNB_DIFF_ACTION}
|
||||
let(:per_user_action) {described_class::USER_CREATED_NOTE_IN_IPYNB_DIFF_ACTION}
|
||||
end
|
||||
|
||||
it_behaves_like 'an action that does not track events' do
|
||||
let(:action) {described_class::NOTE_CREATED_IN_IPYNB_DIFF_MR_ACTION}
|
||||
let(:per_user_action) {described_class::USER_CREATED_NOTE_IN_IPYNB_DIFF_MR_ACTION}
|
||||
end
|
||||
|
||||
it_behaves_like 'an action that does not track events' do
|
||||
let(:action) {described_class::NOTE_CREATED_IN_IPYNB_DIFF_COMMIT_ACTION}
|
||||
let(:per_user_action) {described_class::USER_CREATED_NOTE_IN_IPYNB_DIFF_COMMIT_ACTION}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def event_count(event_name)
|
||||
Gitlab::UsageDataCounters::HLLRedisCounter.unique_events(
|
||||
event_names: event_name,
|
||||
start_date: 2.weeks.ago,
|
||||
end_date: 2.weeks.from_now
|
||||
)
|
||||
end
|
||||
end
|
|
@ -86,6 +86,14 @@ RSpec.describe Sidebars::Projects::Menus::MonitorMenu do
|
|||
let(:item_id) { :tracing }
|
||||
|
||||
it_behaves_like 'access rights checks'
|
||||
|
||||
context 'when feature disabled' do
|
||||
before do
|
||||
stub_feature_flags(monitor_tracing: false)
|
||||
end
|
||||
|
||||
specify { is_expected.to be_nil }
|
||||
end
|
||||
end
|
||||
|
||||
describe 'Error Tracking' do
|
||||
|
|
|
@ -1348,5 +1348,17 @@ RSpec.describe ApplicationSetting do
|
|||
it { is_expected.to validate_numericality_of(:inactive_projects_delete_after_months).is_greater_than(0) }
|
||||
|
||||
it { is_expected.to validate_numericality_of(:inactive_projects_min_size_mb).is_greater_than_or_equal_to(0) }
|
||||
|
||||
it "deletes the redis key used for tracking inactive projects deletion warning emails when setting is updated",
|
||||
:clean_gitlab_redis_shared_state do
|
||||
Gitlab::Redis::SharedState.with do |redis|
|
||||
redis.hset("inactive_projects_deletion_warning_email_notified", "project:1", "2020-01-01")
|
||||
end
|
||||
|
||||
Gitlab::Redis::SharedState.with do |redis|
|
||||
expect { setting.update!(inactive_projects_delete_after_months: 6) }
|
||||
.to change { redis.hgetall('inactive_projects_deletion_warning_email_notified') }.to({})
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -834,7 +834,13 @@ RSpec.describe Event do
|
|||
end
|
||||
end
|
||||
|
||||
context 'when a project was updated more than 1 hour ago' do
|
||||
context 'when a project was updated more than 1 hour ago', :clean_gitlab_redis_shared_state do
|
||||
before do
|
||||
::Gitlab::Redis::SharedState.with do |redis|
|
||||
redis.hset('inactive_projects_deletion_warning_email_notified', "project:#{project.id}", Date.current)
|
||||
end
|
||||
end
|
||||
|
||||
it 'updates the project' do
|
||||
project.touch(:last_activity_at, time: 1.year.ago) # rubocop: disable Rails/SkipsModelValidations
|
||||
|
||||
|
@ -845,6 +851,17 @@ RSpec.describe Event do
|
|||
expect(project.last_activity_at).to be_like_time(event.created_at)
|
||||
expect(project.updated_at).to be_like_time(event.created_at)
|
||||
end
|
||||
|
||||
it "deletes the redis key for if the project was inactive" do
|
||||
Gitlab::Redis::SharedState.with do |redis|
|
||||
expect(redis).to receive(:hdel).with('inactive_projects_deletion_warning_email_notified',
|
||||
"project:#{project.id}")
|
||||
end
|
||||
|
||||
project.touch(:last_activity_at, time: 1.year.ago) # rubocop: disable Rails/SkipsModelValidations
|
||||
|
||||
create_push_event(project, project.first_owner)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@ RSpec.describe Project, factory_default: :keep do
|
|||
include ExternalAuthorizationServiceHelpers
|
||||
include ReloadHelpers
|
||||
include StubGitlabCalls
|
||||
include ProjectHelpers
|
||||
using RSpec::Parameterized::TableSyntax
|
||||
|
||||
let_it_be(:namespace) { create_default(:namespace).freeze }
|
||||
|
@ -8267,6 +8268,28 @@ RSpec.describe Project, factory_default: :keep do
|
|||
it_behaves_like 'returns true if project is inactive'
|
||||
end
|
||||
|
||||
describe '.inactive' do
|
||||
before do
|
||||
stub_application_setting(inactive_projects_min_size_mb: 5)
|
||||
stub_application_setting(inactive_projects_send_warning_email_after_months: 12)
|
||||
end
|
||||
|
||||
it 'returns projects that are inactive' do
|
||||
create_project_with_statistics.tap do |project|
|
||||
project.update!(last_activity_at: Time.current)
|
||||
end
|
||||
create_project_with_statistics.tap do |project|
|
||||
project.update!(last_activity_at: 13.months.ago)
|
||||
end
|
||||
inactive_large_project = create_project_with_statistics(with_data: true, size_multiplier: 2.gigabytes)
|
||||
.tap { |project| project.update!(last_activity_at: 2.years.ago) }
|
||||
create_project_with_statistics(with_data: true, size_multiplier: 2.gigabytes)
|
||||
.tap { |project| project.update!(last_activity_at: 1.month.ago) }
|
||||
|
||||
expect(described_class.inactive).to contain_exactly(inactive_large_project)
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def finish_job(export_job)
|
||||
|
|
|
@ -168,7 +168,6 @@ RSpec.describe Notes::CreateService do
|
|||
before do
|
||||
project_with_repo.add_maintainer(user)
|
||||
end
|
||||
|
||||
context 'when eligible to have a note diff file' do
|
||||
let(:new_opts) do
|
||||
opts.merge(in_reply_to_discussion_id: nil,
|
||||
|
@ -196,6 +195,39 @@ RSpec.describe Notes::CreateService do
|
|||
described_class.new(project_with_repo, user, new_opts).execute(skip_capture_diff_note_position: true)
|
||||
end
|
||||
end
|
||||
|
||||
it 'does not track ipynb note usage data' do
|
||||
expect(::Gitlab::UsageDataCounters::IpynbDiffActivityCounter).not_to receive(:note_created)
|
||||
|
||||
described_class.new(project_with_repo, user, new_opts).execute
|
||||
end
|
||||
|
||||
context 'is ipynb file' do
|
||||
before do
|
||||
allow_any_instance_of(::Gitlab::Diff::File).to receive(:ipynb?).and_return(true)
|
||||
stub_feature_flags(ipynbdiff_notes_tracker: false)
|
||||
end
|
||||
|
||||
context ':ipynbdiff_notes_tracker is off' do
|
||||
it 'does not track ipynb note usage data' do
|
||||
expect(::Gitlab::UsageDataCounters::IpynbDiffActivityCounter).not_to receive(:note_created)
|
||||
|
||||
described_class.new(project_with_repo, user, new_opts).execute
|
||||
end
|
||||
end
|
||||
|
||||
context ':ipynbdiff_notes_tracker is on' do
|
||||
before do
|
||||
stub_feature_flags(ipynbdiff_notes_tracker: true)
|
||||
end
|
||||
|
||||
it 'tracks ipynb diff note creation' do
|
||||
expect(::Gitlab::UsageDataCounters::IpynbDiffActivityCounter).to receive(:note_created)
|
||||
|
||||
described_class.new(project_with_repo, user, new_opts).execute
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when DiffNote is a reply' do
|
||||
|
|
|
@ -24,4 +24,20 @@ module ProjectHelpers
|
|||
|
||||
project.update!(params)
|
||||
end
|
||||
|
||||
def create_project_with_statistics(namespace = nil, with_data: false, size_multiplier: 1)
|
||||
project = namespace.present? ? create(:project, namespace: namespace) : create(:project)
|
||||
project.tap do |p|
|
||||
create(:project_statistics, project: p, with_data: with_data, size_multiplier: size_multiplier)
|
||||
end
|
||||
end
|
||||
|
||||
def grace_months_after_deletion_notification
|
||||
(::Gitlab::CurrentSettings.inactive_projects_delete_after_months -
|
||||
::Gitlab::CurrentSettings.inactive_projects_send_warning_email_after_months).months
|
||||
end
|
||||
|
||||
def deletion_date
|
||||
Date.parse(grace_months_after_deletion_notification.from_now.to_s).to_s
|
||||
end
|
||||
end
|
||||
|
|
|
@ -389,6 +389,7 @@ RSpec.describe 'Every Sidekiq worker' do
|
|||
'ProjectTemplateExportWorker' => false,
|
||||
'ProjectUpdateRepositoryStorageWorker' => 3,
|
||||
'Projects::GitGarbageCollectWorker' => false,
|
||||
'Projects::InactiveProjectsDeletionNotificationWorker' => 3,
|
||||
'Projects::PostCreationWorker' => 3,
|
||||
'Projects::ScheduleBulkRepositoryShardMovesWorker' => 3,
|
||||
'Projects::UpdateRepositoryStorageWorker' => 3,
|
||||
|
|
|
@ -0,0 +1,139 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Projects::InactiveProjectsDeletionCronWorker do
|
||||
include ProjectHelpers
|
||||
|
||||
describe "#perform" do
|
||||
subject(:worker) { described_class.new }
|
||||
|
||||
let_it_be(:admin_user) { create(:user, :admin) }
|
||||
let_it_be(:non_admin_user) { create(:user) }
|
||||
let_it_be(:new_blank_project) do
|
||||
create_project_with_statistics.tap do |project|
|
||||
project.update!(last_activity_at: Time.current)
|
||||
end
|
||||
end
|
||||
|
||||
let_it_be(:inactive_blank_project) do
|
||||
create_project_with_statistics.tap do |project|
|
||||
project.update!(last_activity_at: 13.months.ago)
|
||||
end
|
||||
end
|
||||
|
||||
let_it_be(:inactive_large_project) do
|
||||
create_project_with_statistics(with_data: true, size_multiplier: 2.gigabytes)
|
||||
.tap { |project| project.update!(last_activity_at: 2.years.ago) }
|
||||
end
|
||||
|
||||
let_it_be(:active_large_project) do
|
||||
create_project_with_statistics(with_data: true, size_multiplier: 2.gigabytes)
|
||||
.tap { |project| project.update!(last_activity_at: 1.month.ago) }
|
||||
end
|
||||
|
||||
before do
|
||||
stub_application_setting(inactive_projects_min_size_mb: 5)
|
||||
stub_application_setting(inactive_projects_send_warning_email_after_months: 12)
|
||||
stub_application_setting(inactive_projects_delete_after_months: 14)
|
||||
end
|
||||
|
||||
context 'when delete inactive projects feature is disabled' do
|
||||
before do
|
||||
stub_application_setting(delete_inactive_projects: false)
|
||||
end
|
||||
|
||||
it 'does not invoke Projects::InactiveProjectsDeletionNotificationWorker' do
|
||||
expect(::Projects::InactiveProjectsDeletionNotificationWorker).not_to receive(:perform_in)
|
||||
expect(::Projects::DestroyService).not_to receive(:new)
|
||||
|
||||
worker.perform
|
||||
end
|
||||
|
||||
it 'does not delete the inactive projects' do
|
||||
worker.perform
|
||||
|
||||
expect(inactive_large_project.reload.pending_delete).to eq(false)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when delete inactive projects feature is enabled' do
|
||||
before do
|
||||
stub_application_setting(delete_inactive_projects: true)
|
||||
end
|
||||
|
||||
context 'when feature flag is disabled' do
|
||||
before do
|
||||
stub_feature_flags(inactive_projects_deletion: false)
|
||||
end
|
||||
|
||||
it 'does not invoke Projects::InactiveProjectsDeletionNotificationWorker' do
|
||||
expect(::Projects::InactiveProjectsDeletionNotificationWorker).not_to receive(:perform_in)
|
||||
expect(::Projects::DestroyService).not_to receive(:new)
|
||||
|
||||
worker.perform
|
||||
end
|
||||
|
||||
it 'does not delete the inactive projects' do
|
||||
worker.perform
|
||||
|
||||
expect(inactive_large_project.reload.pending_delete).to eq(false)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when feature flag is enabled', :clean_gitlab_redis_shared_state, :sidekiq_inline do
|
||||
let_it_be(:delay) { anything }
|
||||
|
||||
before do
|
||||
stub_feature_flags(inactive_projects_deletion: true)
|
||||
end
|
||||
|
||||
it 'invokes Projects::InactiveProjectsDeletionNotificationWorker for inactive projects' do
|
||||
Gitlab::Redis::SharedState.with do |redis|
|
||||
expect(redis).to receive(:hset).with('inactive_projects_deletion_warning_email_notified',
|
||||
"project:#{inactive_large_project.id}", Date.current)
|
||||
end
|
||||
expect(::Projects::InactiveProjectsDeletionNotificationWorker).to receive(:perform_in).with(
|
||||
delay, inactive_large_project.id, deletion_date).and_call_original
|
||||
expect(::Projects::DestroyService).not_to receive(:new)
|
||||
|
||||
worker.perform
|
||||
end
|
||||
|
||||
it 'does not invoke InactiveProjectsDeletionNotificationWorker for already notified inactive projects' do
|
||||
Gitlab::Redis::SharedState.with do |redis|
|
||||
redis.hset('inactive_projects_deletion_warning_email_notified', "project:#{inactive_large_project.id}",
|
||||
Date.current.to_s)
|
||||
end
|
||||
|
||||
expect(::Projects::InactiveProjectsDeletionNotificationWorker).not_to receive(:perform_in)
|
||||
expect(::Projects::DestroyService).not_to receive(:new)
|
||||
|
||||
worker.perform
|
||||
end
|
||||
|
||||
it 'invokes Projects::DestroyService for projects that are inactive even after being notified' do
|
||||
Gitlab::Redis::SharedState.with do |redis|
|
||||
redis.hset('inactive_projects_deletion_warning_email_notified', "project:#{inactive_large_project.id}",
|
||||
15.months.ago.to_date.to_s)
|
||||
end
|
||||
|
||||
expect(::Projects::InactiveProjectsDeletionNotificationWorker).not_to receive(:perform_in)
|
||||
expect(::Projects::DestroyService).to receive(:new).with(inactive_large_project, admin_user, {})
|
||||
.at_least(:once).and_call_original
|
||||
|
||||
worker.perform
|
||||
|
||||
expect(inactive_large_project.reload.pending_delete).to eq(true)
|
||||
|
||||
Gitlab::Redis::SharedState.with do |redis|
|
||||
expect(redis.hget('inactive_projects_deletion_warning_email_notified',
|
||||
"project:#{inactive_large_project.id}")).to be_nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
it_behaves_like 'an idempotent worker'
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,41 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Projects::InactiveProjectsDeletionNotificationWorker do
|
||||
describe "#perform" do
|
||||
subject(:worker) { described_class.new }
|
||||
|
||||
let_it_be(:deletion_date) { Date.current }
|
||||
let_it_be(:non_existing_project_id) { non_existing_record_id }
|
||||
let_it_be(:project) { create(:project) }
|
||||
|
||||
it 'invokes NotificationService and calls inactive_project_deletion_warning' do
|
||||
expect_next_instance_of(NotificationService) do |notification|
|
||||
expect(notification).to receive(:inactive_project_deletion_warning).with(project, deletion_date)
|
||||
end
|
||||
|
||||
worker.perform(project.id, deletion_date)
|
||||
end
|
||||
|
||||
it 'adds the project_id to redis key that tracks the deletion warning emails' do
|
||||
worker.perform(project.id, deletion_date)
|
||||
|
||||
Gitlab::Redis::SharedState.with do |redis|
|
||||
expect(redis.hget('inactive_projects_deletion_warning_email_notified',
|
||||
"project:#{project.id}")).to eq(Date.current.to_s)
|
||||
end
|
||||
end
|
||||
|
||||
it 'rescues and logs the exception if project does not exist' do
|
||||
expect(Gitlab::ErrorTracking).to receive(:log_exception).with(instance_of(ActiveRecord::RecordNotFound),
|
||||
{ project_id: non_existing_project_id })
|
||||
|
||||
worker.perform(non_existing_project_id, deletion_date)
|
||||
end
|
||||
|
||||
it_behaves_like 'an idempotent worker' do
|
||||
let(:job_args) { [project.id, deletion_date] }
|
||||
end
|
||||
end
|
||||
end
|
Binary file not shown.
Loading…
Reference in New Issue