Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
aaedbff77d
commit
a7698afc6e
|
@ -1 +1 @@
|
|||
e4d8f69ffa2efd3f2cb0adff5fa66f367f66f6fb
|
||||
9498ab9459048cc595d8e2e411b027d080c0ab0f
|
||||
|
|
6
Gemfile
6
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'
|
||||
|
|
|
@ -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"},
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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'
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -0,0 +1 @@
|
|||
ffa421a7ffc279cb2751ed9e74c212ab60a3b6f7722d15023d39f7ad97ff1e6c
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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?
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 ""
|
||||
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 }
|
||||
|
||||
|
|
|
@ -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) }
|
||||
|
|
|
@ -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) }
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -5,7 +5,6 @@ module UsageDataHelpers
|
|||
snippet_comment
|
||||
merge_request_comment
|
||||
commit_comment
|
||||
navbar_searches
|
||||
).freeze
|
||||
|
||||
COUNTS_KEYS = %i(
|
||||
|
|
Loading…
Reference in New Issue