Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2024-06-18 12:20:04 +00:00
parent 2cec357c4f
commit 04060718ac
55 changed files with 702 additions and 156 deletions

View File

@ -24,6 +24,7 @@ RSpec/MultipleMemoizedHelpers:
- 'spec/requests/api/issues/issues_spec.rb'
- 'spec/requests/api/issues/put_projects_issues_spec.rb'
- 'spec/requests/api/maven_packages_spec.rb'
- 'spec/requests/api/users_spec.rb'
- 'spec/services/boards/issues/list_service_spec.rb'
- 'spec/services/labels/promote_service_spec.rb'
- 'spec/services/merge_requests/push_options_handler_service_spec.rb'

View File

@ -232,7 +232,7 @@ gem 'nokogiri', '~> 1.16' # rubocop:todo Gemfile/MissingFeatureCategory
gem 'gitlab-glfm-markdown', '~> 0.0.17', feature_category: :team_planning
# Calendar rendering
gem 'icalendar' # rubocop:todo Gemfile/MissingFeatureCategory
gem 'icalendar', '~> 2.10.1', feature_category: :system_access
# Diffs
gem 'diffy', '~> 3.4' # rubocop:todo Gemfile/MissingFeatureCategory

View File

@ -317,7 +317,7 @@
{"name":"httpclient","version":"2.8.3","platform":"ruby","checksum":"2951e4991214464c3e92107e46438527d23048e634f3aee91c719e0bdfaebda6"},
{"name":"i18n","version":"1.14.4","platform":"ruby","checksum":"c7deedead0866ea9102975a4eab7968f53de50793a0c211a37808f75dd187551"},
{"name":"i18n_data","version":"0.13.1","platform":"ruby","checksum":"e5aa99b09a69b463bb0443fc1f9540351a49f3d1541c5e91316bafa035c63f66"},
{"name":"icalendar","version":"2.8.0","platform":"ruby","checksum":"e404f970c7572bdebf6f09f9890970b68aab400ba9e609dc7d46098f28d0ee87"},
{"name":"icalendar","version":"2.10.1","platform":"ruby","checksum":"1f3108bb95c89e03d418ac95b2fd6182c0b5d112bbe757cf6e23e3282a3f710e"},
{"name":"ice_cube","version":"0.16.4","platform":"ruby","checksum":"da117e5de24bdc33931be629f9b55048641924442c7e9b72fedc05e5592531b7"},
{"name":"ice_nine","version":"0.11.2","platform":"ruby","checksum":"5d506a7d2723d5592dc121b9928e4931742730131f22a1a37649df1c1e2e63db"},
{"name":"imagen","version":"0.1.8","platform":"ruby","checksum":"fde7b727d4fe79c6bb5ac46c1f7184bf87a6d54df54d712ad2be039d2f93a162"},

View File

@ -955,7 +955,7 @@ GEM
i18n (1.14.4)
concurrent-ruby (~> 1.0)
i18n_data (0.13.1)
icalendar (2.8.0)
icalendar (2.10.1)
ice_cube (~> 0.16)
ice_cube (0.16.4)
ice_nine (0.11.2)
@ -2062,7 +2062,7 @@ DEPENDENCIES
html-pipeline (~> 2.14.3)
html2text
httparty (~> 0.21.0)
icalendar
icalendar (~> 2.10.1)
influxdb-client (~> 3.1)
invisible_captcha (~> 2.1.0)
ipaddr (~> 1.2.5)

View File

@ -90,10 +90,14 @@ module Resolvers
required: false,
description: 'Merge requests updated before the timestamp.'
argument :label_name, [GraphQL::Types::String, { null: true }],
required: false,
description: 'Labels applied to the merge request.'
argument :labels, [GraphQL::Types::String],
required: false,
as: :label_name,
description: 'Array of label names. All resolved merge requests will have all of these labels.'
description: 'Array of label names. All resolved merge requests will have all of these labels.',
deprecated: { reason: 'Use `labelName`', milestone: '17.1' }
argument :merged_after, Types::TimeType,
required: false,
description: 'Merge requests merged after the date.'

View File

@ -24,6 +24,10 @@ module Users
validates :zuora_payment_method_xid, length: { maximum: 50 }, uniqueness: true, allow_nil: true
validates :stripe_setup_intent_xid, length: { maximum: 255 }, allow_nil: true
validates :stripe_payment_method_xid, length: { maximum: 255 }, allow_nil: true
validates :stripe_card_fingerprint, length: { maximum: 255 }, allow_nil: true
validates :last_digits_hash, length: { maximum: 44 }
validates :holder_name_hash, length: { maximum: 44 }
validates :expiration_date_hash, length: { maximum: 44 }

View File

@ -17,7 +17,10 @@ module Users
holder_name: holder_name,
network: network,
expiration_date: expiration_date,
zuora_payment_method_xid: zuora_payment_method_xid
zuora_payment_method_xid: zuora_payment_method_xid,
stripe_setup_intent_xid: stripe_setup_intent_xid,
stripe_payment_method_xid: stripe_payment_method_xid,
stripe_card_fingerprint: stripe_card_fingerprint
}
credit_card.update!(credit_card_params)
@ -56,6 +59,18 @@ module Users
params[:zuora_payment_method_xid]
end
def stripe_setup_intent_xid
params[:stripe_setup_intent_xid]
end
def stripe_payment_method_xid
params[:stripe_payment_method_xid]
end
def stripe_card_fingerprint
params[:stripe_card_fingerprint]
end
def expiration_date
year = params.fetch(:credit_card_expiration_year)
month = params.fetch(:credit_card_expiration_month)

View File

@ -0,0 +1,9 @@
---
migration_job_name: BackfillVulnerabilityFlagsProjectId
description: Backfills sharding key `vulnerability_flags.project_id` from `vulnerability_occurrences`.
feature_category: vulnerability_management
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/156323
milestone: '17.2'
queued_migration_version: 20240613154933
finalize_after: '2024-08-22'
finalized_by: # version of the migration that finalized this BBM

View File

@ -8,4 +8,5 @@ description: Relationships between runners and projects for project runners
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/commit/046b28312704f3131e72dcd2dbdacc5264d4aa62
milestone: '8.0'
gitlab_schema: gitlab_ci
sharding_key_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/459996
sharding_key:
project_id: projects

View File

@ -4,7 +4,8 @@ classes:
- Vulnerabilities::Flag
feature_categories:
- vulnerability_management
description: Stores additional information for vulnerabilities, for example if a vulnerability is identified as a false positive
description: Stores additional information for vulnerabilities, for example if a vulnerability
is identified as a false positive
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/65573
milestone: '14.1'
gitlab_schema: gitlab_main_cell
@ -19,3 +20,4 @@ desired_sharding_key:
table: vulnerability_occurrences
sharding_key: project_id
belongs_to: finding
desired_sharding_key_migration_job_name: BackfillVulnerabilityFlagsProjectId

View File

@ -0,0 +1,9 @@
# frozen_string_literal: true
class AddProjectIdToVulnerabilityFlags < Gitlab::Database::Migration[2.2]
milestone '17.2'
def change
add_column :vulnerability_flags, :project_id, :bigint
end
end

View File

@ -0,0 +1,29 @@
# frozen_string_literal: true
class AddStripeIdentifiersToCreditCardValidation < Gitlab::Database::Migration[2.2]
disable_ddl_transaction!
milestone '17.2'
def up
with_lock_retries do
add_column :user_credit_card_validations, :stripe_setup_intent_xid, :text, if_not_exists: true
add_column :user_credit_card_validations, :stripe_payment_method_xid, :text, if_not_exists: true
add_column :user_credit_card_validations, :stripe_card_fingerprint, :text, if_not_exists: true
end
# Stripe identifiers are currently only around 32 characters, but setting character limit to 255 per the API
# upgrade guidance for compatability with future Stripe-side changes.
#
# More info: https://docs.stripe.com/upgrades
add_text_limit :user_credit_card_validations, :stripe_setup_intent_xid, 255
add_text_limit :user_credit_card_validations, :stripe_payment_method_xid, 255
add_text_limit :user_credit_card_validations, :stripe_card_fingerprint, 255
end
def down
remove_column :user_credit_card_validations, :stripe_setup_intent_xid, if_exists: true
remove_column :user_credit_card_validations, :stripe_payment_method_xid, if_exists: true
remove_column :user_credit_card_validations, :stripe_card_fingerprint, if_exists: true
end
end

View File

@ -0,0 +1,19 @@
# frozen_string_literal: true
class AddIndexForStripeCardFingerprintToCreditCardValidation < Gitlab::Database::Migration[2.2]
disable_ddl_transaction!
milestone '17.2'
INDEX_NAME = 'index_user_credit_card_validations_on_stripe_card_fingerprint'
def up
add_concurrent_index :user_credit_card_validations,
:stripe_card_fingerprint,
name: INDEX_NAME
end
def down
remove_concurrent_index :user_credit_card_validations, :stripe_card_fingerprint, name: INDEX_NAME
end
end

View File

@ -0,0 +1,17 @@
# frozen_string_literal: true
class AddNotNullConstraintToRunnerProjectProjectId < Gitlab::Database::Migration[2.2]
milestone '17.2'
disable_ddl_transaction!
def up
# This will add the `NOT NULL` constraint and validate it
add_not_null_constraint :ci_runner_projects, :project_id
end
def down
# Down is required as `add_not_null_constraint` is not reversible
remove_not_null_constraint :ci_runner_projects, :project_id
end
end

View File

@ -0,0 +1,16 @@
# frozen_string_literal: true
class IndexVulnerabilityFlagsOnProjectId < Gitlab::Database::Migration[2.2]
milestone '17.2'
disable_ddl_transaction!
INDEX_NAME = 'index_vulnerability_flags_on_project_id'
def up
add_concurrent_index :vulnerability_flags, :project_id, name: INDEX_NAME
end
def down
remove_concurrent_index_by_name :vulnerability_flags, INDEX_NAME
end
end

View File

@ -0,0 +1,16 @@
# frozen_string_literal: true
class AddVulnerabilityFlagsProjectIdFk < Gitlab::Database::Migration[2.2]
milestone '17.2'
disable_ddl_transaction!
def up
add_concurrent_foreign_key :vulnerability_flags, :projects, column: :project_id, on_delete: :cascade
end
def down
with_lock_retries do
remove_foreign_key :vulnerability_flags, column: :project_id
end
end
end

View File

@ -0,0 +1,25 @@
# frozen_string_literal: true
class AddVulnerabilityFlagsProjectIdTrigger < Gitlab::Database::Migration[2.2]
milestone '17.2'
def up
install_sharding_key_assignment_trigger(
table: :vulnerability_flags,
sharding_key: :project_id,
parent_table: :vulnerability_occurrences,
parent_sharding_key: :project_id,
foreign_key: :vulnerability_occurrence_id
)
end
def down
remove_sharding_key_assignment_trigger(
table: :vulnerability_flags,
sharding_key: :project_id,
parent_table: :vulnerability_occurrences,
parent_sharding_key: :project_id,
foreign_key: :vulnerability_occurrence_id
)
end
end

View File

@ -0,0 +1,40 @@
# frozen_string_literal: true
class QueueBackfillVulnerabilityFlagsProjectId < Gitlab::Database::Migration[2.2]
milestone '17.2'
restrict_gitlab_migration gitlab_schema: :gitlab_main_cell
MIGRATION = "BackfillVulnerabilityFlagsProjectId"
DELAY_INTERVAL = 2.minutes
BATCH_SIZE = 1000
SUB_BATCH_SIZE = 100
def up
queue_batched_background_migration(
MIGRATION,
:vulnerability_flags,
:id,
:project_id,
:vulnerability_occurrences,
:project_id,
:vulnerability_occurrence_id,
job_interval: DELAY_INTERVAL,
batch_size: BATCH_SIZE,
sub_batch_size: SUB_BATCH_SIZE
)
end
def down
delete_batched_background_migration(
MIGRATION,
:vulnerability_flags,
:id,
[
:project_id,
:vulnerability_occurrences,
:project_id,
:vulnerability_occurrence_id
]
)
end
end

View File

@ -0,0 +1 @@
361cff5b8f21843d56d59de4af3f3854fd75fb2c43bcea4f0b9cb62cac3e80ac

View File

@ -0,0 +1 @@
a35fea9269a434e53ecd96f88e55532297e26dde432a48bbbfa7e47c166cd635

View File

@ -0,0 +1 @@
0325637342ca20cfadcf95be421b38672a5ba42c765d3abea8409bb299d83f38

View File

@ -0,0 +1 @@
aeb4a949fd02dae9965ee17fbd86c363ac8cf2de6aba1ef120e60340ee0fd2eb

View File

@ -0,0 +1 @@
f214e74808ffd5ae207dc91bc75574796043b6d365fb6b0c6c893316ae0454c9

View File

@ -0,0 +1 @@
ee02fe65bcde3710f317b9921fe0371591d1278144aafa47350c720edc31364e

View File

@ -0,0 +1 @@
e156b2eab4ba787def1619ed81263615b11353544980cb6d05850f1773279041

View File

@ -0,0 +1 @@
4b9ccafeaf4e81b843b357581f466f15a268bc520a013ff06778ef1dc5f6faf6

View File

@ -1505,6 +1505,22 @@ RETURN NEW;
END
$$;
CREATE FUNCTION trigger_dc13168b8025() RETURNS trigger
LANGUAGE plpgsql
AS $$
BEGIN
IF NEW."project_id" IS NULL THEN
SELECT "project_id"
INTO NEW."project_id"
FROM "vulnerability_occurrences"
WHERE "vulnerability_occurrences"."id" = NEW."vulnerability_occurrence_id";
END IF;
RETURN NEW;
END
$$;
CREATE FUNCTION trigger_ebab34f83f1d() RETURNS trigger
LANGUAGE plpgsql
AS $$
@ -7855,7 +7871,8 @@ CREATE TABLE ci_runner_projects (
runner_id integer NOT NULL,
created_at timestamp without time zone,
updated_at timestamp without time zone,
project_id integer
project_id integer,
CONSTRAINT check_db297016c6 CHECK ((project_id IS NOT NULL))
);
CREATE SEQUENCE ci_runner_projects_id_seq
@ -18024,6 +18041,12 @@ CREATE TABLE user_credit_card_validations (
expiration_date_hash text,
network_hash text,
zuora_payment_method_xid text,
stripe_setup_intent_xid text,
stripe_payment_method_xid text,
stripe_card_fingerprint text,
CONSTRAINT check_126615a57d CHECK ((char_length(stripe_payment_method_xid) <= 255)),
CONSTRAINT check_209503e313 CHECK ((char_length(stripe_card_fingerprint) <= 255)),
CONSTRAINT check_5d9e69ede5 CHECK ((char_length(stripe_setup_intent_xid) <= 255)),
CONSTRAINT check_7721e1961a CHECK ((char_length(network_hash) <= 44)),
CONSTRAINT check_83f1e2ace3 CHECK ((char_length(expiration_date_hash) <= 44)),
CONSTRAINT check_9a15d14e37 CHECK ((char_length(zuora_payment_method_xid) <= 50)),
@ -18629,6 +18652,7 @@ CREATE TABLE vulnerability_flags (
flag_type smallint DEFAULT 0 NOT NULL,
origin text NOT NULL,
description text NOT NULL,
project_id bigint,
CONSTRAINT check_45e743349f CHECK ((char_length(description) <= 1024)),
CONSTRAINT check_49c1d00032 CHECK ((char_length(origin) <= 255))
);
@ -28772,6 +28796,8 @@ CREATE UNIQUE INDEX index_user_canonical_emails_on_user_id ON user_canonical_ema
CREATE UNIQUE INDEX index_user_canonical_emails_on_user_id_and_canonical_email ON user_canonical_emails USING btree (user_id, canonical_email);
CREATE INDEX index_user_credit_card_validations_on_stripe_card_fingerprint ON user_credit_card_validations USING btree (stripe_card_fingerprint);
CREATE INDEX index_user_custom_attributes_on_key_and_value ON user_custom_attributes USING btree (key, value);
CREATE UNIQUE INDEX index_user_custom_attributes_on_user_id_and_key ON user_custom_attributes USING btree (user_id, key);
@ -28962,6 +28988,8 @@ CREATE INDEX index_vulnerability_findings_remediations_on_remediation_id ON vuln
CREATE UNIQUE INDEX index_vulnerability_findings_remediations_on_unique_keys ON vulnerability_findings_remediations USING btree (vulnerability_occurrence_id, vulnerability_remediation_id);
CREATE INDEX index_vulnerability_flags_on_project_id ON vulnerability_flags USING btree (project_id);
CREATE UNIQUE INDEX index_vulnerability_flags_on_unique_columns ON vulnerability_flags USING btree (vulnerability_occurrence_id, flag_type, origin);
CREATE INDEX index_vulnerability_flags_on_vulnerability_occurrence_id ON vulnerability_flags USING btree (vulnerability_occurrence_id);
@ -31108,6 +31136,8 @@ CREATE TRIGGER trigger_dadd660afe2c BEFORE INSERT OR UPDATE ON packages_debian_g
CREATE TRIGGER trigger_dbdd61a66a91 BEFORE INSERT OR UPDATE ON agent_activity_events FOR EACH ROW EXECUTE FUNCTION trigger_dbdd61a66a91();
CREATE TRIGGER trigger_dc13168b8025 BEFORE INSERT OR UPDATE ON vulnerability_flags FOR EACH ROW EXECUTE FUNCTION trigger_dc13168b8025();
CREATE TRIGGER trigger_delete_project_namespace_on_project_delete AFTER DELETE ON projects FOR EACH ROW WHEN ((old.project_namespace_id IS NOT NULL)) EXECUTE FUNCTION delete_associated_project_namespace();
CREATE TRIGGER trigger_ebab34f83f1d BEFORE INSERT OR UPDATE ON packages_debian_publications FOR EACH ROW EXECUTE FUNCTION trigger_ebab34f83f1d();
@ -32221,6 +32251,9 @@ ALTER TABLE ONLY external_status_checks_protected_branches
ALTER TABLE ONLY dast_profiles_pipelines
ADD CONSTRAINT fk_cc206a8c13 FOREIGN KEY (dast_profile_id) REFERENCES dast_profiles(id) ON DELETE CASCADE;
ALTER TABLE ONLY vulnerability_flags
ADD CONSTRAINT fk_cc3b7b4548 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
ALTER TABLE ONLY todos
ADD CONSTRAINT fk_ccf0373936 FOREIGN KEY (author_id) REFERENCES users(id) ON DELETE CASCADE;

View File

@ -206,7 +206,7 @@ This list of limitations only reflects the latest version of GitLab. If you are
GitLab instances based on our [Reference Architectures](../reference_architectures/index.md), including automation of common daily tasks.
[Epic 1465](https://gitlab.com/groups/gitlab-org/-/epics/1465) proposes to improve Geo installation even more.
- Real-time updates of issues/merge requests (for example, via long polling) doesn't work on the **secondary** site.
- [Selective synchronization](replication/configuration.md#selective-synchronization) only limits what repositories and files are replicated. The entire PostgreSQL data is still replicated. Selective synchronization is not built to accommodate compliance / export control use cases.
- [Selective synchronization](replication/selective_synchronization.md) only limits what repositories and files are replicated. The entire PostgreSQL data is still replicated. Selective synchronization is not built to accommodate compliance / export control use cases.
- [Pages access control](../../user/project/pages/pages_access_control.md) doesn't work on secondaries. See [GitLab issue #9336](https://gitlab.com/gitlab-org/gitlab/-/issues/9336) for details.
- [Disaster recovery](disaster_recovery/index.md) for deployments that have multiple secondary sites causes downtime due to the need to perform complete re-synchronization and re-configuration of all non-promoted secondaries to follow the new primary site.
- For Git over SSH, to make the project clone URL display correctly regardless of which site you are browsing, secondary sites must use the same port as the primary. [GitLab issue #339262](https://gitlab.com/gitlab-org/gitlab/-/issues/339262) proposes to remove this limitation.

View File

@ -4,36 +4,38 @@ group: Geo
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://handbook.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Geo configuration
# Configure a new **secondary** site
DETAILS:
**Tier:** Premium, Ultimate
**Offering:** Self-managed
## Configuring a new **secondary** site
NOTE:
This is the final step in setting up a **secondary** Geo site. Stages of the
setup process must be completed in the documented order.
If not, [complete all prior stages](../setup/index.md#using-linux-package-installations) before proceeding.
Make sure you [set up the database replication](../setup/database.md), and [configured fast lookup of authorized SSH keys](../../operations/fast_ssh_key_lookup.md) in **both primary and secondary sites**.
The basic steps of configuring a **secondary** site are to:
- Replicate required configurations between the **primary** site and the **secondary** sites.
- Configure a tracking database on each **secondary** site.
- Start GitLab on each **secondary** site.
1. Replicate required configurations between the **primary** and the **secondary** site.
1. Configure a tracking database on each **secondary** site.
1. Start GitLab on each **secondary** site.
You are encouraged to first read through all the steps before executing them
in your testing/production environment.
This document focuses on the first item. You are encouraged to first read
through all the steps before executing them in your testing/production
environment.
Prerequisites for **both primary and secondary sites**:
- [Set up the database replication](../setup/database.md)
- [Configure fast lookup of authorized SSH keys](../../operations/fast_ssh_key_lookup.md)
NOTE:
**Do not** set up any custom authentication for the **secondary** sites. This is handled by the **primary** site.
**Do not** set up any custom authentication for the **secondary** site. This is handled by the **primary** site.
Any change that requires access to the **Admin Area** needs to be done in the
**primary** site because the **secondary** site is a read-only replica.
### Step 1. Manually replicate secret GitLab values
## Step 1. Manually replicate secret GitLab values
GitLab stores a number of secret values in the `/etc/gitlab/gitlab-secrets.json`
file which *must* be the same on all of a site's nodes. Until there is
@ -84,7 +86,7 @@ they must be manually replicated to **all nodes of the secondary site**.
gitlab-ctl restart
```
### Step 2. Manually replicate the **primary** site's SSH host keys
## Step 2. Manually replicate the **primary** site's SSH host keys
GitLab integrates with the system-installed SSH daemon, designating a user
(typically named `git`) through which all access requests are handled.
@ -195,7 +197,7 @@ In the following steps, replace `<ssh_host_key_path>` with the one you're using:
SSH into your GitLab **secondary** server in a new terminal. If you are unable to connect,
verify the permissions are correct according to the previous steps.
### Step 3. Add the **secondary** site
## Step 3. Add the **secondary** site
1. SSH into **each Rails and Sidekiq node on your secondary** site and login as root:
@ -233,7 +235,7 @@ In the following steps, replace `<ssh_host_key_path>` with the one you're using:
1. Optional. In **Internal URL (optional)**, enter an internal URL for the secondary site.
1. Optional. Select which groups or storage shards should be replicated by the
**secondary** site. Leave blank to replicate all. For more information, see
[selective synchronization](#selective-synchronization).
[selective synchronization](selective_synchronization.md).
1. Select **Save changes** to add the **secondary** site.
1. SSH into **each Rails, and Sidekiq node on your secondary** site and restart the services:
@ -267,14 +269,14 @@ that the **secondary** site can act on those notifications immediately.
Be sure the _secondary_ site is running and accessible. You can sign in to the
_secondary_ site with the same credentials as were used with the _primary_ site.
### Step 4. (Optional) Using custom certificates
## Step 4. (Optional) Using custom certificates
You can safely skip this step if:
- Your **primary** site uses a public CA-issued HTTPS certificate.
- Your **primary** site only connects to external services with CA-issued (not self-signed) HTTPS certificates.
#### Custom or self-signed certificate for inbound connections
### Custom or self-signed certificate for inbound connections
If your GitLab Geo **primary** site uses a custom or [self-signed certificate to secure inbound HTTPS connections](https://docs.gitlab.com/omnibus/settings/ssl/index.html#install-custom-public-certificates), this can be either a single-domain or multi-domain certificate.
@ -283,7 +285,7 @@ Install the correct certificate based on your certificate type:
- **Multi-domain certificate** that includes both primary and secondary site domains: Install the certificate at `/etc/gitlab/ssl` on all **Rails, Sidekiq, and Gitaly** nodes in the **secondary** site.
- **Single-domain certificate** where the certificates are specific to each Geo site domain: Generate a valid certificate for your **secondary** site's domain and install it at `/etc/gitlab/ssl` following [these instructions](https://docs.gitlab.com/omnibus/settings/ssl/index.html#install-custom-public-certificates) on all **Rails, Sidekiq, and Gitaly** nodes in the **secondary** site.
#### Connecting to external services that use custom certificates
### Connecting to external services that use custom certificates
A copy of the self-signed certificate for the external service needs to be added to the trust store on all the **primary** site's nodes that require access to the service.
@ -322,7 +324,7 @@ If your **primary** site is using a [custom or self-signed certificate for inbou
sudo gitlab-ctl reconfigure
```
### Step 5. Enable Git access over HTTP/HTTPS and SSH
## Step 5. Enable Git access over HTTP/HTTPS and SSH
Geo synchronizes repositories over HTTP/HTTPS, and therefore requires this clone
method to be enabled. This is enabled by default, but if converting an existing site to Geo it should be checked:
@ -337,7 +339,7 @@ On the **primary** site:
1. Follow [Fast lookup of authorized SSH keys in the database](../../operations/fast_ssh_key_lookup.md) on **all primary and secondary** sites.
1. If not using Git over SSH, then set "Enabled Git access protocols" to "Only HTTP(S)".
### Step 6. Verify proper functioning of the **secondary** site
## Step 6. Verify proper functioning of the **secondary** site
You can sign in to the **secondary** site with the same credentials you used with
the **primary** site. After you sign in:
@ -379,43 +381,6 @@ Currently, this is what is synced:
- Issues, merge requests, snippets, and comment attachments.
- Users, groups, and project avatars.
## Selective synchronization
Geo supports selective synchronization, which allows administrators to choose
which projects should be synchronized by **secondary** sites.
A subset of projects can be chosen, either by group or by storage shard. The
former is ideal for replicating data belonging to a subset of users, while the
latter is more suited to progressively rolling out Geo to a large GitLab
instance.
NOTE:
Geo's synchronization logic is outlined in the [documentation](../index.md). Both the solution and the documentation is subject to change from time to time. You must independently determine your legal obligations in regard to privacy and cybersecurity laws, and applicable trade control law on an ongoing basis.
Selective synchronization:
1. Does not restrict permissions from **secondary** sites.
1. Does not hide project metadata from **secondary** sites.
- Since Geo currently relies on PostgreSQL replication, all project metadata
gets replicated to **secondary** sites, but repositories that have not been
selected are empty.
1. Does not reduce the number of events generated for the Geo event log.
- The **primary** site generates events as long as any **secondary** sites are present.
Selective synchronization restrictions are implemented on the **secondary** sites,
not the **primary** site.
### Git operations on unreplicated repositories
Git clone, pull, and push operations over HTTP(S) and SSH are supported for repositories that
exist on the **primary** site but not on **secondary** sites. This situation can occur
when:
- Selective synchronization does not include the project attached to the repository.
- The repository is actively being replicated but has not completed yet.
## Upgrading Geo
See the [upgrading the Geo sites document](upgrading_the_geo_sites.md).
## Troubleshooting
See the [troubleshooting document](troubleshooting.md).

View File

@ -83,11 +83,11 @@ No, Geo sites can be based on different reference architectures. For example, yo
## Does Geo replicate archived projects?
Yes, provided they are not excluded through [selective sync](../replication/configuration.md#selective-synchronization).
Yes, provided they are not excluded through [selective sync](../replication/selective_synchronization.md).
## Does Geo replicate personal projects?
Yes, provided they are not excluded through [selective sync](../replication/configuration.md#selective-synchronization).
Yes, provided they are not excluded through [selective sync](../replication/selective_synchronization.md).
## Are delayed deletion projects replicated to secondary sites?

View File

@ -0,0 +1,42 @@
---
stage: Systems
group: Geo
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://handbook.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Selective synchronization
DETAILS:
**Tier:** Premium, Ultimate
**Offering:** Self-managed
Geo supports selective synchronization, which allows administrators to choose
which projects should be synchronized by **secondary** sites.
A subset of projects can be chosen, either by group or by storage shard. The
former is ideal for replicating data belonging to a subset of users, while the
latter is more suited to progressively rolling out Geo to a large GitLab
instance.
NOTE:
Geo's synchronization logic is outlined in the [documentation](../index.md). Both the solution and the documentation is subject to change from time to time. You must independently determine your legal obligations in regard to privacy and cybersecurity laws, and applicable trade control law on an ongoing basis.
Selective synchronization:
1. Does not restrict permissions from **secondary** sites.
1. Does not hide project metadata from **secondary** sites.
- Since Geo relies on PostgreSQL replication, all project metadata
gets replicated to **secondary** sites, but repositories that have not been
selected are empty.
1. Does not reduce the number of events generated for the Geo event log.
- The **primary** site generates events as long as any **secondary** sites are present.
Selective synchronization restrictions are implemented on the **secondary** sites,
not the **primary** site.
## Git operations on unreplicated repositories
Git clone, pull, and push operations over HTTP(S) and SSH are supported for repositories that
exist on the **primary** site but not on **secondary** sites. This situation can occur
when:
- Selective synchronization does not include the project attached to the repository.
- The repository is actively being replicated but has not completed yet.

View File

@ -323,7 +323,7 @@ secondary site is a read-only copy.
match exactly.
1. Optional. In **Internal URL (optional)**, enter an internal URL for the primary site.
1. Optional. Select which groups or storage shards should be replicated by the
secondary site. To replicate all, leave the field blank. See [selective synchronization](../replication/configuration.md#selective-synchronization).
secondary site. To replicate all, leave the field blank. See [selective synchronization](../replication/selective_synchronization.md).
1. Select **Save changes**.
1. SSH into each Rails and Sidekiq node on your secondary site and restart the services:

View File

@ -574,7 +574,7 @@ You must manually replicate the secret file across all of your secondary sites,
match exactly.
1. Optional. In **Internal URL (optional)**, enter an internal URL for the primary site.
1. Optional. Select which groups or storage shards should be replicated by the
secondary site. To replicate all, leave the field blank. See [selective synchronization](../replication/configuration.md#selective-synchronization).
secondary site. To replicate all, leave the field blank. See [selective synchronization](../replication/selective_synchronization.md).
1. Select **Save changes**.
1. SSH into each Rails and Sidekiq node on your secondary site and restart the services:

View File

@ -37,7 +37,7 @@ the **primary** node is listed first as `Primary site`.
| Setting | Description |
|---------------------------|-------------|
| Selective synchronization | Enable Geo [selective sync](../administration/geo/replication/configuration.md#selective-synchronization) for this **secondary** site. |
| Selective synchronization | Enable Geo [selective sync](../administration/geo/replication/selective_synchronization.md) for this **secondary** site. |
| Repository sync capacity | Number of concurrent requests this **secondary** site makes to the **primary** site when backfilling repositories. |
| File sync capacity | Number of concurrent requests this **secondary** site makes to the **primary** site when backfilling files. |

View File

@ -16035,7 +16035,8 @@ four standard [pagination arguments](#pagination-arguments):
| <a id="addonuserassignedmergerequestsdraft"></a>`draft` | [`Boolean`](#boolean) | Limit result to draft merge requests. |
| <a id="addonuserassignedmergerequestsgroupid"></a>`groupId` | [`GroupID`](#groupid) | The global ID of the group the authored merge requests should be in. Merge requests in subgroups are included. |
| <a id="addonuserassignedmergerequestsiids"></a>`iids` | [`[String!]`](#string) | Array of IIDs of merge requests, for example `[1, 2]`. |
| <a id="addonuserassignedmergerequestslabels"></a>`labels` | [`[String!]`](#string) | Array of label names. All resolved merge requests will have all of these labels. |
| <a id="addonuserassignedmergerequestslabelname"></a>`labelName` | [`[String]`](#string) | Labels applied to the merge request. |
| <a id="addonuserassignedmergerequestslabels"></a>`labels` **{warning-solid}** | [`[String!]`](#string) | **Deprecated** in GitLab 17.1. Use `labelName`. |
| <a id="addonuserassignedmergerequestsmergedafter"></a>`mergedAfter` | [`Time`](#time) | Merge requests merged after the date. |
| <a id="addonuserassignedmergerequestsmergedbefore"></a>`mergedBefore` | [`Time`](#time) | Merge requests merged before the date. |
| <a id="addonuserassignedmergerequestsmilestonetitle"></a>`milestoneTitle` | [`String`](#string) | Title of the milestone. Incompatible with milestoneWildcardId. |
@ -16079,7 +16080,8 @@ four standard [pagination arguments](#pagination-arguments):
| <a id="addonuserauthoredmergerequestsdraft"></a>`draft` | [`Boolean`](#boolean) | Limit result to draft merge requests. |
| <a id="addonuserauthoredmergerequestsgroupid"></a>`groupId` | [`GroupID`](#groupid) | The global ID of the group the authored merge requests should be in. Merge requests in subgroups are included. |
| <a id="addonuserauthoredmergerequestsiids"></a>`iids` | [`[String!]`](#string) | Array of IIDs of merge requests, for example `[1, 2]`. |
| <a id="addonuserauthoredmergerequestslabels"></a>`labels` | [`[String!]`](#string) | Array of label names. All resolved merge requests will have all of these labels. |
| <a id="addonuserauthoredmergerequestslabelname"></a>`labelName` | [`[String]`](#string) | Labels applied to the merge request. |
| <a id="addonuserauthoredmergerequestslabels"></a>`labels` **{warning-solid}** | [`[String!]`](#string) | **Deprecated** in GitLab 17.1. Use `labelName`. |
| <a id="addonuserauthoredmergerequestsmergedafter"></a>`mergedAfter` | [`Time`](#time) | Merge requests merged after the date. |
| <a id="addonuserauthoredmergerequestsmergedbefore"></a>`mergedBefore` | [`Time`](#time) | Merge requests merged before the date. |
| <a id="addonuserauthoredmergerequestsmilestonetitle"></a>`milestoneTitle` | [`String`](#string) | Title of the milestone. Incompatible with milestoneWildcardId. |
@ -16177,7 +16179,8 @@ four standard [pagination arguments](#pagination-arguments):
| <a id="addonuserreviewrequestedmergerequestsdraft"></a>`draft` | [`Boolean`](#boolean) | Limit result to draft merge requests. |
| <a id="addonuserreviewrequestedmergerequestsgroupid"></a>`groupId` | [`GroupID`](#groupid) | The global ID of the group the authored merge requests should be in. Merge requests in subgroups are included. |
| <a id="addonuserreviewrequestedmergerequestsiids"></a>`iids` | [`[String!]`](#string) | Array of IIDs of merge requests, for example `[1, 2]`. |
| <a id="addonuserreviewrequestedmergerequestslabels"></a>`labels` | [`[String!]`](#string) | Array of label names. All resolved merge requests will have all of these labels. |
| <a id="addonuserreviewrequestedmergerequestslabelname"></a>`labelName` | [`[String]`](#string) | Labels applied to the merge request. |
| <a id="addonuserreviewrequestedmergerequestslabels"></a>`labels` **{warning-solid}** | [`[String!]`](#string) | **Deprecated** in GitLab 17.1. Use `labelName`. |
| <a id="addonuserreviewrequestedmergerequestsmergedafter"></a>`mergedAfter` | [`Time`](#time) | Merge requests merged after the date. |
| <a id="addonuserreviewrequestedmergerequestsmergedbefore"></a>`mergedBefore` | [`Time`](#time) | Merge requests merged before the date. |
| <a id="addonuserreviewrequestedmergerequestsmilestonetitle"></a>`milestoneTitle` | [`String`](#string) | Title of the milestone. Incompatible with milestoneWildcardId. |
@ -16845,7 +16848,8 @@ four standard [pagination arguments](#pagination-arguments):
| <a id="autocompleteduserassignedmergerequestsdraft"></a>`draft` | [`Boolean`](#boolean) | Limit result to draft merge requests. |
| <a id="autocompleteduserassignedmergerequestsgroupid"></a>`groupId` | [`GroupID`](#groupid) | The global ID of the group the authored merge requests should be in. Merge requests in subgroups are included. |
| <a id="autocompleteduserassignedmergerequestsiids"></a>`iids` | [`[String!]`](#string) | Array of IIDs of merge requests, for example `[1, 2]`. |
| <a id="autocompleteduserassignedmergerequestslabels"></a>`labels` | [`[String!]`](#string) | Array of label names. All resolved merge requests will have all of these labels. |
| <a id="autocompleteduserassignedmergerequestslabelname"></a>`labelName` | [`[String]`](#string) | Labels applied to the merge request. |
| <a id="autocompleteduserassignedmergerequestslabels"></a>`labels` **{warning-solid}** | [`[String!]`](#string) | **Deprecated** in GitLab 17.1. Use `labelName`. |
| <a id="autocompleteduserassignedmergerequestsmergedafter"></a>`mergedAfter` | [`Time`](#time) | Merge requests merged after the date. |
| <a id="autocompleteduserassignedmergerequestsmergedbefore"></a>`mergedBefore` | [`Time`](#time) | Merge requests merged before the date. |
| <a id="autocompleteduserassignedmergerequestsmilestonetitle"></a>`milestoneTitle` | [`String`](#string) | Title of the milestone. Incompatible with milestoneWildcardId. |
@ -16889,7 +16893,8 @@ four standard [pagination arguments](#pagination-arguments):
| <a id="autocompleteduserauthoredmergerequestsdraft"></a>`draft` | [`Boolean`](#boolean) | Limit result to draft merge requests. |
| <a id="autocompleteduserauthoredmergerequestsgroupid"></a>`groupId` | [`GroupID`](#groupid) | The global ID of the group the authored merge requests should be in. Merge requests in subgroups are included. |
| <a id="autocompleteduserauthoredmergerequestsiids"></a>`iids` | [`[String!]`](#string) | Array of IIDs of merge requests, for example `[1, 2]`. |
| <a id="autocompleteduserauthoredmergerequestslabels"></a>`labels` | [`[String!]`](#string) | Array of label names. All resolved merge requests will have all of these labels. |
| <a id="autocompleteduserauthoredmergerequestslabelname"></a>`labelName` | [`[String]`](#string) | Labels applied to the merge request. |
| <a id="autocompleteduserauthoredmergerequestslabels"></a>`labels` **{warning-solid}** | [`[String!]`](#string) | **Deprecated** in GitLab 17.1. Use `labelName`. |
| <a id="autocompleteduserauthoredmergerequestsmergedafter"></a>`mergedAfter` | [`Time`](#time) | Merge requests merged after the date. |
| <a id="autocompleteduserauthoredmergerequestsmergedbefore"></a>`mergedBefore` | [`Time`](#time) | Merge requests merged before the date. |
| <a id="autocompleteduserauthoredmergerequestsmilestonetitle"></a>`milestoneTitle` | [`String`](#string) | Title of the milestone. Incompatible with milestoneWildcardId. |
@ -16999,7 +17004,8 @@ four standard [pagination arguments](#pagination-arguments):
| <a id="autocompleteduserreviewrequestedmergerequestsdraft"></a>`draft` | [`Boolean`](#boolean) | Limit result to draft merge requests. |
| <a id="autocompleteduserreviewrequestedmergerequestsgroupid"></a>`groupId` | [`GroupID`](#groupid) | The global ID of the group the authored merge requests should be in. Merge requests in subgroups are included. |
| <a id="autocompleteduserreviewrequestedmergerequestsiids"></a>`iids` | [`[String!]`](#string) | Array of IIDs of merge requests, for example `[1, 2]`. |
| <a id="autocompleteduserreviewrequestedmergerequestslabels"></a>`labels` | [`[String!]`](#string) | Array of label names. All resolved merge requests will have all of these labels. |
| <a id="autocompleteduserreviewrequestedmergerequestslabelname"></a>`labelName` | [`[String]`](#string) | Labels applied to the merge request. |
| <a id="autocompleteduserreviewrequestedmergerequestslabels"></a>`labels` **{warning-solid}** | [`[String!]`](#string) | **Deprecated** in GitLab 17.1. Use `labelName`. |
| <a id="autocompleteduserreviewrequestedmergerequestsmergedafter"></a>`mergedAfter` | [`Time`](#time) | Merge requests merged after the date. |
| <a id="autocompleteduserreviewrequestedmergerequestsmergedbefore"></a>`mergedBefore` | [`Time`](#time) | Merge requests merged before the date. |
| <a id="autocompleteduserreviewrequestedmergerequestsmilestonetitle"></a>`milestoneTitle` | [`String`](#string) | Title of the milestone. Incompatible with milestoneWildcardId. |
@ -19043,7 +19049,8 @@ four standard [pagination arguments](#pagination-arguments):
| <a id="currentuserassignedmergerequestsdraft"></a>`draft` | [`Boolean`](#boolean) | Limit result to draft merge requests. |
| <a id="currentuserassignedmergerequestsgroupid"></a>`groupId` | [`GroupID`](#groupid) | The global ID of the group the authored merge requests should be in. Merge requests in subgroups are included. |
| <a id="currentuserassignedmergerequestsiids"></a>`iids` | [`[String!]`](#string) | Array of IIDs of merge requests, for example `[1, 2]`. |
| <a id="currentuserassignedmergerequestslabels"></a>`labels` | [`[String!]`](#string) | Array of label names. All resolved merge requests will have all of these labels. |
| <a id="currentuserassignedmergerequestslabelname"></a>`labelName` | [`[String]`](#string) | Labels applied to the merge request. |
| <a id="currentuserassignedmergerequestslabels"></a>`labels` **{warning-solid}** | [`[String!]`](#string) | **Deprecated** in GitLab 17.1. Use `labelName`. |
| <a id="currentuserassignedmergerequestsmergedafter"></a>`mergedAfter` | [`Time`](#time) | Merge requests merged after the date. |
| <a id="currentuserassignedmergerequestsmergedbefore"></a>`mergedBefore` | [`Time`](#time) | Merge requests merged before the date. |
| <a id="currentuserassignedmergerequestsmilestonetitle"></a>`milestoneTitle` | [`String`](#string) | Title of the milestone. Incompatible with milestoneWildcardId. |
@ -19087,7 +19094,8 @@ four standard [pagination arguments](#pagination-arguments):
| <a id="currentuserauthoredmergerequestsdraft"></a>`draft` | [`Boolean`](#boolean) | Limit result to draft merge requests. |
| <a id="currentuserauthoredmergerequestsgroupid"></a>`groupId` | [`GroupID`](#groupid) | The global ID of the group the authored merge requests should be in. Merge requests in subgroups are included. |
| <a id="currentuserauthoredmergerequestsiids"></a>`iids` | [`[String!]`](#string) | Array of IIDs of merge requests, for example `[1, 2]`. |
| <a id="currentuserauthoredmergerequestslabels"></a>`labels` | [`[String!]`](#string) | Array of label names. All resolved merge requests will have all of these labels. |
| <a id="currentuserauthoredmergerequestslabelname"></a>`labelName` | [`[String]`](#string) | Labels applied to the merge request. |
| <a id="currentuserauthoredmergerequestslabels"></a>`labels` **{warning-solid}** | [`[String!]`](#string) | **Deprecated** in GitLab 17.1. Use `labelName`. |
| <a id="currentuserauthoredmergerequestsmergedafter"></a>`mergedAfter` | [`Time`](#time) | Merge requests merged after the date. |
| <a id="currentuserauthoredmergerequestsmergedbefore"></a>`mergedBefore` | [`Time`](#time) | Merge requests merged before the date. |
| <a id="currentuserauthoredmergerequestsmilestonetitle"></a>`milestoneTitle` | [`String`](#string) | Title of the milestone. Incompatible with milestoneWildcardId. |
@ -19185,7 +19193,8 @@ four standard [pagination arguments](#pagination-arguments):
| <a id="currentuserreviewrequestedmergerequestsdraft"></a>`draft` | [`Boolean`](#boolean) | Limit result to draft merge requests. |
| <a id="currentuserreviewrequestedmergerequestsgroupid"></a>`groupId` | [`GroupID`](#groupid) | The global ID of the group the authored merge requests should be in. Merge requests in subgroups are included. |
| <a id="currentuserreviewrequestedmergerequestsiids"></a>`iids` | [`[String!]`](#string) | Array of IIDs of merge requests, for example `[1, 2]`. |
| <a id="currentuserreviewrequestedmergerequestslabels"></a>`labels` | [`[String!]`](#string) | Array of label names. All resolved merge requests will have all of these labels. |
| <a id="currentuserreviewrequestedmergerequestslabelname"></a>`labelName` | [`[String]`](#string) | Labels applied to the merge request. |
| <a id="currentuserreviewrequestedmergerequestslabels"></a>`labels` **{warning-solid}** | [`[String!]`](#string) | **Deprecated** in GitLab 17.1. Use `labelName`. |
| <a id="currentuserreviewrequestedmergerequestsmergedafter"></a>`mergedAfter` | [`Time`](#time) | Merge requests merged after the date. |
| <a id="currentuserreviewrequestedmergerequestsmergedbefore"></a>`mergedBefore` | [`Time`](#time) | Merge requests merged before the date. |
| <a id="currentuserreviewrequestedmergerequestsmilestonetitle"></a>`milestoneTitle` | [`String`](#string) | Title of the milestone. Incompatible with milestoneWildcardId. |
@ -22392,7 +22401,8 @@ four standard [pagination arguments](#pagination-arguments):
| <a id="groupmergerequestsiids"></a>`iids` | [`[String!]`](#string) | Array of IIDs of merge requests, for example `[1, 2]`. |
| <a id="groupmergerequestsincludearchived"></a>`includeArchived` | [`Boolean`](#boolean) | Return merge requests from archived projects. |
| <a id="groupmergerequestsincludesubgroups"></a>`includeSubgroups` | [`Boolean`](#boolean) | Include merge requests belonging to subgroups. |
| <a id="groupmergerequestslabels"></a>`labels` | [`[String!]`](#string) | Array of label names. All resolved merge requests will have all of these labels. |
| <a id="groupmergerequestslabelname"></a>`labelName` | [`[String]`](#string) | Labels applied to the merge request. |
| <a id="groupmergerequestslabels"></a>`labels` **{warning-solid}** | [`[String!]`](#string) | **Deprecated** in GitLab 17.1. Use `labelName`. |
| <a id="groupmergerequestsmergedafter"></a>`mergedAfter` | [`Time`](#time) | Merge requests merged after the date. |
| <a id="groupmergerequestsmergedbefore"></a>`mergedBefore` | [`Time`](#time) | Merge requests merged before the date. |
| <a id="groupmergerequestsmilestonetitle"></a>`milestoneTitle` | [`String`](#string) | Title of the milestone. Incompatible with milestoneWildcardId. |
@ -24360,7 +24370,8 @@ four standard [pagination arguments](#pagination-arguments):
| <a id="mergerequestassigneeassignedmergerequestsdraft"></a>`draft` | [`Boolean`](#boolean) | Limit result to draft merge requests. |
| <a id="mergerequestassigneeassignedmergerequestsgroupid"></a>`groupId` | [`GroupID`](#groupid) | The global ID of the group the authored merge requests should be in. Merge requests in subgroups are included. |
| <a id="mergerequestassigneeassignedmergerequestsiids"></a>`iids` | [`[String!]`](#string) | Array of IIDs of merge requests, for example `[1, 2]`. |
| <a id="mergerequestassigneeassignedmergerequestslabels"></a>`labels` | [`[String!]`](#string) | Array of label names. All resolved merge requests will have all of these labels. |
| <a id="mergerequestassigneeassignedmergerequestslabelname"></a>`labelName` | [`[String]`](#string) | Labels applied to the merge request. |
| <a id="mergerequestassigneeassignedmergerequestslabels"></a>`labels` **{warning-solid}** | [`[String!]`](#string) | **Deprecated** in GitLab 17.1. Use `labelName`. |
| <a id="mergerequestassigneeassignedmergerequestsmergedafter"></a>`mergedAfter` | [`Time`](#time) | Merge requests merged after the date. |
| <a id="mergerequestassigneeassignedmergerequestsmergedbefore"></a>`mergedBefore` | [`Time`](#time) | Merge requests merged before the date. |
| <a id="mergerequestassigneeassignedmergerequestsmilestonetitle"></a>`milestoneTitle` | [`String`](#string) | Title of the milestone. Incompatible with milestoneWildcardId. |
@ -24404,7 +24415,8 @@ four standard [pagination arguments](#pagination-arguments):
| <a id="mergerequestassigneeauthoredmergerequestsdraft"></a>`draft` | [`Boolean`](#boolean) | Limit result to draft merge requests. |
| <a id="mergerequestassigneeauthoredmergerequestsgroupid"></a>`groupId` | [`GroupID`](#groupid) | The global ID of the group the authored merge requests should be in. Merge requests in subgroups are included. |
| <a id="mergerequestassigneeauthoredmergerequestsiids"></a>`iids` | [`[String!]`](#string) | Array of IIDs of merge requests, for example `[1, 2]`. |
| <a id="mergerequestassigneeauthoredmergerequestslabels"></a>`labels` | [`[String!]`](#string) | Array of label names. All resolved merge requests will have all of these labels. |
| <a id="mergerequestassigneeauthoredmergerequestslabelname"></a>`labelName` | [`[String]`](#string) | Labels applied to the merge request. |
| <a id="mergerequestassigneeauthoredmergerequestslabels"></a>`labels` **{warning-solid}** | [`[String!]`](#string) | **Deprecated** in GitLab 17.1. Use `labelName`. |
| <a id="mergerequestassigneeauthoredmergerequestsmergedafter"></a>`mergedAfter` | [`Time`](#time) | Merge requests merged after the date. |
| <a id="mergerequestassigneeauthoredmergerequestsmergedbefore"></a>`mergedBefore` | [`Time`](#time) | Merge requests merged before the date. |
| <a id="mergerequestassigneeauthoredmergerequestsmilestonetitle"></a>`milestoneTitle` | [`String`](#string) | Title of the milestone. Incompatible with milestoneWildcardId. |
@ -24502,7 +24514,8 @@ four standard [pagination arguments](#pagination-arguments):
| <a id="mergerequestassigneereviewrequestedmergerequestsdraft"></a>`draft` | [`Boolean`](#boolean) | Limit result to draft merge requests. |
| <a id="mergerequestassigneereviewrequestedmergerequestsgroupid"></a>`groupId` | [`GroupID`](#groupid) | The global ID of the group the authored merge requests should be in. Merge requests in subgroups are included. |
| <a id="mergerequestassigneereviewrequestedmergerequestsiids"></a>`iids` | [`[String!]`](#string) | Array of IIDs of merge requests, for example `[1, 2]`. |
| <a id="mergerequestassigneereviewrequestedmergerequestslabels"></a>`labels` | [`[String!]`](#string) | Array of label names. All resolved merge requests will have all of these labels. |
| <a id="mergerequestassigneereviewrequestedmergerequestslabelname"></a>`labelName` | [`[String]`](#string) | Labels applied to the merge request. |
| <a id="mergerequestassigneereviewrequestedmergerequestslabels"></a>`labels` **{warning-solid}** | [`[String!]`](#string) | **Deprecated** in GitLab 17.1. Use `labelName`. |
| <a id="mergerequestassigneereviewrequestedmergerequestsmergedafter"></a>`mergedAfter` | [`Time`](#time) | Merge requests merged after the date. |
| <a id="mergerequestassigneereviewrequestedmergerequestsmergedbefore"></a>`mergedBefore` | [`Time`](#time) | Merge requests merged before the date. |
| <a id="mergerequestassigneereviewrequestedmergerequestsmilestonetitle"></a>`milestoneTitle` | [`String`](#string) | Title of the milestone. Incompatible with milestoneWildcardId. |
@ -24702,7 +24715,8 @@ four standard [pagination arguments](#pagination-arguments):
| <a id="mergerequestauthorassignedmergerequestsdraft"></a>`draft` | [`Boolean`](#boolean) | Limit result to draft merge requests. |
| <a id="mergerequestauthorassignedmergerequestsgroupid"></a>`groupId` | [`GroupID`](#groupid) | The global ID of the group the authored merge requests should be in. Merge requests in subgroups are included. |
| <a id="mergerequestauthorassignedmergerequestsiids"></a>`iids` | [`[String!]`](#string) | Array of IIDs of merge requests, for example `[1, 2]`. |
| <a id="mergerequestauthorassignedmergerequestslabels"></a>`labels` | [`[String!]`](#string) | Array of label names. All resolved merge requests will have all of these labels. |
| <a id="mergerequestauthorassignedmergerequestslabelname"></a>`labelName` | [`[String]`](#string) | Labels applied to the merge request. |
| <a id="mergerequestauthorassignedmergerequestslabels"></a>`labels` **{warning-solid}** | [`[String!]`](#string) | **Deprecated** in GitLab 17.1. Use `labelName`. |
| <a id="mergerequestauthorassignedmergerequestsmergedafter"></a>`mergedAfter` | [`Time`](#time) | Merge requests merged after the date. |
| <a id="mergerequestauthorassignedmergerequestsmergedbefore"></a>`mergedBefore` | [`Time`](#time) | Merge requests merged before the date. |
| <a id="mergerequestauthorassignedmergerequestsmilestonetitle"></a>`milestoneTitle` | [`String`](#string) | Title of the milestone. Incompatible with milestoneWildcardId. |
@ -24746,7 +24760,8 @@ four standard [pagination arguments](#pagination-arguments):
| <a id="mergerequestauthorauthoredmergerequestsdraft"></a>`draft` | [`Boolean`](#boolean) | Limit result to draft merge requests. |
| <a id="mergerequestauthorauthoredmergerequestsgroupid"></a>`groupId` | [`GroupID`](#groupid) | The global ID of the group the authored merge requests should be in. Merge requests in subgroups are included. |
| <a id="mergerequestauthorauthoredmergerequestsiids"></a>`iids` | [`[String!]`](#string) | Array of IIDs of merge requests, for example `[1, 2]`. |
| <a id="mergerequestauthorauthoredmergerequestslabels"></a>`labels` | [`[String!]`](#string) | Array of label names. All resolved merge requests will have all of these labels. |
| <a id="mergerequestauthorauthoredmergerequestslabelname"></a>`labelName` | [`[String]`](#string) | Labels applied to the merge request. |
| <a id="mergerequestauthorauthoredmergerequestslabels"></a>`labels` **{warning-solid}** | [`[String!]`](#string) | **Deprecated** in GitLab 17.1. Use `labelName`. |
| <a id="mergerequestauthorauthoredmergerequestsmergedafter"></a>`mergedAfter` | [`Time`](#time) | Merge requests merged after the date. |
| <a id="mergerequestauthorauthoredmergerequestsmergedbefore"></a>`mergedBefore` | [`Time`](#time) | Merge requests merged before the date. |
| <a id="mergerequestauthorauthoredmergerequestsmilestonetitle"></a>`milestoneTitle` | [`String`](#string) | Title of the milestone. Incompatible with milestoneWildcardId. |
@ -24844,7 +24859,8 @@ four standard [pagination arguments](#pagination-arguments):
| <a id="mergerequestauthorreviewrequestedmergerequestsdraft"></a>`draft` | [`Boolean`](#boolean) | Limit result to draft merge requests. |
| <a id="mergerequestauthorreviewrequestedmergerequestsgroupid"></a>`groupId` | [`GroupID`](#groupid) | The global ID of the group the authored merge requests should be in. Merge requests in subgroups are included. |
| <a id="mergerequestauthorreviewrequestedmergerequestsiids"></a>`iids` | [`[String!]`](#string) | Array of IIDs of merge requests, for example `[1, 2]`. |
| <a id="mergerequestauthorreviewrequestedmergerequestslabels"></a>`labels` | [`[String!]`](#string) | Array of label names. All resolved merge requests will have all of these labels. |
| <a id="mergerequestauthorreviewrequestedmergerequestslabelname"></a>`labelName` | [`[String]`](#string) | Labels applied to the merge request. |
| <a id="mergerequestauthorreviewrequestedmergerequestslabels"></a>`labels` **{warning-solid}** | [`[String!]`](#string) | **Deprecated** in GitLab 17.1. Use `labelName`. |
| <a id="mergerequestauthorreviewrequestedmergerequestsmergedafter"></a>`mergedAfter` | [`Time`](#time) | Merge requests merged after the date. |
| <a id="mergerequestauthorreviewrequestedmergerequestsmergedbefore"></a>`mergedBefore` | [`Time`](#time) | Merge requests merged before the date. |
| <a id="mergerequestauthorreviewrequestedmergerequestsmilestonetitle"></a>`milestoneTitle` | [`String`](#string) | Title of the milestone. Incompatible with milestoneWildcardId. |
@ -25091,7 +25107,8 @@ four standard [pagination arguments](#pagination-arguments):
| <a id="mergerequestparticipantassignedmergerequestsdraft"></a>`draft` | [`Boolean`](#boolean) | Limit result to draft merge requests. |
| <a id="mergerequestparticipantassignedmergerequestsgroupid"></a>`groupId` | [`GroupID`](#groupid) | The global ID of the group the authored merge requests should be in. Merge requests in subgroups are included. |
| <a id="mergerequestparticipantassignedmergerequestsiids"></a>`iids` | [`[String!]`](#string) | Array of IIDs of merge requests, for example `[1, 2]`. |
| <a id="mergerequestparticipantassignedmergerequestslabels"></a>`labels` | [`[String!]`](#string) | Array of label names. All resolved merge requests will have all of these labels. |
| <a id="mergerequestparticipantassignedmergerequestslabelname"></a>`labelName` | [`[String]`](#string) | Labels applied to the merge request. |
| <a id="mergerequestparticipantassignedmergerequestslabels"></a>`labels` **{warning-solid}** | [`[String!]`](#string) | **Deprecated** in GitLab 17.1. Use `labelName`. |
| <a id="mergerequestparticipantassignedmergerequestsmergedafter"></a>`mergedAfter` | [`Time`](#time) | Merge requests merged after the date. |
| <a id="mergerequestparticipantassignedmergerequestsmergedbefore"></a>`mergedBefore` | [`Time`](#time) | Merge requests merged before the date. |
| <a id="mergerequestparticipantassignedmergerequestsmilestonetitle"></a>`milestoneTitle` | [`String`](#string) | Title of the milestone. Incompatible with milestoneWildcardId. |
@ -25135,7 +25152,8 @@ four standard [pagination arguments](#pagination-arguments):
| <a id="mergerequestparticipantauthoredmergerequestsdraft"></a>`draft` | [`Boolean`](#boolean) | Limit result to draft merge requests. |
| <a id="mergerequestparticipantauthoredmergerequestsgroupid"></a>`groupId` | [`GroupID`](#groupid) | The global ID of the group the authored merge requests should be in. Merge requests in subgroups are included. |
| <a id="mergerequestparticipantauthoredmergerequestsiids"></a>`iids` | [`[String!]`](#string) | Array of IIDs of merge requests, for example `[1, 2]`. |
| <a id="mergerequestparticipantauthoredmergerequestslabels"></a>`labels` | [`[String!]`](#string) | Array of label names. All resolved merge requests will have all of these labels. |
| <a id="mergerequestparticipantauthoredmergerequestslabelname"></a>`labelName` | [`[String]`](#string) | Labels applied to the merge request. |
| <a id="mergerequestparticipantauthoredmergerequestslabels"></a>`labels` **{warning-solid}** | [`[String!]`](#string) | **Deprecated** in GitLab 17.1. Use `labelName`. |
| <a id="mergerequestparticipantauthoredmergerequestsmergedafter"></a>`mergedAfter` | [`Time`](#time) | Merge requests merged after the date. |
| <a id="mergerequestparticipantauthoredmergerequestsmergedbefore"></a>`mergedBefore` | [`Time`](#time) | Merge requests merged before the date. |
| <a id="mergerequestparticipantauthoredmergerequestsmilestonetitle"></a>`milestoneTitle` | [`String`](#string) | Title of the milestone. Incompatible with milestoneWildcardId. |
@ -25233,7 +25251,8 @@ four standard [pagination arguments](#pagination-arguments):
| <a id="mergerequestparticipantreviewrequestedmergerequestsdraft"></a>`draft` | [`Boolean`](#boolean) | Limit result to draft merge requests. |
| <a id="mergerequestparticipantreviewrequestedmergerequestsgroupid"></a>`groupId` | [`GroupID`](#groupid) | The global ID of the group the authored merge requests should be in. Merge requests in subgroups are included. |
| <a id="mergerequestparticipantreviewrequestedmergerequestsiids"></a>`iids` | [`[String!]`](#string) | Array of IIDs of merge requests, for example `[1, 2]`. |
| <a id="mergerequestparticipantreviewrequestedmergerequestslabels"></a>`labels` | [`[String!]`](#string) | Array of label names. All resolved merge requests will have all of these labels. |
| <a id="mergerequestparticipantreviewrequestedmergerequestslabelname"></a>`labelName` | [`[String]`](#string) | Labels applied to the merge request. |
| <a id="mergerequestparticipantreviewrequestedmergerequestslabels"></a>`labels` **{warning-solid}** | [`[String!]`](#string) | **Deprecated** in GitLab 17.1. Use `labelName`. |
| <a id="mergerequestparticipantreviewrequestedmergerequestsmergedafter"></a>`mergedAfter` | [`Time`](#time) | Merge requests merged after the date. |
| <a id="mergerequestparticipantreviewrequestedmergerequestsmergedbefore"></a>`mergedBefore` | [`Time`](#time) | Merge requests merged before the date. |
| <a id="mergerequestparticipantreviewrequestedmergerequestsmilestonetitle"></a>`milestoneTitle` | [`String`](#string) | Title of the milestone. Incompatible with milestoneWildcardId. |
@ -25469,7 +25488,8 @@ four standard [pagination arguments](#pagination-arguments):
| <a id="mergerequestreviewerassignedmergerequestsdraft"></a>`draft` | [`Boolean`](#boolean) | Limit result to draft merge requests. |
| <a id="mergerequestreviewerassignedmergerequestsgroupid"></a>`groupId` | [`GroupID`](#groupid) | The global ID of the group the authored merge requests should be in. Merge requests in subgroups are included. |
| <a id="mergerequestreviewerassignedmergerequestsiids"></a>`iids` | [`[String!]`](#string) | Array of IIDs of merge requests, for example `[1, 2]`. |
| <a id="mergerequestreviewerassignedmergerequestslabels"></a>`labels` | [`[String!]`](#string) | Array of label names. All resolved merge requests will have all of these labels. |
| <a id="mergerequestreviewerassignedmergerequestslabelname"></a>`labelName` | [`[String]`](#string) | Labels applied to the merge request. |
| <a id="mergerequestreviewerassignedmergerequestslabels"></a>`labels` **{warning-solid}** | [`[String!]`](#string) | **Deprecated** in GitLab 17.1. Use `labelName`. |
| <a id="mergerequestreviewerassignedmergerequestsmergedafter"></a>`mergedAfter` | [`Time`](#time) | Merge requests merged after the date. |
| <a id="mergerequestreviewerassignedmergerequestsmergedbefore"></a>`mergedBefore` | [`Time`](#time) | Merge requests merged before the date. |
| <a id="mergerequestreviewerassignedmergerequestsmilestonetitle"></a>`milestoneTitle` | [`String`](#string) | Title of the milestone. Incompatible with milestoneWildcardId. |
@ -25513,7 +25533,8 @@ four standard [pagination arguments](#pagination-arguments):
| <a id="mergerequestreviewerauthoredmergerequestsdraft"></a>`draft` | [`Boolean`](#boolean) | Limit result to draft merge requests. |
| <a id="mergerequestreviewerauthoredmergerequestsgroupid"></a>`groupId` | [`GroupID`](#groupid) | The global ID of the group the authored merge requests should be in. Merge requests in subgroups are included. |
| <a id="mergerequestreviewerauthoredmergerequestsiids"></a>`iids` | [`[String!]`](#string) | Array of IIDs of merge requests, for example `[1, 2]`. |
| <a id="mergerequestreviewerauthoredmergerequestslabels"></a>`labels` | [`[String!]`](#string) | Array of label names. All resolved merge requests will have all of these labels. |
| <a id="mergerequestreviewerauthoredmergerequestslabelname"></a>`labelName` | [`[String]`](#string) | Labels applied to the merge request. |
| <a id="mergerequestreviewerauthoredmergerequestslabels"></a>`labels` **{warning-solid}** | [`[String!]`](#string) | **Deprecated** in GitLab 17.1. Use `labelName`. |
| <a id="mergerequestreviewerauthoredmergerequestsmergedafter"></a>`mergedAfter` | [`Time`](#time) | Merge requests merged after the date. |
| <a id="mergerequestreviewerauthoredmergerequestsmergedbefore"></a>`mergedBefore` | [`Time`](#time) | Merge requests merged before the date. |
| <a id="mergerequestreviewerauthoredmergerequestsmilestonetitle"></a>`milestoneTitle` | [`String`](#string) | Title of the milestone. Incompatible with milestoneWildcardId. |
@ -25611,7 +25632,8 @@ four standard [pagination arguments](#pagination-arguments):
| <a id="mergerequestreviewerreviewrequestedmergerequestsdraft"></a>`draft` | [`Boolean`](#boolean) | Limit result to draft merge requests. |
| <a id="mergerequestreviewerreviewrequestedmergerequestsgroupid"></a>`groupId` | [`GroupID`](#groupid) | The global ID of the group the authored merge requests should be in. Merge requests in subgroups are included. |
| <a id="mergerequestreviewerreviewrequestedmergerequestsiids"></a>`iids` | [`[String!]`](#string) | Array of IIDs of merge requests, for example `[1, 2]`. |
| <a id="mergerequestreviewerreviewrequestedmergerequestslabels"></a>`labels` | [`[String!]`](#string) | Array of label names. All resolved merge requests will have all of these labels. |
| <a id="mergerequestreviewerreviewrequestedmergerequestslabelname"></a>`labelName` | [`[String]`](#string) | Labels applied to the merge request. |
| <a id="mergerequestreviewerreviewrequestedmergerequestslabels"></a>`labels` **{warning-solid}** | [`[String!]`](#string) | **Deprecated** in GitLab 17.1. Use `labelName`. |
| <a id="mergerequestreviewerreviewrequestedmergerequestsmergedafter"></a>`mergedAfter` | [`Time`](#time) | Merge requests merged after the date. |
| <a id="mergerequestreviewerreviewrequestedmergerequestsmergedbefore"></a>`mergedBefore` | [`Time`](#time) | Merge requests merged before the date. |
| <a id="mergerequestreviewerreviewrequestedmergerequestsmilestonetitle"></a>`milestoneTitle` | [`String`](#string) | Title of the milestone. Incompatible with milestoneWildcardId. |
@ -28539,7 +28561,8 @@ four standard [pagination arguments](#pagination-arguments):
| <a id="projectmergerequestsdeploymentid"></a>`deploymentId` | [`String`](#string) | ID of the deployment. |
| <a id="projectmergerequestsdraft"></a>`draft` | [`Boolean`](#boolean) | Limit result to draft merge requests. |
| <a id="projectmergerequestsiids"></a>`iids` | [`[String!]`](#string) | Array of IIDs of merge requests, for example `[1, 2]`. |
| <a id="projectmergerequestslabels"></a>`labels` | [`[String!]`](#string) | Array of label names. All resolved merge requests will have all of these labels. |
| <a id="projectmergerequestslabelname"></a>`labelName` | [`[String]`](#string) | Labels applied to the merge request. |
| <a id="projectmergerequestslabels"></a>`labels` **{warning-solid}** | [`[String!]`](#string) | **Deprecated** in GitLab 17.1. Use `labelName`. |
| <a id="projectmergerequestsmergedafter"></a>`mergedAfter` | [`Time`](#time) | Merge requests merged after the date. |
| <a id="projectmergerequestsmergedbefore"></a>`mergedBefore` | [`Time`](#time) | Merge requests merged before the date. |
| <a id="projectmergerequestsmilestonetitle"></a>`milestoneTitle` | [`String`](#string) | Title of the milestone. Incompatible with milestoneWildcardId. |
@ -31324,7 +31347,8 @@ four standard [pagination arguments](#pagination-arguments):
| <a id="usercoreassignedmergerequestsdraft"></a>`draft` | [`Boolean`](#boolean) | Limit result to draft merge requests. |
| <a id="usercoreassignedmergerequestsgroupid"></a>`groupId` | [`GroupID`](#groupid) | The global ID of the group the authored merge requests should be in. Merge requests in subgroups are included. |
| <a id="usercoreassignedmergerequestsiids"></a>`iids` | [`[String!]`](#string) | Array of IIDs of merge requests, for example `[1, 2]`. |
| <a id="usercoreassignedmergerequestslabels"></a>`labels` | [`[String!]`](#string) | Array of label names. All resolved merge requests will have all of these labels. |
| <a id="usercoreassignedmergerequestslabelname"></a>`labelName` | [`[String]`](#string) | Labels applied to the merge request. |
| <a id="usercoreassignedmergerequestslabels"></a>`labels` **{warning-solid}** | [`[String!]`](#string) | **Deprecated** in GitLab 17.1. Use `labelName`. |
| <a id="usercoreassignedmergerequestsmergedafter"></a>`mergedAfter` | [`Time`](#time) | Merge requests merged after the date. |
| <a id="usercoreassignedmergerequestsmergedbefore"></a>`mergedBefore` | [`Time`](#time) | Merge requests merged before the date. |
| <a id="usercoreassignedmergerequestsmilestonetitle"></a>`milestoneTitle` | [`String`](#string) | Title of the milestone. Incompatible with milestoneWildcardId. |
@ -31368,7 +31392,8 @@ four standard [pagination arguments](#pagination-arguments):
| <a id="usercoreauthoredmergerequestsdraft"></a>`draft` | [`Boolean`](#boolean) | Limit result to draft merge requests. |
| <a id="usercoreauthoredmergerequestsgroupid"></a>`groupId` | [`GroupID`](#groupid) | The global ID of the group the authored merge requests should be in. Merge requests in subgroups are included. |
| <a id="usercoreauthoredmergerequestsiids"></a>`iids` | [`[String!]`](#string) | Array of IIDs of merge requests, for example `[1, 2]`. |
| <a id="usercoreauthoredmergerequestslabels"></a>`labels` | [`[String!]`](#string) | Array of label names. All resolved merge requests will have all of these labels. |
| <a id="usercoreauthoredmergerequestslabelname"></a>`labelName` | [`[String]`](#string) | Labels applied to the merge request. |
| <a id="usercoreauthoredmergerequestslabels"></a>`labels` **{warning-solid}** | [`[String!]`](#string) | **Deprecated** in GitLab 17.1. Use `labelName`. |
| <a id="usercoreauthoredmergerequestsmergedafter"></a>`mergedAfter` | [`Time`](#time) | Merge requests merged after the date. |
| <a id="usercoreauthoredmergerequestsmergedbefore"></a>`mergedBefore` | [`Time`](#time) | Merge requests merged before the date. |
| <a id="usercoreauthoredmergerequestsmilestonetitle"></a>`milestoneTitle` | [`String`](#string) | Title of the milestone. Incompatible with milestoneWildcardId. |
@ -31466,7 +31491,8 @@ four standard [pagination arguments](#pagination-arguments):
| <a id="usercorereviewrequestedmergerequestsdraft"></a>`draft` | [`Boolean`](#boolean) | Limit result to draft merge requests. |
| <a id="usercorereviewrequestedmergerequestsgroupid"></a>`groupId` | [`GroupID`](#groupid) | The global ID of the group the authored merge requests should be in. Merge requests in subgroups are included. |
| <a id="usercorereviewrequestedmergerequestsiids"></a>`iids` | [`[String!]`](#string) | Array of IIDs of merge requests, for example `[1, 2]`. |
| <a id="usercorereviewrequestedmergerequestslabels"></a>`labels` | [`[String!]`](#string) | Array of label names. All resolved merge requests will have all of these labels. |
| <a id="usercorereviewrequestedmergerequestslabelname"></a>`labelName` | [`[String]`](#string) | Labels applied to the merge request. |
| <a id="usercorereviewrequestedmergerequestslabels"></a>`labels` **{warning-solid}** | [`[String!]`](#string) | **Deprecated** in GitLab 17.1. Use `labelName`. |
| <a id="usercorereviewrequestedmergerequestsmergedafter"></a>`mergedAfter` | [`Time`](#time) | Merge requests merged after the date. |
| <a id="usercorereviewrequestedmergerequestsmergedbefore"></a>`mergedBefore` | [`Time`](#time) | Merge requests merged before the date. |
| <a id="usercorereviewrequestedmergerequestsmilestonetitle"></a>`milestoneTitle` | [`String`](#string) | Title of the milestone. Incompatible with milestoneWildcardId. |
@ -37759,7 +37785,8 @@ four standard [pagination arguments](#pagination-arguments):
| <a id="userassignedmergerequestsdraft"></a>`draft` | [`Boolean`](#boolean) | Limit result to draft merge requests. |
| <a id="userassignedmergerequestsgroupid"></a>`groupId` | [`GroupID`](#groupid) | The global ID of the group the authored merge requests should be in. Merge requests in subgroups are included. |
| <a id="userassignedmergerequestsiids"></a>`iids` | [`[String!]`](#string) | Array of IIDs of merge requests, for example `[1, 2]`. |
| <a id="userassignedmergerequestslabels"></a>`labels` | [`[String!]`](#string) | Array of label names. All resolved merge requests will have all of these labels. |
| <a id="userassignedmergerequestslabelname"></a>`labelName` | [`[String]`](#string) | Labels applied to the merge request. |
| <a id="userassignedmergerequestslabels"></a>`labels` **{warning-solid}** | [`[String!]`](#string) | **Deprecated** in GitLab 17.1. Use `labelName`. |
| <a id="userassignedmergerequestsmergedafter"></a>`mergedAfter` | [`Time`](#time) | Merge requests merged after the date. |
| <a id="userassignedmergerequestsmergedbefore"></a>`mergedBefore` | [`Time`](#time) | Merge requests merged before the date. |
| <a id="userassignedmergerequestsmilestonetitle"></a>`milestoneTitle` | [`String`](#string) | Title of the milestone. Incompatible with milestoneWildcardId. |
@ -37803,7 +37830,8 @@ four standard [pagination arguments](#pagination-arguments):
| <a id="userauthoredmergerequestsdraft"></a>`draft` | [`Boolean`](#boolean) | Limit result to draft merge requests. |
| <a id="userauthoredmergerequestsgroupid"></a>`groupId` | [`GroupID`](#groupid) | The global ID of the group the authored merge requests should be in. Merge requests in subgroups are included. |
| <a id="userauthoredmergerequestsiids"></a>`iids` | [`[String!]`](#string) | Array of IIDs of merge requests, for example `[1, 2]`. |
| <a id="userauthoredmergerequestslabels"></a>`labels` | [`[String!]`](#string) | Array of label names. All resolved merge requests will have all of these labels. |
| <a id="userauthoredmergerequestslabelname"></a>`labelName` | [`[String]`](#string) | Labels applied to the merge request. |
| <a id="userauthoredmergerequestslabels"></a>`labels` **{warning-solid}** | [`[String!]`](#string) | **Deprecated** in GitLab 17.1. Use `labelName`. |
| <a id="userauthoredmergerequestsmergedafter"></a>`mergedAfter` | [`Time`](#time) | Merge requests merged after the date. |
| <a id="userauthoredmergerequestsmergedbefore"></a>`mergedBefore` | [`Time`](#time) | Merge requests merged before the date. |
| <a id="userauthoredmergerequestsmilestonetitle"></a>`milestoneTitle` | [`String`](#string) | Title of the milestone. Incompatible with milestoneWildcardId. |
@ -37901,7 +37929,8 @@ four standard [pagination arguments](#pagination-arguments):
| <a id="userreviewrequestedmergerequestsdraft"></a>`draft` | [`Boolean`](#boolean) | Limit result to draft merge requests. |
| <a id="userreviewrequestedmergerequestsgroupid"></a>`groupId` | [`GroupID`](#groupid) | The global ID of the group the authored merge requests should be in. Merge requests in subgroups are included. |
| <a id="userreviewrequestedmergerequestsiids"></a>`iids` | [`[String!]`](#string) | Array of IIDs of merge requests, for example `[1, 2]`. |
| <a id="userreviewrequestedmergerequestslabels"></a>`labels` | [`[String!]`](#string) | Array of label names. All resolved merge requests will have all of these labels. |
| <a id="userreviewrequestedmergerequestslabelname"></a>`labelName` | [`[String]`](#string) | Labels applied to the merge request. |
| <a id="userreviewrequestedmergerequestslabels"></a>`labels` **{warning-solid}** | [`[String!]`](#string) | **Deprecated** in GitLab 17.1. Use `labelName`. |
| <a id="userreviewrequestedmergerequestsmergedafter"></a>`mergedAfter` | [`Time`](#time) | Merge requests merged after the date. |
| <a id="userreviewrequestedmergerequestsmergedbefore"></a>`mergedBefore` | [`Time`](#time) | Merge requests merged before the date. |
| <a id="userreviewrequestedmergerequestsmilestonetitle"></a>`milestoneTitle` | [`String`](#string) | Title of the milestone. Incompatible with milestoneWildcardId. |

View File

@ -9,7 +9,7 @@ description: "Documentation for the REST API for Package Protection Rules in Git
DETAILS:
**Tier:** Free, Premium, Ultimate
**Offering:** GitLab.com, Self-managed
**Offering:** Self-managed
**Status:** Experiment
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/151741) in GitLab 17.1 [with a flag](../administration/feature_flags.md) named `packages_protected_packages`. Disabled by default.
@ -72,6 +72,48 @@ Example response:
]
```
## Create a package protection rule
Create a package protection rule for a project.
```plaintext
POST /api/v4/projects/:id/packages/protection/rules
```
Supported attributes:
| Attribute | Type | Required | Description |
|---------------------------------------|-----------------|----------|--------------------------------|
| `id` | integer/string | Yes | ID or [URL-encoded path of the project](rest/index.md#namespaced-path-encoding) owned by the authenticated user. |
| `package_name_pattern` | string | Yes | Package name protected by the protection rule. For example `@my-scope/my-package-*`. Wildcard character `*` allowed. |
| `package_type` | string | Yes | Package type protected by the protection rule. For example `npm`. |
| `minimum_access_level_for_push` | string | Yes | Minimum GitLab access level able to push a package. For example `developer`, `maintainer`, `owner`. |
If successful, returns [`201`](rest/index.md#status-codes) and the created package protection rule.
Can return the following status codes:
- `201 Created`: The package protection rule was created successfully.
- `400 Bad Request`: The package protection rule is invalid.
- `401 Unauthorized`: The access token is invalid.
- `403 Forbidden`: The user does not have permission to create a package protection rule.
- `404 Not Found`: The project was not found.
- `422 Unprocessable Entity`: The package protection rule could not be created, for example, because the `package_name_pattern` is already taken.
Example request:
```shell
curl --request POST \
--header "PRIVATE-TOKEN: <your_access_token>" \
--header "Content-Type: application/json" \
--url "https://gitlab.example.com/api/v4/projects/7/packages/protection/rules" \
--data '{
"package_name_pattern": "package-name-pattern-*",
"package_type": "npm",
"minimum_access_level_for_push": "maintainer"
}'
```
## Delete a package protection rule
Deletes a package protection rule from a project.

View File

@ -582,9 +582,7 @@ In the next iteration, we plan to decompose the Chat primitive into multiple pri
The introduction of Unit Primitives will simplify the management of AI features and provide a more granular control over the functionalities exposed through the AI Gateway. This will also pave the way for future work on supporting user-deployed models and locally hosted models.
For more details, refer to the [Initial Set of Unit Primitives](https://gitlab.com/gitlab-org/gitlab/-/issues/444934) issue.
- [Unit Primitives for Accessing CC Features](https://gitlab.com/groups/gitlab-org/-/epics/12556)
For more details on how to implement and integrate unit primitives, refer to the [Cloud Connector documentation](../../../development/cloud_connector/index.md).
### Self Managed AI Gateway

View File

@ -32,6 +32,35 @@ module API
present user_project.package_protection_rules, with: Entities::Projects::Packages::Protection::Rule
end
desc 'Create a package protection rule for a project' do
success Entities::Projects::Packages::Protection::Rule
failure [
{ code: 400, message: 'Bad Request' },
{ code: 401, message: 'Unauthorized' },
{ code: 403, message: 'Forbidden' },
{ code: 404, message: 'Not Found' },
{ code: 422, message: 'Unprocessable Entity' }
]
tags %w[projects]
end
params do
requires :package_name_pattern, type: String,
desc: 'Package name protected by the rule. For example @my-scope/my-package-*. Wildcard character * allowed.'
requires :package_type, type: String, values: Packages::Protection::Rule.package_types.keys,
desc: 'Package type protected by the rule. For example npm.'
requires :minimum_access_level_for_push, type: String,
values: Packages::Protection::Rule.minimum_access_level_for_pushes.keys,
desc: 'Minimum GitLab access level able to push a package. For example developer, maintainer, owner.'
end
post ':id/packages/protection/rules' do
response = ::Packages::Protection::CreateRuleService.new(project: user_project, current_user: current_user,
params: declared_params(params)).execute
render_api_error!({ error: response.message }, :unprocessable_entity) if response.error?
present response[:package_protection_rule], with: Entities::Projects::Packages::Protection::Rule
end
desc 'Delete package protection rule' do
success code: 204, message: '204 No Content'
failure [

View File

@ -1301,6 +1301,9 @@ module API
requires :credit_card_type, type: String, desc: 'The credit card network name'
optional :zuora_payment_method_xid, type: String, desc: 'The Zuora payment method ID'
optional :stripe_setup_intent_xid, type: String, desc: 'The Stripe setup intent ID'
optional :stripe_payment_method_xid, type: String, desc: 'The Stripe payment method ID'
optional :stripe_card_fingerprint, type: String, desc: 'The Stripe credit card fingerprint'
end
put ":user_id/credit_card_validation", urgency: :low, feature_category: :subscription_management do
authenticated_as_admin!

View File

@ -0,0 +1,10 @@
# frozen_string_literal: true
module Gitlab
module BackgroundMigration
class BackfillVulnerabilityFlagsProjectId < BackfillDesiredShardingKeyJob
operation_name :backfill_vulnerability_flags_project_id
feature_category :vulnerability_management
end
end
end

View File

@ -66,7 +66,7 @@
"@gitlab/favicon-overlay": "2.0.0",
"@gitlab/fonts": "^1.3.0",
"@gitlab/ui": "81.0.0",
"@gitlab/svgs": "3.102.0",
"@gitlab/svgs": "3.103.0",
"@gitlab/web-ide": "^0.0.1-dev-20240531032328",
"@mattiasbuelens/web-streams-adapter": "^0.1.0",
"@rails/actioncable": "7.0.8-4",

View File

@ -743,7 +743,7 @@ module QA
def enabled?(value, default: true)
return default if value.nil?
(value.to_s =~ /^(false|no|0)$/i) != 0
value.to_s.match?(/^(true|yes|1)$/i)
end
end
end

View File

@ -9,26 +9,29 @@ RSpec.describe QA::Runtime::Env do
shared_examples 'boolean method with parameter' do |method:, env_key:, default:, param: nil|
context 'when there is an env variable set' do
it 'returns false when falsey values specified' do
it 'returns false when variable is falsey or unsupported' do
stub_env(env_key, 'false')
expect(described_class.public_send(method, *param)).to be_falsey
expect(described_class.public_send(method, *param)).to eq(false)
stub_env(env_key, 'no')
expect(described_class.public_send(method, *param)).to be_falsey
expect(described_class.public_send(method, *param)).to eq(false)
stub_env(env_key, '0')
expect(described_class.public_send(method, *param)).to be_falsey
end
it 'returns true when anything else specified' do
stub_env(env_key, 'true')
expect(described_class.public_send(method, *param)).to be_truthy
stub_env(env_key, '1')
expect(described_class.public_send(method, *param)).to be_truthy
expect(described_class.public_send(method, *param)).to eq(false)
stub_env(env_key, 'anything')
expect(described_class.public_send(method, *param)).to be_truthy
expect(described_class.public_send(method, *param)).to eq(false)
end
it 'returns true when variable set to truthy' do
stub_env(env_key, 'true')
expect(described_class.public_send(method, *param)).to eq(true)
stub_env(env_key, '1')
expect(described_class.public_send(method, *param)).to eq(true)
stub_env(env_key, 'yes')
expect(described_class.public_send(method, *param)).to eq(true)
end
end

View File

@ -49,7 +49,7 @@ variables:
QA_SUITES: "$QA_SUITES"
QA_TESTS: "$QA_TESTS"
KNAPSACK_TEST_FILE_PATTERN: "$KNAPSACK_TEST_FILE_PATTERN"
COVERBAND_ENABLED: "$COVERBAND_ENABLED"
COVERBAND_ENABLED: "${COVERBAND_ENABLED:-false}"
YML
)

View File

@ -127,7 +127,7 @@ RSpec.describe 'Dashboard Issues Calendar Feed', feature_category: :team_plannin
expected_description = (+"DESCRIPTION:Find out more at #{issue_url(issue)}").insert(75, ' ')
expect(body).to have_text(expected_description)
expect(body).to have_text("DTSTART;VALUE=DATE:#{Date.tomorrow.strftime('%Y%m%d')}")
expect(body).to have_text("URL:#{issue_url(issue)}")
expect(body).to have_text("URI:#{issue_url(issue)}")
expect(body).to have_text('TRANSP:TRANSPARENT')
end
end

View File

@ -90,7 +90,7 @@ RSpec.describe 'Group Issues Calendar Feed', feature_category: :groups_and_proje
expected_description = (+"DESCRIPTION:Find out more at #{issue_url(issue)}").insert(75, ' ')
expect(body).to have_text(expected_description)
expect(body).to have_text("DTSTART;VALUE=DATE:#{Date.tomorrow.strftime('%Y%m%d')}")
expect(body).to have_text("URL:#{issue_url(issue)}")
expect(body).to have_text("URI:#{issue_url(issue)}")
expect(body).to have_text('TRANSP:TRANSPARENT')
end
end

View File

@ -89,7 +89,7 @@ RSpec.describe 'Project Issues Calendar Feed', feature_category: :groups_and_pro
expected_description = (+"DESCRIPTION:Find out more at #{issue_url(issue)}").insert(75, ' ')
expect(body).to have_text(expected_description)
expect(body).to have_text("DTSTART;VALUE=DATE:#{Date.tomorrow.strftime('%Y%m%d')}")
expect(body).to have_text("URL:#{issue_url(issue)}")
expect(body).to have_text("URI:#{issue_url(issue)}")
expect(body).to have_text('TRANSP:TRANSPARENT')
end
end

View File

@ -9,6 +9,7 @@ RSpec.describe Resolvers::ProjectMergeRequestsResolver do
let_it_be(:current_user) { create(:user, developer_of: project) }
let_it_be(:other_user) { create(:user) }
let_it_be(:reviewer) { create(:user) }
let_it_be(:label) { create(:label, project: project) }
let_it_be(:merge_request) do
create(
@ -19,7 +20,8 @@ RSpec.describe Resolvers::ProjectMergeRequestsResolver do
author: other_user,
assignee: other_user,
milestone: create(:milestone, project: project),
reviewers: [reviewer]
reviewers: [reviewer],
labels: [label]
)
end
@ -138,6 +140,14 @@ RSpec.describe Resolvers::ProjectMergeRequestsResolver do
end
end
context 'with label name param' do
it 'filters merge requests by label name' do
result = resolve_mr(project, label_name: [label.name])
expect(result).to contain_exactly(merge_request)
end
end
def resolve_mr(project, resolver: described_class, user: current_user, **args)
resolve(resolver, obj: project, args: args, ctx: { current_user: user })
end

View File

@ -341,6 +341,7 @@ RSpec.describe GitlabSchema.types['Project'], feature_category: :groups_and_proj
:draft,
:approved,
:labels,
:label_name,
:before,
:after,
:first,

View File

@ -0,0 +1,15 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Gitlab::BackgroundMigration::BackfillVulnerabilityFlagsProjectId,
feature_category: :vulnerability_management,
schema: 20240613154929 do
include_examples 'desired sharding key backfill job' do
let(:batch_table) { :vulnerability_flags }
let(:backfill_column) { :project_id }
let(:backfill_via_table) { :vulnerability_occurrences }
let(:backfill_via_column) { :project_id }
let(:backfill_via_foreign_key) { :vulnerability_occurrence_id }
end
end

View File

@ -0,0 +1,33 @@
# frozen_string_literal: true
require 'spec_helper'
require_migration!
RSpec.describe QueueBackfillVulnerabilityFlagsProjectId, feature_category: :vulnerability_management do
let!(:batched_migration) { described_class::MIGRATION }
it 'schedules a new batched migration' do
reversible_migration do |migration|
migration.before -> {
expect(batched_migration).not_to have_scheduled_batched_migration
}
migration.after -> {
expect(batched_migration).to have_scheduled_batched_migration(
table_name: :vulnerability_flags,
column_name: :id,
interval: described_class::DELAY_INTERVAL,
batch_size: described_class::BATCH_SIZE,
sub_batch_size: described_class::SUB_BATCH_SIZE,
gitlab_schema: :gitlab_main_cell,
job_arguments: [
:project_id,
:vulnerability_occurrences,
:project_id,
:vulnerability_occurrence_id
]
)
}
end
end
end

View File

@ -2,7 +2,7 @@
require 'spec_helper'
RSpec.describe API::ProjectPackagesProtectionRules, feature_category: :package_registry do
RSpec.describe API::ProjectPackagesProtectionRules, :aggregate_failures, feature_category: :package_registry do
include ExclusiveLeaseHelpers
let_it_be(:project) { create(:project, :private) }
@ -15,13 +15,22 @@ RSpec.describe API::ProjectPackagesProtectionRules, feature_category: :package_r
let_it_be(:invalid_token) { 'invalid-token123' }
let_it_be(:headers_with_invalid_token) { { Gitlab::Auth::AuthFinders::PRIVATE_TOKEN_HEADER => invalid_token } }
shared_examples 'rejecting project packages protection rules request' do |user_role, status|
context "for #{user_role}" do
shared_examples 'rejecting project packages protection rules request when not enough permissions' do
using RSpec::Parameterized::TableSyntax
where(:user_role, :status) do
:reporter | :forbidden
:developer | :forbidden
:guest | :forbidden
nil | :not_found
end
with_them do
before do
project.send(:"add_#{user_role}", api_user) if user_role
end
it_behaves_like 'returning response status', status
it_behaves_like 'returning response status', params[:status]
end
end
@ -30,10 +39,7 @@ RSpec.describe API::ProjectPackagesProtectionRules, feature_category: :package_r
subject(:get_package_rules) { get(api(url, api_user)) }
it_behaves_like 'rejecting project packages protection rules request', :reporter, :forbidden
it_behaves_like 'rejecting project packages protection rules request', :developer, :forbidden
it_behaves_like 'rejecting project packages protection rules request', :guest, :forbidden
it_behaves_like 'rejecting project packages protection rules request', nil, :not_found
it_behaves_like 'rejecting project packages protection rules request when not enough permissions'
context 'for maintainer' do
let(:api_user) { maintainer }
@ -52,13 +58,13 @@ RSpec.describe API::ProjectPackagesProtectionRules, feature_category: :package_r
context 'when the project id is invalid' do
let(:url) { "/projects/invalid/packages/protection/rules" }
it_behaves_like 'rejecting project packages protection rules request', :maintainer, :not_found
it_behaves_like 'returning response status', :not_found
end
context 'when the project id does not exist' do
let(:url) { "/projects/#{non_existing_record_id}/packages/protection/rules" }
it_behaves_like 'rejecting project packages protection rules request', :maintainer, :not_found
it_behaves_like 'returning response status', :not_found
end
context 'when packages_protected_packages is disabled' do
@ -66,14 +72,89 @@ RSpec.describe API::ProjectPackagesProtectionRules, feature_category: :package_r
stub_feature_flags(packages_protected_packages: false)
end
it_behaves_like 'rejecting project packages protection rules request', :maintainer, :not_found
it_behaves_like 'returning response status', :not_found
end
end
context 'with invalid token' do
subject(:get_package_rules) { get(api(url), headers: headers_with_invalid_token) }
it_behaves_like 'rejecting project packages protection rules request', nil, :unauthorized
it_behaves_like 'returning response status', :unauthorized
end
end
describe 'POST /projects/:id/packages/protection/rules' do
let(:url) { "/projects/#{project.id}/packages/protection/rules" }
let(:params) do
{ package_name_pattern: '@my-new-scope/my-package-*',
package_type: package_protection_rule.package_type,
minimum_access_level_for_push: package_protection_rule.minimum_access_level_for_push }
end
subject(:post_package_rule) { post(api(url, api_user), params: params) }
it_behaves_like 'rejecting project packages protection rules request when not enough permissions'
context 'for maintainer' do
let(:api_user) { maintainer }
it 'creates a package protection rule' do
expect { post_package_rule }.to change { Packages::Protection::Rule.count }.by(1)
expect(response).to have_gitlab_http_status(:created)
end
context 'with invalid package_type' do
before do
params[:package_type] = "not in enum"
end
it 'does not create a package protection rule' do
expect { post_package_rule }.to not_change(Packages::Protection::Rule, :count)
expect(response).to have_gitlab_http_status(:bad_request)
end
end
context 'with invalid minimum_access_level_for_push' do
before do
params[:minimum_access_level_for_push] = "not in enum"
end
it 'does not create a package protection rule' do
expect { post_package_rule }.to not_change(Packages::Protection::Rule, :count)
expect(response).to have_gitlab_http_status(:bad_request)
end
end
context 'with already existing package_name_pattern' do
before do
params[:package_name_pattern] = package_protection_rule.package_name_pattern
end
it 'does not create a package protection rule' do
expect { post_package_rule }.to not_change(Packages::Protection::Rule, :count)
expect(response).to have_gitlab_http_status(:unprocessable_entity)
end
end
context 'when the project id is invalid' do
let(:url) { "/projects/invalid/packages/protection/rules" }
it_behaves_like 'returning response status', :not_found
end
context 'when the project id does not exist' do
let(:url) { "/projects/#{non_existing_record_id}/packages/protection/rules" }
it_behaves_like 'returning response status', :not_found
end
context 'when packages_protected_packages is disabled' do
before do
stub_feature_flags(packages_protected_packages: false)
end
it_behaves_like 'returning response status', :not_found
end
end
end
@ -82,10 +163,7 @@ RSpec.describe API::ProjectPackagesProtectionRules, feature_category: :package_r
subject(:destroy_package_rule) { delete(api(url, api_user)) }
it_behaves_like 'rejecting project packages protection rules request', :reporter, :forbidden
it_behaves_like 'rejecting project packages protection rules request', :developer, :forbidden
it_behaves_like 'rejecting project packages protection rules request', :guest, :forbidden
it_behaves_like 'rejecting project packages protection rules request', nil, :not_found
it_behaves_like 'rejecting project packages protection rules request when not enough permissions'
context 'for maintainer' do
let(:api_user) { maintainer }
@ -102,31 +180,31 @@ RSpec.describe API::ProjectPackagesProtectionRules, feature_category: :package_r
context 'when the package protection rule does belong to another project' do
let(:url) { "/projects/#{other_project.id}/packages/protection/rules/#{package_protection_rule.id}" }
it_behaves_like 'rejecting project packages protection rules request', :maintainer, :not_found
it_behaves_like 'returning response status', :not_found
end
context 'when the project id is invalid' do
let(:url) { "/projects/invalid/packages/protection/rules/#{package_protection_rule.id}" }
it_behaves_like 'rejecting project packages protection rules request', :maintainer, :not_found
it_behaves_like 'returning response status', :not_found
end
context 'when the project id does not exist' do
let(:url) { "/projects/#{non_existing_record_id}/packages/protection/rules/#{package_protection_rule.id}" }
it_behaves_like 'rejecting project packages protection rules request', :maintainer, :not_found
it_behaves_like 'returning response status', :not_found
end
context 'when the rule id is invalid' do
let(:url) { "/projects/#{project.id}/packages/protection/rules/invalid" }
it_behaves_like 'rejecting project packages protection rules request', :maintainer, :bad_request
it_behaves_like 'returning response status', :bad_request
end
context 'when the rule id does not exist' do
let(:url) { "/projects/#{project.id}/packages/protection/rules/#{non_existing_record_id}" }
it_behaves_like 'rejecting project packages protection rules request', :maintainer, :not_found
it_behaves_like 'returning response status', :not_found
end
context 'when packages_protected_packages is disabled' do
@ -134,13 +212,13 @@ RSpec.describe API::ProjectPackagesProtectionRules, feature_category: :package_r
stub_feature_flags(packages_protected_packages: false)
end
it_behaves_like 'rejecting project packages protection rules request', :maintainer, :not_found
it_behaves_like 'returning response status', :not_found
end
context 'with invalid token' do
subject(:delete_package_rules) { delete(api(url), headers: headers_with_invalid_token) }
it_behaves_like 'rejecting project packages protection rules request', nil, :unauthorized
it_behaves_like 'returning response status', :unauthorized
end
end
end

View File

@ -2080,6 +2080,9 @@ RSpec.describe API::Users, :aggregate_failures, feature_category: :user_manageme
let(:expiration_date) { Date.new(expiration_year, expiration_month, -1) }
let(:credit_card_validated_at) { Time.utc(2020, 1, 1) }
let(:zuora_payment_method_xid) { 'abc123' }
let(:stripe_setup_intent_xid) { 'seti_abc123' }
let(:stripe_payment_method_xid) { 'pm_abc123' }
let(:stripe_card_fingerprint) { 'card123' }
let(:path) { "/user/#{user.id}/credit_card_validation" }
let(:params) do
@ -2090,7 +2093,10 @@ RSpec.describe API::Users, :aggregate_failures, feature_category: :user_manageme
credit_card_holder_name: holder_name,
credit_card_type: network,
credit_card_mask_number: last_digits,
zuora_payment_method_xid: zuora_payment_method_xid
zuora_payment_method_xid: zuora_payment_method_xid,
stripe_setup_intent_xid: stripe_setup_intent_xid,
stripe_payment_method_xid: stripe_payment_method_xid,
stripe_card_fingerprint: stripe_card_fingerprint
}
end
@ -2125,7 +2131,10 @@ RSpec.describe API::Users, :aggregate_failures, feature_category: :user_manageme
holder_name_hash: sha256(holder_name.downcase),
last_digits_hash: sha256(last_digits),
expiration_date_hash: sha256(expiration_date.to_s),
zuora_payment_method_xid: zuora_payment_method_xid
zuora_payment_method_xid: zuora_payment_method_xid,
stripe_setup_intent_xid: stripe_setup_intent_xid,
stripe_payment_method_xid: stripe_payment_method_xid,
stripe_card_fingerprint: stripe_card_fingerprint
)
end

View File

@ -17,6 +17,9 @@ RSpec.describe Users::UpsertCreditCardValidationService, feature_category: :user
let(:expiration_date) { Date.new(expiration_year, expiration_month, -1) }
let(:credit_card_validated_at) { Time.utc(2020, 1, 1) }
let(:zuora_payment_method_xid) { 'abc123' }
let(:stripe_setup_intent_xid) { 'seti_abc123' }
let(:stripe_payment_method_xid) { 'pm_abc123' }
let(:stripe_card_fingerprint) { 'card123' }
let(:params) do
{
@ -27,7 +30,10 @@ RSpec.describe Users::UpsertCreditCardValidationService, feature_category: :user
credit_card_holder_name: holder_name,
credit_card_type: network,
credit_card_mask_number: last_digits,
zuora_payment_method_xid: zuora_payment_method_xid
zuora_payment_method_xid: zuora_payment_method_xid,
stripe_setup_intent_xid: stripe_setup_intent_xid,
stripe_payment_method_xid: stripe_payment_method_xid,
stripe_card_fingerprint: stripe_card_fingerprint
}
end
@ -52,7 +58,10 @@ RSpec.describe Users::UpsertCreditCardValidationService, feature_category: :user
holder_name_hash: sha256(holder_name.downcase),
last_digits_hash: sha256(last_digits),
expiration_date_hash: sha256(expiration_date.to_s),
zuora_payment_method_xid: 'abc123'
zuora_payment_method_xid: 'abc123',
stripe_setup_intent_xid: 'seti_abc123',
stripe_payment_method_xid: 'pm_abc123',
stripe_card_fingerprint: 'card123'
)
end
end
@ -113,6 +122,28 @@ RSpec.describe Users::UpsertCreditCardValidationService, feature_category: :user
end
end
context 'when the stripe identifiers are missing' do
let(:stripe_setup_intent_xid) { nil }
let(:stripe_payment_method_xid) { nil }
let(:stripe_card_fingerprint) { nil }
it 'successfully validates the credit card' do
service_result = service.execute
expect(service_result).to be_success
expect(service_result.message).to eq(_('Credit card validation record saved'))
user.reload
expect(user.credit_card_validated_at).to be_present
expect(user.credit_card_validation).to have_attributes(
stripe_setup_intent_xid: nil,
stripe_payment_method_xid: nil,
stripe_card_fingerprint: nil
)
end
end
context 'when the user_id does not exist' do
let(:user_id) { non_existing_record_id }

View File

@ -1326,10 +1326,10 @@
stylelint-declaration-strict-value "1.10.4"
stylelint-scss "6.0.0"
"@gitlab/svgs@3.102.0":
version "3.102.0"
resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-3.102.0.tgz#bf6750e858379b2d45ceb06026540704241df41a"
integrity sha512-EjjBTI3YVrMTG3ZBJSfIKxu7zqFkLLSPHrmQS+2xDgrLZhxFi61vpjp2+nGw1l8gzf0WXyBgqcMHF6YTTrTN4Q==
"@gitlab/svgs@3.103.0":
version "3.103.0"
resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-3.103.0.tgz#af61387481100eadef2bea8fe8605250311ac582"
integrity sha512-jVWCrRVRF6nw2A+Aowc0quXV2bdRPl2v08ElCPSestfdKjQ92tSlCrIsLB8GvdW5aI0eFsD1vJ1w2qkzZdpA4A==
"@gitlab/ui@81.0.0":
version "81.0.0"