Import upstream version 3.0.0
Debian Janitor
2 years ago
0 | name: CI | |
1 | on: [push, pull_request] | |
2 | jobs: | |
3 | tests: | |
4 | runs-on: ubuntu-latest | |
5 | strategy: | |
6 | fail-fast: false | |
7 | matrix: | |
8 | ruby: [ '2.7', '3.0', 'head' ] | |
9 | rails: [ '6.0', '6.1', 'edge' ] | |
10 | include: | |
11 | - ruby: '2.6' | |
12 | rails: '5.2' | |
13 | - ruby: '2.6' | |
14 | rails: '6.0' | |
15 | - ruby: '2.6' | |
16 | rails: '6.1' | |
17 | ||
18 | env: | |
19 | RAILS_VERSION: ${{ matrix.rails }} | |
20 | ||
21 | steps: | |
22 | - uses: actions/checkout@v2 | |
23 | ||
24 | - name: Set up Ruby | |
25 | uses: ruby/setup-ruby@v1 | |
26 | with: | |
27 | ruby-version: ${{ matrix.ruby }} | |
28 | bundler-cache: true | |
29 | ||
30 | - name: Run unit tests | |
31 | run: bundle exec rake test:unit | |
32 | timeout-minutes: 3 | |
33 | ||
34 | - name: Run unit tests | |
35 | run: bundle exec rake test:unit | |
36 | timeout-minutes: 3 | |
37 | ||
38 | - name: Run acceptance tests | |
39 | run: bundle exec rake test:acceptance | |
40 | timeout-minutes: 10 | |
41 | if: ${{ matrix.rails != 'edge' && matrix.ruby != 'head' }} # Acceptance tests use `gem install rails && rails new` |
0 | language: ruby | |
1 | cache: bundler | |
2 | rvm: | |
3 | - 2.4.6 | |
4 | - 2.5.5 | |
5 | - 2.6.3 | |
6 | - ruby-head | |
7 | env: | |
8 | - RAILS_VERSION="~> 4.2.0" | |
9 | - RAILS_VERSION="~> 5.0.0" | |
10 | - RAILS_VERSION="~> 5.1.0" | |
11 | - RAILS_VERSION="~> 5.2.0" | |
12 | - RAILS_VERSION="~> 6.0.0.rc1" | |
13 | matrix: | |
14 | exclude: | |
15 | - rvm: 2.4.6 | |
16 | env: RAILS_VERSION="~> 6.0.0.rc1" | |
17 | - rvm: 2.6.3 | |
18 | env: RAILS_VERSION="~> 4.2.0" | |
19 | allow_failures: | |
20 | - rvm: ruby-head | |
21 | fast_finish: true | |
22 | before_install: | |
23 | - gem update --system 3.0.3 | |
24 | - gem uninstall bundler && gem install bundler -v 1.17.3 | |
25 | before_script: | |
26 | - travis_retry gem install rails --version "$RAILS_VERSION" |
0 | 0 | ## Next Release |
1 | ||
2 | ## 3.0.0 | |
3 | ||
4 | * Require applications to have reloading enabled in the managed environments. | |
5 | * Require Ruby 2.5. | |
6 | * Require Rails 5.2. | |
1 | 7 | |
2 | 8 | ## 2.1.1 |
3 | 9 |
2 | 2 | # Specify your gem's dependencies in spring.gemspec |
3 | 3 | gemspec |
4 | 4 | |
5 | if ENV["RAILS_VERSION"] | |
5 | if ENV["RAILS_VERSION"] == "edge" | |
6 | gem "activesupport", github: "rails/rails", branch: "main" | |
7 | elsif ENV["RAILS_VERSION"] | |
6 | 8 | gem "activesupport", ENV["RAILS_VERSION"] |
7 | 9 | end |
15 | 15 | |
16 | 16 | ## Compatibility |
17 | 17 | |
18 | * Ruby versions: MRI 2.4, MRI 2.5, MRI 2.6 | |
19 | * Rails versions: 4.2, 5.0, 5.1, 5.2, 6.0 (Spring is installed by default when you do | |
18 | * Ruby versions: MRI 2.5, MRI 2.6 | |
19 | * Rails versions: 5.2, 6.0 (Spring is installed by default when you do | |
20 | 20 | `rails new` to generate your application) |
21 | 21 | |
22 | 22 | Spring makes extensive use of `Process.fork`, so won't be able to |
63 | 63 | automatically add `./bin` to your `PATH` when you `cd` into your application. |
64 | 64 | Simply create an `.envrc` file with the command `PATH_add bin` in your |
65 | 65 | Rails directory. |
66 | ||
67 | ### Enable reloading | |
68 | ||
69 | Spring reloads application code, and therefore needs the application to have | |
70 | reloading enabled. | |
71 | ||
72 | Please, make sure `config.cache_classes` is `false` in the environments that | |
73 | Spring manages. That setting is typically configured in | |
74 | `config/environments/*.rb`. In particular, make sure it is `false` for the | |
75 | `test` environment. | |
66 | 76 | |
67 | 77 | ### Usage |
68 | 78 | |
256 | 266 | |
257 | 267 | ## Class reloading |
258 | 268 | |
259 | Spring uses Rails' class reloading mechanism | |
260 | (`ActiveSupport::Dependencies`) to keep your code up to date between | |
261 | test runs. This is the same mechanism which allows you to see changes | |
262 | during development when you refresh the page. However, you may never | |
263 | have used this mechanism with your `test` environment before, and this | |
264 | can cause problems. | |
269 | Spring uses Rails' class reloading mechanism to keep your code up to date | |
270 | between test runs. This is the same mechanism which allows you to see changes | |
271 | during development when you refresh the page. However, you may never have used | |
272 | this mechanism with your `test` environment before, and this can cause problems. | |
265 | 273 | |
266 | 274 | It's important to realise that code reloading means that the constants |
267 | 275 | in your application are *different objects* after files have changed: |
90 | 90 | |
91 | 91 | require Spring.application_root_path.join("config", "application") |
92 | 92 | |
93 | unless Rails.respond_to?(:gem_version) && Rails.gem_version >= Gem::Version.new('4.2.0') | |
94 | raise "Spring only supports Rails >= 4.2.0" | |
95 | end | |
96 | ||
97 | # config/environments/test.rb will have config.cache_classes = true. However | |
98 | # we want it to be false so that we can reload files. This is a hack to | |
99 | # override the effect of config.cache_classes = true. We can then actually | |
100 | # set config.cache_classes = false after loading the environment. | |
101 | Rails::Application.initializer :initialize_dependency_mechanism, group: :all do | |
102 | ActiveSupport::Dependencies.mechanism = :load | |
93 | unless Rails.respond_to?(:gem_version) && Rails.gem_version >= Gem::Version.new('5.2.0') | |
94 | raise "Spring only supports Rails >= 5.2.0" | |
95 | end | |
96 | ||
97 | Rails::Application.initializer :ensure_reloading_is_enabled, group: :all do | |
98 | if Rails.application.config.cache_classes | |
99 | raise <<-MSG.strip_heredoc | |
100 | Spring reloads, and therefore needs the application to have reloading enabled. | |
101 | Please, set config.cache_classes to false in config/environments/#{Rails.env}.rb. | |
102 | MSG | |
103 | end | |
103 | 104 | end |
104 | 105 | |
105 | 106 | require Spring.application_root_path.join("config", "environment") |
106 | ||
107 | @original_cache_classes = Rails.application.config.cache_classes | |
108 | Rails.application.config.cache_classes = false | |
109 | 107 | |
110 | 108 | disconnect_database |
111 | 109 | |
162 | 160 | setup command |
163 | 161 | |
164 | 162 | if Rails.application.reloaders.any?(&:updated?) |
165 | # Rails 5.1 forward-compat. AD::R is deprecated to AS::R in Rails 5. | |
166 | if defined? ActiveSupport::Reloader | |
167 | Rails.application.reloader.reload! | |
168 | else | |
169 | ActionDispatch::Reloader.cleanup! | |
170 | ActionDispatch::Reloader.prepare! | |
171 | end | |
172 | end | |
173 | ||
174 | # Ensure we boot the process in the directory the command was called from, | |
175 | # not from the directory Spring started in | |
176 | original_dir = Dir.pwd | |
177 | Dir.chdir(env['PWD'] || original_dir) | |
163 | Rails.application.reloader.reload! | |
164 | end | |
178 | 165 | |
179 | 166 | pid = fork { |
180 | 167 | Process.setsid |
202 | 189 | # Load in the current env vars, except those which *were* changed when Spring started |
203 | 190 | env.each { |k, v| ENV[k] ||= v } |
204 | 191 | |
205 | # requiring is faster, so if config.cache_classes was true in | |
206 | # the environment's config file, then we can respect that from | |
207 | # here on as we no longer need constant reloading. | |
208 | if @original_cache_classes | |
209 | ActiveSupport::Dependencies.mechanism = :require | |
210 | Rails.application.config.cache_classes = true | |
211 | end | |
212 | ||
213 | 192 | connect_database |
214 | 193 | srand |
215 | 194 | |
241 | 220 | # (i.e. to prevent `spring rake -T | grep db` from hanging forever), |
242 | 221 | # even when exception is raised before forking (i.e. preloading). |
243 | 222 | reset_streams |
244 | Dir.chdir(original_dir) | |
245 | 223 | end |
246 | 224 | |
247 | 225 | def terminate |
0 | 0 | require "pathname" |
1 | require "fileutils" | |
2 | 1 | require "digest/md5" |
3 | require "tmpdir" | |
4 | 2 | |
5 | 3 | require "spring/version" |
6 | 4 | require "spring/sid" |
32 | 30 | end |
33 | 31 | |
34 | 32 | def tmp_path |
33 | require "tmpdir" | |
35 | 34 | path = Pathname.new( |
36 | 35 | ENV["SPRING_TMP_PATH"] || |
37 | 36 | File.join(ENV['XDG_RUNTIME_DIR'] || Dir.tmpdir, "spring-#{Process.uid}") |
38 | 37 | ) |
38 | require "fileutils" | |
39 | 39 | FileUtils.mkdir_p(path) unless path.exist? |
40 | 40 | path |
41 | 41 | end |
12 | 12 | gem.files = Dir["LICENSE.txt", "README.md", "lib/**/*", "bin/*"] |
13 | 13 | gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) } |
14 | 14 | |
15 | gem.required_ruby_version = ">= 2.4.0" | |
15 | gem.required_ruby_version = ">= 2.5.0" | |
16 | 16 | |
17 | 17 | gem.add_development_dependency 'rake' |
18 | 18 | gem.add_development_dependency 'bump' |
11 | 11 | DEFAULT_SPEEDUP = 0.8 |
12 | 12 | |
13 | 13 | def rails_version |
14 | ENV['RAILS_VERSION'] || '~> 5.0.0' | |
14 | if ENV['RAILS_VERSION'] == "edge" | |
15 | "7.0.0.alpha" | |
16 | else | |
17 | '~> 6.0.0' | |
18 | end | |
15 | 19 | end |
16 | 20 | |
17 | 21 | # Extension point for spring-watchers-listen |
116 | 120 | refute_output_includes "bin/rails runner ''", stderr: 'Running via Spring preloader in process' |
117 | 121 | end |
118 | 122 | |
123 | test "raises if config.cache_classes is true" do | |
124 | config_path = app.path("config/environments/development.rb") | |
125 | config = File.read(config_path) | |
126 | config.sub!(/config.cache_classes\s*=\s*false/, "config.cache_classes = true") | |
127 | File.write(config_path, config) | |
128 | ||
129 | assert_failure "bin/rails runner 1", stderr: "Please, set config.cache_classes to false" | |
130 | end | |
131 | ||
119 | 132 | test "test changes are picked up" do |
120 | 133 | assert_speedup do |
121 | 134 | assert_success app.spring_test_command, stdout: "0 failures" |
502 | 515 | assert_failure %(bin/rails runner 'require "sqlite3"'), stderr: "sqlite3" |
503 | 516 | end |
504 | 517 | |
505 | if RUBY_VERSION >= "2.0.0" | |
506 | test "changing the gems.rb works" do | |
507 | FileUtils.mv(app.gemfile, app.gems_rb) | |
508 | FileUtils.mv(app.gemfile_lock, app.gems_locked) | |
509 | ||
510 | assert_success %(bin/rails runner 'require "sqlite3"') | |
511 | ||
512 | File.write(app.gems_rb, app.gems_rb.read.sub(%{gem 'sqlite3'}, %{# gem 'sqlite3'})) | |
513 | app.await_reload | |
514 | ||
515 | assert_failure %(bin/rails runner 'require "sqlite3"'), stderr: "sqlite3" | |
516 | end | |
518 | test "changing the gems.rb works" do | |
519 | FileUtils.mv(app.gemfile, app.gems_rb) | |
520 | FileUtils.mv(app.gemfile_lock, app.gems_locked) | |
521 | ||
522 | assert_success %(bin/rails runner 'require "sqlite3"') | |
523 | ||
524 | File.write(app.gems_rb, app.gems_rb.read.sub(%{gem 'sqlite3'}, %{# gem 'sqlite3'})) | |
525 | app.await_reload | |
526 | ||
527 | assert_failure %(bin/rails runner 'require "sqlite3"'), stderr: "sqlite3" | |
517 | 528 | end |
518 | 529 | |
519 | 530 | test "changing the Gemfile works when Spring calls into itself" do |
530 | 541 | assert_success [%(bin/rails runner 'load Rails.root.join("script.rb")'), timeout: 60] |
531 | 542 | end |
532 | 543 | |
533 | if RUBY_VERSION >= "2.0.0" | |
534 | test "changing the gems.rb works when spring calls into itself" do | |
535 | FileUtils.mv(app.gemfile, app.gems_rb) | |
536 | FileUtils.mv(app.gemfile_lock, app.gems_locked) | |
537 | ||
538 | File.write(app.path("script.rb"), <<-RUBY.strip_heredoc) | |
539 | gemfile = Rails.root.join("gems.rb") | |
540 | File.write(gemfile, "\#{gemfile.read}gem 'text'\\n") | |
541 | Bundler.with_clean_env do | |
542 | system(#{app.env.inspect}, "bundle install") | |
543 | end | |
544 | output = `\#{Rails.root.join('bin/rails')} runner 'require "text"; puts "done";'` | |
545 | exit output.include? "done\n" | |
546 | RUBY | |
547 | ||
548 | assert_success [%(bin/rails runner 'load Rails.root.join("script.rb")'), timeout: 60] | |
549 | end | |
544 | test "changing the gems.rb works when spring calls into itself" do | |
545 | FileUtils.mv(app.gemfile, app.gems_rb) | |
546 | FileUtils.mv(app.gemfile_lock, app.gems_locked) | |
547 | ||
548 | File.write(app.path("script.rb"), <<-RUBY.strip_heredoc) | |
549 | gemfile = Rails.root.join("gems.rb") | |
550 | File.write(gemfile, "\#{gemfile.read}gem 'text'\\n") | |
551 | Bundler.with_clean_env do | |
552 | system(#{app.env.inspect}, "bundle install") | |
553 | end | |
554 | output = `\#{Rails.root.join('bin/rails')} runner 'require "text"; puts "done";'` | |
555 | exit output.include? "done\n" | |
556 | RUBY | |
557 | ||
558 | assert_success [%(bin/rails runner 'load Rails.root.join("script.rb")'), timeout: 60] | |
550 | 559 | end |
551 | 560 | |
552 | 561 | test "changing the environment between runs" do |