Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2022-05-13 15:07:43 +00:00
parent 988424215c
commit 7eca3f5662
163 changed files with 2289 additions and 615 deletions

View File

@ -11,11 +11,6 @@ Gitlab/PolicyRuleBoolean:
Exclude:
- 'ee/app/policies/ee/identity_provider_policy.rb'
# Offense count: 41
# Cop supports --auto-correct.
Performance/ConstantRegexp:
Enabled: false
# Offense count: 1428
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle.
@ -34,11 +29,6 @@ RSpec/PredicateMatcher:
RSpec/RepeatedExampleGroupBody:
Enabled: false
# Offense count: 610
# Cop supports --auto-correct.
RSpec/ScatteredLet:
Enabled: false
# Offense count: 26
# Cop supports --auto-correct.
# Configuration parameters: Include.
@ -78,11 +68,6 @@ Rails/CreateTableWithTimestamps:
Rails/HasManyOrHasOneDependent:
Enabled: false
# Offense count: 47
# Cop supports --auto-correct.
Rails/IndexWith:
Enabled: false
# Offense count: 118
# Configuration parameters: Include.
# Include: app/models/**/*.rb
@ -116,13 +101,6 @@ Rails/WhereExists:
Style/AccessorGrouping:
Enabled: false
# Offense count: 188
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle.
# SupportedStyles: percent_q, bare_percent
Style/BarePercentLiterals:
Enabled: false
# Offense count: 42
# Cop supports --auto-correct.
Style/CaseLikeIf:
@ -158,8 +136,3 @@ Style/Lambda:
# Cop supports --auto-correct.
Style/RedundantRegexpEscape:
Enabled: false
# Offense count: 53
# Cop supports --auto-correct.
Style/RescueModifier:
Enabled: false

View File

@ -2,7 +2,6 @@
Database/MultipleDatabases:
Exclude:
- 'config/initializers/active_record_data_types.rb'
- 'config/initializers/sidekiq.rb'
- 'db/post_migrate/20210317104032_set_iteration_cadence_automatic_to_false.rb'
- 'db/post_migrate/20210811122206_update_external_project_bots.rb'
- 'db/post_migrate/20210812013042_remove_duplicate_project_authorizations.rb'
@ -10,10 +9,6 @@ Database/MultipleDatabases:
- 'lib/backup/manager.rb'
- 'lib/gitlab/background_migration/backfill_projects_with_coverage.rb'
- 'lib/gitlab/background_migration/copy_ci_builds_columns_to_security_scans.rb'
- 'lib/gitlab/database.rb'
- 'lib/gitlab/database/load_balancing/load_balancer.rb'
- 'lib/gitlab/database/migrations/observers/query_log.rb'
- 'lib/tasks/gitlab/db/validate_config.rake'
- 'spec/db/schema_spec.rb'
- 'spec/initializers/database_config_spec.rb'
- 'spec/lib/backup/manager_spec.rb'

View File

@ -0,0 +1,32 @@
---
# Cop supports --auto-correct.
Performance/ConstantRegexp:
# Offense count: 46
# Temporarily disabled due to too many offenses
Enabled: false
Exclude:
- 'app/models/commit.rb'
- 'app/models/commit_range.rb'
- 'app/models/custom_emoji.rb'
- 'app/models/gpg_key.rb'
- 'app/models/merge_request.rb'
- 'app/models/project.rb'
- 'app/models/wiki.rb'
- 'ee/app/models/ee/epic.rb'
- 'lib/banzai/filter/custom_emoji_filter.rb'
- 'lib/gitlab/cleanup/project_uploads.rb'
- 'lib/gitlab/database/reindexing/reindex_concurrently.rb'
- 'lib/gitlab/dependency_linker/base_linker.rb'
- 'lib/gitlab/dependency_linker/composer_json_linker.rb'
- 'lib/gitlab/dependency_linker/godeps_json_linker.rb'
- 'lib/gitlab/dependency_linker/podspec_linker.rb'
- 'lib/gitlab/git.rb'
- 'lib/gitlab/job_waiter.rb'
- 'lib/gitlab/metrics/dashboard/url.rb'
- 'lib/gitlab/path_regex.rb'
- 'lib/gitlab/regex.rb'
- 'scripts/perf/query_limiting_report.rb'
- 'scripts/validate_migration_schema'
- 'spec/models/concerns/token_authenticatable_spec.rb'
- 'spec/scripts/lib/glfm/update_specification_spec.rb'
- 'spec/services/notes/copy_service_spec.rb'

View File

@ -0,0 +1,52 @@
---
# Cop supports --auto-correct.
Rails/IndexWith:
# Offense count: 54
# Temporarily disabled due to too many offenses
Enabled: false
Exclude:
- 'app/helpers/ci/jobs_helper.rb'
- 'app/models/ci/build_trace_chunk.rb'
- 'app/models/ci/processable.rb'
- 'app/models/concerns/cached_commit.rb'
- 'app/models/environment.rb'
- 'app/services/concerns/rate_limited_service.rb'
- 'db/post_migrate/20210731132939_backfill_stage_event_hash.rb'
- 'ee/app/models/vulnerabilities/projects_grade.rb'
- 'ee/lib/ee/gitlab/usage_data.rb'
- 'ee/lib/gitlab/auth/group_saml/auth_hash.rb'
- 'ee/lib/gitlab/custom_file_templates.rb'
- 'ee/lib/gitlab/insights/reducers/count_per_label_reducer.rb'
- 'ee/spec/lib/ee/gitlab/application_context_spec.rb'
- 'ee/spec/models/ee/namespace_spec.rb'
- 'ee/spec/models/sca/license_compliance_spec.rb'
- 'ee/spec/views/admin/dashboard/index.html.haml_spec.rb'
- 'lib/api/entities/project_integration.rb'
- 'lib/api/helpers/packages/conan/api_helpers.rb'
- 'lib/banzai/filter/repository_link_filter.rb'
- 'lib/gitlab/background_migration/update_jira_tracker_data_deployment_type_based_on_url.rb'
- 'lib/gitlab/ci/ansi2html.rb'
- 'lib/gitlab/ci/reports/security/finding.rb'
- 'lib/gitlab/ci/reports/security/identifier.rb'
- 'lib/gitlab/ci/reports/test_suite.rb'
- 'lib/gitlab/database/count/exact_count_strategy.rb'
- 'lib/gitlab/database/migration_helpers.rb'
- 'lib/gitlab/database/obsolete_ignored_columns.rb'
- 'lib/gitlab/issuable_metadata.rb'
- 'lib/gitlab/template/base_template.rb'
- 'lib/gitlab/usage_data.rb'
- 'lib/google_api/cloud_platform/client.rb'
- 'qa/qa/resource/reusable.rb'
- 'scripts/trigger-build.rb'
- 'spec/lib/gitlab/api_authentication/sent_through_builder_spec.rb'
- 'spec/lib/gitlab/conflict/file_spec.rb'
- 'spec/lib/gitlab/import_export/model_configuration_spec.rb'
- 'spec/lib/gitlab/import_export/project/tree_restorer_spec.rb'
- 'spec/lib/google_api/cloud_platform/client_spec.rb'
- 'spec/lib/learn_gitlab/onboarding_spec.rb'
- 'spec/models/event_spec.rb'
- 'spec/presenters/projects/security/configuration_presenter_spec.rb'
- 'spec/support/database/multiple_databases.rb'
- 'spec/support/shared_contexts/services/projects/container_repository/delete_tags_service_shared_context.rb'
- 'spec/support/shared_examples/models/concerns/sanitizable_shared_examples.rb'
- 'spec/views/admin/dashboard/index.html.haml_spec.rb'

View File

@ -0,0 +1,285 @@
---
# Cop supports --auto-correct.
RSpec/ScatteredLet:
# Offense count: 720
# Temporarily disabled due to too many offenses
Enabled: false
Exclude:
- 'ee/spec/features/groups/group_roadmap_spec.rb'
- 'ee/spec/features/merge_trains/two_merge_requests_on_train_spec.rb'
- 'ee/spec/finders/security/pipeline_vulnerabilities_finder_spec.rb'
- 'ee/spec/finders/security/vulnerability_reads_finder_spec.rb'
- 'ee/spec/graphql/mutations/boards/epic_boards/epic_move_list_spec.rb'
- 'ee/spec/graphql/mutations/boards/epics/create_spec.rb'
- 'ee/spec/graphql/mutations/dast_site_profiles/create_spec.rb'
- 'ee/spec/graphql/mutations/merge_requests/accept_spec.rb'
- 'ee/spec/graphql/mutations/releases/update_spec.rb'
- 'ee/spec/graphql/resolvers/security_orchestration/scan_execution_policy_resolver_spec.rb'
- 'ee/spec/graphql/types/boards/board_epic_type_spec.rb'
- 'ee/spec/graphql/types/instance_security_dashboard_type_spec.rb'
- 'ee/spec/helpers/ee/subscribable_banner_helper_spec.rb'
- 'ee/spec/helpers/trial_status_widget_helper_spec.rb'
- 'ee/spec/lib/banzai/reference_parser/iteration_parser_spec.rb'
- 'ee/spec/lib/ee/audit/compliance_framework_changes_auditor_spec.rb'
- 'ee/spec/lib/ee/gitlab/ci/config_spec.rb'
- 'ee/spec/lib/ee/gitlab/email/handler/service_desk_handler_spec.rb'
- 'ee/spec/lib/gitlab/ci/parsers/security/dast_spec.rb'
- 'ee/spec/lib/gitlab/ci/parsers/security/formatters/dependency_list_spec.rb'
- 'ee/spec/lib/gitlab/ci/templates/dast_api_gitlab_ci_yaml_spec.rb'
- 'ee/spec/lib/gitlab/ci/templates/dast_api_latest_gitlab_ci_yaml_spec.rb'
- 'ee/spec/lib/gitlab/cycle_analytics/stage_summary_spec.rb'
- 'ee/spec/lib/gitlab/elastic/bulk_indexer_spec.rb'
- 'ee/spec/lib/gitlab/geo/log_cursor/events/repositories_changed_event_spec.rb'
- 'ee/spec/lib/gitlab/geo/log_cursor/events/repository_updated_event_spec.rb'
- 'ee/spec/lib/gitlab/geo/replication/blob_downloader_spec.rb'
- 'ee/spec/lib/gitlab/git_access_spec.rb'
- 'ee/spec/lib/gitlab/graphql/aggregations/security_orchestration_policies/lazy_dast_profile_aggregate_spec.rb'
- 'ee/spec/lib/gitlab/graphql/aggregations/vulnerability_statistics/lazy_aggregate_spec.rb'
- 'ee/spec/lib/gitlab/insights/reducers/count_per_label_reducer_spec.rb'
- 'ee/spec/lib/gitlab/insights/reducers/label_count_per_period_reducer_spec.rb'
- 'ee/spec/lib/gitlab/usage_data_metrics_spec.rb'
- 'ee/spec/models/analytics/cycle_analytics/group_level_spec.rb'
- 'ee/spec/models/approval_wrapped_any_approver_rule_spec.rb'
- 'ee/spec/models/approvals/scan_finding_wrapped_rule_set_spec.rb'
- 'ee/spec/models/ci/minutes/notification_spec.rb'
- 'ee/spec/models/ci/minutes/quota_spec.rb'
- 'ee/spec/models/ci/pipeline_spec.rb'
- 'ee/spec/models/ee/ci/build_dependencies_spec.rb'
- 'ee/spec/models/ee/namespace/root_storage_size_spec.rb'
- 'ee/spec/models/label_note_spec.rb'
- 'ee/spec/models/sca/license_compliance_spec.rb'
- 'ee/spec/policies/merge_request_policy_spec.rb'
- 'ee/spec/requests/api/graphql/compliance_management/merge_requests/compliance_violations_spec.rb'
- 'ee/spec/requests/api/graphql/group/ci_cd_settings_spec.rb'
- 'ee/spec/requests/api/graphql/group/epic/notes_spec.rb'
- 'ee/spec/requests/api/graphql/group_query_spec.rb'
- 'ee/spec/requests/api/graphql/mutations/boards/epic_boards/epic_move_list_spec.rb'
- 'ee/spec/requests/api/graphql/mutations/incident_management/oncall_rotation/update_spec.rb'
- 'ee/spec/requests/api/graphql/mutations/issues/promote_to_epic_spec.rb'
- 'ee/spec/requests/api/graphql/mutations/security_policy/commit_scan_execution_policy_spec.rb'
- 'ee/spec/requests/api/graphql/project/alert_management/http_integrations_spec.rb'
- 'ee/spec/requests/api/graphql/project/dast_profile_schedule_spec.rb'
- 'ee/spec/requests/api/graphql/project/pipeline/dast_profile_spec.rb'
- 'ee/spec/requests/api/graphql/project/pipelines/dast_profile_spec.rb'
- 'ee/spec/requests/api/internal/base_spec.rb'
- 'ee/spec/requests/api/projects_spec.rb'
- 'ee/spec/requests/api/vulnerability_findings_spec.rb'
- 'ee/spec/requests/git_http_geo_spec.rb'
- 'ee/spec/serializers/status_page/incident_serializer_spec.rb'
- 'ee/spec/services/app_sec/dast/scanner_profiles/update_service_spec.rb'
- 'ee/spec/services/arkose/blocked_users_report_service_spec.rb'
- 'ee/spec/services/arkose/user_verification_service_spec.rb'
- 'ee/spec/services/audit_event_service_spec.rb'
- 'ee/spec/services/audit_events/protected_branch_audit_event_service_spec.rb'
- 'ee/spec/services/ee/issue_links/create_service_spec.rb'
- 'ee/spec/services/epic_issues/create_service_spec.rb'
- 'ee/spec/services/epics/issue_promote_service_spec.rb'
- 'ee/spec/services/gitlab_subscriptions/activate_service_spec.rb'
- 'ee/spec/services/group_saml/saml_provider/create_service_spec.rb'
- 'ee/spec/services/group_saml/saml_provider/update_service_spec.rb'
- 'ee/spec/services/groups/memberships/export_service_spec.rb'
- 'ee/spec/services/incident_management/escalation_policies/create_service_spec.rb'
- 'ee/spec/services/incident_management/oncall_rotations/remove_participant_service_spec.rb'
- 'ee/spec/services/merge_request_approval_settings/update_service_spec.rb'
- 'ee/spec/services/merge_trains/refresh_service_spec.rb'
- 'ee/spec/services/projects/destroy_service_spec.rb'
- 'ee/spec/services/projects/prometheus/alerts/notify_service_spec.rb'
- 'ee/spec/services/quality_management/test_cases/create_service_spec.rb'
- 'ee/spec/services/quick_actions/interpret_service_spec.rb'
- 'ee/spec/services/requirements_management/update_requirement_service_spec.rb'
- 'ee/spec/services/search/group_service_spec.rb'
- 'ee/spec/services/search/project_service_spec.rb'
- 'ee/spec/services/todo_service_spec.rb'
- 'ee/spec/views/shared/_mirror_update_button.html.haml_spec.rb'
- 'ee/spec/views/subscriptions/groups/edit.html.haml_spec.rb'
- 'ee/spec/workers/compliance_management/merge_requests/compliance_violations_worker_spec.rb'
- 'ee/spec/workers/concerns/update_orchestration_policy_configuration_spec.rb'
- 'qa/qa/specs/features/ee/browser_ui/1_manage/group/group_audit_logs_1_spec.rb'
- 'qa/qa/specs/features/ee/browser_ui/1_manage/project/project_audit_logs_spec.rb'
- 'spec/controllers/projects/artifacts_controller_spec.rb'
- 'spec/controllers/projects/deploy_keys_controller_spec.rb'
- 'spec/controllers/projects/environments_controller_spec.rb'
- 'spec/controllers/projects/issues_controller_spec.rb'
- 'spec/controllers/projects/releases/evidences_controller_spec.rb'
- 'spec/controllers/projects/releases_controller_spec.rb'
- 'spec/finders/ci/daily_build_group_report_results_finder_spec.rb'
- 'spec/finders/concerns/finder_with_cross_project_access_spec.rb'
- 'spec/finders/concerns/finder_with_group_hierarchy_spec.rb'
- 'spec/finders/events_finder_spec.rb'
- 'spec/finders/group_projects_finder_spec.rb'
- 'spec/finders/license_template_finder_spec.rb'
- 'spec/frontend/fixtures/pipelines.rb'
- 'spec/graphql/resolvers/commit_pipelines_resolver_spec.rb'
- 'spec/graphql/resolvers/design_management/version_in_collection_resolver_spec.rb'
- 'spec/graphql/resolvers/design_management/versions_resolver_spec.rb'
- 'spec/graphql/types/ci/job_token_scope_type_spec.rb'
- 'spec/helpers/merge_requests_helper_spec.rb'
- 'spec/lib/banzai/filter/references/project_reference_filter_spec.rb'
- 'spec/lib/banzai/filter/references/user_reference_filter_spec.rb'
- 'spec/lib/banzai/filter/upload_link_filter_spec.rb'
- 'spec/lib/banzai/reference_parser/alert_parser_spec.rb'
- 'spec/lib/banzai/reference_parser/commit_parser_spec.rb'
- 'spec/lib/banzai/reference_parser/commit_range_parser_spec.rb'
- 'spec/lib/banzai/reference_parser/external_issue_parser_spec.rb'
- 'spec/lib/banzai/reference_parser/label_parser_spec.rb'
- 'spec/lib/banzai/reference_parser/merge_request_parser_spec.rb'
- 'spec/lib/banzai/reference_parser/milestone_parser_spec.rb'
- 'spec/lib/banzai/reference_parser/project_parser_spec.rb'
- 'spec/lib/banzai/reference_parser/snippet_parser_spec.rb'
- 'spec/lib/banzai/reference_parser/user_parser_spec.rb'
- 'spec/lib/bulk_imports/projects/pipelines/snippets_repository_pipeline_spec.rb'
- 'spec/lib/gitlab/asciidoc/include_processor_spec.rb'
- 'spec/lib/gitlab/auth/ldap/person_spec.rb'
- 'spec/lib/gitlab/auth/saml/auth_hash_spec.rb'
- 'spec/lib/gitlab/background_migration/copy_ci_builds_columns_to_security_scans_spec.rb'
- 'spec/lib/gitlab/background_migration/encrypt_static_object_token_spec.rb'
- 'spec/lib/gitlab/background_migration/legacy_uploads_migrator_spec.rb'
- 'spec/lib/gitlab/background_migration/nullify_orphan_runner_id_on_ci_builds_spec.rb'
- 'spec/lib/gitlab/background_migration/update_jira_tracker_data_deployment_type_based_on_url_spec.rb'
- 'spec/lib/gitlab/ci/config/external/file/artifact_spec.rb'
- 'spec/lib/gitlab/ci/pipeline/chain/helpers_spec.rb'
- 'spec/lib/gitlab/ci/reports/security/vulnerability_reports_comparer_spec.rb'
- 'spec/lib/gitlab/ci/status/stage/factory_spec.rb'
- 'spec/lib/gitlab/ci/variables/builder/group_spec.rb'
- 'spec/lib/gitlab/ci/variables/builder/project_spec.rb'
- 'spec/lib/gitlab/ci/yaml_processor_spec.rb'
- 'spec/lib/gitlab/cycle_analytics/stage_summary_spec.rb'
- 'spec/lib/gitlab/database/background_migration/batched_migration_wrapper_spec.rb'
- 'spec/lib/gitlab/database/migrations/test_batched_background_runner_spec.rb'
- 'spec/lib/gitlab/database/partitioning/partition_manager_spec.rb'
- 'spec/lib/gitlab/database/partitioning_migration_helpers/table_management_helpers_spec.rb'
- 'spec/lib/gitlab/database/postgresql_adapter/empty_query_ping_spec.rb'
- 'spec/lib/gitlab/database/reindexing/grafana_notifier_spec.rb'
- 'spec/lib/gitlab/diff/file_collection/merge_request_diff_batch_spec.rb'
- 'spec/lib/gitlab/diff/formatters/text_formatter_spec.rb'
- 'spec/lib/gitlab/diff/position_spec.rb'
- 'spec/lib/gitlab/diff/position_tracer/image_strategy_spec.rb'
- 'spec/lib/gitlab/diff/position_tracer/line_strategy_spec.rb'
- 'spec/lib/gitlab/diff/suggestion_diff_spec.rb'
- 'spec/lib/gitlab/diff/suggestion_spec.rb'
- 'spec/lib/gitlab/elasticsearch/logs/lines_spec.rb'
- 'spec/lib/gitlab/email/handler/service_desk_handler_spec.rb'
- 'spec/lib/gitlab/error_tracking/processor/context_payload_processor_spec.rb'
- 'spec/lib/gitlab/error_tracking_spec.rb'
- 'spec/lib/gitlab/git/blame_spec.rb'
- 'spec/lib/gitlab/git/diff_collection_spec.rb'
- 'spec/lib/gitlab/git_access_spec.rb'
- 'spec/lib/gitlab/github_import/parallel_scheduling_spec.rb'
- 'spec/lib/gitlab/import_export/group/relation_tree_restorer_spec.rb'
- 'spec/lib/gitlab/import_export/project/export_task_spec.rb'
- 'spec/lib/gitlab/jira_import/issue_serializer_spec.rb'
- 'spec/lib/gitlab/lets_encrypt/client_spec.rb'
- 'spec/lib/gitlab/metrics/dashboard/stages/grafana_formatter_spec.rb'
- 'spec/lib/gitlab/metrics/subscribers/external_http_spec.rb'
- 'spec/lib/gitlab/middleware/memory_report_spec.rb'
- 'spec/lib/gitlab/pagination/gitaly_keyset_pager_spec.rb'
- 'spec/lib/gitlab/pagination/keyset/page_spec.rb'
- 'spec/lib/gitlab/pagination/offset_pagination_spec.rb'
- 'spec/lib/gitlab/patch/database_config_spec.rb'
- 'spec/lib/gitlab/path_regex_spec.rb'
- 'spec/lib/gitlab/prometheus/queries/matched_metric_query_spec.rb'
- 'spec/lib/gitlab/serializer/pagination_spec.rb'
- 'spec/lib/gitlab/sidekiq_middleware/extra_done_log_metadata_spec.rb'
- 'spec/lib/gitlab/sidekiq_middleware/size_limiter/validator_spec.rb'
- 'spec/lib/gitlab/spamcheck/client_spec.rb'
- 'spec/lib/gitlab/template/finders/global_template_finder_spec.rb'
- 'spec/lib/gitlab/tree_summary_spec.rb'
- 'spec/lib/gitlab/usage/service_ping_report_spec.rb'
- 'spec/lib/gitlab/usage_data_metrics_spec.rb'
- 'spec/lib/gitlab/utils/measuring_spec.rb'
- 'spec/lib/gitlab/zentao/client_spec.rb'
- 'spec/lib/peek/views/external_http_spec.rb'
- 'spec/mailers/emails/in_product_marketing_spec.rb'
- 'spec/migrations/20210421163509_schedule_update_jira_tracker_data_deployment_type_based_on_url_spec.rb'
- 'spec/migrations/20220329175119_remove_leftover_ci_job_artifact_deletions_spec.rb'
- 'spec/models/application_record_spec.rb'
- 'spec/models/ci/build_dependencies_spec.rb'
- 'spec/models/ci/pipeline_spec.rb'
- 'spec/models/concerns/issuable_spec.rb'
- 'spec/models/concerns/manual_inverse_association_spec.rb'
- 'spec/models/concerns/noteable_spec.rb'
- 'spec/models/deploy_keys_project_spec.rb'
- 'spec/models/design_management/design_at_version_spec.rb'
- 'spec/models/diff_note_spec.rb'
- 'spec/models/environment_spec.rb'
- 'spec/models/integration_spec.rb'
- 'spec/models/merge_request_diff_spec.rb'
- 'spec/models/merge_request_spec.rb'
- 'spec/models/milestone_spec.rb'
- 'spec/models/push_event_spec.rb'
- 'spec/models/ssh_host_key_spec.rb'
- 'spec/models/user_spec.rb'
- 'spec/models/users/credit_card_validation_spec.rb'
- 'spec/models/wiki_page_spec.rb'
- 'spec/policies/ci/build_policy_spec.rb'
- 'spec/policies/design_management/design_policy_spec.rb'
- 'spec/policies/group_member_policy_spec.rb'
- 'spec/requests/admin/background_migrations_controller_spec.rb'
- 'spec/requests/api/ci/pipeline_schedules_spec.rb'
- 'spec/requests/api/ci/pipelines_spec.rb'
- 'spec/requests/api/commit_statuses_spec.rb'
- 'spec/requests/api/graphql/ci/groups_spec.rb'
- 'spec/requests/api/graphql/ci/pipelines_spec.rb'
- 'spec/requests/api/graphql/mutations/boards/create_spec.rb'
- 'spec/requests/api/graphql/namespace/projects_spec.rb'
- 'spec/requests/api/graphql/project/issue/design_collection/version_spec.rb'
- 'spec/requests/api/graphql/project/issue/design_collection/versions_spec.rb'
- 'spec/requests/api/graphql/project/issue_spec.rb'
- 'spec/requests/api/graphql/project/milestones_spec.rb'
- 'spec/requests/api/graphql/project/pipeline_spec.rb'
- 'spec/requests/api/graphql/project/release_spec.rb'
- 'spec/requests/api/graphql/user/starred_projects_query_spec.rb'
- 'spec/requests/api/issues/get_group_issues_spec.rb'
- 'spec/requests/api/issues/get_project_issues_spec.rb'
- 'spec/requests/api/issues/post_projects_issues_spec.rb'
- 'spec/requests/api/issues/put_projects_issues_spec.rb'
- 'spec/requests/api/merge_requests_spec.rb'
- 'spec/requests/api/notes_spec.rb'
- 'spec/requests/api/project_clusters_spec.rb'
- 'spec/requests/api/project_export_spec.rb'
- 'spec/requests/api/rubygem_packages_spec.rb'
- 'spec/requests/projects/releases_controller_spec.rb'
- 'spec/rubocop/cop/migration/update_column_in_batches_spec.rb'
- 'spec/scripts/pipeline_test_report_builder_spec.rb'
- 'spec/serializers/build_details_entity_spec.rb'
- 'spec/serializers/ci/job_entity_spec.rb'
- 'spec/serializers/merge_requests/pipeline_entity_spec.rb'
- 'spec/services/ci/change_variable_service_spec.rb'
- 'spec/services/ci/change_variables_service_spec.rb'
- 'spec/services/ci/create_downstream_pipeline_service_spec.rb'
- 'spec/services/ci/create_pipeline_service/logger_spec.rb'
- 'spec/services/ci/create_pipeline_service_spec.rb'
- 'spec/services/ci/destroy_pipeline_service_spec.rb'
- 'spec/services/ci/find_exposed_artifacts_service_spec.rb'
- 'spec/services/ci/pipeline_bridge_status_service_spec.rb'
- 'spec/services/commits/cherry_pick_service_spec.rb'
- 'spec/services/design_management/delete_designs_service_spec.rb'
- 'spec/services/design_management/save_designs_service_spec.rb'
- 'spec/services/discussions/capture_diff_note_positions_service_spec.rb'
- 'spec/services/events/destroy_service_spec.rb'
- 'spec/services/git/base_hooks_service_spec.rb'
- 'spec/services/groups/group_links/update_service_spec.rb'
- 'spec/services/jira_import/cloud_users_mapper_service_spec.rb'
- 'spec/services/jira_import/server_users_mapper_service_spec.rb'
- 'spec/services/lfs/push_service_spec.rb'
- 'spec/services/metrics/dashboard/custom_metric_embed_service_spec.rb'
- 'spec/services/metrics/dashboard/dynamic_embed_service_spec.rb'
- 'spec/services/metrics/dashboard/gitlab_alert_embed_service_spec.rb'
- 'spec/services/metrics/dashboard/grafana_metric_embed_service_spec.rb'
- 'spec/services/notification_service_spec.rb'
- 'spec/services/packages/composer/create_package_service_spec.rb'
- 'spec/services/packages/conan/create_package_file_service_spec.rb'
- 'spec/services/packages/debian/create_package_file_service_spec.rb'
- 'spec/services/packages/debian/generate_distribution_key_service_spec.rb'
- 'spec/services/packages/debian/update_distribution_service_spec.rb'
- 'spec/services/projects/lfs_pointers/lfs_download_link_list_service_spec.rb'
- 'spec/services/snippets/create_service_spec.rb'
- 'spec/services/spam/spam_verdict_service_spec.rb'
- 'spec/services/suggestions/create_service_spec.rb'
- 'spec/services/system_notes/design_management_service_spec.rb'
- 'spec/services/system_notes/merge_requests_service_spec.rb'
- 'spec/services/todo_service_spec.rb'
- 'spec/support/shared_examples/graphql/sorted_paginated_query_shared_examples.rb'
- 'spec/tasks/gitlab/artifacts/migrate_rake_spec.rb'
- 'spec/workers/concerns/gitlab/github_import/object_importer_spec.rb'
- 'spec/workers/packages/debian/generate_distribution_worker_spec.rb'

View File

@ -0,0 +1,115 @@
---
# Cop supports --auto-correct.
Style/BarePercentLiterals:
# Offense count: 220
# Temporarily disabled due to too many offenses
Enabled: false
Exclude:
- 'app/models/commit.rb'
- 'app/models/concerns/storage/legacy_namespace.rb'
- 'app/models/integrations/datadog.rb'
- 'app/services/feature_flags/base_service.rb'
- 'app/services/repositories/base_service.rb'
- 'app/services/repositories/destroy_rollback_service.rb'
- 'app/services/repositories/destroy_service.rb'
- 'ee/app/services/jira/jql_builder_service.rb'
- 'ee/lib/ee/gitlab/checks/push_rules/file_size_check.rb'
- 'ee/spec/features/projects/environments/environments_spec.rb'
- 'ee/spec/helpers/subscriptions_helper_spec.rb'
- 'ee/spec/lib/banzai/filter/references/iteration_reference_filter_spec.rb'
- 'ee/spec/lib/gitlab/analytics/cycle_analytics/request_params_spec.rb'
- 'ee/spec/lib/gitlab/status_page/filter/image_filter_spec.rb'
- 'ee/spec/requests/api/ci/jobs_spec.rb'
- 'ee/spec/services/geo/container_repository_sync_spec.rb'
- 'lib/banzai/filter/autolink_filter.rb'
- 'lib/banzai/filter/references/reference_filter.rb'
- 'lib/banzai/filter/spaced_link_filter.rb'
- 'lib/banzai/filter/table_of_contents_filter.rb'
- 'lib/banzai/issuable_extractor.rb'
- 'lib/gitlab/authorized_keys.rb'
- 'lib/gitlab/etag_caching/middleware.rb'
- 'lib/gitlab/etag_caching/router/rails.rb'
- 'lib/gitlab/gl_repository/identifier.rb'
- 'lib/gitlab/import_export/repo_restorer.rb'
- 'lib/kramdown/parser/atlassian_document_format.rb'
- 'lib/tasks/tanuki_emoji.rake'
- 'qa/qa/ee/page/dashboard/projects.rb'
- 'qa/qa/ee/page/group/settings/general.rb'
- 'qa/qa/ee/page/project/issue/show.rb'
- 'qa/qa/ee/page/project/job/show.rb'
- 'qa/qa/ee/page/project/packages/index.rb'
- 'qa/qa/ee/page/project/pipeline/show.rb'
- 'qa/qa/ee/page/project/show.rb'
- 'qa/qa/ee/page/project/snippet/index.rb'
- 'qa/qa/ee/page/project/wiki/show.rb'
- 'qa/qa/page/component/design_management.rb'
- 'qa/qa/page/component/select2.rb'
- 'qa/qa/page/element.rb'
- 'qa/qa/page/file/form.rb'
- 'qa/qa/page/project/web_ide/edit.rb'
- 'qa/qa/resource/events/project.rb'
- 'qa/qa/resource/members.rb'
- 'qa/qa/specs/features/browser_ui/2_plan/email/trigger_email_notification_spec.rb'
- 'qa/qa/specs/features/ee/browser_ui/1_manage/group/group_saml_enforced_sso_new_account_spec.rb'
- 'qa/qa/specs/features/ee/browser_ui/3_create/repository/push_rules_spec.rb'
- 'qa/qa/support/page/logging.rb'
- 'qa/spec/runtime/feature_spec.rb'
- 'scripts/regenerate-schema'
- 'scripts/trigger-build.rb'
- 'spec/controllers/import/fogbugz_controller_spec.rb'
- 'spec/controllers/projects/artifacts_controller_spec.rb'
- 'spec/controllers/projects/design_management/designs/raw_images_controller_spec.rb'
- 'spec/controllers/projects/design_management/designs/resized_image_controller_spec.rb'
- 'spec/features/issues/create_issue_for_discussions_in_merge_request_spec.rb'
- 'spec/features/projects/artifacts/user_downloads_artifacts_spec.rb'
- 'spec/features/projects/badges/coverage_spec.rb'
- 'spec/features/projects/badges/pipeline_badge_spec.rb'
- 'spec/features/projects/issuable_templates_spec.rb'
- 'spec/features/projects/jobs_spec.rb'
- 'spec/features/projects/pipelines/legacy_pipeline_spec.rb'
- 'spec/features/projects/pipelines/legacy_pipelines_spec.rb'
- 'spec/features/projects/pipelines/pipeline_spec.rb'
- 'spec/features/projects/pipelines/pipelines_spec.rb'
- 'spec/features/uploads/user_uploads_avatar_to_group_spec.rb'
- 'spec/features/uploads/user_uploads_avatar_to_profile_spec.rb'
- 'spec/graphql/resolvers/echo_resolver_spec.rb'
- 'spec/helpers/markup_helper_spec.rb'
- 'spec/lib/banzai/filter/autolink_filter_spec.rb'
- 'spec/lib/banzai/filter/external_link_filter_spec.rb'
- 'spec/lib/banzai/filter/image_link_filter_spec.rb'
- 'spec/lib/banzai/filter/references/label_reference_filter_spec.rb'
- 'spec/lib/banzai/filter/references/milestone_reference_filter_spec.rb'
- 'spec/lib/banzai/pipeline/full_pipeline_spec.rb'
- 'spec/lib/banzai/pipeline/plain_markdown_pipeline_spec.rb'
- 'spec/lib/banzai/reference_parser/commit_parser_spec.rb'
- 'spec/lib/banzai/reference_parser/issue_parser_spec.rb'
- 'spec/lib/banzai/reference_parser/merge_request_parser_spec.rb'
- 'spec/lib/gitlab/diff/highlight_spec.rb'
- 'spec/lib/gitlab/error_tracking/stack_trace_highlight_decorator_spec.rb'
- 'spec/lib/gitlab/gfm/reference_rewriter_spec.rb'
- 'spec/lib/gitlab/highlight_spec.rb'
- 'spec/lib/gitlab/pagination/gitaly_keyset_pager_spec.rb'
- 'spec/lib/gitlab/pagination/offset_pagination_spec.rb'
- 'spec/lib/gitlab/prometheus/query_variables_spec.rb'
- 'spec/lib/gitlab/reference_extractor_spec.rb'
- 'spec/lib/gitlab/url_sanitizer_spec.rb'
- 'spec/mailers/emails/releases_spec.rb'
- 'spec/mailers/emails/service_desk_spec.rb'
- 'spec/models/deployment_spec.rb'
- 'spec/models/integrations/drone_ci_spec.rb'
- 'spec/models/integrations/teamcity_spec.rb'
- 'spec/models/project_label_spec.rb'
- 'spec/presenters/snippet_blob_presenter_spec.rb'
- 'spec/requests/api/ci/job_artifacts_spec.rb'
- 'spec/requests/api/deployments_spec.rb'
- 'spec/requests/api/graphql/mutations/snippets/destroy_spec.rb'
- 'spec/rubocop/cop/gitlab/mark_used_feature_flags_spec.rb'
- 'spec/services/prometheus/proxy_variable_substitution_service_spec.rb'
- 'spec/support/banzai/reference_filter_shared_examples.rb'
- 'spec/support/helpers/graphql_helpers.rb'
- 'spec/support/shared_examples/controllers/repository_lfs_file_load_shared_examples.rb'
- 'spec/support/shared_examples/features/resolving_discussions_in_issues_shared_examples.rb'
- 'spec/support/shared_examples/graphql/label_fields.rb'
- 'spec/support/shared_examples/lib/banzai/filters/sanitization_filter_shared_examples.rb'
- 'spec/support_specs/matchers/exceed_query_limit_helpers_spec.rb'
- 'spec/views/layouts/_head.html.haml_spec.rb'

View File

@ -0,0 +1,51 @@
---
# Cop supports --auto-correct.
Style/RescueModifier:
# Offense count: 59
# Temporarily disabled due to too many offenses
Enabled: false
Exclude:
- 'app/controllers/admin/system_info_controller.rb'
- 'app/controllers/users_controller.rb'
- 'app/finders/ci/daily_build_group_report_results_finder.rb'
- 'app/helpers/blob_helper.rb'
- 'app/models/concerns/diff_positionable_note.rb'
- 'app/models/integrations/jira.rb'
- 'app/models/sent_notification.rb'
- 'app/models/todo.rb'
- 'app/services/security/ci_configuration/sast_parser_service.rb'
- 'config/initializers/active_record_data_types.rb'
- 'config/settings.rb'
- 'ee/app/models/license.rb'
- 'ee/lib/ee/gitlab/background_migration/drop_invalid_remediations.rb'
- 'ee/lib/gitlab/geo.rb'
- 'ee/lib/gitlab/geo/health_check.rb'
- 'lib/api/helpers.rb'
- 'lib/feature.rb'
- 'lib/gitlab/current_settings.rb'
- 'lib/gitlab/dependency_linker/cargo_toml_linker.rb'
- 'lib/gitlab/dependency_linker/json_linker.rb'
- 'lib/gitlab/diff/parser.rb'
- 'lib/gitlab/import_export/after_export_strategy_builder.rb'
- 'lib/gitlab/kubernetes.rb'
- 'lib/gitlab/middleware/read_only/controller.rb'
- 'lib/gitlab/process_management.rb'
- 'lib/gitlab/query_limiting/middleware.rb'
- 'lib/gitlab/quick_actions/command_definition.rb'
- 'lib/gitlab/quick_actions/spend_time_and_date_separator.rb'
- 'lib/gitlab/word_diff/segments/diff_hunk.rb'
- 'lib/gitlab/zentao/client.rb'
- 'lib/tasks/gitlab/praefect.rake'
- 'qa/qa/page/component/access_tokens.rb'
- 'qa/qa/page/profile/ssh_keys.rb'
- 'spec/finders/concerns/finder_with_cross_project_access_spec.rb'
- 'spec/lib/gitlab/database/load_balancing/session_spec.rb'
- 'spec/lib/gitlab/database/migrations/instrumentation_spec.rb'
- 'spec/lib/gitlab/email/handler/service_desk_handler_spec.rb'
- 'spec/lib/gitlab/sidekiq_middleware/monitor_spec.rb'
- 'spec/models/concerns/bulk_insert_safe_spec.rb'
- 'spec/models/design_management/version_spec.rb'
- 'spec/models/group_spec.rb'
- 'spec/models/namespace/traversal_hierarchy_spec.rb'
- 'spec/services/design_management/delete_designs_service_spec.rb'
- 'spec/support/shared_examples/lib/gitlab/config/inheritable_shared_examples.rb'

View File

@ -1 +1 @@
60a7383d965aa6a8e69aa2e33a84792cde486cd3
42fab8fc526215f9426bc9f459f9e6da0951c574

View File

@ -1,8 +1,8 @@
import $ from 'jquery';
import { SourceEditorExtension } from '~/editor/extensions/source_editor_extension_base';
import { FileTemplateExtension } from '~/editor/extensions/source_editor_file_template_ext';
import { ToolbarExtension } from '~/editor/extensions/source_editor_toolbar_ext';
import SourceEditor from '~/editor/source_editor';
import { getBlobLanguage } from '~/editor/utils';
import createFlash from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { addEditorMarkdownListeners } from '~/lib/utils/text_markdown';
@ -36,7 +36,7 @@ export default class EditBlob {
import('~/editor/extensions/source_editor_markdown_ext'),
import('~/editor/extensions/source_editor_markdown_livepreview_ext'),
]);
this.editor.use([
this.markdownExtensions = this.editor.use([
{ definition: MarkdownExtension },
{
definition: MarkdownLivePreview,
@ -48,7 +48,6 @@ export default class EditBlob {
message: `${BLOB_EDITOR_ERROR}: ${e}`,
});
}
this.hasMarkdownExtension = true;
addEditorMarkdownListeners(this.editor);
}
@ -58,8 +57,6 @@ export default class EditBlob {
const fileContentEl = document.getElementById('file-content');
const form = document.querySelector('.js-edit-blob-form');
this.hasMarkdownExtension = false;
const rootEditor = new SourceEditor();
this.editor = rootEditor.createInstance({
@ -67,21 +64,29 @@ export default class EditBlob {
blobPath: fileNameEl.value,
blobContent: editorEl.innerText,
});
this.editor.use([{ definition: SourceEditorExtension }, { definition: FileTemplateExtension }]);
this.editor.use([
{ definition: SourceEditorExtension },
{ definition: FileTemplateExtension },
{ definition: ToolbarExtension },
]);
fileNameEl.addEventListener('change', () => {
this.editor.updateModelLanguage(fileNameEl.value);
const newLang = getBlobLanguage(fileNameEl.value);
if (newLang === 'markdown') {
if (!this.hasMarkdownExtension) {
this.fetchMarkdownExtension();
}
}
});
form.addEventListener('submit', () => {
fileContentEl.value = insertFinalNewline(this.editor.getValue());
});
// onDidChangeModelLanguage is part of the native Monaco API
// https://microsoft.github.io/monaco-editor/api/interfaces/monaco.editor.IStandaloneCodeEditor.html#onDidChangeModelLanguage
this.editor.onDidChangeModelLanguage(({ newLanguage = '', oldLanguage = '' }) => {
if (newLanguage === 'markdown') {
this.fetchMarkdownExtension();
} else if (oldLanguage === 'markdown') {
this.editor.unuse(this.markdownExtensions);
}
});
}
initFileSelectors() {

View File

@ -55,8 +55,8 @@ export default {
id="se-toolbar"
class="gl-py-3 gl-px-5 gl-bg-white gl-border-t gl-border-b gl-display-flex gl-justify-content-space-between gl-align-items-center"
>
<template v-for="group in $options.groups">
<gl-button-group v-if="hasGroupItems(group)" :key="group">
<div v-for="group in $options.groups" :key="group">
<gl-button-group v-if="hasGroupItems(group)">
<template v-for="item in getGroupItems(group)">
<source-editor-toolbar-button
:key="item.id"
@ -65,6 +65,6 @@ export default {
/>
</template>
</gl-button-group>
</template>
</div>
</section>
</template>

View File

@ -1,7 +1,5 @@
<script>
import { GlButton, GlTooltipDirective } from '@gitlab/ui';
import updateToolbarItemMutation from '~/editor/graphql/update_item.mutation.graphql';
import getToolbarItemQuery from '~/editor/graphql/get_item.query.graphql';
export default {
name: 'SourceEditorToolbarButton',
@ -20,70 +18,40 @@ export default {
},
},
},
data() {
return {
buttonItem: this.button,
};
},
apollo: {
buttonItem: {
query: getToolbarItemQuery,
variables() {
return {
id: this.button.id,
};
},
update({ item }) {
return item;
},
skip() {
return !this.button.id;
},
},
},
computed: {
icon() {
return this.buttonItem.selected
? this.buttonItem.selectedIcon || this.buttonItem.icon
: this.buttonItem.icon;
return this.button.selected ? this.button.selectedIcon || this.button.icon : this.button.icon;
},
label() {
return this.buttonItem.selected
? this.buttonItem.selectedLabel || this.buttonItem.label
: this.buttonItem.label;
return this.button.selected
? this.button.selectedLabel || this.button.label
: this.button.label;
},
showButton() {
return Object.entries(this.button).length > 0;
},
},
methods: {
clickHandler() {
if (this.buttonItem.onClick) {
this.buttonItem.onClick();
if (this.button.onClick) {
this.button.onClick();
}
this.$apollo.mutate({
mutation: updateToolbarItemMutation,
variables: {
id: this.buttonItem.id,
propsToUpdate: {
selected: !this.buttonItem.selected,
},
},
});
this.$emit('click');
},
},
};
</script>
<template>
<div>
<gl-button
v-gl-tooltip.hover
:category="buttonItem.category"
:variant="buttonItem.variant"
type="button"
:selected="buttonItem.selected"
:icon="icon"
:title="label"
:aria-label="label"
@click="clickHandler"
/>
</div>
<gl-button
v-if="showButton"
v-gl-tooltip.hover
:category="button.category"
:variant="button.variant"
type="button"
:selected="button.selected"
:icon="icon"
:title="label"
:aria-label="label"
@click="clickHandler"
/>
</template>

View File

@ -0,0 +1,53 @@
import produce from 'immer';
import Vue from 'vue';
import VueApollo from 'vue-apollo';
import typeDefs from '~/editor/graphql/typedefs.graphql';
import getToolbarItemsQuery from '~/editor/graphql/get_items.query.graphql';
import createDefaultClient from '~/lib/graphql';
Vue.use(VueApollo);
const resolvers = {
Mutation: {
addToolbarItems: (_, { items = [] }, { cache }) => {
const itemsSourceData = cache.readQuery({ query: getToolbarItemsQuery });
const data = produce(itemsSourceData, (draftData) => {
const existingNodes = draftData?.items?.nodes || [];
draftData.items = {
nodes: Array.isArray(items) ? [...existingNodes, ...items] : [...existingNodes, items],
};
});
cache.writeQuery({ query: getToolbarItemsQuery, data });
},
removeToolbarItems: (_, { ids }, { cache }) => {
const sourceData = cache.readQuery({ query: getToolbarItemsQuery });
const {
items: { nodes },
} = sourceData;
const data = produce(sourceData, (draftData) => {
draftData.items.nodes = nodes.filter((item) => !ids.includes(item.id));
});
cache.writeQuery({ query: getToolbarItemsQuery, data });
},
updateToolbarItem: (_, { id, propsToUpdate }, { cache }) => {
const itemSourceData = cache.readQuery({ query: getToolbarItemsQuery });
const data = produce(itemSourceData, (draftData) => {
const existingNodes = draftData?.items?.nodes || [];
draftData.items = {
nodes: existingNodes.map((item) => {
return item.id === id ? { ...item, ...propsToUpdate } : item;
}),
};
});
cache.writeQuery({ query: getToolbarItemsQuery, data });
},
},
};
const defaultClient = createDefaultClient(resolvers, { typeDefs });
export const apolloProvider = new VueApollo({
defaultClient,
});

View File

@ -1,5 +1,5 @@
import { DEFAULT_DEBOUNCE_AND_THROTTLE_MS } from '~/lib/utils/constants';
import { s__ } from '~/locale';
import { s__, __ } from '~/locale';
export const URI_PREFIX = 'gitlab';
export const CONTENT_UPDATE_DEBOUNCE = DEFAULT_DEBOUNCE_AND_THROTTLE_MS;
@ -57,5 +57,8 @@ export const EXTENSION_CI_SCHEMA_FILE_NAME_MATCH = '.gitlab-ci.yml';
export const EXTENSION_MARKDOWN_PREVIEW_PANEL_CLASS = 'md';
export const EXTENSION_MARKDOWN_PREVIEW_PANEL_PARENT_CLASS = 'source-editor-preview';
export const EXTENSION_MARKDOWN_PREVIEW_ACTION_ID = 'markdown-preview';
export const EXTENSION_MARKDOWN_PREVIEW_HIDE_ACTION_ID = 'markdown-preview-hide';
export const EXTENSION_MARKDOWN_PREVIEW_PANEL_WIDTH = 0.5; // 50% of the width
export const EXTENSION_MARKDOWN_PREVIEW_UPDATE_DELAY = 250; // ms
export const EXTENSION_MARKDOWN_PREVIEW_LABEL = __('Preview Markdown');
export const EXTENSION_MARKDOWN_HIDE_PREVIEW_LABEL = __('Hide Live Preview');

View File

@ -3,14 +3,17 @@ import { BLOB_PREVIEW_ERROR } from '~/blob_edit/constants';
import createFlash from '~/flash';
import { sanitize } from '~/lib/dompurify';
import axios from '~/lib/utils/axios_utils';
import { __ } from '~/locale';
import syntaxHighlight from '~/syntax_highlight';
import {
EXTENSION_MARKDOWN_PREVIEW_PANEL_CLASS,
EXTENSION_MARKDOWN_PREVIEW_ACTION_ID,
EXTENSION_MARKDOWN_PREVIEW_HIDE_ACTION_ID,
EXTENSION_MARKDOWN_PREVIEW_PANEL_WIDTH,
EXTENSION_MARKDOWN_PREVIEW_PANEL_PARENT_CLASS,
EXTENSION_MARKDOWN_PREVIEW_UPDATE_DELAY,
EXTENSION_MARKDOWN_PREVIEW_LABEL,
EXTENSION_MARKDOWN_HIDE_PREVIEW_LABEL,
EDITOR_TOOLBAR_RIGHT_GROUP,
} from '../constants';
const fetchPreview = (text, previewMarkdownPath) => {
@ -41,31 +44,58 @@ export class EditorMarkdownPreviewExtension {
onSetup(instance, setupOptions) {
this.preview = {
el: undefined,
action: undefined,
actions: {
preview: undefined,
hide: undefined,
},
shown: false,
modelChangeListener: undefined,
path: setupOptions.previewMarkdownPath,
actionShowPreviewCondition: instance.createContextKey('toggleLivePreview', true),
};
this.toolbarButtons = [];
this.setupPreviewAction(instance);
if (instance.toolbar) {
this.setupToolbar(instance);
}
}
instance.getModel().onDidChangeLanguage(({ newLanguage, oldLanguage } = {}) => {
if (newLanguage === 'markdown' && oldLanguage !== newLanguage) {
instance.setupPreviewAction();
} else {
instance.cleanup();
}
});
onBeforeUnuse(instance) {
this.cleanup(instance);
const ids = this.toolbarButtons.map((item) => item.id);
if (instance.toolbar) {
instance.toolbar.removeItems(ids);
}
}
instance.onDidChangeModel(() => {
const model = instance.getModel();
if (model) {
const { language } = model.getLanguageIdentifier();
instance.cleanup();
if (language === 'markdown') {
instance.setupPreviewAction();
}
}
});
cleanup(instance) {
if (this.preview.modelChangeListener) {
this.preview.modelChangeListener.dispose();
}
this.preview.actions.preview.dispose();
this.preview.actions.hide.dispose();
if (this.preview.shown) {
this.togglePreviewPanel(instance);
this.togglePreviewLayout(instance);
}
this.preview.shown = false;
}
setupToolbar(instance) {
this.toolbarButtons = [
{
id: EXTENSION_MARKDOWN_PREVIEW_ACTION_ID,
label: EXTENSION_MARKDOWN_PREVIEW_LABEL,
icon: 'live-preview',
selected: false,
group: EDITOR_TOOLBAR_RIGHT_GROUP,
category: 'primary',
selectedLabel: EXTENSION_MARKDOWN_HIDE_PREVIEW_LABEL,
onClick: () => instance.togglePreview(),
},
];
instance.toolbar.addItems(this.toolbarButtons);
}
togglePreviewLayout(instance) {
@ -103,22 +133,33 @@ export class EditorMarkdownPreviewExtension {
setupPreviewAction(instance) {
if (instance.getAction(EXTENSION_MARKDOWN_PREVIEW_ACTION_ID)) return;
this.preview.action = instance.addAction({
id: EXTENSION_MARKDOWN_PREVIEW_ACTION_ID,
label: __('Preview Markdown'),
const actionBasis = {
keybindings: [
// eslint-disable-next-line no-bitwise,no-undef
monaco.KeyMod.chord(monaco.KeyMod.CtrlCmd | monaco.KeyMod.Shift | monaco.KeyCode.KEY_P),
],
contextMenuGroupId: 'navigation',
contextMenuOrder: 1.5,
// Method that will be executed when the action is triggered.
// @param ed The editor instance is passed in as a convenience
run(inst) {
inst.togglePreview();
},
};
this.preview.actions.preview = instance.addAction({
...actionBasis,
id: EXTENSION_MARKDOWN_PREVIEW_ACTION_ID,
label: EXTENSION_MARKDOWN_PREVIEW_LABEL,
precondition: 'toggleLivePreview',
});
this.preview.actions.hide = instance.addAction({
...actionBasis,
id: EXTENSION_MARKDOWN_PREVIEW_HIDE_ACTION_ID,
label: EXTENSION_MARKDOWN_HIDE_PREVIEW_LABEL,
precondition: '!toggleLivePreview',
});
}
@ -126,18 +167,6 @@ export class EditorMarkdownPreviewExtension {
return {
markdownPreview: this.preview,
cleanup: (instance) => {
if (this.preview.modelChangeListener) {
this.preview.modelChangeListener.dispose();
}
this.preview.action.dispose();
if (this.preview.shown) {
this.togglePreviewPanel(instance);
this.togglePreviewLayout(instance);
}
this.preview.shown = false;
},
fetchPreview: (instance) => this.fetchPreview(instance),
setupPreviewAction: (instance) => this.setupPreviewAction(instance),
@ -149,6 +178,8 @@ export class EditorMarkdownPreviewExtension {
this.togglePreviewLayout(instance);
this.togglePreviewPanel(instance);
this.preview.actionShowPreviewCondition.set(!this.preview.actionShowPreviewCondition.get());
if (!this.preview?.shown) {
this.preview.modelChangeListener = instance.onDidChangeModelContent(
debounce(
@ -161,6 +192,11 @@ export class EditorMarkdownPreviewExtension {
}
this.preview.shown = !this.preview?.shown;
if (instance.toolbar) {
instance.toolbar.updateItem(EXTENSION_MARKDOWN_PREVIEW_ACTION_ID, {
selected: this.preview.shown,
});
}
},
};
}

View File

@ -0,0 +1,98 @@
import Vue from 'vue';
import getToolbarItemsQuery from '~/editor/graphql/get_items.query.graphql';
import removeToolbarItemsMutation from '~/editor/graphql/remove_items.mutation.graphql';
import updateToolbarItemMutation from '~/editor/graphql/update_item.mutation.graphql';
import addToolbarItemsMutation from '~/editor/graphql/add_items.mutation.graphql';
import SourceEditorToolbar from '~/editor/components/source_editor_toolbar.vue';
import { apolloProvider } from '~/editor/components/source_editor_toolbar_graphql';
const client = apolloProvider.defaultClient;
export class ToolbarExtension {
/**
* A required getter returning the extension's name
* We have to provide it for every extension instead of relying on the built-in
* `name` prop because the prop does not survive the webpack's minification
* and the name mangling.
* @returns {string}
*/
static get extensionName() {
return 'ToolbarExtension';
}
/**
* THE LIFE-CYCLE CALLBACKS
*/
/**
* Is called before the extension gets used by an instance,
* Use `onSetup` to setup Monaco directly:
* actions, keystrokes, update options, etc.
* Is called only once before the extension gets registered
*
* @param { Object } [instance] The Source Editor instance
* @param { Object } [setupOptions] The setupOptions object
*/
// eslint-disable-next-line class-methods-use-this
onSetup(instance, setupOptions) {
const el = setupOptions?.el || document.getElementById('editor-toolbar');
ToolbarExtension.setupVue(el);
}
static setupVue(el) {
client.cache.writeQuery({ query: getToolbarItemsQuery, data: { items: { nodes: [] } } });
const ToolbarComponent = Vue.extend(SourceEditorToolbar);
const toolbar = new ToolbarComponent({
el,
apolloProvider,
});
toolbar.$mount();
}
/**
* The public API of the extension: these are the methods that will be exposed
* to the end user
* @returns {Object}
*/
// eslint-disable-next-line class-methods-use-this
provides() {
return {
toolbar: {
getItem: (id) => {
const items = client.readQuery({ query: getToolbarItemsQuery })?.items?.nodes || [];
return items.find((item) => item.id === id);
},
getAllItems: () => {
return client.readQuery({ query: getToolbarItemsQuery })?.items?.nodes || [];
},
addItems: (items = []) => {
return client.mutate({
mutation: addToolbarItemsMutation,
variables: {
items,
},
});
},
removeItems: (ids = []) => {
client.mutate({
mutation: removeToolbarItemsMutation,
variables: {
ids,
},
});
},
updateItem: (id = '', propsToUpdate = {}) => {
if (id) {
client.mutate({
mutation: updateToolbarItemMutation,
variables: {
id,
propsToUpdate,
},
});
}
},
},
};
}
}

View File

@ -0,0 +1,3 @@
mutation addItems($items: [Item]) {
addToolbarItems(items: $items) @client
}

View File

@ -1,9 +0,0 @@
query ToolbarItem($id: String!) {
item(id: $id) @client {
id
label
icon
selected
group
}
}

View File

@ -0,0 +1,3 @@
mutation removeToolbarItems($ids: [ID!]) {
removeToolbarItems(ids: $ids) @client
}

View File

@ -0,0 +1,23 @@
type Item {
id: ID!
label: String!
icon: String
selected: Boolean
group: Int!
category: String
selectedLabel: String
}
type Items {
nodes: [Item]!
}
extend type Query {
items: Items
}
extend type Mutation {
updateToolbarItem(id: ID!, propsToUpdate: Item!): LocalErrors
removeToolbarItems(ids: [ID!]): LocalErrors
addToolbarItems(items: [Item]): LocalErrors
}

View File

@ -1,3 +1,3 @@
mutation updateItem($id: String!, $propsToUpdate: Item!) {
mutation updateItem($id: ID!, $propsToUpdate: Item!) {
updateToolbarItem(id: $id, propsToUpdate: $propsToUpdate) @client
}

View File

@ -207,7 +207,7 @@ const createAlert = function createAlert({
});
};
/*
/**
* Flash banner supports different types of Flash configurations
* along with ability to provide actionConfig which can be used to show
* additional action or link on banner next to message
@ -223,6 +223,7 @@ const createAlert = function createAlert({
* @param {Boolean} options.fadeTransition Boolean to determine whether to fade the alert out
* @param {Boolean} options.captureError Boolean to determine whether to send error to Sentry
* @param {Object} options.error Error to be captured in Sentry
* @deprecated Use `createAlert` instead. See https://gitlab.com/gitlab-org/gitlab/-/issues/362334.
*/
const createFlash = function createFlash({
message,

View File

@ -1,8 +1,13 @@
import { debounce } from 'lodash';
import createFlash from '~/flash';
import { __ } from '~/locale';
import { getGroupPathAvailability } from '~/rest_api';
import axios from '~/lib/utils/axios_utils';
import { slugify } from './lib/utils/text_utility';
const DEBOUNCE_TIMEOUT_DURATION = 1000;
export default class Group {
constructor() {
this.groupPaths = Array.from(document.querySelectorAll('.js-autofill-group-path'));
@ -10,7 +15,11 @@ export default class Group {
this.parentId = document.getElementById('group_parent_id');
this.updateHandler = this.update.bind(this);
this.resetHandler = this.reset.bind(this);
this.updateGroupPathSlugHandler = this.updateGroupPathSlug.bind(this);
this.updateGroupPathSlugHandler = debounce(
this.updateGroupPathSlug.bind(this),
DEBOUNCE_TIMEOUT_DURATION,
);
this.currentApiRequestController = null;
this.groupNames.forEach((groupName) => {
groupName.addEventListener('keyup', this.updateHandler);
@ -44,13 +53,23 @@ export default class Group {
});
}
updateGroupPathSlug({ currentTarget: { value } = '' } = {}) {
const slug = this.groupPaths[0]?.value || slugify(value);
updateGroupPathSlug({ target: { value } = '' } = {}) {
if (this.currentApiRequestController !== null) {
this.currentApiRequestController.abort();
}
this.currentApiRequestController = new AbortController();
const slug = slugify(value);
if (!slug) return;
getGroupPathAvailability(slug, this.parentId?.value)
getGroupPathAvailability(slug, this.parentId?.value, {
signal: this.currentApiRequestController.signal,
})
.then(({ data }) => data)
.then(({ exists, suggests }) => {
this.currentApiRequestController = null;
if (exists && suggests.length) {
const [suggestedSlug] = suggests;
@ -63,10 +82,14 @@ export default class Group {
});
}
})
.catch(() =>
.catch((error) => {
if (axios.isCancel(error)) {
return;
}
createFlash({
message: __('An error occurred while checking group path. Please refresh and try again.'),
}),
);
});
});
}
}

View File

@ -90,9 +90,16 @@ export default {
return this.getUserData.id;
},
commentButtonTitle() {
return this.noteType === constants.COMMENT
? this.$options.i18n.comment
: this.$options.i18n.startThread;
const { comment, internalComment, startThread, startInternalThread } = this.$options.i18n;
if (this.getNoteableData.confidential || this.noteIsConfidential) {
return this.noteType === constants.COMMENT ? internalComment : startInternalThread;
}
return this.noteType === constants.COMMENT ? comment : startThread;
},
textareaPlaceholder() {
return this.getNoteableData.confidential || this.noteIsConfidential
? this.$options.i18n.bodyPlaceholderInternal
: this.$options.i18n.bodyPlaceholder;
},
discussionsRequireResolution() {
return this.getNoteableData.noteableType === constants.MERGE_REQUEST_NOTEABLE_TYPE;
@ -371,7 +378,7 @@ export default {
data-testid="comment-field"
data-supports-quick-actions="true"
:aria-label="$options.i18n.comment"
:placeholder="$options.i18n.bodyPlaceholder"
:placeholder="textareaPlaceholder"
@keydown.up="editCurrentUserLastNote()"
@keydown.meta.enter="handleEnter()"
@keydown.ctrl.enter="handleEnter()"
@ -419,6 +426,7 @@ export default {
class="gl-mr-3"
:disabled="disableSubmitButton"
:tracking-label="trackingLabel"
:is-internal-note="noteIsConfidential"
:noteable-display-name="noteableDisplayName"
:discussions-require-resolution="discussionsRequireResolution"
@click="handleSave"

View File

@ -32,6 +32,11 @@ export default {
required: false,
default: false,
},
isInternalNote: {
type: Boolean,
required: false,
default: false,
},
noteableDisplayName: {
type: String,
required: true,
@ -48,18 +53,43 @@ export default {
isNoteTypeDiscussion() {
return this.noteType === constants.DISCUSSION;
},
dropdownCommentButtonTitle() {
const { comment, internalComment } = this.$options.i18n.submitButton;
return this.isInternalNote ? internalComment : comment;
},
dropdownStartThreadButtonTitle() {
const { startThread, startInternalThread } = this.$options.i18n.submitButton;
return this.isInternalNote ? startInternalThread : startThread;
},
commentButtonTitle() {
return this.noteType === constants.COMMENT
? this.$options.i18n.comment
: this.$options.i18n.startThread;
const { comment, internalComment, startThread, startInternalThread } = this.$options.i18n;
if (this.isInternalNote) {
return this.noteType === constants.COMMENT ? internalComment : startInternalThread;
}
return this.noteType === constants.COMMENT ? comment : startThread;
},
startDiscussionDescription() {
return this.discussionsRequireResolution
? this.$options.i18n.discussionThatNeedsResolution
: this.$options.i18n.discussion;
const {
discussionThatNeedsResolution,
internalDiscussionThatNeedsResolution,
discussion,
internalDiscussion,
} = this.$options.i18n;
if (this.isInternalNote) {
return this.discussionsRequireResolution
? internalDiscussionThatNeedsResolution
: internalDiscussion;
}
return this.discussionsRequireResolution ? discussionThatNeedsResolution : discussion;
},
commentDescription() {
return sprintf(this.$options.i18n.submitButton.commentHelp, {
const { commentHelp, internalCommentHelp } = this.$options.i18n.submitButton;
return sprintf(this.isInternalNote ? internalCommentHelp : commentHelp, {
noteableDisplayName: this.noteableDisplayName,
});
},
@ -101,7 +131,7 @@ export default {
:is-checked="isNoteTypeComment"
@click.stop.prevent="setNoteTypeToComment"
>
<strong>{{ $options.i18n.submitButton.comment }}</strong>
<strong>{{ dropdownCommentButtonTitle }}</strong>
<p class="gl-m-0">{{ commentDescription }}</p>
</gl-dropdown-item>
<gl-dropdown-divider />
@ -111,7 +141,7 @@ export default {
data-qa-selector="discussion_menu_item"
@click.stop.prevent="setNoteTypeToDiscussion"
>
<strong>{{ $options.i18n.submitButton.startThread }}</strong>
<strong>{{ dropdownStartThreadButtonTitle }}</strong>
<p class="gl-m-0">{{ startDiscussionDescription }}</p>
</gl-dropdown-item>
</gl-dropdown>

View File

@ -4,6 +4,7 @@ import { GlSafeHtmlDirective } from '@gitlab/ui';
import { escape } from 'lodash';
import { mapActions, mapGetters, mapState } from 'vuex';
import { __ } from '~/locale';
import '~/behaviors/markdown/render_gfm';
import Suggestions from '~/vue_shared/components/markdown/suggestions.vue';
import autosave from '../mixins/autosave';
@ -69,6 +70,9 @@ export default {
noteBody() {
return this.note.note;
},
saveButtonTitle() {
return this.note.confidential ? __('Save internal note') : __('Save comment');
},
hasSuggestion() {
return this.note.suggestions && this.note.suggestions.length;
},
@ -180,6 +184,7 @@ export default {
:note-id="note.id"
:line="line"
:note="note"
:save-button-title="saveButtonTitle"
:help-page-path="helpPagePath"
:discussion="discussion"
:resolve-discussion="note.resolve_discussion"

View File

@ -8,9 +8,11 @@ import markdownField from '~/vue_shared/components/markdown/field.vue';
import eventHub from '../event_hub';
import issuableStateMixin from '../mixins/issuable_state';
import resolvable from '../mixins/resolvable';
import { COMMENT_FORM } from '../i18n';
import CommentFieldLayout from './comment_field_layout.vue';
export default {
i18n: COMMENT_FORM,
name: 'NoteForm',
components: {
markdownField,
@ -133,6 +135,11 @@ export default {
.some((n) => n.current_user?.can_resolve_discussion) || this.isDraft
);
},
textareaPlaceholder() {
return this.discussionNote?.confidential
? this.$options.i18n.bodyPlaceholderInternal
: this.$options.i18n.bodyPlaceholder;
},
noteHash() {
if (this.noteId) {
return `#note_${this.noteId}`;
@ -350,7 +357,7 @@ export default {
data-qa-selector="reply_field"
dir="auto"
:aria-label="__('Reply to comment')"
:placeholder="__('Write a comment or drag your files here…')"
:placeholder="textareaPlaceholder"
@keydown.meta.enter="handleKeySubmit()"
@keydown.ctrl.enter="handleKeySubmit()"
@keydown.exact.up="editMyLastNote()"

View File

@ -1,6 +1,7 @@
<script>
import {
GlIcon,
GlBadge,
GlLoadingIcon,
GlTooltipDirective,
GlSafeHtmlDirective as SafeHtml,
@ -10,8 +11,6 @@ import { __, s__ } from '~/locale';
import timeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
import UserNameWithStatus from '~/sidebar/components/assignees/user_name_with_status.vue';
import { NOTEABLE_TYPE_MAPPING } from '../constants';
export default {
safeHtmlConfig: { ADD_TAGS: ['gl-emoji'] },
components: {
@ -19,6 +18,7 @@ export default {
GitlabTeamMemberBadge: () =>
import('ee_component/vue_shared/components/user_avatar/badges/gitlab_team_member_badge.vue'),
GlIcon,
GlBadge,
GlLoadingIcon,
UserNameWithStatus,
},
@ -111,13 +111,7 @@ export default {
return this.author.name;
},
noteConfidentialityTooltip() {
if (
this.noteableType === NOTEABLE_TYPE_MAPPING.Issue ||
this.noteableType === NOTEABLE_TYPE_MAPPING.MergeRequest
) {
return s__('Notes|This comment is confidential and only visible to project members');
}
return s__('Notes|This comment is confidential and only visible to group members');
return s__('Notes|This internal note will always remain confidential');
},
},
mounted() {
@ -236,15 +230,16 @@ export default {
</a>
<time-ago-tooltip v-else ref="noteTimestamp" :time="createdAt" tooltip-placement="bottom" />
</template>
<gl-icon
<gl-badge
v-if="isConfidential"
v-gl-tooltip:tooltipcontainer.bottom
data-testid="confidentialIndicator"
name="eye-slash"
:size="16"
data-testid="internalNoteIndicator"
variant="warning"
size="sm"
:title="noteConfidentialityTooltip"
class="gl-ml-1 gl-text-orange-700 align-middle"
/>
>
{{ __('Internal note') }}
</gl-badge>
<slot name="extra-controls"></slot>
<gl-loading-icon
v-if="showSpinner"

View File

@ -7,7 +7,7 @@ import { clearDraft, getDiscussionReplyKey } from '~/lib/utils/autosave';
import { isLoggedIn } from '~/lib/utils/common_utils';
import { confirmAction } from '~/lib/utils/confirm_via_gl_modal/confirm_via_gl_modal';
import { ignoreWhilePending } from '~/lib/utils/ignore_while_pending';
import { s__, __ } from '~/locale';
import { s__, __, sprintf } from '~/locale';
import diffLineNoteFormMixin from '~/notes/mixins/diff_line_note_form';
import TimelineEntryItem from '~/vue_shared/components/notes/timeline_entry_item.vue';
import userAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue';
@ -95,6 +95,9 @@ export default {
isLoggedIn() {
return isLoggedIn();
},
commentType() {
return this.discussion.confidential ? __('internal note') : __('comment');
},
autosaveKey() {
return getDiscussionReplyKey(this.firstNote.noteable_type, this.discussion.id);
},
@ -104,6 +107,9 @@ export default {
firstNote() {
return this.discussion.notes.slice(0, 1)[0];
},
saveButtonTitle() {
return this.discussion.confidential ? __('Reply internally') : __('Comment');
},
shouldShowJumpToNextDiscussion() {
return this.showJumpToNextDiscussion(this.discussionsByDiffOrder ? 'diff' : 'discussion');
},
@ -174,7 +180,10 @@ export default {
},
cancelReplyForm: ignoreWhilePending(async function cancelReplyForm(shouldConfirm, isDirty) {
if (shouldConfirm && isDirty) {
const msg = s__('Notes|Are you sure you want to cancel creating this comment?');
const msg = sprintf(
s__('Notes|Are you sure you want to cancel creating this %{commentType}?'),
{ commentType: this.commentType },
);
const confirmed = await confirmAction(msg, {
primaryBtnText: __('Discard changes'),
@ -311,7 +320,7 @@ export default {
ref="noteForm"
:discussion="discussion"
:line="diffLine"
save-button-title="Comment"
:save-button-title="saveButtonTitle"
:autosave-key="autosaveKey"
@handleFormUpdateAddToReview="addReplyToReview"
@handleFormUpdate="saveReply"

View File

@ -108,6 +108,9 @@ export default {
author() {
return this.note.author;
},
commentType() {
return this.note.confidential ? __('internal note') : __('comment');
},
classNameBindings() {
return {
[`note-row-${this.note.id}`]: true,
@ -246,14 +249,19 @@ export default {
this.$emit('handleEdit');
},
async deleteHandler() {
const typeOfComment = this.note.isDraft ? __('pending comment') : __('comment');
let { commentType } = this;
const msg = sprintf(__('Are you sure you want to delete this %{typeOfComment}?'), {
typeOfComment,
if (this.note.isDraft) {
// Draft internal notes (i.e. MR review comments) are not supported.
commentType = __('pending comment');
}
const msg = sprintf(__('Are you sure you want to delete this %{commentType}?'), {
commentType,
});
const confirmed = await confirmAction(msg, {
primaryBtnVariant: 'danger',
primaryBtnText: __('Delete Comment'),
primaryBtnText: this.note.confidential ? __('Delete Internal Note') : __('Delete Comment'),
});
if (confirmed) {
@ -356,7 +364,9 @@ export default {
isDirty,
}) {
if (shouldConfirm && isDirty) {
const msg = __('Are you sure you want to cancel editing this comment?');
const msg = sprintf(__('Are you sure you want to cancel editing this %{commentType}?'), {
commentType: this.commentType,
});
const confirmed = await confirmAction(msg, {
primaryBtnText: __('Cancel editing'),
primaryBtnVariant: 'danger',

View File

@ -6,19 +6,26 @@ export const COMMENT_FORM = {
),
note: __('Note'),
comment: __('Comment'),
internalComment: __('Add internal note'),
issue: __('issue'),
startThread: __('Start thread'),
startInternalThread: __('Start internal thread'),
mergeRequest: __('merge request'),
epic: __('epic'),
bodyPlaceholder: __('Write a comment or drag your files here…'),
confidential: s__('Notes|Make this comment confidential'),
bodyPlaceholderInternal: __('Write an internal note or drag your files here…'),
confidential: s__('Notes|Make this an internal note'),
confidentialVisibility: s__(
'Notes|Confidential comments are only visible to members with the role of Reporter or higher',
'Notes|Internal notes are only visible to the author, assignees, and members with the role of Reporter or higher',
),
discussionThatNeedsResolution: __(
'Discuss a specific suggestion or question that needs to be resolved.',
),
internalDiscussionThatNeedsResolution: __(
'Discuss a specific suggestion or question internally that needs to be resolved.',
),
discussion: __('Discuss a specific suggestion or question.'),
internalDiscussion: __('Discuss a specific suggestion or question internally.'),
actionButtonWithNote: __('%{actionText} & %{openOrClose} %{noteable}'),
actionButton: {
withNote: {
@ -32,7 +39,10 @@ export const COMMENT_FORM = {
},
submitButton: {
startThread: __('Start thread'),
startInternalThread: __('Start internal thread'),
comment: __('Comment'),
internalComment: __('Add internal note'),
commentHelp: __('Add a general comment to this %{noteableDisplayName}.'),
internalCommentHelp: __('Add a confidential internal note to this %{noteableDisplayName}.'),
},
};

View File

@ -90,7 +90,7 @@ const createStatusMessage = ({ reportType, status, total }) => {
if (status) {
message = __('%{reportType} %{status}');
} else if (!total) {
message = __('%{reportType} detected %{totalStart}no%{totalEnd} new vulnerabilities.');
message = __('%{reportType} detected no %{totalStart}new%{totalEnd} vulnerabilities.');
} else {
message = __(
'%{reportType} detected %{totalStart}%{total}%{totalEnd} potential %{vulnMessage}',

View File

@ -4,6 +4,7 @@ class Admin::LabelsController < Admin::ApplicationController
before_action :set_label, only: [:show, :edit, :update, :destroy]
feature_category :team_planning
urgency :low
def index
@labels = Label.templates.page(params[:page])

View File

@ -13,6 +13,7 @@ class AutocompleteController < ApplicationController
feature_category :continuous_delivery, [:deploy_keys_with_owners]
urgency :low, [:merge_request_target_branches, :deploy_keys_with_owners, :users]
urgency :low, [:award_emojis]
urgency :medium, [:projects]
def users

View File

@ -22,6 +22,7 @@ module Boards
before_action :can_move_issues?, only: [:bulk_move]
feature_category :team_planning
urgency :low
def index
list_service = Boards::Issues::ListService.new(board_parent, current_user, filter_params)

View File

@ -9,6 +9,7 @@ module Boards
skip_before_action :authenticate_user!, only: [:index]
feature_category :team_planning
urgency :low
def index
lists = Boards::Lists::ListService.new(board.resource_parent, current_user).execute(board)

View File

@ -2,6 +2,7 @@
class Dashboard::LabelsController < Dashboard::ApplicationController
feature_category :team_planning
urgency :low
def index
respond_to do |format|

View File

@ -5,6 +5,7 @@ class Dashboard::MilestonesController < Dashboard::ApplicationController
before_action :groups, only: :index
feature_category :team_planning
urgency :low
def index
respond_to do |format|

View File

@ -9,6 +9,7 @@ class Dashboard::TodosController < Dashboard::ApplicationController
before_action :find_todos, only: [:index, :destroy_all]
feature_category :team_planning
urgency :low
def index
@sort = params[:sort]

View File

@ -19,6 +19,7 @@ class DashboardController < Dashboard::ApplicationController
feature_category :code_review, [:merge_requests]
urgency :low, [:merge_requests, :activity]
urgency :low, [:issues, :issues_calendar]
def activity
respond_to do |format|

View File

@ -5,6 +5,7 @@ class Groups::AutocompleteSourcesController < Groups::ApplicationController
feature_category :team_planning, [:issues, :labels, :milestones, :commands]
feature_category :code_review, [:merge_requests]
urgency :low, [:issues, :labels, :milestones, :commands]
urgency :low, [:merge_requests]
def members

View File

@ -16,6 +16,7 @@ class Groups::BoardsController < Groups::ApplicationController
end
feature_category :team_planning
urgency :low
private

View File

@ -2,6 +2,7 @@
class Groups::Crm::ContactsController < Groups::ApplicationController
feature_category :team_planning
urgency :low
before_action :validate_root_group!
before_action :authorize_read_crm_contact!

View File

@ -2,6 +2,7 @@
class Groups::Crm::OrganizationsController < Groups::ApplicationController
feature_category :team_planning
urgency :low
before_action :validate_root_group!
before_action :authorize_read_crm_organization!

View File

@ -10,6 +10,7 @@ class Groups::LabelsController < Groups::ApplicationController
respond_to :html
feature_category :team_planning
urgency :low
def index
respond_to do |format|

View File

@ -7,6 +7,7 @@ class Groups::MilestonesController < Groups::ApplicationController
before_action :authorize_admin_milestones!, only: [:edit, :new, :create, :update, :destroy]
feature_category :team_planning
urgency :low
def index
respond_to do |format|

View File

@ -61,6 +61,7 @@ class GroupsController < Groups::ApplicationController
urgency :high, [:unfoldered_environment_names]
urgency :low, [:issues, :issues_calendar, :preview_markdown]
# TODO: Set #show to higher urgency after resolving https://gitlab.com/gitlab-org/gitlab/-/issues/334795
urgency :low, [:merge_requests, :show, :create, :new, :update, :projects, :destroy, :edit, :activity]

View File

@ -2,6 +2,7 @@
class Profiles::NotificationsController < Profiles::ApplicationController
feature_category :team_planning
urgency :low
def show
@user = current_user

View File

@ -4,6 +4,7 @@ class Projects::Analytics::CycleAnalytics::ValueStreamsController < Projects::Ap
respond_to :json
feature_category :planning_analytics
urgency :low
before_action :authorize_read_cycle_analytics!

View File

@ -10,6 +10,7 @@ class Projects::AutocompleteSourcesController < Projects::ApplicationController
feature_category :snippets, [:snippets]
urgency :low, [:merge_requests, :members]
urgency :low, [:issues, :labels, :milestones, :commands, :contacts]
def members
render json: ::Projects::ParticipantsService.new(@project, current_user).execute(target)

View File

@ -16,6 +16,7 @@ class Projects::BoardsController < Projects::ApplicationController
end
feature_category :team_planning
urgency :low
private

View File

@ -12,6 +12,7 @@ module Projects
before_action :authorize_read_merge_request!, only: [:code, :review]
feature_category :planning_analytics
urgency :low
def issue
render_events(cycle_analytics[:issue].events)

View File

@ -14,6 +14,7 @@ class Projects::CycleAnalyticsController < Projects::ApplicationController
track_redis_hll_event :show, name: 'p_analytics_valuestream'
feature_category :planning_analytics
urgency :low
before_action do
push_licensed_feature(:cycle_analytics_for_groups) if project.licensed_feature_available?(:cycle_analytics_for_groups)

View File

@ -10,6 +10,7 @@ class Projects::DiscussionsController < Projects::ApplicationController
before_action :authorize_resolve_discussion!, only: [:resolve, :unresolve]
feature_category :team_planning
urgency :low
def resolve
Discussions::ResolveService.new(project, current_user, one_or_more_discussions: discussion).execute

View File

@ -8,6 +8,7 @@ module Projects
before_action :authorize_issue_link_association!, only: :destroy
feature_category :team_planning
urgency :low
private

View File

@ -65,6 +65,13 @@ class Projects::IssuesController < Projects::ApplicationController
:toggle_award_emoji, :mark_as_spam, :related_branches,
:can_create_branch, :create_merge_request
]
urgency :low, [
:index, :calendar, :show, :new, :create, :edit, :update,
:destroy, :move, :reorder, :designs, :toggle_subscription,
:discussions, :bulk_update, :realtime_changes,
:toggle_award_emoji, :mark_as_spam, :related_branches,
:can_create_branch, :create_merge_request
]
feature_category :service_desk, [:service_desk]
urgency :low, [:service_desk]

View File

@ -15,6 +15,7 @@ class Projects::LabelsController < Projects::ApplicationController
respond_to :js, :html
feature_category :team_planning
urgency :low
def index
respond_to do |format|

View File

@ -19,6 +19,7 @@ class Projects::MilestonesController < Projects::ApplicationController
respond_to :html
feature_category :team_planning
urgency :low
def index
@sort = params[:sort] || 'due_date_asc'

View File

@ -12,6 +12,7 @@ class Projects::NotesController < Projects::ApplicationController
before_action :authorize_resolve_note!, only: [:resolve, :unresolve]
feature_category :team_planning
urgency :low
def delete_attachment
note.remove_attachment!

View File

@ -7,6 +7,7 @@ class Projects::TodosController < Projects::ApplicationController
before_action :authenticate_user!, only: [:create]
feature_category :team_planning
urgency :low
private

View File

@ -6,6 +6,7 @@ class Projects::WorkItemsController < Projects::ApplicationController
end
feature_category :team_planning
urgency :low
def index
render_404 unless project&.work_items_feature_flag_enabled?

View File

@ -58,6 +58,7 @@ class ProjectsController < Projects::ApplicationController
feature_category :portfolio_management, [:planning_hierarchy]
urgency :low, [:export, :remove_export, :generate_new_export, :download_export]
urgency :low, [:preview_markdown, :new_issuable_address]
# TODO: Set high urgency for #show https://gitlab.com/gitlab-org/gitlab/-/issues/334444
urgency :low, [:refs, :show, :toggle_star, :transfer, :archive, :destroy, :update, :create,

View File

@ -4,6 +4,7 @@ class SentNotificationsController < ApplicationController
skip_before_action :authenticate_user!
feature_category :team_planning
urgency :low
def unsubscribe
@sent_notification = SentNotification.for(params[:id])

View File

@ -41,3 +41,5 @@ class GroupGroupLink < ApplicationRecord
Gitlab::Access.human_access(self.group_access)
end
end
GroupGroupLink.prepend_mod_with('GroupGroupLink')

View File

@ -242,11 +242,11 @@ class Namespace < ApplicationRecord
return unless host.ends_with?(gitlab_host)
name = host.delete_suffix(gitlab_host)
Namespace.where(parent_id: nil).by_path(name)
Namespace.top_most.by_path(name)
end
def top_most
where(parent_id: nil)
by_parent(nil)
end
end

View File

@ -133,7 +133,7 @@ module Ci
job.update_column(:artifacts_expire_at, artifact.expire_at)
end
success
success(artifact: artifact)
rescue ActiveRecord::RecordNotUnique => error
track_exception(error, params)
error('another artifact of the same type already exists', :bad_request)

View File

@ -40,6 +40,8 @@
Soft wrap
.file-editor.code
- if Feature.enabled?(:source_editor_toolbar, current_user)
#editor-toolbar
.js-edit-mode-pane.qa-editor#editor{ data: { 'editor-loading': true } }<
%pre.editor-loading-content= params[:content] || local_assigns[:blob_data]
- if local_assigns[:path]

View File

@ -0,0 +1,8 @@
---
name: ci_fix_rules_if_comparison_with_regexp_variable
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/85310
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/359740
milestone: '15.0'
type: development
group: group::pipeline authoring
default_enabled: false

View File

@ -5,4 +5,4 @@ rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/360663
milestone: '15.0'
type: development
group: group::product planning
default_enabled: false
default_enabled: true

View File

@ -56,7 +56,7 @@ Sidekiq.configure_server do |config|
config.on :startup do
# Clear any connections that might have been obtained before starting
# Sidekiq (e.g. in an initializer).
ActiveRecord::Base.clear_all_connections!
ActiveRecord::Base.clear_all_connections! # rubocop:disable Database/MultipleDatabases
# Start monitor to track running jobs. By default, cancel job is not enabled
# To cancel job, it requires `SIDEKIQ_MONITOR_WORKER=1` to enable notification channel

View File

@ -0,0 +1,13 @@
# frozen_string_literal: true
class AddExcludeFromFreeUserCapToNamespaceSettings < Gitlab::Database::Migration[2.0]
enable_lock_retries!
def up
add_column :namespace_settings, :exclude_from_free_user_cap, :boolean, null: false, default: false
end
def down
remove_column :namespace_settings, :exclude_from_free_user_cap
end
end

View File

@ -0,0 +1 @@
cf49c37edf23372a0117895bd2036cefd42616871f42511c6ecbe03a47b96e9f

View File

@ -17419,6 +17419,7 @@ CREATE TABLE namespace_settings (
runner_token_expiration_interval integer,
subgroup_runner_token_expiration_interval integer,
project_runner_token_expiration_interval integer,
exclude_from_free_user_cap boolean DEFAULT false NOT NULL,
CONSTRAINT check_0ba93c78c7 CHECK ((char_length(default_branch_name) <= 255))
);

View File

@ -25,6 +25,7 @@ arity
Artifactory
Asana
Asciidoctor
asdf
Assembla
Atlassian
auditability
@ -98,6 +99,7 @@ Casdoor
CentOS
Ceph
Certbot
cgo
cgroup
cgroups
chai
@ -109,6 +111,7 @@ chatbots
ChatOps
checksummed
checksumming
Chemlab
Citrix
Citus
clonable
@ -206,6 +209,7 @@ enums
ETag
Excon
exfiltration
ExifTool
expirable
Facebook
failover
@ -592,6 +596,7 @@ serializer
serializers
serializing
serverless
setuptools
severities
sharded
sharding
@ -825,6 +830,7 @@ Vagrantfile
validator
validators
vendored
vendoring
versionless
viewport
viewports

View File

@ -26,9 +26,9 @@ these definitions yet.
| Single-node site | A specific configuration of GitLab that uses exactly one node. | GitLab | single-server, single-instance
| Multi-node site | A specific configuration of GitLab that uses more than one node. | GitLab | multi-server, multi-instance, high availability |
| Primary site | A GitLab site whose data is being replicated by at least one secondary site. There can only be a single primary site. | Geo-specific | Geo deployment, Primary node |
| Secondary site(s) | A GitLab site that is configured to replicate the data of a primary site. There can be one or more secondary sites. | Geo-specific | Geo deployment, Secondary node |
| Secondary site | A GitLab site that is configured to replicate the data of a primary site. There can be one or more secondary sites. | Geo-specific | Geo deployment, Secondary node |
| Geo deployment | A collection of two or more GitLab sites with exactly one primary site being replicated by one or more secondary sites. | Geo-specific | |
| Reference architecture(s) | A [specified configuration of GitLab for a number of users](../reference_architectures/index.md), possibly including multiple nodes and multiple sites. | GitLab | |
| Reference architecture | A [specified configuration of GitLab for a number of users](../reference_architectures/index.md), possibly including multiple nodes and multiple sites. | GitLab | |
| Promoting | Changing the role of a site from secondary to primary. | Geo-specific | |
| Demoting | Changing the role of a site from primary to secondary. | Geo-specific | |
| Failover | The entire process that shifts users from a primary Site to a secondary site. This includes promoting a secondary, but contains other parts as well. For example, scheduling maintenance. | Geo-specific | |

View File

@ -992,7 +992,7 @@ On the **primary** node:
1. On the left sidebar, select **Geo > Nodes**.
1. Find the affected **secondary** site and select **Edit**.
1. Ensure the **URL** field matches the value found in `/etc/gitlab/gitlab.rb`
in `external_url "https://gitlab.example.com"` on the frontend server(s) of
in `external_url "https://gitlab.example.com"` on the frontend servers of
the **secondary** node.
## Fixing common errors
@ -1133,7 +1133,7 @@ This happens because GitLab is attempting to display registries from the [Geo tr
## Fixing client errors
### Authorization errors from LFS HTTP(s) client requests
### Authorization errors from LFS HTTP(S) client requests
You may have problems if you're running a version of [Git LFS](https://git-lfs.github.com/) before 2.4.2.
As noted in [this authentication issue](https://github.com/git-lfs/git-lfs/issues/3025),

View File

@ -12,9 +12,9 @@ for updating Geo sites.
## Updating to 14.9
**DO NOT** update to GitLab 14.9.0.
**DO NOT** update to GitLab 14.9.0. Instead, use 14.9.1 or later.
We've discovered an issue with Geo's CI verification feature that may [cause job traces to be lost](https://gitlab.com/gitlab-com/gl-infra/production/-/issues/6664). This issue will be fixed in the next patch release.
We've discovered an issue with Geo's CI verification feature that may [cause job traces to be lost](https://gitlab.com/gitlab-com/gl-infra/production/-/issues/6664). This issue was fixed in [the GitLab 14.9.1 patch release](https://about.gitlab.com/releases/2022/03/23/gitlab-14-9-1-released/).
If you have already updated to GitLab 14.9.0, you can disable the feature causing the issue by [disabling the `geo_job_artifact_replication` feature flag](../../feature_flags.md#how-to-enable-and-disable-features-behind-flags).

View File

@ -967,7 +967,7 @@ application. This is done by updating the `git_data_dirs`.
Particular attention should be shown to:
- the storage name added to `git_data_dirs` in this section must match the
storage name under `praefect['virtual_storages']` on the Praefect node(s). This
storage name under `praefect['virtual_storages']` on the Praefect nodes. This
was set in the [Praefect](#praefect) section of this guide. This document uses
`default` as the Praefect storage name.

View File

@ -377,7 +377,7 @@ Any `Operation not permitted` errors means you should investigate your NFS serve
## NFS in a Firewalled Environment
If the traffic between your NFS server and NFS client(s) is subject to port filtering
If the traffic between your NFS server and NFS clients is subject to port filtering
by a firewall, then you need to reconfigure that firewall to allow NFS communication.
[This guide from The Linux Documentation Project (TDLP)](https://tldp.org/HOWTO/NFS-HOWTO/security.html#FIREWALLS)

View File

@ -354,7 +354,7 @@ file is written, but this can be changed by passing the `--pidfile` option to
```
Keep in mind that the PID file contains the PID of the `sidekiq-cluster`
command and not the PID(s) of the started Sidekiq processes.
command and not the PIDs of the started Sidekiq processes.
### Environment

View File

@ -66,7 +66,7 @@ This software is based in part on the work of the Independent JPEG Group.
## Trademark Usage
Within the GitLab documentation, reference to third party technology(ies) and/or trademarks of third party entities, may be made. The inclusion of reference to third party technology and/or entities is solely for the purposes of example(s) of how GitLab software may interact with, or be used in conjunction with, such third party technology.
Within the GitLab documentation, reference to third-party technologies and/or trademarks of third-party entities may be made. The inclusion of reference to third-party technology and/or entities is solely for the purposes of examples of how GitLab software may interact with, or be used in conjunction with, such third-party technology.
All trademarks, materials, documentation, and other intellectual property remain the property of any/all such third party.
### Trademark Requirements

View File

@ -289,7 +289,7 @@ If the issue is:
Go indexer was a beta indexer which can be optionally turned on/off, but in 12.3 it reached stable status and is now the default.
- Not concerning the Go indexer, it is almost always an
Elasticsearch-side issue. This means you should reach out to your Elasticsearch administrator
regarding the error(s) you are seeing. If you are unsure here, it never hurts to reach
regarding the errors you are seeing. If you are unsure here, it never hurts to reach
out to GitLab support.
Beyond that, review the error. If it is:

View File

@ -315,7 +315,7 @@ queue.each { |job| job.delete if <condition>}
Have a look at the section below for cancelling running jobs.
In the method above, `<queue-name>` is the name of the queue that contains the job(s) you want to delete and `<condition>` decides which jobs get deleted.
In the method above, `<queue-name>` is the name of the queue that contains the jobs you want to delete and `<condition>` decides which jobs get deleted.
Commonly, `<condition>` references the job arguments, which depend on the type of job in question. To find the arguments for a specific queue, you can have a look at the `perform` function of the related worker file, commonly found at `/app/workers/<queue-name>_worker.rb`.

View File

@ -348,7 +348,7 @@ The following table shows the possible return codes for API requests.
| Return values | Description |
|--------------------------|-------------|
| `200 OK` | The `GET`, `PUT` or `DELETE` request was successful, and the resource(s) itself is returned as JSON. |
| `200 OK` | The `GET`, `PUT` or `DELETE` request was successful, and the resource itself is returned as JSON. |
| `204 No Content` | The server has successfully fulfilled the request, and there is no additional content to send in the response payload body. |
| `201 Created` | The `POST` request was successful, and the resource is returned as JSON. |
| `304 Not Modified` | The resource hasn't been modified since the last request. |

View File

@ -1166,7 +1166,7 @@ PUT /projects/:id/issues/:issue_iid
| Attribute | Type | Required | Description |
|----------------|---------|----------|------------------------------------------------------------------------------------------------------------|
| `add_labels` | string | no | Comma-separated label names to add to an issue. |
| `assignee_ids` | integer array | no | The ID of the user(s) to assign the issue to. Set to `0` or provide an empty value to unassign all assignees. |
| `assignee_ids` | integer array | no | The ID of the users to assign the issue to. Set to `0` or provide an empty value to unassign all assignees. |
| `confidential` | boolean | no | Updates an issue to be confidential |
| `description` | string | no | The description of an issue. Limited to 1,048,576 characters. |
| `discussion_locked` | boolean | no | Flag indicating if the issue's discussion is locked. If the discussion is locked only project members can add or edit comments. |

View File

@ -1103,8 +1103,8 @@ POST /projects/:id/merge_requests
| `target_branch` | string | yes | The target branch. |
| `title` | string | yes | Title of MR. |
| `assignee_id` | integer | no | Assignee user ID. |
| `assignee_ids` | integer array | no | The ID of the user(s) to assign the MR to. Set to `0` or provide an empty value to unassign all assignees. |
| `reviewer_ids` | integer array | no | The ID of the user(s) added as a reviewer to the MR. If set to `0` or left empty, no reviewers are added. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/49341) in GitLab 13.8. |
| `assignee_ids` | integer array | no | The ID of the users to assign the MR to. Set to `0` or provide an empty value to unassign all assignees. |
| `reviewer_ids` | integer array | no | The ID of the users added as a reviewer to the MR. If set to `0` or left empty, no reviewers are added. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/49341) in GitLab 13.8. |
| `description` | string | no | Description of MR. Limited to 1,048,576 characters. |
| `target_project_id` | integer | no | The target project (numeric ID). |
| `labels` | string | no | Labels for MR as a comma-separated list. |
@ -1271,8 +1271,8 @@ PUT /projects/:id/merge_requests/:merge_request_iid
| `target_branch` | string | no | The target branch. |
| `title` | string | no | Title of MR. |
| `assignee_id` | integer | no | The ID of the user to assign the merge request to. Set to `0` or provide an empty value to unassign all assignees. |
| `assignee_ids` | integer array | no | The ID of the user(s) to assign the MR to. Set to `0` or provide an empty value to unassign all assignees. |
| `reviewer_ids` | integer array | no | The ID of the user(s) set as a reviewer to the MR. Set the value to `0` or provide an empty value to unset all reviewers. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/49341) in GitLab 13.8. |
| `assignee_ids` | integer array | no | The ID of the users to assign the MR to. Set to `0` or provide an empty value to unassign all assignees. |
| `reviewer_ids` | integer array | no | The ID of the users set as a reviewer to the MR. Set the value to `0` or provide an empty value to unset all reviewers. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/49341) in GitLab 13.8. |
| `milestone_id` | integer | no | The global ID of a milestone to assign the merge request to. Set to `0` or provide an empty value to unassign a milestone.|
| `labels` | string | no | Comma-separated label names for a merge request. Set to an empty string to unassign all labels. |
| `add_labels` | string | no | Comma-separated label names to add to a merge request. |

View File

@ -6,7 +6,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Pages domains API **(FREE)**
Endpoints for connecting custom domain(s) and TLS certificates in [GitLab Pages](https://about.gitlab.com/stages-devops-lifecycle/pages/).
Endpoints for connecting custom domains and TLS certificates in [GitLab Pages](https://about.gitlab.com/stages-devops-lifecycle/pages/).
The GitLab Pages feature must be enabled to use these endpoints. Find out more about [administering](../administration/pages/index.md) and [using](../user/project/pages/index.md) the feature.

View File

@ -253,8 +253,8 @@ listed in the descriptions of the relevant settings.
| `asset_proxy_enabled` | boolean | no | (**If enabled, requires:** `asset_proxy_url`) Enable proxying of assets. GitLab restart is required to apply changes. |
| `asset_proxy_secret_key` | string | no | Shared secret with the asset proxy server. GitLab restart is required to apply changes. |
| `asset_proxy_url` | string | no | URL of the asset proxy server. GitLab restart is required to apply changes. |
| `asset_proxy_whitelist` | string or array of strings | no | (Deprecated: Use `asset_proxy_allowlist` instead) Assets that match these domain(s) are **not** proxied. Wildcards allowed. Your GitLab installation URL is automatically allowlisted. GitLab restart is required to apply changes. |
| `asset_proxy_allowlist` | string or array of strings | no | Assets that match these domain(s) are **not** proxied. Wildcards allowed. Your GitLab installation URL is automatically allowlisted. GitLab restart is required to apply changes. |
| `asset_proxy_whitelist` | string or array of strings | no | (Deprecated: Use `asset_proxy_allowlist` instead) Assets that match these domains are **not** proxied. Wildcards allowed. Your GitLab installation URL is automatically allowlisted. GitLab restart is required to apply changes. |
| `asset_proxy_allowlist` | string or array of strings | no | Assets that match these domains are **not** proxied. Wildcards allowed. Your GitLab installation URL is automatically allowlisted. GitLab restart is required to apply changes. |
| `authorized_keys_enabled` | boolean | no | By default, we write to the `authorized_keys` file to support Git over SSH without additional configuration. GitLab can be optimized to authenticate SSH keys via the database file. Only disable this if you have configured your OpenSSH server to use the AuthorizedKeysCommand. |
| `auto_devops_domain` | string | no | Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages. |
| `auto_devops_enabled` | boolean | no | Enable Auto DevOps for projects by default. It automatically builds, tests, and deploys applications based on a predefined CI/CD configuration. |
@ -288,7 +288,7 @@ listed in the descriptions of the relevant settings.
| `disabled_oauth_sign_in_sources` | array of strings | no | Disabled OAuth sign-in sources. |
| `dns_rebinding_protection_enabled` | boolean | no | Enforce DNS rebinding attack protection. |
| `domain_denylist_enabled` | boolean | no | (**If enabled, requires:** `domain_denylist`) Allows blocking sign-ups from emails from specific domains. |
| `domain_denylist` | array of strings | no | Users with email addresses that match these domain(s) **cannot** sign up. Wildcards allowed. Use separate lines for multiple entries. Ex: `domain.com`, `*.domain.com`. |
| `domain_denylist` | array of strings | no | Users with email addresses that match these domains **cannot** sign up. Wildcards allowed. Use separate lines for multiple entries. Ex: `domain.com`, `*.domain.com`. |
| `domain_allowlist` | array of strings | no | Force people to use only corporate emails for sign-up. Default is `null`, meaning there is no restriction. |
| `dsa_key_restriction` | integer | no | The minimum allowed bit length of an uploaded DSA key. Default is `0` (no restriction). `-1` disables DSA keys. |
| `ecdsa_key_restriction` | integer | no | The minimum allowed curve size (in bits) of an uploaded ECDSA key. Default is `0` (no restriction). `-1` disables ECDSA keys. |

View File

@ -133,8 +133,8 @@ You can find more information on table partitioning for PostgreSQL in the
[documentation page for table partitioning](https://www.postgresql.org/docs/12/ddl-partitioning.html).
Partitioning by date intervals (for example, month, year) allows us to create much smaller tables
(partitions) for each date interval and only access the most recent partition(s) for any
application related operation.
(partitions) for each date interval and only access the most recent partitions for any
application-related operation.
We have to set the partitioning key based on the date interval of interest, which may depend on two
factors:
@ -214,7 +214,7 @@ offloading metadata but only for the case of old data.
In the simplest use case we can provide fast and direct access to recent data, while allowing users
to download an archive with older data. This is an option evaluated in the `audit_events` use case.
Depending on the country and industry, audit events may have a very long retention period, while
only the past month(s) of data are actively accessed through GitLab interface.
only the past months of data are actively accessed through GitLab interface.
Additional use cases may include exporting data to a data warehouse or other types of data stores as
they may be better suited for processing that type of data. An example can be JSON logs that we

View File

@ -35,7 +35,7 @@ You can also view or fork the complete [example source](https://gitlab.com/gitla
}
```
1. Update the `files` key with glob pattern(s) that selects all files that should be included in the published module. More information about `files` can be found [in npm's documentation](https://docs.npmjs.com/cli/v6/configuring-npm/package-json/#files).
1. Update the `files` key with glob patterns that selects all files that should be included in the published module. More information about `files` can be found [in npm's documentation](https://docs.npmjs.com/cli/v6/configuring-npm/package-json/#files).
1. Add a `.gitignore` file to the project to avoid committing `node_modules`:

View File

@ -80,7 +80,7 @@ As mentioned before, this feature is designed to provide **network accessible**
services. A database is the simplest example of such a service.
The services feature is not designed to, and does not, add any software from the
defined `services` image(s) to the job's container.
defined `services` images to the job's container.
For example, if you have the following `services` defined in your job, the `php`,
`node` or `go` commands are **not** available for your script, and the job fails:

View File

@ -3090,6 +3090,8 @@ job:
- Unlike variables in [`script`](../variables/index.md#use-cicd-variables-in-job-scripts)
sections, variables in rules expressions are always formatted as `$VARIABLE`.
- You can use `rules:if` with `include` to [conditionally include other configuration files](includes.md#use-rules-with-include).
- In [GitLab 15.0 and later](https://gitlab.com/gitlab-org/gitlab/-/issues/35438),
variables on the right side of `=~` and `!~` expressions are evaluated as regular expressions.
**Related topics**:

View File

@ -158,7 +158,7 @@ and should not be used. Some other points to consider:
### Why explicit names are required
As Rails is database agnostic, it generates an index name only
from the required options of all indexes: table name and column name(s).
from the required options of all indexes: table name and column names.
For example, imagine the following two indexes are created in a migration:
```ruby
@ -173,7 +173,7 @@ Creation of the second index would fail, because Rails would generate
the same name for both indexes.
This is further complicated by the behavior of the `index_exists?` method.
It considers only the table name, column name(s) and uniqueness specification
It considers only the table name, column names, and uniqueness specification
of the index when making a comparison. Consider:
```ruby
@ -284,8 +284,9 @@ production clone.
### Add a migration to create the index synchronously
After the index is verified to exist on the production database, create a second
merge request that adds the index synchronously. The synchronous
migration results in a no-op on GitLab.com, but you should still add the
merge request that adds the index synchronously. The schema changes must be
updated and committed to `structure.sql` in this second merge request.
The synchronous migration results in a no-op on GitLab.com, but you should still add the
migration as expected for other installations. The below block
demonstrates how to create the second migration for the previous
asynchronous example.

View File

@ -38,7 +38,7 @@ sequenceDiagram
1. The CI/CD job generates a document in an LSIF format (usually `dump.lsif`) using [an
indexer](https://lsif.dev) for the language of a project. The format
[describes](https://github.com/sourcegraph/sourcegraph/blob/main/doc/code_intelligence/explanations/writing_an_indexer.md)
interactions between a method or function and its definition(s) or references. The
interactions between a method or function and its definitions or references. The
document is marked to be stored as an LSIF report artifact.
1. After receiving a request for storing the artifact, Workhorse asks

View File

@ -26,7 +26,7 @@ This is only a recommendation and the reviewer may be from a different team.
However, it is recommended to pick someone who is a [domain expert](#domain-experts).
If your merge request touches more than one domain (for example, Dynamic Analysis and GraphQL), ask for reviews from an expert from each domain.
You can read more about the importance of involving reviewer(s) in the section on the responsibility of the author below.
You can read more about the importance of involving reviewers in the section on the responsibility of the author below.
If you need some guidance (for example, it's your first merge request), feel free to ask
one of the [Merge request coaches](https://about.gitlab.com/company/team/).
@ -107,7 +107,7 @@ For more information, review [the roulette README](https://gitlab.com/gitlab-org
### Approval guidelines
As described in the section on the responsibility of the maintainer below, you
are recommended to get your merge request approved and merged by maintainer(s)
are recommended to get your merge request approved and merged by maintainers
with [domain expertise](#domain-experts).
1. If your merge request includes backend changes (*1*), it must be
@ -444,7 +444,7 @@ experience, refactors the existing code). Then:
- For non-mandatory suggestions, decorate with (non-blocking) so the author knows they can
optionally resolve within the merge request or follow-up at a later stage.
- There's a [Chrome/Firefox add-on](https://gitlab.com/conventionalcomments/conventional-comments-button) which you can use to apply [Conventional Comment](https://conventionalcomments.org/) prefixes.
- Ensure there are no open dependencies. Check [linked issues](../user/project/issues/related_issues.md) for blockers. Clarify with the author(s)
- Ensure there are no open dependencies. Check [linked issues](../user/project/issues/related_issues.md) for blockers. Clarify with the authors
if necessary. If blocked by one or more open MRs, set an [MR dependency](../user/project/merge_requests/merge_request_dependencies.md).
- After a round of line notes, it can be helpful to post a summary note such as
"Looks good to me", or "Just a couple things to address."
@ -697,7 +697,7 @@ Properties of customer critical merge requests:
- The [VP of Development](https://about.gitlab.com/job-families/engineering/development/management/vp/) ([@clefelhocz1](https://gitlab.com/clefelhocz1)) is the DRI for deciding if a merge request qualifies as customer critical.
- The DRI applies the `customer-critical-merge-request` label to the merge request.
- It is required that the reviewer(s) and maintainer(s) involved with a customer critical merge request are engaged as soon as this decision is made.
- It is required that the reviewers and maintainers involved with a customer critical merge request are engaged as soon as this decision is made.
- It is required to prioritize work for those involved on a customer critical merge request so that they have the time available necessary to focus on it.
- It is required to adhere to GitLab [values](https://about.gitlab.com/handbook/values/) and processes when working on customer critical merge requests, taking particular note of family and friends first/work second, definition of done, iteration, and release when it's ready.
- Customer critical merge requests are required to not reduce security, introduce data-loss risk, reduce availability, nor break existing functionality per the process for [prioritizing technical decisions](https://about.gitlab.com/handbook/engineering/development/principles/#prioritizing-technical-decisions).

View File

@ -117,7 +117,7 @@ At any moment, but usually _during_ or _after_ the design's implementation:
for additions or enhancements to the design system.
- Create issues with the [`~UX debt`](issue_workflow.md#technical-and-ux-debt)
label for intentional deviations from the agreed-upon UX requirements due to
time or feasibility challenges, linking back to the corresponding issue(s) or
MR(s).
time or feasibility challenges, linking back to the corresponding issues or
merge requests.
- Create issues for [feature additions or enhancements](issue_workflow.md#feature-proposals)
outside the agreed-upon UX requirements to avoid scope creep.

View File

@ -53,7 +53,7 @@ request is as follows:
1. If you have multiple commits, combine them into a few logically organized
commits by [squashing them](https://git-scm.com/book/en/v2/Git-Tools-Rewriting-History#_squashing),
but do not change the commit history if you're working on shared branches though.
1. Push the commit(s) to your working branch in your fork.
1. Push the commits to your working branch in your fork.
1. Submit a merge request (MR) to the `main` branch in the main GitLab project.
1. Your merge request needs at least 1 approval, but depending on your changes
you might need additional approvals. Refer to the [Approval guidelines](../code_review.md#approval-guidelines).
@ -65,7 +65,7 @@ request is as follows:
template already provided in the "Description" field.
1. If you are contributing documentation, choose `Documentation` from the
"Choose a template" menu and fill in the description according to the template.
1. Use the syntax `Solves #XXX`, `Closes #XXX`, or `Refs #XXX` to mention the issue(s) your merge
1. Use the syntax `Solves #XXX`, `Closes #XXX`, or `Refs #XXX` to mention the issues your merge
request addresses. Referenced issues do not [close automatically](../../user/project/issues/managing_issues.md#closing-issues-automatically).
You must close them manually once the merge request is merged.
1. The MR must include *Before* and *After* screenshots if UI changes are made.

View File

@ -334,7 +334,7 @@ Renaming a table is possible without downtime by following our multi-release
Adding foreign keys usually works in 3 steps:
1. Start a transaction
1. Run `ALTER TABLE` to add the constraint(s)
1. Run `ALTER TABLE` to add the constraints
1. Check all existing data
Because `ALTER TABLE` typically acquires an exclusive lock until the end of a

View File

@ -117,8 +117,8 @@ Showing cross-schema foreign keys (20):
18 | N | ci_job_token_project_scope_links | projects | target_project_id | cascade
19 | N | ci_project_monthly_usages | projects | project_id | cascade
To match FK write one or many filters to match against FROM/TO/COLUMN:
- scripts/decomposition/generate-loose-foreign-key <filter(s)...>
To match foreign key (FK), write one or many filters to match against FROM/TO/COLUMN:
- scripts/decomposition/generate-loose-foreign-key (filters...)
- scripts/decomposition/generate-loose-foreign-key ci_job_artifacts project_id
- scripts/decomposition/generate-loose-foreign-key dast_site_profiles_pipelines
```

View File

@ -43,7 +43,7 @@ problem.
First, a table is partitioned on a partition key, which is a column or
set of columns which determine how the data will be split across the
partitions. The partition key is used by the database when reading or
writing data, to decide which partition(s) need to be accessed. The
writing data, to decide which partitions need to be accessed. The
partition key should be a column that would be included in a `WHERE`
clause on almost all queries accessing that table.

View File

@ -1987,7 +1987,7 @@ To improve performance, sometimes we want to make initial GraphQL queries early.
}
```
- Add startup call(s) with correct variables to the HAML file that serves as a view
- Add startup calls with correct variables to the HAML file that serves as a view
for your application. To add GraphQL startup calls, we use
`add_page_startup_graphql_call` helper where the first parameter is a path to the
query, the second one is an object containing query variables. Path to the query is

Some files were not shown because too many files have changed in this diff Show More