Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2022-07-13 09:08:30 +00:00
parent 33a43bde0e
commit 152d3b652d
45 changed files with 920 additions and 509 deletions

View File

@ -46,6 +46,7 @@ class Issue < ApplicationRecord
TYPES_FOR_LIST = %w(issue incident).freeze TYPES_FOR_LIST = %w(issue incident).freeze
belongs_to :project belongs_to :project
belongs_to :namespace, inverse_of: :issues
belongs_to :duplicated_to, class_name: 'Issue' belongs_to :duplicated_to, class_name: 'Issue'
belongs_to :closed_by, class_name: 'User' belongs_to :closed_by, class_name: 'User'
@ -97,6 +98,7 @@ class Issue < ApplicationRecord
validates :project, presence: true validates :project, presence: true
validates :issue_type, presence: true validates :issue_type, presence: true
validates :namespace, presence: true, if: -> { project.present? }
enum issue_type: WorkItems::Type.base_types enum issue_type: WorkItems::Type.base_types
@ -183,6 +185,8 @@ class Issue < ApplicationRecord
scope :with_null_relative_position, -> { where(relative_position: nil) } scope :with_null_relative_position, -> { where(relative_position: nil) }
scope :with_non_null_relative_position, -> { where.not(relative_position: nil) } scope :with_non_null_relative_position, -> { where.not(relative_position: nil) }
before_validation :ensure_namespace_id
after_commit :expire_etag_cache, unless: :importing? after_commit :expire_etag_cache, unless: :importing?
after_save :ensure_metrics, unless: :importing? after_save :ensure_metrics, unless: :importing?
after_create_commit :record_create_action, unless: :importing? after_create_commit :record_create_action, unless: :importing?
@ -655,6 +659,10 @@ class Issue < ApplicationRecord
# Symptom of running out of space - schedule rebalancing # Symptom of running out of space - schedule rebalancing
Issues::RebalancingWorker.perform_async(nil, *project.self_or_root_group_ids) Issues::RebalancingWorker.perform_async(nil, *project.self_or_root_group_ids)
end end
def ensure_namespace_id
self.namespace = project.project_namespace if project
end
end end
Issue.prepend_mod_with('Issue') Issue.prepend_mod_with('Issue')

View File

@ -74,7 +74,8 @@ class Namespace < ApplicationRecord
has_many :sync_events, class_name: 'Namespaces::SyncEvent' has_many :sync_events, class_name: 'Namespaces::SyncEvent'
has_one :cluster_enabled_grant, inverse_of: :namespace, class_name: 'Clusters::ClusterEnabledGrant' has_one :cluster_enabled_grant, inverse_of: :namespace, class_name: 'Clusters::ClusterEnabledGrant'
has_many :work_items, inverse_of: :namespace, class_name: 'WorkItem' has_many :work_items, inverse_of: :namespace
has_many :issues, inverse_of: :namespace
validates :owner, presence: true, if: ->(n) { n.owner_required? } validates :owner, presence: true, if: ->(n) { n.owner_required? }
validates :name, validates :name,

View File

@ -6,7 +6,7 @@ class WorkItem < Issue
self.table_name = 'issues' self.table_name = 'issues'
self.inheritance_column = :_type_disabled self.inheritance_column = :_type_disabled
belongs_to :namespace, class_name: 'Namespace', foreign_key: :namespace_id, inverse_of: :work_items belongs_to :namespace, inverse_of: :work_items
has_one :parent_link, class_name: '::WorkItems::ParentLink', foreign_key: :work_item_id has_one :parent_link, class_name: '::WorkItems::ParentLink', foreign_key: :work_item_id
has_one :work_item_parent, through: :parent_link, class_name: 'WorkItem' has_one :work_item_parent, through: :parent_link, class_name: 'WorkItem'

View File

@ -2731,15 +2731,6 @@
:weight: 1 :weight: 1
:idempotent: true :idempotent: true
:tags: [] :tags: []
- :name: pages_transfer
:worker_name: PagesTransferWorker
:feature_category: :pages
:has_external_dependencies: false
:urgency: :low
:resource_boundary: :unknown
:weight: 1
:idempotent: false
:tags: []
- :name: phabricator_import_import_tasks - :name: phabricator_import_import_tasks
:worker_name: Gitlab::PhabricatorImport::ImportTasksWorker :worker_name: Gitlab::PhabricatorImport::ImportTasksWorker
:feature_category: :importers :feature_category: :importers

View File

@ -1,20 +0,0 @@
# frozen_string_literal: true
class PagesTransferWorker # rubocop:disable Scalability/IdempotentWorker
include ApplicationWorker
data_consistency :always
sidekiq_options retry: 3
TransferFailedError = Class.new(StandardError)
feature_category :pages
loggable_arguments 0, 1
def perform(method, args)
# noop
# This worker is not necessary anymore and will be removed
# https://gitlab.com/gitlab-org/gitlab/-/issues/340616
end
end

View File

@ -331,8 +331,6 @@
- 1 - 1
- - pages_invalidate_domain_cache - - pages_invalidate_domain_cache
- 1 - 1
- - pages_transfer
- 1
- - personal_access_tokens - - personal_access_tokens
- 1 - 1
- - phabricator_import_import_tasks - - phabricator_import_import_tasks

View File

@ -0,0 +1,41 @@
# This is a template for a feature deprecation.
#
# Please refer to the deprecation guidelines to confirm your understanding of GitLab's definitions.
# https://docs.gitlab.com/ee/development/deprecation_guidelines/#terminology
#
# Deprecations must be announced at least three releases prior to removal.
#
# If an End of Support period applies, the announcement should be shared with GitLab Support
# in the `#spt_managers` on Slack and mention `@gitlab-com/support` in this MR.
#
# Breaking changes must happen in a major release.
#
# For more information please refer to the handbook documentation here:
# https://about.gitlab.com/handbook/marketing/blog/release-posts/#deprecations
#
# Please delete this line and above before submitting your merge request.
#
# REQUIRED FIELDS
#
- name: "Remove `job_age` parameter from `POST /jobs/request` Runner endpoint" # (required) The name of the feature to be deprecated
announcement_milestone: "15.2" # (required) The milestone when this feature was first announced as deprecated.
announcement_date: "2022-07-22" # (required) The date of the milestone release when this feature was first announced as deprecated. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post.
removal_milestone: "16.0" # (required) The milestone when this feature is planned to be removed
removal_date: "2023-05-22" # (required) The date of the milestone release when this feature is planned to be removed. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post.
breaking_change: true # (required) If this deprecation is a breaking change, set this value to true
reporter: jheimbuck_gl # (required) GitLab username of the person reporting the deprecation
stage: Verify # (required) String value of the stage that the feature was created in. e.g., Growth
issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/334253 # (required) Link to the deprecation issue in GitLab
body: | # (required) Do not modify this line, instead modify the lines below.
The `job_age` parameter, returned from the `POST /jobs/request` API endpoint used in communication with GitLab Runner, was never used by any GitLab or Runner feature. This parameter will be removed in GitLab 16.0.
This could be a breaking change for anyone that developed their own runner that relies on this parameter being returned by the endpoint. This is not a breaking change for anyone using an officially released version of GitLab Runner, including public shared runners on GitLab.com.
#
# OPTIONAL FIELDS
#
end_of_support_milestone: # (optional) Use "XX.YY" format. The milestone when support for this feature will end.
end_of_support_date: # (optional) The date of the milestone release when support for this feature will end.
tiers: # (optional - may be required in the future) An array of tiers that the feature is available in currently. e.g., [Free, Silver, Gold, Core, Premium, Ultimate]
documentation_url: # (optional) This is a link to the current documentation page
image_url: # (optional) This is a link to a thumbnail image depicting the feature
video_url: # (optional) Use the youtube thumbnail URL with the structure of https://img.youtube.com/vi/UNIQUEID/hqdefault.jpg

View File

@ -0,0 +1,25 @@
# frozen_string_literal: true
class QueueUpdateDelayedProjectRemovalToNullForUserNamespace < Gitlab::Database::Migration[2.0]
MIGRATION = 'UpdateDelayedProjectRemovalToNullForUserNamespaces'
INTERVAL = 2.minutes
BATCH_SIZE = 10_000
disable_ddl_transaction!
restrict_gitlab_migration gitlab_schema: :gitlab_main
def up
queue_batched_background_migration(
MIGRATION,
:namespace_settings,
:namespace_id,
job_interval: INTERVAL,
batch_size: BATCH_SIZE
)
end
def down
delete_batched_background_migration(MIGRATION, :namespace_settings, :namespace_id, [])
end
end

View File

@ -0,0 +1 @@
24b07a6966c6fd7ab680cf5a9052b7c2f6d20944eaae5d06ef42934364dce222

View File

@ -131,7 +131,8 @@ Example response:
## Group Audit Events ## Group Audit Events
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/34078) in GitLab 12.5. > - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/34078) in GitLab 12.5.
> - [Support for keyset pagination added](https://gitlab.com/gitlab-org/gitlab/-/issues/333968) in GitLab 15.2.
The Group Audit Events API allows you to retrieve [group audit events](../administration/audit_events.md#group-events). The Group Audit Events API allows you to retrieve [group audit events](../administration/audit_events.md#group-events).
This API cannot retrieve project audit events. This API cannot retrieve project audit events.
@ -139,6 +140,10 @@ This API cannot retrieve project audit events.
A user with a Owner role (or above) can retrieve group audit events of all users. A user with a Owner role (or above) can retrieve group audit events of all users.
A user with a Developer or Maintainer role is limited to group audit events based on their individual actions. A user with a Developer or Maintainer role is limited to group audit events based on their individual actions.
This endpoint optionally supports [keyset pagination](index.md#keyset-based-pagination):
- When requesting consecutive pages of results, we recommend you use keyset pagination.
### Retrieve all group audit events ### Retrieve all group audit events
```plaintext ```plaintext

View File

@ -520,10 +520,11 @@ pagination headers.
Keyset-based pagination is supported only for selected resources and ordering Keyset-based pagination is supported only for selected resources and ordering
options: options:
| Resource | Options | Availability | | Resource | Options | Availability |
|:-------------------------|:---------------------------------|:----------------------------------------| |:---------------------------------------------------------|:---------------------------------|:------------------------------------------------------------------------------------------------------------|
| [Projects](projects.md) | `order_by=id` only | Authenticated and unauthenticated users | | [Projects](projects.md) | `order_by=id` only | Authenticated and unauthenticated users |
| [Groups](groups.md) | `order_by=name`, `sort=asc` only | Unauthenticated users only | | [Groups](groups.md) | `order_by=name`, `sort=asc` only | Unauthenticated users only |
| [Group audit events](audit_events.md#group-audit-events) | `order_by=id`, `sort=desc` only | Authenticated users only ([introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/333968) in GitLab 15.2 |
### Pagination response headers ### Pagination response headers

View File

@ -25,26 +25,37 @@ mean FIPS 140-2.
## Current status ## Current status
GitLab Inc has not committed to making GitLab FIPS-compliant at this time. We are
performing initial investigations to see how much work such an effort would be.
Read [Epic &5104](https://gitlab.com/groups/gitlab-org/-/epics/5104) for more Read [Epic &5104](https://gitlab.com/groups/gitlab-org/-/epics/5104) for more
information on the status of the investigation. information on the status of the investigation.
GitLab is actively working towards FIPS compliance.
## FIPS compliance at GitLab ## FIPS compliance at GitLab
In a FIPS context, compliance is a form of self-certification - if we say we are
"FIPS compliant", we mean that we *believe* we are. There are no external
certifications to acquire, but if we are aware of non-compliant areas
in GitLab, we cannot self-certify in good faith.
The known areas of non-compliance are tracked in [Epic &5104](https://gitlab.com/groups/gitlab-org/-/epics/5104).
To be compliant, all components (GitLab itself, Gitaly, etc) must be compliant, To be compliant, all components (GitLab itself, Gitaly, etc) must be compliant,
along with the communication between those components, and any storage used by along with the communication between those components, and any storage used by
them. Where functionality cannot be brought into compliance, it must be disabled them. Where functionality cannot be brought into compliance, it must be disabled
when FIPS mode is enabled. when FIPS mode is enabled.
### Leveraged Cryptographic modules
| Cryptographic module name | CMVP number | Instance type | Software component used |
|----------------------------------------------------------|-------------------------------------------------------------------------------------------------|---------------|-------------------------|
| Ubuntu 20.04 AWS Kernel Crypto API Cryptographic Module | [4132](https://csrc.nist.gov/projects/cryptographic-module-validation-program/certificate/4132) | EC2 | Linux kernel |
| Ubuntu 20.04 OpenSSL Cryptographic Module | [3966](https://csrc.nist.gov/projects/cryptographic-module-validation-program/certificate/3966) | EC2 | Gitaly, Rails (Puma/Sidekiq) |
| Ubuntu 20.04 Libgcrypt Cryptographic Module | [3902](https://csrc.nist.gov/projects/cryptographic-module-validation-program/certificate/3902) | EC2 instances | `gpg`, `sshd` |
| Amazon Linux 2 Kernel Crypto API Cryptographic Module | [3709](https://csrc.nist.gov/projects/cryptographic-module-validation-program/certificate/3709) | EKS nodes | Linux kernel |
| Amazon Linux 2 OpenSSL Cryptographic Module | [3553](https://csrc.nist.gov/projects/cryptographic-module-validation-program/certificate/3553) | EKS nodes | NGINX |
| RedHat Enterprise Linux 8 OpenSSL Cryptographic Module | [3852](https://csrc.nist.gov/projects/cryptographic-module-validation-program/certificate/3852) | EKS nodes | UBI containers: Workhorse, Pages, Container Registry, Rails (Puma/Sidekiq), Security Analyzers |
| RedHat Enterprise Linux 8 Libgcrypt Cryptographic Module | [3784](https://csrc.nist.gov/projects/cryptographic-module-validation-program/certificate/3784) | EKS nodes | UBI containers: GitLab Shell, `gpg` |
### Supported Operating Systems
The supported hybrid environments are:
- Omnibus: Ubuntu 20.04 FIPS
- EKS: Amazon Linux 2
## FIPS validation at GitLab ## FIPS validation at GitLab
Unlike FIPS compliance, FIPS validation is a formal declaration of compliance by Unlike FIPS compliance, FIPS validation is a formal declaration of compliance by
@ -55,89 +66,24 @@ A list of FIPS-validated modules can be found at the
NIST (National Institute of Standards and Technology) NIST (National Institute of Standards and Technology)
[cryptographic module validation program](https://csrc.nist.gov/projects/cryptographic-module-validation-program/validated-modules). [cryptographic module validation program](https://csrc.nist.gov/projects/cryptographic-module-validation-program/validated-modules).
## Setting up a FIPS-enabled development environment ## Install GitLab with FIPS compliance
The simplest approach is to set up a virtual machine running This guide is specifically for public users or GitLab team members with a requirement
[Red Hat Enterprise Linux 8](https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/8/html/security_hardening/using-the-system-wide-cryptographic-policies_security-hardening#switching-the-system-to-fips-mode_using-the-system-wide-cryptographic-policies). to run a production instance of GitLab that is FIPS compliant. This guide outlines
a hybrid deployment using elements from both Omnibus and our Cloud Native GitLab installations.
Red Hat provide free licenses to developers, and permit the CD image to be ### Prerequisites
downloaded from the [Red Hat developer's portal](https://developers.redhat.com).
Registration is required.
After the virtual machine is set up, you can follow the [GDK](https://gitlab.com/gitlab-org/gitlab-development-kit) - Amazon Web Services account. Our first target environment is running on AWS, and uses other FIPS Compliant AWS resources.
installation instructions, including the [advanced instructions for RHEL](https://gitlab.com/gitlab-org/gitlab-development-kit/-/blob/main/doc/advanced.md#red-hat-enterprise-linux). - Ability to run Ubuntu 20.04 machines for GitLab. Our first target environment uses the hybrid architecture.
Note that `asdf` is not used for dependency management because it's essential to
use the RedHat-provided Go compiler and other system dependencies.
### Enable FIPS mode ### Set up a FIPS-enabled cluster
After GDK and its dependencies are installed, run this command (as
root) and restart the virtual machine:
```shell
fips-mode-setup --enable
```
You can check whether it's taken effect by running:
```shell
fips-mode-setup --check
```
In this environment, OpenSSL refuses to perform cryptographic operations
forbidden by the FIPS standards. This enables you to reproduce FIPS-related bugs,
and validate fixes.
You should be able to open a web browser inside the virtual machine and log in
to the GitLab instance.
You can disable FIPS mode again by running this command, then restarting the
virtual machine:
```shell
fips-mode-setup --disable
```
#### Detect FIPS enablement in code
You can query `Gitlab::FIPS` in Ruby code to determine if the instance is FIPS-enabled:
```ruby
def default_min_key_size(name)
if Gitlab::FIPS.enabled?
Gitlab::SSHPublicKey.supported_sizes(name).select(&:positive?).min || -1
else
0
end
end
```
#### Unsupported features in FIPS mode
Some GitLab features may not work when FIPS mode is enabled. The following features are known to not work in FIPS mode; however, there may be additional features not listed here that also do not work properly in FIPS mode:
- [License compliance](../user/compliance/license_compliance/index.md)
- [Dependency scanning](../user/application_security/dependency_scanning/index.md) support for Gradle
- [Solutions for vulnerabilities](../user/application_security/vulnerabilities/index.md#resolve-a-vulnerability) for yarn projects
## Nightly Omnibus FIPS builds
The Distribution team has created [nightly FIPS Omnibus builds](https://packages.gitlab.com/gitlab/nightly-fips-builds). These
GitLab builds are compiled to use the system OpenSSL instead of the Omnibus-embedded version of OpenSSL.
See [the section on how FIPS builds are created](#how-fips-builds-are-created).
## Runner
See the [documentation on installing a FIPS-compliant GitLab Runner](https://docs.gitlab.com/runner/install/#fips-compliant-gitlab-runner).
## Set up a FIPS-enabled cluster
You can use the [GitLab Environment Toolkit](https://gitlab.com/gitlab-org/gitlab-environment-toolkit) to spin You can use the [GitLab Environment Toolkit](https://gitlab.com/gitlab-org/gitlab-environment-toolkit) to spin
up a FIPS-enabled cluster for development and testing. These instructions use Amazon Web Services (AWS) up a FIPS-enabled cluster for development and testing. As mentioned in the prerequisites, these instructions use Amazon Web Services (AWS)
because that is the first target environment, but you can adapt them for other providers. because that is the first target environment.
### Set up your environment #### Set up your environment
To get started, your AWS account must subscribe to a FIPS-enabled Amazon To get started, your AWS account must subscribe to a FIPS-enabled Amazon
Machine Image (AMI) in the [AWS Marketplace console](https://aws.amazon.com/premiumsupport/knowledge-center/launch-ec2-marketplace-subscription/). Machine Image (AMI) in the [AWS Marketplace console](https://aws.amazon.com/premiumsupport/knowledge-center/launch-ec2-marketplace-subscription/).
@ -146,13 +92,13 @@ This example assumes that the `Ubuntu Pro 20.04 FIPS LTS` AMI by
`Canonical Group Limited` has been added your account. This operating `Canonical Group Limited` has been added your account. This operating
system is used for virtual machines running in Amazon EC2. system is used for virtual machines running in Amazon EC2.
### Omnibus #### Omnibus
The simplest way to get a FIPS-enabled GitLab cluster is to use an Omnibus reference architecture. The simplest way to get a FIPS-enabled GitLab cluster is to use an Omnibus reference architecture.
See the [GET Quick Start Guide](https://gitlab.com/gitlab-org/gitlab-environment-toolkit/-/blob/main/docs/environment_quick_start_guide.md) See the [GET Quick Start Guide](https://gitlab.com/gitlab-org/gitlab-environment-toolkit/-/blob/main/docs/environment_quick_start_guide.md)
for more details. The following instructions build on the Quick Start and are also necessary for [Cloud Native Hybrid](#cloud-native-hybrid) installations. for more details. The following instructions build on the Quick Start and are also necessary for [Cloud Native Hybrid](#cloud-native-hybrid) installations.
#### Terraform: Use a FIPS AMI ##### Terraform: Use a FIPS AMI
1. Follow the guide to set up Terraform and Ansible. 1. Follow the guide to set up Terraform and Ansible.
1. After [step 2b](https://gitlab.com/gitlab-org/gitlab-environment-toolkit/-/blob/main/docs/environment_quick_start_guide.md#2b-setup-config), 1. After [step 2b](https://gitlab.com/gitlab-org/gitlab-environment-toolkit/-/blob/main/docs/environment_quick_start_guide.md#2b-setup-config),
@ -197,7 +143,7 @@ an instance, this would result in data loss: not only would disks be
destroyed, but also GitLab secrets would be lost. There is a [Terraform lifecycle rule](https://gitlab.com/gitlab-org/gitlab-environment-toolkit/blob/2aaeaff8ac8067f23cd7b6bb5bf131061649089d/terraform/modules/gitlab_aws_instance/main.tf#L40) destroyed, but also GitLab secrets would be lost. There is a [Terraform lifecycle rule](https://gitlab.com/gitlab-org/gitlab-environment-toolkit/blob/2aaeaff8ac8067f23cd7b6bb5bf131061649089d/terraform/modules/gitlab_aws_instance/main.tf#L40)
to ignore AMI changes. to ignore AMI changes.
#### Ansible: Specify the FIPS Omnibus builds ##### Ansible: Specify the FIPS Omnibus builds
The standard Omnibus GitLab releases build their own OpenSSL library, which is The standard Omnibus GitLab releases build their own OpenSSL library, which is
not FIPS-validated. However, we have nightly builds that create Omnibus packages not FIPS-validated. However, we have nightly builds that create Omnibus packages
@ -211,11 +157,11 @@ in this way:
all: all:
vars: vars:
... ...
gitlab_repo_script_url: "https://packages.gitlab.com/install/repositories/gitlab/nightly-fips-builds/script.deb.sh" gitlab_repo_script_url: "https://packages.gitlab.com/install/repositories/gitlab/gitlab-fips/script.deb.sh"
gitlab_edition: "gitlab-fips" gitlab_edition: "gitlab-fips"
``` ```
### Cloud Native Hybrid #### Cloud Native Hybrid
A Cloud Native Hybrid install uses both Omnibus and Cloud Native GitLab A Cloud Native Hybrid install uses both Omnibus and Cloud Native GitLab
(CNG) images. The previous instructions cover the Omnibus part, but two (CNG) images. The previous instructions cover the Omnibus part, but two
@ -224,7 +170,7 @@ additional steps are needed to enable FIPS in CNG:
1. Use a custom Amazon Elastic Kubernetes Service (EKS) AMI. 1. Use a custom Amazon Elastic Kubernetes Service (EKS) AMI.
1. Use GitLab containers built with RedHat's Universal Base Image (UBI). 1. Use GitLab containers built with RedHat's Universal Base Image (UBI).
#### Build a custom EKS AMI ##### Build a custom EKS AMI
Because Amazon does not yet publish a FIPS-enabled AMI, you have to Because Amazon does not yet publish a FIPS-enabled AMI, you have to
build one yourself with Packer. build one yourself with Packer.
@ -267,7 +213,7 @@ be different.
Building a RHEL-based system with FIPS enabled should be possible, but Building a RHEL-based system with FIPS enabled should be possible, but
there is [an outstanding issue preventing the Packer build from completing](https://github.com/aws-samples/amazon-eks-custom-amis/issues/51). there is [an outstanding issue preventing the Packer build from completing](https://github.com/aws-samples/amazon-eks-custom-amis/issues/51).
#### Terraform: Use a custom EKS AMI ##### Terraform: Use a custom EKS AMI
Now you can set the custom EKS AMI. Now you can set the custom EKS AMI.
@ -294,7 +240,7 @@ Now you can set the custom EKS AMI.
} }
``` ```
#### Ansible: Use UBI images ##### Ansible: Use UBI images
CNG uses a Helm Chart to manage which container images to deploy. By default, GET CNG uses a Helm Chart to manage which container images to deploy. By default, GET
deploys the latest released versions that use Debian-based containers. deploys the latest released versions that use Debian-based containers.
@ -414,6 +360,97 @@ You can find more information on FIPS performance benchmarking in the following
- [Benchmark performance of FIPS reference architecture](https://gitlab.com/gitlab-org/gitlab/-/issues/364051#note_1010450415) - [Benchmark performance of FIPS reference architecture](https://gitlab.com/gitlab-org/gitlab/-/issues/364051#note_1010450415)
## Setting up a FIPS-enabled development environment
The simplest approach is to set up a virtual machine running
[Red Hat Enterprise Linux 8](https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/8/html/security_hardening/using-the-system-wide-cryptographic-policies_security-hardening#switching-the-system-to-fips-mode_using-the-system-wide-cryptographic-policies).
Red Hat provide free licenses to developers, and permit the CD image to be
downloaded from the [Red Hat developer's portal](https://developers.redhat.com).
Registration is required.
After the virtual machine is set up, you can follow the [GDK](https://gitlab.com/gitlab-org/gitlab-development-kit)
installation instructions, including the [advanced instructions for RHEL](https://gitlab.com/gitlab-org/gitlab-development-kit/-/blob/main/doc/advanced.md#red-hat-enterprise-linux).
Note that `asdf` is not used for dependency management because it's essential to
use the RedHat-provided Go compiler and other system dependencies.
### Enable FIPS mode
After GDK and its dependencies are installed, run this command (as
root) and restart the virtual machine:
```shell
fips-mode-setup --enable
```
You can check whether it's taken effect by running:
```shell
fips-mode-setup --check
```
In this environment, OpenSSL refuses to perform cryptographic operations
forbidden by the FIPS standards. This enables you to reproduce FIPS-related bugs,
and validate fixes.
You should be able to open a web browser inside the virtual machine and log in
to the GitLab instance.
You can disable FIPS mode again by running this command, then restarting the
virtual machine:
```shell
fips-mode-setup --disable
```
#### Detect FIPS enablement in code
You can query `Gitlab::FIPS` in Ruby code to determine if the instance is FIPS-enabled:
```ruby
def default_min_key_size(name)
if Gitlab::FIPS.enabled?
Gitlab::SSHPublicKey.supported_sizes(name).select(&:positive?).min || -1
else
0
end
end
```
#### Unsupported features in FIPS mode
Some GitLab features may not work when FIPS mode is enabled. The following features
are known to not work in FIPS mode. However, there may be additional features not
listed here that also do not work properly in FIPS mode:
- [Container Scanning](../user/application_security/container_scanning/index.md) support for scanning images in repositories that require authentication.
- [Code Quality](../ci/testing/code_quality.md) does not support operating in FIPS-compliant mode.
- [Dependency scanning](../user/application_security/dependency_scanning/index.md) support for Gradle.
- [Dynamic Application Security Testing (DAST)](../user/application_security/dast/index.md)
does not support operating in FIPS-compliant mode.
- [License compliance](../user/compliance/license_compliance/index.md).
- [Solutions for vulnerabilities](../user/application_security/vulnerabilities/index.md#resolve-a-vulnerability)
for yarn projects.
- [Static Application Security Testing (SAST)](../user/application_security/sast/index.md)
supports a reduced set of [analyzers](../user/application_security/sast/#fips-enabled-images)
when operating in FIPS-compliant mode.
Additionally, these package repositories are disabled in FIPS mode:
- [Conan package repository](../user/packages/conan_repository/index.md).
- [Debian package repository](../user/packages/debian_repository/index.md).
## Nightly Omnibus FIPS builds
The Distribution team has created [nightly FIPS Omnibus builds](https://packages.gitlab.com/gitlab/nightly-fips-builds). These
GitLab builds are compiled to use the system OpenSSL instead of the Omnibus-embedded version of OpenSSL.
See [the section on how FIPS builds are created](#how-fips-builds-are-created).
## Runner
See the [documentation on installing a FIPS-compliant GitLab Runner](https://docs.gitlab.com/runner/install/#fips-compliant-gitlab-runner).
## Verify FIPS ## Verify FIPS
The following sections describe ways you can verify if FIPS is enabled. The following sections describe ways you can verify if FIPS is enabled.

View File

@ -313,11 +313,11 @@ run:
```shell ```shell
# Validate all queries # Validate all queries
bundle exec rake gitlab::graphql:validate bundle exec rake gitlab:graphql:validate
# Validate one query # Validate one query
bundle exec rake gitlab::graphql:validate[path/to/query.graphql] bundle exec rake gitlab:graphql:validate[path/to/query.graphql]
# Validate a directory # Validate a directory
bundle exec rake gitlab::graphql:validate[path/to/queries] bundle exec rake gitlab:graphql:validate[path/to/queries]
``` ```
This prints out a report with an entry for each query, explaining why This prints out a report with an entry for each query, explaining why
@ -335,11 +335,11 @@ Usage:
```shell ```shell
# Analyze all queries # Analyze all queries
bundle exec rake gitlab::graphql:analyze bundle exec rake gitlab:graphql:analyze
# Analyze one query # Analyze one query
bundle exec rake gitlab::graphql:analyze[path/to/query.graphql] bundle exec rake gitlab:graphql:analyze[path/to/query.graphql]
# Analyze a directory # Analyze a directory
bundle exec rake gitlab::graphql:analyze[path/to/queries] bundle exec rake gitlab:graphql:analyze[path/to/queries]
``` ```
This prints out a report for each query, including the complexity This prints out a report for each query, including the complexity

View File

@ -753,3 +753,223 @@ If this happens, examine the following:
- Confirm there is sufficient disk space for the Gzip operation. - Confirm there is sufficient disk space for the Gzip operation.
- If NFS is being used, check if the mount option `timeout` is set. The - If NFS is being used, check if the mount option `timeout` is set. The
default is `600`, and changing this to smaller values results in this error. default is `600`, and changing this to smaller values results in this error.
### Backup fails with `File name too long` error
During backup, you can get the `File name too long` error ([issue #354984](https://gitlab.com/gitlab-org/gitlab/-/issues/354984)). For example:
```plaintext
Problem: <class 'OSError: [Errno 36] File name too long:
```
This problem stops the backup script from completing. To fix this problem, you must truncate the filenames causing the problem. A maximum of 246 characters, including the file extension, is permitted.
WARNING:
The steps in this section can potentially lead to **data loss**. All steps must be followed strictly in the order given.
Truncating filenames to resolve the error involves:
- Cleaning up remote uploaded files that aren't tracked in the database.
- Truncating the filenames in the database.
- Rerunning the backup task.
#### Clean up remote uploaded files
A [known issue](https://gitlab.com/gitlab-org/gitlab-ce/issues/45425) caused object store uploads to remain after a parent resource was deleted. This issue was [resolved](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/18698).
To fix these files, you must clean up all remote uploaded files that are in the storage but not tracked in the `uploads` database table.
1. List all the object store upload files that can be moved to a lost and found directory if they don't exist in the GitLab database:
```shell
bundle exec rake gitlab:cleanup:remote_upload_files RAILS_ENV=production
```
1. If you are sure you want to delete these files and remove all non-referenced uploaded files, run:
WARNING:
The following action is **irreversible**.
```shell
bundle exec rake gitlab:cleanup:remote_upload_files RAILS_ENV=production DRY_RUN=false
```
#### Truncate the filenames referenced by the database
You must truncate the files referenced by the database that are causing the problem. The filenames referenced by the database are stored:
- In the `uploads` table.
- In the references found. Any reference found from other database tables and columns.
- On the filesystem.
Truncate the filenames in the `uploads` table:
1. Enter the database console:
For Omnibus GitLab 14.2 and later:
```shell
sudo gitlab-rails dbconsole --database main
```
For Omnibus GitLab 14.1 and earlier:
```shell
sudo gitlab-rails dbconsole
```
For installations from source, GitLab 14.2 and later:
```shell
sudo -u git -H bundle exec rails dbconsole -e production --database main
```
For installations from source, GitLab 14.1 and earlier:
```shell
sudo -u git -H bundle exec rails dbconsole -e production
```
1. Search the `uploads` table for filenames longer than 246 characters:
The following query selects the `uploads` records with filenames longer than 246 characters in batches of 0 to 10000. This improves the performance on large GitLab instances with tables having thousand of records.
```sql
CREATE TEMP TABLE uploads_with_long_filenames AS
SELECT ROW_NUMBER() OVER(ORDER BY id) row_id, id, path
FROM uploads AS u
WHERE LENGTH((regexp_match(u.path, '[^\\/:*?"<>|\r\n]+$'))[1]) > 246;
CREATE INDEX ON uploads_with_long_filenames(row_id);
SELECT
u.id,
u.path,
-- Current filename
(regexp_match(u.path, '[^\\/:*?"<>|\r\n]+$'))[1] AS current_filename,
-- New filename
CONCAT(
LEFT(SPLIT_PART((regexp_match(u.path, '[^\\/:*?"<>|\r\n]+$'))[1], '.', 1), 242),
COALESCE(SUBSTRING((regexp_match(u.path, '[^\\/:*?"<>|\r\n]+$'))[1] FROM '\.(?:.(?!\.))+$'))
) AS new_filename,
-- New path
CONCAT(
COALESCE((regexp_match(u.path, '(.*\/).*'))[1], ''),
CONCAT(
LEFT(SPLIT_PART((regexp_match(u.path, '[^\\/:*?"<>|\r\n]+$'))[1], '.', 1), 242),
COALESCE(SUBSTRING((regexp_match(u.path, '[^\\/:*?"<>|\r\n]+$'))[1] FROM '\.(?:.(?!\.))+$'))
)
) AS new_path
FROM uploads_with_long_filenames AS u
WHERE u.row_id > 0 AND u.row_id <= 10000;
```
Output example:
```postgresql
-[ RECORD 1 ]----+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
id | 34
path | public/@hashed/loremipsumdolorsitametconsecteturadipiscingelitseddoeiusmodtemporincididuntutlaboreetdoloremagnaaliquaauctorelitsedvulputatemisitloremipsumdolorsitametconsecteturadipiscingelitseddoeiusmodtemporincididuntutlaboreetdoloremagnaaliquaauctorelitsedvulputatemisit.txt
current_filename | loremipsumdolorsitametconsecteturadipiscingelitseddoeiusmodtemporincididuntutlaboreetdoloremagnaaliquaauctorelitsedvulputatemisitloremipsumdolorsitametconsecteturadipiscingelitseddoeiusmodtemporincididuntutlaboreetdoloremagnaaliquaauctorelitsedvulputatemisit.txt
new_filename | loremipsumdolorsitametconsecteturadipiscingelitseddoeiusmodtemporincididuntutlaboreetdoloremagnaaliquaauctorelitsedvulputatemisitloremipsumdolorsitametconsecteturadipiscingelitseddoeiusmodtemporincididuntutlaboreetdoloremagnaaliquaauctorelits.txt
new_path | public/@hashed/loremipsumdolorsitametconsecteturadipiscingelitseddoeiusmodtemporincididuntutlaboreetdoloremagnaaliquaauctorelitsedvulputatemisitloremipsumdolorsitametconsecteturadipiscingelitseddoeiusmodtemporincididuntutlaboreetdoloremagnaaliquaauctorelits.txt
```
Where:
- `current_filename`: a filename that is currently more than 246 characters long.
- `new_filename`: a filename that has been truncated to 246 characters maximum.
- `new_path`: new path considering the new_filename (truncated).
Once you validate the batch results, you must change the batch size (`row_id`) using the following sequence of numbers (10000 to 20000). Repeat this process until you reach the last record in the `uploads` table.
1. Rename the files found in the `uploads` table from long filenames to new truncated filenames. The following query rolls back the update so you can check the results safely within a transaction wrapper:
```sql
CREATE TEMP TABLE uploads_with_long_filenames AS
SELECT ROW_NUMBER() OVER(ORDER BY id) row_id, path, id
FROM uploads AS u
WHERE LENGTH((regexp_match(u.path, '[^\\/:*?"<>|\r\n]+$'))[1]) > 246;
CREATE INDEX ON uploads_with_long_filenames(row_id);
BEGIN;
WITH updated_uploads AS (
UPDATE uploads
SET
path =
CONCAT(
COALESCE((regexp_match(updatable_uploads.path, '(.*\/).*'))[1], ''),
CONCAT(
LEFT(SPLIT_PART((regexp_match(updatable_uploads.path, '[^\\/:*?"<>|\r\n]+$'))[1], '.', 1), 242),
COALESCE(SUBSTRING((regexp_match(updatable_uploads.path, '[^\\/:*?"<>|\r\n]+$'))[1] FROM '\.(?:.(?!\.))+$'))
)
)
FROM
uploads_with_long_filenames AS updatable_uploads
WHERE
uploads.id = updatable_uploads.id
AND updatable_uploads.row_id > 0 AND updatable_uploads.row_id <= 10000
RETURNING uploads.*
)
SELECT id, path FROM updated_uploads;
ROLLBACK;
```
Once you validate the batch update results, you must change the batch size (`row_id`) using the following sequence of numbers (10000 to 20000). Repeat this process until you reach the last record in the `uploads` table.
1. Validate that the new filenames from the previous query are the expected ones. If you are sure you want to truncate the records found in the previous step to 246 characters, run the following:
WARNING:
The following action is **irreversible**.
```sql
CREATE TEMP TABLE uploads_with_long_filenames AS
SELECT ROW_NUMBER() OVER(ORDER BY id) row_id, path, id
FROM uploads AS u
WHERE LENGTH((regexp_match(u.path, '[^\\/:*?"<>|\r\n]+$'))[1]) > 246;
CREATE INDEX ON uploads_with_long_filenames(row_id);
UPDATE uploads
SET
path =
CONCAT(
COALESCE((regexp_match(updatable_uploads.path, '(.*\/).*'))[1], ''),
CONCAT(
LEFT(SPLIT_PART((regexp_match(updatable_uploads.path, '[^\\/:*?"<>|\r\n]+$'))[1], '.', 1), 242),
COALESCE(SUBSTRING((regexp_match(updatable_uploads.path, '[^\\/:*?"<>|\r\n]+$'))[1] FROM '\.(?:.(?!\.))+$'))
)
)
FROM
uploads_with_long_filenames AS updatable_uploads
WHERE
uploads.id = updatable_uploads.id
AND updatable_uploads.row_id > 0 AND updatable_uploads.row_id <= 10000;
```
Once you finish the batch update, you must change the batch size (`updatable_uploads.row_id`) using the following sequence of numbers (10000 to 20000). Repeat this process until you reach the last record in the `uploads` table.
Truncate the filenames in the references found:
1. Check if those records are referenced somewhere. One way to do this is to dump the database and search for the parent directory name and filename:
1. To dump your database, you can use the following command as an example:
```shell
pg_dump -h /var/opt/gitlab/postgresql/ -d gitlabhq_production > gitlab-dump.tmp
```
1. Then you can search for the references using the `grep` command. Combining the parent directory and the filename can be a good idea. For example:
```shell
grep public/alongfilenamehere.txt gitlab-dump.tmp
```
1. Replace those long filenames using the new filenames obtained from querying the `uploads` table.
Truncate the filenames on the filesystem. You must manually rename the files in your filesystem to the new filenames obtained from querying the `uploads` table.
#### Re-run the backup task
After following all the previous steps, re-run the backup task.

View File

@ -45,6 +45,27 @@ sole discretion of GitLab Inc.
<div class="announcement-milestone"> <div class="announcement-milestone">
## Announced in 15.2
<div class="deprecation removal-160 breaking-change">
### Remove `job_age` parameter from `POST /jobs/request` Runner endpoint
Planned removal: GitLab <span class="removal-milestone">16.0</span> (2023-05-22)
WARNING:
This is a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
Review the details carefully before upgrading.
The `job_age` parameter, returned from the `POST /jobs/request` API endpoint used in communication with GitLab Runner, was never used by any GitLab or Runner feature. This parameter will be removed in GitLab 16.0.
This could be a breaking change for anyone that developed their own runner that relies on this parameter being returned by the endpoint. This is not a breaking change for anyone using an officially released version of GitLab Runner, including public shared runners on GitLab.com.
</div>
</div>
<div class="announcement-milestone">
## Announced in 15.1 ## Announced in 15.1
<div class="deprecation removal-160 breaking-change"> <div class="deprecation removal-160 breaking-change">

View File

@ -99,7 +99,8 @@ The **Overview** dashboard shows the following key metrics that measure team per
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/340150) lead time for changes DORA metric in GitLab 14.5. > - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/340150) lead time for changes DORA metric in GitLab 14.5.
> - DORA API-based deployment metrics for value stream analytics for groups were [moved](https://gitlab.com/gitlab-org/gitlab/-/issues/337256) from GitLab Ultimate to GitLab Premium in GitLab 14.3. > - DORA API-based deployment metrics for value stream analytics for groups were [moved](https://gitlab.com/gitlab-org/gitlab/-/issues/337256) from GitLab Ultimate to GitLab Premium in GitLab 14.3.
> - DORA and key metrics were [separated into distinct rows in the UI](https://gitlab.com/gitlab-org/gitlab/-/issues/359060) in GitLab 15.0. > - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/355304) time to restore service tile in GitLab 15.0.
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/357071) change failure rate tile in GitLab 15.0.
The value stream analytics **Overview** dashboard displays the following [DORA](../../../user/analytics/index.md) metrics: The value stream analytics **Overview** dashboard displays the following [DORA](../../../user/analytics/index.md) metrics:

View File

@ -49,6 +49,7 @@ module API
offset_limit = limit_for_scope(request_scope) offset_limit = limit_for_scope(request_scope)
if (Gitlab::Pagination::Keyset.available_for_type?(relation) || if (Gitlab::Pagination::Keyset.available_for_type?(relation) ||
cursor_based_keyset_pagination_supported?(relation)) && cursor_based_keyset_pagination_supported?(relation)) &&
cursor_based_keyset_pagination_enforced?(relation) &&
offset_limit_exceeded?(offset_limit) offset_limit_exceeded?(offset_limit)
return error!("Offset pagination has a maximum allowed offset of #{offset_limit} " \ return error!("Offset pagination has a maximum allowed offset of #{offset_limit} " \
@ -63,6 +64,10 @@ module API
Gitlab::Pagination::CursorBasedKeyset.available_for_type?(relation) Gitlab::Pagination::CursorBasedKeyset.available_for_type?(relation)
end end
def cursor_based_keyset_pagination_enforced?(relation)
Gitlab::Pagination::CursorBasedKeyset.enforced_for_type?(relation)
end
def keyset_pagination_enabled? def keyset_pagination_enabled?
params[:pagination] == 'keyset' params[:pagination] == 'keyset'
end end

View File

@ -0,0 +1,44 @@
# frozen_string_literal: true
module Gitlab
module BackgroundMigration
# This class is used to update the delayed_project_removal column
# for user namespaces of the namespace_settings table.
class UpdateDelayedProjectRemovalToNullForUserNamespaces < Gitlab::BackgroundMigration::BatchedMigrationJob
# Migration only version of `namespace_settings` table
class NamespaceSetting < ::ApplicationRecord
self.table_name = 'namespace_settings'
end
def perform
each_sub_batch(
operation_name: :set_delayed_project_removal_to_null_for_user_namespace
) do |sub_batch|
set_delayed_project_removal_to_null_for_user_namespace(sub_batch)
end
end
private
def set_delayed_project_removal_to_null_for_user_namespace(relation)
NamespaceSetting.connection.execute(
<<~SQL
UPDATE namespace_settings
SET delayed_project_removal = NULL
WHERE
namespace_settings.namespace_id IN (
SELECT
namespace_settings.namespace_id
FROM
namespace_settings
INNER JOIN namespaces ON namespaces.id = namespace_settings.namespace_id
WHERE
namespaces.id IN (#{relation.select(:namespace_id).to_sql})
AND namespaces.type = 'User'
AND namespace_settings.delayed_project_removal = FALSE)
SQL
)
end
end
end
end

View File

@ -106,6 +106,7 @@ module Gitlab
description: description, description: description,
state_id: Issue.available_states[issue.state], state_id: Issue.available_states[issue.state],
author_id: gitlab_user_id(project, issue.author), author_id: gitlab_user_id(project, issue.author),
namespace_id: project.project_namespace_id,
milestone: milestone, milestone: milestone,
created_at: issue.created_at, created_at: issue.created_at,
updated_at: issue.updated_at updated_at: issue.updated_at

View File

@ -51,6 +51,7 @@ module Gitlab
title: issue.truncated_title, title: issue.truncated_title,
author_id: author_id, author_id: author_id,
project_id: project.id, project_id: project.id,
namespace_id: project.project_namespace_id,
description: description, description: description,
milestone_id: milestone_finder.id_for(issue), milestone_id: milestone_finder.id_for(issue),
state_id: ::Issue.available_states[issue.state], state_id: ::Issue.available_states[issue.state],

View File

@ -18,6 +18,7 @@ module Gitlab
{ {
iid: params[:iid], iid: params[:iid],
project_id: project.id, project_id: project.id,
namespace_id: project.project_namespace_id,
description: description, description: description,
title: title, title: title,
state_id: map_status(jira_issue.status.statusCategory), state_id: map_status(jira_issue.status.statusCategory),

View File

@ -4,9 +4,18 @@ module Gitlab
module Pagination module Pagination
module CursorBasedKeyset module CursorBasedKeyset
SUPPORTED_ORDERING = { SUPPORTED_ORDERING = {
Group => { name: :asc } Group => { name: :asc },
AuditEvent => { id: :desc }
}.freeze }.freeze
# Relation types that are enforced in this list
# enforce the use of keyset pagination, thus erroring out requests
# made with offset pagination above a certain limit.
#
# In many cases this could introduce a breaking change
# so enforcement is optional.
ENFORCED_TYPES = [Group].freeze
def self.available_for_type?(relation) def self.available_for_type?(relation)
SUPPORTED_ORDERING.key?(relation.klass) SUPPORTED_ORDERING.key?(relation.klass)
end end
@ -16,6 +25,10 @@ module Gitlab
order_satisfied?(relation, cursor_based_request_context) order_satisfied?(relation, cursor_based_request_context)
end end
def self.enforced_for_type?(relation)
ENFORCED_TYPES.include?(relation.klass)
end
def self.order_satisfied?(relation, cursor_based_request_context) def self.order_satisfied?(relation, cursor_based_request_context)
order_by_from_request = cursor_based_request_context.order_by order_by_from_request = cursor_based_request_context.order_by

View File

@ -55,9 +55,10 @@ RSpec.describe API::Helpers::PaginationStrategies do
allow(subject).to receive(:keyset_pagination_enabled?).and_return(false) allow(subject).to receive(:keyset_pagination_enabled?).and_return(false)
end end
context 'when keyset pagination is available for the relation' do context 'when keyset pagination is available and enforced for the relation' do
before do before do
allow(Gitlab::Pagination::Keyset).to receive(:available_for_type?).and_return(true) allow(Gitlab::Pagination::Keyset).to receive(:available_for_type?).and_return(true)
allow(Gitlab::Pagination::CursorBasedKeyset).to receive(:enforced_for_type?).and_return(true)
end end
context 'when a request scope is given' do context 'when a request scope is given' do
@ -70,6 +71,18 @@ RSpec.describe API::Helpers::PaginationStrategies do
subject.paginator(relation, request_scope) subject.paginator(relation, request_scope)
end end
context 'when keyset pagination is not enforced' do
before do
allow(Gitlab::Pagination::CursorBasedKeyset).to receive(:enforced_for_type?).and_return(false)
end
it 'returns no errors' do
expect(subject).not_to receive(:error!)
subject.paginator(relation, request_scope)
end
end
end end
context 'when the scope limit is not exceeded' do context 'when the scope limit is not exceeded' do

View File

@ -0,0 +1,49 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Gitlab::BackgroundMigration::UpdateDelayedProjectRemovalToNullForUserNamespaces,
:migration do
let(:namespaces_table) { table(:namespaces) }
let(:namespace_settings_table) { table(:namespace_settings) }
subject(:perform_migration) do
described_class.new(
start_id: 1,
end_id: 30,
batch_table: :namespace_settings,
batch_column: :namespace_id,
sub_batch_size: 2,
pause_ms: 0,
connection: ActiveRecord::Base.connection
).perform
end
before do
namespaces_table.create!(id: 1, name: 'group_namespace', path: 'path-1', type: 'Group')
namespaces_table.create!(id: 2, name: 'user_namespace', path: 'path-2', type: 'User')
namespaces_table.create!(id: 3, name: 'user_three_namespace', path: 'path-3', type: 'User')
namespaces_table.create!(id: 4, name: 'group_four_namespace', path: 'path-4', type: 'Group')
namespaces_table.create!(id: 5, name: 'group_five_namespace', path: 'path-5', type: 'Group')
namespace_settings_table.create!(namespace_id: 1, delayed_project_removal: false)
namespace_settings_table.create!(namespace_id: 2, delayed_project_removal: false)
namespace_settings_table.create!(namespace_id: 3, delayed_project_removal: nil)
namespace_settings_table.create!(namespace_id: 4, delayed_project_removal: true)
namespace_settings_table.create!(namespace_id: 5, delayed_project_removal: nil)
end
it 'updates `delayed_project_removal` column to null for user namespaces', :aggregate_failures do
expect(ActiveRecord::QueryRecorder.new { perform_migration }.count).to eq(7)
expect(migrated_attribute(1)).to be_falsey
expect(migrated_attribute(2)).to be_nil
expect(migrated_attribute(3)).to be_nil
expect(migrated_attribute(4)).to be_truthy
expect(migrated_attribute(5)).to be_nil
end
def migrated_attribute(namespace_id)
namespace_settings_table.find(namespace_id).delayed_project_removal
end
end

View File

@ -328,6 +328,7 @@ RSpec.describe Gitlab::BitbucketImport::Importer do
expect(project.issues.where(state_id: Issue.available_states[:closed]).size).to eq(5) expect(project.issues.where(state_id: Issue.available_states[:closed]).size).to eq(5)
expect(project.issues.where(state_id: Issue.available_states[:opened]).size).to eq(2) expect(project.issues.where(state_id: Issue.available_states[:opened]).size).to eq(2)
expect(project.issues.map(&:namespace_id).uniq).to match_array([project.project_namespace_id])
end end
describe 'wiki import' do describe 'wiki import' do

View File

@ -45,16 +45,26 @@ RSpec.describe Gitlab::EncodingHelper do
end end
context 'with corrupted diff' do context 'with corrupted diff' do
let(:project) { create(:project, :empty_repo) }
let(:repository) { project.repository }
let(:content) { fixture_file('encoding/Japanese.md') }
let(:corrupted_diff) do let(:corrupted_diff) do
with_empty_bare_repository do |repo| commit_a = repository.create_file(
content = File.read(Rails.root.join( project.creator,
'spec/fixtures/encoding/Japanese.md').to_s) 'Japanese.md',
commit_a = commit(repo, 'Japanese.md', content) content,
commit_b = commit(repo, 'Japanese.md', branch_name: 'HEAD',
content.sub('[TODO: Link]', '[現在作業中です: Link]')) message: 'Create Japanese.md'
)
commit_b = repository.update_file(
project.creator,
'Japanese.md',
content.sub('[TODO: Link]', '[現在作業中です: Link]'),
branch_name: 'HEAD',
message: 'Update Japanese.md'
)
repo.diff(commit_a, commit_b).each_line.map(&:content).join repository.diff(commit_a, commit_b).map(&:diff).join
end
end end
let(:cleaned_diff) do let(:cleaned_diff) do
@ -69,26 +79,6 @@ RSpec.describe Gitlab::EncodingHelper do
it 'does not corrupt data but remove invalid characters' do it 'does not corrupt data but remove invalid characters' do
expect(encoded_diff).to eq(cleaned_diff) expect(encoded_diff).to eq(cleaned_diff)
end end
def commit(repo, path, content)
oid = repo.write(content, :blob)
index = repo.index
index.read_tree(repo.head.target.tree) unless repo.empty?
index.add(path: path, oid: oid, mode: 0100644)
user = { name: 'Test', email: 'test@example.com' }
Rugged::Commit.create(
repo,
tree: index.write_tree(repo),
author: user,
committer: user,
message: "Update #{path}",
parents: repo.empty? ? [] : [repo.head.target].compact,
update_ref: 'HEAD'
)
end
end end
end end

View File

@ -4,9 +4,6 @@ require "spec_helper"
RSpec.describe Gitlab::Git::Branch, :seed_helper do RSpec.describe Gitlab::Git::Branch, :seed_helper do
let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH, '', 'group/project') } let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH, '', 'group/project') }
let(:rugged) do
Rugged::Repository.new(File.join(TestEnv.repos_path, repository.relative_path))
end
subject { repository.branches } subject { repository.branches }
@ -81,20 +78,6 @@ RSpec.describe Gitlab::Git::Branch, :seed_helper do
end end
let(:user) { create(:user) } let(:user) { create(:user) }
let(:committer) { { email: user.email, name: user.name } }
let(:params) do
parents = [rugged.head.target]
tree = parents.first.tree
{
message: +'commit message',
author: committer,
committer: committer,
tree: tree,
parents: parents
}
end
let(:stale_sha) { travel_to(Gitlab::Git::Branch::STALE_BRANCH_THRESHOLD.ago - 5.days) { create_commit } } let(:stale_sha) { travel_to(Gitlab::Git::Branch::STALE_BRANCH_THRESHOLD.ago - 5.days) { create_commit } }
let(:active_sha) { travel_to(Gitlab::Git::Branch::STALE_BRANCH_THRESHOLD.ago + 5.days) { create_commit } } let(:active_sha) { travel_to(Gitlab::Git::Branch::STALE_BRANCH_THRESHOLD.ago + 5.days) { create_commit } }
let(:future_sha) { travel_to(100.days.since) { create_commit } } let(:future_sha) { travel_to(100.days.since) { create_commit } }
@ -137,7 +120,11 @@ RSpec.describe Gitlab::Git::Branch, :seed_helper do
it { expect(repository.branches.size).to eq(SeedRepo::Repo::BRANCHES.size) } it { expect(repository.branches.size).to eq(SeedRepo::Repo::BRANCHES.size) }
def create_commit def create_commit
params[:message].delete!(+"\r") repository.multi_action(
Rugged::Commit.create(rugged, params.merge(committer: committer.merge(time: Time.now))) user,
branch_name: 'HEAD',
message: 'commit message',
actions: []
).newrev
end end
end end

View File

@ -3,68 +3,8 @@
require "spec_helper" require "spec_helper"
RSpec.describe Gitlab::Git::Commit, :seed_helper do RSpec.describe Gitlab::Git::Commit, :seed_helper do
include GitHelpers
let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH, '', 'group/project') } let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH, '', 'group/project') }
let(:rugged_repo) do
Rugged::Repository.new(File.join(TestEnv.repos_path, TEST_REPO_PATH))
end
let(:commit) { described_class.find(repository, SeedRepo::Commit::ID) } let(:commit) { described_class.find(repository, SeedRepo::Commit::ID) }
let(:rugged_commit) { rugged_repo.lookup(SeedRepo::Commit::ID) }
describe "Commit info" do
before do
@committer = {
email: 'mike@smith.com',
name: "Mike Smith",
time: Time.new(2000, 1, 1, 0, 0, 0, "+08:00")
}
@author = {
email: 'john@smith.com',
name: "John Smith",
time: Time.new(2000, 1, 1, 0, 0, 0, "-08:00")
}
@parents = [rugged_repo.head.target]
@gitlab_parents = @parents.map { |c| described_class.find(repository, c.oid) }
@tree = @parents.first.tree
sha = Rugged::Commit.create(
rugged_repo,
author: @author,
committer: @committer,
tree: @tree,
parents: @parents,
message: "Refactoring specs",
update_ref: "HEAD"
)
@raw_commit = rugged_repo.lookup(sha)
@commit = described_class.find(repository, sha)
end
it { expect(@commit.short_id).to eq(@raw_commit.oid[0..10]) }
it { expect(@commit.id).to eq(@raw_commit.oid) }
it { expect(@commit.sha).to eq(@raw_commit.oid) }
it { expect(@commit.safe_message).to eq(@raw_commit.message) }
it { expect(@commit.created_at).to eq(@raw_commit.committer[:time]) }
it { expect(@commit.date).to eq(@raw_commit.committer[:time]) }
it { expect(@commit.author_email).to eq(@author[:email]) }
it { expect(@commit.author_name).to eq(@author[:name]) }
it { expect(@commit.committer_name).to eq(@committer[:name]) }
it { expect(@commit.committer_email).to eq(@committer[:email]) }
it { expect(@commit.different_committer?).to be_truthy }
it { expect(@commit.parents).to eq(@gitlab_parents) }
it { expect(@commit.parent_id).to eq(@parents.first.oid) }
it { expect(@commit.no_commit_message).to eq("No commit message") }
after do
# Erase the new commit so other tests get the original repo
repository.write_ref("refs/heads/master", SeedRepo::LastCommit::ID)
end
end
describe "Commit info from gitaly commit" do describe "Commit info from gitaly commit" do
let(:subject) { (+"My commit").force_encoding('ASCII-8BIT') } let(:subject) { (+"My commit").force_encoding('ASCII-8BIT') }
@ -132,7 +72,7 @@ RSpec.describe Gitlab::Git::Commit, :seed_helper do
shared_examples '.find' do shared_examples '.find' do
it "returns first head commit if without params" do it "returns first head commit if without params" do
expect(described_class.last(repository).id).to eq( expect(described_class.last(repository).id).to eq(
rugged_repo.head.target.oid repository.commit.sha
) )
end end
@ -622,19 +562,6 @@ RSpec.describe Gitlab::Git::Commit, :seed_helper do
end end
end end
skip 'move this test to gitaly-ruby' do
RSpec.describe '#init_from_rugged' do
let(:gitlab_commit) { described_class.new(repository, rugged_commit) }
subject { gitlab_commit }
describe '#id' do
subject { super().id }
it { is_expected.to eq(SeedRepo::Commit::ID) }
end
end
end
describe '#init_from_hash' do describe '#init_from_hash' do
let(:commit) { described_class.new(repository, sample_commit_hash) } let(:commit) { described_class.new(repository, sample_commit_hash) }

View File

@ -3,8 +3,6 @@
require 'spec_helper' require 'spec_helper'
RSpec.describe Gitlab::Git::ObjectPool do RSpec.describe Gitlab::Git::ObjectPool do
include RepoHelpers
let(:pool_repository) { create(:pool_repository) } let(:pool_repository) { create(:pool_repository) }
let(:source_repository) { pool_repository.source_project.repository } let(:source_repository) { pool_repository.source_project.repository }
@ -80,8 +78,6 @@ RSpec.describe Gitlab::Git::ObjectPool do
end end
describe '#fetch' do describe '#fetch' do
let(:source_repository_path) { File.join(TestEnv.repos_path, source_repository.relative_path) }
let(:source_repository_rugged) { Rugged::Repository.new(source_repository_path) }
let(:commit_count) { source_repository.commit_count } let(:commit_count) { source_repository.commit_count }
context "when the object's pool repository exists" do context "when the object's pool repository exists" do
@ -106,7 +102,13 @@ RSpec.describe Gitlab::Git::ObjectPool do
end end
it 'fetches objects from the source repository' do it 'fetches objects from the source repository' do
new_commit_id = new_commit_edit_old_file(source_repository_rugged).oid new_commit_id = source_repository.create_file(
pool_repository.source_project.owner,
'a.file',
'This is a file',
branch_name: source_repository.root_ref,
message: 'Add a file'
)
expect(subject.repository.exists?).to be false expect(subject.repository.exists?).to be false

View File

@ -352,12 +352,30 @@ RSpec.describe Gitlab::Git::Repository, :seed_helper do
repository.create_branch('left-branch') repository.create_branch('left-branch')
repository.create_branch('right-branch') repository.create_branch('right-branch')
left.times do left.times do |i|
new_commit_edit_new_file_on_branch(repository_rugged, 'encoding/CHANGELOG', 'left-branch', 'some more content for a', 'some stuff') repository.multi_action(
user,
branch_name: 'left-branch',
message: 'some more content for a',
actions: [{
action: i == 0 ? :create : :update,
file_path: 'encoding/CHANGELOG',
content: 'some stuff'
}]
)
end end
right.times do right.times do |i|
new_commit_edit_new_file_on_branch(repository_rugged, 'encoding/CHANGELOG', 'right-branch', 'some more content for b', 'some stuff') repository.multi_action(
user,
branch_name: 'right-branch',
message: 'some more content for b',
actions: [{
action: i == 0 ? :create : :update,
file_path: 'encoding/CHANGELOG',
content: 'some stuff'
}]
)
end end
end end
@ -392,12 +410,30 @@ RSpec.describe Gitlab::Git::Repository, :seed_helper do
repository.create_branch('left-branch') repository.create_branch('left-branch')
repository.create_branch('right-branch') repository.create_branch('right-branch')
left.times do left.times do |i|
new_commit_edit_new_file_on_branch(repository_rugged, 'encoding/CHANGELOG', 'left-branch', 'some more content for a', 'some stuff') repository.multi_action(
user,
branch_name: 'left-branch',
message: 'some more content for a',
actions: [{
action: i == 0 ? :create : :update,
file_path: 'encoding/CHANGELOG',
content: 'some stuff'
}]
)
end end
right.times do right.times do |i|
new_commit_edit_new_file_on_branch(repository_rugged, 'encoding/CHANGELOG', 'right-branch', 'some more content for b', 'some stuff') repository.multi_action(
user,
branch_name: 'right-branch',
message: 'some more content for b',
actions: [{
action: i == 0 ? :create : :update,
file_path: 'encoding/CHANGELOG',
content: 'some stuff'
}]
)
end end
end end
@ -557,14 +593,31 @@ RSpec.describe Gitlab::Git::Repository, :seed_helper do
describe '#search_files_by_content' do describe '#search_files_by_content' do
let(:repository) { mutable_repository } let(:repository) { mutable_repository }
let(:repository_rugged) { mutable_repository_rugged }
let(:ref) { 'search-files-by-content-branch' } let(:ref) { 'search-files-by-content-branch' }
let(:content) { 'foobarbazmepmep' } let(:content) { 'foobarbazmepmep' }
before do before do
repository.create_branch(ref) repository.create_branch(ref)
new_commit_edit_new_file_on_branch(repository_rugged, 'encoding/CHANGELOG', ref, 'committing something', content) repository.multi_action(
new_commit_edit_new_file_on_branch(repository_rugged, 'anotherfile', ref, 'committing something', content) user,
branch_name: ref,
message: 'committing something',
actions: [{
action: :create,
file_path: 'encoding/CHANGELOG',
content: content
}]
)
repository.multi_action(
user,
branch_name: ref,
message: 'committing something',
actions: [{
action: :create,
file_path: 'anotherfile',
content: content
}]
)
end end
after do after do
@ -667,14 +720,42 @@ RSpec.describe Gitlab::Git::Repository, :seed_helper do
before do before do
# Add new commits so that there's a renamed file in the commit history # Add new commits so that there's a renamed file in the commit history
@commit_with_old_name_id = new_commit_edit_old_file(repository_rugged).oid @commit_with_old_name_id = repository.multi_action(
@rename_commit_id = new_commit_move_file(repository_rugged).oid user,
@commit_with_new_name_id = new_commit_edit_new_file(repository_rugged, "encoding/CHANGELOG", "Edit encoding/CHANGELOG", "I'm a new changelog with different text").oid branch_name: repository.root_ref,
message: 'Update CHANGELOG',
actions: [{
action: :update,
file_path: 'CHANGELOG',
content: 'CHANGELOG'
}]
).newrev
@rename_commit_id = repository.multi_action(
user,
branch_name: repository.root_ref,
message: 'Move CHANGELOG to encoding/',
actions: [{
action: :move,
previous_path: 'CHANGELOG',
file_path: 'encoding/CHANGELOG',
content: 'CHANGELOG'
}]
).newrev
@commit_with_new_name_id = repository.multi_action(
user,
branch_name: repository.root_ref,
message: 'Edit encoding/CHANGELOG',
actions: [{
action: :update,
file_path: 'encoding/CHANGELOG',
content: "I'm a new changelog with different text"
}]
).newrev
end end
after do after do
# Erase our commits so other tests get the original repo # Erase our commits so other tests get the original repo
repository.write_ref("refs/heads/master", SeedRepo::LastCommit::ID) repository.write_ref(repository.root_ref, SeedRepo::LastCommit::ID)
end end
context "where 'follow' == true" do context "where 'follow' == true" do
@ -1804,12 +1885,18 @@ RSpec.describe Gitlab::Git::Repository, :seed_helper do
context 'when the branch exists' do context 'when the branch exists' do
context 'when the commit does not exist locally' do context 'when the commit does not exist locally' do
let(:source_branch) { 'new-branch-for-fetch-source-branch' } let(:source_branch) { 'new-branch-for-fetch-source-branch' }
let(:source_path) { File.join(TestEnv.repos_path, source_repository.relative_path) }
let(:source_rugged) { Rugged::Repository.new(source_path) }
let(:new_oid) { new_commit_edit_old_file(source_rugged).oid }
before do let!(:new_oid) do
source_repository.write_ref(source_branch, new_oid) source_repository.multi_action(
user,
branch_name: source_branch,
message: 'Add a file',
actions: [{
action: :create,
file_path: 'a.file',
content: 'This is a file.'
}]
).newrev
end end
it 'writes the ref' do it 'writes the ref' do
@ -2276,11 +2363,23 @@ RSpec.describe Gitlab::Git::Repository, :seed_helper do
end end
context 'when the diff contains a rename' do context 'when the diff contains a rename' do
let(:end_sha) { new_commit_move_file(repository_rugged).oid } let(:end_sha) do
repository.multi_action(
user,
branch_name: repository.root_ref,
message: 'Move CHANGELOG to encoding/',
actions: [{
action: :move,
previous_path: 'CHANGELOG',
file_path: 'encoding/CHANGELOG',
content: 'CHANGELOG'
}]
).newrev
end
after do after do
# Erase our commits so other tests get the original repo # Erase our commits so other tests get the original repo
repository.write_ref('refs/heads/master', SeedRepo::LastCommit::ID) repository.write_ref(repository.root_ref, SeedRepo::LastCommit::ID)
end end
it 'does not include the renamed file in the sparse checkout' do it 'does not include the renamed file in the sparse checkout' do
@ -2336,10 +2435,7 @@ RSpec.describe Gitlab::Git::Repository, :seed_helper do
let(:project) { create(:project, :repository) } let(:project) { create(:project, :repository) }
let(:pool_repository) { create(:pool_repository) } let(:pool_repository) { create(:pool_repository) }
let(:repository) { project.repository } let(:repository) { project.repository }
let(:repository_path) { File.join(TestEnv.repos_path, repository.relative_path) }
let(:object_pool) { pool_repository.object_pool } let(:object_pool) { pool_repository.object_pool }
let(:object_pool_path) { File.join(TestEnv.repos_path, object_pool.repository.relative_path) }
let(:object_pool_rugged) { Rugged::Repository.new(object_pool_path) }
before do before do
object_pool.create # rubocop:disable Rails/SaveBang object_pool.create # rubocop:disable Rails/SaveBang
@ -2349,25 +2445,24 @@ RSpec.describe Gitlab::Git::Repository, :seed_helper do
expect { repository.disconnect_alternates }.not_to raise_error expect { repository.disconnect_alternates }.not_to raise_error
end end
it 'removes the alternates file' do
object_pool.link(repository)
alternates_file = File.join(repository_path, "objects", "info", "alternates")
expect(File.exist?(alternates_file)).to be_truthy
repository.disconnect_alternates
expect(File.exist?(alternates_file)).to be_falsey
end
it 'can still access objects in the object pool' do it 'can still access objects in the object pool' do
object_pool.link(repository) object_pool.link(repository)
new_commit = new_commit_edit_old_file(object_pool_rugged) new_commit_id = object_pool.repository.multi_action(
expect(repository.commit(new_commit.oid).id).to eq(new_commit.oid) project.owner,
branch_name: object_pool.repository.root_ref,
message: 'Add a file',
actions: [{
action: :create,
file_path: 'a.file',
content: 'This is a file.'
}]
).newrev
expect(repository.commit(new_commit_id).id).to eq(new_commit_id)
repository.disconnect_alternates repository.disconnect_alternates
expect(repository.commit(new_commit.oid).id).to eq(new_commit.oid) expect(repository.commit(new_commit_id).id).to eq(new_commit_id)
end end
end end

View File

@ -3,6 +3,8 @@
require "spec_helper" require "spec_helper"
RSpec.describe Gitlab::Git::Tree, :seed_helper do RSpec.describe Gitlab::Git::Tree, :seed_helper do
let_it_be(:user) { create(:user) }
let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH, '', 'group/project') } let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH, '', 'group/project') }
shared_examples :repo do shared_examples :repo do
@ -85,52 +87,30 @@ RSpec.describe Gitlab::Git::Tree, :seed_helper do
context :flat_path do context :flat_path do
let(:filename) { 'files/flat/path/correct/content.txt' } let(:filename) { 'files/flat/path/correct/content.txt' }
let(:sha) { create_file(filename) }
let(:path) { 'files/flat' } let(:path) { 'files/flat' }
# rubocop: disable Rails/FindBy # rubocop: disable Rails/FindBy
# This is not ActiveRecord where..first # This is not ActiveRecord where..first
let(:subdir_file) { entries.first } let(:subdir_file) { entries.first }
# rubocop: enable Rails/FindBy # rubocop: enable Rails/FindBy
let(:repository_rugged) { Rugged::Repository.new(File.join(SEED_STORAGE_PATH, TEST_REPO_PATH)) } let!(:sha) do
repository.multi_action(
user,
branch_name: 'HEAD',
message: "Create #{filename}",
actions: [{
action: :create,
file_path: filename,
contents: 'test'
}]
).newrev
end
after do
ensure_seeds
end
it { expect(subdir_file.flat_path).to eq('files/flat/path/correct') } it { expect(subdir_file.flat_path).to eq('files/flat/path/correct') }
end end
def create_file(path)
oid = repository_rugged.write('test', :blob)
index = repository_rugged.index
index.add(path: filename, oid: oid, mode: 0100644)
options = commit_options(
repository_rugged,
index,
repository_rugged.head.target,
'HEAD',
'Add new file')
Rugged::Commit.create(repository_rugged, options)
end
# Build the options hash that's passed to Rugged::Commit#create
def commit_options(repo, index, target, ref, message)
options = {}
options[:tree] = index.write_tree(repo)
options[:author] = {
email: "test@example.com",
name: "Test Author",
time: Time.gm(2014, "mar", 3, 20, 15, 1)
}
options[:committer] = {
email: "test@example.com",
name: "Test Author",
time: Time.gm(2014, "mar", 3, 20, 15, 1)
}
options[:message] ||= message
options[:parents] = repo.empty? ? [] : [target].compact
options[:update_ref] = ref
options
end
end end
describe '#file?' do describe '#file?' do

View File

@ -131,6 +131,7 @@ RSpec.describe Gitlab::GithubImport::Importer::IssueImporter, :clean_gitlab_redi
title: 'My Issue', title: 'My Issue',
author_id: user.id, author_id: user.id,
project_id: project.id, project_id: project.id,
namespace_id: project.project_namespace_id,
description: 'This is my issue', description: 'This is my issue',
milestone_id: milestone.id, milestone_id: milestone.id,
state_id: 1, state_id: 1,
@ -160,6 +161,7 @@ RSpec.describe Gitlab::GithubImport::Importer::IssueImporter, :clean_gitlab_redi
title: 'My Issue', title: 'My Issue',
author_id: project.creator_id, author_id: project.creator_id,
project_id: project.id, project_id: project.id,
namespace_id: project.project_namespace_id,
description: "*Created by: alice*\n\nThis is my issue", description: "*Created by: alice*\n\nThis is my issue",
milestone_id: milestone.id, milestone_id: milestone.id,
state_id: 1, state_id: 1,

View File

@ -75,6 +75,7 @@ RSpec.describe Gitlab::JiraImport::IssueSerializer do
expect(subject).to eq( expect(subject).to eq(
iid: iid, iid: iid,
project_id: project.id, project_id: project.id,
namespace_id: project.project_namespace_id,
description: expected_description.strip, description: expected_description.strip,
title: "[#{key}] #{summary}", title: "[#{key}] #{summary}",
state_id: 1, state_id: 1,

View File

@ -15,6 +15,22 @@ RSpec.describe Gitlab::Pagination::CursorBasedKeyset do
end end
end end
describe '.enforced_for_type?' do
subject { described_class.enforced_for_type?(relation) }
context 'when relation is Group' do
let(:relation) { Group.all }
it { is_expected.to be true }
end
context 'when relation is AuditEvent' do
let(:relation) { AuditEvent.all }
it { is_expected.to be false }
end
end
describe '.available?' do describe '.available?' do
let(:request_context) { double('request_context', params: { order_by: order_by, sort: sort }) } let(:request_context) { double('request_context', params: { order_by: order_by, sort: sort }) }
let(:cursor_based_request_context) { Gitlab::Pagination::Keyset::CursorBasedRequestContext.new(request_context) } let(:cursor_based_request_context) { Gitlab::Pagination::Keyset::CursorBasedRequestContext.new(request_context) }

View File

@ -0,0 +1,32 @@
# frozen_string_literal: true
require 'spec_helper'
require_migration!
RSpec.describe QueueUpdateDelayedProjectRemovalToNullForUserNamespace do
let(:migration) { described_class::MIGRATION }
describe '#up' do
it 'schedules background jobs for each batch of namespace settings' do
migrate!
expect(migration).to(
have_scheduled_batched_migration(
table_name: :namespace_settings,
column_name: :namespace_id,
interval: described_class::INTERVAL,
batch_size: described_class::BATCH_SIZE
)
)
end
end
describe '#down' do
it 'deletes all batched migration records' do
migrate!
schema_migrate_down!
expect(migration).not_to have_scheduled_batched_migration
end
end
end

View File

@ -131,6 +131,37 @@ RSpec.describe Issue do
create(:issue) create(:issue)
end end
end end
context 'issue namespace' do
let(:issue) { build(:issue, project: reusable_project) }
it 'sets the namespace_id' do
expect(issue).to be_valid
expect(issue.namespace).to eq(reusable_project.project_namespace)
end
context 'when issue is created' do
it 'sets the namespace_id' do
issue.save!
expect(issue.reload.namespace).to eq(reusable_project.project_namespace)
end
end
context 'when existing issue is saved' do
let(:issue) { create(:issue) }
before do
issue.update!(namespace_id: nil)
end
it 'sets the namespace id' do
issue.update!(title: "#{issue.title} and something extra")
expect(issue.namespace).to eq(issue.project.project_namespace)
end
end
end
end end
context 'order by upvotes' do context 'order by upvotes' do

View File

@ -255,21 +255,10 @@ RSpec.describe Repository do
end end
context 'with a commit with invalid UTF-8 path' do context 'with a commit with invalid UTF-8 path' do
def create_commit_with_invalid_utf8_path
rugged = rugged_repo(repository)
blob_id = Rugged::Blob.from_buffer(rugged, "some contents")
tree_builder = Rugged::Tree::Builder.new(rugged)
tree_builder.insert({ oid: blob_id, name: "hello\x80world", filemode: 0100644 })
tree_id = tree_builder.write
user = { email: "jcai@gitlab.com", time: Time.current.to_time, name: "John Cai" }
Rugged::Commit.create(rugged, message: 'some commit message', parents: [rugged.head.target.oid], tree: tree_id, committer: user, author: user)
end
it 'does not raise an error' do it 'does not raise an error' do
commit = create_commit_with_invalid_utf8_path response = create_file_in_repo(project, 'master', 'master', "hello\x80world", 'some contents')
expect { repository.list_last_commits_for_tree(commit, '.', offset: 0) }.not_to raise_error expect { repository.list_last_commits_for_tree(response[:result], '.', offset: 0) }.not_to raise_error
end end
end end
end end

View File

@ -3,6 +3,8 @@
require 'spec_helper' require 'spec_helper'
RSpec.describe WorkItem do RSpec.describe WorkItem do
let_it_be(:reusable_project) { create(:project) }
describe 'associations' do describe 'associations' do
it { is_expected.to belong_to(:namespace) } it { is_expected.to belong_to(:namespace) }
it { is_expected.to have_one(:work_item_parent).class_name('WorkItem') } it { is_expected.to have_one(:work_item_parent).class_name('WorkItem') }
@ -55,5 +57,55 @@ RSpec.describe WorkItem do
create(:work_item) create(:work_item)
end end
end end
context 'work item namespace' do
let(:work_item) { build(:work_item, project: reusable_project) }
it 'sets the namespace_id' do
expect(work_item).to be_valid
expect(work_item.namespace).to eq(reusable_project.project_namespace)
end
context 'when work item is saved' do
it 'sets the namespace_id' do
work_item.save!
expect(work_item.reload.namespace).to eq(reusable_project.project_namespace)
end
end
context 'when existing work item is saved' do
let(:work_item) { create(:work_item) }
before do
work_item.update!(namespace_id: nil)
end
it 'sets the namespace id' do
work_item.update!(title: "#{work_item.title} and something extra")
expect(work_item.namespace).to eq(work_item.project.project_namespace)
end
end
end
end
describe 'validations' do
subject { work_item.valid? }
describe 'issue_type' do
let(:work_item) { build(:work_item, issue_type: issue_type) }
context 'when a valid type' do
let(:issue_type) { :issue }
it { is_expected.to eq(true) }
end
context 'empty type' do
let(:issue_type) { nil }
it { is_expected.to eq(false) }
end
end
end end
end end

View File

@ -47,6 +47,7 @@ RSpec.describe Issues::MoveService do
it 'creates a new issue in a new project' do it 'creates a new issue in a new project' do
expect(new_issue.project).to eq new_project expect(new_issue.project).to eq new_project
expect(new_issue.namespace_id).to eq new_project.project_namespace_id
end end
it 'copies issue title' do it 'copies issue title' do

View File

@ -59,22 +59,6 @@ RSpec.describe Projects::AfterRenameService do
end end
end end
context 'gitlab pages' do
before do
allow(project_storage).to receive(:rename_repo) { true }
end
context 'when the project does not have pages deployed' do
it 'does nothing with the pages directory' do
allow(project).to receive(:pages_deployed?).and_return(false)
expect(PagesTransferWorker).not_to receive(:perform_async)
service_execute
end
end
end
context 'attachments' do context 'attachments' do
before do before do
expect(project_storage).to receive(:rename_repo) { true } expect(project_storage).to receive(:rename_repo) { true }

View File

@ -715,20 +715,6 @@ RSpec.describe Projects::TransferService do
end end
end end
context 'moving pages' do
let_it_be(:project) { create(:project, namespace: user.namespace) }
before do
group.add_owner(user)
end
it 'does not schedule a job when no pages are deployed' do
expect(PagesTransferWorker).not_to receive(:perform_async)
execute_transfer
end
end
context 'handling issue contacts' do context 'handling issue contacts' do
let_it_be(:root_group) { create(:group) } let_it_be(:root_group) { create(:group) }

View File

@ -137,80 +137,4 @@ eos
file_content: content file_content: content
).execute ).execute
end end
def commit_options(repo, index, target, ref, message)
options = {}
options[:tree] = index.write_tree(repo)
options[:author] = {
email: "test@example.com",
name: "Test Author",
time: Time.gm(2014, "mar", 3, 20, 15, 1)
}
options[:committer] = {
email: "test@example.com",
name: "Test Author",
time: Time.gm(2014, "mar", 3, 20, 15, 1)
}
options[:message] ||= message
options[:parents] = repo.empty? ? [] : [target].compact
options[:update_ref] = ref
options
end
# Writes a new commit to the repo and returns a Rugged::Commit. Replaces the
# contents of CHANGELOG with a single new line of text.
def new_commit_edit_old_file(repo)
oid = repo.write("I replaced the changelog with this text", :blob)
index = repo.index
index.read_tree(repo.head.target.tree)
index.add(path: "CHANGELOG", oid: oid, mode: 0100644)
options = commit_options(
repo,
index,
repo.head.target,
"HEAD",
"Edit CHANGELOG in its original location"
)
sha = Rugged::Commit.create(repo, options)
repo.lookup(sha)
end
# Writes a new commit to the repo and returns a Rugged::Commit. Replaces the
# contents of the specified file_path with new text.
def new_commit_edit_new_file(repo, file_path, commit_message, text, branch = repo.head)
oid = repo.write(text, :blob)
index = repo.index
index.read_tree(branch.target.tree)
index.add(path: file_path, oid: oid, mode: 0100644)
options = commit_options(repo, index, branch.target, branch.canonical_name, commit_message)
sha = Rugged::Commit.create(repo, options)
repo.lookup(sha)
end
# Writes a new commit to the repo and returns a Rugged::Commit. Replaces the
# contents of encoding/CHANGELOG with new text.
def new_commit_edit_new_file_on_branch(repo, file_path, branch_name, commit_message, text)
branch = repo.branches[branch_name]
new_commit_edit_new_file(repo, file_path, commit_message, text, branch)
end
# Writes a new commit to the repo and returns a Rugged::Commit. Moves the
# CHANGELOG file to the encoding/ directory.
def new_commit_move_file(repo)
blob_oid = repo.head.target.tree.detect { |i| i[:name] == "CHANGELOG" }[:oid]
file_content = repo.lookup(blob_oid).content
oid = repo.write(file_content, :blob)
index = repo.index
index.read_tree(repo.head.target.tree)
index.add(path: "encoding/CHANGELOG", oid: oid, mode: 0100644)
index.remove("CHANGELOG")
options = commit_options(repo, index, repo.head.target, "HEAD", "Move CHANGELOG to encoding/")
sha = Rugged::Commit.create(repo, options)
repo.lookup(sha)
end
end end

View File

@ -355,14 +355,6 @@ module TestEnv
"#{forked_repo_path}.bundle" "#{forked_repo_path}.bundle"
end end
def with_empty_bare_repository(name = nil)
path = Rails.root.join('tmp/tests', name || 'empty-bare-repository').to_s
yield(Rugged::Repository.init_at(path, :bare))
ensure
FileUtils.rm_rf(path)
end
def seed_db def seed_db
Gitlab::DatabaseImporters::WorkItems::BaseTypeImporter.upsert_types Gitlab::DatabaseImporters::WorkItems::BaseTypeImporter.upsert_types
end end

View File

@ -1,10 +1,6 @@
# frozen_string_literal: true # frozen_string_literal: true
require 'fileutils'
RSpec.shared_examples 'can collect git garbage' do |update_statistics: true| RSpec.shared_examples 'can collect git garbage' do |update_statistics: true|
include GitHelpers
let!(:lease_uuid) { SecureRandom.uuid } let!(:lease_uuid) { SecureRandom.uuid }
let!(:lease_key) { "resource_housekeeping:#{resource.id}" } let!(:lease_key) { "resource_housekeeping:#{resource.id}" }
let(:params) { [resource.id, task, lease_key, lease_uuid] } let(:params) { [resource.id, task, lease_key, lease_uuid] }
@ -246,39 +242,6 @@ RSpec.shared_examples 'can collect git garbage' do |update_statistics: true|
subject.perform(resource.id, 'prune', lease_key, lease_uuid) subject.perform(resource.id, 'prune', lease_key, lease_uuid)
end end
# Create a new commit on a random new branch
def create_objects(resource)
rugged = rugged_repo(resource.repository)
old_commit = rugged.branches.first.target
new_commit_sha = Rugged::Commit.create(
rugged,
message: "hello world #{SecureRandom.hex(6)}",
author: { email: 'foo@bar', name: 'baz' },
committer: { email: 'foo@bar', name: 'baz' },
tree: old_commit.tree,
parents: [old_commit]
)
repository.write_ref("refs/heads/#{SecureRandom.hex(6)}", new_commit_sha)
end
def packs(resource)
Dir["#{path_to_repo}/objects/pack/*.pack"]
end
def packed_refs(resource)
path = File.join(path_to_repo, 'packed-refs')
FileUtils.touch(path)
File.read(path)
end
def path_to_repo
@path_to_repo ||= File.join(TestEnv.repos_path, resource.repository.relative_path)
end
def bitmap_path(pack)
pack.sub(/\.pack\z/, '.bitmap')
end
end end
context 'with bitmaps enabled' do context 'with bitmaps enabled' do

View File

@ -365,7 +365,6 @@ RSpec.describe 'Every Sidekiq worker' do
'Packages::Rubygems::ExtractionWorker' => 3, 'Packages::Rubygems::ExtractionWorker' => 3,
'PagesDomainSslRenewalWorker' => 3, 'PagesDomainSslRenewalWorker' => 3,
'PagesDomainVerificationWorker' => 3, 'PagesDomainVerificationWorker' => 3,
'PagesTransferWorker' => 3,
'PagesWorker' => 3, 'PagesWorker' => 3,
'PersonalAccessTokens::Groups::PolicyWorker' => 3, 'PersonalAccessTokens::Groups::PolicyWorker' => 3,
'PersonalAccessTokens::Instance::PolicyWorker' => 3, 'PersonalAccessTokens::Instance::PolicyWorker' => 3,