From 0c964b70dfed5ebd644a940f542a1c7b7ec8bccc Mon Sep 17 00:00:00 2001
From: Luke Duncalfe <lduncalfe@gitlab.com>
Date: Thu, 18 Aug 2022 05:56:52 +0000
Subject: [PATCH] Add GraphQL custom emoji schema, flagged

This change exposes GraphQL schema that was previously hidden by default
so has a Changelog.

The old `feature_flag` is deprecated and should be replaced with a
flag that toggles the value of fields and behaviour of mutations.

This also adds `alpha` as the flag is disabled by default.

https://gitlab.com/gitlab-org/gitlab/-/issues/369202

Changelog: added
---
 app/graphql/mutations/custom_emoji/create.rb       |  4 ++++
 app/graphql/mutations/custom_emoji/destroy.rb      |  4 ++++
 app/graphql/types/group_type.rb                    |  6 +++++-
 app/graphql/types/mutation_type.rb                 |  4 ++--
 doc/api/graphql/reference/index.md                 | 10 +++++++---
 .../api/graphql/custom_emoji_query_spec.rb         | 12 +++++++++++-
 .../graphql/mutations/custom_emoji/create_spec.rb  | 14 ++++++++++++++
 .../graphql/mutations/custom_emoji/destroy_spec.rb | 14 ++++++++++++++
 8 files changed, 61 insertions(+), 7 deletions(-)

diff --git a/app/graphql/mutations/custom_emoji/create.rb b/app/graphql/mutations/custom_emoji/create.rb
index 269ea6c999981..535ff44a7fd2d 100644
--- a/app/graphql/mutations/custom_emoji/create.rb
+++ b/app/graphql/mutations/custom_emoji/create.rb
@@ -28,6 +28,10 @@ class Create < BaseMutation
                description: 'Location of the emoji file.'
 
       def resolve(group_path:, **args)
+        if Feature.disabled?(:custom_emoji)
+          raise Gitlab::Graphql::Errors::ResourceNotAvailable, 'Custom emoji feature is disabled'
+        end
+
         group = authorized_find!(group_path: group_path)
         # See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/37911#note_444682238
         args[:external] = true
diff --git a/app/graphql/mutations/custom_emoji/destroy.rb b/app/graphql/mutations/custom_emoji/destroy.rb
index 863b8152cc7f3..64e3f2ed7d3cd 100644
--- a/app/graphql/mutations/custom_emoji/destroy.rb
+++ b/app/graphql/mutations/custom_emoji/destroy.rb
@@ -17,6 +17,10 @@ class Destroy < BaseMutation
                description: 'Global ID of the custom emoji to destroy.'
 
       def resolve(id:)
+        if Feature.disabled?(:custom_emoji)
+          raise Gitlab::Graphql::Errors::ResourceNotAvailable, 'Custom emoji feature is disabled'
+        end
+
         custom_emoji = authorized_find!(id: id)
 
         custom_emoji.destroy!
diff --git a/app/graphql/types/group_type.rb b/app/graphql/types/group_type.rb
index 3a7507b038f89..8542e611f0275 100644
--- a/app/graphql/types/group_type.rb
+++ b/app/graphql/types/group_type.rb
@@ -22,7 +22,7 @@ class GroupType < NamespaceType
           type: Types::CustomEmojiType.connection_type,
           null: true,
           description: 'Custom emoji within this namespace.',
-          _deprecated_feature_flag: :custom_emoji
+          alpha: { milestone: '13.6' }
 
     field :share_with_group_lock,
           type: GraphQL::Types::Boolean,
@@ -278,6 +278,10 @@ def dependency_proxy_setting
       group.dependency_proxy_setting || group.create_dependency_proxy_setting
     end
 
+    def custom_emoji
+      object.custom_emoji if Feature.enabled?(:custom_emoji)
+    end
+
     private
 
     def group
diff --git a/app/graphql/types/mutation_type.rb b/app/graphql/types/mutation_type.rb
index 499c2e786bf4c..e1806e5b19acc 100644
--- a/app/graphql/types/mutation_type.rb
+++ b/app/graphql/types/mutation_type.rb
@@ -37,8 +37,8 @@ class MutationType < BaseObject
     mount_mutation Mutations::Clusters::AgentTokens::Create
     mount_mutation Mutations::Clusters::AgentTokens::Revoke
     mount_mutation Mutations::Commits::Create, calls_gitaly: true
-    mount_mutation Mutations::CustomEmoji::Create, _deprecated_feature_flag: :custom_emoji
-    mount_mutation Mutations::CustomEmoji::Destroy, _deprecated_feature_flag: :custom_emoji
+    mount_mutation Mutations::CustomEmoji::Create, alpha: { milestone: '13.6' }
+    mount_mutation Mutations::CustomEmoji::Destroy, alpha: { milestone: '13.6' }
     mount_mutation Mutations::CustomerRelations::Contacts::Create
     mount_mutation Mutations::CustomerRelations::Contacts::Update
     mount_mutation Mutations::CustomerRelations::Organizations::Create
diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md
index a0c228a69448b..3a2aa1bde9287 100644
--- a/doc/api/graphql/reference/index.md
+++ b/doc/api/graphql/reference/index.md
@@ -1409,7 +1409,9 @@ Input type: `CreateComplianceFrameworkInput`
 
 ### `Mutation.createCustomEmoji`
 
-Available only when feature flag `custom_emoji` is enabled. This flag is disabled by default, because the feature is experimental and is subject to change without notice.
+WARNING:
+**Introduced** in 13.6.
+This feature is in Alpha. It can be changed or removed at any time.
 
 Input type: `CreateCustomEmojiInput`
 
@@ -2271,7 +2273,9 @@ Input type: `DestroyContainerRepositoryTagsInput`
 
 ### `Mutation.destroyCustomEmoji`
 
-Available only when feature flag `custom_emoji` is enabled. This flag is disabled by default, because the feature is experimental and is subject to change without notice.
+WARNING:
+**Introduced** in 13.6.
+This feature is in Alpha. It can be changed or removed at any time.
 
 Input type: `DestroyCustomEmojiInput`
 
@@ -12144,7 +12148,7 @@ four standard [pagination arguments](#connection-pagination-arguments):
 | <a id="groupcontainerrepositoriescount"></a>`containerRepositoriesCount` | [`Int!`](#int) | Number of container repositories in the group. |
 | <a id="groupcontainslockedprojects"></a>`containsLockedProjects` | [`Boolean!`](#boolean) | Includes at least one project where the repository size exceeds the limit. |
 | <a id="groupcrossprojectpipelineavailable"></a>`crossProjectPipelineAvailable` | [`Boolean!`](#boolean) | Indicates if the cross_project_pipeline feature is available for the namespace. |
-| <a id="groupcustomemoji"></a>`customEmoji` | [`CustomEmojiConnection`](#customemojiconnection) | Custom emoji within this namespace. Available only when feature flag `custom_emoji` is enabled. This flag is disabled by default, because the feature is experimental and is subject to change without notice. (see [Connections](#connections)) |
+| <a id="groupcustomemoji"></a>`customEmoji` **{warning-solid}** | [`CustomEmojiConnection`](#customemojiconnection) | **Introduced** in 13.6. This feature is in Alpha. It can be changed or removed at any time. Custom emoji within this namespace. |
 | <a id="groupdependencyproxyblobcount"></a>`dependencyProxyBlobCount` | [`Int!`](#int) | Number of dependency proxy blobs cached in the group. |
 | <a id="groupdependencyproxyblobs"></a>`dependencyProxyBlobs` | [`DependencyProxyBlobConnection`](#dependencyproxyblobconnection) | Dependency Proxy blobs. (see [Connections](#connections)) |
 | <a id="groupdependencyproxyimagecount"></a>`dependencyProxyImageCount` | [`Int!`](#int) | Number of dependency proxy images cached in the group. |
diff --git a/spec/requests/api/graphql/custom_emoji_query_spec.rb b/spec/requests/api/graphql/custom_emoji_query_spec.rb
index 13b7a22e791ca..5dd5ad117b00e 100644
--- a/spec/requests/api/graphql/custom_emoji_query_spec.rb
+++ b/spec/requests/api/graphql/custom_emoji_query_spec.rb
@@ -35,7 +35,17 @@ def custom_emoji_query(group)
       expect(graphql_data['group']['customEmoji']['nodes'].first['name']).to eq(custom_emoji.name)
     end
 
-    it 'returns nil when unauthorised' do
+    it 'returns nil custom emoji when the custom_emoji feature flag is disabled' do
+      stub_feature_flags(custom_emoji: false)
+
+      post_graphql(custom_emoji_query(group), current_user: current_user)
+
+      expect(response).to have_gitlab_http_status(:ok)
+      expect(graphql_data['group']).to be_present
+      expect(graphql_data['group']['customEmoji']).to be_nil
+    end
+
+    it 'returns nil group when unauthorised' do
       user = create(:user)
       post_graphql(custom_emoji_query(group), current_user: user)
 
diff --git a/spec/requests/api/graphql/mutations/custom_emoji/create_spec.rb b/spec/requests/api/graphql/mutations/custom_emoji/create_spec.rb
index c91437fa35576..66facdebe7885 100644
--- a/spec/requests/api/graphql/mutations/custom_emoji/create_spec.rb
+++ b/spec/requests/api/graphql/mutations/custom_emoji/create_spec.rb
@@ -39,5 +39,19 @@
       expect(gql_response['customEmoji']['name']).to eq(attributes[:name])
       expect(gql_response['customEmoji']['url']).to eq(attributes[:url])
     end
+
+    context 'when the custom_emoji feature flag is disabled' do
+      before do
+        stub_feature_flags(custom_emoji: false)
+      end
+
+      it 'does nothing and returns and error' do
+        expect do
+          post_graphql_mutation(mutation, current_user: current_user)
+        end.to not_change(CustomEmoji, :count)
+
+        expect_graphql_errors_to_include('Custom emoji feature is disabled')
+      end
+    end
   end
 end
diff --git a/spec/requests/api/graphql/mutations/custom_emoji/destroy_spec.rb b/spec/requests/api/graphql/mutations/custom_emoji/destroy_spec.rb
index 07fd57a2cee6d..7d25206e61714 100644
--- a/spec/requests/api/graphql/mutations/custom_emoji/destroy_spec.rb
+++ b/spec/requests/api/graphql/mutations/custom_emoji/destroy_spec.rb
@@ -68,6 +68,20 @@
       end
 
       it_behaves_like 'deletes custom emoji'
+
+      context 'when the custom_emoji feature flag is disabled' do
+        before do
+          stub_feature_flags(custom_emoji: false)
+        end
+
+        it_behaves_like 'does not delete custom emoji'
+
+        it 'returns an error' do
+          post_graphql_mutation(mutation, current_user: current_user)
+
+          expect_graphql_errors_to_include('Custom emoji feature is disabled')
+        end
+      end
     end
   end
 end
-- 
GitLab