Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
a300f4d5c7
commit
b556d0fab7
|
@ -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'
|
||||
|
|
|
@ -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'
|
||||
|
|
|
@ -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'
|
||||
|
|
3
Gemfile
3
Gemfile
|
@ -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
|
||||
|
|
|
@ -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"},
|
||||
|
|
16
Gemfile.lock
16
Gemfile.lock
|
@ -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)
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
@import 'gridstack/dist/gridstack';
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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?
|
||||
|
|
|
@ -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.')
|
||||
|
|
|
@ -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?
|
||||
|
|
|
@ -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?
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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:
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
```
|
||||
|
|
|
@ -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
|
||||
}
|
||||
```
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 -->
|
||||
|
|
|
@ -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).
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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')
|
||||
}
|
||||
```
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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.
|
|
@ -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
|
@ -6,6 +6,7 @@ module API
|
|||
expose :admin?, as: :is_admin
|
||||
expose :note
|
||||
expose :namespace_id
|
||||
expose :created_by, with: UserBasic
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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'
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 "-----"
|
||||
|
|
|
@ -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 ""
|
||||
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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__)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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"><p><strong>bold</strong></p></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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
|
Loading…
Reference in New Issue