From 1d17049946ba3bd0b0f04e3559cf7f8540a39759 Mon Sep 17 00:00:00 2001
From: David O'Regan <doregan@gitlab.com>
Date: Fri, 8 Jul 2022 14:54:02 +0000
Subject: [PATCH] Revert "Merge branch '353926' into 'master'"

This reverts merge request !81833
---
 app/models/wiki_page.rb                       |  3 +-
 .../development/wiki_front_matter.yml         |  8 +++
 lib/gitlab/wiki_pages/front_matter_parser.rb  | 18 +++++-
 .../wiki_pages/front_matter_parser_spec.rb    | 29 +++++++++-
 spec/models/wiki_page_spec.rb                 | 57 ++++++++++++++++++-
 5 files changed, 107 insertions(+), 8 deletions(-)
 create mode 100644 config/feature_flags/development/wiki_front_matter.yml

diff --git a/app/models/wiki_page.rb b/app/models/wiki_page.rb
index 647b4e787c6aa5..63c60f5a89ec16 100644
--- a/app/models/wiki_page.rb
+++ b/app/models/wiki_page.rb
@@ -316,6 +316,7 @@ def serialize_front_matter(hash)
   end
 
   def update_front_matter(attrs)
+    return unless Gitlab::WikiPages::FrontMatterParser.enabled?(container)
     return unless attrs.has_key?(:front_matter)
 
     fm_yaml = serialize_front_matter(attrs[:front_matter])
@@ -326,7 +327,7 @@ def update_front_matter(attrs)
 
   def parsed_content
     strong_memoize(:parsed_content) do
-      Gitlab::WikiPages::FrontMatterParser.new(raw_content).parse
+      Gitlab::WikiPages::FrontMatterParser.new(raw_content, container).parse
     end
   end
 
diff --git a/config/feature_flags/development/wiki_front_matter.yml b/config/feature_flags/development/wiki_front_matter.yml
new file mode 100644
index 00000000000000..39196440d176e5
--- /dev/null
+++ b/config/feature_flags/development/wiki_front_matter.yml
@@ -0,0 +1,8 @@
+---
+name: wiki_front_matter
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/27706
+rollout_issue_url: 
+milestone: '12.10'
+type: development
+group: group::editor
+default_enabled: false
diff --git a/lib/gitlab/wiki_pages/front_matter_parser.rb b/lib/gitlab/wiki_pages/front_matter_parser.rb
index ee30fa907f4aac..071b0dde61919c 100644
--- a/lib/gitlab/wiki_pages/front_matter_parser.rb
+++ b/lib/gitlab/wiki_pages/front_matter_parser.rb
@@ -3,6 +3,8 @@
 module Gitlab
   module WikiPages
     class FrontMatterParser
+      FEATURE_FLAG = :wiki_front_matter
+
       # We limit the maximum length of text we are prepared to parse as YAML, to
       # avoid exploitations and attempts to consume memory and CPU. We allow for:
       #  - a title line
@@ -28,12 +30,18 @@ def initialize(content:, front_matter: {}, reason: nil, error: nil)
       end
 
       # @param [String] wiki_content
-      def initialize(wiki_content)
+      # @param [FeatureGate] feature_gate The scope for feature availability
+      def initialize(wiki_content, feature_gate)
         @wiki_content = wiki_content
+        @feature_gate = feature_gate
+      end
+
+      def self.enabled?(gate = nil)
+        Feature.enabled?(FEATURE_FLAG, gate)
       end
 
       def parse
-        return empty_result unless wiki_content.present?
+        return empty_result unless enabled? && wiki_content.present?
         return empty_result(block.error) unless block.valid?
 
         Result.new(front_matter: block.data, content: strip_front_matter_block)
@@ -86,12 +94,16 @@ def not_mapping?
 
       private
 
-      attr_reader :wiki_content
+      attr_reader :wiki_content, :feature_gate
 
       def empty_result(reason = nil, error = nil)
         Result.new(content: wiki_content, reason: reason, error: error)
       end
 
+      def enabled?
+        self.class.enabled?(feature_gate)
+      end
+
       def block
         @block ||= parse_front_matter_block
       end
diff --git a/spec/lib/gitlab/wiki_pages/front_matter_parser_spec.rb b/spec/lib/gitlab/wiki_pages/front_matter_parser_spec.rb
index c0629c8d795a3a..3152dc2ad2f415 100644
--- a/spec/lib/gitlab/wiki_pages/front_matter_parser_spec.rb
+++ b/spec/lib/gitlab/wiki_pages/front_matter_parser_spec.rb
@@ -3,10 +3,11 @@
 require 'spec_helper'
 
 RSpec.describe Gitlab::WikiPages::FrontMatterParser do
-  subject(:parser) { described_class.new(raw_content) }
+  subject(:parser) { described_class.new(raw_content, gate) }
 
   let(:content) { 'This is the content' }
   let(:end_divider) { '---' }
+  let(:gate) { stub_feature_flag_gate('Gate') }
 
   let(:with_front_matter) do
     <<~MD
@@ -61,6 +62,32 @@ def have_correct_front_matter
       it { is_expected.to have_attributes(reason: :no_match) }
     end
 
+    context 'the feature flag is disabled' do
+      let(:raw_content) { with_front_matter }
+
+      before do
+        stub_feature_flags(Gitlab::WikiPages::FrontMatterParser::FEATURE_FLAG => false)
+      end
+
+      it { is_expected.to have_attributes(front_matter: be_empty, content: raw_content) }
+    end
+
+    context 'the feature flag is enabled for the gated object' do
+      let(:raw_content) { with_front_matter }
+
+      before do
+        stub_feature_flags(Gitlab::WikiPages::FrontMatterParser::FEATURE_FLAG => gate)
+      end
+
+      it do
+        is_expected.to have_attributes(
+          front_matter: have_correct_front_matter,
+          content: content + "\n",
+          reason: be_nil
+        )
+      end
+    end
+
     context 'the end divider is ...' do
       let(:end_divider) { '...' }
       let(:raw_content) { with_front_matter }
diff --git a/spec/models/wiki_page_spec.rb b/spec/models/wiki_page_spec.rb
index 51970064c54453..96c396f085c60f 100644
--- a/spec/models/wiki_page_spec.rb
+++ b/spec/models/wiki_page_spec.rb
@@ -24,6 +24,14 @@ def wiki
     container.wiki
   end
 
+  def disable_front_matter
+    stub_feature_flags(Gitlab::WikiPages::FrontMatterParser::FEATURE_FLAG => false)
+  end
+
+  def enable_front_matter_for(thing)
+    stub_feature_flags(Gitlab::WikiPages::FrontMatterParser::FEATURE_FLAG => thing)
+  end
+
   # Use for groups of tests that do not modify their `subject`.
   #
   #   include_context 'subject is persisted page', title: 'my title'
@@ -40,6 +48,12 @@ def wiki
       it { expect(wiki_page).to have_attributes(front_matter: {}, content: content) }
     end
 
+    shared_examples 'a page with front-matter' do
+      let(:front_matter) { { title: 'Foo', slugs: %w[slug_a slug_b] } }
+
+      it { expect(wiki_page.front_matter).to eq(front_matter) }
+    end
+
     context 'the wiki page has front matter' do
       let(:content) do
         <<~MD
@@ -54,13 +68,27 @@ def wiki
         MD
       end
 
-      it 'has front-matter' do
-        expect(wiki_page.front_matter).to eq({ title: 'Foo', slugs: %w[slug_a slug_b] })
-      end
+      it_behaves_like 'a page with front-matter'
 
       it 'strips the front matter from the content' do
         expect(wiki_page.content.strip).to eq('My actual content')
       end
+
+      context 'the feature flag is off' do
+        before do
+          disable_front_matter
+        end
+
+        it_behaves_like 'a page without front-matter'
+
+        context 'but enabled for the container' do
+          before do
+            enable_front_matter_for(container)
+          end
+
+          it_behaves_like 'a page with front-matter'
+        end
+      end
     end
 
     context 'the wiki page does not have front matter' do
@@ -443,6 +471,29 @@ def wiki
           end
         end
 
+        context 'the front-matter feature flag is not enabled' do
+          before do
+            disable_front_matter
+          end
+
+          it 'does not update the front-matter' do
+            content = subject.content
+            subject.update(front_matter: { slugs: ['x'] })
+
+            page = wiki.find_page(subject.title)
+
+            expect([subject, page]).to all(have_attributes(front_matter: be_empty, content: content))
+          end
+
+          context 'but it is enabled for the container' do
+            before do
+              enable_front_matter_for(container)
+            end
+
+            it_behaves_like 'able to update front-matter'
+          end
+        end
+
         it 'updates the wiki-page front-matter and content together' do
           content = 'totally new content'
           subject.update(content: content, front_matter: { slugs: ['x'] })
-- 
GitLab