Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2022-05-16 12:07:51 +00:00
parent f15ffb0170
commit 1c9afffa29
66 changed files with 3334 additions and 1587 deletions

View File

@ -765,3 +765,6 @@ Performance/ActiveRecordSubtransactionMethods:
Migration/BackgroundMigrationBaseClass:
Enabled: false
Style/ClassAndModuleChildren:
Enabled: true

View File

@ -6,17 +6,6 @@
# Note that changes in the inspected code, or installation of new
# versions of RuboCop, may require this file to be generated again.
# Offense count: 1
Gitlab/PolicyRuleBoolean:
Exclude:
- 'ee/app/policies/ee/identity_provider_policy.rb'
# Configuration parameters: Include.
# Include: db/migrate/*.rb
Rails/CreateTableWithTimestamps:
Enabled: false
# Offense count: 354
# Configuration parameters: Include.
# Include: app/models/**/*.rb
Rails/HasManyOrHasOneDependent:
@ -26,10 +15,3 @@ Rails/HasManyOrHasOneDependent:
# Cop supports --auto-correct.
Style/CaseLikeIf:
Enabled: false
# Offense count: 205
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle.
# SupportedStyles: compact, expanded
Style/EmptyMethod:
Enabled: false

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,4 @@
---
Gitlab/PolicyRuleBoolean:
Exclude:
- 'ee/app/policies/ee/identity_provider_policy.rb'

View File

@ -337,7 +337,7 @@ Layout/HashAlignment:
- 'ee/app/helpers/ee/feature_flags_helper.rb'
- 'ee/app/helpers/ee/sorting_helper.rb'
- 'ee/app/models/allowed_email_domain.rb'
- 'ee/app/models/ci/minutes/quota.rb'
- 'ee/app/models/ci/minutes/usage.rb'
- 'ee/app/models/ee/application_setting.rb'
- 'ee/app/models/elastic/reindexing_task.rb'
- 'ee/app/models/gitlab_subscriptions/features.rb'

View File

@ -0,0 +1,69 @@
---
Rails/CreateTableWithTimestamps:
# Offense count: 63
# Temporarily disabled due to too many offenses
Enabled: false
Exclude:
- 'db/migrate/20210305180331_create_ci_unit_tests.rb'
- 'db/migrate/20210305182855_create_ci_unit_test_failures.rb'
- 'db/migrate/20210317035357_create_dast_profiles_pipelines.rb'
- 'db/migrate/20210317104301_create_in_product_marketing_emails.rb'
- 'db/migrate/20210323125809_create_status_check_responses_table.rb'
- 'db/migrate/20210329191850_add_finding_signature_table.rb'
- 'db/migrate/20210411212813_add_clusters_integrations_prometheus.rb'
- 'db/migrate/20210423054022_create_dast_site_profiles_pipelines.rb'
- 'db/migrate/20210429032320_add_escalation_rules.rb'
- 'db/migrate/20210429131525_create_user_credit_card_validations.rb'
- 'db/migrate/20210511104929_add_epic_board_recent_visits_table.rb'
- 'db/migrate/20210512120122_add_pending_builds_table.rb'
- 'db/migrate/20210527194558_create_ci_job_token_project_scope_links.rb'
- 'db/migrate/20210601123341_add_running_builds_table.rb'
- 'db/migrate/20210602122213_add_upcoming_reconciliations.rb'
- 'db/migrate/20210604032738_create_dast_site_profiles_builds.rb'
- 'db/migrate/20210604051330_create_dast_scanner_profiles_builds.rb'
- 'db/migrate/20210604082145_create_external_status_checks_table.rb'
- 'db/migrate/20210713211008_create_banned_users.rb'
- 'db/migrate/20210729081739_create_project_topics.rb'
- 'db/migrate/20210729202143_create_incident_management_issuable_escalation_statuses.rb'
- 'db/migrate/20210730101609_create_analytics_cycle_analytics_stage_event_hashes.rb'
- 'db/migrate/20210809014850_create_agent_group_authorizations.rb'
- 'db/migrate/20210812171704_create_project_ci_feature_usages.rb'
- 'db/migrate/20210813101742_create_zentao_tracker_data.rb'
- 'db/migrate/20210813111909_create_ci_build_trace_metadata.rb'
- 'db/migrate/20210819185500_create_external_audit_event_destinations_table.rb'
- 'db/migrate/20210823172643_create_user_group_callout.rb'
- 'db/migrate/20210823213417_create_dependency_proxy_image_ttl_group_policies.rb'
- 'db/migrate/20210913010411_create_agent_project_authorizations.rb'
- 'db/migrate/20210922215740_create_issue_customer_relations_contacts.rb'
- 'db/migrate/20211004062942_create_coverage_fuzzing_corpuses.rb'
- 'db/migrate/20211004122540_create_member_tasks.rb'
- 'db/migrate/20211011004242_create_content_blocked_states.rb'
- 'db/migrate/20211011140930_create_ci_namespace_mirrors.rb'
- 'db/migrate/20211011140931_create_ci_project_mirrors.rb'
- 'db/migrate/20211011140932_create_namespaces_sync_events.rb'
- 'db/migrate/20211011141239_create_projects_sync_events.rb'
- 'db/migrate/20211028132247_create_packages_npm_metadata.rb'
- 'db/migrate/20211101132310_add_reindexing_queue.rb'
- 'db/migrate/20211101165656_create_upload_states.rb'
- 'db/migrate/20211110014701_create_agent_activity_events.rb'
- 'db/migrate/20211110092710_create_issue_emails.rb'
- 'db/migrate/20211111112425_create_merge_requests_compliance_violations.rb'
- 'db/migrate/20211115132613_create_incident_management_timeline_events.rb'
- 'db/migrate/20211117174209_create_vulnerability_reads.rb'
- 'db/migrate/20211119111006_create_job_artifact_states.rb'
- 'db/migrate/20211119154221_create_pages_deployment_states.rb'
- 'db/migrate/20211119195201_create_deployment_approvals.rb'
- 'db/migrate/20211201143042_create_lfs_object_states.rb'
- 'db/migrate/20211216220939_add_group_crm_settings.rb'
- 'db/migrate/20220110170953_create_ci_secure_files.rb'
- 'db/migrate/20220112205111_create_security_training_providers.rb'
- 'db/migrate/20220113125401_create_security_trainings.rb'
- 'db/migrate/20220120033115_create_alert_management_alert_metric_images.rb'
- 'db/migrate/20220204093120_create_analytics_cycle_analytics_aggregations.rb'
- 'db/migrate/20220211125954_create_related_epic_links.rb'
- 'db/migrate/20220216110023_create_saved_replies.rb'
- 'db/migrate/20220301175426_create_project_build_artifacts_size_refresh.rb'
- 'db/migrate/20220302110724_add_group_features_table.rb'
- 'db/migrate/20220314184009_create_protected_environment_approval_rules.rb'
- 'db/migrate/20220425120604_create_packages_cleanup_policies.rb'
- 'db/migrate/20220503102855_add_namespace_ci_cd_settings_table.rb'

View File

@ -0,0 +1,587 @@
---
# Cop supports --auto-correct.
Style/ClassAndModuleChildren:
Exclude:
- 'app/components/pajamas/toggle_component.rb'
- 'app/controllers/admin/abuse_reports_controller.rb'
- 'app/controllers/admin/application_controller.rb'
- 'app/controllers/admin/application_settings/appearances_controller.rb'
- 'app/controllers/admin/application_settings_controller.rb'
- 'app/controllers/admin/applications_controller.rb'
- 'app/controllers/admin/background_jobs_controller.rb'
- 'app/controllers/admin/background_migrations_controller.rb'
- 'app/controllers/admin/batched_jobs_controller.rb'
- 'app/controllers/admin/broadcast_messages_controller.rb'
- 'app/controllers/admin/ci/variables_controller.rb'
- 'app/controllers/admin/clusters/integrations_controller.rb'
- 'app/controllers/admin/clusters_controller.rb'
- 'app/controllers/admin/cohorts_controller.rb'
- 'app/controllers/admin/dashboard_controller.rb'
- 'app/controllers/admin/deploy_keys_controller.rb'
- 'app/controllers/admin/dev_ops_report_controller.rb'
- 'app/controllers/admin/gitaly_servers_controller.rb'
- 'app/controllers/admin/groups_controller.rb'
- 'app/controllers/admin/health_check_controller.rb'
- 'app/controllers/admin/hook_logs_controller.rb'
- 'app/controllers/admin/hooks_controller.rb'
- 'app/controllers/admin/identities_controller.rb'
- 'app/controllers/admin/impersonation_tokens_controller.rb'
- 'app/controllers/admin/impersonations_controller.rb'
- 'app/controllers/admin/instance_review_controller.rb'
- 'app/controllers/admin/integrations_controller.rb'
- 'app/controllers/admin/jobs_controller.rb'
- 'app/controllers/admin/keys_controller.rb'
- 'app/controllers/admin/labels_controller.rb'
- 'app/controllers/admin/plan_limits_controller.rb'
- 'app/controllers/admin/projects_controller.rb'
- 'app/controllers/admin/runner_projects_controller.rb'
- 'app/controllers/admin/runners_controller.rb'
- 'app/controllers/admin/sessions_controller.rb'
- 'app/controllers/admin/spam_logs_controller.rb'
- 'app/controllers/admin/system_info_controller.rb'
- 'app/controllers/admin/topics/avatars_controller.rb'
- 'app/controllers/admin/topics_controller.rb'
- 'app/controllers/admin/usage_trends_controller.rb'
- 'app/controllers/admin/users_controller.rb'
- 'app/controllers/admin/version_check_controller.rb'
- 'app/controllers/clusters/base_controller.rb'
- 'app/controllers/clusters/clusters_controller.rb'
- 'app/controllers/concerns/integrations/actions.rb'
- 'app/controllers/concerns/integrations/hooks_execution.rb'
- 'app/controllers/concerns/metrics/dashboard/prometheus_api_proxy.rb'
- 'app/controllers/concerns/snippets/blobs_actions.rb'
- 'app/controllers/concerns/snippets/send_blob.rb'
- 'app/controllers/concerns/spammable_actions/akismet_mark_as_spam_action.rb'
- 'app/controllers/concerns/spammable_actions/captcha_check/html_format_actions_support.rb'
- 'app/controllers/concerns/spammable_actions/captcha_check/json_format_actions_support.rb'
- 'app/controllers/concerns/spammable_actions/captcha_check/rest_api_actions_support.rb'
- 'app/controllers/dashboard/application_controller.rb'
- 'app/controllers/dashboard/groups_controller.rb'
- 'app/controllers/dashboard/labels_controller.rb'
- 'app/controllers/dashboard/milestones_controller.rb'
- 'app/controllers/dashboard/projects_controller.rb'
- 'app/controllers/dashboard/snippets_controller.rb'
- 'app/controllers/dashboard/todos_controller.rb'
- 'app/controllers/explore/application_controller.rb'
- 'app/controllers/explore/groups_controller.rb'
- 'app/controllers/explore/projects_controller.rb'
- 'app/controllers/explore/snippets_controller.rb'
- 'app/controllers/groups/application_controller.rb'
- 'app/controllers/groups/autocomplete_sources_controller.rb'
- 'app/controllers/groups/avatars_controller.rb'
- 'app/controllers/groups/boards_controller.rb'
- 'app/controllers/groups/clusters/integrations_controller.rb'
- 'app/controllers/groups/clusters_controller.rb'
- 'app/controllers/groups/crm/contacts_controller.rb'
- 'app/controllers/groups/crm/organizations_controller.rb'
- 'app/controllers/groups/dependency_proxy_auth_controller.rb'
- 'app/controllers/groups/dependency_proxy_for_containers_controller.rb'
- 'app/controllers/groups/deploy_tokens_controller.rb'
- 'app/controllers/groups/email_campaigns_controller.rb'
- 'app/controllers/groups/group_links_controller.rb'
- 'app/controllers/groups/group_members_controller.rb'
- 'app/controllers/groups/imports_controller.rb'
- 'app/controllers/groups/labels_controller.rb'
- 'app/controllers/groups/milestones_controller.rb'
- 'app/controllers/groups/runners_controller.rb'
- 'app/controllers/groups/uploads_controller.rb'
- 'app/controllers/import/available_namespaces_controller.rb'
- 'app/controllers/import/base_controller.rb'
- 'app/controllers/import/bitbucket_controller.rb'
- 'app/controllers/import/bitbucket_server_controller.rb'
- 'app/controllers/import/bulk_imports_controller.rb'
- 'app/controllers/import/fogbugz_controller.rb'
- 'app/controllers/import/gitea_controller.rb'
- 'app/controllers/import/github_controller.rb'
- 'app/controllers/import/gitlab_controller.rb'
- 'app/controllers/import/gitlab_groups_controller.rb'
- 'app/controllers/import/gitlab_projects_controller.rb'
- 'app/controllers/import/history_controller.rb'
- 'app/controllers/import/manifest_controller.rb'
- 'app/controllers/import/phabricator_controller.rb'
- 'app/controllers/import/url_controller.rb'
- 'app/controllers/jira_connect/app_descriptor_controller.rb'
- 'app/controllers/jira_connect/application_controller.rb'
- 'app/controllers/jira_connect/branches_controller.rb'
- 'app/controllers/jira_connect/events_controller.rb'
- 'app/controllers/jira_connect/installations_controller.rb'
- 'app/controllers/jira_connect/oauth_callbacks_controller.rb'
- 'app/controllers/jira_connect/subscriptions_controller.rb'
- 'app/controllers/jira_connect/users_controller.rb'
- 'app/controllers/ldap/omniauth_callbacks_controller.rb'
- 'app/controllers/oauth/applications_controller.rb'
- 'app/controllers/oauth/authorizations_controller.rb'
- 'app/controllers/oauth/authorized_applications_controller.rb'
- 'app/controllers/oauth/jira_dvcs/authorizations_controller.rb'
- 'app/controllers/oauth/token_info_controller.rb'
- 'app/controllers/oauth/tokens_controller.rb'
- 'app/controllers/profiles/accounts_controller.rb'
- 'app/controllers/profiles/active_sessions_controller.rb'
- 'app/controllers/profiles/application_controller.rb'
- 'app/controllers/profiles/avatars_controller.rb'
- 'app/controllers/profiles/chat_names_controller.rb'
- 'app/controllers/profiles/emails_controller.rb'
- 'app/controllers/profiles/gpg_keys_controller.rb'
- 'app/controllers/profiles/groups_controller.rb'
- 'app/controllers/profiles/keys_controller.rb'
- 'app/controllers/profiles/notifications_controller.rb'
- 'app/controllers/profiles/passwords_controller.rb'
- 'app/controllers/profiles/personal_access_tokens_controller.rb'
- 'app/controllers/profiles/preferences_controller.rb'
- 'app/controllers/profiles/two_factor_auths_controller.rb'
- 'app/controllers/profiles/u2f_registrations_controller.rb'
- 'app/controllers/profiles/webauthn_registrations_controller.rb'
- 'app/controllers/projects/alert_management_controller.rb'
- 'app/controllers/projects/analytics/cycle_analytics/stages_controller.rb'
- 'app/controllers/projects/analytics/cycle_analytics/summary_controller.rb'
- 'app/controllers/projects/analytics/cycle_analytics/value_streams_controller.rb'
- 'app/controllers/projects/application_controller.rb'
- 'app/controllers/projects/artifacts_controller.rb'
- 'app/controllers/projects/autocomplete_sources_controller.rb'
- 'app/controllers/projects/avatars_controller.rb'
- 'app/controllers/projects/badges_controller.rb'
- 'app/controllers/projects/blame_controller.rb'
- 'app/controllers/projects/blob_controller.rb'
- 'app/controllers/projects/boards_controller.rb'
- 'app/controllers/projects/branches_controller.rb'
- 'app/controllers/projects/build_artifacts_controller.rb'
- 'app/controllers/projects/builds_controller.rb'
- 'app/controllers/projects/ci/daily_build_group_report_results_controller.rb'
- 'app/controllers/projects/ci/lints_controller.rb'
- 'app/controllers/projects/ci/pipeline_editor_controller.rb'
- 'app/controllers/projects/ci/secure_files_controller.rb'
- 'app/controllers/projects/cluster_agents_controller.rb'
- 'app/controllers/projects/clusters/integrations_controller.rb'
- 'app/controllers/projects/clusters_controller.rb'
- 'app/controllers/projects/commit_controller.rb'
- 'app/controllers/projects/commits_controller.rb'
- 'app/controllers/projects/compare_controller.rb'
- 'app/controllers/projects/confluences_controller.rb'
- 'app/controllers/projects/cycle_analytics_controller.rb'
- 'app/controllers/projects/deploy_keys_controller.rb'
- 'app/controllers/projects/deploy_tokens_controller.rb'
- 'app/controllers/projects/deployments_controller.rb'
- 'app/controllers/projects/design_management/designs_controller.rb'
- 'app/controllers/projects/discussions_controller.rb'
- 'app/controllers/projects/environments/prometheus_api_controller.rb'
- 'app/controllers/projects/environments/sample_metrics_controller.rb'
- 'app/controllers/projects/environments_controller.rb'
- 'app/controllers/projects/error_tracking/base_controller.rb'
- 'app/controllers/projects/error_tracking_controller.rb'
- 'app/controllers/projects/feature_flags_clients_controller.rb'
- 'app/controllers/projects/feature_flags_controller.rb'
- 'app/controllers/projects/feature_flags_user_lists_controller.rb'
- 'app/controllers/projects/find_file_controller.rb'
- 'app/controllers/projects/forks_controller.rb'
- 'app/controllers/projects/google_cloud/base_controller.rb'
- 'app/controllers/projects/google_cloud/deployments_controller.rb'
- 'app/controllers/projects/google_cloud/gcp_regions_controller.rb'
- 'app/controllers/projects/google_cloud/revoke_oauth_controller.rb'
- 'app/controllers/projects/google_cloud/service_accounts_controller.rb'
- 'app/controllers/projects/google_cloud_controller.rb'
- 'app/controllers/projects/grafana_api_controller.rb'
- 'app/controllers/projects/graphs_controller.rb'
- 'app/controllers/projects/group_links_controller.rb'
- 'app/controllers/projects/hook_logs_controller.rb'
- 'app/controllers/projects/hooks_controller.rb'
- 'app/controllers/projects/imports_controller.rb'
- 'app/controllers/projects/incidents_controller.rb'
- 'app/controllers/projects/issues_controller.rb'
- 'app/controllers/projects/jobs_controller.rb'
- 'app/controllers/projects/labels_controller.rb'
- 'app/controllers/projects/learn_gitlab_controller.rb'
- 'app/controllers/projects/mattermosts_controller.rb'
- 'app/controllers/projects/merge_requests/application_controller.rb'
- 'app/controllers/projects/merge_requests/conflicts_controller.rb'
- 'app/controllers/projects/merge_requests/content_controller.rb'
- 'app/controllers/projects/merge_requests/creations_controller.rb'
- 'app/controllers/projects/merge_requests/diffs_controller.rb'
- 'app/controllers/projects/merge_requests/drafts_controller.rb'
- 'app/controllers/projects/merge_requests_controller.rb'
- 'app/controllers/projects/milestones_controller.rb'
- 'app/controllers/projects/mirrors_controller.rb'
- 'app/controllers/projects/network_controller.rb'
- 'app/controllers/projects/notes_controller.rb'
- 'app/controllers/projects/pages_controller.rb'
- 'app/controllers/projects/pages_domains_controller.rb'
- 'app/controllers/projects/pipeline_schedules_controller.rb'
- 'app/controllers/projects/pipelines_controller.rb'
- 'app/controllers/projects/pipelines_settings_controller.rb'
- 'app/controllers/projects/product_analytics_controller.rb'
- 'app/controllers/projects/project_members_controller.rb'
- 'app/controllers/projects/protected_branches_controller.rb'
- 'app/controllers/projects/protected_refs_controller.rb'
- 'app/controllers/projects/protected_tags_controller.rb'
- 'app/controllers/projects/raw_controller.rb'
- 'app/controllers/projects/redirect_controller.rb'
- 'app/controllers/projects/refs_controller.rb'
- 'app/controllers/projects/releases_controller.rb'
- 'app/controllers/projects/repositories_controller.rb'
- 'app/controllers/projects/runner_projects_controller.rb'
- 'app/controllers/projects/runners_controller.rb'
- 'app/controllers/projects/service_desk_controller.rb'
- 'app/controllers/projects/service_hook_logs_controller.rb'
- 'app/controllers/projects/service_ping_controller.rb'
- 'app/controllers/projects/services_controller.rb'
- 'app/controllers/projects/snippets/application_controller.rb'
- 'app/controllers/projects/snippets/blobs_controller.rb'
- 'app/controllers/projects/snippets_controller.rb'
- 'app/controllers/projects/starrers_controller.rb'
- 'app/controllers/projects/static_site_editor_controller.rb'
- 'app/controllers/projects/tags/releases_controller.rb'
- 'app/controllers/projects/tags_controller.rb'
- 'app/controllers/projects/templates_controller.rb'
- 'app/controllers/projects/terraform_controller.rb'
- 'app/controllers/projects/todos_controller.rb'
- 'app/controllers/projects/tree_controller.rb'
- 'app/controllers/projects/triggers_controller.rb'
- 'app/controllers/projects/uploads_controller.rb'
- 'app/controllers/projects/usage_quotas_controller.rb'
- 'app/controllers/projects/variables_controller.rb'
- 'app/controllers/projects/web_ide_schemas_controller.rb'
- 'app/controllers/projects/web_ide_terminals_controller.rb'
- 'app/controllers/projects/wikis_controller.rb'
- 'app/controllers/projects/work_items_controller.rb'
- 'app/controllers/snippets/application_controller.rb'
- 'app/controllers/snippets/blobs_controller.rb'
- 'app/controllers/snippets/notes_controller.rb'
- 'app/controllers/terraform/services_controller.rb'
- 'app/finders/admin/projects_finder.rb'
- 'app/finders/merge_request/metrics_finder.rb'
- 'app/finders/packages/package_file_finder.rb'
- 'app/finders/packages/tags_finder.rb'
- 'app/graphql/types/dependency_proxy/blob_type.rb'
- 'app/graphql/types/dependency_proxy/group_setting_type.rb'
- 'app/graphql/types/dependency_proxy/image_ttl_group_policy_type.rb'
- 'app/graphql/types/dependency_proxy/manifest_type.rb'
- 'app/graphql/types/dependency_proxy/manifest_type_enum.rb'
- 'app/graphql/types/namespace/package_settings_type.rb'
- 'app/graphql/types/namespace/shared_runners_setting_enum.rb'
- 'app/helpers/ci/triggers_helper.rb'
- 'app/helpers/groups/group_members_helper.rb'
- 'app/helpers/projects/alert_management_helper.rb'
- 'app/helpers/projects/cluster_agents_helper.rb'
- 'app/helpers/projects/error_tracking_helper.rb'
- 'app/helpers/projects/incidents_helper.rb'
- 'app/helpers/projects/project_members_helper.rb'
- 'app/helpers/projects/terraform_helper.rb'
- 'app/models/analytics/cycle_analytics/aggregation.rb'
- 'app/models/analytics/cycle_analytics/project_value_stream.rb'
- 'app/models/bulk_imports/configuration.rb'
- 'app/models/bulk_imports/entity.rb'
- 'app/models/bulk_imports/failure.rb'
- 'app/models/bulk_imports/tracker.rb'
- 'app/models/ci/build_pending_state.rb'
- 'app/models/ci/commit_with_pipeline.rb'
- 'app/models/customer_relations/contact.rb'
- 'app/models/customer_relations/issue_contact.rb'
- 'app/models/customer_relations/organization.rb'
- 'app/models/dependency_proxy/blob.rb'
- 'app/models/dependency_proxy/group_setting.rb'
- 'app/models/dependency_proxy/image_ttl_group_policy.rb'
- 'app/models/dependency_proxy/manifest.rb'
- 'app/models/dependency_proxy/registry.rb'
- 'app/models/error_tracking/client_key.rb'
- 'app/models/error_tracking/error.rb'
- 'app/models/error_tracking/error_event.rb'
- 'app/models/group/crm_settings.rb'
- 'app/models/instance_metadata/kas.rb'
- 'app/models/issue/email.rb'
- 'app/models/issue/metrics.rb'
- 'app/models/issues/csv_import.rb'
- 'app/models/loose_foreign_keys/deleted_record.rb'
- 'app/models/merge_request/cleanup_schedule.rb'
- 'app/models/merge_request/diff_commit_user.rb'
- 'app/models/merge_request/metrics.rb'
- 'app/models/namespace/admin_note.rb'
- 'app/models/namespace/aggregation_schedule.rb'
- 'app/models/namespace/package_setting.rb'
- 'app/models/namespace/root_storage_statistics.rb'
- 'app/models/namespaces/sync_event.rb'
- 'app/models/packages/build_info.rb'
- 'app/models/packages/conan/file_metadatum.rb'
- 'app/models/packages/conan/metadatum.rb'
- 'app/models/packages/debian/file_metadatum.rb'
- 'app/models/packages/debian/group_architecture.rb'
- 'app/models/packages/debian/group_component.rb'
- 'app/models/packages/debian/group_component_file.rb'
- 'app/models/packages/debian/group_distribution.rb'
- 'app/models/packages/debian/group_distribution_key.rb'
- 'app/models/packages/debian/project_architecture.rb'
- 'app/models/packages/debian/project_component.rb'
- 'app/models/packages/debian/project_component_file.rb'
- 'app/models/packages/debian/project_distribution.rb'
- 'app/models/packages/debian/project_distribution_key.rb'
- 'app/models/packages/debian/publication.rb'
- 'app/models/packages/dependency.rb'
- 'app/models/packages/dependency_link.rb'
- 'app/models/packages/event.rb'
- 'app/models/packages/maven/metadatum.rb'
- 'app/models/packages/npm/metadatum.rb'
- 'app/models/packages/nuget/dependency_link_metadatum.rb'
- 'app/models/packages/nuget/metadatum.rb'
- 'app/models/packages/package.rb'
- 'app/models/packages/package_file.rb'
- 'app/models/packages/package_file_build_info.rb'
- 'app/models/packages/pypi/metadatum.rb'
- 'app/models/packages/sem_ver.rb'
- 'app/models/packages/tag.rb'
- 'app/models/projects/sync_event.rb'
- 'app/models/protected_branch/merge_access_level.rb'
- 'app/models/protected_branch/push_access_level.rb'
- 'app/models/protected_tag/create_access_level.rb'
- 'app/policies/namespace/package_setting_policy.rb'
- 'app/policies/namespace/root_storage_statistics_policy.rb'
- 'app/policies/wiki_page/meta_policy.rb'
- 'app/serializers/acts_as_taggable_on/tag_entity.rb'
- 'app/serializers/acts_as_taggable_on/tag_serializer.rb'
- 'app/serializers/ci/lint/job_entity.rb'
- 'app/serializers/ci/lint/result_entity.rb'
- 'app/serializers/ci/lint/result_serializer.rb'
- 'app/serializers/ci/pipeline_entity.rb'
- 'app/serializers/import/base_provider_repo_entity.rb'
- 'app/serializers/import/bitbucket_provider_repo_entity.rb'
- 'app/serializers/import/bitbucket_server_provider_repo_entity.rb'
- 'app/serializers/import/bulk_import_entity.rb'
- 'app/serializers/import/fogbugz_provider_repo_entity.rb'
- 'app/serializers/import/githubish_provider_repo_entity.rb'
- 'app/serializers/import/gitlab_provider_repo_entity.rb'
- 'app/serializers/import/manifest_provider_repo_entity.rb'
- 'app/serializers/import/provider_repo_serializer.rb'
- 'app/serializers/jira_connect/app_data_serializer.rb'
- 'app/serializers/jira_connect/group_entity.rb'
- 'app/serializers/jira_connect/subscription_entity.rb'
- 'app/serializers/merge_requests/pipeline_entity.rb'
- 'app/services/projects/branches_by_mode_service.rb'
- 'app/services/repositories/base_service.rb'
- 'app/services/repositories/destroy_rollback_service.rb'
- 'app/services/repositories/destroy_service.rb'
- 'app/services/repositories/shell_destroy_service.rb'
- 'app/uploaders/dependency_proxy/file_uploader.rb'
- 'app/uploaders/packages/composer/cache_uploader.rb'
- 'app/uploaders/packages/debian/component_file_uploader.rb'
- 'app/uploaders/packages/debian/distribution_release_file_uploader.rb'
- 'app/uploaders/packages/package_file_uploader.rb'
- 'app/workers/merge_requests/delete_source_branch_worker.rb'
- 'app/workers/merge_requests/handle_assignees_change_worker.rb'
- 'app/workers/merge_requests/resolve_todos_worker.rb'
- 'config/initializers/active_record_data_types.rb'
- 'config/initializers/http_hostname_override.rb'
- 'config/initializers/httpclient_patch.rb'
- 'config/initializers/omniauth.rb'
- 'config/initializers/postgres_cte_as_materialized.rb'
- 'config/initializers/postgresql_cte.rb'
- 'config/initializers/rdoc_segfault_patch.rb'
- 'config/initializers/zz_metrics.rb'
- 'ee/app/controllers/admin/audit_log_reports_controller.rb'
- 'ee/app/controllers/admin/audit_logs_controller.rb'
- 'ee/app/controllers/admin/credentials_controller.rb'
- 'ee/app/controllers/admin/elasticsearch_controller.rb'
- 'ee/app/controllers/admin/emails_controller.rb'
- 'ee/app/controllers/admin/geo/application_controller.rb'
- 'ee/app/controllers/admin/geo/designs_controller.rb'
- 'ee/app/controllers/admin/geo/nodes_controller.rb'
- 'ee/app/controllers/admin/geo/projects_controller.rb'
- 'ee/app/controllers/admin/geo/replicables_controller.rb'
- 'ee/app/controllers/admin/geo/settings_controller.rb'
- 'ee/app/controllers/admin/licenses_controller.rb'
- 'ee/app/controllers/admin/push_rules_controller.rb'
- 'ee/app/controllers/admin/subscriptions_controller.rb'
- 'ee/app/controllers/admin/user_permission_exports_controller.rb'
- 'ee/app/controllers/concerns/registrations/apply_trial.rb'
- 'ee/app/controllers/concerns/registrations/create_group.rb'
- 'ee/app/controllers/concerns/registrations/create_project.rb'
- 'ee/app/controllers/concerns/registrations/verification.rb'
- 'ee/app/controllers/ee/profiles/accounts_controller.rb'
- 'ee/app/controllers/ee/profiles/preferences_controller.rb'
- 'ee/app/controllers/ee/projects/analytics/cycle_analytics/summary_controller.rb'
- 'ee/app/controllers/ee/projects/incidents_controller.rb'
- 'ee/app/controllers/groups/analytics/application_controller.rb'
- 'ee/app/controllers/groups/analytics/ci_cd_analytics_controller.rb'
- 'ee/app/controllers/groups/analytics/coverage_reports_controller.rb'
- 'ee/app/controllers/groups/analytics/cycle_analytics/value_streams_controller.rb'
- 'ee/app/controllers/groups/analytics/cycle_analytics_controller.rb'
- 'ee/app/controllers/groups/analytics/devops_adoption_controller.rb'
- 'ee/app/controllers/groups/analytics/productivity_analytics_controller.rb'
- 'ee/app/controllers/groups/analytics/repository_analytics_controller.rb'
- 'ee/app/controllers/groups/analytics/tasks_by_type_controller.rb'
- 'ee/app/controllers/groups/audit_events_controller.rb'
- 'ee/app/controllers/groups/billings_controller.rb'
- 'ee/app/controllers/groups/bulk_update_controller.rb'
- 'ee/app/controllers/groups/compliance_frameworks_controller.rb'
- 'ee/app/controllers/groups/contribution_analytics_controller.rb'
- 'ee/app/controllers/groups/epic_boards_controller.rb'
- 'ee/app/controllers/groups/epic_issues_controller.rb'
- 'ee/app/controllers/groups/epics/notes_controller.rb'
- 'ee/app/controllers/groups/epics_controller.rb'
- 'ee/app/controllers/groups/hooks_controller.rb'
- 'ee/app/controllers/groups/insights_controller.rb'
- 'ee/app/controllers/groups/issues_analytics_controller.rb'
- 'ee/app/controllers/groups/issues_controller.rb'
- 'ee/app/controllers/groups/iteration_cadences_controller.rb'
- 'ee/app/controllers/groups/iterations_controller.rb'
- 'ee/app/controllers/groups/ldap_group_links_controller.rb'
- 'ee/app/controllers/groups/ldap_settings_controller.rb'
- 'ee/app/controllers/groups/ldaps_controller.rb'
- 'ee/app/controllers/groups/merge_requests_controller.rb'
- 'ee/app/controllers/groups/omniauth_callbacks_controller.rb'
- 'ee/app/controllers/groups/push_rules_controller.rb'
- 'ee/app/controllers/groups/saml_providers_controller.rb'
- 'ee/app/controllers/groups/scim_oauth_controller.rb'
- 'ee/app/controllers/groups/seat_usage_controller.rb'
- 'ee/app/controllers/groups/security/compliance_dashboards_controller.rb'
- 'ee/app/controllers/groups/security/credentials_controller.rb'
- 'ee/app/controllers/groups/security/dashboard_controller.rb'
- 'ee/app/controllers/groups/security/discover_controller.rb'
- 'ee/app/controllers/groups/security/merge_commit_reports_controller.rb'
- 'ee/app/controllers/groups/sso_controller.rb'
- 'ee/app/controllers/groups/todos_controller.rb'
- 'ee/app/controllers/groups/usage_quotas_controller.rb'
- 'ee/app/controllers/groups/wikis_controller.rb'
- 'ee/app/controllers/oauth/geo_auth_controller.rb'
- 'ee/app/controllers/profiles/billings_controller.rb'
- 'ee/app/controllers/profiles/slacks_controller.rb'
- 'ee/app/controllers/profiles/usage_quotas_controller.rb'
- 'ee/app/controllers/projects/analytics/issues_analytics_controller.rb'
- 'ee/app/controllers/projects/analytics/merge_request_analytics_controller.rb'
- 'ee/app/controllers/projects/approver_groups_controller.rb'
- 'ee/app/controllers/projects/approvers_controller.rb'
- 'ee/app/controllers/projects/audit_events_controller.rb'
- 'ee/app/controllers/projects/insights_controller.rb'
- 'ee/app/controllers/projects/iteration_cadences_controller.rb'
- 'ee/app/controllers/projects/iterations_controller.rb'
- 'ee/app/controllers/projects/path_locks_controller.rb'
- 'ee/app/controllers/projects/protected_environments_controller.rb'
- 'ee/app/controllers/projects/push_rules_controller.rb'
- 'ee/app/controllers/projects/quality/test_cases_controller.rb'
- 'ee/app/controllers/projects/requirements_management/requirements_controller.rb'
- 'ee/app/controllers/projects/subscriptions_controller.rb'
- 'ee/app/controllers/projects/vulnerability_feedback_controller.rb'
- 'ee/app/finders/ee/group_members_finder.rb'
- 'ee/app/graphql/mutations/app_sec/fuzzing/coverage/corpus/create.rb'
- 'ee/app/helpers/ee/groups/analytics/cycle_analytics_helper.rb'
- 'ee/app/helpers/ee/groups/group_members_helper.rb'
- 'ee/app/helpers/ee/security_orchestration_helper.rb'
- 'ee/app/helpers/groups/ldap_sync_helper.rb'
- 'ee/app/helpers/groups/security_features_helper.rb'
- 'ee/app/helpers/groups/sso_helper.rb'
- 'ee/app/helpers/projects/on_demand_scans_helper.rb'
- 'ee/app/helpers/projects/security/api_fuzzing_configuration_helper.rb'
- 'ee/app/helpers/projects/security/dast_configuration_helper.rb'
- 'ee/app/helpers/projects/security/dast_profiles_helper.rb'
- 'ee/app/helpers/projects/security/discover_helper.rb'
- 'ee/app/helpers/projects/security/sast_configuration_helper.rb'
- 'ee/app/models/analytics/cycle_analytics/group_value_stream.rb'
- 'ee/app/models/analytics/devops_adoption.rb'
- 'ee/app/models/analytics/devops_adoption/enabled_namespace.rb'
- 'ee/app/models/analytics/devops_adoption/snapshot.rb'
- 'ee/app/models/analytics/issues_analytics.rb'
- 'ee/app/models/analytics/language_trend.rb'
- 'ee/app/models/analytics/language_trend/repository_language.rb'
- 'ee/app/models/concerns/geo/replicable_registry.rb'
- 'ee/app/models/concerns/geo/selective_sync.rb'
- 'ee/app/models/concerns/geo/syncable.rb'
- 'ee/app/models/dast/profile_schedule.rb'
- 'ee/app/models/ee/ci/job_artifact.rb'
- 'ee/app/models/ee/namespace/root_excess_storage_size.rb'
- 'ee/app/models/ee/namespace/root_storage_size.rb'
- 'ee/app/models/elastic/reindexing_slice.rb'
- 'ee/app/models/elastic/reindexing_subtask.rb'
- 'ee/app/models/elastic/reindexing_task.rb'
- 'ee/app/models/epic/metrics.rb'
- 'ee/app/models/epic/related_epic_link.rb'
- 'ee/app/models/geo/base_registry.rb'
- 'ee/app/models/geo/container_repository_registry.rb'
- 'ee/app/models/geo/deleted_project.rb'
- 'ee/app/models/geo/design_registry.rb'
- 'ee/app/models/geo/event_log_state.rb'
- 'ee/app/models/geo/group_wiki_repository_registry.rb'
- 'ee/app/models/geo/job_artifact_registry.rb'
- 'ee/app/models/geo/lfs_object_registry.rb'
- 'ee/app/models/geo/merge_request_diff_registry.rb'
- 'ee/app/models/geo/package_file_registry.rb'
- 'ee/app/models/geo/pages_deployment_registry.rb'
- 'ee/app/models/geo/project_registry.rb'
- 'ee/app/models/geo/push_user.rb'
- 'ee/app/models/geo/secondary_usage_data.rb'
- 'ee/app/models/geo/snippet_repository_registry.rb'
- 'ee/app/models/geo/terraform_state_version_registry.rb'
- 'ee/app/models/geo/upload_registry.rb'
- 'ee/app/models/protected_branch/required_code_owners_section.rb'
- 'ee/app/models/protected_branch/unprotect_access_level.rb'
- 'ee/app/models/protected_environment/deploy_access_level.rb'
- 'ee/app/serializers/vulnerabilities/feedback_entity.rb'
- 'ee/app/serializers/vulnerabilities/feedback_serializer.rb'
- 'ee/app/serializers/vulnerabilities/finding_diff_serializer.rb'
- 'ee/app/serializers/vulnerabilities/finding_entity.rb'
- 'ee/app/serializers/vulnerabilities/finding_reports_comparer_entity.rb'
- 'ee/app/serializers/vulnerabilities/finding_serializer.rb'
- 'ee/app/serializers/vulnerabilities/identifier_entity.rb'
- 'ee/app/serializers/vulnerabilities/request_entity.rb'
- 'ee/app/serializers/vulnerabilities/response_entity.rb'
- 'ee/app/serializers/vulnerabilities/scanner_entity.rb'
- 'ee/app/services/concerns/epics/related_epic_links/usage_data_helper.rb'
- 'ee/app/services/ee/projects/after_rename_service.rb'
- 'ee/app/services/ee/projects/disable_deploy_key_service.rb'
- 'ee/app/services/ee/projects/enable_deploy_key_service.rb'
- 'ee/app/services/ee/projects/update_pages_service.rb'
- 'ee/db/fixtures/development/20_burndown.rb'
- 'ee/db/fixtures/development/20_vulnerabilities.rb'
- 'ee/db/fixtures/development/21_dast_profiles.rb'
- 'ee/db/fixtures/development/30_customizable_cycle_analytics.rb'
- 'ee/db/fixtures/development/32_compliance_report_violations.rb'
- 'ee/db/fixtures/development/90_productivity_analytics.rb'
- 'ee/lib/ee/gitlab/analytics/cycle_analytics/aggregated/base_query_builder.rb'
- 'ee/lib/ee/gitlab/analytics/cycle_analytics/base_query_builder.rb'
- 'ee/lib/ee/gitlab/analytics/cycle_analytics/records_fetcher.rb'
- 'ee/lib/ee/gitlab/background_migration/recalculate_vulnerability_finding_signatures_for_findings.rb'
- 'ee/lib/ee/gitlab/throttle.rb'
- 'ee/lib/gitlab/path_locks_finder.rb'
- 'lib/api/error_tracking/client_keys.rb'
- 'lib/api/error_tracking/collector.rb'
- 'lib/api/error_tracking/project_settings.rb'
- 'lib/gitlab/background_migration/drop_invalid_vulnerabilities.rb'
- 'lib/gitlab/background_migration/recalculate_vulnerabilities_occurrences_uuid.rb'
- 'lib/gitlab/background_migration/remove_duplicate_vulnerabilities_findings.rb'
- 'lib/gitlab/background_migration/remove_occurrence_pipelines_and_duplicate_vulnerabilities_findings.rb'
- 'lib/gitlab/background_migration/update_jira_tracker_data_deployment_type_based_on_url.rb'
- 'lib/gitlab/ci/badge/base.rb'
- 'lib/gitlab/ci/badge/coverage/metadata.rb'
- 'lib/gitlab/ci/badge/coverage/report.rb'
- 'lib/gitlab/ci/badge/coverage/template.rb'
- 'lib/gitlab/ci/badge/metadata.rb'
- 'lib/gitlab/ci/badge/pipeline/metadata.rb'
- 'lib/gitlab/ci/badge/pipeline/status.rb'
- 'lib/gitlab/ci/badge/pipeline/template.rb'
- 'lib/gitlab/ci/badge/release/latest_release.rb'
- 'lib/gitlab/ci/badge/release/metadata.rb'
- 'lib/gitlab/ci/badge/release/template.rb'
- 'lib/gitlab/ci/badge/template.rb'
- 'lib/gitlab/ci/build/auto_retry.rb'
- 'lib/gitlab/ci/build/rules/rule.rb'
- 'lib/gitlab/ci/build/rules/rule/clause.rb'
- 'lib/gitlab/ci/build/rules/rule/clause/changes.rb'
- 'lib/gitlab/ci/build/rules/rule/clause/exists.rb'
- 'lib/gitlab/ci/build/rules/rule/clause/if.rb'
- 'lib/gitlab/ci/config/entry/include/rules/rule.rb'
- 'lib/gitlab/ci/config/entry/rules/rule.rb'
- 'lib/gitlab/ci/mask_secret.rb'
- 'lib/gitlab/ci/warnings.rb'
- 'lib/gitlab/config_helper.rb'
- 'lib/gitlab/instrumentation/elasticsearch_transport.rb'
- 'lib/gitlab/serverless/service.rb'
- 'lib/gitlab/usage_data_counters/base_counter.rb'
- 'lib/gitlab/usage_data_counters/ci_template_unique_counter.rb'
- 'lib/gitlab/usage_data_counters/cycle_analytics_counter.rb'
- 'lib/gitlab/usage_data_counters/designs_counter.rb'
- 'lib/gitlab/usage_data_counters/note_counter.rb'
- 'lib/gitlab/usage_data_counters/productivity_analytics_counter.rb'
- 'lib/gitlab/usage_data_counters/service_usage_data_counter.rb'
- 'lib/gitlab/usage_data_counters/snippet_counter.rb'
- 'lib/gitlab/usage_data_counters/source_code_counter.rb'
- 'lib/gitlab/usage_data_counters/wiki_page_counter.rb'
- 'lib/release_highlights/validator/entry.rb'
- 'qa/qa/page/component/project/templates.rb'
- 'scripts/perf/gc/print_gc_stats.rb'
- 'spec/support/inspect_squelch.rb'
- 'spec/support/matchers/markdown_matchers.rb'

View File

@ -0,0 +1,196 @@
---
# Cop supports --auto-correct.
Style/EmptyMethod:
# Offense count: 240
# Temporarily disabled due to too many offenses
Enabled: false
Exclude:
- 'app/controllers/admin/application_settings/appearances_controller.rb'
- 'app/controllers/admin/applications_controller.rb'
- 'app/controllers/admin/broadcast_messages_controller.rb'
- 'app/controllers/admin/deploy_keys_controller.rb'
- 'app/controllers/admin/hook_logs_controller.rb'
- 'app/controllers/admin/hooks_controller.rb'
- 'app/controllers/admin/identities_controller.rb'
- 'app/controllers/admin/labels_controller.rb'
- 'app/controllers/admin/runners_controller.rb'
- 'app/controllers/admin/topics_controller.rb'
- 'app/controllers/admin/usage_trends_controller.rb'
- 'app/controllers/admin/users_controller.rb'
- 'app/controllers/concerns/boards_actions.rb'
- 'app/controllers/groups/milestones_controller.rb'
- 'app/controllers/groups/runners_controller.rb'
- 'app/controllers/groups/settings/applications_controller.rb'
- 'app/controllers/groups/settings/ci_cd_controller.rb'
- 'app/controllers/groups/settings/packages_and_registries_controller.rb'
- 'app/controllers/help_controller.rb'
- 'app/controllers/import/bitbucket_server_controller.rb'
- 'app/controllers/import/fogbugz_controller.rb'
- 'app/controllers/import/manifest_controller.rb'
- 'app/controllers/import/phabricator_controller.rb'
- 'app/controllers/profiles/chat_names_controller.rb'
- 'app/controllers/profiles/passwords_controller.rb'
- 'app/controllers/profiles/preferences_controller.rb'
- 'app/controllers/profiles_controller.rb'
- 'app/controllers/projects/alert_management_controller.rb'
- 'app/controllers/projects/ci/lints_controller.rb'
- 'app/controllers/projects/ci/pipeline_editor_controller.rb'
- 'app/controllers/projects/ci/secure_files_controller.rb'
- 'app/controllers/projects/confluences_controller.rb'
- 'app/controllers/projects/deploy_keys_controller.rb'
- 'app/controllers/projects/environments_controller.rb'
- 'app/controllers/projects/feature_flags_controller.rb'
- 'app/controllers/projects/feature_flags_user_lists_controller.rb'
- 'app/controllers/projects/hook_logs_controller.rb'
- 'app/controllers/projects/import/jira_controller.rb'
- 'app/controllers/projects/imports_controller.rb'
- 'app/controllers/projects/incidents_controller.rb'
- 'app/controllers/projects/jobs_controller.rb'
- 'app/controllers/projects/labels_controller.rb'
- 'app/controllers/projects/learn_gitlab_controller.rb'
- 'app/controllers/projects/mattermosts_controller.rb'
- 'app/controllers/projects/pages_domains_controller.rb'
- 'app/controllers/projects/pipeline_schedules_controller.rb'
- 'app/controllers/projects/product_analytics_controller.rb'
- 'app/controllers/projects/runners_controller.rb'
- 'app/controllers/projects/services_controller.rb'
- 'app/controllers/projects/settings/packages_and_registries_controller.rb'
- 'app/controllers/projects/tags/releases_controller.rb'
- 'app/controllers/projects/terraform_controller.rb'
- 'app/controllers/projects/triggers_controller.rb'
- 'app/controllers/registrations/welcome_controller.rb'
- 'app/controllers/search_controller.rb'
- 'app/graphql/resolvers/concerns/caching_array_resolver.rb'
- 'app/helpers/namespace_storage_limit_alert_helper.rb'
- 'app/helpers/subscribable_banner_helper.rb'
- 'app/helpers/users/callouts_helper.rb'
- 'app/models/ci/bridge.rb'
- 'app/models/concerns/cross_database_modification.rb'
- 'app/models/concerns/reactive_caching.rb'
- 'app/models/concerns/relative_positioning.rb'
- 'app/models/hooks/web_hook.rb'
- 'app/models/integrations/hangouts_chat.rb'
- 'app/models/integrations/microsoft_teams.rb'
- 'app/models/integrations/unify_circuit.rb'
- 'app/models/integrations/webex_teams.rb'
- 'app/models/wiki.rb'
- 'app/services/auto_merge/base_service.rb'
- 'app/services/award_emojis/destroy_service.rb'
- 'app/services/issuable_base_service.rb'
- 'app/services/issues/reopen_service.rb'
- 'app/services/projects/transfer_service.rb'
- 'app/workers/authorized_projects_worker.rb'
- 'app/workers/namespaces/root_statistics_worker.rb'
- 'db/migrate/20210420012444_change_web_hook_events_default.rb'
- 'db/migrate/20210507191949_add_remove_on_issue_close_to_labels.rb'
- 'db/migrate/20210729123101_confirm_security_bot.rb'
- 'db/migrate/20211012134316_clean_up_migrate_merge_request_diff_commit_users.rb'
- 'db/post_migrate/20210511095658_schedule_migrate_project_taggings_context_from_tags_to_topics.rb'
- 'db/post_migrate/20210730170823_schedule_security_setting_creation.rb'
- 'db/post_migrate/20210823132600_remove_duplicate_dast_site_tokens.rb'
- 'db/post_migrate/20210826171758_initialize_throttle_unauthenticated_api_columns.rb'
- 'db/post_migrate/20211028100843_delete_issue_merge_request_taggings_records.rb'
- 'db/post_migrate/20220324032250_migrate_shimo_confluence_service_category.rb'
- 'db/post_migrate/20220412143552_consume_remaining_encrypt_integration_property_jobs.rb'
- 'db/post_migrate/20220425121435_backfill_integrations_enable_ssl_verification.rb'
- 'ee/app/controllers/admin/emails_controller.rb'
- 'ee/app/controllers/admin/geo/designs_controller.rb'
- 'ee/app/controllers/admin/geo/settings_controller.rb'
- 'ee/app/controllers/admin/push_rules_controller.rb'
- 'ee/app/controllers/groups/analytics/ci_cd_analytics_controller.rb'
- 'ee/app/controllers/groups/analytics/cycle_analytics_controller.rb'
- 'ee/app/controllers/groups/analytics/devops_adoption_controller.rb'
- 'ee/app/controllers/groups/compliance_frameworks_controller.rb'
- 'ee/app/controllers/groups/feature_discovery_moments_controller.rb'
- 'ee/app/controllers/groups/hooks_controller.rb'
- 'ee/app/controllers/groups/ldap_group_links_controller.rb'
- 'ee/app/controllers/groups/push_rules_controller.rb'
- 'ee/app/controllers/projects/analytics/code_reviews_controller.rb'
- 'ee/app/controllers/projects/analytics/merge_request_analytics_controller.rb'
- 'ee/app/controllers/projects/incident_management/escalation_policies_controller.rb'
- 'ee/app/controllers/projects/incident_management/oncall_schedules_controller.rb'
- 'ee/app/controllers/projects/on_demand_scans_controller.rb'
- 'ee/app/controllers/projects/security/api_fuzzing_configuration_controller.rb'
- 'ee/app/controllers/projects/security/corpus_management_controller.rb'
- 'ee/app/controllers/projects/security/dast_configuration_controller.rb'
- 'ee/app/controllers/projects/security/dast_profiles_controller.rb'
- 'ee/app/controllers/projects/security/dast_scanner_profiles_controller.rb'
- 'ee/app/controllers/projects/security/dast_site_profiles_controller.rb'
- 'ee/app/controllers/projects/security/sast_configuration_controller.rb'
- 'ee/app/controllers/projects/settings/slacks_controller.rb'
- 'ee/app/controllers/registrations/company_controller.rb'
- 'ee/app/controllers/registrations/verification_controller.rb'
- 'ee/app/controllers/subscriptions/groups_controller.rb'
- 'ee/app/controllers/trial_registrations_controller.rb'
- 'ee/app/controllers/trials_controller.rb'
- 'ee/app/experiments/cart_abandonment_modal_experiment.rb'
- 'ee/app/models/ee/epic.rb'
- 'ee/app/services/feature_flag_issues/destroy_service.rb'
- 'ee/db/geo/migrate/20170906174622_remove_duplicates_from_project_registry.rb'
- 'lib/api/helpers/packages/conan/api_helpers.rb'
- 'lib/api/helpers/projects_helpers.rb'
- 'lib/api/projects_relation_builder.rb'
- 'lib/backup/task.rb'
- 'lib/banzai/filter/inline_embeds_filter.rb'
- 'lib/feature.rb'
- 'lib/gitlab/alert_management/payload/base.rb'
- 'lib/gitlab/background_migration/backfill_iteration_cadence_id_for_boards.rb'
- 'lib/gitlab/background_migration/create_security_setting.rb'
- 'lib/gitlab/background_migration/drop_invalid_remediations.rb'
- 'lib/gitlab/background_migration/fix_incorrect_max_seats_used.rb'
- 'lib/gitlab/background_migration/migrate_approver_to_approval_rules.rb'
- 'lib/gitlab/background_migration/migrate_approver_to_approval_rules_check_progress.rb'
- 'lib/gitlab/background_migration/migrate_approver_to_approval_rules_in_batch.rb'
- 'lib/gitlab/background_migration/migrate_job_artifact_registry_to_ssf.rb'
- 'lib/gitlab/background_migration/migrate_requirements_to_work_items.rb'
- 'lib/gitlab/background_migration/recalculate_vulnerability_finding_signatures_for_findings.rb'
- 'lib/gitlab/background_migration/update_vulnerability_occurrences_location.rb'
- 'lib/gitlab/ci/config/entry/need.rb'
- 'lib/gitlab/ci/config/entry/rules/rule.rb'
- 'lib/gitlab/ci/limit.rb'
- 'lib/gitlab/ci/pipeline/chain/validate/after_config.rb'
- 'lib/gitlab/config/entry/node.rb'
- 'lib/gitlab/config/entry/simplifiable.rb'
- 'lib/gitlab/email/message/in_product_marketing/experience.rb'
- 'lib/gitlab/empty_search_results.rb'
- 'lib/gitlab/git_access.rb'
- 'lib/gitlab/import_export/json/ndjson_writer.rb'
- 'lib/gitlab/null_request_store.rb'
- 'lib/gitlab/usage_data_non_sql_metrics.rb'
- 'lib/mattermost/session.rb'
- 'qa/qa/resource/clusters/agent.rb'
- 'qa/qa/resource/clusters/agent_token.rb'
- 'qa/qa/resource/job.rb'
- 'qa/qa/resource/package.rb'
- 'qa/qa/resource/registry_repository.rb'
- 'qa/qa/resource/runner.rb'
- 'qa/qa/service/cluster_provider/k3d.rb'
- 'qa/qa/service/cluster_provider/k3s.rb'
- 'qa/qa/service/cluster_provider/minikube.rb'
- 'spec/controllers/concerns/check_rate_limit_spec.rb'
- 'spec/controllers/concerns/issuable_actions_spec.rb'
- 'spec/initializers/forbid_sidekiq_in_transactions_spec.rb'
- 'spec/lib/api/helpers/rate_limiter_spec.rb'
- 'spec/lib/gitlab/database/load_balancing/sidekiq_client_middleware_spec.rb'
- 'spec/lib/gitlab/database/load_balancing/sidekiq_server_middleware_spec.rb'
- 'spec/lib/gitlab/database/migration_helpers/restrict_gitlab_schema_spec.rb'
- 'spec/lib/gitlab/database/migrations/background_migration_helpers_spec.rb'
- 'spec/lib/gitlab/database/partitioning/sliding_list_strategy_spec.rb'
- 'spec/lib/gitlab/database/postgresql_adapter/dump_schema_versions_mixin_spec.rb'
- 'spec/lib/gitlab/database/postgresql_database_tasks/load_schema_versions_mixin_spec.rb'
- 'spec/lib/gitlab/git/rugged_impl/use_rugged_spec.rb'
- 'spec/lib/gitlab/repository_archive_rate_limiter_spec.rb'
- 'spec/lib/gitlab/repository_cache_adapter_spec.rb'
- 'spec/lib/gitlab/sidekiq_middleware/client_metrics_spec.rb'
- 'spec/lib/gitlab/sidekiq_middleware/duplicate_jobs/client_spec.rb'
- 'spec/lib/gitlab/sidekiq_middleware/duplicate_jobs/server_spec.rb'
- 'spec/lib/gitlab/sidekiq_middleware/instrumentation_logger_spec.rb'
- 'spec/lib/gitlab/sidekiq_middleware/query_analyzer_spec.rb'
- 'spec/lib/gitlab/sidekiq_middleware/server_metrics_spec.rb'
- 'spec/lib/gitlab/sidekiq_middleware/worker_context/client_spec.rb'
- 'spec/lib/gitlab/sidekiq_middleware/worker_context/server_spec.rb'
- 'spec/lib/gitlab/ssh_public_key_spec.rb'
- 'spec/lib/gitlab/utils/delegator_override/validator_spec.rb'
- 'spec/lib/gitlab/utils/delegator_override_spec.rb'
- 'spec/lib/gitlab/utils/override_spec.rb'
- 'spec/workers/concerns/waitable_worker_spec.rb'

View File

@ -0,0 +1,21 @@
import axios from '../lib/utils/axios_utils';
import { buildApiUrl } from './api_utils';
const JIRA_CONNECT_SUBSCRIPTIONS_PATH = '/api/:version/integrations/jira_connect/subscriptions';
export function addJiraConnectSubscription(namespacePath, { jwt, accessToken }) {
const url = buildApiUrl(JIRA_CONNECT_SUBSCRIPTIONS_PATH);
return axios.post(
url,
{
jwt,
namespace_path: namespacePath,
},
{
headers: {
Authorization: `Bearer ${accessToken}`, // eslint-disable-line @gitlab/require-i18n-strings
},
},
);
}

View File

@ -371,7 +371,7 @@ export default {
events.push(TRACKING_MULTIPLE_FILES_MODE);
}
queueRedisHllEvents(events);
queueRedisHllEvents(events, { verifyCap: true });
this.subscribeToVirtualScrollingEvents();
},

View File

@ -379,6 +379,53 @@ export default {
:class="hasBodyClasses.contentByHash"
data-testid="content-area"
>
<gl-alert
v-if="!showLoadingIcon && file.conflict_type"
variant="danger"
:dismissible="false"
data-testid="conflictsAlert"
>
{{ $options.CONFLICT_TEXT[file.conflict_type] }}
<template v-if="!canMerge">
{{ __('Ask someone with write access to resolve it.') }}
</template>
<gl-sprintf
v-else-if="conflictResolutionPath"
:message="
__(
'You can %{gitlabLinkStart}resolve conflicts on GitLab%{gitlabLinkEnd} or %{resolveLocallyStart}resolve it locally%{resolveLocallyEnd}.',
)
"
>
<template #gitlabLink="{ content }">
<gl-button
:href="conflictResolutionPath"
variant="link"
class="gl-vertical-align-text-bottom"
>{{ content }}</gl-button
>
</template>
<template #resolveLocally="{ content }">
<gl-button
variant="link"
class="gl-vertical-align-text-bottom js-check-out-modal-trigger"
>{{ content }}</gl-button
>
</template>
</gl-sprintf>
<gl-sprintf
v-else
:message="__('You can %{resolveLocallyStart}resolve it locally%{resolveLocallyEnd}.')"
>
<template #resolveLocally="{ content }">
<gl-button
variant="link"
class="gl-vertical-align-text-bottom js-check-out-modal-trigger"
>{{ content }}</gl-button
>
</template>
</gl-sprintf>
</gl-alert>
<gl-loading-icon
v-if="showLoadingIcon"
size="sm"
@ -402,53 +449,6 @@ export default {
<div v-else v-safe-html="errorMessage" class="nothing-here-block"></div>
</div>
<template v-else>
<gl-alert
v-if="file.conflict_type"
variant="danger"
:dismissible="false"
data-testid="conflictsAlert"
>
{{ $options.CONFLICT_TEXT[file.conflict_type] }}
<template v-if="!canMerge">
{{ __('Ask someone with write access to resolve it.') }}
</template>
<gl-sprintf
v-else-if="conflictResolutionPath"
:message="
__(
'You can %{gitlabLinkStart}resolve conflicts on GitLab%{gitlabLinkEnd} or %{resolveLocallyStart}resolve it locally%{resolveLocallyEnd}.',
)
"
>
<template #gitlabLink="{ content }">
<gl-button
:href="conflictResolutionPath"
variant="link"
class="gl-vertical-align-text-bottom"
>{{ content }}</gl-button
>
</template>
<template #resolveLocally="{ content }">
<gl-button
variant="link"
class="gl-vertical-align-text-bottom js-check-out-modal-trigger"
>{{ content }}</gl-button
>
</template>
</gl-sprintf>
<gl-sprintf
v-else
:message="__('You can %{resolveLocallyStart}resolve it locally%{resolveLocallyEnd}.')"
>
<template #resolveLocally="{ content }">
<gl-button
variant="link"
class="gl-vertical-align-text-bottom js-check-out-modal-trigger"
>{{ content }}</gl-button
>
</template>
</gl-sprintf>
</gl-alert>
<div
v-if="showWarning"
class="collapsed-file-warning gl-p-7 gl-bg-orange-50 gl-text-center gl-rounded-bottom-left-base gl-rounded-bottom-right-base"

View File

@ -102,6 +102,8 @@ export const CONFLICT_MARKER_THEIR = 'conflict_marker_their';
// Tracking events
export const DEFER_DURATION = 750;
export const TRACKING_CAP_KEY = 'code_review_events_dispatched';
export const TRACKING_CAP_LENGTH = 86400000; // 24 hours
export const TRACKING_CLICK_DIFF_VIEW_SETTING = 'i_code_review_click_diff_view_setting';
export const TRACKING_DIFF_VIEW_INLINE = 'i_code_review_diff_view_inline';

View File

@ -1,13 +1,31 @@
import { delay } from 'lodash';
import api from '~/api';
import { DEFER_DURATION } from '../constants';
import { DEFER_DURATION, TRACKING_CAP_KEY, TRACKING_CAP_LENGTH } from '../constants';
function trackRedisHllUserEvent(event, deferDuration = 0) {
function shouldDispatchEvent() {
const timestamp = parseInt(localStorage.getItem(TRACKING_CAP_KEY), 10);
if (Number.isNaN(timestamp)) {
return true;
}
return timestamp + TRACKING_CAP_LENGTH < Date.now();
}
export function dispatchRedisHllUserEvent(event, deferDuration = 0) {
delay(() => api.trackRedisHllUserEvent(event), deferDuration);
}
export function queueRedisHllEvents(events) {
export function queueRedisHllEvents(events, { verifyCap = false } = {}) {
if (verifyCap) {
if (!shouldDispatchEvent()) {
return;
}
localStorage.setItem(TRACKING_CAP_KEY, Date.now());
}
events.forEach((event, index) => {
trackRedisHllUserEvent(event, DEFER_DURATION * (index + 1));
dispatchRedisHllUserEvent(event, DEFER_DURATION * (index + 1));
});
}

View File

@ -1,20 +1,30 @@
<script>
import { mapActions } from 'vuex';
import { GlButton } from '@gitlab/ui';
import { helpPagePath } from '~/helpers/help_page_helper';
import { addSubscription } from '~/jira_connect/subscriptions/api';
import { persistAlert, reloadPage } from '~/jira_connect/subscriptions/utils';
import { s__ } from '~/locale';
import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import GroupItemName from '../group_item_name.vue';
import {
INTEGRATIONS_DOC_LINK,
I18N_ADD_SUBSCRIPTION_SUCCESS_ALERT_TITLE,
I18N_ADD_SUBSCRIPTION_SUCCESS_ALERT_MESSAGE,
I18N_ADD_SUBSCRIPTIONS_ERROR_MESSAGE,
} from '../../constants';
export default {
components: {
GlButton,
GroupItemName,
},
mixins: [glFeatureFlagMixin()],
inject: {
addSubscriptionsPath: {
default: '',
},
subscriptionsPath: {
default: '',
},
},
props: {
group: {
@ -32,31 +42,41 @@ export default {
isLoading: false,
};
},
computed: {
oauthEnabled() {
return this.glFeatures.jiraConnectOauth;
},
},
methods: {
onClick() {
...mapActions(['addSubscription']),
async onClick() {
if (this.oauthEnabled) {
this.isLoading = true;
await this.addSubscription({
namespacePath: this.group.full_path,
subscriptionsPath: this.subscriptionsPath,
});
this.isLoading = false;
} else {
this.deprecatedAddSubscription();
}
},
deprecatedAddSubscription() {
this.isLoading = true;
addSubscription(this.addSubscriptionsPath, this.group.full_path)
.then(() => {
persistAlert({
title: s__('Integrations|Namespace successfully linked'),
message: s__(
'Integrations|You should now see GitLab.com activity inside your Jira Cloud issues. %{linkStart}Learn more%{linkEnd}',
),
linkUrl: helpPagePath('integration/jira_development_panel.html', {
anchor: 'use-the-integration',
}),
title: I18N_ADD_SUBSCRIPTION_SUCCESS_ALERT_TITLE,
message: I18N_ADD_SUBSCRIPTION_SUCCESS_ALERT_MESSAGE,
linkUrl: INTEGRATIONS_DOC_LINK,
variant: 'success',
});
reloadPage();
})
.catch((error) => {
this.$emit(
'error',
error?.response?.data?.error ||
s__('Integrations|Failed to link namespace. Please try again.'),
);
this.$emit('error', error?.response?.data?.error || I18N_ADD_SUBSCRIPTIONS_ERROR_MESSAGE);
this.isLoading = false;
});
},

View File

@ -34,12 +34,8 @@ export default {
default: '',
},
},
data() {
return {
user: null,
};
},
computed: {
...mapState(['currentUser']),
...mapState(['alert', 'subscriptions']),
shouldShowAlert() {
return Boolean(this.alert?.message);
@ -48,7 +44,11 @@ export default {
return !isEmpty(this.subscriptions);
},
userSignedIn() {
return Boolean(!this.usersPath || this.user);
if (this.isOauthEnabled) {
return Boolean(this.currentUser);
}
return Boolean(!this.usersPath);
},
isOauthEnabled() {
return this.glFeatures.jiraConnectOauth;
@ -85,8 +85,7 @@ export default {
const { linkUrl, title, message, variant } = retrieveAlert() || {};
this.setAlert({ linkUrl, title, message, variant });
},
onSignInOauth(user) {
this.user = user;
onSignInOauth() {
this.fetchSubscriptionsOauth();
},
onSignInError() {
@ -123,7 +122,11 @@ export default {
</template>
</gl-alert>
<user-link :user-signed-in="userSignedIn" :has-subscriptions="hasSubscriptions" :user="user" />
<user-link
:user-signed-in="userSignedIn"
:has-subscriptions="hasSubscriptions"
:user="currentUser"
/>
<div class="gl-layout-w-limited gl-mx-auto gl-px-5 gl-mb-7">
<sign-in-page

View File

@ -1,4 +1,5 @@
<script>
import { mapActions, mapMutations } from 'vuex';
import { GlButton } from '@gitlab/ui';
import axios from '~/lib/utils/axios_utils';
import {
@ -8,8 +9,8 @@ import {
} from '~/jira_connect/subscriptions/constants';
import { setUrlParams } from '~/lib/utils/url_utility';
import AccessorUtilities from '~/lib/utils/accessor';
import { getCurrentUser } from '~/rest_api';
import { createCodeVerifier, createCodeChallenge } from '../pkce';
import { SET_ACCESS_TOKEN } from '../store/mutation_types';
export default {
components: {
@ -31,6 +32,10 @@ export default {
window.removeEventListener('message', this.handleWindowMessage);
},
methods: {
...mapActions(['loadCurrentUser']),
...mapMutations({
setAccessToken: SET_ACCESS_TOKEN,
}),
async startOAuthFlow() {
this.loading = true;
@ -58,7 +63,6 @@ export default {
async handleWindowMessage(event) {
if (window.origin !== event.origin) {
this.loading = false;
this.handleError();
return;
}
@ -74,8 +78,10 @@ export default {
const code = event.data?.code;
try {
const accessToken = await this.getOAuthToken(code);
await this.loadCurrentUser(accessToken);
await this.loadUser(accessToken);
this.setAccessToken(accessToken);
this.$emit('sign-in');
} catch (e) {
this.handleError();
} finally {
@ -98,13 +104,6 @@ export default {
return data.access_token;
},
async loadUser(accessToken) {
const { data } = await getCurrentUser({
headers: { Authorization: `Bearer ${accessToken}` },
});
this.$emit('sign-in', data);
},
},
i18n: {
defaultButtonText: I18N_DEFAULT_SIGN_IN_BUTTON_TEXT,

View File

@ -1,4 +1,5 @@
import { s__ } from '~/locale';
import { helpPagePath } from '~/helpers/help_page_helper';
export const DEFAULT_GROUPS_PER_PAGE = 10;
export const ALERT_LOCALSTORAGE_KEY = 'gitlab_alert';
@ -11,6 +12,19 @@ export const I18N_DEFAULT_SIGN_IN_ERROR_MESSAGE = s__('Integrations|Failed to si
export const I18N_DEFAULT_SUBSCRIPTIONS_ERROR_MESSAGE = s__(
'Integrations|Failed to load subscriptions.',
);
export const I18N_ADD_SUBSCRIPTION_SUCCESS_ALERT_TITLE = s__(
'Integrations|Namespace successfully linked',
);
export const I18N_ADD_SUBSCRIPTION_SUCCESS_ALERT_MESSAGE = s__(
'Integrations|You should now see GitLab.com activity inside your Jira Cloud issues. %{linkStart}Learn more%{linkEnd}',
);
export const INTEGRATIONS_DOC_LINK = helpPagePath('integration/jira_development_panel', {
anchor: 'use-the-integration',
});
export const I18N_ADD_SUBSCRIPTIONS_ERROR_MESSAGE = s__(
'Integrations|Failed to link namespace. Please try again.',
);
const OAUTH_WINDOW_SIZE = 800;
export const OAUTH_WINDOW_OPTIONS = [

View File

@ -29,7 +29,7 @@ export default {
<sign-in-gitlab-com
v-else
:has-subscriptions="hasSubscriptions"
@sign-in-oauth="$emit('sign-in-oauth', $event)"
@sign-in-oauth="$emit('sign-in-oauth')"
@error="$emit('error', $event)"
/>
</template>

View File

@ -1,10 +1,22 @@
import { fetchSubscriptions as fetchSubscriptionsREST } from '~/jira_connect/subscriptions/api';
import { I18N_DEFAULT_SUBSCRIPTIONS_ERROR_MESSAGE } from '../constants';
import { getCurrentUser } from '~/rest_api';
import { addJiraConnectSubscription } from '~/api/integrations_api';
import {
I18N_ADD_SUBSCRIPTION_SUCCESS_ALERT_TITLE,
I18N_ADD_SUBSCRIPTION_SUCCESS_ALERT_MESSAGE,
INTEGRATIONS_DOC_LINK,
I18N_DEFAULT_SUBSCRIPTIONS_ERROR_MESSAGE,
} from '../constants';
import { getJwt } from '../utils';
import {
SET_SUBSCRIPTIONS,
SET_SUBSCRIPTIONS_LOADING,
SET_SUBSCRIPTIONS_ERROR,
ADD_SUBSCRIPTION_LOADING,
ADD_SUBSCRIPTION_ERROR,
SET_ALERT,
SET_CURRENT_USER,
SET_CURRENT_USER_ERROR,
} from './mutation_types';
export const fetchSubscriptions = async ({ commit }, subscriptionsPath) => {
@ -20,3 +32,42 @@ export const fetchSubscriptions = async ({ commit }, subscriptionsPath) => {
commit(SET_SUBSCRIPTIONS_LOADING, false);
}
};
export const loadCurrentUser = async ({ commit }, accessToken) => {
try {
const { data: user } = await getCurrentUser({
headers: { Authorization: `Bearer ${accessToken}` },
});
commit(SET_CURRENT_USER, user);
} catch (e) {
commit(SET_CURRENT_USER_ERROR, e);
}
};
export const addSubscription = async (
{ commit, state, dispatch },
{ namespacePath, subscriptionsPath },
) => {
try {
commit(ADD_SUBSCRIPTION_LOADING, true);
await addJiraConnectSubscription(namespacePath, {
jwt: await getJwt(),
accessToken: state.accessToken,
});
commit(SET_ALERT, {
title: I18N_ADD_SUBSCRIPTION_SUCCESS_ALERT_TITLE,
message: I18N_ADD_SUBSCRIPTION_SUCCESS_ALERT_MESSAGE,
linkUrl: INTEGRATIONS_DOC_LINK,
variant: 'success',
});
dispatch('fetchSubscriptions', subscriptionsPath);
} catch (e) {
commit(ADD_SUBSCRIPTION_ERROR, e);
} finally {
commit(ADD_SUBSCRIPTION_LOADING, false);
}
};

View File

@ -1,4 +1,13 @@
export const SET_ALERT = 'SET_ALERT';
export const SET_SUBSCRIPTIONS = 'SET_SUBSCRIPTIONS';
export const SET_SUBSCRIPTIONS_LOADING = 'SET_SUBSCRIPTIONS_LOADING';
export const SET_SUBSCRIPTIONS_ERROR = 'SET_SUBSCRIPTIONS_ERROR';
export const ADD_SUBSCRIPTION_LOADING = 'ADD_SUBSCRIPTION_LOADING';
export const ADD_SUBSCRIPTION_ERROR = 'ADD_SUBSCRIPTION_ERROR';
export const SET_CURRENT_USER = 'SET_CURRENT_USER';
export const SET_CURRENT_USER_ERROR = 'SET_CURRENT_USER_ERROR';
export const SET_ACCESS_TOKEN = 'SET_ACCESS_TOKEN';

View File

@ -3,12 +3,18 @@ import {
SET_SUBSCRIPTIONS,
SET_SUBSCRIPTIONS_LOADING,
SET_SUBSCRIPTIONS_ERROR,
ADD_SUBSCRIPTION_LOADING,
ADD_SUBSCRIPTION_ERROR,
SET_CURRENT_USER,
SET_CURRENT_USER_ERROR,
SET_ACCESS_TOKEN,
} from './mutation_types';
export default {
[SET_ALERT](state, { title, message, variant, linkUrl } = {}) {
state.alert = { title, message, variant, linkUrl };
},
[SET_SUBSCRIPTIONS](state, subscriptions = []) {
state.subscriptions = subscriptions;
},
@ -18,4 +24,22 @@ export default {
[SET_SUBSCRIPTIONS_ERROR](state, subscriptionsError) {
state.subscriptionsError = subscriptionsError;
},
[ADD_SUBSCRIPTION_LOADING](state, loading) {
state.addSubscriptionLoading = loading;
},
[ADD_SUBSCRIPTION_ERROR](state, error) {
state.addSubscriptionError = error;
},
[SET_CURRENT_USER](state, currentUser) {
state.currentUser = currentUser;
},
[SET_CURRENT_USER_ERROR](state, currentUserError) {
state.currentUserError = currentUserError;
},
[SET_ACCESS_TOKEN](state, accessToken) {
state.accessToken = accessToken;
},
};

View File

@ -1,8 +1,17 @@
export default function createState({ subscriptions = [], subscriptionsLoading = false } = {}) {
return {
alert: undefined,
subscriptions,
subscriptionsLoading,
subscriptionsError: false,
addSubscriptionLoading: false,
addSubscriptionError: false,
currentUser: null,
currentUserError: null,
accessToken: null,
};
}

View File

@ -60,15 +60,15 @@ export default {
<div
class="gl-display-flex gl-align-items-center gl-pl-4 gl-rounded-base gl-mr-3"
:class="{
'gl-bg-orange-50': blocksMerge,
'gl-bg-gray-50': !blocksMerge,
'gl-bg-orange-50': blocksMerge && !allResolved,
'gl-bg-gray-50': !blocksMerge || allResolved,
'gl-pr-4': allResolved,
'gl-pr-2': !allResolved,
}"
data-testid="discussions-counter-text"
>
<template v-if="allResolved">
{{ __('All threads resolved') }}
{{ __('All threads resolved!') }}
</template>
<template v-else>
{{ n__('%d unresolved thread', '%d unresolved threads', unresolvedDiscussionsCount) }}

View File

@ -44,9 +44,3 @@ $header-height: 40px;
height: calc(100% - #{$header-height});
max-width: 1000px;
}
// needed for external_link
svg.s16 {
width: 16px;
height: 16px;
}

View File

@ -1,7 +1,7 @@
# frozen_string_literal: true
# Concern for handling deprecation arguments.
# https://docs.gitlab.com/ee/development/api_graphql_styleguide.html#deprecating-fields-and-enum-values
# https://docs.gitlab.com/ee/development/api_graphql_styleguide.html#deprecating-schema-items
module GitlabStyleDeprecations
extend ActiveSupport::Concern
@ -11,7 +11,7 @@ module GitlabStyleDeprecations
def gitlab_deprecation(kwargs)
if kwargs[:deprecation_reason].present?
raise ArgumentError, 'Use `deprecated` property instead of `deprecation_reason`. ' \
'See https://docs.gitlab.com/ee/development/api_graphql_styleguide.html#deprecating-fields-arguments-and-enum-values'
'See https://docs.gitlab.com/ee/development/api_graphql_styleguide.html#deprecating-schema-items'
end
deprecation = ::Gitlab::Graphql::Deprecation.parse(kwargs.delete(:deprecated))

View File

@ -88,7 +88,7 @@ module NamespacesHelper
}.to_json
end
def pipeline_usage_quota_app_data(namespace)
def pipeline_usage_app_data(namespace)
{
namespace_actual_plan_name: namespace.actual_plan_name,
namespace_path: namespace.full_path,

View File

@ -11,7 +11,7 @@
= s_('JiraService|You can now close this window and%{br}return to the GitLab for Jira application.').html_safe % { br: '<br>'.html_safe }
- if @jira_app_link
%p= external_link s_('Integrations|Return to GitLab for Jira'), @jira_app_link, class: 'gl-button btn btn-confirm'
%p= link_to s_('Integrations|Return to GitLab for Jira'), @jira_app_link, class: 'gl-button btn btn-confirm'
%p= link_to _('Sign out'), destroy_user_session_path, method: :post

View File

@ -31,11 +31,11 @@
= sprite_icon('chevron-double-lg-left')
.detail-page-header-actions.js-issuable-actions{ class: "#{'gl-align-self-start is-merge-request' if updated_mr_header_enabled}" }
- if @merge_request.source_project
= render 'projects/merge_requests/code_dropdown'
- if can_update_merge_request
= link_to _('Edit'), edit_project_merge_request_path(@project, @merge_request), class: "gl-display-none gl-md-display-block btn gl-button btn-default btn-grouped js-issuable-edit", data: { qa_selector: "edit_button" }
- if @merge_request.source_project
= render 'projects/merge_requests/code_dropdown'
- if current_user
= render 'projects/merge_requests/close_reopen_draft_report_toggle'

View File

@ -21,7 +21,7 @@
.text-secondary
= sprite_icon("rocket", size: 12)
= _("Release")
= link_to release.name, project_release_path(@project, release.tag), class: 'gl-text-blue-600!'
= link_to release.name, project_releases_path(@project, anchor: release.tag), class: 'gl-text-blue-600!'
- if tag.message.present?
%pre.wrap

View File

@ -33,6 +33,7 @@
- credential_management
- database
- dataops
- dedicated
- delivery
- dependency_firewall
- dependency_proxy
@ -52,7 +53,6 @@
- experimentation_conversion
- experimentation_expansion
- feature_flags
- free_user_caps_conversion
- five_minute_production_app
- fulfillment_platform
- fuzz_testing
@ -62,7 +62,6 @@
- gitlab_docs
- global_search
- helm_chart_registry
- horse
- importers
- incident_management
- infrastructure_as_code
@ -101,6 +100,7 @@
- redis
- release_evidence
- release_orchestration
- remote_development
- requirements_management
- review_apps
- runbooks

View File

@ -0,0 +1,8 @@
---
name: delayed_project_import_schedule_worker
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/87438
rollout_issue_url: https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/1681
milestone: '15.0'
type: development
group: group::scalability
default_enabled: false

View File

@ -0,0 +1,16 @@
- name: "Jaeger integration removed in GitLab 15.0" # The headline announcing the removal. i.e. "`CI_PROJECT_CONFIG_PATH` removed in Gitlab 14.0"
announcement_milestone: "14.7" # The milestone when this feature was first announced as deprecated.
announcement_date: "2022-01-22"
removal_milestone: "15.0" # The milestone when this feature is being removed.
removal_date: "2022-05-22" # This should almost always be the 22nd of a month (YYYY-MM-DD), the date of the milestone release when this feature will be removed.
breaking_change: true # Change to true if this removal is a breaking change.
reporter: kbychu # GitLab username of the person reporting the removal
body: | # Do not modify this line, instead modify the lines below.
Tracing in GitLab is an integration with Jaeger, an open-source end-to-end distributed tracing system. GitLab users could previously navigate to their Jaeger instance to gain insight into the performance of a deployed application, tracking each function or microservice that handles a given request. Tracing in GitLab was deprecated in GitLab 14.7, and removed in 15.0. To track work on a possible replacement, see the issue for [Opstrace integration with GitLab](https://gitlab.com/groups/gitlab-org/-/epics/6976).
# The following items are not published on the docs page, but may be used in the future.
stage: Monitor # (optional - may be required in the future) String value of the stage that the feature was created in. e.g., Growth
tiers: [Free] # (optional - may be required in the future) An array of tiers that the feature is available in currently. e.g., [Free, Silver, Gold, Core, Premium, Ultimate]
issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/346540 # (optional) This is a link to the deprecation issue in GitLab
documentation_url: https://docs.gitlab.com/ee/operations/tracing.html # (optional) This is a link to the current documentation page
image_url: # (optional) This is a link to a thumbnail image depicting the feature
video_url: # (optional) Use the youtube thumbnail URL with the structure of https://img.youtube.com/vi/UNIQUEID/hqdefault.jpg

View File

@ -561,7 +561,7 @@ This same warning is displayed when:
The default value for `allow_failure` is:
- `true` for [manual jobs](../jobs/job_control.md#create-a-job-that-must-be-run-manually).
- `false` for manual jobs that also use [`rules`](#rules).
- `false` for jobs that use `when: manual` inside [`rules`](#rules).
- `false` in all other cases.
**Keyword type**: Job keyword. You can use it only as part of a job.

View File

@ -97,7 +97,7 @@ discussed in [Nullable fields](#nullable-fields).
Fields that use the [`feature_flag` property](#feature_flag-property) and the flag is disabled by default are exempt
from the deprecation process, and can be removed at any time without notice.
See the [deprecating fields, arguments, and enum values](#deprecating-fields-arguments-and-enum-values) section for how to deprecate items.
See the [deprecating schema items](#deprecating-schema-items) section for how to deprecate items.
## Global IDs
@ -540,18 +540,18 @@ def foo
end
```
## Deprecating fields, arguments, and enum values
## Deprecating schema items
The GitLab GraphQL API is versionless, which means we maintain backwards
compatibility with older versions of the API with every change.
Rather than removing fields, arguments, or [enum values](#enums), they
must be _deprecated_ instead.
Rather than removing fields, arguments, [enum values](#enums), or [mutations](#mutations),
they must be _deprecated_ instead.
The deprecated parts of the schema can then be removed in a future release
in accordance with the [GitLab deprecation process](../api/graphql/index.md#deprecation-and-removal-process).
Fields, arguments, and enum values are deprecated using the `deprecated` property.
Fields, arguments, enum values, and mutations are deprecated using the `deprecated` property.
The value of the property is a `Hash` of:
- `reason` - Reason for the deprecation.
@ -748,7 +748,7 @@ end
```
Enum values can be deprecated using the
[`deprecated` keyword](#deprecating-fields-arguments-and-enum-values).
[`deprecated` keyword](#deprecating-schema-items).
### Defining GraphQL enums dynamically from Rails enums
@ -1713,7 +1713,7 @@ mount_aliased_mutation 'BarMutation', Mutations::FooMutation
```
This allows us to rename a mutation and continue to support the old name,
when coupled with the [`deprecated`](#deprecating-fields-arguments-and-enum-values)
when coupled with the [`deprecated`](#deprecating-schema-items)
argument.
Example:

View File

@ -85,7 +85,7 @@ voters to agree.
When features are deprecated and removed, update the related documentation.
API documentation follows these guidelines, but the GraphQL docs use
a [separate process](../api_graphql_styleguide.md#deprecating-fields-arguments-and-enum-values).
a [separate process](../api_graphql_styleguide.md#deprecating-schema-items).
### Deprecate a page or topic

View File

@ -132,7 +132,7 @@ GitLab database. [Read more about this requirement, and troubleshooting](postgre
| `plpgsql` | 11.7 |
NOTE:
Support for [PostgreSQL 9.6 and 10 was removed in GitLab 13.0](https://about.gitlab.com/releases/2020/05/22/gitlab-13-0-released/#postgresql-11-is-now-the-minimum-required-version-to-install-gitlab) so that GitLab can benefit from PostgreSQL 11 improvements, such as partitioning. For the schedule of transitioning to PostgreSQL 12, see [the related epic](https://gitlab.com/groups/gitlab-org/-/epics/2184).
Support for [PostgreSQL 9.6 and 10 was removed in GitLab 13.0](https://about.gitlab.com/releases/2020/05/22/gitlab-13-0-released/#postgresql-11-is-now-the-minimum-required-version-to-install-gitlab) so that GitLab can benefit from PostgreSQL 11 improvements, such as partitioning.
#### Additional requirements for GitLab Geo

View File

@ -405,6 +405,27 @@ Incremental backups can also be created from [an untarred backup](#skipping-tar-
sudo gitlab-backup create INCREMENTAL=yes SKIP=tar
```
#### Back up specific repository storages
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/86896) in GitLab 15.0.
When using [multiple repository storages](../administration/repository_storage_paths.md),
repositories from specific repository storages can be backed up separately
using the `REPOSITORIES_STORAGES` option. The option accepts a comma-separated list of
storage names.
For example, for Omnibus GitLab installations:
```shell
sudo gitlab-backup create REPOSITORIES_STORAGES=storage1,storage2
```
For example, for installations from source:
```shell
sudo -u git -H bundle exec rake gitlab:backup:create REPOSITORIES_STORAGES=storage1,storage2
```
#### Uploading backups to a remote (cloud) storage
You can let the backup script upload (using the [Fog library](http://fog.io/))
@ -1217,6 +1238,27 @@ For installations from source:
sudo -u git -H bundle exec rake gitlab:backup:restore BACKUP=timestamp_of_backup SKIP=db,uploads RAILS_ENV=production
```
#### Restore specific repository storages
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/86896) in GitLab 15.0.
When using [multiple repository storages](../administration/repository_storage_paths.md),
repositories from specific repository storages can be restored separately
using the `REPOSITORIES_STORAGES` option. The option accepts a comma-separated list of
storage names.
For example, for Omnibus GitLab installations:
```shell
sudo gitlab-backup restore BACKUP=timestamp_of_backup REPOSITORIES_STORAGES=storage1,storage2
```
For example, for installations from source:
```shell
sudo -u git -H bundle exec rake gitlab:backup:restore BACKUP=timestamp_of_backup REPOSITORIES_STORAGES=storage1,storage2
```
## Alternative backup strategies
If your GitLab instance contains a lot of Git repository data, you may find the

View File

@ -233,6 +233,16 @@ The permissions model for GraphQL is being updated. After 15.0, users with the G
The issue for this removal is [GitLab-#350682](https://gitlab.com/gitlab-org/gitlab/-/issues/350682)
### Jaeger integration removed in GitLab 15.0
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.
Tracing in GitLab is an integration with Jaeger, an open-source end-to-end distributed tracing system. GitLab users could previously navigate to their Jaeger instance to gain insight into the performance of a deployed application, tracking each function or microservice that handles a given request. Tracing in GitLab was deprecated in GitLab 14.7, and removed in 15.0. To track work on a possible replacement, see the issue for [Opstrace integration with GitLab](https://gitlab.com/groups/gitlab-org/-/epics/6976).
### Legacy Geo Admin UI routes
In GitLab 13.0, we introduced new project and design replication details routes in the Geo Admin UI. These routes are `/admin/geo/replication/projects` and `/admin/geo/replication/designs`. We kept the legacy routes and redirected them to the new routes. These legacy routes `/admin/geo/projects` and `/admin/geo/designs` have been removed in GitLab 15.0. Please update any bookmarks or scripts that may use the legacy routes.

View File

@ -243,8 +243,8 @@ table.supported-languages ul {
<td>C#</td>
</tr>
<tr>
<td rowspan="3">Python</td>
<td rowspan="3">3.9</td>
<td rowspan="4">Python</td>
<td rowspan="4">3.9</td>
<td><a href="https://setuptools.readthedocs.io/en/latest/">setuptools</a></td>
<td><code>setup.py</code></td>
<td><a href="https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium">Gemnasium</a></td>
@ -273,6 +273,12 @@ table.supported-languages ul {
<td><a href="https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium">Gemnasium</a></td>
<td>N</td>
</tr>
<tr>
<td><a href="https://python-poetry.org/">Poetry</a><sup><b><a href="#notes-regarding-supported-languages-and-package-managers-4">4</a></b></sup></td>
<td><code>poetry.lock</code></td>
<td><a href="https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium">Gemnasium</a></td>
<td>N</td>
</tr>
<tr>
<td>Scala</td>
<td>N/A</td>
@ -312,6 +318,14 @@ table.supported-languages ul {
Support for <a href="https://www.scala-sbt.org/">sbt</a> 1.3 and above was added in GitLab 13.9.
</p>
</li>
<li>
<a id="notes-regarding-supported-languages-and-package-managers-4"></a>
<p>
Support for <a href="https://python-poetry.org/">Poetry</a> projects with a <code>poetry.lock</code> file was [added in GitLab 15.0](https://gitlab.com/gitlab-org/gitlab/-/issues/7006).
Support for projects without a <code>poetry.lock</code> file is tracked in issue:
<a href="https://gitlab.com/gitlab-org/gitlab/-/issues/32774">Poetry's pyproject.toml support for dependency scanning.</a>
</p>
</li>
</ol>
<!-- markdownlint-enable MD044 -->
@ -328,13 +342,13 @@ The following package managers use lockfiles that GitLab analyzers are capable o
| Package Manager | Supported File Format Versions | Tested Versions |
| ------ | ------ | ------ |
| Bundler | N/A | [1.17.3](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium/-/blob/master/qa/fixtures/ruby-bundler/main/Gemfile.lock#L118), [2.1.4](https://gitlab.com/gitlab-org/security-products/tests/ruby-bundler/-/blob/bundler2-FREEZE/Gemfile.lock#L118) |
| Composer | N/A | [1.x](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium/-/blob/master/qa/fixtures/php-composer/main/composer.lock) |
| Conan | 0.4 | [1.x](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium/-/blob/master/qa/fixtures/c-conan/main/conan.lock) |
| Go | N/A | [1.x](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium/-/blob/master/qa/fixtures/go-modules/main/go.sum) |
| NuGet | v1 | [4.9](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium/-/blob/master/qa/fixtures/csharp-nuget-dotnetcore/main/src/web.api/packages.lock.json#L2) |
| npm | v1, v2 | [6.x](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium/-/blob/master/qa/fixtures/js-npm/main/package-lock.json#L4), [7.x](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium/-/blob/master/qa/fixtures/js-npm/lockfileVersion2/package-lock.json#L4) |
| yarn | v1 | [1.x](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium/-/blob/master/qa/fixtures/js-yarn/main/yarn.lock#L2) |
| Bundler | N/A | [1.17.3](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium/-/blob/master/qa/fixtures/ruby-bundler/default/Gemfile.lock#L118), [2.1.4](https://gitlab.com/gitlab-org/security-products/tests/ruby-bundler/-/blob/bundler2-FREEZE/Gemfile.lock#L118) |
| Composer | N/A | [1.x](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium/-/blob/master/qa/fixtures/php-composer/default/composer.lock) |
| Conan | 0.4 | [1.x](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium/-/blob/master/qa/fixtures/c-conan/default/conan.lock) |
| Go | N/A | [1.x](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium/-/blob/master/qa/fixtures/go-modules/default/go.sum) |
| NuGet | v1 | [4.9](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium/-/blob/master/qa/fixtures/csharp-nuget-dotnetcore/default/src/web.api/packages.lock.json#L2) |j
| npm | v1, v2 | [6.x](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium/-/blob/master/qa/fixtures/js-npm/default/package-lock.json#L4), [7.x](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium/-/blob/master/qa/fixtures/js-npm/lockfileVersion2/package-lock.json#L4) |
| yarn | v1 | [1.x](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium/-/blob/master/qa/fixtures/js-yarn/default/yarn.lock#L2) |
#### Obtaining dependency information by running a package manager to generate a parsable file
@ -413,8 +427,14 @@ If you've run into problems while scanning multiple files, please contribute a c
#### Python
We only execute one installation in the directory where a requirements file has been detected, such as `requirements.txt` or any
variation of this file (for example, `requirements.pip` or `requires.txt`).
We only execute one installation in the directory where either a requirements file or a lock file has been detected. Dependencies are only analyzed by `gemnasium-python` for the first file that is detected. Files are searched for in the following order:
1. `requirements.txt`, `requirements.pip`, or `requires.txt` for projects using Pip.
1. `Pipfile` or `Pipfile.lock` for projects using Pipenv.
1. `poetry.lock` for projects using Poetry.
1. `setup.py` for project using Setuptools.
The search begins with the root directory and then continues with subdirectories if no builds are found in the root directory. Consequently a Poetry lock file in the root directory would be detected before a Pipenv file in a subdirectory.
#### Java and Scala
@ -448,15 +468,13 @@ From GitLab 14.8 the `gemnasium` analyzer scans supported JavaScript projects fo
The analyzer for these languages supports multiple lockfiles.
### Support for additional languages
#### Support for additional languages
Support for additional languages, dependency managers, and dependency files are tracked in the following issues:
| Package Managers | Languages | Supported files | Scan tools | Issue |
| ------------------- | --------- | --------------- | ---------- | ----- |
| [Poetry](https://python-poetry.org/) | Python | `poetry.lock` | [Gemnasium](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium) | [GitLab#7006](https://gitlab.com/gitlab-org/gitlab/-/issues/7006) |
For workarounds, see the [Troubleshooting section](#troubleshooting).
| [Poetry](https://python-poetry.org/) | Python | `pyproject.toml` | [Gemnasium](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium) | [GitLab#32774](https://gitlab.com/gitlab-org/gitlab/-/issues/32774) |
## Contribute your scanner
@ -1088,9 +1106,8 @@ Generally, the approach is the following:
1. Add [`dependencies: [<your-converter-job>]`](../../../ci/yaml/index.md#dependencies)
to your `dependency_scanning` job to make use of the converted definitions files.
For example, the unsupported `poetry.lock` file can be
[converted](https://python-poetry.org/docs/cli/#export)
to the supported `requirements.txt` as follows.
For example, Poetry projects that _only_ have a `pyproject.toml`
file can generate the `poetry.lock` file as follows.
```yaml
include:
@ -1099,15 +1116,11 @@ include:
stages:
- test
variables:
PIP_REQUIREMENTS_FILE: "requirements-converted.txt"
gemnasium-python-dependency_scanning:
# Work around https://gitlab.com/gitlab-org/gitlab/-/issues/7006
# Work around https://gitlab.com/gitlab-org/gitlab/-/issues/32774
before_script:
- pip install poetry # Or via another method: https://python-poetry.org/docs/#installation
- poetry export --output="$PIP_REQUIREMENTS_FILE"
- rm poetry.lock pyproject.toml
- pip install "poetry>=1,<2" # Or via another method: https://python-poetry.org/docs/#installation
- poetry update --lock # Generates the lock file to be analyzed.
```
### `Error response from daemon: error processing tar file: docker-tar: relocation error`

View File

@ -714,6 +714,17 @@ module API
end
end
desc 'Start a task to recalculate repository size for a project' do
detail 'This feature was introduced in GitLab 15.0.'
end
post ':id/repository_size', feature_category: :source_code_management do
authorize_admin_project
user_project.repository.expire_statistics_caches
::Projects::UpdateStatisticsService.new(user_project, nil, statistics: [:repository_size, :lfs_objects_size]).execute
end
desc 'Transfer a project to a new namespace'
params do
requires :namespace, type: String, desc: 'The ID or path of the new namespace'

View File

@ -9,6 +9,11 @@ module Backup
# if some of these files are still there, we don't need them in the backup
LEGACY_PAGES_TMP_PATH = '@pages.tmp'
LIST_ENVS = {
skipped: 'SKIP',
repositories_storages: 'REPOSITORIES_STORAGES'
}.freeze
TaskDefinition = Struct.new(
:enabled, # `true` if the task can be used. Treated as `true` when not specified.
:human_name, # Name of the task used for logging.
@ -32,7 +37,7 @@ module Backup
Feature.enabled?(:incremental_repository_backup) &&
Gitlab::Utils.to_boolean(ENV['INCREMENTAL'], default: false)
@definitions = definitions || build_definitions
@definitions = definitions
end
def create
@ -43,7 +48,9 @@ module Backup
update_backup_information
end
@definitions.keys.each do |task_name|
build_backup_information
definitions.keys.each do |task_name|
run_create_task(task_name)
end
@ -65,10 +72,10 @@ module Backup
end
def run_create_task(task_name)
definition = @definitions[task_name]
build_backup_information
definition = definitions[task_name]
unless definition.enabled?
puts_time "Dumping #{definition.human_name} ... ".color(:blue) + "[DISABLED]".color(:cyan)
return
@ -92,7 +99,7 @@ module Backup
read_backup_information
verify_backup_version
@definitions.keys.each do |task_name|
definitions.keys.each do |task_name|
run_restore_task(task_name) if !skipped?(task_name) && enabled_task?(task_name)
end
@ -111,7 +118,9 @@ module Backup
end
def run_restore_task(task_name)
definition = @definitions[task_name]
read_backup_information
definition = definitions[task_name]
unless definition.enabled?
puts_time "Restoring #{definition.human_name} ... ".color(:blue) + "[DISABLED]".color(:cyan)
@ -143,6 +152,10 @@ module Backup
private
def definitions
@definitions ||= build_definitions
end
def build_definitions
{
'db' => TaskDefinition.new(
@ -212,7 +225,7 @@ module Backup
max_storage_concurrency = ENV['GITLAB_BACKUP_MAX_STORAGE_CONCURRENCY'].presence
strategy = Backup::GitalyBackup.new(progress, incremental: incremental?, max_parallelism: max_concurrency, storage_parallelism: max_storage_concurrency)
Repositories.new(progress, strategy: strategy)
Repositories.new(progress, strategy: strategy, storages: repositories_storages)
end
def build_files_task(app_files_dir, excludes: [])
@ -245,7 +258,8 @@ module Backup
gitlab_version: Gitlab::VERSION,
tar_version: tar_version,
installation_type: Gitlab::INSTALLATION_TYPE,
skipped: ENV["SKIP"]
skipped: ENV['SKIP'],
repositories_storages: ENV['REPOSITORIES_STORAGES']
}
end
@ -256,7 +270,9 @@ module Backup
backup_created_at: Time.zone.now,
gitlab_version: Gitlab::VERSION,
tar_version: tar_version,
installation_type: Gitlab::INSTALLATION_TYPE
installation_type: Gitlab::INSTALLATION_TYPE,
skipped: list_env(:skipped).join(','),
repositories_storages: list_env(:repositories_storages).join(',')
)
end
@ -309,7 +325,7 @@ module Backup
puts_time "Deleting tar staging files ... ".color(:blue)
remove_backup_path(MANIFEST_NAME)
@definitions.each do |_, definition|
definitions.each do |_, definition|
remove_backup_path(definition.cleanup_path || definition.destination_path)
end
@ -443,12 +459,26 @@ module Backup
end
def skipped?(item)
ENV.fetch('SKIP', '').include?(item) ||
backup_information[:skipped] && backup_information[:skipped].include?(item)
skipped.include?(item)
end
def skipped
@skipped ||= list_env(:skipped)
end
def repositories_storages
@repositories_storages ||= list_env(:repositories_storages)
end
def list_env(name)
list = ENV.fetch(LIST_ENVS[name], '').split(',')
list += backup_information[name].split(',') if backup_information[name]
list.uniq!
list
end
def enabled_task?(task_name)
@definitions[task_name].enabled?
definitions[task_name].enabled?
end
def backup_file?(file)
@ -503,7 +533,7 @@ module Backup
end
def backup_contents
[MANIFEST_NAME] + @definitions.reject do |name, definition|
[MANIFEST_NAME] + definitions.reject do |name, definition|
skipped?(name) || !enabled_task?(name) ||
(definition.destination_optional && !File.exist?(File.join(backup_path, definition.destination_path)))
end.values.map(&:destination_path)

View File

@ -6,10 +6,11 @@ module Backup
class Repositories < Task
extend ::Gitlab::Utils::Override
def initialize(progress, strategy:)
def initialize(progress, strategy:, storages: [])
super(progress)
@strategy = strategy
@storages = storages
end
override :dump
@ -35,7 +36,7 @@ module Backup
private
attr_reader :strategy
attr_reader :strategy, :storages
def enqueue_consecutive
enqueue_consecutive_projects
@ -49,7 +50,7 @@ module Backup
end
def enqueue_consecutive_snippets
Snippet.find_each(batch_size: 1000) { |snippet| enqueue_snippet(snippet) }
snippet_relation.find_each(batch_size: 1000) { |snippet| enqueue_snippet(snippet) }
end
def enqueue_project(project)
@ -63,7 +64,15 @@ module Backup
end
def project_relation
Project.includes(:route, :group, namespace: :owner)
scope = Project.includes(:route, :group, namespace: :owner)
scope = scope.id_in(ProjectRepository.for_repository_storage(storages).select(:project_id)) if storages.any?
scope
end
def snippet_relation
scope = Snippet.all
scope = scope.id_in(SnippetRepository.for_repository_storage(storages).select(:snippet_id)) if storages.any?
scope
end
def restore_object_pools
@ -88,7 +97,7 @@ module Backup
def cleanup_snippets_without_repositories
invalid_snippets = []
Snippet.find_each(batch_size: 1000).each do |snippet|
snippet_relation.find_each(batch_size: 1000).each do |snippet|
response = Snippets::RepositoryValidationService.new(nil, snippet).execute
next if response.success?

View File

@ -120,6 +120,7 @@ gemnasium-maven-dependency_scanning:
- '{Pipfile,*/Pipfile,*/*/Pipfile}'
- '{requires.txt,*/requires.txt,*/*/requires.txt}'
- '{setup.py,*/setup.py,*/*/setup.py}'
- '{poetry.lock,*/poetry.lock,*/*/poetry.lock}'
gemnasium-python-dependency_scanning:
extends:

View File

@ -3705,7 +3705,7 @@ msgstr ""
msgid "All protected branches"
msgstr ""
msgid "All threads resolved"
msgid "All threads resolved!"
msgstr ""
msgid "All users must accept the Terms of Service and Privacy Policy to access GitLab"
@ -11318,6 +11318,12 @@ msgstr ""
msgid "DastProfiles|Branch missing"
msgstr ""
msgid "DastProfiles|Change scanner profile"
msgstr ""
msgid "DastProfiles|Change site profile"
msgstr ""
msgid "DastProfiles|Choose a scan method"
msgstr ""
@ -11432,9 +11438,6 @@ msgstr ""
msgid "DastProfiles|No scanner profile selected"
msgstr ""
msgid "DastProfiles|No scanner profile selected."
msgstr ""
msgid "DastProfiles|No scanner profiles created yet"
msgstr ""
@ -11489,9 +11492,6 @@ msgstr ""
msgid "DastProfiles|Scanner name"
msgstr ""
msgid "DastProfiles|Scanner profile"
msgstr ""
msgid "DastProfiles|Scanner profiles define the configuration details of a security scanner. %{linkStart}Learn more%{linkEnd}."
msgstr ""
@ -39027,18 +39027,12 @@ msgstr ""
msgid "ThreatMonitoring|Alerts"
msgstr ""
msgid "ThreatMonitoring|All Environments"
msgstr ""
msgid "ThreatMonitoring|Date and time"
msgstr ""
msgid "ThreatMonitoring|Dismissed"
msgstr ""
msgid "ThreatMonitoring|Environment"
msgstr ""
msgid "ThreatMonitoring|Events"
msgstr ""
@ -39066,9 +39060,6 @@ msgstr ""
msgid "ThreatMonitoring|Resolved"
msgstr ""
msgid "ThreatMonitoring|Something went wrong, unable to fetch environments"
msgstr ""
msgid "ThreatMonitoring|Status"
msgstr ""

View File

@ -74,7 +74,11 @@ module QA
end
def has_linked_pipeline?(title: nil)
title ? find_linked_pipeline_by_title(title) : has_element?(:linked_pipeline_container)
# If the pipeline page has loaded linked pipelines should appear, but it can take a little while,
# especially on busier environments.
retry_until(reload: true, message: 'Waiting for linked pipeline to appear') do
title ? find_linked_pipeline_by_title(title) : has_element?(:linked_pipeline_container)
end
end
alias_method :has_child_pipeline?, :has_linked_pipeline?

View File

@ -44,7 +44,7 @@ module QA
end
it(
'creates a multi-project pipeline',
'creates a multi-project pipeline with artifact download',
testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/358064'
) do
Page::Project::Pipeline::Show.perform do |show|
@ -78,7 +78,10 @@ module QA
job1:
stage: test
tags: ["#{executor}"]
script: echo 'done'
script: echo 'done' > output.txt
artifacts:
paths:
- output.txt
staging:
stage: deploy
@ -96,7 +99,12 @@ module QA
"#{downstream_job_name}":
stage: test
tags: ["#{executor}"]
script: echo 'done'
needs:
- project: #{upstream_project.path_with_namespace}
job: job1
ref: main
artifacts: true
script: cat output.txt
YAML
}
end

View File

@ -60,7 +60,14 @@ module QA
child_job:
stage: test
tags: ["#{project.name}"]
script: echo "Child job done!"
needs:
- project: #{project.path_with_namespace}
job: job1
ref: main
artifacts: true
script:
- cat output.txt
- echo "Child job done!"
YAML
}
@ -84,18 +91,28 @@ module QA
file_path: '.gitlab-ci.yml',
content: <<~YAML
stages:
- build
- test
- deploy
default:
tags: ["#{project.name}"]
job1:
stage: build
script: echo "build success" > output.txt
artifacts:
paths:
- output.txt
job2:
stage: test
trigger:
include: ".child-ci.yml"
strategy: depend
job2:
job3:
stage: deploy
tags: ["#{project.name}"]
script: echo "parent deploy done"
YAML

View File

@ -5,33 +5,76 @@ module RuboCop
module Gitlab
# Cop that enforces use of namespaced classes in order to better identify
# high level domains within the codebase.
#
# @example
# # bad
# class MyClass
# end
#
# module Gitlab
# class MyClass
# end
# end
#
# class Gitlab::MyClass
# end
#
# # good
# module MyDomain
# class MyClass
# end
# end
#
# module Gitlab
# module MyDomain
# class MyClass
# end
# end
# end
#
# class Gitlab::MyDomain::MyClass
# end
class NamespacedClass < RuboCop::Cop::Cop
MSG = 'Classes must be declared inside a module indicating a product domain namespace. For more info: https://gitlab.com/gitlab-org/gitlab/-/issues/212156'
def_node_matcher :compact_namespaced_class?, <<~PATTERN
(class (const (const ...) ...) ...)
PATTERN
# These namespaces are considered top-level semantically.
# Note: Nested namespace like Foo::Bar are also supported.
PSEUDO_TOPLEVEL = %w[Gitlab]
.map { _1.split('::') }.freeze
def on_module(node)
@namespaced = true
add_potential_domain_namespace(node)
end
def on_class(node)
return if @namespaced
# Add potential namespaces from compact definitions like `class Foo::Bar`.
# Remove class name because it's not a domain namespace.
add_potential_domain_namespace(node) { _1.pop }
add_offense(node) unless compact_namespaced_class?(node)
add_offense(node) if domain_namespaces.none?
end
private
def domain_namespaces
@domain_namespaces ||= []
end
def add_potential_domain_namespace(node)
return if domain_namespaces.any?
identifiers = identifiers_for(node)
yield(identifiers) if block_given?
PSEUDO_TOPLEVEL.each do |namespaces|
identifiers.shift(namespaces.size) if namespaces == identifiers.first(namespaces.size)
end
domain_namespaces.concat(identifiers)
end
def identifiers_for(node)
node.identifier.source.sub(/^::/, '').split('::')
end
end
end

View File

@ -239,7 +239,7 @@ RSpec.describe 'Merge request > User posts diff notes', :js do
def should_allow_dismissing_a_comment(line_holder, diff_side = nil)
write_comment_on_line(line_holder, diff_side)
accept_gl_confirm(s_('Notes|Are you sure you want to cancel creating this comment?')) do
accept_gl_confirm(s_('Notes|Are you sure you want to cancel creating this comment?'), button_text: _('Discard changes')) do
find('.js-close-discussion-note-form').click
end

View File

@ -1,11 +1,15 @@
import api from '~/api';
import { DEFER_DURATION } from '~/diffs/constants';
import { DEFER_DURATION, TRACKING_CAP_KEY, TRACKING_CAP_LENGTH } from '~/diffs/constants';
import { queueRedisHllEvents } from '~/diffs/utils/queue_events';
jest.mock('~/api', () => ({
trackRedisHllUserEvent: jest.fn(),
}));
beforeAll(() => {
localStorage.clear();
});
describe('diffs events queue', () => {
describe('queueRedisHllEvents', () => {
it('does not dispatch the event immediately', () => {
@ -17,6 +21,7 @@ describe('diffs events queue', () => {
queueRedisHllEvents(['know_event']);
jest.advanceTimersByTime(DEFER_DURATION + 1);
expect(api.trackRedisHllUserEvent).toHaveBeenCalled();
expect(localStorage.getItem(TRACKING_CAP_KEY)).toBe(null);
});
it('increase defer duration based on the provided events count', () => {
@ -32,5 +37,35 @@ describe('diffs events queue', () => {
deferDuration *= index + 1;
});
});
describe('with tracking cap verification', () => {
const currentTimestamp = Date.now();
beforeEach(() => {
localStorage.clear();
});
it('dispatches the event if cap value is not found', () => {
queueRedisHllEvents(['know_event'], { verifyCap: true });
jest.advanceTimersByTime(DEFER_DURATION + 1);
expect(api.trackRedisHllUserEvent).toHaveBeenCalled();
expect(localStorage.getItem(TRACKING_CAP_KEY)).toBe(currentTimestamp.toString());
});
it('dispatches the event if cap value is less than limit', () => {
localStorage.setItem(TRACKING_CAP_KEY, 1);
queueRedisHllEvents(['know_event'], { verifyCap: true });
jest.advanceTimersByTime(DEFER_DURATION + 1);
expect(api.trackRedisHllUserEvent).toHaveBeenCalled();
expect(localStorage.getItem(TRACKING_CAP_KEY)).toBe(currentTimestamp.toString());
});
it('does not dispatch the event if cap value is greater than limit', () => {
localStorage.setItem(TRACKING_CAP_KEY, currentTimestamp - (TRACKING_CAP_LENGTH + 1));
queueRedisHllEvents(['know_event'], { verifyCap: true });
jest.advanceTimersByTime(DEFER_DURATION + 1);
expect(api.trackRedisHllUserEvent).toHaveBeenCalled();
});
});
});
});

View File

@ -7,21 +7,35 @@ import * as JiraConnectApi from '~/jira_connect/subscriptions/api';
import GroupItemName from '~/jira_connect/subscriptions/components/group_item_name.vue';
import GroupsListItem from '~/jira_connect/subscriptions/components/add_namespace_modal/groups_list_item.vue';
import { persistAlert, reloadPage } from '~/jira_connect/subscriptions/utils';
import {
I18N_ADD_SUBSCRIPTION_SUCCESS_ALERT_TITLE,
I18N_ADD_SUBSCRIPTION_SUCCESS_ALERT_MESSAGE,
INTEGRATIONS_DOC_LINK,
} from '~/jira_connect/subscriptions/constants';
import createStore from '~/jira_connect/subscriptions/store';
import { mockGroup1 } from '../../mock_data';
jest.mock('~/jira_connect/subscriptions/utils');
describe('GroupsListItem', () => {
let wrapper;
let store;
const mockAddSubscriptionsPath = '/addSubscriptionsPath';
const createComponent = ({ mountFn = shallowMount } = {}) => {
const createComponent = ({ mountFn = shallowMount, provide } = {}) => {
store = createStore();
jest.spyOn(store, 'dispatch').mockImplementation();
wrapper = mountFn(GroupsListItem, {
store,
propsData: {
group: mockGroup1,
},
provide: {
addSubscriptionsPath: mockAddSubscriptionsPath,
...provide,
},
});
};
@ -51,65 +65,88 @@ describe('GroupsListItem', () => {
});
describe('on Link button click', () => {
let addSubscriptionSpy;
beforeEach(() => {
createComponent({ mountFn: mount });
addSubscriptionSpy = jest.spyOn(JiraConnectApi, 'addSubscription').mockResolvedValue();
});
it('sets button to loading and sends request', async () => {
expect(findLinkButton().props('loading')).toBe(false);
clickLinkButton();
await nextTick();
expect(findLinkButton().props('loading')).toBe(true);
await waitForPromises();
expect(addSubscriptionSpy).toHaveBeenCalledWith(
mockAddSubscriptionsPath,
mockGroup1.full_path,
);
expect(persistAlert).toHaveBeenCalledWith({
linkUrl: '/help/integration/jira_development_panel.html#use-the-integration',
message:
'You should now see GitLab.com activity inside your Jira Cloud issues. %{linkStart}Learn more%{linkEnd}',
title: 'Namespace successfully linked',
variant: 'success',
});
});
describe('when request is successful', () => {
it('reloads the page', async () => {
clickLinkButton();
await waitForPromises();
expect(reloadPage).toHaveBeenCalled();
});
});
describe('when request has errors', () => {
const mockErrorMessage = 'error message';
const mockError = { response: { data: { error: mockErrorMessage } } };
describe('when jiraConnectOauth feature flag is disabled', () => {
let addSubscriptionSpy;
beforeEach(() => {
addSubscriptionSpy = jest
.spyOn(JiraConnectApi, 'addSubscription')
.mockRejectedValue(mockError);
createComponent({ mountFn: mount });
addSubscriptionSpy = jest.spyOn(JiraConnectApi, 'addSubscription').mockResolvedValue();
});
it('emits `error` event', async () => {
clickLinkButton();
it('sets button to loading and sends request', async () => {
expect(findLinkButton().props('loading')).toBe(false);
clickLinkButton();
await nextTick();
expect(findLinkButton().props('loading')).toBe(true);
await waitForPromises();
expect(reloadPage).not.toHaveBeenCalled();
expect(wrapper.emitted('error')[0][0]).toBe(mockErrorMessage);
expect(addSubscriptionSpy).toHaveBeenCalledWith(
mockAddSubscriptionsPath,
mockGroup1.full_path,
);
expect(persistAlert).toHaveBeenCalledWith({
linkUrl: INTEGRATIONS_DOC_LINK,
message: I18N_ADD_SUBSCRIPTION_SUCCESS_ALERT_MESSAGE,
title: I18N_ADD_SUBSCRIPTION_SUCCESS_ALERT_TITLE,
variant: 'success',
});
});
describe('when request is successful', () => {
it('reloads the page', async () => {
clickLinkButton();
await waitForPromises();
expect(reloadPage).toHaveBeenCalled();
});
});
describe('when request has errors', () => {
const mockErrorMessage = 'error message';
const mockError = { response: { data: { error: mockErrorMessage } } };
beforeEach(() => {
addSubscriptionSpy = jest
.spyOn(JiraConnectApi, 'addSubscription')
.mockRejectedValue(mockError);
});
it('emits `error` event', async () => {
clickLinkButton();
await waitForPromises();
expect(reloadPage).not.toHaveBeenCalled();
expect(wrapper.emitted('error')[0][0]).toBe(mockErrorMessage);
});
});
});
describe('when jiraConnectOauth feature flag is enabled', () => {
const mockSubscriptionsPath = '/subscriptions';
beforeEach(() => {
createComponent({
mountFn: mount,
provide: {
subscriptionsPath: mockSubscriptionsPath,
glFeatures: { jiraConnectOauth: true },
},
});
});
it('dispatches `addSubscription` action', async () => {
clickLinkButton();
await nextTick();
expect(store.dispatch).toHaveBeenCalledWith('addSubscription', {
namespacePath: mockGroup1.full_path,
subscriptionsPath: mockSubscriptionsPath,
});
});
});
});

View File

@ -161,32 +161,6 @@ describe('JiraConnectApp', () => {
});
describe('when user signed out', () => {
describe('when sign in page emits `sign-in-oauth` event', () => {
const mockUser = { name: 'test' };
beforeEach(async () => {
createComponent({
provide: {
usersPath: '/mock',
},
});
findSignInPage().vm.$emit('sign-in-oauth', mockUser);
await nextTick();
});
it('hides sign in page and renders subscriptions page', () => {
expect(findSignInPage().exists()).toBe(false);
expect(findSubscriptionsPage().exists()).toBe(true);
});
it('sets correct UserLink props', () => {
expect(findUserLink().props()).toMatchObject({
user: mockUser,
userSignedIn: true,
});
});
});
describe('when sign in page emits `error` event', () => {
beforeEach(async () => {
createComponent({

View File

@ -12,6 +12,8 @@ import waitForPromises from 'helpers/wait_for_promises';
import httpStatus from '~/lib/utils/http_status';
import AccessorUtilities from '~/lib/utils/accessor';
import { getCurrentUser } from '~/rest_api';
import createStore from '~/jira_connect/subscriptions/store';
import { SET_ACCESS_TOKEN } from '~/jira_connect/subscriptions/store/mutation_types';
jest.mock('~/lib/utils/accessor');
jest.mock('~/jira_connect/subscriptions/utils');
@ -31,9 +33,15 @@ const mockOauthMetadata = {
describe('SignInOauthButton', () => {
let wrapper;
let mockAxios;
let store;
const createComponent = ({ slots } = {}) => {
store = createStore();
jest.spyOn(store, 'dispatch').mockImplementation();
jest.spyOn(store, 'commit').mockImplementation();
wrapper = shallowMount(SignInOauthButton, {
store,
slots,
provide: {
oauthMetadata: mockOauthMetadata,
@ -117,10 +125,6 @@ describe('SignInOauthButton', () => {
await waitForPromises();
});
it('emits `error` event', () => {
expect(wrapper.emitted('error')).toBeTruthy();
});
it('does not emit `sign-in` event', () => {
expect(wrapper.emitted('sign-in')).toBeFalsy();
});
@ -164,25 +168,25 @@ describe('SignInOauthButton', () => {
});
});
it('executes GET request to fetch user data', () => {
expect(getCurrentUser).toHaveBeenCalledWith({
headers: { Authorization: `Bearer ${mockAccessToken}` },
});
it('dispatches loadCurrentUser action', () => {
expect(store.dispatch).toHaveBeenCalledWith('loadCurrentUser', mockAccessToken);
});
it('commits SET_ACCESS_TOKEN mutation with correct access token', () => {
expect(store.commit).toHaveBeenCalledWith(SET_ACCESS_TOKEN, mockAccessToken);
});
it('emits `sign-in` event with user data', () => {
expect(wrapper.emitted('sign-in')[0]).toEqual([mockUser]);
expect(wrapper.emitted('sign-in')[0]).toBeTruthy();
});
});
describe('when API requests fail', () => {
beforeEach(async () => {
jest.spyOn(axios, 'post');
jest.spyOn(axios, 'get');
mockAxios
.onPost(mockOauthMetadata.oauth_token_url)
.replyOnce(httpStatus.INTERNAL_SERVER_ERROR, { access_token: mockAccessToken });
mockAxios.onGet('/api/v4/user').replyOnce(httpStatus.INTERNAL_SERVER_ERROR, mockUser);
.replyOnce(httpStatus.INTERNAL_SERVER_ERROR);
window.dispatchEvent(new MessageEvent('message', mockEvent));
@ -190,7 +194,7 @@ describe('SignInOauthButton', () => {
});
it('emits `error` event', () => {
expect(wrapper.emitted('error')).toBeTruthy();
expect(wrapper.emitted('error')[0]).toEqual([]);
});
it('does not emit `sign-in` event', () => {

View File

@ -74,8 +74,8 @@ describe('SignInPage', () => {
describe('when sign-in-oauth event is emitted', () => {
it('emits another sign-in-oauth event', () => {
findSignInGitlabCom().vm.$emit('sign-in-oauth', 'test');
expect(wrapper.emitted('sign-in-oauth')[0][0]).toBe('test');
findSignInGitlabCom().vm.$emit('sign-in-oauth');
expect(wrapper.emitted('sign-in-oauth')[0]).toEqual([]);
});
});
});

View File

@ -1,10 +1,22 @@
import testAction from 'helpers/vuex_action_helper';
import * as types from '~/jira_connect/subscriptions/store/mutation_types';
import { fetchSubscriptions } from '~/jira_connect/subscriptions/store/actions';
import {
fetchSubscriptions,
loadCurrentUser,
addSubscription,
} from '~/jira_connect/subscriptions/store/actions';
import state from '~/jira_connect/subscriptions/store/state';
import * as api from '~/jira_connect/subscriptions/api';
import { I18N_DEFAULT_SUBSCRIPTIONS_ERROR_MESSAGE } from '~/jira_connect/subscriptions/constants';
import * as userApi from '~/api/user_api';
import * as integrationsApi from '~/api/integrations_api';
import {
I18N_DEFAULT_SUBSCRIPTIONS_ERROR_MESSAGE,
I18N_ADD_SUBSCRIPTION_SUCCESS_ALERT_TITLE,
I18N_ADD_SUBSCRIPTION_SUCCESS_ALERT_MESSAGE,
INTEGRATIONS_DOC_LINK,
} from '~/jira_connect/subscriptions/constants';
import * as utils from '~/jira_connect/subscriptions/utils';
describe('JiraConnect actions', () => {
let mockedState;
@ -60,4 +72,101 @@ describe('JiraConnect actions', () => {
});
});
});
describe('loadCurrentUser', () => {
const mockAccessToken = 'abcd1234';
describe('when API request succeeds', () => {
it('commits the SET_ACCESS_TOKEN and SET_CURRENT_USER mutations', async () => {
const mockUser = { name: 'root' };
jest.spyOn(userApi, 'getCurrentUser').mockResolvedValue({ data: mockUser });
await testAction(
loadCurrentUser,
mockAccessToken,
mockedState,
[{ type: types.SET_CURRENT_USER, payload: mockUser }],
[],
);
expect(userApi.getCurrentUser).toHaveBeenCalledWith({
headers: { Authorization: `Bearer ${mockAccessToken}` },
});
});
});
describe('when API request fails', () => {
it('commits the SET_CURRENT_USER_ERROR mutation', async () => {
jest.spyOn(userApi, 'getCurrentUser').mockRejectedValue();
await testAction(
loadCurrentUser,
mockAccessToken,
mockedState,
[{ type: types.SET_CURRENT_USER_ERROR }],
[],
);
});
});
});
describe('addSubscription', () => {
const mockNamespace = 'gitlab-org/gitlab';
const mockSubscriptionsPath = '/subscriptions';
beforeEach(() => {
jest.spyOn(utils, 'getJwt').mockReturnValue('1234');
});
describe('when API request succeeds', () => {
it('commits the SET_ACCESS_TOKEN and SET_CURRENT_USER mutations', async () => {
jest
.spyOn(integrationsApi, 'addJiraConnectSubscription')
.mockResolvedValue({ success: true });
await testAction(
addSubscription,
{ namespacePath: mockNamespace, subscriptionsPath: mockSubscriptionsPath },
mockedState,
[
{ type: types.ADD_SUBSCRIPTION_LOADING, payload: true },
{
type: types.SET_ALERT,
payload: {
title: I18N_ADD_SUBSCRIPTION_SUCCESS_ALERT_TITLE,
message: I18N_ADD_SUBSCRIPTION_SUCCESS_ALERT_MESSAGE,
linkUrl: INTEGRATIONS_DOC_LINK,
variant: 'success',
},
},
{ type: types.ADD_SUBSCRIPTION_LOADING, payload: false },
],
[{ type: 'fetchSubscriptions', payload: mockSubscriptionsPath }],
);
expect(integrationsApi.addJiraConnectSubscription).toHaveBeenCalledWith(mockNamespace, {
accessToken: null,
jwt: '1234',
});
});
});
describe('when API request fails', () => {
it('commits the SET_CURRENT_USER_ERROR mutation', async () => {
jest.spyOn(integrationsApi, 'addJiraConnectSubscription').mockRejectedValue();
await testAction(
addSubscription,
mockNamespace,
mockedState,
[
{ type: types.ADD_SUBSCRIPTION_LOADING, payload: true },
{ type: types.ADD_SUBSCRIPTION_ERROR },
{ type: types.ADD_SUBSCRIPTION_LOADING, payload: false },
],
[],
);
});
});
});
});

View File

@ -26,14 +26,6 @@ describe('JiraConnect store mutations', () => {
});
});
describe('SET_SUBSCRIPTIONS_LOADING', () => {
it('sets subscriptions loading flag', () => {
mutations.SET_SUBSCRIPTIONS_LOADING(localState, true);
expect(localState.subscriptionsLoading).toBe(true);
});
});
describe('SET_SUBSCRIPTIONS', () => {
it('sets subscriptions loading flag', () => {
const mockSubscriptions = [{ name: 'test' }];
@ -42,4 +34,62 @@ describe('JiraConnect store mutations', () => {
expect(localState.subscriptions).toBe(mockSubscriptions);
});
});
describe('SET_SUBSCRIPTIONS_LOADING', () => {
it('sets subscriptions loading flag', () => {
mutations.SET_SUBSCRIPTIONS_LOADING(localState, true);
expect(localState.subscriptionsLoading).toBe(true);
});
});
describe('SET_SUBSCRIPTIONS_ERROR', () => {
it('sets subscriptions error', () => {
mutations.SET_SUBSCRIPTIONS_ERROR(localState, true);
expect(localState.subscriptionsError).toBe(true);
});
});
describe('ADD_SUBSCRIPTION_LOADING', () => {
it('sets addSubscriptionLoading', () => {
mutations.ADD_SUBSCRIPTION_LOADING(localState, true);
expect(localState.addSubscriptionLoading).toBe(true);
});
});
describe('ADD_SUBSCRIPTION_ERROR', () => {
it('sets addSubscriptionError', () => {
mutations.ADD_SUBSCRIPTION_ERROR(localState, true);
expect(localState.addSubscriptionError).toBe(true);
});
});
describe('SET_CURRENT_USER', () => {
it('sets currentUser', () => {
const mockUser = { name: 'root' };
mutations.SET_CURRENT_USER(localState, mockUser);
expect(localState.currentUser).toBe(mockUser);
});
});
describe('SET_CURRENT_USER_ERROR', () => {
it('sets currentUserError', () => {
mutations.SET_CURRENT_USER_ERROR(localState, true);
expect(localState.currentUserError).toBe(true);
});
});
describe('SET_ACCESS_TOKEN', () => {
it('sets accessToken', () => {
const mockAccessToken = 'asdf1234';
mutations.SET_ACCESS_TOKEN(localState, mockAccessToken);
expect(localState.accessToken).toBe(mockAccessToken);
});
});
});

View File

@ -88,6 +88,7 @@ describe('DiscussionCounter component', () => {
'changes background color to $color if blocksMerge is $blocksMerge',
({ blocksMerge, color }) => {
updateStore();
store.state.unresolvedDiscussionsCount = 1;
wrapper = shallowMount(DiscussionCounter, { store, propsData: { blocksMerge } });
expect(wrapper.find('[data-testid="discussions-counter-text"]').classes()).toContain(color);

View File

@ -269,9 +269,9 @@ RSpec.describe NamespacesHelper do
end
end
describe '#pipeline_usage_quota_app_data' do
describe '#pipeline_usage_app_data' do
it 'returns a hash with necessary data for the frontend' do
expect(helper.pipeline_usage_quota_app_data(user_group)).to eql({
expect(helper.pipeline_usage_app_data(user_group)).to eql({
namespace_actual_plan_name: user_group.actual_plan_name,
namespace_path: user_group.full_path,
namespace_id: user_group.id,

View File

@ -853,6 +853,7 @@ RSpec.describe Backup::Manager do
]
)
allow(File).to receive(:exist?).with(File.join(Gitlab.config.backup.path, 'backup_information.yml')).and_return(true)
stub_env('SKIP', 'something')
end
after do
@ -872,7 +873,7 @@ RSpec.describe Backup::Manager do
backup_created_at: backup_time,
full_backup_id: full_backup_id,
gitlab_version: Gitlab::VERSION,
skipped: 'tar'
skipped: 'something,tar'
)
end

View File

@ -5,13 +5,15 @@ require 'spec_helper'
RSpec.describe Backup::Repositories do
let(:progress) { spy(:stdout) }
let(:strategy) { spy(:strategy) }
let(:storages) { [] }
let(:destination) { 'repositories' }
let(:backup_id) { 'backup_id' }
subject do
described_class.new(
progress,
strategy: strategy
strategy: strategy,
storages: storages
)
end
@ -67,17 +69,50 @@ RSpec.describe Backup::Repositories do
end.count
create_list(:project, 2, :repository)
create_list(:snippet, 2, :repository)
expect do
subject.dump(destination, backup_id)
end.not_to exceed_query_limit(control_count)
end
describe 'storages' do
let(:storages) { %w{default} }
let_it_be(:project) { create(:project, :repository) }
before do
stub_storage_settings('test_second_storage' => {
'gitaly_address' => Gitlab.config.repositories.storages.default.gitaly_address,
'path' => TestEnv::SECOND_STORAGE_PATH
})
end
it 'calls enqueue for all repositories on the specified storage', :aggregate_failures do
excluded_project = create(:project, :repository, repository_storage: 'test_second_storage')
excluded_project_snippet = create(:project_snippet, :repository, project: excluded_project)
excluded_project_snippet.track_snippet_repository('test_second_storage')
excluded_personal_snippet = create(:personal_snippet, :repository, author: excluded_project.first_owner)
excluded_personal_snippet.track_snippet_repository('test_second_storage')
subject.dump(destination, backup_id)
expect(strategy).to have_received(:start).with(:create, destination, backup_id: backup_id)
expect(strategy).not_to have_received(:enqueue).with(excluded_project, Gitlab::GlRepository::PROJECT)
expect(strategy).not_to have_received(:enqueue).with(excluded_project_snippet, Gitlab::GlRepository::SNIPPET)
expect(strategy).not_to have_received(:enqueue).with(excluded_personal_snippet, Gitlab::GlRepository::SNIPPET)
expect(strategy).to have_received(:enqueue).with(project, Gitlab::GlRepository::PROJECT)
expect(strategy).to have_received(:enqueue).with(project, Gitlab::GlRepository::WIKI)
expect(strategy).to have_received(:enqueue).with(project, Gitlab::GlRepository::DESIGN)
expect(strategy).to have_received(:finish!)
end
end
end
describe '#restore' do
let_it_be(:project) { create(:project) }
let_it_be(:personal_snippet) { create(:personal_snippet, author: project.first_owner) }
let_it_be(:project_snippet) { create(:project_snippet, project: project, author: project.first_owner) }
let_it_be(:project) { create(:project, :repository) }
let_it_be(:personal_snippet) { create(:personal_snippet, :repository, author: project.first_owner) }
let_it_be(:project_snippet) { create(:project_snippet, :repository, project: project, author: project.first_owner) }
it 'calls enqueue for each repository type', :aggregate_failures do
subject.restore(destination)
@ -116,9 +151,6 @@ RSpec.describe Backup::Repositories do
context 'cleanup snippets' do
before do
create(:snippet_repository, snippet: personal_snippet)
create(:snippet_repository, snippet: project_snippet)
error_response = ServiceResponse.error(message: "Repository has more than one branch")
allow(Snippets::RepositoryValidationService).to receive_message_chain(:new, :execute).and_return(error_response)
end
@ -146,5 +178,35 @@ RSpec.describe Backup::Repositories do
expect(gitlab_shell.repository_exists?(shard_name, path)).to eq false
end
end
context 'storages' do
let(:storages) { %w{default} }
before do
stub_storage_settings('test_second_storage' => {
'gitaly_address' => Gitlab.config.repositories.storages.default.gitaly_address,
'path' => TestEnv::SECOND_STORAGE_PATH
})
end
it 'calls enqueue for all repositories on the specified storage', :aggregate_failures do
excluded_project = create(:project, :repository, repository_storage: 'test_second_storage')
excluded_project_snippet = create(:project_snippet, :repository, project: excluded_project)
excluded_project_snippet.track_snippet_repository('test_second_storage')
excluded_personal_snippet = create(:personal_snippet, :repository, author: excluded_project.first_owner)
excluded_personal_snippet.track_snippet_repository('test_second_storage')
subject.restore(destination)
expect(strategy).to have_received(:start).with(:restore, destination)
expect(strategy).not_to have_received(:enqueue).with(excluded_project, Gitlab::GlRepository::PROJECT)
expect(strategy).not_to have_received(:enqueue).with(excluded_project_snippet, Gitlab::GlRepository::SNIPPET)
expect(strategy).not_to have_received(:enqueue).with(excluded_personal_snippet, Gitlab::GlRepository::SNIPPET)
expect(strategy).to have_received(:enqueue).with(project, Gitlab::GlRepository::PROJECT)
expect(strategy).to have_received(:enqueue).with(project, Gitlab::GlRepository::WIKI)
expect(strategy).to have_received(:enqueue).with(project, Gitlab::GlRepository::DESIGN)
expect(strategy).to have_received(:finish!)
end
end
end
end

View File

@ -4510,6 +4510,43 @@ RSpec.describe API::Projects do
end
end
describe 'POST /projects/:id/repository_size' do
let(:update_statistics_service) { Projects::UpdateStatisticsService.new(project, nil, statistics: [:repository_size, :lfs_objects_size]) }
before do
allow(Projects::UpdateStatisticsService).to receive(:new).with(project, nil, statistics: [:repository_size, :lfs_objects_size]).and_return(update_statistics_service)
end
context 'when authenticated as owner' do
it 'starts the housekeeping process' do
expect(update_statistics_service).to receive(:execute).once
post api("/projects/#{project.id}/repository_size", user)
expect(response).to have_gitlab_http_status(:created)
end
end
context 'when authenticated as developer' do
before do
project_member
end
it 'returns forbidden error' do
post api("/projects/#{project.id}/repository_size", user3)
expect(response).to have_gitlab_http_status(:forbidden)
end
end
context 'when unauthenticated' do
it 'returns authentication error' do
post api("/projects/#{project.id}/repository_size")
expect(response).to have_gitlab_http_status(:unauthorized)
end
end
end
describe 'PUT /projects/:id/transfer' do
context 'when authenticated as owner' do
let(:group) { create :group }

View File

@ -1,72 +1,125 @@
# frozen_string_literal: true
require 'fast_spec_helper'
require 'rubocop/rspec/support'
require_relative '../../../../rubocop/cop/gitlab/namespaced_class'
RSpec.describe RuboCop::Cop::Gitlab::NamespacedClass do
subject(:cop) { described_class.new }
it 'flags a class definition without namespace' do
expect_offense(<<~SOURCE)
class MyClass
^^^^^^^^^^^^^ #{described_class::MSG}
end
SOURCE
end
shared_examples 'enforces namespaced classes' do
def namespaced(code)
return code unless namespace
it 'flags a class definition with inheritance without namespace' do
expect_offense(<<~SOURCE)
class MyClass < ApplicationRecord
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ #{described_class::MSG}
def some_method
true
<<~SOURCE
module #{namespace}
#{code}
end
end
SOURCE
end
SOURCE
end
it 'does not flag the class definition with namespace in separate lines' do
expect_no_offenses(<<~SOURCE)
module MyModule
it 'flags a class definition without additional namespace' do
expect_offense(namespaced(<<~SOURCE))
class MyClass
^^^^^^^^^^^^^ #{described_class::MSG}
end
SOURCE
end
it 'flags a compact class definition without additional namespace' do
expect_offense(<<~SOURCE, namespace: namespace)
class %{namespace}::MyClass
^{namespace}^^^^^^^^^^^^^^^ #{described_class::MSG}
end
SOURCE
end
it 'flags a class definition with inheritance without additional namespace' do
expect_offense(namespaced(<<~SOURCE))
class MyClass < ApplicationRecord
end
class MyOtherClass
def other_method
1 + 1
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ #{described_class::MSG}
def some_method
true
end
end
end
SOURCE
end
SOURCE
end
it 'does not flag the class definition with nested namespace in separate lines' do
expect_no_offenses(<<~SOURCE)
module TopLevelModule
module NestedModule
it 'does not flag the class definition with namespace in separate lines' do
expect_no_offenses(namespaced(<<~SOURCE))
module MyModule
class MyClass < ApplicationRecord
end
class MyOtherClass
def other_method
1 + 1
end
end
end
SOURCE
end
it 'does not flag the class definition with nested namespace in separate lines' do
expect_no_offenses(namespaced(<<~SOURCE))
module TopLevelModule
module NestedModule
class MyClass
end
end
end
SOURCE
end
it 'does not flag the class definition nested inside namespaced class' do
expect_no_offenses(namespaced(<<~SOURCE))
module TopLevelModule
class TopLevelClass
class MyClass
end
end
end
SOURCE
end
it 'does not flag the class definition nested inside compact namespace' do
expect_no_offenses(<<~SOURCE)
module #{namespace}::TopLevelModule
class MyClass
end
end
end
SOURCE
end
SOURCE
end
it 'does not flag the class definition nested inside namespaced class' do
expect_no_offenses(<<~SOURCE)
module TopLevelModule
class TopLevelClass
class MyClass
end
it 'does not flag a compact namespaced class definition' do
expect_no_offenses(namespaced(<<~SOURCE))
class MyModule::MyClass < ApplicationRecord
end
end
SOURCE
SOURCE
end
it 'does not flag a truly compact namespaced class definition' do
expect_no_offenses(<<~SOURCE, namespace: namespace)
class %{namespace}::MyModule::MyClass < ApplicationRecord
end
SOURCE
end
end
it 'does not flag a compact namespaced class definition' do
expect_no_offenses(<<~SOURCE)
class MyModule::MyClass < ApplicationRecord
end
SOURCE
context 'without top-level namespace' do
let(:namespace) { nil }
it_behaves_like 'enforces namespaced classes'
end
context 'with Gitlab namespace' do
let(:namespace) { 'Gitlab' }
it_behaves_like 'enforces namespaced classes'
end
context 'with ::Gitlab namespace' do
let(:namespace) { '::Gitlab' }
it_behaves_like 'enforces namespaced classes'
end
end

View File

@ -6,7 +6,7 @@ RSpec.shared_examples 'Gitlab-style deprecations' do
expect { subject(deprecation_reason: 'foo') }.to raise_error(
ArgumentError,
'Use `deprecated` property instead of `deprecation_reason`. ' \
'See https://docs.gitlab.com/ee/development/api_graphql_styleguide.html#deprecating-fields-arguments-and-enum-values'
'See https://docs.gitlab.com/ee/development/api_graphql_styleguide.html#deprecating-schema-items'
)
end

View File

@ -377,21 +377,6 @@ RSpec.describe 'gitlab:app namespace rake task', :delete do
expect(tar_lines).to include(a_string_matching(repo_name))
end
end
def move_repository_to_secondary(record)
Gitlab::GitalyClient::StorageSettings.allow_disk_access do
default_shard_legacy_path = Gitlab.config.repositories.storages.default.legacy_disk_path
secondary_legacy_path = Gitlab.config.repositories.storages[second_storage_name].legacy_disk_path
dst_dir = File.join(secondary_legacy_path, File.dirname(record.disk_path))
FileUtils.mkdir_p(dst_dir) unless Dir.exist?(dst_dir)
FileUtils.mv(
File.join(default_shard_legacy_path, record.disk_path + '.git'),
File.join(secondary_legacy_path, record.disk_path + '.git')
)
end
end
end
context 'no concurrency' do
@ -405,6 +390,66 @@ RSpec.describe 'gitlab:app namespace rake task', :delete do
it_behaves_like 'includes repositories in all repository storages'
end
context 'REPOSITORIES_STORAGES set' do
before do
stub_env('REPOSITORIES_STORAGES', default_storage_name)
end
it 'includes repositories in default repository storage', :aggregate_failures do
project_a = create(:project, :repository)
project_snippet_a = create(:project_snippet, :repository, project: project_a, author: project_a.first_owner)
project_b = create(:project, :repository, repository_storage: second_storage_name)
project_snippet_b = create(:project_snippet, :repository, project: project_b, author: project_b.first_owner)
project_snippet_b.snippet_repository.update!(shard: project_b.project_repository.shard)
create(:wiki_page, container: project_a)
create(:design, :with_file, issue: create(:issue, project: project_a))
move_repository_to_secondary(project_b)
move_repository_to_secondary(project_snippet_b)
expect { run_rake_task('gitlab:backup:create') }.to output.to_stdout_from_any_process
tar_contents, exit_status = Gitlab::Popen.popen(
%W{tar -tvf #{backup_tar} repositories}
)
tar_lines = tar_contents.lines.grep(/\.bundle/)
expect(exit_status).to eq(0)
[
"#{project_a.disk_path}/.+/001.bundle",
"#{project_a.disk_path}.wiki/.+/001.bundle",
"#{project_a.disk_path}.design/.+/001.bundle",
"#{project_snippet_a.disk_path}/.+/001.bundle"
].each do |repo_name|
expect(tar_lines).to include(a_string_matching(repo_name))
end
[
"#{project_b.disk_path}/.+/001.bundle",
"#{project_snippet_b.disk_path}/.+/001.bundle"
].each do |repo_name|
expect(tar_lines).not_to include(a_string_matching(repo_name))
end
end
end
def move_repository_to_secondary(record)
Gitlab::GitalyClient::StorageSettings.allow_disk_access do
default_shard_legacy_path = Gitlab.config.repositories.storages.default.legacy_disk_path
secondary_legacy_path = Gitlab.config.repositories.storages[second_storage_name].legacy_disk_path
dst_dir = File.join(secondary_legacy_path, File.dirname(record.disk_path))
FileUtils.mkdir_p(dst_dir) unless Dir.exist?(dst_dir)
FileUtils.mv(
File.join(default_shard_legacy_path, record.disk_path + '.git'),
File.join(secondary_legacy_path, record.disk_path + '.git')
)
end
end
end
context 'concurrency settings' do
@ -420,7 +465,7 @@ RSpec.describe 'gitlab:app namespace rake task', :delete do
stub_env('GITLAB_BACKUP_MAX_STORAGE_CONCURRENCY', 2)
expect(::Backup::Repositories).to receive(:new)
.with(anything, strategy: anything)
.with(anything, strategy: anything, storages: [])
.and_call_original
expect(::Backup::GitalyBackup).to receive(:new).with(anything, max_parallelism: 5, storage_parallelism: 2, incremental: false).and_call_original

View File

@ -27,7 +27,7 @@ RSpec.describe 'projects/tags/index.html.haml' do
it 'renders links to the Releases page for tags associated with a release' do
render
expect(rendered).to have_link(release.name, href: project_release_path(project, release.tag))
expect(rendered).to have_link(release.name, href: project_releases_path(project, anchor: release.tag))
end
context 'when the most recent build for a tag has artifacts' do

View File

@ -383,7 +383,7 @@ RSpec.describe 'Every Sidekiq worker' do
'ProjectDailyStatisticsWorker' => 3,
'ProjectDestroyWorker' => 3,
'ProjectExportWorker' => false,
'ProjectImportScheduleWorker' => false,
'ProjectImportScheduleWorker' => 1,
'ProjectScheduleBulkRepositoryShardMovesWorker' => 3,
'ProjectServiceWorker' => 3,
'ProjectTemplateExportWorker' => false,