From 3256c55b0f188227e27a4863532feee84e654911 Mon Sep 17 00:00:00 2001 From: GitLab Bot Date: Tue, 2 Aug 2022 09:11:05 +0000 Subject: [PATCH] Add latest changes from gitlab-org/gitlab@master --- .gitlab/CODEOWNERS | 139 ++++++++++++++++++ GITALY_SERVER_VERSION | 2 +- app/helpers/ci/pipeline_editor_helper.rb | 2 +- app/helpers/projects_helper.rb | 3 +- app/helpers/search_helper.rb | 8 +- .../project_features_compatibility.rb | 4 + app/models/project.rb | 2 +- app/models/project_feature.rb | 1 + app/policies/project_policy.rb | 12 +- ...al_manage_repository_push_audit_event.yml} | 0 .../import_export/project/import_export.yml | 2 + .../changing_repository_storage_spec.rb | 22 +++ rubocop/cop/gitlab/feature_available_usage.rb | 1 + spec/factories/projects.rb | 1 + .../helpers/ci/pipeline_editor_helper_spec.rb | 4 +- spec/helpers/projects_helper_spec.rb | 3 +- spec/helpers/search_helper_spec.rb | 13 +- .../import_export/safe_model_attributes.yml | 1 + .../project_features_compatibility_spec.rb | 2 +- spec/models/project_spec.rb | 1 + spec/policies/project_policy_spec.rb | 133 ++++++++++++++--- .../lib/tooling/find_codeowners_spec.rb | 43 +++++- tooling/config/CODEOWNERS.yml | 21 +++ tooling/lib/tooling/find_codeowners.rb | 92 +++++++----- 24 files changed, 434 insertions(+), 78 deletions(-) rename data/removals/15_0/{removal_manage_ repository_push_audit_event.yml => removal_manage_repository_push_audit_event.yml} (100%) diff --git a/.gitlab/CODEOWNERS b/.gitlab/CODEOWNERS index b7cc60d2f68..d82821205da 100644 --- a/.gitlab/CODEOWNERS +++ b/.gitlab/CODEOWNERS @@ -1057,3 +1057,142 @@ lib/gitlab/checks/** @proglottis @toon @zj-gitlab /lib/system_check/incoming_email/imap_authentication_check.rb @gitlab-org/manage/authentication-and-authorization/approvers /lib/tasks/gitlab/password.rake @gitlab-org/manage/authentication-and-authorization/approvers /lib/tasks/tokens.rake @gitlab-org/manage/authentication-and-authorization/approvers + +[Compliance] +/ee/app/services/audit_events/build_service.rb @gitlab-org/manage/compliance +/ee/spec/services/audit_events/custom_audit_event_service_spec.rb @gitlab-org/manage/compliance +/app/models/audit_event.rb @gitlab-org/manage/compliance +/app/services/audit_event_service.rb @gitlab-org/manage/compliance +/app/services/concerns/audit_event_save_type.rb @gitlab-org/manage/compliance +/app/views/profiles/audit_log.html.haml @gitlab-org/manage/compliance +/config/feature_flags/development/custom_headers_streaming_audit_events_ui.yml @gitlab-org/manage/compliance +/data/deprecations/14-3-repository-push-audit-events.yml @gitlab-org/manage/compliance +/data/removals/15_0/removal_manage_repository_push_audit_event.yml @gitlab-org/manage/compliance +/db/docs/audit_events.yml @gitlab-org/manage/compliance +/db/docs/audit_events_external_audit_event_destinations.yml @gitlab-org/manage/compliance +/db/docs/audit_events_streaming_headers.yml @gitlab-org/manage/compliance +/db/migrate/20210819185500_create_external_audit_event_destinations_table.rb @gitlab-org/manage/compliance +/db/migrate/20220524141800_create_audit_events_streaming_headers.rb @gitlab-org/manage/compliance +/db/post_migrate/20210331105335_drop_non_partitioned_audit_events.rb @gitlab-org/manage/compliance +/db/post_migrate/20220119094503_populate_audit_event_streaming_verification_token.rb @gitlab-org/manage/compliance +/doc/administration/audit_event_streaming.md @gitlab-org/manage/compliance +/doc/administration/audit_events.md @gitlab-org/manage/compliance +/doc/administration/audit_reports.md @gitlab-org/manage/compliance +/doc/administration/auditor_users.md @gitlab-org/manage/compliance +/doc/api/audit_events.md @gitlab-org/manage/compliance +/doc/api/graphql/audit_report.md @gitlab-org/manage/compliance +/ee/app/assets/javascripts/audit_events/components/audit_events_app.vue @gitlab-org/manage/compliance +/ee/app/assets/javascripts/audit_events/components/audit_events_export_button.vue @gitlab-org/manage/compliance +/ee/app/assets/javascripts/audit_events/components/audit_events_filter.vue @gitlab-org/manage/compliance +/ee/app/assets/javascripts/audit_events/components/audit_events_log.vue @gitlab-org/manage/compliance +/ee/app/assets/javascripts/audit_events/components/audit_events_stream.vue @gitlab-org/manage/compliance +/ee/app/assets/javascripts/audit_events/components/audit_events_table.vue @gitlab-org/manage/compliance +/ee/app/assets/javascripts/audit_events/components/tokens/shared/ @gitlab-org/manage/compliance +/ee/app/assets/javascripts/audit_events/init_audit_events.js @gitlab-org/manage/compliance +/ee/app/controllers/admin/audit_log_reports_controller.rb @gitlab-org/manage/compliance +/ee/app/controllers/admin/audit_logs_controller.rb @gitlab-org/manage/compliance +/ee/app/controllers/concerns/audit_events/audit_events_params.rb @gitlab-org/manage/compliance +/ee/app/controllers/groups/audit_events_controller.rb @gitlab-org/manage/compliance +/ee/app/controllers/projects/audit_events_controller.rb @gitlab-org/manage/compliance +/ee/app/finders/audit_event_finder.rb @gitlab-org/manage/compliance +/ee/app/graphql/types/audit_events/external_audit_event_destination_type.rb @gitlab-org/manage/compliance +/ee/app/helpers/audit_events_helper.rb @gitlab-org/manage/compliance +/ee/app/helpers/auditor_user_helper.rb @gitlab-org/manage/compliance +/ee/app/models/audit_events/external_audit_event_destination.rb @gitlab-org/manage/compliance +/ee/app/models/concerns/auditable.rb @gitlab-org/manage/compliance +/ee/app/models/ee/audit_event.rb @gitlab-org/manage/compliance +/ee/app/policies/audit_events/external_audit_event_destination_policy.rb @gitlab-org/manage/compliance +/ee/app/presenters/audit_event_presenter.rb @gitlab-org/manage/compliance +/ee/app/serializers/audit_event_entity.rb @gitlab-org/manage/compliance +/ee/app/serializers/audit_event_serializer.rb @gitlab-org/manage/compliance +/ee/app/services/ci/audit_variable_change_service.rb @gitlab-org/manage/compliance +/ee/app/services/ee/audit_event_service.rb @gitlab-org/manage/compliance +/ee/app/views/admin/users/_auditor_access_level_radio.html.haml @gitlab-org/manage/compliance +/ee/app/views/admin/users/_auditor_user_badge.html.haml @gitlab-org/manage/compliance +/ee/app/views/shared/icons/_icon_audit_events_purple.svg @gitlab-org/manage/compliance +/ee/app/views/shared/promotions/_promote_audit_events.html.haml @gitlab-org/manage/compliance +/ee/app/workers/audit_events/audit_event_streaming_worker.rb @gitlab-org/manage/compliance +/ee/config/events/1652263097_groups__audit_events__index_click_streams_tab.yml @gitlab-org/manage/compliance +/ee/config/events/202108302307_admin_audit_logs_index_click_date_range_button.yml @gitlab-org/manage/compliance +/ee/config/events/202108302307_groups__audit_events_controller_search_audit_event.yml @gitlab-org/manage/compliance +/ee/config/events/202108302307_profiles_controller_search_audit_event.yml @gitlab-org/manage/compliance +/ee/config/events/202108302307_projects__audit_events_controller_search_audit_event.yml @gitlab-org/manage/compliance +/ee/config/events/202111041910_admin__audit_logs_controller_search_audit_event.yml @gitlab-org/manage/compliance +/ee/config/feature_flags/development/audit_event_streaming_git_operations.yml @gitlab-org/manage/compliance +/ee/config/feature_flags/development/audit_log_group_level.yml @gitlab-org/manage/compliance +/ee/config/metrics/counts_28d/20210216183930_g_compliance_audit_events_monthly.yml @gitlab-org/manage/compliance +/ee/config/metrics/counts_28d/20210216183934_i_compliance_audit_events_monthly.yml @gitlab-org/manage/compliance +/ee/config/metrics/counts_28d/20210216183942_a_compliance_audit_events_api_monthly.yml @gitlab-org/manage/compliance +/ee/config/metrics/counts_28d/20211130085433_g_manage_compliance_audit_event_destinations.yml @gitlab-org/manage/compliance +/ee/config/metrics/counts_7d/20210216183906_g_compliance_audit_events.yml @gitlab-org/manage/compliance +/ee/config/metrics/counts_7d/20210216183908_i_compliance_audit_events.yml @gitlab-org/manage/compliance +/ee/config/metrics/counts_7d/20210216183912_a_compliance_audit_events_api.yml @gitlab-org/manage/compliance +/ee/config/metrics/counts_7d/20210216183928_g_compliance_audit_events_weekly.yml @gitlab-org/manage/compliance +/ee/config/metrics/counts_7d/20210216183932_i_compliance_audit_events_weekly.yml @gitlab-org/manage/compliance +/ee/config/metrics/counts_7d/20210216183940_a_compliance_audit_events_api_weekly.yml @gitlab-org/manage/compliance +/ee/config/metrics/counts_all/20211130085433_g_manage_compliance_audit_event_destinations.yml @gitlab-org/manage/compliance +/ee/lib/api/audit_events.rb @gitlab-org/manage/compliance +/ee/lib/audit/external_status_check_changes_auditor.rb @gitlab-org/manage/compliance +/ee/lib/audit/group_merge_request_approval_setting_changes_auditor.rb @gitlab-org/manage/compliance +/ee/lib/audit/group_push_rules_changes_auditor.rb @gitlab-org/manage/compliance +/ee/lib/ee/api/entities/audit_event.rb @gitlab-org/manage/compliance +/ee/lib/ee/audit/ @gitlab-org/manage/compliance +/ee/lib/gitlab/audit/auditor.rb @gitlab-org/manage/compliance +/ee/spec/controllers/admin/audit_log_reports_controller_spec.rb @gitlab-org/manage/compliance +/ee/spec/controllers/admin/audit_logs_controller_spec.rb @gitlab-org/manage/compliance +/ee/spec/controllers/groups/audit_events_controller_spec.rb @gitlab-org/manage/compliance +/ee/spec/controllers/projects/audit_events_controller_spec.rb @gitlab-org/manage/compliance +/ee/spec/factories/audit_events/external_audit_event_destinations.rb @gitlab-org/manage/compliance +/ee/spec/features/admin/admin_audit_logs_spec.rb @gitlab-org/manage/compliance +/ee/spec/features/groups/audit_events_spec.rb @gitlab-org/manage/compliance +/ee/spec/features/projects/audit_events_spec.rb @gitlab-org/manage/compliance +/ee/spec/finders/audit_event_finder_spec.rb @gitlab-org/manage/compliance +/ee/spec/fixtures/api/schemas/public_api/v4/audit_event.json @gitlab-org/manage/compliance +/ee/spec/fixtures/api/schemas/public_api/v4/audit_events.json @gitlab-org/manage/compliance +/ee/spec/frontend/audit_events/components/__snapshots__/ @gitlab-org/manage/compliance +/ee/spec/frontend/audit_events/components/audit_events_app_spec.js @gitlab-org/manage/compliance +/ee/spec/frontend/audit_events/components/audit_events_export_button_spec.js @gitlab-org/manage/compliance +/ee/spec/frontend/audit_events/components/audit_events_filter_spec.js @gitlab-org/manage/compliance +/ee/spec/frontend/audit_events/components/audit_events_logs_spec.js @gitlab-org/manage/compliance +/ee/spec/frontend/audit_events/components/audit_events_stream_spec.js @gitlab-org/manage/compliance +/ee/spec/frontend/audit_events/components/audit_events_table_spec.js @gitlab-org/manage/compliance +/ee/spec/frontend/audit_events/components/tokens/shared/ @gitlab-org/manage/compliance +/ee/spec/graphql/types/audit_events/exterrnal_audit_event_destination_type_spec.rb @gitlab-org/manage/compliance +/ee/spec/helpers/audit_events_helper_spec.rb @gitlab-org/manage/compliance +/ee/spec/lib/audit/external_status_check_changes_auditor_spec.rb @gitlab-org/manage/compliance +/ee/spec/lib/audit/group_merge_request_approval_setting_changes_auditor_spec.rb @gitlab-org/manage/compliance +/ee/spec/lib/audit/group_push_rules_changes_auditor_spec.rb @gitlab-org/manage/compliance +/ee/spec/lib/ee/audit/ @gitlab-org/manage/compliance +/ee/spec/lib/gitlab/audit/auditor_spec.rb @gitlab-org/manage/compliance +/ee/spec/models/audit_events/external_audit_event_destination_spec.rb @gitlab-org/manage/compliance +/ee/spec/models/concerns/auditable_spec.rb @gitlab-org/manage/compliance +/ee/spec/models/ee/audit_event_spec.rb @gitlab-org/manage/compliance +/ee/spec/presenters/audit_event_presenter_spec.rb @gitlab-org/manage/compliance +/ee/spec/requests/admin/audit_events_spec.rb @gitlab-org/manage/compliance +/ee/spec/requests/api/audit_events_spec.rb @gitlab-org/manage/compliance +/ee/spec/requests/api/graphql/group/external_audit_event_destinations_spec.rb @gitlab-org/manage/compliance +/ee/spec/requests/groups/audit_events_spec.rb @gitlab-org/manage/compliance +/ee/spec/requests/projects/audit_events_spec.rb @gitlab-org/manage/compliance +/ee/spec/serializers/audit_event_entity_spec.rb @gitlab-org/manage/compliance +/ee/spec/serializers/audit_event_serializer_spec.rb @gitlab-org/manage/compliance +/ee/spec/services/audit_event_service_spec.rb @gitlab-org/manage/compliance +/ee/spec/support/shared_contexts/audit_event_not_licensed_shared_context.rb @gitlab-org/manage/compliance +/ee/spec/support/shared_contexts/audit_event_queue_shared_context.rb @gitlab-org/manage/compliance +/ee/spec/support/shared_examples/audit/ @gitlab-org/manage/compliance +/ee/spec/support/shared_examples/features/audit_events_filter_shared_examples.rb @gitlab-org/manage/compliance +/ee/spec/support/shared_examples/services/audit_event_logging_shared_examples.rb @gitlab-org/manage/compliance +/ee/spec/workers/audit_events/audit_event_streaming_worker_spec.rb @gitlab-org/manage/compliance +/lib/gitlab/audit_json_logger.rb @gitlab-org/manage/compliance +/qa/qa/ee/page/admin/monitoring/ @gitlab-org/manage/compliance +/qa/qa/specs/features/ee/browser_ui/1_manage/group/group_audit_logs_1_spec.rb @gitlab-org/manage/compliance +/qa/qa/specs/features/ee/browser_ui/1_manage/group/group_audit_logs_2_spec.rb @gitlab-org/manage/compliance +/qa/qa/specs/features/ee/browser_ui/1_manage/instance/ @gitlab-org/manage/compliance +/qa/qa/specs/features/ee/browser_ui/1_manage/project/project_audit_logs_spec.rb @gitlab-org/manage/compliance +/spec/factories/audit_events.rb @gitlab-org/manage/compliance +/spec/migrations/populate_audit_event_streaming_verification_token_spec.rb @gitlab-org/manage/compliance +/spec/models/audit_event_spec.rb @gitlab-org/manage/compliance +/spec/services/audit_event_service_spec.rb @gitlab-org/manage/compliance +/spec/services/concerns/audit_event_save_type_spec.rb @gitlab-org/manage/compliance +/spec/support/shared_examples/sends_git_audit_streaming_event_shared_examples.rb @gitlab-org/manage/compliance +/spec/views/profiles/audit_log.html.haml_spec.rb @gitlab-org/manage/compliance +/vendor/project_templates/hipaa_audit_protocol.tar.gz @gitlab-org/manage/compliance diff --git a/GITALY_SERVER_VERSION b/GITALY_SERVER_VERSION index fa0e10c647e..d89e6180f1a 100644 --- a/GITALY_SERVER_VERSION +++ b/GITALY_SERVER_VERSION @@ -1 +1 @@ -445024454b60b661cc7bc7782c9e9367517f42e2 +157e6b6ad8fd7aa0ebdd43727f00b81f34b100a1 diff --git a/app/helpers/ci/pipeline_editor_helper.rb b/app/helpers/ci/pipeline_editor_helper.rb index d044a93213a..48eb7b4c41a 100644 --- a/app/helpers/ci/pipeline_editor_helper.rb +++ b/app/helpers/ci/pipeline_editor_helper.rb @@ -33,7 +33,7 @@ module Ci "project-full-path" => project.full_path, "project-namespace" => project.namespace.full_path, "runner-help-page-path" => help_page_path('ci/runners/index'), - "simulate-pipeline-help-page-path" => help_page_path('ci/lint', anchor: 'simulate-a-pipeline'), + "simulate-pipeline-help-page-path" => help_page_path('ci/pipeline_editor/index', anchor: 'simulate-a-cicd-pipeline'), "total-branches" => total_branches, "validate-tab-illustration-path" => image_path('illustrations/project-run-CICD-pipelines-sm.svg'), "yml-help-page-path" => help_page_path('ci/yaml/index') diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb index c52cadeaec2..75622e7430c 100644 --- a/app/helpers/projects_helper.rb +++ b/app/helpers/projects_helper.rb @@ -639,7 +639,8 @@ module ProjectsHelper warnAboutPotentiallyUnwantedCharacters: project.warn_about_potentially_unwanted_characters?, enforceAuthChecksOnUploads: project.enforce_auth_checks_on_uploads?, securityAndComplianceAccessLevel: project.security_and_compliance_access_level, - containerRegistryAccessLevel: feature.container_registry_access_level + containerRegistryAccessLevel: feature.container_registry_access_level, + environmentsAccessLevel: feature.environments_access_level } end diff --git a/app/helpers/search_helper.rb b/app/helpers/search_helper.rb index 6e2e0a86446..dc53be330fe 100644 --- a/app/helpers/search_helper.rb +++ b/app/helpers/search_helper.rb @@ -22,14 +22,14 @@ module SearchHelper resource_results(term) when :generic [ - generic_results(term), - recent_items_autocomplete(term) + recent_items_autocomplete(term), + generic_results(term) ] else [ - generic_results(term), + recent_items_autocomplete(term), resource_results(term), - recent_items_autocomplete(term) + generic_results(term) ] end diff --git a/app/models/concerns/project_features_compatibility.rb b/app/models/concerns/project_features_compatibility.rb index 900e8f7d39b..65b1cf023ec 100644 --- a/app/models/concerns/project_features_compatibility.rb +++ b/app/models/concerns/project_features_compatibility.rb @@ -94,6 +94,10 @@ module ProjectFeaturesCompatibility write_feature_attribute_string(:container_registry_access_level, value) end + def environments_access_level=(value) + write_feature_attribute_string(:environments_access_level, value) + end + # TODO: Remove this method after we drop support for project create/edit APIs to set the # container_registry_enabled attribute. They can instead set the container_registry_access_level # attribute. diff --git a/app/models/project.rb b/app/models/project.rb index 8e59a3599dd..cfa726ede41 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -446,7 +446,7 @@ class Project < ApplicationRecord :repository_access_level, :package_registry_access_level, :pages_access_level, :metrics_dashboard_access_level, :analytics_access_level, :operations_access_level, :security_and_compliance_access_level, - :container_registry_access_level, + :container_registry_access_level, :environments_access_level, to: :project_feature, allow_nil: true delegate :show_default_award_emojis, :show_default_award_emojis=, diff --git a/app/models/project_feature.rb b/app/models/project_feature.rb index 0a30e125c83..30d871a2756 100644 --- a/app/models/project_feature.rb +++ b/app/models/project_feature.rb @@ -21,6 +21,7 @@ class ProjectFeature < ApplicationRecord security_and_compliance container_registry package_registry + environments ].freeze EXPORTABLE_FEATURES = (FEATURES - [:security_and_compliance, :pages]).freeze diff --git a/app/policies/project_policy.rb b/app/policies/project_policy.rb index 9d121715d2c..a36aa5721f2 100644 --- a/app/policies/project_policy.rb +++ b/app/policies/project_policy.rb @@ -209,6 +209,7 @@ class ProjectPolicy < BasePolicy analytics operations security_and_compliance + environments ] features.each do |f| @@ -366,7 +367,11 @@ class ProjectPolicy < BasePolicy prevent(:metrics_dashboard) end - rule { operations_disabled }.policy do + condition(:split_operations_visibility_permissions) do + ::Feature.enabled?(:split_operations_visibility_permissions, @subject) + end + + rule { ~split_operations_visibility_permissions & operations_disabled }.policy do prevent(*create_read_update_admin_destroy(:feature_flag)) prevent(*create_read_update_admin_destroy(:environment)) prevent(*create_read_update_admin_destroy(:sentry_issue)) @@ -379,6 +384,11 @@ class ProjectPolicy < BasePolicy prevent(:read_prometheus) end + rule { split_operations_visibility_permissions & environments_disabled }.policy do + prevent(*create_read_update_admin_destroy(:environment)) + prevent(*create_read_update_admin_destroy(:deployment)) + end + rule { can?(:metrics_dashboard) }.policy do enable :read_prometheus enable :read_deployment diff --git a/data/removals/15_0/removal_manage_ repository_push_audit_event.yml b/data/removals/15_0/removal_manage_repository_push_audit_event.yml similarity index 100% rename from data/removals/15_0/removal_manage_ repository_push_audit_event.yml rename to data/removals/15_0/removal_manage_repository_push_audit_event.yml diff --git a/lib/gitlab/import_export/project/import_export.yml b/lib/gitlab/import_export/project/import_export.yml index 50ff6146174..1fdc374aa39 100644 --- a/lib/gitlab/import_export/project/import_export.yml +++ b/lib/gitlab/import_export/project/import_export.yml @@ -284,6 +284,7 @@ included_attributes: - :security_and_compliance_access_level - :container_registry_access_level - :package_registry_access_level + - :environments_access_level prometheus_metrics: - :created_at - :updated_at @@ -686,6 +687,7 @@ included_attributes: - :security_and_compliance_access_level - :container_registry_access_level - :package_registry_access_level + - :environments_access_level - :allow_merge_on_skipped_pipeline - :auto_devops_deploy_strategy - :auto_devops_enabled diff --git a/qa/qa/specs/features/api/3_create/gitaly/changing_repository_storage_spec.rb b/qa/qa/specs/features/api/3_create/gitaly/changing_repository_storage_spec.rb index cd1b7730fa9..5ee6dfdb8d8 100644 --- a/qa/qa/specs/features/api/3_create/gitaly/changing_repository_storage_spec.rb +++ b/qa/qa/specs/features/api/3_create/gitaly/changing_repository_storage_spec.rb @@ -67,6 +67,28 @@ module QA it_behaves_like 'repository storage move' end + + # Note: This test doesn't have the :orchestrated tag because it runs in the Test::Integration::Praefect + # scenario with other tests that aren't considered orchestrated. + # It also runs on staging using nfs-file07 as non-cluster storage and nfs-file22 as cluster/praefect storage + context 'when moving from Gitaly Cluster to Gitaly', :requires_praefect, testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/369204' do + let(:source_storage) { { type: :praefect, name: QA::Runtime::Env.praefect_repository_storage } } + let(:destination_storage) { { type: :gitaly, name: QA::Runtime::Env.non_cluster_repository_storage } } + let(:project) do + Resource::Project.fabricate_via_api! do |project| + project.name = 'repo-storage-move' + project.initialize_with_readme = true + project.repository_storage = source_storage[:name] + project.api_client = Runtime::API::Client.as_admin + end + end + + before do + praefect_manager.gitlab = 'gitlab-gitaly-cluster' + end + + it_behaves_like 'repository storage move' + end end end end diff --git a/rubocop/cop/gitlab/feature_available_usage.rb b/rubocop/cop/gitlab/feature_available_usage.rb index b50bdd8ca43..fafe6c35b5f 100644 --- a/rubocop/cop/gitlab/feature_available_usage.rb +++ b/rubocop/cop/gitlab/feature_available_usage.rb @@ -23,6 +23,7 @@ module RuboCop operations security_and_compliance container_registry + environments ].freeze EE_FEATURES = %i[requirements].freeze ALL_FEATURES = (FEATURES + EE_FEATURES).freeze diff --git a/spec/factories/projects.rb b/spec/factories/projects.rb index 5c8f5d1a603..107fa28a639 100644 --- a/spec/factories/projects.rb +++ b/spec/factories/projects.rb @@ -37,6 +37,7 @@ FactoryBot.define do operations_access_level { ProjectFeature::ENABLED } container_registry_access_level { ProjectFeature::ENABLED } security_and_compliance_access_level { ProjectFeature::PRIVATE } + environments_access_level { ProjectFeature::ENABLED } # we can't assign the delegated `#ci_cd_settings` attributes directly, as the # `#ci_cd_settings` relation needs to be created first diff --git a/spec/helpers/ci/pipeline_editor_helper_spec.rb b/spec/helpers/ci/pipeline_editor_helper_spec.rb index bc9e47a4ca1..5d3837171d0 100644 --- a/spec/helpers/ci/pipeline_editor_helper_spec.rb +++ b/spec/helpers/ci/pipeline_editor_helper_spec.rb @@ -63,7 +63,7 @@ RSpec.describe Ci::PipelineEditorHelper do "project-full-path" => project.full_path, "project-namespace" => project.namespace.full_path, "runner-help-page-path" => help_page_path('ci/runners/index'), - "simulate-pipeline-help-page-path" => help_page_path('ci/lint', anchor: 'simulate-a-pipeline'), + "simulate-pipeline-help-page-path" => help_page_path('ci/pipeline_editor/index', anchor: 'simulate-a-cicd-pipeline'), "total-branches" => project.repository.branches.length, "validate-tab-illustration-path" => 'illustrations/validate.svg', "yml-help-page-path" => help_page_path('ci/yaml/index') @@ -94,7 +94,7 @@ RSpec.describe Ci::PipelineEditorHelper do "project-full-path" => project.full_path, "project-namespace" => project.namespace.full_path, "runner-help-page-path" => help_page_path('ci/runners/index'), - "simulate-pipeline-help-page-path" => help_page_path('ci/lint', anchor: 'simulate-a-pipeline'), + "simulate-pipeline-help-page-path" => help_page_path('ci/pipeline_editor/index', anchor: 'simulate-a-cicd-pipeline'), "total-branches" => 0, "validate-tab-illustration-path" => 'illustrations/validate.svg', "yml-help-page-path" => help_page_path('ci/yaml/index') diff --git a/spec/helpers/projects_helper_spec.rb b/spec/helpers/projects_helper_spec.rb index b443ebff552..200e93f8dff 100644 --- a/spec/helpers/projects_helper_spec.rb +++ b/spec/helpers/projects_helper_spec.rb @@ -966,7 +966,8 @@ RSpec.describe ProjectsHelper do operationsAccessLevel: project.project_feature.operations_access_level, showDefaultAwardEmojis: project.show_default_award_emojis?, securityAndComplianceAccessLevel: project.security_and_compliance_access_level, - containerRegistryAccessLevel: project.project_feature.container_registry_access_level + containerRegistryAccessLevel: project.project_feature.container_registry_access_level, + environmentsAccessLevel: project.project_feature.environments_access_level ) end diff --git a/spec/helpers/search_helper_spec.rb b/spec/helpers/search_helper_spec.rb index 1ead1fc9b8b..513e2865ee3 100644 --- a/spec/helpers/search_helper_spec.rb +++ b/spec/helpers/search_helper_spec.rb @@ -74,19 +74,21 @@ RSpec.describe SearchHelper do expect(result.keys).to match_array(%i[category id value label url avatar_url]) end - it 'includes the users recently viewed issues', :aggregate_failures do + it 'includes the users recently viewed issues and project with correct order', :aggregate_failures do recent_issues = instance_double(::Gitlab::Search::RecentIssues) expect(::Gitlab::Search::RecentIssues).to receive(:new).with(user: user).and_return(recent_issues) project1 = create(:project, :with_avatar, namespace: user.namespace) project2 = create(:project, namespace: user.namespace) issue1 = create(:issue, title: 'issue 1', project: project1) issue2 = create(:issue, title: 'issue 2', project: project2) + project = create(:project, title: 'the search term') + project.add_developer(user) expect(recent_issues).to receive(:search).with('the search term').and_return(Issue.id_in_ordered([issue1.id, issue2.id])) results = search_autocomplete_opts("the search term") - expect(results.count).to eq(2) + expect(results.count).to eq(3) expect(results[0]).to include({ category: 'Recent issues', @@ -103,6 +105,13 @@ RSpec.describe SearchHelper do url: Gitlab::Routing.url_helpers.project_issue_path(issue2.project, issue2), avatar_url: '' # This project didn't have an avatar so set this to '' }) + + expect(results[2]).to include({ + category: 'Projects', + id: project.id, + label: project.full_name, + url: Gitlab::Routing.url_helpers.project_path(project) + }) end it 'includes the users recently viewed issues with the exact same name', :aggregate_failures do diff --git a/spec/lib/gitlab/import_export/safe_model_attributes.yml b/spec/lib/gitlab/import_export/safe_model_attributes.yml index bd60bb53d49..3ff830b825b 100644 --- a/spec/lib/gitlab/import_export/safe_model_attributes.yml +++ b/spec/lib/gitlab/import_export/safe_model_attributes.yml @@ -584,6 +584,7 @@ ProjectFeature: - security_and_compliance_access_level - container_registry_access_level - package_registry_access_level +- environments_access_level - created_at - updated_at ProtectedBranch::MergeAccessLevel: diff --git a/spec/models/concerns/project_features_compatibility_spec.rb b/spec/models/concerns/project_features_compatibility_spec.rb index f2dc8464e86..6730b7a02f3 100644 --- a/spec/models/concerns/project_features_compatibility_spec.rb +++ b/spec/models/concerns/project_features_compatibility_spec.rb @@ -5,7 +5,7 @@ require 'spec_helper' RSpec.describe ProjectFeaturesCompatibility do let(:project) { create(:project) } let(:features_enabled) { %w(issues wiki builds merge_requests snippets security_and_compliance) } - let(:features) { features_enabled + %w(repository pages operations container_registry package_registry) } + let(:features) { features_enabled + %w(repository pages operations container_registry package_registry environments) } # We had issues_enabled, snippets_enabled, builds_enabled, merge_requests_enabled and issues_enabled fields on projects table # All those fields got moved to a new table called project_feature and are now integers instead of booleans diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index b434b2c0332..fb6fc01ed88 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -831,6 +831,7 @@ RSpec.describe Project, factory_default: :keep do it { is_expected.to delegate_method(:last_pipeline).to(:commit).allow_nil } it { is_expected.to delegate_method(:container_registry_enabled?).to(:project_feature) } it { is_expected.to delegate_method(:container_registry_access_level).to(:project_feature) } + it { is_expected.to delegate_method(:environments_access_level).to(:project_feature) } describe 'read project settings' do %i( diff --git a/spec/policies/project_policy_spec.rb b/spec/policies/project_policy_spec.rb index c041c72a0be..01a0a96be30 100644 --- a/spec/policies/project_policy_spec.rb +++ b/spec/policies/project_policy_spec.rb @@ -1930,6 +1930,10 @@ RSpec.describe ProjectPolicy do describe 'operations feature' do using RSpec::Parameterized::TableSyntax + before do + stub_feature_flags(split_operations_visibility_permissions: false) + end + let(:guest_operations_permissions) { [:read_environment, :read_deployment] } let(:developer_operations_permissions) do @@ -2002,30 +2006,6 @@ RSpec.describe ProjectPolicy do end end - def project_subject(project_type) - case project_type - when :public - public_project - when :internal - internal_project - else - private_project - end - end - - def user_subject(role) - case role - when :maintainer - maintainer - when :developer - developer - when :guest - guest - when :anonymous - anonymous - end - end - def permissions_abilities(role) case role when :maintainer @@ -2039,6 +2019,87 @@ RSpec.describe ProjectPolicy do end end + describe 'environments feature' do + using RSpec::Parameterized::TableSyntax + + let(:guest_environments_permissions) { [:read_environment, :read_deployment] } + + let(:developer_environments_permissions) do + guest_environments_permissions + [ + :create_environment, :create_deployment, :update_environment, :update_deployment, :destroy_environment + ] + end + + let(:maintainer_environments_permissions) do + developer_environments_permissions + [:admin_environment, :admin_deployment] + end + + where(:project_visibility, :access_level, :role, :allowed) do + :public | ProjectFeature::ENABLED | :maintainer | true + :public | ProjectFeature::ENABLED | :developer | true + :public | ProjectFeature::ENABLED | :guest | true + :public | ProjectFeature::ENABLED | :anonymous | true + :public | ProjectFeature::PRIVATE | :maintainer | true + :public | ProjectFeature::PRIVATE | :developer | true + :public | ProjectFeature::PRIVATE | :guest | true + :public | ProjectFeature::PRIVATE | :anonymous | false + :public | ProjectFeature::DISABLED | :maintainer | false + :public | ProjectFeature::DISABLED | :developer | false + :public | ProjectFeature::DISABLED | :guest | false + :public | ProjectFeature::DISABLED | :anonymous | false + :internal | ProjectFeature::ENABLED | :maintainer | true + :internal | ProjectFeature::ENABLED | :developer | true + :internal | ProjectFeature::ENABLED | :guest | true + :internal | ProjectFeature::ENABLED | :anonymous | false + :internal | ProjectFeature::PRIVATE | :maintainer | true + :internal | ProjectFeature::PRIVATE | :developer | true + :internal | ProjectFeature::PRIVATE | :guest | true + :internal | ProjectFeature::PRIVATE | :anonymous | false + :internal | ProjectFeature::DISABLED | :maintainer | false + :internal | ProjectFeature::DISABLED | :developer | false + :internal | ProjectFeature::DISABLED | :guest | false + :internal | ProjectFeature::DISABLED | :anonymous | false + :private | ProjectFeature::ENABLED | :maintainer | true + :private | ProjectFeature::ENABLED | :developer | true + :private | ProjectFeature::ENABLED | :guest | false + :private | ProjectFeature::ENABLED | :anonymous | false + :private | ProjectFeature::PRIVATE | :maintainer | true + :private | ProjectFeature::PRIVATE | :developer | true + :private | ProjectFeature::PRIVATE | :guest | false + :private | ProjectFeature::PRIVATE | :anonymous | false + :private | ProjectFeature::DISABLED | :maintainer | false + :private | ProjectFeature::DISABLED | :developer | false + :private | ProjectFeature::DISABLED | :guest | false + :private | ProjectFeature::DISABLED | :anonymous | false + end + + with_them do + let(:current_user) { user_subject(role) } + let(:project) { project_subject(project_visibility) } + + it 'allows/disallows the abilities based on the environments feature access level' do + project.project_feature.update!(environments_access_level: access_level) + + if allowed + expect_allowed(*permissions_abilities(role)) + else + expect_disallowed(*permissions_abilities(role)) + end + end + + def permissions_abilities(role) + case role + when :maintainer + maintainer_environments_permissions + when :developer + developer_environments_permissions + else + guest_environments_permissions + end + end + end + end + describe 'access_security_and_compliance' do context 'when the "Security & Compliance" is enabled' do before do @@ -2481,4 +2542,28 @@ RSpec.describe ProjectPolicy do end end end + + def project_subject(project_type) + case project_type + when :public + public_project + when :internal + internal_project + else + private_project + end + end + + def user_subject(role) + case role + when :maintainer + maintainer + when :developer + developer + when :guest + guest + when :anonymous + anonymous + end + end end diff --git a/spec/tooling/lib/tooling/find_codeowners_spec.rb b/spec/tooling/lib/tooling/find_codeowners_spec.rb index 10c2a076847..5f6f83ab2c7 100644 --- a/spec/tooling/lib/tooling/find_codeowners_spec.rb +++ b/spec/tooling/lib/tooling/find_codeowners_spec.rb @@ -11,6 +11,7 @@ RSpec.describe Tooling::FindCodeowners do allow(subject).to receive(:load_config).and_return( '[Section name]': { '@group': { + entries: %w[whatever entries], allow: { keywords: %w[dir0 file], patterns: ['/%{keyword}/**/*', '/%{keyword}'] @@ -31,8 +32,11 @@ RSpec.describe Tooling::FindCodeowners do end end.to output(<<~CODEOWNERS).to_stdout [Section name] + whatever @group + entries @group /dir0/dir1/ @group /file @group + CODEOWNERS end end @@ -57,21 +61,33 @@ RSpec.describe Tooling::FindCodeowners do patterns: ['%{keyword}'] } } + }, + '[Compliance]': { + '@gitlab-org/manage/compliance': { + entries: %w[ + /ee/app/services/audit_events/build_service.rb + ], + allow: { + patterns: %w[ + /ee/app/services/audit_events/* + ] + } + } } } ) end it 'expands the allow and deny list with keywords and patterns' do - subject.load_definitions.each do |section, group_defintions| - group_defintions.each do |group, definitions| - expect(definitions[:allow]).to be_an(Array) - expect(definitions[:deny]).to be_an(Array) - end + group_defintions = subject.load_definitions[:'[Authentication and Authorization]'] + + group_defintions.each do |group, definitions| + expect(definitions[:allow]).to be_an(Array) + expect(definitions[:deny]).to be_an(Array) end end - it 'expands the auth group' do + it 'expands the patterns for the auth group' do auth = subject.load_definitions.dig( :'[Authentication and Authorization]', :'@gitlab-org/manage/authentication-and-authorization') @@ -95,6 +111,21 @@ RSpec.describe Tooling::FindCodeowners do ] ) end + + it 'retains the array and expands the patterns for the compliance group' do + compliance = subject.load_definitions.dig( + :'[Compliance]', + :'@gitlab-org/manage/compliance') + + expect(compliance).to eq( + entries: %w[ + /ee/app/services/audit_events/build_service.rb + ], + allow: %w[ + /ee/app/services/audit_events/* + ] + ) + end end describe '#load_config' do diff --git a/tooling/config/CODEOWNERS.yml b/tooling/config/CODEOWNERS.yml index 18f3abfc97b..9a3a7e8e5be 100644 --- a/tooling/config/CODEOWNERS.yml +++ b/tooling/config/CODEOWNERS.yml @@ -55,3 +55,24 @@ - '/lib/gitlab/conan_token.rb' patterns: - '%{keyword}' + +'[Compliance]': + '@gitlab-org/manage/compliance': + entries: + - '/ee/app/services/audit_events/build_service.rb' + - '/ee/spec/services/audit_events/custom_audit_event_service_spec.rb' + allow: + keywords: + - audit + patterns: + - '**%{keyword}**' + deny: + keywords: + - '*.png' + - '*bundler-audit*' + - '/ee/app/services/audit_events/*' + - '/ee/spec/services/audit_events/*' + - '/ee/spec/services/ci/*' + - '/ee/spec/services/personal_access_tokens/*' + patterns: + - '%{keyword}' diff --git a/tooling/lib/tooling/find_codeowners.rb b/tooling/lib/tooling/find_codeowners.rb index 3b50b33d85c..6a90f86eecc 100644 --- a/tooling/lib/tooling/find_codeowners.rb +++ b/tooling/lib/tooling/find_codeowners.rb @@ -9,37 +9,10 @@ module Tooling puts section group_defintions.each do |group, list| - matched_files = git_ls_files.each_line.select do |line| - list[:allow].find do |pattern| - path = "/#{line.chomp}" + print_entries(group, list[:entries]) if list[:entries] + print_expanded_entries(group, list) if list[:allow] - path_matches?(pattern, path) && - list[:deny].none? { |pattern| path_matches?(pattern, path) } - end - end - - consolidated = consolidate_paths(matched_files) - consolidated_again = consolidate_paths(consolidated) - - # Consider the directory structure is a tree structure: - # https://en.wikipedia.org/wiki/Tree_(data_structure) - # After we consolidated the leaf entries, it could be possible that - # we can consolidate further for the new leaves. Repeat this - # process until we see no improvements. - while consolidated_again.size < consolidated.size - consolidated = consolidated_again - consolidated_again = consolidate_paths(consolidated) - end - - consolidated.each do |line| - path = line.chomp - - if File.directory?(path) - puts "/#{path}/ #{group}" - else - puts "/#{path} #{group}" - end - end + puts end end end @@ -50,10 +23,20 @@ module Tooling result.each do |section, group_defintions| group_defintions.each do |group, definitions| definitions.transform_values! do |rules| - rules[:keywords].flat_map do |keyword| - rules[:patterns].map do |pattern| - pattern % { keyword: keyword } + case rules + when Hash + case rules[:keywords] + when Array + rules[:keywords].flat_map do |keyword| + rules[:patterns].map do |pattern| + pattern % { keyword: keyword } + end + end + else + rules[:patterns] end + when Array + rules end end end @@ -118,6 +101,49 @@ module Tooling private + def print_entries(group, entries) + entries.each do |entry| + puts "#{entry} #{group}" + end + end + + def print_expanded_entries(group, list) + matched_files = git_ls_files.each_line.select do |line| + list[:allow].find do |pattern| + path = "/#{line.chomp}" + + path_matches?(pattern, path) && + ( + list[:deny].nil? || + list[:deny].none? { |pattern| path_matches?(pattern, path) } + ) + end + end + + consolidated = consolidate_paths(matched_files) + consolidated_again = consolidate_paths(consolidated) + + # Consider the directory structure is a tree structure: + # https://en.wikipedia.org/wiki/Tree_(data_structure) + # After we consolidated the leaf entries, it could be possible that + # we can consolidate further for the new leaves. Repeat this + # process until we see no improvements. + while consolidated_again.size < consolidated.size + consolidated = consolidated_again + consolidated_again = consolidate_paths(consolidated) + end + + consolidated.each do |line| + path = line.chomp + + if File.directory?(path) + puts "/#{path}/ #{group}" + else + puts "/#{path} #{group}" + end + end + end + def find_dir_maxdepth_1(dir) `find #{dir} -maxdepth 1` end