Commit 3ee4aa9c authored by Douglas Barbosa Alexandre's avatar Douglas Barbosa Alexandre

Merge branch '31034-upgrade-to-rails-6' into 'master'

Upgrade to Rails 6

Closes #30030 and #31034

See merge request gitlab-org/gitlab!19891
parents b51d01ff 80661f8b
...@@ -235,12 +235,6 @@ RSpec/FactoriesInMigrationSpecs: ...@@ -235,12 +235,6 @@ RSpec/FactoriesInMigrationSpecs:
- 'spec/lib/ee/gitlab/background_migration/**/*.rb' - 'spec/lib/ee/gitlab/background_migration/**/*.rb'
- 'ee/spec/lib/ee/gitlab/background_migration/**/*.rb' - 'ee/spec/lib/ee/gitlab/background_migration/**/*.rb'
Cop/IncludeActionViewContext:
Enabled: true
Exclude:
- 'spec/**/*'
- 'ee/spec/**/*'
Cop/IncludeSidekiqWorker: Cop/IncludeSidekiqWorker:
Enabled: true Enabled: true
Exclude: Exclude:
......
source 'https://rubygems.org' source 'https://rubygems.org'
gem 'rails', '5.2.3' gem 'rails', '6.0.2'
gem 'bootsnap', '~> 1.4' gem 'bootsnap', '~> 1.4'
...@@ -305,7 +305,7 @@ gem 'gitlab-labkit', '0.9.1' ...@@ -305,7 +305,7 @@ gem 'gitlab-labkit', '0.9.1'
# I18n # I18n
gem 'ruby_parser', '~> 3.8', require: false gem 'ruby_parser', '~> 3.8', require: false
gem 'rails-i18n', '~> 5.1' gem 'rails-i18n', '~> 6.0'
gem 'gettext_i18n_rails', '~> 1.8.0' gem 'gettext_i18n_rails', '~> 1.8.0'
gem 'gettext_i18n_rails_js', '~> 1.3' gem 'gettext_i18n_rails_js', '~> 1.3'
gem 'gettext', '~> 3.2.2', require: false, group: :development gem 'gettext', '~> 3.2.2', require: false, group: :development
...@@ -332,6 +332,7 @@ group :metrics do ...@@ -332,6 +332,7 @@ group :metrics do
end end
group :development do group :development do
gem 'listen', '~> 3.0'
gem 'brakeman', '~> 4.2', require: false gem 'brakeman', '~> 4.2', require: false
gem 'danger', '~> 6.0', require: false gem 'danger', '~> 6.0', require: false
......
...@@ -6,50 +6,64 @@ GEM ...@@ -6,50 +6,64 @@ GEM
ace-rails-ap (4.1.2) ace-rails-ap (4.1.2)
acme-client (2.0.5) acme-client (2.0.5)
faraday (~> 0.9, >= 0.9.1) faraday (~> 0.9, >= 0.9.1)
actioncable (5.2.3) actioncable (6.0.2)
actionpack (= 5.2.3) actionpack (= 6.0.2)
nio4r (~> 2.0) nio4r (~> 2.0)
websocket-driver (>= 0.6.1) websocket-driver (>= 0.6.1)
actionmailer (5.2.3) actionmailbox (6.0.2)
actionpack (= 5.2.3) actionpack (= 6.0.2)
actionview (= 5.2.3) activejob (= 6.0.2)
activejob (= 5.2.3) activerecord (= 6.0.2)
activestorage (= 6.0.2)
activesupport (= 6.0.2)
mail (>= 2.7.1)
actionmailer (6.0.2)
actionpack (= 6.0.2)
actionview (= 6.0.2)
activejob (= 6.0.2)
mail (~> 2.5, >= 2.5.4) mail (~> 2.5, >= 2.5.4)
rails-dom-testing (~> 2.0) rails-dom-testing (~> 2.0)
actionpack (5.2.3) actionpack (6.0.2)
actionview (= 5.2.3) actionview (= 6.0.2)
activesupport (= 5.2.3) activesupport (= 6.0.2)
rack (~> 2.0) rack (~> 2.0)
rack-test (>= 0.6.3) rack-test (>= 0.6.3)
rails-dom-testing (~> 2.0) rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.0, >= 1.0.2) rails-html-sanitizer (~> 1.0, >= 1.2.0)
actionview (5.2.3) actiontext (6.0.2)
activesupport (= 5.2.3) actionpack (= 6.0.2)
activerecord (= 6.0.2)
activestorage (= 6.0.2)
activesupport (= 6.0.2)
nokogiri (>= 1.8.5)
actionview (6.0.2)
activesupport (= 6.0.2)
builder (~> 3.1) builder (~> 3.1)
erubi (~> 1.4) erubi (~> 1.4)
rails-dom-testing (~> 2.0) rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.0, >= 1.0.3) rails-html-sanitizer (~> 1.1, >= 1.2.0)
activejob (5.2.3) activejob (6.0.2)
activesupport (= 5.2.3) activesupport (= 6.0.2)
globalid (>= 0.3.6) globalid (>= 0.3.6)
activemodel (5.2.3) activemodel (6.0.2)
activesupport (= 5.2.3) activesupport (= 6.0.2)
activerecord (5.2.3) activerecord (6.0.2)
activemodel (= 5.2.3) activemodel (= 6.0.2)
activesupport (= 5.2.3) activesupport (= 6.0.2)
arel (>= 9.0)
activerecord-explain-analyze (0.1.0) activerecord-explain-analyze (0.1.0)
activerecord (>= 4) activerecord (>= 4)
pg pg
activestorage (5.2.3) activestorage (6.0.2)
actionpack (= 5.2.3) actionpack (= 6.0.2)
activerecord (= 5.2.3) activejob (= 6.0.2)
activerecord (= 6.0.2)
marcel (~> 0.3.1) marcel (~> 0.3.1)
activesupport (5.2.3) activesupport (6.0.2)
concurrent-ruby (~> 1.0, >= 1.0.2) concurrent-ruby (~> 1.0, >= 1.0.2)
i18n (>= 0.7, < 2) i18n (>= 0.7, < 2)
minitest (~> 5.1) minitest (~> 5.1)
tzinfo (~> 1.1) tzinfo (~> 1.1)
zeitwerk (~> 2.2)
acts-as-taggable-on (6.5.0) acts-as-taggable-on (6.5.0)
activerecord (>= 5.0, < 6.1) activerecord (>= 5.0, < 6.1)
adamantium (0.2.0) adamantium (0.2.0)
...@@ -62,7 +76,6 @@ GEM ...@@ -62,7 +76,6 @@ GEM
apollo_upload_server (2.0.0.beta.3) apollo_upload_server (2.0.0.beta.3)
graphql (>= 1.8) graphql (>= 1.8)
rails (>= 4.2) rails (>= 4.2)
arel (9.0.0)
asana (0.9.3) asana (0.9.3)
faraday (~> 0.9) faraday (~> 0.9)
faraday_middleware (~> 0.9) faraday_middleware (~> 0.9)
...@@ -198,13 +211,14 @@ GEM ...@@ -198,13 +211,14 @@ GEM
declarative-option (0.1.0) declarative-option (0.1.0)
default_value_for (3.3.0) default_value_for (3.3.0)
activerecord (>= 3.2.0, < 6.1) activerecord (>= 3.2.0, < 6.1)
derailed_benchmarks (1.3.5) derailed_benchmarks (1.4.2)
benchmark-ips (~> 2) benchmark-ips (~> 2)
get_process_mem (~> 0) get_process_mem (~> 0)
heapy (~> 0) heapy (~> 0)
memory_profiler (~> 0) memory_profiler (~> 0)
rack (>= 1) rack (>= 1)
rake (> 10, < 13) rake (> 10, < 14)
ruby-statistics (>= 2.1)
thor (~> 0.19) thor (~> 0.19)
descendants_tracker (0.0.4) descendants_tracker (0.0.4)
thread_safe (~> 0.3, >= 0.3.1) thread_safe (~> 0.3, >= 0.3.1)
...@@ -348,7 +362,8 @@ GEM ...@@ -348,7 +362,8 @@ GEM
gemoji (3.0.1) gemoji (3.0.1)
gemojione (3.3.0) gemojione (3.3.0)
json json
get_process_mem (0.2.3) get_process_mem (0.2.5)
ffi (~> 1.0)
gettext (3.2.9) gettext (3.2.9)
locale (>= 2.0.5) locale (>= 2.0.5)
text (>= 1.3.0) text (>= 1.3.0)
...@@ -434,8 +449,9 @@ GEM ...@@ -434,8 +449,9 @@ GEM
activesupport activesupport
grape (~> 1.0) grape (~> 1.0)
rake (~> 12) rake (~> 12)
grape_logging (1.7.0) grape_logging (1.8.3)
grape grape
rack
graphiql-rails (1.4.10) graphiql-rails (1.4.10)
railties railties
sprockets-rails sprockets-rails
...@@ -510,7 +526,7 @@ GEM ...@@ -510,7 +526,7 @@ GEM
mime-types (~> 3.0) mime-types (~> 3.0)
multi_xml (>= 0.5.2) multi_xml (>= 0.5.2)
httpclient (2.8.3) httpclient (2.8.3)
i18n (1.7.1) i18n (1.7.0)
concurrent-ruby (~> 1.0) concurrent-ruby (~> 1.0)
i18n_data (0.8.0) i18n_data (0.8.0)
icalendar (2.4.1) icalendar (2.4.1)
...@@ -609,12 +625,12 @@ GEM ...@@ -609,12 +625,12 @@ GEM
memoist (0.16.0) memoist (0.16.0)
memoizable (0.4.2) memoizable (0.4.2)
thread_safe (~> 0.3, >= 0.3.1) thread_safe (~> 0.3, >= 0.3.1)
memory_profiler (0.9.13) memory_profiler (0.9.14)
method_source (0.9.2) method_source (0.9.2)
mime-types (3.2.2) mime-types (3.2.2)
mime-types-data (~> 3.2015) mime-types-data (~> 3.2015)
mime-types-data (3.2019.0331) mime-types-data (3.2019.0331)
mimemagic (0.3.2) mimemagic (0.3.3)
mini_magick (4.9.5) mini_magick (4.9.5)
mini_mime (1.0.2) mini_mime (1.0.2)
mini_portile2 (2.4.0) mini_portile2 (2.4.0)
...@@ -787,18 +803,20 @@ GEM ...@@ -787,18 +803,20 @@ GEM
rack-test (1.1.0) rack-test (1.1.0)
rack (>= 1.0, < 3) rack (>= 1.0, < 3)
rack-timeout (0.5.1) rack-timeout (0.5.1)
rails (5.2.3) rails (6.0.2)
actioncable (= 5.2.3) actioncable (= 6.0.2)
actionmailer (= 5.2.3) actionmailbox (= 6.0.2)
actionpack (= 5.2.3) actionmailer (= 6.0.2)
actionview (= 5.2.3) actionpack (= 6.0.2)
activejob (= 5.2.3) actiontext (= 6.0.2)
activemodel (= 5.2.3) actionview (= 6.0.2)
activerecord (= 5.2.3) activejob (= 6.0.2)
activestorage (= 5.2.3) activemodel (= 6.0.2)
activesupport (= 5.2.3) activerecord (= 6.0.2)
activestorage (= 6.0.2)
activesupport (= 6.0.2)
bundler (>= 1.3.0) bundler (>= 1.3.0)
railties (= 5.2.3) railties (= 6.0.2)
sprockets-rails (>= 2.0.0) sprockets-rails (>= 2.0.0)
rails-controller-testing (1.0.4) rails-controller-testing (1.0.4)
actionpack (>= 5.0.1.x) actionpack (>= 5.0.1.x)
...@@ -809,15 +827,15 @@ GEM ...@@ -809,15 +827,15 @@ GEM
nokogiri (>= 1.6) nokogiri (>= 1.6)
rails-html-sanitizer (1.3.0) rails-html-sanitizer (1.3.0)
loofah (~> 2.3) loofah (~> 2.3)
rails-i18n (5.1.1) rails-i18n (6.0.0)
i18n (>= 0.7, < 2) i18n (>= 0.7, < 2)
railties (>= 5.0, < 6) railties (>= 6.0.0, < 7)
railties (5.2.3) railties (6.0.2)
actionpack (= 5.2.3) actionpack (= 6.0.2)
activesupport (= 5.2.3) activesupport (= 6.0.2)
method_source method_source
rake (>= 0.8.7) rake (>= 0.8.7)
thor (>= 0.19.0, < 2.0) thor (>= 0.20.3, < 2.0)
rainbow (3.0.0) rainbow (3.0.0)
raindrops (0.19.0) raindrops (0.19.0)
rake (12.3.3) rake (12.3.3)
...@@ -937,6 +955,7 @@ GEM ...@@ -937,6 +955,7 @@ GEM
ruby-progressbar (1.10.1) ruby-progressbar (1.10.1)
ruby-saml (1.7.2) ruby-saml (1.7.2)
nokogiri (>= 1.5.10) nokogiri (>= 1.5.10)
ruby-statistics (2.1.1)
ruby_dep (1.5.0) ruby_dep (1.5.0)
ruby_parser (3.13.1) ruby_parser (3.13.1)
sexp_processor (~> 4.9) sexp_processor (~> 4.9)
...@@ -1111,9 +1130,9 @@ GEM ...@@ -1111,9 +1130,9 @@ GEM
hashdiff hashdiff
webpack-rails (0.9.11) webpack-rails (0.9.11)
railties (>= 3.2.0) railties (>= 3.2.0)
websocket-driver (0.7.0) websocket-driver (0.7.1)
websocket-extensions (>= 0.1.0) websocket-extensions (>= 0.1.0)
websocket-extensions (0.1.3) websocket-extensions (0.1.4)
wikicloth (0.8.1) wikicloth (0.8.1)
builder builder
expression_parser expression_parser
...@@ -1122,6 +1141,7 @@ GEM ...@@ -1122,6 +1141,7 @@ GEM
xml-simple (1.1.5) xml-simple (1.1.5)
xpath (3.2.0) xpath (3.2.0)
nokogiri (~> 1.8) nokogiri (~> 1.8)
zeitwerk (2.2.2)
PLATFORMS PLATFORMS
ruby ruby
...@@ -1259,6 +1279,7 @@ DEPENDENCIES ...@@ -1259,6 +1279,7 @@ DEPENDENCIES
license_finder (~> 5.4) license_finder (~> 5.4)
licensee (~> 8.9) licensee (~> 8.9)
liquid (~> 4.0) liquid (~> 4.0)
listen (~> 3.0)
lograge (~> 0.5) lograge (~> 0.5)
loofah (~> 2.2) loofah (~> 2.2)
lru_redux lru_redux
...@@ -1309,9 +1330,9 @@ DEPENDENCIES ...@@ -1309,9 +1330,9 @@ DEPENDENCIES
rack-oauth2 (~> 1.9.3) rack-oauth2 (~> 1.9.3)
rack-proxy (~> 0.6.0) rack-proxy (~> 0.6.0)
rack-timeout rack-timeout
rails (= 5.2.3) rails (= 6.0.2)
rails-controller-testing rails-controller-testing
rails-i18n (~> 5.1) rails-i18n (~> 6.0)
rainbow (~> 3.0) rainbow (~> 3.0)
raindrops (~> 0.18) raindrops (~> 0.18)
rblineprof (~> 0.3.6) rblineprof (~> 0.3.6)
......
...@@ -120,7 +120,7 @@ class ApplicationController < ActionController::Base ...@@ -120,7 +120,7 @@ class ApplicationController < ActionController::Base
def render(*args) def render(*args)
super.tap do super.tap do
# Set a header for custom error pages to prevent them from being intercepted by gitlab-workhorse # Set a header for custom error pages to prevent them from being intercepted by gitlab-workhorse
if (400..599).cover?(response.status) && workhorse_excluded_content_types.include?(response.content_type) if (400..599).cover?(response.status) && workhorse_excluded_content_types.include?(response.media_type)
response.headers['X-GitLab-Custom-Error'] = '1' response.headers['X-GitLab-Custom-Error'] = '1'
end end
end end
......
...@@ -21,9 +21,9 @@ module MembershipActions ...@@ -21,9 +21,9 @@ module MembershipActions
member = Members::UpdateService member = Members::UpdateService
.new(current_user, update_params) .new(current_user, update_params)
.execute(member) .execute(member)
.present(current_user: current_user)
present_members([member]) member = present_members([member]).first
respond_to do |format| respond_to do |format|
format.js { render 'shared/members/update', locals: { member: member } } format.js { render 'shared/members/update', locals: { member: member } }
end end
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
module SendFileUpload module SendFileUpload
def send_upload(file_upload, send_params: {}, redirect_params: {}, attachment: nil, proxy: false, disposition: 'attachment') def send_upload(file_upload, send_params: {}, redirect_params: {}, attachment: nil, proxy: false, disposition: 'attachment')
if attachment if attachment
response_disposition = ::Gitlab::ContentDisposition.format(disposition: disposition, filename: attachment) response_disposition = ActionDispatch::Http::ContentDisposition.format(disposition: disposition, filename: attachment)
# Response-Content-Type will not override an existing Content-Type in # Response-Content-Type will not override an existing Content-Type in
# Google Cloud Storage, so the metadata needs to be cleared on GCS for # Google Cloud Storage, so the metadata needs to be cleared on GCS for
...@@ -15,7 +15,7 @@ module SendFileUpload ...@@ -15,7 +15,7 @@ module SendFileUpload
# cross-origin JavaScript protection. # cross-origin JavaScript protection.
send_params[:content_type] = 'text/plain' if File.extname(attachment) == '.js' send_params[:content_type] = 'text/plain' if File.extname(attachment) == '.js'
send_params.merge!(filename: attachment, disposition: utf8_encoded_disposition(disposition, attachment)) send_params.merge!(filename: attachment, disposition: disposition)
end end
if file_upload.file_storage? if file_upload.file_storage?
...@@ -28,18 +28,6 @@ module SendFileUpload ...@@ -28,18 +28,6 @@ module SendFileUpload
end end
end end
# Since Rails 5 doesn't properly support support non-ASCII filenames,
# we have to add our own to ensure RFC 5987 compliance. However, Rails
# 5 automatically appends `filename#{filename}` here:
# https://github.com/rails/rails/blob/v5.0.7/actionpack/lib/action_controller/metal/data_streaming.rb#L137
# Rails 6 will have https://github.com/rails/rails/pull/33829, so we
# can get rid of this special case handling when we upgrade.
def utf8_encoded_disposition(disposition, filename)
content = ::Gitlab::ContentDisposition.new(disposition: disposition, filename: filename)
"#{disposition}; #{content.utf8_filename}"
end
def guess_content_type(filename) def guess_content_type(filename)
types = MIME::Types.type_for(filename) types = MIME::Types.type_for(filename)
......
...@@ -4,7 +4,7 @@ require 'nokogiri' ...@@ -4,7 +4,7 @@ require 'nokogiri'
module MarkupHelper module MarkupHelper
include ActionView::Helpers::TextHelper include ActionView::Helpers::TextHelper
include ::Gitlab::ActionViewOutput::Context include ActionView::Context
def plain?(filename) def plain?(filename)
Gitlab::MarkupHelper.plain?(filename) Gitlab::MarkupHelper.plain?(filename)
......
...@@ -200,6 +200,10 @@ class CommitStatus < ApplicationRecord ...@@ -200,6 +200,10 @@ class CommitStatus < ApplicationRecord
update_all('processed=TRUE, lock_version=COALESCE(lock_version,0)+1') update_all('processed=TRUE, lock_version=COALESCE(lock_version,0)+1')
end end
def self.locking_enabled?
false
end
def locking_enabled? def locking_enabled?
will_save_change_to_status? will_save_change_to_status?
end end
......
...@@ -130,6 +130,10 @@ module Issuable ...@@ -130,6 +130,10 @@ module Issuable
strip_attributes :title strip_attributes :title
def self.locking_enabled?
false
end
# We want to use optimistic lock for cases when only title or description are involved # We want to use optimistic lock for cases when only title or description are involved
# http://api.rubyonrails.org/classes/ActiveRecord/Locking/Optimistic.html # http://api.rubyonrails.org/classes/ActiveRecord/Locking/Optimistic.html
def locking_enabled? def locking_enabled?
......
...@@ -37,6 +37,8 @@ module MirrorAuthentication ...@@ -37,6 +37,8 @@ module MirrorAuthentication
end end
define_method("#{name}=") do |value| define_method("#{name}=") do |value|
credentials_will_change!
self.credentials ||= {} self.credentials ||= {}
# Removal of the password, username, etc, generally causes an update of # Removal of the password, username, etc, generally causes an update of
......
...@@ -712,7 +712,7 @@ class MergeRequest < ApplicationRecord ...@@ -712,7 +712,7 @@ class MergeRequest < ApplicationRecord
end end
def validate_branch_name(attr) def validate_branch_name(attr)
return unless changes_include?(attr) return unless will_save_change_to_attribute?(attr)
branch = read_attribute(attr) branch = read_attribute(attr)
......
...@@ -21,7 +21,10 @@ class NotificationSetting < ApplicationRecord ...@@ -21,7 +21,10 @@ class NotificationSetting < ApplicationRecord
# pending delete). # pending delete).
# #
scope :for_projects, -> do scope :for_projects, -> do
includes(:project).references(:projects).where(source_type: 'Project').where.not(projects: { id: nil, pending_delete: true }) includes(:project).references(:projects)
.where(source_type: 'Project')
.where.not(projects: { id: nil })
.where.not(projects: { pending_delete: true })
end end
EMAIL_EVENTS = [ EMAIL_EVENTS = [
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
module UserStatusTooltip module UserStatusTooltip
extend ActiveSupport::Concern extend ActiveSupport::Concern
include ActionView::Helpers::TagHelper include ActionView::Helpers::TagHelper
include ::Gitlab::ActionViewOutput::Context include ActionView::Context
include EmojiHelper include EmojiHelper
include UsersHelper include UsersHelper
......
...@@ -12,7 +12,7 @@ module Projects ...@@ -12,7 +12,7 @@ module Projects
matching_programming_languages = ensure_programming_languages(detection) matching_programming_languages = ensure_programming_languages(detection)
RepositoryLanguage.transaction do RepositoryLanguage.transaction do
project.repository_languages.where(programming_language_id: detection.deletions).delete_all RepositoryLanguage.where(project_id: project.id, programming_language_id: detection.deletions).delete_all
detection.updates.each do |update| detection.updates.each do |update|
RepositoryLanguage RepositoryLanguage
......
...@@ -20,6 +20,8 @@ module Projects ...@@ -20,6 +20,8 @@ module Projects
::Projects::MoveProjectAuthorizationsService.new(@project, @current_user) ::Projects::MoveProjectAuthorizationsService.new(@project, @current_user)
.execute(source_project, remove_remaining_elements: remove_remaining_elements) .execute(source_project, remove_remaining_elements: remove_remaining_elements)
@project.save(touch: false)
success success
end end
end end
......
...@@ -125,7 +125,7 @@ module ObjectStorage ...@@ -125,7 +125,7 @@ module ObjectStorage
included do included do
include AfterCommitQueue include AfterCommitQueue
after_save on: [:create, :update] do after_save do
background_upload(changed_mounts) background_upload(changed_mounts)
end end
end end
......
<% self.formats = ["html"] %> <% self.formats = [:html] %>
<%= raw( <%= raw(
{ {
......
...@@ -26,49 +26,26 @@ module MailScheduler ...@@ -26,49 +26,26 @@ module MailScheduler
end end
def self.perform_async(*args) def self.perform_async(*args)
super(*Arguments.serialize(args)) super(*ActiveJob::Arguments.serialize(args))
end end
private private
# If an argument is in the ActiveJob::Arguments::TYPE_WHITELIST list, # This is copied over from https://github.com/rails/rails/blob/v6.0.1/activejob/lib/active_job/arguments.rb#L50
# because it is declared as a private constant
PERMITTED_TYPES = [NilClass, String, Integer, Float, BigDecimal, TrueClass, FalseClass].freeze
private_constant :PERMITTED_TYPES
# If an argument is in the PERMITTED_TYPES list,
# it means the argument cannot be deserialized. # it means the argument cannot be deserialized.
# Which means there's something wrong with our code. # Which means there's something wrong with our code.
def check_arguments!(args) def check_arguments!(args)
args.each do |arg| args.each do |arg|
if arg.class.in?(ActiveJob::Arguments::TYPE_WHITELIST) if arg.class.in?(PERMITTED_TYPES)
raise(ArgumentError, "Argument `#{arg}` cannot be deserialized because of its type") raise(ArgumentError, "Argument `#{arg}` cannot be deserialized because of its type")
end end
end end
end end
# Permit ActionController::Parameters for serializable Hash
#
# Port of
# https://github.com/rails/rails/commit/945fdd76925c9f615bf016717c4c8db2b2955357#diff-fc90ec41ef75be8b2259526fe1a8b663
module Arguments
include ActiveJob::Arguments
extend self
private
def serialize_argument(argument)
case argument
when -> (arg) { arg.respond_to?(:permitted?) }
serialize_hash(argument.to_h).tap do |result|
result[WITH_INDIFFERENT_ACCESS_KEY] = serialize_argument(true)
end
else
super
end
end
end
# Make sure we remove this patch starting with Rails 6.0.
if Rails.version.start_with?('6.0')
raise <<~MSG
Please remove the patch `Arguments` module and use `ActiveJob::Arguments` again.
MSG
end
end end
end end
#!/usr/bin/env ruby #!/usr/bin/env ruby
require 'fileutils' require 'fileutils'
include FileUtils
# path to your application root. # path to your application root.
APP_ROOT = File.expand_path('..', __dir__) APP_ROOT = File.expand_path('..', __dir__)
...@@ -9,24 +8,25 @@ def system!(*args) ...@@ -9,24 +8,25 @@ def system!(*args)
system(*args) || abort("\n== Command #{args} failed ==") system(*args) || abort("\n== Command #{args} failed ==")
end end
chdir APP_ROOT do FileUtils.chdir APP_ROOT do
# This script is a starting point to setup your application. # This script is a way to setup or update your development environment automatically.
# This script is idempotent, so that you can run it at anytime and get an expectable outcome.
# Add necessary setup steps to this file. # Add necessary setup steps to this file.
puts '== Installing dependencies ==' puts '== Installing dependencies =='
system! 'gem install bundler --conservative' system! 'gem install bundler --conservative'
system('bundle check') || system!('bundle install') system('bundle check') || system!('bundle install')
# Install JavaScript dependencies if using Yarn # Install JavaScript dependencies
# system('bin/yarn') # system('bin/yarn')
# puts "\n== Copying sample files ==" # puts "\n== Copying sample files =="
# unless File.exist?('config/database.yml') # unless File.exist?('config/database.yml')
# cp 'config/database.yml.sample', 'config/database.yml' # FileUtils.cp 'config/database.yml.sample', 'config/database.yml'
# end # end
puts "\n== Preparing database ==" puts "\n== Preparing database =="
system! 'bin/rails db:setup' system! 'bin/rails db:prepare'
puts "\n== Removing old logs and tempfiles ==" puts "\n== Removing old logs and tempfiles =="
system! 'bin/rails log:clear tmp:clear' system! 'bin/rails log:clear tmp:clear'
......
---
title: Upgrade to Rails 6
merge_request: 19891
author:
type: other
require_relative 'boot' require_relative 'boot'
# Based on https://github.com/rails/rails/blob/v5.2.3/railties/lib/rails/all.rb # Based on https://github.com/rails/rails/blob/v6.0.1/railties/lib/rails/all.rb
# Only load the railties we need instead of loading everything # Only load the railties we need instead of loading everything
require 'rails'
require 'active_record/railtie' require 'active_record/railtie'
require 'action_controller/railtie' require 'action_controller/railtie'
require 'action_view/railtie' require 'action_view/railtie'
......
# Load the rails application # Load the Rails application.
require_relative 'application' require_relative 'application'
# Initialize the rails application # Initialize the Rails application.
Rails.application.initialize! Rails.application.initialize!
...@@ -50,4 +50,8 @@ Rails.application.configure do ...@@ -50,4 +50,8 @@ Rails.application.configure do
# BetterErrors live shell (REPL) on every stack frame # BetterErrors live shell (REPL) on every stack frame
BetterErrors::Middleware.allow_ip!("127.0.0.1/0") BetterErrors::Middleware.allow_ip!("127.0.0.1/0")
# Use an evented file watcher to asynchronously detect changes in source code,
# routes, locales, etc. This feature depends on the listen gem.
config.file_watcher = ActiveSupport::EventedFileUpdateChecker
end end
...@@ -24,10 +24,11 @@ module RegisterDateTimeWithTimeZone ...@@ -24,10 +24,11 @@ module RegisterDateTimeWithTimeZone
def initialize_type_map(mapping = type_map) def initialize_type_map(mapping = type_map)
super mapping super mapping
mapping.register_type 'timestamptz' do |_, _, sql_type| register_class_with_precision(
precision = extract_precision(sql_type) mapping,
ActiveRecord::ConnectionAdapters::PostgreSQLAdapter::OID::DateTimeWithTimeZone.new(precision: precision) 'timestamptz',
end ActiveRecord::ConnectionAdapters::PostgreSQLAdapter::OID::DateTimeWithTimeZone
)
end end
end end
...@@ -46,3 +47,5 @@ end ...@@ -46,3 +47,5 @@ end
if (ActiveRecord::Base.connection.active? rescue false) if (ActiveRecord::Base.connection.active? rescue false)
ActiveRecord::Base.connection.send :reload_type_map ActiveRecord::Base.connection.send :reload_type_map
end end
ActiveRecord::Base.time_zone_aware_types += [:datetime_with_timezone]
...@@ -6,7 +6,7 @@ module ActiveRecord ...@@ -6,7 +6,7 @@ module ActiveRecord
self self
end end
def self.run(preloader) def self.run
end end
def self.preloaded_records def self.preloaded_records
......
# frozen_string_literal: true
ActiveRecord::ConnectionAdapters::ConnectionPool.prepend Gitlab::Patch::ActiveRecordQueryCache
...@@ -26,7 +26,7 @@ module ActiveRecord ...@@ -26,7 +26,7 @@ module ActiveRecord
locking_column => possible_previous_lock_value, locking_column => possible_previous_lock_value,
self.class.primary_key => id_in_database self.class.primary_key => id_in_database
).update_all( ).update_all(
attributes_with_values_for_update(attribute_names) attributes_with_values(attribute_names)
) )
if affected_rows != 1 if affected_rows != 1
......
...@@ -12,4 +12,5 @@ if csp_settings['enabled'] ...@@ -12,4 +12,5 @@ if csp_settings['enabled']
Rails.application.config.content_security_policy_report_only = csp_settings['report_only'] Rails.application.config.content_security_policy_report_only = csp_settings['report_only']
Rails.application.config.content_security_policy_nonce_generator = ->(request) { SecureRandom.base64(16) } Rails.application.config.content_security_policy_nonce_generator = ->(request) { SecureRandom.base64(16) }
Rails.application.config.content_security_policy_nonce_directives = %w(script-src)
end end
# Be sure to restart your server when you modify this file. # Be sure to restart your server when you modify this file.
Rails.application.config.action_dispatch.use_cookies_with_metadata = false
Rails.application.config.action_dispatch.cookies_serializer = :hybrid Rails.application.config.action_dispatch.cookies_serializer = :hybrid
...@@ -2,11 +2,11 @@ ...@@ -2,11 +2,11 @@
# of editing this file, please use the migrations feature of Active Record to # of editing this file, please use the migrations feature of Active Record to
# incrementally modify your database, and then regenerate this schema definition. # incrementally modify your database, and then regenerate this schema definition.
# #
# Note that this schema.rb definition is the authoritative source for your # This file is the source Rails uses to define your schema when running `rails
# database schema. If you need to create the application database on another # db:schema:load`. When creating a new database, `rails db:schema:load` tends to
# system, you should be using db:schema:load, not running all the migrations # be faster and is potentially less error prone than running all of your
# from scratch. The latter is a flawed and unsustainable approach (the more migrations # migrations from scratch. Old migrations may fail to apply correctly if those
# you'll amass, the slower it'll run and the greater likelihood for issues). # migrations use external dependencies or application code.
# #
# It's strongly recommended that you check this file into your version control system. # It's strongly recommended that you check this file into your version control system.
......
...@@ -19,7 +19,7 @@ class MergeRequestsComplianceFinder < MergeRequestsFinder ...@@ -19,7 +19,7 @@ class MergeRequestsComplianceFinder < MergeRequestsFinder
.limit(1) .limit(1)
.to_sql .to_sql
sql = find_group_projects.as('projects').to_sql sql = find_group_projects.arel.as('projects').to_sql
records = Project records = Project
.select('projects.id, events.target_id as merge_request_id') .select('projects.id, events.target_id as merge_request_id')
.from([Arel.sql("#{sql} JOIN LATERAL (#{lateral}) #{Event.table_name} ON true")]) .from([Arel.sql("#{sql} JOIN LATERAL (#{lateral}) #{Event.table_name} ON true")])
......
...@@ -58,17 +58,11 @@ module EE ...@@ -58,17 +58,11 @@ module EE
def ce_lookup_context def ce_lookup_context
@ce_lookup_context ||= begin @ce_lookup_context ||= begin
context = lookup_context.dup ce_view_paths = lookup_context.view_paths.paths.reject do |resolver|
# This could duplicate the paths we're going to modify
context.view_paths = lookup_context.view_paths.paths
# Discard lookup path ee/ for the new paths
context.view_paths.paths.delete_if do |resolver|
resolver.to_path.start_with?("#{Rails.root}/ee") resolver.to_path.start_with?("#{Rails.root}/ee")
end end
context ActionView::LookupContext.new(ce_view_paths)
end end
end end
......
...@@ -19,7 +19,7 @@ module EE ...@@ -19,7 +19,7 @@ module EE
belongs_to :user belongs_to :user
belongs_to :group belongs_to :group
protected_type = self.parent.model_name.singular protected_type = self.module_parent.model_name.singular
validates :group_id, uniqueness: { scope: protected_type, allow_nil: true } validates :group_id, uniqueness: { scope: protected_type, allow_nil: true }
validates :user_id, uniqueness: { scope: protected_type, allow_nil: true } validates :user_id, uniqueness: { scope: protected_type, allow_nil: true }
validates :access_level, uniqueness: { scope: protected_type, if: :role?, validates :access_level, uniqueness: { scope: protected_type, if: :role?,
......
...@@ -22,7 +22,7 @@ module Elastic ...@@ -22,7 +22,7 @@ module Elastic
alias_method :real_class, :class alias_method :real_class, :class
def version_namespace def version_namespace
self.class.parent self.class.module_parent
end end
class_methods do class_methods do
......
...@@ -22,7 +22,7 @@ module Elastic ...@@ -22,7 +22,7 @@ module Elastic
end end
def version_namespace def version_namespace
real_class.parent real_class.module_parent
end end
class_methods do class_methods do
......
...@@ -7,7 +7,7 @@ module Elastic ...@@ -7,7 +7,7 @@ module Elastic
extend Elasticsearch::Model::Indexing::ClassMethods extend Elasticsearch::Model::Indexing::ClassMethods
extend Elasticsearch::Model::Naming::ClassMethods extend Elasticsearch::Model::Naming::ClassMethods
self.index_name = [Rails.application.class.parent_name.downcase, Rails.env].join('-') self.index_name = [Rails.application.class.module_parent_name.downcase, Rails.env].join('-')
# ES6 requires a single type per index # ES6 requires a single type per index
self.document_type = 'doc' self.document_type = 'doc'
......
...@@ -46,7 +46,7 @@ module Gitlab ...@@ -46,7 +46,7 @@ module Gitlab
end end
def migration_context def migration_context
ActiveRecord::MigrationContext.new(ActiveRecord::Migrator.migrations_paths) ActiveRecord::MigrationContext.new(ActiveRecord::Migrator.migrations_paths, ActiveRecord::SchemaMigration)
end end
def abort_if_no_geo_config! def abort_if_no_geo_config!
......
...@@ -79,7 +79,7 @@ describe Groups::InsightsController do ...@@ -79,7 +79,7 @@ describe Groups::InsightsController do
it 'does return the default config' do it 'does return the default config' do
subject subject
expect(response.parsed_body).to eq(parent_group.default_insights_config.to_json) expect(response.parsed_body).to eq(parent_group.default_insights_config.as_json)
end end
end end
......
...@@ -37,7 +37,7 @@ describe Projects::DesignsController do ...@@ -37,7 +37,7 @@ describe Projects::DesignsController do
subject subject
expect(response.header['Content-Disposition']).to eq(%Q(attachment; filename*=UTF-8''#{filename}; filename=\"#{filename}\")) expect(response.header['Content-Disposition']).to eq(%Q(attachment; filename=\"#{filename}\"; filename*=UTF-8''#{filename}))
end end
context 'when the design is not an LFS file' do context 'when the design is not an LFS file' do
......
...@@ -85,7 +85,6 @@ FactoryBot.define do ...@@ -85,7 +85,6 @@ FactoryBot.define do
file_name { 'conanfile.py' } file_name { 'conanfile.py' }
file_sha1 { 'be93151dc23ac34a82752444556fe79b32c7a1ad' } file_sha1 { 'be93151dc23ac34a82752444556fe79b32c7a1ad' }
file_md5 { '12345abcde' } file_md5 { '12345abcde' }
file_type { 'py' }
size { 400.kilobytes } size { 400.kilobytes }
end end
...@@ -98,7 +97,6 @@ FactoryBot.define do ...@@ -98,7 +97,6 @@ FactoryBot.define do
file_name { 'conanmanifest.txt' } file_name { 'conanmanifest.txt' }
file_sha1 { 'be93151dc23ac34a82752444556fe79b32c7a1ad' } file_sha1 { 'be93151dc23ac34a82752444556fe79b32c7a1ad' }
file_md5 { '12345abcde' } file_md5 { '12345abcde' }
file_type { 'txt' }
size { 400.kilobytes } size { 400.kilobytes }
end end
...@@ -111,7 +109,6 @@ FactoryBot.define do ...@@ -111,7 +109,6 @@ FactoryBot.define do
file_name { 'conanmanifest.txt' } file_name { 'conanmanifest.txt' }
file_sha1 { 'be93151dc23ac34a82752444556fe79b32c7a1ad' } file_sha1 { 'be93151dc23ac34a82752444556fe79b32c7a1ad' }
file_md5 { '12345abcde' } file_md5 { '12345abcde' }
file_type { 'txt' }
size { 400.kilobytes } size { 400.kilobytes }
end end
...@@ -124,7 +121,6 @@ FactoryBot.define do ...@@ -124,7 +121,6 @@ FactoryBot.define do
file_name { 'conaninfo.txt' } file_name { 'conaninfo.txt' }
file_sha1 { 'be93151dc23ac34a82752444556fe79b32c7a1ad' } file_sha1 { 'be93151dc23ac34a82752444556fe79b32c7a1ad' }
file_md5 { '12345abcde' } file_md5 { '12345abcde' }
file_type { 'txt' }
size { 400.kilobytes } size { 400.kilobytes }
end end
...@@ -137,7 +133,6 @@ FactoryBot.define do ...@@ -137,7 +133,6 @@ FactoryBot.define do
file_name { 'conan_package.tgz' } file_name { 'conan_package.tgz' }
file_sha1 { 'be93151dc23ac34a82752444556fe79b32c7a1ad' } file_sha1 { 'be93151dc23ac34a82752444556fe79b32c7a1ad' }
file_md5 { '12345abcde' } file_md5 { '12345abcde' }
file_type { 'tgz' }
size { 400.kilobytes } size { 400.kilobytes }
end end
end end
...@@ -146,7 +141,6 @@ FactoryBot.define do ...@@ -146,7 +141,6 @@ FactoryBot.define do
file { fixture_file_upload('ee/spec/fixtures/maven/my-app-1.0-20180724.124855-1.jar') } file { fixture_file_upload('ee/spec/fixtures/maven/my-app-1.0-20180724.124855-1.jar') }
file_name { 'my-app-1.0-20180724.124855-1.jar' } file_name { 'my-app-1.0-20180724.124855-1.jar' }
file_sha1 { '4f0bfa298744d505383fbb57c554d4f5c12d88b3' } file_sha1 { '4f0bfa298744d505383fbb57c554d4f5c12d88b3' }
file_type { 'jar' }
size { 100.kilobytes } size { 100.kilobytes }
end end
...@@ -154,7 +148,6 @@ FactoryBot.define do ...@@ -154,7 +148,6 @@ FactoryBot.define do
file { fixture_file_upload('ee/spec/fixtures/maven/my-app-1.0-20180724.124855-1.pom') } file { fixture_file_upload('ee/spec/fixtures/maven/my-app-1.0-20180724.124855-1.pom') }
file_name { 'my-app-1.0-20180724.124855-1.pom' } file_name { 'my-app-1.0-20180724.124855-1.pom' }
file_sha1 { '19c975abd49e5102ca6c74a619f21e0cf0351c57' } file_sha1 { '19c975abd49e5102ca6c74a619f21e0cf0351c57' }
file_type { 'pom' }
size { 200.kilobytes } size { 200.kilobytes }
end end
...@@ -162,7 +155,6 @@ FactoryBot.define do ...@@ -162,7 +155,6 @@ FactoryBot.define do
file { fixture_file_upload('ee/spec/fixtures/maven/maven-metadata.xml') } file { fixture_file_upload('ee/spec/fixtures/maven/maven-metadata.xml') }
file_name { 'maven-metadata.xml' } file_name { 'maven-metadata.xml' }
file_sha1 { '42b1bdc80de64953b6876f5a8c644f20204011b0' } file_sha1 { '42b1bdc80de64953b6876f5a8c644f20204011b0' }
file_type { 'xml' }
size { 300.kilobytes } size { 300.kilobytes }
end end
...@@ -170,7 +162,6 @@ FactoryBot.define do ...@@ -170,7 +162,6 @@ FactoryBot.define do
file { fixture_file_upload('ee/spec/fixtures/npm/foo-1.0.1.tgz') } file { fixture_file_upload('ee/spec/fixtures/npm/foo-1.0.1.tgz') }
file_name { 'foo-1.0.1.tgz' } file_name { 'foo-1.0.1.tgz' }
file_sha1 { 'be93151dc23ac34a82752444556fe79b32c7a1ad' } file_sha1 { 'be93151dc23ac34a82752444556fe79b32c7a1ad' }
file_type { 'tgz' }
size { 400.kilobytes } size { 400.kilobytes }
end end
......
...@@ -25,7 +25,7 @@ describe Groups::SamlProvidersController, '(JavaScript fixtures)', type: :contro ...@@ -25,7 +25,7 @@ describe Groups::SamlProvidersController, '(JavaScript fixtures)', type: :contro
get :show, params: { group_id: group } get :show, params: { group_id: group }
expect(response).to be_success expect(response).to be_successful
expect(response).to render_template 'groups/saml_providers/show' expect(response).to render_template 'groups/saml_providers/show'
end end
end end
...@@ -169,21 +169,21 @@ describe ApplicationHelper do ...@@ -169,21 +169,21 @@ describe ApplicationHelper do
it 'finds the CE partial' do it 'finds the CE partial' do
ce_partial = helper.find_ce_template(partial) ce_partial = helper.find_ce_template(partial)
expect(ce_partial.inspect).to eq(expected_partial_path) expect(ce_partial.short_identifier).to eq(expected_partial_path)
# And it could still find the EE partial # And it could still find the EE partial
ee_partial = helper.lookup_context.find(partial, [], true) ee_partial = helper.lookup_context.find(partial, [], true)
expect(ee_partial.inspect).to eq("ee/#{expected_partial_path}") expect(ee_partial.short_identifier).to eq("ee/#{expected_partial_path}")
end end
it 'finds the CE view' do it 'finds the CE view' do
ce_view = helper.find_ce_template(view) ce_view = helper.find_ce_template(view)
expect(ce_view.inspect).to eq(expected_view_path) expect(ce_view.short_identifier).to eq(expected_view_path)
# And it could still find the EE view # And it could still find the EE view
ee_view = helper.lookup_context.find(view, [], false) ee_view = helper.lookup_context.find(view, [], false)
expect(ee_view.inspect).to eq("ee/#{expected_view_path}") expect(ee_view.short_identifier).to eq("ee/#{expected_view_path}")
end end
end end
end end
......
...@@ -41,14 +41,14 @@ describe API::MavenPackages do ...@@ -41,14 +41,14 @@ describe API::MavenPackages do
subject subject
expect(response).to have_gitlab_http_status(200) expect(response).to have_gitlab_http_status(200)
expect(response.content_type.to_s).to eq('application/octet-stream') expect(response.media_type).to eq('application/octet-stream')
end end
it 'returns sha1 of the file' do it 'returns sha1 of the file' do
download_file(package_file.file_name + '.sha1') download_file(package_file.file_name + '.sha1')
expect(response).to have_gitlab_http_status(200) expect(response).to have_gitlab_http_status(200)
expect(response.content_type.to_s).to eq('text/plain') expect(response.media_type).to eq('text/plain')
expect(response.body).to eq(package_file.file_sha1) expect(response.body).to eq(package_file.file_sha1)
end end
end end
...@@ -67,7 +67,7 @@ describe API::MavenPackages do ...@@ -67,7 +67,7 @@ describe API::MavenPackages do
subject subject
expect(response).to have_gitlab_http_status(200) expect(response).to have_gitlab_http_status(200)
expect(response.content_type.to_s).to eq('application/octet-stream') expect(response.media_type).to eq('application/octet-stream')
end end
it 'denies download when no private token' do it 'denies download when no private token' do
...@@ -80,7 +80,7 @@ describe API::MavenPackages do ...@@ -80,7 +80,7 @@ describe API::MavenPackages do
download_file(package_file.file_name, job_token: job.token) download_file(package_file.file_name, job_token: job.token)
expect(response).to have_gitlab_http_status(200) expect(response).to have_gitlab_http_status(200)
expect(response.content_type.to_s).to eq('application/octet-stream') expect(response.media_type).to eq('application/octet-stream')
end end
end end
...@@ -97,7 +97,7 @@ describe API::MavenPackages do ...@@ -97,7 +97,7 @@ describe API::MavenPackages do
subject subject
expect(response).to have_gitlab_http_status(200) expect(response).to have_gitlab_http_status(200)
expect(response.content_type.to_s).to eq('application/octet-stream') expect(response.media_type).to eq('application/octet-stream')
end end
it 'denies download when not enough permissions' do it 'denies download when not enough permissions' do
...@@ -118,7 +118,7 @@ describe API::MavenPackages do ...@@ -118,7 +118,7 @@ describe API::MavenPackages do
download_file(package_file.file_name, job_token: job.token) download_file(package_file.file_name, job_token: job.token)
expect(response).to have_gitlab_http_status(200) expect(response).to have_gitlab_http_status(200)
expect(response.content_type.to_s).to eq('application/octet-stream') expect(response.media_type).to eq('application/octet-stream')
end end
end end
...@@ -164,14 +164,14 @@ describe API::MavenPackages do ...@@ -164,14 +164,14 @@ describe API::MavenPackages do
subject subject
expect(response).to have_gitlab_http_status(200) expect(response).to have_gitlab_http_status(200)
expect(response.content_type.to_s).to eq('application/octet-stream') expect(response.media_type).to eq('application/octet-stream')
end end
it 'returns sha1 of the file' do it 'returns sha1 of the file' do
download_file(package_file.file_name + '.sha1') download_file(package_file.file_name + '.sha1')
expect(response).to have_gitlab_http_status(200) expect(response).to have_gitlab_http_status(200)
expect(response.content_type.to_s).to eq('text/plain') expect(response.media_type).to eq('text/plain')
expect(response.body).to eq(package_file.file_sha1) expect(response.body).to eq(package_file.file_sha1)
end end
end end
...@@ -190,7 +190,7 @@ describe API::MavenPackages do ...@@ -190,7 +190,7 @@ describe API::MavenPackages do
subject subject
expect(response).to have_gitlab_http_status(200) expect(response).to have_gitlab_http_status(200)
expect(response.content_type.to_s).to eq('application/octet-stream') expect(response.media_type).to eq('application/octet-stream')
end end
it 'denies download when no private token' do it 'denies download when no private token' do
...@@ -203,7 +203,7 @@ describe API::MavenPackages do ...@@ -203,7 +203,7 @@ describe API::MavenPackages do
download_file(package_file.file_name, job_token: job.token) download_file(package_file.file_name, job_token: job.token)
expect(response).to have_gitlab_http_status(200) expect(response).to have_gitlab_http_status(200)
expect(response.content_type.to_s).to eq('application/octet-stream') expect(response.media_type).to eq('application/octet-stream')
end end
end end
...@@ -220,7 +220,7 @@ describe API::MavenPackages do ...@@ -220,7 +220,7 @@ describe API::MavenPackages do
subject subject
expect(response).to have_gitlab_http_status(200) expect(response).to have_gitlab_http_status(200)
expect(response.content_type.to_s).to eq('application/octet-stream') expect(response.media_type).to eq('application/octet-stream')
end end
it 'denies download when not enough permissions' do it 'denies download when not enough permissions' do
...@@ -241,7 +241,7 @@ describe API::MavenPackages do ...@@ -241,7 +241,7 @@ describe API::MavenPackages do
download_file(package_file.file_name, job_token: job.token) download_file(package_file.file_name, job_token: job.token)
expect(response).to have_gitlab_http_status(200) expect(response).to have_gitlab_http_status(200)
expect(response.content_type.to_s).to eq('application/octet-stream') expect(response.media_type).to eq('application/octet-stream')
end end
end end
...@@ -272,14 +272,14 @@ describe API::MavenPackages do ...@@ -272,14 +272,14 @@ describe API::MavenPackages do
subject subject
expect(response).to have_gitlab_http_status(200) expect(response).to have_gitlab_http_status(200)
expect(response.content_type.to_s).to eq('application/octet-stream') expect(response.media_type).to eq('application/octet-stream')
end end
it 'returns sha1 of the file' do it 'returns sha1 of the file' do
download_file(package_file.file_name + '.sha1') download_file(package_file.file_name + '.sha1')
expect(response).to have_gitlab_http_status(200) expect(response).to have_gitlab_http_status(200)
expect(response.content_type.to_s).to eq('text/plain') expect(response.media_type).to eq('text/plain')
expect(response.body).to eq(package_file.file_sha1) expect(response.body).to eq(package_file.file_sha1)
end end
end end
...@@ -297,7 +297,7 @@ describe API::MavenPackages do ...@@ -297,7 +297,7 @@ describe API::MavenPackages do
subject subject
expect(response).to have_gitlab_http_status(200) expect(response).to have_gitlab_http_status(200)
expect(response.content_type.to_s).to eq('application/octet-stream') expect(response.media_type).to eq('application/octet-stream')
end end
it 'denies download when not enough permissions' do it 'denies download when not enough permissions' do
...@@ -318,7 +318,7 @@ describe API::MavenPackages do ...@@ -318,7 +318,7 @@ describe API::MavenPackages do
download_file(package_file.file_name, job_token: job.token) download_file(package_file.file_name, job_token: job.token)
expect(response).to have_gitlab_http_status(200) expect(response).to have_gitlab_http_status(200)
expect(response.content_type.to_s).to eq('application/octet-stream') expect(response.media_type).to eq('application/octet-stream')
end end
end end
...@@ -351,7 +351,7 @@ describe API::MavenPackages do ...@@ -351,7 +351,7 @@ describe API::MavenPackages do
authorize_upload_with_token authorize_upload_with_token
expect(response).to have_gitlab_http_status(200) expect(response).to have_gitlab_http_status(200)
expect(response.content_type.to_s).to eq(Gitlab::Workhorse::INTERNAL_API_CONTENT_TYPE) expect(response.media_type).to eq(Gitlab::Workhorse::INTERNAL_API_CONTENT_TYPE)
expect(json_response['TempPath']).not_to be_nil expect(json_response['TempPath']).not_to be_nil
end end
......
...@@ -434,7 +434,7 @@ module API ...@@ -434,7 +434,7 @@ module API
def present_disk_file!(path, filename, content_type = 'application/octet-stream') def present_disk_file!(path, filename, content_type = 'application/octet-stream')
filename ||= File.basename(path) filename ||= File.basename(path)
header['Content-Disposition'] = ::Gitlab::ContentDisposition.format(disposition: 'attachment', filename: filename) header['Content-Disposition'] = ActionDispatch::Http::ContentDisposition.format(disposition: 'attachment', filename: filename)
header['Content-Transfer-Encoding'] = 'binary' header['Content-Transfer-Encoding'] = 'binary'
content_type content_type content_type content_type
...@@ -542,7 +542,7 @@ module API ...@@ -542,7 +542,7 @@ module API
def send_git_blob(repository, blob) def send_git_blob(repository, blob)
env['api.format'] = :txt env['api.format'] = :txt
content_type 'text/plain' content_type 'text/plain'
header['Content-Disposition'] = ::Gitlab::ContentDisposition.format(disposition: 'inline', filename: blob.name) header['Content-Disposition'] = ActionDispatch::Http::ContentDisposition.format(disposition: 'inline', filename: blob.name)
# Let Workhorse examine the content and determine the better content disposition # Let Workhorse examine the content and determine the better content disposition
header[Gitlab::Workhorse::DETECT_HEADER] = "true" header[Gitlab::Workhorse::DETECT_HEADER] = "true"
......
# frozen_string_literal: true
# This file was simplified from https://raw.githubusercontent.com/rails/rails/195f39804a7a4a0034f25e8704220e03d95a752a/actionview/lib/action_view/context.rb.
#
# It is only needed by modules that need to call ActionView helper
# methods (e.g. those in
# https://github.com/rails/rails/tree/c4d3e202e10ae627b3b9c34498afb45450652421/actionview/lib/action_view/helpers)
# to generate tags outside of a Rails controller (e.g. API, Sidekiq,
# etc.).
#
# In Rails 5, ActionView::Context automatically includes CompiledTemplates.
# This means that any module that includes ActionView::Context is now a descendant
# of CompiledTemplates.
#
# When a partial is rendered for the first time, it runs
# Module#module_eval, which will evaluate a string source that defines a
# new method. For example:
#
# def _app_views_profiles_show_html_haml___1285955918103175884_70307801785400(local_assigns, output_buffer)
# "hello world"
# end
#
# When a new method is defined, the Ruby interpreter clears the method
# cache for all descendants, and all methods for those modules will have
# to be redefined. This can lead to a significant performance penalty.
#
# Rails 6 fixes this behavior by moving out the `include
# CompiledTemplates` into ActionView::Base so that including `ActionView::Context`
# doesn't quietly affect other modules in this way.
if Rails::VERSION::STRING.start_with?('6')
raise 'This module is no longer needed in Rails 6. Use ActionView::Context instead.'
end
module Gitlab
module ActionViewOutput
module Context
attr_accessor :output_buffer, :view_flow
end
end
end
...@@ -33,7 +33,7 @@ module Gitlab ...@@ -33,7 +33,7 @@ module Gitlab
def template_name def template_name
return unless template_name_valid? return unless template_name_valid?
location.first(-SUFFIX.length) location.delete_suffix(SUFFIX)
end end
def template_name_valid? def template_name_valid?
......
# frozen_string_literal: true
# This ports ActionDispatch::Http::ContentDisposition (https://github.com/rails/rails/pull/33829,
# which will be available in Rails 6.
module Gitlab
class ContentDisposition # :nodoc:
# Make sure we remove this patch starting with Rails 6.0.
if Rails.version.start_with?('6.0')
raise <<~MSG
Please remove this file and use `ActionDispatch::Http::ContentDisposition` instead.
MSG
end
def self.format(disposition:, filename:)
new(disposition: disposition, filename: filename).to_s
end
attr_reader :disposition, :filename
def initialize(disposition:, filename:)
@disposition = disposition
@filename = filename
end
# rubocop:disable Style/VariableInterpolation
TRADITIONAL_ESCAPED_CHAR = /[^ A-Za-z0-9!#$+.^_`|~-]/.freeze
def ascii_filename
'filename="' + percent_escape(::I18n.transliterate(filename), TRADITIONAL_ESCAPED_CHAR) + '"'
end
RFC_5987_ESCAPED_CHAR = /[^A-Za-z0-9!#$&+.^_`|~-]/.freeze
# rubocop:enable Style/VariableInterpolation
def utf8_filename
"filename*=UTF-8''" + percent_escape(filename, RFC_5987_ESCAPED_CHAR)
end
def to_s
if filename
"#{disposition}; #{ascii_filename}; #{utf8_filename}"
else
"#{disposition}"
end
end
private
def percent_escape(string, pattern)
string.gsub(pattern) do |char|
char.bytes.map { |byte| "%%%02X" % byte }.join
end
end
end
end
...@@ -204,15 +204,16 @@ module Gitlab ...@@ -204,15 +204,16 @@ module Gitlab
# pool_size - The size of the DB pool. # pool_size - The size of the DB pool.
# host - An optional host name to use instead of the default one. # host - An optional host name to use instead of the default one.
def self.create_connection_pool(pool_size, host = nil, port = nil) def self.create_connection_pool(pool_size, host = nil, port = nil)
# See activerecord-4.2.7.1/lib/active_record/connection_adapters/connection_specification.rb
env = Rails.env env = Rails.env
original_config = ActiveRecord::Base.configurations original_config = ActiveRecord::Base.configurations.to_h
env_config = original_config[env].merge('pool' => pool_size) env_config = original_config[env].merge('pool' => pool_size)
env_config['host'] = host if host env_config['host'] = host if host
env_config['port'] = port if port env_config['port'] = port if port
config = original_config.merge(env => env_config) config = ActiveRecord::DatabaseConfigurations.new(
original_config.merge(env => env_config)
)
spec = spec =
ActiveRecord:: ActiveRecord::
......
...@@ -382,7 +382,7 @@ module Gitlab ...@@ -382,7 +382,7 @@ module Gitlab
count_arel = table.project(Arel.star.count.as('count')) count_arel = table.project(Arel.star.count.as('count'))
count_arel = yield table, count_arel if block_given? count_arel = yield table, count_arel if block_given?
total = exec_query(count_arel.to_sql).to_hash.first['count'].to_i total = exec_query(count_arel.to_sql).to_a.first['count'].to_i
return if total == 0 return if total == 0
...@@ -399,7 +399,7 @@ module Gitlab ...@@ -399,7 +399,7 @@ module Gitlab
start_arel = table.project(table[:id]).order(table[:id].asc).take(1) start_arel = table.project(table[:id]).order(table[:id].asc).take(1)
start_arel = yield table, start_arel if block_given? start_arel = yield table, start_arel if block_given?
start_id = exec_query(start_arel.to_sql).to_hash.first['id'].to_i start_id = exec_query(start_arel.to_sql).to_a.first['id'].to_i
loop do loop do
stop_arel = table.project(table[:id]) stop_arel = table.project(table[:id])
...@@ -409,7 +409,7 @@ module Gitlab ...@@ -409,7 +409,7 @@ module Gitlab
.skip(batch_size) .skip(batch_size)
stop_arel = yield table, stop_arel if block_given? stop_arel = yield table, stop_arel if block_given?
stop_row = exec_query(stop_arel.to_sql).to_hash.first stop_row = exec_query(stop_arel.to_sql).to_a.first
update_arel = Arel::UpdateManager.new update_arel = Arel::UpdateManager.new
.table(table) .table(table)
......
# frozen_string_literal: true
# Fixes a bug where the query cache isn't aware of the shared
# ActiveRecord connection used in tests
# https://github.com/rails/rails/issues/36587
# To be removed with https://gitlab.com/gitlab-org/gitlab-foss/issues/64413
module Gitlab
module Patch
module ActiveRecordQueryCache
# rubocop:disable Gitlab/ModuleWithInstanceVariables
def enable_query_cache!
@query_cache_enabled[connection_cache_key(current_thread)] = true
connection.enable_query_cache! if active_connection?
end
def disable_query_cache!
@query_cache_enabled.delete connection_cache_key(current_thread)
connection.disable_query_cache! if active_connection?
end
def query_cache_enabled
@query_cache_enabled[connection_cache_key(current_thread)]
end
def active_connection?
@thread_cached_conns[connection_cache_key(current_thread)]
end
private
def current_thread
@lock_thread || Thread.current
end
# rubocop:enable Gitlab/ModuleWithInstanceVariables
end
end
end
...@@ -37,10 +37,10 @@ module Gitlab ...@@ -37,10 +37,10 @@ module Gitlab
controller = env[CONTROLLER_KEY] controller = env[CONTROLLER_KEY]
action = "#{controller.class.name}##{controller.action_name}" action = "#{controller.class.name}##{controller.action_name}"
if controller.content_type == 'text/html' if controller.media_type == 'text/html'
action action
else else
"#{action} (#{controller.content_type})" "#{action} (#{controller.media_type})"
end end
end end
......
# frozen_string_literal: true
module RuboCop
module Cop
# Cop that makes sure workers include `::Gitlab::ActionViewOutput::Context`, not `ActionView::Context`.
class IncludeActionViewContext < RuboCop::Cop::Cop
MSG = 'Include `::Gitlab::ActionViewOutput::Context`, not `ActionView::Context`, for Rails 5.'.freeze
def_node_matcher :includes_action_view_context?, <<~PATTERN
(send nil? :include (const (const nil? :ActionView) :Context))
PATTERN
def on_send(node)
return unless includes_action_view_context?(node)
add_offense(node.arguments.first, location: :expression)
end
def autocorrect(node)
lambda do |corrector|
corrector.replace(node.source_range, '::Gitlab::ActionViewOutput::Context')
end
end
end
end
end
...@@ -5,7 +5,6 @@ require_relative 'cop/gitlab/httparty' ...@@ -5,7 +5,6 @@ require_relative 'cop/gitlab/httparty'
require_relative 'cop/gitlab/finder_with_find_by' require_relative 'cop/gitlab/finder_with_find_by'
require_relative 'cop/gitlab/union' require_relative 'cop/gitlab/union'
require_relative 'cop/gitlab/rails_logger' require_relative 'cop/gitlab/rails_logger'
require_relative 'cop/include_action_view_context'
require_relative 'cop/include_sidekiq_worker' require_relative 'cop/include_sidekiq_worker'
require_relative 'cop/safe_params' require_relative 'cop/safe_params'
require_relative 'cop/active_record_association_reload' require_relative 'cop/active_record_association_reload'
......
...@@ -5,7 +5,7 @@ require 'spec_helper' ...@@ -5,7 +5,7 @@ require 'spec_helper'
describe Gitlab::Application do # rubocop:disable RSpec/FilePath describe Gitlab::Application do # rubocop:disable RSpec/FilePath
using RSpec::Parameterized::TableSyntax using RSpec::Parameterized::TableSyntax
FILTERED_PARAM = ActionDispatch::Http::ParameterFilter::FILTERED FILTERED_PARAM = ActiveSupport::ParameterFilter::FILTERED
context 'when parameters are logged' do context 'when parameters are logged' do
describe 'rails does not leak confidential parameters' do describe 'rails does not leak confidential parameters' do
......
...@@ -23,7 +23,7 @@ describe MetricsDashboard do ...@@ -23,7 +23,7 @@ describe MetricsDashboard do
routes.draw { get "metrics_dashboard" => "anonymous#metrics_dashboard" } routes.draw { get "metrics_dashboard" => "anonymous#metrics_dashboard" }
response = get :metrics_dashboard, format: :json response = get :metrics_dashboard, format: :json
JSON.parse(response.parsed_body) response.parsed_body
end end
context 'when no parameters are provided' do context 'when no parameters are provided' do
......
...@@ -59,11 +59,9 @@ describe SendFileUpload do ...@@ -59,11 +59,9 @@ describe SendFileUpload do
let(:params) { { disposition: 'inline', attachment: filename } } let(:params) { { disposition: 'inline', attachment: filename } }
it 'sends a file with inline disposition' do it 'sends a file with inline disposition' do
# Notice the filename= is omitted from the disposition; this is because
# Rails 5 will append this header in send_file
expected_params = { expected_params = {
filename: 'test.png', filename: 'test.png',
disposition: "inline; filename*=UTF-8''test.png" disposition: 'inline'
} }
expect(controller).to receive(:send_file).with(uploader.path, expected_params) expect(controller).to receive(:send_file).with(uploader.path, expected_params)
...@@ -76,34 +74,16 @@ describe SendFileUpload do ...@@ -76,34 +74,16 @@ describe SendFileUpload do
let(:params) { { attachment: filename } } let(:params) { { attachment: filename } }
it 'sends a file with content-type of text/plain' do it 'sends a file with content-type of text/plain' do
# Notice the filename= is omitted from the disposition; this is because
# Rails 5 will append this header in send_file
expected_params = { expected_params = {
content_type: 'text/plain', content_type: 'text/plain',
filename: 'test.js', filename: 'test.js',
disposition: "attachment; filename*=UTF-8''test.js" disposition: 'attachment'
} }
expect(controller).to receive(:send_file).with(uploader.path, expected_params) expect(controller).to receive(:send_file).with(uploader.path, expected_params)
subject subject
end end
context 'with non-ASCII encoded filename' do
let(:filename) { 'テスト.txt' }
# Notice the filename= is omitted from the disposition; this is because
# Rails 5 will append this header in send_file
it 'sends content-disposition for non-ASCII encoded filenames' do
expected_params = {
filename: filename,
disposition: "attachment; filename*=UTF-8''%E3%83%86%E3%82%B9%E3%83%88.txt"
}
expect(controller).to receive(:send_file).with(uploader.path, expected_params)
subject
end
end
context 'with a proxied file in object storage' do context 'with a proxied file in object storage' do
before do before do
stub_uploads_object_storage(uploader: uploader_class) stub_uploads_object_storage(uploader: uploader_class)
......
...@@ -138,14 +138,14 @@ describe Projects::ArtifactsController do ...@@ -138,14 +138,14 @@ describe Projects::ArtifactsController do
let(:filename) { job.artifacts_file.filename } let(:filename) { job.artifacts_file.filename }
it 'sends the artifacts file' do it 'sends the artifacts file' do
# Notice the filename= is omitted from the disposition; this is because
# Rails 5 will append this header in send_file
expect(controller).to receive(:send_file) expect(controller).to receive(:send_file)
.with( .with(
job.artifacts_file.file.path, job.artifacts_file.file.path,
hash_including(disposition: %Q(attachment; filename*=UTF-8''#{filename}))).and_call_original hash_including(disposition: 'attachment', filename: filename)).and_call_original
download_artifact download_artifact
expect(response.headers['Content-Disposition']).to eq(%Q(attachment; filename="#{filename}"; filename*=UTF-8''#{filename}))
end end
end end
...@@ -170,13 +170,13 @@ describe Projects::ArtifactsController do ...@@ -170,13 +170,13 @@ describe Projects::ArtifactsController do
end end
it 'sends the codequality report' do it 'sends the codequality report' do
# Notice the filename= is omitted from the disposition; this is because
# Rails 5 will append this header in send_file
expect(controller).to receive(:send_file) expect(controller).to receive(:send_file)
.with(job.job_artifacts_codequality.file.path, .with(job.job_artifacts_codequality.file.path,
hash_including(disposition: %Q(attachment; filename*=UTF-8''#{filename}))).and_call_original hash_including(disposition: 'attachment', filename: filename)).and_call_original
download_artifact(file_type: file_type) download_artifact(file_type: file_type)
expect(response.headers['Content-Disposition']).to eq(%Q(attachment; filename="#{filename}"; filename*=UTF-8''#{filename}))
end end
end end
......
...@@ -649,7 +649,7 @@ describe UploadsController do ...@@ -649,7 +649,7 @@ describe UploadsController do
get :show, params: { model: 'appearance', mounted_as: 'favicon', id: appearance.id, filename: 'dk.png' } get :show, params: { model: 'appearance', mounted_as: 'favicon', id: appearance.id, filename: 'dk.png' }
expect(response).to have_gitlab_http_status(:ok) expect(response).to have_gitlab_http_status(:ok)
expect(response.header['Content-Disposition']).to end_with 'filename="dk.png"' expect(response.header['Content-Disposition']).to include('filename="dk.png"')
end end
end end
......
...@@ -604,7 +604,7 @@ describe 'Merge request > User sees merge widget', :js do ...@@ -604,7 +604,7 @@ describe 'Merge request > User sees merge widget', :js do
click_button 'addTest' click_button 'addTest'
expect(page).to have_content('6.66') expect(page).to have_content('6.66')
expect(page).to have_content(sample_java_failed_message.gsub!(/\s+/, ' ').strip) expect(page).to have_content(sample_java_failed_message.gsub(/\s+/, ' ').strip)
end end
end end
end end
...@@ -649,7 +649,7 @@ describe 'Merge request > User sees merge widget', :js do ...@@ -649,7 +649,7 @@ describe 'Merge request > User sees merge widget', :js do
click_button 'Test#sum when a is 1 and b is 3 returns summary' click_button 'Test#sum when a is 1 and b is 3 returns summary'
expect(page).to have_content('2.22') expect(page).to have_content('2.22')
expect(page).to have_content(sample_rspec_failed_message.gsub!(/\s+/, ' ').strip) expect(page).to have_content(sample_rspec_failed_message.gsub(/\s+/, ' ').strip)
end end
end end
end end
......
...@@ -9,7 +9,7 @@ describe "User downloads artifacts" do ...@@ -9,7 +9,7 @@ describe "User downloads artifacts" do
shared_examples "downloading" do shared_examples "downloading" do
it "downloads the zip" do it "downloads the zip" do
expect(page.response_headers["Content-Disposition"]).to eq(%Q{attachment; filename*=UTF-8''#{job.artifacts_file.filename}; filename="#{job.artifacts_file.filename}"}) expect(page.response_headers['Content-Disposition']).to eq(%Q{attachment; filename="#{job.artifacts_file.filename}"; filename*=UTF-8''#{job.artifacts_file.filename}})
expect(page.response_headers['Content-Transfer-Encoding']).to eq("binary") expect(page.response_headers['Content-Transfer-Encoding']).to eq("binary")
expect(page.response_headers['Content-Type']).to eq("application/zip") expect(page.response_headers['Content-Type']).to eq("application/zip")
expect(page.source.b).to eq(job.artifacts_file.file.read.b) expect(page.source.b).to eq(job.artifacts_file.file.read.b)
......
...@@ -346,7 +346,7 @@ describe 'Jobs', :clean_gitlab_redis_shared_state do ...@@ -346,7 +346,7 @@ describe 'Jobs', :clean_gitlab_redis_shared_state do
artifact_request = requests.find { |req| req.url.match(%r{artifacts/download}) } artifact_request = requests.find { |req| req.url.match(%r{artifacts/download}) }
expect(artifact_request.response_headers["Content-Disposition"]).to eq(%Q{attachment; filename*=UTF-8''#{job.artifacts_file.filename}; filename="#{job.artifacts_file.filename}"}) expect(artifact_request.response_headers['Content-Disposition']).to eq(%Q{attachment; filename="#{job.artifacts_file.filename}"; filename*=UTF-8''#{job.artifacts_file.filename}})
expect(artifact_request.response_headers['Content-Transfer-Encoding']).to eq("binary") expect(artifact_request.response_headers['Content-Transfer-Encoding']).to eq("binary")
expect(artifact_request.response_headers['Content-Type']).to eq("image/gif") expect(artifact_request.response_headers['Content-Type']).to eq("image/gif")
expect(artifact_request.body).to eq(job.artifacts_file.file.read.b) expect(artifact_request.body).to eq(job.artifacts_file.file.read.b)
......
...@@ -26,7 +26,7 @@ describe Gitlab::QueryLimiting::Middleware do ...@@ -26,7 +26,7 @@ describe Gitlab::QueryLimiting::Middleware do
:controller, :controller,
action_name: 'show', action_name: 'show',
class: double(:class, name: 'UsersController'), class: double(:class, name: 'UsersController'),
content_type: 'text/html' media_type: 'text/html'
) )
} }
...@@ -39,7 +39,7 @@ describe Gitlab::QueryLimiting::Middleware do ...@@ -39,7 +39,7 @@ describe Gitlab::QueryLimiting::Middleware do
:controller, :controller,
action_name: 'show', action_name: 'show',
class: double(:class, name: 'UsersController'), class: double(:class, name: 'UsersController'),
content_type: 'application/json' media_type: 'application/json'
) )
} }
......
...@@ -302,7 +302,11 @@ describe MergeRequest do ...@@ -302,7 +302,11 @@ describe MergeRequest do
it 'returns empty requests' do it 'returns empty requests' do
latest_merge_request_diff = merge_request.merge_request_diffs.create latest_merge_request_diff = merge_request.merge_request_diffs.create
latest_merge_request_diff.merge_request_diff_commits.where(sha: 'b83d6e391c22777fca1ed3012fce84f633d7fed0').delete_all
MergeRequestDiffCommit.where(
merge_request_diff_id: latest_merge_request_diff,
sha: 'b83d6e391c22777fca1ed3012fce84f633d7fed0'
).delete_all
expect(by_commit_sha).to be_empty expect(by_commit_sha).to be_empty
end end
......
# frozen_string_literal: true
require 'spec_helper'
require 'rubocop'
require 'rubocop/rspec/support'
require_relative '../../../rubocop/cop/include_action_view_context'
describe RuboCop::Cop::IncludeActionViewContext do
include CopHelper
subject(:cop) { described_class.new }
context 'when `ActionView::Context` is included' do
let(:source) { 'include ActionView::Context' }
let(:correct_source) { 'include ::Gitlab::ActionViewOutput::Context' }
it 'registers an offense' do
inspect_source(source)
aggregate_failures do
expect(cop.offenses.size).to eq(1)
expect(cop.offenses.map(&:line)).to eq([1])
expect(cop.highlights).to eq(['ActionView::Context'])
end
end
it 'autocorrects to the right version' do
autocorrected = autocorrect_source(source)
expect(autocorrected).to eq(correct_source)
end
end
context 'when `ActionView::Context` is not included' do
it 'registers no offense' do
inspect_source('include Context')
aggregate_failures do
expect(cop.offenses.size).to eq(0)
end
end
end
end
...@@ -62,7 +62,7 @@ module JavaScriptFixturesHelpers ...@@ -62,7 +62,7 @@ module JavaScriptFixturesHelpers
fixture = response.body fixture = response.body
fixture.force_encoding("utf-8") fixture.force_encoding("utf-8")
response_mime_type = Mime::Type.lookup(response.content_type) response_mime_type = Mime::Type.lookup(response.media_type)
if response_mime_type.html? if response_mime_type.html?
doc = Nokogiri::HTML::DocumentFragment.parse(fixture) doc = Nokogiri::HTML::DocumentFragment.parse(fixture)
......
...@@ -21,7 +21,7 @@ module MigrationsHelpers ...@@ -21,7 +21,7 @@ module MigrationsHelpers
end end
def migration_context def migration_context
ActiveRecord::MigrationContext.new(migrations_paths) ActiveRecord::MigrationContext.new(migrations_paths, ActiveRecord::SchemaMigration)
end end
def migrations def migrations
......
# frozen_string_literal: true # frozen_string_literal: true
require 'active_support/core_ext/hash/transform_values'
require 'active_support/hash_with_indifferent_access' require 'active_support/hash_with_indifferent_access'
require 'active_support/dependencies' require 'active_support/dependencies'
......
...@@ -41,13 +41,11 @@ RSpec.shared_examples 'a controller that can serve LFS files' do |options = {}| ...@@ -41,13 +41,11 @@ RSpec.shared_examples 'a controller that can serve LFS files' do |options = {}|
it 'serves the file' do it 'serves the file' do
lfs_uploader = LfsObjectUploader.new(lfs_object) lfs_uploader = LfsObjectUploader.new(lfs_object)
# Notice the filename= is omitted from the disposition; this is because
# Rails 5 will append this header in send_file
expect(controller).to receive(:send_file) expect(controller).to receive(:send_file)
.with( .with(
File.join(lfs_uploader.root, lfs_uploader.store_dir, lfs_uploader.filename), File.join(lfs_uploader.root, lfs_uploader.store_dir, lfs_uploader.filename),
filename: filename, filename: filename,
disposition: %Q(attachment; filename*=UTF-8''#{filename})) disposition: 'attachment')
subject subject
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment