Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2023-10-10 09:08:01 +00:00
parent 3669bcfaaa
commit 0e6368a09e
68 changed files with 1663 additions and 998 deletions

View File

@ -7,6 +7,11 @@ module Resolvers
type Types::Notes::NoteType.connection_type, null: false
argument :filter, Types::WorkItems::NotesFilterTypeEnum,
required: false,
default_value: ::UserPreference::NOTES_FILTERS[:all_notes],
description: 'Type of notes collection: ALL_NOTES, ONLY_COMMENTS, ONLY_ACTIVITY.'
before_connection_authorization do |nodes, current_user|
next if nodes.blank?
@ -16,8 +21,9 @@ module Resolvers
::Preloaders::Projects::NotesPreloader.new(project, current_user).call(nodes)
end
def resolve_with_lookahead(*)
apply_lookahead(object.notes.fresh)
def resolve_with_lookahead(**args)
notes = NotesFinder.new(current_user, build_params(args)).execute
apply_lookahead(notes)
end
private
@ -31,6 +37,17 @@ module Resolvers
award_emoji: [:award_emoji]
}
end
def build_params(args)
params = {
project: object.project,
target: object
}
params[:notes_filter] = args[:filter] if args[:filter].present?
params
end
end
end
end

View File

@ -188,7 +188,7 @@ module GroupsHelper
}
end
def enabled_git_access_protocol_options_for_group
def enabled_git_access_protocol_options_for_group(_)
case ::Gitlab::CurrentSettings.enabled_git_access_protocol
when nil, ""
[[_("Both SSH and HTTP(S)"), "all"], [_("Only SSH"), "ssh"], [_("Only HTTP(S)"), "http"]]

View File

@ -305,7 +305,7 @@ class ApplicationSetting < MainClusterwide::ApplicationRecord
if: :auto_devops_enabled?
validates :enabled_git_access_protocol,
inclusion: { in: %w[ssh http], allow_blank: true }
inclusion: { in: ->(_) { enabled_git_access_protocol_values }, allow_blank: true }
validates :domain_denylist,
presence: { message: 'Domain denylist cannot be empty if denylist is enabled.' },
@ -959,6 +959,10 @@ class ApplicationSetting < MainClusterwide::ApplicationRecord
HUMANIZED_ATTRIBUTES[attribute.to_sym] || super
end
def self.enabled_git_access_protocol_values
%w[ssh http]
end
def parsed_grafana_url
@parsed_grafana_url ||= Gitlab::Utils.parse_url(grafana_url)
end

View File

@ -694,7 +694,7 @@ class Group < Namespace
return GroupMember::NO_ACCESS unless user
return GroupMember::OWNER if user.can_admin_all_resources? && !only_concrete_membership
max_member_access([user.id])[user.id]
max_member_access(user)
end
def mattermost_team_params
@ -953,16 +953,16 @@ class Group < Namespace
end
end
def max_member_access(user_ids)
::Gitlab::Database.allow_cross_joins_across_databases(url: "https://gitlab.com/gitlab-org/gitlab/-/issues/417455") do
Gitlab::SafeRequestLoader.execute(
resource_key: max_member_access_for_resource_key(User),
resource_ids: user_ids,
default_value: Gitlab::Access::NO_ACCESS
) do |user_ids|
members_with_parents.where(user_id: user_ids).group(:user_id).maximum(:access_level)
end
end
def max_member_access(user)
Gitlab::SafeRequestLoader.execute(
resource_key: max_member_access_for_resource_key(User),
resource_ids: [user.id],
default_value: Gitlab::Access::NO_ACCESS
) do |_|
next {} unless user.active?
members_with_parents(only_active_users: false).where(user_id: user.id).group(:user_id).maximum(:access_level)
end.fetch(user.id)
end
def update_two_factor_requirement

View File

@ -10,7 +10,7 @@ class NamespaceSetting < ApplicationRecord
belongs_to :namespace, inverse_of: :namespace_settings
enum jobs_to_be_done: { basics: 0, move_repository: 1, code_storage: 2, exploring: 3, ci: 4, other: 5 }, _suffix: true
enum enabled_git_access_protocol: { all: 0, ssh: 1, http: 2 }, _suffix: true
enum enabled_git_access_protocol: { all: 0, ssh: 1, http: 2, ssh_certificates: 3 }, _suffix: true
attribute :default_branch_protection_defaults, default: -> { {} }

View File

@ -61,8 +61,6 @@ module Namespaces
# INPUT: [[4909902], [4909902,51065789], [4909902,51065793], [7135830], [15599674, 1], [15599674, 1, 3], [15599674, 2]]
# RESULT: [[4909902], [7135830], [15599674, 1], [15599674, 2]]
def shortest_traversal_ids_prefixes
raise ArgumentError, 'Feature not supported since the `:use_traversal_ids` is disabled' unless use_traversal_ids?
prefixes = []
# The array needs to be sorted (O(nlogn)) to ensure shortest elements are always first
@ -91,8 +89,6 @@ module Namespaces
end
def use_traversal_ids?
return false unless Feature.enabled?(:use_traversal_ids)
traversal_ids.present?
end

View File

@ -12,14 +12,10 @@ module Namespaces
# list of namespace IDs, it can be faster to reference the ID in
# traversal_ids than the primary key ID column.
def as_ids
return super unless use_traversal_ids?
select(Arel.sql('namespaces.traversal_ids[array_length(namespaces.traversal_ids, 1)]').as('id'))
end
def roots
return super unless use_traversal_ids?
root_ids = all.select("#{quoted_table_name}.traversal_ids[1]").distinct
unscoped.where(id: root_ids)
end
@ -37,20 +33,14 @@ module Namespaces
end
def self_and_descendants(include_self: true)
return super unless use_traversal_ids?
self_and_descendants_with_comparison_operators(include_self: include_self)
end
def self_and_descendant_ids(include_self: true)
return super unless use_traversal_ids?
self_and_descendants(include_self: include_self).as_ids
end
def self_and_hierarchy
return super unless use_traversal_ids?
unscoped.from_union([all.self_and_ancestors, all.self_and_descendants(include_self: false)])
end
@ -74,10 +64,6 @@ module Namespaces
private
def use_traversal_ids?
Feature.enabled?(:use_traversal_ids)
end
def self_and_ancestors_from_inner_join(include_self: true, upto: nil, hierarchy_order: nil)
base_cte = all.reselect('namespaces.traversal_ids').as_cte(:base_ancestors_cte)

View File

@ -8,8 +8,6 @@ module Preloaders
end
def execute
return unless ::Feature.enabled?(:use_traversal_ids)
# type == 'Group' condition located on subquery to prevent a filter in the query
root_query = Namespace.joins("INNER JOIN (#{join_sql}) as root_query ON root_query.root_id = namespaces.id")
.select('namespaces.*, root_query.id as source_id')

View File

@ -10,7 +10,6 @@ module Preloaders
def execute
return unless @projects.is_a?(ActiveRecord::Relation)
return unless ::Feature.enabled?(:use_traversal_ids)
root_query = Namespace.joins("INNER JOIN (#{join_sql}) as root_query ON root_query.root_id = namespaces.id")
.select('namespaces.*, root_query.id as source_id')

View File

@ -10,27 +10,11 @@ module Preloaders
end
def execute
if ::Feature.enabled?(:use_traversal_ids)
preload_with_traversal_ids
else
preload_direct_memberships
end
preload_with_traversal_ids
end
private
def preload_direct_memberships
group_memberships = GroupMember.active_without_invites_and_requests
.where(user: @user, source_id: @groups)
.group(:source_id)
.maximum(:access_level)
@groups.each do |group|
access_level = group_memberships[group.id]
group.merge_value_to_request_store(User, @user.id, access_level) if access_level.present?
end
end
def preload_with_traversal_ids
# Diagrammatic representation of this step:
# https://gitlab.com/gitlab-org/gitlab/-/merge_requests/111157#note_1271550140

View File

@ -2509,14 +2509,6 @@ class User < MainClusterwide::ApplicationRecord
def ci_namespace_mirrors_for_group_members(level)
search_members = group_members.where('access_level >= ?', level)
# This reduces searched prefixes to only shortest ones
# to avoid querying descendants since they are already covered
# by ancestor namespaces. If the FF is not available fallback to
# inefficient search: https://gitlab.com/gitlab-org/gitlab/-/issues/336436
unless Feature.enabled?(:use_traversal_ids)
return Ci::NamespaceMirror.contains_any_of_namespaces(search_members.pluck(:source_id))
end
traversal_ids = Group.joins(:all_group_members)
.merge(search_members)
.shortest_traversal_ids_prefixes

View File

@ -1,7 +1,7 @@
- if group.root?
.form-group
= f.label _('Enabled Git access protocols'), class: 'label-bold'
= f.select :enabled_git_access_protocol, options_for_select(enabled_git_access_protocol_options_for_group, group.enabled_git_access_protocol), {}, class: 'form-control', data: { qa_selector: 'enabled_git_access_protocol_dropdown' }, disabled: !::Gitlab::CurrentSettings.enabled_git_access_protocol.blank?
= f.select :enabled_git_access_protocol, options_for_select(enabled_git_access_protocol_options_for_group(group), group.enabled_git_access_protocol), {}, class: 'form-control', data: { qa_selector: 'enabled_git_access_protocol_dropdown' }, disabled: !::Gitlab::CurrentSettings.enabled_git_access_protocol.blank?
- if !::Gitlab::CurrentSettings.enabled_git_access_protocol.blank?
.form-text.text-muted
= _("This setting has been configured at the instance level and cannot be overridden per group")

View File

@ -1,8 +1,8 @@
---
name: use_traversal_ids
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56296
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/321948
milestone: '13.11'
name: enforce_ssh_certificates
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/132653
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/426235
milestone: '16.5'
type: development
group: group::tenant scale
default_enabled: true
group: group::source code
default_enabled: false

View File

@ -0,0 +1,10 @@
---
table_name: scan_result_policy_violations
classes:
- Security::ScanResultPolicyViolation
feature_categories:
- security_policy_management
description: Stores scan result policy violations.
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/132254
milestone: '16.5'
gitlab_schema: gitlab_main

View File

@ -0,0 +1,32 @@
# frozen_string_literal: true
class CreateScanResultPolicyViolations < Gitlab::Database::Migration[2.1]
enable_lock_retries!
def up
create_table :scan_result_policy_violations do |t|
t.bigint :scan_result_policy_id,
index: false,
null: false
t.bigint :merge_request_id,
index: { name: 'index_scan_result_policy_violations_on_merge_request_id' },
null: false
t.bigint :project_id,
index: { name: 'index_scan_result_policy_violations_on_project_id' },
null: false
t.timestamps_with_timezone null: false
end
add_index(:scan_result_policy_violations,
%i[scan_result_policy_id merge_request_id],
unique: true,
name: 'index_scan_result_policy_violations_on_policy_and_merge_request')
end
def down
drop_table :scan_result_policy_violations
end
end

View File

@ -0,0 +1,19 @@
# frozen_string_literal: true
class AddScanResultPolicyFkToScanResultPolicyViolations < Gitlab::Database::Migration[2.1]
disable_ddl_transaction!
def up
add_concurrent_foreign_key(
:scan_result_policy_violations,
:scan_result_policies,
column: :scan_result_policy_id,
on_delete: :cascade)
end
def down
with_lock_retries do
remove_foreign_key(:scan_result_policy_violations, column: :scan_result_policy_id)
end
end
end

View File

@ -0,0 +1,19 @@
# frozen_string_literal: true
class AddMergeRequestFkToScanResultPolicyViolations < Gitlab::Database::Migration[2.1]
disable_ddl_transaction!
def up
add_concurrent_foreign_key(
:scan_result_policy_violations,
:merge_requests,
column: :merge_request_id,
on_delete: :cascade)
end
def down
with_lock_retries do
remove_foreign_key(:scan_result_policy_violations, column: :merge_request_id)
end
end
end

View File

@ -0,0 +1,19 @@
# frozen_string_literal: true
class AddProjectFkToScanResultPolicyViolations < Gitlab::Database::Migration[2.1]
disable_ddl_transaction!
def up
add_concurrent_foreign_key(
:scan_result_policy_violations,
:projects,
column: :project_id,
on_delete: :cascade)
end
def down
with_lock_retries do
remove_foreign_key(:scan_result_policy_violations, column: :project_id)
end
end
end

View File

@ -0,0 +1,20 @@
# frozen_string_literal: true
class DeletePagesDomainWithReservedDomains < Gitlab::Database::Migration[2.1]
restrict_gitlab_migration gitlab_schema: :gitlab_main
def up
execute <<~SQL.squish
DELETE FROM "pages_domains"
WHERE LOWER("pages_domains"."domain") IN
('aol.com', 'gmail.com', 'hotmail.co.uk', 'hotmail.com', 'hotmail.fr', 'icloud.com',
'live.com', 'mail.com', 'me.com', 'msn.com', 'outlook.com', 'proton.me', 'protonmail.com',
'tutanota.com', 'yahoo.com', 'yandex.com', 'zohomail.com');
SQL
end
def down
# no-op
# This migration can't be rolled back as we are deleting entires
end
end

View File

@ -0,0 +1,9 @@
# frozen_string_literal: true
class ChangeWorkspacesForceIncludeAllResourcesDefault < Gitlab::Database::Migration[2.1]
enable_lock_retries!
def change
change_column_default(:workspaces, :force_include_all_resources, from: false, to: true)
end
end

View File

@ -0,0 +1 @@
fdc307e3bd5e7762d276219fe877c8b2dd94c90117d914b483c624fc28f4b7dd

View File

@ -0,0 +1 @@
5890e80dd082fbef80ec5772597f90486defd9055b9506e588ac5c63f55d69e7

View File

@ -0,0 +1 @@
6279203061e730ad1e6b969d55cc7aa78c0cca943beaad66852552f72511aba6

View File

@ -0,0 +1 @@
4c391db76b7cf1d380beb4317db727d01372da47e7a97be1bf52f9a791ed0b89

View File

@ -0,0 +1 @@
7f51d5f2f6382dc2b48a766e32b5248846a912a47158872c1c26524127b08c61

View File

@ -0,0 +1 @@
7d7349723ad38ef6615437d563b01aff39b6eb1c58ec29601e770330d0d5ada6

View File

@ -22754,6 +22754,24 @@ CREATE SEQUENCE scan_result_policies_id_seq
ALTER SEQUENCE scan_result_policies_id_seq OWNED BY scan_result_policies.id;
CREATE TABLE scan_result_policy_violations (
id bigint NOT NULL,
scan_result_policy_id bigint NOT NULL,
merge_request_id bigint NOT NULL,
project_id bigint NOT NULL,
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL
);
CREATE SEQUENCE scan_result_policy_violations_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
ALTER SEQUENCE scan_result_policy_violations_id_seq OWNED BY scan_result_policy_violations.id;
CREATE TABLE schema_migrations (
version character varying NOT NULL,
finished_at timestamp with time zone DEFAULT now()
@ -25244,7 +25262,7 @@ CREATE TABLE workspaces (
personal_access_token_id bigint,
config_version integer DEFAULT 1 NOT NULL,
force_full_reconciliation boolean DEFAULT false NOT NULL,
force_include_all_resources boolean DEFAULT false NOT NULL,
force_include_all_resources boolean DEFAULT true NOT NULL,
CONSTRAINT check_15543fb0fa CHECK ((char_length(name) <= 64)),
CONSTRAINT check_157d5f955c CHECK ((char_length(namespace) <= 64)),
CONSTRAINT check_2b401b0034 CHECK ((char_length(deployment_resource_version) <= 64)),
@ -26736,6 +26754,8 @@ ALTER TABLE ONLY sbom_sources ALTER COLUMN id SET DEFAULT nextval('sbom_sources_
ALTER TABLE ONLY scan_result_policies ALTER COLUMN id SET DEFAULT nextval('scan_result_policies_id_seq'::regclass);
ALTER TABLE ONLY scan_result_policy_violations ALTER COLUMN id SET DEFAULT nextval('scan_result_policy_violations_id_seq'::regclass);
ALTER TABLE ONLY scim_identities ALTER COLUMN id SET DEFAULT nextval('scim_identities_id_seq'::regclass);
ALTER TABLE ONLY scim_oauth_access_tokens ALTER COLUMN id SET DEFAULT nextval('scim_oauth_access_tokens_id_seq'::regclass);
@ -29235,6 +29255,9 @@ ALTER TABLE ONLY sbom_sources
ALTER TABLE ONLY scan_result_policies
ADD CONSTRAINT scan_result_policies_pkey PRIMARY KEY (id);
ALTER TABLE ONLY scan_result_policy_violations
ADD CONSTRAINT scan_result_policy_violations_pkey PRIMARY KEY (id);
ALTER TABLE ONLY schema_migrations
ADD CONSTRAINT schema_migrations_pkey PRIMARY KEY (version);
@ -33989,6 +34012,12 @@ CREATE UNIQUE INDEX index_scan_result_policies_on_position_in_configuration ON s
CREATE INDEX index_scan_result_policies_on_project_id ON scan_result_policies USING btree (project_id);
CREATE INDEX index_scan_result_policy_violations_on_merge_request_id ON scan_result_policy_violations USING btree (merge_request_id);
CREATE UNIQUE INDEX index_scan_result_policy_violations_on_policy_and_merge_request ON scan_result_policy_violations USING btree (scan_result_policy_id, merge_request_id);
CREATE INDEX index_scan_result_policy_violations_on_project_id ON scan_result_policy_violations USING btree (project_id);
CREATE INDEX index_scim_identities_on_group_id ON scim_identities USING btree (group_id);
CREATE UNIQUE INDEX index_scim_identities_on_lower_extern_uid_and_group_id ON scim_identities USING btree (lower((extern_uid)::text), group_id);
@ -36710,6 +36739,9 @@ ALTER TABLE ONLY internal_ids
ALTER TABLE ONLY incident_management_timeline_events
ADD CONSTRAINT fk_17a5fafbd4 FOREIGN KEY (issue_id) REFERENCES issues(id) ON DELETE CASCADE;
ALTER TABLE ONLY scan_result_policy_violations
ADD CONSTRAINT fk_17ce579abf FOREIGN KEY (merge_request_id) REFERENCES merge_requests(id) ON DELETE CASCADE;
ALTER TABLE ONLY incident_management_timeline_events
ADD CONSTRAINT fk_1800597ef9 FOREIGN KEY (author_id) REFERENCES users(id) ON DELETE SET NULL;
@ -37091,6 +37123,9 @@ ALTER TABLE ONLY notes
ALTER TABLE ONLY oauth_openid_requests
ADD CONSTRAINT fk_77114b3b09 FOREIGN KEY (access_grant_id) REFERENCES oauth_access_grants(id) ON DELETE CASCADE;
ALTER TABLE ONLY scan_result_policy_violations
ADD CONSTRAINT fk_77251168f1 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
ALTER TABLE ONLY agent_user_access_project_authorizations
ADD CONSTRAINT fk_78034b05d8 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
@ -37673,6 +37708,9 @@ ALTER TABLE ONLY status_check_responses
ALTER TABLE ONLY design_management_designs_versions
ADD CONSTRAINT fk_f4d25ba00c FOREIGN KEY (version_id) REFERENCES design_management_versions(id) ON DELETE CASCADE;
ALTER TABLE ONLY scan_result_policy_violations
ADD CONSTRAINT fk_f53706dbdd FOREIGN KEY (scan_result_policy_id) REFERENCES scan_result_policies(id) ON DELETE CASCADE;
ALTER TABLE ONLY analytics_devops_adoption_segments
ADD CONSTRAINT fk_f5aa768998 FOREIGN KEY (namespace_id) REFERENCES namespaces(id) ON DELETE CASCADE;

View File

@ -1195,6 +1195,8 @@ There are two ways to fix this:
###### Environment variable overrides
> Multiple databases support was [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/133177) in GitLab 16.5.
By default, GitLab uses the database configuration stored in a
configuration file (`database.yml`). However, you can override the database settings
for the backup and restore task by setting environment
@ -1218,6 +1220,15 @@ and port 5432 with the Linux package (Omnibus):
sudo GITLAB_BACKUP_PGHOST=192.168.1.10 GITLAB_BACKUP_PGPORT=5432 /opt/gitlab/bin/gitlab-backup create
```
If you run GitLab on [multiple databases](../postgresql/multiple_databases.md), you can override database settings by including
the database name in the environment variable. For example if your `main` and `ci` databases are
hosted on different database servers, you would append their name after the `GITLAB_BACKUP_` prefix,
leaving the `PG*` names as is:
```shell
sudo GITLAB_BACKUP_MAIN_PGHOST=192.168.1.10 GITLAB_BACKUP_CI_PGHOST=192.168.1.12 /opt/gitlab/bin/gitlab-backup create
```
See the [PostgreSQL documentation](https://www.postgresql.org/docs/12/libpq-envars.html)
for more details on what these parameters do.

View File

@ -7954,6 +7954,30 @@ The edge type for [`Achievement`](#achievement).
| <a id="achievementedgecursor"></a>`cursor` | [`String!`](#string) | A cursor for use in pagination. |
| <a id="achievementedgenode"></a>`node` | [`Achievement`](#achievement) | The item at the end of the edge. |
#### `AddOnUserConnection`
The connection type for [`AddOnUser`](#addonuser).
##### Fields
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="addonuserconnectioncount"></a>`count` | [`Int!`](#int) | Total count of collection. |
| <a id="addonuserconnectionedges"></a>`edges` | [`[AddOnUserEdge]`](#addonuseredge) | A list of edges. |
| <a id="addonuserconnectionnodes"></a>`nodes` | [`[AddOnUser]`](#addonuser) | A list of nodes. |
| <a id="addonuserconnectionpageinfo"></a>`pageInfo` | [`PageInfo!`](#pageinfo) | Information to aid in pagination. |
#### `AddOnUserEdge`
The edge type for [`AddOnUser`](#addonuser).
##### Fields
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="addonuseredgecursor"></a>`cursor` | [`String!`](#string) | A cursor for use in pagination. |
| <a id="addonuseredgenode"></a>`node` | [`AddOnUser`](#addonuser) | The item at the end of the edge. |
#### `AgentConfigurationConnection`
The connection type for [`AgentConfiguration`](#agentconfiguration).
@ -12854,6 +12878,8 @@ A user with add-on data.
| <a id="addonuserid"></a>`id` | [`ID!`](#id) | ID of the user. |
| <a id="addonuseride"></a>`ide` | [`Ide`](#ide) | IDE settings. |
| <a id="addonuserjobtitle"></a>`jobTitle` | [`String`](#string) | Job title of the user. |
| <a id="addonuserlastactivityon"></a>`lastActivityOn` | [`Date`](#date) | Date the user last performed any actions. |
| <a id="addonuserlastloginat"></a>`lastLoginAt` | [`Time`](#time) | Timestamp of the last sign in. |
| <a id="addonuserlinkedin"></a>`linkedin` | [`String`](#string) | LinkedIn profile name of the user. |
| <a id="addonuserlocation"></a>`location` | [`String`](#string) | Location of the user. |
| <a id="addonusername"></a>`name` | [`String!`](#string) | Human-readable name of the user. Returns `****` if the user is a project bot and the requester does not have permission to view the project. |
@ -13207,7 +13233,6 @@ Describes an alert from the project's Alert Management.
| <a id="alertmanagementalertissueiid"></a>`issueIid` **{warning-solid}** | [`ID`](#id) | **Deprecated** in 13.10. Use issue field. |
| <a id="alertmanagementalertmetricsdashboardurl"></a>`metricsDashboardUrl` **{warning-solid}** | [`String`](#string) | **Deprecated** in 16.0. Returns no data. Underlying feature was removed in 16.0. |
| <a id="alertmanagementalertmonitoringtool"></a>`monitoringTool` | [`String`](#string) | Monitoring tool the alert came from. |
| <a id="alertmanagementalertnotes"></a>`notes` | [`NoteConnection!`](#noteconnection) | All notes on this noteable. (see [Connections](#connections)) |
| <a id="alertmanagementalertprometheusalert"></a>`prometheusAlert` | [`PrometheusAlert`](#prometheusalert) | Alert condition for Prometheus. |
| <a id="alertmanagementalertrunbook"></a>`runbook` | [`String`](#string) | Runbook for the alert as defined in alert details. |
| <a id="alertmanagementalertservice"></a>`service` | [`String`](#string) | Service the alert came from. |
@ -13220,6 +13245,22 @@ Describes an alert from the project's Alert Management.
#### Fields with arguments
##### `AlertManagementAlert.notes`
All notes on this noteable.
Returns [`NoteConnection!`](#noteconnection).
This field returns a [connection](#connections). It accepts the
four standard [pagination arguments](#connection-pagination-arguments):
`before: String`, `after: String`, `first: Int`, `last: Int`.
###### Arguments
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="alertmanagementalertnotesfilter"></a>`filter` | [`NotesFilterType`](#notesfiltertype) | Type of notes collection: ALL_NOTES, ONLY_COMMENTS, ONLY_ACTIVITY. |
##### `AlertManagementAlert.todos`
To-do items of the current user for the alert.
@ -13905,7 +13946,6 @@ Represents an epic on an issue board.
| <a id="boardepiciid"></a>`iid` | [`ID!`](#id) | Internal ID of the epic. |
| <a id="boardepicissues"></a>`issues` | [`EpicIssueConnection`](#epicissueconnection) | A list of issues associated with the epic. (see [Connections](#connections)) |
| <a id="boardepiclabels"></a>`labels` | [`LabelConnection`](#labelconnection) | Labels assigned to the epic. (see [Connections](#connections)) |
| <a id="boardepicnotes"></a>`notes` | [`NoteConnection!`](#noteconnection) | All notes on this noteable. (see [Connections](#connections)) |
| <a id="boardepicparent"></a>`parent` | [`Epic`](#epic) | Parent epic of the epic. |
| <a id="boardepicparticipants"></a>`participants` | [`UserCoreConnection`](#usercoreconnection) | List of participants for the epic. (see [Connections](#connections)) |
| <a id="boardepicrelationpath"></a>`relationPath` | [`String`](#string) | URI path of the epic-issue relationship. |
@ -14021,6 +14061,22 @@ four standard [pagination arguments](#connection-pagination-arguments):
| ---- | ---- | ----------- |
| <a id="boardepiccurrentusertodosstate"></a>`state` | [`TodoStateEnum`](#todostateenum) | State of the to-do items. |
##### `BoardEpic.notes`
All notes on this noteable.
Returns [`NoteConnection!`](#noteconnection).
This field returns a [connection](#connections). It accepts the
four standard [pagination arguments](#connection-pagination-arguments):
`before: String`, `after: String`, `first: Int`, `last: Int`.
###### Arguments
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="boardepicnotesfilter"></a>`filter` | [`NotesFilterType`](#notesfiltertype) | Type of notes collection: ALL_NOTES, ONLY_COMMENTS, ONLY_ACTIVITY. |
##### `BoardEpic.reference`
Internal reference of the epic. Returned in shortened format by default.
@ -15904,7 +15960,6 @@ A single design.
| <a id="designimage"></a>`image` | [`String!`](#string) | URL of the full-sized image. |
| <a id="designimagev432x230"></a>`imageV432x230` | [`String`](#string) | The URL of the design resized to fit within the bounds of 432x230. This will be `null` if the image has not been generated. |
| <a id="designissue"></a>`issue` | [`Issue!`](#issue) | Issue the design belongs to. |
| <a id="designnotes"></a>`notes` | [`NoteConnection!`](#noteconnection) | All notes on this noteable. (see [Connections](#connections)) |
| <a id="designnotescount"></a>`notesCount` | [`Int!`](#int) | Total count of user-created notes for this design. |
| <a id="designproject"></a>`project` | [`Project!`](#project) | Project the design belongs to. |
| <a id="designweburl"></a>`webUrl` | [`String!`](#string) | URL of the design. |
@ -15927,6 +15982,22 @@ four standard [pagination arguments](#connection-pagination-arguments):
| ---- | ---- | ----------- |
| <a id="designcurrentusertodosstate"></a>`state` | [`TodoStateEnum`](#todostateenum) | State of the to-do items. |
##### `Design.notes`
All notes on this noteable.
Returns [`NoteConnection!`](#noteconnection).
This field returns a [connection](#connections). It accepts the
four standard [pagination arguments](#connection-pagination-arguments):
`before: String`, `after: String`, `first: Int`, `last: Int`.
###### Arguments
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="designnotesfilter"></a>`filter` | [`NotesFilterType`](#notesfiltertype) | Type of notes collection: ALL_NOTES, ONLY_COMMENTS, ONLY_ACTIVITY. |
##### `Design.versions`
All versions related to this design ordered newest first.
@ -16494,7 +16565,6 @@ Represents an epic.
| <a id="epiciid"></a>`iid` | [`ID!`](#id) | Internal ID of the epic. |
| <a id="epicissues"></a>`issues` | [`EpicIssueConnection`](#epicissueconnection) | A list of issues associated with the epic. (see [Connections](#connections)) |
| <a id="epiclabels"></a>`labels` | [`LabelConnection`](#labelconnection) | Labels assigned to the epic. (see [Connections](#connections)) |
| <a id="epicnotes"></a>`notes` | [`NoteConnection!`](#noteconnection) | All notes on this noteable. (see [Connections](#connections)) |
| <a id="epicparent"></a>`parent` | [`Epic`](#epic) | Parent epic of the epic. |
| <a id="epicparticipants"></a>`participants` | [`UserCoreConnection`](#usercoreconnection) | List of participants for the epic. (see [Connections](#connections)) |
| <a id="epicrelationpath"></a>`relationPath` | [`String`](#string) | URI path of the epic-issue relationship. |
@ -16609,6 +16679,22 @@ four standard [pagination arguments](#connection-pagination-arguments):
| ---- | ---- | ----------- |
| <a id="epiccurrentusertodosstate"></a>`state` | [`TodoStateEnum`](#todostateenum) | State of the to-do items. |
##### `Epic.notes`
All notes on this noteable.
Returns [`NoteConnection!`](#noteconnection).
This field returns a [connection](#connections). It accepts the
four standard [pagination arguments](#connection-pagination-arguments):
`before: String`, `after: String`, `first: Int`, `last: Int`.
###### Arguments
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="epicnotesfilter"></a>`filter` | [`NotesFilterType`](#notesfiltertype) | Type of notes collection: ALL_NOTES, ONLY_COMMENTS, ONLY_ACTIVITY. |
##### `Epic.reference`
Internal reference of the epic. Returned in shortened format by default.
@ -16744,7 +16830,6 @@ Relationship between an epic and an issue.
| <a id="epicissuemilestone"></a>`milestone` | [`Milestone`](#milestone) | Milestone of the issue. |
| <a id="epicissuemoved"></a>`moved` | [`Boolean`](#boolean) | Indicates if issue got moved from other project. |
| <a id="epicissuemovedto"></a>`movedTo` | [`Issue`](#issue) | Updated Issue after it got moved to another project. |
| <a id="epicissuenotes"></a>`notes` | [`NoteConnection!`](#noteconnection) | All notes on this noteable. (see [Connections](#connections)) |
| <a id="epicissueparticipants"></a>`participants` | [`UserCoreConnection`](#usercoreconnection) | List of participants in the issue. (see [Connections](#connections)) |
| <a id="epicissueprojectid"></a>`projectId` | [`Int!`](#int) | ID of the issue project. |
| <a id="epicissuerelatedmergerequests"></a>`relatedMergeRequests` | [`MergeRequestConnection`](#mergerequestconnection) | Merge requests related to the issue. This field can only be resolved for one issue in any single request. (see [Connections](#connections)) |
@ -16828,6 +16913,22 @@ four standard [pagination arguments](#connection-pagination-arguments):
| ---- | ---- | ----------- |
| <a id="epicissueissuableresourcelinksincidentid"></a>`incidentId` | [`IssueID!`](#issueid) | ID of the incident. |
##### `EpicIssue.notes`
All notes on this noteable.
Returns [`NoteConnection!`](#noteconnection).
This field returns a [connection](#connections). It accepts the
four standard [pagination arguments](#connection-pagination-arguments):
`before: String`, `after: String`, `first: Int`, `last: Int`.
###### Arguments
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="epicissuenotesfilter"></a>`filter` | [`NotesFilterType`](#notesfiltertype) | Type of notes collection: ALL_NOTES, ONLY_COMMENTS, ONLY_ACTIVITY. |
##### `EpicIssue.reference`
Internal reference of the issue. Returned in shortened format by default.
@ -17551,6 +17652,27 @@ four standard [pagination arguments](#connection-pagination-arguments):
| ---- | ---- | ----------- |
| <a id="groupachievementsids"></a>`ids` | [`[AchievementsAchievementID!]`](#achievementsachievementid) | Filter achievements by IDs. |
##### `Group.addOnEligibleUsers`
Users in the namespace hierarchy that add ons are applicable for. This only applies to root namespaces.
WARNING:
**Introduced** in 16.5.
This feature is an Experiment. It can be changed or removed at any time.
Returns [`AddOnUserConnection`](#addonuserconnection).
This field returns a [connection](#connections). It accepts the
four standard [pagination arguments](#connection-pagination-arguments):
`before: String`, `after: String`, `first: Int`, `last: Int`.
###### Arguments
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="groupaddoneligibleusersaddontype"></a>`addOnType` | [`GitlabSubscriptionsAddOnType!`](#gitlabsubscriptionsaddontype) | Type of add on to filter the eligible users by. |
| <a id="groupaddoneligibleuserssearch"></a>`search` | [`String`](#string) | Search the user list. |
##### `Group.addOnPurchase`
AddOnPurchase associated with the namespace.
@ -19043,7 +19165,6 @@ Describes an issuable resource link for incident issues.
| <a id="issuemilestone"></a>`milestone` | [`Milestone`](#milestone) | Milestone of the issue. |
| <a id="issuemoved"></a>`moved` | [`Boolean`](#boolean) | Indicates if issue got moved from other project. |
| <a id="issuemovedto"></a>`movedTo` | [`Issue`](#issue) | Updated Issue after it got moved to another project. |
| <a id="issuenotes"></a>`notes` | [`NoteConnection!`](#noteconnection) | All notes on this noteable. (see [Connections](#connections)) |
| <a id="issueparticipants"></a>`participants` | [`UserCoreConnection`](#usercoreconnection) | List of participants in the issue. (see [Connections](#connections)) |
| <a id="issueprojectid"></a>`projectId` | [`Int!`](#int) | ID of the issue project. |
| <a id="issuerelatedmergerequests"></a>`relatedMergeRequests` | [`MergeRequestConnection`](#mergerequestconnection) | Merge requests related to the issue. This field can only be resolved for one issue in any single request. (see [Connections](#connections)) |
@ -19126,6 +19247,22 @@ four standard [pagination arguments](#connection-pagination-arguments):
| ---- | ---- | ----------- |
| <a id="issueissuableresourcelinksincidentid"></a>`incidentId` | [`IssueID!`](#issueid) | ID of the incident. |
##### `Issue.notes`
All notes on this noteable.
Returns [`NoteConnection!`](#noteconnection).
This field returns a [connection](#connections). It accepts the
four standard [pagination arguments](#connection-pagination-arguments):
`before: String`, `after: String`, `first: Int`, `last: Int`.
###### Arguments
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="issuenotesfilter"></a>`filter` | [`NotesFilterType`](#notesfiltertype) | Type of notes collection: ALL_NOTES, ONLY_COMMENTS, ONLY_ACTIVITY. |
##### `Issue.reference`
Internal reference of the issue. Returned in shortened format by default.
@ -19543,7 +19680,6 @@ Defines which user roles, users, or groups can merge into a protected branch.
| <a id="mergerequestmergeablediscussionsstate"></a>`mergeableDiscussionsState` | [`Boolean`](#boolean) | Indicates if all discussions in the merge request have been resolved, allowing the merge request to be merged. |
| <a id="mergerequestmergedat"></a>`mergedAt` | [`Time`](#time) | Timestamp of when the merge request was merged, null if not merged. |
| <a id="mergerequestmilestone"></a>`milestone` | [`Milestone`](#milestone) | Milestone of the merge request. |
| <a id="mergerequestnotes"></a>`notes` | [`NoteConnection!`](#noteconnection) | All notes on this noteable. (see [Connections](#connections)) |
| <a id="mergerequestparticipants"></a>`participants` | [`MergeRequestParticipantConnection`](#mergerequestparticipantconnection) | Participants in the merge request. This includes the author, assignees, reviewers, and users mentioned in notes. (see [Connections](#connections)) |
| <a id="mergerequestpreparedat"></a>`preparedAt` | [`Time`](#time) | Timestamp of when the merge request was prepared. |
| <a id="mergerequestproject"></a>`project` | [`Project!`](#project) | Alias for target_project. |
@ -19629,6 +19765,22 @@ Returns [`FindingReportsComparer`](#findingreportscomparer).
| ---- | ---- | ----------- |
| <a id="mergerequestfindingreportscomparerreporttype"></a>`reportType` | [`ComparableSecurityReportType!`](#comparablesecurityreporttype) | Filter vulnerability findings by report type. |
##### `MergeRequest.notes`
All notes on this noteable.
Returns [`NoteConnection!`](#noteconnection).
This field returns a [connection](#connections). It accepts the
four standard [pagination arguments](#connection-pagination-arguments):
`before: String`, `after: String`, `first: Int`, `last: Int`.
###### Arguments
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="mergerequestnotesfilter"></a>`filter` | [`NotesFilterType`](#notesfiltertype) | Type of notes collection: ALL_NOTES, ONLY_COMMENTS, ONLY_ACTIVITY. |
##### `MergeRequest.pipelines`
Pipelines for the merge request. Note: for performance reasons, no more than the most recent 500 pipelines will be returned.
@ -21026,6 +21178,27 @@ four standard [pagination arguments](#connection-pagination-arguments):
| ---- | ---- | ----------- |
| <a id="namespaceachievementsids"></a>`ids` | [`[AchievementsAchievementID!]`](#achievementsachievementid) | Filter achievements by IDs. |
##### `Namespace.addOnEligibleUsers`
Users in the namespace hierarchy that add ons are applicable for. This only applies to root namespaces.
WARNING:
**Introduced** in 16.5.
This feature is an Experiment. It can be changed or removed at any time.
Returns [`AddOnUserConnection`](#addonuserconnection).
This field returns a [connection](#connections). It accepts the
four standard [pagination arguments](#connection-pagination-arguments):
`before: String`, `after: String`, `first: Int`, `last: Int`.
###### Arguments
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="namespaceaddoneligibleusersaddontype"></a>`addOnType` | [`GitlabSubscriptionsAddOnType!`](#gitlabsubscriptionsaddontype) | Type of add on to filter the eligible users by. |
| <a id="namespaceaddoneligibleuserssearch"></a>`search` | [`String`](#string) | Search the user list. |
##### `Namespace.addOnPurchase`
AddOnPurchase associated with the namespace.
@ -24773,7 +24946,6 @@ Represents a snippet entry.
| <a id="snippetfilename"></a>`fileName` | [`String`](#string) | File Name of the snippet. |
| <a id="snippethttpurltorepo"></a>`httpUrlToRepo` | [`String`](#string) | HTTP URL to the snippet repository. |
| <a id="snippetid"></a>`id` | [`SnippetID!`](#snippetid) | ID of the snippet. |
| <a id="snippetnotes"></a>`notes` | [`NoteConnection!`](#noteconnection) | All notes on this noteable. (see [Connections](#connections)) |
| <a id="snippetproject"></a>`project` | [`Project`](#project) | Project the snippet is associated with. |
| <a id="snippetrawurl"></a>`rawUrl` | [`String!`](#string) | Raw URL of the snippet. |
| <a id="snippetsshurltorepo"></a>`sshUrlToRepo` | [`String`](#string) | SSH URL to the snippet repository. |
@ -24801,6 +24973,22 @@ four standard [pagination arguments](#connection-pagination-arguments):
| ---- | ---- | ----------- |
| <a id="snippetblobspaths"></a>`paths` | [`[String!]`](#string) | Paths of the blobs. |
##### `Snippet.notes`
All notes on this noteable.
Returns [`NoteConnection!`](#noteconnection).
This field returns a [connection](#connections). It accepts the
four standard [pagination arguments](#connection-pagination-arguments):
`before: String`, `after: String`, `first: Int`, `last: Int`.
###### Arguments
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="snippetnotesfilter"></a>`filter` | [`NotesFilterType`](#notesfiltertype) | Type of notes collection: ALL_NOTES, ONLY_COMMENTS, ONLY_ACTIVITY. |
### `SnippetBlob`
Represents the snippet blob.
@ -25788,7 +25976,6 @@ Represents a vulnerability.
| <a id="vulnerabilitylocation"></a>`location` | [`VulnerabilityLocation`](#vulnerabilitylocation) | Location metadata for the vulnerability. Its fields depend on the type of security scan that found the vulnerability. |
| <a id="vulnerabilitymergerequest"></a>`mergeRequest` | [`MergeRequest`](#mergerequest) | Merge request that fixes the vulnerability. |
| <a id="vulnerabilitymessage"></a>`message` **{warning-solid}** | [`String`](#string) | **Deprecated** in 16.1. message field has been removed from security reports schema. |
| <a id="vulnerabilitynotes"></a>`notes` | [`NoteConnection!`](#noteconnection) | All notes on this noteable. (see [Connections](#connections)) |
| <a id="vulnerabilityprimaryidentifier"></a>`primaryIdentifier` | [`VulnerabilityIdentifier`](#vulnerabilityidentifier) | Primary identifier of the vulnerability. |
| <a id="vulnerabilityproject"></a>`project` | [`Project`](#project) | Project on which the vulnerability was found. |
| <a id="vulnerabilityreporttype"></a>`reportType` | [`VulnerabilityReportType`](#vulnerabilityreporttype) | Type of the security report that found the vulnerability (SAST, DEPENDENCY_SCANNING, CONTAINER_SCANNING, DAST, SECRET_DETECTION, COVERAGE_FUZZING, API_FUZZING, CLUSTER_IMAGE_SCANNING, GENERIC). `Scan Type` in the UI. |
@ -25827,6 +26014,22 @@ four standard [pagination arguments](#connection-pagination-arguments):
| ---- | ---- | ----------- |
| <a id="vulnerabilityissuelinkslinktype"></a>`linkType` | [`VulnerabilityIssueLinkType`](#vulnerabilityissuelinktype) | Filter issue links by link type. |
##### `Vulnerability.notes`
All notes on this noteable.
Returns [`NoteConnection!`](#noteconnection).
This field returns a [connection](#connections). It accepts the
four standard [pagination arguments](#connection-pagination-arguments):
`before: String`, `after: String`, `first: Int`, `last: Int`.
###### Arguments
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="vulnerabilitynotesfilter"></a>`filter` | [`NotesFilterType`](#notesfiltertype) | Type of notes collection: ALL_NOTES, ONLY_COMMENTS, ONLY_ACTIVITY. |
### `VulnerabilityContainerImage`
Represents a container image reported on the related vulnerability.
@ -27922,6 +28125,14 @@ Geo registry class.
| <a id="georegistryclassterraform_state_version_registry"></a>`TERRAFORM_STATE_VERSION_REGISTRY` | Geo::TerraformStateVersionRegistry registry class. |
| <a id="georegistryclassupload_registry"></a>`UPLOAD_REGISTRY` | Geo::UploadRegistry registry class. |
### `GitlabSubscriptionsAddOnType`
Types of add-ons.
| Value | Description |
| ----- | ----------- |
| <a id="gitlabsubscriptionsaddontypecode_suggestions"></a>`CODE_SUGGESTIONS` | Code suggestions seat add-on. |
### `GitlabSubscriptionsUserRole`
Role of User.
@ -30600,7 +30811,24 @@ Implementations:
| ---- | ---- | ----------- |
| <a id="noteableinterfacecommenters"></a>`commenters` | [`UserCoreConnection!`](#usercoreconnection) | All commenters on this noteable. (see [Connections](#connections)) |
| <a id="noteableinterfacediscussions"></a>`discussions` | [`DiscussionConnection!`](#discussionconnection) | All discussions on this noteable. (see [Connections](#connections)) |
| <a id="noteableinterfacenotes"></a>`notes` | [`NoteConnection!`](#noteconnection) | All notes on this noteable. (see [Connections](#connections)) |
##### Fields with arguments
###### `NoteableInterface.notes`
All notes on this noteable.
Returns [`NoteConnection!`](#noteconnection).
This field returns a [connection](#connections). It accepts the
four standard [pagination arguments](#connection-pagination-arguments):
`before: String`, `after: String`, `first: Int`, `last: Int`.
####### Arguments
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="noteableinterfacenotesfilter"></a>`filter` | [`NotesFilterType`](#notesfiltertype) | Type of notes collection: ALL_NOTES, ONLY_COMMENTS, ONLY_ACTIVITY. |
#### `OrchestrationPolicy`

View File

@ -231,9 +231,9 @@ Parameters:
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `new_issue_url` | string | true | New Issue URL |
| `issues_url` | string | true | Issue URL |
| `project_url` | string | true | Project URL |
| `new_issue_url` | string | true | New issue URL. |
| `issues_url` | string | true | Issue URL. |
| `project_url` | string | true | Project URL. |
### Disable Bugzilla
@ -371,7 +371,7 @@ Parameters:
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `confluence_url` | string | true | The URL of the Confluence Cloud Workspace hosted on atlassian.net. |
| `confluence_url` | string | true | The URL of the Confluence Workspace hosted on `atlassian.net`. |
### Disable Confluence Workspace
@ -403,9 +403,9 @@ Parameters:
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `new_issue_url` | string | true | New Issue URL |
| `issues_url` | string | true | Issue URL |
| `project_url` | string | true | Project URL |
| `new_issue_url` | string | true | New issue URL. |
| `issues_url` | string | true | Issue URL. |
| `project_url` | string | true | Project URL. |
### Disable a custom issue tracker
@ -438,12 +438,12 @@ Parameters:
| Parameter | Type | Required | Description |
|------------------------|---------|----------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `api_key` | string | true | API key used for authentication with Datadog. |
| `api_url` | string | false | (Advanced) The full URL for your Datadog site |
| `datadog_env` | string | false | For self-managed deployments, set the env% tag for all the data sent to Datadog. |
| `datadog_service` | string | false | Tag all data from this GitLab instance in Datadog. Useful when managing several self-managed deployments |
| `datadog_site` | string | false | The Datadog site to send data to. To send data to the EU site, use `datadoghq.eu` |
| `datadog_tags` | string | false | Custom tags in Datadog. Specify one tag per line in the format: `key:value\nkey2:value2` ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/79665) in GitLab 14.8.) |
| `archive_trace_events` | boolean | false | When enabled, job logs are collected by Datadog and displayed along with pipeline execution traces ([introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/346339) in GitLab 15.3) |
| `api_url` | string | false | (Advanced) The full URL for your Datadog site. |
| `datadog_env` | string | false | For self-managed deployments, set the `env%` tag for all the data sent to Datadog. |
| `datadog_service` | string | false | Tag all data from this GitLab instance in Datadog. Can be used when managing several self-managed deployments. |
| `datadog_site` | string | false | The Datadog site to send data to. To send data to the EU site, use `datadoghq.eu`. |
| `datadog_tags` | string | false | Custom tags in Datadog. Specify one tag per line in the format `key:value\nkey2:value2` ([introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/79665) in GitLab 14.8.). |
| `archive_trace_events` | boolean | false | When enabled, job logs are collected by Datadog and displayed along with pipeline execution traces ([introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/346339) in GitLab 15.3). |
### Disable Datadog
@ -480,24 +480,24 @@ Parameters:
| `webhook` | string | true | Discord webhook (for example, `https://discord.com/api/webhooks/…`). |
| `branches_to_be_notified` | string | false | Branches to send notifications for. Valid options are `all`, `default`, `protected`, and `default_and_protected`. The default value is `default`. |
| `confidential_issues_events` | boolean | false | Enable notifications for confidential issue events. |
| `confidential_issue_channel` | string | false | The webhook override to receive confidential issues events notifications. |
| `confidential_issue_channel` | string | false | The webhook override to receive notifications for confidential issue events. |
| `confidential_note_events` | boolean | false | Enable notifications for confidential note events. |
| `confidential_note_channel` | string | false | The webhook override to receive confidential note events notifications. |
| `confidential_note_channel` | string | false | The webhook override to receive notifications for confidential note events. |
| `issues_events` | boolean | false | Enable notifications for issue events. |
| `issue_channel` | string | false | The webhook override to receive issues events notifications. |
| `issue_channel` | string | false | The webhook override to receive notifications for issue events. |
| `merge_requests_events` | boolean | false | Enable notifications for merge request events. |
| `merge_request_channel` | string | false | The webhook override to receive merge request events notifications. |
| `merge_request_channel` | string | false | The webhook override to receive notifications for merge request events. |
| `note_events` | boolean | false | Enable notifications for note events. |
| `note_channel` | string | false | The webhook override to receive note events notifications. |
| `note_channel` | string | false | The webhook override to receive notifications for note events. |
| `notify_only_broken_pipelines` | boolean | false | Send notifications for broken pipelines. |
| `pipeline_events` | boolean | false | Enable notifications for pipeline events. |
| `pipeline_channel` | string | false | The webhook override to receive pipeline events notifications. |
| `pipeline_channel` | string | false | The webhook override to receive notifications for pipeline events. |
| `push_events` | boolean | false | Enable notifications for push events. |
| `push_channel` | string | false | The webhook override to receive push events notifications. |
| `push_channel` | string | false | The webhook override to receive notifications for push events. |
| `tag_push_events` | boolean | false | Enable notifications for tag push events. |
| `tag_push_channel` | string | false | The webhook override to receive tag push events notifications. |
| `tag_push_channel` | string | false | The webhook override to receive notifications for tag push events. |
| `wiki_page_events` | boolean | false | Enable notifications for wiki page events. |
| `wiki_page_channel` | string | false | The webhook override to receive wiki page events notifications. |
| `wiki_page_channel` | string | false | The webhook override to receive notifications for wiki page events. |
### Disable Discord Notifications
@ -637,7 +637,7 @@ Parameters:
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `external_wiki_url` | string | true | The URL of the external wiki |
| `external_wiki_url` | string | true | The URL of the external wiki. |
### Disable an external wiki
@ -707,33 +707,33 @@ Parameters:
| `username` | string | false | username. |
| `channel` | string | false | Default channel to use if others are not configured. |
| `notify_only_broken_pipelines` | boolean | false | Send notifications for broken pipelines. |
| `notify_only_default_branch` | boolean | false | DEPRECATED: This parameter has been replaced with `branches_to_be_notified`. |
| `notify_only_default_branch` | boolean | false | **Deprecated:** This parameter has been replaced with `branches_to_be_notified`. |
| `branches_to_be_notified` | string | false | Branches to send notifications for. Valid options are `all`, `default`, `protected`, and `default_and_protected`. The default value is `default`. |
| `alert_channel` | string | false | The name of the channel to receive alert events notifications. |
| `alert_channel` | string | false | The name of the channel to receive notifications for alert events. |
| `alert_events` | boolean | false | Enable notifications for alert events. |
| `commit_events` | boolean | false | Enable notifications for commit events. |
| `confidential_issue_channel` | string | false | The name of the channel to receive confidential issues events notifications. |
| `confidential_issue_channel` | string | false | The name of the channel to receive notifications for confidential issue events. |
| `confidential_issues_events` | boolean | false | Enable notifications for confidential issue events. |
| `confidential_note_channel` | string | false | The name of the channel to receive confidential note events notifications. |
| `confidential_note_channel` | string | false | The name of the channel to receive notifications for confidential note events. |
| `confidential_note_events` | boolean | false | Enable notifications for confidential note events. |
| `deployment_channel` | string | false | The name of the channel to receive deployment events notifications. |
| `deployment_channel` | string | false | The name of the channel to receive notifications for deployment events. |
| `deployment_events` | boolean | false | Enable notifications for deployment events. |
| `incident_channel` | string | false | The name of the channel to receive incidents events notifications. |
| `incident_channel` | string | false | The name of the channel to receive notifications for incident events. |
| `incidents_events` | boolean | false | Enable notifications for incident events. |
| `issue_channel` | string | false | The name of the channel to receive issues events notifications. |
| `issue_channel` | string | false | The name of the channel to receive notifications for issue events. |
| `issues_events` | boolean | false | Enable notifications for issue events. |
| `job_events` | boolean | false | Enable notifications for job events. |
| `merge_request_channel` | string | false | The name of the channel to receive merge request events notifications. |
| `merge_request_channel` | string | false | The name of the channel to receive notifications for merge request events. |
| `merge_requests_events` | boolean | false | Enable notifications for merge request events. |
| `note_channel` | string | false | The name of the channel to receive note events notifications. |
| `note_channel` | string | false | The name of the channel to receive notifications for note events. |
| `note_events` | boolean | false | Enable notifications for note events. |
| `pipeline_channel` | string | false | The name of the channel to receive pipeline events notifications. |
| `pipeline_channel` | string | false | The name of the channel to receive notifications for pipeline events. |
| `pipeline_events` | boolean | false | Enable notifications for pipeline events. |
| `push_channel` | string | false | The name of the channel to receive push events notifications. |
| `push_channel` | string | false | The name of the channel to receive notifications for push events. |
| `push_events` | boolean | false | Enable notifications for push events. |
| `tag_push_channel` | string | false | The name of the channel to receive tag push events notifications. |
| `tag_push_channel` | string | false | The name of the channel to receive notifications for tag push events. |
| `tag_push_events` | boolean | false | Enable notifications for tag push events. |
| `wiki_page_channel` | string | false | The name of the channel to receive wiki page events notifications. |
| `wiki_page_channel` | string | false | The name of the channel to receive notifications for wiki page events. |
| `wiki_page_events` | boolean | false | Enable notifications for wiki page events. |
### Disable the GitLab for Slack app
@ -768,7 +768,7 @@ Parameters:
| --------- | ---- | -------- | ----------- |
| `webhook` | string | true | The Hangouts Chat webhook (for example, `https://chat.googleapis.com/v1/spaces...`). |
| `notify_only_broken_pipelines` | boolean | false | Send notifications for broken pipelines. |
| `notify_only_default_branch` | boolean | false | DEPRECATED: This parameter has been replaced with `branches_to_be_notified`. |
| `notify_only_default_branch` | boolean | false | **Deprecated:** This parameter has been replaced with `branches_to_be_notified`. |
| `branches_to_be_notified` | string | false | Branches to send notifications for. Valid options are `all`, `default`, `protected`, and `default_and_protected`. The default value is `default`. |
| `push_events` | boolean | false | Enable notifications for push events. |
| `issues_events` | boolean | false | Enable notifications for issue events. |
@ -810,11 +810,11 @@ Parameters:
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `recipients` | string | true | Recipients/channels separated by whitespaces |
| `default_irc_uri` | string | false | `irc://irc.network.net:6697/` |
| `server_host` | string | false | localhost |
| `server_port` | integer | false | 6659 |
| `colorize_messages` | boolean | false | Colorize messages |
| `recipients` | string | true | Recipients or channels separated by whitespaces. |
| `default_irc_uri` | string | false | `irc://irc.network.net:6697/`. |
| `server_host` | string | false | localhost. |
| `server_port` | integer | false | 6659. |
| `colorize_messages` | boolean | false | Colorize messages. |
### Disable irker
@ -938,7 +938,7 @@ Parameters:
| `jira_issue_transition_id` | string | no | The ID of one or more transitions for [custom issue transitions](../integration/jira/issues.md#custom-issue-transitions). Ignored if `jira_issue_transition_automatic` is enabled. Defaults to a blank string, which disables custom transitions. |
| `commit_events` | boolean | false | Enable notifications for commit events. |
| `merge_requests_events` | boolean | false | Enable notifications for merge request events. |
| `comment_on_event_enabled` | boolean | false | Enable comments inside Jira issues on each GitLab event (commit / merge request). |
| `comment_on_event_enabled` | boolean | false | Enable comments in Jira issues on each GitLab event (commit or merge request). |
### Disable Jira
@ -974,7 +974,7 @@ Parameters:
| `username` | string | false | username. |
| `channel` | string | false | Default channel to use if others are not configured. |
| `notify_only_broken_pipelines` | boolean | false | Send notifications for broken pipelines. |
| `notify_only_default_branch` | boolean | false | DEPRECATED: This parameter has been replaced with `branches_to_be_notified`. |
| `notify_only_default_branch` | boolean | false | **Deprecated:** This parameter has been replaced with `branches_to_be_notified`. |
| `branches_to_be_notified` | string | false | Branches to send notifications for. Valid options are `all`, `default`, `protected`, and `default_and_protected`. The default value is `default`. |
| `push_events` | boolean | false | Enable notifications for push events. |
| `issues_events` | boolean | false | Enable notifications for issue events. |
@ -985,15 +985,15 @@ Parameters:
| `confidential_note_events` | boolean | false | Enable notifications for confidential note events. |
| `pipeline_events` | boolean | false | Enable notifications for pipeline events. |
| `wiki_page_events` | boolean | false | Enable notifications for wiki page events. |
| `push_channel` | string | false | The name of the channel to receive push events notifications. |
| `issue_channel` | string | false | The name of the channel to receive issues events notifications. |
| `confidential_issue_channel` | string | false | The name of the channel to receive confidential issues events notifications. |
| `merge_request_channel` | string | false | The name of the channel to receive merge request events notifications. |
| `note_channel` | string | false | The name of the channel to receive note events notifications. |
| `confidential_note_channel` | string | false | The name of the channel to receive confidential note events notifications. |
| `tag_push_channel` | string | false | The name of the channel to receive tag push events notifications. |
| `pipeline_channel` | string | false | The name of the channel to receive pipeline events notifications. |
| `wiki_page_channel` | string | false | The name of the channel to receive wiki page events notifications. |
| `push_channel` | string | false | The name of the channel to receive notifications for push events. |
| `issue_channel` | string | false | The name of the channel to receive notifications for issue events. |
| `confidential_issue_channel` | string | false | The name of the channel to receive notifications for confidential issue events. |
| `merge_request_channel` | string | false | The name of the channel to receive notifications for merge request events. |
| `note_channel` | string | false | The name of the channel to receive notifications for note events. |
| `confidential_note_channel` | string | false | The name of the channel to receive notifications for confidential note events. |
| `tag_push_channel` | string | false | The name of the channel to receive notifications for tag push events. |
| `pipeline_channel` | string | false | The name of the channel to receive notifications for pipeline events. |
| `wiki_page_channel` | string | false | The name of the channel to receive notifications for wiki page events. |
### Disable Mattermost notifications
@ -1059,7 +1059,7 @@ Parameters:
| --------- | ---- | -------- | ----------- |
| `webhook` | string | true | The Microsoft Teams webhook (for example, `https://outlook.office.com/webhook/...`). |
| `notify_only_broken_pipelines` | boolean | false | Send notifications for broken pipelines. |
| `notify_only_default_branch` | boolean | false | DEPRECATED: This parameter has been replaced with `branches_to_be_notified`. |
| `notify_only_default_branch` | boolean | false | **Deprecated:** This parameter has been replaced with `branches_to_be_notified`. |
| `branches_to_be_notified` | string | false | Branches to send notifications for. Valid options are `all`, `default`, `protected`, and `default_and_protected`. The default value is `default`. |
| `push_events` | boolean | false | Enable notifications for push events. |
| `issues_events` | boolean | false | Enable notifications for issue events. |
@ -1175,9 +1175,9 @@ Parameters:
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `recipients` | string | yes | Comma-separated list of recipient email addresses. |
| `notify_only_broken_pipelines` | boolean | no | Notify only broken pipelines. |
| `notify_only_broken_pipelines` | boolean | no | Send notifications for broken pipelines. |
| `branches_to_be_notified` | string | false | Branches to send notifications for. Valid options are `all`, `default`, `protected`, and `default_and_protected`. The default value is `default`. |
| `notify_only_default_branch` | boolean | no | Send notifications only for the default branch. |
| `notify_only_default_branch` | boolean | no | Send notifications for the default branch. |
| `pipeline_events` | boolean | false | Enable notifications for pipeline events. |
### Disable pipeline status emails
@ -1322,7 +1322,7 @@ Parameters:
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `new_issue_url` | string | true | New Issue URL. |
| `new_issue_url` | string | true | New issue URL. |
| `project_url` | string | true | Project URL. |
| `issues_url` | string | true | Issue URL. |
@ -1416,7 +1416,7 @@ Parameters:
| Parameter | Type | Required | Description |
|-------------------------|--------|----------|-------------------------------|
| `url` | string | yes | URL of the Squash TM webhook. |
| `token` | string | no | Optional token |
| `token` | string | no | Optional token. |
### Disable Squash TM
@ -1449,17 +1449,17 @@ Parameters:
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `token` | string | true | The Telegram bot token (for example, `123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11`). |
| `room` | string | true | Unique identifier for the target chat or the username of the target channel (in the format `@channelusername`) |
| `notify_only_broken_pipelines` | boolean | false | Send notifications for broken pipelines |
| `push_events` | boolean | true | Enable notifications for push events |
| `issues_events` | boolean | true | Enable notifications for issue events |
| `confidential_issues_events` | boolean | true | Enable notifications for confidential issue events |
| `merge_requests_events` | boolean | true | Enable notifications for merge request events |
| `tag_push_events` | boolean | true | Enable notifications for tag push events |
| `note_events` | boolean | true | Enable notifications for note events |
| `confidential_note_events` | boolean | true | Enable notifications for confidential note events |
| `pipeline_events` | boolean | true | Enable notifications for pipeline events |
| `wiki_page_events` | boolean | true | Enable notifications for wiki page events |
| `room` | string | true | Unique identifier for the target chat or the username of the target channel (in the format `@channelusername`). |
| `notify_only_broken_pipelines` | boolean | false | Send notifications for broken pipelines. |
| `push_events` | boolean | true | Enable notifications for push events. |
| `issues_events` | boolean | true | Enable notifications for issue events. |
| `confidential_issues_events` | boolean | true | Enable notifications for confidential issue events. |
| `merge_requests_events` | boolean | true | Enable notifications for merge request events. |
| `tag_push_events` | boolean | true | Enable notifications for tag push events. |
| `note_events` | boolean | true | Enable notifications for note events. |
| `confidential_note_events` | boolean | true | Enable notifications for confidential note events. |
| `pipeline_events` | boolean | true | Enable notifications for pipeline events. |
| `wiki_page_events` | boolean | true | Enable notifications for wiki page events. |
### Disable Telegram

View File

@ -8,10 +8,11 @@ info: To determine the technical writer assigned to the Stage/Group associated w
Notes are comments on:
- Snippets
- Issues
- Merge requests
- [Commits](../user/project/repository/index.md#commit-changes-to-a-repository)
- [Epics](../user/group/epics/index.md)
- [Issues](../user/project/issues/index.md)
- [Merge requests](../user/project/merge_requests/index.md)
- [Snippets](../user/snippets.md)
This includes system notes, which are notes about changes to the object (for example, when an
assignee changes, GitLab posts a system note).

View File

@ -7,81 +7,469 @@ type: index, howto
# Migrating from Jenkins **(FREE ALL)**
If you're migrating from Jenkins to GitLab CI/CD, you should be able
to create CI/CD pipelines that do everything you need.
If you're migrating from Jenkins to GitLab CI/CD, you are able to create CI/CD
pipelines that replicate and enhance your Jenkins workflows.
You can start by watching the [Migrating from Jenkins to GitLab](https://www.youtube.com/watch?v=RlEVGOpYF5Y)
video for examples of:
## Key similarities and differences
- Converting a Jenkins pipeline into a GitLab CI/CD pipeline.
- Using Auto DevOps to test your code automatically.
GitLab CI/CD and Jenkins are CI/CD tools with some similarities. Both GitLab
and Jenkins:
## Get started
- Use stages for collections of jobs.
- Support container-based builds.
The following list of recommended steps was created after observing organizations
that were able to quickly complete this migration.
Additionally, there are some important differences between the two:
Before doing any migration work, you should [start with a migration plan](plan_a_migration.md).
- GitLab CI/CD pipelines are all configured in a YAML format configuration file.
Jenkins uses either a Groovy format configuration file (declarative pipelines)
or Jenkins DSL (scripted pipelines).
- GitLab can run either on SaaS (cloud) or self-managed deployments. Jenkins deployments must be self-managed.
- GitLab provides source code management (SCM) out of the box. Jenkins requires a separate
SCM solution to store code.
- GitLab provides a built-in container registry. Jenkins requires a separate solution
for storing container images.
- GitLab provides built-in templates for scanning code. Jenkins requires 3rd party plugins
for scanning code.
Engineers that need to migrate projects to GitLab CI/CD should first review general
information about GitLab CI/CD:
## Comparison of features and concepts
- Read about some [key GitLab CI/CD features](#key-gitlab-cicd-features).
- Follow tutorials to create:
- [Your first GitLab pipeline](../quick_start/index.md).
- [A more complex pipeline](../quick_start/tutorial.md) that builds, tests,
and deploys a static site.
- Review the [`.gitlab-ci.yml` keyword reference](../yaml/index.md).
Many Jenkins features and concepts have equivalents in GitLab that offer the same
functionality.
Then you can begin the process of migrating to GitLab CI/CD:
### Configuration file
- Ensure [runners](../runners/index.md) are available, either by using shared GitLab.com runners
or installing new runners.
- Migrate build and CI jobs and configure them to show results directly in merge requests.
You can use [Auto DevOps](../../topics/autodevops/index.md) as a starting point,
and [customize](../../topics/autodevops/customize.md) or [decompose](../../topics/autodevops/customize.md#use-individual-components-of-auto-devops)
the configuration as needed.
- Migrate deployment jobs by using [cloud deployment templates](../cloud_deployment/index.md),
[environments](../environments/index.md), and the [GitLab agent for Kubernetes](../../user/clusters/agent/index.md).
- Check if any CI/CD configuration can be reused across different projects, then create
and share [templates](#templates).
- Check the [pipeline efficiency documentation](../pipelines/pipeline_efficiency.md)
to learn how to make your GitLab CI/CD pipelines faster and more efficient.
Jenkins can be configured with a [`Jenkinsfile` in the Groovy format](https://www.jenkins.io/doc/book/pipeline/jenkinsfile/). GitLab CI/CD uses a [`.gitlab-ci.yml` YAML file](../../ci/yaml/gitlab_ci_yaml.md) by default.
If you have questions that are not answered here, the [GitLab community forum](https://forum.gitlab.com/)
can be a great resource.
Example of a `Jenkinsfile`:
### Key GitLab CI/CD features
```groovy
pipeline {
agent any
GitLab CI/CD key features might be different or not exist in Jenkins. For example,
in GitLab:
stages {
stage('hello') {
steps {
echo "Hello World"
}
}
}
}
```
- Pipelines can be triggered with:
- A Git push
- A [Schedule](../pipelines/schedules.md)
- The [GitLab UI](../pipelines/index.md#run-a-pipeline-manually)
- An [API call](../triggers/index.md)
- A [webhook](../triggers/index.md#use-a-webhook)
- You can control which jobs run in which cases with the [`rules` syntax](../yaml/index.md#rules).
- You can reuse pipeline configurations:
- Use the [`extends` keyword](../yaml/index.md#extends) to reuse configuration
in a single pipeline configuration.
- Use the [`include` keyword](../yaml/index.md#include) to reuse configuration across
multiple pipelines and projects.
- Jobs are grouped into stages, and jobs in the same stage can run at the same time.
Stages run in sequence. Jobs can be configured to run outside of the stage ordering with the
[`needs` keyword](../yaml/index.md#needs).
- The [`parallel`](../yaml/index.md#parallel) keyword can automatically parallelize tasks,
especially tests that support parallelization.
- Jobs run independently of each other and have a fresh environment for each job.
Passing artifacts between jobs is controlled using the [`artifacts`](../yaml/index.md#artifacts)
and [`dependencies`](../yaml/index.md#dependencies) keywords.
- The `.gitlab-ci.yml` configuration file exists in your Git repository, like a `Jenkinsfile`,
but is [a YAML file](#yaml-configuration-file), not Groovy.
- GitLab comes with a [container registry](../../user/packages/container_registry/index.md).
You can build and store custom container images to run your jobs in.
The equivalent GitLab CI/CD `.gitlab-ci.yml` file would be:
## Runners
```yaml
stages:
- hello
hello-job:
stage: hello
script:
- echo "Hello World"
```
### Jenkins pipeline syntax
A Jenkins configuration is composed of a `pipeline` block with "sections" and "directives".
GitLab CI/CD has similar functionality, configured with YAML keywords.
#### Sections
| Jenkins | GitLab | Explanation |
|----------|----------------|-------------|
| `agent` | `image` | Jenkins pipelines execute on agents, and the `agent` section defines how the pipeline executes, and the Docker container to use. GitLab jobs execute on _runners_, and the `image` keyword defines the container to use. You can configure your own runners in Kubernetes or on any host. |
| `post` | `after_script` or `stage` | The Jenkins `post` section defines actions that should be performed at the end of a stage or pipeline. In GitLab, use `after_script` for commands to run at the end of a job, and `before_script` for actions to run before the other commands in a job. Use `stage` to select the exact stage a job should run in. GitLab supports both `.pre` and `.post` stages that always run before or after all other defined stages. |
| `stages` | `stages` | Jenkins stages are groups of jobs. GitLab CI/CD also uses stages, but it is more flexible. You can have multiple stages each with multiple independent jobs. Use `stages` at the top level to the stages and their execution order, and use `stage` at the job level to define the stage for that job. |
| `steps` | `script` | Jenkins `steps` define what to execute. GitLab CI/CD uses a `script` section which is similar. The `script` section is a YAML array with separate entries for each command to run in sequence. |
#### Directives
| Jenkins | GitLab | Explanation |
|---------------|----------------|-------------|
| `environment` | `variables` | Jenkins uses `environment` for environment variables. GitLab CI/CD uses the `variables` keyword to define CI/CD variables that can be used during job execution, but also for more dynamic pipeline configuration. These can also be set in the GitLab UI, under CI/CD settings. |
| `options` | Not applicable | Jenkins uses `options` for additional configuration, including timeouts and retry values. GitLab does not need a separate section for options, all configuration is added as CI/CD keywords at the job or pipeline level, for example `timeout` or `retry`. |
| `parameters` | Not applicable | In Jenkins, parameters can be required when triggering a pipeline. Parameters are handled in GitLab with CI/CD variables, which can be defined in many places, including the pipeline configuration, project settings, at runtime manually through the UI, or API. |
| `triggers` | `rules` | In Jenkins, `triggers` defines when a pipeline should run again, for example through cron notation. GitLab CI/CD can run pipelines automatically for many reasons, including Git changes and merge request updates. Use the `rules` keyword to control which events to run jobs for. Scheduled pipelines are defined in the project settings. |
| `tools` | Not applicable | In Jenkins, `tools` defines additional tools to install in the environment. GitLab does not have a similar keyword, as the recommendation is to use container images prebuilt with the exact tools required for your jobs. These images can be cached and can be built to already contain the tools you need for your pipelines. If a job needs additional tools, they can be installed as part of a `before_script` section. |
| `input` | Not applicable | In Jenkins, `input` adds a prompt for user input. Similar to `parameters`, inputs are handled in GitLab through CI/CD variables. |
| `when` | `rules` | In Jenkins, `when` defines when a stage should be executed. GitLab also has a `when` keyword, which defines whether a job should start running based on the status of earlier jobs, for example if jobs passed or failed. To control when to add jobs to specific pipelines, use `rules`. |
### Common configurations
This section goes over commonly used CI/CD configurations, showing how they can be converted
from Jenkins to GitLab CI/CD.
[Jenkins pipelines](https://www.jenkins.io/doc/book/pipeline/) generate automated CI/CD jobs
that are triggered when certain event take place, such as a new commit being pushed.
A Jenkins pipeline is defined in a `Jenkinsfile`. The GitLab equivalent is the [`.gitlab-ci.yml` configuration file](../../ci/yaml/gitlab_ci_yaml.md).
Jenkins does not provide a place to store source code, so the `Jenkinsfile` must be stored
in a separate source control repository.
#### Jobs
Jobs are a set of commands that run in a set sequence to achieve a particular result.
For example, build a container then deploy it to production, in a `Jenkinsfile`:
```groovy
pipeline {
agent any
stages {
stage('build') {
agent { docker 'golang:alpine' }
steps {
apk update
go build -o bin/hello
}
post {
always {
archiveArtifacts artifacts: 'bin/hello'
onlyIfSuccessful: true
}
}
}
stage('deploy') {
agent { docker 'golang:alpine' }
when {
branch 'staging'
}
steps {
echo "Deploying to staging"
scp bin/hello remoteuser@remotehost:/remote/directory
}
}
}
}
```
This example:
- Uses the `golang:alpine` container image.
- Runs a job for building code.
- Stores the built executable as an artifact.
- Adds a second job to deploy to `staging`, which:
- Only exists if the commit targets the `staging` branch.
- Starts after the build stage succeeds.
- Uses the built executable artifact from the earlier job.
The equivalent GitLab CI/CD `.gitlab-ci.yml` file would be:
```yaml
default:
image: golang:alpine
stages:
- build
- deploy
build-job:
stage: build
script:
- apk update
- go build -o bin/hello
artifacts:
paths:
- bin/hello
expire_in: 1 week
deploy-job:
stage: deploy
script:
- echo "Deploying to Staging"
- scp bin/hello remoteuser@remotehost:/remote/directory
rules:
- if: $CI_COMMIT_BRANCH == 'staging'
artifacts:
paths:
- bin/hello
```
##### Parallel
In Jenkins, jobs that are not dependent on previous jobs can run in parallel when
added to a `parallel` section.
For example, in a `Jenkinsfile`:
```groovy
pipeline {
agent any
stages {
stage('Parallel') {
parallel {
stage('Python') {
agent { docker 'python:latest' }
steps {
sh "python --version"
}
}
stage('Java') {
agent { docker 'openjdk:latest' }
when {
branch 'staging'
}
steps {
sh "java -version"
}
}
}
}
}
}
```
This example runs a Python and a Java job in parallel, using different container images.
The Java job only runs when the `staging` branch is changed.
The equivalent GitLab CI/CD `.gitlab-ci.yml` file would be:
```yaml
python-version:
image: python:latest
script:
- python --version
java-version:
image: openjdk:latest
rules:
- if: $CI_COMMIT_BRANCH == 'staging'
script:
- java -version
```
In this case, no extra configuration is needed to make the jobs run in parallel.
Jobs run in parallel by default, each on a different runner assuming there are enough runners
for all the jobs. The Java job is set to only run when the `staging` branch is changed.
##### Matrix
In GitLab you can use a matrix to run a job multiple times in parallel in a single pipeline,
but with different variable values for each instance of the job. Jenkins runs the matrix sequentially.
For example, in a `Jenkinsfile`:
```groovy
matrix {
axes {
axis {
name 'PLATFORM'
values 'linux', 'mac', 'windows'
}
axis {
name 'ARCH'
values 'x64', 'x86'
}
}
stages {
stage('build') {
echo "Building $PLATFORM for $ARCH"
}
stage('test') {
echo "Building $PLATFORM for $ARCH"
}
stage('deploy') {
echo "Building $PLATFORM for $ARCH"
}
}
}
```
The equivalent GitLab CI/CD `.gitlab-ci.yml` file would be:
```yaml
stages:
- build
- test
- deploy
.parallel-hidden-job:
parallel:
matrix:
- PLATFORM: [linux, mac, windows]
ARCH: [x64, x86]
build-job:
extends: .parallel-hidden-job
stage: build
script:
- echo "Building $PLATFORM for $ARCH"
test-job:
extends: .parallel-hidden-job
stage: test
script:
- echo "Testing $PLATFORM for $ARCH"
deploy-job:
extends: .parallel-hidden-job
stage: deploy
script:
- echo "Testing $PLATFORM for $ARCH"
```
#### Container Images
In GitLab you can [run your CI/CD jobs in separate, isolated Docker containers](../../ci/docker/using_docker_images.md)
using the [image](../../ci/yaml/index.md#image) keyword.
For example, in a `Jenkinsfile`:
```groovy
stage('Version') {
agent { docker 'python:latest' }
steps {
echo 'Hello Python'
sh 'python --version'
}
}
```
This example shows commands running in a `python:latest` container.
The equivalent GitLab CI/CD `.gitlab-ci.yml` file would be:
```yaml
version-job:
image: python:latest
script:
- echo "Hello Python"
- python --version
```
#### Variables
In GitLab, use the `variables` keyword to define [CI/CD variables](../variables/index.md).
Use variables to reuse configuration data, have more dynamic configuration, or store important values.
Variables can be defined either globally or per job.
For example, in a `Jenkinsfile`:
```groovy
pipeline {
agent any
environment {
NAME = 'Fern'
}
stages {
stage('English') {
environment {
GREETING = 'Hello'
}
steps {
sh 'echo "$GREETING $NAME"'
}
}
stage('Spanish') {
environment {
GREETING = 'Hola'
}
steps {
sh 'echo "$GREETING $NAME"'
}
}
}
}
```
This example shows how variables can be used to pass values to commands in jobs.
The equivalent GitLab CI/CD `.gitlab-ci.yml` file would be:
```yaml
default:
image: alpine:latest
stages:
- greet
variables:
NAME: "Fern"
english:
stage: greet
variables:
GREETING: "Hello"
script:
- echo "$GREETING $NAME"
spanish:
stage: greet
variables:
GREETING: "Hola"
script:
- echo "$GREETING $NAME"
```
Variables can also be [set in the GitLab UI, in the CI/CD settings](../variables/index.md#define-a-cicd-variable-in-the-ui).
In some cases, you can use [protected](../variables/index.md#protect-a-cicd-variable)
and [masked](../variables/index.md#mask-a-cicd-variable) variables for secret values.
These variables can be accessed in pipeline jobs the same as variables defined in the
configuration file.
For example, in a `Jenkinsfile`:
```groovy
pipeline {
agent any
stages {
stage('Example Username/Password') {
environment {
AWS_ACCESS_KEY = credentials('aws-access-key')
}
steps {
sh 'my-login-script.sh $AWS_ACCESS_KEY'
}
}
}
}
```
The equivalent GitLab CI/CD `.gitlab-ci.yml` file would be:
```yaml
login-job:
script:
- my-login-script.sh $AWS_ACCESS_KEY
```
Additionally, GitLab CI/CD makes [predefined variables](../variables/predefined_variables.md)
available to every pipeline and job which contain values relevant to the pipeline and repository.
#### Expressions and conditionals
When a new pipeline starts, GitLab checks which jobs should run in that pipeline.
You can configure jobs to run depending on factors like the status of variables,
or the pipeline type.
For example, in a `Jenkinsfile`:
```groovy
stage('deploy_staging') {
agent { docker 'alpine:latest' }
when {
branch 'staging'
}
steps {
echo "Deploying to staging"
}
}
```
In this example, the job only runs when the branch we are committing to is named `staging`.
The equivalent GitLab CI/CD `.gitlab-ci.yml` file would be:
```yaml
deploy_staging:
stage: deploy
script:
- echo "Deploy to staging server"
rules:
- if: '$CI_COMMIT_BRANCH == staging'
```
#### Runners
Like Jenkins agents, GitLab runners are the hosts that run jobs. If you are using GitLab.com,
you can use the [shared runner fleet](../runners/index.md) to run jobs without provisioning
@ -99,233 +487,144 @@ Some key details about runners:
for finer control, and associate runners with specific jobs. For example, you can use a tag for jobs that
require dedicated, more powerful, or specific hardware.
- GitLab has [autoscaling for runners](https://docs.gitlab.com/runner/configuration/autoscale.html).
Use autoscaling to provision runners only when needed and scale down when not needed,
similar to ephemeral agents in Jenkins.
Use autoscaling to provision runners only when needed and scale down when not needed.
## YAML configuration file
For example, in a `Jenkinsfile`:
GitLab pipeline configuration files use the [YAML](https://yaml.org/) format instead of
the [Groovy](https://groovy-lang.org/) format that Jenkins uses.
Using YAML is a strength of GitLab CI/CD, as it is a simple format to understand
and start using. For example, a small configuration file with two jobs and some
shared configuration in a hidden job:
```yaml
.test-config:
tags:
- docker-runners
stage: test
test-job:
extends:
- .test-config
script:
- bundle exec rake rspec
lint-job:
extends:
- .test-config
script:
- yarn run prettier
```groovy
pipeline {
agent none
stages {
stage('Linux') {
agent {
label 'linux'
}
steps {
echo "Hello, $USER"
}
}
stage('Windows') {
agent {
label 'windows'
}
steps {
echo "Hello, %USERNAME%"
}
}
}
}
```
In this example:
- The commands to run in jobs are added with the [`script` keyword](../yaml/index.md#script).
- The [`extends` keyword](../yaml/index.md#extends) reduces duplication in the configuration
by adding the same `tags` and `stage` configuration defined in `.test-config` to both jobs.
### Artifacts
In GitLab, any job can use the [`artifacts` keyword](../yaml/index.md#artifacts)
to define a set of [artifacts](../jobs/job_artifacts.md) to be stored when a job completes.
Artifacts are files that can be used in later jobs, for example for testing or deployment.
For example:
The equivalent GitLab CI/CD `.gitlab-ci.yml` file would be:
```yaml
pdf:
script: xelatex mycv.tex
linux_job:
stage: build
tags:
- linux
script:
- echo "Hello, $USER"
windows_job:
stage: build
tags:
- windows
script:
- echo "Hello, %USERNAME%"
```
#### Artifacts
In GitLab, any job can use the [`artifacts`](../../ci/yaml/index.md#artifacts) keyword to define a set of artifacts to
be stored when a job completes. [Artifacts](../../ci/jobs/job_artifacts.md) are files that can be used in later jobs,
for example for testing or deployment.
For example, in a `Jenkinsfile`:
```groovy
stages {
stage('Generate Cat') {
steps {
sh 'touch cat.txt'
sh 'echo "meow" > cat.txt'
}
post {
always {
archiveArtifacts artifacts: 'cat.txt'
onlyIfSuccessful: true
}
}
}
stage('Use Cat') {
steps {
sh 'cat cat.txt'
}
}
}
```
The equivalent GitLab CI/CD `.gitlab-ci.yml` file would be:
```yaml
stages:
- generate
- use
generate_cat:
stage: generate
script:
- touch cat.txt
- echo "meow" > cat.txt
artifacts:
paths:
- mycv.pdf
- output/
- cat.txt
expire_in: 1 week
```
In this example:
- The `mycv.pdf` file and all the files in `output/` are stored and could be used
in later jobs.
- To save resources, the artifacts expire and are deleted after one week.
### Scanning features
You might have used plugins for things like code quality, security, or static application scanning
in Jenkins. Tools like these are already available in GitLab and can be used in your
pipeline.
GitLab features including [code quality](../testing/code_quality.md), [security scanning](../../user/application_security/index.md),
[SAST](../../user/application_security/sast/index.md), and many others generate reports
when they complete. These reports can be displayed in merge requests and pipeline details pages.
### Templates
For organizations with many CI/CD pipelines, you can use project templates to configure
custom CI/CD configuration templates and reuse them across projects.
Group maintainers can configure a group to use as the source for [custom project templates](../../administration/custom_project_templates.md).
These templates can be used by all projects in the group.
An instance administrator can set a group as the source for [instance project templates](../../user/group/custom_project_templates.md),
which can be used by all projects in that instance.
## Convert a declarative Jenkinsfile
A declarative Jenkinsfile contains "Sections" and "Directives" which are used to control the behavior of your
pipelines. Equivalents for all of these exist in GitLab, which we've documented below.
This section is based on the [Jenkinsfile syntax documentation](https://www.jenkins.io/doc/book/pipeline/syntax/)
and is meant to be a mapping of concepts there to concepts in GitLab.
### Sections
#### `agent`
The agent section is used to define how a pipeline executes. For GitLab, we use [runners](../runners/index.md)
to provide this capability. You can configure your own runners in Kubernetes or on any host. You can also take advantage
of our shared runner fleet (the shared runner fleet is only available for GitLab.com users).
We also support using [tags](../runners/configure_runners.md#use-tags-to-control-which-jobs-a-runner-can-run) to direct different jobs
to different runners (execution agents).
The `agent` section also allows you to define which Docker images should be used for execution, for which we use
the [`image`](../yaml/index.md#image) keyword. The `image` can be set on a single job or at the top level, in which
case it applies to all jobs in the pipeline:
```yaml
my_job:
image: alpine
```
#### `post`
The `post` section defines the actions that should be performed at the end of the pipeline. GitLab also supports
this through the use of stages. You can define your stages as follows, and any jobs assigned to the `before_pipeline`
or `after_pipeline` stages run as expected. You can call these stages anything you like:
```yaml
stages:
- before_pipeline
- build
- test
- deploy
- after_pipeline
```
Setting a step to be performed before and after any job can be done via the
[`before_script`](../yaml/index.md#before_script) and [`after_script`](../yaml/index.md#after_script) keywords:
```yaml
default:
before_script:
- echo "I run before any jobs starts in the entire pipeline, and can be responsible for setting up the environment."
```
#### `stages`
GitLab CI/CD also lets you define stages, but is a little bit more free-form to configure. The GitLab [`stages` keyword](../yaml/index.md#stages)
is a top level setting that enumerates the list of stages. You are not required to nest individual jobs underneath
the `stages` section. Any job defined in the `.gitlab-ci.yml` can be made a part of any stage through use of the
[`stage` keyword](../yaml/index.md#stage).
Unless otherwise specified, every pipeline is instantiated with a `build`, `test`, and `deploy` stage
which are run in that order. Jobs that have no `stage` defined are placed by default in the `test` stage.
Of course, each job that refers to a stage must refer to a stage that exists in the pipeline configuration.
```yaml
stages:
- build
- test
- deploy
my_job:
stage: build
```
#### `steps`
The `steps` section is equivalent to the [`script` section](../yaml/index.md#script) of an individual job. The `steps` section is a YAML array
with each line representing an individual command to be run:
```yaml
my_job:
use_cat:
stage: use
script:
- echo "hello! the current time is:"
- time
- cat cat.txt
artifacts:
paths:
- cat.txt
```
### Directives
#### Caching
#### `environment`
A [cache](../../ci/caching/index.md) is created when a job downloads one or more files and
saves them for faster access in the future. Subsequent jobs that use the same cache don't have to download the files again,
so they execute more quickly. The cache is stored on the runner and uploaded to S3 if
[distributed cache is enabled](https://docs.gitlab.com/runner/configuration/autoscale.html#distributed-runners-caching).
Jenkins core does not provide caching.
In GitLab, we use the [`variables` keyword](../yaml/index.md#variables) to define different variables at runtime.
These can also be set up through the GitLab UI, under CI/CD settings. See also our [general documentation on variables](../variables/index.md),
including the section on [protected variables](../variables/index.md#protect-a-cicd-variable). This can be used
to limit access to certain variables to certain environments or runners:
For example, in a `.gitlab-ci.yml` file:
```yaml
variables:
POSTGRES_USER: user
POSTGRES_PASSWORD: testing_password
```
#### `options`
Here, options for different things exist associated with the object in question itself. For example, options related
to jobs are defined in relation to the job itself. If you're looking for a certain option, you should be able to find
where it's located by searching our [complete configuration reference](../yaml/index.md) page.
#### `parameters`
GitLab does not require you to define which variables you want to be available when starting a manual job. A user
can provide any variables they like.
#### `triggers` / `cron`
Because GitLab is integrated tightly with Git, SCM polling options for triggers are not needed. We support a
[syntax for scheduling pipelines](../pipelines/schedules.md).
#### `tools`
GitLab does not support a separate `tools` directive. Our best-practice recommendation is to use pre-built
container images. These images can be cached and can be built to already contain the tools you need for your pipelines. Pipelines can
be set up to automatically build these images as needed and deploy them to the [container registry](../../user/packages/container_registry/index.md).
If you don't use container images with Docker or Kubernetes, but use the `shell` executor on your own system,
you must set up your environment. You can set up the environment in advance, or as part of the jobs
with a `before_script` action that handles this for you.
#### `input`
Similar to the `parameters` keyword, this is not needed because a manual job can always be provided runtime
variable entry.
#### `when`
GitLab does support a [`when` keyword](../yaml/index.md#when) which is used to indicate when a job should be
run in case of (or despite) failure. Most of the logic for controlling pipelines can be found in
our very powerful [`rules` system](../yaml/index.md#rules):
```yaml
my_job:
cache-job:
script:
- echo
rules:
- if: $CI_COMMIT_BRANCH
- echo "This job uses a cache."
cache:
key: binaries-cache-$CI_COMMIT_REF_SLUG
paths:
- binaries/
```
## Secrets Management
### Security Scanning features
You might have used plugins for things like code quality, security, or static application scanning in Jenkins.
GitLab provides [security scanners](../../user/application_security/index.md) out-of-the-box to detect
vulnerabilities in all parts of the SDLC. You can add these plugins in GitLab using templates, for example to add
SAST scanning to your pipeline, add the following to your `.gitlab-ci.yml`:
```yaml
include:
- template: Security/SAST.gitlab-ci.yml
```
You can customize the behavior of security scanners by using CI/CD variables, for example
with the [SAST scanners](../../user/application_security/sast/index.md#available-cicd-variables).
### Secrets Management
Privileged information, often referred to as "secrets", is sensitive information
or credentials you need in your CI/CD workflow. You might use secrets to unlock protected resources
@ -358,15 +657,59 @@ only be done in [the project, group, or instance settings](../variables/index.md
Review the [security guidelines](../variables/index.md#cicd-variable-security) to improve
the safety of your CI/CD variables.
## Additional resources
## Planning and Performing a Migration
The following list of recommended steps was created after observing organizations
that were able to quickly complete this migration.
### Create a Migration Plan
Before starting a migration you should create a [migration plan](plan_a_migration.md) to make preparations for the migration. For a migration from Jenkins, ask yourself the following questions in preparation:
- What plugins are used by jobs in Jenkins today?
- Do you know what these plugins do exactly?
- Do any plugins wrap a common build tool? For example, Maven, Gradle, or NPM?
- What is installed on the Jenkins agents?
- Are there any shared libraries in use?
- How are you authenticating from Jenkins? Are you using SSH keys, API tokens, or other secrets?
- Are there other projects that you need to access from your pipeline?
- Are there credentials in Jenkins to access outside services? For example Ansible Tower,
Artifactory, or other Cloud Providers or deployment targets?
### Prerequisites
Before doing any migration work, you should first:
1. Get familiar with GitLab.
- Read about the [key GitLab CI/CD features](../../ci/index.md).
- Follow tutorials to create [your first GitLab pipeline](../quick_start/index.md) and [more complex pipelines](../quick_start/tutorial.md) that build, test, and deploys a static site.
- Review the [`.gitlab-ci.yml` keyword reference](../yaml/index.md).
1. Set up and configure GitLab.
1. Test your GitLab instance.
- Ensure [runners](../runners/index.md) are available, either by using shared GitLab.com runners or installing new runners.
### Migration Steps
1. Migrate projects from your SCM solution to GitLab.
- (Recommended) You can use the available [importers](../../user/project/import/index.md)
to automate mass imports from external SCM providers.
- You can [import repositories by URL](../../user/project/import/repo_by_url.md).
1. Create a `.gitlab-ci.yml` file in each project.
1. Migrate Jenkins configuration to GitLab CI/CD jobs and configure them to show results directly in merge requests.
1. Migrate deployment jobs by using [cloud deployment templates](../cloud_deployment/index.md),
[environments](../environments/index.md), and the [GitLab agent for Kubernetes](../../user/clusters/agent/index.md).
1. Check if any CI/CD configuration can be reused across different projects, then create
and share CI/CD templates.
1. Check the [pipeline efficiency documentation](../pipelines/pipeline_efficiency.md)
to learn how to make your GitLab CI/CD pipelines faster and more efficient.
### Additional Resources
- You can use the [JenkinsFile Wrapper](https://gitlab.com/gitlab-org/jfr-container-builder/)
to run a complete Jenkins instance inside of a GitLab CI/CD job, including plugins. Use this tool to
help ease the transition to GitLab CI/CD, by delaying the migration of less urgent pipelines.
to run a complete Jenkins instance inside of a GitLab CI/CD job, including plugins. Use this tool to help ease the transition to GitLab CI/CD, by delaying the migration of less urgent pipelines.
NOTE:
The JenkinsFile Wrapper is not packaged with GitLab and falls outside of the scope of support.
For more information, see the [Statement of Support](https://about.gitlab.com/support/statement-of-support/).
- If your tooling outputs packages that you want to make accessible, you can store them
in a [package registry](../../user/packages/index.md).
- Use [review Apps](../review_apps/index.md) to preview changes before merging them.
If you have questions that are not answered here, the [GitLab community forum](https://forum.gitlab.com/) can be a great resource.

View File

@ -55,21 +55,6 @@ the migration requirements:
- How do you deploy your code?
- Where do you deploy your code?
### Jenkins
If you are [migrating from Jenkins](jenkins.md), these additional questions can help with planning
the migration:
- What plugins are used by jobs in Jenkins today?
- Do you know what these plugins do exactly?
- Do any plugin wrap a common build tool? For example, Maven, Gradle, or NPM?
- What is installed on the Jenkins agents?
- Are there any shared libraries in use?
- How are you authenticating from Jenkins? Are you using SSH keys, API tokens, or other secrets?
- Are there other projects that you need to access from your pipeline?
- Are there credentials in Jenkins to access outside services? For example Ansible Tower,
Artifactory, or other Cloud Providers or deployment targets?
## Related topics
- How to migrate Atlassian Bamboo Server's CI/CD infrastructure to GitLab CI/CD, [part one](https://about.gitlab.com/blog/2022/07/06/migration-from-atlassian-bamboo-server-to-gitlab-ci/)

View File

@ -31,6 +31,11 @@ bin/rails g gitlab:analytics:internal_events \
--mr=https://gitlab.com/gitlab-org/gitlab/-/merge_requests/121544
```
Where:
- `time_frames`: Valid options are `7d` and `28d` if you provide a `unique` value and `all` for metrics without `unique`. We are working to make `7d` and `28d` work for metrics with `all` time frame in [this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/411264).
- `unique`: Valid options are `user.id`, `project.id`, and `namespace.id`, as they are logged as part of the standard context. We [are actively working](https://gitlab.com/gitlab-org/gitlab/-/issues/411255) on a way to define uniqueness on arbitrary properties sent with the event, such as `merge_request.id`.
## Trigger events
Triggering an event and thereby updating a metric is slightly different on backend and frontend. Please refer to the relevant section below.
@ -135,7 +140,3 @@ Sometimes we want to send internal events when the component is rendered or load
= render Pajamas::ButtonComponent.new(button_options: { data: { event_tracking_load: 'true', event_tracking: 'i_devops' } }) do
= _("New project")
```
### Limitations
The only values we allow for `unique` are `user.id`, `project.id`, and `namespace.id`, as they are logged as part of the standard context. We currently don't have anywhere to put a value like `merge_request.id`. That will change with self-describing events.

View File

@ -293,20 +293,20 @@ In GitLab 12.1 and later, only PostgreSQL is supported. In GitLab 16.0 and later
1. Install the database packages.
For Ubuntu 20.04 and later:
For Ubuntu 22.04 and later:
```shell
sudo apt install -y postgresql postgresql-client libpq-dev postgresql-contrib
```
For Ubuntu 18.04 and earlier, the available PostgreSQL doesn't meet the minimum
For Ubuntu 20.04 and earlier, the available PostgreSQL doesn't meet the minimum
version requirement. You must add PostgreSQL's repository:
```shell
sudo sh -c 'echo "deb https://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list'
wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo apt-key add -
sudo sh -c 'echo "deb http://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list'
sudo apt update
sudo apt -y install postgresql-12 postgresql-client-12 libpq-dev
sudo apt-get update
sudo apt-get -y install postgresql-14
```
1. Verify the PostgreSQL version you have is supported by the version of GitLab you're

View File

@ -6,6 +6,11 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Dependency Scanning **(ULTIMATE ALL)**
<i class="fa fa-youtube-play youtube" aria-hidden="true"></i>
For an interactive reading and how-to demo of this Dependency Scanning doc, see [How to use dependency scanning tutorial hands-on GitLab Application Security part 3](https://youtu.be/ii05cMbJ4xQ?feature=shared)
<i class="fa fa-youtube-play youtube" aria-hidden="true"></i>
For an interactive reading and how-to demo playlist, see [Get Started With GitLab Application Security Playlist](https://www.youtube.com/playlist?list=PL05JrBw4t0KrUrjDoefSkgZLx5aJYFaF9)
Dependency Scanning analyzes your application's dependencies for known vulnerabilities. All
dependencies are scanned, including transitive dependencies, also known as nested dependencies.

View File

@ -8,6 +8,8 @@ info: To determine the technical writer assigned to the Stage/Group associated w
<i class="fa fa-youtube-play youtube" aria-hidden="true"></i>
For an overview, see [Adopting GitLab application security](https://www.youtube.com/watch?v=5QlxkiKR04k).
<i class="fa fa-youtube-play youtube" aria-hidden="true"></i>
For an interactive reading and how-to demo playlist, see [Get Started With GitLab Application Security Playlist](https://www.youtube.com/playlist?list=PL05JrBw4t0KrUrjDoefSkgZLx5aJYFaF9)
The following steps help you get the most from GitLab application security tools. These steps are a recommended order of operations. You can choose to implement capabilities in a different order or omit features that do not apply to your specific needs.

View File

@ -15,6 +15,11 @@ info: To determine the technical writer assigned to the Stage/Group associated w
> `secret_detection_default_branch` and `secret_detection` were consolidated into one job,
> `secret_detection`.
<i class="fa fa-youtube-play youtube" aria-hidden="true"></i>
For an interactive reading and how-to demo of this Secret Detection doc, see [How to enable secret detection in GitLab Application Security Part 1/2](https://youtu.be/dbMxeO6nJCE?feature=shared) and [How to enable secret detection in GitLab Application Security Part 2/2](https://youtu.be/VL-_hdiTazo?feature=shared)
<i class="fa fa-youtube-play youtube" aria-hidden="true"></i>
For an interactive reading and how-to demo playlist, see [Get Started With GitLab Application Security Playlist](https://www.youtube.com/playlist?list=PL05JrBw4t0KrUrjDoefSkgZLx5aJYFaF9)
People sometimes accidentally commit secrets like keys or API tokens to Git repositories.
After a sensitive value is pushed to a remote repository, anyone with access to the repository can impersonate the authorized user of the secret for malicious purposes.
Most organizations require exposed secrets to be revoked and replaced to address this risk.

View File

@ -134,9 +134,11 @@ can be added to the group.
The most popular public email domains cannot be restricted, such as:
- `gmail.com`, `yahoo.com`, `aol.com`, `icloud.com`
- `hotmail.com`, `hotmail.co.uk`, `hotmail.fr`
- `msn.com`, `live.com`, `outlook.com`
- `aol.com`, `gmail.com`, `hotmail.co.uk`, `hotmail.com`,
- `hotmail.fr`, `icloud.com`, `live.com`, `mail.com`,
- `me.com`, `msn.com`, `outlook.com`,
- `proton.me`, `protonmail.com`, `tutanota.com`,
- `yahoo.com`, `yandex.com`, `zohomail.com`
When you share a group, both the source and target namespaces must allow the domains of the members' email addresses.

View File

@ -61,13 +61,18 @@ When deleting users, you can either:
- Delete the user and their contributions, including:
- Abuse reports.
- Emoji reactions.
- Epics.
- Groups of which the user is the only user with the Owner role.
- Personal access tokens.
- Epics.
- Issues.
- Merge requests.
- Notes and comments.
- Personal access tokens.
- Snippets.
- [Notes and comments](../../../api/notes.md)
on other users' [commits](../../project/repository/index.md#commit-changes-to-a-repository),
[epics](../../group/epics/index.md),
[issues](../../project/issues/index.md),
[merge requests](../../project/merge_requests/index.md)
and [snippets](../../snippets.md).
An alternative to deleting is [blocking a user](../../../administration/moderate_users.md#block-a-user).

View File

@ -19,6 +19,9 @@ To use one or more custom domain names:
- Add a [custom **root domain** or a **subdomain**](#set-up-a-custom-domain).
- Add [SSL/TLS certification](#adding-an-ssltls-certificate-to-pages).
WARNING:
You cannot verify the [most popular public email domains](../../../../user/group/access_and_permissions.md#restrict-group-access-by-domain).
## Set up a custom domain
To set up Pages with a custom domain name, read the requirements and steps below.

View File

@ -16,6 +16,8 @@ module Backup
sslcompression: 'PGSSLCOMPRESSION'
}.freeze
OVERRIDE_PREFIX = "GITLAB_BACKUP_"
attr_reader :config
def initialize(name)
@ -35,7 +37,7 @@ module Backup
original_config = source_model.connection_db_config.configuration_hash.dup
@config = config_for_backup(original_config)
@config = config_for_backup(name, original_config)
@model.establish_connection(
ActiveRecord::DatabaseConfigurations::HashConfig.new(
@ -56,7 +58,7 @@ module Backup
self.class.const_set(klass_name, Class.new(ApplicationRecord))
end
def config_for_backup(config)
def config_for_backup(name, config)
db_config = {
activerecord: config,
pg_env: {}
@ -65,8 +67,9 @@ module Backup
# This enables the use of different PostgreSQL settings in
# case PgBouncer is used. PgBouncer clears the search path,
# which wreaks havoc on Rails if connections are reused.
override = "GITLAB_BACKUP_#{arg}"
val = ENV[override].presence || config[opt].to_s.presence
override_all = "#{OVERRIDE_PREFIX}#{arg}"
override_db = "#{OVERRIDE_PREFIX}#{name.upcase}_#{arg}"
val = ENV[override_db].presence || ENV[override_all].presence || config[opt].to_s.presence
next unless val

View File

@ -32760,6 +32760,9 @@ msgstr ""
msgid "Only SSH"
msgstr ""
msgid "Only SSH Certificates"
msgstr ""
msgid "Only accessible by %{membersPageLinkStart}project members%{membersPageLinkEnd}. Membership must be explicitly granted to each user."
msgstr ""
@ -54473,6 +54476,9 @@ msgstr ""
msgid "You cannot set yourself to awaiting"
msgstr ""
msgid "You cannot verify %{value} because it is a popular public email domain."
msgstr ""
msgid "You cannot write to a read-only secondary GitLab Geo instance. Please use %{link_to_primary_node} instead."
msgstr ""

View File

@ -32,7 +32,7 @@ module QA
click_element(:import_project_button)
wait_until(reload: false) do
has_notice?("The project was successfully imported.") || has_element?(:project_name_content)
has_notice?("The project was successfully imported.") || has_element?('project-name-content')
end
end
end

View File

@ -12,12 +12,12 @@ module QA
end
def has_file_explorer?
page.has_css?('.explorer-folders-view', visible: true)
page.has_css?('[aria-label="Files Explorer"]', visible: true)
has_element?('div[aria-label="Files Explorer"]')
end
def right_click_file_explorer
page.find('.explorer-folders-view', visible: true).right_click
has_element?('div.monaco-list-rows')
find_element('div[aria-label="Files Explorer"]').right_click
end
def open_file_from_explorer(file_name)
@ -32,78 +32,69 @@ module QA
within_element('.monaco-editor', &block)
end
def has_new_folder_menu_item?
page.has_css?('[aria-label="New Folder..."]', visible: true)
def has_right_click_menu_item?
has_element?('div.menu-item-check')
end
def click_new_folder_menu_item
page.find('[aria-label="New Folder..."]').click
end
def enter_new_folder_text_input(name)
page.find('.explorer-item-edited', visible: true)
send_keys(name, :enter)
end
def has_upload_menu_item?
page.has_css?('.menu-item-check', visible: true)
click_element('span[aria-label="New Folder..."]')
end
def click_upload_menu_item
page.find('[aria-label="Upload..."]', visible: true).click
click_element('span[aria-label="Upload..."]')
end
def enter_new_folder_text_input(name)
find_element('input[type="text"]')
send_keys(name, :enter)
end
def enter_file_input(file)
page.find('input[type="file"]', visible: false).send_keys(file)
find_element('input[type="file"]', visible: false).send_keys(file)
end
def has_commit_pending_tab?
page.has_css?('.scm-viewlet-label', visible: true)
has_element?('.scm-viewlet-label')
end
def click_commit_pending_tab
page.find('.scm-viewlet-label', visible: true).click
click_element('.scm-viewlet-label', visible: true)
end
def click_commit_tab
page.find('a.codicon-source-control-view-icon', visible: true).click
click_element('.codicon-source-control-view-icon')
end
def has_commit_message_box?
page.has_css?('div.view-lines.monaco-mouse-cursor-text', visible: true)
has_element?('div[aria-label="Source Control Input"]')
end
def enter_commit_message(message)
page.find('div.view-lines.monaco-mouse-cursor-text', visible: true).send_keys(message)
end
def click_commit_button
page.find('a.monaco-text-button', visible: true).click
end
def has_notification_box?
page.has_css?('a.monaco-text-button', visible: true)
end
def create_merge_request
Support::Waiter.wait_until(max_duration: 10, retry_on_exception: true) do
within_vscode_editor do
page.find('.monaco-button[title="Create MR"]').click
end
within_element('div[aria-label="Source Control Input"]') do
find_element('.view-line').click
send_keys(message)
end
end
def click_commit_button
click_element('div[aria-label="Commit to \'main\'"]')
end
def has_notification_box?
has_element?('.monaco-dialog-box')
end
def click_new_branch
page.find('.monaco-button[title="Create new branch"]').click
click_element('.monaco-button[title="Create new branch"]')
end
def has_branch_input_field?
page.has_css?('.monaco-findInput', visible: true)
has_element?('input[aria-label="input"]')
end
def has_message?(content)
within_vscode_editor do
page.has_content?(content)
has_text?(content)
end
end
@ -133,15 +124,14 @@ module QA
def create_new_folder(name)
within_vscode_editor do
right_click_file_explorer
has_new_folder_menu_item?
# Use for stability, WebIDE inside an iframe is finnicky, webdriver sometimes moves too fast
Support::Waiter.wait_until(max_duration: 20, retry_on_exception: true) do
right_click_file_explorer
has_right_click_menu_item?
click_new_folder_menu_item
# Verify New Folder button is triggered and textbox is waiting for input
enter_new_folder_text_input(name)
page.has_content?(name)
has_text?(name)
end
end
end
@ -160,8 +150,8 @@ module QA
end
has_commit_message_box?
send_keys(message)
page.has_content?(message)
enter_commit_message(message)
has_text?(message)
click_commit_button
has_notification_box?
end
@ -176,8 +166,14 @@ module QA
end
end
def create_merge_request
within_vscode_editor do
has_element?('div[title="GitLab Web IDE Extension (Extension)"]')
click_element('.monaco-button[title="Create MR"]')
end
end
def upload_file(file_path)
wait_for_ide_to_load
within_vscode_editor do
# VSCode eagerly removes the input[type='file'] from click on Upload.
# We need to execute a script on the iframe to stub out the iframes body.removeChild to add it back in.
@ -186,32 +182,40 @@ module QA
# Use for stability, WebIDE inside an iframe is finnicky, webdriver sometimes moves too fast
Support::Waiter.wait_until(max_duration: 20, retry_on_exception: true) do
right_click_file_explorer
has_upload_menu_item?
has_right_click_menu_item?
click_upload_menu_item
enter_file_input(file_path)
end
# Wait for the file to be uploaded
has_text?(file_path)
end
end
def add_file_content(prompt_data)
click_inside_editor_frame
within_file_editor do
send_keys(:enter, :enter, prompt_data)
within_vscode_editor do
click_inside_editor_frame
within_file_editor do
send_keys(:enter, :enter, prompt_data)
end
end
end
def verify_prompt_appears_and_accept(pattern)
within_file_editor do
Support::Waiter.wait_until(max_duration: 30) do
page.text.match?(pattern)
within_vscode_editor do
within_file_editor do
Support::Waiter.wait_until(max_duration: 30) do
page.text.match?(pattern)
end
send_keys(:tab)
end
send_keys(:tab)
end
end
def validate_prompt(pattern)
within_file_editor do
page.text.match?(pattern)
within_vscode_editor do
within_file_editor do
page.text.match?(pattern)
end
end
end
end

View File

@ -8,7 +8,7 @@ module QA
type: :flaky
} do
describe 'Add a directory in Web IDE' do
let(:project) { create(:project, :with_readme, name: 'add-directory-project') }
let(:project) { create(:project, :with_readme, name: 'webide-add-directory-project') }
before do
Flow::Login.sign_in
@ -24,14 +24,15 @@ module QA
])
project.visit!
Page::Project::Show.perform(&:open_web_ide!)
Page::Project::WebIDE::VSCode.perform(&:wait_for_ide_to_load)
end
it 'throws an error', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/386760' do
Page::Project::Show.perform(&:open_web_ide!)
Page::Project::WebIDE::VSCode.perform do |ide|
ide.wait_for_ide_to_load
ide.create_new_folder(directory_name)
ide.has_message?('A file or folder first_directory already exists at this location.')
expect(ide).to have_message('A file or folder first_directory already exists at this location.')
end
end
end
@ -41,15 +42,16 @@ module QA
before do
Page::Project::Show.perform(&:open_web_ide!)
Page::Project::WebIDE::VSCode.perform(&:wait_for_ide_to_load)
end
it 'shows successfully but not able to be committed',
testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/386761' do
Page::Project::WebIDE::VSCode.perform do |ide|
ide.wait_for_ide_to_load
ide.create_new_folder(directory_name)
ide.commit_toggle(directory_name)
ide.has_message?('No changes found. Not able to commit.')
expect(ide).to have_message('No changes found. Not able to commit.')
end
end
end

View File

@ -9,38 +9,42 @@ module QA
} do
describe 'Upload a file in Web IDE' do
let(:file_path) { File.absolute_path(File.join('qa', 'fixtures', 'web_ide', file_name)) }
let(:project) { create(:project, :with_readme, name: 'upload-file-project') }
let(:project) { create(:project, :with_readme, name: 'webide-upload-file-project') }
before do
Flow::Login.sign_in
project.visit!
Page::Project::Show.perform(&:open_web_ide!)
Page::Project::WebIDE::VSCode.perform(&:wait_for_ide_to_load)
end
context 'when a file with the same name already exists' do
let(:file_name) { 'README.md' }
it 'throws an error', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/390005' do
Page::Project::Show.perform(&:open_web_ide!)
Page::Project::WebIDE::VSCode.perform do |ide|
ide.upload_file(file_path)
ide.has_message?("A file or folder with the name 'README.md' already exists in the destination folder")
expect(ide)
.to have_message("A file or folder with the name 'README.md' already exists in the destination folder")
end
end
end
shared_examples 'upload a file' do
it "verifies it successfully uploads and commits to a MR" do
Page::Project::Show.perform(&:open_web_ide!)
Page::Project::WebIDE::VSCode.perform do |ide|
ide.upload_file(file_path)
ide.has_message?(file_name)
ide.commit_and_push(file_name)
ide.has_message?('Success! Your changes have been committed.')
expect(ide).to have_message('Success! Your changes have been committed.')
ide.create_merge_request
end
# Opens the MR in new tab and verify the file is in the MR
page.driver.browser.switch_to.window(page.driver.browser.window_handles.last)
Page::MergeRequest::Show.perform do |merge_request|
expect(merge_request).to have_content(file_name)
end

View File

@ -26,6 +26,7 @@ docker buildx build \
--platform=${ARCH:-amd64} \
--tag="${IMAGE}:${SHA_TAG}" \
--tag="${IMAGE}:${BRANCH_TAG}" \
--provenance=false \
${OUTPUT_OPTION} \
.

View File

@ -90,5 +90,6 @@ docker buildx build \
--build-arg=QA_BUILD_TARGET="${QA_BUILD_TARGET}" \
--file="${CI_PROJECT_DIR}/qa/Dockerfile" \
--push \
--provenance=false \
${DESTINATIONS} \
${CI_PROJECT_DIR}

View File

@ -2,7 +2,7 @@
require 'spec_helper'
RSpec.describe GroupsHelper do
RSpec.describe GroupsHelper, feature_category: :groups_and_projects do
include ApplicationHelper
include AvatarsHelper
@ -97,23 +97,11 @@ RSpec.describe GroupsHelper do
end
end
context 'recursive' do
before do
stub_feature_flags(use_traversal_ids: false)
end
include_examples 'correct ancestor order'
before do
very_deep_nested_group.reload # make sure traversal_ids are reloaded
end
context 'linear' do
before do
stub_feature_flags(use_traversal_ids: true)
very_deep_nested_group.reload # make sure traversal_ids are reloaded
end
include_examples 'correct ancestor order'
end
include_examples 'correct ancestor order'
end
it 'enqueues the elements in the breadcrumb schema list' do
@ -269,21 +257,7 @@ RSpec.describe GroupsHelper do
end
end
context 'recursive' do
before do
stub_feature_flags(use_traversal_ids: false)
end
include_examples 'correct ancestor order'
end
context 'linear' do
before do
stub_feature_flags(use_traversal_ids: true)
end
include_examples 'correct ancestor order'
end
include_examples 'correct ancestor order'
end
end
@ -558,22 +532,24 @@ RSpec.describe GroupsHelper do
end
describe "#enabled_git_access_protocol_options_for_group" do
subject { helper.enabled_git_access_protocol_options_for_group }
let_it_be(:group) { create(:group) }
subject { helper.enabled_git_access_protocol_options_for_group(group) }
before do
expect(::Gitlab::CurrentSettings).to receive(:enabled_git_access_protocol).and_return(instance_setting)
allow(::Gitlab::CurrentSettings).to receive(:enabled_git_access_protocol).and_return(instance_setting)
end
context "instance setting is nil" do
let(:instance_setting) { nil }
it { is_expected.to contain_exactly([_("Both SSH and HTTP(S)"), "all"], [_("Only SSH"), "ssh"], [_("Only HTTP(S)"), "http"]) }
it { is_expected.to include([_("Both SSH and HTTP(S)"), "all"], [_("Only SSH"), "ssh"], [_("Only HTTP(S)"), "http"]) }
end
context "instance setting is blank" do
let(:instance_setting) { nil }
let(:instance_setting) { '' }
it { is_expected.to contain_exactly([_("Both SSH and HTTP(S)"), "all"], [_("Only SSH"), "ssh"], [_("Only HTTP(S)"), "http"]) }
it { is_expected.to include([_("Both SSH and HTTP(S)"), "all"], [_("Only SSH"), "ssh"], [_("Only HTTP(S)"), "http"]) }
end
context "instance setting is ssh" do

View File

@ -3,6 +3,8 @@
require 'spec_helper'
RSpec.describe Backup::DatabaseModel, :reestablished_active_record_base, feature_category: :backup_restore do
using RSpec::Parameterized::TableSyntax
let(:gitlab_database_name) { 'main' }
describe '#connection' do
@ -30,7 +32,7 @@ RSpec.describe Backup::DatabaseModel, :reestablished_active_record_base, feature
).to receive(:configuration_hash).and_return(application_config)
end
context 'when no GITLAB_BACKUP_PG* variables are set' do
shared_examples 'no configuration is overridden' do
it 'ActiveRecord backup configuration is expected to equal application configuration' do
expect(subject[:activerecord]).to eq(application_config)
end
@ -45,9 +47,23 @@ RSpec.describe Backup::DatabaseModel, :reestablished_active_record_base, feature
end
end
context 'when GITLAB_BACKUP_PG* variables are set' do
using RSpec::Parameterized::TableSyntax
shared_examples 'environment variables override application configuration' do
let(:active_record_key) { described_class::SUPPORTED_OVERRIDES.invert[pg_env] }
it 'ActiveRecord backup configuration overrides application configuration' do
expect(subject[:activerecord]).to eq(application_config.merge(active_record_key => overridden_value))
end
it 'PostgreSQL ENV overrides application configuration' do
expect(subject[:pg_env]).to include({ pg_env => overridden_value })
end
end
context 'when no GITLAB_BACKUP_PG* variables are set' do
it_behaves_like 'no configuration is overridden'
end
context 'when GITLAB_BACKUP_PG* variables are set' do
where(:env_variable, :overridden_value) do
'GITLAB_BACKUP_PGHOST' | 'test.invalid.'
'GITLAB_BACKUP_PGUSER' | 'some_user'
@ -63,18 +79,76 @@ RSpec.describe Backup::DatabaseModel, :reestablished_active_record_base, feature
with_them do
let(:pg_env) { env_variable[/GITLAB_BACKUP_(\w+)/, 1] }
let(:active_record_key) { described_class::SUPPORTED_OVERRIDES.invert[pg_env] }
before do
stub_env(env_variable, overridden_value)
end
it 'ActiveRecord backup configuration overrides application configuration' do
expect(subject[:activerecord]).to eq(application_config.merge(active_record_key => overridden_value))
it_behaves_like 'environment variables override application configuration'
end
end
context 'when GITLAB_BACKUP_<DBNAME>_PG* variables are set' do
context 'and environment variables are for the current database name' do
where(:env_variable, :overridden_value) do
'GITLAB_BACKUP_MAIN_PGHOST' | 'test.invalid.'
'GITLAB_BACKUP_MAIN_PGUSER' | 'some_user'
'GITLAB_BACKUP_MAIN_PGPORT' | '1543'
'GITLAB_BACKUP_MAIN_PGPASSWORD' | 'secret'
'GITLAB_BACKUP_MAIN_PGSSLMODE' | 'allow'
'GITLAB_BACKUP_MAIN_PGSSLKEY' | 'some_key'
'GITLAB_BACKUP_MAIN_PGSSLCERT' | '/path/to/cert'
'GITLAB_BACKUP_MAIN_PGSSLROOTCERT' | '/path/to/root/cert'
'GITLAB_BACKUP_MAIN_PGSSLCRL' | '/path/to/crl'
'GITLAB_BACKUP_MAIN_PGSSLCOMPRESSION' | '1'
end
it 'PostgreSQL ENV overrides application configuration' do
expect(subject[:pg_env]).to include({ pg_env => overridden_value })
with_them do
let(:pg_env) { env_variable[/GITLAB_BACKUP_MAIN_(\w+)/, 1] }
before do
stub_env(env_variable, overridden_value)
end
it_behaves_like 'environment variables override application configuration'
end
end
context 'and environment variables are for another database' do
where(:env_variable, :overridden_value) do
'GITLAB_BACKUP_CI_PGHOST' | 'test.invalid.'
'GITLAB_BACKUP_CI_PGUSER' | 'some_user'
'GITLAB_BACKUP_CI_PGPORT' | '1543'
'GITLAB_BACKUP_CI_PGPASSWORD' | 'secret'
'GITLAB_BACKUP_CI_PGSSLMODE' | 'allow'
'GITLAB_BACKUP_CI_PGSSLKEY' | 'some_key'
'GITLAB_BACKUP_CI_PGSSLCERT' | '/path/to/cert'
'GITLAB_BACKUP_CI_PGSSLROOTCERT' | '/path/to/root/cert'
'GITLAB_BACKUP_CI_PGSSLCRL' | '/path/to/crl'
'GITLAB_BACKUP_CI_PGSSLCOMPRESSION' | '1'
end
with_them do
let(:pg_env) { env_variable[/GITLAB_BACKUP_CI_(\w+)/, 1] }
before do
stub_env(env_variable, overridden_value)
end
it_behaves_like 'no configuration is overridden'
end
end
context 'when both GITLAB_BACKUP_PGUSER and GITLAB_BACKUP_MAIN_PGUSER variable are present' do
before do
stub_env('GITLAB_BACKUP_PGUSER', 'generic_user')
stub_env('GITLAB_BACKUP_MAIN_PGUSER', 'specfic_user')
end
it 'prefers more specific GITLAB_BACKUP_MAIN_PGUSER' do
config = subject
expect(config.dig(:activerecord, :username)).to eq('specfic_user')
expect(config.dig(:pg_env, 'PGUSER')).to eq('specfic_user')
end
end
end

View File

@ -2,7 +2,7 @@
require 'spec_helper'
RSpec.describe Gitlab::Ci::Variables::Builder::Group do
RSpec.describe Gitlab::Ci::Variables::Builder::Group, feature_category: :secrets_management do
let_it_be(:group) { create(:group) }
let(:builder) { described_class.new(group) }
@ -185,21 +185,7 @@ RSpec.describe Gitlab::Ci::Variables::Builder::Group do
end
end
context 'recursive' do
before do
stub_feature_flags(use_traversal_ids: false)
end
include_examples 'correct ancestor order'
end
context 'linear' do
before do
stub_feature_flags(use_traversal_ids: true)
end
include_examples 'correct ancestor order'
end
include_examples 'correct ancestor order'
end
end
end

View File

@ -250,6 +250,7 @@ merge_requests:
- created_environments
- predictions
- user_agent_detail
- scan_result_policy_violations
external_pull_requests:
- project
merge_request_diff:
@ -823,6 +824,7 @@ project:
- design_management_repository_state
- compliance_standards_adherence
- scan_result_policy_reads
- scan_result_policy_violations
- project_state
- security_policy_bots
- target_branch_rules

View File

@ -2,7 +2,7 @@
require "spec_helper"
RSpec.describe Gitlab::ProtocolAccess do
RSpec.describe Gitlab::ProtocolAccess, feature_category: :source_code_management do
using RSpec::Parameterized::TableSyntax
let_it_be(:group) { create(:group) }
@ -10,25 +10,34 @@ RSpec.describe Gitlab::ProtocolAccess do
describe ".allowed?" do
where(:protocol, :project, :admin_setting, :namespace_setting, :expected_result) do
"web" | nil | nil | nil | true
"ssh" | nil | nil | nil | true
"http" | nil | nil | nil | true
"ssh" | nil | "" | nil | true
"http" | nil | "" | nil | true
"ssh" | nil | "ssh" | nil | true
"http" | nil | "http" | nil | true
"ssh" | nil | "http" | nil | false
"http" | nil | "ssh" | nil | false
"ssh" | ref(:p1) | nil | "all" | true
"http" | ref(:p1) | nil | "all" | true
"ssh" | ref(:p1) | nil | "ssh" | true
"http" | ref(:p1) | nil | "http" | true
"ssh" | ref(:p1) | nil | "http" | false
"http" | ref(:p1) | nil | "ssh" | false
"ssh" | ref(:p1) | "" | "all" | true
"http" | ref(:p1) | "" | "all" | true
"ssh" | ref(:p1) | "ssh" | "ssh" | true
"http" | ref(:p1) | "http" | "http" | true
"web" | nil | nil | nil | true
"ssh" | nil | nil | nil | true
"http" | nil | nil | nil | true
"ssh_certificates" | nil | nil | nil | true
"ssh" | nil | "" | nil | true
"http" | nil | "" | nil | true
"ssh_certificates" | nil | "" | nil | true
"ssh" | nil | "ssh" | nil | true
"http" | nil | "http" | nil | true
"ssh_certificates" | nil | "ssh_certificates" | nil | true
"ssh" | nil | "http" | nil | false
"http" | nil | "ssh" | nil | false
"ssh_certificates" | nil | "ssh" | nil | false
"ssh" | ref(:p1) | nil | "all" | true
"http" | ref(:p1) | nil | "all" | true
"ssh_certificates" | ref(:p1) | nil | "all" | true
"ssh" | ref(:p1) | nil | "ssh" | true
"http" | ref(:p1) | nil | "http" | true
"ssh_certificates" | ref(:p1) | nil | "ssh_certificates" | true
"ssh" | ref(:p1) | nil | "http" | false
"http" | ref(:p1) | nil | "ssh" | false
"ssh_certificates" | ref(:p1) | nil | "ssh" | false
"ssh" | ref(:p1) | "" | "all" | true
"http" | ref(:p1) | "" | "all" | true
"ssh_certificates" | ref(:p1) | "" | "all" | true
"ssh" | ref(:p1) | "ssh" | "ssh" | true
"http" | ref(:p1) | "http" | "http" | true
"ssh_certificates" | ref(:p1) | "ssh_certificates" | "ssh_certificates" | true
end
with_them do

View File

@ -0,0 +1,30 @@
# frozen_string_literal: true
require 'spec_helper'
require_migration!
RSpec.describe DeletePagesDomainWithReservedDomains, feature_category: :pages do
describe 'migrates' do
context 'when a reserved domain is provided' do
it 'delete the domain' do
table(:pages_domains).create!(domain: 'gmail.com', verification_code: 'gmail')
expect { migrate! }.to change { PagesDomain.count }.by(-1)
end
end
context 'when a reserved domain is provided with non standard case' do
it 'delete the domain' do
table(:pages_domains).create!(domain: 'AOl.com', verification_code: 'aol')
expect { migrate! }.to change { PagesDomain.count }.by(-1)
end
end
context 'when a non reserved domain is provided' do
it 'does not delete the domain' do
table(:pages_domains).create!(domain: 'example.com', verification_code: 'example')
expect { migrate! }.not_to change { PagesDomain.count }
expect(table(:pages_domains).find_by(domain: 'example.com')).not_to be_nil
end
end
end
end

View File

@ -309,19 +309,7 @@ RSpec.describe Ci::Runner, type: :model, feature_category: :runner do
end
end
context 'when use_traversal_ids* are enabled' do
it_behaves_like '.belonging_to_parent_groups_of_project'
end
context 'when use_traversal_ids* are disabled' do
before do
stub_feature_flags(
use_traversal_ids: false
)
end
it_behaves_like '.belonging_to_parent_groups_of_project'
end
it_behaves_like '.belonging_to_parent_groups_of_project'
context 'with instance runners sharing enabled' do
# group specific

View File

@ -683,160 +683,126 @@ RSpec.describe Group, feature_category: :groups_and_projects do
context 'traversal queries' do
let_it_be(:group, reload: true) { create(:group, :nested) }
context 'recursive' do
before do
stub_feature_flags(use_traversal_ids: false)
end
it_behaves_like 'namespace traversal'
it_behaves_like 'namespace traversal'
describe '#self_and_descendants' do
it { expect(group.self_and_descendants.to_sql).to include 'traversal_ids @>' }
end
describe '#self_and_descendants' do
it { expect(group.self_and_descendants.to_sql).not_to include 'traversal_ids @>' }
end
describe '#self_and_descendant_ids' do
it { expect(group.self_and_descendant_ids.to_sql).to include 'traversal_ids @>' }
end
describe '#self_and_descendant_ids' do
it { expect(group.self_and_descendant_ids.to_sql).not_to include 'traversal_ids @>' }
end
describe '#descendants' do
it { expect(group.descendants.to_sql).to include 'traversal_ids @>' }
end
describe '#descendants' do
it { expect(group.descendants.to_sql).not_to include 'traversal_ids @>' }
end
describe '#self_and_hierarchy' do
it { expect(group.self_and_hierarchy.to_sql).to include 'traversal_ids @>' }
end
describe '#self_and_hierarchy' do
it { expect(group.self_and_hierarchy.to_sql).not_to include 'traversal_ids @>' }
end
describe '#ancestors' do
it { expect(group.ancestors.to_sql).to include "\"namespaces\".\"id\" = #{group.parent_id}" }
describe '#ancestors' do
it { expect(group.ancestors.to_sql).not_to include 'traversal_ids <@' }
end
describe '.shortest_traversal_ids_prefixes' do
it { expect { described_class.shortest_traversal_ids_prefixes }.to raise_error /Feature not supported since the `:use_traversal_ids` is disabled/ }
it 'hierarchy order' do
expect(group.ancestors(hierarchy_order: :asc).to_sql).to include 'ORDER BY "depth" ASC'
end
end
context 'linear' do
it_behaves_like 'namespace traversal'
describe '#ancestors_upto' do
it { expect(group.ancestors_upto.to_sql).to include "WITH ORDINALITY" }
end
describe '#self_and_descendants' do
it { expect(group.self_and_descendants.to_sql).to include 'traversal_ids @>' }
end
describe '.shortest_traversal_ids_prefixes' do
subject { filter.shortest_traversal_ids_prefixes }
describe '#self_and_descendant_ids' do
it { expect(group.self_and_descendant_ids.to_sql).to include 'traversal_ids @>' }
end
context 'for many top-level namespaces' do
let!(:top_level_groups) { create_list(:group, 4) }
describe '#descendants' do
it { expect(group.descendants.to_sql).to include 'traversal_ids @>' }
end
context 'when querying all groups' do
let(:filter) { described_class.id_in(top_level_groups) }
describe '#self_and_hierarchy' do
it { expect(group.self_and_hierarchy.to_sql).to include 'traversal_ids @>' }
end
describe '#ancestors' do
it { expect(group.ancestors.to_sql).to include "\"namespaces\".\"id\" = #{group.parent_id}" }
it 'hierarchy order' do
expect(group.ancestors(hierarchy_order: :asc).to_sql).to include 'ORDER BY "depth" ASC'
end
end
describe '#ancestors_upto' do
it { expect(group.ancestors_upto.to_sql).to include "WITH ORDINALITY" }
end
describe '.shortest_traversal_ids_prefixes' do
subject { filter.shortest_traversal_ids_prefixes }
context 'for many top-level namespaces' do
let!(:top_level_groups) { create_list(:group, 4) }
context 'when querying all groups' do
let(:filter) { described_class.id_in(top_level_groups) }
it "returns all traversal_ids" do
is_expected.to contain_exactly(
*top_level_groups.map { |group| [group.id] }
)
end
end
context 'when querying selected groups' do
let(:filter) { described_class.id_in(top_level_groups.first) }
it "returns only a selected traversal_ids" do
is_expected.to contain_exactly([top_level_groups.first.id])
end
it "returns all traversal_ids" do
is_expected.to contain_exactly(
*top_level_groups.map { |group| [group.id] }
)
end
end
context 'for namespace hierarchy' do
let!(:group_a) { create(:group) }
let!(:group_a_sub_1) { create(:group, parent: group_a) }
let!(:group_a_sub_2) { create(:group, parent: group_a) }
let!(:group_b) { create(:group) }
let!(:group_b_sub_1) { create(:group, parent: group_b) }
let!(:group_c) { create(:group) }
context 'when querying selected groups' do
let(:filter) { described_class.id_in(top_level_groups.first) }
context 'when querying all groups' do
let(:filter) { described_class.id_in([group_a, group_a_sub_1, group_a_sub_2, group_b, group_b_sub_1, group_c]) }
it 'returns only shortest prefixes of top-level groups' do
is_expected.to contain_exactly(
[group_a.id],
[group_b.id],
[group_c.id]
)
end
end
context 'when sub-group is reparented' do
let(:filter) { described_class.id_in([group_b_sub_1, group_c]) }
before do
group_b_sub_1.update!(parent: group_c)
end
it 'returns a proper shortest prefix of a new group' do
is_expected.to contain_exactly(
[group_c.id]
)
end
end
context 'when querying sub-groups' do
let(:filter) { described_class.id_in([group_a_sub_1, group_b_sub_1, group_c]) }
it 'returns sub-groups as they are shortest prefixes' do
is_expected.to contain_exactly(
[group_a.id, group_a_sub_1.id],
[group_b.id, group_b_sub_1.id],
[group_c.id]
)
end
end
context 'when querying group and sub-group of this group' do
let(:filter) { described_class.id_in([group_a, group_a_sub_1, group_c]) }
it 'returns parent groups as this contains all sub-groups' do
is_expected.to contain_exactly(
[group_a.id],
[group_c.id]
)
end
it "returns only a selected traversal_ids" do
is_expected.to contain_exactly([top_level_groups.first.id])
end
end
end
context 'when project namespace exists in the group' do
let!(:project) { create(:project, group: group) }
let!(:project_namespace) { project.project_namespace }
context 'for namespace hierarchy' do
let!(:group_a) { create(:group) }
let!(:group_a_sub_1) { create(:group, parent: group_a) }
let!(:group_a_sub_2) { create(:group, parent: group_a) }
let!(:group_b) { create(:group) }
let!(:group_b_sub_1) { create(:group, parent: group_b) }
let!(:group_c) { create(:group) }
it 'filters out project namespace' do
expect(group.descendants.find_by_id(project_namespace.id)).to be_nil
context 'when querying all groups' do
let(:filter) { described_class.id_in([group_a, group_a_sub_1, group_a_sub_2, group_b, group_b_sub_1, group_c]) }
it 'returns only shortest prefixes of top-level groups' do
is_expected.to contain_exactly(
[group_a.id],
[group_b.id],
[group_c.id]
)
end
end
context 'when sub-group is reparented' do
let(:filter) { described_class.id_in([group_b_sub_1, group_c]) }
before do
group_b_sub_1.update!(parent: group_c)
end
it 'returns a proper shortest prefix of a new group' do
is_expected.to contain_exactly(
[group_c.id]
)
end
end
context 'when querying sub-groups' do
let(:filter) { described_class.id_in([group_a_sub_1, group_b_sub_1, group_c]) }
it 'returns sub-groups as they are shortest prefixes' do
is_expected.to contain_exactly(
[group_a.id, group_a_sub_1.id],
[group_b.id, group_b_sub_1.id],
[group_c.id]
)
end
end
context 'when querying group and sub-group of this group' do
let(:filter) { described_class.id_in([group_a, group_a_sub_1, group_c]) }
it 'returns parent groups as this contains all sub-groups' do
is_expected.to contain_exactly(
[group_a.id],
[group_c.id]
)
end
end
end
end
context 'when project namespace exists in the group' do
let!(:project) { create(:project, group: group) }
let!(:project_namespace) { project.project_namespace }
it 'filters out project namespace' do
expect(group.descendants.find_by_id(project_namespace.id)).to be_nil
end
end
end
@ -1683,6 +1649,14 @@ RSpec.describe Group, feature_category: :groups_and_projects do
it 'returns correct access level' do
expect(group.max_member_access_for_user(group_user)).to eq(Gitlab::Access::OWNER)
end
context 'when user is not active' do
let_it_be(:group_user) { create(:user, :deactivated) }
it 'returns NO_ACCESS' do
expect(group.max_member_access_for_user(group_user)).to eq(Gitlab::Access::NO_ACCESS)
end
end
end
context 'when user is nil' do

View File

@ -598,23 +598,7 @@ RSpec.describe Integration, feature_category: :integrations do
end
end
context 'recursive' do
before do
stub_feature_flags(use_traversal_ids: false)
end
include_examples 'correct ancestor order'
end
context 'linear' do
before do
stub_feature_flags(use_traversal_ids: true)
sub_subgroup.reload # make sure traversal_ids are reloaded
end
include_examples 'correct ancestor order'
end
include_examples 'correct ancestor order'
end
end
end

View File

@ -12,7 +12,7 @@ RSpec.describe NamespaceSetting, feature_category: :groups_and_projects, type: :
end
it { is_expected.to define_enum_for(:jobs_to_be_done).with_values([:basics, :move_repository, :code_storage, :exploring, :ci, :other]).with_suffix }
it { is_expected.to define_enum_for(:enabled_git_access_protocol).with_values([:all, :ssh, :http]).with_suffix }
it { is_expected.to define_enum_for(:enabled_git_access_protocol).with_suffix }
describe 'default values' do
subject(:setting) { described_class.new }

View File

@ -661,23 +661,7 @@ RSpec.describe Namespace, feature_category: :groups_and_projects do
end
context 'traversal scopes' do
context 'recursive' do
before do
stub_feature_flags(use_traversal_ids: false)
end
it_behaves_like 'namespace traversal scopes'
end
context 'linear' do
it_behaves_like 'namespace traversal scopes'
end
shared_examples 'makes recursive queries' do
specify do
expect { subject }.to make_queries_matching(/WITH RECURSIVE/)
end
end
it_behaves_like 'namespace traversal scopes'
shared_examples 'does not make recursive queries' do
specify do
@ -691,14 +675,6 @@ RSpec.describe Namespace, feature_category: :groups_and_projects do
subject { described_class.where(id: namespace).self_and_descendants.load }
it_behaves_like 'does not make recursive queries'
context 'when feature flag :use_traversal_ids is disabled' do
before do
stub_feature_flags(use_traversal_ids: false)
end
it_behaves_like 'makes recursive queries'
end
end
describe '.self_and_descendant_ids' do
@ -707,14 +683,6 @@ RSpec.describe Namespace, feature_category: :groups_and_projects do
subject { described_class.where(id: namespace).self_and_descendant_ids.load }
it_behaves_like 'does not make recursive queries'
context 'when feature flag :use_traversal_ids is disabled' do
before do
stub_feature_flags(use_traversal_ids: false)
end
it_behaves_like 'makes recursive queries'
end
end
end
@ -1292,30 +1260,6 @@ RSpec.describe Namespace, feature_category: :groups_and_projects do
it { is_expected.to eq false }
end
describe '#use_traversal_ids?' do
let_it_be(:namespace, reload: true) { create(:namespace) }
subject { namespace.use_traversal_ids? }
context 'when use_traversal_ids feature flag is true' do
before do
stub_feature_flags(use_traversal_ids: true)
end
it { is_expected.to eq true }
it_behaves_like 'disabled feature flag when traversal_ids is blank'
end
context 'when use_traversal_ids feature flag is false' do
before do
stub_feature_flags(use_traversal_ids: false)
end
it { is_expected.to eq false }
end
end
describe '#users_with_descendants' do
let(:user_a) { create(:user) }
let(:user_b) { create(:user) }
@ -1419,28 +1363,14 @@ RSpec.describe Namespace, feature_category: :groups_and_projects do
end
describe '#all_projects' do
context 'with use_traversal_ids feature flag enabled' do
before do
stub_feature_flags(use_traversal_ids: true)
end
include_examples '#all_projects'
include_examples '#all_projects'
# Using #self_and_descendant instead of #self_and_descendant_ids can produce
# very slow queries.
it 'calls self_and_descendant_ids' do
namespace = create(:group)
expect(namespace).to receive(:self_and_descendant_ids)
namespace.all_projects
end
end
context 'with use_traversal_ids feature flag disabled' do
before do
stub_feature_flags(use_traversal_ids: false)
end
include_examples '#all_projects'
# Using #self_and_descendant instead of #self_and_descendant_ids can produce
# very slow queries.
it 'calls self_and_descendant_ids' do
namespace = create(:group)
expect(namespace).to receive(:self_and_descendant_ids)
namespace.all_projects
end
end

View File

@ -2,7 +2,7 @@
require 'spec_helper'
RSpec.describe PagesDomain do
RSpec.describe PagesDomain, feature_category: :pages do
using RSpec::Parameterized::TableSyntax
subject(:pages_domain) { described_class.new }

View File

@ -2,7 +2,7 @@
require 'spec_helper'
RSpec.describe Preloaders::ProjectRootAncestorPreloader do
RSpec.describe Preloaders::ProjectRootAncestorPreloader, feature_category: :system_access do
let_it_be(:root_parent1) { create(:group, :private, name: 'root-1', path: 'root-1') }
let_it_be(:root_parent2) { create(:group, name: 'root-2', path: 'root-2') }
let_it_be(:guest_project) { create(:project, name: 'public guest', path: 'public-guest') }
@ -43,87 +43,47 @@ RSpec.describe Preloaders::ProjectRootAncestorPreloader do
end
end
context 'when use_traversal_ids FF is enabled' do
context 'when the preloader is used' do
context 'when no additional preloads are provided' do
before do
preload_ancestors(:group)
end
it_behaves_like 'executes N matching DB queries', 0
end
context 'when additional preloads are provided' do
let(:additional_preloads) { [:route] }
let(:root_query_regex) { /\ASELECT.+FROM "routes" WHERE "routes"."source_id" = \d+/ }
before do
preload_ancestors
end
it_behaves_like 'executes N matching DB queries', 0, :full_path
end
context 'when projects are an array and not an ActiveRecord::Relation' do
before do
described_class.new(projects, :namespace, additional_preloads).execute
end
it_behaves_like 'executes N matching DB queries', 4
end
end
context 'when the preloader is not used' do
it_behaves_like 'executes N matching DB queries', 4
end
context 'when using a :group sti name and passing projects in a user namespace' do
let(:projects) { [private_developer_project] }
let(:additional_preloads) { [:ip_restrictions, :saml_provider] }
it 'does not load a nil value for root_ancestor' do
context 'when the preloader is used' do
context 'when no additional preloads are provided' do
before do
preload_ancestors(:group)
expect(pristine_projects.first.root_ancestor).to eq(private_developer_project.root_ancestor)
end
end
end
context 'when use_traversal_ids FF is disabled' do
before do
stub_feature_flags(use_traversal_ids: false)
it_behaves_like 'executes N matching DB queries', 0
end
context 'when the preloader is used' do
context 'when additional preloads are provided' do
let(:additional_preloads) { [:route] }
let(:root_query_regex) { /\ASELECT.+FROM "routes" WHERE "routes"."source_id" = \d+/ }
before do
preload_ancestors
end
context 'when no additional preloads are provided' do
it_behaves_like 'executes N matching DB queries', 4
end
context 'when additional preloads are provided' do
let(:additional_preloads) { [:route] }
let(:root_query_regex) { /\ASELECT.+FROM "routes" WHERE "routes"."source_id" = \d+/ }
it_behaves_like 'executes N matching DB queries', 4, :full_path
end
it_behaves_like 'executes N matching DB queries', 0, :full_path
end
context 'when the preloader is not used' do
context 'when projects are an array and not an ActiveRecord::Relation' do
before do
described_class.new(projects, :namespace, additional_preloads).execute
end
it_behaves_like 'executes N matching DB queries', 4
end
end
context 'when using a :group sti name and passing projects in a user namespace' do
let(:projects) { [private_developer_project] }
let(:additional_preloads) { [:ip_restrictions, :saml_provider] }
context 'when the preloader is not used' do
it_behaves_like 'executes N matching DB queries', 4
end
it 'does not load a nil value for root_ancestor' do
preload_ancestors(:group)
context 'when using a :group sti name and passing projects in a user namespace' do
let(:projects) { [private_developer_project] }
let(:additional_preloads) { [:ip_restrictions, :saml_provider] }
expect(pristine_projects.first.root_ancestor).to eq(private_developer_project.root_ancestor)
end
it 'does not load a nil value for root_ancestor' do
preload_ancestors(:group)
expect(pristine_projects.first.root_ancestor).to eq(private_developer_project.root_ancestor)
end
end

View File

@ -34,46 +34,31 @@ RSpec.describe Preloaders::UserMaxAccessLevelInGroupsPreloader, feature_category
let(:groups) { [group1, group2, group3, child_maintainer, child_indirect_access] }
context 'when traversal_ids feature flag is disabled' do
it_behaves_like 'executes N max member permission queries to the DB' do
before do
stub_feature_flags(use_traversal_ids: false)
described_class.new(groups, user).execute
end
# One query for group with no access and another one per group where the user is not a direct member
let(:expected_query_count) { 2 }
it_behaves_like 'executes N max member permission queries to the DB' do
before do
described_class.new(groups, user).execute
end
let(:expected_query_count) { 0 }
end
context 'when traversal_ids feature flag is enabled' do
it_behaves_like 'executes N max member permission queries to the DB' do
before do
stub_feature_flags(use_traversal_ids: true)
described_class.new(groups, user).execute
end
context 'for groups arising from group shares' do
let_it_be(:group4) { create(:group, :private) }
let_it_be(:group4_subgroup) { create(:group, :private, parent: group4) }
let(:expected_query_count) { 0 }
let(:groups) { [group4, group4_subgroup] }
before do
create(:group_group_link, :guest, shared_with_group: group1, shared_group: group4)
end
context 'for groups arising from group shares' do
let_it_be(:group4) { create(:group, :private) }
let_it_be(:group4_subgroup) { create(:group, :private, parent: group4) }
it 'sets the right access level in cache for groups arising from group shares' do
described_class.new(groups, user).execute
let(:groups) { [group4, group4_subgroup] }
groups.each do |group|
cached_access_level = group.max_member_access_for_user(user)
before do
create(:group_group_link, :guest, shared_with_group: group1, shared_group: group4)
end
it 'sets the right access level in cache for groups arising from group shares' do
described_class.new(groups, user).execute
groups.each do |group|
cached_access_level = group.max_member_access_for_user(user)
expect(cached_access_level).to eq(Gitlab::Access::GUEST)
end
expect(cached_access_level).to eq(Gitlab::Access::GUEST)
end
end
end

View File

@ -5073,14 +5073,6 @@ RSpec.describe User, feature_category: :user_profile do
describe '#ci_owned_runners' do
it_behaves_like '#ci_owned_runners'
context 'when FF use_traversal_ids is disabled fallbacks to inefficient implementation' do
before do
stub_feature_flags(use_traversal_ids: false)
end
it_behaves_like '#ci_owned_runners'
end
end
describe '#projects_with_reporter_access_limited_to' do

View File

@ -145,14 +145,6 @@ RSpec.describe Ci::ProcessSyncEventsService, feature_category: :continuous_integ
end
end
context 'when the use_traversal_ids FF is disabled' do
before do
stub_feature_flags(use_traversal_ids: false)
end
it_behaves_like 'event consuming'
end
it_behaves_like 'event consuming'
it 'enqueues Namespaces::ProcessSyncEventsWorker if any left' do

View File

@ -14,9 +14,21 @@ RSpec.shared_context 'exposing regular notes on a noteable in GraphQL' do
let(:user) { note.author }
context 'for regular notes' do
let!(:system_note) do
create(
:note,
system: true,
noteable: noteable,
project: (noteable.project if noteable.respond_to?(:project))
)
end
let(:filters) { "" }
let(:query) do
note_fields = <<~NOTES
notes {
notes #{filters} {
count
edges {
node {
#{all_graphql_fields_for('Note', max_depth: 1)}
@ -42,11 +54,12 @@ RSpec.shared_context 'exposing regular notes on a noteable in GraphQL' do
end
end
it 'includes the note' do
it 'includes all notes' do
post_graphql(query, current_user: user)
expect(noteable_data['notes']['edges'].first['node']['body'])
.to eq(note.note)
expect(noteable_data['notes']['count']).to eq(2)
expect(noteable_data['notes']['edges'][0]['node']['body']).to eq(system_note.note)
expect(noteable_data['notes']['edges'][1]['node']['body']).to eq(note.note)
end
it 'avoids N+1 queries' do
@ -69,6 +82,42 @@ RSpec.shared_context 'exposing regular notes on a noteable in GraphQL' do
expect { post_graphql(query, current_user: user) }.not_to exceed_query_limit(control)
expect_graphql_errors_to_be_empty
end
context 'when filter is provided' do
context 'when filter is set to ALL_NOTES' do
let(:filters) { "(filter: ALL_NOTES)" }
it 'returns all the notes' do
post_graphql(query, current_user: user)
expect(noteable_data['notes']['count']).to eq(2)
expect(noteable_data['notes']['edges'][0]['node']['body']).to eq(system_note.note)
expect(noteable_data['notes']['edges'][1]['node']['body']).to eq(note.note)
end
end
context 'when filter is set to ONLY_COMMENTS' do
let(:filters) { "(filter: ONLY_COMMENTS)" }
it 'returns only the comments' do
post_graphql(query, current_user: user)
expect(noteable_data['notes']['count']).to eq(1)
expect(noteable_data['notes']['edges'][0]['node']['body']).to eq(note.note)
end
end
context 'when filter is set to ONLY_ACTIVITY' do
let(:filters) { "(filter: ONLY_ACTIVITY)" }
it 'returns only the activity notes' do
post_graphql(query, current_user: user)
expect(noteable_data['notes']['count']).to eq(1)
expect(noteable_data['notes']['edges'][0]['node']['body']).to eq(system_note.note)
end
end
end
end
context "for discussions" do

View File

@ -240,14 +240,6 @@ RSpec.shared_examples 'namespace traversal' do
describe '#ancestors_upto' do
include_examples '#ancestors_upto'
context 'with use_traversal_ids disabled' do
before do
stub_feature_flags(use_traversal_ids: false)
end
include_examples '#ancestors_upto'
end
end
describe '#descendants' do

View File

@ -70,28 +70,10 @@ RSpec.shared_examples 'namespace traversal scopes' do
end
describe '.roots' do
context "use_traversal_ids feature flag is true" do
before do
stub_feature_flags(use_traversal_ids: true)
end
it_behaves_like '.roots'
it_behaves_like '.roots'
it 'not make recursive queries' do
expect { described_class.where(id: [nested_group_1]).roots.load }.not_to make_queries_matching(/WITH RECURSIVE/)
end
end
context "use_traversal_ids feature flag is false" do
before do
stub_feature_flags(use_traversal_ids: false)
end
it_behaves_like '.roots'
it 'makes recursive queries' do
expect { described_class.where(id: [nested_group_1]).roots.load }.to make_queries_matching(/WITH RECURSIVE/)
end
it 'not make recursive queries' do
expect { described_class.where(id: [nested_group_1]).roots.load }.not_to make_queries_matching(/WITH RECURSIVE/)
end
end