Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
9aca3d8ca6
commit
267bb63c52
|
|
@ -1,9 +1,7 @@
|
|||
@import 'mixins_and_variables_and_functions';
|
||||
|
||||
@import '@gitlab/ui/src/scss/bootstrap';
|
||||
@import 'bootstrap-vue/src/index';
|
||||
|
||||
@import '@gitlab/ui/src/scss/utilities';
|
||||
@import '@gitlab/ui/src/scss/bootstrap_vue';
|
||||
|
||||
// We should only import styles that we actually use.
|
||||
@import '@gitlab/ui/src/components/base/alert/alert';
|
||||
|
|
|
|||
|
|
@ -8,6 +8,10 @@ module Issuable
|
|||
end
|
||||
|
||||
def execute(issuable)
|
||||
# load sync object before destroy otherwise we cannot access it for
|
||||
# deletion of label links in delete_label_links
|
||||
@synced_object_to_delete = issuable.try(:sync_object)
|
||||
|
||||
before_destroy(issuable)
|
||||
after_destroy(issuable) if issuable.destroy
|
||||
end
|
||||
|
|
@ -29,14 +33,32 @@ module Issuable
|
|||
end
|
||||
|
||||
def delete_todos(issuable)
|
||||
synced_object_to_delete = @synced_object_to_delete
|
||||
|
||||
issuable.run_after_commit_or_now do
|
||||
TodosDestroyer::DestroyedIssuableWorker.perform_async(issuable.id, issuable.class.name)
|
||||
TodosDestroyer::DestroyedIssuableWorker.perform_async(issuable.id, issuable.class.base_class.name)
|
||||
|
||||
# if there is a sync object, we need to cleanup its todos as well
|
||||
next unless synced_object_to_delete
|
||||
|
||||
TodosDestroyer::DestroyedIssuableWorker.perform_async(
|
||||
synced_object_to_delete.id, synced_object_to_delete.class.base_class.name
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
def delete_label_links(issuable)
|
||||
synced_object_to_delete = @synced_object_to_delete
|
||||
|
||||
issuable.run_after_commit_or_now do
|
||||
Issuable::LabelLinksDestroyWorker.perform_async(issuable.id, issuable.class.name)
|
||||
Issuable::LabelLinksDestroyWorker.perform_async(issuable.id, issuable.class.base_class.name)
|
||||
|
||||
# if there is a sync object, we need to cleanup its label links as well
|
||||
next unless synced_object_to_delete
|
||||
|
||||
Issuable::LabelLinksDestroyWorker.perform_async(
|
||||
synced_object_to_delete.id, synced_object_to_delete.class.base_class.name
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -3,3 +3,4 @@
|
|||
= webpack_bundle_tag 'jira_connect_app'
|
||||
|
||||
- add_page_specific_style 'page_bundles/jira_connect', defer: false
|
||||
- add_page_specific_style 'tailwind'
|
||||
|
|
|
|||
|
|
@ -0,0 +1,25 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class RemoveProjectStatisticsRepositorySizeAndProjectIdIndex < Gitlab::Database::Migration[2.2]
|
||||
milestone '17.1'
|
||||
|
||||
INDEX_NAME = 'index_project_statistics_on_repository_size_and_project_id'
|
||||
COLUMNS = %i[repository_size project_id]
|
||||
|
||||
# TODO: Index to be destroyed synchronously in https://gitlab.com/gitlab-org/gitlab/-/issues/466691
|
||||
def up
|
||||
return unless should_run?
|
||||
|
||||
prepare_async_index_removal :project_statistics, COLUMNS, name: INDEX_NAME
|
||||
end
|
||||
|
||||
def down
|
||||
return unless should_run?
|
||||
|
||||
unprepare_async_index :project_statistics, COLUMNS, name: INDEX_NAME
|
||||
end
|
||||
|
||||
def should_run?
|
||||
Gitlab.com_except_jh?
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1 @@
|
|||
572b8d57ea60ff7cf45598081d29d82a7134221d7e27a1be1c562fc7f081536e
|
||||
|
|
@ -114,6 +114,47 @@ curl --request POST \
|
|||
}'
|
||||
```
|
||||
|
||||
### Update a package protection rule
|
||||
|
||||
Update a package protection rule for a project.
|
||||
|
||||
```plaintext
|
||||
PATCH /api/v4/projects/:id/packages/protection/rules/:package_protection_rule_id
|
||||
```
|
||||
|
||||
Supported attributes:
|
||||
|
||||
| Attribute | Type | Required | Description |
|
||||
|---------------------------------------|-----------------|----------|--------------------------------|
|
||||
| `id` | integer/string | Yes | ID or [URL-encoded path of the project](rest/index.md#namespaced-path-encoding) owned by the authenticated user. |
|
||||
| `package_protection_rule_id` | integer | Yes | ID of the package protection rule to be updated. |
|
||||
| `package_name_pattern` | string | No | Package name protected by the protection rule. For example `@my-scope/my-package-*`. Wildcard character `*` allowed. |
|
||||
| `package_type` | string | No | Package type protected by the protection rule. For example `npm`. |
|
||||
| `minimum_access_level_for_push` | string | No | Minimum GitLab access level able to push a package. For example `developer`, `maintainer`, `owner`. |
|
||||
|
||||
If successful, returns [`200`](rest/index.md#status-codes) and the updated package protection rule.
|
||||
|
||||
Can return the following status codes:
|
||||
|
||||
- `200 OK`: The package protection rule was patched successfully.
|
||||
- `400 Bad Request`: The patch is invalid.
|
||||
- `401 Unauthorized`: The access token is invalid.
|
||||
- `403 Forbidden`: The user does not have permission to patch a package protection rule.
|
||||
- `404 Not Found`: The project was not found.
|
||||
- `422 Unprocessable Entity`: The package protection rule could not be patched, for example, because the `package_name_pattern` is already taken.
|
||||
|
||||
Example request:
|
||||
|
||||
```shell
|
||||
curl --request PATCH \
|
||||
--header "PRIVATE-TOKEN: <your_access_token>" \
|
||||
--header "Content-Type: application/json" \
|
||||
--url "https://gitlab.example.com/api/v4/projects/7/packages/protection/rules/32" \
|
||||
--data '{
|
||||
"package_name_pattern": "new-package-name-pattern-*"
|
||||
}'
|
||||
```
|
||||
|
||||
## Delete a package protection rule
|
||||
|
||||
Deletes a package protection rule from a project.
|
||||
|
|
|
|||
|
|
@ -18,70 +18,111 @@ module API
|
|||
requires :id, types: [String, Integer], desc: 'The ID or URL-encoded path of the project'
|
||||
end
|
||||
resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
|
||||
desc 'Get list of package protection rules for a project' do
|
||||
success Entities::Projects::Packages::Protection::Rule
|
||||
failure [
|
||||
{ code: 401, message: 'Unauthorized' },
|
||||
{ code: 403, message: 'Forbidden' },
|
||||
{ code: 404, message: 'Not Found' }
|
||||
]
|
||||
tags %w[projects]
|
||||
is_array true
|
||||
end
|
||||
get ':id/packages/protection/rules' do
|
||||
present user_project.package_protection_rules, with: Entities::Projects::Packages::Protection::Rule
|
||||
end
|
||||
resource ':id/packages/protection/rules' do
|
||||
desc 'Get list of package protection rules for a project' do
|
||||
success Entities::Projects::Packages::Protection::Rule
|
||||
failure [
|
||||
{ code: 401, message: 'Unauthorized' },
|
||||
{ code: 403, message: 'Forbidden' },
|
||||
{ code: 404, message: 'Not Found' }
|
||||
]
|
||||
tags %w[projects]
|
||||
is_array true
|
||||
hidden true
|
||||
end
|
||||
get do
|
||||
present user_project.package_protection_rules, with: Entities::Projects::Packages::Protection::Rule
|
||||
end
|
||||
|
||||
desc 'Create a package protection rule for a project' do
|
||||
success Entities::Projects::Packages::Protection::Rule
|
||||
failure [
|
||||
{ code: 400, message: 'Bad Request' },
|
||||
{ code: 401, message: 'Unauthorized' },
|
||||
{ code: 403, message: 'Forbidden' },
|
||||
{ code: 404, message: 'Not Found' },
|
||||
{ code: 422, message: 'Unprocessable Entity' }
|
||||
]
|
||||
tags %w[projects]
|
||||
end
|
||||
params do
|
||||
requires :package_name_pattern, type: String,
|
||||
desc: 'Package name protected by the rule. For example @my-scope/my-package-*. Wildcard character * allowed.'
|
||||
requires :package_type, type: String, values: Packages::Protection::Rule.package_types.keys,
|
||||
desc: 'Package type protected by the rule. For example npm.'
|
||||
requires :minimum_access_level_for_push, type: String,
|
||||
values: Packages::Protection::Rule.minimum_access_level_for_pushes.keys,
|
||||
desc: 'Minimum GitLab access level able to push a package. For example developer, maintainer, owner.'
|
||||
end
|
||||
post ':id/packages/protection/rules' do
|
||||
response = ::Packages::Protection::CreateRuleService.new(project: user_project, current_user: current_user,
|
||||
params: declared_params(params)).execute
|
||||
desc 'Create a package protection rule for a project' do
|
||||
success Entities::Projects::Packages::Protection::Rule
|
||||
failure [
|
||||
{ code: 400, message: 'Bad Request' },
|
||||
{ code: 401, message: 'Unauthorized' },
|
||||
{ code: 403, message: 'Forbidden' },
|
||||
{ code: 404, message: 'Not Found' },
|
||||
{ code: 422, message: 'Unprocessable Entity' }
|
||||
]
|
||||
tags %w[projects]
|
||||
hidden true
|
||||
end
|
||||
params do
|
||||
requires :package_name_pattern, type: String,
|
||||
desc: 'Package name protected by the rule. For example @my-scope/my-package-*.
|
||||
Wildcard character * allowed.'
|
||||
requires :package_type, type: String, values: Packages::Protection::Rule.package_types.keys,
|
||||
desc: 'Package type protected by the rule. For example npm.'
|
||||
requires :minimum_access_level_for_push, type: String,
|
||||
values: Packages::Protection::Rule.minimum_access_level_for_pushes.keys,
|
||||
desc: 'Minimum GitLab access level able to push a package. For example developer, maintainer, owner.'
|
||||
end
|
||||
post do
|
||||
response = ::Packages::Protection::CreateRuleService.new(project: user_project, current_user: current_user,
|
||||
params: declared_params).execute
|
||||
|
||||
render_api_error!({ error: response.message }, :unprocessable_entity) if response.error?
|
||||
render_api_error!({ error: response.message }, :unprocessable_entity) if response.error?
|
||||
|
||||
present response[:package_protection_rule], with: Entities::Projects::Packages::Protection::Rule
|
||||
end
|
||||
present response[:package_protection_rule], with: Entities::Projects::Packages::Protection::Rule
|
||||
end
|
||||
|
||||
desc 'Delete package protection rule' do
|
||||
success code: 204, message: '204 No Content'
|
||||
failure [
|
||||
{ code: 400, message: 'Bad Request' },
|
||||
{ code: 401, message: 'Unauthorized' },
|
||||
{ code: 403, message: 'Forbidden' },
|
||||
{ code: 404, message: 'Not Found' }
|
||||
]
|
||||
tags %w[projects]
|
||||
end
|
||||
params do
|
||||
requires :package_protection_rule_id, type: Integer, desc: 'The ID of the package protection rule'
|
||||
end
|
||||
delete ':id/packages/protection/rules/:package_protection_rule_id' do
|
||||
package_protection_rule = user_project.package_protection_rules.find(params[:package_protection_rule_id])
|
||||
params do
|
||||
requires :package_protection_rule_id, type: Integer, desc: 'The ID of the package protection rule'
|
||||
end
|
||||
resource ':package_protection_rule_id' do
|
||||
desc 'Update a package protection rule for a project' do
|
||||
success Entities::Projects::Packages::Protection::Rule
|
||||
failure [
|
||||
{ code: 400, message: 'Bad Request' },
|
||||
{ code: 401, message: 'Unauthorized' },
|
||||
{ code: 403, message: 'Forbidden' },
|
||||
{ code: 404, message: 'Not Found' },
|
||||
{ code: 422, message: 'Unprocessable Entity' }
|
||||
]
|
||||
tags %w[projects]
|
||||
hidden true
|
||||
end
|
||||
params do
|
||||
optional :package_name_pattern, type: String,
|
||||
desc: 'Package name protected by the rule. For example @my-scope/my-package-*.
|
||||
Wildcard character * allowed.'
|
||||
optional :package_type, type: String, values: Packages::Protection::Rule.package_types.keys,
|
||||
desc: 'Package type protected by the rule. For example npm.'
|
||||
optional :minimum_access_level_for_push, type: String,
|
||||
values: Packages::Protection::Rule.minimum_access_level_for_pushes.keys,
|
||||
desc: 'Minimum GitLab access level able to push a package. For example developer, maintainer, owner.'
|
||||
end
|
||||
patch do
|
||||
package_protection_rule = user_project.package_protection_rules.find(params[:package_protection_rule_id])
|
||||
|
||||
destroy_conditionally!(package_protection_rule) do |package_protection_rule|
|
||||
response = ::Packages::Protection::DeleteRuleService.new(package_protection_rule,
|
||||
current_user: current_user).execute
|
||||
response = ::Packages::Protection::UpdateRuleService.new(package_protection_rule,
|
||||
current_user: current_user, params: declared_params(include_missing: false)).execute
|
||||
|
||||
render_api_error!({ error: response.message }, :bad_request) if response.error?
|
||||
render_api_error!({ error: response.message }, :unprocessable_entity) if response.error?
|
||||
|
||||
present response[:package_protection_rule], with: Entities::Projects::Packages::Protection::Rule
|
||||
end
|
||||
|
||||
desc 'Delete package protection rule' do
|
||||
success code: 204, message: '204 No Content'
|
||||
failure [
|
||||
{ code: 400, message: 'Bad Request' },
|
||||
{ code: 401, message: 'Unauthorized' },
|
||||
{ code: 403, message: 'Forbidden' },
|
||||
{ code: 404, message: 'Not Found' }
|
||||
]
|
||||
tags %w[projects]
|
||||
hidden true
|
||||
end
|
||||
delete do
|
||||
package_protection_rule = user_project.package_protection_rules.find(params[:package_protection_rule_id])
|
||||
|
||||
destroy_conditionally!(package_protection_rule) do |package_protection_rule|
|
||||
response = ::Packages::Protection::DeleteRuleService.new(package_protection_rule,
|
||||
current_user: current_user).execute
|
||||
|
||||
render_api_error!({ error: response.message }, :bad_request) if response.error?
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ gem 'capybara', '~> 3.40.0'
|
|||
gem 'capybara-screenshot', '~> 1.0.26'
|
||||
gem 'rake', '~> 13', '>= 13.2.1'
|
||||
gem 'rspec', '~> 3.13'
|
||||
gem 'selenium-webdriver', '= 4.21.1'
|
||||
gem 'selenium-webdriver', '= 4.22.0'
|
||||
gem 'airborne', '~> 0.3.7', require: false # airborne is messing with rspec sandboxed mode so not requiring by default
|
||||
gem 'rest-client', '~> 2.1.0'
|
||||
gem 'rspec_junit_formatter', '~> 0.6.0'
|
||||
|
|
|
|||
|
|
@ -210,6 +210,7 @@ GEM
|
|||
llhttp-ffi (0.4.0)
|
||||
ffi-compiler (~> 1.0)
|
||||
rake (~> 13.0)
|
||||
logger (1.6.0)
|
||||
loofah (2.21.3)
|
||||
crass (~> 1.0.2)
|
||||
nokogiri (>= 1.12.0)
|
||||
|
|
@ -318,8 +319,9 @@ GEM
|
|||
sawyer (0.9.2)
|
||||
addressable (>= 2.3.5)
|
||||
faraday (>= 0.17.3, < 3)
|
||||
selenium-webdriver (4.21.1)
|
||||
selenium-webdriver (4.22.0)
|
||||
base64 (~> 0.2)
|
||||
logger (~> 1.4)
|
||||
rexml (~> 3.2, >= 3.2.5)
|
||||
rubyzip (>= 1.2.2, < 3.0)
|
||||
websocket (~> 1.0)
|
||||
|
|
@ -409,11 +411,11 @@ DEPENDENCIES
|
|||
rspec-parameterized (~> 1.0.2)
|
||||
rspec_junit_formatter (~> 0.6.0)
|
||||
ruby-debug-ide (~> 0.7.3)
|
||||
selenium-webdriver (= 4.21.1)
|
||||
selenium-webdriver (= 4.22.0)
|
||||
slack-notifier (~> 2.4)
|
||||
terminal-table (~> 3.0.2)
|
||||
warning (~> 1.4)
|
||||
zeitwerk (~> 2.6, >= 2.6.15)
|
||||
|
||||
BUNDLED WITH
|
||||
2.5.11
|
||||
2.5.13
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ module QA
|
|||
end
|
||||
|
||||
it(
|
||||
'user registers a new group runner',
|
||||
'user registers a new group runner', :blocking,
|
||||
testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/388740'
|
||||
) do
|
||||
Flow::Login.sign_in
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ module QA
|
|||
runner.remove_via_api!
|
||||
end
|
||||
|
||||
it 'user registers a new project runner', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/348025' do
|
||||
it 'user registers a new project runner', :blocking, testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/348025' do
|
||||
Flow::Login.sign_in
|
||||
|
||||
runner.project.visit!
|
||||
|
|
|
|||
|
|
@ -0,0 +1,42 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
require_migration!
|
||||
|
||||
RSpec.describe RemoveProjectStatisticsRepositorySizeAndProjectIdIndex, feature_category: :consumables_cost_management do
|
||||
let(:migration) { described_class.new }
|
||||
let(:postgres_async_indexes) { table(:postgres_async_indexes) }
|
||||
|
||||
describe '#up' do
|
||||
subject(:up) { migration.up }
|
||||
|
||||
it 'does nothing when not on gitlab.com' do
|
||||
expect { up }.not_to change { postgres_async_indexes.count }
|
||||
end
|
||||
|
||||
it 'prepares async index removal when on gitlab.com', :saas do
|
||||
expect { up }.to change { postgres_async_indexes.count }.from(0).to(1)
|
||||
end
|
||||
end
|
||||
|
||||
describe '#down' do
|
||||
subject(:down) { migration.down }
|
||||
|
||||
before do
|
||||
postgres_async_indexes.create!(
|
||||
name: 'index_project_statistics_on_repository_size_and_project_id',
|
||||
table_name: 'project_statistics',
|
||||
definition: 'test index'
|
||||
)
|
||||
end
|
||||
|
||||
it 'does nothing when not on gitlab.com' do
|
||||
expect { down }.not_to change { postgres_async_indexes.count }
|
||||
end
|
||||
|
||||
it 'unprepares async index removal when on gitlab.com', :saas do
|
||||
expect { down }.to change { postgres_async_indexes.count }.from(1).to(0)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -15,6 +15,12 @@ RSpec.describe API::ProjectPackagesProtectionRules, :aggregate_failures, feature
|
|||
let_it_be(:invalid_token) { 'invalid-token123' }
|
||||
let_it_be(:headers_with_invalid_token) { { Gitlab::Auth::AuthFinders::PRIVATE_TOKEN_HEADER => invalid_token } }
|
||||
|
||||
let(:params) do
|
||||
{ package_name_pattern: '@my-new-scope/my-package-*',
|
||||
package_type: package_protection_rule.package_type,
|
||||
minimum_access_level_for_push: package_protection_rule.minimum_access_level_for_push }
|
||||
end
|
||||
|
||||
shared_examples 'rejecting project packages protection rules request when not enough permissions' do
|
||||
using RSpec::Parameterized::TableSyntax
|
||||
|
||||
|
|
@ -34,6 +40,48 @@ RSpec.describe API::ProjectPackagesProtectionRules, :aggregate_failures, feature
|
|||
end
|
||||
end
|
||||
|
||||
shared_examples 'rejecting project packages protection rules request when enough permissions' do
|
||||
context 'when feature flag is disabled' do
|
||||
before do
|
||||
stub_feature_flags(packages_protected_packages: false)
|
||||
end
|
||||
|
||||
it_behaves_like 'returning response status', :not_found
|
||||
end
|
||||
|
||||
context 'when the project id is invalid' do
|
||||
let(:url) { "/projects/invalid/packages/protection/rules" }
|
||||
|
||||
it_behaves_like 'returning response status', :not_found
|
||||
end
|
||||
|
||||
context 'when the project id does not exist' do
|
||||
let(:url) { "/projects/#{non_existing_record_id}/packages/protection/rules" }
|
||||
|
||||
it_behaves_like 'returning response status', :not_found
|
||||
end
|
||||
end
|
||||
|
||||
shared_examples 'rejecting project packages protection rules request when handling rule ids' do
|
||||
context 'when the rule id is invalid' do
|
||||
let(:url) { "/projects/#{project.id}/packages/protection/rules/invalid" }
|
||||
|
||||
it_behaves_like 'returning response status', :bad_request
|
||||
end
|
||||
|
||||
context 'when the rule id does not exist' do
|
||||
let(:url) { "/projects/#{project.id}/packages/protection/rules/#{non_existing_record_id}" }
|
||||
|
||||
it_behaves_like 'returning response status', :not_found
|
||||
end
|
||||
|
||||
context 'when the package protection rule does belong to another project' do
|
||||
let(:url) { "/projects/#{other_project.id}/packages/protection/rules/#{package_protection_rule.id}" }
|
||||
|
||||
it_behaves_like 'returning response status', :not_found
|
||||
end
|
||||
end
|
||||
|
||||
describe 'GET /projects/:id/packages/protection/rules' do
|
||||
let(:url) { "/projects/#{project.id}/packages/protection/rules" }
|
||||
|
||||
|
|
@ -55,25 +103,7 @@ RSpec.describe API::ProjectPackagesProtectionRules, :aggregate_failures, feature
|
|||
expect(json_response.count).to eq(2)
|
||||
end
|
||||
|
||||
context 'when the project id is invalid' do
|
||||
let(:url) { "/projects/invalid/packages/protection/rules" }
|
||||
|
||||
it_behaves_like 'returning response status', :not_found
|
||||
end
|
||||
|
||||
context 'when the project id does not exist' do
|
||||
let(:url) { "/projects/#{non_existing_record_id}/packages/protection/rules" }
|
||||
|
||||
it_behaves_like 'returning response status', :not_found
|
||||
end
|
||||
|
||||
context 'when packages_protected_packages is disabled' do
|
||||
before do
|
||||
stub_feature_flags(packages_protected_packages: false)
|
||||
end
|
||||
|
||||
it_behaves_like 'returning response status', :not_found
|
||||
end
|
||||
it_behaves_like 'rejecting project packages protection rules request when enough permissions'
|
||||
end
|
||||
|
||||
context 'with invalid token' do
|
||||
|
|
@ -85,11 +115,6 @@ RSpec.describe API::ProjectPackagesProtectionRules, :aggregate_failures, feature
|
|||
|
||||
describe 'POST /projects/:id/packages/protection/rules' do
|
||||
let(:url) { "/projects/#{project.id}/packages/protection/rules" }
|
||||
let(:params) do
|
||||
{ package_name_pattern: '@my-new-scope/my-package-*',
|
||||
package_type: package_protection_rule.package_type,
|
||||
minimum_access_level_for_push: package_protection_rule.minimum_access_level_for_push }
|
||||
end
|
||||
|
||||
subject(:post_package_rule) { post(api(url, api_user), params: params) }
|
||||
|
||||
|
|
@ -136,25 +161,86 @@ RSpec.describe API::ProjectPackagesProtectionRules, :aggregate_failures, feature
|
|||
end
|
||||
end
|
||||
|
||||
context 'when the project id is invalid' do
|
||||
let(:url) { "/projects/invalid/packages/protection/rules" }
|
||||
it_behaves_like 'rejecting project packages protection rules request when enough permissions'
|
||||
end
|
||||
|
||||
it_behaves_like 'returning response status', :not_found
|
||||
end
|
||||
context 'with invalid token' do
|
||||
subject(:post_package_rules) { post(api(url), headers: headers_with_invalid_token, params: params) }
|
||||
|
||||
context 'when the project id does not exist' do
|
||||
let(:url) { "/projects/#{non_existing_record_id}/packages/protection/rules" }
|
||||
it_behaves_like 'returning response status', :unauthorized
|
||||
end
|
||||
end
|
||||
|
||||
it_behaves_like 'returning response status', :not_found
|
||||
end
|
||||
describe 'PATCH /projects/:id/packages/protection/rules/:package_protection_rule_id' do
|
||||
let(:url) { "/projects/#{project.id}/packages/protection/rules/#{package_protection_rule.id}" }
|
||||
|
||||
context 'when packages_protected_packages is disabled' do
|
||||
subject(:patch_package_rule) { patch(api(url, api_user), params: params) }
|
||||
|
||||
it_behaves_like 'rejecting project packages protection rules request when not enough permissions'
|
||||
|
||||
context 'for maintainer' do
|
||||
let(:api_user) { maintainer }
|
||||
let_it_be(:changed_scope) { '@my-changed-scope/my-package-*' }
|
||||
|
||||
context 'with full changeset' do
|
||||
before do
|
||||
stub_feature_flags(packages_protected_packages: false)
|
||||
params[:package_name_pattern] = changed_scope
|
||||
end
|
||||
|
||||
it_behaves_like 'returning response status', :not_found
|
||||
it 'updates a package protection rule' do
|
||||
patch_package_rule
|
||||
|
||||
expect(response).to have_gitlab_http_status(:ok)
|
||||
expect(json_response["package_name_pattern"]).to eq(changed_scope)
|
||||
expect(json_response["package_type"]).to eq(package_protection_rule.package_type)
|
||||
end
|
||||
end
|
||||
|
||||
context 'with a single change' do
|
||||
let(:params) { { package_name_pattern: changed_scope } }
|
||||
|
||||
it 'updates a package protection rule' do
|
||||
patch_package_rule
|
||||
|
||||
expect(response).to have_gitlab_http_status(:ok)
|
||||
expect(json_response["package_name_pattern"]).to eq(changed_scope)
|
||||
end
|
||||
end
|
||||
|
||||
context 'with invalid package_type' do
|
||||
before do
|
||||
params[:package_type] = "not in enum"
|
||||
end
|
||||
|
||||
it_behaves_like 'returning response status', :bad_request
|
||||
end
|
||||
|
||||
context 'with invalid minimum_access_level_for_push' do
|
||||
before do
|
||||
params[:minimum_access_level_for_push] = "not in enum"
|
||||
end
|
||||
|
||||
it_behaves_like 'returning response status', :bad_request
|
||||
end
|
||||
|
||||
context 'with already existing package_name_pattern' do
|
||||
before do
|
||||
other_package_protection_rule = create(:package_protection_rule, project: project,
|
||||
package_name_pattern: "@my-scope/my-package-*")
|
||||
params[:package_name_pattern] = other_package_protection_rule.package_name_pattern
|
||||
end
|
||||
|
||||
it_behaves_like 'returning response status', :unprocessable_entity
|
||||
end
|
||||
|
||||
it_behaves_like 'rejecting project packages protection rules request when handling rule ids'
|
||||
it_behaves_like 'rejecting project packages protection rules request when enough permissions'
|
||||
end
|
||||
|
||||
context 'with invalid token' do
|
||||
subject(:patch_package_rules) { patch(api(url), headers: headers_with_invalid_token, params: params) }
|
||||
|
||||
it_behaves_like 'returning response status', :unauthorized
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -175,44 +261,9 @@ RSpec.describe API::ProjectPackagesProtectionRules, :aggregate_failures, feature
|
|||
end.to raise_error(ActiveRecord::RecordNotFound)
|
||||
expect(response).to have_gitlab_http_status(:no_content)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the package protection rule does belong to another project' do
|
||||
let(:url) { "/projects/#{other_project.id}/packages/protection/rules/#{package_protection_rule.id}" }
|
||||
|
||||
it_behaves_like 'returning response status', :not_found
|
||||
end
|
||||
|
||||
context 'when the project id is invalid' do
|
||||
let(:url) { "/projects/invalid/packages/protection/rules/#{package_protection_rule.id}" }
|
||||
|
||||
it_behaves_like 'returning response status', :not_found
|
||||
end
|
||||
|
||||
context 'when the project id does not exist' do
|
||||
let(:url) { "/projects/#{non_existing_record_id}/packages/protection/rules/#{package_protection_rule.id}" }
|
||||
|
||||
it_behaves_like 'returning response status', :not_found
|
||||
end
|
||||
|
||||
context 'when the rule id is invalid' do
|
||||
let(:url) { "/projects/#{project.id}/packages/protection/rules/invalid" }
|
||||
|
||||
it_behaves_like 'returning response status', :bad_request
|
||||
end
|
||||
|
||||
context 'when the rule id does not exist' do
|
||||
let(:url) { "/projects/#{project.id}/packages/protection/rules/#{non_existing_record_id}" }
|
||||
|
||||
it_behaves_like 'returning response status', :not_found
|
||||
end
|
||||
|
||||
context 'when packages_protected_packages is disabled' do
|
||||
before do
|
||||
stub_feature_flags(packages_protected_packages: false)
|
||||
end
|
||||
|
||||
it_behaves_like 'returning response status', :not_found
|
||||
it_behaves_like 'rejecting project packages protection rules request when handling rule ids'
|
||||
it_behaves_like 'rejecting project packages protection rules request when enough permissions'
|
||||
end
|
||||
|
||||
context 'with invalid token' do
|
||||
|
|
|
|||
|
|
@ -1,18 +1,22 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
RSpec.shared_examples_for 'service scheduling async deletes' do
|
||||
it 'destroys associated todos asynchronously' do
|
||||
expect(worker_class)
|
||||
.to receive(:perform_async)
|
||||
.with(issuable.id, issuable.class.name)
|
||||
it 'destroys associated todos asynchronously', :sidekiq_inline do
|
||||
expect(worker_class).to receive(:perform_async).with(issuable.id, issuable.class.base_class.name)
|
||||
|
||||
if try(:sync_object).present?
|
||||
expect(worker_class).to receive(:perform_async).with(sync_object.id, sync_object.class.base_class.name)
|
||||
end
|
||||
|
||||
subject.execute(issuable)
|
||||
end
|
||||
|
||||
it 'works inside a transaction' do
|
||||
expect(worker_class)
|
||||
.to receive(:perform_async)
|
||||
.with(issuable.id, issuable.class.name)
|
||||
it 'works inside a transaction', :sidekiq_inline do
|
||||
expect(worker_class).to receive(:perform_async).with(issuable.id, issuable.class.base_class.name)
|
||||
|
||||
if try(:sync_object).present?
|
||||
expect(worker_class).to receive(:perform_async).with(sync_object.id, sync_object.class.base_class.name)
|
||||
end
|
||||
|
||||
ApplicationRecord.transaction do
|
||||
subject.execute(issuable)
|
||||
|
|
|
|||
Loading…
Reference in New Issue