diff --git a/db/docs/batched_background_migrations/backfill_ci_secure_file_states_project_id.yml b/db/docs/batched_background_migrations/backfill_ci_secure_file_states_project_id.yml new file mode 100644 index 0000000000000000000000000000000000000000..71c8c76c7bd0e3ffd8deb9a9d1545b7ec2788777 --- /dev/null +++ b/db/docs/batched_background_migrations/backfill_ci_secure_file_states_project_id.yml @@ -0,0 +1,9 @@ +--- +migration_job_name: BackfillCiSecureFileStatesProjectId +description: Backfills sharding key `ci_secure_file_states.project_id` from `ci_secure_files`. +feature_category: secrets_management +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/167617 +milestone: '17.5' +queued_migration_version: 20240930125311 +finalize_after: '2024-10-22' +finalized_by: # version of the migration that finalized this BBM diff --git a/db/docs/ci_secure_file_states.yml b/db/docs/ci_secure_file_states.yml index 39f559491ece686f89d7d38b417592ed899d1238..796b24c4df4514c322d07af7693d15ad9e6700ec 100644 --- a/db/docs/ci_secure_file_states.yml +++ b/db/docs/ci_secure_file_states.yml @@ -17,3 +17,4 @@ desired_sharding_key: table: ci_secure_files sharding_key: project_id belongs_to: ci_secure_file +desired_sharding_key_migration_job_name: BackfillCiSecureFileStatesProjectId diff --git a/db/migrate/20240930125308_add_project_id_to_ci_secure_file_states.rb b/db/migrate/20240930125308_add_project_id_to_ci_secure_file_states.rb new file mode 100644 index 0000000000000000000000000000000000000000..1b096de187bb5fecf20e214f3a183ad812451a4e --- /dev/null +++ b/db/migrate/20240930125308_add_project_id_to_ci_secure_file_states.rb @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +class AddProjectIdToCiSecureFileStates < Gitlab::Database::Migration[2.2] + milestone '17.5' + + def change + add_column :ci_secure_file_states, :project_id, :bigint + end +end diff --git a/db/post_migrate/20240930125309_index_ci_secure_file_states_on_project_id.rb b/db/post_migrate/20240930125309_index_ci_secure_file_states_on_project_id.rb new file mode 100644 index 0000000000000000000000000000000000000000..09a1fe51fa27102d2064164ab60a967632c21dfa --- /dev/null +++ b/db/post_migrate/20240930125309_index_ci_secure_file_states_on_project_id.rb @@ -0,0 +1,16 @@ +# frozen_string_literal: true + +class IndexCiSecureFileStatesOnProjectId < Gitlab::Database::Migration[2.2] + milestone '17.5' + disable_ddl_transaction! + + INDEX_NAME = 'index_ci_secure_file_states_on_project_id' + + def up + add_concurrent_index :ci_secure_file_states, :project_id, name: INDEX_NAME + end + + def down + remove_concurrent_index_by_name :ci_secure_file_states, INDEX_NAME + end +end diff --git a/db/post_migrate/20240930125310_add_ci_secure_file_states_project_id_trigger.rb b/db/post_migrate/20240930125310_add_ci_secure_file_states_project_id_trigger.rb new file mode 100644 index 0000000000000000000000000000000000000000..faa0ff03e329c5a5d58cad00846a3c233ffd5ce4 --- /dev/null +++ b/db/post_migrate/20240930125310_add_ci_secure_file_states_project_id_trigger.rb @@ -0,0 +1,25 @@ +# frozen_string_literal: true + +class AddCiSecureFileStatesProjectIdTrigger < Gitlab::Database::Migration[2.2] + milestone '17.5' + + def up + install_sharding_key_assignment_trigger( + table: :ci_secure_file_states, + sharding_key: :project_id, + parent_table: :ci_secure_files, + parent_sharding_key: :project_id, + foreign_key: :ci_secure_file_id + ) + end + + def down + remove_sharding_key_assignment_trigger( + table: :ci_secure_file_states, + sharding_key: :project_id, + parent_table: :ci_secure_files, + parent_sharding_key: :project_id, + foreign_key: :ci_secure_file_id + ) + end +end diff --git a/db/post_migrate/20240930125311_queue_backfill_ci_secure_file_states_project_id.rb b/db/post_migrate/20240930125311_queue_backfill_ci_secure_file_states_project_id.rb new file mode 100644 index 0000000000000000000000000000000000000000..44645c60221e3051924355aa9bc26fd42659d942 --- /dev/null +++ b/db/post_migrate/20240930125311_queue_backfill_ci_secure_file_states_project_id.rb @@ -0,0 +1,40 @@ +# frozen_string_literal: true + +class QueueBackfillCiSecureFileStatesProjectId < Gitlab::Database::Migration[2.2] + milestone '17.5' + restrict_gitlab_migration gitlab_schema: :gitlab_ci + + MIGRATION = "BackfillCiSecureFileStatesProjectId" + DELAY_INTERVAL = 2.minutes + BATCH_SIZE = 1000 + SUB_BATCH_SIZE = 100 + + def up + queue_batched_background_migration( + MIGRATION, + :ci_secure_file_states, + :ci_secure_file_id, + :project_id, + :ci_secure_files, + :project_id, + :ci_secure_file_id, + job_interval: DELAY_INTERVAL, + batch_size: BATCH_SIZE, + sub_batch_size: SUB_BATCH_SIZE + ) + end + + def down + delete_batched_background_migration( + MIGRATION, + :ci_secure_file_states, + :ci_secure_file_id, + [ + :project_id, + :ci_secure_files, + :project_id, + :ci_secure_file_id + ] + ) + end +end diff --git a/db/schema_migrations/20240930125308 b/db/schema_migrations/20240930125308 new file mode 100644 index 0000000000000000000000000000000000000000..3ad785c1bb05e25981507b755c190958e903f08f --- /dev/null +++ b/db/schema_migrations/20240930125308 @@ -0,0 +1 @@ +b226424a525abb340c104a6c8d5debc5ad0297220b37bff32aaeaa767702d21a \ No newline at end of file diff --git a/db/schema_migrations/20240930125309 b/db/schema_migrations/20240930125309 new file mode 100644 index 0000000000000000000000000000000000000000..248462abefa7453486e9e54fd643040c7b0a2cd5 --- /dev/null +++ b/db/schema_migrations/20240930125309 @@ -0,0 +1 @@ +fc748d24f09f804e50dc62a9e9f5f5941ecd7235a55760f84bfd1c5dd2a95edf \ No newline at end of file diff --git a/db/schema_migrations/20240930125310 b/db/schema_migrations/20240930125310 new file mode 100644 index 0000000000000000000000000000000000000000..abca0c65f00945a6897a9ed9e0e3ce694d87a9b1 --- /dev/null +++ b/db/schema_migrations/20240930125310 @@ -0,0 +1 @@ +6634a974d38adbe6d05a40ccfbd6e5d7469bc2462e7784c70e52e8ecbdb8a447 \ No newline at end of file diff --git a/db/schema_migrations/20240930125311 b/db/schema_migrations/20240930125311 new file mode 100644 index 0000000000000000000000000000000000000000..09a5867fa648e59875cc4b9a76de33608c2ca9df --- /dev/null +++ b/db/schema_migrations/20240930125311 @@ -0,0 +1 @@ +64a55d736a19fb1a04f3f046808e3f9d2f88485a85a9c44b119e4756ad38187e \ No newline at end of file diff --git a/db/structure.sql b/db/structure.sql index 28f58af15e0cee5145004dfb9fdfd4642c8bc930..c24845b8ffa81b9c6743a1f545e8bd9c24c80faf 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -1801,6 +1801,22 @@ RETURN NEW; END $$; +CREATE FUNCTION trigger_8b39d532224c() RETURNS trigger + LANGUAGE plpgsql + AS $$ +BEGIN +IF NEW."project_id" IS NULL THEN + SELECT "project_id" + INTO NEW."project_id" + FROM "ci_secure_files" + WHERE "ci_secure_files"."id" = NEW."ci_secure_file_id"; +END IF; + +RETURN NEW; + +END +$$; + CREATE FUNCTION trigger_8ba31bddd655() RETURNS trigger LANGUAGE plpgsql AS $$ @@ -9095,6 +9111,7 @@ CREATE TABLE ci_secure_file_states ( verification_retry_count smallint, verification_checksum bytea, verification_failure text, + project_id bigint, CONSTRAINT check_a79e5a9261 CHECK ((char_length(verification_failure) <= 255)) ); @@ -28379,6 +28396,8 @@ CREATE INDEX index_ci_secure_file_states_needs_verification ON ci_secure_file_st CREATE INDEX index_ci_secure_file_states_on_ci_secure_file_id ON ci_secure_file_states USING btree (ci_secure_file_id); +CREATE INDEX index_ci_secure_file_states_on_project_id ON ci_secure_file_states USING btree (project_id); + CREATE INDEX index_ci_secure_file_states_on_verification_state ON ci_secure_file_states USING btree (verification_state); CREATE INDEX index_ci_secure_file_states_pending_verification ON ci_secure_file_states USING btree (verified_at NULLS FIRST) WHERE (verification_state = 0); @@ -33689,6 +33708,8 @@ CREATE TRIGGER trigger_8a38ce2327de BEFORE INSERT OR UPDATE ON boards_epic_user_ CREATE TRIGGER trigger_8ac78f164b2d BEFORE INSERT OR UPDATE ON design_management_repositories FOR EACH ROW EXECUTE FUNCTION trigger_8ac78f164b2d(); +CREATE TRIGGER trigger_8b39d532224c BEFORE INSERT OR UPDATE ON ci_secure_file_states FOR EACH ROW EXECUTE FUNCTION trigger_8b39d532224c(); + CREATE TRIGGER trigger_8ba31bddd655 BEFORE INSERT OR UPDATE ON vulnerability_occurrence_pipelines FOR EACH ROW EXECUTE FUNCTION trigger_8ba31bddd655(); CREATE TRIGGER trigger_8d002f38bdef BEFORE INSERT OR UPDATE ON packages_debian_group_components FOR EACH ROW EXECUTE FUNCTION trigger_8d002f38bdef(); diff --git a/lib/gitlab/background_migration/backfill_ci_secure_file_states_project_id.rb b/lib/gitlab/background_migration/backfill_ci_secure_file_states_project_id.rb new file mode 100644 index 0000000000000000000000000000000000000000..2d19fdaf963d44b000103bf468fcc4cb896fa84f --- /dev/null +++ b/lib/gitlab/background_migration/backfill_ci_secure_file_states_project_id.rb @@ -0,0 +1,10 @@ +# frozen_string_literal: true + +module Gitlab + module BackgroundMigration + class BackfillCiSecureFileStatesProjectId < BackfillDesiredShardingKeyJob + operation_name :backfill_ci_secure_file_states_project_id + feature_category :secrets_management + end + end +end diff --git a/spec/db/schema_spec.rb b/spec/db/schema_spec.rb index 3ec0b7ef8ce0fa0a733509b03dd8af6c23354e11..580df2d6e15aebd97b56acba1db380ac8d1313c3 100644 --- a/spec/db/schema_spec.rb +++ b/spec/db/schema_spec.rb @@ -95,6 +95,7 @@ ci_pipeline_schedule_variables: %w[project_id], ci_pipeline_variables: %w[partition_id pipeline_id project_id], ci_pipelines: %w[partition_id auto_canceled_by_partition_id], + ci_secure_file_states: %w[project_id], ci_unit_test_failures: %w[project_id], ci_resources: %w[project_id], p_ci_pipelines: %w[partition_id auto_canceled_by_partition_id auto_canceled_by_id], diff --git a/spec/lib/gitlab/background_migration/backfill_ci_secure_file_states_project_id_spec.rb b/spec/lib/gitlab/background_migration/backfill_ci_secure_file_states_project_id_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..cc28a1e2e1012cb93816e12f7d970f2c2872aa5c --- /dev/null +++ b/spec/lib/gitlab/background_migration/backfill_ci_secure_file_states_project_id_spec.rb @@ -0,0 +1,17 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Gitlab::BackgroundMigration::BackfillCiSecureFileStatesProjectId, + feature_category: :secrets_management, + schema: 20240930125308, + migration: :gitlab_ci do + include_examples 'desired sharding key backfill job' do + let(:batch_table) { :ci_secure_file_states } + let(:batch_column) { :ci_secure_file_id } + let(:backfill_column) { :project_id } + let(:backfill_via_table) { :ci_secure_files } + let(:backfill_via_column) { :project_id } + let(:backfill_via_foreign_key) { :ci_secure_file_id } + end +end diff --git a/spec/migrations/20240930125312_queue_backfill_ci_secure_file_states_project_id_spec.rb b/spec/migrations/20240930125312_queue_backfill_ci_secure_file_states_project_id_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..d0ca7b6d9955c930cb9e56f5c5a0af487cf18b9f --- /dev/null +++ b/spec/migrations/20240930125312_queue_backfill_ci_secure_file_states_project_id_spec.rb @@ -0,0 +1,33 @@ +# frozen_string_literal: true + +require 'spec_helper' +require_migration! + +RSpec.describe QueueBackfillCiSecureFileStatesProjectId, migration: :gitlab_ci, feature_category: :secrets_management 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( + table_name: :ci_secure_file_states, + column_name: :ci_secure_file_id, + interval: described_class::DELAY_INTERVAL, + batch_size: described_class::BATCH_SIZE, + sub_batch_size: described_class::SUB_BATCH_SIZE, + gitlab_schema: :gitlab_ci, + job_arguments: [ + :project_id, + :ci_secure_files, + :project_id, + :ci_secure_file_id + ] + ) + } + end + end +end