Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2025-01-17 18:37:25 +00:00
parent a1f2c38e4b
commit dfd347c174
112 changed files with 1173 additions and 417 deletions

View File

@ -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:

View File

@ -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'

View File

@ -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 });
},
};

View File

@ -171,9 +171,9 @@ export default {
<div class="row gl-mt-8">
<main class="col-md-6 gl-pr-8">
<header class="gl-mb-5">
<h3 class="gl-mt-0 gl-text-subtle" data-testid="step-count">
<h2 class="gl-mt-0" data-testid="step-count">
{{ sprintf($options.i18n.stepNofN, { currentStep, stepCount }) }}
</h3>
</h2>
<gl-progress-bar :value="progress" />
</header>
<section class="gl-mb-4">

View File

@ -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

View File

@ -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

View File

@ -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]

View File

@ -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

View File

@ -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-'

View File

@ -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

View File

@ -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?

View File

@ -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

View File

@ -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

View File

@ -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?

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -0,0 +1 @@
22a0025bf1ff0bf243698761c17bcfdb181599a4f31ac696c20511dfd1afbf9b

View File

@ -0,0 +1 @@
79ded29b939ad063a58275fec52191c01161d48b89758b05f3dc3f15c41f018d

View File

@ -0,0 +1 @@
e57acf78acb8d7c507b2e4d611be22d6741f4a0e09970776bb86f2aca266b542

View File

@ -0,0 +1 @@
b358e94b4be73e82fe3140c3cd0e0d2568a1e6eccd682ca0edb932207f28cf26

View File

@ -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))
);

View File

@ -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,

View File

@ -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).

View File

@ -18344,6 +18344,29 @@ The edge type for [`Workspace`](#workspace).
| <a id="workspaceedgecursor"></a>`cursor` | [`String!`](#string) | A cursor for use in pagination. |
| <a id="workspaceedgenode"></a>`node` | [`Workspace`](#workspace) | The item at the end of the edge. |
#### `WorkspaceVariableConnection`
The connection type for [`WorkspaceVariable`](#workspacevariable).
##### Fields
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="workspacevariableconnectionedges"></a>`edges` | [`[WorkspaceVariableEdge]`](#workspacevariableedge) | A list of edges. |
| <a id="workspacevariableconnectionnodes"></a>`nodes` | [`[WorkspaceVariable]`](#workspacevariable) | A list of nodes. |
| <a id="workspacevariableconnectionpageinfo"></a>`pageInfo` | [`PageInfo!`](#pageinfo) | Information to aid in pagination. |
#### `WorkspaceVariableEdge`
The edge type for [`WorkspaceVariable`](#workspacevariable).
##### Fields
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="workspacevariableedgecursor"></a>`cursor` | [`String!`](#string) | A cursor for use in pagination. |
| <a id="workspacevariableedgenode"></a>`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):
| ---- | ---- | ----------- |
| <a id="clusteragentworkspacesactualstates"></a>`actualStates` | [`[String!]`](#string) | Filter workspaces by actual states. |
| <a id="clusteragentworkspacesids"></a>`ids` | [`[RemoteDevelopmentWorkspaceID!]`](#remotedevelopmentworkspaceid) | Filter workspaces by workspace GlobalIDs. For example, `["gid://gitlab/RemoteDevelopment::Workspace/1"]`. |
| <a id="clusteragentworkspacesprojectids"></a>`projectIds` | [`[ProjectID!]`](#projectid) | Filter workspaces by project GlobalID. |
| <a id="clusteragentworkspacesprojectids"></a>`projectIds` | [`[ProjectID!]`](#projectid) | Filter workspaces by project GlobalIDs. |
### `ClusterAgentActivityEvent`
@ -38476,8 +38499,24 @@ Represents a remote development workspace.
| <a id="workspaceupdatedat"></a>`updatedAt` | [`Time!`](#time) | Timestamp of the last update to any mutable workspace property. |
| <a id="workspaceurl"></a>`url` | [`String!`](#string) | URL of the workspace. |
| <a id="workspaceuser"></a>`user` | [`UserCore!`](#usercore) | Owner of the workspace. |
| <a id="workspaceworkspacevariables"></a>`workspaceVariables` **{warning-solid}** | [`WorkspaceVariableConnection`](#workspacevariableconnection) | **Introduced** in GitLab 17.9. **Status**: Experiment. User defined variables associated with the workspace. |
| <a id="workspaceworkspacesagentconfigversion"></a>`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 |
| ---- | ---- | ----------- |
| <a id="workspacevariablecreatedat"></a>`createdAt` | [`Time!`](#time) | Timestamp of when the workspace variable was created. |
| <a id="workspacevariableid"></a>`id` | [`RemoteDevelopmentWorkspaceVariableID!`](#remotedevelopmentworkspacevariableid) | Global ID of the workspace variable. |
| <a id="workspacevariablekey"></a>`key` | [`String`](#string) | Name of the workspace variable. |
| <a id="workspacevariableupdatedat"></a>`updatedAt` | [`Time!`](#time) | Timestamp of when the workspace variable was updated. |
| <a id="workspacevariablevalue"></a>`value` | [`String`](#string) | Value of the workspace variable. |
| <a id="workspacevariablevariabletype"></a>`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.
| ----- | ----------- |
| <a id="workspacevariableinputtypeenvironment"></a>`ENVIRONMENT` | Name type. |
### `WorkspaceVariableType`
Enum for the type of the variable injected in a workspace.
| Value | Description |
| ----- | ----------- |
| <a id="workspacevariabletypeenvironment"></a>`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 |
| ---- | ---- | ----------- |
| <a id="workspacevariableinputkey"></a>`key` | [`String!`](#string) | Key of the variable. |
| <a id="workspacevariableinputtype"></a>`type` | [`WorkspaceVariableInputType!`](#workspacevariableinputtype) | Type of the variable to be injected in a workspace. |
| <a id="workspacevariableinputkey"></a>`key` | [`String!`](#string) | Name of the workspace variable. |
| <a id="workspacevariableinputtype"></a>`type` **{warning-solid}** | [`WorkspaceVariableInputType`](#workspacevariableinputtype) | **Deprecated:** Use `variableType` instead. Deprecated in GitLab 17.9. |
| <a id="workspacevariableinputvalue"></a>`value` | [`String!`](#string) | Value of the variable. |
| <a id="workspacevariableinputvariabletype"></a>`variableType` | [`WorkspaceVariableType`](#workspacevariabletype) | Type of the variable to be injected in a workspace. |

View File

@ -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).

View File

@ -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.

View File

@ -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.

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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")

View File

@ -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 ""

View File

@ -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);

View File

@ -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' } : {}),
},
},
);

View File

@ -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

View File

@ -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',

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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 }

View File

@ -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"
}
}
}
}

View File

@ -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);
});
});
});

View File

@ -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

View File

@ -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!

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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 }

View File

@ -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

View File

@ -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

View File

@ -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 }

View File

@ -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

View File

@ -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

View File

@ -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) }

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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) }

View File

@ -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'

View File

@ -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))

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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
[
{

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

Some files were not shown because too many files have changed in this diff Show More