Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2025-03-12 09:09:57 +00:00
parent a527e81858
commit 7eb03d3ceb
51 changed files with 344 additions and 380 deletions

View File

@ -47,10 +47,15 @@ docs-lint markdown:
needs: []
script:
- source ./scripts/utils.sh
- yarn_install_script
- install_gitlab_gem
- scripts/lint-doc.sh
- scripts/lint/check_mermaid.mjs
- |
function docs_lint_markdown() {
yarn_install_script
install_gitlab_gem
scripts/lint-doc.sh
scripts/lint/check_mermaid.mjs
}
run_with_custom_exit_code docs_lint_markdown
docs code_quality:
extends:
@ -97,8 +102,10 @@ docs-lint links:
- .docs-markdown-lint-image
stage: lint
needs: []
before_script:
- source scripts/utils.sh
script:
- lychee --offline --no-progress --include-fragments doc
- run_with_custom_exit_code lychee --offline --no-progress --include-fragments doc
docs-lint deprecations-and-removals:
variables:
@ -111,8 +118,13 @@ docs-lint deprecations-and-removals:
stage: lint
needs: []
script:
- bundle exec rake gitlab:docs:check_deprecations
- bundle exec rake gitlab:docs:check_windows
- |
function docs_lint_deprecations_and_removals() {
bundle exec rake gitlab:docs:check_deprecations
bundle exec rake gitlab:docs:check_windows
}
run_with_custom_exit_code docs_lint_deprecations_and_removals
docs-lint redirects:
image: ${GITLAB_DEPENDENCY_PROXY_ADDRESS}ruby:${RUBY_VERSION}-alpine
@ -121,5 +133,7 @@ docs-lint redirects:
- .default-retry
- .docs:rules:redirect-check
needs: []
before_script:
- source scripts/utils.sh
script:
- ./scripts/lint-docs-redirects.rb
- run_with_custom_exit_code ./scripts/lint-docs-redirects.rb

View File

@ -334,7 +334,7 @@ jest:
junit: junit_jest.xml
parallel: 11
script:
- run_timed_command scripts/frontend/jest_ci.js
- run_with_custom_exit_code run_timed_command scripts/frontend/jest_ci.js
jest-with-fixtures:
extends:
@ -348,7 +348,7 @@ jest-with-fixtures:
- !reference [.with-fixtures-needs, needs]
parallel: 2
script:
- run_timed_command "scripts/frontend/jest_ci.js --fixtures"
- run_with_custom_exit_code run_timed_command "scripts/frontend/jest_ci.js --fixtures"
jest vue3:
extends:
@ -388,7 +388,7 @@ jest vue3 mr:
- junit_jest.xml
parallel: 6
script:
- run_timed_command "scripts/frontend/jest_ci.js --vue3"
- run_with_custom_exit_code run_timed_command "scripts/frontend/jest_ci.js --vue3"
allow_failure: false
jest-with-fixtures vue3 mr:
@ -408,7 +408,7 @@ jest-with-fixtures vue3 mr:
- junit_jest.xml
parallel: 1
script:
- run_timed_command "scripts/frontend/jest_ci.js --vue3 --fixtures"
- run_with_custom_exit_code run_timed_command "scripts/frontend/jest_ci.js --vue3 --fixtures"
jest predictive:
extends:
@ -418,7 +418,15 @@ jest predictive:
- !reference [jest, needs]
- "detect-tests"
script:
- if [[ -s "$RSPEC_CHANGED_FILES_PATH" ]] || [[ -s "$RSPEC_MATCHING_JS_FILES_PATH" ]]; then run_timed_command "scripts/frontend/jest_ci.js --predictive"; fi
- |
function jest_predictive() {
if [[ -s "$RSPEC_CHANGED_FILES_PATH" ]] || [[ -s "$RSPEC_MATCHING_JS_FILES_PATH" ]]; then
run_timed_command "scripts/frontend/jest_ci.js --predictive"
fi
}
run_with_custom_exit_code jest_predictive
parallel: 4
jest-with-fixtures predictive:
@ -429,7 +437,14 @@ jest-with-fixtures predictive:
- !reference [jest-with-fixtures, needs]
- "detect-tests"
script:
- if [[ -s "$RSPEC_CHANGED_FILES_PATH" ]] || [[ -s "$RSPEC_MATCHING_JS_FILES_PATH" ]]; then run_timed_command "scripts/frontend/jest_ci.js --predictive --fixtures"; fi
- |
function jest_with_fixtures_predictive() {
if [[ -s "$RSPEC_CHANGED_FILES_PATH" ]] || [[ -s "$RSPEC_MATCHING_JS_FILES_PATH" ]]; then
run_timed_command "scripts/frontend/jest_ci.js --predictive --fixtures"
fi
}
run_with_custom_exit_code jest_with_fixtures_predictive
jest vue3 predictive:
extends:
@ -439,7 +454,14 @@ jest vue3 predictive:
- !reference [jest vue3 mr, needs]
- "detect-tests"
script:
- if [[ -s "$RSPEC_CHANGED_FILES_PATH" ]] || [[ -s "$RSPEC_MATCHING_JS_FILES_PATH" ]]; then run_timed_command "scripts/frontend/jest_ci.js --vue3 --predictive"; fi
- |
function jest_vue3_predictive() {
if [[ -s "$RSPEC_CHANGED_FILES_PATH" ]] || [[ -s "$RSPEC_MATCHING_JS_FILES_PATH" ]]; then
run_timed_command "scripts/frontend/jest_ci.js --vue3 --predictive"
fi
}
run_with_custom_exit_code jest_vue3_predictive
jest-with-fixtures vue3 predictive:
extends:
@ -449,7 +471,14 @@ jest-with-fixtures vue3 predictive:
- !reference [jest-with-fixtures vue3 mr, needs]
- "detect-tests"
script:
- if [[ -s "$RSPEC_CHANGED_FILES_PATH" ]] || [[ -s "$RSPEC_MATCHING_JS_FILES_PATH" ]]; then run_timed_command "scripts/frontend/jest_ci.js --vue3 --predictive --fixtures"; fi
- |
function jest_with_fixtures_vue3_predictive() {
if [[ -s "$RSPEC_CHANGED_FILES_PATH" ]] || [[ -s "$RSPEC_MATCHING_JS_FILES_PATH" ]]; then
run_timed_command "scripts/frontend/jest_ci.js --vue3 --predictive --fixtures";
fi
}
run_with_custom_exit_code jest_with_fixtures_vue3_predictive
allow_failure: false
jest vue3 check quarantined predictive:
@ -460,7 +489,14 @@ jest vue3 check quarantined predictive:
- !reference [jest vue3 mr, needs]
- "detect-tests"
script:
- if [[ -s "$RSPEC_CHANGED_FILES_PATH" ]] || [[ -s "$RSPEC_MATCHING_JS_FILES_PATH" ]]; then run_timed_command "./scripts/frontend/check_jest_vue3_quarantine.js"; fi
- |
function jest_vue_check_quarantined_predictive() {
if [[ -s "$RSPEC_CHANGED_FILES_PATH" ]] || [[ -s "$RSPEC_MATCHING_JS_FILES_PATH" ]]; then
run_timed_command "./scripts/frontend/check_jest_vue3_quarantine.js"
fi
}
run_with_custom_exit_code jest_vue_check_quarantined_predictive
parallel: 4
artifacts:
name: quarantined_tests_output
@ -483,7 +519,14 @@ jest vue3 check quarantined:
- .frontend:rules:jest-vue3-check-quarantined
parallel: 4
script:
- if [[ -s "$RSPEC_CHANGED_FILES_PATH" ]] || [[ -s "$RSPEC_MATCHING_JS_FILES_PATH" ]]; then run_timed_command "./scripts/frontend/check_jest_vue3_quarantine.js --all"; fi
- |
function jest_vue3_check_quarantined() {
if [[ -s "$RSPEC_CHANGED_FILES_PATH" ]] || [[ -s "$RSPEC_MATCHING_JS_FILES_PATH" ]]; then
run_timed_command "./scripts/frontend/check_jest_vue3_quarantine.js --all"
fi
}
run_with_custom_exit_code jest_vue3_check_quarantined
jest-with-fixtures vue3 check quarantined:
extends:
@ -498,7 +541,7 @@ jest-integration:
- .repo-from-artifacts
- .frontend:rules:jest-integration
script:
- run_timed_command "yarn jest:integration --ci"
- run_with_custom_exit_code run_timed_command "yarn jest:integration --ci"
needs:
# it's ok to wait for the repo artifact as we're waiting for the fixtures (which wait for the repo artifact) anyway
- !reference [.repo-from-artifacts, needs]
@ -550,7 +593,7 @@ jest-linters:
- .frontend:rules:jest-linters
needs: []
script:
- run_timed_command "yarn jest:eslint --ci"
- run_with_custom_exit_code run_timed_command "yarn jest:eslint --ci"
coverage-frontend:
extends:

View File

@ -56,6 +56,7 @@ export default {
<template>
<div class="gl-flex gl-flex-col gl-gap-3 md:gl-flex-row">
<gl-filtered-search
class="gl-min-w-0 gl-grow"
:value="tokens"
:placeholder="s__('CredentialsInventory|Search or filter credentials...')"
:available-tokens="availableTokens"
@ -66,7 +67,7 @@ export default {
<gl-sorting
v-if="!hasKey"
block
dropdown-class="gl-w-full"
dropdown-class="gl-w-full !gl-flex"
:is-ascending="sorting.isAsc"
:sort-by="sorting.value"
:sort-options="$options.SORT_OPTIONS"

View File

@ -1,17 +0,0 @@
# frozen_string_literal: true
module DiffsStreamResource
extend ActiveSupport::Concern
def diffs_stream_url(resource, offset = nil, diff_view = nil)
return if offset && offset > resource.diffs_for_streaming.diff_files.count
diffs_stream_resource_url(resource, offset, diff_view)
end
private
def diffs_stream_resource_url(resource, offset, diff_view)
raise NotImplementedError
end
end

View File

@ -0,0 +1,34 @@
# frozen_string_literal: true
module RapidDiffsResource
extend ActiveSupport::Concern
def diffs_stream_url(resource, offset = nil, diff_view = nil)
return if offset && offset > resource.diffs_for_streaming.diff_files.count
diffs_stream_resource_url(resource, offset, diff_view)
end
def diff_files_metadata
return render_404 unless rapid_diffs_enabled?
return render_404 unless diffs_resource.present?
render json: {
diff_files: DiffFileMetadataEntity.represent(diffs_resource.raw_diff_files(sorted: true))
}
end
private
def rapid_diffs_enabled?
::Feature.enabled?(:rapid_diffs, current_user, type: :wip)
end
def diffs_resource
raise NotImplementedError
end
def diffs_stream_resource_url(resource, offset, diff_view)
raise NotImplementedError
end
end

View File

@ -9,7 +9,7 @@ class Projects::CommitController < Projects::ApplicationController
include DiffForPath
include DiffHelper
include SourcegraphDecorator
include DiffsStreamResource
include RapidDiffsResource
# Authorize
before_action :require_non_empty_project
@ -298,6 +298,10 @@ class Projects::CommitController < Projects::ApplicationController
check_rate_limit!(:expanded_diff_files, scope: current_user || request.ip)
end
def diffs_resource
commit&.diffs(commit_diff_options)
end
end
Projects::CommitController.prepend_mod_with('Projects::CommitController')

View File

@ -7,6 +7,7 @@ class Projects::CompareController < Projects::ApplicationController
include DiffHelper
include RendersCommits
include CompareHelper
include RapidDiffsResource
# Authorize
before_action :require_non_empty_project
@ -195,4 +196,8 @@ class Projects::CompareController < Projects::ApplicationController
def compare_params
@compare_params ||= params.permit(:from, :to, :from_project_id, :straight, :to_project_id)
end
def diffs_resource
compare&.diffs(diff_options)
end
end

View File

@ -5,6 +5,7 @@ class Projects::MergeRequests::CreationsController < Projects::MergeRequests::Ap
include DiffHelper
include RendersCommits
include ProductAnalyticsTracking
include RapidDiffsResource
skip_before_action :merge_request
before_action :authorize_create_merge_request_from!
@ -105,6 +106,10 @@ class Projects::MergeRequests::CreationsController < Projects::MergeRequests::Ap
render json: ProjectSerializer.new.represent(get_target_projects)
end
def diffs_resource
@merge_request&.compare&.diffs
end
private
def get_target_projects

View File

@ -13,7 +13,7 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
include Gitlab::Cache::Helpers
include MergeRequestsHelper
include ParseCommitDate
include DiffsStreamResource
include RapidDiffsResource
prepend_before_action(only: [:index]) { authenticate_sessionless_user!(:rss) }
skip_before_action :merge_request, only: [:index, :bulk_update, :export_csv]
@ -693,6 +693,10 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
_("This merge request has reached the maximum limit of %{limit} versions and cannot be updated further. " \
"Close this merge request and create a new one instead."), limit: MergeRequest::DIFF_VERSION_LIMIT)
end
def diffs_resource
@merge_request.latest_diffs
end
end
Projects::MergeRequestsController.prepend_mod_with('Projects::MergeRequestsController')

View File

@ -1,17 +0,0 @@
# frozen_string_literal: true
module Resolvers
module WorkItems
module Widgets
class StatusResolver < BaseResolver
type ::Types::WorkItems::Widgets::StatusType.connection_type, null: true
def resolve
[]
end
end
end
end
end
Resolvers::WorkItems::Widgets::StatusResolver.prepend_mod

View File

@ -347,10 +347,6 @@ module Types
method: :linked_to_subscription?,
description: 'Indicates if group is linked to a subscription.'
field :allowed_statuses, Types::WorkItems::Widgets::StatusType.connection_type,
null: true, description: 'Allowed statuses for the group.',
experiment: { milestone: '17.8' }, resolver: Resolvers::WorkItems::Widgets::StatusResolver
def label(title:)
BatchLoader::GraphQL.for(title).batch(key: group) do |titles, loader, args|
LabelsFinder

View File

@ -133,10 +133,6 @@ module Types
calls_gitaly: true,
description: 'Work item description templates available to the namespace.'
field :allowed_statuses, Types::WorkItems::Widgets::StatusType.connection_type,
null: true, description: 'Allowed statuses for the namespace.',
experiment: { milestone: '17.8' }, resolver: Resolvers::WorkItems::Widgets::StatusResolver
markdown_field :description_html, null: true
def achievements_path

View File

@ -805,10 +805,6 @@ module Types
connection: true,
description: "List of the project's Pages Deployments."
field :allowed_statuses, Types::WorkItems::Widgets::StatusType.connection_type,
null: true, description: 'Allowed statuses for the project.',
experiment: { milestone: '17.8' }, resolver: Resolvers::WorkItems::Widgets::StatusResolver
field :pages_force_https, GraphQL::Types::Boolean,
null: false,
description: "Project's Pages site redirects unsecured connections to HTTPS."

View File

@ -14,14 +14,12 @@ module Types
ORPHAN_TYPES = [
::Types::WorkItems::WidgetDefinitions::AssigneesType,
::Types::WorkItems::WidgetDefinitions::GenericType,
::Types::WorkItems::WidgetDefinitions::HierarchyType,
::Types::WorkItems::WidgetDefinitions::StatusType
::Types::WorkItems::WidgetDefinitions::HierarchyType
].freeze
TYPE_MAPPING = {
::WorkItems::Widgets::Assignees => ::Types::WorkItems::WidgetDefinitions::AssigneesType,
::WorkItems::Widgets::Hierarchy => ::Types::WorkItems::WidgetDefinitions::HierarchyType,
::WorkItems::Widgets::Status => ::Types::WorkItems::WidgetDefinitions::StatusType
::WorkItems::Widgets::Hierarchy => ::Types::WorkItems::WidgetDefinitions::HierarchyType
}.freeze
def self.ce_orphan_types

View File

@ -1,21 +0,0 @@
# frozen_string_literal: true
module Types
module WorkItems
module WidgetDefinitions
# rubocop:disable Graphql/AuthorizeTypes -- Authorization too granular, parent type is authorized
class StatusType < BaseObject
graphql_name 'WorkItemWidgetDefinitionStatus'
description 'Represents a Status widget definition'
implements ::Types::WorkItems::WidgetDefinitionInterface
field :allowed_statuses, ::Types::WorkItems::Widgets::StatusType.connection_type,
null: true, experiment: { milestone: '17.8' },
description: 'Allowed statuses for the work item type.',
resolver: Resolvers::WorkItems::Widgets::StatusResolver
end
# rubocop:enable Graphql/AuthorizeTypes
end
end
end

View File

@ -33,7 +33,6 @@ module Types
::WorkItems::Widgets::Development => ::Types::WorkItems::Widgets::DevelopmentType,
::WorkItems::Widgets::CrmContacts => ::Types::WorkItems::Widgets::CrmContactsType,
::WorkItems::Widgets::EmailParticipants => ::Types::WorkItems::Widgets::EmailParticipantsType,
::WorkItems::Widgets::Status => ::Types::WorkItems::Widgets::StatusType,
::WorkItems::Widgets::LinkedResources => ::Types::WorkItems::Widgets::LinkedResourcesType,
::WorkItems::Widgets::ErrorTracking => ::Types::WorkItems::Widgets::ErrorTrackingType
}.freeze

View File

@ -1,43 +0,0 @@
# frozen_string_literal: true
module Types
module WorkItems
module Widgets
# Disabling widget level authorization as it might be too granular
# and we already authorize the parent work item
# rubocop:disable Graphql/AuthorizeTypes -- reason above
class StatusType < BaseObject
graphql_name 'WorkItemWidgetStatus'
description 'Represents status widget'
implements ::Types::WorkItems::WidgetInterface
field :id, Types::GlobalIDType,
null: true,
experiment: { milestone: '17.8' },
description: 'ID of the status.'
field :name, GraphQL::Types::String,
null: true,
experiment: { milestone: '17.8' },
description: 'Name of the status.'
field :icon_name, GraphQL::Types::String,
null: true,
experiment: { milestone: '17.8' },
description: 'Icon name of the status.'
field :color, GraphQL::Types::String,
null: true,
experiment: { milestone: '17.10' },
description: 'Color of the status.'
field :position, GraphQL::Types::Int,
null: true,
experiment: { milestone: '17.10' },
description: 'Position of the status within its category.'
end
# rubocop:enable Graphql/AuthorizeTypes
end
end
end

View File

@ -901,6 +901,12 @@ class MergeRequest < ApplicationRecord
end
end
def latest_diffs
diff = diffable_merge_ref? ? merge_head_diff : merge_request_diff
diff.diffs(diff_options)
end
def diffs(diff_options = {})
if compare
# When saving MR diffs, `expanded` is implicitly added (because we need

View File

@ -42,7 +42,7 @@ module WorkItems
development: 23,
crm_contacts: 24,
email_participants: 25,
status: 26,
status: 26, # EE-only
linked_resources: 27,
custom_fields: 28, # EE-only
error_tracking: 29,

View File

@ -1,25 +0,0 @@
# frozen_string_literal: true
module WorkItems
module Widgets
class Status < Base
# TODO - remove this once the widget table is implementeed
# https://gitlab.com/gitlab-org/gitlab/-/issues/498393
include GlobalID::Identification
# TODO - remove this once the widget table is implementeed
# All the below fields gets delegated to the model https://gitlab.com/gitlab-org/gitlab/-/issues/498393
def id
'10'
end
def name
'Status'
end
def icon_name
'status icon'
end
end
end
end

View File

@ -1,12 +0,0 @@
# frozen_string_literal: true
module WorkItems
module DataSync
module Widgets
class Status < Base
# Need this class to make spec pass at https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/spec/models/ee/work_items/widget_definition_spec.rb#L49
# Will be implemented as part of https://gitlab.com/groups/gitlab-org/-/epics/14793
end
end
end
end

View File

@ -6,5 +6,5 @@ introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/139851
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/435391
milestone: '16.9'
type: ops
group: group::global search
group: group::durability
default_enabled: true

View File

@ -45,6 +45,7 @@ resources :merge_requests, concerns: :awardable, except: [:new, :create, :show],
get :diff_for_path, controller: 'merge_requests/diffs'
get 'diff_by_file_hash/:file_hash', to: 'merge_requests/diffs#diff_by_file_hash', as: :diff_by_file_hash
get :diffs_stream, to: 'merge_requests/diffs_stream#diffs'
get :diff_files_metadata
# NOTE: Fallback to `merge_requests/diffs#diff_for_path` to handle `collapsed_diff_url` from the collapsed partial
scope controller: 'merge_requests/diffs_stream' do
@ -95,5 +96,6 @@ scope path: 'merge_requests', controller: 'merge_requests/creations' do
get :branch_from
get :branch_to
get :diffs_stream, to: 'merge_requests/creations_diffs_stream#diffs'
get :diff_files_metadata
end
end

View File

@ -19,6 +19,7 @@ scope format: false do
get :diff_for_path
get :signatures
get :diffs_stream, to: 'compare_diffs_stream#diffs'
get :diff_files_metadata
end
end
@ -112,6 +113,7 @@ resources :commit, only: [:show], constraints: { id: Gitlab::Git::Commit::SHA_PA
get :diff_for_path
get :diff_files
get :merge_requests
get :diff_files_metadata
end
end

View File

@ -9,6 +9,5 @@ feature_categories:
description: Information about runner managers associated to instance Ci::Runner models
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/168131
milestone: '17.6'
gitlab_schema: gitlab_ci
exempt_from_sharding: true
gitlab_schema: gitlab_ci_cell_local
table_size: small

View File

@ -16,7 +16,13 @@ class AddProjectIdToMergeRequestDiffFiles < Gitlab::Database::Migration[2.2]
add_column SOURCE_TABLE, :project_id, :bigint, if_not_exists: true
end
add_concurrent_foreign_key SOURCE_TABLE, :projects, column: :project_id, on_delete: :cascade
# This caused the incident https://gitlab.com/gitlab-com/gl-infra/production/-/issues/19474
# We must first add the index before adding a foreign key. We also explicitly removed it in
# db/post_migrate/20250312061803_remove_project_id_fk_from_merge_request_diff_files.rb to clean up any installations
# that ran this.
#
# no-op:
# add_concurrent_foreign_key SOURCE_TABLE, :projects, column: :project_id, on_delete: :cascade
end
def down

View File

@ -0,0 +1,20 @@
# frozen_string_literal: true
class RemoveProjectIdFkFromMergeRequestDiffFiles < Gitlab::Database::Migration[2.2]
milestone '17.10'
disable_ddl_transaction!
FK_NAME = 'fk_0e3ba01603'
def up
with_lock_retries do
remove_foreign_key_if_exists(:merge_request_diff_files, :projects, name: FK_NAME, reverse_lock_order: true)
end
end
def down
# no-op
# we won't add this again, as it may create problems without an index
end
end

View File

@ -0,0 +1 @@
c643bd5a8781d57cf943170020f44972ad0e06faa1f602b80409eea7704310ee

View File

@ -39401,9 +39401,6 @@ ALTER TABLE ONLY subscription_user_add_on_assignments
ALTER TABLE ONLY approval_project_rules_users
ADD CONSTRAINT fk_0dfcd9e339 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
ALTER TABLE ONLY merge_request_diff_files
ADD CONSTRAINT fk_0e3ba01603 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
ALTER TABLE ONLY ci_runner_projects
ADD CONSTRAINT fk_0e743433ff FOREIGN KEY (runner_id) REFERENCES ci_runners_archived(id) ON DELETE CASCADE;

View File

@ -27148,7 +27148,7 @@ four standard [pagination arguments](#pagination-arguments):
| <a id="groupcustomfieldsactive"></a>`active` | [`Boolean`](#boolean) | Filter for active fields. If `false`, excludes active fields. If `true`, returns only active fields. |
| <a id="groupcustomfieldsfieldtype"></a>`fieldType` | [`CustomFieldType`](#customfieldtype) | Filter for selected field type. |
| <a id="groupcustomfieldssearch"></a>`search` | [`String`](#string) | Search query for custom field name. |
| <a id="groupcustomfieldsworkitemtypeids"></a>`workItemTypeIds` | [`[WorkItemsTypeID!]`](#workitemstypeid) | Filter custom fields associated to any of the given work item types. If empty, returns custom fields not associated to any work item type. |
| <a id="groupcustomfieldsworkitemtypeid"></a>`workItemTypeId` | [`WorkItemsTypeID`](#workitemstypeid) | Filter custom fields associated to the given work item type. |
##### `Group.customizableDashboardVisualizations`
@ -32174,7 +32174,7 @@ four standard [pagination arguments](#pagination-arguments):
| <a id="namespacecustomfieldsactive"></a>`active` | [`Boolean`](#boolean) | Filter for active fields. If `false`, excludes active fields. If `true`, returns only active fields. |
| <a id="namespacecustomfieldsfieldtype"></a>`fieldType` | [`CustomFieldType`](#customfieldtype) | Filter for selected field type. |
| <a id="namespacecustomfieldssearch"></a>`search` | [`String`](#string) | Search query for custom field name. |
| <a id="namespacecustomfieldsworkitemtypeids"></a>`workItemTypeIds` | [`[WorkItemsTypeID!]`](#workitemstypeid) | Filter custom fields associated to any of the given work item types. If empty, returns custom fields not associated to any work item type. |
| <a id="namespacecustomfieldsworkitemtypeid"></a>`workItemTypeId` | [`WorkItemsTypeID`](#workitemstypeid) | Filter custom fields associated to the given work item type. |
##### `Namespace.importSourceUsers`

View File

@ -367,7 +367,7 @@ On GitLab Self-Managed, by default the `fallback_behavior` field is available. T
{{< history >}}
- [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/498624) support for use in pipeline execution policies in GitLab 17.10 [with a flag](../../../administration/feature_flags.md) named `unblock_rules_using_pipeline_execution_policies`. Disabled by default.
- [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/498624) support for use in pipeline execution policies in GitLab 17.10 [with a flag](../../../administration/feature_flags.md) named `unblock_rules_using_pipeline_execution_policies`. Enabled by default.
{{< /history >}}

View File

@ -546,9 +546,11 @@ function run_with_custom_exit_code() {
set +e # temporarily disable exit on error to prevent premature exit
# runs command passed in as argument, save standard error and standard output
output=$("$@" 2>&1)
output=$(set -e; "$@" 2>&1)
initial_exit_code=$?
echo "initial_exit_code: $initial_exit_code"
local trace_file="stdout_stderr_log.out"
echo "$output" | tee "$trace_file"

View File

@ -2,10 +2,10 @@
require 'spec_helper'
RSpec.describe DiffsStreamResource, type: :controller, feature_category: :source_code_management do
RSpec.describe RapidDiffsResource, type: :controller, feature_category: :source_code_management do
subject(:controller) do
Class.new(ApplicationController) do
include DiffsStreamResource
include RapidDiffsResource
def call_diffs_stream_resource_url(resource, offset, diff_view)
diffs_stream_resource_url(resource, offset, diff_view)
@ -14,6 +14,10 @@ RSpec.describe DiffsStreamResource, type: :controller, feature_category: :source
def call_diffs_stream_url(resource, offset, diff_view)
diffs_stream_url(resource, offset, diff_view)
end
def call_diffs_resource
diffs_resource
end
end
end
@ -40,4 +44,12 @@ RSpec.describe DiffsStreamResource, type: :controller, feature_category: :source
end
end
end
describe '#diffs_resource' do
it 'raises NotImplementedError' do
expect do
controller.new.call_diffs_resource
end.to raise_error(NotImplementedError)
end
end
end

View File

@ -771,5 +771,32 @@ RSpec.describe Projects::CompareController, feature_category: :source_code_manag
expect(response).to have_gitlab_http_status(:not_found)
end
end
describe 'Get #diff_files_metadata' do
let(:params) do
{
namespace_id: project.namespace,
project_id: project,
from: from,
to: to
}
end
let(:send_request) { get :diff_files_metadata, params: params }
context 'with valid params' do
let(:from) { '6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9' }
let(:to) { '5937ac0a7beb003549fc5fd26fc247adbce4a52e' }
include_examples 'diff files metadata'
end
context 'with invalid params' do
let(:from) { '0123456789' }
let(:to) { '987654321' }
include_examples 'missing diff files metadata'
end
end
end
end

View File

@ -31,7 +31,6 @@ RSpec.describe 'Database schema',
ci_sources_pipelines: [%w[source_partition_id source_pipeline_id], %w[partition_id pipeline_id]],
ci_sources_projects: [%w[partition_id pipeline_id]], # index on pipeline_id is sufficient
ci_stages: [%w[partition_id pipeline_id]], # the index on pipeline_id is sufficient
merge_request_diff_files: [%w[project_id]], # async index to be created - https://gitlab.com/gitlab-org/gitlab/-/issues/523103
notes: %w[namespace_id], # this index is added in an async manner, hence it needs to be ignored in the first phase.
p_ci_build_trace_metadata: [%w[partition_id build_id], %w[partition_id trace_artifact_id]], # the index on build_id is enough
p_ci_builds: [%w[partition_id stage_id], %w[partition_id execution_config_id], %w[auto_canceled_by_partition_id auto_canceled_by_id], %w[upstream_pipeline_partition_id upstream_pipeline_id], %w[partition_id commit_id]], # https://gitlab.com/gitlab-org/gitlab/-/merge_requests/142804#note_1745483081
@ -172,6 +171,7 @@ RSpec.describe 'Database schema',
merge_request_cleanup_schedules: %w[project_id],
merge_requests_compliance_violations: %w[target_project_id],
merge_request_diffs: %w[project_id],
merge_request_diff_files: %w[project_id],
merge_request_diff_commits: %w[commit_author_id committer_id],
# merge_request_diff_commits_b5377a7a34 is the temporary table for the merge_request_diff_commits partitioning
# backfill. It will get foreign keys after the partitioning is finished.

View File

@ -1,53 +0,0 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Resolvers::WorkItems::Widgets::StatusResolver, feature_category: :team_planning do
include GraphqlHelpers
let_it_be(:group) { create(:group) }
let_it_be(:project) { create(:project, group: group) }
let_it_be(:current_user) { create(:user) }
let_it_be(:task_type) { create(:work_item_type, :task) }
let_it_be(:widget_definition) do
create(:widget_definition, widget_type: :status, work_item_type: task_type, name: 'TesT Widget')
end
shared_examples 'does not return system defined statuses' do
it 'returns an empty array' do
expect(resolve_statuses&.items).to eq([])
end
end
describe '#resolve' do
let(:resource_parent) { group }
context 'with group' do
it_behaves_like 'does not return system defined statuses'
end
context 'with project' do
let(:resource_parent) { project }
it_behaves_like 'does not return system defined statuses'
end
context 'with unsupported namespace' do
let(:resource_parent) { current_user.namespace }
it_behaves_like 'does not return system defined statuses'
end
context 'with work_item_status feature flag disabled' do
before do
stub_feature_flags(work_item_status: false)
end
it_behaves_like 'does not return system defined statuses'
end
end
def resolve_statuses(args = {}, context = { current_user: current_user, resource_parent: resource_parent })
resolve(described_class, obj: widget_definition, args: args, ctx: context)
end
end

View File

@ -29,7 +29,7 @@ RSpec.describe GitlabSchema.types['Group'], feature_category: :groups_and_projec
contact_state_counts contacts work_item_types
recent_issue_boards ci_variables releases environment_scopes work_items autocomplete_users
lock_math_rendering_limits_enabled math_rendering_limits_enabled created_at updated_at
organization_edit_path is_linked_to_subscription allowed_statuses
organization_edit_path is_linked_to_subscription
]
expect(described_class).to include_graphql_fields(*expected_fields)

View File

@ -12,7 +12,7 @@ RSpec.describe GitlabSchema.types['Namespace'] do
id name path full_name full_path achievements_path description description_html visibility
lfs_enabled request_access_enabled projects root_storage_statistics shared_runners_setting
timelog_categories achievements work_item pages_deployments import_source_users work_item_types
sidebar work_item_description_templates allowed_statuses ci_cd_settings avatar_url
sidebar work_item_description_templates ci_cd_settings avatar_url
]
expect(described_class).to include_graphql_fields(*expected_fields)

View File

@ -46,8 +46,8 @@ RSpec.describe GitlabSchema.types['Project'], feature_category: :groups_and_proj
ci_cd_settings detailed_import_status value_streams ml_models
allows_multiple_merge_request_assignees allows_multiple_merge_request_reviewers is_forked
protectable_branches available_deploy_keys explore_catalog_path
container_protection_tag_rules allowed_statuses
pages_force_https pages_use_unique_domain ci_pipeline_creation_request ci_pipeline_creation_inputs
container_protection_tag_rules pages_force_https pages_use_unique_domain ci_pipeline_creation_request
ci_pipeline_creation_inputs
]
expect(described_class).to include_graphql_fields(*expected_fields)

View File

@ -26,12 +26,6 @@ RSpec.describe Types::WorkItems::WidgetDefinitionInterface, feature_category: :t
it { is_expected.to eq(Types::WorkItems::WidgetDefinitions::HierarchyType) }
end
context 'for status widget' do
let(:object) { build(:widget_definition, widget_type: 'status') }
it { is_expected.to eq(Types::WorkItems::WidgetDefinitions::StatusType) }
end
context 'for other widgets' do
let(:object) { build(:widget_definition, widget_type: 'description') }

View File

@ -30,7 +30,6 @@ RSpec.describe Types::WorkItems::WidgetInterface, feature_category: :team_planni
WorkItems::Widgets::Designs | Types::WorkItems::Widgets::DesignsType
WorkItems::Widgets::CrmContacts | Types::WorkItems::Widgets::CrmContactsType
WorkItems::Widgets::EmailParticipants | Types::WorkItems::Widgets::EmailParticipantsType
WorkItems::Widgets::Status | Types::WorkItems::Widgets::StatusType
WorkItems::Widgets::ErrorTracking | Types::WorkItems::Widgets::ErrorTrackingType
end

View File

@ -1,13 +0,0 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Types::WorkItems::Widgets::StatusType, feature_category: :team_planning do
it 'exposes the expected fields' do
expected_fields = %i[id name icon_name color position]
expected_fields.each do |field|
expect(described_class).to have_graphql_field(field)
end
end
end

View File

@ -22,7 +22,6 @@ RSpec.describe WorkItems::WidgetDefinition, feature_category: :team_planning do
::WorkItems::Widgets::Development,
::WorkItems::Widgets::CrmContacts,
::WorkItems::Widgets::EmailParticipants,
::WorkItems::Widgets::Status,
::WorkItems::Widgets::ErrorTracking
]
@ -37,7 +36,8 @@ RSpec.describe WorkItems::WidgetDefinition, feature_category: :team_planning do
::WorkItems::Widgets::TestReports,
::WorkItems::Widgets::Color,
::WorkItems::Widgets::CustomFields,
::WorkItems::Widgets::Vulnerabilities
::WorkItems::Widgets::Vulnerabilities,
::WorkItems::Widgets::Status
]
end

View File

@ -1513,37 +1513,6 @@ RSpec.describe 'Query.work_item(id)', feature_category: :team_planning do
end
end
describe 'status widget' do
let_it_be(:task_work_item) { create(:work_item, :task, project: project) }
let_it_be(:global_id) { task_work_item.to_global_id }
let(:work_item_fields) do
<<~GRAPHQL
id
widgets {
type
... on WorkItemWidgetStatus {
id
name
iconName
}
}
GRAPHQL
end
it 'returns mock status data' do
expect(work_item_data).to include(
'widgets' => array_including(
hash_including(
'type' => 'STATUS',
'id' => 'gid://gitlab/WorkItems::Widgets::Status/10',
'name' => 'Status',
'iconName' => 'status icon'
)
)
)
end
end
context 'when an Issue Global ID is provided' do
let(:global_id) { Issue.find(work_item.id).to_gid.to_s }

View File

@ -210,17 +210,16 @@ RSpec.describe Organizations::OrganizationsController, feature_category: :cell d
context 'when organization has multiple projects' do
let_it_be(:stale_project) do
create(:project, organization: organization, last_activity_at: Date.yesterday)
create(:project, :public, organization: organization, last_activity_at: 3.days.ago)
.tap { |project| create(:project_member, :developer, user:, project:) }
end
let_it_be(:recently_updated_project) do
create(:project, organization: organization, last_activity_at: Date.current)
create(:project, :public, organization: organization, last_activity_at: Date.current)
.tap { |project| create(:project_member, :developer, user:, project:) }
end
before_all do
stale_project.add_developer(user)
recently_updated_project.add_developer(user)
sign_in(user)
end

View File

@ -94,6 +94,34 @@ RSpec.describe Projects::CommitController, feature_category: :source_code_manage
end
end
describe 'GET #diff_files_metadata' do
let(:params) do
{
namespace_id: project.namespace,
project_id: project,
id: sha
}
end
let(:send_request) { get diff_files_metadata_namespace_project_commit_path(params) }
before do
sign_in(user)
end
context 'with valid params' do
let(:sha) { '7d3b0f7cff5f37573aea97cebfd5692ea1689924' }
include_examples 'diff files metadata'
end
context 'with invalid params' do
let(:sha) { '0123456789' }
include_examples 'missing diff files metadata'
end
end
describe 'GET #diff_files' do
let(:master_pickable_sha) { '7d3b0f7cff5f37573aea97cebfd5692ea1689924' }
let(:format) { :html }

View File

@ -76,6 +76,36 @@ RSpec.describe 'merge requests creations', feature_category: :code_review_workfl
end
end
end
describe 'GET new/diff_files_metadata' do
let(:send_request) { get namespace_project_new_merge_request_diff_files_metadata_path(params) }
context 'with valid params' do
let(:params) do
{
namespace_id: project.namespace.to_param,
project_id: project,
merge_request: {
source_branch: 'fix',
target_branch: 'master'
}
}
end
include_examples 'diff files metadata'
end
context 'with invalid params' do
let(:params) do
{
namespace_id: project.namespace.to_param,
project_id: project
}
end
include_examples 'missing diff files metadata'
end
end
end
describe 'POST /:namespace/:project/merge_requests' do

View File

@ -286,6 +286,28 @@ RSpec.describe Projects::MergeRequestsController, feature_category: :source_code
end
end
describe 'GET #diff_files_metadata' do
before do
project.add_developer(user)
login_as(user)
end
let(:send_request) { get diff_files_metadata_project_merge_request_path(project, merge_request) }
include_examples 'diff files metadata'
context 'when merge_request_diff does not exist' do
let(:merge_request) { create(:merge_request, :skip_diff_creation, author: user) }
let(:project) { merge_request.project }
it 'returns an empty array' do
send_request
expect(json_response['diff_files']).to be_empty
end
end
end
describe 'PUT #update' do
before do
project.add_developer(user)

View File

@ -19,11 +19,6 @@ RSpec.shared_context 'with work item types request context' do
nodes { id name }
}
}
... on WorkItemWidgetDefinitionStatus {
allowedStatuses {
nodes { id name iconName color position }
}
}
}
supportedConversionTypes {
id
@ -70,11 +65,6 @@ RSpec.shared_context 'with work item types request context' do
next hierarchy_widget_attributes(work_item_type, base_attributes, resource_parent)
end
if widget == WorkItems::Widgets::Status
next status_widget_attributes(work_item_type,
base_attributes, resource_parent)
end
next base_attributes unless widget_attributes[widget.type]
base_attributes.merge(widget_attributes[widget.type])
@ -95,50 +85,4 @@ RSpec.shared_context 'with work item types request context' do
base_attributes
.merge({ 'allowedChildTypes' => { 'nodes' => child_types }, 'allowedParentTypes' => { 'nodes' => parent_types } })
end
def status_widget_attributes(_work_item_type, base_attributes, resource_parent)
unless resource_parent&.root_ancestor&.try(:work_item_status_feature_available?)
return base_attributes.merge({ 'allowedStatuses' => { 'nodes' => [] } })
end
statuses = [
{
'id' => 'gid://gitlab/WorkItems::Statuses::SystemDefined::Status/1',
'name' => 'To do',
'iconName' => 'status-waiting',
'color' => '#535158',
'position' => 0
},
{
'id' => 'gid://gitlab/WorkItems::Statuses::SystemDefined::Status/2',
'name' => 'In progress',
'iconName' => 'status-running',
'color' => '#0b5cad',
'position' => 0
},
{
'id' => 'gid://gitlab/WorkItems::Statuses::SystemDefined::Status/3',
'name' => 'Done',
'iconName' => 'status-success',
'color' => '#23663b',
'position' => 0
},
{
'id' => 'gid://gitlab/WorkItems::Statuses::SystemDefined::Status/4',
'name' => "Won't do",
'iconName' => 'status-cancelled',
'color' => '#ae1901',
'position' => 0
},
{
'id' => 'gid://gitlab/WorkItems::Statuses::SystemDefined::Status/5',
'name' => 'Duplicate',
'iconName' => 'status-cancelled',
'color' => '#ae1901',
'position' => 10
}
]
base_attributes.merge({ 'allowedStatuses' => { 'nodes' => statuses } })
end
end

View File

@ -0,0 +1,30 @@
# frozen_string_literal: true
RSpec.shared_examples 'diff files metadata' do
it 'returns a json response' do
send_request
expect(response).to have_gitlab_http_status(:success)
expect(json_response['diff_files']).to be_an Array
end
context 'when the rapid_diffs feature flag is disabled' do
before do
stub_feature_flags(rapid_diffs: false)
end
it 'returns a 404 status' do
send_request
expect(response).to have_gitlab_http_status(:not_found)
end
end
end
RSpec.shared_examples 'missing diff files metadata' do
it 'returns a 404 status' do
send_request
expect(response).to have_gitlab_http_status(:not_found)
end
end

View File

@ -33,25 +33,6 @@ RSpec.shared_examples 'graphql work item type list request spec' do |context_nam
)
end
if Gitlab.ee?
it 'returns the allowed custom statuses' do
stub_licensed_features(work_item_custom_status: true)
post_graphql(query, current_user: current_user)
work_item_types = graphql_data_at(parent_key, :workItemTypes, :nodes)
status_widgets = work_item_types.flat_map do |work_item_type|
work_item_type['widgetDefinitions'].select { |widget| widget['type'] == 'STATUS' }
end
expect(status_widgets).to be_present
status_widgets.each do |widget|
expect(widget['allowedStatuses']).to be_present
expect(widget['allowedStatuses']['nodes']).to all(include('id', 'name', 'iconName', 'color',
'position'))
end
end
end
it 'prevents N+1 queries' do
# Destroy 2 existing types
WorkItems::Type.by_type([:issue, :task]).delete_all