diff options
139 files changed, 1548 insertions, 2028 deletions
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index b26c2d16d77..2c3d18d21be 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -77,18 +77,6 @@ stages: - mysql:5.7 - redis:alpine -.rails4: &rails4 - allow_failure: false - except: - variables: - - $CI_COMMIT_REF_NAME =~ /(^docs[\/-].*|.*-docs$)/ - - $CI_COMMIT_REF_NAME =~ /(^qa[\/-].*|.*-qa$)/ - - $CI_COMMIT_REF_NAME =~ /norails4/ - - $RAILS5_DISABLED - variables: - BUNDLE_GEMFILE: "Gemfile.rails4" - RAILS5: "false" - # Skip all jobs except the ones that begin with 'docs/'. # Used for commits including ONLY documentation changes. # https://docs.gitlab.com/ce/development/documentation/#testing @@ -180,18 +168,10 @@ stages: <<: *rspec-metadata <<: *use-pg -.rspec-metadata-pg-rails4: &rspec-metadata-pg-rails4 - <<: *rspec-metadata-pg - <<: *rails4 - .rspec-metadata-mysql: &rspec-metadata-mysql <<: *rspec-metadata <<: *use-mysql -.rspec-metadata-mysql-rails4: &rspec-metadata-mysql-rails4 - <<: *rspec-metadata-mysql - <<: *rails4 - .only-canonical-masters: &only-canonical-masters only: - master@gitlab-org/gitlab-ce @@ -432,7 +412,6 @@ setup-test-env: script: - bundle exec ruby -Ispec -e 'require "spec_helper" ; TestEnv.init' - scripts/gitaly-test-build # Do not use 'bundle exec' here - - BUNDLE_GEMFILE=Gemfile.rails4 bundle install $BUNDLE_INSTALL_FLAGS artifacts: expire_in: 7d paths: @@ -513,14 +492,6 @@ rspec-mysql: <<: *rspec-metadata-mysql parallel: 50 -rspec-pg-rails4: - <<: *rspec-metadata-pg-rails4 - parallel: 50 - -rspec-mysql-rails4: - <<: *rspec-metadata-mysql-rails4 - parallel: 50 - static-analysis: <<: *dedicated-no-docs-no-db-pull-cache-job dependencies: @@ -565,12 +536,6 @@ downtime_check: - /(^docs[\/-].*|.*-docs$)/ - /(^qa[\/-].*|.*-qa$)/ -rails4_gemfile_lock_check: - <<: *dedicated-no-docs-no-db-pull-cache-job - <<: *except-docs-and-qa - script: - - scripts/rails4-gemfile-lock-check - ee_compat_check: <<: *rake-exec dependencies: [] diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 3ab76965287..847a0f74aa2 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -149,17 +149,6 @@ RSpec/ExpectChange: RSpec/ExpectInHook: Enabled: false -# Offense count: 7 -# Configuration parameters: EnforcedStyle. -# SupportedStyles: implicit, each, example -RSpec/HookArgument: - Exclude: - - 'spec/spec_helper.rb' - - 'spec/support/carrierwave.rb' - - 'spec/support/db_cleaner.rb' - - 'spec/support/gitaly.rb' - - 'spec/support/setup_builds_storage.rb' - # Offense count: 19 # Configuration parameters: EnforcedStyle. # SupportedStyles: it_behaves_like, it_should_behave_like diff --git a/CHANGELOG.md b/CHANGELOG.md index d1e324c5518..a51ac887aed 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -628,6 +628,13 @@ entry. - Check frozen string in style builds. (gfyoung) +## 11.3.13 (2018-12-13) + +### Security (1 change) + +- Validate LFS hrefs before downloading them. + + ## 11.3.12 (2018-12-06) ### Security (1 change) @@ -1,22 +1,6 @@ -# --- Special code for migrating to Rails 5.0 --- -def rails5? - !%w[0 false].include?(ENV["RAILS5"]) -end - -gem_versions = {} -gem_versions['activerecord_sane_schema_dumper'] = rails5? ? '1.0' : '0.2' -gem_versions['rails'] = rails5? ? '5.0.7' : '4.2.11' -gem_versions['rails-i18n'] = rails5? ? '~> 5.1' : '~> 4.0.9' - -# The 2.0.6 version of rack requires monkeypatch to be present in -# `config.ru`. This can be removed once a new update for Rack -# is available that contains https://github.com/rack/rack/pull/1201. -gem_versions['rack'] = rails5? ? '2.0.6' : '1.6.11' -# --- The end of special code for migrating to Rails 5.0 --- - source 'https://rubygems.org' -gem 'rails', gem_versions['rails'] +gem 'rails', '5.0.7' gem 'rails-deprecated_sanitizer', '~> 1.0.3' # Improves copy-on-write performance for MRI @@ -28,11 +12,7 @@ gem 'responders', '~> 2.0' gem 'sprockets', '~> 3.7.0' # Default values for AR models -if rails5? - gem 'gitlab-default_value_for', '~> 3.1.1', require: 'default_value_for' -else - gem 'default_value_for', '~> 3.0.0' -end +gem 'gitlab-default_value_for', '~> 3.1.1', require: 'default_value_for' # Supported DBs gem 'mysql2', '~> 0.4.10', group: :mysql @@ -159,7 +139,10 @@ gem 'icalendar' gem 'diffy', '~> 3.1.0' # Application server -gem 'rack', gem_versions['rack'] +# The 2.0.6 version of rack requires monkeypatch to be present in +# `config.ru`. This can be removed once a new update for Rack +# is available that contains https://github.com/rack/rack/pull/1201. +gem 'rack', '2.0.6' group :unicorn do gem 'unicorn', '~> 5.1.0' @@ -297,7 +280,7 @@ gem 'premailer-rails', '~> 1.9.7' # I18n gem 'ruby_parser', '~> 3.8', require: false -gem 'rails-i18n', gem_versions['rails-i18n'] +gem 'rails-i18n', '~> 5.1' gem 'gettext_i18n_rails', '~> 1.8.0' gem 'gettext_i18n_rails_js', '~> 1.3' gem 'gettext', '~> 3.2.2', require: false, group: :development @@ -383,7 +366,7 @@ group :development, :test do gem 'license_finder', '~> 5.4', require: false gem 'knapsack', '~> 1.17' - gem 'activerecord_sane_schema_dumper', gem_versions['activerecord_sane_schema_dumper'] + gem 'activerecord_sane_schema_dumper', '1.0' gem 'stackprof', '~> 0.2.10', require: false @@ -397,8 +380,7 @@ group :test do gem 'email_spec', '~> 2.2.0' gem 'json-schema', '~> 2.8.0' gem 'webmock', '~> 2.3.2' - gem 'rails-controller-testing' if rails5? # Rails5 only gem. - gem 'test_after_commit', '~> 1.1' unless rails5? # Remove this gem when migrated to rails 5.0. It's been integrated to rails 5.0. + gem 'rails-controller-testing' gem 'sham_rack', '~> 1.3.6' gem 'concurrent-ruby', '~> 1.1' gem 'test-prof', '~> 0.2.5' diff --git a/Gemfile.rails4 b/Gemfile.rails4 deleted file mode 100644 index 0ec00e702aa..00000000000 --- a/Gemfile.rails4 +++ /dev/null @@ -1,7 +0,0 @@ -# BUNDLE_GEMFILE=Gemfile.rails4 bundle install - -ENV["RAILS5"] = "false" - -gemfile = File.expand_path("../Gemfile", __FILE__) - -eval(File.read(gemfile), nil, gemfile) diff --git a/Gemfile.rails4.lock b/Gemfile.rails4.lock deleted file mode 100644 index 3d81c570b89..00000000000 --- a/Gemfile.rails4.lock +++ /dev/null @@ -1,1164 +0,0 @@ -GEM - remote: https://rubygems.org/ - specs: - RedCloth (4.3.2) - abstract_type (0.0.7) - ace-rails-ap (4.1.2) - actionmailer (4.2.10) - actionpack (= 4.2.10) - actionview (= 4.2.10) - activejob (= 4.2.10) - mail (~> 2.5, >= 2.5.4) - rails-dom-testing (~> 1.0, >= 1.0.5) - actionpack (4.2.10) - actionview (= 4.2.10) - activesupport (= 4.2.10) - rack (~> 1.6) - rack-test (~> 0.6.2) - rails-dom-testing (~> 1.0, >= 1.0.5) - rails-html-sanitizer (~> 1.0, >= 1.0.2) - actionview (4.2.10) - activesupport (= 4.2.10) - builder (~> 3.1) - erubis (~> 2.7.0) - rails-dom-testing (~> 1.0, >= 1.0.5) - rails-html-sanitizer (~> 1.0, >= 1.0.3) - activejob (4.2.10) - activesupport (= 4.2.10) - globalid (>= 0.3.0) - activemodel (4.2.10) - activesupport (= 4.2.10) - builder (~> 3.1) - activerecord (4.2.10) - activemodel (= 4.2.10) - activesupport (= 4.2.10) - arel (~> 6.0) - activerecord_sane_schema_dumper (0.2) - rails (>= 4, < 5) - activesupport (4.2.10) - i18n (~> 0.7) - minitest (~> 5.1) - thread_safe (~> 0.3, >= 0.3.4) - tzinfo (~> 1.1) - acts-as-taggable-on (5.0.0) - activerecord (>= 4.2.8) - adamantium (0.2.0) - ice_nine (~> 0.11.0) - memoizable (~> 0.4.0) - addressable (2.5.2) - public_suffix (>= 2.0.2, < 4.0) - aes_key_wrap (1.0.1) - akismet (2.0.0) - arel (6.0.4) - asana (0.8.1) - faraday (~> 0.9) - faraday_middleware (~> 0.9) - faraday_middleware-multi_json (~> 0.0) - oauth2 (~> 1.0) - asciidoctor (1.5.8) - asciidoctor-plantuml (0.0.8) - asciidoctor (~> 1.5) - ast (2.4.0) - atomic (1.1.99) - attr_encrypted (3.1.0) - encryptor (~> 3.0.0) - attr_required (1.0.0) - awesome_print (1.8.0) - 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.2.2) - bcrypt (3.1.12) - bcrypt_pbkdf (1.0.0) - benchmark-ips (2.3.0) - better_errors (2.5.0) - coderay (>= 1.0.0) - erubi (>= 1.0.0) - rack (>= 0.9.0) - bindata (2.4.3) - binding_ninja (0.2.2) - binding_of_caller (0.8.0) - debug_inspector (>= 0.0.1) - bootsnap (1.3.2) - msgpack (~> 1.0) - bootstrap_form (2.7.0) - brakeman (4.2.1) - browser (2.5.3) - builder (3.2.3) - bullet (5.5.1) - activesupport (>= 3.0.0) - uniform_notifier (~> 1.10.0) - bundler-audit (0.5.0) - bundler (~> 1.2) - thor (~> 0.18) - byebug (9.0.6) - capybara (2.15.1) - addressable - mini_mime (>= 0.1.3) - nokogiri (>= 1.3.3) - rack (>= 1.0.0) - rack-test (>= 0.5.4) - xpath (~> 2.0) - capybara-screenshot (1.0.14) - capybara (>= 1.0, < 3) - launchy - carrierwave (1.2.3) - activemodel (>= 4.0.0) - activesupport (>= 4.0.0) - mime-types (>= 1.16) - cause (0.1) - charlock_holmes (0.7.6) - childprocess (0.9.0) - ffi (~> 1.0, >= 1.0.11) - chronic (0.10.2) - chronic_duration (0.10.6) - numerizer (~> 0.1.1) - chunky_png (1.3.5) - citrus (3.0.2) - coderay (1.1.2) - coercible (1.0.0) - descendants_tracker (~> 0.0.1) - commonmarker (0.17.13) - ruby-enum (~> 0.5) - concord (0.1.5) - adamantium (~> 0.2.0) - equalizer (~> 0.0.9) - concurrent-ruby (1.1.3) - concurrent-ruby-ext (1.1.3) - concurrent-ruby (= 1.1.3) - connection_pool (2.2.2) - crack (0.4.3) - safe_yaml (~> 1.0.0) - crass (1.0.4) - creole (0.5.0) - css_parser (1.5.0) - addressable - daemons (1.2.6) - database_cleaner (1.5.3) - debug_inspector (0.0.3) - debugger-ruby_core_source (1.3.8) - deckar01-task_list (2.0.0) - html-pipeline - declarative (0.0.10) - declarative-option (0.1.0) - default_value_for (3.0.2) - activerecord (>= 3.2.0, < 5.1) - descendants_tracker (0.0.4) - thread_safe (~> 0.3, >= 0.3.1) - device_detector (1.0.0) - devise (4.4.3) - bcrypt (~> 3.0) - orm_adapter (~> 0.1) - railties (>= 4.1.0, < 6.0) - responders - warden (~> 1.2.3) - devise-two-factor (3.0.0) - activesupport - attr_encrypted (>= 1.3, < 4, != 2) - devise (~> 4.0) - railties - rotp (~> 2.0) - diff-lcs (1.3) - diffy (3.1.0) - discordrb-webhooks-blackst0ne (3.3.0) - rest-client (~> 2.0) - docile (1.1.5) - domain_name (0.5.20180417) - unf (>= 0.0.5, < 1.0.0) - doorkeeper (4.3.2) - railties (>= 4.2) - doorkeeper-openid_connect (1.5.0) - doorkeeper (~> 4.3) - json-jwt (~> 1.6) - ed25519 (1.2.4) - email_reply_trimmer (0.1.6) - email_spec (2.2.0) - htmlentities (~> 4.3.3) - launchy (~> 2.1) - mail (~> 2.7) - encryptor (3.0.0) - equalizer (0.0.11) - erubi (1.7.1) - erubis (2.7.0) - escape_utils (1.2.1) - et-orbi (1.0.3) - tzinfo - eventmachine (1.2.7) - excon (0.62.0) - execjs (2.6.0) - expression_parser (0.9.0) - factory_bot (4.8.2) - activesupport (>= 3.0.0) - factory_bot_rails (4.8.2) - factory_bot (~> 4.8.2) - railties (>= 3.0.0) - faraday (0.12.2) - multipart-post (>= 1.2, < 3) - faraday_middleware (0.12.2) - faraday (>= 0.7.4, < 1.0) - faraday_middleware-multi_json (0.0.6) - faraday_middleware - multi_json - fast_blank (1.0.0) - fast_gettext (1.6.0) - ffaker (2.10.0) - ffi (1.9.25) - flipper (0.13.0) - flipper-active_record (0.13.0) - activerecord (>= 3.2, < 6) - flipper (~> 0.13.0) - flipper-active_support_cache_store (0.13.0) - activesupport (>= 3.2, < 6) - flipper (~> 0.13.0) - flowdock (0.7.1) - httparty (~> 0.7) - multi_json - fog-aliyun (0.2.0) - fog-core (~> 1.27) - fog-json (~> 1.0) - ipaddress (~> 0.8) - xml-simple (~> 1.1) - fog-aws (2.0.1) - fog-core (~> 1.38) - fog-json (~> 1.0) - fog-xml (~> 0.1) - ipaddress (~> 0.8) - fog-core (1.45.0) - builder - excon (~> 0.58) - formatador (~> 0.2) - fog-google (1.7.1) - fog-core - fog-json - fog-xml - google-api-client (~> 0.23.0) - fog-json (1.0.2) - fog-core (~> 1.0) - multi_json (~> 1.10) - fog-local (0.3.1) - fog-core (~> 1.27) - fog-openstack (0.1.21) - fog-core (>= 1.40) - fog-json (>= 1.0) - ipaddress (>= 0.8) - fog-rackspace (0.1.1) - fog-core (>= 1.35) - fog-json (>= 1.0) - fog-xml (>= 0.1) - ipaddress (>= 0.8) - fog-xml (0.1.3) - fog-core - nokogiri (>= 1.5.11, < 2.0.0) - font-awesome-rails (4.7.0.1) - railties (>= 3.2, < 5.1) - foreman (0.84.0) - thor (~> 0.19.1) - formatador (0.2.5) - fuubar (2.2.0) - rspec-core (~> 3.0) - ruby-progressbar (~> 1.4) - gemojione (3.3.0) - json - get_process_mem (0.2.0) - gettext (3.2.9) - locale (>= 2.0.5) - text (>= 1.3.0) - gettext_i18n_rails (1.8.0) - fast_gettext (>= 0.9.0) - gettext_i18n_rails_js (1.3.0) - gettext (>= 3.0.2) - gettext_i18n_rails (>= 0.7.1) - po_to_json (>= 1.0.0) - rails (>= 3.2.0) - gitaly-proto (1.3.0) - grpc (~> 1.0) - github-markup (1.7.0) - gitlab-markup (1.6.5) - gitlab-sidekiq-fetcher (0.3.0) - sidekiq (~> 5) - gitlab-styles (2.4.1) - rubocop (~> 0.54.0) - rubocop-gitlab-security (~> 0.1.0) - rubocop-rspec (~> 1.19) - gitlab_omniauth-ldap (2.0.4) - net-ldap (~> 0.16) - omniauth (~> 1.3) - pyu-ruby-sasl (>= 0.0.3.3, < 0.1) - rubyntlm (~> 0.5) - globalid (0.4.1) - activesupport (>= 4.2.0) - gon (6.2.0) - actionpack (>= 3.0) - multi_json - request_store (>= 1.0) - google-api-client (0.23.4) - addressable (~> 2.5, >= 2.5.1) - googleauth (>= 0.5, < 0.7.0) - httpclient (>= 2.8.1, < 3.0) - mime-types (~> 3.0) - representable (~> 3.0) - retriable (>= 2.0, < 4.0) - google-protobuf (3.6.1) - googleapis-common-protos-types (1.0.2) - google-protobuf (~> 3.0) - googleauth (0.6.6) - faraday (~> 0.12) - jwt (>= 1.4, < 3.0) - memoist (~> 0.12) - multi_json (~> 1.11) - os (>= 0.9, < 2.0) - signet (~> 0.7) - gpgme (2.0.18) - mini_portile2 (~> 2.3) - grape (1.1.0) - activesupport - builder - 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.0.6) - activesupport (>= 4, < 5.1) - grape (~> 1.0) - rake (~> 12) - grape_logging (1.7.0) - grape - graphiql-rails (1.4.10) - railties - sprockets-rails - graphql (1.8.1) - grpc (1.15.0) - google-protobuf (~> 3.1) - googleapis-common-protos-types (~> 1.0.0) - haml (5.0.4) - temple (>= 0.8.0) - tilt - haml_lint (0.28.0) - haml (>= 4.0, < 5.1) - rainbow - rake (>= 10, < 13) - rubocop (>= 0.50.0) - sysexits (~> 1.1) - hamlit (2.8.8) - temple (>= 0.8.0) - thor - tilt - hangouts-chat (0.0.5) - hashdiff (0.3.4) - hashie (3.5.7) - hashie-forbidden_attributes (0.1.1) - hashie (>= 3.0) - health_check (2.6.0) - rails (>= 4.0) - hipchat (1.5.2) - httparty - mimemagic - html-pipeline (2.8.4) - activesupport (>= 2) - nokogiri (>= 1.4) - html2text (0.2.0) - nokogiri (~> 1.6) - htmlentities (4.3.4) - http (3.3.0) - addressable (~> 2.3) - http-cookie (~> 1.0) - http-form_data (~> 2.0) - http_parser.rb (~> 0.6.0) - http-cookie (1.0.3) - domain_name (~> 0.5) - http-form_data (2.1.1) - http_parser.rb (0.6.0) - httparty (0.13.7) - json (~> 1.8) - multi_xml (>= 0.5.2) - httpclient (2.8.3) - i18n (0.9.5) - concurrent-ruby (~> 1.0) - icalendar (2.4.1) - ice_nine (0.11.2) - influxdb (0.2.3) - cause - json - ipaddress (0.8.3) - jira-ruby (1.4.1) - activesupport - multipart-post - oauth (~> 0.5, >= 0.5.0) - jquery-atwho-rails (1.3.2) - js_regex (2.2.1) - regexp_parser (>= 0.4.11, <= 0.5.0) - json (1.8.6) - json-jwt (1.9.4) - activesupport - aes_key_wrap - bindata - json-schema (2.8.0) - addressable (>= 2.4) - jwt (1.5.6) - kaminari (1.0.1) - activesupport (>= 4.1.0) - kaminari-actionview (= 1.0.1) - kaminari-activerecord (= 1.0.1) - kaminari-core (= 1.0.1) - kaminari-actionview (1.0.1) - actionview - kaminari-core (= 1.0.1) - kaminari-activerecord (1.0.1) - activerecord - kaminari-core (= 1.0.1) - kaminari-core (1.0.1) - kgio (2.10.0) - knapsack (1.17.0) - rake - kubeclient (4.0.0) - http (~> 3.0) - recursive-open-struct (~> 1.0, >= 1.0.4) - rest-client (~> 2.0) - launchy (2.4.3) - addressable (~> 2.3) - letter_opener (1.4.1) - launchy (~> 2.2) - letter_opener_web (1.3.0) - actionmailer (>= 3.2) - letter_opener (~> 1.0) - railties (>= 3.2) - license_finder (5.4.0) - bundler - rubyzip - thor - toml (= 0.2.0) - with_env (= 1.1.0) - xml-simple - licensee (8.9.2) - rugged (~> 0.24) - locale (2.1.2) - lograge (0.10.0) - actionpack (>= 4) - activesupport (>= 4) - railties (>= 4) - request_store (~> 1.0) - loofah (2.2.3) - crass (~> 1.0.2) - nokogiri (>= 1.5.9) - mail (2.7.0) - mini_mime (>= 0.1.1) - mail_room (0.9.1) - memoist (0.16.0) - memoizable (0.4.2) - thread_safe (~> 0.3, >= 0.3.1) - method_source (0.9.0) - mime-types (3.2.2) - mime-types-data (~> 3.2015) - mime-types-data (3.2018.0812) - mimemagic (0.3.2) - mini_magick (4.8.0) - mini_mime (1.0.1) - mini_portile2 (2.3.0) - minitest (5.7.0) - msgpack (1.2.4) - multi_json (1.13.1) - multi_xml (0.6.0) - multipart-post (2.0.0) - mustermann (1.0.3) - mustermann-grape (1.0.0) - mustermann (~> 1.0.0) - mysql2 (0.4.10) - nakayoshi_fork (0.0.4) - net-ldap (0.16.0) - net-ssh (5.0.1) - netrc (0.11.0) - nokogiri (1.8.5) - mini_portile2 (~> 2.3.0) - nokogumbo (1.5.0) - nokogiri - numerizer (0.1.1) - oauth (0.5.4) - oauth2 (1.4.0) - faraday (>= 0.8, < 0.13) - jwt (~> 1.0) - multi_json (~> 1.3) - multi_xml (~> 0.5) - rack (>= 1.2, < 3) - octokit (4.9.0) - sawyer (~> 0.8.0, >= 0.5.3) - omniauth (1.8.1) - hashie (>= 3.4.6, < 3.6.0) - rack (>= 1.6.2, < 3) - omniauth-auth0 (2.0.0) - omniauth-oauth2 (~> 1.4) - omniauth-authentiq (0.3.3) - jwt (>= 1.5) - omniauth-oauth2 (>= 1.5) - omniauth-azure-oauth2 (0.0.9) - jwt (~> 1.0) - omniauth (~> 1.0) - omniauth-oauth2 (~> 1.4) - omniauth-cas3 (1.1.4) - addressable (~> 2.3) - nokogiri (~> 1.7, >= 1.7.1) - omniauth (~> 1.2) - omniauth-facebook (4.0.0) - omniauth-oauth2 (~> 1.2) - omniauth-github (1.3.0) - omniauth (~> 1.5) - omniauth-oauth2 (>= 1.4.0, < 2.0) - omniauth-gitlab (1.0.3) - omniauth (~> 1.0) - omniauth-oauth2 (~> 1.0) - omniauth-google-oauth2 (0.5.3) - jwt (>= 1.5) - omniauth (>= 1.1.1) - omniauth-oauth2 (>= 1.5) - omniauth-kerberos (0.3.0) - omniauth-multipassword - timfel-krb5-auth (~> 0.8) - omniauth-multipassword (0.4.2) - omniauth (~> 1.0) - omniauth-oauth (1.1.0) - oauth - omniauth (~> 1.0) - omniauth-oauth2 (1.5.0) - oauth2 (~> 1.1) - omniauth (~> 1.2) - omniauth-oauth2-generic (0.2.2) - omniauth-oauth2 (~> 1.0) - omniauth-saml (1.10.0) - omniauth (~> 1.3, >= 1.3.2) - ruby-saml (~> 1.7) - omniauth-shibboleth (1.3.0) - omniauth (>= 1.0.0) - omniauth-twitter (1.4.0) - omniauth-oauth (~> 1.1) - rack - omniauth_crowd (2.2.3) - activesupport - nokogiri (>= 1.4.4) - omniauth (~> 1.0) - org-ruby (0.9.12) - rubypants (~> 0.2) - orm_adapter (0.5.0) - os (1.0.0) - parallel (1.12.1) - parser (2.5.3.0) - ast (~> 2.4.0) - parslet (1.8.2) - peek (1.0.1) - concurrent-ruby (>= 0.9.0) - concurrent-ruby-ext (>= 0.9.0) - railties (>= 4.0.0) - peek-gc (0.0.2) - peek - peek-mysql2 (1.1.0) - atomic (>= 1.0.0) - mysql2 - peek - peek-pg (1.3.0) - concurrent-ruby - concurrent-ruby-ext - peek - pg - peek-rblineprof (0.2.0) - peek - rblineprof - peek-redis (1.2.0) - atomic (>= 1.0.0) - peek - redis - pg (0.18.4) - po_to_json (1.0.1) - json (>= 1.6.0) - powerpack (0.1.1) - premailer (1.10.4) - addressable - css_parser (>= 1.4.10) - htmlentities (>= 4.0.0) - premailer-rails (1.9.7) - actionmailer (>= 3, < 6) - premailer (~> 1.7, >= 1.7.9) - proc_to_ast (0.1.0) - coderay - parser - unparser - procto (0.0.3) - prometheus-client-mmap (0.9.4) - pry (0.11.3) - coderay (~> 1.1.0) - method_source (~> 0.9.0) - pry-byebug (3.4.3) - byebug (>= 9.0, < 9.1) - pry (~> 0.10) - pry-rails (0.3.6) - pry (>= 0.10.4) - public_suffix (3.0.3) - puma (3.12.0) - puma_worker_killer (0.1.0) - get_process_mem (~> 0.2) - puma (>= 2.7, < 4) - pyu-ruby-sasl (0.0.3.3) - rack (1.6.11) - rack-accept (0.4.5) - rack (>= 0.4) - rack-attack (4.4.1) - rack - rack-cors (1.0.2) - rack-oauth2 (1.2.3) - activesupport (>= 2.3) - attr_required (>= 0.0.5) - httpclient (>= 2.4) - multi_json (>= 1.3.6) - rack (>= 1.1) - rack-protection (2.0.4) - rack - rack-proxy (0.6.0) - rack - rack-test (0.6.3) - rack (>= 1.0) - rails (4.2.11) - actionmailer (= 4.2.11) - actionpack (= 4.2.11) - actionview (= 4.2.11) - activejob (= 4.2.11) - activemodel (= 4.2.11) - activerecord (= 4.2.11) - activesupport (= 4.2.11) - bundler (>= 1.3.0, < 2.0) - railties (= 4.2.11) - sprockets-rails - rails-deprecated_sanitizer (1.0.3) - activesupport (>= 4.2.0.alpha) - rails-dom-testing (1.0.9) - activesupport (>= 4.2.0, < 5.0) - nokogiri (~> 1.6) - rails-deprecated_sanitizer (>= 1.0.1) - rails-html-sanitizer (1.0.4) - loofah (~> 2.2, >= 2.2.2) - rails-i18n (4.0.9) - i18n (~> 0.7) - railties (~> 4.0) - railties (4.2.10) - actionpack (= 4.2.10) - activesupport (= 4.2.10) - rake (>= 0.8.7) - thor (>= 0.18.1, < 2.0) - rainbow (3.0.0) - raindrops (0.18.0) - rake (12.3.1) - rb-fsevent (0.10.2) - rb-inotify (0.9.10) - ffi (>= 0.5.0, < 2) - rblineprof (0.3.6) - debugger-ruby_core_source (~> 1.3) - rbtrace (0.4.10) - ffi (>= 1.0.6) - msgpack (>= 0.4.3) - trollop (>= 1.16.2) - rdoc (6.0.4) - re2 (1.1.1) - recaptcha (3.0.0) - json - recursive-open-struct (1.1.0) - redcarpet (3.4.0) - redis (3.3.5) - redis-actionpack (5.0.2) - actionpack (>= 4.0, < 6) - redis-rack (>= 1, < 3) - redis-store (>= 1.1.0, < 2) - redis-activesupport (5.0.4) - activesupport (>= 3, < 6) - redis-store (>= 1.3, < 2) - redis-namespace (1.6.0) - redis (>= 3.0.4) - redis-rack (2.0.4) - rack (>= 1.5, < 3) - redis-store (>= 1.2, < 2) - redis-rails (5.0.2) - redis-actionpack (>= 5.0, < 6) - redis-activesupport (>= 5.0, < 6) - redis-store (>= 1.2, < 2) - redis-store (1.6.0) - redis (>= 2.2, < 5) - regexp_parser (0.5.0) - representable (3.0.4) - declarative (< 0.1.0) - declarative-option (< 0.2.0) - uber (< 0.2.0) - request_store (1.3.1) - responders (2.4.0) - actionpack (>= 4.2.0, < 5.3) - railties (>= 4.2.0, < 5.3) - rest-client (2.0.2) - http-cookie (>= 1.0.2, < 2.0) - mime-types (>= 1.16, < 4.0) - netrc (~> 0.8) - retriable (3.1.2) - rinku (2.0.0) - rotp (2.1.2) - rouge (3.3.0) - rqrcode (0.7.0) - chunky_png - rqrcode-rails3 (0.1.7) - rqrcode (>= 0.4.2) - rspec (3.7.0) - rspec-core (~> 3.7.0) - rspec-expectations (~> 3.7.0) - rspec-mocks (~> 3.7.0) - rspec-core (3.7.1) - rspec-support (~> 3.7.0) - rspec-expectations (3.7.0) - diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.7.0) - rspec-mocks (3.7.0) - diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.7.0) - rspec-parameterized (0.4.1) - binding_ninja (>= 0.2.1) - parser - proc_to_ast - rspec (>= 2.13, < 4) - unparser - rspec-rails (3.7.2) - actionpack (>= 3.0) - activesupport (>= 3.0) - railties (>= 3.0) - rspec-core (~> 3.7.0) - rspec-expectations (~> 3.7.0) - rspec-mocks (~> 3.7.0) - rspec-support (~> 3.7.0) - rspec-retry (0.4.5) - rspec-core - rspec-set (0.1.3) - rspec-support (3.7.1) - rspec_junit_formatter (0.2.3) - builder (< 4) - rspec-core (>= 2, < 4, != 2.12.0) - rspec_profiling (0.0.5) - activerecord - pg - rails - sqlite3 - rubocop (0.54.0) - parallel (~> 1.10) - parser (>= 2.5) - powerpack (~> 0.1) - rainbow (>= 2.2.2, < 4.0) - ruby-progressbar (~> 1.7) - unicode-display_width (~> 1.0, >= 1.0.1) - rubocop-gitlab-security (0.1.1) - rubocop (>= 0.51) - rubocop-rspec (1.22.2) - rubocop (>= 0.52.1) - ruby-enum (0.7.2) - i18n - ruby-fogbugz (0.2.1) - crack (~> 0.4) - ruby-prof (0.17.0) - ruby-progressbar (1.9.0) - ruby-saml (1.7.2) - nokogiri (>= 1.5.10) - ruby_parser (3.11.0) - sexp_processor (~> 4.9) - rubyntlm (0.6.2) - rubypants (0.2.0) - rubyzip (1.2.2) - rufus-scheduler (3.4.0) - et-orbi (~> 1.0) - rugged (0.27.5) - safe_yaml (1.0.4) - sanitize (4.6.6) - crass (~> 1.0.2) - nokogiri (>= 1.4.4) - nokogumbo (~> 1.4) - sass (3.5.5) - sass-listen (~> 4.0.0) - sass-listen (4.0.0) - rb-fsevent (~> 0.9, >= 0.9.4) - rb-inotify (~> 0.9, >= 0.9.7) - sass-rails (5.0.6) - railties (>= 4.0.0, < 6) - sass (~> 3.1) - sprockets (>= 2.8, < 4.0) - sprockets-rails (>= 2.0, < 4.0) - tilt (>= 1.1, < 3) - sawyer (0.8.1) - addressable (>= 2.3.5, < 2.6) - faraday (~> 0.8, < 1.0) - scss_lint (0.56.0) - rake (>= 0.9, < 13) - sass (~> 3.5.3) - seed-fu (2.3.7) - activerecord (>= 3.1) - activesupport (>= 3.1) - select2-rails (3.5.9.3) - thor (~> 0.14) - selenium-webdriver (3.12.0) - childprocess (~> 0.5) - rubyzip (~> 1.2) - sentry-raven (2.7.2) - faraday (>= 0.7.6, < 1.0) - settingslogic (2.0.9) - sexp_processor (4.11.0) - sham_rack (1.3.6) - rack - shoulda-matchers (3.1.2) - activesupport (>= 4.0.0) - sidekiq (5.2.3) - connection_pool (~> 2.2, >= 2.2.2) - rack-protection (>= 1.5.0) - redis (>= 3.3.5, < 5) - sidekiq-cron (0.6.0) - rufus-scheduler (>= 3.3.0) - sidekiq (>= 4.2.1) - signet (0.11.0) - addressable (~> 2.3) - faraday (~> 0.9) - jwt (>= 1.5, < 3.0) - multi_json (~> 1.10) - simple_po_parser (1.1.2) - simplecov (0.14.1) - docile (~> 1.1.0) - json (>= 1.8, < 3) - simplecov-html (~> 0.10.0) - simplecov-html (0.10.0) - slack-notifier (1.5.1) - spring (2.0.2) - activesupport (>= 4.2) - spring-commands-rspec (1.0.4) - spring (>= 0.9.1) - sprockets (3.7.2) - concurrent-ruby (~> 1.0) - rack (> 1, < 3) - sprockets-rails (3.2.1) - actionpack (>= 4.0) - activesupport (>= 4.0) - sprockets (>= 3.0.0) - sqlite3 (1.3.13) - sshkey (1.9.0) - stackprof (0.2.10) - state_machines (0.5.0) - state_machines-activemodel (0.5.1) - activemodel (>= 4.1, < 6.0) - state_machines (>= 0.5.0) - state_machines-activerecord (0.5.1) - activerecord (>= 4.1, < 6.0) - state_machines-activemodel (>= 0.5.0) - sys-filesystem (1.1.6) - ffi - sysexits (1.2.0) - temple (0.8.0) - test-prof (0.2.5) - test_after_commit (1.1.0) - activerecord (>= 3.2) - text (1.3.1) - thin (1.7.2) - daemons (~> 1.0, >= 1.0.9) - eventmachine (~> 1.0, >= 1.0.4) - rack (>= 1, < 3) - thor (0.19.4) - thread_safe (0.3.6) - tilt (2.0.8) - timecop (0.8.1) - timfel-krb5-auth (0.8.3) - toml (0.2.0) - parslet (~> 1.8.0) - toml-rb (1.0.0) - citrus (~> 3.0, > 3.0) - trollop (2.1.3) - truncato (0.7.10) - htmlentities (~> 4.3.1) - nokogiri (~> 1.8.0, >= 1.7.0) - tzinfo (1.2.5) - thread_safe (~> 0.1) - u2f (0.2.1) - uber (0.1.0) - uglifier (2.7.2) - execjs (>= 0.3.0) - json (>= 1.8.0) - unf (0.1.4) - unf_ext - unf_ext (0.0.7.5) - unicode-display_width (1.3.2) - unicorn (5.1.0) - kgio (~> 2.6) - raindrops (~> 0.7) - unicorn-worker-killer (0.4.4) - get_process_mem (~> 0) - unicorn (>= 4, < 6) - uniform_notifier (1.10.0) - unparser (0.4.2) - abstract_type (~> 0.0.7) - adamantium (~> 0.2.0) - concord (~> 0.1.5) - diff-lcs (~> 1.3) - equalizer (~> 0.0.9) - parser (>= 2.3.1.2, < 2.6) - procto (~> 0.0.2) - validates_hostname (1.0.6) - activerecord (>= 3.0) - activesupport (>= 3.0) - version_sorter (2.1.0) - 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.7) - rack (>= 1.0) - webmock (2.3.2) - addressable (>= 2.3.6) - crack (>= 0.3.2) - hashdiff - webpack-rails (0.9.11) - railties (>= 3.2.0) - wikicloth (0.8.1) - builder - expression_parser - rinku - with_env (1.1.0) - xml-simple (1.1.5) - xpath (2.1.0) - nokogiri (~> 1.3) - -PLATFORMS - ruby - -DEPENDENCIES - RedCloth (~> 4.3.2) - ace-rails-ap (~> 4.1.0) - activerecord_sane_schema_dumper (= 0.2) - acts-as-taggable-on (~> 5.0) - addressable (~> 2.5.2) - akismet (~> 2.0) - asana (~> 0.8.1) - asciidoctor (~> 1.5.8) - asciidoctor-plantuml (= 0.0.8) - attr_encrypted (~> 3.1.0) - awesome_print - babosa (~> 1.0.2) - base32 (~> 0.3.0) - batch-loader (~> 1.2.2) - bcrypt_pbkdf (~> 1.0) - benchmark-ips (~> 2.3.0) - better_errors (~> 2.5.0) - binding_of_caller (~> 0.8.0) - bootsnap (~> 1.3) - bootstrap_form (~> 2.7.0) - brakeman (~> 4.2) - browser (~> 2.5) - bullet (~> 5.5.0) - bundler-audit (~> 0.5.0) - capybara (~> 2.15) - capybara-screenshot (~> 1.0.0) - carrierwave (= 1.2.3) - charlock_holmes (~> 0.7.5) - chronic (~> 0.10.2) - chronic_duration (~> 0.10.6) - commonmarker (~> 0.17) - concurrent-ruby (~> 1.1) - connection_pool (~> 2.0) - creole (~> 0.5.0) - database_cleaner (~> 1.5.0) - deckar01-task_list (= 2.0.0) - default_value_for (~> 3.0.0) - device_detector - devise (~> 4.4) - devise-two-factor (~> 3.0.0) - diffy (~> 3.1.0) - discordrb-webhooks-blackst0ne (~> 3.3) - doorkeeper (~> 4.3) - doorkeeper-openid_connect (~> 1.5) - ed25519 (~> 1.2) - email_reply_trimmer (~> 0.1) - email_spec (~> 2.2.0) - escape_utils (~> 1.1) - factory_bot_rails (~> 4.8.2) - faraday (~> 0.12) - fast_blank - ffaker (~> 2.10) - flipper (~> 0.13.0) - flipper-active_record (~> 0.13.0) - flipper-active_support_cache_store (~> 0.13.0) - flowdock (~> 0.7) - fog-aliyun (~> 0.2.0) - fog-aws (~> 2.0.1) - fog-core (~> 1.44) - fog-google (~> 1.7.1) - fog-local (~> 0.3) - fog-openstack (~> 0.1) - fog-rackspace (~> 0.1.1) - font-awesome-rails (~> 4.7) - foreman (~> 0.84.0) - fuubar (~> 2.2.0) - gemojione (~> 3.3) - gettext (~> 3.2.2) - gettext_i18n_rails (~> 1.8.0) - gettext_i18n_rails_js (~> 1.3) - gitaly-proto (~> 1.3.0) - github-markup (~> 1.7.0) - gitlab-markup (~> 1.6.5) - gitlab-sidekiq-fetcher - gitlab-styles (~> 2.4) - gitlab_omniauth-ldap (~> 2.0.4) - gon (~> 6.2) - google-api-client (~> 0.23) - google-protobuf (~> 3.6) - gpgme (~> 2.0.18) - grape (~> 1.1.0) - grape-entity (~> 0.7.1) - grape-path-helpers (~> 1.0) - grape_logging (~> 1.7) - graphiql-rails (~> 1.4.10) - graphql (~> 1.8.0) - grpc (~> 1.15.0) - haml_lint (~> 0.28.0) - hamlit (~> 2.8.8) - hangouts-chat (~> 0.0.5) - hashie-forbidden_attributes - health_check (~> 2.6.0) - hipchat (~> 1.5.0) - html-pipeline (~> 2.8) - html2text - httparty (~> 0.13.3) - icalendar - influxdb (~> 0.2) - jira-ruby (~> 1.4) - jquery-atwho-rails (~> 1.3.2) - js_regex (~> 2.2.1) - json-schema (~> 2.8.0) - jwt (~> 1.5.6) - kaminari (~> 1.0) - knapsack (~> 1.17) - kubeclient (~> 4.0.0) - letter_opener_web (~> 1.3.0) - license_finder (~> 5.4) - licensee (~> 8.9) - lograge (~> 0.5) - loofah (~> 2.2) - mail_room (~> 0.9.1) - method_source (~> 0.8) - mimemagic (~> 0.3.2) - mini_magick - minitest (~> 5.7.0) - mysql2 (~> 0.4.10) - nakayoshi_fork (~> 0.0.4) - net-ldap - net-ssh (~> 5.0) - nokogiri (~> 1.8.2) - oauth2 (~> 1.4) - octokit (~> 4.9) - omniauth (~> 1.8) - omniauth-auth0 (~> 2.0.0) - omniauth-authentiq (~> 0.3.3) - omniauth-azure-oauth2 (~> 0.0.9) - omniauth-cas3 (~> 1.1.4) - omniauth-facebook (~> 4.0.0) - omniauth-github (~> 1.3) - omniauth-gitlab (~> 1.0.2) - omniauth-google-oauth2 (~> 0.5.3) - omniauth-kerberos (~> 0.3.0) - omniauth-oauth2-generic (~> 0.2.2) - omniauth-saml (~> 1.10) - omniauth-shibboleth (~> 1.3.0) - omniauth-twitter (~> 1.4) - omniauth_crowd (~> 2.2.0) - org-ruby (~> 0.9.12) - peek (~> 1.0.1) - peek-gc (~> 0.0.2) - peek-mysql2 (~> 1.1.0) - peek-pg (~> 1.3.0) - peek-rblineprof (~> 0.2.0) - peek-redis (~> 1.2.0) - pg (~> 0.18.2) - premailer-rails (~> 1.9.7) - prometheus-client-mmap (~> 0.9.4) - pry-byebug (~> 3.4.1) - pry-rails (~> 0.3.4) - puma (~> 3.12) - puma_worker_killer - rack (= 1.6.11) - rack-attack (~> 4.4.1) - rack-cors (~> 1.0.0) - rack-oauth2 (~> 1.2.1) - rack-proxy (~> 0.6.0) - rails (= 4.2.11) - rails-deprecated_sanitizer (~> 1.0.3) - rails-i18n (~> 4.0.9) - rainbow (~> 3.0) - raindrops (~> 0.18) - rblineprof (~> 0.3.6) - rbtrace (~> 0.4) - rdoc (~> 6.0) - re2 (~> 1.1.1) - recaptcha (~> 3.0) - redcarpet (~> 3.4) - redis (~> 3.2) - redis-namespace (~> 1.6.0) - redis-rails (~> 5.0.2) - request_store (~> 1.3) - responders (~> 2.0) - rouge (~> 3.1) - rqrcode-rails3 (~> 0.1.7) - rspec-parameterized - rspec-rails (~> 3.7.0) - rspec-retry (~> 0.4.5) - rspec-set (~> 0.1.3) - rspec_junit_formatter - rspec_profiling (~> 0.0.5) - rubocop (~> 0.54.0) - rubocop-rspec (~> 1.22.1) - ruby-fogbugz (~> 0.2.1) - ruby-prof (~> 0.17.0) - ruby-progressbar - ruby_parser (~> 3.8) - rufus-scheduler (~> 3.4) - rugged (~> 0.27) - sanitize (~> 4.6) - sass (~> 3.5) - sass-rails (~> 5.0.6) - scss_lint (~> 0.56.0) - seed-fu (~> 2.3.7) - select2-rails (~> 3.5.9) - selenium-webdriver (~> 3.12) - sentry-raven (~> 2.7) - settingslogic (~> 2.0.9) - sham_rack (~> 1.3.6) - shoulda-matchers (~> 3.1.2) - sidekiq (~> 5.2.1) - sidekiq-cron (~> 0.6.0) - simple_po_parser (~> 1.1.2) - simplecov (~> 0.14.0) - slack-notifier (~> 1.5.1) - spring (~> 2.0.0) - spring-commands-rspec (~> 1.0.4) - sprockets (~> 3.7.0) - sshkey (~> 1.9.0) - stackprof (~> 0.2.10) - state_machines-activerecord (~> 0.5.1) - sys-filesystem (~> 1.1.6) - test-prof (~> 0.2.5) - test_after_commit (~> 1.1) - thin (~> 1.7.0) - timecop (~> 0.8.0) - toml-rb (~> 1.0.0) - truncato (~> 0.7.9) - u2f (~> 0.2.1) - uglifier (~> 2.7.2) - unf (~> 0.1.4) - unicorn (~> 5.1.0) - unicorn-worker-killer (~> 0.4.4) - validates_hostname (~> 1.0.6) - version_sorter (~> 2.1.0) - virtus (~> 1.0.1) - vmstat (~> 2.3.0) - webmock (~> 2.3.2) - webpack-rails (~> 0.9.10) - wikicloth (= 0.8.1) - -BUNDLED WITH - 1.17.1 diff --git a/app/assets/javascripts/blob_edit/blob_bundle.js b/app/assets/javascripts/blob_edit/blob_bundle.js index 9f547471170..b07f951346e 100644 --- a/app/assets/javascripts/blob_edit/blob_bundle.js +++ b/app/assets/javascripts/blob_edit/blob_bundle.js @@ -17,6 +17,11 @@ export default () => { const currentAction = $('.js-file-title').data('currentAction'); const projectId = editBlobForm.data('project-id'); const commitButton = $('.js-commit-button'); + const cancelLink = $('.btn.btn-cancel'); + + cancelLink.on('click', () => { + window.onbeforeunload = null; + }); commitButton.on('click', () => { window.onbeforeunload = null; diff --git a/app/assets/javascripts/diffs/components/diff_content.vue b/app/assets/javascripts/diffs/components/diff_content.vue index ac963f2971e..42d09e44768 100644 --- a/app/assets/javascripts/diffs/components/diff_content.vue +++ b/app/assets/javascripts/diffs/components/diff_content.vue @@ -1,6 +1,7 @@ <script> import { mapActions, mapGetters, mapState } from 'vuex'; import DiffViewer from '~/vue_shared/components/diff_viewer/diff_viewer.vue'; +import EmptyFileViewer from '~/vue_shared/components/diff_viewer/viewers/empty_file.vue'; import InlineDiffView from './inline_diff_view.vue'; import ParallelDiffView from './parallel_diff_view.vue'; import NoteForm from '../../notes/components/note_form.vue'; @@ -17,6 +18,7 @@ export default { NoteForm, DiffDiscussions, ImageDiffOverlay, + EmptyFileViewer, }, props: { diffFile: { @@ -75,14 +77,15 @@ export default { <div class="diff-content"> <div class="diff-viewer"> <template v-if="isTextFile"> + <empty-file-viewer v-if="diffFile.empty" /> <inline-diff-view - v-if="isInlineView" + v-else-if="isInlineView" :diff-file="diffFile" :diff-lines="diffFile.highlighted_diff_lines || []" :help-page-path="helpPagePath" /> <parallel-diff-view - v-if="isParallelView" + v-else-if="isParallelView" :diff-file="diffFile" :diff-lines="diffFile.parallel_diff_lines || []" :help-page-path="helpPagePath" diff --git a/app/assets/javascripts/notes/components/noteable_discussion.vue b/app/assets/javascripts/notes/components/noteable_discussion.vue index 4156fe0d229..07c938a0021 100644 --- a/app/assets/javascripts/notes/components/noteable_discussion.vue +++ b/app/assets/javascripts/notes/components/noteable_discussion.vue @@ -413,7 +413,7 @@ Please check your network connection and try again.`; </template> </ul> <div - v-if="!isRepliesCollapsed" + v-if="!isRepliesCollapsed || !hasReplies" :class="{ 'is-replying': isReplying }" class="discussion-reply-holder" > diff --git a/app/assets/javascripts/pages/projects/issues/form.js b/app/assets/javascripts/pages/projects/issues/form.js index 02a56685a35..f99023ad8e7 100644 --- a/app/assets/javascripts/pages/projects/issues/form.js +++ b/app/assets/javascripts/pages/projects/issues/form.js @@ -17,7 +17,7 @@ export default () => { new MilestoneSelect(); new IssuableTemplateSelectors(); - if (gon.features.issueSuggestions && gon.features.graphql) { + if (gon.features.graphql) { initSuggestions(); } }; diff --git a/app/assets/javascripts/releases/components/release_block.vue b/app/assets/javascripts/releases/components/release_block.vue new file mode 100644 index 00000000000..bd65a225d8f --- /dev/null +++ b/app/assets/javascripts/releases/components/release_block.vue @@ -0,0 +1,145 @@ +<script> +import { GlTooltipDirective, GlLink } from '@gitlab/ui'; +import Icon from '~/vue_shared/components/icon.vue'; +import UserAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue'; +import timeagoMixin from '~/vue_shared/mixins/timeago'; +import { sprintf } from '../../locale'; + +export default { + name: 'ReleaseBlock', + components: { + GlLink, + Icon, + UserAvatarLink, + }, + directives: { + GlTooltip: GlTooltipDirective, + }, + mixins: [timeagoMixin], + props: { + name: { + type: String, + required: true, + }, + tag: { + type: String, + required: true, + }, + commit: { + type: Object, + required: true, + }, + description: { + type: String, + required: false, + default: '', + }, + author: { + type: Object, + required: true, + }, + createdAt: { + type: String, + required: false, + default: '', + }, + assetsCount: { + type: Number, + required: false, + default: 0, + }, + sources: { + type: Array, + required: false, + default: () => [], + }, + links: { + type: Array, + required: false, + default: () => [], + }, + }, + computed: { + releasedTimeAgo() { + return sprintf('released %{time}', { + time: this.timeFormated(this.createdAt), + }); + }, + userImageAltDescription() { + return this.author && this.author.username + ? sprintf("%{username}'s avatar", { username: this.author.username }) + : null; + }, + }, +}; +</script> +<template> + <div class="card"> + <div class="card-body"> + <h2 class="card-title mt-0">{{ name }}</h2> + + <div class="card-subtitle d-flex flex-wrap text-secondary"> + <div class="append-right-8"> + <icon name="commit" class="align-middle" /> + <span v-gl-tooltip.bottom :title="commit.title">{{ commit.short_id }}</span> + </div> + + <div class="append-right-8"> + <icon name="tag" class="align-middle" /> + <span v-gl-tooltip.bottom :title="__('Tag')">{{ tag }}</span> + </div> + + <div class="append-right-4"> + • + <span v-gl-tooltip.bottom :title="tooltipTitle(createdAt)">{{ releasedTimeAgo }}</span> + </div> + + <div class="d-flex"> + by + <user-avatar-link + class="prepend-left-4" + :link-href="author.path" + :img-src="author.avatar_url" + :img-alt="userImageAltDescription" + :tooltip-text="author.username" + /> + </div> + </div> + + <div class="card-text prepend-top-default"> + <b> + {{ __('Assets') }} <span class="js-assets-count badge badge-pill">{{ assetsCount }}</span> + </b> + + <ul class="pl-0 mb-0 prepend-top-8 list-unstyled js-assets-list"> + <li v-for="link in links" :key="link.name" class="append-bottom-8"> + <gl-link v-gl-tooltip.bottom :title="__('Download asset')" :href="link.url"> + <icon name="package" class="align-middle append-right-4" /> {{ link.name }} + </gl-link> + </li> + </ul> + + <div class="dropdown"> + <button + type="button" + class="btn btn-link" + data-toggle="dropdown" + aria-haspopup="true" + aria-expanded="false" + > + <icon name="doc-code" class="align-top append-right-4" /> {{ __('Source code') }} + <icon name="arrow-down" /> + </button> + + <div class="js-sources-dropdown dropdown-menu"> + <li v-for="asset in sources" :key="asset.url"> + <gl-link :href="asset.url">{{ __('Download') }} {{ asset.format }}</gl-link> + </li> + </div> + </div> + </div> + + <div class="card-text prepend-top-default"><div v-html="description"></div></div> + </div> + </div> +</template> diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_rebase.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_rebase.vue index adfbcd18588..0bcccc50eb2 100644 --- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_rebase.vue +++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_rebase.vue @@ -72,7 +72,7 @@ export default { Flash('Something went wrong. Please try again.'); } - eventHub.$emit('MRWidgetUpdateRequested'); + eventHub.$emit('MRWidgetRebaseSuccess'); stopPolling(); } }) diff --git a/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue b/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue index 3c3e3efcc36..d8a75388e84 100644 --- a/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue +++ b/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue @@ -155,13 +155,13 @@ export default { }; return new MRWidgetService(endpoints); }, - checkStatus(cb) { + checkStatus(cb, isRebased) { return this.service .checkStatus() .then(res => res.data) .then(data => { this.handleNotification(data); - this.mr.setData(data); + this.mr.setData(data, isRebased); this.setFaviconHelper(); if (cb) { @@ -263,6 +263,10 @@ export default { this.checkStatus(cb); }); + eventHub.$on('MRWidgetRebaseSuccess', cb => { + this.checkStatus(cb, true); + }); + // `params` should be an Array contains a Boolean, like `[true]` // Passing parameter as Boolean didn't work. eventHub.$on('SetBranchRemoveFlag', params => { diff --git a/app/assets/javascripts/vue_merge_request_widget/stores/get_state_key.js b/app/assets/javascripts/vue_merge_request_widget/stores/get_state_key.js index f7f0c1b6cb7..066a3b833d7 100644 --- a/app/assets/javascripts/vue_merge_request_widget/stores/get_state_key.js +++ b/app/assets/javascripts/vue_merge_request_widget/stores/get_state_key.js @@ -19,7 +19,7 @@ export default function deviseState(data) { return stateKey.unresolvedDiscussions; } else if (this.isPipelineBlocked) { return stateKey.pipelineBlocked; - } else if (this.hasSHAChanged) { + } else if (this.isSHAMismatch) { return stateKey.shaMismatch; } else if (this.mergeWhenPipelineSucceeds) { return this.mergeError ? stateKey.autoMergeFailed : stateKey.mergeWhenPipelineSucceeds; diff --git a/app/assets/javascripts/vue_merge_request_widget/stores/mr_widget_store.js b/app/assets/javascripts/vue_merge_request_widget/stores/mr_widget_store.js index 5c9a7133a6e..c777bcca0fa 100644 --- a/app/assets/javascripts/vue_merge_request_widget/stores/mr_widget_store.js +++ b/app/assets/javascripts/vue_merge_request_widget/stores/mr_widget_store.js @@ -11,7 +11,11 @@ export default class MergeRequestStore { this.setData(data); } - setData(data) { + setData(data, isRebased) { + if (isRebased) { + this.sha = data.diff_head_sha; + } + const currentUser = data.current_user; const pipelineStatus = data.pipeline ? data.pipeline.details.status : null; @@ -84,7 +88,7 @@ export default class MergeRequestStore { this.canMerge = !!data.merge_path; this.canCreateIssue = currentUser.can_create_issue || false; this.canCancelAutomaticMerge = !!data.cancel_merge_when_pipeline_succeeds_path; - this.hasSHAChanged = this.sha !== data.diff_head_sha; + this.isSHAMismatch = this.sha !== data.diff_head_sha; this.canBeMerged = data.can_be_merged || false; this.isMergeAllowed = data.mergeable || false; this.mergeOngoing = data.merge_ongoing; diff --git a/app/assets/javascripts/vue_shared/components/diff_viewer/viewers/empty_file.vue b/app/assets/javascripts/vue_shared/components/diff_viewer/viewers/empty_file.vue new file mode 100644 index 00000000000..53210cbcc93 --- /dev/null +++ b/app/assets/javascripts/vue_shared/components/diff_viewer/viewers/empty_file.vue @@ -0,0 +1,3 @@ +<template> + <div class="nothing-here-block">{{ __('Empty file') }}</div> +</template> diff --git a/app/assets/stylesheets/framework/dropdowns.scss b/app/assets/stylesheets/framework/dropdowns.scss index b47b1cb76dc..afcb230797a 100644 --- a/app/assets/stylesheets/framework/dropdowns.scss +++ b/app/assets/stylesheets/framework/dropdowns.scss @@ -534,8 +534,9 @@ .dropdown-title { position: relative; - padding: 2px 25px 10px; - margin: 0 10px 10px; + padding: $dropdown-item-padding-y $dropdown-item-padding-x; + padding-bottom: #{2 * $dropdown-item-padding-y}; + margin-bottom: $dropdown-item-padding-y; font-weight: $gl-font-weight-bold; line-height: 1; text-align: center; diff --git a/app/controllers/graphql_controller.rb b/app/controllers/graphql_controller.rb index 6ea4758ec32..3ef03bc9622 100644 --- a/app/controllers/graphql_controller.rb +++ b/app/controllers/graphql_controller.rb @@ -43,6 +43,6 @@ class GraphqlController < ApplicationController end def check_graphql_feature_flag! - render_404 unless Feature.enabled?(:graphql) + render_404 unless Gitlab::Graphql.enabled? end end diff --git a/app/controllers/projects/issues_controller.rb b/app/controllers/projects/issues_controller.rb index c6ab6b4642e..5ed46fc0545 100644 --- a/app/controllers/projects/issues_controller.rb +++ b/app/controllers/projects/issues_controller.rb @@ -268,7 +268,6 @@ class Projects::IssuesController < Projects::ApplicationController end def set_suggested_issues_feature_flags - push_frontend_feature_flag(:graphql) - push_frontend_feature_flag(:issue_suggestions) + push_frontend_feature_flag(:graphql, default_enabled: true) end end diff --git a/app/helpers/version_check_helper.rb b/app/helpers/version_check_helper.rb index ab77b149072..5e519cf5c19 100644 --- a/app/helpers/version_check_helper.rb +++ b/app/helpers/version_check_helper.rb @@ -6,8 +6,7 @@ module VersionCheckHelper return unless Gitlab::CurrentSettings.version_check_enabled return if User.single_user&.requires_usage_stats_consent? - image_url = VersionCheck.new.url - image_tag image_url, class: 'js-version-status-badge' + image_tag VersionCheck.url, class: 'js-version-status-badge' end def link_to_version diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb index d06022a0fb7..2cdb4780412 100644 --- a/app/models/ci/pipeline.rb +++ b/app/models/ci/pipeline.rb @@ -68,11 +68,7 @@ module Ci # this `Hash` with new values. enum_with_nil source: ::Ci::PipelineEnums.sources - enum_with_nil config_source: { - unknown_source: nil, - repository_source: 1, - auto_devops_source: 2 - } + enum_with_nil config_source: ::Ci::PipelineEnums.config_sources # We use `Ci::PipelineEnums.failure_reasons` here so that EE can more easily # extend this `Hash` with new values. diff --git a/app/models/ci/pipeline_enums.rb b/app/models/ci/pipeline_enums.rb index c0f16066e0b..2994aaae4aa 100644 --- a/app/models/ci/pipeline_enums.rb +++ b/app/models/ci/pipeline_enums.rb @@ -25,5 +25,15 @@ module Ci merge_request: 10 } end + + # Returns the `Hash` to use for creating the `config_sources` enum for + # `Ci::Pipeline`. + def self.config_sources + { + unknown_source: nil, + repository_source: 1, + auto_devops_source: 2 + } + end end end diff --git a/app/models/clusters/applications/knative.rb b/app/models/clusters/applications/knative.rb index 168a24da738..0c72d7d8340 100644 --- a/app/models/clusters/applications/knative.rb +++ b/app/models/clusters/applications/knative.rb @@ -3,7 +3,7 @@ module Clusters module Applications class Knative < ActiveRecord::Base - VERSION = '0.1.3'.freeze + VERSION = '0.2.2'.freeze REPOSITORY = 'https://storage.googleapis.com/triggermesh-charts'.freeze FETCH_IP_ADDRESS_DELAY = 30.seconds diff --git a/app/models/release.rb b/app/models/release.rb index cba80ad30ca..7a09ee459a6 100644 --- a/app/models/release.rb +++ b/app/models/release.rb @@ -6,6 +6,7 @@ class Release < ActiveRecord::Base cache_markdown_field :description belongs_to :project + belongs_to :author, class_name: 'User' validates :description, :project, :tag, presence: true end diff --git a/app/models/user.rb b/app/models/user.rb index dbd754dd25a..f20756d1cc3 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -130,6 +130,7 @@ class User < ActiveRecord::Base has_many :issues, dependent: :destroy, foreign_key: :author_id # rubocop:disable Cop/ActiveRecordDependent has_many :merge_requests, dependent: :destroy, foreign_key: :author_id # rubocop:disable Cop/ActiveRecordDependent has_many :events, dependent: :destroy, foreign_key: :author_id # rubocop:disable Cop/ActiveRecordDependent + has_many :releases, dependent: :nullify, foreign_key: :author_id # rubocop:disable Cop/ActiveRecordDependent has_many :subscriptions, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent has_many :oauth_applications, class_name: 'Doorkeeper::Application', as: :owner, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent has_one :abuse_report, dependent: :destroy, foreign_key: :user_id # rubocop:disable Cop/ActiveRecordDependent diff --git a/app/presenters/clusters/cluster_presenter.rb b/app/presenters/clusters/cluster_presenter.rb index 7e6eccb648c..0473bb8c72a 100644 --- a/app/presenters/clusters/cluster_presenter.rb +++ b/app/presenters/clusters/cluster_presenter.rb @@ -12,6 +12,14 @@ module Clusters can?(current_user, :update_cluster, cluster) && created? end + def cluster_type_description + if cluster.project_type? + s_("ClusterIntegration|Project cluster") + elsif cluster.group_type? + s_("ClusterIntegration|Group cluster") + end + end + def show_path if cluster.project_type? project_cluster_path(project, cluster) diff --git a/app/serializers/diff_file_entity.rb b/app/serializers/diff_file_entity.rb index f0881829efd..b0aaec3326d 100644 --- a/app/serializers/diff_file_entity.rb +++ b/app/serializers/diff_file_entity.rb @@ -5,6 +5,7 @@ class DiffFileEntity < DiffFileBaseEntity include IconsHelper expose :too_large?, as: :too_large + expose :empty?, as: :empty expose :added_lines expose :removed_lines diff --git a/app/serializers/issue_board_entity.rb b/app/serializers/issue_board_entity.rb index 58ab804a3c8..e3dc43240c6 100644 --- a/app/serializers/issue_board_entity.rb +++ b/app/serializers/issue_board_entity.rb @@ -17,7 +17,7 @@ class IssueBoardEntity < Grape::Entity end expose :milestone, expose_nil: false do |issue| - API::Entities::Project.represent issue.milestone, only: [:id, :title] + API::Entities::Milestone.represent issue.milestone, only: [:id, :title] end expose :assignees do |issue| diff --git a/app/services/create_release_service.rb b/app/services/create_release_service.rb index 8d1fdbe11c3..ab2dc5337aa 100644 --- a/app/services/create_release_service.rb +++ b/app/services/create_release_service.rb @@ -13,8 +13,13 @@ class CreateReleaseService < BaseService if release error('Release already exists', 409) else - release = project.releases.new({ tag: tag_name, description: release_description }) - release.save + release = project.releases.create!( + tag: tag_name, + name: tag_name, + sha: existing_tag.dereferenced_target.sha, + author: current_user, + description: release_description + ) success(release) end diff --git a/app/services/labels/promote_service.rb b/app/services/labels/promote_service.rb index f30ad706c63..3c0e6196d4f 100644 --- a/app/services/labels/promote_service.rb +++ b/app/services/labels/promote_service.rb @@ -57,7 +57,7 @@ module Labels def update_issuables(new_label, label_ids) LabelLink .where(label: label_ids) - .update_all(label_id: new_label) + .update_all(label_id: new_label.id) end # rubocop: enable CodeReuse/ActiveRecord @@ -65,7 +65,7 @@ module Labels def update_resource_label_events(new_label, label_ids) ResourceLabelEvent .where(label: label_ids) - .update_all(label_id: new_label) + .update_all(label_id: new_label.id) end # rubocop: enable CodeReuse/ActiveRecord @@ -73,7 +73,7 @@ module Labels def update_issue_board_lists(new_label, label_ids) List .where(label: label_ids) - .update_all(label_id: new_label) + .update_all(label_id: new_label.id) end # rubocop: enable CodeReuse/ActiveRecord @@ -81,7 +81,7 @@ module Labels def update_priorities(new_label, label_ids) LabelPriority .where(label: label_ids) - .update_all(label_id: new_label) + .update_all(label_id: new_label.id) end # rubocop: enable CodeReuse/ActiveRecord diff --git a/app/services/projects/lfs_pointers/lfs_download_service.rb b/app/services/projects/lfs_pointers/lfs_download_service.rb index 1c4a8d05be6..f9b9781ad5f 100644 --- a/app/services/projects/lfs_pointers/lfs_download_service.rb +++ b/app/services/projects/lfs_pointers/lfs_download_service.rb @@ -4,6 +4,8 @@ module Projects module LfsPointers class LfsDownloadService < BaseService + VALID_PROTOCOLS = %w[http https].freeze + # rubocop: disable CodeReuse/ActiveRecord def execute(oid, url) return unless project&.lfs_enabled? && oid.present? && url.present? @@ -11,6 +13,7 @@ module Projects return if LfsObject.exists?(oid: oid) sanitized_uri = Gitlab::UrlSanitizer.new(url) + Gitlab::UrlBlocker.validate!(sanitized_uri.sanitized_url, protocols: VALID_PROTOCOLS) with_tmp_file(oid) do |file| size = download_and_save_file(file, sanitized_uri) diff --git a/app/services/tags/create_service.rb b/app/services/tags/create_service.rb index 35390f5082c..6bb9bb3988e 100644 --- a/app/services/tags/create_service.rb +++ b/app/services/tags/create_service.rb @@ -20,7 +20,7 @@ module Tags end if new_tag - if release_description + if release_description.present? CreateReleaseService.new(@project, @current_user) .execute(tag_name, release_description) end diff --git a/app/views/clusters/clusters/_cluster.html.haml b/app/views/clusters/clusters/_cluster.html.haml index adeca013749..e15de3d504d 100644 --- a/app/views/clusters/clusters/_cluster.html.haml +++ b/app/views/clusters/clusters/_cluster.html.haml @@ -13,4 +13,4 @@ .table-mobile-header{ role: "rowheader" } .table-mobile-content %span.badge.badge-light - = cluster.project_type? ? s_("ClusterIntegration|Project cluster") : s_("ClusterIntegration|Group cluster") + = cluster.cluster_type_description diff --git a/app/views/shared/issuable/_form.html.haml b/app/views/shared/issuable/_form.html.haml index 1618655182c..c6a391ae563 100644 --- a/app/views/shared/issuable/_form.html.haml +++ b/app/views/shared/issuable/_form.html.haml @@ -17,7 +17,7 @@ = render 'shared/issuable/form/template_selector', issuable: issuable = render 'shared/issuable/form/title', issuable: issuable, form: form, has_wip_commits: commits && commits.detect(&:work_in_progress?) -- if Feature.enabled?(:issue_suggestions) && Feature.enabled?(:graphql) +- if Gitlab::Graphql.enabled? #js-suggestions{ data: { project_path: @project.full_path } } = render 'shared/form_elements/description', model: issuable, form: form, project: project diff --git a/bin/rails b/bin/rails index d21b64b3007..07396602377 100755 --- a/bin/rails +++ b/bin/rails @@ -1,14 +1,4 @@ #!/usr/bin/env ruby - -# Remove this block when upgraded to rails 5.0. -if %w[0 false].include?(ENV["RAILS5"]) - begin - load File.expand_path('../spring', __FILE__) - rescue LoadError => e - raise unless e.message.include?('spring') - end -end - APP_PATH = File.expand_path('../config/application', __dir__) require_relative '../config/boot' require 'rails/commands' @@ -1,14 +1,4 @@ #!/usr/bin/env ruby - -# Remove this block when upgraded to rails 5.0. -if %w[0 false].include?(ENV["RAILS5"]) - begin - load File.expand_path('../spring', __FILE__) - rescue LoadError => e - raise unless e.message.include?('spring') - end -end - require_relative '../config/boot' require 'rake' Rake.application.run diff --git a/bin/rspec b/bin/rspec index b0770e30a70..4236753c9c1 100755 --- a/bin/rspec +++ b/bin/rspec @@ -1,10 +1,5 @@ #!/usr/bin/env ruby -# Remove these two lines below when upgraded to rails 5.0. -# Allow run `rspec` command as `RAILS5=1 rspec ...` instead of `BUNDLE_GEMFILE=Gemfile.rails5 rspec ...` -gemfile = %w[0 false].include?(ENV["RAILS5"]) ? "Gemfile.rails4" : "Gemfile" -ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../#{gemfile}", __dir__) - begin load File.expand_path('../spring', __FILE__) rescue LoadError => e diff --git a/bin/setup b/bin/setup index 34bb667087a..883825bc0a2 100755 --- a/bin/setup +++ b/bin/setup @@ -1,18 +1,12 @@ #!/usr/bin/env ruby -def rails5? - !%w[0 false].include?(ENV["RAILS5"]) -end - require "pathname" # path to your application root. APP_ROOT = Pathname.new File.expand_path("../../", __FILE__) -if rails5? - def system!(*args) - system(*args) || abort("\n== Command #{args} failed ==") - end +def system!(*args) + system(*args) || abort("\n== Command #{args} failed ==") end Dir.chdir APP_ROOT do @@ -20,14 +14,8 @@ Dir.chdir APP_ROOT do # Add necessary setup steps to this file: puts "== Installing dependencies ==" - - if rails5? - system! "gem install bundler --conservative" - system("bundle check") || system!("bundle install") - else - system "gem install bundler --conservative" - system "bundle check || bundle install" - end + system! "gem install bundler --conservative" + system("bundle check") || system!("bundle install") # puts "\n== Copying sample files ==" # unless File.exist?("config/database.yml") @@ -35,27 +23,11 @@ Dir.chdir APP_ROOT do # end puts "\n== Preparing database ==" - - if rails5? - system! "bin/rails db:setup" - else - system "bin/rake db:reset" - end + system! "bin/rails db:setup" puts "\n== Removing old logs and tempfiles ==" - - if rails5? - system! "bin/rails log:clear tmp:clear" - else - system "rm -f log/*" - system "rm -rf tmp/cache" - end + system! "bin/rails log:clear tmp:clear" puts "\n== Restarting application server ==" - - if rails5? - system! "bin/rails restart" - else - system "touch tmp/restart.txt" - end + system! "bin/rails restart" end diff --git a/changelogs/unreleased/41766-vue-component.yml b/changelogs/unreleased/41766-vue-component.yml new file mode 100644 index 00000000000..12343c8ce84 --- /dev/null +++ b/changelogs/unreleased/41766-vue-component.yml @@ -0,0 +1,5 @@ +--- +title: Creates component for release block +merge_request: 23697 +author: +type: added diff --git a/changelogs/unreleased/47052-merge-button-does-not-appear-after-rebase-ing.yml b/changelogs/unreleased/47052-merge-button-does-not-appear-after-rebase-ing.yml new file mode 100644 index 00000000000..fd1e4605f2d --- /dev/null +++ b/changelogs/unreleased/47052-merge-button-does-not-appear-after-rebase-ing.yml @@ -0,0 +1,5 @@ +--- +title: Allow merge after rebase without page refresh on FF repositories +merge_request: 23572 +author: +type: fixed diff --git a/changelogs/unreleased/54786-mr-empty-file-display.yml b/changelogs/unreleased/54786-mr-empty-file-display.yml new file mode 100644 index 00000000000..5adf5744755 --- /dev/null +++ b/changelogs/unreleased/54786-mr-empty-file-display.yml @@ -0,0 +1,5 @@ +--- +title: Display empty files properly on MR diffs +merge_request: 23671 +author: Sean Nichols +type: fixed diff --git a/changelogs/unreleased/55344-only-prompt-user-once-when-navigating-away-from-file-editor.yml b/changelogs/unreleased/55344-only-prompt-user-once-when-navigating-away-from-file-editor.yml new file mode 100644 index 00000000000..9c4d73c5323 --- /dev/null +++ b/changelogs/unreleased/55344-only-prompt-user-once-when-navigating-away-from-file-editor.yml @@ -0,0 +1,5 @@ +--- +title: Only prompt user once when navigating away from file editor +merge_request: 23820 +author: Sam Bigelow +type: fixed diff --git a/changelogs/unreleased/55402-broken-master-karma-test-failing-in-spec-javascripts-boards-components-issue_due_date_spec-js.yml b/changelogs/unreleased/55402-broken-master-karma-test-failing-in-spec-javascripts-boards-components-issue_due_date_spec-js.yml new file mode 100644 index 00000000000..d2ff095ce55 --- /dev/null +++ b/changelogs/unreleased/55402-broken-master-karma-test-failing-in-spec-javascripts-boards-components-issue_due_date_spec-js.yml @@ -0,0 +1,5 @@ +--- +title: Fix due date test +merge_request: 23845 +author: +type: other diff --git a/changelogs/unreleased/ac-releases-name-sha-author.yml b/changelogs/unreleased/ac-releases-name-sha-author.yml new file mode 100644 index 00000000000..e84b82847eb --- /dev/null +++ b/changelogs/unreleased/ac-releases-name-sha-author.yml @@ -0,0 +1,5 @@ +--- +title: Add name, author_id, and sha to releases table +merge_request: 23763 +author: +type: added diff --git a/changelogs/unreleased/deprecated-delete-all-params.yml b/changelogs/unreleased/deprecated-delete-all-params.yml new file mode 100644 index 00000000000..e23fe92a738 --- /dev/null +++ b/changelogs/unreleased/deprecated-delete-all-params.yml @@ -0,0 +1,5 @@ +--- +title: 'Fix deprecation: Passing conditions to delete_all is deprecated' +merge_request: 23817 +author: Jasper Maes +type: other diff --git a/changelogs/unreleased/deprecated-passing-activerecord-objects.yml b/changelogs/unreleased/deprecated-passing-activerecord-objects.yml new file mode 100644 index 00000000000..e58647186b8 --- /dev/null +++ b/changelogs/unreleased/deprecated-passing-activerecord-objects.yml @@ -0,0 +1,5 @@ +--- +title: 'Fix deprecation: Passing ActiveRecord::Base objects to sanitize_sql_hash_for_assignment' +merge_request: 23818 +author: Jasper Maes +type: other diff --git a/changelogs/unreleased/remove-rails4-support.yml b/changelogs/unreleased/remove-rails4-support.yml new file mode 100644 index 00000000000..a05c913a70c --- /dev/null +++ b/changelogs/unreleased/remove-rails4-support.yml @@ -0,0 +1,5 @@ +--- +title: Remove rails 4 support in CI, Gemfiles, bin/ and config/ +merge_request: 23717 +author: Jasper Maes +type: other diff --git a/changelogs/unreleased/security-2754-fix-lfs-import.yml b/changelogs/unreleased/security-2754-fix-lfs-import.yml new file mode 100644 index 00000000000..e8e74c9c3f6 --- /dev/null +++ b/changelogs/unreleased/security-2754-fix-lfs-import.yml @@ -0,0 +1,5 @@ +--- +title: Validate LFS hrefs before downloading them +merge_request: +author: +type: security diff --git a/changelogs/unreleased/triggermesh-knative-version.yml b/changelogs/unreleased/triggermesh-knative-version.yml new file mode 100644 index 00000000000..27f400962da --- /dev/null +++ b/changelogs/unreleased/triggermesh-knative-version.yml @@ -0,0 +1,5 @@ +--- +title: Knative version bump 0.1.3 -> 0.2.2 +merge_request: +author: Chris Baumbauer +type: changed diff --git a/changelogs/unreleased/winh-dropdown-title-padding.yml b/changelogs/unreleased/winh-dropdown-title-padding.yml new file mode 100644 index 00000000000..9d65175b536 --- /dev/null +++ b/changelogs/unreleased/winh-dropdown-title-padding.yml @@ -0,0 +1,5 @@ +--- +title: Adjust padding of .dropdown-title to comply with design specs +merge_request: 23546 +author: +type: changed diff --git a/changelogs/unreleased/winh-resolved-discussions-reply-field.yml b/changelogs/unreleased/winh-resolved-discussions-reply-field.yml new file mode 100644 index 00000000000..01cf35ae8a7 --- /dev/null +++ b/changelogs/unreleased/winh-resolved-discussions-reply-field.yml @@ -0,0 +1,5 @@ +--- +title: Display reply field if resolved discussion has no replies +merge_request: 23801 +author: +type: fixed diff --git a/config/application.rb b/config/application.rb index f10b8ed5bd2..720196b945e 100644 --- a/config/application.rb +++ b/config/application.rb @@ -8,7 +8,7 @@ module Gitlab # This method is used for smooth upgrading from the current Rails 4.x to Rails 5.0. # https://gitlab.com/gitlab-org/gitlab-ce/issues/14286 def self.rails5? - !%w[0 false].include?(ENV["RAILS5"]) + true end class Application < Rails::Application @@ -26,9 +26,6 @@ module Gitlab # setting disabled require_dependency Rails.root.join('lib/mysql_zero_date') - # This can be removed when we drop support for rails 4 - require_dependency Rails.root.join('lib/rails4_migration_version') - # Settings in config/environments/* take precedence over those specified here. # Application configuration should go into files in config/initializers # -- all .rb files in that directory are automatically loaded. @@ -86,7 +83,7 @@ module Gitlab # namespaces/users. # https://github.com/rails/rails/blob/5-0-stable/actioncable/lib/action_cable.rb#L38 # Please change this value when configuring ActionCable for real usage. - config.action_cable.mount_path = "/-/cable" if rails5? + config.action_cable.mount_path = "/-/cable" # Configure sensitive parameters which will be filtered from the log file. # @@ -213,8 +210,6 @@ module Gitlab config.cache_store = :redis_store, caching_config_hash - config.active_record.raise_in_transactional_callbacks = true unless rails5? - config.active_job.queue_adapter = :sidekiq # This is needed for gitlab-shell diff --git a/config/boot.rb b/config/boot.rb index 725473ac7f6..2811f0e6188 100644 --- a/config/boot.rb +++ b/config/boot.rb @@ -1,11 +1,4 @@ -def rails5? - !%w[0 false].include?(ENV["RAILS5"]) -end - -require 'rubygems' unless rails5? - -gemfile = rails5? ? "Gemfile" : "Gemfile.rails4" -ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../#{gemfile}", __dir__) +ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__) # Set up gems listed in the Gemfile. require 'bundler/setup' if File.exist?(ENV['BUNDLE_GEMFILE']) diff --git a/config/environment.rb b/config/environment.rb index 3a52656a2c1..7e55c7803d3 100644 --- a/config/environment.rb +++ b/config/environment.rb @@ -1,11 +1,6 @@ # Load the rails application -# Remove this condition when upgraded to rails 5.0. -if %w[0 false].include?(ENV["RAILS5"]) - require File.expand_path('application', __dir__) -else - require_relative 'application' -end +require_relative 'application' # Initialize the rails application Rails.application.initialize! diff --git a/config/environments/production.rb b/config/environments/production.rb index 49a4e873093..09bcf49a9a5 100644 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -9,11 +9,7 @@ Rails.application.configure do config.action_controller.perform_caching = true # Disable Rails's static asset server (Apache or nginx will already do this) - if Gitlab.rails5? - config.public_file_server.enabled = false - else - config.serve_static_files = false - end + config.public_file_server.enabled = false # Compress JavaScripts and CSS. config.assets.js_compressor = :uglifier diff --git a/config/environments/test.rb b/config/environments/test.rb index 072f93150a3..3461099253a 100644 --- a/config/environments/test.rb +++ b/config/environments/test.rb @@ -19,13 +19,8 @@ Rails.application.configure do # Configure static asset server for tests with Cache-Control for performance config.assets.compile = false if ENV['CI'] - if Gitlab.rails5? - config.public_file_server.enabled = true - config.public_file_server.headers = { 'Cache-Control' => 'public, max-age=3600' } - else - config.serve_static_files = true - config.static_cache_control = "public, max-age=3600" - end + config.public_file_server.enabled = true + config.public_file_server.headers = { 'Cache-Control' => 'public, max-age=3600' } # Show full error reports and disable caching config.consider_all_requests_local = true diff --git a/config/initializers/active_record_array_type_casting.rb b/config/initializers/active_record_array_type_casting.rb deleted file mode 100644 index a149e048ee2..00000000000 --- a/config/initializers/active_record_array_type_casting.rb +++ /dev/null @@ -1,23 +0,0 @@ -# Remove this initializer when upgraded to Rails 5.0 -unless Gitlab.rails5? - module ActiveRecord - class PredicateBuilder - class ArrayHandler - module TypeCasting - def call(attribute, value) - # This is necessary because by default ActiveRecord does not respect - # custom type definitions (like our `ShaAttribute`) when providing an - # array in `where`, like in `where(commit_sha: [sha1, sha2, sha3])`. - model = attribute.relation&.engine - type = model.user_provided_columns[attribute.name] if model - value = value.map { |value| type.type_cast_for_database(value) } if type - - super(attribute, value) - end - end - - prepend TypeCasting - end - end - end -end diff --git a/config/initializers/active_record_avoid_type_casting_in_uniqueness_validator.rb b/config/initializers/active_record_avoid_type_casting_in_uniqueness_validator.rb index ef4abb77bd7..3e765469995 100644 --- a/config/initializers/active_record_avoid_type_casting_in_uniqueness_validator.rb +++ b/config/initializers/active_record_avoid_type_casting_in_uniqueness_validator.rb @@ -20,75 +20,73 @@ # # This bug was fixed in Rails 5.1 by https://github.com/rails/rails/pull/24745/commits/aa062318c451512035c10898a1af95943b1a3803 -if Gitlab.rails5? - if Rails.version.start_with?("5.1") - raise "Remove this monkey patch: #{__FILE__}" - end +if Rails.version.start_with?("5.1") + raise "Remove this monkey patch: #{__FILE__}" +end - # Copy-paste from https://github.com/kamipo/rails/blob/aa062318c451512035c10898a1af95943b1a3803/activerecord/lib/active_record/validations/uniqueness.rb - # including local fixes to make Rubocop happy again. - module ActiveRecord - module Validations - class UniquenessValidator < ActiveModel::EachValidator # :nodoc: - def validate_each(record, attribute, value) - finder_class = find_finder_class_for(record) - table = finder_class.arel_table - value = map_enum_attribute(finder_class, attribute, value) +# Copy-paste from https://github.com/kamipo/rails/blob/aa062318c451512035c10898a1af95943b1a3803/activerecord/lib/active_record/validations/uniqueness.rb +# including local fixes to make Rubocop happy again. +module ActiveRecord + module Validations + class UniquenessValidator < ActiveModel::EachValidator # :nodoc: + def validate_each(record, attribute, value) + finder_class = find_finder_class_for(record) + table = finder_class.arel_table + value = map_enum_attribute(finder_class, attribute, value) - relation = build_relation(finder_class, table, attribute, value) + relation = build_relation(finder_class, table, attribute, value) - if record.persisted? - if finder_class.primary_key - relation = relation.where.not(finder_class.primary_key => record.id_was || record.id) - else - raise UnknownPrimaryKey.new(finder_class, "Can not validate uniqueness for persisted record without primary key.") - end + if record.persisted? + if finder_class.primary_key + relation = relation.where.not(finder_class.primary_key => record.id_was || record.id) + else + raise UnknownPrimaryKey.new(finder_class, "Can not validate uniqueness for persisted record without primary key.") end + end - relation = scope_relation(record, table, relation) - relation = relation.merge(options[:conditions]) if options[:conditions] + relation = scope_relation(record, table, relation) + relation = relation.merge(options[:conditions]) if options[:conditions] - if relation.exists? - error_options = options.except(:case_sensitive, :scope, :conditions) - error_options[:value] = value + if relation.exists? + error_options = options.except(:case_sensitive, :scope, :conditions) + error_options[:value] = value - record.errors.add(attribute, :taken, error_options) - end - rescue RangeError + record.errors.add(attribute, :taken, error_options) end + rescue RangeError + end - protected - - def build_relation(klass, table, attribute, value) #:nodoc: - if reflection = klass._reflect_on_association(attribute) - attribute = reflection.foreign_key - value = value.attributes[reflection.klass.primary_key] unless value.nil? - end + protected - # the attribute may be an aliased attribute - if klass.attribute_alias?(attribute) - attribute = klass.attribute_alias(attribute) - end + def build_relation(klass, table, attribute, value) #:nodoc: + if reflection = klass._reflect_on_association(attribute) + attribute = reflection.foreign_key + value = value.attributes[reflection.klass.primary_key] unless value.nil? + end - attribute_name = attribute.to_s + # the attribute may be an aliased attribute + if klass.attribute_alias?(attribute) + attribute = klass.attribute_alias(attribute) + end - column = klass.columns_hash[attribute_name] - cast_type = klass.type_for_attribute(attribute_name) + attribute_name = attribute.to_s - comparison = - if !options[:case_sensitive] && !value.nil? - # will use SQL LOWER function before comparison, unless it detects a case insensitive collation - klass.connection.case_insensitive_comparison(table, attribute, column, value) - else - klass.connection.case_sensitive_comparison(table, attribute, column, value) - end + column = klass.columns_hash[attribute_name] + cast_type = klass.type_for_attribute(attribute_name) - if value.nil? - klass.unscoped.where(comparison) + comparison = + if !options[:case_sensitive] && !value.nil? + # will use SQL LOWER function before comparison, unless it detects a case insensitive collation + klass.connection.case_insensitive_comparison(table, attribute, column, value) else - bind = Relation::QueryAttribute.new(attribute_name, value, cast_type) - klass.unscoped.where(comparison, bind) + klass.connection.case_sensitive_comparison(table, attribute, column, value) end + + if value.nil? + klass.unscoped.where(comparison) + else + bind = Relation::QueryAttribute.new(attribute_name, value, cast_type) + klass.unscoped.where(comparison, bind) end end end diff --git a/config/initializers/active_record_data_types.rb b/config/initializers/active_record_data_types.rb index 717e30b5b7e..e95157bfde5 100644 --- a/config/initializers/active_record_data_types.rb +++ b/config/initializers/active_record_data_types.rb @@ -65,7 +65,7 @@ elsif Gitlab::Database.mysql? prepend RegisterDateTimeWithTimeZone # Add the class `DateTimeWithTimeZone` so we can map `timestamp` to it. - class MysqlDateTimeWithTimeZone < (Gitlab.rails5? ? ActiveRecord::Type::DateTime : MysqlDateTime) + class MysqlDateTimeWithTimeZone < ActiveRecord::Type::DateTime def type :datetime_with_timezone end diff --git a/config/initializers/active_record_locking.rb b/config/initializers/active_record_locking.rb index 21ff323927b..bfe41e6029a 100644 --- a/config/initializers/active_record_locking.rb +++ b/config/initializers/active_record_locking.rb @@ -64,21 +64,13 @@ module ActiveRecord # This is patched because we want `lock_version` default to `NULL` # rather than `0` - if Gitlab.rails5? - class LockingType - def deserialize(value) - super - end - - def serialize(value) - super - end + class LockingType + def deserialize(value) + super end - else - class LockingType < SimpleDelegator - def type_cast_from_database(value) - super - end + + def serialize(value) + super end end end diff --git a/config/initializers/application_controller_renderer.rb b/config/initializers/application_controller_renderer.rb deleted file mode 100644 index a65f8aecf9e..00000000000 --- a/config/initializers/application_controller_renderer.rb +++ /dev/null @@ -1,12 +0,0 @@ -# Remove this `if` condition when upgraded to rails 5.0. -# The body must be kept. -if Gitlab.rails5? - # Be sure to restart your server when you modify this file. - - # ActiveSupport::Reloader.to_prepare do - # ApplicationController.renderer.defaults.merge!( - # http_host: 'example.org', - # https: false - # ) - # end -end diff --git a/config/initializers/ar5_batching.rb b/config/initializers/ar5_batching.rb deleted file mode 100644 index 874455ce5af..00000000000 --- a/config/initializers/ar5_batching.rb +++ /dev/null @@ -1,40 +0,0 @@ -# Remove this file when upgraded to rails 5.0. -unless Gitlab.rails5? - module ActiveRecord - module Batches - # Differences from upstream: enumerator support was removed, and custom - # order/limit clauses are ignored without a warning. - def in_batches(of: 1000, start: nil, finish: nil, load: false) - raise "Must provide a block" unless block_given? - - relation = self.reorder(batch_order).limit(of) - relation = relation.where(arel_table[primary_key].gteq(start)) if start - relation = relation.where(arel_table[primary_key].lteq(finish)) if finish - batch_relation = relation - - loop do - if load - records = batch_relation.records - ids = records.map(&:id) - yielded_relation = self.where(primary_key => ids) - yielded_relation.load_records(records) - else - ids = batch_relation.pluck(primary_key) - yielded_relation = self.where(primary_key => ids) - end - - break if ids.empty? - - primary_key_offset = ids.last - raise ArgumentError.new("Primary key not included in the custom select clause") unless primary_key_offset - - yield yielded_relation - - break if ids.length < of - - batch_relation = relation.where(arel_table[primary_key].gt(primary_key_offset)) - end - end - end - end -end diff --git a/config/initializers/ar5_pg_10_support.rb b/config/initializers/ar5_pg_10_support.rb deleted file mode 100644 index 40548290ce8..00000000000 --- a/config/initializers/ar5_pg_10_support.rb +++ /dev/null @@ -1,58 +0,0 @@ -# Remove this file when upgraded to rails 5.0. -if !Gitlab.rails5? && Gitlab::Database.postgresql? - require 'active_record/connection_adapters/postgresql_adapter' - require 'active_record/connection_adapters/postgresql/schema_statements' - - # - # Monkey-patch the refused Rails 4.2 patch at https://github.com/rails/rails/pull/31330 - # - # Updates sequence logic to support PostgreSQL 10. - # - # rubocop:disable all - module ActiveRecord - module ConnectionAdapters - - # We need #postgresql_version to be public as in ActiveRecord 5 for seed_fu - # to work. In ActiveRecord 4, it is protected. - # https://github.com/mbleigh/seed-fu/issues/123 - class PostgreSQLAdapter - public :postgresql_version - end - - module PostgreSQL - module SchemaStatements - # Resets the sequence of a table's primary key to the maximum value. - def reset_pk_sequence!(table, pk = nil, sequence = nil) #:nodoc: - unless pk and sequence - default_pk, default_sequence = pk_and_sequence_for(table) - - pk ||= default_pk - sequence ||= default_sequence - end - - if @logger && pk && !sequence - @logger.warn "#{table} has primary key #{pk} with no default sequence" - end - - if pk && sequence - quoted_sequence = quote_table_name(sequence) - max_pk = select_value("SELECT MAX(#{quote_column_name pk}) FROM #{quote_table_name(table)}") - if max_pk.nil? - if postgresql_version >= 100000 - minvalue = select_value("SELECT seqmin FROM pg_sequence WHERE seqrelid = #{quote(quoted_sequence)}::regclass") - else - minvalue = select_value("SELECT min_value FROM #{quoted_sequence}") - end - end - - select_value <<-end_sql, 'SCHEMA' - SELECT setval(#{quote(quoted_sequence)}, #{max_pk ? max_pk : minvalue}, #{max_pk ? true : false}) - end_sql - end - end - end - end - end - end - # rubocop:enable all -end diff --git a/config/initializers/mysql_set_length_for_binary_indexes.rb b/config/initializers/mysql_set_length_for_binary_indexes.rb index 0445d8fcae2..552f3a20a95 100644 --- a/config/initializers/mysql_set_length_for_binary_indexes.rb +++ b/config/initializers/mysql_set_length_for_binary_indexes.rb @@ -2,28 +2,6 @@ # MySQL adapter apply a length of 20. Otherwise MySQL can't create an index on # binary columns. -# This module can be removed once a Rails 5 schema is used. -# It can't be wrapped in a check that checks Gitlab.rails5? because -# the old Rails 4 schema layout is still used -module MysqlSetLengthForBinaryIndex - def add_index(table_name, column_names, options = {}) - options[:length] ||= {} - Array(column_names).each do |column_name| - column = ActiveRecord::Base.connection.columns(table_name).find { |c| c.name == column_name } - - if column&.type == :binary - options[:length][column_name] = 20 - end - end - - super(table_name, column_names, options) - end -end - -if defined?(ActiveRecord::ConnectionAdapters::Mysql2Adapter) - ActiveRecord::ConnectionAdapters::Mysql2Adapter.send(:prepend, MysqlSetLengthForBinaryIndex) -end - module MysqlSetLengthForBinaryIndexAndIgnorePostgresOptionsForSchema # This method is used in Rails 5 schema loading as t.index def index(column_names, options = {}) @@ -34,15 +12,6 @@ module MysqlSetLengthForBinaryIndexAndIgnorePostgresOptionsForSchema return end - # when running rails 4 with rails 5 schema, rails 4 doesn't support multiple - # indexes on the same set of columns. Mysql doesn't support partial indexes, so if - # an index already exists and we add another index, skip it if it's partial: - # see https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/21492#note_102821326 - if !Gitlab.rails5? && indexes[column_names] && options[:where] - warn "WARNING: index on columns #{column_names} already exists and partial index is not supported, skipping." - return - end - options[:length] ||= {} Array(column_names).each do |column_name| column = columns.find { |c| c.name == column_name } @@ -56,14 +25,6 @@ module MysqlSetLengthForBinaryIndexAndIgnorePostgresOptionsForSchema end end -def mysql_adapter? - defined?(ActiveRecord::ConnectionAdapters::Mysql2Adapter) && ActiveRecord::Base.connection.is_a?(ActiveRecord::ConnectionAdapters::Mysql2Adapter) -end - -if Gitlab.rails5? - if defined?(ActiveRecord::ConnectionAdapters::MySQL::TableDefinition) - ActiveRecord::ConnectionAdapters::MySQL::TableDefinition.send(:prepend, MysqlSetLengthForBinaryIndexAndIgnorePostgresOptionsForSchema) - end -elsif mysql_adapter? && defined?(ActiveRecord::ConnectionAdapters::TableDefinition) - ActiveRecord::ConnectionAdapters::TableDefinition.send(:prepend, MysqlSetLengthForBinaryIndexAndIgnorePostgresOptionsForSchema) +if defined?(ActiveRecord::ConnectionAdapters::MySQL::TableDefinition) + ActiveRecord::ConnectionAdapters::MySQL::TableDefinition.send(:prepend, MysqlSetLengthForBinaryIndexAndIgnorePostgresOptionsForSchema) end diff --git a/config/initializers/new_framework_defaults.rb b/config/initializers/new_framework_defaults.rb index 2d130bc0bf8..5adb9f7a4b4 100644 --- a/config/initializers/new_framework_defaults.rb +++ b/config/initializers/new_framework_defaults.rb @@ -1,29 +1,27 @@ # Remove this `if` condition when upgraded to rails 5.0. # The body must be kept. -if Gitlab.rails5? - # Be sure to restart your server when you modify this file. - # - # This file contains migration options to ease your Rails 5.0 upgrade. - # - # Once upgraded flip defaults one by one to migrate to the new default. - # - # Read the Guide for Upgrading Ruby on Rails for more info on each option. +# Be sure to restart your server when you modify this file. +# +# This file contains migration options to ease your Rails 5.0 upgrade. +# +# Once upgraded flip defaults one by one to migrate to the new default. +# +# Read the Guide for Upgrading Ruby on Rails for more info on each option. - Rails.application.config.action_controller.raise_on_unfiltered_parameters = true +Rails.application.config.action_controller.raise_on_unfiltered_parameters = true - # Enable per-form CSRF tokens. Previous versions had false. - Rails.application.config.action_controller.per_form_csrf_tokens = false +# Enable per-form CSRF tokens. Previous versions had false. +Rails.application.config.action_controller.per_form_csrf_tokens = false - # Enable origin-checking CSRF mitigation. Previous versions had false. - Rails.application.config.action_controller.forgery_protection_origin_check = false +# Enable origin-checking CSRF mitigation. Previous versions had false. +Rails.application.config.action_controller.forgery_protection_origin_check = false - # Make Ruby 2.4 preserve the timezone of the receiver when calling `to_time`. - # Previous versions had false. - ActiveSupport.to_time_preserves_timezone = false +# Make Ruby 2.4 preserve the timezone of the receiver when calling `to_time`. +# Previous versions had false. +ActiveSupport.to_time_preserves_timezone = false - # Require `belongs_to` associations by default. Previous versions had false. - Rails.application.config.active_record.belongs_to_required_by_default = false +# Require `belongs_to` associations by default. Previous versions had false. +Rails.application.config.active_record.belongs_to_required_by_default = false - # Do not halt callback chains when a callback returns false. Previous versions had true. - ActiveSupport.halt_callback_chains_on_return_false = true -end +# Do not halt callback chains when a callback returns false. Previous versions had true. +ActiveSupport.halt_callback_chains_on_return_false = true diff --git a/config/initializers/postgresql_opclasses_support.rb b/config/initializers/postgresql_opclasses_support.rb index 5d643b75dd8..70b530415f5 100644 --- a/config/initializers/postgresql_opclasses_support.rb +++ b/config/initializers/postgresql_opclasses_support.rb @@ -41,10 +41,7 @@ module ActiveRecord # Abstract representation of an index definition on a table. Instances of # this type are typically created and returned by methods in database # adapters. e.g. ActiveRecord::ConnectionAdapters::AbstractMysqlAdapter#indexes - attrs = [:table, :name, :unique, :columns, :lengths, :orders, :where, :type, :using, :opclasses] - - # In Rails 5 the second last attribute is newly `:comment` - attrs.insert(-2, :comment) if Gitlab.rails5? + attrs = [:table, :name, :unique, :columns, :lengths, :orders, :where, :type, :using, :comment, :opclasses] class IndexDefinition < Struct.new(*attrs) #:nodoc: end @@ -112,15 +109,8 @@ module ActiveRecord result.map do |row| index_name = row[0] - unique = if Gitlab.rails5? - row[1] - else - row[1] == 't' - end - indkey = row[2].split(" ") - if Gitlab.rails5? - indkey = indkey.map(&:to_i) - end + unique = row[1] + indkey = row[2].split(" ").map(&:to_i) inddef = row[3] oid = row[4] @@ -144,8 +134,7 @@ module ActiveRecord [column, opclass] if opclass end.compact] - index_attrs = [table_name, index_name, unique, column_names, [], orders, where, nil, using, opclasses] - index_attrs.insert(-2, nil) if Gitlab.rails5? # include index comment for Rails 5 + index_attrs = [table_name, index_name, unique, column_names, [], orders, where, nil, using, nil, opclasses] IndexDefinition.new(*index_attrs) end @@ -205,7 +194,7 @@ module ActiveRecord index_parts << "using: #{index.using.inspect}" if index.using index_parts << "type: #{index.type.inspect}" if index.type index_parts << "opclasses: #{index.opclasses.inspect}" if index.opclasses.present? - index_parts << "comment: #{index.comment.inspect}" if Gitlab.rails5? && index.comment + index_parts << "comment: #{index.comment.inspect}" if index.comment index_parts end diff --git a/config/initializers/static_files.rb b/config/initializers/static_files.rb index a0b8b68f3ef..e02f0868e9f 100644 --- a/config/initializers/static_files.rb +++ b/config/initializers/static_files.rb @@ -1,26 +1,17 @@ app = Rails.application -if (Gitlab.rails5? && app.config.public_file_server.enabled) || app.config.serve_static_files +if app.config.public_file_server.enabled # The `ActionDispatch::Static` middleware intercepts requests for static files # by checking if they exist in the `/public` directory. # We're replacing it with our `Gitlab::Middleware::Static` that does the same, # except ignoring `/uploads`, letting those go through to the GitLab Rails app. - if Gitlab.rails5? - app.config.middleware.swap( - ActionDispatch::Static, - Gitlab::Middleware::Static, - app.paths["public"].first, - headers: app.config.public_file_server.headers - ) - else - app.config.middleware.swap( - ActionDispatch::Static, - Gitlab::Middleware::Static, - app.paths["public"].first, - app.config.static_cache_control - ) - end + app.config.middleware.swap( + ActionDispatch::Static, + Gitlab::Middleware::Static, + app.paths["public"].first, + headers: app.config.public_file_server.headers + ) # If webpack-dev-server is configured, proxy webpack's public directory # instead of looking for static assets diff --git a/config/initializers/trusted_proxies.rb b/config/initializers/trusted_proxies.rb index ca2eed664ed..7af465d8443 100644 --- a/config/initializers/trusted_proxies.rb +++ b/config/initializers/trusted_proxies.rb @@ -26,12 +26,10 @@ Rails.application.config.action_dispatch.trusted_proxies = ( # A monkey patch to make trusted proxies work with Rails 5.0. # Inspired by https://github.com/rails/rails/issues/5223#issuecomment-263778719 # Remove this monkey patch when upstream is fixed. -if Gitlab.rails5? - module TrustedProxyMonkeyPatch - def ip - @ip ||= (get_header("action_dispatch.remote_ip") || super).to_s - end +module TrustedProxyMonkeyPatch + def ip + @ip ||= (get_header("action_dispatch.remote_ip") || super).to_s end - - ActionDispatch::Request.send(:include, TrustedProxyMonkeyPatch) end + +ActionDispatch::Request.send(:include, TrustedProxyMonkeyPatch) diff --git a/config/routes/api.rb b/config/routes/api.rb index b1aebf4d606..3719b7d3a1e 100644 --- a/config/routes/api.rb +++ b/config/routes/api.rb @@ -1,4 +1,4 @@ -constraints(::Constraints::FeatureConstrainer.new(:graphql)) do +constraints(::Constraints::FeatureConstrainer.new(:graphql, default_enabled: true)) do post '/api/graphql', to: 'graphql#execute' mount GraphiQL::Rails::Engine, at: '/-/graphql-explorer', graphql_path: '/api/graphql' end diff --git a/danger/gemfile/Dangerfile b/danger/gemfile/Dangerfile index 8ef4a464fe4..4e91abc371a 100644 --- a/danger/gemfile/Dangerfile +++ b/danger/gemfile/Dangerfile @@ -4,7 +4,7 @@ GEMFILE_LOCK_NOT_UPDATED_MESSAGE = <<~MSG.freeze Usually, when %<gemfile>s is updated, you should run ``` bundle install && \ - BUNDLE_GEMFILE=Gemfile.rails5 bundle install + bundle install ``` or diff --git a/db/migrate/20181211092510_add_name_author_id_and_sha_to_releases.rb b/db/migrate/20181211092510_add_name_author_id_and_sha_to_releases.rb new file mode 100644 index 00000000000..60815e0c31a --- /dev/null +++ b/db/migrate/20181211092510_add_name_author_id_and_sha_to_releases.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +class AddNameAuthorIdAndShaToReleases < ActiveRecord::Migration[5.0] + include Gitlab::Database::MigrationHelpers + + DOWNTIME = false + + def change + add_column :releases, :author_id, :integer + add_column :releases, :name, :string + add_column :releases, :sha, :string + end +end diff --git a/db/migrate/20181211092514_add_author_id_index_and_fk_to_releases.rb b/db/migrate/20181211092514_add_author_id_index_and_fk_to_releases.rb new file mode 100644 index 00000000000..f6350a49944 --- /dev/null +++ b/db/migrate/20181211092514_add_author_id_index_and_fk_to_releases.rb @@ -0,0 +1,21 @@ +# frozen_string_literal: true + +class AddAuthorIdIndexAndFkToReleases < ActiveRecord::Migration[5.0] + include Gitlab::Database::MigrationHelpers + + DOWNTIME = false + + disable_ddl_transaction! + + def up + add_concurrent_index :releases, :author_id + + add_concurrent_foreign_key :releases, :users, column: :author_id, on_delete: :nullify + end + + def down + remove_foreign_key :releases, column: :author_id + + remove_concurrent_index :releases, column: :author_id + end +end diff --git a/db/migrate/20181212104941_backfill_releases_name_with_tag_name.rb b/db/migrate/20181212104941_backfill_releases_name_with_tag_name.rb new file mode 100644 index 00000000000..e152dc87bc1 --- /dev/null +++ b/db/migrate/20181212104941_backfill_releases_name_with_tag_name.rb @@ -0,0 +1,17 @@ +# frozen_string_literal: true + +class BackfillReleasesNameWithTagName < ActiveRecord::Migration[5.0] + include Gitlab::Database::MigrationHelpers + + DOWNTIME = false + + disable_ddl_transaction! + + def up + update_column_in_batches(:releases, :name, Release.arel_table[:tag]) + end + + def down + # no-op + end +end diff --git a/db/schema.rb b/db/schema.rb index 10b7aa8a99f..008bff49a2b 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20181204154019) do +ActiveRecord::Schema.define(version: 20181212104941) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -1803,6 +1803,10 @@ ActiveRecord::Schema.define(version: 20181204154019) do t.datetime "updated_at" t.text "description_html" t.integer "cached_markdown_version" + t.integer "author_id" + t.string "name" + t.string "sha" + t.index ["author_id"], name: "index_releases_on_author_id", using: :btree t.index ["project_id", "tag"], name: "index_releases_on_project_id_and_tag", using: :btree t.index ["project_id"], name: "index_releases_on_project_id", using: :btree end @@ -2433,6 +2437,7 @@ ActiveRecord::Schema.define(version: 20181204154019) do add_foreign_key "protected_tags", "projects", name: "fk_8e4af87648", on_delete: :cascade add_foreign_key "push_event_payloads", "events", name: "fk_36c74129da", on_delete: :cascade add_foreign_key "releases", "projects", name: "fk_47fe2a0596", on_delete: :cascade + add_foreign_key "releases", "users", column: "author_id", name: "fk_8e4456f90f", on_delete: :nullify add_foreign_key "remote_mirrors", "projects", on_delete: :cascade add_foreign_key "repository_languages", "projects", on_delete: :cascade add_foreign_key "resource_label_events", "issues", on_delete: :cascade diff --git a/doc/administration/container_registry.md b/doc/administration/container_registry.md index cfe7b0e05e3..5b7a61ef8ff 100644 --- a/doc/administration/container_registry.md +++ b/doc/administration/container_registry.md @@ -604,6 +604,52 @@ Registry out of the box, it is possible to make it work if you follow [Docker's documentation][docker-insecure-self-signed]. You may find some additional information in [issue 18239][ce-18239]. +## Troubleshooting + +When using AWS S3 with the GitLab registry, an error may occur when pushing +large images. Look in the Registry log for the following error: + +``` +level=error msg="response completed with error" err.code=unknown err.detail="unexpected EOF" err.message="unknown error" +``` + +To resolve the error specify a `chunksize` value in the Registry configuration. +Start with a value between `25000000` (25MB) and `50000000` (50MB). + +**For Omnibus installations** + +1. Edit `/etc/gitlab/gitlab.rb`: + + ```ruby + registry['storage'] = { + 's3' => { + 'accesskey' => 'AKIAKIAKI', + 'secretkey' => 'secret123', + 'bucket' => 'gitlab-registry-bucket-AKIAKIAKI', + 'chunksize' => 25000000 + } + } + ``` + +1. Save the file and [reconfigure GitLab][] for the changes to take effect. + +--- + +**For installations from source** + +1. Edit `config/gitlab.yml`: + + ```yaml + storage: + s3: + accesskey: 'AKIAKIAKI' + secretkey: 'secret123' + bucket: 'gitlab-registry-bucket-AKIAKIAKI' + chunksize: 25000000 + ``` + +1. Save the file and [restart GitLab][] for the changes to take effect. + [ce-18239]: https://gitlab.com/gitlab-org/gitlab-ce/issues/18239 [docker-insecure-self-signed]: https://docs.docker.com/registry/insecure/#use-self-signed-certificates [reconfigure gitlab]: restart_gitlab.md#omnibus-gitlab-reconfigure diff --git a/doc/ci/yaml/README.md b/doc/ci/yaml/README.md index 4dafde0462a..acfcd05624d 100644 --- a/doc/ci/yaml/README.md +++ b/doc/ci/yaml/README.md @@ -402,7 +402,7 @@ job: script: echo 'test' ``` -is translated to +is translated to: ```yaml job: @@ -412,49 +412,64 @@ job: ## `only` and `except` (complex) -> `refs` and `kubernetes` policies introduced in GitLab 10.0 -> -> `variables` policy introduced in 10.7 -> -> `changes` policy [introduced](https://gitlab.com/gitlab-org/gitlab-ce/issues/19232) in 11.4 +> - `refs` and `kubernetes` policies introduced in GitLab 10.0. +> - `variables` policy introduced in GitLab 10.7. +> - `changes` policy [introduced](https://gitlab.com/gitlab-org/gitlab-ce/issues/19232) in GitLab 11.4. CAUTION: **Warning:** This an _alpha_ feature, and it is subject to change at any time without prior notice! -Since GitLab 10.0 it is possible to define a more elaborate only/except job -policy configuration. +GitLab supports both simple and complex strategies, so it's possible to use an +array and a hash configuration scheme. -GitLab now supports both, simple and complex strategies, so it is possible to -use an array and a hash configuration scheme. +Four keys are available: -Four keys are now available: `refs`, `kubernetes` and `variables` and `changes`. +- `refs` +- `variables` +- `changes` +- `kubernetes` -### `refs` and `kubernetes` +If you use multiple keys under `only` or `except`, they act as an AND. The logic is: -Refs strategy equals to simplified only/except configuration, whereas -kubernetes strategy accepts only `active` keyword. +> (any of refs) AND (any of variables) AND (any of changes) AND (if kubernetes is active) -### `only:variables` +### `only:refs` and `except:refs` -`variables` keyword is used to define variables expressions. In other words -you can use predefined variables / project / group or -environment-scoped variables to define an expression GitLab is going to -evaluate in order to decide whether a job should be created or not. +The `refs` strategy can take the same values as the +[simplified only/except configuration](#only-and-except-simplified). -See the example below. Job is going to be created only when pipeline has been -scheduled or runs for a `master` branch, and only if kubernetes service is -active in the project. +In the example below, the `deploy` job is going to be created only when the +pipeline has been [scheduled][schedules] or runs for the `master` branch: ```yaml -job: +deploy: only: refs: - master - schedules +``` + +### `only:kubernetes` and `except:kubernetes` + +The `kubernetes` strategy accepts only the `active` keyword. + +In the example below, the `deploy` job is going to be created only when the +Kubernetes service is active in the project: + +```yaml +deploy: + only: kubernetes: active ``` +### `only:variables` and `except:variables` + +The `variables` keyword is used to define variables expressions. In other words, +you can use predefined variables / project / group or +environment-scoped variables to define an expression GitLab is going to +evaluate in order to decide whether a job should be created or not. + Examples of using variables expressions: ```yaml @@ -468,7 +483,7 @@ deploy: - $STAGING ``` -Another use case is exluding jobs depending on a commit message _(added in 11.0)_: +Another use case is excluding jobs depending on a commit message: ```yaml end-to-end: @@ -478,11 +493,11 @@ end-to-end: - $CI_COMMIT_MESSAGE =~ /skip-end-to-end-tests/ ``` -Learn more about variables expressions on [a separate page][variables-expressions]. +Learn more about [variables expressions](../variables/README.md#variables-expressions). -### `only:changes` +### `only:changes` and `except:changes` -Using `changes` keyword with `only` or `except` makes it possible to define if +Using the `changes` keyword with `only` or `except`, makes it possible to define if a job should be created based on files modified by a git push event. For example: @@ -499,13 +514,13 @@ docker build: ``` In the scenario above, if you are pushing multiple commits to GitLab to an -existing branch, GitLab creates and triggers `docker build` job, provided that +existing branch, GitLab creates and triggers the `docker build` job, provided that one of the commits contains changes to either: - The `Dockerfile` file. - Any of the files inside `docker/scripts/` directory. -- Any of the files and subfolders inside `dockerfiles` directory. -- Any of the files with `rb`, `py`, `sh` extensions inside `more_scripts` directory. +- Any of the files and subdirectories inside the `dockerfiles` directory. +- Any of the files with `rb`, `py`, `sh` extensions inside the `more_scripts` directory. CAUTION: **Warning:** There are some caveats when using this feature with new branches and tags. See @@ -614,7 +629,7 @@ failure. fails. 1. `always` - execute job regardless of the status of jobs from prior stages. 1. `manual` - execute job manually (added in GitLab 8.10). Read about - [manual actions](#when-manual) below. + [manual actions](#whenmanual) below. For example: @@ -674,7 +689,7 @@ Manual actions are a special type of job that are not executed automatically, they need to be explicitly started by a user. An example usage of manual actions would be a deployment to a production environment. Manual actions can be started from the pipeline, job, environment, and deployment views. Read more at the -[environments documentation][env-manual]. +[environments documentation](../environments.md#manually-deploying-to-environments). Manual actions can be either optional or blocking. Blocking manual actions will block the execution of the pipeline at the stage this action is defined in. It's @@ -1323,7 +1338,7 @@ The test reports are collected regardless of the job results (success or failure You can use [`artifacts:expire_in`](#artifacts-expire_in) to set up an expiration date for their artifacts. -NOTE: **Note:** +NOTE: **Note:** If you also want the ability to browse the report output files, include the [`artifacts:paths`](#artifactspaths) keyword. @@ -1657,7 +1672,7 @@ rspec: ``` NOTE: **Note:** -`include` requires the external YAML files to have the extensions `.yml` or `.yaml`. +`include` requires the external YAML files to have the extensions `.yml` or `.yaml`. The external file will not be included if the extension is missing. You can define it either as a single string, or, in case you want to include @@ -1709,20 +1724,24 @@ include: The remote file must be publicly accessible through a simple GET request, as we don't support authentication schemas in the remote URL. NOTE: **Note:** - In order to include files from another repository inside your local network, + In order to include files from another repository inside your local network, you may need to enable the **Allow requests to the local network from hooks and services** checkbox located in the **Settings > Network > Outbound requests** section within the **Admin area**. --- -Since GitLab 10.8 we are now recursively merging the files defined in `include` +Since GitLab 10.8 we are now deep merging the files defined in `include` with those in `.gitlab-ci.yml`. Files defined by `include` are always -evaluated first and recursively merged with the content of `.gitlab-ci.yml`, no +evaluated first and merged with the content of `.gitlab-ci.yml`, no matter the position of the `include` keyword. You can take advantage of -recursive merging to customize and override details in included CI +merging to customize and override details in included CI configurations with local definitions. +NOTE: **Note:** +The recursive includes are not supported, meaning your external files +should not use the `include` keyword, as it will be ignored. + The following example shows specific YAML-defined variables and details of the `production` job from an include file being customized in `.gitlab-ci.yml`. @@ -1772,11 +1791,7 @@ with the environment url of the `production` job defined in `autodevops-template.yml` have been overridden by new values defined in `.gitlab-ci.yml`. -NOTE: **Note:** -Recursive includes are not supported meaning your external files -should not use the `include` keyword, as it will be ignored. - -Recursive merging lets you extend and override dictionary mappings, but +The merging lets you extend and override dictionary mappings, but you cannot add or modify items to an included array. For example, to add an additional item to the production job script, you must repeat the existing script items. @@ -2195,19 +2210,14 @@ try to quote them, or change them to a different form (e.g., `/bin/true`). ## Examples -Visit the [examples README][examples] to see a list of examples using GitLab -CI with various languages. +See a [list of examples](../examples/README.md "CI/CD examples") for using +GitLab CI/CD with various languages. -[env-manual]: ../environments.md#manually-deploying-to-environments -[examples]: ../examples/README.md [ce-6323]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/6323 -[environment]: ../environments.md [ce-6669]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/6669 -[variables]: ../variables/README.md [ce-7983]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/7983 [ce-7447]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/7447 [ce-12909]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/12909 -[schedules]: ../../user/project/pipelines/schedules.md -[variables-expressions]: ../variables/README.md#variables-expressions -[ee]: https://about.gitlab.com/gitlab-ee/ -[gitlab-versions]: https://about.gitlab.com/products/ +[environment]: ../environments.md "CI/CD environments" +[schedules]: ../../user/project/pipelines/schedules.md "Pipelines schedules" +[variables]: ../variables/README.md "CI/CD variables" diff --git a/doc/development/README.md b/doc/development/README.md index bcf57a223f5..f22dde32de9 100644 --- a/doc/development/README.md +++ b/doc/development/README.md @@ -52,7 +52,6 @@ description: 'Learn how to contribute to GitLab.' - [Prometheus metrics](prometheus_metrics.md) - [Guidelines for reusing abstractions](reusing_abstractions.md) - [DeclarativePolicy framework](policies.md) -- [Switching to Rails 5](switching_to_rails5.md) ## Performance guides diff --git a/doc/development/i18n/proofreader.md b/doc/development/i18n/proofreader.md index 8f1317e235d..ac910e80a89 100644 --- a/doc/development/i18n/proofreader.md +++ b/doc/development/i18n/proofreader.md @@ -12,7 +12,7 @@ are very appreciative of the work done by translators and proofreaders! - Bulgarian - Lyubomir Vasilev - [Crowdin](https://crowdin.com/profile/lyubomirv) - Catalan - - Proofreaders needed. + - David Planella - [GitLab](https://gitlab.com/dplanella), [Crowdin](https://crowdin.com/profile/dplanella) - Chinese Simplified - Huang Tao - [GitLab](https://gitlab.com/htve), [Crowdin](https://crowdin.com/profile/htve) - Chinese Traditional diff --git a/doc/development/new_fe_guide/style/prettier.md b/doc/development/new_fe_guide/style/prettier.md index baaea67d38b..4495f38f262 100644 --- a/doc/development/new_fe_guide/style/prettier.md +++ b/doc/development/new_fe_guide/style/prettier.md @@ -57,3 +57,38 @@ node ./scripts/frontend/prettier.js save-all ./vendor/ ``` This will go over all files in a specific folder and save it. + +## VSCode Settings + +### Format on Save + +To automatically format your files with Prettier, add the following properties to your User or Workspace Settings: + +```javascript +{ + "[javascript]": { + "editor.formatOnSave": true + }, + "[vue]": { + "editor.formatOnSave": true + }, +} +``` + +### Conflicts with Vetur Extension + +There are some [runtime issues](https://github.com/vuejs/vetur/issues/950) with [Prettier](https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode) and [the Vetur extension](https://marketplace.visualstudio.com/items?itemName=octref.vetur) for VSCode. To fix this, try adding the following properties to your User or Workspace Settings: + +```javascript +{ + "prettier.disableLanguages": [], + "vetur.format.defaultFormatter.html": "none", + "vetur.format.defaultFormatter.js": "none", + "vetur.format.defaultFormatter.css": "none", + "vetur.format.defaultFormatter.less": "none", + "vetur.format.defaultFormatter.postcss": "none", + "vetur.format.defaultFormatter.scss": "none", + "vetur.format.defaultFormatter.stylus": "none", + "vetur.format.defaultFormatter.ts": "none", +} +``` diff --git a/doc/development/switching_to_rails5.md b/doc/development/switching_to_rails5.md deleted file mode 100644 index c9a4ce1a1d1..00000000000 --- a/doc/development/switching_to_rails5.md +++ /dev/null @@ -1,27 +0,0 @@ -# Switching to Rails 5 - -GitLab switched recently to Rails 5. This is a big change (especially for backend development) and it introduces couple of temporary inconveniences. - -## After the switch, I found a broken feature. What do I do? - -Many fixes and tweaks were done to make our codebase compatible with Rails 5, but it's possible that not all issues were found. If you find an bug, please create an issue and assign it the ~rails5 label. - -## It takes much longer to run CI pipelines that build GitLab. Why? - -We are temporarily running CI pipelines with Rails 4 and 5 so that we ensure we remain compatible with Rails 4 in case we must revert back to Rails 4 from Rails 5 (this can double the duration of CI pipelines). - -We might revert back to Rails 4 if we found a major issue we were unable to quickly fix. - -Once we are sure we can stay with Rails 5, we will stop running CI pipelines with Rails 4. - -## Can I skip running Rails 4 tests? - -If you are sure that your merge request doesn't introduce any incompatibility, you can just include `norails4` anywhere in your branch name and Rails 4 tests will be skipped. - -## CI is failing on my test with Rails 4. How can I debug it? - -You can run specs locally with Rails 4 using the following command: - -```sh -BUNDLE_GEMFILE=Gemfile.rails4 RAILS5=0 bundle exec rspec ... -``` diff --git a/doc/user/project/clusters/index.md b/doc/user/project/clusters/index.md index 5d9345fe0e3..db48388e90d 100644 --- a/doc/user/project/clusters/index.md +++ b/doc/user/project/clusters/index.md @@ -140,13 +140,14 @@ To add an existing Kubernetes cluster to your project: to grant access. - **Project namespace** (optional) - You don't have to fill it in; by leaving it blank, GitLab will create one for you. Also: - - Each project should have a unique namespace. - - The project namespace is not necessarily the namespace of the secret, if - you're using a secret with broader permissions, like the secret from `default`. - - You should **not** use `default` as the project namespace. - - If you or someone created a secret specifically for the project, usually - with limited permissions, the secret's namespace and project namespace may - be the same. + - Each project should have a unique namespace. + - The project namespace is not necessarily the namespace of the secret, if + you're using a secret with broader permissions, like the secret from `default`. + - You should **not** use `default` as the project namespace. + - If you or someone created a secret specifically for the project, usually + with limited permissions, the secret's namespace and project namespace may + be the same. + 1. Finally, click the **Create Kubernetes cluster** button. After a couple of minutes, your cluster will be ready to go. You can now proceed @@ -168,7 +169,7 @@ are trusted, so **only trusted users should be allowed to control your clusters* The default cluster configuration grants access to a wide set of functionalities needed to successfully build and deploy a containerized -application. Bare in mind that the same credentials are used for all the +application. Bear in mind that the same credentials are used for all the applications running on the cluster. ## Access controls @@ -354,6 +355,18 @@ to reach your apps. This heavily depends on your domain provider, but in case you aren't sure, just create an A record with a wildcard host like `*.example.com.`. +## Multiple Kubernetes clusters **[PREMIUM]** + +> Introduced in [GitLab Premium][ee] 10.3. + +With GitLab Premium, you can associate more than one Kubernetes clusters to your +project. That way you can have different clusters for different environments, +like dev, staging, production, etc. + +Simply add another cluster, like you did the first time, and make sure to +[set an environment scope](#setting-the-environment-scope) that will +differentiate the new cluster with the rest. + ## Setting the environment scope **[PREMIUM]** When adding more than one Kubernetes clusters to your project, you need @@ -372,11 +385,11 @@ Also, jobs that don't have an environment keyword set will not be able to access For example, let's say the following Kubernetes clusters exist in a project: -| Cluster | Environment scope | -| ---------- | ------------------- | -| Development| `*` | -| Staging | `staging/*` | -| Production | `production/*` | +| Cluster | Environment scope | +| ----------- | ----------------- | +| Development | `*` | +| Staging | `staging` | +| Production | `production` | And the following environments are set in [`.gitlab-ci.yml`](../../../ci/yaml/README.md): @@ -393,14 +406,14 @@ deploy to staging: stage: deploy script: make deploy environment: - name: staging/$CI_COMMIT_REF_NAME + name: staging url: https://staging.example.com/ deploy to production: stage: deploy script: make deploy environment: - name: production/$CI_COMMIT_REF_NAME + name: production url: https://example.com/ ``` @@ -410,18 +423,6 @@ The result will then be: - The staging cluster will be used for the "deploy to staging" job. - The production cluster will be used for the "deploy to production" job. -## Multiple Kubernetes clusters - -> Introduced in [GitLab Premium][ee] 10.3. - -With GitLab Premium, you can associate more than one Kubernetes clusters to your -project. That way you can have different clusters for different environments, -like dev, staging, production, etc. - -Simply add another cluster, like you did the first time, and make sure to -[set an environment scope](#setting-the-environment-scope) that will -differentiate the new cluster with the rest. - ## Deployment variables The Kubernetes cluster integration exposes the following @@ -463,6 +464,14 @@ builds is that they must have a matching your build has no `environment:name` set, it will not be passed the Kubernetes credentials. +## Monitoring your Kubernetes cluster **[ULTIMATE]** + +> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/4701) in [GitLab Ultimate][ee] 10.6. + +When [Prometheus is deployed](#installing-applications), GitLab will automatically monitor the cluster's health. At the top of the cluster settings page, CPU and Memory utilization is displayed, along with the total amount available. Keeping an eye on cluster resources can be important, if the cluster runs out of memory pods may be shutdown or fail to start. + +![Cluster Monitoring](https://docs.gitlab.com/ee/user/project/clusters/img/k8s_cluster_monitoring.png) + ## Enabling or disabling the Kubernetes cluster integration After you have successfully added your cluster information, you can enable the @@ -489,13 +498,16 @@ To remove the Kubernetes cluster integration from your project, simply click the **Remove integration** button. You will then be able to follow the procedure and add a Kubernetes cluster again. +## View Kubernetes pod logs from GitLab **[ULTIMATE]** + +Learn how to easily +[view the logs of running pods in connected Kubernetes clusters](https://docs.gitlab.com/ee/user/project/clusters/kubernetes_pod_logs.html). + ## What you can get with the Kubernetes integration Here's what you can do with GitLab if you enable the Kubernetes integration. -### Deploy Boards - -> Available in [GitLab Premium][ee]. +### Deploy Boards **[PREMIUM]** GitLab's Deploy Boards offer a consolidated view of the current health and status of each CI [environment](../../../ci/environments.md) running on Kubernetes, @@ -503,24 +515,22 @@ displaying the status of the pods in the deployment. Developers and other teammates can view the progress and status of a rollout, pod by pod, in the workflow they already use without any need to access Kubernetes. -[> Read more about Deploy Boards](https://docs.gitlab.com/ee/user/project/deploy_boards.html) +[Read more about Deploy Boards](https://docs.gitlab.com/ee/user/project/deploy_boards.html) -### Canary Deployments - -> Available in [GitLab Premium][ee]. +### Canary Deployments **[PREMIUM]** Leverage [Kubernetes' Canary deployments](https://kubernetes.io/docs/concepts/cluster-administration/manage-deployment/#canary-deployments) and visualize your canary deployments right inside the Deploy Board, without the need to leave GitLab. -[> Read more about Canary Deployments](https://docs.gitlab.com/ee/user/project/canary_deployments.html) +[Read more about Canary Deployments](https://docs.gitlab.com/ee/user/project/canary_deployments.html) ### Kubernetes monitoring Automatically detect and monitor Kubernetes metrics. Automatic monitoring of [NGINX ingress](../integrations/prometheus_library/nginx.md) is also supported. -[> Read more about Kubernetes monitoring](../integrations/prometheus_library/kubernetes.md) +[Read more about Kubernetes monitoring](../integrations/prometheus_library/kubernetes.md) ### Auto DevOps @@ -530,7 +540,7 @@ applications. To make full use of Auto DevOps(Auto Deploy, Auto Review Apps, and Auto Monitoring) you will need the Kubernetes project integration enabled. -[> Read more about Auto DevOps](../../../topics/autodevops/index.md) +[Read more about Auto DevOps](../../../topics/autodevops/index.md) ### Web terminals @@ -546,8 +556,6 @@ containers. To use this integration, you should deploy to Kubernetes using the deployment variables above, ensuring any pods you create are labelled with `app=$CI_ENVIRONMENT_SLUG`. GitLab will do the rest! -## Read more - ### Integrating Amazon EKS cluster with GitLab - Learn how to [connect and deploy to an Amazon EKS cluster](eks_and_gitlab/index.md). diff --git a/doc/user/project/clusters/serverless/img/deploy-stage.png b/doc/user/project/clusters/serverless/img/deploy-stage.png Binary files differindex dc2f8af9c63..a1e0095bf29 100644 --- a/doc/user/project/clusters/serverless/img/deploy-stage.png +++ b/doc/user/project/clusters/serverless/img/deploy-stage.png diff --git a/doc/user/project/clusters/serverless/img/dns-entry.png b/doc/user/project/clusters/serverless/img/dns-entry.png Binary files differindex 2e7655c6041..678743f256e 100644 --- a/doc/user/project/clusters/serverless/img/dns-entry.png +++ b/doc/user/project/clusters/serverless/img/dns-entry.png diff --git a/doc/user/project/clusters/serverless/img/install-knative.png b/doc/user/project/clusters/serverless/img/install-knative.png Binary files differindex a9fcc127240..94f4c84181f 100644 --- a/doc/user/project/clusters/serverless/img/install-knative.png +++ b/doc/user/project/clusters/serverless/img/install-knative.png diff --git a/doc/user/project/clusters/serverless/img/knative-app.png b/doc/user/project/clusters/serverless/img/knative-app.png Binary files differindex 54301e1786f..a5b2945f6f4 100644 --- a/doc/user/project/clusters/serverless/img/knative-app.png +++ b/doc/user/project/clusters/serverless/img/knative-app.png diff --git a/doc/user/project/clusters/serverless/img/serverless-page.png b/doc/user/project/clusters/serverless/img/serverless-page.png Binary files differindex 473ee801f10..5d808fc2d4f 100644 --- a/doc/user/project/clusters/serverless/img/serverless-page.png +++ b/doc/user/project/clusters/serverless/img/serverless-page.png diff --git a/doc/user/project/clusters/serverless/index.md b/doc/user/project/clusters/serverless/index.md index bdbc4f7f09d..c1f2e844362 100644 --- a/doc/user/project/clusters/serverless/index.md +++ b/doc/user/project/clusters/serverless/index.md @@ -2,109 +2,204 @@ > Introduced in GitLab 11.5. +CAUTION: **Caution:** +Serverless is currently in [alpha](https://about.gitlab.com/handbook/product/#alpha). + Run serverless workloads on Kubernetes using [Knative](https://cloud.google.com/knative/). ## Overview Knative extends Kubernetes to provide a set of middleware components that are useful to build modern, source-centric, container-based applications. Knative brings some significant benefits out of the box through its main components: -- [Build:](https://github.com/knative/build) Source-to-container build orchestration -- [Eventing:](https://github.com/knative/eventing) Management and delivery of events -- [Serving:](https://github.com/knative/serving) Request-driven compute that can scale to zero +- [Build](https://github.com/knative/build): Source-to-container build orchestration. +- [Eventing](https://github.com/knative/eventing): Management and delivery of events. +- [Serving](https://github.com/knative/serving): Request-driven compute that can scale to zero. For more information on Knative, visit the [Knative docs repo](https://github.com/knative/docs). +With GitLab serverless, you can deploy both functions-as-a-service (FaaS) and serverless applications. + ## Requirements To run Knative on Gitlab, you will need: -1. **Kubernetes:** An RBAC-enabled Kubernetes cluster is required to deploy Knative. - The simplest way to get started is to add a cluster using [GitLab's GKE integration](https://docs.gitlab.com/ee/user/project/clusters/#adding-and-creating-a-new-gke-cluster-via-gitlab). - GitLab recommends -1. **Helm Tiller:** Helm is a package manager for Kubernetes and is required to install - all the other applications. -1. **Domain Name:** Knative will provide its own load balancer using Istio. It will provide an - external IP address for all the applications served by Knative. You will be prompted to enter a - wildcard domain where your applications will be served. Configure your DNS server to use the +1. **Kubernetes Cluster:** An RBAC-enabled Kubernetes cluster is required to deploy Knative. + The simplest way to get started is to add a cluster using [GitLab's GKE integration](../index.md#adding-and-creating-a-new-gke-cluster-via-gitlab). +1. **Helm Tiller:** Helm is a package manager for Kubernetes and is required to install + Knative. +1. **Domain Name:** Knative will provide its own load balancer using Istio. It will provide an + external IP address for all the applications served by Knative. You will be prompted to enter a + wildcard domain where your applications will be served. Configure your DNS server to use the external IP address for that domain. -1. **Serverless `gitlab-ci.yml` Template:** GitLab uses [Kaniko](https://github.com/GoogleContainerTools/kaniko) - to build the application and the [TriggerMesh CLI](https://github.com/triggermesh/tm), to simplify the +1. **`gitlab-ci.yml`:** GitLab uses [Kaniko](https://github.com/GoogleContainerTools/kaniko) + to build the application and the [TriggerMesh CLI](https://github.com/triggermesh/tm) to simplify the deployment of knative services and functions. - - Add the following `.gitlab-ci.yml` to the root of your repository (you may skip this step if using the sample - [Knative Ruby App](https://gitlab.com/knative-examples/knative-ruby-app) mentioned below). - - ```yaml - stages: - - build - - deploy - - build: - stage: build - image: - name: gcr.io/kaniko-project/executor:debug - entrypoint: [""] - only: - - master - script: - - echo "{\"auths\":{\"$CI_REGISTRY\":{\"username\":\"$CI_REGISTRY_USER\",\"password\":\"$CI_REGISTRY_PASSWORD\"}}}" > /kaniko/.docker/config.json - - /kaniko/executor --context $CI_PROJECT_DIR --dockerfile $CI_PROJECT_DIR/Dockerfile --destination $CI_REGISTRY_IMAGE - - deploy: - stage: deploy - image: gcr.io/triggermesh/tm@sha256:e3ee74db94d215bd297738d93577481f3e4db38013326c90d57f873df7ab41d5 - only: - - master - environment: production - script: - - echo "$CI_REGISTRY_IMAGE" - - tm -n "$KUBE_NAMESPACE" --config "$KUBECONFIG" deploy service "$CI_PROJECT_NAME" --from-image "$CI_REGISTRY_IMAGE" --wait - ``` - -1. **Dockerfile:** Knative requires a Dockerfile in order to build your application. It should be included - at the root of your project's repo and expose port 8080. +1. **`serverless.yml`** (for [functions only](#deploying-functions)): When using serverless to deploy functions, the `serverless.yml` file + will contain the information for all the functions being hosted in the repository as well as a reference to the + runtime being used. +1. **`Dockerfile`:** Knative requires a `Dockerfile` in order to build your application. It should be included + at the root of your project's repo and expose port `8080`. ## Installing Knative via GitLab's Kubernetes integration NOTE: **Note:** -Minimum recommended cluster size to run Knative is 3-nodes, 6 vCPUs, and 22.50 GB memory. RBAC must be enabled. - -You may download the sample [Knative Ruby App](https://gitlab.com/knative-examples/knative-ruby-app) to get started. - -1. [Add a Kubernetes cluster](https://docs.gitlab.com/ce/user/project/clusters/) and install Helm. +The minimum recommended cluster size to run Knative is 3-nodes, 6 vCPUs, and 22.50 GB memory. **RBAC must be enabled.** -1. Once Helm has been successfully installed, on the Knative app section, enter the domain to be used with +1. [Add a Kubernetes cluster](../index.md) and install Helm. +1. Once Helm has been successfully installed, on the Knative app section, enter the domain to be used with your application and click "Install". ![install-knative](img/install-knative.png) -1. After the Knative installation has finished, retrieve the Istio Ingress IP address by running the following command: +1. After the Knative installation has finished, you can wait for the IP address to be displayed in the + **Knative IP Address** field or retrieve the Istio Ingress IP address by running the following command: - ```bash - kubectl get svc --namespace=istio-system knative-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].ip} ' - ``` + ```bash + kubectl get svc --namespace=istio-system knative-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].ip} ' + ``` - Output: + Output: - ```bash - 35.161.143.124 my-machine-name:~ my-user$ - ``` + ```bash + 35.161.143.124 my-machine-name:~ my-user$ + ``` -1. The ingress is now available at this address and will route incoming requests to the proper service based on the DNS - name in the request. To support this, a wildcard DNS A record should be created for the desired domain name. For example, - if your Knative base domain is `knative.example.com` then you need to create an A record with domain `*.knative.example.com` - pointing the ip address of the ingress. +1. The ingress is now available at this address and will route incoming requests to the proper service based on the DNS + name in the request. To support this, a wildcard DNS A record should be created for the desired domain name. For example, + if your Knative base domain is `knative.info` then you need to create an A record with domain `*.knative.info` + pointing the ip address of the ingress. ![dns entry](img/dns-entry.png) +## Deploying Functions + +> Introduced in GitLab 11.6. + +Using functions is useful for initiating, responding, or triggering independent +events without needing to maintain a complex unified infrastructure. This allows +you to focus on a single task that can be executed/scaled automatically and independently. + +In order to deploy functions to your Knative instance, the following templates must be present: + +1. `gitlab-ci.yml`: This template allows to define the stage, environment, and + image to be used for your functions. It must be included at the root of your repository: + + ```yaml + stages: + - deploy + + functions: + stage: deploy + environment: test + image: gcr.io/triggermesh/tm:v0.0.6 + script: + - tm -n "$KUBE_NAMESPACE" set registry-auth gitlab-registry --registry "$CI_REGISTRY" --username "$CI_REGISTRY_USER" --password "$CI_JOB_TOKEN" + - tm -n "$KUBE_NAMESPACE" --registry-host "$CI_REGISTRY_IMAGE" deploy --wait + ``` + +2. `serverless.yml`: This template contains the metadata for your functions, + such as name, runtime, and environment. It must be included at the root of your repository: + + ```yaml + service: knative-test + description: "Deploying functions from GitLab using Knative" + + provider: + name: triggermesh + registry-secret: gitlab-registry + environment: + FOO: BAR + + functions: + container: + handler: simple + description: "knative canonical sample" + runtime: https://gitlab.com/triggermesh/runtimes/raw/master/kaniko.yaml + buildargs: + - DIRECTORY=simple + environment: + SIMPLE_MSG: Hello + + nodejs: + handler: nodejs + runtime: https://gitlab.com/triggermesh/runtimes/raw/master/nodejs.yaml + description: "nodejs fragment" + buildargs: + - DIRECTORY=nodejs + environment: + FUNCTION: nodejs + ``` + +After the templates have been created, each function must be defined as a single +file in your repository. Committing a function to your project will result in a +CI pipeline being executed which will deploy each function as a Knative service. +Once the deploy stage has finished, additional details for the function will +appear under **Operations > Serverless**. + +![serverless page](img/serverless-page.png) + +This page contains all functions available for the project, the URL for +accessing the function, and if available, the function's runtime information. +The details are derived from the Knative installation inside each of the project's +Kubernetes cluster. + +The function details can be retrieved directly from Knative on the cluster: + +```bash +kubectl -n "$KUBE_NAMESPACE" get services.serving.knative.dev +``` + +Currently, the Serverless page presents all functions available in all clusters registered for the project with Knative installed. + +## Deploying Serverless applications + +> Introduced in GitLab 11.5. + +NOTE: **Note:** +You can reference the sample [Knative Ruby App](https://gitlab.com/knative-examples/knative-ruby-app) to get started. + +Add the following `.gitlab-ci.yml` to the root of your repository +(you may skip this step if using the sample [Knative Ruby App](https://gitlab.com/knative-examples/knative-ruby-app) mentioned above): + +```yaml +stages: + - build + - deploy + +build: + stage: build + image: + name: gcr.io/kaniko-project/executor:debug + entrypoint: [""] + only: + - master + script: + - echo "{\"auths\":{\"$CI_REGISTRY\":{\"username\":\"$CI_REGISTRY_USER\",\"password\":\"$CI_REGISTRY_PASSWORD\"}}}" > /kaniko/.docker/config.json + - /kaniko/executor --context $CI_PROJECT_DIR --dockerfile $CI_PROJECT_DIR/Dockerfile --destination $CI_REGISTRY_IMAGE + +deploy: + stage: deploy + image: gcr.io/triggermesh/tm@sha256:e3ee74db94d215bd297738d93577481f3e4db38013326c90d57f873df7ab41d5 + only: + - master + environment: production + script: + - echo "$CI_REGISTRY_IMAGE" + - tm -n "$KUBE_NAMESPACE" --config "$KUBECONFIG" deploy service "$CI_PROJECT_NAME" --from-image "$CI_REGISTRY_IMAGE" --wait +``` + ## Deploy the application with Knative -With all the pieces in place, you can simply create a new CI pipeline to deploy the Knative application. Navigate to -**CI/CD >> Pipelines** and click the **Run Pipeline** button at the upper-right part of the screen. Then, on the +With all the pieces in place, you can create a new CI pipeline to deploy the Knative application. Navigate to +**CI/CD > Pipelines** and click the **Run Pipeline** button at the upper-right part of the screen. Then, on the Pipelines page, click **Create pipeline**. ## Obtain the URL for the Knative deployment +There are two ways to obtain the URL for the Knative deployment. + +### Using the CI/CD deployment job output + Once all the stages of the pipeline finish, click the **deploy** stage. ![deploy stage](img/deploy-stage.png) @@ -131,7 +226,7 @@ Service domain: knative.knative-4342902.knative.info Job succeeded ``` -The second to last line, labeled **Service domain** contains the URL for the deployment. Copy and paste the domain into your +The second to last line, labeled **Service domain** contains the URL for the deployment. Copy and paste the domain into your browser to see the app live. -![knative app](img/knative-app.png)
\ No newline at end of file +![knative app](img/knative-app.png) diff --git a/doc/user/project/integrations/prometheus.md b/doc/user/project/integrations/prometheus.md index 7d0e567cae7..d9a2eeb32ae 100644 --- a/doc/user/project/integrations/prometheus.md +++ b/doc/user/project/integrations/prometheus.md @@ -41,6 +41,7 @@ Once you have a connected Kubernetes cluster with Helm installed, deploying a ma Prometheus is deployed into the `gitlab-managed-apps` namespace, using the [official Helm chart](https://github.com/kubernetes/charts/tree/master/stable/prometheus). Prometheus is only accessible within the cluster, with GitLab communicating through the [Kubernetes API](https://kubernetes.io/docs/concepts/overview/kubernetes-api/). The Prometheus server will [automatically detect and monitor](https://prometheus.io/docs/prometheus/latest/configuration/configuration/#%3Ckubernetes_sd_config%3E) nodes, pods, and endpoints. To configure a resource to be monitored by Prometheus, simply set the following [Kubernetes annotations](https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/): + * `prometheus.io/scrape` to `true` to enable monitoring of the resource. * `prometheus.io/port` to define the port of the metrics endpoint. * `prometheus.io/path` to define the path of the metrics endpoint. Defaults to `/metrics`. diff --git a/doc/user/project/pages/getting_started_part_three.md b/doc/user/project/pages/getting_started_part_three.md index 247e8d2a6a0..cea9628966d 100644 --- a/doc/user/project/pages/getting_started_part_three.md +++ b/doc/user/project/pages/getting_started_part_three.md @@ -234,26 +234,25 @@ reiterating the importance of HTTPS. ## Issuing Certificates -GitLab Pages accepts [PEM](https://support.quovadisglobal.com/kb/a37/what-is-pem-format.aspx) certificates issued by -[Certificate Authorities (CA)](https://en.wikipedia.org/wiki/Certificate_authority) -and self-signed certificates. Of course, -[you'd rather issue a certificate than generate a self-signed](https://en.wikipedia.org/wiki/Self-signed_certificate), -for security reasons and for having browsers trusting your -site's certificate. - -There are several different kinds of certificates, each one -with certain security level. A static personal website will +GitLab Pages accepts certificates provided in the [PEM](https://support.quovadisglobal.com/kb/a37/what-is-pem-format.aspx) format, issued by +[Certificate Authorities (CAs)](https://en.wikipedia.org/wiki/Certificate_authority) or as +[self-signed certificates](https://en.wikipedia.org/wiki/Self-signed_certificate). Note that [self-signed certificates are typically not used](https://securingtomorrow.mcafee.com/other-blogs/mcafee-labs/self-signed-certificates-secure-so-why-ban/) +for public websites for security reasons and to ensure that browsers trust your site's certificate. + +There are various kinds of certificates, each one +with a certain security level. A static personal website will not require the same security level as an online banking web app, -for instance. There are a couple Certificate Authorities that +for instance. + +There are some certificate authorities that offer free certificates, aiming to make the internet more secure to everyone. The most popular is [Let's Encrypt](https://letsencrypt.org/), which issues certificates trusted by most of browsers, it's open -source, and free to use. Please read through this tutorial to -understand [how to secure your GitLab Pages website with Let's Encrypt](https://about.gitlab.com/2016/04/11/tutorial-securing-your-gitlab-pages-with-tls-and-letsencrypt/). +source, and free to use. See our tutorial on [how to secure your GitLab Pages website with Let's Encrypt](lets_encrypt_for_gitlab_pages.md). -With the same popularity, there are [certificates issued by CloudFlare](https://www.cloudflare.com/ssl/), +Similarly popular are [certificates issued by CloudFlare](https://www.cloudflare.com/ssl/), which also offers a [free CDN service](https://blog.cloudflare.com/cloudflares-free-cdn-and-you/). -Their certs are valid up to 15 years. Read through the tutorial on +Their certs are valid up to 15 years. See the tutorial on [how to add a CloudFlare Certificate to your GitLab Pages website](https://about.gitlab.com/2017/02/07/setting-up-gitlab-pages-with-cloudflare-certificates/). ### Adding certificates to your project diff --git a/doc/user/project/pages/index.md b/doc/user/project/pages/index.md index 7de9ae0caea..ce4fccdaff3 100644 --- a/doc/user/project/pages/index.md +++ b/doc/user/project/pages/index.md @@ -170,7 +170,7 @@ optionally secure it with SSL/TLS certificates. You can read the following tutorials to learn how to use these third-party certificates with GitLab Pages: - [CloudFlare](https://about.gitlab.com/2017/02/07/setting-up-gitlab-pages-with-cloudflare-certificates/) -- [Let's Encrypt](https://about.gitlab.com/2016/04/11/tutorial-securing-your-gitlab-pages-with-tls-and-letsencrypt/) (mind that although this article is out-of-date, it can still be useful to guide you through the basic steps) +- [Let's Encrypt](lets_encrypt_for_gitlab_pages.md) ## Advanced use diff --git a/doc/user/project/pages/lets_encrypt_for_gitlab_pages.md b/doc/user/project/pages/lets_encrypt_for_gitlab_pages.md new file mode 100644 index 00000000000..f639188684b --- /dev/null +++ b/doc/user/project/pages/lets_encrypt_for_gitlab_pages.md @@ -0,0 +1,158 @@ +--- +description: "How to secure GitLab Pages websites with Let's Encrypt." +--- + +# Let's Encrypt for GitLab Pages + +If you have a GitLab Pages website served under your own domain, +you might want to secure it with a SSL/TSL certificate. + +[Let's Encrypt](https://letsencrypt.org) is a free, automated, and +open source Certificate Authority. + +## Requirements + +To follow along with this tutorial, we assume you already have: + +- Created a [project](getting_started_part_two.md) in GitLab which + contains your website's source code. +- Acquired a domain (`example.com`) and added a [DNS entry](getting_started_part_three.md#dns-records) + pointing it to your Pages website. +- [Added your domain to your Pages project](getting_started_part_three.md#add-your-custom-domain-to-gitlab-pages-settings) + and verified your ownership. +- Cloned your project into your computer. +- Your website up and running, served under HTTP protocol at `http://example.com`. + +## Obtaining a Let's Encrypt certificate + +Once you have the requirements addressed, follow the instructions +below to learn how to obtain the certificate. + +NOTE: **Note:** +The instructions below were tested on macOS Mojave. For other +operating systems the steps might be slightly different. Follow the +[CertBot instructions](https://certbot.eff.org/) according to your OS. + +1. On your computer, open a terminal and navigate to your repository's + root directory: + + ```bash + cd path/to/dir + ``` + +1. Install CertBot (the tool Let's Encrypt uses to issue certificates): + + ```bash + brew install certbot + ``` + +1. Request a certificate for your domain (`example.com`) and + provide an email account (`your@email.com`) to receive notifications: + + ```bash + sudo certbot certonly -a manual -d example.com --email your@email.com + ``` + + Alternatively, you can register without adding an e-mail account, + but you won't be notified about the certificate expiration's date: + + ```bash + sudo certbot certonly -a manual -d example.com --register-unsafely-without-email + ``` + + TIP: **Tip:** + Read through CertBot's documentation on their + [command line options](https://certbot.eff.org/docs/using.html#certbot-command-line-options). + +1. You'll be prompted with a message to agree with their terms. + Press `A` to agree and `Y` to let they log your IP. + + CertBot will then prompt you with the following message: + + ```bash + Create a file containing just this data: + + Rxnv6WKo95hsuLVX3osmT6LgmzsJKSaK9htlPToohOP.HUGNKk82jlsmOOfphlt8Jy69iuglsn095nxOMH9j3Yb + + And make it available on your web server at this URL: + + http://example.com/.well-known/acme-challenge/Rxnv6WKo95hsuLVX3osmT6LgmzsJKSaK9htlPToohOP + + Press Enter to Continue + ``` + +1. **Do not press Enter yet.** Let's Encrypt will need to verify your + domain ownership before issuing the certificate. To do so, create 3 + consecutive directories under your website's root: + `/.well-known/acme-challenge/Rxnv6WKo95hsuLVX3osmT6LgmzsJKSaK9htlPToohOP/` + and add to the last folder an `index.html` file containing the content + referred on the previous prompt message: + + ```bash + Rxnv6WKo95hsuLVX3osmT6LgmzsJKSaK9htlPToohOP.HUGNKk82jlsmOOfphlt8Jy69iuglsn095nxOMH9j3Yb + ``` + + Note that this file needs to be accessed under + `http://example.com/.well-known/acme-challenge/Rxnv6WKo95hsuLVX3osmT6LgmzsJKSaK9htlPToohOP` + to allow Let's Encrypt to verify the ownership of your domain, + therefore, it needs to be part of the website content under the + repo's [`public`](index.md#how-it-works) folder. + +1. Add, commit, and push the file into your repo in GitLab. Once the pipeline + passes, press **Enter** on your terminal to continue issuing your + certificate. CertBot will then prompt you with the following message: + + ```bash + Waiting for verification... + Cleaning up challenges + + IMPORTANT NOTES: + - Congratulations! Your certificate and chain have been saved at: + /etc/letsencrypt/live/example.com/fullchain.pem + Your key file has been saved at: + /etc/letsencrypt/live/example.com/privkey.pem + Your cert will expire on 2019-03-12. To obtain a new or tweaked + version of this certificate in the future, simply run certbot + again. To non-interactively renew *all* of your certificates, run + "certbot renew" + - If you like Certbot, please consider supporting our work by: + + Donating to ISRG / Let's Encrypt: https://letsencrypt.org/donate + Donating to EFF: https://eff.org/donate-le + ``` + +## Add your certificate to GitLab Pages + +Now that your certificate has been issued, let's add it to your Pages site: + +1. Back at GitLab, navigate to your project's **Settings > Pages**, + find your domain and click **Details** and **Edit** to add your certificate. +1. From your terminal, copy and paste the certificate into the first field + **Certificate (PEM)**: + + ```bash + sudo cat /etc/letsencrypt/live/example.com/fullchain.pem | pbcopy + ``` + +1. Copy and paste the public key into the second field **Key (PEM)**: + + ```bash + sudo cat /etc/letsencrypt/live/example.com/privkey.pem | pbcopy + ``` + +1. Click **Save changes** to apply them to your website. +1. Wait a few minutes for DNS propagation. +1. Visit your website at `https://example.com`. + +To force `https` connections on your site, navigate to your +project's **Settings > Pages** and check **Force domains with SSL +certificates to use HTTPS**. + +## Renewal + +Let's Encrypt certificates expire every 90 days and you'll have to +renew them periodically. To renew all your certificates at once, run: + +```bash +sudo certbot renew +``` diff --git a/lib/api/commit_statuses.rb b/lib/api/commit_statuses.rb index 62c966e06b4..08b4f8db8b0 100644 --- a/lib/api/commit_statuses.rb +++ b/lib/api/commit_statuses.rb @@ -116,7 +116,7 @@ module API end MergeRequest.where(source_project: @project, source_branch: ref) - .update_all(head_pipeline_id: pipeline) if pipeline.latest? + .update_all(head_pipeline_id: pipeline.id) if pipeline.latest? present status, with: Entities::CommitStatus rescue StateMachines::InvalidTransition => e diff --git a/lib/constraints/feature_constrainer.rb b/lib/constraints/feature_constrainer.rb index ca4376a9d38..cd246cf37a4 100644 --- a/lib/constraints/feature_constrainer.rb +++ b/lib/constraints/feature_constrainer.rb @@ -2,14 +2,14 @@ module Constraints class FeatureConstrainer - attr_reader :feature + attr_reader :args - def initialize(feature) - @feature = feature + def initialize(*args) + @args = args end def matches?(_request) - Feature.enabled?(feature) + Feature.enabled?(*args) end end end diff --git a/lib/gitlab/diff/file.rb b/lib/gitlab/diff/file.rb index a85c5386d98..b5fc8d364c8 100644 --- a/lib/gitlab/diff/file.rb +++ b/lib/gitlab/diff/file.rb @@ -255,6 +255,10 @@ module Gitlab end # rubocop: enable CodeReuse/ActiveRecord + def empty? + valid_blobs.map(&:empty?).all? + end + def raw_binary? try_blobs(:raw_binary?) end diff --git a/lib/gitlab/graphql.rb b/lib/gitlab/graphql.rb index 74c04e5380e..8a59e83974f 100644 --- a/lib/gitlab/graphql.rb +++ b/lib/gitlab/graphql.rb @@ -3,5 +3,9 @@ module Gitlab module Graphql StandardGraphqlError = Class.new(StandardError) + + def self.enabled? + Feature.enabled?(:graphql, default_enabled: true) + end end end diff --git a/lib/gitlab/import_export/import_export.yml b/lib/gitlab/import_export/import_export.yml index d10d4f2f746..3cd8ede830c 100644 --- a/lib/gitlab/import_export/import_export.yml +++ b/lib/gitlab/import_export/import_export.yml @@ -27,7 +27,8 @@ project_tree: - :award_emoji - notes: :author - - :releases + - releases: + :author - project_members: - :user - merge_requests: diff --git a/lib/rails4_migration_version.rb b/lib/rails4_migration_version.rb deleted file mode 100644 index ae48734dfad..00000000000 --- a/lib/rails4_migration_version.rb +++ /dev/null @@ -1,16 +0,0 @@ -# rubocop:disable Naming/FileName -# frozen_string_literal: true - -# When switching to rails 5, we added migration version to all migration -# classes. This patch makes it possible to run versioned migrations -# also with rails 4 - -unless Gitlab.rails5? - module ActiveRecord - class Migration - def self.[](version) - Migration - end - end - end -end diff --git a/lib/version_check.rb b/lib/version_check.rb index ccf7bb493db..c9f102f6b19 100644 --- a/lib/version_check.rb +++ b/lib/version_check.rb @@ -5,16 +5,17 @@ require "base64" # This class is used to build image URL to # check if it is a new version for update class VersionCheck - def data + def self.data { version: Gitlab::VERSION } end - def url + def self.url encoded_data = Base64.urlsafe_encode64(data.to_json) + "#{host}?gitlab_info=#{encoded_data}" end - def host + def self.host 'https://version.gitlab.com/check.svg' end end diff --git a/locale/gitlab.pot b/locale/gitlab.pot index b85eb6bdc88..0584d2006f7 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -711,6 +711,9 @@ msgstr "" msgid "Ask your group maintainer to set up a group Runner." msgstr "" +msgid "Assets" +msgstr "" + msgid "Assign custom color like #FF0000" msgstr "" @@ -2587,6 +2590,9 @@ msgstr "" msgid "Download" msgstr "" +msgid "Download asset" +msgstr "" + msgid "Download tar" msgstr "" @@ -2662,6 +2668,9 @@ msgstr "" msgid "Embed" msgstr "" +msgid "Empty file" +msgstr "" + msgid "Enable" msgstr "" @@ -6377,6 +6386,9 @@ msgstr "" msgid "System metrics (Kubernetes)" msgstr "" +msgid "Tag" +msgstr "" + msgid "Tags" msgstr "" diff --git a/scripts/prepare_build.sh b/scripts/prepare_build.sh index 18dd8dcf1f5..d85c53090a4 100644 --- a/scripts/prepare_build.sh +++ b/scripts/prepare_build.sh @@ -1,7 +1,6 @@ . scripts/utils.sh export SETUP_DB=${SETUP_DB:-true} -export CREATE_DB_USER=${CREATE_DB_USER:-$SETUP_DB} export USE_BUNDLE_INSTALL=${USE_BUNDLE_INSTALL:-true} export BUNDLE_INSTALL_FLAGS="--without=production --jobs=$(nproc) --path=vendor --retry=3 --quiet" diff --git a/scripts/rails4-gemfile-lock-check b/scripts/rails4-gemfile-lock-check deleted file mode 100755 index a74a49874e1..00000000000 --- a/scripts/rails4-gemfile-lock-check +++ /dev/null @@ -1,19 +0,0 @@ -#!/usr/bin/env bash - -echo -e "=> Checking if Gemfile.rails4.lock is up-to-date...\\n" - -cp Gemfile.rails4.lock Gemfile.rails4.lock.orig -BUNDLE_GEMFILE=Gemfile.rails4 bundle install "$BUNDLE_INSTALL_FLAGS" -diff -u Gemfile.rails4.lock.orig Gemfile.rails4.lock >/dev/null 2>&1 - -if [ $? == 1 ] -then - diff -u Gemfile.rails4.lock.orig Gemfile.rails4.lock - - echo -e "\\n✖ ERROR: Gemfile.rails4.lock is not up-to-date! - Please run 'BUNDLE_GEMFILE=Gemfile.rails4 bundle install'\\n" >&2 - exit 1 -fi - -echo "✔ Gemfile.rails4.lock is up-to-date" -exit 0 diff --git a/spec/controllers/projects/services_controller_spec.rb b/spec/controllers/projects/services_controller_spec.rb index 45cea8c1351..0941af6779f 100644 --- a/spec/controllers/projects/services_controller_spec.rb +++ b/spec/controllers/projects/services_controller_spec.rb @@ -3,9 +3,8 @@ require 'spec_helper' describe Projects::ServicesController do let(:project) { create(:project, :repository) } let(:user) { create(:user) } - let(:service) { create(:hipchat_service, project: project) } - let(:hipchat_client) { { '#room' => double(send: true) } } - let(:service_params) { { token: 'hipchat_token_p', room: '#room' } } + let(:service) { create(:jira_service, project: project) } + let(:service_params) { { username: 'username', password: 'password', url: 'http://example.com' } } before do sign_in(user) @@ -24,13 +23,13 @@ describe Projects::ServicesController do end context 'when validations fail' do - let(:service_params) { { active: 'true', token: '' } } + let(:service_params) { { active: 'true', url: '' } } it 'returns error messages in JSON response' do - put :test, namespace_id: project.namespace, project_id: project, id: :hipchat, service: service_params + put :test, namespace_id: project.namespace, project_id: project, id: service.to_param, service: service_params expect(json_response['message']).to eq "Validations failed." - expect(json_response['service_response']).to eq "Token can't be blank" + expect(json_response['service_response']).to include "Url can't be blank" expect(response).to have_gitlab_http_status(200) end end @@ -52,7 +51,8 @@ describe Projects::ServicesController do end it 'returns success' do - expect(HipChat::Client).to receive(:new).with('hipchat_token_p', anything).and_return(hipchat_client) + stub_request(:get, 'http://example.com/rest/api/2/serverInfo') + .to_return(status: 200, body: '{}') put :test, namespace_id: project.namespace, project_id: project, id: service.to_param, service: service_params @@ -61,7 +61,8 @@ describe Projects::ServicesController do end it 'returns success' do - expect(HipChat::Client).to receive(:new).with('hipchat_token_p', anything).and_return(hipchat_client) + stub_request(:get, 'http://example.com/rest/api/2/serverInfo') + .to_return(status: 200, body: '{}') put :test, namespace_id: project.namespace, project_id: project, id: service.to_param, service: service_params @@ -76,12 +77,16 @@ describe Projects::ServicesController do it 'persist the object' do do_put + expect(response).to have_gitlab_http_status(200) + expect(json_response).to be_empty expect(BuildkiteService.first).to be_present end it 'creates the ServiceHook object' do do_put + expect(response).to have_gitlab_http_status(200) + expect(json_response).to be_empty expect(BuildkiteService.first.service_hook).to be_present end @@ -96,13 +101,18 @@ describe Projects::ServicesController do context 'failure' do it 'returns success status code and the error message' do - expect(HipChat::Client).to receive(:new).with('hipchat_token_p', anything).and_raise('Bad test') + stub_request(:get, 'http://example.com/rest/api/2/serverInfo') + .to_return(status: 404) put :test, namespace_id: project.namespace, project_id: project, id: service.to_param, service: service_params - expect(response.status).to eq(200) - expect(JSON.parse(response.body)) - .to eq('error' => true, 'message' => 'Test failed.', 'service_response' => 'Bad test', 'test_failed' => true) + expect(response).to have_gitlab_http_status(200) + expect(json_response).to eq( + 'error' => true, + 'message' => 'Test failed.', + 'service_response' => '', + 'test_failed' => true + ) end end end @@ -114,7 +124,7 @@ describe Projects::ServicesController do namespace_id: project.namespace, project_id: project, id: service.to_param, service: { active: true } expect(response).to redirect_to(project_settings_integrations_path(project)) - expect(flash[:notice]).to eq 'HipChat activated.' + expect(flash[:notice]).to eq 'JIRA activated.' end end @@ -123,7 +133,7 @@ describe Projects::ServicesController do put :update, namespace_id: project.namespace, project_id: project, id: service.to_param, service: { active: false } - expect(flash[:notice]).to eq 'HipChat settings saved, but not activated.' + expect(flash[:notice]).to eq 'JIRA settings saved, but not activated.' end end diff --git a/spec/factories/releases.rb b/spec/factories/releases.rb index d80c65cf8bb..18047c74a5d 100644 --- a/spec/factories/releases.rb +++ b/spec/factories/releases.rb @@ -1,6 +1,7 @@ FactoryBot.define do factory :release do tag "v1.1.0" + name { tag } description "Awesome release" project end diff --git a/spec/features/help_pages_spec.rb b/spec/features/help_pages_spec.rb index c29dfb01381..e24b1f4349d 100644 --- a/spec/features/help_pages_spec.rb +++ b/spec/features/help_pages_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe 'Help Pages' do @@ -52,23 +54,21 @@ describe 'Help Pages' do end end - context 'in a production environment with version check enabled', :js do + context 'in a production environment with version check enabled' do before do - allow(Rails.env).to receive(:production?) { true } stub_application_setting(version_check_enabled: true) - allow_any_instance_of(VersionCheck).to receive(:url) { '/version-check-url' } + + allow(Rails.env).to receive(:production?).and_return(true) + allow(VersionCheck).to receive(:url).and_return('/version-check-url') sign_in(create(:user)) visit help_path end it 'has a version check image' do - expect(find('.js-version-status-badge', visible: false)['src']).to end_with('/version-check-url') - end - - it 'hides the version check image if the image request fails' do - # We use '--load-images=yes' with poltergeist so the image fails to load - expect(page).to have_selector('.js-version-status-badge', visible: false) + # Check `data-src` due to lazy image loading + expect(find('.js-version-status-badge', visible: false)['data-src']) + .to end_with('/version-check-url') end end diff --git a/spec/features/issues/user_creates_issue_spec.rb b/spec/features/issues/user_creates_issue_spec.rb index 687a6f1eafc..830d56035aa 100644 --- a/spec/features/issues/user_creates_issue_spec.rb +++ b/spec/features/issues/user_creates_issue_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "spec_helper" describe "User creates issue" do @@ -64,10 +66,10 @@ describe "User creates issue" do end context "with labels" do - LABEL_TITLES = %w(bug feature enhancement).freeze + let(:label_titles) { %w(bug feature enhancement) } before do - LABEL_TITLES.each do |title| + label_titles.each do |title| create(:label, project: project, title: title) end end @@ -77,13 +79,13 @@ describe "User creates issue" do fill_in("Title", with: issue_title) click_button("Label") - click_link(LABEL_TITLES.first) + click_link(label_titles.first) click_button("Submit issue") expect(page).to have_content(issue_title) .and have_content(user.name) .and have_content(project.name) - .and have_content(LABEL_TITLES.first) + .and have_content(label_titles.first) end end end diff --git a/spec/features/merge_request/user_merges_when_pipeline_succeeds_spec.rb b/spec/features/merge_request/user_merges_when_pipeline_succeeds_spec.rb index 53ed5d78598..29b3d2b629b 100644 --- a/spec/features/merge_request/user_merges_when_pipeline_succeeds_spec.rb +++ b/spec/features/merge_request/user_merges_when_pipeline_succeeds_spec.rb @@ -88,6 +88,8 @@ describe 'Merge request > User merges when pipeline succeeds', :js do describe 'enabling Merge when pipeline succeeds via dropdown' do it 'activates the Merge when pipeline succeeds feature' do + wait_for_requests + find('.js-merge-moment').click click_link 'Merge when pipeline succeeds' diff --git a/spec/features/projects/labels/user_views_labels_spec.rb b/spec/features/projects/labels/user_views_labels_spec.rb index 0cbeca4e392..2c8267764bd 100644 --- a/spec/features/projects/labels/user_views_labels_spec.rb +++ b/spec/features/projects/labels/user_views_labels_spec.rb @@ -1,13 +1,15 @@ +# frozen_string_literal: true + require "spec_helper" describe "User views labels" do set(:project) { create(:project_empty_repo, :public) } set(:user) { create(:user) } - LABEL_TITLES = %w[bug enhancement feature].freeze + let(:label_titles) { %w[bug enhancement feature] } before do - LABEL_TITLES.each { |title| create(:label, project: project, title: title) } + label_titles.each { |title| create(:label, project: project, title: title) } project.add_guest(user) sign_in(user) @@ -17,7 +19,7 @@ describe "User views labels" do it "shows all labels" do page.within('.other-labels .manage-labels-list') do - LABEL_TITLES.each { |title| expect(page).to have_content(title) } + label_titles.each { |title| expect(page).to have_content(title) } end end end diff --git a/spec/helpers/version_check_helper_spec.rb b/spec/helpers/version_check_helper_spec.rb index 9d4e34abef5..bfec7ad4bba 100644 --- a/spec/helpers/version_check_helper_spec.rb +++ b/spec/helpers/version_check_helper_spec.rb @@ -13,21 +13,21 @@ describe VersionCheckHelper do before do allow(Rails.env).to receive(:production?) { true } allow(Gitlab::CurrentSettings.current_application_settings).to receive(:version_check_enabled) { true } - allow_any_instance_of(VersionCheck).to receive(:url) { 'https://version.host.com/check.svg?gitlab_info=xxx' } - - @image_tag = helper.version_status_badge + allow(VersionCheck).to receive(:url) { 'https://version.host.com/check.svg?gitlab_info=xxx' } end it 'should return an image tag' do - expect(@image_tag).to match(/^<img/) + expect(helper.version_status_badge).to start_with('<img') end it 'should have a js prefixed css class' do - expect(@image_tag).to match(/class="js-version-status-badge lazy"/) + expect(helper.version_status_badge) + .to match(/class="js-version-status-badge lazy"/) end it 'should have a VersionCheck url as the src' do - expect(@image_tag).to match(%r{src="https://version\.host\.com/check\.svg\?gitlab_info=xxx"}) + expect(helper.version_status_badge) + .to include(%{src="https://version.host.com/check.svg?gitlab_info=xxx"}) end end end diff --git a/spec/javascripts/blob_edit/blob_bundle_spec.js b/spec/javascripts/blob_edit/blob_bundle_spec.js index 759d170af77..57f60a4a3dd 100644 --- a/spec/javascripts/blob_edit/blob_bundle_spec.js +++ b/spec/javascripts/blob_edit/blob_bundle_spec.js @@ -14,6 +14,7 @@ describe('EditBlob', () => { setFixtures(` <div class="js-edit-blob-form"> <button class="js-commit-button"></button> + <a class="btn btn-cancel" href="#"></a> </div>`); blobBundle(); }); @@ -27,4 +28,10 @@ describe('EditBlob', () => { expect(window.onbeforeunload).toBeNull(); }); + + it('removes beforeunload listener when cancel link is clicked', () => { + $('.btn.btn-cancel').click(); + + expect(window.onbeforeunload).toBeNull(); + }); }); diff --git a/spec/javascripts/boards/components/issue_due_date_spec.js b/spec/javascripts/boards/components/issue_due_date_spec.js index 9e49330c052..054cf8c5b7d 100644 --- a/spec/javascripts/boards/components/issue_due_date_spec.js +++ b/spec/javascripts/boards/components/issue_due_date_spec.js @@ -49,10 +49,11 @@ describe('Issue Due Date component', () => { it('should render month and day for other dates', () => { date.setDate(date.getDate() + 17); vm = createComponent(date); + const today = new Date(); + const isDueInCurrentYear = today.getFullYear() === date.getFullYear(); + const format = isDueInCurrentYear ? 'mmm d' : 'mmm d, yyyy'; - expect(vm.$el.querySelector('time').textContent.trim()).toEqual( - dateFormat(date, 'mmm d', true), - ); + expect(vm.$el.querySelector('time').textContent.trim()).toEqual(dateFormat(date, format, true)); }); it('should contain the correct `.text-danger` css class for overdue issue', () => { diff --git a/spec/javascripts/diffs/components/diff_content_spec.js b/spec/javascripts/diffs/components/diff_content_spec.js index d688560a260..9e158327a77 100644 --- a/spec/javascripts/diffs/components/diff_content_spec.js +++ b/spec/javascripts/diffs/components/diff_content_spec.js @@ -50,6 +50,45 @@ describe('DiffContent', () => { }); }); + describe('empty files', () => { + beforeEach(() => { + vm.diffFile.empty = true; + vm.diffFile.highlighted_diff_lines = []; + vm.diffFile.parallel_diff_lines = []; + }); + + it('should render a message', done => { + vm.$nextTick(() => { + const block = vm.$el.querySelector('.diff-viewer .nothing-here-block'); + + expect(block).not.toBe(null); + expect(block.textContent.trim()).toContain('Empty file'); + + done(); + }); + }); + + it('should not render multiple messages', done => { + vm.diffFile.mode_changed = true; + vm.diffFile.b_mode = '100755'; + vm.diffFile.viewer.name = 'mode_changed'; + + vm.$nextTick(() => { + expect(vm.$el.querySelectorAll('.nothing-here-block').length).toBe(1); + + done(); + }); + }); + + it('should not render diff table', done => { + vm.$nextTick(() => { + expect(vm.$el.querySelector('table')).toBe(null); + + done(); + }); + }); + }); + describe('Non-Text diffs', () => { beforeEach(() => { vm.diffFile.viewer.name = 'image'; diff --git a/spec/javascripts/releases/components/release_block_spec.js b/spec/javascripts/releases/components/release_block_spec.js new file mode 100644 index 00000000000..c0cd15b7507 --- /dev/null +++ b/spec/javascripts/releases/components/release_block_spec.js @@ -0,0 +1,148 @@ +import Vue from 'vue'; +import component from '~/releases/components/release_block.vue'; +import timeagoMixin from '~/vue_shared/mixins/timeago'; + +import mountComponent from '../../helpers/vue_mount_component_helper'; + +describe('Release block', () => { + const Component = Vue.extend(component); + + const release = { + name: 'Bionic Beaver', + tag_name: '18.04', + description: '## changelog\n\n* line 1\n* line2', + description_html: '<div><h2>changelog</h2><ul><li>line1</li<li>line 2</li></ul></div>', + author_name: 'Release bot', + author_email: 'release-bot@example.com', + created_at: '2012-05-28T05:00:00-07:00', + commit: { + id: '2695effb5807a22ff3d138d593fd856244e155e7', + short_id: '2695effb', + title: 'Initial commit', + created_at: '2017-07-26T11:08:53.000+02:00', + parent_ids: ['2a4b78934375d7f53875269ffd4f45fd83a84ebe'], + message: 'Initial commit', + author_name: 'John Smith', + author_email: 'john@example.com', + authored_date: '2012-05-28T04:42:42-07:00', + committer_name: 'Jack Smith', + committer_email: 'jack@example.com', + committed_date: '2012-05-28T04:42:42-07:00', + }, + assets: { + count: 6, + sources: [ + { + format: 'zip', + url: 'https://gitlab.com/gitlab-org/gitlab-ce/-/archive/v11.3.12/gitlab-ce-v11.3.12.zip', + }, + { + format: 'tar.gz', + url: + 'https://gitlab.com/gitlab-org/gitlab-ce/-/archive/v11.3.12/gitlab-ce-v11.3.12.tar.gz', + }, + { + format: 'tar.bz2', + url: + 'https://gitlab.com/gitlab-org/gitlab-ce/-/archive/v11.3.12/gitlab-ce-v11.3.12.tar.bz2', + }, + { + format: 'tar', + url: 'https://gitlab.com/gitlab-org/gitlab-ce/-/archive/v11.3.12/gitlab-ce-v11.3.12.tar', + }, + ], + links: [ + { + name: 'release-18.04.dmg', + url: 'https://my-external-hosting.example.com/scrambled-url/', + external: true, + }, + { + name: 'binary-linux-amd64', + url: + 'https://gitlab.com/gitlab-org/gitlab-ce/-/jobs/artifacts/v11.6.0-rc4/download?job=rspec-mysql+41%2F50', + external: false, + }, + ], + }, + }; + + const props = { + name: release.name, + tag: release.tag_name, + commit: release.commit, + description: release.description_html, + author: { + avatar_url: 'uploads/-/system/user/avatar/johndoe/avatar.png', + id: 482476, + name: 'John Doe', + path: '/johndoe', + state: 'active', + status_tooltip_html: null, + username: 'johndoe', + web_url: 'https://gitlab.com/johndoe', + }, + createdAt: release.created_at, + assetsCount: release.assets.count, + sources: release.assets.sources, + links: release.assets.links, + }; + + let vm; + + beforeEach(() => { + vm = mountComponent(Component, props); + }); + + afterEach(() => { + vm.$destroy(); + }); + + it('renders release name', () => { + expect(vm.$el.textContent).toContain(release.name); + }); + + it('renders commit sha', () => { + expect(vm.$el.textContent).toContain(release.commit.short_id); + }); + + it('renders tag name', () => { + expect(vm.$el.textContent).toContain(release.tag_name); + }); + + it('renders release date', () => { + expect(vm.$el.textContent).toContain(timeagoMixin.methods.timeFormated(release.created_at)); + }); + + it('renders number of assets provided', () => { + expect(vm.$el.querySelector('.js-assets-count').textContent).toContain(release.assets.count); + }); + + it('renders dropdown with the sources', () => { + expect(vm.$el.querySelectorAll('.js-sources-dropdown li').length).toEqual( + release.assets.sources.length, + ); + + expect(vm.$el.querySelector('.js-sources-dropdown li a').getAttribute('href')).toEqual( + release.assets.sources[0].url, + ); + + expect(vm.$el.querySelector('.js-sources-dropdown li a').textContent).toContain( + release.assets.sources[0].format, + ); + }); + + it('renders list with the links provided', () => { + expect(vm.$el.querySelectorAll('.js-assets-list li').length).toEqual( + release.assets.links.length, + ); + + expect(vm.$el.querySelector('.js-assets-list li a').getAttribute('href')).toEqual( + release.assets.links[0].url, + ); + + expect(vm.$el.querySelector('.js-assets-list li a').textContent).toContain( + release.assets.links[0].name, + ); + }); +}); diff --git a/spec/javascripts/vue_mr_widget/components/mr_widget_rebase_spec.js b/spec/javascripts/vue_mr_widget/components/mr_widget_rebase_spec.js index 300133dc602..212519743aa 100644 --- a/spec/javascripts/vue_mr_widget/components/mr_widget_rebase_spec.js +++ b/spec/javascripts/vue_mr_widget/components/mr_widget_rebase_spec.js @@ -114,7 +114,7 @@ describe('Merge request widget rebase component', () => { // Wait for the eventHub to be called .then(vm.$nextTick()) .then(() => { - expect(eventHub.$emit).toHaveBeenCalledWith('MRWidgetUpdateRequested'); + expect(eventHub.$emit).toHaveBeenCalledWith('MRWidgetRebaseSuccess'); }) .then(done) .catch(done.fail); diff --git a/spec/javascripts/vue_mr_widget/stores/get_state_key_spec.js b/spec/javascripts/vue_mr_widget/stores/get_state_key_spec.js index 9d34bdd1084..61ef26cd080 100644 --- a/spec/javascripts/vue_mr_widget/stores/get_state_key_spec.js +++ b/spec/javascripts/vue_mr_widget/stores/get_state_key_spec.js @@ -35,7 +35,7 @@ describe('getStateKey', () => { expect(bound()).toEqual('mergeWhenPipelineSucceeds'); - context.hasSHAChanged = true; + context.isSHAMismatch = true; expect(bound()).toEqual('shaMismatch'); diff --git a/spec/javascripts/vue_mr_widget/stores/mr_widget_store_spec.js b/spec/javascripts/vue_mr_widget/stores/mr_widget_store_spec.js index f5079147f60..c226704694c 100644 --- a/spec/javascripts/vue_mr_widget/stores/mr_widget_store_spec.js +++ b/spec/javascripts/vue_mr_widget/stores/mr_widget_store_spec.js @@ -3,23 +3,30 @@ import { stateKey } from '~/vue_merge_request_widget/stores/state_maps'; import mockData from '../mock_data'; describe('MergeRequestStore', () => { - describe('setData', () => { - let store; + let store; - beforeEach(() => { - store = new MergeRequestStore(mockData); - }); + beforeEach(() => { + store = new MergeRequestStore(mockData); + }); - it('should set hasSHAChanged when the diff SHA changes', () => { + describe('setData', () => { + it('should set isSHAMismatch when the diff SHA changes', () => { store.setData({ ...mockData, diff_head_sha: 'a-different-string' }); - expect(store.hasSHAChanged).toBe(true); + expect(store.isSHAMismatch).toBe(true); }); - it('should not set hasSHAChanged when other data changes', () => { + it('should not set isSHAMismatch when other data changes', () => { store.setData({ ...mockData, work_in_progress: !mockData.work_in_progress }); - expect(store.hasSHAChanged).toBe(false); + expect(store.isSHAMismatch).toBe(false); + }); + + it('should update cached sha after rebasing', () => { + store.setData({ ...mockData, diff_head_sha: 'abc123' }, true); + + expect(store.isSHAMismatch).toBe(false); + expect(store.sha).toBe('abc123'); }); describe('isPipelinePassing', () => { diff --git a/spec/lib/constraints/feature_constrainer_spec.rb b/spec/lib/constraints/feature_constrainer_spec.rb new file mode 100644 index 00000000000..42efc164f81 --- /dev/null +++ b/spec/lib/constraints/feature_constrainer_spec.rb @@ -0,0 +1,11 @@ +require 'spec_helper' + +describe Constraints::FeatureConstrainer do + describe '#matches' do + it 'calls Feature.enabled? with the correct arguments' do + expect(Feature).to receive(:enabled?).with(:feature_name, "an object", default_enabled: true) + + described_class.new(:feature_name, "an object", default_enabled: true).matches?(double('request')) + end + end +end diff --git a/spec/lib/gitlab/background_migration/migrate_build_stage_spec.rb b/spec/lib/gitlab/background_migration/migrate_build_stage_spec.rb index 5ce84c61042..7c7e58d6bb7 100644 --- a/spec/lib/gitlab/background_migration/migrate_build_stage_spec.rb +++ b/spec/lib/gitlab/background_migration/migrate_build_stage_spec.rb @@ -6,8 +6,18 @@ describe Gitlab::BackgroundMigration::MigrateBuildStage, :migration, schema: 201 let(:stages) { table(:ci_stages) } let(:jobs) { table(:ci_builds) } - STATUSES = { created: 0, pending: 1, running: 2, success: 3, - failed: 4, canceled: 5, skipped: 6, manual: 7 }.freeze + let(:statuses) do + { + created: 0, + pending: 1, + running: 2, + success: 3, + failed: 4, + canceled: 5, + skipped: 6, + manual: 7 + } + end before do projects.create!(id: 123, name: 'gitlab', path: 'gitlab-ce') @@ -36,9 +46,9 @@ describe Gitlab::BackgroundMigration::MigrateBuildStage, :migration, schema: 201 expect(stages.all.pluck(:name)).to match_array %w[test build deploy] expect(jobs.where(stage_id: nil)).to be_one expect(jobs.find_by(stage_id: nil).id).to eq 6 - expect(stages.all.pluck(:status)).to match_array [STATUSES[:success], - STATUSES[:failed], - STATUSES[:pending]] + expect(stages.all.pluck(:status)).to match_array [statuses[:success], + statuses[:failed], + statuses[:pending]] end it 'recovers from unique constraint violation only twice' do diff --git a/spec/lib/gitlab/background_migration/migrate_stage_status_spec.rb b/spec/lib/gitlab/background_migration/migrate_stage_status_spec.rb index 878158910be..89b56906ed0 100644 --- a/spec/lib/gitlab/background_migration/migrate_stage_status_spec.rb +++ b/spec/lib/gitlab/background_migration/migrate_stage_status_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe Gitlab::BackgroundMigration::MigrateStageStatus, :migration, schema: 20170711145320 do @@ -6,8 +8,18 @@ describe Gitlab::BackgroundMigration::MigrateStageStatus, :migration, schema: 20 let(:stages) { table(:ci_stages) } let(:jobs) { table(:ci_builds) } - STATUSES = { created: 0, pending: 1, running: 2, success: 3, - failed: 4, canceled: 5, skipped: 6, manual: 7 }.freeze + let(:statuses) do + { + created: 0, + pending: 1, + running: 2, + success: 3, + failed: 4, + canceled: 5, + skipped: 6, + manual: 7 + } + end before do projects.create!(id: 1, name: 'gitlab1', path: 'gitlab1') @@ -26,8 +38,8 @@ describe Gitlab::BackgroundMigration::MigrateStageStatus, :migration, schema: 20 it 'sets a correct stage status' do described_class.new.perform(1, 2) - expect(stages.first.status).to eq STATUSES[:running] - expect(stages.second.status).to eq STATUSES[:failed] + expect(stages.first.status).to eq statuses[:running] + expect(stages.second.status).to eq statuses[:failed] end end @@ -35,8 +47,8 @@ describe Gitlab::BackgroundMigration::MigrateStageStatus, :migration, schema: 20 it 'sets a skipped stage status' do described_class.new.perform(1, 2) - expect(stages.first.status).to eq STATUSES[:skipped] - expect(stages.second.status).to eq STATUSES[:skipped] + expect(stages.first.status).to eq statuses[:skipped] + expect(stages.second.status).to eq statuses[:skipped] end end @@ -50,8 +62,8 @@ describe Gitlab::BackgroundMigration::MigrateStageStatus, :migration, schema: 20 it 'sets a correct stage status' do described_class.new.perform(1, 2) - expect(stages.first.status).to eq STATUSES[:canceled] - expect(stages.second.status).to eq STATUSES[:success] + expect(stages.first.status).to eq statuses[:canceled] + expect(stages.second.status).to eq statuses[:success] end end @@ -65,8 +77,8 @@ describe Gitlab::BackgroundMigration::MigrateStageStatus, :migration, schema: 20 it 'sets a correct stage status' do described_class.new.perform(1, 2) - expect(stages.first.status).to eq STATUSES[:manual] - expect(stages.second.status).to eq STATUSES[:success] + expect(stages.first.status).to eq statuses[:manual] + expect(stages.second.status).to eq statuses[:success] end end diff --git a/spec/lib/gitlab/database/migration_helpers_spec.rb b/spec/lib/gitlab/database/migration_helpers_spec.rb index 23f27939dd2..4e83b27e4a5 100644 --- a/spec/lib/gitlab/database/migration_helpers_spec.rb +++ b/spec/lib/gitlab/database/migration_helpers_spec.rb @@ -1338,12 +1338,7 @@ describe Gitlab::Database::MigrationHelpers do end describe '#index_exists_by_name?' do - # TODO: remove rails5-only after removing rails4 tests - # rails 4 can not handle multiple indexes on the same column set if - # index was added by 't.index' - t.index is used by default in schema.rb in - # rails 5. Let's run this test only in rails 5 env: - # see https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/21492#note_113602758 - it 'returns true if an index exists', :rails5 do + it 'returns true if an index exists' do expect(model.index_exists_by_name?(:projects, 'index_projects_on_path')) .to be_truthy end diff --git a/spec/lib/gitlab/database_spec.rb b/spec/lib/gitlab/database_spec.rb index fc295b2deff..0826bc3eeed 100644 --- a/spec/lib/gitlab/database_spec.rb +++ b/spec/lib/gitlab/database_spec.rb @@ -462,8 +462,7 @@ describe Gitlab::Database do expect(described_class.db_read_only?).to be_truthy end - # TODO: remove rails5-only tag after removing rails4 tests - it 'detects a read only database', :rails5 do + it 'detects a read only database' do allow(ActiveRecord::Base.connection).to receive(:execute).with('SELECT pg_is_in_recovery()').and_return([{ "pg_is_in_recovery" => true }]) expect(described_class.db_read_only?).to be_truthy @@ -475,8 +474,7 @@ describe Gitlab::Database do expect(described_class.db_read_only?).to be_falsey end - # TODO: remove rails5-only tag after removing rails4 tests - it 'detects a read write database', :rails5 do + it 'detects a read write database' do allow(ActiveRecord::Base.connection).to receive(:execute).with('SELECT pg_is_in_recovery()').and_return([{ "pg_is_in_recovery" => false }]) expect(described_class.db_read_only?).to be_falsey diff --git a/spec/lib/gitlab/diff/file_spec.rb b/spec/lib/gitlab/diff/file_spec.rb index 3417896e259..b15d22c634a 100644 --- a/spec/lib/gitlab/diff/file_spec.rb +++ b/spec/lib/gitlab/diff/file_spec.rb @@ -583,6 +583,12 @@ describe Gitlab::Diff::File do end end + describe '#empty?' do + it 'returns true' do + expect(diff_file.empty?).to be_truthy + end + end + describe '#different_type?' do it 'returns false' do expect(diff_file).not_to be_different_type @@ -662,4 +668,87 @@ describe Gitlab::Diff::File do end end end + + describe '#empty?' do + let(:project) do + create(:project, :custom_repo, files: {}) + end + let(:branch_name) { 'master' } + + def create_file(file_name, content) + Files::CreateService.new( + project, + project.owner, + commit_message: 'Update', + start_branch: branch_name, + branch_name: branch_name, + file_path: file_name, + file_content: content + ).execute + + project.commit(branch_name).diffs.diff_files.first + end + + def update_file(file_name, content) + Files::UpdateService.new( + project, + project.owner, + commit_message: 'Update', + start_branch: branch_name, + branch_name: branch_name, + file_path: file_name, + file_content: content + ).execute + + project.commit(branch_name).diffs.diff_files.first + end + + def delete_file(file_name) + Files::DeleteService.new( + project, + project.owner, + commit_message: 'Update', + start_branch: branch_name, + branch_name: branch_name, + file_path: file_name + ).execute + + project.commit(branch_name).diffs.diff_files.first + end + + context 'when empty file is created' do + it 'returns true' do + diff_file = create_file('empty.md', '') + + expect(diff_file.empty?).to be_truthy + end + end + + context 'when empty file is deleted' do + it 'returns true' do + create_file('empty.md', '') + diff_file = delete_file('empty.md') + + expect(diff_file.empty?).to be_truthy + end + end + + context 'when file with content is truncated' do + it 'returns false' do + create_file('with-content.md', 'file content') + diff_file = update_file('with-content.md', '') + + expect(diff_file.empty?).to be_falsey + end + end + + context 'when empty file has content added' do + it 'returns false' do + create_file('empty.md', '') + diff_file = update_file('empty.md', 'new content') + + expect(diff_file.empty?).to be_falsey + end + end + end end diff --git a/spec/lib/gitlab/github_import/importer/pull_request_importer_spec.rb b/spec/lib/gitlab/github_import/importer/pull_request_importer_spec.rb index efca8564894..25684ea9e2c 100644 --- a/spec/lib/gitlab/github_import/importer/pull_request_importer_spec.rb +++ b/spec/lib/gitlab/github_import/importer/pull_request_importer_spec.rb @@ -240,12 +240,7 @@ describe Gitlab::GithubImport::Importer::PullRequestImporter, :clean_gitlab_redi .and_return(user.id) end - # TODO: remove rails5-only after removing rails4 tests - # rails 4 can not handle multiple indexes on the same column set if - # index was added by 't.index' - t.index is used by default in schema.rb in - # rails 5. Let's run this test only in rails 5 env: - # see https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/21492#note_113602758 - it 'returns the existing merge request', :rails5 do + it 'returns the existing merge request' do mr1, exists1 = importer.create_merge_request mr2, exists2 = importer.create_merge_request diff --git a/spec/lib/gitlab/import_export/all_models.yml b/spec/lib/gitlab/import_export/all_models.yml index 72abd8973cb..c8c74883640 100644 --- a/spec/lib/gitlab/import_export/all_models.yml +++ b/spec/lib/gitlab/import_export/all_models.yml @@ -64,6 +64,7 @@ snippets: - award_emoji - user_agent_detail releases: +- author - project project_members: - created_by diff --git a/spec/lib/gitlab/import_export/safe_model_attributes.yml b/spec/lib/gitlab/import_export/safe_model_attributes.yml index d3bfde181bc..24b1f2d995b 100644 --- a/spec/lib/gitlab/import_export/safe_model_attributes.yml +++ b/spec/lib/gitlab/import_export/safe_model_attributes.yml @@ -112,8 +112,11 @@ ProjectSnippet: - visibility_level Release: - id +- name - tag +- sha - description +- author_id - project_id - created_at - updated_at diff --git a/spec/migrations/backfill_releases_name_with_tag_name_spec.rb b/spec/migrations/backfill_releases_name_with_tag_name_spec.rb new file mode 100644 index 00000000000..6f436de84b7 --- /dev/null +++ b/spec/migrations/backfill_releases_name_with_tag_name_spec.rb @@ -0,0 +1,23 @@ +# frozen_string_literal: true + +require 'spec_helper' +require Rails.root.join('db', 'migrate', '20181212104941_backfill_releases_name_with_tag_name.rb') + +describe BackfillReleasesNameWithTagName, :migration do + let(:releases) { table(:releases) } + let(:namespaces) { table(:namespaces) } + let(:projects) { table(:projects) } + + let(:namespace) { namespaces.create(name: 'foo', path: 'foo') } + let(:project) { projects.create!(namespace_id: namespace.id) } + let(:release) { releases.create!(project_id: project.id, tag: 'v1.0.0') } + + it 'defaults name to tag value' do + expect(release.tag).to be_present + + migrate! + + release.reload + expect(release.name).to eq(release.tag) + end +end diff --git a/spec/models/clusters/applications/knative_spec.rb b/spec/models/clusters/applications/knative_spec.rb index a1579b90436..809880f5969 100644 --- a/spec/models/clusters/applications/knative_spec.rb +++ b/spec/models/clusters/applications/knative_spec.rb @@ -33,10 +33,10 @@ describe Clusters::Applications::Knative do end context 'application install previously errored with older version' do - let(:application) { create(:clusters_applications_knative, :scheduled, version: '0.1.3') } + let(:application) { create(:clusters_applications_knative, :scheduled, version: '0.2.2') } it 'updates the application version' do - expect(application.reload.version).to eq('0.1.3') + expect(application.reload.version).to eq('0.2.2') end end end @@ -105,7 +105,7 @@ describe Clusters::Applications::Knative do it 'should be initialized with knative arguments' do expect(subject.name).to eq('knative') expect(subject.chart).to eq('knative/knative') - expect(subject.version).to eq('0.1.3') + expect(subject.version).to eq('0.2.2') expect(subject.files).to eq(knative.files) end end diff --git a/spec/models/merge_request_diff_spec.rb b/spec/models/merge_request_diff_spec.rb index cbe60b3a4a5..33e984dc399 100644 --- a/spec/models/merge_request_diff_spec.rb +++ b/spec/models/merge_request_diff_spec.rb @@ -105,7 +105,7 @@ describe MergeRequestDiff do context 'when the raw diffs are empty' do before do - MergeRequestDiffFile.delete_all(merge_request_diff_id: diff_with_commits.id) + MergeRequestDiffFile.where(merge_request_diff_id: diff_with_commits.id).delete_all end it 'returns an empty DiffCollection' do diff --git a/spec/models/release_spec.rb b/spec/models/release_spec.rb index 3f86347c3ae..51725eeacac 100644 --- a/spec/models/release_spec.rb +++ b/spec/models/release_spec.rb @@ -7,6 +7,7 @@ RSpec.describe Release do describe 'associations' do it { is_expected.to belong_to(:project) } + it { is_expected.to belong_to(:author).class_name('User') } end describe 'validation' do diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index ff075e65c76..8b3021113bc 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -45,6 +45,7 @@ describe User do it { is_expected.to have_many(:uploads) } it { is_expected.to have_many(:reported_abuse_reports).dependent(:destroy).class_name('AbuseReport') } it { is_expected.to have_many(:custom_attributes).class_name('UserCustomAttribute') } + it { is_expected.to have_many(:releases).dependent(:nullify) } describe "#abuse_report" do let(:current_user) { create(:user) } diff --git a/spec/presenters/clusters/cluster_presenter_spec.rb b/spec/presenters/clusters/cluster_presenter_spec.rb index 72c5eac3ede..63c2ff26a45 100644 --- a/spec/presenters/clusters/cluster_presenter_spec.rb +++ b/spec/presenters/clusters/cluster_presenter_spec.rb @@ -74,6 +74,20 @@ describe Clusters::ClusterPresenter do end end + describe '#cluster_type_description' do + subject { described_class.new(cluster).cluster_type_description } + + context 'project_type cluster' do + it { is_expected.to eq('Project cluster') } + end + + context 'group_type cluster' do + let(:cluster) { create(:cluster, :provided_by_gcp, :group) } + + it { is_expected.to eq('Group cluster') } + end + end + describe '#show_path' do subject { described_class.new(cluster).show_path } diff --git a/spec/serializers/issue_board_entity_spec.rb b/spec/serializers/issue_board_entity_spec.rb index 06d9d3657e6..f6fa2a794f6 100644 --- a/spec/serializers/issue_board_entity_spec.rb +++ b/spec/serializers/issue_board_entity_spec.rb @@ -3,21 +3,40 @@ require 'spec_helper' describe IssueBoardEntity do - let(:project) { create(:project) } - let(:resource) { create(:issue, project: project) } - let(:user) { create(:user) } - - let(:request) { double('request', current_user: user) } + let(:project) { create(:project) } + let(:resource) { create(:issue, project: project) } + let(:user) { create(:user) } + let(:milestone) { create(:milestone, project: project) } + let(:label) { create(:label, project: project, title: 'Test Label') } + let(:request) { double('request', current_user: user) } subject { described_class.new(resource, request: request).as_json } it 'has basic attributes' do expect(subject).to include(:id, :iid, :title, :confidential, :due_date, :project_id, :relative_position, - :project, :labels) + :labels, :assignees, project: hash_including(:id, :path)) end it 'has path and endpoints' do expect(subject).to include(:reference_path, :real_path, :issue_sidebar_endpoint, :toggle_subscription_endpoint, :assignable_labels_endpoint) end + + it 'has milestone attributes' do + resource.milestone = milestone + + expect(subject).to include(milestone: hash_including(:id, :title)) + end + + it 'has assignee attributes' do + resource.assignees = [user] + + expect(subject).to include(assignees: array_including(hash_including(:id, :name, :username, :avatar_url))) + end + + it 'has label attributes' do + resource.labels = [label] + + expect(subject).to include(labels: array_including(hash_including(:id, :title, :color, :description, :text_color, :priority))) + end end diff --git a/spec/services/create_release_service_spec.rb b/spec/services/create_release_service_spec.rb index ac0a0458f56..1a2dd0b39ee 100644 --- a/spec/services/create_release_service_spec.rb +++ b/spec/services/create_release_service_spec.rb @@ -6,6 +6,8 @@ describe CreateReleaseService do let(:tag_name) { project.repository.tag_names.first } let(:description) { 'Awesome release!' } let(:service) { described_class.new(project, user) } + let(:tag) { project.repository.find_tag(tag_name) } + let(:sha) { tag.dereferenced_target.sha } it 'creates a new release' do result = service.execute(tag_name, description) @@ -13,6 +15,9 @@ describe CreateReleaseService do release = project.releases.find_by(tag: tag_name) expect(release).not_to be_nil expect(release.description).to eq(description) + expect(release.name).to eq(tag_name) + expect(release.sha).to eq(sha) + expect(release.author).to eq(user) end it 'raises an error if the tag does not exist' do diff --git a/spec/services/projects/lfs_pointers/lfs_download_service_spec.rb b/spec/services/projects/lfs_pointers/lfs_download_service_spec.rb index 6af5bfc7689..d7d7f1874eb 100644 --- a/spec/services/projects/lfs_pointers/lfs_download_service_spec.rb +++ b/spec/services/projects/lfs_pointers/lfs_download_service_spec.rb @@ -54,6 +54,18 @@ describe Projects::LfsPointers::LfsDownloadService do end end + context 'when a bad URL is used' do + where(download_link: ['/etc/passwd', 'ftp://example.com', 'http://127.0.0.2']) + + with_them do + it 'does not download the file' do + expect(subject).not_to receive(:download_and_save_file) + + expect { subject.execute(oid, download_link) }.not_to change { LfsObject.count } + end + end + end + context 'when an lfs object with the same oid already exists' do before do create(:lfs_object, oid: 'oid') diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 3fedb9ed48c..fb3421b61d3 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -115,7 +115,7 @@ RSpec.configure do |config| TestEnv.clean_test_path end - config.before(:example) do + config.before do # Enable all features by default for testing allow(Feature).to receive(:enabled?) { true } @@ -136,11 +136,11 @@ RSpec.configure do |config| RequestStore.clear! end - config.after(:example) do + config.after do Fog.unmock! if Fog.mock? end - config.after(:example) do + config.after do Gitlab::CurrentSettings.clear_in_memory_application_settings! end @@ -235,10 +235,6 @@ RSpec.configure do |config| example.run if Gitlab::Database.mysql? end - config.around(:each, :rails5) do |example| - example.run if Gitlab.rails5? - end - # This makes sure the `ApplicationController#can?` method is stubbed with the # original implementation for all view specs. config.before(:each, type: :view) do diff --git a/spec/support/carrierwave.rb b/spec/support/carrierwave.rb index b4b016e408f..b376822d530 100644 --- a/spec/support/carrierwave.rb +++ b/spec/support/carrierwave.rb @@ -1,7 +1,7 @@ CarrierWave.root = File.expand_path('tmp/tests/public', Rails.root) RSpec.configure do |config| - config.after(:each) do + config.after do FileUtils.rm_rf(CarrierWave.root) end end diff --git a/spec/support/db_cleaner.rb b/spec/support/db_cleaner.rb index 5edc5de2a09..34b9efaaecd 100644 --- a/spec/support/db_cleaner.rb +++ b/spec/support/db_cleaner.rb @@ -23,7 +23,7 @@ RSpec.configure do |config| DatabaseCleaner.clean_with(:deletion, cache_tables: false) end - config.before(:each) do + config.before do DatabaseCleaner.strategy = :transaction end @@ -39,11 +39,11 @@ RSpec.configure do |config| DatabaseCleaner.strategy = :deletion, { cache_tables: false } end - config.before(:each) do + config.before do DatabaseCleaner.start end - config.append_after(:each) do + config.append_after do DatabaseCleaner.clean end end diff --git a/spec/support/features/discussion_comments_shared_example.rb b/spec/support/features/discussion_comments_shared_example.rb index 922f3df144d..42a086d58d2 100644 --- a/spec/support/features/discussion_comments_shared_example.rb +++ b/spec/support/features/discussion_comments_shared_example.rb @@ -178,6 +178,16 @@ shared_examples 'discussion comments' do |resource_name| let(:note_id) { find("#{comments_selector} .note:first-child", match: :first)['data-note-id'] } let(:reply_id) { find("#{comments_selector} .note:last-child", match: :first)['data-note-id'] } + it 'can be replied to after resolving' do + click_button "Resolve discussion" + wait_for_requests + + refresh + wait_for_requests + + submit_reply('to reply or not reply') + end + it 'shows resolved discussion when toggled' do submit_reply('a') diff --git a/spec/support/setup_builds_storage.rb b/spec/support/setup_builds_storage.rb index 2e7c88bfc09..1d2a4856724 100644 --- a/spec/support/setup_builds_storage.rb +++ b/spec/support/setup_builds_storage.rb @@ -11,7 +11,7 @@ RSpec.configure do |config| FileUtils.mkdir_p(builds_path) end - config.before(:each) do + config.before do FileUtils.rm_rf(builds_path) FileUtils.mkdir_p(builds_path) end diff --git a/spec/support/shared_examples/serializers/diff_file_entity_examples.rb b/spec/support/shared_examples/serializers/diff_file_entity_examples.rb index b8065886c42..1770308f789 100644 --- a/spec/support/shared_examples/serializers/diff_file_entity_examples.rb +++ b/spec/support/shared_examples/serializers/diff_file_entity_examples.rb @@ -32,7 +32,7 @@ shared_examples 'diff file entity' do it 'exposes correct attributes' do expect(subject).to include(:too_large, :added_lines, :removed_lines, :context_lines_path, :highlighted_diff_lines, - :parallel_diff_lines) + :parallel_diff_lines, :empty) end it 'includes viewer' do |