Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitleaksignore1
-rw-r--r--.rubocop_todo/gitlab/namespaced_class.yml1
-rw-r--r--Gemfile2
-rw-r--r--Gemfile.checksum2
-rw-r--r--Gemfile.lock4
-rw-r--r--app/assets/stylesheets/_page_specific_files.scss1
-rw-r--r--app/assets/stylesheets/page_bundles/projects_usage_quotas.scss (renamed from app/assets/stylesheets/pages/storage_quota.scss)4
-rw-r--r--app/controllers/admin/application_settings_controller.rb4
-rw-r--r--app/models/bulk_imports/entity.rb2
-rw-r--r--app/models/concerns/enums/package_metadata.rb4
-rw-r--r--app/models/user_preference.rb2
-rw-r--r--app/policies/group_policy.rb11
-rw-r--r--app/services/bulk_imports/create_service.rb27
-rw-r--r--app/services/ci/runners/create_runner_service.rb2
-rw-r--r--app/views/layouts/nav/sidebar/_admin.html.haml1
-rw-r--r--app/views/projects/usage_quotas/index.html.haml1
-rw-r--r--config/application.rb1
-rw-r--r--config/feature_flags/development/fix_dora_deployment_frequency_calculation.yml8
-rw-r--r--db/migrate/20230403145705_add_purl_sync_to_settings.rb7
-rw-r--r--db/migrate/20230406134436_add_identity_toggle_to_user_preferences.rb9
-rw-r--r--db/schema_migrations/202304031457051
-rw-r--r--db/schema_migrations/202304061344361
-rw-r--r--db/structure.sql2
-rw-r--r--doc/api/bulk_imports.md5
-rw-r--r--doc/api/runners.md32
-rw-r--r--doc/api/users.md39
-rw-r--r--doc/user/admin_area/settings/index.md4
-rw-r--r--doc/user/admin_area/settings/security_and_compliance.md20
-rw-r--r--doc/user/compliance/license_scanning_of_cyclonedx_files/index.md1
-rw-r--r--doc/user/group/import/index.md4
-rw-r--r--doc/user/ssh.md2
-rw-r--r--lib/api/bulk_imports.rb4
-rw-r--r--lib/api/ci/runner.rb10
-rw-r--r--lib/api/ci/runners.rb6
-rw-r--r--lib/api/users.rb55
-rw-r--r--lib/bulk_imports/error.rb5
-rw-r--r--lib/bulk_imports/projects/transformers/project_attributes_transformer.rb2
-rw-r--r--lib/gitlab/import_export/base/relation_factory.rb7
-rw-r--r--lib/gitlab/import_export/project/import_export.yml24
-rw-r--r--lib/gitlab/import_export/project/relation_factory.rb8
-rw-r--r--locale/gitlab.pot9
-rw-r--r--package.json2
-rw-r--r--spec/features/projects/pipeline_schedules_spec.rb1
-rw-r--r--spec/fixtures/lib/gitlab/import_export/complex/project.json37
-rw-r--r--spec/frontend/alerts_settings/components/__snapshots__/alerts_form_spec.js.snap1
-rw-r--r--spec/lib/bulk_imports/groups/transformers/group_attributes_transformer_spec.rb43
-rw-r--r--spec/lib/bulk_imports/projects/transformers/project_attributes_transformer_spec.rb23
-rw-r--r--spec/lib/gitlab/import_export/all_models.yml17
-rw-r--r--spec/lib/gitlab/import_export/safe_model_attributes.yml18
-rw-r--r--spec/models/user_preference_spec.rb7
-rw-r--r--spec/policies/group_policy_spec.rb118
-rw-r--r--spec/requests/api/bulk_imports_spec.rb20
-rw-r--r--spec/requests/api/users_spec.rb154
-rw-r--r--spec/services/bulk_imports/create_service_spec.rb83
-rw-r--r--spec/services/ci/runners/create_runner_service_spec.rb11
-rw-r--r--spec/support/shared_examples/bulk_imports/visibility_level_examples.rb37
-rw-r--r--spec/support/shared_examples/finders/issues_finder_shared_examples.rb4
-rw-r--r--yarn.lock8
58 files changed, 774 insertions, 145 deletions
diff --git a/.gitleaksignore b/.gitleaksignore
index eab7926138c..56652ab4dae 100644
--- a/.gitleaksignore
+++ b/.gitleaksignore
@@ -1,2 +1,3 @@
7e07fe42d34916b276a7b068f4faa8bdc0ebc984:doc/architecture/blueprints/runner_tokens/index.md:gitlab-rrt:485
f6504b498548380198ad38295d9caa71412115f0:doc/architecture/blueprints/runner_tokens/index.md:generic-api-key:506
+afedb913baf4203aa688421873fdb9f94649578e:doc/api/users.md:generic-api-key:2201
diff --git a/.rubocop_todo/gitlab/namespaced_class.yml b/.rubocop_todo/gitlab/namespaced_class.yml
index df842dd1c22..0ec0bc66869 100644
--- a/.rubocop_todo/gitlab/namespaced_class.yml
+++ b/.rubocop_todo/gitlab/namespaced_class.yml
@@ -875,6 +875,7 @@ Gitlab/NamespacedClass:
- 'ee/app/models/approval_merge_request_rule.rb'
- 'ee/app/models/approval_merge_request_rule_source.rb'
- 'ee/app/models/approval_project_rule.rb'
+ - 'ee/app/models/approval_project_rules_user.rb'
- 'ee/app/models/approval_project_rules_protected_branch.rb'
- 'ee/app/models/approval_state.rb'
- 'ee/app/models/approval_wrapped_any_approver_rule.rb'
diff --git a/Gemfile b/Gemfile
index dc47a224332..2d71fd1527d 100644
--- a/Gemfile
+++ b/Gemfile
@@ -371,7 +371,7 @@ gem 'prometheus-client-mmap', '~> 0.19', require: 'prometheus/client'
gem 'warning', '~> 1.3.0'
group :development do
- gem 'lefthook', '~> 1.3.9', require: false
+ gem 'lefthook', '~> 1.3.10', require: false
gem 'rubocop'
gem 'solargraph', '~> 0.47.2', require: false
diff --git a/Gemfile.checksum b/Gemfile.checksum
index 1ca1791b3e1..ac037cd00af 100644
--- a/Gemfile.checksum
+++ b/Gemfile.checksum
@@ -327,7 +327,7 @@
{"name":"kramdown-parser-gfm","version":"1.1.0","platform":"ruby","checksum":"fb39745516427d2988543bf01fc4cf0ab1149476382393e0e9c48592f6581729"},
{"name":"kubeclient","version":"4.11.0","platform":"ruby","checksum":"4985fcd749fb8c364a668a8350a49821647f03aa52d9ee6cbc582beb8e883fcc"},
{"name":"launchy","version":"2.5.0","platform":"ruby","checksum":"954243c4255920982ce682f89a42e76372dba94770bf09c23a523e204bdebef5"},
-{"name":"lefthook","version":"1.3.9","platform":"ruby","checksum":"e305760b9e9e0de66662270d5803a753127fba6dc33baf013ff1ca7df0488c88"},
+{"name":"lefthook","version":"1.3.10","platform":"ruby","checksum":"68cd583689b0484eed4e5eee58fb4a8c1b40892821d69cd813f8b38e959a59b3"},
{"name":"letter_opener","version":"1.7.0","platform":"ruby","checksum":"095bc0d58e006e5b43ea7d219e64ecf2de8d1f7d9dafc432040a845cf59b4725"},
{"name":"letter_opener_web","version":"2.0.0","platform":"ruby","checksum":"33860ad41e1785d75456500e8ca8bba8ed71ee6eaf08a98d06bbab67c5577b6f"},
{"name":"libyajl2","version":"1.2.0","platform":"ruby","checksum":"1117cd1e48db013b626e36269bbf1cef210538ca6d2e62d3fa3db9ded005b258"},
diff --git a/Gemfile.lock b/Gemfile.lock
index 7069b8986ae..2bd006d7a97 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -885,7 +885,7 @@ GEM
rest-client (~> 2.0)
launchy (2.5.0)
addressable (~> 2.7)
- lefthook (1.3.9)
+ lefthook (1.3.10)
letter_opener (1.7.0)
launchy (~> 2.2)
letter_opener_web (2.0.0)
@@ -1803,7 +1803,7 @@ DEPENDENCIES
knapsack (~> 1.21.1)
kramdown (~> 2.3.1)
kubeclient (~> 4.11.0)
- lefthook (~> 1.3.9)
+ lefthook (~> 1.3.10)
letter_opener_web (~> 2.0.0)
license_finder (~> 7.0)
licensee (~> 9.15)
diff --git a/app/assets/stylesheets/_page_specific_files.scss b/app/assets/stylesheets/_page_specific_files.scss
index c7693fb993d..cd626f449d9 100644
--- a/app/assets/stylesheets/_page_specific_files.scss
+++ b/app/assets/stylesheets/_page_specific_files.scss
@@ -14,4 +14,3 @@
@import './pages/projects';
@import './pages/registry';
@import './pages/settings';
-@import './pages/storage_quota';
diff --git a/app/assets/stylesheets/pages/storage_quota.scss b/app/assets/stylesheets/page_bundles/projects_usage_quotas.scss
index 347bd1316c0..8f2cbc402c9 100644
--- a/app/assets/stylesheets/pages/storage_quota.scss
+++ b/app/assets/stylesheets/page_bundles/projects_usage_quotas.scss
@@ -1,3 +1,5 @@
+@import 'mixins_and_variables_and_functions';
+
.storage-type-usage {
&:first-child {
@include gl-rounded-top-left-base;
@@ -12,6 +14,6 @@
&:not(:last-child) {
@include gl-border-r-2;
@include gl-border-r-solid;
- @include gl-border-white;
+ border-right-color: var(--white, $white);
}
}
diff --git a/app/controllers/admin/application_settings_controller.rb b/app/controllers/admin/application_settings_controller.rb
index 0bbfeae6656..96d78034ad6 100644
--- a/app/controllers/admin/application_settings_controller.rb
+++ b/app/controllers/admin/application_settings_controller.rb
@@ -234,6 +234,9 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController
params[:application_setting][:valid_runner_registrars]&.delete("")
params[:application_setting][:restricted_visibility_levels]&.delete("")
+ params[:application_setting][:package_metadata_purl_types]&.delete("")
+ params[:application_setting][:package_metadata_purl_types]&.map!(&:to_i)
+
if params[:application_setting].key?(:required_instance_ci_template)
if params[:application_setting][:required_instance_ci_template].empty?
params[:application_setting][:required_instance_ci_template] = nil
@@ -276,6 +279,7 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController
:default_branch_name,
disabled_oauth_sign_in_sources: [],
import_sources: [],
+ package_metadata_purl_types: [],
restricted_visibility_levels: [],
repository_storages_weighted: {},
valid_runner_registrars: []
diff --git a/app/models/bulk_imports/entity.rb b/app/models/bulk_imports/entity.rb
index d5d1d38784e..b3540917197 100644
--- a/app/models/bulk_imports/entity.rb
+++ b/app/models/bulk_imports/entity.rb
@@ -56,7 +56,7 @@ class BulkImports::Entity < ApplicationRecord
validates :destination_namespace,
presence: true,
- if: :project
+ if: :project?
validate :validate_parent_is_a_group, if: :parent
validate :validate_imported_entity_type
diff --git a/app/models/concerns/enums/package_metadata.rb b/app/models/concerns/enums/package_metadata.rb
index abacee363c9..a866e2b995a 100644
--- a/app/models/concerns/enums/package_metadata.rb
+++ b/app/models/concerns/enums/package_metadata.rb
@@ -20,5 +20,9 @@ module Enums
def self.purl_types
PURL_TYPES
end
+
+ def self.purl_types_numerical
+ purl_types.invert
+ end
end
end
diff --git a/app/models/user_preference.rb b/app/models/user_preference.rb
index ecc64da2098..2519db825c0 100644
--- a/app/models/user_preference.rb
+++ b/app/models/user_preference.rb
@@ -24,6 +24,8 @@ class UserPreference < ApplicationRecord
allow_blank: true
validates :use_legacy_web_ide, allow_nil: false, inclusion: { in: [true, false] }
+ validates :pass_user_identities_to_ci_jwt, allow_nil: false, inclusion: { in: [true, false] }
+
validates :pinned_nav_items, json_schema: { filename: 'pinned_nav_items' }
ignore_columns :experience_level, remove_with: '14.10', remove_after: '2021-03-22'
diff --git a/app/policies/group_policy.rb b/app/policies/group_policy.rb
index a285a8e361b..1f8e003b09a 100644
--- a/app/policies/group_policy.rb
+++ b/app/policies/group_policy.rb
@@ -191,6 +191,7 @@ class GroupPolicy < Namespaces::GroupProjectNamespaceSharedPolicy
enable :destroy_package
enable :admin_package
enable :create_projects
+ enable :import_projects
enable :admin_pipeline
enable :admin_build
enable :add_cluster
@@ -261,14 +262,20 @@ class GroupPolicy < Namespaces::GroupProjectNamespaceSharedPolicy
end.enable :change_share_with_group_lock
rule { developer & developer_maintainer_access }.enable :create_projects
- rule { create_projects_disabled }.prevent :create_projects
+ rule { create_projects_disabled }.policy do
+ prevent :create_projects
+ prevent :import_projects
+ end
rule { owner | admin }.policy do
enable :owner_access
enable :read_statistics
end
- rule { maintainer & can?(:create_projects) }.enable :transfer_projects
+ rule { maintainer & can?(:create_projects) }.policy do
+ enable :transfer_projects
+ enable :import_projects
+ end
rule { read_package_registry_deploy_token }.policy do
enable :read_package
diff --git a/app/services/bulk_imports/create_service.rb b/app/services/bulk_imports/create_service.rb
index aec32209b19..4c9c59ac504 100644
--- a/app/services/bulk_imports/create_service.rb
+++ b/app/services/bulk_imports/create_service.rb
@@ -2,7 +2,7 @@
# Entry point of the BulkImport/Direct Transfer feature.
# This service receives a Gitlab Instance connection params
-# and a list of groups to be imported.
+# and a list of groups or projects to be imported.
#
# Process topography:
#
@@ -15,16 +15,17 @@
# P1 (sync)
#
# - Create a BulkImport record
-# - Create a BulkImport::Entity for each group to be imported
-# - Enqueue a BulkImportWorker job (P2) to import the given groups (entities)
+# - Create a BulkImport::Entity for each group or project (entities) to be imported
+# - Enqueue a BulkImportWorker job (P2) to import the given entity
#
# Pn (async)
#
# - For each group to be imported (BulkImport::Entity.with_status(:created))
# - Import the group data
# - Create entities for each subgroup of the imported group
-# - Enqueue a BulkImports::CreateService job (Pn) to import the new entities (subgroups)
-#
+# - Create entities for each project of the imported group
+# - Enqueue a BulkImportWorker job (Pn) to import the new entities
+
module BulkImports
class CreateService
ENTITY_TYPES_MAPPING = {
@@ -84,7 +85,7 @@ module BulkImports
Array.wrap(params).each do |entity_params|
track_access_level(entity_params)
- validate_destination_namespace(entity_params[:destination_namespace])
+ validate_destination_namespace(entity_params)
validate_destination_slug(entity_params[:destination_slug] || entity_params[:destination_name])
validate_destination_full_path(entity_params)
@@ -137,10 +138,18 @@ module BulkImports
credentials[:url].starts_with?(Settings.gitlab.base_url)
end
- def validate_destination_namespace(destination_namespace)
- return if destination_namespace =~ Gitlab::Regex.bulk_import_destination_namespace_path_regex
+ def validate_destination_namespace(entity_params)
+ destination_namespace = entity_params[:destination_namespace]
+ source_type = entity_params[:source_type]
- raise BulkImports::Error.destination_namespace_validation_failure
+ return if destination_namespace.blank?
+
+ group = Group.find_by_full_path(destination_namespace)
+ if group.nil? ||
+ (source_type == 'group_entity' && !current_user.can?(:create_subgroup, group)) ||
+ (source_type == 'project_entity' && !current_user.can?(:import_projects, group))
+ raise BulkImports::Error.destination_namespace_validation_failure(destination_namespace)
+ end
end
def validate_destination_slug(destination_slug)
diff --git a/app/services/ci/runners/create_runner_service.rb b/app/services/ci/runners/create_runner_service.rb
index fcb664500a9..ff4a33e431b 100644
--- a/app/services/ci/runners/create_runner_service.rb
+++ b/app/services/ci/runners/create_runner_service.rb
@@ -29,7 +29,7 @@ module Ci
return ServiceResponse.success(payload: { runner: runner }) if runner.save
- ServiceResponse.error(message: runner.errors.full_messages)
+ ServiceResponse.error(message: runner.errors.full_messages, reason: :save_error)
end
def normalize_params
diff --git a/app/views/layouts/nav/sidebar/_admin.html.haml b/app/views/layouts/nav/sidebar/_admin.html.haml
index 24b301fadce..2d61e403623 100644
--- a/app/views/layouts/nav/sidebar/_admin.html.haml
+++ b/app/views/layouts/nav/sidebar/_admin.html.haml
@@ -270,6 +270,7 @@
= link_to ci_cd_admin_application_settings_path, title: _('CI/CD') do
%span
= _('CI/CD')
+ = render_if_exists 'layouts/nav/ee/admin/security_and_compliance_sidebar'
= nav_link(path: 'application_settings#reporting') do
= link_to reporting_admin_application_settings_path, title: _('Reporting') do
%span
diff --git a/app/views/projects/usage_quotas/index.html.haml b/app/views/projects/usage_quotas/index.html.haml
index bbe7eed6b14..5bfe6b650d1 100644
--- a/app/views/projects/usage_quotas/index.html.haml
+++ b/app/views/projects/usage_quotas/index.html.haml
@@ -1,4 +1,5 @@
- page_title s_("UsageQuota|Usage")
+- add_page_specific_style 'page_bundles/projects_usage_quotas'
= render_if_exists 'shared/ultimate_feature_removal_banner', project: @project
diff --git a/config/application.rb b/config/application.rb
index f041d435c7f..b1bc833979b 100644
--- a/config/application.rb
+++ b/config/application.rb
@@ -317,6 +317,7 @@ module Gitlab
config.assets.precompile << "page_bundles/profiles/preferences.css"
config.assets.precompile << "page_bundles/project.css"
config.assets.precompile << "page_bundles/projects_edit.css"
+ config.assets.precompile << "page_bundles/projects_usage_quotas.css"
config.assets.precompile << "page_bundles/prometheus.css"
config.assets.precompile << "page_bundles/promotions.css"
config.assets.precompile << "page_bundles/releases.css"
diff --git a/config/feature_flags/development/fix_dora_deployment_frequency_calculation.yml b/config/feature_flags/development/fix_dora_deployment_frequency_calculation.yml
new file mode 100644
index 00000000000..627c42695eb
--- /dev/null
+++ b/config/feature_flags/development/fix_dora_deployment_frequency_calculation.yml
@@ -0,0 +1,8 @@
+---
+name: fix_dora_deployment_frequency_calculation
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/116644
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/404565
+milestone: '15.11'
+type: development
+group: group::optimize
+default_enabled: false
diff --git a/db/migrate/20230403145705_add_purl_sync_to_settings.rb b/db/migrate/20230403145705_add_purl_sync_to_settings.rb
new file mode 100644
index 00000000000..3bc9ce07235
--- /dev/null
+++ b/db/migrate/20230403145705_add_purl_sync_to_settings.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+class AddPurlSyncToSettings < Gitlab::Database::Migration[2.1]
+ def change
+ add_column :application_settings, :package_metadata_purl_types, :smallint, array: true, default: []
+ end
+end
diff --git a/db/migrate/20230406134436_add_identity_toggle_to_user_preferences.rb b/db/migrate/20230406134436_add_identity_toggle_to_user_preferences.rb
new file mode 100644
index 00000000000..0b7fcceb3ee
--- /dev/null
+++ b/db/migrate/20230406134436_add_identity_toggle_to_user_preferences.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+class AddIdentityToggleToUserPreferences < Gitlab::Database::Migration[2.1]
+ enable_lock_retries!
+
+ def change
+ add_column :user_preferences, :pass_user_identities_to_ci_jwt, :boolean, default: false, null: false
+ end
+end
diff --git a/db/schema_migrations/20230403145705 b/db/schema_migrations/20230403145705
new file mode 100644
index 00000000000..80e6357e3e4
--- /dev/null
+++ b/db/schema_migrations/20230403145705
@@ -0,0 +1 @@
+856d50399914b6df0c07d328723197a57806c0883157cbfe67f0c578708a1bde \ No newline at end of file
diff --git a/db/schema_migrations/20230406134436 b/db/schema_migrations/20230406134436
new file mode 100644
index 00000000000..17d51bba6ce
--- /dev/null
+++ b/db/schema_migrations/20230406134436
@@ -0,0 +1 @@
+3b7a512959c9d109ee4b454693ebfafed624869c82fa64d92b3f780165e91feb \ No newline at end of file
diff --git a/db/structure.sql b/db/structure.sql
index b6e93ad1f95..d0bf9a5e91a 100644
--- a/db/structure.sql
+++ b/db/structure.sql
@@ -11749,6 +11749,7 @@ CREATE TABLE application_settings (
encrypted_openai_api_key_iv bytea,
database_max_running_batched_background_migrations integer DEFAULT 2 NOT NULL,
silent_mode_enabled boolean DEFAULT false NOT NULL,
+ package_metadata_purl_types smallint[] DEFAULT '{}'::smallint[],
CONSTRAINT app_settings_container_reg_cleanup_tags_max_list_size_positive CHECK ((container_registry_cleanup_tags_service_max_list_size >= 0)),
CONSTRAINT app_settings_container_registry_pre_import_tags_rate_positive CHECK ((container_registry_pre_import_tags_rate >= (0)::numeric)),
CONSTRAINT app_settings_dep_proxy_ttl_policies_worker_capacity_positive CHECK ((dependency_proxy_ttl_group_policy_worker_capacity >= 0)),
@@ -23373,6 +23374,7 @@ CREATE TABLE user_preferences (
use_new_navigation boolean,
achievements_enabled boolean DEFAULT true NOT NULL,
pinned_nav_items jsonb DEFAULT '{}'::jsonb NOT NULL,
+ pass_user_identities_to_ci_jwt boolean DEFAULT false NOT NULL,
CONSTRAINT check_89bf269f41 CHECK ((char_length(diffs_deletion_color) <= 7)),
CONSTRAINT check_d07ccd35f7 CHECK ((char_length(diffs_addition_color) <= 7))
);
diff --git a/doc/api/bulk_imports.md b/doc/api/bulk_imports.md
index 96e2912498b..f8d354a56ed 100644
--- a/doc/api/bulk_imports.md
+++ b/doc/api/bulk_imports.md
@@ -18,7 +18,8 @@ prerequisites for [migrating groups by direct transfer](../user/group/import/ind
## Start a new group migration
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/66353) in GitLab 14.2.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/66353) in GitLab 14.2.
+> - `project_entity` source type [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/390515) in GitLab 15.11.
```plaintext
POST /bulk_imports
@@ -30,7 +31,7 @@ POST /bulk_imports
| `configuration[url]` | String | yes | Source GitLab instance URL. |
| `configuration[access_token]` | String | yes | Access token to the source GitLab instance. |
| `entities` | Array | yes | List of entities to import. |
-| `entities[source_type]` | String | yes | Source entity type (only `group_entity` is supported). |
+| `entities[source_type]` | String | yes | Source entity type. Valid values are `group_entity` (GitLab 14.2 and later) and `project_entity` (GitLab 15.11 and later). |
| `entities[source_full_path]` | String | yes | Source full path of the entity to import. |
| `entities[destination_name]` | String | yes | Deprecated: Use :destination_slug instead. Destination slug for the entity. |
| `entities[destination_slug]` | String | yes | Destination slug for the entity. |
diff --git a/doc/api/runners.md b/doc/api/runners.md
index 1a722163c41..8d0be1c3aba 100644
--- a/doc/api/runners.md
+++ b/doc/api/runners.md
@@ -273,10 +273,10 @@ PUT /runners/:id
| `id` | integer | yes | The ID of a runner |
| `description` | string | no | The description of the runner |
| `active` | boolean | no | Deprecated: Use `paused` instead. Flag indicating whether the runner is allowed to receive jobs |
-| `paused` | boolean | no | Specifies whether the runner should ignore new jobs |
+| `paused` | boolean | no | Specifies if the runner should ignore new jobs |
| `tag_list` | array | no | The list of tags for the runner |
-| `run_untagged` | boolean | no | Specifies whether the runner can execute untagged jobs |
-| `locked` | boolean | no | Specifies whether the runner is locked |
+| `run_untagged` | boolean | no | Specifies if the runner can execute untagged jobs |
+| `locked` | boolean | no | Specifies if the runner is locked |
| `access_level` | string | no | The access level of the runner; `not_protected` or `ref_protected` |
| `maximum_timeout` | integer | no | Maximum timeout that limits the amount of time (in seconds) that runners can run jobs |
@@ -656,20 +656,20 @@ Register a new runner for the instance.
POST /runners
```
-| Attribute | Type | Required | Description |
-|--------------------|--------------|----------|---------------------------------------------------------------------------------------------------------------------------------------------------------------|
-| `token` | string | yes | [Registration token](#registration-and-authentication-tokens) |
-| `description` | string | no | Runner's description |
+| Attribute | Type | Required | Description |
+|--------------------|--------------|----------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| `token` | string | yes | [Registration token](#registration-and-authentication-tokens) |
+| `description` | string | no | Description of the runner |
| `info` | hash | no | Runner's metadata. You can include `name`, `version`, `revision`, `platform`, and `architecture`, but only `version`, `platform`, and `architecture` are displayed in the Admin Area of the UI |
-| `active` | boolean | no | Deprecated: Use `paused` instead. Specifies whether the runner is allowed to receive new jobs |
-| `paused` | boolean | no | Specifies whether the runner should ignore new jobs |
-| `locked` | boolean | no | Specifies whether the runner should be locked for the current project |
-| `run_untagged` | boolean | no | Specifies whether the runner should handle untagged jobs |
-| `tag_list` | string array | no | A list of runner tags |
-| `access_level` | string | no | The access level of the runner; `not_protected` or `ref_protected` |
-| `maximum_timeout` | integer | no | Maximum timeout that limits the amount of time (in seconds) that runners can run jobs |
-| `maintainer_note` | string | no | [Deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/350730), see `maintenance_note` |
-| `maintenance_note` | string | no | Free-form maintenance notes for the runner (1024 characters) |
+| `active` | boolean | no | Deprecated: Use `paused` instead. Specifies if the runner is allowed to receive new jobs |
+| `paused` | boolean | no | Specifies if the runner should ignore new jobs |
+| `locked` | boolean | no | Specifies if the runner should be locked for the current project |
+| `run_untagged` | boolean | no | Specifies if the runner should handle untagged jobs |
+| `tag_list` | string array | no | A list of runner tags |
+| `access_level` | string | no | The access level of the runner; `not_protected` or `ref_protected` |
+| `maximum_timeout` | integer | no | Maximum timeout that limits the amount of time (in seconds) that runners can run jobs |
+| `maintainer_note` | string | no | [Deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/350730), see `maintenance_note` |
+| `maintenance_note` | string | no | Free-form maintenance notes for the runner (1024 characters) |
```shell
curl --request POST "https://gitlab.example.com/api/v4/runners" \
diff --git a/doc/api/users.md b/doc/api/users.md
index dba1c30f7e8..bb261cea682 100644
--- a/doc/api/users.md
+++ b/doc/api/users.md
@@ -2196,3 +2196,42 @@ Returns:
- `400 Bad request` if two factor authentication is not enabled for the specified user.
- `403 Forbidden` if not authenticated as an administrator.
- `404 User Not Found` if user cannot be found.
+
+## Create a CI runner **(FREE SELF)**
+
+It creates a new runner, linked to the current user.
+
+Requires administrator access or ownership of the target namespace or project. Token values are returned once. Make sure you save it because you can't access
+it again.
+
+```plaintext
+POST /user/runners
+```
+
+| Attribute | Type | Required | Description |
+|--------------------|--------------|----------|-----------------------------------------------------------------------------------------------------------------------------------------|
+| `runner_type` | string | yes | Specifies the scope of the runner; `instance_type`, `group_type`, or `project_type`. |
+| `namespace_id` | integer | no | The ID of the project or group that the runner is created in. Required if `runner_type` is `group_type` or `project_type`. |
+| `description` | string | no | Description of the runner. |
+| `paused` | boolean | no | Specifies if the runner should ignore new jobs. |
+| `locked` | boolean | no | Specifies if the runner should be locked for the current project. |
+| `run_untagged` | boolean | no | Specifies if the runner should handle untagged jobs. |
+| `tag_list` | string array | no | A list of runner tags. |
+| `access_level` | string | no | The access level of the runner; `not_protected` or `ref_protected`. |
+| `maximum_timeout` | integer | no | Maximum timeout that limits the amount of time (in seconds) that runners can run jobs. |
+| `maintenance_note` | string | no | Free-form maintenance notes for the runner (1024 characters). |
+
+```shell
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" --data "runner_type=instance_type" \
+ "https://gitlab.example.com/api/v4/user/runners"
+```
+
+Example response:
+
+```json
+{
+ "id": 9171,
+ "token": "glrt-kyahzxLaj4Dc1jQf4xjX",
+ "token_expires_at": null
+}
+```
diff --git a/doc/user/admin_area/settings/index.md b/doc/user/admin_area/settings/index.md
index 152c35dd504..11c14102efb 100644
--- a/doc/user/admin_area/settings/index.md
+++ b/doc/user/admin_area/settings/index.md
@@ -66,6 +66,10 @@ The **CI/CD** settings contain:
[risks are involved](../../packages/container_registry/reduce_container_registry_storage.md#use-with-external-container-registries)
in enabling some of these settings.
+## Security and Compliance settings
+
+- [License compliance settings](security_and_compliance.md#choose-package-registry-metadata-to-sync): Enable or disable synchronization of package metadata by a registry type.
+
### Geo **(PREMIUM SELF)**
The **Geo** setting contains:
diff --git a/doc/user/admin_area/settings/security_and_compliance.md b/doc/user/admin_area/settings/security_and_compliance.md
new file mode 100644
index 00000000000..13abf1027cd
--- /dev/null
+++ b/doc/user/admin_area/settings/security_and_compliance.md
@@ -0,0 +1,20 @@
+---
+stage: Secure
+group: Composition Analysis
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
+type: howto
+---
+
+# Security and Compliance Admin Area settings **(ULTIMATE SELF)**
+
+The settings for package metadata synchronization are located in the [Admin Area](index.md).
+
+## Choose package registry metadata to sync
+
+To choose the packages you want to synchronize with the GitLab License Database for [License Compliance](../../compliance/license_scanning_of_cyclonedx_files/index.md):
+
+1. On the top bar, select **Main menu > Admin**.
+1. On the left sidebar, select **Settings > Security and Compliance**.
+1. Expand **License Compliance**.
+1. Select or clear checkboxes for the package registries that you want to sync.
+1. Select **Save changes**.
diff --git a/doc/user/compliance/license_scanning_of_cyclonedx_files/index.md b/doc/user/compliance/license_scanning_of_cyclonedx_files/index.md
index e81951d93d4..1ca10ed61db 100644
--- a/doc/user/compliance/license_scanning_of_cyclonedx_files/index.md
+++ b/doc/user/compliance/license_scanning_of_cyclonedx_files/index.md
@@ -22,6 +22,7 @@ Licenses not in the SPDX list are reported as "Unknown". License information can
Prerequisites:
+- Enable [Synchronization with the GitLab License Database](../../admin_area/settings/security_and_compliance.md#choose-package-registry-metadata-to-sync) in Admin Area for the GitLab instance.
- Enable [Dependency Scanning](../../application_security/dependency_scanning/index.md#configuration).
From the `.gitlab-ci.yml` file, remove the deprecated line `Jobs/License-Scanning.gitlab-ci.yml`, if
diff --git a/doc/user/group/import/index.md b/doc/user/group/import/index.md
index 8e8299594f0..2fba15d58b6 100644
--- a/doc/user/group/import/index.md
+++ b/doc/user/group/import/index.md
@@ -225,6 +225,7 @@ Group items that are migrated to the destination GitLab instance include:
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/267945) in GitLab 14.4 [with a flag](../../feature_flags.md) named `bulk_import_projects`. Disabled by default.
> - [Enabled on GitLab.com](https://gitlab.com/gitlab-org/gitlab/-/issues/339941) in GitLab 15.6.
> - `bulk_import_projects` feature flag [removed](https://gitlab.com/gitlab-org/gitlab/-/issues/339941) in GitLab 15.10.
+> - Project-only migrations using API [added](https://gitlab.com/gitlab-org/gitlab/-/issues/390515) in GitLab 15.11.
If you choose to migrate projects when you [select groups to migrate](#select-the-groups-and-projects-to-import),
project items are migrated with the projects.
@@ -246,6 +247,9 @@ specific project item is migrated:
Any other project items are **not** migrated.
+If you choose not to migrate projects along with groups or if you want to retry a project migration, you can
+initiate project-only migrations using the [API](../../../api/bulk_imports.md).
+
WARNING:
Migrating projects when migrating groups by direct transfer is in [Beta](../../../policy/alpha-beta-support.md#beta)
and is not ready for production use.
diff --git a/doc/user/ssh.md b/doc/user/ssh.md
index 3ab61fa77a9..a74c3fea360 100644
--- a/doc/user/ssh.md
+++ b/doc/user/ssh.md
@@ -20,8 +20,6 @@ SSH uses two keys, a public key and a private key.
- The public key can be distributed.
- The private key should be protected.
-When you need to copy or upload your SSH public key, make sure you do not accidentally copy or upload your private key instead.
-
You cannot expose data by uploading your public key. When you need to copy or upload your SSH public key, make sure you do not accidentally copy or upload your private key instead.
You can use your private key to [sign commits](project/repository/ssh_signed_commits/index.md),
diff --git a/lib/api/bulk_imports.rb b/lib/api/bulk_imports.rb
index e3dc9ea52cb..b4ace6cd6bc 100644
--- a/lib/api/bulk_imports.rb
+++ b/lib/api/bulk_imports.rb
@@ -59,8 +59,8 @@ module API
requires :entities, type: Array, desc: 'List of entities to import' do
requires :source_type,
type: String,
- desc: 'Source entity type (only `group_entity` is supported)',
- values: %w[group_entity]
+ desc: 'Source entity type',
+ values: %w[group_entity project_entity]
requires :source_full_path,
type: String,
desc: 'Relative path of the source entity to import',
diff --git a/lib/api/ci/runner.rb b/lib/api/ci/runner.rb
index 1ecd498c6a8..d61171ea9f4 100644
--- a/lib/api/ci/runner.rb
+++ b/lib/api/ci/runner.rb
@@ -15,7 +15,7 @@ module API
end
params do
requires :token, type: String, desc: 'Registration token'
- optional :description, type: String, desc: %q(Runner's description)
+ optional :description, type: String, desc: %q(Description of the runner)
optional :maintainer_note, type: String, desc: %q(Deprecated: see `maintenance_note`)
optional :maintenance_note, type: String,
desc: %q(Free-form maintenance notes for the runner (1024 characters))
@@ -27,13 +27,13 @@ module API
optional :architecture, type: String, desc: %q(Runner's architecture)
end
optional :active, type: Boolean,
- desc: 'Deprecated: Use `paused` instead. Specifies whether the runner is allowed ' \
+ desc: 'Deprecated: Use `paused` instead. Specifies if the runner is allowed ' \
'to receive new jobs'
- optional :paused, type: Boolean, desc: 'Specifies whether the runner should ignore new jobs'
- optional :locked, type: Boolean, desc: 'Specifies whether the runner should be locked for the current project'
+ optional :paused, type: Boolean, desc: 'Specifies if the runner should ignore new jobs'
+ optional :locked, type: Boolean, desc: 'Specifies if the runner should be locked for the current project'
optional :access_level, type: String, values: ::Ci::Runner.access_levels.keys,
desc: 'The access level of the runner'
- optional :run_untagged, type: Boolean, desc: 'Specifies whether the runner should handle untagged jobs'
+ optional :run_untagged, type: Boolean, desc: 'Specifies if the runner should handle untagged jobs'
optional :tag_list, type: Array[String], coerce_with: ::API::Validations::Types::CommaSeparatedToArray.coerce,
desc: %q(A list of runner tags)
optional :maximum_timeout, type: Integer,
diff --git a/lib/api/ci/runners.rb b/lib/api/ci/runners.rb
index f2f0f32261a..42817c782f4 100644
--- a/lib/api/ci/runners.rb
+++ b/lib/api/ci/runners.rb
@@ -158,11 +158,11 @@ module API
requires :id, type: Integer, desc: 'The ID of a runner'
optional :description, type: String, desc: 'The description of the runner'
optional :active, type: Boolean, desc: 'Deprecated: Use `paused` instead. Flag indicating whether the runner is allowed to receive jobs'
- optional :paused, type: Boolean, desc: 'Specifies whether the runner should ignore new jobs'
+ optional :paused, type: Boolean, desc: 'Specifies if the runner should ignore new jobs'
optional :tag_list, type: Array[String], coerce_with: ::API::Validations::Types::CommaSeparatedToArray.coerce,
desc: 'The list of tags for a runner', documentation: { example: "['macos', 'shell']" }
- optional :run_untagged, type: Boolean, desc: 'Specifies whether the runner can execute untagged jobs'
- optional :locked, type: Boolean, desc: 'Specifies whether the runner is locked'
+ optional :run_untagged, type: Boolean, desc: 'Specifies if the runner can execute untagged jobs'
+ optional :locked, type: Boolean, desc: 'Specifies if the runner is locked'
optional :access_level, type: String, values: ::Ci::Runner.access_levels.keys,
desc: 'The access level of the runner'
optional :maximum_timeout, type: Integer,
diff --git a/lib/api/users.rb b/lib/api/users.rb
index 0c118767bc4..8d34be362f4 100644
--- a/lib/api/users.rb
+++ b/lib/api/users.rb
@@ -1365,6 +1365,61 @@ module API
get 'status', feature_category: :user_profile do
present current_user.status || {}, with: Entities::UserStatus
end
+
+ desc 'Create a runner owned by currently authenticated user' do
+ detail 'Create a new runner'
+ success Entities::Ci::RunnerRegistrationDetails
+ failure [[400, 'Bad Request'], [403, 'Forbidden']]
+ tags %w[user runners]
+ end
+ params do
+ requires :runner_type, type: String, values: ::Ci::Runner.runner_types.keys,
+ desc: %q(Specifies the scope of the runner)
+ given runner_type: ->(runner_type) { %i[group_type project_type].include? runner_type } do
+ requires :namespace_id, type: Integer,
+ desc: 'The ID of the project or group that the runner is created in',
+ documentation: { example: 1 }
+ end
+ optional :description, type: String, desc: %q(Description of the runner)
+ optional :maintenance_note, type: String,
+ desc: %q(Free-form maintenance notes for the runner (1024 characters))
+ optional :paused, type: Boolean, desc: 'Specifies if the runner should ignore new jobs (defaults to false)'
+ optional :locked, type: Boolean,
+ desc: 'Specifies if the runner should be locked for the current project (defaults to false)'
+ optional :access_level, type: String, values: ::Ci::Runner.access_levels.keys,
+ desc: 'The access level of the runner'
+ optional :run_untagged, type: Boolean,
+ desc: 'Specifies if the runner should handle untagged jobs (defaults to true)'
+ optional :tag_list, type: Array[String], coerce_with: ::API::Validations::Types::CommaSeparatedToArray.coerce,
+ desc: %q(A list of runner tags)
+ optional :maximum_timeout, type: Integer,
+ desc: 'Maximum timeout that limits the amount of time (in seconds) that runners can run jobs'
+ end
+ post 'runners', urgency: :low, feature_category: :runner_fleet do
+ attributes = attributes_for_keys(
+ %i[runner_type namespace_id description maintenance_note paused locked run_untagged tag_list
+ access_level maximum_timeout]
+ )
+
+ namespace_id = attributes.delete(:namespace_id)
+ if namespace_id
+ case attributes[:runner_type]
+ when 'group_type'
+ attributes[:scope] = ::Group.find(namespace_id)
+ when 'project_type'
+ attributes[:scope] = ::Project.find(namespace_id)
+ end
+ end
+
+ result = ::Ci::Runners::CreateRunnerService.new(user: current_user, params: attributes).execute
+ if result.error?
+ message = result.errors.to_sentence
+ forbidden!(message) if result.reason == :forbidden
+ bad_request!(message)
+ end
+
+ present result.payload[:runner], with: Entities::Ci::RunnerRegistrationDetails
+ end
end
end
end
diff --git a/lib/bulk_imports/error.rb b/lib/bulk_imports/error.rb
index 616b58d1852..c40b4bc7f34 100644
--- a/lib/bulk_imports/error.rb
+++ b/lib/bulk_imports/error.rb
@@ -15,9 +15,8 @@ module BulkImports
self.new("Invalid source URL. Enter only the base URL of the source GitLab instance.")
end
- def self.destination_namespace_validation_failure
- self.new("Import failed. Destination group or subgroup path " \
- "#{Gitlab::Regex.bulk_import_destination_namespace_path_regex_message}")
+ def self.destination_namespace_validation_failure(destination_namespace)
+ self.new("Import failed. Destination '#{destination_namespace}' is invalid, or you don't have permission.")
end
def self.destination_slug_validation_failure
diff --git a/lib/bulk_imports/projects/transformers/project_attributes_transformer.rb b/lib/bulk_imports/projects/transformers/project_attributes_transformer.rb
index 72b32ad5b3b..1e025e91038 100644
--- a/lib/bulk_imports/projects/transformers/project_attributes_transformer.rb
+++ b/lib/bulk_imports/projects/transformers/project_attributes_transformer.rb
@@ -21,7 +21,7 @@ module BulkImports
project[:created_at] = data['created_at']
project[:import_type] = PROJECT_IMPORT_TYPE
project[:visibility_level] = visibility_level(entity, namespace, data['visibility'])
- project[:namespace_id] = namespace.id if namespace
+ project[:namespace_id] = namespace.id
project.with_indifferent_access
end
diff --git a/lib/gitlab/import_export/base/relation_factory.rb b/lib/gitlab/import_export/base/relation_factory.rb
index e3813070aa4..3d96e891797 100644
--- a/lib/gitlab/import_export/base/relation_factory.rb
+++ b/lib/gitlab/import_export/base/relation_factory.rb
@@ -295,6 +295,13 @@ module Gitlab
end
def unique_relation?
+ # this guard is necessary because
+ # when multiple approval_project_rules_protected_branch referenced the same protected branch
+ # or approval_project_rules_user referenced the same user
+ # the different instances were squashed into one
+ # because this method returned true for reason that needs investigation
+ return if @relation_sym == :approval_rules
+
strong_memoize(:unique_relation) do
importable_foreign_key.present? &&
(has_unique_index_on_importable_fk? || uses_importable_fk_as_primary_key?)
diff --git a/lib/gitlab/import_export/project/import_export.yml b/lib/gitlab/import_export/project/import_export.yml
index 335096faed6..56cbc5f1bb4 100644
--- a/lib/gitlab/import_export/project/import_export.yml
+++ b/lib/gitlab/import_export/project/import_export.yml
@@ -1195,6 +1195,9 @@ ee:
- :milestone
- lists:
- :milestone
+ - approval_rules:
+ - :approval_project_rules_protected_branches
+ - :approval_project_rules_users
included_attributes:
issuable_sla:
@@ -1260,9 +1263,30 @@ ee:
- :description
iterations_cadence:
- :title
+ approval_rules:
+ - :approvals_required
+ - :name
+ - :rule_type
+ - :scanners
+ - :vulnerabilities_allowed
+ - :severity_levels
+ - :report_type
+ - :vulnerability_states
+ - :orchestration_policy_idx
+ - :applies_to_all_protected_branches
+ approval_project_rules_protected_branches:
+ - :protected_branch
+ approval_project_rules_users:
+ - :user_id
excluded_attributes:
project:
- :vulnerability_hooks_integrations
+ approval_rules:
+ - :created_at
+ - :updated_at
+ methods:
+ approval_project_rules_protected_branches:
+ - :branch_name
preloads:
issues:
epic:
diff --git a/lib/gitlab/import_export/project/relation_factory.rb b/lib/gitlab/import_export/project/relation_factory.rb
index ab95e306abf..9afa7cc1dae 100644
--- a/lib/gitlab/import_export/project/relation_factory.rb
+++ b/lib/gitlab/import_export/project/relation_factory.rb
@@ -92,6 +92,7 @@ module Gitlab
when :'Ci::PipelineSchedule' then setup_pipeline_schedule
when :'ProtectedBranch::MergeAccessLevel' then setup_protected_branch_access_level
when :'ProtectedBranch::PushAccessLevel' then setup_protected_branch_access_level
+ when :ApprovalProjectRulesProtectedBranch then setup_merge_approval_protected_branch
when :releases then setup_release
end
@@ -195,6 +196,13 @@ module Gitlab
root_ancestor.max_member_access_for_user(@user) == Gitlab::Access::OWNER
end
+ def setup_merge_approval_protected_branch
+ source_branch_name = @relation_hash.delete('branch_name')
+ target_branch = @importable.protected_branches.find_by(name: source_branch_name)
+
+ @relation_hash['protected_branch'] = target_branch
+ end
+
def compute_relative_position
return unless max_relative_position
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 689a1464a62..331a90588a9 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -3111,6 +3111,9 @@ msgstr ""
msgid "AdminSettings|Only enable search after installing the plugin, enabling indexing, and recreating the index."
msgstr ""
+msgid "AdminSettings|Package registry metadata to sync"
+msgstr ""
+
msgid "AdminSettings|Pause Elasticsearch indexing"
msgstr ""
@@ -30869,6 +30872,9 @@ msgstr ""
msgid "Package registry rate limits"
msgstr ""
+msgid "Package registry types for which metadata is stored, required for License Compliance for CycloneDX files"
+msgstr ""
+
msgid "Package type"
msgstr ""
@@ -40894,6 +40900,9 @@ msgstr[1] ""
msgid "Settings"
msgstr ""
+msgid "Settings for the License Compliance feature"
+msgstr ""
+
msgid "Settings|Unable to load the merge request options settings. Try reloading the page."
msgstr ""
diff --git a/package.json b/package.json
index 047ab50598b..7d2b3c5af39 100644
--- a/package.json
+++ b/package.json
@@ -56,7 +56,7 @@
"@gitlab/favicon-overlay": "2.0.0",
"@gitlab/fonts": "^1.2.0",
"@gitlab/svgs": "3.38.0",
- "@gitlab/ui": "60.0.0",
+ "@gitlab/ui": "60.1.0",
"@gitlab/visual-review-tools": "1.7.3",
"@gitlab/web-ide": "0.0.1-dev-20230407181558",
"@mattiasbuelens/web-streams-adapter": "^0.1.0",
diff --git a/spec/features/projects/pipeline_schedules_spec.rb b/spec/features/projects/pipeline_schedules_spec.rb
index f7e2adb7829..81e003d7d1c 100644
--- a/spec/features/projects/pipeline_schedules_spec.rb
+++ b/spec/features/projects/pipeline_schedules_spec.rb
@@ -431,5 +431,6 @@ RSpec.describe 'Pipeline Schedules', :js, feature_category: :projects do
select_timezone
select_target_branch
+ find('body').click # close dropdown
end
end
diff --git a/spec/fixtures/lib/gitlab/import_export/complex/project.json b/spec/fixtures/lib/gitlab/import_export/complex/project.json
index f57f0f3c08c..cdf9395fbe6 100644
--- a/spec/fixtures/lib/gitlab/import_export/complex/project.json
+++ b/spec/fixtures/lib/gitlab/import_export/complex/project.json
@@ -8039,7 +8039,7 @@
"protected_environment_id": 1,
"created_at": "2017-10-19T15:36:23.466Z",
"updated_at": "2017-10-19T15:36:23.466Z",
- "access_level": null,
+ "access_level": 40,
"user_id": 1,
"group_id": null
}
@@ -8309,5 +8309,38 @@
"reject_unsigned_commits": true,
"commit_committer_check": true,
"regexp_uses_re2": true
- }
+ },
+ "approval_rules": [
+ {
+ "approvals_required": 1,
+ "name": "MustContain",
+ "rule_type": "regular",
+ "scanners": [
+
+ ],
+ "vulnerabilities_allowed": 0,
+ "severity_levels": [
+ "unknown",
+ "high",
+ "critical"
+ ],
+ "report_type": null,
+ "vulnerability_states": [
+ "newly_detected"
+ ],
+ "orchestration_policy_idx": null,
+ "applies_to_all_protected_branches": false,
+ "approval_project_rules_protected_branches": [
+ {
+ "protected_branch_id": 1,
+ "branch_name": "master"
+ }
+ ],
+ "approval_project_rules_users": [
+ {
+ "user_id": 35
+ }
+ ]
+ }
+ ]
}
diff --git a/spec/frontend/alerts_settings/components/__snapshots__/alerts_form_spec.js.snap b/spec/frontend/alerts_settings/components/__snapshots__/alerts_form_spec.js.snap
index 4a60d605cae..202a0a04192 100644
--- a/spec/frontend/alerts_settings/components/__snapshots__/alerts_form_spec.js.snap
+++ b/spec/frontend/alerts_settings/components/__snapshots__/alerts_form_spec.js.snap
@@ -61,6 +61,7 @@ exports[`Alert integration settings form default state should match the default
items="[object Object]"
noresultstext="No results found"
placement="left"
+ popperoptions="[object Object]"
resetbuttonlabel=""
searchplaceholder="Search"
selected="selecte_tmpl"
diff --git a/spec/lib/bulk_imports/groups/transformers/group_attributes_transformer_spec.rb b/spec/lib/bulk_imports/groups/transformers/group_attributes_transformer_spec.rb
index ab0d57f574b..9782f2aac27 100644
--- a/spec/lib/bulk_imports/groups/transformers/group_attributes_transformer_spec.rb
+++ b/spec/lib/bulk_imports/groups/transformers/group_attributes_transformer_spec.rb
@@ -181,6 +181,49 @@ RSpec.describe BulkImports::Groups::Transformers::GroupAttributesTransformer, fe
subject(:transformed_data) { described_class.new.transform(context, data) }
include_examples 'visibility level settings'
+
+ context 'when destination is blank' do
+ let(:destination_namespace) { '' }
+
+ context 'when visibility level is public' do
+ let(:data) { { 'visibility' => 'public' } }
+
+ it 'sets visibility level to public' do
+ expect(transformed_data[:visibility_level]).to eq(Gitlab::VisibilityLevel::PUBLIC)
+ end
+ end
+
+ context 'when when visibility level is internal' do
+ let(:data) { { 'visibility' => 'internal' } }
+
+ it 'sets visibility level to internal' do
+ expect(transformed_data[:visibility_level]).to eq(Gitlab::VisibilityLevel::INTERNAL)
+ end
+ end
+
+ context 'when private' do
+ let(:data) { { 'visibility' => 'private' } }
+
+ it 'sets visibility level to private' do
+ expect(transformed_data[:visibility_level]).to eq(Gitlab::VisibilityLevel::PRIVATE)
+ end
+ end
+
+ context 'when visibility level is restricted' do
+ let(:data) { { 'visibility' => 'internal' } }
+
+ it 'sets visibility level to private' do
+ stub_application_setting(
+ restricted_visibility_levels: [
+ Gitlab::VisibilityLevel::INTERNAL,
+ Gitlab::VisibilityLevel::PUBLIC
+ ]
+ )
+
+ expect(transformed_data[:visibility_level]).to eq(Gitlab::VisibilityLevel::PRIVATE)
+ end
+ end
+ end
end
end
end
diff --git a/spec/lib/bulk_imports/projects/transformers/project_attributes_transformer_spec.rb b/spec/lib/bulk_imports/projects/transformers/project_attributes_transformer_spec.rb
index 40ad4ee8be5..0e3d8b36fb2 100644
--- a/spec/lib/bulk_imports/projects/transformers/project_attributes_transformer_spec.rb
+++ b/spec/lib/bulk_imports/projects/transformers/project_attributes_transformer_spec.rb
@@ -46,27 +46,8 @@ RSpec.describe BulkImports::Projects::Transformers::ProjectAttributesTransformer
end
describe 'namespace_id' do
- context 'when destination namespace is present' do
- it 'adds namespace_id' do
- expect(transformed_data[:namespace_id]).to eq(destination_group.id)
- end
- end
-
- context 'when destination namespace is blank' do
- it 'does not add namespace_id key' do
- entity = create(
- :bulk_import_entity,
- source_type: :project_entity,
- bulk_import: bulk_import,
- source_full_path: 'source/full/path',
- destination_slug: 'Destination-Project-Name',
- destination_namespace: ''
- )
-
- context = double(entity: entity)
-
- expect(described_class.new.transform(context, data)).not_to have_key(:namespace_id)
- end
+ it 'adds namespace_id' do
+ expect(transformed_data[:namespace_id]).to eq(destination_group.id)
end
end
diff --git a/spec/lib/gitlab/import_export/all_models.yml b/spec/lib/gitlab/import_export/all_models.yml
index 1883a6499cd..74ac0639eb6 100644
--- a/spec/lib/gitlab/import_export/all_models.yml
+++ b/spec/lib/gitlab/import_export/all_models.yml
@@ -1009,3 +1009,20 @@ iterations_cadence:
- iterations
catalog_resource:
- project
+approval_rules:
+ - users
+ - groups
+ - group_users
+ - security_orchestration_policy_configuration
+ - protected_branches
+ - approval_merge_request_rule_sources
+ - approval_merge_request_rules
+ - approval_project_rules_users
+ - approval_project_rules_protected_branches
+ - scan_result_policy_read
+approval_project_rules_users:
+ - user
+ - approval_project_rule
+approval_project_rules_protected_branches:
+ - protected_branch
+ - approval_project_rule
diff --git a/spec/lib/gitlab/import_export/safe_model_attributes.yml b/spec/lib/gitlab/import_export/safe_model_attributes.yml
index 2384baabb6b..854909fd592 100644
--- a/spec/lib/gitlab/import_export/safe_model_attributes.yml
+++ b/spec/lib/gitlab/import_export/safe_model_attributes.yml
@@ -1060,3 +1060,21 @@ ResourceIterationEvent:
- action
Iterations::Cadence:
- title
+ApprovalProjectRule:
+ - approvals_required
+ - name
+ - rule_type
+ - scanners
+ - vulnerabilities_allowed
+ - severity_levels
+ - report_type
+ - vulnerability_states
+ - orchestration_policy_idx
+ - applies_to_all_protected_branches
+ApprovalProjectRulesUser:
+ - user_id
+ - approval_project_rule_id
+ApprovalProjectRulesProtectedBranch:
+ - protected_branch_id
+ - approval_project_rule_id
+ - branch_name
diff --git a/spec/models/user_preference_spec.rb b/spec/models/user_preference_spec.rb
index a6f64c90657..5c368b1632b 100644
--- a/spec/models/user_preference_spec.rb
+++ b/spec/models/user_preference_spec.rb
@@ -54,6 +54,13 @@ RSpec.describe UserPreference do
it { is_expected.not_to allow_value(nil).for(:use_legacy_web_ide) }
it { is_expected.not_to allow_value("").for(:use_legacy_web_ide) }
end
+
+ describe 'pass_user_identities_to_ci_jwt' do
+ it { is_expected.to allow_value(true).for(:pass_user_identities_to_ci_jwt) }
+ it { is_expected.to allow_value(false).for(:pass_user_identities_to_ci_jwt) }
+ it { is_expected.not_to allow_value(nil).for(:pass_user_identities_to_ci_jwt) }
+ it { is_expected.not_to allow_value("").for(:pass_user_identities_to_ci_jwt) }
+ end
end
describe 'notes filters global keys' do
diff --git a/spec/policies/group_policy_spec.rb b/spec/policies/group_policy_spec.rb
index bd1e90b839c..935b9124534 100644
--- a/spec/policies/group_policy_spec.rb
+++ b/spec/policies/group_policy_spec.rb
@@ -670,6 +670,124 @@ RSpec.describe GroupPolicy, feature_category: :system_access do
end
end
+ context 'import_projects' do
+ before do
+ group.update!(project_creation_level: project_creation_level)
+ end
+
+ context 'when group has no project creation level set' do
+ let(:project_creation_level) { nil }
+
+ context 'reporter' do
+ let(:current_user) { reporter }
+
+ it { is_expected.to be_disallowed(:import_projects) }
+ end
+
+ context 'developer' do
+ let(:current_user) { developer }
+
+ it { is_expected.to be_disallowed(:import_projects) }
+ end
+
+ context 'maintainer' do
+ let(:current_user) { maintainer }
+
+ it { is_expected.to be_allowed(:import_projects) }
+ end
+
+ context 'owner' do
+ let(:current_user) { owner }
+
+ it { is_expected.to be_allowed(:import_projects) }
+ end
+ end
+
+ context 'when group has project creation level set to no one' do
+ let(:project_creation_level) { ::Gitlab::Access::NO_ONE_PROJECT_ACCESS }
+
+ context 'reporter' do
+ let(:current_user) { reporter }
+
+ it { is_expected.to be_disallowed(:import_projects) }
+ end
+
+ context 'developer' do
+ let(:current_user) { developer }
+
+ it { is_expected.to be_disallowed(:import_projects) }
+ end
+
+ context 'maintainer' do
+ let(:current_user) { maintainer }
+
+ it { is_expected.to be_disallowed(:import_projects) }
+ end
+
+ context 'owner' do
+ let(:current_user) { owner }
+
+ it { is_expected.to be_disallowed(:import_projects) }
+ end
+ end
+
+ context 'when group has project creation level set to maintainer only' do
+ let(:project_creation_level) { ::Gitlab::Access::MAINTAINER_PROJECT_ACCESS }
+
+ context 'reporter' do
+ let(:current_user) { reporter }
+
+ it { is_expected.to be_disallowed(:import_projects) }
+ end
+
+ context 'developer' do
+ let(:current_user) { developer }
+
+ it { is_expected.to be_disallowed(:import_projects) }
+ end
+
+ context 'maintainer' do
+ let(:current_user) { maintainer }
+
+ it { is_expected.to be_allowed(:import_projects) }
+ end
+
+ context 'owner' do
+ let(:current_user) { owner }
+
+ it { is_expected.to be_allowed(:import_projects) }
+ end
+ end
+
+ context 'when group has project creation level set to developers + maintainer' do
+ let(:project_creation_level) { ::Gitlab::Access::DEVELOPER_MAINTAINER_PROJECT_ACCESS }
+
+ context 'reporter' do
+ let(:current_user) { reporter }
+
+ it { is_expected.to be_disallowed(:import_projects) }
+ end
+
+ context 'developer' do
+ let(:current_user) { developer }
+
+ it { is_expected.to be_disallowed(:import_projects) }
+ end
+
+ context 'maintainer' do
+ let(:current_user) { maintainer }
+
+ it { is_expected.to be_allowed(:import_projects) }
+ end
+
+ context 'owner' do
+ let(:current_user) { owner }
+
+ it { is_expected.to be_allowed(:import_projects) }
+ end
+ end
+ end
+
context 'create_subgroup' do
context 'when group has subgroup creation level set to owner' do
before do
diff --git a/spec/requests/api/bulk_imports_spec.rb b/spec/requests/api/bulk_imports_spec.rb
index ff76b9369af..b159d4ad445 100644
--- a/spec/requests/api/bulk_imports_spec.rb
+++ b/spec/requests/api/bulk_imports_spec.rb
@@ -75,6 +75,8 @@ RSpec.describe API::BulkImports, feature_category: :importers do
end
describe 'POST /bulk_imports' do
+ let_it_be(:destination_namespace) { create(:group) }
+
let(:request) { post api('/bulk_imports', user), params: params }
let(:destination_param) { { destination_slug: 'destination_slug' } }
let(:params) do
@@ -87,7 +89,7 @@ RSpec.describe API::BulkImports, feature_category: :importers do
{
source_type: 'group_entity',
source_full_path: 'full_path',
- destination_namespace: 'destination_namespace'
+ destination_namespace: destination_namespace.path
}.merge(destination_param)
]
}
@@ -108,6 +110,8 @@ RSpec.describe API::BulkImports, feature_category: :importers do
end
stub_request(:get, "http://gitlab.example/api/v4/#{source_entity_type}/#{source_entity_identifier}/export_relations/status?page=1&per_page=30&private_token=access_token")
.to_return(status: 200, body: "", headers: {})
+
+ destination_namespace.add_owner(user)
end
shared_examples 'starting a new migration' do
@@ -197,7 +201,7 @@ RSpec.describe API::BulkImports, feature_category: :importers do
{
source_type: 'group_entity',
source_full_path: 'full_path',
- destination_namespace: 'destination_namespace'
+ destination_namespace: destination_namespace.path
}
]
}
@@ -223,17 +227,13 @@ RSpec.describe API::BulkImports, feature_category: :importers do
end
end
- context 'when the destination_namespace is invalid' do
+ context 'when the destination_namespace does not exist' do
it 'returns invalid error' do
- params[:entities][0][:destination_namespace] = "?not a destination-namespace"
+ params[:entities][0][:destination_namespace] = "invalid-destination-namespace"
request
- expect(response).to have_gitlab_http_status(:bad_request)
- expect(json_response['error']).to eq("entities[0][destination_namespace] must have a relative " \
- "path structure with no HTTP protocol characters, or leading or " \
- "trailing forward slashes. Path segments must not start or " \
- "end with a special character, and must not contain " \
- "consecutive special characters.")
+ expect(response).to have_gitlab_http_status(:unprocessable_entity)
+ expect(json_response['message']).to eq("Import failed. Destination 'invalid-destination-namespace' is invalid, or you don't have permission.")
end
end
diff --git a/spec/requests/api/users_spec.rb b/spec/requests/api/users_spec.rb
index 6ff5cd7e100..522452656bc 100644
--- a/spec/requests/api/users_spec.rb
+++ b/spec/requests/api/users_spec.rb
@@ -4632,4 +4632,158 @@ RSpec.describe API::Users, :aggregate_failures, feature_category: :user_profile
let(:attributable) { user }
let(:other_attributable) { admin }
end
+
+ describe 'POST /user/runners', feature_category: :runner_fleet do
+ subject(:request) { post api('/user/runners', current_user, **post_args), params: runner_attrs }
+
+ let_it_be(:group_owner) { create(:user) }
+ let_it_be(:group) { create(:group) }
+ let_it_be(:project) { create(:project, namespace: group) }
+
+ let(:post_args) { { admin_mode: true } }
+ let(:runner_attrs) { { runner_type: 'instance_type' } }
+
+ before do
+ group.add_owner(group_owner)
+ end
+
+ shared_context 'returns forbidden when user does not have sufficient permissions' do
+ let(:current_user) { admin }
+ let(:post_args) { { admin_mode: false } }
+
+ it 'does not create a runner' do
+ expect do
+ request
+
+ expect(response).to have_gitlab_http_status(:forbidden)
+ end.not_to change { Ci::Runner.count }
+ end
+ end
+
+ shared_examples 'creates a runner' do
+ it 'creates a runner' do
+ expect do
+ request
+
+ expect(response).to have_gitlab_http_status(:created)
+ end.to change { Ci::Runner.count }.by(1)
+ end
+ end
+
+ shared_examples 'fails to create runner with :bad_request' do
+ it 'does not create runner' do
+ expect do
+ request
+
+ expect(response).to have_gitlab_http_status(:bad_request)
+ expect(json_response['message']).to include(expected_error)
+ end.not_to change { Ci::Runner.count }
+ end
+ end
+
+ context 'when runner_type is :instance_type' do
+ let(:runner_attrs) { { runner_type: 'instance_type' } }
+
+ context 'when user has sufficient permissions' do
+ let(:current_user) { admin }
+
+ it_behaves_like 'creates a runner'
+ end
+
+ it_behaves_like 'returns forbidden when user does not have sufficient permissions'
+
+ context 'when model validation fails' do
+ let(:runner_attrs) { { runner_type: 'instance_type', run_untagged: false, tag_list: [] } }
+ let(:current_user) { admin }
+
+ it_behaves_like 'fails to create runner with :bad_request' do
+ let(:expected_error) { 'Tags list can not be empty' }
+ end
+ end
+ end
+
+ context 'when runner_type is :group_type' do
+ let(:post_args) { {} }
+
+ context 'when namespace_id is specified' do
+ let(:runner_attrs) { { runner_type: 'group_type', namespace_id: group.id } }
+
+ context 'when user has sufficient permissions' do
+ let(:current_user) { group_owner }
+
+ it_behaves_like 'creates a runner'
+ end
+
+ it_behaves_like 'returns forbidden when user does not have sufficient permissions'
+ end
+
+ context 'when namespace_id is not specified' do
+ let(:runner_attrs) { { runner_type: 'group_type' } }
+ let(:current_user) { group_owner }
+
+ it_behaves_like 'fails to create runner with :bad_request' do
+ let(:expected_error) { 'Missing/invalid scope' }
+ end
+ end
+ end
+
+ context 'when runner_type is :project_type' do
+ let(:post_args) { {} }
+
+ context 'when namespace_id is specified' do
+ let(:runner_attrs) { { runner_type: 'project_type', namespace_id: project.id } }
+
+ context 'when user has sufficient permissions' do
+ let(:current_user) { group_owner }
+
+ it_behaves_like 'creates a runner'
+ end
+
+ it_behaves_like 'returns forbidden when user does not have sufficient permissions'
+ end
+
+ context 'when namespace_id is not specified' do
+ let(:runner_attrs) { { runner_type: 'project_type' } }
+ let(:current_user) { group_owner }
+
+ it_behaves_like 'fails to create runner with :bad_request' do
+ let(:expected_error) { 'Missing/invalid scope' }
+ end
+ end
+ end
+
+ context 'with missing runner_type' do
+ let(:runner_attrs) { {} }
+ let(:current_user) { admin }
+
+ it 'fails to create runner with :bad_request' do
+ expect do
+ request
+
+ expect(response).to have_gitlab_http_status(:bad_request)
+ expect(json_response['error']).to eq('runner_type is missing, runner_type does not have a valid value')
+ end.not_to change { Ci::Runner.count }
+ end
+ end
+
+ context 'with unknown runner_type' do
+ let(:runner_attrs) { { runner_type: 'unknown' } }
+ let(:current_user) { admin }
+
+ it 'fails to create runner with :bad_request' do
+ expect do
+ request
+
+ expect(response).to have_gitlab_http_status(:bad_request)
+ expect(json_response['error']).to eq('runner_type does not have a valid value')
+ end.not_to change { Ci::Runner.count }
+ end
+ end
+
+ it 'returns a 401 error if unauthorized' do
+ post api('/user/runners'), params: runner_attrs
+
+ expect(response).to have_gitlab_http_status(:unauthorized)
+ end
+ end
end
diff --git a/spec/services/bulk_imports/create_service_spec.rb b/spec/services/bulk_imports/create_service_spec.rb
index c68030a89a8..ff4afd6abd0 100644
--- a/spec/services/bulk_imports/create_service_spec.rb
+++ b/spec/services/bulk_imports/create_service_spec.rb
@@ -135,10 +135,11 @@ RSpec.describe BulkImports::CreateService, feature_category: :importers do
body: { 'scopes' => ['api'] }.to_json,
headers: { 'Content-Type' => 'application/json' }
)
+
+ parent_group.add_owner(user)
end
it 'creates bulk import' do
- parent_group.add_owner(user)
expect { subject.execute }.to change { BulkImport.count }.by(1)
last_bulk_import = BulkImport.last
@@ -231,10 +232,11 @@ RSpec.describe BulkImports::CreateService, feature_category: :importers do
status: 200
)
end
+
+ parent_group.add_owner(user)
end
it 'creates bulk import' do
- parent_group.add_owner(user)
expect { subject.execute }.to change { BulkImport.count }.by(1)
last_bulk_import = BulkImport.last
@@ -341,6 +343,8 @@ RSpec.describe BulkImports::CreateService, feature_category: :importers do
end
it 'defines access_level as not a member' do
+ parent_group.members.delete_all
+
subject.execute
expect_snowplow_event(
category: 'BulkImports::CreateService',
@@ -403,7 +407,7 @@ RSpec.describe BulkImports::CreateService, feature_category: :importers do
end
end
- describe '.validate_setting_enabled!' do
+ describe '#validate_setting_enabled!' do
let(:entity_source_id) { 'gid://gitlab/Model/12345' }
let(:graphql_client) { instance_double(BulkImports::Clients::Graphql) }
let(:http_client) { instance_double(BulkImports::Clients::HTTP) }
@@ -502,15 +506,15 @@ RSpec.describe BulkImports::CreateService, feature_category: :importers do
end
end
- describe '.validate_destination_namespace' do
- context 'when the destination_namespace is invalid' do
+ describe '#validate_destination_namespace' do
+ context 'when the destination_namespace does not exist' do
let(:params) do
[
{
source_type: 'group_entity',
source_full_path: 'full/path/to/source',
destination_slug: 'destination-slug',
- destination_namespace: '---destination----namespace---',
+ destination_namespace: 'destination-namespace',
migrate_projects: migrate_projects
}
]
@@ -522,17 +526,62 @@ RSpec.describe BulkImports::CreateService, feature_category: :importers do
expect(result).to be_a(ServiceResponse)
expect(result).to be_error
expect(result.message)
- .to eq(
- "Import failed. Destination group or subgroup path " \
- "must have a relative path structure with no HTTP protocol characters, or leading " \
- "or trailing forward slashes. Path segments must not start or end with a special " \
- "character, and must not contain consecutive special characters."
- )
+ .to eq("Import failed. Destination 'destination-namespace' is invalid, or you don't have permission.")
+ end
+ end
+
+ context 'when the user does not have permission to create subgroups' do
+ let(:params) do
+ [
+ {
+ source_type: 'group_entity',
+ source_full_path: 'full/path/to/source',
+ destination_slug: 'destination-slug',
+ destination_namespace: parent_group.path,
+ migrate_projects: migrate_projects
+ }
+ ]
+ end
+
+ it 'returns ServiceResponse with an error message' do
+ parent_group.members.delete_all
+
+ result = subject.execute
+
+ expect(result).to be_a(ServiceResponse)
+ expect(result).to be_error
+ expect(result.message)
+ .to eq("Import failed. Destination '#{parent_group.path}' is invalid, or you don't have permission.")
+ end
+ end
+
+ context 'when the user does not have permission to create projects' do
+ let(:params) do
+ [
+ {
+ source_type: 'project_entity',
+ source_full_path: 'full/path/to/source',
+ destination_slug: 'destination-slug',
+ destination_namespace: parent_group.path,
+ migrate_projects: migrate_projects
+ }
+ ]
+ end
+
+ it 'returns ServiceResponse with an error message' do
+ parent_group.members.delete_all
+
+ result = subject.execute
+
+ expect(result).to be_a(ServiceResponse)
+ expect(result).to be_error
+ expect(result.message)
+ .to eq("Import failed. Destination '#{parent_group.path}' is invalid, or you don't have permission.")
end
end
end
- describe '.validate_destination_slug' do
+ describe '#validate_destination_slug' do
context 'when the destination_slug is invalid' do
let(:params) do
[
@@ -540,7 +589,7 @@ RSpec.describe BulkImports::CreateService, feature_category: :importers do
source_type: 'group_entity',
source_full_path: 'full/path/to/source',
destination_slug: 'destin-*-ation-slug',
- destination_namespace: 'destination_namespace',
+ destination_namespace: parent_group.path,
migrate_projects: migrate_projects
}
]
@@ -561,7 +610,7 @@ RSpec.describe BulkImports::CreateService, feature_category: :importers do
end
end
- describe '.validate_destination_full_path' do
+ describe '#validate_destination_full_path' do
context 'when the source_type is a group' do
context 'when the provided destination_slug already exists in the destination_namespace' do
let_it_be(:existing_subgroup) { create(:group, path: 'existing-subgroup', parent_id: parent_group.id ) }
@@ -657,6 +706,8 @@ RSpec.describe BulkImports::CreateService, feature_category: :importers do
end
it 'returns ServiceResponse with an error message' do
+ existing_group.add_owner(user)
+
result = subject.execute
expect(result).to be_a(ServiceResponse)
@@ -684,6 +735,8 @@ RSpec.describe BulkImports::CreateService, feature_category: :importers do
end
it 'returns success ServiceResponse' do
+ existing_group.add_owner(user)
+
result = subject.execute
expect(result).to be_a(ServiceResponse)
diff --git a/spec/services/ci/runners/create_runner_service_spec.rb b/spec/services/ci/runners/create_runner_service_spec.rb
index 886411ec5fb..db337b0b005 100644
--- a/spec/services/ci/runners/create_runner_service_spec.rb
+++ b/spec/services/ci/runners/create_runner_service_spec.rb
@@ -179,6 +179,17 @@ RSpec.describe ::Ci::Runners::CreateRunnerService, "#execute", feature_category:
it_behaves_like 'it cannot create a runner'
end
+
+ context 'when model validation fails' do
+ let(:params) { { runner_type: 'instance_type', run_untagged: false, tag_list: [] } }
+
+ it_behaves_like 'it cannot create a runner'
+
+ it 'returns error message and reason', :aggregate_failures do
+ expect(execute.reason).to eq(:save_error)
+ expect(execute.message).to contain_exactly(a_string_including('Tags list can not be empty'))
+ end
+ end
end
end
end
diff --git a/spec/support/shared_examples/bulk_imports/visibility_level_examples.rb b/spec/support/shared_examples/bulk_imports/visibility_level_examples.rb
index 40e9726f89c..02eae250e6a 100644
--- a/spec/support/shared_examples/bulk_imports/visibility_level_examples.rb
+++ b/spec/support/shared_examples/bulk_imports/visibility_level_examples.rb
@@ -27,14 +27,6 @@ RSpec.shared_examples 'visibility level settings' do
expect(transformed_data[:visibility_level]).to eq(Gitlab::VisibilityLevel::PRIVATE)
end
end
-
- context 'when destination is blank' do
- let(:destination_namespace) { '' }
-
- it 'sets visibility level to public' do
- expect(transformed_data[:visibility_level]).to eq(Gitlab::VisibilityLevel::PUBLIC)
- end
- end
end
context 'when internal' do
@@ -63,27 +55,6 @@ RSpec.shared_examples 'visibility level settings' do
expect(transformed_data[:visibility_level]).to eq(Gitlab::VisibilityLevel::PRIVATE)
end
end
-
- context 'when destination is blank' do
- let(:destination_namespace) { '' }
-
- it 'sets visibility level to internal' do
- expect(transformed_data[:visibility_level]).to eq(Gitlab::VisibilityLevel::INTERNAL)
- end
-
- context 'when visibility level is restricted' do
- it 'sets visibility level to private' do
- stub_application_setting(
- restricted_visibility_levels: [
- Gitlab::VisibilityLevel::INTERNAL,
- Gitlab::VisibilityLevel::PUBLIC
- ]
- )
-
- expect(transformed_data[:visibility_level]).to eq(Gitlab::VisibilityLevel::PRIVATE)
- end
- end
- end
end
context 'when private' do
@@ -112,13 +83,5 @@ RSpec.shared_examples 'visibility level settings' do
expect(transformed_data[:visibility_level]).to eq(Gitlab::VisibilityLevel::PRIVATE)
end
end
-
- context 'when destination is blank' do
- let(:destination_namespace) { '' }
-
- it 'sets visibility level to private' do
- expect(transformed_data[:visibility_level]).to eq(Gitlab::VisibilityLevel::PRIVATE)
- end
- end
end
end
diff --git a/spec/support/shared_examples/finders/issues_finder_shared_examples.rb b/spec/support/shared_examples/finders/issues_finder_shared_examples.rb
index b96d2a4b373..78863fe1169 100644
--- a/spec/support/shared_examples/finders/issues_finder_shared_examples.rb
+++ b/spec/support/shared_examples/finders/issues_finder_shared_examples.rb
@@ -598,7 +598,7 @@ RSpec.shared_examples 'issues or work items finder' do |factory, execute_context
end
context 'filtering by no label' do
- let(:params) { { label_name: described_class::Params::FILTER_NONE } }
+ let(:params) { { label_name: IssuableFinder::Params::FILTER_NONE } }
it 'returns items with no labels' do
expect(items).to contain_exactly(item1, item4, item5)
@@ -606,7 +606,7 @@ RSpec.shared_examples 'issues or work items finder' do |factory, execute_context
end
context 'filtering by any label' do
- let(:params) { { label_name: described_class::Params::FILTER_ANY } }
+ let(:params) { { label_name: IssuableFinder::Params::FILTER_ANY } }
it 'returns items that have one or more label' do
create_list(:label_link, 2, label: create(:label, project: project2), target: item3)
diff --git a/yarn.lock b/yarn.lock
index 81c99c4f1b6..80c4560170c 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1127,10 +1127,10 @@
resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-3.38.0.tgz#5c316bc139b3017eea92bb8d603c7ff26fa9ddb7"
integrity sha512-yDkZnuYDQlBB7Eb7noSHGlNpZE6KgM6kX2zB0bmGdHBY2w4wbnjgCR8INYFblH19QGlIToxoW3rOL9iobu4Puw==
-"@gitlab/ui@60.0.0":
- version "60.0.0"
- resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-60.0.0.tgz#dc5331c9658881487f5fa1e769b4f33572999729"
- integrity sha512-/2RyNmM/Ji2/hetMbmsbk7p2Ody5dH9/Rp0jryhNeCARxxcFUeUxZbe0Un61k1Tcln6v/IStA05woSUcp257EQ==
+"@gitlab/ui@60.1.0":
+ version "60.1.0"
+ resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-60.1.0.tgz#cbdbf5456297a7446d9b2d188be256a76324b756"
+ integrity sha512-dA6fogo1o+hgQ4rBcbKB46unOAJtMDJ51dCzdG9W7M/dqqNAxtSw7wI4EWoRbqcsaQnSuxTCV+YjpihwcPJL5g==
dependencies:
"@popperjs/core" "^2.11.2"
bootstrap-vue "2.23.1"