diff --git a/debian/patches/0050-relax-stable-libs.patch b/debian/patches/0050-relax-stable-libs.patch index 80d6ba1848..f2b1ed6c9f 100644 --- a/debian/patches/0050-relax-stable-libs.patch +++ b/debian/patches/0050-relax-stable-libs.patch @@ -26,7 +26,7 @@ gitlab Gemfile # Supported DBs gem 'pg', '~> 1.1' @@ -22,31 +22,31 @@ - gem 'grape-path-helpers', '~> 1.2' + gem 'grape-path-helpers', '~> 1.3' gem 'faraday', '~> 0.12' -gem 'marginalia', '~> 1.8.0' @@ -69,7 +69,7 @@ gitlab Gemfile # Kerberos authentication. EE-only gem 'gssapi', group: :kerberos -@@ -57,42 +57,42 @@ +@@ -57,14 +57,14 @@ gem 'invisible_captcha', '~> 0.12.1' # Two-factor authentication @@ -86,10 +86,9 @@ gitlab Gemfile +gem 'validates_hostname', '~> 1.0', '>= 1.0.10' +gem 'rubyzip', '~> 2.0', require: 'zip' # GitLab Pages letsencrypt support --gem 'acme-client', '~> 2.0.5' -+gem 'acme-client', '~> 2.0', '>= 2.0.5' + gem 'acme-client', '~> 2.0', '>= 2.0.6' - # Browser detection +@@ -72,12 +72,12 @@ gem 'browser', '~> 2.5' # GPG @@ -104,8 +103,9 @@ gitlab Gemfile gem 'net-ldap' # API --gem 'grape', '~> 1.1.0' -+gem 'grape', '~> 1.1' +@@ -85,16 +85,16 @@ + # Remove config/initializers/grape_patch.rb + gem 'grape', '= 1.4.0' gem 'grape-entity', '~> 0.7.1' -gem 'rack-cors', '~> 1.0.6', require: 'rack/cors' +gem 'rack-cors', '~> 1.0', '>= 1.0.6', require: 'rack/cors' @@ -124,7 +124,7 @@ gitlab Gemfile # Disable strong_params so that Mash does not respond to :permitted? gem 'hashie-forbidden_attributes' -@@ -101,7 +101,7 @@ +@@ -103,7 +103,7 @@ gem 'kaminari', '~> 1.0' # HAML @@ -133,7 +133,7 @@ gitlab Gemfile # Files attachments gem 'carrierwave', '~> 1.3' -@@ -111,7 +111,7 @@ +@@ -113,7 +113,7 @@ gem 'fog-aws', '~> 3.5' # Locked until fog-google resolves https://github.com/fog/fog-google/issues/421. # Also see config/initializers/fog_core_patch.rb. @@ -142,7 +142,7 @@ gitlab Gemfile gem 'fog-google', '~> 1.10' gem 'fog-local', '~> 0.6' gem 'fog-openstack', '~> 1.0' -@@ -125,7 +125,7 @@ +@@ -127,7 +127,7 @@ gem 'unf', '~> 0.1.4' # Seed data @@ -151,7 +151,7 @@ gitlab Gemfile # Search gem 'elasticsearch-model', '~> 6.1' -@@ -136,22 +136,22 @@ +@@ -138,23 +138,23 @@ # Markdown and HTML processing gem 'html-pipeline', '~> 2.12' @@ -162,8 +162,10 @@ gitlab Gemfile +gem 'gitlab-markup', '~> 1.7', '>= 1.7.1' +gem 'github-markup', '~> 1.7', require: 'github/markup' gem 'commonmarker', '~> 0.20' +-gem 'kramdown', '~> 2.2.1' -gem 'RedCloth', '~> 4.3.2' -gem 'rdoc', '~> 6.1.2' ++gem 'kramdown', '~> 2.2', '>= 2.2.1' +gem 'RedCloth', '~> 4.3', '>= 4.3.2' +gem 'rdoc', '~> 6.1', '>= 6.1.2' gem 'org-ruby', '~> 0.9.12' @@ -173,8 +175,8 @@ gitlab Gemfile +gem 'asciidoctor', '~> 2.0', '>= 2.0.10' gem 'asciidoctor-include-ext', '~> 0.3.1', require: false gem 'asciidoctor-plantuml', '~> 0.0.12' --gem 'rouge', '~> 3.19.0' -+gem 'rouge', '~> 3.19' +-gem 'rouge', '~> 3.21.0' ++gem 'rouge', '~> 3.21' gem 'truncato', '~> 0.7.11' -gem 'bootstrap_form', '~> 4.2.0' -gem 'nokogiri', '~> 1.10.9' @@ -183,16 +185,16 @@ gitlab Gemfile gem 'escape_utils', '~> 1.1' # Calendar rendering -@@ -162,7 +162,7 @@ +@@ -165,7 +165,7 @@ gem 'diff_match_patch', '~> 0.1.0' # Application server -gem 'rack', '~> 2.0.9' +gem 'rack', '~> 2.0', '>= 2.0.9' + # https://github.com/sharpstone/rack-timeout/blob/master/README.md#rails-apps-manually + gem 'rack-timeout', '~> 0.5.1', require: 'rack/timeout/base' - group :unicorn do - gem 'unicorn', '~> 5.5' -@@ -182,13 +182,13 @@ +@@ -186,13 +186,13 @@ gem 'acts-as-taggable-on', '~> 6.0' # Background jobs @@ -209,7 +211,7 @@ gitlab Gemfile # HTTP requests gem 'httparty', '~> 0.16.4' -@@ -200,14 +200,14 @@ +@@ -204,14 +204,14 @@ gem 'ruby-progressbar' # GitLab settings @@ -227,7 +229,7 @@ gitlab Gemfile # Export Ruby Regex to Javascript gem 'js_regex', '~> 3.1' -@@ -220,13 +220,13 @@ +@@ -224,23 +224,23 @@ gem 'connection_pool', '~> 2.0' # Redis session store @@ -242,8 +244,11 @@ gitlab Gemfile +gem 'hipchat', '~> 1.5' # Jira integration - gem 'jira-ruby', '~> 2.0.0' -@@ -236,7 +236,7 @@ +-gem 'jira-ruby', '~> 2.0.0' ++gem 'jira-ruby', '~> 2.0' + gem 'atlassian-jwt', '~> 0.2.0' + + # Flowdock integration gem 'flowdock', '~> 0.7' # Slack integration @@ -252,7 +257,7 @@ gitlab Gemfile # Hangouts Chat integration gem 'hangouts-chat', '~> 0.0.5' -@@ -248,11 +248,11 @@ +@@ -254,11 +254,11 @@ gem 'ruby-fogbugz', '~> 0.2.1' # Kubernetes integration @@ -266,7 +271,7 @@ gitlab Gemfile # Sanitizes SVG input gem 'loofah', '~> 2.2' -@@ -261,7 +261,7 @@ +@@ -267,7 +267,7 @@ gem 'licensee', '~> 8.9' # Ace editor @@ -275,7 +280,7 @@ gitlab Gemfile # Detect and convert string character encoding gem 'charlock_holmes', '~> 0.7.5' -@@ -279,8 +279,8 @@ +@@ -285,8 +285,8 @@ gem 'webpack-rails', '~> 0.9.10' gem 'rack-proxy', '~> 0.6.0' @@ -286,7 +291,7 @@ gitlab Gemfile gem 'addressable', '~> 2.7' gem 'font-awesome-rails', '~> 4.7' -@@ -292,24 +292,24 @@ +@@ -298,24 +298,24 @@ gem "gitlab-license", "~> 1.0" # Protect against bruteforcing @@ -300,8 +305,8 @@ gitlab Gemfile +gem 'premailer-rails', '~> 1.10', '>= 1.10.3' # LabKit: Tracing and Correlation --gem 'gitlab-labkit', '0.12.0' -+gem 'gitlab-labkit', '~> 0.12.0' +-gem 'gitlab-labkit', '0.12.1' ++gem 'gitlab-labkit', '~> 0.12.1' # I18n gem 'ruby_parser', '~> 3.8', require: false @@ -317,7 +322,7 @@ gitlab Gemfile # Perf bar gem 'peek', '~> 1.1' -@@ -343,40 +343,40 @@ +@@ -348,29 +348,29 @@ group :development, :test do gem 'bullet', '~> 6.0.2' @@ -346,8 +351,8 @@ gitlab Gemfile + gem 'spring', '~> 2.0' + gem 'spring-commands-rspec', '~> 1.0', '>= 1.0.4' -- gem 'gitlab-styles', '~> 4.2.0', require: false -+ gem 'gitlab-styles', '~> 4.2', require: false +- gem 'gitlab-styles', '~> 4.3.0', require: false ++ gem 'gitlab-styles', '~> 4.3', require: false # Pin these dependencies, otherwise a new rule could break the CI pipelines - gem 'rubocop', '~> 0.82.0' - gem 'rubocop-performance', '~> 1.5.2' @@ -358,7 +363,8 @@ gitlab Gemfile gem 'scss_lint', '~> 0.56.0', require: false gem 'haml_lint', '~> 0.34.0', require: false - gem 'simplecov', '~> 0.18.5', require: false +@@ -378,11 +378,11 @@ + gem 'simplecov-cobertura', '~> 1.3.1', require: false gem 'bundler-audit', '~> 0.6.1', require: false - gem 'benchmark-ips', '~> 2.3.0', require: false @@ -371,7 +377,7 @@ gitlab Gemfile gem 'timecop', '~> 0.9.1' -@@ -391,18 +391,18 @@ +@@ -399,18 +399,18 @@ end group :test do @@ -396,7 +402,7 @@ gitlab Gemfile gem 'rails-controller-testing' gem 'concurrent-ruby', '~> 1.1' gem 'test-prof', '~> 0.10.0' -@@ -421,7 +421,7 @@ +@@ -429,7 +429,7 @@ gem 'email_reply_trimmer', '~> 0.1' gem 'html2text' @@ -405,7 +411,7 @@ gitlab Gemfile gem 'stackprof', '~> 0.2.15', require: false gem 'rbtrace', '~> 0.4', require: false gem 'memory_profiler', '~> 0.9', require: false -@@ -432,11 +432,11 @@ +@@ -440,11 +440,11 @@ gem 'oauth2', '~> 1.4' # Health check @@ -420,12 +426,12 @@ gitlab Gemfile # NTP client gem 'net-ntp' -@@ -452,13 +452,13 @@ +@@ -460,13 +460,13 @@ end # Gitaly GRPC protocol definitions --gem 'gitaly', '~> 13.1.0.pre.rc1' -+gem 'gitaly', '~> 13.1' +-gem 'gitaly', '~> 13.2.0.pre.rc2' ++gem 'gitaly', '~> 13.2' -gem 'grpc', '~> 1.24.0' +gem 'grpc', '~> 1.24' @@ -438,7 +444,7 @@ gitlab Gemfile # Feature toggles gem 'flipper', '~> 0.17.1' -@@ -476,12 +476,12 @@ +@@ -484,12 +484,12 @@ # Countries list gem 'countries', '~> 3.0' @@ -453,11 +459,15 @@ gitlab Gemfile # Locked as long as quoted-printable encoding issues are not resolved # Monkey-patched in `config/initializers/mail_encoding_patch.rb` -@@ -495,5 +495,5 @@ +@@ -503,7 +503,7 @@ gem 'valid_email', '~> 0.1' # JSON -gem 'json', '~> 2.3.0' -gem 'json-schema', '~> 2.8.0' +-gem 'oj', '~> 3.10.6' +-gem 'multi_json', '~> 1.14.1' +gem 'json', '~> 2.3' +gem 'json-schema', '~> 2.8' ++gem 'oj', '~> 3.10', '>= 3.10.6' ++gem 'multi_json', '~> 1.14', '>= 1.14.1' diff --git a/debian/patches/0100-remove-development-test.patch b/debian/patches/0100-remove-development-test.patch index 930879a827..0c976bebec 100644 --- a/debian/patches/0100-remove-development-test.patch +++ b/debian/patches/0100-remove-development-test.patch @@ -2,7 +2,7 @@ Bundler will fail when it can't find these locally --- a/Gemfile +++ b/Gemfile -@@ -92,7 +92,6 @@ +@@ -94,7 +94,6 @@ # https://gitlab.com/gitlab-org/gitlab/issues/31747 gem 'graphiql-rails', '~> 1.4', '>= 1.4.10' gem 'apollo_upload_server', '~> 2.0.0.beta3' @@ -10,7 +10,7 @@ Bundler will fail when it can't find these locally # Disable strong_params so that Mash does not respond to :permitted? gem 'hashie-forbidden_attributes' -@@ -307,7 +306,6 @@ +@@ -313,7 +312,6 @@ gem 'rails-i18n', '~> 6.0' gem 'gettext_i18n_rails', '~> 1.8' gem 'gettext_i18n_rails_js', '~> 1.3' @@ -18,7 +18,7 @@ Bundler will fail when it can't find these locally gem 'batch-loader', '~> 1.4' -@@ -326,21 +324,6 @@ +@@ -332,20 +330,6 @@ gem 'raindrops', '~> 0.18' end @@ -27,10 +27,9 @@ Bundler will fail when it can't find these locally - gem 'danger', '~> 6.0', require: false - - gem 'letter_opener_web', '~> 1.3.4' -- gem 'rblineprof', '~> 0.3.6', platform: :mri, require: false - - # Better errors handler -- gem 'better_errors', '~> 2.5.0' +- gem 'better_errors', '~> 2.7.1' - gem 'binding_of_caller', '~> 0.8.0' - - # thin instead webrick @@ -40,11 +39,11 @@ Bundler will fail when it can't find these locally group :development, :test do gem 'bullet', '~> 6.0.2' gem 'pry-byebug', '~> 3.5','>= 3.5.1', platform: :mri -@@ -361,17 +344,6 @@ +@@ -366,18 +350,6 @@ gem 'spring', '~> 2.0' gem 'spring-commands-rspec', '~> 1.0', '>= 1.0.4' -- gem 'gitlab-styles', '~> 4.2', require: false +- gem 'gitlab-styles', '~> 4.3', require: false - # Pin these dependencies, otherwise a new rule could break the CI pipelines - gem 'rubocop', '~> 0.82' - gem 'rubocop-performance', '~> 1.5', '>= 1.5.2' @@ -53,13 +52,14 @@ Bundler will fail when it can't find these locally - gem 'scss_lint', '~> 0.56.0', require: false - gem 'haml_lint', '~> 0.34.0', require: false - gem 'simplecov', '~> 0.18.5', require: false +- gem 'simplecov-cobertura', '~> 1.3.1', require: false - gem 'bundler-audit', '~> 0.6.1', require: false - gem 'benchmark-ips', '~> 2.3', require: false gem 'knapsack', '~> 1.17' -@@ -385,11 +357,6 @@ - gem 'parallel', '~> 1.19', require: false +@@ -393,11 +365,6 @@ + gem 'rblineprof', '~> 0.3.6', platform: :mri, require: false end -# Gems required in omnibus-gitlab pipeline diff --git a/debian/patches/0110-make-test-dependencies-conditional.patch b/debian/patches/0110-make-test-dependencies-conditional.patch index 06b2bd7d64..b99981824a 100644 --- a/debian/patches/0110-make-test-dependencies-conditional.patch +++ b/debian/patches/0110-make-test-dependencies-conditional.patch @@ -2,7 +2,7 @@ Make test dependencies conditional so we can enable them when running autopkgtes --- a/Gemfile +++ b/Gemfile -@@ -324,7 +324,7 @@ +@@ -330,7 +330,7 @@ gem 'raindrops', '~> 0.18' end @@ -11,12 +11,12 @@ Make test dependencies conditional so we can enable them when running autopkgtes gem 'bullet', '~> 6.0.2' gem 'pry-byebug', '~> 3.5','>= 3.5.1', platform: :mri gem 'pry-rails', '~> 0.3.9' -@@ -355,9 +355,6 @@ - gem 'png_quantizator', '~> 0.2.1', require: false - +@@ -363,9 +363,7 @@ gem 'parallel', '~> 1.19', require: false + + gem 'rblineprof', '~> 0.3.6', platform: :mri, require: false -end -- + -group :test do gem 'fuubar', '~> 2.2' gem 'rspec-retry', '~> 0.6.1' diff --git a/debian/patches/0340-relax-httparty.patch b/debian/patches/0340-relax-httparty.patch index aeff7d6deb..add139ab2a 100644 --- a/debian/patches/0340-relax-httparty.patch +++ b/debian/patches/0340-relax-httparty.patch @@ -2,7 +2,7 @@ Allow newer versions of httparty to satisfy dependency --- a/Gemfile +++ b/Gemfile -@@ -190,7 +190,7 @@ +@@ -194,7 +194,7 @@ gem 'fugit', '~> 1.2', '>= 1.2.1' # HTTP requests diff --git a/debian/patches/0350-relax-method-source.patch b/debian/patches/0350-relax-method-source.patch index be5df4e0a6..8d98d262f5 100644 --- a/debian/patches/0350-relax-method-source.patch +++ b/debian/patches/0350-relax-method-source.patch @@ -2,7 +2,7 @@ Allow newer version to satisfy requirement --- a/Gemfile +++ b/Gemfile -@@ -317,7 +317,7 @@ +@@ -323,7 +323,7 @@ # Metrics group :metrics do diff --git a/debian/patches/0350-relax-rdoc.patch b/debian/patches/0350-relax-rdoc.patch index bef2ae03ca..fdfe2ff1d3 100644 --- a/debian/patches/0350-relax-rdoc.patch +++ b/debian/patches/0350-relax-rdoc.patch @@ -2,9 +2,9 @@ Allow rdoc from ruby 2.5 to match requirement --- a/Gemfile +++ b/Gemfile -@@ -140,7 +140,7 @@ - gem 'github-markup', '~> 1.7', require: 'github/markup' +@@ -143,7 +143,7 @@ gem 'commonmarker', '~> 0.20' + gem 'kramdown', '~> 2.2', '>= 2.2.1' gem 'RedCloth', '~> 4.3', '>= 4.3.2' -gem 'rdoc', '~> 6.1', '>= 6.1.2' +gem 'rdoc', '~> 6.0' diff --git a/debian/patches/0430-remove-gitlab-markup.patch b/debian/patches/0430-remove-gitlab-markup.patch index 946b6a94b2..7ca4b56ef2 100644 --- a/debian/patches/0430-remove-gitlab-markup.patch +++ b/debian/patches/0430-remove-gitlab-markup.patch @@ -4,11 +4,11 @@ maintaining two almost same packages. --- a/Gemfile +++ b/Gemfile -@@ -136,7 +136,6 @@ +@@ -138,7 +138,6 @@ # Markdown and HTML processing gem 'html-pipeline', '~> 2.12' gem 'deckar01-task_list', '~> 2.3', '>= 2.3.1' -gem 'gitlab-markup', '~> 1.7', '>= 1.7.1' gem 'github-markup', '~> 1.7', require: 'github/markup' gem 'commonmarker', '~> 0.20' - gem 'RedCloth', '~> 4.3', '>= 4.3.2' + gem 'kramdown', '~> 2.2', '>= 2.2.1' diff --git a/debian/patches/0440-remove-puma.patch b/debian/patches/0440-remove-puma.patch index e25d5eef92..8ad2bcb208 100644 --- a/debian/patches/0440-remove-puma.patch +++ b/debian/patches/0440-remove-puma.patch @@ -2,21 +2,13 @@ We are using unicorn so don't need puma --- a/Gemfile +++ b/Gemfile -@@ -161,18 +161,13 @@ - - # Application server - gem 'rack', '~> 2.0', '>= 2.0.9' -+gem 'rack-timeout', require: false - - group :unicorn do - gem 'unicorn', '~> 5.5' +@@ -172,11 +172,6 @@ gem 'unicorn-worker-killer', '~> 0.4.4' end -group :puma do - gem 'gitlab-puma', '~> 4.3.3.gitlab.2', require: false - gem 'gitlab-puma_worker_killer', '~> 0.1.1.gitlab.1', require: false -- gem 'rack-timeout', require: false -end - # State machine diff --git a/debian/patches/0480-embed-elasticsearch-model.patch b/debian/patches/0480-embed-elasticsearch-model.patch index 914c2137bc..e6a170e75e 100644 --- a/debian/patches/0480-embed-elasticsearch-model.patch +++ b/debian/patches/0480-embed-elasticsearch-model.patch @@ -2,7 +2,7 @@ Embed this gem until gitlab moved to 7.x version --- a/Gemfile +++ b/Gemfile -@@ -127,7 +127,7 @@ +@@ -129,7 +129,7 @@ gem 'seed-fu', '~> 2.3', '>= 2.3.7' # Search diff --git a/debian/patches/0480-embed-elasticsearch-rails.patch b/debian/patches/0480-embed-elasticsearch-rails.patch index 15d0facd30..53d041fbab 100644 --- a/debian/patches/0480-embed-elasticsearch-rails.patch +++ b/debian/patches/0480-embed-elasticsearch-rails.patch @@ -2,7 +2,7 @@ Embed this gem until gitlab moved to 7.x version --- a/Gemfile +++ b/Gemfile -@@ -128,7 +128,7 @@ +@@ -130,7 +130,7 @@ # Search gem 'elasticsearch-model', '~> 6.1', path: 'vendor/gems/elasticsearch-model' diff --git a/debian/patches/0480-embed-faraday-middleware-aws-signers-v4.patch b/debian/patches/0480-embed-faraday-middleware-aws-signers-v4.patch index 97624bbff9..46e11e007b 100644 --- a/debian/patches/0480-embed-faraday-middleware-aws-signers-v4.patch +++ b/debian/patches/0480-embed-faraday-middleware-aws-signers-v4.patch @@ -5,7 +5,7 @@ Bug: https://gitlab.com/gitlab-org/gitlab/-/issues/37931 --- a/Gemfile +++ b/Gemfile -@@ -131,7 +131,7 @@ +@@ -133,7 +133,7 @@ gem 'elasticsearch-rails', '~> 6.1', require: 'elasticsearch/rails/instrumentation', path: 'vendor/gems/elasticsearch-rails' gem 'elasticsearch-api', '~> 6.8' gem 'aws-sdk' diff --git a/debian/patches/0482-remove-ee-only-gems.patch b/debian/patches/0482-remove-ee-only-gems.patch index 5ef9d88726..daa57d77e2 100644 --- a/debian/patches/0482-remove-ee-only-gems.patch +++ b/debian/patches/0482-remove-ee-only-gems.patch @@ -12,7 +12,7 @@ This gem is used only in gitlab Enterprise Edition # Spam and anti-bot protection gem 'recaptcha', '~> 4.11', require: 'recaptcha/rails' gem 'akismet', '~> 3.0' -@@ -282,8 +279,6 @@ +@@ -288,8 +285,6 @@ gem 'request_store', '~> 1.5' gem 'base32', '~> 0.3.0' diff --git a/debian/patches/0484-relax-grape-entity.patch b/debian/patches/0484-relax-grape-entity.patch index 5ea3b04451..46b297a9de 100644 --- a/debian/patches/0484-relax-grape-entity.patch +++ b/debian/patches/0484-relax-grape-entity.patch @@ -2,10 +2,10 @@ Debian already has 0.8 --- a/Gemfile +++ b/Gemfile -@@ -79,7 +79,7 @@ - - # API - gem 'grape', '~> 1.1' +@@ -81,7 +81,7 @@ + # Locked at Grape v1.4.0 until https://github.com/ruby-grape/grape/pull/2088 is merged + # Remove config/initializers/grape_patch.rb + gem 'grape', '= 1.4.0' -gem 'grape-entity', '~> 0.7.1' +gem 'grape-entity', '~> 0.8' gem 'rack-cors', '~> 1.0', '>= 1.0.6', require: 'rack/cors' diff --git a/debian/patches/0510-remove-dev-dependencies.patch b/debian/patches/0510-remove-dev-dependencies.patch index 9c027ac2af..b312152520 100644 --- a/debian/patches/0510-remove-dev-dependencies.patch +++ b/debian/patches/0510-remove-dev-dependencies.patch @@ -2,14 +2,15 @@ These are not required in production --- a/package.json +++ b/package.json -@@ -155,66 +155,7 @@ +@@ -156,66 +156,7 @@ "xterm": "3.14.5" }, "devDependencies": { -- "acorn": "^6.3.0", - "@babel/plugin-transform-modules-commonjs": "^7.10.1", - "@gitlab/eslint-plugin": "3.1.0", +- "@testing-library/dom": "^7.16.2", - "@vue/test-utils": "^1.0.0-beta.30", +- "acorn": "^6.3.0", - "axios-mock-adapter": "^1.15.0", - "babel-jest": "^24.1.0", - "babel-plugin-dynamic-import-node": "^2.2.0", @@ -26,7 +27,6 @@ These are not required in production - "eslint-plugin-no-jquery": "^2.3.0", - "gettext-extractor": "^3.4.3", - "gettext-extractor-vue": "^4.0.2", -- "graphql-tag": "^2.10.1", - "istanbul-lib-coverage": "^3.0.0", - "istanbul-lib-report": "^3.0.0", - "istanbul-reports": "^3.0.0", @@ -66,7 +66,7 @@ These are not required in production - "yarn-check-webpack-plugin": "^1.2.0", - "yarn-deduplicate": "^1.1.1" - }, -+ }, ++ }, "blockedDependencies": { - "bootstrap-vue": "https://docs.gitlab.com/ee/development/fe_guide/dependencies.md#bootstrapvue" + "bootstrap-vue": "https://docs.gitlab.com/ee/development/fe_guide/dependencies.html#bootstrapvue" }, diff --git a/debian/patches/0740-use-packaged-modules.patch b/debian/patches/0740-use-packaged-modules.patch index b43a438306..7ca416fc6b 100644 --- a/debian/patches/0740-use-packaged-modules.patch +++ b/debian/patches/0740-use-packaged-modules.patch @@ -9,7 +9,7 @@ Use debian packaged node modules when available @@ -6,7 +6,6 @@ const StatsWriterPlugin = require('webpack-stats-plugin').StatsWriterPlugin; const CompressionPlugin = require('compression-webpack-plugin'); - const MonacoWebpackPlugin = require('monaco-editor-webpack-plugin'); + const MonacoWebpackPlugin = require('./plugins/monaco_webpack'); -const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin; const CopyWebpackPlugin = require('copy-webpack-plugin'); const vendorDllHash = require('./helpers/vendor_dll_hash'); @@ -76,7 +76,7 @@ Use debian packaged node modules when available }; --- a/package.json +++ b/package.json -@@ -33,12 +33,6 @@ +@@ -35,12 +35,6 @@ "webpack-prod": "NODE_OPTIONS=\"--max-old-space-size=3584\" NODE_ENV=production webpack --config config/webpack.config.js" }, "dependencies": { @@ -87,9 +87,9 @@ Use debian packaged node modules when available - "@babel/plugin-syntax-import-meta": "^7.10.1", - "@babel/preset-env": "^7.10.1", "@gitlab/at.js": "1.5.5", - "@gitlab/svgs": "1.140.0", - "@gitlab/ui": "17.0.1", -@@ -53,54 +47,28 @@ + "@gitlab/svgs": "1.152.0", + "@gitlab/ui": "17.33.0", +@@ -55,55 +49,29 @@ "apollo-link": "^1.2.11", "apollo-link-batch-http": "^1.2.11", "apollo-upload-client": "^10.0.0", @@ -101,7 +101,6 @@ Use debian packaged node modules when available "bootstrap": "4.4.1", - "brace-expansion": "^1.1.8", - "cache-loader": "^4.1.0", - "classlist-polyfill": "^1.2.0", - "clipboard": "^1.7.1", - "codemirror": "^5.48.4", "codesandbox-api": "0.0.23", @@ -124,12 +123,13 @@ Use debian packaged node modules when available "emoji-unicode-version": "^0.2.1", - "exports-loader": "^0.7.0", "file-loader": "^5.1.0", - "formdata-polyfill": "^3.0.19", "fuzzaldrin-plus": "^0.6.0", - "glob": "^7.1.6", "graphql": "^14.0.2", + "graphql-tag": "^2.10.1", "immer": "^5.2.1", - "imports-loader": "^0.8.0", + "ipaddr.js": "^1.9.1", - "jed": "^1.1.1", "jest-transform-graphql": "^2.1.0", - "jquery": "^3.4.1", @@ -137,6 +137,7 @@ Use debian packaged node modules when available "jquery.caret": "^0.3.1", "jquery.waitforimages": "^2.2.0", - "js-cookie": "^2.2.1", + "js-yaml": "^3.13.1", - "jszip": "^3.1.3", - "jszip-utils": "^0.0.2", "katex": "^0.10.0", @@ -144,10 +145,10 @@ Use debian packaged node modules when available "marked": "^0.3.12", "mermaid": "^8.5.2", "mersenne-twister": "1.1.0", -@@ -108,13 +76,9 @@ - "mitt": "^1.2.0", - "monaco-editor": "^0.18.1", - "monaco-editor-webpack-plugin": "^1.7.0", +@@ -111,13 +79,9 @@ + "monaco-editor": "^0.20.0", + "monaco-editor-webpack-plugin": "^1.9.0", + "monaco-yaml": "^2.4.0", - "mousetrap": "^1.4.6", "pdfjs-dist": "^2.0.943", "pikaday": "^1.8.0", @@ -158,8 +159,8 @@ Use debian packaged node modules when available "raphael": "^2.2.7", "raw-loader": "^4.0.0", "sanitize-html": "^1.22.0", -@@ -128,31 +92,21 @@ - "svg4everybody": "2.1.9", +@@ -130,30 +94,20 @@ + "style-loader": "^1.1.3", "swagger-ui-dist": "^3.26.2", "three": "^0.84.0", - "three-orbit-controls": "^82.1.0", @@ -168,8 +169,7 @@ Use debian packaged node modules when available "tiptap": "^1.8.0", "tiptap-commands": "^1.4.0", "tiptap-extensions": "^1.8.0", - "tributejs": "4.1.3", - "unfetch": "^4.1.0", + "tributejs": "5.1.3", - "url-loader": "^3.0.0", "uuid": "8.1.0", "visibilityjs": "^1.2.4", @@ -190,7 +190,7 @@ Use debian packaged node modules when available + "webpack-stats-plugin": "^0.3.1" }, "devDependencies": { - }, + }, --- a/babel.config.js +++ b/babel.config.js @@ -19,9 +19,12 @@ diff --git a/debian/patches/0741-add-graphql-tag.patch b/debian/patches/0741-add-graphql-tag.patch deleted file mode 100644 index 963fc6a932..0000000000 --- a/debian/patches/0741-add-graphql-tag.patch +++ /dev/null @@ -1,12 +0,0 @@ -yarn fails to install graphql-tag - ---- a/package.json -+++ b/package.json -@@ -64,6 +64,7 @@ - "formdata-polyfill": "^3.0.19", - "fuzzaldrin-plus": "^0.6.0", - "graphql": "^14.0.2", -+ "graphql-tag": "^2.10.0", - "immer": "^5.2.1", - "jest-transform-graphql": "^2.1.0", - "jquery.caret": "^0.3.1", diff --git a/debian/patches/0760-update-grape.patch b/debian/patches/0760-update-grape.patch deleted file mode 100644 index 52d425ac69..0000000000 --- a/debian/patches/0760-update-grape.patch +++ /dev/null @@ -1,2368 +0,0 @@ -From d5617969480da3d774c908bb00b3c37f7060a5a4 Mon Sep 17 00:00:00 2001 -From: Stan Hu -Date: Fri, 29 May 2020 16:12:45 -0700 -Subject: [PATCH 1/5] Upgrade to Grape v1.3.3 - -This brings back many of the changes in -https://gitlab.com/gitlab-org/gitlab/-/merge_requests/27276. This was -reverted due to some failures in the QA tests with nil parameters. - -This brings in Ruby 2.7 support and a number of fixes: -https://github.com/ruby-grape/grape/blob/master/CHANGELOG.md - -1. Move all inherited `Grape::API` -> `Grape::API::Instance` -2. Remove use of Virtus since this has been removed from Grape. -3. Extract `Rack::Response` from API error -4. Grape v1.2.3 pulled in a fix used in `SafeFile`: -https://github.com/ruby-grape/grape/pull/1844, so we no longer need -to maintain our custom type. -5. Adapt `WorkhorseFile` with the latest changes to make custom types work -with Grape and dry-types. -6. Ensure `Array[String]` is coerced properly. - -The change from Virtus to dry-types now requires all strings to be -coerced to arrays. Before this was done within Virtus. - -7. Coerce `Array[Integer]` types to arrays of integers - -The change from Virtus to dry-types now requires all strings to be -coerced to arrays of integers. Before this was done within Virtus. - -This merge request also introduces two Rubocop rules for Grape v1.3: - -1. `Grape::API::Instance` instead of `Grape::API` is required, unless we -solve https://gitlab.com/gitlab-org/gitlab/-/issues/215230. - -2. Grape parameters defined with `Array` types (e.g. `Array[String]`, -`Array[Integer]`) must have a `coerce_with` block or they will fail to -parse properly. See -https://github.com/ruby-grape/grape/blob/master/UPGRADING.md for more -details. - -Closes https://gitlab.com/gitlab-org/gitlab/-/issues/195960 ---- - .rubocop.yml | 12 +++ - Gemfile | 4 +- - Gemfile.lock | 55 +++++++----- - changelogs/unreleased/sh-update-grape-gem.yml | 5 ++ - doc/development/api_styleguide.md | 8 ++ - doc/development/ee_features.md | 12 +-- - ee/lib/api/analytics/code_review_analytics.rb | 2 +- - .../api/analytics/group_activity_analytics.rb | 2 +- - ee/lib/api/audit_events.rb | 2 +- - ee/lib/api/composer_packages.rb | 2 +- - ee/lib/api/conan_packages.rb | 2 +- - ee/lib/api/dependencies.rb | 3 +- - ee/lib/api/dependency_proxy.rb | 2 +- - .../api/elasticsearch_indexed_namespaces.rb | 2 +- - ee/lib/api/epic_issues.rb | 2 +- - ee/lib/api/epic_links.rb | 2 +- - ee/lib/api/epics.rb | 8 +- - ee/lib/api/feature_flag_scopes.rb | 2 +- - ee/lib/api/feature_flags.rb | 2 +- - ee/lib/api/feature_flags_user_lists.rb | 2 +- - ee/lib/api/geo.rb | 2 +- - ee/lib/api/geo_nodes.rb | 2 +- - ee/lib/api/geo_replication.rb | 2 +- - ee/lib/api/go_proxy.rb | 2 +- - ee/lib/api/group_hooks.rb | 2 +- - ee/lib/api/group_packages.rb | 2 +- - .../helpers/project_approval_rules_helpers.rb | 14 ++-- - ee/lib/api/issue_links.rb | 2 +- - ee/lib/api/ldap.rb | 2 +- - ee/lib/api/ldap_group_links.rb | 2 +- - ee/lib/api/license.rb | 2 +- - ee/lib/api/managed_licenses.rb | 2 +- - ee/lib/api/maven_packages.rb | 2 +- - ee/lib/api/merge_request_approval_rules.rb | 12 ++- - ee/lib/api/merge_request_approvals.rb | 10 +-- - ee/lib/api/merge_trains.rb | 2 +- - ee/lib/api/npm_packages.rb | 2 +- - ee/lib/api/nuget_packages.rb | 2 +- - ee/lib/api/package_files.rb | 2 +- - ee/lib/api/project_aliases.rb | 2 +- - ee/lib/api/project_approval_rules.rb | 2 +- - ee/lib/api/project_approval_settings.rb | 2 +- - ee/lib/api/project_approvals.rb | 8 +- - ee/lib/api/project_mirror.rb | 2 +- - ee/lib/api/project_packages.rb | 2 +- - ee/lib/api/project_push_rule.rb | 2 +- - ee/lib/api/protected_environments.rb | 2 +- - ee/lib/api/pypi_packages.rb | 2 +- - ee/lib/api/scim.rb | 2 +- - ee/lib/api/unleash.rb | 2 +- - ee/lib/api/v3/github.rb | 2 +- - ee/lib/api/visual_review_discussions.rb | 2 +- - ee/lib/api/vulnerabilities.rb | 2 +- - ee/lib/api/vulnerability_exports.rb | 2 +- - ee/lib/api/vulnerability_findings.rb | 8 +- - ee/lib/api/vulnerability_issue_links.rb | 2 +- - ee/lib/ee/api/boards.rb | 2 +- - ee/lib/ee/api/group_boards.rb | 2 +- - ee/lib/ee/api/helpers/settings_helpers.rb | 6 +- - ee/spec/lib/ee/api/helpers_spec.rb | 2 +- - .../api/merge_request_approval_rules_spec.rb | 34 +++++--- - .../api/merge_request_approvals_spec.rb | 10 +-- - .../api/project_approval_rules_spec.rb | 1 + - .../api/project_approval_settings_spec.rb | 1 + - ...ject_approval_rules_api_shared_examples.rb | 7 +- - lib/api/access_requests.rb | 2 +- - lib/api/admin/ci/variables.rb | 2 +- - lib/api/admin/sidekiq.rb | 2 +- - lib/api/api.rb | 2 +- - lib/api/api_guard.rb | 11 ++- - lib/api/appearance.rb | 2 +- - lib/api/applications.rb | 2 +- - lib/api/avatar.rb | 2 +- - lib/api/award_emoji.rb | 2 +- - lib/api/badges.rb | 2 +- - lib/api/boards.rb | 2 +- - lib/api/branches.rb | 2 +- - lib/api/broadcast_messages.rb | 2 +- - lib/api/commit_statuses.rb | 2 +- - lib/api/commits.rb | 2 +- - lib/api/container_registry_event.rb | 2 +- - lib/api/deploy_keys.rb | 2 +- - lib/api/deploy_tokens.rb | 6 +- - lib/api/deployments.rb | 2 +- - lib/api/discussions.rb | 2 +- - lib/api/environments.rb | 2 +- - lib/api/error_tracking.rb | 2 +- - lib/api/events.rb | 2 +- - lib/api/features.rb | 2 +- - lib/api/files.rb | 2 +- - lib/api/freeze_periods.rb | 2 +- - lib/api/group_boards.rb | 2 +- - lib/api/group_clusters.rb | 2 +- - lib/api/group_container_repositories.rb | 2 +- - lib/api/group_export.rb | 2 +- - lib/api/group_import.rb | 2 +- - lib/api/group_labels.rb | 2 +- - lib/api/group_milestones.rb | 2 +- - lib/api/group_variables.rb | 2 +- - lib/api/groups.rb | 4 +- - lib/api/helpers/merge_requests_helpers.rb | 2 +- - lib/api/helpers/projects_helpers.rb | 2 +- - lib/api/import_github.rb | 2 +- - lib/api/internal/base.rb | 2 +- - lib/api/internal/pages.rb | 2 +- - lib/api/issues.rb | 14 ++-- - lib/api/job_artifacts.rb | 2 +- - lib/api/jobs.rb | 2 +- - lib/api/keys.rb | 2 +- - lib/api/labels.rb | 2 +- - lib/api/lint.rb | 2 +- - lib/api/markdown.rb | 2 +- - lib/api/members.rb | 6 +- - lib/api/merge_request_diffs.rb | 2 +- - lib/api/merge_requests.rb | 12 +-- - lib/api/metrics/dashboard/annotations.rb | 2 +- - lib/api/metrics/user_starred_dashboards.rb | 2 +- - lib/api/milestone_responses.rb | 2 +- - lib/api/namespaces.rb | 2 +- - lib/api/notes.rb | 2 +- - lib/api/notification_settings.rb | 2 +- - lib/api/pages.rb | 2 +- - lib/api/pages_domains.rb | 2 +- - lib/api/pagination_params.rb | 2 +- - lib/api/pipeline_schedules.rb | 2 +- - lib/api/pipelines.rb | 2 +- - lib/api/project_clusters.rb | 2 +- - lib/api/project_container_repositories.rb | 2 +- - lib/api/project_events.rb | 2 +- - lib/api/project_export.rb | 2 +- - lib/api/project_hooks.rb | 2 +- - lib/api/project_import.rb | 2 +- - lib/api/project_milestones.rb | 2 +- - lib/api/project_repository_storage_moves.rb | 2 +- - lib/api/project_snapshots.rb | 2 +- - lib/api/project_snippets.rb | 2 +- - lib/api/project_statistics.rb | 2 +- - lib/api/project_templates.rb | 2 +- - lib/api/projects.rb | 4 +- - lib/api/protected_branches.rb | 2 +- - lib/api/protected_tags.rb | 2 +- - lib/api/release/links.rb | 2 +- - lib/api/releases.rb | 2 +- - lib/api/remote_mirrors.rb | 2 +- - lib/api/repositories.rb | 4 +- - lib/api/resource_label_events.rb | 2 +- - lib/api/resource_milestone_events.rb | 2 +- - lib/api/runner.rb | 4 +- - lib/api/runners.rb | 12 +-- - lib/api/search.rb | 2 +- - lib/api/services.rb | 2 +- - lib/api/settings.rb | 11 +-- - lib/api/sidekiq_metrics.rb | 2 +- - lib/api/snippets.rb | 2 +- - lib/api/statistics.rb | 2 +- - lib/api/submodules.rb | 2 +- - lib/api/subscriptions.rb | 2 +- - lib/api/suggestions.rb | 2 +- - lib/api/system_hooks.rb | 2 +- - lib/api/tags.rb | 2 +- - lib/api/templates.rb | 2 +- - lib/api/terraform/state.rb | 2 +- - lib/api/todos.rb | 2 +- - lib/api/triggers.rb | 2 +- - lib/api/user_counts.rb | 2 +- - lib/api/users.rb | 2 +- - .../types/comma_separated_to_array.rb | 2 +- - .../types/comma_separated_to_integer_array.rb | 15 ++++ - lib/api/validations/types/labels_list.rb | 24 ------ - lib/api/validations/types/safe_file.rb | 15 ---- - lib/api/validations/types/workhorse_file.rb | 13 ++- - lib/api/variables.rb | 2 +- - lib/api/version.rb | 2 +- - lib/api/wikis.rb | 4 +- - rubocop/cop/api/grape_api_instance.rb | 42 ++++++++++ - rubocop/cop/api/grape_array_missing_coerce.rb | 83 +++++++++++++++++++ - spec/requests/api/settings_spec.rb | 10 ++- - .../cop/api/grape_api_instance_spec.rb | 31 +++++++ - .../api/grape_array_missing_coerce_spec.rb | 64 ++++++++++++++ - spec/rubocop/cop/code_reuse/worker_spec.rb | 2 +- - 180 files changed, 571 insertions(+), 316 deletions(-) - create mode 100644 changelogs/unreleased/sh-update-grape-gem.yml - create mode 100644 lib/api/validations/types/comma_separated_to_integer_array.rb - delete mode 100644 lib/api/validations/types/labels_list.rb - delete mode 100644 lib/api/validations/types/safe_file.rb - create mode 100644 rubocop/cop/api/grape_api_instance.rb - create mode 100644 rubocop/cop/api/grape_array_missing_coerce.rb - create mode 100644 spec/rubocop/cop/api/grape_api_instance_spec.rb - create mode 100644 spec/rubocop/cop/api/grape_array_missing_coerce_spec.rb - ---- a/.rubocop.yml -+++ b/.rubocop.yml -@@ -308,6 +308,18 @@ - - 'spec/**/*' - - 'ee/spec/**/*' - -+API/GrapeAPIInstance: -+ Enabled: true -+ Include: -+ - 'lib/**/api/**/*.rb' -+ - 'ee/**/api/**/*.rb' -+ -+API/GrapeArrayMissingCoerce: -+ Enabled: true -+ Include: -+ - 'lib/**/api/**/*.rb' -+ - 'ee/**/api/**/*.rb' -+ - Cop/SidekiqOptionsQueue: - Enabled: true - Exclude: ---- a/Gemfile -+++ b/Gemfile -@@ -19,7 +19,7 @@ - gem 'pg', '~> 1.1' - - gem 'rugged', '~> 0.28' --gem 'grape-path-helpers', '~> 1.2' -+gem 'grape-path-helpers', '~> 1.3' - - gem 'faraday', '~> 0.12' - gem 'marginalia', '~> 1.8' ---- a/Gemfile.lock -+++ b/Gemfile.lock -@@ -103,10 +103,6 @@ - aws-sdk-core (= 2.11.374) - aws-sigv4 (1.1.0) - aws-eventstream (~> 1.0, >= 1.0.2) -- axiom-types (0.1.1) -- descendants_tracker (~> 0.0.4) -- ice_nine (~> 0.11.0) -- thread_safe (~> 0.3, >= 0.3.1) - babosa (1.0.2) - base32 (0.3.2) - batch-loader (1.4.0) -@@ -164,8 +160,6 @@ - nap - open4 (~> 1.3) - coderay (1.1.2) -- coercible (1.0.0) -- descendants_tracker (~> 0.0.1) - colored2 (3.1.2) - commonmarker (0.20.1) - ruby-enum (~> 0.5) -@@ -221,8 +215,6 @@ - ruby-statistics (>= 2.1) - thor (>= 0.19, < 2) - unicode_plot (>= 0.0.4, < 1.0.0) -- descendants_tracker (0.0.4) -- thread_safe (~> 0.3, >= 0.3.1) - device_detector (1.0.0) - devise (4.7.1) - bcrypt (~> 3.0) -@@ -249,6 +241,28 @@ - doorkeeper-openid_connect (1.6.3) - doorkeeper (>= 5.0, < 5.2) - json-jwt (~> 1.6) -+ dry-configurable (0.11.5) -+ concurrent-ruby (~> 1.0) -+ dry-core (~> 0.4, >= 0.4.7) -+ dry-equalizer (~> 0.2) -+ dry-container (0.7.2) -+ concurrent-ruby (~> 1.0) -+ dry-configurable (~> 0.1, >= 0.1.3) -+ dry-core (0.4.9) -+ concurrent-ruby (~> 1.0) -+ dry-equalizer (0.3.0) -+ dry-inflector (0.2.0) -+ dry-logic (1.0.6) -+ concurrent-ruby (~> 1.0) -+ dry-core (~> 0.2) -+ dry-equalizer (~> 0.2) -+ dry-types (1.4.0) -+ concurrent-ruby (~> 1.0) -+ dry-container (~> 0.3) -+ dry-core (~> 0.4, >= 0.4.4) -+ dry-equalizer (~> 0.3) -+ dry-inflector (~> 0.1, >= 0.1.2) -+ dry-logic (~> 1.0, >= 1.0.2) - ed25519 (1.2.4) - elasticsearch (6.8.0) - elasticsearch-api (= 6.8.0) -@@ -439,19 +453,19 @@ - signet (~> 0.14) - gpgme (2.0.20) - mini_portile2 (~> 2.3) -- grape (1.1.0) -+ grape (1.3.3) - activesupport - builder -+ dry-types (>= 1.1) - mustermann-grape (~> 1.0.0) - rack (>= 1.3.0) - rack-accept -- virtus (>= 1.0.0) - grape-entity (0.7.1) - activesupport (>= 4.0) - multi_json (>= 1.3.2) -- grape-path-helpers (1.2.0) -+ grape-path-helpers (1.3.0) - activesupport -- grape (~> 1.0) -+ grape (~> 1.3) - rake (~> 12) - grape_logging (1.8.3) - grape -@@ -641,9 +655,10 @@ - multi_xml (0.6.0) - multipart-post (2.1.1) - murmurhash3 (0.1.6) -- mustermann (1.0.3) -- mustermann-grape (1.0.0) -- mustermann (~> 1.0.0) -+ mustermann (1.1.1) -+ ruby2_keywords (~> 0.0.1) -+ mustermann-grape (1.0.1) -+ mustermann (>= 1.0.0) - nakayoshi_fork (0.0.4) - nap (1.1.0) - nenv (0.3.0) -@@ -958,6 +973,7 @@ - ruby-saml (1.7.2) - nokogiri (>= 1.5.10) - ruby-statistics (2.1.2) -+ ruby2_keywords (0.0.2) - ruby_dep (1.5.0) - ruby_parser (3.13.1) - sexp_processor (~> 4.9) -@@ -1119,11 +1135,6 @@ - activerecord (>= 3.0) - activesupport (>= 3.0) - version_sorter (2.2.4) -- virtus (1.0.5) -- axiom-types (~> 0.1) -- coercible (~> 1.0) -- descendants_tracker (~> 0.0, >= 0.0.3) -- equalizer (~> 0.0, >= 0.0.9) - vmstat (2.3.0) - warden (1.2.8) - rack (>= 2.0.6) -@@ -1254,9 +1265,9 @@ - google-api-client (~> 0.33) - google-protobuf (~> 3.8.0) - gpgme (~> 2.0.19) -- grape (~> 1.1.0) -+ grape (~> 1.3.3) - grape-entity (~> 0.7.1) -- grape-path-helpers (~> 1.2) -+ grape-path-helpers (~> 1.3) - grape_logging (~> 1.7) - graphiql-rails (~> 1.4.10) - graphql (~> 1.10.5) ---- /dev/null -+++ b/changelogs/unreleased/sh-update-grape-gem.yml -@@ -0,0 +1,5 @@ -+--- -+title: Upgrade Grape v1.1.0 to v1.3.3 -+merge_request: 33450 -+author: -+type: other ---- a/doc/development/api_styleguide.md -+++ b/doc/development/api_styleguide.md -@@ -98,6 +98,14 @@ - Model.create(foo: params[:foo]) - ``` - -+## Array types -+ -+With Grape v1.3+, Array types must be defined with a `coerce_with` -+block, or parameters will fail to validate when passed a string from an -+API request. See the [Grape upgrading -+documentation](https://github.com/ruby-grape/grape/blob/master/UPGRADING.md#ensure-that-array-types-have-explicit-coercions) -+for more details. -+ - ## Using HTTP status helpers - - For non-200 HTTP responses, use the provided helpers in `lib/api/helpers.rb` to ensure correct behavior (`not_found!`, `no_content!` etc.). These will `throw` inside Grape and abort the execution of your endpoint. ---- a/doc/development/ee_features.md -+++ b/doc/development/ee_features.md -@@ -512,12 +512,12 @@ - interface first here. - - For example, suppose we have a few more optional parameters for EE. We can move the --parameters out of the `Grape::API` class to a helper module, so we can inject it -+parameters out of the `Grape::API::Instance` class to a helper module, so we can inject it - before it would be used in the class. - - ```ruby - module API -- class Projects < Grape::API -+ class Projects < Grape::API::Instance - helpers Helpers::ProjectsHelpers - end - end -@@ -578,7 +578,7 @@ - - ```ruby - module API -- class JobArtifacts < Grape::API -+ class JobArtifacts < Grape::API::Instance - # EE::API::JobArtifacts would override the following helpers - helpers do - def authorize_download_artifacts! -@@ -622,7 +622,7 @@ - - ```ruby - module API -- class MergeRequests < Grape::API -+ class MergeRequests < Grape::API::Instance - helpers do - # EE::API::MergeRequests would override the following helpers - def update_merge_request_ee(merge_request) -@@ -691,7 +691,7 @@ - ```ruby - # api/merge_requests/parameters.rb - module API -- class MergeRequests < Grape::API -+ class MergeRequests < Grape::API::Instance - module Parameters - def self.update_params_at_least_one_of - %i[ -@@ -707,7 +707,7 @@ - - # api/merge_requests.rb - module API -- class MergeRequests < Grape::API -+ class MergeRequests < Grape::API::Instance - params do - at_least_one_of(*Parameters.update_params_at_least_one_of) - end ---- a/lib/api/access_requests.rb -+++ b/lib/api/access_requests.rb -@@ -1,7 +1,7 @@ - # frozen_string_literal: true - - module API -- class AccessRequests < Grape::API -+ class AccessRequests < Grape::API::Instance - include PaginationParams - - before { authenticate! } ---- a/lib/api/admin/ci/variables.rb -+++ b/lib/api/admin/ci/variables.rb -@@ -3,7 +3,7 @@ - module API - module Admin - module Ci -- class Variables < Grape::API -+ class Variables < Grape::API::Instance - include PaginationParams - - before { authenticated_as_admin! } ---- a/lib/api/admin/sidekiq.rb -+++ b/lib/api/admin/sidekiq.rb -@@ -2,7 +2,7 @@ - - module API - module Admin -- class Sidekiq < Grape::API -+ class Sidekiq < Grape::API::Instance - before { authenticated_as_admin! } - - namespace 'admin' do ---- a/lib/api/api.rb -+++ b/lib/api/api.rb -@@ -1,7 +1,7 @@ - # frozen_string_literal: true - - module API -- class API < Grape::API -+ class API < Grape::API::Instance - include APIGuard - - LOG_FILENAME = Rails.root.join("log", "api_json.log") ---- a/lib/api/api_guard.rb -+++ b/lib/api/api_guard.rb -@@ -153,7 +153,16 @@ - { scope: e.scopes }) - end - -- response.finish -+ finished_response = nil -+ response.finish do |rack_response| -+ # Grape expects a Rack::Response -+ # (https://github.com/ruby-grape/grape/commit/c117bff7d22971675f4b34367d3a98bc31c8fc02), -+ # and we need to retrieve it here: -+ # https://github.com/nov/rack-oauth2/blob/40c9a99fd80486ccb8de0e4869ae384547c0d703/lib/rack/oauth2/server/abstract/error.rb#L28 -+ finished_response = rack_response -+ end -+ -+ finished_response - end - end - end ---- a/lib/api/appearance.rb -+++ b/lib/api/appearance.rb -@@ -1,7 +1,7 @@ - # frozen_string_literal: true - - module API -- class Appearance < Grape::API -+ class Appearance < Grape::API::Instance - before { authenticated_as_admin! } - - helpers do ---- a/lib/api/applications.rb -+++ b/lib/api/applications.rb -@@ -2,7 +2,7 @@ - - module API - # External applications API -- class Applications < Grape::API -+ class Applications < Grape::API::Instance - before { authenticated_as_admin! } - - resource :applications do ---- a/lib/api/avatar.rb -+++ b/lib/api/avatar.rb -@@ -1,7 +1,7 @@ - # frozen_string_literal: true - - module API -- class Avatar < Grape::API -+ class Avatar < Grape::API::Instance - resource :avatar do - desc 'Return avatar url for a user' do - success Entities::Avatar ---- a/lib/api/award_emoji.rb -+++ b/lib/api/award_emoji.rb -@@ -1,7 +1,7 @@ - # frozen_string_literal: true - - module API -- class AwardEmoji < Grape::API -+ class AwardEmoji < Grape::API::Instance - include PaginationParams - - before { authenticate! } ---- a/lib/api/badges.rb -+++ b/lib/api/badges.rb -@@ -1,7 +1,7 @@ - # frozen_string_literal: true - - module API -- class Badges < Grape::API -+ class Badges < Grape::API::Instance - include PaginationParams - - before { authenticate_non_get! } ---- a/lib/api/boards.rb -+++ b/lib/api/boards.rb -@@ -1,7 +1,7 @@ - # frozen_string_literal: true - - module API -- class Boards < Grape::API -+ class Boards < Grape::API::Instance - include BoardsResponses - include PaginationParams - ---- a/lib/api/branches.rb -+++ b/lib/api/branches.rb -@@ -3,7 +3,7 @@ - require 'mime/types' - - module API -- class Branches < Grape::API -+ class Branches < Grape::API::Instance - include PaginationParams - - BRANCH_ENDPOINT_REQUIREMENTS = API::NAMESPACE_OR_PROJECT_REQUIREMENTS.merge(branch: API::NO_SLASH_URL_PART_REGEX) ---- a/lib/api/broadcast_messages.rb -+++ b/lib/api/broadcast_messages.rb -@@ -1,7 +1,7 @@ - # frozen_string_literal: true - - module API -- class BroadcastMessages < Grape::API -+ class BroadcastMessages < Grape::API::Instance - include PaginationParams - - resource :broadcast_messages do ---- a/lib/api/commit_statuses.rb -+++ b/lib/api/commit_statuses.rb -@@ -3,7 +3,7 @@ - require 'mime/types' - - module API -- class CommitStatuses < Grape::API -+ class CommitStatuses < Grape::API::Instance - params do - requires :id, type: String, desc: 'The ID of a project' - end ---- a/lib/api/commits.rb -+++ b/lib/api/commits.rb -@@ -3,7 +3,7 @@ - require 'mime/types' - - module API -- class Commits < Grape::API -+ class Commits < Grape::API::Instance - include PaginationParams - - before do ---- a/lib/api/container_registry_event.rb -+++ b/lib/api/container_registry_event.rb -@@ -1,7 +1,7 @@ - # frozen_string_literal: true - - module API -- class ContainerRegistryEvent < Grape::API -+ class ContainerRegistryEvent < Grape::API::Instance - DOCKER_DISTRIBUTION_EVENTS_V1_JSON = 'application/vnd.docker.distribution.events.v1+json' - - before { authenticate_registry_notification! } ---- a/lib/api/deploy_keys.rb -+++ b/lib/api/deploy_keys.rb -@@ -1,7 +1,7 @@ - # frozen_string_literal: true - - module API -- class DeployKeys < Grape::API -+ class DeployKeys < Grape::API::Instance - include PaginationParams - - before { authenticate! } ---- a/lib/api/deploy_tokens.rb -+++ b/lib/api/deploy_tokens.rb -@@ -1,7 +1,7 @@ - # frozen_string_literal: true - - module API -- class DeployTokens < Grape::API -+ class DeployTokens < Grape::API::Instance - include PaginationParams - - helpers do -@@ -56,7 +56,7 @@ - - params do - requires :name, type: String, desc: "New deploy token's name" -- requires :scopes, type: Array[String], values: ::DeployToken::AVAILABLE_SCOPES.map(&:to_s), -+ requires :scopes, type: Array[String], coerce_with: ::API::Validations::Types::CommaSeparatedToArray.coerce, values: ::DeployToken::AVAILABLE_SCOPES.map(&:to_s), - desc: 'Indicates the deploy token scopes. Must be at least one of "read_repository", "read_registry", "write_registry", "read_package_registry", or "write_package_registry".' - optional :expires_at, type: DateTime, desc: 'Expiration date for the deploy token. Does not expire if no value is provided.' - optional :username, type: String, desc: 'Username for deploy token. Default is `gitlab+deploy-token-{n}`' -@@ -119,7 +119,7 @@ - - params do - requires :name, type: String, desc: 'The name of the deploy token' -- requires :scopes, type: Array[String], values: ::DeployToken::AVAILABLE_SCOPES.map(&:to_s), -+ requires :scopes, type: Array[String], coerce_with: ::API::Validations::Types::CommaSeparatedToArray.coerce, values: ::DeployToken::AVAILABLE_SCOPES.map(&:to_s), - desc: 'Indicates the deploy token scopes. Must be at least one of "read_repository", "read_registry", "write_registry", "read_package_registry", or "write_package_registry".' - optional :expires_at, type: DateTime, desc: 'Expiration date for the deploy token. Does not expire if no value is provided.' - optional :username, type: String, desc: 'Username for deploy token. Default is `gitlab+deploy-token-{n}`' ---- a/lib/api/deployments.rb -+++ b/lib/api/deployments.rb -@@ -2,7 +2,7 @@ - - module API - # Deployments RESTful API endpoints -- class Deployments < Grape::API -+ class Deployments < Grape::API::Instance - include PaginationParams - - before { authenticate! } ---- a/lib/api/discussions.rb -+++ b/lib/api/discussions.rb -@@ -1,7 +1,7 @@ - # frozen_string_literal: true - - module API -- class Discussions < Grape::API -+ class Discussions < Grape::API::Instance - include PaginationParams - helpers ::API::Helpers::NotesHelpers - helpers ::RendersNotes ---- a/lib/api/environments.rb -+++ b/lib/api/environments.rb -@@ -2,7 +2,7 @@ - - module API - # Environments RESTfull API endpoints -- class Environments < Grape::API -+ class Environments < Grape::API::Instance - include PaginationParams - - before { authenticate! } ---- a/lib/api/error_tracking.rb -+++ b/lib/api/error_tracking.rb -@@ -1,7 +1,7 @@ - # frozen_string_literal: true - - module API -- class ErrorTracking < Grape::API -+ class ErrorTracking < Grape::API::Instance - before { authenticate! } - - params do ---- a/lib/api/events.rb -+++ b/lib/api/events.rb -@@ -1,7 +1,7 @@ - # frozen_string_literal: true - - module API -- class Events < Grape::API -+ class Events < Grape::API::Instance - include PaginationParams - include APIGuard - helpers ::API::Helpers::EventsHelpers ---- a/lib/api/features.rb -+++ b/lib/api/features.rb -@@ -1,7 +1,7 @@ - # frozen_string_literal: true - - module API -- class Features < Grape::API -+ class Features < Grape::API::Instance - before { authenticated_as_admin! } - - helpers do ---- a/lib/api/files.rb -+++ b/lib/api/files.rb -@@ -1,7 +1,7 @@ - # frozen_string_literal: true - - module API -- class Files < Grape::API -+ class Files < Grape::API::Instance - include APIGuard - - FILE_ENDPOINT_REQUIREMENTS = API::NAMESPACE_OR_PROJECT_REQUIREMENTS.merge(file_path: API::NO_SLASH_URL_PART_REGEX) ---- a/lib/api/freeze_periods.rb -+++ b/lib/api/freeze_periods.rb -@@ -1,7 +1,7 @@ - # frozen_string_literal: true - - module API -- class FreezePeriods < Grape::API -+ class FreezePeriods < Grape::API::Instance - include PaginationParams - - before { authenticate! } ---- a/lib/api/group_boards.rb -+++ b/lib/api/group_boards.rb -@@ -1,7 +1,7 @@ - # frozen_string_literal: true - - module API -- class GroupBoards < Grape::API -+ class GroupBoards < Grape::API::Instance - include BoardsResponses - include PaginationParams - ---- a/lib/api/group_clusters.rb -+++ b/lib/api/group_clusters.rb -@@ -1,7 +1,7 @@ - # frozen_string_literal: true - - module API -- class GroupClusters < Grape::API -+ class GroupClusters < Grape::API::Instance - include PaginationParams - - before { authenticate! } ---- a/lib/api/group_container_repositories.rb -+++ b/lib/api/group_container_repositories.rb -@@ -1,7 +1,7 @@ - # frozen_string_literal: true - - module API -- class GroupContainerRepositories < Grape::API -+ class GroupContainerRepositories < Grape::API::Instance - include PaginationParams - - before { authorize_read_group_container_images! } ---- a/lib/api/group_export.rb -+++ b/lib/api/group_export.rb -@@ -1,7 +1,7 @@ - # frozen_string_literal: true - - module API -- class GroupExport < Grape::API -+ class GroupExport < Grape::API::Instance - helpers Helpers::RateLimiter - - before do ---- a/lib/api/group_import.rb -+++ b/lib/api/group_import.rb -@@ -1,7 +1,7 @@ - # frozen_string_literal: true - - module API -- class GroupImport < Grape::API -+ class GroupImport < Grape::API::Instance - helpers Helpers::FileUploadHelpers - - helpers do ---- a/lib/api/group_labels.rb -+++ b/lib/api/group_labels.rb -@@ -1,7 +1,7 @@ - # frozen_string_literal: true - - module API -- class GroupLabels < Grape::API -+ class GroupLabels < Grape::API::Instance - include PaginationParams - helpers ::API::Helpers::LabelHelpers - ---- a/lib/api/group_milestones.rb -+++ b/lib/api/group_milestones.rb -@@ -1,7 +1,7 @@ - # frozen_string_literal: true - - module API -- class GroupMilestones < Grape::API -+ class GroupMilestones < Grape::API::Instance - include MilestoneResponses - include PaginationParams - ---- a/lib/api/group_variables.rb -+++ b/lib/api/group_variables.rb -@@ -1,7 +1,7 @@ - # frozen_string_literal: true - - module API -- class GroupVariables < Grape::API -+ class GroupVariables < Grape::API::Instance - include PaginationParams - - before { authenticate! } ---- a/lib/api/groups.rb -+++ b/lib/api/groups.rb -@@ -1,7 +1,7 @@ - # frozen_string_literal: true - - module API -- class Groups < Grape::API -+ class Groups < Grape::API::Instance - include PaginationParams - include Helpers::CustomAttributes - -@@ -16,7 +16,7 @@ - - params :group_list_params do - use :statistics_params -- optional :skip_groups, type: Array[Integer], desc: 'Array of group ids to exclude from list' -+ optional :skip_groups, type: Array[Integer], coerce_with: ::API::Validations::Types::CommaSeparatedToIntegerArray.coerce, desc: 'Array of group ids to exclude from list' - optional :all_available, type: Boolean, desc: 'Show all group that you have access to' - optional :search, type: String, desc: 'Search for a specific group' - optional :owned, type: Boolean, default: false, desc: 'Limit by owned by authenticated user' ---- a/lib/api/helpers/merge_requests_helpers.rb -+++ b/lib/api/helpers/merge_requests_helpers.rb -@@ -24,7 +24,7 @@ - optional :milestone, type: String, desc: 'Return merge requests for a specific milestone' - optional :labels, - type: Array[String], -- coerce_with: Validations::Types::LabelsList.coerce, -+ coerce_with: Validations::Types::CommaSeparatedToArray.coerce, - desc: 'Comma-separated list of label names' - optional :with_labels_details, type: Boolean, desc: 'Return titles of labels and other details', default: false - optional :with_merge_status_recheck, type: Boolean, desc: 'Request that stale merge statuses be rechecked asynchronously', default: false ---- a/lib/api/helpers/projects_helpers.rb -+++ b/lib/api/helpers/projects_helpers.rb -@@ -46,7 +46,7 @@ - optional :only_allow_merge_if_pipeline_succeeds, type: Boolean, desc: 'Only allow to merge if builds succeed' - optional :allow_merge_on_skipped_pipeline, type: Boolean, desc: 'Allow to merge if pipeline is skipped' - optional :only_allow_merge_if_all_discussions_are_resolved, type: Boolean, desc: 'Only allow to merge if all discussions are resolved' -- optional :tag_list, type: Array[String], desc: 'The list of tags for a project' -+ optional :tag_list, type: Array[String], coerce_with: ::API::Validations::Types::CommaSeparatedToArray.coerce, desc: 'The list of tags for a project' - # TODO: remove rubocop disable - https://gitlab.com/gitlab-org/gitlab/issues/14960 - optional :avatar, type: File, desc: 'Avatar image for project' # rubocop:disable Scalability/FileUploads - optional :printing_merge_request_link_enabled, type: Boolean, desc: 'Show link to create/view merge request when pushing from the command line' ---- a/lib/api/import_github.rb -+++ b/lib/api/import_github.rb -@@ -1,7 +1,7 @@ - # frozen_string_literal: true - - module API -- class ImportGithub < Grape::API -+ class ImportGithub < Grape::API::Instance - rescue_from Octokit::Unauthorized, with: :provider_unauthorized - - before do ---- a/lib/api/internal/base.rb -+++ b/lib/api/internal/base.rb -@@ -3,7 +3,7 @@ - module API - # Internal access API - module Internal -- class Base < Grape::API -+ class Base < Grape::API::Instance - before { authenticate_by_gitlab_shell_token! } - - before do ---- a/lib/api/internal/pages.rb -+++ b/lib/api/internal/pages.rb -@@ -3,7 +3,7 @@ - module API - # Pages Internal API - module Internal -- class Pages < Grape::API -+ class Pages < Grape::API::Instance - before do - authenticate_gitlab_pages_request! - end ---- a/lib/api/issues.rb -+++ b/lib/api/issues.rb -@@ -1,18 +1,21 @@ - # frozen_string_literal: true - - module API -- class Issues < Grape::API -+ class Issues < Grape::API::Instance - include PaginationParams - helpers Helpers::IssuesHelpers - helpers Helpers::RateLimiter - -- before { authenticate_non_get! } -+ before do -+ authenticate_non_get! -+ coerce_nil_params_to_array! -+ end - - helpers do - params :negatable_issue_filter_params do -- optional :labels, type: Array[String], coerce_with: Validations::Types::LabelsList.coerce, desc: 'Comma-separated list of label names' -+ optional :labels, type: Array[String], coerce_with: ::API::Validations::Types::CommaSeparatedToArray.coerce, desc: 'Comma-separated list of label names' - optional :milestone, type: String, desc: 'Milestone title' -- optional :iids, type: Array[Integer], desc: 'The IID array of issues' -+ optional :iids, type: Array[Integer], coerce_with: ::API::Validations::Types::CommaSeparatedToIntegerArray.coerce, desc: 'The IID array of issues' - optional :search, type: String, desc: 'Search issues for text present in the title, description, or any combination of these' - optional :in, type: String, desc: '`title`, `description`, or a string joining them with comma' - -@@ -62,12 +65,12 @@ - - params :issue_params do - optional :description, type: String, desc: 'The description of an issue' -- optional :assignee_ids, type: Array[Integer], desc: 'The array of user IDs to assign issue' -+ optional :assignee_ids, type: Array[Integer], coerce_with: ::API::Validations::Types::CommaSeparatedToIntegerArray.coerce, desc: 'The array of user IDs to assign issue' - optional :assignee_id, type: Integer, desc: '[Deprecated] The ID of a user to assign issue' - optional :milestone_id, type: Integer, desc: 'The ID of a milestone to assign issue' -- optional :labels, type: Array[String], coerce_with: Validations::Types::LabelsList.coerce, desc: 'Comma-separated list of label names' -- optional :add_labels, type: Array[String], coerce_with: Validations::Types::LabelsList.coerce, desc: 'Comma-separated list of label names' -- optional :remove_labels, type: Array[String], coerce_with: Validations::Types::LabelsList.coerce, desc: 'Comma-separated list of label names' -+ optional :labels, type: Array[String], coerce_with: ::API::Validations::Types::CommaSeparatedToArray.coerce, desc: 'Comma-separated list of label names' -+ optional :add_labels, type: Array[String], coerce_with: ::API::Validations::Types::CommaSeparatedToArray.coerce, desc: 'Comma-separated list of label names' -+ optional :remove_labels, type: Array[String], coerce_with: ::API::Validations::Types::CommaSeparatedToArray.coerce, desc: 'Comma-separated list of label names' - optional :due_date, type: String, desc: 'Date string in the format YEAR-MONTH-DAY' - optional :confidential, type: Boolean, desc: 'Boolean parameter if the issue should be confidential' - optional :discussion_locked, type: Boolean, desc: " Boolean parameter indicating if the issue's discussion is locked" ---- a/lib/api/job_artifacts.rb -+++ b/lib/api/job_artifacts.rb -@@ -1,7 +1,7 @@ - # frozen_string_literal: true - - module API -- class JobArtifacts < Grape::API -+ class JobArtifacts < Grape::API::Instance - before { authenticate_non_get! } - - # EE::API::JobArtifacts would override the following helpers ---- a/lib/api/jobs.rb -+++ b/lib/api/jobs.rb -@@ -1,7 +1,7 @@ - # frozen_string_literal: true - - module API -- class Jobs < Grape::API -+ class Jobs < Grape::API::Instance - include PaginationParams - - before { authenticate! } ---- a/lib/api/keys.rb -+++ b/lib/api/keys.rb -@@ -2,7 +2,7 @@ - - module API - # Keys API -- class Keys < Grape::API -+ class Keys < Grape::API::Instance - before { authenticate! } - - resource :keys do ---- a/lib/api/labels.rb -+++ b/lib/api/labels.rb -@@ -1,7 +1,7 @@ - # frozen_string_literal: true - - module API -- class Labels < Grape::API -+ class Labels < Grape::API::Instance - include PaginationParams - helpers ::API::Helpers::LabelHelpers - ---- a/lib/api/lint.rb -+++ b/lib/api/lint.rb -@@ -1,7 +1,7 @@ - # frozen_string_literal: true - - module API -- class Lint < Grape::API -+ class Lint < Grape::API::Instance - namespace :ci do - desc 'Validation of .gitlab-ci.yml content' - params do ---- a/lib/api/markdown.rb -+++ b/lib/api/markdown.rb -@@ -1,7 +1,7 @@ - # frozen_string_literal: true - - module API -- class Markdown < Grape::API -+ class Markdown < Grape::API::Instance - params do - requires :text, type: String, desc: "The markdown text to render" - optional :gfm, type: Boolean, desc: "Render text using GitLab Flavored Markdown" ---- a/lib/api/members.rb -+++ b/lib/api/members.rb -@@ -1,7 +1,7 @@ - # frozen_string_literal: true - - module API -- class Members < Grape::API -+ class Members < Grape::API::Instance - include PaginationParams - - before { authenticate! } -@@ -18,7 +18,7 @@ - end - params do - optional :query, type: String, desc: 'A query string to search for members' -- optional :user_ids, type: Array[Integer], desc: 'Array of user ids to look up for membership' -+ optional :user_ids, type: Array[Integer], coerce_with: ::API::Validations::Types::CommaSeparatedToIntegerArray.coerce, desc: 'Array of user ids to look up for membership' - optional :show_seat_info, type: Boolean, desc: 'Show seat information for members' - use :optional_filter_params_ee - use :pagination -@@ -37,7 +37,7 @@ - end - params do - optional :query, type: String, desc: 'A query string to search for members' -- optional :user_ids, type: Array[Integer], desc: 'Array of user ids to look up for membership' -+ optional :user_ids, type: Array[Integer], coerce_with: ::API::Validations::Types::CommaSeparatedToIntegerArray.coerce, desc: 'Array of user ids to look up for membership' - optional :show_seat_info, type: Boolean, desc: 'Show seat information for members' - use :pagination - end ---- a/lib/api/merge_request_diffs.rb -+++ b/lib/api/merge_request_diffs.rb -@@ -2,7 +2,7 @@ - - module API - # MergeRequestDiff API -- class MergeRequestDiffs < Grape::API -+ class MergeRequestDiffs < Grape::API::Instance - include PaginationParams - - before { authenticate! } ---- a/lib/api/merge_requests.rb -+++ b/lib/api/merge_requests.rb -@@ -1,12 +1,15 @@ - # frozen_string_literal: true - - module API -- class MergeRequests < Grape::API -+ class MergeRequests < Grape::API::Instance - include PaginationParams - - CONTEXT_COMMITS_POST_LIMIT = 20 - -- before { authenticate_non_get! } -+ before do -+ authenticate_non_get! -+ coerce_nil_params_to_array! -+ end - - helpers Helpers::MergeRequestsHelpers - -@@ -179,11 +182,11 @@ - params :optional_params do - optional :description, type: String, desc: 'The description of the merge request' - optional :assignee_id, type: Integer, desc: 'The ID of a user to assign the merge request' -- optional :assignee_ids, type: Array[Integer], desc: 'The array of user IDs to assign issue' -+ optional :assignee_ids, type: Array[Integer], coerce_with: ::API::Validations::Types::CommaSeparatedToIntegerArray.coerce, desc: 'The array of user IDs to assign issue' - optional :milestone_id, type: Integer, desc: 'The ID of a milestone to assign the merge request' -- optional :labels, type: Array[String], coerce_with: Validations::Types::LabelsList.coerce, desc: 'Comma-separated list of label names' -- optional :add_labels, type: Array[String], coerce_with: Validations::Types::LabelsList.coerce, desc: 'Comma-separated list of label names' -- optional :remove_labels, type: Array[String], coerce_with: Validations::Types::LabelsList.coerce, desc: 'Comma-separated list of label names' -+ optional :labels, type: Array[String], coerce_with: Validations::Types::CommaSeparatedToArray.coerce, desc: 'Comma-separated list of label names' -+ optional :add_labels, type: Array[String], coerce_with: Validations::Types::CommaSeparatedToArray.coerce, desc: 'Comma-separated list of label names' -+ optional :remove_labels, type: Array[String], coerce_with: Validations::Types::CommaSeparatedToArray.coerce, desc: 'Comma-separated list of label names' - optional :remove_source_branch, type: Boolean, desc: 'Remove source branch when merging' - optional :allow_collaboration, type: Boolean, desc: 'Allow commits from members who can merge to the target branch' - optional :allow_maintainer_to_push, type: Boolean, as: :allow_collaboration, desc: '[deprecated] See allow_collaboration' -@@ -198,7 +201,7 @@ - end - params do - use :merge_requests_params -- optional :iids, type: Array[Integer], desc: 'The IID array of merge requests' -+ optional :iids, type: Array[Integer], coerce_with: ::API::Validations::Types::CommaSeparatedToIntegerArray.coerce, desc: 'The IID array of merge requests' - end - get ":id/merge_requests" do - authorize! :read_merge_request, user_project -@@ -315,7 +318,7 @@ - end - - params do -- requires :commits, type: Array, allow_blank: false, desc: 'List of context commits sha' -+ requires :commits, type: Array[String], coerce_with: ::API::Validations::Types::CommaSeparatedToArray.coerce, allow_blank: false, desc: 'List of context commits sha' - end - desc 'create context commits of merge request' do - success Entities::Commit -@@ -345,7 +348,7 @@ - end - - params do -- requires :commits, type: Array, allow_blank: false, desc: 'List of context commits sha' -+ requires :commits, type: Array[String], coerce_with: ::API::Validations::Types::CommaSeparatedToArray.coerce, allow_blank: false, desc: 'List of context commits sha' - end - desc 'remove context commits of merge request' - delete ':id/merge_requests/:merge_request_iid/context_commits' do ---- a/lib/api/metrics/dashboard/annotations.rb -+++ b/lib/api/metrics/dashboard/annotations.rb -@@ -3,7 +3,7 @@ - module API - module Metrics - module Dashboard -- class Annotations < Grape::API -+ class Annotations < Grape::API::Instance - desc 'Create a new monitoring dashboard annotation' do - success Entities::Metrics::Dashboard::Annotation - end ---- a/lib/api/metrics/user_starred_dashboards.rb -+++ b/lib/api/metrics/user_starred_dashboards.rb -@@ -2,7 +2,7 @@ - - module API - module Metrics -- class UserStarredDashboards < Grape::API -+ class UserStarredDashboards < Grape::API::Instance - resource :projects do - desc 'Marks selected metrics dashboard as starred' do - success Entities::Metrics::UserStarredDashboard ---- a/lib/api/milestone_responses.rb -+++ b/lib/api/milestone_responses.rb -@@ -15,7 +15,7 @@ - params :list_params do - optional :state, type: String, values: %w[active closed all], default: 'all', - desc: 'Return "active", "closed", or "all" milestones' -- optional :iids, type: Array[Integer], desc: 'The IIDs of the milestones' -+ optional :iids, type: Array[Integer], coerce_with: ::API::Validations::Types::CommaSeparatedToIntegerArray.coerce, desc: 'The IIDs of the milestones' - optional :title, type: String, desc: 'The title of the milestones' - optional :search, type: String, desc: 'The search criteria for the title or description of the milestone' - use :pagination ---- a/lib/api/namespaces.rb -+++ b/lib/api/namespaces.rb -@@ -1,7 +1,7 @@ - # frozen_string_literal: true - - module API -- class Namespaces < Grape::API -+ class Namespaces < Grape::API::Instance - include PaginationParams - - before { authenticate! } ---- a/lib/api/notes.rb -+++ b/lib/api/notes.rb -@@ -1,7 +1,7 @@ - # frozen_string_literal: true - - module API -- class Notes < Grape::API -+ class Notes < Grape::API::Instance - include PaginationParams - helpers ::API::Helpers::NotesHelpers - ---- a/lib/api/notification_settings.rb -+++ b/lib/api/notification_settings.rb -@@ -2,7 +2,7 @@ - - module API - # notification_settings API -- class NotificationSettings < Grape::API -+ class NotificationSettings < Grape::API::Instance - before { authenticate! } - - helpers ::API::Helpers::MembersHelpers ---- a/lib/api/pages.rb -+++ b/lib/api/pages.rb -@@ -1,7 +1,7 @@ - # frozen_string_literal: true - - module API -- class Pages < Grape::API -+ class Pages < Grape::API::Instance - before do - require_pages_config_enabled! - authenticated_with_can_read_all_resources! ---- a/lib/api/pages_domains.rb -+++ b/lib/api/pages_domains.rb -@@ -1,7 +1,7 @@ - # frozen_string_literal: true - - module API -- class PagesDomains < Grape::API -+ class PagesDomains < Grape::API::Instance - include PaginationParams - - PAGES_DOMAINS_ENDPOINT_REQUIREMENTS = API::NAMESPACE_OR_PROJECT_REQUIREMENTS.merge(domain: API::NO_SLASH_URL_PART_REGEX) ---- a/lib/api/pagination_params.rb -+++ b/lib/api/pagination_params.rb -@@ -4,7 +4,7 @@ - # Concern for declare pagination params. - # - # @example -- # class CustomApiResource < Grape::API -+ # class CustomApiResource < Grape::API::Instance - # include PaginationParams - # - # params do ---- a/lib/api/pipeline_schedules.rb -+++ b/lib/api/pipeline_schedules.rb -@@ -1,7 +1,7 @@ - # frozen_string_literal: true - - module API -- class PipelineSchedules < Grape::API -+ class PipelineSchedules < Grape::API::Instance - include PaginationParams - - before { authenticate! } ---- a/lib/api/pipelines.rb -+++ b/lib/api/pipelines.rb -@@ -1,7 +1,7 @@ - # frozen_string_literal: true - - module API -- class Pipelines < Grape::API -+ class Pipelines < Grape::API::Instance - include PaginationParams - - before { authenticate_non_get! } ---- a/lib/api/project_clusters.rb -+++ b/lib/api/project_clusters.rb -@@ -1,7 +1,7 @@ - # frozen_string_literal: true - - module API -- class ProjectClusters < Grape::API -+ class ProjectClusters < Grape::API::Instance - include PaginationParams - - before { authenticate! } ---- a/lib/api/project_container_repositories.rb -+++ b/lib/api/project_container_repositories.rb -@@ -1,7 +1,7 @@ - # frozen_string_literal: true - - module API -- class ProjectContainerRepositories < Grape::API -+ class ProjectContainerRepositories < Grape::API::Instance - include PaginationParams - - REPOSITORY_ENDPOINT_REQUIREMENTS = API::NAMESPACE_OR_PROJECT_REQUIREMENTS.merge( ---- a/lib/api/project_events.rb -+++ b/lib/api/project_events.rb -@@ -1,7 +1,7 @@ - # frozen_string_literal: true - - module API -- class ProjectEvents < Grape::API -+ class ProjectEvents < Grape::API::Instance - include PaginationParams - include APIGuard - helpers ::API::Helpers::EventsHelpers ---- a/lib/api/project_export.rb -+++ b/lib/api/project_export.rb -@@ -1,7 +1,7 @@ - # frozen_string_literal: true - - module API -- class ProjectExport < Grape::API -+ class ProjectExport < Grape::API::Instance - helpers Helpers::RateLimiter - - before do ---- a/lib/api/project_hooks.rb -+++ b/lib/api/project_hooks.rb -@@ -1,7 +1,7 @@ - # frozen_string_literal: true - - module API -- class ProjectHooks < Grape::API -+ class ProjectHooks < Grape::API::Instance - include PaginationParams - - before { authenticate! } ---- a/lib/api/project_import.rb -+++ b/lib/api/project_import.rb -@@ -1,7 +1,7 @@ - # frozen_string_literal: true - - module API -- class ProjectImport < Grape::API -+ class ProjectImport < Grape::API::Instance - include PaginationParams - - MAXIMUM_FILE_SIZE = 50.megabytes ---- a/lib/api/project_milestones.rb -+++ b/lib/api/project_milestones.rb -@@ -1,7 +1,7 @@ - # frozen_string_literal: true - - module API -- class ProjectMilestones < Grape::API -+ class ProjectMilestones < Grape::API::Instance - include PaginationParams - include MilestoneResponses - ---- a/lib/api/project_repository_storage_moves.rb -+++ b/lib/api/project_repository_storage_moves.rb -@@ -1,7 +1,7 @@ - # frozen_string_literal: true - - module API -- class ProjectRepositoryStorageMoves < Grape::API -+ class ProjectRepositoryStorageMoves < Grape::API::Instance - include PaginationParams - - before { authenticated_as_admin! } ---- a/lib/api/project_snapshots.rb -+++ b/lib/api/project_snapshots.rb -@@ -1,7 +1,7 @@ - # frozen_string_literal: true - - module API -- class ProjectSnapshots < Grape::API -+ class ProjectSnapshots < Grape::API::Instance - helpers ::API::Helpers::ProjectSnapshotsHelpers - - before { authorize_read_git_snapshot! } ---- a/lib/api/project_snippets.rb -+++ b/lib/api/project_snippets.rb -@@ -1,7 +1,7 @@ - # frozen_string_literal: true - - module API -- class ProjectSnippets < Grape::API -+ class ProjectSnippets < Grape::API::Instance - include PaginationParams - - before { authenticate! } ---- a/lib/api/project_statistics.rb -+++ b/lib/api/project_statistics.rb -@@ -1,7 +1,7 @@ - # frozen_string_literal: true - - module API -- class ProjectStatistics < Grape::API -+ class ProjectStatistics < Grape::API::Instance - before do - authenticate! - authorize! :daily_statistics, user_project ---- a/lib/api/project_templates.rb -+++ b/lib/api/project_templates.rb -@@ -1,7 +1,7 @@ - # frozen_string_literal: true - - module API -- class ProjectTemplates < Grape::API -+ class ProjectTemplates < Grape::API::Instance - include PaginationParams - - TEMPLATE_TYPES = %w[dockerfiles gitignores gitlab_ci_ymls licenses].freeze ---- a/lib/api/projects.rb -+++ b/lib/api/projects.rb -@@ -3,13 +3,16 @@ - require_dependency 'declarative_policy' - - module API -- class Projects < Grape::API -+ class Projects < Grape::API::Instance - include PaginationParams - include Helpers::CustomAttributes - - helpers Helpers::ProjectsHelpers - -- before { authenticate_non_get! } -+ before do -+ authenticate_non_get! -+ coerce_nil_params_to_array! -+ end - - helpers do - # EE::API::Projects would override this method -@@ -524,7 +527,7 @@ - end - params do - optional :search, type: String, desc: 'Return list of users matching the search criteria' -- optional :skip_users, type: Array[Integer], desc: 'Filter out users with the specified IDs' -+ optional :skip_users, type: Array[Integer], coerce_with: ::API::Validations::Types::CommaSeparatedToIntegerArray.coerce, desc: 'Filter out users with the specified IDs' - use :pagination - end - get ':id/users' do ---- a/lib/api/protected_branches.rb -+++ b/lib/api/protected_branches.rb -@@ -1,7 +1,7 @@ - # frozen_string_literal: true - - module API -- class ProtectedBranches < Grape::API -+ class ProtectedBranches < Grape::API::Instance - include PaginationParams - - BRANCH_ENDPOINT_REQUIREMENTS = API::NAMESPACE_OR_PROJECT_REQUIREMENTS.merge(name: API::NO_SLASH_URL_PART_REGEX) ---- a/lib/api/protected_tags.rb -+++ b/lib/api/protected_tags.rb -@@ -1,7 +1,7 @@ - # frozen_string_literal: true - - module API -- class ProtectedTags < Grape::API -+ class ProtectedTags < Grape::API::Instance - include PaginationParams - - TAG_ENDPOINT_REQUIREMENTS = API::NAMESPACE_OR_PROJECT_REQUIREMENTS.merge(name: API::NO_SLASH_URL_PART_REGEX) ---- a/lib/api/release/links.rb -+++ b/lib/api/release/links.rb -@@ -2,7 +2,7 @@ - - module API - module Release -- class Links < Grape::API -+ class Links < Grape::API::Instance - include PaginationParams - - RELEASE_ENDPOINT_REQUIREMENTS = API::NAMESPACE_OR_PROJECT_REQUIREMENTS ---- a/lib/api/releases.rb -+++ b/lib/api/releases.rb -@@ -1,13 +1,16 @@ - # frozen_string_literal: true - - module API -- class Releases < Grape::API -+ class Releases < Grape::API::Instance - include PaginationParams - - RELEASE_ENDPOINT_REQUIREMENTS = API::NAMESPACE_OR_PROJECT_REQUIREMENTS - .merge(tag_name: API::NO_SLASH_URL_PART_REGEX) - -- before { authorize_read_releases! } -+ before do -+ authorize_read_releases! -+ coerce_nil_params_to_array! -+ end - - params do - requires :id, type: String, desc: 'The ID of a project' -@@ -54,7 +57,7 @@ - requires :url, type: String - end - end -- optional :milestones, type: Array, desc: 'The titles of the related milestones', default: [] -+ optional :milestones, type: Array[String], coerce_with: ::API::Validations::Types::CommaSeparatedToArray.coerce, desc: 'The titles of the related milestones', default: [] - optional :released_at, type: DateTime, desc: 'The date when the release will be/was ready. Defaults to the current time.' - end - route_setting :authentication, job_token_allowed: true ---- a/lib/api/remote_mirrors.rb -+++ b/lib/api/remote_mirrors.rb -@@ -1,7 +1,7 @@ - # frozen_string_literal: true - - module API -- class RemoteMirrors < Grape::API -+ class RemoteMirrors < Grape::API::Instance - include PaginationParams - - before do ---- a/lib/api/repositories.rb -+++ b/lib/api/repositories.rb -@@ -3,12 +3,15 @@ - require 'mime/types' - - module API -- class Repositories < Grape::API -+ class Repositories < Grape::API::Instance - include PaginationParams - - helpers ::API::Helpers::HeadersHelpers - -- before { authorize! :download_code, user_project } -+ before do -+ authorize! :download_code, user_project -+ coerce_nil_params_to_array! -+ end - - params do - requires :id, type: String, desc: 'The ID of a project' -@@ -143,7 +146,7 @@ - success Entities::Commit - end - params do -- requires :refs, type: Array[String] -+ requires :refs, type: Array[String], coerce_with: ::API::Validations::Types::CommaSeparatedToArray.coerce - end - get ':id/repository/merge_base' do - refs = params[:refs] ---- a/lib/api/resource_label_events.rb -+++ b/lib/api/resource_label_events.rb -@@ -1,7 +1,7 @@ - # frozen_string_literal: true - - module API -- class ResourceLabelEvents < Grape::API -+ class ResourceLabelEvents < Grape::API::Instance - include PaginationParams - helpers ::API::Helpers::NotesHelpers - ---- a/lib/api/resource_milestone_events.rb -+++ b/lib/api/resource_milestone_events.rb -@@ -1,7 +1,7 @@ - # frozen_string_literal: true - - module API -- class ResourceMilestoneEvents < Grape::API -+ class ResourceMilestoneEvents < Grape::API::Instance - include PaginationParams - helpers ::API::Helpers::NotesHelpers - ---- a/lib/api/runner.rb -+++ b/lib/api/runner.rb -@@ -1,9 +1,13 @@ - # frozen_string_literal: true - - module API -- class Runner < Grape::API -+ class Runner < Grape::API::Instance - helpers ::API::Helpers::Runner - -+ before do -+ coerce_nil_params_to_array! -+ end -+ - resource :runners do - desc 'Registers a new Runner' do - success Entities::RunnerRegistrationDetails -@@ -18,7 +22,7 @@ - optional :access_level, type: String, values: Ci::Runner.access_levels.keys, - desc: 'The access_level of the runner' - optional :run_untagged, type: Boolean, desc: 'Should Runner handle untagged jobs' -- optional :tag_list, type: Array[String], desc: %q(List of Runner's tags) -+ optional :tag_list, type: Array[String], coerce_with: ::API::Validations::Types::CommaSeparatedToArray.coerce, desc: %q(List of Runner's tags) - optional :maximum_timeout, type: Integer, desc: 'Maximum timeout set when this Runner will handle the job' - end - post '/' do ---- a/lib/api/runners.rb -+++ b/lib/api/runners.rb -@@ -1,10 +1,13 @@ - # frozen_string_literal: true - - module API -- class Runners < Grape::API -+ class Runners < Grape::API::Instance - include PaginationParams - -- before { authenticate! } -+ before do -+ authenticate! -+ coerce_nil_params_to_array! -+ end - - resource :runners do - desc 'Get runners available for user' do -@@ -17,7 +20,7 @@ - desc: 'The type of the runners to show' - optional :status, type: String, values: Ci::Runner::AVAILABLE_STATUSES, - desc: 'The status of the runners to show' -- optional :tag_list, type: Array[String], desc: 'The tags of the runners to show' -+ optional :tag_list, type: Array[String], coerce_with: ::API::Validations::Types::CommaSeparatedToArray.coerce, desc: 'The tags of the runners to show' - use :pagination - end - get do -@@ -40,7 +43,7 @@ - desc: 'The type of the runners to show' - optional :status, type: String, values: Ci::Runner::AVAILABLE_STATUSES, - desc: 'The status of the runners to show' -- optional :tag_list, type: Array[String], desc: 'The tags of the runners to show' -+ optional :tag_list, type: Array[String], coerce_with: ::API::Validations::Types::CommaSeparatedToArray.coerce, desc: 'The tags of the runners to show' - use :pagination - end - get 'all' do -@@ -75,7 +78,7 @@ - requires :id, type: Integer, desc: 'The ID of the runner' - optional :description, type: String, desc: 'The description of the runner' - optional :active, type: Boolean, desc: 'The state of a runner' -- optional :tag_list, type: Array[String], desc: 'The list of tags for a runner' -+ optional :tag_list, type: Array[String], coerce_with: ::API::Validations::Types::CommaSeparatedToArray.coerce, desc: 'The list of tags for a runner' - optional :run_untagged, type: Boolean, desc: 'Flag indicating the runner can execute untagged jobs' - optional :locked, type: Boolean, desc: 'Flag indicating the runner is locked' - optional :access_level, type: String, values: Ci::Runner.access_levels.keys, -@@ -145,7 +148,7 @@ - desc: 'The type of the runners to show' - optional :status, type: String, values: Ci::Runner::AVAILABLE_STATUSES, - desc: 'The status of the runners to show' -- optional :tag_list, type: Array[String], desc: 'The tags of the runners to show' -+ optional :tag_list, type: Array[String], coerce_with: ::API::Validations::Types::CommaSeparatedToArray.coerce, desc: 'The tags of the runners to show' - use :pagination - end - get ':id/runners' do -@@ -208,7 +211,7 @@ - desc: 'The type of the runners to show' - optional :status, type: String, values: Ci::Runner::AVAILABLE_STATUSES, - desc: 'The status of the runners to show' -- optional :tag_list, type: Array[String], desc: 'The tags of the runners to show' -+ optional :tag_list, type: Array[String], coerce_with: ::API::Validations::Types::CommaSeparatedToArray.coerce, desc: 'The tags of the runners to show' - use :pagination - end - get ':id/runners' do ---- a/lib/api/search.rb -+++ b/lib/api/search.rb -@@ -1,7 +1,7 @@ - # frozen_string_literal: true - - module API -- class Search < Grape::API -+ class Search < Grape::API::Instance - include PaginationParams - - before { authenticate! } ---- a/lib/api/services.rb -+++ b/lib/api/services.rb -@@ -1,6 +1,6 @@ - # frozen_string_literal: true - module API -- class Services < Grape::API -+ class Services < Grape::API::Instance - services = Helpers::ServicesHelpers.services - service_classes = Helpers::ServicesHelpers.service_classes - ---- a/lib/api/settings.rb -+++ b/lib/api/settings.rb -@@ -1,8 +1,11 @@ - # frozen_string_literal: true - - module API -- class Settings < Grape::API -- before { authenticated_as_admin! } -+ class Settings < Grape::API::Instance -+ before do -+ authenticated_as_admin! -+ coerce_nil_params_to_array! -+ end - - helpers Helpers::SettingsHelpers - -@@ -49,7 +52,7 @@ - optional :default_project_visibility, type: String, values: Gitlab::VisibilityLevel.string_values, desc: 'The default project visibility' - optional :default_projects_limit, type: Integer, desc: 'The maximum number of personal projects' - optional :default_snippet_visibility, type: String, values: Gitlab::VisibilityLevel.string_values, desc: 'The default snippet visibility' -- optional :disabled_oauth_sign_in_sources, type: Array[String], desc: 'Disable certain OAuth sign-in sources' -+ optional :disabled_oauth_sign_in_sources, type: Array[String], coerce_with: Validations::Types::CommaSeparatedToArray.coerce, desc: 'Disable certain OAuth sign-in sources' - optional :domain_blacklist_enabled, type: Boolean, desc: 'Enable domain blacklist for sign ups' - optional :domain_blacklist, type: Array[String], coerce_with: Validations::Types::CommaSeparatedToArray.coerce, desc: 'Users with e-mail addresses that match these domain(s) will NOT be able to sign-up. Wildcards allowed. Use separate lines for multiple entries. Ex: domain.com, *.domain.com' - optional :domain_whitelist, type: Array[String], coerce_with: Validations::Types::CommaSeparatedToArray.coerce, desc: 'ONLY users with e-mail addresses that match these domain(s) will be able to sign-up. Wildcards allowed. Use separate lines for multiple entries. Ex: domain.com, *.domain.com' -@@ -79,7 +82,8 @@ - requires :housekeeping_incremental_repack_period, type: Integer, desc: "Number of Git pushes after which an incremental 'git repack' is run." - end - optional :html_emails_enabled, type: Boolean, desc: 'By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format.' -- optional :import_sources, type: Array[String], values: %w[github bitbucket bitbucket_server gitlab google_code fogbugz git gitlab_project gitea manifest phabricator], -+ optional :import_sources, type: Array[String], coerce_with: Validations::Types::CommaSeparatedToArray.coerce, -+ values: %w[github bitbucket bitbucket_server gitlab google_code fogbugz git gitlab_project gitea manifest phabricator], - desc: 'Enabled sources for code import during project creation. OmniAuth must be configured for GitHub, Bitbucket, and GitLab.com' - optional :max_artifacts_size, type: Integer, desc: "Set the maximum file size for each job's artifacts" - optional :max_attachment_size, type: Integer, desc: 'Maximum attachment size in MB' -@@ -113,13 +117,13 @@ - requires :recaptcha_private_key, type: String, desc: 'Generate private key at http://www.google.com/recaptcha' - end - optional :repository_checks_enabled, type: Boolean, desc: "GitLab will periodically run 'git fsck' in all project and wiki repositories to look for silent disk corruption issues." -- optional :repository_storages, type: Array[String], desc: 'Storage paths for new projects' -+ optional :repository_storages, type: Array[String], coerce_with: Validations::Types::CommaSeparatedToArray.coerce, desc: 'Storage paths for new projects' - optional :repository_storages_weighted, type: Hash, desc: 'Storage paths for new projects with a weighted value between 0 and 100' - optional :require_two_factor_authentication, type: Boolean, desc: 'Require all users to set up Two-factor authentication' - given require_two_factor_authentication: ->(val) { val } do - requires :two_factor_grace_period, type: Integer, desc: 'Amount of time (in hours) that users are allowed to skip forced configuration of two-factor authentication' - end -- optional :restricted_visibility_levels, type: Array[String], desc: 'Selected levels cannot be used by non-admin users for groups, projects or snippets. If the public level is restricted, user profiles are only visible to logged in users.' -+ optional :restricted_visibility_levels, type: Array[String], coerce_with: Validations::Types::CommaSeparatedToArray.coerce, desc: 'Selected levels cannot be used by non-admin users for groups, projects or snippets. If the public level is restricted, user profiles are only visible to logged in users.' - optional :send_user_confirmation_email, type: Boolean, desc: 'Send confirmation email on sign-up' - optional :session_expire_delay, type: Integer, desc: 'Session duration in minutes. GitLab restart is required to apply changes.' - optional :shared_runners_enabled, type: Boolean, desc: 'Enable shared runners for new projects' ---- a/lib/api/sidekiq_metrics.rb -+++ b/lib/api/sidekiq_metrics.rb -@@ -3,7 +3,7 @@ - require 'sidekiq/api' - - module API -- class SidekiqMetrics < Grape::API -+ class SidekiqMetrics < Grape::API::Instance - before { authenticated_as_admin! } - - helpers do ---- a/lib/api/snippets.rb -+++ b/lib/api/snippets.rb -@@ -2,7 +2,7 @@ - - module API - # Snippets API -- class Snippets < Grape::API -+ class Snippets < Grape::API::Instance - include PaginationParams - - before { authenticate! } ---- a/lib/api/statistics.rb -+++ b/lib/api/statistics.rb -@@ -1,7 +1,7 @@ - # frozen_string_literal: true - - module API -- class Statistics < Grape::API -+ class Statistics < Grape::API::Instance - before { authenticated_as_admin! } - - COUNTED_ITEMS = [Project, User, Group, ForkNetworkMember, ForkNetwork, Issue, ---- a/lib/api/submodules.rb -+++ b/lib/api/submodules.rb -@@ -1,7 +1,7 @@ - # frozen_string_literal: true - - module API -- class Submodules < Grape::API -+ class Submodules < Grape::API::Instance - before { authenticate! } - - helpers do ---- a/lib/api/subscriptions.rb -+++ b/lib/api/subscriptions.rb -@@ -1,7 +1,7 @@ - # frozen_string_literal: true - - module API -- class Subscriptions < Grape::API -+ class Subscriptions < Grape::API::Instance - helpers ::API::Helpers::LabelHelpers - - before { authenticate! } ---- a/lib/api/suggestions.rb -+++ b/lib/api/suggestions.rb -@@ -1,7 +1,7 @@ - # frozen_string_literal: true - - module API -- class Suggestions < Grape::API -+ class Suggestions < Grape::API::Instance - before { authenticate! } - - resource :suggestions do -@@ -25,7 +25,7 @@ - success Entities::Suggestion - end - params do -- requires :ids, type: Array[String], desc: "An array of suggestion ID's" -+ requires :ids, type: Array[Integer], coerce_with: ::API::Validations::Types::CommaSeparatedToIntegerArray.coerce, desc: "An array of suggestion ID's" - end - put 'batch_apply' do - ids = params[:ids] ---- a/lib/api/system_hooks.rb -+++ b/lib/api/system_hooks.rb -@@ -1,7 +1,7 @@ - # frozen_string_literal: true - - module API -- class SystemHooks < Grape::API -+ class SystemHooks < Grape::API::Instance - include PaginationParams - - before do ---- a/lib/api/tags.rb -+++ b/lib/api/tags.rb -@@ -1,7 +1,7 @@ - # frozen_string_literal: true - - module API -- class Tags < Grape::API -+ class Tags < Grape::API::Instance - include PaginationParams - - TAG_ENDPOINT_REQUIREMENTS = API::NAMESPACE_OR_PROJECT_REQUIREMENTS.merge(tag_name: API::NO_SLASH_URL_PART_REGEX) ---- a/lib/api/templates.rb -+++ b/lib/api/templates.rb -@@ -1,7 +1,7 @@ - # frozen_string_literal: true - - module API -- class Templates < Grape::API -+ class Templates < Grape::API::Instance - include PaginationParams - - GLOBAL_TEMPLATE_TYPES = { ---- a/lib/api/terraform/state.rb -+++ b/lib/api/terraform/state.rb -@@ -4,7 +4,7 @@ - - module API - module Terraform -- class State < Grape::API -+ class State < Grape::API::Instance - include ::Gitlab::Utils::StrongMemoize - - default_format :json ---- a/lib/api/todos.rb -+++ b/lib/api/todos.rb -@@ -1,7 +1,7 @@ - # frozen_string_literal: true - - module API -- class Todos < Grape::API -+ class Todos < Grape::API::Instance - include PaginationParams - - before { authenticate! } ---- a/lib/api/triggers.rb -+++ b/lib/api/triggers.rb -@@ -1,7 +1,7 @@ - # frozen_string_literal: true - - module API -- class Triggers < Grape::API -+ class Triggers < Grape::API::Instance - include PaginationParams - - HTTP_GITLAB_EVENT_HEADER = "HTTP_#{WebHookService::GITLAB_EVENT_HEADER}".underscore.upcase ---- a/lib/api/user_counts.rb -+++ b/lib/api/user_counts.rb -@@ -1,7 +1,7 @@ - # frozen_string_literal: true - - module API -- class UserCounts < Grape::API -+ class UserCounts < Grape::API::Instance - resource :user_counts do - desc 'Return the user specific counts' do - detail 'Open MR Count' ---- a/lib/api/users.rb -+++ b/lib/api/users.rb -@@ -1,7 +1,7 @@ - # frozen_string_literal: true - - module API -- class Users < Grape::API -+ class Users < Grape::API::Instance - include PaginationParams - include APIGuard - include Helpers::CustomAttributes ---- a/lib/api/validations/types/comma_separated_to_array.rb -+++ b/lib/api/validations/types/comma_separated_to_array.rb -@@ -10,7 +10,7 @@ - when String - value.split(',').map(&:strip) - when Array -- value.map { |v| v.to_s.split(',').map(&:strip) }.flatten -+ value.flat_map { |v| v.to_s.split(',').map(&:strip) } - else - [] - end ---- /dev/null -+++ b/lib/api/validations/types/comma_separated_to_integer_array.rb -@@ -0,0 +1,15 @@ -+# frozen_string_literal: true -+ -+module API -+ module Validations -+ module Types -+ class CommaSeparatedToIntegerArray < CommaSeparatedToArray -+ def self.coerce -+ lambda do |value| -+ super.call(value).map(&:to_i) -+ end -+ end -+ end -+ end -+ end -+end ---- a/lib/api/validations/types/labels_list.rb -+++ /dev/null -@@ -1,24 +0,0 @@ --# frozen_string_literal: true -- --module API -- module Validations -- module Types -- class LabelsList -- def self.coerce -- lambda do |value| -- case value -- when String -- value.split(',').map(&:strip) -- when Array -- value.flat_map { |v| v.to_s.split(',').map(&:strip) } -- when LabelsList -- value -- else -- [] -- end -- end -- end -- end -- end -- end --end ---- a/lib/api/validations/types/safe_file.rb -+++ /dev/null -@@ -1,15 +0,0 @@ --# frozen_string_literal: true -- --# This module overrides the Grape type validator defined in --# https://github.com/ruby-grape/grape/blob/master/lib/grape/validations/types/file.rb --module API -- module Validations -- module Types -- class SafeFile < ::Grape::Validations::Types::File -- def value_coerced?(value) -- super && value[:tempfile].is_a?(Tempfile) -- end -- end -- end -- end --end ---- a/lib/api/validations/types/workhorse_file.rb -+++ b/lib/api/validations/types/workhorse_file.rb -@@ -3,15 +3,14 @@ - module API - module Validations - module Types -- class WorkhorseFile < Virtus::Attribute -- def coerce(input) -- # Processing of multipart file objects -- # is already taken care of by Gitlab::Middleware::Multipart. -- # Nothing to do here. -- input -+ class WorkhorseFile -+ def self.parse(value) -+ raise "#{value.class} is not an UploadedFile type" unless parsed?(value) -+ -+ value - end - -- def value_coerced?(value) -+ def self.parsed?(value) - value.is_a?(::UploadedFile) - end - end ---- a/lib/api/variables.rb -+++ b/lib/api/variables.rb -@@ -1,7 +1,7 @@ - # frozen_string_literal: true - - module API -- class Variables < Grape::API -+ class Variables < Grape::API::Instance - include PaginationParams - - before { authenticate! } ---- a/lib/api/version.rb -+++ b/lib/api/version.rb -@@ -1,7 +1,7 @@ - # frozen_string_literal: true - - module API -- class Version < Grape::API -+ class Version < Grape::API::Instance - helpers ::API::Helpers::GraphqlHelpers - include APIGuard - ---- a/lib/api/wikis.rb -+++ b/lib/api/wikis.rb -@@ -1,7 +1,7 @@ - # frozen_string_literal: true - - module API -- class Wikis < Grape::API -+ class Wikis < Grape::API::Instance - helpers do - def commit_params(attrs) - # In order to avoid service disruption this can work with an old workhorse without the acceleration -@@ -117,7 +117,7 @@ - success Entities::WikiAttachment - end - params do -- requires :file, types: [::API::Validations::Types::SafeFile, ::API::Validations::Types::WorkhorseFile], desc: 'The attachment file to be uploaded' -+ requires :file, types: [Rack::Multipart::UploadedFile, ::API::Validations::Types::WorkhorseFile], desc: 'The attachment file to be uploaded' - optional :branch, type: String, desc: 'The name of the branch' - end - post ":id/wikis/attachments" do ---- /dev/null -+++ b/rubocop/cop/api/grape_api_instance.rb -@@ -0,0 +1,42 @@ -+# frozen_string_literal: true -+ -+module RuboCop -+ module Cop -+ module API -+ class GrapeAPIInstance < RuboCop::Cop::Cop -+ # This cop checks that APIs subclass Grape::API::Instance with Grape v1.3+. -+ # -+ # @example -+ # -+ # # bad -+ # module API -+ # class Projects < Grape::API -+ # end -+ # end -+ # -+ # # good -+ # module API -+ # class Projects < Grape::API::Instance -+ # end -+ # end -+ MSG = 'Inherit from Grape::API::Instance instead of Grape::API. ' \ -+ 'For more details check the https://gitlab.com/gitlab-org/gitlab/-/issues/215230.' -+ -+ def_node_matcher :grape_api_definition, <<~PATTERN -+ (class -+ (const _ _) -+ (const -+ (const nil? :Grape) :API) -+ ... -+ ) -+ PATTERN -+ -+ def on_class(node) -+ grape_api_definition(node) do -+ add_offense(node.children[1]) -+ end -+ end -+ end -+ end -+ end -+end ---- /dev/null -+++ b/rubocop/cop/api/grape_array_missing_coerce.rb -@@ -0,0 +1,83 @@ -+# frozen_string_literal: true -+ -+module RuboCop -+ module Cop -+ module API -+ class GrapeArrayMissingCoerce < RuboCop::Cop::Cop -+ # This cop checks that Grape API parameters using an Array type -+ # implement a coerce_with method: -+ # -+ # https://github.com/ruby-grape/grape/blob/master/UPGRADING.md#ensure-that-array-types-have-explicit-coercions -+ # -+ # @example -+ # -+ # # bad -+ # requires :values, type: Array[String] -+ # -+ # # good -+ # requires :values, type: Array[String], coerce_with: Validations::Types::CommaSeparatedToArray.coerce -+ # -+ # end -+ MSG = 'This Grape parameter defines an Array but is missing a coerce_with definition. ' \ -+ 'For more details, see https://github.com/ruby-grape/grape/blob/master/UPGRADING.md#ensure-that-array-types-have-explicit-coercions' -+ -+ def_node_matcher :grape_api_instance?, <<~PATTERN -+ (class -+ (const _ _) -+ (const -+ (const -+ (const nil? :Grape) :API) :Instance) -+ ... -+ ) -+ PATTERN -+ -+ def_node_matcher :grape_api_param_block?, <<~PATTERN -+ (send _ {:requires :optional} -+ (sym _) -+ $_) -+ PATTERN -+ -+ def_node_matcher :grape_type_def?, <<~PATTERN -+ (sym :type) -+ PATTERN -+ -+ def_node_matcher :grape_array_type?, <<~PATTERN -+ (send -+ (const nil? :Array) :[] -+ (const nil? _)) -+ PATTERN -+ -+ def_node_matcher :grape_coerce_with?, <<~PATTERN -+ (sym :coerce_with) -+ PATTERN -+ -+ def on_class(node) -+ @grape_api ||= grape_api_instance?(node) -+ end -+ -+ def on_send(node) -+ return unless @grape_api -+ -+ match = grape_api_param_block?(node) -+ -+ return unless match.is_a?(RuboCop::AST::HashNode) -+ -+ is_array_type = false -+ has_coerce_method = false -+ -+ match.each_pair do |first, second| -+ has_coerce_method ||= grape_coerce_with?(first) -+ -+ if grape_type_def?(first) && grape_array_type?(second) -+ is_array_type = true -+ end -+ end -+ -+ if is_array_type && !has_coerce_method -+ add_offense(node) -+ end -+ end -+ end -+ end -+ end -+end ---- a/spec/requests/api/settings_spec.rb -+++ b/spec/requests/api/settings_spec.rb -@@ -62,14 +62,14 @@ - default_projects_limit: 3, - default_project_creation: 2, - password_authentication_enabled_for_web: false, -- repository_storages: ['custom'], -+ repository_storages: 'custom', - plantuml_enabled: true, - plantuml_url: 'http://plantuml.example.com', - sourcegraph_enabled: true, - sourcegraph_url: 'https://sourcegraph.com', - sourcegraph_public_only: false, - default_snippet_visibility: 'internal', -- restricted_visibility_levels: ['public'], -+ restricted_visibility_levels: 'public', - default_artifacts_expire_in: '2 days', - help_page_text: 'custom help text', - help_page_hide_commercial_content: true, -@@ -94,7 +94,9 @@ - issues_create_limit: 300, - raw_blob_request_limit: 300, - spam_check_endpoint_enabled: true, -- spam_check_endpoint_url: 'https://example.com/spam_check' -+ spam_check_endpoint_url: 'https://example.com/spam_check', -+ disabled_oauth_sign_in_sources: 'unknown', -+ import_sources: 'github,bitbucket' - } - - expect(response).to have_gitlab_http_status(:ok) -@@ -135,6 +137,8 @@ - expect(json_response['raw_blob_request_limit']).to eq(300) - expect(json_response['spam_check_endpoint_enabled']).to be_truthy - expect(json_response['spam_check_endpoint_url']).to eq('https://example.com/spam_check') -+ expect(json_response['disabled_oauth_sign_in_sources']).to eq([]) -+ expect(json_response['import_sources']).to match_array(%w(github bitbucket)) - end - end - ---- /dev/null -+++ b/spec/rubocop/cop/api/grape_api_instance_spec.rb -@@ -0,0 +1,31 @@ -+# frozen_string_literal: true -+ -+require 'fast_spec_helper' -+require 'rubocop' -+require_relative '../../../support/helpers/expect_offense' -+require_relative '../../../../rubocop/cop/api/grape_api_instance' -+ -+describe RuboCop::Cop::API::GrapeAPIInstance do -+ include CopHelper -+ include ExpectOffense -+ -+ subject(:cop) { described_class.new } -+ -+ it 'adds an offense when inheriting from Grape::API' do -+ inspect_source(<<~CODE) -+ class SomeAPI < Grape::API -+ end -+ CODE -+ -+ expect(cop.offenses.size).to eq(1) -+ end -+ -+ it 'does not add an offense when inheriting from Grape::API::Instance' do -+ inspect_source(<<~CODE) -+ class SomeAPI < Grape::API::Instance -+ end -+ CODE -+ -+ expect(cop.offenses.size).to be_zero -+ end -+end ---- /dev/null -+++ b/spec/rubocop/cop/api/grape_array_missing_coerce_spec.rb -@@ -0,0 +1,64 @@ -+# frozen_string_literal: true -+ -+require 'fast_spec_helper' -+require 'rubocop' -+require_relative '../../../support/helpers/expect_offense' -+require_relative '../../../../rubocop/cop/api/grape_array_missing_coerce' -+ -+describe RuboCop::Cop::API::GrapeArrayMissingCoerce do -+ include CopHelper -+ include ExpectOffense -+ -+ subject(:cop) { described_class.new } -+ -+ it 'adds an offense with a required parameter' do -+ inspect_source(<<~CODE) -+ class SomeAPI < Grape::API::Instance -+ params do -+ requires :values, type: Array[String] -+ end -+ end -+ CODE -+ -+ expect(cop.offenses.size).to eq(1) -+ end -+ -+ it 'adds an offense with an optional parameter' do -+ inspect_source(<<~CODE) -+ class SomeAPI < Grape::API::Instance -+ params do -+ optional :values, type: Array[String] -+ end -+ end -+ CODE -+ -+ expect(cop.offenses.size).to eq(1) -+ end -+ -+ it 'does not add an offense' do -+ inspect_source(<<~CODE) -+ class SomeAPI < Grape::API::Instance -+ params do -+ requires :values, type: Array[String], coerce_with: ->(val) { val.split(',').map(&:strip) } -+ requires :milestone, type: String, desc: 'Milestone title' -+ optional :assignee_id, types: [Integer, String], integer_none_any: true, -+ desc: 'Return issues which are assigned to the user with the given ID' -+ end -+ end -+ CODE -+ -+ expect(cop.offenses.size).to be_zero -+ end -+ -+ it 'does not add an offense for unrelated classes' do -+ inspect_source(<<~CODE) -+ class SomeClass -+ params do -+ requires :values, type: Array[String] -+ end -+ end -+ CODE -+ -+ expect(cop.offenses.size).to be_zero -+ end -+end ---- a/spec/rubocop/cop/code_reuse/worker_spec.rb -+++ b/spec/rubocop/cop/code_reuse/worker_spec.rb -@@ -31,7 +31,7 @@ - .and_return(true) - - expect_offense(<<~SOURCE) -- class Foo < Grape::API -+ class Foo < Grape::API::Instance - resource :projects do - get '/' do - FooWorker.perform_async ---- a/lib/api/helpers/common_helpers.rb -+++ b/lib/api/helpers/common_helpers.rb -@@ -12,6 +12,26 @@ - end - end - end -+ -+ # Grape v1.3.3 no longer automatically coerces an Array -+ # type to an empty array if the value is nil. -+ def coerce_nil_params_to_array! -+ keys_to_coerce = params_with_array_types -+ -+ params.each do |key, val| -+ params[key] = Array(val) if val.nil? && keys_to_coerce.include?(key) -+ end -+ end -+ -+ def params_with_array_types -+ options[:route_options][:params].map do |key, val| -+ param_type = val[:type] -+ # Search for parameters with Array types (e.g. "[String]", "[Integer]", etc.) -+ if param_type =~ %r(\[\w*\]) -+ key -+ end -+ end.compact.to_set -+ end - end - end - end ---- a/spec/requests/api/applications_spec.rb -+++ b/spec/requests/api/applications_spec.rb -@@ -74,14 +74,15 @@ - expect(json_response['error']).to eq('scopes is missing') - end - -- it 'does not allow creating an application with confidential set to nil' do -+ it 'defaults to creating an application with confidential' do - expect do - post api('/applications', admin_user), params: { name: 'application_name', redirect_uri: 'http://application.url', scopes: '', confidential: nil } -- end.not_to change { Doorkeeper::Application.count } -+ end.to change { Doorkeeper::Application.count }.by(1) - -- expect(response).to have_gitlab_http_status(:bad_request) -+ expect(response).to have_gitlab_http_status(:created) - expect(json_response).to be_a Hash -- expect(json_response['message']['confidential'].first).to eq('is not included in the list') -+ expect(json_response['callback_url']).to eq('http://application.url') -+ expect(json_response['confidential']).to be true - end - end - diff --git a/debian/patches/0790-protobuf-compat.patch b/debian/patches/0790-protobuf-compat.patch index 06f5c441fd..577cd22830 100644 --- a/debian/patches/0790-protobuf-compat.patch +++ b/debian/patches/0790-protobuf-compat.patch @@ -15,6 +15,6 @@ Subject: [PATCH 2/2] Fix protobuf compatibility (Thanks to Stan Hu) { - repository: repository.gitaly_repository, + repository: repository.gitaly_repository.to_h, - address: Gitlab::GitalyClient.address(container.repository_storage), - token: Gitlab::GitalyClient.token(container.repository_storage), + address: Gitlab::GitalyClient.address(repository.shard), + token: Gitlab::GitalyClient.token(repository.shard), features: Feature::Gitaly.server_feature_flags diff --git a/debian/patches/series b/debian/patches/series index 3d445b75dc..3107ccd3e5 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -22,7 +22,5 @@ 0700-add-salsa-link-to-help.patch 0710-use-yarnpkg.patch 0740-use-packaged-modules.patch -0741-add-graphql-tag.patch 0750-fix-relative-paths.patch -0760-update-grape.patch 0790-protobuf-compat.patch