Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
5ae452ecba
commit
3c5025227f
|
|
@ -31,7 +31,7 @@ Gitlab/DocUrl:
|
|||
- 'lib/gitlab/ci/config/entry/processable.rb'
|
||||
- 'lib/gitlab/config_checker/external_database_checker.rb'
|
||||
- 'lib/gitlab/config_checker/puma_rugged_checker.rb'
|
||||
- 'lib/gitlab/database.rb'
|
||||
- 'lib/gitlab/database_warnings.rb'
|
||||
- 'lib/gitlab/database/migration_helpers/automatic_lock_writes_on_tables.rb'
|
||||
- 'lib/gitlab/database/migration_helpers/v2.rb'
|
||||
- 'lib/gitlab/database/migrations/batched_background_migration_helpers.rb'
|
||||
|
|
|
|||
|
|
@ -30,7 +30,6 @@ Naming/HeredocDelimiterNaming:
|
|||
- 'lib/feature/shared.rb'
|
||||
- 'lib/gitlab/cache/import/caching.rb'
|
||||
- 'lib/gitlab/conflict/file_collection.rb'
|
||||
- 'lib/gitlab/database.rb'
|
||||
- 'lib/gitlab/database/migration_helpers.rb'
|
||||
- 'lib/gitlab/database/migration_helpers/v2.rb'
|
||||
- 'lib/gitlab/exclusive_lease.rb'
|
||||
|
|
|
|||
17
CHANGELOG.md
17
CHANGELOG.md
|
|
@ -2,6 +2,17 @@
|
|||
documentation](doc/development/changelog.md) for instructions on adding your own
|
||||
entry.
|
||||
|
||||
## 16.3.4 (2023-09-18)
|
||||
|
||||
### Fixed (2 changes)
|
||||
|
||||
- [Fix Geo secondary proxying Git pulls unnecessarily](gitlab-org/security/gitlab@d4ac7db42e80dec97fee07c50471f1e7b60d3bcc) **GitLab Enterprise Edition**
|
||||
- [Use new indexer, fix removing blobs from index](gitlab-org/security/gitlab@5d48e6871bc6f1c36b93c10f2a54cf28d6adbc65) **GitLab Enterprise Edition**
|
||||
|
||||
### Security (1 change)
|
||||
|
||||
- [Enforce that the policy is executed by the bot user](gitlab-org/security/gitlab@3f278f761f18ee0b14aca68e2e5f764e1e274176) ([merge request](gitlab-org/security/gitlab!3568))
|
||||
|
||||
## 16.3.3 (2023-09-12)
|
||||
|
||||
### Fixed (2 changes)
|
||||
|
|
@ -825,6 +836,12 @@ entry.
|
|||
- [Fix test pollution in count_deployments_metric_spec](gitlab-org/gitlab@610e6a033fe9b20aabc237b18837cddf150d4d1b) ([merge request](gitlab-org/gitlab!126808))
|
||||
- [Update BulkImports::PipelineBatchWorker resource boundary](gitlab-org/gitlab@7d2477d81bcc2d035be26587802706f7098b6e44) ([merge request](gitlab-org/gitlab!126696))
|
||||
|
||||
## 16.2.7 (2023-09-18)
|
||||
|
||||
### Security (1 change)
|
||||
|
||||
- [Enforce that the policy is executed by the bot user](gitlab-org/security/gitlab@336d6829bf5268dbbb1ccdaa224ed65c431a9ed6) ([merge request](gitlab-org/security/gitlab!3569))
|
||||
|
||||
## 16.2.6 (2023-09-12)
|
||||
|
||||
### Fixed (3 changes)
|
||||
|
|
|
|||
|
|
@ -102,17 +102,16 @@ class ActiveSession
|
|||
|
||||
# set marketing cookie when user has active session
|
||||
def self.set_active_user_cookie(auth)
|
||||
auth.cookies[:about_gitlab_active_user] =
|
||||
expiration_time = 2.weeks.from_now
|
||||
|
||||
auth.cookies[:gitlab_user] =
|
||||
{
|
||||
value: true,
|
||||
domain: Gitlab.config.gitlab.host
|
||||
domain: Gitlab.config.gitlab.host,
|
||||
expires: expiration_time
|
||||
}
|
||||
end
|
||||
|
||||
def self.unset_active_user_cookie(auth)
|
||||
auth.cookies.delete :about_gitlab_active_user
|
||||
end
|
||||
|
||||
def self.list(user)
|
||||
Gitlab::Redis::Sessions.with do |redis|
|
||||
cleaned_up_lookup_entries(redis, user).map do |raw_session|
|
||||
|
|
|
|||
|
|
@ -8,15 +8,15 @@ class PoolRepository < ApplicationRecord
|
|||
include AfterCommitQueue
|
||||
|
||||
belongs_to :source_project, class_name: 'Project'
|
||||
validates :source_project, presence: true
|
||||
|
||||
has_many :member_projects, class_name: 'Project'
|
||||
|
||||
after_create :set_disk_path
|
||||
|
||||
scope :by_source_project, ->(project) { where(source_project: project) }
|
||||
scope :by_source_project_and_shard_name, ->(project, shard_name) do
|
||||
by_source_project(project)
|
||||
scope :by_disk_path, ->(disk_path) { where(disk_path: disk_path) }
|
||||
scope :by_disk_path_and_shard_name, ->(disk_path, shard_name) do
|
||||
by_disk_path(disk_path)
|
||||
.for_repository_storage(shard_name)
|
||||
end
|
||||
|
||||
|
|
@ -101,8 +101,8 @@ class PoolRepository < ApplicationRecord
|
|||
@object_pool ||= Gitlab::Git::ObjectPool.new(
|
||||
shard.name,
|
||||
disk_path + '.git',
|
||||
source_project.repository.raw,
|
||||
source_project.full_path
|
||||
source_project&.repository&.raw,
|
||||
source_project&.full_path
|
||||
)
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -2846,7 +2846,7 @@ class Project < ApplicationRecord
|
|||
return if old_pool_repository.blank?
|
||||
return if pool_repository_shard_matches_repository?(old_pool_repository)
|
||||
|
||||
new_pool_repository = PoolRepository.by_source_project_and_shard_name(old_pool_repository.source_project, repository_storage).take!
|
||||
new_pool_repository = PoolRepository.by_disk_path_and_shard_name(old_pool_repository.disk_path, repository_storage).take!
|
||||
update!(pool_repository: new_pool_repository)
|
||||
|
||||
old_pool_repository.unlink_repository(repository, disconnect: !pending_delete?)
|
||||
|
|
|
|||
|
|
@ -80,8 +80,8 @@ module Projects
|
|||
end
|
||||
|
||||
def pool_repository_exists_for?(shard_name:, pool_repository:)
|
||||
PoolRepository.by_source_project_and_shard_name(
|
||||
pool_repository.source_project,
|
||||
PoolRepository.by_disk_path_and_shard_name(
|
||||
pool_repository.disk_path,
|
||||
shard_name
|
||||
).exists?
|
||||
end
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ module Users
|
|||
end
|
||||
|
||||
def signup_params
|
||||
super + [:skip_confirmation]
|
||||
super + [:skip_confirmation, :external]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
Gitlab::Database.check_single_connection_and_print_warning
|
||||
Gitlab::DatabaseWarnings.check_single_connection_and_print_warning
|
||||
|
|
|
|||
|
|
@ -3,4 +3,4 @@
|
|||
raise "PostgreSQL is the only supported database from GitLab 12.1" unless
|
||||
ApplicationRecord.database.postgresql?
|
||||
|
||||
Gitlab::Database.check_postgres_version_and_print_warning
|
||||
Gitlab::DatabaseWarnings.check_postgres_version_and_print_warning
|
||||
|
|
|
|||
|
|
@ -38,8 +38,6 @@ Rails.application.configure do |config|
|
|||
|
||||
Warden::Manager.before_logout(scope: :user) do |user, auth, opts|
|
||||
user ||= auth.user
|
||||
# deletes marketing cookie when user session ends
|
||||
ActiveSession.unset_active_user_cookie(auth) if ::Gitlab.com?
|
||||
# Rails CSRF protection may attempt to log out a user before that
|
||||
# user even logs in
|
||||
next unless user
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ the entry, instead of relying on the key changing.
|
|||
|
||||
### Multi-key commands
|
||||
|
||||
GitLab supports Redis Cluster only for the Redis [rate-limiting](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/redis/rate_limiting.rb) type, introduced in [epic 823](https://gitlab.com/groups/gitlab-com/gl-infra/-/epics/823).
|
||||
GitLab supports Redis Cluster for [cache-related workloads](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/redis/cache.rb) type, introduced in [epic 878](https://gitlab.com/groups/gitlab-com/gl-infra/-/epics/878).
|
||||
|
||||
This imposes an additional constraint on naming: where GitLab is performing
|
||||
operations that require several keys to be held on the same Redis server - for
|
||||
|
|
@ -81,6 +81,12 @@ Developers are highly encouraged to use [hash-tags](https://redis.io/docs/refere
|
|||
where appropriate to facilitate future adoption of Redis Cluster in more Redis types. For example, the Namespace model uses hash-tags
|
||||
for its [config cache keys](https://gitlab.com/gitlab-org/gitlab/-/blob/1a12337058f260d38405886d82da5e8bb5d8da0b/app/models/namespace.rb#L786).
|
||||
|
||||
To perform multi-key commands, developers may use the [`Gitlab::Redis::CrossSlot::Pipeline`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/redis/cross_slot.rb) wrapper.
|
||||
However, this does not work for [transactions](https://redis.io/docs/interact/transactions/) as Redis Cluster does not support cross-slot transactions.
|
||||
|
||||
For `Rails.cache`, we handle the `MGET` command found in `read_multi_get` by [patching it](https://gitlab.com/gitlab-org/gitlab/-/blob/c2bad2aac25e2f2778897bd4759506a72b118b15/lib/gitlab/patch/redis_cache_store.rb#L10) to use the `Gitlab::Redis::CrossSlot::Pipeline` wrapper.
|
||||
The minimum size of the pipeline is set to 1000 commands and it can be adjusted by using the `GITLAB_REDIS_CLUSTER_PIPELINE_BATCH_LIMIT` environment variable.
|
||||
|
||||
## Redis in structured logging
|
||||
|
||||
For GitLab Team Members: There are <i class="fa fa-youtube-play youtube" aria-hidden="true"></i>
|
||||
|
|
|
|||
|
|
@ -148,7 +148,8 @@ The workaround is to amend your group or instance push rules to allow branches f
|
|||
- Scan result policies created at the group or sub-group level can take some time to apply to all the merge requests in the group.
|
||||
- Scheduled scan execution policies run with a minimum 15 minute cadence. Learn more [about the schedule rule type](../policies/scan-execution-policies.md#schedule-rule-type).
|
||||
- When scheduling pipelines, keep in mind that CRON scheduling is based on UTC on GitLab SaaS and is based on your server time for self managed instances. When testing new policies, it may appear pipelines are not running properly when in fact they are scheduled in your server's timezone.
|
||||
- When enforcing scan execution policies, security policies creates a bot in the target project that will trigger scheduled pipelines to ensure enforcement. If the bot is deleted, the target project's pipeline will default back to be triggered by the user who last updated the security policy project's `policy.yml` file. The user must have permission to trigger the pipeline in the project for the policy to be enforced, and the pipeline to run.
|
||||
- When enforcing scan execution policies, security policies creates a bot in the target project that will trigger scheduled pipelines to ensure enforcement. If the bot is
|
||||
deleted or missing, the target project's pipeline will not be executed. To recreate a security policy bot user unlink and link the security policy project again.
|
||||
- You should not link a security policy project to a development project and to the group or sub-group the development project belongs to at the same time. Linking this way will result in approval rules from the Scan Result Policy not being applied to merge requests in the development project.
|
||||
- When creating a Scan Result Policy, neither the array `severity_levels` nor the array `vulnerability_states` in the [scan_finding rule](../policies/scan-result-policies.md#scan_finding-rule-type) can be left empty; for a working rule, at least one entry must exist.
|
||||
- When configuring pipeline and scan result policies, it's important to remember that security scans performed in manual jobs aren't verified to determine whether MR approval is required. When you run a manual job with security scans, it won't ensure approval even if vulnerabilities are introduced.
|
||||
|
|
|
|||
|
|
@ -141,7 +141,7 @@ This rule schedules a scan pipeline, enforcing the defined actions on the schedu
|
|||
|
||||
Scheduled scan pipelines are triggered by a security policy bot user that is a guest member of the project with elevated permissions for users of type `security_policy_bot` so it may carry out this task. Security policy bot users are automatically created when the security policy project is linked, and removed when the security policy project is unlinked.
|
||||
|
||||
If the project does not have a security policy bot user, the scheduled scan pipeline is triggered by the user that modified the security policy project last.
|
||||
If the project does not have a security policy bot user, the scheduled scan pipeline will not be triggered. To recreate a security policy bot user unlink and link the security policy project again.
|
||||
|
||||
GitLab supports the following types of CRON syntax for the `cadence` field:
|
||||
|
||||
|
|
|
|||
|
|
@ -145,52 +145,48 @@ subjects:
|
|||
|
||||
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/131144) in GitLab 16.4.
|
||||
|
||||
You can [configure an agent](#configure-kubernetes-access) to allow GitLab users to access a cluster with the Kubernetes API.
|
||||
You can configure an agent to allow GitLab users to access a cluster with the Kubernetes API.
|
||||
|
||||
Use a [personal access token](../../profile/personal_access_tokens.md)
|
||||
with the `k8s_proxy` scope to access the cluster via `kubectl`:
|
||||
Prerequisite:
|
||||
|
||||
- You have an agent configured with the `user_access` entry.
|
||||
|
||||
To grant Kubernetes API access:
|
||||
|
||||
1. Configure the agent with the [`user_access` entry](user_access.md).
|
||||
1. On the left sidebar, select **Search or go to** and find your project.
|
||||
1. Select **Operate > Kubernetes clusters** and retrieve the numerical ID of the agent you want to access. You need the ID to construct the full API token.
|
||||
1. Create a [personal access token](../../profile/personal_access_tokens.md) with the `k8s_proxy` scope. You need the access token to construct the full API token.
|
||||
1. Construct `kube config` entries to access the cluster:
|
||||
1. Make sure that the proper `kube config` is selected.
|
||||
For example, you can set the `KUBECONFIG` environment variable.
|
||||
1. Add the GitLab KAS proxy cluster to the `kube config`:
|
||||
1. Make sure that the proper `kube config` is selected.
|
||||
For example, you can set the `KUBECONFIG` environment variable.
|
||||
1. Add the GitLab KAS proxy cluster to the `kube config`:
|
||||
|
||||
```shell
|
||||
kubectl config set-cluster gitlab --server "https://kas.gitlab.com/k8s-proxy"
|
||||
```
|
||||
```shell
|
||||
kubectl config set-cluster <cluster_name> --server "https://kas.gitlab.com/k8s-proxy"
|
||||
```
|
||||
|
||||
The `server` argument points to the KAS address of your GitLab instance.
|
||||
On GitLab.com, this is `https://kas.gitlab.com/k8s-proxy`.
|
||||
You can get the KAS address of your instance when you register an agent.
|
||||
The `server` argument points to the KAS address of your GitLab instance.
|
||||
On GitLab.com, this is `https://kas.gitlab.com/k8s-proxy`.
|
||||
You can get the KAS address of your instance when you register an agent.
|
||||
|
||||
If needed, change `gitlab` to the name of your cluster.
|
||||
1. Use your numerical agent ID and personal access token to construct an API token:
|
||||
1. Use your numerical agent ID and personal access token to construct an API token:
|
||||
|
||||
```shell
|
||||
kubectl config set-credentials gitlab-user --token "pat:<agent-id>:<token>"
|
||||
```
|
||||
```shell
|
||||
kubectl config set-credentials <gitlab_user> --token "pat:<agent-id>:<token>"
|
||||
```
|
||||
|
||||
If needed, change `gitlab-user` to your credentials name.
|
||||
1. Add the context to combine the cluster and the user:
|
||||
1. Add the context to combine the cluster and the user:
|
||||
|
||||
```shell
|
||||
kubectl config set-context gitlab-agent --cluster gitlab --user gitlab-user
|
||||
```
|
||||
```shell
|
||||
kubectl config set-context <gitlab_agent> --cluster <cluster_name> --user <gitlab_user>
|
||||
```
|
||||
|
||||
If needed, change the arguments to `cluster` and `user`. The arguments must match the cluster name and user from the previous steps.
|
||||
1. Activate the new context:
|
||||
|
||||
You can customize the context name.
|
||||
1. Activate the new context:
|
||||
```shell
|
||||
kubectl config use-context <gitlab_agent>
|
||||
```
|
||||
|
||||
```shell
|
||||
kubectl config use-context gitlab-agent
|
||||
```
|
||||
|
||||
If needed, change `gitlab-agent` to the context name you set in the last step.
|
||||
1. Check that the configuration works:
|
||||
|
||||
```shell
|
||||
|
|
|
|||
|
|
@ -397,15 +397,15 @@ When you sign in, three cookies are set:
|
|||
|
||||
- A session cookie called `_gitlab_session`.
|
||||
This cookie has no set expiration date. However, it expires based on its `session_expire_delay`.
|
||||
- A session cookie called `about_gitlab_active_user`.
|
||||
This cookie is used by the [marketing site](https://about.gitlab.com/) to determine if a user has an active GitLab session. No user information is passed to the cookie and it expires with the session.
|
||||
- A session cookie called `gitlab_user`.
|
||||
This cookie is used by the [marketing site](https://about.gitlab.com/) to determine if a user has an active GitLab session. No user information is passed to the cookie and it expires two weeks from login.
|
||||
- A persistent cookie called `remember_user_token`, which is set only if you selected **Remember me** on the sign-in page.
|
||||
|
||||
When you close your browser, the `_gitlab_session` and `about_gitlab_active_user` cookies are usually cleared client-side.
|
||||
When you close your browser, the `_gitlab_session` and `gitlab_user` cookies are usually cleared client-side.
|
||||
When it expires or isn't available, GitLab:
|
||||
|
||||
- Uses the `remember_user_token`cookie to get you a new `_gitlab_session` cookie and keep you signed in, even if you close your browser.
|
||||
- Sets the `about_gitlab_active_user` to `true`.
|
||||
- Sets the `gitlab_user` to `true`.
|
||||
|
||||
When both the `remember_user_token` and `_gitlab_session` cookies are gone or expired, you must sign in again.
|
||||
|
||||
|
|
|
|||
|
|
@ -185,59 +185,6 @@ module Gitlab
|
|||
end
|
||||
# rubocop: enable CodeReuse/ActiveRecord
|
||||
|
||||
def self.check_postgres_version_and_print_warning
|
||||
return if Gitlab::Runtime.rails_runner?
|
||||
|
||||
database_base_models.each do |name, model|
|
||||
database = Gitlab::Database::Reflection.new(model)
|
||||
|
||||
next if database.postgresql_minimum_supported_version?
|
||||
|
||||
Kernel.warn ERB.new(Rainbow.new.wrap(<<~EOS).red).result
|
||||
|
||||
██ ██ █████ ██████ ███ ██ ██ ███ ██ ██████
|
||||
██ ██ ██ ██ ██ ██ ████ ██ ██ ████ ██ ██
|
||||
██ █ ██ ███████ ██████ ██ ██ ██ ██ ██ ██ ██ ██ ███
|
||||
██ ███ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
|
||||
███ ███ ██ ██ ██ ██ ██ ████ ██ ██ ████ ██████
|
||||
|
||||
******************************************************************************
|
||||
You are using PostgreSQL #{database.version} for the #{name} database, but this version of GitLab requires PostgreSQL >= <%= Gitlab::Database::MINIMUM_POSTGRES_VERSION %>.
|
||||
<% if Rails.env.development? || Rails.env.test? %>
|
||||
If using gitlab-development-kit, please find the relevant steps here:
|
||||
https://gitlab.com/gitlab-org/gitlab-development-kit/-/blob/main/doc/howto/postgresql.md#upgrade-postgresql
|
||||
<% end %>
|
||||
Please upgrade your environment to a supported PostgreSQL version. See
|
||||
https://docs.gitlab.com/ee/install/requirements.html#database for details.
|
||||
******************************************************************************
|
||||
EOS
|
||||
rescue ActiveRecord::ActiveRecordError, PG::Error
|
||||
# ignore - happens when Rake tasks yet have to create a database, e.g. for testing
|
||||
end
|
||||
end
|
||||
|
||||
def self.check_single_connection_and_print_warning
|
||||
return if Gitlab::Runtime.rails_runner?
|
||||
return unless database_mode == MODE_SINGLE_DATABASE
|
||||
|
||||
Kernel.warn ERB.new(Rainbow.new.wrap(<<~EOS).red).result
|
||||
|
||||
██ ██ █████ ██████ ███ ██ ██ ███ ██ ██████
|
||||
██ ██ ██ ██ ██ ██ ████ ██ ██ ████ ██ ██
|
||||
██ █ ██ ███████ ██████ ██ ██ ██ ██ ██ ██ ██ ██ ███
|
||||
██ ███ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
|
||||
███ ███ ██ ██ ██ ██ ██ ████ ██ ██ ████ ██████
|
||||
|
||||
******************************************************************************
|
||||
Your database has a single connection, and single connections were
|
||||
deprecated in GitLab 15.9 https://docs.gitlab.com/ee/update/deprecations.html#single-database-connection-is-deprecated.
|
||||
|
||||
Please add a :ci section to your database, following these instructions:
|
||||
https://docs.gitlab.com/ee/install/installation.html#configure-gitlab-db-settings.
|
||||
******************************************************************************
|
||||
EOS
|
||||
end
|
||||
|
||||
def self.random
|
||||
"RANDOM()"
|
||||
end
|
||||
|
|
|
|||
|
|
@ -0,0 +1,60 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Gitlab
|
||||
module DatabaseWarnings
|
||||
def self.check_postgres_version_and_print_warning
|
||||
return if Gitlab::Runtime.rails_runner?
|
||||
|
||||
Gitlab::Database.database_base_models.each do |name, model|
|
||||
database = Gitlab::Database::Reflection.new(model)
|
||||
|
||||
next if database.postgresql_minimum_supported_version?
|
||||
|
||||
Kernel.warn ERB.new(Rainbow.new.wrap(<<~WARNING).red).result
|
||||
|
||||
██ ██ █████ ██████ ███ ██ ██ ███ ██ ██████
|
||||
██ ██ ██ ██ ██ ██ ████ ██ ██ ████ ██ ██
|
||||
██ █ ██ ███████ ██████ ██ ██ ██ ██ ██ ██ ██ ██ ███
|
||||
██ ███ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
|
||||
███ ███ ██ ██ ██ ██ ██ ████ ██ ██ ████ ██████
|
||||
|
||||
******************************************************************************
|
||||
You are using PostgreSQL #{database.version} for the #{name} database, but this version of GitLab requires PostgreSQL >= <%= Gitlab::Database::MINIMUM_POSTGRES_VERSION %>.
|
||||
<% if Rails.env.development? || Rails.env.test? %>
|
||||
If using gitlab-development-kit, please find the relevant steps here:
|
||||
https://gitlab.com/gitlab-org/gitlab-development-kit/-/blob/main/doc/howto/postgresql.md#upgrade-postgresql
|
||||
<% end %>
|
||||
Please upgrade your environment to a supported PostgreSQL version. See
|
||||
https://docs.gitlab.com/ee/install/requirements.html#database for details.
|
||||
******************************************************************************
|
||||
WARNING
|
||||
rescue ActiveRecord::ActiveRecordError, PG::Error
|
||||
# ignore - happens when Rake tasks yet have to create a database, e.g. for testing
|
||||
end
|
||||
end
|
||||
|
||||
def self.check_single_connection_and_print_warning
|
||||
return if Gitlab::Runtime.rails_runner?
|
||||
return unless Gitlab::Database.database_mode == Gitlab::Database::MODE_SINGLE_DATABASE
|
||||
|
||||
Kernel.warn ERB.new(Rainbow.new.wrap(<<~WARNING).red).result
|
||||
|
||||
██ ██ █████ ██████ ███ ██ ██ ███ ██ ██████
|
||||
██ ██ ██ ██ ██ ██ ████ ██ ██ ████ ██ ██
|
||||
██ █ ██ ███████ ██████ ██ ██ ██ ██ ██ ██ ██ ██ ███
|
||||
██ ███ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
|
||||
███ ███ ██ ██ ██ ██ ██ ████ ██ ██ ████ ██████
|
||||
|
||||
******************************************************************************
|
||||
Your database has a single connection, and single connections were
|
||||
deprecated in GitLab 15.9 https://docs.gitlab.com/ee/update/deprecations.html#single-database-connection-is-deprecated.
|
||||
|
||||
Please add a :ci section to your database, following these instructions:
|
||||
https://docs.gitlab.com/ee/install/installation.html#configure-gitlab-db-settings.
|
||||
******************************************************************************
|
||||
WARNING
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Gitlab::DatabaseWarnings.prepend_mod_with('Gitlab::DatabaseWarnings')
|
||||
|
|
@ -3,8 +3,6 @@
|
|||
module Gitlab
|
||||
module Patch
|
||||
module RedisCacheStore
|
||||
PIPELINE_BATCH_SIZE = 100
|
||||
|
||||
# We will try keep patched code explicit and matching the original signature in
|
||||
# https://github.com/rails/rails/blob/v6.1.7.2/activesupport/lib/active_support/cache/redis_cache_store.rb#L361
|
||||
def read_multi_mget(*names) # rubocop:disable Style/ArgumentsForwarding
|
||||
|
|
@ -21,7 +19,7 @@ module Gitlab
|
|||
|
||||
delete_count = 0
|
||||
redis.with do |conn|
|
||||
entries.each_slice(PIPELINE_BATCH_SIZE) do |subset|
|
||||
entries.each_slice(pipeline_batch_size) do |subset|
|
||||
delete_count += Gitlab::Redis::CrossSlot::Pipeline.new(conn).pipelined do |pipeline|
|
||||
subset.each { |entry| pipeline.del(entry) }
|
||||
end.sum
|
||||
|
|
@ -59,7 +57,7 @@ module Gitlab
|
|||
end
|
||||
|
||||
def pipeline_mget(conn, keys)
|
||||
keys.each_slice(PIPELINE_BATCH_SIZE).flat_map do |subset|
|
||||
keys.each_slice(pipeline_batch_size).flat_map do |subset|
|
||||
Gitlab::Redis::CrossSlot::Pipeline.new(conn).pipelined do |p|
|
||||
subset.each { |key| p.get(key) }
|
||||
end
|
||||
|
|
@ -68,6 +66,10 @@ module Gitlab
|
|||
|
||||
private
|
||||
|
||||
def pipeline_batch_size
|
||||
@pipeline_batch_size ||= [ENV['GITLAB_REDIS_CLUSTER_PIPELINE_BATCH_LIMIT'].to_i, 1000].max
|
||||
end
|
||||
|
||||
def enable_rails_cache_pipeline_patch?
|
||||
redis.with { |c| ::Gitlab::Redis::ClusterUtil.cluster?(c) }
|
||||
end
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ module QA
|
|||
|
||||
def has_file_explorer?
|
||||
page.has_css?('.explorer-folders-view', visible: true)
|
||||
page.has_css?('[aria-label="Files Explorer"]', visible: true)
|
||||
end
|
||||
|
||||
def right_click_file_explorer
|
||||
|
|
@ -33,11 +34,11 @@ module QA
|
|||
end
|
||||
|
||||
def has_upload_menu_item?
|
||||
page.has_css?('[aria-label="Upload..."]', visible: true)
|
||||
page.has_css?('.menu-item-check', visible: true)
|
||||
end
|
||||
|
||||
def click_upload_menu_item
|
||||
page.find('[aria-label="Upload..."]').click
|
||||
page.find('[aria-label="Upload..."]', visible: true).click
|
||||
end
|
||||
|
||||
def enter_file_input(file)
|
||||
|
|
@ -170,11 +171,10 @@ module QA
|
|||
# We need to execute a script on the iframe to stub out the iframes body.removeChild to add it back in.
|
||||
page.execute_script("document.body.removeChild = function(){};")
|
||||
|
||||
right_click_file_explorer
|
||||
has_upload_menu_item?
|
||||
|
||||
# Use for stability, WebIDE inside an iframe is finnicky, webdriver sometimes moves too fast
|
||||
Support::Waiter.wait_until(max_duration: 60, retry_on_exception: true) do
|
||||
Support::Waiter.wait_until(max_duration: 20, retry_on_exception: true) do
|
||||
right_click_file_explorer
|
||||
has_upload_menu_item?
|
||||
click_upload_menu_item
|
||||
enter_file_input(file_path)
|
||||
end
|
||||
|
|
|
|||
|
|
@ -67,11 +67,10 @@ module QA
|
|||
|
||||
context 'for personal projects' do
|
||||
let!(:project) do
|
||||
Resource::Project.fabricate_via_api! do |project|
|
||||
project.api_client = owner_api_client
|
||||
project.name = 'qa-owner-personal-project'
|
||||
project.personal_namespace = owner.username
|
||||
end
|
||||
create(:project,
|
||||
name: 'qa-owner-personal-project',
|
||||
api_client: owner_api_client,
|
||||
personal_namespace: owner.username)
|
||||
end
|
||||
|
||||
it_behaves_like 'adds user as owner', :personal_project, 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/352542'
|
||||
|
|
@ -80,13 +79,7 @@ module QA
|
|||
|
||||
context 'for group projects' do
|
||||
let!(:group) { create(:group) }
|
||||
|
||||
let!(:project) do
|
||||
Resource::Project.fabricate_via_api! do |project|
|
||||
project.group = group
|
||||
project.name = 'qa-owner-group-project'
|
||||
end
|
||||
end
|
||||
let!(:project) { create(:project, name: 'qa-owner-group-project', group: group) }
|
||||
|
||||
it_behaves_like 'adds user as owner', :group_project, 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/366436'
|
||||
it_behaves_like 'adds user as maintainer', 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/366435'
|
||||
|
|
|
|||
|
|
@ -22,12 +22,7 @@ module QA
|
|||
end
|
||||
|
||||
let(:project) do
|
||||
Resource::Project.fabricate_via_api! do |project|
|
||||
project.name = 'project-for-tags'
|
||||
project.initialize_with_readme = true
|
||||
project.api_client = followed_user_api_client
|
||||
project.group = group
|
||||
end
|
||||
create(:project, :with_readme, name: 'project-for-tags', api_client: followed_user_api_client, group: group)
|
||||
end
|
||||
|
||||
let(:merge_request) do
|
||||
|
|
|
|||
|
|
@ -9,13 +9,7 @@ module QA
|
|||
|
||||
let!(:group) { create(:group, path: "group-to-test-access-termination-#{SecureRandom.hex(8)}") }
|
||||
|
||||
let!(:project) do
|
||||
Resource::Project.fabricate_via_api! do |project|
|
||||
project.group = group
|
||||
project.name = "project-for-user-access-termination"
|
||||
project.initialize_with_readme = true
|
||||
end
|
||||
end
|
||||
let!(:project) { create(:project, :with_readme, name: 'project-for-user-access-termination', group: group) }
|
||||
|
||||
context 'with terminated parent group membership' do
|
||||
before do
|
||||
|
|
|
|||
|
|
@ -21,11 +21,7 @@ module QA
|
|||
end
|
||||
|
||||
let!(:sub_group_project) do
|
||||
Resource::Project.fabricate_via_api! do |project|
|
||||
project.group = sub_group
|
||||
project.name = "sub-group-project-to-test-user-access"
|
||||
project.initialize_with_readme = true
|
||||
end
|
||||
create(:project, :with_readme, name: 'sub-group-project-to-test-user-access', group: sub_group)
|
||||
end
|
||||
|
||||
before do
|
||||
|
|
@ -57,11 +53,7 @@ module QA
|
|||
|
||||
context 'when added to sub-group' do
|
||||
let!(:parent_group_project) do
|
||||
Resource::Project.fabricate_via_api! do |project|
|
||||
project.group = parent_group
|
||||
project.name = "parent-group-project-to-test-user-access"
|
||||
project.initialize_with_readme = true
|
||||
end
|
||||
create(:project, :with_readme, name: 'parent-group-project-to-test-user-access', group: parent_group)
|
||||
end
|
||||
|
||||
let!(:sub_group_user) { create(:user, api_client: admin_api_client) }
|
||||
|
|
|
|||
|
|
@ -198,96 +198,6 @@ RSpec.describe Gitlab::Database, feature_category: :database do
|
|||
end
|
||||
end
|
||||
|
||||
describe '.check_postgres_version_and_print_warning' do
|
||||
let(:reflect) { instance_spy(Gitlab::Database::Reflection) }
|
||||
|
||||
subject { described_class.check_postgres_version_and_print_warning }
|
||||
|
||||
before do
|
||||
allow(Gitlab::Database::Reflection)
|
||||
.to receive(:new)
|
||||
.and_return(reflect)
|
||||
end
|
||||
|
||||
it 'prints a warning if not compliant with minimum postgres version' do
|
||||
allow(reflect).to receive(:postgresql_minimum_supported_version?).and_return(false)
|
||||
|
||||
expect(Kernel)
|
||||
.to receive(:warn)
|
||||
.with(/You are using PostgreSQL/)
|
||||
.exactly(described_class.database_base_models.length)
|
||||
.times
|
||||
|
||||
subject
|
||||
end
|
||||
|
||||
it 'doesnt print a warning if compliant with minimum postgres version' do
|
||||
allow(reflect).to receive(:postgresql_minimum_supported_version?).and_return(true)
|
||||
|
||||
expect(Kernel).not_to receive(:warn).with(/You are using PostgreSQL/)
|
||||
|
||||
subject
|
||||
end
|
||||
|
||||
it 'doesnt print a warning in Rails runner environment' do
|
||||
allow(reflect).to receive(:postgresql_minimum_supported_version?).and_return(false)
|
||||
allow(Gitlab::Runtime).to receive(:rails_runner?).and_return(true)
|
||||
|
||||
expect(Kernel).not_to receive(:warn).with(/You are using PostgreSQL/)
|
||||
|
||||
subject
|
||||
end
|
||||
|
||||
it 'ignores ActiveRecord errors' do
|
||||
allow(reflect).to receive(:postgresql_minimum_supported_version?).and_raise(ActiveRecord::ActiveRecordError)
|
||||
|
||||
expect { subject }.not_to raise_error
|
||||
end
|
||||
|
||||
it 'ignores Postgres errors' do
|
||||
allow(reflect).to receive(:postgresql_minimum_supported_version?).and_raise(PG::Error)
|
||||
|
||||
expect { subject }.not_to raise_error
|
||||
end
|
||||
end
|
||||
|
||||
describe '.check_single_connection_and_print_warning' do
|
||||
subject { described_class.check_single_connection_and_print_warning }
|
||||
|
||||
it 'prints a warning if single connection' do
|
||||
allow(described_class).to receive(:database_mode).and_return(::Gitlab::Database::MODE_SINGLE_DATABASE)
|
||||
|
||||
expect(Kernel).to receive(:warn).with(/Your database has a single connection/)
|
||||
|
||||
subject
|
||||
end
|
||||
|
||||
it 'does not print a warning if single ci connection' do
|
||||
allow(described_class).to receive(:database_mode).and_return(::Gitlab::Database::MODE_SINGLE_DATABASE_CI_CONNECTION)
|
||||
|
||||
expect(Kernel).not_to receive(:warn)
|
||||
|
||||
subject
|
||||
end
|
||||
|
||||
it 'does not print a warning if multiple connection' do
|
||||
allow(described_class).to receive(:database_mode).and_return(::Gitlab::Database::MODE_MULTIPLE_DATABASES)
|
||||
|
||||
expect(Kernel).not_to receive(:warn)
|
||||
|
||||
subject
|
||||
end
|
||||
|
||||
it 'does not print a warning in Rails runner environment' do
|
||||
allow(described_class).to receive(:database_mode).and_return(::Gitlab::Database::MODE_SINGLE_DATABASE)
|
||||
allow(Gitlab::Runtime).to receive(:rails_runner?).and_return(true)
|
||||
|
||||
expect(Kernel).not_to receive(:warn)
|
||||
|
||||
subject
|
||||
end
|
||||
end
|
||||
|
||||
describe '.db_config_for_connection' do
|
||||
context 'when the regular connection is used' do
|
||||
it 'returns db_config' do
|
||||
|
|
|
|||
|
|
@ -0,0 +1,96 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Gitlab::DatabaseWarnings, feature_category: :database do
|
||||
describe '.check_postgres_version_and_print_warning' do
|
||||
let(:reflect) { instance_spy(Gitlab::Database::Reflection) }
|
||||
|
||||
subject { described_class.check_postgres_version_and_print_warning }
|
||||
|
||||
before do
|
||||
allow(Gitlab::Database::Reflection)
|
||||
.to receive(:new)
|
||||
.and_return(reflect)
|
||||
end
|
||||
|
||||
it 'prints a warning if not compliant with minimum postgres version' do
|
||||
allow(reflect).to receive(:postgresql_minimum_supported_version?).and_return(false)
|
||||
|
||||
expect(Kernel)
|
||||
.to receive(:warn)
|
||||
.with(/You are using PostgreSQL/)
|
||||
.exactly(Gitlab::Database.database_base_models.length)
|
||||
.times
|
||||
|
||||
subject
|
||||
end
|
||||
|
||||
it 'does not print a warning if compliant with minimum postgres version' do
|
||||
allow(reflect).to receive(:postgresql_minimum_supported_version?).and_return(true)
|
||||
|
||||
expect(Kernel).not_to receive(:warn).with(/You are using PostgreSQL/)
|
||||
|
||||
subject
|
||||
end
|
||||
|
||||
it 'does not print a warning in Rails runner environment' do
|
||||
allow(reflect).to receive(:postgresql_minimum_supported_version?).and_return(false)
|
||||
allow(Gitlab::Runtime).to receive(:rails_runner?).and_return(true)
|
||||
|
||||
expect(Kernel).not_to receive(:warn).with(/You are using PostgreSQL/)
|
||||
|
||||
subject
|
||||
end
|
||||
|
||||
it 'ignores ActiveRecord errors' do
|
||||
allow(reflect).to receive(:postgresql_minimum_supported_version?).and_raise(ActiveRecord::ActiveRecordError)
|
||||
|
||||
expect { subject }.not_to raise_error
|
||||
end
|
||||
|
||||
it 'ignores Postgres errors' do
|
||||
allow(reflect).to receive(:postgresql_minimum_supported_version?).and_raise(PG::Error)
|
||||
|
||||
expect { subject }.not_to raise_error
|
||||
end
|
||||
end
|
||||
|
||||
describe '.check_single_connection_and_print_warning' do
|
||||
subject { described_class.check_single_connection_and_print_warning }
|
||||
|
||||
it 'prints a warning if single connection' do
|
||||
allow(Gitlab::Database).to receive(:database_mode).and_return(Gitlab::Database::MODE_SINGLE_DATABASE)
|
||||
|
||||
expect(Kernel).to receive(:warn).with(/Your database has a single connection/)
|
||||
|
||||
subject
|
||||
end
|
||||
|
||||
it 'does not print a warning if single ci connection' do
|
||||
allow(Gitlab::Database).to receive(:database_mode)
|
||||
.and_return(Gitlab::Database::MODE_SINGLE_DATABASE_CI_CONNECTION)
|
||||
|
||||
expect(Kernel).not_to receive(:warn)
|
||||
|
||||
subject
|
||||
end
|
||||
|
||||
it 'does not print a warning if multiple connection' do
|
||||
allow(Gitlab::Database).to receive(:database_mode).and_return(Gitlab::Database::MODE_MULTIPLE_DATABASES)
|
||||
|
||||
expect(Kernel).not_to receive(:warn)
|
||||
|
||||
subject
|
||||
end
|
||||
|
||||
it 'does not print a warning in Rails runner environment' do
|
||||
allow(Gitlab::Database).to receive(:database_mode).and_return(Gitlab::Database::MODE_SINGLE_DATABASE)
|
||||
allow(Gitlab::Runtime).to receive(:rails_runner?).and_return(true)
|
||||
|
||||
expect(Kernel).not_to receive(:warn)
|
||||
|
||||
subject
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -34,23 +34,53 @@ RSpec.describe Gitlab::Patch::RedisCacheStore, :use_clean_rails_redis_caching, f
|
|||
end
|
||||
|
||||
context 'when reading large amount of keys' do
|
||||
it 'batches get into pipelines of 100' do
|
||||
cache.redis.with do |redis|
|
||||
normal_cluster = !redis.is_a?(Gitlab::Redis::MultiStore) && Gitlab::Redis::ClusterUtil.cluster?(redis)
|
||||
multistore_cluster = redis.is_a?(Gitlab::Redis::MultiStore) &&
|
||||
::Gitlab::Redis::ClusterUtil.cluster?(redis.default_store)
|
||||
let(:input_size) { 2000 }
|
||||
let(:chunk_size) { 1000 }
|
||||
|
||||
if normal_cluster || multistore_cluster
|
||||
expect(redis).to receive(:pipelined).at_least(2).and_call_original
|
||||
else
|
||||
expect(redis).to receive(:mget).and_call_original
|
||||
shared_examples 'read large amount of keys' do
|
||||
it 'breaks the input into 2 chunks for redis cluster' do
|
||||
cache.redis.with do |redis|
|
||||
normal_cluster = !redis.is_a?(Gitlab::Redis::MultiStore) && Gitlab::Redis::ClusterUtil.cluster?(redis)
|
||||
multistore_cluster = redis.is_a?(Gitlab::Redis::MultiStore) &&
|
||||
::Gitlab::Redis::ClusterUtil.cluster?(redis.default_store)
|
||||
|
||||
if normal_cluster || multistore_cluster
|
||||
expect_next_instances_of(Gitlab::Redis::CrossSlot::Pipeline, 2) do |pipeline|
|
||||
obj = instance_double(::Redis)
|
||||
expect(pipeline).to receive(:pipelined).and_yield(obj)
|
||||
expect(obj).to receive(:get).exactly(chunk_size).times
|
||||
end
|
||||
else
|
||||
expect(redis).to receive(:mget).and_call_original
|
||||
end
|
||||
end
|
||||
|
||||
Gitlab::Instrumentation::RedisClusterValidator.allow_cross_slot_commands do
|
||||
cache.read_multi(*Array.new(input_size) { |i| i })
|
||||
end
|
||||
end
|
||||
|
||||
Gitlab::Instrumentation::RedisClusterValidator.allow_cross_slot_commands do
|
||||
cache.read_multi(*Array.new(101) { |i| i })
|
||||
end
|
||||
end
|
||||
|
||||
context 'when GITLAB_REDIS_CLUSTER_PIPELINE_BATCH_LIMIT is smaller than the default' do
|
||||
before do
|
||||
stub_env('GITLAB_REDIS_CLUSTER_PIPELINE_BATCH_LIMIT', 10)
|
||||
end
|
||||
|
||||
it_behaves_like 'read large amount of keys'
|
||||
end
|
||||
|
||||
context 'when GITLAB_REDIS_CLUSTER_PIPELINE_BATCH_LIMIT is larger than the default' do
|
||||
let(:input_size) { 4000 }
|
||||
let(:chunk_size) { 2000 }
|
||||
|
||||
before do
|
||||
stub_env('GITLAB_REDIS_CLUSTER_PIPELINE_BATCH_LIMIT', chunk_size)
|
||||
end
|
||||
|
||||
it_behaves_like 'read large amount of keys'
|
||||
end
|
||||
|
||||
it_behaves_like 'read large amount of keys'
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -89,7 +119,7 @@ RSpec.describe Gitlab::Patch::RedisCacheStore, :use_clean_rails_redis_caching, f
|
|||
|
||||
context 'when deleting large amount of keys' do
|
||||
before do
|
||||
200.times { |i| cache.write(i, i) }
|
||||
2000.times { |i| cache.write(i, i) }
|
||||
end
|
||||
|
||||
it 'calls pipeline multiple times' do
|
||||
|
|
@ -105,9 +135,9 @@ RSpec.describe Gitlab::Patch::RedisCacheStore, :use_clean_rails_redis_caching, f
|
|||
|
||||
expect(
|
||||
Gitlab::Instrumentation::RedisClusterValidator.allow_cross_slot_commands do
|
||||
cache.delete_multi(Array(0..199))
|
||||
cache.delete_multi(Array(0..1999))
|
||||
end
|
||||
).to eq(200)
|
||||
).to eq(2000)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -650,25 +650,13 @@ RSpec.describe ActiveSession, :clean_gitlab_redis_sessions do
|
|||
end
|
||||
end
|
||||
|
||||
describe '.set_active_user_cookie' do
|
||||
describe '.set_active_user_cookie', :freeze_time do
|
||||
let(:auth) { double(cookies: {}) }
|
||||
|
||||
it 'sets marketing cookie' do
|
||||
described_class.set_active_user_cookie(auth)
|
||||
expect(auth.cookies[:about_gitlab_active_user][:value]).to be_truthy
|
||||
end
|
||||
end
|
||||
|
||||
describe '.unset_active_user_cookie' do
|
||||
let(:auth) { double(cookies: {}) }
|
||||
|
||||
before do
|
||||
described_class.set_active_user_cookie(auth)
|
||||
end
|
||||
|
||||
it 'unsets marketing cookie' do
|
||||
described_class.unset_active_user_cookie(auth)
|
||||
expect(auth.cookies[:about_gitlab_active_user]).to be_nil
|
||||
expect(auth.cookies[:gitlab_user][:value]).to be_truthy
|
||||
expect(auth.cookies[:gitlab_user][:expires]).to be_within(1.minute).of(2.weeks.from_now)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -13,15 +13,17 @@ RSpec.describe PoolRepository, feature_category: :source_code_management do
|
|||
let!(:pool_repository) { create(:pool_repository) }
|
||||
|
||||
it { is_expected.to validate_presence_of(:shard) }
|
||||
it { is_expected.to validate_presence_of(:source_project) }
|
||||
end
|
||||
|
||||
describe 'scopes' do
|
||||
let_it_be(:project1) { create(:project) }
|
||||
let_it_be(:project2) { create(:project) }
|
||||
let_it_be(:new_shard) { create(:shard, name: 'new') }
|
||||
let_it_be(:pool_repository1) { create(:pool_repository, source_project: project1) }
|
||||
let_it_be(:pool_repository2) { create(:pool_repository, source_project: project1, shard: new_shard) }
|
||||
let_it_be(:pool_repository1) { create(:pool_repository, source_project: project1, disk_path: 'disk_path') }
|
||||
let_it_be(:pool_repository2) do
|
||||
create(:pool_repository, source_project: project1, disk_path: 'disk_path', shard: new_shard)
|
||||
end
|
||||
|
||||
let_it_be(:another_pool_repository) { create(:pool_repository, source_project: project2) }
|
||||
|
||||
describe '.by_source_project' do
|
||||
|
|
@ -32,8 +34,8 @@ RSpec.describe PoolRepository, feature_category: :source_code_management do
|
|||
end
|
||||
end
|
||||
|
||||
describe '.by_source_project_and_shard_name' do
|
||||
subject { described_class.by_source_project_and_shard_name(project1, new_shard.name) }
|
||||
describe '.by_disk_path_and_shard_name' do
|
||||
subject { described_class.by_disk_path_and_shard_name('disk_path', new_shard.name) }
|
||||
|
||||
it 'returns only a requested pool repository' do
|
||||
is_expected.to match_array([pool_repository2])
|
||||
|
|
@ -91,4 +93,38 @@ RSpec.describe PoolRepository, feature_category: :source_code_management do
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#object_pool' do
|
||||
subject { pool.object_pool }
|
||||
|
||||
let(:pool) { build(:pool_repository, :ready, source_project: project, disk_path: disk_path) }
|
||||
let(:project) { build(:project) }
|
||||
let(:disk_path) { 'disk_path' }
|
||||
|
||||
it 'returns an object pool instance' do
|
||||
is_expected.to be_a_kind_of(Gitlab::Git::ObjectPool)
|
||||
|
||||
is_expected.to have_attributes(
|
||||
storage: pool.shard.name,
|
||||
relative_path: "#{pool.disk_path}.git",
|
||||
source_repository: pool.source_project.repository.raw,
|
||||
gl_project_path: pool.source_project.full_path
|
||||
)
|
||||
end
|
||||
|
||||
context 'when source project is missing' do
|
||||
let(:project) { nil }
|
||||
|
||||
it 'returns an object pool instance' do
|
||||
is_expected.to be_a_kind_of(Gitlab::Git::ObjectPool)
|
||||
|
||||
is_expected.to have_attributes(
|
||||
storage: pool.shard.name,
|
||||
relative_path: "#{pool.disk_path}.git",
|
||||
source_repository: nil,
|
||||
gl_project_path: nil
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -7018,8 +7018,11 @@ RSpec.describe Project, factory_default: :keep, feature_category: :groups_and_pr
|
|||
let_it_be_with_reload(:project) { create(:project, :empty_repo) }
|
||||
let_it_be(:shard_to) { create(:shard, name: 'test_second_storage') }
|
||||
|
||||
let!(:pool1) { create(:pool_repository, source_project: project) }
|
||||
let!(:pool2) { create(:pool_repository, shard: shard_to, source_project: project) }
|
||||
let(:disk_path1) { '@pool/aa/bb' }
|
||||
let(:disk_path2) { disk_path1 }
|
||||
|
||||
let!(:pool1) { create(:pool_repository, disk_path: disk_path1, source_project: project) }
|
||||
let!(:pool2) { create(:pool_repository, disk_path: disk_path2, shard: shard_to, source_project: project) }
|
||||
let(:project_pool) { pool1 }
|
||||
let(:repository_storage) { shard_to.name }
|
||||
|
||||
|
|
@ -7077,6 +7080,14 @@ RSpec.describe Project, factory_default: :keep, feature_category: :groups_and_pr
|
|||
expect { swap_pool_repository! }.to raise_error(ActiveRecord::RecordNotFound)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when pool repository has a different disk path' do
|
||||
let(:disk_path2) { '@pool/different' }
|
||||
|
||||
it 'raises record not found error' do
|
||||
expect { swap_pool_repository! }.to raise_error(ActiveRecord::RecordNotFound)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#leave_pool_repository' do
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ require 'spec_helper'
|
|||
RSpec.describe 'Sessions', feature_category: :system_access do
|
||||
include SessionHelpers
|
||||
|
||||
let_it_be(:user) { create(:user) }
|
||||
let(:user) { create(:user) }
|
||||
|
||||
context 'for authentication', :allow_forgery_protection do
|
||||
it 'logout does not require a csrf token' do
|
||||
|
|
@ -17,20 +17,20 @@ RSpec.describe 'Sessions', feature_category: :system_access do
|
|||
end
|
||||
end
|
||||
|
||||
describe 'about_gitlab_active_user', :saas do
|
||||
describe 'gitlab_user cookie', :saas do
|
||||
let_it_be(:user) { create(:user) }
|
||||
|
||||
context 'when user signs in' do
|
||||
it 'sets marketing cookie' do
|
||||
post user_session_path(user: { login: user.username, password: user.password })
|
||||
|
||||
expect(response.cookies['about_gitlab_active_user']).to be_present
|
||||
expect(response.cookies['gitlab_user']).to be_present
|
||||
end
|
||||
end
|
||||
|
||||
context 'when user uses remember_me' do
|
||||
it 'sets marketing cookie' do
|
||||
post user_session_path(user: { login: user.username, password: user.password, remember_me: true })
|
||||
|
||||
expect(response.cookies['about_gitlab_active_user']).to be_present
|
||||
expect(response.cookies['gitlab_user']).to be_present
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -74,18 +74,6 @@ RSpec.describe 'Sessions', feature_category: :system_access do
|
|||
end
|
||||
end
|
||||
|
||||
context 'when user signs out' do
|
||||
before do
|
||||
post user_session_path(user: { login: user.username, password: user.password })
|
||||
end
|
||||
|
||||
it 'deletes marketing cookie' do
|
||||
post(destroy_user_session_path)
|
||||
|
||||
expect(response.cookies['about_gitlab_active_user']).to be_nil
|
||||
end
|
||||
end
|
||||
|
||||
context 'when user is not using GitLab SaaS' do
|
||||
before do
|
||||
allow(::Gitlab).to receive(:com?).and_return(false)
|
||||
|
|
@ -93,8 +81,7 @@ RSpec.describe 'Sessions', feature_category: :system_access do
|
|||
|
||||
it 'does not set marketing cookie' do
|
||||
post user_session_path(user: { login: user.username, password: user.password })
|
||||
|
||||
expect(response.cookies['about_gitlab_active_user']).to be_nil
|
||||
expect(response.cookies['gitlab_user']).to be_nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -229,6 +229,27 @@ RSpec.describe Projects::UpdateRepositoryStorageService, feature_category: :sour
|
|||
end
|
||||
end
|
||||
|
||||
context 'when new shard has a repository pool without the root project' do
|
||||
let!(:new_pool_repository) { create(:pool_repository, :ready, shard: shard_to, disk_path: pool_repository.disk_path) }
|
||||
|
||||
before do
|
||||
pool_repository.update!(source_project: nil)
|
||||
new_pool_repository.update!(source_project: nil)
|
||||
end
|
||||
|
||||
it 'connects project to it' do
|
||||
result = subject.execute
|
||||
expect(result).to be_success
|
||||
|
||||
project.reload.cleanup
|
||||
|
||||
project_pool_repository = project.pool_repository
|
||||
|
||||
expect(project_pool_repository).to eq(new_pool_repository)
|
||||
expect(object_pool_double).to have_received(:link).with(project.repository.raw)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when repository does not exist' do
|
||||
let(:project) { create(:project) }
|
||||
let(:checksum) { nil }
|
||||
|
|
@ -266,6 +287,32 @@ RSpec.describe Projects::UpdateRepositoryStorageService, feature_category: :sour
|
|||
end
|
||||
end
|
||||
|
||||
context 'when project belongs to the repository pool without a root project' do
|
||||
let!(:pool_repository) { create(:pool_repository, :ready, shard: shard_from) }
|
||||
|
||||
before do
|
||||
pool_repository.update!(source_project: nil)
|
||||
project.update!(pool_repository: pool_repository)
|
||||
end
|
||||
|
||||
it 'creates a new repository pool without a root project and connects project to it' do
|
||||
result = subject.execute
|
||||
expect(result).to be_success
|
||||
|
||||
project.reload.cleanup
|
||||
|
||||
new_pool_repository = project.pool_repository
|
||||
|
||||
expect(new_pool_repository).not_to eq(pool_repository)
|
||||
expect(new_pool_repository.shard).to eq(shard_second_storage)
|
||||
expect(new_pool_repository.state).to eq('ready')
|
||||
expect(new_pool_repository.source_project).to eq(nil)
|
||||
expect(new_pool_repository.disk_path).to eq(pool_repository.disk_path)
|
||||
|
||||
expect(object_pool_double).to have_received(:link).with(project.repository.raw)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when object pool checksum does not match' do
|
||||
let(:new_object_pool_checksum) { 'not_match' }
|
||||
|
||||
|
|
|
|||
|
|
@ -12,5 +12,13 @@ RSpec.describe Users::AuthorizedBuildService, feature_category: :user_management
|
|||
|
||||
it_behaves_like 'common user build items'
|
||||
it_behaves_like 'current user not admin build items'
|
||||
|
||||
context 'for additional authorized build allowed params' do
|
||||
before do
|
||||
params.merge!(external: true)
|
||||
end
|
||||
|
||||
it { expect(user).to be_external }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -16,6 +16,57 @@ RSpec.describe Users::BuildService, feature_category: :user_management do
|
|||
|
||||
it_behaves_like 'common user build items'
|
||||
it_behaves_like 'current user not admin build items'
|
||||
|
||||
context 'with "user_default_external" application setting' do
|
||||
using RSpec::Parameterized::TableSyntax
|
||||
|
||||
where(:user_default_external, :external, :email, :user_default_internal_regex, :result) do
|
||||
true | nil | 'fl@example.com' | nil | true
|
||||
true | true | 'fl@example.com' | nil | true
|
||||
true | false | 'fl@example.com' | nil | true # admin difference
|
||||
|
||||
true | nil | 'fl@example.com' | '' | true
|
||||
true | true | 'fl@example.com' | '' | true
|
||||
true | false | 'fl@example.com' | '' | true # admin difference
|
||||
|
||||
true | nil | 'fl@example.com' | '^(?:(?!\.ext@).)*$\r?' | false
|
||||
true | true | 'fl@example.com' | '^(?:(?!\.ext@).)*$\r?' | false # admin difference
|
||||
true | false | 'fl@example.com' | '^(?:(?!\.ext@).)*$\r?' | false
|
||||
|
||||
true | nil | 'tester.ext@domain.com' | '^(?:(?!\.ext@).)*$\r?' | true
|
||||
true | true | 'tester.ext@domain.com' | '^(?:(?!\.ext@).)*$\r?' | true
|
||||
true | false | 'tester.ext@domain.com' | '^(?:(?!\.ext@).)*$\r?' | true # admin difference
|
||||
|
||||
false | nil | 'fl@example.com' | nil | false
|
||||
false | true | 'fl@example.com' | nil | false # admin difference
|
||||
false | false | 'fl@example.com' | nil | false
|
||||
|
||||
false | nil | 'fl@example.com' | '' | false
|
||||
false | true | 'fl@example.com' | '' | false # admin difference
|
||||
false | false | 'fl@example.com' | '' | false
|
||||
|
||||
false | nil | 'fl@example.com' | '^(?:(?!\.ext@).)*$\r?' | false
|
||||
false | true | 'fl@example.com' | '^(?:(?!\.ext@).)*$\r?' | false # admin difference
|
||||
false | false | 'fl@example.com' | '^(?:(?!\.ext@).)*$\r?' | false
|
||||
|
||||
false | nil | 'tester.ext@domain.com' | '^(?:(?!\.ext@).)*$\r?' | false
|
||||
false | true | 'tester.ext@domain.com' | '^(?:(?!\.ext@).)*$\r?' | false # admin difference
|
||||
false | false | 'tester.ext@domain.com' | '^(?:(?!\.ext@).)*$\r?' | false
|
||||
end
|
||||
|
||||
with_them do
|
||||
before do
|
||||
stub_application_setting(user_default_external: user_default_external)
|
||||
stub_application_setting(user_default_internal_regex: user_default_internal_regex)
|
||||
|
||||
params.merge!({ external: external, email: email }.compact)
|
||||
end
|
||||
|
||||
it 'sets the value of Gitlab::CurrentSettings.user_default_external' do
|
||||
expect(user.external).to eq(result)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'with non admin current_user' do
|
||||
|
|
|
|||
|
|
@ -33,57 +33,6 @@ RSpec.shared_examples 'common user build items' do
|
|||
end
|
||||
|
||||
RSpec.shared_examples_for 'current user not admin build items' do
|
||||
using RSpec::Parameterized::TableSyntax
|
||||
|
||||
context 'with "user_default_external" application setting' do
|
||||
where(:user_default_external, :external, :email, :user_default_internal_regex, :result) do
|
||||
true | nil | 'fl@example.com' | nil | true
|
||||
true | true | 'fl@example.com' | nil | true
|
||||
true | false | 'fl@example.com' | nil | true # admin difference
|
||||
|
||||
true | nil | 'fl@example.com' | '' | true
|
||||
true | true | 'fl@example.com' | '' | true
|
||||
true | false | 'fl@example.com' | '' | true # admin difference
|
||||
|
||||
true | nil | 'fl@example.com' | '^(?:(?!\.ext@).)*$\r?' | false
|
||||
true | true | 'fl@example.com' | '^(?:(?!\.ext@).)*$\r?' | false # admin difference
|
||||
true | false | 'fl@example.com' | '^(?:(?!\.ext@).)*$\r?' | false
|
||||
|
||||
true | nil | 'tester.ext@domain.com' | '^(?:(?!\.ext@).)*$\r?' | true
|
||||
true | true | 'tester.ext@domain.com' | '^(?:(?!\.ext@).)*$\r?' | true
|
||||
true | false | 'tester.ext@domain.com' | '^(?:(?!\.ext@).)*$\r?' | true # admin difference
|
||||
|
||||
false | nil | 'fl@example.com' | nil | false
|
||||
false | true | 'fl@example.com' | nil | false # admin difference
|
||||
false | false | 'fl@example.com' | nil | false
|
||||
|
||||
false | nil | 'fl@example.com' | '' | false
|
||||
false | true | 'fl@example.com' | '' | false # admin difference
|
||||
false | false | 'fl@example.com' | '' | false
|
||||
|
||||
false | nil | 'fl@example.com' | '^(?:(?!\.ext@).)*$\r?' | false
|
||||
false | true | 'fl@example.com' | '^(?:(?!\.ext@).)*$\r?' | false # admin difference
|
||||
false | false | 'fl@example.com' | '^(?:(?!\.ext@).)*$\r?' | false
|
||||
|
||||
false | nil | 'tester.ext@domain.com' | '^(?:(?!\.ext@).)*$\r?' | false
|
||||
false | true | 'tester.ext@domain.com' | '^(?:(?!\.ext@).)*$\r?' | false # admin difference
|
||||
false | false | 'tester.ext@domain.com' | '^(?:(?!\.ext@).)*$\r?' | false
|
||||
end
|
||||
|
||||
with_them do
|
||||
before do
|
||||
stub_application_setting(user_default_external: user_default_external)
|
||||
stub_application_setting(user_default_internal_regex: user_default_internal_regex)
|
||||
|
||||
params.merge!({ external: external, email: email }.compact)
|
||||
end
|
||||
|
||||
it 'sets the value of Gitlab::CurrentSettings.user_default_external' do
|
||||
expect(user.external).to eq(result)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when "email_confirmation_setting" application setting is set to `hard`' do
|
||||
before do
|
||||
stub_application_setting_enum('email_confirmation_setting', 'hard')
|
||||
|
|
|
|||
Loading…
Reference in New Issue