From 98ba44db4ff7215e9a7df3ca156a056b0528d94f Mon Sep 17 00:00:00 2001 From: GitLab Bot Date: Mon, 3 Mar 2025 15:12:42 +0000 Subject: [PATCH] Add latest changes from gitlab-org/gitlab@master --- .rubocop_todo/gitlab/no_find_in_workers.yml | 1 - .rubocop_todo/rspec/be_nil.yml | 20 --- .rubocop_todo/rspec/named_subject.yml | 1 - .rubocop_todo/style/format_string.yml | 14 -- .../components/abuse_category_selector.vue | 7 +- .../components/links_to_spam_input.vue | 8 +- .../super_sidebar/super_sidebar_bundle.js | 1 + .../projects/application_controller.rb | 3 +- .../google_cloud/deployments_controller.rb | 2 +- .../service_accounts_controller.rb | 4 +- app/controllers/projects/issues_controller.rb | 3 +- .../projects/pipeline_schedules_controller.rb | 7 +- .../projects/settings/ci_cd_controller.rb | 3 +- app/controllers/projects_controller.rb | 6 +- app/controllers/search_controller.rb | 12 +- app/controllers/users_controller.rb | 4 +- app/finders/todos_finder.rb | 6 +- .../mutations/release_asset_links/create.rb | 3 +- .../resolvers/merge_requests_resolver.rb | 38 ++++- ...unioned_merge_request_filter_input_type.rb | 13 ++ app/helpers/button_helper.rb | 4 +- app/helpers/ci/builds_helper.rb | 2 +- app/helpers/ci/runners_helper.rb | 6 +- app/helpers/form_helper.rb | 4 +- .../work_items/related_work_item_link.rb | 2 + .../bulk_reassign_from_csv_service.rb | 8 + app/views/abuse_reports/new.html.haml | 21 +-- .../nav/breadcrumbs/_breadcrumbs.html.haml | 2 +- app/views/projects/blob/_editor.html.haml | 26 ++-- app/workers/ci/delete_objects_worker.rb | 4 +- .../development/source_editor_toolbar.yml | 8 - .../duo_chat_docs_qa_claude_3_7.yml | 9 ++ data/deprecations/17-9-move-agentk-to-cng.yml | 15 +- ...ackfill_ml_candidate_params_project_id.yml | 2 +- ...ed_tag_create_access_levels_project_id.yml | 5 +- ...ted_tag_create_access_levels_project_id.rb | 21 +++ ...backfill_ml_candidate_params_project_id.rb | 21 +++ db/schema_migrations/20250213231531 | 1 + db/schema_migrations/20250302231854 | 1 + .../gitlab_duo_self_hosted/_index.md | 25 +++- doc/api/graphql/reference/_index.md | 58 ++++++++ doc/api/model_registry.md | 7 +- doc/topics/git/undo.md | 9 +- doc/update/deprecations.md | 15 +- doc/user/packages/generic_packages/_index.md | 3 +- .../ml/experiment_tracking/mlflow_client.md | 3 +- lib/gitlab/gon_helper.rb | 1 - locale/gitlab.pot | 12 ++ package.json | 4 +- .../settings/ci_cd_controller_spec.rb | 2 +- spec/controllers/projects_controller_spec.rb | 2 +- spec/features/projects/blobs/edit_spec.rb | 8 +- spec/finders/merge_requests_finder_spec.rb | 44 ++++++ .../release_asset_links/create_spec.rb | 2 +- .../resolvers/merge_requests_resolver_spec.rb | 138 ++++++++++++++++++ .../project_merge_requests_resolver_spec.rb | 3 +- ...ed_merge_request_filter_input_type_spec.rb | 33 +++++ .../custom_email_verification_spec.rb | 2 +- spec/models/snippet_spec.rb | 6 +- spec/models/user_spec.rb | 14 +- spec/presenters/project_presenter_spec.rb | 4 +- spec/requests/api/applications_spec.rb | 2 +- spec/requests/api/ci/pipelines_spec.rb | 10 +- spec/requests/api/ci/secure_files_spec.rb | 6 +- spec/requests/api/environments_spec.rb | 2 +- spec/requests/api/markdown_uploads_spec.rb | 4 +- spec/requests/api/merge_requests_spec.rb | 2 +- spec/requests/api/settings_spec.rb | 20 +-- .../bulk_reassign_from_csv_service_spec.rb | 30 ++++ .../gitlab/gitaly_client_shared_examples.rb | 4 +- .../template/template_shared_examples.rb | 2 +- .../diff_positionable_note_shared_examples.rb | 4 +- .../models/user_mentions_shared_examples.rb | 6 +- .../projects/services_shared_examples.rb | 4 +- .../services/auto_merge_shared_examples.rb | 2 +- .../helpers/keyset_pagination_helpers_spec.rb | 2 +- spec/uploaders/object_storage_spec.rb | 2 +- .../error_tracking_issue_link_worker_spec.rb | 2 +- .../assignment_from_csv_worker_spec.rb | 2 +- yarn.lock | 78 +++++----- 80 files changed, 656 insertions(+), 241 deletions(-) create mode 100644 app/graphql/types/merge_requests/unioned_merge_request_filter_input_type.rb delete mode 100644 config/feature_flags/development/source_editor_toolbar.yml create mode 100644 config/feature_flags/gitlab_com_derisk/duo_chat_docs_qa_claude_3_7.yml create mode 100644 db/post_migrate/20250213231531_finalize_hk_backfill_protected_tag_create_access_levels_project_id.rb create mode 100644 db/post_migrate/20250302231854_finalize_hk_backfill_ml_candidate_params_project_id.rb create mode 100644 db/schema_migrations/20250213231531 create mode 100644 db/schema_migrations/20250302231854 create mode 100644 spec/graphql/types/merge_requests/unioned_merge_request_filter_input_type_spec.rb diff --git a/.rubocop_todo/gitlab/no_find_in_workers.yml b/.rubocop_todo/gitlab/no_find_in_workers.yml index 90de403d03e..47b5fff7ff5 100644 --- a/.rubocop_todo/gitlab/no_find_in_workers.yml +++ b/.rubocop_todo/gitlab/no_find_in_workers.yml @@ -89,5 +89,4 @@ Gitlab/NoFindInWorkers: - 'ee/app/workers/namespaces/storage_usage_export_worker.rb' - 'ee/app/workers/repository_update_mirror_worker.rb' - 'ee/app/workers/requirements_management/import_requirements_csv_worker.rb' - - 'ee/app/workers/search/zoekt/namespace_indexer_worker.rb' - 'ee/app/workers/work_items/rolledup_dates/bulk_update_handler.rb' diff --git a/.rubocop_todo/rspec/be_nil.yml b/.rubocop_todo/rspec/be_nil.yml index c0cb2fd539e..384c2c9db4c 100644 --- a/.rubocop_todo/rspec/be_nil.yml +++ b/.rubocop_todo/rspec/be_nil.yml @@ -58,23 +58,3 @@ RSpec/BeNil: - 'spec/models/ml/model_spec.rb' - 'spec/models/ml/model_version_spec.rb' - 'spec/models/project_spec.rb' - - 'spec/models/service_desk/custom_email_verification_spec.rb' - - 'spec/models/snippet_spec.rb' - - 'spec/models/user_spec.rb' - - 'spec/presenters/project_presenter_spec.rb' - - 'spec/requests/api/applications_spec.rb' - - 'spec/requests/api/ci/pipelines_spec.rb' - - 'spec/requests/api/ci/secure_files_spec.rb' - - 'spec/requests/api/environments_spec.rb' - - 'spec/requests/api/markdown_uploads_spec.rb' - - 'spec/requests/api/merge_requests_spec.rb' - - 'spec/requests/api/settings_spec.rb' - - 'spec/support/shared_examples/lib/gitlab/gitaly_client_shared_examples.rb' - - 'spec/support/shared_examples/lib/gitlab/template/template_shared_examples.rb' - - 'spec/support/shared_examples/models/diff_positionable_note_shared_examples.rb' - - 'spec/support/shared_examples/models/user_mentions_shared_examples.rb' - - 'spec/support/shared_examples/requests/api/graphql/projects/services_shared_examples.rb' - - 'spec/support/shared_examples/services/auto_merge_shared_examples.rb' - - 'spec/support_specs/helpers/keyset_pagination_helpers_spec.rb' - - 'spec/uploaders/object_storage_spec.rb' - - 'spec/workers/error_tracking_issue_link_worker_spec.rb' diff --git a/.rubocop_todo/rspec/named_subject.yml b/.rubocop_todo/rspec/named_subject.yml index 29f8f1f7cc0..4b56c1ba3b1 100644 --- a/.rubocop_todo/rspec/named_subject.yml +++ b/.rubocop_todo/rspec/named_subject.yml @@ -1089,7 +1089,6 @@ RSpec/NamedSubject: - 'ee/spec/workers/repository_update_mirror_worker_spec.rb' - 'ee/spec/workers/requirements_management/import_requirements_csv_worker_spec.rb' - 'ee/spec/workers/requirements_management/process_requirements_reports_worker_spec.rb' - - 'ee/spec/workers/search/zoekt/namespace_indexer_worker_spec.rb' - 'ee/spec/workers/security/scan_execution_policies/rule_schedule_worker_spec.rb' - 'ee/spec/workers/security/scans/purge_by_job_id_worker_spec.rb' - 'ee/spec/workers/security/track_secure_scans_worker_spec.rb' diff --git a/.rubocop_todo/style/format_string.yml b/.rubocop_todo/style/format_string.yml index c59ee1b3062..8cadd90336d 100644 --- a/.rubocop_todo/style/format_string.yml +++ b/.rubocop_todo/style/format_string.yml @@ -2,21 +2,7 @@ # Cop supports --autocorrect. Style/FormatString: Exclude: - - 'app/controllers/projects/google_cloud/deployments_controller.rb' - - 'app/controllers/projects/google_cloud/service_accounts_controller.rb' - - 'app/controllers/projects/issues_controller.rb' - - 'app/controllers/projects/pipeline_schedules_controller.rb' - - 'app/controllers/projects/settings/ci_cd_controller.rb' - - 'app/controllers/projects_controller.rb' - - 'app/controllers/search_controller.rb' - - 'app/controllers/users_controller.rb' - - 'app/finders/todos_finder.rb' - - 'app/graphql/mutations/release_asset_links/create.rb' - - 'app/helpers/button_helper.rb' - - 'app/helpers/ci/builds_helper.rb' - - 'app/helpers/ci/runners_helper.rb' - 'app/helpers/emails_helper.rb' - - 'app/helpers/form_helper.rb' - 'app/helpers/groups/group_members_helper.rb' - 'app/helpers/groups_helper.rb' - 'app/helpers/import_helper.rb' diff --git a/app/assets/javascripts/abuse_reports/components/abuse_category_selector.vue b/app/assets/javascripts/abuse_reports/components/abuse_category_selector.vue index 005b4f2b816..42725e8e44c 100644 --- a/app/assets/javascripts/abuse_reports/components/abuse_category_selector.vue +++ b/app/assets/javascripts/abuse_reports/components/abuse_category_selector.vue @@ -92,8 +92,13 @@ export default { data-testid="input-referer" /> - +
- - + e track_event(:error_google_api) - flash[:warning] = _('Google Cloud Error - %{error}') % { error: e } + flash[:warning] = safe_format(_('Google Cloud Error - %{error}'), error: e) redirect_to project_google_cloud_deployments_path(project) end diff --git a/app/controllers/projects/google_cloud/service_accounts_controller.rb b/app/controllers/projects/google_cloud/service_accounts_controller.rb index 5a5f53943c0..3b45011b957 100644 --- a/app/controllers/projects/google_cloud/service_accounts_controller.rb +++ b/app/controllers/projects/google_cloud/service_accounts_controller.rb @@ -20,7 +20,7 @@ class Projects::GoogleCloud::ServiceAccountsController < Projects::GoogleCloud:: end rescue Google::Apis::Error => e track_event(:error_google_api) - flash[:warning] = _('Google Cloud Error - %{error}') % { error: e } + flash[:warning] = safe_format(_('Google Cloud Error - %{error}'), error: e) redirect_to project_google_cloud_configuration_path(project) end @@ -39,7 +39,7 @@ class Projects::GoogleCloud::ServiceAccountsController < Projects::GoogleCloud:: redirect_to project_google_cloud_configuration_path(project), notice: response.message rescue Google::Apis::Error => e track_event(:error_google_api) - flash[:warning] = _('Google Cloud Error - %{error}') % { error: e } + flash[:warning] = safe_format(_('Google Cloud Error - %{error}'), error: e) redirect_to project_google_cloud_configuration_path(project) end end diff --git a/app/controllers/projects/issues_controller.rb b/app/controllers/projects/issues_controller.rb index a4c9da5e4e8..b04da3878ed 100644 --- a/app/controllers/projects/issues_controller.rb +++ b/app/controllers/projects/issues_controller.rb @@ -266,7 +266,8 @@ class Projects::IssuesController < Projects::ApplicationController IssuableExportCsvWorker.perform_async(:issue, current_user.id, project.id, finder_options.to_h) # rubocop:disable CodeReuse/Worker index_path = project_issues_path(project) - message = _('Your CSV export has started. It will be emailed to %{email} when complete.') % { email: current_user.notification_email_or_default } + message = safe_format(_('Your CSV export has started. It will be emailed to %{email} when complete.'), + email: current_user.notification_email_or_default) redirect_to(index_path, notice: message) end diff --git a/app/controllers/projects/pipeline_schedules_controller.rb b/app/controllers/projects/pipeline_schedules_controller.rb index 10416d9cad8..f50be195750 100644 --- a/app/controllers/projects/pipeline_schedules_controller.rb +++ b/app/controllers/projects/pipeline_schedules_controller.rb @@ -1,6 +1,8 @@ # frozen_string_literal: true class Projects::PipelineSchedulesController < Projects::ApplicationController + include SafeFormatHelper + before_action :schedule, except: [:index, :new, :create] before_action :check_play_rate_limit!, only: [:play] @@ -50,9 +52,8 @@ class Projects::PipelineSchedulesController < Projects::ApplicationController .execute(schedule) if job_id - pipelines_link_start = "" - message = _("Successfully scheduled a pipeline to run. Go to the %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details.") % { pipelines_link_start: pipelines_link_start, pipelines_link_end: "" } - flash[:notice] = message.html_safe + pipelines_link = helpers.link_to('', project_pipelines_path(@project)) + flash[:notice] = safe_format(_("Successfully scheduled a pipeline to run. Go to the %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details."), tag_pair(pipelines_link, :pipelines_link_start, :pipelines_link_end)) else flash[:alert] = _('Unable to schedule a pipeline to run immediately') end diff --git a/app/controllers/projects/settings/ci_cd_controller.rb b/app/controllers/projects/settings/ci_cd_controller.rb index eb260b55f5d..7c440205b24 100644 --- a/app/controllers/projects/settings/ci_cd_controller.rb +++ b/app/controllers/projects/settings/ci_cd_controller.rb @@ -47,7 +47,8 @@ module Projects Projects::UpdateService.new(project, current_user, update_params).tap do |service| result = service.execute if result[:status] == :success - flash[:toast] = _("Pipelines settings for '%{project_name}' were successfully updated.") % { project_name: @project.name } + flash[:toast] = safe_format(_("Pipelines settings for '%{project_name}' were successfully updated."), + project_name: @project.name) run_autodevops_pipeline(service) diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index 54655bb5872..0b0c8b11198 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -111,7 +111,7 @@ class ProjectsController < Projects::ApplicationController if @project.saved? redirect_to( project_path(@project, custom_import_params), - notice: _("Project '%{project_name}' was successfully created.") % { project_name: @project.name } + notice: safe_format(_("Project '%{project_name}' was successfully created."), project_name: @project.name) ) else render 'new' @@ -173,7 +173,7 @@ class ProjectsController < Projects::ApplicationController end if @project.pending_delete? - flash.now[:alert] = _("Project '%{project_name}' queued for deletion.") % { project_name: @project.name } + flash.now[:alert] = safe_format(_("Project '%{project_name}' queued for deletion."), project_name: @project.name) end @ref_type = 'heads' @@ -196,7 +196,7 @@ class ProjectsController < Projects::ApplicationController return access_denied! unless can?(current_user, :remove_project, @project) ::Projects::DestroyService.new(@project, current_user, {}).async_execute - flash[:toast] = format(_("Project '%{project_name}' is being deleted."), project_name: @project.full_name) + flash[:toast] = safe_format(_("Project '%{project_name}' is being deleted."), project_name: @project.full_name) redirect_to dashboard_projects_path, status: :found rescue Projects::DestroyService::DestroyError => e diff --git a/app/controllers/search_controller.rb b/app/controllers/search_controller.rb index be0b0854fe5..8ec26c6dbbc 100644 --- a/app/controllers/search_controller.rb +++ b/app/controllers/search_controller.rb @@ -2,6 +2,7 @@ class SearchController < ApplicationController include ControllerWithCrossProjectAccessCheck + include SafeFormatHelper include SearchHelper include ProductAnalyticsTracking include Gitlab::InternalEventsTracking @@ -232,14 +233,15 @@ class SearchController < ApplicationController return false unless commit.present? link = search_path(safe_params.merge(force_search_results: true)) - flash[:notice] = ERB::Util.html_escape( + search_link = helpers.link_to('', link) + + flash[:notice] = safe_format( _( "You have been redirected to the only result; " \ "see the %{a_start}search results%{a_end} instead." - ) - ) % { - a_start: "".html_safe, a_end: ''.html_safe - } + ), + tag_pair(search_link, :a_start, :a_end) + ) redirect_to project_commit_path(@project, commit) true diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 4e1f44fdfb9..512742070ac 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -7,6 +7,7 @@ class UsersController < ApplicationController include RendersProjectsList include ControllerWithCrossProjectAccessCheck include Gitlab::NoteableMetadata + include SafeFormatHelper FOLLOWERS_FOLLOWING_USERS_PER_PAGE = 21 @@ -65,7 +66,8 @@ class UsersController < ApplicationController end format.json do - msg = "This endpoint is deprecated. Use %s instead." % user_activity_path + msg = safe_format("This endpoint is deprecated. Use %{user_activity_path} instead.", + user_activity_path: user_activity_path) render json: { message: msg }, status: :not_found end end diff --git a/app/finders/todos_finder.rb b/app/finders/todos_finder.rb index f8cc4a55acf..22ccb3bebdc 100644 --- a/app/finders/todos_finder.rb +++ b/app/finders/todos_finder.rb @@ -20,6 +20,7 @@ class TodosFinder prepend FinderWithCrossProjectAccess include FinderMethods include Gitlab::Utils::StrongMemoize + include SafeFormatHelper requires_cross_project_access unless: -> { project? } @@ -143,9 +144,8 @@ class TodosFinder end def invalid_type_message - _("Unsupported todo type passed. Supported todo types are: %{todo_types}") % { - todo_types: self.class.todo_types.to_a.join(', ') - } + safe_format(_("Unsupported todo type passed. Supported todo types are: %{todo_types}"), + todo_types: self.class.todo_types.to_a.join(', ')) end def sort(items) diff --git a/app/graphql/mutations/release_asset_links/create.rb b/app/graphql/mutations/release_asset_links/create.rb index 363ee98d468..9af587a1949 100644 --- a/app/graphql/mutations/release_asset_links/create.rb +++ b/app/graphql/mutations/release_asset_links/create.rb @@ -6,6 +6,7 @@ module Mutations graphql_name 'ReleaseAssetLinkCreate' include FindsProject + include SafeFormatHelper include Types::ReleaseAssetLinkSharedInputArguments authorize :create_release @@ -28,7 +29,7 @@ module Mutations release = project.releases.find_by_tag(tag) if release.nil? - message = _('Release with tag "%{tag}" was not found') % { tag: tag } + message = safe_format(_('Release with tag "%{tag}" was not found'), tag: tag) return { link: nil, errors: [message] } end diff --git a/app/graphql/resolvers/merge_requests_resolver.rb b/app/graphql/resolvers/merge_requests_resolver.rb index e6adac4740d..3e832335378 100644 --- a/app/graphql/resolvers/merge_requests_resolver.rb +++ b/app/graphql/resolvers/merge_requests_resolver.rb @@ -14,6 +14,9 @@ module Resolvers argument :assignee_username, GraphQL::Types::String, required: false, description: 'Username of the assignee.' + argument :assignee_usernames, [GraphQL::Types::String], + required: false, + description: 'Usernames of users assigned to the merge request.' argument :assignee_wildcard_id, ::Types::AssigneeWildcardIdEnum, required: false, description: 'Filter by assignee presence. Incompatible with assigneeUsernames and assigneeUsername.' @@ -43,18 +46,19 @@ module Resolvers required: false, description: 'Filter by release tag.' + argument :iids, [GraphQL::Types::String], + required: false, + description: 'Array of IIDs of merge requests, for example `[1, 2]`.' argument :merged_by, GraphQL::Types::String, required: false, as: :merge_user_username, description: 'Username of the merger.' - argument :my_reaction_emoji, GraphQL::Types::String, required: false, description: 'Filter by your reaction emoji.' - - argument :iids, [GraphQL::Types::String], - required: false, - description: 'Array of IIDs of merge requests, for example `[1, 2]`.' + argument :or, Types::MergeRequests::UnionedMergeRequestFilterInputType, + description: 'List of arguments with inclusive OR.', + required: false argument :source_branches, [GraphQL::Types::String], required: false, @@ -204,7 +208,7 @@ module Resolvers description: 'Filters merge requests to exclude the target branch names provided in the given array.' end - validates mutually_exclusive: [:assignee_username, :assignee_wildcard_id] + validates mutually_exclusive: [:assignee_usernames, :assignee_username, :assignee_wildcard_id] validates mutually_exclusive: [:reviewer_username, :reviewer_wildcard_id] validates mutually_exclusive: [:milestone_title, :milestone_wildcard_id] @@ -219,6 +223,28 @@ module Resolvers def some_argument_is_empty?(args) args.values.any? { |v| v.is_a?(Array) && v.empty? } end + + private + + def prepare_finder_params(args) + params = super + params[:not] = params[:not].to_h if params[:not] + params[:or] = params[:or].to_h if params[:or] + + prepare_assignee_username_params(params) + + params + end + + def prepare_assignee_username_params(args) + rewrite_param_name(args, :assignee_usernames, :assignee_username) + rewrite_param_name(args[:or], :assignee_usernames, :assignee_username) + rewrite_param_name(args[:not], :assignee_usernames, :assignee_username) + end + + def rewrite_param_name(params, old_name, new_name) + params[new_name] = params.delete(old_name) if params && params[old_name].present? + end end end diff --git a/app/graphql/types/merge_requests/unioned_merge_request_filter_input_type.rb b/app/graphql/types/merge_requests/unioned_merge_request_filter_input_type.rb new file mode 100644 index 00000000000..17f4b0b9665 --- /dev/null +++ b/app/graphql/types/merge_requests/unioned_merge_request_filter_input_type.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +module Types + module MergeRequests + class UnionedMergeRequestFilterInputType < BaseInputObject + graphql_name 'UnionedMergeRequestFilterInput' + + argument :assignee_usernames, [GraphQL::Types::String], + required: false, + description: 'Filters MRs that are assigned to at least one of the given users.' + end + end +end diff --git a/app/helpers/button_helper.rb b/app/helpers/button_helper.rb index 15bb96142a2..62976c3d7df 100644 --- a/app/helpers/button_helper.rb +++ b/app/helpers/button_helper.rb @@ -79,9 +79,9 @@ module ButtonHelper def http_dropdown_description(protocol) if current_user.try(:require_password_creation_for_git?) - _("Set a password on your account to pull or push via %{protocol}.") % { protocol: protocol } + safe_format(_("Set a password on your account to pull or push via %{protocol}."), protocol: protocol) elsif current_user.try(:require_personal_access_token_creation_for_git_auth?) - _("Create a personal access token on your account to pull or push via %{protocol}.") % { protocol: protocol } + safe_format(_("Create a personal access token on your account to pull or push via %{protocol}."), protocol: protocol) end end diff --git a/app/helpers/ci/builds_helper.rb b/app/helpers/ci/builds_helper.rb index 6fa3840fac0..f65b6a835ee 100644 --- a/app/helpers/ci/builds_helper.rb +++ b/app/helpers/ci/builds_helper.rb @@ -4,7 +4,7 @@ module Ci module BuildsHelper def build_failed_issue_options { - title: _("Job Failed #%{build_id}") % { build_id: @build.id }, + title: safe_format(_("Job Failed #%{build_id}"), build_id: @build.id), description: project_job_url(@project, @build) } end diff --git a/app/helpers/ci/runners_helper.rb b/app/helpers/ci/runners_helper.rb index 1fba67f743a..333b30b1157 100644 --- a/app/helpers/ci/runners_helper.rb +++ b/app/helpers/ci/runners_helper.rb @@ -14,7 +14,7 @@ module Ci case status when :online - title = s_("Runners|Runner is online; last contact was %{runner_contact} ago") % { runner_contact: time_ago_in_words(contacted_at) } + title = safe_format(s_("Runners|Runner is online; last contact was %{runner_contact} ago"), runner_contact: time_ago_in_words(contacted_at)) icon = 'status-active' span_class = 'gl-text-success' when :never_contacted @@ -23,7 +23,7 @@ module Ci when :offline title = if contacted_at - s_("Runners|Runner is offline; last contact was %{runner_contact} ago") % { runner_contact: time_ago_in_words(contacted_at) } + safe_format(s_("Runners|Runner is offline; last contact was %{runner_contact} ago"), runner_contact: time_ago_in_words(contacted_at)) else s_("Runners|Runner is offline; it has never contacted this instance") end @@ -32,7 +32,7 @@ module Ci span_class = 'gl-text-subtle' when :stale # runner may have contacted (or not) and be stale: consider both cases. - title = contacted_at ? s_("Runners|Runner is stale; last contact was %{runner_contact} ago") % { runner_contact: time_ago_in_words(contacted_at) } : s_("Runners|Runner is stale; it has never contacted this instance") + title = contacted_at ? safe_format(s_("Runners|Runner is stale; last contact was %{runner_contact} ago"), runner_contact: time_ago_in_words(contacted_at)) : s_("Runners|Runner is stale; it has never contacted this instance") icon = 'time-out' span_class = 'gl-text-warning' end diff --git a/app/helpers/form_helper.rb b/app/helpers/form_helper.rb index ef1ff7b155b..5c291e5e051 100644 --- a/app/helpers/form_helper.rb +++ b/app/helpers/form_helper.rb @@ -6,11 +6,11 @@ module FormHelper return unless errors.any? - headline = custom_headline || (n_( + headline = custom_headline || safe_format(n_( 'The %{type} contains the following error:', 'The %{type} contains the following errors:', errors.count - ) % { type: type }) + ), type: type) truncate = Array.wrap(truncate) diff --git a/app/models/work_items/related_work_item_link.rb b/app/models/work_items/related_work_item_link.rb index fb0069541fb..6f05ff8dfbd 100644 --- a/app/models/work_items/related_work_item_link.rb +++ b/app/models/work_items/related_work_item_link.rb @@ -3,6 +3,8 @@ module WorkItems class RelatedWorkItemLink < ApplicationRecord include LinkableItem + include CreatedAtFilterable + include UpdatedAtFilterable self.table_name = 'issue_links' diff --git a/app/services/import/source_users/bulk_reassign_from_csv_service.rb b/app/services/import/source_users/bulk_reassign_from_csv_service.rb index 3de4d089ee7..e82c2bd980f 100644 --- a/app/services/import/source_users/bulk_reassign_from_csv_service.rb +++ b/app/services/import/source_users/bulk_reassign_from_csv_service.rb @@ -92,6 +92,14 @@ module Import ) end + # If the source user is already in some mid-reassignment state for the + # same reassign_to_user, we treat it as though the CSV line matched. + # This is to avoid misleading error messages if a worker restart causes + # the same CSV line to be processed multiple times. + if !source_user.reassignable_status? && source_user.reassign_to_user_id == reassign_to_user.id + return ServiceResponse.success(payload: source_user) + end + ::Import::SourceUsers::ReassignService.new( source_user, reassign_to_user, diff --git a/app/views/abuse_reports/new.html.haml b/app/views/abuse_reports/new.html.haml index d35437fa148..c47d2ee7d4a 100644 --- a/app/views/abuse_reports/new.html.haml +++ b/app/views/abuse_reports/new.html.haml @@ -9,32 +9,33 @@ = form_errors(@abuse_report) = f.hidden_field :user_id - = f.hidden_field :category .form-group.row .col-lg-8 - = f.label :reported_user - + = f.label :category + = f.text_field :category, class: "form-control gl-form-input", readonly: true + .form-group.row + .col-lg-8 + = f.label :user_name, for: 'user_name' - name = "#{@abuse_report.user.name} (@#{@abuse_report.user.username})" - = text_field_tag :user_name, name, class: "form-control", readonly: true + = text_field_tag :user_name, name, class: "form-control gl-form-input", readonly: true .form-group.row .col-lg-8 - = f.label :reported_from - = f.text_field :reported_from_url, class: "form-control", readonly: true + = f.label :reported_from_url + = f.text_field :reported_from_url, class: "form-control gl-form-input", readonly: true #js-links-to-spam{ data: { links: Array(@abuse_report.links_to_spam) } } .form-group.row .col-lg-8 = f.label :screenshot do - %span - = s_('ReportAbuse|Screenshot') + = s_('ReportAbuse|Screenshot') %div = render 'shared/file_picker_button', f: f, field: :screenshot, help_text: _("Screenshot must be less than 1 MB."), mime_types: valid_image_mimetypes .form-group.row .col-lg-8 - = f.label :reason - = f.text_area :message, class: "form-control", rows: 4, required: true + = f.label :message + = f.text_area :message, class: "form-control gl-form-input", rows: 4, required: true .form-text.gl-text-subtle = _("Explain why you're reporting the user.") diff --git a/app/views/layouts/nav/breadcrumbs/_breadcrumbs.html.haml b/app/views/layouts/nav/breadcrumbs/_breadcrumbs.html.haml index 4797a7f8100..59702d3b30a 100644 --- a/app/views/layouts/nav/breadcrumbs/_breadcrumbs.html.haml +++ b/app/views/layouts/nav/breadcrumbs/_breadcrumbs.html.haml @@ -2,7 +2,7 @@ - if !hide_top_links && @header_title && @header_title_url - push_to_schema_breadcrumb(@header_title, @header_title_url) - unless @skip_current_level_breadcrumb - - push_to_schema_breadcrumb(@breadcrumb_title, breadcrumb_title_link) + - push_to_schema_breadcrumb(@breadcrumb_title, breadcrumb_title_link, @breadcrumb_title_avatar) -# See https://schema.org/BreadcrumbList -# haml-lint:disable InlineJavaScript diff --git a/app/views/projects/blob/_editor.html.haml b/app/views/projects/blob/_editor.html.haml index aff70f248c2..d403d4e5c03 100644 --- a/app/views/projects/blob/_editor.html.haml +++ b/app/views/projects/blob/_editor.html.haml @@ -19,21 +19,17 @@ - input_options = { label: _('File name'), id: 'file_name', name: 'file_name', value: params[:file_name] || '', required: true, placeholder: "Filename", testid: 'file-name-field', class: 'new-file-name js-file-path-name-input' } = render 'filepath_form', input_options: input_options - - if Feature.enabled?(:source_editor_toolbar, current_user) - #editor-toolbar - - - else - .file-buttons.gl-flex.gl-items-center.gl-justify-end - - if is_markdown - .md-header.gl-flex.gl-px-2.gl-rounded-base.gl-mx-2.gl-mt-2 - .gl-flex.gl-items-center.gl-flex-wrap.gl-justify-between - .md-header-toolbar.gl-flex.gl-py-2.gl-flex-wrap{ class: "!gl-m-0" } - = render 'shared/blob/markdown_buttons', supports_file_upload: false - %span.soft-wrap-toggle - = render Pajamas::ButtonComponent.new(icon: 'soft-unwrap', button_options: { class: 'no-wrap' }) do - = _("No wrap") - = render Pajamas::ButtonComponent.new(icon: 'soft-wrap', button_options: { class: 'soft-wrap' }) do - = _("Soft wrap") + .file-buttons.gl-flex.gl-items-center.gl-justify-end + - if is_markdown + .md-header.gl-flex.gl-px-2.gl-rounded-base.gl-mx-2.gl-mt-2 + .gl-flex.gl-items-center.gl-flex-wrap.gl-justify-between + .md-header-toolbar.gl-flex.gl-py-2.gl-flex-wrap{ class: "!gl-m-0" } + = render 'shared/blob/markdown_buttons', supports_file_upload: false + %span.soft-wrap-toggle + = render Pajamas::ButtonComponent.new(icon: 'soft-unwrap', button_options: { class: 'no-wrap' }) do + = _("No wrap") + = render Pajamas::ButtonComponent.new(icon: 'soft-wrap', button_options: { class: 'soft-wrap' }) do + = _("Soft wrap") .file-editor.code .js-edit-mode-pane#editor{ data: { 'editor-loading': true, testid: 'source-editor-preview-container', ref: ref} }< diff --git a/app/workers/ci/delete_objects_worker.rb b/app/workers/ci/delete_objects_worker.rb index 579e2a11543..287a15d4147 100644 --- a/app/workers/ci/delete_objects_worker.rb +++ b/app/workers/ci/delete_objects_worker.rb @@ -41,7 +41,9 @@ module Ci def deletion_delay_metrics(latencies) return { min: nil, max: nil, sum: 0, average: nil, total_count: 0 } if latencies.blank? - sum = latencies.sum.to_f + latencies = latencies.map(&:to_f) + + sum = latencies.sum size = latencies.size { diff --git a/config/feature_flags/development/source_editor_toolbar.yml b/config/feature_flags/development/source_editor_toolbar.yml deleted file mode 100644 index 6d8a749b945..00000000000 --- a/config/feature_flags/development/source_editor_toolbar.yml +++ /dev/null @@ -1,8 +0,0 @@ ---- -name: source_editor_toolbar -introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/82304 -rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/354748 -milestone: '14.9' -type: development -group: group::source code -default_enabled: false diff --git a/config/feature_flags/gitlab_com_derisk/duo_chat_docs_qa_claude_3_7.yml b/config/feature_flags/gitlab_com_derisk/duo_chat_docs_qa_claude_3_7.yml new file mode 100644 index 00000000000..7071d4f42f3 --- /dev/null +++ b/config/feature_flags/gitlab_com_derisk/duo_chat_docs_qa_claude_3_7.yml @@ -0,0 +1,9 @@ +--- +name: duo_chat_docs_qa_claude_3_7 +feature_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/521058 +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/182991 +rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/521833 +milestone: '17.10' +group: group::duo chat +type: gitlab_com_derisk +default_enabled: false diff --git a/data/deprecations/17-9-move-agentk-to-cng.yml b/data/deprecations/17-9-move-agentk-to-cng.yml index 615b3e1bd0d..552805d665c 100644 --- a/data/deprecations/17-9-move-agentk-to-cng.yml +++ b/data/deprecations/17-9-move-agentk-to-cng.yml @@ -11,8 +11,15 @@ resolution_role: Admin manual_task: true body: | # (required) Don't change this line. - We are moving the `agentk` container registry from [its project-specific registry](https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent/container_registry/1223205) to [the Cloud Native GitLab registry](https://gitlab.com/gitlab-org/build/CNG/container_registry/8241772). - From GitLab 18.0, the project-specific registry will not receive `agentk` updates. - If you mirror the `agentk` container to a local registry, you should change your mirror source to the CNG registry. + We are moving the `agentk` container registry from + [its project-specific registry](https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent/container_registry/1223205) + to [the Cloud Native GitLab (CNG) registry](https://gitlab.com/gitlab-org/build/CNG/container_registry/8241772). + From GitLab 18.0 onward, `agentk` images built in CNG will mirror into the project-specific registry. + The new image is equivalent to the old image, except the new image only supports `amd64` and `arm64` architectures. + It does not support the 32-bit `arm` architecture. + From GitLab 19.0 onward, the project-specific registry will not receive `agentk` updates. + If you mirror the `agentk` container to a local registry, you should change your mirror source to the + [CNG registry](https://gitlab.com/gitlab-org/build/CNG/container_registry/8241772). - If you use the official Helm charts, they will start deploying from the new location seamlessly. + If you use the official [GitLab Agent Helm chart](https://gitlab.com/gitlab-org/charts/gitlab-agent/), + the new `agentk` image will start deploying from the new location seamlessly in GitLab 18.0. diff --git a/db/docs/batched_background_migrations/backfill_ml_candidate_params_project_id.yml b/db/docs/batched_background_migrations/backfill_ml_candidate_params_project_id.yml index cc28b212f17..f2936fc8cac 100644 --- a/db/docs/batched_background_migrations/backfill_ml_candidate_params_project_id.yml +++ b/db/docs/batched_background_migrations/backfill_ml_candidate_params_project_id.yml @@ -5,4 +5,4 @@ feature_category: mlops introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/165336 milestone: '17.4' queued_migration_version: 20240906131415 -finalized_by: # version of the migration that finalized this BBM +finalized_by: '20250302231854' diff --git a/db/docs/batched_background_migrations/backfill_protected_tag_create_access_levels_project_id.yml b/db/docs/batched_background_migrations/backfill_protected_tag_create_access_levels_project_id.yml index 73d04b8e8c1..f82c8bf541a 100644 --- a/db/docs/batched_background_migrations/backfill_protected_tag_create_access_levels_project_id.yml +++ b/db/docs/batched_background_migrations/backfill_protected_tag_create_access_levels_project_id.yml @@ -1,8 +1,9 @@ --- migration_job_name: BackfillProtectedTagCreateAccessLevelsProjectId -description: Backfills sharding key `protected_tag_create_access_levels.project_id` from `protected_tags`. +description: Backfills sharding key `protected_tag_create_access_levels.project_id` + from `protected_tags`. feature_category: source_code_management introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/156637 milestone: '17.2' queued_migration_version: 20240618122511 -finalized_by: # version of the migration that finalized this BBM +finalized_by: '20250213231531' diff --git a/db/post_migrate/20250213231531_finalize_hk_backfill_protected_tag_create_access_levels_project_id.rb b/db/post_migrate/20250213231531_finalize_hk_backfill_protected_tag_create_access_levels_project_id.rb new file mode 100644 index 00000000000..5f54cee5742 --- /dev/null +++ b/db/post_migrate/20250213231531_finalize_hk_backfill_protected_tag_create_access_levels_project_id.rb @@ -0,0 +1,21 @@ +# frozen_string_literal: true + +class FinalizeHkBackfillProtectedTagCreateAccessLevelsProjectId < Gitlab::Database::Migration[2.2] + milestone '17.10' + + disable_ddl_transaction! + + restrict_gitlab_migration gitlab_schema: :gitlab_main_cell + + def up + ensure_batched_background_migration_is_finished( + job_class_name: 'BackfillProtectedTagCreateAccessLevelsProjectId', + table_name: :protected_tag_create_access_levels, + column_name: :id, + job_arguments: [:project_id, :protected_tags, :project_id, :protected_tag_id], + finalize: true + ) + end + + def down; end +end diff --git a/db/post_migrate/20250302231854_finalize_hk_backfill_ml_candidate_params_project_id.rb b/db/post_migrate/20250302231854_finalize_hk_backfill_ml_candidate_params_project_id.rb new file mode 100644 index 00000000000..e5232b796e9 --- /dev/null +++ b/db/post_migrate/20250302231854_finalize_hk_backfill_ml_candidate_params_project_id.rb @@ -0,0 +1,21 @@ +# frozen_string_literal: true + +class FinalizeHkBackfillMlCandidateParamsProjectId < Gitlab::Database::Migration[2.2] + milestone '17.10' + + disable_ddl_transaction! + + restrict_gitlab_migration gitlab_schema: :gitlab_main_cell + + def up + ensure_batched_background_migration_is_finished( + job_class_name: 'BackfillMlCandidateParamsProjectId', + table_name: :ml_candidate_params, + column_name: :id, + job_arguments: [:project_id, :ml_candidates, :project_id, :candidate_id], + finalize: true + ) + end + + def down; end +end diff --git a/db/schema_migrations/20250213231531 b/db/schema_migrations/20250213231531 new file mode 100644 index 00000000000..32ac2f74d66 --- /dev/null +++ b/db/schema_migrations/20250213231531 @@ -0,0 +1 @@ +204f38d5453a47d0a1dd1f758e8b194bf64b80f46fb22f6754fa6d083df8974a \ No newline at end of file diff --git a/db/schema_migrations/20250302231854 b/db/schema_migrations/20250302231854 new file mode 100644 index 00000000000..f30afb90a24 --- /dev/null +++ b/db/schema_migrations/20250302231854 @@ -0,0 +1 @@ +200a96d5653c314ed9005d8e8027b7ec378ddd2ce76156c9fba450fe741881dd \ No newline at end of file diff --git a/doc/administration/gitlab_duo_self_hosted/_index.md b/doc/administration/gitlab_duo_self_hosted/_index.md index 42f873ceb82..d71aab04bc1 100644 --- a/doc/administration/gitlab_duo_self_hosted/_index.md +++ b/doc/administration/gitlab_duo_self_hosted/_index.md @@ -81,18 +81,25 @@ Before setting up the GitLab Duo Self-Hosted infrastructure, you must have: ## Decide on your configuration type -The configuration for GitLab Duo Self-Hosted is different to the default configuration -that uses GitLab external AI vendors. +GitLab Self-Managed customers can implement AI-powered features using either of the following options: -{{< alert type="note" >}} +- [**Self-hosted AI gateway and LLMs**](#self-hosted-ai-gateway-and-llms): Full control over your AI infrastructure. +- [**GitLab.com AI gateway with default GitLab external vendor LLMs**](#gitlabcom-ai-gateway-with-default-gitlab-external-vendor-llms): Use GitLab managed AI infrastructure. -Both of the following configuration types are for GitLab Self-Managed instances. +The differences between these options are: -{{< /alert >}} +| Feature | Self-hosted AI gateway | GitLab.com AI gateway | +|---------|------------------------|------------------------| +| Infrastructure requirements | Requires hosting your own AI gateway and models | No additional infrastructure needed | +| Model options | Choose from [supported models](../gitlab_duo_self_hosted/supported_models_and_hardware_requirements.md) | Uses the default GitLab external vendor LLMs | +| Network requirements | Can operate in fully isolated networks | Requires internet connectivity | +| Responsibilities | You set up your infrastructure, and do your own maintenance | GitLab does the set up and maintenance | ### Self-hosted AI gateway and LLMs -In a fully self-hosted configuration, you deploy your own AI gateway and LLMs in your infrastructure, without relying on external public services. This gives you full control over your data and security. +In a fully self-hosted configuration, you deploy your own AI gateway and use any [supported LLMs](supported_models_and_hardware_requirements.md) in your infrastructure, without relying on external public services. This gives you full control over your data and security. + +While this configuration is fully self-hosted and you can use models like Mistral that are hosted on your own infrastructure, you can still use cloud-based LLM services like [AWS Bedrock](https://aws.amazon.com/bedrock/) or [Azure OpenAI](https://azure.microsoft.com/en-us/products/ai-services/openai-service) as your model backend. If you have an offline environment with physical barriers or security policies that prevent or limit internet access, and comprehensive LLM controls, you can use GitLab Duo Self-Hosted. @@ -110,7 +117,11 @@ GitLab.com AI gateway with default GitLab external vendor LLMs. The GitLab.com AI gateway is the default Enterprise offering and is not self-hosted. In this configuration, you connect your instance to the GitLab-hosted AI gateway, which -integrates with external vendor LLM providers (such as Google Vertex or Anthropic). +integrates with external vendor LLM providers, including: + +- [Anthropic](https://www.anthropic.com/) +- [Fireworks AI](https://fireworks.ai/) +- [Google Vertex](https://cloud.google.com/vertex-ai/) These LLMs communicate through the [GitLab Cloud Connector](../../development/cloud_connector/_index.md), offering a ready-to-use AI solution without the need for on-premise infrastructure. diff --git a/doc/api/graphql/reference/_index.md b/doc/api/graphql/reference/_index.md index b33088e712c..6892dd8ac85 100644 --- a/doc/api/graphql/reference/_index.md +++ b/doc/api/graphql/reference/_index.md @@ -19678,6 +19678,7 @@ four standard [pagination arguments](#pagination-arguments): | `milestoneWildcardId` | [`MilestoneWildcardId`](#milestonewildcardid) | Filter issues by milestone ID wildcard. Incompatible with milestoneTitle. | | `myReactionEmoji` | [`String`](#string) | Filter by your reaction emoji. | | `not` | [`MergeRequestsResolverNegatedParams`](#mergerequestsresolvernegatedparams) | List of negated arguments. Warning: this argument is experimental and a subject to change in future. | +| `or` | [`UnionedMergeRequestFilterInput`](#unionedmergerequestfilterinput) | List of arguments with inclusive OR. | | `projectId` | [`ProjectID`](#projectid) | The global ID of the project the authored merge requests should be in. Incompatible with projectPath. | | `projectPath` | [`String`](#string) | The full-path of the project the authored merge requests should be in. Incompatible with projectId. | | `releaseTag` | [`String`](#string) | Filter by release tag. | @@ -19712,6 +19713,7 @@ four standard [pagination arguments](#pagination-arguments): | `approvedBy` | [`[String!]`](#string) | Usernames of the approvers. | | `approver` | [`[String!]`](#string) | Usernames of possible approvers. | | `assigneeUsername` | [`String`](#string) | Username of the assignee. | +| `assigneeUsernames` | [`[String!]`](#string) | Usernames of users assigned to the merge request. | | `assigneeWildcardId` | [`AssigneeWildcardId`](#assigneewildcardid) | Filter by assignee presence. Incompatible with assigneeUsernames and assigneeUsername. | | `blobPath` {{< icon name="warning-solid" >}} | [`String`](#string) | **Introduced** in GitLab 17.7. **Status**: Experiment. Path of the blob changed in merge request. Requires state, targetBranches, and createdAfter arguments. Available only when the feature flag `filter_blob_path` is enabled. | | `createdAfter` | [`Time`](#time) | Merge requests created after the timestamp. | @@ -19734,6 +19736,7 @@ four standard [pagination arguments](#pagination-arguments): | `milestoneWildcardId` | [`MilestoneWildcardId`](#milestonewildcardid) | Filter issues by milestone ID wildcard. Incompatible with milestoneTitle. | | `myReactionEmoji` | [`String`](#string) | Filter by your reaction emoji. | | `not` | [`MergeRequestsResolverNegatedParams`](#mergerequestsresolvernegatedparams) | List of negated arguments. Warning: this argument is experimental and a subject to change in future. | +| `or` | [`UnionedMergeRequestFilterInput`](#unionedmergerequestfilterinput) | List of arguments with inclusive OR. | | `projectId` | [`ProjectID`](#projectid) | The global ID of the project the authored merge requests should be in. Incompatible with projectPath. | | `projectPath` | [`String`](#string) | The full-path of the project the authored merge requests should be in. Incompatible with projectId. | | `releaseTag` | [`String`](#string) | Filter by release tag. | @@ -19827,6 +19830,7 @@ four standard [pagination arguments](#pagination-arguments): | `approvedBy` | [`[String!]`](#string) | Usernames of the approvers. | | `approver` | [`[String!]`](#string) | Usernames of possible approvers. | | `assigneeUsername` | [`String`](#string) | Username of the assignee. | +| `assigneeUsernames` | [`[String!]`](#string) | Usernames of users assigned to the merge request. | | `assigneeWildcardId` | [`AssigneeWildcardId`](#assigneewildcardid) | Filter by assignee presence. Incompatible with assigneeUsernames and assigneeUsername. | | `authorUsername` | [`String`](#string) | Username of the author. | | `blobPath` {{< icon name="warning-solid" >}} | [`String`](#string) | **Introduced** in GitLab 17.7. **Status**: Experiment. Path of the blob changed in merge request. Requires state, targetBranches, and createdAfter arguments. Available only when the feature flag `filter_blob_path` is enabled. | @@ -19850,6 +19854,7 @@ four standard [pagination arguments](#pagination-arguments): | `milestoneWildcardId` | [`MilestoneWildcardId`](#milestonewildcardid) | Filter issues by milestone ID wildcard. Incompatible with milestoneTitle. | | `myReactionEmoji` | [`String`](#string) | Filter by your reaction emoji. | | `not` | [`MergeRequestsResolverNegatedParams`](#mergerequestsresolvernegatedparams) | List of negated arguments. Warning: this argument is experimental and a subject to change in future. | +| `or` | [`UnionedMergeRequestFilterInput`](#unionedmergerequestfilterinput) | List of arguments with inclusive OR. | | `projectId` | [`ProjectID`](#projectid) | The global ID of the project the authored merge requests should be in. Incompatible with projectPath. | | `projectPath` | [`String`](#string) | The full-path of the project the authored merge requests should be in. Incompatible with projectId. | | `releaseTag` | [`String`](#string) | Filter by release tag. | @@ -20691,6 +20696,7 @@ four standard [pagination arguments](#pagination-arguments): | `milestoneWildcardId` | [`MilestoneWildcardId`](#milestonewildcardid) | Filter issues by milestone ID wildcard. Incompatible with milestoneTitle. | | `myReactionEmoji` | [`String`](#string) | Filter by your reaction emoji. | | `not` | [`MergeRequestsResolverNegatedParams`](#mergerequestsresolvernegatedparams) | List of negated arguments. Warning: this argument is experimental and a subject to change in future. | +| `or` | [`UnionedMergeRequestFilterInput`](#unionedmergerequestfilterinput) | List of arguments with inclusive OR. | | `projectId` | [`ProjectID`](#projectid) | The global ID of the project the authored merge requests should be in. Incompatible with projectPath. | | `projectPath` | [`String`](#string) | The full-path of the project the authored merge requests should be in. Incompatible with projectId. | | `releaseTag` | [`String`](#string) | Filter by release tag. | @@ -20725,6 +20731,7 @@ four standard [pagination arguments](#pagination-arguments): | `approvedBy` | [`[String!]`](#string) | Usernames of the approvers. | | `approver` | [`[String!]`](#string) | Usernames of possible approvers. | | `assigneeUsername` | [`String`](#string) | Username of the assignee. | +| `assigneeUsernames` | [`[String!]`](#string) | Usernames of users assigned to the merge request. | | `assigneeWildcardId` | [`AssigneeWildcardId`](#assigneewildcardid) | Filter by assignee presence. Incompatible with assigneeUsernames and assigneeUsername. | | `blobPath` {{< icon name="warning-solid" >}} | [`String`](#string) | **Introduced** in GitLab 17.7. **Status**: Experiment. Path of the blob changed in merge request. Requires state, targetBranches, and createdAfter arguments. Available only when the feature flag `filter_blob_path` is enabled. | | `createdAfter` | [`Time`](#time) | Merge requests created after the timestamp. | @@ -20747,6 +20754,7 @@ four standard [pagination arguments](#pagination-arguments): | `milestoneWildcardId` | [`MilestoneWildcardId`](#milestonewildcardid) | Filter issues by milestone ID wildcard. Incompatible with milestoneTitle. | | `myReactionEmoji` | [`String`](#string) | Filter by your reaction emoji. | | `not` | [`MergeRequestsResolverNegatedParams`](#mergerequestsresolvernegatedparams) | List of negated arguments. Warning: this argument is experimental and a subject to change in future. | +| `or` | [`UnionedMergeRequestFilterInput`](#unionedmergerequestfilterinput) | List of arguments with inclusive OR. | | `projectId` | [`ProjectID`](#projectid) | The global ID of the project the authored merge requests should be in. Incompatible with projectPath. | | `projectPath` | [`String`](#string) | The full-path of the project the authored merge requests should be in. Incompatible with projectId. | | `releaseTag` | [`String`](#string) | Filter by release tag. | @@ -20852,6 +20860,7 @@ four standard [pagination arguments](#pagination-arguments): | `approvedBy` | [`[String!]`](#string) | Usernames of the approvers. | | `approver` | [`[String!]`](#string) | Usernames of possible approvers. | | `assigneeUsername` | [`String`](#string) | Username of the assignee. | +| `assigneeUsernames` | [`[String!]`](#string) | Usernames of users assigned to the merge request. | | `assigneeWildcardId` | [`AssigneeWildcardId`](#assigneewildcardid) | Filter by assignee presence. Incompatible with assigneeUsernames and assigneeUsername. | | `authorUsername` | [`String`](#string) | Username of the author. | | `blobPath` {{< icon name="warning-solid" >}} | [`String`](#string) | **Introduced** in GitLab 17.7. **Status**: Experiment. Path of the blob changed in merge request. Requires state, targetBranches, and createdAfter arguments. Available only when the feature flag `filter_blob_path` is enabled. | @@ -20875,6 +20884,7 @@ four standard [pagination arguments](#pagination-arguments): | `milestoneWildcardId` | [`MilestoneWildcardId`](#milestonewildcardid) | Filter issues by milestone ID wildcard. Incompatible with milestoneTitle. | | `myReactionEmoji` | [`String`](#string) | Filter by your reaction emoji. | | `not` | [`MergeRequestsResolverNegatedParams`](#mergerequestsresolvernegatedparams) | List of negated arguments. Warning: this argument is experimental and a subject to change in future. | +| `or` | [`UnionedMergeRequestFilterInput`](#unionedmergerequestfilterinput) | List of arguments with inclusive OR. | | `projectId` | [`ProjectID`](#projectid) | The global ID of the project the authored merge requests should be in. Incompatible with projectPath. | | `projectPath` | [`String`](#string) | The full-path of the project the authored merge requests should be in. Incompatible with projectId. | | `releaseTag` | [`String`](#string) | Filter by release tag. | @@ -23388,6 +23398,7 @@ four standard [pagination arguments](#pagination-arguments): | `milestoneWildcardId` | [`MilestoneWildcardId`](#milestonewildcardid) | Filter issues by milestone ID wildcard. Incompatible with milestoneTitle. | | `myReactionEmoji` | [`String`](#string) | Filter by your reaction emoji. | | `not` | [`MergeRequestsResolverNegatedParams`](#mergerequestsresolvernegatedparams) | List of negated arguments. Warning: this argument is experimental and a subject to change in future. | +| `or` | [`UnionedMergeRequestFilterInput`](#unionedmergerequestfilterinput) | List of arguments with inclusive OR. | | `projectId` | [`ProjectID`](#projectid) | The global ID of the project the authored merge requests should be in. Incompatible with projectPath. | | `projectPath` | [`String`](#string) | The full-path of the project the authored merge requests should be in. Incompatible with projectId. | | `releaseTag` | [`String`](#string) | Filter by release tag. | @@ -23448,6 +23459,7 @@ four standard [pagination arguments](#pagination-arguments): | `milestoneWildcardId` | [`MilestoneWildcardId`](#milestonewildcardid) | Filter issues by milestone ID wildcard. Incompatible with milestoneTitle. | | `myReactionEmoji` | [`String`](#string) | Filter by your reaction emoji. | | `not` | [`MergeRequestsResolverNegatedParams`](#mergerequestsresolvernegatedparams) | List of negated arguments. Warning: this argument is experimental and a subject to change in future. | +| `or` | [`UnionedMergeRequestFilterInput`](#unionedmergerequestfilterinput) | List of arguments with inclusive OR. | | `projectId` | [`ProjectID`](#projectid) | The global ID of the project the authored merge requests should be in. Incompatible with projectPath. | | `projectPath` | [`String`](#string) | The full-path of the project the authored merge requests should be in. Incompatible with projectId. | | `releaseTag` | [`String`](#string) | Filter by release tag. | @@ -23481,6 +23493,7 @@ four standard [pagination arguments](#pagination-arguments): | `approvedBy` | [`[String!]`](#string) | Usernames of the approvers. | | `approver` | [`[String!]`](#string) | Usernames of possible approvers. | | `assigneeUsername` | [`String`](#string) | Username of the assignee. | +| `assigneeUsernames` | [`[String!]`](#string) | Usernames of users assigned to the merge request. | | `assigneeWildcardId` | [`AssigneeWildcardId`](#assigneewildcardid) | Filter by assignee presence. Incompatible with assigneeUsernames and assigneeUsername. | | `blobPath` {{< icon name="warning-solid" >}} | [`String`](#string) | **Introduced** in GitLab 17.7. **Status**: Experiment. Path of the blob changed in merge request. Requires state, targetBranches, and createdAfter arguments. Available only when the feature flag `filter_blob_path` is enabled. | | `createdAfter` | [`Time`](#time) | Merge requests created after the timestamp. | @@ -23503,6 +23516,7 @@ four standard [pagination arguments](#pagination-arguments): | `milestoneWildcardId` | [`MilestoneWildcardId`](#milestonewildcardid) | Filter issues by milestone ID wildcard. Incompatible with milestoneTitle. | | `myReactionEmoji` | [`String`](#string) | Filter by your reaction emoji. | | `not` | [`MergeRequestsResolverNegatedParams`](#mergerequestsresolvernegatedparams) | List of negated arguments. Warning: this argument is experimental and a subject to change in future. | +| `or` | [`UnionedMergeRequestFilterInput`](#unionedmergerequestfilterinput) | List of arguments with inclusive OR. | | `projectId` | [`ProjectID`](#projectid) | The global ID of the project the authored merge requests should be in. Incompatible with projectPath. | | `projectPath` | [`String`](#string) | The full-path of the project the authored merge requests should be in. Incompatible with projectId. | | `releaseTag` | [`String`](#string) | Filter by release tag. | @@ -23596,6 +23610,7 @@ four standard [pagination arguments](#pagination-arguments): | `approvedBy` | [`[String!]`](#string) | Usernames of the approvers. | | `approver` | [`[String!]`](#string) | Usernames of possible approvers. | | `assigneeUsername` | [`String`](#string) | Username of the assignee. | +| `assigneeUsernames` | [`[String!]`](#string) | Usernames of users assigned to the merge request. | | `assigneeWildcardId` | [`AssigneeWildcardId`](#assigneewildcardid) | Filter by assignee presence. Incompatible with assigneeUsernames and assigneeUsername. | | `authorUsername` | [`String`](#string) | Username of the author. | | `blobPath` {{< icon name="warning-solid" >}} | [`String`](#string) | **Introduced** in GitLab 17.7. **Status**: Experiment. Path of the blob changed in merge request. Requires state, targetBranches, and createdAfter arguments. Available only when the feature flag `filter_blob_path` is enabled. | @@ -23619,6 +23634,7 @@ four standard [pagination arguments](#pagination-arguments): | `milestoneWildcardId` | [`MilestoneWildcardId`](#milestonewildcardid) | Filter issues by milestone ID wildcard. Incompatible with milestoneTitle. | | `myReactionEmoji` | [`String`](#string) | Filter by your reaction emoji. | | `not` | [`MergeRequestsResolverNegatedParams`](#mergerequestsresolvernegatedparams) | List of negated arguments. Warning: this argument is experimental and a subject to change in future. | +| `or` | [`UnionedMergeRequestFilterInput`](#unionedmergerequestfilterinput) | List of arguments with inclusive OR. | | `projectId` | [`ProjectID`](#projectid) | The global ID of the project the authored merge requests should be in. Incompatible with projectPath. | | `projectPath` | [`String`](#string) | The full-path of the project the authored merge requests should be in. Incompatible with projectId. | | `releaseTag` | [`String`](#string) | Filter by release tag. | @@ -27309,6 +27325,7 @@ four standard [pagination arguments](#pagination-arguments): | `approvedBy` | [`[String!]`](#string) | Usernames of the approvers. | | `approver` | [`[String!]`](#string) | Usernames of possible approvers. | | `assigneeUsername` | [`String`](#string) | Username of the assignee. | +| `assigneeUsernames` | [`[String!]`](#string) | Usernames of users assigned to the merge request. | | `assigneeWildcardId` | [`AssigneeWildcardId`](#assigneewildcardid) | Filter by assignee presence. Incompatible with assigneeUsernames and assigneeUsername. | | `authorUsername` | [`String`](#string) | Username of the author. | | `blobPath` {{< icon name="warning-solid" >}} | [`String`](#string) | **Introduced** in GitLab 17.7. **Status**: Experiment. Path of the blob changed in merge request. Requires state, targetBranches, and createdAfter arguments. Available only when the feature flag `filter_blob_path` is enabled. | @@ -27332,6 +27349,7 @@ four standard [pagination arguments](#pagination-arguments): | `milestoneWildcardId` | [`MilestoneWildcardId`](#milestonewildcardid) | Filter issues by milestone ID wildcard. Incompatible with milestoneTitle. | | `myReactionEmoji` | [`String`](#string) | Filter by your reaction emoji. | | `not` | [`MergeRequestsResolverNegatedParams`](#mergerequestsresolvernegatedparams) | List of negated arguments. Warning: this argument is experimental and a subject to change in future. | +| `or` | [`UnionedMergeRequestFilterInput`](#unionedmergerequestfilterinput) | List of arguments with inclusive OR. | | `releaseTag` | [`String`](#string) | Filter by release tag. | | `reviewState` {{< icon name="warning-solid" >}} | [`MergeRequestReviewState`](#mergerequestreviewstate) | **Introduced** in GitLab 17.0. **Status**: Experiment. Reviewer state of the merge request. | | `reviewStates` {{< icon name="warning-solid" >}} | [`[MergeRequestReviewState!]`](#mergerequestreviewstate) | **Introduced** in GitLab 17.0. **Status**: Experiment. Reviewer states of the merge request. | @@ -29667,6 +29685,7 @@ four standard [pagination arguments](#pagination-arguments): | `milestoneWildcardId` | [`MilestoneWildcardId`](#milestonewildcardid) | Filter issues by milestone ID wildcard. Incompatible with milestoneTitle. | | `myReactionEmoji` | [`String`](#string) | Filter by your reaction emoji. | | `not` | [`MergeRequestsResolverNegatedParams`](#mergerequestsresolvernegatedparams) | List of negated arguments. Warning: this argument is experimental and a subject to change in future. | +| `or` | [`UnionedMergeRequestFilterInput`](#unionedmergerequestfilterinput) | List of arguments with inclusive OR. | | `projectId` | [`ProjectID`](#projectid) | The global ID of the project the authored merge requests should be in. Incompatible with projectPath. | | `projectPath` | [`String`](#string) | The full-path of the project the authored merge requests should be in. Incompatible with projectId. | | `releaseTag` | [`String`](#string) | Filter by release tag. | @@ -29701,6 +29720,7 @@ four standard [pagination arguments](#pagination-arguments): | `approvedBy` | [`[String!]`](#string) | Usernames of the approvers. | | `approver` | [`[String!]`](#string) | Usernames of possible approvers. | | `assigneeUsername` | [`String`](#string) | Username of the assignee. | +| `assigneeUsernames` | [`[String!]`](#string) | Usernames of users assigned to the merge request. | | `assigneeWildcardId` | [`AssigneeWildcardId`](#assigneewildcardid) | Filter by assignee presence. Incompatible with assigneeUsernames and assigneeUsername. | | `blobPath` {{< icon name="warning-solid" >}} | [`String`](#string) | **Introduced** in GitLab 17.7. **Status**: Experiment. Path of the blob changed in merge request. Requires state, targetBranches, and createdAfter arguments. Available only when the feature flag `filter_blob_path` is enabled. | | `createdAfter` | [`Time`](#time) | Merge requests created after the timestamp. | @@ -29723,6 +29743,7 @@ four standard [pagination arguments](#pagination-arguments): | `milestoneWildcardId` | [`MilestoneWildcardId`](#milestonewildcardid) | Filter issues by milestone ID wildcard. Incompatible with milestoneTitle. | | `myReactionEmoji` | [`String`](#string) | Filter by your reaction emoji. | | `not` | [`MergeRequestsResolverNegatedParams`](#mergerequestsresolvernegatedparams) | List of negated arguments. Warning: this argument is experimental and a subject to change in future. | +| `or` | [`UnionedMergeRequestFilterInput`](#unionedmergerequestfilterinput) | List of arguments with inclusive OR. | | `projectId` | [`ProjectID`](#projectid) | The global ID of the project the authored merge requests should be in. Incompatible with projectPath. | | `projectPath` | [`String`](#string) | The full-path of the project the authored merge requests should be in. Incompatible with projectId. | | `releaseTag` | [`String`](#string) | Filter by release tag. | @@ -29816,6 +29837,7 @@ four standard [pagination arguments](#pagination-arguments): | `approvedBy` | [`[String!]`](#string) | Usernames of the approvers. | | `approver` | [`[String!]`](#string) | Usernames of possible approvers. | | `assigneeUsername` | [`String`](#string) | Username of the assignee. | +| `assigneeUsernames` | [`[String!]`](#string) | Usernames of users assigned to the merge request. | | `assigneeWildcardId` | [`AssigneeWildcardId`](#assigneewildcardid) | Filter by assignee presence. Incompatible with assigneeUsernames and assigneeUsername. | | `authorUsername` | [`String`](#string) | Username of the author. | | `blobPath` {{< icon name="warning-solid" >}} | [`String`](#string) | **Introduced** in GitLab 17.7. **Status**: Experiment. Path of the blob changed in merge request. Requires state, targetBranches, and createdAfter arguments. Available only when the feature flag `filter_blob_path` is enabled. | @@ -29839,6 +29861,7 @@ four standard [pagination arguments](#pagination-arguments): | `milestoneWildcardId` | [`MilestoneWildcardId`](#milestonewildcardid) | Filter issues by milestone ID wildcard. Incompatible with milestoneTitle. | | `myReactionEmoji` | [`String`](#string) | Filter by your reaction emoji. | | `not` | [`MergeRequestsResolverNegatedParams`](#mergerequestsresolvernegatedparams) | List of negated arguments. Warning: this argument is experimental and a subject to change in future. | +| `or` | [`UnionedMergeRequestFilterInput`](#unionedmergerequestfilterinput) | List of arguments with inclusive OR. | | `projectId` | [`ProjectID`](#projectid) | The global ID of the project the authored merge requests should be in. Incompatible with projectPath. | | `projectPath` | [`String`](#string) | The full-path of the project the authored merge requests should be in. Incompatible with projectId. | | `releaseTag` | [`String`](#string) | Filter by release tag. | @@ -30079,6 +30102,7 @@ four standard [pagination arguments](#pagination-arguments): | `milestoneWildcardId` | [`MilestoneWildcardId`](#milestonewildcardid) | Filter issues by milestone ID wildcard. Incompatible with milestoneTitle. | | `myReactionEmoji` | [`String`](#string) | Filter by your reaction emoji. | | `not` | [`MergeRequestsResolverNegatedParams`](#mergerequestsresolvernegatedparams) | List of negated arguments. Warning: this argument is experimental and a subject to change in future. | +| `or` | [`UnionedMergeRequestFilterInput`](#unionedmergerequestfilterinput) | List of arguments with inclusive OR. | | `projectId` | [`ProjectID`](#projectid) | The global ID of the project the authored merge requests should be in. Incompatible with projectPath. | | `projectPath` | [`String`](#string) | The full-path of the project the authored merge requests should be in. Incompatible with projectId. | | `releaseTag` | [`String`](#string) | Filter by release tag. | @@ -30113,6 +30137,7 @@ four standard [pagination arguments](#pagination-arguments): | `approvedBy` | [`[String!]`](#string) | Usernames of the approvers. | | `approver` | [`[String!]`](#string) | Usernames of possible approvers. | | `assigneeUsername` | [`String`](#string) | Username of the assignee. | +| `assigneeUsernames` | [`[String!]`](#string) | Usernames of users assigned to the merge request. | | `assigneeWildcardId` | [`AssigneeWildcardId`](#assigneewildcardid) | Filter by assignee presence. Incompatible with assigneeUsernames and assigneeUsername. | | `blobPath` {{< icon name="warning-solid" >}} | [`String`](#string) | **Introduced** in GitLab 17.7. **Status**: Experiment. Path of the blob changed in merge request. Requires state, targetBranches, and createdAfter arguments. Available only when the feature flag `filter_blob_path` is enabled. | | `createdAfter` | [`Time`](#time) | Merge requests created after the timestamp. | @@ -30135,6 +30160,7 @@ four standard [pagination arguments](#pagination-arguments): | `milestoneWildcardId` | [`MilestoneWildcardId`](#milestonewildcardid) | Filter issues by milestone ID wildcard. Incompatible with milestoneTitle. | | `myReactionEmoji` | [`String`](#string) | Filter by your reaction emoji. | | `not` | [`MergeRequestsResolverNegatedParams`](#mergerequestsresolvernegatedparams) | List of negated arguments. Warning: this argument is experimental and a subject to change in future. | +| `or` | [`UnionedMergeRequestFilterInput`](#unionedmergerequestfilterinput) | List of arguments with inclusive OR. | | `projectId` | [`ProjectID`](#projectid) | The global ID of the project the authored merge requests should be in. Incompatible with projectPath. | | `projectPath` | [`String`](#string) | The full-path of the project the authored merge requests should be in. Incompatible with projectId. | | `releaseTag` | [`String`](#string) | Filter by release tag. | @@ -30228,6 +30254,7 @@ four standard [pagination arguments](#pagination-arguments): | `approvedBy` | [`[String!]`](#string) | Usernames of the approvers. | | `approver` | [`[String!]`](#string) | Usernames of possible approvers. | | `assigneeUsername` | [`String`](#string) | Username of the assignee. | +| `assigneeUsernames` | [`[String!]`](#string) | Usernames of users assigned to the merge request. | | `assigneeWildcardId` | [`AssigneeWildcardId`](#assigneewildcardid) | Filter by assignee presence. Incompatible with assigneeUsernames and assigneeUsername. | | `authorUsername` | [`String`](#string) | Username of the author. | | `blobPath` {{< icon name="warning-solid" >}} | [`String`](#string) | **Introduced** in GitLab 17.7. **Status**: Experiment. Path of the blob changed in merge request. Requires state, targetBranches, and createdAfter arguments. Available only when the feature flag `filter_blob_path` is enabled. | @@ -30251,6 +30278,7 @@ four standard [pagination arguments](#pagination-arguments): | `milestoneWildcardId` | [`MilestoneWildcardId`](#milestonewildcardid) | Filter issues by milestone ID wildcard. Incompatible with milestoneTitle. | | `myReactionEmoji` | [`String`](#string) | Filter by your reaction emoji. | | `not` | [`MergeRequestsResolverNegatedParams`](#mergerequestsresolvernegatedparams) | List of negated arguments. Warning: this argument is experimental and a subject to change in future. | +| `or` | [`UnionedMergeRequestFilterInput`](#unionedmergerequestfilterinput) | List of arguments with inclusive OR. | | `projectId` | [`ProjectID`](#projectid) | The global ID of the project the authored merge requests should be in. Incompatible with projectPath. | | `projectPath` | [`String`](#string) | The full-path of the project the authored merge requests should be in. Incompatible with projectId. | | `releaseTag` | [`String`](#string) | Filter by release tag. | @@ -30542,6 +30570,7 @@ four standard [pagination arguments](#pagination-arguments): | `milestoneWildcardId` | [`MilestoneWildcardId`](#milestonewildcardid) | Filter issues by milestone ID wildcard. Incompatible with milestoneTitle. | | `myReactionEmoji` | [`String`](#string) | Filter by your reaction emoji. | | `not` | [`MergeRequestsResolverNegatedParams`](#mergerequestsresolvernegatedparams) | List of negated arguments. Warning: this argument is experimental and a subject to change in future. | +| `or` | [`UnionedMergeRequestFilterInput`](#unionedmergerequestfilterinput) | List of arguments with inclusive OR. | | `projectId` | [`ProjectID`](#projectid) | The global ID of the project the authored merge requests should be in. Incompatible with projectPath. | | `projectPath` | [`String`](#string) | The full-path of the project the authored merge requests should be in. Incompatible with projectId. | | `releaseTag` | [`String`](#string) | Filter by release tag. | @@ -30576,6 +30605,7 @@ four standard [pagination arguments](#pagination-arguments): | `approvedBy` | [`[String!]`](#string) | Usernames of the approvers. | | `approver` | [`[String!]`](#string) | Usernames of possible approvers. | | `assigneeUsername` | [`String`](#string) | Username of the assignee. | +| `assigneeUsernames` | [`[String!]`](#string) | Usernames of users assigned to the merge request. | | `assigneeWildcardId` | [`AssigneeWildcardId`](#assigneewildcardid) | Filter by assignee presence. Incompatible with assigneeUsernames and assigneeUsername. | | `blobPath` {{< icon name="warning-solid" >}} | [`String`](#string) | **Introduced** in GitLab 17.7. **Status**: Experiment. Path of the blob changed in merge request. Requires state, targetBranches, and createdAfter arguments. Available only when the feature flag `filter_blob_path` is enabled. | | `createdAfter` | [`Time`](#time) | Merge requests created after the timestamp. | @@ -30598,6 +30628,7 @@ four standard [pagination arguments](#pagination-arguments): | `milestoneWildcardId` | [`MilestoneWildcardId`](#milestonewildcardid) | Filter issues by milestone ID wildcard. Incompatible with milestoneTitle. | | `myReactionEmoji` | [`String`](#string) | Filter by your reaction emoji. | | `not` | [`MergeRequestsResolverNegatedParams`](#mergerequestsresolvernegatedparams) | List of negated arguments. Warning: this argument is experimental and a subject to change in future. | +| `or` | [`UnionedMergeRequestFilterInput`](#unionedmergerequestfilterinput) | List of arguments with inclusive OR. | | `projectId` | [`ProjectID`](#projectid) | The global ID of the project the authored merge requests should be in. Incompatible with projectPath. | | `projectPath` | [`String`](#string) | The full-path of the project the authored merge requests should be in. Incompatible with projectId. | | `releaseTag` | [`String`](#string) | Filter by release tag. | @@ -30691,6 +30722,7 @@ four standard [pagination arguments](#pagination-arguments): | `approvedBy` | [`[String!]`](#string) | Usernames of the approvers. | | `approver` | [`[String!]`](#string) | Usernames of possible approvers. | | `assigneeUsername` | [`String`](#string) | Username of the assignee. | +| `assigneeUsernames` | [`[String!]`](#string) | Usernames of users assigned to the merge request. | | `assigneeWildcardId` | [`AssigneeWildcardId`](#assigneewildcardid) | Filter by assignee presence. Incompatible with assigneeUsernames and assigneeUsername. | | `authorUsername` | [`String`](#string) | Username of the author. | | `blobPath` {{< icon name="warning-solid" >}} | [`String`](#string) | **Introduced** in GitLab 17.7. **Status**: Experiment. Path of the blob changed in merge request. Requires state, targetBranches, and createdAfter arguments. Available only when the feature flag `filter_blob_path` is enabled. | @@ -30714,6 +30746,7 @@ four standard [pagination arguments](#pagination-arguments): | `milestoneWildcardId` | [`MilestoneWildcardId`](#milestonewildcardid) | Filter issues by milestone ID wildcard. Incompatible with milestoneTitle. | | `myReactionEmoji` | [`String`](#string) | Filter by your reaction emoji. | | `not` | [`MergeRequestsResolverNegatedParams`](#mergerequestsresolvernegatedparams) | List of negated arguments. Warning: this argument is experimental and a subject to change in future. | +| `or` | [`UnionedMergeRequestFilterInput`](#unionedmergerequestfilterinput) | List of arguments with inclusive OR. | | `projectId` | [`ProjectID`](#projectid) | The global ID of the project the authored merge requests should be in. Incompatible with projectPath. | | `projectPath` | [`String`](#string) | The full-path of the project the authored merge requests should be in. Incompatible with projectId. | | `releaseTag` | [`String`](#string) | Filter by release tag. | @@ -30973,6 +31006,7 @@ four standard [pagination arguments](#pagination-arguments): | `milestoneWildcardId` | [`MilestoneWildcardId`](#milestonewildcardid) | Filter issues by milestone ID wildcard. Incompatible with milestoneTitle. | | `myReactionEmoji` | [`String`](#string) | Filter by your reaction emoji. | | `not` | [`MergeRequestsResolverNegatedParams`](#mergerequestsresolvernegatedparams) | List of negated arguments. Warning: this argument is experimental and a subject to change in future. | +| `or` | [`UnionedMergeRequestFilterInput`](#unionedmergerequestfilterinput) | List of arguments with inclusive OR. | | `projectId` | [`ProjectID`](#projectid) | The global ID of the project the authored merge requests should be in. Incompatible with projectPath. | | `projectPath` | [`String`](#string) | The full-path of the project the authored merge requests should be in. Incompatible with projectId. | | `releaseTag` | [`String`](#string) | Filter by release tag. | @@ -31007,6 +31041,7 @@ four standard [pagination arguments](#pagination-arguments): | `approvedBy` | [`[String!]`](#string) | Usernames of the approvers. | | `approver` | [`[String!]`](#string) | Usernames of possible approvers. | | `assigneeUsername` | [`String`](#string) | Username of the assignee. | +| `assigneeUsernames` | [`[String!]`](#string) | Usernames of users assigned to the merge request. | | `assigneeWildcardId` | [`AssigneeWildcardId`](#assigneewildcardid) | Filter by assignee presence. Incompatible with assigneeUsernames and assigneeUsername. | | `blobPath` {{< icon name="warning-solid" >}} | [`String`](#string) | **Introduced** in GitLab 17.7. **Status**: Experiment. Path of the blob changed in merge request. Requires state, targetBranches, and createdAfter arguments. Available only when the feature flag `filter_blob_path` is enabled. | | `createdAfter` | [`Time`](#time) | Merge requests created after the timestamp. | @@ -31029,6 +31064,7 @@ four standard [pagination arguments](#pagination-arguments): | `milestoneWildcardId` | [`MilestoneWildcardId`](#milestonewildcardid) | Filter issues by milestone ID wildcard. Incompatible with milestoneTitle. | | `myReactionEmoji` | [`String`](#string) | Filter by your reaction emoji. | | `not` | [`MergeRequestsResolverNegatedParams`](#mergerequestsresolvernegatedparams) | List of negated arguments. Warning: this argument is experimental and a subject to change in future. | +| `or` | [`UnionedMergeRequestFilterInput`](#unionedmergerequestfilterinput) | List of arguments with inclusive OR. | | `projectId` | [`ProjectID`](#projectid) | The global ID of the project the authored merge requests should be in. Incompatible with projectPath. | | `projectPath` | [`String`](#string) | The full-path of the project the authored merge requests should be in. Incompatible with projectId. | | `releaseTag` | [`String`](#string) | Filter by release tag. | @@ -31122,6 +31158,7 @@ four standard [pagination arguments](#pagination-arguments): | `approvedBy` | [`[String!]`](#string) | Usernames of the approvers. | | `approver` | [`[String!]`](#string) | Usernames of possible approvers. | | `assigneeUsername` | [`String`](#string) | Username of the assignee. | +| `assigneeUsernames` | [`[String!]`](#string) | Usernames of users assigned to the merge request. | | `assigneeWildcardId` | [`AssigneeWildcardId`](#assigneewildcardid) | Filter by assignee presence. Incompatible with assigneeUsernames and assigneeUsername. | | `authorUsername` | [`String`](#string) | Username of the author. | | `blobPath` {{< icon name="warning-solid" >}} | [`String`](#string) | **Introduced** in GitLab 17.7. **Status**: Experiment. Path of the blob changed in merge request. Requires state, targetBranches, and createdAfter arguments. Available only when the feature flag `filter_blob_path` is enabled. | @@ -31145,6 +31182,7 @@ four standard [pagination arguments](#pagination-arguments): | `milestoneWildcardId` | [`MilestoneWildcardId`](#milestonewildcardid) | Filter issues by milestone ID wildcard. Incompatible with milestoneTitle. | | `myReactionEmoji` | [`String`](#string) | Filter by your reaction emoji. | | `not` | [`MergeRequestsResolverNegatedParams`](#mergerequestsresolvernegatedparams) | List of negated arguments. Warning: this argument is experimental and a subject to change in future. | +| `or` | [`UnionedMergeRequestFilterInput`](#unionedmergerequestfilterinput) | List of arguments with inclusive OR. | | `projectId` | [`ProjectID`](#projectid) | The global ID of the project the authored merge requests should be in. Incompatible with projectPath. | | `projectPath` | [`String`](#string) | The full-path of the project the authored merge requests should be in. Incompatible with projectId. | | `releaseTag` | [`String`](#string) | Filter by release tag. | @@ -34654,6 +34692,7 @@ four standard [pagination arguments](#pagination-arguments): | `approvedBy` | [`[String!]`](#string) | Usernames of the approvers. | | `approver` | [`[String!]`](#string) | Usernames of possible approvers. | | `assigneeUsername` | [`String`](#string) | Username of the assignee. | +| `assigneeUsernames` | [`[String!]`](#string) | Usernames of users assigned to the merge request. | | `assigneeWildcardId` | [`AssigneeWildcardId`](#assigneewildcardid) | Filter by assignee presence. Incompatible with assigneeUsernames and assigneeUsername. | | `authorUsername` | [`String`](#string) | Username of the author. | | `blobPath` {{< icon name="warning-solid" >}} | [`String`](#string) | **Introduced** in GitLab 17.7. **Status**: Experiment. Path of the blob changed in merge request. Requires state, targetBranches, and createdAfter arguments. Available only when the feature flag `filter_blob_path` is enabled. | @@ -34675,6 +34714,7 @@ four standard [pagination arguments](#pagination-arguments): | `milestoneWildcardId` | [`MilestoneWildcardId`](#milestonewildcardid) | Filter issues by milestone ID wildcard. Incompatible with milestoneTitle. | | `myReactionEmoji` | [`String`](#string) | Filter by your reaction emoji. | | `not` | [`MergeRequestsResolverNegatedParams`](#mergerequestsresolvernegatedparams) | List of negated arguments. Warning: this argument is experimental and a subject to change in future. | +| `or` | [`UnionedMergeRequestFilterInput`](#unionedmergerequestfilterinput) | List of arguments with inclusive OR. | | `releaseTag` | [`String`](#string) | Filter by release tag. | | `reviewState` {{< icon name="warning-solid" >}} | [`MergeRequestReviewState`](#mergerequestreviewstate) | **Introduced** in GitLab 17.0. **Status**: Experiment. Reviewer state of the merge request. | | `reviewStates` {{< icon name="warning-solid" >}} | [`[MergeRequestReviewState!]`](#mergerequestreviewstate) | **Introduced** in GitLab 17.0. **Status**: Experiment. Reviewer states of the merge request. | @@ -38126,6 +38166,7 @@ four standard [pagination arguments](#pagination-arguments): | `milestoneWildcardId` | [`MilestoneWildcardId`](#milestonewildcardid) | Filter issues by milestone ID wildcard. Incompatible with milestoneTitle. | | `myReactionEmoji` | [`String`](#string) | Filter by your reaction emoji. | | `not` | [`MergeRequestsResolverNegatedParams`](#mergerequestsresolvernegatedparams) | List of negated arguments. Warning: this argument is experimental and a subject to change in future. | +| `or` | [`UnionedMergeRequestFilterInput`](#unionedmergerequestfilterinput) | List of arguments with inclusive OR. | | `projectId` | [`ProjectID`](#projectid) | The global ID of the project the authored merge requests should be in. Incompatible with projectPath. | | `projectPath` | [`String`](#string) | The full-path of the project the authored merge requests should be in. Incompatible with projectId. | | `releaseTag` | [`String`](#string) | Filter by release tag. | @@ -38160,6 +38201,7 @@ four standard [pagination arguments](#pagination-arguments): | `approvedBy` | [`[String!]`](#string) | Usernames of the approvers. | | `approver` | [`[String!]`](#string) | Usernames of possible approvers. | | `assigneeUsername` | [`String`](#string) | Username of the assignee. | +| `assigneeUsernames` | [`[String!]`](#string) | Usernames of users assigned to the merge request. | | `assigneeWildcardId` | [`AssigneeWildcardId`](#assigneewildcardid) | Filter by assignee presence. Incompatible with assigneeUsernames and assigneeUsername. | | `blobPath` {{< icon name="warning-solid" >}} | [`String`](#string) | **Introduced** in GitLab 17.7. **Status**: Experiment. Path of the blob changed in merge request. Requires state, targetBranches, and createdAfter arguments. Available only when the feature flag `filter_blob_path` is enabled. | | `createdAfter` | [`Time`](#time) | Merge requests created after the timestamp. | @@ -38182,6 +38224,7 @@ four standard [pagination arguments](#pagination-arguments): | `milestoneWildcardId` | [`MilestoneWildcardId`](#milestonewildcardid) | Filter issues by milestone ID wildcard. Incompatible with milestoneTitle. | | `myReactionEmoji` | [`String`](#string) | Filter by your reaction emoji. | | `not` | [`MergeRequestsResolverNegatedParams`](#mergerequestsresolvernegatedparams) | List of negated arguments. Warning: this argument is experimental and a subject to change in future. | +| `or` | [`UnionedMergeRequestFilterInput`](#unionedmergerequestfilterinput) | List of arguments with inclusive OR. | | `projectId` | [`ProjectID`](#projectid) | The global ID of the project the authored merge requests should be in. Incompatible with projectPath. | | `projectPath` | [`String`](#string) | The full-path of the project the authored merge requests should be in. Incompatible with projectId. | | `releaseTag` | [`String`](#string) | Filter by release tag. | @@ -38275,6 +38318,7 @@ four standard [pagination arguments](#pagination-arguments): | `approvedBy` | [`[String!]`](#string) | Usernames of the approvers. | | `approver` | [`[String!]`](#string) | Usernames of possible approvers. | | `assigneeUsername` | [`String`](#string) | Username of the assignee. | +| `assigneeUsernames` | [`[String!]`](#string) | Usernames of users assigned to the merge request. | | `assigneeWildcardId` | [`AssigneeWildcardId`](#assigneewildcardid) | Filter by assignee presence. Incompatible with assigneeUsernames and assigneeUsername. | | `authorUsername` | [`String`](#string) | Username of the author. | | `blobPath` {{< icon name="warning-solid" >}} | [`String`](#string) | **Introduced** in GitLab 17.7. **Status**: Experiment. Path of the blob changed in merge request. Requires state, targetBranches, and createdAfter arguments. Available only when the feature flag `filter_blob_path` is enabled. | @@ -38298,6 +38342,7 @@ four standard [pagination arguments](#pagination-arguments): | `milestoneWildcardId` | [`MilestoneWildcardId`](#milestonewildcardid) | Filter issues by milestone ID wildcard. Incompatible with milestoneTitle. | | `myReactionEmoji` | [`String`](#string) | Filter by your reaction emoji. | | `not` | [`MergeRequestsResolverNegatedParams`](#mergerequestsresolvernegatedparams) | List of negated arguments. Warning: this argument is experimental and a subject to change in future. | +| `or` | [`UnionedMergeRequestFilterInput`](#unionedmergerequestfilterinput) | List of arguments with inclusive OR. | | `projectId` | [`ProjectID`](#projectid) | The global ID of the project the authored merge requests should be in. Incompatible with projectPath. | | `projectPath` | [`String`](#string) | The full-path of the project the authored merge requests should be in. Incompatible with projectId. | | `releaseTag` | [`String`](#string) | Filter by release tag. | @@ -46143,6 +46188,7 @@ four standard [pagination arguments](#pagination-arguments): | `milestoneWildcardId` | [`MilestoneWildcardId`](#milestonewildcardid) | Filter issues by milestone ID wildcard. Incompatible with milestoneTitle. | | `myReactionEmoji` | [`String`](#string) | Filter by your reaction emoji. | | `not` | [`MergeRequestsResolverNegatedParams`](#mergerequestsresolvernegatedparams) | List of negated arguments. Warning: this argument is experimental and a subject to change in future. | +| `or` | [`UnionedMergeRequestFilterInput`](#unionedmergerequestfilterinput) | List of arguments with inclusive OR. | | `projectId` | [`ProjectID`](#projectid) | The global ID of the project the authored merge requests should be in. Incompatible with projectPath. | | `projectPath` | [`String`](#string) | The full-path of the project the authored merge requests should be in. Incompatible with projectId. | | `releaseTag` | [`String`](#string) | Filter by release tag. | @@ -46177,6 +46223,7 @@ four standard [pagination arguments](#pagination-arguments): | `approvedBy` | [`[String!]`](#string) | Usernames of the approvers. | | `approver` | [`[String!]`](#string) | Usernames of possible approvers. | | `assigneeUsername` | [`String`](#string) | Username of the assignee. | +| `assigneeUsernames` | [`[String!]`](#string) | Usernames of users assigned to the merge request. | | `assigneeWildcardId` | [`AssigneeWildcardId`](#assigneewildcardid) | Filter by assignee presence. Incompatible with assigneeUsernames and assigneeUsername. | | `blobPath` {{< icon name="warning-solid" >}} | [`String`](#string) | **Introduced** in GitLab 17.7. **Status**: Experiment. Path of the blob changed in merge request. Requires state, targetBranches, and createdAfter arguments. Available only when the feature flag `filter_blob_path` is enabled. | | `createdAfter` | [`Time`](#time) | Merge requests created after the timestamp. | @@ -46199,6 +46246,7 @@ four standard [pagination arguments](#pagination-arguments): | `milestoneWildcardId` | [`MilestoneWildcardId`](#milestonewildcardid) | Filter issues by milestone ID wildcard. Incompatible with milestoneTitle. | | `myReactionEmoji` | [`String`](#string) | Filter by your reaction emoji. | | `not` | [`MergeRequestsResolverNegatedParams`](#mergerequestsresolvernegatedparams) | List of negated arguments. Warning: this argument is experimental and a subject to change in future. | +| `or` | [`UnionedMergeRequestFilterInput`](#unionedmergerequestfilterinput) | List of arguments with inclusive OR. | | `projectId` | [`ProjectID`](#projectid) | The global ID of the project the authored merge requests should be in. Incompatible with projectPath. | | `projectPath` | [`String`](#string) | The full-path of the project the authored merge requests should be in. Incompatible with projectId. | | `releaseTag` | [`String`](#string) | Filter by release tag. | @@ -46292,6 +46340,7 @@ four standard [pagination arguments](#pagination-arguments): | `approvedBy` | [`[String!]`](#string) | Usernames of the approvers. | | `approver` | [`[String!]`](#string) | Usernames of possible approvers. | | `assigneeUsername` | [`String`](#string) | Username of the assignee. | +| `assigneeUsernames` | [`[String!]`](#string) | Usernames of users assigned to the merge request. | | `assigneeWildcardId` | [`AssigneeWildcardId`](#assigneewildcardid) | Filter by assignee presence. Incompatible with assigneeUsernames and assigneeUsername. | | `authorUsername` | [`String`](#string) | Username of the author. | | `blobPath` {{< icon name="warning-solid" >}} | [`String`](#string) | **Introduced** in GitLab 17.7. **Status**: Experiment. Path of the blob changed in merge request. Requires state, targetBranches, and createdAfter arguments. Available only when the feature flag `filter_blob_path` is enabled. | @@ -46315,6 +46364,7 @@ four standard [pagination arguments](#pagination-arguments): | `milestoneWildcardId` | [`MilestoneWildcardId`](#milestonewildcardid) | Filter issues by milestone ID wildcard. Incompatible with milestoneTitle. | | `myReactionEmoji` | [`String`](#string) | Filter by your reaction emoji. | | `not` | [`MergeRequestsResolverNegatedParams`](#mergerequestsresolvernegatedparams) | List of negated arguments. Warning: this argument is experimental and a subject to change in future. | +| `or` | [`UnionedMergeRequestFilterInput`](#unionedmergerequestfilterinput) | List of arguments with inclusive OR. | | `projectId` | [`ProjectID`](#projectid) | The global ID of the project the authored merge requests should be in. Incompatible with projectPath. | | `projectPath` | [`String`](#string) | The full-path of the project the authored merge requests should be in. Incompatible with projectId. | | `releaseTag` | [`String`](#string) | Filter by release tag. | @@ -47358,6 +47408,14 @@ Attributes for defining a tracking event. | `authorUsernames` | [`[String!]`](#string) | Filters issues that are authored by one of the given users. | | `labelNames` | [`[String!]`](#string) | Filters issues that have at least one of the given labels. | +### `UnionedMergeRequestFilterInput` + +#### Arguments + +| Name | Type | Description | +| ---- | ---- | ----------- | +| `assigneeUsernames` | [`[String!]`](#string) | Filters MRs that are assigned to at least one of the given users. | + ### `UnionedWorkItemFilterInput` #### Arguments diff --git a/doc/api/model_registry.md b/doc/api/model_registry.md index 8855b83ebef..0ccd7dfbcfd 100644 --- a/doc/api/model_registry.md +++ b/doc/api/model_registry.md @@ -20,12 +20,17 @@ Returns the file. GET /projects/:id/packages/ml_models/:model_version_id/files/(*path/):file_name ``` +For Versions, the `:model_version_id` is specified in the URL of the model version. +In the following example, the model version is `5`: `/namespace/project/-/ml/models/1/versions/5`. + +For Runs, the ID must prepended with `candidate:`. In the following example, the `:model_version_id` is `candidate:5`: `/namespace/project/-/ml/candidates/5`. + Parameters: | Attribute | Type | Required | Description | |--------------------|-------------------|----------|----------------------------------------------------------------------------------------| | `id` | integer or string | yes | The ID or [URL-encoded path of the project](rest/_index.md#namespaced-paths) | -| `model_version_id` | integer | yes | The model version ID for the file | +| `model_version_id` | integer or string | yes | The model version ID for the file | | `path` | string | yes | File directory path | | `filename` | string | yes | Filename | diff --git a/doc/topics/git/undo.md b/doc/topics/git/undo.md index b20cdef5a69..84b7bb66679 100644 --- a/doc/topics/git/undo.md +++ b/doc/topics/git/undo.md @@ -5,10 +5,15 @@ info: To determine the technical writer assigned to the Stage/Group associated w title: Revert and undo changes --- -Git provides options for undoing changes at any point in the +Working with Git involves experimentation and iteration. Mistakes happen during development, +and sometimes you need to reverse changes. Git gives you control over your code history +with features to undo changes at any point in your [Git workflow](get_started.md#understand-the-git-workflow). -The method to use depends on whether the changes are: +Recover from accidental commits, remove sensitive data, fix incorrect merges, and maintain a clean +repository history. When collaborating with others, preserve transparency with new revert +commits, or reset your work locally before sharing. The method to use depends on whether the +changes are: - Only on your local computer. - Stored remotely on a Git server such as GitLab.com. diff --git a/doc/update/deprecations.md b/doc/update/deprecations.md index a867696489c..d47f03bafcc 100644 --- a/doc/update/deprecations.md +++ b/doc/update/deprecations.md @@ -2003,11 +2003,18 @@ We will be transitioning to a new IID as a result of moving requirements to a [w
-We are moving the `agentk` container registry from [its project-specific registry](https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent/container_registry/1223205) to [the Cloud Native GitLab registry](https://gitlab.com/gitlab-org/build/CNG/container_registry/8241772). -From GitLab 18.0, the project-specific registry will not receive `agentk` updates. -If you mirror the `agentk` container to a local registry, you should change your mirror source to the CNG registry. +We are moving the `agentk` container registry from +[its project-specific registry](https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent/container_registry/1223205) +to [the Cloud Native GitLab (CNG) registry](https://gitlab.com/gitlab-org/build/CNG/container_registry/8241772). +From GitLab 18.0 onward, `agentk` images built in CNG will mirror into the project-specific registry. +The new image is equivalent to the old image, except the new image only supports `amd64` and `arm64` architectures. +It does not support the 32-bit `arm` architecture. +From GitLab 19.0 onward, the project-specific registry will not receive `agentk` updates. +If you mirror the `agentk` container to a local registry, you should change your mirror source to the +[CNG registry](https://gitlab.com/gitlab-org/build/CNG/container_registry/8241772). -If you use the official Helm charts, they will start deploying from the new location seamlessly. +If you use the official [GitLab Agent Helm chart](https://gitlab.com/gitlab-org/charts/gitlab-agent/), +the new `agentk` image will start deploying from the new location seamlessly in GitLab 18.0.
diff --git a/doc/user/packages/generic_packages/_index.md b/doc/user/packages/generic_packages/_index.md index 8ba6badb9e0..4aea3d5f84f 100644 --- a/doc/user/packages/generic_packages/_index.md +++ b/doc/user/packages/generic_packages/_index.md @@ -462,6 +462,7 @@ To download all files in a package, list the package contents using the GitLab A ```shell TOKEN="" PROJECT_ID="24" +PACKAGE_ID="1234" PACKAGE_NAME="my_package" PACKAGE_VERSION="1.0.0" OUTPUT_DIR="./downloaded_package" @@ -471,7 +472,7 @@ mkdir -p "$OUTPUT_DIR" # Get list of files in the package files=$(curl --location --header "PRIVATE-TOKEN: $TOKEN" \ - "https://gitlab.example.com/api/v4/projects/$PROJECT_ID/packages/generic/$PACKAGE_NAME/$PACKAGE_VERSION/files" \ + "https://gitlab.example.com/api/v4/projects/$PROJECT_ID/packages/$PACKAGE_ID/package_files" \ | jq -r '.[].file_name') # Download each file diff --git a/doc/user/project/ml/experiment_tracking/mlflow_client.md b/doc/user/project/ml/experiment_tracking/mlflow_client.md index 95c0925b6c7..b20dd54c52b 100644 --- a/doc/user/project/ml/experiment_tracking/mlflow_client.md +++ b/doc/user/project/ml/experiment_tracking/mlflow_client.md @@ -452,6 +452,7 @@ of the methods below are also supported with the same caveats. | `update_run` | Yes | 15.11 | | | `log_model` | Partial | 15.11 | (15.11) Saves the artifacts, but not the model data. `artifact_path` must be empty. | | `load_model` | Yes | 17.5 | | +| `download_artifacts` | Yes | 17.9 | | Other MLflowClient methods: @@ -471,5 +472,5 @@ Other MLflowClient methods: ## Known issues - The API GitLab supports is the one defined at MLflow version 2.7.1. -- MLflow client methods not listed above are not supported. +- MLflow client methods not listed in [supported methods](#supported-mlflow-client-methods-and-caveats) might still work but have not been tested. - During creation of experiments and runs, ExperimentTags are stored, even though they are not displayed. diff --git a/lib/gitlab/gon_helper.rb b/lib/gitlab/gon_helper.rb index fa1a34702b5..b2f344b6ed0 100644 --- a/lib/gitlab/gon_helper.rb +++ b/lib/gitlab/gon_helper.rb @@ -81,7 +81,6 @@ module Gitlab # Initialize gon.features with any flags that should be # made globally available to the frontend - push_frontend_feature_flag(:source_editor_toolbar) push_frontend_feature_flag(:vscode_web_ide, current_user) push_frontend_feature_flag(:ui_for_organizations, current_user) push_frontend_feature_flag(:organization_switching, current_user) diff --git a/locale/gitlab.pot b/locale/gitlab.pot index 85f9a47ff59..49945b910de 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -50688,6 +50688,9 @@ msgstr "" msgid "ScanExecutionPolicy|%{rules} every time a pipeline runs for %{scopes} %{branches} %{branchExceptions} %{agents} %{namespaces}" msgstr "" +msgid "ScanExecutionPolicy|%{strategySelector} pipeline file to run from %{projectSelector}" +msgstr "" + msgid "ScanExecutionPolicy|%{strategySelector}into the %{boldStart}.gitlab-ci.yml%{boldEnd} with the following %{boldStart}pipeline execution file%{boldEnd} from %{projectSelector}" msgstr "" @@ -50817,6 +50820,9 @@ msgstr "" msgid "ScanExecutionPolicy|The content of this pipeline execution YAML file is injected into the .gitlab-ci.yml file of the target project. Custom stages used in the pipeline execution YAML are ignored, unless they are defined in the `.gitlab-ci.yml` file of the target project. All GitLab CI/CD features are supported." msgstr "" +msgid "ScanExecutionPolicy|The content of this pipeline execution YAML file of the target project is run at the scheduled time. All GitLab CI/CD features are supported." +msgstr "" + msgid "ScanExecutionPolicy|The content of this pipeline execution YAML file overrides the .gitlab-ci.yml file of the target project. All GitLab CI/CD features are supported." msgstr "" @@ -52791,6 +52797,12 @@ msgstr "" msgid "SecurityOrchestration|Scan will automatically choose a runner to run on because there are no tags exist on runners. You can %{linkStart}create a new tag in settings%{linkEnd}." msgstr "" +msgid "SecurityOrchestration|Schedule a new" +msgstr "" + +msgid "SecurityOrchestration|Schedules" +msgstr "" + msgid "SecurityOrchestration|Scope" msgstr "" diff --git a/package.json b/package.json index 0dcaaefad97..2dca3b6aab2 100644 --- a/package.json +++ b/package.json @@ -63,7 +63,7 @@ "@gitlab/fonts": "^1.3.0", "@gitlab/query-language-rust": "0.4.0", "@gitlab/svgs": "3.123.0", - "@gitlab/ui": "108.8.1", + "@gitlab/ui": "108.9.0", "@gitlab/vue-router-vue3": "npm:vue-router@4.5.0", "@gitlab/vuex-vue3": "npm:vuex@4.1.0", "@gitlab/web-ide": "^0.0.1-dev-20250211142744", @@ -71,7 +71,7 @@ "@mattiasbuelens/web-streams-adapter": "^0.1.0", "@rails/actioncable": "7.0.807", "@rails/ujs": "7.0.807", - "@sentry/browser": "9.1.0", + "@sentry/browser": "9.3.0", "@snowplow/browser-plugin-client-hints": "^3.24.2", "@snowplow/browser-plugin-form-tracking": "^3.24.2", "@snowplow/browser-plugin-ga-cookies": "^3.24.2", diff --git a/spec/controllers/projects/settings/ci_cd_controller_spec.rb b/spec/controllers/projects/settings/ci_cd_controller_spec.rb index 167dfe58b10..069d388224c 100644 --- a/spec/controllers/projects/settings/ci_cd_controller_spec.rb +++ b/spec/controllers/projects/settings/ci_cd_controller_spec.rb @@ -222,7 +222,7 @@ RSpec.describe Projects::Settings::CiCdController, feature_category: :continuous subject expect(response).to have_gitlab_http_status(:found) - expect(flash[:toast]).to eq("Pipelines settings for '#{project.name}' were successfully updated.") + expect(flash[:toast]).to eq("Pipelines settings for '#{project.name}' were successfully updated.") end context 'when updating the auto_devops settings' do diff --git a/spec/controllers/projects_controller_spec.rb b/spec/controllers/projects_controller_spec.rb index ba9c681b010..d4ad55f4230 100644 --- a/spec/controllers/projects_controller_spec.rb +++ b/spec/controllers/projects_controller_spec.rb @@ -1116,7 +1116,7 @@ RSpec.describe ProjectsController, feature_category: :groups_and_projects do expect { Project.find(orig_id) }.to raise_error(ActiveRecord::RecordNotFound) expect(response).to have_gitlab_http_status(:found) - expect(flash[:toast]).to eq(format(_("Project '%{project_name}' is being deleted."), project_name: project.full_name)) + expect(flash[:toast]).to eq(format(_("Project '%{project_name}' is being deleted."), project_name: project.full_name)) expect(response).to redirect_to(dashboard_projects_path) end diff --git a/spec/features/projects/blobs/edit_spec.rb b/spec/features/projects/blobs/edit_spec.rb index c47143cde44..447599f6046 100644 --- a/spec/features/projects/blobs/edit_spec.rb +++ b/spec/features/projects/blobs/edit_spec.rb @@ -107,13 +107,7 @@ RSpec.describe 'Editing file blob', :js, feature_category: :source_code_manageme end end - it "has defined set of toolbar buttons when the flag is on" do - stub_feature_flags(source_editor_toolbar: true) - has_toolbar_buttons - end - - it "has defined set of toolbar buttons when the flag is off" do - stub_feature_flags(source_editor_toolbar: false) + it "has defined set of toolbar buttons" do has_toolbar_buttons end end diff --git a/spec/finders/merge_requests_finder_spec.rb b/spec/finders/merge_requests_finder_spec.rb index 736c14249b3..cff3b2ed71b 100644 --- a/spec/finders/merge_requests_finder_spec.rb +++ b/spec/finders/merge_requests_finder_spec.rb @@ -486,6 +486,50 @@ RSpec.describe MergeRequestsFinder, feature_category: :code_review_workflow do it_behaves_like 'any assignee filter' do let(:expected_issuables) { [merge_request1, merge_request2, merge_request3] } end + + context 'filtering by multiple assignee usernames' do + let(:merge_request1) { create(:merge_request, source_project: project1, source_branch: 'feature_x', target_branch: 'master') } + let(:merge_request2) { create(:merge_request, source_project: project1, source_branch: 'feature_y', target_branch: 'master') } + let(:user1) { create(:user) } + let(:user2) { create(:user) } + + before do + project1.add_developer(user1) + project1.add_developer(user2) + merge_request1.assignees = [user1] + merge_request2.assignees = [user2] + end + + it 'returns merge requests that are assigned to any of the users' do + params = { or: { assignee_usernames: [user1.username, user2.username] }, project_id: project1.id } + + merge_requests = described_class.new(user1, params).execute + + expect(merge_requests).to contain_exactly(merge_request1, merge_request2) + end + + it 'returns no merge requests when users do not have any assignments' do + unassigned_user = create(:user) + project1.add_developer(unassigned_user) + params = { or: { assignee_username: [unassigned_user.username] }, project_id: project1 } + + merge_requests = described_class.new(user, params).execute + + expect(merge_requests).to be_empty + end + + context 'when using NOT filter' do + it 'excludes merge requests assigned to any of the specified users' do + params = { not: { assignee_username: [user1.username, user2.username] }, project_id: project1.id } + merge_request3 = create(:merge_request, source_project: project1) + + merge_requests = described_class.new(user, params).execute + + expect(merge_requests).to contain_exactly(merge_request3) + expect(merge_requests).not_to include(merge_request1, merge_request2) + end + end + end end context 'reviewer filtering' do diff --git a/spec/graphql/mutations/release_asset_links/create_spec.rb b/spec/graphql/mutations/release_asset_links/create_spec.rb index ef57a6a01ef..c3efe023991 100644 --- a/spec/graphql/mutations/release_asset_links/create_spec.rb +++ b/spec/graphql/mutations/release_asset_links/create_spec.rb @@ -98,7 +98,7 @@ RSpec.describe Mutations::ReleaseAssetLinks::Create, feature_category: :release_ context "when the release doesn't exist" do let(:tag) { "nonexistent-tag" } - it_behaves_like 'returns errors-as-data', ['Release with tag "nonexistent-tag" was not found'] + it_behaves_like 'returns errors-as-data', ['Release with tag "nonexistent-tag" was not found'] end context 'when the URL is badly formatted' do diff --git a/spec/graphql/resolvers/merge_requests_resolver_spec.rb b/spec/graphql/resolvers/merge_requests_resolver_spec.rb index 7ea881dd99b..492df1f72de 100644 --- a/spec/graphql/resolvers/merge_requests_resolver_spec.rb +++ b/spec/graphql/resolvers/merge_requests_resolver_spec.rb @@ -750,6 +750,144 @@ RSpec.describe Resolvers::MergeRequestsResolver, feature_category: :code_review_ end end + describe 'private methods' do + # Create a test subclass that exposes private methods + let(:test_resolver_class) do + Class.new(Resolvers::MergeRequestsResolver) do + # Make private methods public + public :prepare_finder_params, :prepare_assignee_username_params, :rewrite_param_name + end + end + + let(:resolver) { test_resolver_class.allocate } + + before do + allow(resolver).to receive(:super).and_return({ base_param: 'value' }) + end + + describe '#prepare_finder_params' do + it 'converts :not to a hash' do + args = { not: { assignee_usernames: [current_user.username] } } + result = resolver.prepare_finder_params(args) + + expect(result[:not]).to eq({ assignee_username: [current_user.username] }) + end + + it 'converts :or to a hash' do + args = { or: { assignee_usernames: [current_user.username] } } + result = resolver.prepare_finder_params(args) + + expect(result[:or]).to eq({ assignee_username: [current_user.username] }) + end + + it 'returns the modified params' do + args = { assignee_usernames: ['user1'] } + result = resolver.prepare_finder_params(args) + + expect(result).to include(assignee_username: ['user1']) + expect(result).not_to include(:assignee_usernames) + end + + it 'handles nested conditions' do + args = { + or: { assignee_usernames: ['user1'] }, + not: { assignee_usernames: ['user2'] } + } + result = resolver.prepare_finder_params(args) + + expect(result[:or]).to include(assignee_username: ['user1']) + expect(result[:not]).to include(assignee_username: ['user2']) + end + end + + describe '#prepare_assignee_username_params' do + it 'rewrites assignee_usernames to assignee_username in the main args' do + args = { assignee_usernames: %w[user1 user2] } + resolver.prepare_assignee_username_params(args) + + expect(args[:assignee_username]).to eq(%w[user1 user2]) + expect(args[:assignee_usernames]).to be_nil + end + + it 'rewrites assignee_usernames in :or conditions' do + args = { or: { assignee_usernames: %w[user1 user2] } } + resolver.prepare_assignee_username_params(args) + + expect(args[:or][:assignee_username]).to eq(%w[user1 user2]) + expect(args[:or][:assignee_usernames]).to be_nil + end + + it 'rewrites assignee_usernames in :not conditions' do + args = { not: { assignee_usernames: %w[user1 user2] } } + resolver.prepare_assignee_username_params(args) + + expect(args[:not][:assignee_username]).to eq(%w[user1 user2]) + expect(args[:not][:assignee_usernames]).to be_nil + end + end + + describe '#rewrite_param_name' do + it 'rewrites parameter name when old_name exists and has a value' do + params = { old_name: 'value' } + resolver.rewrite_param_name(params, :old_name, :new_name) + + expect(params[:new_name]).to eq('value') + expect(params[:old_name]).to be_nil + end + + it 'does nothing when old_name exists but is empty' do + params = { old_name: '' } + resolver.rewrite_param_name(params, :old_name, :new_name) + + expect(params[:new_name]).to be_nil + expect(params[:old_name]).to eq('') + end + + it 'does nothing when old_name exists but is nil' do + params = { old_name: nil } + resolver.rewrite_param_name(params, :old_name, :new_name) + + expect(params[:new_name]).to be_nil + expect(params[:old_name]).to be_nil + end + + it 'does nothing when old_name does not exist' do + params = { different_name: 'value' } + resolver.rewrite_param_name(params, :old_name, :new_name) + + expect(params[:new_name]).to be_nil + expect(params[:different_name]).to eq('value') + end + + it 'handles nil params' do + expect { resolver.rewrite_param_name(nil, :old_name, :new_name) }.not_to raise_error + end + + it 'handles empty params' do + params = {} + resolver.rewrite_param_name(params, :old_name, :new_name) + + expect(params).to eq({}) + end + + it 'handles arrays as values' do + params = { old_name: %w[value1 value2] } + resolver.rewrite_param_name(params, :old_name, :new_name) + + expect(params[:new_name]).to eq(%w[value1 value2]) + expect(params[:old_name]).to be_nil + end + + it 'handles hashes as values' do + params = { old_name: { nested: 'value' } } + resolver.rewrite_param_name(params, :old_name, :new_name) + + expect(params[:new_name]).to eq({ nested: 'value' }) + expect(params[:old_name]).to be_nil + end + end + end + def resolve_mr_single(project, iid) resolve_mr(project, resolver: described_class.single, iid: iid.to_s) end diff --git a/spec/graphql/resolvers/project_merge_requests_resolver_spec.rb b/spec/graphql/resolvers/project_merge_requests_resolver_spec.rb index e39057ea1f8..afaaab0462e 100644 --- a/spec/graphql/resolvers/project_merge_requests_resolver_spec.rb +++ b/spec/graphql/resolvers/project_merge_requests_resolver_spec.rb @@ -113,7 +113,8 @@ RSpec.describe Resolvers::ProjectMergeRequestsResolver do it 'returns error when assignee username and wildcard id are used' do expect_graphql_error_to_be_created(GraphQL::Schema::Validator::ValidationFailedError, - 'Only one of [assigneeUsername, assigneeWildcardId] arguments is allowed at the same time.') do + 'Only one of [assigneeUsernames, assigneeUsername, assigneeWildcardId] ' \ + 'arguments is allowed at the same time.') do resolve_mr(project, assignee_username: current_user.username, assignee_wildcard_id: 'ANY') end end diff --git a/spec/graphql/types/merge_requests/unioned_merge_request_filter_input_type_spec.rb b/spec/graphql/types/merge_requests/unioned_merge_request_filter_input_type_spec.rb new file mode 100644 index 00000000000..d05466b4fe6 --- /dev/null +++ b/spec/graphql/types/merge_requests/unioned_merge_request_filter_input_type_spec.rb @@ -0,0 +1,33 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Types::MergeRequests::UnionedMergeRequestFilterInputType, feature_category: :code_review_workflow do + it 'has the correct graphql name' do + expect(described_class.graphql_name).to eq('UnionedMergeRequestFilterInput') + end + + describe 'arguments' do + subject(:arguments) { described_class.arguments } + + it 'defines assignee_usernames argument' do + expect(arguments).to include('assigneeUsernames') + end + + describe 'assignee_usernames argument' do + let(:argument) { subject['assigneeUsernames'] } + + it 'is not required' do + expect(argument.type.non_null?).to be false + end + + it 'is an array of strings' do + expect(argument.type).to be_a(GraphQL::Schema::List) + end + + it 'has the correct description' do + expect(argument.description).to eq('Filters MRs that are assigned to at least one of the given users.') + end + end + end +end diff --git a/spec/models/service_desk/custom_email_verification_spec.rb b/spec/models/service_desk/custom_email_verification_spec.rb index 2598eb06c8e..e7edf80205a 100644 --- a/spec/models/service_desk/custom_email_verification_spec.rb +++ b/spec/models/service_desk/custom_email_verification_spec.rb @@ -130,7 +130,7 @@ RSpec.describe ServiceDesk::CustomEmailVerification, feature_category: :service_ context 'when triggered_at is not set' do it 'returns nil' do subject.triggered_at = nil - expect(subject.accepted_until).to be nil + expect(subject.accepted_until).to be_nil end end end diff --git a/spec/models/snippet_spec.rb b/spec/models/snippet_spec.rb index 778b5146d3e..d0e92be0167 100644 --- a/spec/models/snippet_spec.rb +++ b/spec/models/snippet_spec.rb @@ -480,7 +480,7 @@ RSpec.describe Snippet, feature_category: :source_code_management do created_at_without_ms # to_s truncates ms of the argument ) - expect(result).to be(nil) + expect(result).to be_nil end it 'returns nil if title does not match' do @@ -490,7 +490,7 @@ RSpec.describe Snippet, feature_category: :source_code_management do created_at_without_ms # to_s truncates ms of the argument ) - expect(result).to be(nil) + expect(result).to be_nil end it 'returns nil if created_at does not match' do @@ -500,7 +500,7 @@ RSpec.describe Snippet, feature_category: :source_code_management do snippet.created_at # fails match by milliseconds ) - expect(result).to be(nil) + expect(result).to be_nil end end diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index 9096f41d400..aeb3445d403 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -1973,7 +1973,7 @@ RSpec.describe User, feature_category: :user_profile do context 'when credit_card_validation does not exist' do it 'returns nil' do - expect(user.credit_card_validated_at).to be nil + expect(user.credit_card_validated_at).to be_nil end end @@ -4688,7 +4688,7 @@ RSpec.describe User, feature_category: :user_profile do subject { create(:user, email: email, notification_email: nil) } it 'defaults to the primary email' do - expect(subject.notification_email).to be nil + expect(subject.notification_email).to be_nil expect(subject.notification_email_or_default).to eq(email) end end @@ -8614,7 +8614,7 @@ RSpec.describe User, feature_category: :user_profile do it 'un-sets the secondary email' do expect(subject).to receive(:save) subject.unset_secondary_emails_matching_deleted_email!(deleted_email) - expect(subject.commit_email).to be nil + expect(subject.commit_email).to be_nil end end end @@ -8733,7 +8733,7 @@ RSpec.describe User, feature_category: :user_profile do user = create(:user) create(:project, :repository, :private, path: user.username, namespace: user.namespace) - expect(user.user_readme).to be(nil) + expect(user.user_readme).to be_nil end end @@ -8805,7 +8805,7 @@ RSpec.describe User, feature_category: :user_profile do let(:project) {} it 'returns nil' do - expect(emails).to be(nil) + expect(emails).to be_nil end end @@ -8817,7 +8817,7 @@ RSpec.describe User, feature_category: :user_profile do context 'without a defined root group namespace_commit_email' do context 'without a defined project namespace_commit_email' do it 'returns nil' do - expect(emails).to be(nil) + expect(emails).to be_nil end end @@ -8864,7 +8864,7 @@ RSpec.describe User, feature_category: :user_profile do context 'without a defined project namespace_commit_email' do it 'returns nil' do - expect(emails).to be(nil) + expect(emails).to be_nil end end diff --git a/spec/presenters/project_presenter_spec.rb b/spec/presenters/project_presenter_spec.rb index 9ce360fdc80..793d0340829 100644 --- a/spec/presenters/project_presenter_spec.rb +++ b/spec/presenters/project_presenter_spec.rb @@ -285,7 +285,7 @@ RSpec.describe ProjectPresenter do describe '#storage_anchor_data' do it 'does not return storage data for non-admin users' do - expect(presenter.storage_anchor_data).to be(nil) + expect(presenter.storage_anchor_data).to be_nil end it 'returns storage data with usage quotas link for admin users' do @@ -305,7 +305,7 @@ RSpec.describe ProjectPresenter do context 'when user cannot collaborate' do it 'returns no value' do - expect(presenter.gitlab_ci_anchor_data).to be(nil) + expect(presenter.gitlab_ci_anchor_data).to be_nil end end diff --git a/spec/requests/api/applications_spec.rb b/spec/requests/api/applications_spec.rb index 5de9f47c685..14876ccd986 100644 --- a/spec/requests/api/applications_spec.rb +++ b/spec/requests/api/applications_spec.rb @@ -214,7 +214,7 @@ RSpec.describe API::Applications, :aggregate_failures, :api, feature_category: : post api(path, admin, admin_mode: true), params: {} expect(response).to have_gitlab_http_status(:created) - expect(json_response['secret']).not_to be nil + expect(json_response['secret']).not_to be_nil expect(application.secret_matches?(json_response['secret'])).not_to eq(true) end diff --git a/spec/requests/api/ci/pipelines_spec.rb b/spec/requests/api/ci/pipelines_spec.rb index 540b6e7d9cf..999b0b5aeeb 100644 --- a/spec/requests/api/ci/pipelines_spec.rb +++ b/spec/requests/api/ci/pipelines_spec.rb @@ -904,7 +904,7 @@ RSpec.describe API::Ci::Pipelines, feature_category: :continuous_integration do expect(response).to have_gitlab_http_status(:not_found) expect(json_response['message']).to eq '404 Not found' - expect(json_response['id']).to be nil + expect(json_response['id']).to be_nil end context 'with coverage' do @@ -926,7 +926,7 @@ RSpec.describe API::Ci::Pipelines, feature_category: :continuous_integration do expect(response).to have_gitlab_http_status(:not_found) expect(json_response['message']).to eq '404 Project Not Found' - expect(json_response['id']).to be nil + expect(json_response['id']).to be_nil end end @@ -1001,7 +1001,7 @@ RSpec.describe API::Ci::Pipelines, feature_category: :continuous_integration do expect(response).to have_gitlab_http_status(:not_found) expect(json_response['message']).to eq '404 Project Not Found' - expect(json_response['id']).to be nil + expect(json_response['id']).to be_nil end end end @@ -1258,7 +1258,7 @@ RSpec.describe API::Ci::Pipelines, feature_category: :continuous_integration do expect(response).to have_gitlab_http_status(:not_found) expect(json_response['message']).to eq '404 Project Not Found' - expect(json_response['id']).to be nil + expect(json_response['id']).to be_nil end end @@ -1275,7 +1275,7 @@ RSpec.describe API::Ci::Pipelines, feature_category: :continuous_integration do expect(response).to have_gitlab_http_status(:forbidden) expect(json_response['message']).to eq 'hello world' - expect(json_response['id']).to be nil + expect(json_response['id']).to be_nil end end end diff --git a/spec/requests/api/ci/secure_files_spec.rb b/spec/requests/api/ci/secure_files_spec.rb index 971e2bd9fd1..d82162cb5aa 100644 --- a/spec/requests/api/ci/secure_files_spec.rb +++ b/spec/requests/api/ci/secure_files_spec.rb @@ -96,9 +96,9 @@ RSpec.describe API::Ci::SecureFiles, feature_category: :mobile_devops do expect(response).to have_gitlab_http_status(:ok) expect(json_response['name']).to eq(secure_file.name) - expect(json_response['expires_at']).to be nil - expect(json_response['metadata']).to be nil - expect(json_response['file_extension']).to be nil + expect(json_response['expires_at']).to be_nil + expect(json_response['metadata']).to be_nil + expect(json_response['file_extension']).to be_nil end it 'returns project secure file details with metadata when supported' do diff --git a/spec/requests/api/environments_spec.rb b/spec/requests/api/environments_spec.rb index e714a5dd444..5ed6e1c5501 100644 --- a/spec/requests/api/environments_spec.rb +++ b/spec/requests/api/environments_spec.rb @@ -150,7 +150,7 @@ RSpec.describe API::Environments, feature_category: :continuous_delivery do expect(json_response['description']).to eq('description') expect(json_response['slug']).to eq('mepmep') expect(json_response['tier']).to eq('staging') - expect(json_response['external']).to be nil + expect(json_response['external']).to be_nil expect(json_response['auto_stop_setting']).to eq('always') end diff --git a/spec/requests/api/markdown_uploads_spec.rb b/spec/requests/api/markdown_uploads_spec.rb index 5c0c19c3a0f..678c7383d0b 100644 --- a/spec/requests/api/markdown_uploads_spec.rb +++ b/spec/requests/api/markdown_uploads_spec.rb @@ -74,12 +74,12 @@ RSpec.describe API::MarkdownUploads, feature_category: :team_planning do end # rubocop: enable RSpec/AnyInstanceOf - expect(path).not_to be(nil) + expect(path).not_to be_nil expect(Rack::Multipart::Parser::TEMPFILE_FACTORY).to receive(:call).and_return(tempfile) post api(path, user), params: { file: fixture_file_upload("spec/fixtures/dk.png", "image/png") } - expect(tempfile.path).to be(nil) + expect(tempfile.path).to be_nil expect(File.exist?(path)).to be(false) end end diff --git a/spec/requests/api/merge_requests_spec.rb b/spec/requests/api/merge_requests_spec.rb index 5f9986ada5a..994137d5eef 100644 --- a/spec/requests/api/merge_requests_spec.rb +++ b/spec/requests/api/merge_requests_spec.rb @@ -3421,7 +3421,7 @@ RSpec.describe API::MergeRequests, :aggregate_failures, feature_category: :sourc expect(response).to have_gitlab_http_status(:ok) expect(source_repository.branch_exists?(source_branch)).to be false - expect(merge_request.reload.should_remove_source_branch?).to be nil + expect(merge_request.reload.should_remove_source_branch?).to be_nil end it 'does not remove the source branch' do diff --git a/spec/requests/api/settings_spec.rb b/spec/requests/api/settings_spec.rb index dd7b89763ac..24f8af9681d 100644 --- a/spec/requests/api/settings_spec.rb +++ b/spec/requests/api/settings_spec.rb @@ -310,7 +310,7 @@ RSpec.describe API::Settings, 'Settings', :do_not_mock_admin_mode_setting, featu expect(json_response['namespace_aggregation_schedule_lease_duration_in_seconds']).to be(400) expect(json_response['max_import_remote_file_size']).to be(2) expect(json_response['bulk_import_max_download_file_size']).to be(1) - expect(json_response['security_txt_content']).to be(nil) + expect(json_response['security_txt_content']).to be_nil expect(json_response['bulk_import_concurrent_pipeline_batch_limit']).to be(2) expect(json_response['downstream_pipeline_trigger_limit_per_project_user_sha']).to be(300) expect(json_response['concurrent_github_import_jobs_limit']).to be(2) @@ -643,11 +643,11 @@ RSpec.describe API::Settings, 'Settings', :do_not_mock_admin_mode_setting, featu expect(response).to have_gitlab_http_status(:bad_request) - expect(json_response['slack_app_enabled']).to be(nil) - expect(json_response['slack_app_id']).to be(nil) - expect(json_response['slack_app_secret']).to be(nil) - expect(json_response['slack_app_signing_secret']).to be(nil) - expect(json_response['slack_app_verification_token']).to be(nil) + expect(json_response['slack_app_enabled']).to be_nil + expect(json_response['slack_app_id']).to be_nil + expect(json_response['slack_app_secret']).to be_nil + expect(json_response['slack_app_signing_secret']).to be_nil + expect(json_response['slack_app_verification_token']).to be_nil message = json_response['message'] @@ -689,10 +689,10 @@ RSpec.describe API::Settings, 'Settings', :do_not_mock_admin_mode_setting, featu expect(response).to have_gitlab_http_status(:ok) expect(json_response['slack_app_enabled']).to be(false) - expect(json_response['slack_app_id']).to be(nil) - expect(json_response['slack_app_secret']).to be(nil) - expect(json_response['slack_app_signing_secret']).to be(nil) - expect(json_response['slack_app_verification_token']).to be(nil) + expect(json_response['slack_app_id']).to be_nil + expect(json_response['slack_app_secret']).to be_nil + expect(json_response['slack_app_signing_secret']).to be_nil + expect(json_response['slack_app_verification_token']).to be_nil end end end diff --git a/spec/services/import/source_users/bulk_reassign_from_csv_service_spec.rb b/spec/services/import/source_users/bulk_reassign_from_csv_service_spec.rb index fbf46e4e9d3..d3150762662 100644 --- a/spec/services/import/source_users/bulk_reassign_from_csv_service_spec.rb +++ b/spec/services/import/source_users/bulk_reassign_from_csv_service_spec.rb @@ -113,6 +113,36 @@ RSpec.describe Import::SourceUsers::BulkReassignFromCsvService, feature_category end end + context 'when the requested reassignment is already pending' do + let(:username) { 'alice-gl' } + + before do + source_user.update!(status: 1, reassign_to_user: user, reassignment_token: SecureRandom.hex) + end + + it 'treats it as a match' do + result = execute_service + + stats = result.payload[:stats] + expect(stats).to match(matched: 1, failed: 0, skipped: 0) + end + end + + context 'when a different reassignment is already pending' do + let(:username) { 'alice-gl' } + + before do + source_user.update!(status: 1, reassign_to_user: create(:user), reassignment_token: SecureRandom.hex) + end + + it 'treats it as a failure' do + result = execute_service + + stats = result.payload[:stats] + expect(stats).to match(matched: 0, failed: 1, skipped: 0) + end + end + context 'when the reassignment service returns an error' do before do allow_next_instance_of(::Import::SourceUsers::ReassignService) do |reassign_service| diff --git a/spec/support/shared_examples/lib/gitlab/gitaly_client_shared_examples.rb b/spec/support/shared_examples/lib/gitlab/gitaly_client_shared_examples.rb index d388abb16c6..29ffa200b29 100644 --- a/spec/support/shared_examples/lib/gitlab/gitaly_client_shared_examples.rb +++ b/spec/support/shared_examples/lib/gitlab/gitaly_client_shared_examples.rb @@ -16,13 +16,13 @@ RSpec.shared_examples 'Gitaly feature flag actors are inferred from repository' expect(service.repository_actor.flipper_id).to eql(repository.flipper_id) if expected_project.nil? - expect(service.project_actor).to be(nil) + expect(service.project_actor).to be_nil else expect(service.project_actor.flipper_id).to eql(expected_project.flipper_id) end if expected_group.nil? - expect(service.group_actor).to be(nil) + expect(service.group_actor).to be_nil else expect(service.group_actor.flipper_id).to eql(expected_group.flipper_id) end diff --git a/spec/support/shared_examples/lib/gitlab/template/template_shared_examples.rb b/spec/support/shared_examples/lib/gitlab/template/template_shared_examples.rb index a2a4c57d62e..4bdbd7d390c 100644 --- a/spec/support/shared_examples/lib/gitlab/template/template_shared_examples.rb +++ b/spec/support/shared_examples/lib/gitlab/template/template_shared_examples.rb @@ -26,7 +26,7 @@ RSpec.shared_examples 'file template shared examples' do |filename, file_extensi describe '.find' do it 'returns nil if the file does not exist' do - expect(subject.find('nonexistent-file')).to be nil + expect(subject.find('nonexistent-file')).to be_nil end it 'returns the corresponding object of a valid file' do diff --git a/spec/support/shared_examples/models/diff_positionable_note_shared_examples.rb b/spec/support/shared_examples/models/diff_positionable_note_shared_examples.rb index f7ddb2655ee..cef18603bf9 100644 --- a/spec/support/shared_examples/models/diff_positionable_note_shared_examples.rb +++ b/spec/support/shared_examples/models/diff_positionable_note_shared_examples.rb @@ -52,7 +52,7 @@ RSpec.shared_examples 'a valid diff positionable note' do |factory_on_commit| describe "#{method}=" do it "doesn't accept non-hash JSON passed as a string" do subject.send(:"#{method}=", "true") - expect(subject.attributes_before_type_cast[method.to_s]).to be(nil) + expect(subject.attributes_before_type_cast[method.to_s]).to be_nil end it "does accept a position hash as a string" do @@ -62,7 +62,7 @@ RSpec.shared_examples 'a valid diff positionable note' do |factory_on_commit| it "doesn't accept an array" do subject.send(:"#{method}=", ["test"]) - expect(subject.attributes_before_type_cast[method.to_s]).to be(nil) + expect(subject.attributes_before_type_cast[method.to_s]).to be_nil end it "does accept a hash" do diff --git a/spec/support/shared_examples/models/user_mentions_shared_examples.rb b/spec/support/shared_examples/models/user_mentions_shared_examples.rb index 948f8a1f088..71e9f10bbae 100644 --- a/spec/support/shared_examples/models/user_mentions_shared_examples.rb +++ b/spec/support/shared_examples/models/user_mentions_shared_examples.rb @@ -4,9 +4,9 @@ RSpec.shared_examples 'has user mentions' do describe '#has_mentions?' do context 'when no mentions' do it 'returns false' do - expect(subject.mentioned_users_ids).to be nil - expect(subject.mentioned_projects_ids).to be nil - expect(subject.mentioned_groups_ids).to be nil + expect(subject.mentioned_users_ids).to be_nil + expect(subject.mentioned_projects_ids).to be_nil + expect(subject.mentioned_groups_ids).to be_nil expect(subject.has_mentions?).to be false end end diff --git a/spec/support/shared_examples/requests/api/graphql/projects/services_shared_examples.rb b/spec/support/shared_examples/requests/api/graphql/projects/services_shared_examples.rb index da1caef63ba..29c655c02da 100644 --- a/spec/support/shared_examples/requests/api/graphql/projects/services_shared_examples.rb +++ b/spec/support/shared_examples/requests/api/graphql/projects/services_shared_examples.rb @@ -8,7 +8,7 @@ RSpec.shared_examples 'unauthorized users cannot read services' do context 'when anonymous user' do let(:current_user) { nil } - it { expect(services).to be nil } + it { expect(services).to be_nil } end context 'when user developer' do @@ -16,6 +16,6 @@ RSpec.shared_examples 'unauthorized users cannot read services' do project.add_developer(current_user) end - it { expect(services).to be nil } + it { expect(services).to be_nil } end end diff --git a/spec/support/shared_examples/services/auto_merge_shared_examples.rb b/spec/support/shared_examples/services/auto_merge_shared_examples.rb index 8984a4f4d36..86f564f72b3 100644 --- a/spec/support/shared_examples/services/auto_merge_shared_examples.rb +++ b/spec/support/shared_examples/services/auto_merge_shared_examples.rb @@ -157,7 +157,7 @@ RSpec.shared_examples 'auto_merge service #cancel' do it "resets all the pipeline succeeds params" do expect(mr_merge_if_green_enabled.merge_when_pipeline_succeeds).to be_falsey expect(mr_merge_if_green_enabled.merge_params).to eq({}) - expect(mr_merge_if_green_enabled.merge_user).to be nil + expect(mr_merge_if_green_enabled.merge_user).to be_nil end it 'posts a system note' do diff --git a/spec/support_specs/helpers/keyset_pagination_helpers_spec.rb b/spec/support_specs/helpers/keyset_pagination_helpers_spec.rb index ec63f33776c..443caf87ac8 100644 --- a/spec/support_specs/helpers/keyset_pagination_helpers_spec.rb +++ b/spec/support_specs/helpers/keyset_pagination_helpers_spec.rb @@ -82,7 +82,7 @@ RSpec.describe KeysetPaginationHelpers, feature_category: :api do # malformed as the regxe is expecting the url to be surrounded by `<>` let(:headers) { { 'LINK' => %(rel="next", GARBAGE, #{url}; rel="prev") } } - it { is_expected.to be nil } + it { is_expected.to be_nil } end end end diff --git a/spec/uploaders/object_storage_spec.rb b/spec/uploaders/object_storage_spec.rb index 4da6aa48fa6..c7fb95d16f1 100644 --- a/spec/uploaders/object_storage_spec.rb +++ b/spec/uploaders/object_storage_spec.rb @@ -572,7 +572,7 @@ RSpec.describe ObjectStorage, :clean_gitlab_redis_shared_state, feature_category context 'when FIPS is disabled' do it 'response disables FIPS' do - expect(subject[:UploadHashFunctions]).to be nil + expect(subject[:UploadHashFunctions]).to be_nil end end diff --git a/spec/workers/error_tracking_issue_link_worker_spec.rb b/spec/workers/error_tracking_issue_link_worker_spec.rb index b3d023ee5ea..8d8d496e81c 100644 --- a/spec/workers/error_tracking_issue_link_worker_spec.rb +++ b/spec/workers/error_tracking_issue_link_worker_spec.rb @@ -36,7 +36,7 @@ RSpec.describe ErrorTrackingIssueLinkWorker, feature_category: :observability do expect_any_instance_of(ErrorTracking::SentryClient).not_to receive(:repos) expect_any_instance_of(ErrorTracking::SentryClient).not_to receive(:create_issue_link) - expect(subject).to be nil + expect(subject).to be_nil end end diff --git a/spec/workers/import/user_mapping/assignment_from_csv_worker_spec.rb b/spec/workers/import/user_mapping/assignment_from_csv_worker_spec.rb index fb3da7af2a3..6d3b56f7703 100644 --- a/spec/workers/import/user_mapping/assignment_from_csv_worker_spec.rb +++ b/spec/workers/import/user_mapping/assignment_from_csv_worker_spec.rb @@ -30,7 +30,7 @@ RSpec.describe Import::UserMapping::AssignmentFromCsvWorker, feature_category: : allow(Upload).to receive(:find_by_id).and_return(fake_upload) allow_next_instance_of(Import::SourceUsers::BulkReassignFromCsvService) do |service| - allow(service).to receive(:find_source_user).and_return(source_user) + allow(service).to receive(:find_source_user).and_return(source_user.reload) end end diff --git a/yarn.lock b/yarn.lock index 9eebb3bbf83..0a19f0fcd3f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1436,10 +1436,10 @@ resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-3.123.0.tgz#1fa3b1a709755ff7c8ef67e18c0442101655ebf0" integrity sha512-yjVn+utOTIKk8d9JlvGo6EgJ4TQ+CKpe3RddflAqtsQqQuL/2MlVdtaUePybxYzWIaumFuh5LouQ6BrWyw1niQ== -"@gitlab/ui@108.8.1": - version "108.8.1" - resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-108.8.1.tgz#b30b7ae85bd538243ecc44585f19883810832633" - integrity sha512-FF3JJsA7SumT2G8s6vyfsDXCau+IwhDnN7c3/fqC9R3W9E+QxnE6K8i12UjV+WR4hsqq6SywpwOzJxfmPkXs9w== +"@gitlab/ui@108.9.0": + version "108.9.0" + resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-108.9.0.tgz#bfc2e48d79fea22b1c3b0bf20e89cbe46f46e32b" + integrity sha512-6wcSK040l9+7ppHzx4ab78oGpJmT5cjOtytoezA9plBq1tpbbFd7ENt7DH0ZWxP9A8M8wVR7D8N1EzGKjesahQ== dependencies: "@floating-ui/dom" "1.4.3" echarts "^5.3.2" @@ -2520,51 +2520,51 @@ resolved "https://registry.yarnpkg.com/@rtsao/scc/-/scc-1.1.0.tgz#927dd2fae9bc3361403ac2c7a00c32ddce9ad7e8" integrity sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g== -"@sentry-internal/browser-utils@9.1.0": - version "9.1.0" - resolved "https://registry.yarnpkg.com/@sentry-internal/browser-utils/-/browser-utils-9.1.0.tgz#0f67de865d4e1b3a60cd618cdda8431d383e6b71" - integrity sha512-S1uT+kkFlstWpwnaBTIJSwwAID8PS3aA0fIidOjNezeoUE5gOvpsjDATo9q+sl6FbGWynxMz6EnYSrq/5tuaBQ== +"@sentry-internal/browser-utils@9.3.0": + version "9.3.0" + resolved "https://registry.yarnpkg.com/@sentry-internal/browser-utils/-/browser-utils-9.3.0.tgz#345fa61da239186fa0ad6c7194d4a1f7df7646c7" + integrity sha512-G3z4HCUyb5nJe03EPUhWjnaHqMDt4mOTFJDNha3DGoB51lMYojpQI1Qo1u6bY4qkWVSO1c+HqOU0RVsXoAchtQ== dependencies: - "@sentry/core" "9.1.0" + "@sentry/core" "9.3.0" -"@sentry-internal/feedback@9.1.0": - version "9.1.0" - resolved "https://registry.yarnpkg.com/@sentry-internal/feedback/-/feedback-9.1.0.tgz#e96edd4e46c8ab19f00855f60fa3bed01106bb5b" - integrity sha512-jTDCqkqH3QDC8m9WO4mB06hqnBRsl3p7ozoh0E774UvNB6blOEZjShhSGMMEy5jbbJajPWsOivCofUtFAwbfGw== +"@sentry-internal/feedback@9.3.0": + version "9.3.0" + resolved "https://registry.yarnpkg.com/@sentry-internal/feedback/-/feedback-9.3.0.tgz#d60bcedd01907478b286512ce54f59682b2910e0" + integrity sha512-LQmIbQaATlN5QEwCD2Xt+7VKfwfR5W3dbn0jdF1x4hQFE/srdnOj60xMz/mj3tP5BxV552xJniGsyZ8lXHDb2A== dependencies: - "@sentry/core" "9.1.0" + "@sentry/core" "9.3.0" -"@sentry-internal/replay-canvas@9.1.0": - version "9.1.0" - resolved "https://registry.yarnpkg.com/@sentry-internal/replay-canvas/-/replay-canvas-9.1.0.tgz#20be6ac4b722078ebdbc760aada02858ecbffe7e" - integrity sha512-gxredVe+mOgfNqDJ3dTLiRON3FK1rZ8d0LHp7TICK/umLkWFkuso0DbNeyKU+3XCEjCr9VM7ZRqTDMzmY6zyVg== +"@sentry-internal/replay-canvas@9.3.0": + version "9.3.0" + resolved "https://registry.yarnpkg.com/@sentry-internal/replay-canvas/-/replay-canvas-9.3.0.tgz#b9432ab65152304b5f86f99efdeffcd92091f733" + integrity sha512-MhDMJeRGa55a0D541+OzTFMWwbabthhDGbAL90/NpappfyeBbAiktmCNl0BFTZuRbCGrC2m1LLCqHegCVKW4fQ== dependencies: - "@sentry-internal/replay" "9.1.0" - "@sentry/core" "9.1.0" + "@sentry-internal/replay" "9.3.0" + "@sentry/core" "9.3.0" -"@sentry-internal/replay@9.1.0": - version "9.1.0" - resolved "https://registry.yarnpkg.com/@sentry-internal/replay/-/replay-9.1.0.tgz#b423edf4dabaea0b7ba689a87b19cf3ea87075f0" - integrity sha512-E2xrUoms90qvm0BVOuaZ8QfkMoTUEgoIW/35uOeaqNcL7uOIj8c5cSEQQKit2Dr7CL6W+Ci5c6Khdyd5C0NL5w== +"@sentry-internal/replay@9.3.0": + version "9.3.0" + resolved "https://registry.yarnpkg.com/@sentry-internal/replay/-/replay-9.3.0.tgz#c846cf77cd8deefda84316f1a938bbeae5861564" + integrity sha512-ZkH+Gahn89JygpuiFn26ZgAqJXHtnr+HjfQ2ONOFoWQHNH6X5wk75UTma55aYk1d8VcBPFoU6WjFhZoQ55SV1g== dependencies: - "@sentry-internal/browser-utils" "9.1.0" - "@sentry/core" "9.1.0" + "@sentry-internal/browser-utils" "9.3.0" + "@sentry/core" "9.3.0" -"@sentry/browser@9.1.0": - version "9.1.0" - resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-9.1.0.tgz#7798a930562b3b403611e1f201fb8e50e59da472" - integrity sha512-G55e5j77DqRW3LkalJLAjRRfuyKrjHaKTnwIYXa6ycO+Q1+l14pEUxu+eK5Abu2rtSdViwRSb5/G6a/miSUlYA== +"@sentry/browser@9.3.0": + version "9.3.0" + resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-9.3.0.tgz#270e93c0f1bc10abb6651255bcaa30ba21c4928a" + integrity sha512-yPwWWQo/hpN63p0NGmk/Dd1Fx5CQRWNMfuV7dtfPBtg3vRjDecA9OLyK29AqK5h3Fl8FuJOyOqB87CvtXUqh5g== dependencies: - "@sentry-internal/browser-utils" "9.1.0" - "@sentry-internal/feedback" "9.1.0" - "@sentry-internal/replay" "9.1.0" - "@sentry-internal/replay-canvas" "9.1.0" - "@sentry/core" "9.1.0" + "@sentry-internal/browser-utils" "9.3.0" + "@sentry-internal/feedback" "9.3.0" + "@sentry-internal/replay" "9.3.0" + "@sentry-internal/replay-canvas" "9.3.0" + "@sentry/core" "9.3.0" -"@sentry/core@9.1.0": - version "9.1.0" - resolved "https://registry.yarnpkg.com/@sentry/core/-/core-9.1.0.tgz#db7438d144b7ea405260c33082971eedab48d7f3" - integrity sha512-djWEzSBpMgqdF3GQuxO+kXCUX+Mgq42G4Uah/HSUBvPDHKipMmyWlutGRoFyVPPOnCDgpHu3wCt83wbpEyVmDw== +"@sentry/core@9.3.0": + version "9.3.0" + resolved "https://registry.yarnpkg.com/@sentry/core/-/core-9.3.0.tgz#d5a1ab7deecd95f86316e658129d3874557cbfd9" + integrity sha512-SxQ4z7wTkfguvYb2ctNEMU9kVAbhl9ymfjhLnrvtygTwL5soLqAKdco/lX/4P9K9Osgb2Dl6urQWRl+AhzKVbQ== "@sinclair/typebox@^0.27.8": version "0.27.8"