Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2022-10-18 15:10:37 +00:00
parent a300f4d5c7
commit b556d0fab7
52 changed files with 9953 additions and 388 deletions

View File

@ -1,12 +1,9 @@
---
# Cop supports --auto-correct.
Rails/ActiveRecordCallbacksOrder:
# Offense count: 30
# Temporarily disabled due to too many offenses
Enabled: false
Details: grace period
Exclude:
- 'app/models/award_emoji.rb'
- 'app/models/ci/job_artifact.rb'
- 'app/models/gpg_key.rb'
- 'app/models/group.rb'
- 'app/models/issue.rb'

View File

@ -1,8 +1,6 @@
---
Rails/InverseOf:
# Offense count: 210
# Temporarily disabled due to too many offenses
Enabled: false
Details: grace period
Exclude:
- 'app/models/alert_management/alert.rb'
- 'app/models/alert_management/alert_assignee.rb'
@ -12,7 +10,6 @@ Rails/InverseOf:
- 'app/models/board.rb'
- 'app/models/bulk_imports/entity.rb'
- 'app/models/bulk_imports/tracker.rb'
- 'app/models/chat_name.rb'
- 'app/models/ci/bridge.rb'
- 'app/models/ci/build.rb'
- 'app/models/ci/build_pending_state.rb'
@ -25,7 +22,6 @@ Rails/InverseOf:
- 'app/models/ci/runner.rb'
- 'app/models/ci/runner_namespace.rb'
- 'app/models/ci/sources/pipeline.rb'
- 'app/models/ci/stage.rb'
- 'app/models/ci/trigger_request.rb'
- 'app/models/ci/unit_test_failure.rb'
- 'app/models/clusters/applications/runner.rb'
@ -38,7 +34,6 @@ Rails/InverseOf:
- 'app/models/concerns/analytics/cycle_analytics/stage.rb'
- 'app/models/concerns/awardable.rb'
- 'app/models/concerns/commit_signature.rb'
- 'app/models/concerns/merge_request_reviewer_state.rb'
- 'app/models/concerns/with_uploads.rb'
- 'app/models/custom_emoji.rb'
- 'app/models/customer_relations/contact.rb'
@ -51,7 +46,7 @@ Rails/InverseOf:
- 'app/models/group.rb'
- 'app/models/group/crm_settings.rb'
- 'app/models/group_group_link.rb'
- 'app/models/hooks/service_hook.rb'
- 'app/models/group_label.rb'
- 'app/models/incident_management/timeline_event.rb'
- 'app/models/integrations/base_slash_commands.rb'
- 'app/models/issue.rb'
@ -66,11 +61,15 @@ Rails/InverseOf:
- 'app/models/packages/composer/cache_file.rb'
- 'app/models/packages/maven/metadatum.rb'
- 'app/models/project.rb'
- 'app/models/project_label.rb'
- 'app/models/resource_state_event.rb'
- 'app/models/serverless/domain_cluster.rb'
- 'app/models/terraform/state_version.rb'
- 'app/models/time_tracking/timelog_category.rb'
- 'app/models/todo.rb'
- 'app/models/user.rb'
- 'app/models/users/phone_number_validation.rb'
- 'app/models/work_item.rb'
- 'app/models/x509_certificate.rb'
- 'ee/app/models/allowed_email_domain.rb'
- 'ee/app/models/analytics/cycle_analytics/group_stage.rb'
@ -78,12 +77,14 @@ Rails/InverseOf:
- 'ee/app/models/analytics/devops_adoption/enabled_namespace.rb'
- 'ee/app/models/analytics/devops_adoption/snapshot.rb'
- 'ee/app/models/audit_events/external_audit_event_destination.rb'
- 'ee/app/models/audit_events/streaming/header.rb'
- 'ee/app/models/ci/sources/project.rb'
- 'ee/app/models/compliance_management/compliance_framework/project_settings.rb'
- 'ee/app/models/concerns/incident_management/base_pending_escalation.rb'
- 'ee/app/models/dast/profile_schedule.rb'
- 'ee/app/models/ee/ci/build.rb'
- 'ee/app/models/ee/ci/pipeline.rb'
- 'ee/app/models/ee/clusters/agent.rb'
- 'ee/app/models/ee/epic.rb'
- 'ee/app/models/ee/group.rb'
- 'ee/app/models/ee/iteration.rb'
@ -105,9 +106,9 @@ Rails/InverseOf:
- 'ee/app/models/integrations/gitlab_slack_application.rb'
- 'ee/app/models/requirements_management/requirement.rb'
- 'ee/app/models/requirements_management/test_report.rb'
- 'ee/app/models/sbom/vulnerable_component_version.rb'
- 'ee/app/models/security/orchestration_policy_configuration.rb'
- 'ee/app/models/security/orchestration_policy_rule_schedule.rb'
- 'ee/app/models/slack_integration.rb'
- 'ee/app/models/software_license_policy.rb'
- 'ee/app/models/user_permission_export_upload.rb'
- 'ee/app/models/vulnerabilities/feedback.rb'

View File

@ -1,10 +1,9 @@
---
# Cop supports --auto-correct.
Style/KeywordParametersOrder:
# Offense count: 110
# Temporarily disabled due to too many offenses
Enabled: false
Details: grace period
Exclude:
- 'app/controllers/concerns/product_analytics_tracking.rb'
- 'app/finders/group_descendants_finder.rb'
- 'app/finders/merge_request_target_project_finder.rb'
- 'app/graphql/resolvers/package_pipelines_resolver.rb'
@ -30,20 +29,23 @@ Style/KeywordParametersOrder:
- 'ee/app/services/analytics/devops_adoption/enabled_namespaces/create_service.rb'
- 'ee/app/services/analytics/devops_adoption/enabled_namespaces/find_or_create_service.rb'
- 'ee/app/services/audit_events/user_impersonation_group_audit_event_service.rb'
- 'ee/app/services/members/activate_service.rb'
- 'ee/lib/gitlab/elastic/helper.rb'
- 'ee/lib/gitlab/insights/executors/dora_executor.rb'
- 'ee/lib/gitlab/insights/executors/issuable_executor.rb'
- 'ee/spec/lib/ee/gitlab/background_migration/drop_invalid_remediations_spec.rb'
- 'ee/spec/requests/api/deployments_spec.rb'
- 'lib/gitlab/background_migration/batched_migration_job.rb'
- 'lib/gitlab/checks/timed_logger.rb'
- 'lib/gitlab/ci/reports/security/finding.rb'
- 'lib/gitlab/cleanup/personal_access_tokens.rb'
- 'lib/gitlab/database/partitioning/monthly_strategy.rb'
- 'lib/gitlab/database/with_lock_retries.rb'
- 'lib/gitlab/diff/diff_refs.rb'
- 'lib/gitlab/email/smime/signer.rb'
- 'lib/gitlab/error_tracking.rb'
- 'lib/gitlab/exclusive_lease.rb'
- 'lib/gitlab/import_export/import_failure_service.rb'
- 'lib/gitlab/merge_requests/mergeability/results_store.rb'
- 'lib/gitlab/usage_data_counters/editor_unique_counter.rb'
- 'lib/microsoft_teams/notifier.rb'
- 'qa/qa/specs/features/ee/browser_ui/3_create/repository/file_locking_spec.rb'
- 'qa/qa/specs/features/ee/browser_ui/3_create/repository/push_rules_spec.rb'
@ -64,9 +66,12 @@ Style/KeywordParametersOrder:
- 'spec/migrations/20220107064845_populate_vulnerability_reads_spec.rb'
- 'spec/migrations/confirm_support_bot_user_spec.rb'
- 'spec/services/service_ping/submit_service_ping_service_spec.rb'
- 'spec/support/helpers/doc_url_helper.rb'
- 'spec/support/helpers/smime_helper.rb'
- 'spec/support/helpers/workhorse_helpers.rb'
- 'spec/support/shared_examples/projects/container_repository/cleanup_tags_service_shared_examples.rb'
- 'spec/support/shared_examples/services/container_expiration_policy_shared_examples.rb'
- 'spec/support/shared_examples/services/dependency_proxy_ttl_policies_shared_examples.rb'
- 'spec/support/shared_examples/services/namespace_package_settings_shared_examples.rb'
- 'spec/tasks/gitlab/usage_data_rake_spec.rb'
- 'spec/workers/container_expiration_policies/cleanup_container_repository_worker_spec.rb'

View File

@ -43,7 +43,7 @@ gem 'rugged', '~> 1.2'
gem 'grape-path-helpers', '~> 1.7.1'
gem 'faraday', '~> 1.0'
gem 'marginalia', '~> 1.10.0'
gem 'marginalia', '~> 1.11.1'
# Authorization
gem 'declarative_policy', '~> 1.1.0'
@ -478,7 +478,6 @@ gem 'gitlab-mail_room', '~> 0.0.9', require: 'mail_room'
gem 'email_reply_trimmer', '~> 0.1'
gem 'html2text'
gem 'ruby-prof', '~> 1.3.0'
gem 'stackprof', '~> 0.2.21', require: false
gem 'rbtrace', '~> 0.4', require: false
gem 'memory_profiler', '~> 0.9', require: false

View File

@ -319,7 +319,7 @@
{"name":"lumberjack","version":"1.2.7","platform":"ruby","checksum":"a5c6aae6b4234f1420dbcd80b23e3bca0817bd239440dde097ebe3fa63c63b1f"},
{"name":"mail","version":"2.7.1","platform":"ruby","checksum":"ec2a3d489f7510b90d8eaa3f6abaad7038cf1d663cdf8ee66d0214a0bdf99c03"},
{"name":"marcel","version":"1.0.2","platform":"ruby","checksum":"a013b677ef46cbcb49fd5c59b3d35803d2ee04dd75d8bfdc43533fc5a31f7e4e"},
{"name":"marginalia","version":"1.10.0","platform":"ruby","checksum":"68289091ee493e1a8f22369c245f250652a6538e497fdeef68cb2a2490830380"},
{"name":"marginalia","version":"1.11.1","platform":"ruby","checksum":"cb63212ab63e42746e27595e912cb20408a1a28bcd0edde55d15b7c45fa289cf"},
{"name":"memoist","version":"0.16.2","platform":"ruby","checksum":"a52c53a3f25b5875151670b2f3fd44388633486dc0f09f9a7150ead1e3bf3c45"},
{"name":"memory_profiler","version":"0.9.14","platform":"ruby","checksum":"de558cf6525d8d56d2c0ea465b1664517fbe45560f892dc7a898d3b8c2863b12"},
{"name":"method_source","version":"1.0.0","platform":"ruby","checksum":"d779455a2b5666a079ce58577bfad8534f571af7cec8107f4dce328f0981dede"},
@ -484,14 +484,14 @@
{"name":"rqrcode-rails3","version":"0.1.7","platform":"ruby","checksum":"6f0582f26485123e5ed6f2a8a2871f00d86d353e0f58c8429a5a13212bcf48c4"},
{"name":"rspec","version":"3.10.0","platform":"ruby","checksum":"b870b43d49ae4a4e063b94976d2742b0854ec10458c425d569b5556ee5898ab7"},
{"name":"rspec-benchmark","version":"0.6.0","platform":"ruby","checksum":"1014adb57ec2599a2455c63884229f367a2fff6a63a77fd68ce5d804c83dd6cf"},
{"name":"rspec-core","version":"3.10.1","platform":"ruby","checksum":"ac9abdc9577a3a34e9e92815603da8343931055ab4fba1c2a49de6dd3b749673"},
{"name":"rspec-core","version":"3.10.2","platform":"ruby","checksum":"005659ce9dd356dd5d2acb4bcdcc5915291f4a312447b500af3b75aab564951b"},
{"name":"rspec-expectations","version":"3.10.1","platform":"ruby","checksum":"27acf5d5df13f8cc8f7158001ebf572513bcec3d45404ba76e0a8998895ce9eb"},
{"name":"rspec-mocks","version":"3.10.3","platform":"ruby","checksum":"d2f6f3d8b7569b1e846703d164cb23e24c7f530d38217fc06da2beaf6024260a"},
{"name":"rspec-parameterized","version":"0.5.0","platform":"ruby","checksum":"f163ac07b5edd1eeb13136480623db7020852c70cf0ad2fa98e31384ae162454"},
{"name":"rspec-rails","version":"5.0.1","platform":"ruby","checksum":"c61e7f35db2266f83b3cc58a340fc3ec0bd6344818040430fd5ddc99775242de"},
{"name":"rspec-retry","version":"0.6.1","platform":"ruby","checksum":"86b7e8513c5b0c713c2e28854f4d996deb8efa6304eef50f0ad68ee6c563d8da"},
{"name":"rspec-support","version":"3.10.2","platform":"ruby","checksum":"74315f89069fbaf2a710e2117340373b77ee45eceb026de87e0cad9dd5154596"},
{"name":"rspec_junit_formatter","version":"0.4.1","platform":"ruby","checksum":"3788f9b3fabc6284b93493cf4b3a80cba2b59b3a774b95f39dd7886d5faed6ab"},
{"name":"rspec-support","version":"3.10.3","platform":"ruby","checksum":"65c88f8cbe579461f411097682e6402960eae327eef08e86ef581b8c609e4c5e"},
{"name":"rspec_junit_formatter","version":"0.6.0","platform":"ruby","checksum":"40dde674e6ae4e6cc0ff560da25497677e34fefd2338cc467a8972f602b62b15"},
{"name":"rspec_profiling","version":"0.0.6","platform":"ruby","checksum":"7a45697f79dcec9a174a0e26703465f6bd52ee78e8d798741240bfcef38f6e6e"},
{"name":"rubocop","version":"1.36.0","platform":"ruby","checksum":"368e47dcab8417419949bbadb11ec41fd94e6b785f8bff4f9cc56a1ddf60ffac"},
{"name":"rubocop-ast","version":"1.21.0","platform":"ruby","checksum":"8f5d98611343498602de2d41bc583aca71599daad16daeadaeeee60f134c9568"},
@ -502,8 +502,6 @@
{"name":"rubocop-rspec","version":"2.12.1","platform":"ruby","checksum":"9278d22d4525261caf30d591eef3d47910a125e74f75f41ffa470acd208423f9"},
{"name":"ruby-fogbugz","version":"0.2.1","platform":"ruby","checksum":"15b2e7fe7e95b021a94ee6e9d8bb32fdad6ae44e820c2ce0dc312fe6e77d40ca"},
{"name":"ruby-magic","version":"0.5.4","platform":"ruby","checksum":"2c17b185130d10a83791f63a40baa358c4b138af37da3f4dab53690121c421d5"},
{"name":"ruby-prof","version":"1.3.1","platform":"ruby","checksum":"e735d20c92954e1fa2a4475539c99dfc8d0166b4cc6915ca309e8ee2dd19323c"},
{"name":"ruby-prof","version":"1.3.1","platform":"x64-mingw32","checksum":"a97bb6ff0abb01131ecba88799222d492d9124e057535db8e5bd47119f2a58ba"},
{"name":"ruby-progressbar","version":"1.11.0","platform":"ruby","checksum":"cc127db3866dc414ffccbf92928a241e585b3aa2b758a5563e74a6ee0f57d50a"},
{"name":"ruby-saml","version":"1.13.0","platform":"ruby","checksum":"d31cbdf5fb8fdd6aa3187e48dba3085cfeb751af30276a5739aa3659a66f069c"},
{"name":"ruby-statistics","version":"3.0.0","platform":"ruby","checksum":"610301370346931cb701e3a8d3d3e28eb65681162cae6066c0c11abf20efdc81"},

View File

@ -854,9 +854,9 @@ GEM
mail (2.7.1)
mini_mime (>= 0.1.1)
marcel (1.0.2)
marginalia (1.10.0)
actionpack (>= 2.3)
activerecord (>= 2.3)
marginalia (1.11.1)
actionpack (>= 5.2)
activerecord (>= 5.2)
memoist (0.16.2)
memory_profiler (0.9.14)
method_source (1.0.0)
@ -1190,7 +1190,7 @@ GEM
benchmark-perf (~> 0.6)
benchmark-trend (~> 0.4)
rspec (>= 3.0)
rspec-core (3.10.1)
rspec-core (3.10.2)
rspec-support (~> 3.10.0)
rspec-expectations (3.10.1)
diff-lcs (>= 1.2.0, < 2.0)
@ -1214,8 +1214,8 @@ GEM
rspec-support (~> 3.10)
rspec-retry (0.6.1)
rspec-core (> 3.3)
rspec-support (3.10.2)
rspec_junit_formatter (0.4.1)
rspec-support (3.10.3)
rspec_junit_formatter (0.6.0)
rspec-core (>= 2, < 4, != 2.12.0)
rspec_profiling (0.0.6)
activerecord
@ -1251,7 +1251,6 @@ GEM
crack (~> 0.4)
ruby-magic (0.5.4)
mini_portile2 (~> 2.6)
ruby-prof (1.3.1)
ruby-progressbar (1.11.0)
ruby-saml (1.13.0)
nokogiri (>= 1.10.5)
@ -1692,7 +1691,7 @@ DEPENDENCIES
lru_redux
mail (= 2.7.1)
mail-smtp_pool (~> 0.1.0)!
marginalia (~> 1.10.0)
marginalia (~> 1.11.1)
memory_profiler (~> 0.9)
microsoft_graph_mailer (~> 0.1.0)!
mini_magick (~> 4.10.1)
@ -1772,7 +1771,6 @@ DEPENDENCIES
rubocop
ruby-fogbugz (~> 0.2.1)
ruby-magic (~> 0.5)
ruby-prof (~> 1.3.0)
ruby-progressbar (~> 1.10)
ruby-saml (~> 1.13.0)
ruby_parser (~> 3.15)

View File

@ -0,0 +1 @@
@import 'gridstack/dist/gridstack';

View File

@ -13,7 +13,7 @@ module Boards
scope :ordered, -> { order(:list_type, :position) }
scope :destroyable, -> { where(list_type: list_types.slice(*destroyable_types).values) }
scope :movable, -> { where(list_type: list_types.slice(*movable_types).values) }
scope :without_types, ->(list_types) { where.not(list_type: list_types) }
scope :with_types, ->(list_types) { where(list_type: list_types) }
class << self
def preload_preferences_for_user(lists, user)

View File

@ -9,23 +9,27 @@ module Boards
end
lists = board.lists.preload_associated_models
lists = lists.with_types(available_list_types_for(board))
return lists.id_in(params[:list_id]) if params[:list_id].present?
list_types = unavailable_list_types_for(board)
lists.without_types(list_types)
lists
end
private
def unavailable_list_types_for(board)
hidden_lists_for(board)
def available_list_types_for(board)
licensed_list_types(board) + visible_lists(board)
end
def hidden_lists_for(board)
[].tap do |hidden|
hidden << ::List.list_types[:backlog] if board.hide_backlog_list?
hidden << ::List.list_types[:closed] if board.hide_closed_list?
def licensed_list_types(board)
[List.list_types[:label]]
end
def visible_lists(board)
[].tap do |visible|
visible << ::List.list_types[:backlog] unless board.hide_backlog_list?
visible << ::List.list_types[:closed] unless board.hide_closed_list?
end
end
end

View File

@ -42,7 +42,7 @@
%tbody
%tr{ style: 'width:100%;' }
%td{ style: "#{default_style}text-align:center;" }
- password_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: 'https://docs.gitlab.com/ee/user/profile/#changing-your-password' }
- password_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: 'https://docs.gitlab.com/ee/user/profile/user_passwords.html#change-your-password' }
= _('If you recently tried to sign in, but mistakenly entered a wrong two-factor authentication code, you may ignore this email.')
- if password_authentication_enabled_for_web?

View File

@ -3,5 +3,5 @@
= _('We detected an attempt to sign in to your %{host} account using a wrong two-factor authentication code, from the following IP address: %{ip}, at %{time}') % { host: Gitlab.config.gitlab.host, ip: @ip, time: @time }
= _('If you recently tried to sign in, but mistakenly entered a wrong two-factor authentication code, you may ignore this email.')
= _('If you did not recently try to sign in, you should immediately change your password: %{password_link}.') % { password_link: 'https://docs.gitlab.com/ee/user/profile/#changing-your-password' }
= _('If you did not recently try to sign in, you should immediately change your password: %{password_link}.') % { password_link: 'https://docs.gitlab.com/ee/user/profile/user_passwords.html#change-your-password' }
= _('Make sure you choose a strong, unique password.')

View File

@ -42,7 +42,7 @@
%tbody
%tr{ style: 'width:100%;' }
%td{ style: "#{default_style}text-align:center;" }
- password_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: 'https://docs.gitlab.com/ee/user/profile/#changing-your-password' }
- password_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: 'https://docs.gitlab.com/ee/user/profile/user_passwords.html#change-your-password' }
= _('If you recently signed in and recognize the IP address, you may disregard this email.')
- if password_authentication_enabled_for_web?

View File

@ -3,7 +3,7 @@
= _('A sign-in to your account has been made from the following IP address: %{ip}') % { ip: @ip }
= _('If you recently signed in and recognize the IP address, you may disregard this email.')
= _('If you did not recently sign in, you should immediately change your password: %{password_link}.') % { password_link: 'https://docs.gitlab.com/ee/user/profile/#changing-your-password' }
= _('If you did not recently sign in, you should immediately change your password: %{password_link}.') % { password_link: 'https://docs.gitlab.com/ee/user/profile/user_passwords.html#change-your-password' }
= _('Passwords should be unique and not used for any other sites or services.')
- unless @user.two_factor_enabled?

View File

@ -324,6 +324,7 @@ module Gitlab
config.assets.precompile << "page_bundles/xterm.css"
config.assets.precompile << "lazy_bundles/cropper.css"
config.assets.precompile << "lazy_bundles/select2.css"
config.assets.precompile << "lazy_bundles/gridstack.css"
config.assets.precompile << "performance_bar.css"
config.assets.precompile << "disable_animations.css"
config.assets.precompile << "test_environment.css"

View File

@ -199,7 +199,8 @@ successfully, you must replicate their data using some other means.
|[CI job artifacts](../../../ci/pipelines/job_artifacts.md) | **Yes** (10.4) | **Yes** (14.10) | [**Yes** (15.1)](https://gitlab.com/groups/gitlab-org/-/epics/5551) | [No](object_storage.md#verification-of-files-in-object-storage) | Verification is behind the feature flag `geo_job_artifact_replication`, enabled by default in 14.10. |
|[CI Pipeline Artifacts](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/models/ci/pipeline_artifact.rb) | [**Yes** (13.11)](https://gitlab.com/gitlab-org/gitlab/-/issues/238464) | [**Yes** (13.11)](https://gitlab.com/gitlab-org/gitlab/-/issues/238464) | [**Yes** (15.1)](https://gitlab.com/groups/gitlab-org/-/epics/5551) | [No](object_storage.md#verification-of-files-in-object-storage) | Persists additional artifacts after a pipeline completes. |
|[CI Secure Files](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/models/ci/secure_file.rb) | [**Yes** (15.3)](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/91430) | [**Yes** (15.3)](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/91430) | [**Yes** (15.3)](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/91430) | [No](object_storage.md#verification-of-files-in-object-storage) | Verification is behind the feature flag `geo_ci_secure_file_replication`, enabled by default in 15.3. |
|[Container Registry](../../packages/container_registry.md) | **Yes** (12.3) | No | No | No | Disabled by default. See [instructions](container_registry.md) to enable. |
|[Container Registry](../../packages/container_registry.md) | **Yes** (12.3)* | No | No | No | Replication is behind feature flag `geo_container_repository_replication`, enabled by default.
Requires additional configuration. See [instructions](container_registry.md) to set up the Container Registry replication. |
|[Infrastructure Registry](../../../user/packages/infrastructure_registry/index.md) | **Yes** (14.0) | **Yes** (14.0) | [**Yes** (15.1)](https://gitlab.com/groups/gitlab-org/-/epics/5551) | [No](object_storage.md#verification-of-files-in-object-storage) | Behind feature flag `geo_package_file_replication`, enabled by default. |
|[Project designs repository](../../../user/project/issues/design_management.md) | **Yes** (12.7) | [No](https://gitlab.com/gitlab-org/gitlab/-/issues/32467) | N/A | N/A | Designs also require replication of LFS objects and Uploads. |
|[Package Registry](../../../user/packages/package_registry/index.md) | **Yes** (13.2) | **Yes** (13.10) | [**Yes** (15.1)](https://gitlab.com/groups/gitlab-org/-/epics/5551) | [No](object_storage.md#verification-of-files-in-object-storage) | Behind feature flag `geo_package_file_replication`, enabled by default. |
@ -214,3 +215,5 @@ successfully, you must replicate their data using some other means.
|[Elasticsearch integration](../../../integration/advanced_search/elasticsearch.md) | [Not planned](https://gitlab.com/gitlab-org/gitlab/-/issues/1186) | No | No | No | Not planned because further product discovery is required and Elasticsearch (ES) clusters can be rebuilt. Secondaries use the same ES cluster as the primary. |
|[Dependency proxy images](../../../user/packages/dependency_proxy/index.md) | [Planned](https://gitlab.com/groups/gitlab-org/-/epics/8833) | No | No | No | Blocked by [Geo: Secondary Mimicry](https://gitlab.com/groups/gitlab-org/-/epics/1528). Replication of this cache is not needed for disaster recovery purposes because it can be recreated from external sources. |
|[Vulnerability Export](../../../user/application_security/vulnerability_report/index.md#export-vulnerability-details) | [Not planned](https://gitlab.com/groups/gitlab-org/-/epics/3111) | No | No | No | Not planned because they are ephemeral and sensitive information. They can be regenerated on demand. |
\* Migrated to [self-service framework](../../../development/geo/framework.md) in 15.5. See GitLab issue [#337436](https://gitlab.com/gitlab-org/gitlab/-/issues/337436) for more details.

View File

@ -1696,7 +1696,9 @@ To configure Praefect with TLS:
Sidekiq requires connection to the [Redis](#configure-redis),
[PostgreSQL](#configure-postgresql) and [Gitaly](#configure-gitaly) instances.
[Object storage](#configure-the-object-storage) is also required to be configured.
Since it's recommended to use [Object storage](#configure-the-object-storage)
over [NFS](#configure-nfs-optional) for data objects, the following examples
include the Object storage configuration.
- `10.6.0.101`: Sidekiq 1
- `10.6.0.102`: Sidekiq 2
@ -1864,7 +1866,9 @@ run [multiple Sidekiq processes](../operations/extra_sidekiq_processes.md).
## Configure GitLab Rails
This section describes how to configure the GitLab application (Rails) component.
[Object storage](#configure-the-object-storage) is also required to be configured.
Since it's recommended to use [Object storage](#configure-the-object-storage)
over [NFS](#configure-nfs-optional) for data objects, the following examples
include the Object storage configuration.
The following IPs will be used as an example:
@ -2015,48 +2019,7 @@ On each node perform the following:
1. [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
1. If you're not using NFS, [enable incremental logging](#enable-incremental-logging).
1. If you're [using NFS](#configure-nfs-optional):
1. If necessary, install the NFS client utility packages using the following
commands:
```shell
# Ubuntu/Debian
apt-get install nfs-common
# CentOS/Red Hat
yum install nfs-utils nfs-utils-lib
```
1. Specify the necessary NFS mounts in `/etc/fstab`.
The exact contents of `/etc/fstab` will depend on how you chose
to configure your NFS server. See the [NFS documentation](../nfs.md)
for examples and the various options.
1. Create the shared directories. These may be different depending on your NFS
mount locations.
```shell
mkdir -p /var/opt/gitlab/.ssh /var/opt/gitlab/gitlab-rails/uploads /var/opt/gitlab/gitlab-rails/shared /var/opt/gitlab/gitlab-ci/builds /var/opt/gitlab/git-data
```
1. Edit `/etc/gitlab/gitlab.rb` and use the following configuration:
```ruby
## Prevent GitLab from starting if NFS data mounts are not available
high_availability['mountpoint'] = '/var/opt/gitlab/git-data'
## Ensure UIDs and GIDs match between servers for permissions via NFS
user['uid'] = 9000
user['gid'] = 9000
web_server['uid'] = 9001
web_server['gid'] = 9001
registry['uid'] = 9002
registry['gid'] = 9002
```
1. Save the file and [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure).
1. [Enable incremental logging](#enable-incremental-logging), unless you are using [NFS](#configure-nfs-optional).
1. Confirm the node can connect to Gitaly:

View File

@ -1699,7 +1699,9 @@ To configure Praefect with TLS:
Sidekiq requires connection to the [Redis](#configure-redis),
[PostgreSQL](#configure-postgresql) and [Gitaly](#configure-gitaly) instances.
[Object storage](#configure-the-object-storage) is also required to be configured.
Since it's recommended to use [Object storage](#configure-the-object-storage)
over [NFS](#configure-nfs-optional) for data objects, the following examples
include the Object storage configuration.
- `10.6.0.101`: Sidekiq 1
- `10.6.0.102`: Sidekiq 2
@ -1867,7 +1869,9 @@ run [multiple Sidekiq processes](../operations/extra_sidekiq_processes.md).
## Configure GitLab Rails
This section describes how to configure the GitLab application (Rails) component.
[Object storage](#configure-the-object-storage) is also required to be configured.
Since it's recommended to use [Object storage](#configure-the-object-storage)
over [NFS](#configure-nfs-optional) for data objects, the following examples
include the Object storage configuration.
The following IPs will be used as an example:
@ -2020,48 +2024,8 @@ On each node perform the following:
1. [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
1. If you're not using NFS, [enable incremental logging](#enable-incremental-logging).
1. [Enable incremental logging](#enable-incremental-logging), unless you are using [NFS](#configure-nfs-optional).
1. If you're [using NFS](#configure-nfs-optional):
1. If necessary, install the NFS client utility packages using the following
commands:
```shell
# Ubuntu/Debian
apt-get install nfs-common
# CentOS/Red Hat
yum install nfs-utils nfs-utils-lib
```
1. Specify the necessary NFS mounts in `/etc/fstab`.
The exact contents of `/etc/fstab` will depend on how you chose
to configure your NFS server. See the [NFS documentation](../nfs.md)
for examples and the various options.
1. Create the shared directories. These may be different depending on your NFS
mount locations.
```shell
mkdir -p /var/opt/gitlab/.ssh /var/opt/gitlab/gitlab-rails/uploads /var/opt/gitlab/gitlab-rails/shared /var/opt/gitlab/gitlab-ci/builds /var/opt/gitlab/git-data
```
1. Edit `/etc/gitlab/gitlab.rb` and use the following configuration:
```ruby
## Prevent GitLab from starting if NFS data mounts are not available
high_availability['mountpoint'] = '/var/opt/gitlab/git-data'
## Ensure UIDs and GIDs match between servers for permissions via NFS
user['uid'] = 9000
user['gid'] = 9000
web_server['uid'] = 9001
web_server['gid'] = 9001
registry['uid'] = 9002
registry['gid'] = 9002
```
1. Save the file and [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure).
1. Confirm the node can connect to Gitaly:
```shell

View File

@ -592,31 +592,6 @@ but this is dependent on workload.
On each node perform the following:
1. If you're [using NFS](#configure-nfs-optional):
1. If necessary, install the NFS client utility packages using the following
commands:
```shell
# Ubuntu/Debian
apt-get install nfs-common
# CentOS/Red Hat
yum install nfs-utils nfs-utils-lib
```
1. Specify the necessary NFS mounts in `/etc/fstab`.
The exact contents of `/etc/fstab` will depend on how you chose
to configure your NFS server. See the [NFS documentation](../nfs.md)
for examples and the various options.
1. Create the shared directories. These may be different depending on your NFS
mount locations.
```shell
mkdir -p /var/opt/gitlab/.ssh /var/opt/gitlab/gitlab-rails/uploads /var/opt/gitlab/gitlab-rails/shared /var/opt/gitlab/gitlab-ci/builds /var/opt/gitlab/git-data
```
1. [Download and install](https://about.gitlab.com/install/) the Omnibus GitLab
package of your choice. Be sure to follow _only_ installation steps 1 and 2
on the page.
@ -745,9 +720,10 @@ On each node perform the following:
1. [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
1. If you're not using NFS, [enable incremental logging](#enable-incremental-logging).
1. [Enable incremental logging](#enable-incremental-logging), unless you are using [NFS](#configure-nfs-optional).
1. Run `sudo gitlab-rake gitlab:gitaly:check` to confirm the node can connect to Gitaly.
1. Tail the logs to see the requests:
```shell

View File

@ -1639,7 +1639,9 @@ To configure Praefect with TLS:
Sidekiq requires connection to the [Redis](#configure-redis),
[PostgreSQL](#configure-postgresql) and [Gitaly](#configure-gitaly) instances.
[Object storage](#configure-the-object-storage) is also required to be configured.
Since it's recommended to use [Object storage](#configure-the-object-storage)
over [NFS](#configure-nfs-optional) for data objects, the following examples
include the Object storage configuration.
The following IPs will be used as an example:
@ -1806,35 +1808,12 @@ run [multiple Sidekiq processes](../operations/extra_sidekiq_processes.md).
## Configure GitLab Rails
This section describes how to configure the GitLab application (Rails) component.
[Object storage](#configure-the-object-storage) is also required to be configured.
Since it's recommended to use [Object storage](#configure-the-object-storage)
over [NFS](#configure-nfs-optional) for data objects, the following examples
include the Object storage configuration.
On each node perform the following:
1. If you're [using NFS](#configure-nfs-optional):
1. If necessary, install the NFS client utility packages using the following
commands:
```shell
# Ubuntu/Debian
apt-get install nfs-common
# CentOS/Red Hat
yum install nfs-utils nfs-utils-lib
```
1. Specify the necessary NFS mounts in `/etc/fstab`.
The exact contents of `/etc/fstab` will depend on how you chose
to configure your NFS server. See the [NFS documentation](../nfs.md)
for examples and the various options.
1. Create the shared directories. These may be different depending on your NFS
mount locations.
```shell
mkdir -p /var/opt/gitlab/.ssh /var/opt/gitlab/gitlab-rails/uploads /var/opt/gitlab/gitlab-rails/shared /var/opt/gitlab/gitlab-ci/builds /var/opt/gitlab/git-data
```
1. [Download and install](https://about.gitlab.com/install/) the Omnibus GitLab
package of your choice. Be sure to follow _only_ installation steps 1 and 2
on the page.
@ -1982,7 +1961,7 @@ On each node perform the following:
1. [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
1. If you're not using NFS, [enable incremental logging](#enable-incremental-logging).
1. [Enable incremental logging](#enable-incremental-logging), unless you are using [NFS](#configure-nfs-optional).
1. Run `sudo gitlab-rake gitlab:gitaly:check` to confirm the node can connect to Gitaly.

View File

@ -1709,7 +1709,9 @@ To configure Praefect with TLS:
Sidekiq requires connection to the [Redis](#configure-redis),
[PostgreSQL](#configure-postgresql) and [Gitaly](#configure-gitaly) instances.
[Object storage](#configure-the-object-storage) is also required to be configured.
Since it's recommended to use [Object storage](#configure-the-object-storage)
over [NFS](#configure-nfs-optional) for data objects, the following examples
include the Object storage configuration.
- `10.6.0.101`: Sidekiq 1
- `10.6.0.102`: Sidekiq 2
@ -1877,7 +1879,9 @@ run [multiple Sidekiq processes](../operations/extra_sidekiq_processes.md).
## Configure GitLab Rails
This section describes how to configure the GitLab application (Rails) component.
[Object storage](#configure-the-object-storage) is also required to be configured.
Since it's recommended to use [Object storage](#configure-the-object-storage)
over [NFS](#configure-nfs-optional) for data objects, the following examples
include the Object storage configuration.
The following IPs will be used as an example:
@ -2037,48 +2041,8 @@ On each node perform the following:
1. [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
1. If you're not using NFS, [enable incremental logging](#enable-incremental-logging).
1. [Enable incremental logging](#enable-incremental-logging), unless you are using [NFS](#configure-nfs-optional).
1. If you're [using NFS](#configure-nfs-optional):
1. If necessary, install the NFS client utility packages using the following
commands:
```shell
# Ubuntu/Debian
apt-get install nfs-common
# CentOS/Red Hat
yum install nfs-utils nfs-utils-lib
```
1. Specify the necessary NFS mounts in `/etc/fstab`.
The exact contents of `/etc/fstab` will depend on how you chose
to configure your NFS server. See the [NFS documentation](../nfs.md)
for examples and the various options.
1. Create the shared directories. These may be different depending on your NFS
mount locations.
```shell
mkdir -p /var/opt/gitlab/.ssh /var/opt/gitlab/gitlab-rails/uploads /var/opt/gitlab/gitlab-rails/shared /var/opt/gitlab/gitlab-ci/builds /var/opt/gitlab/git-data
```
1. Edit `/etc/gitlab/gitlab.rb` and use the following configuration:
```ruby
## Prevent GitLab from starting if NFS data mounts are not available
high_availability['mountpoint'] = '/var/opt/gitlab/git-data'
## Ensure UIDs and GIDs match between servers for permissions via NFS
user['uid'] = 9000
user['gid'] = 9000
web_server['uid'] = 9001
web_server['gid'] = 9001
registry['uid'] = 9002
registry['gid'] = 9002
```
1. Save the file and [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure).
1. Confirm the node can connect to Gitaly:
```shell

View File

@ -1636,7 +1636,9 @@ To configure Praefect with TLS:
Sidekiq requires connection to the [Redis](#configure-redis),
[PostgreSQL](#configure-postgresql) and [Gitaly](#configure-gitaly) instances.
[Object storage](#configure-the-object-storage) is also required to be configured.
Since it's recommended to use [Object storage](#configure-the-object-storage)
over [NFS](#configure-nfs-optional) for data objects, the following examples
include the Object storage configuration.
- `10.6.0.71`: Sidekiq 1
- `10.6.0.72`: Sidekiq 2
@ -1802,35 +1804,12 @@ run [multiple Sidekiq processes](../operations/extra_sidekiq_processes.md).
## Configure GitLab Rails
This section describes how to configure the GitLab application (Rails) component.
[Object storage](#configure-the-object-storage) is also required to be configured.
Since it's recommended to use [Object storage](#configure-the-object-storage)
over [NFS](#configure-nfs-optional) for data objects, the following examples
include the Object storage configuration.
On each node perform the following:
1. If you're [using NFS](#configure-nfs-optional):
1. If necessary, install the NFS client utility packages using the following
commands:
```shell
# Ubuntu/Debian
apt-get install nfs-common
# CentOS/Red Hat
yum install nfs-utils nfs-utils-lib
```
1. Specify the necessary NFS mounts in `/etc/fstab`.
The exact contents of `/etc/fstab` depends on how you chose
to configure your NFS server. See the [NFS documentation](../nfs.md)
for examples and the various options.
1. Create the shared directories. These may be different depending on your NFS
mount locations.
```shell
mkdir -p /var/opt/gitlab/.ssh /var/opt/gitlab/gitlab-rails/uploads /var/opt/gitlab/gitlab-rails/shared /var/opt/gitlab/gitlab-ci/builds /var/opt/gitlab/git-data
```
1. [Download and install](https://about.gitlab.com/install/) the Omnibus GitLab
package of your choice. Be sure to follow _only_ installation steps 1 and 2
on the page.
@ -1981,9 +1960,10 @@ On each node perform the following:
1. [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
1. If you're not using NFS, [enable incremental logging](#enable-incremental-logging).
1. [Enable incremental logging](#enable-incremental-logging), unless you are using [NFS](#configure-nfs-optional).
1. Run `sudo gitlab-rake gitlab:gitaly:check` to confirm the node can connect to Gitaly.
1. Tail the logs to see the requests:
```shell

View File

@ -779,3 +779,24 @@ Prints the metrics saved in `conversational_development_index_metrics`.
```shell
rake gitlab:usage_data:generate_and_send
```
## GraphQL
Call a [GraphQL](../../api/graphql/getting_started.md) endpoint through the Rails console:
```ruby
query = <<~EOQ
query securityGetProjects($search: String!) {
projects(search: $search) {
nodes {
path
}
}
}
EOQ
variables = { "search": "gitlab" }
result = GitlabSchema.execute(query, variables: variables, context: { current_user: current_user })
result.to_h
```

View File

@ -106,7 +106,8 @@ GET /users?without_project_bots=true
### For administrators **(FREE SELF)**
> The `namespace_id` field in the response was [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/82045) in GitLab 14.10.
> - The `namespace_id` field in the response was [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/82045) in GitLab 14.10.
> - The `created_by` field in the response was [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/93092) in GitLab 15.6.
```plaintext
GET /users
@ -161,7 +162,8 @@ GET /users
"private_profile": false,
"current_sign_in_ip": "196.165.1.102",
"last_sign_in_ip": "172.127.2.22",
"namespace_id": 1
"namespace_id": 1,
"created_by": null
},
{
"id": 2,
@ -196,7 +198,8 @@ GET /users
"private_profile": false,
"current_sign_in_ip": "10.165.1.102",
"last_sign_in_ip": "172.127.2.22",
"namespace_id": 2
"namespace_id": 2,
"created_by": null
}
]
```
@ -269,6 +272,13 @@ You can include the users' [custom attributes](custom_attributes.md) in the resp
GET /users?with_custom_attributes=true
```
You can use the `created_by` parameter to see if a user account was created:
- [Manually by an administrator](../user/profile/account/create_accounts.md#create-users-in-admin-area).
- As a [project bot user](../user/project/settings/project_access_tokens.md#bot-users-for-projects).
If the returned value is `null`, the account was created by a user who registered an account themselves.
## Single user
Get a single user.
@ -315,7 +325,8 @@ Parameters:
### For administrators **(FREE SELF)**
> The `namespace_id` field in the response was [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/82045) in GitLab 14.10.
> - The `namespace_id` field in the response was [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/82045) in GitLab 14.10.
> - The `created_by` field in the response was [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/93092) in GitLab 15.6.
```plaintext
GET /users/:id
@ -378,7 +389,8 @@ Example Responses:
"plan": "gold",
"trial": true,
"sign_in_count": 1337,
"namespace_id": 1
"namespace_id": 1,
"created_by": null
}
```
@ -419,6 +431,13 @@ see the `group_saml` option and `provisioned_by_group_id` parameter:
}
```
Administrators can use the `created_by` parameter to see if a user account was created:
- [Manually by an administrator](../user/profile/account/create_accounts.md#create-users-in-admin-area).
- As a [project bot user](../user/project/settings/project_access_tokens.md#bot-users-for-projects).
If the returned value is `null`, the account was created by a user who registered an account themselves.
You can include the user's [custom attributes](custom_attributes.md) in the response with:
```plaintext
@ -630,7 +649,8 @@ Users on [GitLab Premium or higher](https://about.gitlab.com/pricing/) also see
### For administrators **(FREE SELF)**
> The `namespace_id` field in the response was [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/82045) in GitLab 14.10.
> - The `namespace_id` field in the response was [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/82045) in GitLab 14.10.
> - The `created_by` field in the response was [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/93092) in GitLab 15.6.
```plaintext
GET /user
@ -683,6 +703,7 @@ Parameters:
"current_sign_in_ip": "196.165.1.102",
"last_sign_in_ip": "172.127.2.22",
"namespace_id": 1,
"created_by": null,
"note": null
}
```

View File

@ -281,11 +281,17 @@ declarative partitioning.
Doing that will also allow us to use a Unified Resource Identifier for
partitioned resources, that will contain a pointer to a pipeline ID, we could
then use to efficiently lookup a partition the resource is stored in. We could
use an ID like `1e240-5ba0` for pipeline `123456`, build `23456`. If we decide
to update the primary identifier of a partitioned resource (today it is just a
big integer) it is important to design a system that is resilient to migrating
data between partitions, to avoid changing idenfiers when rebalancing happens.
then use to efficiently lookup a partition the resource is stored in. It might
be important when a resources can be directly referenced by an URL, in UI or
API. We could use an ID like `1e240-5ba0` for pipeline `123456`, build `23456`.
Using a dash `-` can prevent an identifier from being highlighted and copied
with a mouse double-click. If we want to avoid this problem, we can use any
character of written representation that is not present in base-16 numeral
system - any letter from `g` to `z` in Latin alphabet, for example `x`. In that
case an example of an URI would look like `1e240x5ba0`. If we decide to update
the primary identifier of a partitioned resource (today it is just a big
integer) it is important to design a system that is resilient to migrating data
between partitions, to avoid changing idenfiers when rebalancing happens.
`ci_partitions` table will store information about a partition identifier,
pipeline ids range it is valid for and whether the partitions have been

View File

@ -43,10 +43,10 @@ to be able to keep using this and ship fixes and updates needed for our use case
and the documentation for it has been removed from the official page. This
means that the original reason to use Docker Machine is no longer valid too.
To keep supporting our customers and the wider community we need to design a
new mechanism for GitLab Runner auto-scaling. It not only needs to support
auto-scaling, but it also needs to do that in the way to enable us to build on
top of it to improve efficiency, reliability and availability.
To keep supporting our customers and the wider community and to improve our SaaS runners
maintenance we need to design a new mechanism for GitLab Runner auto-scaling. It not only
needs to support auto-scaling, but it also needs to do that in the way to enable us to
build on top of it to improve efficiency, reliability and availability.
We call this new mechanism the "next GitLab Runner Scaling architecture".
@ -62,6 +62,66 @@ subject to change or delay. The development, release and timing of any
products, features, or functionality remain at the sole discretion of GitLab
Inc._
## Continuing building on Docker Machine
At this moment one of our core products - GitLab Runner - and one of its most
important features - ability to auto-scale job execution environments - depends
on an external product that is abandoned.
Docker Machine project itself is also hard to maintain. Its design starts to
show its age, which makes it hard to bring new features and fixes. A huge
codebase that it brings with a lack of internal knowledge about it makes it
hard for our maintainers to support and properly handle incoming feature
requests and community contributions.
Docker Machine and it integrated 20+ drivers for cloud and virtualization
providers creates also another subset of problems, like:
- Each cloud/virtualization environment brings features that come and go
and we would need to maintain support for them (add new features, fix
bugs).
- We basically need to become experts for each of the virtualization/cloud
provider to properly support integration with their API,
- Every single provider that Docker Machine integrates with has its
bugs, security releases, vulnerabilities - to maintain the project properly
we would need to be on top of all of that and handle updates whenever
they are needed.
Another problem is the fact that Docker Machine, from its beginnings, was
focused on managing Linux based instances only. Despite that at some moment
Docker got official and native integration on Windows, Docker Machine never
followed this step. Nor its designed to make such integration easy.
There is also no support for MacOS. This one is obvious - Docker Machine is a
tool to maintain hosts for Docker Engine and there is no native Docker Engine
for MacOS. And by native we mean MacOS containers executed within MacOS
operating system. Docker for MacOS product is not a native support - it's just
a tooling and a virtualized Linux instance installed with it that makes it
easier to develop **Linux containers** on MacOS development instances.
This means that only one of three of our officially supported platforms -
Linux, Windows and MacOS - have a fully-featured support for CI/CD
auto-scaling. For Windows there is a possibility to use Kubernetes (which in
some cases have limitations) and maybe with a lot of effort we could bring
support for Windows into Docker Machine. But for MacOS, there is no
auto-scaling solution provided natively by GitLab Runner.
This is a huge limitation for our users and a frequently requested feature.
It's also a limitation for our SaaS runners offering. We've maintained to
create some sort of auto-scaling for our SaaS Windows and SaaS MacOS runners
hacking around Custom executor. But experiences from past three years show
that it's not the best way of doing this. And yet, after this time, Windows
and MacOS runners autoscaling lacks a lot of performance and feature support
that we have with our SaaS Linux runners.
To keep supporting our customers and the wider community and to improve our
SaaS runners maintenance we need to design a new mechanism for GitLab Runner
auto-scaling. It not only needs to support auto-scaling, but it also needs to
do that in the way to enable us to build on top of it to improve efficiency,
reliability and availability.
## Proposal
Currently, GitLab Runner auto-scaling can be configured in a few ways. Some
@ -246,9 +306,17 @@ abstraction.
- Design the new auto-scaling architecture aiming for having more choices and
flexibility in the future, instead of imposing new constraints.
- Design the new auto-scaling architecture to experiment with running multiple
jobs in parallel, on a single machine.
jobs in parallel, on a single machine.
- Design the new provisioning architecture to replace Docker Machine in a way
that the wider community can easily build on top of the new abstractions.
- New auto-scaling method should become a core component of GitLab Runner product so that
we can simplify maintenance, use the same tooling, test configuration and Go language
setup as we do in our other main products.
- It should support multiple job execution environments - not only Docker containers
on Linux operating system.
The best design would be to bring auto-scaling as a feature wrapped around
our current executors like Docker or Shell.
#### Principles for the new plugin system
@ -270,10 +338,14 @@ abstraction.
- Favor gRPC communication between a plugin and GitLab Runner.
- Make it possible to version communication interface and support many versions.
- Make Go a primary language for writing plugins but accept other languages too.
- Prefer a GitLab job-aware autoscaler to provider specific autoscalers. Cloud provider
autoscalers don't know which VM to delete when scaling down so they make sub-optimal
decisions. Rather than teaching all autoscalers about GitLab jobs, we prefer to
have one, GitLab-owned autoscaler (not in the plugin).
- Autoscaling mechanism should be fully owned by GitLab.
Cloud provider autoscalers don't know which VM to delete when scaling down so
they make sub-optimal decisions. Rather than teaching all autoscalers about GitLab
jobs, we prefer to have one, GitLab-owned autoscaler (not in the plugin).
It will also ensure that we can shape the future of the mechanism and make decisions
that fit our needs and requirements.
## Plugin boundary proposals
@ -350,7 +422,7 @@ Proposal:
<!-- vale gitlab.Spelling = NO -->
| Role | Who
| Role | Who |
|------------------------------|-------------------------------------------------|
| Authors | Grzegorz Bizon, Tomasz Maczukin, Joseph Burnett |
| Architecture Evolution Coach | Kamil Trzciński |
@ -360,16 +432,16 @@ Proposal:
DRIs:
| Role | Who
|------------------------------|------------------------|
| Leadership | Elliot Rushton |
| Product | Darren Eastman |
| Engineering | Tomasz Maczukin |
| Role | Who |
|-------------|-----------------|
| Leadership | Elliot Rushton |
| Product | Darren Eastman |
| Engineering | Tomasz Maczukin |
Domain experts:
| Area | Who
|------------------------------|------------------------|
| Domain Expert / Runner | Arran Walker |
| Area | Who |
|------------------------|--------------|
| Domain Expert / Runner | Arran Walker |
<!-- vale gitlab.Spelling = YES -->

View File

@ -60,6 +60,14 @@ To make submodules work correctly in CI/CD jobs:
GIT_SUBMODULE_STRATEGY: recursive
```
1. You can filter or exclude specific submodules to control which submodules will be synced using
[`GIT_SUBMODULE_PATHS`](runners/configure_runners.md#git-submodule-paths).
```yaml
variables:
GIT_SUBMODULE_PATHS: submoduleA submoduleB
```
1. You can provide additional flags to control advanced checkout behavior using
[`GIT_SUBMODULE_UPDATE_FLAGS`](runners/configure_runners.md#git-submodule-update-flags).

View File

@ -302,6 +302,7 @@ globally or for individual jobs:
- [`GIT_CHECKOUT`](#git-checkout)
- [`GIT_CLEAN_FLAGS`](#git-clean-flags)
- [`GIT_FETCH_EXTRA_FLAGS`](#git-fetch-extra-flags)
- [`GIT_SUBMODULE_PATHS`](#git-submodule-paths)
- [`GIT_SUBMODULE_UPDATE_FLAGS`](#git-submodule-update-flags)
- [`GIT_DEPTH`](#shallow-cloning) (shallow cloning)
- [`GIT_CLONE_PATH`](#custom-build-directories) (custom build directories)
@ -488,6 +489,32 @@ git fetch origin $REFSPECS --depth 50 --prune
Where `$REFSPECS` is a value provided to the runner internally by GitLab.
### Git submodule paths
> [Introduced](https://gitlab.com/gitlab-org/gitlab-runner/-/merge_requests/2249) in GitLab Runner 14.0.
Use the `GIT_SUBMODULE_PATHS` variable to control which submodules have to be synced or updated.
You can set it globally or per-job in the [`variables`](../yaml/index.md#variables) section.
This variable can be very useful for projects which have a large number of submodules which not all of them
need to be synced or updated in all CI jobs.
The path syntax is the same as [`git submodule`](https://git-scm.com/docs/git-submodule#Documentation/git-submodule.txt-ltpathgt82308203):
- To sync and update specific paths:
```yaml
variables:
GIT_SUBMODULE_PATHS: submoduleA submoduleB
```
- To exclude specific paths:
```yaml
variables:
GIT_SUBMODULE_PATHS: :(exclude)submoduleA :(exclude)submoduleB
```
### Git submodule update flags
> [Introduced](https://gitlab.com/gitlab-org/gitlab-runner/-/merge_requests/3192) in GitLab Runner 14.8.

View File

@ -4,7 +4,7 @@ group: Database
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Foreign Keys & Associations
# Foreign keys and associations
When adding an association to a model you must also add a foreign key. For
example, say you have the following model:
@ -20,7 +20,7 @@ that data consistency is enforced on database level. Foreign keys also mean that
the database can very quickly remove associated data (for example, when removing a
user), instead of Rails having to do this.
## Adding Foreign Keys In Migrations
## Adding foreign keys in migrations
Foreign keys can be added concurrently using `add_concurrent_foreign_key` as
defined in `Gitlab::Database::MigrationHelpers`. See the
@ -31,7 +31,7 @@ you have removed any orphaned rows. The method `add_concurrent_foreign_key`
does not take care of this so you must do so manually. See
[adding foreign key constraint to an existing column](add_foreign_key_to_existing_column.md).
## Updating Foreign Keys In Migrations
## Updating foreign keys in migrations
Sometimes a foreign key constraint must be changed, preserving the column
but updating the constraint condition. For example, moving from
@ -45,64 +45,64 @@ To replace a foreign key:
1. [Add the new foreign key without validation](add_foreign_key_to_existing_column.md#prevent-invalid-records)
The name of the foreign key constraint must be changed to add a new
foreign key before removing the old one.
The name of the foreign key constraint must be changed to add a new
foreign key before removing the old one.
```ruby
class ReplaceFkOnPackagesPackagesProjectId < Gitlab::Database::Migration[2.0]
disable_ddl_transaction!
```ruby
class ReplaceFkOnPackagesPackagesProjectId < Gitlab::Database::Migration[2.0]
disable_ddl_transaction!
NEW_CONSTRAINT_NAME = 'fk_new'
NEW_CONSTRAINT_NAME = 'fk_new'
def up
add_concurrent_foreign_key(:packages_packages, :projects, column: :project_id, on_delete: :nullify, validate: false, name: NEW_CONSTRAINT_NAME)
end
def up
add_concurrent_foreign_key(:packages_packages, :projects, column: :project_id, on_delete: :nullify, validate: false, name: NEW_CONSTRAINT_NAME)
end
def down
with_lock_retries do
remove_foreign_key_if_exists(:packages_packages, column: :project_id, on_delete: :nullify, name: NEW_CONSTRAINT_NAME)
end
end
end
```
def down
with_lock_retries do
remove_foreign_key_if_exists(:packages_packages, column: :project_id, on_delete: :nullify, name: NEW_CONSTRAINT_NAME)
end
end
end
```
1. [Validate the new foreign key](add_foreign_key_to_existing_column.md#validate-the-foreign-key)
```ruby
class ValidateFkNew < Gitlab::Database::Migration[2.0]
NEW_CONSTRAINT_NAME = 'fk_new'
```ruby
class ValidateFkNew < Gitlab::Database::Migration[2.0]
NEW_CONSTRAINT_NAME = 'fk_new'
# foreign key added in <link to MR or path to migration adding new FK>
def up
validate_foreign_key(:packages_packages, name: NEW_CONSTRAINT_NAME)
end
# foreign key added in <link to MR or path to migration adding new FK>
def up
validate_foreign_key(:packages_packages, name: NEW_CONSTRAINT_NAME)
end
def down
# no-op
end
end
```
def down
# no-op
end
end
```
1. Remove the old foreign key:
```ruby
class RemoveFkOld < Gitlab::Database::Migration[2.0]
OLD_CONSTRAINT_NAME = 'fk_old'
```ruby
class RemoveFkOld < Gitlab::Database::Migration[2.0]
OLD_CONSTRAINT_NAME = 'fk_old'
# new foreign key added in <link to MR or path to migration adding new FK>
# and validated in <link to MR or path to migration validating new FK>
def up
remove_foreign_key_if_exists(:packages_packages, column: :project_id, on_delete: :cascade, name: OLD_CONSTRAINT_NAME)
end
# new foreign key added in <link to MR or path to migration adding new FK>
# and validated in <link to MR or path to migration validating new FK>
def up
remove_foreign_key_if_exists(:packages_packages, column: :project_id, on_delete: :cascade, name: OLD_CONSTRAINT_NAME)
end
def down
# Validation is skipped here, so if rolled back, this will need to be revalidated in a separate migration
add_concurrent_foreign_key(:packages_packages, :projects, column: :project_id, on_delete: :cascade, validate: false, name: OLD_CONSTRAINT_NAME)
end
end
```
def down
# Validation is skipped here, so if rolled back, this will need to be revalidated in a separate migration
add_concurrent_foreign_key(:packages_packages, :projects, column: :project_id, on_delete: :cascade, validate: false, name: OLD_CONSTRAINT_NAME)
end
end
```
## Cascading Deletes
## Cascading deletes
Every foreign key must define an `ON DELETE` clause, and in 99% of the cases
this should be set to `CASCADE`.
@ -124,7 +124,7 @@ have a foreign key constraint. So if that spec fails, don't add the column to
`IGNORED_FK_COLUMNS`, but instead add the FK constraint, or consider naming it
differently.
## Dependent Removals
## Dependent removals
Don't define options such as `dependent: :destroy` or `dependent: :delete` when
defining an association. Defining these options means Rails handles the
@ -182,9 +182,9 @@ create_table :user_configs, id: false do |t|
end
```
Setting `default: nil` ensures a primary key sequence is not created, and since the primary key
Setting `default: nil` ensures a primary key sequence is not created, and because the primary key
automatically gets an index, we set `index: false` to avoid creating a duplicate.
You also need to add the new primary key to the model:
You must also add the new primary key to the model:
```ruby
class UserConfig < ActiveRecord::Base

View File

@ -0,0 +1,99 @@
---
stage: Analytics
group: Product Analytics
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Customizable dashboards **(PREMIUM)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/98610) in GitLab 15.5 as an [Alpha feature](../../policy/alpha-beta-support.md#alpha-features).
Customizable dashboards provide a dashboard structure that allows users to create
their own dashboards and commit the structure to a repository.
## Usage
To use customizable dashboards:
1. Create your dashboard component.
1. Render an instance of `CustomizableDashboard`.
1. Pass a list of widgets to render.
For example, a customizable dashboard for users over time:
```vue
<script>
import CustomizableDashboard from 'ee/vue_shared/components/customizable_dashboard/customizable_dashboard.vue';
import { s__ } from '~/locale';
export default {
name: 'AnalyticsDashboard',
components: {
CustomizableDashboard,
},
data() {
return {
widgets: [
{
component: 'CubeLineChart', // The name of the widget component.
title: s__('ProductAnalytics|Users / Time'), // The title shown on the widget component.
// Gridstack settings based upon https://github.com/gridstack/gridstack.js/tree/master/doc#item-options.
// All values are grid row/column numbers up to 12.
// We use the default 12 column grid https://github.com/gridstack/gridstack.js#change-grid-columns.
gridAttributes: {
size: {
height: 4,
width: 6,
minHeight: 4,
minWidth: 6,
},
position: {
xPos: 0,
yPos: 0,
},
},
// Options that are used to set bespoke values for each widget.
// Available customizations are determined by the widget itself.
customizations: {},
// Chart options defined by the charting library being used by the widget.
chartOptions: {
xAxis: { name: __('Time'), type: 'time' },
yAxis: { name: __('Counts') },
},
// The data for the widget.
// This could be imported or in this case, a query passed to be used by the widgets API.
// Each widget type determines how it handles this property.
data: {
query: {
users: {
measures: ['Jitsu.count'],
dimensions: ['Jitsu.eventType'],
},
},
},
},
]
};
},
};
</script>
<template>
<h1>{{ s__('ProductAnalytics|Analytics dashboard') }}</h1>
<customizable-dashboard :widgets="widgets" />
</template>
```
The widgets data can be retrieved from a file or API request, or imported through HTML data attributes.
For each widget, a `component` is defined. Each `component` is a component declaration and should be included in
[`vue_shared/components/customizable_dashboard/widgets_base.vue`](https://gitlab.com/gitlab-org/gitlab/blob/master/ee/app/assets/javascripts/vue_shared/components/customizable_dashboard/widgets_base.vue)
as a dynamic import, to keep the memory usage down until it is used.
For example:
```javascript
components: {
CubeLineChart: () => import('ee/product_analytics/dashboards/components/widgets/cube_line_chart.vue')
}
```

View File

@ -114,6 +114,7 @@ Consult these topics for information on contributing to specific GitLab features
- [Cached queries guidelines](cached_queries.md), for tracking down N+1 queries
masked by query caching, memory profiling and why should we avoid cached
queries.
- [JSON guidelines](json.md) for how to handle JSON in a performant manner.
## Database guides

46
doc/development/json.md Normal file
View File

@ -0,0 +1,46 @@
---
stage: none
group: unassigned
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# JSON Guidelines
At GitLab we handle a lot of JSON data. To best ensure we remain performant
when handling large JSON encodes or decodes, we use our own JSON class
instead of the default methods.
## `Gitlab::Json`
This class should be used in place of any calls to the default `JSON` class,
`.to_json` calls, and the like. It implements the majority of the public
methods provided by `JSON`, such as `.parse`, `.generate`, `.dump`, etc, and
should be entirely identical in its response.
The difference being that by sending all JSON handling through `Gitlab::Json`
we can change the gem being used in the background. We use `oj`
instead of the `json` gem, which uses C extensions and is therefore notably
faster.
This class came into existence because, due to the age of the GitLab application,
it was proving impossible to just replace the `json` gem with `oj` by default because:
- The number of tests with exact expectations of the responses.
- The subtle variances between different JSON processors, particularly
around formatting.
The `Gitlab::Json` class takes this into account and can
vary the adapter based on the use case, and account for outdated formatting
expectations.
## `Gitlab::Json::PrecompiledJson`
This class is used by our hooks into the Grape framework to ensure that
already-generated JSON is not then run through JSON generation
a second time when returning the response.
## `Gitlab::Json::LimitedEncoder`
This class can be used to generate JSON but fail with an error if the
resulting JSON would be too large. The default limit for the `.encode`
method is 25 MB, but this can be customized when using the method.

View File

@ -46,10 +46,7 @@ A new subscription must be purchased and applied as needed.
Pricing is [tier-based](https://about.gitlab.com/pricing/), allowing you to choose
the features which fit your budget. For information on what features are available
at each tier for each product, see:
- [GitLab SaaS feature comparison](https://about.gitlab.com/pricing/gitlab-com/feature-comparison/)
- [GitLab self-managed feature comparison](https://about.gitlab.com/pricing/self-managed/feature-comparison/)
at each tier for each product, see: [GitLab self-managed feature comparison](https://about.gitlab.com/pricing/feature-comparison/)
## Find your subscription

File diff suppressed because it is too large Load Diff

View File

@ -6,6 +6,7 @@ module API
expose :admin?, as: :is_admin
expose :note
expose :namespace_id
expose :created_by, with: UserBasic
end
end
end

View File

@ -59,7 +59,7 @@ module API
optional :only_allow_merge_if_all_discussions_are_resolved, type: Boolean, desc: 'Only allow to merge if all threads are resolved'
optional :tag_list, type: Array[String], coerce_with: ::API::Validations::Types::CommaSeparatedToArray.coerce, desc: 'Deprecated: Use :topics instead'
optional :topics, type: Array[String], coerce_with: ::API::Validations::Types::CommaSeparatedToArray.coerce, desc: 'The list of topics for a project'
optional :avatar, type: ::API::Validations::Types::WorkhorseFile, desc: 'Avatar image for project'
optional :avatar, type: ::API::Validations::Types::WorkhorseFile, desc: 'Avatar image for project', documentation: { type: 'file' }
optional :printing_merge_request_link_enabled, type: Boolean, desc: 'Show link to create/view merge request when pushing from the command line'
optional :merge_method, type: String, values: %w(ff rebase_merge merge), desc: 'The merge method used when merging merge requests'
optional :suggestion_commit_message, type: String, desc: 'The commit message used to apply merge request suggestions'
@ -73,7 +73,7 @@ module API
optional :repository_storage, type: String, desc: 'Which storage shard the repository is on. Available only to admins'
optional :packages_enabled, type: Boolean, desc: 'Enable project packages feature'
optional :squash_option, type: String, values: %w(never always default_on default_off), desc: 'Squash default for project. One of `never`, `always`, `default_on`, or `default_off`.'
optional :mr_default_target_self, Boolean, desc: 'Merge requests of this forked project targets itself by default'
optional :mr_default_target_self, type: Boolean, desc: 'Merge requests of this forked project targets itself by default'
end
params :optional_project_params_ee do

View File

@ -46,7 +46,8 @@ module API
optional :description, type: String, desc: 'Override the project description'
optional :upload, type: Hash do
optional :url, type: String, desc: 'The URL to upload the project'
optional :http_method, type: String, default: 'PUT', desc: 'HTTP method to upload the exported project'
optional :http_method, type: String, default: 'PUT', values: %w[PUT POST],
desc: 'HTTP method to upload the exported project'
end
end
post ':id/export' do

View File

@ -55,7 +55,7 @@ module API
params do
requires :path, type: String, desc: 'The new project path and name'
requires :file, type: ::API::Validations::Types::WorkhorseFile, desc: 'The project export file to be imported'
requires :file, type: ::API::Validations::Types::WorkhorseFile, desc: 'The project export file to be imported', documentation: { type: 'file' }
optional :name, type: String, desc: 'The name of the project to be imported. Defaults to the path of the project if not provided.'
optional :namespace, type: String, desc: "The ID or name of the namespace that the project will be imported into. Defaults to the current user's namespace."
optional :overwrite, type: Boolean, default: false, desc: 'If there is a project in the same namespace and with the same name overwrite it'

View File

@ -33,6 +33,7 @@ module Gitlab
gon.sprite_file_icons = IconsHelper.sprite_file_icons_path
gon.emoji_sprites_css_path = ActionController::Base.helpers.stylesheet_path('emoji_sprites')
gon.select2_css_path = ActionController::Base.helpers.stylesheet_path('lazy_bundles/select2.css')
gon.gridstack_css_path = ActionController::Base.helpers.stylesheet_path('lazy_bundles/gridstack.css')
gon.test_env = Rails.env.test?
gon.disable_animations = Gitlab.config.gitlab['disable_animations']
gon.suggested_label_colors = LabelsHelper.suggested_colors

View File

@ -7,10 +7,10 @@ namespace :tw do
task :codeowners do
CodeOwnerRule = Struct.new(:category, :writer)
DocumentOwnerMapping = Struct.new(:path, :writer) do
def writer_owns_all_pages?(mappings)
mappings
.select { |mapping| mapping.directory == directory }
.all? { |mapping| mapping.writer == writer }
def writer_owns_directory?(mappings)
dir_mappings = mappings.select { |mapping| mapping.directory == directory }
dir_mappings.count { |mapping| mapping.writer == writer } / dir_mappings.length.to_f > 0.5
end
def directory
@ -115,14 +115,14 @@ namespace :tw do
deduplicated_mappings = Set.new
mappings.each do |mapping|
if mapping.writer_owns_all_pages?(mappings)
if mapping.writer_owns_directory?(mappings)
deduplicated_mappings.add("#{mapping.directory}/ #{mapping.writer}")
else
deduplicated_mappings.add("#{mapping.path} #{mapping.writer}")
end
end
deduplicated_mappings.each { |mapping| puts mapping }
deduplicated_mappings.sort.each { |mapping| puts mapping }
if errors.present?
puts "-----"

View File

@ -30800,9 +30800,15 @@ msgstr ""
msgid "Product Analytics"
msgstr ""
msgid "ProductAnalytics|Audience"
msgstr ""
msgid "ProductAnalytics|There is no data for this type of chart currently. Please see the Setup tab if you have not configured the product analytics tool already."
msgstr ""
msgid "ProductAnalytics|Widgets content"
msgstr ""
msgid "Productivity"
msgstr ""

View File

@ -127,6 +127,7 @@
"fuzzaldrin-plus": "^0.6.0",
"graphql": "^15.7.2",
"graphql-tag": "^2.11.0",
"gridstack": "^7.0.0",
"highlight.js": "^11.5.1",
"immer": "^9.0.15",
"ipaddr.js": "^1.9.1",

View File

@ -24,6 +24,7 @@ module Glfm
specification_input_glfm_path.join('glfm_example_metadata.yml')
GLFM_EXAMPLE_NORMALIZATIONS_YML_PATH = specification_input_glfm_path.join('glfm_example_normalizations.yml')
GLFM_SPEC_TXT_PATH = specification_path.join('output/spec.txt')
GLFM_SPEC_HTML_PATH = specification_path.join('output/spec.html')
# Example Snapshot (ES) files
es_fixtures_path = File.expand_path("../../../glfm_specification/example_snapshots", __dir__)

View File

@ -25,7 +25,7 @@ require_relative 'shared'
# It is intended to be invoked as a helper subprocess from the `update_example_snapshots.rb`
# script class. It's not intended to be run or used directly. This usage is also reinforced
# by not naming the file with a `_spec.rb` ending.
RSpec.describe 'Render Static HTML', :api, type: :request do # rubocop:disable RSpec/TopLevelDescribePath
RSpec.describe 'Render Static HTML', :api, type: :request do
include Glfm::Constants
include Glfm::Shared
@ -34,7 +34,12 @@ RSpec.describe 'Render Static HTML', :api, type: :request do # rubocop:disable R
it do
markdown_hash = YAML.safe_load(File.open(ENV.fetch('INPUT_MARKDOWN_YML_PATH')), symbolize_names: true)
metadata_hash = YAML.safe_load(File.open(ENV.fetch('INPUT_METADATA_YML_PATH')), symbolize_names: true) || {}
metadata_hash =
if input_metadata_yml_path = ENV['INPUT_METADATA_YML_PATH']
YAML.safe_load(File.open(input_metadata_yml_path), symbolize_names: true) || {}
else
{}
end
# NOTE: We cannot parallelize this loop like the Javascript WYSIWYG example generation does,
# because the rspec `post` API cannot be parallized (it is not thread-safe, it can't find

View File

@ -10,7 +10,7 @@ require_relative 'constants'
require_relative 'shared'
require_relative 'parse_examples'
# IMPORTANT NOTE: See https://docs.gitlab.com/ee/development/gitlab_flavored_markdown/specification_guide/
# IMPORTANT NOTE: See https://docs.gitlab.com/ee/development/gitlab_flavored_markdown/specification_guide/#update-example-snapshotsrb-script
# for details on the implementation and usage of this script. This developers guide
# contains diagrams and documentation of this script,
# including explanations and examples of all files it reads and writes.
@ -30,8 +30,6 @@ module Glfm
def process(skip_static_and_wysiwyg: false)
output('Updating example snapshots...')
output('(Skipping static HTML generation)') if skip_static_and_wysiwyg
output("Reading #{GLFM_SPEC_TXT_PATH}...")
glfm_spec_txt_lines = File.open(GLFM_SPEC_TXT_PATH).readlines
@ -266,7 +264,7 @@ module Glfm
# NOTE 2: We run this as an RSpec process, for the same reasons we run via Jest process below:
# because that's the easiest way to ensure a reliable, fully-configured environment in which
# to execute the markdown-generation logic. Also, in the static/backend case, Rspec
# to execute the markdown-processing logic. Also, in the static/backend case, Rspec
# provides the easiest and most reliable way to generate example data via Factorybot
# creation of stable model records. This ensures consistent snapshot values across
# machines/environments.

View File

@ -2,19 +2,38 @@
require 'fileutils'
require 'open-uri'
require 'pathname'
require 'tempfile'
require 'yaml'
require_relative 'constants'
require_relative 'shared'
# IMPORTANT NOTE: See https://docs.gitlab.com/ee/development/gitlab_flavored_markdown/specification_guide/#update-specificationrb-script
# for details on the implementation and usage of this script. This developers guide
# contains diagrams and documentation of this script,
# including explanations and examples of all files it reads and writes.
#
# Also note that this script is intentionally written in a pure-functional (not OO) style,
# with no dependencies on Rails or the GitLab libraries. These choices are intended to make
# it faster and easier to test and debug.
module Glfm
class UpdateSpecification
include Constants
include Shared
def process
def process(skip_spec_html_generation: false)
output('Updating specification...')
ghfm_spec_lines = load_ghfm_spec
glfm_spec_txt_string = build_glfm_spec_txt(ghfm_spec_lines)
write_glfm_spec_txt(glfm_spec_txt_string)
if skip_spec_html_generation
output("Skipping GLFM spec.html generation...")
return
end
glfm_spec_html_string = generate_glfm_spec_html(glfm_spec_txt_string)
write_glfm_spec_html(glfm_spec_html_string)
end
private
@ -43,7 +62,11 @@ module Glfm
def update_ghfm_spec_md
output("Downloading #{GHFM_SPEC_TXT_URI}...")
ghfm_spec_txt_uri_io = URI.parse(GHFM_SPEC_TXT_URI).open
# NOTE: We use `URI.parse` to avoid RuboCop warning "Security/Open",
# even though we are using a trusted URI from a string literal constant.
# See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/98656#note_1138595002 for details.
ghfm_spec_txt_uri_parsed = URI.parse(GHFM_SPEC_TXT_URI)
ghfm_spec_txt_uri_io = ghfm_spec_txt_uri_parsed.open
# Read IO stream into an array of lines for easy processing later
ghfm_spec_lines = ghfm_spec_txt_uri_io.readlines
@ -132,5 +155,49 @@ module Glfm
FileUtils.mkdir_p(Pathname.new(GLFM_SPEC_TXT_PATH).dirname)
write_file(GLFM_SPEC_TXT_PATH, glfm_spec_txt_string)
end
def generate_glfm_spec_html(glfm_spec_txt_string)
output("Generating spec.html from spec.txt markdown...")
input_markdown_yml_string = <<~MARKDOWN
---
spec_txt: |
#{glfm_spec_txt_string.gsub(/^/, ' ')}
MARKDOWN
# NOTE: We must copy the input YAML file used by the `render_static_html.rb`
# to a separate temporary file in order for the script to read them, because it is run in
# a separate subprocess, and during unit testing we are unable to substitute the mock
# StringIO when reading the input files in the subprocess.
ENV['INPUT_MARKDOWN_YML_PATH'] = Dir::Tmpname.create(MARKDOWN_TEMPFILE_BASENAME) do |path|
write_file(path, input_markdown_yml_string)
end
# NOTE 1: We shell out to perform the conversion of markdown to static HTML by invoking a
# separate subprocess. This allows us to avoid using the Rails API or environment in this
# script, which makes developing and running the unit tests for this script much faster,
# because they can use 'fast_spec_helper' which does not require the entire Rails environment.
# NOTE 2: We run this as an RSpec process, for the same reasons we run via Jest process below:
# because that's the easiest way to ensure a reliable, fully-configured environment in which
# to execute the markdown-processing logic. Also, in the static/backend case.
# Dir::Tmpname.create requires a block, but we are using the non-block form to get the path
# via the return value, so we pass an empty block to avoid an error.
static_html_tempfile_path = Dir::Tmpname.create(STATIC_HTML_TEMPFILE_BASENAME) {}
ENV['OUTPUT_STATIC_HTML_TEMPFILE_PATH'] = static_html_tempfile_path
cmd = %(bin/rspec #{__dir__}/render_static_html.rb)
run_external_cmd(cmd)
output("Reading generated spec.html from tempfile #{static_html_tempfile_path}...")
YAML.safe_load(File.open(static_html_tempfile_path), symbolize_names: true).fetch(:spec_txt)
end
def write_glfm_spec_html(glfm_spec_html_string)
output("Writing #{GLFM_SPEC_TXT_PATH}...")
FileUtils.mkdir_p(Pathname.new(GLFM_SPEC_HTML_PATH).dirname)
write_file(GLFM_SPEC_HTML_PATH, "#{glfm_spec_html_string}\n")
end
end
end

View File

@ -404,7 +404,7 @@ RSpec.describe Emails::Profile do
end
it 'includes a link to the change password documentation' do
is_expected.to have_body_text 'https://docs.gitlab.com/ee/user/profile/#changing-your-password'
is_expected.to have_body_text 'https://docs.gitlab.com/ee/user/profile/user_passwords.html#change-your-password'
end
it 'mentions two factor authentication when two factor is not enabled' do
@ -454,7 +454,7 @@ RSpec.describe Emails::Profile do
end
it 'includes a link to the change password documentation' do
is_expected.to have_body_text 'https://docs.gitlab.com/ee/user/profile/#changing-your-password'
is_expected.to have_body_text 'https://docs.gitlab.com/ee/user/profile/user_passwords.html#change-your-password'
end
end

View File

@ -165,6 +165,7 @@ RSpec.describe API::Users do
expect(json_response.first).not_to have_key('note')
expect(json_response.first).not_to have_key('namespace_id')
expect(json_response.first).not_to have_key('created_by')
end
end
@ -175,6 +176,7 @@ RSpec.describe API::Users do
expect(json_response.first).not_to have_key('note')
expect(json_response.first).not_to have_key('namespace_id')
expect(json_response.first).not_to have_key('created_by')
end
end
@ -186,6 +188,26 @@ RSpec.describe API::Users do
expect(json_response.first).to have_key('note')
expect(json_response.first['note']).to eq '2018-11-05 | 2FA removed | user requested | www.gitlab.com'
end
context 'with `created_by` details' do
it 'has created_by as nil with a self-registered account' do
get api("/users", admin), params: { username: user.username }
expect(response).to have_gitlab_http_status(:success)
expect(json_response.first).to have_key('created_by')
expect(json_response.first['created_by']).to eq(nil)
end
it 'is created_by a user and has those details' do
created = create(:user, created_by_id: user.id)
get api("/users", admin), params: { username: created.username }
expect(response).to have_gitlab_http_status(:success)
expect(json_response.first['created_by'].symbolize_keys)
.to eq(API::Entities::UserBasic.new(user).as_json)
end
end
end
context 'N+1 queries' do

View File

@ -2,8 +2,8 @@
require 'fast_spec_helper'
require_relative '../../../../scripts/lib/glfm/update_example_snapshots'
# IMPORTANT NOTE: See https://docs.gitlab.com/ee/development/gitlab_flavored_markdown/specification_guide/
# for details on the implementation and usage of the `update_example_snapshots` script being tested.
# IMPORTANT NOTE: See https://docs.gitlab.com/ee/development/gitlab_flavored_markdown/specification_guide/#update-example-snapshotsrb-script
# for details on the implementation and usage of the `update_example_snapshots.rb` script being tested.
# This developers guide contains diagrams and documentation of the script,
# including explanations and examples of all files it reads and writes.
#
@ -16,11 +16,11 @@ require_relative '../../../../scripts/lib/glfm/update_example_snapshots'
# which runs a jest test environment. This results in each full run of the script
# taking between 30-60 seconds. The majority of this is spent loading the Rails environment.
#
# However, only the `writing html.yml and prosemirror_json.yml` context is used
# to test these slow sub-processes, and it only contains a single example.
# However, only the `with full processing of static and WYSIWYG HTML` context is used
# to test these slow sub-processes, and it only contains two examples.
#
# All other tests currently in the file pass the `skip_static_and_wysiwyg: true`
# flag to `#process`, which skips the slow sub-processes. All of these tests
# flag to `#process`, which skips the slow sub-processes. All of these other tests
# should run in sub-second time when the Spring pre-loader is used. This allows
# logic which is not directly related to the slow sub-processes to be TDD'd with a
# very rapid feedback cycle.

View File

@ -4,12 +4,35 @@ require 'fast_spec_helper'
require_relative '../../../../scripts/lib/glfm/update_specification'
require_relative '../../../support/helpers/next_instance_of'
# IMPORTANT NOTE: See https://docs.gitlab.com/ee/development/gitlab_flavored_markdown/specification_guide/#update-specificationrb-script
# for details on the implementation and usage of the `update_specification.rb` script being tested.
# This developers guide contains diagrams and documentation of the script,
# including explanations and examples of all files it reads and writes.
#
# Note that this test is not structured in a traditional way, with multiple examples
# to cover all different scenarios. Instead, the content of the stubbed test fixture
# files are crafted to cover multiple scenarios with in a single example run.
#
# This is because the invocation of the full script is slow, because it executes
# a subshell for processing, which runs a full Rails environment.
# This results in each full run of the script taking between 30-60 seconds.
# The majority of this is spent loading the Rails environment.
#
# However, only the `with generation of spec.html` context is used
# to test this slow sub-process, and it only contains one example.
#
# All other tests currently in the file pass the `skip_spec_html_generation: true`
# flag to `#process`, which skips the slow sub-process. All of these other tests
# should run in sub-second time when the Spring pre-loader is used. This allows
# logic which is not directly related to the slow sub-processes to be TDD'd with a
# very rapid feedback cycle.
RSpec.describe Glfm::UpdateSpecification, '#process' do
include NextInstanceOf
subject { described_class.new }
let(:ghfm_spec_txt_uri) { described_class::GHFM_SPEC_TXT_URI }
let(:ghfm_spec_txt_uri_parsed) { instance_double(URI::HTTPS, :ghfm_spec_txt_uri_parsed) }
let(:ghfm_spec_txt_uri_io) { StringIO.new(ghfm_spec_txt_contents) }
let(:ghfm_spec_md_path) { described_class::GHFM_SPEC_MD_PATH }
let(:ghfm_spec_txt_local_io) { StringIO.new(ghfm_spec_txt_contents) }
@ -22,6 +45,9 @@ RSpec.describe Glfm::UpdateSpecification, '#process' do
let(:glfm_internal_extension_examples_md_io) { StringIO.new(glfm_internal_extension_examples_md_contents) }
let(:glfm_spec_txt_path) { described_class::GLFM_SPEC_TXT_PATH }
let(:glfm_spec_txt_io) { StringIO.new }
let(:glfm_spec_html_path) { described_class::GLFM_SPEC_HTML_PATH }
let(:glfm_spec_html_io) { StringIO.new }
let(:markdown_tempfile_io) { StringIO.new }
let(:ghfm_spec_txt_contents) do
<<~MARKDOWN
@ -93,9 +119,10 @@ RSpec.describe Glfm::UpdateSpecification, '#process' do
# We mock out the URI and local file IO objects with real StringIO, instead of just mock
# objects. This gives better and more realistic coverage, while still avoiding
# actual network and filesystem I/O during the spec run.
allow_next_instance_of(URI::HTTP) do |instance|
allow(instance).to receive(:open).and_return(ghfm_spec_txt_uri_io)
end
# input files
allow(URI).to receive(:parse).with(ghfm_spec_txt_uri).and_return(ghfm_spec_txt_uri_parsed)
allow(ghfm_spec_txt_uri_parsed).to receive(:open).and_return(ghfm_spec_txt_uri_io)
allow(File).to receive(:open).with(ghfm_spec_md_path) { ghfm_spec_txt_local_io }
allow(File).to receive(:open).with(glfm_intro_md_path) { glfm_intro_md_io }
allow(File).to receive(:open).with(glfm_official_specification_examples_md_path) do
@ -104,7 +131,21 @@ RSpec.describe Glfm::UpdateSpecification, '#process' do
allow(File).to receive(:open).with(glfm_internal_extension_examples_md_path) do
glfm_internal_extension_examples_md_io
end
# output files
allow(File).to receive(:open).with(glfm_spec_txt_path, 'w') { glfm_spec_txt_io }
allow(File).to receive(:open).with(glfm_spec_html_path, 'w') { glfm_spec_html_io }
# Allow normal opening of Tempfile files created during script execution.
tempfile_basenames = [
described_class::MARKDOWN_TEMPFILE_BASENAME[0],
described_class::STATIC_HTML_TEMPFILE_BASENAME[0]
].join('|')
# NOTE: This approach with a single regex seems to be the only way this can work. If you
# attempt to have multiple `allow...and_call_original` with `any_args`, the mocked
# parameter matching will fail to match the second one.
tempfiles_regex = /(#{tempfile_basenames})/
allow(File).to receive(:open).with(tempfiles_regex, any_args).and_call_original
# Prevent console output when running tests
allow(subject).to receive(:output)
@ -115,7 +156,7 @@ RSpec.describe Glfm::UpdateSpecification, '#process' do
it 'does not download' do
expect(URI).not_to receive(:parse).with(ghfm_spec_txt_uri)
subject.process
subject.process(skip_spec_html_generation: true)
expect(reread_io(ghfm_spec_txt_local_io)).to eq(ghfm_spec_txt_contents)
end
@ -131,7 +172,7 @@ RSpec.describe Glfm::UpdateSpecification, '#process' do
context 'with success' do
it 'downloads and saves' do
subject.process
subject.process(skip_spec_html_generation: true)
expect(reread_io(ghfm_spec_txt_local_io)).to eq(ghfm_spec_txt_contents)
end
@ -149,7 +190,9 @@ RSpec.describe Glfm::UpdateSpecification, '#process' do
end
it 'raises an error' do
expect { subject.process }.to raise_error /version mismatch.*expected.*29.*got.*30/i
expect do
subject.process(skip_spec_html_generation: true)
end.to raise_error /version mismatch.*expected.*29.*got.*30/i
end
end
@ -157,7 +200,7 @@ RSpec.describe Glfm::UpdateSpecification, '#process' do
let(:ghfm_spec_txt_contents) { '' }
it 'raises an error if lines cannot be read' do
expect { subject.process }.to raise_error /unable to read lines/i
expect { subject.process(skip_spec_html_generation: true) }.to raise_error /unable to read lines/i
end
end
@ -167,7 +210,7 @@ RSpec.describe Glfm::UpdateSpecification, '#process' do
end
it 'raises an error if file is blank' do
expect { subject.process }.to raise_error /unable to read string/i
expect { subject.process(skip_spec_html_generation: true) }.to raise_error /unable to read string/i
end
end
end
@ -178,7 +221,7 @@ RSpec.describe Glfm::UpdateSpecification, '#process' do
let(:glfm_contents) { reread_io(glfm_spec_txt_io) }
before do
subject.process
subject.process(skip_spec_html_generation: true)
end
it 'replaces the header text with the GitLab version' do
@ -214,6 +257,51 @@ RSpec.describe Glfm::UpdateSpecification, '#process' do
end
end
describe 'writing GLFM spec.html' do
let(:glfm_contents) { reread_io(glfm_spec_html_io) }
before do
subject.process
end
it 'renders HTML from spec.txt', :unlimited_max_formatted_output_length do
expected = <<~HTML
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="1:1-4:3" class="code highlight js-syntax-highlight language-yaml" lang="yaml" data-lang-params="frontmatter" v-pre="true"><code><span id="LC1" class="line" lang="yaml"><span class="na">title</span><span class="pi">:</span> <span class="s">GitLab Flavored Markdown (GLFM) Spec</span></span>
<span id="LC2" class="line" lang="yaml"><span class="na">version</span><span class="pi">:</span> <span class="s">alpha</span></span></code></pre>
<copy-code></copy-code>
</div>
<h1 data-sourcepos="6:1-6:14" dir="auto">
<a id="user-content-introduction" class="anchor" href="#introduction" aria-hidden="true"></a>Introduction</h1>
<h2 data-sourcepos="8:1-8:36" dir="auto">
<a id="user-content-what-is-gitlab-flavored-markdown" class="anchor" href="#what-is-gitlab-flavored-markdown" aria-hidden="true"></a>What is GitLab Flavored Markdown?</h2>
<p data-sourcepos="10:1-10:42" dir="auto">Intro text about GitLab Flavored Markdown.</p>
<h1 data-sourcepos="12:1-12:23" dir="auto">
<a id="user-content-section-with-examples" class="anchor" href="#section-with-examples" aria-hidden="true"></a>Section with Examples</h1>
<h2 data-sourcepos="14:1-14:9" dir="auto">
<a id="user-content-strong" class="anchor" href="#strong" aria-hidden="true"></a>Strong</h2>
<div class="gl-relative markdown-code-block js-markdown-code">
<pre data-sourcepos="16:1-20:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">__bold__</span>
<span id="LC2" class="line" lang="plaintext">.</span>
<span id="LC3" class="line" lang="plaintext">&lt;p&gt;&lt;strong&gt;bold&lt;/strong&gt;&lt;/p&gt;</span></code></pre>
<copy-code></copy-code>
</div>
<p data-sourcepos="22:1-22:36" dir="auto">End of last GitHub examples section.</p>
<h1 data-sourcepos="24:1-24:46" dir="auto">
<a id="user-content-official-specification-section-with-examples" class="anchor" href="#official-specification-section-with-examples" aria-hidden="true"></a>Official Specification Section with Examples</h1>
<p data-sourcepos="26:1-26:14" dir="auto">Some examples.</p>
<h1 data-sourcepos="28:1-28:42" dir="auto">
<a id="user-content-internal-extension-section-with-examples" class="anchor" href="#internal-extension-section-with-examples" aria-hidden="true"></a>Internal Extension Section with Examples</h1>
<p data-sourcepos="30:1-30:14" dir="auto">Some examples.</p>
<h1 data-sourcepos="34:1-34:10" dir="auto">
<a id="user-content-appendix" class="anchor" href="#appendix" aria-hidden="true"></a>Appendix</h1>
<p data-sourcepos="36:1-36:14" dir="auto">Appendix text.</p>
HTML
expect(glfm_contents).to be == expected
end
end
def reread_io(io)
# Reset the io StringIO to the beginning position of the buffer
io.seek(0)

View File

@ -3,13 +3,40 @@
require 'spec_helper'
RSpec.describe Boards::Lists::ListService do
let(:user) { create(:user) }
let_it_be(:user) { create(:user) }
let_it_be(:group) { create(:group) }
RSpec.shared_examples 'FOSS lists only' do
context 'when board contains a non FOSS list' do
# This scenario may happen when there used to be an EE license and user downgraded
let!(:backlog_list) { create_backlog_list(board) }
let_it_be(:milestone) { create(:milestone, group: group) }
let_it_be(:assignee_list) do
list = build(:list, board: board, user_id: user.id, list_type: List.list_types[:assignee], position: 0)
list.save!(validate: false)
list
end
let_it_be(:milestone_list) do
list = build(:list, board: board, milestone_id: milestone.id, list_type: List.list_types[:milestone], position: 1) # rubocop:disable Layout/LineLength
list.save!(validate: false)
list
end
it "returns only FOSS board's lists" do
# just making sure these non FOSS lists actually exist on the board
expect(board.lists.with_types([List.list_types[:assignee], List.list_types[:milestone]]).count).to eq 2
# check that the FOSS lists are not returned from the service
expect(service.execute(board)).to match_array [backlog_list, list, board.lists.closed.first]
end
end
end
describe '#execute' do
let(:service) { described_class.new(parent, user) }
context 'when board parent is a project' do
let_it_be(:project) { create(:project) }
let_it_be(:project) { create(:project, group: group) }
let_it_be_with_reload(:board) { create(:board, project: project) }
let_it_be(:label) { create(:label, project: project) }
let_it_be(:list) { create(:list, board: board, label: label) }
@ -18,10 +45,10 @@ RSpec.describe Boards::Lists::ListService do
let(:parent) { project }
it_behaves_like 'lists list service'
it_behaves_like 'FOSS lists only'
end
context 'when board parent is a group' do
let_it_be(:group) { create(:group) }
let_it_be_with_reload(:board) { create(:board, group: group) }
let_it_be(:label) { create(:group_label, group: group) }
let_it_be(:list) { create(:list, board: board, label: label) }
@ -30,6 +57,7 @@ RSpec.describe Boards::Lists::ListService do
let(:parent) { group }
it_behaves_like 'lists list service'
it_behaves_like 'FOSS lists only'
end
def create_backlog_list(board)

View File

@ -27,14 +27,6 @@ RSpec.shared_examples 'boards listable model' do |list_factory|
.to eq([list1, list3, list4, list2])
end
end
describe '.without_types' do
it 'excludes lists of given types' do
lists = described_class.without_types([:label, :closed])
expect(lists).to match_array([list1])
end
end
end
describe '#destroyable?' do

View File

@ -6331,6 +6331,11 @@ graphql@^15.7.2:
resolved "https://registry.yarnpkg.com/graphql/-/graphql-15.7.2.tgz#85ab0eeb83722977151b3feb4d631b5f2ab287ef"
integrity sha512-AnnKk7hFQFmU/2I9YSQf3xw44ctnSFCfp3zE0N6W174gqe9fWG/2rKaKxROK7CcI3XtERpjEKFqts8o319Kf7A==
gridstack@^7.0.0:
version "7.0.0"
resolved "https://registry.yarnpkg.com/gridstack/-/gridstack-7.0.0.tgz#2d00b28efa8d22a8b9ad2640c8ab64b494bbfdc9"
integrity sha512-iBts/PRuqg6OQvdpv7A84p3RROxzXVSKjM3SJHrdl2pdDZKmIpGo2oxjdCHv6l+SzU2EuptcHd1Rqouocwl1Cg==
gzip-size@^6.0.0:
version "6.0.0"
resolved "https://registry.yarnpkg.com/gzip-size/-/gzip-size-6.0.0.tgz#065367fd50c239c0671cbcbad5be3e2eeb10e462"