From a367afc1e2779b981f4ba522f6dc3b1d4c792d44 Mon Sep 17 00:00:00 2001
From: Jerry Seto <jseto@gitlab.com>
Date: Tue, 18 Jul 2023 17:37:05 +0000
Subject: [PATCH] Check changes for files over a limit

Log if changes would cause new files to exceed a global limit.

Contributes to: https://gitlab.com/gitlab-org/gitlab/-/issues/393535
---
 .../development/global_file_size_check.yml    |  8 +++++
 lib/gitlab/checks/changes_access.rb           |  1 +
 lib/gitlab/checks/global_file_size_check.rb   | 29 +++++++++++++++
 spec/lib/gitlab/checks/changes_access_spec.rb |  8 +++++
 .../checks/global_file_size_check_spec.rb     | 36 +++++++++++++++++++
 5 files changed, 82 insertions(+)
 create mode 100644 config/feature_flags/development/global_file_size_check.yml
 create mode 100644 lib/gitlab/checks/global_file_size_check.rb
 create mode 100644 spec/lib/gitlab/checks/global_file_size_check_spec.rb

diff --git a/config/feature_flags/development/global_file_size_check.yml b/config/feature_flags/development/global_file_size_check.yml
new file mode 100644
index 0000000000000..eea775cdad564
--- /dev/null
+++ b/config/feature_flags/development/global_file_size_check.yml
@@ -0,0 +1,8 @@
+---
+name: global_file_size_check
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/125956
+rollout_issue_url:
+milestone: '16.2'
+type: development
+group: group::source code
+default_enabled: false
diff --git a/lib/gitlab/checks/changes_access.rb b/lib/gitlab/checks/changes_access.rb
index 194e3f6e93868..3fd7e44985e9a 100644
--- a/lib/gitlab/checks/changes_access.rb
+++ b/lib/gitlab/checks/changes_access.rb
@@ -117,6 +117,7 @@ def single_access_checks!
 
       def bulk_access_checks!
         Gitlab::Checks::LfsCheck.new(self).validate!
+        Gitlab::Checks::GlobalFileSizeCheck.new(self).validate!
       end
 
       def blank_rev?(rev)
diff --git a/lib/gitlab/checks/global_file_size_check.rb b/lib/gitlab/checks/global_file_size_check.rb
new file mode 100644
index 0000000000000..418d2d32b57fe
--- /dev/null
+++ b/lib/gitlab/checks/global_file_size_check.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+module Gitlab
+  module Checks
+    class GlobalFileSizeCheck < BaseBulkChecker
+      MAX_FILE_SIZE_MB = 100
+      LOG_MESSAGE = 'Checking for blobs over the file size limit'
+
+      def validate!
+        return unless Feature.enabled?(:global_file_size_check, project)
+
+        Gitlab::AppJsonLogger.info(LOG_MESSAGE)
+        logger.log_timed(LOG_MESSAGE) do
+          Gitlab::Checks::FileSizeCheck::AllowExistingOversizedBlobs.new(
+            project: project,
+            changes: changes,
+            file_size_limit_megabytes: MAX_FILE_SIZE_MB
+          ).find
+
+          # TODO: https://gitlab.com/gitlab-org/gitlab/-/issues/393535
+          # - set limit per plan tier
+          # - raise an error if large blobs are found
+        end
+
+        true
+      end
+    end
+  end
+end
diff --git a/spec/lib/gitlab/checks/changes_access_spec.rb b/spec/lib/gitlab/checks/changes_access_spec.rb
index 552afcdb1806f..854c04dd581cd 100644
--- a/spec/lib/gitlab/checks/changes_access_spec.rb
+++ b/spec/lib/gitlab/checks/changes_access_spec.rb
@@ -24,6 +24,14 @@
 
         subject.validate!
       end
+
+      it 'calls file size check' do
+        expect_next_instance_of(Gitlab::Checks::GlobalFileSizeCheck) do |instance|
+          expect(instance).to receive(:validate!)
+        end
+
+        subject.validate!
+      end
     end
 
     context 'when time limit was reached' do
diff --git a/spec/lib/gitlab/checks/global_file_size_check_spec.rb b/spec/lib/gitlab/checks/global_file_size_check_spec.rb
new file mode 100644
index 0000000000000..9ea0c73b1c7a0
--- /dev/null
+++ b/spec/lib/gitlab/checks/global_file_size_check_spec.rb
@@ -0,0 +1,36 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Checks::GlobalFileSizeCheck, feature_category: :source_code_management do
+  include_context 'changes access checks context'
+
+  describe '#validate!' do
+    context 'when global_file_size_check is disabled' do
+      before do
+        stub_feature_flags(global_file_size_check: false)
+      end
+
+      it 'does not log' do
+        expect(subject).not_to receive(:log_timed)
+        expect(Gitlab::AppJsonLogger).not_to receive(:info)
+        expect(Gitlab::Checks::FileSizeCheck::AllowExistingOversizedBlobs).not_to receive(:new)
+        subject.validate!
+      end
+    end
+
+    it 'checks for file sizes' do
+      expect_next_instance_of(Gitlab::Checks::FileSizeCheck::AllowExistingOversizedBlobs,
+        project: project,
+        changes: changes,
+        file_size_limit_megabytes: 100
+      ) do |check|
+        expect(check).to receive(:find).and_call_original
+      end
+      expect(subject.logger).to receive(:log_timed).with('Checking for blobs over the file size limit')
+        .and_call_original
+      expect(Gitlab::AppJsonLogger).to receive(:info).with('Checking for blobs over the file size limit')
+      subject.validate!
+    end
+  end
+end
-- 
GitLab