diff --git a/app/models/concerns/project_features_compatibility.rb b/app/models/concerns/project_features_compatibility.rb index b910c0ab5c2a312bae42c1d411828e5437214cb5..76c733b1c0bdc74b6d9e8b5399dfa8c9925a22f8 100644 --- a/app/models/concerns/project_features_compatibility.rb +++ b/app/models/concerns/project_features_compatibility.rb @@ -114,6 +114,10 @@ def infrastructure_access_level=(value) write_feature_attribute_string(:infrastructure_access_level, value) end + def model_experiments_access_level=(value) + write_feature_attribute_string(:model_experiments_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 ef87b611fca6d32dcf9c18dead4be899ca42e254..c749388d79e09e47d8a21b14ac74cdff9c24cfcb 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -491,6 +491,7 @@ def self.integration_association_name(name) :operations_access_level, :security_and_compliance_access_level, :container_registry_access_level, :environments_access_level, :feature_flags_access_level, :monitor_access_level, :releases_access_level, :infrastructure_access_level, + :model_experiments_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 772a82fa173c8306b2c98e40576a4462597e2dec..3c533b4a60d3172c786969f7ffec3a6151b74c5d 100644 --- a/app/models/project_feature.rb +++ b/app/models/project_feature.rb @@ -26,6 +26,7 @@ class ProjectFeature < ApplicationRecord feature_flags releases infrastructure + model_experiments ].freeze EXPORTABLE_FEATURES = (FEATURES - [:security_and_compliance, :pages]).freeze @@ -79,6 +80,7 @@ def required_minimum_access_level_for_private_project(feature) attribute :infrastructure_access_level, default: ENABLED attribute :feature_flags_access_level, default: ENABLED attribute :environments_access_level, default: ENABLED + attribute :model_experiments_access_level, default: ENABLED attribute :package_registry_access_level, default: -> do if ::Gitlab.config.packages.enabled diff --git a/db/migrate/20230522132239_add_model_experiments_access_level_to_project_feature.rb b/db/migrate/20230522132239_add_model_experiments_access_level_to_project_feature.rb new file mode 100644 index 0000000000000000000000000000000000000000..a34b8a15521c0f3794453493d61f087960c1b34b --- /dev/null +++ b/db/migrate/20230522132239_add_model_experiments_access_level_to_project_feature.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +class AddModelExperimentsAccessLevelToProjectFeature < Gitlab::Database::Migration[2.1] + OPERATIONS_DEFAULT_VALUE = 20 + + enable_lock_retries! + + def change + add_column :project_features, + :model_experiments_access_level, + :integer, + null: false, + default: OPERATIONS_DEFAULT_VALUE + end +end diff --git a/db/schema_migrations/20230522132239 b/db/schema_migrations/20230522132239 new file mode 100644 index 0000000000000000000000000000000000000000..365eb1606cb4552a8335da5023b3eda92a25b01d --- /dev/null +++ b/db/schema_migrations/20230522132239 @@ -0,0 +1 @@ +7cda2cca39c53859e84bb7ecf3a2a9817f598486632a3cdd922dde6057b5c930 \ No newline at end of file diff --git a/db/structure.sql b/db/structure.sql index 99a76247e01b1550677a76e9993c2f8a92a03aad..084c266ce134c16661c1d35c57d3d5e9beff2644 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -20899,7 +20899,8 @@ CREATE TABLE project_features ( infrastructure_access_level integer DEFAULT 20 NOT NULL, feature_flags_access_level integer DEFAULT 20 NOT NULL, environments_access_level integer DEFAULT 20 NOT NULL, - releases_access_level integer DEFAULT 20 NOT NULL + releases_access_level integer DEFAULT 20 NOT NULL, + model_experiments_access_level integer DEFAULT 20 NOT NULL ); CREATE SEQUENCE project_features_id_seq diff --git a/ee/config/audit_events/types/project_feature_model_experiments_access_level_updated.yml b/ee/config/audit_events/types/project_feature_model_experiments_access_level_updated.yml new file mode 100644 index 0000000000000000000000000000000000000000..c521a6c92a7155e9b4fa6a67c327efd1c972a95e --- /dev/null +++ b/ee/config/audit_events/types/project_feature_model_experiments_access_level_updated.yml @@ -0,0 +1,9 @@ +--- +name: project_feature_model_experiments_access_level_updated +description: Model experiments access level was updated +introduced_by_issue: https://gitlab.com/gitlab-org/gitlab/-/issues/412384 +introduced_by_mr: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/121027 +feature_category: mlops +milestone: '16.1' +saved_to_database: true +streamed: true diff --git a/ee/lib/audit/project_feature_changes_auditor.rb b/ee/lib/audit/project_feature_changes_auditor.rb index 310abd42d80e7505b24053870843687f9ac4864a..4a2ce47154056219a13e1ac511086f8cfddb1236 100644 --- a/ee/lib/audit/project_feature_changes_auditor.rb +++ b/ee/lib/audit/project_feature_changes_auditor.rb @@ -24,7 +24,8 @@ class ProjectFeatureChangesAuditor < BaseChangesAuditor infrastructure_access_level: 'project_feature_infrastructure_access_level_updated', feature_flags_access_level: 'project_feature_feature_flags_access_level_updated', environments_access_level: 'project_feature_environments_access_level_updated', - releases_access_level: 'project_feature_releases_access_level_updated' + releases_access_level: 'project_feature_releases_access_level_updated', + model_experiments_access_level: 'project_feature_model_experiments_access_level_updated' }.freeze def initialize(current_user, model, project) diff --git a/lib/gitlab/import_export/project/import_export.yml b/lib/gitlab/import_export/project/import_export.yml index 56cbc5f1bb4adc0a41f8a933b9e20670a3a82e2c..410e918649baefeded12bd2dbcffba39086a7ad2 100644 --- a/lib/gitlab/import_export/project/import_export.yml +++ b/lib/gitlab/import_export/project/import_export.yml @@ -321,6 +321,7 @@ included_attributes: - :feature_flags_access_level - :releases_access_level - :infrastructure_access_level + - :model_experiments_access_level prometheus_metrics: - :created_at - :updated_at @@ -741,6 +742,7 @@ included_attributes: - :feature_flags_access_level - :releases_access_level - :infrastructure_access_level + - :model_experiments_access_level - :auto_devops_deploy_strategy - :auto_devops_enabled - :container_registry_enabled diff --git a/rubocop/cop/gitlab/feature_available_usage.rb b/rubocop/cop/gitlab/feature_available_usage.rb index df4409c27e051a5e18f4f7ff5148f52cee565bb6..cbfb89d3053c5ee794714d4ada32f8887707023c 100644 --- a/rubocop/cop/gitlab/feature_available_usage.rb +++ b/rubocop/cop/gitlab/feature_available_usage.rb @@ -28,6 +28,7 @@ class FeatureAvailableUsage < RuboCop::Cop::Base feature_flags releases infrastructure + model_experiments ].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 1b485e47127a516353da483c261ad9e2e60042ea..6e3e119ddabae9b0a845247d39e7b54217f32c45 100644 --- a/spec/factories/projects.rb +++ b/spec/factories/projects.rb @@ -42,6 +42,7 @@ feature_flags_access_level { ProjectFeature::ENABLED } releases_access_level { ProjectFeature::ENABLED } infrastructure_access_level { ProjectFeature::ENABLED } + model_experiments_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/lib/gitlab/import_export/safe_model_attributes.yml b/spec/lib/gitlab/import_export/safe_model_attributes.yml index 9e5b5ccd64a176af29f064f05c79df29f4619baa..abdd874137788fc5c7016a6ea7d31b80d0eb1323 100644 --- a/spec/lib/gitlab/import_export/safe_model_attributes.yml +++ b/spec/lib/gitlab/import_export/safe_model_attributes.yml @@ -704,6 +704,7 @@ ProjectFeature: - releases_access_level - monitor_access_level - infrastructure_access_level +- model_experiments_access_level - created_at - updated_at ProtectedBranch::MergeAccessLevel: diff --git a/spec/models/project_feature_spec.rb b/spec/models/project_feature_spec.rb index 8dd1f7b1831afd5fcc5e87a2cae0cd39866cf8a3..48c9567ebb3d0c4e9c4a8f6bc6976c25b2c1618e 100644 --- a/spec/models/project_feature_spec.rb +++ b/spec/models/project_feature_spec.rb @@ -30,6 +30,7 @@ specify { expect(subject.releases_access_level).to eq(ProjectFeature::ENABLED) } specify { expect(subject.package_registry_access_level).to eq(ProjectFeature::ENABLED) } specify { expect(subject.container_registry_access_level).to eq(ProjectFeature::ENABLED) } + specify { expect(subject.model_experiments_access_level).to eq(ProjectFeature::ENABLED) } end describe 'PRIVATE_FEATURES_MIN_ACCESS_LEVEL_FOR_PRIVATE_PROJECT' do diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index 6cf7c16124f2bf7d545733edcbe89d8c4e2f7d93..bb9981dd5aa43d557ff1866fefcfef411799b77f 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -1057,6 +1057,7 @@ 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) } + it { is_expected.to delegate_method(:model_experiments_access_level).to(:project_feature) } it { is_expected.to delegate_method(:feature_flags_access_level).to(:project_feature) } it { is_expected.to delegate_method(:releases_access_level).to(:project_feature) } it { is_expected.to delegate_method(:infrastructure_access_level).to(:project_feature) } diff --git a/spec/requests/api/project_attributes.yml b/spec/requests/api/project_attributes.yml index bf233ed59299567bd538277f1878559a86be832e..e0e9c944fe49884f5896c1e32d69a7e1cb73cb36 100644 --- a/spec/requests/api/project_attributes.yml +++ b/spec/requests/api/project_attributes.yml @@ -127,6 +127,7 @@ project_feature: - project_id - updated_at - operations_access_level + - model_experiments_access_level computed_attributes: - issues_enabled - jobs_enabled