diff --git a/lib/capistrano/dsl/task_enhancements.rb b/lib/capistrano/dsl/task_enhancements.rb index 7b93c412..a3536adb 100644 --- a/lib/capistrano/dsl/task_enhancements.rb +++ b/lib/capistrano/dsl/task_enhancements.rb @@ -11,5 +11,26 @@ module Capistrano invoke(post_task) end end + + def remote_file(task) + target_roles = task.delete(:roles) { :all } + define_remote_file_task(task, target_roles) + end + + def define_remote_file_task(task, target_roles) + Rake::Task.define_task(task) do |t| + prerequisite_file = t.prerequisites.first + file = shared_path.join(t.name) + + on roles(target_roles) do + unless test "[ -f #{file} ]" + info "Uploading #{prerequisite_file} to #{file}" + upload! File.open(prerequisite_file), file + end + end + + end + end + end end diff --git a/spec/integration/remote_file_task_spec.rb b/spec/integration/remote_file_task_spec.rb new file mode 100644 index 00000000..25eb8016 --- /dev/null +++ b/spec/integration/remote_file_task_spec.rb @@ -0,0 +1,51 @@ +require 'integration_spec_helper' + +describe 'cap deploy:started', slow: true do + before do + install_test_app_with(config) + copy_task_to_test_app('spec/support/tasks/database.cap') + end + + let(:config) { + %{ + set :stage, :#{stage} + set :deploy_to, '#{deploy_to}' + set :repo_url, 'git://github.com/capistrano/capistrano.git' + set :branch, 'v3' + server 'localhost', roles: %w{web app}, user: '#{current_user}' + set :linked_files, %w{config/database.yml} + set :linked_dirs, %w{config} + } + } + + describe 'linked_files' do + + before do + cap 'deploy:check:linked_dirs' + end + + subject { cap 'deploy:check:linked_files' } + + context 'where the file does not exist' do + it 'creates the file with the remote_task prerequisite' do + expect(subject).to match 'Uploading' + expect(subject).not_to match 'config/database.yml does not exist' + expect(subject).to match 'successful' + end + end + + context 'where the file already exists' do + before do + FileUtils.touch(shared_path.join('config/database.yml')) + end + + it 'will not recreate the file if it already exists' do + expect(subject).not_to match 'Uploading' + expect(subject).not_to match 'config/database.yml does not exist' + expect(subject).to match 'successful' + end + end + + end +end + diff --git a/spec/support/tasks/database.cap b/spec/support/tasks/database.cap new file mode 100644 index 00000000..a5572642 --- /dev/null +++ b/spec/support/tasks/database.cap @@ -0,0 +1,11 @@ +namespace :deploy do + namespace :check do + task :linked_files => 'config/database.yml' + end +end + +remote_file 'config/database.yml' => '/tmp/database.yml', roles: :all + +file '/tmp/database.yml' do |t| + sh "touch #{t.name}" +end diff --git a/spec/support/test_app.rb b/spec/support/test_app.rb index 1cbdea90..b186c00b 100644 --- a/spec/support/test_app.rb +++ b/spec/support/test_app.rb @@ -83,7 +83,19 @@ module TestApp test_app_path.join('Gemfile') end + def capfile + test_app_path.join('Capfile') + end + def current_user `whoami`.chomp end + + def task_dir + test_app_path.join('lib/capistrano/tasks') + end + + def copy_task_to_test_app(source) + FileUtils.cp(source, task_dir) + end end