diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2024-01-11 15:09:29 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2024-01-11 15:09:29 +0300 |
commit | 97feef1f73fd0a3237d1a2aef4e977e7e27ecace (patch) | |
tree | 4153af3602f242ed1a138fe70bd843a2564dab19 | |
parent | 6f5be4b446db2f17fc0307c4fce8ae285b35d89a (diff) |
Add latest changes from gitlab-org/gitlab@master
91 files changed, 1164 insertions, 192 deletions
@@ -425,7 +425,7 @@ group :development, :test do gem 'awesome_print', require: false # rubocop:todo Gemfile/MissingFeatureCategory gem 'database_cleaner-active_record', '~> 2.1.0', feature_category: :database - gem 'factory_bot_rails', '~> 6.2.0' # rubocop:todo Gemfile/MissingFeatureCategory + gem 'factory_bot_rails', '~> 6.4.3' # rubocop:todo Gemfile/MissingFeatureCategory gem 'rspec-rails', '~> 6.1.0', feature_category: :shared # Prevent occasions where minitest is not bundled in packaged versions of ruby (see #3826) diff --git a/Gemfile.checksum b/Gemfile.checksum index 1b529e0a14f..45c0a47eb63 100644 --- a/Gemfile.checksum +++ b/Gemfile.checksum @@ -155,8 +155,8 @@ {"name":"expgen","version":"0.1.1","platform":"ruby","checksum":"4e6a0f65b210a201d6045debb3e62a24e33251a49f81a11b067d303a60d3a239"}, {"name":"expression_parser","version":"0.9.0","platform":"ruby","checksum":"2b56db3cffc48c3337f4f29f5bc2374c86e7ba29acb40269c74bb55af9f868a4"}, {"name":"extended-markdown-filter","version":"0.7.0","platform":"ruby","checksum":"c8eeef7409fbae18c6b407cd3e4eeb5d25c35cb08fe1ac06f375df3db2d4f138"}, -{"name":"factory_bot","version":"6.2.0","platform":"ruby","checksum":"d181902cdda531cf6cef036001b3a700a7b5e04bac63976864530120b2ac7d13"}, -{"name":"factory_bot_rails","version":"6.2.0","platform":"ruby","checksum":"278b969666b078e76e1c972c501da9b1fac15e5b0ff328cc7ce400366164d0a1"}, +{"name":"factory_bot","version":"6.4.5","platform":"ruby","checksum":"d71dd29bc95f0ec2bf27e3dd9b1b4d557bd534caca744663cb7db4bacf3198be"}, +{"name":"factory_bot_rails","version":"6.4.3","platform":"ruby","checksum":"ea73ceac1c0ff3dc11fff390bf2ea8a2604066525ed8ecd3b3bc2c267226dcc8"}, {"name":"faraday","version":"1.10.0","platform":"ruby","checksum":"a42158d5c1932c16fd483c512f7e0797b4916096bcf0eb5fb927a1c915a7ea02"}, {"name":"faraday-em_http","version":"1.0.0","platform":"ruby","checksum":"7a3d4c7079789121054f57e08cd4ef7e40ad1549b63101f38c7093a9d6c59689"}, {"name":"faraday-em_synchrony","version":"1.0.0","platform":"ruby","checksum":"460dad1c30cc692d6e77d4c391ccadb4eca4854b315632cd7e560f74275cf9ed"}, diff --git a/Gemfile.lock b/Gemfile.lock index b087aedf845..f124754654b 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -553,10 +553,10 @@ GEM expression_parser (0.9.0) extended-markdown-filter (0.7.0) html-pipeline (~> 2.9) - factory_bot (6.2.0) + factory_bot (6.4.5) activesupport (>= 5.0.0) - factory_bot_rails (6.2.0) - factory_bot (~> 6.2.0) + factory_bot_rails (6.4.3) + factory_bot (~> 6.4) railties (>= 5.0.0) faraday (1.10.0) faraday-em_http (~> 1.0) @@ -1870,7 +1870,7 @@ DEPENDENCIES email_reply_trimmer (~> 0.1) email_spec (~> 2.2.0) error_tracking_open_api! - factory_bot_rails (~> 6.2.0) + factory_bot_rails (~> 6.4.3) faraday (~> 1.0) faraday_middleware-aws-sigv4 (~> 0.3.0) fast_blank (~> 1.0.1) diff --git a/app/assets/javascripts/work_items/components/notes/work_item_comment_form.vue b/app/assets/javascripts/work_items/components/notes/work_item_comment_form.vue index 1e6bd9ff1ac..9ede327b2f1 100644 --- a/app/assets/javascripts/work_items/components/notes/work_item_comment_form.vue +++ b/app/assets/javascripts/work_items/components/notes/work_item_comment_form.vue @@ -235,7 +235,9 @@ export default { :work-item-id="workItemId" :work-item-state="workItemState" :work-item-type="workItemType" + :has-comment="!!commentText.length" can-update + @submit-comment="$emit('submitForm', { commentText, isNoteInternal })" @error="$emit('error', $event)" /> <gl-button diff --git a/app/assets/javascripts/work_items/components/work_item_state_toggle.vue b/app/assets/javascripts/work_items/components/work_item_state_toggle.vue index 69752967efe..48884be54f6 100644 --- a/app/assets/javascripts/work_items/components/work_item_state_toggle.vue +++ b/app/assets/javascripts/work_items/components/work_item_state_toggle.vue @@ -38,6 +38,11 @@ export default { required: false, default: false, }, + hasComment: { + type: Boolean, + required: false, + default: false, + }, }, data() { return { @@ -49,9 +54,15 @@ export default { return this.workItemState === STATE_OPEN; }, toggleWorkItemStateText() { - const baseText = this.isWorkItemOpen + let baseText = this.isWorkItemOpen ? __('Close %{workItemType}') : __('Reopen %{workItemType}'); + + if (this.hasComment) { + baseText = this.isWorkItemOpen + ? __('Comment & close %{workItemType}') + : __('Comment & reopen %{workItemType}'); + } return sprintfWorkItem(baseText, this.workItemType); }, tracking() { @@ -96,6 +107,10 @@ export default { Sentry.captureException(error); } + if (this.hasComment) { + this.$emit('submit-comment'); + } + this.updateInProgress = false; }, }, diff --git a/app/controllers/admin/ci/variables_controller.rb b/app/controllers/admin/ci/variables_controller.rb index 4ab67e54766..1085de6fa05 100644 --- a/app/controllers/admin/ci/variables_controller.rb +++ b/app/controllers/admin/ci/variables_controller.rb @@ -44,7 +44,7 @@ module Admin end def variable_params_attributes - %i[id variable_type key secret_value protected masked raw _destroy] + %i[id variable_type key description secret_value protected masked raw _destroy] end end end diff --git a/app/controllers/groups/variables_controller.rb b/app/controllers/groups/variables_controller.rb index fad3a6ab9f5..d27d70dc857 100644 --- a/app/controllers/groups/variables_controller.rb +++ b/app/controllers/groups/variables_controller.rb @@ -50,7 +50,7 @@ module Groups end def variable_params_attributes - %i[id variable_type key secret_value protected masked raw _destroy] + %i[id variable_type key description secret_value protected masked raw _destroy] end def authorize_admin_build! diff --git a/app/controllers/projects/variables_controller.rb b/app/controllers/projects/variables_controller.rb index f7542d68642..29ecca1b7e0 100644 --- a/app/controllers/projects/variables_controller.rb +++ b/app/controllers/projects/variables_controller.rb @@ -47,6 +47,6 @@ class Projects::VariablesController < Projects::ApplicationController end def variable_params_attributes - %i[id variable_type key secret_value protected masked raw environment_scope _destroy] + %i[id variable_type key description secret_value protected masked raw environment_scope _destroy] end end diff --git a/app/graphql/types/ci/inherited_ci_variable_type.rb b/app/graphql/types/ci/inherited_ci_variable_type.rb index 2d8dcdaeefe..c90e34b25dd 100644 --- a/app/graphql/types/ci/inherited_ci_variable_type.rb +++ b/app/graphql/types/ci/inherited_ci_variable_type.rb @@ -15,6 +15,10 @@ module Types null: true, description: 'Name of the variable.' + field :description, GraphQL::Types::String, + null: true, + description: 'Description of the variable.' + field :raw, GraphQL::Types::Boolean, null: true, description: 'Indicates whether the variable is raw.' diff --git a/app/graphql/types/ci/instance_variable_type.rb b/app/graphql/types/ci/instance_variable_type.rb index e3230556769..457cd8a1ba2 100644 --- a/app/graphql/types/ci/instance_variable_type.rb +++ b/app/graphql/types/ci/instance_variable_type.rb @@ -13,6 +13,10 @@ module Types null: false, description: 'ID of the variable.' + field :description, GraphQL::Types::String, + null: true, + description: 'Description of the variable.' + field :environment_scope, GraphQL::Types::String, null: true, deprecated: { diff --git a/app/models/bulk_imports/entity.rb b/app/models/bulk_imports/entity.rb index 894e28dd88a..a6969ce6f76 100644 --- a/app/models/bulk_imports/entity.rb +++ b/app/models/bulk_imports/entity.rb @@ -150,9 +150,9 @@ class BulkImports::Entity < ApplicationRecord File.join(base_resource_path, 'export_relations') end - def export_relations_url_path(batched: false) - if batched && bulk_import.supports_batched_export? - Gitlab::Utils.add_url_parameters(export_relations_url_path_base, batched: batched) + def export_relations_url_path + if bulk_import.supports_batched_export? + Gitlab::Utils.add_url_parameters(export_relations_url_path_base, batched: true) else export_relations_url_path_base end diff --git a/app/models/ci/instance_variable.rb b/app/models/ci/instance_variable.rb index 179befb8469..6a2fb1132c0 100644 --- a/app/models/ci/instance_variable.rb +++ b/app/models/ci/instance_variable.rb @@ -13,6 +13,7 @@ module Ci alias_attribute :secret_value, :value + validates :description, length: { maximum: 255 }, allow_blank: true validates :key, uniqueness: { message: -> (object, data) { _("(%{value}) has already been taken") } } diff --git a/app/models/ci/pipeline_artifact.rb b/app/models/ci/pipeline_artifact.rb index 6d22a875aab..e0e6906f211 100644 --- a/app/models/ci/pipeline_artifact.rb +++ b/app/models/ci/pipeline_artifact.rb @@ -4,6 +4,7 @@ module Ci class PipelineArtifact < Ci::ApplicationRecord + include Ci::Partitionable include UpdateProjectStatistics include Artifactable include FileStoreMounter @@ -31,6 +32,8 @@ module Ci validates :size, presence: true, numericality: { less_than_or_equal_to: FILE_SIZE_LIMIT } validates :file_type, presence: true + partitionable scope: :pipeline + mount_file_store_uploader Ci::PipelineArtifactUploader update_project_statistics project_statistics_name: :pipeline_artifacts_size diff --git a/app/models/ci/pipeline_metadata.rb b/app/models/ci/pipeline_metadata.rb index a41cdf61b71..21d102374f0 100644 --- a/app/models/ci/pipeline_metadata.rb +++ b/app/models/ci/pipeline_metadata.rb @@ -2,6 +2,9 @@ module Ci class PipelineMetadata < Ci::ApplicationRecord + include Ci::Partitionable + include Importable + self.primary_key = :pipeline_id enum auto_cancel_on_new_commit: { @@ -21,5 +24,7 @@ module Ci validates :pipeline, presence: true validates :project, presence: true validates :name, length: { minimum: 1, maximum: 255 }, allow_nil: true + + partitionable scope: :pipeline end end diff --git a/app/models/concerns/ci/partitionable/testing.rb b/app/models/concerns/ci/partitionable/testing.rb index cea46e9f1b6..86a7d5fcf38 100644 --- a/app/models/concerns/ci/partitionable/testing.rb +++ b/app/models/concerns/ci/partitionable/testing.rb @@ -21,7 +21,9 @@ module Ci Ci::PendingBuild Ci::RunningBuild Ci::RunnerManagerBuild + Ci::PipelineArtifact Ci::PipelineChatData + Ci::PipelineMetadata Ci::PipelineVariable Ci::Sources::Pipeline Ci::Stage diff --git a/app/serializers/ci/basic_variable_entity.rb b/app/serializers/ci/basic_variable_entity.rb index 210c01408a6..5907bf0f29c 100644 --- a/app/serializers/ci/basic_variable_entity.rb +++ b/app/serializers/ci/basic_variable_entity.rb @@ -5,6 +5,7 @@ module Ci expose :id expose :key expose :value + expose :description expose :variable_type expose :protected?, as: :protected diff --git a/app/workers/bulk_imports/export_request_worker.rb b/app/workers/bulk_imports/export_request_worker.rb index bfe561cca5c..5204db2159d 100644 --- a/app/workers/bulk_imports/export_request_worker.rb +++ b/app/workers/bulk_imports/export_request_worker.rb @@ -75,7 +75,7 @@ module BulkImports ::GlobalID.parse(response.dig(*entity_query.data_path, 'id')).model_id rescue StandardError => e - log_exception(e, message: 'Failed to fetch source entity id') + log_warning(e, message: 'Failed to fetch source entity id') nil end @@ -92,14 +92,21 @@ module BulkImports @logger ||= Logger.build.with_entity(entity) end - def log_exception(exception, payload) + def build_payload(exception, payload) Gitlab::ExceptionLogFormatter.format!(exception, payload) + structured_payload(payload) + end + + def log_warning(exception, payload) + logger.warn(build_payload(exception, payload)) + end - logger.error(structured_payload(payload)) + def log_error(exception, payload) + logger.error(build_payload(exception, payload)) end def log_and_fail(exception) - log_exception(exception, message: "Request to export #{entity.source_type} failed") + log_error(exception, message: "Request to export #{entity.source_type} failed") BulkImports::Failure.create(failure_attributes(exception)) @@ -107,7 +114,7 @@ module BulkImports end def export_url - entity.export_relations_url_path(batched: Feature.enabled?(:bulk_imports_batched_import_export)) + entity.export_relations_url_path end end end diff --git a/app/workers/click_house/event_authors_consistency_cron_worker.rb b/app/workers/click_house/event_authors_consistency_cron_worker.rb index 5c52cda0204..c35aadba593 100644 --- a/app/workers/click_house/event_authors_consistency_cron_worker.rb +++ b/app/workers/click_house/event_authors_consistency_cron_worker.rb @@ -103,14 +103,14 @@ module ClickHouse def delete_records_from_click_house(ids) query = ClickHouse::Client::Query.new( - raw_query: "DELETE FROM events WHERE author_id IN ({author_ids:Array(UInt64)})", + raw_query: "ALTER TABLE events DELETE WHERE author_id IN ({author_ids:Array(UInt64)})", placeholders: { author_ids: ids.to_json } ) connection.execute(query) query = ClickHouse::Client::Query.new( - raw_query: "DELETE FROM event_authors WHERE author_id IN ({author_ids:Array(UInt64)})", + raw_query: "ALTER TABLE event_authors DELETE WHERE author_id IN ({author_ids:Array(UInt64)})", placeholders: { author_ids: ids.to_json } ) diff --git a/app/workers/concerns/gitlab/github_import/object_importer.rb b/app/workers/concerns/gitlab/github_import/object_importer.rb index 22bbc563272..da0a54c79f8 100644 --- a/app/workers/concerns/gitlab/github_import/object_importer.rb +++ b/app/workers/concerns/gitlab/github_import/object_importer.rb @@ -53,9 +53,7 @@ module Gitlab importer_class.new(object, project, client).execute - if increment_object_counter?(object) - Gitlab::GithubImport::ObjectCounter.increment(project, object_type, :imported) - end + increment_object_counter(object, project) if increment_object_counter?(object) info(project.id, message: 'importer finished') rescue ActiveRecord::RecordInvalid, NotRetriableError, NoMethodError => e @@ -73,6 +71,10 @@ module Gitlab true end + def increment_object_counter(_object, project) + Gitlab::GithubImport::ObjectCounter.increment(project, object_type, :imported) + end + def object_type raise NotImplementedError end diff --git a/app/workers/gitlab/github_import/import_issue_event_worker.rb b/app/workers/gitlab/github_import/import_issue_event_worker.rb index d7071d3ee09..f5e88787a77 100644 --- a/app/workers/gitlab/github_import/import_issue_event_worker.rb +++ b/app/workers/gitlab/github_import/import_issue_event_worker.rb @@ -16,6 +16,16 @@ module Gitlab def object_type :issue_event end + + def increment_object_counter(object, project) + counter_type = importer_class::EVENT_COUNTER_MAP[object[:event]] if import_settings.extended_events? + counter_type ||= object_type + Gitlab::GithubImport::ObjectCounter.increment(project, counter_type, :imported) + end + + def import_settings + @import_settings ||= Gitlab::GithubImport::Settings.new(project) + end end end end diff --git a/config/feature_flags/beta/container_scanning_continuous_vulnerability_scans.yml b/config/feature_flags/beta/container_scanning_continuous_vulnerability_scans.yml new file mode 100644 index 00000000000..0169f3949c9 --- /dev/null +++ b/config/feature_flags/beta/container_scanning_continuous_vulnerability_scans.yml @@ -0,0 +1,9 @@ +--- +name: container_scanning_continuous_vulnerability_scans +feature_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/435435 +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/141023 +rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/437162 +milestone: '16.8' +group: group::composition analysis +type: beta +default_enabled: false diff --git a/config/feature_flags/development/bulk_imports_batched_import_export.yml b/config/feature_flags/development/bulk_imports_batched_import_export.yml deleted file mode 100644 index bf114b6d0a8..00000000000 --- a/config/feature_flags/development/bulk_imports_batched_import_export.yml +++ /dev/null @@ -1,8 +0,0 @@ ---- -name: bulk_imports_batched_import_export -introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/124434 -rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/406559 -milestone: '16.2' -type: development -group: group::import and integrate -default_enabled: true diff --git a/db/docs/batched_background_migrations/backfill_partition_id_ci_pipeline_artifact.yml b/db/docs/batched_background_migrations/backfill_partition_id_ci_pipeline_artifact.yml new file mode 100644 index 00000000000..18a4ac13db1 --- /dev/null +++ b/db/docs/batched_background_migrations/backfill_partition_id_ci_pipeline_artifact.yml @@ -0,0 +1,9 @@ +--- +migration_job_name: BackfillPartitionIdCiPipelineArtifact +description: Fixes incorrect values for ci_pipeline_artifacts being in the wrong partition +feature_category: continuous_integration +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/141345 +milestone: '16.8' +queued_migration_version: 20240109090354 +finalize_after: '2024-01-22' +finalized_by: # version of the migration that finalized this BBM diff --git a/db/docs/batched_background_migrations/backfill_partition_id_ci_pipeline_metadata.yml b/db/docs/batched_background_migrations/backfill_partition_id_ci_pipeline_metadata.yml new file mode 100644 index 00000000000..a56fcfd4cca --- /dev/null +++ b/db/docs/batched_background_migrations/backfill_partition_id_ci_pipeline_metadata.yml @@ -0,0 +1,9 @@ +--- +migration_job_name: BackfillPartitionIdCiPipelineMetadata +description: Fixes incorrect values for ci_pipeline_metadata being in the wrong partition +feature_category: continuous_integration +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/141078 +milestone: '16.8' +queued_migration_version: 20240108082419 +finalize_after: '2024-01-15' +finalized_by: # version of the migration that finalized this BBM diff --git a/db/migrate/20231222071942_add_description_to_ci_instance_variables.rb b/db/migrate/20231222071942_add_description_to_ci_instance_variables.rb new file mode 100644 index 00000000000..e71f27411eb --- /dev/null +++ b/db/migrate/20231222071942_add_description_to_ci_instance_variables.rb @@ -0,0 +1,12 @@ +# frozen_string_literal: true + +class AddDescriptionToCiInstanceVariables < Gitlab::Database::Migration[2.2] + milestone '16.8' + enable_lock_retries! + + # rubocop:disable Migration/AddLimitToTextColumns -- text limit is added in 20231222072237_add_text_limit_to_ci_instance_variables_description.rb migration + def change + add_column(:ci_instance_variables, :description, :text) + end + # rubocop:enable Migration/AddLimitToTextColumns +end diff --git a/db/migrate/20240104150106_add_partition_id_to_pipeline_metadata.rb b/db/migrate/20240104150106_add_partition_id_to_pipeline_metadata.rb new file mode 100644 index 00000000000..cdada059306 --- /dev/null +++ b/db/migrate/20240104150106_add_partition_id_to_pipeline_metadata.rb @@ -0,0 +1,10 @@ +# frozen_string_literal: true + +class AddPartitionIdToPipelineMetadata < Gitlab::Database::Migration[2.2] + milestone '16.8' + enable_lock_retries! + + def change + add_column(:ci_pipeline_metadata, :partition_id, :bigint, default: 100, null: false) + end +end diff --git a/db/migrate/20240104191736_migrate_zoekt_indexed_namespaces_to_zoekt_enabled_namespaces.rb b/db/migrate/20240104191736_migrate_zoekt_indexed_namespaces_to_zoekt_enabled_namespaces.rb new file mode 100644 index 00000000000..3c3ef67e322 --- /dev/null +++ b/db/migrate/20240104191736_migrate_zoekt_indexed_namespaces_to_zoekt_enabled_namespaces.rb @@ -0,0 +1,30 @@ +# frozen_string_literal: true + +class MigrateZoektIndexedNamespacesToZoektEnabledNamespaces < Gitlab::Database::Migration[2.2] + disable_ddl_transaction! + + restrict_gitlab_migration gitlab_schema: :gitlab_main + + milestone '16.8' + + INSERTED_COLUMNS = %w[ + root_namespace_id + search + created_at + updated_at + ].join(',') + + def up + connection.execute(<<~SQL) + INSERT INTO zoekt_enabled_namespaces (#{INSERTED_COLUMNS}) + (SELECT DISTINCT ON (namespace_id) namespace_id, search, created_at, updated_at + FROM zoekt_indexed_namespaces ORDER BY namespace_id, search) + SQL + end + + def down + connection.execute(<<~SQL) + DELETE FROM zoekt_enabled_namespaces + SQL + end +end diff --git a/db/migrate/20240104191802_migrate_zoekt_indexed_namespaces_to_zoekt_indices.rb b/db/migrate/20240104191802_migrate_zoekt_indexed_namespaces_to_zoekt_indices.rb new file mode 100644 index 00000000000..5461ad5094b --- /dev/null +++ b/db/migrate/20240104191802_migrate_zoekt_indexed_namespaces_to_zoekt_indices.rb @@ -0,0 +1,46 @@ +# frozen_string_literal: true + +class MigrateZoektIndexedNamespacesToZoektIndices < Gitlab::Database::Migration[2.2] + disable_ddl_transaction! + + restrict_gitlab_migration gitlab_schema: :gitlab_main + + milestone '16.8' + + INSERTED_COLUMNS = %w[ + zoekt_enabled_namespace_id + namespace_id + zoekt_node_id + state + created_at + updated_at + ].join(',') + + STATE_READY = 10 + + def up + connection.execute(<<~SQL) + WITH indexed_namespaces AS ( + (SELECT DISTINCT ON (namespace_id) namespace_id, search, zoekt_node_id + FROM zoekt_indexed_namespaces ORDER BY namespace_id, search) + ) + + INSERT INTO zoekt_indices (#{INSERTED_COLUMNS}) + SELECT + zoekt_enabled_namespaces.id, + indexed_namespaces.namespace_id, + indexed_namespaces.zoekt_node_id, + #{STATE_READY}, + NOW(), + NOW() + FROM zoekt_enabled_namespaces + JOIN indexed_namespaces ON indexed_namespaces.namespace_id = zoekt_enabled_namespaces.root_namespace_id + SQL + end + + def down + connection.execute(<<~SQL) + DELETE FROM zoekt_indices + SQL + end +end diff --git a/db/migrate/20240109082354_add_partition_id_to_pipeline_artifact.rb b/db/migrate/20240109082354_add_partition_id_to_pipeline_artifact.rb new file mode 100644 index 00000000000..8a922aed648 --- /dev/null +++ b/db/migrate/20240109082354_add_partition_id_to_pipeline_artifact.rb @@ -0,0 +1,10 @@ +# frozen_string_literal: true + +class AddPartitionIdToPipelineArtifact < Gitlab::Database::Migration[2.2] + milestone '16.8' + enable_lock_retries! + + def change + add_column(:ci_pipeline_artifacts, :partition_id, :bigint, default: 100, null: false) + end +end diff --git a/db/post_migrate/20231222072237_add_text_limit_to_ci_instance_variables_description.rb b/db/post_migrate/20231222072237_add_text_limit_to_ci_instance_variables_description.rb new file mode 100644 index 00000000000..6ad13a591e4 --- /dev/null +++ b/db/post_migrate/20231222072237_add_text_limit_to_ci_instance_variables_description.rb @@ -0,0 +1,18 @@ +# frozen_string_literal: true + +class AddTextLimitToCiInstanceVariablesDescription < Gitlab::Database::Migration[2.2] + milestone '16.8' + + disable_ddl_transaction! + + TABLE_NAME = :ci_instance_variables + COLUMN_NAME = :description + + def up + add_text_limit(TABLE_NAME, COLUMN_NAME, 255) + end + + def down + remove_text_limit(TABLE_NAME, COLUMN_NAME) + end +end diff --git a/db/post_migrate/20240108082419_queue_backfill_partition_id_ci_pipeline_metadata.rb b/db/post_migrate/20240108082419_queue_backfill_partition_id_ci_pipeline_metadata.rb new file mode 100644 index 00000000000..6bcaf376a05 --- /dev/null +++ b/db/post_migrate/20240108082419_queue_backfill_partition_id_ci_pipeline_metadata.rb @@ -0,0 +1,26 @@ +# frozen_string_literal: true + +class QueueBackfillPartitionIdCiPipelineMetadata < Gitlab::Database::Migration[2.2] + milestone '16.8' + restrict_gitlab_migration gitlab_schema: :gitlab_ci + + MIGRATION = 'BackfillPartitionIdCiPipelineMetadata' + DELAY_INTERVAL = 2.minutes + BATCH_SIZE = 1000 + SUB_BATCH_SIZE = 250 + + def up + queue_batched_background_migration( + MIGRATION, + :ci_pipeline_metadata, + :pipeline_id, + job_interval: DELAY_INTERVAL, + batch_size: BATCH_SIZE, + sub_batch_size: SUB_BATCH_SIZE + ) + end + + def down + delete_batched_background_migration(MIGRATION, :ci_pipeline_metadata, :pipeline_id, []) + end +end diff --git a/db/post_migrate/20240109090354_queue_backfill_partition_id_ci_pipeline_artifact.rb b/db/post_migrate/20240109090354_queue_backfill_partition_id_ci_pipeline_artifact.rb new file mode 100644 index 00000000000..30959a299fb --- /dev/null +++ b/db/post_migrate/20240109090354_queue_backfill_partition_id_ci_pipeline_artifact.rb @@ -0,0 +1,26 @@ +# frozen_string_literal: true + +class QueueBackfillPartitionIdCiPipelineArtifact < Gitlab::Database::Migration[2.2] + milestone '16.8' + restrict_gitlab_migration gitlab_schema: :gitlab_ci + + MIGRATION = 'BackfillPartitionIdCiPipelineArtifact' + DELAY_INTERVAL = 2.minutes + BATCH_SIZE = 1000 + SUB_BATCH_SIZE = 100 + + def up + queue_batched_background_migration( + MIGRATION, + :ci_pipeline_artifacts, + :id, + job_interval: DELAY_INTERVAL, + batch_size: BATCH_SIZE, + sub_batch_size: SUB_BATCH_SIZE + ) + end + + def down + delete_batched_background_migration(MIGRATION, :ci_pipeline_artifacts, :id, []) + end +end diff --git a/db/schema_migrations/20231222071942 b/db/schema_migrations/20231222071942 new file mode 100644 index 00000000000..cc33e2239e2 --- /dev/null +++ b/db/schema_migrations/20231222071942 @@ -0,0 +1 @@ +187b2c6e79e0f9e4636923f646ef9b5b5c609cb1797dac6265a1aa12e2a46f31
\ No newline at end of file diff --git a/db/schema_migrations/20231222072237 b/db/schema_migrations/20231222072237 new file mode 100644 index 00000000000..4c71203247b --- /dev/null +++ b/db/schema_migrations/20231222072237 @@ -0,0 +1 @@ +c92fb56354f4471103cb34f0a49294961a221dde5ecea72b0f132fdd1c813095
\ No newline at end of file diff --git a/db/schema_migrations/20240104150106 b/db/schema_migrations/20240104150106 new file mode 100644 index 00000000000..d2e7dbf0590 --- /dev/null +++ b/db/schema_migrations/20240104150106 @@ -0,0 +1 @@ +e6829ae7a671ff2c13c78721c9304bcbaa7738aea01d8e83aeac79d0da2d2a47
\ No newline at end of file diff --git a/db/schema_migrations/20240104191736 b/db/schema_migrations/20240104191736 new file mode 100644 index 00000000000..8072f3c5bfa --- /dev/null +++ b/db/schema_migrations/20240104191736 @@ -0,0 +1 @@ +92f7eddc8ba255987adc42e1140b47256c62235762f431ba8047561f120004dc
\ No newline at end of file diff --git a/db/schema_migrations/20240104191802 b/db/schema_migrations/20240104191802 new file mode 100644 index 00000000000..36ad8605992 --- /dev/null +++ b/db/schema_migrations/20240104191802 @@ -0,0 +1 @@ +eb3a7d14833470fe74420874ed883428d54a4d1a24a7f131f2049bf2f7efa929
\ No newline at end of file diff --git a/db/schema_migrations/20240108082419 b/db/schema_migrations/20240108082419 new file mode 100644 index 00000000000..8286b90e678 --- /dev/null +++ b/db/schema_migrations/20240108082419 @@ -0,0 +1 @@ +273a951feb99c6064529c3a4403210ec0ff4a0be41867b7b90809b89fd767f5d
\ No newline at end of file diff --git a/db/schema_migrations/20240109082354 b/db/schema_migrations/20240109082354 new file mode 100644 index 00000000000..37ffffb7267 --- /dev/null +++ b/db/schema_migrations/20240109082354 @@ -0,0 +1 @@ +b264b391bc50ede33db98df9e1e54a074c850e2e4af0c5bd380ce1f32646c95b
\ No newline at end of file diff --git a/db/schema_migrations/20240109090354 b/db/schema_migrations/20240109090354 new file mode 100644 index 00000000000..26f68dd746a --- /dev/null +++ b/db/schema_migrations/20240109090354 @@ -0,0 +1 @@ +7420ebb45a2ef0f82527b7427ec741bf8807efb966c317a9fedfda5c04fb4947
\ No newline at end of file diff --git a/db/structure.sql b/db/structure.sql index d7fe66a0086..bd165b96799 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -14344,9 +14344,11 @@ CREATE TABLE ci_instance_variables ( encrypted_value text, encrypted_value_iv text, raw boolean DEFAULT false NOT NULL, + description text, CONSTRAINT check_07a45a5bcb CHECK ((char_length(encrypted_value_iv) <= 255)), CONSTRAINT check_5aede12208 CHECK ((char_length(key) <= 255)), - CONSTRAINT check_956afd70f1 CHECK ((char_length(encrypted_value) <= 13579)) + CONSTRAINT check_956afd70f1 CHECK ((char_length(encrypted_value) <= 13579)), + CONSTRAINT check_a0a9762afa CHECK ((char_length(description) <= 255)) ); CREATE SEQUENCE ci_instance_variables_id_seq @@ -14554,6 +14556,7 @@ CREATE TABLE ci_pipeline_artifacts ( verification_checksum bytea, verification_failure text, locked smallint DEFAULT 2, + partition_id bigint DEFAULT 100 NOT NULL, CONSTRAINT check_191b5850ec CHECK ((char_length(file) <= 255)), CONSTRAINT check_abeeb71caf CHECK ((file IS NOT NULL)), CONSTRAINT ci_pipeline_artifacts_verification_failure_text_limit CHECK ((char_length(verification_failure) <= 255)) @@ -14608,6 +14611,7 @@ CREATE TABLE ci_pipeline_metadata ( name text, auto_cancel_on_new_commit smallint DEFAULT 0 NOT NULL, auto_cancel_on_job_failure smallint DEFAULT 0 NOT NULL, + partition_id bigint DEFAULT 100 NOT NULL, CONSTRAINT check_9d3665463c CHECK ((char_length(name) <= 255)) ); diff --git a/doc/administration/reference_architectures/10k_users.md b/doc/administration/reference_architectures/10k_users.md index f4492488a23..41897a999ec 100644 --- a/doc/administration/reference_architectures/10k_users.md +++ b/doc/administration/reference_architectures/10k_users.md @@ -1889,6 +1889,15 @@ Updates to example must be made at: 'google_json_key_location' => '<path-to-gcp-service-account-key>' } gitlab_rails['backup_upload_remote_directory'] = "<gcp-backups-state-bucket-name>" + + gitlab_rails['ci_secure_files_object_store_enabled'] = true + gitlab_rails['ci_secure_files_object_store_remote_directory'] = "gcp-ci_secure_files-bucket-name" + + gitlab_rails['ci_secure_files_object_store_connection'] = { + 'provider' => 'Google', + 'google_project' => '<gcp-project-name>', + 'google_json_key_location' => '<path-to-gcp-service-account-key>' + } ``` 1. Copy the `/etc/gitlab/gitlab-secrets.json` file from the first Linux package node you configured and add or replace @@ -2027,6 +2036,14 @@ On each node perform the following: 'google_json_key_location' => '<path-to-gcp-service-account-key>' } gitlab_rails['backup_upload_remote_directory'] = "<gcp-backups-state-bucket-name>" + gitlab_rails['ci_secure_files_object_store_enabled'] = true + gitlab_rails['ci_secure_files_object_store_remote_directory'] = "gcp-ci_secure_files-bucket-name" + + gitlab_rails['ci_secure_files_object_store_connection'] = { + 'provider' => 'Google', + 'google_project' => '<gcp-project-name>', + 'google_json_key_location' => '<path-to-gcp-service-account-key>' + } ``` 1. If you're using [Gitaly with TLS support](#gitaly-cluster-tls-support), make sure the diff --git a/doc/administration/reference_architectures/25k_users.md b/doc/administration/reference_architectures/25k_users.md index 21a21370c8f..2f0b51e6662 100644 --- a/doc/administration/reference_architectures/25k_users.md +++ b/doc/administration/reference_architectures/25k_users.md @@ -1897,6 +1897,15 @@ Updates to example must be made at: 'google_json_key_location' => '<path-to-gcp-service-account-key>' } gitlab_rails['backup_upload_remote_directory'] = "<gcp-backups-state-bucket-name>" + + gitlab_rails['ci_secure_files_object_store_enabled'] = true + gitlab_rails['ci_secure_files_object_store_remote_directory'] = "gcp-ci_secure_files-bucket-name" + + gitlab_rails['ci_secure_files_object_store_connection'] = { + 'provider' => 'Google', + 'google_project' => '<gcp-project-name>', + 'google_json_key_location' => '<path-to-gcp-service-account-key>' + } ``` 1. Copy the `/etc/gitlab/gitlab-secrets.json` file from the first Linux package node you configured and add or replace @@ -2037,6 +2046,14 @@ On each node perform the following: 'google_json_key_location' => '<path-to-gcp-service-account-key>' } gitlab_rails['backup_upload_remote_directory'] = "<gcp-backups-state-bucket-name>" + gitlab_rails['ci_secure_files_object_store_enabled'] = true + gitlab_rails['ci_secure_files_object_store_remote_directory'] = "gcp-ci_secure_files-bucket-name" + + gitlab_rails['ci_secure_files_object_store_connection'] = { + 'provider' => 'Google', + 'google_project' => '<gcp-project-name>', + 'google_json_key_location' => '<path-to-gcp-service-account-key>' + } ``` 1. If you're using [Gitaly with TLS support](#gitaly-cluster-tls-support), make sure the diff --git a/doc/administration/reference_architectures/2k_users.md b/doc/administration/reference_architectures/2k_users.md index 4c020f4d698..dd71190b76d 100644 --- a/doc/administration/reference_architectures/2k_users.md +++ b/doc/administration/reference_architectures/2k_users.md @@ -694,6 +694,14 @@ Updates to example must be made at: 'google_json_key_location' => '<path-to-gcp-service-account-key>' } gitlab_rails['backup_upload_remote_directory'] = "<gcp-backups-state-bucket-name>" + gitlab_rails['ci_secure_files_object_store_enabled'] = true + gitlab_rails['ci_secure_files_object_store_remote_directory'] = "gcp-ci_secure_files-bucket-name" + + gitlab_rails['ci_secure_files_object_store_connection'] = { + 'provider' => 'Google', + 'google_project' => '<gcp-project-name>', + 'google_json_key_location' => '<path-to-gcp-service-account-key>' + } ``` 1. Copy the `/etc/gitlab/gitlab-secrets.json` file from the first Linux package node you configured and add or replace @@ -822,6 +830,15 @@ On each node perform the following: } gitlab_rails['backup_upload_remote_directory'] = "<gcp-backups-state-bucket-name>" + gitlab_rails['ci_secure_files_object_store_enabled'] = true + gitlab_rails['ci_secure_files_object_store_remote_directory'] = "gcp-ci_secure_files-bucket-name" + + gitlab_rails['ci_secure_files_object_store_connection'] = { + 'provider' => 'Google', + 'google_project' => '<gcp-project-name>', + 'google_json_key_location' => '<path-to-gcp-service-account-key>' + } + ## Uncomment and edit the following options if you have set up NFS ## ## Prevent GitLab from starting if NFS data mounts are not available diff --git a/doc/administration/reference_architectures/3k_users.md b/doc/administration/reference_architectures/3k_users.md index 9cfe0f2e3f6..5d0ab62d4a2 100644 --- a/doc/administration/reference_architectures/3k_users.md +++ b/doc/administration/reference_architectures/3k_users.md @@ -1812,6 +1812,15 @@ Updates to example must be made at: 'google_json_key_location' => '<path-to-gcp-service-account-key>' } gitlab_rails['backup_upload_remote_directory'] = "<gcp-backups-state-bucket-name>" + + gitlab_rails['ci_secure_files_object_store_enabled'] = true + gitlab_rails['ci_secure_files_object_store_remote_directory'] = "gcp-ci_secure_files-bucket-name" + + gitlab_rails['ci_secure_files_object_store_connection'] = { + 'provider' => 'Google', + 'google_project' => '<gcp-project-name>', + 'google_json_key_location' => '<path-to-gcp-service-account-key>' + } ``` 1. Copy the `/etc/gitlab/gitlab-secrets.json` file from the first Linux package node you configured and add or replace @@ -1976,6 +1985,14 @@ On each node perform the following: 'google_json_key_location' => '<path-to-gcp-service-account-key>' } gitlab_rails['backup_upload_remote_directory'] = "<gcp-backups-state-bucket-name>" + gitlab_rails['ci_secure_files_object_store_enabled'] = true + gitlab_rails['ci_secure_files_object_store_remote_directory'] = "gcp-ci_secure_files-bucket-name" + + gitlab_rails['ci_secure_files_object_store_connection'] = { + 'provider' => 'Google', + 'google_project' => '<gcp-project-name>', + 'google_json_key_location' => '<path-to-gcp-service-account-key>' + } ``` 1. If you're using [Gitaly with TLS support](#gitaly-cluster-tls-support), make sure the diff --git a/doc/administration/reference_architectures/50k_users.md b/doc/administration/reference_architectures/50k_users.md index 76428598d96..ed66620119e 100644 --- a/doc/administration/reference_architectures/50k_users.md +++ b/doc/administration/reference_architectures/50k_users.md @@ -1904,6 +1904,15 @@ Updates to example must be made at: 'google_json_key_location' => '<path-to-gcp-service-account-key>' } gitlab_rails['backup_upload_remote_directory'] = "<gcp-backups-state-bucket-name>" + + gitlab_rails['ci_secure_files_object_store_enabled'] = true + gitlab_rails['ci_secure_files_object_store_remote_directory'] = "gcp-ci_secure_files-bucket-name" + + gitlab_rails['ci_secure_files_object_store_connection'] = { + 'provider' => 'Google', + 'google_project' => '<gcp-project-name>', + 'google_json_key_location' => '<path-to-gcp-service-account-key>' + } ``` 1. Copy the `/etc/gitlab/gitlab-secrets.json` file from the first Linux package node you configured and add or replace @@ -2050,7 +2059,16 @@ On each node perform the following: 'google_project' => '<gcp-project-name>', 'google_json_key_location' => '<path-to-gcp-service-account-key>' } + gitlab_rails['backup_upload_remote_directory'] = "<gcp-backups-state-bucket-name>" + gitlab_rails['ci_secure_files_object_store_enabled'] = true + gitlab_rails['ci_secure_files_object_store_remote_directory'] = "gcp-ci_secure_files-bucket-name" + + gitlab_rails['ci_secure_files_object_store_connection'] = { + 'provider' => 'Google', + 'google_project' => '<gcp-project-name>', + 'google_json_key_location' => '<path-to-gcp-service-account-key>' + } ``` 1. If you're using [Gitaly with TLS support](#gitaly-cluster-tls-support), make sure the diff --git a/doc/administration/reference_architectures/5k_users.md b/doc/administration/reference_architectures/5k_users.md index 2b3d928d8f6..796ff3f2952 100644 --- a/doc/administration/reference_architectures/5k_users.md +++ b/doc/administration/reference_architectures/5k_users.md @@ -1803,6 +1803,15 @@ Updates to example must be made at: 'google_json_key_location' => '<path-to-gcp-service-account-key>' } gitlab_rails['backup_upload_remote_directory'] = "<gcp-backups-state-bucket-name>" + + gitlab_rails['ci_secure_files_object_store_enabled'] = true + gitlab_rails['ci_secure_files_object_store_remote_directory'] = "gcp-ci_secure_files-bucket-name" + + gitlab_rails['ci_secure_files_object_store_connection'] = { + 'provider' => 'Google', + 'google_project' => '<gcp-project-name>', + 'google_json_key_location' => '<path-to-gcp-service-account-key>' + } ``` 1. Copy the `/etc/gitlab/gitlab-secrets.json` file from the first Linux package node you configured and add or replace @@ -1960,7 +1969,15 @@ On each node perform the following: 'google_json_key_location' => '<path-to-gcp-service-account-key>' } gitlab_rails['backup_upload_remote_directory'] = "<gcp-backups-state-bucket-name>" + gitlab_rails['ci_secure_files_object_store_enabled'] = true + gitlab_rails['ci_secure_files_object_store_remote_directory'] = "gcp-ci_secure_files-bucket-name" + gitlab_rails['ci_secure_files_object_store_connection'] = { + 'provider' => 'Google', + 'google_project' => '<gcp-project-name>', + 'google_json_key_location' => '<path-to-gcp-service-account-key>' + } + ## Uncomment and edit the following options if you have set up NFS ## ## Prevent GitLab from starting if NFS data mounts are not available diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md index 02dde734f9a..e433277d560 100644 --- a/doc/api/graphql/reference/index.md +++ b/doc/api/graphql/reference/index.md @@ -15750,6 +15750,7 @@ CI/CD variables for a GitLab instance. | Name | Type | Description | | ---- | ---- | ----------- | +| <a id="ciinstancevariabledescription"></a>`description` | [`String`](#string) | Description of the variable. | | <a id="ciinstancevariableenvironmentscope"></a>`environmentScope` **{warning-solid}** | [`String`](#string) | **Deprecated** in 15.3. No longer used, only available for GroupVariableType and ProjectVariableType. | | <a id="ciinstancevariableid"></a>`id` | [`ID!`](#id) | ID of the variable. | | <a id="ciinstancevariablekey"></a>`key` | [`String`](#string) | Name of the variable. | @@ -16853,6 +16854,7 @@ The currently authenticated GitLab user. | <a id="currentusercommitemail"></a>`commitEmail` | [`String`](#string) | User's default commit email. | | <a id="currentusercreatedat"></a>`createdAt` | [`Time`](#time) | Timestamp of when the user was created. | | <a id="currentuserdiscord"></a>`discord` | [`String`](#string) | Discord ID of the user. | +| <a id="currentuserduochatavailable"></a>`duoChatAvailable` **{warning-solid}** | [`Boolean!`](#boolean) | **Introduced** in 16.8. This feature is an Experiment. It can be changed or removed at any time. User access to AI chat feature. | | <a id="currentuseremail"></a>`email` **{warning-solid}** | [`String`](#string) | **Deprecated** in 13.7. This was renamed. Use: [`User.publicEmail`](#userpublicemail). | | <a id="currentuseremails"></a>`emails` | [`EmailConnection`](#emailconnection) | User's email addresses. (see [Connections](#connections)) | | <a id="currentusergitpodenabled"></a>`gitpodEnabled` | [`Boolean`](#boolean) | Whether Gitpod is enabled at the user level. | @@ -20817,6 +20819,7 @@ CI/CD variables a project inherites from its parent group and ancestors. | Name | Type | Description | | ---- | ---- | ----------- | +| <a id="inheritedcivariabledescription"></a>`description` | [`String`](#string) | Description of the variable. | | <a id="inheritedcivariableenvironmentscope"></a>`environmentScope` | [`String`](#string) | Scope defining the environments that can use the variable. | | <a id="inheritedcivariablegroupcicdsettingspath"></a>`groupCiCdSettingsPath` | [`String`](#string) | Indicates the path to the CI/CD settings of the group the variable belongs to. | | <a id="inheritedcivariablegroupname"></a>`groupName` | [`String`](#string) | Indicates group the variable belongs to. | diff --git a/doc/api/instance_level_ci_variables.md b/doc/api/instance_level_ci_variables.md index a4018a46525..466479e0cdb 100644 --- a/doc/api/instance_level_ci_variables.md +++ b/doc/api/instance_level_ci_variables.md @@ -22,6 +22,7 @@ curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/a [ { "key": "TEST_VARIABLE_1", + "description": null, "variable_type": "env_var", "value": "TEST_1", "protected": false, @@ -30,6 +31,7 @@ curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/a }, { "key": "TEST_VARIABLE_2", + "description": null, "variable_type": "env_var", "value": "TEST_2", "protected": false, @@ -58,6 +60,7 @@ curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/a ```json { "key": "TEST_VARIABLE_1", + "description": null, "variable_type": "env_var", "value": "TEST_1", "protected": false, @@ -93,6 +96,7 @@ curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" \ ```json { "key": "NEW_VARIABLE", + "description": null, "value": "new value", "variable_type": "env_var", "protected": false, @@ -126,6 +130,7 @@ curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" \ ```json { "key": "NEW_VARIABLE", + "description": null, "value": "updated value", "variable_type": "env_var", "protected": true, diff --git a/doc/api/integrations.md b/doc/api/integrations.md index babb8ec40df..9aec4e0b17d 100644 --- a/doc/api/integrations.md +++ b/doc/api/integrations.md @@ -696,71 +696,6 @@ Get the GitHub integration settings for a project. GET /projects/:id/integrations/github ``` -## Slack notifications - -### Set up Slack notifications - -Set up Slack notifications for a project. - -```plaintext -PUT /projects/:id/integrations/slack -``` - -Parameters: - -| Parameter | Type | Required | Description | -| --------- | ---- | -------- | ----------- | -| `webhook` | string | true | Slack notifications webhook (for example, `https://hooks.slack.com/services/...`). | -| `username` | string | false | Slack notifications username. | -| `channel` | string | false | Default channel to use if no other channel is configured. | -| `notify_only_broken_pipelines` | boolean | false | Send notifications for broken pipelines. | -| `notify_only_default_branch` | boolean | false | **Deprecated:** This parameter has been replaced with `branches_to_be_notified`. | -| `branches_to_be_notified` | string | false | Branches to send notifications for. Valid options are `all`, `default`, `protected`, and `default_and_protected`. The default value is `default`. | -| `labels_to_be_notified` | string | false | Labels to send notifications for. Leave blank to receive notifications for all events. | -| `labels_to_be_notified_behavior` | string | false | Labels to be notified for. Valid options are `match_any` and `match_all`. The default value is `match_any`. | -| `alert_channel` | string | false | The name of the channel to receive notifications for alert events. | -| `alert_events` | boolean | false | Enable notifications for alert events. | -| `commit_events` | boolean | false | Enable notifications for commit events. | -| `confidential_issue_channel` | string | false | The name of the channel to receive notifications for confidential issue events. | -| `confidential_issues_events` | boolean | false | Enable notifications for confidential issue events. | -| `confidential_note_channel` | string | false | The name of the channel to receive notifications for confidential note events. | -| `confidential_note_events` | boolean | false | Enable notifications for confidential note events. | -| `deployment_channel` | string | false | The name of the channel to receive notifications for deployment events. | -| `deployment_events` | boolean | false | Enable notifications for deployment events. | -| `incident_channel` | string | false | The name of the channel to receive notifications for incident events. | -| `incidents_events` | boolean | false | Enable notifications for incident events. | -| `issue_channel` | string | false | The name of the channel to receive notifications for issue events. | -| `issues_events` | boolean | false | Enable notifications for issue events. | -| `job_events` | boolean | false | Enable notifications for job events. | -| `merge_request_channel` | string | false | The name of the channel to receive notifications for merge request events. | -| `merge_requests_events` | boolean | false | Enable notifications for merge request events. | -| `note_channel` | string | false | The name of the channel to receive notifications for note events. | -| `note_events` | boolean | false | Enable notifications for note events. | -| `pipeline_channel` | string | false | The name of the channel to receive notifications for pipeline events. | -| `pipeline_events` | boolean | false | Enable notifications for pipeline events. | -| `push_channel` | string | false | The name of the channel to receive notifications for push events. | -| `push_events` | boolean | false | Enable notifications for push events. | -| `tag_push_channel` | string | false | The name of the channel to receive notifications for tag push events. | -| `tag_push_events` | boolean | false | Enable notifications for tag push events. | -| `wiki_page_channel` | string | false | The name of the channel to receive notifications for wiki page events. | -| `wiki_page_events` | boolean | false | Enable notifications for wiki page events. | - -### Disable Slack notifications - -Disable Slack notifications for a project. Integration settings are reset. - -```plaintext -DELETE /projects/:id/integrations/slack -``` - -### Get Slack notifications settings - -Get the Slack notifications settings for a project. - -```plaintext -GET /projects/:id/integrations/slack -``` - ## Google Chat ### Set up Google Chat @@ -1423,6 +1358,71 @@ Get the Redmine integration settings for a project. GET /projects/:id/integrations/redmine ``` +## Slack notifications + +### Set up Slack notifications + +Set up Slack notifications for a project. + +```plaintext +PUT /projects/:id/integrations/slack +``` + +Parameters: + +| Parameter | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `webhook` | string | true | Slack notifications webhook (for example, `https://hooks.slack.com/services/...`). | +| `username` | string | false | Slack notifications username. | +| `channel` | string | false | Default channel to use if no other channel is configured. | +| `notify_only_broken_pipelines` | boolean | false | Send notifications for broken pipelines. | +| `notify_only_default_branch` | boolean | false | **Deprecated:** This parameter has been replaced with `branches_to_be_notified`. | +| `branches_to_be_notified` | string | false | Branches to send notifications for. Valid options are `all`, `default`, `protected`, and `default_and_protected`. The default value is `default`. | +| `labels_to_be_notified` | string | false | Labels to send notifications for. Leave blank to receive notifications for all events. | +| `labels_to_be_notified_behavior` | string | false | Labels to be notified for. Valid options are `match_any` and `match_all`. The default value is `match_any`. | +| `alert_channel` | string | false | The name of the channel to receive notifications for alert events. | +| `alert_events` | boolean | false | Enable notifications for alert events. | +| `commit_events` | boolean | false | Enable notifications for commit events. | +| `confidential_issue_channel` | string | false | The name of the channel to receive notifications for confidential issue events. | +| `confidential_issues_events` | boolean | false | Enable notifications for confidential issue events. | +| `confidential_note_channel` | string | false | The name of the channel to receive notifications for confidential note events. | +| `confidential_note_events` | boolean | false | Enable notifications for confidential note events. | +| `deployment_channel` | string | false | The name of the channel to receive notifications for deployment events. | +| `deployment_events` | boolean | false | Enable notifications for deployment events. | +| `incident_channel` | string | false | The name of the channel to receive notifications for incident events. | +| `incidents_events` | boolean | false | Enable notifications for incident events. | +| `issue_channel` | string | false | The name of the channel to receive notifications for issue events. | +| `issues_events` | boolean | false | Enable notifications for issue events. | +| `job_events` | boolean | false | Enable notifications for job events. | +| `merge_request_channel` | string | false | The name of the channel to receive notifications for merge request events. | +| `merge_requests_events` | boolean | false | Enable notifications for merge request events. | +| `note_channel` | string | false | The name of the channel to receive notifications for note events. | +| `note_events` | boolean | false | Enable notifications for note events. | +| `pipeline_channel` | string | false | The name of the channel to receive notifications for pipeline events. | +| `pipeline_events` | boolean | false | Enable notifications for pipeline events. | +| `push_channel` | string | false | The name of the channel to receive notifications for push events. | +| `push_events` | boolean | false | Enable notifications for push events. | +| `tag_push_channel` | string | false | The name of the channel to receive notifications for tag push events. | +| `tag_push_events` | boolean | false | Enable notifications for tag push events. | +| `wiki_page_channel` | string | false | The name of the channel to receive notifications for wiki page events. | +| `wiki_page_events` | boolean | false | Enable notifications for wiki page events. | + +### Disable Slack notifications + +Disable Slack notifications for a project. Integration settings are reset. + +```plaintext +DELETE /projects/:id/integrations/slack +``` + +### Get Slack notifications settings + +Get the Slack notifications settings for a project. + +```plaintext +GET /projects/:id/integrations/slack +``` + ## Slack slash commands ### Set up Slack slash commands diff --git a/doc/api/settings.md b/doc/api/settings.md index cf34cf3d65e..bde4c769b92 100644 --- a/doc/api/settings.md +++ b/doc/api/settings.md @@ -527,7 +527,7 @@ listed in the descriptions of the relevant settings. | `protected_ci_variables` | boolean | no | CI/CD variables are protected by default. | | `disable_overriding_approvers_per_merge_request` | boolean | no | Prevent editing approval rules in projects and merge requests | | `prevent_merge_requests_author_approval` | boolean | no | Prevent approval by author | -| `prevent_merge_requests_committers_approval` | boolean | no | Prevent editing approval rules in projects and merge requests | +| `prevent_merge_requests_committers_approval` | boolean | no | Prevent approval by committers to merge requests | | `push_event_activities_limit` | integer | no | Maximum number of changes (branches or tags) in a single push above which a [bulk push event is created](../administration/settings/push_event_activities_limit.md). Setting to `0` does not disable throttling. | | `push_event_hooks_limit` | integer | no | Maximum number of changes (branches or tags) in a single push above which webhooks and integrations are not triggered. Setting to `0` does not disable throttling. | | `rate_limiting_response_text` | string | no | When rate limiting is enabled via the `throttle_*` settings, send this plain text response when a rate limit is exceeded. 'Retry later' is sent if this is blank. | diff --git a/doc/ci/runners/img/runner_fleet_dashboard.png b/doc/ci/runners/img/runner_fleet_dashboard.png Binary files differindex 242ebf4aea9..8c77b5a1aa9 100644 --- a/doc/ci/runners/img/runner_fleet_dashboard.png +++ b/doc/ci/runners/img/runner_fleet_dashboard.png diff --git a/doc/ci/runners/runner_fleet_dashboard.md b/doc/ci/runners/runner_fleet_dashboard.md index a79f5ab5713..f329561cf4b 100644 --- a/doc/ci/runners/runner_fleet_dashboard.md +++ b/doc/ci/runners/runner_fleet_dashboard.md @@ -31,12 +31,28 @@ To view the runner fleet dashboard: 1. On the left sidebar, at the bottom, select **Admin Area**. 1. Select **Runners**. -1. Click **Fleet dashboard**. +1. Select **Fleet dashboard**. Most of the dashboard works without any additional actions, with the exception of **Wait time to pick a job** chart and features proposed in [epic 11183](https://gitlab.com/groups/gitlab-org/-/epics/11183). These features require [setting up an additional infrastructure](#enable-more-ci-analytics-features-with-clickhouse). +## Export compute minutes used by instance runners + +Prerequisites: + +- You must be an administrator. + +To analyze runner usage, you can export a CSV file that contains the number of jobs and executed runner minutes. The +CSV file shows the runner type and job status for each project. The CSV is sent to your email when the export is completed. + +To export compute minutes used by instance runners: + +1. On the left sidebar, at the bottom, select **Admin Area**. +1. Select **Runners**. +1. Select **Fleet dashboard**. +1. Select **Export CSV**. + ## Enable more CI analytics features with ClickHouse **(ULTIMATE EXPERIMENT)** > - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/11180) in GitLab 16.7 with the [flags](../../administration/feature_flags.md) named `ci_data_ingestion_to_click_house` and `clickhouse_ci_analytics`. Disabled by default. diff --git a/doc/development/database/table_partitioning.md b/doc/development/database/table_partitioning.md index 2b805e964c7..cb159a404fd 100644 --- a/doc/development/database/table_partitioning.md +++ b/doc/development/database/table_partitioning.md @@ -632,3 +632,73 @@ class AsyncPrepareTableConstraintsForListPartitioning < Gitlab::Database::Migrat end end ``` + +### Step 7 - Re-point foreign keys to parent table + +The tables that reference the initial partition must be updated to point to the +parent table now. Without this change, the records from those tables +will not be able to locate the rows in the next partitions because they will look +for them in the initial partition. + +Steps: + +- Add the foreign key to the partitioned table and validate it asynchronously, + [for example](https://gitlab.com/gitlab-org/gitlab/-/blob/65d63f6a00196c3a7d59f15191920f271ab2b145/db/post_migrate/20230524135543_replace_ci_build_pending_states_foreign_key.rb). +- Validate it synchronously after the asynchronously validation was completed on GitLab.com, + [for example](https://gitlab.com/gitlab-org/gitlab/-/blob/65d63f6a00196c3a7d59f15191920f271ab2b145/db/post_migrate/20230530140456_validate_fk_ci_build_pending_states_p_ci_builds.rb). +- Remove the old foreign key and rename the new one to the old name, + [for example](https://gitlab.com/gitlab-org/gitlab/-/blob/65d63f6a00196c3a7d59f15191920f271ab2b145/db/post_migrate/20230615083713_replace_old_fk_ci_build_pending_states_to_builds.rb#L9). + +### Step 8 - Ensure ID uniqueness across partitions + +All uniqueness constraints must include the partitioning key, so we can have +duplicate IDs across partitions. To solve this we enforce that only the database +can set the ID values and use a sequence to generate them because sequences are +guaranteed to generate unique values. + +For example: + +```ruby +class EnsureIdUniquenessForPCiBuilds < Gitlab::Database::Migration[2.1] + include Gitlab::Database::PartitioningMigrationHelpers::UniquenessHelpers + + enable_lock_retries! + + TABLE_NAME = :p_ci_builds + FUNCTION_NAME = :assign_p_ci_builds_id_value + + def up + ensure_unique_id(TABLE_NAME) + end + + def down + execute(<<~SQL.squish) + ALTER TABLE #{TABLE_NAME} + ALTER COLUMN id SET DEFAULT nextval('ci_builds_id_seq'::regclass); + + DROP FUNCTION IF EXISTS #{FUNCTION_NAME} CASCADE; + SQL + end +``` + +### Step 9 - Analyze the partitioned table and create new partitions + +The autovacuum daemon does not process partitioned tables. It is necessary to +periodically run a manual `ANALYZE` to keep the statistics of the table hierarchy +up to date. + +Models that implement `Ci::Partitionable` with `partitioned: true` option are +analyzed by default on a weekly basis. To enable this and create new partitions +you need to register the model in the [PostgreSQL initializer](https://gitlab.com/gitlab-org/gitlab/-/blob/b7f0e3f1bcd2ffc220768bbc373364151775ca8e/config/initializers/postgres_partitioning.rb). + +### Step 10 - Update the application to use the partitioned table + +Now that the parent table is ready, we can update the application to use it: + +```ruby +class Model < ApplicationRecord + self.table_name = :partitioned_table +end +``` + +Depending on the model, it might be safer to use a [change management issue](https://gitlab.com/gitlab-com/gl-infra/production/-/issues/16387). diff --git a/doc/user/application_security/dependency_scanning/index.md b/doc/user/application_security/dependency_scanning/index.md index 953dc96ce87..4e1c394c582 100644 --- a/doc/user/application_security/dependency_scanning/index.md +++ b/doc/user/application_security/dependency_scanning/index.md @@ -308,22 +308,22 @@ the project first. When a supported dependency file is detected, all dependencies, including transitive dependencies are analyzed. There is no limit to the depth of nested or transitive dependencies that are analyzed. -### Dependency analyzers +### Analyzers -Dependency Scanning supports the following official analyzers: +Dependency Scanning supports the following official +[Gemnasium-based](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium) analyzers: - `gemnasium` - `gemnasium-maven` - `gemnasium-python` -Each of these supported Gemnasium-based Dependency Scanning analyzers exist in the following project: - -- [`gemnasium`](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium) - -The analyzers are published as Docker images, which Dependency Scanning uses -to launch dedicated containers for each analysis. You can also integrate a custom +The analyzers are published as Docker images, which Dependency Scanning uses to launch dedicated +containers for each analysis. You can also integrate a custom [security scanner](../../../development/integrations/secure.md). +Each analyzer is updated as new versions of Gemnasium are released. For more information, see the +analyzer [Release Process documentation](../../../development/sec/analyzer_development_guide.md#versioning-and-release-process). + ### How analyzers obtain dependency information GitLab analyzers obtain dependency information using one of the following two methods: @@ -807,7 +807,7 @@ The following variables allow configuration of global dependency scanning settin | CI/CD variables | Description | | ----------------------------|------------ | | `ADDITIONAL_CA_CERT_BUNDLE` | Bundle of CA certs to trust. The bundle of certificates provided here is also used by other tools during the scanning process, such as `git`, `yarn`, or `npm`. For more details, see [Using a custom SSL CA certificate authority](#using-a-custom-ssl-ca-certificate-authority). | -| `DS_EXCLUDED_ANALYZERS` | Specify the analyzers (by name) to exclude from Dependency Scanning. For more information, see [Dependency Scanning analyzers](#dependency-analyzers). | +| `DS_EXCLUDED_ANALYZERS` | Specify the analyzers (by name) to exclude from Dependency Scanning. For more information, see [Analyzers](#analyzers). | | `DS_EXCLUDED_PATHS` | Exclude files and directories from the scan based on the paths. A comma-separated list of patterns. Patterns can be globs (see [`doublestar.Match`](https://pkg.go.dev/github.com/bmatcuk/doublestar/v4@v4.0.2#Match) for supported patterns), or file or folder paths (for example, `doc,spec`). Parent directories also match patterns. Default: `"spec, test, tests, tmp"`. | | `DS_IMAGE_SUFFIX` | Suffix added to the image name. (GitLab team members can view more information in this confidential issue: `https://gitlab.com/gitlab-org/gitlab/-/issues/354796`). Automatically set to `"-fips"` when FIPS mode is enabled. | | `DS_MAX_DEPTH` | Defines how many directory levels deep that the analyzer should search for supported files to scan. A value of `-1` scans all directories regardless of depth. Default: `2`. | @@ -1022,10 +1022,6 @@ merge cyclonedx sboms: - gl-sbom-all.cdx.json ``` -## Versioning and release process - -Check the [Release Process documentation](../../../development/sec/analyzer_development_guide.md#versioning-and-release-process). - ## Contributing to the vulnerability database To find a vulnerability, you can search the [`GitLab Advisory Database`](https://advisories.gitlab.com/). diff --git a/doc/user/project/members/index.md b/doc/user/project/members/index.md index 92aaee1ae54..ac1381e5358 100644 --- a/doc/user/project/members/index.md +++ b/doc/user/project/members/index.md @@ -59,6 +59,7 @@ Prerequisites: - You must have the Owner or Maintainer role. - [Group membership lock](../../group/access_and_permissions.md#prevent-members-from-being-added-to-projects-in-a-group) must be disabled. +- If [sign-up is disabled](../../../administration/settings/sign_up_restrictions.md#disable-new-sign-ups), an administrator must add the user by email first. To add a user to a project: diff --git a/lib/api/admin/ci/variables.rb b/lib/api/admin/ci/variables.rb index 3277acc1b52..a443f7f3476 100644 --- a/lib/api/admin/ci/variables.rb +++ b/lib/api/admin/ci/variables.rb @@ -54,6 +54,10 @@ module API type: String, desc: 'The key of the variable. Max 255 characters' + optional :description, + type: String, + desc: 'The description of the variable' + requires :value, type: String, desc: 'The value of a variable' @@ -98,6 +102,10 @@ module API type: String, desc: 'The key of a variable' + optional :description, + type: String, + desc: 'The description of the variable' + optional :value, type: String, desc: 'The value of a variable' diff --git a/lib/api/entities/bulk_imports/entity_failure.rb b/lib/api/entities/bulk_imports/entity_failure.rb index 08708a7c961..4771e6cb894 100644 --- a/lib/api/entities/bulk_imports/entity_failure.rb +++ b/lib/api/entities/bulk_imports/entity_failure.rb @@ -6,7 +6,7 @@ module API class EntityFailure < Grape::Entity expose :relation, documentation: { type: 'string', example: 'label' } expose :exception_message, documentation: { type: 'string', example: 'error message' } do |failure| - ::Projects::ImportErrorFilter.filter_message(failure.exception_message.truncate(72)) + ::Projects::ImportErrorFilter.filter_message(failure.exception_message).truncate(255) end expose :exception_class, documentation: { type: 'string', example: 'Exception' } expose :correlation_id_value, documentation: { type: 'string', example: 'dfcf583058ed4508e4c7c617bd7f0edd' } diff --git a/lib/gitlab/background_migration/backfill_partition_id_ci_pipeline_artifact.rb b/lib/gitlab/background_migration/backfill_partition_id_ci_pipeline_artifact.rb new file mode 100644 index 00000000000..73996ce4460 --- /dev/null +++ b/lib/gitlab/background_migration/backfill_partition_id_ci_pipeline_artifact.rb @@ -0,0 +1,28 @@ +# frozen_string_literal: true + +module Gitlab + module BackgroundMigration + class BackfillPartitionIdCiPipelineArtifact < BatchedMigrationJob + operation_name :update_all + feature_category :continuous_integration + + def perform + return unless uses_multiple_partitions? + + each_sub_batch do |sub_batch| + sub_batch + .where('ci_pipeline_artifacts.pipeline_id = ci_pipelines.id') + .update_all('partition_id = ci_pipelines.partition_id FROM ci_pipelines') + end + end + + private + + def uses_multiple_partitions? + !!connection.select_value(<<~SQL) + SELECT true FROM p_ci_builds WHERE partition_id = 101 LIMIT 1 + SQL + end + end + end +end diff --git a/lib/gitlab/background_migration/backfill_partition_id_ci_pipeline_metadata.rb b/lib/gitlab/background_migration/backfill_partition_id_ci_pipeline_metadata.rb new file mode 100644 index 00000000000..6fa4037f1ac --- /dev/null +++ b/lib/gitlab/background_migration/backfill_partition_id_ci_pipeline_metadata.rb @@ -0,0 +1,28 @@ +# frozen_string_literal: true + +module Gitlab + module BackgroundMigration + class BackfillPartitionIdCiPipelineMetadata < BatchedMigrationJob + operation_name :update_all + feature_category :continuous_integration + + def perform + return unless uses_multiple_partitions? + + each_sub_batch do |sub_batch| + sub_batch + .where('ci_pipeline_metadata.pipeline_id = ci_pipelines.id') + .update_all('partition_id = ci_pipelines.partition_id FROM ci_pipelines') + end + end + + private + + def uses_multiple_partitions? + !!connection.select_value(<<~SQL) + SELECT true FROM p_ci_builds WHERE partition_id = 101 LIMIT 1 + SQL + end + end + end +end diff --git a/lib/gitlab/database/query_analyzers/prevent_cross_database_modification.rb b/lib/gitlab/database/query_analyzers/prevent_cross_database_modification.rb index fb25cb70e57..f16b6ca2177 100644 --- a/lib/gitlab/database/query_analyzers/prevent_cross_database_modification.rb +++ b/lib/gitlab/database/query_analyzers/prevent_cross_database_modification.rb @@ -86,7 +86,7 @@ module Gitlab end return unless self.in_transaction? - return if in_factory_bot_create? + return if Thread.current[:factory_bot_objects] && Thread.current[:factory_bot_objects] > 0 # PgQuery might fail in some cases due to limited nesting: # https://github.com/pganalyze/pg_query/issues/209 @@ -192,20 +192,6 @@ module Gitlab def self.in_transaction? context[:transaction_depth_by_db].values.any?(&:positive?) end - - # We ignore execution in the #create method from FactoryBot - # because it is not representative of real code we run in - # production. There are far too many false positives caused - # by instantiating objects in different `gitlab_schema` in a - # FactoryBot `create`. - def self.in_factory_bot_create? - Rails.env.test? && caller_locations.any? do |l| - l.path.end_with?('lib/factory_bot/evaluation.rb') && l.label == 'create' || - l.path.end_with?('lib/factory_bot/strategy/create.rb') || - l.path.end_with?('lib/factory_bot/strategy/build.rb') || - l.path.end_with?('shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb') && l.label == 'create_existing_record' - end - end end end end diff --git a/lib/gitlab/github_import/importer/issue_event_importer.rb b/lib/gitlab/github_import/importer/issue_event_importer.rb index 2068f789fec..9f15e9a25d8 100644 --- a/lib/gitlab/github_import/importer/issue_event_importer.rb +++ b/lib/gitlab/github_import/importer/issue_event_importer.rb @@ -27,6 +27,12 @@ module Gitlab reviewed ].freeze + EVENT_COUNTER_MAP = { + 'commented' => 'note', + 'reviewed' => 'pull_request_review', + 'merged' => 'pull_request_merged_by' + }.freeze + # issue_event - An instance of `Gitlab::GithubImport::Representation::IssueEvent`. # project - An instance of `Project`. # client - An instance of `Gitlab::GithubImport::Client`. diff --git a/lib/gitlab/github_import/importer/single_endpoint_issue_events_importer.rb b/lib/gitlab/github_import/importer/single_endpoint_issue_events_importer.rb index 20fff73ac3d..126a0b8fa4a 100644 --- a/lib/gitlab/github_import/importer/single_endpoint_issue_events_importer.rb +++ b/lib/gitlab/github_import/importer/single_endpoint_issue_events_importer.rb @@ -34,7 +34,7 @@ module Gitlab cache_event(parent_record, associated) - Gitlab::GithubImport::ObjectCounter.increment(project, object_type, :fetched) + increment_object_counter(associated[:event]) pull_request = parent_record.is_a? MergeRequest associated[:issue] = { number: parent_record.iid, pull_request: pull_request } @@ -66,6 +66,12 @@ module Gitlab :issue_event end + def increment_object_counter(event_name) + counter_type = importer_class::EVENT_COUNTER_MAP[event_name] if import_settings.extended_events? + counter_type ||= object_type + Gitlab::GithubImport::ObjectCounter.increment(project, counter_type, :fetched) + end + def collection_method :issue_timeline end diff --git a/locale/gitlab.pot b/locale/gitlab.pot index f2f93a2a6c8..65bd7e16e1b 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -8081,13 +8081,13 @@ msgstr "" msgid "Billing|An error occurred while loading billable members list." msgstr "" -msgid "Billing|An error occurred while loading details for the Code Suggestions add-on. If the problem persists, please %{supportLinkStart}contact support%{supportLinkEnd}." +msgid "Billing|An error occurred while loading details for the Duo Pro add-on. If the problem persists, please %{supportLinkStart}contact support%{supportLinkEnd}." msgstr "" msgid "Billing|An error occurred while loading pending members list" msgstr "" -msgid "Billing|An error occurred while loading users of the Code Suggestions add-on. If the problem persists, please %{supportLinkStart}contact support%{supportLinkEnd}." +msgid "Billing|An error occurred while loading users of the Duo Pro add-on. If the problem persists, please %{supportLinkStart}contact support%{supportLinkEnd}." msgstr "" msgid "Billing|An error occurred while removing a billable member." @@ -8105,10 +8105,10 @@ msgstr "" msgid "Billing|Enter at least three characters to search." msgstr "" -msgid "Billing|Error assigning Code Suggestions add-on" +msgid "Billing|Error assigning Duo Pro add-on" msgstr "" -msgid "Billing|Error un-assigning Code Suggestions add-on" +msgid "Billing|Error un-assigning Duo Pro add-on" msgstr "" msgid "Billing|Explore paid plans" @@ -8173,7 +8173,7 @@ msgstr "" msgid "Billing|You can upgrade to a paid tier to get access to more features." msgstr "" -msgid "Billing|You have assigned all available Code Suggestions add-on seats. Please %{salesLinkStart}contact sales%{salesLinkEnd} if you would like to purchase more seats." +msgid "Billing|You have assigned all available Duo Pro add-on seats. Please %{salesLinkStart}contact sales%{salesLinkEnd} if you would like to purchase more seats." msgstr "" msgid "Billing|Your group recently changed to use the Free plan. %{over_limit_message} You can free up space for new members by removing those who no longer need access or toggling them to over-limit. To get an unlimited number of members, you can %{link_start}upgrade%{link_end} to a paid tier." @@ -12286,6 +12286,12 @@ msgstr "" msgid "Comment" msgstr "" +msgid "Comment & close %{workItemType}" +msgstr "" + +msgid "Comment & reopen %{workItemType}" +msgstr "" + msgid "Comment '%{label}' position" msgstr "" diff --git a/spec/db/schema_spec.rb b/spec/db/schema_spec.rb index ae9404eac63..24ec5467c86 100644 --- a/spec/db/schema_spec.rb +++ b/spec/db/schema_spec.rb @@ -48,7 +48,9 @@ RSpec.describe 'Database schema', feature_category: :database do chat_teams: %w[team_id], ci_builds: %w[project_id runner_id user_id erased_by_id trigger_request_id partition_id auto_canceled_by_partition_id], ci_namespace_monthly_usages: %w[namespace_id], + ci_pipeline_artifacts: %w[partition_id], ci_pipeline_chat_data: %w[partition_id], + ci_pipeline_metadata: %w[partition_id], ci_pipeline_variables: %w[partition_id], ci_pipelines: %w[partition_id], ci_runner_projects: %w[runner_id], diff --git a/spec/fixtures/api/schemas/variable.json b/spec/fixtures/api/schemas/variable.json index 440e812d95b..b708c6ec14f 100644 --- a/spec/fixtures/api/schemas/variable.json +++ b/spec/fixtures/api/schemas/variable.json @@ -11,6 +11,12 @@ "id": { "type": "integer" }, + "description": { + "type": [ + "string", + "null" + ] + }, "key": { "type": "string" }, @@ -35,4 +41,4 @@ } }, "additionalProperties": false -}
\ No newline at end of file +} diff --git a/spec/frontend/work_items/components/notes/work_item_comment_form_spec.js b/spec/frontend/work_items/components/notes/work_item_comment_form_spec.js index fe89c525fea..cbde3c4a065 100644 --- a/spec/frontend/work_items/components/notes/work_item_comment_form_spec.js +++ b/spec/frontend/work_items/components/notes/work_item_comment_form_spec.js @@ -208,6 +208,20 @@ describe('Work item comment form component', () => { ['Something went wrong while updating the task. Please try again.'], ]); }); + + it('emits `submitForm` event on closing of work item', async () => { + createComponent({ + isNewDiscussion: true, + }); + + findWorkItemToggleStateButton().vm.$emit('submit-comment'); + + await waitForPromises(); + + expect(wrapper.emitted('submitForm')).toEqual([ + [{ commentText: draftComment, isNoteInternal: false }], + ]); + }); }); describe('internal note', () => { @@ -239,6 +253,17 @@ describe('Work item comment form component', () => { expect(findConfirmButton().text()).toBe(WorkItemCommentForm.i18n.addInternalNote); }); + + it('emits `submitForm` event on closing of work item', async () => { + findInternalNoteCheckbox().vm.$emit('input', true); + findWorkItemToggleStateButton().vm.$emit('submit-comment'); + + await waitForPromises(); + + expect(wrapper.emitted('submitForm')).toEqual([ + [{ commentText: draftComment, isNoteInternal: true }], + ]); + }); }); }); }); diff --git a/spec/frontend/work_items/components/work_item_state_toggle_spec.js b/spec/frontend/work_items/components/work_item_state_toggle_spec.js index a210bd50422..988df402d60 100644 --- a/spec/frontend/work_items/components/work_item_state_toggle_spec.js +++ b/spec/frontend/work_items/components/work_item_state_toggle_spec.js @@ -32,6 +32,7 @@ describe('Work Item State toggle button component', () => { canUpdate = true, workItemState = STATE_OPEN, workItemType = 'Task', + hasComment = false, } = {}) => { wrapper = shallowMount(WorkItemStateToggle, { apolloProvider: createMockApollo([[updateWorkItemMutation, mutationHandler]]), @@ -40,6 +41,7 @@ describe('Work Item State toggle button component', () => { workItemState, workItemType, canUpdate, + hasComment, }, }); }; @@ -61,6 +63,23 @@ describe('Work Item State toggle button component', () => { expect(findStateToggleButton().text()).toBe(buttonText); }, ); + + it.each` + workItemState | workItemType | buttonText + ${STATE_OPEN} | ${'Task'} | ${'Comment & close task'} + ${STATE_CLOSED} | ${'Task'} | ${'Comment & reopen task'} + ${STATE_OPEN} | ${'Objective'} | ${'Comment & close objective'} + ${STATE_CLOSED} | ${'Objective'} | ${'Comment & reopen objective'} + ${STATE_OPEN} | ${'Key result'} | ${'Comment & close key result'} + ${STATE_CLOSED} | ${'Key result'} | ${'Comment & reopen key result'} + `( + 'is "$buttonText" when "$workItemType" state is "$workItemState" and hasComment is true', + ({ workItemState, workItemType, buttonText }) => { + createComponent({ workItemState, workItemType, hasComment: true }); + + expect(findStateToggleButton().text()).toBe(buttonText); + }, + ); }); describe('when updating the state', () => { @@ -92,6 +111,15 @@ describe('Work Item State toggle button component', () => { }); }); + it('emits `submit-comment` when hasComment is true', async () => { + createComponent({ hasComment: true }); + + findStateToggleButton().vm.$emit('click'); + await waitForPromises(); + + expect(wrapper.emitted('submit-comment')).toBeDefined(); + }); + it('emits an error message when the mutation was unsuccessful', async () => { createComponent({ mutationHandler: jest.fn().mockRejectedValue('Error!') }); diff --git a/spec/graphql/types/ci/inherited_ci_variable_type_spec.rb b/spec/graphql/types/ci/inherited_ci_variable_type_spec.rb index daf80ff9978..973d6d602c9 100644 --- a/spec/graphql/types/ci/inherited_ci_variable_type_spec.rb +++ b/spec/graphql/types/ci/inherited_ci_variable_type_spec.rb @@ -7,13 +7,14 @@ RSpec.describe GitlabSchema.types['InheritedCiVariable'], feature_category: :sec expect(described_class).to have_graphql_fields( :id, :key, - :raw, - :variable_type, + :description, :environment_scope, + :group_name, + :group_ci_cd_settings_path, :masked, :protected, - :group_name, - :group_ci_cd_settings_path + :raw, + :variable_type ).at_least end end diff --git a/spec/graphql/types/ci/instance_variable_type_spec.rb b/spec/graphql/types/ci/instance_variable_type_spec.rb index c77a4ac1dc4..bd3dd30f3c8 100644 --- a/spec/graphql/types/ci/instance_variable_type_spec.rb +++ b/spec/graphql/types/ci/instance_variable_type_spec.rb @@ -5,5 +5,7 @@ require 'spec_helper' RSpec.describe GitlabSchema.types['CiInstanceVariable'] do specify { expect(described_class.interfaces).to contain_exactly(Types::Ci::VariableInterface) } - specify { expect(described_class).to have_graphql_fields(:environment_scope, :masked, :protected).at_least } + specify do + expect(described_class).to have_graphql_fields(:environment_scope, :masked, :protected, :description).at_least + end end diff --git a/spec/lib/api/entities/bulk_imports/entity_failure_spec.rb b/spec/lib/api/entities/bulk_imports/entity_failure_spec.rb index 217e6c11630..20563bfb685 100644 --- a/spec/lib/api/entities/bulk_imports/entity_failure_spec.rb +++ b/spec/lib/api/entities/bulk_imports/entity_failure_spec.rb @@ -19,10 +19,10 @@ RSpec.describe API::Entities::BulkImports::EntityFailure, feature_category: :imp end describe 'exception message' do - it 'truncates exception message to 72 characters' do - failure.update!(exception_message: 'a' * 100) + it 'truncates exception message to 255 characters' do + failure.update!(exception_message: 'a' * 500) - expect(subject[:exception_message].length).to eq(72) + expect(subject[:exception_message].length).to eq(255) end it 'removes paths from the message' do @@ -30,5 +30,13 @@ RSpec.describe API::Entities::BulkImports::EntityFailure, feature_category: :imp expect(subject[:exception_message]).to eq('Test [FILTERED]') end + + it 'removes long paths without clipping the message' do + exception_message = "Test #{'/abc' * 300} #{'a' * 500}" + failure.update!(exception_message: exception_message) + filtered_message = "Test [FILTERED] #{'a' * 500}" + + expect(subject[:exception_message]).to eq(filtered_message.truncate(255)) + end end end diff --git a/spec/lib/gitlab/background_migration/backfill_partition_id_ci_pipeline_artifact_spec.rb b/spec/lib/gitlab/background_migration/backfill_partition_id_ci_pipeline_artifact_spec.rb new file mode 100644 index 00000000000..c466fdaa36a --- /dev/null +++ b/spec/lib/gitlab/background_migration/backfill_partition_id_ci_pipeline_artifact_spec.rb @@ -0,0 +1,94 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Gitlab::BackgroundMigration::BackfillPartitionIdCiPipelineArtifact, + feature_category: :continuous_integration do + let(:ci_pipelines_table) { table(:ci_pipelines, database: :ci) } + let(:ci_pipeline_artifacts_table) { table(:ci_pipeline_artifacts, database: :ci) } + let!(:pipeline_100) { ci_pipelines_table.create!(id: 1, partition_id: 100) } + let!(:pipeline_101) { ci_pipelines_table.create!(id: 2, partition_id: 101) } + let!(:pipeline_102) { ci_pipelines_table.create!(id: 3, partition_id: 101) } + let!(:ci_pipeline_artifact_100) do + ci_pipeline_artifacts_table.create!( + id: 1, + pipeline_id: pipeline_100.id, + project_id: 1, + size: 1.megabyte, + file_type: 1, + file_format: 1, + file: fixture_file_upload( + Rails.root.join('spec/fixtures/pipeline_artifacts/code_coverage.json'), 'application/json' + ), + partition_id: pipeline_100.partition_id + ) + end + + let!(:ci_pipeline_artifact_101) do + ci_pipeline_artifacts_table.create!( + id: 2, + pipeline_id: pipeline_101.id, + project_id: 1, + size: 1.megabyte, + file_type: 1, + file_format: 1, + file: fixture_file_upload( + Rails.root.join('spec/fixtures/pipeline_artifacts/code_coverage.json'), 'application/json' + ), + partition_id: pipeline_101.partition_id + ) + end + + let!(:invalid_ci_pipeline_artifact) do + ci_pipeline_artifacts_table.create!( + id: 3, + pipeline_id: pipeline_102.id, + project_id: 1, + size: 1.megabyte, + file_type: 1, + file_format: 1, + file: fixture_file_upload( + Rails.root.join('spec/fixtures/pipeline_artifacts/code_coverage.json'), 'application/json' + ), + partition_id: pipeline_100.partition_id + ) + end + + let(:migration_attrs) do + { + start_id: ci_pipeline_artifacts_table.minimum(:pipeline_id), + end_id: ci_pipeline_artifacts_table.maximum(:pipeline_id), + batch_table: :ci_pipeline_artifacts, + batch_column: :id, + sub_batch_size: 1, + pause_ms: 0, + connection: Ci::ApplicationRecord.connection + } + end + + let!(:migration) { described_class.new(**migration_attrs) } + + describe '#perform' do + context 'when second partition does not exist' do + it 'does not execute the migration' do + expect { migration.perform } + .not_to change { invalid_ci_pipeline_artifact.reload.partition_id } + end + end + + context 'when second partition exists' do + before do + allow(migration).to receive(:uses_multiple_partitions?).and_return(true) + end + + it 'fixes invalid records in the wrong the partition' do + expect { migration.perform } + .to not_change { ci_pipeline_artifact_100.reload.partition_id } + .and not_change { ci_pipeline_artifact_101.reload.partition_id } + .and change { invalid_ci_pipeline_artifact.reload.partition_id } + .from(100) + .to(101) + end + end + end +end diff --git a/spec/lib/gitlab/background_migration/backfill_partition_id_ci_pipeline_metadata_spec.rb b/spec/lib/gitlab/background_migration/backfill_partition_id_ci_pipeline_metadata_spec.rb new file mode 100644 index 00000000000..d09d5016dcc --- /dev/null +++ b/spec/lib/gitlab/background_migration/backfill_partition_id_ci_pipeline_metadata_spec.rb @@ -0,0 +1,73 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Gitlab::BackgroundMigration::BackfillPartitionIdCiPipelineMetadata, + feature_category: :continuous_integration do + let(:ci_pipelines_table) { table(:ci_pipelines, database: :ci) } + let(:ci_pipeline_metadata_table) { table(:ci_pipeline_metadata, database: :ci) } + let!(:pipeline_100) { ci_pipelines_table.create!(id: 1, partition_id: 100) } + let!(:pipeline_101) { ci_pipelines_table.create!(id: 2, partition_id: 101) } + let!(:pipeline_102) { ci_pipelines_table.create!(id: 3, partition_id: 101) } + let!(:ci_pipeline_metadata_100) do + ci_pipeline_metadata_table.create!( + pipeline_id: pipeline_100.id, + project_id: 1, + partition_id: pipeline_100.partition_id + ) + end + + let!(:ci_pipeline_metadata_101) do + ci_pipeline_metadata_table.create!( + pipeline_id: pipeline_101.id, + project_id: 1, + partition_id: pipeline_101.partition_id + ) + end + + let!(:invalid_ci_pipeline_metadata) do + ci_pipeline_metadata_table.create!( + pipeline_id: pipeline_102.id, + project_id: 1, + partition_id: pipeline_100.partition_id + ) + end + + let(:migration_attrs) do + { + start_id: ci_pipeline_metadata_table.minimum(:pipeline_id), + end_id: ci_pipeline_metadata_table.maximum(:pipeline_id), + batch_table: :ci_pipeline_metadata, + batch_column: :pipeline_id, + sub_batch_size: 1, + pause_ms: 0, + connection: Ci::ApplicationRecord.connection + } + end + + let!(:migration) { described_class.new(**migration_attrs) } + + describe '#perform' do + context 'when second partition does not exist' do + it 'does not execute the migration' do + expect { migration.perform } + .not_to change { invalid_ci_pipeline_metadata.reload.partition_id } + end + end + + context 'when second partition exists' do + before do + allow(migration).to receive(:uses_multiple_partitions?).and_return(true) + end + + it 'fixes invalid records in the wrong the partition' do + expect { migration.perform } + .to not_change { ci_pipeline_metadata_100.reload.partition_id } + .and not_change { ci_pipeline_metadata_101.reload.partition_id } + .and change { invalid_ci_pipeline_metadata.reload.partition_id } + .from(100) + .to(101) + end + end + end +end diff --git a/spec/lib/gitlab/database/query_analyzers/prevent_cross_database_modification_spec.rb b/spec/lib/gitlab/database/query_analyzers/prevent_cross_database_modification_spec.rb index 3ccdb907cba..d5584342dd5 100644 --- a/spec/lib/gitlab/database/query_analyzers/prevent_cross_database_modification_spec.rb +++ b/spec/lib/gitlab/database/query_analyzers/prevent_cross_database_modification_spec.rb @@ -239,7 +239,7 @@ RSpec.describe Gitlab::Database::QueryAnalyzers::PreventCrossDatabaseModificatio end end - context 'when uniquiness validation is tested', type: :model do + context 'when uniqueness validation is tested', type: :model do subject { build(:ci_variable) } it 'does not raise exceptions' do diff --git a/spec/lib/gitlab/github_import/importer/single_endpoint_issue_events_importer_spec.rb b/spec/lib/gitlab/github_import/importer/single_endpoint_issue_events_importer_spec.rb index 93fcda8a4f0..19142b94519 100644 --- a/spec/lib/gitlab/github_import/importer/single_endpoint_issue_events_importer_spec.rb +++ b/spec/lib/gitlab/github_import/importer/single_endpoint_issue_events_importer_spec.rb @@ -208,6 +208,38 @@ RSpec.describe Gitlab::GithubImport::Importer::SingleEndpointIssueEventsImporter end end + describe 'increment object counter' do + it 'increments counter' do + expect(Gitlab::GithubImport::ObjectCounter).to receive(:increment).with(project, :issue_event, :fetched) + + subject.each_object_to_import { |event| event } + end + + context 'when event should increment a mapped fetched counter' do + before do + stub_const('Gitlab::GithubImport::Importer::IssueEventImporter::EVENT_COUNTER_MAP', { + 'closed' => 'custom_type' + }) + end + + it 'increments the mapped fetched counter' do + expect(Gitlab::GithubImport::ObjectCounter).to receive(:increment).with(project, 'custom_type', :fetched) + + subject.each_object_to_import { |event| event } + end + + context 'when extended_events is disabled' do + let(:extended_events) { false } + + it 'increments the issue_event fetched counter' do + expect(Gitlab::GithubImport::ObjectCounter).to receive(:increment).with(project, :issue_event, :fetched) + + subject.each_object_to_import { |event| event } + end + end + end + end + describe 'save events' do shared_examples 'saves event' do it 'saves event' do diff --git a/spec/migrations/20240108082419_queue_backfill_partition_id_ci_pipeline_metadata_spec.rb b/spec/migrations/20240108082419_queue_backfill_partition_id_ci_pipeline_metadata_spec.rb new file mode 100644 index 00000000000..625225b1f3e --- /dev/null +++ b/spec/migrations/20240108082419_queue_backfill_partition_id_ci_pipeline_metadata_spec.rb @@ -0,0 +1,56 @@ +# frozen_string_literal: true + +require 'spec_helper' +require_migration! + +RSpec.describe QueueBackfillPartitionIdCiPipelineMetadata, migration: :gitlab_ci, feature_category: :continuous_integration do + let!(:batched_migrations) { table(:batched_background_migrations) } + let!(:migration) { described_class::MIGRATION } + + describe '#up' do + context 'with migration present' do + let!(:ci_backfill_partition_id_ci_pipeline_metadata_migration) do + batched_migrations.create!( + job_class_name: 'QueueBackfillPartitionIdCiPipelineMetadata', + table_name: :ci_pipeline_metadata, + column_name: :pipeline_id, + job_arguments: [], + interval: 2.minutes, + min_value: 1, + max_value: 2, + batch_size: 1000, + sub_batch_size: 100, + gitlab_schema: :gitlab_ci, + status: 3 # finished + ) + end + + context 'when migration finished successfully' do + it 'does not raise exception' do + expect { migrate! }.not_to raise_error + end + + it 'schedules background jobs for each batch of ci_pipeline_metadata' do + migrate! + + expect(migration).to have_scheduled_batched_migration( + gitlab_schema: :gitlab_ci, + table_name: :ci_pipeline_metadata, + column_name: :pipeline_id, + batch_size: described_class::BATCH_SIZE, + sub_batch_size: described_class::SUB_BATCH_SIZE + ) + end + end + end + end + + describe '#down' do + it 'deletes all batched migration records' do + migrate! + schema_migrate_down! + + expect(migration).not_to have_scheduled_batched_migration + end + end +end diff --git a/spec/migrations/20240109090354_queue_backfill_partition_id_ci_pipeline_artifact_spec.rb b/spec/migrations/20240109090354_queue_backfill_partition_id_ci_pipeline_artifact_spec.rb new file mode 100644 index 00000000000..b2764cfc882 --- /dev/null +++ b/spec/migrations/20240109090354_queue_backfill_partition_id_ci_pipeline_artifact_spec.rb @@ -0,0 +1,56 @@ +# frozen_string_literal: true + +require 'spec_helper' +require_migration! + +RSpec.describe QueueBackfillPartitionIdCiPipelineArtifact, migration: :gitlab_ci, feature_category: :continuous_integration do + let!(:batched_migrations) { table(:batched_background_migrations) } + let!(:migration) { described_class::MIGRATION } + + describe '#up' do + context 'with migration present' do + let!(:ci_backfill_partition_id_ci_pipeline_artifact_migration) do + batched_migrations.create!( + job_class_name: 'QueueBackfillPartitionIdCiPipelineArtifact', + table_name: :ci_pipeline_artifacts, + column_name: :id, + job_arguments: [], + interval: 2.minutes, + min_value: 1, + max_value: 2, + batch_size: 1000, + sub_batch_size: 100, + gitlab_schema: :gitlab_ci, + status: 3 # finished + ) + end + + context 'when migration finished successfully' do + it 'does not raise exception' do + expect { migrate! }.not_to raise_error + end + + it 'schedules background jobs for each batch of ci_pipeline_artifacts' do + migrate! + + expect(migration).to have_scheduled_batched_migration( + gitlab_schema: :gitlab_ci, + table_name: :ci_pipeline_artifacts, + column_name: :id, + batch_size: described_class::BATCH_SIZE, + sub_batch_size: described_class::SUB_BATCH_SIZE + ) + end + end + end + end + + describe '#down' do + it 'deletes all batched migration records' do + migrate! + schema_migrate_down! + + expect(migration).not_to have_scheduled_batched_migration + end + end +end diff --git a/spec/models/bulk_imports/entity_spec.rb b/spec/models/bulk_imports/entity_spec.rb index ce143a1aa33..014b050a5b5 100644 --- a/spec/models/bulk_imports/entity_spec.rb +++ b/spec/models/bulk_imports/entity_spec.rb @@ -307,8 +307,7 @@ RSpec.describe BulkImports::Entity, type: :model, feature_category: :importers d import = build(:bulk_import, source_version: '16.2.0') entity = build(:bulk_import_entity, :project_entity, bulk_import: import) - expect(entity.export_relations_url_path(batched: true)) - .to eq("/projects/#{entity.source_xid}/export_relations?batched=true") + expect(entity.export_relations_url_path).to eq("/projects/#{entity.source_xid}/export_relations?batched=true") end end @@ -316,8 +315,7 @@ RSpec.describe BulkImports::Entity, type: :model, feature_category: :importers d it 'returns export relations url' do entity = build(:bulk_import_entity) - expect(entity.export_relations_url_path(batched: true)) - .to eq("/groups/#{entity.source_xid}/export_relations") + expect(entity.export_relations_url_path).to eq("/groups/#{entity.source_xid}/export_relations") end end end diff --git a/spec/models/ci/instance_variable_spec.rb b/spec/models/ci/instance_variable_spec.rb index 0ef1dfbd55c..9a6a78ee5f4 100644 --- a/spec/models/ci/instance_variable_spec.rb +++ b/spec/models/ci/instance_variable_spec.rb @@ -113,4 +113,10 @@ RSpec.describe Ci::InstanceVariable do end end end + + describe "description" do + it { is_expected.to allow_values('').for(:description) } + it { is_expected.to allow_values(nil).for(:description) } + it { is_expected.to validate_length_of(:description).is_at_most(255) } + end end diff --git a/spec/models/ci/pipeline_artifact_spec.rb b/spec/models/ci/pipeline_artifact_spec.rb index eb89c7af208..1cb99ec22b9 100644 --- a/spec/models/ci/pipeline_artifact_spec.rb +++ b/spec/models/ci/pipeline_artifact_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Ci::PipelineArtifact, type: :model do +RSpec.describe Ci::PipelineArtifact, type: :model, feature_category: :build_artifacts do let(:coverage_report) { create(:ci_pipeline_artifact, :with_coverage_report) } describe 'associations' do @@ -309,4 +309,19 @@ RSpec.describe Ci::PipelineArtifact, type: :model do let!(:model) { create(:ci_pipeline_artifact, project: parent) } end end + + describe 'partitioning', :ci_partitionable do + include Ci::PartitioningHelpers + + let(:pipeline) { create(:ci_pipeline) } + let(:pipeline_artifact) { create(:ci_pipeline_artifact, pipeline: pipeline) } + + before do + stub_current_partition_id + end + + it 'assigns the same partition id as the one that pipeline has' do + expect(pipeline_artifact.partition_id).to eq(ci_testing_partition_id) + end + end end diff --git a/spec/models/ci/pipeline_metadata_spec.rb b/spec/models/ci/pipeline_metadata_spec.rb index c114c0e945e..efe180b1db3 100644 --- a/spec/models/ci/pipeline_metadata_spec.rb +++ b/spec/models/ci/pipeline_metadata_spec.rb @@ -27,4 +27,19 @@ RSpec.describe Ci::PipelineMetadata, feature_category: :pipeline_composition do ).with_prefix end end + + describe 'partitioning', :ci_partitionable do + include Ci::PartitioningHelpers + + let(:pipeline) { create(:ci_pipeline) } + let(:pipeline_metadata) { create(:ci_pipeline_metadata, pipeline: pipeline) } + + before do + stub_current_partition_id + end + + it 'assigns the same partition id as the one that pipeline has' do + expect(pipeline_metadata.partition_id).to eq(ci_testing_partition_id) + end + end end diff --git a/spec/requests/api/graphql/ci/instance_variables_spec.rb b/spec/requests/api/graphql/ci/instance_variables_spec.rb index a612b4c91b6..6731631a075 100644 --- a/spec/requests/api/graphql/ci/instance_variables_spec.rb +++ b/spec/requests/api/graphql/ci/instance_variables_spec.rb @@ -12,6 +12,7 @@ RSpec.describe 'Query.ciVariables', feature_category: :secrets_management do nodes { id key + description value variableType protected @@ -36,6 +37,7 @@ RSpec.describe 'Query.ciVariables', feature_category: :secrets_management do expect(graphql_data.dig('ciVariables', 'nodes')).to contain_exactly({ 'id' => variable.to_global_id.to_s, 'key' => 'TEST_VAR', + 'description' => nil, 'value' => 'test', 'variableType' => 'ENV_VAR', 'masked' => false, diff --git a/spec/serializers/ci/group_variable_entity_spec.rb b/spec/serializers/ci/group_variable_entity_spec.rb index 42c4e940421..c4f8543408f 100644 --- a/spec/serializers/ci/group_variable_entity_spec.rb +++ b/spec/serializers/ci/group_variable_entity_spec.rb @@ -11,7 +11,7 @@ RSpec.describe Ci::GroupVariableEntity do it 'contains required fields' do expect(subject.keys).to contain_exactly( - :id, :key, :value, :protected, :variable_type, :environment_scope, :raw, :masked + :id, :key, :description, :value, :protected, :variable_type, :environment_scope, :raw, :masked ) end end diff --git a/spec/serializers/ci/variable_entity_spec.rb b/spec/serializers/ci/variable_entity_spec.rb index 96111604028..184fc100a03 100644 --- a/spec/serializers/ci/variable_entity_spec.rb +++ b/spec/serializers/ci/variable_entity_spec.rb @@ -11,7 +11,7 @@ RSpec.describe Ci::VariableEntity do it 'contains required fields' do expect(subject.keys).to contain_exactly( - :id, :key, :value, :protected, :environment_scope, :variable_type, :raw, :masked + :id, :key, :description, :value, :protected, :environment_scope, :variable_type, :raw, :masked ) end end diff --git a/spec/support/database/prevent_cross_database_modification.rb b/spec/support/database/prevent_cross_database_modification.rb index 02572d011f7..948bc21dafa 100644 --- a/spec/support/database/prevent_cross_database_modification.rb +++ b/spec/support/database/prevent_cross_database_modification.rb @@ -68,4 +68,11 @@ RSpec.configure do |config| ::ApplicationRecord.gitlab_transactions_stack.clear end + + config.before(:suite) do + ActiveSupport::Notifications.subscribe("factory_bot.run_factory") do |_name, _start, _finish, _id, payload| + strategy = payload[:strategy] + Thread.current[:factory_bot_objects] -= 1 if strategy == :create + end + end end diff --git a/spec/support/factory_bot.rb b/spec/support/factory_bot.rb index d30098a5cc0..00aa54990ef 100644 --- a/spec/support/factory_bot.rb +++ b/spec/support/factory_bot.rb @@ -4,13 +4,14 @@ FactoryBot.define do after(:build) do |object, _| next unless object.respond_to?(:factory_bot_built=) + # This will help the PreventCrossDatabaseModification to temporarily + # allow the object table when it's saved later. object.factory_bot_built = true end - before(:create) do |object, _| - next unless object.respond_to?(:factory_bot_built=) - - object.factory_bot_built = false + before(:create) do |_object, _| + Thread.current[:factory_bot_objects] ||= 0 + Thread.current[:factory_bot_objects] += 1 end end diff --git a/spec/support/shared_examples/controllers/variables_shared_examples.rb b/spec/support/shared_examples/controllers/variables_shared_examples.rb index d979683cce7..c807ffaba6f 100644 --- a/spec/support/shared_examples/controllers/variables_shared_examples.rb +++ b/spec/support/shared_examples/controllers/variables_shared_examples.rb @@ -82,7 +82,7 @@ RSpec.shared_examples 'PATCH #update updates variables' do context 'with valid new variable parameters' do let(:variables_attributes) do [ - variable_attributes.merge(secret_value: 'other_value'), + variable_attributes.merge(secret_value: 'other_value', description: 'other_description'), new_variable_attributes ] end @@ -94,6 +94,7 @@ RSpec.shared_examples 'PATCH #update updates variables' do variable.reload expect(variable.value).to eq('other_value') + expect(variable.description).to eq('other_description') expect(variable.raw?).not_to be(old_raw) end diff --git a/spec/tooling/danger/project_helper_spec.rb b/spec/tooling/danger/project_helper_spec.rb index 4eff248a6f0..90409ff5559 100644 --- a/spec/tooling/danger/project_helper_spec.rb +++ b/spec/tooling/danger/project_helper_spec.rb @@ -252,6 +252,8 @@ RSpec.describe Tooling::Danger::ProjectHelper, feature_category: :tooling do [:backend, :analytics_instrumentation] | '+ foo_count(User.active)' | ['lib/gitlab/usage_data.rb'] [:backend] | '+ count(User.active)' | ['user.rb'] [:database, :backend] | '+ User.upsert({ name: "blah" })' | ['app/foo/bar.rb'] + [:database, :backend] | '+ User.upsert(' | ['app/foo/bar.rb'] + [:database, :backend] | '+ Organizations::OrganizationUser.upsert({' | ['app/foo/bar.rb'] [:database, :backend] | '+ upsert({ name: "blah" })' | ['app/foo/bar.rb'] [:database, :backend] | '+ .upsert({ name: "blah" })' | ['app/foo/bar.rb'] [:database, :backend] | '+ .delete_all' | ['app/foo/bar.rb'] diff --git a/spec/workers/bulk_imports/export_request_worker_spec.rb b/spec/workers/bulk_imports/export_request_worker_spec.rb index 2cc6348bb27..25adaef28fd 100644 --- a/spec/workers/bulk_imports/export_request_worker_spec.rb +++ b/spec/workers/bulk_imports/export_request_worker_spec.rb @@ -62,7 +62,7 @@ RSpec.describe BulkImports::ExportRequestWorker, feature_category: :importers do context 'when something goes wrong during source id fetch' do let(:entity_source_id) { 'invalid' } - it 'logs the error & requests relations export using full path url' do + it 'logs the exception as a warning & requests relations export using full path url' do allow(BulkImports::EntityWorker).to receive(:perform_async) expect_next_instance_of(BulkImports::Clients::HTTP) do |client| @@ -74,7 +74,7 @@ RSpec.describe BulkImports::ExportRequestWorker, feature_category: :importers do expect_next_instance_of(BulkImports::Logger) do |logger| expect(logger).to receive(:with_entity).with(entity).and_call_original - expect(logger).to receive(:error).with( + expect(logger).to receive(:warn).with( a_hash_including( 'exception.backtrace' => anything, 'exception.class' => 'NoMethodError', @@ -123,20 +123,6 @@ RSpec.describe BulkImports::ExportRequestWorker, feature_category: :importers do described_class.new.perform(entity.id) end - - context 'when bulk_imports_batched_import_export feature flag is disabled' do - it 'requests relation export without batched param' do - stub_feature_flags(bulk_imports_batched_import_export: false) - - expected_url = "/projects/#{entity.source_xid}/export_relations" - - expect_next_instance_of(BulkImports::Clients::HTTP) do |client| - expect(client).to receive(:post).with(expected_url) - end - - described_class.new.perform(entity.id) - end - end end end diff --git a/spec/workers/gitlab/github_import/import_issue_event_worker_spec.rb b/spec/workers/gitlab/github_import/import_issue_event_worker_spec.rb index aa8243154ef..cbe27934bd5 100644 --- a/spec/workers/gitlab/github_import/import_issue_event_worker_spec.rb +++ b/spec/workers/gitlab/github_import/import_issue_event_worker_spec.rb @@ -5,16 +5,13 @@ require 'spec_helper' RSpec.describe Gitlab::GithubImport::ImportIssueEventWorker, feature_category: :importers do subject(:worker) { described_class.new } - describe '#import' do - let(:import_state) { create(:import_state, :started) } - - let(:project) do - instance_double('Project', full_path: 'foo/bar', id: 1, import_state: import_state) + describe '#execute' do + let_it_be(:project) do + create(:project, import_url: 'https://github.com/foo/bar.git', import_state: create(:import_state, :started)) end - let(:client) { instance_double('Gitlab::GithubImport::Client') } - let(:importer) { instance_double('Gitlab::GithubImport::Importer::IssueEventImporter') } - + let(:client) { instance_double(Gitlab::GithubImport::Client) } + let(:extended_events) { true } let(:event_hash) do { 'id' => 6501124486, @@ -29,23 +26,55 @@ RSpec.describe Gitlab::GithubImport::ImportIssueEventWorker, feature_category: : } end - it 'imports an issue event' do - expect(Gitlab::GithubImport::Importer::IssueEventImporter) - .to receive(:new) - .with( - an_instance_of(Gitlab::GithubImport::Representation::IssueEvent), - project, - client - ) - .and_return(importer) + before do + allow_next_instance_of(Gitlab::GithubImport::Settings) do |setting| + allow(setting).to receive(:extended_events?).and_return(extended_events) + end + end - expect(importer).to receive(:execute) + it 'imports an issue event and increase importer counter' do + expect_next_instance_of(Gitlab::GithubImport::Importer::IssueEventImporter, + an_instance_of(Gitlab::GithubImport::Representation::IssueEvent), + project, + client + ) do |importer| + expect(importer).to receive(:execute) + end expect(Gitlab::GithubImport::ObjectCounter) .to receive(:increment) + .with(project, :issue_event, :imported) .and_call_original worker.import(project, client, event_hash) end + + context 'when event should increment a mapped importer counter' do + before do + stub_const('Gitlab::GithubImport::Importer::IssueEventImporter::EVENT_COUNTER_MAP', { + 'closed' => 'custom_type' + }) + + allow_next_instance_of(Gitlab::GithubImport::Importer::IssueEventImporter) do |importer| + allow(importer).to receive(:execute) + end + end + + it 'increments the mapped importer counter' do + expect(Gitlab::GithubImport::ObjectCounter).to receive(:increment).with(project, 'custom_type', :imported) + + worker.import(project, client, event_hash) + end + + context 'when extended_events is disabled' do + let(:extended_events) { false } + + it 'increments the issue_event importer counter' do + expect(Gitlab::GithubImport::ObjectCounter).to receive(:increment).with(project, :issue_event, :imported) + + worker.import(project, client, event_hash) + end + end + end end end diff --git a/tooling/danger/project_helper.rb b/tooling/danger/project_helper.rb index 633516591a8..bf2dba64065 100644 --- a/tooling/danger/project_helper.rb +++ b/tooling/danger/project_helper.rb @@ -105,7 +105,7 @@ module Tooling %r{\A(app/models/project_authorization|app/services/users/refresh_authorized_projects_service)(/|\.rb)} => [:database, :backend], %r{\A((ee|jh)/)?app/finders/} => [:database, :backend], %r{\Arubocop/cop/migration(/|\.rb)} => :database, - [%r{\A((ee|jh)/)?(app|lib)/.+\.rb}, %r{\A\+\s+(\w*\.)?(update_all|upsert|upsert_all|delete_all|destroy_all)(\(.*\))?\s*\z}] => [:database, :backend], + [%r{\A((ee|jh)/)?(app|lib)/.+\.rb}, %r{\A\+\s+(\S*\.)?(update_all|upsert|upsert_all|delete_all|destroy_all)(\(.*\)|\(|\(.*)?\s*\z}] => [:database, :backend], %r{\Alib/gitlab/ci/templates} => :ci_template, |