summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Gemfile2
-rw-r--r--Gemfile.lock4
-rw-r--r--app/models/concerns/bulk_insert_safe.rb35
-rw-r--r--app/services/projects/import_export/export_service.rb2
-rw-r--r--app/services/projects/prometheus/alerts/notify_service.rb124
-rw-r--r--changelogs/unreleased/211818-enable-streaming-serializer-ff.yml5
-rw-r--r--changelogs/unreleased/dblessing_okta_scim.yml5
-rw-r--r--config/initializers/active_record_schema_versions.rb5
-rw-r--r--db/structure.sql2039
-rw-r--r--doc/development/chatops_on_gitlabcom.md2
-rw-r--r--lib/api/releases.rb4
-rw-r--r--lib/gitlab/database/postgresql_adapter/schema_versions_copy_mixin.rb28
-rw-r--r--lib/gitlab/profiler.rb4
-rw-r--r--lib/gitlab/profiler/total_time_flat_printer.rb42
-rw-r--r--lib/gitlab/setup_helper.rb143
-rw-r--r--lib/tasks/gitlab/gitaly.rake2
-rw-r--r--lib/uploaded_file.rb2
-rw-r--r--package.json2
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/merge_request/rebase_merge_request_spec.rb2
-rwxr-xr-xscripts/gitaly-test-build7
-rwxr-xr-xscripts/gitaly-test-spawn5
-rw-r--r--scripts/gitaly_test.rb37
-rw-r--r--spec/lib/gitlab/database/postgresql_adapter/schema_versions_copy_mixin_spec.rb42
-rw-r--r--spec/lib/uploaded_file_spec.rb10
-rw-r--r--spec/models/concerns/bulk_insert_safe_spec.rb31
-rw-r--r--spec/requests/api/releases_spec.rb20
-rw-r--r--spec/services/projects/prometheus/alerts/notify_service_spec.rb343
-rw-r--r--spec/support/helpers/test_env.rb53
-rw-r--r--spec/support/praefect.rb11
-rw-r--r--spec/support/shared_examples/models/concerns/bulk_insert_safe_shared_examples.rb6
-rw-r--r--yarn.lock8
31 files changed, 1843 insertions, 1182 deletions
diff --git a/Gemfile b/Gemfile
index e70e64c0875..414a8a67744 100644
--- a/Gemfile
+++ b/Gemfile
@@ -425,7 +425,7 @@ gem 'gitlab-mail_room', '~> 0.0.3', require: 'mail_room'
gem 'email_reply_trimmer', '~> 0.1'
gem 'html2text'
-gem 'ruby-prof', '~> 1.0.0'
+gem 'ruby-prof', '~> 1.3.0'
gem 'stackprof', '~> 0.2.15', require: false
gem 'rbtrace', '~> 0.4', require: false
gem 'memory_profiler', '~> 0.9', require: false
diff --git a/Gemfile.lock b/Gemfile.lock
index e96a38ccf22..bb64fb09649 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -951,7 +951,7 @@ GEM
i18n
ruby-fogbugz (0.2.1)
crack (~> 0.4)
- ruby-prof (1.0.0)
+ ruby-prof (1.3.1)
ruby-progressbar (1.10.1)
ruby-saml (1.7.2)
nokogiri (>= 1.5.10)
@@ -1358,7 +1358,7 @@ DEPENDENCIES
rubocop-performance (~> 1.4.1)
rubocop-rspec (~> 1.37.0)
ruby-fogbugz (~> 0.2.1)
- ruby-prof (~> 1.0.0)
+ ruby-prof (~> 1.3.0)
ruby-progressbar
ruby_parser (~> 3.8)
rubyzip (~> 2.0.0)
diff --git a/app/models/concerns/bulk_insert_safe.rb b/app/models/concerns/bulk_insert_safe.rb
index a61db2dc148..f1a2d566e97 100644
--- a/app/models/concerns/bulk_insert_safe.rb
+++ b/app/models/concerns/bulk_insert_safe.rb
@@ -68,6 +68,9 @@ module BulkInsertSafe
# @param [Boolean] validate Whether validations should run on [items]
# @param [Integer] batch_size How many items should at most be inserted at once
# @param [Boolean] skip_duplicates Marks duplicates as allowed, and skips inserting them
+ # @param [Symbol] returns Pass :ids to return an array with the primary key values
+ # for all inserted records or nil to omit the underlying
+ # RETURNING SQL clause entirely.
# @param [Proc] handle_attributes Block that will receive each item attribute hash
# prior to insertion for further processing
#
@@ -78,10 +81,11 @@ module BulkInsertSafe
#
# @return true if operation succeeded, throws otherwise.
#
- def bulk_insert!(items, validate: true, skip_duplicates: false, batch_size: DEFAULT_BATCH_SIZE, &handle_attributes)
+ def bulk_insert!(items, validate: true, skip_duplicates: false, returns: nil, batch_size: DEFAULT_BATCH_SIZE, &handle_attributes)
_bulk_insert_all!(items,
validate: validate,
on_duplicate: skip_duplicates ? :skip : :raise,
+ returns: returns,
unique_by: nil,
batch_size: batch_size,
&handle_attributes)
@@ -94,6 +98,9 @@ module BulkInsertSafe
# @param [Boolean] validate Whether validations should run on [items]
# @param [Integer] batch_size How many items should at most be inserted at once
# @param [Symbol/Array] unique_by Defines index or columns to use to consider item duplicate
+ # @param [Symbol] returns Pass :ids to return an array with the primary key values
+ # for all inserted or updated records or nil to omit the
+ # underlying RETURNING SQL clause entirely.
# @param [Proc] handle_attributes Block that will receive each item attribute hash
# prior to insertion for further processing
#
@@ -109,10 +116,11 @@ module BulkInsertSafe
#
# @return true if operation succeeded, throws otherwise.
#
- def bulk_upsert!(items, unique_by:, validate: true, batch_size: DEFAULT_BATCH_SIZE, &handle_attributes)
+ def bulk_upsert!(items, unique_by:, returns: nil, validate: true, batch_size: DEFAULT_BATCH_SIZE, &handle_attributes)
_bulk_insert_all!(items,
validate: validate,
on_duplicate: :update,
+ returns: returns,
unique_by: unique_by,
batch_size: batch_size,
&handle_attributes)
@@ -120,21 +128,30 @@ module BulkInsertSafe
private
- def _bulk_insert_all!(items, on_duplicate:, unique_by:, validate:, batch_size:, &handle_attributes)
- return true if items.empty?
+ def _bulk_insert_all!(items, on_duplicate:, returns:, unique_by:, validate:, batch_size:, &handle_attributes)
+ return [] if items.empty?
+
+ returning =
+ case returns
+ when :ids
+ [primary_key]
+ when nil
+ false
+ else
+ raise ArgumentError, "returns needs to be :ids or nil"
+ end
transaction do
- items.each_slice(batch_size) do |item_batch|
+ items.each_slice(batch_size).flat_map do |item_batch|
attributes = _bulk_insert_item_attributes(
item_batch, validate, &handle_attributes)
ActiveRecord::InsertAll
- .new(self, attributes, on_duplicate: on_duplicate, unique_by: unique_by)
- .execute
+ .new(self, attributes, on_duplicate: on_duplicate, returning: returning, unique_by: unique_by)
+ .execute
+ .pluck(primary_key)
end
end
-
- true
end
def _bulk_insert_item_attributes(items, validate_items)
diff --git a/app/services/projects/import_export/export_service.rb b/app/services/projects/import_export/export_service.rb
index f4214410226..fa098e7417c 100644
--- a/app/services/projects/import_export/export_service.rb
+++ b/app/services/projects/import_export/export_service.rb
@@ -58,7 +58,7 @@ module Projects
end
def tree_saver_class
- if ::Feature.enabled?(:streaming_serializer, project)
+ if ::Feature.enabled?(:streaming_serializer, project, default_enabled: true)
Gitlab::ImportExport::Project::TreeSaver
else
# Once we remove :streaming_serializer feature flag, Project::LegacyTreeSaver should be removed as well
diff --git a/app/services/projects/prometheus/alerts/notify_service.rb b/app/services/projects/prometheus/alerts/notify_service.rb
new file mode 100644
index 00000000000..89791aecabb
--- /dev/null
+++ b/app/services/projects/prometheus/alerts/notify_service.rb
@@ -0,0 +1,124 @@
+# frozen_string_literal: true
+
+module Projects
+ module Prometheus
+ module Alerts
+ class NotifyService < BaseService
+ include Gitlab::Utils::StrongMemoize
+ include IncidentManagement::Settings
+
+ def execute(token)
+ return false unless valid_payload_size?
+ return false unless valid_version?
+ return false unless valid_alert_manager_token?(token)
+
+ persist_events
+ send_alert_email if send_email?
+ process_incident_issues if process_issues?
+
+ true
+ end
+
+ private
+
+ def valid_payload_size?
+ Gitlab::Utils::DeepSize.new(params).valid?
+ end
+
+ def send_email?
+ incident_management_setting.send_email && firings.any?
+ end
+
+ def firings
+ @firings ||= alerts_by_status('firing')
+ end
+
+ def alerts_by_status(status)
+ alerts.select { |alert| alert['status'] == status }
+ end
+
+ def alerts
+ params['alerts']
+ end
+
+ def valid_version?
+ params['version'] == '4'
+ end
+
+ def valid_alert_manager_token?(token)
+ valid_for_manual?(token) || valid_for_managed?(token)
+ end
+
+ def valid_for_manual?(token)
+ prometheus = project.find_or_initialize_service('prometheus')
+ return false unless prometheus.manual_configuration?
+
+ if setting = project.alerting_setting
+ compare_token(token, setting.token)
+ else
+ token.nil?
+ end
+ end
+
+ def valid_for_managed?(token)
+ prometheus_application = available_prometheus_application(project)
+ return false unless prometheus_application
+
+ if token
+ compare_token(token, prometheus_application.alert_manager_token)
+ else
+ prometheus_application.alert_manager_token.nil?
+ end
+ end
+
+ def available_prometheus_application(project)
+ alert_id = gitlab_alert_id
+ return unless alert_id
+
+ alert = find_alert(project, alert_id)
+ return unless alert
+
+ cluster = alert.environment.deployment_platform&.cluster
+ return unless cluster&.enabled?
+ return unless cluster.application_prometheus_available?
+
+ cluster.application_prometheus
+ end
+
+ def find_alert(project, metric)
+ Projects::Prometheus::AlertsFinder
+ .new(project: project, metric: metric)
+ .execute
+ .first
+ end
+
+ def gitlab_alert_id
+ alerts&.first&.dig('labels', 'gitlab_alert_id')
+ end
+
+ def compare_token(expected, actual)
+ return unless expected && actual
+
+ ActiveSupport::SecurityUtils.secure_compare(expected, actual)
+ end
+
+ def send_alert_email
+ notification_service
+ .async
+ .prometheus_alerts_fired(project, firings)
+ end
+
+ def process_incident_issues
+ alerts.each do |alert|
+ IncidentManagement::ProcessPrometheusAlertWorker
+ .perform_async(project.id, alert.to_h)
+ end
+ end
+
+ def persist_events
+ CreateEventsService.new(project, nil, params).execute
+ end
+ end
+ end
+ end
+end
diff --git a/changelogs/unreleased/211818-enable-streaming-serializer-ff.yml b/changelogs/unreleased/211818-enable-streaming-serializer-ff.yml
new file mode 100644
index 00000000000..d0f420d0c26
--- /dev/null
+++ b/changelogs/unreleased/211818-enable-streaming-serializer-ff.yml
@@ -0,0 +1,5 @@
+---
+title: Enable streaming serializer feature flag by default.
+merge_request: 27813
+author:
+type: performance
diff --git a/changelogs/unreleased/dblessing_okta_scim.yml b/changelogs/unreleased/dblessing_okta_scim.yml
new file mode 100644
index 00000000000..16baae42004
--- /dev/null
+++ b/changelogs/unreleased/dblessing_okta_scim.yml
@@ -0,0 +1,5 @@
+---
+title: Add support for Okta as a SCIM provider
+merge_request: 25649
+author:
+type: added
diff --git a/config/initializers/active_record_schema_versions.rb b/config/initializers/active_record_schema_versions.rb
new file mode 100644
index 00000000000..a7c342e8053
--- /dev/null
+++ b/config/initializers/active_record_schema_versions.rb
@@ -0,0 +1,5 @@
+# frozen_string_literal: true
+
+# Patch to use COPY in db/structure.sql when populating schema_migrations table
+# This is intended to reduce potential for merge conflicts in db/structure.sql
+ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.prepend(Gitlab::Database::PostgresqlAdapter::SchemaVersionsCopyMixin)
diff --git a/db/structure.sql b/db/structure.sql
index 92671eb5ae4..6301ec6df80 100644
--- a/db/structure.sql
+++ b/db/structure.sql
@@ -11775,1023 +11775,1024 @@ ALTER TABLE ONLY public.timelogs
ALTER TABLE ONLY public.timelogs
ADD CONSTRAINT fk_timelogs_merge_requests_merge_request_id FOREIGN KEY (merge_request_id) REFERENCES public.merge_requests(id) ON DELETE CASCADE;
-INSERT INTO "schema_migrations" (version) VALUES
-('20171230123729'),
-('20180101160629'),
-('20180101160630'),
-('20180102220145'),
-('20180103123548'),
-('20180104131052'),
-('20180105212544'),
-('20180109183319'),
-('20180113220114'),
-('20180115094742'),
-('20180115113902'),
-('20180115201419'),
-('20180116193854'),
-('20180119121225'),
-('20180119135717'),
-('20180119160751'),
-('20180122154930'),
-('20180122162010'),
-('20180125214301'),
-('20180129193323'),
-('20180201102129'),
-('20180201110056'),
-('20180201145907'),
-('20180204200836'),
-('20180206200543'),
-('20180208183958'),
-('20180209115333'),
-('20180209165249'),
-('20180212030105'),
-('20180212101828'),
-('20180212101928'),
-('20180212102028'),
-('20180213131630'),
-('20180214093516'),
-('20180214155405'),
-('20180215181245'),
-('20180216120000'),
-('20180216120010'),
-('20180216120020'),
-('20180216120030'),
-('20180216120040'),
-('20180216120050'),
-('20180216121020'),
-('20180216121030'),
-('20180219153455'),
-('20180220150310'),
-('20180221151752'),
-('20180222043024'),
-('20180223120443'),
-('20180223124427'),
-('20180223144945'),
-('20180226050030'),
-('20180227182112'),
-('20180228172924'),
-('20180301010859'),
-('20180301084653'),
-('20180302152117'),
-('20180305095250'),
-('20180305100050'),
-('20180305144721'),
-('20180306074045'),
-('20180306134842'),
-('20180306164012'),
-('20180307012445'),
-('20180308052825'),
-('20180308125206'),
-('20180309121820'),
-('20180309160427'),
-('20180314100728'),
-('20180314145917'),
-('20180315160435'),
-('20180319190020'),
-('20180320182229'),
-('20180323150945'),
-('20180326202229'),
-('20180327101207'),
-('20180330121048'),
-('20180403035759'),
-('20180405101928'),
-('20180405142733'),
-('20180408143354'),
-('20180408143355'),
-('20180409170809'),
-('20180413022611'),
-('20180416155103'),
-('20180417090132'),
-('20180417101040'),
-('20180417101940'),
-('20180418053107'),
-('20180420010016'),
-('20180420010616'),
-('20180420080616'),
-('20180423204600'),
-('20180424090541'),
-('20180424134533'),
-('20180424151928'),
-('20180424160449'),
-('20180425075446'),
-('20180425131009'),
-('20180425205249'),
-('20180426102016'),
-('20180430101916'),
-('20180430143705'),
-('20180502122856'),
-('20180503131624'),
-('20180503141722'),
-('20180503150427'),
-('20180503175053'),
-('20180503175054'),
-('20180503193542'),
-('20180503193953'),
-('20180503200320'),
-('20180504195842'),
-('20180507083701'),
-('20180508055821'),
-('20180508100222'),
-('20180508102840'),
-('20180508135515'),
-('20180511090724'),
-('20180511131058'),
-('20180511174224'),
-('20180512061621'),
-('20180514161336'),
-('20180515005612'),
-('20180515121227'),
-('20180517082340'),
-('20180523042841'),
-('20180523125103'),
-('20180524132016'),
-('20180529093006'),
-('20180529152628'),
-('20180530135500'),
-('20180531185349'),
-('20180531220618'),
-('20180601213245'),
-('20180603190921'),
-('20180604123514'),
-('20180607071808'),
-('20180608091413'),
-('20180608110058'),
-('20180608201435'),
-('20180612103626'),
-('20180613081317'),
-('20180625113853'),
-('20180626125654'),
-('20180628124813'),
-('20180629153018'),
-('20180629191052'),
-('20180702120647'),
-('20180702124358'),
-('20180702134423'),
-('20180704145007'),
-('20180704204006'),
-('20180705160945'),
-('20180706223200'),
-('20180710162338'),
-('20180711103851'),
-('20180711103922'),
-('20180713092803'),
-('20180717125853'),
-('20180718005113'),
-('20180720023512'),
-('20180722103201'),
-('20180723135214'),
-('20180726172057'),
-('20180807153545'),
-('20180808162000'),
-('20180809195358'),
-('20180813101999'),
-('20180813102000'),
-('20180814153625'),
-('20180815040323'),
-('20180815160409'),
-('20180815170510'),
-('20180815175440'),
-('20180816161409'),
-('20180816193530'),
-('20180824202952'),
-('20180826111825'),
-('20180831164905'),
-('20180831164907'),
-('20180831164908'),
-('20180831164909'),
-('20180831164910'),
-('20180901171833'),
-('20180901200537'),
-('20180902070406'),
-('20180906101639'),
-('20180907015926'),
-('20180910115836'),
-('20180910153412'),
-('20180910153413'),
-('20180912111628'),
-('20180913142237'),
-('20180914162043'),
-('20180914201132'),
-('20180916011959'),
-('20180917172041'),
-('20180924141949'),
-('20180924190739'),
-('20180924201039'),
-('20180925200829'),
-('20180927073410'),
-('20181002172433'),
-('20181005110927'),
-('20181005125926'),
-('20181006004100'),
-('20181008145341'),
-('20181008145359'),
-('20181008200441'),
-('20181009190428'),
-('20181010133639'),
-('20181010235606'),
-('20181013005024'),
-('20181014203236'),
-('20181015155839'),
-('20181016141739'),
-('20181016152238'),
-('20181017001059'),
-('20181019032400'),
-('20181019032408'),
-('20181019105553'),
-('20181022135539'),
-('20181022173835'),
-('20181023104858'),
-('20181023144439'),
-('20181025115728'),
-('20181026091631'),
-('20181026143227'),
-('20181027114222'),
-('20181028120717'),
-('20181030135124'),
-('20181030154446'),
-('20181031145139'),
-('20181031190558'),
-('20181031190559'),
-('20181101091005'),
-('20181101091124'),
-('20181101144347'),
-('20181101191341'),
-('20181105201455'),
-('20181106135939'),
-('20181107054254'),
-('20181108091549'),
-('20181112103239'),
-('20181115140140'),
-('20181116050532'),
-('20181116141415'),
-('20181116141504'),
-('20181119081539'),
-('20181119132520'),
-('20181120082911'),
-('20181120091639'),
-('20181120151656'),
-('20181121101842'),
-('20181121101843'),
-('20181121111200'),
-('20181122160027'),
-('20181123042307'),
-('20181123135036'),
-('20181123144235'),
-('20181126150622'),
-('20181126153547'),
-('20181128123704'),
-('20181129104854'),
-('20181129104944'),
-('20181130102132'),
-('20181203002526'),
-('20181205171941'),
-('20181211092510'),
-('20181211092514'),
-('20181212104941'),
-('20181212171634'),
-('20181219130552'),
-('20181219145520'),
-('20181219145521'),
-('20181228175414'),
-('20190102152410'),
-('20190103140724'),
-('20190104182041'),
-('20190107151020'),
-('20190108192941'),
-('20190109153125'),
-('20190114172110'),
-('20190115054215'),
-('20190115054216'),
-('20190115092821'),
-('20190116234221'),
-('20190124200344'),
-('20190130091630'),
-('20190131122559'),
-('20190204115450'),
-('20190206193120'),
-('20190211131150'),
-('20190214112022'),
-('20190215154930'),
-('20190218134158'),
-('20190218134209'),
-('20190219201635'),
-('20190220142344'),
-('20190220150130'),
-('20190222051615'),
-('20190225152525'),
-('20190225160300'),
-('20190225160301'),
-('20190228192410'),
-('20190301081611'),
-('20190301182457'),
-('20190312071108'),
-('20190312113229'),
-('20190312113634'),
-('20190313092516'),
-('20190315191339'),
-('20190320174702'),
-('20190322132835'),
-('20190322164830'),
-('20190325080727'),
-('20190325105715'),
-('20190325111602'),
-('20190325165127'),
-('20190326164045'),
-('20190327163904'),
-('20190329085614'),
-('20190402150158'),
-('20190402224749'),
-('20190403161806'),
-('20190404143330'),
-('20190404231137'),
-('20190408163745'),
-('20190409224933'),
-('20190410173409'),
-('20190412155659'),
-('20190412183653'),
-('20190414185432'),
-('20190415030217'),
-('20190415095825'),
-('20190415172035'),
-('20190416185130'),
-('20190416213556'),
-('20190416213615'),
-('20190416213631'),
-('20190418132125'),
-('20190418132750'),
-('20190418182545'),
-('20190419121952'),
-('20190419123057'),
-('20190422082247'),
-('20190423124640'),
-('20190424134256'),
-('20190426180107'),
-('20190429082448'),
-('20190430131225'),
-('20190430142025'),
-('20190506135337'),
-('20190506135400'),
-('20190511144331'),
-('20190513174947'),
-('20190514105711'),
-('20190515125613'),
-('20190516011213'),
-('20190516151857'),
-('20190516155724'),
-('20190517153211'),
-('20190520200123'),
-('20190520201748'),
-('20190521174505'),
-('20190522143720'),
-('20190523112344'),
-('20190524062810'),
-('20190524071727'),
-('20190524073827'),
-('20190527011309'),
-('20190527194830'),
-('20190527194900'),
-('20190528173628'),
-('20190528180441'),
-('20190529142545'),
-('20190530042141'),
-('20190530154715'),
-('20190531153110'),
-('20190602014139'),
-('20190603124955'),
-('20190604091310'),
-('20190604184643'),
-('20190605104727'),
-('20190605184422'),
-('20190606014128'),
-('20190606034427'),
-('20190606054649'),
-('20190606054742'),
-('20190606054832'),
-('20190606163724'),
-('20190606175050'),
-('20190606202100'),
-('20190607085356'),
-('20190607145325'),
-('20190607190856'),
-('20190607205656'),
-('20190610142825'),
-('20190611090827'),
-('20190611100201'),
-('20190611100202'),
-('20190611161641'),
-('20190611161642'),
-('20190612111201'),
-('20190612111404'),
-('20190613030606'),
-('20190613044655'),
-('20190613073003'),
-('20190613231640'),
-('20190617123615'),
-('20190618171120'),
-('20190619175843'),
-('20190620105427'),
-('20190620112608'),
-('20190621022810'),
-('20190621151636'),
-('20190623212503'),
-('20190624123615'),
-('20190625115224'),
-('20190625184066'),
-('20190626175626'),
-('20190627051902'),
-('20190627100221'),
-('20190627122264'),
-('20190628145246'),
-('20190628185000'),
-('20190628185004'),
-('20190628191740'),
-('20190702173936'),
-('20190703043358'),
-('20190703130053'),
-('20190703171157'),
-('20190703171555'),
-('20190703185326'),
-('20190709204413'),
-('20190709220014'),
-('20190709220143'),
-('20190710151229'),
-('20190711124721'),
-('20190711200053'),
-('20190711200508'),
-('20190711201818'),
-('20190712040400'),
-('20190712040412'),
-('20190712064021'),
-('20190715042813'),
-('20190715043944'),
-('20190715043954'),
-('20190715044501'),
-('20190715114644'),
-('20190715140740'),
-('20190715142138'),
-('20190715173819'),
-('20190715193142'),
-('20190715215532'),
-('20190715215549'),
-('20190716144222'),
-('20190719122333'),
-('20190719174505'),
-('20190722104947'),
-('20190722132830'),
-('20190722144316'),
-('20190723105753'),
-('20190723153247'),
-('20190724112147'),
-('20190725012225'),
-('20190725080128'),
-('20190725183432'),
-('20190726101050'),
-('20190726101133'),
-('20190729062536'),
-('20190729090456'),
-('20190729180447'),
-('20190731084415'),
-('20190801060809'),
-('20190801114109'),
-('20190801142441'),
-('20190801193427'),
-('20190802012622'),
-('20190802091750'),
-('20190802195602'),
-('20190802235445'),
-('20190805140353'),
-('20190806071559'),
-('20190807023052'),
-('20190808152507'),
-('20190809072552'),
-('20190812070645'),
-('20190814205640'),
-('20190815093936'),
-('20190815093949'),
-('20190816151221'),
-('20190819131155'),
-('20190819231552'),
-('20190820163320'),
-('20190821040941'),
-('20190822175441'),
-('20190822181528'),
-('20190822185441'),
-('20190823055948'),
-('20190826090628'),
-('20190826100605'),
-('20190827102026'),
-('20190827222124'),
-('20190828083843'),
-('20190828110802'),
-('20190828170945'),
-('20190828172831'),
-('20190829131130'),
-('20190830075508'),
-('20190830080123'),
-('20190830080626'),
-('20190830140240'),
-('20190901174200'),
-('20190902131045'),
-('20190902152329'),
-('20190902160015'),
-('20190903150358'),
-('20190903150435'),
-('20190904173203'),
-('20190904205212'),
-('20190905022045'),
-('20190905074652'),
-('20190905091812'),
-('20190905091831'),
-('20190905140605'),
-('20190905223800'),
-('20190905223900'),
-('20190906104555'),
-('20190907184714'),
-('20190909045845'),
-('20190909141517'),
-('20190910000130'),
-('20190910103144'),
-('20190910114843'),
-('20190910125852'),
-('20190910211526'),
-('20190910212256'),
-('20190911115056'),
-('20190911115109'),
-('20190911115207'),
-('20190911115222'),
-('20190911251732'),
-('20190912061145'),
-('20190912223232'),
-('20190913174707'),
-('20190913175827'),
-('20190914223900'),
-('20190917173107'),
-('20190918025618'),
-('20190918102042'),
-('20190918104212'),
-('20190918104222'),
-('20190918104731'),
-('20190918121135'),
-('20190919040324'),
-('20190919091300'),
-('20190919104119'),
-('20190919162036'),
-('20190919183411'),
-('20190920122420'),
-('20190920194925'),
-('20190920224341'),
-('20190924124627'),
-('20190924152703'),
-('20190925055714'),
-('20190925055902'),
-('20190926041216'),
-('20190926180443'),
-('20190926225633'),
-('20190927055500'),
-('20190927055540'),
-('20190927074328'),
-('20190929180751'),
-('20190929180813'),
-('20190929180827'),
-('20190930025655'),
-('20190930063627'),
-('20190930082942'),
-('20190930153535'),
-('20191001040549'),
-('20191001170300'),
-('20191002031332'),
-('20191002123516'),
-('20191003015155'),
-('20191003060227'),
-('20191003064615'),
-('20191003130045'),
-('20191003150045'),
-('20191003161031'),
-('20191003161032'),
-('20191003195218'),
-('20191003195620'),
-('20191003200045'),
-('20191003250045'),
-('20191003300045'),
-('20191003350045'),
-('20191004080818'),
-('20191004081520'),
-('20191004133612'),
-('20191004151428'),
-('20191007163701'),
-('20191007163736'),
-('20191008013056'),
-('20191008142331'),
-('20191008143850'),
-('20191008180203'),
-('20191008200204'),
-('20191009100244'),
-('20191009110124'),
-('20191009110757'),
-('20191009222222'),
-('20191010174846'),
-('20191011084019'),
-('20191013100213'),
-('20191014025629'),
-('20191014030134'),
-('20191014030730'),
-('20191014084150'),
-('20191014123159'),
-('20191014132931'),
-('20191015154408'),
-('20191016072826'),
-('20191016133352'),
-('20191016220135'),
-('20191017001326'),
-('20191017045817'),
-('20191017094449'),
-('20191017134513'),
-('20191017180026'),
-('20191017191341'),
-('20191021101942'),
-('20191022113635'),
-('20191023093207'),
-('20191023132005'),
-('20191023152913'),
-('20191024134020'),
-('20191025092748'),
-('20191026041447'),
-('20191026120008'),
-('20191026120112'),
-('20191026124116'),
-('20191028130054'),
-('20191028162543'),
-('20191028184740'),
-('20191029095537'),
-('20191029125305'),
-('20191029191901'),
-('20191030135044'),
-('20191030152934'),
-('20191030193050'),
-('20191030223057'),
-('20191031095636'),
-('20191031112603'),
-('20191101092917'),
-('20191103202505'),
-('20191104142124'),
-('20191104205020'),
-('20191105094558'),
-('20191105094625'),
-('20191105134413'),
-('20191105140942'),
-('20191105155113'),
-('20191105193652'),
-('20191106144901'),
-('20191106150931'),
-('20191107064946'),
-('20191107173446'),
-('20191107220314'),
-('20191108031900'),
-('20191108202723'),
-('20191111115229'),
-('20191111115431'),
-('20191111121500'),
-('20191111165017'),
-('20191111175230'),
-('20191112023159'),
-('20191112090226'),
-('20191112105448'),
-('20191112115247'),
-('20191112115317'),
-('20191112214305'),
-('20191112221821'),
-('20191112232338'),
-('20191114132259'),
-('20191114173508'),
-('20191114173602'),
-('20191114173624'),
-('20191114201118'),
-('20191114204343'),
-('20191115001123'),
-('20191115001843'),
-('20191115091425'),
-('20191115114032'),
-('20191115115043'),
-('20191115115522'),
-('20191118053631'),
-('20191118155702'),
-('20191118173522'),
-('20191118182722'),
-('20191118211629'),
-('20191119023952'),
-('20191119220425'),
-('20191119221041'),
-('20191119231621'),
-('20191120084627'),
-('20191120115530'),
-('20191120200015'),
-('20191121111621'),
-('20191121121947'),
-('20191121122856'),
-('20191121161018'),
-('20191121193110'),
-('20191122135327'),
-('20191122161519'),
-('20191123062354'),
-('20191123081456'),
-('20191124150431'),
-('20191125024005'),
-('20191125114345'),
-('20191125133353'),
-('20191125140458'),
-('20191126134210'),
-('20191127030005'),
-('20191127151619'),
-('20191127151629'),
-('20191127163053'),
-('20191127221608'),
-('20191128145231'),
-('20191128145232'),
-('20191128145233'),
-('20191128162854'),
-('20191129134844'),
-('20191129144630'),
-('20191129144631'),
-('20191202031812'),
-('20191202181924'),
-('20191203121729'),
-('20191204070713'),
-('20191204093410'),
-('20191204114127'),
-('20191204192726'),
-('20191205060723'),
-('20191205084057'),
-('20191205094702'),
-('20191205145647'),
-('20191205212923'),
-('20191205212924'),
-('20191206014412'),
-('20191206022133'),
-('20191206122926'),
-('20191207104000'),
-('20191208071111'),
-('20191208071112'),
-('20191208110214'),
-('20191209143606'),
-('20191209215316'),
-('20191210211253'),
-('20191212140117'),
-('20191212162434'),
-('20191213104838'),
-('20191213120427'),
-('20191213143656'),
-('20191213184609'),
-('20191214175727'),
-('20191216074800'),
-('20191216074802'),
-('20191216074803'),
-('20191216094119'),
-('20191216183531'),
-('20191216183532'),
-('20191217165641'),
-('20191217212348'),
-('20191218084115'),
-('20191218122457'),
-('20191218124915'),
-('20191218125015'),
-('20191218190253'),
-('20191218225624'),
-('20191223124940'),
-('20191225071320'),
-('20191227140254'),
-('20191229140154'),
-('20200102140148'),
-('20200102170221'),
-('20200103190741'),
-('20200103192859'),
-('20200103192914'),
-('20200103195205'),
-('20200104113850'),
-('20200106071113'),
-('20200106085831'),
-('20200107172020'),
-('20200108100603'),
-('20200108155731'),
-('20200108233040'),
-('20200109030418'),
-('20200109085206'),
-('20200109233938'),
-('20200110089001'),
-('20200110090153'),
-('20200110121314'),
-('20200110144316'),
-('20200110203532'),
-('20200113133352'),
-('20200113151354'),
-('20200114112932'),
-('20200114113341'),
-('20200114140305'),
-('20200114204949'),
-('20200115135132'),
-('20200115135234'),
-('20200116051619'),
-('20200116175538'),
-('20200117112554'),
-('20200117194830'),
-('20200117194840'),
-('20200117194850'),
-('20200117194900'),
-('20200120083607'),
-('20200121132641'),
-('20200121192942'),
-('20200121194000'),
-('20200121194048'),
-('20200121194154'),
-('20200121200203'),
-('20200122123016'),
-('20200122144759'),
-('20200122161638'),
-('20200123040535'),
-('20200123045415'),
-('20200123090839'),
-('20200123091422'),
-('20200123091622'),
-('20200123091734'),
-('20200123091854'),
-('20200123155929'),
-('20200124053531'),
-('20200124110831'),
-('20200124143014'),
-('20200127090233'),
-('20200127111840'),
-('20200128105731'),
-('20200128132510'),
-('20200128133510'),
-('20200128134110'),
-('20200128141125'),
-('20200128184209'),
-('20200128210353'),
-('20200129034515'),
-('20200129035446'),
-('20200129035708'),
-('20200129133716'),
-('20200129172428'),
-('20200130134335'),
-('20200130145430'),
-('20200130161817'),
-('20200131140428'),
-('20200131181354'),
-('20200131191754'),
-('20200202100932'),
-('20200203015140'),
-('20200203025400'),
-('20200203025602'),
-('20200203025619'),
-('20200203025744'),
-('20200203025801'),
-('20200203025821'),
-('20200203104214'),
-('20200203173508'),
-('20200203183508'),
-('20200203232433'),
-('20200204070729'),
-('20200204113223'),
-('20200204113224'),
-('20200204131054'),
-('20200204131831'),
-('20200205143231'),
-('20200206091544'),
-('20200206112850'),
-('20200206135203'),
-('20200206141511'),
-('20200207062728'),
-('20200207090921'),
-('20200207132752'),
-('20200207151640'),
-('20200207182131'),
-('20200207184023'),
-('20200207185149'),
-('20200209131152'),
-('20200210062432'),
-('20200210092405'),
-('20200210135504'),
-('20200210184410'),
-('20200210184420'),
-('20200211152410'),
-('20200211155000'),
-('20200211155100'),
-('20200211155539'),
-('20200211174946'),
-('20200212014653'),
-('20200212052620'),
-('20200212133945'),
-('20200212134201'),
-('20200213093702'),
-('20200213155311'),
-('20200213204737'),
-('20200213220159'),
-('20200213220211'),
-('20200214025454'),
-('20200214034836'),
-('20200214085940'),
-('20200214214934'),
-('20200215222507'),
-('20200215225103'),
-('20200217223651'),
-('20200217225719'),
-('20200219105209'),
-('20200219133859'),
-('20200219135440'),
-('20200219141307'),
-('20200219142522'),
-('20200219183456'),
-('20200219184219'),
-('20200219193058'),
-('20200219193117'),
-('20200220180944'),
-('20200221023320'),
-('20200221074028'),
-('20200221100514'),
-('20200221105436'),
-('20200221142216'),
-('20200221144534'),
-('20200222055543'),
-('20200224020219'),
-('20200224163804'),
-('20200224185814'),
-('20200225111018'),
-('20200225123228'),
-('20200226100614'),
-('20200226100624'),
-('20200226100634'),
-('20200226162156'),
-('20200226162239'),
-('20200226162634'),
-('20200226162723'),
-('20200227140242'),
-('20200227164113'),
-('20200227165129'),
-('20200228160542'),
-('20200302142052'),
-('20200302152516'),
-('20200303055348'),
-('20200303074328'),
-('20200304085423'),
-('20200304090155'),
-('20200304121828'),
-('20200304121844'),
-('20200304124406'),
-('20200304160800'),
-('20200304160801'),
-('20200304160823'),
-('20200304211738'),
-('20200305121159'),
-('20200305151736'),
-('20200306095654'),
-('20200306160521'),
-('20200306170211'),
-('20200306170321'),
-('20200306170531'),
-('20200306192548'),
-('20200306193236'),
-('20200309140540'),
-('20200309162244'),
-('20200309195209'),
-('20200309195710'),
-('20200310075115'),
-('20200310123229'),
-('20200310132654'),
-('20200310133822'),
-('20200310135818'),
-('20200310135823'),
-('20200310145304'),
-('20200311074438'),
-('20200311082301'),
-('20200311084025'),
-('20200311093210'),
-('20200311094020'),
-('20200311141053'),
-('20200311141943'),
-('20200311154110'),
-('20200311165635'),
-('20200311192351'),
-('20200311214912'),
-('20200312125121'),
-('20200312160532'),
-('20200312163407'),
-('20200313101649'),
-('20200313123934'),
-('20200316111759'),
-('20200316162648'),
-('20200316173312'),
-('20200317142110'),
-('20200318140400'),
-('20200318152134'),
-('20200318162148'),
-('20200318163148'),
-('20200318164448'),
-('20200318165448'),
-('20200318175008'),
-('20200319123041'),
-('20200319203901'),
-('20200320112455'),
-('20200320123839'),
-('20200323075043'),
-('20200323122201'),
-('20200324115359');
+COPY "schema_migrations" (version) FROM STDIN;
+20171230123729
+20180101160629
+20180101160630
+20180102220145
+20180103123548
+20180104131052
+20180105212544
+20180109183319
+20180113220114
+20180115094742
+20180115113902
+20180115201419
+20180116193854
+20180119121225
+20180119135717
+20180119160751
+20180122154930
+20180122162010
+20180125214301
+20180129193323
+20180201102129
+20180201110056
+20180201145907
+20180204200836
+20180206200543
+20180208183958
+20180209115333
+20180209165249
+20180212030105
+20180212101828
+20180212101928
+20180212102028
+20180213131630
+20180214093516
+20180214155405
+20180215181245
+20180216120000
+20180216120010
+20180216120020
+20180216120030
+20180216120040
+20180216120050
+20180216121020
+20180216121030
+20180219153455
+20180220150310
+20180221151752
+20180222043024
+20180223120443
+20180223124427
+20180223144945
+20180226050030
+20180227182112
+20180228172924
+20180301010859
+20180301084653
+20180302152117
+20180305095250
+20180305100050
+20180305144721
+20180306074045
+20180306134842
+20180306164012
+20180307012445
+20180308052825
+20180308125206
+20180309121820
+20180309160427
+20180314100728
+20180314145917
+20180315160435
+20180319190020
+20180320182229
+20180323150945
+20180326202229
+20180327101207
+20180330121048
+20180403035759
+20180405101928
+20180405142733
+20180408143354
+20180408143355
+20180409170809
+20180413022611
+20180416155103
+20180417090132
+20180417101040
+20180417101940
+20180418053107
+20180420010016
+20180420010616
+20180420080616
+20180423204600
+20180424090541
+20180424134533
+20180424151928
+20180424160449
+20180425075446
+20180425131009
+20180425205249
+20180426102016
+20180430101916
+20180430143705
+20180502122856
+20180503131624
+20180503141722
+20180503150427
+20180503175053
+20180503175054
+20180503193542
+20180503193953
+20180503200320
+20180504195842
+20180507083701
+20180508055821
+20180508100222
+20180508102840
+20180508135515
+20180511090724
+20180511131058
+20180511174224
+20180512061621
+20180514161336
+20180515005612
+20180515121227
+20180517082340
+20180523042841
+20180523125103
+20180524132016
+20180529093006
+20180529152628
+20180530135500
+20180531185349
+20180531220618
+20180601213245
+20180603190921
+20180604123514
+20180607071808
+20180608091413
+20180608110058
+20180608201435
+20180612103626
+20180613081317
+20180625113853
+20180626125654
+20180628124813
+20180629153018
+20180629191052
+20180702120647
+20180702124358
+20180702134423
+20180704145007
+20180704204006
+20180705160945
+20180706223200
+20180710162338
+20180711103851
+20180711103922
+20180713092803
+20180717125853
+20180718005113
+20180720023512
+20180722103201
+20180723135214
+20180726172057
+20180807153545
+20180808162000
+20180809195358
+20180813101999
+20180813102000
+20180814153625
+20180815040323
+20180815160409
+20180815170510
+20180815175440
+20180816161409
+20180816193530
+20180824202952
+20180826111825
+20180831164905
+20180831164907
+20180831164908
+20180831164909
+20180831164910
+20180901171833
+20180901200537
+20180902070406
+20180906101639
+20180907015926
+20180910115836
+20180910153412
+20180910153413
+20180912111628
+20180913142237
+20180914162043
+20180914201132
+20180916011959
+20180917172041
+20180924141949
+20180924190739
+20180924201039
+20180925200829
+20180927073410
+20181002172433
+20181005110927
+20181005125926
+20181006004100
+20181008145341
+20181008145359
+20181008200441
+20181009190428
+20181010133639
+20181010235606
+20181013005024
+20181014203236
+20181015155839
+20181016141739
+20181016152238
+20181017001059
+20181019032400
+20181019032408
+20181019105553
+20181022135539
+20181022173835
+20181023104858
+20181023144439
+20181025115728
+20181026091631
+20181026143227
+20181027114222
+20181028120717
+20181030135124
+20181030154446
+20181031145139
+20181031190558
+20181031190559
+20181101091005
+20181101091124
+20181101144347
+20181101191341
+20181105201455
+20181106135939
+20181107054254
+20181108091549
+20181112103239
+20181115140140
+20181116050532
+20181116141415
+20181116141504
+20181119081539
+20181119132520
+20181120082911
+20181120091639
+20181120151656
+20181121101842
+20181121101843
+20181121111200
+20181122160027
+20181123042307
+20181123135036
+20181123144235
+20181126150622
+20181126153547
+20181128123704
+20181129104854
+20181129104944
+20181130102132
+20181203002526
+20181205171941
+20181211092510
+20181211092514
+20181212104941
+20181212171634
+20181219130552
+20181219145520
+20181219145521
+20181228175414
+20190102152410
+20190103140724
+20190104182041
+20190107151020
+20190108192941
+20190109153125
+20190114172110
+20190115054215
+20190115054216
+20190115092821
+20190116234221
+20190124200344
+20190130091630
+20190131122559
+20190204115450
+20190206193120
+20190211131150
+20190214112022
+20190215154930
+20190218134158
+20190218134209
+20190219201635
+20190220142344
+20190220150130
+20190222051615
+20190225152525
+20190225160300
+20190225160301
+20190228192410
+20190301081611
+20190301182457
+20190312071108
+20190312113229
+20190312113634
+20190313092516
+20190315191339
+20190320174702
+20190322132835
+20190322164830
+20190325080727
+20190325105715
+20190325111602
+20190325165127
+20190326164045
+20190327163904
+20190329085614
+20190402150158
+20190402224749
+20190403161806
+20190404143330
+20190404231137
+20190408163745
+20190409224933
+20190410173409
+20190412155659
+20190412183653
+20190414185432
+20190415030217
+20190415095825
+20190415172035
+20190416185130
+20190416213556
+20190416213615
+20190416213631
+20190418132125
+20190418132750
+20190418182545
+20190419121952
+20190419123057
+20190422082247
+20190423124640
+20190424134256
+20190426180107
+20190429082448
+20190430131225
+20190430142025
+20190506135337
+20190506135400
+20190511144331
+20190513174947
+20190514105711
+20190515125613
+20190516011213
+20190516151857
+20190516155724
+20190517153211
+20190520200123
+20190520201748
+20190521174505
+20190522143720
+20190523112344
+20190524062810
+20190524071727
+20190524073827
+20190527011309
+20190527194830
+20190527194900
+20190528173628
+20190528180441
+20190529142545
+20190530042141
+20190530154715
+20190531153110
+20190602014139
+20190603124955
+20190604091310
+20190604184643
+20190605104727
+20190605184422
+20190606014128
+20190606034427
+20190606054649
+20190606054742
+20190606054832
+20190606163724
+20190606175050
+20190606202100
+20190607085356
+20190607145325
+20190607190856
+20190607205656
+20190610142825
+20190611090827
+20190611100201
+20190611100202
+20190611161641
+20190611161642
+20190612111201
+20190612111404
+20190613030606
+20190613044655
+20190613073003
+20190613231640
+20190617123615
+20190618171120
+20190619175843
+20190620105427
+20190620112608
+20190621022810
+20190621151636
+20190623212503
+20190624123615
+20190625115224
+20190625184066
+20190626175626
+20190627051902
+20190627100221
+20190627122264
+20190628145246
+20190628185000
+20190628185004
+20190628191740
+20190702173936
+20190703043358
+20190703130053
+20190703171157
+20190703171555
+20190703185326
+20190709204413
+20190709220014
+20190709220143
+20190710151229
+20190711124721
+20190711200053
+20190711200508
+20190711201818
+20190712040400
+20190712040412
+20190712064021
+20190715042813
+20190715043944
+20190715043954
+20190715044501
+20190715114644
+20190715140740
+20190715142138
+20190715173819
+20190715193142
+20190715215532
+20190715215549
+20190716144222
+20190719122333
+20190719174505
+20190722104947
+20190722132830
+20190722144316
+20190723105753
+20190723153247
+20190724112147
+20190725012225
+20190725080128
+20190725183432
+20190726101050
+20190726101133
+20190729062536
+20190729090456
+20190729180447
+20190731084415
+20190801060809
+20190801114109
+20190801142441
+20190801193427
+20190802012622
+20190802091750
+20190802195602
+20190802235445
+20190805140353
+20190806071559
+20190807023052
+20190808152507
+20190809072552
+20190812070645
+20190814205640
+20190815093936
+20190815093949
+20190816151221
+20190819131155
+20190819231552
+20190820163320
+20190821040941
+20190822175441
+20190822181528
+20190822185441
+20190823055948
+20190826090628
+20190826100605
+20190827102026
+20190827222124
+20190828083843
+20190828110802
+20190828170945
+20190828172831
+20190829131130
+20190830075508
+20190830080123
+20190830080626
+20190830140240
+20190901174200
+20190902131045
+20190902152329
+20190902160015
+20190903150358
+20190903150435
+20190904173203
+20190904205212
+20190905022045
+20190905074652
+20190905091812
+20190905091831
+20190905140605
+20190905223800
+20190905223900
+20190906104555
+20190907184714
+20190909045845
+20190909141517
+20190910000130
+20190910103144
+20190910114843
+20190910125852
+20190910211526
+20190910212256
+20190911115056
+20190911115109
+20190911115207
+20190911115222
+20190911251732
+20190912061145
+20190912223232
+20190913174707
+20190913175827
+20190914223900
+20190917173107
+20190918025618
+20190918102042
+20190918104212
+20190918104222
+20190918104731
+20190918121135
+20190919040324
+20190919091300
+20190919104119
+20190919162036
+20190919183411
+20190920122420
+20190920194925
+20190920224341
+20190924124627
+20190924152703
+20190925055714
+20190925055902
+20190926041216
+20190926180443
+20190926225633
+20190927055500
+20190927055540
+20190927074328
+20190929180751
+20190929180813
+20190929180827
+20190930025655
+20190930063627
+20190930082942
+20190930153535
+20191001040549
+20191001170300
+20191002031332
+20191002123516
+20191003015155
+20191003060227
+20191003064615
+20191003130045
+20191003150045
+20191003161031
+20191003161032
+20191003195218
+20191003195620
+20191003200045
+20191003250045
+20191003300045
+20191003350045
+20191004080818
+20191004081520
+20191004133612
+20191004151428
+20191007163701
+20191007163736
+20191008013056
+20191008142331
+20191008143850
+20191008180203
+20191008200204
+20191009100244
+20191009110124
+20191009110757
+20191009222222
+20191010174846
+20191011084019
+20191013100213
+20191014025629
+20191014030134
+20191014030730
+20191014084150
+20191014123159
+20191014132931
+20191015154408
+20191016072826
+20191016133352
+20191016220135
+20191017001326
+20191017045817
+20191017094449
+20191017134513
+20191017180026
+20191017191341
+20191021101942
+20191022113635
+20191023093207
+20191023132005
+20191023152913
+20191024134020
+20191025092748
+20191026041447
+20191026120008
+20191026120112
+20191026124116
+20191028130054
+20191028162543
+20191028184740
+20191029095537
+20191029125305
+20191029191901
+20191030135044
+20191030152934
+20191030193050
+20191030223057
+20191031095636
+20191031112603
+20191101092917
+20191103202505
+20191104142124
+20191104205020
+20191105094558
+20191105094625
+20191105134413
+20191105140942
+20191105155113
+20191105193652
+20191106144901
+20191106150931
+20191107064946
+20191107173446
+20191107220314
+20191108031900
+20191108202723
+20191111115229
+20191111115431
+20191111121500
+20191111165017
+20191111175230
+20191112023159
+20191112090226
+20191112105448
+20191112115247
+20191112115317
+20191112214305
+20191112221821
+20191112232338
+20191114132259
+20191114173508
+20191114173602
+20191114173624
+20191114201118
+20191114204343
+20191115001123
+20191115001843
+20191115091425
+20191115114032
+20191115115043
+20191115115522
+20191118053631
+20191118155702
+20191118173522
+20191118182722
+20191118211629
+20191119023952
+20191119220425
+20191119221041
+20191119231621
+20191120084627
+20191120115530
+20191120200015
+20191121111621
+20191121121947
+20191121122856
+20191121161018
+20191121193110
+20191122135327
+20191122161519
+20191123062354
+20191123081456
+20191124150431
+20191125024005
+20191125114345
+20191125133353
+20191125140458
+20191126134210
+20191127030005
+20191127151619
+20191127151629
+20191127163053
+20191127221608
+20191128145231
+20191128145232
+20191128145233
+20191128162854
+20191129134844
+20191129144630
+20191129144631
+20191202031812
+20191202181924
+20191203121729
+20191204070713
+20191204093410
+20191204114127
+20191204192726
+20191205060723
+20191205084057
+20191205094702
+20191205145647
+20191205212923
+20191205212924
+20191206014412
+20191206022133
+20191206122926
+20191207104000
+20191208071111
+20191208071112
+20191208110214
+20191209143606
+20191209215316
+20191210211253
+20191212140117
+20191212162434
+20191213104838
+20191213120427
+20191213143656
+20191213184609
+20191214175727
+20191216074800
+20191216074802
+20191216074803
+20191216094119
+20191216183531
+20191216183532
+20191217165641
+20191217212348
+20191218084115
+20191218122457
+20191218124915
+20191218125015
+20191218190253
+20191218225624
+20191223124940
+20191225071320
+20191227140254
+20191229140154
+20200102140148
+20200102170221
+20200103190741
+20200103192859
+20200103192914
+20200103195205
+20200104113850
+20200106071113
+20200106085831
+20200107172020
+20200108100603
+20200108155731
+20200108233040
+20200109030418
+20200109085206
+20200109233938
+20200110089001
+20200110090153
+20200110121314
+20200110144316
+20200110203532
+20200113133352
+20200113151354
+20200114112932
+20200114113341
+20200114140305
+20200114204949
+20200115135132
+20200115135234
+20200116051619
+20200116175538
+20200117112554
+20200117194830
+20200117194840
+20200117194850
+20200117194900
+20200120083607
+20200121132641
+20200121192942
+20200121194000
+20200121194048
+20200121194154
+20200121200203
+20200122123016
+20200122144759
+20200122161638
+20200123040535
+20200123045415
+20200123090839
+20200123091422
+20200123091622
+20200123091734
+20200123091854
+20200123155929
+20200124053531
+20200124110831
+20200124143014
+20200127090233
+20200127111840
+20200128105731
+20200128132510
+20200128133510
+20200128134110
+20200128141125
+20200128184209
+20200128210353
+20200129034515
+20200129035446
+20200129035708
+20200129133716
+20200129172428
+20200130134335
+20200130145430
+20200130161817
+20200131140428
+20200131181354
+20200131191754
+20200202100932
+20200203015140
+20200203025400
+20200203025602
+20200203025619
+20200203025744
+20200203025801
+20200203025821
+20200203104214
+20200203173508
+20200203183508
+20200203232433
+20200204070729
+20200204113223
+20200204113224
+20200204131054
+20200204131831
+20200205143231
+20200206091544
+20200206112850
+20200206135203
+20200206141511
+20200207062728
+20200207090921
+20200207132752
+20200207151640
+20200207182131
+20200207184023
+20200207185149
+20200209131152
+20200210062432
+20200210092405
+20200210135504
+20200210184410
+20200210184420
+20200211152410
+20200211155000
+20200211155100
+20200211155539
+20200211174946
+20200212014653
+20200212052620
+20200212133945
+20200212134201
+20200213093702
+20200213155311
+20200213204737
+20200213220159
+20200213220211
+20200214025454
+20200214034836
+20200214085940
+20200214214934
+20200215222507
+20200215225103
+20200217223651
+20200217225719
+20200219105209
+20200219133859
+20200219135440
+20200219141307
+20200219142522
+20200219183456
+20200219184219
+20200219193058
+20200219193117
+20200220180944
+20200221023320
+20200221074028
+20200221100514
+20200221105436
+20200221142216
+20200221144534
+20200222055543
+20200224020219
+20200224163804
+20200224185814
+20200225111018
+20200225123228
+20200226100614
+20200226100624
+20200226100634
+20200226162156
+20200226162239
+20200226162634
+20200226162723
+20200227140242
+20200227164113
+20200227165129
+20200228160542
+20200302142052
+20200302152516
+20200303055348
+20200303074328
+20200304085423
+20200304090155
+20200304121828
+20200304121844
+20200304124406
+20200304160800
+20200304160801
+20200304160823
+20200304211738
+20200305121159
+20200305151736
+20200306095654
+20200306160521
+20200306170211
+20200306170321
+20200306170531
+20200306192548
+20200306193236
+20200309140540
+20200309162244
+20200309195209
+20200309195710
+20200310075115
+20200310123229
+20200310132654
+20200310133822
+20200310135818
+20200310135823
+20200310145304
+20200311074438
+20200311082301
+20200311084025
+20200311093210
+20200311094020
+20200311141053
+20200311141943
+20200311154110
+20200311165635
+20200311192351
+20200311214912
+20200312125121
+20200312160532
+20200312163407
+20200313101649
+20200313123934
+20200316111759
+20200316162648
+20200316173312
+20200317142110
+20200318140400
+20200318152134
+20200318162148
+20200318163148
+20200318164448
+20200318165448
+20200318175008
+20200319123041
+20200319203901
+20200320112455
+20200320123839
+20200323075043
+20200323122201
+20200324115359
+\.
diff --git a/doc/development/chatops_on_gitlabcom.md b/doc/development/chatops_on_gitlabcom.md
index f3687b8d697..60056c2f65c 100644
--- a/doc/development/chatops_on_gitlabcom.md
+++ b/doc/development/chatops_on_gitlabcom.md
@@ -14,7 +14,7 @@ tasks such as:
To request access to Chatops on GitLab.com:
1. Log into <https://ops.gitlab.net/users/sign_in> **using the same username** as for GitLab.com (you may have to rename it).
-1. Ask in the [#production](https://gitlab.slack.com/messages/production) channel to add you by running `/chatops run member add <username> gitlab-com/chatops --ops`.
+1. Ask in the [#production](https://gitlab.slack.com/messages/production) channel for an existing member to add you to the `chatops` project in Ops. They can do it by running `/chatops run member add <username> gitlab-com/chatops --ops` command in that channel.
NOTE: **Note:** If you had to change your username for GitLab.com on the first step, make sure [to reflect this information](https://gitlab.com/gitlab-com/www-gitlab-com#adding-yourself-to-the-team-page) on [the team page](https://about.gitlab.com/company/team/).
diff --git a/lib/api/releases.rb b/lib/api/releases.rb
index 1be263ac80d..95b3e90323c 100644
--- a/lib/api/releases.rb
+++ b/lib/api/releases.rb
@@ -150,6 +150,10 @@ module API
authorize! :download_code, release
end
+ def authorize_create_evidence!
+ # This is a separate method so that EE can extend its behaviour
+ end
+
def release
@release ||= user_project.releases.find_by_tag(params[:tag])
end
diff --git a/lib/gitlab/database/postgresql_adapter/schema_versions_copy_mixin.rb b/lib/gitlab/database/postgresql_adapter/schema_versions_copy_mixin.rb
new file mode 100644
index 00000000000..d8f96643dcb
--- /dev/null
+++ b/lib/gitlab/database/postgresql_adapter/schema_versions_copy_mixin.rb
@@ -0,0 +1,28 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Database
+ module PostgresqlAdapter
+ module SchemaVersionsCopyMixin
+ extend ActiveSupport::Concern
+
+ def dump_schema_information # :nodoc:
+ versions = schema_migration.all_versions
+ copy_versions_sql(versions) if versions.any?
+ end
+
+ private
+
+ def copy_versions_sql(versions)
+ sm_table = quote_table_name(schema_migration.table_name)
+
+ sql = +"COPY #{sm_table} (version) FROM STDIN;\n"
+ sql << versions.map { |v| Integer(v) }.sort.join("\n")
+ sql << "\n\\.\n"
+
+ sql
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/profiler.rb b/lib/gitlab/profiler.rb
index e10cdf0d8fb..42f43f998c4 100644
--- a/lib/gitlab/profiler.rb
+++ b/lib/gitlab/profiler.rb
@@ -168,9 +168,9 @@ module Gitlab
# rubocop: enable CodeReuse/ActiveRecord
def self.print_by_total_time(result, options = {})
- default_options = { sort_method: :total_time }
+ default_options = { sort_method: :total_time, filter_by: :total_time }
- Gitlab::Profiler::TotalTimeFlatPrinter.new(result).print(STDOUT, default_options.merge(options))
+ RubyProf::FlatPrinter.new(result).print(STDOUT, default_options.merge(options))
end
end
end
diff --git a/lib/gitlab/profiler/total_time_flat_printer.rb b/lib/gitlab/profiler/total_time_flat_printer.rb
deleted file mode 100644
index 9846bad3c08..00000000000
--- a/lib/gitlab/profiler/total_time_flat_printer.rb
+++ /dev/null
@@ -1,42 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module Profiler
- class TotalTimeFlatPrinter < RubyProf::FlatPrinter
- def max_percent
- @options[:max_percent] || 100
- end
-
- # Copied from:
- # <https://github.com/ruby-prof/ruby-prof/blob/master/lib/ruby-prof/printers/flat_printer.rb>
- #
- # The changes are just to filter by total time, not self time, and add a
- # max_percent option as well.
- def print_methods(thread)
- total_time = thread.total_time
- methods = thread.methods.sort_by(&sort_method).reverse
-
- sum = 0
- methods.each do |method|
- total_percent = (method.total_time / total_time) * 100
- next if total_percent < min_percent
- next if total_percent > max_percent
-
- sum += method.self_time
-
- @output << "%6.2f %9.3f %9.3f %9.3f %9.3f %8d %s%-30s %s\n" % [
- method.self_time / total_time * 100, # %self
- method.total_time, # total
- method.self_time, # self
- method.wait_time, # wait
- method.children_time, # children
- method.called, # calls
- method.recursive? ? "*" : " ", # cycle
- method.full_name, # method_name
- method_location(method) # location
- ]
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/setup_helper.rb b/lib/gitlab/setup_helper.rb
index 99a7e617884..196dc0e3447 100644
--- a/lib/gitlab/setup_helper.rb
+++ b/lib/gitlab/setup_helper.rb
@@ -4,75 +4,110 @@ require 'toml-rb'
module Gitlab
module SetupHelper
- class << self
- # We cannot create config.toml files for all possible Gitaly configuations.
- # For instance, if Gitaly is running on another machine then it makes no
- # sense to write a config.toml file on the current machine. This method will
- # only generate a configuration for the most common and simplest case: when
- # we have exactly one Gitaly process and we are sure it is running locally
- # because it uses a Unix socket.
- # For development and testing purposes, an extra storage is added to gitaly,
- # which is not known to Rails, but must be explicitly stubbed.
- def gitaly_configuration_toml(gitaly_dir, storage_paths, gitaly_ruby: true)
- storages = []
- address = nil
-
- Gitlab.config.repositories.storages.each do |key, val|
- if address
- if address != val['gitaly_address']
- raise ArgumentError, "Your gitlab.yml contains more than one gitaly_address."
+ def create_configuration(dir, storage_paths, force: false)
+ generate_configuration(
+ configuration_toml(dir, storage_paths),
+ get_config_path(dir),
+ force: force
+ )
+ end
+
+ # rubocop:disable Rails/Output
+ def generate_configuration(toml_data, config_path, force: false)
+ FileUtils.rm_f(config_path) if force
+
+ File.open(config_path, File::WRONLY | File::CREAT | File::EXCL) do |f|
+ f.puts toml_data
+ end
+ rescue Errno::EEXIST
+ puts 'Skipping config.toml generation:'
+ puts 'A configuration file already exists.'
+ rescue ArgumentError => e
+ puts 'Skipping config.toml generation:'
+ puts e.message
+ end
+ # rubocop:enable Rails/Output
+
+ module Gitaly
+ extend Gitlab::SetupHelper
+ class << self
+ # We cannot create config.toml files for all possible Gitaly configuations.
+ # For instance, if Gitaly is running on another machine then it makes no
+ # sense to write a config.toml file on the current machine. This method will
+ # only generate a configuration for the most common and simplest case: when
+ # we have exactly one Gitaly process and we are sure it is running locally
+ # because it uses a Unix socket.
+ # For development and testing purposes, an extra storage is added to gitaly,
+ # which is not known to Rails, but must be explicitly stubbed.
+ def configuration_toml(gitaly_dir, storage_paths, gitaly_ruby: true)
+ storages = []
+ address = nil
+
+ Gitlab.config.repositories.storages.each do |key, val|
+ if address
+ if address != val['gitaly_address']
+ raise ArgumentError, "Your gitlab.yml contains more than one gitaly_address."
+ end
+ elsif URI(val['gitaly_address']).scheme != 'unix'
+ raise ArgumentError, "Automatic config.toml generation only supports 'unix:' addresses."
+ else
+ address = val['gitaly_address']
end
- elsif URI(val['gitaly_address']).scheme != 'unix'
- raise ArgumentError, "Automatic config.toml generation only supports 'unix:' addresses."
- else
- address = val['gitaly_address']
+
+ storages << { name: key, path: storage_paths[key] }
end
- storages << { name: key, path: storage_paths[key] }
- end
+ config = { socket_path: address.sub(/\Aunix:/, '') }
- if Rails.env.test?
- storage_path = Rails.root.join('tmp', 'tests', 'second_storage').to_s
- storages << { name: 'test_second_storage', path: storage_path }
- end
+ if Rails.env.test?
+ storage_path = Rails.root.join('tmp', 'tests', 'second_storage').to_s
+ storages << { name: 'test_second_storage', path: storage_path }
+
+ config[:auth] = { token: 'secret' }
+ # Compared to production, tests run in constrained environments. This
+ # number is meant to grow with the number of concurrent rails requests /
+ # sidekiq jobs, and concurrency will be low anyway in test.
+ config[:git] = { catfile_cache_size: 5 }
+ end
- config = { socket_path: address.sub(/\Aunix:/, ''), storage: storages }
- config[:auth] = { token: 'secret' } if Rails.env.test?
+ config[:storage] = storages
- internal_socket_dir = File.join(gitaly_dir, 'internal_sockets')
- FileUtils.mkdir(internal_socket_dir) unless File.exist?(internal_socket_dir)
- config[:internal_socket_dir] = internal_socket_dir
+ internal_socket_dir = File.join(gitaly_dir, 'internal_sockets')
+ FileUtils.mkdir(internal_socket_dir) unless File.exist?(internal_socket_dir)
+ config[:internal_socket_dir] = internal_socket_dir
- config[:'gitaly-ruby'] = { dir: File.join(gitaly_dir, 'ruby') } if gitaly_ruby
- config[:'gitlab-shell'] = { dir: Gitlab.config.gitlab_shell.path }
- config[:bin_dir] = Gitlab.config.gitaly.client_path
+ config[:'gitaly-ruby'] = { dir: File.join(gitaly_dir, 'ruby') } if gitaly_ruby
+ config[:'gitlab-shell'] = { dir: Gitlab.config.gitlab_shell.path }
+ config[:bin_dir] = Gitlab.config.gitaly.client_path
- if Rails.env.test?
- # Compared to production, tests run in constrained environments. This
- # number is meant to grow with the number of concurrent rails requests /
- # sidekiq jobs, and concurrency will be low anyway in test.
- config[:git] = { catfile_cache_size: 5 }
+ TomlRB.dump(config)
end
- TomlRB.dump(config)
+ private
+
+ def get_config_path(dir)
+ File.join(dir, 'config.toml')
+ end
end
+ end
+
+ module Praefect
+ extend Gitlab::SetupHelper
+ class << self
+ def configuration_toml(gitaly_dir, storage_paths)
+ nodes = [{ storage: 'default', address: "unix:#{gitaly_dir}/gitaly.socket", primary: true, token: 'secret' }]
+ config = { socket_path: "#{gitaly_dir}/praefect.socket", virtual_storage_name: 'default', token: 'secret', node: nodes }
+ config[:token] = 'secret' if Rails.env.test?
+
+ TomlRB.dump(config)
+ end
- # rubocop:disable Rails/Output
- def create_gitaly_configuration(dir, storage_paths, force: false)
- config_path = File.join(dir, 'config.toml')
- FileUtils.rm_f(config_path) if force
+ private
- File.open(config_path, File::WRONLY | File::CREAT | File::EXCL) do |f|
- f.puts gitaly_configuration_toml(dir, storage_paths)
+ def get_config_path(dir)
+ File.join(dir, 'praefect.config.toml')
end
- rescue Errno::EEXIST
- puts "Skipping config.toml generation:"
- puts "A configuration file already exists."
- rescue ArgumentError => e
- puts "Skipping config.toml generation:"
- puts e.message
end
- # rubocop:enable Rails/Output
end
end
end
diff --git a/lib/tasks/gitlab/gitaly.rake b/lib/tasks/gitlab/gitaly.rake
index c63ddb62f2a..ee47f71af93 100644
--- a/lib/tasks/gitlab/gitaly.rake
+++ b/lib/tasks/gitlab/gitaly.rake
@@ -27,7 +27,7 @@ Usage: rake "gitlab:gitaly:install[/installation/dir,/storage/path]")
end
storage_paths = { 'default' => args.storage_path }
- Gitlab::SetupHelper.create_gitaly_configuration(args.dir, storage_paths)
+ Gitlab::SetupHelper::Gitaly.create_configuration(args.dir, storage_paths)
Dir.chdir(args.dir) do
# In CI we run scripts/gitaly-test-build instead of this command
unless ENV['CI'].present?
diff --git a/lib/uploaded_file.rb b/lib/uploaded_file.rb
index 424db653fb8..f8d596b5d14 100644
--- a/lib/uploaded_file.rb
+++ b/lib/uploaded_file.rb
@@ -48,7 +48,7 @@ class UploadedFile
return if path.blank? && remote_id.blank?
file_path = nil
- if path
+ if path.present?
file_path = File.realpath(path)
paths = Array(upload_paths) << Dir.tmpdir
diff --git a/package.json b/package.json
index 5102e5730b3..225c8e7817b 100644
--- a/package.json
+++ b/package.json
@@ -40,7 +40,7 @@
"@babel/preset-env": "^7.8.4",
"@gitlab/at.js": "^1.5.5",
"@gitlab/svgs": "^1.115.0",
- "@gitlab/ui": "^10.0.0",
+ "@gitlab/ui": "^10.0.1",
"@gitlab/visual-review-tools": "1.5.1",
"@sentry/browser": "^5.10.2",
"@sourcegraph/code-host-integration": "0.0.33",
diff --git a/qa/qa/specs/features/browser_ui/3_create/merge_request/rebase_merge_request_spec.rb b/qa/qa/specs/features/browser_ui/3_create/merge_request/rebase_merge_request_spec.rb
index 1c78deae2bf..4e189faec6e 100644
--- a/qa/qa/specs/features/browser_ui/3_create/merge_request/rebase_merge_request_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/merge_request/rebase_merge_request_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module QA
- context 'Create', quarantine: { issue: 'https://gitlab.com/gitlab-org/gitlab/issues/36817', type: :bug } do
+ context 'Create', quarantine: { issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/30226', type: :bug } do
describe 'Merge request rebasing' do
it 'user rebases source branch of merge request' do
Flow::Login.sign_in
diff --git a/scripts/gitaly-test-build b/scripts/gitaly-test-build
index 374401caf89..fcf0049162b 100755
--- a/scripts/gitaly-test-build
+++ b/scripts/gitaly-test-build
@@ -17,13 +17,16 @@ class GitalyTestBuild
check_gitaly_config!
# Starting gitaly further validates its configuration
- pid = start_gitaly
- Process.kill('TERM', pid)
+ gitaly_pid = start_gitaly
+ praefect_pid = start_praefect
+ Process.kill('TERM', gitaly_pid)
+ Process.kill('TERM', praefect_pid)
# Make the 'gitaly' executable look newer than 'GITALY_SERVER_VERSION'.
# Without this a gitaly executable created in the setup-test-env job
# will look stale compared to GITALY_SERVER_VERSION.
FileUtils.touch(File.join(tmp_tests_gitaly_dir, 'gitaly'), mtime: Time.now + (1 << 24))
+ FileUtils.touch(File.join(tmp_tests_gitaly_dir, 'praefect'), mtime: Time.now + (1 << 24))
end
end
diff --git a/scripts/gitaly-test-spawn b/scripts/gitaly-test-spawn
index e9f91f75650..8e16b2bb656 100755
--- a/scripts/gitaly-test-spawn
+++ b/scripts/gitaly-test-spawn
@@ -13,10 +13,9 @@ class GitalyTestSpawn
# # Uncomment line below to see all gitaly logs merged into CI trace
# spawn('sleep 1; tail -f log/gitaly-test.log')
- pid = start_gitaly
-
# In local development this pid file is used by rspec.
- IO.write(File.expand_path('../tmp/tests/gitaly.pid', __dir__), pid)
+ IO.write(File.expand_path('../tmp/tests/gitaly.pid', __dir__), start_gitaly)
+ IO.write(File.expand_path('../tmp/tests/praefect.pid', __dir__), start_praefect)
end
end
diff --git a/scripts/gitaly_test.rb b/scripts/gitaly_test.rb
index 922dc17ed2e..8db47afdd4d 100644
--- a/scripts/gitaly_test.rb
+++ b/scripts/gitaly_test.rb
@@ -37,16 +37,31 @@ module GitalyTest
env_hash
end
- def config_path
- File.join(tmp_tests_gitaly_dir, 'config.toml')
+ def config_path(service)
+ case service
+ when :gitaly
+ File.join(tmp_tests_gitaly_dir, 'config.toml')
+ when :praefect
+ File.join(tmp_tests_gitaly_dir, 'praefect.config.toml')
+ end
end
def start_gitaly
- args = %W[#{tmp_tests_gitaly_dir}/gitaly #{config_path}]
- pid = spawn(env, *args, [:out, :err] => 'log/gitaly-test.log')
+ start(:gitaly)
+ end
+
+ def start_praefect
+ start(:praefect)
+ end
+
+ def start(service)
+ args = ["#{tmp_tests_gitaly_dir}/#{service}"]
+ args.push("-config") if service == :praefect
+ args.push(config_path(service))
+ pid = spawn(env, *args, [:out, :err] => "log/#{service}-test.log")
begin
- try_connect!
+ try_connect!(service)
rescue
Process.kill('TERM', pid)
raise
@@ -68,11 +83,11 @@ module GitalyTest
abort 'bundle check failed' unless system(env, 'bundle', 'check', chdir: File.dirname(gemfile))
end
- def read_socket_path
+ def read_socket_path(service)
# This code needs to work in an environment where we cannot use bundler,
# so we cannot easily use the toml-rb gem. This ad-hoc parser should be
# good enough.
- config_text = IO.read(config_path)
+ config_text = IO.read(config_path(service))
config_text.lines.each do |line|
match_data = line.match(/^\s*socket_path\s*=\s*"([^"]*)"$/)
@@ -80,14 +95,14 @@ module GitalyTest
return match_data[1] if match_data
end
- raise "failed to find socket_path in #{config_path}"
+ raise "failed to find socket_path in #{config_path(service)}"
end
- def try_connect!
- print "Trying to connect to gitaly: "
+ def try_connect!(service)
+ print "Trying to connect to #{service}: "
timeout = 20
delay = 0.1
- socket = read_socket_path
+ socket = read_socket_path(service)
Integer(timeout / delay).times do
UNIXSocket.new(socket)
diff --git a/spec/lib/gitlab/database/postgresql_adapter/schema_versions_copy_mixin_spec.rb b/spec/lib/gitlab/database/postgresql_adapter/schema_versions_copy_mixin_spec.rb
new file mode 100644
index 00000000000..968dfc1ea43
--- /dev/null
+++ b/spec/lib/gitlab/database/postgresql_adapter/schema_versions_copy_mixin_spec.rb
@@ -0,0 +1,42 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Gitlab::Database::PostgresqlAdapter::SchemaVersionsCopyMixin do
+ let(:schema_migration) { double('schem_migration', table_name: table_name, all_versions: versions) }
+ let(:versions) { %w(5 2 1000 200 4 93 2) }
+ let(:table_name) { "schema_migrations" }
+
+ let(:instance) do
+ Object.new.extend(described_class)
+ end
+
+ before do
+ allow(instance).to receive(:schema_migration).and_return(schema_migration)
+ allow(instance).to receive(:quote_table_name).with(table_name).and_return("\"#{table_name}\"")
+ end
+
+ subject { instance.dump_schema_information }
+
+ it 'uses COPY FROM STDIN' do
+ expect(subject.split("\n").first).to match(/COPY "schema_migrations" \(version\) FROM STDIN;/)
+ end
+
+ it 'contains a sorted list of versions by their numeric value' do
+ version_lines = subject.split("\n")[1..-2].map(&:to_i)
+
+ expect(version_lines).to eq(versions.map(&:to_i).sort)
+ end
+
+ it 'contains a end-of-data marker' do
+ expect(subject).to end_with("\\.\n")
+ end
+
+ context 'with non-Integer versions' do
+ let(:versions) { %w(5 2 4 abc) }
+
+ it 'raises an error' do
+ expect { subject }.to raise_error(/invalid value for Integer/)
+ end
+ end
+end
diff --git a/spec/lib/uploaded_file_spec.rb b/spec/lib/uploaded_file_spec.rb
index 2bbbd67b13c..25536c07dd9 100644
--- a/spec/lib/uploaded_file_spec.rb
+++ b/spec/lib/uploaded_file_spec.rb
@@ -59,6 +59,16 @@ describe UploadedFile do
expect(subject.sha256).to eq('sha256')
expect(subject.remote_id).to eq('remote_id')
end
+
+ it 'handles a blank path' do
+ params['file.path'] = ''
+
+ # Not a real file, so can't determine size itself
+ params['file.size'] = 1.byte
+
+ expect { described_class.from_params(params, :file, upload_path) }
+ .not_to raise_error
+ end
end
end
diff --git a/spec/models/concerns/bulk_insert_safe_spec.rb b/spec/models/concerns/bulk_insert_safe_spec.rb
index a8e56cb8bdd..5ed1d6b9967 100644
--- a/spec/models/concerns/bulk_insert_safe_spec.rb
+++ b/spec/models/concerns/bulk_insert_safe_spec.rb
@@ -129,10 +129,37 @@ describe BulkInsertSafe do
end.not_to change { described_class.count }
end
- it 'does nothing and returns true when items are empty' do
- expect(described_class.bulk_insert!([])).to be(true)
+ it 'does nothing and returns an empty array when items are empty' do
+ expect(described_class.bulk_insert!([])).to eq([])
expect(described_class.count).to eq(0)
end
+
+ context 'with returns option set' do
+ context 'when is set to :ids' do
+ it 'return an array with the primary key values for all inserted records' do
+ items = described_class.valid_list(1)
+
+ expect(described_class.bulk_insert!(items, returns: :ids)).to contain_exactly(a_kind_of(Integer))
+ end
+ end
+
+ context 'when is set to nil' do
+ it 'returns an empty array' do
+ items = described_class.valid_list(1)
+
+ expect(described_class.bulk_insert!(items, returns: nil)).to eq([])
+ end
+ end
+
+ context 'when is set to anything else' do
+ it 'raises an error' do
+ items = described_class.valid_list(1)
+
+ expect { described_class.bulk_insert!([items], returns: [:id, :name]) }
+ .to raise_error(ArgumentError, "returns needs to be :ids or nil")
+ end
+ end
+ end
end
context 'when duplicate items are to be inserted' do
diff --git a/spec/requests/api/releases_spec.rb b/spec/requests/api/releases_spec.rb
index e66e999dc27..0589554bf44 100644
--- a/spec/requests/api/releases_spec.rb
+++ b/spec/requests/api/releases_spec.rb
@@ -6,6 +6,7 @@ describe API::Releases do
let(:project) { create(:project, :repository, :private) }
let(:maintainer) { create(:user) }
let(:reporter) { create(:user) }
+ let(:developer) { create(:user) }
let(:guest) { create(:user) }
let(:non_project_member) { create(:user) }
let(:commit) { create(:commit, project: project) }
@@ -15,6 +16,7 @@ describe API::Releases do
project.add_maintainer(maintainer)
project.add_reporter(reporter)
project.add_guest(guest)
+ project.add_developer(developer)
project.repository.add_tag(maintainer, 'v0.1', commit.id)
project.repository.add_tag(maintainer, 'v0.2', commit.id)
@@ -248,6 +250,24 @@ describe API::Releases do
.to match_array(release.sources.map(&:url))
end
+ context 'with evidence' do
+ let!(:evidence) { create(:evidence, release: release) }
+
+ it 'returns the evidence' do
+ get api("/projects/#{project.id}/releases/v0.1", maintainer)
+
+ expect(json_response['evidences'].count).to eq(1)
+ end
+
+ it '#collected_at' do
+ Timecop.freeze(Time.now.round) do
+ get api("/projects/#{project.id}/releases/v0.1", maintainer)
+
+ expect(json_response['evidences'].first['collected_at'].to_datetime.to_i).to be_within(1.minute).of(release.evidences.first.created_at.to_i)
+ end
+ end
+ end
+
context 'when release has link asset' do
let!(:link) do
create(:release_link,
diff --git a/spec/services/projects/prometheus/alerts/notify_service_spec.rb b/spec/services/projects/prometheus/alerts/notify_service_spec.rb
new file mode 100644
index 00000000000..ce850e65329
--- /dev/null
+++ b/spec/services/projects/prometheus/alerts/notify_service_spec.rb
@@ -0,0 +1,343 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Projects::Prometheus::Alerts::NotifyService do
+ let_it_be(:project, reload: true) { create(:project) }
+
+ let(:service) { described_class.new(project, nil, payload) }
+ let(:token_input) { 'token' }
+
+ let!(:setting) do
+ create(:project_incident_management_setting, project: project, send_email: true, create_issue: true)
+ end
+
+ let(:subject) { service.execute(token_input) }
+
+ before do
+ # We use `let_it_be(:project)` so we make sure to clear caches
+ project.clear_memoization(:licensed_feature_available)
+ end
+
+ shared_examples 'sends notification email' do
+ let(:notification_service) { spy }
+
+ it 'sends a notification for firing alerts only' do
+ expect(NotificationService)
+ .to receive(:new)
+ .and_return(notification_service)
+
+ expect(notification_service)
+ .to receive_message_chain(:async, :prometheus_alerts_fired)
+
+ expect(subject).to eq(true)
+ end
+ end
+
+ shared_examples 'processes incident issues' do |amount|
+ let(:create_incident_service) { spy }
+
+ it 'processes issues' do
+ expect(IncidentManagement::ProcessPrometheusAlertWorker)
+ .to receive(:perform_async)
+ .with(project.id, kind_of(Hash))
+ .exactly(amount).times
+
+ Sidekiq::Testing.inline! do
+ expect(subject).to eq(true)
+ end
+ end
+ end
+
+ shared_examples 'does not process incident issues' do
+ it 'does not process issues' do
+ expect(IncidentManagement::ProcessPrometheusAlertWorker)
+ .not_to receive(:perform_async)
+
+ expect(subject).to eq(true)
+ end
+ end
+
+ shared_examples 'persists events' do
+ let(:create_events_service) { spy }
+
+ it 'persists events' do
+ expect(Projects::Prometheus::Alerts::CreateEventsService)
+ .to receive(:new)
+ .and_return(create_events_service)
+
+ expect(create_events_service)
+ .to receive(:execute)
+
+ expect(subject).to eq(true)
+ end
+ end
+
+ shared_examples 'notifies alerts' do
+ it_behaves_like 'sends notification email'
+ it_behaves_like 'persists events'
+ end
+
+ shared_examples 'no notifications' do
+ let(:notification_service) { spy }
+ let(:create_events_service) { spy }
+
+ it 'does not notify' do
+ expect(notification_service).not_to receive(:async)
+ expect(create_events_service).not_to receive(:execute)
+
+ expect(subject).to eq(false)
+ end
+ end
+
+ context 'with valid payload' do
+ let(:alert_firing) { create(:prometheus_alert, project: project) }
+ let(:alert_resolved) { create(:prometheus_alert, project: project) }
+ let(:payload_raw) { payload_for(firing: [alert_firing], resolved: [alert_resolved]) }
+ let(:payload) { ActionController::Parameters.new(payload_raw).permit! }
+ let(:payload_alert_firing) { payload_raw['alerts'].first }
+ let(:token) { 'token' }
+
+ context 'with project specific cluster' do
+ using RSpec::Parameterized::TableSyntax
+
+ where(:cluster_enabled, :status, :configured_token, :token_input, :result) do
+ true | :installed | token | token | :success
+ true | :installed | nil | nil | :success
+ true | :updated | token | token | :success
+ true | :updating | token | token | :failure
+ true | :installed | token | 'x' | :failure
+ true | :installed | nil | token | :failure
+ true | :installed | token | nil | :failure
+ true | nil | token | token | :failure
+ false | :installed | token | token | :failure
+ end
+
+ with_them do
+ before do
+ cluster = create(:cluster, :provided_by_user,
+ projects: [project],
+ enabled: cluster_enabled)
+
+ if status
+ create(:clusters_applications_prometheus, status,
+ cluster: cluster,
+ alert_manager_token: configured_token)
+ end
+ end
+
+ case result = params[:result]
+ when :success
+ it_behaves_like 'notifies alerts'
+ when :failure
+ it_behaves_like 'no notifications'
+ else
+ raise "invalid result: #{result.inspect}"
+ end
+ end
+ end
+
+ context 'without project specific cluster' do
+ let!(:cluster) { create(:cluster, enabled: true) }
+
+ it_behaves_like 'no notifications'
+ end
+
+ context 'with manual prometheus installation' do
+ using RSpec::Parameterized::TableSyntax
+
+ where(:alerting_setting, :configured_token, :token_input, :result) do
+ true | token | token | :success
+ true | token | 'x' | :failure
+ true | token | nil | :failure
+ false | nil | nil | :success
+ false | nil | token | :failure
+ end
+
+ with_them do
+ let(:alert_manager_token) { token_input }
+
+ before do
+ create(:prometheus_service, project: project)
+
+ if alerting_setting
+ create(:project_alerting_setting,
+ project: project,
+ token: configured_token)
+ end
+ end
+
+ case result = params[:result]
+ when :success
+ it_behaves_like 'notifies alerts'
+ when :failure
+ it_behaves_like 'no notifications'
+ else
+ raise "invalid result: #{result.inspect}"
+ end
+ end
+ end
+
+ context 'alert emails' do
+ before do
+ create(:prometheus_service, project: project)
+ create(:project_alerting_setting, project: project, token: token)
+ end
+
+ context 'when incident_management_setting does not exist' do
+ let!(:setting) { nil }
+
+ it_behaves_like 'persists events'
+
+ it 'does not send notification email', :sidekiq_might_not_need_inline do
+ expect_any_instance_of(NotificationService)
+ .not_to receive(:async)
+
+ expect(subject).to eq(true)
+ end
+ end
+
+ context 'when incident_management_setting.send_email is true' do
+ it_behaves_like 'notifies alerts'
+ end
+
+ context 'incident_management_setting.send_email is false' do
+ let!(:setting) do
+ create(:project_incident_management_setting, send_email: false, project: project)
+ end
+
+ it_behaves_like 'persists events'
+
+ it 'does not send notification' do
+ expect(NotificationService).not_to receive(:new)
+
+ expect(subject).to eq(true)
+ end
+ end
+ end
+
+ context 'process incident issues' do
+ before do
+ create(:prometheus_service, project: project)
+ create(:project_alerting_setting, project: project, token: token)
+ end
+
+ context 'with create_issue setting enabled' do
+ before do
+ setting.update!(create_issue: true)
+ end
+
+ it_behaves_like 'processes incident issues', 2
+
+ context 'multiple firing alerts' do
+ let(:payload_raw) do
+ payload_for(firing: [alert_firing, alert_firing], resolved: [])
+ end
+
+ it_behaves_like 'processes incident issues', 2
+ end
+
+ context 'without firing alerts' do
+ let(:payload_raw) do
+ payload_for(firing: [], resolved: [alert_resolved])
+ end
+
+ it_behaves_like 'processes incident issues', 1
+ end
+ end
+
+ context 'with create_issue setting disabled' do
+ before do
+ setting.update!(create_issue: false)
+ end
+
+ it_behaves_like 'does not process incident issues'
+ end
+ end
+ end
+
+ context 'with invalid payload' do
+ context 'without version' do
+ let(:payload) { {} }
+
+ it_behaves_like 'no notifications'
+ end
+
+ context 'when version is not "4"' do
+ let(:payload) { { 'version' => '5' } }
+
+ it_behaves_like 'no notifications'
+ end
+
+ context 'with missing alerts' do
+ let(:payload) { { 'version' => '4' } }
+
+ it_behaves_like 'no notifications'
+ end
+
+ context 'when the payload is too big' do
+ let(:payload) { { 'the-payload-is-too-big' => true } }
+ let(:deep_size_object) { instance_double(Gitlab::Utils::DeepSize, valid?: false) }
+
+ before do
+ allow(Gitlab::Utils::DeepSize).to receive(:new).and_return(deep_size_object)
+ end
+
+ it_behaves_like 'no notifications'
+
+ it 'does not process issues' do
+ expect(IncidentManagement::ProcessPrometheusAlertWorker)
+ .not_to receive(:perform_async)
+
+ subject
+ end
+ end
+ end
+
+ private
+
+ def payload_for(firing: [], resolved: [])
+ status = firing.any? ? 'firing' : 'resolved'
+ alerts = firing + resolved
+ alert_name = alerts.first.title
+ prometheus_metric_id = alerts.first.prometheus_metric_id.to_s
+
+ alerts_map = \
+ firing.map { |alert| map_alert_payload('firing', alert) } +
+ resolved.map { |alert| map_alert_payload('resolved', alert) }
+
+ # See https://prometheus.io/docs/alerting/configuration/#%3Cwebhook_config%3E
+ {
+ 'version' => '4',
+ 'receiver' => 'gitlab',
+ 'status' => status,
+ 'alerts' => alerts_map,
+ 'groupLabels' => {
+ 'alertname' => alert_name
+ },
+ 'commonLabels' => {
+ 'alertname' => alert_name,
+ 'gitlab' => 'hook',
+ 'gitlab_alert_id' => prometheus_metric_id
+ },
+ 'commonAnnotations' => {},
+ 'externalURL' => '',
+ 'groupKey' => "{}:{alertname=\'#{alert_name}\'}"
+ }
+ end
+
+ def map_alert_payload(status, alert)
+ {
+ 'status' => status,
+ 'labels' => {
+ 'alertname' => alert.title,
+ 'gitlab' => 'hook',
+ 'gitlab_alert_id' => alert.prometheus_metric_id.to_s
+ },
+ 'annotations' => {},
+ 'startsAt' => '2018-09-24T08:57:31.095725221Z',
+ 'endsAt' => '0001-01-01T00:00:00Z',
+ 'generatorURL' => 'http://prometheus-prometheus-server-URL'
+ }
+ end
+end
diff --git a/spec/support/helpers/test_env.rb b/spec/support/helpers/test_env.rb
index 66c2faac2dd..2e69c59c80a 100644
--- a/spec/support/helpers/test_env.rb
+++ b/spec/support/helpers/test_env.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: true
require 'rspec/mocks'
-require 'toml-rb'
module TestEnv
extend ActiveSupport::Concern
@@ -87,7 +86,7 @@ module TestEnv
'conflict-resolvable-fork' => '404fa3f'
}.freeze
- TMP_TEST_PATH = Rails.root.join('tmp', 'tests', '**')
+ TMP_TEST_PATH = Rails.root.join('tmp', 'tests').freeze
REPOS_STORAGE = 'default'.freeze
SECOND_STORAGE_PATH = Rails.root.join('tmp', 'tests', 'second_storage')
@@ -140,7 +139,7 @@ module TestEnv
#
# Keeps gitlab-shell and gitlab-test
def clean_test_path
- Dir[TMP_TEST_PATH].each do |entry|
+ Dir[File.join(TMP_TEST_PATH, '**')].each do |entry|
unless test_dirs.include?(File.basename(entry))
FileUtils.rm_rf(entry)
end
@@ -164,7 +163,8 @@ module TestEnv
install_dir: gitaly_dir,
version: Gitlab::GitalyClient.expected_server_version,
task: "gitlab:gitaly:install[#{install_gitaly_args}]") do
- Gitlab::SetupHelper.create_gitaly_configuration(gitaly_dir, { 'default' => repos_path }, force: true)
+ Gitlab::SetupHelper::Gitaly.create_configuration(gitaly_dir, { 'default' => repos_path }, force: true)
+ Gitlab::SetupHelper::Praefect.create_configuration(gitaly_dir, { 'praefect' => repos_path }, force: true)
start_gitaly(gitaly_dir)
end
end
@@ -192,17 +192,38 @@ module TestEnv
end
end
- @gitaly_pid = Integer(File.read('tmp/tests/gitaly.pid'))
+ gitaly_pid = Integer(File.read(TMP_TEST_PATH.join('gitaly.pid')))
+ praefect_pid = Integer(File.read(TMP_TEST_PATH.join('praefect.pid')))
- Kernel.at_exit { stop_gitaly }
+ Kernel.at_exit { stop(gitaly_pid) }
+ Kernel.at_exit { stop(praefect_pid) }
- wait_gitaly
+ wait('gitaly')
+ wait('praefect')
end
- def wait_gitaly
+ def stop(pid)
+ Process.kill('KILL', pid)
+ rescue Errno::ESRCH
+ # The process can already be gone if the test run was INTerrupted.
+ end
+
+ def gitaly_url
+ ENV.fetch('GITALY_REPO_URL', nil)
+ end
+
+ def socket_path(service)
+ TMP_TEST_PATH.join('gitaly', "#{service}.socket").to_s
+ end
+
+ def praefect_socket_path
+ "unix:" + socket_path(:praefect)
+ end
+
+ def wait(service)
sleep_time = 10
sleep_interval = 0.1
- socket = Gitlab::GitalyClient.address('default').sub('unix:', '')
+ socket = socket_path(service)
Integer(sleep_time / sleep_interval).times do
Socket.unix(socket)
@@ -211,19 +232,7 @@ module TestEnv
sleep sleep_interval
end
- raise "could not connect to gitaly at #{socket.inspect} after #{sleep_time} seconds"
- end
-
- def stop_gitaly
- return unless @gitaly_pid
-
- Process.kill('KILL', @gitaly_pid)
- rescue Errno::ESRCH
- # The process can already be gone if the test run was INTerrupted.
- end
-
- def gitaly_url
- ENV.fetch('GITALY_REPO_URL', nil)
+ raise "could not connect to #{service} at #{socket.inspect} after #{sleep_time} seconds"
end
def setup_workhorse
diff --git a/spec/support/praefect.rb b/spec/support/praefect.rb
new file mode 100644
index 00000000000..3218275c2aa
--- /dev/null
+++ b/spec/support/praefect.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+require_relative 'helpers/test_env'
+
+RSpec.configure do |config|
+ config.before(:each, :praefect) do
+ allow(Gitlab.config.repositories.storages['default']).to receive(:[]).and_call_original
+ allow(Gitlab.config.repositories.storages['default']).to receive(:[]).with('gitaly_address')
+ .and_return(TestEnv.praefect_socket_path)
+ end
+end
diff --git a/spec/support/shared_examples/models/concerns/bulk_insert_safe_shared_examples.rb b/spec/support/shared_examples/models/concerns/bulk_insert_safe_shared_examples.rb
index c6180a5a196..7bcd6191f1d 100644
--- a/spec/support/shared_examples/models/concerns/bulk_insert_safe_shared_examples.rb
+++ b/spec/support/shared_examples/models/concerns/bulk_insert_safe_shared_examples.rb
@@ -45,11 +45,11 @@ RSpec.shared_examples 'a BulkInsertSafe model' do |klass|
expect { target_class.bulk_insert!(items) }.to change { target_class.count }.by(items.size)
end
- it 'returns true' do
+ it 'returns an empty array' do
items = valid_items_for_bulk_insertion
expect(items).not_to be_empty
- expect(target_class.bulk_insert!(items)).to be true
+ expect(target_class.bulk_insert!(items)).to eq([])
end
end
@@ -69,7 +69,7 @@ RSpec.shared_examples 'a BulkInsertSafe model' do |klass|
# it is not always possible to create invalid items
if items.any?
- expect(target_class.bulk_insert!(items, validate: false)).to be(true)
+ expect(target_class.bulk_insert!(items, validate: false)).to eq([])
expect(target_class.count).to eq(items.size)
end
end
diff --git a/yarn.lock b/yarn.lock
index f97529d9e4c..4886a3651d1 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -786,10 +786,10 @@
resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-1.115.0.tgz#2762ad045d5a2bd728f74fcb4c00caa9bd6dbc22"
integrity sha512-jlmNGqCTpSiPFrNbLaW6GGXNbvIShLdrpeYTtSEz/yFJMClQfPjHc8Zm9bl/PqAM5d/yGQqk8e+rBc4LeAhEfg==
-"@gitlab/ui@^10.0.0":
- version "10.0.0"
- resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-10.0.0.tgz#dced1119237f328367e8c4922cf4e1ae986fac54"
- integrity sha512-+qsojtfE5mhryjJyReXBY9C3J4s4jlRpHfEcaCFuhcebtq5Uhd6xgLwgxT+E7fMvtLQpGATMo1DiD80yhLb2pQ==
+"@gitlab/ui@^10.0.1":
+ version "10.0.1"
+ resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-10.0.1.tgz#65deee8ded3b8d003dfd74cd93c7eb0549e11b37"
+ integrity sha512-RMOJjpZjmWJnu0ebfGJsPOn6/ko+HlfHYbBXBImpTIk6Xsr5AaRjT4yCYEoefZ55jK/SJ2nxHytqrMe26wjfDA==
dependencies:
"@babel/standalone" "^7.0.0"
"@gitlab/vue-toasted" "^1.3.0"