Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
7131c1e219
commit
4abd579c45
|
|
@ -3736,11 +3736,6 @@ Gitlab/BoundedContexts:
|
|||
- 'ee/app/workers/ldap_sync_worker.rb'
|
||||
- 'ee/app/workers/licenses/reset_submit_license_usage_data_banner_worker.rb'
|
||||
- 'ee/app/workers/llm/completion_worker.rb'
|
||||
- 'ee/app/workers/llm/embedding/gitlab_documentation/cleanup_previous_versions_records_worker.rb'
|
||||
- 'ee/app/workers/llm/embedding/gitlab_documentation/create_db_embeddings_per_doc_file_worker.rb'
|
||||
- 'ee/app/workers/llm/embedding/gitlab_documentation/create_embeddings_records_worker.rb'
|
||||
- 'ee/app/workers/llm/embedding/gitlab_documentation/embeddings_worker_context.rb'
|
||||
- 'ee/app/workers/llm/embedding/gitlab_documentation/set_embeddings_on_the_record_worker.rb'
|
||||
- 'ee/app/workers/llm/namespace_access_cache_reset_worker.rb'
|
||||
- 'ee/app/workers/llm/vertex_ai_access_token_refresh_worker.rb'
|
||||
- 'ee/app/workers/members_destroyer/clean_up_group_protected_branch_rules_worker.rb'
|
||||
|
|
|
|||
|
|
@ -139,10 +139,6 @@ Gitlab/FeatureFlagWithoutActor:
|
|||
- 'ee/app/views/projects/settings/merge_requests/_merge_trains_settings.html.haml'
|
||||
- 'ee/app/workers/elastic/migration_worker.rb'
|
||||
- 'ee/app/workers/gitlab_subscriptions/add_on_purchases/schedule_bulk_refresh_user_assignments_worker.rb'
|
||||
- 'ee/app/workers/llm/embedding/gitlab_documentation/cleanup_previous_versions_records_worker.rb'
|
||||
- 'ee/app/workers/llm/embedding/gitlab_documentation/create_db_embeddings_per_doc_file_worker.rb'
|
||||
- 'ee/app/workers/llm/embedding/gitlab_documentation/create_embeddings_records_worker.rb'
|
||||
- 'ee/app/workers/llm/embedding/gitlab_documentation/set_embeddings_on_the_record_worker.rb'
|
||||
- 'ee/app/workers/llm/vertex_ai_access_token_refresh_worker.rb'
|
||||
- 'ee/app/workers/search/index_curation_worker.rb'
|
||||
- 'ee/app/workers/search/zoekt/scheduling_worker.rb'
|
||||
|
|
|
|||
|
|
@ -1570,8 +1570,6 @@ Style/InlineDisableAnnotation:
|
|||
- 'ee/app/workers/ldap_group_sync_worker.rb'
|
||||
- 'ee/app/workers/ldap_sync_worker.rb'
|
||||
- 'ee/app/workers/licenses/reset_submit_license_usage_data_banner_worker.rb'
|
||||
- 'ee/app/workers/llm/embedding/gitlab_documentation/cleanup_previous_versions_records_worker.rb'
|
||||
- 'ee/app/workers/llm/embedding/gitlab_documentation/create_db_embeddings_per_doc_file_worker.rb'
|
||||
- 'ee/app/workers/members_destroyer/clean_up_group_protected_branch_rules_worker.rb'
|
||||
- 'ee/app/workers/merge_request_reset_approvals_worker.rb'
|
||||
- 'ee/app/workers/new_epic_worker.rb'
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
412263801bb4a37fdf09aed95269342369dc74a7
|
||||
47c3c8bc2d5a93e83eee6b250a06e4c39d9c929c
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
v17.2.0-rc1
|
||||
v17.2.0-rc2
|
||||
|
|
|
|||
|
|
@ -164,7 +164,7 @@ export default {
|
|||
return referencePath.slice(0, referencePath.indexOf('#'));
|
||||
},
|
||||
showWorkItemEpics() {
|
||||
return this.glFeatures.displayWorkItemEpicIssueSidebar;
|
||||
return this.glFeatures.workItemEpics;
|
||||
},
|
||||
showEpicSidebarDropdownWidget() {
|
||||
return this.epicFeatureAvailable && !this.isIncidentSidebar && this.activeBoardIssuable.id;
|
||||
|
|
|
|||
|
|
@ -99,7 +99,7 @@ export default {
|
|||
errorTexts: {
|
||||
[LOAD_FAILURE]: __('We are currently unable to fetch data for this graph.'),
|
||||
[PARSE_FAILURE]: __('There was an error parsing the data for this graph.'),
|
||||
[UNSUPPORTED_DATA]: __('DAG visualization requires at least 3 dependent jobs.'),
|
||||
[UNSUPPORTED_DATA]: __('Needs visualization requires at least 3 dependent jobs.'),
|
||||
[DEFAULT]: __('An unknown error occurred while loading this graph.'),
|
||||
},
|
||||
emptyStateTexts: {
|
||||
|
|
@ -108,9 +108,9 @@ export default {
|
|||
'Using the %{codeStart}needs%{codeEnd} keyword makes jobs run before their stage is reached. Jobs run as soon as their %{codeStart}needs%{codeEnd} relationships are met, which speeds up your pipelines.',
|
||||
),
|
||||
secondDescription: __(
|
||||
"If you add %{codeStart}needs%{codeEnd} to jobs in your pipeline you'll be able to view the %{codeStart}needs%{codeEnd} relationships between jobs in this tab as a %{linkStart}Directed Acyclic Graph (DAG)%{linkEnd}.",
|
||||
"If you add %{codeStart}needs%{codeEnd} to jobs in your pipeline you'll be able to view the %{codeStart}needs%{codeEnd} dependencies between jobs in this tab.",
|
||||
),
|
||||
button: __('Learn more about Needs relationships'),
|
||||
button: __('Learn more about needs dependencies'),
|
||||
},
|
||||
computed: {
|
||||
failure() {
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ class Groups::BoardsController < Groups::ApplicationController
|
|||
|
||||
before_action do
|
||||
push_frontend_feature_flag(:board_multi_select, group)
|
||||
push_frontend_feature_flag(:display_work_item_epic_issue_sidebar, group)
|
||||
end
|
||||
|
||||
feature_category :team_planning
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ class Projects::BoardsController < Projects::ApplicationController
|
|||
before_action :check_issues_available!
|
||||
before_action do
|
||||
push_frontend_feature_flag(:board_multi_select, project)
|
||||
push_frontend_feature_flag(:display_work_item_epic_issue_sidebar, project)
|
||||
end
|
||||
|
||||
feature_category :team_planning
|
||||
|
|
|
|||
|
|
@ -48,7 +48,6 @@ class Projects::IssuesController < Projects::ApplicationController
|
|||
push_frontend_feature_flag(:issues_grid_view)
|
||||
push_frontend_feature_flag(:service_desk_ticket)
|
||||
push_frontend_feature_flag(:issues_list_drawer, project)
|
||||
push_frontend_feature_flag(:display_work_item_epic_issue_sidebar, project)
|
||||
push_frontend_feature_flag(:notifications_todos_buttons, current_user)
|
||||
end
|
||||
|
||||
|
|
@ -66,7 +65,6 @@ class Projects::IssuesController < Projects::ApplicationController
|
|||
push_force_frontend_feature_flag(:work_items_beta, project&.work_items_beta_feature_flag_enabled?)
|
||||
push_force_frontend_feature_flag(:work_items_alpha, project&.work_items_alpha_feature_flag_enabled?)
|
||||
push_frontend_feature_flag(:epic_widget_edit_confirmation, project)
|
||||
push_frontend_feature_flag(:display_work_item_epic_issue_sidebar, project)
|
||||
push_frontend_feature_flag(:namespace_level_work_items, project&.group)
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ module Mutations
|
|||
:replace_ids
|
||||
end
|
||||
|
||||
response = ::Issues::SetCrmContactsService.new(project: project, current_user: current_user, params: { attribute_name => contact_ids })
|
||||
response = ::Issues::SetCrmContactsService.new(container: project, current_user: current_user, params: { attribute_name => contact_ids })
|
||||
.execute(issue)
|
||||
|
||||
{
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ module PlanLimitsHelper
|
|||
when :ci_pipeline_schedules
|
||||
s_('AdminSettings|Maximum number of pipeline schedules')
|
||||
when :ci_needs_size_limit
|
||||
s_('AdminSettings|Maximum number of DAG dependencies that a job can have')
|
||||
s_('AdminSettings|Maximum number of needs dependencies that a job can have')
|
||||
when :ci_registered_group_runners
|
||||
s_('AdminSettings|Maximum number of runners registered per group')
|
||||
when :ci_registered_project_runners
|
||||
|
|
|
|||
|
|
@ -40,6 +40,10 @@ class BaseContainerService
|
|||
end
|
||||
strong_memoize_attr :project_group
|
||||
|
||||
def root_ancestor
|
||||
project_group&.root_ancestor || group&.root_ancestor
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def handle_container_type(container)
|
||||
|
|
|
|||
|
|
@ -301,7 +301,7 @@ class IssuableBaseService < ::BaseContainerService
|
|||
def set_crm_contacts(issuable, add_crm_contact_emails, remove_crm_contact_emails = [])
|
||||
return unless add_crm_contact_emails.present? || remove_crm_contact_emails.present?
|
||||
|
||||
::Issues::SetCrmContactsService.new(project: project, current_user: current_user, params: { add_emails: add_crm_contact_emails, remove_emails: remove_crm_contact_emails }).execute(issuable)
|
||||
::Issues::SetCrmContactsService.new(container: project, current_user: current_user, params: { add_emails: add_crm_contact_emails, remove_emails: remove_crm_contact_emails }).execute(issuable)
|
||||
end
|
||||
|
||||
def before_create(issuable)
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Issues
|
||||
class SetCrmContactsService < ::BaseProjectService
|
||||
class SetCrmContactsService < ::BaseContainerService
|
||||
MAX_ADDITIONAL_CONTACTS = 6
|
||||
|
||||
# Replacing contacts by email is not currently supported
|
||||
|
|
@ -52,7 +52,7 @@ module Issues
|
|||
end
|
||||
|
||||
def add_by_email
|
||||
contact_ids = ::CustomerRelations::Contact.find_ids_by_emails(project_group.root_ancestor, emails(:add_emails))
|
||||
contact_ids = ::CustomerRelations::Contact.find_ids_by_emails(container.root_ancestor, emails(:add_emails))
|
||||
add_by_id(contact_ids)
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -114,7 +114,7 @@
|
|||
.form-group
|
||||
= f.label :ci_needs_size_limit, plan_limit_setting_description(:ci_needs_size_limit)
|
||||
= f.number_field :ci_needs_size_limit, class: 'form-control gl-form-input'
|
||||
.form-text.text-muted= s_('AdminSettings|This limit cannot be disabled. Set to 0 to block all DAG dependencies.')
|
||||
.form-text.text-muted= s_('AdminSettings|This limit cannot be disabled. Set to 0 to block all job (needs) dependencies.')
|
||||
.form-group
|
||||
= f.label :ci_registered_group_runners, plan_limit_setting_description(:ci_registered_group_runners)
|
||||
= f.number_field :ci_registered_group_runners, class: 'form-control gl-form-input'
|
||||
|
|
|
|||
|
|
@ -13,11 +13,7 @@ module Gitlab
|
|||
|
||||
importer.execute
|
||||
|
||||
if Feature.enabled?(:bitbucket_cloud_convert_mentions_to_users, project.creator)
|
||||
return ImportUsersWorker.perform_async(project.id)
|
||||
end
|
||||
|
||||
ImportPullRequestsWorker.perform_async(project.id)
|
||||
ImportUsersWorker.perform_async(project.id)
|
||||
end
|
||||
|
||||
def importer_class
|
||||
|
|
|
|||
|
|
@ -1,8 +0,0 @@
|
|||
---
|
||||
name: display_work_item_epic_issue_sidebar
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/135480
|
||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/430337
|
||||
milestone: '16.8'
|
||||
type: development
|
||||
group: group::product planning
|
||||
default_enabled: false
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
---
|
||||
name: bitbucket_cloud_convert_mentions_to_users
|
||||
feature_issue_url:
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/144923
|
||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/442484
|
||||
milestone: '16.10'
|
||||
group: group::import and integrate
|
||||
type: gitlab_com_derisk
|
||||
default_enabled: false
|
||||
|
|
@ -824,12 +824,6 @@ Gitlab.ee do
|
|||
Settings.cron_jobs['sync_service_token_worker'] ||= {}
|
||||
Settings.cron_jobs['sync_service_token_worker']['cron'] ||= "#{rand(60)} #{rand(5..6)} * * * UTC"
|
||||
Settings.cron_jobs['sync_service_token_worker']['job_class'] = '::CloudConnector::SyncServiceTokenWorker'
|
||||
Settings.cron_jobs['llm_embedding_gitlab_documentation_create_embeddings_records_worker'] ||= {}
|
||||
Settings.cron_jobs['llm_embedding_gitlab_documentation_create_embeddings_records_worker']['cron'] ||= '0 5 * * 1,2,3,4,5'
|
||||
Settings.cron_jobs['llm_embedding_gitlab_documentation_create_embeddings_records_worker']['job_class'] ||= 'Llm::Embedding::GitlabDocumentation::CreateEmbeddingsRecordsWorker'
|
||||
Settings.cron_jobs['llm_embedding_gitlab_documentation_cleanup_previous_versions_records_worker'] ||= {}
|
||||
Settings.cron_jobs['llm_embedding_gitlab_documentation_cleanup_previous_versions_records_worker']['cron'] ||= '0 0 * * *'
|
||||
Settings.cron_jobs['llm_embedding_gitlab_documentation_cleanup_previous_versions_records_worker']['job_class'] ||= 'Llm::Embedding::GitlabDocumentation::CleanupPreviousVersionsRecordsWorker'
|
||||
Settings.cron_jobs['users_create_statistics_worker'] ||= {}
|
||||
Settings.cron_jobs['users_create_statistics_worker']['cron'] ||= '2 15 * * *'
|
||||
Settings.cron_jobs['users_create_statistics_worker']['job_class'] = 'Users::CreateStatisticsWorker'
|
||||
|
|
|
|||
|
|
@ -463,10 +463,6 @@
|
|||
- 2
|
||||
- - llm_completion
|
||||
- 1
|
||||
- - llm_embedding_gitlab_documentation_create_db_embeddings_per_doc_file
|
||||
- 1
|
||||
- - llm_embedding_gitlab_documentation_set_embeddings_on_the_record
|
||||
- 1
|
||||
- - llm_namespace_access_cache_reset
|
||||
- 1
|
||||
- - llm_vertex_ai_access_token_refresh
|
||||
|
|
|
|||
|
|
@ -5,6 +5,8 @@ PIPELINE_CHANGES_MESSAGE = <<~MSG
|
|||
|
||||
This merge request contains changes to the pipeline configuration for the GitLab project.
|
||||
|
||||
Please run `spec/dot_gitlab_ci/job_dependency_spec.rb` locally to confirm that the configuration is valid. This test can be slow and is quarantined in CI for now.
|
||||
|
||||
Please consider the effect of the changes in this merge request on the following:
|
||||
- Effects on different [pipeline types](https://docs.gitlab.com/ee/development/pipelines/index.html#pipelines-types-for-merge-requests)
|
||||
- Effects on non-canonical projects:
|
||||
|
|
|
|||
|
|
@ -0,0 +1,43 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class CleanupBigintConversionsForPCiBuildsAttempt2 < Gitlab::Database::Migration[2.2]
|
||||
include Gitlab::Database::SchemaHelpers
|
||||
|
||||
milestone '17.3'
|
||||
|
||||
enable_lock_retries!
|
||||
|
||||
TABLE_NAME = :p_ci_builds
|
||||
TRIGGER_NAME = :trigger_10ee1357e825
|
||||
COLUMN_NAMES = %i[
|
||||
auto_canceled_by_id
|
||||
commit_id
|
||||
erased_by_id
|
||||
project_id
|
||||
runner_id
|
||||
trigger_request_id
|
||||
upstream_pipeline_id
|
||||
user_id
|
||||
]
|
||||
|
||||
def up
|
||||
return unless trigger_and_integer_columns_exists?
|
||||
|
||||
lock_tables(TABLE_NAME, mode: :access_exclusive, only: true)
|
||||
lock_tables(TABLE_NAME, mode: :access_exclusive)
|
||||
cleanup_conversion_of_integer_to_bigint(TABLE_NAME, COLUMN_NAMES)
|
||||
end
|
||||
|
||||
def down
|
||||
return if trigger_and_integer_columns_exists?
|
||||
|
||||
restore_conversion_of_integer_to_bigint(TABLE_NAME, COLUMN_NAMES)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def trigger_and_integer_columns_exists?
|
||||
trigger_exists?(TABLE_NAME, TRIGGER_NAME) && \
|
||||
COLUMN_NAMES.all? { |name| column_exists?(TABLE_NAME, "#{name}_convert_to_bigint") }
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1 @@
|
|||
3b33d9061546cc040f69ff79fbe381cb4578ef134143281ee85e2547933f551e
|
||||
|
|
@ -841,22 +841,6 @@ RETURN NEW;
|
|||
END
|
||||
$$;
|
||||
|
||||
CREATE FUNCTION trigger_10ee1357e825() RETURNS trigger
|
||||
LANGUAGE plpgsql
|
||||
AS $$
|
||||
BEGIN
|
||||
NEW."auto_canceled_by_id_convert_to_bigint" := NEW."auto_canceled_by_id";
|
||||
NEW."commit_id_convert_to_bigint" := NEW."commit_id";
|
||||
NEW."erased_by_id_convert_to_bigint" := NEW."erased_by_id";
|
||||
NEW."project_id_convert_to_bigint" := NEW."project_id";
|
||||
NEW."runner_id_convert_to_bigint" := NEW."runner_id";
|
||||
NEW."trigger_request_id_convert_to_bigint" := NEW."trigger_request_id";
|
||||
NEW."upstream_pipeline_id_convert_to_bigint" := NEW."upstream_pipeline_id";
|
||||
NEW."user_id_convert_to_bigint" := NEW."user_id";
|
||||
RETURN NEW;
|
||||
END;
|
||||
$$;
|
||||
|
||||
CREATE FUNCTION trigger_13d4aa8fe3dd() RETURNS trigger
|
||||
LANGUAGE plpgsql
|
||||
AS $$
|
||||
|
|
@ -2172,23 +2156,17 @@ CREATE TABLE p_ci_builds (
|
|||
created_at timestamp without time zone,
|
||||
updated_at timestamp without time zone,
|
||||
started_at timestamp without time zone,
|
||||
runner_id_convert_to_bigint integer,
|
||||
coverage double precision,
|
||||
commit_id_convert_to_bigint integer,
|
||||
name character varying,
|
||||
options text,
|
||||
allow_failure boolean DEFAULT false NOT NULL,
|
||||
stage character varying,
|
||||
trigger_request_id_convert_to_bigint integer,
|
||||
stage_idx integer,
|
||||
tag boolean,
|
||||
ref character varying,
|
||||
user_id_convert_to_bigint integer,
|
||||
type character varying,
|
||||
target_url character varying,
|
||||
description character varying,
|
||||
project_id_convert_to_bigint integer,
|
||||
erased_by_id_convert_to_bigint integer,
|
||||
erased_at timestamp without time zone,
|
||||
artifacts_expire_at timestamp without time zone,
|
||||
environment character varying,
|
||||
|
|
@ -2197,13 +2175,11 @@ CREATE TABLE p_ci_builds (
|
|||
queued_at timestamp without time zone,
|
||||
lock_version integer DEFAULT 0,
|
||||
coverage_regex character varying,
|
||||
auto_canceled_by_id_convert_to_bigint integer,
|
||||
retried boolean,
|
||||
protected boolean,
|
||||
failure_reason integer,
|
||||
scheduled_at timestamp with time zone,
|
||||
token_encrypted character varying,
|
||||
upstream_pipeline_id_convert_to_bigint integer,
|
||||
resource_group_id bigint,
|
||||
waiting_for_resource_at timestamp with time zone,
|
||||
processed boolean,
|
||||
|
|
@ -7497,23 +7473,17 @@ CREATE TABLE ci_builds (
|
|||
created_at timestamp without time zone,
|
||||
updated_at timestamp without time zone,
|
||||
started_at timestamp without time zone,
|
||||
runner_id_convert_to_bigint integer,
|
||||
coverage double precision,
|
||||
commit_id_convert_to_bigint integer,
|
||||
name character varying,
|
||||
options text,
|
||||
allow_failure boolean DEFAULT false NOT NULL,
|
||||
stage character varying,
|
||||
trigger_request_id_convert_to_bigint integer,
|
||||
stage_idx integer,
|
||||
tag boolean,
|
||||
ref character varying,
|
||||
user_id_convert_to_bigint integer,
|
||||
type character varying,
|
||||
target_url character varying,
|
||||
description character varying,
|
||||
project_id_convert_to_bigint integer,
|
||||
erased_by_id_convert_to_bigint integer,
|
||||
erased_at timestamp without time zone,
|
||||
artifacts_expire_at timestamp without time zone,
|
||||
environment character varying,
|
||||
|
|
@ -7522,13 +7492,11 @@ CREATE TABLE ci_builds (
|
|||
queued_at timestamp without time zone,
|
||||
lock_version integer DEFAULT 0,
|
||||
coverage_regex character varying,
|
||||
auto_canceled_by_id_convert_to_bigint integer,
|
||||
retried boolean,
|
||||
protected boolean,
|
||||
failure_reason integer,
|
||||
scheduled_at timestamp with time zone,
|
||||
token_encrypted character varying,
|
||||
upstream_pipeline_id_convert_to_bigint integer,
|
||||
resource_group_id bigint,
|
||||
waiting_for_resource_at timestamp with time zone,
|
||||
processed boolean,
|
||||
|
|
@ -31776,8 +31744,6 @@ CREATE TRIGGER trigger_0da002390fdc BEFORE INSERT OR UPDATE ON operations_featur
|
|||
|
||||
CREATE TRIGGER trigger_0e13f214e504 BEFORE INSERT OR UPDATE ON merge_request_assignment_events FOR EACH ROW EXECUTE FUNCTION trigger_0e13f214e504();
|
||||
|
||||
CREATE TRIGGER trigger_10ee1357e825 BEFORE INSERT OR UPDATE ON p_ci_builds FOR EACH ROW EXECUTE FUNCTION trigger_10ee1357e825();
|
||||
|
||||
CREATE TRIGGER trigger_13d4aa8fe3dd BEFORE INSERT OR UPDATE ON draft_notes FOR EACH ROW EXECUTE FUNCTION trigger_13d4aa8fe3dd();
|
||||
|
||||
CREATE TRIGGER trigger_174b23fa3dfb BEFORE INSERT OR UPDATE ON approval_project_rules_users FOR EACH ROW EXECUTE FUNCTION trigger_174b23fa3dfb();
|
||||
|
|
|
|||
|
|
@ -53,7 +53,6 @@ exceptions:
|
|||
- CVS
|
||||
- CVSS
|
||||
- CWE
|
||||
- DAG
|
||||
- DAST
|
||||
- DDL
|
||||
- DHCP
|
||||
|
|
|
|||
|
|
@ -939,6 +939,7 @@ SSDs
|
|||
SSGs
|
||||
Stackdriver
|
||||
Stackprof
|
||||
stageless
|
||||
starrer
|
||||
starrers
|
||||
storable
|
||||
|
|
|
|||
|
|
@ -76,7 +76,7 @@ can choose a custom limit. For example, to set the limit to `100`:
|
|||
Plan.default.actual_limits.update!(ci_needs_size_limit: 100)
|
||||
```
|
||||
|
||||
To disable directed acyclic graphs (DAG), set the limit to `0`. Pipelines with jobs
|
||||
To disable `needs` dependencies, set the limit to `0`. Pipelines with jobs
|
||||
configured to use `needs` then return the error `job can only need 0 others`.
|
||||
|
||||
## Change maximum scheduled pipeline frequency
|
||||
|
|
|
|||
|
|
@ -260,7 +260,7 @@ from the Admin area:
|
|||
- **Total number of jobs in currently active pipelines**
|
||||
- **Maximum number of pipeline subscriptions to and from a project**
|
||||
- **Maximum number of pipeline schedules**
|
||||
- **Maximum number of DAG dependencies that a job can have**
|
||||
- **Maximum number of needs dependencies that a job can have**
|
||||
- **Maximum number of runners registered per group**
|
||||
- **Maximum number of runners registered per project**
|
||||
- **Maximum number of downstream pipelines in a pipeline's hierarchy tree**
|
||||
|
|
|
|||
|
|
@ -39048,6 +39048,7 @@ Attributes for defining a CI/CD variable.
|
|||
| Name | Type | Description |
|
||||
| ---- | ---- | ----------- |
|
||||
| <a id="complianceframeworkfiltersid"></a>`id` | [`ComplianceManagementFrameworkID`](#compliancemanagementframeworkid) | ID of the compliance framework. |
|
||||
| <a id="complianceframeworkfiltersids"></a>`ids` | [`[ComplianceManagementFrameworkID!]`](#compliancemanagementframeworkid) | IDs of the compliance framework. |
|
||||
| <a id="complianceframeworkfiltersnot"></a>`not` | [`NegatedComplianceFrameworkFilters`](#negatedcomplianceframeworkfilters) | Negated compliance framework filter input. |
|
||||
| <a id="complianceframeworkfilterspresencefilter"></a>`presenceFilter` | [`ComplianceFrameworkPresenceFilter`](#complianceframeworkpresencefilter) | Checks presence of compliance framework of the project, "none" and "any" values are supported. |
|
||||
|
||||
|
|
@ -39292,6 +39293,7 @@ A year and month input for querying product analytics usage data.
|
|||
| Name | Type | Description |
|
||||
| ---- | ---- | ----------- |
|
||||
| <a id="negatedcomplianceframeworkfiltersid"></a>`id` | [`ComplianceManagementFrameworkID`](#compliancemanagementframeworkid) | ID of the compliance framework. |
|
||||
| <a id="negatedcomplianceframeworkfiltersids"></a>`ids` | [`[ComplianceManagementFrameworkID!]`](#compliancemanagementframeworkid) | IDs of the compliance framework. |
|
||||
|
||||
### `NegatedEpicBoardIssueInput`
|
||||
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@ curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/a
|
|||
"active" : true,
|
||||
"created_at" : "2021-01-20T22:11:48.151Z",
|
||||
"revoked" : false,
|
||||
"last_used_at": null,
|
||||
"access_level": 40
|
||||
},
|
||||
{
|
||||
|
|
@ -60,6 +61,7 @@ curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/a
|
|||
"active" : false,
|
||||
"created_at" : "2021-01-21T12:12:38.123Z",
|
||||
"revoked" : true,
|
||||
"last_used_at": "2021-02-13T10:34:57.178Z",
|
||||
"access_level": 40
|
||||
}
|
||||
]
|
||||
|
|
|
|||
|
|
@ -2791,7 +2791,7 @@ paths:
|
|||
format: int32
|
||||
ci_needs_size_limit:
|
||||
type: integer
|
||||
description: Maximum number of DAG dependencies that a job can have
|
||||
description: Maximum number of needs dependencies that a job can have
|
||||
format: int32
|
||||
ci_registered_group_runners:
|
||||
type: integer
|
||||
|
|
|
|||
|
|
@ -59744,7 +59744,7 @@ definitions:
|
|||
ci_needs_size_limit:
|
||||
type: integer
|
||||
format: int32
|
||||
description: Maximum number of DAG dependencies that a job can have
|
||||
description: Maximum number of needs dependencies that a job can have
|
||||
ci_registered_group_runners:
|
||||
type: integer
|
||||
format: int32
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@ PUT /application/plan_limits
|
|||
| `ci_active_jobs` | integer | no | Total number of jobs in currently active pipelines. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/85895) in GitLab 15.0. |
|
||||
| `ci_project_subscriptions` | integer | no | Maximum number of pipeline subscriptions to and from a project. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/85895) in GitLab 15.0. |
|
||||
| `ci_pipeline_schedules` | integer | no | Maximum number of pipeline schedules. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/85895) in GitLab 15.0. |
|
||||
| `ci_needs_size_limit` | integer | no | Maximum number of [DAG](../ci/directed_acyclic_graph/index.md) dependencies that a job can have. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/85895) in GitLab 15.0. |
|
||||
| `ci_needs_size_limit` | integer | no | Maximum number of [`needs`](../ci/directed_acyclic_graph/index.md) dependencies that a job can have. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/85895) in GitLab 15.0. |
|
||||
| `ci_registered_group_runners` | integer | no | Maximum number of runners registered per group. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/85895) in GitLab 15.0. |
|
||||
| `ci_registered_project_runners` | integer | no | Maximum number of runners registered per project. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/85895) in GitLab 15.0. |
|
||||
| `dotenv_size` | integer | no | Maximum size of a dotenv artifact in bytes. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/432529) in GitLab 17.1. |
|
||||
|
|
|
|||
|
|
@ -46,8 +46,9 @@ curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/a
|
|||
"id" : 42,
|
||||
"active" : true,
|
||||
"created_at" : "2021-01-20T22:11:48.151Z",
|
||||
"last_used_at" : null,
|
||||
"revoked" : false,
|
||||
"access_level": 40
|
||||
"access_level" : 40
|
||||
},
|
||||
{
|
||||
"user_id" : 141,
|
||||
|
|
@ -60,7 +61,8 @@ curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/a
|
|||
"active" : false,
|
||||
"created_at" : "2021-01-21T12:12:38.123Z",
|
||||
"revoked" : true,
|
||||
"access_level": 40
|
||||
"last_used_at" : "2021-02-13T10:34:57.178Z",
|
||||
"access_level" : 40
|
||||
}
|
||||
]
|
||||
```
|
||||
|
|
|
|||
|
|
@ -4,26 +4,26 @@ group: Pipeline Authoring
|
|||
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://handbook.gitlab.com/handbook/product/ux/technical-writing/#assignments
|
||||
---
|
||||
|
||||
# Directed Acyclic Graph
|
||||
# Make jobs start earlier with `needs`
|
||||
|
||||
DETAILS:
|
||||
**Tier:** Free, Premium, Ultimate
|
||||
**Offering:** GitLab.com, Self-managed, GitLab Dedicated
|
||||
|
||||
A [directed acyclic graph](https://en.wikipedia.org/wiki/Directed_acyclic_graph) can be
|
||||
used in the context of a CI/CD pipeline to build relationships between jobs such that
|
||||
execution is performed in the quickest possible manner, regardless how stages may
|
||||
be set up.
|
||||
You can use the [`needs`](../yaml/index.md#needs) keyword to create dependencies between jobs
|
||||
in a pipeline. Jobs run as soon as their dependencies are met, regardless of the pipeline's `stages`
|
||||
configuration. You can even configure a pipeline with no stages defined (effectively one large stage)
|
||||
and jobs still run in the proper order. This pipeline structure is a kind of
|
||||
[directed acyclic graph](https://en.wikipedia.org/wiki/Directed_acyclic_graph).
|
||||
|
||||
For example, you may have a specific tool or separate website that is built
|
||||
as part of your main project. Using a DAG, you can specify the relationship between
|
||||
as part of your main project. Using `needs`, you can specify dependencies between
|
||||
these jobs and GitLab executes the jobs as soon as possible instead of waiting
|
||||
for each stage to complete.
|
||||
|
||||
Unlike other DAG solutions for CI/CD, GitLab does not require you to choose one or the
|
||||
other. You can implement a hybrid combination of DAG and traditional
|
||||
stage-based operation within a single pipeline. Configuration is kept very simple,
|
||||
requiring a single keyword to enable the feature for any job.
|
||||
Unlike other solutions for CI/CD, GitLab does not require you to choose between staged
|
||||
or stageless execution flow. You can implement a hybrid combination of staged and stageless
|
||||
in a single pipeline, using only the `needs` keyword to enable the feature for any job.
|
||||
|
||||
Consider a monorepo as follows:
|
||||
|
||||
|
|
@ -34,7 +34,7 @@ Consider a monorepo as follows:
|
|||
./service_d
|
||||
```
|
||||
|
||||
It has a pipeline that looks like the following:
|
||||
This project could have a pipeline organized into three stages:
|
||||
|
||||
| build | test | deploy |
|
||||
|-----------|----------|--------|
|
||||
|
|
@ -43,45 +43,44 @@ It has a pipeline that looks like the following:
|
|||
| `build_c` | `test_c` | `deploy_c` |
|
||||
| `build_d` | `test_d` | `deploy_d` |
|
||||
|
||||
Using a DAG, you can relate the `_a` jobs to each other separately from the `_b` jobs,
|
||||
and even if service `a` takes a very long time to build, service `b` doesn't
|
||||
wait for it and finishes as quickly as it can. In this very same pipeline, `_c` and
|
||||
`_d` can be left alone and run together in staged sequence just like any standard
|
||||
GitLab pipeline.
|
||||
You can improve job execution by using `needs` to relate the `a` jobs to each other
|
||||
separately from the `b`, `c`, and `d` jobs. `build_a` could take a very long time to build,
|
||||
but `test_b` doesn't need to wait, it can be configured to start as soon as `build_b` is finished,
|
||||
which could be much faster.
|
||||
|
||||
If desired, `c` and `d` jobs can be left to run in stage sequence.
|
||||
|
||||
The `needs` keyword also works with the [parallel](../yaml/index.md#parallel) keyword,
|
||||
giving you powerful options for parallelization in your pipeline.
|
||||
|
||||
## Use cases
|
||||
|
||||
A DAG can help solve several different kinds of relationships between jobs within
|
||||
a CI/CD pipeline. Most typically this would cover when jobs need to fan in or out,
|
||||
and/or merge back together (diamond dependencies). This can happen when you're
|
||||
handling multi-platform builds or complex webs of dependencies as in something like
|
||||
an operating system build or a complex deployment graph of independently deployable
|
||||
but related microservices.
|
||||
You can use the [`needs`](../yaml/index.md#needs) keyword to define several different kinds of
|
||||
dependencies between jobs in a CI/CD pipeline. You can set dependencies to fan in or out,
|
||||
and even merge back together (diamond dependencies). These dependencies could be used for
|
||||
pipelines that:
|
||||
|
||||
Additionally, a DAG can help with general speediness of pipelines and helping
|
||||
to deliver fast feedback. By creating dependency relationships that don't unnecessarily
|
||||
- Handle multi-platform builds.
|
||||
- Have a complex web of dependencies like an operating system build.
|
||||
- Have a deployment graph of independently deployable but related microservices.
|
||||
|
||||
Additionally, `needs` can help improve the overall speed of pipelines and provide fast feedback.
|
||||
By creating dependencies that don't unnecessarily
|
||||
block each other, your pipelines run as quickly as possible regardless of
|
||||
pipeline stages, ensuring output (including errors) is available to developers
|
||||
as quickly as possible.
|
||||
|
||||
## Usage
|
||||
<!--- start_remove The following content will be removed on remove_date: '2024-12-19' -->
|
||||
## Needs dependency visualization (deprecated)
|
||||
|
||||
Relationships are defined between jobs using the [`needs` keyword](../yaml/index.md#needs).
|
||||
WARNING:
|
||||
This feature was [deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/336560) in GitLab 17.1
|
||||
and is planned for removal in 17.4. View `needs` relationships in the
|
||||
[full pipeline graph](../pipelines/index.md#group-jobs-by-stage-or-needs-configuration) instead.
|
||||
|
||||
The `needs` keyword also works with the [parallel](../yaml/index.md#parallel) keyword,
|
||||
giving you powerful options for parallelization within your pipeline.
|
||||
|
||||
## Limitations
|
||||
|
||||
A directed acyclic graph is a complicated feature, and as of the initial MVC there
|
||||
are certain use cases that you may need to work around. For more information, check the:
|
||||
|
||||
- [`needs` additional details](../yaml/index.md#needs).
|
||||
- Related epic [tracking planned improvements](https://gitlab.com/groups/gitlab-org/-/epics/1716).
|
||||
|
||||
## Needs Visualization
|
||||
|
||||
The needs visualization makes it easier to visualize the relationships between dependent jobs in a DAG. This graph displays all the jobs in a pipeline that need or are needed by other jobs. Jobs with no relationships are not displayed in this view.
|
||||
The needs dependency visualization makes it easier to visualize the dependencies
|
||||
between jobs in a pipeline. This graph displays all the jobs in a pipeline
|
||||
that need or are needed by other jobs. Jobs with no dependencies are not displayed in this view.
|
||||
|
||||
To see the needs visualization, select **Needs** when viewing a pipeline that uses the `needs` keyword.
|
||||
|
||||
|
|
@ -90,5 +89,4 @@ To see the needs visualization, select **Needs** when viewing a pipeline that us
|
|||
Selecting a node highlights all the job paths it depends on.
|
||||
|
||||

|
||||
|
||||
You can also see `needs` relationships in [full pipeline graphs](../pipelines/index.md#group-jobs-by-stage-or-needs-configuration).
|
||||
<!--- end_remove -->
|
||||
|
|
|
|||
Binary file not shown.
|
Before Width: | Height: | Size: 35 KiB |
|
|
@ -45,7 +45,7 @@ Pipelines can be configured in many different ways:
|
|||
|
||||
- [Basic pipelines](pipeline_architectures.md#basic-pipelines) run everything in each stage concurrently,
|
||||
followed by the next stage.
|
||||
- [Directed Acyclic Graph Pipeline (DAG) pipelines](../directed_acyclic_graph/index.md) are based on relationships
|
||||
- [Pipelines that use the `needs` keyword](../directed_acyclic_graph/index.md) run based on dependencies
|
||||
between jobs and can run more quickly than basic pipelines.
|
||||
- [Merge request pipelines](../pipelines/merge_request_pipelines.md) run for merge
|
||||
requests only (rather than for every commit).
|
||||
|
|
@ -399,9 +399,7 @@ by stage configuration, select **stage** in the **Group jobs by** section:
|
|||

|
||||
|
||||
To group the jobs by [`needs`](../yaml/index.md#needs) configuration, select **Job dependencies**.
|
||||
You can optionally select **Show dependencies** to render lines between dependent jobs,
|
||||
similar to the [`needs` visualization](../directed_acyclic_graph/index.md#needs-visualization)
|
||||
in the pipeline editor:
|
||||
You can optionally select **Show dependencies** to render lines between dependent jobs.
|
||||
|
||||

|
||||
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ You can structure your pipelines with different methods, each with their
|
|||
own advantages. These methods can be mixed and matched if needed:
|
||||
|
||||
- [Basic](#basic-pipelines): Good for straightforward projects where all the configuration is in one place.
|
||||
- [Directed Acyclic Graph](#directed-acyclic-graph-pipelines): Good for large, complex projects that need efficient execution.
|
||||
- [Pipelines with the `needs` keyword](#pipelines-with-the-needs-keyword): Good for large, complex projects that need efficient execution.
|
||||
- [Parent-child pipelines](#parent-child-pipelines): Good for monorepos and projects with lots of independently defined components.
|
||||
|
||||
<i class="fa fa-youtube-play youtube" aria-hidden="true"></i>
|
||||
|
|
@ -116,13 +116,12 @@ deploy_b:
|
|||
environment: production
|
||||
```
|
||||
|
||||
## Directed Acyclic Graph Pipelines
|
||||
## Pipelines with the `needs` keyword
|
||||
|
||||
If efficiency is important to you and you want everything to run as quickly as possible,
|
||||
you can use [Directed Acyclic Graphs (DAG)](../directed_acyclic_graph/index.md). Use the
|
||||
[`needs` keyword](../yaml/index.md#needs) to define dependency relationships between
|
||||
your jobs. When GitLab knows the relationships between your jobs, it can run everything
|
||||
as fast as possible, and even skips into subsequent stages when possible.
|
||||
If efficiency is important and you want everything to run as quickly as possible,
|
||||
you can use the [`needs` keyword](../directed_acyclic_graph/index.md) to define dependencies
|
||||
between your jobs. When GitLab knows the dependencies between your jobs,
|
||||
jobs can run as fast as possible, even starting earlier than other jobs in the same stage.
|
||||
|
||||
In the example below, if `build_a` and `test_a` are much faster than `build_b` and
|
||||
`test_b`, GitLab starts `deploy_a` even if `build_b` is still running.
|
||||
|
|
@ -130,16 +129,16 @@ In the example below, if `build_a` and `test_a` are much faster than `build_b` a
|
|||
```mermaid
|
||||
%%{init: { "fontFamily": "GitLab Sans" }}%%
|
||||
graph LR
|
||||
accTitle: Pipeline using DAG
|
||||
accTitle: Pipeline using needs
|
||||
accDescr: Shows how two jobs can start without waiting for earlier stages to complete
|
||||
|
||||
subgraph Pipeline using DAG
|
||||
subgraph Pipeline using needs
|
||||
build_a --> test_a --> deploy_a
|
||||
build_b --> test_b --> deploy_b
|
||||
end
|
||||
```
|
||||
|
||||
Example DAG `/.gitlab-ci.yml` configuration matching the diagram:
|
||||
Example `/.gitlab-ci.yml` configuration matching the diagram:
|
||||
|
||||
```yaml
|
||||
stages:
|
||||
|
|
@ -208,7 +207,7 @@ YAML is dynamically generated.
|
|||
|
||||

|
||||
|
||||
In the [basic pipeline](#basic-pipelines) and [directed acyclic graph](#directed-acyclic-graph-pipelines)
|
||||
In the [basic pipeline](#basic-pipelines) and [`needs` pipeline](#pipelines-with-the-needs-keyword)
|
||||
examples above, there are two packages that could be built independently.
|
||||
These cases are ideal for using [parent-child pipelines](downstream_pipelines.md#parent-child-pipelines).
|
||||
It separates out the configuration into multiple files, keeping things simpler.
|
||||
|
|
@ -218,7 +217,7 @@ You can combine parent-child pipelines with:
|
|||
when there are changes to that area.
|
||||
- The [`include` keyword](../yaml/index.md#include): Bring in common behaviors, ensuring
|
||||
you are not repeating yourself.
|
||||
- [DAG pipelines](#directed-acyclic-graph-pipelines) inside of child pipelines, achieving the benefits of both.
|
||||
- The [`needs` keyword](#pipelines-with-the-needs-keyword) inside of child pipelines, achieving the benefits of both.
|
||||
|
||||
```mermaid
|
||||
%%{init: { "fontFamily": "GitLab Sans" }}%%
|
||||
|
|
@ -263,7 +262,7 @@ trigger_b:
|
|||
```
|
||||
|
||||
Example child `a` pipeline configuration, located in `/a/.gitlab-ci.yml`, making
|
||||
use of the DAG `needs` keyword:
|
||||
use of the `needs` keyword:
|
||||
|
||||
```yaml
|
||||
stages:
|
||||
|
|
@ -294,7 +293,7 @@ deploy_a:
|
|||
```
|
||||
|
||||
Example child `b` pipeline configuration, located in `/b/.gitlab-ci.yml`, making
|
||||
use of the DAG `needs` keyword:
|
||||
use of the `needs` keyword:
|
||||
|
||||
```yaml
|
||||
stages:
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ heavily influenced by the:
|
|||
- [Size of the repository](../../user/project/repository/monorepos/index.md)
|
||||
- Total number of stages and jobs.
|
||||
- Dependencies between jobs.
|
||||
- The ["critical path"](#directed-acyclic-graphs-dag-visualization), which represents
|
||||
- The ["critical path"](#needs-dependency-visualization), which represents
|
||||
the minimum and maximum pipeline duration.
|
||||
|
||||
Additional points to pay attention relate to [GitLab Runners](../runners/index.md):
|
||||
|
|
@ -89,12 +89,10 @@ running simultaneously to support the parallel jobs.
|
|||
The [testing levels for GitLab](../../development/testing_guide/testing_levels.md)
|
||||
provide an example of a complex testing strategy with many components involved.
|
||||
|
||||
### Directed Acyclic Graphs (DAG) visualization
|
||||
### `needs` dependency visualization
|
||||
|
||||
The [Directed Acyclic Graph](../directed_acyclic_graph/index.md) (DAG) visualization can help analyze the critical path in
|
||||
the pipeline and understand possible blockers.
|
||||
|
||||

|
||||
Viewing the `needs` dependencies in the [full pipeline graph](../pipelines/index.md#group-jobs-by-stage-or-needs-configuration)
|
||||
can help analyze the critical path in the pipeline and understand possible blockers.
|
||||
|
||||
### Pipeline Monitoring
|
||||
|
||||
|
|
@ -185,11 +183,11 @@ Decide if it's important for long jobs to run early, before fast feedback from
|
|||
faster jobs. The initial failures may make it clear that the rest of the pipeline
|
||||
shouldn't run, saving pipeline resources.
|
||||
|
||||
### Directed Acyclic Graphs (DAG)
|
||||
### `needs` keyword
|
||||
|
||||
In a basic configuration, jobs always wait for all other jobs in earlier stages to complete
|
||||
before running. This is the simplest configuration, but it's also the slowest in most
|
||||
cases. [Directed Acyclic Graphs](../directed_acyclic_graph/index.md) and
|
||||
cases. [Pipelines with the `needs` keyword](../directed_acyclic_graph/index.md) and
|
||||
[parent/child pipelines](downstream_pipelines.md#parent-child-pipelines) are more flexible and can
|
||||
be more efficient, but can also make pipelines harder to understand and analyze.
|
||||
|
||||
|
|
|
|||
|
|
@ -147,8 +147,8 @@ For the complete `.gitlab-ci.yml` syntax, see the full [CI/CD YAML syntax refere
|
|||
- Each job contains a script section and belongs to a stage:
|
||||
- [`stage`](../yaml/index.md#stage) describes the sequential execution of jobs.
|
||||
If there are runners available, jobs in a single stage run in parallel.
|
||||
- Use the [`needs` keyword](../yaml/index.md#needs) to run jobs out of stage order.
|
||||
This creates a [Directed Acyclic Graph (DAG)](../directed_acyclic_graph/index.md).
|
||||
- Use the [`needs` keyword](../yaml/index.md#needs) to [run jobs out of stage order](../directed_acyclic_graph/index.md),
|
||||
to increase pipeline speed and efficiency.
|
||||
- You can set additional configuration to customize how your jobs and stages perform:
|
||||
- Use the [`rules`](../yaml/index.md#rules) keyword to specify when to run or skip jobs.
|
||||
The `only` and `except` legacy keywords are still supported, but can't be used
|
||||
|
|
|
|||
|
|
@ -38,29 +38,33 @@ called `Gitlab::BitbucketImport::AdvanceStageWorker`.
|
|||
This worker imports the repository, wiki and labels, scheduling the next stage when
|
||||
done.
|
||||
|
||||
### 2. Stage::ImportPullRequestsWorker
|
||||
### 2. Stage::ImportUsersWorker
|
||||
|
||||
This worker imports members of the source Bitbucket Cloud workspace.
|
||||
|
||||
### 3. Stage::ImportPullRequestsWorker
|
||||
|
||||
This worker imports all pull requests. For every pull request, a job for the
|
||||
`Gitlab::BitbucketImport::ImportPullRequestWorker` worker is scheduled.
|
||||
|
||||
### 3. Stage::ImportPullRequestsNotesWorker
|
||||
### 4. Stage::ImportPullRequestsNotesWorker
|
||||
|
||||
This worker imports notes (comments) for all merge requests.
|
||||
|
||||
For every merge request, a job for the `Gitlab::BitbucketImport::ImportPullRequestNotesWorker` worker is scheduled which imports all notes for the merge request.
|
||||
|
||||
### 4. Stage::ImportIssuesWorker
|
||||
### 5. Stage::ImportIssuesWorker
|
||||
|
||||
This worker imports all issues. For every issue, a job for the
|
||||
`Gitlab::BitbucketImport::ImportIssueWorker` worker is scheduled.
|
||||
|
||||
### 5. Stage::ImportIssuesNotesWorker
|
||||
### 6. Stage::ImportIssuesNotesWorker
|
||||
|
||||
This worker imports notes (comments) for all issues.
|
||||
|
||||
For every issue, a job for the `Gitlab::BitbucketImport::ImportIssueNotesWorker` worker is scheduled which imports all notes for the issue.
|
||||
|
||||
### 5. Stage::FinishImportWorker
|
||||
### 7. Stage::FinishImportWorker
|
||||
|
||||
This worker completes the import process by performing some housekeeping
|
||||
such as marking the import as completed.
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ processing it, and returns any syntax or semantic errors. The `YAML Processor` c
|
|||
|
||||
The `CreatePipelineService` receives the abstract data structure returned by the `YAML Processor`,
|
||||
which then converts it to persisted models (like pipeline, stages, and jobs). After that, the pipeline is ready
|
||||
to be processed. Processing a pipeline means running the jobs in order of execution (stage or DAG)
|
||||
to be processed. Processing a pipeline means running the jobs in order of execution (stage or `needs`)
|
||||
until either one of the following:
|
||||
|
||||
- All expected jobs have been executed.
|
||||
|
|
@ -109,7 +109,7 @@ A job with the `created` state isn't seen by the runner yet. To make it possible
|
|||
1. The job is created in the very first stage of the pipeline.
|
||||
1. The job required a manual start and it has been triggered.
|
||||
1. All jobs from the previous stage have completed successfully. In this case we transition all jobs from the next stage to `pending`.
|
||||
1. The job specifies DAG dependencies using `needs:` and all the dependent jobs are completed.
|
||||
1. The job specifies needs dependencies using `needs:` and all the dependent jobs are completed.
|
||||
1. The job has not been [dropped](#dropping-stuck-builds) because of its not-runnable state by [`Ci::PipelineCreation::DropNotRunnableBuildsService`](https://gitlab.com/gitlab-org/gitlab/-/blob/v16.0.4-ee/ee/app/services/ci/pipeline_creation/drop_not_runnable_builds_service.rb).
|
||||
|
||||
When the runner is connected, it requests the next `pending` job to run by polling the server continuously.
|
||||
|
|
|
|||
|
|
@ -1290,24 +1290,25 @@ Verify your feature appears in `gon.licensed_features` in the browser console.
|
|||
EE licensed features that enhance existing functionality in the UI add new
|
||||
elements or interactions to your Vue application as components.
|
||||
|
||||
To separate template differences, use a child EE component to separate Vue template differences.
|
||||
You must import the EE component [asynchronously](https://v2.vuejs.org/v2/guide/components-dynamic-async.html#Async-Components).
|
||||
You can import EE components inside CE components to add EE features.
|
||||
|
||||
This allows GitLab to load the correct component in EE, while in CE GitLab loads an empty component
|
||||
that renders nothing. This code **must** exist in the CE repository, in addition to the EE repository.
|
||||
Use an `ee_component` alias to import an EE component. In EE the `ee_component` import alias points
|
||||
to the `ee/app/assets/javascripts` directory. While in CE this alias will be resolved to an empty
|
||||
component that renders nothing.
|
||||
|
||||
A CE component acts as the entry point to your EE feature. To add a EE component,
|
||||
locate it the `ee/` directory and add it with `import('ee_component/...')`:
|
||||
Here is an example of an EE component imported to a CE component:
|
||||
|
||||
```html
|
||||
```vue
|
||||
<script>
|
||||
// app/assets/javascripts/feature/components/form.vue
|
||||
|
||||
// In EE this will be resolved as `ee/app/assets/javascripts/feature/components/my_ee_component.vue`
|
||||
// In CE as `app/assets/javascripts/vue_shared/components/empty_component.js`
|
||||
import MyEeComponent from 'ee_component/feature/components/my_ee_component.vue';
|
||||
|
||||
export default {
|
||||
mixins: [glFeatureFlagMixin()],
|
||||
components: {
|
||||
// Import an EE component from CE
|
||||
MyEeComponent: () => import('ee_component/components/my_ee_component.vue'),
|
||||
MyEeComponent,
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
|
@ -1321,10 +1322,15 @@ export default {
|
|||
</template>
|
||||
```
|
||||
|
||||
NOTE:
|
||||
An EE component can be imported
|
||||
[asynchronously](https://v2.vuejs.org/v2/guide/components-dynamic-async.html#Async-Components) if
|
||||
its rendering within CE codebase relies on some check (e.g. a feature flag check).
|
||||
|
||||
Check `glFeatures` to ensure that the Vue components are guarded. The components render only when
|
||||
the license is present.
|
||||
|
||||
```html
|
||||
```vue
|
||||
<script>
|
||||
// ee/app/assets/javascripts/feature/components/special_component.vue
|
||||
|
||||
|
|
@ -1421,11 +1427,8 @@ export default {
|
|||
|
||||
**For EE components that need different results for the same computed values, we can pass in props to the CE wrapper as seen in the example.**
|
||||
|
||||
- **EE Child components**
|
||||
- Since we are using the asynchronous loading to check which component to load, we'd still use the component's name, check [this example](#extend-vue-applications-with-ee-vue-components).
|
||||
|
||||
- **EE extra HTML**
|
||||
- For the templates that have extra HTML in EE we should move it into a new component and use the `ee_else_ce` dynamic import
|
||||
- For the templates that have extra HTML in EE we should move it into a new component and use the `ee_else_ce` import alias
|
||||
|
||||
#### Extend other JS code
|
||||
|
||||
|
|
|
|||
|
|
@ -1934,3 +1934,106 @@ Example:
|
|||
```json
|
||||
{ "op": "Add", "path": "name.formatted", "value": "New Name" }
|
||||
```
|
||||
|
||||
## Namespaces
|
||||
|
||||
### Get a namespace by ID
|
||||
|
||||
```plaintext
|
||||
GET /internal/gitlab_subscriptions/namespaces/:id
|
||||
```
|
||||
|
||||
Parameters:
|
||||
|
||||
| Attribute | Type | Required | Description |
|
||||
| --------- | -------------- | -------- | ----------- |
|
||||
| `id` | integer/string | yes | ID or [URL-encoded path of the namespace](../../api/rest/index.md#namespaced-path-encoding) |
|
||||
|
||||
Example request:
|
||||
|
||||
```shell
|
||||
curl --request GET --header "PRIVATE-TOKEN: <admin_access_token>" "https://gitlab.com/api/v4/internal/gitlab_subscriptions/namespaces/1"
|
||||
```
|
||||
|
||||
Example response:
|
||||
|
||||
```json
|
||||
{
|
||||
"id": 1,
|
||||
"name": "group1",
|
||||
"path": "group1",
|
||||
"kind": "group",
|
||||
"full_path": "group1",
|
||||
"parent_id": null,
|
||||
"avatar_url": null,
|
||||
"web_url": "https://gitlab.example.com/groups/group1",
|
||||
"members_count_with_descendants": 2,
|
||||
"billable_members_count": 2,
|
||||
"max_seats_used": 0,
|
||||
"seats_in_use": 0,
|
||||
"plan": "default",
|
||||
"end_date": null,
|
||||
"trial_ends_on": null,
|
||||
"trial": false,
|
||||
"root_repository_size": 100,
|
||||
"projects_count": 3
|
||||
}
|
||||
```
|
||||
|
||||
#### Known consumers
|
||||
|
||||
- CustomersDot
|
||||
|
||||
### Update a namespace
|
||||
|
||||
Use a PUT command to update an existing namespace.
|
||||
|
||||
```plaintext
|
||||
PUT /internal/gitlab_subscriptions/namespaces/:id
|
||||
```
|
||||
|
||||
Parameters:
|
||||
|
||||
| Attribute | Type | Required | Description |
|
||||
| --------- | -------------- | -------- | ----------- |
|
||||
| `id` | integer/string | yes | ID or [URL-encoded path of the namespace](../../api/rest/index.md#namespaced-path-encoding) |
|
||||
| `shared_runners_minutes_limit` | integer | no | Compute minutes quota |
|
||||
| `extra_shared_runners_minutes_limit` | integer | no | Extra compute minutes |
|
||||
| `additional_purchased_storage_size` | integer | no | Additional storage size |
|
||||
| `additional_purchased_storage_ends_on` | date | no | Additional purchased storage Ends on |
|
||||
| `gitlab_subscription_attributes` | hash | no | Hash object containing GitLab Subscription attributes. Accepts `seats`,`max_seats_used`,`plan_code`,`end_date`,`auto_renew`,`trial`,`trial_ends_on`,`trial_starts_on`,`trial_extension_type` |
|
||||
|
||||
Example request:
|
||||
|
||||
```shell
|
||||
curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.com/api/v4/internal/gitlab_subscriptions/namespaces/1 --data '{"shared_runners_minutes_limit":1000}'"
|
||||
```
|
||||
|
||||
Example response:
|
||||
|
||||
```json
|
||||
{
|
||||
"id": 1,
|
||||
"name": "group1",
|
||||
"path": "group1",
|
||||
"kind": "group",
|
||||
"full_path": "group1",
|
||||
"parent_id": null,
|
||||
"avatar_url": null,
|
||||
"web_url": "https://gitlab.example.com/groups/group1",
|
||||
"members_count_with_descendants": 2,
|
||||
"billable_members_count": 2,
|
||||
"max_seats_used": 0,
|
||||
"seats_in_use": 0,
|
||||
"plan": "default",
|
||||
"end_date": null,
|
||||
"trial_ends_on": null,
|
||||
"trial": false,
|
||||
"root_repository_size": 100,
|
||||
"projects_count": 3
|
||||
}
|
||||
```
|
||||
|
||||
#### Known consumers
|
||||
|
||||
- CustomersDot
|
||||
|
|
|
|||
|
|
@ -438,7 +438,7 @@ For this scenario, you have to:
|
|||
|
||||
Additionally, `scripts/utils.sh` is always downloaded from the API when this pattern is used (this file contains the code for `.fast-no-clone-job`).
|
||||
|
||||
#### Runner tags
|
||||
### Runner tags
|
||||
|
||||
On GitLab.com, both unprivileged and privileged runners are
|
||||
available. For projects in the `gitlab-org` group and forks of those
|
||||
|
|
@ -459,3 +459,87 @@ no matching runners are available.
|
|||
|
||||
See [the GitLab Repositories handbook page](https://handbook.gitlab.com/handbook/engineering/gitlab-repositories/#cicd-configuration)
|
||||
for more information.
|
||||
|
||||
### Using the `gitlab` Ruby gem in the canonical project
|
||||
|
||||
When calling `require 'gitlab'` in the canonical project, it will require the `lib/gitlab.rb` file when `$LOAD_PATH` has `lib`, which happens when we're loading the application (`config/application.rb`) or tests (`spec/spec_helper.rb`).
|
||||
|
||||
This means we're not able to load the `gitlab` gem under the above conditions and even if we can, the constant name will conflict, breaking internal assumptions and causing random errors.
|
||||
If you are working on a script that is using [the `gitlab` Ruby gem](https://github.com/NARKOZ/gitlab), you will need to take a few precautions:
|
||||
|
||||
#### 1 - Conditional require of the gem
|
||||
|
||||
To avoid potential conflicts, only require the `gitlab` gem if the `Gitlab` constant isn't defined:
|
||||
|
||||
```ruby
|
||||
# Bad
|
||||
require 'gitlab'
|
||||
|
||||
# Good
|
||||
if Object.const_defined?(:RSpec)
|
||||
# Ok, we're testing, we know we're going to stub `Gitlab`, so we just ignore
|
||||
else
|
||||
require 'gitlab'
|
||||
|
||||
if Gitlab.singleton_class.method_defined?(:com?)
|
||||
abort 'lib/gitlab.rb is loaded, and this means we can no longer load the client and we cannot proceed'
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
#### 2 - Mock the `gitlab` gem entirely in your specs
|
||||
|
||||
In your specs, `require 'gitlab'` will reference the `lib/gitlab.rb` file:
|
||||
|
||||
```ruby
|
||||
# Bad
|
||||
allow(GitLab).to receive(:a_method).and_return(...)
|
||||
|
||||
# Good
|
||||
client = double('GitLab')
|
||||
# In order to easily stub the client, consider using a method to return the client.
|
||||
# We can then stub the method to return our fake client, which we can further stub its methods.
|
||||
#
|
||||
# This is the pattern followed below
|
||||
let(:instance) { described_class.new }
|
||||
|
||||
allow(instance).to receive(:gitlab).and_return(client)
|
||||
allow(client).to receive(:a_method).and_return(...)
|
||||
```
|
||||
|
||||
In case you need to query jobs for instance, the following snippet will be useful:
|
||||
|
||||
```ruby
|
||||
# Bad
|
||||
allow(GitLab).to receive(:pipeline_jobs).and_return(...)
|
||||
|
||||
# Good
|
||||
#
|
||||
# rubocop:disable RSpec/VerifiedDoubles -- We do not load the Gitlab client directly
|
||||
client = double('GitLab')
|
||||
allow(instance).to receive(:gitlab).and_return(client)
|
||||
|
||||
jobs = ['job1', 'job2']
|
||||
allow(client).to yield_jobs(:pipeline_jobs, jobs)
|
||||
|
||||
def yield_jobs(api_method, jobs)
|
||||
messages = receive_message_chain(api_method, :auto_paginate)
|
||||
|
||||
jobs.inject(messages) do |stub, job_name|
|
||||
stub.and_yield(double(name: job_name))
|
||||
end
|
||||
end
|
||||
# rubocop:enable RSpec/VerifiedDoubles
|
||||
```
|
||||
|
||||
#### 3 - Do not call your script with `bundle exec`
|
||||
|
||||
Executing with `bundle exec` will change the `$LOAD_PATH` for Ruby, and it will load `lib/gitlab.rb` when calling `require 'gitlab'`:
|
||||
|
||||
```shell
|
||||
# Bad
|
||||
bundle exec scripts/my-script.rb
|
||||
|
||||
# Good
|
||||
scripts/my-script.rb
|
||||
```
|
||||
|
|
|
|||
|
|
@ -498,7 +498,7 @@ including:
|
|||
|
||||
- [Configuration Files](../administration/backup_restore/backup_gitlab.md#storing-configuration-files)
|
||||
|
||||
- [Elasticsearch](https://www.elastic.co/guide/en/elasticsearch/reference/current/snapshot-restore.md)
|
||||
- [Elasticsearch](https://www.elastic.co/guide/en/elasticsearch/reference/current/snapshot-restore.html)
|
||||
|
||||
GitLab Geo
|
||||
|
||||
|
|
@ -721,7 +721,7 @@ for self-managed customers that covers topics such as:
|
|||
|
||||
- [Operating System Recommendations](hardening_operating_system_recommendations.md)
|
||||
|
||||
GitLab CIS Benchmark Guide - GitLab has published a [CIS Benchmark](https://about.gitlab.com/blog/2024/04/17/gitlab-introduces-new-cis-benchmark-for-improved-security/index.md)
|
||||
GitLab CIS Benchmark Guide - GitLab has published a [CIS Benchmark](https://about.gitlab.com/blog/2024/04/17/gitlab-introduces-new-cis-benchmark-for-improved-security/)
|
||||
to guide hardening decisions in the application. This may be used in
|
||||
concert with this guide to harden the environment in accordance with NIST 800-53
|
||||
controls. Not all suggestions in the CIS Benchmark directly align with
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ To view the roadmap in a group:
|
|||
1. On the left sidebar, select **Search or go to** and find your group.
|
||||
1. Select **Plan > Roadmap**.
|
||||
|
||||
The Roadmap page shows the epics and milestones in a
|
||||
The roadmap shows the epics and milestones in a
|
||||
group, one of its subgroups, or a project in one of the groups.
|
||||
|
||||
On the epic bars, you can see each epic's title, progress, and completed weight percentage.
|
||||
|
|
@ -50,7 +50,7 @@ heading to toggle the list of the milestone bars.
|
|||
|
||||

|
||||
|
||||
## Sort and filter the Roadmap
|
||||
## Sort and filter the roadmap
|
||||
|
||||
> - Filtering by group was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/385191) in GitLab 15.9.
|
||||
> - Sorting by title, created date, and last updated date [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/460492) in GitLab 17.0.
|
||||
|
|
@ -61,7 +61,7 @@ Filtering roadmaps by milestone might not be available to you. Be sure to review
|
|||
When you want to explore a roadmap, there are several ways to make it easier by sorting epics or
|
||||
filtering them by what's important for you.
|
||||
|
||||
You can sort epics in the Roadmap view by:
|
||||
In the Roadmap view, you can sort epics by:
|
||||
|
||||
- Start date
|
||||
- Due date
|
||||
|
|
@ -73,7 +73,7 @@ Each option contains a button that toggles the sort order between **ascending**
|
|||
and **descending**. The sort option and order persist when browsing Epics, including
|
||||
the [epics list view](../epics/index.md).
|
||||
|
||||
You can also filter epics in the Roadmap view by the epics':
|
||||
In the Roadmap view, you can also filter by the epics':
|
||||
|
||||
- Author
|
||||
- Label
|
||||
|
|
@ -121,7 +121,7 @@ Roadmap provides these date range options, each with a predetermined timeline du
|
|||
|
||||
### Layout presets
|
||||
|
||||
Depending on selected [date range preset](#date-range-presets), Roadmap supports
|
||||
Depending on selected [date range preset](#date-range-presets), the roadmap supports
|
||||
these layout presets:
|
||||
|
||||
- **Quarters**: Available only when the **Within 3 years** date range is selected.
|
||||
|
|
|
|||
|
|
@ -88,7 +88,7 @@ IID. The link to the artifacts can also be accessed from the **Experiment Candid
|
|||
|
||||
## View CI information
|
||||
|
||||
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/119788) in 16.1
|
||||
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/119788) in GitLab 16.1.
|
||||
|
||||
Candidates can be associated to the CI job that created them, allowing quick links to the merge request, pipeline, and user that triggered the pipeline:
|
||||
|
||||
|
|
|
|||
10
lefthook.yml
10
lefthook.yml
|
|
@ -129,6 +129,11 @@ pre-push:
|
|||
tags: secrets
|
||||
files: git diff --name-only --diff-filter=d $(git merge-base origin/master HEAD)..HEAD
|
||||
run: 'if command -v gitleaks > /dev/null 2>&1; then gitleaks detect --log-opts="$(git merge-base origin/master HEAD)..HEAD" --no-banner --redact --verbose; else echo "WARNING: gitleaks is not installed. Please install it. See https://github.com/zricethezav/gitleaks#installing."; fi'
|
||||
reminder-to-validate-ci-config:
|
||||
tags: ci config
|
||||
files: git diff --name-only --diff-filter=d $(git merge-base origin/master HEAD)..HEAD
|
||||
glob: '{.gitlab-ci.yml,.gitlab/**/*.yml}'
|
||||
run: "echo '🚨WARNING: You are modifying ci pipeline configurations. Please test your changes by running `bundle exec rspec spec/dot_gitlab_ci/job_dependency_spec.rb`. If you think we are missing test coverage for your changes, please add them.'"
|
||||
|
||||
scripts:
|
||||
'merge_conflicts':
|
||||
|
|
@ -156,6 +161,11 @@ pre-commit:
|
|||
tags: secrets
|
||||
files: git diff --name-only --diff-filter=d --staged
|
||||
run: 'if command -v gitleaks > /dev/null 2>&1; then gitleaks protect --no-banner --staged --redact --verbose; else echo "WARNING: gitleaks is not installed. Please install it. See https://github.com/zricethezav/gitleaks#installing."; fi'
|
||||
reminder-to-validate-ci-config:
|
||||
tags: ci config
|
||||
files: git diff --name-only --diff-filter=d --staged
|
||||
glob: '{.gitlab-ci.yml,.gitlab/**/*.yml}'
|
||||
run: "echo '🚨WARNING: You are modifying ci pipeline configurations. Please test your changes by running `bundle exec rspec spec/dot_gitlab_ci/job_dependency_spec.rb`. If you think we are missing test coverage for your changes, please add them.'"
|
||||
|
||||
auto-fix:
|
||||
parallel: true
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ module API
|
|||
optional :ci_project_subscriptions, type: Integer,
|
||||
desc: 'Maximum number of pipeline subscriptions to and from a project'
|
||||
optional :ci_pipeline_schedules, type: Integer, desc: 'Maximum number of pipeline schedules'
|
||||
optional :ci_needs_size_limit, type: Integer, desc: 'Maximum number of DAG dependencies that a job can have'
|
||||
optional :ci_needs_size_limit, type: Integer, desc: 'Maximum number of needs dependencies that a job can have'
|
||||
optional :ci_registered_group_runners, type: Integer, desc: 'Maximum number of runners registered per group'
|
||||
optional :ci_registered_project_runners, type: Integer, desc: 'Maximum number of runners registered per project'
|
||||
optional :conan_max_file_size, type: Integer, desc: 'Maximum Conan package file size in bytes'
|
||||
|
|
|
|||
|
|
@ -1233,8 +1233,15 @@ into similar problems in the future (e.g. when new tables are created).
|
|||
end
|
||||
end
|
||||
|
||||
def lock_tables(*tables, mode: :access_exclusive)
|
||||
execute("LOCK TABLE #{tables.join(', ')} IN #{mode.to_s.upcase.tr('_', ' ')} MODE")
|
||||
def lock_tables(*tables, mode: :access_exclusive, only: nil, nowait: nil)
|
||||
only_param = only && 'ONLY'
|
||||
nowait_param = nowait && 'NOWAIT'
|
||||
tables_param = tables.map { |t| quote_table_name(t) }.join(', ')
|
||||
mode_param = mode.to_s.upcase.tr('_', ' ')
|
||||
|
||||
execute(<<~SQL.squish)
|
||||
LOCK TABLE #{only_param} #{tables_param} IN #{mode_param} MODE #{nowait_param}
|
||||
SQL
|
||||
end
|
||||
|
||||
private
|
||||
|
|
|
|||
|
|
@ -138,7 +138,7 @@ module Gitlab
|
|||
klass: self.class,
|
||||
logger: Gitlab::AppLogger,
|
||||
connection: connection
|
||||
).run(&block)
|
||||
).run(raise_on_exhaustion: true, &block)
|
||||
end
|
||||
|
||||
def table_partitioned?
|
||||
|
|
@ -160,7 +160,7 @@ module Gitlab
|
|||
|
||||
primary_transaction(statement_timeout: STATEMENT_TIMEOUT) do
|
||||
# Running ANALYZE on partitioned table will go through itself and its partitions
|
||||
connection.execute("ANALYZE #{model.quoted_table_name}")
|
||||
connection.execute("ANALYZE (SKIP_LOCKED) #{model.quoted_table_name}")
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -51,11 +51,8 @@ module Gitlab
|
|||
end
|
||||
|
||||
def pluck_mentions_from_text(text)
|
||||
gitlab_like_mentions = text.scan(GITLAB_MENTIONS_REGEX)
|
||||
|
||||
return gitlab_like_mentions unless Feature.enabled?(:bitbucket_cloud_convert_mentions_to_users, project_creator)
|
||||
|
||||
(gitlab_like_mentions + text.scan(BITBUCKET_MENTIONS_REGEX)).flatten
|
||||
mentions = text.scan(GITLAB_MENTIONS_REGEX) + text.scan(BITBUCKET_MENTIONS_REGEX)
|
||||
mentions.flatten
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -4009,9 +4009,6 @@ msgstr ""
|
|||
msgid "AdminSettings|Maximum includes"
|
||||
msgstr ""
|
||||
|
||||
msgid "AdminSettings|Maximum number of DAG dependencies that a job can have"
|
||||
msgstr ""
|
||||
|
||||
msgid "AdminSettings|Maximum number of Instance-level CI/CD variables that can be defined"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -4024,6 +4021,9 @@ msgstr ""
|
|||
msgid "AdminSettings|Maximum number of jobs in a single pipeline"
|
||||
msgstr ""
|
||||
|
||||
msgid "AdminSettings|Maximum number of needs dependencies that a job can have"
|
||||
msgstr ""
|
||||
|
||||
msgid "AdminSettings|Maximum number of pipeline schedules"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -4183,7 +4183,7 @@ msgstr ""
|
|||
msgid "AdminSettings|This cost factor will be applied to the storage consumed by forks."
|
||||
msgstr ""
|
||||
|
||||
msgid "AdminSettings|This limit cannot be disabled. Set to 0 to block all DAG dependencies."
|
||||
msgid "AdminSettings|This limit cannot be disabled. Set to 0 to block all job (needs) dependencies."
|
||||
msgstr ""
|
||||
|
||||
msgid "AdminSettings|To enable Registration Features, first enable Service Ping."
|
||||
|
|
@ -16378,9 +16378,6 @@ msgstr ""
|
|||
msgid "CycleAnalytics|seconds"
|
||||
msgstr ""
|
||||
|
||||
msgid "DAG visualization requires at least 3 dependent jobs."
|
||||
msgstr ""
|
||||
|
||||
msgid "DAST configuration not found"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -26896,7 +26893,7 @@ msgstr ""
|
|||
msgid "If using GitHub, you’ll see pipeline statuses on GitHub for your commits and pull requests. %{more_info_link}"
|
||||
msgstr ""
|
||||
|
||||
msgid "If you add %{codeStart}needs%{codeEnd} to jobs in your pipeline you'll be able to view the %{codeStart}needs%{codeEnd} relationships between jobs in this tab as a %{linkStart}Directed Acyclic Graph (DAG)%{linkEnd}."
|
||||
msgid "If you add %{codeStart}needs%{codeEnd} to jobs in your pipeline you'll be able to view the %{codeStart}needs%{codeEnd} dependencies between jobs in this tab."
|
||||
msgstr ""
|
||||
|
||||
msgid "If you are unable to sign in or recover your password, contact a GitLab administrator."
|
||||
|
|
@ -30771,9 +30768,6 @@ msgstr ""
|
|||
msgid "Learn more about GitLab"
|
||||
msgstr ""
|
||||
|
||||
msgid "Learn more about Needs relationships"
|
||||
msgstr ""
|
||||
|
||||
msgid "Learn more about Service Desk"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -30810,6 +30804,9 @@ msgstr ""
|
|||
msgid "Learn more about max seats used"
|
||||
msgstr ""
|
||||
|
||||
msgid "Learn more about needs dependencies"
|
||||
msgstr ""
|
||||
|
||||
msgid "Learn more about seats owed"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -34525,6 +34522,9 @@ msgstr ""
|
|||
msgid "Needs attention"
|
||||
msgstr ""
|
||||
|
||||
msgid "Needs visualization requires at least 3 dependent jobs."
|
||||
msgstr ""
|
||||
|
||||
msgid "Network"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,8 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
# We need to take some precautions when using the `gitlab` gem in this project.
|
||||
#
|
||||
# See https://docs.gitlab.com/ee/development/pipelines/internals.html#using-the-gitlab-ruby-gem-in-the-canonical-project.
|
||||
require 'gitlab'
|
||||
require_relative 'default_options'
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,8 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
# We need to take some precautions when using the `gitlab` gem in this project.
|
||||
#
|
||||
# See https://docs.gitlab.com/ee/development/pipelines/internals.html#using-the-gitlab-ruby-gem-in-the-canonical-project.
|
||||
require 'gitlab'
|
||||
require_relative 'default_options'
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,8 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
# We need to take some precautions when using the `gitlab` gem in this project.
|
||||
#
|
||||
# See https://docs.gitlab.com/ee/development/pipelines/internals.html#using-the-gitlab-ruby-gem-in-the-canonical-project.
|
||||
require 'gitlab'
|
||||
require_relative 'default_options'
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,9 @@
|
|||
|
||||
# frozen_string_literal: true
|
||||
|
||||
# We need to take some precautions when using the `gitlab` gem in this project.
|
||||
#
|
||||
# See https://docs.gitlab.com/ee/development/pipelines/internals.html#using-the-gitlab-ruby-gem-in-the-canonical-project.
|
||||
require 'gitlab'
|
||||
|
||||
require_relative 'api/default_options'
|
||||
|
|
|
|||
|
|
@ -1,6 +1,9 @@
|
|||
#!/usr/bin/env ruby
|
||||
# frozen_string_literal: true
|
||||
|
||||
# We need to take some precautions when using the `gitlab` gem in this project.
|
||||
#
|
||||
# See https://docs.gitlab.com/ee/development/pipelines/internals.html#using-the-gitlab-ruby-gem-in-the-canonical-project.
|
||||
require 'gitlab'
|
||||
require 'json'
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,9 @@
|
|||
|
||||
# frozen_string_literal: true
|
||||
|
||||
# We need to take some precautions when using the `gitlab` gem in this project.
|
||||
#
|
||||
# See https://docs.gitlab.com/ee/development/pipelines/internals.html#using-the-gitlab-ruby-gem-in-the-canonical-project.
|
||||
require 'gitlab'
|
||||
require 'optparse'
|
||||
|
||||
|
|
|
|||
|
|
@ -2,8 +2,11 @@
|
|||
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'optparse'
|
||||
# We need to take some precautions when using the `gitlab` gem in this project.
|
||||
#
|
||||
# See https://docs.gitlab.com/ee/development/pipelines/internals.html#using-the-gitlab-ruby-gem-in-the-canonical-project.
|
||||
require 'gitlab'
|
||||
require 'optparse'
|
||||
|
||||
module Packages
|
||||
class AutomatedCleanup
|
||||
|
|
|
|||
|
|
@ -11,9 +11,12 @@
|
|||
# - See https://gitlab.com/gitlab-org/gitlab/-/issues/325640
|
||||
# - See https://gitlab.com/groups/gitlab-org/-/epics/5670
|
||||
|
||||
require 'rubygems'
|
||||
# We need to take some precautions when using the `gitlab` gem in this project.
|
||||
#
|
||||
# See https://docs.gitlab.com/ee/development/pipelines/internals.html#using-the-gitlab-ruby-gem-in-the-canonical-project.
|
||||
require 'gitlab'
|
||||
require 'optparse'
|
||||
require 'rubygems'
|
||||
|
||||
class QueryLimitingReport
|
||||
GITLAB_PROJECT_ID = 278964 # gitlab-org/gitlab project
|
||||
|
|
|
|||
|
|
@ -1,8 +1,17 @@
|
|||
#!/usr/bin/env ruby
|
||||
# frozen_string_literal: true
|
||||
|
||||
if Object.const_defined?(:RSpec)
|
||||
# Ok, we're testing, we know we're going to stub `Gitlab`, so we just ignore
|
||||
else
|
||||
require 'gitlab'
|
||||
|
||||
if Gitlab.singleton_class.method_defined?(:com?)
|
||||
abort 'lib/gitlab.rb is loaded, and this means we can no longer load the client and we cannot proceed'
|
||||
end
|
||||
end
|
||||
|
||||
require 'time'
|
||||
require 'gitlab' unless Object.const_defined?(:Gitlab)
|
||||
|
||||
class PreMergeChecks
|
||||
DEFAULT_API_ENDPOINT = "https://gitlab.com/api/v4"
|
||||
|
|
|
|||
|
|
@ -4,7 +4,16 @@
|
|||
# We need to take some precautions when using the `gitlab` gem in this project.
|
||||
#
|
||||
# See https://docs.gitlab.com/ee/development/pipelines/internals.html#using-the-gitlab-ruby-gem-in-the-canonical-project.
|
||||
require 'gitlab' unless Object.const_defined?(:Gitlab)
|
||||
if Object.const_defined?(:RSpec)
|
||||
# Ok, we're testing, we know we're going to stub `Gitlab`, so we just ignore
|
||||
else
|
||||
require 'gitlab'
|
||||
|
||||
if Gitlab.singleton_class.method_defined?(:com?)
|
||||
abort 'lib/gitlab.rb is loaded, and this means we can no longer load the client and we cannot proceed'
|
||||
end
|
||||
end
|
||||
|
||||
require 'net/http'
|
||||
|
||||
class SetPipelineName
|
||||
|
|
|
|||
|
|
@ -2,8 +2,11 @@
|
|||
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'optparse'
|
||||
# We need to take some precautions when using the `gitlab` gem in this project.
|
||||
#
|
||||
# See https://docs.gitlab.com/ee/development/pipelines/internals.html#using-the-gitlab-ruby-gem-in-the-canonical-project.
|
||||
require 'gitlab'
|
||||
require 'optparse'
|
||||
require_relative File.expand_path('../../tooling/lib/tooling/helm3_client.rb', __dir__)
|
||||
require_relative File.expand_path('../../tooling/lib/tooling/kubernetes_client.rb', __dir__)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,20 @@
|
|||
#!/usr/bin/env ruby
|
||||
# frozen_string_literal: true
|
||||
|
||||
# We need to take some precautions when using the `gitlab` gem in this project.
|
||||
#
|
||||
# See https://docs.gitlab.com/ee/development/pipelines/internals.html#using-the-gitlab-ruby-gem-in-the-canonical-project.
|
||||
#
|
||||
# In spec/scripts/setup/find_jh_branch_spec.rb we completely stub it
|
||||
require 'gitlab' unless Object.const_defined?(:Gitlab)
|
||||
if Object.const_defined?(:RSpec)
|
||||
# Ok, we're testing, we know we're going to stub `Gitlab`, so we just ignore
|
||||
else
|
||||
require 'gitlab'
|
||||
|
||||
if Gitlab.singleton_class.method_defined?(:com?)
|
||||
abort 'lib/gitlab.rb is loaded, and this means we can no longer load the client and we cannot proceed'
|
||||
end
|
||||
end
|
||||
|
||||
require_relative '../api/default_options'
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,21 @@
|
|||
#!/usr/bin/env ruby
|
||||
# frozen_string_literal: true
|
||||
|
||||
# We need to take some precautions when using the `gitlab` gem in this project.
|
||||
#
|
||||
# See https://docs.gitlab.com/ee/development/pipelines/internals.html#using-the-gitlab-ruby-gem-in-the-canonical-project.
|
||||
#
|
||||
# In spec/scripts/setup/generate_as_if_foss_env_spec.rb we completely stub it
|
||||
require 'gitlab' unless Object.const_defined?(:Gitlab)
|
||||
if Object.const_defined?(:RSpec)
|
||||
# Ok, we're testing, we know we're going to stub `Gitlab`, so we just ignore
|
||||
else
|
||||
require 'gitlab'
|
||||
|
||||
if Gitlab.singleton_class.method_defined?(:com?)
|
||||
abort 'lib/gitlab.rb is loaded, and this means we can no longer load the client and we cannot proceed'
|
||||
end
|
||||
end
|
||||
|
||||
require 'set' # rubocop:disable Lint/RedundantRequireStatement -- Ruby 3.1 and earlier needs this. Drop this line after Ruby 3.2+ is only supported.
|
||||
|
||||
class GenerateAsIfFossEnv
|
||||
|
|
|
|||
|
|
@ -1,6 +1,9 @@
|
|||
#!/usr/bin/env ruby
|
||||
# frozen_string_literal: true
|
||||
|
||||
# We need to take some precautions when using the `gitlab` gem in this project.
|
||||
#
|
||||
# See https://docs.gitlab.com/ee/development/pipelines/internals.html#using-the-gitlab-ruby-gem-in-the-canonical-project.
|
||||
require 'gitlab'
|
||||
|
||||
module Trigger
|
||||
|
|
|
|||
|
|
@ -2,9 +2,63 @@
|
|||
|
||||
require 'spec_helper'
|
||||
|
||||
# ***********************************************************************************************************
|
||||
# The tests in this file are recommended to run locally to test ci configuration changes
|
||||
# The test runs quite slowly because our configuration logic is very complex and it takes time to process
|
||||
# ***********************************************************************************************************
|
||||
#
|
||||
# HOW TO CONTRIBUTE
|
||||
#
|
||||
# For example, ci rule changes could break gitlab-foss pipelines, as seen in
|
||||
# https://gitlab.com/gitlab-org/quality/engineering-productivity/master-broken-incidents/-/issues/7356
|
||||
# we then added test cases by simulating pipeline for gitlab-org/gitlab-foss
|
||||
# See `with gitlab.com gitlab-org gitlab-foss project` context below for details.
|
||||
# If you think we are missing important test cases for a pipeline type, please add them following this exmaple.
|
||||
# ***********************************************************************************************************
|
||||
RSpec.describe 'ci jobs dependency', feature_category: :tooling,
|
||||
quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/34040#note_1991033499' do
|
||||
include RepoHelpers
|
||||
def sync_local_files_to_project(project, user, branch_name, files:)
|
||||
actions = []
|
||||
|
||||
entries = project.repository.tree(branch_name, recursive: true).entries
|
||||
entries.map! { |e| e.dir? ? project.repository.tree(branch_name, e.path, recursive: true).entries : e }
|
||||
current_files = entries.flatten.select(&:file?).map(&:path).uniq
|
||||
|
||||
# Delete old
|
||||
actions.concat (current_files - files).map { |file| { action: :delete, file_path: file } }
|
||||
# Add new
|
||||
actions.concat (files - current_files).map { |file|
|
||||
{ action: :create, file_path: file, content: read_file(file) }
|
||||
}
|
||||
|
||||
# Update changed
|
||||
(current_files & files).each do |file|
|
||||
content = read_file(file)
|
||||
if content != project.repository.blob_data_at(branch_name, file)
|
||||
actions << { action: :update, file_path: file, content: content }
|
||||
end
|
||||
end
|
||||
|
||||
if actions.any?
|
||||
puts "Syncing files to #{branch_name} branch"
|
||||
project.repository.commit_files(user, branch_name: branch_name, message: 'syncing', actions: actions)
|
||||
else
|
||||
puts "No file syncing needed"
|
||||
end
|
||||
end
|
||||
|
||||
def read_file(file, ignore_ci_component: true)
|
||||
content = File.read(file)
|
||||
|
||||
return content unless ignore_ci_component
|
||||
|
||||
fake_job = <<~YAML
|
||||
.ignore:
|
||||
script: echo ok
|
||||
YAML
|
||||
|
||||
file.end_with?('.yml') && %r{^\s*- component:.*CI_SERVER_}.match?(content) ? fake_job : content
|
||||
end
|
||||
|
||||
let_it_be(:group) { create(:group, path: 'ci-org') }
|
||||
let_it_be(:user) { create(:user) }
|
||||
|
|
@ -15,11 +69,13 @@ RSpec.describe 'ci jobs dependency', feature_category: :tooling,
|
|||
let(:gitlab_com_variables_attributes_base) do
|
||||
[
|
||||
{ key: 'CI_SERVER_HOST', value: 'gitlab.com' },
|
||||
{ key: 'CI_PROJECT_NAMESPACE', value: 'gitlab-org/gitlab' }
|
||||
{ key: 'CI_PROJECT_NAMESPACE', value: 'gitlab-org' },
|
||||
{ key: 'CI_PROJECT_PATH', value: 'gitlab-org/gitlab' }
|
||||
]
|
||||
end
|
||||
|
||||
let(:create_pipeline_service) { Ci::CreatePipelineService.new(project, user, ref: master_branch) }
|
||||
let(:jobs) { pipeline.stages.flat_map { |s| s.statuses.map(&:name) } }
|
||||
|
||||
around(:all) do |example|
|
||||
with_net_connect_allowed { example.run } # creating pipeline requires network call to fetch templates
|
||||
|
|
@ -36,38 +92,44 @@ RSpec.describe 'ci jobs dependency', feature_category: :tooling,
|
|||
)
|
||||
end
|
||||
|
||||
context 'with gitlab.com gitlab-org/gitlab master pipeline' do
|
||||
shared_examples 'master pipeline' do
|
||||
let(:content) do
|
||||
project.repository.blob_at(master_branch, '.gitlab-ci.yml').data
|
||||
end
|
||||
|
||||
shared_examples 'master pipeline' do |trigger_source|
|
||||
subject(:pipeline) do
|
||||
create_pipeline_service
|
||||
.execute(trigger_source, dry_run: true, content: content, variables_attributes: variables_attributes)
|
||||
.payload
|
||||
end
|
||||
|
||||
it 'is valid' do
|
||||
expect(pipeline.yaml_errors).to be nil
|
||||
expect(pipeline.status).to eq('created')
|
||||
end
|
||||
subject(:pipeline) do
|
||||
create_pipeline_service
|
||||
.execute(trigger_source, dry_run: true, content: content, variables_attributes: variables_attributes)
|
||||
.payload
|
||||
end
|
||||
|
||||
it 'is valid' do
|
||||
expect(pipeline.yaml_errors).to be nil
|
||||
expect(pipeline.status).to eq('created')
|
||||
expect(jobs).to include(expected_job_name)
|
||||
end
|
||||
end
|
||||
|
||||
context 'with gitlab.com gitlab-org/gitlab master pipeline' do
|
||||
context 'with default master pipeline' do
|
||||
let(:variables_attributes) { gitlab_com_variables_attributes_base }
|
||||
let(:trigger_source) { :push }
|
||||
let(:expected_job_name) { 'rspec background_migration pg14 1/5' }
|
||||
|
||||
# Test: remove rules from .rails:rules:setup-test-env
|
||||
it_behaves_like 'master pipeline', :push
|
||||
it_behaves_like 'master pipeline'
|
||||
end
|
||||
|
||||
context 'with scheduled nightly' do
|
||||
let(:trigger_source) { :schedule }
|
||||
let(:expected_job_name) { 'rspec migration pg16 1/15' }
|
||||
let(:variables_attributes) do
|
||||
[
|
||||
*gitlab_com_variables_attributes_base,
|
||||
{ key: 'SCHEDULE_TYPE', value: 'nightly' }
|
||||
]
|
||||
end
|
||||
|
||||
# .if-default-branch-schedule-nightly
|
||||
# included in .qa:rules:package-and-test-ce
|
||||
# used by e2e:package-and-test-ce
|
||||
|
|
@ -77,10 +139,12 @@ RSpec.describe 'ci jobs dependency', feature_category: :tooling,
|
|||
# Test: I can remove this rule from .qa:rules:determine-e2e-tests
|
||||
# - <<: *if-dot-com-gitlab-org-schedule
|
||||
# allow_failure: true
|
||||
it_behaves_like 'master pipeline', :schedule
|
||||
it_behaves_like 'master pipeline'
|
||||
end
|
||||
|
||||
context 'with scheduled maintenance' do
|
||||
let(:trigger_source) { :schedule }
|
||||
let(:expected_job_name) { 'rspec-ee system pg14 no_gitaly_transactions 1/14' }
|
||||
let(:variables_attributes) do
|
||||
[
|
||||
*gitlab_com_variables_attributes_base,
|
||||
|
|
@ -88,7 +152,33 @@ RSpec.describe 'ci jobs dependency', feature_category: :tooling,
|
|||
]
|
||||
end
|
||||
|
||||
it_behaves_like 'master pipeline', :schedule
|
||||
it_behaves_like 'master pipeline'
|
||||
end
|
||||
end
|
||||
|
||||
context 'with gitlab.com gitlab-org gitlab-foss project' do
|
||||
let(:variables_attributes) do
|
||||
[
|
||||
{ key: 'CI_SERVER_HOST', value: 'gitlab.com' },
|
||||
{ key: 'CI_PROJECT_NAMESPACE', value: 'gitlab-org' },
|
||||
{ key: 'CI_PROJECT_PATH', value: 'gitlab-org/gitlab-foss' }
|
||||
]
|
||||
end
|
||||
|
||||
context 'with master pipeline triggered by push' do
|
||||
let(:trigger_source) { :push }
|
||||
let(:expected_job_name) { 'rspec background_migration pg14 1/5' }
|
||||
|
||||
it_behaves_like 'master pipeline'
|
||||
end
|
||||
|
||||
context 'with scheduled master pipeline' do
|
||||
let(:trigger_source) { :schedule }
|
||||
let(:expected_job_name) { 'rspec background_migration pg14 1/5' }
|
||||
|
||||
# Verify by removing the following rule from .qa:rules:e2e:test-on-cng
|
||||
# - !reference [".qa:rules:package-and-test-never-run", rules]
|
||||
it_behaves_like 'master pipeline'
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -149,7 +239,6 @@ RSpec.describe 'ci jobs dependency', feature_category: :tooling,
|
|||
end
|
||||
|
||||
it "creates a valid pipeline with expected job" do
|
||||
jobs = pipeline.stages.flat_map { |s| s.statuses.map(&:name) }.join("\n")
|
||||
expect(pipeline.yaml_errors).to be nil
|
||||
expect(pipeline.status).to eq('created')
|
||||
# to confirm that the dependent job is actually created and rule out false positives
|
||||
|
|
@ -166,13 +255,13 @@ RSpec.describe 'ci jobs dependency', feature_category: :tooling,
|
|||
it_behaves_like 'merge request pipeline'
|
||||
end
|
||||
|
||||
# backstage-patterns, #.code-backstage-patterns and frontend ci pattern
|
||||
# Test: remove the following rules from `.frontend:rules:default-frontend-jobs`:
|
||||
# - <<: *if-merge-request-labels-run-all-rspec
|
||||
# - <<: *if-default-refs
|
||||
# changes: *code-backstage-patterns
|
||||
context 'when unlabled MR is changing Dangerfile, .gitlab/ci/frontend.gitlab-ci.yml' do
|
||||
let(:labels_string) { '' }
|
||||
let(:changed_files) { ['Dangerfile', '.gitlab/ci/frontend.gitlab-ci.yml'] }
|
||||
let(:expected_job_name) { 'rspec-all frontend_fixture' }
|
||||
let(:expected_job_name) { 'rspec-all frontend_fixture 1/7' }
|
||||
|
||||
it_behaves_like 'merge request pipeline'
|
||||
end
|
||||
|
|
@ -182,7 +271,7 @@ RSpec.describe 'ci jobs dependency', feature_category: :tooling,
|
|||
context 'when MR labeled with `pipeline:run-all-rspec` is changing keeps/quarantine-test.rb' do
|
||||
let(:labels_string) { 'pipeline:run-all-rspec' }
|
||||
let(:changed_files) { ['keeps/quarantine-test.rb'] }
|
||||
let(:expected_job_name) { 'rspec-all frontend_fixture' }
|
||||
let(:expected_job_name) { 'rspec-all frontend_fixture 1/7' }
|
||||
|
||||
it_behaves_like 'merge request pipeline'
|
||||
end
|
||||
|
|
@ -208,7 +297,7 @@ RSpec.describe 'ci jobs dependency', feature_category: :tooling,
|
|||
let(:create_pipeline_service) { Ci::CreatePipelineService.new(project, user, ref: target_branch) }
|
||||
let(:labels_string) { '' }
|
||||
let(:changed_files) { ['keeps/quarantine-test.rb'] }
|
||||
let(:expected_job_name) { 'rspec-all frontend_fixture' }
|
||||
let(:expected_job_name) { 'rspec-all frontend_fixture 1/7' }
|
||||
|
||||
before do
|
||||
sync_local_files_to_project(
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import { builders } from 'prosemirror-test-builder';
|
||||
import { GlLoadingIcon, GlListboxItem, GlCollapsibleListbox } from '@gitlab/ui';
|
||||
import { nextTick } from 'vue';
|
||||
import { mountExtended } from 'helpers/vue_test_utils_helper';
|
||||
|
|
@ -6,7 +7,7 @@ import ReferenceBubbleMenu from '~/content_editor/components/bubble_menus/refere
|
|||
import BubbleMenu from '~/content_editor/components/bubble_menus/bubble_menu.vue';
|
||||
import { stubComponent } from 'helpers/stub_component';
|
||||
import Reference from '~/content_editor/extensions/reference';
|
||||
import { createTestEditor, emitEditorEvent, createDocBuilder } from '../../test_utils';
|
||||
import { createTestEditor, emitEditorEvent } from '../../test_utils';
|
||||
|
||||
const mockWorkItem = {
|
||||
href: 'https://gitlab.com/gitlab-org/gitlab/-/work_items/12',
|
||||
|
|
@ -51,14 +52,7 @@ describe('content_editor/components/bubble_menus/reference_bubble_menu', () => {
|
|||
contentEditor = { resolveReference: jest.fn().mockImplementation(() => new Promise(() => {})) };
|
||||
eventHub = eventHubFactory();
|
||||
|
||||
({
|
||||
builders: { doc, p, reference },
|
||||
} = createDocBuilder({
|
||||
tiptapEditor,
|
||||
names: {
|
||||
reference: { nodeType: Reference.name },
|
||||
},
|
||||
}));
|
||||
({ doc, paragraph: p, reference } = builders(tiptapEditor.schema));
|
||||
};
|
||||
|
||||
const expectedDocs = {
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import { builders } from 'prosemirror-test-builder';
|
||||
import { nextTick } from 'vue';
|
||||
import { NodeViewWrapper } from '@tiptap/vue-2';
|
||||
import { mountExtended } from 'helpers/vue_test_utils_helper';
|
||||
|
|
@ -6,7 +7,7 @@ import eventHubFactory from '~/helpers/event_hub_factory';
|
|||
import Heading from '~/content_editor/extensions/heading';
|
||||
import Diagram from '~/content_editor/extensions/diagram';
|
||||
import TableOfContentsWrapper from '~/content_editor/components/wrappers/table_of_contents.vue';
|
||||
import { createTestEditor, createDocBuilder, emitEditorEvent } from '../../test_utils';
|
||||
import { createTestEditor, emitEditorEvent } from '../../test_utils';
|
||||
|
||||
describe('content/components/wrappers/table_of_contents', () => {
|
||||
let wrapper;
|
||||
|
|
@ -43,14 +44,7 @@ describe('content/components/wrappers/table_of_contents', () => {
|
|||
buildEditor();
|
||||
createWrapper();
|
||||
|
||||
const {
|
||||
builders: { heading, doc },
|
||||
} = createDocBuilder({
|
||||
tiptapEditor,
|
||||
names: {
|
||||
heading: { nodeType: Heading.name },
|
||||
},
|
||||
});
|
||||
const { heading, doc } = builders(tiptapEditor.schema);
|
||||
|
||||
const initialDoc = doc(
|
||||
heading({ level: 1 }, 'Heading 1'),
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import fs from 'fs';
|
||||
import axios from 'axios';
|
||||
import MockAdapter from 'axios-mock-adapter';
|
||||
import { builders } from 'prosemirror-test-builder';
|
||||
import Attachment from '~/content_editor/extensions/attachment';
|
||||
import DrawioDiagram from '~/content_editor/extensions/drawio_diagram';
|
||||
import Image from '~/content_editor/extensions/image';
|
||||
|
|
@ -10,7 +11,7 @@ import Link from '~/content_editor/extensions/link';
|
|||
import { VARIANT_DANGER } from '~/alert';
|
||||
import { HTTP_STATUS_INTERNAL_SERVER_ERROR, HTTP_STATUS_OK } from '~/lib/utils/http_status';
|
||||
import eventHubFactory from '~/helpers/event_hub_factory';
|
||||
import { createTestEditor, createDocBuilder, expectDocumentAfterTransaction } from '../test_utils';
|
||||
import { createTestEditor, expectDocumentAfterTransaction } from '../test_utils';
|
||||
import {
|
||||
PROJECT_WIKI_ATTACHMENT_IMAGE_HTML,
|
||||
PROJECT_WIKI_ATTACHMENT_IMAGE_SVG_HTML,
|
||||
|
|
@ -81,17 +82,14 @@ describe('content_editor/extensions/attachment', () => {
|
|||
});
|
||||
|
||||
({
|
||||
builders: { doc, p, image, audio, video, link, drawioDiagram },
|
||||
} = createDocBuilder({
|
||||
tiptapEditor,
|
||||
names: {
|
||||
image: { nodeType: Image.name },
|
||||
link: { nodeType: Link.name },
|
||||
audio: { nodeType: Audio.name },
|
||||
video: { nodeType: Video.name },
|
||||
drawioDiagram: { nodeType: DrawioDiagram.name },
|
||||
},
|
||||
}));
|
||||
doc,
|
||||
paragraph: p,
|
||||
image,
|
||||
audio,
|
||||
video,
|
||||
link,
|
||||
drawioDiagram,
|
||||
} = builders(tiptapEditor.schema));
|
||||
|
||||
mock = new MockAdapter(axios);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import { builders } from 'prosemirror-test-builder';
|
||||
import Blockquote from '~/content_editor/extensions/blockquote';
|
||||
import { createTestEditor, createDocBuilder, triggerNodeInputRule } from '../test_utils';
|
||||
import { createTestEditor, triggerNodeInputRule } from '../test_utils';
|
||||
|
||||
describe('content_editor/extensions/blockquote', () => {
|
||||
let tiptapEditor;
|
||||
|
|
@ -10,14 +11,7 @@ describe('content_editor/extensions/blockquote', () => {
|
|||
beforeEach(() => {
|
||||
tiptapEditor = createTestEditor({ extensions: [Blockquote] });
|
||||
|
||||
({
|
||||
builders: { doc, p, blockquote },
|
||||
} = createDocBuilder({
|
||||
tiptapEditor,
|
||||
names: {
|
||||
blockquote: { nodeType: Blockquote.name },
|
||||
},
|
||||
}));
|
||||
({ doc, paragraph: p, blockquote } = builders(tiptapEditor.schema));
|
||||
});
|
||||
|
||||
it.each`
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import { builders } from 'prosemirror-test-builder';
|
||||
import CodeBlockHighlight from '~/content_editor/extensions/code_block_highlight';
|
||||
import languageLoader from '~/content_editor/services/code_block_language_loader';
|
||||
import { createTestEditor, createDocBuilder, triggerNodeInputRule } from '../test_utils';
|
||||
import { createTestEditor, triggerNodeInputRule } from '../test_utils';
|
||||
|
||||
const CODE_BLOCK_HTML = `<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:1-3:3" data-canonical-lang="javascript" class="code highlight js-syntax-highlight language-javascript" v-pre="true"><code><span id="LC1" class="line" lang="javascript"><span class="nx">console</span><span class="p">.</span><span class="nf">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">hello world</span><span class="dl">'</span><span class="p">)</span></span></code></pre>
<copy-code></copy-code>
</div>`;
|
||||
|
||||
|
|
@ -16,14 +17,7 @@ describe('content_editor/extensions/code_block_highlight', () => {
|
|||
extensions: [CodeBlockHighlight],
|
||||
});
|
||||
|
||||
({
|
||||
builders: { doc, codeBlock },
|
||||
} = createDocBuilder({
|
||||
tiptapEditor,
|
||||
names: {
|
||||
codeBlock: { nodeType: CodeBlockHighlight.name },
|
||||
},
|
||||
}));
|
||||
({ doc, codeBlock } = builders(tiptapEditor.schema));
|
||||
});
|
||||
|
||||
describe('when parsing HTML', () => {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import { builders } from 'prosemirror-test-builder';
|
||||
import Bold from '~/content_editor/extensions/bold';
|
||||
import Code from '~/content_editor/extensions/code';
|
||||
import { createTestEditor, createDocBuilder } from '../test_utils';
|
||||
import { createTestEditor } from '../test_utils';
|
||||
|
||||
describe('content_editor/extensions/code', () => {
|
||||
let tiptapEditor;
|
||||
|
|
@ -12,15 +13,7 @@ describe('content_editor/extensions/code', () => {
|
|||
beforeEach(() => {
|
||||
tiptapEditor = createTestEditor({ extensions: [Bold, Code] });
|
||||
|
||||
({
|
||||
builders: { doc, p, bold, code },
|
||||
} = createDocBuilder({
|
||||
tiptapEditor,
|
||||
names: {
|
||||
bold: { markType: Bold.name },
|
||||
code: { markType: Code.name },
|
||||
},
|
||||
}));
|
||||
({ doc, paragraph: p, bold, code } = builders(tiptapEditor.schema));
|
||||
});
|
||||
|
||||
it.each`
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
import { builders } from 'prosemirror-test-builder';
|
||||
import CodeBlockHighlight from '~/content_editor/extensions/code_block_highlight';
|
||||
import CodeSuggestion from '~/content_editor/extensions/code_suggestion';
|
||||
import {
|
||||
createTestEditor,
|
||||
createDocBuilder,
|
||||
triggerNodeInputRule,
|
||||
expectDocumentAfterTransaction,
|
||||
sleep,
|
||||
|
|
@ -51,15 +51,7 @@ describe('content_editor/extensions/code_suggestion', () => {
|
|||
],
|
||||
});
|
||||
|
||||
({
|
||||
builders: { doc, codeSuggestion },
|
||||
} = createDocBuilder({
|
||||
tiptapEditor,
|
||||
names: {
|
||||
codeBlock: { nodeType: CodeBlockHighlight.name },
|
||||
codeSuggestion: { nodeType: CodeSuggestion.name },
|
||||
},
|
||||
}));
|
||||
({ doc, codeSuggestion } = builders(tiptapEditor.schema));
|
||||
};
|
||||
|
||||
describe('insertCodeSuggestion command', () => {
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import { builders } from 'prosemirror-test-builder';
|
||||
import CopyPaste from '~/content_editor/extensions/copy_paste';
|
||||
import CodeBlockHighlight from '~/content_editor/extensions/code_block_highlight';
|
||||
import Loading, { findAllLoaders } from '~/content_editor/extensions/loading';
|
||||
|
|
@ -18,7 +19,7 @@ import eventHubFactory from '~/helpers/event_hub_factory';
|
|||
import { ALERT_EVENT } from '~/content_editor/constants';
|
||||
import waitForPromises from 'helpers/wait_for_promises';
|
||||
import MarkdownSerializer from '~/content_editor/services/markdown_serializer';
|
||||
import { createTestEditor, createDocBuilder, waitUntilNextDocTransaction } from '../test_utils';
|
||||
import { createTestEditor, waitUntilNextDocTransaction } from '../test_utils';
|
||||
|
||||
const PARAGRAPH_HTML =
|
||||
'<p dir="auto">Some text with <strong>bold</strong> and <em>italic</em> text.</p>';
|
||||
|
|
@ -72,20 +73,15 @@ describe('content_editor/extensions/copy_paste', () => {
|
|||
});
|
||||
|
||||
({
|
||||
builders: { doc, p, bold, italic, heading, codeBlock, bulletList, listItem },
|
||||
} = createDocBuilder({
|
||||
tiptapEditor,
|
||||
names: {
|
||||
bold: { markType: Bold.name },
|
||||
italic: { markType: Italic.name },
|
||||
heading: { nodeType: Heading.name },
|
||||
bulletList: { nodeType: BulletList.name },
|
||||
listItem: { nodeType: ListItem.name },
|
||||
codeBlock: { nodeType: CodeBlockHighlight.name },
|
||||
diagram: { nodeType: Diagram.name },
|
||||
frontmatter: { nodeType: Frontmatter.name },
|
||||
},
|
||||
}));
|
||||
doc,
|
||||
paragraph: p,
|
||||
bold,
|
||||
italic,
|
||||
heading,
|
||||
codeBlock,
|
||||
bulletList,
|
||||
listItem,
|
||||
} = builders(tiptapEditor.schema));
|
||||
});
|
||||
|
||||
const buildClipboardEvent = ({ eventName = 'paste', data = {}, types = ['text/plain'] } = {}) => {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import { builders } from 'prosemirror-test-builder';
|
||||
import DescriptionList from '~/content_editor/extensions/description_list';
|
||||
import DescriptionItem from '~/content_editor/extensions/description_item';
|
||||
import { createTestEditor, createDocBuilder, triggerKeyboardInput } from '../test_utils';
|
||||
import { createTestEditor, triggerKeyboardInput } from '../test_utils';
|
||||
|
||||
describe('content_editor/extensions/description_item', () => {
|
||||
let tiptapEditor;
|
||||
|
|
@ -12,15 +13,7 @@ describe('content_editor/extensions/description_item', () => {
|
|||
beforeEach(() => {
|
||||
tiptapEditor = createTestEditor({ extensions: [DescriptionList, DescriptionItem] });
|
||||
|
||||
({
|
||||
builders: { doc, p, descriptionList, descriptionItem },
|
||||
} = createDocBuilder({
|
||||
tiptapEditor,
|
||||
names: {
|
||||
descriptionList: { nodeType: DescriptionList.name },
|
||||
descriptionItem: { nodeType: DescriptionItem.name },
|
||||
},
|
||||
}));
|
||||
({ doc, paragraph: p, descriptionList, descriptionItem } = builders(tiptapEditor.schema));
|
||||
});
|
||||
|
||||
describe('shortcut: Enter', () => {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import { builders } from 'prosemirror-test-builder';
|
||||
import DescriptionList from '~/content_editor/extensions/description_list';
|
||||
import DescriptionItem from '~/content_editor/extensions/description_item';
|
||||
import { createTestEditor, createDocBuilder, triggerNodeInputRule } from '../test_utils';
|
||||
import { createTestEditor, triggerNodeInputRule } from '../test_utils';
|
||||
|
||||
describe('content_editor/extensions/description_list', () => {
|
||||
let tiptapEditor;
|
||||
|
|
@ -12,15 +13,7 @@ describe('content_editor/extensions/description_list', () => {
|
|||
beforeEach(() => {
|
||||
tiptapEditor = createTestEditor({ extensions: [DescriptionList, DescriptionItem] });
|
||||
|
||||
({
|
||||
builders: { doc, p, descriptionList, descriptionItem },
|
||||
} = createDocBuilder({
|
||||
tiptapEditor,
|
||||
names: {
|
||||
descriptionList: { nodeType: DescriptionList.name },
|
||||
descriptionItem: { nodeType: DescriptionItem.name },
|
||||
},
|
||||
}));
|
||||
({ doc, paragraph: p, descriptionList, descriptionItem } = builders(tiptapEditor.schema));
|
||||
});
|
||||
|
||||
it.each`
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import { builders } from 'prosemirror-test-builder';
|
||||
import Details from '~/content_editor/extensions/details';
|
||||
import DetailsContent from '~/content_editor/extensions/details_content';
|
||||
import { createTestEditor, createDocBuilder, triggerKeyboardInput } from '../test_utils';
|
||||
import { createTestEditor, triggerKeyboardInput } from '../test_utils';
|
||||
|
||||
describe('content_editor/extensions/details_content', () => {
|
||||
let tiptapEditor;
|
||||
|
|
@ -12,15 +13,7 @@ describe('content_editor/extensions/details_content', () => {
|
|||
beforeEach(() => {
|
||||
tiptapEditor = createTestEditor({ extensions: [Details, DetailsContent] });
|
||||
|
||||
({
|
||||
builders: { doc, p, details, detailsContent },
|
||||
} = createDocBuilder({
|
||||
tiptapEditor,
|
||||
names: {
|
||||
details: { nodeType: Details.name },
|
||||
detailsContent: { nodeType: DetailsContent.name },
|
||||
},
|
||||
}));
|
||||
({ doc, paragraph: p, details, detailsContent } = builders(tiptapEditor.schema));
|
||||
});
|
||||
|
||||
describe('shortcut: Enter', () => {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import { builders } from 'prosemirror-test-builder';
|
||||
import Details from '~/content_editor/extensions/details';
|
||||
import DetailsContent from '~/content_editor/extensions/details_content';
|
||||
import { createTestEditor, createDocBuilder, triggerNodeInputRule } from '../test_utils';
|
||||
import { createTestEditor, triggerNodeInputRule } from '../test_utils';
|
||||
|
||||
describe('content_editor/extensions/details', () => {
|
||||
let tiptapEditor;
|
||||
|
|
@ -12,15 +13,7 @@ describe('content_editor/extensions/details', () => {
|
|||
beforeEach(() => {
|
||||
tiptapEditor = createTestEditor({ extensions: [Details, DetailsContent] });
|
||||
|
||||
({
|
||||
builders: { doc, p, details, detailsContent },
|
||||
} = createDocBuilder({
|
||||
tiptapEditor,
|
||||
names: {
|
||||
details: { nodeType: Details.name },
|
||||
detailsContent: { nodeType: DetailsContent.name },
|
||||
},
|
||||
}));
|
||||
({ doc, paragraph: p, details, detailsContent } = builders(tiptapEditor.schema));
|
||||
});
|
||||
|
||||
describe('setDetails command', () => {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import { builders } from 'prosemirror-test-builder';
|
||||
import Diagram from '~/content_editor/extensions/diagram';
|
||||
import CodeBlockHighlight from '~/content_editor/extensions/code_block_highlight';
|
||||
import { createTestEditor, createDocBuilder } from '../test_utils';
|
||||
import { createTestEditor } from '../test_utils';
|
||||
|
||||
const DIAGRAM_HTML = `<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:1-5:3" data-canonical-lang="mermaid" class="code highlight js-syntax-highlight language-mermaid" v-pre="true"><code class="js-render-mermaid"><span id="LC1" class="line" lang="mermaid">pie title NETFLIX</span>
<span id="LC2" class="line" lang="mermaid"> "Time spent looking for movie" : 90</span>
<span id="LC3" class="line" lang="mermaid"> "Time spent watching it" : 10</span></code></pre>
<copy-code></copy-code>
</div>`;
|
||||
|
||||
|
|
@ -14,15 +15,7 @@ describe('content_editor/extensions/diagram', () => {
|
|||
extensions: [CodeBlockHighlight, Diagram],
|
||||
});
|
||||
|
||||
({
|
||||
builders: { doc, diagram },
|
||||
} = createDocBuilder({
|
||||
tiptapEditor,
|
||||
names: {
|
||||
codeBlock: { nodeType: CodeBlockHighlight.name },
|
||||
diagram: { nodeType: Diagram.name },
|
||||
},
|
||||
}));
|
||||
({ doc, diagram } = builders(tiptapEditor.schema));
|
||||
};
|
||||
|
||||
it('inherits from code block highlight extension', () => {
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
import { builders } from 'prosemirror-test-builder';
|
||||
import DrawioDiagram from '~/content_editor/extensions/drawio_diagram';
|
||||
import Image from '~/content_editor/extensions/image';
|
||||
import { create } from '~/drawio/content_editor_facade';
|
||||
import { launchDrawioEditor } from '~/drawio/drawio_editor';
|
||||
import { createTestEditor, createDocBuilder } from '../test_utils';
|
||||
import { createTestEditor } from '../test_utils';
|
||||
import {
|
||||
PROJECT_WIKI_ATTACHMENT_IMAGE_HTML,
|
||||
PROJECT_WIKI_ATTACHMENT_DRAWIO_DIAGRAM_HTML,
|
||||
|
|
@ -15,7 +16,7 @@ jest.mock('~/drawio/drawio_editor');
|
|||
describe('content_editor/extensions/drawio_diagram', () => {
|
||||
let tiptapEditor;
|
||||
let doc;
|
||||
let paragraph;
|
||||
let p;
|
||||
let image;
|
||||
let drawioDiagram;
|
||||
let assetResolver;
|
||||
|
|
@ -28,24 +29,14 @@ describe('content_editor/extensions/drawio_diagram', () => {
|
|||
tiptapEditor = createTestEditor({
|
||||
extensions: [Image, DrawioDiagram.configure({ uploadsPath, assetResolver })],
|
||||
});
|
||||
const { builders } = createDocBuilder({
|
||||
tiptapEditor,
|
||||
names: {
|
||||
image: { nodeType: Image.name },
|
||||
drawioDiagram: { nodeType: DrawioDiagram.name },
|
||||
},
|
||||
});
|
||||
|
||||
doc = builders.doc;
|
||||
paragraph = builders.paragraph;
|
||||
image = builders.image;
|
||||
drawioDiagram = builders.drawioDiagram;
|
||||
({ doc, paragraph: p, image, drawioDiagram } = builders(tiptapEditor.schema));
|
||||
});
|
||||
|
||||
describe('parsing', () => {
|
||||
it('distinguishes a drawio diagram from an image', () => {
|
||||
const expectedDocWithDiagram = doc(
|
||||
paragraph(
|
||||
p(
|
||||
drawioDiagram({
|
||||
alt: 'test-file',
|
||||
canonicalSrc: 'test-file.drawio.svg',
|
||||
|
|
@ -54,7 +45,7 @@ describe('content_editor/extensions/drawio_diagram', () => {
|
|||
),
|
||||
);
|
||||
const expectedDocWithImage = doc(
|
||||
paragraph(
|
||||
p(
|
||||
image({
|
||||
alt: 'test-file',
|
||||
canonicalSrc: 'test-file.png',
|
||||
|
|
|
|||
|
|
@ -1,13 +1,13 @@
|
|||
import { builders, eq } from 'prosemirror-test-builder';
|
||||
import { initEmojiMock } from 'helpers/emoji';
|
||||
import Emoji from '~/content_editor/extensions/emoji';
|
||||
import { createTestEditor, createDocBuilder, triggerNodeInputRule } from '../test_utils';
|
||||
import { createTestEditor, triggerNodeInputRule } from '../test_utils';
|
||||
|
||||
describe('content_editor/extensions/emoji', () => {
|
||||
let tiptapEditor;
|
||||
let doc;
|
||||
let p;
|
||||
let emoji;
|
||||
let eq;
|
||||
|
||||
beforeEach(async () => {
|
||||
await initEmojiMock();
|
||||
|
|
@ -15,15 +15,7 @@ describe('content_editor/extensions/emoji', () => {
|
|||
|
||||
beforeEach(() => {
|
||||
tiptapEditor = createTestEditor({ extensions: [Emoji] });
|
||||
({
|
||||
builders: { doc, p, emoji },
|
||||
eq,
|
||||
} = createDocBuilder({
|
||||
tiptapEditor,
|
||||
names: {
|
||||
loading: { nodeType: Emoji.name },
|
||||
},
|
||||
}));
|
||||
({ doc, paragraph: p, emoji } = builders(tiptapEditor.schema));
|
||||
});
|
||||
|
||||
describe('when typing a valid emoji input rule', () => {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import { builders } from 'prosemirror-test-builder';
|
||||
import Frontmatter from '~/content_editor/extensions/frontmatter';
|
||||
import CodeBlockHighlight from '~/content_editor/extensions/code_block_highlight';
|
||||
import { createTestEditor, createDocBuilder, triggerNodeInputRule } from '../test_utils';
|
||||
import { createTestEditor, triggerNodeInputRule } from '../test_utils';
|
||||
|
||||
describe('content_editor/extensions/frontmatter', () => {
|
||||
let tiptapEditor;
|
||||
|
|
@ -11,15 +12,7 @@ describe('content_editor/extensions/frontmatter', () => {
|
|||
beforeEach(() => {
|
||||
tiptapEditor = createTestEditor({ extensions: [Frontmatter, CodeBlockHighlight] });
|
||||
|
||||
({
|
||||
builders: { doc, codeBlock, frontmatter },
|
||||
} = createDocBuilder({
|
||||
tiptapEditor,
|
||||
names: {
|
||||
frontmatter: { nodeType: Frontmatter.name },
|
||||
codeBlock: { nodeType: CodeBlockHighlight.name },
|
||||
},
|
||||
}));
|
||||
({ doc, codeBlock, frontmatter } = builders(tiptapEditor.schema));
|
||||
});
|
||||
|
||||
it('inherits from code block highlight extension', () => {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import { builders } from 'prosemirror-test-builder';
|
||||
import HardBreak from '~/content_editor/extensions/hard_break';
|
||||
import { createTestEditor, createDocBuilder } from '../test_utils';
|
||||
import { createTestEditor } from '../test_utils';
|
||||
|
||||
describe('content_editor/extensions/hard_break', () => {
|
||||
let tiptapEditor;
|
||||
|
|
@ -10,12 +11,7 @@ describe('content_editor/extensions/hard_break', () => {
|
|||
beforeEach(() => {
|
||||
tiptapEditor = createTestEditor({ extensions: [HardBreak] });
|
||||
|
||||
({
|
||||
builders: { doc, p },
|
||||
} = createDocBuilder({
|
||||
tiptapEditor,
|
||||
names: { hardBreak: { nodeType: HardBreak.name } },
|
||||
}));
|
||||
({ doc, paragraph: p } = builders(tiptapEditor.schema));
|
||||
});
|
||||
|
||||
describe('Mod-Enter shortcut', () => {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import { builders } from 'prosemirror-test-builder';
|
||||
import Heading from '~/content_editor/extensions/heading';
|
||||
import { createTestEditor, createDocBuilder, triggerNodeInputRule } from '../test_utils';
|
||||
import { createTestEditor, triggerNodeInputRule } from '../test_utils';
|
||||
|
||||
describe('content_editor/extensions/heading', () => {
|
||||
let tiptapEditor;
|
||||
|
|
@ -9,14 +10,7 @@ describe('content_editor/extensions/heading', () => {
|
|||
|
||||
beforeEach(() => {
|
||||
tiptapEditor = createTestEditor({ extensions: [Heading] });
|
||||
({
|
||||
builders: { doc, p, heading },
|
||||
} = createDocBuilder({
|
||||
tiptapEditor,
|
||||
names: {
|
||||
heading: { nodeType: Heading.name },
|
||||
},
|
||||
}));
|
||||
({ doc, paragraph: p, heading } = builders(tiptapEditor.schema));
|
||||
});
|
||||
|
||||
describe('when typing a valid heading input rule', () => {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import { builders } from 'prosemirror-test-builder';
|
||||
import HorizontalRule from '~/content_editor/extensions/horizontal_rule';
|
||||
import { createTestEditor, createDocBuilder, triggerNodeInputRule } from '../test_utils';
|
||||
import { createTestEditor, triggerNodeInputRule } from '../test_utils';
|
||||
|
||||
describe('content_editor/extensions/horizontal_rule', () => {
|
||||
let tiptapEditor;
|
||||
|
|
@ -10,14 +11,7 @@ describe('content_editor/extensions/horizontal_rule', () => {
|
|||
beforeEach(() => {
|
||||
tiptapEditor = createTestEditor({ extensions: [HorizontalRule] });
|
||||
|
||||
({
|
||||
builders: { doc, p, horizontalRule },
|
||||
} = createDocBuilder({
|
||||
tiptapEditor,
|
||||
names: {
|
||||
horizontalRule: { nodeType: HorizontalRule.name },
|
||||
},
|
||||
}));
|
||||
({ doc, paragraph: p, horizontalRule } = builders(tiptapEditor.schema));
|
||||
});
|
||||
|
||||
it.each`
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import { builders } from 'prosemirror-test-builder';
|
||||
import HTMLMarks from '~/content_editor/extensions/html_marks';
|
||||
import { createTestEditor, createDocBuilder } from '../test_utils';
|
||||
import { createTestEditor } from '../test_utils';
|
||||
|
||||
describe('content_editor/extensions/html_marks', () => {
|
||||
let tiptapEditor;
|
||||
|
|
@ -25,37 +26,24 @@ describe('content_editor/extensions/html_marks', () => {
|
|||
tiptapEditor = createTestEditor({ extensions: [...HTMLMarks] });
|
||||
|
||||
({
|
||||
builders: {
|
||||
doc,
|
||||
ins,
|
||||
abbr,
|
||||
bdo,
|
||||
cite,
|
||||
dfn,
|
||||
small,
|
||||
span,
|
||||
time,
|
||||
kbd,
|
||||
q,
|
||||
samp,
|
||||
var: varMark,
|
||||
ruby,
|
||||
rp,
|
||||
rt,
|
||||
p,
|
||||
},
|
||||
} = createDocBuilder({
|
||||
tiptapEditor,
|
||||
names: {
|
||||
...HTMLMarks.reduce(
|
||||
(builders, htmlMark) => ({
|
||||
...builders,
|
||||
[htmlMark.name]: { markType: htmlMark.name },
|
||||
}),
|
||||
{},
|
||||
),
|
||||
},
|
||||
}));
|
||||
doc,
|
||||
ins,
|
||||
abbr,
|
||||
bdo,
|
||||
cite,
|
||||
dfn,
|
||||
small,
|
||||
span,
|
||||
time,
|
||||
kbd,
|
||||
q,
|
||||
samp,
|
||||
var: varMark,
|
||||
ruby,
|
||||
rp,
|
||||
rt,
|
||||
paragraph: p,
|
||||
} = builders(tiptapEditor.schema));
|
||||
});
|
||||
|
||||
it.each`
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import { builders } from 'prosemirror-test-builder';
|
||||
import HTMLNodes from '~/content_editor/extensions/html_nodes';
|
||||
import { createTestEditor, createDocBuilder } from '../test_utils';
|
||||
import { createTestEditor } from '../test_utils';
|
||||
|
||||
describe('content_editor/extensions/html_nodes', () => {
|
||||
let tiptapEditor;
|
||||
|
|
@ -11,20 +12,7 @@ describe('content_editor/extensions/html_nodes', () => {
|
|||
beforeEach(() => {
|
||||
tiptapEditor = createTestEditor({ extensions: [...HTMLNodes] });
|
||||
|
||||
({
|
||||
builders: { doc, p, pre, div },
|
||||
} = createDocBuilder({
|
||||
tiptapEditor,
|
||||
names: {
|
||||
...HTMLNodes.reduce(
|
||||
(builders, htmlNode) => ({
|
||||
...builders,
|
||||
[htmlNode.name]: { nodeType: htmlNode.name },
|
||||
}),
|
||||
{},
|
||||
),
|
||||
},
|
||||
}));
|
||||
({ doc, paragraph: p, pre, div } = builders(tiptapEditor.schema));
|
||||
});
|
||||
|
||||
it.each`
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import { builders } from 'prosemirror-test-builder';
|
||||
import Image from '~/content_editor/extensions/image';
|
||||
import { createTestEditor, createDocBuilder } from '../test_utils';
|
||||
import { createTestEditor } from '../test_utils';
|
||||
|
||||
describe('content_editor/extensions/image', () => {
|
||||
let tiptapEditor;
|
||||
|
|
@ -10,14 +11,7 @@ describe('content_editor/extensions/image', () => {
|
|||
beforeEach(() => {
|
||||
tiptapEditor = createTestEditor({ extensions: [Image] });
|
||||
|
||||
({
|
||||
builders: { doc, p, image },
|
||||
} = createDocBuilder({
|
||||
tiptapEditor,
|
||||
names: {
|
||||
image: { nodeType: Image.name },
|
||||
},
|
||||
}));
|
||||
({ doc, paragraph: p, image } = builders(tiptapEditor.schema));
|
||||
});
|
||||
|
||||
it('sets the draggable option to true', () => {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import { builders } from 'prosemirror-test-builder';
|
||||
import InlineDiff from '~/content_editor/extensions/inline_diff';
|
||||
import { createTestEditor, createDocBuilder, triggerMarkInputRule } from '../test_utils';
|
||||
import { createTestEditor, triggerMarkInputRule } from '../test_utils';
|
||||
|
||||
describe('content_editor/extensions/inline_diff', () => {
|
||||
let tiptapEditor;
|
||||
|
|
@ -9,14 +10,7 @@ describe('content_editor/extensions/inline_diff', () => {
|
|||
|
||||
beforeEach(() => {
|
||||
tiptapEditor = createTestEditor({ extensions: [InlineDiff] });
|
||||
({
|
||||
builders: { doc, p, inlineDiff },
|
||||
} = createDocBuilder({
|
||||
tiptapEditor,
|
||||
names: {
|
||||
inlineDiff: { markType: InlineDiff.name },
|
||||
},
|
||||
}));
|
||||
({ doc, paragraph: p, inlineDiff } = builders(tiptapEditor.schema));
|
||||
});
|
||||
|
||||
it.each`
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import { builders } from 'prosemirror-test-builder';
|
||||
import Link from '~/content_editor/extensions/link';
|
||||
import { createTestEditor, createDocBuilder, triggerMarkInputRule } from '../test_utils';
|
||||
import { createTestEditor, triggerMarkInputRule } from '../test_utils';
|
||||
|
||||
describe('content_editor/extensions/link', () => {
|
||||
let tiptapEditor;
|
||||
|
|
@ -9,14 +10,7 @@ describe('content_editor/extensions/link', () => {
|
|||
|
||||
beforeEach(() => {
|
||||
tiptapEditor = createTestEditor({ extensions: [Link] });
|
||||
({
|
||||
builders: { doc, p, link },
|
||||
} = createDocBuilder({
|
||||
tiptapEditor,
|
||||
names: {
|
||||
link: { markType: Link.name },
|
||||
},
|
||||
}));
|
||||
({ doc, paragraph: p, link } = builders(tiptapEditor.schema));
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import { builders } from 'prosemirror-test-builder';
|
||||
import MathInline from '~/content_editor/extensions/math_inline';
|
||||
import { createTestEditor, createDocBuilder, triggerMarkInputRule } from '../test_utils';
|
||||
import { createTestEditor, triggerMarkInputRule } from '../test_utils';
|
||||
|
||||
describe('content_editor/extensions/math_inline', () => {
|
||||
let tiptapEditor;
|
||||
|
|
@ -10,14 +11,7 @@ describe('content_editor/extensions/math_inline', () => {
|
|||
beforeEach(() => {
|
||||
tiptapEditor = createTestEditor({ extensions: [MathInline] });
|
||||
|
||||
({
|
||||
builders: { doc, p, mathInline },
|
||||
} = createDocBuilder({
|
||||
tiptapEditor,
|
||||
names: {
|
||||
details: { markType: MathInline.name },
|
||||
},
|
||||
}));
|
||||
({ doc, paragraph: p, mathInline } = builders(tiptapEditor.schema));
|
||||
});
|
||||
|
||||
it.each`
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import { createTestEditor, createDocBuilder } from '../test_utils';
|
||||
import { builders } from 'prosemirror-test-builder';
|
||||
import { createTestEditor } from '../test_utils';
|
||||
|
||||
describe('content_editor/extensions/paragraph', () => {
|
||||
let tiptapEditor;
|
||||
|
|
@ -8,9 +9,7 @@ describe('content_editor/extensions/paragraph', () => {
|
|||
beforeEach(() => {
|
||||
tiptapEditor = createTestEditor();
|
||||
|
||||
({
|
||||
builders: { doc, p },
|
||||
} = createDocBuilder({ tiptapEditor }));
|
||||
({ doc, paragraph: p } = builders(tiptapEditor.schema));
|
||||
});
|
||||
|
||||
describe('Shift-Enter shortcut', () => {
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import { builders } from 'prosemirror-test-builder';
|
||||
import Reference from '~/content_editor/extensions/reference';
|
||||
import ReferenceLabel from '~/content_editor/extensions/reference_label';
|
||||
import AssetResolver from '~/content_editor/services/asset_resolver';
|
||||
|
|
@ -11,12 +12,7 @@ import {
|
|||
RESOLVED_USER_HTML,
|
||||
RESOLVED_VULNERABILITY_HTML,
|
||||
} from '../test_constants';
|
||||
import {
|
||||
createTestEditor,
|
||||
createDocBuilder,
|
||||
triggerNodeInputRule,
|
||||
waitUntilTransaction,
|
||||
} from '../test_utils';
|
||||
import { createTestEditor, triggerNodeInputRule, waitUntilTransaction } from '../test_utils';
|
||||
|
||||
describe('content_editor/extensions/reference', () => {
|
||||
let tiptapEditor;
|
||||
|
|
@ -35,15 +31,7 @@ describe('content_editor/extensions/reference', () => {
|
|||
extensions: [Reference.configure({ assetResolver }), ReferenceLabel],
|
||||
});
|
||||
|
||||
({
|
||||
builders: { doc, p, reference, referenceLabel },
|
||||
} = createDocBuilder({
|
||||
tiptapEditor,
|
||||
names: {
|
||||
reference: { nodeType: Reference.name },
|
||||
referenceLabel: { nodeType: ReferenceLabel.name },
|
||||
},
|
||||
}));
|
||||
({ doc, paragraph: p, reference, referenceLabel } = builders(tiptapEditor.schema));
|
||||
});
|
||||
|
||||
describe('when typing a valid reference input rule', () => {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import { builders } from 'prosemirror-test-builder';
|
||||
import TableOfContents from '~/content_editor/extensions/table_of_contents';
|
||||
import { createTestEditor, createDocBuilder, triggerNodeInputRule } from '../test_utils';
|
||||
import { createTestEditor, triggerNodeInputRule } from '../test_utils';
|
||||
|
||||
describe('content_editor/extensions/table_of_contents', () => {
|
||||
let tiptapEditor;
|
||||
|
|
@ -9,12 +10,7 @@ describe('content_editor/extensions/table_of_contents', () => {
|
|||
|
||||
beforeEach(() => {
|
||||
tiptapEditor = createTestEditor({ extensions: [TableOfContents] });
|
||||
({
|
||||
builders: { doc, p, tableOfContents },
|
||||
} = createDocBuilder({
|
||||
tiptapEditor,
|
||||
names: { tableOfContents: { nodeType: TableOfContents.name } },
|
||||
}));
|
||||
({ doc, paragraph: p, tableOfContents } = builders(tiptapEditor.schema));
|
||||
});
|
||||
|
||||
it.each`
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import { builders } from 'prosemirror-test-builder';
|
||||
import Bold from '~/content_editor/extensions/bold';
|
||||
import BulletList from '~/content_editor/extensions/bullet_list';
|
||||
import ListItem from '~/content_editor/extensions/list_item';
|
||||
|
|
@ -5,7 +6,7 @@ import Table from '~/content_editor/extensions/table';
|
|||
import TableCell from '~/content_editor/extensions/table_cell';
|
||||
import TableRow from '~/content_editor/extensions/table_row';
|
||||
import TableHeader from '~/content_editor/extensions/table_header';
|
||||
import { createTestEditor, createDocBuilder } from '../test_utils';
|
||||
import { createTestEditor } from '../test_utils';
|
||||
|
||||
describe('content_editor/extensions/table', () => {
|
||||
let tiptapEditor;
|
||||
|
|
@ -24,19 +25,13 @@ describe('content_editor/extensions/table', () => {
|
|||
});
|
||||
|
||||
({
|
||||
builders: { doc, p, table, tableCell, tableHeader, tableRow },
|
||||
} = createDocBuilder({
|
||||
tiptapEditor,
|
||||
names: {
|
||||
bold: { markType: Bold.name },
|
||||
table: { nodeType: Table.name },
|
||||
tableHeader: { nodeType: TableHeader.name },
|
||||
tableCell: { nodeType: TableCell.name },
|
||||
tableRow: { nodeType: TableRow.name },
|
||||
bulletList: { nodeType: BulletList.name },
|
||||
listItem: { nodeType: ListItem.name },
|
||||
},
|
||||
}));
|
||||
doc,
|
||||
paragraph: p,
|
||||
table,
|
||||
tableCell,
|
||||
tableHeader,
|
||||
tableRow,
|
||||
} = builders(tiptapEditor.schema));
|
||||
|
||||
initialDoc = doc(
|
||||
table(
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import { builders } from 'prosemirror-test-builder';
|
||||
import TaskList from '~/content_editor/extensions/task_list';
|
||||
import TaskItem from '~/content_editor/extensions/task_item';
|
||||
import { createTestEditor, createDocBuilder } from '../test_utils';
|
||||
import { createTestEditor } from '../test_utils';
|
||||
|
||||
describe('content_editor/extensions/task_item', () => {
|
||||
let tiptapEditor;
|
||||
|
|
@ -12,15 +13,7 @@ describe('content_editor/extensions/task_item', () => {
|
|||
beforeEach(() => {
|
||||
tiptapEditor = createTestEditor({ extensions: [TaskList, TaskItem] });
|
||||
|
||||
({
|
||||
builders: { doc, p, taskList, taskItem },
|
||||
} = createDocBuilder({
|
||||
tiptapEditor,
|
||||
names: {
|
||||
taskItem: { nodeType: TaskItem.name },
|
||||
taskList: { nodeType: TaskList.name },
|
||||
},
|
||||
}));
|
||||
({ doc, paragraph: p, taskList, taskItem } = builders(tiptapEditor.schema));
|
||||
});
|
||||
|
||||
it('sets the draggable option to true', () => {
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue