From 50cbca798388e5093ee6302d1c6670923e97c258 Mon Sep 17 00:00:00 2001
From: Safwan Ahmed <safahmed@gitlab.com>
Date: Mon, 11 Nov 2024 18:05:57 +0000
Subject: [PATCH] Apply 1 suggestion(s) to 1 file(s)

Co-authored-by: Peter Leitzen <pleitzen@gitlab.com>
---
 danger/plugins/remote_development.rb          |   9 ++
 danger/remote_development/Dangerfile          |   3 +
 .../desired_config_generator_spec.rb          | 121 ++++++++++++++++++
 .../desired_config_generator.rb               |  62 +++++++++
 4 files changed, 195 insertions(+)
 create mode 100644 danger/plugins/remote_development.rb
 create mode 100644 danger/remote_development/Dangerfile
 create mode 100644 spec/tooling/danger/remote_development/desired_config_generator_spec.rb
 create mode 100644 tooling/danger/remote_development/desired_config_generator.rb

diff --git a/danger/plugins/remote_development.rb b/danger/plugins/remote_development.rb
new file mode 100644
index 0000000000000..a40584a3a3873
--- /dev/null
+++ b/danger/plugins/remote_development.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+require_relative '../../tooling/danger/remote_development/desired_config_generator'
+
+module Danger
+  class RemoteDevelopment < ::Danger::Plugin
+    include Tooling::Danger::RemoteDevelopment::DesiredConfigGenerator
+  end
+end
diff --git a/danger/remote_development/Dangerfile b/danger/remote_development/Dangerfile
new file mode 100644
index 0000000000000..91a69b1d90844
--- /dev/null
+++ b/danger/remote_development/Dangerfile
@@ -0,0 +1,3 @@
+# frozen_string_literal: true
+
+remote_development.add_comment_if_shared_context_updated
diff --git a/spec/tooling/danger/remote_development/desired_config_generator_spec.rb b/spec/tooling/danger/remote_development/desired_config_generator_spec.rb
new file mode 100644
index 0000000000000..6b43c19dfbef5
--- /dev/null
+++ b/spec/tooling/danger/remote_development/desired_config_generator_spec.rb
@@ -0,0 +1,121 @@
+# frozen_string_literal: true
+
+require 'fast_spec_helper'
+require 'gitlab/dangerfiles/spec_helper'
+
+require_relative '../../../../tooling/danger/remote_development/desired_config_generator'
+require_relative '../../../../tooling/danger/project_helper'
+
+RSpec.describe Tooling::Danger::RemoteDevelopment::DesiredConfigGenerator, feature_category: :tooling do
+  subject(:remote_development) { fake_danger.new(helper: fake_helper) }
+
+  let(:fake_danger) { DangerSpecHelper.fake_danger.include(described_class) }
+  let(:fake_project_helper) { instance_double(Tooling::Danger::ProjectHelper) }
+  let(:shared_context_file) { described_class::REMOTE_DEVELOPMENT_SHARED_CONTEXT }
+  let(:devfile_parser_file) { described_class::DEVFILE_PARSER }
+  let(:desired_config_generator_file) { described_class::DESIRED_CONFIG_GENERATOR }
+  let(:comment) { "" }
+  let(:changed_files) { [] }
+  let(:file_diff) do
+    [
+      "+Any changes to the file is valid...."
+    ]
+  end
+
+  let(:file_lines) { file_diff.map { |line| line.delete_prefix('+') } }
+
+  include_context "with dangerfile"
+
+  describe '#add_comment_if_shared_context_updated' do
+    shared_examples "adds a comment to the shared context file" do
+      it 'adds comment to the shared_context file' do
+        expect(remote_development).to receive(:markdown).with("\n#{comment}",
+          file: shared_context_file, line: 1)
+        remote_development.add_comment_if_shared_context_updated
+      end
+    end
+
+    shared_examples "does not a comment to the shared context file" do
+      it 'does not add any comment to the shared_context file' do
+        expect(remote_development).not_to receive(:markdown)
+        remote_development.add_comment_if_shared_context_updated
+      end
+    end
+
+    before do
+      allow(remote_development).to receive(:project_helper).and_return(fake_project_helper)
+      allow(remote_development.helper).to receive(:all_changed_files).and_return(changed_files)
+      allow(remote_development.helper).to receive(:changed_lines).with(shared_context_file).and_return(file_diff)
+      allow(remote_development.project_helper).to receive(:file_lines).and_return(file_lines)
+    end
+
+    context 'when no relevant files changes' do
+      it_behaves_like 'does not a comment to the shared context file'
+    end
+
+    context 'when only the shared_context_file changes' do
+      let(:changed_files) { [shared_context_file] }
+
+      it_behaves_like 'does not a comment to the shared context file'
+    end
+
+    context 'when the shared_context and devfile parser files change' do
+      let(:changed_files) do
+        [
+          shared_context_file,
+          devfile_parser_file
+        ]
+      end
+
+      let(:comment) do
+        <<~TEXT.chop
+          This merge request updated the [`shared_context`](#{shared_context_file}) file \
+          as well as the [`devfile_parser`](#{devfile_parser_file}) file. Please consider \
+          reviewing any changes made to the `shared_context` file is valid.
+        TEXT
+      end
+
+      it_behaves_like 'adds a comment to the shared context file'
+    end
+
+    context 'when the shared_context and desired_config files change' do
+      let(:changed_files) do
+        [
+          shared_context_file,
+          desired_config_generator_file
+        ]
+      end
+
+      let(:comment) do
+        <<~TEXT.chop
+          This merge request updated the [`shared_context`](#{shared_context_file}) file \
+          and the [`desired_config_generator`](#{desired_config_generator_file}) file\
+          . Please consider reviewing any changes made to the `shared_context` file is valid.
+        TEXT
+      end
+
+      it_behaves_like 'adds a comment to the shared context file'
+    end
+
+    context 'when the shared_context,dev_file_parser and desired_config files change' do
+      let(:changed_files) do
+        [
+          shared_context_file,
+          devfile_parser_file,
+          desired_config_generator_file
+        ]
+      end
+
+      let(:comment) do
+        <<~TEXT.chop
+          This merge request updated the [`shared_context`](#{shared_context_file}) file \
+          as well as the [`devfile_parser`](#{devfile_parser_file}) file \
+          and the [`desired_config_generator`](#{desired_config_generator_file}) file\
+          . Please consider reviewing any changes made to the `shared_context` file is valid.
+        TEXT
+      end
+
+      it_behaves_like 'adds a comment to the shared context file'
+    end
+  end
+end
diff --git a/tooling/danger/remote_development/desired_config_generator.rb b/tooling/danger/remote_development/desired_config_generator.rb
new file mode 100644
index 0000000000000..e036195670e4c
--- /dev/null
+++ b/tooling/danger/remote_development/desired_config_generator.rb
@@ -0,0 +1,62 @@
+# frozen_string_literal: true
+
+require_relative '../suggestor'
+
+module Tooling
+  module Danger
+    module RemoteDevelopment
+      module DesiredConfigGenerator
+        include ::Tooling::Danger::Suggestor
+
+        WORKSPACE_LIB = 'ee/lib/remote_development/workspace_operations'
+        SHARED_CONTEXT_PATH = 'ee/spec/support/shared_contexts/remote_development'
+        DESIRED_CONFIG_GENERATOR = "#{WORKSPACE_LIB}/reconcile/output/desired_config_generator.rb".freeze
+        DEVFILE_PARSER = "#{WORKSPACE_LIB}/reconcile/output/devfile_parser.rb".freeze
+        REMOTE_DEVELOPMENT_SHARED_CONTEXT = "#{SHARED_CONTEXT_PATH}/remote_development_shared_contexts.rb".freeze
+
+        def add_comment_if_shared_context_updated
+          return unless remote_development_shared_context_updated? && either_config_files_updated?
+
+          # Make the suggestion on any change to the file once
+          add_suggestion(
+            filename: REMOTE_DEVELOPMENT_SHARED_CONTEXT,
+            regex: /.+/,
+            comment_text: build_comment,
+            once_per_file: true
+          )
+        end
+
+        private
+
+        def build_comment
+          prefix = "This merge request updated the [`shared_context`](#{REMOTE_DEVELOPMENT_SHARED_CONTEXT}) file"
+          prefix.concat(" as well as the [`devfile_parser`](#{DEVFILE_PARSER}) file") if devfile_parser_updated?
+
+          if desired_config_generator_updated?
+            prefix.concat(" and the [`desired_config_generator`](#{DESIRED_CONFIG_GENERATOR}) file")
+          end
+
+          suffix = ". Please consider reviewing any changes made to the `shared_context` file is valid."
+          prefix.concat(suffix)
+          prefix
+        end
+
+        def either_config_files_updated?
+          devfile_parser_updated? || desired_config_generator_updated?
+        end
+
+        def remote_development_shared_context_updated?
+          helper.all_changed_files.include?(REMOTE_DEVELOPMENT_SHARED_CONTEXT)
+        end
+
+        def desired_config_generator_updated?
+          helper.all_changed_files.include?(DESIRED_CONFIG_GENERATOR)
+        end
+
+        def devfile_parser_updated?
+          helper.all_changed_files.include?(DEVFILE_PARSER)
+        end
+      end
+    end
+  end
+end
-- 
GitLab