Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
74dd67ddea
commit
3e1c760141
|
|
@ -7,9 +7,11 @@ require:
|
|||
- rubocop-rspec
|
||||
|
||||
inherit_from:
|
||||
- .rubocop_manual_todo.yml
|
||||
- .rubocop_todo.yml
|
||||
- ./rubocop/rubocop-migrations.yml
|
||||
- ./rubocop/rubocop-usage-data.yml
|
||||
- ./rubocop/rubocop-code_reuse.yml
|
||||
|
||||
inherit_mode:
|
||||
merge:
|
||||
|
|
|
|||
|
|
@ -0,0 +1,755 @@
|
|||
FactoryBot/InlineAssociation:
|
||||
Exclude:
|
||||
- 'ee/spec/factories/analytics/cycle_analytics/group_stages.rb'
|
||||
- 'ee/spec/factories/geo/event_log.rb'
|
||||
- 'ee/spec/factories/groups.rb'
|
||||
- 'ee/spec/factories/merge_request_blocks.rb'
|
||||
- 'ee/spec/factories/vulnerabilities/feedback.rb'
|
||||
- 'spec/factories/atlassian_identities.rb'
|
||||
- 'spec/factories/design_management/design_at_version.rb'
|
||||
- 'spec/factories/design_management/designs.rb'
|
||||
- 'spec/factories/design_management/versions.rb'
|
||||
- 'spec/factories/events.rb'
|
||||
- 'spec/factories/git_wiki_commit_details.rb'
|
||||
- 'spec/factories/gitaly/commit.rb'
|
||||
- 'spec/factories/go_module_commits.rb'
|
||||
- 'spec/factories/go_module_versions.rb'
|
||||
- 'spec/factories/go_modules.rb'
|
||||
- 'spec/factories/group_group_links.rb'
|
||||
- 'spec/factories/import_export_uploads.rb'
|
||||
- 'spec/factories/merge_requests.rb'
|
||||
- 'spec/factories/notes.rb'
|
||||
- 'spec/factories/packages.rb'
|
||||
- 'spec/factories/packages/package_file.rb'
|
||||
- 'spec/factories/sent_notifications.rb'
|
||||
- 'spec/factories/uploads.rb'
|
||||
- 'spec/factories/wiki_pages.rb'
|
||||
|
||||
Graphql/IDType:
|
||||
Exclude:
|
||||
- 'ee/app/graphql/ee/mutations/issues/update.rb'
|
||||
- 'ee/app/graphql/mutations/iterations/update.rb'
|
||||
- 'ee/app/graphql/resolvers/iterations_resolver.rb'
|
||||
- 'app/graphql/mutations/boards/issues/issue_move_list.rb'
|
||||
- 'app/graphql/mutations/issues/update.rb'
|
||||
- 'app/graphql/mutations/metrics/dashboard/annotations/delete.rb'
|
||||
- 'app/graphql/mutations/snippets/destroy.rb'
|
||||
- 'app/graphql/mutations/snippets/mark_as_spam.rb'
|
||||
- 'app/graphql/mutations/snippets/update.rb'
|
||||
- 'app/graphql/resolvers/design_management/design_at_version_resolver.rb'
|
||||
- 'app/graphql/resolvers/design_management/design_resolver.rb'
|
||||
- 'app/graphql/resolvers/design_management/designs_resolver.rb'
|
||||
- 'app/graphql/resolvers/design_management/version/design_at_version_resolver.rb'
|
||||
- 'app/graphql/resolvers/design_management/version_in_collection_resolver.rb'
|
||||
- 'app/graphql/resolvers/design_management/version_resolver.rb'
|
||||
- 'app/graphql/resolvers/design_management/versions_resolver.rb'
|
||||
- 'app/graphql/resolvers/error_tracking/sentry_detailed_error_resolver.rb'
|
||||
- 'app/graphql/resolvers/error_tracking/sentry_error_stack_trace_resolver.rb'
|
||||
- 'app/graphql/resolvers/snippets_resolver.rb'
|
||||
- 'app/graphql/resolvers/user_merge_requests_resolver.rb'
|
||||
|
||||
Rails/SaveBang:
|
||||
Exclude:
|
||||
- 'ee/spec/controllers/projects/merge_requests_controller_spec.rb'
|
||||
- 'ee/spec/controllers/subscriptions_controller_spec.rb'
|
||||
- 'ee/spec/frontend/fixtures/analytics.rb'
|
||||
- 'ee/spec/graphql/resolvers/vulnerabilities_resolver_spec.rb'
|
||||
- 'ee/spec/initializers/fog_google_https_private_urls_spec.rb'
|
||||
- 'ee/spec/lib/analytics/merge_request_metrics_calculator_spec.rb'
|
||||
- 'ee/spec/lib/ee/gitlab/auth/ldap/sync/group_spec.rb'
|
||||
- 'ee/spec/lib/ee/gitlab/checks/push_rules/commit_check_spec.rb'
|
||||
- 'ee/spec/lib/ee/gitlab/ci/pipeline/quota/activity_spec.rb'
|
||||
- 'ee/spec/lib/gitlab/auth/ldap/access_spec.rb'
|
||||
- 'ee/spec/lib/gitlab/auth/o_auth/user_spec.rb'
|
||||
- 'ee/spec/lib/gitlab/auth/saml/user_spec.rb'
|
||||
- 'ee/spec/lib/gitlab/background_migration/fix_orphan_promoted_issues_spec.rb'
|
||||
- 'ee/spec/lib/gitlab/elastic/search_results_spec.rb'
|
||||
- 'ee/spec/lib/gitlab/email/handler/ee/service_desk_handler_spec.rb'
|
||||
- 'ee/spec/lib/gitlab/geo_spec.rb'
|
||||
- 'ee/spec/lib/gitlab/git_access_spec.rb'
|
||||
- 'ee/spec/lib/gitlab/import_export/group/relation_factory_spec.rb'
|
||||
- 'ee/spec/lib/gitlab/mirror_spec.rb'
|
||||
- 'ee/spec/mailers/notify_spec.rb'
|
||||
- 'ee/spec/migrations/fix_any_approver_rule_for_projects_spec.rb'
|
||||
- 'ee/spec/migrations/geo/migrate_ci_job_artifacts_to_separate_registry_spec.rb'
|
||||
- 'ee/spec/migrations/geo/migrate_lfs_objects_to_separate_registry_spec.rb'
|
||||
- 'ee/spec/migrations/schedule_merge_request_any_approval_rule_migration_spec.rb'
|
||||
- 'ee/spec/migrations/schedule_project_any_approval_rule_migration_spec.rb'
|
||||
- 'ee/spec/models/application_setting_spec.rb'
|
||||
- 'ee/spec/models/approval_merge_request_rule_spec.rb'
|
||||
- 'ee/spec/models/approval_project_rule_spec.rb'
|
||||
- 'ee/spec/models/burndown_spec.rb'
|
||||
- 'ee/spec/models/ci/pipeline_spec.rb'
|
||||
- 'ee/spec/models/ci/subscriptions/project_spec.rb'
|
||||
- 'ee/spec/models/ee/appearance_spec.rb'
|
||||
- 'ee/spec/models/ee/ci/job_artifact_spec.rb'
|
||||
- 'ee/spec/models/ee/protected_branch_spec.rb'
|
||||
- 'ee/spec/models/ee/protected_ref_access_spec.rb'
|
||||
- 'ee/spec/models/ee/protected_ref_spec.rb'
|
||||
- 'ee/spec/models/elasticsearch_indexed_namespace_spec.rb'
|
||||
- 'ee/spec/models/environment_spec.rb'
|
||||
- 'ee/spec/models/epic_spec.rb'
|
||||
- 'ee/spec/models/geo/project_registry_spec.rb'
|
||||
- 'ee/spec/models/geo_node_spec.rb'
|
||||
- 'ee/spec/models/geo_node_status_spec.rb'
|
||||
- 'ee/spec/models/gitlab_subscription_spec.rb'
|
||||
- 'ee/spec/models/group_spec.rb'
|
||||
- 'ee/spec/models/issue_spec.rb'
|
||||
- 'ee/spec/models/label_note_spec.rb'
|
||||
- 'ee/spec/models/lfs_object_spec.rb'
|
||||
- 'ee/spec/models/license_spec.rb'
|
||||
- 'ee/spec/models/merge_request_spec.rb'
|
||||
- 'ee/spec/models/merge_train_spec.rb'
|
||||
- 'spec/models/packages/package_spec.rb'
|
||||
- 'ee/spec/models/project_ci_cd_setting_spec.rb'
|
||||
- 'ee/spec/models/project_spec.rb'
|
||||
- 'ee/spec/models/protected_environment_spec.rb'
|
||||
- 'ee/spec/models/repository_spec.rb'
|
||||
- 'ee/spec/models/scim_identity_spec.rb'
|
||||
- 'ee/spec/models/scim_oauth_access_token_spec.rb'
|
||||
- 'ee/spec/models/upload_spec.rb'
|
||||
- 'ee/spec/models/user_preference_spec.rb'
|
||||
- 'ee/spec/models/user_spec.rb'
|
||||
- 'ee/spec/models/visible_approvable_spec.rb'
|
||||
- 'ee/spec/models/vulnerabilities/feedback_spec.rb'
|
||||
- 'ee/spec/models/vulnerabilities/issue_link_spec.rb'
|
||||
- 'ee/spec/presenters/audit_event_presenter_spec.rb'
|
||||
- 'ee/spec/presenters/epic_presenter_spec.rb'
|
||||
- 'ee/spec/requests/api/boards_spec.rb'
|
||||
- 'ee/spec/requests/api/epic_issues_spec.rb'
|
||||
- 'ee/spec/requests/api/epic_links_spec.rb'
|
||||
- 'ee/spec/requests/api/epics_spec.rb'
|
||||
- 'ee/spec/requests/api/geo_nodes_spec.rb'
|
||||
- 'ee/spec/requests/api/geo_spec.rb'
|
||||
- 'ee/spec/requests/api/graphql/group/epics_spec.rb'
|
||||
- 'ee/spec/requests/api/graphql/mutations/epic_tree/reorder_spec.rb'
|
||||
- 'ee/spec/requests/api/groups_spec.rb'
|
||||
- 'ee/spec/requests/api/issues_spec.rb'
|
||||
- 'ee/spec/requests/api/ldap_group_links_spec.rb'
|
||||
- 'ee/spec/requests/api/merge_request_approval_rules_spec.rb'
|
||||
- 'ee/spec/requests/api/merge_request_approvals_spec.rb'
|
||||
- 'ee/spec/requests/api/merge_requests_spec.rb'
|
||||
- 'ee/spec/requests/api/project_approvals_spec.rb'
|
||||
- 'ee/spec/requests/api/projects_spec.rb'
|
||||
- 'ee/spec/requests/api/protected_branches_spec.rb'
|
||||
- 'ee/spec/requests/api/scim_spec.rb'
|
||||
- 'ee/spec/requests/api/todos_spec.rb'
|
||||
- 'ee/spec/requests/lfs_http_spec.rb'
|
||||
- 'ee/spec/services/approval_rules/finalize_service_spec.rb'
|
||||
- 'ee/spec/services/approval_rules/update_service_spec.rb'
|
||||
- 'ee/spec/services/ee/boards/issues/create_service_spec.rb'
|
||||
- 'ee/spec/services/ee/boards/issues/list_service_spec.rb'
|
||||
- 'ee/spec/services/ee/boards/lists/list_service_spec.rb'
|
||||
- 'ee/spec/services/ee/issuable/clone/attributes_rewriter_spec.rb'
|
||||
- 'ee/spec/services/ee/issuable/common_system_notes_service_spec.rb'
|
||||
- 'ee/spec/services/ee/issues/update_service_spec.rb'
|
||||
- 'ee/spec/services/ee/merge_requests/refresh_service_spec.rb'
|
||||
- 'ee/spec/services/ee/merge_requests/update_service_spec.rb'
|
||||
- 'ee/spec/services/ee/notes/quick_actions_service_spec.rb'
|
||||
- 'ee/spec/services/ee/notification_service_spec.rb'
|
||||
- 'ee/spec/services/epic_links/create_service_spec.rb'
|
||||
- 'ee/spec/services/epics/close_service_spec.rb'
|
||||
- 'ee/spec/services/epics/issue_promote_service_spec.rb'
|
||||
- 'ee/spec/services/epics/reopen_service_spec.rb'
|
||||
- 'ee/spec/services/epics/tree_reorder_service_spec.rb'
|
||||
- 'ee/spec/services/epics/update_dates_service_spec.rb'
|
||||
- 'ee/spec/services/epics/update_service_spec.rb'
|
||||
- 'ee/spec/services/geo/blob_verification_secondary_service_spec.rb'
|
||||
- 'ee/spec/services/geo/files_expire_service_spec.rb'
|
||||
- 'ee/spec/services/geo/metrics_update_service_spec.rb'
|
||||
- 'ee/spec/services/geo/registry_consistency_service_spec.rb'
|
||||
- 'ee/spec/services/geo/repository_verification_secondary_service_spec.rb'
|
||||
- 'ee/spec/services/groups/autocomplete_service_spec.rb'
|
||||
- 'ee/spec/services/ldap_group_reset_service_spec.rb'
|
||||
- 'ee/spec/services/lfs/unlock_file_service_spec.rb'
|
||||
- 'ee/spec/services/merge_trains/refresh_merge_request_service_spec.rb'
|
||||
- 'ee/spec/services/quick_actions/interpret_service_spec.rb'
|
||||
- 'ee/spec/services/slash_commands/global_slack_handler_spec.rb'
|
||||
- 'ee/spec/services/start_pull_mirroring_service_spec.rb'
|
||||
- 'ee/spec/services/status_page/trigger_publish_service_spec.rb'
|
||||
- 'ee/spec/services/todo_service_spec.rb'
|
||||
- 'ee/spec/services/update_build_minutes_service_spec.rb'
|
||||
- 'ee/spec/services/vulnerability_feedback/create_service_spec.rb'
|
||||
- 'ee/spec/support/protected_tags/access_control_shared_examples.rb'
|
||||
- 'ee/spec/support/shared_examples/features/protected_branches_access_control_shared_examples.rb'
|
||||
- 'ee/spec/support/shared_examples/finders/geo/framework_registry_finder_shared_examples.rb'
|
||||
- 'ee/spec/support/shared_examples/graphql/geo/geo_registries_resolver_shared_examples.rb'
|
||||
- 'ee/spec/support/shared_examples/lib/analytics/common_merge_request_metrics_refresh_shared_examples.rb'
|
||||
- 'ee/spec/support/shared_examples/policies/protected_environments_shared_examples.rb'
|
||||
- 'ee/spec/workers/adjourned_project_deletion_worker_spec.rb'
|
||||
- 'ee/spec/workers/clear_shared_runners_minutes_worker_spec.rb'
|
||||
- 'ee/spec/workers/create_github_webhook_worker_spec.rb'
|
||||
- 'ee/spec/workers/elastic_namespace_rollout_worker_spec.rb'
|
||||
- 'ee/spec/workers/geo/container_repository_sync_dispatch_worker_spec.rb'
|
||||
- 'ee/spec/workers/geo/file_download_dispatch_worker_spec.rb'
|
||||
- 'ee/spec/workers/geo/prune_event_log_worker_spec.rb'
|
||||
- 'ee/spec/workers/geo/registry_sync_worker_spec.rb'
|
||||
- 'ee/spec/workers/geo/repository_shard_sync_worker_spec.rb'
|
||||
- 'ee/spec/workers/repository_import_worker_spec.rb'
|
||||
- 'ee/spec/workers/update_all_mirrors_worker_spec.rb'
|
||||
- 'qa/qa/specs/features/browser_ui/3_create/repository/push_mirroring_over_http_spec.rb'
|
||||
- 'qa/qa/specs/features/browser_ui/3_create/repository/push_mirroring_lfs_over_http_spec.rb'
|
||||
- 'qa/qa/specs/features/ee/browser_ui/3_create/repository/pull_mirroring_over_http_spec.rb'
|
||||
- 'qa/qa/specs/features/ee/browser_ui/3_create/repository/pull_mirroring_over_ssh_with_key_spec.rb'
|
||||
- 'spec/controllers/abuse_reports_controller_spec.rb'
|
||||
- 'spec/controllers/admin/impersonations_controller_spec.rb'
|
||||
- 'spec/controllers/admin/runners_controller_spec.rb'
|
||||
- 'spec/controllers/admin/services_controller_spec.rb'
|
||||
- 'spec/controllers/boards/issues_controller_spec.rb'
|
||||
- 'spec/controllers/groups/milestones_controller_spec.rb'
|
||||
- 'spec/controllers/groups/runners_controller_spec.rb'
|
||||
- 'spec/controllers/groups/uploads_controller_spec.rb'
|
||||
- 'spec/controllers/groups_controller_spec.rb'
|
||||
- 'spec/controllers/oauth/authorizations_controller_spec.rb'
|
||||
- 'spec/controllers/omniauth_callbacks_controller_spec.rb'
|
||||
- 'spec/controllers/profiles/emails_controller_spec.rb'
|
||||
- 'spec/controllers/profiles/notifications_controller_spec.rb'
|
||||
- 'spec/controllers/projects/artifacts_controller_spec.rb'
|
||||
- 'spec/controllers/projects/cycle_analytics/events_controller_spec.rb'
|
||||
- 'spec/controllers/projects/cycle_analytics_controller_spec.rb'
|
||||
- 'spec/controllers/projects/discussions_controller_spec.rb'
|
||||
- 'spec/controllers/projects/forks_controller_spec.rb'
|
||||
- 'spec/controllers/projects/group_links_controller_spec.rb'
|
||||
- 'spec/controllers/projects/imports_controller_spec.rb'
|
||||
- 'spec/controllers/projects/issues_controller_spec.rb'
|
||||
- 'spec/controllers/projects/labels_controller_spec.rb'
|
||||
- 'spec/controllers/projects/milestones_controller_spec.rb'
|
||||
- 'spec/controllers/projects/notes_controller_spec.rb'
|
||||
- 'spec/controllers/projects/pipelines_controller_spec.rb'
|
||||
- 'spec/controllers/projects/releases/evidences_controller_spec.rb'
|
||||
- 'spec/controllers/projects/runners_controller_spec.rb'
|
||||
- 'spec/controllers/projects/starrers_controller_spec.rb'
|
||||
- 'spec/controllers/projects/uploads_controller_spec.rb'
|
||||
- 'spec/controllers/projects_controller_spec.rb'
|
||||
- 'spec/controllers/sent_notifications_controller_spec.rb'
|
||||
- 'spec/controllers/sessions_controller_spec.rb'
|
||||
- 'spec/controllers/users_controller_spec.rb'
|
||||
- 'spec/factories_spec.rb'
|
||||
- 'spec/features/admin/admin_appearance_spec.rb'
|
||||
- 'spec/features/admin/admin_labels_spec.rb'
|
||||
- 'spec/features/admin/admin_mode/login_spec.rb'
|
||||
- 'spec/features/admin/admin_runners_spec.rb'
|
||||
- 'spec/features/admin/admin_sees_project_statistics_spec.rb'
|
||||
- 'spec/features/admin/admin_sees_projects_statistics_spec.rb'
|
||||
- 'spec/features/admin/admin_users_impersonation_tokens_spec.rb'
|
||||
- 'spec/features/admin/admin_users_spec.rb'
|
||||
- 'spec/features/boards/sidebar_spec.rb'
|
||||
- 'spec/features/calendar_spec.rb'
|
||||
- 'spec/features/commits_spec.rb'
|
||||
- 'spec/features/dashboard/datetime_on_tooltips_spec.rb'
|
||||
- 'spec/features/dashboard/issuables_counter_spec.rb'
|
||||
- 'spec/features/dashboard/project_member_activity_index_spec.rb'
|
||||
- 'spec/features/dashboard/projects_spec.rb'
|
||||
- 'spec/features/error_tracking/user_sees_error_index_spec.rb'
|
||||
- 'spec/features/groups/members/request_access_spec.rb'
|
||||
- 'spec/features/issuables/close_reopen_report_toggle_spec.rb'
|
||||
- 'spec/features/issues/bulk_assignment_labels_spec.rb'
|
||||
- 'spec/features/issues/gfm_autocomplete_spec.rb'
|
||||
- 'spec/features/issues/issue_sidebar_spec.rb'
|
||||
- 'spec/features/issues/note_polling_spec.rb'
|
||||
- 'spec/features/issues/user_creates_branch_and_merge_request_spec.rb'
|
||||
- 'spec/features/issues/user_creates_confidential_merge_request_spec.rb'
|
||||
- 'spec/features/issues/user_edits_issue_spec.rb'
|
||||
- 'spec/features/issues/user_filters_issues_spec.rb'
|
||||
- 'spec/features/issues/user_sees_live_update_spec.rb'
|
||||
- 'spec/features/issues/user_sorts_issues_spec.rb'
|
||||
- 'spec/features/profiles/emails_spec.rb'
|
||||
- 'spec/features/profiles/password_spec.rb'
|
||||
- 'spec/features/profiles/personal_access_tokens_spec.rb'
|
||||
- 'spec/features/projects/features_visibility_spec.rb'
|
||||
- 'spec/features/projects/fork_spec.rb'
|
||||
- 'spec/features/projects/jobs/permissions_spec.rb'
|
||||
- 'spec/features/projects/jobs_spec.rb'
|
||||
- 'spec/features/projects/members/user_requests_access_spec.rb'
|
||||
- 'spec/features/projects/pages_lets_encrypt_spec.rb'
|
||||
- 'spec/features/projects/pages_spec.rb'
|
||||
- 'spec/features/projects/pipelines/pipeline_spec.rb'
|
||||
- 'spec/features/projects/pipelines/pipelines_spec.rb'
|
||||
- 'spec/features/projects/remote_mirror_spec.rb'
|
||||
- 'spec/features/projects/services/user_activates_slack_notifications_spec.rb'
|
||||
- 'spec/features/projects/settings/access_tokens_spec.rb'
|
||||
- 'spec/features/projects/show/user_sees_deletion_failure_message_spec.rb'
|
||||
- 'spec/features/projects/user_sees_sidebar_spec.rb'
|
||||
- 'spec/features/projects/wiki/user_updates_wiki_page_spec.rb'
|
||||
- 'spec/features/projects/wiki/user_views_wiki_page_spec.rb'
|
||||
- 'spec/features/projects/wiki/users_views_asciidoc_page_with_includes_spec.rb'
|
||||
- 'spec/features/runners_spec.rb'
|
||||
- 'spec/features/security/project/internal_access_spec.rb'
|
||||
- 'spec/features/security/project/private_access_spec.rb'
|
||||
- 'spec/features/security/project/public_access_spec.rb'
|
||||
- 'spec/features/users/login_spec.rb'
|
||||
- 'spec/features/users/show_spec.rb'
|
||||
- 'spec/frontend/fixtures/issues.rb'
|
||||
- 'spec/frontend/fixtures/merge_requests.rb'
|
||||
- 'spec/graphql/mutations/merge_requests/set_locked_spec.rb'
|
||||
- 'spec/graphql/mutations/merge_requests/set_wip_spec.rb'
|
||||
- 'spec/graphql/resolvers/boards_resolver_spec.rb'
|
||||
- 'spec/initializers/active_record_locking_spec.rb'
|
||||
- 'spec/initializers/fog_google_https_private_urls_spec.rb'
|
||||
- 'spec/lib/after_commit_queue_spec.rb'
|
||||
- 'spec/lib/backup/manager_spec.rb'
|
||||
- 'spec/lib/banzai/reference_parser/external_issue_parser_spec.rb'
|
||||
- 'spec/lib/banzai/reference_redactor_spec.rb'
|
||||
- 'spec/lib/gitlab/alerting/alert_spec.rb'
|
||||
- 'spec/lib/gitlab/analytics/cycle_analytics/records_fetcher_spec.rb'
|
||||
- 'spec/lib/gitlab/auth/ldap/user_spec.rb'
|
||||
- 'spec/lib/gitlab/auth/o_auth/user_spec.rb'
|
||||
- 'spec/lib/gitlab/auth/saml/user_spec.rb'
|
||||
- 'spec/lib/gitlab/auth_spec.rb'
|
||||
- 'spec/lib/gitlab/authorized_keys_spec.rb'
|
||||
- 'spec/lib/gitlab/background_migration/backfill_deployment_clusters_from_deployments_spec.rb'
|
||||
- 'spec/lib/gitlab/background_migration/backfill_project_repositories_spec.rb'
|
||||
- 'spec/lib/gitlab/background_migration/backfill_project_settings_spec.rb'
|
||||
- 'spec/lib/gitlab/background_migration/backfill_push_rules_id_in_projects_spec.rb'
|
||||
- 'spec/lib/gitlab/background_migration/backfill_snippet_repositories_spec.rb'
|
||||
- 'spec/lib/gitlab/background_migration/digest_column_spec.rb'
|
||||
- 'spec/lib/gitlab/background_migration/encrypt_columns_spec.rb'
|
||||
- 'spec/lib/gitlab/background_migration/fix_cross_project_label_links_spec.rb'
|
||||
- 'spec/lib/gitlab/background_migration/fix_projects_without_project_feature_spec.rb'
|
||||
- 'spec/lib/gitlab/background_migration/fix_projects_without_prometheus_service_spec.rb'
|
||||
- 'spec/lib/gitlab/background_migration/fix_user_namespace_names_spec.rb'
|
||||
- 'spec/lib/gitlab/background_migration/fix_user_project_route_names_spec.rb'
|
||||
- 'spec/lib/gitlab/background_migration/legacy_upload_mover_spec.rb'
|
||||
- 'spec/lib/gitlab/background_migration/legacy_uploads_migrator_spec.rb'
|
||||
- 'spec/lib/gitlab/background_migration/link_lfs_objects_projects_spec.rb'
|
||||
- 'spec/lib/gitlab/background_migration/migrate_issue_trackers_sensitive_data_spec.rb'
|
||||
- 'spec/lib/gitlab/background_migration/migrate_stage_index_spec.rb'
|
||||
- 'spec/lib/gitlab/background_migration/migrate_users_bio_to_user_details_spec.rb'
|
||||
- 'spec/lib/gitlab/background_migration/populate_canonical_emails_spec.rb'
|
||||
- 'spec/lib/gitlab/background_migration/populate_merge_request_assignees_table_spec.rb'
|
||||
- 'spec/lib/gitlab/background_migration/populate_user_highest_roles_table_spec.rb'
|
||||
- 'spec/lib/gitlab/background_migration/recalculate_project_authorizations_spec.rb'
|
||||
- 'spec/lib/gitlab/background_migration/remove_restricted_todos_spec.rb'
|
||||
- 'spec/lib/gitlab/background_migration/reset_merge_status_spec.rb'
|
||||
- 'spec/lib/gitlab/background_migration/set_confidential_note_events_on_services_spec.rb'
|
||||
- 'spec/lib/gitlab/background_migration/set_confidential_note_events_on_webhooks_spec.rb'
|
||||
- 'spec/lib/gitlab/bitbucket_server_import/importer_spec.rb'
|
||||
- 'spec/lib/gitlab/ci/ansi2json/style_spec.rb'
|
||||
- 'spec/lib/gitlab/ci/status/build/common_spec.rb'
|
||||
- 'spec/lib/gitlab/cycle_analytics/base_event_fetcher_spec.rb'
|
||||
- 'spec/lib/gitlab/database/custom_structure_spec.rb'
|
||||
- 'spec/lib/gitlab/database/partitioning_migration_helpers/table_management_helpers_spec.rb'
|
||||
- 'spec/lib/gitlab/database_importers/self_monitoring/project/create_service_spec.rb'
|
||||
- 'spec/lib/gitlab/email/handler/create_note_handler_spec.rb'
|
||||
- 'spec/lib/gitlab/email/handler/unsubscribe_handler_spec.rb'
|
||||
- 'spec/lib/gitlab/gfm/reference_rewriter_spec.rb'
|
||||
- 'spec/lib/gitlab/git_access_spec.rb'
|
||||
- 'spec/lib/gitlab/gitaly_client/object_pool_service_spec.rb'
|
||||
- 'spec/lib/gitlab/gitaly_client/repository_service_spec.rb'
|
||||
- 'spec/lib/gitlab/import_export/avatar_saver_spec.rb'
|
||||
- 'spec/lib/gitlab/import_export/base/relation_factory_spec.rb'
|
||||
- 'spec/lib/gitlab/import_export/design_repo_restorer_spec.rb'
|
||||
- 'spec/lib/gitlab/import_export/fast_hash_serializer_spec.rb'
|
||||
- 'spec/lib/gitlab/import_export/fork_spec.rb'
|
||||
- 'spec/lib/gitlab/import_export/group/legacy_tree_saver_spec.rb'
|
||||
- 'spec/lib/gitlab/import_export/group/relation_factory_spec.rb'
|
||||
- 'spec/lib/gitlab/import_export/group/tree_saver_spec.rb'
|
||||
- 'spec/lib/gitlab/import_export/importer_spec.rb'
|
||||
- 'spec/lib/gitlab/import_export/lfs_restorer_spec.rb'
|
||||
- 'spec/lib/gitlab/import_export/lfs_saver_spec.rb'
|
||||
- 'spec/lib/gitlab/import_export/members_mapper_spec.rb'
|
||||
- 'spec/lib/gitlab/import_export/project/relation_factory_spec.rb'
|
||||
- 'spec/lib/gitlab/import_export/project/tree_restorer_spec.rb'
|
||||
- 'spec/lib/gitlab/import_export/project/tree_saver_spec.rb'
|
||||
- 'spec/lib/gitlab/import_export/repo_restorer_spec.rb'
|
||||
- 'spec/lib/gitlab/import_export/saver_spec.rb'
|
||||
- 'spec/lib/gitlab/import_export/snippet_repo_restorer_spec.rb'
|
||||
- 'spec/lib/gitlab/import_export/snippet_repo_saver_spec.rb'
|
||||
- 'spec/lib/gitlab/import_export/snippets_repo_restorer_spec.rb'
|
||||
- 'spec/lib/gitlab/import_export/snippets_repo_saver_spec.rb'
|
||||
- 'spec/lib/gitlab/import_export/uploads_manager_spec.rb'
|
||||
- 'spec/lib/gitlab/import_export/uploads_saver_spec.rb'
|
||||
- 'spec/lib/gitlab/import_export/wiki_restorer_spec.rb'
|
||||
- 'spec/lib/gitlab/legacy_github_import/importer_spec.rb'
|
||||
- 'spec/lib/gitlab/legacy_github_import/issue_formatter_spec.rb'
|
||||
- 'spec/lib/gitlab/legacy_github_import/milestone_formatter_spec.rb'
|
||||
- 'spec/lib/gitlab/legacy_github_import/pull_request_formatter_spec.rb'
|
||||
- 'spec/lib/gitlab/lets_encrypt/client_spec.rb'
|
||||
- 'spec/lib/gitlab/markdown_cache/active_record/extension_spec.rb'
|
||||
- 'spec/lib/gitlab/markdown_cache/redis/store_spec.rb'
|
||||
- 'spec/lib/gitlab/middleware/go_spec.rb'
|
||||
- 'spec/lib/gitlab/shard_health_cache_spec.rb'
|
||||
- 'spec/lib/mattermost/command_spec.rb'
|
||||
- 'spec/lib/mattermost/session_spec.rb'
|
||||
- 'spec/lib/mattermost/team_spec.rb'
|
||||
- 'spec/mailers/notify_spec.rb'
|
||||
- 'spec/migrations/20190924152703_migrate_issue_trackers_data_spec.rb'
|
||||
- 'spec/migrations/20200122123016_backfill_project_settings_spec.rb'
|
||||
- 'spec/migrations/20200123155929_remove_invalid_jira_data_spec.rb'
|
||||
- 'spec/migrations/20200127090233_remove_invalid_issue_tracker_data_spec.rb'
|
||||
- 'spec/migrations/20200130145430_reschedule_migrate_issue_trackers_data_spec.rb'
|
||||
- 'spec/migrations/20200313203550_remove_orphaned_chat_names_spec.rb'
|
||||
- 'spec/migrations/20200406102120_backfill_deployment_clusters_from_deployments_spec.rb'
|
||||
- 'spec/migrations/20200526115436_dedup_mr_metrics_spec.rb'
|
||||
- 'spec/migrations/add_deploy_token_type_to_deploy_tokens_spec.rb'
|
||||
- 'spec/migrations/add_incident_settings_to_all_existing_projects_spec.rb'
|
||||
- 'spec/migrations/add_unique_constraint_to_approvals_user_id_and_merge_request_id_spec.rb'
|
||||
- 'spec/migrations/backfill_and_add_not_null_constraint_to_released_at_column_on_releases_table_spec.rb'
|
||||
- 'spec/migrations/backfill_imported_snippet_repositories_spec.rb'
|
||||
- 'spec/migrations/backfill_releases_table_updated_at_and_add_not_null_constraints_to_timestamps_spec.rb'
|
||||
- 'spec/migrations/backfill_snippet_repositories_spec.rb'
|
||||
- 'spec/migrations/encrypt_plaintext_attributes_on_application_settings_spec.rb'
|
||||
- 'spec/migrations/enqueue_reset_merge_status_second_run_spec.rb'
|
||||
- 'spec/migrations/enqueue_reset_merge_status_spec.rb'
|
||||
- 'spec/migrations/fill_file_store_lfs_objects_spec.rb'
|
||||
- 'spec/migrations/fill_store_uploads_spec.rb'
|
||||
- 'spec/migrations/fix_null_type_labels_spec.rb'
|
||||
- 'spec/migrations/fix_pool_repository_source_project_id_spec.rb'
|
||||
- 'spec/migrations/fix_projects_without_project_feature_spec.rb'
|
||||
- 'spec/migrations/fix_projects_without_prometheus_services_spec.rb'
|
||||
- 'spec/migrations/fix_wrong_pages_access_level_spec.rb'
|
||||
- 'spec/migrations/insert_project_hooks_plan_limits_spec.rb'
|
||||
- 'spec/migrations/migrate_auto_dev_ops_domain_to_cluster_domain_spec.rb'
|
||||
- 'spec/migrations/move_limits_from_plans_spec.rb'
|
||||
- 'spec/migrations/populate_project_statistics_packages_size_spec.rb'
|
||||
- 'spec/migrations/schedule_link_lfs_objects_projects_spec.rb'
|
||||
- 'spec/migrations/schedule_populate_merge_request_assignees_table_spec.rb'
|
||||
- 'spec/migrations/seed_repository_storages_weighted_spec.rb'
|
||||
- 'spec/models/appearance_spec.rb'
|
||||
- 'spec/models/application_record_spec.rb'
|
||||
- 'spec/models/application_setting_spec.rb'
|
||||
- 'spec/models/clusters/applications/helm_spec.rb'
|
||||
- 'spec/models/commit_spec.rb'
|
||||
- 'spec/models/commit_status_spec.rb'
|
||||
- 'spec/models/container_repository_spec.rb'
|
||||
- 'spec/models/deploy_keys_project_spec.rb'
|
||||
- 'spec/models/deploy_token_spec.rb'
|
||||
- 'spec/models/deployment_spec.rb'
|
||||
- 'spec/models/design_management/version_spec.rb'
|
||||
- 'spec/models/diff_discussion_spec.rb'
|
||||
- 'spec/models/diff_note_spec.rb'
|
||||
- 'spec/models/email_spec.rb'
|
||||
- 'spec/models/environment_spec.rb'
|
||||
- 'spec/models/event_spec.rb'
|
||||
- 'spec/models/fork_network_spec.rb'
|
||||
- 'spec/models/generic_commit_status_spec.rb'
|
||||
- 'spec/models/grafana_integration_spec.rb'
|
||||
- 'spec/models/group_spec.rb'
|
||||
- 'spec/models/hooks/system_hook_spec.rb'
|
||||
- 'spec/models/hooks/web_hook_spec.rb'
|
||||
- 'spec/models/identity_spec.rb'
|
||||
- 'spec/models/issue/metrics_spec.rb'
|
||||
- 'spec/models/issue_spec.rb'
|
||||
- 'spec/models/jira_import_state_spec.rb'
|
||||
- 'spec/models/key_spec.rb'
|
||||
- 'spec/models/lfs_objects_project_spec.rb'
|
||||
- 'spec/models/member_spec.rb'
|
||||
- 'spec/models/members/group_member_spec.rb'
|
||||
- 'spec/models/members/project_member_spec.rb'
|
||||
- 'spec/models/merge_request_spec.rb'
|
||||
- 'spec/models/milestone_spec.rb'
|
||||
- 'spec/models/namespace_spec.rb'
|
||||
- 'spec/models/note_spec.rb'
|
||||
- 'spec/models/notification_setting_spec.rb'
|
||||
- 'spec/models/operations/feature_flag_scope_spec.rb'
|
||||
- 'spec/models/operations/feature_flags/strategy_spec.rb'
|
||||
- 'spec/models/operations/feature_flags/user_list_spec.rb'
|
||||
- 'spec/models/pages_domain_spec.rb'
|
||||
- 'spec/models/project_auto_devops_spec.rb'
|
||||
- 'spec/models/project_feature_spec.rb'
|
||||
- 'spec/models/project_spec.rb'
|
||||
- 'spec/models/project_team_spec.rb'
|
||||
- 'spec/models/protectable_dropdown_spec.rb'
|
||||
- 'spec/models/redirect_route_spec.rb'
|
||||
- 'spec/models/release_spec.rb'
|
||||
- 'spec/models/remote_mirror_spec.rb'
|
||||
- 'spec/models/resource_milestone_event_spec.rb'
|
||||
- 'spec/models/route_spec.rb'
|
||||
- 'spec/models/sentry_issue_spec.rb'
|
||||
- 'spec/models/service_spec.rb'
|
||||
- 'spec/models/snippet_spec.rb'
|
||||
- 'spec/models/upload_spec.rb'
|
||||
- 'spec/models/user_preference_spec.rb'
|
||||
- 'spec/models/user_spec.rb'
|
||||
- 'spec/models/user_status_spec.rb'
|
||||
- 'spec/models/wiki_page/meta_spec.rb'
|
||||
- 'spec/models/wiki_page_spec.rb'
|
||||
- 'spec/presenters/ci/build_runner_presenter_spec.rb'
|
||||
- 'spec/presenters/ci/trigger_presenter_spec.rb'
|
||||
- 'spec/presenters/packages/conan/package_presenter_spec.rb'
|
||||
- 'spec/requests/api/ci/runner_spec.rb'
|
||||
- 'spec/requests/api/commit_statuses_spec.rb'
|
||||
- 'spec/requests/api/conan_packages_spec.rb'
|
||||
- 'spec/requests/api/deployments_spec.rb'
|
||||
- 'spec/requests/api/environments_spec.rb'
|
||||
- 'spec/requests/api/go_proxy_spec.rb'
|
||||
- 'spec/requests/api/graphql/mutations/merge_requests/set_labels_spec.rb'
|
||||
- 'spec/requests/api/graphql/user_query_spec.rb'
|
||||
- 'spec/requests/api/graphql_spec.rb'
|
||||
- 'spec/requests/api/group_import_spec.rb'
|
||||
- 'spec/requests/api/group_milestones_spec.rb'
|
||||
- 'spec/requests/api/internal/base_spec.rb'
|
||||
- 'spec/requests/api/issues/get_group_issues_spec.rb'
|
||||
- 'spec/requests/api/issues/post_projects_issues_spec.rb'
|
||||
- 'spec/requests/api/jobs_spec.rb'
|
||||
- 'spec/requests/api/labels_spec.rb'
|
||||
- 'spec/requests/api/project_import_spec.rb'
|
||||
- 'spec/requests/projects/cycle_analytics_events_spec.rb'
|
||||
|
||||
Rails/TimeZone:
|
||||
Enabled: true
|
||||
Exclude:
|
||||
- 'lib/gitlab/popen.rb'
|
||||
- 'ee/lib/delay.rb'
|
||||
- 'ee/lib/gitlab/elastic/helper.rb'
|
||||
- 'ee/lib/gitlab/elastic/indexer.rb'
|
||||
- 'ee/lib/gitlab/geo/base_request.rb'
|
||||
- 'ee/lib/gitlab/geo/event_gap_tracking.rb'
|
||||
- 'ee/lib/gitlab/geo/log_cursor/events/design_repository_updated_event.rb'
|
||||
- 'ee/lib/gitlab/geo/log_cursor/events/repository_updated_event.rb'
|
||||
- 'ee/lib/gitlab/geo/log_cursor/logger.rb'
|
||||
- 'ee/lib/gitlab/geo/oauth/login_state.rb'
|
||||
- 'ee/lib/gitlab/prometheus/queries/cluster_query.rb'
|
||||
- 'ee/lib/gitlab/prometheus/queries/packet_flow_query.rb'
|
||||
- 'ee/spec/lib/ee/gitlab/checks/push_rules/commit_check_spec.rb'
|
||||
- 'ee/spec/lib/ee/gitlab/ci/pipeline/quota/job_activity_spec.rb'
|
||||
- 'ee/spec/lib/gitlab/analytics/cycle_analytics/data_collector_spec.rb'
|
||||
- 'ee/spec/lib/gitlab/analytics/cycle_analytics/summary/group/stage_summary_spec.rb'
|
||||
- 'ee/spec/lib/gitlab/analytics/cycle_analytics/summary/group/stage_time_summary_spec.rb'
|
||||
- 'ee/spec/lib/gitlab/auth/ldap/access_spec.rb'
|
||||
- 'ee/spec/lib/gitlab/auth/smartcard/san_extension_spec.rb'
|
||||
- 'ee/spec/lib/gitlab/auth/smartcard/session_spec.rb'
|
||||
- 'ee/spec/lib/gitlab/background_migration/fix_orphan_promoted_issues_spec.rb'
|
||||
- 'ee/spec/lib/gitlab/ci/pipeline/chain/limit/job_activity_spec.rb'
|
||||
- 'ee/spec/lib/gitlab/elastic/client_spec.rb'
|
||||
- 'ee/spec/lib/gitlab/geo/base_request_spec.rb'
|
||||
- 'ee/spec/lib/gitlab/geo/log_cursor/events/cache_invalidation_event_spec.rb'
|
||||
- 'ee/spec/lib/gitlab/geo/log_cursor/events/container_repository_updated_event_spec.rb'
|
||||
- 'ee/spec/lib/gitlab/geo/log_cursor/events/design_repository_updated_event_spec.rb'
|
||||
- 'ee/spec/lib/gitlab/geo/log_cursor/events/event_spec.rb'
|
||||
- 'ee/spec/lib/gitlab/geo/log_cursor/events/hashed_storage_attachments_event_spec.rb'
|
||||
- 'ee/spec/lib/gitlab/geo/log_cursor/events/hashed_storage_migrated_event_spec.rb'
|
||||
- 'ee/spec/lib/gitlab/geo/log_cursor/events/job_artifact_deleted_event_spec.rb'
|
||||
- 'ee/spec/lib/gitlab/geo/log_cursor/events/lfs_object_deleted_event_spec.rb'
|
||||
- 'ee/spec/lib/gitlab/geo/log_cursor/events/repositories_changed_event_spec.rb'
|
||||
- 'ee/spec/lib/gitlab/geo/log_cursor/events/repository_created_event_spec.rb'
|
||||
- 'ee/spec/lib/gitlab/geo/log_cursor/events/repository_deleted_event_spec.rb'
|
||||
- 'ee/spec/lib/gitlab/geo/log_cursor/events/repository_renamed_event_spec.rb'
|
||||
- 'ee/spec/lib/gitlab/geo/log_cursor/events/repository_updated_event_spec.rb'
|
||||
- 'ee/spec/lib/gitlab/geo/log_cursor/events/reset_checksum_event_spec.rb'
|
||||
- 'ee/spec/lib/gitlab/geo/log_cursor/events/upload_deleted_event_spec.rb'
|
||||
- 'ee/spec/lib/gitlab/geo/log_cursor/logger_spec.rb'
|
||||
- 'ee/spec/lib/gitlab/git_access_spec.rb'
|
||||
- 'ee/spec/lib/gitlab/prometheus/queries/additional_metrics_deployment_query_spec.rb'
|
||||
- 'ee/spec/lib/gitlab/prometheus/queries/cluster_query_spec.rb'
|
||||
- 'ee/spec/lib/gitlab/prometheus/queries/packet_flow_query_spec.rb'
|
||||
- 'lib/api/helpers.rb'
|
||||
- 'lib/api/sidekiq_metrics.rb'
|
||||
- 'lib/backup/manager.rb'
|
||||
- 'lib/bitbucket_server/representation/base.rb'
|
||||
- 'lib/gitlab/auth/current_user_mode.rb'
|
||||
- 'lib/gitlab/auth/ldap/access.rb'
|
||||
- 'lib/gitlab/chaos.rb'
|
||||
- 'lib/gitlab/checks/timed_logger.rb'
|
||||
- 'lib/gitlab/ci/ansi2json/line.rb'
|
||||
- 'lib/gitlab/ci/pipeline/chain/sequence.rb'
|
||||
- 'lib/gitlab/ci/pipeline/duration.rb'
|
||||
- 'lib/gitlab/cycle_analytics/summary/deployment_frequency.rb'
|
||||
- 'lib/gitlab/database.rb'
|
||||
- 'lib/gitlab/external_authorization/access.rb'
|
||||
- 'lib/gitlab/external_authorization/cache.rb'
|
||||
- 'lib/gitlab/gitaly_client.rb'
|
||||
- 'lib/gitlab/gitaly_client/ref_service.rb'
|
||||
- 'lib/gitlab/github_import/representation.rb'
|
||||
- 'lib/gitlab/grape_logging/loggers/queue_duration_logger.rb'
|
||||
- 'lib/gitlab/health_checks/base_abstract_check.rb'
|
||||
- 'lib/gitlab/import_export.rb'
|
||||
- 'lib/gitlab/instrumentation/elasticsearch_transport.rb'
|
||||
- 'lib/gitlab/instrumentation/redis_interceptor.rb'
|
||||
- 'lib/gitlab/instrumentation_helper.rb'
|
||||
- 'lib/gitlab/kubernetes/helm/certificate.rb'
|
||||
- 'lib/gitlab/lfs_token.rb'
|
||||
- 'lib/gitlab/loop_helpers.rb'
|
||||
- 'lib/gitlab/phabricator_import/representation/task.rb'
|
||||
- 'lib/gitlab/prometheus/queries/additional_metrics_environment_query.rb'
|
||||
- 'lib/gitlab/prometheus/queries/matched_metric_query.rb'
|
||||
- 'lib/gitlab/prometheus_client.rb'
|
||||
- 'lib/gitlab/sherlock/transaction.rb'
|
||||
- 'lib/gitlab/task_helpers.rb'
|
||||
- 'lib/gitlab/x509/tag.rb'
|
||||
- 'lib/grafana/time_window.rb'
|
||||
- 'lib/json_web_token/token.rb'
|
||||
- 'lib/object_storage/direct_upload.rb'
|
||||
- 'lib/quality/seeders/issues.rb'
|
||||
- 'lib/rspec_flaky/flaky_example.rb'
|
||||
- 'lib/rspec_flaky/report.rb'
|
||||
- 'lib/tasks/gitlab/assets.rake'
|
||||
- 'lib/tasks/gitlab/backup.rake'
|
||||
- 'lib/tasks/gitlab/cleanup.rake'
|
||||
- 'lib/tasks/gitlab/list_repos.rake'
|
||||
- 'spec/lib/api/helpers_spec.rb'
|
||||
- 'spec/lib/gitlab/analytics/cycle_analytics/base_query_builder_spec.rb'
|
||||
- 'spec/lib/gitlab/app_json_logger_spec.rb'
|
||||
- 'spec/lib/gitlab/app_text_logger_spec.rb'
|
||||
- 'spec/lib/gitlab/auth/current_user_mode_spec.rb'
|
||||
- 'spec/lib/gitlab/background_migration/recalculate_project_authorizations_spec.rb'
|
||||
- 'spec/lib/gitlab/background_migration/wrongfully_confirmed_email_unconfirmer_spec.rb'
|
||||
- 'spec/lib/gitlab/bitbucket_import/importer_spec.rb'
|
||||
- 'spec/lib/gitlab/bitbucket_server_import/importer_spec.rb'
|
||||
- 'spec/lib/gitlab/checks/timed_logger_spec.rb'
|
||||
- 'spec/lib/gitlab/ci/cron_parser_spec.rb'
|
||||
- 'spec/lib/gitlab/cycle_analytics/stage_summary_spec.rb'
|
||||
- 'spec/lib/gitlab/cycle_analytics/usage_data_spec.rb'
|
||||
- 'spec/lib/gitlab/data_builder/note_spec.rb'
|
||||
- 'spec/lib/gitlab/database/background_migration_job_spec.rb'
|
||||
- 'spec/lib/gitlab/database_spec.rb'
|
||||
- 'spec/lib/gitlab/discussions_diff/file_collection_spec.rb'
|
||||
- 'spec/lib/gitlab/external_authorization/access_spec.rb'
|
||||
- 'spec/lib/gitlab/external_authorization/cache_spec.rb'
|
||||
- 'spec/lib/gitlab/external_authorization/logger_spec.rb'
|
||||
- 'spec/lib/gitlab/fogbugz_import/importer_spec.rb'
|
||||
- 'spec/lib/gitlab/git/branch_spec.rb'
|
||||
- 'spec/lib/gitlab/git/commit_spec.rb'
|
||||
- 'spec/lib/gitlab/git/repository_spec.rb'
|
||||
- 'spec/lib/gitlab/git_access_spec.rb'
|
||||
- 'spec/lib/gitlab/github_import/importer/diff_note_importer_spec.rb'
|
||||
- 'spec/lib/gitlab/github_import/importer/issue_importer_spec.rb'
|
||||
- 'spec/lib/gitlab/github_import/importer/issues_importer_spec.rb'
|
||||
- 'spec/lib/gitlab/github_import/importer/milestones_importer_spec.rb'
|
||||
- 'spec/lib/gitlab/github_import/importer/note_importer_spec.rb'
|
||||
- 'spec/lib/gitlab/github_import/importer/pull_request_importer_spec.rb'
|
||||
- 'spec/lib/gitlab/github_import/importer/releases_importer_spec.rb'
|
||||
- 'spec/lib/gitlab/github_import/representation/diff_note_spec.rb'
|
||||
- 'spec/lib/gitlab/github_import/representation/issue_spec.rb'
|
||||
- 'spec/lib/gitlab/github_import/representation/note_spec.rb'
|
||||
- 'spec/lib/gitlab/github_import/representation/pull_request_spec.rb'
|
||||
- 'spec/lib/gitlab/grape_logging/formatters/lograge_with_timestamp_spec.rb'
|
||||
- 'spec/lib/gitlab/grape_logging/loggers/cloudflare_logger_spec.rb'
|
||||
- 'spec/lib/gitlab/grape_logging/loggers/queue_duration_logger_spec.rb'
|
||||
- 'spec/lib/gitlab/graphql_logger_spec.rb'
|
||||
- 'spec/lib/gitlab/graphs/commits_spec.rb'
|
||||
- 'spec/lib/gitlab/import_export/project/relation_factory_spec.rb'
|
||||
- 'spec/lib/gitlab/instrumentation_helper_spec.rb'
|
||||
- 'spec/lib/gitlab/json_logger_spec.rb'
|
||||
- 'spec/lib/gitlab/lfs_token_spec.rb'
|
||||
- 'spec/lib/gitlab/log_timestamp_formatter_spec.rb'
|
||||
- 'spec/lib/gitlab/middleware/rails_queue_duration_spec.rb'
|
||||
- 'spec/lib/gitlab/omniauth_logging/json_formatter_spec.rb'
|
||||
- 'spec/lib/gitlab/phabricator_import/issues/task_importer_spec.rb'
|
||||
- 'spec/lib/gitlab/phabricator_import/representation/task_spec.rb'
|
||||
- 'spec/lib/gitlab/prometheus/queries/additional_metrics_deployment_query_spec.rb'
|
||||
- 'spec/lib/gitlab/prometheus/queries/deployment_query_spec.rb'
|
||||
- 'spec/lib/gitlab/prometheus/queries/validate_query_spec.rb'
|
||||
- 'spec/lib/gitlab/sherlock/transaction_spec.rb'
|
||||
- 'spec/lib/gitlab/sidekiq_logging/json_formatter_spec.rb'
|
||||
- 'spec/lib/gitlab/sidekiq_middleware/duplicate_jobs/strategies/until_executing_spec.rb'
|
||||
- 'spec/lib/gitlab/updated_notes_paginator_spec.rb'
|
||||
- 'spec/lib/gitlab/utils/json_size_estimator_spec.rb'
|
||||
- 'spec/lib/gitlab/x509/signature_spec.rb'
|
||||
- 'spec/lib/grafana/time_window_spec.rb'
|
||||
- 'spec/lib/json_web_token/hmac_token_spec.rb'
|
||||
- 'spec/lib/rspec_flaky/flaky_example_spec.rb'
|
||||
- 'spec/lib/rspec_flaky/listener_spec.rb'
|
||||
- 'spec/lib/rspec_flaky/report_spec.rb'
|
||||
|
||||
RSpec/TimecopFreeze:
|
||||
Exclude:
|
||||
- 'ee/spec/controllers/admin/application_settings_controller_spec.rb'
|
||||
- 'ee/spec/controllers/projects/security/network_policies_controller_spec.rb'
|
||||
- 'ee/spec/features/admin/admin_reset_pipeline_minutes_spec.rb'
|
||||
- 'ee/spec/features/boards/sidebar_spec.rb'
|
||||
- 'ee/spec/features/groups/analytics/cycle_analytics/filters_and_data_spec.rb'
|
||||
- 'ee/spec/features/groups/iteration_spec.rb'
|
||||
- 'ee/spec/features/projects/mirror_spec.rb'
|
||||
- 'ee/spec/features/projects/services/prometheus_custom_metrics_spec.rb'
|
||||
- 'ee/spec/finders/productivity_analytics_finder_spec.rb'
|
||||
- 'ee/spec/frontend/fixtures/analytics.rb'
|
||||
- 'ee/spec/helpers/vulnerabilities_helper_spec.rb'
|
||||
- 'ee/spec/lib/analytics/merge_request_metrics_refresh_spec.rb'
|
||||
- 'ee/spec/lib/analytics/productivity_analytics_request_params_spec.rb'
|
||||
- 'ee/spec/lib/ee/gitlab/background_migration/populate_vulnerability_historical_statistics_spec.rb'
|
||||
- 'ee/spec/lib/gitlab/analytics/cycle_analytics/data_collector_spec.rb'
|
||||
- 'ee/spec/lib/gitlab/analytics/cycle_analytics/group_stage_time_summary_spec.rb'
|
||||
- 'ee/spec/lib/gitlab/analytics/cycle_analytics/summary/group/stage_time_summary_spec.rb'
|
||||
- 'ee/spec/lib/gitlab/analytics/type_of_work/tasks_by_type_spec.rb'
|
||||
- 'ee/spec/lib/gitlab/auth/group_saml/sso_enforcer_spec.rb'
|
||||
- 'ee/spec/lib/gitlab/database/load_balancing/host_spec.rb'
|
||||
- 'ee/spec/lib/gitlab/geo/base_request_spec.rb'
|
||||
- 'ee/spec/lib/gitlab/geo/event_gap_tracking_spec.rb'
|
||||
- 'ee/spec/lib/gitlab/geo/git_push_http_spec.rb'
|
||||
- 'ee/spec/lib/gitlab/geo/log_cursor/daemon_spec.rb'
|
||||
- 'ee/spec/lib/gitlab/geo/log_cursor/events/repository_updated_event_spec.rb'
|
||||
- 'ee/spec/lib/gitlab/geo/oauth/login_state_spec.rb'
|
||||
- 'ee/spec/lib/gitlab/insights/reducers/count_per_period_reducer_spec.rb'
|
||||
- 'ee/spec/lib/gitlab/prometheus/queries/additional_metrics_environment_query_spec.rb'
|
||||
- 'ee/spec/lib/gitlab/prometheus/queries/cluster_query_spec.rb'
|
||||
- 'ee/spec/migrations/populate_vulnerability_historical_statistics_for_year_spec.rb'
|
||||
- 'ee/spec/migrations/remove_duplicated_cs_findings_spec.rb'
|
||||
- 'ee/spec/migrations/remove_duplicated_cs_findings_without_vulnerability_id_spec.rb'
|
||||
- 'ee/spec/migrations/schedule_fix_orphan_promoted_issues_spec.rb'
|
||||
- 'ee/spec/migrations/schedule_merge_request_any_approval_rule_migration_spec.rb'
|
||||
- 'ee/spec/migrations/schedule_populate_resolved_on_default_branch_column_spec.rb'
|
||||
- 'ee/spec/migrations/schedule_populate_vulnerability_historical_statistics_spec.rb'
|
||||
- 'ee/spec/migrations/schedule_project_any_approval_rule_migration_spec.rb'
|
||||
- 'ee/spec/migrations/set_resolved_state_on_vulnerabilities_spec.rb'
|
||||
- 'ee/spec/migrations/20190926180443_schedule_epic_issues_after_epics_move_spec.rb'
|
||||
- 'ee/spec/models/analytics/cycle_analytics/group_level_spec.rb'
|
||||
- 'ee/spec/models/burndown_spec.rb'
|
||||
- 'ee/spec/models/ee/namespace_spec.rb'
|
||||
- 'ee/spec/models/geo/project_registry_spec.rb'
|
||||
- 'ee/spec/models/merge_train_spec.rb'
|
||||
- 'ee/spec/models/productivity_analytics_spec.rb'
|
||||
- 'ee/spec/models/project_spec.rb'
|
||||
- 'ee/spec/models/vulnerabilities/export_spec.rb'
|
||||
- 'ee/spec/requests/api/vulnerabilities_spec.rb'
|
||||
- 'ee/spec/services/geo/file_download_service_spec.rb'
|
||||
- 'ee/spec/services/vulnerabilities/confirm_service_spec.rb'
|
||||
- 'ee/spec/services/vulnerabilities/dismiss_service_spec.rb'
|
||||
- 'ee/spec/services/vulnerabilities/resolve_service_spec.rb'
|
||||
- 'ee/spec/services/vulnerabilities/revert_to_detected_service_spec.rb'
|
||||
- 'ee/spec/services/vulnerability_exports/export_service_spec.rb'
|
||||
- 'ee/spec/support/shared_contexts/lib/gitlab/insights/reducers/reducers_shared_contexts.rb'
|
||||
- 'qa/spec/support/repeater_spec.rb'
|
||||
- 'spec/features/profiles/active_sessions_spec.rb'
|
||||
- 'spec/features/projects/environments/environment_metrics_spec.rb'
|
||||
- 'spec/features/users/active_sessions_spec.rb'
|
||||
- 'spec/lib/atlassian/jira_connect/client_spec.rb'
|
||||
- 'spec/lib/gitlab/analytics/cycle_analytics/base_query_builder_spec.rb'
|
||||
- 'spec/lib/gitlab/analytics/cycle_analytics/median_spec.rb'
|
||||
- 'spec/lib/gitlab/analytics/cycle_analytics/records_fetcher_spec.rb'
|
||||
- 'spec/lib/gitlab/anonymous_session_spec.rb'
|
||||
- 'spec/lib/gitlab/auth/unique_ips_limiter_spec.rb'
|
||||
- 'spec/lib/gitlab/checks/timed_logger_spec.rb'
|
||||
- 'spec/lib/gitlab/cycle_analytics/stage_summary_spec.rb'
|
||||
- 'spec/lib/gitlab/cycle_analytics/usage_data_spec.rb'
|
||||
- 'spec/lib/gitlab/instrumentation_helper_spec.rb'
|
||||
- 'spec/lib/gitlab/omniauth_logging/json_formatter_spec.rb'
|
||||
- 'spec/lib/gitlab/puma_logging/json_formatter_spec.rb'
|
||||
- 'spec/lib/gitlab/sidekiq_logging/structured_logger_spec.rb'
|
||||
- 'spec/lib/json_web_token/hmac_token_spec.rb'
|
||||
- 'spec/lib/rspec_flaky/flaky_example_spec.rb'
|
||||
- 'spec/lib/rspec_flaky/listener_spec.rb'
|
||||
- 'spec/models/active_session_spec.rb'
|
||||
- 'spec/models/container_repository_spec.rb'
|
||||
- 'spec/models/pages/lookup_path_spec.rb'
|
||||
- 'spec/models/project_feature_usage_spec.rb'
|
||||
- 'spec/requests/api/v3/github_spec.rb'
|
||||
- 'spec/serializers/entity_date_helper_spec.rb'
|
||||
- 'spec/support/cycle_analytics_helpers/test_generation.rb'
|
||||
- 'spec/support/helpers/cycle_analytics_helpers.rb'
|
||||
- 'spec/support/helpers/javascript_fixtures_helpers.rb'
|
||||
- 'spec/support/shared_contexts/rack_attack_shared_context.rb'
|
||||
- 'spec/support/shared_examples/workers/concerns/reenqueuer_shared_examples.rb'
|
||||
- 'spec/workers/concerns/reenqueuer_spec.rb'
|
||||
- 'spec/workers/metrics/dashboard/prune_old_annotations_worker_spec.rb'
|
||||
|
||||
RSpec/TimecopTravel:
|
||||
Exclude:
|
||||
- 'ee/spec/lib/gitlab/geo/event_gap_tracking_spec.rb'
|
||||
- 'ee/spec/lib/gitlab/geo/git_push_http_spec.rb'
|
||||
- 'ee/spec/lib/gitlab/geo/jwt_request_decoder_spec.rb'
|
||||
- 'ee/spec/lib/gitlab/geo/log_cursor/daemon_spec.rb'
|
||||
- 'ee/spec/models/broadcast_message_spec.rb'
|
||||
- 'ee/spec/models/burndown_spec.rb'
|
||||
- 'qa/spec/support/repeater_spec.rb'
|
||||
- 'spec/features/users/terms_spec.rb'
|
||||
- 'spec/lib/feature_spec.rb'
|
||||
- 'spec/models/broadcast_message_spec.rb'
|
||||
- 'spec/models/concerns/issuable_spec.rb'
|
||||
- 'spec/requests/api/ci/runner/jobs_trace_spec.rb'
|
||||
- 'spec/requests/api/issues/put_projects_issues_spec.rb'
|
||||
- 'spec/support/shared_contexts/cache_allowed_users_in_namespace_shared_context.rb'
|
||||
- 'spec/support/shared_examples/requests/api/time_tracking_shared_examples.rb'
|
||||
- 'spec/support/shared_examples/workers/concerns/reenqueuer_shared_examples.rb'
|
||||
- 'spec/workers/concerns/reenqueuer_spec.rb'
|
||||
- 'spec/lib/gitlab/analytics/cycle_analytics/median_spec.rb'
|
||||
1320
.rubocop_todo.yml
1320
.rubocop_todo.yml
File diff suppressed because it is too large
Load Diff
6
Gemfile
6
Gemfile
|
|
@ -370,11 +370,7 @@ group :development, :test do
|
|||
gem 'spring', '~> 2.0.0'
|
||||
gem 'spring-commands-rspec', '~> 1.0.4'
|
||||
|
||||
gem 'gitlab-styles', '~> 4.3.0', require: false
|
||||
# Pin these dependencies, otherwise a new rule could break the CI pipelines
|
||||
gem 'rubocop', '~> 0.82.0'
|
||||
gem 'rubocop-performance', '~> 1.5.2'
|
||||
gem 'rubocop-rspec', '~> 1.37.0'
|
||||
gem 'gitlab-styles', '~> 5.0.0', require: false
|
||||
|
||||
gem 'scss_lint', '~> 0.56.0', require: false
|
||||
gem 'haml_lint', '~> 0.36.0', require: false
|
||||
|
|
|
|||
47
Gemfile.lock
47
Gemfile.lock
|
|
@ -449,12 +449,12 @@ GEM
|
|||
gitlab-puma (>= 2.7, < 5)
|
||||
gitlab-sidekiq-fetcher (0.5.2)
|
||||
sidekiq (~> 5)
|
||||
gitlab-styles (4.3.0)
|
||||
rubocop (~> 0.82.0)
|
||||
gitlab-styles (5.0.0)
|
||||
rubocop (~> 0.89.1)
|
||||
rubocop-gitlab-security (~> 0.1.0)
|
||||
rubocop-performance (~> 1.5.2)
|
||||
rubocop-rails (~> 2.5)
|
||||
rubocop-rspec (~> 1.36)
|
||||
rubocop-performance (~> 1.8.1)
|
||||
rubocop-rails (~> 2.8)
|
||||
rubocop-rspec (~> 1.44)
|
||||
gitlab_chronic_duration (0.10.6.2)
|
||||
numerizer (~> 0.2)
|
||||
gitlab_omniauth-ldap (2.1.1)
|
||||
|
|
@ -602,7 +602,6 @@ GEM
|
|||
jaeger-client (1.1.0)
|
||||
opentracing (~> 0.3)
|
||||
thrift
|
||||
jaro_winkler (1.5.4)
|
||||
jira-ruby (2.0.0)
|
||||
activesupport
|
||||
atlassian-jwt
|
||||
|
|
@ -834,7 +833,7 @@ GEM
|
|||
rubypants (~> 0.2)
|
||||
orm_adapter (0.5.0)
|
||||
os (1.0.0)
|
||||
parallel (1.19.1)
|
||||
parallel (1.19.2)
|
||||
parser (2.7.2.0)
|
||||
ast (~> 2.4.1)
|
||||
parslet (1.8.2)
|
||||
|
|
@ -958,7 +957,7 @@ GEM
|
|||
redis-store (>= 1.2, < 2)
|
||||
redis-store (1.8.1)
|
||||
redis (>= 4, < 5)
|
||||
regexp_parser (1.5.1)
|
||||
regexp_parser (1.8.2)
|
||||
regexp_property_values (0.3.5)
|
||||
representable (3.0.4)
|
||||
declarative (< 0.1.0)
|
||||
|
|
@ -1019,24 +1018,29 @@ GEM
|
|||
pg
|
||||
rails
|
||||
sqlite3
|
||||
rubocop (0.82.0)
|
||||
jaro_winkler (~> 1.5.1)
|
||||
rubocop (0.89.1)
|
||||
parallel (~> 1.10)
|
||||
parser (>= 2.7.0.1)
|
||||
parser (>= 2.7.1.1)
|
||||
rainbow (>= 2.2.2, < 4.0)
|
||||
regexp_parser (>= 1.7)
|
||||
rexml
|
||||
rubocop-ast (>= 0.3.0, < 1.0)
|
||||
ruby-progressbar (~> 1.7)
|
||||
unicode-display_width (>= 1.4.0, < 2.0)
|
||||
rubocop-ast (0.8.0)
|
||||
parser (>= 2.7.1.5)
|
||||
rubocop-gitlab-security (0.1.1)
|
||||
rubocop (>= 0.51)
|
||||
rubocop-performance (1.5.2)
|
||||
rubocop (>= 0.71.0)
|
||||
rubocop-rails (2.5.2)
|
||||
activesupport
|
||||
rubocop-performance (1.8.1)
|
||||
rubocop (>= 0.87.0)
|
||||
rubocop-ast (>= 0.4.0)
|
||||
rubocop-rails (2.8.1)
|
||||
activesupport (>= 4.2.0)
|
||||
rack (>= 1.1)
|
||||
rubocop (>= 0.72.0)
|
||||
rubocop-rspec (1.37.0)
|
||||
rubocop (>= 0.68.1)
|
||||
rubocop (>= 0.87.0)
|
||||
rubocop-rspec (1.44.1)
|
||||
rubocop (~> 0.87)
|
||||
rubocop-ast (>= 0.7.1)
|
||||
ruby-enum (0.7.2)
|
||||
i18n
|
||||
ruby-fogbugz (0.2.1)
|
||||
|
|
@ -1249,7 +1253,7 @@ GEM
|
|||
xpath (3.2.0)
|
||||
nokogiri (~> 1.8)
|
||||
yajl-ruby (1.4.1)
|
||||
zeitwerk (2.4.0)
|
||||
zeitwerk (2.4.1)
|
||||
|
||||
PLATFORMS
|
||||
ruby
|
||||
|
|
@ -1353,7 +1357,7 @@ DEPENDENCIES
|
|||
gitlab-puma (~> 4.3.3.gitlab.2)
|
||||
gitlab-puma_worker_killer (~> 0.1.1.gitlab.1)
|
||||
gitlab-sidekiq-fetcher (= 0.5.2)
|
||||
gitlab-styles (~> 4.3.0)
|
||||
gitlab-styles (~> 5.0.0)
|
||||
gitlab_chronic_duration (~> 0.10.6.2)
|
||||
gitlab_omniauth-ldap (~> 2.1.1)
|
||||
gon (~> 6.2)
|
||||
|
|
@ -1473,9 +1477,6 @@ DEPENDENCIES
|
|||
rspec-retry (~> 0.6.1)
|
||||
rspec_junit_formatter
|
||||
rspec_profiling (~> 0.0.6)
|
||||
rubocop (~> 0.82.0)
|
||||
rubocop-performance (~> 1.5.2)
|
||||
rubocop-rspec (~> 1.37.0)
|
||||
ruby-fogbugz (~> 0.2.1)
|
||||
ruby-prof (~> 1.3.0)
|
||||
ruby-progressbar
|
||||
|
|
|
|||
|
|
@ -1,5 +1,12 @@
|
|||
<script>
|
||||
import { GlTable, GlIcon, GlTooltipDirective, GlLoadingIcon } from '@gitlab/ui';
|
||||
import {
|
||||
GlButtonGroup,
|
||||
GlButton,
|
||||
GlIcon,
|
||||
GlLoadingIcon,
|
||||
GlTable,
|
||||
GlTooltipDirective,
|
||||
} from '@gitlab/ui';
|
||||
import { s__, __ } from '~/locale';
|
||||
import Tracking from '~/tracking';
|
||||
import { trackAlertIntegrationsViewsOptions } from '../constants';
|
||||
|
|
@ -25,9 +32,11 @@ const bodyTrClass =
|
|||
export default {
|
||||
i18n,
|
||||
components: {
|
||||
GlTable,
|
||||
GlButtonGroup,
|
||||
GlButton,
|
||||
GlIcon,
|
||||
GlLoadingIcon,
|
||||
GlTable,
|
||||
},
|
||||
directives: {
|
||||
GlTooltip: GlTooltipDirective,
|
||||
|
|
@ -57,6 +66,10 @@ export default {
|
|||
key: 'type',
|
||||
label: __('Type'),
|
||||
},
|
||||
{
|
||||
key: 'actions',
|
||||
label: __('Actions'),
|
||||
},
|
||||
],
|
||||
computed: {
|
||||
tbodyTrClass() {
|
||||
|
|
@ -111,6 +124,13 @@ export default {
|
|||
</span>
|
||||
</template>
|
||||
|
||||
<template #cell(actions)="{ item }">
|
||||
<gl-button-group>
|
||||
<gl-button icon="pencil" @click="$emit('edit-integration', { id: item.id })" />
|
||||
<gl-button icon="remove" @click="$emit('delete-integration', { id: item.id })" />
|
||||
</gl-button-group>
|
||||
</template>
|
||||
|
||||
<template #table-busy>
|
||||
<gl-loading-icon size="lg" color="dark" class="mt-3" />
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -21,12 +21,14 @@ import {
|
|||
JSON_VALIDATE_DELAY,
|
||||
targetPrometheusUrlPlaceholder,
|
||||
typeSet,
|
||||
defaultFormState,
|
||||
} from '../constants';
|
||||
|
||||
export default {
|
||||
targetPrometheusUrlPlaceholder,
|
||||
JSON_VALIDATE_DELAY,
|
||||
typeSet,
|
||||
defaultFormState,
|
||||
i18n: {
|
||||
integrationFormSteps: {
|
||||
step1: {
|
||||
|
|
@ -62,6 +64,11 @@ export default {
|
|||
label: s__('AlertSettings|Prometheus API base URL'),
|
||||
help: s__('AlertSettings|URL cannot be blank and must start with http or https'),
|
||||
},
|
||||
restKeyInfo: {
|
||||
label: s__(
|
||||
'AlertSettings|Resetting the authorization key for this project will require updating the authorization key in every alert source it is enabled in.',
|
||||
),
|
||||
},
|
||||
},
|
||||
},
|
||||
components: {
|
||||
|
|
@ -95,23 +102,18 @@ export default {
|
|||
type: Boolean,
|
||||
required: true,
|
||||
},
|
||||
currentIntegration: {
|
||||
type: Object,
|
||||
required: false,
|
||||
default: null,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
selectedIntegration: integrationTypesNew[0].value,
|
||||
active: false,
|
||||
options: integrationTypesNew,
|
||||
formVisible: false,
|
||||
integrationForm: {
|
||||
name: '',
|
||||
integrationTestPayload: {
|
||||
json: null,
|
||||
error: null,
|
||||
},
|
||||
active: false,
|
||||
authKey: '',
|
||||
url: '',
|
||||
apiUrl: '',
|
||||
},
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
|
|
@ -125,9 +127,29 @@ export default {
|
|||
case this.$options.typeSet.prometheus:
|
||||
return this.prometheus;
|
||||
default:
|
||||
return {};
|
||||
return this.defaultFormState;
|
||||
}
|
||||
},
|
||||
integrationForm() {
|
||||
return {
|
||||
name: this.currentIntegration?.name || '',
|
||||
integrationTestPayload: {
|
||||
json: null,
|
||||
error: null,
|
||||
},
|
||||
active: this.currentIntegration?.active || false,
|
||||
token: this.currentIntegration?.token || '',
|
||||
url: this.currentIntegration?.url || '',
|
||||
apiUrl: this.currentIntegration?.apiUrl || '',
|
||||
};
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
currentIntegration(val) {
|
||||
this.selectedIntegration = val.type;
|
||||
this.active = val.active;
|
||||
this.onIntegrationTypeSelect();
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
onIntegrationTypeSelect() {
|
||||
|
|
@ -142,18 +164,29 @@ export default {
|
|||
this.onSubmit();
|
||||
},
|
||||
onSubmit() {
|
||||
const { name, apiUrl, active } = this.integrationForm;
|
||||
const { name, apiUrl } = this.integrationForm;
|
||||
const variables =
|
||||
this.selectedIntegration === this.$options.typeSet.http
|
||||
? { name, active }
|
||||
: { apiUrl, active };
|
||||
this.$emit('on-create-new-integration', { type: this.selectedIntegration, variables });
|
||||
? { name, active: this.active }
|
||||
: { apiUrl, active: this.active };
|
||||
const integrationPayload = { type: this.selectedIntegration, variables };
|
||||
|
||||
if (this.currentIntegration) {
|
||||
return this.$emit('update-integration', integrationPayload);
|
||||
}
|
||||
|
||||
return this.$emit('create-new-integration', integrationPayload);
|
||||
},
|
||||
onReset() {
|
||||
// TODO: Reset form values
|
||||
this.integrationForm = this.defaultFormState;
|
||||
this.selectedIntegration = integrationTypesNew[0].value;
|
||||
this.onIntegrationTypeSelect();
|
||||
},
|
||||
onResetAuthKey() {
|
||||
// TODO: Handle reset auth key via GraphQL
|
||||
this.$emit('reset-token', {
|
||||
type: this.selectedIntegration,
|
||||
variables: { id: this.currentIntegration.id },
|
||||
});
|
||||
},
|
||||
validateJson() {
|
||||
this.integrationForm.integrationTestPayload.error = null;
|
||||
|
|
@ -214,7 +247,7 @@ export default {
|
|||
/>
|
||||
|
||||
<gl-toggle
|
||||
v-model="integrationForm.active"
|
||||
v-model="active"
|
||||
:is-loading="loading"
|
||||
:label="__('Active')"
|
||||
class="gl-my-4 gl-font-weight-normal"
|
||||
|
|
@ -242,13 +275,9 @@ export default {
|
|||
{{ s__('AlertSettings|Webhook URL') }}
|
||||
</span>
|
||||
|
||||
<gl-form-input-group id="url" readonly :value="selectedIntegrationType.url">
|
||||
<gl-form-input-group id="url" readonly :value="integrationForm.url">
|
||||
<template #append>
|
||||
<clipboard-button
|
||||
:text="selectedIntegrationType.url || ''"
|
||||
:title="__('Copy')"
|
||||
class="gl-m-0!"
|
||||
/>
|
||||
<clipboard-button :text="integrationForm.url" :title="__('Copy')" class="gl-m-0!" />
|
||||
</template>
|
||||
</gl-form-input-group>
|
||||
</div>
|
||||
|
|
@ -262,14 +291,10 @@ export default {
|
|||
id="authorization-key"
|
||||
class="gl-mb-2"
|
||||
readonly
|
||||
:value="selectedIntegrationType.authKey"
|
||||
:value="integrationForm.token"
|
||||
>
|
||||
<template #append>
|
||||
<clipboard-button
|
||||
:text="selectedIntegrationType.authKey || ''"
|
||||
:title="__('Copy')"
|
||||
class="gl-m-0!"
|
||||
/>
|
||||
<clipboard-button :text="integrationForm.token" :title="__('Copy')" class="gl-m-0!" />
|
||||
</template>
|
||||
</gl-form-input-group>
|
||||
|
||||
|
|
@ -281,9 +306,9 @@ export default {
|
|||
:title="$options.i18n.integrationFormSteps.step3.reset"
|
||||
:ok-title="$options.i18n.integrationFormSteps.step3.reset"
|
||||
ok-variant="danger"
|
||||
@ok="() => {}"
|
||||
@ok="onResetAuthKey"
|
||||
>
|
||||
{{ $options.i18n.integrationFormSteps.step3.reset }}
|
||||
{{ $options.i18n.integrationFormSteps.restKeyInfo.label }}
|
||||
</gl-modal>
|
||||
</div>
|
||||
</gl-form-group>
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ export default {
|
|||
selectedIntegration: integrationTypes[0].value,
|
||||
options: integrationTypes,
|
||||
active: false,
|
||||
authKey: '',
|
||||
token: '',
|
||||
targetUrl: '',
|
||||
feedback: {
|
||||
variant: 'danger',
|
||||
|
|
@ -98,7 +98,7 @@ export default {
|
|||
case 'HTTP': {
|
||||
return {
|
||||
url: this.generic.url,
|
||||
authKey: this.generic.authKey,
|
||||
token: this.generic.token,
|
||||
active: this.generic.active,
|
||||
resetKey: this.resetKey.bind(this),
|
||||
};
|
||||
|
|
@ -106,7 +106,7 @@ export default {
|
|||
case 'PROMETHEUS': {
|
||||
return {
|
||||
url: this.prometheus.url,
|
||||
authKey: this.prometheus.authKey,
|
||||
token: this.prometheus.token,
|
||||
active: this.prometheus.active,
|
||||
resetKey: this.resetKey.bind(this, 'PROMETHEUS'),
|
||||
targetUrl: this.prometheus.prometheusApiUrl,
|
||||
|
|
@ -167,7 +167,7 @@ export default {
|
|||
this.setOpsgenieAsDefault();
|
||||
}
|
||||
this.active = this.selectedIntegrationType.active;
|
||||
this.authKey = this.selectedIntegrationType.authKey ?? '';
|
||||
this.token = this.selectedIntegrationType.token ?? '';
|
||||
},
|
||||
methods: {
|
||||
createUserErrorMessage(errors = {}) {
|
||||
|
|
@ -212,8 +212,8 @@ export default {
|
|||
|
||||
return fn
|
||||
.then(({ data: { token } }) => {
|
||||
this.authKey = token;
|
||||
this.setFeedback({ feedbackMessage: this.$options.i18n.authKeyRest, variant: 'success' });
|
||||
this.token = token;
|
||||
this.setFeedback({ feedbackMessage: this.$options.i18n.tokenRest, variant: 'success' });
|
||||
})
|
||||
.catch(() => {
|
||||
this.setFeedback({ feedbackMessage: this.$options.i18n.errorKeyMsg, variant: 'danger' });
|
||||
|
|
@ -313,7 +313,7 @@ export default {
|
|||
.updateTestAlert({
|
||||
endpoint: this.selectedIntegrationType.url,
|
||||
data: this.testAlert.json,
|
||||
authKey: this.selectedIntegrationType.authKey,
|
||||
token: this.selectedIntegrationType.token,
|
||||
})
|
||||
.then(() => {
|
||||
this.setFeedback({
|
||||
|
|
@ -439,21 +439,21 @@ export default {
|
|||
{{ prometheusInfo }}
|
||||
</span>
|
||||
</gl-form-group>
|
||||
<gl-form-group :label="$options.i18n.authKeyLabel" label-for="authorization-key">
|
||||
<gl-form-input-group id="authorization-key" class="gl-mb-2" readonly :value="authKey">
|
||||
<gl-form-group :label="$options.i18n.tokenLabel" label-for="authorization-key">
|
||||
<gl-form-input-group id="authorization-key" class="gl-mb-2" readonly :value="token">
|
||||
<template #append>
|
||||
<clipboard-button
|
||||
:text="authKey"
|
||||
:text="token"
|
||||
:title="$options.i18n.copyToClipboard"
|
||||
class="gl-m-0!"
|
||||
/>
|
||||
</template>
|
||||
</gl-form-input-group>
|
||||
<gl-button v-gl-modal.authKeyModal :disabled="!active" class="gl-mt-3">{{
|
||||
<gl-button v-gl-modal.tokenModal :disabled="!active" class="gl-mt-3">{{
|
||||
$options.i18n.resetKey
|
||||
}}</gl-button>
|
||||
<gl-modal
|
||||
modal-id="authKeyModal"
|
||||
modal-id="tokenModal"
|
||||
:title="$options.i18n.resetKey"
|
||||
:ok-title="$options.i18n.resetKey"
|
||||
ok-variant="danger"
|
||||
|
|
|
|||
|
|
@ -7,6 +7,10 @@ import createFlash, { FLASH_TYPES } from '~/flash';
|
|||
import getIntegrationsQuery from '../graphql/queries/get_integrations.query.graphql';
|
||||
import createHttpIntegrationMutation from '../graphql/mutations/create_http_integration.mutation.graphql';
|
||||
import createPrometheusIntegrationMutation from '../graphql/mutations/create_prometheus_integration.mutation.graphql';
|
||||
import updateHttpIntegrationMutation from '../graphql/mutations/update_http_integration.mutation.graphql';
|
||||
import updatePrometheusIntegrationMutation from '../graphql/mutations/update_prometheus_integration.mutation.graphql';
|
||||
import resetHttpTokenMutation from '../graphql/mutations/reset_http_token.mutation.graphql';
|
||||
import resetPrometheusTokenMutation from '../graphql/mutations/reset_prometheus_token.mutation.graphql';
|
||||
import IntegrationsList from './alerts_integrations_list.vue';
|
||||
import SettingsFormOld from './alerts_settings_form_old.vue';
|
||||
import SettingsFormNew from './alerts_settings_form_new.vue';
|
||||
|
|
@ -52,16 +56,16 @@ export default {
|
|||
list,
|
||||
};
|
||||
},
|
||||
error() {
|
||||
this.errored = true;
|
||||
error(err) {
|
||||
createFlash({ message: err });
|
||||
},
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
errored: false,
|
||||
isUpdating: false,
|
||||
integrations: {},
|
||||
currentIntegration: null,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
|
|
@ -84,7 +88,7 @@ export default {
|
|||
},
|
||||
},
|
||||
methods: {
|
||||
onCreateNewIntegration({ type, variables }) {
|
||||
createNewIntegration({ type, variables }) {
|
||||
this.isUpdating = true;
|
||||
this.$apollo
|
||||
.mutate({
|
||||
|
|
@ -109,7 +113,6 @@ export default {
|
|||
});
|
||||
})
|
||||
.catch(err => {
|
||||
this.errored = true;
|
||||
createFlash({ message: err });
|
||||
})
|
||||
.finally(() => {
|
||||
|
|
@ -151,6 +154,72 @@ export default {
|
|||
data,
|
||||
});
|
||||
},
|
||||
updateIntegration({ type, variables }) {
|
||||
this.isUpdating = true;
|
||||
this.$apollo
|
||||
.mutate({
|
||||
mutation:
|
||||
type === this.$options.typeSet.http
|
||||
? updateHttpIntegrationMutation
|
||||
: updatePrometheusIntegrationMutation,
|
||||
variables: {
|
||||
...variables,
|
||||
id: this.currentIntegration.id,
|
||||
},
|
||||
})
|
||||
.then(({ data: { httpIntegrationUpdate, prometheusIntegrationUpdate } = {} } = {}) => {
|
||||
const error = httpIntegrationUpdate?.errors[0] || prometheusIntegrationUpdate?.errors[0];
|
||||
if (error) {
|
||||
return createFlash({ message: error });
|
||||
}
|
||||
return createFlash({
|
||||
message: this.$options.i18n.changesSaved,
|
||||
type: FLASH_TYPES.SUCCESS,
|
||||
});
|
||||
})
|
||||
.catch(err => {
|
||||
createFlash({ message: err });
|
||||
})
|
||||
.finally(() => {
|
||||
this.isUpdating = false;
|
||||
});
|
||||
},
|
||||
resetToken({ type, variables }) {
|
||||
this.isUpdating = true;
|
||||
this.$apollo
|
||||
.mutate({
|
||||
mutation:
|
||||
type === this.$options.typeSet.http
|
||||
? resetHttpTokenMutation
|
||||
: resetPrometheusTokenMutation,
|
||||
variables,
|
||||
})
|
||||
.then(
|
||||
({ data: { httpIntegrationResetToken, prometheusIntegrationResetToken } = {} } = {}) => {
|
||||
const error =
|
||||
httpIntegrationResetToken?.errors[0] || prometheusIntegrationResetToken?.errors[0];
|
||||
if (error) {
|
||||
return createFlash({ message: error });
|
||||
}
|
||||
return createFlash({
|
||||
message: this.$options.i18n.changesSaved,
|
||||
type: FLASH_TYPES.SUCCESS,
|
||||
});
|
||||
},
|
||||
)
|
||||
.catch(err => {
|
||||
createFlash({ message: err });
|
||||
})
|
||||
.finally(() => {
|
||||
this.isUpdating = false;
|
||||
});
|
||||
},
|
||||
editIntegration({ id }) {
|
||||
this.currentIntegration = this.integrations.list.find(integration => integration.id === id);
|
||||
},
|
||||
deleteIntegration() {
|
||||
// TODO, handle delete via GraphQL
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
|
@ -160,11 +229,16 @@ export default {
|
|||
<integrations-list
|
||||
:integrations="glFeatures.httpIntegrationsList ? integrations.list : intergrationsOptionsOld"
|
||||
:loading="loading"
|
||||
@edit-integration="editIntegration"
|
||||
@delete-integration="deleteIntegration"
|
||||
/>
|
||||
<settings-form-new
|
||||
v-if="glFeatures.httpIntegrationsList"
|
||||
:loading="loading"
|
||||
@on-create-new-integration="onCreateNewIntegration"
|
||||
:loading="isUpdating"
|
||||
:current-integration="currentIntegration"
|
||||
@create-new-integration="createNewIntegration"
|
||||
@update-integration="updateIntegration"
|
||||
@reset-token="resetToken"
|
||||
/>
|
||||
<settings-form-old v-else />
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -57,6 +57,15 @@ export const typeSet = {
|
|||
prometheus: 'PROMETHEUS',
|
||||
};
|
||||
|
||||
export const defaultFormState = {
|
||||
name: '',
|
||||
active: false,
|
||||
token: '',
|
||||
url: '',
|
||||
apiUrl: '',
|
||||
integrationTestPayload: { json: null, error: null },
|
||||
};
|
||||
|
||||
export const JSON_VALIDATE_DELAY = 250;
|
||||
|
||||
export const targetPrometheusUrlPlaceholder = 'http://prometheus.example.com/';
|
||||
|
|
|
|||
|
|
@ -0,0 +1,10 @@
|
|||
#import "../fragments/integration_item.fragment.graphql"
|
||||
|
||||
mutation resetHttpIntegrationToken($id: ID!) {
|
||||
httpIntegrationResetToken(input: { id: $id }) {
|
||||
errors
|
||||
integration {
|
||||
...IntegrationItem
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
#import "../fragments/integration_item.fragment.graphql"
|
||||
|
||||
mutation resetPrometheusIntegrationToken($id: ID!) {
|
||||
prometheusIntegrationResetToken(input: { id: $id }) {
|
||||
errors
|
||||
integration {
|
||||
...IntegrationItem
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
#import "../fragments/integration_item.fragment.graphql"
|
||||
|
||||
mutation updateHttpIntegration($id: ID!, $name: String!, $active: Boolean!) {
|
||||
httpIntegrationUpdate(input: { id: $id, name: $name, active: $active }) {
|
||||
errors
|
||||
integration {
|
||||
...IntegrationItem
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
#import "../fragments/integration_item.fragment.graphql"
|
||||
|
||||
mutation updatePrometheusIntegration($id: ID!, $apiUrl: String!, $active: Boolean!) {
|
||||
prometheusIntegrationUpdate(input: { id: $id, apiUrl: $apiUrl, active: $active }) {
|
||||
errors
|
||||
integration {
|
||||
...IntegrationItem
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -50,7 +50,7 @@ export default el => {
|
|||
prometheus: {
|
||||
active: parseBoolean(prometheusActivated),
|
||||
url: prometheusUrl,
|
||||
authKey: prometheusAuthorizationKey,
|
||||
token: prometheusAuthorizationKey,
|
||||
prometheusFormPath,
|
||||
prometheusResetKeyPath,
|
||||
prometheusApiUrl,
|
||||
|
|
@ -60,7 +60,7 @@ export default el => {
|
|||
alertsUsageUrl,
|
||||
active: parseBoolean(activatedStr),
|
||||
formPath,
|
||||
authKey: authorizationKey,
|
||||
token: authorizationKey,
|
||||
url,
|
||||
},
|
||||
opsgenie: {
|
||||
|
|
|
|||
|
|
@ -1,11 +1,10 @@
|
|||
<script>
|
||||
import { GlButton, GlLoadingIcon, GlTooltipDirective } from '@gitlab/ui';
|
||||
import { GlButton, GlTooltipDirective } from '@gitlab/ui';
|
||||
import { VALID_DESIGN_FILE_MIMETYPE } from '../../constants';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
GlButton,
|
||||
GlLoadingIcon,
|
||||
},
|
||||
directives: {
|
||||
GlTooltip: GlTooltipDirective,
|
||||
|
|
@ -38,12 +37,12 @@ export default {
|
|||
)
|
||||
"
|
||||
:disabled="isSaving"
|
||||
:loading="isSaving"
|
||||
variant="default"
|
||||
size="small"
|
||||
@click="openFileUpload"
|
||||
>
|
||||
{{ s__('DesignManagement|Upload designs') }}
|
||||
<gl-loading-icon v-if="isSaving" inline class="ml-1" />
|
||||
</gl-button>
|
||||
|
||||
<input
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ export default {
|
|||
<p class="gl-mb-0">
|
||||
{{
|
||||
s__(
|
||||
'Integrations|Projects using custom settings will not be impacted unless the project owner chooses to use instance-level defaults.',
|
||||
'Integrations|Projects using custom settings will not be impacted unless the project owner chooses to use parent level defaults.',
|
||||
)
|
||||
}}
|
||||
</p>
|
||||
|
|
|
|||
|
|
@ -38,8 +38,11 @@ export default {
|
|||
isJira() {
|
||||
return this.propsSource.type === 'jira';
|
||||
},
|
||||
isInstanceLevel() {
|
||||
return this.propsSource.integrationLevel === integrationLevels.INSTANCE;
|
||||
isInstanceOrGroupLevel() {
|
||||
return (
|
||||
this.propsSource.integrationLevel === integrationLevels.INSTANCE ||
|
||||
this.propsSource.integrationLevel === integrationLevels.GROUP
|
||||
);
|
||||
},
|
||||
showJiraIssuesFields() {
|
||||
return this.isJira && this.glFeatures.jiraIssuesIntegration;
|
||||
|
|
@ -91,7 +94,7 @@ export default {
|
|||
v-bind="propsSource.jiraIssuesProps"
|
||||
/>
|
||||
<div v-if="isEditable" class="footer-block row-content-block">
|
||||
<template v-if="isInstanceLevel">
|
||||
<template v-if="isInstanceOrGroupLevel">
|
||||
<gl-button
|
||||
v-gl-modal.confirmSaveIntegration
|
||||
category="primary"
|
||||
|
|
|
|||
|
|
@ -108,12 +108,7 @@ export default {
|
|||
:label="s__('Integrations|Comment detail:')"
|
||||
data-testid="comment-detail"
|
||||
>
|
||||
<input
|
||||
v-if="isInheriting"
|
||||
name="service[comment_detail]"
|
||||
type="hidden"
|
||||
:value="commentDetail"
|
||||
/>
|
||||
<input name="service[comment_detail]" type="hidden" :value="commentDetail" />
|
||||
<gl-form-radio
|
||||
v-for="commentDetailOption in commentDetailOptions"
|
||||
:key="commentDetailOption.value"
|
||||
|
|
|
|||
|
|
@ -6,13 +6,13 @@ import {
|
|||
GlDatepicker,
|
||||
GlLink,
|
||||
GlSprintf,
|
||||
GlSearchBoxByType,
|
||||
GlButton,
|
||||
GlFormInput,
|
||||
} from '@gitlab/ui';
|
||||
import eventHub from '../event_hub';
|
||||
import { s__, sprintf } from '~/locale';
|
||||
import Api from '~/api';
|
||||
import MembersTokenSelect from '~/invite_members/components/members_token_select.vue';
|
||||
|
||||
export default {
|
||||
name: 'InviteMembersModal',
|
||||
|
|
@ -23,9 +23,9 @@ export default {
|
|||
GlDropdown,
|
||||
GlDropdownItem,
|
||||
GlSprintf,
|
||||
GlSearchBoxByType,
|
||||
GlButton,
|
||||
GlFormInput,
|
||||
MembersTokenSelect,
|
||||
},
|
||||
props: {
|
||||
groupId: {
|
||||
|
|
@ -129,44 +129,45 @@ export default {
|
|||
},
|
||||
labels: {
|
||||
modalTitle: s__('InviteMembersModal|Invite team members'),
|
||||
userToInvite: s__('InviteMembersModal|GitLab member or Email address'),
|
||||
newUsersToInvite: s__('InviteMembersModal|GitLab member or Email address'),
|
||||
userPlaceholder: s__('InviteMembersModal|Search for members to invite'),
|
||||
accessLevel: s__('InviteMembersModal|Choose a role permission'),
|
||||
accessExpireDate: s__('InviteMembersModal|Access expiration date (optional)'),
|
||||
toastMessageSuccessful: s__('InviteMembersModal|Users were succesfully added'),
|
||||
toastMessageUnsuccessful: s__('InviteMembersModal|User not invited. Feature coming soon!'),
|
||||
toastMessageSuccessful: s__('InviteMembersModal|Members were successfully added'),
|
||||
toastMessageUnsuccessful: s__('InviteMembersModal|Some of the members could not be added'),
|
||||
readMoreText: s__(`InviteMembersModal|%{linkStart}Read more%{linkEnd} about role permissions`),
|
||||
inviteButtonText: s__('InviteMembersModal|Invite'),
|
||||
cancelButtonText: s__('InviteMembersModal|Cancel'),
|
||||
headerCloseLabel: s__('InviteMembersModal|Close invite team members'),
|
||||
},
|
||||
membersTokenSelectLabelId: 'invite-members-input',
|
||||
};
|
||||
</script>
|
||||
<template>
|
||||
<gl-modal :modal-id="modalId" size="sm" :title="$options.labels.modalTitle">
|
||||
<gl-modal
|
||||
:modal-id="modalId"
|
||||
size="sm"
|
||||
:title="$options.labels.modalTitle"
|
||||
:header-close-label="$options.labels.headerCloseLabel"
|
||||
>
|
||||
<div class="gl-ml-5 gl-mr-5">
|
||||
<div>{{ introText }}</div>
|
||||
|
||||
<label class="gl-font-weight-bold gl-mt-5">{{ $options.labels.userToInvite }}</label>
|
||||
<label :id="$options.membersTokenSelectLabelId" class="gl-font-weight-bold gl-mt-5">{{
|
||||
$options.labels.newUsersToInvite
|
||||
}}</label>
|
||||
<div class="gl-mt-2">
|
||||
<gl-search-box-by-type
|
||||
<members-token-select
|
||||
v-model="newUsersToInvite"
|
||||
:label="$options.labels.newUsersToInvite"
|
||||
:aria-labelledby="$options.membersTokenSelectLabelId"
|
||||
:placeholder="$options.labels.userPlaceholder"
|
||||
type="text"
|
||||
autocomplete="off"
|
||||
autocorrect="off"
|
||||
autocapitalize="off"
|
||||
spellcheck="false"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<label class="gl-font-weight-bold gl-mt-5">{{ $options.labels.accessLevel }}</label>
|
||||
<div class="gl-mt-2 gl-w-half gl-xs-w-full">
|
||||
<gl-dropdown
|
||||
menu-class="dropdown-menu-selectable"
|
||||
class="gl-shadow-none gl-w-full"
|
||||
v-bind="$attrs"
|
||||
:text="selectedRoleName"
|
||||
>
|
||||
<gl-dropdown class="gl-shadow-none gl-w-full" v-bind="$attrs" :text="selectedRoleName">
|
||||
<template v-for="(key, item) in accessLevels">
|
||||
<gl-dropdown-item
|
||||
:key="key"
|
||||
|
|
@ -215,9 +216,13 @@ export default {
|
|||
{{ $options.labels.cancelButtonText }}
|
||||
</gl-button>
|
||||
<div class="gl-mr-3"></div>
|
||||
<gl-button ref="inviteButton" variant="success" @click="sendInvite">{{
|
||||
$options.labels.inviteButtonText
|
||||
}}</gl-button>
|
||||
<gl-button
|
||||
ref="inviteButton"
|
||||
:disabled="!newUsersToInvite"
|
||||
variant="success"
|
||||
@click="sendInvite"
|
||||
>{{ $options.labels.inviteButtonText }}</gl-button
|
||||
>
|
||||
</div>
|
||||
</template>
|
||||
</gl-modal>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,120 @@
|
|||
<script>
|
||||
import { debounce } from 'lodash';
|
||||
import { GlTokenSelector, GlAvatar, GlAvatarLabeled } from '@gitlab/ui';
|
||||
import { USER_SEARCH_DELAY } from '../constants';
|
||||
import Api from '~/api';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
GlTokenSelector,
|
||||
GlAvatar,
|
||||
GlAvatarLabeled,
|
||||
},
|
||||
props: {
|
||||
placeholder: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: '',
|
||||
},
|
||||
ariaLabelledby: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
query: '',
|
||||
users: [],
|
||||
selectedTokens: [],
|
||||
hasBeenFocused: false,
|
||||
hideDropdownWithNoItems: true,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
newUsersToInvite() {
|
||||
return this.selectedTokens
|
||||
.map(obj => {
|
||||
return obj.id;
|
||||
})
|
||||
.join(',');
|
||||
},
|
||||
placeholderText() {
|
||||
if (this.selectedTokens.length === 0) {
|
||||
return this.placeholder;
|
||||
}
|
||||
return '';
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
handleTextInput(query) {
|
||||
this.hideDropdownWithNoItems = false;
|
||||
this.query = query;
|
||||
this.loading = true;
|
||||
this.retrieveUsers(query);
|
||||
},
|
||||
retrieveUsers: debounce(function debouncedRetrieveUsers() {
|
||||
return Api.users(this.query, this.$options.queryOptions)
|
||||
.then(response => {
|
||||
this.users = response.data.map(token => ({
|
||||
id: token.id,
|
||||
name: token.name,
|
||||
username: token.username,
|
||||
avatar_url: token.avatar_url,
|
||||
}));
|
||||
this.loading = false;
|
||||
})
|
||||
.catch(() => {
|
||||
this.loading = false;
|
||||
});
|
||||
}, USER_SEARCH_DELAY),
|
||||
handleInput() {
|
||||
this.$emit('input', this.newUsersToInvite);
|
||||
},
|
||||
handleBlur() {
|
||||
this.hideDropdownWithNoItems = false;
|
||||
},
|
||||
handleFocus() {
|
||||
// The modal auto-focuses on the input when opened.
|
||||
// This prevents the dropdown from opening when the modal opens.
|
||||
if (this.hasBeenFocused) {
|
||||
this.loading = true;
|
||||
this.retrieveUsers();
|
||||
}
|
||||
|
||||
this.hasBeenFocused = true;
|
||||
},
|
||||
},
|
||||
queryOptions: { exclude_internal: true, active: true },
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<gl-token-selector
|
||||
v-model="selectedTokens"
|
||||
:dropdown-items="users"
|
||||
:loading="loading"
|
||||
:allow-user-defined-tokens="false"
|
||||
:hide-dropdown-with-no-items="hideDropdownWithNoItems"
|
||||
:placeholder="placeholderText"
|
||||
:aria-labelledby="ariaLabelledby"
|
||||
@blur="handleBlur"
|
||||
@text-input="handleTextInput"
|
||||
@input="handleInput"
|
||||
@focus="handleFocus"
|
||||
>
|
||||
<template #token-content="{ token }">
|
||||
<gl-avatar v-if="token.avatar_url" :src="token.avatar_url" :size="16" />
|
||||
{{ token.name }}
|
||||
</template>
|
||||
|
||||
<template #dropdown-item-content="{ dropdownItem }">
|
||||
<gl-avatar-labeled
|
||||
:src="dropdownItem.avatar_url"
|
||||
:size="32"
|
||||
:label="dropdownItem.name"
|
||||
:sub-label="dropdownItem.username"
|
||||
/>
|
||||
</template>
|
||||
</gl-token-selector>
|
||||
</template>
|
||||
|
|
@ -0,0 +1 @@
|
|||
export const USER_SEARCH_DELAY = 200;
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
globals:
|
||||
AP: readonly
|
||||
rules:
|
||||
'@gitlab/require-i18n-strings': off
|
||||
'@gitlab/vue-require-i18n-strings': off
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
<script>
|
||||
export default {};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div></div>
|
||||
</template>
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
import Vue from 'vue';
|
||||
import App from './components/app.vue';
|
||||
|
||||
function initJiraConnect() {
|
||||
const el = document.querySelector('.js-jira-connect-app');
|
||||
|
||||
return new Vue({
|
||||
el,
|
||||
render(createElement) {
|
||||
return createElement(App, {});
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
document.addEventListener('DOMContentLoaded', initJiraConnect);
|
||||
|
|
@ -115,14 +115,10 @@ code {
|
|||
background-color: $gray-50;
|
||||
border-radius: $border-radius-default;
|
||||
|
||||
.code > & {
|
||||
background-color: inherit;
|
||||
padding: unset;
|
||||
}
|
||||
|
||||
.code > &,
|
||||
.build-trace & {
|
||||
background-color: inherit;
|
||||
padding: inherit;
|
||||
padding: unset;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,6 @@
|
|||
@import 'framework/variables';
|
||||
@import 'mixins_and_variables_and_functions';
|
||||
// We should only import styles that we actually use.
|
||||
// @import '@gitlab/ui/src/scss/gitlab_ui';
|
||||
|
||||
$atlaskit-border-color: #dfe1e6;
|
||||
|
||||
|
|
|
|||
|
|
@ -150,6 +150,14 @@ module PageLayoutHelper
|
|||
css_class.join(' ')
|
||||
end
|
||||
|
||||
def page_itemtype(itemtype = nil)
|
||||
if itemtype
|
||||
@page_itemtype = { itemscope: true, itemtype: itemtype }
|
||||
else
|
||||
@page_itemtype || {}
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def generic_canonical_url
|
||||
|
|
|
|||
|
|
@ -91,18 +91,18 @@ module UsersHelper
|
|||
end
|
||||
end
|
||||
|
||||
def work_information(user)
|
||||
def work_information(user, with_schema_markup: false)
|
||||
return unless user
|
||||
|
||||
organization = user.organization
|
||||
job_title = user.job_title
|
||||
|
||||
if organization.present? && job_title.present?
|
||||
s_('Profile|%{job_title} at %{organization}') % { job_title: job_title, organization: organization }
|
||||
render_job_title_and_organization(job_title, organization, with_schema_markup: with_schema_markup)
|
||||
elsif job_title.present?
|
||||
job_title
|
||||
render_job_title(job_title, with_schema_markup: with_schema_markup)
|
||||
elsif organization.present?
|
||||
organization
|
||||
render_organization(organization, with_schema_markup: with_schema_markup)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -151,6 +151,35 @@ module UsersHelper
|
|||
|
||||
items
|
||||
end
|
||||
|
||||
def render_job_title(job_title, with_schema_markup: false)
|
||||
if with_schema_markup
|
||||
content_tag :span, itemprop: 'jobTitle' do
|
||||
job_title
|
||||
end
|
||||
else
|
||||
job_title
|
||||
end
|
||||
end
|
||||
|
||||
def render_organization(organization, with_schema_markup: false)
|
||||
if with_schema_markup
|
||||
content_tag :span, itemprop: 'worksFor' do
|
||||
organization
|
||||
end
|
||||
else
|
||||
organization
|
||||
end
|
||||
end
|
||||
|
||||
def render_job_title_and_organization(job_title, organization, with_schema_markup: false)
|
||||
if with_schema_markup
|
||||
job_title = '<span itemprop="jobTitle">'.html_safe + job_title + "</span>".html_safe
|
||||
organization = '<span itemprop="worksFor">'.html_safe + organization + "</span>".html_safe
|
||||
end
|
||||
|
||||
html_escape(s_('Profile|%{job_title} at %{organization}')) % { job_title: job_title, organization: organization }
|
||||
end
|
||||
end
|
||||
|
||||
UsersHelper.prepend_if_ee('EE::UsersHelper')
|
||||
|
|
|
|||
|
|
@ -21,6 +21,8 @@
|
|||
.gl-mt-5
|
||||
%p Note: this integration only works with accounts on GitLab.com (SaaS).
|
||||
- else
|
||||
.js-jira-connect-app
|
||||
|
||||
%form#add-subscription-form.subscription-form{ action: jira_connect_subscriptions_path }
|
||||
.ak-field-group
|
||||
%label
|
||||
|
|
@ -57,5 +59,8 @@
|
|||
or enable cross-site cookies in your browser when adding a namespace.
|
||||
%a{ href: 'https://gitlab.com/gitlab-org/gitlab/-/issues/263509', target: '_blank', rel: 'noopener noreferrer' } Learn more
|
||||
|
||||
= webpack_bundle_tag 'performance_bar' if performance_bar_enabled?
|
||||
= webpack_bundle_tag 'jira_connect_app'
|
||||
|
||||
= page_specific_javascript_tag('jira_connect.js')
|
||||
- add_page_specific_style 'page_bundles/jira_connect'
|
||||
|
|
|
|||
|
|
@ -20,6 +20,6 @@
|
|||
- unless @hide_breadcrumbs
|
||||
= render "layouts/nav/breadcrumbs"
|
||||
%div{ class: "#{(container_class unless @no_container)} #{@content_class}" }
|
||||
.content{ id: "content-body" }
|
||||
.content{ id: "content-body", **page_itemtype }
|
||||
= render "layouts/flash", extra_flash_class: 'limit-container-width'
|
||||
= yield
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
- page_title @user.blocked? ? s_('UserProfile|Blocked user') : @user.name
|
||||
- page_description @user.bio_html
|
||||
- header_title @user.name, user_path(@user)
|
||||
- page_itemtype 'http://schema.org/Person'
|
||||
- link_classes = "flex-grow-1 mx-1 "
|
||||
|
||||
= content_for :meta_tags do
|
||||
|
|
@ -35,7 +36,7 @@
|
|||
.profile-header{ class: [('with-no-profile-tabs' if profile_tabs.empty?)] }
|
||||
.avatar-holder
|
||||
= link_to avatar_icon_for_user(@user, 400), target: '_blank', rel: 'noopener noreferrer' do
|
||||
= image_tag avatar_icon_for_user(@user, 90), class: "avatar s90", alt: ''
|
||||
= image_tag avatar_icon_for_user(@user, 90), class: "avatar s90", alt: '', itemprop: 'image'
|
||||
|
||||
- if @user.blocked?
|
||||
.user-info
|
||||
|
|
@ -44,7 +45,7 @@
|
|||
= render "users/profile_basic_info"
|
||||
- else
|
||||
.user-info
|
||||
.cover-title
|
||||
.cover-title{ itemprop: 'name' }
|
||||
= @user.name
|
||||
|
||||
- if @user.status
|
||||
|
|
@ -54,15 +55,15 @@
|
|||
= render "users/profile_basic_info"
|
||||
.cover-desc.cgray.mb-1.mb-sm-2
|
||||
- unless @user.location.blank?
|
||||
.profile-link-holder.middle-dot-divider-sm.d-block.d-sm-inline.mb-1.mb-sm-0
|
||||
.profile-link-holder.middle-dot-divider-sm.d-block.d-sm-inline.mb-1.mb-sm-0{ itemprop: 'address', itemscope: true, itemtype: 'https://schema.org/PostalAddress' }
|
||||
= sprite_icon('location', css_class: 'vertical-align-sub fgray')
|
||||
%span.vertical-align-middle
|
||||
%span.vertical-align-middle{ itemprop: 'addressLocality' }
|
||||
= @user.location
|
||||
- unless work_information(@user).blank?
|
||||
.profile-link-holder.middle-dot-divider-sm.d-block.d-sm-inline
|
||||
= sprite_icon('work', css_class: 'vertical-align-middle fgray')
|
||||
%span.vertical-align-middle
|
||||
= work_information(@user)
|
||||
= work_information(@user, with_schema_markup: true)
|
||||
.cover-desc.cgray.mb-1.mb-sm-2
|
||||
- unless @user.skype.blank?
|
||||
.profile-link-holder.middle-dot-divider
|
||||
|
|
@ -80,10 +81,10 @@
|
|||
.profile-link-holder.middle-dot-divider-sm.d-block.d-sm-inline.mt-1.mt-sm-0
|
||||
- if Feature.enabled?(:security_auto_fix) && @user.bot?
|
||||
= sprite_icon('question', css_class: 'gl-text-blue-600')
|
||||
= link_to @user.short_website_url, @user.full_website_url, class: 'text-link', target: '_blank', rel: 'me noopener noreferrer nofollow'
|
||||
= link_to @user.short_website_url, @user.full_website_url, class: 'text-link', target: '_blank', rel: 'me noopener noreferrer nofollow', itemprop: 'url'
|
||||
- unless @user.public_email.blank?
|
||||
.profile-link-holder.middle-dot-divider-sm.d-block.d-sm-inline.mt-1.mt-sm-0
|
||||
= link_to @user.public_email, "mailto:#{@user.public_email}", class: 'text-link'
|
||||
= link_to @user.public_email, "mailto:#{@user.public_email}", class: 'text-link', itemprop: 'email'
|
||||
- if @user.bio.present?
|
||||
.cover-desc.cgray
|
||||
.profile-user-bio
|
||||
|
|
|
|||
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Fix setting Comment detail for Jira and modal for groups
|
||||
merge_request: 46945
|
||||
author:
|
||||
type: fixed
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Add structured markup for users
|
||||
merge_request: 46553
|
||||
author:
|
||||
type: added
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Use standard loading state for Design Upload button
|
||||
merge_request: 46292
|
||||
author:
|
||||
type: changed
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Fix code lines being cut-off on failed job tab
|
||||
merge_request: 46885
|
||||
author:
|
||||
type: fixed
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Add GraphQL burnup endpoint under milestone and iteration reports
|
||||
merge_request: 45121
|
||||
author:
|
||||
type: added
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
---
|
||||
name: security_on_demand_scans_http_header_validation
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/42812
|
||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/276403
|
||||
milestone: '13.6'
|
||||
type: development
|
||||
group: group::dynamic analysis
|
||||
default_enabled: false
|
||||
|
|
@ -82,6 +82,7 @@ function generateEntries() {
|
|||
// sentry: './sentry/index.js', Temporarily commented out to investigate performance: https://gitlab.com/gitlab-org/gitlab/-/issues/251179
|
||||
performance_bar: './performance_bar/index.js',
|
||||
chrome_84_icon_fix: './lib/chrome_84_icon_fix.js',
|
||||
jira_connect_app: './jira_connect/index.js',
|
||||
};
|
||||
|
||||
return Object.assign(manualEntries, autoEntries);
|
||||
|
|
|
|||
|
|
@ -10818,7 +10818,7 @@ enum IssueType {
|
|||
"""
|
||||
Represents an iteration object
|
||||
"""
|
||||
type Iteration implements TimeboxBurnupTimeSeriesInterface {
|
||||
type Iteration implements TimeboxReportInterface {
|
||||
"""
|
||||
Daily scope and completed totals for burnup charts
|
||||
"""
|
||||
|
|
@ -10854,6 +10854,11 @@ type Iteration implements TimeboxBurnupTimeSeriesInterface {
|
|||
"""
|
||||
iid: ID!
|
||||
|
||||
"""
|
||||
Historically accurate report about the timebox
|
||||
"""
|
||||
report: TimeboxReport
|
||||
|
||||
"""
|
||||
Web path of the iteration, scoped to the query parent. Only valid for Project parents. Returns null in other contexts
|
||||
"""
|
||||
|
|
@ -12831,7 +12836,7 @@ type MetricsDashboardAnnotationEdge {
|
|||
"""
|
||||
Represents a milestone
|
||||
"""
|
||||
type Milestone implements TimeboxBurnupTimeSeriesInterface {
|
||||
type Milestone implements TimeboxReportInterface {
|
||||
"""
|
||||
Daily scope and completed totals for burnup charts
|
||||
"""
|
||||
|
|
@ -12867,6 +12872,11 @@ type Milestone implements TimeboxBurnupTimeSeriesInterface {
|
|||
"""
|
||||
projectMilestone: Boolean!
|
||||
|
||||
"""
|
||||
Historically accurate report about the timebox
|
||||
"""
|
||||
report: TimeboxReport
|
||||
|
||||
"""
|
||||
Timestamp of the milestone start date
|
||||
"""
|
||||
|
|
@ -20155,13 +20165,28 @@ Time represented in ISO 8601
|
|||
"""
|
||||
scalar Time
|
||||
|
||||
interface TimeboxBurnupTimeSeriesInterface {
|
||||
"""
|
||||
Represents a historically accurate report about the timebox
|
||||
"""
|
||||
type TimeboxReport {
|
||||
"""
|
||||
Daily scope and completed totals for burnup charts
|
||||
"""
|
||||
burnupTimeSeries: [BurnupChartDailyTotals!]
|
||||
}
|
||||
|
||||
interface TimeboxReportInterface {
|
||||
"""
|
||||
Daily scope and completed totals for burnup charts
|
||||
"""
|
||||
burnupTimeSeries: [BurnupChartDailyTotals!]
|
||||
|
||||
"""
|
||||
Historically accurate report about the timebox
|
||||
"""
|
||||
report: TimeboxReport
|
||||
}
|
||||
|
||||
"""
|
||||
A time-frame defined as a closed inclusive range of two dates
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -29533,6 +29533,20 @@
|
|||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
},
|
||||
{
|
||||
"name": "report",
|
||||
"description": "Historically accurate report about the timebox",
|
||||
"args": [
|
||||
|
||||
],
|
||||
"type": {
|
||||
"kind": "OBJECT",
|
||||
"name": "TimeboxReport",
|
||||
"ofType": null
|
||||
},
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
},
|
||||
{
|
||||
"name": "scopedPath",
|
||||
"description": "Web path of the iteration, scoped to the query parent. Only valid for Project parents. Returns null in other contexts",
|
||||
|
|
@ -29670,7 +29684,7 @@
|
|||
"interfaces": [
|
||||
{
|
||||
"kind": "INTERFACE",
|
||||
"name": "TimeboxBurnupTimeSeriesInterface",
|
||||
"name": "TimeboxReportInterface",
|
||||
"ofType": null
|
||||
}
|
||||
],
|
||||
|
|
@ -35318,6 +35332,20 @@
|
|||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
},
|
||||
{
|
||||
"name": "report",
|
||||
"description": "Historically accurate report about the timebox",
|
||||
"args": [
|
||||
|
||||
],
|
||||
"type": {
|
||||
"kind": "OBJECT",
|
||||
"name": "TimeboxReport",
|
||||
"ofType": null
|
||||
},
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
},
|
||||
{
|
||||
"name": "startDate",
|
||||
"description": "Timestamp of the milestone start date",
|
||||
|
|
@ -35441,7 +35469,7 @@
|
|||
"interfaces": [
|
||||
{
|
||||
"kind": "INTERFACE",
|
||||
"name": "TimeboxBurnupTimeSeriesInterface",
|
||||
"name": "TimeboxReportInterface",
|
||||
"ofType": null
|
||||
}
|
||||
],
|
||||
|
|
@ -58503,9 +58531,44 @@
|
|||
"enumValues": null,
|
||||
"possibleTypes": null
|
||||
},
|
||||
{
|
||||
"kind": "OBJECT",
|
||||
"name": "TimeboxReport",
|
||||
"description": "Represents a historically accurate report about the timebox",
|
||||
"fields": [
|
||||
{
|
||||
"name": "burnupTimeSeries",
|
||||
"description": "Daily scope and completed totals for burnup charts",
|
||||
"args": [
|
||||
|
||||
],
|
||||
"type": {
|
||||
"kind": "LIST",
|
||||
"name": null,
|
||||
"ofType": {
|
||||
"kind": "NON_NULL",
|
||||
"name": null,
|
||||
"ofType": {
|
||||
"kind": "OBJECT",
|
||||
"name": "BurnupChartDailyTotals",
|
||||
"ofType": null
|
||||
}
|
||||
}
|
||||
},
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
}
|
||||
],
|
||||
"inputFields": null,
|
||||
"interfaces": [
|
||||
|
||||
],
|
||||
"enumValues": null,
|
||||
"possibleTypes": null
|
||||
},
|
||||
{
|
||||
"kind": "INTERFACE",
|
||||
"name": "TimeboxBurnupTimeSeriesInterface",
|
||||
"name": "TimeboxReportInterface",
|
||||
"description": null,
|
||||
"fields": [
|
||||
{
|
||||
|
|
@ -58529,6 +58592,20 @@
|
|||
},
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
},
|
||||
{
|
||||
"name": "report",
|
||||
"description": "Historically accurate report about the timebox",
|
||||
"args": [
|
||||
|
||||
],
|
||||
"type": {
|
||||
"kind": "OBJECT",
|
||||
"name": "TimeboxReport",
|
||||
"ofType": null
|
||||
},
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
}
|
||||
],
|
||||
"inputFields": null,
|
||||
|
|
|
|||
|
|
@ -1652,6 +1652,7 @@ Represents an iteration object.
|
|||
| `dueDate` | Time | Timestamp of the iteration due date |
|
||||
| `id` | ID! | ID of the iteration |
|
||||
| `iid` | ID! | Internal ID of the iteration |
|
||||
| `report` | TimeboxReport | Historically accurate report about the timebox |
|
||||
| `scopedPath` | String | Web path of the iteration, scoped to the query parent. Only valid for Project parents. Returns null in other contexts |
|
||||
| `scopedUrl` | String | Web URL of the iteration, scoped to the query parent. Only valid for Project parents. Returns null in other contexts |
|
||||
| `startDate` | Time | Timestamp of the iteration start date |
|
||||
|
|
@ -1964,6 +1965,7 @@ Represents a milestone.
|
|||
| `groupMilestone` | Boolean! | Indicates if milestone is at group level |
|
||||
| `id` | ID! | ID of the milestone |
|
||||
| `projectMilestone` | Boolean! | Indicates if milestone is at project level |
|
||||
| `report` | TimeboxReport | Historically accurate report about the timebox |
|
||||
| `startDate` | Time | Timestamp of the milestone start date |
|
||||
| `state` | MilestoneStateEnum! | State of the milestone |
|
||||
| `stats` | MilestoneStats | Milestone statistics |
|
||||
|
|
@ -2958,6 +2960,14 @@ Represents a requirement test report.
|
|||
| `id` | ID! | ID of the test report |
|
||||
| `state` | TestReportState! | State of the test report |
|
||||
|
||||
### TimeboxReport
|
||||
|
||||
Represents a historically accurate report about the timebox.
|
||||
|
||||
| Field | Type | Description |
|
||||
| ----- | ---- | ----------- |
|
||||
| `burnupTimeSeries` | BurnupChartDailyTotals! => Array | Daily scope and completed totals for burnup charts |
|
||||
|
||||
### Timelog
|
||||
|
||||
| Field | Type | Description |
|
||||
|
|
|
|||
|
|
@ -128,12 +128,6 @@ This helps you avoid having to add the `only:` rule to all of your jobs to make
|
|||
them always run. You can use this format to set up a Review App, helping to
|
||||
save resources.
|
||||
|
||||
### Using SAST, DAST, and other Secure Templates with Pipelines for Merge Requests
|
||||
|
||||
To use [Secure templates](https://gitlab.com/gitlab-org/gitlab/-/tree/master/lib/gitlab/ci/templates/Security)
|
||||
with pipelines for merge requests, you may need to apply a `rules: if: merge_request_event` for the
|
||||
Secure scans to run in the same pipeline as the commit.
|
||||
|
||||
#### Excluding certain branches
|
||||
|
||||
Pipelines for merge requests require special treatment when
|
||||
|
|
|
|||
|
|
@ -138,13 +138,14 @@ Commit messages should follow the guidelines below, for reasons explained by Chr
|
|||
- The merge request should not contain more than 10 commit messages.
|
||||
- The commit subject should contain at least 3 words.
|
||||
|
||||
CAUTION: **Caution:**
|
||||
If the guidelines are not met, the MR may not pass the
|
||||
[Danger checks](https://gitlab.com/gitlab-org/gitlab/blob/master/danger/commit_messages/Dangerfile).
|
||||
**Important notes:**
|
||||
|
||||
TIP: **Tip:**
|
||||
Consider enabling [Squash and merge](../../user/project/merge_requests/squash_and_merge.md#squash-and-merge) if your merge
|
||||
request includes "Applied suggestion to X files" commits, so that Danger can ignore those.
|
||||
- If the guidelines are not met, the MR may not pass the [Danger checks](https://gitlab.com/gitlab-org/gitlab/blob/master/danger/commit_messages/Dangerfile).
|
||||
- Consider enabling [Squash and merge](../../user/project/merge_requests/squash_and_merge.md#squash-and-merge)
|
||||
if your merge request includes "Applied suggestion to X files" commits, so that Danger can ignore those.
|
||||
- The prefixes in the form of `[prefix]` and `prefix:` are allowed (they can be all lowercase, as long
|
||||
as the message itself is capitalized). For instance, `danger: Improve Danger behavior` and
|
||||
`[API] Improve the labels endpoint` are valid commit messages.
|
||||
|
||||
#### Why these standards matter
|
||||
|
||||
|
|
|
|||
|
|
@ -83,3 +83,25 @@ inject scripts into the web app.
|
|||
Inline styles should be avoided in almost all cases, they should only be used
|
||||
when no alternatives can be found. This allows reusability of styles as well as
|
||||
readability.
|
||||
|
||||
### Sanitize HTML output
|
||||
|
||||
If you need to output raw HTML, you should sanitize it.
|
||||
|
||||
If you are using Vue, you can use the[`v-safe-html` directive](https://gitlab-org.gitlab.io/gitlab-ui/?path=/story/directives-safe-html-directive--default) from GitLab UI.
|
||||
|
||||
For other use cases, wrap a preconfigured version of [`dompurify`](https://www.npmjs.com/package/dompurify)
|
||||
that also allows the icons to be rendered:
|
||||
|
||||
```javascript
|
||||
import { sanitize } from '~/lib/dompurify';
|
||||
|
||||
const unsafeHtml = '<some unsafe content ... >';
|
||||
|
||||
// ...
|
||||
|
||||
element.appendChild(sanitize(unsafeHtml));
|
||||
```
|
||||
|
||||
This `sanitize` function takes the same configuration as the
|
||||
original.
|
||||
|
|
|
|||
|
|
@ -329,6 +329,7 @@ References:
|
|||
|
||||
- When updating the content of an HTML element using JavaScript, mark user-controlled values as `textContent` or `nodeValue` instead of `innerHTML`.
|
||||
- Avoid using `v-html` with user-controlled data, use [`v-safe-html`](https://gitlab-org.gitlab.io/gitlab-ui/?path=/story/directives-safe-html-directive--default) instead.
|
||||
- Render unsafe or unsanitized content using [`dompurify`](fe_guide/security.md#sanitize-html-output).
|
||||
- Consider using [`gl-sprintf`](../../ee/development/i18n/externalization.md#interpolation) to interpolate translated strings securely.
|
||||
- Avoid `__()` with translations that contain user-controlled values.
|
||||
- When working with `postMessage`, ensure the `origin` of the message is allowlisted.
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ This is a partial list of the [RSpec metadata](https://relishapp.com/rspec/rspec
|
|||
| `:elasticsearch` | The test requires an Elasticsearch service. It is used by the [instance-level scenario](https://gitlab.com/gitlab-org/gitlab-qa#definitions) [`Test::Integration::Elasticsearch`](https://gitlab.com/gitlab-org/gitlab/-/blob/72b62b51bdf513e2936301cb6c7c91ec27c35b4d/qa/qa/ee/scenario/test/integration/elasticsearch.rb) to include only tests that require Elasticsearch. |
|
||||
| `:gitaly_cluster` | The test will run against a GitLab instance where repositories are stored on redundant Gitaly nodes behind a Praefect node. All nodes are [separate containers](../../../administration/gitaly/praefect.md#requirements-for-configuring-a-gitaly-cluster). Tests that use this tag have a longer setup time since there are three additional containers that need to be started. |
|
||||
| `:jira` | The test requires a Jira Server. [GitLab-QA](https://gitlab.com/gitlab-org/gitlab-qa) will provision the Jira Server in a Docker container when the `Test::Integration::Jira` test scenario is run.
|
||||
| `:kubernetes` | The test includes a GitLab instance that is configured to be run behind an SSH tunnel, allowing a TLS-accessible GitLab. This test will also include provisioning of at least one Kubernetes cluster to test against. *This tag is often be paired with `:orchestrated`.* |
|
||||
| `:kubernetes` | The test includes a GitLab instance that is configured to be run behind an SSH tunnel, allowing a TLS-accessible GitLab. This test will also include provisioning of at least one Kubernetes cluster to test against. _This tag is often be paired with `:orchestrated`._ |
|
||||
| `:only` | The test is only to be run against specific environments or pipelines. See [Environment selection](environment_selection.md) for more information. |
|
||||
| `:orchestrated` | The GitLab instance under test may be [configured by `gitlab-qa`](https://gitlab.com/gitlab-org/gitlab-qa/-/blob/master/docs/what_tests_can_be_run.md#orchestrated-tests) to be different to the default GitLab configuration, or `gitlab-qa` may launch additional services in separate Docker containers, or both. Tests tagged with `:orchestrated` are excluded when testing environments where we can't dynamically modify GitLab's configuration (for example, Staging). |
|
||||
| `:quarantine` | The test has been [quarantined](https://about.gitlab.com/handbook/engineering/quality/guidelines/debugging-qa-test-failures/#quarantining-tests), will run in a separate job that only includes quarantined tests, and is allowed to fail. The test will be skipped in its regular job so that if it fails it will not hold up the pipeline. Note that you can also [quarantine a test only when it runs against specific environment](environment_selection.md#quarantining-a-test-for-a-specific-environment). |
|
||||
|
|
@ -25,3 +25,20 @@ This is a partial list of the [RSpec metadata](https://relishapp.com/rspec/rspec
|
|||
| `:runner` | The test depends on and will set up a GitLab Runner instance, typically to run a pipeline. |
|
||||
| `:skip_live_env` | The test will be excluded when run against live deployed environments such as Staging, Canary, and Production. |
|
||||
| `:testcase` | The link to the test case issue in the [Quality Testcases project](https://gitlab.com/gitlab-org/quality/testcases/). |
|
||||
| `:mattermost` | The test requires a GitLab Mattermost service on the GitLab instance. |
|
||||
| `:ldap_no_server` | The test requires a GitLab instance to be configured to use LDAP. To be used with the `:orchestrated` tag. It does not spin up an LDAP server at orchestration time. Instead, it creates the LDAP server at runtime. |
|
||||
| `:ldap_no_tls` | The test requires a GitLab instance to be configured to use an external LDAP server with TLS not enabled. |
|
||||
| `:ldap_tls` | The test requires a GitLab instance to be configured to use an external LDAP server with TLS enabled. |
|
||||
| `:object_storage` | The test requires a GitLab instance to be configured to use multiple [object storage types](../../../administration/object_storage.md). Uses MinIO as the object storage server. |
|
||||
| `:smtp` | The test requires a GitLab instance to be configured to use an SMTP server. Tests SMTP notification email delivery from GitLab by using MailHog. |
|
||||
| `:group_saml` | The test requires a GitLab instance that has SAML SSO enabled at the group level. Interacts with an external SAML identity provider. Paired with the `:orchestrated` tag. |
|
||||
| `:instance_saml` | The test requires a GitLab instance that has SAML SSO enabled at the instance level. Interacts with an external SAML identity provider. Paired with the `:orchestrated` tag. |
|
||||
| `:skip_signup_disabled` | The test uses UI to sign up a new user and will be skipped in any environment that does not allow new user registration via the UI. |
|
||||
| `:smoke` | The test belongs to the test suite which verifies basic functionality of a GitLab instance.|
|
||||
| `:github` | The test requires a GitHub personal access token. |
|
||||
| `:repository_storage` | The test requires a GitLab instance to be configured to use multiple [repository storage paths](../../../administration/repository_storage_paths.md). Paired with the `:orchestrated` tag. |
|
||||
| `:geo` | The test requires two GitLab Geo instances - a primary and a secondary - to be spun up. |
|
||||
| `:relative_url` | The test requires a GitLab instance to be installed under a [relative URL](../../../install/relative_url.md). |
|
||||
| `:requires_git_protocol_v2` | The test requires that Git protocol version 2 is enabled on the server. It's assumed to be enabled by default but if not the test can be skipped by setting `QA_CAN_TEST_GIT_PROTOCOL_V2` to `false`. |
|
||||
| `:requires_praefect` | The test requires that the GitLab instance uses [Gitaly Cluster](../../../administration/gitaly/praefect.md) (a.k.a. Praefect) as the repository storage . It's assumed to be used by default but if not the test can be skipped by setting `QA_CAN_TEST_PRAEFECT` to `false`. |
|
||||
| `:packages` | The test requires a GitLab instance that has the [Package Registry](../../../administration/packages/#gitlab-package-registry-administration) enabled. |
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
---
|
||||
stage: none
|
||||
group: unassigned
|
||||
stage: Enablement
|
||||
group: Distribution
|
||||
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
|
||||
type: concepts
|
||||
---
|
||||
|
|
@ -57,21 +57,11 @@ one major version. For example, it is safe to:
|
|||
|
||||
- `12.7.5` -> `12.10.5`
|
||||
- `11.3.4` -> `11.11.1`
|
||||
- `10.6.6` -> `10.8.3`
|
||||
- `11.3.4` -> `11.11.8`
|
||||
- `10.6.6` -> `10.8.7`
|
||||
- `9.2.3` -> `9.5.5`
|
||||
- `8.9.4` -> `8.12.3`
|
||||
|
||||
- Upgrade the *patch* version. For example:
|
||||
|
||||
- `12.0.4` -> `12.0.12`
|
||||
- `11.11.1` -> `11.11.8`
|
||||
- `10.6.3` -> `10.6.6`
|
||||
- `11.11.1` -> `11.11.8`
|
||||
- `10.6.3` -> `10.6.6`
|
||||
- `9.5.5` -> `9.5.9`
|
||||
- `8.9.2` -> `8.9.6`
|
||||
|
||||
NOTE: **Note:**
|
||||
Version specific changes in Omnibus GitLab Linux packages can be found in [the Omnibus GitLab documentation](https://docs.gitlab.com/omnibus/update/README.html#version-specific-changes).
|
||||
|
|
@ -82,87 +72,9 @@ Instructions are available for downloading an Omnibus GitLab Linux package local
|
|||
NOTE: **Note:**
|
||||
A step-by-step guide to [upgrading the Omnibus-bundled PostgreSQL is documented separately](https://docs.gitlab.com/omnibus/settings/database.html#upgrade-packaged-postgresql-server).
|
||||
|
||||
### Upgrading major versions
|
||||
## Upgrading major versions
|
||||
|
||||
Upgrading the *major* version requires more attention.
|
||||
Backward-incompatible changes and migrations are reserved for major versions.
|
||||
We cannot guarantee that upgrading between major versions will be seamless.
|
||||
We suggest upgrading to the latest available *minor* version within
|
||||
your major version before proceeding to the next major version.
|
||||
Doing this will address any backward-incompatible changes or deprecations
|
||||
to help ensure a successful upgrade to the next major release.
|
||||
|
||||
It's also important to ensure that any background migrations have been fully completed
|
||||
before upgrading to a new major version. To see the current size of the `background_migration` queue,
|
||||
[Check for background migrations before upgrading](../update/README.md#checking-for-background-migrations-before-upgrading).
|
||||
|
||||
If your GitLab instance has any runners associated with it, it is very
|
||||
important to upgrade GitLab Runner to match the GitLab minor version that was
|
||||
upgraded to. This is to ensure [compatibility with GitLab versions](https://docs.gitlab.com/runner/#compatibility-with-gitlab-versions).
|
||||
|
||||
### Version 12 onward: Extra step for major upgrades
|
||||
|
||||
From version 12 onward, an additional step is required. More significant migrations
|
||||
may occur during major release upgrades.
|
||||
|
||||
NOTE: **Note:**
|
||||
If you are planning to upgrade from `12.0.x` to `12.10.x`, it is necessary to perform an intermediary upgrade to `12.1.x`
|
||||
before upgrading to `12.10.x` to avoid [#215141](https://gitlab.com/gitlab-org/gitlab/-/issues/215141).
|
||||
|
||||
To ensure these are successful:
|
||||
|
||||
1. Increment to the first minor version (`x.0.x`) during the major version jump.
|
||||
1. Proceed with upgrading to a newer release.
|
||||
|
||||
**For example: `11.5.x` -> `11.11.x` -> `12.0.x` -> `12.1.x` -> `12.10.x` -> `13.0.x`**
|
||||
|
||||
### Example upgrade paths
|
||||
|
||||
Please see the table below for some examples:
|
||||
|
||||
| Target version | Your version | Recommended upgrade path | Note |
|
||||
| --------------------- | ------------ | ------------------------ | ---- |
|
||||
| `13.4.3` | `12.9.2` | `12.9.2` -> `12.10.14` -> `13.0.14` -> `13.4.3` | Two intermediate versions are required: the final `12.10` release, plus `13.0`. |
|
||||
| `13.2.10` | `11.5.0` | `11.5.0` -> `11.11.8` -> `12.0.12` -> `12.1.17` -> `12.10.14` -> `13.0.14` -> `13.2.10` | Five intermediate versions are required: the final `11.11`, `12.0`, `12.1` and `12.10` releases, plus `13.0`. |
|
||||
| `12.10.14` | `11.3.4` | `11.3.4` -> `11.11.8` -> `12.0.12` -> `12.1.17` -> `12.10.14` | Three intermediate versions are required: the final `11.11` and `12.0` releases, plus `12.1` |
|
||||
| `12.9.5` | `10.4.5` | `10.4.5` -> `10.8.7` -> `11.11.8` -> `12.0.12` -> `12.1.17` -> `12.9.5` | Four intermediate versions are required: `10.8`, `11.11`, `12.0` and `12.1`, then `12.9.5` |
|
||||
| `12.2.5` | `9.2.6` | `9.2.6` -> `9.5.10` -> `10.8.7` -> `11.11.8` -> `12.0.12` -> `12.1.17` -> `12.2.5` | Five intermediate versions are required: `9.5`, `10.8`, `11.11`, `12.0`, `12.1`, then `12.2`. |
|
||||
| `11.3.4` | `8.13.4` | `8.13.4` -> `8.17.7` -> `9.5.10` -> `10.8.7` -> `11.3.4` | `8.17.7` is the last version in version 8, `9.5.10` is the last version in version 9, `10.8.7` is the last version in version 10. |
|
||||
|
||||
### Upgrades from versions earlier than 8.12
|
||||
|
||||
- `8.11.x` and earlier: you might have to upgrade to `8.12.0` specifically before you can upgrade to `8.17.7`. This was [reported in an issue](https://gitlab.com/gitlab-org/gitlab/-/issues/207259).
|
||||
- [CI changes prior to version 8.0](https://docs.gitlab.com/omnibus/update/README.html#updating-gitlab-ci-from-prior-540-to-version-714-via-omnibus-gitlab)
|
||||
when it was merged into GitLab.
|
||||
|
||||
### Multi-step upgrade paths with GitLab all-in-one Linux package repository
|
||||
|
||||
Linux package managers default to installing the latest available version of a package for installation and upgrades.
|
||||
Upgrading directly to the latest major version can be problematic for older GitLab versions that require a multi-stage upgrade path.
|
||||
|
||||
When following an upgrade path spanning multiple versions, for each upgrade, specify the intended GitLab version number in your package manager's install or upgrade command.
|
||||
|
||||
Examples:
|
||||
|
||||
```shell
|
||||
# apt-get (Ubuntu/Debian)
|
||||
sudo apt-get upgrade gitlab-ee=12.0.12-ee.0
|
||||
# yum (RHEL/CentOS 6 and 7)
|
||||
yum install gitlab-ee-12.0.12-ee.0.el7
|
||||
# dnf (RHEL/CentOS 8)
|
||||
dnf install gitlab-ee-12.0.12-ee.0.el8
|
||||
# zypper (SUSE)
|
||||
zypper install gitlab-ee=12.0.12-ee.0
|
||||
```
|
||||
|
||||
To identify the GitLab version number in your package manager, run the following commands:
|
||||
|
||||
```shell
|
||||
# apt-cache (Ubuntu/Debian)
|
||||
sudo apt-cache madison gitlab-ee
|
||||
# yum (RHEL/CentOS 6 and 7)
|
||||
yum --showduplicates list gitlab-ee
|
||||
```
|
||||
Backward-incompatible changes and migrations are reserved for major versions. See the [upgrade guide](../update/README.md#upgrading-to-a-new-major-version).
|
||||
|
||||
## Patch releases
|
||||
|
||||
|
|
@ -237,19 +149,6 @@ This decision is made on a case-by-case basis.
|
|||
|
||||
## More information
|
||||
|
||||
Check [our release posts](https://about.gitlab.com/releases/categories/releases/).
|
||||
|
||||
Each month, we publish either a major or minor release of GitLab. At the end
|
||||
of those release posts, there are three sections to look for: Deprecations, Removals, and Important notes on upgrading. These will include:
|
||||
|
||||
- Steps you need to perform as part of an upgrade.
|
||||
For example [8.12](https://about.gitlab.com/releases/2016/09/22/gitlab-8-12-released/#upgrade-barometer)
|
||||
required the Elasticsearch index to be recreated. Any older version of GitLab upgrading to 8.12 or higher would require this.
|
||||
- Changes to the versions of software we support such as
|
||||
[ceasing support for IE11 in GitLab 13](https://about.gitlab.com/releases/2020/03/22/gitlab-12-9-released/#ending-support-for-internet-explorer-11).
|
||||
|
||||
You should check all the major and minor versions you're passing over.
|
||||
|
||||
More information about the release procedures can be found in our
|
||||
[release documentation](https://gitlab.com/gitlab-org/release/docs). You may also want to read our
|
||||
[Responsible Disclosure Policy](https://about.gitlab.com/security/disclosure/).
|
||||
|
|
|
|||
|
|
@ -1,34 +1,51 @@
|
|||
---
|
||||
stage: none
|
||||
group: unassigned
|
||||
stage: Enablement
|
||||
group: Distribution
|
||||
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
|
||||
---
|
||||
|
||||
# Updating GitLab
|
||||
# Upgrading GitLab
|
||||
|
||||
Upgrading GitLab is a relatively straightforward process, but the complexity
|
||||
can increase based on the installation method you have used, how old your
|
||||
GitLab version is, if you're upgrading to a major version, and so on.
|
||||
|
||||
Make sure to read the whole page as it contains information related to every upgrade method.
|
||||
|
||||
The [maintenance policy documentation](../policy/maintenance.md)
|
||||
has additional information about upgrading, including:
|
||||
|
||||
- How to interpret GitLab product versioning.
|
||||
- Recommendations on the what release to run.
|
||||
- How we use patch and security patch releases.
|
||||
- When we backport code changes.
|
||||
|
||||
## Upgrade based on installation method
|
||||
|
||||
Depending on the installation method and your GitLab version, there are multiple
|
||||
update guides.
|
||||
official ways to update GitLab:
|
||||
|
||||
There are currently 3 official ways to install GitLab:
|
||||
- [Linux packages (Omnibus GitLab)](#linux-packages-omnibus-gitlab)
|
||||
- [Source installations](#installation-from-source)
|
||||
- [Docker installations](#installation-using-docker)
|
||||
- [Kubernetes (Helm) installations](#installation-using-helm)
|
||||
|
||||
- [Omnibus packages](#omnibus-packages)
|
||||
- [Source installation](#installation-from-source)
|
||||
- [Docker installation](#installation-using-docker)
|
||||
### Linux packages (Omnibus GitLab)
|
||||
|
||||
Based on your installation, choose a section below that fits your needs.
|
||||
The [Omnibus update guide](https://docs.gitlab.com/omnibus/update/)
|
||||
contains the steps needed to update a package installed by GitLab's official
|
||||
repositories.
|
||||
|
||||
## Omnibus Packages
|
||||
There are also instructions when you want to
|
||||
[update to a specific version](https://docs.gitlab.com/omnibus/update/#multi-step-upgrade-using-the-official-repositories).
|
||||
|
||||
- The [Omnibus update guide](https://docs.gitlab.com/omnibus/update/README.html)
|
||||
contains the steps needed to update an Omnibus GitLab package.
|
||||
|
||||
## Installation from source
|
||||
### Installation from source
|
||||
|
||||
- [Upgrading Community Edition and Enterprise Edition from
|
||||
source](upgrading_from_source.md) - The guidelines for upgrading Community
|
||||
Edition and Enterprise Edition from source.
|
||||
- [Patch versions](patch_versions.md) guide includes the steps needed for a
|
||||
patch version, such as 6.2.0 to 6.2.1, and apply to both Community and Enterprise
|
||||
patch version, such as 13.2.0 to 13.2.1, and apply to both Community and Enterprise
|
||||
Editions.
|
||||
|
||||
In the past we used separate documents for the upgrading instructions, but we
|
||||
|
|
@ -38,12 +55,136 @@ can still be found in the Git repository:
|
|||
- [Old upgrading guidelines for Community Edition](https://gitlab.com/gitlab-org/gitlab-foss/tree/11-8-stable/doc/update)
|
||||
- [Old upgrading guidelines for Enterprise Edition](https://gitlab.com/gitlab-org/gitlab/tree/11-8-stable-ee/doc/update)
|
||||
|
||||
## Installation using Docker
|
||||
### Installation using Docker
|
||||
|
||||
GitLab provides official Docker images for both Community and Enterprise
|
||||
editions. They are based on the Omnibus package and instructions on how to
|
||||
update them are in [a separate document](https://docs.gitlab.com/omnibus/docker/README.html).
|
||||
|
||||
### Installation using Helm
|
||||
|
||||
GitLab can be deployed into a Kubernetes cluster using Helm.
|
||||
Instructions on how to update a cloud-native deployment are in
|
||||
[a separate document](https://docs.gitlab.com/charts/installation/upgrade.html).
|
||||
|
||||
Use the [version mapping](https://docs.gitlab.com/charts/installation/version_mappings.html)
|
||||
from the chart version to GitLab version to determine the [upgrade path](#upgrade-paths).
|
||||
|
||||
## Checking for background migrations before upgrading
|
||||
|
||||
Certain major/minor releases may require a set of background migrations to be
|
||||
finished. The number of remaining migrations jobs can be found by running the
|
||||
following command:
|
||||
|
||||
**For Omnibus installations**
|
||||
|
||||
If using GitLab 12.9 and newer, run:
|
||||
|
||||
```shell
|
||||
sudo gitlab-rails runner -e production 'puts Gitlab::BackgroundMigration.remaining'
|
||||
```
|
||||
|
||||
If using GitLab 12.8 and older, run the following using a [Rails console](../administration/operations/rails_console.md#starting-a-rails-console-session):
|
||||
|
||||
```ruby
|
||||
puts Sidekiq::Queue.new("background_migration").size
|
||||
Sidekiq::ScheduledSet.new.select { |r| r.klass == 'BackgroundMigrationWorker' }.size
|
||||
```
|
||||
|
||||
**For installations from source**
|
||||
|
||||
If using GitLab 12.9 and newer, run:
|
||||
|
||||
```shell
|
||||
cd /home/git/gitlab
|
||||
sudo -u git -H bundle exec rails runner -e production 'puts Gitlab::BackgroundMigration.remaining'
|
||||
```
|
||||
|
||||
If using GitLab 12.8 and older, run the following using a [Rails console](../administration/operations/rails_console.md#starting-a-rails-console-session):
|
||||
|
||||
```ruby
|
||||
puts Sidekiq::Queue.new("background_migration").size
|
||||
Sidekiq::ScheduledSet.new.select { |r| r.klass == 'BackgroundMigrationWorker' }.size
|
||||
```
|
||||
|
||||
### What do I do if my background migrations are stuck?
|
||||
|
||||
CAUTION: **Warning:**
|
||||
The following operations can disrupt your GitLab performance.
|
||||
|
||||
It is safe to re-execute these commands, especially if you have 1000+ pending jobs which would likely overflow your runtime memory.
|
||||
|
||||
**For Omnibus installations**
|
||||
|
||||
```shell
|
||||
# Start the rails console
|
||||
sudo gitlab-rails c
|
||||
|
||||
# Execute the following in the rails console
|
||||
scheduled_queue = Sidekiq::ScheduledSet.new
|
||||
pending_job_classes = scheduled_queue.select { |job| job["class"] == "BackgroundMigrationWorker" }.map { |job| job["args"].first }.uniq
|
||||
pending_job_classes.each { |job_class| Gitlab::BackgroundMigration.steal(job_class) }
|
||||
```
|
||||
|
||||
**For installations from source**
|
||||
|
||||
```shell
|
||||
# Start the rails console
|
||||
sudo -u git -H bundle exec rails RAILS_ENV=production
|
||||
|
||||
# Execute the following in the rails console
|
||||
scheduled_queue = Sidekiq::ScheduledSet.new
|
||||
pending_job_classes = scheduled_queue.select { |job| job["class"] == "BackgroundMigrationWorker" }.map { |job| job["args"].first }.uniq
|
||||
pending_job_classes.each { |job_class| Gitlab::BackgroundMigration.steal(job_class) }
|
||||
```
|
||||
|
||||
## Upgrade paths
|
||||
|
||||
Although you can generally upgrade through multiple GitLab versions in one go,
|
||||
sometimes this can cause issues.
|
||||
|
||||
Find where your version sits in the upgrade path below, and upgrade GitLab
|
||||
accordingly, while also consulting the
|
||||
[version-specific upgrade instructions](#version-specific-upgrading-instructions):
|
||||
|
||||
`8.11.x` -> `8.12.0` -> `8.17.7` -> `9.5.10` -> `10.8.7` -> `11.11.8` -> `12.0.12` -> `12.1.17` -> `12.10.14` -> `13.0.14` -> `13.1.11` - > `13.5.3`
|
||||
|
||||
The following table, while not exhaustive, shows some examples of the supported
|
||||
upgrade paths.
|
||||
|
||||
| Target version | Your version | Supported upgrade path | Note |
|
||||
| --------------------- | ------------ | ------------------------ | ---- |
|
||||
| `13.4.3` | `12.9.2` | `12.9.2` -> `12.10.14` -> `13.0.14` -> `13.4.3` | Two intermediate versions are required: the final `12.10` release, plus `13.0`. |
|
||||
| `13.2.10` | `11.5.0` | `11.5.0` -> `11.11.8` -> `12.0.12` -> `12.1.17` -> `12.10.14` -> `13.0.14` -> `13.2.10` | Five intermediate versions are required: the final `11.11`, `12.0`, `12.1` and `12.10` releases, plus `13.0`. |
|
||||
| `12.10.14` | `11.3.4` | `11.3.4` -> `11.11.8` -> `12.0.12` -> `12.1.17` -> `12.10.14` | Three intermediate versions are required: the final `11.11` and `12.0` releases, plus `12.1` |
|
||||
| `12.9.5` | `10.4.5` | `10.4.5` -> `10.8.7` -> `11.11.8` -> `12.0.12` -> `12.1.17` -> `12.9.5` | Four intermediate versions are required: `10.8`, `11.11`, `12.0` and `12.1`, then `12.9.5` |
|
||||
| `12.2.5` | `9.2.6` | `9.2.6` -> `9.5.10` -> `10.8.7` -> `11.11.8` -> `12.0.12` -> `12.1.17` -> `12.2.5` | Five intermediate versions are required: `9.5`, `10.8`, `11.11`, `12.0`, `12.1`, then `12.2`. |
|
||||
| `11.3.4` | `8.13.4` | `8.13.4` -> `8.17.7` -> `9.5.10` -> `10.8.7` -> `11.3.4` | `8.17.7` is the last version in version 8, `9.5.10` is the last version in version 9, `10.8.7` is the last version in version 10. |
|
||||
|
||||
## Upgrading to a new major version
|
||||
|
||||
Upgrading the *major* version requires more attention.
|
||||
Backward-incompatible changes and migrations are reserved for major versions.
|
||||
We cannot guarantee that upgrading between major versions will be seamless.
|
||||
It is suggested to upgrade to the latest available *minor* version within
|
||||
your major version before proceeding to the next major version.
|
||||
Doing this will address any backward-incompatible changes or deprecations
|
||||
to help ensure a successful upgrade to the next major release.
|
||||
Identify a [supported upgrade path](#upgrade-paths).
|
||||
|
||||
More significant migrations may occur during major release upgrades. To ensure these are successful:
|
||||
|
||||
1. Increment to the first minor version (`x.0.x`) during the major version jump.
|
||||
1. Proceed with upgrading to a newer release.
|
||||
|
||||
It's also important to ensure that any background migrations have been fully completed
|
||||
before upgrading to a new major version. To see the current size of the `background_migration` queue,
|
||||
[Check for background migrations before upgrading](#checking-for-background-migrations-before-upgrading).
|
||||
|
||||
If your GitLab instance has any runners associated with it, it is very
|
||||
important to upgrade GitLab Runner to match the GitLab minor version that was
|
||||
upgraded to. This is to ensure [compatibility with GitLab versions](https://docs.gitlab.com/runner/#compatibility-with-gitlab-versions).
|
||||
|
||||
## Upgrading without downtime
|
||||
|
||||
Starting with GitLab 9.1.0 it's possible to upgrade to a newer major, minor, or
|
||||
|
|
@ -93,7 +234,7 @@ To help explain this, let's look at some examples.
|
|||
which is the latest patch release of 9.4. When GitLab 9.5.0 is released this
|
||||
installation can be safely upgraded to 9.5.0 without requiring downtime if the
|
||||
requirements mentioned above are met. You can also skip 9.5.0 and upgrade to
|
||||
9.5.1 once it's released, but you **can not** upgrade straight to 9.6.0; you
|
||||
9.5.1 after it's released, but you **can not** upgrade straight to 9.6.0; you
|
||||
_have_ to first upgrade to a 9.5.x release.
|
||||
|
||||
**Example 2:** You are running a large GitLab installation using version 9.4.2,
|
||||
|
|
@ -115,95 +256,13 @@ meet the other online upgrade requirements mentioned above.
|
|||
|
||||
Steps to [upgrade without downtime](https://docs.gitlab.com/omnibus/update/README.html#zero-downtime-updates).
|
||||
|
||||
## Checking for background migrations before upgrading
|
||||
|
||||
Certain major/minor releases may require a set of background migrations to be
|
||||
finished. The number of remaining migrations jobs can be found by running the
|
||||
following command:
|
||||
|
||||
**For Omnibus installations**
|
||||
|
||||
If using GitLab 12.9 and newer, run:
|
||||
|
||||
```shell
|
||||
sudo gitlab-rails runner -e production 'puts Gitlab::BackgroundMigration.remaining'
|
||||
```
|
||||
|
||||
If using GitLab 12.8 and older, run the following using a [Rails console](../administration/operations/rails_console.md#starting-a-rails-console-session):
|
||||
|
||||
```ruby
|
||||
puts Sidekiq::Queue.new("background_migration").size
|
||||
Sidekiq::ScheduledSet.new.select { |r| r.klass == 'BackgroundMigrationWorker' }.size
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
**For installations from source**
|
||||
|
||||
If using GitLab 12.9 and newer, run:
|
||||
|
||||
```shell
|
||||
cd /home/git/gitlab
|
||||
sudo -u git -H bundle exec rails runner -e production 'puts Gitlab::BackgroundMigration.remaining'
|
||||
```
|
||||
|
||||
If using GitLab 12.8 and older, run the following using a [Rails console](../administration/operations/rails_console.md#starting-a-rails-console-session):
|
||||
|
||||
```ruby
|
||||
puts Sidekiq::Queue.new("background_migration").size
|
||||
Sidekiq::ScheduledSet.new.select { |r| r.klass == 'BackgroundMigrationWorker' }.size
|
||||
```
|
||||
|
||||
### What do I do if my background migrations are stuck?
|
||||
|
||||
CAUTION: **Warning:**
|
||||
The following operations can disrupt your GitLab performance.
|
||||
|
||||
NOTE: **Note:**
|
||||
It is safe to re-execute these commands, especially if you have 1000+ pending jobs which would likely overflow your runtime memory.
|
||||
|
||||
**For Omnibus installations**
|
||||
|
||||
```shell
|
||||
# Start the rails console
|
||||
sudo gitlab-rails c
|
||||
|
||||
# Execute the following in the rails console
|
||||
scheduled_queue = Sidekiq::ScheduledSet.new
|
||||
pending_job_classes = scheduled_queue.select { |job| job["class"] == "BackgroundMigrationWorker" }.map { |job| job["args"].first }.uniq
|
||||
pending_job_classes.each { |job_class| Gitlab::BackgroundMigration.steal(job_class) }
|
||||
```
|
||||
|
||||
**For installations from source**
|
||||
|
||||
```shell
|
||||
# Start the rails console
|
||||
sudo -u git -H bundle exec rails RAILS_ENV=production
|
||||
|
||||
# Execute the following in the rails console
|
||||
scheduled_queue = Sidekiq::ScheduledSet.new
|
||||
pending_job_classes = scheduled_queue.select { |job| job["class"] == "BackgroundMigrationWorker" }.map { |job| job["args"].first }.uniq
|
||||
pending_job_classes.each { |job_class| Gitlab::BackgroundMigration.steal(job_class) }
|
||||
```
|
||||
|
||||
## Upgrading to a new major version
|
||||
|
||||
Major versions are reserved for backwards incompatible changes. We recommend that
|
||||
you first upgrade to the latest available minor version within your major version.
|
||||
Please follow the [Upgrade Recommendations](../policy/maintenance.md#upgrade-recommendations)
|
||||
to identify a supported upgrade path.
|
||||
|
||||
Before upgrading to a new major version, you should ensure that any background
|
||||
migration jobs from previous releases have been completed. To see the current size
|
||||
of the `background_migration` queue, [check for background migrations before upgrading](#checking-for-background-migrations-before-upgrading).
|
||||
|
||||
## Upgrading between editions
|
||||
|
||||
GitLab comes in two flavors: [Community Edition](https://about.gitlab.com/features/#community) which is MIT licensed,
|
||||
and [Enterprise Edition](https://about.gitlab.com/features/#enterprise) which builds on top of the Community Edition and
|
||||
includes extra features mainly aimed at organizations with more than 100 users.
|
||||
|
||||
Below you can find some guides to help you change editions easily.
|
||||
Below you can find some guides to help you change GitLab editions.
|
||||
|
||||
### Community to Enterprise Edition
|
||||
|
||||
|
|
@ -226,7 +285,30 @@ If you need to downgrade your Enterprise Edition installation back to Community
|
|||
Edition, you can follow [this guide](../downgrade_ee_to_ce/README.md) to make the process as smooth as
|
||||
possible.
|
||||
|
||||
## Version specific upgrading instructions
|
||||
## Version-specific upgrading instructions
|
||||
|
||||
Each month, a major or minor release of GitLab is published along with a
|
||||
[release post](https://about.gitlab.com/releases/categories/releases/).
|
||||
You should check all the major and minor versions you're passing over.
|
||||
At the end of those release posts, there are three sections to look for:
|
||||
|
||||
- Deprecations
|
||||
- Removals
|
||||
- Important notes on upgrading
|
||||
|
||||
These will include:
|
||||
|
||||
- Steps you need to perform as part of an upgrade.
|
||||
For example [8.12](https://about.gitlab.com/releases/2016/09/22/gitlab-8-12-released/#upgrade-barometer)
|
||||
required the Elasticsearch index to be recreated. Any older version of GitLab upgrading to 8.12 or higher would require this.
|
||||
- Changes to the versions of software we support such as
|
||||
[ceasing support for IE11 in GitLab 13](https://about.gitlab.com/releases/2020/03/22/gitlab-12-9-released/#ending-support-for-internet-explorer-11).
|
||||
|
||||
Apart from the instructions in this section, you should also check the
|
||||
installation-specific upgrade instructions, based on how you installed GitLab:
|
||||
|
||||
- [Linux packages (Omnibus GitLab)](https://docs.gitlab.com/omnibus/update/README.html#version-specific-changes)
|
||||
- [Helm charts](https://docs.gitlab.com/charts/installation/upgrade.html)
|
||||
|
||||
### 13.6.0
|
||||
|
||||
|
|
@ -293,10 +375,16 @@ automatically upgraded.
|
|||
However, session cookie downgrades are not supported. So after upgrading to 12.2.0,
|
||||
any downgrades would result to all sessions being invalidated and users are logged out.
|
||||
|
||||
### 12.1.0
|
||||
|
||||
If you are planning to upgrade from `12.0.x` to `12.10.x`, it is necessary to
|
||||
perform an intermediary upgrade to `12.1.x` before upgrading to `12.10.x` to
|
||||
avoid issues like [#215141](https://gitlab.com/gitlab-org/gitlab/-/issues/215141).
|
||||
|
||||
### 12.0.0
|
||||
|
||||
In 12.0.0 we made various database related changes. These changes require that
|
||||
users first upgrade to the latest 11.11 patch release. Once upgraded to 11.11.x,
|
||||
users first upgrade to the latest 11.11 patch release. After upgraded to 11.11.x,
|
||||
users can upgrade to 12.0.x. Failure to do so may result in database migrations
|
||||
not being applied, which could lead to application errors.
|
||||
|
||||
|
|
@ -308,11 +396,17 @@ release for 11.11.x. You can upgrade as usual to 12.0.x.
|
|||
|
||||
Example 2: you are currently using a version of GitLab 10.x. To upgrade, first
|
||||
upgrade to the last 10.x release (10.8.7) then the last 11.x release (11.11.8).
|
||||
Once upgraded to 11.11.8 you can safely upgrade to 12.0.x.
|
||||
After upgraded to 11.11.8 you can safely upgrade to 12.0.x.
|
||||
|
||||
See our [documentation on upgrade paths](../policy/maintenance.md#upgrade-recommendations)
|
||||
for more information.
|
||||
|
||||
### Upgrades from versions earlier than 8.12
|
||||
|
||||
- `8.11.x` and earlier: you might have to upgrade to `8.12.0` specifically before you can upgrade to `8.17.7`. This was [reported in an issue](https://gitlab.com/gitlab-org/gitlab/-/issues/207259).
|
||||
- [CI changes prior to version 8.0](https://docs.gitlab.com/omnibus/update/README.html#updating-gitlab-ci-from-prior-540-to-version-714-via-omnibus-gitlab)
|
||||
when it was merged into GitLab.
|
||||
|
||||
## Miscellaneous
|
||||
|
||||
- [MySQL to PostgreSQL](mysql_to_postgresql.md) guides you through migrating
|
||||
|
|
|
|||
|
|
@ -18,6 +18,12 @@ If you choose a size larger than what is currently configured for the web server
|
|||
you will likely get errors. See the [troubleshooting section](#troubleshooting) for more
|
||||
details.
|
||||
|
||||
## Max push size
|
||||
|
||||
You can change the maximum push size for your repository.
|
||||
Navigate to **Admin Area (wrench icon) > Settings > General**, then expand **Account and Limit**.
|
||||
From here, you can increase or decrease by changing the value in `Maximum push size (MB)`.
|
||||
|
||||
## Max import size
|
||||
|
||||
You can change the maximum file size for imports in GitLab.
|
||||
|
|
|
|||
Binary file not shown.
|
Before Width: | Height: | Size: 8.8 KiB |
|
|
@ -21,7 +21,7 @@ For an overview of application security with GitLab, see
|
|||
## Quick start
|
||||
|
||||
Get started quickly with Dependency Scanning, License Scanning, Static Application Security
|
||||
Testing (SAST), and Secret Detection by adding the following to your `.gitlab-ci.yml`:
|
||||
Testing (SAST), and Secret Detection by adding the following to your [`.gitlab-ci.yml`](../../ci/yaml/README.md):
|
||||
|
||||
```yaml
|
||||
include:
|
||||
|
|
@ -70,12 +70,26 @@ GitLab uses the following tools to scan and report known vulnerabilities found i
|
|||
| [Dependency List](dependency_list/index.md) **(ULTIMATE)** | View your project's dependencies and their known vulnerabilities. |
|
||||
| [Dependency Scanning](dependency_scanning/index.md) **(ULTIMATE)** | Analyze your dependencies for known vulnerabilities. |
|
||||
| [Dynamic Application Security Testing (DAST)](dast/index.md) **(ULTIMATE)** | Analyze running web applications for known vulnerabilities. |
|
||||
| [API fuzzing](api_fuzzing/index.md) **(ULTIMATE)** | Find unknown bugs and vulnerabilities in web APIs with fuzzing. |
|
||||
| [API fuzzing](api_fuzzing/index.md) **(ULTIMATE)** | Find unknown bugs and vulnerabilities in web APIs with fuzzing. |
|
||||
| [Secret Detection](secret_detection/index.md) **(ULTIMATE)** | Analyze Git history for leaked secrets. |
|
||||
| [Security Dashboard](security_dashboard/index.md) **(ULTIMATE)** | View vulnerabilities in all your projects and groups. |
|
||||
| [Static Application Security Testing (SAST)](sast/index.md) | Analyze source code for known vulnerabilities. |
|
||||
| [Coverage fuzzing](coverage_fuzzing/index.md) **(ULTIMATE)** | Find unknown bugs and vulnerabilities with coverage-guided fuzzing. |
|
||||
|
||||
### Use security scanning tools with Pipelines for Merge Requests
|
||||
|
||||
The security scanning tools can all be added to pipelines with [templates](https://gitlab.com/gitlab-org/gitlab/-/tree/master/lib/gitlab/ci/templates/Security).
|
||||
See each tool for details on how to use include each template in your CI/CD configuration.
|
||||
|
||||
By default, the application security jobs are configured to run for branch pipelines only.
|
||||
To use them with [pipelines for merge requests](../../ci/merge_request_pipelines/index.md),
|
||||
you may need to override the default `rules:` configuration to add:
|
||||
|
||||
```yaml
|
||||
rules:
|
||||
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
|
||||
```
|
||||
|
||||
## Security Scanning with Auto DevOps
|
||||
|
||||
When [Auto DevOps](../../topics/autodevops/) is enabled, all GitLab Security scanning tools will be configured using default settings.
|
||||
|
|
@ -144,21 +158,21 @@ To view details of DAST vulnerabilities:
|
|||
|
||||
1. Click on the vulnerability's description. The following details are provided:
|
||||
|
||||
| Field | Description |
|
||||
|:-----------------|:------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| Description | Description of the vulnerability. |
|
||||
| Project | Namespace and project in which the vulnerability was detected. |
|
||||
| Method | HTTP method used to detect the vulnerability. |
|
||||
| URL | URL at which the vulnerability was detected. |
|
||||
| Request Headers | Headers of the request. |
|
||||
| Response Status | Response status received from the application. |
|
||||
| Response Headers | Headers of the response received from the application. |
|
||||
| Field | Description |
|
||||
|:-----------------|:------------------------------------------------------------------ |
|
||||
| Description | Description of the vulnerability. |
|
||||
| Project | Namespace and project in which the vulnerability was detected. |
|
||||
| Method | HTTP method used to detect the vulnerability. |
|
||||
| URL | URL at which the vulnerability was detected. |
|
||||
| Request Headers | Headers of the request. |
|
||||
| Response Status | Response status received from the application. |
|
||||
| Response Headers | Headers of the response received from the application. |
|
||||
| Evidence | Evidence of the data found that verified the vulnerability. Often a snippet of the request or response, this can be used to help verify that the finding is a vulnerability. |
|
||||
| Identifiers | Identifiers of the vulnerability. |
|
||||
| Severity | Severity of the vulnerability. |
|
||||
| Scanner Type | Type of vulnerability report. |
|
||||
| Links | Links to further details of the detected vulnerability. |
|
||||
| Solution | Details of a recommended solution to the vulnerability (optional). |
|
||||
| Identifiers | Identifiers of the vulnerability. |
|
||||
| Severity | Severity of the vulnerability. |
|
||||
| Scanner Type | Type of vulnerability report. |
|
||||
| Links | Links to further details of the detected vulnerability. |
|
||||
| Solution | Details of a recommended solution to the vulnerability (optional). |
|
||||
|
||||
#### Hide sensitive information in headers
|
||||
|
||||
|
|
@ -238,14 +252,11 @@ Selecting the button creates a merge request with the solution.
|
|||
|
||||
#### Manually applying the suggested patch
|
||||
|
||||
1. To manually apply the patch that was generated by GitLab for a vulnerability, select the dropdown arrow on the **Resolve
|
||||
with merge request** button, then select **Download patch to resolve**:
|
||||
To manually apply the patch that GitLab generated for a vulnerability:
|
||||
|
||||

|
||||
1. Select the **Resolve with merge request** dropdown, then select **Download patch to resolve**:
|
||||
|
||||
1. The button's text changes to **Download patch to resolve**. Click on it to download the patch:
|
||||
|
||||

|
||||

|
||||
|
||||
1. Ensure your local project has the same commit checked out that was used to generate the patch.
|
||||
1. Run `git apply remediation.patch`.
|
||||
|
|
|
|||
Binary file not shown.
|
After Width: | Height: | Size: 92 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 60 KiB |
|
|
@ -117,6 +117,28 @@ the dropdown) **Approved-By** and select the user.
|
|||
|
||||

|
||||
|
||||
### Filtering merge requests by environment or deployment date **(CORE)**
|
||||
|
||||
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/44041) in GitLab 13.6.
|
||||
|
||||
To filter merge requests by deployment data, such as the environment or a date,
|
||||
you can type (or select from the dropdown) the following:
|
||||
|
||||
- Environment
|
||||
- Deployed-before
|
||||
- Deployed-after
|
||||
|
||||
When filtering by an environment, a dropdown presents all environments that
|
||||
you can choose from:
|
||||
|
||||

|
||||
|
||||
When filtering by a deploy date, you must enter the date manually. Deploy dates
|
||||
use the format `YYYY-MM-DD`, and must be quoted if you wish to specify
|
||||
both a date and time (`"YYYY-MM-DD HH:MM"`):
|
||||
|
||||

|
||||
|
||||
## Filters autocomplete
|
||||
|
||||
GitLab provides many filters across many pages (issues, merge requests, epics,
|
||||
|
|
|
|||
|
|
@ -190,7 +190,7 @@ module Gitlab
|
|||
%r{\A(ee/)?vendor/} => :backend,
|
||||
%r{\A(Gemfile|Gemfile.lock|Rakefile)\z} => :backend,
|
||||
%r{\A[A-Z_]+_VERSION\z} => :backend,
|
||||
%r{\A\.rubocop(_todo)?\.yml\z} => :backend,
|
||||
%r{\A\.rubocop((_manual)?_todo)?\.yml\z} => :backend,
|
||||
%r{\Afile_hooks/} => :backend,
|
||||
|
||||
%r{\A(ee/)?qa/} => :qa,
|
||||
|
|
|
|||
|
|
@ -8319,6 +8319,9 @@ msgstr ""
|
|||
msgid "DastProfiles|Authentication URL"
|
||||
msgstr ""
|
||||
|
||||
msgid "DastProfiles|Copy HTTP header to clipboard"
|
||||
msgstr ""
|
||||
|
||||
msgid "DastProfiles|Could not create site validation token. Please refresh the page, or try again later."
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -8385,6 +8388,9 @@ msgstr ""
|
|||
msgid "DastProfiles|Error Details"
|
||||
msgstr ""
|
||||
|
||||
msgid "DastProfiles|Header validation"
|
||||
msgstr ""
|
||||
|
||||
msgid "DastProfiles|Hide debug messages"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -8469,9 +8475,15 @@ msgstr ""
|
|||
msgid "DastProfiles|Step 1 - Choose site validation method"
|
||||
msgstr ""
|
||||
|
||||
msgid "DastProfiles|Step 2 - Add following HTTP header to your site"
|
||||
msgstr ""
|
||||
|
||||
msgid "DastProfiles|Step 2 - Add following text to the target site"
|
||||
msgstr ""
|
||||
|
||||
msgid "DastProfiles|Step 3 - Confirm header location and validate"
|
||||
msgstr ""
|
||||
|
||||
msgid "DastProfiles|Step 3 - Confirm text file location and validate"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -8508,7 +8520,7 @@ msgstr ""
|
|||
msgid "DastProfiles|Validating..."
|
||||
msgstr ""
|
||||
|
||||
msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the choosen method."
|
||||
msgid "DastProfiles|Validation failed, please make sure that you follow the steps above with the chosen method."
|
||||
msgstr ""
|
||||
|
||||
msgid "DastProfiles|Validation failed. Please try again."
|
||||
|
|
@ -14507,7 +14519,7 @@ msgstr ""
|
|||
msgid "Integrations|Issues created in Jira are shown here once you have created the issues in project setup in Jira."
|
||||
msgstr ""
|
||||
|
||||
msgid "Integrations|Projects using custom settings will not be impacted unless the project owner chooses to use instance-level defaults."
|
||||
msgid "Integrations|Projects using custom settings will not be impacted unless the project owner chooses to use parent level defaults."
|
||||
msgstr ""
|
||||
|
||||
msgid "Integrations|Return to GitLab for Jira"
|
||||
|
|
@ -14732,6 +14744,9 @@ msgstr ""
|
|||
msgid "InviteMembersModal|Choose a role permission"
|
||||
msgstr ""
|
||||
|
||||
msgid "InviteMembersModal|Close invite team members"
|
||||
msgstr ""
|
||||
|
||||
msgid "InviteMembersModal|GitLab member or Email address"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -14741,13 +14756,13 @@ msgstr ""
|
|||
msgid "InviteMembersModal|Invite team members"
|
||||
msgstr ""
|
||||
|
||||
msgid "InviteMembersModal|Members were successfully added"
|
||||
msgstr ""
|
||||
|
||||
msgid "InviteMembersModal|Search for members to invite"
|
||||
msgstr ""
|
||||
|
||||
msgid "InviteMembersModal|User not invited. Feature coming soon!"
|
||||
msgstr ""
|
||||
|
||||
msgid "InviteMembersModal|Users were succesfully added"
|
||||
msgid "InviteMembersModal|Some of the members could not be added"
|
||||
msgstr ""
|
||||
|
||||
msgid "InviteMembersModal|You're inviting members to the %{group_name} group"
|
||||
|
|
|
|||
|
|
@ -2,11 +2,8 @@
|
|||
|
||||
module QA
|
||||
RSpec.describe 'Verify' do
|
||||
describe 'Run pipeline', :requires_admin, :skip_live_env do
|
||||
# [TODO]: Developer to remove :requires_admin and :skip_live_env once FF is removed in https://gitlab.com/gitlab-org/gitlab/-/issues/229632
|
||||
|
||||
describe 'Run pipeline', only: { subdomain: :staging } do
|
||||
context 'with web only rule' do
|
||||
let(:feature_flag) { :new_pipeline_form }
|
||||
let(:job_name) { 'test_job' }
|
||||
let(:project) do
|
||||
Resource::Project.fabricate_via_api! do |project|
|
||||
|
|
@ -20,33 +17,29 @@ module QA
|
|||
commit.commit_message = 'Add .gitlab-ci.yml'
|
||||
commit.add_files(
|
||||
[
|
||||
{
|
||||
file_path: '.gitlab-ci.yml',
|
||||
content: <<~YAML
|
||||
#{job_name}:
|
||||
tags:
|
||||
- #{project.name}
|
||||
script: echo 'OK'
|
||||
only:
|
||||
- web
|
||||
YAML
|
||||
}
|
||||
{
|
||||
file_path: '.gitlab-ci.yml',
|
||||
content: <<~YAML
|
||||
#{job_name}:
|
||||
tags:
|
||||
- #{project.name}
|
||||
script: echo 'OK'
|
||||
only:
|
||||
- web
|
||||
|
||||
YAML
|
||||
}
|
||||
]
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
before do
|
||||
Runtime::Feature.enable(feature_flag) # [TODO]: Developer to remove when feature flag is removed
|
||||
Flow::Login.sign_in
|
||||
project.visit!
|
||||
Page::Project::Menu.perform(&:click_ci_cd_pipelines)
|
||||
end
|
||||
|
||||
after do
|
||||
Runtime::Feature.disable(feature_flag) # [TODO]: Developer to remove when feature flag is removed
|
||||
end
|
||||
|
||||
it 'can trigger pipeline', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/946' do
|
||||
Page::Project::Pipeline::Index.perform do |index|
|
||||
expect(index).not_to have_pipeline # should not auto trigger pipeline
|
||||
|
|
|
|||
|
|
@ -1,168 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require_relative '../../code_reuse_helpers'
|
||||
|
||||
module RuboCop
|
||||
module Cop
|
||||
module CodeReuse
|
||||
# Cop that denies the use of ActiveRecord methods outside of models.
|
||||
class ActiveRecord < RuboCop::Cop::Cop
|
||||
include CodeReuseHelpers
|
||||
|
||||
MSG = 'This method can only be used inside an ActiveRecord model: ' \
|
||||
'https://gitlab.com/gitlab-org/gitlab-foss/issues/49653'
|
||||
|
||||
# Various methods from ActiveRecord::Querying that are denied. We
|
||||
# exclude some generic ones such as `any?` and `first`, as these may
|
||||
# lead to too many false positives, since `Array` also supports these
|
||||
# methods.
|
||||
#
|
||||
# The keys of this Hash are the denied method names. The values are
|
||||
# booleans that indicate if the method should only be denied if any
|
||||
# arguments are provided.
|
||||
NOT_ALLOWED = {
|
||||
average: true,
|
||||
calculate: true,
|
||||
count_by_sql: true,
|
||||
create_with: true,
|
||||
distinct: false,
|
||||
eager_load: true,
|
||||
exists?: true,
|
||||
find_by: true,
|
||||
find_by!: true,
|
||||
find_by_sql: true,
|
||||
find_each: true,
|
||||
find_in_batches: true,
|
||||
find_or_create_by: true,
|
||||
find_or_create_by!: true,
|
||||
find_or_initialize_by: true,
|
||||
first!: false,
|
||||
first_or_create: true,
|
||||
first_or_create!: true,
|
||||
first_or_initialize: true,
|
||||
from: true,
|
||||
group: true,
|
||||
having: true,
|
||||
ids: false,
|
||||
includes: true,
|
||||
joins: true,
|
||||
limit: true,
|
||||
lock: false,
|
||||
many?: false,
|
||||
offset: true,
|
||||
order: true,
|
||||
pluck: true,
|
||||
preload: true,
|
||||
readonly: false,
|
||||
references: true,
|
||||
reorder: true,
|
||||
rewhere: true,
|
||||
take: false,
|
||||
take!: false,
|
||||
unscope: false,
|
||||
where: false,
|
||||
with: true
|
||||
}.freeze
|
||||
|
||||
# Directories that allow the use of the denied methods. These
|
||||
# directories are checked relative to both . and ee/
|
||||
ALLOWED_DIRECTORIES = %w[
|
||||
app/models
|
||||
config
|
||||
danger
|
||||
db
|
||||
lib/backup
|
||||
lib/banzai
|
||||
lib/gitlab/background_migration
|
||||
lib/gitlab/cycle_analytics
|
||||
lib/gitlab/database
|
||||
lib/gitlab/import_export
|
||||
lib/gitlab/project_authorizations
|
||||
lib/gitlab/sql
|
||||
lib/system_check
|
||||
lib/tasks
|
||||
qa
|
||||
rubocop
|
||||
spec
|
||||
].freeze
|
||||
|
||||
def on_send(node)
|
||||
return if in_allowed_directory?(node)
|
||||
|
||||
receiver = node.children[0]
|
||||
send_name = node.children[1]
|
||||
first_arg = node.children[2]
|
||||
|
||||
if receiver && NOT_ALLOWED.key?(send_name)
|
||||
# If the rule requires an argument to be given, but none are
|
||||
# provided, we won't register an offense. This prevents us from
|
||||
# adding offenses for `project.group`, while still covering
|
||||
# `Project.group(:name)`.
|
||||
return if NOT_ALLOWED[send_name] && !first_arg
|
||||
|
||||
add_offense(node, location: :selector)
|
||||
end
|
||||
end
|
||||
|
||||
# Returns true if the node resides in one of the allowed
|
||||
# directories.
|
||||
def in_allowed_directory?(node)
|
||||
path = file_path_for_node(node)
|
||||
|
||||
ALLOWED_DIRECTORIES.any? do |directory|
|
||||
path.start_with?(
|
||||
File.join(rails_root, directory),
|
||||
File.join(rails_root, 'ee', directory)
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
# We can not auto correct code like this, as it requires manual
|
||||
# refactoring. Instead, we'll just allow the surrounding scope.
|
||||
#
|
||||
# Despite this method's presence, you should not use it. This method
|
||||
# exists to make it possible to allow large chunks of offenses we
|
||||
# can't fix in the short term. If you are writing new code, follow the
|
||||
# code reuse guidelines, instead of allowing any new offenses.
|
||||
def autocorrect(node)
|
||||
scope = surrounding_scope_of(node)
|
||||
indent = indentation_of(scope)
|
||||
|
||||
lambda do |corrector|
|
||||
# This prevents us from inserting the same enable/disable comment
|
||||
# for a method or block that has multiple offenses.
|
||||
next if allowed_scopes.include?(scope)
|
||||
|
||||
corrector.insert_before(
|
||||
scope.source_range,
|
||||
"# rubocop: disable #{cop_name}\n#{indent}"
|
||||
)
|
||||
|
||||
corrector.insert_after(
|
||||
scope.source_range,
|
||||
"\n#{indent}# rubocop: enable #{cop_name}"
|
||||
)
|
||||
|
||||
allowed_scopes << scope
|
||||
end
|
||||
end
|
||||
|
||||
def indentation_of(node)
|
||||
' ' * node.loc.expression.source_line[/\A */].length
|
||||
end
|
||||
|
||||
def surrounding_scope_of(node)
|
||||
%i[def defs block begin].each do |type|
|
||||
if (found = node.each_ancestor(type).first)
|
||||
return found
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def allowed_scopes
|
||||
@allowed_scopes ||= Set.new
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -5,7 +5,7 @@ module RuboCop
|
|||
def in_qa_file?(node)
|
||||
path = node.location.expression.source_buffer.name
|
||||
|
||||
path.start_with?(File.join(RuboCop::PathUtil.pwd, 'qa'))
|
||||
path.start_with?(File.join(Dir.pwd, 'qa'))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -0,0 +1,41 @@
|
|||
# Denies the use of ActiveRecord methods outside of configured
|
||||
# excluded directories
|
||||
# Directories that allow the use of the denied methods.
|
||||
# To start we provide a default configuration that matches
|
||||
# a standard Rails app and enable.
|
||||
# The default configuration can be overridden by
|
||||
# providing your own Exclusion list as follows:
|
||||
# CodeReuse/ActiveRecord:
|
||||
# Enabled: true
|
||||
# Exclude:
|
||||
# - app/models/**/*.rb
|
||||
# - config/**/*.rb
|
||||
# - db/**/*.rb
|
||||
# - lib/tasks/**/*.rb
|
||||
# - spec/**/*.rb
|
||||
# - lib/gitlab/**/*.rb
|
||||
CodeReuse/ActiveRecord:
|
||||
Exclude:
|
||||
- app/models/**/*.rb
|
||||
- config/**/*.rb
|
||||
- db/**/*.rb
|
||||
- lib/tasks/**/*.rake
|
||||
- spec/**/*.rb
|
||||
- danger/**/*.rb
|
||||
- lib/backup/**/*.rb
|
||||
- lib/banzai/**/*.rb
|
||||
- lib/gitlab/background_migration/**/*.rb
|
||||
- lib/gitlab/cycle_analytics/**/*.rb
|
||||
- lib/gitlab/database/**/*.rb
|
||||
- lib/gitlab/database_importers/common_metrics/importer.rb
|
||||
- lib/gitlab/import_export/**/*.rb
|
||||
- lib/gitlab/project_authorizations.rb
|
||||
- lib/gitlab/sql/**/*.rb
|
||||
- lib/system_check/**/*.rb
|
||||
- qa/**/*.rb
|
||||
- rubocop/**/*.rb
|
||||
- ee/app/models/**/*.rb
|
||||
- ee/spec/**/*.rb
|
||||
- ee/db/fixtures/**/*.rb
|
||||
- ee/lib/tasks/**/*.rake
|
||||
- ee/lib/ee/gitlab/background_migration/**/*.rb
|
||||
|
|
@ -5,11 +5,13 @@ require 'spec_helper'
|
|||
RSpec.describe 'User page' do
|
||||
include ExternalAuthorizationServiceHelpers
|
||||
|
||||
let(:user) { create(:user, bio: '**Lorem** _ipsum_ dolor sit [amet](https://example.com)') }
|
||||
let_it_be(:user) { create(:user, bio: '**Lorem** _ipsum_ dolor sit [amet](https://example.com)') }
|
||||
|
||||
subject { visit(user_path(user)) }
|
||||
|
||||
context 'with public profile' do
|
||||
it 'shows all the tabs' do
|
||||
visit(user_path(user))
|
||||
subject
|
||||
|
||||
page.within '.nav-links' do
|
||||
expect(page).to have_link('Overview')
|
||||
|
|
@ -22,14 +24,12 @@ RSpec.describe 'User page' do
|
|||
end
|
||||
|
||||
it 'does not show private profile message' do
|
||||
visit(user_path(user))
|
||||
subject
|
||||
|
||||
expect(page).not_to have_content("This user has a private profile")
|
||||
end
|
||||
|
||||
context 'work information' do
|
||||
subject { visit(user_path(user)) }
|
||||
|
||||
it 'shows job title and organization details' do
|
||||
user.update(organization: 'GitLab - work info test', job_title: 'Frontend Engineer')
|
||||
|
||||
|
|
@ -57,24 +57,24 @@ RSpec.describe 'User page' do
|
|||
end
|
||||
|
||||
context 'with private profile' do
|
||||
let(:user) { create(:user, private_profile: true) }
|
||||
let_it_be(:user) { create(:user, private_profile: true) }
|
||||
|
||||
it 'shows no tab' do
|
||||
visit(user_path(user))
|
||||
subject
|
||||
|
||||
expect(page).to have_css("div.profile-header")
|
||||
expect(page).not_to have_css("ul.nav-links")
|
||||
end
|
||||
|
||||
it 'shows private profile message' do
|
||||
visit(user_path(user))
|
||||
subject
|
||||
|
||||
expect(page).to have_content("This user has a private profile")
|
||||
end
|
||||
|
||||
it 'shows own tabs' do
|
||||
sign_in(user)
|
||||
visit(user_path(user))
|
||||
subject
|
||||
|
||||
page.within '.nav-links' do
|
||||
expect(page).to have_link('Overview')
|
||||
|
|
@ -88,36 +88,36 @@ RSpec.describe 'User page' do
|
|||
end
|
||||
|
||||
context 'with blocked profile' do
|
||||
let(:user) { create(:user, state: :blocked) }
|
||||
let_it_be(:user) { create(:user, state: :blocked) }
|
||||
|
||||
it 'shows no tab' do
|
||||
visit(user_path(user))
|
||||
subject
|
||||
|
||||
expect(page).to have_css("div.profile-header")
|
||||
expect(page).not_to have_css("ul.nav-links")
|
||||
end
|
||||
|
||||
it 'shows blocked message' do
|
||||
visit(user_path(user))
|
||||
subject
|
||||
|
||||
expect(page).to have_content("This user is blocked")
|
||||
end
|
||||
|
||||
it 'shows user name as blocked' do
|
||||
visit(user_path(user))
|
||||
subject
|
||||
|
||||
expect(page).to have_css(".cover-title", text: 'Blocked user')
|
||||
end
|
||||
|
||||
it 'shows no additional fields' do
|
||||
visit(user_path(user))
|
||||
subject
|
||||
|
||||
expect(page).not_to have_css(".profile-user-bio")
|
||||
expect(page).not_to have_css(".profile-link-holder")
|
||||
end
|
||||
|
||||
it 'shows username' do
|
||||
visit(user_path(user))
|
||||
subject
|
||||
|
||||
expect(page).to have_content("@#{user.username}")
|
||||
end
|
||||
|
|
@ -126,7 +126,7 @@ RSpec.describe 'User page' do
|
|||
it 'shows the status if there was one' do
|
||||
create(:user_status, user: user, message: "Working hard!")
|
||||
|
||||
visit(user_path(user))
|
||||
subject
|
||||
|
||||
expect(page).to have_content("Working hard!")
|
||||
end
|
||||
|
|
@ -135,7 +135,7 @@ RSpec.describe 'User page' do
|
|||
it 'shows the sign in link' do
|
||||
stub_application_setting(signup_enabled: false)
|
||||
|
||||
visit(user_path(user))
|
||||
subject
|
||||
|
||||
page.within '.navbar-nav' do
|
||||
expect(page).to have_link('Sign in')
|
||||
|
|
@ -147,7 +147,7 @@ RSpec.describe 'User page' do
|
|||
it 'shows the sign in and register link' do
|
||||
stub_application_setting(signup_enabled: true)
|
||||
|
||||
visit(user_path(user))
|
||||
subject
|
||||
|
||||
page.within '.navbar-nav' do
|
||||
expect(page).to have_link('Sign in / Register')
|
||||
|
|
@ -157,7 +157,7 @@ RSpec.describe 'User page' do
|
|||
|
||||
context 'most recent activity' do
|
||||
it 'shows the most recent activity' do
|
||||
visit(user_path(user))
|
||||
subject
|
||||
|
||||
expect(page).to have_content('Most Recent Activity')
|
||||
end
|
||||
|
|
@ -168,7 +168,7 @@ RSpec.describe 'User page' do
|
|||
end
|
||||
|
||||
it 'hides the most recent activity' do
|
||||
visit(user_path(user))
|
||||
subject
|
||||
|
||||
expect(page).not_to have_content('Most Recent Activity')
|
||||
end
|
||||
|
|
@ -177,14 +177,14 @@ RSpec.describe 'User page' do
|
|||
|
||||
context 'page description' do
|
||||
before do
|
||||
visit(user_path(user))
|
||||
subject
|
||||
end
|
||||
|
||||
it_behaves_like 'page meta description', 'Lorem ipsum dolor sit amet'
|
||||
end
|
||||
|
||||
context 'with a bot user' do
|
||||
let(:user) { create(:user, user_type: :security_bot) }
|
||||
let_it_be(:user) { create(:user, user_type: :security_bot) }
|
||||
|
||||
describe 'feature flag enabled' do
|
||||
before do
|
||||
|
|
@ -192,7 +192,7 @@ RSpec.describe 'User page' do
|
|||
end
|
||||
|
||||
it 'only shows Overview and Activity tabs' do
|
||||
visit(user_path(user))
|
||||
subject
|
||||
|
||||
page.within '.nav-links' do
|
||||
expect(page).to have_link('Overview')
|
||||
|
|
@ -211,7 +211,7 @@ RSpec.describe 'User page' do
|
|||
end
|
||||
|
||||
it 'only shows Overview and Activity tabs' do
|
||||
visit(user_path(user))
|
||||
subject
|
||||
|
||||
page.within '.nav-links' do
|
||||
expect(page).to have_link('Overview')
|
||||
|
|
@ -224,4 +224,24 @@ RSpec.describe 'User page' do
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'structured markup' do
|
||||
let_it_be(:user) { create(:user, website_url: 'https://gitlab.com', organization: 'GitLab', job_title: 'Frontend Engineer', email: 'public@example.com', public_email: 'public@example.com', location: 'Country', created_at: Time.now, updated_at: Time.now) }
|
||||
|
||||
it 'shows Person structured markup' do
|
||||
subject
|
||||
|
||||
aggregate_failures do
|
||||
expect(page).to have_selector('[itemscope][itemtype="http://schema.org/Person"]')
|
||||
expect(page).to have_selector('img[itemprop="image"]')
|
||||
expect(page).to have_selector('[itemprop="name"]')
|
||||
expect(page).to have_selector('[itemprop="address"][itemscope][itemtype="https://schema.org/PostalAddress"]')
|
||||
expect(page).to have_selector('[itemprop="addressLocality"]')
|
||||
expect(page).to have_selector('[itemprop="url"]')
|
||||
expect(page).to have_selector('[itemprop="email"]')
|
||||
expect(page).to have_selector('span[itemprop="jobTitle"]')
|
||||
expect(page).to have_selector('span[itemprop="worksFor"]')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -24,10 +24,10 @@ exports[`AlertsSettingsFormOld with default values renders the initial template
|
|||
|
||||
</span>
|
||||
</gl-form-group-stub>
|
||||
<gl-form-group-stub label=\\"Authorization key\\" label-for=\\"authorization-key\\">
|
||||
<gl-form-group-stub label-for=\\"authorization-key\\">
|
||||
<gl-form-input-group-stub value=\\"\\" predefinedoptions=\\"[object Object]\\" id=\\"authorization-key\\" readonly=\\"\\" class=\\"gl-mb-2\\"></gl-form-input-group-stub>
|
||||
<gl-button-stub category=\\"primary\\" variant=\\"default\\" size=\\"medium\\" icon=\\"\\" buttontextclasses=\\"\\" disabled=\\"true\\" class=\\"gl-mt-3\\" role=\\"button\\" tabindex=\\"0\\">Reset key</gl-button-stub>
|
||||
<gl-modal-stub modalid=\\"authKeyModal\\" titletag=\\"h4\\" modalclass=\\"\\" size=\\"md\\" title=\\"Reset key\\" ok-title=\\"Reset key\\" ok-variant=\\"danger\\">
|
||||
<gl-modal-stub modalid=\\"tokenModal\\" titletag=\\"h4\\" modalclass=\\"\\" size=\\"md\\" title=\\"Reset key\\" ok-title=\\"Reset key\\" ok-variant=\\"danger\\">
|
||||
Resetting the authorization key for this project will require updating the authorization key in every alert source it is enabled in.
|
||||
</gl-modal-stub>
|
||||
</gl-form-group-stub>
|
||||
|
|
|
|||
|
|
@ -70,16 +70,10 @@ describe('AlertsSettingsFormNew', () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('when form is invalid', () => {
|
||||
// TODO, implement specs for when form is invalid
|
||||
});
|
||||
|
||||
describe('when form is valid', () => {
|
||||
beforeEach(() => {
|
||||
describe('submitting integration form', () => {
|
||||
it('allows for create-new-integration with the correct form values for HTTP', async () => {
|
||||
createComponent({});
|
||||
});
|
||||
|
||||
it('allows for on-create-new-integration with the correct form values for HTTP', async () => {
|
||||
const options = findSelect().findAll('option');
|
||||
await options.at(1).setSelected();
|
||||
|
||||
|
|
@ -97,13 +91,15 @@ describe('AlertsSettingsFormNew', () => {
|
|||
|
||||
await wrapper.vm.$nextTick();
|
||||
|
||||
expect(wrapper.emitted('on-create-new-integration')).toBeTruthy();
|
||||
expect(wrapper.emitted('on-create-new-integration')[0]).toEqual([
|
||||
expect(wrapper.emitted('create-new-integration')).toBeTruthy();
|
||||
expect(wrapper.emitted('create-new-integration')[0]).toEqual([
|
||||
{ type: typeSet.http, variables: { name: 'Test integration', active: true } },
|
||||
]);
|
||||
});
|
||||
|
||||
it('allows for on-create-new-integration with the correct form values for PROMETHEUS', async () => {
|
||||
it('allows for create-new-integration with the correct form values for PROMETHEUS', async () => {
|
||||
createComponent({});
|
||||
|
||||
const options = findSelect().findAll('option');
|
||||
await options.at(2).setSelected();
|
||||
|
||||
|
|
@ -124,8 +120,73 @@ describe('AlertsSettingsFormNew', () => {
|
|||
|
||||
await wrapper.vm.$nextTick();
|
||||
|
||||
expect(wrapper.emitted('on-create-new-integration')).toBeTruthy();
|
||||
expect(wrapper.emitted('on-create-new-integration')[0]).toEqual([
|
||||
expect(wrapper.emitted('create-new-integration')).toBeTruthy();
|
||||
expect(wrapper.emitted('create-new-integration')[0]).toEqual([
|
||||
{ type: typeSet.prometheus, variables: { apiUrl: 'https://test.com', active: true } },
|
||||
]);
|
||||
});
|
||||
|
||||
it('allows for update-integration with the correct form values for HTTP', async () => {
|
||||
createComponent({
|
||||
props: {
|
||||
currentIntegration: { id: '1' },
|
||||
loading: false,
|
||||
},
|
||||
});
|
||||
|
||||
const options = findSelect().findAll('option');
|
||||
await options.at(1).setSelected();
|
||||
|
||||
await findFormFields()
|
||||
.at(0)
|
||||
.setValue('Test integration');
|
||||
await findFormToggle().trigger('click');
|
||||
|
||||
await wrapper.vm.$nextTick();
|
||||
|
||||
expect(findSubmitButton().exists()).toBe(true);
|
||||
expect(findSubmitButton().text()).toBe('Save integration');
|
||||
|
||||
findForm().trigger('submit');
|
||||
|
||||
await wrapper.vm.$nextTick();
|
||||
|
||||
expect(wrapper.emitted('update-integration')).toBeTruthy();
|
||||
expect(wrapper.emitted('update-integration')[0]).toEqual([
|
||||
{ type: typeSet.http, variables: { name: 'Test integration', active: true } },
|
||||
]);
|
||||
});
|
||||
|
||||
it('allows for update-integration with the correct form values for PROMETHEUS', async () => {
|
||||
createComponent({
|
||||
props: {
|
||||
currentIntegration: { id: '1' },
|
||||
loading: false,
|
||||
},
|
||||
});
|
||||
|
||||
const options = findSelect().findAll('option');
|
||||
await options.at(2).setSelected();
|
||||
|
||||
await findFormFields()
|
||||
.at(0)
|
||||
.setValue('Test integration');
|
||||
await findFormFields()
|
||||
.at(1)
|
||||
.setValue('https://test.com');
|
||||
await findFormToggle().trigger('click');
|
||||
|
||||
await wrapper.vm.$nextTick();
|
||||
|
||||
expect(findSubmitButton().exists()).toBe(true);
|
||||
expect(findSubmitButton().text()).toBe('Save integration');
|
||||
|
||||
findForm().trigger('submit');
|
||||
|
||||
await wrapper.vm.$nextTick();
|
||||
|
||||
expect(wrapper.emitted('update-integration')).toBeTruthy();
|
||||
expect(wrapper.emitted('update-integration')[0]).toEqual([
|
||||
{ type: typeSet.prometheus, variables: { apiUrl: 'https://test.com', active: true } },
|
||||
]);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@ describe('AlertsSettingsFormOld', () => {
|
|||
createComponent(
|
||||
{},
|
||||
{
|
||||
authKey: 'newToken',
|
||||
token: 'newToken',
|
||||
},
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -6,14 +6,24 @@ import AlertsSettingsFormNew from '~/alerts_settings/components/alerts_settings_
|
|||
import IntegrationsList from '~/alerts_settings/components/alerts_integrations_list.vue';
|
||||
import createHttpIntegrationMutation from '~/alerts_settings/graphql/mutations/create_http_integration.mutation.graphql';
|
||||
import createPrometheusIntegrationMutation from '~/alerts_settings/graphql/mutations/create_prometheus_integration.mutation.graphql';
|
||||
import updateHttpIntegrationMutation from '~/alerts_settings/graphql/mutations/update_http_integration.mutation.graphql';
|
||||
import updatePrometheusIntegrationMutation from '~/alerts_settings/graphql/mutations/update_prometheus_integration.mutation.graphql';
|
||||
import resetHttpTokenMutation from '~/alerts_settings/graphql/mutations/reset_http_token.mutation.graphql';
|
||||
import resetPrometheusTokenMutation from '~/alerts_settings/graphql/mutations/reset_prometheus_token.mutation.graphql';
|
||||
import { typeSet } from '~/alerts_settings/constants';
|
||||
import createFlash from '~/flash';
|
||||
import { defaultAlertSettingsConfig } from './util';
|
||||
import mockIntegrations from './mocks/integrations.json';
|
||||
import {
|
||||
createHttpVariables,
|
||||
updateHttpVariables,
|
||||
createPrometheusVariables,
|
||||
updatePrometheusVariables,
|
||||
ID,
|
||||
} from './mocks/apollo_mock';
|
||||
|
||||
jest.mock('~/flash');
|
||||
|
||||
const projectPath = '';
|
||||
|
||||
describe('AlertsSettingsWrapper', () => {
|
||||
let wrapper;
|
||||
|
||||
|
|
@ -80,7 +90,7 @@ describe('AlertsSettingsWrapper', () => {
|
|||
|
||||
it('renders the IntegrationsList table using the API data', () => {
|
||||
createComponent({
|
||||
data: { integrations: { list: mockIntegrations } },
|
||||
data: { integrations: { list: mockIntegrations }, currentIntegration: mockIntegrations[0] },
|
||||
provide: { glFeatures: { httpIntegrationsList: true } },
|
||||
loading: false,
|
||||
});
|
||||
|
|
@ -100,7 +110,7 @@ describe('AlertsSettingsWrapper', () => {
|
|||
|
||||
it('calls `$apollo.mutate` with `createHttpIntegrationMutation`', () => {
|
||||
createComponent({
|
||||
data: { integrations: { list: mockIntegrations } },
|
||||
data: { integrations: { list: mockIntegrations }, currentIntegration: mockIntegrations[0] },
|
||||
provide: { glFeatures: { httpIntegrationsList: true } },
|
||||
loading: false,
|
||||
});
|
||||
|
|
@ -108,26 +118,66 @@ describe('AlertsSettingsWrapper', () => {
|
|||
jest.spyOn(wrapper.vm.$apollo, 'mutate').mockResolvedValue({
|
||||
data: { createHttpIntegrationMutation: { integration: { id: '1' } } },
|
||||
});
|
||||
wrapper.find(AlertsSettingsFormNew).vm.$emit('on-create-new-integration', {
|
||||
type: 'HTTP',
|
||||
variables: { name: 'Test 1', active: true },
|
||||
wrapper.find(AlertsSettingsFormNew).vm.$emit('create-new-integration', {
|
||||
type: typeSet.http,
|
||||
variables: createHttpVariables,
|
||||
});
|
||||
|
||||
expect(wrapper.vm.$apollo.mutate).toHaveBeenCalledTimes(1);
|
||||
expect(wrapper.vm.$apollo.mutate).toHaveBeenCalledWith({
|
||||
mutation: createHttpIntegrationMutation,
|
||||
update: expect.anything(),
|
||||
variables: createHttpVariables,
|
||||
});
|
||||
});
|
||||
|
||||
it('calls `$apollo.mutate` with `updateHttpIntegrationMutation`', () => {
|
||||
createComponent({
|
||||
data: { integrations: { list: mockIntegrations }, currentIntegration: mockIntegrations[0] },
|
||||
provide: { glFeatures: { httpIntegrationsList: true } },
|
||||
loading: false,
|
||||
});
|
||||
|
||||
jest.spyOn(wrapper.vm.$apollo, 'mutate').mockResolvedValue({
|
||||
data: { updateHttpIntegrationMutation: { integration: { id: '1' } } },
|
||||
});
|
||||
wrapper.find(AlertsSettingsFormNew).vm.$emit('update-integration', {
|
||||
type: typeSet.http,
|
||||
variables: updateHttpVariables,
|
||||
});
|
||||
|
||||
expect(wrapper.vm.$apollo.mutate).toHaveBeenCalledWith({
|
||||
mutation: updateHttpIntegrationMutation,
|
||||
variables: updateHttpVariables,
|
||||
});
|
||||
});
|
||||
|
||||
it('calls `$apollo.mutate` with `resetHttpTokenMutation`', () => {
|
||||
createComponent({
|
||||
data: { integrations: { list: mockIntegrations }, currentIntegration: mockIntegrations[0] },
|
||||
provide: { glFeatures: { httpIntegrationsList: true } },
|
||||
loading: false,
|
||||
});
|
||||
|
||||
jest.spyOn(wrapper.vm.$apollo, 'mutate').mockResolvedValue({
|
||||
data: { resetHttpTokenMutation: { integration: { id: '1' } } },
|
||||
});
|
||||
wrapper.find(AlertsSettingsFormNew).vm.$emit('reset-token', {
|
||||
type: typeSet.http,
|
||||
variables: { id: ID },
|
||||
});
|
||||
|
||||
expect(wrapper.vm.$apollo.mutate).toHaveBeenCalledWith({
|
||||
mutation: resetHttpTokenMutation,
|
||||
variables: {
|
||||
name: 'Test 1',
|
||||
active: true,
|
||||
projectPath,
|
||||
id: ID,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('calls `$apollo.mutate` with `createPrometheusIntegrationMutation`', () => {
|
||||
createComponent({
|
||||
data: { integrations: { list: mockIntegrations } },
|
||||
data: { integrations: { list: mockIntegrations }, currentIntegration: mockIntegrations[0] },
|
||||
provide: { glFeatures: { httpIntegrationsList: true } },
|
||||
loading: false,
|
||||
});
|
||||
|
|
@ -135,33 +185,107 @@ describe('AlertsSettingsWrapper', () => {
|
|||
jest.spyOn(wrapper.vm.$apollo, 'mutate').mockResolvedValue({
|
||||
data: { createPrometheusIntegrationMutation: { integration: { id: '2' } } },
|
||||
});
|
||||
wrapper.find(AlertsSettingsFormNew).vm.$emit('on-create-new-integration', {
|
||||
type: 'PROMETHEUS',
|
||||
variables: { apiUrl: 'https://test.com', active: true },
|
||||
wrapper.find(AlertsSettingsFormNew).vm.$emit('create-new-integration', {
|
||||
type: typeSet.prometheus,
|
||||
variables: createPrometheusVariables,
|
||||
});
|
||||
|
||||
expect(wrapper.vm.$apollo.mutate).toHaveBeenCalledTimes(1);
|
||||
expect(wrapper.vm.$apollo.mutate).toHaveBeenCalledWith({
|
||||
mutation: createPrometheusIntegrationMutation,
|
||||
update: expect.anything(),
|
||||
variables: createPrometheusVariables,
|
||||
});
|
||||
});
|
||||
|
||||
it('calls `$apollo.mutate` with `updatePrometheusIntegrationMutation`', () => {
|
||||
createComponent({
|
||||
data: { integrations: { list: mockIntegrations }, currentIntegration: mockIntegrations[0] },
|
||||
provide: { glFeatures: { httpIntegrationsList: true } },
|
||||
loading: false,
|
||||
});
|
||||
|
||||
jest.spyOn(wrapper.vm.$apollo, 'mutate').mockResolvedValue({
|
||||
data: { updatePrometheusIntegrationMutation: { integration: { id: '2' } } },
|
||||
});
|
||||
wrapper.find(AlertsSettingsFormNew).vm.$emit('update-integration', {
|
||||
type: typeSet.prometheus,
|
||||
variables: updatePrometheusVariables,
|
||||
});
|
||||
|
||||
expect(wrapper.vm.$apollo.mutate).toHaveBeenCalledWith({
|
||||
mutation: updatePrometheusIntegrationMutation,
|
||||
variables: updatePrometheusVariables,
|
||||
});
|
||||
});
|
||||
|
||||
it('calls `$apollo.mutate` with `resetPrometheusTokenMutation`', () => {
|
||||
createComponent({
|
||||
data: { integrations: { list: mockIntegrations }, currentIntegration: mockIntegrations[0] },
|
||||
provide: { glFeatures: { httpIntegrationsList: true } },
|
||||
loading: false,
|
||||
});
|
||||
|
||||
jest.spyOn(wrapper.vm.$apollo, 'mutate').mockResolvedValue({
|
||||
data: { resetPrometheusTokenMutation: { integration: { id: '1' } } },
|
||||
});
|
||||
wrapper.find(AlertsSettingsFormNew).vm.$emit('reset-token', {
|
||||
type: typeSet.prometheus,
|
||||
variables: { id: ID },
|
||||
});
|
||||
|
||||
expect(wrapper.vm.$apollo.mutate).toHaveBeenCalledWith({
|
||||
mutation: resetPrometheusTokenMutation,
|
||||
variables: {
|
||||
apiUrl: 'https://test.com',
|
||||
active: true,
|
||||
projectPath,
|
||||
id: ID,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('shows error alert when integration creation fails ', () => {
|
||||
it('shows error alert when integration creation fails ', async () => {
|
||||
const errorMsg = 'Something went wrong';
|
||||
createComponent({
|
||||
data: { integrations: { list: mockIntegrations } },
|
||||
data: { integrations: { list: mockIntegrations }, currentIntegration: mockIntegrations[0] },
|
||||
provide: { glFeatures: { httpIntegrationsList: true } },
|
||||
loading: false,
|
||||
});
|
||||
|
||||
jest.spyOn(wrapper.vm.$apollo, 'mutate').mockRejectedValue(errorMsg);
|
||||
wrapper.find(AlertsSettingsFormNew).vm.$emit('on-create-new-integration', {});
|
||||
wrapper.find(AlertsSettingsFormNew).vm.$emit('create-new-integration', {});
|
||||
|
||||
setImmediate(() => {
|
||||
expect(createFlash).toHaveBeenCalledWith({ message: errorMsg });
|
||||
});
|
||||
});
|
||||
|
||||
it('shows error alert when integration token reset fails ', () => {
|
||||
const errorMsg = 'Something went wrong';
|
||||
createComponent({
|
||||
data: { integrations: { list: mockIntegrations }, currentIntegration: mockIntegrations[0] },
|
||||
provide: { glFeatures: { httpIntegrationsList: true } },
|
||||
loading: false,
|
||||
});
|
||||
|
||||
jest.spyOn(wrapper.vm.$apollo, 'mutate').mockRejectedValue(errorMsg);
|
||||
|
||||
wrapper.find(AlertsSettingsFormNew).vm.$emit('reset-token', {});
|
||||
|
||||
setImmediate(() => {
|
||||
expect(createFlash).toHaveBeenCalledWith({ message: errorMsg });
|
||||
});
|
||||
});
|
||||
|
||||
it('shows error alert when integration update fails ', () => {
|
||||
const errorMsg = 'Something went wrong';
|
||||
createComponent({
|
||||
data: { integrations: { list: mockIntegrations }, currentIntegration: mockIntegrations[0] },
|
||||
provide: { glFeatures: { httpIntegrationsList: true } },
|
||||
loading: false,
|
||||
});
|
||||
|
||||
jest.spyOn(wrapper.vm.$apollo, 'mutate').mockRejectedValue(errorMsg);
|
||||
|
||||
wrapper.find(AlertsSettingsFormNew).vm.$emit('update-integration', {});
|
||||
|
||||
setImmediate(() => {
|
||||
expect(createFlash).toHaveBeenCalledWith({ message: errorMsg });
|
||||
|
|
|
|||
|
|
@ -0,0 +1,26 @@
|
|||
const projectPath = '';
|
||||
export const ID = 'gid://gitlab/AlertManagement::HttpIntegration/7';
|
||||
|
||||
export const createHttpVariables = {
|
||||
name: 'Test Pre',
|
||||
active: true,
|
||||
projectPath,
|
||||
};
|
||||
|
||||
export const updateHttpVariables = {
|
||||
name: 'Test Pre',
|
||||
active: true,
|
||||
id: ID,
|
||||
};
|
||||
|
||||
export const createPrometheusVariables = {
|
||||
apiUrl: 'https://test-pre.com',
|
||||
active: true,
|
||||
projectPath,
|
||||
};
|
||||
|
||||
export const updatePrometheusVariables = {
|
||||
apiUrl: 'https://test-pre.com',
|
||||
active: true,
|
||||
id: ID,
|
||||
};
|
||||
|
|
@ -14,41 +14,7 @@ exports[`Design management upload button component renders inverted upload desig
|
|||
>
|
||||
|
||||
Upload designs
|
||||
|
||||
<!---->
|
||||
</gl-button-stub>
|
||||
|
||||
<input
|
||||
accept="image/*"
|
||||
class="hide"
|
||||
multiple="multiple"
|
||||
name="design_file"
|
||||
type="file"
|
||||
/>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`Design management upload button component renders loading icon 1`] = `
|
||||
<div>
|
||||
<gl-button-stub
|
||||
buttontextclasses=""
|
||||
category="primary"
|
||||
disabled="true"
|
||||
icon=""
|
||||
size="small"
|
||||
title="Adding a design with the same filename replaces the file in a new version."
|
||||
variant="default"
|
||||
>
|
||||
|
||||
Upload designs
|
||||
|
||||
<gl-loading-icon-stub
|
||||
class="ml-1"
|
||||
color="dark"
|
||||
inline="true"
|
||||
label="Loading"
|
||||
size="sm"
|
||||
/>
|
||||
|
||||
</gl-button-stub>
|
||||
|
||||
<input
|
||||
|
|
@ -73,8 +39,7 @@ exports[`Design management upload button component renders upload design button
|
|||
>
|
||||
|
||||
Upload designs
|
||||
|
||||
<!---->
|
||||
|
||||
</gl-button-stub>
|
||||
|
||||
<input
|
||||
|
|
|
|||
|
|
@ -1,10 +1,11 @@
|
|||
import { shallowMount } from '@vue/test-utils';
|
||||
import { GlButton } from '@gitlab/ui';
|
||||
import UploadButton from '~/design_management/components/upload/button.vue';
|
||||
|
||||
describe('Design management upload button component', () => {
|
||||
let wrapper;
|
||||
|
||||
function createComponent(isSaving = false, isInverted = false) {
|
||||
function createComponent({ isSaving = false, isInverted = false } = {}) {
|
||||
wrapper = shallowMount(UploadButton, {
|
||||
propsData: {
|
||||
isSaving,
|
||||
|
|
@ -24,15 +25,19 @@ describe('Design management upload button component', () => {
|
|||
});
|
||||
|
||||
it('renders inverted upload design button', () => {
|
||||
createComponent(false, true);
|
||||
createComponent({ isInverted: true });
|
||||
|
||||
expect(wrapper.element).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('renders loading icon', () => {
|
||||
createComponent(true);
|
||||
describe('when `isSaving` prop is `true`', () => {
|
||||
it('Button `loading` prop is `true`', () => {
|
||||
createComponent({ isSaving: true });
|
||||
|
||||
expect(wrapper.element).toMatchSnapshot();
|
||||
const button = wrapper.find(GlButton);
|
||||
expect(button.exists()).toBe(true);
|
||||
expect(button.props('loading')).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('onFileUploadChange', () => {
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ describe('ConfirmationModal', () => {
|
|||
'Saving will update the default settings for all projects that are not using custom settings.',
|
||||
);
|
||||
expect(findGlModal().text()).toContain(
|
||||
'Projects using custom settings will not be impacted unless the project owner chooses to use instance-level defaults.',
|
||||
'Projects using custom settings will not be impacted unless the project owner chooses to use parent level defaults.',
|
||||
);
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import JiraTriggerFields from '~/integrations/edit/components/jira_trigger_field
|
|||
import JiraIssuesFields from '~/integrations/edit/components/jira_issues_fields.vue';
|
||||
import TriggerFields from '~/integrations/edit/components/trigger_fields.vue';
|
||||
import DynamicField from '~/integrations/edit/components/dynamic_field.vue';
|
||||
import { integrationLevels } from '~/integrations/edit/constants';
|
||||
|
||||
describe('IntegrationForm', () => {
|
||||
let wrapper;
|
||||
|
|
@ -69,14 +70,24 @@ describe('IntegrationForm', () => {
|
|||
describe('integrationLevel is instance', () => {
|
||||
it('renders ConfirmationModal', () => {
|
||||
createComponent({
|
||||
integrationLevel: 'instance',
|
||||
integrationLevel: integrationLevels.INSTANCE,
|
||||
});
|
||||
|
||||
expect(findConfirmationModal().exists()).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('integrationLevel is not instance', () => {
|
||||
describe('integrationLevel is group', () => {
|
||||
it('renders ConfirmationModal', () => {
|
||||
createComponent({
|
||||
integrationLevel: integrationLevels.GROUP,
|
||||
});
|
||||
|
||||
expect(findConfirmationModal().exists()).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('integrationLevel is project', () => {
|
||||
it('does not render ConfirmationModal', () => {
|
||||
createComponent({
|
||||
integrationLevel: 'project',
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ const accessLevels = { Guest: 10, Reporter: 20, Developer: 30, Maintainer: 40, O
|
|||
const defaultAccessLevel = '10';
|
||||
const helpLink = 'https://example.com';
|
||||
|
||||
const createComponent = () => {
|
||||
const createComponent = (data = {}) => {
|
||||
return shallowMount(InviteMembersModal, {
|
||||
propsData: {
|
||||
groupId,
|
||||
|
|
@ -18,9 +18,14 @@ const createComponent = () => {
|
|||
defaultAccessLevel,
|
||||
helpLink,
|
||||
},
|
||||
data() {
|
||||
return data;
|
||||
},
|
||||
stubs: {
|
||||
GlSprintf,
|
||||
'gl-modal': '<div><slot name="modal-footer"></slot><slot></slot></div>',
|
||||
'gl-dropdown': true,
|
||||
'gl-dropdown-item': true,
|
||||
GlSprintf,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
|
@ -34,7 +39,7 @@ describe('InviteMembersModal', () => {
|
|||
});
|
||||
|
||||
const findDropdown = () => wrapper.find(GlDropdown);
|
||||
const findDropdownItems = () => wrapper.findAll(GlDropdownItem);
|
||||
const findDropdownItems = () => findDropdown().findAll(GlDropdownItem);
|
||||
const findDatepicker = () => wrapper.find(GlDatepicker);
|
||||
const findLink = () => wrapper.find(GlLink);
|
||||
const findCancelButton = () => wrapper.find({ ref: 'cancelButton' });
|
||||
|
|
@ -88,28 +93,72 @@ describe('InviteMembersModal', () => {
|
|||
format: 'json',
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
wrapper = createComponent();
|
||||
|
||||
jest.spyOn(Api, 'inviteGroupMember').mockResolvedValue({ data: postData });
|
||||
wrapper.vm.$toast = { show: jest.fn() };
|
||||
|
||||
wrapper.vm.submitForm(postData);
|
||||
});
|
||||
|
||||
it('calls Api inviteGroupMember with the correct params', () => {
|
||||
expect(Api.inviteGroupMember).toHaveBeenCalledWith(groupId, postData);
|
||||
});
|
||||
|
||||
describe('when the invite was sent successfully', () => {
|
||||
const toastMessageSuccessful = 'Users were succesfully added';
|
||||
beforeEach(() => {
|
||||
wrapper = createComponent();
|
||||
|
||||
wrapper.vm.$toast = { show: jest.fn() };
|
||||
jest.spyOn(Api, 'inviteGroupMember').mockResolvedValue({ data: postData });
|
||||
|
||||
wrapper.vm.submitForm(postData);
|
||||
});
|
||||
|
||||
it('displays the successful toastMessage', () => {
|
||||
const toastMessageSuccessful = 'Members were successfully added';
|
||||
|
||||
expect(wrapper.vm.$toast.show).toHaveBeenCalledWith(
|
||||
toastMessageSuccessful,
|
||||
wrapper.vm.toastOptions,
|
||||
);
|
||||
});
|
||||
|
||||
it('calls Api inviteGroupMember with the correct params', () => {
|
||||
expect(Api.inviteGroupMember).toHaveBeenCalledWith(groupId, postData);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when sending the invite for a single member returned an api error', () => {
|
||||
const apiErrorMessage = 'Members already exists';
|
||||
|
||||
beforeEach(() => {
|
||||
wrapper = createComponent({ newUsersToInvite: '123' });
|
||||
|
||||
wrapper.vm.$toast = { show: jest.fn() };
|
||||
jest
|
||||
.spyOn(Api, 'inviteGroupMember')
|
||||
.mockRejectedValue({ response: { data: { message: apiErrorMessage } } });
|
||||
|
||||
findInviteButton().vm.$emit('click');
|
||||
});
|
||||
|
||||
it('displays the api error message for the toastMessage', () => {
|
||||
expect(wrapper.vm.$toast.show).toHaveBeenCalledWith(
|
||||
apiErrorMessage,
|
||||
wrapper.vm.toastOptions,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when sending the invite for multiple members returned any error', () => {
|
||||
const genericErrorMessage = 'Some of the members could not be added';
|
||||
|
||||
beforeEach(() => {
|
||||
wrapper = createComponent({ newUsersToInvite: '123' });
|
||||
|
||||
wrapper.vm.$toast = { show: jest.fn() };
|
||||
jest
|
||||
.spyOn(Api, 'inviteGroupMember')
|
||||
.mockRejectedValue({ response: { data: { success: false } } });
|
||||
|
||||
findInviteButton().vm.$emit('click');
|
||||
});
|
||||
|
||||
it('displays the expected toastMessage', () => {
|
||||
expect(wrapper.vm.$toast.show).toHaveBeenCalledWith(
|
||||
genericErrorMessage,
|
||||
wrapper.vm.toastOptions,
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -0,0 +1,112 @@
|
|||
import { shallowMount } from '@vue/test-utils';
|
||||
import { nextTick } from 'vue';
|
||||
import { GlTokenSelector } from '@gitlab/ui';
|
||||
import waitForPromises from 'helpers/wait_for_promises';
|
||||
import Api from '~/api';
|
||||
import MembersTokenSelect from '~/invite_members/components/members_token_select.vue';
|
||||
|
||||
const label = 'testgroup';
|
||||
const placeholder = 'Search for a member';
|
||||
const user1 = { id: 1, name: 'Name One', username: 'one_1', avatar_url: '' };
|
||||
const user2 = { id: 2, name: 'Name Two', username: 'two_2', avatar_url: '' };
|
||||
const allUsers = [user1, user2];
|
||||
|
||||
const createComponent = () => {
|
||||
return shallowMount(MembersTokenSelect, {
|
||||
propsData: {
|
||||
ariaLabelledby: label,
|
||||
placeholder,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
describe('MembersTokenSelect', () => {
|
||||
let wrapper;
|
||||
|
||||
beforeEach(() => {
|
||||
jest.spyOn(Api, 'users').mockResolvedValue({ data: allUsers });
|
||||
wrapper = createComponent();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
wrapper.destroy();
|
||||
wrapper = null;
|
||||
});
|
||||
|
||||
const findTokenSelector = () => wrapper.find(GlTokenSelector);
|
||||
|
||||
describe('rendering the token-selector component', () => {
|
||||
it('renders with the correct props', () => {
|
||||
const expectedProps = {
|
||||
ariaLabelledby: label,
|
||||
placeholder,
|
||||
};
|
||||
|
||||
expect(findTokenSelector().props()).toEqual(expect.objectContaining(expectedProps));
|
||||
});
|
||||
});
|
||||
|
||||
describe('users', () => {
|
||||
describe('when input is focused for the first time (modal auto-focus)', () => {
|
||||
it('does not call the API', async () => {
|
||||
findTokenSelector().vm.$emit('focus');
|
||||
|
||||
await waitForPromises();
|
||||
|
||||
expect(Api.users).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('when input is manually focused', () => {
|
||||
it('calls the API and sets dropdown items as request result', async () => {
|
||||
const tokenSelector = findTokenSelector();
|
||||
|
||||
tokenSelector.vm.$emit('focus');
|
||||
tokenSelector.vm.$emit('blur');
|
||||
tokenSelector.vm.$emit('focus');
|
||||
|
||||
await waitForPromises();
|
||||
|
||||
expect(tokenSelector.props('dropdownItems')).toMatchObject(allUsers);
|
||||
expect(tokenSelector.props('hideDropdownWithNoItems')).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when text input is typed in', () => {
|
||||
it('calls the API with search parameter', async () => {
|
||||
const searchParam = 'One';
|
||||
const tokenSelector = findTokenSelector();
|
||||
|
||||
tokenSelector.vm.$emit('text-input', searchParam);
|
||||
|
||||
await waitForPromises();
|
||||
|
||||
expect(Api.users).toHaveBeenCalledWith(searchParam, wrapper.vm.$options.queryOptions);
|
||||
expect(tokenSelector.props('hideDropdownWithNoItems')).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when user is selected', () => {
|
||||
it('emits `input` event with selected users', () => {
|
||||
findTokenSelector().vm.$emit('input', [
|
||||
{ id: 1, name: 'John Smith' },
|
||||
{ id: 2, name: 'Jane Doe' },
|
||||
]);
|
||||
|
||||
expect(wrapper.emitted().input[0][0]).toBe('1,2');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('when text input is blurred', () => {
|
||||
it('clears text input', async () => {
|
||||
const tokenSelector = findTokenSelector();
|
||||
|
||||
tokenSelector.vm.$emit('blur');
|
||||
|
||||
await nextTick();
|
||||
|
||||
expect(tokenSelector.props('hideDropdownWithNoItems')).toBe(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
@ -208,4 +208,27 @@ RSpec.describe PageLayoutHelper do
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#page_itemtype' do
|
||||
subject { helper.page_itemtype(itemtype) }
|
||||
|
||||
context 'when itemtype is passed' do
|
||||
let(:itemtype) { 'http://schema.org/Person' }
|
||||
|
||||
it 'stores and returns the itemtype value' do
|
||||
attrs = { itemscope: true, itemtype: itemtype }
|
||||
|
||||
expect(subject).to eq attrs
|
||||
expect(helper.page_itemtype(nil)).to eq attrs
|
||||
end
|
||||
end
|
||||
|
||||
context 'when no itemtype is provided' do
|
||||
let(:itemtype) { nil }
|
||||
|
||||
it 'returns an empty hash' do
|
||||
expect(subject).to eq({})
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -204,31 +204,9 @@ RSpec.describe UsersHelper do
|
|||
end
|
||||
|
||||
describe '#work_information' do
|
||||
subject { helper.work_information(user) }
|
||||
let(:with_schema_markup) { false }
|
||||
|
||||
context 'when both job_title and organization are present' do
|
||||
let(:user) { build(:user, organization: 'GitLab', job_title: 'Frontend Engineer') }
|
||||
|
||||
it 'returns job title concatenated with organization' do
|
||||
is_expected.to eq('Frontend Engineer at GitLab')
|
||||
end
|
||||
end
|
||||
|
||||
context 'when only organization is present' do
|
||||
let(:user) { build(:user, organization: 'GitLab') }
|
||||
|
||||
it "returns organization" do
|
||||
is_expected.to eq('GitLab')
|
||||
end
|
||||
end
|
||||
|
||||
context 'when only job_title is present' do
|
||||
let(:user) { build(:user, job_title: 'Frontend Engineer') }
|
||||
|
||||
it 'returns job title' do
|
||||
is_expected.to eq('Frontend Engineer')
|
||||
end
|
||||
end
|
||||
subject { helper.work_information(user, with_schema_markup: with_schema_markup) }
|
||||
|
||||
context 'when neither organization nor job_title are present' do
|
||||
it { is_expected.to be_nil }
|
||||
|
|
@ -239,5 +217,59 @@ RSpec.describe UsersHelper do
|
|||
|
||||
it { is_expected.to be_nil }
|
||||
end
|
||||
|
||||
context 'without schema markup' do
|
||||
context 'when both job_title and organization are present' do
|
||||
let(:user) { build(:user, organization: 'GitLab', job_title: 'Frontend Engineer') }
|
||||
|
||||
it 'returns job title concatenated with organization' do
|
||||
is_expected.to eq('Frontend Engineer at GitLab')
|
||||
end
|
||||
end
|
||||
|
||||
context 'when only organization is present' do
|
||||
let(:user) { build(:user, organization: 'GitLab') }
|
||||
|
||||
it "returns organization" do
|
||||
is_expected.to eq('GitLab')
|
||||
end
|
||||
end
|
||||
|
||||
context 'when only job_title is present' do
|
||||
let(:user) { build(:user, job_title: 'Frontend Engineer') }
|
||||
|
||||
it 'returns job title' do
|
||||
is_expected.to eq('Frontend Engineer')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'with schema markup' do
|
||||
let(:with_schema_markup) { true }
|
||||
|
||||
context 'when both job_title and organization are present' do
|
||||
let(:user) { build(:user, organization: 'GitLab', job_title: 'Frontend Engineer') }
|
||||
|
||||
it 'returns job title concatenated with organization' do
|
||||
is_expected.to eq('<span itemprop="jobTitle">Frontend Engineer</span> at <span itemprop="worksFor">GitLab</span>')
|
||||
end
|
||||
end
|
||||
|
||||
context 'when only organization is present' do
|
||||
let(:user) { build(:user, organization: 'GitLab') }
|
||||
|
||||
it "returns organization" do
|
||||
is_expected.to eq('<span itemprop="worksFor">GitLab</span>')
|
||||
end
|
||||
end
|
||||
|
||||
context 'when only job_title is present' do
|
||||
let(:user) { build(:user, job_title: 'Frontend Engineer') }
|
||||
|
||||
it 'returns job title' do
|
||||
is_expected.to eq('<span itemprop="jobTitle">Frontend Engineer</span>')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -236,13 +236,16 @@ RSpec.describe Gitlab::Danger::Helper do
|
|||
|
||||
'.gitlab/ci/frontend.gitlab-ci.yml' | %i[frontend engineering_productivity]
|
||||
|
||||
'app/models/foo' | [:backend]
|
||||
'bin/foo' | [:backend]
|
||||
'config/foo' | [:backend]
|
||||
'lib/foo' | [:backend]
|
||||
'rubocop/foo' | [:backend]
|
||||
'spec/foo' | [:backend]
|
||||
'spec/foo/bar' | [:backend]
|
||||
'app/models/foo' | [:backend]
|
||||
'bin/foo' | [:backend]
|
||||
'config/foo' | [:backend]
|
||||
'lib/foo' | [:backend]
|
||||
'rubocop/foo' | [:backend]
|
||||
'.rubocop.yml' | [:backend]
|
||||
'.rubocop_todo.yml' | [:backend]
|
||||
'.rubocop_manual_todo.yml' | [:backend]
|
||||
'spec/foo' | [:backend]
|
||||
'spec/foo/bar' | [:backend]
|
||||
|
||||
'ee/app/foo' | [:backend]
|
||||
'ee/bin/foo' | [:backend]
|
||||
|
|
|
|||
|
|
@ -108,7 +108,7 @@ RSpec.describe Key, :mailer do
|
|||
expect(build(:key, key: 'ssh-rsa an-invalid-key==')).not_to be_valid
|
||||
end
|
||||
|
||||
where(:factory, :chars, :expected_sections) do
|
||||
where(:factory, :characters, :expected_sections) do
|
||||
[
|
||||
[:key, ["\n", "\r\n"], 3],
|
||||
[:key, [' ', ' '], 3],
|
||||
|
|
@ -122,7 +122,7 @@ RSpec.describe Key, :mailer do
|
|||
let!(:original_fingerprint_sha256) { key.fingerprint_sha256 }
|
||||
|
||||
it 'accepts a key with blank space characters after stripping them' do
|
||||
modified_key = key.key.insert(100, chars.first).insert(40, chars.last)
|
||||
modified_key = key.key.insert(100, characters.first).insert(40, characters.last)
|
||||
_, content = modified_key.split
|
||||
|
||||
key.update!(key: modified_key)
|
||||
|
|
|
|||
|
|
@ -1,134 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'fast_spec_helper'
|
||||
require 'rubocop'
|
||||
require_relative '../../../../rubocop/cop/code_reuse/active_record'
|
||||
|
||||
RSpec.describe RuboCop::Cop::CodeReuse::ActiveRecord, type: :rubocop do
|
||||
include CopHelper
|
||||
|
||||
subject(:cop) { described_class.new }
|
||||
|
||||
it 'flags the use of "where" without any arguments' do
|
||||
expect_offense(<<~SOURCE)
|
||||
def foo
|
||||
User.where
|
||||
^^^^^ This method can only be used inside an ActiveRecord model: https://gitlab.com/gitlab-org/gitlab-foss/issues/49653
|
||||
end
|
||||
SOURCE
|
||||
end
|
||||
|
||||
it 'flags the use of "where" with arguments' do
|
||||
expect_offense(<<~SOURCE)
|
||||
def foo
|
||||
User.where(id: 10)
|
||||
^^^^^ This method can only be used inside an ActiveRecord model: https://gitlab.com/gitlab-org/gitlab-foss/issues/49653
|
||||
end
|
||||
SOURCE
|
||||
end
|
||||
|
||||
it 'does not flag the use of "group" without any arguments' do
|
||||
expect_no_offenses(<<~SOURCE)
|
||||
def foo
|
||||
project.group
|
||||
end
|
||||
SOURCE
|
||||
end
|
||||
|
||||
it 'flags the use of "group" with arguments' do
|
||||
expect_offense(<<~SOURCE)
|
||||
def foo
|
||||
project.group(:name)
|
||||
^^^^^ This method can only be used inside an ActiveRecord model: https://gitlab.com/gitlab-org/gitlab-foss/issues/49653
|
||||
end
|
||||
SOURCE
|
||||
end
|
||||
|
||||
it 'does not flag the use of ActiveRecord models in a model' do
|
||||
path = rails_root_join('app', 'models', 'foo.rb').to_s
|
||||
|
||||
expect_no_offenses(<<~SOURCE, path)
|
||||
def foo
|
||||
project.group(:name)
|
||||
end
|
||||
SOURCE
|
||||
end
|
||||
|
||||
it 'does not flag the use of ActiveRecord models in a spec' do
|
||||
path = rails_root_join('spec', 'foo_spec.rb').to_s
|
||||
|
||||
expect_no_offenses(<<~SOURCE, path)
|
||||
def foo
|
||||
project.group(:name)
|
||||
end
|
||||
SOURCE
|
||||
end
|
||||
|
||||
it 'does not flag the use of ActiveRecord models in a background migration' do
|
||||
path = rails_root_join('lib', 'gitlab', 'background_migration', 'foo.rb').to_s
|
||||
|
||||
expect_no_offenses(<<~SOURCE, path)
|
||||
def foo
|
||||
project.group(:name)
|
||||
end
|
||||
SOURCE
|
||||
end
|
||||
|
||||
it 'does not flag the use of ActiveRecord models in lib/gitlab/database' do
|
||||
path = rails_root_join('lib', 'gitlab', 'database', 'foo.rb').to_s
|
||||
|
||||
expect_no_offenses(<<~SOURCE, path)
|
||||
def foo
|
||||
project.group(:name)
|
||||
end
|
||||
SOURCE
|
||||
end
|
||||
|
||||
it 'autocorrects offenses in instance methods by allowing them' do
|
||||
corrected = autocorrect_source(<<~SOURCE)
|
||||
def foo
|
||||
User.where
|
||||
end
|
||||
SOURCE
|
||||
|
||||
expect(corrected).to eq(<<~SOURCE)
|
||||
# rubocop: disable CodeReuse/ActiveRecord
|
||||
def foo
|
||||
User.where
|
||||
end
|
||||
# rubocop: enable CodeReuse/ActiveRecord
|
||||
SOURCE
|
||||
end
|
||||
|
||||
it 'autocorrects offenses in class methods by allowing them' do
|
||||
corrected = autocorrect_source(<<~SOURCE)
|
||||
def self.foo
|
||||
User.where
|
||||
end
|
||||
SOURCE
|
||||
|
||||
expect(corrected).to eq(<<~SOURCE)
|
||||
# rubocop: disable CodeReuse/ActiveRecord
|
||||
def self.foo
|
||||
User.where
|
||||
end
|
||||
# rubocop: enable CodeReuse/ActiveRecord
|
||||
SOURCE
|
||||
end
|
||||
|
||||
it 'autocorrects offenses in blocks by allowing them' do
|
||||
corrected = autocorrect_source(<<~SOURCE)
|
||||
get '/' do
|
||||
User.where
|
||||
end
|
||||
SOURCE
|
||||
|
||||
expect(corrected).to eq(<<~SOURCE)
|
||||
# rubocop: disable CodeReuse/ActiveRecord
|
||||
get '/' do
|
||||
User.where
|
||||
end
|
||||
# rubocop: enable CodeReuse/ActiveRecord
|
||||
SOURCE
|
||||
end
|
||||
end
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'fast_spec_helper'
|
||||
|
||||
require 'rubocop'
|
||||
require_relative '../../../../rubocop/cop/rspec/be_success_matcher'
|
||||
|
||||
RSpec.describe RuboCop::Cop::RSpec::BeSuccessMatcher, type: :rubocop do
|
||||
|
|
|
|||
|
|
@ -0,0 +1,74 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'tempfile'
|
||||
|
||||
# This module provides methods that make it easier to test Cops.
|
||||
module CopHelper
|
||||
extend RSpec::SharedContext
|
||||
|
||||
let(:ruby_version) { 2.4 }
|
||||
let(:rails_version) { false }
|
||||
|
||||
def inspect_source_file(source)
|
||||
Tempfile.open('tmp') { |f| inspect_source(source, f) }
|
||||
end
|
||||
|
||||
def inspect_source(source, file = nil)
|
||||
RuboCop::Formatter::DisabledConfigFormatter.config_to_allow_offenses = {}
|
||||
RuboCop::Formatter::DisabledConfigFormatter.detected_styles = {}
|
||||
processed_source = parse_source(source, file)
|
||||
raise 'Error parsing example code' unless processed_source.valid_syntax?
|
||||
|
||||
_investigate(cop, processed_source)
|
||||
end
|
||||
|
||||
def parse_source(source, file = nil)
|
||||
if file&.respond_to?(:write)
|
||||
file.write(source)
|
||||
file.rewind
|
||||
file = file.path
|
||||
end
|
||||
|
||||
RuboCop::ProcessedSource.new(source, ruby_version, file)
|
||||
end
|
||||
|
||||
def autocorrect_source_file(source)
|
||||
Tempfile.open('tmp') { |f| autocorrect_source(source, f) }
|
||||
end
|
||||
|
||||
def autocorrect_source(source, file = nil)
|
||||
RuboCop::Formatter::DisabledConfigFormatter.config_to_allow_offenses = {}
|
||||
RuboCop::Formatter::DisabledConfigFormatter.detected_styles = {}
|
||||
cop.instance_variable_get(:@options)[:auto_correct] = true
|
||||
processed_source = parse_source(source, file)
|
||||
_investigate(cop, processed_source)
|
||||
|
||||
@last_corrector.rewrite
|
||||
end
|
||||
|
||||
def _investigate(cop, processed_source)
|
||||
team = RuboCop::Cop::Team.new([cop], nil, raise_error: true)
|
||||
report = team.investigate(processed_source)
|
||||
@last_corrector = report.correctors.first || RuboCop::Cop::Corrector.new(processed_source)
|
||||
report.offenses
|
||||
end
|
||||
end
|
||||
|
||||
module RuboCop
|
||||
module Cop
|
||||
# Monkey-patch Cop for tests to provide easy access to messages and
|
||||
# highlights.
|
||||
# this file is an exact copy of source except for this line
|
||||
# where we change to the new Base class defined in rubocop and skirt around our superclass mismatch for class Cop
|
||||
# when running a rubocop spec.
|
||||
class Base
|
||||
def messages
|
||||
offenses.sort.map(&:message)
|
||||
end
|
||||
|
||||
def highlights
|
||||
offenses.sort.map { |o| o.location.source }
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -5,7 +5,8 @@ require_relative "helpers/stub_metrics"
|
|||
require_relative "helpers/stub_object_storage"
|
||||
require_relative "helpers/stub_env"
|
||||
require_relative "helpers/fast_rails_root"
|
||||
require 'rubocop/rspec/support'
|
||||
|
||||
require_relative 'rubocop_patch'
|
||||
|
||||
RSpec.configure do |config|
|
||||
config.mock_with :rspec
|
||||
|
|
|
|||
|
|
@ -0,0 +1,21 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
# There is an issue between rubocop versions 0.86 and 0.87 (verified by testing locally)
|
||||
# where the monkey patching in cop_helper is referencing class Cop and should really be referencing class Base instead
|
||||
# the gem's version of the cop_helper causes this issue when testing a rubocop cop locally and in CI
|
||||
# The only difference in this file as compared to gem source file is that we include our own cop_helper instead
|
||||
# which is a direct copy with a fix for the monkey patching part.
|
||||
# Doing this, resolves the issue.
|
||||
# Ideally we should move away from using the cop_helper at all as is the direction of rubocop as seen
|
||||
# here - https://github.com/rubocop-hq/rubocop/issues/8003
|
||||
# more info https://gitlab.com/gitlab-org/gitlab/-/merge_requests/46477
|
||||
|
||||
require_relative 'helpers/cop_helper'
|
||||
require 'rubocop/rspec/host_environment_simulation_helper'
|
||||
require 'rubocop/rspec/shared_contexts'
|
||||
require 'rubocop/rspec/expect_offense'
|
||||
|
||||
RSpec.configure do |config|
|
||||
config.include CopHelper
|
||||
config.include HostEnvironmentSimulatorHelper
|
||||
end
|
||||
|
|
@ -4,6 +4,6 @@
|
|||
source 'https://rubygems.org'
|
||||
|
||||
gem 'overcommit'
|
||||
gem 'gitlab-styles', '~> 4.3.0', require: false
|
||||
gem 'gitlab-styles', '~> 5.0.0', require: false
|
||||
gem 'scss_lint', '~> 0.56.0', require: false
|
||||
gem 'haml_lint', '~> 0.34.0', require: false
|
||||
|
|
|
|||
|
|
@ -1,22 +1,22 @@
|
|||
GEM
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
activesupport (6.0.3)
|
||||
activesupport (6.0.3.4)
|
||||
concurrent-ruby (~> 1.0, >= 1.0.2)
|
||||
i18n (>= 0.7, < 2)
|
||||
minitest (~> 5.1)
|
||||
tzinfo (~> 1.1)
|
||||
zeitwerk (~> 2.2, >= 2.2.2)
|
||||
ast (2.4.0)
|
||||
ast (2.4.1)
|
||||
childprocess (3.0.0)
|
||||
concurrent-ruby (1.1.6)
|
||||
concurrent-ruby (1.1.7)
|
||||
ffi (1.12.2)
|
||||
gitlab-styles (4.3.0)
|
||||
rubocop (~> 0.82.0)
|
||||
gitlab-styles (5.0.0)
|
||||
rubocop (~> 0.89.1)
|
||||
rubocop-gitlab-security (~> 0.1.0)
|
||||
rubocop-performance (~> 1.5.2)
|
||||
rubocop-rails (~> 2.5)
|
||||
rubocop-rspec (~> 1.36)
|
||||
rubocop-performance (~> 1.8.1)
|
||||
rubocop-rails (~> 2.8)
|
||||
rubocop-rspec (~> 1.44)
|
||||
haml (5.1.2)
|
||||
temple (>= 0.8.0)
|
||||
tilt
|
||||
|
|
@ -25,42 +25,47 @@ GEM
|
|||
rainbow
|
||||
rubocop (>= 0.50.0)
|
||||
sysexits (~> 1.1)
|
||||
i18n (1.8.2)
|
||||
i18n (1.8.5)
|
||||
concurrent-ruby (~> 1.0)
|
||||
iniparse (1.5.0)
|
||||
jaro_winkler (1.5.4)
|
||||
minitest (5.11.3)
|
||||
minitest (5.14.2)
|
||||
overcommit (0.53.0)
|
||||
childprocess (>= 0.6.3, < 4)
|
||||
iniparse (~> 1.4)
|
||||
parallel (1.19.1)
|
||||
parser (2.7.1.2)
|
||||
ast (~> 2.4.0)
|
||||
rack (2.0.9)
|
||||
parallel (1.19.2)
|
||||
parser (2.7.2.0)
|
||||
ast (~> 2.4.1)
|
||||
rack (2.2.3)
|
||||
rainbow (3.0.0)
|
||||
rake (12.3.3)
|
||||
rb-fsevent (0.10.2)
|
||||
rb-inotify (0.9.10)
|
||||
ffi (>= 0.5.0, < 2)
|
||||
regexp_parser (1.8.2)
|
||||
rexml (3.2.4)
|
||||
rubocop (0.82.0)
|
||||
jaro_winkler (~> 1.5.1)
|
||||
rubocop (0.89.1)
|
||||
parallel (~> 1.10)
|
||||
parser (>= 2.7.0.1)
|
||||
parser (>= 2.7.1.1)
|
||||
rainbow (>= 2.2.2, < 4.0)
|
||||
regexp_parser (>= 1.7)
|
||||
rexml
|
||||
rubocop-ast (>= 0.3.0, < 1.0)
|
||||
ruby-progressbar (~> 1.7)
|
||||
unicode-display_width (>= 1.4.0, < 2.0)
|
||||
rubocop-ast (0.8.0)
|
||||
parser (>= 2.7.1.5)
|
||||
rubocop-gitlab-security (0.1.1)
|
||||
rubocop (>= 0.51)
|
||||
rubocop-performance (1.5.2)
|
||||
rubocop (>= 0.71.0)
|
||||
rubocop-rails (2.5.2)
|
||||
activesupport
|
||||
rubocop-performance (1.8.1)
|
||||
rubocop (>= 0.87.0)
|
||||
rubocop-ast (>= 0.4.0)
|
||||
rubocop-rails (2.8.1)
|
||||
activesupport (>= 4.2.0)
|
||||
rack (>= 1.1)
|
||||
rubocop (>= 0.72.0)
|
||||
rubocop-rspec (1.37.0)
|
||||
rubocop (>= 0.68.1)
|
||||
rubocop (>= 0.87.0)
|
||||
rubocop-rspec (1.44.1)
|
||||
rubocop (~> 0.87)
|
||||
rubocop-ast (>= 0.7.1)
|
||||
ruby-progressbar (1.10.1)
|
||||
sass (3.5.5)
|
||||
sass-listen (~> 4.0.0)
|
||||
|
|
@ -77,13 +82,13 @@ GEM
|
|||
tzinfo (1.2.7)
|
||||
thread_safe (~> 0.1)
|
||||
unicode-display_width (1.7.0)
|
||||
zeitwerk (2.3.0)
|
||||
zeitwerk (2.4.1)
|
||||
|
||||
PLATFORMS
|
||||
ruby
|
||||
|
||||
DEPENDENCIES
|
||||
gitlab-styles (~> 4.3.0)
|
||||
gitlab-styles (~> 5.0.0)
|
||||
haml_lint (~> 0.34.0)
|
||||
overcommit
|
||||
scss_lint (~> 0.56.0)
|
||||
|
|
|
|||
Loading…
Reference in New Issue