Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
f7500ff667
commit
d6a7d36ff2
|
|
@ -764,6 +764,7 @@ rspec-ee:predictive:trigger single-db-ci-connection:
|
|||
.rspec-ee-base-gitlab-duo:
|
||||
extends:
|
||||
- .rspec-ee-base-pg14
|
||||
when: manual
|
||||
variables:
|
||||
REAL_AI_REQUEST: "true"
|
||||
AI_GATEWAY_URL: http://ai-gateway:5052
|
||||
|
|
@ -1297,7 +1298,7 @@ rspec-ee system pg16:
|
|||
stage: test
|
||||
script:
|
||||
- !reference [.base-script, script]
|
||||
- rspec_section rspec_fail_fast "${MATCHING_TESTS_PATH}" "--fail-fast=${RSPEC_FAIL_FAST_THRESHOLD} --tag ~quarantine --tag ~zoekt --tag ~click_house"
|
||||
- rspec_section rspec_fail_fast "${MATCHING_TESTS_PATH}" "--fail-fast=${RSPEC_FAIL_FAST_THRESHOLD} --tag ~quarantine --tag ~zoekt --tag ~click_house --tag ~real_ai_request"
|
||||
|
||||
rspec fail-fast:
|
||||
extends:
|
||||
|
|
|
|||
|
|
@ -107,7 +107,7 @@ include:
|
|||
# spec/lib, yet background migration tests are also sitting there,
|
||||
# and they should run on their own jobs so we don't need to run them
|
||||
# in unit tests again.
|
||||
- rspec_section rspec_parallelized_job "--fail-fast=${RSPEC_FAIL_FAST_THRESHOLD} --tag ~quarantine --tag ~level:background_migration --tag ~click_house"
|
||||
- rspec_section rspec_parallelized_job "--fail-fast=${RSPEC_FAIL_FAST_THRESHOLD} --tag ~quarantine --tag ~level:background_migration --tag ~click_house --tag ~real_ai_request"
|
||||
after_script:
|
||||
- source scripts/utils.sh
|
||||
- log_disk_usage # https://gitlab.com/gitlab-org/gitlab/-/issues/478880
|
||||
|
|
@ -204,7 +204,7 @@ include:
|
|||
.rspec-base-migration:
|
||||
script:
|
||||
- !reference [.base-script, script]
|
||||
- rspec_section rspec_parallelized_job "--fail-fast=${RSPEC_FAIL_FAST_THRESHOLD} --tag ~quarantine --tag ~zoekt --tag ~click_house"
|
||||
- rspec_section rspec_parallelized_job "--fail-fast=${RSPEC_FAIL_FAST_THRESHOLD} --tag ~quarantine --tag ~zoekt --tag ~click_house --tag ~real_ai_request"
|
||||
after_script:
|
||||
- !reference [.rspec-base, after_script]
|
||||
|
||||
|
|
|
|||
10
.rubocop.yml
10
.rubocop.yml
|
|
@ -67,6 +67,13 @@ Rails/Date:
|
|||
# See https://gitlab.com/gitlab-org/gitlab/-/issues/502580
|
||||
- danger/database/Dangerfile
|
||||
|
||||
Rails/Pluck:
|
||||
Exclude:
|
||||
# See https://gitlab.com/gitlab-org/gitlab/-/issues/502580
|
||||
- 'tooling/danger/**/*'
|
||||
# See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/94047#note_1179689274
|
||||
AutoCorrect: false
|
||||
|
||||
RSpec:
|
||||
Language:
|
||||
Includes:
|
||||
|
|
@ -363,9 +370,6 @@ Rails/MailerName:
|
|||
# See for the context on why it's excluded https://gitlab.com/gitlab-org/gitlab/-/issues/239356#note_956419227
|
||||
- 'app/mailers/notify.rb'
|
||||
|
||||
Rails/Pluck:
|
||||
# See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/94047#note_1179689274
|
||||
AutoCorrect: false
|
||||
|
||||
Rails/RakeEnvironment:
|
||||
# Context on why it's disabled: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/93419#note_1048223982
|
||||
|
|
|
|||
|
|
@ -945,6 +945,7 @@ Gitlab/BoundedContexts:
|
|||
- 'app/models/concerns/token_authenticatable_strategies/encrypted.rb'
|
||||
- 'app/models/concerns/token_authenticatable_strategies/encryption_helper.rb'
|
||||
- 'app/models/concerns/token_authenticatable_strategies/insecure.rb'
|
||||
- 'app/models/concerns/token_authenticatable_strategies/routable_token_generator.rb'
|
||||
- 'app/models/concerns/transactions.rb'
|
||||
- 'app/models/concerns/transitionable.rb'
|
||||
- 'app/models/concerns/triggerable_hooks.rb'
|
||||
|
|
@ -3405,7 +3406,6 @@ Gitlab/BoundedContexts:
|
|||
- 'ee/app/services/personal_access_tokens/groups/update_lifetime_service.rb'
|
||||
- 'ee/app/services/personal_access_tokens/instance/update_lifetime_service.rb'
|
||||
- 'ee/app/services/personal_access_tokens/revoke_invalid_tokens.rb'
|
||||
- 'ee/app/services/personal_access_tokens/rotation_verifier_service.rb'
|
||||
- 'ee/app/services/phone_verification/telesign_client/base_service.rb'
|
||||
- 'ee/app/services/phone_verification/telesign_client/risk_score_service.rb'
|
||||
- 'ee/app/services/phone_verification/telesign_client/send_verification_code_service.rb'
|
||||
|
|
|
|||
|
|
@ -243,7 +243,6 @@ Layout/ClassStructure:
|
|||
- 'ee/app/services/package_metadata/ingestion/compressed_package/package_ingestion_task.rb'
|
||||
- 'ee/app/services/path_locks/lock_service.rb'
|
||||
- 'ee/app/services/path_locks/unlock_service.rb'
|
||||
- 'ee/app/services/personal_access_tokens/rotation_verifier_service.rb'
|
||||
- 'ee/app/services/search/zoekt/callback_service.rb'
|
||||
- 'ee/app/services/search/zoekt/task_serializer_service.rb'
|
||||
- 'ee/app/services/security/ingestion/tasks/update_vulnerability_uuids.rb'
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ Layout/LineLength:
|
|||
- 'app/controllers/concerns/issuable_collections.rb'
|
||||
- 'app/controllers/concerns/membership_actions.rb'
|
||||
- 'app/controllers/concerns/notes_actions.rb'
|
||||
- 'app/controllers/groups/milestones_controller.rb'
|
||||
- 'app/controllers/groups_controller.rb'
|
||||
- 'app/controllers/import/base_controller.rb'
|
||||
- 'app/controllers/import/bitbucket_controller.rb'
|
||||
|
|
@ -791,7 +792,6 @@ Layout/LineLength:
|
|||
- 'ee/app/services/jira/requests/issues/list_service.rb'
|
||||
- 'ee/app/services/merge_requests/create_from_vulnerability_data_service.rb'
|
||||
- 'ee/app/services/merge_trains/refresh_merge_request_service.rb'
|
||||
- 'ee/app/services/personal_access_tokens/rotation_verifier_service.rb'
|
||||
- 'ee/app/services/projects/mark_for_deletion_service.rb'
|
||||
- 'ee/app/services/projects/update_mirror_service.rb'
|
||||
- 'ee/app/services/security/ingestion/finding_map.rb'
|
||||
|
|
@ -1075,6 +1075,7 @@ Layout/LineLength:
|
|||
- 'ee/spec/features/groups/saml_providers_spec.rb'
|
||||
- 'ee/spec/features/groups/scim_token_spec.rb'
|
||||
- 'ee/spec/features/groups/security/compliance_dashboards_spec.rb'
|
||||
- 'ee/spec/features/groups/settings/domain_verification_spec.rb'
|
||||
- 'ee/spec/features/integrations/jira/jira_issues_list_spec.rb'
|
||||
- 'ee/spec/features/issues/filtered_search/filter_issues_weight_spec.rb'
|
||||
- 'ee/spec/features/labels_hierarchy_spec.rb'
|
||||
|
|
@ -1096,6 +1097,7 @@ Layout/LineLength:
|
|||
- 'ee/spec/features/projects/iterations/user_views_iteration_spec.rb'
|
||||
- 'ee/spec/features/projects/members/member_is_removed_from_project_spec.rb'
|
||||
- 'ee/spec/features/projects/members/member_leaves_project_spec.rb'
|
||||
- 'ee/spec/features/projects/mirror_spec.rb'
|
||||
- 'ee/spec/features/projects/new_project_spec.rb'
|
||||
- 'ee/spec/features/projects/pipelines/pipeline_spec.rb'
|
||||
- 'ee/spec/features/projects/quality/test_case_list_spec.rb'
|
||||
|
|
@ -1251,6 +1253,7 @@ Layout/LineLength:
|
|||
- 'ee/spec/lib/audit/details_spec.rb'
|
||||
- 'ee/spec/lib/banzai/filter/jira_private_image_link_filter_spec.rb'
|
||||
- 'ee/spec/lib/banzai/filter/references/epic_reference_filter_spec.rb'
|
||||
- 'ee/spec/lib/banzai/filter/references/iterations_cadence_reference_filter_spec.rb'
|
||||
- 'ee/spec/lib/banzai/filter/references/label_reference_filter_spec.rb'
|
||||
- 'ee/spec/lib/banzai/filter/references/vulnerability_reference_filters_spec.rb'
|
||||
- 'ee/spec/lib/bulk_imports/projects/pipelines/issues_pipeline_spec.rb'
|
||||
|
|
@ -1387,6 +1390,7 @@ Layout/LineLength:
|
|||
- 'ee/spec/lib/gitlab/usage/metrics/instrumentations/count_event_streaming_destinations_metric_spec.rb'
|
||||
- 'ee/spec/lib/gitlab/usage/metrics/instrumentations/count_groups_with_event_streaming_destinations_metric_spec.rb'
|
||||
- 'ee/spec/lib/gitlab/usage/metrics/instrumentations/count_projects_with_external_status_checks_metric_spec.rb'
|
||||
- 'ee/spec/lib/gitlab/usage/metrics/instrumentations/count_security_scans_metric_spec.rb'
|
||||
- 'ee/spec/lib/gitlab/usage/metrics/instrumentations/count_users_associating_group_milestones_to_releases_metric_spec.rb'
|
||||
- 'ee/spec/lib/gitlab/usage/metrics/instrumentations/count_users_creating_ci_builds_metric_spec.rb'
|
||||
- 'ee/spec/lib/gitlab/usage/metrics/instrumentations/license_metric_spec.rb'
|
||||
|
|
@ -1816,7 +1820,6 @@ Layout/LineLength:
|
|||
- 'ee/spec/services/merge_trains/create_pipeline_service_spec.rb'
|
||||
- 'ee/spec/services/merge_trains/refresh_merge_request_service_spec.rb'
|
||||
- 'ee/spec/services/personal_access_tokens/create_service_audit_log_spec.rb'
|
||||
- 'ee/spec/services/personal_access_tokens/rotation_verifier_service_spec.rb'
|
||||
- 'ee/spec/services/projects/alerting/notify_service_spec.rb'
|
||||
- 'ee/spec/services/projects/cleanup_service_spec.rb'
|
||||
- 'ee/spec/services/projects/gitlab_projects_import_service_spec.rb'
|
||||
|
|
@ -1891,6 +1894,7 @@ Layout/LineLength:
|
|||
- 'ee/spec/support/shared_contexts/status_page/status_page_list_objects.rb'
|
||||
- 'ee/spec/support/shared_examples/controllers/analytics/cycle_analytics/shared_stage_shared_examples.rb'
|
||||
- 'ee/spec/support/shared_examples/controllers/concerns/description_diff_actions_shared_examples.rb'
|
||||
- 'ee/spec/support/shared_examples/features/dashboard_saml_reauth_banner_shared_examples.rb'
|
||||
- 'ee/spec/support/shared_examples/features/epics_filtered_search_shared_examples.rb'
|
||||
- 'ee/spec/support/shared_examples/features/sidebar_shared_examples.rb'
|
||||
- 'ee/spec/support/shared_examples/finders/geo/registry_finder_shared_examples.rb'
|
||||
|
|
@ -2065,6 +2069,7 @@ Layout/LineLength:
|
|||
- 'lib/api/settings.rb'
|
||||
- 'lib/api/snippet_repository_storage_moves.rb'
|
||||
- 'lib/api/snippets.rb'
|
||||
- 'lib/api/submodules.rb'
|
||||
- 'lib/api/suggestions.rb'
|
||||
- 'lib/api/tags.rb'
|
||||
- 'lib/api/templates.rb'
|
||||
|
|
@ -2426,6 +2431,7 @@ Layout/LineLength:
|
|||
- 'qa/qa/resource/registry_repository.rb'
|
||||
- 'qa/qa/resource/repository/push.rb'
|
||||
- 'qa/qa/resource/snippet.rb'
|
||||
- 'qa/qa/resource/user_runners.rb'
|
||||
- 'qa/qa/resource/wiki/group_page.rb'
|
||||
- 'qa/qa/runtime/api/repository_storage_moves.rb'
|
||||
- 'qa/qa/runtime/env.rb'
|
||||
|
|
@ -2434,6 +2440,7 @@ Layout/LineLength:
|
|||
- 'qa/qa/scenario/bootable.rb'
|
||||
- 'qa/qa/service/cluster_provider/gcloud.rb'
|
||||
- 'qa/qa/service/cluster_provider/k3s.rb'
|
||||
- 'qa/qa/service/docker_run/gitlab_runner.rb'
|
||||
- 'qa/qa/service/praefect_manager.rb'
|
||||
- 'qa/qa/specs/features/api/3_create/merge_request/push_options_labels_spec.rb'
|
||||
- 'qa/qa/specs/features/api/3_create/merge_request/push_options_mwps_spec.rb'
|
||||
|
|
@ -2515,6 +2522,7 @@ Layout/LineLength:
|
|||
- 'qa/qa/tools/delete_test_users.rb'
|
||||
- 'qa/qa/tools/generate_perf_testdata.rb'
|
||||
- 'qa/qa/tools/initialize_gitlab_auth.rb'
|
||||
- 'qa/qa/vendor/one_password/cli.rb'
|
||||
- 'qa/spec/git/repository_spec.rb'
|
||||
- 'qa/spec/resource/api_fabricator_spec.rb'
|
||||
- 'qa/spec/runtime/env_spec.rb'
|
||||
|
|
@ -2698,6 +2706,7 @@ Layout/LineLength:
|
|||
- 'spec/features/groups/milestone_spec.rb'
|
||||
- 'spec/features/groups/milestones_sorting_spec.rb'
|
||||
- 'spec/features/groups/packages_spec.rb'
|
||||
- 'spec/features/groups/participants_autocomplete_spec.rb'
|
||||
- 'spec/features/groups/settings/access_tokens_spec.rb'
|
||||
- 'spec/features/groups/settings/repository_spec.rb'
|
||||
- 'spec/features/groups_spec.rb'
|
||||
|
|
@ -2734,6 +2743,7 @@ Layout/LineLength:
|
|||
- 'spec/features/merge_request/user_comments_on_diff_spec.rb'
|
||||
- 'spec/features/merge_request/user_creates_image_diff_notes_spec.rb'
|
||||
- 'spec/features/merge_request/user_creates_merge_request_spec.rb'
|
||||
- 'spec/features/merge_request/user_edits_mr_spec.rb'
|
||||
- 'spec/features/merge_request/user_expands_diff_spec.rb'
|
||||
- 'spec/features/merge_request/user_interacts_with_batched_mr_diffs_spec.rb'
|
||||
- 'spec/features/merge_request/user_posts_diff_notes_spec.rb'
|
||||
|
|
@ -3260,6 +3270,8 @@ Layout/LineLength:
|
|||
- 'spec/lib/gitlab/diff/inline_diff_marker_spec.rb'
|
||||
- 'spec/lib/gitlab/diff/position_tracer/line_strategy_spec.rb'
|
||||
- 'spec/lib/gitlab/diff/suggestion_spec.rb'
|
||||
- 'spec/lib/gitlab/doorkeeper_secret_storing/secret/pbkdf2_sha512_spec.rb'
|
||||
- 'spec/lib/gitlab/doorkeeper_secret_storing/token/pbkdf2_sha512_spec.rb'
|
||||
- 'spec/lib/gitlab/email/failure_handler_spec.rb'
|
||||
- 'spec/lib/gitlab/email/handler/create_issue_handler_spec.rb'
|
||||
- 'spec/lib/gitlab/email/handler/create_merge_request_handler_spec.rb'
|
||||
|
|
@ -3361,6 +3373,7 @@ Layout/LineLength:
|
|||
- 'spec/lib/gitlab/legacy_github_import/pull_request_formatter_spec.rb'
|
||||
- 'spec/lib/gitlab/lfs/client_spec.rb'
|
||||
- 'spec/lib/gitlab/mail_room/authenticator_spec.rb'
|
||||
- 'spec/lib/gitlab/merge_requests/message_generator_spec.rb'
|
||||
- 'spec/lib/gitlab/metrics/background_transaction_spec.rb'
|
||||
- 'spec/lib/gitlab/metrics/boot_time_tracker_spec.rb'
|
||||
- 'spec/lib/gitlab/metrics/elasticsearch_rack_middleware_spec.rb'
|
||||
|
|
@ -3406,6 +3419,7 @@ Layout/LineLength:
|
|||
- 'spec/lib/gitlab/route_map_spec.rb'
|
||||
- 'spec/lib/gitlab/sanitizers/exif_spec.rb'
|
||||
- 'spec/lib/gitlab/sanitizers/svg_spec.rb'
|
||||
- 'spec/lib/gitlab/search/abuse_detection_spec.rb'
|
||||
- 'spec/lib/gitlab/search/found_blob_spec.rb'
|
||||
- 'spec/lib/gitlab/search_results_spec.rb'
|
||||
- 'spec/lib/gitlab/serializer/pagination_spec.rb'
|
||||
|
|
@ -3484,6 +3498,7 @@ Layout/LineLength:
|
|||
- 'spec/mailers/emails/service_desk_spec.rb'
|
||||
- 'spec/mailers/notify_spec.rb'
|
||||
- 'spec/migrations/active_record/schema_spec.rb'
|
||||
- 'spec/migrations/db/post_migrate/20240319005754_swap_columns_for_upstream_pipeline_id_between_ci_builds_and_ci_pipelines_spec.rb'
|
||||
- 'spec/models/active_session_spec.rb'
|
||||
- 'spec/models/alert_management/alert_spec.rb'
|
||||
- 'spec/models/analytics/cycle_analytics/aggregation_spec.rb'
|
||||
|
|
@ -3835,6 +3850,7 @@ Layout/LineLength:
|
|||
- 'spec/requests/projects/merge_requests/context_commit_diffs_spec.rb'
|
||||
- 'spec/requests/projects/merge_requests_discussions_spec.rb'
|
||||
- 'spec/requests/projects/merge_requests_spec.rb'
|
||||
- 'spec/requests/projects/releases_controller_spec.rb'
|
||||
- 'spec/requests/projects/settings/access_tokens_controller_spec.rb'
|
||||
- 'spec/requests/projects/tags_controller_spec.rb'
|
||||
- 'spec/requests/projects_controller_spec.rb'
|
||||
|
|
@ -4129,6 +4145,7 @@ Layout/LineLength:
|
|||
- 'spec/support/helpers/live_debugger.rb'
|
||||
- 'spec/support/helpers/login_helpers.rb'
|
||||
- 'spec/support/helpers/merge_request_diff_helpers.rb'
|
||||
- 'spec/support/helpers/migrations_helpers/vulnerabilities_findings_helper.rb'
|
||||
- 'spec/support/helpers/prometheus_helpers.rb'
|
||||
- 'spec/support/helpers/seed_repo.rb'
|
||||
- 'spec/support/helpers/selection_helper.rb'
|
||||
|
|
@ -4171,6 +4188,7 @@ Layout/LineLength:
|
|||
- 'spec/support/shared_examples/features/editable_merge_request_shared_examples.rb'
|
||||
- 'spec/support/shared_examples/features/error_tracking_shared_example.rb'
|
||||
- 'spec/support/shared_examples/features/manage_applications_shared_examples.rb'
|
||||
- 'spec/support/shared_examples/features/milestone_editing_shared_examples.rb'
|
||||
- 'spec/support/shared_examples/features/page_description_shared_examples.rb'
|
||||
- 'spec/support/shared_examples/features/sidebar/sidebar_milestone_shared_examples.rb'
|
||||
- 'spec/support/shared_examples/features/wiki/user_views_asciidoc_page_with_includes_shared_examples.rb'
|
||||
|
|
|
|||
|
|
@ -1,56 +1,5 @@
|
|||
---
|
||||
# Cop supports --autocorrect.
|
||||
Lint/RedundantCopDisableDirective:
|
||||
# Offense count: 62
|
||||
# Temporarily disabled due to too many offenses
|
||||
# Temporarily disabled
|
||||
Enabled: false
|
||||
Exclude:
|
||||
- 'app/controllers/groups/milestones_controller.rb'
|
||||
- 'app/models/concerns/integrations/base/integration.rb'
|
||||
- 'app/models/work_items/type.rb'
|
||||
- 'app/policies/issue_policy.rb'
|
||||
- 'app/services/ci/runners/set_runner_associated_projects_service.rb'
|
||||
- 'app/services/work_items/data_sync/clone_service.rb'
|
||||
- 'app/services/work_items/data_sync/move_service.rb'
|
||||
- 'db/migrate/20241021082113_create_partitioned_ci_runners.rb'
|
||||
- 'db/migrate/20241024204816_create_partitioned_ci_runner_managers.rb'
|
||||
- 'db/post_migrate/20241021163518_drop_user_canonical_emails_table.rb'
|
||||
- 'ee/app/controllers/ee/projects/settings/ci_cd_controller.rb'
|
||||
- 'ee/app/models/ee/audit_events/project_audit_event.rb'
|
||||
- 'ee/app/services/search/zoekt/routing_service.rb'
|
||||
- 'ee/app/services/vulnerabilities/statistics/adjustment_service.rb'
|
||||
- 'ee/db/geo/migrate/20210504143244_add_verification_to_merge_request_diff_registry.rb'
|
||||
- 'ee/spec/features/groups/settings/domain_verification_spec.rb'
|
||||
- 'ee/spec/features/projects/mirror_spec.rb'
|
||||
- 'ee/spec/lib/banzai/filter/references/iterations_cadence_reference_filter_spec.rb'
|
||||
- 'ee/spec/lib/gitlab/elastic/client_spec.rb'
|
||||
- 'ee/spec/lib/gitlab/usage/metrics/instrumentations/count_secure_pipelines_metric_spec.rb'
|
||||
- 'ee/spec/lib/gitlab/usage/metrics/instrumentations/count_security_scans_metric_spec.rb'
|
||||
- 'ee/spec/support/shared_examples/features/dashboard_saml_reauth_banner_shared_examples.rb'
|
||||
- 'ee/spec/views/admin/users/show.html.haml_spec.rb'
|
||||
- 'lib/api/submodules.rb'
|
||||
- 'lib/gitlab/popen/runner.rb'
|
||||
- 'qa/qa/resource/user_runners.rb'
|
||||
- 'qa/qa/service/docker_run/gitlab_runner.rb'
|
||||
- 'qa/qa/vendor/one_password/cli.rb'
|
||||
- 'spec/components/previews/pajamas/banner_component_preview.rb'
|
||||
- 'spec/features/groups/participants_autocomplete_spec.rb'
|
||||
- 'spec/features/merge_request/user_edits_mr_spec.rb'
|
||||
- 'spec/lib/gitlab/doorkeeper_secret_storing/secret/pbkdf2_sha512_spec.rb'
|
||||
- 'spec/lib/gitlab/doorkeeper_secret_storing/token/pbkdf2_sha512_spec.rb'
|
||||
- 'spec/lib/gitlab/merge_requests/message_generator_spec.rb'
|
||||
- 'spec/lib/gitlab/search/abuse_detection_spec.rb'
|
||||
- 'spec/migrations/db/post_migrate/20240319005754_swap_columns_for_upstream_pipeline_id_between_ci_builds_and_ci_pipelines_spec.rb'
|
||||
- 'spec/models/concerns/encrypted_user_password_spec.rb'
|
||||
- 'spec/requests/api/alert_management_alerts_spec.rb'
|
||||
- 'spec/requests/projects/releases_controller_spec.rb'
|
||||
- 'spec/scripts/setup/tests-metadata_spec.rb'
|
||||
- 'spec/services/ci/create_pipeline_service/logger_spec.rb'
|
||||
- 'spec/services/packages/pypi/create_package_service_spec.rb'
|
||||
- 'spec/services/pages_domains/create_acme_order_service_spec.rb'
|
||||
- 'spec/support/helpers/migrations_helpers/vulnerabilities_findings_helper.rb'
|
||||
- 'spec/support/helpers/wait_for_requests.rb'
|
||||
- 'spec/support/shared_examples/features/milestone_editing_shared_examples.rb'
|
||||
- 'spec/support/shared_examples/models/concerns/protected_ref_access_shared_examples.rb'
|
||||
- 'tooling/danger/sidekiq_queues.rb'
|
||||
- 'tooling/danger/stable_branch.rb'
|
||||
|
|
|
|||
|
|
@ -705,7 +705,6 @@ RSpec/ContextWording:
|
|||
- 'ee/spec/services/milestones/update_service_spec.rb'
|
||||
- 'ee/spec/services/package_metadata/ingestion/ingestion_service_spec.rb'
|
||||
- 'ee/spec/services/personal_access_tokens/revoke_invalid_tokens_spec.rb'
|
||||
- 'ee/spec/services/personal_access_tokens/rotation_verifier_service_spec.rb'
|
||||
- 'ee/spec/services/projects/alerting/notify_service_spec.rb'
|
||||
- 'ee/spec/services/projects/create_from_template_service_spec.rb'
|
||||
- 'ee/spec/services/projects/destroy_service_spec.rb'
|
||||
|
|
|
|||
|
|
@ -198,7 +198,6 @@ RSpec/ExampleWithoutDescription:
|
|||
- 'ee/spec/services/package_metadata/compressed_package_data_object_spec.rb'
|
||||
- 'ee/spec/services/package_metadata/data_object_fabricator_spec.rb'
|
||||
- 'ee/spec/services/package_metadata/data_objects/cve_enrichment_spec.rb'
|
||||
- 'ee/spec/services/personal_access_tokens/rotation_verifier_service_spec.rb'
|
||||
- 'ee/spec/services/sbom/ingestion/occurrence_map_spec.rb'
|
||||
- 'ee/spec/services/security/scan_result_policies/sync_findings_to_approval_rules_service_spec.rb'
|
||||
- 'ee/spec/services/security/scan_result_policies/update_approvals_service_spec.rb'
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
9d2ddd160b10e94d8ff252071373d278bfaf4208
|
||||
9fd3ef87a54f73b17bf775d30b2153e8b242cf1c
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import { __, s__ } from '~/locale';
|
|||
export const ACCESS_LEVEL_NO_ACCESS_INTEGER = 0;
|
||||
export const ACCESS_LEVEL_MINIMAL_ACCESS_INTEGER = 5;
|
||||
export const ACCESS_LEVEL_GUEST_INTEGER = 10;
|
||||
export const ACCESS_LEVEL_PLANNER_INTEGER = 15;
|
||||
export const ACCESS_LEVEL_REPORTER_INTEGER = 20;
|
||||
export const ACCESS_LEVEL_DEVELOPER_INTEGER = 30;
|
||||
export const ACCESS_LEVEL_MAINTAINER_INTEGER = 40;
|
||||
|
|
@ -14,6 +15,7 @@ export const ACCESS_LEVEL_ADMIN_INTEGER = 60;
|
|||
export const ACCESS_LEVEL_NO_ACCESS_STRING = 'NO_ACCESS';
|
||||
export const ACCESS_LEVEL_MINIMAL_ACCESS_STRING = 'MINIMAL_ACCESS';
|
||||
export const ACCESS_LEVEL_GUEST_STRING = 'GUEST';
|
||||
export const ACCESS_LEVEL_PLANNER_STRING = 'PLANNER';
|
||||
export const ACCESS_LEVEL_REPORTER_STRING = 'REPORTER';
|
||||
export const ACCESS_LEVEL_DEVELOPER_STRING = 'DEVELOPER';
|
||||
export const ACCESS_LEVEL_MAINTAINER_STRING = 'MAINTAINER';
|
||||
|
|
@ -23,6 +25,7 @@ export const ACCESS_LEVELS_INTEGER_TO_STRING = {
|
|||
[ACCESS_LEVEL_NO_ACCESS_INTEGER]: ACCESS_LEVEL_NO_ACCESS_STRING,
|
||||
[ACCESS_LEVEL_MINIMAL_ACCESS_INTEGER]: ACCESS_LEVEL_MINIMAL_ACCESS_STRING,
|
||||
[ACCESS_LEVEL_GUEST_INTEGER]: ACCESS_LEVEL_GUEST_STRING,
|
||||
[ACCESS_LEVEL_PLANNER_INTEGER]: ACCESS_LEVEL_PLANNER_STRING,
|
||||
[ACCESS_LEVEL_REPORTER_INTEGER]: ACCESS_LEVEL_REPORTER_STRING,
|
||||
[ACCESS_LEVEL_DEVELOPER_INTEGER]: ACCESS_LEVEL_DEVELOPER_STRING,
|
||||
[ACCESS_LEVEL_MAINTAINER_INTEGER]: ACCESS_LEVEL_MAINTAINER_STRING,
|
||||
|
|
@ -32,6 +35,7 @@ export const ACCESS_LEVELS_INTEGER_TO_STRING = {
|
|||
const ACCESS_LEVEL_NO_ACCESS = __('No access');
|
||||
const ACCESS_LEVEL_MINIMAL_ACCESS = __('Minimal Access');
|
||||
const ACCESS_LEVEL_GUEST = __('Guest');
|
||||
const ACCESS_LEVEL_PLANNER = __('Planner');
|
||||
const ACCESS_LEVEL_REPORTER = __('Reporter');
|
||||
const ACCESS_LEVEL_DEVELOPER = __('Developer');
|
||||
const ACCESS_LEVEL_MAINTAINER = __('Maintainer');
|
||||
|
|
@ -56,6 +60,16 @@ export const BASE_ROLES = [
|
|||
'MemberRole|The Guest role is for users who need visibility into a project or group but should not have the ability to make changes, such as external stakeholders.',
|
||||
),
|
||||
},
|
||||
{
|
||||
value: 'PLANNER',
|
||||
text: ACCESS_LEVEL_PLANNER,
|
||||
accessLevel: ACCESS_LEVEL_PLANNER_INTEGER,
|
||||
memberRoleId: null,
|
||||
occupiesSeat: true,
|
||||
description: s__(
|
||||
'MemberRole|The Planner role is suitable for team members who need to manage projects and track work items but do not need to contribute code, such as project managers and scrum masters.',
|
||||
),
|
||||
},
|
||||
{
|
||||
value: 'REPORTER',
|
||||
text: ACCESS_LEVEL_REPORTER,
|
||||
|
|
|
|||
|
|
@ -45,6 +45,10 @@ export default {
|
|||
|
||||
urlParams.search = this.searchTerm.length > 0 ? this.searchTerm : null;
|
||||
|
||||
if (urlParams.search) {
|
||||
urlParams.state = 'all';
|
||||
}
|
||||
|
||||
const newUrl = mergeUrlParams(urlParams, this.projectBranchesFilteredPath);
|
||||
visitUrl(newUrl);
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,3 +1,8 @@
|
|||
import initTodosApp from '~/todos';
|
||||
import Todos from './todos';
|
||||
|
||||
new Todos(); // eslint-disable-line no-new
|
||||
if (gon.features.todosVueApplication) {
|
||||
initTodosApp();
|
||||
} else {
|
||||
new Todos(); // eslint-disable-line no-new
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +0,0 @@
|
|||
import initTodosApp from '~/todos';
|
||||
|
||||
initTodosApp();
|
||||
|
|
@ -11,16 +11,12 @@ import {
|
|||
} from '@gitlab/ui';
|
||||
import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
|
||||
import { getHTTPProtocol } from '~/lib/utils/url_utility';
|
||||
import { __, s__, sprintf } from '~/locale';
|
||||
import { __, sprintf } from '~/locale';
|
||||
|
||||
export default {
|
||||
i18n: {
|
||||
steps: {
|
||||
step1: s__('WikiClone|Step 1: Clone repository'),
|
||||
step2: s__('WikiClone|Step 2: Install and start Gollum'),
|
||||
step2Directory: s__('WikiClone|Go to directory'),
|
||||
step2Install: s__('WikiClone|Install Gollum'),
|
||||
step2Start: s__('WikiClone|Start Gollum and edit locally'),
|
||||
step1: __('Clone repository'),
|
||||
},
|
||||
cloneWithSsh: __('Clone with SSH'),
|
||||
copyToClipboard: __('Copy to clipboard'),
|
||||
|
|
@ -62,15 +58,6 @@ export default {
|
|||
cloneHttpUrlDisplay() {
|
||||
return `git clone ${this.cloneHttpUrl}`; // eslint-disable-line @gitlab/require-i18n-strings
|
||||
},
|
||||
directoryCommand() {
|
||||
return `cd ${this.wikiPath}`; // eslint-disable-line @gitlab/require-i18n-strings
|
||||
},
|
||||
installCommand() {
|
||||
return 'gem install gollum'; // eslint-disable-line @gitlab/require-i18n-strings
|
||||
},
|
||||
gollumCommand() {
|
||||
return 'gollum';
|
||||
},
|
||||
listItem() {
|
||||
return {
|
||||
text: __('Clone repository'),
|
||||
|
|
@ -156,65 +143,6 @@ export default {
|
|||
</gl-form-input-group>
|
||||
</gl-form-group>
|
||||
</div>
|
||||
<div class="gl-mt-6">
|
||||
<h3 class="gl-heading-4">
|
||||
{{ $options.i18n.steps.step2 }}
|
||||
</h3>
|
||||
<gl-form-group :label="$options.i18n.steps.step2Directory" label-for="go-to-directory">
|
||||
<gl-form-input-group
|
||||
id="go-to-directory"
|
||||
:value="directoryCommand"
|
||||
:label="$options.i18n.steps.step2Directory"
|
||||
input-class="!gl-font-monospace"
|
||||
readonly
|
||||
select-on-click
|
||||
>
|
||||
<template #append>
|
||||
<clipboard-button
|
||||
:text="directoryCommand"
|
||||
:title="$options.i18n.copyToClipboard"
|
||||
data-clipboard-target="#go-to-directory"
|
||||
/>
|
||||
</template>
|
||||
</gl-form-input-group>
|
||||
</gl-form-group>
|
||||
<gl-form-group :label="$options.i18n.steps.step2Install" label-for="install-gollum">
|
||||
<gl-form-input-group
|
||||
id="install-gollum"
|
||||
:value="installCommand"
|
||||
:label="$options.i18n.steps.step2Install"
|
||||
input-class="!gl-font-monospace"
|
||||
readonly
|
||||
select-on-click
|
||||
>
|
||||
<template #append>
|
||||
<clipboard-button
|
||||
:text="installCommand"
|
||||
:title="$options.i18n.copyToClipboard"
|
||||
data-clipboard-target="#install-gollum"
|
||||
/>
|
||||
</template>
|
||||
</gl-form-input-group>
|
||||
</gl-form-group>
|
||||
<gl-form-group :label="$options.i18n.steps.step2Start" label-for="run-gollum">
|
||||
<gl-form-input-group
|
||||
id="run-gollum"
|
||||
:value="gollumCommand"
|
||||
:label="$options.i18n.steps.step2Start"
|
||||
input-class="!gl-font-monospace"
|
||||
readonly
|
||||
select-on-click
|
||||
>
|
||||
<template #append>
|
||||
<clipboard-button
|
||||
:text="gollumCommand"
|
||||
:title="$options.i18n.copyToClipboard"
|
||||
data-clipboard-target="#run-gollum"
|
||||
/>
|
||||
</template>
|
||||
</gl-form-input-group>
|
||||
</gl-form-group>
|
||||
</div>
|
||||
</gl-modal>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import CustomizableDashboard from './customizable_dashboard.vue';
|
|||
|
||||
export default {
|
||||
component: CustomizableDashboard,
|
||||
title: '~/vue_shared/components/customizable_dashboard',
|
||||
title: 'vue_shared/components/customizable_dashboard',
|
||||
};
|
||||
|
||||
const Template = (args, { argTypes }) => ({
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import PanelsBase from './panels_base.vue';
|
|||
|
||||
export default {
|
||||
component: PanelsBase,
|
||||
title: '~/vue_shared/components/panels_base',
|
||||
title: 'vue_shared/components/panels_base',
|
||||
};
|
||||
|
||||
const Template = (args, { argTypes }) => ({
|
||||
|
|
|
|||
|
|
@ -34,14 +34,6 @@
|
|||
text-align: center;
|
||||
}
|
||||
|
||||
.no-btn {
|
||||
border: 0;
|
||||
background: none;
|
||||
outline: none;
|
||||
width: 100%;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.environment-child-row {
|
||||
padding-left: 20px;
|
||||
}
|
||||
|
|
@ -90,43 +82,6 @@
|
|||
}
|
||||
}
|
||||
|
||||
.metric-area {
|
||||
opacity: 0.25;
|
||||
}
|
||||
|
||||
.rect-text-metric {
|
||||
fill: var(--white, $white);
|
||||
stroke-width: 1;
|
||||
stroke: var(--gray-600, $gray-600);
|
||||
}
|
||||
|
||||
.rect-axis-text {
|
||||
fill: var(--white, $white);
|
||||
}
|
||||
|
||||
.selected-metric-line {
|
||||
stroke: var(--gray-900, $gray-900);
|
||||
stroke-width: 1;
|
||||
}
|
||||
|
||||
.deployment-line {
|
||||
stroke: var(--white, $white);
|
||||
stroke-width: 1;
|
||||
}
|
||||
|
||||
.divider-line {
|
||||
stroke-width: 1;
|
||||
stroke: var(--gray-600, $gray-600);
|
||||
}
|
||||
|
||||
.environments-actions {
|
||||
.external-url,
|
||||
.monitoring-url,
|
||||
.terminal-button {
|
||||
width: 38px;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Deploy boards
|
||||
*/
|
||||
|
|
@ -170,10 +125,6 @@
|
|||
margin-left: 10px;
|
||||
}
|
||||
|
||||
&.deploy-board-error-message {
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.deploy-board-empty-state-text {
|
||||
order: 2;
|
||||
flex-wrap: wrap;
|
||||
|
|
|
|||
|
|
@ -126,15 +126,9 @@
|
|||
overflow: visible;
|
||||
}
|
||||
|
||||
|
||||
div:has(> .diff-file-is-active) {
|
||||
box-shadow: 0 0 0 1px var(--gl-focus-ring-outer-color);
|
||||
border-radius: #{$border-radius + $gl-spacing-scale-1};
|
||||
padding: $gl-spacing-scale-1;
|
||||
|
||||
.diff-file-is-active {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.diff-file-is-active {
|
||||
outline: 1px solid var(--gl-focus-ring-outer-color);
|
||||
outline-offset: 2px;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -191,7 +191,6 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController
|
|||
allowed_to_push: [:access_level]
|
||||
}
|
||||
] },
|
||||
:can_create_organization,
|
||||
:lets_encrypt_notification_email,
|
||||
:lets_encrypt_terms_of_service_accepted,
|
||||
:domain_denylist_file,
|
||||
|
|
|
|||
|
|
@ -13,17 +13,26 @@ class Dashboard::TodosController < Dashboard::ApplicationController
|
|||
urgency :low
|
||||
|
||||
def index
|
||||
@sort = pagination_params[:sort]
|
||||
@todos = @todos.page(pagination_params[:page])
|
||||
@todos = @todos.with_entity_associations
|
||||
push_frontend_feature_flag(:todos_vue_application, current_user)
|
||||
|
||||
return if redirect_out_of_range(@todos, todos_page_count(@todos))
|
||||
# When removing the `todos_vue_application`, also drop the #vue method below
|
||||
if Feature.enabled?(:todos_vue_application, current_user)
|
||||
render :vue
|
||||
else
|
||||
@sort = pagination_params[:sort]
|
||||
@todos = @todos.page(pagination_params[:page])
|
||||
@todos = @todos.with_entity_associations
|
||||
|
||||
@allowed_todos = ::Todos::AllowedTargetFilterService.new(@todos, current_user).execute
|
||||
return if redirect_out_of_range(@todos, todos_page_count(@todos))
|
||||
|
||||
@allowed_todos = ::Todos::AllowedTargetFilterService.new(@todos, current_user).execute
|
||||
end
|
||||
end
|
||||
|
||||
# To be removed along with the `todos_vue_application` feature flag.
|
||||
# Also make sure to remove the corresponding route in `config/routes/dashboard.rb`.
|
||||
def vue
|
||||
redirect_to(dashboard_todos_path, status: :found) unless Feature.enabled?(:todos_vue_application, current_user)
|
||||
redirect_to(dashboard_todos_path, status: :found)
|
||||
end
|
||||
|
||||
def destroy
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ class Groups::MilestonesController < Groups::ApplicationController
|
|||
render json: {
|
||||
errors: [
|
||||
format(
|
||||
_("Someone edited this %{model_name} at the same time you did. Please refresh your browser and make sure your changes will not unintentionally remove theirs."), # rubocop:disable Layout/LineLength
|
||||
_("Someone edited this %{model_name} at the same time you did. Please refresh your browser and make sure your changes will not unintentionally remove theirs."),
|
||||
model_name: _('milestone')
|
||||
)
|
||||
]
|
||||
|
|
|
|||
|
|
@ -52,8 +52,7 @@ class RootController < Dashboard::ProjectsController
|
|||
when 'groups'
|
||||
redirect_to(dashboard_groups_path)
|
||||
when 'todos'
|
||||
redirect_to(Feature.enabled?(:todos_vue_application,
|
||||
current_user) ? vue_dashboard_todos_path : dashboard_todos_path)
|
||||
redirect_to(dashboard_todos_path)
|
||||
when 'issues'
|
||||
redirect_to(issues_dashboard_path(assignee_username: current_user.username))
|
||||
when 'merge_requests'
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
module Issues
|
||||
class ConfidentialityFilter < Issuables::BaseFilter
|
||||
CONFIDENTIAL_ACCESS_LEVEL = Gitlab::Access::REPORTER
|
||||
CONFIDENTIAL_ACCESS_LEVEL = Gitlab::Access::PLANNER
|
||||
|
||||
def initialize(current_user:, parent:, assignee_filter:, related_groups: nil, **kwargs)
|
||||
@current_user = current_user
|
||||
|
|
|
|||
|
|
@ -35,6 +35,10 @@ module Resolvers
|
|||
required: false,
|
||||
description: 'Filter projects by programming language name (case insensitive). For example: "css" or "ruby".'
|
||||
|
||||
before_connection_authorization do |projects, current_user|
|
||||
::Preloaders::UserMaxAccessLevelInProjectsPreloader.new(projects, current_user).execute
|
||||
end
|
||||
|
||||
def resolve_with_lookahead(**args)
|
||||
validate_args!(args)
|
||||
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ module Types
|
|||
end
|
||||
|
||||
value 'GUEST', value: Gitlab::Access::GUEST, description: descriptions[Gitlab::Access::GUEST]
|
||||
value 'PLANNER', value: Gitlab::Access::PLANNER, description: descriptions[Gitlab::Access::PLANNER]
|
||||
value 'REPORTER', value: Gitlab::Access::REPORTER, description: descriptions[Gitlab::Access::REPORTER]
|
||||
value 'DEVELOPER', value: Gitlab::Access::DEVELOPER, description: descriptions[Gitlab::Access::DEVELOPER]
|
||||
value 'MAINTAINER', value: Gitlab::Access::MAINTAINER, description: descriptions[Gitlab::Access::MAINTAINER]
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ module Types
|
|||
Types::WorkItems::ClosingMergeRequestType.connection_type,
|
||||
null: true,
|
||||
description: 'Merge requests that will close the work item when merged.'
|
||||
field :related_branches, # rubocop:disable GraphQL/ExtractType -- no need to extract to related
|
||||
field :related_branches,
|
||||
Types::WorkItems::RelatedBranchType.connection_type,
|
||||
calls_gitaly: true,
|
||||
description: 'Branches that have referred to the work item, but do not have an associated merge request.',
|
||||
|
|
|
|||
|
|
@ -502,6 +502,7 @@ module ApplicationSettingsHelper
|
|||
:pipeline_limit_per_project_user_sha,
|
||||
:invitation_flow_enforcement,
|
||||
:can_create_group,
|
||||
:can_create_organization,
|
||||
:bulk_import_concurrent_pipeline_batch_limit,
|
||||
:concurrent_relation_batch_export_limit,
|
||||
:bulk_import_enabled,
|
||||
|
|
|
|||
|
|
@ -771,6 +771,7 @@ module ProjectsHelper
|
|||
Gitlab::Access::NO_ACCESS => _('No access'),
|
||||
Gitlab::Access::MINIMAL_ACCESS => _("Minimal Access"),
|
||||
Gitlab::Access::GUEST => _('Guest'),
|
||||
Gitlab::Access::PLANNER => _('Planner'),
|
||||
Gitlab::Access::REPORTER => _('Reporter'),
|
||||
Gitlab::Access::DEVELOPER => _('Developer'),
|
||||
Gitlab::Access::MAINTAINER => _('Maintainer'),
|
||||
|
|
|
|||
|
|
@ -98,11 +98,7 @@ module SidebarsHelper
|
|||
issues_dashboard_path: issues_dashboard_path(assignee_username: user.username),
|
||||
merge_request_dashboard_path: user.merge_request_dashboard_enabled? ? merge_requests_dashboard_path : nil,
|
||||
|
||||
todos_dashboard_path: if Feature.enabled?(:todos_vue_application, user)
|
||||
vue_dashboard_todos_path
|
||||
else
|
||||
dashboard_todos_path
|
||||
end,
|
||||
todos_dashboard_path: dashboard_todos_path,
|
||||
|
||||
create_new_menu_groups: create_new_menu_groups(group: group, project: project),
|
||||
merge_request_menu: create_merge_request_menu(user),
|
||||
|
|
|
|||
|
|
@ -122,8 +122,14 @@ module Ci
|
|||
project = options&.dig(:trigger, :project)
|
||||
next unless project
|
||||
|
||||
scoped_variables.to_runner_variables.then do |all_variables|
|
||||
::ExpandVariables.expand(project, all_variables)
|
||||
if ci_optimize_memory_for_variables_enabled?
|
||||
scoped_variables.to_hash_variables.then do |all_variables|
|
||||
::ExpandVariables.expand(project, all_variables)
|
||||
end
|
||||
else
|
||||
scoped_variables.to_runner_variables.then do |all_variables|
|
||||
::ExpandVariables.expand(project, all_variables)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -223,8 +229,14 @@ module Ci
|
|||
branch = options&.dig(:trigger, :branch)
|
||||
return unless branch
|
||||
|
||||
scoped_variables.to_runner_variables.then do |all_variables|
|
||||
::ExpandVariables.expand(branch, all_variables)
|
||||
if ci_optimize_memory_for_variables_enabled?
|
||||
scoped_variables.to_hash_variables.then do |all_variables|
|
||||
::ExpandVariables.expand(branch, all_variables)
|
||||
end
|
||||
else
|
||||
scoped_variables.to_runner_variables.then do |all_variables|
|
||||
::ExpandVariables.expand(branch, all_variables)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -339,6 +351,11 @@ module Ci
|
|||
}
|
||||
}
|
||||
end
|
||||
|
||||
def ci_optimize_memory_for_variables_enabled?
|
||||
::Feature.enabled?(:ci_optimize_memory_for_variables, project)
|
||||
end
|
||||
strong_memoize_attr :ci_optimize_memory_for_variables_enabled?
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -692,7 +692,7 @@ module Integrations
|
|||
|
||||
def api_field_names
|
||||
fields # rubocop:disable Style/NumberedParameters -- existing code moved as is
|
||||
.reject { _1[:type] == :password || _1[:name] == 'webhook' || (_1.key?(:if) && _1[:if] != true) } # rubocop:disable Style/NumberedParameters -- existing code moved as is
|
||||
.reject { _1[:type] == :password || _1[:name] == 'webhook' || (_1.key?(:if) && _1[:if] != true) }
|
||||
.pluck(:name) # rubocop:disable Database/AvoidUsingPluckWithoutLimit -- existing code moved as is
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -2,14 +2,10 @@
|
|||
|
||||
module TokenAuthenticatableStrategies
|
||||
class Base
|
||||
RANDOM_BYTES_LENGTH = 16
|
||||
TRUE_PROC = ->(_) { true }
|
||||
|
||||
attr_reader :klass, :token_field, :expires_at_field, :options
|
||||
|
||||
def self.random_bytes
|
||||
SecureRandom.random_bytes(RANDOM_BYTES_LENGTH)
|
||||
end
|
||||
|
||||
def initialize(klass, token_field, options)
|
||||
@klass = klass
|
||||
@token_field = token_field
|
||||
|
|
@ -94,6 +90,8 @@ module TokenAuthenticatableStrategies
|
|||
|
||||
private
|
||||
|
||||
# If a `format_with_prefix` option is provided, it applies and returns the formatted token.
|
||||
# Otherwise, default implementation returns the token as-is
|
||||
def prefix_for(token_owner_record)
|
||||
case prefix_option = options[:format_with_prefix]
|
||||
when nil
|
||||
|
|
@ -105,18 +103,9 @@ module TokenAuthenticatableStrategies
|
|||
end
|
||||
end
|
||||
|
||||
# If a `format_with_prefix` option is provided, it applies and returns the formatted token.
|
||||
# Otherwise, default implementation returns the token as-is
|
||||
def format_token(token_owner_record, token)
|
||||
prefix = prefix_for(token_owner_record)
|
||||
|
||||
prefix ? "#{prefix}#{token}" : token
|
||||
end
|
||||
|
||||
def write_new_token(token_owner_record)
|
||||
new_token = generate_available_token(token_owner_record)
|
||||
formatted_token = format_token(token_owner_record, new_token)
|
||||
set_token(token_owner_record, formatted_token)
|
||||
set_token(token_owner_record, new_token)
|
||||
|
||||
if expirable?
|
||||
token_owner_record[@expires_at_field] = @options[:expires_at].to_proc.call(token_owner_record)
|
||||
|
|
@ -135,33 +124,30 @@ module TokenAuthenticatableStrategies
|
|||
end
|
||||
|
||||
def generate_token(token_owner_record)
|
||||
if @options[:token_generator]
|
||||
@options[:token_generator].call
|
||||
if token_generator_proc
|
||||
"#{prefix_for(token_owner_record)}#{token_generator_proc.call}"
|
||||
# TODO: Make all tokens routable by default: https://gitlab.com/gitlab-org/gitlab/-/issues/500016
|
||||
elsif generate_routable_token?(token_owner_record)
|
||||
generate_routable_payload(@options[:routable_token], token_owner_record)
|
||||
RoutableTokenGenerator.new(
|
||||
token_owner_record,
|
||||
routing_payload: options.dig(:routable_token, :payload),
|
||||
prefix: prefix_for(token_owner_record)
|
||||
).generate_token
|
||||
else
|
||||
Devise.friendly_token
|
||||
"#{prefix_for(token_owner_record)}#{Devise.friendly_token}"
|
||||
end
|
||||
end
|
||||
|
||||
def generate_routable_token?(token_owner_record)
|
||||
@options[:routable_token] && token_owner_record.respond_to?(:user) && Feature.enabled?(:routable_token, token_owner_record.user)
|
||||
@options.dig(:routable_token, :payload) && routing_condition_proc.call(token_owner_record)
|
||||
end
|
||||
|
||||
def default_routing_payload_hash
|
||||
{
|
||||
c: Settings.cell[:id]&.to_s(36),
|
||||
r: self.class.random_bytes
|
||||
}
|
||||
def token_generator_proc
|
||||
@options[:token_generator]
|
||||
end
|
||||
|
||||
def generate_routable_payload(routable_parts, token_owner_record)
|
||||
payload_hash = default_routing_payload_hash.merge(
|
||||
routable_parts.transform_values { |generator| generator.call(token_owner_record) }
|
||||
).compact_blank
|
||||
|
||||
Base64.urlsafe_encode64(payload_hash.sort.map { |k, v| "#{k}:#{v}" }.join("\n"), padding: false)
|
||||
def routing_condition_proc
|
||||
@options.dig(:routable_token, :if) || TRUE_PROC
|
||||
end
|
||||
|
||||
def relation(unscoped)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,112 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module TokenAuthenticatableStrategies
|
||||
class RoutableTokenGenerator
|
||||
RANDOM_BYTES_LENGTH = 16
|
||||
BASE64_PAYLOAD_LENGTH_HOLDER_BYTES = 2
|
||||
CRC_BYTES = 7
|
||||
VALID_ROUTING_KEYS = %i[c g o p u].freeze
|
||||
REQUIRED_ROUTING_KEYS = %i[o].freeze
|
||||
MAXIMUM_SIZE_OF_ROUTING_PAYLOAD = 159
|
||||
DEFAULT_ROUTING_PAYLOAD_HASH =
|
||||
{
|
||||
c: ->(_) { Settings.cell[:id] }
|
||||
}.freeze
|
||||
|
||||
PayloadTooLarge = Class.new(RuntimeError)
|
||||
MissingRequiredRoutingKeys = Class.new(ArgumentError)
|
||||
InvalidRoutingKeys = Class.new(ArgumentError)
|
||||
|
||||
def self.random_bytes(length)
|
||||
SecureRandom.random_bytes(length)
|
||||
end
|
||||
|
||||
attr_reader :token_owner_record, :routing_payload, :prefix
|
||||
|
||||
def initialize(token_owner_record, routing_payload:, prefix: '')
|
||||
@token_owner_record = token_owner_record
|
||||
@routing_payload = routing_payload
|
||||
@prefix = prefix
|
||||
|
||||
validate_routing_keys!
|
||||
end
|
||||
|
||||
def generate_token
|
||||
routing_hash
|
||||
.then { |routing_hash| build_payload(routing_hash) }
|
||||
.then { |payload| check_payload_size!(payload) }
|
||||
.then { |payload| encode_payload(payload, self.class.random_bytes(RANDOM_BYTES_LENGTH)) }
|
||||
.then { |encoded_payload| append_crc(encoded_payload) }
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def validate_routing_keys!
|
||||
check_required_routing_keys!
|
||||
check_invalid_routing_keys!
|
||||
end
|
||||
|
||||
def routing_hash
|
||||
routing_payload
|
||||
.merge(DEFAULT_ROUTING_PAYLOAD_HASH)
|
||||
.transform_values { |generator| format_value(generator.call(token_owner_record)) }
|
||||
.compact_blank
|
||||
.sort
|
||||
end
|
||||
|
||||
def build_payload(routing_hash)
|
||||
routing_hash.map { |k, v| "#{k}:#{v}" }.join("\n")
|
||||
end
|
||||
|
||||
def format_value(value)
|
||||
value.is_a?(Integer) ? value.to_s(36) : value
|
||||
end
|
||||
|
||||
def encode_payload(payload, random_bytes)
|
||||
encodable_payload = "#{payload}#{random_bytes}#{[random_bytes.size].pack('C')}"
|
||||
base64_payload = Base64.urlsafe_encode64(encodable_payload, padding: false)
|
||||
base64_payload_length = base64_payload.size.to_s(36).rjust(BASE64_PAYLOAD_LENGTH_HOLDER_BYTES, '0')
|
||||
"#{prefix}#{base64_payload}.#{base64_payload_length}"
|
||||
end
|
||||
|
||||
def append_crc(encoded_payload)
|
||||
crc = Zlib.crc32(encoded_payload).to_s(36).rjust(CRC_BYTES, '0')
|
||||
"#{encoded_payload}#{crc}"
|
||||
end
|
||||
|
||||
def check_required_routing_keys!
|
||||
missing_keys = REQUIRED_ROUTING_KEYS - routing_payload.keys
|
||||
return if missing_keys.empty?
|
||||
|
||||
raise MissingRequiredRoutingKeys, missing_keys_error_message(missing_keys)
|
||||
end
|
||||
|
||||
def check_invalid_routing_keys!
|
||||
invalid_keys = routing_payload.keys - VALID_ROUTING_KEYS
|
||||
return if invalid_keys.empty?
|
||||
|
||||
raise InvalidRoutingKeys, invalid_keys_error_message(invalid_keys)
|
||||
end
|
||||
|
||||
def check_payload_size!(payload)
|
||||
return payload if payload.size <= MAXIMUM_SIZE_OF_ROUTING_PAYLOAD
|
||||
|
||||
raise PayloadTooLarge, payload_size_error_message(payload.size)
|
||||
end
|
||||
|
||||
def missing_keys_error_message(missing_keys)
|
||||
"Missing required routing keys: #{missing_keys.map(&:inspect).join(', ')}. " \
|
||||
"Required routing keys are: #{REQUIRED_ROUTING_KEYS.map(&:inspect).join(', ')}."
|
||||
end
|
||||
|
||||
def invalid_keys_error_message(invalid_keys)
|
||||
"Invalid routing keys: #{invalid_keys.map(&:inspect).join(', ')}. " \
|
||||
"Valid routing keys are: #{VALID_ROUTING_KEYS.map(&:inspect).join(', ')}."
|
||||
end
|
||||
|
||||
def payload_size_error_message(size)
|
||||
"Routing payload is too big: #{size}. " \
|
||||
"Maximum size is #{MAXIMUM_SIZE_OF_ROUTING_PAYLOAD}."
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -553,6 +553,10 @@ class Group < Namespace
|
|||
add_member(user, :guest, current_user: current_user)
|
||||
end
|
||||
|
||||
def add_planner(user, current_user = nil)
|
||||
add_member(user, :planner, current_user: current_user)
|
||||
end
|
||||
|
||||
def add_reporter(user, current_user = nil)
|
||||
add_member(user, :reporter, current_user: current_user)
|
||||
end
|
||||
|
|
|
|||
|
|
@ -835,7 +835,7 @@ class Issue < ApplicationRecord
|
|||
elsif project.personal? && project.team.owner?(user)
|
||||
true
|
||||
elsif confidential? && !assignee_or_author?(user)
|
||||
project.member?(user, Gitlab::Access::REPORTER)
|
||||
project.member?(user, Gitlab::Access::PLANNER)
|
||||
elsif project.public? || (project.internal? && !user.external?)
|
||||
project.feature_available?(:issues, user)
|
||||
else
|
||||
|
|
@ -848,7 +848,7 @@ class Issue < ApplicationRecord
|
|||
return false unless namespace.is_a?(::Group)
|
||||
|
||||
if confidential? && !assignee_or_author?(user)
|
||||
namespace.member?(user, Gitlab::Access::REPORTER)
|
||||
namespace.member?(user, Gitlab::Access::PLANNER)
|
||||
else
|
||||
namespace.member?(user)
|
||||
end
|
||||
|
|
|
|||
|
|
@ -189,6 +189,7 @@ class Member < ApplicationRecord
|
|||
scope :has_access, -> { active.where('access_level > 0') }
|
||||
|
||||
scope :guests, -> { active.where(access_level: GUEST) }
|
||||
scope :planners, -> { active.where(access_level: PLANNER) }
|
||||
scope :reporters, -> { active.where(access_level: REPORTER) }
|
||||
scope :developers, -> { active.where(access_level: DEVELOPER) }
|
||||
scope :maintainers, -> { active.where(access_level: MAINTAINER) }
|
||||
|
|
|
|||
|
|
@ -538,7 +538,7 @@ class Project < ApplicationRecord
|
|||
with_options to: :team do
|
||||
delegate :members, prefix: true
|
||||
delegate :add_member, :add_members, :member?
|
||||
delegate :add_guest, :add_reporter, :add_developer, :add_maintainer, :add_owner, :add_role
|
||||
delegate :add_guest, :add_planner, :add_reporter, :add_developer, :add_maintainer, :add_owner, :add_role
|
||||
delegate :has_user?
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -11,6 +11,10 @@ class ProjectTeam
|
|||
add_member(user, :guest, current_user: current_user)
|
||||
end
|
||||
|
||||
def add_planner(user, current_user: nil)
|
||||
add_member(user, :planner, current_user: current_user)
|
||||
end
|
||||
|
||||
def add_reporter(user, current_user: nil)
|
||||
add_member(user, :reporter, current_user: current_user)
|
||||
end
|
||||
|
|
@ -89,6 +93,10 @@ class ProjectTeam
|
|||
@guests ||= fetch_members(Gitlab::Access::GUEST)
|
||||
end
|
||||
|
||||
def planners
|
||||
@planners ||= fetch_members(Gitlab::Access::PLANNER)
|
||||
end
|
||||
|
||||
def reporters
|
||||
@reporters ||= fetch_members(Gitlab::Access::REPORTER)
|
||||
end
|
||||
|
|
@ -152,6 +160,10 @@ class ProjectTeam
|
|||
max_member_access(user.id) == Gitlab::Access::GUEST
|
||||
end
|
||||
|
||||
def planner?(user)
|
||||
max_member_access(user.id) == Gitlab::Access::PLANNER
|
||||
end
|
||||
|
||||
def reporter?(user)
|
||||
max_member_access(user.id) == Gitlab::Access::REPORTER
|
||||
end
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ module System
|
|||
|
||||
ALLOWED_TARGET_ACCESS_LEVELS = [
|
||||
Gitlab::Access::GUEST,
|
||||
Gitlab::Access::PLANNER,
|
||||
Gitlab::Access::REPORTER,
|
||||
Gitlab::Access::DEVELOPER,
|
||||
Gitlab::Access::MAINTAINER,
|
||||
|
|
|
|||
|
|
@ -1424,7 +1424,7 @@ class User < ApplicationRecord
|
|||
#
|
||||
# This logic is duplicated from `Ability#project_abilities` into a SQL form.
|
||||
def projects_where_can_admin_issues
|
||||
authorized_projects(Gitlab::Access::REPORTER).non_archived.with_issues_enabled
|
||||
authorized_projects(Gitlab::Access::PLANNER).non_archived.with_issues_enabled
|
||||
end
|
||||
|
||||
# rubocop: disable CodeReuse/ServiceClass
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ module WorkItems
|
|||
issue: { name: TYPE_NAMES[:issue], icon_name: 'issue-type-issue', enum_value: 0, id: 1 },
|
||||
incident: { name: TYPE_NAMES[:incident], icon_name: 'issue-type-incident', enum_value: 1, id: 2 },
|
||||
test_case: { name: TYPE_NAMES[:test_case], icon_name: 'issue-type-test-case', enum_value: 2, id: 3 }, ## EE-only
|
||||
requirement: { name: TYPE_NAMES[:requirement], icon_name: 'issue-type-requirements', enum_value: 3, id: 4 }, ## EE-only # rubocop:disable Layout/LineLength -- Only comment exceeds length
|
||||
requirement: { name: TYPE_NAMES[:requirement], icon_name: 'issue-type-requirements', enum_value: 3, id: 4 }, ## EE
|
||||
task: { name: TYPE_NAMES[:task], icon_name: 'issue-type-task', enum_value: 4, id: 5 },
|
||||
objective: { name: TYPE_NAMES[:objective], icon_name: 'issue-type-objective', enum_value: 5, id: 6 }, ## EE-only
|
||||
key_result: { name: TYPE_NAMES[:key_result], icon_name: 'issue-type-keyresult', enum_value: 6, id: 7 }, ## EE-only
|
||||
|
|
|
|||
|
|
@ -16,11 +16,11 @@ class BoardPolicy < BasePolicy
|
|||
enable :read_issue
|
||||
end
|
||||
|
||||
condition(:reporter_of_group_projects) do
|
||||
condition(:planner_of_group_projects) do
|
||||
next unless @user
|
||||
|
||||
group_projects_for(user: @user, group: @subject.resource_parent)
|
||||
.visible_to_user_and_access_level(@user, ::Gitlab::Access::REPORTER)
|
||||
.visible_to_user_and_access_level(@user, ::Gitlab::Access::PLANNER)
|
||||
.exists?
|
||||
end
|
||||
|
||||
|
|
@ -28,7 +28,7 @@ class BoardPolicy < BasePolicy
|
|||
enable :create_non_backlog_issues
|
||||
end
|
||||
|
||||
rule { is_group_board & reporter_of_group_projects }.policy do
|
||||
rule { is_group_board & planner_of_group_projects }.policy do
|
||||
enable :create_non_backlog_issues
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -13,6 +13,8 @@ class GroupPolicy < Namespaces::GroupProjectNamespaceSharedPolicy
|
|||
condition(:has_access) { access_level != GroupMember::NO_ACCESS }
|
||||
|
||||
condition(:guest) { access_level >= GroupMember::GUEST }
|
||||
# This is not a linear condition (some policies available for planner might not be available for higher access levels)
|
||||
condition(:planner) { access_level == GroupMember::PLANNER }
|
||||
condition(:developer) { access_level >= GroupMember::DEVELOPER }
|
||||
condition(:owner) { access_level >= GroupMember::OWNER }
|
||||
condition(:maintainer) { access_level >= GroupMember::MAINTAINER }
|
||||
|
|
@ -135,6 +137,21 @@ class GroupPolicy < Namespaces::GroupProjectNamespaceSharedPolicy
|
|||
enable :award_emoji
|
||||
end
|
||||
|
||||
rule { planner }.policy do
|
||||
enable :planner_access
|
||||
enable :guest_access
|
||||
enable :admin_label
|
||||
enable :admin_milestone
|
||||
enable :admin_issue_board
|
||||
enable :admin_issue_board_list
|
||||
enable :admin_issue
|
||||
enable :update_issue
|
||||
enable :destroy_issue
|
||||
enable :read_confidential_issues
|
||||
enable :read_crm_organization
|
||||
enable :read_crm_contact
|
||||
end
|
||||
|
||||
rule { admin | organization_owner }.policy do
|
||||
enable :read_group
|
||||
end
|
||||
|
|
@ -403,7 +420,7 @@ class GroupPolicy < Namespaces::GroupProjectNamespaceSharedPolicy
|
|||
rule { can?(:admin_group) | can?(:admin_runner) }.enable :admin_group_or_admin_runner
|
||||
|
||||
# Should be matched with ProjectPolicy#read_internal_note
|
||||
rule { admin | reporter }.enable :read_internal_note
|
||||
rule { admin | reporter | planner }.enable :read_internal_note
|
||||
|
||||
rule { can?(:remove_group) }.enable :view_edit_page
|
||||
|
||||
|
|
|
|||
|
|
@ -12,6 +12,11 @@ class IssuablePolicy < BasePolicy
|
|||
@user && @subject.assignee_or_author?(@user)
|
||||
end
|
||||
|
||||
desc "User has planner or reporter access"
|
||||
condition(:planner_or_reporter_access) do
|
||||
can?(:reporter_access) || can?(:planner_access)
|
||||
end
|
||||
|
||||
condition(:is_author) { @subject&.author == @user }
|
||||
|
||||
condition(:is_incident) { @subject.incident_type_issue? }
|
||||
|
|
@ -53,7 +58,7 @@ class IssuablePolicy < BasePolicy
|
|||
enable :admin_incident_management_timeline_event
|
||||
end
|
||||
|
||||
rule { can?(:reporter_access) }.policy do
|
||||
rule { planner_or_reporter_access }.policy do
|
||||
enable :create_timelog
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -13,10 +13,12 @@ class IssuePolicy < IssuablePolicy
|
|||
false
|
||||
end
|
||||
|
||||
# rubocop:disable Cop/UserAdmin -- specifically check the admin attribute
|
||||
desc "User can read confidential issues"
|
||||
condition(:can_read_confidential) do
|
||||
@user && (@user.admin? || can?(:reporter_access) || assignee_or_author?) # rubocop:disable Cop/UserAdmin
|
||||
@user && (@user.admin? || planner_or_reporter_access? || assignee_or_author?)
|
||||
end
|
||||
# rubocop:enable Cop/UserAdmin
|
||||
|
||||
desc "Project belongs to a group, crm is enabled and user can read contacts in source group"
|
||||
condition(:can_read_crm_contacts, scope: :subject) do
|
||||
|
|
@ -45,13 +47,11 @@ class IssuePolicy < IssuablePolicy
|
|||
end
|
||||
end
|
||||
|
||||
# rubocop:disable Gitlab/FeatureFlagWithoutActor -- this is a on/off toggle
|
||||
# group level issues license for now is equivalent to epics license. We'll have to migrate epics license to
|
||||
# work items context once epics are fully migrated to work items.
|
||||
condition(:group_level_issues_license_available) do
|
||||
epics_license_available?
|
||||
end
|
||||
# rubocop:enable Gitlab/FeatureFlagWithoutActor
|
||||
|
||||
rule { group_issue & can?(:read_group) }.policy do
|
||||
enable :create_note
|
||||
|
|
@ -145,7 +145,7 @@ class IssuePolicy < IssuablePolicy
|
|||
enable :set_issue_crm_contacts
|
||||
end
|
||||
|
||||
rule { can?(:reporter_access) }.policy do
|
||||
rule { planner_or_reporter_access }.policy do
|
||||
enable :mark_note_as_internal
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ class MergeRequestPolicy < IssuablePolicy
|
|||
enable :set_merge_request_metadata
|
||||
end
|
||||
|
||||
rule { can?(:reporter_access) }.policy do
|
||||
rule { planner_or_reporter_access }.policy do
|
||||
enable :mark_note_as_internal
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -19,6 +19,10 @@ module Namespaces
|
|||
enable :reopen_issue
|
||||
end
|
||||
|
||||
rule { can?(:planner_access) }.policy do
|
||||
enable :reopen_issue
|
||||
end
|
||||
|
||||
rule { can?(:guest_access) }.policy do
|
||||
enable :read_work_item
|
||||
enable :read_issue
|
||||
|
|
|
|||
|
|
@ -15,6 +15,10 @@ class ProjectPolicy < BasePolicy
|
|||
desc "User has guest access"
|
||||
condition(:guest) { team_member? }
|
||||
|
||||
# This is not a linear condition (some policies available for planner might not be available for higher access levels)
|
||||
desc "User has planner access"
|
||||
condition(:planner) { team_access_level == Gitlab::Access::PLANNER }
|
||||
|
||||
desc "User has reporter access"
|
||||
condition(:reporter) { team_access_level >= Gitlab::Access::REPORTER }
|
||||
|
||||
|
|
@ -311,6 +315,11 @@ class ProjectPolicy < BasePolicy
|
|||
Feature.enabled?(:hide_projects_of_banned_users) && @subject.created_and_owned_by_banned_user?
|
||||
end
|
||||
|
||||
desc "User has either planner or reporter access"
|
||||
condition(:planner_or_reporter_access) do
|
||||
can?(:reporter_access) || can?(:planner_access)
|
||||
end
|
||||
|
||||
# `:read_project` may be prevented in EE, but `:read_project_for_iids` should
|
||||
# not.
|
||||
rule { guest | admin | organization_owner }.enable :read_project_for_iids
|
||||
|
|
@ -320,6 +329,7 @@ class ProjectPolicy < BasePolicy
|
|||
rule { can?(:read_all_resources) }.enable :read_confidential_issues
|
||||
|
||||
rule { guest }.enable :guest_access
|
||||
rule { planner }.enable :planner_access
|
||||
rule { reporter }.enable :reporter_access
|
||||
rule { developer }.enable :developer_access
|
||||
rule { maintainer }.enable :maintainer_access
|
||||
|
|
@ -329,6 +339,7 @@ class ProjectPolicy < BasePolicy
|
|||
|
||||
rule { can?(:owner_access) }.policy do
|
||||
enable :guest_access
|
||||
enable :planner_access
|
||||
enable :reporter_access
|
||||
enable :developer_access
|
||||
enable :maintainer_access
|
||||
|
|
@ -379,6 +390,29 @@ class ProjectPolicy < BasePolicy
|
|||
enable :read_upload
|
||||
end
|
||||
|
||||
rule { can?(:planner_access) }.policy do
|
||||
enable :guest_access
|
||||
enable :admin_issue_board
|
||||
enable :admin_issue_board_list
|
||||
enable :update_issue
|
||||
enable :reopen_issue
|
||||
enable :admin_issue
|
||||
enable :destroy_issue
|
||||
enable :read_confidential_issues
|
||||
enable :create_design
|
||||
enable :update_design
|
||||
enable :move_design
|
||||
enable :destroy_design
|
||||
enable :admin_label
|
||||
enable :admin_milestone
|
||||
enable :download_wiki_code
|
||||
enable :create_wiki
|
||||
enable :admin_wiki
|
||||
enable :read_merge_request
|
||||
enable :download_code
|
||||
enable :export_work_items
|
||||
end
|
||||
|
||||
rule { can?(:reporter_access) & can?(:create_issue) }.enable :create_incident
|
||||
|
||||
rule { can?(:reporter_access) & can?(:read_environment) }.enable :read_freeze_period
|
||||
|
|
@ -503,8 +537,8 @@ class ProjectPolicy < BasePolicy
|
|||
rule { owner | admin | organization_owner | guest | group_member | group_requester }.prevent :request_access
|
||||
rule { ~request_access_enabled }.prevent :request_access
|
||||
|
||||
rule { can?(:developer_access) & can?(:create_issue) }.enable :import_issues
|
||||
rule { can?(:reporter_access) & can?(:create_work_item) }.enable :import_work_items
|
||||
rule { (can?(:planner_access) | can?(:developer_access)) & can?(:create_issue) }.enable :import_issues
|
||||
rule { planner_or_reporter_access & can?(:create_work_item) }.enable :import_work_items
|
||||
|
||||
rule { can?(:developer_access) }.policy do
|
||||
enable :create_package
|
||||
|
|
@ -747,6 +781,7 @@ class ProjectPolicy < BasePolicy
|
|||
# If this project is public or internal we want to prevent all aside from a few public policies
|
||||
rule { public_or_internal & ~project_allowed_for_job_token_by_scope }.policy do
|
||||
prevent :guest_access
|
||||
prevent :planner_access
|
||||
prevent :public_access
|
||||
prevent :reporter_access
|
||||
prevent :developer_access
|
||||
|
|
@ -854,6 +889,7 @@ class ProjectPolicy < BasePolicy
|
|||
# `:read_project_for_iids` is not prevented by this condition, as it is
|
||||
# used for cross-project reference checks.
|
||||
prevent :guest_access
|
||||
prevent :planner_access
|
||||
prevent :public_access
|
||||
prevent :public_user_access
|
||||
prevent :reporter_access
|
||||
|
|
@ -1013,7 +1049,7 @@ class ProjectPolicy < BasePolicy
|
|||
end
|
||||
|
||||
# Should be matched with GroupPolicy#read_internal_note
|
||||
rule { admin | can?(:reporter_access) }.enable :read_internal_note
|
||||
rule { admin | planner_or_reporter_access }.enable :read_internal_note
|
||||
|
||||
rule { can?(:developer_access) & namespace_catalog_available }.policy do
|
||||
enable :read_namespace_catalog
|
||||
|
|
@ -1117,7 +1153,7 @@ class ProjectPolicy < BasePolicy
|
|||
return -1 if @user.nil?
|
||||
return -1 unless user_is_user?
|
||||
|
||||
lookup_access_level!
|
||||
@team_access_level ||= lookup_access_level!
|
||||
end
|
||||
|
||||
def lookup_access_level!
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ module Ci
|
|||
|
||||
response = ServiceResponse.success
|
||||
runner.transaction do
|
||||
current_project_ids = runner.project_ids # rubocop:disable CodeReuse/ActiveRecord -- reasonable use
|
||||
current_project_ids = runner.project_ids
|
||||
|
||||
response = associate_new_projects(new_project_ids, current_project_ids)
|
||||
response = disassociate_old_projects(new_project_ids, current_project_ids) if response.success?
|
||||
|
|
|
|||
|
|
@ -37,12 +37,14 @@ module Groups
|
|||
end
|
||||
|
||||
def public_only?
|
||||
!user_is_at_least_reporter?
|
||||
# Although PLANNER is not a linear access level, it can be considered so for the purpose of issues visibility
|
||||
# because the same permissions apply to all levels higher than Gitlab::Access::PLANNER
|
||||
!user_is_at_least_planner?
|
||||
end
|
||||
|
||||
def user_is_at_least_reporter?
|
||||
strong_memoize(:user_is_at_least_reporter) do
|
||||
group.member?(user, Gitlab::Access::REPORTER)
|
||||
def user_is_at_least_planner?
|
||||
strong_memoize(:user_is_at_least_planner) do
|
||||
group.member?(user, Gitlab::Access::PLANNER)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -21,12 +21,12 @@ module Projects
|
|||
end
|
||||
|
||||
def public_only?
|
||||
!user_is_at_least_reporter?
|
||||
!user_is_at_least_planner?
|
||||
end
|
||||
|
||||
def user_is_at_least_reporter?
|
||||
strong_memoize(:user_is_at_least_reporter) do
|
||||
@project.member?(@user, Gitlab::Access::REPORTER)
|
||||
def user_is_at_least_planner?
|
||||
strong_memoize(:user_is_at_least_planner) do
|
||||
@project.member?(@user, Gitlab::Access::PLANNER)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -57,7 +57,7 @@ module Projects
|
|||
end
|
||||
end
|
||||
|
||||
# We only show issues count including confidential for reporters, who are allowed to view confidential issues.
|
||||
# We only show issues count including confidential for planners, who are allowed to view confidential issues.
|
||||
# This will still show a discrepancy on issues number but should be less than before.
|
||||
# Check https://gitlab.com/gitlab-org/gitlab-foss/issues/38418 description.
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
module Todos
|
||||
module Destroy
|
||||
# Service class for deleting todos that belongs to confidential issues.
|
||||
# It deletes todos for users that are not at least reporters, issue author or assignee.
|
||||
# It deletes todos for users that are not at least planners, issue author or assignee.
|
||||
#
|
||||
# Accepts issue_id or project_id as argument.
|
||||
# When issue_id is passed it deletes matching todos for one confidential issue.
|
||||
|
|
|
|||
|
|
@ -19,8 +19,10 @@ module Todos
|
|||
def execute
|
||||
return unless entity && user
|
||||
|
||||
# if at least reporter, all entities including confidential issues can be accessed
|
||||
return if user_has_reporter_access?
|
||||
# If at least planner, all entities including confidential issues can be accessed. Although PLANNER is not a
|
||||
# linear access level, it can be considered so for the purpose of issuables visibility because the same
|
||||
# permissions apply to all levels higher than Gitlab::Access::PLANNER
|
||||
return if user_has_planner_access?
|
||||
|
||||
remove_confidential_resource_todos
|
||||
remove_group_todos
|
||||
|
|
@ -52,7 +54,7 @@ module Todos
|
|||
Todo
|
||||
.for_type(Issue.name)
|
||||
.for_internal_notes
|
||||
.for_project(non_authorized_reporter_projects) # Only Reporter+ can read internal notes
|
||||
.for_project(non_authorized_planner_projects) # Only Planner+ can read internal notes
|
||||
.for_user(user)
|
||||
.delete_all
|
||||
end
|
||||
|
|
@ -65,9 +67,9 @@ module Todos
|
|||
.for_user(user)
|
||||
.delete_all
|
||||
|
||||
# MRs require reporter access, so remove those todos that are not authorized
|
||||
# MRs require planner access, so remove those todos that are not authorized
|
||||
Todo
|
||||
.for_project(non_authorized_reporter_projects)
|
||||
.for_project(non_authorized_planner_projects)
|
||||
.for_type(MergeRequest.name)
|
||||
.for_user(user)
|
||||
.delete_all
|
||||
|
|
@ -87,30 +89,30 @@ module Todos
|
|||
when Project
|
||||
{ id: entity.id }
|
||||
when Namespace
|
||||
{ namespace_id: non_authorized_reporter_groups }
|
||||
{ namespace_id: non_authorized_planner_groups }
|
||||
end
|
||||
|
||||
Project.where(condition) # rubocop: disable CodeReuse/ActiveRecord
|
||||
end
|
||||
|
||||
def authorized_reporter_projects
|
||||
user.authorized_projects(Gitlab::Access::REPORTER).select(:id)
|
||||
def authorized_planner_projects
|
||||
user.authorized_projects(Gitlab::Access::PLANNER).select(:id)
|
||||
end
|
||||
|
||||
def authorized_guest_projects
|
||||
user.authorized_projects(Gitlab::Access::GUEST).select(:id)
|
||||
end
|
||||
|
||||
def non_authorized_reporter_projects
|
||||
projects.id_not_in(authorized_reporter_projects)
|
||||
def non_authorized_planner_projects
|
||||
projects.id_not_in(authorized_planner_projects)
|
||||
end
|
||||
|
||||
def non_authorized_guest_projects
|
||||
projects.id_not_in(authorized_guest_projects)
|
||||
end
|
||||
|
||||
def authorized_reporter_groups
|
||||
GroupsFinder.new(user, min_access_level: Gitlab::Access::REPORTER).execute.select(:id)
|
||||
def authorized_planner_groups
|
||||
GroupsFinder.new(user, min_access_level: Gitlab::Access::PLANNER).execute.select(:id)
|
||||
end
|
||||
|
||||
# rubocop: disable CodeReuse/ActiveRecord
|
||||
|
|
@ -124,15 +126,15 @@ module Todos
|
|||
end
|
||||
# rubocop: enable CodeReuse/ActiveRecord
|
||||
|
||||
def non_authorized_reporter_groups
|
||||
def non_authorized_planner_groups
|
||||
entity.self_and_descendants.select(:id)
|
||||
.id_not_in(authorized_reporter_groups)
|
||||
.id_not_in(authorized_planner_groups)
|
||||
end
|
||||
|
||||
def user_has_reporter_access?
|
||||
def user_has_planner_access?
|
||||
return unless entity.is_a?(Namespace)
|
||||
|
||||
entity.member?(User.find(user.id), Gitlab::Access::REPORTER)
|
||||
entity.member?(User.find(user.id), Gitlab::Access::PLANNER)
|
||||
end
|
||||
|
||||
def confidential_issues
|
||||
|
|
@ -141,7 +143,7 @@ module Todos
|
|||
Issue
|
||||
.in_projects(projects)
|
||||
.confidential_only
|
||||
.not_in_projects(authorized_reporter_projects)
|
||||
.not_in_projects(authorized_planner_projects)
|
||||
.not_authored_by(user)
|
||||
.id_not_in(assigned_ids)
|
||||
end
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ module WorkItems
|
|||
return error(error_message, :unprocessable_entity)
|
||||
end
|
||||
|
||||
if target_namespace.pending_delete? # rubocop:disable Style/GuardClause -- does not read right with other checks above
|
||||
if target_namespace.pending_delete?
|
||||
error_message = s_('CloneWorkItem|Cannot clone work item to target namespace as it is pending deletion.')
|
||||
|
||||
return error(error_message, :unprocessable_entity)
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ module WorkItems
|
|||
return error(error_message, :unprocessable_entity)
|
||||
end
|
||||
|
||||
if target_namespace.pending_delete? # rubocop:disable Style/GuardClause -- does not read right with other checks above
|
||||
if target_namespace.pending_delete?
|
||||
error_message = s_('MoveWorkItem|Cannot move work item to target namespace as it is pending deletion.')
|
||||
|
||||
return error(error_message, :unprocessable_entity)
|
||||
|
|
|
|||
|
|
@ -10,13 +10,13 @@
|
|||
.top-area
|
||||
= gl_tabs_nav({ class: 'gl-grow gl-border-b-0' }) do
|
||||
= gl_tab_link_to s_('Branches|Overview'), project_branches_path(@project), { item_active: @mode == 'overview', title: s_('Branches|Show overview of the branches') }
|
||||
= gl_tab_link_to s_('Branches|Active'), project_branches_filtered_path(@project, state: 'active'), { title: s_('Branches|Show active branches') }
|
||||
= gl_tab_link_to s_('Branches|Stale'), project_branches_filtered_path(@project, state: 'stale'), { title: s_('Branches|Show stale branches') }
|
||||
= gl_tab_link_to s_('Branches|Active'), project_branches_filtered_path(@project, state: 'active'), { item_active: @mode == 'active', title: s_('Branches|Show active branches') }
|
||||
= gl_tab_link_to s_('Branches|Stale'), project_branches_filtered_path(@project, state: 'stale'), { item_active: @mode == 'stale', title: s_('Branches|Show stale branches') }
|
||||
= gl_tab_link_to s_('Branches|All'), project_branches_filtered_path(@project, state: 'all'), { item_active: %w[overview active stale].exclude?(@mode), title: s_('Branches|Show all branches') }
|
||||
|
||||
.nav-controls
|
||||
#js-branches-sort-dropdown{ data: {
|
||||
project_branches_filtered_path: project_branches_path(@project, state: 'all'),
|
||||
project_branches_filtered_path: project_branches_path(@project, state: @mode),
|
||||
sort_options: branches_sort_options_hash.to_json,
|
||||
show_dropdown: @mode == 'overview' ? 'false' : 'true',
|
||||
sorted_by: @sort }
|
||||
|
|
|
|||
|
|
@ -6,29 +6,6 @@
|
|||
|
||||
.wiki-page-header.has-sidebar-toggle.gl-flex-col.gl-py-5
|
||||
%h1.gl-heading-1{ class: '!gl-mt-0' }= s_('WikiClone|Clone Wiki repository')
|
||||
%h2.gl-heading-3{ class: '!gl-mb-0' }= s_('WikiClone|Step 1: Clone repository')
|
||||
|
||||
%h5= s_("WikiClone|Clone repository")
|
||||
= wiki_sidebar_toggle_button
|
||||
|
||||
= render "shared/clone_panel", container: @wiki
|
||||
|
||||
.wiki-git-access.gl-mt-3
|
||||
%h2.gl-heading-3= s_('WikiClone|Step 2: Install and start Gollum')
|
||||
|
||||
%h5.gl-mt-2= s_("WikiClone|Go to directory")
|
||||
%pre.dark
|
||||
:preserve
|
||||
cd #{h @wiki.path}
|
||||
|
||||
%h5= s_("WikiClone|Install Gollum")
|
||||
%pre.dark
|
||||
:preserve
|
||||
gem install gollum
|
||||
|
||||
%h5.gl-mt-2= s_("WikiClone|Start Gollum and edit locally")
|
||||
%pre.dark
|
||||
:preserve
|
||||
gollum
|
||||
|
||||
= render 'shared/wikis/sidebar'
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
---
|
||||
name: routable_token
|
||||
feature_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/486946
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/169581
|
||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/499537
|
||||
milestone: '17.6'
|
||||
group: group::tenant scale
|
||||
type: gitlab_com_derisk
|
||||
name: ci_optimize_memory_for_variables
|
||||
feature_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/499707
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/173126
|
||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/502800
|
||||
milestone: '17.7'
|
||||
group: group::pipeline authoring
|
||||
type: beta
|
||||
default_enabled: false
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
- name: Use self-hosted model for GitLab Duo Chat
|
||||
description: |
|
||||
You can now host your own supported large language models (LLMs) and configure them to enable self-hosted GitLab Duo Chat. This feature is in beta and available with an Ultimate and Duo Enterprise subscription on GitLab self-managed. With self-hosted models, you can use models hosted either on-premise or in a private cloud to enable GitLab Duo Chat or Code Suggestions (introduced as a beta feature in GitLab 17.5). For Code Suggestions, we currently support open-source Mistral models on vLLM or AWS Bedrock, Claude 3.5 Sonnet on AWS Bedrock, and OpenAI models on Azure OpenAI. For Chat, we currently support open-source Mistral models on vLLM or AWS Bedrock, and Claude 3.5 Sonnet on AWS Bedrock. By enabling self-hosted models, you can leverage the power of generative AI while maintaining complete data sovereignty and privacy.
|
||||
stage: ai-powered
|
||||
self-managed: true
|
||||
gitlab-com: false
|
||||
available_in: [Ultimate]
|
||||
documentation_link: https://docs.gitlab.com/ee/administration/self_hosted_models/
|
||||
image_url: https://about.gitlab.com/images/17_6/self-hosted-models-ui-17.6.png
|
||||
published_at: 2024-11-21
|
||||
release: 17.6
|
||||
|
||||
- name: Vulnerability report grouping
|
||||
description: |
|
||||
Users require the ability to view vulnerabilities in groups. This will help security analysts optimize their triage tasks by utilizing bulk actions. In addition users can see how many vulnerabilities match their group; i.e. how many OWASP Top 10 vulnerabilities are there?
|
||||
stage: security_risk_management
|
||||
self-managed: true
|
||||
gitlab-com: true
|
||||
available_in: [Ultimate]
|
||||
documentation_link: https://docs.gitlab.com/ee/user/application_security/vulnerability_report/#group-vulnerabilities
|
||||
image_url: https://about.gitlab.com/images/17_6/vulnerability_report_grouping.png
|
||||
published_at: 2024-11-21
|
||||
release: 17.6
|
||||
|
||||
- name: Display release notes on deployment details page
|
||||
description: |
|
||||
Have you ever wondered what might be included in a deployment you’ve been asked to approve? In past versions, you could create a release with a detailed description about its content and instructions for testing, but the related environment-specific deployment did not show this data. We are happy to share that GitLab now displays the release notes under the related deployment details page.
|
||||
stage: deploy
|
||||
self-managed: true
|
||||
gitlab-com: true
|
||||
available_in: [Free, Premium, Ultimate]
|
||||
documentation_link: https://docs.gitlab.com/ee/ci/environments/deployment_approvals.html#view-blocked-deployments
|
||||
image_url: https://about.gitlab.com/images/17_6/deploy-automatically-show-release-notes.png
|
||||
published_at: 2024-11-21
|
||||
release: 17.6
|
||||
|
||||
- name: Enhanced merge request reviewer assignments
|
||||
description: |
|
||||
Now, when assigning reviewers, the sidebar creates a connection between the approval requirements for your merge request and reviewers. View each approval rule, then select from approvers who can satisfy that approval rule and move the merge request forward for you. If you use optional CODEOWNER sections those rules are also shown in the sidebar to help you identify appropriate subject matter experts for your changes.
|
||||
stage: create
|
||||
self-managed: true
|
||||
gitlab-com: true
|
||||
available_in: [Free, Premium, Ultimate]
|
||||
documentation_link: https://docs.gitlab.com/ee/user/project/merge_requests/reviews/#request-a-review
|
||||
image_url: https://about.gitlab.com/images/17_6/create-enhanced-reviewer-assignment.png
|
||||
published_at: 2024-11-21
|
||||
release: 17.6
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
---
|
||||
view_name: postgres_table_sizes
|
||||
classes:
|
||||
- Gitlab::Database::PostgresTableSize
|
||||
feature_categories:
|
||||
- database
|
||||
description: SQL view to get information about postgres table sizes
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/173113
|
||||
milestone: '17.7'
|
||||
gitlab_schema: gitlab_shared
|
||||
|
|
@ -35,7 +35,6 @@ class CreatePartitionedCiRunners < Gitlab::Database::Migration[2.2]
|
|||
|
||||
def create_partitioned_table(name)
|
||||
options = 'PARTITION BY LIST (runner_type)'
|
||||
# rubocop: disable Migration/EnsureFactoryForTable -- we'll reuse the ci_runners factory once migrated
|
||||
create_table name, primary_key: PARTITIONED_TABLE_PK, options: options do |t|
|
||||
t.bigint :id, null: false
|
||||
t.bigint :creator_id
|
||||
|
|
@ -88,6 +87,5 @@ class CreatePartitionedCiRunners < Gitlab::Database::Migration[2.2]
|
|||
t.index %i[token_expires_at id], name: "idx_#{name}_on_token_expires_at_desc_and_id_desc",
|
||||
order: { token_expires_at: :desc, runner_type: :asc, id: :desc }
|
||||
end
|
||||
# rubocop: enable Migration/EnsureFactoryForTable
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -28,7 +28,6 @@ class CreatePartitionedCiRunnerManagers < Gitlab::Database::Migration[2.2]
|
|||
|
||||
def create_partitioned_table(name)
|
||||
options = 'PARTITION BY LIST (runner_type)'
|
||||
# rubocop: disable Migration/EnsureFactoryForTable -- we'll reuse the ci_runner_machines factory once migrated
|
||||
create_table name, primary_key: PARTITIONED_TABLE_PK, options: options do |t|
|
||||
t.bigint :id, null: false
|
||||
t.bigint :runner_id, null: false
|
||||
|
|
@ -59,6 +58,5 @@ class CreatePartitionedCiRunnerManagers < Gitlab::Database::Migration[2.2]
|
|||
name: "index_#{name}_on_patch_version"
|
||||
t.index :version, name: "index_#{name}_on_version"
|
||||
end
|
||||
# rubocop: enable Migration/EnsureFactoryForTable
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -0,0 +1,29 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class AddPostgresTableSizesView < Gitlab::Database::Migration[2.2]
|
||||
milestone '17.7'
|
||||
|
||||
def up
|
||||
execute(<<~SQL)
|
||||
CREATE OR REPLACE VIEW postgres_table_sizes AS
|
||||
SELECT
|
||||
schemaname || '.' || relname as identifier,
|
||||
schemaname as schema_name,
|
||||
relname as table_name,
|
||||
pg_size_pretty(pg_total_relation_size(quote_ident(schemaname) || '.' || quote_ident(relname))) as total_size,
|
||||
pg_size_pretty(pg_relation_size(quote_ident(schemaname) || '.' || quote_ident(relname))) as table_size,
|
||||
pg_size_pretty(pg_total_relation_size(quote_ident(schemaname) || '.' || quote_ident(relname)) -
|
||||
pg_relation_size(quote_ident(schemaname) || '.' || quote_ident(relname))) as index_size,
|
||||
pg_total_relation_size(quote_ident(schemaname) || '.' || quote_ident(relname)) as size_in_bytes
|
||||
FROM pg_stat_user_tables
|
||||
WHERE pg_total_relation_size(quote_ident(schemaname) || '.' || quote_ident(relname)) IS NOT NULL
|
||||
ORDER BY pg_total_relation_size(quote_ident(schemaname) || '.' || quote_ident(relname)) DESC;
|
||||
SQL
|
||||
end
|
||||
|
||||
def down
|
||||
execute(<<~SQL)
|
||||
DROP VIEW postgres_table_sizes
|
||||
SQL
|
||||
end
|
||||
end
|
||||
|
|
@ -12,7 +12,7 @@ class DropUserCanonicalEmailsTable < Gitlab::Database::Migration[2.2]
|
|||
create_table :user_canonical_emails do |t|
|
||||
t.timestamps_with_timezone
|
||||
t.references :user, index: false, null: false, foreign_key: { on_delete: :cascade }
|
||||
t.string :canonical_email, null: false, index: true # rubocop:disable Migration/AddLimitToStringColumns -- limit ignored in original migration
|
||||
t.string :canonical_email, null: false, index: true
|
||||
end
|
||||
|
||||
add_index :user_canonical_emails, [:user_id, :canonical_email], unique: true
|
||||
|
|
|
|||
|
|
@ -0,0 +1 @@
|
|||
0bff9c7868fd9cbc139610f9f4a39e7ccc54b059ea1cec5d17fbf67725f83121
|
||||
|
|
@ -17459,6 +17459,18 @@ CREATE VIEW postgres_sequences AS
|
|||
LEFT JOIN pg_attribute ON (((dep_pg_class.oid = pg_attribute.attrelid) AND (pg_depend.refobjsubid = pg_attribute.attnum))))
|
||||
WHERE (seq_pg_class.relkind = 'S'::"char");
|
||||
|
||||
CREATE VIEW postgres_table_sizes AS
|
||||
SELECT (((pg_stat_user_tables.schemaname)::text || '.'::text) || (pg_stat_user_tables.relname)::text) AS identifier,
|
||||
pg_stat_user_tables.schemaname AS schema_name,
|
||||
pg_stat_user_tables.relname AS table_name,
|
||||
pg_size_pretty(pg_total_relation_size((((quote_ident((pg_stat_user_tables.schemaname)::text) || '.'::text) || quote_ident((pg_stat_user_tables.relname)::text)))::regclass)) AS total_size,
|
||||
pg_size_pretty(pg_relation_size((((quote_ident((pg_stat_user_tables.schemaname)::text) || '.'::text) || quote_ident((pg_stat_user_tables.relname)::text)))::regclass)) AS table_size,
|
||||
pg_size_pretty((pg_total_relation_size((((quote_ident((pg_stat_user_tables.schemaname)::text) || '.'::text) || quote_ident((pg_stat_user_tables.relname)::text)))::regclass) - pg_relation_size((((quote_ident((pg_stat_user_tables.schemaname)::text) || '.'::text) || quote_ident((pg_stat_user_tables.relname)::text)))::regclass))) AS index_size,
|
||||
pg_total_relation_size((((quote_ident((pg_stat_user_tables.schemaname)::text) || '.'::text) || quote_ident((pg_stat_user_tables.relname)::text)))::regclass) AS size_in_bytes
|
||||
FROM pg_stat_user_tables
|
||||
WHERE (pg_total_relation_size((((quote_ident((pg_stat_user_tables.schemaname)::text) || '.'::text) || quote_ident((pg_stat_user_tables.relname)::text)))::regclass) IS NOT NULL)
|
||||
ORDER BY (pg_total_relation_size((((quote_ident((pg_stat_user_tables.schemaname)::text) || '.'::text) || quote_ident((pg_stat_user_tables.relname)::text)))::regclass)) DESC;
|
||||
|
||||
CREATE TABLE programming_languages (
|
||||
id bigint NOT NULL,
|
||||
name character varying NOT NULL,
|
||||
|
|
|
|||
|
|
@ -23,12 +23,12 @@ and the following external authentication and authorization providers:
|
|||
NOTE:
|
||||
UltraAuth has removed their software which supports OmniAuth integration. We have therefore removed all references to UltraAuth integration.
|
||||
|
||||
## SaaS vs self-managed comparison
|
||||
## GitLab.com compared to self-managed
|
||||
|
||||
The external authentication and authorization providers may support the following capabilities.
|
||||
For more information, see the links shown on this page for each external provider.
|
||||
|
||||
| Capability | SaaS | Self-managed |
|
||||
| Capability | GitLab.com | Self-managed |
|
||||
|-------------------------------------------------|-----------------------------------------|------------------------------------|
|
||||
| **User Provisioning** | SCIM<br>SAML <sup>1</sup> | LDAP <sup>1</sup><br>SAML <sup>1</sup><br>[OmniAuth Providers](../../integration/omniauth.md#supported-providers) <sup>1</sup><br>SCIM |
|
||||
| **User Detail Updating** (not group management) | Not Available | LDAP Sync |
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
---
|
||||
stage: Govern
|
||||
stage: Software Supply Chain Security
|
||||
group: Anti-Abuse
|
||||
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://handbook.gitlab.com/handbook/product/ux/technical-writing/#assignments
|
||||
---
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
---
|
||||
stage: Govern
|
||||
stage: Software Supply Chain Security
|
||||
group: Anti-Abuse
|
||||
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://handbook.gitlab.com/handbook/product/ux/technical-writing/#assignments
|
||||
---
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
---
|
||||
stage: Govern
|
||||
stage: Software Supply Chain Security
|
||||
group: Anti-Abuse
|
||||
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://handbook.gitlab.com/handbook/product/ux/technical-writing/#assignments
|
||||
---
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
---
|
||||
stage: Govern
|
||||
stage: Software Supply Chain Security
|
||||
group: Anti-Abuse
|
||||
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://handbook.gitlab.com/handbook/product/ux/technical-writing/#assignments
|
||||
---
|
||||
|
|
|
|||
|
|
@ -245,13 +245,10 @@ When you require expiration dates for new access tokens:
|
|||
|
||||
DETAILS:
|
||||
**Tier:** Premium, Ultimate
|
||||
**Offering:** Self-managed
|
||||
**Offering:** Self-managed, GitLab Dedicated
|
||||
|
||||
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/163726) in GitLab 17.5 [with a feature flag](../feature_flags.md) named `allow_top_level_group_owners_to_create_service_accounts` for GitLab self-managed. Disabled by default.
|
||||
> - [Generally available](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/125835) in GitLab 17.6. Feature flag `allow_top_level_group_owners_to_create_service_accounts` removed.
|
||||
|
||||
FLAG:
|
||||
On GitLab self-managed, by default this feature is not available. To make it available, an administrator can [enable the feature flag](../feature_flags.md) named `allow_top_level_group_owners_to_create_service_accounts`. On GitLab.com, this feature is available.
|
||||
> - [Generally available](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/172502) in GitLab 17.6. Feature flag `allow_top_level_group_owners_to_create_service_accounts` removed.
|
||||
|
||||
By default, in GitLab self-managed, top-level group Owners can not create service accounts. GitLab administrators can allow top-level group Owners to create service accounts.
|
||||
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ following levels are recognized:
|
|||
- No access (`0`)
|
||||
- Minimal access (`5`)
|
||||
- Guest (`10`)
|
||||
- Planner (`15`)
|
||||
- Reporter (`20`)
|
||||
- Developer (`30`)
|
||||
- Maintainer (`40`)
|
||||
|
|
|
|||
|
|
@ -127,6 +127,7 @@ The `target_access_levels` are defined in the `Gitlab::Access` module. The
|
|||
following levels are valid:
|
||||
|
||||
- Guest (`10`)
|
||||
- Planner (`15`)
|
||||
- Reporter (`20`)
|
||||
- Developer (`30`)
|
||||
- Maintainer (`40`)
|
||||
|
|
@ -198,6 +199,7 @@ The `target_access_levels` are defined in the `Gitlab::Access` module. The
|
|||
following levels are valid:
|
||||
|
||||
- Guest (`10`)
|
||||
- Planner (`15`)
|
||||
- Reporter (`20`)
|
||||
- Developer (`30`)
|
||||
- Maintainer (`40`)
|
||||
|
|
|
|||
|
|
@ -39234,6 +39234,7 @@ Access level of a group or project member.
|
|||
| <a id="memberaccesslevelmaintainer"></a>`MAINTAINER` | The Maintainer role is primarily used for managing code reviews, approvals, and administrative settings for projects. This role can also manage project memberships. |
|
||||
| <a id="memberaccesslevelminimal_access"></a>`MINIMAL_ACCESS` | The Minimal Access role is for users who need the least amount of access into groups and projects. You can assign this role as a default, before giving a user another role with more permissions. |
|
||||
| <a id="memberaccesslevelowner"></a>`OWNER` | The Owner role is normally assigned to the individual or team responsible for managing and maintaining the group or creating the project. This role has the highest level of administrative control, and can manage all aspects of the group or project, including managing other Owners. |
|
||||
| <a id="memberaccesslevelplanner"></a>`PLANNER` | The Planner role is suitable for team members who need to manage projects and track work items but do not need to contribute code. |
|
||||
| <a id="memberaccesslevelreporter"></a>`REPORTER` | The Reporter role is suitable for team members who need to stay informed about a project or group but do not actively contribute code. |
|
||||
|
||||
### `MemberAccessLevelName`
|
||||
|
|
@ -39246,6 +39247,7 @@ Name of access levels of a group or project member.
|
|||
| <a id="memberaccesslevelnameguest"></a>`GUEST` | Guest access. |
|
||||
| <a id="memberaccesslevelnamemaintainer"></a>`MAINTAINER` | Maintainer access. |
|
||||
| <a id="memberaccesslevelnameowner"></a>`OWNER` | Owner access. |
|
||||
| <a id="memberaccesslevelnameplanner"></a>`PLANNER` | Planner access. |
|
||||
| <a id="memberaccesslevelnamereporter"></a>`REPORTER` | Reporter access. |
|
||||
|
||||
### `MemberApprovalStatusType`
|
||||
|
|
|
|||
|
|
@ -116,7 +116,7 @@ POST /groups/:id/access_tokens
|
|||
| `id` | integer or string | yes | ID or [URL-encoded path of the group](rest/index.md#namespaced-paths) |
|
||||
| `name` | String | yes | Name of the group access token |
|
||||
| `scopes` | `Array[String]` | yes | [List of scopes](../user/group/settings/group_access_tokens.md#scopes-for-a-group-access-token) |
|
||||
| `access_level` | Integer | no | Access level. Valid values are `10` (Guest), `20` (Reporter), `30` (Developer), `40` (Maintainer), and `50` (Owner). |
|
||||
| `access_level` | Integer | no | Access level. Valid values are `10` (Guest), `15` (Planner), `20` (Reporter), `30` (Developer), `40` (Maintainer), and `50` (Owner). |
|
||||
| `expires_at` | Date | yes | Expiration date of the access token in ISO format (`YYYY-MM-DD`). The date cannot be set later than the [maximum allowable lifetime of an access token](../user/profile/personal_access_tokens.md#access-token-expiration). |
|
||||
|
||||
```shell
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ levels are defined in the `Gitlab::Access` module. Currently, these levels are v
|
|||
- No access (`0`)
|
||||
- Minimal access (`5`)
|
||||
- Guest (`10`)
|
||||
- Planner (`15`)
|
||||
- Reporter (`20`)
|
||||
- Developer (`30`)
|
||||
- Maintainer (`40`)
|
||||
|
|
|
|||
|
|
@ -100,7 +100,7 @@ Supported attributes:
|
|||
|:----------|:--------|:---------|:-------------------------------------|
|
||||
| `name` | string | yes | The name of the member role. |
|
||||
| `description` | string | no | The description of the member role. |
|
||||
| `base_access_level` | integer | yes | Base access level for configured role. Valid values are `10` (Guest), `20` (Reporter), `30` (Developer), `40` (Maintainer), or `50` (Owner).|
|
||||
| `base_access_level` | integer | yes | Base access level for configured role. Valid values are `10` (Guest), `15` (Planner), `20` (Reporter), `30` (Developer), `40` (Maintainer), or `50` (Owner).|
|
||||
| `admin_cicd_variables` | boolean | no | Permission to create, read, update, and delete CI/CD variables. |
|
||||
| `admin_compliance_framework` | boolean | no | Permission to administer compliance frameworks. |
|
||||
| `admin_group_member` | boolean | no | Permission to add, remove and assign members in a group. |
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ in the `Gitlab::Access` module as `access_level`.
|
|||
- No access (`0`)
|
||||
- Minimal access (`5`)
|
||||
- Guest (`10`)
|
||||
- Planner (`15`)
|
||||
- Reporter (`20`)
|
||||
- Developer (`30`)
|
||||
- Maintainer (`40`)
|
||||
|
|
|
|||
|
|
@ -123,8 +123,9 @@ Parameters:
|
|||
## Delete project milestone
|
||||
|
||||
> - [Changed](https://gitlab.com/gitlab-org/gitlab/-/issues/343889) the minimum user role from Developer to Reporter in GitLab 15.0.
|
||||
> - [Changed](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/169256) the minimum user role from Reporter to Planner in GitLab 17.7.
|
||||
|
||||
Only for users with at least the Reporter role for the project.
|
||||
Only for users with at least the Planner role for the project.
|
||||
|
||||
```plaintext
|
||||
DELETE /projects/:id/milestones/:milestone_id
|
||||
|
|
@ -170,8 +171,9 @@ Parameters:
|
|||
## Promote project milestone to a group milestone
|
||||
|
||||
> - [Changed](https://gitlab.com/gitlab-org/gitlab/-/issues/343889) the minimum user role from Developer to Reporter in GitLab 15.0.
|
||||
> - [Changed](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/169256) the minimum user role from Reporter to Planner in GitLab 17.7.
|
||||
|
||||
Only for users with at least the Reporter role for the group.
|
||||
Only for users with at least the Planner role for the group.
|
||||
|
||||
```plaintext
|
||||
POST /projects/:id/milestones/:milestone_id/promote
|
||||
|
|
|
|||
|
|
@ -122,7 +122,7 @@ POST projects/:id/access_tokens
|
|||
| `id` | integer or string | yes | ID or [URL-encoded path of the project](rest/index.md#namespaced-paths) |
|
||||
| `name` | string | yes | Name of the project access token |
|
||||
| `scopes` | `Array[String]` | yes | [List of scopes](../user/project/settings/project_access_tokens.md#scopes-for-a-project-access-token) |
|
||||
| `access_level` | integer | no | Access level. Valid values are `10` (Guest), `20` (Reporter), `30` (Developer), `40` (Maintainer), and `50` (Owner). Defaults to `40`. |
|
||||
| `access_level` | integer | no | Access level. Valid values are `10` (Guest), `15` (Planner), `20` (Reporter), `30` (Developer), `40` (Maintainer), and `50` (Owner). Defaults to `40`. |
|
||||
| `expires_at` | date | yes | Expiration date of the access token in ISO format (`YYYY-MM-DD`). The date cannot be set later than the [maximum allowable lifetime of an access token](../user/profile/personal_access_tokens.md#access-token-expiration). |
|
||||
|
||||
```shell
|
||||
|
|
|
|||
|
|
@ -30,9 +30,11 @@ For more information, see [Product Stage Direction - Plan](https://about.gitlab.
|
|||
|
||||
## Create a test case
|
||||
|
||||
> - [Changed](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/169256) the minimum user role from Reporter to Planner in GitLab 17.7.
|
||||
|
||||
Prerequisites:
|
||||
|
||||
- You must have at least the Reporter role.
|
||||
- You must have at least the Planner role.
|
||||
|
||||
To create a test case in a GitLab project:
|
||||
|
||||
|
|
@ -51,7 +53,7 @@ Prerequisites:
|
|||
|
||||
- Non-confidential test case in a public project: You don't have to be a member of the project.
|
||||
- Non-confidential test case in a private project: You must have at least the Guest role for the project.
|
||||
- Confidential test case (regardless of project visibility): You must have at least the Reporter role for the project.
|
||||
- Confidential test case (regardless of project visibility): You must have at least the Planner role for the project.
|
||||
|
||||
To view a test case:
|
||||
|
||||
|
|
@ -63,11 +65,13 @@ To view a test case:
|
|||
|
||||
## Edit a test case
|
||||
|
||||
> - [Changed](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/169256) the minimum user role from Reporter to Planner in GitLab 17.7.
|
||||
|
||||
You can edit a test case's title and description.
|
||||
|
||||
Prerequisites:
|
||||
|
||||
- You must have at least the Reporter role.
|
||||
- You must have at least the Planner role.
|
||||
- Users demoted to the Guest role can continue to edit the test cases they created
|
||||
when they were in the higher role.
|
||||
|
||||
|
|
@ -81,12 +85,13 @@ To edit a test case:
|
|||
## Make a test case confidential
|
||||
|
||||
> - Introduced for [new](https://gitlab.com/gitlab-org/gitlab/-/issues/422121) and [existing](https://gitlab.com/gitlab-org/gitlab/-/issues/422120) test cases in GitLab 16.5.
|
||||
> - [Changed](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/169256) the minimum user role from Reporter to Planner in GitLab 17.7.
|
||||
|
||||
If you're working on a test case that contains private information, you can make it confidential.
|
||||
|
||||
Prerequisites:
|
||||
|
||||
- You must have at least the Reporter role.
|
||||
- You must have at least the Planner role.
|
||||
|
||||
To make a test case confidential:
|
||||
|
||||
|
|
@ -98,11 +103,13 @@ or editing an existing one.
|
|||
|
||||
## Archive a test case
|
||||
|
||||
> - [Changed](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/169256) the minimum user role from Reporter to Planner in GitLab 17.7.
|
||||
|
||||
When you want to stop using a test case, you can archive it. You can [reopen an archived test case](#reopen-an-archived-test-case) later.
|
||||
|
||||
Prerequisites:
|
||||
|
||||
- You must have at least the Reporter role.
|
||||
- You must have at least the Planner role.
|
||||
|
||||
To archive a test case, on the test case's page, select **Archive test case**.
|
||||
|
||||
|
|
@ -114,11 +121,13 @@ To view archived test cases:
|
|||
|
||||
## Reopen an archived test case
|
||||
|
||||
> - [Changed](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/169256) the minimum user role from Reporter to Planner in GitLab 17.7.
|
||||
|
||||
If you decide to start using an archived test case again, you can reopen it.
|
||||
|
||||
Prerequisites:
|
||||
|
||||
- You must have at least the Reporter role.
|
||||
- You must have at least the Planner role.
|
||||
|
||||
To reopen an archived test case:
|
||||
|
||||
|
|
|
|||
|
|
@ -1320,6 +1320,7 @@ When writing alt text:
|
|||
- Try to avoid repeating text you've already used in the topic.
|
||||
- Do not use inline styling like bold, italics, or backticks.
|
||||
Screen readers read `**text**` as `star star text star star`.
|
||||
- Use an empty alt text tag (`alt=""`) instead of omitting the tag altogether when the image does not add any unique information to the page. For example, when the image is decorative or is already fully described in the body text or caption. An empty alt tag tells assistive technologies that you have omitted the text intentionally, while a missing alt tag is ambiguous.
|
||||
|
||||
#### Automatic screenshot generator
|
||||
|
||||
|
|
|
|||
|
|
@ -31,12 +31,13 @@ You can read more about enabling browser-specific keyboard navigation on [a11ypr
|
|||
|
||||
## Quick checklist
|
||||
|
||||
- [Text](#text-inputs-with-accessible-names),
|
||||
[select](#select-inputs-with-accessible-names),
|
||||
[checkbox](#checkbox-inputs-with-accessible-names),
|
||||
[radio](#radio-inputs-with-accessible-names),
|
||||
- [Text](https://design.gitlab.com/components/text-input#accessibility),
|
||||
[textarea](https://design.gitlab.com/components/textarea#accessibility),
|
||||
[select](https://design.gitlab.com/components/select#accessibility),
|
||||
[checkbox](https://design.gitlab.com/components/checkbox#accessibility),
|
||||
[radio](https://design.gitlab.com/components/radio-button#accessibility),
|
||||
[file](#file-inputs-with-accessible-names),
|
||||
and [toggle](#gltoggle-components-with-accessible-names) inputs have accessible names.
|
||||
and [toggle](https://design.gitlab.com/components/toggle#accessibility) inputs have accessible names.
|
||||
- [Buttons](#buttons-and-links-with-descriptive-accessible-names),
|
||||
[links](#buttons-and-links-with-descriptive-accessible-names),
|
||||
and [images](#images-with-accessible-names) have descriptive accessible names.
|
||||
|
|
@ -45,7 +46,7 @@ You can read more about enabling browser-specific keyboard navigation on [a11ypr
|
|||
- [Clickable icons](#icons-that-are-clickable) are buttons, that is, `<gl-button icon="close" />` is used and not `<gl-icon />`.
|
||||
- Icon-only buttons have an `aria-label`.
|
||||
- Interactive elements can be [accessed with the Tab key](#support-keyboard-only-use) and have a visible focus state.
|
||||
- Elements with [tooltips](#tooltips) are focusable using the Tab key.
|
||||
- Elements with [tooltips](https://design.gitlab.com/components/tooltip#accessibility) are focusable using the Tab key.
|
||||
- Are any `role`, `tabindex` or `aria-*` attributes unnecessary?
|
||||
- Can any `div` or `span` elements be replaced with a more semantic [HTML element](https://developer.mozilla.org/en-US/docs/Web/HTML/Element) like `p`, `button`, or `time`?
|
||||
|
||||
|
|
@ -85,151 +86,6 @@ Note that [when using `GlFormGroup`](https://bootstrap-vue.org/docs/components/f
|
|||
- Passing only a `label` prop renders a `fieldset` with a `legend` containing the `label` value.
|
||||
- Passing both a `label` and a `label-for` prop renders a `label` that points to the form input with the same `label-for` ID.
|
||||
|
||||
#### Text inputs with accessible names
|
||||
|
||||
When using `GlFormGroup`, the `label` prop alone does not give the input an accessible name.
|
||||
The `label-for` prop must also be provided to give the input an accessible name.
|
||||
|
||||
Text input examples:
|
||||
|
||||
```html
|
||||
<!-- Input with label -->
|
||||
<gl-form-group :label="__('Issue title')" label-for="issue-title">
|
||||
<gl-form-input id="issue-title" v-model="title" />
|
||||
</gl-form-group>
|
||||
|
||||
<!-- Input with hidden label -->
|
||||
<gl-form-group :label="__('Issue title')" label-for="issue-title" label-sr-only>
|
||||
<gl-form-input id="issue-title" v-model="title" />
|
||||
</gl-form-group>
|
||||
```
|
||||
|
||||
`textarea` examples:
|
||||
|
||||
```html
|
||||
<!-- textarea with label -->
|
||||
<gl-form-group :label="__('Issue description')" label-for="issue-description">
|
||||
<gl-form-textarea id="issue-description" v-model="description" />
|
||||
</gl-form-group>
|
||||
|
||||
<!-- textarea with hidden label -->
|
||||
<gl-form-group :label="__('Issue description')" label-for="issue-description" label-sr-only>
|
||||
<gl-form-textarea id="issue-description" v-model="description" />
|
||||
</gl-form-group>
|
||||
```
|
||||
|
||||
Alternatively, you can use a plain `label` element:
|
||||
|
||||
```html
|
||||
<!-- Input with label using `label` -->
|
||||
<label for="issue-title">{{ __('Issue title') }}</label>
|
||||
<gl-form-input id="issue-title" v-model="title" />
|
||||
|
||||
<!-- Input with hidden label using `label` -->
|
||||
<label for="issue-title" class="gl-sr-only">{{ __('Issue title') }}</label>
|
||||
<gl-form-input id="issue-title" v-model="title" />
|
||||
```
|
||||
|
||||
#### Select inputs with accessible names
|
||||
|
||||
Select input examples:
|
||||
|
||||
```html
|
||||
<!-- Select input with label -->
|
||||
<gl-form-group :label="__('Issue status')" label-for="issue-status">
|
||||
<gl-form-select id="issue-status" v-model="status" :options="options" />
|
||||
</gl-form-group>
|
||||
|
||||
<!-- Select input with hidden label -->
|
||||
<gl-form-group :label="__('Issue status')" label-for="issue-status" label-sr-only>
|
||||
<gl-form-select id="issue-status" v-model="status" :options="options" />
|
||||
</gl-form-group>
|
||||
```
|
||||
|
||||
#### Checkbox inputs with accessible names
|
||||
|
||||
Single checkbox:
|
||||
|
||||
```html
|
||||
<!-- Single checkbox with label -->
|
||||
<gl-form-checkbox v-model="status" value="task-complete">
|
||||
{{ __('Task complete') }}
|
||||
</gl-form-checkbox>
|
||||
|
||||
<!-- Single checkbox with hidden label -->
|
||||
<gl-form-checkbox v-model="status" value="task-complete">
|
||||
<span class="gl-sr-only">{{ __('Task complete') }}</span>
|
||||
</gl-form-checkbox>
|
||||
```
|
||||
|
||||
Multiple checkboxes:
|
||||
|
||||
```html
|
||||
<!-- Multiple labeled checkboxes grouped within a fieldset -->
|
||||
<gl-form-group :label="__('Task list')">
|
||||
<gl-form-checkbox value="task-1">{{ __('Task 1') }}</gl-form-checkbox>
|
||||
<gl-form-checkbox value="task-2">{{ __('Task 2') }}</gl-form-checkbox>
|
||||
</gl-form-group>
|
||||
|
||||
<!-- Or -->
|
||||
<gl-form-group :label="__('Task list')">
|
||||
<gl-form-checkbox-group v-model="selected" :options="options" />
|
||||
</gl-form-group>
|
||||
|
||||
<!-- Multiple labeled checkboxes grouped within a fieldset with hidden legend -->
|
||||
<gl-form-group :label="__('Task list')" label-sr-only>
|
||||
<gl-form-checkbox value="task-1">{{ __('Task 1') }}</gl-form-checkbox>
|
||||
<gl-form-checkbox value="task-2">{{ __('Task 2') }}</gl-form-checkbox>
|
||||
</gl-form-group>
|
||||
|
||||
<!-- Or -->
|
||||
<gl-form-group :label="__('Task list')" label-sr-only>
|
||||
<gl-form-checkbox-group v-model="selected" :options="options" />
|
||||
</gl-form-group>
|
||||
```
|
||||
|
||||
#### Radio inputs with accessible names
|
||||
|
||||
Single radio input:
|
||||
|
||||
```html
|
||||
<!-- Single radio with a label -->
|
||||
<gl-form-radio v-model="status" value="opened">
|
||||
{{ __('Opened') }}
|
||||
</gl-form-radio>
|
||||
|
||||
<!-- Single radio with a hidden label -->
|
||||
<gl-form-radio v-model="status" value="opened">
|
||||
<span class="gl-sr-only">{{ __('Opened') }}</span>
|
||||
</gl-form-radio>
|
||||
```
|
||||
|
||||
Multiple radio inputs:
|
||||
|
||||
```html
|
||||
<!-- Multiple labeled radio inputs grouped within a fieldset -->
|
||||
<gl-form-group :label="__('Issue status')">
|
||||
<gl-form-radio value="opened">{{ __('Opened') }}</gl-form-radio>
|
||||
<gl-form-radio value="closed">{{ __('Closed') }}</gl-form-radio>
|
||||
</gl-form-group>
|
||||
|
||||
<!-- Or -->
|
||||
<gl-form-group :label="__('Issue status')">
|
||||
<gl-form-radio-group v-model="selected" :options="options" />
|
||||
</gl-form-group>
|
||||
|
||||
<!-- Multiple labeled radio inputs grouped within a fieldset with hidden legend -->
|
||||
<gl-form-group :label="__('Issue status')" label-sr-only>
|
||||
<gl-form-radio value="opened">{{ __('Opened') }}</gl-form-radio>
|
||||
<gl-form-radio value="closed">{{ __('Closed') }}</gl-form-radio>
|
||||
</gl-form-group>
|
||||
|
||||
<!-- Or -->
|
||||
<gl-form-group :label="__('Issue status')" label-sr-only>
|
||||
<gl-form-radio-group v-model="selected" :options="options" />
|
||||
</gl-form-group>
|
||||
```
|
||||
|
||||
#### File inputs with accessible names
|
||||
|
||||
File input examples:
|
||||
|
|
@ -244,27 +100,6 @@ File input examples:
|
|||
<input id="attach-file" type="file" />
|
||||
```
|
||||
|
||||
#### GlToggle components with accessible names
|
||||
|
||||
`GlToggle` examples:
|
||||
|
||||
```html
|
||||
<!-- GlToggle with label -->
|
||||
<gl-toggle v-model="notifications" :label="__('Notifications')" />
|
||||
|
||||
<!-- GlToggle with hidden label -->
|
||||
<gl-toggle v-model="notifications" :label="__('Notifications')" label-position="hidden" />
|
||||
```
|
||||
|
||||
#### GlFormCombobox components with accessible names
|
||||
|
||||
`GlFormCombobox` example:
|
||||
|
||||
```html
|
||||
<!-- GlFormCombobox with label -->
|
||||
<gl-form-combobox :label-text="__('Key')" :token-list="$options.tokenList" />
|
||||
```
|
||||
|
||||
#### Images with accessible names
|
||||
|
||||
Image examples:
|
||||
|
|
@ -295,14 +130,6 @@ Buttons and links should have accessible names that are descriptive enough to be
|
|||
<gl-link :href="url">{{ __("GitLab's accessibility page") }}</gl-link>
|
||||
```
|
||||
|
||||
#### Links styled like buttons
|
||||
|
||||
Links can be styled like buttons using `GlButton`.
|
||||
|
||||
```html
|
||||
<gl-button :href="url">{{ __('Link styled as a button') }}</gl-button>
|
||||
```
|
||||
|
||||
## Role
|
||||
|
||||
In general, avoid using `role`.
|
||||
|
|
@ -355,7 +182,7 @@ Use interactive elements instead of `div` and `span` tags.
|
|||
For example:
|
||||
|
||||
- If the element should be clickable, use a `button` (`GlButton`).
|
||||
- If the element should be text editable, use an [`input` or `textarea`](#text-inputs-with-accessible-names).
|
||||
- If the element should be text editable, use an [`input`](https://design.gitlab.com/components/text-input#accessibility) or [`textarea`](https://design.gitlab.com/components/textarea#accessibility).
|
||||
|
||||
Once the markup is semantically complete, use CSS to update it to its desired visual state.
|
||||
|
||||
|
|
@ -451,28 +278,6 @@ Icons that are clickable are semantically buttons, so they should be rendered as
|
|||
<gl-button icon="close" category="tertiary" :aria-label="__('Close')" @click="handleClick" />
|
||||
```
|
||||
|
||||
## Tooltips
|
||||
|
||||
When adding tooltips, we must ensure that the element with the tooltip can receive focus so keyboard users can see the tooltip.
|
||||
If the element is a static one, such as an icon, we can enclose it in a button, which already is
|
||||
focusable, so we don't have to add `tabindex=0` to the icon.
|
||||
|
||||
The following code snippet is a good example of an icon with a tooltip.
|
||||
|
||||
- It is automatically focusable, as it is a button.
|
||||
- It is given an accessible name with `aria-label`, as it is a button with no text.
|
||||
|
||||
```html
|
||||
<button
|
||||
v-gl-tooltip
|
||||
class="gl-border-0 gl-bg-transparent gl-p-0 gl-leading-0"
|
||||
:title="tooltipText"
|
||||
:aria-label="__('Warning')"
|
||||
>
|
||||
<gl-icon name="warning" />
|
||||
</button>
|
||||
```
|
||||
|
||||
## Hiding elements
|
||||
|
||||
Use the following table to hide elements from users, when appropriate.
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
---
|
||||
stage: Govern
|
||||
stage: Software Supply Chain Security
|
||||
group: Anti-Abuse
|
||||
info: Any user with at least the Maintainer role can merge updates to this content. For details, see https://docs.gitlab.com/ee/development/development_processes.html#development-guidelines-review.
|
||||
---
|
||||
|
|
|
|||
|
|
@ -89,17 +89,15 @@ sequenceDiagram
|
|||
- `elapsed` - Amount of time which passed since Service Ping report process started and moment of error occurrence
|
||||
- `message` - Error message
|
||||
|
||||
<pre>
|
||||
<code>
|
||||
{
|
||||
"uuid"=>"02333324-1cd7-4c3b-a45b-a4993f05fb1d",
|
||||
"hostname"=>"127.0.0.1",
|
||||
"version"=>"14.7.0-pre",
|
||||
"elapsed"=>0.006946,
|
||||
"message"=>'PG::UndefinedColumn: ERROR: column \"non_existent_attribute\" does not exist\nLINE 1: SELECT COUNT(non_existent_attribute) FROM \"issues\" /*applica...'
|
||||
}
|
||||
</code>
|
||||
</pre>
|
||||
```ruby
|
||||
{
|
||||
"uuid"=>"02333324-1cd7-4c3b-a45b-a4993f05fb1d",
|
||||
"hostname"=>"127.0.0.1",
|
||||
"version"=>"14.7.0-pre",
|
||||
"elapsed"=>0.006946,
|
||||
"message"=>'PG::UndefinedColumn: ERROR: column \"non_existent_attribute\" does not exist\nLINE 1: SELECT COUNT(non_existent_attribute) FROM \"issues\" /*applica...'
|
||||
}
|
||||
```
|
||||
|
||||
1. Finally, the timing metadata information that is used for diagnostic purposes is submitted to the Versions application. It consists of a list of metric identifiers and the time it took to calculate the metrics:
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
---
|
||||
stage: Govern
|
||||
stage: Software Supply Chain Security
|
||||
group: Anti-Abuse
|
||||
info: Any user with at least the Maintainer role can merge updates to this content. For details, see https://docs.gitlab.com/ee/development/development_processes.html#development-guidelines-review.
|
||||
---
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
---
|
||||
stage: Govern
|
||||
stage: Software Supply Chain Security
|
||||
group: Anti-Abuse
|
||||
info: Any user with at least the Maintainer role can merge updates to this content. For details, see https://docs.gitlab.com/ee/development/development_processes.html#development-guidelines-review.
|
||||
---
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
---
|
||||
stage: Govern
|
||||
stage: Software Supply Chain Security
|
||||
group: Anti-Abuse
|
||||
info: Any user with at least the Maintainer role can merge updates to this content. For details, see https://docs.gitlab.com/ee/development/development_processes.html#development-guidelines-review.
|
||||
---
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
---
|
||||
stage: Govern
|
||||
stage: Software Supply Chain Security
|
||||
group: Anti-Abuse
|
||||
info: Any user with at least the Maintainer role can merge updates to this content. For details, see https://docs.gitlab.com/ee/development/development_processes.html#development-guidelines-review.
|
||||
---
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
---
|
||||
stage: Govern
|
||||
stage: Software Supply Chain Security
|
||||
group: Anti-Abuse
|
||||
info: Any user with at least the Maintainer role can merge updates to this content. For details, see https://docs.gitlab.com/ee/development/development_processes.html#development-guidelines-review.
|
||||
---
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
---
|
||||
stage: Govern
|
||||
stage: Software Supply Chain Security
|
||||
group: Anti-Abuse
|
||||
info: Any user with at least the Maintainer role can merge updates to this content. For details, see https://docs.gitlab.com/ee/development/development_processes.html#development-guidelines-review.
|
||||
---
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
---
|
||||
stage: Govern
|
||||
stage: Software Supply Chain Security
|
||||
group: Anti-Abuse
|
||||
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://handbook.gitlab.com/handbook/product/ux/technical-writing/#assignments
|
||||
---
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
---
|
||||
stage: Govern
|
||||
stage: Software Supply Chain Security
|
||||
group: Anti-Abuse
|
||||
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://handbook.gitlab.com/handbook/product/ux/technical-writing/#assignments
|
||||
---
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
---
|
||||
stage: Govern
|
||||
stage: Software Supply Chain Security
|
||||
group: Anti-Abuse
|
||||
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://handbook.gitlab.com/handbook/product/ux/technical-writing/#assignments
|
||||
---
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
---
|
||||
stage: Govern
|
||||
stage: Software Supply Chain Security
|
||||
group: Anti-Abuse
|
||||
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://handbook.gitlab.com/handbook/product/ux/technical-writing/#assignments
|
||||
---
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
---
|
||||
stage: Govern
|
||||
stage: Software Supply Chain Security
|
||||
group: Anti-Abuse
|
||||
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://handbook.gitlab.com/handbook/product/ux/technical-writing/#assignments
|
||||
---
|
||||
|
|
|
|||
|
|
@ -4,123 +4,123 @@ group: Distribution
|
|||
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://handbook.gitlab.com/handbook/product/ux/technical-writing/#assignments
|
||||
---
|
||||
|
||||
# Convert Community Edition to Enterprise Edition
|
||||
# Convert a Linux package CE instance to EE
|
||||
|
||||
DETAILS:
|
||||
**Tier:** Free, Premium, Ultimate
|
||||
**Offering:** Self-managed
|
||||
|
||||
To convert an existing GitLab Community Edition (CE) server installed using the Linux
|
||||
packages to GitLab [Enterprise Edition](https://about.gitlab.com/pricing/) (EE), you install the EE
|
||||
package on top of CE.
|
||||
You can convert an existing Linux package instance from Community Edition (CE) to Enterprise Edition (EE).
|
||||
To convert the instance, you install the EE Linux package on top of the CE instance.
|
||||
|
||||
Converting from the same version of CE to EE is not explicitly necessary, and any standard upgrade
|
||||
(for example, CE 12.0 to EE 12.1) should work. However, in the following steps we assume that
|
||||
you are upgrading the same version (for example, CE 12.1 to EE 12.1), which is **recommended**.
|
||||
You don't need the same version of CE to EE. For example, CE 17.0 to EE 17.1 should work. However, upgrading the same
|
||||
version (for example, CE 17.1 to EE 17.1) is **recommended**.
|
||||
|
||||
WARNING:
|
||||
When updating to EE from CE, avoid reverting back to CE if you plan to go to EE again in the
|
||||
future. Reverting back to CE can cause
|
||||
[database issues](package_troubleshooting.md#500-error-when-accessing-project--settings--repository)
|
||||
that may require Support intervention.
|
||||
After you convert from EE from CE, don't revert back to CE if you plan to go to EE again. Reverting back to CE can cause
|
||||
[database issues](package_troubleshooting.md#500-error-when-accessing-project--settings--repository) that may require
|
||||
Support intervention.
|
||||
|
||||
The steps can be summed up to:
|
||||
## Convert from CE to EE
|
||||
|
||||
To convert a Linux package CE instance to EE:
|
||||
|
||||
1. Make a [GitLab backup](../../administration/backup_restore/backup_gitlab.md).
|
||||
|
||||
1. Find the installed GitLab version:
|
||||
|
||||
**For Debian/Ubuntu**
|
||||
::Tabs
|
||||
|
||||
:::TabTitle Debian/Ubuntu
|
||||
|
||||
```shell
|
||||
sudo apt-cache policy gitlab-ce | grep Installed
|
||||
```
|
||||
|
||||
The output should be similar to: `Installed: 13.0.4-ce.0`. In that case,
|
||||
the equivalent Enterprise Edition version is: `13.0.4-ee.0`. Write this
|
||||
value down.
|
||||
Note down the returned version.
|
||||
|
||||
**For CentOS/RHEL**
|
||||
:::TabTitle CentOS/RHEL
|
||||
|
||||
```shell
|
||||
sudo rpm -q gitlab-ce
|
||||
```
|
||||
|
||||
The output should be similar to: `gitlab-ce-13.0.4-ce.0.el8.x86_64`. In that
|
||||
case, the equivalent Enterprise Edition version is:
|
||||
`gitlab-ee-13.0.4-ee.0.el8.x86_64`. Write this value down.
|
||||
Note down the returned version.
|
||||
|
||||
1. Add the `gitlab-ee` [Apt or Yum repository](https://packages.gitlab.com/gitlab/gitlab-ee/install):
|
||||
::EndTabs
|
||||
|
||||
**For Debian/Ubuntu**
|
||||
1. Add the `gitlab-ee` [Apt or Yum repository](https://packages.gitlab.com/gitlab/gitlab-ee/install). These commands
|
||||
find your OS version and automatically set up the repository. If you are not comfortable installing the repository
|
||||
through a piped script, you can first [check the script's contents](https://packages.gitlab.com/gitlab/gitlab-ee/install).
|
||||
|
||||
::Tabs
|
||||
|
||||
:::TabTitle Debian/Ubuntu
|
||||
|
||||
```shell
|
||||
curl --silent "https://packages.gitlab.com/install/repositories/gitlab/gitlab-ee/script.deb.sh" | sudo bash
|
||||
```
|
||||
|
||||
**For CentOS/RHEL**
|
||||
:::TabTitle CentOS/RHEL
|
||||
|
||||
```shell
|
||||
curl --silent "https://packages.gitlab.com/install/repositories/gitlab/gitlab-ee/script.rpm.sh" | sudo bash
|
||||
```
|
||||
|
||||
The above command finds your OS version and automatically set up the
|
||||
repository. If you are not comfortable installing the repository through a
|
||||
piped script, you can first
|
||||
[check its contents](https://packages.gitlab.com/gitlab/gitlab-ee/install).
|
||||
::EndTabs
|
||||
|
||||
NOTE:
|
||||
If you want to use `dpkg`/`rpm` instead of `apt-get`/`yum`, go through the first
|
||||
step to find the current GitLab version, then follow
|
||||
[Upgrade using a manually downloaded package](index.md#by-using-a-downloaded-package),
|
||||
and then [add your license](../../administration/license.md).
|
||||
To use `dpkg` or `rpm` instead of using `apt-get` or `yum` follow
|
||||
[Upgrade using a manually downloaded package](index.md#by-using-a-downloaded-package).
|
||||
|
||||
1. Install the `gitlab-ee` package. The install automatically
|
||||
uninstalls the `gitlab-ce` package on your GitLab server. `reconfigure`
|
||||
Omnibus right after the `gitlab-ee` package is installed. **Make sure that you
|
||||
install the exact same GitLab version**:
|
||||
1. Install the `gitlab-ee` Linux package. The install automatically uninstalls the `gitlab-ce` package on your GitLab.
|
||||
|
||||
**For Debian/Ubuntu**
|
||||
::Tabs
|
||||
|
||||
:::TabTitle Debian/Ubuntu
|
||||
|
||||
```shell
|
||||
## Make sure the repositories are up-to-date
|
||||
sudo apt-get update
|
||||
|
||||
## Install the package using the version you wrote down from step 1
|
||||
sudo apt-get install gitlab-ee=13.0.4-ee.0
|
||||
sudo apt-get install gitlab-ee=17.1.0-ee.0
|
||||
|
||||
## Reconfigure GitLab
|
||||
sudo gitlab-ctl reconfigure
|
||||
```
|
||||
|
||||
**For CentOS/RHEL**
|
||||
:::TabTitle CentOS/RHEL
|
||||
|
||||
```shell
|
||||
## Install the package using the version you wrote down from step 1
|
||||
sudo yum install gitlab-ee-13.0.4-ee.0.el8.x86_64
|
||||
sudo yum install gitlab-ee-17.1.0-ee.0.el9.x86_64
|
||||
|
||||
## Reconfigure GitLab
|
||||
sudo gitlab-ctl reconfigure
|
||||
```
|
||||
|
||||
1. Now activate GitLab Enterprise Edition by [adding your license](../../administration/license.md).
|
||||
::EndTabs
|
||||
|
||||
1. After you confirm that GitLab is working as expected, you may remove the old
|
||||
Community Edition repository:
|
||||
1. [Add your license](../../administration/license.md) to activate Enterprise Edition.
|
||||
1. Confirm that GitLab is working as expected, then you can remove the old Community Edition repository:
|
||||
|
||||
**For Debian/Ubuntu**
|
||||
::Tabs
|
||||
|
||||
:::TabTitle Debian/Ubuntu
|
||||
|
||||
```shell
|
||||
sudo rm /etc/apt/sources.list.d/gitlab_gitlab-ce.list
|
||||
```
|
||||
|
||||
**For CentOS/RHEL**
|
||||
:::TabTitle CentOS/RHEL
|
||||
|
||||
```shell
|
||||
sudo rm /etc/yum.repos.d/gitlab_gitlab-ce.repo
|
||||
```
|
||||
|
||||
1. Optional. [Set up the Elasticsearch integration](../../integration/advanced_search/elasticsearch.md) to enable [advanced search](../../user/search/advanced_search.md).
|
||||
::EndTabs
|
||||
|
||||
1. Optional. [Set up the Elasticsearch integration](../../integration/advanced_search/elasticsearch.md) to enable
|
||||
[advanced search](../../user/search/advanced_search.md).
|
||||
|
||||
That's it! You can now use GitLab Enterprise Edition! To upgrade to a newer
|
||||
version, follow [Upgrading Linux package instances](index.md).
|
||||
|
|
|
|||
|
|
@ -242,6 +242,21 @@ You can [define project or group variables in the UI](../../../ci/variables/inde
|
|||
|
||||
To prevent a regular pipeline from triggering, users can push a commit to a protected branch with `[skip ci]` in the commit message. However, jobs defined with a pipeline execution policy are always triggered, as the policy ignores the `[skip ci]` directive. This prevents developers from skipping the execution of jobs defined in the policy, which ensures that critical security and compliance checks are always performed.
|
||||
|
||||
## Interaction with scan execution policies
|
||||
|
||||
When you use pipeline execution policies with the `override_ci` strategy, be aware that this can affect the behavior of [scan execution policies](scan_execution_policies.md):
|
||||
|
||||
- The scan execution policy may be overridden if both pipeline execution policies and scan execution policies are configured for a project, and the pipeline execution policy uses the `override_ci` strategy.
|
||||
|
||||
This is because the `override_ci` strategy removes all CI/CD configuration that is defined on the project level, including policies.
|
||||
|
||||
To ensure that both pipeline execution policies and scan execution policies are applied:
|
||||
|
||||
- Consider using a different strategy for pipeline execution policies, such as `inject_ci`.
|
||||
- If you must use `override_ci`, include the scanner templates that you require in your pipeline execution policy to maintain the desired security scans.
|
||||
|
||||
Support for improvements in the integration between these policy types is proposed in [issue 504434](https://gitlab.com/gitlab-org/gitlab/-/issues/504434).
|
||||
|
||||
## Examples
|
||||
|
||||
These examples demonstrate what you can achieve with pipeline execution policies.
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue