diff --git a/db/docs/batched_background_migrations/mark_admin_bot_runners_as_hosted.yml b/db/docs/batched_background_migrations/mark_admin_bot_runners_as_hosted.yml new file mode 100644 index 0000000000000000000000000000000000000000..358c4124bbe1cb1b36817b6095092c997adff8b7 --- /dev/null +++ b/db/docs/batched_background_migrations/mark_admin_bot_runners_as_hosted.yml @@ -0,0 +1,8 @@ +--- +migration_job_name: MarkAdminBotRunnersAsHosted +description: Mark runners created by admin bot as hosted on GitLab Dedicated +feature_category: hosted_runners +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/183329 +milestone: '18.0' +queued_migration_version: 20250505095336 +finalized_by: # version of the migration that finalized this BBM diff --git a/db/post_migrate/20250505095336_queue_mark_admin_bot_runners_as_hosted.rb b/db/post_migrate/20250505095336_queue_mark_admin_bot_runners_as_hosted.rb new file mode 100644 index 0000000000000000000000000000000000000000..a1a2eacf4aa9a7f0d55f1cfbbf85f3035dcba087 --- /dev/null +++ b/db/post_migrate/20250505095336_queue_mark_admin_bot_runners_as_hosted.rb @@ -0,0 +1,28 @@ +# frozen_string_literal: true + +class QueueMarkAdminBotRunnersAsHosted < Gitlab::Database::Migration[2.3] + milestone '18.0' + + # Select the applicable gitlab schema for your batched background migration + restrict_gitlab_migration gitlab_schema: :gitlab_ci + + MIGRATION = "MarkAdminBotRunnersAsHosted" + DELAY_INTERVAL = 2.minutes + BATCH_SIZE = 1000 + SUB_BATCH_SIZE = 100 + + def up + queue_batched_background_migration( + MIGRATION, + :ci_runners, + :id, + job_interval: DELAY_INTERVAL, + batch_size: BATCH_SIZE, + sub_batch_size: SUB_BATCH_SIZE + ) + end + + def down + delete_batched_background_migration(MIGRATION, :ci_runners, :id, []) + end +end diff --git a/db/schema_migrations/20250505095336 b/db/schema_migrations/20250505095336 new file mode 100644 index 0000000000000000000000000000000000000000..28ff1b5608bacf12414ddd8104fa2580fefdc020 --- /dev/null +++ b/db/schema_migrations/20250505095336 @@ -0,0 +1 @@ +75166bbf5d04065b48b810200cada005c73109b8da8ccebc6ed9f3195951928a \ No newline at end of file diff --git a/ee/lib/ee/gitlab/background_migration/mark_admin_bot_runners_as_hosted.rb b/ee/lib/ee/gitlab/background_migration/mark_admin_bot_runners_as_hosted.rb new file mode 100644 index 0000000000000000000000000000000000000000..3332ec1e8d7aa99aaa7f44bfc292cff569c46c0e --- /dev/null +++ b/ee/lib/ee/gitlab/background_migration/mark_admin_bot_runners_as_hosted.rb @@ -0,0 +1,44 @@ +# frozen_string_literal: true + +module EE + module Gitlab + module BackgroundMigration + module MarkAdminBotRunnersAsHosted + extend ActiveSupport::Concern + extend ::Gitlab::Utils::Override + + prepended do + operation_name :mark_admin_bot_runners_as_hosted + feature_category :hosted_runners + end + + override :perform + def perform + return unless ::Gitlab::CurrentSettings.gitlab_dedicated_instance + + each_sub_batch do |sub_batch| + sub_batch.each do |runner| + next unless runner.creator_id == admin_bot.id + + CiHostedRunner.find_or_create_by!(runner_id: runner.id) + end + end + end + + class ApplicationSetting < ApplicationRecord + self.table_name = :application_settings + end + + class CiHostedRunner < ::Ci::ApplicationRecord + self.table_name = :ci_hosted_runners + end + + private + + def admin_bot + @_admin_bot ||= ::Users::Internal.admin_bot + end + end + end + end +end diff --git a/ee/spec/lib/ee/gitlab/background_migration/mark_admin_bot_runners_as_hosted_spec.rb b/ee/spec/lib/ee/gitlab/background_migration/mark_admin_bot_runners_as_hosted_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..4dd7a2113e5f9a1764c3a14a8a1f89d16ea1dad9 --- /dev/null +++ b/ee/spec/lib/ee/gitlab/background_migration/mark_admin_bot_runners_as_hosted_spec.rb @@ -0,0 +1,66 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Gitlab::BackgroundMigration::MarkAdminBotRunnersAsHosted, + feature_category: :hosted_runners do + let!(:admin_bot) { Users::Internal.admin_bot } + + let!(:admin_bot_runner) do + table(:ci_runners, database: :ci, primary_key: :id) + .create!(runner_type: 1, creator_id: admin_bot.id) + end + + let!(:admin_bot_runner2) do + table(:ci_runners, database: :ci, primary_key: :id) + .create!(runner_type: 1, creator_id: admin_bot.id) + end + + let!(:non_admin_bot_runner) { table(:ci_runners, database: :ci, primary_key: :id).create!(runner_type: 1) } + + before do + allow(Gitlab::CurrentSettings).to receive(:gitlab_dedicated_instance).and_return(true) + end + + subject(:migration) do + described_class.new( + start_id: Ci::Runner.minimum(:id), + end_id: Ci::Runner.maximum(:id), + batch_table: :ci_runners, + batch_column: :id, + sub_batch_size: 100, + pause_ms: 0, + connection: ::Ci::ApplicationRecord.connection + ) + end + + describe '#perform' do + context 'when on a dedicated instance' do + it 'marks runners created by admin bot as hosted' do + expect { migration.perform }.to change { Ci::HostedRunner.count }.by(2) + + expect(Ci::HostedRunner.exists?(runner_id: admin_bot_runner.id)).to be_truthy + expect(Ci::HostedRunner.exists?(runner_id: admin_bot_runner2.id)).to be_truthy + expect(Ci::HostedRunner.exists?(runner_id: non_admin_bot_runner.id)).to be_falsey + end + + it 'does not create duplicate hosted runner records' do + Ci::HostedRunner.create!(runner_id: admin_bot_runner.id) + + expect { migration.perform }.to change { Ci::HostedRunner.count }.by(1) + + expect(Ci::HostedRunner.exists?(runner_id: admin_bot_runner2.id)).to be_truthy + end + end + + context 'when not on a dedicated instance' do + before do + allow(Gitlab::CurrentSettings).to receive(:gitlab_dedicated_instance).and_return(false) + end + + it 'does not create any hosted runner records' do + expect { migration.perform }.not_to change { Ci::HostedRunner.count } + end + end + end +end diff --git a/lib/gitlab/background_migration/mark_admin_bot_runners_as_hosted.rb b/lib/gitlab/background_migration/mark_admin_bot_runners_as_hosted.rb new file mode 100644 index 0000000000000000000000000000000000000000..edf5cc61aee5a8652385c2258d9dae7c26d9daf5 --- /dev/null +++ b/lib/gitlab/background_migration/mark_admin_bot_runners_as_hosted.rb @@ -0,0 +1,17 @@ +# frozen_string_literal: true + +module Gitlab + module BackgroundMigration + # This class doesn't create SecuritySetting + # as this feature exists only in EE + class MarkAdminBotRunnersAsHosted < BatchedMigrationJob + feature_category :hosted_runners + + def perform; end + end + end +end + +# rubocop:disable Layout/LineLength -- If I do multiline, another cop complains about prepend should be last line +Gitlab::BackgroundMigration::MarkAdminBotRunnersAsHosted.prepend_mod_with('Gitlab::BackgroundMigration::MarkAdminBotRunnersAsHosted') +# rubocop:enable Layout/LineLength diff --git a/spec/migrations/20250505095336_queue_mark_admin_bot_runners_as_hosted_spec.rb b/spec/migrations/20250505095336_queue_mark_admin_bot_runners_as_hosted_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..4738d49a36d306c8ad9420736e48536e90b6d22a --- /dev/null +++ b/spec/migrations/20250505095336_queue_mark_admin_bot_runners_as_hosted_spec.rb @@ -0,0 +1,27 @@ +# frozen_string_literal: true + +require 'spec_helper' +require_migration! + +RSpec.describe QueueMarkAdminBotRunnersAsHosted, migration: :gitlab_ci, feature_category: :hosted_runners do + let!(:batched_migration) { described_class::MIGRATION } + + it 'schedules a new batched migration' do + reversible_migration do |migration| + migration.before -> { + expect(batched_migration).not_to have_scheduled_batched_migration + } + + migration.after -> { + expect(batched_migration).to have_scheduled_batched_migration( + gitlab_schema: :gitlab_ci, + table_name: :ci_runners, + column_name: :id, + interval: described_class::DELAY_INTERVAL, + batch_size: described_class::BATCH_SIZE, + sub_batch_size: described_class::SUB_BATCH_SIZE + ) + } + end + end +end