From ba4b4912423309b76293e9eaab7879ee03a79d61 Mon Sep 17 00:00:00 2001
From: Lin Jen-Shin <jen-shin@gitlab.com>
Date: Tue, 2 Jan 2024 19:12:22 +0000
Subject: [PATCH] Run jest in the as-if-foss cross project pipeline when
 applicable

---
 .gitlab/ci/as-if-foss.gitlab-ci.yml           |  1 +
 .gitlab/ci/rules.gitlab-ci.yml                |  2 +
 scripts/setup/generate-as-if-foss-env.rb      | 79 ++++++++++++++---
 .../setup/generate_as_if_foss_env_spec.rb     | 84 +++++++++++++++++++
 4 files changed, 155 insertions(+), 11 deletions(-)
 create mode 100644 spec/scripts/setup/generate_as_if_foss_env_spec.rb

diff --git a/.gitlab/ci/as-if-foss.gitlab-ci.yml b/.gitlab/ci/as-if-foss.gitlab-ci.yml
index c1ba9d01c77d..0c496ebacd83 100644
--- a/.gitlab/ci/as-if-foss.gitlab-ci.yml
+++ b/.gitlab/ci/as-if-foss.gitlab-ci.yml
@@ -64,6 +64,7 @@ start-as-if-foss:
     ENABLE_RSPEC_MIGRATION: $ENABLE_RSPEC_MIGRATION
     ENABLE_RSPEC_BACKGROUND_MIGRATION: $ENABLE_RSPEC_BACKGROUND_MIGRATION
     ENABLE_RSPEC_SYSTEM: $ENABLE_RSPEC_SYSTEM
+    ENABLE_JEST: $ENABLE_JEST
   trigger:
     project: gitlab-org/gitlab-foss
     branch: as-if-foss/${CI_COMMIT_REF_NAME}
diff --git a/.gitlab/ci/rules.gitlab-ci.yml b/.gitlab/ci/rules.gitlab-ci.yml
index 8817f8707e97..84d39f3aeef5 100644
--- a/.gitlab/ci/rules.gitlab-ci.yml
+++ b/.gitlab/ci/rules.gitlab-ci.yml
@@ -1250,6 +1250,7 @@
   rules:
     - <<: *if-merge-request-labels-pipeline-expedite
       when: never
+    - if: '$ENABLE_JEST == "true"'
     - <<: *if-merge-request-labels-run-all-rspec
     - <<: *if-merge-request-labels-frontend-and-feature-flag
     - <<: *if-default-refs
@@ -1300,6 +1301,7 @@
       when: never
     - <<: *if-fork-merge-request
       when: never
+    - if: '$ENABLE_JEST == "true"'
     - <<: *if-merge-request-labels-run-all-jest
     - <<: *if-merge-request-labels-frontend-and-feature-flag
     - <<: *if-merge-request
diff --git a/scripts/setup/generate-as-if-foss-env.rb b/scripts/setup/generate-as-if-foss-env.rb
index 68b869287a6d..ee688e4f1d06 100755
--- a/scripts/setup/generate-as-if-foss-env.rb
+++ b/scripts/setup/generate-as-if-foss-env.rb
@@ -1,22 +1,79 @@
 #!/usr/bin/env ruby
 # frozen_string_literal: true
 
-require 'gitlab'
+# In spec/scripts/setup/generate_as_if_foss_env_spec.rb we completely stub it
+require 'gitlab' unless Object.const_defined?(:Gitlab)
 require 'set'
 
-client = Gitlab.client(endpoint: ENV['CI_API_V4_URL'], private_token: '')
+class GenerateAsIfFossEnv
+  def initialize
+    @client = Gitlab.client(endpoint: ENV['CI_API_V4_URL'], private_token: '')
+    @rspec_jobs = Set.new
+    @jest_jobs = Set.new
+  end
 
-rspec_jobs = Set.new
+  def variables
+    @variables ||= generate_variables
+  end
 
-client.pipeline_jobs(ENV['CI_PROJECT_ID'], ENV['CI_PIPELINE_ID']).auto_paginate do |job|
-  rspec_type = job.name[/^rspec ([\w\-]+)/, 1]
+  def display
+    variables.each do |key, value|
+      puts "#{key}=#{value}"
+    end
+  end
 
-  rspec_jobs << rspec_type if rspec_type
-end
+  private
+
+  attr_reader :client, :rspec_jobs, :jest_jobs
+
+  def generate_variables
+    scan_jobs
+
+    {
+      START_AS_IF_FOSS: 'true',
+      RUBY_VERSION: ENV['RUBY_VERSION']
+    }.merge(rspec_variables).merge(jest_variables)
+  end
+
+  def scan_jobs
+    each_job do |job|
+      detect_rspec(job) || detect_jest(job)
+    end
+  end
+
+  def each_job
+    client.pipeline_jobs(ENV['CI_PROJECT_ID'], ENV['CI_PIPELINE_ID']).auto_paginate do |job|
+      yield(job)
+    end
+  end
+
+  def detect_rspec(job)
+    rspec_type = job.name[/^rspec ([\w\-]+)/, 1]
 
-puts 'START_AS_IF_FOSS=true', "RUBY_VERSION=#{ENV['RUBY_VERSION']}"
-puts 'ENABLE_RSPEC=true' if rspec_jobs.any?
+    rspec_jobs << rspec_type if rspec_type
+  end
 
-rspec_jobs.each do |rspec|
-  puts "ENABLE_RSPEC_#{rspec.upcase.tr('-', '_')}=true"
+  def detect_jest(job)
+    jest_type = job.name[/^jest([\w\-]*)/, 1]
+
+    jest_jobs << jest_type if jest_type
+  end
+
+  def rspec_variables
+    return {} if rspec_jobs.empty?
+
+    rspec_jobs.inject({ ENABLE_RSPEC: 'true' }) do |result, rspec|
+      result.merge("ENABLE_RSPEC_#{rspec.upcase.tr('-', '_')}": 'true')
+    end
+  end
+
+  def jest_variables
+    return {} if jest_jobs.empty?
+
+    jest_jobs.inject({ ENABLE_JEST: 'true' }) do |result, jest|
+      result.merge("ENABLE_JEST#{jest.upcase.tr('-', '_')}": 'true')
+    end
+  end
 end
+
+GenerateAsIfFossEnv.new.display if $PROGRAM_NAME == __FILE__
diff --git a/spec/scripts/setup/generate_as_if_foss_env_spec.rb b/spec/scripts/setup/generate_as_if_foss_env_spec.rb
new file mode 100644
index 000000000000..bd4c741ffadd
--- /dev/null
+++ b/spec/scripts/setup/generate_as_if_foss_env_spec.rb
@@ -0,0 +1,84 @@
+# frozen_string_literal: true
+
+require 'fast_spec_helper'
+require 'gitlab/rspec/stub_env'
+
+# NOTE: Under the context of fast_spec_helper, when we `require 'gitlab'`
+# we do not load the Gitlab client, but our own Gitlab module.
+# Keep this in mind and just stub anything which might touch it!
+require_relative '../../../scripts/setup/generate-as-if-foss-env'
+
+RSpec.describe GenerateAsIfFossEnv, feature_category: :tooling do
+  include StubENV
+
+  subject(:generate) { described_class.new }
+
+  before do
+    stub_env(RUBY_VERSION: '3.1')
+  end
+
+  shared_context 'when there are all jobs' do
+    let(:jobs) do
+      [
+        'rspec fast_spec_helper',
+        'rspec unit',
+        'rspec integration',
+        'rspec system',
+        'rspec migration',
+        'rspec background-migration',
+        'jest',
+        'jest-integration'
+      ]
+    end
+
+    before do
+      messages = receive_message_chain(:client, :pipeline_jobs, :auto_paginate)
+
+      yield_jobs = jobs.inject(messages) do |stub, job|
+        stub.and_yield(double(name: job)) # rubocop:disable RSpec/VerifiedDoubles -- As explained at the top of this file, we do not load the Gitlab client
+      end
+
+      allow(Gitlab).to yield_jobs
+    end
+  end
+
+  describe '#variables' do
+    include_context 'when there are all jobs'
+
+    it 'returns correct variables' do
+      expect(generate.variables).to eq({
+        START_AS_IF_FOSS: 'true',
+        RUBY_VERSION: ENV['RUBY_VERSION'],
+        ENABLE_RSPEC: 'true',
+        ENABLE_RSPEC_FAST_SPEC_HELPER: 'true',
+        ENABLE_RSPEC_UNIT: 'true',
+        ENABLE_RSPEC_INTEGRATION: 'true',
+        ENABLE_RSPEC_SYSTEM: 'true',
+        ENABLE_RSPEC_MIGRATION: 'true',
+        ENABLE_RSPEC_BACKGROUND_MIGRATION: 'true',
+        ENABLE_JEST: 'true',
+        ENABLE_JEST_INTEGRATION: 'true'
+      })
+    end
+  end
+
+  describe '#display' do
+    include_context 'when there are all jobs'
+
+    it 'puts correct variables' do
+      expect { generate.display }.to output(<<~ENV).to_stdout
+        START_AS_IF_FOSS=true
+        RUBY_VERSION=#{ENV['RUBY_VERSION']}
+        ENABLE_RSPEC=true
+        ENABLE_RSPEC_FAST_SPEC_HELPER=true
+        ENABLE_RSPEC_UNIT=true
+        ENABLE_RSPEC_INTEGRATION=true
+        ENABLE_RSPEC_SYSTEM=true
+        ENABLE_RSPEC_MIGRATION=true
+        ENABLE_RSPEC_BACKGROUND_MIGRATION=true
+        ENABLE_JEST=true
+        ENABLE_JEST_INTEGRATION=true
+      ENV
+    end
+  end
+end
-- 
GitLab