diff --git a/db/migrate/20251111101929_add_issue_id_to_duo_workflows_workflows.rb b/db/migrate/20251111101929_add_issue_id_to_duo_workflows_workflows.rb new file mode 100644 index 0000000000000000000000000000000000000000..a5394856615878336b7df6a4a76590efe036c2a3 --- /dev/null +++ b/db/migrate/20251111101929_add_issue_id_to_duo_workflows_workflows.rb @@ -0,0 +1,25 @@ +# frozen_string_literal: true + +class AddIssueIdToDuoWorkflowsWorkflows < Gitlab::Database::Migration[2.3] + disable_ddl_transaction! + + milestone '18.6' + + INDEX_NAME = 'index_duo_workflows_workflows_on_issue_id' + TABLE = :duo_workflows_workflows + + def up + with_lock_retries do + add_column TABLE, :issue_id, :bigint, null: true, if_not_exists: true + end + + add_concurrent_index TABLE, :issue_id, name: INDEX_NAME + add_concurrent_foreign_key TABLE, :issues, column: :issue_id, on_delete: :cascade + end + + def down + with_lock_retries do + remove_column TABLE, :issue_id, :bigint, null: true, if_exists: true + end + end +end diff --git a/db/migrate/20251111102913_add_merge_request_id_to_duo_workflows_workflows.rb b/db/migrate/20251111102913_add_merge_request_id_to_duo_workflows_workflows.rb new file mode 100644 index 0000000000000000000000000000000000000000..f48a824611ac69bae1ea198fcdb87c5be438fb24 --- /dev/null +++ b/db/migrate/20251111102913_add_merge_request_id_to_duo_workflows_workflows.rb @@ -0,0 +1,25 @@ +# frozen_string_literal: true + +class AddMergeRequestIdToDuoWorkflowsWorkflows < Gitlab::Database::Migration[2.3] + disable_ddl_transaction! + + milestone '18.6' + + INDEX_NAME = 'index_duo_workflows_workflows_on_merge_request_id' + TABLE = :duo_workflows_workflows + + def up + with_lock_retries do + add_column TABLE, :merge_request_id, :bigint, null: true, if_not_exists: true + end + + add_concurrent_index TABLE, :merge_request_id, name: INDEX_NAME + add_concurrent_foreign_key TABLE, :merge_requests, column: :merge_request_id, on_delete: :cascade + end + + def down + with_lock_retries do + remove_column TABLE, :merge_request_id, :bigint, null: true, if_exists: true + end + end +end diff --git a/db/migrate/20251111104032_add_single_noteable_constraint_to_duo_workflows_workflows.rb b/db/migrate/20251111104032_add_single_noteable_constraint_to_duo_workflows_workflows.rb new file mode 100644 index 0000000000000000000000000000000000000000..9f2700183c93d4fd2d3bde5cf9ef6a0ead6c51ff --- /dev/null +++ b/db/migrate/20251111104032_add_single_noteable_constraint_to_duo_workflows_workflows.rb @@ -0,0 +1,19 @@ +# frozen_string_literal: true + +class AddSingleNoteableConstraintToDuoWorkflowsWorkflows < Gitlab::Database::Migration[2.3] + disable_ddl_transaction! + + milestone '18.6' + + CONSTRAINT_NAME = 'check_workflows_single_noteable' + + def up + add_check_constraint :duo_workflows_workflows, + 'num_nonnulls(issue_id, merge_request_id) <= 1', + CONSTRAINT_NAME + end + + def down + remove_check_constraint :duo_workflows_workflows, CONSTRAINT_NAME + end +end diff --git a/db/schema_migrations/20251111101929 b/db/schema_migrations/20251111101929 new file mode 100644 index 0000000000000000000000000000000000000000..34f201659d77c4e3942c31ef69660e42133a2651 --- /dev/null +++ b/db/schema_migrations/20251111101929 @@ -0,0 +1 @@ +18ce72e2b1e04d94471abd60d5b81f6edb0271bb15edc0608302a973b9611cb3 \ No newline at end of file diff --git a/db/schema_migrations/20251111102913 b/db/schema_migrations/20251111102913 new file mode 100644 index 0000000000000000000000000000000000000000..0acb348749d73477e76f283b12e10ba1095af468 --- /dev/null +++ b/db/schema_migrations/20251111102913 @@ -0,0 +1 @@ +48b6fb18dbbba95e9fe0d79daf4094b3b24c9c897d0e36a643f09a82241cc976 \ No newline at end of file diff --git a/db/schema_migrations/20251111104032 b/db/schema_migrations/20251111104032 new file mode 100644 index 0000000000000000000000000000000000000000..8b848d9ce1225efd66fca91c783a43428e5a8cdb --- /dev/null +++ b/db/schema_migrations/20251111104032 @@ -0,0 +1 @@ +a4c55ca116143f952fd08dc3f767ea6ae00edf27938ad8d51817903166174e59 \ No newline at end of file diff --git a/db/structure.sql b/db/structure.sql index 39ec20faa13dc57c4ff7c8fb7ae7a7b234e4080d..b4a9b21fd0c19d45ca3bc25333976bdcff82e1c3 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -16650,10 +16650,13 @@ CREATE TABLE duo_workflows_workflows ( environment smallint, namespace_id bigint, ai_catalog_item_version_id bigint, + issue_id bigint, + merge_request_id bigint, CONSTRAINT check_30ca07a4ef CHECK ((char_length(goal) <= 16384)), CONSTRAINT check_3a9162f1ae CHECK ((char_length(image) <= 2048)), CONSTRAINT check_73884a5839 CHECK ((num_nonnulls(namespace_id, project_id) = 1)), - CONSTRAINT check_ec723e2a1a CHECK ((char_length(workflow_definition) <= 255)) + CONSTRAINT check_ec723e2a1a CHECK ((char_length(workflow_definition) <= 255)), + CONSTRAINT check_workflows_single_noteable CHECK ((num_nonnulls(issue_id, merge_request_id) <= 1)) ); CREATE SEQUENCE duo_workflows_workflows_id_seq @@ -40247,6 +40250,10 @@ CREATE INDEX index_duo_workflows_events_on_workflow_id ON duo_workflows_events U CREATE INDEX index_duo_workflows_workflows_on_ai_catalog_item_version_id ON duo_workflows_workflows USING btree (ai_catalog_item_version_id); +CREATE INDEX index_duo_workflows_workflows_on_issue_id ON duo_workflows_workflows USING btree (issue_id); + +CREATE INDEX index_duo_workflows_workflows_on_merge_request_id ON duo_workflows_workflows USING btree (merge_request_id); + CREATE INDEX index_duo_workflows_workflows_on_namespace_id ON duo_workflows_workflows USING btree (namespace_id); CREATE INDEX index_duo_workflows_workflows_on_project_id ON duo_workflows_workflows USING btree (project_id); @@ -50242,6 +50249,9 @@ ALTER TABLE ONLY packages_helm_file_metadata ALTER TABLE ONLY bulk_import_failures ADD CONSTRAINT fk_dad28985ee FOREIGN KEY (namespace_id) REFERENCES namespaces(id) ON DELETE CASCADE; +ALTER TABLE ONLY duo_workflows_workflows + ADD CONSTRAINT fk_daffbfef9a FOREIGN KEY (issue_id) REFERENCES issues(id) ON DELETE CASCADE; + ALTER TABLE ONLY project_topics ADD CONSTRAINT fk_db13576296 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE; @@ -50413,6 +50423,9 @@ ALTER TABLE ONLY merge_requests_compliance_violations ALTER TABLE ONLY issue_emails ADD CONSTRAINT fk_ed0f4c4b51 FOREIGN KEY (namespace_id) REFERENCES namespaces(id) ON DELETE CASCADE; +ALTER TABLE ONLY duo_workflows_workflows + ADD CONSTRAINT fk_ed58162ace FOREIGN KEY (merge_request_id) REFERENCES merge_requests(id) ON DELETE CASCADE; + ALTER TABLE ONLY cluster_agent_migrations ADD CONSTRAINT fk_ed8ffda028 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE; diff --git a/ee/app/models/ai/duo_workflows/workflow.rb b/ee/app/models/ai/duo_workflows/workflow.rb index 194f4a0cbdcaa13cd04cd6045708a9692cc6cab0..c0f61ddc142e6fb59ce655d1b1d4c034fb15a2bc 100644 --- a/ee/app/models/ai/duo_workflows/workflow.rb +++ b/ee/app/models/ai/duo_workflows/workflow.rb @@ -14,6 +14,8 @@ class Workflow < ::ApplicationRecord belongs_to :project, optional: true belongs_to :namespace, optional: true belongs_to :ai_catalog_item_version, optional: true, class_name: 'Ai::Catalog::ItemVersion' + belongs_to :issue, optional: true + belongs_to :merge_request, optional: true has_many :checkpoints, class_name: 'Ai::DuoWorkflows::Checkpoint' has_many :checkpoint_writes, class_name: 'Ai::DuoWorkflows::CheckpointWrite' diff --git a/ee/spec/models/ai/duo_workflows/workflow_spec.rb b/ee/spec/models/ai/duo_workflows/workflow_spec.rb index 3eb7095501510bf55702e02d4a03153dfaf6a0e0..3e9af9234dd0732ec28193ffdc2483a6f6f36490 100644 --- a/ee/spec/models/ai/duo_workflows/workflow_spec.rb +++ b/ee/spec/models/ai/duo_workflows/workflow_spec.rb @@ -14,6 +14,8 @@ it { is_expected.to have_many(:checkpoint_writes).class_name('Ai::DuoWorkflows::CheckpointWrite') } it { is_expected.to belong_to(:project).optional } it { is_expected.to belong_to(:namespace).optional } + it { is_expected.to belong_to(:issue).optional } + it { is_expected.to belong_to(:merge_request).optional } it { is_expected.to belong_to(:ai_catalog_item_version).optional } it { is_expected.to belong_to(:ai_catalog_item_version).class_name('Ai::Catalog::ItemVersion') }