Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2025-02-05 09:11:43 +00:00
parent 32b8c029dc
commit f84cdc5587
38 changed files with 137 additions and 387 deletions

View File

@ -1 +1 @@
35cfdacad6baf3e031993625b9ce4e5d46dfd388
7186455e61c1a6556cd6f0664a9c90c5da2e6bae

View File

@ -21,11 +21,6 @@ export default {
required: false,
default: false,
},
duplicatesAllowed: {
type: Boolean,
default: false,
required: false,
},
duplicateExceptionRegex: {
type: String,
default: '',
@ -68,7 +63,7 @@ export default {
>
<gl-form-input
:id="id"
:disabled="duplicatesAllowed || loading"
:disabled="loading"
width="lg"
:value="duplicateExceptionRegex"
:state="isExceptionRegexValid"

View File

@ -1,6 +1,5 @@
<script>
import { GlTableLite, GlToggle } from '@gitlab/ui';
import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import {
GENERIC_PACKAGE_FORMAT,
MAVEN_PACKAGE_FORMAT,
@ -49,7 +48,6 @@ export default {
GlToggle,
ExceptionsInput,
},
mixins: [glFeatureFlagMixin()],
inject: ['groupPath'],
props: {
packageSettings: {
@ -160,13 +158,6 @@ export default {
this.$emit('error');
}
},
allowDuplicateExceptions(item) {
if (item.format === NUGET_PACKAGE_FORMAT) return item.duplicatesAllowed;
// We're also enabling the duplicate exceptions input when duplicates are allowed
// But the change is behind the packagesAllowDuplicateExceptions feature flag
return !this.glFeatures.packagesAllowDuplicateExceptions && item.duplicatesAllowed;
},
update(type, value) {
this.updateSettings({ [type]: value });
},
@ -204,7 +195,6 @@ export default {
<template #cell(exceptions)="{ item }">
<exceptions-input
:id="item.id"
:duplicates-allowed="allowDuplicateExceptions(item)"
:duplicate-exception-regex="item.duplicateExceptionRegex"
:duplicate-exception-regex-error="item.duplicateExceptionRegexError"
:name="item.modelNames.exception"

View File

@ -9,7 +9,6 @@ module Groups
before_action do
push_frontend_feature_flag(:maven_central_request_forwarding, group)
push_frontend_feature_flag(:packages_allow_duplicate_exceptions, group)
end
feature_category :package_registry

View File

@ -366,9 +366,9 @@ module Ci
begin
transaction do
if self.runner_projects.empty?
self.sharding_key_id = project.id
if ::Project.id_in(sharding_key_id).empty?
self.clear_memoization(:owner)
self.sharding_key_id = fallback_owner_project&.id || project.id
end
self.runner_projects << ::Ci::RunnerProject.new(project: project, runner: self)
@ -407,14 +407,9 @@ module Ci
when 'group_type'
::Group.find_by_id(sharding_key_id)
when 'project_type'
# NOTE: when a project is deleted, the respective ci_runner_projects records are not immediately
# deleted by the LFK, so we might find join records that point to a non-existing project
project = ::Project.find_by_id(sharding_key_id)
return project if project
owner_project = ::Project.find_by_id(sharding_key_id)
project_ids = runner_projects.order(:id).pluck(:project_id)
projects_added_to_runner_asc = Arel.sql("array_position(ARRAY[#{project_ids.join(',')}]::bigint[], id)")
Project.order(projects_added_to_runner_asc).find_by_id(project_ids)
owner_project || fallback_owner_project
end
end
strong_memoize_attr :owner
@ -570,6 +565,14 @@ module Ci
joins(:runner_managers).merge(RunnerManager.with_upgrade_status(upgrade_status))
end
def fallback_owner_project
# NOTE: when a project is deleted, the respective ci_runner_projects records are not immediately
# deleted by the LFK, so we might find join records that point to a still-existing project
project_ids = runner_projects.order(:id).pluck(:project_id)
projects_added_to_runner_asc = Arel.sql("array_position(ARRAY[#{project_ids.join(',')}]::bigint[], id)")
Project.order(projects_added_to_runner_asc).find_by_id(project_ids)
end
def compute_token_expiration_instance
return unless expiration_interval = Gitlab::CurrentSettings.runner_token_expiration_interval

View File

@ -44,13 +44,9 @@ class Namespace::PackageSetting < ApplicationRecord
"\\A#{package.package_settings["#{package.package_type}_duplicate_exception_regex"]}\\z"
)
if Feature.enabled?(:packages_allow_duplicate_exceptions, package.project.group)
regex_match = regex.match?(package.name) || regex.match?(package.version)
regex_match = regex.match?(package.name) || regex.match?(package.version)
duplicates_allowed ? !regex_match : regex_match
else
duplicates_allowed || regex.match?(package.name) || regex.match?(package.version)
end
duplicates_allowed ? !regex_match : regex_match
end
end
end

View File

@ -667,6 +667,13 @@ class ProjectPolicy < BasePolicy
enable :admin_protected_branch
end
rule { can?(:manage_protected_tags) }.policy do
enable :read_protected_tags
enable :create_protected_tags
enable :update_protected_tags
enable :destroy_protected_tags
end
rule { can?(:admin_build) }.enable :manage_trigger
rule { can?(:admin_runner) }.enable :read_runner

View File

@ -42,18 +42,12 @@ module Packages
end
def duplicates_not_allowed?
ff_enabled = Feature.enabled?(:packages_allow_duplicate_exceptions, project.group)
package_settings_with_duplicates_allowed.none? do |setting|
exception_regex_matches = ::Gitlab::UntrustedRegexp
.new("\\A#{setting.terraform_module_duplicate_exception_regex}\\z")
.match?(name)
if ff_enabled
setting.terraform_module_duplicates_allowed ? !exception_regex_matches : exception_regex_matches
else
setting.terraform_module_duplicates_allowed || exception_regex_matches
end
setting.terraform_module_duplicates_allowed ? !exception_regex_matches : exception_regex_matches
end
end

View File

@ -5,7 +5,7 @@ module ProtectedTags
attr_reader :protected_tag
def execute
raise Gitlab::Access::AccessDeniedError unless can?(current_user, :admin_project, project)
raise Gitlab::Access::AccessDeniedError unless can?(current_user, :create_protected_tags, project)
project.protected_tags.create(params)
end

View File

@ -3,6 +3,8 @@
module ProtectedTags
class DestroyService < BaseService
def execute(protected_tag)
raise Gitlab::Access::AccessDeniedError unless can?(current_user, :destroy_protected_tags, project)
protected_tag.destroy
end
end

View File

@ -1,9 +0,0 @@
---
name: packages_allow_duplicate_exceptions
feature_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/482901
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/165467
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/498085
milestone: '17.7'
group: group::package registry
type: gitlab_com_derisk
default_enabled: false

View File

@ -12,9 +12,9 @@
window: "1"
body: | # (required) Do not modify this line, instead modify the lines below.
The support for registration tokens and certain runner configuration arguments in the `POST` method operation on the `/api/v4/runners` endpoint is deprecated.
This endpoint [registers](https://docs.gitlab.com/ee/api/runners.html#register-a-new-runner) a runner
with a GitLab instance at the instance, group, or project level through the API. In GitLab 17.0, registration tokens, and support for certain configuration arguments,
will start returning the HTTP `410 Gone` status code in GitLab 17.0. For more information, see [Migrating to the new runner registration workflow](https://docs.gitlab.com/ee/ci/runners/new_creation_workflow.html#prevent-your-runner-registration-workflow-from-breaking).
This endpoint [registers](https://docs.gitlab.com/ee/api/runners.html#create-a-runner) a runner
with a GitLab instance at the instance, group, or project level through the API. In GitLab 18.0, registration tokens, and support for certain configuration arguments,
will start returning the HTTP `410 Gone` status code. For more information, see [Migrating to the new runner registration workflow](https://docs.gitlab.com/ee/ci/runners/new_creation_workflow.html#prevent-your-runner-registration-workflow-from-breaking).
The configuration arguments disabled for runner authentication tokens are:
@ -29,4 +29,4 @@
This change is a breaking change. You should [create a runner in the UI](https://docs.gitlab.com/ee/ci/runners/runners_scope.html) to add configurations, and use the runner authentication token in the `gitlab-runner register` command instead.
end_of_support_milestone: # (optional) Use "XX.YY" format. The milestone when support for this feature will end.
tiers: # (optional - may be required in the future) An array of tiers that the feature is available in currently. e.g., [Free, Silver, Gold, Core, Premium, Ultimate]
documentation_url: https://docs.gitlab.com/ee/api/runners.html#register-a-new-runner # (optional) This is a link to the current documentation page
documentation_url: https://docs.gitlab.com/ee/api/runners.html#create-a-runner # (optional) This is a link to the current documentation page

View File

@ -24,8 +24,8 @@
as part of the new [GitLab Runner token architecture](https://docs.gitlab.com/ee/ci/runners/new_creation_workflow.html).
The work is planned in [this epic](https://gitlab.com/groups/gitlab-org/-/epics/7633).
This new architecture introduces a new method for registering runners and will eliminate the legacy
[runner registration token](https://docs.gitlab.com/ee/security/token_overview.html#runner-registration-tokens).
[runner registration token](https://docs.gitlab.com/ee/security/tokens/index.html#runner-registration-tokens-deprecated).
From GitLab 18.0 and later, the runner registration methods implemented by the new GitLab Runner token architecture will be the only supported methods.
end_of_support_milestone: # (optional) Use "XX.YY" format. The milestone when support for this feature will end.
tiers: # (optional - may be required in the future) An array of tiers that the feature is available in currently. e.g., [Free, Silver, Gold, Core, Premium, Ultimate]
documentation_url: https://docs.gitlab.com/ee/api/runners.html#register-a-new-runner # (optional) This is a link to the current documentation page
documentation_url: https://docs.gitlab.com/ee/api/runners.html#create-a-runner # (optional) This is a link to the current documentation page

View File

@ -1,4 +1,4 @@
- title: '`ciUsedMinutes` GraphQL field renamed to `ciDuration`'
- title: '`ciMinutesUsed` GraphQL field renamed to `ciDuration`'
removal_milestone: '18.0'
announcement_milestone: '17.5'
breaking_change: true
@ -11,8 +11,8 @@
manual_task: true
window: "2"
body: |
The `ciDuration` field of the `CiRunnerUsage` and `CiRunnerUsageByProject` types replaces the former `ciUsedMinutes` field.
Update all references to `ciUsedMinutes` from these types to `ciDuration`.
The `ciDuration` field of the `CiRunnerUsage` and `CiRunnerUsageByProject` types replaces the former `ciMinutesUsed` field.
Update all references to `ciMinutesUsed` from these types to `ciDuration`.
tiers: Ultimate
documentation_url: https://docs.gitlab.com/ee/api/graphql/reference/#cirunnerusage

View File

@ -20,7 +20,7 @@
as part of the new [GitLab Runner token architecture](https://docs.gitlab.com/ee/ci/runners/new_creation_workflow.html).
For details, see [epic 7633](https://gitlab.com/groups/gitlab-org/-/epics/7633).
This new architecture introduces a new method for registering runners and eliminates the legacy
[runner registration token](https://docs.gitlab.com/ee/security/token_overview.html#runner-registration-tokens).
[runner registration token](https://docs.gitlab.com/ee/security/tokens/index.html#runner-registration-tokens-deprecated).
In GitLab 18.0, only the runner registration methods implemented in the new GitLab Runner token architecture will be supported.
#
# When support for this feature ends, in XX.YY milestone format.
@ -29,7 +29,7 @@
# like [Free, Silver, Gold, Core, Premium, Ultimate]
tiers:
# Links to documentation and thumbnail image
documentation_url: https://docs.gitlab.com/ee/api/runners.html#register-a-new-runner # (optional) This is a link to the current documentation page
documentation_url: https://docs.gitlab.com/ee/api/runners.html#create-a-runner # (optional) This is a link to the current documentation page
image_url:
# Use the youtube thumbnail URL with the structure of https://img.youtube.com/vi/UNIQUEID/hqdefault.jpg
video_url:

View File

@ -218,4 +218,4 @@ Also plan ahead if you need the following GitLab Dedicated features:
To view all available infrastructure configuration options, see [Configure your GitLab Dedicated instance](../../administration/dedicated/configure_instance.md).
NOTE:
New GitLab Dedicated instances use default settings for a self-managed instance. A GitLab administrator can change these settings from the [Admin Area](../../administration/admin_area.md).
New GitLab Dedicated instances use the same default settings as GitLab Self-Managed. A GitLab administrator can change these settings from the [Admin Area](../../administration/admin_area.md).

View File

@ -350,7 +350,7 @@ tail -f log/elasticsearch.log
For `ActiveRecord` objects, the `ApplicationVersionedSearch` concern can be included on the model to index data based on callbacks. If that's not suitable, call `Elastic::ProcessBookkeepingService.track!()` with an instance of `Search::Elastic::Reference` whenever a document should be indexed.
Always check for `Gitlab::CurrentSettings.elasticsearch_indexing?` and `use_elasticsearch?` because some self-managed instances do not have Elasticsearch enabled and [namespace limiting](../integration/advanced_search/elasticsearch.md#limit-the-amount-of-namespace-and-project-data-to-index) can be enabled.
Always check for `Gitlab::CurrentSettings.elasticsearch_indexing?` and `use_elasticsearch?` because some GitLab Self-Managed instances do not have Elasticsearch enabled and [namespace limiting](../integration/advanced_search/elasticsearch.md#limit-the-amount-of-namespace-and-project-data-to-index) can be enabled.
Also check that the index is able to handle the index request. For example, check that the index exists if it was added in the current major release by verifying that the migration to add the index was completed: `Elastic::DataMigrationService.migration_has_finished?`.

View File

@ -316,7 +316,7 @@ For more information, see [the guideline of the regression evaluator](https://gi
## GitLab Duo Chat Self-managed End-to-End Tests
In MRs, the end-to-end tests exercise the Duo Chat functionality of self-managed instances by using an instance of the GitLab Linux package
In MRs, the end-to-end tests exercise the Duo Chat functionality of GitLab Self-Managed instances by using an instance of the GitLab Linux package
integrated with the `latest` version of AI gateway. The instance of AI gateway is configured to return [mock responses](https://gitlab.com/gitlab-org/modelops/applied-ml/code-suggestions/ai-assist#mocking-ai-model-responses).
To view the results of these tests, open the `e2e:test-on-omnibus-ee` child pipeline and view the `ai-gateway` job.

View File

@ -236,7 +236,7 @@ Include in the MR description:
access and size. Include in the MR description answers to these questions:
- What is the anticipated growth for the new table over the next 3 months, 6 months, 1 year? What assumptions are these based on?
- How many reads and writes per hour would you expect this table to have in 3 months, 6 months, 1 year? Under what circumstances are rows updated? What assumptions are these based on?
- Based on the anticipated data volume and access patterns, does the new table pose an availability risk to GitLab.com or self-managed instances? Does the proposed design scale to support the needs of GitLab.com and self-managed customers?
- Based on the anticipated data volume and access patterns, does the new table pose an availability risk to GitLab.com or GitLab Self-Managed instances? Does the proposed design scale to support the needs of GitLab.com and GitLab Self-Managed customers?
#### Preparation when removing columns, tables, indexes, or other structures

View File

@ -423,6 +423,24 @@ about toggling feature flags.
See [cleaning up feature flags](controls.md#cleaning-up) for more information about
deleting feature flags.
## Migrate an `ops` feature flag to an application setting
To migrate an `ops` feature flag to an application setting:
1. In application settings, create or identify an existing `JSONB` column to store the setting.
1. Write a migration to backfill the column.
For an example, see [merge request 148014](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/148014).
1. Optional. In application settings, update the documentation for the setting.
1. In the **Admin** area, create a setting to enable or disable the feature.
1. Replace the feature flag everywhere with the application setting.
1. Update all the relevant documentation pages.
1. Mark the backfill migration as a `NOOP` and remove the feature flag after the mandatory upgrade path is crossed.
For an example, see [merge request 151080](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/151080).
The changes to backfill application settings and use the settings in the code must be merged in the same milestone.
If frontend changes are merged in a later milestone, you should add documentation about how to update the settings
by using the [application settings API](../../api/settings.md) or the Rails console.
## Develop with a feature flag
There are two main ways of using feature flags in the GitLab codebase:

View File

@ -258,4 +258,4 @@ resolved.
- Blog post: [Getting started with Git LFS](https://about.gitlab.com/blog/2017/01/30/getting-started-with-git-lfs-tutorial/)
- User documentation: [Git Large File Storage (LFS)](../topics/git/lfs/index.md)
- [GitLab Git Large File Storage (LFS) Administration](../administration/lfs/index.md) for self-managed instances
- [GitLab Git Large File Storage (LFS) Administration](../administration/lfs/index.md) for GitLab Self-Managed

View File

@ -239,7 +239,7 @@ Your migration **must be** reversible. This is very important, as it should
be possible to downgrade in case of a vulnerability or bugs.
**Note**: On GitLab production environments, if a problem occurs, a roll-forward strategy is used instead of rolling back migrations using `db:rollback`.
On self-managed instances we advise users to restore the backup which was created before the upgrade process started.
On GitLab Self-Managed, we advise users to restore the backup which was created before the upgrade process started.
The `down` method is used primarily in the development environment, for example, when a developer wants to ensure
their local copy of `structure.sql` file and database are in a consistent state when switching between commits or branches.
@ -1544,7 +1544,7 @@ Any table which has some high read operation compared to current [high-traffic t
As a general rule, we discourage adding columns to high-traffic tables that are purely for
analytics or reporting of GitLab.com. This can have negative performance impacts for all
self-managed instances without providing direct feature value to them.
GitLab Self-Managed instances without providing direct feature value to them.
## Milestone

View File

@ -63,7 +63,7 @@ This window takes place on April 28 - 30, 2025 from 09:00 UTC to 22:00 UTC.
| [Replace GraphQL field `take_ownership_pipeline_schedule` with `admin_pipeline_schedule` in PipelineSchedulePermissions](https://gitlab.com/gitlab-org/gitlab/-/issues/391941) | Low | Verify | Project |
| [`GITLAB_SHARED_RUNNERS_REGISTRATION_TOKEN` is deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/453949) | Medium | Verify | Instance |
| [The `heroku/builder:22` image is deprecated](https://gitlab.com/gitlab-org/cluster-integration/auto-build-image/-/issues/79) | Medium | Deploy | Project |
| [`ciUsedMinutes` GraphQL field renamed to `ciDuration`](https://gitlab.com/gitlab-org/gitlab/-/issues/497364) | Medium | Verify | Instance |
| [`ciMinutesUsed` GraphQL field renamed to `ciDuration`](https://gitlab.com/gitlab-org/gitlab/-/issues/497364) | Medium | Verify | Instance |
| [`mergeTrainIndex` and `mergeTrainsCount` GraphQL fields deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/473759) | Low | Verify | Project |
| [RunnersRegistrationTokenReset GraphQL mutation is deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/505703) | High | Verify | Instance, group, project |
| [Behavior change for Upcoming and Started milestone filters](https://gitlab.com/gitlab-org/gitlab/-/issues/501294) | Low | Plan | Group, project |

View File

@ -1213,9 +1213,9 @@ Instance administrators can set higher or lower limits as needed in the Admin ar
</div>
The support for registration tokens and certain runner configuration arguments in the `POST` method operation on the `/api/v4/runners` endpoint is deprecated.
This endpoint [registers](https://docs.gitlab.com/ee/api/runners.html#register-a-new-runner) a runner
with a GitLab instance at the instance, group, or project level through the API. In GitLab 17.0, registration tokens, and support for certain configuration arguments,
will start returning the HTTP `410 Gone` status code in GitLab 17.0. For more information, see [Migrating to the new runner registration workflow](https://docs.gitlab.com/ee/ci/runners/new_creation_workflow.html#prevent-your-runner-registration-workflow-from-breaking).
This endpoint [registers](https://docs.gitlab.com/ee/api/runners.html#create-a-runner) a runner
with a GitLab instance at the instance, group, or project level through the API. In GitLab 18.0, registration tokens, and support for certain configuration arguments,
will start returning the HTTP `410 Gone` status code. For more information, see [Migrating to the new runner registration workflow](https://docs.gitlab.com/ee/ci/runners/new_creation_workflow.html#prevent-your-runner-registration-workflow-from-breaking).
The configuration arguments disabled for runner authentication tokens are:
@ -1451,7 +1451,7 @@ A new method to bind runners to a GitLab instance has been implemented
as part of the new [GitLab Runner token architecture](https://docs.gitlab.com/ee/ci/runners/new_creation_workflow.html).
For details, see [epic 7633](https://gitlab.com/groups/gitlab-org/-/epics/7633).
This new architecture introduces a new method for registering runners and eliminates the legacy
[runner registration token](https://docs.gitlab.com/ee/security/token_overview.html#runner-registration-tokens).
[runner registration token](https://docs.gitlab.com/ee/security/tokens/index.html#runner-registration-tokens-deprecated).
In GitLab 18.0, only the runner registration methods implemented in the new GitLab Runner token architecture will be supported.
</div>
@ -1524,7 +1524,7 @@ We plan to implement a new method to bind runners to a GitLab instance
as part of the new [GitLab Runner token architecture](https://docs.gitlab.com/ee/ci/runners/new_creation_workflow.html).
The work is planned in [this epic](https://gitlab.com/groups/gitlab-org/-/epics/7633).
This new architecture introduces a new method for registering runners and will eliminate the legacy
[runner registration token](https://docs.gitlab.com/ee/security/token_overview.html#runner-registration-tokens).
[runner registration token](https://docs.gitlab.com/ee/security/tokens/index.html#runner-registration-tokens-deprecated).
From GitLab 18.0 and later, the runner registration methods implemented by the new GitLab Runner token architecture will be the only supported methods.
</div>
@ -1737,7 +1737,7 @@ With the [upcoming default behavior change to the CI/CD job token](https://docs.
<div class="deprecation breaking-change" data-milestone="18.0">
### `ciUsedMinutes` GraphQL field renamed to `ciDuration`
### `ciMinutesUsed` GraphQL field renamed to `ciDuration`
<div class="deprecation-notes">
@ -1747,8 +1747,8 @@ With the [upcoming default behavior change to the CI/CD job token](https://docs.
</div>
The `ciDuration` field of the `CiRunnerUsage` and `CiRunnerUsageByProject` types replaces the former `ciUsedMinutes` field.
Update all references to `ciUsedMinutes` from these types to `ciDuration`.
The `ciDuration` field of the `CiRunnerUsage` and `CiRunnerUsageByProject` types replaces the former `ciMinutesUsed` field.
Update all references to `ciMinutesUsed` from these types to `ciDuration`.
</div>

View File

@ -476,6 +476,9 @@ To disable publishing duplicate file names:
1. In the **Generic** row of the **Duplicate packages** table, turn off the **Allow duplicates** toggle.
1. Optional. In the **Exceptions** text box, enter a regular expression that matches the names and versions of packages to allow.
NOTE:
If **Allow duplicates** is turned on, you can specify package names and versions that should not have duplicates in the **Exceptions** text box.
## Add a package retention policy
Implement a package retention policy to manage storage and maintain relevant versions.

View File

@ -874,6 +874,9 @@ In the UI:
1. In the **Maven** row of the **Duplicate packages** table, turn off the **Allow duplicates** toggle.
1. Optional. In the **Exceptions** text box, enter a regular expression that matches the names and versions of packages to allow.
NOTE:
If **Allow duplicates** is turned on, you can specify package names and versions that should not have duplicates in the **Exceptions** text box.
Your changes are automatically saved.
### Request forwarding to Maven Central

View File

@ -445,6 +445,9 @@ In the UI:
1. In the **NuGet** row of the **Duplicate packages** table, turn off the **Allow duplicates** toggle.
1. Optional. In the **Exceptions** text box, enter a regular expression that matches the names and versions of packages to allow.
NOTE:
If **Allow duplicates** is turned on, you can specify package names and versions that should not have duplicates in the **Exceptions** text box.
Your changes are automatically saved.
WARNING:

View File

@ -171,10 +171,13 @@ To allow publishing duplicate module names:
1. On the left sidebar, select **Search or go to** and find your group.
1. Select **Settings > Packages and registries**.
1. In the **Terraform module** row of the **Duplicate packages** table, turn off the **Allow duplicates** toggle.
1. Optional. In the **Exceptions** text box, enter a regular expression that matches the names of packages to allow.
1. Optional. In the **Exceptions** text box, enter a regular expression that matches the names of modules to allow.
Your changes are automatically saved.
NOTE:
If **Allow duplicates** is turned on, you can specify module names that should not have duplicates in the **Exceptions** text box.
You can also allow publishing duplicate names by enabling `terraform_module_duplicates_allowed` in the [GraphQL API](../../../api/graphql/reference/_index.md#packagesettings).
To allow duplicates with specific names:

View File

@ -6,8 +6,6 @@ module API
TAG_ENDPOINT_REQUIREMENTS = API::NAMESPACE_OR_PROJECT_REQUIREMENTS.merge(name: API::NO_SLASH_URL_PART_REGEX)
before { authorize_admin_project }
feature_category :source_code_management
helpers Helpers::ProtectedTagsHelpers
@ -31,6 +29,7 @@ module API
end
# rubocop: disable CodeReuse/ActiveRecord
get ':id/protected_tags' do
authorize!(:read_protected_tags, user_project)
protected_tags = user_project.protected_tags.preload(:create_access_levels)
present paginate(protected_tags), with: Entities::ProtectedTag, project: user_project
@ -51,6 +50,7 @@ module API
end
# rubocop: disable CodeReuse/ActiveRecord
get ':id/protected_tags/:name', requirements: TAG_ENDPOINT_REQUIREMENTS do
authorize!(:read_protected_tags, user_project)
protected_tag = user_project.protected_tags.find_by!(name: params[:name])
present protected_tag, with: Entities::ProtectedTag, project: user_project
@ -77,6 +77,7 @@ module API
use :optional_params_ee
end
post ':id/protected_tags' do
authorize!(:create_protected_tags, user_project)
protected_tags_params = {
name: params[:name],
create_access_levels_attributes: ::ProtectedRefs::AccessLevelParams.new(:create, params).access_levels
@ -108,9 +109,14 @@ module API
end
# rubocop: disable CodeReuse/ActiveRecord
delete ':id/protected_tags/:name', requirements: TAG_ENDPOINT_REQUIREMENTS do
authorize!(:destroy_protected_tags, user_project)
protected_tag = user_project.protected_tags.find_by!(name: params[:name])
destroy_conditionally!(protected_tag)
destroy_conditionally!(protected_tag) do
destroy_service = ::ProtectedTags::DestroyService.new(user_project, current_user)
destroy_service.execute(protected_tag)
end
end
# rubocop: enable CodeReuse/ActiveRecord
end

View File

@ -82,16 +82,10 @@ RSpec.describe 'Group Package and registry settings', feature_category: :package
wait_for_requests
within_testid 'maven-settings' do
expect(page).to have_field _('Exceptions')
click_button class: 'gl-toggle'
expect(page).to have_field _('Exceptions'), disabled: false
visit_settings_page
expect(page).to have_field _('Exceptions'), disabled: false
end
expect(find('.gl-toast')).to have_content('Settings saved successfully.')
end
it 'shows an error on wrong regex', :js do
@ -101,7 +95,7 @@ RSpec.describe 'Group Package and registry settings', feature_category: :package
within_testid 'maven-settings' do
click_button class: 'gl-toggle'
fill_in _('Exceptions'), with: ')'
fill_in class: 'gl-form-input', with: ')'
# simulate blur event
send_keys(:tab)
@ -110,64 +104,16 @@ RSpec.describe 'Group Package and registry settings', feature_category: :package
expect(page).to have_content('is an invalid regexp')
end
context 'when packages_allow_duplicate_exceptions disabled' do
before do
stub_feature_flags(packages_allow_duplicate_exceptions: false)
end
it 'automatically saves changes to the server', :js do
visit_settings_page
wait_for_requests
within_testid 'maven-settings' do
expect(page).to have_field _('Exceptions'), disabled: true
click_button class: 'gl-toggle'
expect(page).to have_field _('Exceptions'), disabled: false
visit_settings_page
expect(page).to have_field _('Exceptions'), disabled: false
end
end
end
context 'in a sub group' do
it 'works correctly', :js do
it 'automatically saves changes to the server', :js do
visit_sub_group_settings_page
wait_for_requests
within_testid 'maven-settings' do
expect(page).to have_content('Allow duplicates')
expect(page).to have_field _('Exceptions')
click_button class: 'gl-toggle'
expect(page).to have_field _('Exceptions'), disabled: false
end
end
context 'when packages_allow_duplicate_exceptions disabled' do
before do
stub_feature_flags(packages_allow_duplicate_exceptions: false)
end
it 'works correctly', :js do
visit_sub_group_settings_page
wait_for_requests
within_testid 'maven-settings' do
expect(page).to have_content('Allow duplicates')
expect(page).to have_field _('Exceptions'), disabled: true
click_button class: 'gl-toggle'
expect(page).to have_field _('Exceptions'), disabled: false
end
end
expect(find('.gl-toast')).to have_content('Settings saved successfully.')
end
end
end

View File

@ -8,7 +8,6 @@ describe('Exceptions Input', () => {
let wrapper;
const defaultProps = {
duplicatesAllowed: false,
duplicateExceptionRegex: 'foo',
id: 'maven-duplicated-settings-regex-input',
name: 'exceptionModel',

View File

@ -37,9 +37,6 @@ describe('Packages Settings', () => {
const mountComponent = ({
mountFn = shallowMountExtended,
mutationResolver = jest.fn().mockResolvedValue(groupPackageSettingsMutationMock()),
features = {
packagesAllowDuplicateExceptions: false,
},
} = {}) => {
Vue.use(VueApollo);
@ -49,10 +46,7 @@ describe('Packages Settings', () => {
wrapper = mountFn(component, {
apolloProvider,
provide: {
...defaultProvide,
glFeatures: features,
},
provide: defaultProvide,
propsData: {
packageSettings,
},
@ -141,12 +135,11 @@ describe('Packages Settings', () => {
it('renders ExceptionsInput and assigns duplication allowness and exception props', () => {
mountComponent({ mountFn: mountExtended });
const { mavenDuplicatesAllowed, mavenDuplicateExceptionRegex } = packageSettings;
const { mavenDuplicateExceptionRegex } = packageSettings;
expect(findMavenDuplicatedSettingsExceptionsInput().exists()).toBe(true);
expect(findMavenDuplicatedSettingsExceptionsInput().props()).toMatchObject({
duplicatesAllowed: mavenDuplicatesAllowed,
duplicateExceptionRegex: mavenDuplicateExceptionRegex,
duplicateExceptionRegexError: '',
loading: false,
@ -155,28 +148,6 @@ describe('Packages Settings', () => {
});
});
describe('with packagesAllowDuplicateExceptions FF enabled', () => {
it('renders ExceptionsInput and assigns duplication allowness and exception props', () => {
mountComponent({
mountFn: mountExtended,
features: { packagesAllowDuplicateExceptions: true },
});
const { mavenDuplicateExceptionRegex } = packageSettings;
expect(findMavenDuplicatedSettingsExceptionsInput().exists()).toBe(true);
expect(findMavenDuplicatedSettingsExceptionsInput().props()).toMatchObject({
duplicatesAllowed: false,
duplicateExceptionRegex: mavenDuplicateExceptionRegex,
duplicateExceptionRegexError: '',
loading: false,
name: 'mavenDuplicateExceptionRegex',
id: 'maven-duplicated-settings-regex-input',
});
});
});
it('on update event calls the mutation', () => {
const mutationResolver = jest.fn().mockResolvedValue(groupPackageSettingsMutationMock());
mountComponent({ mountFn: mountExtended, mutationResolver });
@ -215,10 +186,9 @@ describe('Packages Settings', () => {
it('renders ExceptionsInput and assigns duplication allowness and exception props', () => {
mountComponent({ mountFn: mountExtended });
const { genericDuplicatesAllowed, genericDuplicateExceptionRegex } = packageSettings;
const { genericDuplicateExceptionRegex } = packageSettings;
expect(findGenericDuplicatedSettingsExceptionsInput().props()).toMatchObject({
duplicatesAllowed: genericDuplicatesAllowed,
duplicateExceptionRegex: genericDuplicateExceptionRegex,
duplicateExceptionRegexError: '',
loading: false,
@ -227,26 +197,6 @@ describe('Packages Settings', () => {
});
});
describe('with packagesAllowDuplicateExceptions FF enabled', () => {
it('renders ExceptionsInput and assigns duplication allowness and exception props', () => {
mountComponent({
mountFn: mountExtended,
features: { packagesAllowDuplicateExceptions: true },
});
const { genericDuplicateExceptionRegex } = packageSettings;
expect(findGenericDuplicatedSettingsExceptionsInput().props()).toMatchObject({
duplicatesAllowed: false,
duplicateExceptionRegex: genericDuplicateExceptionRegex,
duplicateExceptionRegexError: '',
loading: false,
name: 'genericDuplicateExceptionRegex',
id: 'generic-duplicated-settings-regex-input',
});
});
});
it('on update event calls the mutation', () => {
const mutationResolver = jest.fn().mockResolvedValue(groupPackageSettingsMutationMock());
mountComponent({ mountFn: mountExtended, mutationResolver });
@ -287,10 +237,9 @@ describe('Packages Settings', () => {
it('renders ExceptionsInput and assigns duplication allowness and exception props', () => {
mountComponent({ mountFn: mountExtended });
const { nugetDuplicatesAllowed, nugetDuplicateExceptionRegex } = packageSettings;
const { nugetDuplicateExceptionRegex } = packageSettings;
expect(findNugetDuplicatedSettingsExceptionsInput().props()).toMatchObject({
duplicatesAllowed: nugetDuplicatesAllowed,
duplicateExceptionRegex: nugetDuplicateExceptionRegex,
duplicateExceptionRegexError: '',
loading: false,
@ -338,11 +287,9 @@ describe('Packages Settings', () => {
it('renders ExceptionsInput and assigns duplication allowness and exception props', () => {
mountComponent({ mountFn: mountExtended });
const { terraformModuleDuplicatesAllowed, terraformModuleDuplicateExceptionRegex } =
packageSettings;
const { terraformModuleDuplicateExceptionRegex } = packageSettings;
expect(findTerraformModuleDuplicatedSettingsExceptionsInput().props()).toMatchObject({
duplicatesAllowed: terraformModuleDuplicatesAllowed,
duplicateExceptionRegex: terraformModuleDuplicateExceptionRegex,
duplicateExceptionRegexError: '',
loading: false,
@ -351,26 +298,6 @@ describe('Packages Settings', () => {
});
});
describe('with packagesAllowDuplicateExceptions FF enabled', () => {
it('renders ExceptionsInput and assigns duplication allowness and exception props', () => {
mountComponent({
mountFn: mountExtended,
features: { packagesAllowDuplicateExceptions: true },
});
const { terraformModuleDuplicateExceptionRegex } = packageSettings;
expect(findTerraformModuleDuplicatedSettingsExceptionsInput().props()).toMatchObject({
duplicatesAllowed: false,
duplicateExceptionRegex: terraformModuleDuplicateExceptionRegex,
duplicateExceptionRegexError: '',
loading: false,
name: 'terraformModuleDuplicateExceptionRegex',
id: 'terraform-module-duplicated-settings-regex-input',
});
});
});
it('on update event calls the mutation', () => {
const mutationResolver = jest.fn().mockResolvedValue(groupPackageSettingsMutationMock());
mountComponent({ mountFn: mountExtended, mutationResolver });

View File

@ -535,19 +535,48 @@ RSpec.describe Ci::Runner, type: :model, factory_default: :keep, feature_categor
end
context 'with project runner' do
let(:runner) { create(:ci_runner, :project, projects: [other_project]) }
let_it_be_with_refind(:owner_project) { create(:project, group: group) }
let_it_be_with_reload(:fallback_owner_project) { create(:project, group: group) }
let(:associated_projects) { [owner_project, fallback_owner_project] }
let(:runner) { create(:ci_runner, :project, projects: associated_projects) }
it 'assigns runner to project' do
expect(assign_to).to be_truthy
expect(runner).to be_project_type
expect(runner.runner_projects.pluck(:project_id)).to contain_exactly(project.id, other_project.id)
expect(runner.runner_projects.pluck(:project_id))
.to contain_exactly(project.id, owner_project.id, fallback_owner_project.id)
end
it 'does not change sharding_key_id or owner' do
expect { assign_to }
.to not_change { runner.sharding_key_id }.from(other_project.id)
.and not_change { runner.owner }.from(other_project)
.to not_change { runner.sharding_key_id }.from(owner_project.id)
.and not_change { runner.owner }.from(owner_project)
end
context 'when sharding_key_id does not point to an existing project' do
subject(:assign_to) do
owner_project.destroy!
runner.assign_to(project)
end
it 'changes sharding_key_id and owner to fallback owner project' do
expect { assign_to }
.to change { runner.sharding_key_id }.from(owner_project.id).to(fallback_owner_project.id)
.and change { runner.owner }.from(owner_project).to(fallback_owner_project)
end
context 'and fallback does not exist' do
let(:associated_projects) { [owner_project] }
it 'changes sharding_key_id and owner to newly-assigned project' do
expect { assign_to }
.to change { runner.sharding_key_id }.from(owner_project.id).to(project.id)
.and change { runner.owner }.from(owner_project).to(project)
end
end
end
end
end

View File

@ -142,41 +142,6 @@ RSpec.describe Namespace::PackageSetting, feature_category: :package_registry do
end
end
context 'with packages_allow_duplicate_exceptions disabled' do
before do
stub_feature_flags(packages_allow_duplicate_exceptions: false)
end
context 'package types with package_settings' do
Namespace::PackageSetting::PACKAGES_WITH_SETTINGS.each do |package_type|
context "with package_type: #{package_type}" do
let_it_be(:package) { create("#{package_type}_package", package_name_and_version(package_type)) }
let_it_be(:package_type) { package.package_type }
let_it_be(:package_setting) { package.project.namespace.package_settings }
where(:duplicates_allowed, :duplicate_exception_regex, :result) do
true | '' | true
false | '' | false
false | '.*' | true
false | 'fo.*' | true
false | '.*be.*' | true
end
with_them do
before do
package_setting.update!(
"#{package_type}_duplicates_allowed" => duplicates_allowed,
"#{package_type}_duplicate_exception_regex" => duplicate_exception_regex
)
end
it { is_expected.to be(result) }
end
end
end
end
end
it_behaves_like 'package types without package_settings'
end

View File

@ -562,44 +562,6 @@ RSpec.describe API::GenericPackages, feature_category: :package_registry do
it_behaves_like 'returns a bad request'
end
context 'with packages_allow_duplicate_exceptions disabled' do
before do
stub_feature_flags(packages_allow_duplicate_exceptions: false)
end
it_behaves_like 'returns a bad request'
context 'when regex matches package name' do
before do
package_settings.update_column(
:generic_duplicate_exception_regex,
".*#{existing_package.name.last(3)}.*"
)
end
it_behaves_like 'creates a new package'
end
context 'when regex matches package version' do
before do
package_settings.update_column(
:generic_duplicate_exception_regex,
".*#{existing_package.version.last(3)}.*"
)
end
it_behaves_like 'creates a new package'
end
context 'when regex does not match package name or version' do
before do
package_settings.update_column(:generic_duplicate_exception_regex, ".*zzz.*")
end
it_behaves_like 'returns a bad request'
end
end
end
context 'when package duplicates are allowed' do
@ -638,44 +600,6 @@ RSpec.describe API::GenericPackages, feature_category: :package_registry do
it_behaves_like 'creates a new package'
end
context 'with packages_allow_duplicate_exceptions disabled' do
before do
stub_feature_flags(packages_allow_duplicate_exceptions: false)
end
it_behaves_like 'creates a new package'
context 'when regex matches package name' do
before do
package_settings.update_column(
:generic_duplicate_exception_regex,
".*#{existing_package.name.last(3)}.*"
)
end
it_behaves_like 'creates a new package'
end
context 'when regex matches package version' do
before do
package_settings.update_column(
:generic_duplicate_exception_regex,
".*#{existing_package.version.last(3)}.*"
)
end
it_behaves_like 'creates a new package'
end
context 'when regex does not match package name or version' do
before do
package_settings.update_column(:generic_duplicate_exception_regex, ".*zzz.*")
end
it_behaves_like 'creates a new package'
end
end
end
context 'marked as pending_destruction' do

View File

@ -119,14 +119,6 @@ RSpec.describe Packages::Generic::CreatePackageFileService, feature_category: :p
end
it_behaves_like 'allows creating the file'
context 'when packages_allow_duplicate_exceptions is disabled' do
before do
stub_feature_flags(packages_allow_duplicate_exceptions: false)
end
it_behaves_like 'allows creating the file'
end
end
end
@ -143,14 +135,6 @@ RSpec.describe Packages::Generic::CreatePackageFileService, feature_category: :p
end
it_behaves_like 'does not allow duplicates'
context 'when packages_allow_duplicate_exceptions is disabled' do
before do
stub_feature_flags(packages_allow_duplicate_exceptions: false)
end
it_behaves_like 'allows creating the file'
end
end
context 'with multiple files for the same package and the same pipeline' do

View File

@ -55,14 +55,6 @@ RSpec.describe Packages::Maven::FindOrCreatePackageService, feature_category: :p
end
end
shared_examples 'reuse existing package when packages_allow_duplicate_exceptions is disabled' do
before do
stub_feature_flags(packages_allow_duplicate_exceptions: false)
end
it_behaves_like 'reuse existing package'
end
context 'with path including version' do
# Note that "path with version" and "file type maven metadata xml" only exists for snapshot versions
# In other words, we will never have an metadata xml upload on a path with version for a non snapshot version
@ -237,8 +229,6 @@ RSpec.describe Packages::Maven::FindOrCreatePackageService, feature_category: :p
end
it_behaves_like 'returning an error', with_message: 'Duplicate package is not allowed'
it_behaves_like 'reuse existing package when packages_allow_duplicate_exceptions is disabled'
end
context 'when the package version matches the exception regex' do
@ -247,8 +237,6 @@ RSpec.describe Packages::Maven::FindOrCreatePackageService, feature_category: :p
end
it_behaves_like 'returning an error', with_message: 'Duplicate package is not allowed'
it_behaves_like 'reuse existing package when packages_allow_duplicate_exceptions is disabled'
end
context 'when the exception regex is blank' do

View File

@ -94,15 +94,6 @@ RSpec.describe Packages::TerraformModule::CreatePackageService, feature_category
it_behaves_like 'duplicate package error'
it_behaves_like 'with duplicate regex exception, allow creation of matching package'
context 'when packages_allow_duplicate_exceptions is disabled' do
before do
stub_feature_flags(packages_allow_duplicate_exceptions: false)
end
it_behaves_like 'duplicate package error'
it_behaves_like 'with duplicate regex exception, allow creation of matching package'
end
end
context 'when duplicates allowed' do
@ -112,14 +103,6 @@ RSpec.describe Packages::TerraformModule::CreatePackageService, feature_category
it_behaves_like 'creating a package'
it_behaves_like 'with duplicate regex exception, prevent creation of matching package'
context 'when packages_allow_duplicate_exceptions is disabled' do
before do
stub_feature_flags(packages_allow_duplicate_exceptions: false)
end
it_behaves_like 'creating a package'
end
end
context 'for ancestor namespace' do
@ -147,14 +130,6 @@ RSpec.describe Packages::TerraformModule::CreatePackageService, feature_category
end
it_behaves_like 'duplicate package error'
context 'with packages_allow_duplicate_exceptions disabled' do
before do
stub_feature_flags(packages_allow_duplicate_exceptions: false)
end
it_behaves_like 'creating a package'
end
end
end