Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2022-10-07 00:08:16 +00:00
parent ca3ff7f842
commit b3e461ab0f
46 changed files with 797 additions and 282 deletions

View File

@ -1,11 +1,10 @@
--- ---
# Cop supports --auto-correct. # Cop supports --auto-correct.
Style/ExplicitBlockArgument: Style/ExplicitBlockArgument:
# Offense count: 143 Details: grace period
# Temporarily disabled due to too many offenses
Enabled: false
Exclude: Exclude:
- 'app/controllers/admin/background_migrations_controller.rb' - 'app/controllers/admin/background_migrations_controller.rb'
- 'app/controllers/admin/batched_jobs_controller.rb'
- 'app/controllers/application_controller.rb' - 'app/controllers/application_controller.rb'
- 'app/models/application_record.rb' - 'app/models/application_record.rb'
- 'app/models/broadcast_message.rb' - 'app/models/broadcast_message.rb'
@ -14,13 +13,14 @@ Style/ExplicitBlockArgument:
- 'app/models/ci/build_trace_chunks/redis_trace_chunks.rb' - 'app/models/ci/build_trace_chunks/redis_trace_chunks.rb'
- 'app/models/concerns/counter_attribute.rb' - 'app/models/concerns/counter_attribute.rb'
- 'app/models/merge_request.rb' - 'app/models/merge_request.rb'
- 'app/models/merge_request_diff.rb'
- 'app/models/snippet_repository.rb' - 'app/models/snippet_repository.rb'
- 'app/services/import_export_clean_up_service.rb' - 'app/services/import_export_clean_up_service.rb'
- 'app/services/packages/debian/generate_distribution_key_service.rb' - 'app/services/packages/debian/generate_distribution_key_service.rb'
- 'app/workers/concerns/each_shard_worker.rb' - 'app/workers/concerns/each_shard_worker.rb'
- 'db/migrate/20210629031900_associate_existing_dast_builds_with_variables.rb'
- 'ee/app/services/gitlab_subscriptions/fetch_subscription_plans_service.rb' - 'ee/app/services/gitlab_subscriptions/fetch_subscription_plans_service.rb'
- 'ee/app/services/group_saml/identity/destroy_service.rb' - 'ee/app/services/group_saml/identity/destroy_service.rb'
- 'ee/app/services/security/security_orchestration_policies/base_merge_requests_service.rb'
- 'ee/lib/ee/backup/repositories.rb' - 'ee/lib/ee/backup/repositories.rb'
- 'ee/lib/ee/gitlab/background_migration/migrate_approver_to_approval_rules.rb' - 'ee/lib/ee/gitlab/background_migration/migrate_approver_to_approval_rules.rb'
- 'ee/lib/gitlab/audit/events/preloader.rb' - 'ee/lib/gitlab/audit/events/preloader.rb'
@ -44,6 +44,7 @@ Style/ExplicitBlockArgument:
- 'lib/gitlab/ci/variables/collection.rb' - 'lib/gitlab/ci/variables/collection.rb'
- 'lib/gitlab/cleanup/remote_uploads.rb' - 'lib/gitlab/cleanup/remote_uploads.rb'
- 'lib/gitlab/database/dynamic_model_helpers.rb' - 'lib/gitlab/database/dynamic_model_helpers.rb'
- 'lib/gitlab/database/lock_writes_manager.rb'
- 'lib/gitlab/database/reindexing/reindex_concurrently.rb' - 'lib/gitlab/database/reindexing/reindex_concurrently.rb'
- 'lib/gitlab/git/changes.rb' - 'lib/gitlab/git/changes.rb'
- 'lib/gitlab/gitaly_client/list_blobs_adapter.rb' - 'lib/gitlab/gitaly_client/list_blobs_adapter.rb'
@ -58,16 +59,20 @@ Style/ExplicitBlockArgument:
- 'lib/gitlab/import_export/project/base_task.rb' - 'lib/gitlab/import_export/project/base_task.rb'
- 'lib/gitlab/import_export/project/export_task.rb' - 'lib/gitlab/import_export/project/export_task.rb'
- 'lib/gitlab/import_export/project/import_task.rb' - 'lib/gitlab/import_export/project/import_task.rb'
- 'lib/gitlab/import_export/remote_stream_upload.rb'
- 'lib/gitlab/issuable/clone/copy_resource_events_service.rb'
- 'lib/gitlab/metrics/dashboard/cache.rb' - 'lib/gitlab/metrics/dashboard/cache.rb'
- 'lib/gitlab/metrics/dashboard/stages/base_stage.rb' - 'lib/gitlab/metrics/dashboard/stages/base_stage.rb'
- 'lib/gitlab/profiler.rb' - 'lib/gitlab/profiler.rb'
- 'lib/gitlab/redis/wrapper.rb' - 'lib/gitlab/redis/wrapper.rb'
- 'lib/gitlab/reference_counter.rb' - 'lib/gitlab/reference_counter.rb'
- 'lib/gitlab/seeder.rb' - 'lib/gitlab/seeder.rb'
- 'lib/gitlab/sidekiq_middleware/duplicate_jobs/duplicate_job.rb'
- 'lib/gitlab/sidekiq_middleware/monitor.rb' - 'lib/gitlab/sidekiq_middleware/monitor.rb'
- 'lib/gitlab/sidekiq_middleware/query_analyzer.rb' - 'lib/gitlab/sidekiq_middleware/query_analyzer.rb'
- 'lib/gitlab/sidekiq_middleware/request_store_middleware.rb' - 'lib/gitlab/sidekiq_middleware/request_store_middleware.rb'
- 'lib/gitlab/sidekiq_middleware/server_metrics.rb' - 'lib/gitlab/sidekiq_middleware/server_metrics.rb'
- 'lib/gitlab/sidekiq_status.rb'
- 'lib/gitlab/utils/measuring.rb' - 'lib/gitlab/utils/measuring.rb'
- 'lib/tasks/config_lint.rake' - 'lib/tasks/config_lint.rake'
- 'qa/qa/ee/page/insights/show.rb' - 'qa/qa/ee/page/insights/show.rb'
@ -87,7 +92,6 @@ Style/ExplicitBlockArgument:
- 'qa/qa/resource/events/base.rb' - 'qa/qa/resource/events/base.rb'
- 'qa/qa/runtime/api/repository_storage_moves.rb' - 'qa/qa/runtime/api/repository_storage_moves.rb'
- 'qa/qa/runtime/search.rb' - 'qa/qa/runtime/search.rb'
- 'qa/qa/specs/features/browser_ui/3_create/repository/push_over_http_file_size_spec.rb'
- 'rubocop/code_reuse_helpers.rb' - 'rubocop/code_reuse_helpers.rb'
- 'spec/features/merge_request/user_sees_wip_help_message_spec.rb' - 'spec/features/merge_request/user_sees_wip_help_message_spec.rb'
- 'spec/features/projects/features_visibility_spec.rb' - 'spec/features/projects/features_visibility_spec.rb'
@ -99,9 +103,10 @@ Style/ExplicitBlockArgument:
- 'spec/models/repository_spec.rb' - 'spec/models/repository_spec.rb'
- 'spec/services/pages/zip_directory_service_spec.rb' - 'spec/services/pages/zip_directory_service_spec.rb'
- 'spec/services/todo_service_spec.rb' - 'spec/services/todo_service_spec.rb'
- 'spec/support/database/gitlab_schemas_validate_connection.rb'
- 'spec/support/helpers/feature_flag_helpers.rb' - 'spec/support/helpers/feature_flag_helpers.rb'
- 'spec/support/helpers/features/runners_helpers.rb'
- 'spec/support/helpers/features/top_nav_spec_helpers.rb' - 'spec/support/helpers/features/top_nav_spec_helpers.rb'
- 'spec/support/helpers/graphql_helpers.rb'
- 'spec/support/helpers/modal_helpers.rb' - 'spec/support/helpers/modal_helpers.rb'
- 'spec/support/helpers/next_found_instance_of.rb' - 'spec/support/helpers/next_found_instance_of.rb'
- 'spec/support/helpers/usage_data_helpers.rb' - 'spec/support/helpers/usage_data_helpers.rb'

12
Gemfile
View File

@ -76,7 +76,7 @@ gem 'omniauth-authentiq', '~> 0.3.3'
gem 'gitlab-omniauth-openid-connect', '~> 0.10.0', require: 'omniauth_openid_connect' gem 'gitlab-omniauth-openid-connect', '~> 0.10.0', require: 'omniauth_openid_connect'
gem 'omniauth-salesforce', '~> 1.0.5', path: 'vendor/gems/omniauth-salesforce' # See gem README.md gem 'omniauth-salesforce', '~> 1.0.5', path: 'vendor/gems/omniauth-salesforce' # See gem README.md
gem 'omniauth-atlassian-oauth2', '~> 0.2.0' gem 'omniauth-atlassian-oauth2', '~> 0.2.0'
gem 'rack-oauth2', '~> 1.21.2' gem 'rack-oauth2', '~> 1.21.3'
gem 'jwt', '~> 2.1.0' gem 'jwt', '~> 2.1.0'
# Kerberos authentication. EE-only # Kerberos authentication. EE-only
@ -118,7 +118,7 @@ gem 'net-ldap', '~> 0.16.3'
# API # API
gem 'grape', '~> 1.5.2' gem 'grape', '~> 1.5.2'
gem 'grape-entity', '~> 0.10.0' gem 'grape-entity', '~> 0.10.0'
gem 'rack-cors', '~> 1.1.0', require: 'rack/cors' gem 'rack-cors', '~> 1.1.1', require: 'rack/cors'
# GraphQL API # GraphQL API
gem 'graphql', '~> 1.13.12' gem 'graphql', '~> 1.13.12'
@ -166,7 +166,7 @@ gem 'seed-fu', '~> 2.3.7'
gem 'elasticsearch-model', '~> 7.2' gem 'elasticsearch-model', '~> 7.2'
gem 'elasticsearch-rails', '~> 7.2', require: 'elasticsearch/rails/instrumentation' gem 'elasticsearch-rails', '~> 7.2', require: 'elasticsearch/rails/instrumentation'
gem 'elasticsearch-api', '7.13.3' gem 'elasticsearch-api', '7.13.3'
gem 'aws-sdk-core', '~> 3.131.0' gem 'aws-sdk-core', '~> 3.156.0'
gem 'aws-sdk-cloudformation', '~> 1' gem 'aws-sdk-cloudformation', '~> 1'
gem 'aws-sdk-s3', '~> 1.114.0' gem 'aws-sdk-s3', '~> 1.114.0'
gem 'faraday_middleware-aws-sigv4', '~>0.3.0' gem 'faraday_middleware-aws-sigv4', '~>0.3.0'
@ -204,7 +204,7 @@ gem 'diff_match_patch', '~> 0.1.0'
# Application server # Application server
gem 'rack', '~> 2.2.4' gem 'rack', '~> 2.2.4'
# https://github.com/zombocom/rack-timeout/blob/master/README.md#rails-apps-manually # https://github.com/zombocom/rack-timeout/blob/master/README.md#rails-apps-manually
gem 'rack-timeout', '~> 0.6.0', require: 'rack/timeout/base' gem 'rack-timeout', '~> 0.6.3', require: 'rack/timeout/base'
group :puma do group :puma do
gem 'puma', '~> 5.6.5', require: false gem 'puma', '~> 5.6.5', require: false
@ -309,7 +309,7 @@ gem 'fast_blank'
gem 'gitlab-chronic', '~> 0.10.5' gem 'gitlab-chronic', '~> 0.10.5'
gem 'gitlab_chronic_duration', '~> 0.10.6.2' gem 'gitlab_chronic_duration', '~> 0.10.6.2'
gem 'rack-proxy', '~> 0.7.2' gem 'rack-proxy', '~> 0.7.4'
gem 'sassc-rails', '~> 2.1.0' gem 'sassc-rails', '~> 2.1.0'
gem 'autoprefixer-rails', '10.2.5.1' gem 'autoprefixer-rails', '10.2.5.1'
@ -324,7 +324,7 @@ gem 'base32', '~> 0.3.0'
gem 'gitlab-license', '~> 2.2.1' gem 'gitlab-license', '~> 2.2.1'
# Protect against bruteforcing # Protect against bruteforcing
gem 'rack-attack', '~> 6.6.0' gem 'rack-attack', '~> 6.6.1'
# Sentry integration # Sentry integration
gem 'sentry-raven', '~> 3.1' gem 'sentry-raven', '~> 3.1'

View File

@ -31,12 +31,12 @@
{"name":"awesome_print","version":"1.9.2","platform":"ruby","checksum":"e99b32b704acff16d768b3468680793ced40bfdc4537eb07e06a4be11133786e"}, {"name":"awesome_print","version":"1.9.2","platform":"ruby","checksum":"e99b32b704acff16d768b3468680793ced40bfdc4537eb07e06a4be11133786e"},
{"name":"awrence","version":"1.1.1","platform":"ruby","checksum":"9be584c97408ed92d5e1ca11740853646fe270de675f2f8dd44e8233226dfc97"}, {"name":"awrence","version":"1.1.1","platform":"ruby","checksum":"9be584c97408ed92d5e1ca11740853646fe270de675f2f8dd44e8233226dfc97"},
{"name":"aws-eventstream","version":"1.2.0","platform":"ruby","checksum":"ffa53482c92880b001ff2fb06919b9bb82fd847cbb0fa244985d2ebb6dd0d1df"}, {"name":"aws-eventstream","version":"1.2.0","platform":"ruby","checksum":"ffa53482c92880b001ff2fb06919b9bb82fd847cbb0fa244985d2ebb6dd0d1df"},
{"name":"aws-partitions","version":"1.600.0","platform":"ruby","checksum":"23592386dd0bb34c38fae2714eb1ab5c18fbef714f22b042815a92fdd51fa733"}, {"name":"aws-partitions","version":"1.638.0","platform":"ruby","checksum":"8dfe833a15e81cd586b2a9bc624c4800d6e4b003aa76f2e588972fd78be3941f"},
{"name":"aws-sdk-cloudformation","version":"1.41.0","platform":"ruby","checksum":"31e47539719734413671edf9b1a31f8673fbf9688549f50c41affabbcb1c6b26"}, {"name":"aws-sdk-cloudformation","version":"1.41.0","platform":"ruby","checksum":"31e47539719734413671edf9b1a31f8673fbf9688549f50c41affabbcb1c6b26"},
{"name":"aws-sdk-core","version":"3.131.1","platform":"ruby","checksum":"481c602d682b61abccb4e9f5b64750907bb49758f6f31b3bec599819951a3f7a"}, {"name":"aws-sdk-core","version":"3.156.0","platform":"ruby","checksum":"0975d3894936dbaf9120dac7781245f177e8ba8f109100bd86a0711d4f9ee01d"},
{"name":"aws-sdk-kms","version":"1.57.0","platform":"ruby","checksum":"ffd7dbb9b4251f29d4f508af761d0addd7035a346a88e3481cdb4dc548e51bd5"}, {"name":"aws-sdk-kms","version":"1.57.0","platform":"ruby","checksum":"ffd7dbb9b4251f29d4f508af761d0addd7035a346a88e3481cdb4dc548e51bd5"},
{"name":"aws-sdk-s3","version":"1.114.0","platform":"ruby","checksum":"ce0f71df1a7b0fb1f88d40a70636ef1a9b08e69fb560694c5dab3f4ac7efcde4"}, {"name":"aws-sdk-s3","version":"1.114.0","platform":"ruby","checksum":"ce0f71df1a7b0fb1f88d40a70636ef1a9b08e69fb560694c5dab3f4ac7efcde4"},
{"name":"aws-sigv4","version":"1.5.0","platform":"ruby","checksum":"3f81c08bacabec6cbc77ebbbac755ca6132a74a4a3279afbde64db83796ce776"}, {"name":"aws-sigv4","version":"1.5.1","platform":"ruby","checksum":"d68c87fff4ee843b4b92b23c7f31f957f254ec6eb064181f7119124aab8b8bb4"},
{"name":"azure-storage-blob","version":"2.0.3","platform":"ruby","checksum":"61b76118843c91776bd24bee22c74adafeb7c4bb3a858a325047dae3b59d0363"}, {"name":"azure-storage-blob","version":"2.0.3","platform":"ruby","checksum":"61b76118843c91776bd24bee22c74adafeb7c4bb3a858a325047dae3b59d0363"},
{"name":"azure-storage-common","version":"2.0.4","platform":"ruby","checksum":"608f4daab0e06b583b73dcffd3246ea39e78056de31630286b0cf97af7d6956b"}, {"name":"azure-storage-common","version":"2.0.4","platform":"ruby","checksum":"608f4daab0e06b583b73dcffd3246ea39e78056de31630286b0cf97af7d6956b"},
{"name":"babosa","version":"1.0.4","platform":"ruby","checksum":"18dea450f595462ed7cb80595abd76b2e535db8c91b350f6c4b3d73986c5bc99"}, {"name":"babosa","version":"1.0.4","platform":"ruby","checksum":"18dea450f595462ed7cb80595abd76b2e535db8c91b350f6c4b3d73986c5bc99"},
@ -52,7 +52,7 @@
{"name":"benchmark-perf","version":"0.6.0","platform":"ruby","checksum":"fe2b01959f3de0f9dd34820d54ef881eb4f3589fccb7d17b63068ac92d7f9621"}, {"name":"benchmark-perf","version":"0.6.0","platform":"ruby","checksum":"fe2b01959f3de0f9dd34820d54ef881eb4f3589fccb7d17b63068ac92d7f9621"},
{"name":"benchmark-trend","version":"0.4.0","platform":"ruby","checksum":"de5a02a9f443babefbbd97784759820decee8554a0c273d859c02a0990845d81"}, {"name":"benchmark-trend","version":"0.4.0","platform":"ruby","checksum":"de5a02a9f443babefbbd97784759820decee8554a0c273d859c02a0990845d81"},
{"name":"better_errors","version":"2.9.1","platform":"ruby","checksum":"39efc116ab04d6c4200052c5782936e4bd99906978d098992bce6bf81d054284"}, {"name":"better_errors","version":"2.9.1","platform":"ruby","checksum":"39efc116ab04d6c4200052c5782936e4bd99906978d098992bce6bf81d054284"},
{"name":"bindata","version":"2.4.10","platform":"ruby","checksum":"798b5e3ec00e9d562243076b819c16b1e226eb176d5b7b5cd21417bc3589981a"}, {"name":"bindata","version":"2.4.11","platform":"ruby","checksum":"c38e0c99ffcd80c10a0a7ae6c8586d2fe26bf245cbefac90bec8764523220f6a"},
{"name":"binding_ninja","version":"0.2.3","platform":"java","checksum":"bbcf70b211d6e397493bf57c249bbec6aaf28fa7dafeb78e447b1b2f0610484f"}, {"name":"binding_ninja","version":"0.2.3","platform":"java","checksum":"bbcf70b211d6e397493bf57c249bbec6aaf28fa7dafeb78e447b1b2f0610484f"},
{"name":"binding_ninja","version":"0.2.3","platform":"ruby","checksum":"4a85550a0066ee4721506b4e150857486808e50c9ddfeed04bdc896bb61eca9d"}, {"name":"binding_ninja","version":"0.2.3","platform":"ruby","checksum":"4a85550a0066ee4721506b4e150857486808e50c9ddfeed04bdc896bb61eca9d"},
{"name":"bootsnap","version":"1.13.0","platform":"ruby","checksum":"c673282ec0f48506f093ca9acefe0f666d1ab9fda716e49fb95c9fe677653e78"}, {"name":"bootsnap","version":"1.13.0","platform":"ruby","checksum":"c673282ec0f48506f093ca9acefe0f666d1ab9fda716e49fb95c9fe677653e78"},
@ -284,7 +284,7 @@
{"name":"js_regex","version":"3.7.0","platform":"ruby","checksum":"b13fac68c4416d1a5f21c3bab8a71b4530f424b7c4ff9f46d8e62b895dc05975"}, {"name":"js_regex","version":"3.7.0","platform":"ruby","checksum":"b13fac68c4416d1a5f21c3bab8a71b4530f424b7c4ff9f46d8e62b895dc05975"},
{"name":"json","version":"2.5.1","platform":"java","checksum":"be284a0c4a9d0373e81b0d5dfe71ed5b18d0479f05970e60a77be89a2978ce6c"}, {"name":"json","version":"2.5.1","platform":"java","checksum":"be284a0c4a9d0373e81b0d5dfe71ed5b18d0479f05970e60a77be89a2978ce6c"},
{"name":"json","version":"2.5.1","platform":"ruby","checksum":"918d8c41dacb7cfdbe0c7bbd6014a5372f0cf1c454ca150e9f4010fe80cc3153"}, {"name":"json","version":"2.5.1","platform":"ruby","checksum":"918d8c41dacb7cfdbe0c7bbd6014a5372f0cf1c454ca150e9f4010fe80cc3153"},
{"name":"json-jwt","version":"1.13.0","platform":"ruby","checksum":"b9bded80ba687e59d199db365731494ee68214f27d0d7be5b635b9956b98eb5b"}, {"name":"json-jwt","version":"1.15.3","platform":"ruby","checksum":"66db4f14e538a774c15502a5b5b26b1f3e7585481bbb96df490aa74b5c2d6110"},
{"name":"json_schemer","version":"0.2.18","platform":"ruby","checksum":"3362c21efbefdd12ce994e541a1e7fdb86fd267a6541dd8715e8a580fe3b6be6"}, {"name":"json_schemer","version":"0.2.18","platform":"ruby","checksum":"3362c21efbefdd12ce994e541a1e7fdb86fd267a6541dd8715e8a580fe3b6be6"},
{"name":"jsonpath","version":"1.1.2","platform":"ruby","checksum":"6804124c244d04418218acb85b15c7caa79c592d7d6970195300428458946d3a"}, {"name":"jsonpath","version":"1.1.2","platform":"ruby","checksum":"6804124c244d04418218acb85b15c7caa79c592d7d6970195300428458946d3a"},
{"name":"jwt","version":"2.1.0","platform":"ruby","checksum":"7e7e7ffc1a5ebce628ac7da428341c50615a3a10ac47bb74c22c1cba325613f0"}, {"name":"jwt","version":"2.1.0","platform":"ruby","checksum":"7e7e7ffc1a5ebce628ac7da428341c50615a3a10ac47bb74c22c1cba325613f0"},
@ -430,11 +430,11 @@
{"name":"rack-accept","version":"0.4.5","platform":"ruby","checksum":"66247b5449db64ebb93ae2ec4af4764b87d1ae8a7463c7c68893ac13fa8d4da2"}, {"name":"rack-accept","version":"0.4.5","platform":"ruby","checksum":"66247b5449db64ebb93ae2ec4af4764b87d1ae8a7463c7c68893ac13fa8d4da2"},
{"name":"rack-attack","version":"6.6.1","platform":"ruby","checksum":"187e5d248c6a162ed8cafa8241a7b5947d9b9cf122a4870eb1cdd0db861f3a11"}, {"name":"rack-attack","version":"6.6.1","platform":"ruby","checksum":"187e5d248c6a162ed8cafa8241a7b5947d9b9cf122a4870eb1cdd0db861f3a11"},
{"name":"rack-cors","version":"1.1.1","platform":"ruby","checksum":"4702644ac6d63ebbddff372a3cd4cd573513287e3524b5a5415f678970057a4b"}, {"name":"rack-cors","version":"1.1.1","platform":"ruby","checksum":"4702644ac6d63ebbddff372a3cd4cd573513287e3524b5a5415f678970057a4b"},
{"name":"rack-oauth2","version":"1.21.2","platform":"ruby","checksum":"06fc157cad243ac11d8681c18139c4556a3f86b518f0fcb419e29512181a3ff2"}, {"name":"rack-oauth2","version":"1.21.3","platform":"ruby","checksum":"4e72a79dd6a866692e84422a552b27c38a5a1918ded06661e04910f2bbe676ba"},
{"name":"rack-protection","version":"2.2.2","platform":"ruby","checksum":"fd41414dbabbec274af0bdb1f72a48504449de4d979782c9af38cbb5dfff3299"}, {"name":"rack-protection","version":"2.2.2","platform":"ruby","checksum":"fd41414dbabbec274af0bdb1f72a48504449de4d979782c9af38cbb5dfff3299"},
{"name":"rack-proxy","version":"0.7.2","platform":"ruby","checksum":"89c74fd6d3e5a4db0ed7e0d8b9915dbc85360fd6f98f6c1f9a66479fe236f4b6"}, {"name":"rack-proxy","version":"0.7.4","platform":"ruby","checksum":"a8bb373583d8a3165d8caf5af5fd7c32c9e8a91b983fbc531efa0e3d6617d2d4"},
{"name":"rack-test","version":"1.1.0","platform":"ruby","checksum":"154161f40f162b1c009a655b7b0c5de3a3102cc6d7d2e94b64e1f46ace800866"}, {"name":"rack-test","version":"1.1.0","platform":"ruby","checksum":"154161f40f162b1c009a655b7b0c5de3a3102cc6d7d2e94b64e1f46ace800866"},
{"name":"rack-timeout","version":"0.6.0","platform":"ruby","checksum":"6038d1cc31936394bd2c57bb16c17b31d2fd1d33ce928537cf0ef6f1f1905099"}, {"name":"rack-timeout","version":"0.6.3","platform":"ruby","checksum":"1754892eacc124d405e7f1145731ec9b7421ebd1bee5d51ddc18b72c204d0ab3"},
{"name":"rails","version":"6.1.6.1","platform":"ruby","checksum":"17024921a3913fb341f584542b06adf6bb12977a8b92d5fce093c3996c963686"}, {"name":"rails","version":"6.1.6.1","platform":"ruby","checksum":"17024921a3913fb341f584542b06adf6bb12977a8b92d5fce093c3996c963686"},
{"name":"rails-controller-testing","version":"1.0.5","platform":"ruby","checksum":"741448db59366073e86fc965ba403f881c636b79a2c39a48d0486f2607182e94"}, {"name":"rails-controller-testing","version":"1.0.5","platform":"ruby","checksum":"741448db59366073e86fc965ba403f881c636b79a2c39a48d0486f2607182e94"},
{"name":"rails-dom-testing","version":"2.0.3","platform":"ruby","checksum":"b140c4f39f6e609c8113137b9a60dfc2ecb89864e496f87f23a68b3b8f12d8d1"}, {"name":"rails-dom-testing","version":"2.0.3","platform":"ruby","checksum":"b140c4f39f6e609c8113137b9a60dfc2ecb89864e496f87f23a68b3b8f12d8d1"},

View File

@ -190,11 +190,11 @@ GEM
awesome_print (1.9.2) awesome_print (1.9.2)
awrence (1.1.1) awrence (1.1.1)
aws-eventstream (1.2.0) aws-eventstream (1.2.0)
aws-partitions (1.600.0) aws-partitions (1.638.0)
aws-sdk-cloudformation (1.41.0) aws-sdk-cloudformation (1.41.0)
aws-sdk-core (~> 3, >= 3.99.0) aws-sdk-core (~> 3, >= 3.99.0)
aws-sigv4 (~> 1.1) aws-sigv4 (~> 1.1)
aws-sdk-core (3.131.1) aws-sdk-core (3.156.0)
aws-eventstream (~> 1, >= 1.0.2) aws-eventstream (~> 1, >= 1.0.2)
aws-partitions (~> 1, >= 1.525.0) aws-partitions (~> 1, >= 1.525.0)
aws-sigv4 (~> 1.1) aws-sigv4 (~> 1.1)
@ -206,7 +206,7 @@ GEM
aws-sdk-core (~> 3, >= 3.127.0) aws-sdk-core (~> 3, >= 3.127.0)
aws-sdk-kms (~> 1) aws-sdk-kms (~> 1)
aws-sigv4 (~> 1.4) aws-sigv4 (~> 1.4)
aws-sigv4 (1.5.0) aws-sigv4 (1.5.1)
aws-eventstream (~> 1, >= 1.0.2) aws-eventstream (~> 1, >= 1.0.2)
azure-storage-blob (2.0.3) azure-storage-blob (2.0.3)
azure-storage-common (~> 2.0) azure-storage-common (~> 2.0)
@ -232,7 +232,7 @@ GEM
coderay (>= 1.0.0) coderay (>= 1.0.0)
erubi (>= 1.0.0) erubi (>= 1.0.0)
rack (>= 0.9.0) rack (>= 0.9.0)
bindata (2.4.10) bindata (2.4.11)
binding_ninja (0.2.3) binding_ninja (0.2.3)
bootsnap (1.13.0) bootsnap (1.13.0)
msgpack (~> 1.2) msgpack (~> 1.2)
@ -761,10 +761,11 @@ GEM
regexp_parser (~> 2.1) regexp_parser (~> 2.1)
regexp_property_values (~> 1.0) regexp_property_values (~> 1.0)
json (2.5.1) json (2.5.1)
json-jwt (1.13.0) json-jwt (1.15.3)
activesupport (>= 4.2) activesupport (>= 4.2)
aes_key_wrap aes_key_wrap
bindata bindata
httpclient
json_schemer (0.2.18) json_schemer (0.2.18)
ecma-re-validator (~> 0.3) ecma-re-validator (~> 0.3)
hana (~> 1.3) hana (~> 1.3)
@ -1070,7 +1071,7 @@ GEM
rack (>= 1.0, < 3) rack (>= 1.0, < 3)
rack-cors (1.1.1) rack-cors (1.1.1)
rack (>= 2.0.0) rack (>= 2.0.0)
rack-oauth2 (1.21.2) rack-oauth2 (1.21.3)
activesupport activesupport
attr_required attr_required
httpclient httpclient
@ -1078,11 +1079,11 @@ GEM
rack (>= 2.1.0) rack (>= 2.1.0)
rack-protection (2.2.2) rack-protection (2.2.2)
rack rack
rack-proxy (0.7.2) rack-proxy (0.7.4)
rack rack
rack-test (1.1.0) rack-test (1.1.0)
rack (>= 1.0, < 3) rack (>= 1.0, < 3)
rack-timeout (0.6.0) rack-timeout (0.6.3)
rails (6.1.6.1) rails (6.1.6.1)
actioncable (= 6.1.6.1) actioncable (= 6.1.6.1)
actionmailbox (= 6.1.6.1) actionmailbox (= 6.1.6.1)
@ -1544,7 +1545,7 @@ DEPENDENCIES
autoprefixer-rails (= 10.2.5.1) autoprefixer-rails (= 10.2.5.1)
awesome_print awesome_print
aws-sdk-cloudformation (~> 1) aws-sdk-cloudformation (~> 1)
aws-sdk-core (~> 3.131.0) aws-sdk-core (~> 3.156.0)
aws-sdk-s3 (~> 1.114.0) aws-sdk-s3 (~> 1.114.0)
babosa (~> 1.0.4) babosa (~> 1.0.4)
base32 (~> 0.3.0) base32 (~> 0.3.0)
@ -1730,11 +1731,11 @@ DEPENDENCIES
puma (~> 5.6.5) puma (~> 5.6.5)
puma_worker_killer (~> 0.3.1) puma_worker_killer (~> 0.3.1)
rack (~> 2.2.4) rack (~> 2.2.4)
rack-attack (~> 6.6.0) rack-attack (~> 6.6.1)
rack-cors (~> 1.1.0) rack-cors (~> 1.1.1)
rack-oauth2 (~> 1.21.2) rack-oauth2 (~> 1.21.3)
rack-proxy (~> 0.7.2) rack-proxy (~> 0.7.4)
rack-timeout (~> 0.6.0) rack-timeout (~> 0.6.3)
rails (~> 6.1.6.1) rails (~> 6.1.6.1)
rails-controller-testing rails-controller-testing
rails-i18n (~> 7.0) rails-i18n (~> 7.0)

View File

@ -12,22 +12,6 @@ module MarkupHelper
# https://gitlab.com/gitlab-org/gitlab/-/issues/365358 # https://gitlab.com/gitlab-org/gitlab/-/issues/365358
RENDER_TIMEOUT = 5.seconds RENDER_TIMEOUT = 5.seconds
def plain?(filename)
Gitlab::MarkupHelper.plain?(filename)
end
def markup?(filename)
Gitlab::MarkupHelper.markup?(filename)
end
def gitlab_markdown?(filename)
Gitlab::MarkupHelper.gitlab_markdown?(filename)
end
def asciidoc?(filename)
Gitlab::MarkupHelper.asciidoc?(filename)
end
# Use this in places where you would normally use link_to(gfm(...), ...). # Use this in places where you would normally use link_to(gfm(...), ...).
def link_to_markdown(body, url, html_options = {}) def link_to_markdown(body, url, html_options = {})
return '' if body.blank? return '' if body.blank?
@ -146,11 +130,11 @@ module MarkupHelper
return '' unless text.present? return '' unless text.present?
markup = proc do markup = proc do
if gitlab_markdown?(file_name) if Gitlab::MarkupHelper.gitlab_markdown?(file_name)
markdown_unsafe(text, context) markdown_unsafe(text, context)
elsif asciidoc?(file_name) elsif Gitlab::MarkupHelper.asciidoc?(file_name)
asciidoc_unsafe(text, context) asciidoc_unsafe(text, context)
elsif plain?(file_name) elsif Gitlab::MarkupHelper.plain?(file_name)
plain_unsafe(text) plain_unsafe(text)
else else
other_markup_unsafe(file_name, text, context) other_markup_unsafe(file_name, text, context)

View File

@ -350,7 +350,7 @@ class Snippet < ApplicationRecord
end end
def can_cache_field?(field) def can_cache_field?(field)
field != :content || MarkupHelper.gitlab_markdown?(file_name) field != :content || Gitlab::MarkupHelper.gitlab_markdown?(file_name)
end end
def hexdigest def hexdigest

View File

@ -1,7 +1,6 @@
# frozen_string_literal: true # frozen_string_literal: true
class Tree class Tree
include Gitlab::MarkupHelper
include Gitlab::Utils::StrongMemoize include Gitlab::Utils::StrongMemoize
attr_accessor :repository, :sha, :path, :entries, :cursor attr_accessor :repository, :sha, :path, :entries, :cursor
@ -24,11 +23,11 @@ class Tree
end end
previewable_readmes = available_readmes.select do |blob| previewable_readmes = available_readmes.select do |blob|
previewable?(blob.name) Gitlab::MarkupHelper.previewable?(blob.name)
end end
plain_readmes = available_readmes.select do |blob| plain_readmes = available_readmes.select do |blob|
plain?(blob.name) Gitlab::MarkupHelper.plain?(blob.name)
end end
# Prioritize previewable over plain readmes # Prioritize previewable over plain readmes

View File

@ -20,7 +20,7 @@ module Ci
def execute def execute
in_lock(EXCLUSIVE_LOCK_KEY, ttl: LOCK_TIMEOUT, retries: 1) do in_lock(EXCLUSIVE_LOCK_KEY, ttl: LOCK_TIMEOUT, retries: 1) do
destroy_unlocked_pipeline_artifacts if ::Feature.enabled?(:ci_destroy_unlocked_pipeline_artifacts) destroy_unlocked_pipeline_artifacts
legacy_destroy_pipeline_artifacts legacy_destroy_pipeline_artifacts
end end

View File

@ -1,4 +1,4 @@
- if markup?(@blob.name) - if Gitlab::MarkupHelper.markup?(@blob.name)
.file-content.md .file-content.md
= markup(@blob.name, @content) = markup(@blob.name, @content)
- else - else

View File

@ -1,8 +0,0 @@
---
name: ci_destroy_unlocked_pipeline_artifacts
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/98633
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/375011
milestone: '15.5'
type: development
group: group::pipeline insights
default_enabled: false

View File

@ -0,0 +1,28 @@
# frozen_string_literal: true
class ScheduleResetDuplicateCiRunnersTokenValues < Gitlab::Database::Migration[2.0]
restrict_gitlab_migration gitlab_schema: :gitlab_ci
disable_ddl_transaction!
MIGRATION = 'ResetDuplicateCiRunnersTokenValues'
DELAY_INTERVAL = 2.minutes
BATCH_SIZE = 2_000
MAX_BATCH_SIZE = 100_000
SUB_BATCH_SIZE = 500
def up
queue_batched_background_migration(
MIGRATION,
:ci_runners,
:id,
job_interval: DELAY_INTERVAL,
batch_size: BATCH_SIZE,
max_batch_size: MAX_BATCH_SIZE,
sub_batch_size: SUB_BATCH_SIZE
)
end
def down
delete_batched_background_migration(MIGRATION, :ci_runners, :id, [])
end
end

View File

@ -0,0 +1,28 @@
# frozen_string_literal: true
class ScheduleResetDuplicateCiRunnersTokenEncryptedValues < Gitlab::Database::Migration[2.0]
restrict_gitlab_migration gitlab_schema: :gitlab_ci
disable_ddl_transaction!
MIGRATION = 'ResetDuplicateCiRunnersTokenEncryptedValues'
DELAY_INTERVAL = 2.minutes
BATCH_SIZE = 2_000
MAX_BATCH_SIZE = 100_000
SUB_BATCH_SIZE = 500
def up
queue_batched_background_migration(
MIGRATION,
:ci_runners,
:id,
job_interval: DELAY_INTERVAL,
batch_size: BATCH_SIZE,
max_batch_size: MAX_BATCH_SIZE,
sub_batch_size: SUB_BATCH_SIZE
)
end
def down
delete_batched_background_migration(MIGRATION, :ci_runners, :id, [])
end
end

View File

@ -0,0 +1 @@
79aa2360fdf84d7bee402cf51e29813b9c25acfe809123ac5a3218644a63c71f

View File

@ -0,0 +1 @@
f48217567db22e6a4d3a32c607911da9f9a39a37d75be158a893ce840f718f02

View File

@ -0,0 +1,197 @@
---
stage: Package
group: Package
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
---
# Dependency Proxy
The Dependency Proxy is a pull-through-cache for registry images from DockerHub. This document describes how this
feature is constructed in GitLab.
## Container registry
The Dependency Proxy for the container registry acts a stand-in for a remote container registry. In our case,
the remote registry is the public DockerHub registry.
```mermaid
flowchart TD
id1([$ docker]) --> id2([GitLab Dependency Proxy])
id2 --> id3([DockerHub])
```
From the user's perspective, the GitLab instance is just a container registry that they are interacting with to
pull images by using `docker login gitlab.com`
When you use `docker login gitlab.com`, the Docker client uses the [v2 API](https://docs.docker.com/registry/spec/api/)
to make requests.
To support authentication, we must include one route:
- [API Version Check](https://docs.docker.com/registry/spec/api/#api-version-check)
To support `docker pull` requests, we must include two additional routes:
- [Pulling an image manifest](https://docs.docker.com/registry/spec/api/#pulling-an-image-manifest)
- [Pulling an image layer (blob)](https://docs.docker.com/registry/spec/api/#pulling-a-layer)
These routes are defined in [`gitlab-org/gitlab/config/routes/group.rb`](https://gitlab.com/gitlab-org/gitlab/-/blob/3f76455ac9cf90a927767e55c837d6b07af818df/config/routes/group.rb#L164-175).
In its simplest form, the Dependency Proxy manages three requests:
- Logging in / returning a JWT
- Fetching a manifest
- Fetching a blob
Here is what the general request sequence looks like for the Dependency Proxy:
```mermaid
sequenceDiagram
Client->>+GitLab: Login? / request token
GitLab->>+Client: JWT
Client->>+GitLab: request a manifest for an image
GitLab->>+ExternalRegistry: request JWT
ExternalRegistry->>+GitLab : JWT
GitLab->>+ExternalRegistry : request manifest
ExternalRegistry->>+GitLab : return manifest
GitLab->>+GitLab : store manifest
GitLab->>+Client : return manifest
loop request image layers
Client->>+GitLab: request a blob from the manifest
GitLab->>+ExternalRegistry: request JWT
ExternalRegistry->>+GitLab : JWT
GitLab->>+ExternalRegistry : request blob
ExternalRegistry->>+GitLab : return blob
GitLab->>+GitLab : store blob
GitLab->>+Client : return blob
end
```
### Authentication and authorization
When a Docker client authenticates with a registry, the registry tells the client where to get a JSON Web Token
(JWT) and to use it for all subsequent requests. This allows the authentication service to live in a separate
application from the registry. For example, the GitLab container registry directs Docker clients to get a token
from `https://gitlab.com/jwt/auth`. This endpoint is part of the `gitlab-org/gitlab` project, also known as the
rails project or web service.
When a user tries to log into the dependency proxy with a Docker client, we must tell it where to get a JWT. We
can use the same endpoint we use with the container registry: `https://gitlab.com/jwt/auth`. But in our case,
we tell the Docker client to specify `service=dependency_proxy` in the parameters so can use a separate underlying
service to generate the token.
This sequence diagram shows the request flow for logging into the Dependency Proxy.
```mermaid
sequenceDiagram
autonumber
participant C as Docker CLI
participant R as GitLab (Dependency Proxy)
Note right of C: User tries `docker login gitlab.com` and enters username/password
C->>R: GET /v2/
Note left of R: Check for Authorization header, return 401 if none, return 200 if token exists and is valid
R->>C: 401 Unauthorized with header "WWW-Authenticate": "Bearer realm=\"http://gitlab.com/jwt/auth\",service=\"registry.docker.io\""
Note right of C: Request Oauth token using HTTP Basic Auth
C->>R: GET /jwt/auth
Note left of R: Token is returned
R->>C: 200 OK (with Bearer token included)
Note right of C: original request is tested again
C->>R: GET /v2/ (this time with `Authorization: Bearer [token]` header)
Note right of C: Login Succeeded
R->>C: 200 OK
```
The dependency proxy uses its own authentication service, separate from the authentication managed by the UI
(`ApplicationController`) and API (`ApiGuard`). Once the service has created a JWT, the `DependencyProxy::ApplicationController`
manages authentication and authorization for the rest of the requests. It manages the user by using `GitLab::Auth::Result` and
is similar to the authentication implemented by the Git client requests in `GitHttpClientController`.
### Caching
Blobs are cached artifacts with no logic around them. We cache them by digest. When we receive a request for a new blob,
we check to see if we have a blob with the requested digest, and return it. Otherwise we fetch it from the external
registry and cache it.
Manifests are more complicated, partially due to [rate limiting on DockerHub](https://www.docker.com/increase-rate-limits/).
A manifest is essentially a recipe for creating an image. It has a list of blobs to create a certain image. So
`alpine:latest` has a manifest associated with it that specifies the blobs needed to create the `alpine:latest`
image. The interesting part is that `alpine:latest` can change over time, so we can't just cache the manifest and
assume it is OK to use forever. Instead, we must check the digest of the manifest, which is an Etag. This gets
interesting because the requests for manifests often don't include the digest. So how do we know if the manifest
we have cached is still the most up-to-date `alpine:latest`? DockerHub allows free HEAD requests that don't count
toward their rate limit. The HEAD request returns the manifest digest so we can tell whether or not the one we
have is stale.
With this knowledge, we have built the following logic to manage manifest requests:
```mermaid
graph TD
A[Receive manifest request] --> | We have the manifest cached.| B{Docker manifest HEAD request}
A --> | We do not have manifest cached.| C{Docker manifest GET request}
B --> | Digest matches the one in the DB | D[Fetch manifest from cache]
B --> | Network failure, cannot reach DockerHub | D[Fetch manifest from cache]
B --> | Digest does not match the one in DB | C
C --> E[Save manifest to cache, save digest to database]
D --> F
E --> F[Return manifest]
```
### Workhorse for file handling
Management of file uploads and caching happens in [Workhorse](../workhorse/index.md). This explains the additional
[`POST` routes](https://gitlab.com/gitlab-org/gitlab/-/blob/3f76455ac9cf90a927767e55c837d6b07af818df/config/routes/group.rb#L170-173)
that we have for the Dependency Proxy.
The [send_dependency](https://gitlab.com/gitlab-org/gitlab/-/blob/7359d23f4e078479969c872924150219c6f1665f/app/helpers/workhorse_helper.rb#L46-53)
method makes a request to Workhorse including the previously fetched JWT from the external registry. Workhorse then
can use that token to request the manifest or blob the user originally requested. The Workhorse code lives in
[`workhorse/internal/dependencyproxy/dependencyproxy.go`](https://gitlab.com/gitlab-org/gitlab/-/blob/b8f44a8f3c26efe9932c2ada2df75ef7acb8417b/workhorse/internal/dependencyproxy/dependencyproxy.go#L4).
Once we put it all together, the sequence for requesting an image file looks like this:
```mermaid
sequenceDiagram
Client->>Workhorse: GET /v2/*group_id/dependency_proxy/containers/*image/manifests/*tag
Workhorse->>Rails: GET /v2/*group_id/dependency_proxy/containers/*image/manifests/*tag
Rails->>Rails: Check DB. Is manifest persisted in cache?
alt In Cache
Rails->>Workhorse: Respond with send-url injector
Workhorse->>Client: Send the file to the client
else Not In Cache
Rails->>Rails: Generate auth token and download URL for the manifest in upstream registry
Rails->>Workhorse: Respond with send-dependency injector
Workhorse->>External Registry: Request the manifest
External Registry->>Workhorse: Download the manifest
Workhorse->>Rails: GET /v2/*group_id/dependency_proxy/containers/*image/manifest/*tag/authorize
Rails->>Workhorse: Respond with upload instructions
Workhorse->>Client: Send the manifest file to the client with original headers
Workhorse->>Object Storage: Save the manifest file with some of it's header values
Workhorse->>Rails: Finalize the upload
end
```
### Cleanup policies
The cleanup policies for the Dependency Proxy work as time-to-live policies. They allow users to set the number
of days a file is allowed to remain cached if it has been unread. Since there is no way to associate the blobs
with the images they belong to (to do this, we would need to build the metadata database that the container registry
folks built), we can set up rules like "if this blob has not been pulled in 90 days, delete it". This means that
any files that are continuously getting pulled will not be removed from the cache, but if, for example,
`alpine:latest` changes and one of the underlying blobs is no longer used, it will eventually get cleaned up
because it has stopped getting pulled. We use the `read_at` attribute to track the last time a given
`dependency_proxy_blob` or `dependency_proxy_manifest` was pulled.
These work using a cron worker, [DependencyProxy::CleanupDependencyProxyWorker](https://gitlab.com/gitlab-org/gitlab/-/blob/7359d23f4e078479969c872924150219c6f1665f/app/workers/dependency_proxy/cleanup_dependency_proxy_worker.rb#L4),
that will kick off two [limited capacity](../sidekiq/limited_capacity_worker.md) workers: one to delete blobs,
and one to delete manifests. The capacity is set in an [application setting](settings.md#container-registry).
### Historic reference links
- [Dependency proxy for private groups](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/46042) - initial authentication implementation
- [Manifest caching](https://gitlab.com/gitlab-org/gitlab/-/issues/241639) - initial manifest caching implementation
- [Workhorse for blobs](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/71890) - initial workhorse implementation
- [Workhorse for manifest](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/73033) - moving manifest cache logic to Workhorse
- [Deploy token support](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/64363) - authorization largely updated
- [SSO support](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/67373) - changes how policies are checked

View File

@ -8,6 +8,8 @@ info: To determine the technical writer assigned to the Stage/Group associated w
Development and Architectural documentation for the package registry Development and Architectural documentation for the package registry
- [Debian repository structure](debian_repository.md)
- [Dependency proxy structure](dependency_proxy.md)
- [Developing a new format](new_format_development.md) - [Developing a new format](new_format_development.md)
- [Settings](settings.md) - [Settings](settings.md)
- [Structure / Schema](structure.md) - [Structure / Schema](structure.md)

View File

@ -0,0 +1,31 @@
# frozen_string_literal: true
module Gitlab
module BackgroundMigration
# A job to nullify duplicate token_encrypted values in ci_runners table in batches
class ResetDuplicateCiRunnersTokenEncryptedValues < BatchedMigrationJob
def perform
each_sub_batch(operation_name: :nullify_duplicate_ci_runner_token_encrypted_values) do |sub_batch|
# Reset duplicate runner encrypted tokens that would prevent creating an unique index.
nullify_duplicate_ci_runner_token_encrypted_values(sub_batch)
end
end
private
def nullify_duplicate_ci_runner_token_encrypted_values(sub_batch)
batchable_model = define_batchable_model(batch_table, connection: connection)
duplicate_tokens = batchable_model
.where(token_encrypted: sub_batch.select(:token_encrypted).distinct)
.group(:token_encrypted)
.having('COUNT(*) > 1')
.pluck(:token_encrypted)
return if duplicate_tokens.empty?
batchable_model.where(token_encrypted: duplicate_tokens).update_all(token_encrypted: nil)
end
end
end
end

View File

@ -0,0 +1,29 @@
# frozen_string_literal: true
module Gitlab
module BackgroundMigration
# A job to nullify duplicate token values in ci_runners table in batches
class ResetDuplicateCiRunnersTokenValues < BatchedMigrationJob
def perform
each_sub_batch(operation_name: :nullify_duplicate_ci_runner_token_values) do |sub_batch|
# Reset duplicate runner tokens that would prevent creating an unique index.
nullify_duplicate_ci_runner_token_values(sub_batch)
end
end
private
def nullify_duplicate_ci_runner_token_values(sub_batch)
batchable_model = define_batchable_model(batch_table, connection: connection)
duplicate_tokens = batchable_model
.where(token: sub_batch.select(:token).distinct)
.group(:token)
.having('COUNT(*) > 1')
.pluck(:token)
batchable_model.where(token: duplicate_tokens).update_all(token: nil) if duplicate_tokens.any?
end
end
end
end

View File

@ -23,7 +23,7 @@ module Gitlab
# rubocop: enable CodeReuse/ActiveRecord # rubocop: enable CodeReuse/ActiveRecord
def url def url
raw_data.url || '' raw_data[:url] || ''
end end
end end
end end

View File

@ -3,7 +3,17 @@
module Gitlab module Gitlab
module LegacyGithubImport module LegacyGithubImport
class BranchFormatter < BaseFormatter class BranchFormatter < BaseFormatter
delegate :repo, :sha, :ref, to: :raw_data def repo
raw_data[:repo]
end
def sha
raw_data[:sha]
end
def ref
raw_data[:ref]
end
def exists? def exists?
branch_exists? && commit_exists? branch_exists? && commit_exists?
@ -14,7 +24,7 @@ module Gitlab
end end
def user def user
raw_data.user&.login || 'unknown' raw_data.dig(:user, :login) || 'unknown'
end end
def short_sha def short_sha

View File

@ -9,19 +9,19 @@ module Gitlab
{ {
project: project, project: project,
note: note, note: note,
commit_id: raw_data.commit_id, commit_id: raw_data[:commit_id],
line_code: line_code, line_code: line_code,
author_id: author_id, author_id: author_id,
type: type, type: type,
created_at: raw_data.created_at, created_at: raw_data[:created_at],
updated_at: raw_data.updated_at updated_at: raw_data[:updated_at]
} }
end end
private private
def author def author
@author ||= UserFormatter.new(client, raw_data.user) @author ||= UserFormatter.new(client, raw_data[:user])
end end
def author_id def author_id
@ -29,7 +29,7 @@ module Gitlab
end end
def body def body
raw_data.body || "" raw_data[:body] || ""
end end
def line_code def line_code
@ -48,11 +48,11 @@ module Gitlab
end end
def diff_hunk def diff_hunk
raw_data.diff_hunk raw_data[:diff_hunk]
end end
def file_path def file_path
raw_data.path raw_data[:path]
end end
def note def note

View File

@ -96,7 +96,7 @@ module Gitlab
def import_labels def import_labels
fetch_resources(:labels, repo, per_page: 100) do |labels| fetch_resources(:labels, repo, per_page: 100) do |labels|
labels.each do |raw| labels.each do |raw|
gh_label = LabelFormatter.new(project, raw) gh_label = LabelFormatter.new(project, raw.to_h)
gh_label.create! gh_label.create!
rescue StandardError => e rescue StandardError => e
errors << { type: :label, url: Gitlab::UrlSanitizer.sanitize(gh_label.url), errors: e.message } errors << { type: :label, url: Gitlab::UrlSanitizer.sanitize(gh_label.url), errors: e.message }
@ -109,7 +109,7 @@ module Gitlab
def import_milestones def import_milestones
fetch_resources(:milestones, repo, state: :all, per_page: 100) do |milestones| fetch_resources(:milestones, repo, state: :all, per_page: 100) do |milestones|
milestones.each do |raw| milestones.each do |raw|
gh_milestone = MilestoneFormatter.new(project, raw) gh_milestone = MilestoneFormatter.new(project, raw.to_h)
gh_milestone.create! gh_milestone.create!
rescue StandardError => e rescue StandardError => e
errors << { type: :milestone, url: Gitlab::UrlSanitizer.sanitize(gh_milestone.url), errors: e.message } errors << { type: :milestone, url: Gitlab::UrlSanitizer.sanitize(gh_milestone.url), errors: e.message }
@ -121,6 +121,7 @@ module Gitlab
def import_issues def import_issues
fetch_resources(:issues, repo, state: :all, sort: :created, direction: :asc, per_page: 100) do |issues| fetch_resources(:issues, repo, state: :all, sort: :created, direction: :asc, per_page: 100) do |issues|
issues.each do |raw| issues.each do |raw|
raw = raw.to_h
gh_issue = IssueFormatter.new(project, raw, client) gh_issue = IssueFormatter.new(project, raw, client)
begin begin
@ -143,6 +144,7 @@ module Gitlab
def import_pull_requests def import_pull_requests
fetch_resources(:pull_requests, repo, state: :all, sort: :created, direction: :asc, per_page: 100) do |pull_requests| fetch_resources(:pull_requests, repo, state: :all, sort: :created, direction: :asc, per_page: 100) do |pull_requests|
pull_requests.each do |raw| pull_requests.each do |raw|
raw = raw.to_h
gh_pull_request = PullRequestFormatter.new(project, raw, client) gh_pull_request = PullRequestFormatter.new(project, raw, client)
next unless gh_pull_request.valid? next unless gh_pull_request.valid?
@ -190,10 +192,12 @@ module Gitlab
end end
def apply_labels(issuable, raw) def apply_labels(issuable, raw)
return unless raw.labels.count > 0 raw = raw.to_h
label_ids = raw.labels return unless raw[:labels].count > 0
.map { |attrs| @labels[attrs.name] }
label_ids = raw[:labels]
.map { |attrs| @labels[attrs[:name]] }
.compact .compact
issuable.update_attribute(:label_ids, label_ids) issuable.update_attribute(:label_ids, label_ids)
@ -226,10 +230,12 @@ module Gitlab
def create_comments(comments) def create_comments(comments)
ActiveRecord::Base.no_touching do ActiveRecord::Base.no_touching do
comments.each do |raw| comments.each do |raw|
raw = raw.to_h
comment = CommentFormatter.new(project, raw, client) comment = CommentFormatter.new(project, raw, client)
# GH does not return info about comment's parent, so we guess it by checking its URL! # GH does not return info about comment's parent, so we guess it by checking its URL!
*_, parent, iid = URI(raw.html_url).path.split('/') *_, parent, iid = URI(raw[:html_url]).path.split('/')
issuable = if parent == 'issues' issuable = if parent == 'issues'
Issue.find_by(project_id: project.id, iid: iid) Issue.find_by(project_id: project.id, iid: iid)
@ -241,7 +247,7 @@ module Gitlab
issuable.notes.create!(comment.attributes) issuable.notes.create!(comment.attributes)
rescue StandardError => e rescue StandardError => e
errors << { type: :comment, url: Gitlab::UrlSanitizer.sanitize(raw.url), errors: e.message } errors << { type: :comment, url: Gitlab::UrlSanitizer.sanitize(raw[:url]), errors: e.message }
end end
end end
end end
@ -251,7 +257,7 @@ module Gitlab
last_note_attrs = nil last_note_attrs = nil
cut_off_index = comments.find_index do |raw| cut_off_index = comments.find_index do |raw|
comment = CommentFormatter.new(project, raw) comment = CommentFormatter.new(project, raw.to_h)
comment_attrs = comment.attributes comment_attrs = comment.attributes
last_note_attrs ||= last_note.slice(*comment_attrs.keys) last_note_attrs ||= last_note.slice(*comment_attrs.keys)
@ -282,7 +288,7 @@ module Gitlab
def import_releases def import_releases
fetch_resources(:releases, repo, per_page: 100) do |releases| fetch_resources(:releases, repo, per_page: 100) do |releases|
releases.each do |raw| releases.each do |raw|
gh_release = ReleaseFormatter.new(project, raw) gh_release = ReleaseFormatter.new(project, raw.to_h)
gh_release.create! if gh_release.valid? gh_release.create! if gh_release.valid?
rescue StandardError => e rescue StandardError => e
errors << { type: :release, url: Gitlab::UrlSanitizer.sanitize(gh_release.url), errors: e.message } errors << { type: :release, url: Gitlab::UrlSanitizer.sanitize(gh_release.url), errors: e.message }

View File

@ -9,7 +9,9 @@ module Gitlab
raise NotImplementedError raise NotImplementedError
end end
delegate :number, to: :raw_data def number
raw_data[:number]
end
def find_condition def find_condition
{ iid: number } { iid: number }
@ -18,15 +20,15 @@ module Gitlab
private private
def state def state
raw_data.state == 'closed' ? 'closed' : 'opened' raw_data[:state] == 'closed' ? 'closed' : 'opened'
end end
def assigned? def assigned?
raw_data.assignee.present? raw_data[:assignee].present?
end end
def author def author
@author ||= UserFormatter.new(client, raw_data.user) @author ||= UserFormatter.new(client, raw_data[:user])
end end
def author_id def author_id
@ -35,7 +37,7 @@ module Gitlab
def assignee def assignee
if assigned? if assigned?
@assignee ||= UserFormatter.new(client, raw_data.assignee) @assignee ||= UserFormatter.new(client, raw_data[:assignee])
end end
end end
@ -46,7 +48,7 @@ module Gitlab
end end
def body def body
raw_data.body || "" raw_data[:body] || ""
end end
def description def description
@ -59,8 +61,8 @@ module Gitlab
# rubocop: disable CodeReuse/ActiveRecord # rubocop: disable CodeReuse/ActiveRecord
def milestone def milestone
if raw_data.milestone.present? if raw_data[:milestone].present?
milestone = MilestoneFormatter.new(project, raw_data.milestone) milestone = MilestoneFormatter.new(project, raw_data[:milestone])
project.milestones.find_by(milestone.find_condition) project.milestones.find_by(milestone.find_condition)
end end
end end

View File

@ -8,18 +8,18 @@ module Gitlab
iid: number, iid: number,
project: project, project: project,
milestone: milestone, milestone: milestone,
title: raw_data.title, title: raw_data[:title],
description: description, description: description,
state: state, state: state,
author_id: author_id, author_id: author_id,
assignee_ids: Array(assignee_id), assignee_ids: Array(assignee_id),
created_at: raw_data.created_at, created_at: raw_data[:created_at],
updated_at: raw_data.updated_at updated_at: raw_data[:updated_at]
} }
end end
def has_comments? def has_comments?
raw_data.comments > 0 raw_data[:comments] > 0
end end
def project_association def project_association
@ -27,7 +27,7 @@ module Gitlab
end end
def pull_request? def pull_request?
raw_data.pull_request.present? raw_data[:pull_request].present?
end end
end end
end end

View File

@ -28,11 +28,11 @@ module Gitlab
private private
def color def color
"##{raw_data.color}" "##{raw_data[:color]}"
end end
def title def title
raw_data.name raw_data[:name]
end end
end end
end end

View File

@ -7,12 +7,12 @@ module Gitlab
{ {
iid: number, iid: number,
project: project, project: project,
title: raw_data.title, title: raw_data[:title],
description: raw_data.description, description: raw_data[:description],
due_date: raw_data.due_on, due_date: raw_data[:due_on],
state: state, state: state,
created_at: raw_data.created_at, created_at: raw_data[:created_at],
updated_at: raw_data.updated_at updated_at: raw_data[:updated_at]
} }
end end
@ -26,16 +26,16 @@ module Gitlab
def number def number
if project.gitea_import? if project.gitea_import?
raw_data.id raw_data[:id]
else else
raw_data.number raw_data[:number]
end end
end end
private private
def state def state
raw_data.state == 'closed' ? 'closed' : 'active' raw_data[:state] == 'closed' ? 'closed' : 'active'
end end
end end
end end

View File

@ -9,7 +9,7 @@ module Gitlab
def attributes def attributes
{ {
iid: number, iid: number,
title: raw_data.title, title: raw_data[:title],
description: description, description: description,
source_project: source_branch_project, source_project: source_branch_project,
source_branch: source_branch_name, source_branch: source_branch_name,
@ -21,8 +21,8 @@ module Gitlab
milestone: milestone, milestone: milestone,
author_id: author_id, author_id: author_id,
assignee_id: assignee_id, assignee_id: assignee_id,
created_at: raw_data.created_at, created_at: raw_data[:created_at],
updated_at: raw_data.updated_at, updated_at: raw_data[:updated_at],
imported: true imported: true
} }
end end
@ -36,7 +36,7 @@ module Gitlab
end end
def source_branch def source_branch
@source_branch ||= BranchFormatter.new(project, raw_data.head) @source_branch ||= BranchFormatter.new(project, raw_data[:head])
end end
def source_branch_name def source_branch_name
@ -57,7 +57,7 @@ module Gitlab
end end
def target_branch def target_branch
@target_branch ||= BranchFormatter.new(project, raw_data.base) @target_branch ||= BranchFormatter.new(project, raw_data[:base])
end end
def target_branch_name def target_branch_name
@ -71,7 +71,7 @@ module Gitlab
def cross_project? def cross_project?
return true if source_branch_repo.nil? return true if source_branch_repo.nil?
source_branch_repo.id != target_branch_repo.id source_branch_repo[:id] != target_branch_repo[:id]
end end
def opened? def opened?
@ -81,7 +81,7 @@ module Gitlab
private private
def state def state
if raw_data.state == 'closed' && raw_data.merged_at.present? if raw_data[:state] == 'closed' && raw_data[:merged_at].present?
'merged' 'merged'
else else
super super

View File

@ -6,13 +6,13 @@ module Gitlab
def attributes def attributes
{ {
project: project, project: project,
tag: raw_data.tag_name, tag: raw_data[:tag_name],
name: raw_data.name, name: raw_data[:name],
description: raw_data.body, description: raw_data[:body],
created_at: raw_data.created_at, created_at: raw_data[:created_at],
# Draft releases will have a null published_at # Draft releases will have a null published_at
released_at: raw_data.published_at || Time.current, released_at: raw_data[:published_at] || Time.current,
updated_at: raw_data.created_at updated_at: raw_data[:created_at]
} }
end end
@ -21,11 +21,11 @@ module Gitlab
end end
def find_condition def find_condition
{ tag: raw_data.tag_name } { tag: raw_data[:tag_name] }
end end
def valid? def valid?
!raw_data.draft && raw_data.tag_name.present? !raw_data[:draft] && raw_data[:tag_name].present?
end end
end end
end end

View File

@ -5,13 +5,19 @@ module Gitlab
class UserFormatter class UserFormatter
attr_reader :client, :raw attr_reader :client, :raw
delegate :id, :login, to: :raw, allow_nil: true
def initialize(client, raw) def initialize(client, raw)
@client = client @client = client
@raw = raw @raw = raw
end end
def id
raw[:id]
end
def login
raw[:login]
end
def gitlab_id def gitlab_id
return @gitlab_id if defined?(@gitlab_id) return @gitlab_id if defined?(@gitlab_id)
@ -21,7 +27,7 @@ module Gitlab
private private
def email def email
@email ||= client.user(raw.login).try(:email) @email ||= client.user(raw[:login]).to_h[:email]
end end
def find_by_email def find_by_email

View File

@ -425,21 +425,21 @@ FooBar
end end
it 'delegates to #markdown_unsafe when file name corresponds to Markdown' do it 'delegates to #markdown_unsafe when file name corresponds to Markdown' do
expect(helper).to receive(:gitlab_markdown?).with('foo.md').and_return(true) expect(Gitlab::MarkupHelper).to receive(:gitlab_markdown?).with('foo.md').and_return(true)
expect(helper).to receive(:markdown_unsafe).and_return('NOEL') expect(helper).to receive(:markdown_unsafe).and_return('NOEL')
expect(helper.markup('foo.md', content)).to eq('NOEL') expect(helper.markup('foo.md', content)).to eq('NOEL')
end end
it 'delegates to #asciidoc_unsafe when file name corresponds to AsciiDoc' do it 'delegates to #asciidoc_unsafe when file name corresponds to AsciiDoc' do
expect(helper).to receive(:asciidoc?).with('foo.adoc').and_return(true) expect(Gitlab::MarkupHelper).to receive(:asciidoc?).with('foo.adoc').and_return(true)
expect(helper).to receive(:asciidoc_unsafe).and_return('NOEL') expect(helper).to receive(:asciidoc_unsafe).and_return('NOEL')
expect(helper.markup('foo.adoc', content)).to eq('NOEL') expect(helper.markup('foo.adoc', content)).to eq('NOEL')
end end
it 'uses passed in rendered content' do it 'uses passed in rendered content' do
expect(helper).not_to receive(:gitlab_markdown?) expect(Gitlab::MarkupHelper).not_to receive(:gitlab_markdown?)
expect(helper).not_to receive(:markdown_unsafe) expect(helper).not_to receive(:markdown_unsafe)
expect(helper.markup('foo.md', content, rendered: '<p>NOEL</p>')).to eq('<p>NOEL</p>') expect(helper.markup('foo.md', content, rendered: '<p>NOEL</p>')).to eq('<p>NOEL</p>')

View File

@ -0,0 +1,70 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Gitlab::BackgroundMigration::ResetDuplicateCiRunnersTokenEncryptedValues,
:migration,
schema: 20220922143634 do
it { expect(described_class).to be < Gitlab::BackgroundMigration::BatchedMigrationJob }
describe '#perform' do
let(:ci_runners) { table(:ci_runners, database: :ci) }
let(:test_worker) do
described_class.new(
start_id: 1,
end_id: 4,
batch_table: :ci_runners,
batch_column: :id,
sub_batch_size: 2,
pause_ms: 0,
connection: Ci::ApplicationRecord.connection
)
end
subject(:perform) { test_worker.perform }
before do
ci_runners.create!(id: 1, runner_type: 1, token_encrypted: 'duplicate')
ci_runners.create!(id: 2, runner_type: 1, token_encrypted: 'a-token')
ci_runners.create!(id: 3, runner_type: 1, token_encrypted: 'duplicate-2')
ci_runners.create!(id: 4, runner_type: 1, token_encrypted: nil)
ci_runners.create!(id: 5, runner_type: 1, token_encrypted: 'duplicate-2')
ci_runners.create!(id: 6, runner_type: 1, token_encrypted: 'duplicate')
ci_runners.create!(id: 7, runner_type: 1, token_encrypted: 'another-token')
ci_runners.create!(id: 8, runner_type: 1, token_encrypted: 'another-token')
end
it 'nullifies duplicate encrypted tokens', :aggregate_failures do
expect { perform }.to change { ci_runners.all.order(:id).pluck(:id, :token_encrypted).to_h }
.from(
{
1 => 'duplicate',
2 => 'a-token',
3 => 'duplicate-2',
4 => nil,
5 => 'duplicate-2',
6 => 'duplicate',
7 => 'another-token',
8 => 'another-token'
}
)
.to(
{
1 => nil,
2 => 'a-token',
3 => nil,
4 => nil,
5 => nil,
6 => nil,
7 => 'another-token',
8 => 'another-token'
}
)
expect(ci_runners.count).to eq(8)
expect(ci_runners.pluck(:token_encrypted).uniq).to match_array [
nil, 'a-token', 'another-token'
]
end
end
end

View File

@ -0,0 +1,70 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Gitlab::BackgroundMigration::ResetDuplicateCiRunnersTokenValues,
:migration,
schema: 20220922143143 do
it { expect(described_class).to be < Gitlab::BackgroundMigration::BatchedMigrationJob }
describe '#perform' do
let(:ci_runners) { table(:ci_runners, database: :ci) }
let(:test_worker) do
described_class.new(
start_id: 1,
end_id: 4,
batch_table: :ci_runners,
batch_column: :id,
sub_batch_size: 2,
pause_ms: 0,
connection: Ci::ApplicationRecord.connection
)
end
subject(:perform) { test_worker.perform }
before do
ci_runners.create!(id: 1, runner_type: 1, token: 'duplicate')
ci_runners.create!(id: 2, runner_type: 1, token: 'a-token')
ci_runners.create!(id: 3, runner_type: 1, token: 'duplicate-2')
ci_runners.create!(id: 4, runner_type: 1, token: nil)
ci_runners.create!(id: 5, runner_type: 1, token: 'duplicate-2')
ci_runners.create!(id: 6, runner_type: 1, token: 'duplicate')
ci_runners.create!(id: 7, runner_type: 1, token: 'another-token')
ci_runners.create!(id: 8, runner_type: 1, token: 'another-token')
end
it 'nullifies duplicate tokens', :aggregate_failures do
expect { perform }.to change { ci_runners.all.order(:id).pluck(:id, :token).to_h }
.from(
{
1 => 'duplicate',
2 => 'a-token',
3 => 'duplicate-2',
4 => nil,
5 => 'duplicate-2',
6 => 'duplicate',
7 => 'another-token',
8 => 'another-token'
}
)
.to(
{
1 => nil,
2 => 'a-token',
3 => nil,
4 => nil,
5 => nil,
6 => nil,
7 => 'another-token',
8 => 'another-token'
}
)
expect(ci_runners.count).to eq(8)
expect(ci_runners.pluck(:token).uniq).to match_array [
nil, 'a-token', 'another-token'
]
end
end
end

View File

@ -3,7 +3,7 @@
require 'spec_helper' require 'spec_helper'
RSpec.describe Gitlab::LegacyGithubImport::BranchFormatter do RSpec.describe Gitlab::LegacyGithubImport::BranchFormatter do
let(:project) { create(:project, :repository) } let_it_be(:project) { create(:project, :repository) }
let(:commit) { create(:commit, project: project) } let(:commit) { create(:commit, project: project) }
let(:repo) { double } let(:repo) { double }
let(:raw) do let(:raw) do
@ -16,19 +16,19 @@ RSpec.describe Gitlab::LegacyGithubImport::BranchFormatter do
describe '#exists?' do describe '#exists?' do
it 'returns true when branch exists and commit is part of the branch' do it 'returns true when branch exists and commit is part of the branch' do
branch = described_class.new(project, double(raw)) branch = described_class.new(project, raw)
expect(branch.exists?).to eq true expect(branch.exists?).to eq true
end end
it 'returns false when branch exists and commit is not part of the branch' do it 'returns false when branch exists and commit is not part of the branch' do
branch = described_class.new(project, double(raw.merge(ref: 'feature'))) branch = described_class.new(project, raw.merge(ref: 'feature'))
expect(branch.exists?).to eq false expect(branch.exists?).to eq false
end end
it 'returns false when branch does not exist' do it 'returns false when branch does not exist' do
branch = described_class.new(project, double(raw.merge(ref: 'removed-branch'))) branch = described_class.new(project, raw.merge(ref: 'removed-branch'))
expect(branch.exists?).to eq false expect(branch.exists?).to eq false
end end
@ -36,7 +36,7 @@ RSpec.describe Gitlab::LegacyGithubImport::BranchFormatter do
describe '#repo' do describe '#repo' do
it 'returns raw repo' do it 'returns raw repo' do
branch = described_class.new(project, double(raw)) branch = described_class.new(project, raw)
expect(branch.repo).to eq repo expect(branch.repo).to eq repo
end end
@ -44,7 +44,7 @@ RSpec.describe Gitlab::LegacyGithubImport::BranchFormatter do
describe '#sha' do describe '#sha' do
it 'returns raw sha' do it 'returns raw sha' do
branch = described_class.new(project, double(raw)) branch = described_class.new(project, raw)
expect(branch.sha).to eq commit.id expect(branch.sha).to eq commit.id
end end
@ -52,19 +52,19 @@ RSpec.describe Gitlab::LegacyGithubImport::BranchFormatter do
describe '#valid?' do describe '#valid?' do
it 'returns true when raw sha and ref are present' do it 'returns true when raw sha and ref are present' do
branch = described_class.new(project, double(raw)) branch = described_class.new(project, raw)
expect(branch.valid?).to eq true expect(branch.valid?).to eq true
end end
it 'returns false when raw sha is blank' do it 'returns false when raw sha is blank' do
branch = described_class.new(project, double(raw.merge(sha: nil))) branch = described_class.new(project, raw.merge(sha: nil))
expect(branch.valid?).to eq false expect(branch.valid?).to eq false
end end
it 'returns false when raw ref is blank' do it 'returns false when raw ref is blank' do
branch = described_class.new(project, double(raw.merge(ref: nil))) branch = described_class.new(project, raw.merge(ref: nil))
expect(branch.valid?).to eq false expect(branch.valid?).to eq false
end end

View File

@ -3,9 +3,9 @@
require 'spec_helper' require 'spec_helper'
RSpec.describe Gitlab::LegacyGithubImport::CommentFormatter do RSpec.describe Gitlab::LegacyGithubImport::CommentFormatter do
let_it_be(:project) { create(:project) }
let(:client) { double } let(:client) { double }
let(:project) { create(:project) } let(:octocat) { { id: 123456, login: 'octocat', email: 'octocat@example.com' } }
let(:octocat) { double(id: 123456, login: 'octocat', email: 'octocat@example.com') }
let(:created_at) { DateTime.strptime('2013-04-10T20:09:31Z') } let(:created_at) { DateTime.strptime('2013-04-10T20:09:31Z') }
let(:updated_at) { DateTime.strptime('2014-03-03T18:58:10Z') } let(:updated_at) { DateTime.strptime('2014-03-03T18:58:10Z') }
let(:base) do let(:base) do
@ -27,7 +27,7 @@ RSpec.describe Gitlab::LegacyGithubImport::CommentFormatter do
describe '#attributes' do describe '#attributes' do
context 'when do not reference a portion of the diff' do context 'when do not reference a portion of the diff' do
let(:raw) { double(base) } let(:raw) { base }
it 'returns formatted attributes' do it 'returns formatted attributes' do
expected = { expected = {
@ -55,7 +55,7 @@ RSpec.describe Gitlab::LegacyGithubImport::CommentFormatter do
} }
end end
let(:raw) { double(base.merge(diff)) } let(:raw) { base.merge(diff) }
it 'returns formatted attributes' do it 'returns formatted attributes' do
expected = { expected = {
@ -74,22 +74,22 @@ RSpec.describe Gitlab::LegacyGithubImport::CommentFormatter do
end end
context 'when author is a GitLab user' do context 'when author is a GitLab user' do
let(:raw) { double(base.merge(user: octocat)) } let(:raw) { base.merge(user: octocat) }
it 'returns GitLab user id associated with GitHub id as author_id' do it 'returns GitLab user id associated with GitHub id as author_id' do
gl_user = create(:omniauth_user, extern_uid: octocat.id, provider: 'github') gl_user = create(:omniauth_user, extern_uid: octocat[:id], provider: 'github')
expect(comment.attributes.fetch(:author_id)).to eq gl_user.id expect(comment.attributes.fetch(:author_id)).to eq gl_user.id
end end
it 'returns GitLab user id associated with GitHub email as author_id' do it 'returns GitLab user id associated with GitHub email as author_id' do
gl_user = create(:user, email: octocat.email) gl_user = create(:user, email: octocat[:email])
expect(comment.attributes.fetch(:author_id)).to eq gl_user.id expect(comment.attributes.fetch(:author_id)).to eq gl_user.id
end end
it 'returns note without created at tag line' do it 'returns note without created at tag line' do
create(:omniauth_user, extern_uid: octocat.id, provider: 'github') create(:omniauth_user, extern_uid: octocat[:id], provider: 'github')
expect(comment.attributes.fetch(:note)).to eq("I'm having a problem with this.") expect(comment.attributes.fetch(:note)).to eq("I'm having a problem with this.")
end end

View File

@ -59,23 +59,23 @@ RSpec.describe Gitlab::LegacyGithubImport::Importer do
end end
let(:label1) do let(:label1) do
double( {
name: 'Bug', name: 'Bug',
color: 'ff0000', color: 'ff0000',
url: "#{api_root}/repos/octocat/Hello-World/labels/bug" url: "#{api_root}/repos/octocat/Hello-World/labels/bug"
) }
end end
let(:label2) do let(:label2) do
double( {
name: nil, name: nil,
color: 'ff0000', color: 'ff0000',
url: "#{api_root}/repos/octocat/Hello-World/labels/bug" url: "#{api_root}/repos/octocat/Hello-World/labels/bug"
) }
end end
let(:milestone) do let(:milestone) do
double( {
id: 1347, # For Gitea id: 1347, # For Gitea
number: 1347, number: 1347,
state: 'open', state: 'open',
@ -86,11 +86,11 @@ RSpec.describe Gitlab::LegacyGithubImport::Importer do
updated_at: updated_at, updated_at: updated_at,
closed_at: nil, closed_at: nil,
url: "#{api_root}/repos/octocat/Hello-World/milestones/1" url: "#{api_root}/repos/octocat/Hello-World/milestones/1"
) }
end end
let(:issue1) do let(:issue1) do
double( {
number: 1347, number: 1347,
milestone: nil, milestone: nil,
state: 'open', state: 'open',
@ -104,12 +104,12 @@ RSpec.describe Gitlab::LegacyGithubImport::Importer do
updated_at: updated_at, updated_at: updated_at,
closed_at: nil, closed_at: nil,
url: "#{api_root}/repos/octocat/Hello-World/issues/1347", url: "#{api_root}/repos/octocat/Hello-World/issues/1347",
labels: [double(name: 'Label #1')] labels: [{ name: 'Label #1' }]
) }
end end
let(:issue2) do let(:issue2) do
double( {
number: 1348, number: 1348,
milestone: nil, milestone: nil,
state: 'open', state: 'open',
@ -123,12 +123,12 @@ RSpec.describe Gitlab::LegacyGithubImport::Importer do
updated_at: updated_at, updated_at: updated_at,
closed_at: nil, closed_at: nil,
url: "#{api_root}/repos/octocat/Hello-World/issues/1348", url: "#{api_root}/repos/octocat/Hello-World/issues/1348",
labels: [double(name: 'Label #2')] labels: [{ name: 'Label #2' }]
) }
end end
let(:release1) do let(:release1) do
double( {
tag_name: 'v1.0.0', tag_name: 'v1.0.0',
name: 'First release', name: 'First release',
body: 'Release v1.0.0', body: 'Release v1.0.0',
@ -137,11 +137,11 @@ RSpec.describe Gitlab::LegacyGithubImport::Importer do
published_at: created_at, published_at: created_at,
updated_at: updated_at, updated_at: updated_at,
url: "#{api_root}/repos/octocat/Hello-World/releases/1" url: "#{api_root}/repos/octocat/Hello-World/releases/1"
) }
end end
let(:release2) do let(:release2) do
double( {
tag_name: 'v1.1.0', tag_name: 'v1.1.0',
name: 'Second release', name: 'Second release',
body: nil, body: nil,
@ -150,7 +150,7 @@ RSpec.describe Gitlab::LegacyGithubImport::Importer do
published_at: created_at, published_at: created_at,
updated_at: updated_at, updated_at: updated_at,
url: "#{api_root}/repos/octocat/Hello-World/releases/2" url: "#{api_root}/repos/octocat/Hello-World/releases/2"
) }
end end
subject { described_class.new(project) } subject { described_class.new(project) }
@ -210,18 +210,18 @@ RSpec.describe Gitlab::LegacyGithubImport::Importer do
end end
let(:project) { create(:project, :repository, :wiki_disabled, import_url: "#{repo_root}/octocat/Hello-World.git") } let(:project) { create(:project, :repository, :wiki_disabled, import_url: "#{repo_root}/octocat/Hello-World.git") }
let(:octocat) { double(id: 123456, login: 'octocat', email: 'octocat@example.com') } let(:octocat) { { id: 123456, login: 'octocat', email: 'octocat@example.com' } }
let(:credentials) { { user: 'joe' } } let(:credentials) { { user: 'joe' } }
let(:created_at) { DateTime.strptime('2011-01-26T19:01:12Z') } let(:created_at) { DateTime.strptime('2011-01-26T19:01:12Z') }
let(:updated_at) { DateTime.strptime('2011-01-27T19:01:12Z') } let(:updated_at) { DateTime.strptime('2011-01-27T19:01:12Z') }
let(:repository) { double(id: 1, fork: false) } let(:repository) { { id: 1, fork: false } }
let(:source_sha) { create(:commit, project: project).id } let(:source_sha) { create(:commit, project: project).id }
let(:source_branch) { double(ref: 'branch-merged', repo: repository, sha: source_sha, user: octocat) } let(:source_branch) { { ref: 'branch-merged', repo: repository, sha: source_sha, user: octocat } }
let(:target_sha) { create(:commit, project: project, git_commit: RepoHelpers.another_sample_commit).id } let(:target_sha) { create(:commit, project: project, git_commit: RepoHelpers.another_sample_commit).id }
let(:target_branch) { double(ref: 'master', repo: repository, sha: target_sha, user: octocat) } let(:target_branch) { { ref: 'master', repo: repository, sha: target_sha, user: octocat } }
let(:pull_request) do let(:pull_request) do
double( {
number: 1347, number: 1347,
milestone: nil, milestone: nil,
state: 'open', state: 'open',
@ -236,12 +236,12 @@ RSpec.describe Gitlab::LegacyGithubImport::Importer do
closed_at: nil, closed_at: nil,
merged_at: nil, merged_at: nil,
url: "#{api_root}/repos/octocat/Hello-World/pulls/1347", url: "#{api_root}/repos/octocat/Hello-World/pulls/1347",
labels: [double(name: 'Label #2')] labels: [{ name: 'Label #2' }]
) }
end end
let(:closed_pull_request) do let(:closed_pull_request) do
double( {
number: 1347, number: 1347,
milestone: nil, milestone: nil,
state: 'closed', state: 'closed',
@ -256,8 +256,8 @@ RSpec.describe Gitlab::LegacyGithubImport::Importer do
closed_at: updated_at, closed_at: updated_at,
merged_at: nil, merged_at: nil,
url: "#{api_root}/repos/octocat/Hello-World/pulls/1347", url: "#{api_root}/repos/octocat/Hello-World/pulls/1347",
labels: [double(name: 'Label #2')] labels: [{ name: 'Label #2' }]
) }
end end
context 'when importing a Gitea project' do context 'when importing a Gitea project' do

View File

@ -4,7 +4,7 @@ require 'fast_spec_helper'
RSpec.describe Gitlab::LegacyGithubImport::IssuableFormatter do RSpec.describe Gitlab::LegacyGithubImport::IssuableFormatter do
let(:raw_data) do let(:raw_data) do
double(number: 42) { number: 42 }
end end
let(:project) { double(import_type: 'github') } let(:project) { double(import_type: 'github') }

View File

@ -3,9 +3,9 @@
require 'spec_helper' require 'spec_helper'
RSpec.describe Gitlab::LegacyGithubImport::IssueFormatter do RSpec.describe Gitlab::LegacyGithubImport::IssueFormatter do
let_it_be(:project) { create(:project, namespace: create(:namespace, path: 'octocat')) }
let(:client) { double } let(:client) { double }
let!(:project) { create(:project, namespace: create(:namespace, path: 'octocat')) } let(:octocat) { { id: 123456, login: 'octocat', email: 'octocat@example.com' } }
let(:octocat) { double(id: 123456, login: 'octocat', email: 'octocat@example.com') }
let(:created_at) { DateTime.strptime('2011-01-26T19:01:12Z') } let(:created_at) { DateTime.strptime('2011-01-26T19:01:12Z') }
let(:updated_at) { DateTime.strptime('2011-01-27T19:01:12Z') } let(:updated_at) { DateTime.strptime('2011-01-27T19:01:12Z') }
@ -34,7 +34,7 @@ RSpec.describe Gitlab::LegacyGithubImport::IssueFormatter do
shared_examples 'Gitlab::LegacyGithubImport::IssueFormatter#attributes' do shared_examples 'Gitlab::LegacyGithubImport::IssueFormatter#attributes' do
context 'when issue is open' do context 'when issue is open' do
let(:raw_data) { double(base_data.merge(state: 'open')) } let(:raw_data) { base_data.merge(state: 'open') }
it 'returns formatted attributes' do it 'returns formatted attributes' do
expected = { expected = {
@ -55,7 +55,7 @@ RSpec.describe Gitlab::LegacyGithubImport::IssueFormatter do
end end
context 'when issue is closed' do context 'when issue is closed' do
let(:raw_data) { double(base_data.merge(state: 'closed')) } let(:raw_data) { base_data.merge(state: 'closed') }
it 'returns formatted attributes' do it 'returns formatted attributes' do
expected = { expected = {
@ -76,28 +76,28 @@ RSpec.describe Gitlab::LegacyGithubImport::IssueFormatter do
end end
context 'when it is assigned to someone' do context 'when it is assigned to someone' do
let(:raw_data) { double(base_data.merge(assignee: octocat)) } let(:raw_data) { base_data.merge(assignee: octocat) }
it 'returns nil as assignee_id when is not a GitLab user' do it 'returns nil as assignee_id when is not a GitLab user' do
expect(issue.attributes.fetch(:assignee_ids)).to be_empty expect(issue.attributes.fetch(:assignee_ids)).to be_empty
end end
it 'returns GitLab user id associated with GitHub id as assignee_id' do it 'returns GitLab user id associated with GitHub id as assignee_id' do
gl_user = create(:omniauth_user, extern_uid: octocat.id, provider: 'github') gl_user = create(:omniauth_user, extern_uid: octocat[:id], provider: 'github')
expect(issue.attributes.fetch(:assignee_ids)).to eq [gl_user.id] expect(issue.attributes.fetch(:assignee_ids)).to eq [gl_user.id]
end end
it 'returns GitLab user id associated with GitHub email as assignee_id' do it 'returns GitLab user id associated with GitHub email as assignee_id' do
gl_user = create(:user, email: octocat.email) gl_user = create(:user, email: octocat[:email])
expect(issue.attributes.fetch(:assignee_ids)).to eq [gl_user.id] expect(issue.attributes.fetch(:assignee_ids)).to eq [gl_user.id]
end end
end end
context 'when it has a milestone' do context 'when it has a milestone' do
let(:milestone) { double(id: 42, number: 42) } let(:milestone) { { id: 42, number: 42 } }
let(:raw_data) { double(base_data.merge(milestone: milestone)) } let(:raw_data) { base_data.merge(milestone: milestone) }
it 'returns nil when milestone does not exist' do it 'returns nil when milestone does not exist' do
expect(issue.attributes.fetch(:milestone)).to be_nil expect(issue.attributes.fetch(:milestone)).to be_nil
@ -111,26 +111,26 @@ RSpec.describe Gitlab::LegacyGithubImport::IssueFormatter do
end end
context 'when author is a GitLab user' do context 'when author is a GitLab user' do
let(:raw_data) { double(base_data.merge(user: octocat)) } let(:raw_data) { base_data.merge(user: octocat) }
it 'returns project creator_id as author_id when is not a GitLab user' do it 'returns project creator_id as author_id when is not a GitLab user' do
expect(issue.attributes.fetch(:author_id)).to eq project.creator_id expect(issue.attributes.fetch(:author_id)).to eq project.creator_id
end end
it 'returns GitLab user id associated with GitHub id as author_id' do it 'returns GitLab user id associated with GitHub id as author_id' do
gl_user = create(:omniauth_user, extern_uid: octocat.id, provider: 'github') gl_user = create(:omniauth_user, extern_uid: octocat[:id], provider: 'github')
expect(issue.attributes.fetch(:author_id)).to eq gl_user.id expect(issue.attributes.fetch(:author_id)).to eq gl_user.id
end end
it 'returns GitLab user id associated with GitHub email as author_id' do it 'returns GitLab user id associated with GitHub email as author_id' do
gl_user = create(:user, email: octocat.email) gl_user = create(:user, email: octocat[:email])
expect(issue.attributes.fetch(:author_id)).to eq gl_user.id expect(issue.attributes.fetch(:author_id)).to eq gl_user.id
end end
it 'returns description without created at tag line' do it 'returns description without created at tag line' do
create(:omniauth_user, extern_uid: octocat.id, provider: 'github') create(:omniauth_user, extern_uid: octocat[:id], provider: 'github')
expect(issue.attributes.fetch(:description)).to eq("I'm having a problem with this.") expect(issue.attributes.fetch(:description)).to eq("I'm having a problem with this.")
end end
@ -138,7 +138,7 @@ RSpec.describe Gitlab::LegacyGithubImport::IssueFormatter do
end end
shared_examples 'Gitlab::LegacyGithubImport::IssueFormatter#number' do shared_examples 'Gitlab::LegacyGithubImport::IssueFormatter#number' do
let(:raw_data) { double(base_data.merge(number: 1347)) } let(:raw_data) { base_data.merge(number: 1347) }
it 'returns issue number' do it 'returns issue number' do
expect(issue.number).to eq 1347 expect(issue.number).to eq 1347
@ -161,7 +161,7 @@ RSpec.describe Gitlab::LegacyGithubImport::IssueFormatter do
describe '#has_comments?' do describe '#has_comments?' do
context 'when number of comments is greater than zero' do context 'when number of comments is greater than zero' do
let(:raw_data) { double(base_data.merge(comments: 1)) } let(:raw_data) { base_data.merge(comments: 1) }
it 'returns true' do it 'returns true' do
expect(issue.has_comments?).to eq true expect(issue.has_comments?).to eq true
@ -169,7 +169,7 @@ RSpec.describe Gitlab::LegacyGithubImport::IssueFormatter do
end end
context 'when number of comments is equal to zero' do context 'when number of comments is equal to zero' do
let(:raw_data) { double(base_data.merge(comments: 0)) } let(:raw_data) { base_data.merge(comments: 0) }
it 'returns false' do it 'returns false' do
expect(issue.has_comments?).to eq false expect(issue.has_comments?).to eq false
@ -179,7 +179,7 @@ RSpec.describe Gitlab::LegacyGithubImport::IssueFormatter do
describe '#pull_request?' do describe '#pull_request?' do
context 'when mention a pull request' do context 'when mention a pull request' do
let(:raw_data) { double(base_data.merge(pull_request: double)) } let(:raw_data) { base_data.merge(pull_request: double) }
it 'returns true' do it 'returns true' do
expect(issue.pull_request?).to eq true expect(issue.pull_request?).to eq true
@ -187,7 +187,7 @@ RSpec.describe Gitlab::LegacyGithubImport::IssueFormatter do
end end
context 'when does not mention a pull request' do context 'when does not mention a pull request' do
let(:raw_data) { double(base_data.merge(pull_request: nil)) } let(:raw_data) { base_data.merge(pull_request: nil) }
it 'returns false' do it 'returns false' do
expect(issue.pull_request?).to eq false expect(issue.pull_request?).to eq false

View File

@ -3,8 +3,8 @@
require 'spec_helper' require 'spec_helper'
RSpec.describe Gitlab::LegacyGithubImport::LabelFormatter do RSpec.describe Gitlab::LegacyGithubImport::LabelFormatter do
let(:project) { create(:project) } let_it_be(:project) { create(:project) }
let(:raw) { double(name: 'improvements', color: 'e6e6e6') } let(:raw) { { name: 'improvements', color: 'e6e6e6' } }
subject { described_class.new(project, raw) } subject { described_class.new(project, raw) }
@ -27,7 +27,7 @@ RSpec.describe Gitlab::LegacyGithubImport::LabelFormatter do
context 'when label exists' do context 'when label exists' do
it 'does not create a new label' do it 'does not create a new label' do
Labels::CreateService.new(name: raw.name).execute(project: project) Labels::CreateService.new(name: raw[:name]).execute(project: project)
expect { subject.create! }.not_to change(Label, :count) expect { subject.create! }.not_to change(Label, :count)
end end

View File

@ -3,7 +3,7 @@
require 'spec_helper' require 'spec_helper'
RSpec.describe Gitlab::LegacyGithubImport::MilestoneFormatter do RSpec.describe Gitlab::LegacyGithubImport::MilestoneFormatter do
let(:project) { create(:project) } let_it_be(:project) { create(:project) }
let(:created_at) { DateTime.strptime('2011-01-26T19:01:12Z') } let(:created_at) { DateTime.strptime('2011-01-26T19:01:12Z') }
let(:updated_at) { DateTime.strptime('2011-01-27T19:01:12Z') } let(:updated_at) { DateTime.strptime('2011-01-27T19:01:12Z') }
let(:base_data) do let(:base_data) do
@ -26,7 +26,7 @@ RSpec.describe Gitlab::LegacyGithubImport::MilestoneFormatter do
let(:data) { base_data.merge(iid_attr => 1347) } let(:data) { base_data.merge(iid_attr => 1347) }
context 'when milestone is open' do context 'when milestone is open' do
let(:raw_data) { double(data.merge(state: 'open')) } let(:raw_data) { data.merge(state: 'open') }
it 'returns formatted attributes' do it 'returns formatted attributes' do
expected = { expected = {
@ -45,7 +45,7 @@ RSpec.describe Gitlab::LegacyGithubImport::MilestoneFormatter do
end end
context 'when milestone is closed' do context 'when milestone is closed' do
let(:raw_data) { double(data.merge(state: 'closed')) } let(:raw_data) { data.merge(state: 'closed') }
it 'returns formatted attributes' do it 'returns formatted attributes' do
expected = { expected = {
@ -65,7 +65,7 @@ RSpec.describe Gitlab::LegacyGithubImport::MilestoneFormatter do
context 'when milestone has a due date' do context 'when milestone has a due date' do
let(:due_date) { DateTime.strptime('2011-01-28T19:01:12Z') } let(:due_date) { DateTime.strptime('2011-01-28T19:01:12Z') }
let(:raw_data) { double(data.merge(due_on: due_date)) } let(:raw_data) { data.merge(due_on: due_date) }
it 'returns formatted attributes' do it 'returns formatted attributes' do
expected = { expected = {

View File

@ -3,22 +3,22 @@
require 'spec_helper' require 'spec_helper'
RSpec.describe Gitlab::LegacyGithubImport::PullRequestFormatter do RSpec.describe Gitlab::LegacyGithubImport::PullRequestFormatter do
let_it_be(:project) { create(:project, :repository) }
let(:client) { double } let(:client) { double }
let(:project) { create(:project, :repository) }
let(:source_sha) { create(:commit, project: project).id } let(:source_sha) { create(:commit, project: project).id }
let(:target_commit) { create(:commit, project: project, git_commit: RepoHelpers.another_sample_commit) } let(:target_commit) { create(:commit, project: project, git_commit: RepoHelpers.another_sample_commit) }
let(:target_sha) { target_commit.id } let(:target_sha) { target_commit.id }
let(:target_short_sha) { target_commit.id.to_s[0..7] } let(:target_short_sha) { target_commit.id.to_s[0..7] }
let(:repository) { double(id: 1, fork: false) } let(:repository) { { id: 1, fork: false } }
let(:source_repo) { repository } let(:source_repo) { repository }
let(:source_branch) { double(ref: 'branch-merged', repo: source_repo, sha: source_sha) } let(:source_branch) { { ref: 'branch-merged', repo: source_repo, sha: source_sha } }
let(:forked_source_repo) { double(id: 2, fork: true, name: 'otherproject', full_name: 'company/otherproject') } let(:forked_source_repo) { { id: 2, fork: true, name: 'otherproject', full_name: 'company/otherproject' } }
let(:target_repo) { repository } let(:target_repo) { repository }
let(:target_branch) { double(ref: 'master', repo: target_repo, sha: target_sha, user: octocat) } let(:target_branch) { { ref: 'master', repo: target_repo, sha: target_sha, user: octocat } }
let(:removed_branch) { double(ref: 'removed-branch', repo: source_repo, sha: '2e5d3239642f9161dcbbc4b70a211a68e5e45e2b', user: octocat) } let(:removed_branch) { { ref: 'removed-branch', repo: source_repo, sha: '2e5d3239642f9161dcbbc4b70a211a68e5e45e2b', user: octocat } }
let(:forked_branch) { double(ref: 'master', repo: forked_source_repo, sha: '2e5d3239642f9161dcbbc4b70a211a68e5e45e2b', user: octocat) } let(:forked_branch) { { ref: 'master', repo: forked_source_repo, sha: '2e5d3239642f9161dcbbc4b70a211a68e5e45e2b', user: octocat } }
let(:branch_deleted_repo) { double(ref: 'master', repo: nil, sha: '2e5d3239642f9161dcbbc4b70a211a68e5e45e2b', user: octocat) } let(:branch_deleted_repo) { { ref: 'master', repo: nil, sha: '2e5d3239642f9161dcbbc4b70a211a68e5e45e2b', user: octocat } }
let(:octocat) { double(id: 123456, login: 'octocat', email: 'octocat@example.com') } let(:octocat) { { id: 123456, login: 'octocat', email: 'octocat@example.com' } }
let(:created_at) { DateTime.strptime('2011-01-26T19:01:12Z') } let(:created_at) { DateTime.strptime('2011-01-26T19:01:12Z') }
let(:updated_at) { DateTime.strptime('2011-01-27T19:01:12Z') } let(:updated_at) { DateTime.strptime('2011-01-27T19:01:12Z') }
let(:base_data) do let(:base_data) do
@ -48,7 +48,7 @@ RSpec.describe Gitlab::LegacyGithubImport::PullRequestFormatter do
shared_examples 'Gitlab::LegacyGithubImport::PullRequestFormatter#attributes' do shared_examples 'Gitlab::LegacyGithubImport::PullRequestFormatter#attributes' do
context 'when pull request is open' do context 'when pull request is open' do
let(:raw_data) { double(base_data.merge(state: 'open')) } let(:raw_data) { base_data.merge(state: 'open') }
it 'returns formatted attributes' do it 'returns formatted attributes' do
expected = { expected = {
@ -75,7 +75,7 @@ RSpec.describe Gitlab::LegacyGithubImport::PullRequestFormatter do
end end
context 'when pull request is closed' do context 'when pull request is closed' do
let(:raw_data) { double(base_data.merge(state: 'closed')) } let(:raw_data) { base_data.merge(state: 'closed') }
it 'returns formatted attributes' do it 'returns formatted attributes' do
expected = { expected = {
@ -103,7 +103,7 @@ RSpec.describe Gitlab::LegacyGithubImport::PullRequestFormatter do
context 'when pull request is merged' do context 'when pull request is merged' do
let(:merged_at) { DateTime.strptime('2011-01-28T13:01:12Z') } let(:merged_at) { DateTime.strptime('2011-01-28T13:01:12Z') }
let(:raw_data) { double(base_data.merge(state: 'closed', merged_at: merged_at)) } let(:raw_data) { base_data.merge(state: 'closed', merged_at: merged_at) }
it 'returns formatted attributes' do it 'returns formatted attributes' do
expected = { expected = {
@ -130,54 +130,54 @@ RSpec.describe Gitlab::LegacyGithubImport::PullRequestFormatter do
end end
context 'when it is assigned to someone' do context 'when it is assigned to someone' do
let(:raw_data) { double(base_data.merge(assignee: octocat)) } let(:raw_data) { base_data.merge(assignee: octocat) }
it 'returns nil as assignee_id when is not a GitLab user' do it 'returns nil as assignee_id when is not a GitLab user' do
expect(pull_request.attributes.fetch(:assignee_id)).to be_nil expect(pull_request.attributes.fetch(:assignee_id)).to be_nil
end end
it 'returns GitLab user id associated with GitHub id as assignee_id' do it 'returns GitLab user id associated with GitHub id as assignee_id' do
gl_user = create(:omniauth_user, extern_uid: octocat.id, provider: 'github') gl_user = create(:omniauth_user, extern_uid: octocat[:id], provider: 'github')
expect(pull_request.attributes.fetch(:assignee_id)).to eq gl_user.id expect(pull_request.attributes.fetch(:assignee_id)).to eq gl_user.id
end end
it 'returns GitLab user id associated with GitHub email as assignee_id' do it 'returns GitLab user id associated with GitHub email as assignee_id' do
gl_user = create(:user, email: octocat.email) gl_user = create(:user, email: octocat[:email])
expect(pull_request.attributes.fetch(:assignee_id)).to eq gl_user.id expect(pull_request.attributes.fetch(:assignee_id)).to eq gl_user.id
end end
end end
context 'when author is a GitLab user' do context 'when author is a GitLab user' do
let(:raw_data) { double(base_data.merge(user: octocat)) } let(:raw_data) { base_data.merge(user: octocat) }
it 'returns project creator_id as author_id when is not a GitLab user' do it 'returns project creator_id as author_id when is not a GitLab user' do
expect(pull_request.attributes.fetch(:author_id)).to eq project.creator_id expect(pull_request.attributes.fetch(:author_id)).to eq project.creator_id
end end
it 'returns GitLab user id associated with GitHub id as author_id' do it 'returns GitLab user id associated with GitHub id as author_id' do
gl_user = create(:omniauth_user, extern_uid: octocat.id, provider: 'github') gl_user = create(:omniauth_user, extern_uid: octocat[:id], provider: 'github')
expect(pull_request.attributes.fetch(:author_id)).to eq gl_user.id expect(pull_request.attributes.fetch(:author_id)).to eq gl_user.id
end end
it 'returns GitLab user id associated with GitHub email as author_id' do it 'returns GitLab user id associated with GitHub email as author_id' do
gl_user = create(:user, email: octocat.email) gl_user = create(:user, email: octocat[:email])
expect(pull_request.attributes.fetch(:author_id)).to eq gl_user.id expect(pull_request.attributes.fetch(:author_id)).to eq gl_user.id
end end
it 'returns description without created at tag line' do it 'returns description without created at tag line' do
create(:omniauth_user, extern_uid: octocat.id, provider: 'github') create(:omniauth_user, extern_uid: octocat[:id], provider: 'github')
expect(pull_request.attributes.fetch(:description)).to eq('Please pull these awesome changes') expect(pull_request.attributes.fetch(:description)).to eq('Please pull these awesome changes')
end end
end end
context 'when it has a milestone' do context 'when it has a milestone' do
let(:milestone) { double(id: 42, number: 42) } let(:milestone) { { id: 42, number: 42 } }
let(:raw_data) { double(base_data.merge(milestone: milestone)) } let(:raw_data) { base_data.merge(milestone: milestone) }
it 'returns nil when milestone does not exist' do it 'returns nil when milestone does not exist' do
expect(pull_request.attributes.fetch(:milestone)).to be_nil expect(pull_request.attributes.fetch(:milestone)).to be_nil
@ -192,7 +192,7 @@ RSpec.describe Gitlab::LegacyGithubImport::PullRequestFormatter do
end end
shared_examples 'Gitlab::LegacyGithubImport::PullRequestFormatter#number' do shared_examples 'Gitlab::LegacyGithubImport::PullRequestFormatter#number' do
let(:raw_data) { double(base_data) } let(:raw_data) { base_data }
it 'returns pull request number' do it 'returns pull request number' do
expect(pull_request.number).to eq 1347 expect(pull_request.number).to eq 1347
@ -201,7 +201,7 @@ RSpec.describe Gitlab::LegacyGithubImport::PullRequestFormatter do
shared_examples 'Gitlab::LegacyGithubImport::PullRequestFormatter#source_branch_name' do shared_examples 'Gitlab::LegacyGithubImport::PullRequestFormatter#source_branch_name' do
context 'when source branch exists' do context 'when source branch exists' do
let(:raw_data) { double(base_data) } let(:raw_data) { base_data }
it 'returns branch ref' do it 'returns branch ref' do
expect(pull_request.source_branch_name).to eq 'branch-merged' expect(pull_request.source_branch_name).to eq 'branch-merged'
@ -209,7 +209,7 @@ RSpec.describe Gitlab::LegacyGithubImport::PullRequestFormatter do
end end
context 'when source branch does not exist' do context 'when source branch does not exist' do
let(:raw_data) { double(base_data.merge(head: removed_branch)) } let(:raw_data) { base_data.merge(head: removed_branch) }
it 'prefixes branch name with gh-:short_sha/:number/:user pattern to avoid collision' do it 'prefixes branch name with gh-:short_sha/:number/:user pattern to avoid collision' do
expect(pull_request.source_branch_name).to eq "gh-#{target_short_sha}/1347/octocat/removed-branch" expect(pull_request.source_branch_name).to eq "gh-#{target_short_sha}/1347/octocat/removed-branch"
@ -217,7 +217,7 @@ RSpec.describe Gitlab::LegacyGithubImport::PullRequestFormatter do
end end
context 'when source branch is from a fork' do context 'when source branch is from a fork' do
let(:raw_data) { double(base_data.merge(head: forked_branch)) } let(:raw_data) { base_data.merge(head: forked_branch) }
it 'prefixes branch name with gh-:short_sha/:number/:user pattern to avoid collision' do it 'prefixes branch name with gh-:short_sha/:number/:user pattern to avoid collision' do
expect(pull_request.source_branch_name).to eq "gh-#{target_short_sha}/1347/octocat/master" expect(pull_request.source_branch_name).to eq "gh-#{target_short_sha}/1347/octocat/master"
@ -225,7 +225,7 @@ RSpec.describe Gitlab::LegacyGithubImport::PullRequestFormatter do
end end
context 'when source branch is from a deleted fork' do context 'when source branch is from a deleted fork' do
let(:raw_data) { double(base_data.merge(head: branch_deleted_repo)) } let(:raw_data) { base_data.merge(head: branch_deleted_repo) }
it 'prefixes branch name with gh-:short_sha/:number/:user pattern to avoid collision' do it 'prefixes branch name with gh-:short_sha/:number/:user pattern to avoid collision' do
expect(pull_request.source_branch_name).to eq "gh-#{target_short_sha}/1347/octocat/master" expect(pull_request.source_branch_name).to eq "gh-#{target_short_sha}/1347/octocat/master"
@ -235,7 +235,7 @@ RSpec.describe Gitlab::LegacyGithubImport::PullRequestFormatter do
shared_examples 'Gitlab::LegacyGithubImport::PullRequestFormatter#target_branch_name' do shared_examples 'Gitlab::LegacyGithubImport::PullRequestFormatter#target_branch_name' do
context 'when target branch exists' do context 'when target branch exists' do
let(:raw_data) { double(base_data) } let(:raw_data) { base_data }
it 'returns branch ref' do it 'returns branch ref' do
expect(pull_request.target_branch_name).to eq 'master' expect(pull_request.target_branch_name).to eq 'master'
@ -243,7 +243,7 @@ RSpec.describe Gitlab::LegacyGithubImport::PullRequestFormatter do
end end
context 'when target branch does not exist' do context 'when target branch does not exist' do
let(:raw_data) { double(base_data.merge(base: removed_branch)) } let(:raw_data) { base_data.merge(base: removed_branch) }
it 'prefixes branch name with gh-:short_sha/:number/:user pattern to avoid collision' do it 'prefixes branch name with gh-:short_sha/:number/:user pattern to avoid collision' do
expect(pull_request.target_branch_name).to eq 'gl-2e5d3239/1347/octocat/removed-branch' expect(pull_request.target_branch_name).to eq 'gl-2e5d3239/1347/octocat/removed-branch'
@ -271,7 +271,7 @@ RSpec.describe Gitlab::LegacyGithubImport::PullRequestFormatter do
describe '#valid?' do describe '#valid?' do
context 'when source, and target repos are not a fork' do context 'when source, and target repos are not a fork' do
let(:raw_data) { double(base_data) } let(:raw_data) { base_data }
it 'returns true' do it 'returns true' do
expect(pull_request.valid?).to eq true expect(pull_request.valid?).to eq true
@ -279,8 +279,8 @@ RSpec.describe Gitlab::LegacyGithubImport::PullRequestFormatter do
end end
context 'when source repo is a fork' do context 'when source repo is a fork' do
let(:source_repo) { double(id: 2) } let(:source_repo) { { id: 2 } }
let(:raw_data) { double(base_data) } let(:raw_data) { base_data }
it 'returns true' do it 'returns true' do
expect(pull_request.valid?).to eq true expect(pull_request.valid?).to eq true
@ -288,8 +288,8 @@ RSpec.describe Gitlab::LegacyGithubImport::PullRequestFormatter do
end end
context 'when target repo is a fork' do context 'when target repo is a fork' do
let(:target_repo) { double(id: 2) } let(:target_repo) { { id: 2 } }
let(:raw_data) { double(base_data) } let(:raw_data) { base_data }
it 'returns true' do it 'returns true' do
expect(pull_request.valid?).to eq true expect(pull_request.valid?).to eq true
@ -299,7 +299,7 @@ RSpec.describe Gitlab::LegacyGithubImport::PullRequestFormatter do
describe '#cross_project?' do describe '#cross_project?' do
context 'when source and target repositories are different' do context 'when source and target repositories are different' do
let(:raw_data) { double(base_data.merge(head: forked_branch)) } let(:raw_data) { base_data.merge(head: forked_branch) }
it 'returns true' do it 'returns true' do
expect(pull_request.cross_project?).to eq true expect(pull_request.cross_project?).to eq true
@ -307,7 +307,7 @@ RSpec.describe Gitlab::LegacyGithubImport::PullRequestFormatter do
end end
context 'when source repository does not exist anymore' do context 'when source repository does not exist anymore' do
let(:raw_data) { double(base_data.merge(head: branch_deleted_repo)) } let(:raw_data) { base_data.merge(head: branch_deleted_repo) }
it 'returns true' do it 'returns true' do
expect(pull_request.cross_project?).to eq true expect(pull_request.cross_project?).to eq true
@ -315,7 +315,7 @@ RSpec.describe Gitlab::LegacyGithubImport::PullRequestFormatter do
end end
context 'when source and target repositories are the same' do context 'when source and target repositories are the same' do
let(:raw_data) { double(base_data.merge(head: source_branch)) } let(:raw_data) { base_data.merge(head: source_branch) }
it 'returns false' do it 'returns false' do
expect(pull_request.cross_project?).to eq false expect(pull_request.cross_project?).to eq false
@ -324,7 +324,7 @@ RSpec.describe Gitlab::LegacyGithubImport::PullRequestFormatter do
end end
describe '#source_branch_exists?' do describe '#source_branch_exists?' do
let(:raw_data) { double(base_data.merge(head: forked_branch)) } let(:raw_data) { base_data.merge(head: forked_branch) }
it 'returns false when is a cross_project' do it 'returns false when is a cross_project' do
expect(pull_request.source_branch_exists?).to eq false expect(pull_request.source_branch_exists?).to eq false
@ -332,7 +332,7 @@ RSpec.describe Gitlab::LegacyGithubImport::PullRequestFormatter do
end end
describe '#url' do describe '#url' do
let(:raw_data) { double(base_data) } let(:raw_data) { base_data }
it 'return raw url' do it 'return raw url' do
expect(pull_request.url).to eq 'https://api.github.com/repos/octocat/Hello-World/pulls/1347' expect(pull_request.url).to eq 'https://api.github.com/repos/octocat/Hello-World/pulls/1347'
@ -340,7 +340,7 @@ RSpec.describe Gitlab::LegacyGithubImport::PullRequestFormatter do
end end
describe '#opened?' do describe '#opened?' do
let(:raw_data) { double(base_data.merge(state: 'open')) } let(:raw_data) { base_data.merge(state: 'open') }
it 'returns true when state is "open"' do it 'returns true when state is "open"' do
expect(pull_request.opened?).to be_truthy expect(pull_request.opened?).to be_truthy

View File

@ -3,8 +3,8 @@
require 'spec_helper' require 'spec_helper'
RSpec.describe Gitlab::LegacyGithubImport::ReleaseFormatter do RSpec.describe Gitlab::LegacyGithubImport::ReleaseFormatter do
let!(:project) { create(:project, namespace: create(:namespace, path: 'octocat')) } let_it_be(:project) { create(:project, namespace: create(:namespace, path: 'octocat')) }
let(:octocat) { double(id: 123456, login: 'octocat') } let(:octocat) { { id: 123456, login: 'octocat' } }
let(:created_at) { DateTime.strptime('2011-01-26T19:01:12Z') } let(:created_at) { DateTime.strptime('2011-01-26T19:01:12Z') }
let(:published_at) { DateTime.strptime('2011-01-26T20:00:00Z') } let(:published_at) { DateTime.strptime('2011-01-26T20:00:00Z') }
@ -22,7 +22,7 @@ RSpec.describe Gitlab::LegacyGithubImport::ReleaseFormatter do
subject(:release) { described_class.new(project, raw_data) } subject(:release) { described_class.new(project, raw_data) }
describe '#attributes' do describe '#attributes' do
let(:raw_data) { double(base_data) } let(:raw_data) { base_data }
it 'returns formatted attributes' do it 'returns formatted attributes' do
expected = { expected = {
@ -49,7 +49,7 @@ RSpec.describe Gitlab::LegacyGithubImport::ReleaseFormatter do
describe '#valid' do describe '#valid' do
context 'when release is not a draft' do context 'when release is not a draft' do
let(:raw_data) { double(base_data) } let(:raw_data) { base_data }
it 'returns true' do it 'returns true' do
expect(release.valid?).to eq true expect(release.valid?).to eq true
@ -57,7 +57,7 @@ RSpec.describe Gitlab::LegacyGithubImport::ReleaseFormatter do
end end
context 'when release is draft' do context 'when release is draft' do
let(:raw_data) { double(base_data.merge(draft: true)) } let(:raw_data) { base_data.merge(draft: true) }
it 'returns false' do it 'returns false' do
expect(release.valid?).to eq false expect(release.valid?).to eq false
@ -65,7 +65,7 @@ RSpec.describe Gitlab::LegacyGithubImport::ReleaseFormatter do
end end
context 'when release has NULL tag' do context 'when release has NULL tag' do
let(:raw_data) { double(base_data.merge(tag_name: '')) } let(:raw_data) { base_data.merge(tag_name: '') }
it 'returns false' do it 'returns false' do
expect(release.valid?).to eq false expect(release.valid?).to eq false

View File

@ -4,7 +4,7 @@ require 'spec_helper'
RSpec.describe Gitlab::LegacyGithubImport::UserFormatter do RSpec.describe Gitlab::LegacyGithubImport::UserFormatter do
let(:client) { double } let(:client) { double }
let(:octocat) { double(id: 123456, login: 'octocat', email: 'octocat@example.com') } let(:octocat) { { id: 123456, login: 'octocat', email: 'octocat@example.com' } }
subject(:user) { described_class.new(client, octocat) } subject(:user) { described_class.new(client, octocat) }
@ -15,33 +15,33 @@ RSpec.describe Gitlab::LegacyGithubImport::UserFormatter do
describe '#gitlab_id' do describe '#gitlab_id' do
context 'when GitHub user is a GitLab user' do context 'when GitHub user is a GitLab user' do
it 'return GitLab user id when user associated their account with GitHub' do it 'return GitLab user id when user associated their account with GitHub' do
gl_user = create(:omniauth_user, extern_uid: octocat.id, provider: 'github') gl_user = create(:omniauth_user, extern_uid: octocat[:id], provider: 'github')
expect(user.gitlab_id).to eq gl_user.id expect(user.gitlab_id).to eq gl_user.id
end end
it 'returns GitLab user id when user confirmed primary email matches GitHub email' do it 'returns GitLab user id when user confirmed primary email matches GitHub email' do
gl_user = create(:user, email: octocat.email) gl_user = create(:user, email: octocat[:email])
expect(user.gitlab_id).to eq gl_user.id expect(user.gitlab_id).to eq gl_user.id
end end
it 'returns GitLab user id when user unconfirmed primary email matches GitHub email' do it 'returns GitLab user id when user unconfirmed primary email matches GitHub email' do
gl_user = create(:user, :unconfirmed, email: octocat.email) gl_user = create(:user, :unconfirmed, email: octocat[:email])
expect(user.gitlab_id).to eq gl_user.id expect(user.gitlab_id).to eq gl_user.id
end end
it 'returns GitLab user id when user confirmed secondary email matches GitHub email' do it 'returns GitLab user id when user confirmed secondary email matches GitHub email' do
gl_user = create(:user, email: 'johndoe@example.com') gl_user = create(:user, email: 'johndoe@example.com')
create(:email, :confirmed, user: gl_user, email: octocat.email) create(:email, :confirmed, user: gl_user, email: octocat[:email])
expect(user.gitlab_id).to eq gl_user.id expect(user.gitlab_id).to eq gl_user.id
end end
it 'returns nil when user unconfirmed secondary email matches GitHub email' do it 'returns nil when user unconfirmed secondary email matches GitHub email' do
gl_user = create(:user, email: 'johndoe@example.com') gl_user = create(:user, email: 'johndoe@example.com')
create(:email, user: gl_user, email: octocat.email) create(:email, user: gl_user, email: octocat[:email])
expect(user.gitlab_id).to be_nil expect(user.gitlab_id).to be_nil
end end

View File

@ -0,0 +1,35 @@
# frozen_string_literal: true
require 'spec_helper'
require_migration!
RSpec.describe ScheduleResetDuplicateCiRunnersTokenValues, migration: :gitlab_ci do
let(:migration) { described_class::MIGRATION }
describe '#up' do
it 'schedules background jobs for each batch of runners' do
migrate!
expect(migration).to(
have_scheduled_batched_migration(
gitlab_schema: :gitlab_ci,
table_name: :ci_runners,
column_name: :id,
interval: described_class::DELAY_INTERVAL,
batch_size: described_class::BATCH_SIZE,
max_batch_size: described_class::MAX_BATCH_SIZE,
sub_batch_size: described_class::SUB_BATCH_SIZE
)
)
end
end
describe '#down' do
it 'deletes all batched migration records' do
migrate!
schema_migrate_down!
expect(migration).not_to have_scheduled_batched_migration
end
end
end

View File

@ -0,0 +1,35 @@
# frozen_string_literal: true
require 'spec_helper'
require_migration!
RSpec.describe ScheduleResetDuplicateCiRunnersTokenEncryptedValues, migration: :gitlab_ci do
let(:migration) { described_class::MIGRATION }
describe '#up' do
it 'schedules background jobs for each batch of runners' do
migrate!
expect(migration).to(
have_scheduled_batched_migration(
gitlab_schema: :gitlab_ci,
table_name: :ci_runners,
column_name: :id,
interval: described_class::DELAY_INTERVAL,
batch_size: described_class::BATCH_SIZE,
max_batch_size: described_class::MAX_BATCH_SIZE,
sub_batch_size: described_class::SUB_BATCH_SIZE
)
)
end
end
describe '#down' do
it 'deletes all batched migration records' do
migrate!
schema_migrate_down!
expect(migration).not_to have_scheduled_batched_migration
end
end
end

View File

@ -91,10 +91,6 @@ RSpec.describe Ci::PipelineArtifacts::DestroyAllExpiredService, :clean_gitlab_re
before do before do
create_list(:ci_pipeline_artifact, 2, :artifact_unlocked, expire_at: 1.week.ago) create_list(:ci_pipeline_artifact, 2, :artifact_unlocked, expire_at: 1.week.ago)
end
context 'with ci_destroy_unlocked_pipeline_artifacts feature flag enabled' do
before do
allow(service).to receive(:legacy_destroy_pipeline_artifacts) allow(service).to receive(:legacy_destroy_pipeline_artifacts)
end end
@ -119,19 +115,6 @@ RSpec.describe Ci::PipelineArtifacts::DestroyAllExpiredService, :clean_gitlab_re
end end
end end
end end
context 'with ci_destroy_unlocked_pipeline_artifacts feature flag disabled' do
before do
stub_feature_flags(ci_destroy_unlocked_pipeline_artifacts: false)
end
it 'destroys all expired artifacts' do
expect(service).not_to receive(:destroy_unlocked_pipeline_artifacts)
expect { subject }.to change { Ci::PipelineArtifact.count }.by(-2)
expect(not_expired_artifact.reload).to be_present
end
end
end
end end
describe '.destroy_artifacts_batch' do describe '.destroy_artifacts_batch' do

View File

@ -74,8 +74,8 @@ RSpec.describe ProjectCacheWorker do
context 'with plain readme' do context 'with plain readme' do
it 'refreshes the method caches' do it 'refreshes the method caches' do
allow(MarkupHelper).to receive(:gitlab_markdown?).and_return(false) allow(Gitlab::MarkupHelper).to receive(:gitlab_markdown?).and_return(false)
allow(MarkupHelper).to receive(:plain?).and_return(true) allow(Gitlab::MarkupHelper).to receive(:plain?).and_return(true)
expect_any_instance_of(Repository).to receive(:refresh_method_caches) expect_any_instance_of(Repository).to receive(:refresh_method_caches)
.with(%i(readme)) .with(%i(readme))