Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2024-10-28 09:22:00 +00:00
parent 7129754815
commit 6e8929e31d
32 changed files with 329 additions and 79 deletions

View File

@ -1 +1 @@
fd923fb927c727b14365468890dfc41a53794682
f5b045d8694528efbe2e08984ac5867bdfe41aee

View File

@ -30,6 +30,10 @@ module Packages
end
end
def can_create_package?
can?(current_user, :create_package, project)
end
private
def package_attrs(attrs)

View File

@ -6,13 +6,13 @@ module Packages
include ::Gitlab::Utils::StrongMemoize
ERROR_REASON_INVALID_PARAMETER = :invalid_parameter
ERROR_REASON_PACKAGE_PROTECTED = :package_protected
ERROR_RESPONSE_PACKAGE_PROTECTED =
ServiceResponse.error(message: 'Package protected.', reason: :package_protected)
ERROR_RESPONSE_UNAUTHORIZED = ServiceResponse.error(message: 'Unauthorized', reason: :unauthorized)
def execute
if current_package_protected?
return ServiceResponse.error(message: 'Package protected.',
reason: ERROR_REASON_PACKAGE_PROTECTED)
end
return ERROR_RESPONSE_UNAUTHORIZED unless can_create_package?
return ERROR_RESPONSE_PACKAGE_PROTECTED if current_package_protected?
::Packages::Package.transaction do
meta = Packages::Pypi::Metadatum.new(

View File

@ -3,7 +3,6 @@ migration_job_name: BackfillIncidentManagementPendingAlertEscalationsProjectId
description: Backfills sharding key `incident_management_pending_alert_escalations.project_id` from `alert_management_alerts`.
feature_category: incident_management
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/166816
milestone: '17.5'
queued_migration_version: 20240922141648
finalize_after: '2024-10-22'
milestone: '17.6'
queued_migration_version: 20241025073808
finalized_by: # version of the migration that finalized this BBM

View File

@ -0,0 +1,9 @@
# frozen_string_literal: true
class AddCreatedByToCustomFields < Gitlab::Database::Migration[2.2]
milestone '17.6'
def change
add_reference :custom_fields, :created_by, index: true, foreign_key: { on_delete: :nullify, to_table: :users } # rubocop:disable Migration/AddReference -- table is empty
end
end

View File

@ -0,0 +1,9 @@
# frozen_string_literal: true
class AddUpdatedByToCustomFields < Gitlab::Database::Migration[2.2]
milestone '17.6'
def change
add_reference :custom_fields, :updated_by, index: true, foreign_key: { on_delete: :nullify, to_table: :users } # rubocop:disable Migration/AddReference -- table is empty
end
end

View File

@ -7,13 +7,12 @@ class AddIncidentManagementPendingAlertEscalationsProjectIdFk < Gitlab::Database
disable_ddl_transaction!
def up
add_concurrent_partitioned_foreign_key :incident_management_pending_alert_escalations, :projects,
column: :project_id, on_delete: :cascade
# no-op because there was a bug in the original migration, which has been
# fixed by https://gitlab.com/gitlab-org/gitlab/-/merge_requests/168212
end
def down
with_lock_retries do
remove_foreign_key :incident_management_pending_alert_escalations, column: :project_id
end
# no-op because there was a bug in the original migration, which has been
# fixed by https://gitlab.com/gitlab-org/gitlab/-/merge_requests/168212
end
end

View File

@ -4,22 +4,12 @@ class AddIncidentManagementPendingAlertEscalationsProjectIdTrigger < Gitlab::Dat
milestone '17.5'
def up
install_sharding_key_assignment_trigger(
table: :incident_management_pending_alert_escalations,
sharding_key: :project_id,
parent_table: :alert_management_alerts,
parent_sharding_key: :project_id,
foreign_key: :alert_id
)
# no-op because there was a bug in the original migration, which has been
# fixed by https://gitlab.com/gitlab-org/gitlab/-/merge_requests/168212
end
def down
remove_sharding_key_assignment_trigger(
table: :incident_management_pending_alert_escalations,
sharding_key: :project_id,
parent_table: :alert_management_alerts,
parent_sharding_key: :project_id,
foreign_key: :alert_id
)
# no-op because there was a bug in the original migration, which has been
# fixed by https://gitlab.com/gitlab-org/gitlab/-/merge_requests/168212
end
end

View File

@ -10,32 +10,12 @@ class QueueBackfillIncidentManagementPendingAlertEscalationsProjectId < Gitlab::
SUB_BATCH_SIZE = 100
def up
queue_batched_background_migration(
MIGRATION,
:incident_management_pending_alert_escalations,
:id,
:project_id,
:alert_management_alerts,
:project_id,
:alert_id,
job_interval: DELAY_INTERVAL,
batch_size: BATCH_SIZE,
batch_class_name: 'LooseIndexScanBatchingStrategy',
sub_batch_size: SUB_BATCH_SIZE
)
# no-op because there was a bug in the original migration, which has been
# fixed by https://gitlab.com/gitlab-org/gitlab/-/merge_requests/168212
end
def down
delete_batched_background_migration(
MIGRATION,
:incident_management_pending_alert_escalations,
:id,
[
:project_id,
:alert_management_alerts,
:project_id,
:alert_id
]
)
# no-op because there was a bug in the original migration, which has been
# fixed by https://gitlab.com/gitlab-org/gitlab/-/merge_requests/168212
end
end

View File

@ -0,0 +1,16 @@
# frozen_string_literal: true
class RemoveBbmIncidentManagementPendingAlertEscProjectId < Gitlab::Database::Migration[2.2]
milestone '17.6'
restrict_gitlab_migration gitlab_schema: :gitlab_main_cell
MIGRATION = "BackfillIncidentManagementPendingAlertEscalationsProjectId"
def up
delete_batched_background_migration(MIGRATION, :incident_management_pending_alert_escalations, :id,
[:project_id, :alert_management_alerts, :project_id, :alert_id])
end
def down; end
end

View File

@ -0,0 +1,21 @@
# frozen_string_literal: true
class RemoveIncidentManagementPendingAlertEscProjectIdFk < Gitlab::Database::Migration[2.2]
include Gitlab::Database::PartitioningMigrationHelpers
milestone '17.6'
disable_ddl_transaction!
CONSTRAINT_NAME = 'fk_rails_2bbafb00ef'
def up
with_lock_retries do
remove_foreign_key_if_exists(:incident_management_pending_alert_escalations, :projects, name: CONSTRAINT_NAME)
end
end
def down
add_concurrent_partitioned_foreign_key :incident_management_pending_alert_escalations, :projects,
column: :project_id, on_delete: :cascade, name: CONSTRAINT_NAME
end
end

View File

@ -0,0 +1,38 @@
# frozen_string_literal: true
class RemoveIncidentManagementPendingAlertEscProjectIdTrigger < Gitlab::Database::Migration[2.2]
milestone '17.6'
disable_ddl_transaction!
def up
with_lock_retries do
execute <<~SQL
DROP TRIGGER IF EXISTS trigger_2a994bb5629f ON incident_management_pending_alert_escalations;
DROP FUNCTION IF EXISTS trigger_2a994bb5629f();
SQL
end
end
def down
execute <<~SQL
CREATE FUNCTION trigger_2a994bb5629f() RETURNS trigger
LANGUAGE plpgsql
AS $$
BEGIN
IF NEW."project_id" IS NULL THEN
SELECT "project_id"
INTO NEW."project_id"
FROM "alert_management_alerts"
WHERE "alert_management_alerts"."id" = NEW."alert_id";
END IF;
RETURN NEW;
END;
$$;
CREATE TRIGGER trigger_2a994bb5629f
BEFORE INSERT OR UPDATE ON incident_management_pending_alert_escalations
FOR EACH ROW
EXECUTE FUNCTION trigger_2a994bb5629f();
SQL
end
end

View File

@ -0,0 +1,20 @@
# frozen_string_literal: true
class AddIncidentManagementPendingAlertEscProjectIdFk < Gitlab::Database::Migration[2.2]
include Gitlab::Database::PartitioningMigrationHelpers
milestone '17.6'
disable_ddl_transaction!
def up
add_concurrent_partitioned_foreign_key :incident_management_pending_alert_escalations, :projects,
column: :project_id, on_delete: :cascade, reverse_lock_order: true
end
def down
with_lock_retries do
remove_foreign_key_if_exists :incident_management_pending_alert_escalations, column: :project_id,
reverse_lock_order: true
end
end
end

View File

@ -0,0 +1,25 @@
# frozen_string_literal: true
class AddIncidentManagementPendingAlertEscProjectIdTrigger < Gitlab::Database::Migration[2.2]
milestone '17.6'
def up
install_sharding_key_assignment_trigger(
table: :incident_management_pending_alert_escalations,
sharding_key: :project_id,
parent_table: :alert_management_alerts,
parent_sharding_key: :project_id,
foreign_key: :alert_id
)
end
def down
remove_sharding_key_assignment_trigger(
table: :incident_management_pending_alert_escalations,
sharding_key: :project_id,
parent_table: :alert_management_alerts,
parent_sharding_key: :project_id,
foreign_key: :alert_id
)
end
end

View File

@ -0,0 +1,42 @@
# frozen_string_literal: true
class QueueBackfillIncidentManagementPendingAlertEscProjectId < Gitlab::Database::Migration[2.2]
milestone '17.6'
restrict_gitlab_migration gitlab_schema: :gitlab_main_cell
MIGRATION = "BackfillIncidentManagementPendingAlertEscalationsProjectId"
DELAY_INTERVAL = 2.minutes
BATCH_SIZE = 1000
SUB_BATCH_SIZE = 100
def up
queue_batched_background_migration(
MIGRATION,
:incident_management_pending_alert_escalations,
:id,
:project_id,
:alert_management_alerts,
:project_id,
:alert_id,
job_interval: DELAY_INTERVAL,
batch_size: BATCH_SIZE,
batch_class_name: 'LooseIndexScanBatchingStrategy',
sub_batch_size: SUB_BATCH_SIZE
)
end
def down
delete_batched_background_migration(
MIGRATION,
:incident_management_pending_alert_escalations,
:id,
[
:project_id,
:alert_management_alerts,
:project_id,
:alert_id
]
)
end
end

View File

@ -0,0 +1 @@
a0e4e34019e63322618d0bad2a1c271f07dfb99852ef913045e35bbba7f2a6a1

View File

@ -0,0 +1 @@
0f9f28442fc0a89d1beb1f89b17df636a409e6841f9ab234dc8297a6fb4625aa

View File

@ -0,0 +1 @@
d9f0d28c35d08427014710004597625e351f8c8ad9fb2e244887c9201e0177ea

View File

@ -0,0 +1 @@
d30a5ae139557ab677d23941ce5b55ecb0f6d67f7b55035ea33fb229eb236cc6

View File

@ -0,0 +1 @@
345f6b90e74d6c7a5e6133d4f895717f76aa4156ac877cd494c5e16c320a053a

View File

@ -0,0 +1 @@
0f7f885d6493a5c9b6a13641d5e516190511a077f0b91f4d7f2e0cdf4c99e135

View File

@ -0,0 +1 @@
55055788e7c493b41c9d18f5cb03dacd157827cd92d31dd40d4790e2b3a6373d

View File

@ -0,0 +1 @@
c4a17ceba5f4174bd71068b5ff12d2f38b1c744e6304cbdd635320929fbb868b

View File

@ -10162,6 +10162,8 @@ CREATE TABLE custom_fields (
archived_at timestamp with time zone,
field_type smallint NOT NULL,
name text NOT NULL,
created_by_id bigint,
updated_by_id bigint,
CONSTRAINT check_b047b04af9 CHECK ((char_length(name) <= 255))
);
@ -28765,6 +28767,10 @@ CREATE UNIQUE INDEX index_custom_emoji_on_namespace_id_and_name ON custom_emoji
CREATE INDEX index_custom_field_select_options_on_namespace_id ON custom_field_select_options USING btree (namespace_id);
CREATE INDEX index_custom_fields_on_created_by_id ON custom_fields USING btree (created_by_id);
CREATE INDEX index_custom_fields_on_updated_by_id ON custom_fields USING btree (updated_by_id);
CREATE UNIQUE INDEX index_custom_software_licenses_on_project_id_and_name ON custom_software_licenses USING btree (project_id, name);
CREATE INDEX index_customer_relations_contacts_on_group_id ON customer_relations_contacts USING btree (group_id);
@ -36232,6 +36238,9 @@ ALTER TABLE ONLY ci_builds
ALTER TABLE ONLY upcoming_reconciliations
ADD CONSTRAINT fk_rails_497b4938ac FOREIGN KEY (namespace_id) REFERENCES namespaces(id) ON DELETE CASCADE;
ALTER TABLE ONLY custom_fields
ADD CONSTRAINT fk_rails_4a74c8558e FOREIGN KEY (created_by_id) REFERENCES users(id) ON DELETE SET NULL;
ALTER TABLE ONLY group_deletion_schedules
ADD CONSTRAINT fk_rails_4b8c694a6c FOREIGN KEY (group_id) REFERENCES namespaces(id) ON DELETE CASCADE;
@ -36628,6 +36637,9 @@ ALTER TABLE ONLY dependency_proxy_manifest_states
ALTER TABLE ONLY ci_job_artifact_states
ADD CONSTRAINT fk_rails_80a9cba3b2_p FOREIGN KEY (partition_id, job_artifact_id) REFERENCES p_ci_job_artifacts(partition_id, id) ON UPDATE CASCADE ON DELETE CASCADE;
ALTER TABLE ONLY custom_fields
ADD CONSTRAINT fk_rails_80c4a47616 FOREIGN KEY (updated_by_id) REFERENCES users(id) ON DELETE SET NULL;
ALTER TABLE ONLY approval_merge_request_rules_users
ADD CONSTRAINT fk_rails_80e6801803 FOREIGN KEY (approval_merge_request_rule_id) REFERENCES approval_merge_request_rules(id) ON DELETE CASCADE;

View File

@ -102,7 +102,7 @@ for all authenticated users, and on the **Admin** area pages. The statuses are:
- Red: The version of GitLab you are running is vulnerable. You should install
the latest version with security fixes as soon as possible.
![Orange version check example](../settings/img/update_available_v10_6.png)
![Version check showing that a non-critical update is available for the GitLab instance](../settings/img/update_available_v10_6.png)
### Enable or disable version check

View File

@ -3880,6 +3880,55 @@ Input type: `CreateTestCaseInput`
| <a id="mutationcreatetestcaseerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
| <a id="mutationcreatetestcasetestcase"></a>`testCase` | [`Issue`](#issue) | Test case created. |
### `Mutation.customFieldCreate`
DETAILS:
**Introduced** in GitLab 17.6.
**Status**: Experiment.
Input type: `CustomFieldCreateInput`
#### Arguments
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="mutationcustomfieldcreateclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
| <a id="mutationcustomfieldcreatefieldtype"></a>`fieldType` | [`CustomFieldType!`](#customfieldtype) | Type of custom field. |
| <a id="mutationcustomfieldcreategrouppath"></a>`groupPath` | [`ID!`](#id) | Group path where the custom field is created. |
| <a id="mutationcustomfieldcreatename"></a>`name` | [`String!`](#string) | Name of the custom field. |
#### Fields
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="mutationcustomfieldcreateclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
| <a id="mutationcustomfieldcreatecustomfield"></a>`customField` | [`CustomField`](#customfield) | Created custom field. |
| <a id="mutationcustomfieldcreateerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
### `Mutation.customFieldUpdate`
DETAILS:
**Introduced** in GitLab 17.6.
**Status**: Experiment.
Input type: `CustomFieldUpdateInput`
#### Arguments
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="mutationcustomfieldupdateclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
| <a id="mutationcustomfieldupdateid"></a>`id` | [`IssuablesCustomFieldID!`](#issuablescustomfieldid) | Global ID of the custom field. |
| <a id="mutationcustomfieldupdatename"></a>`name` | [`String!`](#string) | Name of the custom field. |
#### Fields
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="mutationcustomfieldupdateclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
| <a id="mutationcustomfieldupdatecustomfield"></a>`customField` | [`CustomField`](#customfield) | Updated custom field. |
| <a id="mutationcustomfieldupdateerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
### `Mutation.customerRelationsContactCreate`
Input type: `CustomerRelationsContactCreateInput`
@ -21420,11 +21469,13 @@ Represents a custom field.
| ---- | ---- | ----------- |
| <a id="customfieldactive"></a>`active` | [`Boolean!`](#boolean) | Whether the custom field is active. |
| <a id="customfieldcreatedat"></a>`createdAt` | [`Time!`](#time) | Timestamp when the custom field was created. |
| <a id="customfieldcreatedby"></a>`createdBy` | [`UserCore`](#usercore) | User that created the custom field. |
| <a id="customfieldfieldtype"></a>`fieldType` | [`CustomFieldType!`](#customfieldtype) | Type of custom field. |
| <a id="customfieldid"></a>`id` | [`IssuablesCustomFieldID!`](#issuablescustomfieldid) | Global ID of the custom field. |
| <a id="customfieldname"></a>`name` | [`String!`](#string) | Name of the custom field. |
| <a id="customfieldselectoptions"></a>`selectOptions` | [`[CustomFieldSelectOption!]`](#customfieldselectoption) | Available options for a select field. |
| <a id="customfieldupdatedat"></a>`updatedAt` | [`Time!`](#time) | Timestamp when the custom field was last updated. |
| <a id="customfieldupdatedby"></a>`updatedBy` | [`UserCore`](#usercore) | User that last updated the custom field. |
| <a id="customfieldworkitemtypes"></a>`workItemTypes` | [`[WorkItemType!]`](#workitemtype) | Work item types that the custom field is available on. |
### `CustomFieldSelectOption`

View File

@ -76,7 +76,7 @@ The first step is to benchmark the cadence of code releases between groups and p
Lead time for changes is the amount of time it takes a code change to get into production.
**Lead time for changes** is not the same as **Lead time**. In the value stream, lead time measures the time it takes for work on an issue to move from the moment it's requested (Issue created) to the moment it's fulfilled and delivered (Issue closed).
**Lead time for changes** is not the same as **Lead time**. In value stream analytics, lead time measures the time it takes for work on an issue to move from the moment it's requested (Issue created) to the moment it's fulfilled and delivered (Issue closed).
For software leaders, lead time for changes reflects the efficiency of CI/CD pipelines and visualizes how quickly work is delivered to customers.
Over time, the lead time for changes should decrease, while your team's performance should increase. Low lead time for changes means more efficient CI/CD pipelines.
@ -94,6 +94,7 @@ The first step is to benchmark the CI/CD pipelines' efficiency between groups an
- Using Value Stream Analytics to identify bottlenecks in the processes.
- Breaking the changes down into smaller iterations.
- Adding automation.
- Improving the performance of your pipelines.
## Time to restore service
@ -104,7 +105,7 @@ Low time to restore service means the organization can take risks with new innov
### How time to restore service is calculated
In GitLab, time to restore service is measured as the median time an incident was open for on a production environment.
In GitLab, time to restore service is measured as the median time an incident was open on a production environment.
GitLab calculates the number of seconds an incident was open on a production environment in the given time period. This assumes:
- [GitLab incidents](../../operations/incident_management/incidents.md) are tracked.
@ -117,17 +118,18 @@ The first step is to benchmark the team response and recover from service interr
- Improving the observability into the production environment.
- Improving response workflows.
- Improving deployment frequency and lead time for changes so fixes can get into production more efficiently.
## Change failure rate
Change failure rate is how often a change cause failure in production.
Change failure rate is how often a change causes a failure in production.
Software leaders can use the change failure rate metric to gain insights into the quality of the code being shipped.
High change failure rate may indicate an inefficient deployment process or insufficient automated testing coverage.
### How change failure rate is calculated
In GitLab, change failure rate is measured as the percentage of deployments that cause an incident in production in the given time period.
In GitLab, change failure rate is measured as the percentage of deployments that cause an incident in production in a given time period.
GitLab calculates change failure rate as the number of incidents divided by the number of deployments to a production environment. This calculation assumes:
- [GitLab incidents](../../operations/incident_management/incidents.md) are tracked.
@ -227,7 +229,7 @@ These deployment records are not created for pull-based deployments, for example
To track DORA metrics in these cases, you can [create a deployment record](../../api/deployments.md#create-a-deployment) using the Deployments API.
You must set the environment name where the deployment tier is configured, because the tier variable is specified for the given environment, not for the deployments.
For more information, see [Track deployments of an external deployment tool](../../ci/environments/external_deployment_tools.md).
For more information, see [track deployments of an external deployment tool](../../ci/environments/external_deployment_tools.md).
### Measure DORA metrics with Jira
@ -239,7 +241,7 @@ For more information, see [Track deployments of an external deployment tool](../
For PagerDuty, you can set up a [webhook to automatically create a GitLab incident for each PagerDuty incident](../../operations/incident_management/manage_incidents.md#using-the-pagerduty-webhook).
This configuration requires you to make changes in both PagerDuty and GitLab.
For others incident management tools, you can set up the
For other incident management tools, you can set up the
[HTTP integration](../../operations/incident_management/integrations.md#http-endpoints),
and use it to automatically:
@ -252,8 +254,8 @@ The table below provides an overview of the DORA metrics' availability in projec
| Metric | Level | Comments |
|---------------------------|-------------------|----------|
| `deployment_frequency` | Project | |
| `deployment_frequency` | Group | |
| `deployment_frequency` | Project | Unit in deployment count. |
| `deployment_frequency` | Group | Unit in deployment count. Aggregation method is average. |
| `lead_time_for_changes` | Project | Unit in seconds. Aggregation method is median. |
| `lead_time_for_changes` | Group | Unit in seconds. Aggregation method is median. |
| `time_to_restore_service` | Project and group | Unit in days. Aggregation method is median. (Available in UI chart in GitLab 15.1 and later) |

View File

@ -27,8 +27,8 @@ To view contribution analytics:
Three bar charts and a table illustrate the number of contributions made by each group member:
- Push events
- Merge requests
- Closed issues
- Created, merged, and closed merge requests
- Created and closed issues
### View a member's contributions

View File

@ -306,7 +306,7 @@ module API
.new(project, current_user, declared_params.merge(build: current_authenticated_job))
.execute
if service_response.error? && service_response.reason == Packages::Pypi::CreatePackageService::ERROR_REASON_PACKAGE_PROTECTED
if service_response.error? && service_response.reason == Packages::Pypi::CreatePackageService::ERROR_RESPONSE_PACKAGE_PROTECTED.reason
forbidden!(service_response.message)
end

View File

@ -64535,6 +64535,9 @@ msgstr ""
msgid "can only be changed by a group admin."
msgstr ""
msgid "can only have a maximum of %{limit} active custom fields."
msgstr ""
msgid "can only have one escalation policy"
msgstr ""

View File

@ -3,7 +3,7 @@
require 'spec_helper'
require_migration!
RSpec.describe QueueBackfillIncidentManagementPendingAlertEscalationsProjectId, feature_category: :incident_management do
RSpec.describe QueueBackfillIncidentManagementPendingAlertEscProjectId, feature_category: :incident_management do
let!(:batched_migration) { described_class::MIGRATION }
it 'schedules a new batched migration' do

View File

@ -24,9 +24,21 @@ RSpec.describe Packages::Pypi::CreatePackageService, :aggregate_failures, featur
}
end
describe '#execute' do
subject(:execute_service) { described_class.new(project, user, params).execute }
subject(:execute_service) { described_class.new(project, user, params).execute }
shared_examples 'an error response while not creating a pypi package' do |message:, reason:|
it_behaves_like 'returning an error service response', message: message
it { is_expected.to have_attributes(reason: reason) }
it 'does not create any pypi-related package records' do
expect { execute_service }
.to not_change { Packages::Package.count }
.and not_change { Packages::Package.pypi.count }
.and not_change { Packages::PackageFile.count }
end
end
describe '#execute' do
let(:created_package) { Packages::Package.pypi.last }
context 'without an existing package' do
@ -150,16 +162,9 @@ RSpec.describe Packages::Pypi::CreatePackageService, :aggregate_failures, featur
params[:md5_digest] = md5
end
it_behaves_like 'returning an error service response',
message: 'Validation failed: File name has already been taken' do
it { is_expected.to have_attributes(reason: :invalid_parameter) }
end
it 'does not create a pypi package' do
expect { execute_service }
.to change { Packages::Package.pypi.count }.by(0)
.and change { Packages::PackageFile.count }.by(0)
end
it_behaves_like 'an error response while not creating a pypi package',
message: 'Validation failed: File name has already been taken',
reason: :invalid_parameter
context 'with a pending_destruction package' do
before do
@ -199,6 +204,22 @@ RSpec.describe Packages::Pypi::CreatePackageService, :aggregate_failures, featur
end
end
context 'with unauthorized user' do
let_it_be(:user) { create(:user) }
it_behaves_like 'an error response while not creating a pypi package',
message: 'Unauthorized',
reason: :unauthorized
end
context 'without user' do
let_it_be(:user) { nil }
it_behaves_like 'an error response while not creating a pypi package',
message: 'Unauthorized',
reason: :unauthorized
end
context 'with package protection rule for different roles and package_name_patterns' do
let_it_be_with_reload(:package_protection_rule) do
create(:package_protection_rule, package_type: :pypi, project: project)
@ -245,8 +266,9 @@ RSpec.describe Packages::Pypi::CreatePackageService, :aggregate_failures, featur
end
shared_examples 'an error service response for unauthorized' do
it_behaves_like 'returning an error service response', message: 'Unauthorized'
it { is_expected.to have_attributes(reason: :invalid_parameter) }
it_behaves_like 'an error response while not creating a pypi package',
message: 'Unauthorized',
reason: :unauthorized
end
before do