From 5f8b5e3463d518395aeccc55dff20ae16f59b42c Mon Sep 17 00:00:00 2001
From: Luke Duncalfe <lduncalfe@gitlab.com>
Date: Thu, 16 Jun 2022 04:42:04 +0000
Subject: [PATCH] Update docs milestone description for alpha

`alpha` deprecations were added in
https://gitlab.com/gitlab-org/gitlab/-/merge_requests/84756 as a hackish
way to denote an alpha field in GraphQL.

This change updates the generated docs to no longer say:
"Deprecated in <milestone>" for these kinds of deprecations.

Partly https://gitlab.com/gitlab-org/gitlab/-/issues/336383

Changelog: changed
---
 doc/api/graphql/reference/index.md            | 38 +++++++++----------
 doc/development/api_graphql_styleguide.md     | 33 ++++++++++++++--
 lib/gitlab/graphql/deprecation.rb             | 28 ++++++++++----
 ...tlab_style_deprecations_shared_examples.rb |  8 ++--
 4 files changed, 74 insertions(+), 33 deletions(-)

diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md
index 1da6beaee9a5c..15cf2f4d6c0d9 100644
--- a/doc/api/graphql/reference/index.md
+++ b/doc/api/graphql/reference/index.md
@@ -559,8 +559,8 @@ Returns [`Vulnerability`](#vulnerability).
 Find a work item. Returns `null` if `work_items` feature flag is disabled.
 
 WARNING:
-**Deprecated** in 15.1.
-This feature is in Alpha, and can be removed or changed at any point.
+**Introduced** in 15.1.
+This feature is in Alpha. It can be changed or removed at any time.
 
 Returns [`WorkItem`](#workitem).
 
@@ -5413,8 +5413,8 @@ Input type: `VulnerabilityRevertToDetectedInput`
 Creates a work item. Available only when feature flag `work_items` is enabled.
 
 WARNING:
-**Deprecated** in 15.1.
-This feature is in Alpha, and can be removed or changed at any point.
+**Introduced** in 15.1.
+This feature is in Alpha. It can be changed or removed at any time.
 
 Input type: `WorkItemCreateInput`
 
@@ -5441,8 +5441,8 @@ Input type: `WorkItemCreateInput`
 Creates a work item from a task in another work item's description. Available only when feature flag `work_items` is enabled.
 
 WARNING:
-**Deprecated** in 15.1.
-This feature is in Alpha, and can be removed or changed at any point.
+**Introduced** in 15.1.
+This feature is in Alpha. It can be changed or removed at any time.
 
 Input type: `WorkItemCreateFromTaskInput`
 
@@ -5468,8 +5468,8 @@ Input type: `WorkItemCreateFromTaskInput`
 Deletes a work item. Available only when feature flag `work_items` is enabled.
 
 WARNING:
-**Deprecated** in 15.1.
-This feature is in Alpha, and can be removed or changed at any point.
+**Introduced** in 15.1.
+This feature is in Alpha. It can be changed or removed at any time.
 
 Input type: `WorkItemDeleteInput`
 
@@ -5493,8 +5493,8 @@ Input type: `WorkItemDeleteInput`
 Deletes a task in a work item's description. Available only when feature flag `work_items` is enabled.
 
 WARNING:
-**Deprecated** in 15.1.
-This feature is in Alpha, and can be removed or changed at any point.
+**Introduced** in 15.1.
+This feature is in Alpha. It can be changed or removed at any time.
 
 Input type: `WorkItemDeleteTaskInput`
 
@@ -5520,8 +5520,8 @@ Input type: `WorkItemDeleteTaskInput`
 Updates a work item by Global ID. Available only when feature flag `work_items` is enabled.
 
 WARNING:
-**Deprecated** in 15.1.
-This feature is in Alpha, and can be removed or changed at any point.
+**Introduced** in 15.1.
+This feature is in Alpha. It can be changed or removed at any time.
 
 Input type: `WorkItemUpdateInput`
 
@@ -5547,8 +5547,8 @@ Input type: `WorkItemUpdateInput`
 Updates a work item's task by Global ID. Available only when feature flag `work_items` is enabled.
 
 WARNING:
-**Deprecated** in 15.1.
-This feature is in Alpha, and can be removed or changed at any point.
+**Introduced** in 15.1.
+This feature is in Alpha. It can be changed or removed at any time.
 
 Input type: `WorkItemUpdateTaskInput`
 
@@ -5574,8 +5574,8 @@ Input type: `WorkItemUpdateTaskInput`
 Updates the attributes of a work item's widgets by global ID. Available only when feature flag `work_items` is enabled.
 
 WARNING:
-**Deprecated** in 15.1.
-This feature is in Alpha, and can be removed or changed at any point.
+**Introduced** in 15.1.
+This feature is in Alpha. It can be changed or removed at any time.
 
 Input type: `WorkItemUpdateWidgetsInput`
 
@@ -9806,7 +9806,7 @@ Represents the total number of issues and their weights for a particular day.
 | <a id="cirunnershortsha"></a>`shortSha` | [`String`](#string) | First eight characters of the runner's token used to authenticate new job requests. Used as the runner's unique ID. |
 | <a id="cirunnertaglist"></a>`tagList` | [`[String!]`](#string) | Tags associated with the runner. |
 | <a id="cirunnertokenexpiresat"></a>`tokenExpiresAt` | [`Time`](#time) | Runner token expiration time. |
-| <a id="cirunnerupgradestatus"></a>`upgradeStatus` **{warning-solid}** | [`CiRunnerUpgradeStatusType`](#cirunnerupgradestatustype) | **Deprecated** in 14.10. This feature is in Alpha, and can be removed or changed at any point. |
+| <a id="cirunnerupgradestatus"></a>`upgradeStatus` **{warning-solid}** | [`CiRunnerUpgradeStatusType`](#cirunnerupgradestatustype) | **Introduced** in 14.10. This feature is in Alpha. It can be changed or removed at any time. |
 | <a id="cirunneruserpermissions"></a>`userPermissions` | [`RunnerPermissions!`](#runnerpermissions) | Permissions for the current user on the resource. |
 | <a id="cirunnerversion"></a>`version` | [`String`](#string) | Version of the runner. |
 
@@ -15894,8 +15894,8 @@ four standard [pagination arguments](#connection-pagination-arguments):
 Work items of the project.
 
 WARNING:
-**Deprecated** in 15.1.
-This feature is in Alpha, and can be removed or changed at any point.
+**Introduced** in 15.1.
+This feature is in Alpha. It can be changed or removed at any time.
 
 Returns [`WorkItemConnection`](#workitemconnection).
 
diff --git a/doc/development/api_graphql_styleguide.md b/doc/development/api_graphql_styleguide.md
index 1660d3d149354..0ad80508bb9e4 100644
--- a/doc/development/api_graphql_styleguide.md
+++ b/doc/development/api_graphql_styleguide.md
@@ -94,11 +94,16 @@ discussed in [Nullable fields](#nullable-fields).
 - Lowering the global limits for query complexity and depth.
 - Anything else that can result in queries hitting a limit that previously was allowed.
 
-Fields that use the [`feature_flag` property](#feature_flag-property) and the flag is disabled by default are exempt
-from the deprecation process, and can be removed at any time without notice.
-
 See the [deprecating schema items](#deprecating-schema-items) section for how to deprecate items.
 
+### Breaking change exemptions
+
+Two scenarios exist where schema items are exempt from the deprecation process,
+and can be removed or changed at any time without notice. These are schema items that either:
+
+- Use the [`feature_flag` property](#feature_flag-property) _and_ the flag is disabled by default.
+- Are [marked as alpha](#marking-schema-items-as-alpha).
+
 ## Global IDs
 
 The GitLab GraphQL API uses Global IDs (i.e: `"gid://gitlab/MyObject/123"`)
@@ -718,6 +723,28 @@ aware of the support.
 
 The documentation will mention that the old Global ID style is now deprecated.
 
+## Marking schema items as Alpha
+
+Fields, arguments, enum values, and mutations can be marked as being in
+[alpha](https://about.gitlab.com/handbook/product/gitlab-the-product/#alpha-beta-ga).
+
+An item marked as "alpha" is exempt from the deprecation process and can be removed
+at any time without notice.
+
+This leverages GraphQL deprecations to cause the schema item to appear as deprecated,
+and will be described as being in "alpha" in our generated docs and its GraphQL description.
+
+To mark a schema item as being in "alpha", use the `deprecated:` keyword with `reason: :alpha`.
+You must provide the `milestone:` that introduced the alpha item.
+
+For example:
+
+```ruby
+field :token, GraphQL::Types::String, null: true,
+      deprecated: { reason: :alpha, milestone: '10.0' },
+      description: 'Token for login.'
+```
+
 ## Enums
 
 GitLab GraphQL enums are defined in `app/graphql/types`. When defining new enums, the
diff --git a/lib/gitlab/graphql/deprecation.rb b/lib/gitlab/graphql/deprecation.rb
index 3335e5117145b..d30751fe46ecd 100644
--- a/lib/gitlab/graphql/deprecation.rb
+++ b/lib/gitlab/graphql/deprecation.rb
@@ -3,9 +3,12 @@
 module Gitlab
   module Graphql
     class Deprecation
+      REASON_RENAMED = :renamed
+      REASON_ALPHA = :alpha
+
       REASONS = {
-        renamed: 'This was renamed.',
-        alpha: 'This feature is in Alpha, and can be removed or changed at any point.'
+        REASON_RENAMED => 'This was renamed.',
+        REASON_ALPHA => 'This feature is in Alpha. It can be changed or removed at any time.'
       }.freeze
 
       include ActiveModel::Validations
@@ -39,7 +42,7 @@ def ==(other)
 
       def markdown(context: :inline)
         parts = [
-          "#{deprecated_in(format: :markdown)}.",
+          "#{changed_in_milestone(format: :markdown)}.",
           reason_text,
           replacement_markdown.then { |r| "Use: #{r}." if r }
         ].compact
@@ -77,7 +80,7 @@ def deprecation_reason
         [
           reason_text,
           replacement && "Please use `#{replacement}`.",
-          "#{deprecated_in}."
+          "#{changed_in_milestone}."
         ].compact.join(' ')
       end
 
@@ -107,15 +110,24 @@ def reason_text
       end
 
       def description_suffix
-        " #{deprecated_in}: #{reason_text}"
+        " #{changed_in_milestone}: #{reason_text}"
       end
 
-      def deprecated_in(format: :plain)
+      # Returns 'Deprecated in <milestone>' for proper deprecations.
+      # Retruns 'Introduced in <milestone>' for :alpha deprecations.
+      # Formatted to markdown or plain format.
+      def changed_in_milestone(format: :plain)
+        verb = if reason == REASON_ALPHA
+                 'Introduced'
+               else
+                 'Deprecated'
+               end
+
         case format
         when :plain
-          "Deprecated in #{milestone}"
+          "#{verb} in #{milestone}"
         when :markdown
-          "**Deprecated** in #{milestone}"
+          "**#{verb}** in #{milestone}"
         end
       end
     end
diff --git a/spec/support/shared_examples/graphql/types/gitlab_style_deprecations_shared_examples.rb b/spec/support/shared_examples/graphql/types/gitlab_style_deprecations_shared_examples.rb
index cf9c36fafe8b4..7fd54408b1192 100644
--- a/spec/support/shared_examples/graphql/types/gitlab_style_deprecations_shared_examples.rb
+++ b/spec/support/shared_examples/graphql/types/gitlab_style_deprecations_shared_examples.rb
@@ -53,18 +53,20 @@
   it 'adds information about the replacement if provided' do
     deprecable = subject(deprecated: { milestone: '1.10', reason: :renamed, replacement: 'Foo.bar' })
 
-    expect(deprecable.deprecation_reason).to include 'Please use `Foo.bar`'
+    expect(deprecable.deprecation_reason).to include('Please use `Foo.bar`')
   end
 
   it 'supports named reasons: renamed' do
     deprecable = subject(deprecated: { milestone: '1.10', reason: :renamed })
 
-    expect(deprecable.deprecation_reason).to include 'This was renamed.'
+    expect(deprecable.deprecation_reason).to eq('This was renamed. Deprecated in 1.10.')
   end
 
   it 'supports named reasons: alpha' do
     deprecable = subject(deprecated: { milestone: '1.10', reason: :alpha })
 
-    expect(deprecable.deprecation_reason).to include 'This feature is in Alpha'
+    expect(deprecable.deprecation_reason).to eq(
+      'This feature is in Alpha. It can be changed or removed at any time. Introduced in 1.10.'
+    )
   end
 end
-- 
GitLab