Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
3d6aa90710
commit
049f94a652
15 changed files with 318 additions and 60 deletions
|
@ -0,0 +1,19 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class TempIndexForProjectNamespaceMemberBackfill < Gitlab::Database::Migration[1.0]
|
||||
INDEX_NAME = 'tmp_index_for_namespace_id_migration_on_project_members'
|
||||
|
||||
disable_ddl_transaction!
|
||||
|
||||
def up
|
||||
# Temporary index to be removed in future
|
||||
# https://gitlab.com/gitlab-org/gitlab/-/issues/356509
|
||||
add_concurrent_index :members, :id,
|
||||
where: "members.member_namespace_id IS NULL and members.type = 'ProjectMember'",
|
||||
name: INDEX_NAME
|
||||
end
|
||||
|
||||
def down
|
||||
remove_concurrent_index_by_name :members, INDEX_NAME
|
||||
end
|
||||
end
|
|
@ -0,0 +1,27 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class ScheduleBackfillProjectMemberNamespaceId < Gitlab::Database::Migration[1.0]
|
||||
MIGRATION = 'BackfillProjectMemberNamespaceId'
|
||||
INTERVAL = 2.minutes
|
||||
BATCH_SIZE = 1_000
|
||||
MAX_BATCH_SIZE = 2_000
|
||||
SUB_BATCH_SIZE = 200
|
||||
|
||||
disable_ddl_transaction!
|
||||
|
||||
def up
|
||||
queue_batched_background_migration(
|
||||
MIGRATION,
|
||||
:members,
|
||||
:id,
|
||||
job_interval: INTERVAL,
|
||||
batch_size: BATCH_SIZE,
|
||||
max_batch_size: MAX_BATCH_SIZE,
|
||||
sub_batch_size: SUB_BATCH_SIZE
|
||||
)
|
||||
end
|
||||
|
||||
def down
|
||||
delete_batched_background_migration(MIGRATION, :members, :id, [])
|
||||
end
|
||||
end
|
1
db/schema_migrations/20220516054002
Normal file
1
db/schema_migrations/20220516054002
Normal file
|
@ -0,0 +1 @@
|
|||
72412b4e47f69737ecc50f234d182b2bb9c7d0a03426baffec137651613468c6
|
1
db/schema_migrations/20220516054011
Normal file
1
db/schema_migrations/20220516054011
Normal file
|
@ -0,0 +1 @@
|
|||
23e7a5c3ea535b7faf0e9ba3e95d8ca1431ba96f5f431e0fed0e0c8df340d882
|
|
@ -29796,6 +29796,8 @@ CREATE INDEX tmp_index_container_repositories_on_id_migration_state ON container
|
|||
|
||||
CREATE INDEX tmp_index_for_namespace_id_migration_on_group_members ON members USING btree (id) WHERE ((member_namespace_id IS NULL) AND ((type)::text = 'GroupMember'::text));
|
||||
|
||||
CREATE INDEX tmp_index_for_namespace_id_migration_on_project_members ON members USING btree (id) WHERE ((member_namespace_id IS NULL) AND ((type)::text = 'ProjectMember'::text));
|
||||
|
||||
CREATE INDEX tmp_index_for_namespace_id_migration_on_routes ON routes USING btree (id) WHERE ((namespace_id IS NULL) AND ((source_type)::text = 'Namespace'::text));
|
||||
|
||||
CREATE INDEX tmp_index_for_null_project_namespace_id ON projects USING btree (id) WHERE (project_namespace_id IS NULL);
|
||||
|
|
|
@ -317,6 +317,17 @@ the Container Registry by themselves, follow the steps below.
|
|||
|
||||
1. Save the file and [restart GitLab](../restart_gitlab.md#installations-from-source) for the changes to take effect.
|
||||
|
||||
### Increase token duration
|
||||
|
||||
In GitLab, tokens for the Container Registry expire every five minutes.
|
||||
To increase the token duration:
|
||||
|
||||
1. On the top bar, select **Menu > Admin**.
|
||||
1. On the left sidebar, select **Settings > CI/CD**.
|
||||
1. Expand **Container Registry**.
|
||||
1. For the **Authorization token duration (minutes)**, update the value.
|
||||
1. Select **Save changes**.
|
||||
|
||||
## Configure storage for the Container Registry
|
||||
|
||||
NOTE:
|
||||
|
@ -1226,29 +1237,6 @@ mounting the Docker daemon and setting `privileged = false` in the GitLab Runner
|
|||
|
||||
Additional information about this: [issue 18239](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/18239).
|
||||
|
||||
### `unauthorized: authentication required` when pushing large images
|
||||
|
||||
Example error:
|
||||
|
||||
```shell
|
||||
docker push gitlab.example.com/myproject/docs:latest
|
||||
The push refers to a repository [gitlab.example.com/myproject/docs]
|
||||
630816f32edb: Preparing
|
||||
530d5553aec8: Preparing
|
||||
...
|
||||
4b0bab9ff599: Waiting
|
||||
d1c800db26c7: Waiting
|
||||
42755cf4ee95: Waiting
|
||||
unauthorized: authentication required
|
||||
```
|
||||
|
||||
GitLab has a default token expiration of 5 minutes for the registry. When pushing
|
||||
larger images, or images that take longer than 5 minutes to push, users may
|
||||
encounter this error. On GitLab.com, the expiration time is 15 minutes.
|
||||
|
||||
Administrators can increase the token duration in **Admin Area > Settings >
|
||||
CI/CD > Container Registry > Authorization token duration (minutes)**.
|
||||
|
||||
### Docker login attempt fails with: 'token signed by untrusted key'
|
||||
|
||||
[Registry relies on GitLab to validate credentials](#architecture-of-gitlab-container-registry)
|
||||
|
|
|
@ -139,6 +139,16 @@ Do not use **and so on**. Instead, be more specific. For details, see
|
|||
|
||||
Use [**section**](#section) instead of **area**. The only exception is [the Admin Area](#admin-area).
|
||||
|
||||
## associate
|
||||
|
||||
Do not use **associate** when describing adding issues to epics, or users to issues, merge requests,
|
||||
or epics.
|
||||
|
||||
Instead, use **assign**. For example:
|
||||
|
||||
- Assign the issue to an epic.
|
||||
- Assign a user to the issue.
|
||||
|
||||
## below
|
||||
|
||||
Try to avoid **below** when referring to an example or table in a documentation page. If required, use **following** instead. For example:
|
||||
|
@ -347,6 +357,8 @@ See also [**type**](#type).
|
|||
|
||||
Use lowercase for **epic**.
|
||||
|
||||
See also [associate](#associate).
|
||||
|
||||
## epic board
|
||||
|
||||
Use lowercase for **epic board**.
|
||||
|
|
|
@ -7,36 +7,33 @@ info: To determine the technical writer assigned to the Stage/Group associated w
|
|||
|
||||
# Elasticsearch integration **(PREMIUM SELF)**
|
||||
|
||||
> Moved to GitLab Premium in 13.9.
|
||||
|
||||
This page describes how to enable Advanced Search. When enabled,
|
||||
Advanced Search provides faster search response times and [improved search features](../user/search/advanced_search.md).
|
||||
|
||||
## Version requirements
|
||||
|
||||
> Support for Elasticsearch 6.8 was [deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/350275) in GitLab 14.8 and is scheduled for removal in GitLab 15.0.
|
||||
### Elasticsearch version requirements
|
||||
|
||||
| GitLab version | Elasticsearch version |
|
||||
|----------------------|--------------------------|
|
||||
| GitLab 14.8 or later | Elasticsearch 7.x - 7.17 |
|
||||
| GitLab 13.9 - 14.7 | Elasticsearch 6.8 - 7.x |
|
||||
| GitLab 13.3 - 13.8 | Elasticsearch 6.4 - 7.x |
|
||||
| GitLab 12.7 - 13.2 | Elasticsearch 6.x - 7.x |
|
||||
| GitLab 11.5 - 12.6 | Elasticsearch 5.6 - 6.x |
|
||||
> Support for Elasticsearch 6.8 was [removed](https://gitlab.com/gitlab-org/gitlab/-/issues/350275) in GitLab 15.0.
|
||||
|
||||
The Elasticsearch Integration works with supported versions of
|
||||
Elasticsearch and follows Elasticsearch's [End of Life Policy](https://www.elastic.co/support/eol).
|
||||
Advanced Search works with the following versions of Elasticsearch.
|
||||
|
||||
| GitLab version | Elasticsearch version |
|
||||
|-----------------------|--------------------------|
|
||||
| GitLab 15.0 or later | Elasticsearch 7.x - 8.x |
|
||||
| GitLab 13.9 - 14.10 | Elasticsearch 6.8 - 7.x |
|
||||
| GitLab 13.3 - 13.8 | Elasticsearch 6.4 - 7.x |
|
||||
| GitLab 12.7 - 13.2 | Elasticsearch 6.x - 7.x |
|
||||
|
||||
Advanced Search follows Elasticsearch's [End of Life Policy](https://www.elastic.co/support/eol).
|
||||
When we change Elasticsearch supported versions in GitLab, we announce them in [deprecation notes](https://about.gitlab.com/handbook/marketing/blog/release-posts/#deprecations) in monthly release posts
|
||||
before we remove them.
|
||||
|
||||
### Versions not supported
|
||||
### OpenSearch version requirements
|
||||
|
||||
GitLab does not support:
|
||||
|
||||
- [Amazon's OpenSearch](https://aws.amazon.com/blogs/opensource/opensearch-1-0-launches/)
|
||||
(a [fork of Elasticsearch](https://www.elastic.co/what-is/opensearch)). Use AWS Elasticsearch Service 7.10 instead.
|
||||
For updates, see [issue #327560](https://gitlab.com/gitlab-org/gitlab/-/issues/327560).
|
||||
- Elasticsearch 8.0. For updates, see [issue #350600](https://gitlab.com/gitlab-org/gitlab/-/issues/350600). Use Elasticsearch 7.17 instead.
|
||||
| GitLab version | Elasticsearch version |
|
||||
|-----------------------|--------------------------|
|
||||
| GitLab 15.0 or later | OpenSearch 1.x or later |
|
||||
|
||||
## System requirements
|
||||
|
||||
|
@ -59,8 +56,6 @@ source. You must [install it separately](https://www.elastic.co/guide/en/elastic
|
|||
You can install Elasticsearch yourself, or use a cloud hosted offering such as [Elasticsearch Service](https://www.elastic.co/elasticsearch/service) (available on AWS, GCP, or Azure) or the [Amazon OpenSearch](https://docs.aws.amazon.com/opensearch-service/latest/developerguide/gsg.html)
|
||||
service.
|
||||
|
||||
If using the Amazon OpenSearch service, ensure that you select `Elasticsearch 7.10` when configuring Deployment type. As noted in [Versions not supported](#versions-not-supported), Amazon's non-Elasticsearch versions are not yet supported.
|
||||
|
||||
You should install Elasticsearch on a separate server. Running Elasticsearch on the same server as GitLab is not recommended and can cause a degradation in GitLab instance performance.
|
||||
|
||||
For a single node Elasticsearch cluster, the functional cluster health status is always yellow due to the allocation of the primary shard. Elasticsearch cannot assign replica shards to the same node as primary shards.
|
||||
|
@ -72,14 +67,10 @@ The search index updates after you:
|
|||
|
||||
## Upgrade to a new Elasticsearch major version
|
||||
|
||||
Elasticsearch reads and uses indices created in the previous major version. You are not required to change the GitLab configuration when you upgrade Elasticsearch.
|
||||
> - Elasticsearch 6.8 support is removed with GitLab 15.0.
|
||||
> - Upgrading from GitLab 14.10 to 15.0 requires that you are using any version of Elasticsearch 7.x.
|
||||
|
||||
If your current index was created before GitLab 13.0, you must reindex from scratch to create an alias to use features such as [zero downtime reindexing](#zero-downtime-reindexing). After you reindex, you can perform zero downtime reindexing and also benefit from future features that use the alias.
|
||||
|
||||
To check if your current index was created before GitLab 13.0, use the [Elasticsearch cat aliases API](https://www.elastic.co/guide/en/elasticsearch/reference/7.11/cat-alias.html).
|
||||
If the returned list of aliases does not contain a `gitlab-production` alias, you must reindex to use features such as zero downtime reindexing.
|
||||
If the returned list of aliases contains an entry for `gitlab-production` that points to an index
|
||||
named `gitlab-production-<numerical timestamp>`, your index was created after GitLab 13.0.
|
||||
You are not required to change the GitLab configuration when you upgrade Elasticsearch.
|
||||
|
||||
## Elasticsearch repository indexer
|
||||
|
||||
|
@ -1101,3 +1092,13 @@ es:ESHttpPost
|
|||
es:ESHttpPut
|
||||
es:ESHttpPatch
|
||||
```
|
||||
|
||||
### Role-mapping when using AWS Elasticsearch or AWS OpenSearch fine-grained access control
|
||||
|
||||
When using fine-grained access control with an IAM role, you might encounter the following error:
|
||||
|
||||
```plaintext
|
||||
{"error":{"root_cause":[{"type":"security_exception","reason":"no permissions for [indices:data/write/bulk] and User [name=arn:aws:iam::xxx:role/INSERT_ROLE_NAME_HERE, backend_roles=[arn:aws:iam::xxx:role/INSERT_ROLE_NAME_HERE], requestedTenant=null]"}],"type":"security_exception","reason":"no permissions for [indices:data/write/bulk] and User [name=arn:aws:iam::xxx:role/INSERT_ROLE_NAME_HERE, backend_roles=[arn:aws:iam::xxx:role/INSERT_ROLE_NAME_HERE], requestedTenant=null]"},"status":403}
|
||||
```
|
||||
|
||||
To fix this, you need to [map the roles to users](https://docs.aws.amazon.com/opensearch-service/latest/developerguide/fgac.html#fgac-mapping) in Kibana.
|
||||
|
|
|
@ -619,9 +619,10 @@ You should consider these security implications before configuring IP address re
|
|||
- **Administrators and group owners can access group settings from any IP address**: Users with these permission levels can always
|
||||
access the group settings, regardless of IP restriction, but they cannot access projects
|
||||
belonging to the group when accessing from a disallowed IP address.
|
||||
- **Some GitLab API endpoints will remain accessible from any IP**: Only the [group](../../api/groups.md) (including all
|
||||
[group resources](../../api/api_resources.md#group-resources)) APIs and [project](../../api/api_resources.md#project-resources)
|
||||
(including all [project resources](../../api/api_resources.md#project-resources)) APIs are protected by IP address restrictions.
|
||||
- **Some GitLab API endpoints will remain accessible from any IP**: Users coming from denied IP addresses can still see group and project
|
||||
names and hierarchies. Only the [group](../../api/groups.md) (including all [group resources](../../api/api_resources.md#group-resources))
|
||||
APIs and [project](../../api/api_resources.md#project-resources) (including all [project resources](../../api/api_resources.md#project-resources))
|
||||
APIs are protected by IP address restrictions.
|
||||
- **Activities performed by GitLab Runners are not bound by IP restrictions**:
|
||||
When you register a runner, it is not bound by the IP restrictions. When the runner
|
||||
requests a new job or an update to a job's state, it is also not bound by
|
||||
|
|
|
@ -707,3 +707,27 @@ GitLab is [migrating to the next generation of the Container Registry](https://g
|
|||
During the migration, you may encounter difficulty deleting tags.
|
||||
If you encounter an error, it's likely that your image repository is in the process of being migrated.
|
||||
Please wait a few minutes and try again.
|
||||
|
||||
### `unauthorized: authentication required` when pushing large images
|
||||
|
||||
When pushing large images, you might get an error like the following:
|
||||
|
||||
```shell
|
||||
docker push gitlab.example.com/myproject/docs:latest
|
||||
The push refers to a repository [gitlab.example.com/myproject/docs]
|
||||
630816f32edb: Preparing
|
||||
530d5553aec8: Preparing
|
||||
...
|
||||
4b0bab9ff599: Waiting
|
||||
d1c800db26c7: Waiting
|
||||
42755cf4ee95: Waiting
|
||||
unauthorized: authentication required
|
||||
```
|
||||
|
||||
On self-managed GitLab instances, by default, tokens for the Container Registry expire every five minutes.
|
||||
When pushing larger images, or images that take longer than five minutes to push,
|
||||
you might encounter this error. On GitLab.com, the expiration time is 15 minutes.
|
||||
|
||||
If you are using self-managed GitLab, you can ask an administrator to
|
||||
[increase the token duration](../../../administration/packages/container_registry.md#increase-token-duration)
|
||||
if necessary.
|
||||
|
|
|
@ -32,6 +32,11 @@ Prerequisites:
|
|||
If authenticating with a deploy token, it must be configured with the `write_package_registry`
|
||||
scope. If authenticating with a personal access token or project access token, it must be
|
||||
configured with the `api` scope.
|
||||
- You must call this API endpoint serially when attempting to upload multiple files under the
|
||||
same package name and version. Attempts to concurrently upload multiple files into
|
||||
a new package name and version may face partial failures with
|
||||
`HTTP 500: Internal Server Error` responses due to the requests racing to
|
||||
create the package.
|
||||
|
||||
```plaintext
|
||||
PUT /projects/:id/packages/generic/:package_name/:package_version/:file_name?status=:status
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Gitlab
|
||||
module BackgroundMigration
|
||||
# Backfills the `members.member_namespace_id` column for `type=ProjectMember`
|
||||
class BackfillProjectMemberNamespaceId < Gitlab::BackgroundMigration::BatchedMigrationJob
|
||||
def perform
|
||||
parent_batch_relation = relation_scoped_to_range(batch_table, batch_column, start_id, end_id)
|
||||
|
||||
parent_batch_relation.each_batch(column: batch_column, of: sub_batch_size, order_hint: :type) do |sub_batch|
|
||||
batch_metrics.time_operation(:update_all) do
|
||||
# rubocop:disable Layout/LineLength
|
||||
sub_batch.update_all('member_namespace_id = (SELECT projects.project_namespace_id FROM projects WHERE projects.id = source_id)')
|
||||
# rubocop:enable Layout/LineLength
|
||||
end
|
||||
|
||||
pause_ms_value = [0, pause_ms].max
|
||||
sleep(pause_ms_value * 0.001)
|
||||
end
|
||||
end
|
||||
|
||||
def batch_metrics
|
||||
@batch_metrics ||= Gitlab::Database::BackgroundMigration::BatchMetrics.new
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def relation_scoped_to_range(source_table, source_key_column, start_id, stop_id)
|
||||
define_batchable_model(source_table, connection: ApplicationRecord.connection)
|
||||
.where(source_key_column => start_id..stop_id)
|
||||
.joins('INNER JOIN projects ON members.source_id = projects.id')
|
||||
.where(type: 'ProjectMember', source_type: 'Project')
|
||||
.where(member_namespace_id: nil)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,7 +1,12 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module QA
|
||||
RSpec.describe 'Plan', :smoke, feature_flag: { name: 'vue_issues_list', scope: :group } do
|
||||
RSpec.describe(
|
||||
'Plan',
|
||||
:smoke,
|
||||
feature_flag: { name: 'vue_issues_list', scope: :group },
|
||||
quarantine: { issue: 'https://gitlab.com/gitlab-com/gl-infra/production/-/issues/7099', type: :investigating, only: { subdomain: 'pre' } }
|
||||
) do
|
||||
describe 'Issue creation' do
|
||||
let(:project) { Resource::Project.fabricate_via_api! }
|
||||
let(:closed_issue) { Resource::Issue.fabricate_via_api! { |issue| issue.project = project } }
|
||||
|
@ -15,8 +20,7 @@ module QA
|
|||
it(
|
||||
'creates an issue',
|
||||
:mobile,
|
||||
testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347989',
|
||||
except: { subdomain: 'pre' }
|
||||
testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347989'
|
||||
) do
|
||||
issue = Resource::Issue.fabricate_via_browser_ui! { |issue| issue.project = project }
|
||||
|
||||
|
@ -33,8 +37,7 @@ module QA
|
|||
it(
|
||||
'closes an issue',
|
||||
:mobile,
|
||||
testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347967',
|
||||
except: { subdomain: 'pre' }
|
||||
testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347967'
|
||||
) do
|
||||
closed_issue.visit!
|
||||
|
||||
|
@ -71,7 +74,11 @@ module QA
|
|||
# The following example is excluded from running in `review-qa-smoke` job
|
||||
# as it proved to be flaky when running against Review App
|
||||
# See https://gitlab.com/gitlab-com/www-gitlab-com/-/issues/11568#note_621999351
|
||||
it 'comments on an issue with an attachment', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347946', except: { subdomain: 'pre', job: 'review-qa-smoke' } do
|
||||
it(
|
||||
'comments on an issue with an attachment',
|
||||
testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347946',
|
||||
except: { job: 'review-qa-smoke' }
|
||||
) do
|
||||
Page::Project::Issue::Show.perform do |show|
|
||||
show.comment('See attached image for scale', attachment: file_to_attach)
|
||||
|
||||
|
|
|
@ -0,0 +1,104 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Gitlab::BackgroundMigration::BackfillProjectMemberNamespaceId, :migration, schema: 20220516054011 do
|
||||
let(:migration) do
|
||||
described_class.new(start_id: 1, end_id: 10,
|
||||
batch_table: table_name, batch_column: batch_column,
|
||||
sub_batch_size: sub_batch_size, pause_ms: pause_ms,
|
||||
connection: ApplicationRecord.connection)
|
||||
end
|
||||
|
||||
let(:members_table) { table(:members) }
|
||||
let(:projects_table) { table(:projects) }
|
||||
let(:namespaces_table) { table(:namespaces) }
|
||||
|
||||
let(:table_name) { 'members' }
|
||||
let(:batch_column) { :id }
|
||||
let(:sub_batch_size) { 100 }
|
||||
let(:pause_ms) { 0 }
|
||||
|
||||
subject(:perform_migration) do
|
||||
migration.perform
|
||||
end
|
||||
|
||||
before do
|
||||
namespaces_table.create!(id: 201, name: 'group1', path: 'group1', type: 'Group')
|
||||
namespaces_table.create!(id: 202, name: 'group2', path: 'group2', type: 'Group')
|
||||
namespaces_table.create!(id: 300, name: 'project-namespace-1', path: 'project-namespace-1-path', type: 'Project')
|
||||
namespaces_table.create!(id: 301, name: 'project-namespace-2', path: 'project-namespace-2-path', type: 'Project')
|
||||
namespaces_table.create!(id: 302, name: 'project-namespace-3', path: 'project-namespace-3-path', type: 'Project')
|
||||
|
||||
projects_table.create!(id: 100, name: 'project1', path: 'project1', namespace_id: 202, project_namespace_id: 300)
|
||||
projects_table.create!(id: 101, name: 'project2', path: 'project2', namespace_id: 202, project_namespace_id: 301)
|
||||
projects_table.create!(id: 102, name: 'project3', path: 'project3', namespace_id: 202, project_namespace_id: 302)
|
||||
|
||||
# project1, no member namespace (fill in)
|
||||
members_table.create!(id: 1, source_id: 100,
|
||||
source_type: 'Project', type: 'ProjectMember',
|
||||
member_namespace_id: nil, access_level: 10, notification_level: 3)
|
||||
# bogus source id, no member namespace id (do nothing)
|
||||
members_table.create!(id: 2, source_id: non_existing_record_id,
|
||||
source_type: 'Project', type: 'ProjectMember',
|
||||
member_namespace_id: nil, access_level: 10, notification_level: 3)
|
||||
# project3, existing member namespace id (do nothing)
|
||||
members_table.create!(id: 3, source_id: 102,
|
||||
source_type: 'Project', type: 'ProjectMember',
|
||||
member_namespace_id: 300, access_level: 10, notification_level: 3)
|
||||
|
||||
# Group memberships (do not change)
|
||||
# group1, no member namespace (do nothing)
|
||||
members_table.create!(id: 4, source_id: 201,
|
||||
source_type: 'Namespace', type: 'GroupMember',
|
||||
member_namespace_id: nil, access_level: 10, notification_level: 3)
|
||||
# group2, existing member namespace (do nothing)
|
||||
members_table.create!(id: 5, source_id: 202,
|
||||
source_type: 'Namespace', type: 'GroupMember',
|
||||
member_namespace_id: 201, access_level: 10, notification_level: 3)
|
||||
|
||||
# Project Namespace memberships (do not change)
|
||||
# project namespace, existing member namespace (do nothing)
|
||||
members_table.create!(id: 6, source_id: 300,
|
||||
source_type: 'Namespace', type: 'ProjectNamespaceMember',
|
||||
member_namespace_id: 201, access_level: 10, notification_level: 3)
|
||||
# project namespace, not member namespace (do nothing)
|
||||
members_table.create!(id: 7, source_id: 301,
|
||||
source_type: 'Namespace', type: 'ProjectNamespaceMember',
|
||||
member_namespace_id: 201, access_level: 10, notification_level: 3)
|
||||
end
|
||||
|
||||
it 'backfills `member_namespace_id` for the selected records', :aggregate_failures do
|
||||
expect(members_table.where(type: 'ProjectMember', member_namespace_id: nil).count).to eq 2
|
||||
expect(members_table.where(type: 'GroupMember', member_namespace_id: nil).count).to eq 1
|
||||
|
||||
queries = ActiveRecord::QueryRecorder.new do
|
||||
perform_migration
|
||||
end
|
||||
|
||||
# rubocop:disable Layout/LineLength
|
||||
expect(queries.count).to eq(3)
|
||||
expect(members_table.where(type: 'ProjectMember', member_namespace_id: nil).count).to eq 1 # just the bogus one
|
||||
expect(members_table.where(type: 'ProjectMember').pluck(:member_namespace_id)).to match_array([nil, 300, 300])
|
||||
expect(members_table.where(type: 'GroupMember', member_namespace_id: nil).count).to eq 1
|
||||
expect(members_table.where(type: 'GroupMember').pluck(:member_namespace_id)).to match_array([nil, 201])
|
||||
# rubocop:enable Layout/LineLength
|
||||
end
|
||||
|
||||
it 'tracks timings of queries' do
|
||||
expect(migration.batch_metrics.timings).to be_empty
|
||||
|
||||
expect { perform_migration }.to change { migration.batch_metrics.timings }
|
||||
end
|
||||
|
||||
context 'when given a negative pause_ms' do
|
||||
let(:pause_ms) { -9 }
|
||||
let(:sub_batch_size) { 2 }
|
||||
|
||||
it 'uses 0 as a floor for pause_ms' do
|
||||
expect(migration).to receive(:sleep).with(0)
|
||||
|
||||
perform_migration
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,29 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
require_migration!
|
||||
|
||||
RSpec.describe ScheduleBackfillProjectMemberNamespaceId do
|
||||
let_it_be(:migration) { described_class::MIGRATION }
|
||||
|
||||
describe '#up' do
|
||||
it 'schedules background jobs for each batch of project members' do
|
||||
migrate!
|
||||
|
||||
expect(migration).to have_scheduled_batched_migration(
|
||||
table_name: :members,
|
||||
column_name: :id,
|
||||
interval: described_class::INTERVAL
|
||||
)
|
||||
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
|
Loading…
Reference in a new issue