Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
12fc930567
commit
696edc7f23
|
|
@ -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'
|
||||
|
|
|
|||
|
|
@ -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'
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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])
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
|
|
|||
|
|
@ -129,6 +129,7 @@ query getPipelineDetails($projectPath: ID!, $iid: ID!) {
|
|||
tooltip
|
||||
hasDetails
|
||||
detailsPath
|
||||
deploymentDetailsPath
|
||||
group
|
||||
label
|
||||
text
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -95,6 +95,8 @@
|
|||
- 2
|
||||
- - authorized_projects
|
||||
- 2
|
||||
- - authz_ldap_admin_role
|
||||
- 1
|
||||
- - auto_devops
|
||||
- 2
|
||||
- - auto_merge
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
class AddDuoFeaturesEnabledCascadingSetting < Gitlab::Database::Migration[2.2]
|
||||
include Gitlab::Database::MigrationHelpers::CascadingNamespaceSettings
|
||||
|
||||
enable_lock_retries!
|
||||
|
||||
milestone '16.10'
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
class SwapVulnerabilityFeedbackPipelineIdConvertToBigint < Gitlab::Database::Migration[2.2]
|
||||
include Gitlab::Database::MigrationHelpers::Swapping
|
||||
|
||||
milestone '17.0'
|
||||
disable_ddl_transaction!
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
class SwapPackagesBuildInfosPipelineIdConvertToBigint < Gitlab::Database::Migration[2.2]
|
||||
include Gitlab::Database::MigrationHelpers::Swapping
|
||||
|
||||
milestone '17.0'
|
||||
disable_ddl_transaction!
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
class SwapMergeTrainsPipelineIdConvertToBigint < Gitlab::Database::Migration[2.2]
|
||||
include Gitlab::Database::MigrationHelpers::Swapping
|
||||
|
||||
milestone '17.0'
|
||||
disable_ddl_transaction!
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
class SwapMergeRequestMetricsPipelineIdConvertToBigint < Gitlab::Database::Migration[2.2]
|
||||
include Gitlab::Database::MigrationHelpers::Swapping
|
||||
|
||||
milestone '17.0'
|
||||
disable_ddl_transaction!
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
class SwapColumnsForPCiBuildsTriggerRequestAndErasedBy < Gitlab::Database::Migration[2.2]
|
||||
include ::Gitlab::Database::MigrationHelpers::Swapping
|
||||
|
||||
milestone '17.1'
|
||||
disable_ddl_transaction!
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
class SwapVulnerabilityOccurrencePipelinesPipelineIdConvertToBigint < Gitlab::Database::Migration[2.2]
|
||||
include Gitlab::Database::MigrationHelpers::Swapping
|
||||
|
||||
milestone '17.1'
|
||||
disable_ddl_transaction!
|
||||
|
||||
|
|
|
|||
|
|
@ -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. |
|
||||
|
|
|
|||
|
|
@ -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 >}}
|
||||
|
||||
|
|
|
|||
|
|
@ -70,8 +70,7 @@ module Gitlab
|
|||
LabelFilter.new(
|
||||
stage: stage,
|
||||
params: params,
|
||||
project: nil,
|
||||
group: root_ancestor
|
||||
parent: root_ancestor
|
||||
).filter(query)
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)"
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -91,6 +91,10 @@ module Gitlab
|
|||
def confirmation_message
|
||||
nil
|
||||
end
|
||||
|
||||
def deployment_details_path
|
||||
nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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', () => {
|
||||
|
|
|
|||
|
|
@ -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',
|
||||
|
|
|
|||
|
|
@ -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',
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in New Issue