summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2022-09-23 00:10:38 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2022-09-23 00:10:38 +0000
commita7698afc6e7a5a6e4e5044f5b310a2c69c554053 (patch)
tree5be1ccc63a64e7cd3decc9523ec8cbaa950db758
parentaaedbff77d0e656e9738322a59476bbb2fab8266 (diff)
downloadgitlab-ce-a7698afc6e7a5a6e4e5044f5b310a2c69c554053.tar.gz
Add latest changes from gitlab-org/gitlab@master
-rw-r--r--GITALY_SERVER_VERSION2
-rw-r--r--Gemfile6
-rw-r--r--Gemfile.checksum23
-rw-r--r--app/models/incident_management/timeline_event.rb3
-rw-r--r--app/models/ml/candidate_param.rb1
-rw-r--r--config/feature_flags/development/escape_gitaly_refs.yml8
-rw-r--r--config/locales/en.yml2
-rw-r--r--config/metrics/counts_all/20210216180413_all_searches.yml5
-rw-r--r--config/metrics/counts_all/20210216180414_navbar_searches.yml5
-rw-r--r--config/metrics/counts_all/20210505015532_kubernetes_agent_k8s_api_proxy_request.yml4
-rw-r--r--db/migrate/20220914080716_add_index_to_candidate_id_and_name_on_ml_candidate_params.rb15
-rw-r--r--db/schema_migrations/202209140807161
-rw-r--r--db/structure.sql2
-rw-r--r--doc/administration/geo/secondary_proxy/index.md7
-rw-r--r--doc/development/gemfile.md36
-rw-r--r--lib/api/entities/ml/mlflow/run.rb1
-rw-r--r--lib/api/entities/ml/mlflow/run_param.rb14
-rw-r--r--lib/api/ml/mlflow.rb70
-rw-r--r--lib/gitlab/encoding_helper.rb2
-rw-r--r--lib/gitlab/usage/metrics/instrumentations/redis_metric.rb10
-rw-r--r--lib/gitlab/usage_data_counters.rb4
-rw-r--r--locale/gitlab.pot3
-rw-r--r--spec/factories/ml/candidate_params.rb10
-rw-r--r--spec/factories/ml/candidates.rb3
-rw-r--r--spec/graphql/mutations/incident_management/timeline_event/create_spec.rb2
-rw-r--r--spec/graphql/mutations/incident_management/timeline_event/update_spec.rb2
-rw-r--r--spec/lib/api/entities/ml/mlflow/run_spec.rb24
-rw-r--r--spec/lib/gitlab/encoding_helper_spec.rb12
-rw-r--r--spec/lib/gitlab/usage/metrics/instrumentations/redis_metric_spec.rb14
-rw-r--r--spec/lib/gitlab/usage_data_spec.rb7
-rw-r--r--spec/models/incident_management/timeline_event_spec.rb1
-rw-r--r--spec/models/ml/candidate_spec.rb2
-rw-r--r--spec/requests/api/ml/mlflow_spec.rb114
-rw-r--r--spec/services/incident_management/timeline_events/create_service_spec.rb2
-rw-r--r--spec/services/incident_management/timeline_events/destroy_service_spec.rb2
-rw-r--r--spec/services/incident_management/timeline_events/update_service_spec.rb2
-rw-r--r--spec/support/helpers/usage_data_helpers.rb1
37 files changed, 349 insertions, 73 deletions
diff --git a/GITALY_SERVER_VERSION b/GITALY_SERVER_VERSION
index beb66fcc2b4..80c8a866e1f 100644
--- a/GITALY_SERVER_VERSION
+++ b/GITALY_SERVER_VERSION
@@ -1 +1 @@
-e4d8f69ffa2efd3f2cb0adff5fa66f367f66f6fb
+9498ab9459048cc595d8e2e411b027d080c0ab0f
diff --git a/Gemfile b/Gemfile
index 53b5d96b476..8cf345a5829 100644
--- a/Gemfile
+++ b/Gemfile
@@ -2,6 +2,12 @@
source 'https://rubygems.org'
+if ENV['BUNDLER_CHECKSUM_VERIFICATION_OPT_IN'] # this verification is still experimental
+ $:.unshift(File.expand_path("vendor/gems/bundler-checksum/lib", __dir__))
+ require 'bundler-checksum'
+ Bundler::Checksum.patch!
+end
+
gem 'bundler-checksum', '~> 0.1.0', path: 'vendor/gems/bundler-checksum', require: false
gem 'rails', '~> 6.1.6.1'
diff --git a/Gemfile.checksum b/Gemfile.checksum
index 542a8d25fb6..31845fc2f3b 100644
--- a/Gemfile.checksum
+++ b/Gemfile.checksum
@@ -205,11 +205,11 @@
{"name":"gitlab-labkit","version":"0.24.0","platform":"ruby","checksum":"8f16e5aa4e0a05be58958fe880bdd53c84b659a081ea9981d2b510922a4a0548"},
{"name":"gitlab-license","version":"2.2.1","platform":"ruby","checksum":"39fcf6be8b2887df8afe01b5dcbae8d08b7c5d937ff56b0fb40484a8c4f02d30"},
{"name":"gitlab-mail_room","version":"0.0.9","platform":"ruby","checksum":"6700374b5c0aa9d9ad4e711aeb677f0b7d415a6d01d3baa699efab25349d851c"},
-{"name":"gitlab-markup","version":"1.8.0","platform":"ruby","checksum":"fb629369dca5dd343e47ebf5fa2e0a0fc146012fc49c35eff5ca826ae4186c86"},
+{"name":"gitlab-markup","version":"1.8.1","platform":"ruby","checksum":"ab1f9fd016977497c2af25b76341dea670533014f406861834a0bd99f646707b"},
{"name":"gitlab-net-dns","version":"0.9.1","platform":"ruby","checksum":"bcd1a08dcb31b731e8ff602d828de619d2d9f53f5812f6abacf11c720873d4cb"},
{"name":"gitlab-omniauth-openid-connect","version":"0.10.0","platform":"ruby","checksum":"ea44a23ea93457057bba6a9912e883f5aefab36a941c6c58512c8a7095fb1153"},
{"name":"gitlab-sidekiq-fetcher","version":"0.8.0","platform":"ruby","checksum":"9c564caa2a958d44a8d78672dc23b2a206102d0223b41b77b58626a945e37362"},
-{"name":"gitlab-styles","version":"8.0.0","platform":"ruby","checksum":"ff77d8543b7093e387430ebdaa2adce9dc3caaa8b10ce9bf9b40242d5f7b66da"},
+{"name":"gitlab-styles","version":"9.0.0","platform":"ruby","checksum":"ef0edfab8f807a5be2309ba24dfc44fec5ba52ed68b87167c051e9ffdadb3bad"},
{"name":"gitlab_chronic_duration","version":"0.10.6.2","platform":"ruby","checksum":"6dda4cfe7dca9b958f163ac8835c3d9cc70cf8df8cbb89bb2fbf9ba4375105fb"},
{"name":"gitlab_omniauth-ldap","version":"2.2.0","platform":"ruby","checksum":"bb4d20acb3b123ed654a8f6a47d3fac673ece7ed0b6992edb92dca14bad2838c"},
{"name":"globalid","version":"1.0.0","platform":"ruby","checksum":"1253641b1dc3392721c964351773755d75135d3d3c5cc65d88b0a3880a60bed8"},
@@ -364,7 +364,7 @@
{"name":"notiffany","version":"0.1.3","platform":"ruby","checksum":"d37669605b7f8dcb04e004e6373e2a780b98c776f8eb503ac9578557d7808738"},
{"name":"numerizer","version":"0.2.0","platform":"ruby","checksum":"e58076d5ee5370417b7e52d9cb25836d62acd1b8d9a194c308707986c1705d7b"},
{"name":"oauth","version":"0.5.6","platform":"ruby","checksum":"4085fe28e0c5e2434135e00a6555294fd2a4ff96a98d1bdecdcd619fc6368dff"},
-{"name":"oauth2","version":"2.0.3","platform":"ruby","checksum":"b343d8665a936b4223b335b38f8640134ce14e07c540b8d17e8bbac0b4e5c41b"},
+{"name":"oauth2","version":"2.0.9","platform":"ruby","checksum":"b21f9defcf52dc1610e0dfab4c868342173dcd707fd15c777d9f4f04e153f7fb"},
{"name":"octokit","version":"4.25.1","platform":"ruby","checksum":"c02092ee82dcdfe84db0e0ea630a70d32becc54245a4f0bacfd21c010df09b96"},
{"name":"ohai","version":"16.10.6","platform":"ruby","checksum":"b835806e585faea4ac8346b68c722fb5fc29a29f73fd7e3a022f9073132dec22"},
{"name":"oj","version":"3.13.21","platform":"ruby","checksum":"aef31a8dcc6f0b9b4bb5cc7ac6cc5272b2d851deb11a1804c2ed6b5501b50e46"},
@@ -380,7 +380,6 @@
{"name":"omniauth-oauth","version":"1.2.0","platform":"ruby","checksum":"e7a78658498dc83aa3f3be1a776425c0f06a60d45d9236dbe5e98e61fadf827b"},
{"name":"omniauth-oauth2","version":"1.7.3","platform":"ruby","checksum":"3f5a8f99fa72e0f91d2abd7475ceb972a4ae67ed59e049f314c0c1bad81f4745"},
{"name":"omniauth-oauth2-generic","version":"0.2.2","platform":"ruby","checksum":"e30814f6c472e04f3d9e4a3ddc03bc9a46f53f9333f8d443bf3ad43c6ebcdbd4"},
-{"name":"omniauth-rails_csrf_protection","version":"1.0.1","platform":"ruby","checksum":"fc546aeb7d43b7b9d7737051c380156e61c8f080b898cd4934d523eaa7e59acf"},
{"name":"omniauth-saml","version":"2.0.0","platform":"ruby","checksum":"02594fd6630de26a9e65a2e64223e9ad32324fa97a6c7f1f22a1553ea3dd44c7"},
{"name":"omniauth-shibboleth","version":"1.3.0","platform":"ruby","checksum":"b0bb725ced5cb76fbfc187ddbb8ad6864d0cd5df714cab36a528df8ee4b1d113"},
{"name":"omniauth-twitter","version":"1.4.0","platform":"ruby","checksum":"c5cc6c77cd767745ffa9ebbd5fbd694a3fa99d1d2d82a4d7def0bf3b6131b264"},
@@ -405,7 +404,7 @@
{"name":"pg","version":"1.4.1","platform":"x64-mingw-ucrt","checksum":"de35769d4e7c25daa035f2dc33447e74711ab0dc8b73f685a846987e0080d030"},
{"name":"pg","version":"1.4.1","platform":"x64-mingw32","checksum":"3457bf6bfdda7144097ef23d490a83980ba4572c78c58689aadaf58940a1989d"},
{"name":"pg","version":"1.4.1","platform":"x86-mingw32","checksum":"323d09138b7bbfc6ae8eb427774d3639fc0e995983e65bb729527bf8e859fc29"},
-{"name":"pg_query","version":"2.1.3","platform":"ruby","checksum":"f3dd4b4c88c638eab48e9274f0dd88c584b60f8da58e3008b873192fe1e47001"},
+{"name":"pg_query","version":"2.1.4","platform":"ruby","checksum":"48f1363f88cf9d86fa11d76d1b0f839ca3723b8bd397b7cbc4b578e1ca82d0bb"},
{"name":"plist","version":"3.6.0","platform":"ruby","checksum":"f468bcf6b72ec6d1585ed6744eb4817c1932a5bf91895ed056e69b7f12ca10f2"},
{"name":"png_quantizator","version":"0.2.1","platform":"ruby","checksum":"6023d4d064125c3a7e02929c95b7320ed6ac0d7341f9e8de0c9ea6576ef3106b"},
{"name":"po_to_json","version":"1.0.1","platform":"ruby","checksum":"6a7188aa6c42a22c9718f9b39062862ef7f3d8f6a7b4177cae058c3308b56af7"},
@@ -444,7 +443,6 @@
{"name":"rainbow","version":"3.1.1","platform":"ruby","checksum":"039491aa3a89f42efa1d6dec2fc4e62ede96eb6acd95e52f1ad581182b79bc6a"},
{"name":"rake","version":"13.0.6","platform":"ruby","checksum":"5ce4bf5037b4196c24ac62834d8db1ce175470391026bd9e557d669beeb19097"},
{"name":"randexp","version":"0.1.7","platform":"ruby","checksum":"3026510ecf6a8e8642b9b96fa44bb41af6d24058023b7df77cf280f08e14e4c8"},
-{"name":"rash_alt","version":"0.4.12","platform":"ruby","checksum":"1d4a6dd5b8fdcecc6b777c0b924dbf31c125ddd8d805e72dc9359db8324e1607"},
{"name":"rb-fsevent","version":"0.11.2","platform":"ruby","checksum":"43900b972e7301d6570f64b850a5aa67833ee7d87b458ee92805d56b7318aefe"},
{"name":"rb-inotify","version":"0.10.1","platform":"ruby","checksum":"050062d4f31d307cca52c3f6a7f4b946df8de25fc4bd373e1a5142e41034a7ca"},
{"name":"rbtrace","version":"0.4.14","platform":"ruby","checksum":"162bbf89cecabfc4f09c869b655f6f3a679c4870ebb7cbdcadf7393a81cc1769"},
@@ -457,7 +455,7 @@
{"name":"redcarpet","version":"3.5.1","platform":"ruby","checksum":"717f64cb6ec11c8d9ec9b521ed26ca2eeda68b4fe1fc3388a641176dbd47732f"},
{"name":"redis","version":"4.7.1","platform":"ruby","checksum":"ecb256d4e53ead3eca05bf394dd100e6a162c136f461fe752ddf5d35b64a2df6"},
{"name":"redis-actionpack","version":"5.3.0","platform":"ruby","checksum":"3fb1ad0a8fd9d26a289c9399bb609dcaef38bf37711e6f677a53ca728fc19140"},
-{"name":"redis-namespace","version":"1.8.1","platform":"ruby","checksum":"c81707d693e5e754c690b4e1fa68ecfa8bd1028fbf306e533b3832e44e76c54c"},
+{"name":"redis-namespace","version":"1.9.0","platform":"ruby","checksum":"0923961f38cf15b86cb57d92507e0a3b32480729eb5033249f5de8b12e0d8612"},
{"name":"redis-rack","version":"2.1.4","platform":"ruby","checksum":"0872eecb303e483c3863d6bd0d47323d230640d41c1a4ac4a2c7596ec0b1774c"},
{"name":"redis-store","version":"1.9.1","platform":"ruby","checksum":"7b4c7438d46f7b7ce8f67fc0eda3a04fc67d32d28cf606cc98a5df4d2b77071d"},
{"name":"regexp_parser","version":"2.5.0","platform":"ruby","checksum":"a076d2d35ab8d11feab5fecf8aa09ec6df68c2429810748cba079f7b021ecde5"},
@@ -489,13 +487,13 @@
{"name":"rspec-support","version":"3.10.2","platform":"ruby","checksum":"74315f89069fbaf2a710e2117340373b77ee45eceb026de87e0cad9dd5154596"},
{"name":"rspec_junit_formatter","version":"0.4.1","platform":"ruby","checksum":"3788f9b3fabc6284b93493cf4b3a80cba2b59b3a774b95f39dd7886d5faed6ab"},
{"name":"rspec_profiling","version":"0.0.6","platform":"ruby","checksum":"7a45697f79dcec9a174a0e26703465f6bd52ee78e8d798741240bfcef38f6e6e"},
-{"name":"rubocop","version":"0.93.1","platform":"ruby","checksum":"73b44fbbe872edbd3f14487175b6369a0f48e952c155f305896ffa56c48b195e"},
+{"name":"rubocop","version":"1.36.0","platform":"ruby","checksum":"368e47dcab8417419949bbadb11ec41fd94e6b785f8bff4f9cc56a1ddf60ffac"},
{"name":"rubocop-ast","version":"1.21.0","platform":"ruby","checksum":"8f5d98611343498602de2d41bc583aca71599daad16daeadaeeee60f134c9568"},
{"name":"rubocop-gitlab-security","version":"0.1.1","platform":"ruby","checksum":"96f6ed727847a5876ddfc89ee0399438a1aef7934db773c7efce907e2720006c"},
{"name":"rubocop-graphql","version":"0.14.6","platform":"ruby","checksum":"b40f2cbac9990ece44eb85eec5c5ae04fca1e197c07c790ac1ca60600b55bdad"},
-{"name":"rubocop-performance","version":"1.9.2","platform":"ruby","checksum":"3373ad82b70189fa16b593b6237eb06186da669d468b7d6483bca64c0a844a05"},
-{"name":"rubocop-rails","version":"2.9.1","platform":"ruby","checksum":"2d8d113c3ae074c78c89cb706b4a08116d730bf92dbef148798498171435c540"},
-{"name":"rubocop-rspec","version":"1.44.1","platform":"ruby","checksum":"7b2238e7d6cf17a925a90992914f3cd8ecd68b65b31710d60a3f7f647f8a8b2a"},
+{"name":"rubocop-performance","version":"1.14.3","platform":"ruby","checksum":"ee45ae3e40388ff809d9c5e2ef6ef9d59dc86c59c97110f96d5540267f860751"},
+{"name":"rubocop-rails","version":"2.15.2","platform":"ruby","checksum":"1891ab46a6eaf36b841ad27c9c8a22e77a2c3ae85bc334111d3f8075e417643c"},
+{"name":"rubocop-rspec","version":"2.12.1","platform":"ruby","checksum":"9278d22d4525261caf30d591eef3d47910a125e74f75f41ffa470acd208423f9"},
{"name":"ruby-fogbugz","version":"0.2.1","platform":"ruby","checksum":"15b2e7fe7e95b021a94ee6e9d8bb32fdad6ae44e820c2ce0dc312fe6e77d40ca"},
{"name":"ruby-magic","version":"0.5.4","platform":"ruby","checksum":"2c17b185130d10a83791f63a40baa358c4b138af37da3f4dab53690121c421d5"},
{"name":"ruby-prof","version":"1.3.1","platform":"ruby","checksum":"e735d20c92954e1fa2a4475539c99dfc8d0166b4cc6915ca309e8ee2dd19323c"},
@@ -544,6 +542,7 @@
{"name":"simplecov_json_formatter","version":"0.1.4","platform":"ruby","checksum":"529418fbe8de1713ac2b2d612aa3daa56d316975d307244399fa4838c601b428"},
{"name":"sixarm_ruby_unaccent","version":"1.2.0","platform":"ruby","checksum":"0043a6077bdf2c4b03040152676a07f8bf77144f9b007b1960ee5c94d13a4384"},
{"name":"slack-messenger","version":"2.3.4","platform":"ruby","checksum":"49c611d2be5b0f9c250a3a957b9cc09b9c07b81dacb9843642d87b6fa35609c1"},
+{"name":"snaky_hash","version":"2.0.0","platform":"ruby","checksum":"fe8b2e39e8ff69320f7812af73ea06401579e29ff1734a7009567391600687de"},
{"name":"snowplow-tracker","version":"0.6.1","platform":"ruby","checksum":"9cec52fd060619f4974b3dc1f7d9a2776c5e31b668a6ead53145b9780e312314"},
{"name":"solargraph","version":"0.46.0","platform":"ruby","checksum":"1da9fd8c364501f18b0454e54506e7098bc38dae719219713fe5f246dfc91465"},
{"name":"sorted_set","version":"1.0.3","platform":"java","checksum":"996283f2e5c6e838825bcdcee31d6306515ae5f24bcb0ee4ce09dfff32919b8c"},
@@ -614,7 +613,7 @@
{"name":"validate_email","version":"0.1.6","platform":"ruby","checksum":"9dfe9016d527b17a8d3a6e95e4dc50a125400eef899d13d4cc2a254393f82ee4"},
{"name":"validate_url","version":"1.0.15","platform":"ruby","checksum":"72fe164c0713d63a9970bd6700bea948babbfbdcec392f2342b6704042f57451"},
{"name":"validates_hostname","version":"1.0.11","platform":"ruby","checksum":"d506bae0342ec14c920eb319e057fc1886c321a59b85b4b6e966ee4b88fab8c3"},
-{"name":"version_gem","version":"1.0.0","platform":"ruby","checksum":"929c93a4d46482bb3b0359980c7a5fb1b5a833548f1202a480b08a6f0a5f8f2f"},
+{"name":"version_gem","version":"1.1.0","platform":"ruby","checksum":"6b009518020db57f51ec7b410213fae2bf692baea9f1b51770db97fbc93d9a80"},
{"name":"version_sorter","version":"2.2.4","platform":"ruby","checksum":"7ad071609edfaa3cf28c42d83b1a03096e43512244ae5a9e2fce1404f7e06d41"},
{"name":"view_component","version":"2.71.0","platform":"ruby","checksum":"c1880647800d9cfb03ff4ba92313db624a4a4b3d5753e137effe86e5f2b3662b"},
{"name":"vmstat","version":"2.3.0","platform":"ruby","checksum":"ab5446a3e3bd0a9cdb9d9ac69a0bbd119c4f161d945a0846a519dd7018af656d"},
diff --git a/app/models/incident_management/timeline_event.rb b/app/models/incident_management/timeline_event.rb
index dd0d3c6585d..de193308558 100644
--- a/app/models/incident_management/timeline_event.rb
+++ b/app/models/incident_management/timeline_event.rb
@@ -18,7 +18,8 @@ module IncidentManagement
validates :project, :incident, :occurred_at, presence: true
validates :action, presence: true, length: { maximum: 128 }
- validates :note, :note_html, presence: true, length: { maximum: 10_000 }
+ validates :note, presence: true, length: { maximum: 10_000 }
+ validates :note_html, length: { maximum: 10_000 }
scope :order_occurred_at_asc_id_asc, -> { reorder(occurred_at: :asc, id: :asc) }
end
diff --git a/app/models/ml/candidate_param.rb b/app/models/ml/candidate_param.rb
index cbdddcc8a1a..a259e059379 100644
--- a/app/models/ml/candidate_param.rb
+++ b/app/models/ml/candidate_param.rb
@@ -3,6 +3,7 @@
module Ml
class CandidateParam < ApplicationRecord
validates :candidate, presence: true
+ validates :name, uniqueness: { scope: :candidate }
validates :name, :value, length: { maximum: 250 }, presence: true
belongs_to :candidate, class_name: 'Ml::Candidate'
diff --git a/config/feature_flags/development/escape_gitaly_refs.yml b/config/feature_flags/development/escape_gitaly_refs.yml
deleted file mode 100644
index b42cc4c07e5..00000000000
--- a/config/feature_flags/development/escape_gitaly_refs.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: escape_gitaly_refs
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/91058
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/366437
-milestone: '15.2'
-type: development
-group: group::source code
-default_enabled: true
diff --git a/config/locales/en.yml b/config/locales/en.yml
index 56df8f93113..3c33cdac3f1 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -5,6 +5,8 @@ en:
hello: "Hello world"
activerecord:
attributes:
+ incident_management/timeline_event:
+ note: 'Timeline text'
issue_link:
source: Source issue
target: Target issue
diff --git a/config/metrics/counts_all/20210216180413_all_searches.yml b/config/metrics/counts_all/20210216180413_all_searches.yml
index 2f45e0c6e20..abd2e31b8d8 100644
--- a/config/metrics/counts_all/20210216180413_all_searches.yml
+++ b/config/metrics/counts_all/20210216180413_all_searches.yml
@@ -11,6 +11,11 @@ value_type: number
status: active
time_frame: all
data_source: redis
+instrumentation_class: RedisMetric
+options:
+ prefix: null
+ event: all_searches_count
+ include_usage_prefix: false
distribution:
- ce
- ee
diff --git a/config/metrics/counts_all/20210216180414_navbar_searches.yml b/config/metrics/counts_all/20210216180414_navbar_searches.yml
index b2af79bb43c..9ba086ed271 100644
--- a/config/metrics/counts_all/20210216180414_navbar_searches.yml
+++ b/config/metrics/counts_all/20210216180414_navbar_searches.yml
@@ -11,6 +11,11 @@ value_type: number
status: active
time_frame: all
data_source: redis
+instrumentation_class: RedisMetric
+options:
+ prefix: null
+ event: navbar_searches_count
+ include_usage_prefix: false
distribution:
- ce
- ee
diff --git a/config/metrics/counts_all/20210505015532_kubernetes_agent_k8s_api_proxy_request.yml b/config/metrics/counts_all/20210505015532_kubernetes_agent_k8s_api_proxy_request.yml
index 185e8a199b6..fcb2be99fab 100644
--- a/config/metrics/counts_all/20210505015532_kubernetes_agent_k8s_api_proxy_request.yml
+++ b/config/metrics/counts_all/20210505015532_kubernetes_agent_k8s_api_proxy_request.yml
@@ -12,6 +12,10 @@ milestone: '13.12'
introduced_by_url:
time_frame: all
data_source: redis
+instrumentation_class: RedisMetric
+options:
+ prefix: kubernetes_agent
+ event: k8s_api_proxy_request
distribution:
- ce
- ee
diff --git a/db/migrate/20220914080716_add_index_to_candidate_id_and_name_on_ml_candidate_params.rb b/db/migrate/20220914080716_add_index_to_candidate_id_and_name_on_ml_candidate_params.rb
new file mode 100644
index 00000000000..caf30961ace
--- /dev/null
+++ b/db/migrate/20220914080716_add_index_to_candidate_id_and_name_on_ml_candidate_params.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+class AddIndexToCandidateIdAndNameOnMlCandidateParams < Gitlab::Database::Migration[2.0]
+ disable_ddl_transaction!
+
+ INDEX_NAME = 'index_ml_candidate_params_on_candidate_id_on_name'
+
+ def up
+ add_concurrent_index :ml_candidate_params, [:candidate_id, :name], unique: true, name: INDEX_NAME
+ end
+
+ def down
+ remove_concurrent_index_by_name(:ml_candidate_params, INDEX_NAME)
+ end
+end
diff --git a/db/schema_migrations/20220914080716 b/db/schema_migrations/20220914080716
new file mode 100644
index 00000000000..7c807e61c26
--- /dev/null
+++ b/db/schema_migrations/20220914080716
@@ -0,0 +1 @@
+ffa421a7ffc279cb2751ed9e74c212ab60a3b6f7722d15023d39f7ad97ff1e6c \ No newline at end of file
diff --git a/db/structure.sql b/db/structure.sql
index c26af7af0da..fb1f550625e 100644
--- a/db/structure.sql
+++ b/db/structure.sql
@@ -29410,6 +29410,8 @@ CREATE INDEX index_ml_candidate_metrics_on_candidate_id ON ml_candidate_metrics
CREATE INDEX index_ml_candidate_params_on_candidate_id ON ml_candidate_params USING btree (candidate_id);
+CREATE UNIQUE INDEX index_ml_candidate_params_on_candidate_id_on_name ON ml_candidate_params USING btree (candidate_id, name);
+
CREATE UNIQUE INDEX index_ml_candidates_on_experiment_id_and_iid ON ml_candidates USING btree (experiment_id, iid);
CREATE INDEX index_ml_candidates_on_user_id ON ml_candidates USING btree (user_id);
diff --git a/doc/administration/geo/secondary_proxy/index.md b/doc/administration/geo/secondary_proxy/index.md
index b088d8a8af2..2786982bb51 100644
--- a/doc/administration/geo/secondary_proxy/index.md
+++ b/doc/administration/geo/secondary_proxy/index.md
@@ -147,6 +147,13 @@ for details.
- [Viewing projects and designs data from a primary site is not possible when using a unified URL](../index.md#view-replication-data-on-the-primary-site).
+- When secondary proxying is used together with separate URLs, registering [GitLab runners](https://docs.gitlab.com/runner/) to clone from
+secondary sites is not supported. The runner registration will succeed, but the clone URL will default to the primary site. The runner
+[clone URL](https://docs.gitlab.com/runner/configuration/advanced-configuration.html#the-runners-section) is configured per GitLab deployment
+and cannot be configured per Geo site. Therefore, all runners will clone from the primary site (or configured clone URL) irrespective of
+which Geo site they register on. For information about GitLab CI using a specific Geo secondary to clone from, see issue
+[3294](https://gitlab.com/gitlab-org/gitlab/-/issues/3294#note_1009488466).
+
## Behavior of secondary sites when the primary Geo site is down
Considering that web traffic is proxied to the primary, the behavior of the secondary sites differs when the primary
diff --git a/doc/development/gemfile.md b/doc/development/gemfile.md
index dd687763356..7d3531afb49 100644
--- a/doc/development/gemfile.md
+++ b/doc/development/gemfile.md
@@ -6,9 +6,43 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Gemfile guidelines
-When adding a new entry to `Gemfile` or upgrading an existing dependency pay
+When adding a new entry to `Gemfile`, or upgrading an existing dependency pay
attention to the following rules.
+## Bundler checksum verification
+
+In [GitLab 15.5 and later](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/98508), gem
+checksums are checked before installation. This verification is still
+experimental so it is only active for CI.
+
+If the downloaded gem's checksum does not match the checksum record in
+`Gemfile.checksum`, you will see an error saying that Bundler cannot continue
+installing a gem because there is a potential security issue.
+
+You will see this error as well if you updated, or added a new gem without
+updating `Gemfile.checksum`. To fix this error,
+[update the Gemfile.checksum](#updating-the-checksum-file).
+
+You can opt-in to this verification locally by setting the
+`BUNDLER_CHECKSUM_VERIFICATION_OPT_IN` environment variable:
+
+```shell
+export BUNDLER_CHECKSUM_VERIFICATION_OPT_IN=1
+bundle install
+```
+
+### Updating the checksum file
+
+This needs to be done for any new, or updated gems.
+
+1. When updating `Gemfile.lock`, make sure to also update `Gemfile.checksum` with:
+
+ ```shell
+ bundle exec bundler-checksum init
+ ```
+
+1. Check and commit the changes for `Gemfile.checksum`.
+
## No gems fetched from Git repositories
We do not allow gems that are fetched from Git repositories. All gems have
diff --git a/lib/api/entities/ml/mlflow/run.rb b/lib/api/entities/ml/mlflow/run.rb
index 937d222ea37..a8e1cfe08dd 100644
--- a/lib/api/entities/ml/mlflow/run.rb
+++ b/lib/api/entities/ml/mlflow/run.rb
@@ -9,6 +9,7 @@ module API
expose(:info) { |candidate| RunInfo.represent(candidate) }
expose :data do
expose :metrics, using: Metric
+ expose :params, using: RunParam
end
end
end
diff --git a/lib/api/entities/ml/mlflow/run_param.rb b/lib/api/entities/ml/mlflow/run_param.rb
new file mode 100644
index 00000000000..75fee738f8b
--- /dev/null
+++ b/lib/api/entities/ml/mlflow/run_param.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+module API
+ module Entities
+ module Ml
+ module Mlflow
+ class RunParam < Grape::Entity
+ expose :name, as: :key
+ expose :value
+ end
+ end
+ end
+ end
+end
diff --git a/lib/api/ml/mlflow.rb b/lib/api/ml/mlflow.rb
index a5a22927eb0..d1f8daaa93d 100644
--- a/lib/api/ml/mlflow.rb
+++ b/lib/api/ml/mlflow.rb
@@ -160,7 +160,7 @@ module API
@candidate.status = params[:status].downcase if params[:status]
@candidate.end_time = params[:end_time] if params[:end_time]
- @candidate.save if @candidate.valid?
+ @candidate.save
present @candidate, with: Entities::Ml::Mlflow::UpdateRun
end
@@ -188,6 +188,74 @@ module API
{}
end
+
+ desc 'Logs a parameter to a run.' do
+ summary 'Log a param used for a run. A param is a key-value pair (string key, string value). '\
+ 'Examples include hyperparameters used for ML model training and constant dates and values '\
+ 'used in an ETL pipeline. A param can be logged only once for a run, duplicate will be .'\
+ 'ignored'
+
+ detail 'https://www.mlflow.org/docs/1.28.0/rest-api.html#log-param'
+ end
+ params do
+ requires :run_id, type: String, desc: 'UUID of the run.'
+ requires :key, type: String, desc: 'Name for the parameter.'
+ requires :value, type: String, desc: 'Value for the parameter.'
+ end
+ post 'log-parameter', urgency: :low do
+ ::Ml::CandidateParam.create(candidate: @candidate, name: params[:key], value: params[:value])
+
+ {}
+ end
+
+ desc 'Logs multiple parameters and metrics.' do
+ summary 'Log a batch of metrics and params for a run. Validation errors will block the entire batch, '\
+ 'duplicate errors will be ignored.'
+
+ detail 'https://www.mlflow.org/docs/1.28.0/rest-api.html#log-param'
+ end
+ params do
+ requires :run_id, type: String, desc: 'UUID of the run.'
+ optional :metrics, type: Array, default: [] do
+ requires :key, type: String, desc: 'Name for the metric.'
+ requires :value, type: Float, desc: 'Value of the metric.'
+ requires :timestamp, type: Integer, desc: 'Unix timestamp in milliseconds when metric was recorded'
+ optional :step, type: Integer, desc: 'Step at which the metric was recorded'
+ end
+ optional :params, type: Array, default: [] do
+ requires :key, type: String, desc: 'Name for the metric.'
+ requires :value, type: String, desc: 'Value of the metric.'
+ end
+ end
+ post 'log-batch', urgency: :low do
+ times = { created_at: Time.zone.now, updated_at: Time.zone.now }
+
+ metrics = params[:metrics].map do |metric|
+ {
+ candidate_id: @candidate.id,
+ name: metric[:key],
+ value: metric[:value],
+ tracked_at: metric[:timestamp],
+ step: metric[:step],
+ **times
+ }
+ end
+
+ ::Ml::CandidateMetric.insert_all(metrics, returning: false) unless metrics.empty?
+
+ parameters = params[:params].map do |p|
+ {
+ candidate_id: @candidate.id,
+ name: p[:key],
+ value: p[:value],
+ **times
+ }
+ end
+
+ ::Ml::CandidateParam.insert_all(parameters, returning: false) unless parameters.empty?
+
+ {}
+ end
end
end
end
diff --git a/lib/gitlab/encoding_helper.rb b/lib/gitlab/encoding_helper.rb
index 34c674c3003..b1fd35184ac 100644
--- a/lib/gitlab/encoding_helper.rb
+++ b/lib/gitlab/encoding_helper.rb
@@ -73,8 +73,6 @@ module Gitlab
# This method escapes unsupported UTF-8 characters instead of deleting them
def encode_utf8_with_escaping!(message)
- return encode!(message) if Feature.disabled?(:escape_gitaly_refs)
-
message = force_encode_utf8(message)
return message if message.valid_encoding?
diff --git a/lib/gitlab/usage/metrics/instrumentations/redis_metric.rb b/lib/gitlab/usage/metrics/instrumentations/redis_metric.rb
index 26d963e2407..57a417b4cf3 100644
--- a/lib/gitlab/usage/metrics/instrumentations/redis_metric.rb
+++ b/lib/gitlab/usage/metrics/instrumentations/redis_metric.rb
@@ -17,12 +17,13 @@ module Gitlab
include Gitlab::UsageDataCounters::RedisCounter
USAGE_PREFIX = "USAGE_"
+ OPTIONS_PREFIX_KEY = :prefix
def initialize(time_frame:, options: {})
super
raise ArgumentError, "'event' option is required" unless metric_event.present?
- raise ArgumentError, "'prefix' option is required" unless prefix.present?
+ raise ArgumentError, "'prefix' option is required" unless options.has_key?(OPTIONS_PREFIX_KEY)
end
def metric_event
@@ -30,7 +31,7 @@ module Gitlab
end
def prefix
- options[:prefix]
+ options[OPTIONS_PREFIX_KEY]
end
def include_usage_prefix?
@@ -50,9 +51,10 @@ module Gitlab
private
def redis_key
- key = "#{prefix}_#{metric_event}".upcase
+ key = metric_event.dup
+ key.prepend("#{prefix}_") if prefix
key.prepend(USAGE_PREFIX) if include_usage_prefix?
- key
+ key.upcase
end
end
end
diff --git a/lib/gitlab/usage_data_counters.rb b/lib/gitlab/usage_data_counters.rb
index 65f72e229a7..8198628b1fa 100644
--- a/lib/gitlab/usage_data_counters.rb
+++ b/lib/gitlab/usage_data_counters.rb
@@ -4,8 +4,6 @@ module Gitlab
module UsageDataCounters
COUNTERS = [
NoteCounter,
- SearchCounter,
- KubernetesAgentCounter,
MergeRequestWidgetExtensionCounter
].freeze
@@ -14,6 +12,8 @@ module Gitlab
MergeRequestCounter,
DesignsCounter,
DiffsCounter,
+ KubernetesAgentCounter,
+ SearchCounter,
ServiceUsageDataCounter,
WebIdeCounter,
WikiPageCounter,
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 248dced98d0..9698d43f6a5 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -40327,9 +40327,6 @@ msgstr ""
msgid "There is no data available. Please change your selection."
msgstr ""
-msgid "There is no seat left to activate the member"
-msgstr ""
-
msgid "There is no table data available."
msgstr ""
diff --git a/spec/factories/ml/candidate_params.rb b/spec/factories/ml/candidate_params.rb
new file mode 100644
index 00000000000..73cb0c54089
--- /dev/null
+++ b/spec/factories/ml/candidate_params.rb
@@ -0,0 +1,10 @@
+# frozen_string_literal: true
+
+FactoryBot.define do
+ factory :ml_candidate_params, class: '::Ml::CandidateParam' do
+ association :candidate, factory: :ml_candidates
+
+ sequence(:name) { |n| "metric#{n}" }
+ sequence(:value) { |n| "value#{n}" }
+ end
+end
diff --git a/spec/factories/ml/candidates.rb b/spec/factories/ml/candidates.rb
index c8649f80ff2..4fbcdc46103 100644
--- a/spec/factories/ml/candidates.rb
+++ b/spec/factories/ml/candidates.rb
@@ -4,9 +4,10 @@ FactoryBot.define do
association :experiment, factory: :ml_experiments
association :user
- trait :with_metrics do
+ trait :with_metrics_and_params do
after(:create) do |candidate|
candidate.metrics = FactoryBot.create_list(:ml_candidate_metrics, 2, candidate: candidate )
+ candidate.params = FactoryBot.create_list(:ml_candidate_params, 2, candidate: candidate )
end
end
end
diff --git a/spec/graphql/mutations/incident_management/timeline_event/create_spec.rb b/spec/graphql/mutations/incident_management/timeline_event/create_spec.rb
index ea74e427dd6..9254d84b29c 100644
--- a/spec/graphql/mutations/incident_management/timeline_event/create_spec.rb
+++ b/spec/graphql/mutations/incident_management/timeline_event/create_spec.rb
@@ -37,7 +37,7 @@ RSpec.describe Mutations::IncidentManagement::TimelineEvent::Create do
let(:args) { {} }
it_behaves_like 'responding with an incident timeline errors',
- errors: ["Occurred at can't be blank, Note can't be blank, and Note html can't be blank"]
+ errors: ["Occurred at can't be blank and Timeline text can't be blank"]
end
end
diff --git a/spec/graphql/mutations/incident_management/timeline_event/update_spec.rb b/spec/graphql/mutations/incident_management/timeline_event/update_spec.rb
index 102d33378c6..7081fb7117e 100644
--- a/spec/graphql/mutations/incident_management/timeline_event/update_spec.rb
+++ b/spec/graphql/mutations/incident_management/timeline_event/update_spec.rb
@@ -65,7 +65,7 @@ RSpec.describe Mutations::IncidentManagement::TimelineEvent::Update do
end
it 'responds with error' do
- expect(resolve).to eq(timeline_event: nil, errors: ["Note can't be blank"])
+ expect(resolve).to eq(timeline_event: nil, errors: ["Timeline text can't be blank"])
end
end
diff --git a/spec/lib/api/entities/ml/mlflow/run_spec.rb b/spec/lib/api/entities/ml/mlflow/run_spec.rb
index 5511861991e..b8d38093681 100644
--- a/spec/lib/api/entities/ml/mlflow/run_spec.rb
+++ b/spec/lib/api/entities/ml/mlflow/run_spec.rb
@@ -3,7 +3,7 @@
require 'spec_helper'
RSpec.describe API::Entities::Ml::Mlflow::Run do
- let_it_be(:candidate) { create(:ml_candidates, :with_metrics) }
+ let_it_be(:candidate) { create(:ml_candidates, :with_metrics_and_params) }
subject { described_class.new(candidate).as_json }
@@ -29,6 +29,18 @@ RSpec.describe API::Entities::Ml::Mlflow::Run do
expect(presented_metric[:step]).to eq(metric.step)
end
+ it 'presents the params' do
+ expect(subject.dig(:run, :data, :params).size).to eq(candidate.params.size)
+ end
+
+ it 'presents params correctly' do
+ presented_param = subject.dig(:run, :data, :params)[0]
+ param = candidate.params[0]
+
+ expect(presented_param[:key]).to eq(param.name)
+ expect(presented_param[:value]).to eq(param.value)
+ end
+
context 'when candidate has no metrics' do
before do
allow(candidate).to receive(:metrics).and_return([])
@@ -38,4 +50,14 @@ RSpec.describe API::Entities::Ml::Mlflow::Run do
expect(subject.dig(:run, :data, :metrics)).to be_empty
end
end
+
+ context 'when candidate has no params' do
+ before do
+ allow(candidate).to receive(:params).and_return([])
+ end
+
+ it 'data is empty' do
+ expect(subject.dig(:run, :data, :params)).to be_empty
+ end
+ end
end
diff --git a/spec/lib/gitlab/encoding_helper_spec.rb b/spec/lib/gitlab/encoding_helper_spec.rb
index 690396d4dbc..c62e3071fc1 100644
--- a/spec/lib/gitlab/encoding_helper_spec.rb
+++ b/spec/lib/gitlab/encoding_helper_spec.rb
@@ -114,18 +114,6 @@ RSpec.describe Gitlab::EncodingHelper do
expect(ext_class.encode_utf8_with_escaping!(input)).to eq(expected)
end
end
-
- context 'when feature flag is disabled' do
- before do
- stub_feature_flags(escape_gitaly_refs: false)
- end
-
- it 'uses #encode! method' do
- expect(ext_class).to receive(:encode!).with('String')
-
- ext_class.encode_utf8_with_escaping!('String')
- end
- end
end
describe '#encode_utf8' do
diff --git a/spec/lib/gitlab/usage/metrics/instrumentations/redis_metric_spec.rb b/spec/lib/gitlab/usage/metrics/instrumentations/redis_metric_spec.rb
index 80ae5c6fd21..8f9c3573897 100644
--- a/spec/lib/gitlab/usage/metrics/instrumentations/redis_metric_spec.rb
+++ b/spec/lib/gitlab/usage/metrics/instrumentations/redis_metric_spec.rb
@@ -58,4 +58,18 @@ RSpec.describe Gitlab::Usage::Metrics::Instrumentations::RedisMetric, :clean_git
options: { event: 'merge_requests_count', prefix: 'web_ide', include_usage_prefix: false }
}
end
+
+ context "with prefix disabled" do
+ let(:expected_value) { 3 }
+
+ before do
+ 3.times do
+ Gitlab::UsageDataCounters::SearchCounter.count(:all_searches)
+ end
+ end
+
+ it_behaves_like 'a correct instrumented metric value', {
+ options: { event: 'all_searches_count', prefix: nil, include_usage_prefix: false }
+ }
+ end
end
diff --git a/spec/lib/gitlab/usage_data_spec.rb b/spec/lib/gitlab/usage_data_spec.rb
index 46ed4b57d3a..745aa20a6a2 100644
--- a/spec/lib/gitlab/usage_data_spec.rb
+++ b/spec/lib/gitlab/usage_data_spec.rb
@@ -758,13 +758,6 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
end
end
- describe '.usage_counters' do
- subject { described_class.usage_counters }
-
- it { is_expected.to include(:kubernetes_agent_gitops_sync) }
- it { is_expected.to include(:kubernetes_agent_k8s_api_proxy_request) }
- end
-
describe '.usage_data_counters' do
subject { described_class.usage_data_counters }
diff --git a/spec/models/incident_management/timeline_event_spec.rb b/spec/models/incident_management/timeline_event_spec.rb
index fea391acda3..c68bcd4a9ed 100644
--- a/spec/models/incident_management/timeline_event_spec.rb
+++ b/spec/models/incident_management/timeline_event_spec.rb
@@ -22,7 +22,6 @@ RSpec.describe IncidentManagement::TimelineEvent do
it { is_expected.to validate_presence_of(:incident) }
it { is_expected.to validate_presence_of(:note) }
it { is_expected.to validate_length_of(:note).is_at_most(10_000) }
- it { is_expected.to validate_presence_of(:note_html) }
it { is_expected.to validate_length_of(:note_html).is_at_most(10_000) }
it { is_expected.to validate_presence_of(:occurred_at) }
it { is_expected.to validate_presence_of(:action) }
diff --git a/spec/models/ml/candidate_spec.rb b/spec/models/ml/candidate_spec.rb
index 7a2dd4b1892..3bf1e80a152 100644
--- a/spec/models/ml/candidate_spec.rb
+++ b/spec/models/ml/candidate_spec.rb
@@ -3,7 +3,7 @@
require 'spec_helper'
RSpec.describe Ml::Candidate, factory_default: :keep do
- let_it_be(:candidate) { create_default(:ml_candidates, :with_metrics) }
+ let_it_be(:candidate) { create_default(:ml_candidates, :with_metrics_and_params) }
describe 'associations' do
it { is_expected.to belong_to(:experiment) }
diff --git a/spec/requests/api/ml/mlflow_spec.rb b/spec/requests/api/ml/mlflow_spec.rb
index 1377bb365f7..859fb9de936 100644
--- a/spec/requests/api/ml/mlflow_spec.rb
+++ b/spec/requests/api/ml/mlflow_spec.rb
@@ -16,7 +16,8 @@ RSpec.describe API::Ml::Mlflow do
end
let_it_be(:candidate) do
- create(:ml_candidates, :with_metrics, user: experiment.user, start_time: 1234, experiment: experiment)
+ create(:ml_candidates,
+ :with_metrics_and_params, user: experiment.user, start_time: 1234, experiment: experiment)
end
let_it_be(:tokens) do
@@ -142,7 +143,7 @@ RSpec.describe API::Ml::Mlflow do
let(:experiment_iid) { experiment.iid.to_s }
let(:route) { "/projects/#{project_id}/ml/mflow/api/2.0/mlflow/experiments/get?experiment_id=#{experiment_iid}" }
- it 'returns the experiment' do
+ it 'returns the experiment', :aggregate_failures do
expect(response).to have_gitlab_http_status(:ok)
expect(response).to match_response_schema('ml/get_experiment')
expect(json_response).to include({
@@ -181,7 +182,7 @@ RSpec.describe API::Ml::Mlflow do
"/projects/#{project_id}/ml/mflow/api/2.0/mlflow/experiments/get-by-name?experiment_name=#{experiment_name}"
end
- it 'returns the experiment' do
+ it 'returns the experiment', :aggregate_failures do
expect(response).to have_gitlab_http_status(:ok)
expect(response).to match_response_schema('ml/get_experiment')
expect(json_response).to include({
@@ -220,7 +221,7 @@ RSpec.describe API::Ml::Mlflow do
let(:params) { { name: 'new_experiment' } }
let(:request) { post api(route), params: params, headers: headers }
- it 'creates the experiment' do
+ it 'creates the experiment', :aggregate_failures do
expect(response).to have_gitlab_http_status(:created)
expect(json_response).to include('experiment_id' )
end
@@ -259,7 +260,7 @@ RSpec.describe API::Ml::Mlflow do
let(:params) { { experiment_id: experiment.iid.to_s, start_time: Time.now.to_i } }
let(:request) { post api(route), params: params, headers: headers }
- it 'creates the run' do
+ it 'creates the run', :aggregate_failures do
expected_properties = {
'experiment_id' => params[:experiment_id],
'user_id' => current_user.id.to_s,
@@ -272,7 +273,7 @@ RSpec.describe API::Ml::Mlflow do
expect(response).to have_gitlab_http_status(:created)
expect(response).to match_response_schema('ml/run')
expect(json_response['run']).to include('info' => hash_including(**expected_properties),
- 'data' => { 'metrics' => [] })
+ 'data' => { 'metrics' => [], 'params' => [] })
end
describe 'Error States' do
@@ -303,7 +304,7 @@ RSpec.describe API::Ml::Mlflow do
let(:route) { "/projects/#{project_id}/ml/mflow/api/2.0/mlflow/runs/get" }
let(:default_params) { { 'run_id' => candidate.iid } }
- it 'gets the run' do
+ it 'gets the run', :aggregate_failures do
expected_properties = {
'experiment_id' => candidate.experiment.iid.to_s,
'user_id' => candidate.user.id.to_s,
@@ -321,6 +322,10 @@ RSpec.describe API::Ml::Mlflow do
'metrics' => [
hash_including('key' => candidate.metrics[0].name),
hash_including('key' => candidate.metrics[1].name)
+ ],
+ 'params' => [
+ { 'key' => candidate.params[0].name, 'value' => candidate.params[0].value },
+ { 'key' => candidate.params[1].name, 'value' => candidate.params[1].value }
]
})
end
@@ -337,7 +342,7 @@ RSpec.describe API::Ml::Mlflow do
let(:request) { post api(route), params: params, headers: headers }
let(:route) { "/projects/#{project_id}/ml/mflow/api/2.0/mlflow/runs/update" }
- it 'updates the run' do
+ it 'updates the run', :aggregate_failures do
expected_properties = {
'experiment_id' => candidate.experiment.iid.to_s,
'user_id' => candidate.user.id.to_s,
@@ -377,7 +382,7 @@ RSpec.describe API::Ml::Mlflow do
let(:default_params) { { run_id: candidate.iid.to_s, key: 'some_key', value: 10.0, timestamp: Time.now.to_i } }
let(:request) { post api(route), params: params, headers: headers }
- it 'logs the metric' do
+ it 'logs the metric', :aggregate_failures do
candidate.metrics.reload
expect(response).to have_gitlab_http_status(:success)
@@ -392,5 +397,96 @@ RSpec.describe API::Ml::Mlflow do
it_behaves_like 'Bad Request on missing required', [:key, :value, :timestamp]
end
end
+
+ describe 'POST /projects/:id/ml/mflow/api/2.0/mlflow/runs/log-parameter' do
+ let(:route) { "/projects/#{project_id}/ml/mflow/api/2.0/mlflow/runs/log-parameter" }
+ let(:default_params) { { run_id: candidate.iid.to_s, key: 'some_key', value: 'value' } }
+ let(:request) { post api(route), params: params, headers: headers }
+
+ it 'logs the parameter', :aggregate_failures do
+ candidate.params.reload
+
+ expect(response).to have_gitlab_http_status(:success)
+ expect(json_response).to be_empty
+ expect(candidate.params.length).to eq(3)
+ end
+
+ context 'when parameter was already logged' do
+ let(:params) { default_params.tap { |p| p[:key] = candidate.params[0].name } }
+
+ it 'does not log', :aggregate_failures do
+ candidate.params.reload
+
+ expect(response).to have_gitlab_http_status(:success)
+ expect(json_response).to be_empty
+ expect(candidate.params.length).to eq(2)
+ end
+ end
+
+ describe 'Error Cases' do
+ it_behaves_like 'shared error cases'
+ it_behaves_like 'Requires api scope'
+ it_behaves_like 'run_id param error cases'
+ it_behaves_like 'Bad Request on missing required', [:key, :value]
+ end
+ end
+
+ describe 'POST /projects/:id/ml/mflow/api/2.0/mlflow/runs/log-batch' do
+ let(:candidate2) do
+ create(:ml_candidates, user: experiment.user, start_time: 1234, experiment: experiment)
+ end
+
+ let(:route) { "/projects/#{project_id}/ml/mflow/api/2.0/mlflow/runs/log-batch" }
+ let(:default_params) do
+ {
+ run_id: candidate2.iid.to_s,
+ metrics: [
+ { key: 'mae', value: 2.5, timestamp: 1552550804 },
+ { key: 'rmse', value: 2.7, timestamp: 1552550804 }
+ ],
+ params: [{ key: 'model_class', value: 'LogisticRegression' }]
+ }
+ end
+
+ let(:request) { post api(route), params: params, headers: headers }
+
+ it 'logs parameters and metrics', :aggregate_failures do
+ expect(response).to have_gitlab_http_status(:success)
+ expect(json_response).to be_empty
+ expect(candidate2.params.size).to eq(1)
+ expect(candidate2.metrics.size).to eq(2)
+ end
+
+ context 'when parameter was already logged' do
+ let(:params) do
+ default_params.tap { |p| p[:params] = [{ key: 'hello', value: 'a' }, { key: 'hello', value: 'b' }] }
+ end
+
+ it 'does not log', :aggregate_failures do
+ candidate.params.reload
+
+ expect(response).to have_gitlab_http_status(:success)
+ expect(candidate2.params.size).to eq(1)
+ end
+ end
+
+ describe 'Error Cases' do
+ context 'when required metric key is missing' do
+ let(:params) { default_params.tap { |p| p[:metrics] = [p[:metrics][0].delete(:key)] } }
+
+ it_behaves_like 'Bad Request'
+ end
+
+ context 'when required param key is missing' do
+ let(:params) { default_params.tap { |p| p[:params] = [p[:params][0].delete(:key)] } }
+
+ it_behaves_like 'Bad Request'
+ end
+
+ it_behaves_like 'shared error cases'
+ it_behaves_like 'Requires api scope'
+ it_behaves_like 'run_id param error cases'
+ end
+ end
end
end
diff --git a/spec/services/incident_management/timeline_events/create_service_spec.rb b/spec/services/incident_management/timeline_events/create_service_spec.rb
index b999403e168..0e6864387d6 100644
--- a/spec/services/incident_management/timeline_events/create_service_spec.rb
+++ b/spec/services/incident_management/timeline_events/create_service_spec.rb
@@ -71,7 +71,7 @@ RSpec.describe IncidentManagement::TimelineEvents::CreateService do
context 'when error occurs during creation' do
let(:args) { {} }
- it_behaves_like 'error response', "Occurred at can't be blank, Note can't be blank, and Note html can't be blank"
+ it_behaves_like 'error response', "Occurred at can't be blank and Timeline text can't be blank"
end
context 'with default action' do
diff --git a/spec/services/incident_management/timeline_events/destroy_service_spec.rb b/spec/services/incident_management/timeline_events/destroy_service_spec.rb
index 09026f87116..2fffe75b53c 100644
--- a/spec/services/incident_management/timeline_events/destroy_service_spec.rb
+++ b/spec/services/incident_management/timeline_events/destroy_service_spec.rb
@@ -48,7 +48,7 @@ RSpec.describe IncidentManagement::TimelineEvents::DestroyService do
timeline_event.errors.add(:note, 'cannot be removed')
end
- it_behaves_like 'error response', 'Note cannot be removed'
+ it_behaves_like 'error response', 'Timeline text cannot be removed'
end
context 'success response' do
diff --git a/spec/services/incident_management/timeline_events/update_service_spec.rb b/spec/services/incident_management/timeline_events/update_service_spec.rb
index f612c72e2a8..21aa983dbd1 100644
--- a/spec/services/incident_management/timeline_events/update_service_spec.rb
+++ b/spec/services/incident_management/timeline_events/update_service_spec.rb
@@ -98,7 +98,7 @@ RSpec.describe IncidentManagement::TimelineEvents::UpdateService do
context 'when note is blank' do
let(:params) { { note: '', occurred_at: occurred_at } }
- it_behaves_like 'error response', "Note can't be blank"
+ it_behaves_like 'error response', "Timeline text can't be blank"
end
context 'when occurred_at is nil' do
diff --git a/spec/support/helpers/usage_data_helpers.rb b/spec/support/helpers/usage_data_helpers.rb
index 90903f16bd7..89bb9492125 100644
--- a/spec/support/helpers/usage_data_helpers.rb
+++ b/spec/support/helpers/usage_data_helpers.rb
@@ -5,7 +5,6 @@ module UsageDataHelpers
snippet_comment
merge_request_comment
commit_comment
- navbar_searches
).freeze
COUNTS_KEYS = %i(