diff --git a/.gitlab/ci/frontend.gitlab-ci.yml b/.gitlab/ci/frontend.gitlab-ci.yml
index 67cfb6f183b..0f17be70530 100644
--- a/.gitlab/ci/frontend.gitlab-ci.yml
+++ b/.gitlab/ci/frontend.gitlab-ci.yml
@@ -311,8 +311,7 @@ jest:
junit: junit_jest.xml
parallel: 11
script:
- - if [[ -z "${CI_MERGE_REQUEST_IID}" ]] && ! [[ "$CI_COMMIT_BRANCH" =~ ^as-if-foss/ ]]; then export JEST_COVERAGE="--coverage"; fi
- - run_timed_command "scripts/frontend/jest_ci.js $JEST_COVERAGE"
+ - run_timed_command scripts/frontend/jest_ci.js
jest-with-fixtures:
extends:
@@ -326,8 +325,7 @@ jest-with-fixtures:
- !reference [.with-fixtures-needs, needs]
parallel: 2
script:
- - if [[ -z "${CI_MERGE_REQUEST_IID}" ]] && ! [[ "$CI_COMMIT_BRANCH" =~ ^as-if-foss/ ]]; then export JEST_COVERAGE="--coverage"; fi
- - run_timed_command "scripts/frontend/jest_ci.js --fixtures $JEST_COVERAGE"
+ - run_timed_command "scripts/frontend/jest_ci.js --fixtures"
jest vue3:
extends:
diff --git a/.rubocop_todo/layout/space_inside_parens.yml b/.rubocop_todo/layout/space_inside_parens.yml
deleted file mode 100644
index 00ef85b4d95..00000000000
--- a/.rubocop_todo/layout/space_inside_parens.yml
+++ /dev/null
@@ -1,23 +0,0 @@
----
-# Cop supports --autocorrect.
-Layout/SpaceInsideParens:
- Exclude:
- - 'spec/policies/clusters/agent_policy_spec.rb'
- - 'spec/presenters/ci/build_presenter_spec.rb'
- - 'spec/presenters/packages/conan/package_presenter_spec.rb'
- - 'spec/requests/jwt_controller_spec.rb'
- - 'spec/requests/projects/merge_requests/diffs_spec.rb'
- - 'spec/requests/projects/merge_requests_spec.rb'
- - 'spec/requests/projects/releases_controller_spec.rb'
- - 'spec/requests/search_controller_spec.rb'
- - 'spec/serializers/analytics_build_entity_spec.rb'
- - 'spec/services/bulk_imports/create_service_spec.rb'
- - 'spec/services/jira_connect_installations/proxy_lifecycle_event_service_spec.rb'
- - 'spec/tasks/gitlab/db_rake_spec.rb'
- - 'spec/validators/devise_email_validator_spec.rb'
- - 'spec/views/dashboard/projects/_blank_state_welcome.html.haml_spec.rb'
- - 'spec/workers/concerns/gitlab/github_import/object_importer_spec.rb'
- - 'spec/workers/gitlab/jira_import/stage/import_labels_worker_spec.rb'
- - 'spec/workers/pipeline_schedule_worker_spec.rb'
- - 'spec/workers/purge_dependency_proxy_cache_worker_spec.rb'
- - 'spec/workers/releases/manage_evidence_worker_spec.rb'
diff --git a/app/assets/javascripts/batch_comments/store/mutations.js b/app/assets/javascripts/batch_comments/store/mutations.js
index 97b9bbe1a7e..eab08498b0d 100644
--- a/app/assets/javascripts/batch_comments/store/mutations.js
+++ b/app/assets/javascripts/batch_comments/store/mutations.js
@@ -70,9 +70,9 @@ export default {
[types.SET_REVIEW_BAR_RENDERED]() {
this.reviewBarRendered = true;
},
- [types.SET_DRAFT_EDITING](state, { draftId, isEditing }) {
- const draftIndex = state.drafts.findIndex((draft) => draft.id === draftId);
- const draft = state.drafts[draftIndex];
- state.drafts.splice(draftIndex, 1, { ...draft, isEditing });
+ [types.SET_DRAFT_EDITING]({ draftId, isEditing }) {
+ const draftIndex = this.drafts.findIndex((draft) => draft.id === draftId);
+ const draft = this.drafts[draftIndex];
+ this.drafts.splice(draftIndex, 1, { ...draft, isEditing });
},
};
diff --git a/app/assets/javascripts/pipeline_wizard/components/wrapper.vue b/app/assets/javascripts/pipeline_wizard/components/wrapper.vue
index b00bb1c34b1..473993d5729 100644
--- a/app/assets/javascripts/pipeline_wizard/components/wrapper.vue
+++ b/app/assets/javascripts/pipeline_wizard/components/wrapper.vue
@@ -171,9 +171,9 @@ export default {
-
+
{{ sprintf($options.i18n.stepNofN, { currentStep, stepCount }) }}
-
+
diff --git a/app/finders/concerns/packages/finder_helper.rb b/app/finders/concerns/packages/finder_helper.rb
index 673b2cbe4a7..12382fbb09c 100644
--- a/app/finders/concerns/packages/finder_helper.rb
+++ b/app/finders/concerns/packages/finder_helper.rb
@@ -63,12 +63,16 @@ module Packages
def projects_visible_to_reporters(user, within_group:, within_public_package_registry: false)
return user.accessible_projects if user.is_a?(DeployToken)
- unless within_public_package_registry
- return within_group.all_projects.public_or_visible_to_user(user, ::Gitlab::Access::REPORTER)
- end
+ access = if Feature.enabled?(:allow_guest_plus_roles_to_pull_packages, within_group.root_ancestor)
+ ::Gitlab::Access::GUEST
+ else
+ ::Gitlab::Access::REPORTER
+ end
+
+ return within_group.all_projects.public_or_visible_to_user(user, access) unless within_public_package_registry
::Project
- .public_or_visible_to_user(user, Gitlab::Access::REPORTER)
+ .public_or_visible_to_user(user, access)
.or(::Project.with_public_package_registry)
.in_namespace(within_group.self_and_descendants)
end
diff --git a/app/finders/packages/conan/package_finder.rb b/app/finders/packages/conan/package_finder.rb
index f0ce5e23f73..4dd9808a7d6 100644
--- a/app/finders/packages/conan/package_finder.rb
+++ b/app/finders/packages/conan/package_finder.rb
@@ -37,7 +37,8 @@ module Packages
end
def projects_available_in_current_context
- return ::Project.public_or_visible_to_user(current_user, ::Gitlab::Access::REPORTER) unless username.present?
+ return ::Project.public_or_visible_to_user(current_user, project_min_access_level) unless username.present?
+
return project_from_path if can_access_project_package?
nil
@@ -55,6 +56,12 @@ module Packages
def can_access_project_package?
Ability.allowed?(current_user, :read_package, project_from_path.try(:packages_policy_subject))
end
+
+ def project_min_access_level
+ return ::Gitlab::Access::GUEST if Feature.enabled?(:allow_guest_plus_roles_to_pull_packages, current_user)
+
+ ::Gitlab::Access::REPORTER
+ end
end
end
end
diff --git a/app/finders/packages/group_packages_finder.rb b/app/finders/packages/group_packages_finder.rb
index 98406616ecb..e7cdbd271e1 100644
--- a/app/finders/packages/group_packages_finder.rb
+++ b/app/finders/packages/group_packages_finder.rb
@@ -60,7 +60,13 @@ module Packages
end
def visible_projects
- public_or_visible = ::Project.public_or_visible_to_user(current_user, Gitlab::Access::REPORTER)
+ access = if Feature.enabled?(:allow_guest_plus_roles_to_pull_packages, group.root_ancestor)
+ ::Gitlab::Access::GUEST
+ else
+ ::Gitlab::Access::REPORTER
+ end
+
+ public_or_visible = ::Project.public_or_visible_to_user(current_user, access)
return public_or_visible.or(with_public_package_registry) if params[:within_public_package_registry]
diff --git a/app/models/bulk_imports/configuration.rb b/app/models/bulk_imports/configuration.rb
index 2f5c1fdd723..5c9c24b28cc 100644
--- a/app/models/bulk_imports/configuration.rb
+++ b/app/models/bulk_imports/configuration.rb
@@ -5,10 +5,6 @@
class BulkImports::Configuration < ApplicationRecord
self.table_name = 'bulk_import_configurations'
- include IgnorableColumns
-
- ignore_column :migrate_memberships, remove_with: '17.8', remove_after: '2025-01-20'
-
belongs_to :bulk_import, inverse_of: :configuration, optional: false
validates :url, :access_token, length: { maximum: 255 }, presence: true
diff --git a/app/models/deploy_token.rb b/app/models/deploy_token.rb
index d8112f7ef8f..2a24084d5e2 100644
--- a/app/models/deploy_token.rb
+++ b/app/models/deploy_token.rb
@@ -8,7 +8,7 @@ class DeployToken < ApplicationRecord
AVAILABLE_SCOPES = %i[read_repository read_registry write_registry
read_package_registry write_package_registry
- read_virtual_registry].freeze
+ read_virtual_registry write_virtual_registry].freeze
GITLAB_DEPLOY_TOKEN_NAME = 'gitlab-deploy-token'
DEPLOY_TOKEN_PREFIX = 'gldt-'
diff --git a/app/models/vulnerability.rb b/app/models/vulnerability.rb
index bdbadfbaeb2..5df4de00b26 100644
--- a/app/models/vulnerability.rb
+++ b/app/models/vulnerability.rb
@@ -4,6 +4,9 @@
class Vulnerability < Gitlab::Database::SecApplicationRecord
include EachBatch
include AfterCommitQueue
+ include IgnorableColumns
+
+ ignore_column :confidence, :confidence_overridden, remove_after: '2025-01-19', remove_with: '17.9'
alias_attribute :vulnerability_id, :id
diff --git a/app/policies/group_policy.rb b/app/policies/group_policy.rb
index 0d916028af6..295cc0eb5e8 100644
--- a/app/policies/group_policy.rb
+++ b/app/policies/group_policy.rb
@@ -126,6 +126,10 @@ class GroupPolicy < Namespaces::GroupProjectNamespaceSharedPolicy
@subject.allow_runner_registration_token?
end
+ condition(:allow_guest_plus_roles_to_pull_packages_enabled, scope: :subject) do
+ Feature.enabled?(:allow_guest_plus_roles_to_pull_packages, @subject.root_ancestor)
+ end
+
rule { can?(:read_group) & design_management_enabled }.policy do
enable :read_design_activity
end
@@ -436,6 +440,11 @@ class GroupPolicy < Namespaces::GroupProjectNamespaceSharedPolicy
rule { can?(:remove_group) }.enable :view_edit_page
+ # TODO: Remove this rule and move :read_package permission from reporter to guest
+ # with the rollout of the FF allow_guest_plus_roles_to_pull_packages
+ # https://gitlab.com/gitlab-org/gitlab/-/issues/512210
+ rule { guest & allow_guest_plus_roles_to_pull_packages_enabled }.enable :read_package
+
def access_level(for_any_session: false)
return GroupMember::NO_ACCESS if @user.nil?
return GroupMember::NO_ACCESS unless user_is_user?
diff --git a/app/policies/packages/policies/group_policy.rb b/app/policies/packages/policies/group_policy.rb
index 3a03aa32cf9..0694a2ae736 100644
--- a/app/policies/packages/policies/group_policy.rb
+++ b/app/policies/packages/policies/group_policy.rb
@@ -14,10 +14,16 @@ module Packages
@subject.all_projects.with_public_package_registry.any?
end
+ condition(:allow_guest_plus_roles_to_pull_packages_enabled, scope: :subject) do
+ Feature.enabled?(:allow_guest_plus_roles_to_pull_packages, @subject.root_ancestor)
+ end
+
rule { group.public_group }.policy do
enable :read_package
end
+ # TODO: Remove with the rollout of the FF allow_guest_plus_roles_to_pull_packages
+ # https://gitlab.com/gitlab-org/gitlab/-/issues/512210
rule { group.reporter }.policy do
enable :read_package
end
@@ -38,6 +44,10 @@ module Packages
# package-related actions that we don't want to.
enable :read_package_within_public_registries
end
+
+ rule { group.guest & allow_guest_plus_roles_to_pull_packages_enabled }.policy do
+ enable :read_package
+ end
end
end
end
diff --git a/app/policies/packages/policies/project_policy.rb b/app/policies/packages/policies/project_policy.rb
index 8ede55b96c9..8e591659cf7 100644
--- a/app/policies/packages/policies/project_policy.rb
+++ b/app/policies/packages/policies/project_policy.rb
@@ -12,10 +12,16 @@ module Packages
Gitlab::CurrentSettings.package_registry_allow_anyone_to_pull_option
end
+ condition(:allow_guest_plus_roles_to_pull_packages_enabled, scope: :subject) do
+ Feature.enabled?(:allow_guest_plus_roles_to_pull_packages, @subject.project.root_ancestor)
+ end
+
rule { project.packages_disabled }.policy do
prevent(:read_package)
end
+ # TODO: Remove with the rollout of the FF allow_guest_plus_roles_to_pull_packages
+ # https://gitlab.com/gitlab-org/gitlab/-/issues/512210
rule { can?(:reporter_access) }.policy do
enable :read_package
end
@@ -24,6 +30,10 @@ module Packages
enable :read_package
end
+ rule { can?(:guest_access) & allow_guest_plus_roles_to_pull_packages_enabled }.policy do
+ enable :read_package
+ end
+
rule { project.read_package_registry_deploy_token }.policy do
enable :read_package
end
diff --git a/app/policies/project_policy.rb b/app/policies/project_policy.rb
index b6d8442796e..db11ebe6b8d 100644
--- a/app/policies/project_policy.rb
+++ b/app/policies/project_policy.rb
@@ -320,6 +320,10 @@ class ProjectPolicy < BasePolicy
can?(:reporter_access) || can?(:planner_access)
end
+ condition(:allow_guest_plus_roles_to_pull_packages_enabled, scope: :subject) do
+ Feature.enabled?(:allow_guest_plus_roles_to_pull_packages, @subject.root_ancestor)
+ end
+
# `:read_project` may be prevented in EE, but `:read_project_for_iids` should
# not.
rule { guest | admin | organization_owner }.enable :read_project_for_iids
@@ -1096,6 +1100,12 @@ class ProjectPolicy < BasePolicy
enable :read_ci_pipeline_schedules_plan_limit
end
+ # TODO: Remove this rule and move :read_package permission from
+ # can?(:reporter_access) to can?(:guest_access)
+ # with the rollout of the FF allow_guest_plus_roles_to_pull_packages
+ # https://gitlab.com/gitlab-org/gitlab/-/issues/512210
+ rule { can?(:guest_access) & allow_guest_plus_roles_to_pull_packages_enabled }.enable :read_package
+
private
def team_member?
diff --git a/app/services/audit_event_service.rb b/app/services/audit_event_service.rb
index ef0d0a534b5..32c03f22566 100644
--- a/app/services/audit_event_service.rb
+++ b/app/services/audit_event_service.rb
@@ -144,10 +144,9 @@ class AuditEventService
def log_authentication_event_to_database
return unless Gitlab::Database.read_write? && authentication_event?
- event = AuthenticationEvent.new(authentication_event_payload)
- save_or_track event
-
- event
+ AuthenticationEvent.new(authentication_event_payload).tap do |event|
+ save_or_track event
+ end
end
def save_or_track(event)
@@ -155,6 +154,8 @@ class AuditEventService
stream_event_to_external_destinations(event) if should_save_stream?(@save_type)
rescue StandardError => e
Gitlab::ErrorTracking.track_and_raise_for_dev_exception(e, audit_event_type: event.class.to_s)
+
+ nil
end
end
diff --git a/config/feature_flags/beta/license_scanning_with_sbom_licenses.yml b/config/feature_flags/gitlab_com_derisk/allow_guest_plus_roles_to_pull_packages.yml
similarity index 52%
rename from config/feature_flags/beta/license_scanning_with_sbom_licenses.yml
rename to config/feature_flags/gitlab_com_derisk/allow_guest_plus_roles_to_pull_packages.yml
index 04ba6f39873..a4e0b37598a 100644
--- a/config/feature_flags/beta/license_scanning_with_sbom_licenses.yml
+++ b/config/feature_flags/gitlab_com_derisk/allow_guest_plus_roles_to_pull_packages.yml
@@ -1,9 +1,9 @@
---
-name: license_scanning_with_sbom_licenses
-feature_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/370013
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/162102
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/415946
-milestone: '17.4'
-group: group::threat insights
-type: beta
-default_enabled: true
+name: allow_guest_plus_roles_to_pull_packages
+feature_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/336622
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/177267
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/512210
+milestone: '17.9'
+group: group::package registry
+type: gitlab_com_derisk
+default_enabled: false
diff --git a/db/docs/batched_background_migrations/migrate_remaining_software_license_without_spdx_identifier_to_custom_licenses.yml b/db/docs/batched_background_migrations/migrate_remaining_software_license_without_spdx_identifier_to_custom_licenses.yml
index 1437c9c0dcd..3af4bf0b2cb 100644
--- a/db/docs/batched_background_migrations/migrate_remaining_software_license_without_spdx_identifier_to_custom_licenses.yml
+++ b/db/docs/batched_background_migrations/migrate_remaining_software_license_without_spdx_identifier_to_custom_licenses.yml
@@ -5,4 +5,5 @@ feature_category: security_policy_management
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/173790
milestone: '17.7'
queued_migration_version: 20241127151803
-finalized_by: # version of the migration that finalized this BBM
+finalized_by: 20250114213926
+
diff --git a/db/docs/batched_background_migrations/recalculate_sharding_key_id_for_orphaned_project_runner_managers.yml b/db/docs/batched_background_migrations/recalculate_sharding_key_id_for_orphaned_project_runner_managers.yml
index cca8eb775c5..af4125448f9 100644
--- a/db/docs/batched_background_migrations/recalculate_sharding_key_id_for_orphaned_project_runner_managers.yml
+++ b/db/docs/batched_background_migrations/recalculate_sharding_key_id_for_orphaned_project_runner_managers.yml
@@ -5,6 +5,6 @@ description: >
If there is no other assigned project to fall back to, the runner manager is deleted.
feature_category: runner
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/177423
-milestone: '17.9'
+milestone: '17.8'
queued_migration_version: 20250108170045
finalized_by: # version of the migration that finalized this BBM
diff --git a/db/docs/batched_background_migrations/recalculate_sharding_key_id_for_orphaned_project_runner_taggings.yml b/db/docs/batched_background_migrations/recalculate_sharding_key_id_for_orphaned_project_runner_taggings.yml
index 435573ba846..44c8b392d53 100644
--- a/db/docs/batched_background_migrations/recalculate_sharding_key_id_for_orphaned_project_runner_taggings.yml
+++ b/db/docs/batched_background_migrations/recalculate_sharding_key_id_for_orphaned_project_runner_taggings.yml
@@ -5,6 +5,6 @@ description: >
If there is no other assigned project to fall back to, the runner manager is deleted.
feature_category: runner
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/177423
-milestone: '17.9'
+milestone: '17.8'
queued_migration_version: 20250109133913
finalized_by: # version of the migration that finalized this BBM
diff --git a/db/docs/batched_background_migrations/recalculate_sharding_key_id_for_orphaned_project_runners.yml b/db/docs/batched_background_migrations/recalculate_sharding_key_id_for_orphaned_project_runners.yml
index 44fcc4aa231..802b926e3aa 100644
--- a/db/docs/batched_background_migrations/recalculate_sharding_key_id_for_orphaned_project_runners.yml
+++ b/db/docs/batched_background_migrations/recalculate_sharding_key_id_for_orphaned_project_runners.yml
@@ -5,6 +5,6 @@ description: >
If there is no other assigned project to fall back to, the runner is deleted.
feature_category: runner
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/177271
-milestone: '17.9'
+milestone: '17.8'
queued_migration_version: 20250108120138
finalized_by: # version of the migration that finalized this BBM
diff --git a/db/migrate/20241203052500_add_write_virtual_registry_scope_to_deploy_tokens.rb b/db/migrate/20241203052500_add_write_virtual_registry_scope_to_deploy_tokens.rb
new file mode 100644
index 00000000000..45f780113e6
--- /dev/null
+++ b/db/migrate/20241203052500_add_write_virtual_registry_scope_to_deploy_tokens.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+class AddWriteVirtualRegistryScopeToDeployTokens < Gitlab::Database::Migration[2.2]
+ milestone '17.9'
+
+ def change
+ add_column :deploy_tokens, :write_virtual_registry, :boolean, default: false, null: false
+ end
+end
diff --git a/db/migrate/20250114194544_add_user_provided_to_workspace_variables.rb b/db/migrate/20250114194544_add_user_provided_to_workspace_variables.rb
new file mode 100644
index 00000000000..07c3759b69d
--- /dev/null
+++ b/db/migrate/20250114194544_add_user_provided_to_workspace_variables.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+class AddUserProvidedToWorkspaceVariables < Gitlab::Database::Migration[2.2]
+ milestone '17.9'
+
+ def change
+ add_column :workspace_variables, :user_provided, :boolean, null: false, default: false, if_not_exists: true
+ end
+end
diff --git a/db/migrate/20250114194610_backfill_user_provided_workspace_variables.rb b/db/migrate/20250114194610_backfill_user_provided_workspace_variables.rb
new file mode 100644
index 00000000000..187625cea7b
--- /dev/null
+++ b/db/migrate/20250114194610_backfill_user_provided_workspace_variables.rb
@@ -0,0 +1,54 @@
+# frozen_string_literal: true
+
+class BackfillUserProvidedWorkspaceVariables < Gitlab::Database::Migration[2.2]
+ milestone '17.9'
+
+ restrict_gitlab_migration gitlab_schema: :gitlab_main
+
+ class WorkspaceVariable < MigrationRecord
+ self.table_name = :workspace_variables
+
+ include EachBatch
+ end
+
+ BATCH_SIZE = 100
+
+ # Since file type is not supported for user variables
+ VARIABLE_ENV_TYPE = 0
+
+ # Internal workspace variables that get created on workspace creation
+ # Reference: /ee/lib/remote_development/workspace_operations/create/workspace_variables.rb
+ WORKSPACE_INTERNAL_VARIABLES = %w[
+ GIT_CONFIG_COUNT
+ GIT_CONFIG_KEY_0
+ GIT_CONFIG_VALUE_0
+ GIT_CONFIG_KEY_1
+ GIT_CONFIG_VALUE_1
+ GIT_CONFIG_KEY_2
+ GIT_CONFIG_VALUE_2
+ GL_GIT_CREDENTIAL_STORE_FILE_PATH
+ GL_TOKEN_FILE_PATH
+ GL_WORKSPACE_DOMAIN_TEMPLATE
+ GL_EDITOR_EXTENSIONS_GALLERY_SERVICE_URL
+ GL_EDITOR_EXTENSIONS_GALLERY_ITEM_URL
+ GL_EDITOR_EXTENSIONS_GALLERY_RESOURCE_URL_TEMPLATE
+ GITLAB_WORKFLOW_INSTANCE_URL
+ GITLAB_WORKFLOW_TOKEN_FILE
+ ].freeze
+
+ def up
+ WorkspaceVariable.reset_column_information
+
+ WorkspaceVariable.each_batch(of: BATCH_SIZE) do |batch|
+ batch.where(variable_type: VARIABLE_ENV_TYPE).where.not(key: WORKSPACE_INTERNAL_VARIABLES)
+ .update_all(user_provided: true)
+ end
+ end
+
+ def down
+ WorkspaceVariable.reset_column_information
+
+ # Column is NOT NULL DEFAULT 0, so setting back to default
+ WorkspaceVariable.update_all(user_provided: false)
+ end
+end
diff --git a/db/post_migrate/20250108120138_queue_recalculate_sharding_key_id_for_orphaned_project_runners.rb b/db/post_migrate/20250108120138_queue_recalculate_sharding_key_id_for_orphaned_project_runners.rb
index 1e607d12afc..408fa7fad87 100644
--- a/db/post_migrate/20250108120138_queue_recalculate_sharding_key_id_for_orphaned_project_runners.rb
+++ b/db/post_migrate/20250108120138_queue_recalculate_sharding_key_id_for_orphaned_project_runners.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
class QueueRecalculateShardingKeyIdForOrphanedProjectRunners < Gitlab::Database::Migration[2.2]
- milestone '17.9'
+ milestone '17.8'
restrict_gitlab_migration gitlab_schema: :gitlab_ci
diff --git a/db/post_migrate/20250108170045_queue_recalculate_sharding_key_id_for_orphaned_project_runner_managers.rb b/db/post_migrate/20250108170045_queue_recalculate_sharding_key_id_for_orphaned_project_runner_managers.rb
index ac00f9cf77e..53fd8551d94 100644
--- a/db/post_migrate/20250108170045_queue_recalculate_sharding_key_id_for_orphaned_project_runner_managers.rb
+++ b/db/post_migrate/20250108170045_queue_recalculate_sharding_key_id_for_orphaned_project_runner_managers.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
class QueueRecalculateShardingKeyIdForOrphanedProjectRunnerManagers < Gitlab::Database::Migration[2.2]
- milestone '17.9'
+ milestone '17.8'
restrict_gitlab_migration gitlab_schema: :gitlab_ci
diff --git a/db/post_migrate/20250109133913_queue_recalculate_sharding_key_id_for_orphaned_project_runner_taggings.rb b/db/post_migrate/20250109133913_queue_recalculate_sharding_key_id_for_orphaned_project_runner_taggings.rb
index c0d80f76239..926f016e74d 100644
--- a/db/post_migrate/20250109133913_queue_recalculate_sharding_key_id_for_orphaned_project_runner_taggings.rb
+++ b/db/post_migrate/20250109133913_queue_recalculate_sharding_key_id_for_orphaned_project_runner_taggings.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
class QueueRecalculateShardingKeyIdForOrphanedProjectRunnerTaggings < Gitlab::Database::Migration[2.2]
- milestone '17.9'
+ milestone '17.8'
restrict_gitlab_migration gitlab_schema: :gitlab_ci
diff --git a/db/post_migrate/20250114213926_finalize_migrate_software_license_without_spdx_identifier_to_custom_licenses.rb b/db/post_migrate/20250114213926_finalize_migrate_software_license_without_spdx_identifier_to_custom_licenses.rb
new file mode 100644
index 00000000000..97dcaf70755
--- /dev/null
+++ b/db/post_migrate/20250114213926_finalize_migrate_software_license_without_spdx_identifier_to_custom_licenses.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+class FinalizeMigrateSoftwareLicenseWithoutSpdxIdentifierToCustomLicenses < Gitlab::Database::Migration[2.2]
+ milestone '17.9'
+
+ disable_ddl_transaction!
+ restrict_gitlab_migration gitlab_schema: :gitlab_main
+
+ MIGRATION = "MigrateRemainingSoftwareLicenseWithoutSpdxIdentifierToCustomLicenses"
+
+ def up
+ ensure_batched_background_migration_is_finished(
+ job_class_name: MIGRATION,
+ table_name: :software_license_policies,
+ column_name: :id,
+ job_arguments: [],
+ finalize: true
+ )
+ end
+
+ def down
+ # no-op
+ end
+end
diff --git a/db/schema_migrations/20241203052500 b/db/schema_migrations/20241203052500
new file mode 100644
index 00000000000..9a4d1ca27ec
--- /dev/null
+++ b/db/schema_migrations/20241203052500
@@ -0,0 +1 @@
+22a0025bf1ff0bf243698761c17bcfdb181599a4f31ac696c20511dfd1afbf9b
\ No newline at end of file
diff --git a/db/schema_migrations/20250114194544 b/db/schema_migrations/20250114194544
new file mode 100644
index 00000000000..1136a615f5b
--- /dev/null
+++ b/db/schema_migrations/20250114194544
@@ -0,0 +1 @@
+79ded29b939ad063a58275fec52191c01161d48b89758b05f3dc3f15c41f018d
\ No newline at end of file
diff --git a/db/schema_migrations/20250114194610 b/db/schema_migrations/20250114194610
new file mode 100644
index 00000000000..04cc0d3f4f3
--- /dev/null
+++ b/db/schema_migrations/20250114194610
@@ -0,0 +1 @@
+e57acf78acb8d7c507b2e4d611be22d6741f4a0e09970776bb86f2aca266b542
\ No newline at end of file
diff --git a/db/schema_migrations/20250114213926 b/db/schema_migrations/20250114213926
new file mode 100644
index 00000000000..15a74910ff3
--- /dev/null
+++ b/db/schema_migrations/20250114213926
@@ -0,0 +1 @@
+b358e94b4be73e82fe3140c3cd0e0d2568a1e6eccd682ca0edb932207f28cf26
\ No newline at end of file
diff --git a/db/structure.sql b/db/structure.sql
index f5a4c711e52..8f620fca56b 100644
--- a/db/structure.sql
+++ b/db/structure.sql
@@ -12204,7 +12204,8 @@ CREATE TABLE deploy_tokens (
creator_id bigint,
read_virtual_registry boolean DEFAULT false NOT NULL,
project_id bigint,
- group_id bigint
+ group_id bigint,
+ write_virtual_registry boolean DEFAULT false NOT NULL
);
CREATE SEQUENCE deploy_tokens_id_seq
@@ -23305,6 +23306,7 @@ CREATE TABLE workspace_variables (
encrypted_value bytea NOT NULL,
encrypted_value_iv bytea NOT NULL,
project_id bigint,
+ user_provided boolean DEFAULT false NOT NULL,
CONSTRAINT check_5545042100 CHECK ((char_length(key) <= 255)),
CONSTRAINT check_ed95da8691 CHECK ((project_id IS NOT NULL))
);
diff --git a/doc/administration/dedicated/maintenance.md b/doc/administration/dedicated/maintenance.md
index 0f2b797e0ff..abb4e785053 100644
--- a/doc/administration/dedicated/maintenance.md
+++ b/doc/administration/dedicated/maintenance.md
@@ -54,6 +54,9 @@ Upgrades occur in your selected [maintenance window](#maintenance-windows) accor
For example, GitLab 16.9 released on 2024-02-15. Instances in the EMEA and Americas (Option 1) regions were then upgraded to 16.8 on 2024-02-20, 5 days after the 16.9 release.
+NOTE:
+If a production change lock (PCL) is active during a scheduled upgrade, GitLab defers the upgrade to the first maintenance window after the PCL ends. For more information, including upcoming and current PCL periods, see [Production Change Lock](https://handbook.gitlab.com/handbook/engineering/infrastructure/team/gitlab-dedicated/#production-change-lock-pcl).
+
## Emergency maintenance
In an event of a platform outage, degradation, or a security event requiring urgent action,
diff --git a/doc/administration/terraform_state.md b/doc/administration/terraform_state.md
index 6792b525518..40891e3b520 100644
--- a/doc/administration/terraform_state.md
+++ b/doc/administration/terraform_state.md
@@ -248,3 +248,51 @@ To find a state file path:
```
The relative path is displayed.
+
+## Restoring Terraform state files from backups
+
+To restore Terraform state files from backups, you must have access to the encrypted state files and the GitLab database.
+
+### Database tables
+
+The following database table helps trace the S3 path back to specific projects:
+
+- `terraform_states`: Contains the base state information, including the universally unique ID (UUID) for each state.
+
+### File structure and path composition
+
+The state files are stored in a specific directory structure, where:
+
+- The first three segments of the path are derived from the SHA-2 hash value of the project ID.
+- Each state has a UUID stored on the `terraform_states` database table that forms part of the path.
+
+For example, for a project where the:
+
+- Project ID is `12345`
+- State UUID is `example-uuid`
+
+If the SHA-2 hash value of `12345` is `5994471abb01112afcc18159f6cc74b4f511b99806da59b3caf5a9c173cacfc5`, the folder structure would be:
+
+```plaintext
+terraform/ <- configured Terraform storage directory
+├─ 59/ <- first and second character of project ID hash
+| ├─ 94/ <- third and fourth character of project ID hash
+| | ├─ 5994471abb01112afcc18159f6cc74b4f511b99806da59b3caf5a9c173cacfc5/ <- full project ID hash
+| | | ├─ example-uuid/ <- state UUID
+| | | | ├─ 1.tf <- individual state versions
+| | | | ├─ 2.tf
+| | | | ├─ 3.tf
+```
+
+### Decryption process
+
+The state files are encrypted using Lockbox and require the following information for decryption:
+
+- The `db_key_base` [application secret](../development/application_secrets.md#secret-entries)
+- The project ID
+
+The encryption key is derived from both the `db_key_base` and the project ID. If you can't access `db_key_base`, decryption is not possible.
+
+To learn how to manually decrypt files, see the documentation from [Lockbox](https://github.com/ankane/lockbox).
+
+To view the encryption key generation process, see the [state uploader code](https://gitlab.com/gitlab-org/gitlab/-/blob/e0137111fbbd28316f38da30075aba641e702b98/app/uploaders/terraform/state_uploader.rb#L43).
diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md
index c81a45705eb..72b97ec76c5 100644
--- a/doc/api/graphql/reference/index.md
+++ b/doc/api/graphql/reference/index.md
@@ -18344,6 +18344,29 @@ The edge type for [`Workspace`](#workspace).
| `cursor` | [`String!`](#string) | A cursor for use in pagination. |
| `node` | [`Workspace`](#workspace) | The item at the end of the edge. |
+#### `WorkspaceVariableConnection`
+
+The connection type for [`WorkspaceVariable`](#workspacevariable).
+
+##### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| `edges` | [`[WorkspaceVariableEdge]`](#workspacevariableedge) | A list of edges. |
+| `nodes` | [`[WorkspaceVariable]`](#workspacevariable) | A list of nodes. |
+| `pageInfo` | [`PageInfo!`](#pageinfo) | Information to aid in pagination. |
+
+#### `WorkspaceVariableEdge`
+
+The edge type for [`WorkspaceVariable`](#workspacevariable).
+
+##### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| `cursor` | [`String!`](#string) | A cursor for use in pagination. |
+| `node` | [`WorkspaceVariable`](#workspacevariable) | The item at the end of the edge. |
+
## Object types
Object types represent the resources that the GitLab GraphQL API can return.
@@ -21308,7 +21331,7 @@ four standard [pagination arguments](#pagination-arguments):
| ---- | ---- | ----------- |
| `actualStates` | [`[String!]`](#string) | Filter workspaces by actual states. |
| `ids` | [`[RemoteDevelopmentWorkspaceID!]`](#remotedevelopmentworkspaceid) | Filter workspaces by workspace GlobalIDs. For example, `["gid://gitlab/RemoteDevelopment::Workspace/1"]`. |
-| `projectIds` | [`[ProjectID!]`](#projectid) | Filter workspaces by project GlobalID. |
+| `projectIds` | [`[ProjectID!]`](#projectid) | Filter workspaces by project GlobalIDs. |
### `ClusterAgentActivityEvent`
@@ -38476,8 +38499,24 @@ Represents a remote development workspace.
| `updatedAt` | [`Time!`](#time) | Timestamp of the last update to any mutable workspace property. |
| `url` | [`String!`](#string) | URL of the workspace. |
| `user` | [`UserCore!`](#usercore) | Owner of the workspace. |
+| `workspaceVariables` **{warning-solid}** | [`WorkspaceVariableConnection`](#workspacevariableconnection) | **Introduced** in GitLab 17.9. **Status**: Experiment. User defined variables associated with the workspace. |
| `workspacesAgentConfigVersion` **{warning-solid}** | [`Int!`](#int) | **Introduced** in GitLab 17.6. **Status**: Experiment. Version of the associated WorkspacesAgentConfig for the workspace. |
+### `WorkspaceVariable`
+
+Represents a remote development workspace variable.
+
+#### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| `createdAt` | [`Time!`](#time) | Timestamp of when the workspace variable was created. |
+| `id` | [`RemoteDevelopmentWorkspaceVariableID!`](#remotedevelopmentworkspacevariableid) | Global ID of the workspace variable. |
+| `key` | [`String`](#string) | Name of the workspace variable. |
+| `updatedAt` | [`Time!`](#time) | Timestamp of when the workspace variable was updated. |
+| `value` | [`String`](#string) | Value of the workspace variable. |
+| `variableType` | [`WorkspaceVariableType`](#workspacevariabletype) | Type of the workspace variable. |
+
### `WorkspacesAgentConfig`
Represents a workspaces agent config.
@@ -42179,6 +42218,14 @@ Enum for the type of the variable to be injected in a workspace.
| ----- | ----------- |
| `ENVIRONMENT` | Name type. |
+### `WorkspaceVariableType`
+
+Enum for the type of the variable injected in a workspace.
+
+| Value | Description |
+| ----- | ----------- |
+| `ENVIRONMENT` | Environment type. |
+
## Scalar types
Scalar values are atomic values, and do not have fields of their own.
@@ -43151,6 +43198,12 @@ A `RemoteDevelopmentWorkspaceID` is a global ID. It is encoded as a string.
An example `RemoteDevelopmentWorkspaceID` is: `"gid://gitlab/RemoteDevelopment::Workspace/1"`.
+### `RemoteDevelopmentWorkspaceVariableID`
+
+A `RemoteDevelopmentWorkspaceVariableID` is a global ID. It is encoded as a string.
+
+An example `RemoteDevelopmentWorkspaceVariableID` is: `"gid://gitlab/RemoteDevelopment::WorkspaceVariable/1"`.
+
### `RemoteDevelopmentWorkspacesAgentConfigID`
A `RemoteDevelopmentWorkspacesAgentConfigID` is a global ID. It is encoded as a string.
@@ -45636,6 +45689,7 @@ Attributes for defining a variable to be injected in a workspace.
| Name | Type | Description |
| ---- | ---- | ----------- |
-| `key` | [`String!`](#string) | Key of the variable. |
-| `type` | [`WorkspaceVariableInputType!`](#workspacevariableinputtype) | Type of the variable to be injected in a workspace. |
+| `key` | [`String!`](#string) | Name of the workspace variable. |
+| `type` **{warning-solid}** | [`WorkspaceVariableInputType`](#workspacevariableinputtype) | **Deprecated:** Use `variableType` instead. Deprecated in GitLab 17.9. |
| `value` | [`String!`](#string) | Value of the variable. |
+| `variableType` | [`WorkspaceVariableType`](#workspacevariabletype) | Type of the variable to be injected in a workspace. |
diff --git a/doc/update/versions/gitlab_17_changes.md b/doc/update/versions/gitlab_17_changes.md
index db3ad6ef51e..4d3e9a11efc 100644
--- a/doc/update/versions/gitlab_17_changes.md
+++ b/doc/update/versions/gitlab_17_changes.md
@@ -214,6 +214,17 @@ For more information, see [issue 480328](https://gitlab.com/gitlab-org/gitlab/-/
gitlab-rake db:migrate:up:ci VERSION=20241028085044
```
+## 17.8.0
+
+- In GitLab 17.8.0, GitLab agent server for Kubernetes (KAS) does not start with the default settings on the GitLab Linux package (Omnibus) and Docker installations.
+ To resolve this issue, edit `/etc/gitlab/gitlab.rb`:
+
+ ```ruby
+ gitlab_kas['env'] = { 'OWN_PRIVATE_API_URL' => 'grpc://127.0.0.1:8155' }
+ ```
+
+ Multiple node installations should use the settings described in the [documentation](../../administration/clusters/kas.md).
+
## 17.7.0
- Git 2.47.0 and later is required by Gitaly. For installations from source, you should use the [Git version provided by Gitaly](../../install/installation.md#git).
diff --git a/doc/user/application_security/policies/vulnerability_management_policy.md b/doc/user/application_security/policies/vulnerability_management_policy.md
index 100d09f2826..437f7e6a5ca 100644
--- a/doc/user/application_security/policies/vulnerability_management_policy.md
+++ b/doc/user/application_security/policies/vulnerability_management_policy.md
@@ -12,10 +12,7 @@ DETAILS:
> - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/5708) support for enforcing policies on projects in GitLab 17.7 [with a flag](../../../administration/feature_flags.md) named `vulnerability_management_policy_type`. Enabled by default.
> - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/15697) support for enforcing policies on groups in GitLab 17.8 for the group-level [with a flag](../../../administration/feature_flags.md) named `vulnerability_management_policy_type_group`. Enabled by default.
-
-FLAG:
-The availability of this feature is controlled by a feature flag.
-For more information, see the history.
+> - [Generally available](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/178031) in GitLab 17.9. Feature flags `vulnerability_management_policy_type` and `vulnerability_management_policy_type_group` removed.
Use a vulnerability management policy to automatically resolve vulnerabilities that are no longer
detected. This can help reduce the workload of triaging vulnerabilities.
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 9ea9048019e..9e1b0786e05 100644
--- a/doc/user/compliance/license_scanning_of_cyclonedx_files/index.md
+++ b/doc/user/compliance/license_scanning_of_cyclonedx_files/index.md
@@ -15,6 +15,7 @@ DETAILS:
> - The legacy License Compliance analyzer (`License-Scanning.gitlab-ci.yml`) was [removed](https://gitlab.com/gitlab-org/gitlab/-/issues/439162) in GitLab 17.0.
> - In GitLab 17.5 we introduced the ability to use a CycloneDX report artifact as a source of data for license information behind the feature flag `license_scanning_with_sbom_licenses`, disabled by default.
> - In GitLab 17.6 the ability to use a CycloneDX report artifact as a source of data for license information has been enabled by default. The feature flag `license_scanning_with_sbom_licenses` is still present to disable the feature if necessary.
+> - In GitLab 17.8 the feature flag `license_scanning_with_sbom_licenses` was removed.
To detect the licenses in use, License Compliance relies on running the
[Dependency Scanning CI Jobs](../../application_security/dependency_scanning/index.md),
@@ -216,8 +217,9 @@ CycloneDX reports for licenses. For more information, see the offline [quick sta
## Use CycloneDX report as a source of license information
The ability to use a CI report artifact as a source of license information data was introduced in GitLab 17.5 behind the feature flag `license_scanning_with_sbom_licenses` and enabled by default in 17.6.
+In GitLab 17.8 the feature flag `license_scanning_with_sbom_licenses` was removed.
-When the feature flag `license_scanning_with_sbom_licenses` is enabled, the License Scanning uses the [licenses](https://cyclonedx.org/use-cases/#license-compliance) field of the CycloneDX JSON SBOM when available. If the license information is unavailable, the license information imported from the external license database will be used(current behavior).
+The License Scanning uses the [licenses](https://cyclonedx.org/use-cases/#license-compliance) field of the CycloneDX JSON SBOM when available. If the license information is unavailable, the license information imported from the external license database will be used(current behavior).
License information can be provided using a valid SPDX identifier or a license name. However, providing a license using an SPDX License Expression is not supported.
More information about the license field format can be found on the [CycloneDX](https://cyclonedx.org/use-cases/#license-compliance) specification.
diff --git a/lib/api/deploy_tokens.rb b/lib/api/deploy_tokens.rb
index 78f55d188bc..5440f960ee6 100644
--- a/lib/api/deploy_tokens.rb
+++ b/lib/api/deploy_tokens.rb
@@ -19,6 +19,8 @@ module API
result_hash[:read_package_registry] = scopes.include?('read_package_registry')
result_hash[:write_package_registry] = scopes.include?('write_package_registry')
result_hash[:read_repository] = scopes.include?('read_repository')
+ result_hash[:read_virtual_registry] = scopes.include?('read_virtual_registry')
+ result_hash[:write_virtual_registry] = scopes.include?('write_virtual_registry')
result_hash
end
@@ -90,7 +92,7 @@ module API
type: Array[String],
coerce_with: ::API::Validations::Types::CommaSeparatedToArray.coerce,
values: ::DeployToken::AVAILABLE_SCOPES.map(&:to_s),
- desc: 'Indicates the deploy token scopes. Must be at least one of `read_repository`, `read_registry`, `write_registry`, `read_package_registry`, or `write_package_registry`.'
+ desc: 'Indicates the deploy token scopes. Must be at least one of `read_repository`, `read_registry`, `write_registry`, `read_package_registry`, `write_package_registry`, `read_virtual_registry`, or `write_virtual_registry`.'
optional :expires_at, type: DateTime, desc: 'Expiration date for the deploy token. Does not expire if no value is provided. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`).'
optional :username, type: String, desc: 'Username for deploy token. Default is `gitlab+deploy-token-{n}`'
end
diff --git a/lib/gitlab/audit/auditor.rb b/lib/gitlab/audit/auditor.rb
index 43ba5466951..0ea8a3fed2c 100644
--- a/lib/gitlab/audit/auditor.rb
+++ b/lib/gitlab/audit/auditor.rb
@@ -196,6 +196,8 @@ module Gitlab
end
rescue ActiveRecord::RecordInvalid => e
::Gitlab::ErrorTracking.track_exception(e, audit_operation: @name)
+
+ nil
end
def log_to_file(events)
diff --git a/lib/gitlab/audit/logging.rb b/lib/gitlab/audit/logging.rb
index b07d2dfa9ec..039debd3835 100644
--- a/lib/gitlab/audit/logging.rb
+++ b/lib/gitlab/audit/logging.rb
@@ -16,6 +16,8 @@ module Gitlab
events.each { |event| log_event(event) }
rescue ActiveRecord::RecordInvalid => e
::Gitlab::ErrorTracking.track_exception(e, audit_operation: audit_operation)
+
+ nil
end
private
diff --git a/lib/gitlab/auth.rb b/lib/gitlab/auth.rb
index 4fa771b447c..b7dec9bce85 100644
--- a/lib/gitlab/auth.rb
+++ b/lib/gitlab/auth.rb
@@ -46,6 +46,13 @@ module Gitlab
WRITE_REGISTRY_SCOPE = :write_registry
REGISTRY_SCOPES = [READ_REGISTRY_SCOPE, WRITE_REGISTRY_SCOPE].freeze
+ # Scopes used for Virtual Registry access
+ READ_VIRTUAL_REGISTRY_SCOPE = :read_virtual_registry
+ WRITE_VIRTUAL_REGISTRY_SCOPE = :write_virtual_registry
+ VIRTUAL_REGISTRY_SCOPES = [
+ READ_VIRTUAL_REGISTRY_SCOPE, WRITE_VIRTUAL_REGISTRY_SCOPE
+ ].freeze
+
# Scopes used for GitLab Observability access which is outside of the GitLab app itself.
# Hence the lack of ability mapping in `abilities_for_scopes`.
READ_OBSERVABILITY_SCOPE = :read_observability
@@ -289,6 +296,8 @@ module Gitlab
read_api: read_only_authentication_abilities,
read_registry: %i[read_container_image],
write_registry: %i[create_container_image],
+ read_virtual_registry: %i[read_dependency_proxy],
+ write_virtual_registry: %i[write_dependency_proxy],
read_repository: %i[download_code],
write_repository: %i[download_code push_code],
create_runner: %i[create_instance_runner create_runner],
@@ -435,6 +444,12 @@ module Gitlab
REGISTRY_SCOPES
end
+ def virtual_registry_scopes
+ return [] unless Gitlab.config.dependency_proxy.enabled
+
+ VIRTUAL_REGISTRY_SCOPES
+ end
+
def resource_bot_scopes
non_admin_available_scopes - [READ_USER_SCOPE]
end
@@ -479,7 +494,7 @@ module Gitlab
end
def non_admin_available_scopes
- API_SCOPES + REPOSITORY_SCOPES + registry_scopes + OBSERVABILITY_SCOPES + AI_FEATURES_SCOPES
+ API_SCOPES + REPOSITORY_SCOPES + registry_scopes + virtual_registry_scopes + OBSERVABILITY_SCOPES + AI_FEATURES_SCOPES
end
def find_build_by_token(token)
diff --git a/lib/gitlab/ci/parsers/sbom/component.rb b/lib/gitlab/ci/parsers/sbom/component.rb
index d31edff2315..4e1a8312f4b 100644
--- a/lib/gitlab/ci/parsers/sbom/component.rb
+++ b/lib/gitlab/ci/parsers/sbom/component.rb
@@ -9,9 +9,8 @@ module Gitlab
TRIVY_SOURCE_PACKAGE_FIELD = 'SrcName'
- def initialize(data, project: nil)
+ def initialize(data)
@data = data
- @project = project
end
def parse
@@ -57,8 +56,6 @@ module Gitlab
strong_memoize_attr :container_scanning_component?
def licenses
- return [] unless Feature.enabled?(:license_scanning_with_sbom_licenses, @project)
-
data.fetch('licenses', []).filter_map do |license_data|
license = License.new(license_data).parse
next unless license
diff --git a/lib/gitlab/ci/parsers/sbom/cyclonedx.rb b/lib/gitlab/ci/parsers/sbom/cyclonedx.rb
index 05b03f32380..97648dd315d 100644
--- a/lib/gitlab/ci/parsers/sbom/cyclonedx.rb
+++ b/lib/gitlab/ci/parsers/sbom/cyclonedx.rb
@@ -5,10 +5,6 @@ module Gitlab
module Parsers
module Sbom
class Cyclonedx
- def initialize(project: nil)
- @project = project
- end
-
def parse!(blob, sbom_report)
@report = sbom_report
@data = Gitlab::Json.parse(blob)
@@ -64,7 +60,7 @@ module Gitlab
def parse_components
data['components']&.each_with_index do |component_data, index|
- component = Component.new(component_data, project: @project).parse
+ component = Component.new(component_data).parse
report.add_component(component) if component.ingestible?
rescue ::Sbom::PackageUrl::InvalidPackageUrl
report.add_error("/components/#{index}/purl is invalid")
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 3b2806c0e00..dd06e4ee7f5 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -40789,9 +40789,18 @@ msgstr ""
msgid "PagesUsageQuota|Learn about limits for Pages deployments"
msgstr ""
+msgid "PagesUsageQuota|Other projects in namespace"
+msgstr ""
+
msgid "PagesUsageQuota|Remaining deployments"
msgstr ""
+msgid "PagesUsageQuota|This project"
+msgstr ""
+
+msgid "PagesUsageQuota|This project is using the namespace domain \"%{domain}\". The usage quota includes parallel deployments for all projects in the namespace that use this domain."
+msgstr ""
+
msgid "Pages|+ %{n} more deployments"
msgstr ""
@@ -51728,9 +51737,6 @@ msgstr ""
msgid "SecurityOrchestration|Security policy projects store your organization's security policies. They are identified when policies are created, or when a project is linked as a security policy project. %{linkStart}Learn more%{linkEnd}."
msgstr ""
-msgid "SecurityOrchestration|Security policy scheduled scans maximum top-level group concurrency"
-msgstr ""
-
msgid "SecurityOrchestration|SecurityOrchestration|Scan execution policies with more than %{maxCount} actions detected. Those policies will not work after GitLab 18.0 (May 15, 2025). Before then you must edit these policies to reduce the number of actions."
msgstr ""
diff --git a/patches/@vue+compat+3.5.13.patch b/patches/@vue+compat+3.5.13.patch
new file mode 100644
index 00000000000..bc279e20ab5
--- /dev/null
+++ b/patches/@vue+compat+3.5.13.patch
@@ -0,0 +1,27 @@
+diff --git a/node_modules/@vue/compat/dist/vue.cjs.js b/node_modules/@vue/compat/dist/vue.cjs.js
+index 5b4b617..1baafa5 100644
+--- a/node_modules/@vue/compat/dist/vue.cjs.js
++++ b/node_modules/@vue/compat/dist/vue.cjs.js
+@@ -10208,8 +10208,20 @@ function emit(instance, event, ...rawArgs) {
+ }
+ }
+ let args = rawArgs;
+- const isModelListener = event.startsWith("update:");
+- const modifiers = isModelListener && getModelModifiers(props, event.slice(7));
++
++ // This applies https://github.com/vuejs/core/pull/12654. Once that has been
++ // merged and we've upgraded to the version of @vue/compat that includes it,
++ // this patch can be removed.
++ let isModelListener;
++ let modifiers;
++ if (
++ (isModelListener = compatModelEventPrefix + event in props)
++ ) {
++ modifiers = props.modelModifiers
++ } else if ((isModelListener = event.startsWith('update:'))) {
++ modifiers = getModelModifiers(props, event.slice(7));
++ }
++
+ if (modifiers) {
+ if (modifiers.trim) {
+ args = rawArgs.map((a) => isString(a) ? a.trim() : a);
diff --git a/scripts/frontend/jest_ci.js b/scripts/frontend/jest_ci.js
index fe853063682..ff1d10eea7d 100755
--- a/scripts/frontend/jest_ci.js
+++ b/scripts/frontend/jest_ci.js
@@ -29,7 +29,10 @@ function parseArgumentsAndEnvironment() {
program
.usage('[options]')
.description(`Runs Jest under CI.`)
- .option('--vue3', 'Run tests under Vue 3 (via @vue/compat). The default is to run under Vue 2.')
+ .option(
+ '--vue3',
+ 'Run tests under Vue 3 (via @vue/compat). The default is to run under Vue 2. The VUE_VERSION environment variable must agree with this option.',
+ )
.option(
'--predictive',
'Only run specs affected by the changes in the merge request. The default is to run all specs.',
@@ -38,7 +41,10 @@ function parseArgumentsAndEnvironment() {
'--fixtures',
'Only run specs which rely on generated fixtures. The default is to only run specs which do not rely on generated fixtures.',
)
- .option('--coverage', 'Tell Jest to generate coverage. The default is not to.')
+ .option(
+ '--coverage',
+ "Tell Jest to generate coverage. If not specified, it's enabled only on non-FOSS branch or tag pipelines under Vue 2, non-predictive runs.",
+ )
.parse(process.argv);
if (!IS_CI) {
@@ -47,6 +53,20 @@ function parseArgumentsAndEnvironment() {
process.exit(1);
}
+ if (program.vue3 && process.env.VUE_VERSION !== '3') {
+ console.warn(
+ `Expected environment variable VUE_VERSION=3 given option '--vue3', got VUE_VERSION="${process.env.VUE_VERSION}".`,
+ );
+ process.exit(1);
+ }
+
+ if (!program.vue3 && ![undefined, '2'].includes(process.env.VUE_VERSION)) {
+ console.warn(
+ `Expected unset environment variable VUE_VERSION, or VUE_VERSION=2, got VUE_VERSION="${process.env.VUE_VERSION}".`,
+ );
+ process.exit(1);
+ }
+
const changedFiles = [];
if (program.predictive) {
const { RSPEC_MATCHING_JS_FILES_PATH, RSPEC_CHANGED_FILES_PATH } = process.env;
@@ -72,11 +92,18 @@ function parseArgumentsAndEnvironment() {
}
}
+ const coverage =
+ program.coverage ||
+ (!process.env.CI_MERGE_REQUEST_IID &&
+ !/^as-if-foss\//.test(process.env.CI_COMMIT_BRANCH) &&
+ !program.vue3 &&
+ !program.predictive);
+
return {
vue3: program.vue3,
predictive: program.predictive,
fixtures: program.fixtures,
- coverage: program.coverage,
+ coverage,
nodeIndex: process.env.CI_NODE_INDEX ?? '1',
nodeTotal: process.env.CI_NODE_TOTAL ?? '1',
changedFiles,
@@ -124,7 +151,6 @@ function runJest({ vue3, predictive, fixtures, coverage, nodeIndex, nodeTotal, c
env: {
...process.env,
...(fixtures ? { JEST_FIXTURE_JOBS_ONLY: '1' } : {}),
- ...(vue3 ? { VUE_VERSION: '3' } : {}),
},
},
);
diff --git a/scripts/frontend/quarantined_vue3_specs.txt b/scripts/frontend/quarantined_vue3_specs.txt
index 92bf9242274..a8c0e219fbf 100644
--- a/scripts/frontend/quarantined_vue3_specs.txt
+++ b/scripts/frontend/quarantined_vue3_specs.txt
@@ -3,7 +3,6 @@
ee/spec/frontend/access_tokens/components/expires_at_field_spec.js
ee/spec/frontend/admin/application_settings/general/components/license_dropzone_spec.js
ee/spec/frontend/admin/signup_restrictions/components/signup_form_spec.js
-ee/spec/frontend/admin/subscriptions/show/components/subscription_activation_form_spec.js
ee/spec/frontend/admin/subscriptions/show/components/subscription_breakdown_spec.js
ee/spec/frontend/ai/settings/components/duo_experiment_beta_features_form_spec.js
ee/spec/frontend/analytics/analytics_dashboards/components/analytics_dashboard_panel_spec.js
@@ -135,7 +134,6 @@ spec/frontend/ci/pipeline_editor/components/pipeline_editor_tabs_spec.js
spec/frontend/ci/pipeline_editor/pipeline_editor_app_spec.js
spec/frontend/ci/runner/components/registration/runner_instructions/runner_instructions_modal_spec.js
spec/frontend/ci/runner/components/runner_filtered_search_bar_spec.js
-spec/frontend/ci/runner/components/runner_form_fields_spec.js
spec/frontend/ci_settings_pipeline_triggers/components/edit_trigger_modal_spec.js
spec/frontend/clusters/agents/components/activity_history_item_spec.js
spec/frontend/clusters/agents/components/revoke_token_button_spec.js
@@ -220,9 +218,7 @@ spec/frontend/packages_and_registries/package_registry/pages/details_spec.js
spec/frontend/packages_and_registries/settings/group/components/forwarding_settings_spec.js
spec/frontend/packages_and_registries/settings/project/settings/components/cleanup_image_tags_spec.js
spec/frontend/packages_and_registries/settings/project/settings/components/container_expiration_policy_spec.js
-spec/frontend/packages_and_registries/settings/project/settings/components/container_protection_repository_rule_form_spec.js
spec/frontend/packages_and_registries/settings/project/settings/components/container_protection_repository_rules_spec.js
-spec/frontend/packages_and_registries/settings/project/settings/components/packages_protection_rule_form_spec.js
spec/frontend/packages_and_registries/settings/project/settings/components/packages_protection_rules_spec.js
spec/frontend/pages/projects/forks/new/components/fork_form_spec.js
spec/frontend/pages/projects/forks/new/components/project_namespace_spec.js
diff --git a/scripts/verify-tff-mapping b/scripts/verify-tff-mapping
index 2cc79af778f..17bf6fe518f 100755
--- a/scripts/verify-tff-mapping
+++ b/scripts/verify-tff-mapping
@@ -472,18 +472,6 @@ tests = [
## END Remote development GraphQL mutations
## BEGIN Remote development GraphQL resolvers (in alphabetical order by resolver source file path)
- {
- explanation: 'Map Remote Development GraphQL query root admin_workspaces_resolver.rb to request specs',
- changed_file: 'ee/app/graphql/resolvers/remote_development/admin_workspaces_resolver.rb',
- expected: %w[
- ee/spec/requests/api/graphql/remote_development/workspace/with_id_arg_spec.rb
- ee/spec/requests/api/graphql/remote_development/workspaces/with_actual_states_arg_spec.rb
- ee/spec/requests/api/graphql/remote_development/workspaces/with_agent_ids_arg_spec.rb
- ee/spec/requests/api/graphql/remote_development/workspaces/with_ids_arg_spec.rb
- ee/spec/requests/api/graphql/remote_development/workspaces/with_no_args_spec.rb
- ee/spec/requests/api/graphql/remote_development/workspaces/with_project_ids_arg_spec.rb
- ]
- },
{
explanation:
'Map Remote Development GraphQL cluster_agent/remote_development_agent_config_resolver.rb to request specs',
@@ -502,6 +490,7 @@ tests = [
ee/spec/requests/api/graphql/remote_development/cluster_agent/workspaces/with_ids_arg_spec.rb
ee/spec/requests/api/graphql/remote_development/cluster_agent/workspaces/with_no_args_spec.rb
ee/spec/requests/api/graphql/remote_development/cluster_agent/workspaces/with_project_ids_arg_spec.rb
+ ee/spec/requests/api/graphql/remote_development/workspace_variables/with_no_args_spec.rb
]
},
{
@@ -526,6 +515,19 @@ tests = [
]
# rubocop:enable Layout/LineLength
},
+ {
+ explanation: 'Map Remote Development GraphQL query root workspaces_admin_resolver.rb to request specs',
+ changed_file: 'ee/app/graphql/resolvers/remote_development/workspaces_admin_resolver.rb',
+ expected: %w[
+ ee/spec/requests/api/graphql/remote_development/workspace/with_id_arg_spec.rb
+ ee/spec/requests/api/graphql/remote_development/workspaces/with_actual_states_arg_spec.rb
+ ee/spec/requests/api/graphql/remote_development/workspaces/with_agent_ids_arg_spec.rb
+ ee/spec/requests/api/graphql/remote_development/workspaces/with_ids_arg_spec.rb
+ ee/spec/requests/api/graphql/remote_development/workspaces/with_no_args_spec.rb
+ ee/spec/requests/api/graphql/remote_development/workspaces/with_project_ids_arg_spec.rb
+ ee/spec/requests/api/graphql/remote_development/workspace_variables/with_no_args_spec.rb
+ ]
+ },
{
explanation: 'Map Remote Development GraphQL workspaces_resolver.rb to request specs',
changed_file: 'ee/app/graphql/resolvers/remote_development/workspaces_resolver.rb',
@@ -536,9 +538,12 @@ tests = [
ee/spec/requests/api/graphql/remote_development/current_user/workspaces/with_ids_arg_spec.rb
ee/spec/requests/api/graphql/remote_development/current_user/workspaces/with_no_args_spec.rb
ee/spec/requests/api/graphql/remote_development/current_user/workspaces/with_project_ids_arg_spec.rb
+ ee/spec/requests/api/graphql/remote_development/workspace_variables/with_no_args_spec.rb
]
},
+ ## END Remote development GraphQL resolvers
+ ## BEGIN Remote development GraphQL types
{
explanation: 'Map Remote Development GraphQL query root workspace type resolver to request specs',
changed_file: 'ee/app/graphql/types/remote_development/workspace_type.rb',
@@ -547,7 +552,37 @@ tests = [
ee/spec/requests/api/graphql/remote_development/workspace/with_id_arg_spec.rb
]
},
- ## END Remote development GraphQL resolvers
+ {
+ explanation: 'Map Remote Development GraphQL workspace_variable_type.rb to request specs',
+ changed_file: 'ee/app/graphql/types/remote_development/workspace_variable_type.rb',
+ expected: %w[
+ ee/spec/graphql/types/remote_development/workspace_variable_type_spec.rb
+ ee/spec/requests/api/graphql/remote_development/workspace_variables/with_no_args_spec.rb
+ ]
+ },
+ {
+ explanation: 'Map Remote Development GraphQL workspace_variable_input_type_enum.rb to request specs',
+ changed_file: 'ee/app/graphql/types/remote_development/workspace_variable_input.rb',
+ expected: %w[
+ ee/spec/graphql/types/remote_development/workspace_variable_input_spec.rb
+ ee/spec/requests/api/graphql/mutations/remote_development/workspace_operations/create_spec.rb
+ ]
+ },
+ {
+ explanation: 'Map Remote Development GraphQL workspace_variable_type_enum.rb to request specs',
+ changed_file: 'ee/app/graphql/types/remote_development/workspace_variable_type_enum.rb',
+ expected: %w[
+ ee/spec/requests/api/graphql/remote_development/workspace_variables/with_no_args_spec.rb
+ ]
+ },
+ {
+ explanation: 'Map Remote Development GraphQL workspace_variable_input_type_enum.rb to request specs',
+ changed_file: 'ee/app/graphql/types/remote_development/workspace_variable_input_type_enum.rb',
+ expected: %w[
+ ee/spec/requests/api/graphql/mutations/remote_development/workspace_operations/create_spec.rb
+ ]
+ },
+ ## END Remote development GraphQL types
{
explanation: 'https://gitlab.com/gitlab-org/gitlab/-/issues/466068#note_1987834618',
diff --git a/spec/db/schema_spec.rb b/spec/db/schema_spec.rb
index 3ba7a04f456..e682436fda7 100644
--- a/spec/db/schema_spec.rb
+++ b/spec/db/schema_spec.rb
@@ -420,7 +420,8 @@ RSpec.describe 'Database schema',
'ProjectAutoDevops' => %w[deploy_strategy],
'ResourceLabelEvent' => %w[action],
'User' => %w[layout dashboard project_view],
- 'Users::Callout' => %w[feature_name]
+ 'Users::Callout' => %w[feature_name],
+ 'Vulnerability' => %w[confidence] # this enum is in the process of being deprecated
}.freeze
end
diff --git a/spec/factories/deploy_tokens.rb b/spec/factories/deploy_tokens.rb
index d0a8a57102f..c53de4d7aeb 100644
--- a/spec/factories/deploy_tokens.rb
+++ b/spec/factories/deploy_tokens.rb
@@ -38,6 +38,7 @@ FactoryBot.define do
read_package_registry { true }
write_package_registry { true }
read_virtual_registry { true }
+ write_virtual_registry { true }
end
trait :dependency_proxy_scopes do
diff --git a/spec/finders/concerns/packages/finder_helper_spec.rb b/spec/finders/concerns/packages/finder_helper_spec.rb
index 07c3b95651c..08a03d81cc9 100644
--- a/spec/finders/concerns/packages/finder_helper_spec.rb
+++ b/spec/finders/concerns/packages/finder_helper_spec.rb
@@ -164,15 +164,15 @@ RSpec.describe ::Packages::FinderHelper, feature_category: :package_registry do
'PUBLIC' | 'PUBLIC' | 'PUBLIC' | :anonymous | 'returning both packages'
'PUBLIC' | 'PUBLIC' | 'PRIVATE' | :maintainer | 'returning both packages'
'PUBLIC' | 'PUBLIC' | 'PRIVATE' | :developer | 'returning both packages'
- 'PUBLIC' | 'PUBLIC' | 'PRIVATE' | :guest | 'returning package1'
+ 'PUBLIC' | 'PUBLIC' | 'PRIVATE' | :guest | 'returning both packages'
'PUBLIC' | 'PUBLIC' | 'PRIVATE' | :anonymous | 'returning package1'
'PUBLIC' | 'PRIVATE' | 'PRIVATE' | :maintainer | 'returning both packages'
'PUBLIC' | 'PRIVATE' | 'PRIVATE' | :developer | 'returning both packages'
- 'PUBLIC' | 'PRIVATE' | 'PRIVATE' | :guest | 'returning package1'
+ 'PUBLIC' | 'PRIVATE' | 'PRIVATE' | :guest | 'returning both packages'
'PUBLIC' | 'PRIVATE' | 'PRIVATE' | :anonymous | 'returning package1'
'PRIVATE' | 'PRIVATE' | 'PRIVATE' | :maintainer | 'returning both packages'
'PRIVATE' | 'PRIVATE' | 'PRIVATE' | :developer | 'returning both packages'
- 'PRIVATE' | 'PRIVATE' | 'PRIVATE' | :guest | 'returning no packages'
+ 'PRIVATE' | 'PRIVATE' | 'PRIVATE' | :guest | 'returning both packages'
'PRIVATE' | 'PRIVATE' | 'PRIVATE' | :anonymous | 'returning no packages'
end
@@ -211,6 +211,33 @@ RSpec.describe ::Packages::FinderHelper, feature_category: :package_registry do
it_behaves_like 'returning package1'
end
end
+
+ context 'when allow_guest_plus_roles_to_pull_packages is disabled' do
+ before_all do
+ group.add_guest(user)
+ subgroup.add_guest(user)
+ project1.add_guest(user)
+ project2.add_guest(user)
+ end
+
+ before do
+ stub_feature_flags(allow_guest_plus_roles_to_pull_packages: false)
+ project2.update!(visibility_level: Gitlab::VisibilityLevel.const_get(project2_visibility, false))
+ subgroup.update!(visibility_level: Gitlab::VisibilityLevel.const_get(subgroup_visibility, false))
+ project1.update!(visibility_level: Gitlab::VisibilityLevel.const_get(group_visibility, false))
+ group.update!(visibility_level: Gitlab::VisibilityLevel.const_get(group_visibility, false))
+ end
+
+ where(:group_visibility, :subgroup_visibility, :project2_visibility, :shared_example_name) do
+ 'PUBLIC' | 'PUBLIC' | 'PRIVATE' | 'returning package1'
+ 'PUBLIC' | 'PRIVATE' | 'PRIVATE' | 'returning package1'
+ 'PRIVATE' | 'PRIVATE' | 'PRIVATE' | 'returning no packages'
+ end
+
+ with_them do
+ it_behaves_like params[:shared_example_name]
+ end
+ end
end
context 'with a group deploy token' do
@@ -303,15 +330,15 @@ RSpec.describe ::Packages::FinderHelper, feature_category: :package_registry do
'PUBLIC' | 'PUBLIC' | 'PUBLIC' | :anonymous | 'returning both projects'
'PUBLIC' | 'PUBLIC' | 'PRIVATE' | :maintainer | 'returning both projects'
'PUBLIC' | 'PUBLIC' | 'PRIVATE' | :developer | 'returning both projects'
- 'PUBLIC' | 'PUBLIC' | 'PRIVATE' | :guest | 'returning project1'
+ 'PUBLIC' | 'PUBLIC' | 'PRIVATE' | :guest | 'returning both projects'
'PUBLIC' | 'PUBLIC' | 'PRIVATE' | :anonymous | 'returning project1'
'PUBLIC' | 'PRIVATE' | 'PRIVATE' | :maintainer | 'returning both projects'
'PUBLIC' | 'PRIVATE' | 'PRIVATE' | :developer | 'returning both projects'
- 'PUBLIC' | 'PRIVATE' | 'PRIVATE' | :guest | 'returning project1'
+ 'PUBLIC' | 'PRIVATE' | 'PRIVATE' | :guest | 'returning both projects'
'PUBLIC' | 'PRIVATE' | 'PRIVATE' | :anonymous | 'returning project1'
'PRIVATE' | 'PRIVATE' | 'PRIVATE' | :maintainer | 'returning both projects'
'PRIVATE' | 'PRIVATE' | 'PRIVATE' | :developer | 'returning both projects'
- 'PRIVATE' | 'PRIVATE' | 'PRIVATE' | :guest | 'returning no project'
+ 'PRIVATE' | 'PRIVATE' | 'PRIVATE' | :guest | 'returning both projects'
'PRIVATE' | 'PRIVATE' | 'PRIVATE' | :anonymous | 'returning no project'
end
diff --git a/spec/finders/packages/conan/package_finder_spec.rb b/spec/finders/packages/conan/package_finder_spec.rb
index 703d9ee1a64..44091424237 100644
--- a/spec/finders/packages/conan/package_finder_spec.rb
+++ b/spec/finders/packages/conan/package_finder_spec.rb
@@ -25,7 +25,7 @@ RSpec.describe ::Packages::Conan::PackageFinder, feature_category: :package_regi
:private | :maintainer | true
:private | :developer | true
:private | :reporter | true
- :private | :guest | false
+ :private | :guest | true
:private | :anonymous | false
:internal | :maintainer | true
@@ -98,6 +98,19 @@ RSpec.describe ::Packages::Conan::PackageFinder, feature_category: :package_regi
it { is_expected.to match_array([private_package]) }
end
end
+
+ context 'when allow_guest_plus_roles_to_pull_packages is disabled' do
+ before_all do
+ project.update_column(:visibility_level, Gitlab::VisibilityLevel.string_options['private'])
+ project.add_guest(user)
+ end
+
+ before do
+ stub_feature_flags(allow_guest_plus_roles_to_pull_packages: false)
+ end
+
+ it { is_expected.to eq([]) }
+ end
end
context 'with package user name' do
diff --git a/spec/finders/packages/group_packages_finder_spec.rb b/spec/finders/packages/group_packages_finder_spec.rb
index 143fef91e5d..9690d124f16 100644
--- a/spec/finders/packages/group_packages_finder_spec.rb
+++ b/spec/finders/packages/group_packages_finder_spec.rb
@@ -74,12 +74,12 @@ RSpec.describe Packages::GroupPackagesFinder, feature_category: :package_registr
:developer | :public | :private | :all
:maintainer | :public | :private | :all
:anonymous | :private | :enabled | :none
- :guest | :private | :enabled | :none
+ :guest | :private | :enabled | :all
:reporter | :private | :enabled | :all
:developer | :private | :enabled | :all
:maintainer | :private | :enabled | :all
:anonymous | :private | :private | :none
- :guest | :private | :private | :none
+ :guest | :private | :private | :all
:reporter | :private | :private | :all
:developer | :private | :private | :all
:maintainer | :private | :private | :all
@@ -117,6 +117,31 @@ RSpec.describe Packages::GroupPackagesFinder, feature_category: :package_registr
end
end
+ context 'when allow_guest_plus_roles_to_pull_packages is disabled' do
+ let(:add_user_to_group) { false }
+
+ before do
+ subgroup.update!(visibility: 'private')
+ group.update!(visibility: 'private')
+
+ project.add_guest(user)
+ subproject.add_guest(user)
+
+ stub_feature_flags(allow_guest_plus_roles_to_pull_packages: false)
+ end
+
+ %w[enabled private].each do |repository_visibility|
+ context "when repository visiblity #{repository_visibility}" do
+ before do
+ project.update!(visibility: 'private', repository_access_level: repository_visibility)
+ subproject.update!(visibility: 'private', repository_access_level: repository_visibility)
+ end
+
+ it { is_expected.to match_array([]) }
+ end
+ end
+ end
+
context 'deploy tokens' do
let(:add_user_to_group) { false }
diff --git a/spec/fixtures/api/schemas/public_api/v4/deploy_token.json b/spec/fixtures/api/schemas/public_api/v4/deploy_token.json
index 664740c2a3c..a52bae4666e 100644
--- a/spec/fixtures/api/schemas/public_api/v4/deploy_token.json
+++ b/spec/fixtures/api/schemas/public_api/v4/deploy_token.json
@@ -25,7 +25,15 @@
"scopes": {
"type": "array",
"items": {
- "type": "string"
+ "enum": [
+ "read_repository",
+ "read_registry",
+ "write_registry",
+ "read_package_registry",
+ "write_package_registry",
+ "read_virtual_registry",
+ "write_virtual_registry"
+ ]
}
},
"token": {
@@ -38,4 +46,4 @@
"type": "boolean"
}
}
-}
\ No newline at end of file
+}
diff --git a/spec/frontend/batch_comments/store/mutations_spec.js b/spec/frontend/batch_comments/store/mutations_spec.js
index e4e9e6f34d2..4c2d4923c46 100644
--- a/spec/frontend/batch_comments/store/mutations_spec.js
+++ b/spec/frontend/batch_comments/store/mutations_spec.js
@@ -1,21 +1,26 @@
+import { createTestingPinia } from '@pinia/testing';
import * as types from '~/batch_comments/stores/modules/batch_comments/mutation_types';
-import mutations from '~/batch_comments/stores/modules/batch_comments/mutations';
-import createState from '~/batch_comments/stores/modules/batch_comments/state';
+import { useBatchComments } from '~/batch_comments/store';
+import { useLegacyDiffs } from '~/diffs/stores/legacy_diffs';
+import { globalAccessorPlugin } from '~/pinia/plugins';
+import { useNotes } from '~/notes/store/legacy_notes';
-// eslint-disable-next-line jest/no-disabled-tests
-describe.skip('Batch comments mutations', () => {
- let state;
+describe('Batch comments mutations', () => {
+ let store;
beforeEach(() => {
- state = createState();
+ createTestingPinia({ stubActions: false, plugins: [globalAccessorPlugin] });
+ useLegacyDiffs();
+ useNotes();
+ store = useBatchComments();
});
describe(types.ADD_NEW_DRAFT, () => {
const draft = { id: 1, note: 'test' };
it('adds processed object into drafts array', () => {
- mutations[types.ADD_NEW_DRAFT](state, draft);
+ store[types.ADD_NEW_DRAFT](draft);
- expect(state.drafts).toEqual([
+ expect(store.drafts).toEqual([
{
...draft,
isDraft: true,
@@ -24,26 +29,26 @@ describe.skip('Batch comments mutations', () => {
});
it('sets `shouldAnimateReviewButton` to true if it is a first draft', () => {
- mutations[types.ADD_NEW_DRAFT](state, draft);
+ store[types.ADD_NEW_DRAFT](draft);
- expect(state.shouldAnimateReviewButton).toBe(true);
+ expect(store.shouldAnimateReviewButton).toBe(true);
});
it('does not set `shouldAnimateReviewButton` to true if it is not a first draft', () => {
- state.drafts.push({ id: 1 }, { id: 2 });
- mutations[types.ADD_NEW_DRAFT](state, { id: 2, note: 'test2' });
+ store.drafts.push({ id: 1 }, { id: 2 });
+ store[types.ADD_NEW_DRAFT]({ id: 2, note: 'test2' });
- expect(state.shouldAnimateReviewButton).toBe(false);
+ expect(store.shouldAnimateReviewButton).toBe(false);
});
});
describe(types.DELETE_DRAFT, () => {
it('removes draft from array by ID', () => {
- state.drafts.push({ id: 1 }, { id: 2 });
+ store.drafts.push({ id: 1 }, { id: 2 });
- mutations[types.DELETE_DRAFT](state, 1);
+ store[types.DELETE_DRAFT](1);
- expect(state.drafts).toEqual([{ id: 2 }]);
+ expect(store.drafts).toEqual([{ id: 2 }]);
});
});
@@ -51,9 +56,9 @@ describe.skip('Batch comments mutations', () => {
it('adds to processed drafts in state', () => {
const drafts = [{ id: 1 }, { id: 2 }];
- mutations[types.SET_BATCH_COMMENTS_DRAFTS](state, drafts);
+ store[types.SET_BATCH_COMMENTS_DRAFTS](drafts);
- expect(state.drafts).toEqual([
+ expect(store.drafts).toEqual([
{
id: 1,
isDraft: true,
@@ -68,39 +73,39 @@ describe.skip('Batch comments mutations', () => {
describe(types.REQUEST_PUBLISH_REVIEW, () => {
it('sets isPublishing to true', () => {
- mutations[types.REQUEST_PUBLISH_REVIEW](state);
+ store[types.REQUEST_PUBLISH_REVIEW]();
- expect(state.isPublishing).toBe(true);
+ expect(store.isPublishing).toBe(true);
});
});
describe(types.RECEIVE_PUBLISH_REVIEW_SUCCESS, () => {
it('sets isPublishing to false', () => {
- state.isPublishing = true;
+ store.isPublishing = true;
- mutations[types.RECEIVE_PUBLISH_REVIEW_SUCCESS](state);
+ store[types.RECEIVE_PUBLISH_REVIEW_SUCCESS]();
- expect(state.isPublishing).toBe(false);
+ expect(store.isPublishing).toBe(false);
});
});
describe(types.RECEIVE_PUBLISH_REVIEW_ERROR, () => {
it('updates isPublishing to false', () => {
- state.isPublishing = true;
+ store.isPublishing = true;
- mutations[types.RECEIVE_PUBLISH_REVIEW_ERROR](state);
+ store[types.RECEIVE_PUBLISH_REVIEW_ERROR]();
- expect(state.isPublishing).toBe(false);
+ expect(store.isPublishing).toBe(false);
});
});
describe(types.RECEIVE_DRAFT_UPDATE_SUCCESS, () => {
it('updates draft in store', () => {
- state.drafts.push({ id: 1 });
+ store.drafts.push({ id: 1 });
- mutations[types.RECEIVE_DRAFT_UPDATE_SUCCESS](state, { id: 1, note: 'test' });
+ store[types.RECEIVE_DRAFT_UPDATE_SUCCESS]({ id: 1, note: 'test' });
- expect(state.drafts).toEqual([
+ expect(store.drafts).toEqual([
{
id: 1,
note: 'test',
@@ -112,21 +117,21 @@ describe.skip('Batch comments mutations', () => {
describe(types.CLEAR_DRAFTS, () => {
it('clears drafts array', () => {
- state.drafts.push({ id: 1 });
+ store.drafts.push({ id: 1 });
- mutations[types.CLEAR_DRAFTS](state);
+ store[types.CLEAR_DRAFTS]();
- expect(state.drafts).toEqual([]);
+ expect(store.drafts).toEqual([]);
});
});
describe(types.SET_DRAFT_EDITING, () => {
it('sets draft editing mode', () => {
- state.drafts.push({ id: 1, isEditing: false });
+ store.drafts.push({ id: 1, isEditing: false });
- mutations[types.SET_DRAFT_EDITING](state, { draftId: 1, isEditing: true });
+ store[types.SET_DRAFT_EDITING]({ draftId: 1, isEditing: true });
- expect(state.drafts[0].isEditing).toBe(true);
+ expect(store.drafts[0].isEditing).toBe(true);
});
});
});
diff --git a/spec/lib/api/helpers/packages_helpers_spec.rb b/spec/lib/api/helpers/packages_helpers_spec.rb
index 21681280d0c..a615b972644 100644
--- a/spec/lib/api/helpers/packages_helpers_spec.rb
+++ b/spec/lib/api/helpers/packages_helpers_spec.rb
@@ -262,10 +262,8 @@ RSpec.describe API::Helpers::PackagesHelpers, feature_category: :package_registr
project.add_guest(user)
end
- it 'returns Forbidden' do
- expect(helper).to receive(:render_api_error!).with('403 Forbidden', 403)
-
- is_expected.to be_nil
+ it 'returns project' do
+ is_expected.to eq(project)
end
end
end
diff --git a/spec/lib/gitlab/audit/auditor_spec.rb b/spec/lib/gitlab/audit/auditor_spec.rb
index dd5b8823624..6230cd1601b 100644
--- a/spec/lib/gitlab/audit/auditor_spec.rb
+++ b/spec/lib/gitlab/audit/auditor_spec.rb
@@ -312,12 +312,11 @@ RSpec.describe Gitlab::Audit::Auditor, feature_category: :audit_events do
context 'when audit events are invalid' do
before do
- expect_next_instance_of(AuditEvent) do |instance|
- allow(instance).to receive(:save!).and_raise(ActiveRecord::RecordInvalid)
- end
allow(Gitlab::ErrorTracking).to receive(:track_exception)
end
+ let(:author) { build(:user) } # use non-persisted author (hence non-valid id)
+
it 'tracks error' do
audit!
diff --git a/spec/lib/gitlab/auth_spec.rb b/spec/lib/gitlab/auth_spec.rb
index b1df7cf55d2..06b33d5e9cb 100644
--- a/spec/lib/gitlab/auth_spec.rb
+++ b/spec/lib/gitlab/auth_spec.rb
@@ -37,6 +37,10 @@ RSpec.describe Gitlab::Auth, :use_clean_rails_memory_store_caching, feature_cate
it 'DEFAULT_SCOPES contains all default scopes' do
expect(subject::DEFAULT_SCOPES).to match_array [:api]
end
+
+ it 'VIRTUAL_REGISTRY_SCOPES contains all scopes for Virtual Registry access' do
+ expect(subject::VIRTUAL_REGISTRY_SCOPES).to match_array %i[read_virtual_registry write_virtual_registry]
+ end
end
describe 'available_scopes' do
@@ -227,6 +231,28 @@ RSpec.describe Gitlab::Auth, :use_clean_rails_memory_store_caching, feature_cate
end
end
end
+
+ context 'virtual_registry_scopes' do
+ context 'when dependency proxy and virtual registry are both disabled' do
+ before do
+ stub_config(dependency_proxy: { enabled: false })
+ end
+
+ it 'is empty' do
+ expect(subject.virtual_registry_scopes).to eq []
+ end
+ end
+
+ context 'when dependency proxy is enabled' do
+ before do
+ stub_config(dependency_proxy: { enabled: true })
+ end
+
+ it 'contains all virtual registry related scopes' do
+ expect(subject.virtual_registry_scopes).to eq %i[read_virtual_registry write_virtual_registry]
+ end
+ end
+ end
end
describe 'find_for_git_client' do
diff --git a/spec/lib/gitlab/ci/parsers/sbom/component_spec.rb b/spec/lib/gitlab/ci/parsers/sbom/component_spec.rb
index ecd48cd7242..5f56470a54a 100644
--- a/spec/lib/gitlab/ci/parsers/sbom/component_spec.rb
+++ b/spec/lib/gitlab/ci/parsers/sbom/component_spec.rb
@@ -38,30 +38,18 @@ RSpec.describe Gitlab::Ci::Parsers::Sbom::Component, feature_category: :dependen
data.merge!(license_info)
end
- context "when the feature flag `license_scanning_with_sbom_licenses` is enabled" do
- it "sets the license information" do
- is_expected.to be_kind_of(::Gitlab::Ci::Reports::Sbom::Component)
- expect(component.licenses.count).to eq(1)
- expect(component.licenses.first.name).to eq(license_name)
- end
-
- context "when the license is defined by an expression" do
- let(:license_info) do
- { "licenses" => [{ "expression" => "EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0" }] }
- end
-
- it "ignores the license" do
- expect(component.licenses).to be_empty
- end
- end
+ it "sets the license information" do
+ is_expected.to be_kind_of(::Gitlab::Ci::Reports::Sbom::Component)
+ expect(component.licenses.count).to eq(1)
+ expect(component.licenses.first.name).to eq(license_name)
end
- context "when the feature flag `license_scanning_with_sbom_licenses` is disabled" do
- before do
- stub_feature_flags(license_scanning_with_sbom_licenses: false)
+ context "when the license is defined by an expression" do
+ let(:license_info) do
+ { "licenses" => [{ "expression" => "EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0" }] }
end
- it "does not includes the license information" do
+ it "ignores the license" do
expect(component.licenses).to be_empty
end
end
diff --git a/spec/migrations/20250114194610_backfill_user_provided_workspace_variables_spec.rb b/spec/migrations/20250114194610_backfill_user_provided_workspace_variables_spec.rb
new file mode 100644
index 00000000000..eaa67992b0d
--- /dev/null
+++ b/spec/migrations/20250114194610_backfill_user_provided_workspace_variables_spec.rb
@@ -0,0 +1,119 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require_migration!
+
+RSpec.describe BackfillUserProvidedWorkspaceVariables, feature_category: :workspaces do
+ let(:user) { table(:users).create!(name: 'test-user', email: 'test@example.com', projects_limit: 5) }
+ let(:organization) { table(:organizations).create!(name: 'test-org', path: 'default') }
+ let(:namespace) { table(:namespaces).create!(name: 'name', path: 'path', organization_id: organization.id) }
+ let(:workspace_variables) { table(:workspace_variables) }
+
+ let(:project) do
+ table(:projects).create!(namespace_id: namespace.id, project_namespace_id: namespace.id,
+ organization_id: organization.id)
+ end
+
+ let!(:personal_access_token) do
+ table(:personal_access_tokens).create!(
+ user_id: user.id,
+ name: 'token_name',
+ organization_id: organization.id,
+ expires_at: Time.now
+ )
+ end
+
+ let(:cluster_agent) { table(:cluster_agents).create!(name: 'remotedev', project_id: project.id) }
+
+ let!(:agent) do
+ table(:workspaces_agent_configs).create!(
+ cluster_agent_id: cluster_agent.id,
+ enabled: true,
+ dns_zone: 'test.workspace.me',
+ project_id: project.id
+ )
+ end
+
+ let!(:agent_config_version) do
+ table(:workspaces_agent_config_versions).create!(
+ project_id: project.id,
+ item_id: agent.id,
+ item_type: 'RemoteDevelopment::WorkspacesAgentConfig',
+ event: 'create'
+ )
+ end
+
+ let!(:workspace) do
+ table(:workspaces).create!(
+ user_id: user.id,
+ project_id: project.id,
+ cluster_agent_id: cluster_agent.id,
+ desired_state_updated_at: Time.now,
+ responded_to_agent_at: Time.now,
+ name: 'workspace-1',
+ namespace: 'workspace_1_namespace',
+ desired_state: 'Running',
+ actual_state: 'Running',
+ project_ref: 'devfile-ref',
+ devfile_path: 'devfile-path',
+ devfile: 'devfile',
+ processed_devfile: 'processed_dev_file',
+ url: 'workspace-url',
+ deployment_resource_version: 'v1',
+ personal_access_token_id: personal_access_token.id,
+ max_hours_before_termination: 5760,
+ workspaces_agent_config_version: agent_config_version.id,
+ desired_config_generator_version: 3
+ )
+ end
+
+ let!(:workspace_static_file_variable) do
+ workspace_variables.create!(
+ workspace_id: workspace.id,
+ project_id: project.id,
+ key: 'gl_token',
+ variable_type: 1,
+ encrypted_value: 'encrypted_value',
+ encrypted_value_iv: 'encrypted_value_iv'
+ )
+ end
+
+ let!(:workspace_static_env_variable) do
+ workspace_variables.create!(
+ workspace_id: workspace.id,
+ project_id: project.id,
+ key: 'GIT_CONFIG_COUNT',
+ variable_type: 0,
+ encrypted_value: 'encrypted_value',
+ encrypted_value_iv: 'encrypted_value_iv'
+ )
+ end
+
+ let!(:workspace_user_provided_variable) do
+ workspace_variables.create!(
+ workspace_id: workspace.id,
+ project_id: project.id,
+ key: 'variable_key',
+ variable_type: 0,
+ encrypted_value: 'encrypted_value',
+ encrypted_value_iv: 'encrypted_value_iv'
+ )
+ end
+
+ it 'sets user_provided to true for all non-internal environment variables in the table' do
+ reversible_migration do |migration|
+ migration.before -> {
+ expect(workspace_variables.pluck(:user_provided)).to all(be false)
+ }
+
+ migration.after -> {
+ user_provided_variable = workspace_variables.where(variable_type: described_class::VARIABLE_ENV_TYPE)
+ .where.not(key: described_class::WORKSPACE_INTERNAL_VARIABLES).first
+
+ expect(workspace_static_file_variable.user_provided).to be(false)
+ expect(workspace_static_env_variable.user_provided).to be(false)
+ expect(user_provided_variable.user_provided).to be(true)
+ }
+ end
+ end
+end
diff --git a/spec/migrations/db/post_migrate/20250114213926_finalize_migrate_software_license_without_spdx_identifier_to_custom_licenses_spec.rb b/spec/migrations/db/post_migrate/20250114213926_finalize_migrate_software_license_without_spdx_identifier_to_custom_licenses_spec.rb
new file mode 100644
index 00000000000..58fc36f51cc
--- /dev/null
+++ b/spec/migrations/db/post_migrate/20250114213926_finalize_migrate_software_license_without_spdx_identifier_to_custom_licenses_spec.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require_migration!
+
+RSpec.describe FinalizeMigrateSoftwareLicenseWithoutSpdxIdentifierToCustomLicenses, feature_category: :security_policy_management do
+ it 'finalizes FinalizeMigrateRemainingSoftwareLicenseWithoutSpdxIdentifierToCustomLicenses migration' do
+ expect_next_instance_of(described_class) do |instance|
+ expect(instance).to receive(:ensure_batched_background_migration_is_finished).with(
+ job_class_name: 'MigrateRemainingSoftwareLicenseWithoutSpdxIdentifierToCustomLicenses',
+ table_name: :software_license_policies,
+ column_name: :id,
+ job_arguments: [],
+ finalize: true
+ )
+ end
+
+ migrate!
+ end
+end
diff --git a/spec/policies/clusters/agent_policy_spec.rb b/spec/policies/clusters/agent_policy_spec.rb
index b3c43647a84..05ce9845c02 100644
--- a/spec/policies/clusters/agent_policy_spec.rb
+++ b/spec/policies/clusters/agent_policy_spec.rb
@@ -3,7 +3,7 @@
require 'spec_helper'
RSpec.describe Clusters::AgentPolicy do
- let(:cluster_agent) { create(:cluster_agent, name: 'agent' ) }
+ let(:cluster_agent) { create(:cluster_agent, name: 'agent') }
let(:user) { create(:admin) }
let(:policy) { described_class.new(user, cluster_agent) }
let(:project) { cluster_agent.project }
diff --git a/spec/policies/group_policy_spec.rb b/spec/policies/group_policy_spec.rb
index da404305aa4..e7596f6310f 100644
--- a/spec/policies/group_policy_spec.rb
+++ b/spec/policies/group_policy_spec.rb
@@ -1190,13 +1190,29 @@ RSpec.describe GroupPolicy, feature_category: :system_access do
context 'with planner' do
let(:current_user) { planner }
- it { is_expected.to be_disallowed(:read_package) }
+ it { is_expected.to be_allowed(:read_package) }
+
+ context 'when allow_guest_plus_roles_to_pull_packages is disabled' do
+ before do
+ stub_feature_flags(allow_guest_plus_roles_to_pull_packages: false)
+ end
+
+ it { is_expected.to be_disallowed(:read_package) }
+ end
end
context 'with guest' do
let(:current_user) { guest }
- it { is_expected.to be_disallowed(:read_package) }
+ it { is_expected.to be_allowed(:read_package) }
+
+ context 'when allow_guest_plus_roles_to_pull_packages is disabled' do
+ before do
+ stub_feature_flags(allow_guest_plus_roles_to_pull_packages: false)
+ end
+
+ it { is_expected.to be_disallowed(:read_package) }
+ end
end
context 'with non member' do
diff --git a/spec/policies/packages/policies/group_policy_spec.rb b/spec/policies/packages/policies/group_policy_spec.rb
index 165984dea1d..8c0bf1b4894 100644
--- a/spec/policies/packages/policies/group_policy_spec.rb
+++ b/spec/policies/packages/policies/group_policy_spec.rb
@@ -41,7 +41,15 @@ RSpec.describe Packages::Policies::GroupPolicy, feature_category: :package_regis
context 'with guest' do
let(:current_user) { guest }
- it { is_expected.to be_disallowed(:read_package) }
+ it { is_expected.to be_allowed(:read_package) }
+
+ context 'when allow_guest_plus_roles_to_pull_packages is disabled' do
+ before do
+ stub_feature_flags(allow_guest_plus_roles_to_pull_packages: false)
+ end
+
+ it { is_expected.to be_disallowed(:read_package) }
+ end
end
context 'with non member' do
diff --git a/spec/policies/packages/policies/project_policy_spec.rb b/spec/policies/packages/policies/project_policy_spec.rb
index 96714123d08..d624830a8bb 100644
--- a/spec/policies/packages/policies/project_policy_spec.rb
+++ b/spec/policies/packages/policies/project_policy_spec.rb
@@ -48,7 +48,7 @@ RSpec.describe Packages::Policies::ProjectPolicy, feature_category: :package_reg
ref(:private_project) | ProjectFeature::PRIVATE | ref(:anonymous) | false
ref(:private_project) | ProjectFeature::PRIVATE | ref(:non_member) | false
- ref(:private_project) | ProjectFeature::PRIVATE | ref(:guest) | false
+ ref(:private_project) | ProjectFeature::PRIVATE | ref(:guest) | true
ref(:private_project) | ProjectFeature::PRIVATE | ref(:reporter) | true
ref(:private_project) | ProjectFeature::PRIVATE | ref(:developer) | true
ref(:private_project) | ProjectFeature::PRIVATE | ref(:maintainer) | true
@@ -122,6 +122,17 @@ RSpec.describe Packages::Policies::ProjectPolicy, feature_category: :package_reg
end
end
+ context 'when allow_guest_plus_roles_to_pull_packages is disabled' do
+ let(:project) { private_project }
+ let(:current_user) { guest }
+
+ before do
+ stub_feature_flags(allow_guest_plus_roles_to_pull_packages: false)
+ end
+
+ it { is_expected.to be_disallowed(:read_package) }
+ end
+
context 'with admin' do
let(:current_user) { admin }
diff --git a/spec/policies/project_policy_spec.rb b/spec/policies/project_policy_spec.rb
index b38c391803d..b988cbf349b 100644
--- a/spec/policies/project_policy_spec.rb
+++ b/spec/policies/project_policy_spec.rb
@@ -1698,6 +1698,8 @@ RSpec.describe ProjectPolicy, feature_category: :system_access do
end
describe 'read_package' do
+ using RSpec::Parameterized::TableSyntax
+
context 'with admin' do
let(:current_user) { admin }
@@ -1706,11 +1708,39 @@ RSpec.describe ProjectPolicy, feature_category: :system_access do
it_behaves_like 'package access with repository disabled'
end
- %w[anonymous non_member guest planner reporter developer maintainer owner].each do |role|
- context "with #{role}" do
- let(:current_user) { send(role) }
+ where(:project, :role, :allowed) do
+ ref(:public_project) | :anonymous | true
+ ref(:public_project) | :non_member | true
+ ref(:public_project) | :guest | true
- it { is_expected.to be_allowed(:read_package) }
+ ref(:private_project) | :anonymous | false
+ ref(:private_project) | :non_member | false
+ ref(:private_project) | :guest | true
+ end
+
+ with_them do
+ let(:current_user) { send(role) }
+
+ it do
+ expect(subject.can?(:read_package)).to be(allowed)
+ end
+ end
+
+ context 'with private project' do
+ let(:project) { private_project }
+
+ context 'when allow_guest_plus_roles_to_pull_packages is disabled' do
+ before do
+ stub_feature_flags(allow_guest_plus_roles_to_pull_packages: false)
+ end
+
+ %w[guest planner].each do |role|
+ context "with #{role}" do
+ let(:current_user) { send(role) }
+
+ it { is_expected.to be_disallowed(:read_package) }
+ end
+ end
end
end
end
diff --git a/spec/presenters/ci/build_presenter_spec.rb b/spec/presenters/ci/build_presenter_spec.rb
index 2d3f4f44b54..8f0a35f0ac2 100644
--- a/spec/presenters/ci/build_presenter_spec.rb
+++ b/spec/presenters/ci/build_presenter_spec.rb
@@ -129,7 +129,7 @@ RSpec.describe Ci::BuildPresenter do
context 'when variable is stored in ci_trigger_requests.variables' do
before do
- trigger_request.update_attribute(:variables, { 'TRIGGER_KEY_1' => 'TRIGGER_VALUE_1' } )
+ trigger_request.update_attribute(:variables, { 'TRIGGER_KEY_1' => 'TRIGGER_VALUE_1' })
end
it 'returns variables' do
diff --git a/spec/presenters/packages/conan/package_presenter_spec.rb b/spec/presenters/packages/conan/package_presenter_spec.rb
index 71e10e0c254..618f2014f16 100644
--- a/spec/presenters/packages/conan/package_presenter_spec.rb
+++ b/spec/presenters/packages/conan/package_presenter_spec.rb
@@ -51,7 +51,7 @@ RSpec.describe ::Packages::Conan::PackagePresenter, feature_category: :package_r
it { is_expected.to eq(expected_result) }
context 'when there are multiple channels for the same package' do
- let(:conan_metadatum) { create(:conan_metadatum, package_channel: 'newest' ) }
+ let(:conan_metadatum) { create(:conan_metadatum, package_channel: 'newest') }
let!(:newest_package) { create(:conan_package, name: package.name, version: package.version, project: project, conan_metadatum: conan_metadatum) }
it { is_expected.to eq(expected_result) }
diff --git a/spec/requests/api/composer_packages_spec.rb b/spec/requests/api/composer_packages_spec.rb
index 37488e81fe3..9f5a58a6d64 100644
--- a/spec/requests/api/composer_packages_spec.rb
+++ b/spec/requests/api/composer_packages_spec.rb
@@ -51,9 +51,9 @@ RSpec.describe API::ComposerPackages, feature_category: :package_registry do
'PRIVATE' | :developer | :user | true | true
'PRIVATE' | :developer | :user | false | false # Anonymous User - fallback
'PRIVATE' | :developer | :job | true | true
- 'PRIVATE' | :guest | :user | true | false
+ 'PRIVATE' | :guest | :user | true | true
'PRIVATE' | :guest | :user | false | false # Anonymous User - fallback
- 'PRIVATE' | :guest | :job | true | false
+ 'PRIVATE' | :guest | :job | true | true
'PRIVATE' | nil | :user | true | false
'PRIVATE' | nil | :user | false | false # Anonymous User - fallback
'PRIVATE' | nil | :job | true | false
@@ -82,9 +82,9 @@ RSpec.describe API::ComposerPackages, feature_category: :package_registry do
:PRIVATE | :developer | :user | true | :success | true
:PRIVATE | :developer | :user | false | :unauthorized | false
:PRIVATE | :developer | :job | true | :success | false # Anonymous User - fallback
- :PRIVATE | :guest | :user | true | :success | false
+ :PRIVATE | :guest | :user | true | :success | true
:PRIVATE | :guest | :user | false | :unauthorized | false
- :PRIVATE | :guest | :job | true | :success | false # Anonymous User - fallback
+ :PRIVATE | :guest | :job | true | :success | false
:PRIVATE | nil | :user | true | :success | false
:PRIVATE | nil | :user | false | :unauthorized | false
:PRIVATE | nil | nil | nil | :success | false # Anonymous User
@@ -110,9 +110,9 @@ RSpec.describe API::ComposerPackages, feature_category: :package_registry do
:developer | :user | true | 'Composer package index' | :success | true
:developer | :user | false | 'process Composer api request' | :unauthorized | false
:developer | :job | true | 'Composer package index' | :success | true
- :guest | :user | true | 'Composer package index' | :success | false
+ :guest | :user | true | 'Composer package index' | :success | true
:guest | :user | false | 'process Composer api request' | :unauthorized | false
- :guest | :job | true | 'Composer package index' | :success | false
+ :guest | :job | true | 'Composer package index' | :success | true
nil | :user | true | 'Composer package index' | :not_found | false
nil | :user | false | 'process Composer api request' | :unauthorized | false
nil | :job | true | 'Composer package index' | :not_found | false
@@ -131,7 +131,7 @@ RSpec.describe API::ComposerPackages, feature_category: :package_registry do
:developer | :user | true | 'Composer package index' | :success | true
:developer | :user | false | 'process Composer api request' | :unauthorized | false
:developer | :job | true | 'process Composer api request' | :unauthorized | false
- :guest | :user | true | 'Composer package index' | :success | false
+ :guest | :user | true | 'Composer package index' | :success | true
:guest | :user | false | 'process Composer api request' | :unauthorized | false
:guest | :job | true | 'process Composer api request' | :unauthorized | false
nil | :user | true | 'Composer package index' | :not_found | false
@@ -175,9 +175,9 @@ RSpec.describe API::ComposerPackages, feature_category: :package_registry do
'PRIVATE' | :developer | :user | true | 'Composer provider index' | :success
'PRIVATE' | :developer | :user | false | 'process Composer api request' | :unauthorized
'PRIVATE' | :developer | :job | true | 'Composer provider index' | :success
- 'PRIVATE' | :guest | :user | true | 'Composer empty provider index' | :success
+ 'PRIVATE' | :guest | :user | true | 'Composer provider index' | :success
'PRIVATE' | :guest | :user | false | 'process Composer api request' | :unauthorized
- 'PRIVATE' | :guest | :job | true | 'Composer empty provider index' | :success
+ 'PRIVATE' | :guest | :job | true | 'Composer provider index' | :success
'PRIVATE' | nil | :user | true | 'process Composer api request' | :not_found
'PRIVATE' | nil | :user | false | 'process Composer api request' | :unauthorized
'PRIVATE' | nil | :job | true | 'process Composer api request' | :not_found
@@ -206,7 +206,7 @@ RSpec.describe API::ComposerPackages, feature_category: :package_registry do
'PRIVATE' | :developer | :user | true | 'Composer provider index' | :success
'PRIVATE' | :developer | :user | false | 'process Composer api request' | :unauthorized
'PRIVATE' | :developer | :job | true | 'process Composer api request' | :unauthorized
- 'PRIVATE' | :guest | :user | true | 'Composer empty provider index' | :success
+ 'PRIVATE' | :guest | :user | true | 'Composer provider index' | :success
'PRIVATE' | :guest | :user | false | 'process Composer api request' | :unauthorized
'PRIVATE' | :guest | :job | true | 'process Composer api request' | :unauthorized
'PRIVATE' | nil | :user | true | 'process Composer api request' | :not_found
@@ -259,9 +259,9 @@ RSpec.describe API::ComposerPackages, feature_category: :package_registry do
'PRIVATE' | :developer | :user | true | 'Composer package api request' | :success
'PRIVATE' | :developer | :user | false | 'process Composer api request' | :unauthorized
'PRIVATE' | :developer | :job | true | 'Composer package api request' | :success
- 'PRIVATE' | :guest | :user | true | 'process Composer api request' | :not_found
+ 'PRIVATE' | :guest | :user | true | 'Composer package api request' | :success
'PRIVATE' | :guest | :user | false | 'process Composer api request' | :unauthorized
- 'PRIVATE' | :guest | :job | true | 'process Composer api request' | :not_found
+ 'PRIVATE' | :guest | :job | true | 'Composer package api request' | :success
'PRIVATE' | nil | :user | true | 'process Composer api request' | :not_found
'PRIVATE' | nil | :user | false | 'process Composer api request' | :unauthorized
'PRIVATE' | nil | :job | true | 'process Composer api request' | :not_found
@@ -290,7 +290,7 @@ RSpec.describe API::ComposerPackages, feature_category: :package_registry do
'PRIVATE' | :developer | :user | true | 'Composer package api request' | :success
'PRIVATE' | :developer | :user | false | 'process Composer api request' | :unauthorized
'PRIVATE' | :developer | :job | true | 'process Composer api request' | :unauthorized
- 'PRIVATE' | :guest | :user | true | 'process Composer api request' | :not_found
+ 'PRIVATE' | :guest | :user | true | 'Composer package api request' | :success
'PRIVATE' | :guest | :user | false | 'process Composer api request' | :unauthorized
'PRIVATE' | :guest | :job | true | 'process Composer api request' | :unauthorized
'PRIVATE' | nil | :user | true | 'process Composer api request' | :not_found
@@ -350,9 +350,9 @@ RSpec.describe API::ComposerPackages, feature_category: :package_registry do
'PRIVATE' | :developer | :user | true | 'Composer package api request' | :success
'PRIVATE' | :developer | :user | false | 'process Composer api request' | :unauthorized
'PRIVATE' | :developer | :job | true | 'Composer package api request' | :success
- 'PRIVATE' | :guest | :user | true | 'process Composer api request' | :not_found
+ 'PRIVATE' | :guest | :user | true | 'Composer package api request' | :success
'PRIVATE' | :guest | :user | false | 'process Composer api request' | :unauthorized
- 'PRIVATE' | :guest | :job | true | 'process Composer api request' | :not_found
+ 'PRIVATE' | :guest | :job | true | 'Composer package api request' | :success
'PRIVATE' | nil | :user | true | 'process Composer api request' | :not_found
'PRIVATE' | nil | :user | false | 'process Composer api request' | :unauthorized
'PRIVATE' | nil | :job | true | 'process Composer api request' | :not_found
@@ -381,7 +381,7 @@ RSpec.describe API::ComposerPackages, feature_category: :package_registry do
'PRIVATE' | :developer | :user | true | 'Composer package api request' | :success
'PRIVATE' | :developer | :user | false | 'process Composer api request' | :unauthorized
'PRIVATE' | :developer | :job | true | 'process Composer api request' | :unauthorized
- 'PRIVATE' | :guest | :user | true | 'process Composer api request' | :not_found
+ 'PRIVATE' | :guest | :user | true | 'Composer package api request' | :success
'PRIVATE' | :guest | :user | false | 'process Composer api request' | :unauthorized
'PRIVATE' | :guest | :job | true | 'process Composer api request' | :unauthorized
'PRIVATE' | nil | :user | true | 'process Composer api request' | :not_found
@@ -602,9 +602,9 @@ RSpec.describe API::ComposerPackages, feature_category: :package_registry do
'PRIVATE' | :developer | :user | true | :success
'PRIVATE' | :developer | :user | false | :unauthorized
'PRIVATE' | :developer | :job | true | :success
- 'PRIVATE' | :guest | :user | true | :forbidden
+ 'PRIVATE' | :guest | :user | true | :success
'PRIVATE' | :guest | :user | false | :unauthorized
- 'PRIVATE' | :guest | :job | true | :forbidden
+ 'PRIVATE' | :guest | :job | true | :success
'PRIVATE' | nil | :user | true | :not_found
'PRIVATE' | nil | :user | false | :unauthorized
'PRIVATE' | nil | :job | true | :not_found
@@ -660,7 +660,7 @@ RSpec.describe API::ComposerPackages, feature_category: :package_registry do
'PRIVATE' | :developer | :user | true | :success
'PRIVATE' | :developer | :user | false | :unauthorized
'PRIVATE' | :developer | :job | true | :unauthorized
- 'PRIVATE' | :guest | :user | true | :forbidden
+ 'PRIVATE' | :guest | :user | true | :success
'PRIVATE' | :guest | :user | false | :unauthorized
'PRIVATE' | :guest | :job | true | :unauthorized
'PRIVATE' | nil | :user | true | :not_found
diff --git a/spec/requests/api/deploy_tokens_spec.rb b/spec/requests/api/deploy_tokens_spec.rb
index 2f215cd5bd1..6820c325c9b 100644
--- a/spec/requests/api/deploy_tokens_spec.rb
+++ b/spec/requests/api/deploy_tokens_spec.rb
@@ -386,16 +386,38 @@ RSpec.describe API::DeployTokens, :aggregate_failures, feature_category: :contin
send(entity).send("add_#{authorized_role}", user)
end
- it 'creates the deploy token' do
- expect { subject }.to change { DeployToken.count }.by(1)
+ ::DeployToken::AVAILABLE_SCOPES.map(&:to_s).each do |scope|
+ context "with valid scope #{scope}" do
+ before do
+ params[:scopes] = [scope.to_sym]
+ end
- expect(response).to have_gitlab_http_status(:created)
- expect(response).to match_response_schema('public_api/v4/deploy_token')
- expect(json_response['name']).to eq('Foo')
- expect(json_response['scopes']).to eq(['read_repository'])
- expect(json_response['username']).to eq('Bar')
- expect(json_response['expires_at'].to_time.to_i).to eq(expires_time.to_i)
- expect(json_response['token']).to match(/gldt-[A-Za-z0-9_-]{20}/)
+ it 'creates the deploy token' do
+ expect { subject }.to change { DeployToken.count }.by(1)
+
+ expect(response).to have_gitlab_http_status(:created)
+ expect(response).to match_response_schema('public_api/v4/deploy_token')
+ expect(json_response['name']).to eq('Foo')
+ expect(json_response['scopes']).to eq([scope])
+ expect(json_response['username']).to eq('Bar')
+ expect(json_response['expires_at'].to_time.to_i).to eq(expires_time.to_i)
+ expect(json_response['token']).to match(/gldt-[A-Za-z0-9_-]{20}/)
+ end
+ end
+
+ context 'with all scopes' do
+ before do
+ params[:scopes] = ::DeployToken::AVAILABLE_SCOPES
+ end
+
+ it 'creates the deploy token with all scopes' do
+ expect { subject }.to change { DeployToken.count }.by(1)
+
+ expect(response).to have_gitlab_http_status(:created)
+ expect(response).to match_response_schema('public_api/v4/deploy_token')
+ expect(json_response['scopes']).to eq(::DeployToken::AVAILABLE_SCOPES.map(&:to_s))
+ end
+ end
end
context 'with no optional params given' do
diff --git a/spec/requests/api/generic_packages_spec.rb b/spec/requests/api/generic_packages_spec.rb
index 6c8ae0b053f..61e22553f34 100644
--- a/spec/requests/api/generic_packages_spec.rb
+++ b/spec/requests/api/generic_packages_spec.rb
@@ -771,9 +771,9 @@ RSpec.describe API::GenericPackages, feature_category: :package_registry do
'PUBLIC' | :guest | false | :invalid_user_basic_auth | :success
'PUBLIC' | :anonymous | false | :none | :success
'PRIVATE' | :developer | true | :personal_access_token | :success
- 'PRIVATE' | :guest | true | :personal_access_token | :forbidden
+ 'PRIVATE' | :guest | true | :personal_access_token | :success
'PRIVATE' | :developer | true | :user_basic_auth | :success
- 'PRIVATE' | :guest | true | :user_basic_auth | :forbidden
+ 'PRIVATE' | :guest | true | :user_basic_auth | :success
'PRIVATE' | :developer | true | :invalid_personal_access_token | :unauthorized
'PRIVATE' | :guest | true | :invalid_personal_access_token | :unauthorized
'PRIVATE' | :developer | true | :invalid_user_basic_auth | :unauthorized
diff --git a/spec/requests/api/graphql/packages/package_spec.rb b/spec/requests/api/graphql/packages/package_spec.rb
index ebf97480187..4054d848b0d 100644
--- a/spec/requests/api/graphql/packages/package_spec.rb
+++ b/spec/requests/api/graphql/packages/package_spec.rb
@@ -42,32 +42,38 @@ RSpec.describe 'package details', feature_category: :package_registry do
subject { post_graphql(query, current_user: user) }
- context 'with unauthorized user' do
+ context 'when allow_guest_plus_roles_to_pull_packages is disabled' do
before do
- project.update!(visibility_level: Gitlab::VisibilityLevel::PRIVATE)
- project.add_guest(user)
+ stub_feature_flags(allow_guest_plus_roles_to_pull_packages: false)
end
- it 'returns no packages' do
- subject
-
- expect(graphql_data_at(:package)).to be_nil
- end
-
- context 'with access to package registry for everyone' do
+ context 'with unauthorized user' do
before do
- project.project_feature.update!(package_registry_access_level: ProjectFeature::PUBLIC)
+ project.update!(visibility_level: Gitlab::VisibilityLevel::PRIVATE)
+ project.add_guest(user)
+ end
+
+ it 'returns no packages' do
subject
+
+ expect(graphql_data_at(:package)).to be_nil
end
- it_behaves_like 'a working graphql query' do
- it 'matches the JSON schema' do
- expect(package_details).to match_schema('graphql/packages/package_details')
+ context 'with access to package registry for everyone' do
+ before do
+ project.project_feature.update!(package_registry_access_level: ProjectFeature::PUBLIC)
+ subject
end
- end
- it '`public_package` returns true' do
- expect(graphql_data_at(:package, :public_package)).to eq(true)
+ it_behaves_like 'a working graphql query' do
+ it 'matches the JSON schema' do
+ expect(package_details).to match_schema('graphql/packages/package_details')
+ end
+ end
+
+ it '`public_package` returns true' do
+ expect(graphql_data_at(:package, :public_package)).to eq(true)
+ end
end
end
end
diff --git a/spec/requests/api/group_packages_spec.rb b/spec/requests/api/group_packages_spec.rb
index e5566bae914..2f4a0ed7db9 100644
--- a/spec/requests/api/group_packages_spec.rb
+++ b/spec/requests/api/group_packages_spec.rb
@@ -82,7 +82,7 @@ RSpec.describe API::GroupPackages, feature_category: :package_registry do
it_behaves_like 'returns packages', :group, :maintainer
it_behaves_like 'returns packages', :group, :developer
it_behaves_like 'returns packages', :group, :reporter
- it_behaves_like 'rejects packages access', :group, :guest, :forbidden
+ it_behaves_like 'returns packages', :group, :guest
context 'with subgroup' do
let(:subgroup) { create(:group, :private, parent: group) }
@@ -93,7 +93,7 @@ RSpec.describe API::GroupPackages, feature_category: :package_registry do
it_behaves_like 'returns packages with subgroups', :group, :maintainer
it_behaves_like 'returns packages with subgroups', :group, :developer
it_behaves_like 'returns packages with subgroups', :group, :reporter
- it_behaves_like 'rejects packages access', :group, :guest, :forbidden
+ it_behaves_like 'returns packages with subgroups', :group, :guest
context 'excluding subgroup' do
let(:url) { "/groups/#{group.id}/packages?exclude_subgroups=true" }
@@ -102,7 +102,7 @@ RSpec.describe API::GroupPackages, feature_category: :package_registry do
it_behaves_like 'returns packages', :group, :maintainer
it_behaves_like 'returns packages', :group, :developer
it_behaves_like 'returns packages', :group, :reporter
- it_behaves_like 'rejects packages access', :group, :guest, :forbidden
+ it_behaves_like 'returns packages', :group, :guest
end
end
end
diff --git a/spec/requests/api/helm_packages_spec.rb b/spec/requests/api/helm_packages_spec.rb
index 75f60c59759..230279c2af9 100644
--- a/spec/requests/api/helm_packages_spec.rb
+++ b/spec/requests/api/helm_packages_spec.rb
@@ -66,7 +66,7 @@ RSpec.describe API::HelmPackages, feature_category: :package_registry do
:public | :not_a_member | 'process helm download content request' | :success
:public | :anonymous | 'process helm download content request' | :success
:private | :reporter | 'process helm download content request' | :success
- :private | :guest | 'rejects helm packages access' | :forbidden
+ :private | :guest | 'process helm download content request' | :success
:private | :not_a_member | 'rejects helm packages access' | :not_found
:private | :anonymous | 'rejects helm packages access' | :unauthorized
end
diff --git a/spec/requests/api/maven_packages_spec.rb b/spec/requests/api/maven_packages_spec.rb
index 7bca93f3c19..faec16b7192 100644
--- a/spec/requests/api/maven_packages_spec.rb
+++ b/spec/requests/api/maven_packages_spec.rb
@@ -431,13 +431,19 @@ RSpec.describe API::MavenPackages, feature_category: :package_registry do
it_behaves_like 'bumping the package last downloaded at field'
it_behaves_like 'successfully returning the file'
- it 'denies download when not enough permissions' do
- unless project.root_namespace == user.namespace
- project.add_guest(user)
+ context 'when allow_guest_plus_roles_to_pull_packages is disabled' do
+ before do
+ stub_feature_flags(allow_guest_plus_roles_to_pull_packages: false)
+ end
- subject
+ it 'denies download when not enough permissions' do
+ unless project.root_namespace == user.namespace
+ project.add_guest(user)
- expect(response).to have_gitlab_http_status(:forbidden)
+ subject
+
+ expect(response).to have_gitlab_http_status(:forbidden)
+ end
end
end
@@ -587,12 +593,18 @@ RSpec.describe API::MavenPackages, feature_category: :package_registry do
it_behaves_like 'bumping the package last downloaded at field'
it_behaves_like 'successfully returning the file'
- it 'denies download when not enough permissions' do
- group.add_guest(user)
+ context 'when allow_guest_plus_roles_to_pull_packages is disabled' do
+ before do
+ stub_feature_flags(allow_guest_plus_roles_to_pull_packages: false)
+ end
- subject
+ it 'denies download when not enough permissions' do
+ group.add_guest(user)
- expect(response).to have_gitlab_http_status(download_denied_status)
+ subject
+
+ expect(response).to have_gitlab_http_status(download_denied_status)
+ end
end
it 'denies download when no private token' do
@@ -643,21 +655,27 @@ RSpec.describe API::MavenPackages, feature_category: :package_registry do
project.add_developer(user)
end
- context 'when user does not have enough permission for the recent project' do
- it 'tries to download the recent package' do
- subject
-
- expect(response).to have_gitlab_http_status(:forbidden)
- end
- end
-
- context 'when the FF maven_remove_permissions_check_from_finder disabled' do
+ context 'when allow_guest_plus_roles_to_pull_packages is disabled' do
before do
- stub_feature_flags(maven_remove_permissions_check_from_finder: false)
+ stub_feature_flags(allow_guest_plus_roles_to_pull_packages: false)
end
- it_behaves_like 'bumping the package last downloaded at field'
- it_behaves_like 'successfully returning the file'
+ context 'when user does not have enough permission for the recent project' do
+ it 'tries to download the recent package' do
+ subject
+
+ expect(response).to have_gitlab_http_status(:forbidden)
+ end
+ end
+
+ context 'when the FF maven_remove_permissions_check_from_finder disabled' do
+ before do
+ stub_feature_flags(maven_remove_permissions_check_from_finder: false)
+ end
+
+ it_behaves_like 'bumping the package last downloaded at field'
+ it_behaves_like 'successfully returning the file'
+ end
end
end
@@ -818,12 +836,18 @@ RSpec.describe API::MavenPackages, feature_category: :package_registry do
it_behaves_like 'bumping the package last downloaded at field'
it_behaves_like 'successfully returning the file'
- it 'denies download when not enough permissions' do
- project.add_guest(user)
+ context 'when allow_guest_plus_roles_to_pull_packages is disabled' do
+ before do
+ stub_feature_flags(allow_guest_plus_roles_to_pull_packages: false)
+ end
- subject
+ it 'denies download when not enough permissions' do
+ project.add_guest(user)
- expect(response).to have_gitlab_http_status(:forbidden)
+ subject
+
+ expect(response).to have_gitlab_http_status(:forbidden)
+ end
end
it 'denies download when no private token' do
diff --git a/spec/requests/api/ml_model_packages_spec.rb b/spec/requests/api/ml_model_packages_spec.rb
index aed59fabd42..96434756e1e 100644
--- a/spec/requests/api/ml_model_packages_spec.rb
+++ b/spec/requests/api/ml_model_packages_spec.rb
@@ -81,8 +81,8 @@ RSpec.describe ::API::MlModelPackages, feature_category: :mlops do
true | :developer | :private | true | :personal_access_token | :success
true | :developer | :public | true | :job_token | :success
true | :developer | :public | true | :personal_access_token | :success
- true | :guest | :private | true | :job_token | :forbidden
- true | :guest | :private | true | :personal_access_token | :forbidden
+ true | :guest | :private | true | :job_token | :success
+ true | :guest | :private | true | :personal_access_token | :success
true | :guest | :public | true | :job_token | :success
true | :guest | :public | true | :personal_access_token | :success
true | :reporter | :private | true | :job_token | :success
diff --git a/spec/requests/api/npm_group_packages_spec.rb b/spec/requests/api/npm_group_packages_spec.rb
index 12b2ccd1bf7..a0d883dc5f7 100644
--- a/spec/requests/api/npm_group_packages_spec.rb
+++ b/spec/requests/api/npm_group_packages_spec.rb
@@ -30,10 +30,10 @@ RSpec.describe API::NpmGroupPackages, feature_category: :package_registry do
:oauth | :public | :public | :guest | :ok
:oauth | :public | :internal | :guest | :ok
- :oauth | :public | :private | :guest | :forbidden
+ :oauth | :public | :private | :guest | :ok
:oauth | :internal | :internal | :guest | :ok
- :oauth | :internal | :private | :guest | :forbidden
- :oauth | :private | :private | :guest | :forbidden
+ :oauth | :internal | :private | :guest | :ok
+ :oauth | :private | :private | :guest | :ok
:oauth | :public | :public | :reporter | :ok
:oauth | :public | :internal | :reporter | :ok
:oauth | :public | :private | :reporter | :ok
@@ -43,10 +43,10 @@ RSpec.describe API::NpmGroupPackages, feature_category: :package_registry do
:personal_access_token | :public | :public | :guest | :ok
:personal_access_token | :public | :internal | :guest | :ok
- :personal_access_token | :public | :private | :guest | :forbidden
+ :personal_access_token | :public | :private | :guest | :ok
:personal_access_token | :internal | :internal | :guest | :ok
- :personal_access_token | :internal | :private | :guest | :forbidden
- :personal_access_token | :private | :private | :guest | :forbidden
+ :personal_access_token | :internal | :private | :guest | :ok
+ :personal_access_token | :private | :private | :guest | :ok
:personal_access_token | :public | :public | :reporter | :ok
:personal_access_token | :public | :internal | :reporter | :ok
:personal_access_token | :public | :private | :reporter | :ok
diff --git a/spec/requests/api/npm_project_packages_spec.rb b/spec/requests/api/npm_project_packages_spec.rb
index 64977f2f805..8d18024fe68 100644
--- a/spec/requests/api/npm_project_packages_spec.rb
+++ b/spec/requests/api/npm_project_packages_spec.rb
@@ -205,15 +205,21 @@ RSpec.describe API::NpmProjectPackages, feature_category: :package_registry do
it_behaves_like 'a package file that requires auth'
- context 'with guest' do
- let(:headers) { build_token_auth_header(token.plaintext_token) }
+ context 'when allow_guest_plus_roles_to_pull_packages is disabled' do
+ before do
+ stub_feature_flags(allow_guest_plus_roles_to_pull_packages: false)
+ end
- it 'denies download when not enough permissions' do
- project.add_guest(user)
+ context 'with guest' do
+ let(:headers) { build_token_auth_header(token.plaintext_token) }
- subject
+ it 'denies download when not enough permissions' do
+ project.add_guest(user)
- expect(response).to have_gitlab_http_status(:forbidden)
+ subject
+
+ expect(response).to have_gitlab_http_status(:forbidden)
+ end
end
end
diff --git a/spec/requests/api/nuget_group_packages_spec.rb b/spec/requests/api/nuget_group_packages_spec.rb
index 8e3aef20b58..b61aee57ca8 100644
--- a/spec/requests/api/nuget_group_packages_spec.rb
+++ b/spec/requests/api/nuget_group_packages_spec.rb
@@ -45,9 +45,7 @@ RSpec.describe API::NugetGroupPackages, feature_category: :package_registry do
example_names_with_status:
{
anonymous_requests_example_name: 'rejects nuget packages access',
- anonymous_requests_status: :unauthorized,
- guest_requests_example_name: 'rejects nuget packages access',
- guest_requests_status: :not_found
+ anonymous_requests_status: :unauthorized
}
it_behaves_like 'allows anyone to pull public nuget packages on group level' do
@@ -62,9 +60,7 @@ RSpec.describe API::NugetGroupPackages, feature_category: :package_registry do
example_names_with_status:
{
anonymous_requests_example_name: 'rejects nuget packages access',
- anonymous_requests_status: :unauthorized,
- guest_requests_example_name: 'rejects nuget packages access',
- guest_requests_status: :not_found
+ anonymous_requests_status: :unauthorized
}
it_behaves_like 'allows anyone to pull public nuget packages on group level' do
@@ -78,9 +74,7 @@ RSpec.describe API::NugetGroupPackages, feature_category: :package_registry do
it_behaves_like 'handling nuget search requests',
example_names_with_status: {
anonymous_requests_example_name: 'rejects nuget packages access',
- anonymous_requests_status: :unauthorized,
- guest_requests_example_name: 'process empty nuget search request',
- guest_requests_status: :success
+ anonymous_requests_status: :unauthorized
}
it_behaves_like 'allows anyone to pull public nuget packages on group level' do
diff --git a/spec/requests/api/nuget_project_packages_spec.rb b/spec/requests/api/nuget_project_packages_spec.rb
index 6f0eb3d2895..662804d6db3 100644
--- a/spec/requests/api/nuget_project_packages_spec.rb
+++ b/spec/requests/api/nuget_project_packages_spec.rb
@@ -167,7 +167,7 @@ RSpec.describe API::NugetProjectPackages, feature_category: :package_registry do
'PUBLIC' | :guest | false | false | 'rejects nuget packages access' | :unauthorized
'PUBLIC' | :anonymous | false | true | 'process nuget download versions request' | :success
'PRIVATE' | :developer | true | true | 'process nuget download versions request' | :success
- 'PRIVATE' | :guest | true | true | 'rejects nuget packages access' | :forbidden
+ 'PRIVATE' | :guest | true | true | 'process nuget download versions request' | :success
'PRIVATE' | :developer | true | false | 'rejects nuget packages access' | :unauthorized
'PRIVATE' | :guest | true | false | 'rejects nuget packages access' | :unauthorized
'PRIVATE' | :developer | false | true | 'rejects nuget packages access' | :not_found
@@ -228,7 +228,7 @@ RSpec.describe API::NugetProjectPackages, feature_category: :package_registry do
'PUBLIC' | :guest | false | false | 'rejects nuget packages access' | :unauthorized
'PUBLIC' | :anonymous | false | true | 'process nuget download content request' | :success
'PRIVATE' | :developer | true | true | 'process nuget download content request' | :success
- 'PRIVATE' | :guest | true | true | 'rejects nuget packages access' | :forbidden
+ 'PRIVATE' | :guest | true | true | 'process nuget download content request' | :success
'PRIVATE' | :developer | true | false | 'rejects nuget packages access' | :unauthorized
'PRIVATE' | :guest | true | false | 'rejects nuget packages access' | :unauthorized
'PRIVATE' | :developer | false | true | 'rejects nuget packages access' | :not_found
diff --git a/spec/requests/api/project_packages_spec.rb b/spec/requests/api/project_packages_spec.rb
index b6b143c9f71..88677e2acce 100644
--- a/spec/requests/api/project_packages_spec.rb
+++ b/spec/requests/api/project_packages_spec.rb
@@ -115,7 +115,7 @@ RSpec.describe API::ProjectPackages, feature_category: :package_registry do
it_behaves_like 'returns packages', :project, :developer
it_behaves_like 'returns packages', :project, :reporter
it_behaves_like 'rejects packages access', :project, :no_type, :not_found
- it_behaves_like 'rejects packages access', :project, :guest, :forbidden
+ it_behaves_like 'returns packages', :project, :guest
context 'user is a maintainer' do
before do
@@ -450,7 +450,7 @@ RSpec.describe API::ProjectPackages, feature_category: :package_registry do
:public | :guest | false | :personal_access_token | false | 'returning response status' | :unauthorized
:public | :anonymous | false | nil | true | 'returns package pipelines' | :success
:private | :developer | true | :personal_access_token | true | 'returns package pipelines' | :success
- :private | :guest | true | :personal_access_token | true | 'returning response status' | :forbidden
+ :private | :guest | true | :personal_access_token | true | 'returns package pipelines' | :success
:private | :developer | true | :personal_access_token | false | 'returning response status' | :unauthorized
:private | :guest | true | :personal_access_token | false | 'returning response status' | :unauthorized
:private | :developer | false | :personal_access_token | true | 'returning response status' | :not_found
diff --git a/spec/requests/api/rpm_project_packages_spec.rb b/spec/requests/api/rpm_project_packages_spec.rb
index 515970f86a1..b6c8fb87655 100644
--- a/spec/requests/api/rpm_project_packages_spec.rb
+++ b/spec/requests/api/rpm_project_packages_spec.rb
@@ -88,7 +88,7 @@ RSpec.describe API::RpmProjectPackages, feature_category: :package_registry do
context 'with valid project' do
where(:visibility_level, :user_role, :member, :user_token, :shared_examples_name, :expected_status) do
'PUBLIC' | :developer | true | true | 'process rpm packages upload/download' | success_status
- 'PUBLIC' | :guest | true | true | 'process rpm packages upload/download' | :forbidden
+ 'PUBLIC' | :guest | true | true | 'process rpm packages upload/download' | success_status
'PUBLIC' | :developer | true | false | 'rejects rpm packages access' | :unauthorized
'PUBLIC' | :guest | true | false | 'rejects rpm packages access' | :unauthorized
'PUBLIC' | :developer | false | true | 'process rpm packages upload/download' | :not_found
@@ -97,7 +97,7 @@ RSpec.describe API::RpmProjectPackages, feature_category: :package_registry do
'PUBLIC' | :guest | false | false | 'rejects rpm packages access' | :unauthorized
'PUBLIC' | :anonymous | false | true | 'process rpm packages upload/download' | :unauthorized
'PRIVATE' | :developer | true | true | 'process rpm packages upload/download' | success_status
- 'PRIVATE' | :guest | true | true | 'rejects rpm packages access' | :forbidden
+ 'PRIVATE' | :guest | true | true | 'process rpm packages upload/download' | success_status
'PRIVATE' | :developer | true | false | 'rejects rpm packages access' | :unauthorized
'PRIVATE' | :guest | true | false | 'rejects rpm packages access' | :unauthorized
'PRIVATE' | :developer | false | true | 'rejects rpm packages access' | :not_found
diff --git a/spec/requests/api/rubygem_packages_spec.rb b/spec/requests/api/rubygem_packages_spec.rb
index 1774b43ccb3..c7340cd8fe5 100644
--- a/spec/requests/api/rubygem_packages_spec.rb
+++ b/spec/requests/api/rubygem_packages_spec.rb
@@ -63,11 +63,11 @@ RSpec.describe API::RubygemPackages, feature_category: :package_registry do
end
where(:user_role, :token_type, :valid_token, :status) do
- :guest | :personal_access_token | true | :forbidden
+ :guest | :personal_access_token | true | :not_found
:guest | :personal_access_token | false | :unauthorized
:guest | :deploy_token | true | :not_found
:guest | :deploy_token | false | :unauthorized
- :guest | :job_token | true | :forbidden
+ :guest | :job_token | true | :not_found
:guest | :job_token | false | :unauthorized
:reporter | :personal_access_token | true | :not_found
:reporter | :personal_access_token | false | :unauthorized
@@ -139,7 +139,7 @@ RSpec.describe API::RubygemPackages, feature_category: :package_registry do
:public | :guest | false | :personal_access_token | false | 'rejects rubygems packages access' | :unauthorized
:public | :anonymous | false | :personal_access_token | true | 'Rubygems gem download' | :success
:private | :developer | true | :personal_access_token | true | 'Rubygems gem download' | :success
- :private | :guest | true | :personal_access_token | true | 'rejects rubygems packages access' | :forbidden
+ :private | :guest | true | :personal_access_token | true | 'Rubygems gem download' | :success
:private | :developer | true | :personal_access_token | false | 'rejects rubygems packages access' | :unauthorized
:private | :guest | true | :personal_access_token | false | 'rejects rubygems packages access' | :unauthorized
:private | :developer | false | :personal_access_token | true | 'rejects rubygems packages access' | :not_found
@@ -156,7 +156,7 @@ RSpec.describe API::RubygemPackages, feature_category: :package_registry do
:public | :developer | false | :job_token | false | 'rejects rubygems packages access' | :unauthorized
:public | :guest | false | :job_token | false | 'rejects rubygems packages access' | :unauthorized
:private | :developer | true | :job_token | true | 'Rubygems gem download' | :success
- :private | :guest | true | :job_token | true | 'rejects rubygems packages access' | :forbidden
+ :private | :guest | true | :job_token | true | 'Rubygems gem download' | :success
:private | :developer | true | :job_token | false | 'rejects rubygems packages access' | :unauthorized
:private | :guest | true | :job_token | false | 'rejects rubygems packages access' | :unauthorized
:private | :developer | false | :job_token | true | 'rejects rubygems packages access' | :not_found
@@ -406,7 +406,7 @@ RSpec.describe API::RubygemPackages, feature_category: :package_registry do
:public | :guest | false | :personal_access_token | false | 'rejects rubygems packages access' | :unauthorized
:public | :anonymous | false | :personal_access_token | true | 'dependency endpoint success' | :success
:private | :developer | true | :personal_access_token | true | 'dependency endpoint success' | :success
- :private | :guest | true | :personal_access_token | true | 'rejects rubygems packages access' | :forbidden
+ :private | :guest | true | :personal_access_token | true | 'dependency endpoint success' | :success
:private | :developer | true | :personal_access_token | false | 'rejects rubygems packages access' | :unauthorized
:private | :guest | true | :personal_access_token | false | 'rejects rubygems packages access' | :unauthorized
:private | :developer | false | :personal_access_token | true | 'rejects rubygems packages access' | :not_found
@@ -423,7 +423,7 @@ RSpec.describe API::RubygemPackages, feature_category: :package_registry do
:public | :developer | false | :job_token | false | 'rejects rubygems packages access' | :unauthorized
:public | :guest | false | :job_token | false | 'rejects rubygems packages access' | :unauthorized
:private | :developer | true | :job_token | true | 'dependency endpoint success' | :success
- :private | :guest | true | :job_token | true | 'rejects rubygems packages access' | :forbidden
+ :private | :guest | true | :job_token | true | 'dependency endpoint success' | :success
:private | :developer | true | :job_token | false | 'rejects rubygems packages access' | :unauthorized
:private | :guest | true | :job_token | false | 'rejects rubygems packages access' | :unauthorized
:private | :developer | false | :job_token | true | 'rejects rubygems packages access' | :not_found
diff --git a/spec/requests/api/terraform/modules/v1/namespace_packages_spec.rb b/spec/requests/api/terraform/modules/v1/namespace_packages_spec.rb
index 079fe913a52..3baffdfc491 100644
--- a/spec/requests/api/terraform/modules/v1/namespace_packages_spec.rb
+++ b/spec/requests/api/terraform/modules/v1/namespace_packages_spec.rb
@@ -40,8 +40,8 @@ RSpec.describe API::Terraform::Modules::V1::NamespacePackages, feature_category:
:public | :developer | false | :invalid | 'rejects terraform module packages access' | :unauthorized
:public | :guest | false | :invalid | 'rejects terraform module packages access' | :unauthorized
:public | :anonymous | false | nil | 'returns no terraform module packages' | :success
- :private | :developer | true | :personal_access_token | 'returns terraform module packages' | :success
- :private | :guest | true | :personal_access_token | 'rejects terraform module packages access' | :forbidden
+ :private | :developer | true | :personal_access_token | 'returns terraform module packages' | :success
+ :private | :guest | true | :personal_access_token | 'returns terraform module packages' | :success
:private | :developer | true | :invalid | 'rejects terraform module packages access' | :unauthorized
:private | :guest | true | :invalid | 'rejects terraform module packages access' | :unauthorized
:private | :developer | false | :personal_access_token | 'rejects terraform module packages access' | :forbidden
@@ -49,15 +49,15 @@ RSpec.describe API::Terraform::Modules::V1::NamespacePackages, feature_category:
:private | :developer | false | :invalid | 'rejects terraform module packages access' | :unauthorized
:private | :guest | false | :invalid | 'rejects terraform module packages access' | :unauthorized
:private | :anonymous | false | nil | 'rejects terraform module packages access' | :unauthorized
- :public | :developer | true | :job_token | 'returns terraform module packages' | :success
- :public | :guest | true | :job_token | 'returns no terraform module packages' | :success
+ :public | :developer | true | :job_token | 'returns terraform module packages' | :success
+ :public | :guest | true | :job_token | 'returns terraform module packages' | :success
:public | :guest | true | :invalid | 'rejects terraform module packages access' | :unauthorized
:public | :developer | false | :job_token | 'returns no terraform module packages' | :success
:public | :guest | false | :job_token | 'returns no terraform module packages' | :success
:public | :developer | false | :invalid | 'rejects terraform module packages access' | :unauthorized
:public | :guest | false | :invalid | 'rejects terraform module packages access' | :unauthorized
- :private | :developer | true | :job_token | 'returns terraform module packages' | :success
- :private | :guest | true | :job_token | 'rejects terraform module packages access' | :forbidden
+ :private | :developer | true | :job_token | 'returns terraform module packages' | :success
+ :private | :guest | true | :job_token | 'returns terraform module packages' | :success
:private | :developer | true | :invalid | 'rejects terraform module packages access' | :unauthorized
:private | :guest | true | :invalid | 'rejects terraform module packages access' | :unauthorized
:private | :developer | false | :job_token | 'rejects terraform module packages access' | :forbidden
@@ -116,7 +116,7 @@ RSpec.describe API::Terraform::Modules::V1::NamespacePackages, feature_category:
:public | :guest | false | :invalid | 'rejects terraform module packages access' | :unauthorized
:public | :anonymous | false | nil | 'redirects to version download' | :found
:private | :developer | true | :personal_access_token | 'redirects to version download' | :found
- :private | :guest | true | :personal_access_token | 'rejects terraform module packages access' | :forbidden
+ :private | :guest | true | :personal_access_token | 'redirects to version download' | :found
:private | :developer | true | :invalid | 'rejects terraform module packages access' | :unauthorized
:private | :guest | true | :invalid | 'rejects terraform module packages access' | :unauthorized
:private | :developer | false | :personal_access_token | 'rejects terraform module packages access' | :forbidden
@@ -132,7 +132,7 @@ RSpec.describe API::Terraform::Modules::V1::NamespacePackages, feature_category:
:public | :developer | false | :invalid | 'rejects terraform module packages access' | :unauthorized
:public | :guest | false | :invalid | 'rejects terraform module packages access' | :unauthorized
:private | :developer | true | :job_token | 'redirects to version download' | :found
- :private | :guest | true | :job_token | 'rejects terraform module packages access' | :forbidden
+ :private | :guest | true | :job_token | 'redirects to version download' | :found
:private | :developer | true | :invalid | 'rejects terraform module packages access' | :unauthorized
:private | :guest | true | :invalid | 'rejects terraform module packages access' | :unauthorized
:private | :developer | false | :job_token | 'rejects terraform module packages access' | :forbidden
@@ -185,8 +185,8 @@ RSpec.describe API::Terraform::Modules::V1::NamespacePackages, feature_category:
:public | :developer | false | :invalid | 'rejects terraform module packages access' | :unauthorized
:public | :guest | false | :invalid | 'rejects terraform module packages access' | :unauthorized
:public | :anonymous | false | nil | 'returns terraform module version' | :success
- :private | :developer | true | :personal_access_token | 'returns terraform module version' | :success
- :private | :guest | true | :personal_access_token | 'rejects terraform module packages access' | :forbidden
+ :private | :developer | true | :personal_access_token | 'returns terraform module version' | :success
+ :private | :guest | true | :personal_access_token | 'returns terraform module version' | :success
:private | :developer | true | :invalid | 'rejects terraform module packages access' | :unauthorized
:private | :guest | true | :invalid | 'rejects terraform module packages access' | :unauthorized
:private | :developer | false | :personal_access_token | 'rejects terraform module packages access' | :forbidden
@@ -201,8 +201,8 @@ RSpec.describe API::Terraform::Modules::V1::NamespacePackages, feature_category:
:public | :guest | false | :job_token | 'returns terraform module version' | :success
:public | :developer | false | :invalid | 'rejects terraform module packages access' | :unauthorized
:public | :guest | false | :invalid | 'rejects terraform module packages access' | :unauthorized
- :private | :developer | true | :job_token | 'returns terraform module version' | :success
- :private | :guest | true | :job_token | 'rejects terraform module packages access' | :forbidden
+ :private | :developer | true | :job_token | 'returns terraform module version' | :success
+ :private | :guest | true | :job_token | 'returns terraform module version' | :success
:private | :developer | true | :invalid | 'rejects terraform module packages access' | :unauthorized
:private | :guest | true | :invalid | 'rejects terraform module packages access' | :unauthorized
:private | :developer | false | :job_token | 'rejects terraform module packages access' | :forbidden
@@ -257,8 +257,8 @@ RSpec.describe API::Terraform::Modules::V1::NamespacePackages, feature_category:
:public | :developer | false | :invalid | 'rejects terraform module packages access' | :unauthorized
:public | :guest | false | :invalid | 'rejects terraform module packages access' | :unauthorized
:public | :anonymous | false | nil | 'returns terraform module version' | :success
- :private | :developer | true | :personal_access_token | 'returns terraform module version' | :success
- :private | :guest | true | :personal_access_token | 'rejects terraform module packages access' | :forbidden
+ :private | :developer | true | :personal_access_token | 'returns terraform module version' | :success
+ :private | :guest | true | :personal_access_token | 'returns terraform module version' | :success
:private | :developer | true | :invalid | 'rejects terraform module packages access' | :unauthorized
:private | :guest | true | :invalid | 'rejects terraform module packages access' | :unauthorized
:private | :developer | false | :personal_access_token | 'rejects terraform module packages access' | :forbidden
@@ -273,8 +273,8 @@ RSpec.describe API::Terraform::Modules::V1::NamespacePackages, feature_category:
:public | :guest | false | :job_token | 'returns terraform module version' | :success
:public | :developer | false | :invalid | 'rejects terraform module packages access' | :unauthorized
:public | :guest | false | :invalid | 'rejects terraform module packages access' | :unauthorized
- :private | :developer | true | :job_token | 'returns terraform module version' | :success
- :private | :guest | true | :job_token | 'rejects terraform module packages access' | :forbidden
+ :private | :developer | true | :job_token | 'returns terraform module version' | :success
+ :private | :guest | true | :job_token | 'returns terraform module version' | :success
:private | :developer | true | :invalid | 'rejects terraform module packages access' | :unauthorized
:private | :guest | true | :invalid | 'rejects terraform module packages access' | :unauthorized
:private | :developer | false | :job_token | 'rejects terraform module packages access' | :forbidden
@@ -316,8 +316,8 @@ RSpec.describe API::Terraform::Modules::V1::NamespacePackages, feature_category:
:public | :developer | false | :invalid | 'rejects terraform module packages access' | :unauthorized
:public | :guest | false | :invalid | 'rejects terraform module packages access' | :unauthorized
:public | :anonymous | false | nil | 'grants terraform module download' | :success
- :private | :developer | true | :personal_access_token | 'grants terraform module download' | :success
- :private | :guest | true | :personal_access_token | 'rejects terraform module packages access' | :forbidden
+ :private | :developer | true | :personal_access_token | 'grants terraform module download' | :success
+ :private | :guest | true | :personal_access_token | 'grants terraform module download' | :success
:private | :developer | true | :invalid | 'rejects terraform module packages access' | :unauthorized
:private | :guest | true | :invalid | 'rejects terraform module packages access' | :unauthorized
:private | :developer | false | :personal_access_token | 'rejects terraform module packages access' | :forbidden
@@ -332,8 +332,8 @@ RSpec.describe API::Terraform::Modules::V1::NamespacePackages, feature_category:
:public | :guest | false | :job_token | 'grants terraform module download' | :success
:public | :developer | false | :invalid | 'rejects terraform module packages access' | :unauthorized
:public | :guest | false | :invalid | 'rejects terraform module packages access' | :unauthorized
- :private | :developer | true | :job_token | 'grants terraform module download' | :success
- :private | :guest | true | :job_token | 'rejects terraform module packages access' | :forbidden
+ :private | :developer | true | :job_token | 'grants terraform module download' | :success
+ :private | :guest | true | :job_token | 'grants terraform module download' | :success
:private | :developer | true | :invalid | 'rejects terraform module packages access' | :unauthorized
:private | :guest | true | :invalid | 'rejects terraform module packages access' | :unauthorized
:private | :developer | false | :job_token | 'rejects terraform module packages access' | :forbidden
@@ -385,7 +385,7 @@ RSpec.describe API::Terraform::Modules::V1::NamespacePackages, feature_category:
:public | :guest | false | :invalid | 'rejects terraform module packages access' | :unauthorized
:public | :anonymous | false | nil | 'grants terraform module package file access' | :success
:private | :developer | true | :personal_access_token | 'grants terraform module package file access' | :success
- :private | :guest | true | :personal_access_token | 'rejects terraform module packages access' | :forbidden
+ :private | :guest | true | :personal_access_token | 'grants terraform module package file access' | :success
:private | :developer | true | :invalid | 'rejects terraform module packages access' | :unauthorized
:private | :guest | true | :invalid | 'rejects terraform module packages access' | :unauthorized
:private | :developer | false | :personal_access_token | 'rejects terraform module packages access' | :forbidden
@@ -401,7 +401,7 @@ RSpec.describe API::Terraform::Modules::V1::NamespacePackages, feature_category:
:public | :developer | false | :invalid | 'rejects terraform module packages access' | :unauthorized
:public | :guest | false | :invalid | 'rejects terraform module packages access' | :unauthorized
:private | :developer | true | :job_token | 'grants terraform module package file access' | :success
- :private | :guest | true | :job_token | 'rejects terraform module packages access' | :forbidden
+ :private | :guest | true | :job_token | 'grants terraform module package file access' | :success
:private | :developer | true | :invalid | 'rejects terraform module packages access' | :unauthorized
:private | :guest | true | :invalid | 'rejects terraform module packages access' | :unauthorized
:private | :developer | false | :job_token | 'rejects terraform module packages access' | :forbidden
diff --git a/spec/requests/jwt_controller_spec.rb b/spec/requests/jwt_controller_spec.rb
index 212c1aefaf3..bd4d3d8055b 100644
--- a/spec/requests/jwt_controller_spec.rb
+++ b/spec/requests/jwt_controller_spec.rb
@@ -5,7 +5,7 @@ require 'spec_helper'
RSpec.describe JwtController, feature_category: :system_access do
include_context 'parsed logs'
- let(:service) { double(execute: {} ) }
+ let(:service) { double(execute: {}) }
let(:service_class) { Auth::ContainerRegistryAuthenticationService }
let(:service_name) { 'container_registry' }
let(:parameters) { { service: service_name } }
@@ -23,7 +23,7 @@ RSpec.describe JwtController, feature_category: :system_access do
end
shared_examples 'a token that expires today' do
- let(:pat) { create(:personal_access_token, user: user, scopes: ['api'], expires_at: Date.today ) }
+ let(:pat) { create(:personal_access_token, user: user, scopes: ['api'], expires_at: Date.today) }
let(:headers) { { authorization: credentials('personal_access_token', pat.token) } }
it 'fails authentication' do
diff --git a/spec/requests/projects/merge_requests/diffs_spec.rb b/spec/requests/projects/merge_requests/diffs_spec.rb
index 86356bb1b1e..7e66d37b69c 100644
--- a/spec/requests/projects/merge_requests/diffs_spec.rb
+++ b/spec/requests/projects/merge_requests/diffs_spec.rb
@@ -190,7 +190,7 @@ RSpec.describe 'Merge Requests Diffs', feature_category: :code_review_workflow d
end
context 'with the different expanded option' do
- subject { go(page: 0, per_page: 5, expanded: true ) }
+ subject { go(page: 0, per_page: 5, expanded: true) }
let(:collection) { Gitlab::Diff::FileCollection::MergeRequestDiffBatch }
let(:expected_options) { collection_arguments(total_pages: 20) }
diff --git a/spec/requests/projects/merge_requests_spec.rb b/spec/requests/projects/merge_requests_spec.rb
index e57808e6728..0f30c765459 100644
--- a/spec/requests/projects/merge_requests_spec.rb
+++ b/spec/requests/projects/merge_requests_spec.rb
@@ -86,7 +86,7 @@ RSpec.describe 'merge requests actions', feature_category: :source_code_manageme
context 'when the assignee is changed' do
before do
- update_service( assignee_ids: [] )
+ update_service(assignee_ids: [])
end
it_behaves_like 'a non-cached request'
diff --git a/spec/requests/projects/releases_controller_spec.rb b/spec/requests/projects/releases_controller_spec.rb
index 8cf1c83e13d..8eb4feb170c 100644
--- a/spec/requests/projects/releases_controller_spec.rb
+++ b/spec/requests/projects/releases_controller_spec.rb
@@ -8,7 +8,7 @@ RSpec.describe 'Projects::ReleasesController', feature_category: :release_orches
# Added as a request spec because of https://gitlab.com/gitlab-org/gitlab/-/issues/232386
describe 'GET #downloads' do
- let_it_be(:release) { create(:release, project: project, tag: 'v11.9.0-rc2' ) }
+ let_it_be(:release) { create(:release, project: project, tag: 'v11.9.0-rc2') }
let(:internal_redirect_url) { "https://#{Gitlab.config.gitlab.host}:#{Gitlab.config.gitlab.port}/abcd" }
let!(:link) do
create(:release_link, release: release, name: 'internal gitlab url', filepath: filepath,
@@ -117,7 +117,7 @@ RSpec.describe 'Projects::ReleasesController', feature_category: :release_orches
end
context 'when user has permissions to read code' do
- let_it_be(:release) { create(:release, project: project, tag: 'v11.9.0-rc2' ) }
+ let_it_be(:release) { create(:release, project: project, tag: 'v11.9.0-rc2') }
before do
login_as(user)
@@ -131,7 +131,7 @@ RSpec.describe 'Projects::ReleasesController', feature_category: :release_orches
end
context 'when user doesn\'t have permissions to read code' do
- let_it_be(:release) { create(:release, project: project, tag: 'v11.9.0-rc2' ) }
+ let_it_be(:release) { create(:release, project: project, tag: 'v11.9.0-rc2') }
let_it_be(:new_user) { create(:user, guest_of: project) }
before do
@@ -153,7 +153,7 @@ RSpec.describe 'Projects::ReleasesController', feature_category: :release_orches
create(:project, :repository, :public, repository_access_level: ProjectFeature::PRIVATE)
end
- let_it_be(:release) { create(:release, project: public_project, tag: 'v11.9.0-rc2' ) }
+ let_it_be(:release) { create(:release, project: public_project, tag: 'v11.9.0-rc2') }
it 'dosn\'t show commit details in the atom feed' do
get(project_releases_url(public_project, format: :atom))
diff --git a/spec/requests/search_controller_spec.rb b/spec/requests/search_controller_spec.rb
index 50957f1caf2..18bbe60b716 100644
--- a/spec/requests/search_controller_spec.rb
+++ b/spec/requests/search_controller_spec.rb
@@ -149,20 +149,20 @@ RSpec.describe SearchController, type: :request, feature_category: :global_searc
end
it 'finds a commit in uppercase and redirects to its page' do
- send_search_request( { search: sha.upcase, scope: 'projects', project_id: project.id })
+ send_search_request({ search: sha.upcase, scope: 'projects', project_id: project.id })
expect(response).to redirect_to(project_commit_path(project, sha))
end
it 'finds a commit with a partial sha and redirects to its page' do
- send_search_request( { search: sha[0..10], scope: 'projects', project_id: project.id })
+ send_search_request({ search: sha[0..10], scope: 'projects', project_id: project.id })
expect(response).to redirect_to(project_commit_path(project, sha))
end
it 'redirects to the commit even if another scope result is returned' do
create(:note, project: project, note: "This is the #{sha}")
- send_search_request( { search: sha, scope: 'projects', project_id: project.id })
+ send_search_request({ search: sha, scope: 'projects', project_id: project.id })
expect(response).to redirect_to(project_commit_path(project, sha))
end
diff --git a/spec/serializers/analytics_build_entity_spec.rb b/spec/serializers/analytics_build_entity_spec.rb
index b5678d91248..1aec5c2c38e 100644
--- a/spec/serializers/analytics_build_entity_spec.rb
+++ b/spec/serializers/analytics_build_entity_spec.rb
@@ -45,7 +45,7 @@ RSpec.describe AnalyticsBuildEntity do
end
it 'contains the duration' do
- expect(subject[:total_time]).to eq(hours: 1 )
+ expect(subject[:total_time]).to eq(hours: 1)
end
context 'no started at or finished at date' do
diff --git a/spec/services/audit_event_service_spec.rb b/spec/services/audit_event_service_spec.rb
index b401d6b18da..b68b62c8131 100644
--- a/spec/services/audit_event_service_spec.rb
+++ b/spec/services/audit_event_service_spec.rb
@@ -116,16 +116,18 @@ RSpec.describe AuditEventService, :with_license, feature_category: :audit_events
audit_service.for_authentication.security_event
end
- it 'tracks exceptions when the event cannot be created' do
- allow_next_instance_of(AuditEvent) do |event|
- allow(event).to receive(:valid?).and_return(false)
+ context 'when the event cannot be created' do
+ let(:user) { create(:user, current_sign_in_ip: "not-an-ip-address") }
+
+ before do
+ allow(Gitlab::RequestContext.instance).to receive(:client_ip).and_return("not-an-ip-address")
end
- expect(Gitlab::ErrorTracking).to(
- receive(:track_and_raise_for_dev_exception)
- )
+ it 'tracks exceptions' do
+ expect(Gitlab::ErrorTracking).to receive(:track_and_raise_for_dev_exception)
- audit_service.for_authentication.security_event
+ audit_service.for_authentication.security_event
+ end
end
context 'with IP address', :request_store do
@@ -138,7 +140,6 @@ RSpec.describe AuditEventService, :with_license, feature_category: :audit_events
with_them do
let(:user) { create(:user, current_sign_in_ip: from_author_sign_in) }
- let(:audit_service) { described_class.new(user, user, with: 'standard') }
before do
allow(Gitlab::RequestContext.instance).to receive(:client_ip).and_return(from_context)
diff --git a/spec/services/bulk_imports/create_service_spec.rb b/spec/services/bulk_imports/create_service_spec.rb
index 7a9153ad1db..709eb8c0ab8 100644
--- a/spec/services/bulk_imports/create_service_spec.rb
+++ b/spec/services/bulk_imports/create_service_spec.rb
@@ -112,7 +112,7 @@ RSpec.describe BulkImports::CreateService, :clean_gitlab_redis_shared_state, fea
.to receive(:execute)
.and_return(instance_double(GraphQL::Client::Response, original_hash: {
'data' => { 'group' => { 'id' => 'gid://gitlab/Group/165' } }
- } ))
+ }))
allow(client).to receive(:parse)
end
@@ -142,7 +142,7 @@ RSpec.describe BulkImports::CreateService, :clean_gitlab_redis_shared_state, fea
.to receive(:execute)
.and_return(instance_double(GraphQL::Client::Response, original_hash: {
'data' => { 'group' => { 'id' => 'gid://gitlab/Group/165' } }
- } ))
+ }))
allow(client).to receive(:parse)
end
@@ -174,7 +174,7 @@ RSpec.describe BulkImports::CreateService, :clean_gitlab_redis_shared_state, fea
.to receive(:execute)
.and_return(instance_double(GraphQL::Client::Response, original_hash: {
'data' => { 'group' => { 'id' => 'gid://gitlab/Group/165' } }
- } ))
+ }))
allow(client).to receive(:parse)
end
@@ -391,7 +391,7 @@ RSpec.describe BulkImports::CreateService, :clean_gitlab_redis_shared_state, fea
.to receive(:execute)
.and_return(instance_double(GraphQL::Client::Response, original_hash: {
'data' => { 'group' => { 'id' => 'gid://gitlab/Group/165' } }
- } ))
+ }))
allow(client).to receive(:parse)
end
@@ -407,7 +407,7 @@ RSpec.describe BulkImports::CreateService, :clean_gitlab_redis_shared_state, fea
.to receive(:execute)
.and_return(instance_double(GraphQL::Client::Response, original_hash: {
'data' => { 'group' => { 'id' => 'gid://gitlab/Group/165' } }
- } ))
+ }))
allow(client).to receive(:parse)
end
@@ -542,7 +542,7 @@ RSpec.describe BulkImports::CreateService, :clean_gitlab_redis_shared_state, fea
describe '#user-role' do
context 'when there is a parent_namespace and the user is a member' do
- let(:group2) { create(:group, path: 'destination200', source_id: parent_group.id ) }
+ let(:group2) { create(:group, path: 'destination200', source_id: parent_group.id) }
let(:params) do
[
{
@@ -856,8 +856,8 @@ RSpec.describe BulkImports::CreateService, :clean_gitlab_redis_shared_state, fea
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 ) }
- let_it_be(:existing_subgroup_2) { create(:group, path: 'existing-subgroup_2', parent_id: parent_group.id ) }
+ let_it_be(:existing_subgroup) { create(:group, path: 'existing-subgroup', parent_id: parent_group.id) }
+ let_it_be(:existing_subgroup_2) { create(:group, path: 'existing-subgroup_2', parent_id: parent_group.id) }
let(:params) do
[
{
@@ -937,8 +937,8 @@ RSpec.describe BulkImports::CreateService, :clean_gitlab_redis_shared_state, fea
context 'when the source_type is a project' do
context 'when the provided destination_slug already exists in the destination_namespace' do
- let_it_be(:existing_group) { create(:group, path: 'existing-group' ) }
- let_it_be(:existing_project) { create(:project, path: 'existing-project', parent_id: existing_group.id ) }
+ let_it_be(:existing_group) { create(:group, path: 'existing-group') }
+ let_it_be(:existing_project) { create(:project, path: 'existing-project', parent_id: existing_group.id) }
let(:params) do
[
{
@@ -968,7 +968,7 @@ RSpec.describe BulkImports::CreateService, :clean_gitlab_redis_shared_state, fea
end
context 'when the destination_slug does not conflict with an existing project' do
- let_it_be(:existing_group) { create(:group, path: 'existing-group' ) }
+ let_it_be(:existing_group) { create(:group, path: 'existing-group') }
let(:params) do
[
{
diff --git a/spec/services/jira_connect_installations/proxy_lifecycle_event_service_spec.rb b/spec/services/jira_connect_installations/proxy_lifecycle_event_service_spec.rb
index 3c144de2208..0d6290d777b 100644
--- a/spec/services/jira_connect_installations/proxy_lifecycle_event_service_spec.rb
+++ b/spec/services/jira_connect_installations/proxy_lifecycle_event_service_spec.rb
@@ -87,7 +87,7 @@ RSpec.describe JiraConnectInstallations::ProxyLifecycleEventService, feature_cat
it 'returns an error ServiceResponse', :aggregate_failures do
expect(execute_service).to be_kind_of(ServiceResponse)
expect(execute_service[:status]).to eq(:error)
- expect(execute_service[:message]).to eq( { type: :response_error, code: 422 } )
+ expect(execute_service[:message]).to eq({ type: :response_error, code: 422 })
end
it 'logs the error response' do
diff --git a/spec/support/matchers/graphql_matchers.rb b/spec/support/matchers/graphql_matchers.rb
index 470fdc670d8..5f9830e22de 100644
--- a/spec/support/matchers/graphql_matchers.rb
+++ b/spec/support/matchers/graphql_matchers.rb
@@ -113,10 +113,34 @@ RSpec::Matchers.define :have_graphql_arguments do |*expected|
end
failure_message do |field|
- names = expected_names(field).inspect
- args = field.arguments.keys.inspect
+ expected_values = expected_names(field).sort
+ actual_values = field.arguments.keys.sort
- "expected #{field.name} to have the following arguments: #{names}, but it has #{args}."
+ extra_values = actual_values - expected_values
+ missing_values = expected_values - actual_values
+
+ message = <<~MESSAGE
+ expected #{field.name} to have the following arguments:
+ #{expected_values.inspect}
+ but it has
+ #{actual_values.inspect}
+ MESSAGE
+
+ if extra_values.present?
+ message += <<~MESSAGE
+ \n Extra values:
+ #{extra_values.inspect}
+ MESSAGE
+ end
+
+ if missing_values.present?
+ message += <<~MESSAGE
+ \n Missing values:
+ #{missing_values.inspect}
+ MESSAGE
+ end
+
+ message
end
end
diff --git a/spec/support/shared_examples/requests/api/conan_packages_shared_examples.rb b/spec/support/shared_examples/requests/api/conan_packages_shared_examples.rb
index c33ed76a234..a1938d97402 100644
--- a/spec/support/shared_examples/requests/api/conan_packages_shared_examples.rb
+++ b/spec/support/shared_examples/requests/api/conan_packages_shared_examples.rb
@@ -63,7 +63,7 @@ RSpec.shared_examples 'conan search endpoint' do
:maintainer | true
:developer | true
:reporter | true
- :guest | false
+ :guest | true
:anonymous | false
end
@@ -715,12 +715,18 @@ RSpec.shared_examples 'a private project with packages' do
expect(response.media_type).to eq('application/octet-stream')
end
- it 'denies download when not enough permissions' do
- project.add_guest(user)
+ context 'when allow_guest_plus_roles_to_pull_packages is disabled' do
+ before do
+ stub_feature_flags(allow_guest_plus_roles_to_pull_packages: false)
+ end
- subject
+ it 'denies download when not enough permissions' do
+ project.add_guest(user)
- expect(response).to have_gitlab_http_status(:forbidden)
+ subject
+
+ expect(response).to have_gitlab_http_status(:forbidden)
+ end
end
end
diff --git a/spec/support/shared_examples/requests/api/debian_distributions_shared_examples.rb b/spec/support/shared_examples/requests/api/debian_distributions_shared_examples.rb
index 5cd63c33936..e4c4bddc629 100644
--- a/spec/support/shared_examples/requests/api/debian_distributions_shared_examples.rb
+++ b/spec/support/shared_examples/requests/api/debian_distributions_shared_examples.rb
@@ -119,7 +119,7 @@ RSpec.shared_examples 'Debian distributions read endpoint' do |desired_behavior,
:public | :invalid_token | :private_token | :unauthorized | nil
:private | :developer | :private_token | success_status | success_body
:private | :developer | :basic | :not_found | nil
- :private | :guest | :private_token | :forbidden | nil
+ :private | :guest | :private_token | success_status | success_body
:private | :not_a_member | :private_token | :not_found | nil
:private | :anonymous | :private_token | :not_found | nil
:private | :invalid_token | :private_token | :unauthorized | nil
diff --git a/spec/support/shared_examples/requests/api/debian_packages_shared_examples.rb b/spec/support/shared_examples/requests/api/debian_packages_shared_examples.rb
index 513f9802b34..7f2f2ef7446 100644
--- a/spec/support/shared_examples/requests/api/debian_packages_shared_examples.rb
+++ b/spec/support/shared_examples/requests/api/debian_packages_shared_examples.rb
@@ -115,7 +115,7 @@ RSpec.shared_examples 'Debian packages read endpoint' do |desired_behavior, succ
:public | :invalid_token | :basic | :unauthorized | nil
:private | :developer | :basic | success_status | success_body
:private | :developer | :private_token | :unauthorized | nil
- :private | :guest | :basic | :forbidden | nil
+ :private | :guest | :basic | success_status | success_body
:private | :not_a_member | :basic | :not_found | nil
:private | :anonymous | :basic | :unauthorized | nil
:private | :invalid_token | :basic | :unauthorized | nil
diff --git a/spec/support/shared_examples/requests/api/helm_packages_shared_examples.rb b/spec/support/shared_examples/requests/api/helm_packages_shared_examples.rb
index 9c20b95eb80..1dd88e6bf2e 100644
--- a/spec/support/shared_examples/requests/api/helm_packages_shared_examples.rb
+++ b/spec/support/shared_examples/requests/api/helm_packages_shared_examples.rb
@@ -227,7 +227,7 @@ RSpec.shared_examples 'handling helm chart index requests' do
:public | :not_a_member | 'process helm service index request' | :success
:public | :anonymous | 'process helm service index request' | :success
:private | :reporter | 'process helm service index request' | :success
- :private | :guest | 'rejects helm packages access' | :forbidden
+ :private | :guest | 'process helm service index request' | :success
:private | :not_a_member | 'rejects helm packages access' | :not_found
:private | :anonymous | 'rejects helm packages access' | :unauthorized
end
@@ -264,7 +264,7 @@ RSpec.shared_examples 'handling helm chart index requests' do
:public | :not_a_member | 'process helm service index request' | :success
:public | :anonymous | 'process helm service index request' | :success
:private | :reporter | 'process helm service index request' | :success
- :private | :guest | 'rejects helm packages access' | :forbidden
+ :private | :guest | 'process helm service index request' | :success
:private | :not_a_member | 'rejects helm packages access' | :not_found
:private | :anonymous | 'rejects helm packages access' | :unauthorized
end
diff --git a/spec/support/shared_examples/requests/api/npm_packages_shared_examples.rb b/spec/support/shared_examples/requests/api/npm_packages_shared_examples.rb
index b6bb3601aa1..3e48c10c9c7 100644
--- a/spec/support/shared_examples/requests/api/npm_packages_shared_examples.rb
+++ b/spec/support/shared_examples/requests/api/npm_packages_shared_examples.rb
@@ -98,7 +98,7 @@ RSpec.shared_examples 'handling get metadata requests' do |scope: :project|
set_visibility('private', scope)
end
- it_behaves_like 'reject metadata request', status: :forbidden
+ it_behaves_like 'accept metadata request', status: :ok
end
end
@@ -205,7 +205,7 @@ RSpec.shared_examples 'handling get metadata requests' do |scope: :project|
true | :public | nil | 'redirect metadata request' | :redirected
false | :public | nil | 'returning response status with error' | :not_found
false | :private | nil | 'reject metadata request' | :unauthorized
- false | :private | :guest | 'reject metadata request' | :forbidden
+ false | :private | :guest | 'returning response status with error' | :not_found
false | :private | :reporter | 'returning response status with error' | :not_found
end
@@ -339,7 +339,7 @@ RSpec.shared_examples 'handling audit request' do |path:, scope: :project|
project.add_guest(user)
end
- it_behaves_like 'reject audit request', status: :forbidden
+ it_behaves_like 'accept audit request', status: :ok
end
%i[oauth personal_access_token job_token deploy_token].each do |auth|
@@ -451,7 +451,7 @@ RSpec.shared_examples 'handling get dist tags requests' do |scope: :project|
project.update!(visibility: 'private')
end
- it_behaves_like 'reject package tags request', status: :forbidden
+ it_behaves_like 'accept package tags request', status: :ok
end
end
@@ -524,7 +524,7 @@ RSpec.shared_examples 'handling get dist tags requests' do |scope: :project|
:internal | nil | 'reject package tags request' | :unauthorized
:public | :guest | 'returning response status with error' | :not_found
:internal | :guest | 'returning response status with error' | :not_found
- :private | :guest | 'reject package tags request' | :forbidden
+ :private | :guest | 'returning response status with error' | :not_found
:public | :reporter | 'returning response status with error' | :not_found
end
@@ -778,28 +778,34 @@ RSpec.shared_examples 'handling get metadata requests for packages in multiple p
end
end
- context 'with limited access to the project with the last package version' do
- before_all do
- project2.add_guest(user)
- end
-
- it 'includes matching package versions from authorized projects in the response' do
- subject
-
- expect(json_response['versions'].keys).to contain_exactly(package.version)
- end
- end
-
- context 'with limited access to the project with the first package version' do
+ context 'when allow_guest_plus_roles_to_pull_packages is disabled' do
before do
- project.update!(visibility: 'private')
- project.add_guest(user)
+ stub_feature_flags(allow_guest_plus_roles_to_pull_packages: false)
end
- it 'includes matching package versions from authorized projects in the response' do
- subject
+ context 'with limited access to the project with the last package version' do
+ before_all do
+ project2.add_guest(user)
+ end
- expect(json_response['versions'].keys).to contain_exactly(package2.version)
+ it 'includes matching package versions from authorized projects in the response' do
+ subject
+
+ expect(json_response['versions'].keys).to contain_exactly(package.version)
+ end
+ end
+
+ context 'with limited access to the project with the first package version' do
+ before do
+ project.update!(visibility: 'private')
+ project.add_guest(user)
+ end
+
+ it 'includes matching package versions from authorized projects in the response' do
+ subject
+
+ expect(json_response['versions'].keys).to contain_exactly(package2.version)
+ end
end
end
end
diff --git a/spec/support/shared_examples/requests/api/nuget_endpoints_shared_examples.rb b/spec/support/shared_examples/requests/api/nuget_endpoints_shared_examples.rb
index 150e9a4e004..c7fb144df32 100644
--- a/spec/support/shared_examples/requests/api/nuget_endpoints_shared_examples.rb
+++ b/spec/support/shared_examples/requests/api/nuget_endpoints_shared_examples.rb
@@ -46,8 +46,6 @@ RSpec.shared_examples 'handling nuget metadata requests with package name' do |e
anonymous_requests_example_name = example_names_with_status.fetch(:anonymous_requests_example_name, 'process nuget metadata request at package name level')
anonymous_requests_status = example_names_with_status.fetch(:anonymous_requests_status, :success)
- guest_requests_example_name = example_names_with_status.fetch(:guest_requests_example_name, 'rejects nuget packages access')
- guest_requests_status = example_names_with_status.fetch(:guest_requests_status, :forbidden)
let_it_be(:package_name) { 'Dummy.Package' }
let_it_be(:packages) { create_list(:nuget_package, 5, :with_metadatum, name: package_name, project: project) }
@@ -73,7 +71,7 @@ RSpec.shared_examples 'handling nuget metadata requests with package name' do |e
'PUBLIC' | :guest | false | false | 'rejects nuget packages access' | :unauthorized
'PUBLIC' | :anonymous | false | true | anonymous_requests_example_name | anonymous_requests_status
'PRIVATE' | :developer | true | true | 'process nuget metadata request at package name level' | :success
- 'PRIVATE' | :guest | true | true | guest_requests_example_name | guest_requests_status
+ 'PRIVATE' | :guest | true | true | 'process nuget metadata request at package name level' | :success
'PRIVATE' | :developer | true | false | 'rejects nuget packages access' | :unauthorized
'PRIVATE' | :guest | true | false | 'rejects nuget packages access' | :unauthorized
'PRIVATE' | :developer | false | true | 'rejects nuget packages access' | :not_found
@@ -114,8 +112,6 @@ RSpec.shared_examples 'handling nuget metadata requests with package name and pa
anonymous_requests_example_name = example_names_with_status.fetch(:anonymous_requests_example_name, 'process nuget metadata request at package name and package version level')
anonymous_requests_status = example_names_with_status.fetch(:anonymous_requests_status, :success)
- guest_requests_example_name = example_names_with_status.fetch(:guest_requests_example_name, 'rejects nuget packages access')
- guest_requests_status = example_names_with_status.fetch(:guest_requests_status, :forbidden)
let_it_be(:package_name) { 'Dummy.Package' }
let_it_be(:package) { create(:nuget_package, :with_metadatum, name: package_name, project: project) }
@@ -141,7 +137,7 @@ RSpec.shared_examples 'handling nuget metadata requests with package name and pa
'PUBLIC' | :guest | false | false | 'rejects nuget packages access' | :unauthorized
'PUBLIC' | :anonymous | false | true | anonymous_requests_example_name | anonymous_requests_status
'PRIVATE' | :developer | true | true | 'process nuget metadata request at package name and package version level' | :success
- 'PRIVATE' | :guest | true | true | guest_requests_example_name | guest_requests_status
+ 'PRIVATE' | :guest | true | true | 'process nuget metadata request at package name and package version level' | :success
'PRIVATE' | :developer | true | false | 'rejects nuget packages access' | :unauthorized
'PRIVATE' | :guest | true | false | 'rejects nuget packages access' | :unauthorized
'PRIVATE' | :developer | false | true | 'rejects nuget packages access' | :not_found
@@ -180,8 +176,6 @@ end
RSpec.shared_examples 'handling nuget search requests' do |example_names_with_status: {}|
anonymous_requests_example_name = example_names_with_status.fetch(:anonymous_requests_example_name, 'process nuget search request')
anonymous_requests_status = example_names_with_status.fetch(:anonymous_requests_status, :success)
- guest_requests_example_name = example_names_with_status.fetch(:guest_requests_example_name, 'rejects nuget packages access')
- guest_requests_status = example_names_with_status.fetch(:guest_requests_status, :forbidden)
let_it_be(:package_a) { create(:nuget_package, :with_metadatum, name: 'Dummy.PackageA', project: project) }
let_it_be(:tag) { create(:packages_tag, package: package_a, name: 'test') }
@@ -212,7 +206,7 @@ RSpec.shared_examples 'handling nuget search requests' do |example_names_with_st
'PUBLIC' | :guest | false | false | 'rejects nuget packages access' | :unauthorized
'PUBLIC' | :anonymous | false | true | anonymous_requests_example_name | anonymous_requests_status
'PRIVATE' | :developer | true | true | 'process nuget search request' | :success
- 'PRIVATE' | :guest | true | true | guest_requests_example_name | guest_requests_status
+ 'PRIVATE' | :guest | true | true | 'process nuget search request' | :success
'PRIVATE' | :developer | true | false | 'rejects nuget packages access' | :unauthorized
'PRIVATE' | :guest | true | false | 'rejects nuget packages access' | :unauthorized
'PRIVATE' | :developer | false | true | 'rejects nuget packages access' | :not_found
diff --git a/spec/support/shared_examples/requests/api/pypi_packages_shared_examples.rb b/spec/support/shared_examples/requests/api/pypi_packages_shared_examples.rb
index 6201e21ae98..925def4d5cf 100644
--- a/spec/support/shared_examples/requests/api/pypi_packages_shared_examples.rb
+++ b/spec/support/shared_examples/requests/api/pypi_packages_shared_examples.rb
@@ -241,7 +241,7 @@ RSpec.shared_examples 'pypi simple API endpoint' do
:public | :guest | false | false | 'PyPI package versions' | :success
:public | :anonymous | false | true | 'PyPI package versions' | :success
:private | :developer | true | true | 'PyPI package versions' | :success
- :private | :guest | true | true | 'process PyPI api request' | :forbidden
+ :private | :guest | true | true | 'PyPI package versions' | :success
:private | :developer | true | false | 'process PyPI api request' | :unauthorized
:private | :guest | true | false | 'process PyPI api request' | :unauthorized
:private | :developer | false | true | 'process PyPI api request' | :not_found
@@ -326,7 +326,7 @@ RSpec.shared_examples 'pypi simple index API endpoint' do
:public | :guest | false | false | 'PyPI package index' | :success
:public | :anonymous | false | true | 'PyPI package index' | :success
:private | :developer | true | true | 'PyPI package index' | :success
- :private | :guest | true | true | 'process PyPI api request' | :forbidden
+ :private | :guest | true | true | 'PyPI package index' | :success
:private | :developer | true | false | 'process PyPI api request' | :unauthorized
:private | :guest | true | false | 'process PyPI api request' | :unauthorized
:private | :developer | false | true | 'process PyPI api request' | :not_found
@@ -365,7 +365,7 @@ RSpec.shared_examples 'pypi file download endpoint' do
:public | :guest | false | false | 'PyPI package download' | :success
:public | :anonymous | false | true | 'PyPI package download' | :success
:private | :developer | true | true | 'PyPI package download' | :success
- :private | :guest | true | true | 'rejected package download' | :forbidden
+ :private | :guest | true | true | 'PyPI package download' | :success
:private | :developer | true | false | 'rejected package download' | :unauthorized
:private | :guest | true | false | 'rejected package download' | :unauthorized
:private | :developer | false | true | 'rejected package download' | :not_found
diff --git a/spec/support/shared_examples/requests/api/terraform/modules/v1/packages_shared_examples.rb b/spec/support/shared_examples/requests/api/terraform/modules/v1/packages_shared_examples.rb
index 4389c891efa..5bff73f32f6 100644
--- a/spec/support/shared_examples/requests/api/terraform/modules/v1/packages_shared_examples.rb
+++ b/spec/support/shared_examples/requests/api/terraform/modules/v1/packages_shared_examples.rb
@@ -314,7 +314,7 @@ RSpec.shared_examples 'handling project level terraform module download requests
:public | :developer | false | :personal_access_token | 'grants terraform module package file access' | :success
:public | :guest | false | :personal_access_token | 'grants terraform module package file access' | :success
:private | :developer | true | :personal_access_token | 'grants terraform module package file access' | :success
- :private | :guest | true | :personal_access_token | 'rejects terraform module packages access' | :forbidden
+ :private | :guest | true | :personal_access_token | 'grants terraform module package file access' | :success
:private | :developer | false | :personal_access_token | 'rejects terraform module packages access' | :not_found
:private | :guest | false | :personal_access_token | 'rejects terraform module packages access' | :not_found
:internal | :developer | true | :personal_access_token | 'grants terraform module package file access' | :success
@@ -327,7 +327,7 @@ RSpec.shared_examples 'handling project level terraform module download requests
:public | :developer | false | :job_token | 'grants terraform module package file access' | :success
:public | :guest | false | :job_token | 'grants terraform module package file access' | :success
:private | :developer | true | :job_token | 'grants terraform module package file access' | :success
- :private | :guest | true | :job_token | 'rejects terraform module packages access' | :forbidden
+ :private | :guest | true | :job_token | 'grants terraform module package file access' | :success
:private | :developer | false | :job_token | 'rejects terraform module packages access' | :not_found
:private | :guest | false | :job_token | 'rejects terraform module packages access' | :not_found
:internal | :developer | true | :job_token | 'grants terraform module package file access' | :success
diff --git a/spec/tasks/gitlab/db_rake_spec.rb b/spec/tasks/gitlab/db_rake_spec.rb
index 528ab1048a2..e0248358192 100644
--- a/spec/tasks/gitlab/db_rake_spec.rb
+++ b/spec/tasks/gitlab/db_rake_spec.rb
@@ -1372,7 +1372,7 @@ RSpec.describe 'gitlab:db namespace rake task', :silence_stdout, feature_categor
end
describe 'gitlab:db:reset_as_non_superuser' do
- let(:connection_pool) { instance_double(ActiveRecord::ConnectionAdapters::ConnectionPool ) }
+ let(:connection_pool) { instance_double(ActiveRecord::ConnectionAdapters::ConnectionPool) }
let(:connection) { instance_double(ActiveRecord::ConnectionAdapters::PostgreSQLAdapter) }
let(:configurations) { double(ActiveRecord::DatabaseConfigurations) }
let(:configuration) { instance_double(ActiveRecord::DatabaseConfigurations::HashConfig, env_name: 'test', name: 'main') }
diff --git a/spec/validators/devise_email_validator_spec.rb b/spec/validators/devise_email_validator_spec.rb
index 9ffb46bee4c..1b5126ed1a5 100644
--- a/spec/validators/devise_email_validator_spec.rb
+++ b/spec/validators/devise_email_validator_spec.rb
@@ -83,7 +83,7 @@ RSpec.describe DeviseEmailValidator do
context 'when regexp is set as String' do
it 'raise argument error' do
- expect { described_class.new( { regexp: 'something' } ) }.to raise_error ArgumentError
+ expect { described_class.new({ regexp: 'something' }) }.to raise_error ArgumentError
end
end
diff --git a/spec/views/dashboard/projects/_blank_state_welcome.html.haml_spec.rb b/spec/views/dashboard/projects/_blank_state_welcome.html.haml_spec.rb
index 3a80f38e78d..20ad6e21807 100644
--- a/spec/views/dashboard/projects/_blank_state_welcome.html.haml_spec.rb
+++ b/spec/views/dashboard/projects/_blank_state_welcome.html.haml_spec.rb
@@ -25,7 +25,7 @@ RSpec.describe 'dashboard/projects/_blank_state_welcome.html.haml' do
end
context 'with project creation disabled' do
- let_it_be(:user_projects_limit) { create(:user, projects_limit: 0 ) }
+ let_it_be(:user_projects_limit) { create(:user, projects_limit: 0) }
before do
allow(view).to receive(:current_user).and_return(user_projects_limit)
diff --git a/spec/workers/concerns/gitlab/github_import/object_importer_spec.rb b/spec/workers/concerns/gitlab/github_import/object_importer_spec.rb
index 71b33e19b84..dbf057f85b4 100644
--- a/spec/workers/concerns/gitlab/github_import/object_importer_spec.rb
+++ b/spec/workers/concerns/gitlab/github_import/object_importer_spec.rb
@@ -128,7 +128,7 @@ RSpec.describe Gitlab::GithubImport::ObjectImporter, :aggregate_failures, featur
}
)
- worker.import(project, client, { 'number' => 11, 'github_id' => 2 } )
+ worker.import(project, client, { 'number' => 11, 'github_id' => 2 })
end
it 'logs error when the import fails' do
diff --git a/spec/workers/gitlab/jira_import/stage/import_labels_worker_spec.rb b/spec/workers/gitlab/jira_import/stage/import_labels_worker_spec.rb
index d9c2407a423..410e01cc6b0 100644
--- a/spec/workers/gitlab/jira_import/stage/import_labels_worker_spec.rb
+++ b/spec/workers/gitlab/jira_import/stage/import_labels_worker_spec.rb
@@ -29,7 +29,7 @@ RSpec.describe Gitlab::JiraImport::Stage::ImportLabelsWorker, feature_category:
jira_import.start!
WebMock.stub_request(:get, 'https://jira.example.com/rest/api/2/label?maxResults=500&startAt=0')
- .to_return(body: {}.to_json )
+ .to_return(body: {}.to_json)
end
it_behaves_like 'advance to next stage', :issues
diff --git a/spec/workers/pipeline_schedule_worker_spec.rb b/spec/workers/pipeline_schedule_worker_spec.rb
index a91c9f0d4cb..03a309cfb7e 100644
--- a/spec/workers/pipeline_schedule_worker_spec.rb
+++ b/spec/workers/pipeline_schedule_worker_spec.rb
@@ -76,7 +76,7 @@ RSpec.describe PipelineScheduleWorker, :sidekiq_inline, feature_category: :conti
context 'when gitlab-ci.yml is corrupted' do
before do
- stub_ci_pipeline_yaml_file(YAML.dump(rspec: { variables: 'rspec' } ))
+ stub_ci_pipeline_yaml_file(YAML.dump(rspec: { variables: 'rspec' }))
end
it 'creates a new pipeline' do
diff --git a/spec/workers/purge_dependency_proxy_cache_worker_spec.rb b/spec/workers/purge_dependency_proxy_cache_worker_spec.rb
index e745653fdbc..c998b21b300 100644
--- a/spec/workers/purge_dependency_proxy_cache_worker_spec.rb
+++ b/spec/workers/purge_dependency_proxy_cache_worker_spec.rb
@@ -4,9 +4,9 @@ require 'spec_helper'
RSpec.describe PurgeDependencyProxyCacheWorker, type: :worker, feature_category: :virtual_registry do
let_it_be(:user) { create(:admin) }
- let_it_be_with_refind(:blob) { create(:dependency_proxy_blob ) }
+ let_it_be_with_refind(:blob) { create(:dependency_proxy_blob) }
let_it_be_with_reload(:group) { blob.group }
- let_it_be_with_refind(:manifest) { create(:dependency_proxy_manifest, group: group ) }
+ let_it_be_with_refind(:manifest) { create(:dependency_proxy_manifest, group: group) }
let_it_be(:group_id) { group.id }
subject { described_class.new.perform(user.id, group_id) }
@@ -52,7 +52,7 @@ RSpec.describe PurgeDependencyProxyCacheWorker, type: :worker, feature_category:
end
context 'an invalid user id' do
- let(:user) { double('User', id: 99999 ) }
+ let(:user) { double('User', id: 99999) }
it_behaves_like 'not expiring blobs and manifests'
end
diff --git a/spec/workers/releases/manage_evidence_worker_spec.rb b/spec/workers/releases/manage_evidence_worker_spec.rb
index 4f710e732eb..471e3ba701a 100644
--- a/spec/workers/releases/manage_evidence_worker_spec.rb
+++ b/spec/workers/releases/manage_evidence_worker_spec.rb
@@ -71,7 +71,7 @@ RSpec.describe Releases::ManageEvidenceWorker, feature_category: :release_eviden
context 'when evidence has already been created' do
let(:release) { create(:release, project: project, released_at: 1.hour.since) }
- let!(:evidence) { create(:evidence, release: release ) }
+ let!(:evidence) { create(:evidence, release: release) }
it_behaves_like 'does not create a new Evidence record'
end
diff --git a/tests.yml b/tests.yml
index e6a9fc51438..b98d630f0a2 100644
--- a/tests.yml
+++ b/tests.yml
@@ -124,10 +124,11 @@ mapping:
test: 'spec/mailers/previews_spec.rb'
## BEGIN Remote development GraphQL resolvers (in alphabetical order by resolver source file path)
- - source: 'ee/app/graphql/resolvers/remote_development/admin_workspaces_resolver\.rb'
+ - source: 'ee/app/graphql/resolvers/remote_development/workspaces_admin_resolver\.rb'
test:
- 'ee/spec/requests/api/graphql/remote_development/workspace/*_spec.rb'
- 'ee/spec/requests/api/graphql/remote_development/workspaces/*_spec.rb'
+ - 'ee/spec/requests/api/graphql/remote_development/workspace_variables/*_spec.rb'
- source: 'ee/app/graphql/resolvers/remote_development/cluster_agent/remote_development_agent_config_resolver\.rb'
test:
@@ -140,10 +141,12 @@ mapping:
- source: 'ee/app/graphql/resolvers/remote_development/cluster_agent/workspaces_resolver\.rb'
test:
- 'ee/spec/requests/api/graphql/remote_development/cluster_agent/workspaces/*_spec.rb'
+ - 'ee/spec/requests/api/graphql/remote_development/workspace_variables/*_spec.rb'
- source: 'ee/app/graphql/resolvers/remote_development/workspaces_resolver\.rb'
test:
- 'ee/spec/requests/api/graphql/remote_development/current_user/workspaces/*_spec.rb'
+ - 'ee/spec/requests/api/graphql/remote_development/workspace_variables/*_spec.rb'
- source: 'ee/app/graphql/resolvers/remote_development/namespace/cluster_agents_resolver\.rb'
test:
@@ -154,13 +157,35 @@ mapping:
test:
- 'ee/spec/requests/api/graphql/remote_development/current_user/workspaces/*_spec.rb'
- 'ee/spec/requests/api/graphql/remote_development/workspace/*_spec.rb'
+ - 'ee/spec/requests/api/graphql/remote_development/workspace_variables/*_spec.rb'
## END Remote development GraphQL resolvers
+ ## BEGIN Remote development GraphQL types
+
- source: 'ee/app/graphql/types/remote_development/workspace_type\.rb'
test:
- 'ee/spec/requests/api/graphql/remote_development/workspace/with_id_arg_spec.rb'
+ - source: 'ee/app/graphql/types/remote_development/workspace_variable_input\.rb'
+ test:
+ - 'ee/spec/graphql/types/remote_development/workspace_variable_input_spec.rb'
+ - 'ee/spec/requests/api/graphql/mutations/remote_development/workspace_operations/create_spec.rb'
+
+ - source: 'ee/app/graphql/types/remote_development/workspace_variable_type\.rb'
+ test:
+ - 'ee/spec/requests/api/graphql/remote_development/workspace_variables/with_no_args_spec.rb'
+
+ - source: 'ee/app/graphql/types/remote_development/workspace_variable_type_enum\.rb'
+ test:
+ - 'ee/spec/requests/api/graphql/remote_development/workspace_variables/with_no_args_spec.rb'
+
+ - source: 'ee/app/graphql/types/remote_development/workspace_variable_input_type_enum\.rb'
+ test:
+ - 'ee/spec/requests/api/graphql/mutations/remote_development/workspace_operations/create_spec.rb'
+
+ ## END Remote development GraphQL types
+
# Usage metric schema changes should trigger validations for all metrics and tooling
- source: 'config/metrics/schema/.*\.json'
test: