Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
3d53332cde
commit
40ea82e97a
|
|
@ -2699,6 +2699,8 @@
|
|||
when: never
|
||||
- if: '$DEPENDENCY_SCANNING_DISABLED || $GITLAB_FEATURES !~ /\bdependency_scanning\b/ || $DS_EXCLUDED_ANALYZERS =~ /gemnasium([^-]|$)/'
|
||||
when: never
|
||||
# Run Dependency Scanning on master until https://gitlab.com/gitlab-org/gitlab/-/issues/361657 is resolved
|
||||
- <<: *if-default-branch-refs
|
||||
- <<: *if-default-refs
|
||||
changes: *dependency-patterns
|
||||
|
||||
|
|
@ -2708,6 +2710,8 @@
|
|||
when: never
|
||||
- if: '$DEPENDENCY_SCANNING_DISABLED || $GITLAB_FEATURES !~ /\bdependency_scanning\b/ || $DS_EXCLUDED_ANALYZERS =~ /gemnasium-python/'
|
||||
when: never
|
||||
# Run Dependency Scanning on master until https://gitlab.com/gitlab-org/gitlab/-/issues/361657 is resolved
|
||||
- <<: *if-default-branch-refs
|
||||
- <<: *if-default-refs
|
||||
changes: *python-patterns
|
||||
|
||||
|
|
|
|||
|
|
@ -290,7 +290,6 @@ RSpec/ExampleWithoutDescription:
|
|||
- 'spec/initializers/gitlab_http_spec.rb'
|
||||
- 'spec/initializers/google_cloud_profiler_spec.rb'
|
||||
- 'spec/keeps/helpers/postgres_ai_spec.rb'
|
||||
- 'spec/lib/api/entities/virtual_registries/packages/maven/cached_response_spec.rb'
|
||||
- 'spec/lib/banzai/filter/commit_trailers_filter_spec.rb'
|
||||
- 'spec/lib/banzai/pipeline/incident_management/timeline_event_pipeline_spec.rb'
|
||||
- 'spec/lib/banzai/pipeline_spec.rb'
|
||||
|
|
@ -477,7 +476,6 @@ RSpec/ExampleWithoutDescription:
|
|||
- 'spec/models/users/banned_user_spec.rb'
|
||||
- 'spec/models/users/phone_number_validation_spec.rb'
|
||||
- 'spec/models/users/project_callout_spec.rb'
|
||||
- 'spec/models/virtual_registries/packages/maven/cached_response_spec.rb'
|
||||
- 'spec/models/virtual_registries/packages/maven/registry_spec.rb'
|
||||
- 'spec/models/virtual_registries/packages/maven/registry_upstream_spec.rb'
|
||||
- 'spec/models/virtual_registries/packages/maven/upstream_spec.rb'
|
||||
|
|
|
|||
|
|
@ -113,6 +113,7 @@ export default {
|
|||
class="!gl-text-subtle"
|
||||
:aria-expanded="isExpanded.toString()"
|
||||
:aria-controls="$options.ariaControlsId"
|
||||
data-testid="toggle-button"
|
||||
@click="toggleWidget"
|
||||
>
|
||||
<gl-icon :name="iconName" class="gl-mr-2" />
|
||||
|
|
@ -126,6 +127,15 @@ export default {
|
|||
{{ failedJobsCountBadge }}
|
||||
</gl-badge>
|
||||
</template>
|
||||
<template #actions>
|
||||
<gl-button
|
||||
v-if="isExpanded"
|
||||
href="https://gitlab.com/gitlab-org/gitlab/-/issues/502436"
|
||||
data-testid="feedback-button"
|
||||
>
|
||||
{{ __('Leave feedback') }}
|
||||
</gl-button>
|
||||
</template>
|
||||
<failed-jobs-list
|
||||
v-if="isExpanded"
|
||||
:is-maximum-job-limit-reached="isMaximumJobLimitReached"
|
||||
|
|
|
|||
|
|
@ -91,7 +91,7 @@ export default {
|
|||
@primary="onSubmit"
|
||||
>
|
||||
<template #modal-title>
|
||||
<gl-sprintf :message="s__('Environments|Stopping %{environmentName}')">
|
||||
<gl-sprintf :message="s__('Environments|Stop %{environmentName}')">
|
||||
<template #environmentName>
|
||||
<span v-gl-tooltip :title="environment.name" class="gl-grow gl-truncate">
|
||||
{{ environment.name }}?
|
||||
|
|
|
|||
|
|
@ -392,6 +392,7 @@ class GfmAutoComplete {
|
|||
UNASSIGN_REVIEWER: '/unassign_reviewer',
|
||||
REASSIGN: '/reassign',
|
||||
CC: '/cc',
|
||||
REQUEST_REVIEW: '/request_review',
|
||||
};
|
||||
let assignees = [];
|
||||
let reviewers = [];
|
||||
|
|
|
|||
|
|
@ -709,6 +709,7 @@ export default {
|
|||
:sort-options="sortOptions"
|
||||
:initial-sort-by="sortKey"
|
||||
:issuables="mergeRequests"
|
||||
issuable-symbol="!"
|
||||
:error="mergeRequestsError"
|
||||
:tabs="$options.mergeRequestListTabs"
|
||||
:current-tab="state"
|
||||
|
|
|
|||
|
|
@ -231,6 +231,7 @@ export default {
|
|||
category="tertiary"
|
||||
type="reset"
|
||||
class="sidebar-collapsed-icon sidebar-collapsed-container !gl-rounded-none !gl-shadow-none"
|
||||
:class="{ '!gl-text-blue-500': hasTodo }"
|
||||
@click.stop.prevent="toggleTodo"
|
||||
>
|
||||
<gl-animated-todo-icon :is-on="hasTodo" />
|
||||
|
|
|
|||
|
|
@ -159,7 +159,7 @@ export default {
|
|||
>
|
||||
<template #list-item="{ item }">
|
||||
<strong class="gl-block gl-w-full">{{ item.text }}</strong>
|
||||
<gl-truncate class="gl-mt-2" :text="item.content" position="end" />
|
||||
<gl-truncate class="gl-mt-2 gl-text-subtle" :text="item.content" position="end" />
|
||||
</template>
|
||||
</gl-disclosure-dropdown-group>
|
||||
</ul>
|
||||
|
|
|
|||
|
|
@ -99,6 +99,10 @@
|
|||
.comment-templates-modal {
|
||||
padding: 3rem 0.5rem 0;
|
||||
|
||||
.modal-content {
|
||||
@apply gl-max-h-[80vh];
|
||||
}
|
||||
|
||||
// stylelint-disable-next-line gitlab/no-gl-class
|
||||
&.gl-modal .modal-dialog {
|
||||
align-items: flex-start;
|
||||
|
|
|
|||
|
|
@ -6,17 +6,22 @@ module Integrations
|
|||
|
||||
field :webhook,
|
||||
section: SECTION_TYPE_CONNECTION,
|
||||
help: 'https://yourcircuit.com/rest/v2/webhooks/incoming/…',
|
||||
help: -> { _('The Unify Circuit webhook (for example, `https://circuit.com/rest/v2/webhooks/incoming/...`).') },
|
||||
required: true
|
||||
|
||||
field :notify_only_broken_pipelines,
|
||||
type: :checkbox,
|
||||
description: -> { _('Send notifications for broken pipelines.') },
|
||||
section: SECTION_TYPE_CONFIGURATION
|
||||
|
||||
field :branches_to_be_notified,
|
||||
type: :select,
|
||||
section: SECTION_TYPE_CONFIGURATION,
|
||||
title: -> { s_('Integrations|Branches for which notifications are to be sent') },
|
||||
description: -> {
|
||||
_('Branches to send notifications for. Valid options are `all`, `default`, `protected`, ' \
|
||||
'and `default_and_protected`. The default value is `default`.')
|
||||
},
|
||||
choices: -> { branch_choices }
|
||||
|
||||
def self.title
|
||||
|
|
|
|||
|
|
@ -7,16 +7,16 @@ module Packages
|
|||
include ShaAttribute
|
||||
include Packages::Destructible
|
||||
|
||||
# Used in destroying stale symbols in worker
|
||||
# Used in destroying orphan symbols in worker
|
||||
enum :status, default: 0, processing: 1, error: 3
|
||||
|
||||
belongs_to :package, class_name: 'Packages::Nuget::Package', inverse_of: :nuget_symbols
|
||||
belongs_to :project
|
||||
|
||||
delegate :project_id, :project, to: :package
|
||||
delegate :project_id, :project, to: :package, allow_nil: true
|
||||
|
||||
validates :file, :file_path, :signature, :object_storage_key, :size, presence: true
|
||||
validates :signature, uniqueness: { scope: :file_path }
|
||||
validates :signature, uniqueness: { scope: %i[file_path package_id] }, if: -> { package }
|
||||
validates :object_storage_key, uniqueness: true
|
||||
validates :package, presence: true
|
||||
|
||||
|
|
@ -26,8 +26,8 @@ module Packages
|
|||
|
||||
before_validation :set_object_storage_key, on: :create
|
||||
|
||||
scope :stale, -> { where(package_id: nil) }
|
||||
scope :pending_destruction, -> { stale.default }
|
||||
scope :orphan, -> { where(package_id: nil) }
|
||||
scope :pending_destruction, -> { orphan.default }
|
||||
scope :with_file_name, ->(file_name) { where(arel_table[:file].lower.eq(file_name.downcase)) }
|
||||
scope :with_signature, ->(signature) { where(arel_table[:signature].lower.eq(signature.downcase)) }
|
||||
scope :with_file_sha256, ->(checksums) { where(file_sha256: Array.wrap(checksums).map(&:downcase)) }
|
||||
|
|
@ -36,6 +36,7 @@ module Packages
|
|||
with_signature(signature)
|
||||
.with_file_name(file_name)
|
||||
.with_file_sha256(checksums)
|
||||
.where.not(orphan.where_values_hash)
|
||||
.take
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ module VirtualRegistries
|
|||
enum :status, default: 0, processing: 1, pending_destruction: 2, error: 3
|
||||
|
||||
ignore_column :downloads_count, remove_with: '17.8', remove_after: '2024-12-23'
|
||||
ignore_column :downloaded_at, remove_with: '17.9', remove_after: '2025-01-23'
|
||||
|
||||
validates :group, top_level_group: true, presence: true
|
||||
validates :relative_path,
|
||||
|
|
@ -86,13 +87,6 @@ module VirtualRegistries
|
|||
(upstream_checked_at + upstream.cache_validity_hours.hours).past?
|
||||
end
|
||||
|
||||
def bump_statistics(include_upstream_checked_at: false)
|
||||
now = Time.zone.now
|
||||
updates = { downloaded_at: now }
|
||||
updates[:upstream_checked_at] = now if include_upstream_checked_at
|
||||
update_columns(**updates)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def set_object_storage_key
|
||||
|
|
|
|||
|
|
@ -10,7 +10,8 @@ module Import
|
|||
|
||||
def initialize(import_source_user)
|
||||
@import_source_user = import_source_user
|
||||
@reassigned_by_user = User.find_by_id(import_source_user.reassigned_by_user_id)
|
||||
@reassigned_by_user = import_source_user.reassigned_by_user
|
||||
@project_membership_created = false
|
||||
end
|
||||
|
||||
def execute
|
||||
|
|
@ -24,6 +25,8 @@ module Import
|
|||
create_memberships
|
||||
delete_placeholder_memberships
|
||||
|
||||
UserProjectAccessChangedService.new(import_source_user.reassign_to_user_id).execute if project_membership_created?
|
||||
|
||||
import_source_user.complete!
|
||||
end
|
||||
|
||||
|
|
@ -153,6 +156,8 @@ module Import
|
|||
)
|
||||
|
||||
member.save!
|
||||
|
||||
@project_membership_created = true if memberable.is_a?(Project)
|
||||
rescue ActiveRecord::ActiveRecordError => exception
|
||||
Gitlab::ErrorTracking.track_and_raise_for_dev_exception(
|
||||
exception,
|
||||
|
|
@ -193,6 +198,10 @@ module Import
|
|||
Import::Placeholders::Membership.by_source_user(import_source_user)
|
||||
end
|
||||
|
||||
def project_membership_created?
|
||||
@project_membership_created == true
|
||||
end
|
||||
|
||||
def log_create_membership_skipped(message, placeholder_membership, existing_membership)
|
||||
log_info(
|
||||
message,
|
||||
|
|
|
|||
|
|
@ -4,7 +4,9 @@ module Notes
|
|||
class CreateService < ::Notes::BaseService
|
||||
include IncidentManagement::UsageData
|
||||
|
||||
def execute(skip_capture_diff_note_position: false, skip_merge_status_trigger: false, executing_user: nil)
|
||||
def execute(
|
||||
skip_capture_diff_note_position: false, skip_merge_status_trigger: false, executing_user: nil,
|
||||
importing: false)
|
||||
Gitlab::Database::QueryAnalyzers::PreventCrossDatabaseModification.temporary_ignore_tables_in_transaction(
|
||||
%w[
|
||||
notes
|
||||
|
|
@ -29,7 +31,7 @@ module Notes
|
|||
execute_quick_actions(note) do |only_commands|
|
||||
note.check_for_spam(action: :create, user: current_user) if check_for_spam?(only_commands)
|
||||
|
||||
after_commit(note)
|
||||
after_commit(note) unless importing
|
||||
|
||||
note_saved = note.with_transaction_returning_status do
|
||||
break false if only_commands
|
||||
|
|
|
|||
|
|
@ -29,7 +29,6 @@ module VirtualRegistries
|
|||
file: file,
|
||||
size: file.size,
|
||||
file_sha1: file.sha1,
|
||||
downloaded_at: now,
|
||||
content_type: content_type
|
||||
}
|
||||
updates[:file_md5] = file.md5 unless Gitlab::FIPS.enabled?
|
||||
|
|
|
|||
|
|
@ -65,11 +65,8 @@ module VirtualRegistries
|
|||
|
||||
def cache_response_still_valid?
|
||||
return false unless cached_response
|
||||
return true unless cached_response.stale?
|
||||
|
||||
unless cached_response.stale?
|
||||
cached_response.bump_statistics
|
||||
return true
|
||||
end
|
||||
# cached response with no etag can't be checked
|
||||
return false if cached_response.upstream_etag.blank?
|
||||
|
||||
|
|
@ -77,7 +74,7 @@ module VirtualRegistries
|
|||
|
||||
return false unless cached_response.upstream_etag == response.headers['etag']
|
||||
|
||||
cached_response.bump_statistics(include_upstream_checked_at: true)
|
||||
cached_response.update_column(:upstream_checked_at, Time.current)
|
||||
true
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,33 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class UpdateUniqueIndexOnPackagesNugetSymbol < Gitlab::Database::Migration[2.2]
|
||||
disable_ddl_transaction!
|
||||
milestone '17.7'
|
||||
|
||||
TABLE_NAME = :packages_nuget_symbols
|
||||
OLD_INDEX_NAME = :index_packages_nuget_symbols_on_signature_and_file_path
|
||||
NEW_INDEX_NAME = :idx_pkgs_nuget_symbols_on_signature_and_file_path_with_pkg_id
|
||||
|
||||
def up
|
||||
add_concurrent_index(
|
||||
TABLE_NAME,
|
||||
%i[signature file_path],
|
||||
unique: true,
|
||||
name: NEW_INDEX_NAME,
|
||||
where: 'package_id IS NOT NULL'
|
||||
)
|
||||
|
||||
remove_concurrent_index_by_name(TABLE_NAME, OLD_INDEX_NAME)
|
||||
end
|
||||
|
||||
def down
|
||||
add_concurrent_index(
|
||||
TABLE_NAME,
|
||||
%i[signature file_path],
|
||||
unique: true,
|
||||
name: OLD_INDEX_NAME
|
||||
)
|
||||
|
||||
remove_concurrent_index_by_name(TABLE_NAME, NEW_INDEX_NAME)
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1 @@
|
|||
da65c2c8c0afc61af3000cdf6fe11ddaf61e157b6b73f0b274d825b4adf2d43b
|
||||
|
|
@ -28515,6 +28515,8 @@ CREATE INDEX idx_pkgs_npm_metadata_caches_on_id_and_project_id_and_status ON pac
|
|||
|
||||
CREATE INDEX idx_pkgs_nuget_symbols_on_lowercase_signature_and_file_name ON packages_nuget_symbols USING btree (lower(signature), lower(file));
|
||||
|
||||
CREATE UNIQUE INDEX idx_pkgs_nuget_symbols_on_signature_and_file_path_with_pkg_id ON packages_nuget_symbols USING btree (signature, file_path) WHERE (package_id IS NOT NULL);
|
||||
|
||||
CREATE INDEX idx_pkgs_on_project_id_name_version_on_installable_terraform ON packages_packages USING btree (project_id, name, version, id) WHERE ((package_type = 12) AND (status = ANY (ARRAY[0, 1])));
|
||||
|
||||
CREATE INDEX idx_pkgs_project_id_lower_name_when_nuget_installable_version ON packages_packages USING btree (project_id, lower((name)::text)) WHERE ((package_type = 4) AND (version IS NOT NULL) AND (status = ANY (ARRAY[0, 1])));
|
||||
|
|
@ -31329,8 +31331,6 @@ CREATE INDEX index_packages_nuget_symbols_on_package_id ON packages_nuget_symbol
|
|||
|
||||
CREATE INDEX index_packages_nuget_symbols_on_project_id ON packages_nuget_symbols USING btree (project_id);
|
||||
|
||||
CREATE UNIQUE INDEX index_packages_nuget_symbols_on_signature_and_file_path ON packages_nuget_symbols USING btree (signature, file_path);
|
||||
|
||||
CREATE INDEX index_packages_on_available_pypi_packages ON packages_packages USING btree (project_id, id) WHERE ((status = ANY (ARRAY[0, 1])) AND (package_type = 5) AND (version IS NOT NULL));
|
||||
|
||||
CREATE INDEX index_packages_package_file_build_infos_on_package_file_id ON packages_package_file_build_infos USING btree (package_file_id);
|
||||
|
|
|
|||
|
|
@ -48,3 +48,4 @@ Customize and configure your self-managed GitLab installation.
|
|||
- [Snippets](../administration/snippets/index.md)
|
||||
- [Host the product documentation](../administration/docs_self_host.md)
|
||||
- [Custom HTML header tags](../administration/custom_html_header_tags.md)
|
||||
- [Self-hosted models](../administration/self_hosted_models/index.md)
|
||||
|
|
|
|||
|
|
@ -12,7 +12,8 @@ Learn how to administer a self-managed GitLab instance.
|
|||
| | | |
|
||||
|--|--|--|
|
||||
| [**Get started**](../administration/get_started.md)<br>Administration overview. | [**All feature flags**](../user/feature_flags.md)<br>Complete list of flags. | [**Authentication and authorization**](../administration/auth/index.md)<br>Third-party authentication providers. |
|
||||
| [**Configure your installation**](../administration/configure.md)<br>Installation settings. | [**Update your Admin area settings**](../administration/settings/index.md)<br>Product settings. | [**Configure GitLab Dedicated**](../administration/dedicated/index.md)<br>IP allowlists, SAML, maintenance. |
|
||||
| [**Maintain your installation**](../administration/operations/index.md)<br>Backup and restore, move repos, maintenance tasks. | [**Secure your application**](../user/application_security/secure_your_application.md)<br>SSH key limits, 2FA, tokens, hardening. | [**Administer users**](../user/profile/account/create_accounts.md)<br>Passwords, user moderation, broadcast messages. |
|
||||
| [**Configure GitLab**](../administration/configure.md)<br>Installation settings. | [**Update your Admin area settings**](../administration/settings/index.md)<br>Product settings. | [**Maintain GitLab**](../administration/operations/index.md)<br>Backup and restore, move repositories, maintenance tasks. |
|
||||
| [**Monitor GitLab**](../administration/monitoring/index.md)<br>Performance, health, uptime monitoring. | [**Secure GitLab**](../security/index.md)<br>SSH key limits, 2FA, tokens, hardening. | [**Administer users**](../user/profile/account/create_accounts.md)<br>Passwords, user moderation, broadcast messages. |
|
||||
| [**GitLab Dedicated**](../administration/dedicated/index.md)<br>Get started with GitLab Dedicated. | | |
|
||||
|
||||
Only GitLab team members have access to administration tools and settings on GitLab.com.
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
---
|
||||
stage: Monitor
|
||||
group: Platform Insights
|
||||
description: Performance, health, uptime monitoring.
|
||||
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://handbook.gitlab.com/handbook/product/ux/technical-writing/#assignments
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -20959,6 +20959,7 @@ Represents a ComplianceFramework associated with a Project.
|
|||
| <a id="complianceframeworkprojects"></a>`projects` | [`ProjectConnection`](#projectconnection) | Projects associated with the compliance framework. (see [Connections](#connections)) |
|
||||
| <a id="complianceframeworkscanexecutionpolicies"></a>`scanExecutionPolicies` | [`ScanExecutionPolicyConnection`](#scanexecutionpolicyconnection) | Scan Execution Policies of the compliance framework. (see [Connections](#connections)) |
|
||||
| <a id="complianceframeworkscanresultpolicies"></a>`scanResultPolicies` | [`ScanResultPolicyConnection`](#scanresultpolicyconnection) | Scan Result Policies of the compliance framework. (see [Connections](#connections)) |
|
||||
| <a id="complianceframeworkvulnerabilitymanagementpolicies"></a>`vulnerabilityManagementPolicies` | [`VulnerabilityManagementPolicyConnection`](#vulnerabilitymanagementpolicyconnection) | Vulnerability Management Policies of the compliance framework. (see [Connections](#connections)) |
|
||||
|
||||
### `ComplianceRequirement`
|
||||
|
||||
|
|
@ -25649,6 +25650,27 @@ Returns [`[VulnerableProjectsByGrade!]`](#vulnerableprojectsbygrade).
|
|||
| <a id="groupvulnerabilitygradesincludesubgroups"></a>`includeSubgroups` | [`Boolean`](#boolean) | Include grades belonging to subgroups. |
|
||||
| <a id="groupvulnerabilitygradeslettergrade"></a>`letterGrade` | [`VulnerabilityGrade`](#vulnerabilitygrade) | Filter the response by given letter grade. |
|
||||
|
||||
##### `Group.vulnerabilityManagementPolicies`
|
||||
|
||||
Vulnerability Management Policies of the project.
|
||||
|
||||
DETAILS:
|
||||
**Introduced** in GitLab 17.7.
|
||||
**Status**: Experiment.
|
||||
|
||||
Returns [`VulnerabilityManagementPolicyConnection`](#vulnerabilitymanagementpolicyconnection).
|
||||
|
||||
This field returns a [connection](#connections). It accepts the
|
||||
four standard [pagination arguments](#pagination-arguments):
|
||||
`before: String`, `after: String`, `first: Int`, and `last: Int`.
|
||||
|
||||
###### Arguments
|
||||
|
||||
| Name | Type | Description |
|
||||
| ---- | ---- | ----------- |
|
||||
| <a id="groupvulnerabilitymanagementpoliciesincludeunscoped"></a>`includeUnscoped` | [`Boolean`](#boolean) | Filter policies that are scoped to the project. |
|
||||
| <a id="groupvulnerabilitymanagementpoliciesrelationship"></a>`relationship` | [`SecurityPolicyRelationType`](#securitypolicyrelationtype) | Filter policies by the given policy relationship. |
|
||||
|
||||
##### `Group.vulnerabilitySeveritiesCount`
|
||||
|
||||
Counts for each vulnerability severity in the group and its subgroups.
|
||||
|
|
@ -29477,6 +29499,27 @@ four standard [pagination arguments](#pagination-arguments):
|
|||
| <a id="namespacescanresultpoliciesincludeunscoped"></a>`includeUnscoped` **{warning-solid}** | [`Boolean`](#boolean) | **Introduced** in GitLab 17.3. **Status**: Experiment. Filter policies that are scoped to the project. |
|
||||
| <a id="namespacescanresultpoliciesrelationship"></a>`relationship` | [`SecurityPolicyRelationType`](#securitypolicyrelationtype) | Filter policies by the given policy relationship. |
|
||||
|
||||
##### `Namespace.vulnerabilityManagementPolicies`
|
||||
|
||||
Vulnerability Management Policies of the project.
|
||||
|
||||
DETAILS:
|
||||
**Introduced** in GitLab 17.7.
|
||||
**Status**: Experiment.
|
||||
|
||||
Returns [`VulnerabilityManagementPolicyConnection`](#vulnerabilitymanagementpolicyconnection).
|
||||
|
||||
This field returns a [connection](#connections). It accepts the
|
||||
four standard [pagination arguments](#pagination-arguments):
|
||||
`before: String`, `after: String`, `first: Int`, and `last: Int`.
|
||||
|
||||
###### Arguments
|
||||
|
||||
| Name | Type | Description |
|
||||
| ---- | ---- | ----------- |
|
||||
| <a id="namespacevulnerabilitymanagementpoliciesincludeunscoped"></a>`includeUnscoped` | [`Boolean`](#boolean) | Filter policies that are scoped to the project. |
|
||||
| <a id="namespacevulnerabilitymanagementpoliciesrelationship"></a>`relationship` | [`SecurityPolicyRelationType`](#securitypolicyrelationtype) | Filter policies by the given policy relationship. |
|
||||
|
||||
##### `Namespace.workItem`
|
||||
|
||||
Find a work item by IID directly associated with the namespace(project or group). Returns `null` for group level work items if the `namespace_level_work_items` feature flag is disabled.
|
||||
|
|
|
|||
|
|
@ -15,12 +15,12 @@ shows the status of its most recent pipeline, or shows **No pipeline** if a pipe
|
|||
|
||||
Possible statuses include:
|
||||
|
||||
- **Pipeline canceled**
|
||||
- **Pipeline failed**
|
||||
- **Pipeline passed**
|
||||
- **Pipeline pending**
|
||||
- **Pipeline running**
|
||||
- **Pipeline skipped**
|
||||
- Pipeline canceled
|
||||
- Pipeline failed
|
||||
- Pipeline passed
|
||||
- Pipeline pending
|
||||
- Pipeline running
|
||||
- Pipeline skipped
|
||||
|
||||
## View pipeline information
|
||||
|
||||
|
|
@ -91,7 +91,15 @@ VS Code opens a new tab (`.gitlab-ci (Merged).yml`) with full information.
|
|||
|
||||
### CI/CD variable autocompletion
|
||||
|
||||
Quickly find the CI/CD variable you are looking for with the CI/CD variable autocompletion:
|
||||
Quickly find the CI/CD variable you are looking for with the CI/CD variable autocompletion.
|
||||
|
||||
Prerequisites:
|
||||
|
||||
- Your file is named either:
|
||||
- `.gitlab-ci.yml`.
|
||||
- Beginning with `.gitlab-ci` and ending with `.yml` or `.yaml`, like `.gitlab-ci.production.yml`.
|
||||
|
||||
To autocomplete a variable:
|
||||
|
||||
1. In VS Code, open your `.gitlab-ci.yml` file, and ensure the file's tab is in focus.
|
||||
1. Begin entering the name of a variable to display auto-complete options.
|
||||
|
|
|
|||
|
|
@ -198,18 +198,62 @@ To view issues and merge requests for a specific project:
|
|||
- All project merge requests
|
||||
- Your [custom queries](custom_queries.md)
|
||||
|
||||
1. Select an issue or merge request to open it in a new VS Code tab.
|
||||
1. Optional. If you select a merge request, its sidebar entry expands to show all files changed
|
||||
in the merge request. Deleted files are marked in red. For example:
|
||||
Select an issue or merge request to open it in a new VS Code tab.
|
||||
|
||||
## Review a merge request
|
||||
|
||||
Use this extension to review, comment on, and approve merge requests without leaving VS Code:
|
||||
|
||||
1. While viewing [issues and merge requests](#view-issues-and-merge-requests) in VS Code, select the
|
||||
merge request you want to review. Its sidebar entry expands with more information.
|
||||
1. Under the merge request's number and title, select **Description** to read more about the merge request.
|
||||
1. To review the proposed changes to a file, select the file from the list to show it in a VS Code tab.
|
||||
Diff comments are shown inline in the tab. In the list, deleted files are marked in red:
|
||||
|
||||

|
||||
|
||||
1. Select a file to view its diff in a VS Code tab.
|
||||
Use the diff to:
|
||||
|
||||
- Review and create discussions.
|
||||
- Resolve and unresolve these discussions.
|
||||
- Delete and edit individual comments.
|
||||
|
||||
### Compare with default branch
|
||||
|
||||
<!-- vale gitlab_base.InclusiveLanguage = NO -->
|
||||
|
||||
To compare your branch with your project's default branch, without creating a merge request:
|
||||
|
||||
1. Open the Command Palette:
|
||||
- For macOS, press <kbd>Command</kbd>+<kbd>Shift</kbd>+<kbd>P</kbd>.
|
||||
- For Windows or Linux, press <kbd>Ctrl</kbd>+<kbd>Shift</kbd>+<kbd>P</kbd>.
|
||||
1. In the Command Palette, search for **GitLab: Compare current branch with master** and press <kbd>Enter</kbd>.
|
||||
|
||||
The extension opens a new browser tab. It shows a diff between the most recent commit on your branch, and
|
||||
the most recent commit on your project's default branch.
|
||||
|
||||
<!-- vale gitlab_base.InclusiveLanguage = YES -->
|
||||
|
||||
### Open current file in GitLab UI
|
||||
|
||||
To open a file from your current GitLab project in the GitLab UI, with specific lines highlighted:
|
||||
|
||||
1. Open your desired file in VS Code.
|
||||
1. Select the lines you want to highlight.
|
||||
1. Open the Command Palette:
|
||||
- For macOS, press <kbd>Command</kbd>+<kbd>Shift</kbd>+<kbd>P</kbd>.
|
||||
- For Windows or Linux, press <kbd>Ctrl</kbd>+<kbd>Shift</kbd>+<kbd>P</kbd>.
|
||||
1. In the Command Palette, search for **GitLab: Open active file on GitLab** and press <kbd>Enter</kbd>.
|
||||
|
||||
## View security findings
|
||||
|
||||
DETAILS:
|
||||
**Tier:** Ultimate
|
||||
**Offering:** GitLab.com, Self-managed, GitLab Dedicated
|
||||
|
||||
Prerequisites:
|
||||
|
||||
- You're using GitLab Workflow version 3.74.0 or later.
|
||||
- Your project includes [Security Risk Management](https://about.gitlab.com/features/?stage=secure) features, such as
|
||||
Static Application Security Testing (SAST), Dynamic Application Security Testing (DAST),
|
||||
Container Scanning, or Dependency Scanning.
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ Prerequisites:
|
|||
| `gitlab.certKey`| null | Unsupported. See [epic 6244](https://gitlab.com/groups/gitlab-org/-/epics/6244). If your self-managed GitLab instance requires a custom certificate or key pair, set this option to point to your certificate key file. See `gitlab.cert`. |
|
||||
| `gitlab.ignoreCertificateErrors` | false | Unsupported. See [epic 6244](https://gitlab.com/groups/gitlab-org/-/epics/6244). If you use a self-managed GitLab instance with no SSL certificate, or have certificate issues that prevent you from using the extension, set this option to `true` to ignore certificate errors. |
|
||||
|
||||
## Disable code suggestions
|
||||
## Disable Code Suggestions
|
||||
|
||||
Code completion is enabled by default. To disable it:
|
||||
|
||||
|
|
@ -193,3 +193,15 @@ A workaround exists for Ubuntu users who use versions of VS Code earlier than 1.
|
|||
|
||||
If you use VS Code version 1.68.0 or later, re-installation might not be possible. However, you can still run
|
||||
the last three steps to re-authenticate.
|
||||
|
||||
## Set token with environment variables
|
||||
|
||||
If you often delete your VS Code storage, such as in Gitpod containers, you can create environment variables
|
||||
before starting VS Code. If you set the token in a
|
||||
[VS Code environment variable](https://code.visualstudio.com/docs/editor/variables-reference#_environment-variables),
|
||||
you don't have to set a personal access token each time you delete your VS Code storage. Set these variables:
|
||||
|
||||
- `GITLAB_WORKFLOW_INSTANCE_URL`: Your GitLab instance URL, like `https://gitlab.com`.
|
||||
- `GITLAB_WORKFLOW_TOKEN`: Your personal access token, which you created [during setup](https://gitlab.com/gitlab-org/gitlab-vscode-extension/#setup).
|
||||
|
||||
The token configured in an environment variable is overridden if you configure a token for the same GitLab instance in the extension.
|
||||
|
|
|
|||
|
|
@ -11,15 +11,11 @@ DETAILS:
|
|||
**Offering:** GitLab.com, Self-managed, GitLab Dedicated
|
||||
|
||||
There's no automatic removal process for blobs. Unless you delete them manually, they're stored
|
||||
indefinitely. Since this impacts your
|
||||
[storage usage quota](../../storage_usage_quotas.md),
|
||||
it's important that you clear unused items from the cache. This page covers several options for
|
||||
doing so.
|
||||
indefinitely. This page covers several options for clearing unused items from the cache.
|
||||
|
||||
## Check Dependency Proxy Storage Use
|
||||
|
||||
The Usage Quotas page (**Settings > Usage Quotas > Storage**) displays storage usage for Packages, which includes the Dependency Proxy,
|
||||
however, the storage is not yet displayed.
|
||||
The [**Usage Quotas**](../../storage_usage_quotas.md) page displays storage usage for the dependency proxy.
|
||||
|
||||
## Use the API to clear the cache
|
||||
|
||||
|
|
|
|||
|
|
@ -204,35 +204,31 @@ Replace `@scope` with your package's scope.
|
|||
|
||||
### For installing packages
|
||||
|
||||
When installing packages, you can use project, group, or instance endpoints. The URL structure varies accordingly:
|
||||
|
||||
You can configure these URLs using one of the following methods:
|
||||
|
||||
When you install packages, you can use project, group, or instance endpoints. The URL structure varies accordingly.
|
||||
To configure these URLs, use one of these methods:
|
||||
|
||||
::Tabs
|
||||
|
||||
:::TabTitle `.npmrc` file
|
||||
:::TabTitle `.npmrc` file
|
||||
|
||||
Create or edit the `.npmrc` file in your project root. Use the appropriate URL based on your needs:
|
||||
|
||||
- For a project:
|
||||
|
||||
```shell
|
||||
npm config set @scope:registry=https://gitlab.example.com/api/v4/projects/<project_id>/packages/npm/
|
||||
@scope:registry=https://gitlab.example.com/api/v4/projects/<project_id>/packages/npm/
|
||||
```
|
||||
|
||||
- For a group:
|
||||
|
||||
```shell
|
||||
npm config set @scope:registry=https://gitlab.example.com/api/v4/groups/<group_id>/-/packages/npm/
|
||||
@scope:registry=https://gitlab.example.com/api/v4/groups/<group_id>/-/packages/npm/
|
||||
```
|
||||
|
||||
- For an instance:
|
||||
|
||||
```shell
|
||||
npm config set @scope:registry=https://gitlab.example.com/api/v4/packages/npm/
|
||||
@scope:registry=https://gitlab.example.com/api/v4/packages/npm/
|
||||
```
|
||||
|
||||
:::TabTitle `npm config`
|
||||
|
|
|
|||
|
|
@ -57,8 +57,8 @@ To auto-format this table, use the VS Code Markdown Table formatter: `https://do
|
|||
| `/approve` | **{dotted-circle}** No | **{check-circle}** Yes | **{dotted-circle}** No | Approve the merge request. |
|
||||
| `/assign @user1 @user2` | **{check-circle}** Yes | **{check-circle}** Yes | **{dotted-circle}** No | Assign one or more users. |
|
||||
| `/assign me` | **{check-circle}** Yes | **{check-circle}** Yes | **{dotted-circle}** No | Assign yourself. |
|
||||
| `/assign_reviewer @user1 @user2` or `/reviewer @user1 @user2` or `/request_review @user1 @user2` | **{dotted-circle}** No | **{check-circle}** Yes | **{dotted-circle}** No | Assign one or more users as reviewers. |
|
||||
| `/assign_reviewer me` or `/reviewer me` or `/request_review me` | **{dotted-circle}** No | **{check-circle}** Yes | **{dotted-circle}** No | Assign yourself as a reviewer. |
|
||||
| `/assign_reviewer @user1 @user2` or `/reviewer @user1 @user2` | **{dotted-circle}** No | **{check-circle}** Yes | **{dotted-circle}** No | Assign one or more users as reviewers. |
|
||||
| `/assign_reviewer me` or `/reviewer me` | **{dotted-circle}** No | **{check-circle}** Yes | **{dotted-circle}** No | Assign yourself as a reviewer. |
|
||||
| `/blocked_by <issue1> <issue2>` | **{check-circle}** Yes | **{dotted-circle}** No | **{dotted-circle}** No | Mark the issue as blocked by other issues. The `<issue>` value should be in the format of `#issue`, `group/project#issue`, or the full issue URL. ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/214232) in GitLab 16.0). |
|
||||
| `/blocks <issue1> <issue2>` | **{check-circle}** Yes | **{dotted-circle}** No | **{dotted-circle}** No | Mark the issue as blocking other issues. The `<issue>` value should be in the format of `#issue`, `group/project#issue`, or the full issue URL. ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/214232) in GitLab 16.0). |
|
||||
| `/cc @user` | **{check-circle}** Yes | **{check-circle}** Yes | **{check-circle}** Yes | Mention a user. This command performs no action. You can instead type `CC @user` or only `@user`. |
|
||||
|
|
@ -112,6 +112,8 @@ To auto-format this table, use the VS Code Markdown Table formatter: `https://do
|
|||
| `/remove_time_spent` | **{check-circle}** Yes | **{check-circle}** Yes | **{dotted-circle}** No | Remove time spent. |
|
||||
| `/remove_zoom` | **{check-circle}** Yes | **{dotted-circle}** No | **{dotted-circle}** No | Remove Zoom meeting from this issue. |
|
||||
| `/reopen` | **{check-circle}** Yes | **{check-circle}** Yes | **{check-circle}** Yes | Reopen. |
|
||||
| `/request_review @user1 @user2` | **{dotted-circle}** No | **{check-circle}** Yes | **{dotted-circle}** No | Assigns or requests a new review from one or more users. |
|
||||
| `/request_review me` | **{dotted-circle}** No | **{check-circle}** Yes | **{dotted-circle}** No | Assigns or requests a new review from one or more users. |
|
||||
| `/severity <severity>` | **{check-circle}** Yes | **{dotted-circle}** No | **{dotted-circle}** No | Set the severity. Issue type must be `Incident`. Options for `<severity>` are `S1` ... `S4`, `critical`, `high`, `medium`, `low`, `unknown`. |
|
||||
| `/shrug` | **{check-circle}** Yes | **{check-circle}** Yes | **{check-circle}** Yes | Add `¯\_(ツ)_/¯`. |
|
||||
| `/spend <time> [<date>]` or `/spend_time <time> [<date>]` | **{check-circle}** Yes | **{check-circle}** Yes | **{dotted-circle}** No | Add or subtract spent time. Optionally, specify the date that time was spent on. For example, `/spend 1mo 2w 3d 4h 5m 2018-08-26` or `/spend -1h 30m`. For more information, see [Time tracking](time_tracking.md). Alias `/spend_time` [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/16501) in GitLab 15.6. |
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@ To set up infrastructure for workspaces:
|
|||
> - **Git reference** and **Devfile location** [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/392382) in GitLab 16.10.
|
||||
> - **Time before automatic termination** [renamed](https://gitlab.com/gitlab-org/gitlab/-/issues/392382) to **Workspace automatically terminates after** in GitLab 16.10.
|
||||
> - **Variables** [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/463514) in GitLab 17.1.
|
||||
> - **Workspace automatically terminates after** [removed](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/166065) in GitLab 17.6.
|
||||
|
||||
Prerequisites:
|
||||
|
||||
|
|
@ -65,8 +66,6 @@ To create a workspace:
|
|||
GitLab uses to create the workspace.
|
||||
1. In **Devfile location**, enter the path to the devfile you use to configure the workspace.
|
||||
If your devfile is not in the root directory of your project, specify a relative path.
|
||||
1. In **Workspace automatically terminates after**, enter the number of hours until the workspace automatically terminates.
|
||||
This timeout is a safety measure to prevent a workspace from consuming excessive resources or running indefinitely.
|
||||
1. In **Variables**, enter the keys and values of the environment variables you want to inject into the workspace.
|
||||
To add a new variable, select **Add variable**.
|
||||
1. Select **Create workspace**.
|
||||
|
|
|
|||
|
|
@ -17,7 +17,6 @@ module API
|
|||
:file_md5,
|
||||
:file_sha1,
|
||||
:size,
|
||||
:downloaded_at,
|
||||
:relative_path,
|
||||
:upstream_etag,
|
||||
:content_type,
|
||||
|
|
|
|||
|
|
@ -428,14 +428,7 @@ module API
|
|||
}
|
||||
],
|
||||
'telegram' => ::Integrations::Telegram.api_arguments,
|
||||
'unify-circuit' => [
|
||||
{
|
||||
required: true,
|
||||
name: :webhook,
|
||||
type: String,
|
||||
desc: 'The Unify Circuit webhook. e.g. https://circuit.com/rest/v2/webhooks/incoming/…'
|
||||
}
|
||||
].flatten,
|
||||
'unify-circuit' => ::Integrations::UnifyCircuit.api_arguments,
|
||||
'webex-teams' => ::Integrations::WebexTeams.api_arguments,
|
||||
'zentao' => [
|
||||
{
|
||||
|
|
|
|||
|
|
@ -91,6 +91,8 @@ module Gitlab
|
|||
rescue Timeout::Error => e
|
||||
class_name = name.demodulize
|
||||
Gitlab::ErrorTracking.track_exception(e, project_id: context[:project]&.id, class_name: class_name)
|
||||
|
||||
input
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -270,7 +270,9 @@ module Gitlab
|
|||
def parent_ids
|
||||
return @parent_ids unless @lazy_load_parents
|
||||
|
||||
@parent_ids ||= @repository.commit(id).parent_ids
|
||||
@parent_ids = @repository.commit(id).parent_ids if @parent_ids.nil? || @parent_ids.empty?
|
||||
|
||||
@parent_ids
|
||||
end
|
||||
|
||||
def parent_id
|
||||
|
|
|
|||
|
|
@ -74,7 +74,8 @@ module Gitlab
|
|||
line_code: note.line_code,
|
||||
created_at: note.created_at,
|
||||
updated_at: note.updated_at,
|
||||
st_diff: note.diff_hash.to_yaml
|
||||
st_diff: note.diff_hash.to_yaml,
|
||||
imported_from: ::Import::HasImportSource::IMPORT_SOURCES[:github]
|
||||
}
|
||||
|
||||
diff_note = LegacyDiffNote.new(attributes.merge(importing: true))
|
||||
|
|
@ -102,8 +103,9 @@ module Gitlab
|
|||
commit_id: note.original_commit_id,
|
||||
created_at: note.created_at,
|
||||
updated_at: note.updated_at,
|
||||
position: note.diff_position
|
||||
}).execute
|
||||
position: note.diff_position,
|
||||
imported_from: ::Import::SOURCE_GITHUB
|
||||
}).execute(importing: true)
|
||||
|
||||
raise DiffNoteCreationError, record unless record.persisted?
|
||||
|
||||
|
|
|
|||
|
|
@ -314,7 +314,7 @@ module Gitlab
|
|||
parse_params do |reviewer_param|
|
||||
extract_users(reviewer_param)
|
||||
end
|
||||
command :assign_reviewer, :reviewer, :request_review do |users|
|
||||
command :assign_reviewer, :reviewer do |users|
|
||||
next if users.empty?
|
||||
|
||||
if quick_action_target.allows_multiple_reviewers?
|
||||
|
|
@ -325,6 +325,54 @@ module Gitlab
|
|||
end
|
||||
end
|
||||
|
||||
########################################################################
|
||||
#
|
||||
# /request_review
|
||||
#
|
||||
desc do
|
||||
_('Request a review')
|
||||
end
|
||||
explanation do |users|
|
||||
_('Requests a review from %{reviewer_users_sentence}.') % { reviewer_users_sentence: reviewer_users_sentence(users) }
|
||||
end
|
||||
execution_message do |users = nil|
|
||||
if users.blank?
|
||||
_("Failed to request a review because no user was specified.")
|
||||
else
|
||||
_('Requested a review from %{reviewer_users_sentence}.') % { reviewer_users_sentence: reviewer_users_sentence(users) }
|
||||
end
|
||||
end
|
||||
params do
|
||||
quick_action_target.allows_multiple_reviewers? ? '@user1 @user2' : '@user'
|
||||
end
|
||||
types MergeRequest
|
||||
condition do
|
||||
current_user.can?(:"admin_#{quick_action_target.to_ability_name}", project)
|
||||
end
|
||||
parse_params do |reviewer_param|
|
||||
extract_users(reviewer_param)
|
||||
end
|
||||
command :request_review do |users|
|
||||
next if users.empty?
|
||||
|
||||
@updates[:reviewer_ids] ||= quick_action_target.reviewers.map(&:id)
|
||||
|
||||
service = ::MergeRequests::RequestReviewService.new(
|
||||
project: quick_action_target.project,
|
||||
current_user: current_user
|
||||
)
|
||||
|
||||
reviewers_to_add(users).each do |user|
|
||||
if @updates[:reviewer_ids].include?(user.id)
|
||||
# Request a new review from the reviewer if they are already assigned
|
||||
service.execute(quick_action_target, user)
|
||||
else
|
||||
# Assign the user as a reviewer if they are not already
|
||||
@updates[:reviewer_ids] << user.id
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
########################################################################
|
||||
#
|
||||
# /unassign_reviewer
|
||||
|
|
|
|||
|
|
@ -21798,6 +21798,9 @@ msgstr ""
|
|||
msgid "Environments|Stop"
|
||||
msgstr ""
|
||||
|
||||
msgid "Environments|Stop %{environmentName}"
|
||||
msgstr ""
|
||||
|
||||
msgid "Environments|Stop environment"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -21807,9 +21810,6 @@ msgstr ""
|
|||
msgid "Environments|Stop unused environments"
|
||||
msgstr ""
|
||||
|
||||
msgid "Environments|Stopping %{environmentName}"
|
||||
msgstr ""
|
||||
|
||||
msgid "Environments|Synced"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -23269,6 +23269,9 @@ msgstr ""
|
|||
msgid "Failed to remove user key."
|
||||
msgstr ""
|
||||
|
||||
msgid "Failed to request a review because no user was specified."
|
||||
msgstr ""
|
||||
|
||||
msgid "Failed to retrieve page"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -46514,6 +46517,9 @@ msgstr ""
|
|||
msgid "Request a new one"
|
||||
msgstr ""
|
||||
|
||||
msgid "Request a review"
|
||||
msgstr ""
|
||||
|
||||
msgid "Request changes"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -46547,6 +46553,9 @@ msgstr ""
|
|||
msgid "Requested %{time_ago}"
|
||||
msgstr ""
|
||||
|
||||
msgid "Requested a review from %{reviewer_users_sentence}."
|
||||
msgstr ""
|
||||
|
||||
msgid "Requested design version does not exist."
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -46562,6 +46571,9 @@ msgstr ""
|
|||
msgid "Requests a Duo Code Review"
|
||||
msgstr ""
|
||||
|
||||
msgid "Requests a review from %{reviewer_users_sentence}."
|
||||
msgstr ""
|
||||
|
||||
msgid "Requests for pages at %{code_start}%{help_text_url}%{code_end} redirect to the URL. The destination must meet certain requirements. %{docs_link_start}Learn more%{docs_link_end}."
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -55253,6 +55265,9 @@ msgstr ""
|
|||
msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
|
||||
msgstr ""
|
||||
|
||||
msgid "The Unify Circuit webhook (for example, `https://circuit.com/rest/v2/webhooks/incoming/...`)."
|
||||
msgstr ""
|
||||
|
||||
msgid "The XML file must be less than %{max_size} MB."
|
||||
msgstr ""
|
||||
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ FactoryBot.define do
|
|||
size { 100.bytes }
|
||||
sequence(:signature) { |n| "b91a152048fc4b3883bf3cf73fbc03f#{n}FFFFFFFF" }
|
||||
file_sha256 { 'dd1aaf26c557685cc37f93f53a2b6befb2c2e679f5ace6ec7a26d12086f358be' }
|
||||
project_id { package.project_id }
|
||||
|
||||
transient do
|
||||
file_fixture { 'spec/fixtures/packages/nuget/symbol/package.pdb' }
|
||||
|
|
@ -16,7 +17,7 @@ FactoryBot.define do
|
|||
symbol.file = fixture_file_upload(evaluator.file_fixture)
|
||||
end
|
||||
|
||||
trait :stale do
|
||||
trait :orphan do
|
||||
after(:create) do |entry|
|
||||
entry.update_attribute(:package_id, nil)
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { GlBadge, GlButton } from '@gitlab/ui';
|
||||
import { GlBadge } from '@gitlab/ui';
|
||||
import Vue from 'vue';
|
||||
import VueApollo from 'vue-apollo';
|
||||
import createMockApollo from 'helpers/mock_apollo_helper';
|
||||
|
|
@ -51,10 +51,11 @@ describe('PipelineFailedJobsWidget component', () => {
|
|||
});
|
||||
};
|
||||
|
||||
const findFailedJobsButton = () => wrapper.findComponent(GlButton);
|
||||
const findFailedJobsButton = () => wrapper.findByTestId('toggle-button');
|
||||
const findFailedJobsList = () => wrapper.findComponent(FailedJobsList);
|
||||
const findCrudComponent = () => wrapper.findComponent(CrudComponent);
|
||||
const findCount = () => wrapper.findComponent(GlBadge);
|
||||
const findFeedbackButton = () => wrapper.findByTestId('feedback-button');
|
||||
|
||||
describe('when there are failed jobs', () => {
|
||||
beforeEach(async () => {
|
||||
|
|
@ -93,6 +94,10 @@ describe('PipelineFailedJobsWidget component', () => {
|
|||
it('the failed jobs button has the correct "aria-expanded" attribute value', () => {
|
||||
expect(findFailedJobsButton().attributes('aria-expanded')).toBe('true');
|
||||
});
|
||||
|
||||
it('displays feedback button', () => {
|
||||
expect(findFeedbackButton().exists()).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when the job details are not expanded', () => {
|
||||
|
|
@ -107,6 +112,10 @@ describe('PipelineFailedJobsWidget component', () => {
|
|||
it('the failed jobs button has the correct "aria-expanded" attribute value', () => {
|
||||
expect(findFailedJobsButton().attributes('aria-expanded')).toBe('false');
|
||||
});
|
||||
|
||||
it('does not display feedback button', () => {
|
||||
expect(findFeedbackButton().exists()).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('"aria-controls" attribute', () => {
|
||||
|
|
|
|||
|
|
@ -123,6 +123,7 @@ describe('Merge requests list app', () => {
|
|||
recentSearchesStorageKey: 'merge_requests',
|
||||
sortOptions: getSortOptions({ hasManualSort: false }),
|
||||
initialSortBy: 'CREATED_DESC',
|
||||
issuableSymbol: '!',
|
||||
issuables: getQueryResponse.data.project.mergeRequests.nodes,
|
||||
tabs: mergeRequestListTabs,
|
||||
currentTab: 'opened',
|
||||
|
|
|
|||
|
|
@ -7,8 +7,8 @@ RSpec.describe API::Entities::VirtualRegistries::Packages::Maven::CachedResponse
|
|||
|
||||
subject { described_class.new(cached_response).as_json }
|
||||
|
||||
it do
|
||||
it 'has the expected attributes' do
|
||||
is_expected.to include(:cached_response_id, :group_id, :upstream_id, :upstream_checked_at, :created_at, :updated_at,
|
||||
:file, :file_md5, :file_sha1, :size, :downloaded_at, :relative_path, :upstream_etag, :content_type)
|
||||
:file, :file_md5, :file_sha1, :size, :relative_path, :upstream_etag, :content_type)
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -987,9 +987,9 @@ module Gitlab
|
|||
expect(Gitlab::ErrorTracking).to receive(:track_exception).with(
|
||||
instance_of(Timeout::Error),
|
||||
project_id: context[:project].id, class_name: described_class.name.demodulize
|
||||
)
|
||||
).and_call_original
|
||||
|
||||
render('<b>ascii</b>', context)
|
||||
expect(render('<b>ascii</b>', context)).to eq '<b>ascii</b>'
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -52,6 +52,7 @@ RSpec.describe Gitlab::GithubImport::Importer::DiffNoteImporter, :aggregate_fail
|
|||
|
||||
note = project.notes.diff_notes.take
|
||||
expect(note).to be_valid
|
||||
expect(note.imported_from).to eq(::Import::SOURCE_GITHUB.to_s)
|
||||
expect(note.author_id).to eq(user.id)
|
||||
expect(note.commit_id).to eq('original123abc')
|
||||
expect(note.created_at).to eq(created_at)
|
||||
|
|
@ -160,12 +161,18 @@ RSpec.describe Gitlab::GithubImport::Importer::DiffNoteImporter, :aggregate_fail
|
|||
end
|
||||
|
||||
it 'imports the note as diff note' do
|
||||
expect_next_instance_of(Import::Github::Notes::CreateService) do |service|
|
||||
expect(service).to receive(:execute).with(importing: true).and_call_original
|
||||
end
|
||||
|
||||
expect { subject.execute }
|
||||
.to change(DiffNote, :count)
|
||||
.by(1)
|
||||
.and not_change(LegacyDiffNote, :count)
|
||||
|
||||
note = project.notes.diff_notes.take
|
||||
expect(note).to be_valid
|
||||
expect(note.imported_from).to eq(::Import::SOURCE_GITHUB.to_s)
|
||||
expect(note.noteable_type).to eq('MergeRequest')
|
||||
expect(note.noteable_id).to eq(merge_request.id)
|
||||
expect(note.project_id).to eq(project.id)
|
||||
|
|
@ -313,12 +320,17 @@ RSpec.describe Gitlab::GithubImport::Importer::DiffNoteImporter, :aggregate_fail
|
|||
end
|
||||
|
||||
it 'imports the note as diff note' do
|
||||
expect_next_instance_of(Import::Github::Notes::CreateService) do |service|
|
||||
expect(service).to receive(:execute).with(importing: true).and_call_original
|
||||
end
|
||||
|
||||
expect { subject.execute }
|
||||
.to change(DiffNote, :count)
|
||||
.by(1)
|
||||
|
||||
note = project.notes.diff_notes.take
|
||||
expect(note).to be_valid
|
||||
expect(note.imported_from).to eq(::Import::SOURCE_GITHUB.to_s)
|
||||
expect(note.noteable_type).to eq('MergeRequest')
|
||||
expect(note.noteable_id).to eq(merge_request.id)
|
||||
expect(note.project_id).to eq(project.id)
|
||||
|
|
|
|||
|
|
@ -21,32 +21,45 @@ RSpec.describe Packages::Nuget::Symbol, type: :model, feature_category: :package
|
|||
it { is_expected.to validate_presence_of(:signature) }
|
||||
it { is_expected.to validate_presence_of(:object_storage_key) }
|
||||
it { is_expected.to validate_presence_of(:size) }
|
||||
it { is_expected.to validate_uniqueness_of(:signature).scoped_to(:file_path) }
|
||||
it { is_expected.to validate_uniqueness_of(:object_storage_key).case_insensitive }
|
||||
it { is_expected.to validate_uniqueness_of(:signature).scoped_to(:file_path, :package_id) }
|
||||
|
||||
context 'when package is nil' do
|
||||
let(:new_symbol) { build(:nuget_symbol, signature: symbol.signature) }
|
||||
|
||||
before do
|
||||
new_symbol.package = nil
|
||||
new_symbol.validate
|
||||
end
|
||||
|
||||
it 'does not validate uniqueness of signature' do
|
||||
expect(new_symbol.errors.messages_for(:signature)).not_to include 'has already been taken'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'delegations' do
|
||||
it { is_expected.to delegate_method(:project_id).to(:package) }
|
||||
it { is_expected.to delegate_method(:project).to(:package) }
|
||||
it { is_expected.to delegate_method(:project_id).to(:package).allow_nil }
|
||||
it { is_expected.to delegate_method(:project).to(:package).allow_nil }
|
||||
end
|
||||
|
||||
describe 'scopes' do
|
||||
describe '.stale' do
|
||||
subject { described_class.stale }
|
||||
describe '.orphan' do
|
||||
subject { described_class.orphan }
|
||||
|
||||
let_it_be(:symbol) { create(:nuget_symbol) }
|
||||
let_it_be(:stale_symbol) { create(:nuget_symbol, :stale) }
|
||||
let_it_be(:orphan_symbol) { create(:nuget_symbol, :orphan) }
|
||||
|
||||
it { is_expected.to contain_exactly(stale_symbol) }
|
||||
it { is_expected.to contain_exactly(orphan_symbol) }
|
||||
end
|
||||
|
||||
describe '.pending_destruction' do
|
||||
subject { described_class.pending_destruction }
|
||||
|
||||
let_it_be(:symbol) { create(:nuget_symbol, :stale, :processing) }
|
||||
let_it_be(:stale_symbol) { create(:nuget_symbol, :stale) }
|
||||
let_it_be(:symbol) { create(:nuget_symbol, :orphan, :processing) }
|
||||
let_it_be(:orphan_symbol) { create(:nuget_symbol, :orphan) }
|
||||
|
||||
it { is_expected.to contain_exactly(stale_symbol) }
|
||||
it { is_expected.to contain_exactly(orphan_symbol) }
|
||||
end
|
||||
|
||||
describe '.with_signature' do
|
||||
|
|
@ -122,6 +135,14 @@ RSpec.describe Packages::Nuget::Symbol, type: :model, feature_category: :package
|
|||
end
|
||||
|
||||
it { is_expected.to eq(symbol) }
|
||||
|
||||
context 'when package_id is not present' do
|
||||
before do
|
||||
symbol.update_column(:package_id, nil)
|
||||
end
|
||||
|
||||
it { is_expected.to be_nil }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -74,7 +74,7 @@ RSpec.describe VirtualRegistries::Packages::Maven::CachedResponse, type: :model,
|
|||
end
|
||||
|
||||
describe 'associations' do
|
||||
it do
|
||||
it 'belongs to an upstream' do
|
||||
is_expected.to belong_to(:upstream)
|
||||
.class_name('VirtualRegistries::Packages::Maven::Upstream')
|
||||
.inverse_of(:cached_responses)
|
||||
|
|
@ -180,16 +180,15 @@ RSpec.describe VirtualRegistries::Packages::Maven::CachedResponse, type: :model,
|
|||
|
||||
subject(:create_or_update) do
|
||||
with_threads do
|
||||
file = Tempfile.new('test.txt').tap { |f| f.write('test') }
|
||||
described_class.create_or_update_by!(
|
||||
upstream: upstream,
|
||||
group_id: upstream.group_id,
|
||||
relative_path: '/test',
|
||||
updates: { file: file, size: size, file_sha1: 'test' }
|
||||
)
|
||||
ensure
|
||||
file.close
|
||||
file.unlink
|
||||
Tempfile.create('test.txt') do |file|
|
||||
file.write('test')
|
||||
described_class.create_or_update_by!(
|
||||
upstream: upstream,
|
||||
group_id: upstream.group_id,
|
||||
relative_path: '/test',
|
||||
updates: { file: file, size: size, file_sha1: 'test' }
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -275,26 +274,6 @@ RSpec.describe VirtualRegistries::Packages::Maven::CachedResponse, type: :model,
|
|||
end
|
||||
end
|
||||
|
||||
describe '#bump_statistics', :freeze_time do
|
||||
let_it_be_with_reload(:cached_response) { create(:virtual_registries_packages_maven_cached_response) }
|
||||
|
||||
subject(:bump) { cached_response.bump_statistics }
|
||||
|
||||
it 'updates the correct statistics' do
|
||||
expect { bump }.to change { cached_response.downloaded_at }.to(Time.zone.now)
|
||||
end
|
||||
|
||||
context 'with include_upstream_checked_at' do
|
||||
subject(:bump) { cached_response.bump_statistics(include_upstream_checked_at: true) }
|
||||
|
||||
it 'updates the correct statistics' do
|
||||
expect { bump }
|
||||
.to change { cached_response.reload.downloaded_at }.to(Time.zone.now)
|
||||
.and change { cached_response.upstream_checked_at }.to(Time.zone.now)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'with loose foreign key on virtual_registries_packages_maven_cached_responses.upstream_id' do
|
||||
it_behaves_like 'update by a loose foreign key' do
|
||||
let_it_be(:parent) { create(:virtual_registries_packages_maven_upstream) }
|
||||
|
|
@ -315,12 +294,12 @@ RSpec.describe VirtualRegistries::Packages::Maven::CachedResponse, type: :model,
|
|||
# create a race condition - structure from https://blog.arkency.com/2015/09/testing-race-conditions/
|
||||
wait_for_it = true
|
||||
|
||||
threads = Array.new(count) do |i|
|
||||
threads = Array.new(count) do
|
||||
Thread.new do
|
||||
# A loop to make threads busy until we `join` them
|
||||
true while wait_for_it
|
||||
|
||||
yield(i)
|
||||
yield
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -1339,7 +1339,6 @@ RSpec.describe API::VirtualRegistries::Packages::Maven, :aggregate_failures, fea
|
|||
relative_path: "/#{path}",
|
||||
upstream_etag: nil,
|
||||
upstream_checked_at: Time.zone.now,
|
||||
downloaded_at: Time.zone.now,
|
||||
file_sha1: kind_of(String),
|
||||
file_md5: kind_of(String)
|
||||
)
|
||||
|
|
|
|||
|
|
@ -194,6 +194,30 @@ RSpec.describe Import::ReassignPlaceholderUserRecordsService, feature_category:
|
|||
)
|
||||
end
|
||||
|
||||
it 'calls UserProjectAccessChangedService' do
|
||||
expect_next_instance_of(UserProjectAccessChangedService, reassign_to_user.id) do |service|
|
||||
expect(service).to receive(:execute)
|
||||
end
|
||||
|
||||
service.execute
|
||||
end
|
||||
|
||||
it 'does not call UserProjectAccessChangedService when there are no memberships created' do
|
||||
Import::Placeholders::Membership.delete_all
|
||||
|
||||
expect(UserProjectAccessChangedService).not_to receive(:new)
|
||||
|
||||
expect { service.execute }.not_to change { Member.count }
|
||||
end
|
||||
|
||||
it 'does not call UserProjectAccessChangedService when only group memberships are created' do
|
||||
Import::Placeholders::Membership.where(project: project).delete_all
|
||||
|
||||
expect(UserProjectAccessChangedService).not_to receive(:new)
|
||||
|
||||
expect { service.execute }.to change { GroupMember.count }.by(1)
|
||||
end
|
||||
|
||||
it 'deletes reassigned placeholder references and memberships for the source user' do
|
||||
expect { service.execute }
|
||||
.to change { Import::SourceUserPlaceholderReference.where(source_user: source_user).count }.to(0)
|
||||
|
|
@ -203,6 +227,7 @@ RSpec.describe Import::ReassignPlaceholderUserRecordsService, feature_category:
|
|||
context 'when reassigned by user no longer exists' do
|
||||
before do
|
||||
source_user.reassigned_by_user.destroy!
|
||||
source_user.reload
|
||||
end
|
||||
|
||||
it 'can still create memberships' do
|
||||
|
|
@ -210,7 +235,8 @@ RSpec.describe Import::ReassignPlaceholderUserRecordsService, feature_category:
|
|||
end
|
||||
|
||||
it 'logs a warning' do
|
||||
expect(::Import::Framework::Logger).to receive(:warn).with(
|
||||
allow(Import::Framework::Logger).to receive(:warn)
|
||||
expect(Import::Framework::Logger).to receive(:warn).with(
|
||||
hash_including(
|
||||
message: 'Reassigned by user was not found, this may affect membership checks',
|
||||
source_user_id: source_user.id
|
||||
|
|
|
|||
|
|
@ -151,6 +151,14 @@ RSpec.describe Notes::CreateService, feature_category: :team_planning do
|
|||
described_class.new(project, user, opts).execute
|
||||
end
|
||||
|
||||
context 'when importing execute option is set to true' do
|
||||
it 'does not enqueue NewNoteWorker' do
|
||||
expect(NewNoteWorker).not_to receive(:perform_async)
|
||||
|
||||
described_class.new(project, user, opts).execute(importing: true)
|
||||
end
|
||||
end
|
||||
|
||||
context 'issue is an incident' do
|
||||
let(:issue) { create(:incident, project: project) }
|
||||
|
||||
|
|
|
|||
|
|
@ -1162,12 +1162,6 @@ RSpec.describe QuickActions::InterpretService, feature_category: :text_editors d
|
|||
it_behaves_like 'assign_reviewer command'
|
||||
end
|
||||
|
||||
context 'with the "request_review" alias' do
|
||||
let(:content) { "/request_review @#{developer.username}" }
|
||||
|
||||
it_behaves_like 'assign_reviewer command'
|
||||
end
|
||||
|
||||
context 'with no user' do
|
||||
let(:content) { '/assign_reviewer' }
|
||||
|
||||
|
|
@ -1183,6 +1177,91 @@ RSpec.describe QuickActions::InterpretService, feature_category: :text_editors d
|
|||
end
|
||||
end
|
||||
|
||||
describe 'request_review command' do
|
||||
let(:content) { "/request_review @#{developer.username}" }
|
||||
let(:issuable) { merge_request }
|
||||
|
||||
context 'with one user' do
|
||||
it 'assigns a reviewer to a single user' do
|
||||
_, updates, message = service.execute(content, issuable)
|
||||
translated_string = _("Requested a review from %{developer_to_reference}.")
|
||||
formatted_message = format(translated_string, developer_to_reference: developer.to_reference.to_s)
|
||||
|
||||
expect(updates).to eq(reviewer_ids: [developer.id])
|
||||
expect(message).to eq(formatted_message)
|
||||
end
|
||||
|
||||
it 'explains command' do
|
||||
_, explanations = service.explain(content, issuable)
|
||||
|
||||
expect(explanations).to eq(["Requests a review from #{developer.to_reference}."])
|
||||
end
|
||||
end
|
||||
|
||||
context 'when user is already assigned' do
|
||||
let(:merge_request) { create(:merge_request, source_project: project, reviewers: [developer]) }
|
||||
|
||||
it 'requests a review' do
|
||||
expect_next_instance_of(::MergeRequests::RequestReviewService) do |service|
|
||||
expect(service).to receive(:execute).with(merge_request, developer)
|
||||
end
|
||||
|
||||
_, _, message = service.execute(content, issuable)
|
||||
|
||||
translated_string = _("Requested a review from %{developer_to_reference}.")
|
||||
formatted_message = format(translated_string, developer_to_reference: developer.to_reference.to_s)
|
||||
|
||||
expect(message).to eq(formatted_message)
|
||||
end
|
||||
end
|
||||
|
||||
# CE does not have multiple reviewers
|
||||
context 'assign command with multiple reviewers' do
|
||||
before do
|
||||
project.add_developer(developer2)
|
||||
end
|
||||
|
||||
# There's no guarantee that the reference extractor will preserve
|
||||
# the order of the mentioned users since this is dependent on the
|
||||
# order in which rows are returned. We just ensure that at least
|
||||
# one of the mentioned users is assigned.
|
||||
context 'assigns to one of the two users' do
|
||||
let(:content) { "/request_review @#{developer.username} @#{developer2.username}" }
|
||||
|
||||
it 'assigns to a single reviewer' do
|
||||
_, updates, message = service.execute(content, issuable)
|
||||
|
||||
expect(updates[:reviewer_ids].count).to eq(1)
|
||||
reviewer = updates[:reviewer_ids].first
|
||||
expect([developer.id, developer2.id]).to include(reviewer)
|
||||
|
||||
user = reviewer == developer.id ? developer : developer2
|
||||
|
||||
expect(message).to match("Requested a review from #{user.to_reference}.")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'with "me" alias' do
|
||||
let(:content) { '/request_review me' }
|
||||
|
||||
it 'assigns a reviewer to a single user' do
|
||||
_, updates, message = service.execute(content, issuable)
|
||||
translated_string = _("Requested a review from %{developer_to_reference}.")
|
||||
formatted_message = format(translated_string, developer_to_reference: developer.to_reference.to_s)
|
||||
|
||||
expect(updates).to eq(reviewer_ids: [developer.id])
|
||||
expect(message).to eq(formatted_message)
|
||||
end
|
||||
end
|
||||
|
||||
context 'with no user' do
|
||||
let(:content) { '/request_review' }
|
||||
|
||||
it_behaves_like 'failed command', "Failed to request a review because no user was specified."
|
||||
end
|
||||
end
|
||||
|
||||
describe 'unassign_reviewer command' do
|
||||
# CE does not have multiple reviewers, so basically anything
|
||||
# after /unassign_reviewer (including whitespace) will remove
|
||||
|
|
|
|||
|
|
@ -33,7 +33,6 @@ RSpec.describe VirtualRegistries::Packages::Maven::CachedResponses::CreateOrUpda
|
|||
expect(last_cached_response).to have_attributes(
|
||||
group_id: registry.group.id,
|
||||
upstream_checked_at: Time.zone.now,
|
||||
downloaded_at: Time.zone.now,
|
||||
relative_path: "/#{path}",
|
||||
upstream_etag: etag,
|
||||
content_type: content_type,
|
||||
|
|
@ -72,7 +71,6 @@ RSpec.describe VirtualRegistries::Packages::Maven::CachedResponses::CreateOrUpda
|
|||
expect(execute.payload).to eq(cached_response: last_cached_response)
|
||||
|
||||
expect(last_cached_response).to have_attributes(
|
||||
downloaded_at: Time.zone.now,
|
||||
upstream_checked_at: Time.zone.now,
|
||||
upstream_etag: etag
|
||||
)
|
||||
|
|
|
|||
|
|
@ -82,12 +82,6 @@ RSpec.describe VirtualRegistries::Packages::Maven::HandleFileRequestService, :ag
|
|||
|
||||
it_behaves_like 'returning a service response success response', action: :download_file
|
||||
|
||||
it 'bumps the statistics', :freeze_time do
|
||||
stub_external_registry_request(etag: etag_returned_by_upstream)
|
||||
|
||||
expect { execute }.to change { cached_response.reload.downloaded_at }.to(Time.zone.now)
|
||||
end
|
||||
|
||||
context 'and is too old' do
|
||||
before do
|
||||
cached_response.update!(upstream_checked_at: 1.year.ago)
|
||||
|
|
@ -101,9 +95,7 @@ RSpec.describe VirtualRegistries::Packages::Maven::HandleFileRequestService, :ag
|
|||
it 'bumps the statistics', :freeze_time do
|
||||
stub_external_registry_request(etag: etag_returned_by_upstream)
|
||||
|
||||
expect { execute }
|
||||
.to change { cached_response.reload.downloaded_at }.to(Time.zone.now)
|
||||
.and change { cached_response.upstream_checked_at }.to(Time.zone.now)
|
||||
expect { execute }.to change { cached_response.reload.upstream_checked_at }.to(Time.zone.now)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -87,7 +87,7 @@ RSpec.describe Packages::CleanupPackageRegistryWorker, type: :worker, feature_ca
|
|||
end
|
||||
|
||||
context 'with nuget symbols pending destruction' do
|
||||
let_it_be(:nuget_symbol) { create(:nuget_symbol, :stale) }
|
||||
let_it_be(:nuget_symbol) { create(:nuget_symbol, :orphan) }
|
||||
|
||||
it_behaves_like 'an idempotent worker' do
|
||||
it 'queues the cleanup job' do
|
||||
|
|
|
|||
|
|
@ -21,9 +21,9 @@ RSpec.describe Packages::Nuget::CleanupStaleSymbolsWorker, type: :worker, featur
|
|||
|
||||
context 'with work to do' do
|
||||
let_it_be(:symbol_1) { create(:nuget_symbol) }
|
||||
let_it_be(:symbol_2) { create(:nuget_symbol, :stale) }
|
||||
let_it_be(:symbol_2) { create(:nuget_symbol, :orphan) }
|
||||
|
||||
it 'deletes the stale symbol', :aggregate_failures do
|
||||
it 'deletes the orphan symbol', :aggregate_failures do
|
||||
expect(worker).to receive(:log_extra_metadata_on_done).with(:nuget_symbol_id, symbol_2.id)
|
||||
expect(Packages::Nuget::Symbol).to receive(:next_pending_destruction).with(order_by: nil).and_call_original
|
||||
expect { perform_work }.to change { Packages::Nuget::Symbol.count }.by(-1)
|
||||
|
|
@ -31,8 +31,8 @@ RSpec.describe Packages::Nuget::CleanupStaleSymbolsWorker, type: :worker, featur
|
|||
end
|
||||
end
|
||||
|
||||
context 'with a stale symbol' do
|
||||
let_it_be(:symbol) { create(:nuget_symbol, :stale) }
|
||||
context 'with an orphan symbol' do
|
||||
let_it_be(:symbol) { create(:nuget_symbol, :orphan) }
|
||||
|
||||
context 'with an error during deletion' do
|
||||
before do
|
||||
|
|
|
|||
Loading…
Reference in New Issue