diff --git a/.rubocop_todo/gitlab/feature_flag_key_dynamic.yml b/.rubocop_todo/gitlab/feature_flag_key_dynamic.yml index 15526de6320..b5285c6b6ba 100644 --- a/.rubocop_todo/gitlab/feature_flag_key_dynamic.yml +++ b/.rubocop_todo/gitlab/feature_flag_key_dynamic.yml @@ -32,7 +32,6 @@ Gitlab/FeatureFlagKeyDynamic: - 'lib/gitlab/redis/multi_store.rb' - 'lib/gitlab/sidekiq_middleware/skip_jobs.rb' - 'lib/gitlab/sidekiq_sharding/router.rb' - - 'lib/gitlab/tracking/event_eligibility_checker.rb' - 'lib/web_ide/extension_marketplace.rb' - 'spec/lib/feature_spec.rb' - 'spec/requests/api/features_spec.rb' diff --git a/app/assets/javascripts/packages_and_registries/settings/project/components/container_protection_tag_rule_form.vue b/app/assets/javascripts/packages_and_registries/settings/project/components/container_protection_tag_rule_form.vue index 8adfb34d210..aa064fb9617 100644 --- a/app/assets/javascripts/packages_and_registries/settings/project/components/container_protection_tag_rule_form.vue +++ b/app/assets/javascripts/packages_and_registries/settings/project/components/container_protection_tag_rule_form.vue @@ -5,6 +5,7 @@ import { GlFormGroup, GlForm, GlFormInput, + GlFormRadio, GlFormSelect, GlLink, GlSprintf, @@ -16,8 +17,12 @@ import { GRAPHQL_ACCESS_LEVEL_VALUE_MAINTAINER, } from '~/packages_and_registries/settings/project/constants'; import { __, s__ } from '~/locale'; -import { InternalEvents } from '~/tracking'; import * as Sentry from '~/sentry/sentry_browser_wrapper'; +import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; +import glAbilitiesMixin from '~/vue_shared/mixins/gl_abilities_mixin'; + +const PROTECTED_RULE_TYPE = 'protected'; +const IMMUTABLE_RULE_TYPE = 'immutable'; export default { components: { @@ -29,8 +34,9 @@ export default { GlFormSelect, GlLink, GlSprintf, + GlFormRadio, }, - mixins: [InternalEvents.mixin()], + mixins: [glFeatureFlagsMixin(), glAbilitiesMixin()], inject: ['projectPath'], props: { rule: { @@ -49,17 +55,39 @@ export default { minimumAccessLevelForDelete: this.rule?.minimumAccessLevelForDelete ?? GRAPHQL_ACCESS_LEVEL_VALUE_MAINTAINER, }, + tagRuleType: PROTECTED_RULE_TYPE, showValidation: false, updateInProgress: false, }; }, computed: { createProtectionRuleMutationInput() { + if (this.isProtectedTagRuleType) { + return { + projectPath: this.projectPath, + ...this.protectionRuleFormData, + }; + } return { projectPath: this.projectPath, - ...this.protectionRuleFormData, + tagNamePattern: this.protectionRuleFormData.tagNamePattern, }; }, + isFeatureFlagEnabled() { + return this.glFeatures.containerRegistryImmutableTags; + }, + isProtectedTagRuleType() { + return this.tagRuleType === PROTECTED_RULE_TYPE; + }, + canCreateImmutableTagRule() { + return ( + this.isFeatureFlagEnabled && + this.glAbilities.createContainerRegistryProtectionImmutableTagRule + ); + }, + showProtectionType() { + return this.canCreateImmutableTagRule && !this.rule; + }, isTagNamePatternValid() { if (this.showValidation) { return this.tagNamePattern.length > 0 && this.tagNamePattern.length < 100; @@ -81,6 +109,20 @@ export default { tagNamePattern() { return this.protectionRuleFormData.tagNamePattern; }, + tagNamePatternLabel() { + return this.isProtectedTagRuleType + ? s__('ContainerRegistry|Protect container tags matching') + : s__('ContainerRegistry|Apply immutability rule to tags matching'); + }, + tagNamePatternDescription() { + return this.isProtectedTagRuleType + ? s__( + 'ContainerRegistry|Tags with names that match this regex pattern are protected. Must be less than 100 characters. %{linkStart}What regex patterns are supported?%{linkEnd}', + ) + : s__( + 'ContainerRegistry|Tags with names that match this regex pattern are immutable. Must be less than 100 characters. %{linkStart}What regex patterns are supported?%{linkEnd}', + ); + }, submitButtonText() { return this.rule ? __('Save changes') : s__('ContainerRegistry|Add rule'); }, @@ -120,11 +162,6 @@ export default { } this.$emit('submit', data[this.mutationKey].containerProtectionTagRule); - if (this.rule) { - this.trackEvent('container_protection_tag_rule_created'); - } else { - this.trackEvent('container_protection_tag_rule_updated'); - } }) .catch((error) => { this.handleError(error); @@ -153,6 +190,8 @@ export default { } }, }, + PROTECTED_RULE_TYPE, + IMMUTABLE_RULE_TYPE, minimumAccessLevelOptions: MinimumAccessLevelOptions, }; @@ -168,8 +207,37 @@ export default {
{{ error }}
+ +