diff --git a/.gitlab/ci/rules.gitlab-ci.yml b/.gitlab/ci/rules.gitlab-ci.yml index b93abae916e..3495fba499e 100644 --- a/.gitlab/ci/rules.gitlab-ci.yml +++ b/.gitlab/ci/rules.gitlab-ci.yml @@ -1680,6 +1680,8 @@ when: never - <<: *if-security-merge-request when: never + - <<: *if-merge-request-targeting-stable-branch + when: never - !reference [.frontend:rules:jest, rules] ################ diff --git a/.rubocop_todo/layout/line_length.yml b/.rubocop_todo/layout/line_length.yml index 5ea230fbdd6..60e60e868ad 100644 --- a/.rubocop_todo/layout/line_length.yml +++ b/.rubocop_todo/layout/line_length.yml @@ -1932,7 +1932,6 @@ Layout/LineLength: - 'lib/api/rubygem_packages.rb' - 'lib/api/settings.rb' - 'lib/api/snippet_repository_storage_moves.rb' - - 'lib/api/snippets.rb' - 'lib/api/submodules.rb' - 'lib/api/suggestions.rb' - 'lib/api/tags.rb' diff --git a/app/assets/javascripts/batch_comments/components/submit_dropdown.vue b/app/assets/javascripts/batch_comments/components/submit_dropdown.vue index e06dc85d396..b2f54d6112d 100644 --- a/app/assets/javascripts/batch_comments/components/submit_dropdown.vue +++ b/app/assets/javascripts/batch_comments/components/submit_dropdown.vue @@ -244,7 +244,7 @@ export default { placement="bottom-end" class="submit-review-dropdown" :class="{ 'submit-review-dropdown-animated': shouldAnimateReviewButton }" - data-testid="submit-review-dropdown" + data-testid="review-drawer-toggle" fluid-width @beforeClose="onBeforeClose" @shown="setDropdownVisible(true)" diff --git a/app/assets/javascripts/batch_comments/components/submit_review_button.vue b/app/assets/javascripts/batch_comments/components/submit_review_button.vue index 59c90fe1358..23cc0e1c4f2 100644 --- a/app/assets/javascripts/batch_comments/components/submit_review_button.vue +++ b/app/assets/javascripts/batch_comments/components/submit_review_button.vue @@ -20,7 +20,7 @@ export default { diff --git a/app/assets/javascripts/diffs/components/tree_list.vue b/app/assets/javascripts/diffs/components/tree_list.vue index 4e942ce3da0..7e339e73e29 100644 --- a/app/assets/javascripts/diffs/components/tree_list.vue +++ b/app/assets/javascripts/diffs/components/tree_list.vue @@ -230,12 +230,26 @@ export default { diff --git a/app/assets/javascripts/work_items/components/work_item_detail.vue b/app/assets/javascripts/work_items/components/work_item_detail.vue index 6755a5dac70..e1f6a6b814c 100644 --- a/app/assets/javascripts/work_items/components/work_item_detail.vue +++ b/app/assets/javascripts/work_items/components/work_item_detail.vue @@ -451,9 +451,6 @@ export default { showWorkItemTree() { return this.findWidget(WIDGET_TYPE_HIERARCHY) && this.allowedChildTypes?.length > 0; }, - showWorkItemVulnerabilities() { - return this.glFeatures.workItemRelatedVulnerabilities; - }, titleClassHeader() { return { 'sm:!gl-hidden gl-mt-3': this.shouldShowAncestors, @@ -1219,7 +1216,6 @@ export default { /> work_item_type_id) - end - def create_issue(issue_attributes, project_id) label_ids = issue_attributes.delete('label_ids') assignee_ids = issue_attributes.delete('assignee_ids') - issue_id = insert_and_return_id(ensure_correct_work_item_type(issue_attributes), Issue) + issue_id = insert_and_return_id(issue_attributes, Issue) label_issue(project_id, issue_id, label_ids) assign_issue(project_id, issue_id, assignee_ids) diff --git a/app/workers/packages/cleanup_package_file_worker.rb b/app/workers/packages/cleanup_package_file_worker.rb index 180efd50ef3..8f0acc1618c 100644 --- a/app/workers/packages/cleanup_package_file_worker.rb +++ b/app/workers/packages/cleanup_package_file_worker.rb @@ -13,20 +13,30 @@ module Packages worker_resource_boundary :unknown idempotent! + delegate :package, :conan_file_metadatum, to: :artifact, private: true + delegate :recipe_revision, :package_reference, :package_revision, to: :conan_file_metadatum, private: true + def max_running_jobs ::Gitlab::CurrentSettings.packages_cleanup_package_file_worker_capacity end private + def before_destroy + # Load the metadatum into the memory for subsequent operations, since the metadatum is deleted + # by CASCADE delete when package file is deleted. + conan_file_metadatum if package.conan? + end + def after_destroy - pkg = artifact.package # Ml::ModelVersion need the package to be able to upload files later # Issue https://gitlab.com/gitlab-org/gitlab/-/issues/461322 - return if pkg.ml_model? + return if package.ml_model? - pkg.transaction do - pkg.destroy if model.for_package_ids(pkg.id).empty? + cleanup_conan_objects if package.conan? + + package.transaction do + package.destroy if model.for_package_ids(package.id).empty? end end @@ -38,6 +48,16 @@ module Packages model.next_pending_destruction(order_by: :id) end + def cleanup_conan_objects + return unless conan_file_metadatum + + # return early as destroy will trigger the cascading delete + return if recipe_revision&.orphan? && recipe_revision.destroy + return if package_reference&.orphan? && package_reference.destroy + + package_revision.destroy if package_revision&.orphan? + end + def log_metadata(package_file) log_extra_metadata_on_done(:package_file_id, package_file.id) log_extra_metadata_on_done(:package_id, package_file.package_id) diff --git a/config/feature_flags/wip/improved_review_experience.yml b/config/feature_flags/beta/improved_review_experience.yml similarity index 75% rename from config/feature_flags/wip/improved_review_experience.yml rename to config/feature_flags/beta/improved_review_experience.yml index 62d716a1f6a..83622b1998c 100644 --- a/config/feature_flags/wip/improved_review_experience.yml +++ b/config/feature_flags/beta/improved_review_experience.yml @@ -2,8 +2,8 @@ name: improved_review_experience feature_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/525841 introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/185795 -rollout_issue_url: +rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/535461 milestone: '17.11' group: group::code review -type: wip +type: beta default_enabled: false diff --git a/db/docs/ci_builds_metadata.yml b/db/docs/deleted_tables/ci_builds_metadata.yml similarity index 75% rename from db/docs/ci_builds_metadata.yml rename to db/docs/deleted_tables/ci_builds_metadata.yml index 3a26936d42c..af8666a04e8 100644 --- a/db/docs/ci_builds_metadata.yml +++ b/db/docs/deleted_tables/ci_builds_metadata.yml @@ -10,3 +10,5 @@ gitlab_schema: gitlab_ci sharding_key: project_id: projects table_size: over_limit +removed_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/191033 +removed_in_milestone: '18.1' diff --git a/db/migrate/20250509115821_add_orcid_to_user.rb b/db/migrate/20250509115821_add_orcid_to_user.rb new file mode 100644 index 00000000000..77d47df35f6 --- /dev/null +++ b/db/migrate/20250509115821_add_orcid_to_user.rb @@ -0,0 +1,25 @@ +# frozen_string_literal: true + +# See https://docs.gitlab.com/ee/development/migration_style_guide.html +# for more information on how to write migrations for GitLab. + +class AddOrcidToUser < Gitlab::Database::Migration[2.3] + USER_DETAILS_FIELD_LIMIT = 256 + disable_ddl_transaction! + + milestone '18.0' + + def up + with_lock_retries do + add_column :user_details, :orcid, :text, default: '', null: false, if_not_exists: true + end + + add_text_limit :user_details, :orcid, USER_DETAILS_FIELD_LIMIT + end + + def down + with_lock_retries do + remove_column :user_details, :orcid + end + end +end diff --git a/db/post_migrate/20250512121701_move_ci_builds_metadata_to_dynamic_schema.rb b/db/post_migrate/20250512121701_move_ci_builds_metadata_to_dynamic_schema.rb new file mode 100644 index 00000000000..6b32f01018e --- /dev/null +++ b/db/post_migrate/20250512121701_move_ci_builds_metadata_to_dynamic_schema.rb @@ -0,0 +1,35 @@ +# frozen_string_literal: true + +class MoveCiBuildsMetadataToDynamicSchema < Gitlab::Database::Migration[2.3] + include Gitlab::Database::MigrationHelpers::WraparoundAutovacuum + + milestone '18.1' + + DYNAMIC_SCHEMA = Gitlab::Database::DYNAMIC_PARTITIONS_SCHEMA + TABLE_NAME = :ci_builds_metadata + + def up + return unless can_execute_on?(TABLE_NAME) + + connection.execute(<<~SQL) + ALTER TABLE IF EXISTS #{TABLE_NAME} SET SCHEMA #{DYNAMIC_SCHEMA}; + SQL + end + + def down + return unless can_execute_on?(TABLE_NAME) + + table_identifier = "#{DYNAMIC_SCHEMA}.#{TABLE_NAME}" + + if table_exists?(table_identifier) + connection.execute(<<~SQL) + ALTER TABLE IF EXISTS #{table_identifier} SET SCHEMA #{connection.current_schema}; + SQL + else # In tests we set the database from structure.sql, so the table doesn't exist + connection.execute(<<~SQL) + DROP TABLE IF EXISTS #{DYNAMIC_SCHEMA}.#{TABLE_NAME}_100; + CREATE TABLE IF NOT EXISTS #{TABLE_NAME} PARTITION OF p_#{TABLE_NAME} FOR VALUES IN (100); + SQL + end + end +end diff --git a/db/schema_migrations/20250509115821 b/db/schema_migrations/20250509115821 new file mode 100644 index 00000000000..f72d96bfccb --- /dev/null +++ b/db/schema_migrations/20250509115821 @@ -0,0 +1 @@ +d80822eca404b199f56ef3659fdc09c5c3452dc10e5339762c708ac4e099a5b3 \ No newline at end of file diff --git a/db/schema_migrations/20250512121701 b/db/schema_migrations/20250512121701 new file mode 100644 index 00000000000..f4b974253d6 --- /dev/null +++ b/db/schema_migrations/20250512121701 @@ -0,0 +1 @@ +39935f20dc0a333502460214553dc4dd35be6016a17df17e52f0f379cf0a88d3 \ No newline at end of file diff --git a/db/structure.sql b/db/structure.sql index 114e7ab467f..7a553339367 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -10901,25 +10901,6 @@ CREATE SEQUENCE ci_builds_metadata_id_seq ALTER SEQUENCE ci_builds_metadata_id_seq OWNED BY p_ci_builds_metadata.id; -CREATE TABLE ci_builds_metadata ( - project_id bigint NOT NULL, - timeout integer, - timeout_source integer DEFAULT 1 NOT NULL, - interruptible boolean, - config_options jsonb, - config_variables jsonb, - has_exposed_artifacts boolean, - environment_auto_stop_in character varying(255), - expanded_environment_name character varying(255), - secrets jsonb DEFAULT '{}'::jsonb NOT NULL, - build_id bigint NOT NULL, - id bigint DEFAULT nextval('ci_builds_metadata_id_seq'::regclass) NOT NULL, - id_tokens jsonb DEFAULT '{}'::jsonb NOT NULL, - partition_id bigint NOT NULL, - debug_trace_enabled boolean DEFAULT false NOT NULL, - exit_code smallint -); - CREATE TABLE ci_builds_runner_session ( id bigint NOT NULL, url character varying NOT NULL, @@ -24075,6 +24056,7 @@ CREATE TABLE user_details ( onboarding_status jsonb DEFAULT '{}'::jsonb NOT NULL, bluesky text DEFAULT ''::text NOT NULL, bot_namespace_id bigint, + orcid text DEFAULT ''::text NOT NULL, CONSTRAINT check_18a53381cd CHECK ((char_length(bluesky) <= 256)), CONSTRAINT check_245664af82 CHECK ((char_length(webauthn_xid) <= 100)), CONSTRAINT check_444573ee52 CHECK ((char_length(skype) <= 500)), @@ -24084,6 +24066,7 @@ CREATE TABLE user_details ( CONSTRAINT check_7d6489f8f3 CHECK ((char_length(linkedin) <= 500)), CONSTRAINT check_7fe2044093 CHECK ((char_length(website_url) <= 500)), CONSTRAINT check_8a7fcf8a60 CHECK ((char_length(location) <= 500)), + CONSTRAINT check_99b0365865 CHECK ((char_length(orcid) <= 256)), CONSTRAINT check_a73b398c60 CHECK ((char_length(phone) <= 50)), CONSTRAINT check_eeeaf8d4f0 CHECK ((char_length(pronouns) <= 50)), CONSTRAINT check_f1a8a05b9a CHECK ((char_length(mastodon) <= 500)), @@ -26600,8 +26583,6 @@ ALTER TABLE ONLY uploads_9ba88c4165 ATTACH PARTITION bulk_import_export_upload_u ALTER TABLE ONLY p_ci_builds ATTACH PARTITION ci_builds FOR VALUES IN ('100'); -ALTER TABLE ONLY p_ci_builds_metadata ATTACH PARTITION ci_builds_metadata FOR VALUES IN ('100'); - ALTER TABLE ONLY p_ci_job_artifacts ATTACH PARTITION ci_job_artifacts FOR VALUES IN ('100', '101'); ALTER TABLE ONLY p_ci_pipelines ATTACH PARTITION ci_pipelines FOR VALUES IN ('100', '101', '102'); @@ -29115,12 +29096,6 @@ ALTER TABLE ONLY ci_build_report_results ALTER TABLE ONLY ci_build_trace_chunks ADD CONSTRAINT ci_build_trace_chunks_pkey PRIMARY KEY (id); -ALTER TABLE ONLY p_ci_builds_metadata - ADD CONSTRAINT p_ci_builds_metadata_pkey PRIMARY KEY (id, partition_id); - -ALTER TABLE ONLY ci_builds_metadata - ADD CONSTRAINT ci_builds_metadata_pkey PRIMARY KEY (id, partition_id); - ALTER TABLE ONLY p_ci_builds ADD CONSTRAINT p_ci_builds_pkey PRIMARY KEY (id, partition_id); @@ -30279,6 +30254,9 @@ ALTER TABLE ONLY p_ci_build_trace_metadata ALTER TABLE ONLY p_ci_builds_execution_configs ADD CONSTRAINT p_ci_builds_execution_configs_pkey PRIMARY KEY (id, partition_id); +ALTER TABLE ONLY p_ci_builds_metadata + ADD CONSTRAINT p_ci_builds_metadata_pkey PRIMARY KEY (id, partition_id); + ALTER TABLE ONLY p_ci_finished_build_ch_sync_events ADD CONSTRAINT p_ci_finished_build_ch_sync_events_pkey PRIMARY KEY (build_id, partition); @@ -34124,22 +34102,6 @@ CREATE INDEX index_ci_build_trace_chunks_on_partition_id_build_id ON ci_build_tr CREATE INDEX index_ci_build_trace_chunks_on_project_id ON ci_build_trace_chunks USING btree (project_id); -CREATE INDEX p_ci_builds_metadata_build_id_idx ON ONLY p_ci_builds_metadata USING btree (build_id) WHERE (has_exposed_artifacts IS TRUE); - -CREATE INDEX index_ci_builds_metadata_on_build_id_and_has_exposed_artifacts ON ci_builds_metadata USING btree (build_id) WHERE (has_exposed_artifacts IS TRUE); - -CREATE INDEX p_ci_builds_metadata_build_id_id_idx ON ONLY p_ci_builds_metadata USING btree (build_id) INCLUDE (id) WHERE (interruptible = true); - -CREATE INDEX index_ci_builds_metadata_on_build_id_and_id_and_interruptible ON ci_builds_metadata USING btree (build_id) INCLUDE (id) WHERE (interruptible = true); - -CREATE UNIQUE INDEX p_ci_builds_metadata_build_id_partition_id_idx ON ONLY p_ci_builds_metadata USING btree (build_id, partition_id); - -CREATE UNIQUE INDEX index_ci_builds_metadata_on_build_id_partition_id_unique ON ci_builds_metadata USING btree (build_id, partition_id); - -CREATE INDEX p_ci_builds_metadata_project_id_idx ON ONLY p_ci_builds_metadata USING btree (project_id); - -CREATE INDEX index_ci_builds_metadata_on_project_id ON ci_builds_metadata USING btree (project_id); - CREATE INDEX p_ci_builds_auto_canceled_by_id_idx ON ONLY p_ci_builds USING btree (auto_canceled_by_id) WHERE (auto_canceled_by_id IS NOT NULL); CREATE INDEX index_ci_builds_on_auto_canceled_by_id ON ci_builds USING btree (auto_canceled_by_id) WHERE (auto_canceled_by_id IS NOT NULL); @@ -38302,6 +38264,14 @@ CREATE INDEX organization_detail_uploads_uploaded_by_user_id_idx ON organization CREATE INDEX organization_detail_uploads_uploader_path_idx ON organization_detail_uploads USING btree (uploader, path); +CREATE INDEX p_ci_builds_metadata_build_id_id_idx ON ONLY p_ci_builds_metadata USING btree (build_id) INCLUDE (id) WHERE (interruptible = true); + +CREATE INDEX p_ci_builds_metadata_build_id_idx ON ONLY p_ci_builds_metadata USING btree (build_id) WHERE (has_exposed_artifacts IS TRUE); + +CREATE UNIQUE INDEX p_ci_builds_metadata_build_id_partition_id_idx ON ONLY p_ci_builds_metadata USING btree (build_id, partition_id); + +CREATE INDEX p_ci_builds_metadata_project_id_idx ON ONLY p_ci_builds_metadata USING btree (project_id); + CREATE INDEX p_ci_builds_scheduled_at_idx ON ONLY p_ci_builds USING btree (scheduled_at) WHERE ((scheduled_at IS NOT NULL) AND ((type)::text = 'Ci::Build'::text) AND ((status)::text = 'scheduled'::text)); CREATE UNIQUE INDEX p_ci_builds_token_encrypted_partition_id_idx ON ONLY p_ci_builds USING btree (token_encrypted, partition_id) WHERE (token_encrypted IS NOT NULL); @@ -40502,8 +40472,6 @@ ALTER INDEX index_uploads_9ba88c4165_on_uploader_and_path ATTACH PARTITION bulk_ ALTER INDEX p_ci_builds_status_created_at_project_id_idx ATTACH PARTITION ci_builds_gitlab_monitor_metrics; -ALTER INDEX p_ci_builds_metadata_pkey ATTACH PARTITION ci_builds_metadata_pkey; - ALTER INDEX p_ci_builds_pkey ATTACH PARTITION ci_builds_pkey; ALTER INDEX p_ci_job_artifacts_pkey ATTACH PARTITION ci_job_artifacts_pkey; @@ -40670,14 +40638,6 @@ ALTER INDEX tmp_p_ci_builds_trigger_request_id_idx ATTACH PARTITION index_437b18 ALTER INDEX index_ci_runner_machines_on_executor_type ATTACH PARTITION index_aa3b4fe8c6; -ALTER INDEX p_ci_builds_metadata_build_id_idx ATTACH PARTITION index_ci_builds_metadata_on_build_id_and_has_exposed_artifacts; - -ALTER INDEX p_ci_builds_metadata_build_id_id_idx ATTACH PARTITION index_ci_builds_metadata_on_build_id_and_id_and_interruptible; - -ALTER INDEX p_ci_builds_metadata_build_id_partition_id_idx ATTACH PARTITION index_ci_builds_metadata_on_build_id_partition_id_unique; - -ALTER INDEX p_ci_builds_metadata_project_id_idx ATTACH PARTITION index_ci_builds_metadata_on_project_id; - ALTER INDEX p_ci_builds_auto_canceled_by_id_idx ATTACH PARTITION index_ci_builds_on_auto_canceled_by_id; ALTER INDEX p_ci_builds_commit_id_stage_idx_created_at_idx ATTACH PARTITION index_ci_builds_on_commit_id_and_stage_idx_and_created_at; diff --git a/doc/administration/geo/secondary_proxy/runners.md b/doc/administration/geo/secondary_proxy/runners.md index 89afbb90aa0..71ad743c13e 100644 --- a/doc/administration/geo/secondary_proxy/runners.md +++ b/doc/administration/geo/secondary_proxy/runners.md @@ -2,13 +2,14 @@ stage: Tenant Scale group: Geo info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://handbook.gitlab.com/handbook/product/ux/technical-writing/#assignments +gitlab_dedicated: yes title: Secondary runners --- {{< details >}} - Tier: Premium, Ultimate -- Offering: GitLab Self-Managed +- Offering: GitLab Self-Managed, GitLab Dedicated {{< /details >}} @@ -29,6 +30,12 @@ The jobs that start during the first stage of a pipeline almost always have thei ## Use secondary runners with a Location Aware public URL (Unified URL) +{{< details >}} + +- Offering: GitLab Self-Managed + +{{< /details >}} + Using [Location-Aware DNS](_index.md#configure-location-aware-dns), with the feature flag enabled works with no extra configuration. After you install and register a runner in the same location as a secondary site, it automatically talks to the closest site, and only proxies to the primary if the secondary is out of date. ## Use secondary runners with separate URLs @@ -44,6 +51,12 @@ When executing [a planned failover](../disaster_recovery/planned_failover.md), s ### With Location Aware public URL +{{< details >}} + +- Offering: GitLab Self-Managed + +{{< /details >}} + When using [Location-Aware DNS](_index.md#configure-location-aware-dns), all runners automatically connect to the closest Geo site. When failing over to a new primary: diff --git a/doc/administration/integration/diagrams_net.md b/doc/administration/integration/diagrams_net.md index c8b68d3e168..2f8a345f2c7 100644 --- a/doc/administration/integration/diagrams_net.md +++ b/doc/administration/integration/diagrams_net.md @@ -2,14 +2,15 @@ stage: Create group: Source Code info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://handbook.gitlab.com/handbook/product/ux/technical-writing/#assignments -description: Configure a Diagrams.net integration for GitLab Self-Managed. +description: Configure a Diagrams.net integration for GitLab. +gitlab_dedicated: yes title: Diagrams.net --- {{< details >}} - Tier: Free, Premium, Ultimate -- Offering: GitLab Self-Managed +- Offering: GitLab Self-Managed, GitLab Dedicated {{< /details >}} @@ -25,7 +26,7 @@ The diagram editor is available in both the plain text editor and the rich text On GitLab.com, this integration is enabled for all SaaS users and does not require any additional configuration. -On GitLab Self-Managed, you can choose to integrate with the free [diagrams.net](https://www.drawio.com/) +On GitLab Self-Managed and GitLab Dedicated, you can choose to integrate with the free [diagrams.net](https://www.drawio.com/) website, or host your own diagrams.net site in offline environments. To set up the integration, you must: diff --git a/doc/administration/integration/kroki.md b/doc/administration/integration/kroki.md index e60b8914c14..ad636565dba 100644 --- a/doc/administration/integration/kroki.md +++ b/doc/administration/integration/kroki.md @@ -2,13 +2,14 @@ stage: Plan group: Project Management info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://handbook.gitlab.com/handbook/product/ux/technical-writing/#assignments +gitlab_dedicated: yes title: Kroki --- {{< details >}} - Tier: Free, Premium, Ultimate -- Offering: GitLab Self-Managed +- Offering: GitLab Self-Managed, GitLab Dedicated {{< /details >}} diff --git a/doc/administration/polling.md b/doc/administration/polling.md index 8b4f26721ca..d56a0ed9754 100644 --- a/doc/administration/polling.md +++ b/doc/administration/polling.md @@ -2,13 +2,14 @@ stage: Systems group: Distribution info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://handbook.gitlab.com/handbook/product/ux/technical-writing/#assignments +gitlab_dedicated: yes title: Polling interval multiplier --- {{< details >}} - Tier: Free, Premium, Ultimate -- Offering: GitLab Self-Managed +- Offering: GitLab Self-Managed, GitLab Dedicated {{< /details >}} diff --git a/doc/administration/review_spam_logs.md b/doc/administration/review_spam_logs.md index c19bbd2c419..3f257bd0afb 100644 --- a/doc/administration/review_spam_logs.md +++ b/doc/administration/review_spam_logs.md @@ -2,13 +2,14 @@ stage: Software Supply Chain Security group: Authorization info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://handbook.gitlab.com/handbook/product/ux/technical-writing/#assignments +gitlab_dedicated: yes title: Review spam logs --- {{< details >}} - Tier: Free, Premium, Ultimate -- Offering: GitLab Self-Managed +- Offering: GitLab Self-Managed, GitLab Dedicated {{< /details >}} diff --git a/doc/administration/settings/deprecated_api_rate_limits.md b/doc/administration/settings/deprecated_api_rate_limits.md index 99fba56e87e..191d174ce00 100644 --- a/doc/administration/settings/deprecated_api_rate_limits.md +++ b/doc/administration/settings/deprecated_api_rate_limits.md @@ -2,14 +2,15 @@ stage: Create group: Source Code info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://handbook.gitlab.com/handbook/product/ux/technical-writing/#assignments -description: Define limits for deprecated APIs on GitLab Self-Managed. +description: Define limits for deprecated APIs on GitLab. +gitlab_dedicated: yes title: Deprecated API rate limits --- {{< details >}} - Tier: Free, Premium, Ultimate -- Offering: GitLab Self-Managed +- Offering: GitLab Self-Managed, GitLab Dedicated {{< /details >}} diff --git a/doc/api/graphql/reference/_index.md b/doc/api/graphql/reference/_index.md index 63670237fc5..5c87c60203e 100644 --- a/doc/api/graphql/reference/_index.md +++ b/doc/api/graphql/reference/_index.md @@ -28236,6 +28236,7 @@ four standard [pagination arguments](#pagination-arguments): | ---- | ---- | ----------- | | `componentIds` | [`[SbomComponentID!]`](#sbomcomponentid) | Filter dependencies by component IDs. | | `componentNames` | [`[String!]`](#string) | Filter dependencies by component names. | +| `componentVersions` | [`[String!]`](#string) | Filter dependencies by component versions. | | `packageManagers` | [`[PackageManager!]`](#packagemanager) | Filter dependencies by package managers. | | `sort` | [`DependencySort`](#dependencysort) | Sort dependencies by given criteria. | | `sourceTypes` | [`[SbomSourceType!]`](#sbomsourcetype) | Filter dependencies by source type. | @@ -28261,6 +28262,7 @@ four standard [pagination arguments](#pagination-arguments): | ---- | ---- | ----------- | | `componentIds` | [`[SbomComponentID!]`](#sbomcomponentid) | Filter dependencies by component IDs. | | `componentNames` | [`[String!]`](#string) | Filter dependencies by component names. | +| `componentVersions` | [`[String!]`](#string) | Filter dependencies by component versions. | | `packageManagers` | [`[PackageManager!]`](#packagemanager) | Filter dependencies by package managers. | | `projectCountMax` | [`Int`](#int) | Filter dependencies by maximum project count. | | `projectCountMin` | [`Int`](#int) | Filter dependencies by minimum project count. | @@ -35874,6 +35876,7 @@ four standard [pagination arguments](#pagination-arguments): | ---- | ---- | ----------- | | `componentIds` | [`[SbomComponentID!]`](#sbomcomponentid) | Filter dependencies by component IDs. | | `componentNames` | [`[String!]`](#string) | Filter dependencies by component names. | +| `componentVersions` | [`[String!]`](#string) | Filter dependencies by component versions. | | `packageManagers` | [`[PackageManager!]`](#packagemanager) | Filter dependencies by package managers. | | `sort` | [`DependencySort`](#dependencysort) | Sort dependencies by given criteria. | | `sourceTypes` | [`[SbomSourceType!]`](#sbomsourcetype) | Filter dependencies by source type. | diff --git a/doc/api/license.md b/doc/api/license.md index 5e1c49953e1..69b7f2b358b 100644 --- a/doc/api/license.md +++ b/doc/api/license.md @@ -2,13 +2,14 @@ stage: Fulfillment group: Utilization info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://handbook.gitlab.com/handbook/product/ux/technical-writing/#assignments +gitlab_dedicated: yes title: License API --- {{< details >}} - Tier: Free, Premium, Ultimate -- Offering: GitLab Self-Managed +- Offering: GitLab Self-Managed, GitLab Dedicated {{< /details >}} diff --git a/doc/api/sidekiq_metrics.md b/doc/api/sidekiq_metrics.md index 9badb3af03f..c191c701f60 100644 --- a/doc/api/sidekiq_metrics.md +++ b/doc/api/sidekiq_metrics.md @@ -2,13 +2,14 @@ stage: Systems group: Distribution info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://handbook.gitlab.com/handbook/product/ux/technical-writing/#assignments +gitlab_dedicated: yes title: Sidekiq Metrics API --- {{< details >}} - Tier: Free, Premium, Ultimate -- Offering: GitLab Self-Managed +- Offering: GitLab Self-Managed, GitLab Dedicated {{< /details >}} diff --git a/doc/ci/docker/_index.md b/doc/ci/docker/_index.md index 2e90ea1df88..0e75ac748a9 100644 --- a/doc/ci/docker/_index.md +++ b/doc/ci/docker/_index.md @@ -23,7 +23,7 @@ You can incorporate [Docker](https://www.docker.com) into your CI/CD workflow in or in the GitLab container registry. Your job then runs in a container that's based on the image. The container has all the Node dependencies you need to build your app. -- **Use [Docker](using_docker_build.md) or [kaniko](using_kaniko.md) to build Docker images.** +- **Use [Docker](using_docker_build.md) to build Docker images.** You can create CI/CD jobs to build Docker images and publish them to a container registry. diff --git a/doc/ci/docker/using_docker_build.md b/doc/ci/docker/using_docker_build.md index 616e6e4e7ef..97856af43b7 100644 --- a/doc/ci/docker/using_docker_build.md +++ b/doc/ci/docker/using_docker_build.md @@ -748,11 +748,8 @@ and [using the OverlayFS storage driver](https://docs.docker.com/storage/storage ## Docker alternatives -To build Docker images without enabling privileged mode on the runner, you can -use one of these alternatives: - -- [`kaniko`](using_kaniko.md). -- [`buildah`](#buildah-example). +To build Docker images without enabling privileged mode on the runner, +use [`buildah`](#buildah-example). ### Buildah example @@ -987,7 +984,7 @@ To resolve this issue: image: name: docker:19.03 variables: - DOCKER_HOST: tcp://localhost:2375 + DOCKER_HOST: tcp://localhost:2375 DOCKER_TLS_CERTDIR: "" CA_CERTIFICATE: "$CA_CERTIFICATE" services: @@ -999,7 +996,7 @@ To resolve this issue: echo "$CA_CERTIFICATE" > /usr/local/share/ca-certificates/custom-ca.crt && \ update-ca-certificates && \ dockerd-entrypoint.sh || exit - script: + script: - docker info - docker login -u $DOCKER_USERNAME -p $DOCKER_PASSWORD $DOCKER_REGISTRY - docker build -t "${DOCKER_REGISTRY}/my-app:${CI_COMMIT_REF_NAME}" . diff --git a/doc/subscriptions/gitlab_com/gitlab_subscription_troubleshooting.md b/doc/subscriptions/gitlab_com/gitlab_subscription_troubleshooting.md index dab931e12ec..b203dc6012f 100644 --- a/doc/subscriptions/gitlab_com/gitlab_subscription_troubleshooting.md +++ b/doc/subscriptions/gitlab_com/gitlab_subscription_troubleshooting.md @@ -3,17 +3,18 @@ stage: Fulfillment group: Subscription Management info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://handbook.gitlab.com/handbook/product/ux/technical-writing/#assignments description: Seat usage, compute minutes, storage limits, renewal info. +gitlab_dedicated: yes title: Troubleshooting GitLab subscription --- {{< details >}} - Tier: Premium, Ultimate -- Offering: GitLab.com, GitLab Self-Managed +- Offering: GitLab.com, GitLab Self-Managed, GitLab Dedicated {{< /details >}} -When you purchase or use subscriptions for GitLab.com or GitLab Self-Managed, you might encounter the following issues. +When you purchase or use subscriptions for GitLab, you might encounter the following issues. ## Credit card declined @@ -93,7 +94,7 @@ Ensure that you have the Owner role for that namespace, and review the [transfer ## Subscription data fails to synchronize -On GitLab Self-Managed, your subscription data might fail to synchronize. +On GitLab Self-Managed or GitLab Dedicated, your subscription data might fail to synchronize. This issue can occur when network traffic between your GitLab instance and certain IP addresses is not allowed. diff --git a/doc/user/application_security/vulnerability_report/_index.md b/doc/user/application_security/vulnerability_report/_index.md index c8cec04f7c8..c82ea2d19b0 100644 --- a/doc/user/application_security/vulnerability_report/_index.md +++ b/doc/user/application_security/vulnerability_report/_index.md @@ -356,16 +356,10 @@ For each selected vulnerability: - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/13216) in GitLab 17.9 [with a flag](../../../administration/feature_flags.md) named `enhanced_vulnerability_bulk_actions`. Disabled by default. - [Enabled on GitLab.com, GitLab Self-Managed, and GitLab Dedicated](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/190213) in GitLab 18.0. +- [Generally available](https://gitlab.com/gitlab-org/gitlab/-/issues/515204) in GitLab 18.1. Feature flag `enhanced_vulnerability_bulk_actions` removed. {{< /history >}} -{{< alert type="flag" >}} - -The availability of this feature is controlled by a feature flag. -For more information, see the history. - -{{< /alert >}} - You can link one or more vulnerabilities to existing issues in the vulnerability report. Prerequisites: diff --git a/gems/activerecord-gitlab/Gemfile b/gems/activerecord-gitlab/Gemfile index 6fa23eafde9..f05d7b9df8e 100644 --- a/gems/activerecord-gitlab/Gemfile +++ b/gems/activerecord-gitlab/Gemfile @@ -4,4 +4,4 @@ source "https://rubygems.org" gemspec -gem 'activerecord', '~> 7.0.8' # rubocop:disable Gemfile/MissingFeatureCategory +gem 'activerecord', '~> 7.1.5.1' # rubocop:disable Gemfile/MissingFeatureCategory diff --git a/gems/activerecord-gitlab/Gemfile.lock b/gems/activerecord-gitlab/Gemfile.lock index 7acf26b9f48..25b40a992de 100644 --- a/gems/activerecord-gitlab/Gemfile.lock +++ b/gems/activerecord-gitlab/Gemfile.lock @@ -7,19 +7,33 @@ PATH GEM remote: https://rubygems.org/ specs: - activemodel (7.0.8.7) - activesupport (= 7.0.8.7) - activerecord (7.0.8.7) - activemodel (= 7.0.8.7) - activesupport (= 7.0.8.7) - activesupport (7.0.8.7) + activemodel (7.1.5.1) + activesupport (= 7.1.5.1) + activerecord (7.1.5.1) + activemodel (= 7.1.5.1) + activesupport (= 7.1.5.1) + timeout (>= 0.4.0) + activesupport (7.1.5.1) + base64 + benchmark (>= 0.3) + bigdecimal concurrent-ruby (~> 1.0, >= 1.0.2) + connection_pool (>= 2.2.5) + drb i18n (>= 1.6, < 2) + logger (>= 1.4.2) minitest (>= 5.1) + mutex_m + securerandom (>= 0.3) tzinfo (~> 2.0) ast (2.4.2) + base64 (0.2.0) + benchmark (0.4.0) + bigdecimal (3.1.9) concurrent-ruby (1.2.2) + connection_pool (2.5.3) diff-lcs (1.5.0) + drb (2.2.1) gitlab-styles (10.1.0) rubocop (~> 1.50.2) rubocop-graphql (~> 0.18) @@ -29,8 +43,10 @@ GEM i18n (1.13.0) concurrent-ruby (~> 1.0) json (2.6.3) + logger (1.7.0) mini_portile2 (2.8.2) minitest (5.18.0) + mutex_m (0.3.0) parallel (1.23.0) parser (3.2.2.3) ast (~> 2.4.1) @@ -83,8 +99,10 @@ GEM rubocop-capybara (~> 2.17) rubocop-factory_bot (~> 2.22) ruby-progressbar (1.13.0) + securerandom (0.4.1) sqlite3 (1.6.3) mini_portile2 (~> 2.8.0) + timeout (0.4.3) tzinfo (2.0.6) concurrent-ruby (~> 1.0) unicode-display_width (2.4.2) @@ -93,7 +111,7 @@ PLATFORMS ruby DEPENDENCIES - activerecord (~> 7.0.8) + activerecord (~> 7.1.5.1) activerecord-gitlab! gitlab-styles (~> 10.1.0) rspec (~> 3.12) @@ -102,18 +120,25 @@ DEPENDENCIES sqlite3 (~> 1.6) CHECKSUMS - activemodel (7.0.8.7) sha256=f13b04bb055c1e85b965ce40b0a2e671b8d97835083597bc7fbc04cde0f40a83 - activerecord (7.0.8.7) sha256=f94fc8510e58a18e462c5ee8862c9be75e2bfad0688e8d022b86a6e05df2a45a + activemodel (7.1.5.1) sha256=74727466854a7fbdfe8f2702ca3112b23877500d4926bf7e02e921ad542191f1 + activerecord (7.1.5.1) sha256=f40ad1609bf33b9ba5bdc4e16d80a77b1517153234ceb413d31d635d7b91f1e3 activerecord-gitlab (0.2.0) - activesupport (7.0.8.7) sha256=df4702375de924aae81709c831605317c5417f0bd9e502a0373ff84a067204ff + activesupport (7.1.5.1) sha256=9f0c482e473b9868cb3dfe3e9db549a3bd2302c02e4f595a5caac144a8c7cfb8 ast (2.4.2) sha256=1e280232e6a33754cde542bc5ef85520b74db2aac73ec14acef453784447cc12 + base64 (0.2.0) sha256=0f25e9b21a02a0cc0cea8ef92b2041035d39350946e8789c562b2d1a3da01507 + benchmark (0.4.0) sha256=0f12f8c495545e3710c3e4f0480f63f06b4c842cc94cec7f33a956f5180e874a + bigdecimal (3.1.9) sha256=2ffc742031521ad69c2dfc815a98e426a230a3d22aeac1995826a75dabfad8cc concurrent-ruby (1.2.2) sha256=3879119b8b75e3b62616acc256c64a134d0b0a7a9a3fcba5a233025bcde22c4f + connection_pool (2.5.3) sha256=cfd74a82b9b094d1ce30c4f1a346da23ee19dc8a062a16a85f58eab1ced4305b diff-lcs (1.5.0) sha256=49b934001c8c6aedb37ba19daec5c634da27b318a7a3c654ae979d6ba1929b67 + drb (2.2.1) sha256=e9d472bf785f558b96b25358bae115646da0dbfd45107ad858b0bc0d935cb340 gitlab-styles (10.1.0) sha256=f42745f5397d042fe24cf2d0eb56c995b37f9f43d8fb79b834d197a1cafdc84a i18n (1.13.0) sha256=1d24cacd941be578faa7fc5d537d573a3e76e2822ce7dffc0c71c41ba91e63fa json (2.6.3) sha256=86aaea16adf346a2b22743d88f8dcceeb1038843989ab93cda44b5176c845459 + logger (1.7.0) sha256=196edec7cc44b66cfb40f9755ce11b392f21f7967696af15d274dde7edff0203 mini_portile2 (2.8.2) sha256=46b2d244cc6ff01a89bf61274690c09fdbdca47a84ae9eac39039e81231aee7c minitest (5.18.0) sha256=06f43aa0692ce3acf19cb5bc539ad2c6095ca3d2c7e5fbafc58a7d847e898745 + mutex_m (0.3.0) sha256=cfcb04ac16b69c4813777022fdceda24e9f798e48092a2b817eb4c0a782b0751 parallel (1.23.0) sha256=27154713ad6ef32fa3dcb7788a721d6c07bca77e72443b4c6080a14145288c49 parser (3.2.2.3) sha256=10685f358ab36ffea2252dc4952e5b8fad3a297a8152a85f59adc982747b91eb racc (1.7.1) sha256=af64124836fdd3c00e830703d7f873ea5deabde923f37006a39f5a5e0da16387 @@ -135,7 +160,9 @@ CHECKSUMS rubocop-rails (2.20.2) sha256=d20cbd613900fa22bcf85a7fba78ab68b21fc4f90b1e73c97284d40674332417 rubocop-rspec (2.22.0) sha256=2d7493222c81c78ad304ddd81aaf64b3543bcfac6d3d8706c220331921753a03 ruby-progressbar (1.13.0) sha256=80fc9c47a9b640d6834e0dc7b3c94c9df37f08cb072b7761e4a71e22cff29b33 + securerandom (0.4.1) sha256=cc5193d414a4341b6e225f0cb4446aceca8e50d5e1888743fac16987638ea0b1 sqlite3 (1.6.3) sha256=67b476378889b15c93f9b78d39f6d92636dda414194d570d3a1b27514a9e2541 + timeout (0.4.3) sha256=9509f079b2b55fe4236d79633bd75e34c1c1e7e3fb4b56cb5fda61f80a0fe30e tzinfo (2.0.6) sha256=8daf828cc77bcf7d63b0e3bdb6caa47e2272dcfaf4fbfe46f8c3a9df087a829b unicode-display_width (2.4.2) sha256=6a10205d1a19ca790c4e53064ba93f09d9eb234bf6bd135d9deb6001c21428be diff --git a/gems/activerecord-gitlab/Gemfile.next b/gems/activerecord-gitlab/Gemfile.next index eca22b26413..f8892552603 100644 --- a/gems/activerecord-gitlab/Gemfile.next +++ b/gems/activerecord-gitlab/Gemfile.next @@ -4,4 +4,4 @@ source "https://rubygems.org" gemspec -gem 'activerecord', '~> 7.1' # rubocop:disable Gemfile/MissingFeatureCategory +gem 'activerecord', '~> 7.2' # rubocop:disable Gemfile/MissingFeatureCategory diff --git a/gems/activerecord-gitlab/Gemfile.next.lock b/gems/activerecord-gitlab/Gemfile.next.lock index 16ebd85ec1c..08a004831be 100644 --- a/gems/activerecord-gitlab/Gemfile.next.lock +++ b/gems/activerecord-gitlab/Gemfile.next.lock @@ -7,24 +7,27 @@ PATH GEM remote: https://rubygems.org/ specs: - activemodel (7.1.3.4) - activesupport (= 7.1.3.4) - activerecord (7.1.3.4) - activemodel (= 7.1.3.4) - activesupport (= 7.1.3.4) + activemodel (7.2.2.1) + activesupport (= 7.2.2.1) + activerecord (7.2.2.1) + activemodel (= 7.2.2.1) + activesupport (= 7.2.2.1) timeout (>= 0.4.0) - activesupport (7.1.3.4) + activesupport (7.2.2.1) base64 + benchmark (>= 0.3) bigdecimal - concurrent-ruby (~> 1.0, >= 1.0.2) + concurrent-ruby (~> 1.0, >= 1.3.1) connection_pool (>= 2.2.5) drb i18n (>= 1.6, < 2) + logger (>= 1.4.2) minitest (>= 5.1) - mutex_m - tzinfo (~> 2.0) + securerandom (>= 0.3) + tzinfo (~> 2.0, >= 2.0.5) ast (2.4.2) base64 (0.2.0) + benchmark (0.4.0) bigdecimal (3.1.8) concurrent-ruby (1.3.3) connection_pool (2.4.1) @@ -39,8 +42,8 @@ GEM i18n (1.14.5) concurrent-ruby (~> 1.0) json (2.7.2) + logger (1.7.0) minitest (5.24.1) - mutex_m (0.2.0) parallel (1.25.1) parser (3.3.4.0) ast (~> 2.4.1) @@ -98,6 +101,7 @@ GEM rubocop-rspec_rails (2.29.0) rubocop (~> 1.40) ruby-progressbar (1.13.0) + securerandom (0.4.1) sqlite3 (1.7.3-aarch64-linux) sqlite3 (1.7.3-arm-linux) sqlite3 (1.7.3-arm64-darwin) @@ -105,7 +109,7 @@ GEM sqlite3 (1.7.3-x86_64-darwin) sqlite3 (1.7.3-x86_64-linux) strscan (3.1.0) - timeout (0.4.1) + timeout (0.4.3) tzinfo (2.0.6) concurrent-ruby (~> 1.0) unicode-display_width (2.5.0) @@ -119,7 +123,7 @@ PLATFORMS x86_64-linux DEPENDENCIES - activerecord (~> 7.1) + activerecord (~> 7.2) activerecord-gitlab! gitlab-styles (~> 10.1.0) rspec (~> 3.12) diff --git a/gems/activerecord-gitlab/lib/active_record/gitlab_patches/partitioning/base.rb b/gems/activerecord-gitlab/lib/active_record/gitlab_patches/partitioning/base.rb index fcc195dabe4..7618ce87afe 100644 --- a/gems/activerecord-gitlab/lib/active_record/gitlab_patches/partitioning/base.rb +++ b/gems/activerecord-gitlab/lib/active_record/gitlab_patches/partitioning/base.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -if ::ActiveRecord::VERSION::STRING >= "7.2" +if ::ActiveRecord::VERSION::STRING >= "7.3" raise 'New version of active-record detected, please remove or update this patch' end @@ -9,7 +9,7 @@ module ActiveRecord module GitlabPatches module Partitioning module Base - if ::ActiveRecord::VERSION::STRING <= "7.1" + if ::ActiveRecord::VERSION::STRING <= "7.2" def _query_constraints_hash if self.class.query_constraints_list.nil? { @primary_key => id_in_database } @@ -28,7 +28,7 @@ module ActiveRecord @query_constraints_list = columns_list.map(&:to_s) end - if ::ActiveRecord::VERSION::STRING <= "7.1" + if ::ActiveRecord::VERSION::STRING <= "7.2" def query_constraints_list # :nodoc: @query_constraints_list ||= if base_class? || primary_key != base_class.primary_key primary_key if primary_key.is_a?(Array) diff --git a/lib/api/snippets.rb b/lib/api/snippets.rb index 8a382111a8a..22fff24ee68 100644 --- a/lib/api/snippets.rb +++ b/lib/api/snippets.rb @@ -69,7 +69,11 @@ module API filter_params = declared_params(include_missing: false).merge(only_personal: true) - present paginate(find_snippets(user: nil, params: filter_params)), with: Entities::PersonalSnippet, current_user: current_user + present( + paginate(find_snippets(user: nil, params: filter_params)), + with: Entities::PersonalSnippet, + current_user: current_user + ) end desc 'List all snippets current_user has access to' do @@ -141,7 +145,11 @@ module API authorize! :create_snippet attrs = process_create_params(declared_params(include_missing: false)) - service_response = ::Snippets::CreateService.new(project: nil, current_user: current_user, params: attrs).execute + service_response = ::Snippets::CreateService.new( + project: nil, + current_user: current_user, + params: attrs + ).execute snippet = service_response.payload[:snippet] if service_response.success? @@ -188,7 +196,12 @@ module API validate_params_for_multiple_files(snippet) attrs = process_update_params(declared_params(include_missing: false)) - service_response = ::Snippets::UpdateService.new(project: nil, current_user: current_user, params: attrs, perform_spam_check: true).execute(snippet) + service_response = ::Snippets::UpdateService.new( + project: nil, + current_user: current_user, + params: attrs, + perform_spam_check: true + ).execute(snippet) snippet = service_response.payload[:snippet] diff --git a/lib/gitlab/memory/watchdog/configurator.rb b/lib/gitlab/memory/watchdog/configurator.rb index fe3f83355a0..70e192613a5 100644 --- a/lib/gitlab/memory/watchdog/configurator.rb +++ b/lib/gitlab/memory/watchdog/configurator.rb @@ -4,7 +4,7 @@ module Gitlab module Memory class Watchdog class Configurator - DEFAULT_PUMA_WORKER_RSS_LIMIT_MB = 1200 + DEFAULT_PUMA_WORKER_RSS_LIMIT_MB = 1500 DEFAULT_SLEEP_INTERVAL_S = 60 DEFAULT_SIDEKIQ_SLEEP_INTERVAL_S = 3 MIN_SIDEKIQ_SLEEP_INTERVAL_S = 2 diff --git a/locale/gitlab.pot b/locale/gitlab.pot index 4e16bd2194d..da63770e720 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -15136,9 +15136,6 @@ msgstr "" msgid "Commit|containing commit" msgstr "" -msgid "Community forum" -msgstr "" - msgid "Company" msgstr "" @@ -26501,6 +26498,9 @@ msgstr "" msgid "File added." msgstr "" +msgid "File browser" +msgstr "" + msgid "File changed and moved." msgstr "" @@ -26558,6 +26558,9 @@ msgstr "" msgid "File too large. Secure files must be less than %{limit} MB." msgstr "" +msgid "File tree" +msgstr "" + msgid "File upload error." msgstr "" @@ -28166,6 +28169,9 @@ msgstr "" msgid "GitLab commit" msgstr "" +msgid "GitLab community forum" +msgstr "" + msgid "GitLab container registry API not supported" msgstr "" @@ -28706,6 +28712,12 @@ msgstr "" msgid "GlobalSearch|Epics" msgstr "" +msgid "GlobalSearch|Exclude forks" +msgstr "" + +msgid "GlobalSearch|Exclude search results from forked projects" +msgstr "" + msgid "GlobalSearch|Explore" msgstr "" @@ -28757,15 +28769,9 @@ msgstr "" msgid "GlobalSearch|Include archived" msgstr "" -msgid "GlobalSearch|Include forks" -msgstr "" - msgid "GlobalSearch|Include search results from archived projects" msgstr "" -msgid "GlobalSearch|Include search results from forked projects" -msgstr "" - msgid "GlobalSearch|Incremental indexing queue length" msgstr "" @@ -73184,6 +73190,9 @@ msgstr "" msgid "must contain only a mastodon handle." msgstr "" +msgid "must contain only a orcid ID." +msgstr "" + msgid "must have a repository" msgstr "" diff --git a/qa/qa/page/merge_request/show.rb b/qa/qa/page/merge_request/show.rb index 00ca4d5e177..1bab9871433 100644 --- a/qa/qa/page/merge_request/show.rb +++ b/qa/qa/page/merge_request/show.rb @@ -20,6 +20,14 @@ module QA element 'submit-review-button' end + view 'app/assets/javascripts/batch_comments/components/review_drawer.vue' do + element 'submit-review-button' + end + + view 'app/assets/javascripts/batch_comments/components/submit_review_button.vue' do + element 'review-drawer-toggle' + end + view 'app/assets/javascripts/diffs/components/compare_dropdown_layout.vue' do element 'version-dropdown-content' end @@ -185,11 +193,7 @@ module QA end end - within_element('review-bar-content') do - click_element('review-preview-dropdown') - end - - click_element('submit-review-dropdown') + all_elements('review-drawer-toggle', minimum: 1).first.click click_element('submit-review-button') # After clicking the button, wait for the review bar to disappear diff --git a/qa/qa/specs/features/browser_ui/3_create/merge_request/add_batch_comments_in_merge_request_spec.rb b/qa/qa/specs/features/browser_ui/3_create/merge_request/add_batch_comments_in_merge_request_spec.rb index 34e0e012702..c3abc50c242 100644 --- a/qa/qa/specs/features/browser_ui/3_create/merge_request/add_batch_comments_in_merge_request_spec.rb +++ b/qa/qa/specs/features/browser_ui/3_create/merge_request/add_batch_comments_in_merge_request_spec.rb @@ -3,17 +3,14 @@ module QA RSpec.describe 'Create' do # admin required to check if feature flag is enabled - describe 'Batch comments in merge request', :smoke, :requires_admin, product_group: :code_review do + describe 'Batch comments in merge request', :smoke, product_group: :code_review do let(:project) { create(:project, name: 'project-with-merge-request') } let(:merge_request) do create(:merge_request, title: 'This is a merge request', description: 'Great feature', project: project) end it 'user submits a non-diff review', - testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347777', - feature_flag: { name: :improved_review_experience } do - skip('improved_review_experience FF is WIP') if Runtime::Feature.enabled?('improved_review_experience') - + testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347777' do Flow::Login.sign_in merge_request.visit! @@ -30,10 +27,7 @@ module QA end it 'user submits a diff review', - testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347778', - feature_flag: { name: :improved_review_experience } do - skip('improved_review_experience FF is WIP') if Runtime::Feature.enabled?('improved_review_experience') - + testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347778' do Flow::Login.sign_in merge_request.visit! diff --git a/spec/controllers/admin/integrations_controller_spec.rb b/spec/controllers/admin/integrations_controller_spec.rb index f27b99b6a86..5b8ee305acd 100644 --- a/spec/controllers/admin/integrations_controller_spec.rb +++ b/spec/controllers/admin/integrations_controller_spec.rb @@ -2,9 +2,9 @@ require 'spec_helper' -RSpec.describe Admin::IntegrationsController, feature_category: :integrations do +RSpec.describe Admin::IntegrationsController, :with_current_organization, feature_category: :integrations do let_it_be(:admin) { create(:admin) } - let_it_be(:organization) { create(:organization, :default) } + let_it_be(:organization) { current_organization } before do stub_feature_flags(remove_monitor_metrics: false) @@ -45,14 +45,12 @@ RSpec.describe Admin::IntegrationsController, feature_category: :integrations do describe '#update' do include JiraIntegrationHelpers - let_it_be(:organization) { create(:organization) } let(:integration) { create(:jira_integration, :instance) } let(:integration_name) { integration.class.to_param } before do stub_jira_integration_test allow(PropagateIntegrationWorker).to receive(:perform_async) - allow(Current).to receive(:organization).and_return(organization) put :update, params: { id: integration_name, service: params } end diff --git a/spec/db/schema_spec.rb b/spec/db/schema_spec.rb index aeeb978bd9f..fdb3e2482a8 100644 --- a/spec/db/schema_spec.rb +++ b/spec/db/schema_spec.rb @@ -65,7 +65,6 @@ RSpec.describe 'Database schema', 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 execution_config_id upstream_pipeline_partition_id], - ci_builds_metadata: %w[partition_id project_id build_id], ci_build_needs: %w[project_id], ci_build_pending_states: %w[project_id], ci_build_trace_chunks: %w[project_id], diff --git a/spec/features/merge_request/batch_comments_spec.rb b/spec/features/merge_request/batch_comments_spec.rb index f2020d2e791..fb4162ee65b 100644 --- a/spec/features/merge_request/batch_comments_spec.rb +++ b/spec/features/merge_request/batch_comments_spec.rb @@ -13,8 +13,6 @@ RSpec.describe 'Merge request > Batch comments', :js, feature_category: :code_re end before do - stub_feature_flags(improved_review_experience: false) - project.add_maintainer(user) sign_in(user) @@ -27,21 +25,22 @@ RSpec.describe 'Merge request > Batch comments', :js, feature_category: :code_re expect(find('.draft-note')).to have_content('Line is wrong') - expect(page).to have_selector('[data-testid="review_bar_component"]') - - expect(find('[data-testid="review_bar_component"] .gl-badge')).to have_content('1') + expect(first('[data-testid="review-drawer-toggle"] .gl-badge')).to have_content('1') end it 'publishes review' do write_diff_comment - page.within('.review-bar-content') do - click_button 'Finish review' - click_button 'Submit review' + page.within '.merge-request-tabs-holder' do + click_button 'Your review' end + click_button 'Submit review' + wait_for_requests + find_by_scrolling("[id='#{sample_compare.changes[0][:line_code]}']") + expect(page).not_to have_selector('.draft-note', text: 'Line is wrong') expect(page).to have_selector('.note:not(.draft-note)', text: 'Line is wrong') @@ -150,7 +149,9 @@ RSpec.describe 'Merge request > Batch comments', :js, feature_category: :code_re expect(page).to have_selector('.draft-note', text: 'Its a draft comment') - click_button('Pending comments') + page.within '.merge-request-tabs-holder' do + click_button 'Your review' + end expect(page).to have_text('2 pending comments') end @@ -160,7 +161,9 @@ RSpec.describe 'Merge request > Batch comments', :js, feature_category: :code_re expect(page).to have_selector('.note:not(.draft-note)', text: 'Its a regular comment') - click_button('Pending comments') + page.within '.merge-request-tabs-holder' do + click_button 'Your review' + end expect(page).to have_text('1 pending comment') end @@ -180,7 +183,7 @@ RSpec.describe 'Merge request > Batch comments', :js, feature_category: :code_re expect(find('.new .draft-note')).to have_content('Line is wrong') expect(find('.old .draft-note')).to have_content('Another wrong line') - expect(find('.review-bar-content .gl-badge')).to have_content('2') + expect(first('[data-testid="review-drawer-toggle"] .gl-badge')).to have_content('2') end end @@ -206,11 +209,12 @@ RSpec.describe 'Merge request > Batch comments', :js, feature_category: :code_re write_reply_to_discussion(resolve: true) - page.within('.review-bar-content') do - click_button 'Finish review' - click_button 'Submit review' + page.within '.merge-request-tabs-holder' do + click_button 'Your review' end + click_button 'Submit review' + wait_for_requests page.within(first('.discussions-counter')) do @@ -249,11 +253,12 @@ RSpec.describe 'Merge request > Batch comments', :js, feature_category: :code_re write_reply_to_discussion(button_text: 'Start a review', unresolve: true) - page.within('.review-bar-content') do - click_button 'Finish review' - click_button 'Submit review' + page.within '.merge-request-tabs-holder' do + click_button 'Your review' end + click_button 'Submit review' + wait_for_requests page.within(first('.discussions-counter')) do diff --git a/spec/features/merge_request/user_sees_merge_request_file_tree_sidebar_spec.rb b/spec/features/merge_request/user_sees_merge_request_file_tree_sidebar_spec.rb index 4097f9da1cc..3829c20cb38 100644 --- a/spec/features/merge_request/user_sees_merge_request_file_tree_sidebar_spec.rb +++ b/spec/features/merge_request/user_sees_merge_request_file_tree_sidebar_spec.rb @@ -12,20 +12,19 @@ RSpec.describe 'Merge request > User sees merge request file tree sidebar', :js, let(:sidebar_scroller) { sidebar.find('.vue-recycle-scroller') } before do - stub_feature_flags(improved_review_experience: false) sign_in(user) visit diffs_project_merge_request_path(project, merge_request) wait_for_requests end it 'sees file tree sidebar' do - expect(page).to have_selector('.file-row[role=button]') + expect(page).to have_selector('[data-testid="file-tree-container"]') end shared_examples 'last entry clickable' do specify do sidebar_scroller.execute_script('this.scrollBy(0,99999)') - button = find_all('.file-row[role=button]').last + button = find_all('[data-testid="file-tree-container"] nav button').last title = button.find('[data-testid=file-row-name-container]')[:title] expect(button.obscured?).to be_falsy button.click @@ -35,26 +34,6 @@ RSpec.describe 'Merge request > User sees merge request file tree sidebar', :js, it_behaves_like 'last entry clickable' - context 'when has started a review' do - before do - add_diff_line_draft_comment('foo', find('.line_holder', match: :first)) - # wait for review bar to appear - find_by_testid('review_bar_component') - # wait for sidebar to adjust - sleep(1) - end - - it_behaves_like 'last entry clickable' - - context 'when scrolled into full view' do - before do - sidebar.execute_script("this.scrollIntoView({ block: 'end' })") - end - - it_behaves_like 'last entry clickable' - end - end - context 'when viewing using file-by-file mode' do let(:user) { create(:user, view_diffs_file_by_file: true) } diff --git a/spec/frontend/diffs/components/diff_file_row_spec.js b/spec/frontend/diffs/components/diff_file_row_spec.js index 26c719816f5..9f72978768c 100644 --- a/spec/frontend/diffs/components/diff_file_row_spec.js +++ b/spec/frontend/diffs/components/diff_file_row_spec.js @@ -48,6 +48,7 @@ describe('Diff File Row component', () => { file: {}, size: 16, showTooltip: true, + asButton: false, }), ); }); diff --git a/spec/frontend/diffs/components/tree_list_spec.js b/spec/frontend/diffs/components/tree_list_spec.js index 07b26457acd..a4ee48353b2 100644 --- a/spec/frontend/diffs/components/tree_list_spec.js +++ b/spec/frontend/diffs/components/tree_list_spec.js @@ -170,14 +170,14 @@ describe('Diffs tree list component', () => { return treeEntries; }; - describe('default', () => { - beforeEach(() => { - createComponent(); - }); + it('renders empty text', () => { + createComponent(); + expect(wrapper.text()).toContain('No files found'); + }); - it('renders empty text', () => { - expect(wrapper.text()).toContain('No files found'); - }); + it('renders title', () => { + createComponent(); + expect(wrapper.find('h2').text()).toContain('Files'); }); it('renders file count', () => { diff --git a/spec/frontend/groups/your_work/graphql/resolvers_spec.js b/spec/frontend/groups/your_work/graphql/resolvers_spec.js index 33d7d139f82..1c7678c26b5 100644 --- a/spec/frontend/groups/your_work/graphql/resolvers_spec.js +++ b/spec/frontend/groups/your_work/graphql/resolvers_spec.js @@ -64,7 +64,6 @@ describe('your work groups resolver', () => { fullName: 'frontend-fixtures-group', parent: { id: null }, webUrl: mockGroup.web_url, - organizationEditPath: '', descriptionHtml: '', avatarUrl: null, descendantGroupsCount: 1, diff --git a/spec/frontend/search/sidebar/components/forked_filter_spec.js b/spec/frontend/search/sidebar/components/forked_filter_spec.js index 1c048a64852..0c25680fd05 100644 --- a/spec/frontend/search/sidebar/components/forked_filter_spec.js +++ b/spec/frontend/search/sidebar/components/forked_filter_spec.js @@ -51,7 +51,7 @@ describe('ForksFilter', () => { it('wraps the label element with a tooltip', () => { const tooltip = getBinding(findCheckboxFilterLabel().element, 'gl-tooltip'); expect(tooltip).toBeDefined(); - expect(tooltip.value).toBe('Include search results from forked projects'); + expect(tooltip.value).toBe('Exclude search results from forked projects'); }); }); @@ -71,19 +71,19 @@ describe('ForksFilter', () => { it('wraps the label element with a tooltip', () => { const tooltip = getBinding(findCheckboxFilterLabel().element, 'gl-tooltip'); expect(tooltip).toBeDefined(); - expect(tooltip.value).toBe('Include search results from forked projects'); + expect(tooltip.value).toBe('Exclude search results from forked projects'); }); }); describe.each` - include_forked | checkboxState - ${'true'} | ${'true'} - ${'sdfsdf'} | ${'false'} - ${''} | ${'false'} - ${'false'} | ${'false'} - `('selectedFilter', ({ include_forked, checkboxState }) => { + exclude_forks | checkboxState + ${'true'} | ${'true'} + ${'sdfsdf'} | ${'false'} + ${''} | ${'false'} + ${'false'} | ${'false'} + `('selectedFilter', ({ exclude_forks, checkboxState }) => { beforeEach(() => { - createComponent({ urlQuery: { include_forked } }); + createComponent({ urlQuery: { exclude_forks } }); }); it('renders the component', () => { @@ -101,7 +101,7 @@ describe('ForksFilter', () => { findCheckboxFilter().vm.$emit('input', selectedFilter); expect(defaultActions.setQuery).toHaveBeenCalledWith(expect.any(Object), { - key: 'include_forked', + key: 'exclude_forks', value: 'false', }); expect(selectedFilter).toEqual([false]); diff --git a/spec/frontend/vue_shared/components/changed_file_icon_spec.js b/spec/frontend/vue_shared/components/changed_file_icon_spec.js index fbde83cb427..8b2f36012e2 100644 --- a/spec/frontend/vue_shared/components/changed_file_icon_spec.js +++ b/spec/frontend/vue_shared/components/changed_file_icon_spec.js @@ -108,4 +108,12 @@ describe('Changed file icon', () => { expect(findIconName()).toEqual(iconName); }); + + it('can be rendered as span', () => { + factory({ + asButton: false, + }); + + expect(wrapper.element.tagName).toBe('SPAN'); + }); }); diff --git a/spec/frontend/vue_shared/components/file_row_spec.js b/spec/frontend/vue_shared/components/file_row_spec.js index a33cc165361..cf69077d549 100644 --- a/spec/frontend/vue_shared/components/file_row_spec.js +++ b/spec/frontend/vue_shared/components/file_row_spec.js @@ -34,6 +34,14 @@ describe('File row component', () => { expect(name.text().trim()).toEqual(fileName); }); + it('renders as button', () => { + createComponent({ + file: file('t4'), + level: 0, + }); + expect(wrapper.find('button').exists()).toBe(true); + }); + it('renders the full path as title', () => { const filePath = 'path/to/file/with a very long folder name/'; const fileName = 'foo.txt'; diff --git a/spec/helpers/projects_helper_spec.rb b/spec/helpers/projects_helper_spec.rb index e7e0852dc46..980276b9762 100644 --- a/spec/helpers/projects_helper_spec.rb +++ b/spec/helpers/projects_helper_spec.rb @@ -965,6 +965,34 @@ RSpec.describe ProjectsHelper, feature_category: :source_code_management do end end + describe '#remove_project_message' do + subject(:message) { helper.remove_project_message(project) } + + before do + allow(project).to receive(:delayed_deletion_ready?).and_return(enabled) + end + + context 'when project has delayed deletion enabled' do + let(:enabled) { true } + + specify do + deletion_date = helper.permanent_deletion_date_formatted(Date.current) + + expect(message).to eq "Deleting a project places it into a read-only state until #{deletion_date}, " \ + "at which point the project will be permanently deleted. Are you ABSOLUTELY sure?" + end + end + + context 'when project has delayed deletion disabled' do + let(:enabled) { false } + + specify do + expect(message).to eq "You are going to delete #{project.full_name}. Deleted projects CANNOT be " \ + "restored! Are you ABSOLUTELY sure?" + end + end + end + describe '#project_permissions_panel_data' do subject { helper.project_permissions_panel_data(project) } diff --git a/spec/lib/gitlab/database/partition_helpers_spec.rb b/spec/lib/gitlab/database/partition_helpers_spec.rb index f5f20ff474a..bf1c8267365 100644 --- a/spec/lib/gitlab/database/partition_helpers_spec.rb +++ b/spec/lib/gitlab/database/partition_helpers_spec.rb @@ -12,9 +12,14 @@ RSpec.describe Gitlab::Database::PartitionHelpers, feature_category: :database d describe "#partition?" do subject(:is_partitioned) { model.partition?(table_name) } - let(:table_name) { 'ci_builds_metadata' } - context "when a partition table exist" do + let(:table_name) { '_test_ci_builds_metadata' } + + before do + model.connection.create_table("#{table_name}_p", options: 'PARTITION BY LIST (id)') + model.connection.execute("CREATE TABLE #{table_name} PARTITION OF #{table_name}_p FOR VALUES IN (1)") + end + context 'when the view postgres_partitions exists' do it 'calls the view', :aggregate_failures do expect(Gitlab::Database::PostgresPartition).to receive(:partition_exists?).with(table_name).and_call_original diff --git a/spec/lib/gitlab/database/postgres_partition_spec.rb b/spec/lib/gitlab/database/postgres_partition_spec.rb index 75d11ed9b7d..a5175c2fff4 100644 --- a/spec/lib/gitlab/database/postgres_partition_spec.rb +++ b/spec/lib/gitlab/database/postgres_partition_spec.rb @@ -151,7 +151,14 @@ RSpec.describe Gitlab::Database::PostgresPartition, type: :model, feature_catego subject { described_class.partition_exists?(table_name) } context 'when the partition exists' do - let(:table_name) { "ci_builds_metadata" } + let(:table_name) { "_test_partition_02" } + + before do + ActiveRecord::Base.connection.execute(<<~SQL) + CREATE TABLE #{table_name} PARTITION OF public._test_partitioned_table + FOR VALUES FROM ('2020-02-01') to ('2020-03-01'); + SQL + end it { is_expected.to be_truthy } end @@ -167,7 +174,14 @@ RSpec.describe Gitlab::Database::PostgresPartition, type: :model, feature_catego subject { described_class.legacy_partition_exists?(table_name) } context 'when the partition exists' do - let(:table_name) { "ci_builds_metadata" } + let(:table_name) { "_test_partition_02" } + + before do + ActiveRecord::Base.connection.execute(<<~SQL) + CREATE TABLE #{table_name} PARTITION OF public._test_partitioned_table + FOR VALUES FROM ('2020-02-01') to ('2020-03-01'); + SQL + end it { is_expected.to be_truthy } end diff --git a/spec/lib/gitlab/database/sharding_key_spec.rb b/spec/lib/gitlab/database/sharding_key_spec.rb index 1d6d16f01f8..3ede9178e86 100644 --- a/spec/lib/gitlab/database/sharding_key_spec.rb +++ b/spec/lib/gitlab/database/sharding_key_spec.rb @@ -80,7 +80,6 @@ RSpec.describe 'new tables missing sharding_key', feature_category: :cell do # 2. It does not yet have a foreign key as the index is still being backfilled let(:allowed_to_be_missing_foreign_key) do [ - 'ci_builds_metadata.project_id', 'ci_deleted_objects.project_id', # LFK already present on p_ci_builds and cascade delete all ci resources 'ci_job_artifacts.project_id', 'ci_namespace_monthly_usages.namespace_id', # https://gitlab.com/gitlab-org/gitlab/-/issues/321400 diff --git a/spec/lib/gitlab/import_export/json/streaming_serializer_spec.rb b/spec/lib/gitlab/import_export/json/streaming_serializer_spec.rb index 808b15b4df2..891693374d9 100644 --- a/spec/lib/gitlab/import_export/json/streaming_serializer_spec.rb +++ b/spec/lib/gitlab/import_export/json/streaming_serializer_spec.rb @@ -20,12 +20,7 @@ RSpec.describe Gitlab::ImportExport::Json::StreamingSerializer, :clean_gitlab_re approvals_before_merge: 1) end - let_it_be(:issue) do - # TODO: .reload can be removed after the migration https://gitlab.com/gitlab-org/gitlab/-/issues/497857 - create(:issue, - assignees: [user], - project: exportable).reload - end + let_it_be(:issue) { create(:issue, assignees: [user], project: exportable) } let(:exportable_path) { 'project' } let(:logger) { Gitlab::Export::Logger.build } @@ -367,8 +362,7 @@ RSpec.describe Gitlab::ImportExport::Json::StreamingSerializer, :clean_gitlab_re describe 'with inaccessible associations' do let_it_be(:milestone) { create(:milestone, project: exportable) } - # TODO: .reload can be removed after the migration https://gitlab.com/gitlab-org/gitlab/-/issues/497857 - let_it_be(:issue) { create(:issue, assignees: [user], project: exportable, milestone: milestone).reload } + let_it_be(:issue) { create(:issue, assignees: [user], project: exportable, milestone: milestone) } let_it_be(:label1) { create(:label, project: exportable) } let_it_be(:label2) { create(:label, project: exportable) } let_it_be(:link1) { create(:label_link, label: label1, target: issue) } diff --git a/spec/migrations/move_ci_builds_metadata_to_dynamic_schema_spec.rb b/spec/migrations/move_ci_builds_metadata_to_dynamic_schema_spec.rb new file mode 100644 index 00000000000..5c0e732a22a --- /dev/null +++ b/spec/migrations/move_ci_builds_metadata_to_dynamic_schema_spec.rb @@ -0,0 +1,66 @@ +# frozen_string_literal: true + +require 'spec_helper' +require_migration! + +RSpec.describe MoveCiBuildsMetadataToDynamicSchema, :migration, feature_category: :continuous_integration do + let(:migration) { described_class.new } + let(:table_name) { described_class::TABLE_NAME } + let(:identifier) { "#{described_class::DYNAMIC_SCHEMA}.#{table_name}" } + + describe '#up' do + it 'moves the table into the dynamic schema' do + expect(table_exists?(table_name)).to be_truthy + + migration.up + + expect(table_exists?(table_name)).to be_falsey + expect(table_exists?(identifier)).to be_truthy + end + end + + describe '#down' do + context 'when the partition exists in the dynamic schema' do + before do + migration.up + + ApplicationRecord.connection.execute(<<~SQL) + DROP TABLE IF EXISTS #{identifier}_100; + CREATE TABLE IF NOT EXISTS #{identifier} PARTITION OF p_#{table_name} FOR VALUES IN (100); + SQL + end + + it 'moves the table into the current schema' do + expect(table_exists?(identifier)).to be_truthy + + migration.down + + expect(table_exists?(table_name)).to be_truthy + end + end + + context 'when the partition does not exist in the dynamic schema' do + before do + migration.up + + ApplicationRecord.connection.execute(<<~SQL) + DROP TABLE IF EXISTS #{identifier}; + CREATE TABLE IF NOT EXISTS #{identifier}_100 PARTITION OF p_#{table_name} FOR VALUES IN (100); + SQL + end + + it 'creates the table into the current schema' do + expect(table_exists?(identifier)).to be_falsey + expect(table_exists?("#{identifier}_100")).to be_truthy + + migration.down + + expect(table_exists?(table_name)).to be_truthy + end + end + end + + def table_exists?(name) + ApplicationRecord.connection.table_exists?(name) + end +end diff --git a/spec/models/concerns/packages/conan/package_fileable_spec.rb b/spec/models/concerns/packages/conan/package_fileable_spec.rb new file mode 100644 index 00000000000..848a4b5638e --- /dev/null +++ b/spec/models/concerns/packages/conan/package_fileable_spec.rb @@ -0,0 +1,39 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Packages::Conan::PackageFileable, type: :model, feature_category: :package_registry do + let_it_be(:instance) { build(:conan_recipe_revision) } + + describe 'associations' do + subject { instance } + + it 'has many file_metadata' do + is_expected.to have_many(:file_metadata) + end + + it 'has many package_files through file_metadata' do + is_expected.to have_many(:package_files).through(:file_metadata) + end + end + + describe '#orphan?' do + subject { instance.orphan? } + + context 'when package_files is empty' do + it 'returns true' do + is_expected.to be_truthy + end + end + + context 'when package_files is not empty' do + let_it_be(:package_file) do + create(:conan_package_file, :conan_recipe_file, package: instance.package, conan_recipe_revision: instance) + end + + it 'returns false' do + is_expected.to be_falsey + end + end + end +end diff --git a/spec/models/packages/conan/package_reference_spec.rb b/spec/models/packages/conan/package_reference_spec.rb index baccbe785b9..67c4a618312 100644 --- a/spec/models/packages/conan/package_reference_spec.rb +++ b/spec/models/packages/conan/package_reference_spec.rb @@ -3,6 +3,8 @@ require 'spec_helper' RSpec.describe Packages::Conan::PackageReference, type: :model, feature_category: :package_registry do + it { is_expected.to be_a(Packages::Conan::PackageFileable) } + describe 'associations' do it 'belongs to package' do is_expected.to belong_to(:package).class_name('Packages::Conan::Package').inverse_of(:conan_package_references) diff --git a/spec/models/packages/conan/package_revision_spec.rb b/spec/models/packages/conan/package_revision_spec.rb index 31e5b803c64..345a1576c5d 100644 --- a/spec/models/packages/conan/package_revision_spec.rb +++ b/spec/models/packages/conan/package_revision_spec.rb @@ -5,6 +5,8 @@ require 'spec_helper' RSpec.describe Packages::Conan::PackageRevision, type: :model, feature_category: :package_registry do using RSpec::Parameterized::TableSyntax + it { is_expected.to be_a(Packages::Conan::PackageFileable) } + describe 'associations' do it 'belongs to package' do is_expected.to belong_to(:package).class_name('Packages::Conan::Package').inverse_of(:conan_package_revisions) diff --git a/spec/models/packages/conan/recipe_revision_spec.rb b/spec/models/packages/conan/recipe_revision_spec.rb index 0e220e5c0fa..8ac5952844b 100644 --- a/spec/models/packages/conan/recipe_revision_spec.rb +++ b/spec/models/packages/conan/recipe_revision_spec.rb @@ -5,6 +5,8 @@ require 'spec_helper' RSpec.describe Packages::Conan::RecipeRevision, type: :model, feature_category: :package_registry do using RSpec::Parameterized::TableSyntax + it { is_expected.to be_a(Packages::Conan::PackageFileable) } + describe 'associations' do it 'belongs to package' do is_expected.to belong_to(:package).class_name('Packages::Conan::Package').inverse_of(:conan_recipe_revisions) diff --git a/spec/models/user_detail_spec.rb b/spec/models/user_detail_spec.rb index 7defbc74afd..bbdf1d158bd 100644 --- a/spec/models/user_detail_spec.rb +++ b/spec/models/user_detail_spec.rb @@ -385,6 +385,44 @@ RSpec.describe UserDetail, feature_category: :system_access do end end + describe '#orcid' do + context 'when orcid is set' do + let_it_be(:user_detail) { create(:user).user_detail } + + it 'accepts a valid orcid username' do + user_detail.orcid = '1234-1234-1234-1234' + + expect(user_detail).to be_valid + end + + context 'when orcid id is wrong' do + it 'throws an error when orcid username format is too long' do + user_detail.orcid = '1234-1234-1234-1234-1234' + + expect(user_detail).not_to be_valid + expect(user_detail.errors.full_messages) + .to match_array([_('Orcid must contain only a orcid ID.')]) + end + + it 'throws an error when orcid username format is too short' do + user_detail.orcid = '1234-1234' + + expect(user_detail).not_to be_valid + expect(user_detail.errors.full_messages) + .to match_array([_('Orcid must contain only a orcid ID.')]) + end + + it 'throws an error when orcid username format is letters' do + user_detail.orcid = 'abcd-abcd-abcd-abcd' + + expect(user_detail).not_to be_valid + expect(user_detail.errors.full_messages) + .to match_array([_('Orcid must contain only a orcid ID.')]) + end + end + end + end + describe '#location' do it { is_expected.to validate_length_of(:location).is_at_most(500) } end @@ -423,6 +461,7 @@ RSpec.describe UserDetail, feature_category: :system_access do linkedin: 'linkedin', location: 'location', bluesky: 'did:plc:ewvi7nxzyoun6zhxrhs64oiz', + orcid: '1234-1234-1234-1234', mastodon: '@robin@example.com', organization: 'organization', skype: 'skype', @@ -447,6 +486,7 @@ RSpec.describe UserDetail, feature_category: :system_access do it_behaves_like 'prevents `nil` value', :linkedin it_behaves_like 'prevents `nil` value', :location it_behaves_like 'prevents `nil` value', :bluesky + it_behaves_like 'prevents `nil` value', :orcid it_behaves_like 'prevents `nil` value', :mastodon it_behaves_like 'prevents `nil` value', :organization it_behaves_like 'prevents `nil` value', :skype diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index a6801166395..1559af4ad46 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -150,6 +150,9 @@ RSpec.describe User, feature_category: :user_profile do it { is_expected.to delegate_method(:skype).to(:user_detail).allow_nil } it { is_expected.to delegate_method(:skype=).to(:user_detail).with_arguments(:args).allow_nil } + it { is_expected.to delegate_method(:orcid).to(:user_detail).allow_nil } + it { is_expected.to delegate_method(:orcid=).to(:user_detail).with_arguments(:args).allow_nil } + it { is_expected.to delegate_method(:website_url).to(:user_detail).allow_nil } it { is_expected.to delegate_method(:website_url=).to(:user_detail).with_arguments(:args).allow_nil } diff --git a/spec/support/shared_examples/graphql/mutations/issues/permission_check_shared_examples.rb b/spec/support/shared_examples/graphql/mutations/issues/permission_check_shared_examples.rb index c443046a668..5b4b83c4268 100644 --- a/spec/support/shared_examples/graphql/mutations/issues/permission_check_shared_examples.rb +++ b/spec/support/shared_examples/graphql/mutations/issues/permission_check_shared_examples.rb @@ -21,8 +21,7 @@ RSpec.shared_examples 'permission level for issue mutation is correctly verified ) end - # TODO: .reload can be removed after the migration https://gitlab.com/gitlab-org/gitlab/-/issues/497857 - let(:expected) { issue_attributes(issue.reload) } + let(:expected) { issue_attributes(issue) } shared_examples_for 'when the user does not have access to the resource' do |raise_for_assigned_and_author| before do diff --git a/spec/views/devise/shared/_footer.html.haml_spec.rb b/spec/views/devise/shared/_footer.html.haml_spec.rb index ef239ebd812..c1d0ad8a322 100644 --- a/spec/views/devise/shared/_footer.html.haml_spec.rb +++ b/spec/views/devise/shared/_footer.html.haml_spec.rb @@ -24,7 +24,7 @@ RSpec.describe 'devise/shared/_footer', feature_category: :system_access do end it { is_expected.to have_link(_('About GitLab'), href: ApplicationHelper.promo_url) } - it { is_expected.to have_link(_('Community forum'), href: ApplicationHelper.community_forum) } + it { is_expected.to have_link(_('GitLab community forum'), href: ApplicationHelper.community_forum) } context 'when one trust is enabled' do before do diff --git a/spec/workers/gitlab/jira_import/import_issue_worker_spec.rb b/spec/workers/gitlab/jira_import/import_issue_worker_spec.rb index d7ad0eb9e49..b557123e3bf 100644 --- a/spec/workers/gitlab/jira_import/import_issue_worker_spec.rb +++ b/spec/workers/gitlab/jira_import/import_issue_worker_spec.rb @@ -115,27 +115,6 @@ RSpec.describe Gitlab::JiraImport::ImportIssueWorker, feature_category: :importe expect(issue.work_item_type_id).to eq(issue_type.id) end - context 'when legacy correct_work_item_type_id was part of the attributes (backward compatibility)' do - let(:issue_type) { ::WorkItems::Type.default_issue_type } - # At the moment, both id and correct_id columns have the same value in the work_item_types table - let(:correct_work_item_type_id) { issue_type.id } - let(:issue_attrs) do - Gitlab::JiraImport::IssueSerializer.new( - project, - jira_issue, - user.id, - issue_type, - params - ).execute.except(:work_item_type_id).merge(correct_work_item_type_id: correct_work_item_type_id) - end - - it 'creates an issue with the correct type' do - issue = Issue.last - - expect(issue.work_item_type_id).to eq(issue_type.id) - end - end - context 'when assignee_ids is nil' do let(:assignee_ids) { nil } diff --git a/spec/workers/packages/cleanup_package_file_worker_spec.rb b/spec/workers/packages/cleanup_package_file_worker_spec.rb index 2eca1dcea07..e0a894982fc 100644 --- a/spec/workers/packages/cleanup_package_file_worker_spec.rb +++ b/spec/workers/packages/cleanup_package_file_worker_spec.rb @@ -107,6 +107,108 @@ RSpec.describe Packages::CleanupPackageFileWorker, type: :worker, feature_catego .and change { Packages::Package.count }.by(0) end end + + context 'with a Conan package file' do + let_it_be(:package) { create(:conan_package, without_package_files: true) } + let_it_be(:package_file) { create(:conan_package_file, :conan_package_info, :pending_destruction, package: package) } + let_it_be(:package_file_2) { create(:conan_package_file, package: package) } + let_it_be(:recipe_revision) { package.conan_recipe_revisions.first } + let_it_be(:package_reference) { package.conan_package_references.first } + let_it_be(:package_revision) { package.conan_package_revisions.first } + + context 'when deleting recipe revision' do + context 'when the recipe revision is orphan but there are other recipe revisions' do + let_it_be(:recipe_revision2) { create(:conan_recipe_revision, package: package) } + let_it_be(:other_metadata) do + create(:conan_file_metadatum, recipe_revision: recipe_revision2, package_file: package_file_2) + end + + it 'deletes the recipe revision and its dependent objects' do + expect { subject }.to change { Packages::PackageFile.count }.by(-1) + .and change { Packages::Conan::RecipeRevision.count }.by(-1) + .and change { Packages::Conan::PackageReference.count }.by(-1) + .and change { Packages::Conan::PackageRevision.count }.by(-1) + .and not_change { Packages::Conan::Package.count } + end + end + + context 'when the recipe revision is not orphan' do + let_it_be(:other_metadata) do + create(:conan_file_metadatum, recipe_revision: recipe_revision, package_file: package_file_2) + end + + it 'does not delete the recipe revision' do + expect { subject }.to change { Packages::PackageFile.count }.by(-1) + .and not_change { Packages::Conan::RecipeRevision.count } + end + end + end + + context 'when deleting package reference' do + context 'when the package reference is orphan but there are other package references' do + let_it_be(:package_reference2) { create(:conan_package_reference, package: package, recipe_revision: recipe_revision) } + let_it_be(:package_revision2) { create(:conan_package_revision, package: package, package_reference: package_reference2) } + let_it_be(:other_metadata) do + create(:conan_file_metadatum, recipe_revision: recipe_revision, package_reference: package_reference2, + package_revision: package_revision2, package_file: package_file_2, conan_file_type: 'package_file') + end + + it 'deletes the package reference and its dependent package revision' do + expect { subject }.to change { Packages::PackageFile.count }.by(-1) + .and change { Packages::Conan::PackageReference.count }.by(-1) + .and change { Packages::Conan::PackageRevision.count }.by(-1) + .and not_change { Packages::Conan::RecipeRevision.count } + .and not_change { Packages::Conan::Package.count } + end + end + + context 'when the package reference is still referenced by other package files' do + let_it_be(:other_metadata) do + create(:conan_file_metadatum, + conan_file_type: 'package_file', + recipe_revision: recipe_revision, + package_reference: package_reference, + package_revision: create(:conan_package_revision, package: package, package_reference: package_reference), + package_file: package_file_2) + end + + it 'does not delete the package reference' do + expect { subject }.to change { Packages::PackageFile.count }.by(-1) + .and not_change { Packages::Conan::PackageReference.count } + end + end + end + + context 'when deleting package revision' do + context 'when the package revision is orphan but there are other package revisions' do + let_it_be(:package_revision2) { create(:conan_package_revision, package: package) } + let_it_be(:other_metadata) do + create(:conan_file_metadatum, recipe_revision: recipe_revision, package_reference: package_reference, + package_revision: package_revision2, conan_file_type: 'package_file', package_file: package_file_2) + end + + it 'deletes the package revision' do + expect { subject }.to change { Packages::PackageFile.count }.by(-1) + .and change { Packages::Conan::PackageRevision.count }.by(-1) + .and not_change { Packages::Conan::RecipeRevision.count } + .and not_change { Packages::Conan::PackageReference.count } + .and not_change { Packages::Conan::Package.count } + end + end + + context 'when the package revision is still referenced by other package files' do + let_it_be(:other_metadata) do + create(:conan_file_metadatum, conan_file_type: 'package_file', recipe_revision: recipe_revision, + package_reference: package_reference, package_revision: package_revision, package_file: package_file_2) + end + + it 'does not delete the package revision' do + expect { subject }.to change { Packages::PackageFile.count }.by(-1) + .and not_change { Packages::Conan::PackageRevision.count } + end + end + end + end end describe '#max_running_jobs' do diff --git a/workhorse/go.mod b/workhorse/go.mod index 9c2bb453534..d3666462d68 100644 --- a/workhorse/go.mod +++ b/workhorse/go.mod @@ -25,7 +25,7 @@ require ( github.com/jpillora/backoff v1.0.0 github.com/mitchellh/copystructure v1.2.0 github.com/prometheus/client_golang v1.21.1 - github.com/redis/go-redis/v9 v9.7.3 + github.com/redis/go-redis/v9 v9.8.0 github.com/sebest/xff v0.0.0-20210106013422-671bd2870b3a github.com/sirupsen/logrus v1.9.3 github.com/sony/gobreaker/v2 v2.1.0 diff --git a/workhorse/go.sum b/workhorse/go.sum index 1ade3594e72..f0d0e83e781 100644 --- a/workhorse/go.sum +++ b/workhorse/go.sum @@ -544,8 +544,8 @@ github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0leargg github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= github.com/prometheus/prometheus v0.54.0 h1:6+VmEkohHcofl3W5LyRlhw1Lfm575w/aX6ZFyVAmzM0= github.com/prometheus/prometheus v0.54.0/go.mod h1:xlLByHhk2g3ycakQGrMaU8K7OySZx98BzeCR99991NY= -github.com/redis/go-redis/v9 v9.7.3 h1:YpPyAayJV+XErNsatSElgRZZVCwXX9QzkKYNvO7x0wM= -github.com/redis/go-redis/v9 v9.7.3/go.mod h1:bGUrSggJ9X9GUmZpZNEOQKaANxSGgOEBRltRTZHSvrA= +github.com/redis/go-redis/v9 v9.8.0 h1:q3nRvjrlge/6UD7eTu/DSg2uYiU2mCL0G/uzBWqhicI= +github.com/redis/go-redis/v9 v9.8.0/go.mod h1:huWgSWd8mW6+m0VPhJjSSQ+d6Nh1VICQ6Q5lHuCH/Iw= github.com/redis/rueidis v1.0.19 h1:s65oWtotzlIFN8eMPhyYwxlwLR1lUdhza2KtWprKYSo= github.com/redis/rueidis v1.0.19/go.mod h1:8B+r5wdnjwK3lTFml5VtxjzGOQAC+5UmujoD12pDrEo= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=