Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2025-04-30 03:10:38 +00:00
parent 12fc930567
commit 696edc7f23
40 changed files with 163 additions and 114 deletions

View File

@ -12,7 +12,6 @@ Gitlab/FeatureFlagKeyDynamic:
- 'app/workers/concerns/worker_attributes.rb'
- 'app/workers/loose_foreign_keys/cleanup_worker.rb'
- 'ee/app/graphql/resolvers/ai/user_available_features_resolver.rb'
- 'ee/app/graphql/resolvers/ai/user_code_suggestions_contexts_resolver.rb'
- 'ee/app/models/concerns/geo/verifiable_replicator.rb'
- 'ee/app/models/members/member_role.rb'
- 'ee/app/services/search/zoekt/info_service.rb'

View File

@ -4,9 +4,6 @@ Layout/LineBreakAfterFinalMixin:
Exclude:
- 'app/graphql/resolvers/integrations/exclusions_resolver.rb'
- 'app/graphql/resolvers/projects/deploy_key_resolver.rb'
- 'app/models/alert_management/metric_image.rb'
- 'app/models/protected_branch/merge_access_level.rb'
- 'app/models/protected_branch/push_access_level.rb'
- 'app/policies/project_member_policy.rb'
- 'app/serializers/cluster_serializer.rb'
- 'app/serializers/container_repositories_serializer.rb'
@ -41,21 +38,7 @@ Layout/LineBreakAfterFinalMixin:
- 'app/workers/stuck_export_jobs_worker.rb'
- 'app/workers/user_status_cleanup/batch_worker.rb'
- 'app/workers/users/create_statistics_worker.rb'
- 'db/migrate/20240213223630_add_duo_features_enabled_cascading_setting.rb'
- 'db/post_migrate/20240419122328_swap_vulnerability_feedback_pipeline_id_convert_to_bigint.rb'
- 'db/post_migrate/20240419131607_swap_packages_build_infos_pipeline_id_convert_to_bigint.rb'
- 'db/post_migrate/20240422080018_swap_merge_trains_pipeline_id_convert_to_bigint.rb'
- 'db/post_migrate/20240424111535_swap_merge_request_metrics_pipeline_id_convert_to_bigint.rb'
- 'db/post_migrate/20240513111937_swap_columns_for_p_ci_builds_trigger_request_and_erased_by.rb'
- 'db/post_migrate/20240514081440_swap_vulnerability_occurrence_pipelines_pipeline_id_convert_to_bigint.rb'
- 'ee/app/controllers/explore/dependencies_controller.rb'
- 'ee/app/finders/security/pipeline_vulnerabilities_finder.rb'
- 'ee/app/graphql/subscriptions/ai_completion_response.rb'
- 'ee/app/models/approval_project_rules_protected_branch.rb'
- 'ee/app/models/approval_rules/approval_group_rule.rb'
- 'ee/app/models/approval_rules/approval_group_rules_protected_branch.rb'
- 'ee/app/models/vulnerabilities/scanner.rb'
- 'ee/app/models/vulnerabilities/statistic.rb'
- 'ee/app/services/ee/ip_restrictions/update_service.rb'
- 'ee/app/services/gitlab_subscriptions/trials/base_apply_trial_service.rb'
- 'ee/app/services/incident_management/oncall_rotations/edit_service.rb'
@ -79,7 +62,6 @@ Layout/LineBreakAfterFinalMixin:
- 'ee/lib/api/resource_iteration_events.rb'
- 'ee/lib/api/resource_weight_events.rb'
- 'ee/lib/ee/api/entities/project_push_rule.rb'
- 'ee/lib/ee/gitlab/background_migration/create_compliance_standards_adherence.rb'
- 'ee/lib/gitlab/auth/group_saml/identity_linker.rb'
- 'ee/lib/gitlab/llm/chain/tools/explain_code/prompts/anthropic.rb'
- 'ee/lib/gitlab/search/zoekt/client.rb'
@ -103,8 +85,6 @@ Layout/LineBreakAfterFinalMixin:
- 'lib/feature.rb'
- 'lib/gitlab/auth/current_user_mode.rb'
- 'lib/gitlab/auth/otp/strategies/forti_token_cloud.rb'
- 'lib/gitlab/background_migration/backfill_draft_status_on_merge_requests_with_corrected_regex.rb'
- 'lib/gitlab/background_migration/update_jira_tracker_data_deployment_type_based_on_url.rb'
- 'lib/gitlab/ci/config/interpolation/config.rb'
- 'lib/gitlab/cluster/rack_timeout_observer.rb'
- 'lib/gitlab/etag_caching/router/graphql.rb'

View File

@ -142,12 +142,12 @@ export default {
},
detailsPath() {
if (this.isLink) {
return this.status.detailsPath;
return this.status.detailsPath || this.status.deploymentDetailsPath;
}
return null;
},
hasDetails() {
return this.status.hasDetails;
return this.status.hasDetails || this.status.deploymentDetailsPath;
},
hasRetryAction() {
return Boolean(this.job?.status?.action?.title === RETRY_ACTION_TITLE);
@ -221,7 +221,7 @@ export default {
* @return {Boolean}
*/
hasAction() {
return this.job.status && this.job.status.action && this.job.status.action.path;
return this.job.status?.action?.path && this.job.status?.action?.icon;
},
hasManualConfirmationMessage() {
return this.job.status.action.confirmationMessage !== null;

View File

@ -325,7 +325,7 @@ export default {
@mouseover="setActionTooltip(true)"
@mouseout="setActionTooltip(false)"
>
<gl-icon :name="action.icon" size="12" />
<gl-icon :name="action.icon" :size="12" />
</gl-button>
</div>
</div>

View File

@ -97,6 +97,7 @@
}
.rd-line-number {
position: relative;
padding: 0 10px 0 5px;
text-align: right;
background-color: var(--code-line-nubmer-background-color, $white);
@ -146,6 +147,12 @@
&::before {
content: attr(data-line-number);
}
&::after {
content: '';
position: absolute;
inset: 0 -1px;
}
}
.rd-line-content,

View File

@ -412,8 +412,7 @@ class IssuableFinder
strong_memoize(:label_filter) do
Issuables::LabelFilter.new(
params: original_params,
project: params.project,
group: params.group
parent: params.parent
)
end
end
@ -493,15 +492,19 @@ class IssuableFinder
end
def by_crm_contact(items)
return items unless can_filter_by_crm_contact?
Issuables::CrmContactFilter.new(params: original_params).filter(items)
Issuables::CrmContactFilter.new(
params: original_params,
parent: params.parent,
current_user: current_user
).filter(items)
end
def by_crm_organization(items)
return items unless can_filter_by_crm_organization?
Issuables::CrmOrganizationFilter.new(params: original_params).filter(items)
Issuables::CrmOrganizationFilter.new(
params: original_params,
parent: params.parent,
current_user: current_user
).filter(items)
end
def by_subscribed(items)
@ -516,18 +519,4 @@ class IssuableFinder
items
end
end
def can_filter_by_crm_contact?
current_user&.can?(:read_crm_contact, crm_group)
end
def can_filter_by_crm_organization?
current_user&.can?(:read_crm_organization, crm_group)
end
def crm_group
strong_memoize(:crm_group) do
params.group&.crm_group || params.project&.crm_group
end
end
end

View File

@ -2,13 +2,13 @@
module Issuables
class BaseFilter
attr_reader :params
FILTER_NONE = 'none'
FILTER_ANY = 'any'
def initialize(params:)
def initialize(params:, parent: nil, current_user: nil)
@params = params
@parent = parent
@current_user = current_user
end
def filter
@ -17,6 +17,8 @@ module Issuables
private
attr_reader :params, :parent, :current_user
def or_params
params[:or]
end

View File

@ -9,6 +9,7 @@ module Issuables
# rubocop: disable CodeReuse/ActiveRecord
def by_crm_contact(issuables)
return issuables if params[:crm_contact_id].blank?
return issuables unless current_user&.can?(:read_crm_contact, parent&.crm_group)
condition = CustomerRelations::IssueContact
.where(contact_id: params[:crm_contact_id])

View File

@ -9,6 +9,7 @@ module Issuables
# rubocop: disable CodeReuse/ActiveRecord
def by_crm_organization(issuables)
return issuables if params[:crm_organization_id].blank?
return issuables unless current_user&.can?(:read_crm_organization, parent&.crm_group)
condition = CustomerRelations::IssueContact
.joins(:contact)

View File

@ -5,13 +5,6 @@ module Issuables
include Gitlab::Utils::StrongMemoize
extend Gitlab::Cache::RequestCache
def initialize(project:, group:, **kwargs)
@project = project
@group = group
super(**kwargs)
end
def filter(issuables)
filtered = by_label(issuables)
filtered = by_label_union(filtered)
@ -40,8 +33,6 @@ module Issuables
private
attr_reader :project, :group
# rubocop: disable CodeReuse/ActiveRecord
def by_label(issuables)
return issuables unless label_names_from_params.present?
@ -195,7 +186,7 @@ module Issuables
def root_namespace
strong_memoize(:root_namespace) do
(@project || @group)&.root_ancestor
parent&.root_ancestor
end
end
end

View File

@ -4,9 +4,7 @@ module Issues
class ConfidentialityFilter < Issuables::BaseFilter
CONFIDENTIAL_ACCESS_LEVEL = Gitlab::Access::PLANNER
def initialize(current_user:, parent:, assignee_filter:, related_groups: nil, **kwargs)
@current_user = current_user
@parent = parent
def initialize(assignee_filter:, related_groups: nil, **kwargs)
@assignee_filter = assignee_filter
@related_groups = related_groups
@ -17,14 +15,14 @@ module Issues
issues = issues.confidential_only if params[:confidential]
# We do not need to do the confidentiality check if we know that only public issues will be returned
return issues.public_only if @current_user.blank? || params[:confidential] == false
return issues.public_only if current_user.blank? || params[:confidential] == false
return issues if user_can_see_all_confidential_issues?
issues.public_only.or(
issues.confidential_only.merge(
issues.authored(@current_user)
.or(issues.assigned_to(@current_user))
issues.authored(current_user)
.or(issues.assigned_to(current_user))
.or(access_to_parent_exists(issues))
)
).allow_cross_joins_across_databases(url: 'https://gitlab.com/gitlab-org/gitlab/-/issues/422045')
@ -33,18 +31,18 @@ module Issues
private
def user_can_see_all_confidential_issues?
Ability.allowed?(@current_user, :read_all_resources) ||
Ability.allowed?(@current_user, :read_confidential_issues, @parent) ||
Ability.allowed?(current_user, :read_all_resources) ||
Ability.allowed?(current_user, :read_confidential_issues, parent) ||
# If already filtering by assignee we can skip confidentiality checks since a user
# can always see confidential issues assigned to them. This is just an
# optimization since a very common use case of this Finder is to load the
# count of issues assigned to the user for the header bar.
@assignee_filter.includes_user?(@current_user)
@assignee_filter.includes_user?(current_user)
end
def access_to_parent_exists(issues)
access_to_project_level_issue_exists = issues.where_exists(
@current_user.authorizations_for_projects(
current_user.authorizations_for_projects(
min_access_level: CONFIDENTIAL_ACCESS_LEVEL,
related_project_column: 'issues.project_id'
)
@ -55,7 +53,7 @@ module Issues
access_to_project_level_issue_exists.project_level.or(
issues.group_level.in_namespaces(
Group.id_in(
Group.groups_user_can(@related_groups, @current_user, :read_confidential_issues, same_root: true)
Group.groups_user_can(@related_groups, current_user, :read_confidential_issues, same_root: true)
)
)
)

View File

@ -129,6 +129,7 @@ query getPipelineDetails($projectPath: ID!, $iid: ID!) {
tooltip
hasDetails
detailsPath
deploymentDetailsPath
group
label
text

View File

@ -11,6 +11,8 @@ module Types
null: true,
calls_gitaly: true,
description: 'Action information for the status. This includes method, button title, icon, path, and title.'
field :deployment_details_path, GraphQL::Types::String, null: true,
description: 'Path of the deployment details for the status.'
field :details_path, GraphQL::Types::String, null: true,
description: 'Path of the details for the status.'
field :favicon, GraphQL::Types::String, null: true,

View File

@ -3,6 +3,7 @@
module AlertManagement
class MetricImage < ApplicationRecord
include MetricImageUploading
self.table_name = 'alert_management_alert_metric_images'
belongs_to :alert, class_name: 'AlertManagement::Alert', foreign_key: 'alert_id', inverse_of: :metric_images

View File

@ -2,6 +2,7 @@
class ProtectedBranch::MergeAccessLevel < ApplicationRecord
include ProtectedBranchAccess
# default value for the access_level column
GITLAB_DEFAULT_ACCESS_LEVEL = Gitlab::Access::MAINTAINER
end

View File

@ -3,6 +3,7 @@
class ProtectedBranch::PushAccessLevel < ApplicationRecord
include ProtectedBranchAccess
include ProtectedRefDeployKeyAccess
# default value for the access_level column
GITLAB_DEFAULT_ACCESS_LEVEL = Gitlab::Access::MAINTAINER

View File

@ -147,16 +147,8 @@ module Boards
# rubocop: enable CodeReuse/ActiveRecord
def labels_filter
Issuables::LabelFilter.new(params: {}, project: project, group: group)
Issuables::LabelFilter.new(params: {}, parent: parent)
end
strong_memoize_attr :labels_filter
def group
parent if parent.is_a?(Group)
end
def project
parent if parent.is_a?(Project)
end
end
end

View File

@ -95,6 +95,8 @@
- 2
- - authorized_projects
- 2
- - authz_ldap_admin_role
- 1
- - auto_devops
- 2
- - auto_merge

View File

@ -2,6 +2,7 @@
class AddDuoFeaturesEnabledCascadingSetting < Gitlab::Database::Migration[2.2]
include Gitlab::Database::MigrationHelpers::CascadingNamespaceSettings
enable_lock_retries!
milestone '16.10'

View File

@ -2,6 +2,7 @@
class SwapVulnerabilityFeedbackPipelineIdConvertToBigint < Gitlab::Database::Migration[2.2]
include Gitlab::Database::MigrationHelpers::Swapping
milestone '17.0'
disable_ddl_transaction!

View File

@ -2,6 +2,7 @@
class SwapPackagesBuildInfosPipelineIdConvertToBigint < Gitlab::Database::Migration[2.2]
include Gitlab::Database::MigrationHelpers::Swapping
milestone '17.0'
disable_ddl_transaction!

View File

@ -2,6 +2,7 @@
class SwapMergeTrainsPipelineIdConvertToBigint < Gitlab::Database::Migration[2.2]
include Gitlab::Database::MigrationHelpers::Swapping
milestone '17.0'
disable_ddl_transaction!

View File

@ -2,6 +2,7 @@
class SwapMergeRequestMetricsPipelineIdConvertToBigint < Gitlab::Database::Migration[2.2]
include Gitlab::Database::MigrationHelpers::Swapping
milestone '17.0'
disable_ddl_transaction!

View File

@ -2,6 +2,7 @@
class SwapColumnsForPCiBuildsTriggerRequestAndErasedBy < Gitlab::Database::Migration[2.2]
include ::Gitlab::Database::MigrationHelpers::Swapping
milestone '17.1'
disable_ddl_transaction!

View File

@ -2,6 +2,7 @@
class SwapVulnerabilityOccurrencePipelinesPipelineIdConvertToBigint < Gitlab::Database::Migration[2.2]
include Gitlab::Database::MigrationHelpers::Swapping
milestone '17.1'
disable_ddl_transaction!

View File

@ -1948,6 +1948,29 @@ Input type: `AddProjectToSecurityDashboardInput`
| <a id="mutationaddprojecttosecuritydashboarderrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
| <a id="mutationaddprojecttosecuritydashboardproject"></a>`project` | [`Project`](#project) | Project that was added to the Instance Security Dashboard. |
### `Mutation.adminRolesLdapSync`
{{< details >}}
**Introduced** in GitLab 18.0.
**Status**: Experiment.
{{< /details >}}
Input type: `AdminRolesLdapSyncInput`
#### Arguments
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="mutationadminrolesldapsyncclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
#### Fields
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="mutationadminrolesldapsyncclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
| <a id="mutationadminrolesldapsyncerrors"></a>`errors` | [`[String!]`](#string) | Errors encountered during operation. |
| <a id="mutationadminrolesldapsyncsuccess"></a>`success` | [`Boolean`](#boolean) | Whether the sync was successfully enqueued. |
### `Mutation.adminSidekiqQueuesDeleteJobs`
Input type: `AdminSidekiqQueuesDeleteJobsInput`
@ -25892,6 +25915,7 @@ Details of the import status of a project.
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="detailedstatusaction"></a>`action` | [`StatusAction`](#statusaction) | Action information for the status. This includes method, button title, icon, path, and title. |
| <a id="detailedstatusdeploymentdetailspath"></a>`deploymentDetailsPath` | [`String`](#string) | Path of the deployment details for the status. |
| <a id="detailedstatusdetailspath"></a>`detailsPath` | [`String`](#string) | Path of the details for the status. |
| <a id="detailedstatusfavicon"></a>`favicon` | [`String`](#string) | Favicon of the status. |
| <a id="detailedstatusgroup"></a>`group` {{< icon name="warning-solid" >}} | [`String`](#string) | **Deprecated** in GitLab 16.4. The `group` attribute is deprecated. Use `name` instead. |

View File

@ -65,7 +65,7 @@ Test the regex patterns carefully. Tool output formats can change over time, and
| Tool | Language | Command | Regex pattern |
|------------|----------|----------------|---------------|
| pytest-cov | Python | `pytest --cov` | `/TOTAL.*? (100(?:\.0+)?\%\|[1-9]?\d(?:\.\d+)?\%)$/` |
| pytest-cov | Python | `pytest --cov` | `/TOTAL.*? (100(?:\.0+)?\%\\|[1-9]?\d(?:\.\d+)?\%)$/` |
| Simplecov | Ruby | `rspec spec` | `/\(\d+.\d+\%\) covered/` |
{{< /tab >}}
@ -84,7 +84,7 @@ Test the regex patterns carefully. Tool output formats can change over time, and
| Tool | Language | Command | Regex pattern |
|-----------|-------------|------------------------------------|---------------|
| JaCoCo | Java/Kotlin | `./gradlew test jacocoTestReport` | `/Total.*?([0-9]{1,3})%/` |
| Scoverage | Scala | `sbt coverage test coverageReport` | `/(?i)total.*? (100(?:\.0+)?\%\|[1-9]?\d(?:\.\d+)?\%)$/` |
| Scoverage | Scala | `sbt coverage test coverageReport` | `/(?i)total.*? (100(?:\.0+)?\%\\|[1-9]?\d(?:\.\d+)?\%)$/` |
{{< /tab >}}
@ -131,7 +131,7 @@ Test the regex patterns carefully. Tool output formats can change over time, and
| Tool | Command | Regex pattern |
|-------------|--------------------|---------------|
| excoveralls | None | `/\[TOTAL\]\s+(\d+\.\d+)%/` |
| mix | `mix test --cover` | `/\d+.\d+\%\s+\|\s+Total/` |
| mix | `mix test --cover` | `/\d+.\d+\%\s+\\|\s+Total/` |
{{< /tab >}}

View File

@ -70,8 +70,7 @@ module Gitlab
LabelFilter.new(
stage: stage,
params: params,
project: nil,
group: root_ancestor
parent: root_ancestor
).filter(query)
end

View File

@ -8,10 +8,10 @@ module Gitlab
class LabelFilter < Issuables::LabelFilter
extend ::Gitlab::Utils::Override
def initialize(stage:, project:, group:, **kwargs)
def initialize(stage:, **kwargs)
@stage = stage
super(project: project, group: group, **kwargs)
super(**kwargs)
end
private

View File

@ -9,6 +9,7 @@ module Gitlab
# Migration only version of MergeRequest table
class MergeRequest < ::ApplicationRecord
include EachBatch
validates :suggested_reviewers, json_schema: { filename: 'merge_request_suggested_reviewers' }
CORRECTED_REGEXP_STR = "^(\\[draft\\]|\\(draft\\)|draft:|draft|\\[WIP\\]|WIP:|WIP)"

View File

@ -10,6 +10,7 @@ module Gitlab
self.inheritance_column = :_type_disabled
include ::Integrations::BaseDataFields
attr_encrypted :url, encryption_options
attr_encrypted :api_url, encryption_options

View File

@ -91,6 +91,10 @@ module Gitlab
def confirmation_message
nil
end
def deployment_details_path
nil
end
end
end
end

View File

@ -5,6 +5,7 @@ require 'spec_helper'
RSpec.describe Issuables::CrmContactFilter do
let_it_be(:group) { create(:group) }
let_it_be(:project) { create(:project, group: group) }
let_it_be(:developer) { create(:user, developer_of: group) }
let_it_be(:contact1) { create(:contact, group: group) }
let_it_be(:contact2) { create(:contact, group: group) }
@ -14,32 +15,36 @@ RSpec.describe Issuables::CrmContactFilter do
let_it_be(:contact2_issue1) { create(:issue, project: project) }
let_it_be(:issues) { Issue.where(id: [contact1_issue1.id, contact1_issue2.id, contact2_issue1.id]) }
let(:params) { {} }
before_all do
create(:issue_customer_relations_contact, issue: contact1_issue1, contact: contact1)
create(:issue_customer_relations_contact, issue: contact1_issue2, contact: contact1)
create(:issue_customer_relations_contact, issue: contact2_issue1, contact: contact2)
end
subject(:crm_contact_filter) { described_class.new(params: params, parent: group, current_user: developer) }
describe 'when a contact has issues' do
it 'returns all contact1 issues' do
params = { crm_contact_id: contact1.id }
params[:crm_contact_id] = contact1.id
expect(described_class.new(params: params).filter(issues)).to contain_exactly(contact1_issue1, contact1_issue2)
expect(crm_contact_filter.filter(issues)).to contain_exactly(contact1_issue1, contact1_issue2)
end
it 'returns all contact2 issues' do
params = { crm_contact_id: contact2.id }
params[:crm_contact_id] = contact2.id
expect(described_class.new(params: params).filter(issues)).to contain_exactly(contact2_issue1)
expect(crm_contact_filter.filter(issues)).to contain_exactly(contact2_issue1)
end
end
describe 'when a contact has no issues' do
it 'returns no issues' do
contact3 = create(:contact, group: group)
params = { crm_contact_id: contact3.id }
params[:crm_contact_id] = contact3.id
expect(described_class.new(params: params).filter(issues)).to be_empty
expect(crm_contact_filter.filter(issues)).to be_empty
end
end
end

View File

@ -5,6 +5,7 @@ require 'spec_helper'
RSpec.describe Issuables::CrmOrganizationFilter do
let_it_be(:group) { create(:group) }
let_it_be(:project) { create(:project, group: group) }
let_it_be(:developer) { create(:user, developer_of: group) }
let_it_be(:crm_organization1) { create(:crm_organization, group: group) }
let_it_be(:crm_organization2) { create(:crm_organization, group: group) }
@ -17,32 +18,36 @@ RSpec.describe Issuables::CrmOrganizationFilter do
let_it_be(:contact3_issue) { create(:issue, project: project) }
let_it_be(:issues) { Issue.where(id: [contact1_issue.id, contact2_issue.id, contact3_issue.id]) }
let(:params) { {} }
before_all do
create(:issue_customer_relations_contact, issue: contact1_issue, contact: contact1)
create(:issue_customer_relations_contact, issue: contact2_issue, contact: contact2)
create(:issue_customer_relations_contact, issue: contact3_issue, contact: contact3)
end
subject(:crm_organization_filter) { described_class.new(params: params, parent: group, current_user: developer) }
describe 'when an organization has issues' do
it 'returns all crm_organization1 issues' do
params = { crm_organization_id: crm_organization1.id }
params[:crm_organization_id] = crm_organization1.id
expect(described_class.new(params: params).filter(issues)).to contain_exactly(contact1_issue, contact2_issue)
expect(crm_organization_filter.filter(issues)).to contain_exactly(contact1_issue, contact2_issue)
end
it 'returns all crm_organization2 issues' do
params = { crm_organization_id: crm_organization2.id }
params[:crm_organization_id] = crm_organization2.id
expect(described_class.new(params: params).filter(issues)).to contain_exactly(contact3_issue)
expect(crm_organization_filter.filter(issues)).to contain_exactly(contact3_issue)
end
end
describe 'when an organization has no issues' do
it 'returns no issues' do
crm_organization3 = create(:crm_organization, group: group)
params = { crm_organization_id: crm_organization3.id }
params[:crm_organization_id] = crm_organization3.id
expect(described_class.new(params: params).filter(issues)).to be_empty
expect(crm_organization_filter.filter(issues)).to be_empty
end
end
end

View File

@ -11,6 +11,7 @@ import { mountExtended, shallowMountExtended } from 'helpers/vue_test_utils_help
import { stubComponent } from 'helpers/stub_component';
import {
delayedJob,
bridgeJob,
mockJob,
mockJobWithoutDetails,
mockJobWithUnauthorizedAction,
@ -84,6 +85,12 @@ describe('pipeline graph job item', () => {
expect(wrapper.text()).toBe(mockJob.name);
});
it('should use deployment details path as the details path for manual bridge jobs', () => {
createWrapper({ props: { job: bridgeJob } });
expect(findJobItemContent().attributes('href')).toBe(bridgeJob.status.deploymentDetailsPath);
});
});
describe('name without link', () => {

View File

@ -222,6 +222,7 @@ export const wrappedPipelineReturn = {
label: 'passed',
hasDetails: true,
detailsPath: '/root/elemenohpee/-/jobs/1662',
deploymentDetailsPath: null,
group: 'success',
action: {
__typename: 'StatusAction',
@ -300,6 +301,26 @@ export const delayedJob = {
},
};
export const bridgeJob = {
id: 4255,
name: 'test',
kind: BRIDGE_KIND,
status: {
icon: 'status_manual',
text: 'Manual',
label: 'manual action',
tooltip: 'View deployment details page',
group: 'manual',
deploymentDetailsPath: 'path/to/deployment',
hasDetails: false,
action: {
icon: null,
title: null,
path: null,
},
},
};
export const mockJob = {
id: 4256,
name: 'test',

View File

@ -1215,6 +1215,7 @@ export const mockPipelineStatusUpdatedResponse = {
__typename: 'Pipeline',
detailedStatus: {
detailsPath: '/root/simple-ci-project/-/pipelines/1257',
deploymentDetailsPath: null,
icon: 'status_success',
id: 'success-1255-1255',
label: 'passed',

View File

@ -14,7 +14,7 @@ RSpec.describe Types::Ci::DetailedStatusType do
:id, :group, :icon, :favicon,
:details_path, :has_details,
:label, :name, :text, :tooltip,
:action
:action, :deployment_details_path
)
end

View File

@ -20,4 +20,10 @@ RSpec.describe Gitlab::Ci::Status::Core do
expect(status.confirmation_message).to be_nil
end
end
describe '#deployment_details_path' do
it 'returns nil by default' do
expect(status.deployment_details_path).to be_nil
end
end
end

View File

@ -18,20 +18,20 @@ RSpec.describe 'cross-database foreign keys' do
'system_access_microsoft_applications.namespace_id',
'ci_runner_taggings.tag_id', # https://gitlab.com/gitlab-org/gitlab/-/issues/467664
'ci_runner_taggings_instance_type.tag_id', # https://gitlab.com/gitlab-org/gitlab/-/issues/467664
'ci_secure_file_states.ci_secure_file_id',
'dependency_proxy_blob_states.dependency_proxy_blob_id',
'dependency_proxy_blob_states.group_id',
'dependency_proxy_manifest_states.dependency_proxy_manifest_id',
'dependency_proxy_manifest_states.group_id',
'lfs_objects_projects.lfs_object_id',
'merge_request_diff_details.merge_request_diff_id',
'merge_request_diff_details.project_id',
'pages_deployment_states.pages_deployment_id',
'pages_deployment_states.project_id',
'snippet_repositories.snippet_id',
'snippet_repositories.snippet_organization_id',
'snippet_repositories.snippet_project_id',
'upload_states.upload_id',
'ci_secure_file_states.ci_secure_file_id', # https://gitlab.com/groups/gitlab-org/-/epics/17347
'dependency_proxy_blob_states.dependency_proxy_blob_id', # https://gitlab.com/groups/gitlab-org/-/epics/17347
'dependency_proxy_blob_states.group_id', # https://gitlab.com/groups/gitlab-org/-/epics/17347
'dependency_proxy_manifest_states.dependency_proxy_manifest_id', # https://gitlab.com/groups/gitlab-org/-/epics/17347
'dependency_proxy_manifest_states.group_id', # https://gitlab.com/groups/gitlab-org/-/epics/17347
'lfs_objects_projects.lfs_object_id', # https://gitlab.com/groups/gitlab-org/-/epics/17347
'merge_request_diff_details.merge_request_diff_id', # https://gitlab.com/groups/gitlab-org/-/epics/17347
'merge_request_diff_details.project_id', # https://gitlab.com/groups/gitlab-org/-/epics/17347
'pages_deployment_states.pages_deployment_id', # https://gitlab.com/groups/gitlab-org/-/epics/17347
'pages_deployment_states.project_id', # https://gitlab.com/groups/gitlab-org/-/epics/17347
'snippet_repositories.snippet_id', # https://gitlab.com/groups/gitlab-org/-/epics/17347
'snippet_repositories.snippet_organization_id', # https://gitlab.com/groups/gitlab-org/-/epics/17347
'snippet_repositories.snippet_project_id', # https://gitlab.com/groups/gitlab-org/-/epics/17347
'upload_states.upload_id', # https://gitlab.com/groups/gitlab-org/-/epics/17347
'application_settings.web_ide_oauth_application_id', # https://gitlab.com/gitlab-org/gitlab/-/issues/531355
'ai_settings.amazon_q_oauth_application_id', # https://gitlab.com/gitlab-org/gitlab/-/issues/531356
'ai_settings.duo_workflow_oauth_application_id', # https://gitlab.com/gitlab-org/gitlab/-/issues/531356