capistrano / symfony

Capistrano tasks for deploying the Symfony standard edition
MIT License
354 stars 65 forks source link

Task for running (and enforcing passed) tests #117

Open webdevilopers opened 5 years ago

webdevilopers commented 5 years ago

Maybe it is an interesting feature to run unit tests either locally before deploying or on production after deploy.

I'm no ruby expert so this was my first approach:

namespace :deploy do
  #before :deploy, "deploy:run_tests"
  before :deploy, "tasks:run_tests"
end

namespace :tasks do

  task :run_tests do
      run_locally do
        execute :php, fetch(:vendor_path) + "/phpunit/phpunit/phpunit --configuration " + fetch(:app_path) + "/phpunit.xml " + fetch(:tests_path)
      end
  end

Based on this question:

But I'm not sure how to get a return value to inform cap to continue. Currently this solution will stop deployment even when tests pass.

(Backtrace restricted to imported tasks)
cap aborted!
SSHKit::Command::Failed: php exit status: 256
php stdout: PHPUnit 7.2.4 by Sebastian Bergmann and contributors.

Trace:

/var/lib/gems/2.5.0/gems/sshkit-1.16.1/lib/sshkit/command.rb:99:in `exit_status='
/var/lib/gems/2.5.0/gems/sshkit-1.16.1/lib/sshkit/backends/local.rb:64:in `block in execute_command'
/usr/lib/ruby/2.5.0/open3.rb:205:in `popen_run'
/usr/lib/ruby/2.5.0/open3.rb:95:in `popen3'
/var/lib/gems/2.5.0/gems/sshkit-1.16.1/lib/sshkit/backends/local.rb:46:in `execute_command'
/var/lib/gems/2.5.0/gems/sshkit-1.16.1/lib/sshkit/backends/abstract.rb:141:in `block in create_command_and_execute'
/var/lib/gems/2.5.0/gems/sshkit-1.16.1/lib/sshkit/backends/abstract.rb:141:in `tap'
/var/lib/gems/2.5.0/gems/sshkit-1.16.1/lib/sshkit/backends/abstract.rb:141:in `create_command_and_execute'
/var/lib/gems/2.5.0/gems/sshkit-1.16.1/lib/sshkit/backends/abstract.rb:74:in `execute'
app/config/deploy.rb:70:in `block (3 levels) in <top (required)>'
/var/lib/gems/2.5.0/gems/sshkit-1.16.1/lib/sshkit/backends/abstract.rb:29:in `instance_exec'
/var/lib/gems/2.5.0/gems/sshkit-1.16.1/lib/sshkit/backends/abstract.rb:29:in `run'
/var/lib/gems/2.5.0/gems/capistrano-3.11.0/lib/capistrano/dsl.rb:76:in `run_locally'
app/config/deploy.rb:68:in `block (2 levels) in <top (required)>'
/usr/lib/ruby/vendor_ruby/rake/task.rb:271:in `block in execute'
/usr/lib/ruby/vendor_ruby/rake/task.rb:271:in `each'
/usr/lib/ruby/vendor_ruby/rake/task.rb:271:in `execute'
/var/lib/gems/2.5.0/gems/airbrussh-1.3.0/lib/airbrussh/rake/context.rb:62:in `execute'
/usr/lib/ruby/vendor_ruby/rake/task.rb:213:in `block in invoke_with_call_chain'
/usr/lib/ruby/2.5.0/monitor.rb:226:in `mon_synchronize'
/usr/lib/ruby/vendor_ruby/rake/task.rb:193:in `invoke_with_call_chain'
/usr/lib/ruby/vendor_ruby/rake/task.rb:237:in `block in invoke_prerequisites'
/usr/lib/ruby/vendor_ruby/rake/task.rb:235:in `each'
/usr/lib/ruby/vendor_ruby/rake/task.rb:235:in `invoke_prerequisites'
/usr/lib/ruby/vendor_ruby/rake/task.rb:212:in `block in invoke_with_call_chain'
/usr/lib/ruby/2.5.0/monitor.rb:226:in `mon_synchronize'
/usr/lib/ruby/vendor_ruby/rake/task.rb:193:in `invoke_with_call_chain'
/usr/lib/ruby/vendor_ruby/rake/task.rb:182:in `invoke'
/usr/lib/ruby/vendor_ruby/rake/application.rb:160:in `invoke_task'
/usr/lib/ruby/vendor_ruby/rake/application.rb:116:in `block (2 levels) in top_level'
/usr/lib/ruby/vendor_ruby/rake/application.rb:116:in `each'
/usr/lib/ruby/vendor_ruby/rake/application.rb:116:in `block in top_level'
/usr/lib/ruby/vendor_ruby/rake/application.rb:125:in `run_with_threads'
/usr/lib/ruby/vendor_ruby/rake/application.rb:110:in `top_level'
/usr/lib/ruby/vendor_ruby/rake/application.rb:83:in `block in run'
/usr/lib/ruby/vendor_ruby/rake/application.rb:186:in `standard_exception_handling'
/usr/lib/ruby/vendor_ruby/rake/application.rb:80:in `run'
/var/lib/gems/2.5.0/gems/capistrano-3.11.0/lib/capistrano/application.rb:14:in `run'
/var/lib/gems/2.5.0/gems/capistrano-3.11.0/bin/cap:3:in `<top (required)>'
/usr/local/bin/cap:23:in `load'
/usr/local/bin/cap:23:in `<main>'
Tasks: TOP => deploy => tasks:run_tests
webdevilopers commented 5 years ago

Thanks to @radmen I was able to identify the problem. The tests were throwing deprecation notices that would let the process fail. The notices could be hidden by this configuration in phpunit.xml:

<php>
    <env name="SYMFONY_DEPRECATIONS_HELPER" value="weak" />
</php>

Solution provided here by @BigZ:

Symfony 2:

set :tests_path, fetch(:app_path) + "/../tests"
set :vendor_path, fetch(:app_path) + "/../vendor"

namespace :deploy do
  before :starting, "tasks:run_tests"
end

namespace :tasks do

  task :run_tests do
    run_locally do
      execute :php, fetch(:vendor_path) + "/phpunit/phpunit/phpunit --configuration " + fetch(:app_path) + "/phpunit.xml " + fetch(:tests_path)
    end
  end

end

If you are using the PHPUnit Bridge and Symfony >= 3:

set :tests_path, "tests"
set :vendor_path, "vendor"

namespace :deploy do
  before :starting, "tasks:run_tests"
end

namespace :tasks do
  task :run_tests do
    run_locally do
      execute :php, fetch(:vendor_path) + "/bin/simple-phpunit --configuration phpunit.xml " + fetch(:tests_path)
    end
  end
end

Anybody interested in adding this task to this repo?

BigZ commented 5 years ago

Hi @webdevilopers I think the tests should be run in a Continuous Integration, not in capistrano. just make test && make deploy if you really want to do it on your machine because this task is heavily related to the fact that you use phpunit and a specific configuration file. PS: if you want to force weak deprecation notice, you can set it per-command, like SYMFONY_DEPRECATIONS_HELPER=weak php vendor/bin/phpunit

webdevilopers commented 5 years ago

SYMFONY_DEPRECATIONS_HELPER=weak php vendor/bin/phpunit

Thanks for the hint @BigZ !