mirror of
https://github.com/capistrano/capistrano
synced 2023-03-27 23:21:18 -04:00
Add integration tests for deploy task
This commit adds the outlines of a testing framework for Cap tasks. Currently just the `cap install` and `cap deploy` tasks are covered. For now, these tests can only be run if it is `ssh localhost` will work for you and are currently excluded from the suite. It is my intention to eventually replace the `sshkit` backend with a test backend, but for now this is good enough to prevent simple regressions.
This commit is contained in:
parent
a8e00045df
commit
f5a585b3a4
10 changed files with 286 additions and 8 deletions
34
spec/integration/deploy_finalize_spec.rb
Normal file
34
spec/integration/deploy_finalize_spec.rb
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
require 'integration_spec_helper'
|
||||||
|
|
||||||
|
describe 'cap deploy:finished', slow: true do
|
||||||
|
before do
|
||||||
|
install_test_app_with(config)
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'deploy' do
|
||||||
|
let(:config) {
|
||||||
|
%{
|
||||||
|
set :stage, :#{stage}
|
||||||
|
set :deploy_to, '#{deploy_to}'
|
||||||
|
set :repo, '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{bin log public/system vendor/bundle}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
describe 'log_revision' do
|
||||||
|
before do
|
||||||
|
cap 'deploy:started'
|
||||||
|
cap 'deploy:update'
|
||||||
|
cap 'deploy:finalize'
|
||||||
|
cap 'deploy:finished'
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'writes the log file' do
|
||||||
|
expect(deploy_to.join('revisions.log')).to be_a_file
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
36
spec/integration/deploy_finished_spec.rb
Normal file
36
spec/integration/deploy_finished_spec.rb
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
require 'integration_spec_helper'
|
||||||
|
|
||||||
|
describe 'cap deploy:finished', slow: true do
|
||||||
|
before do
|
||||||
|
install_test_app_with(config)
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'deploy' do
|
||||||
|
let(:config) {
|
||||||
|
%{
|
||||||
|
set :stage, :#{stage}
|
||||||
|
set :deploy_to, '#{deploy_to}'
|
||||||
|
set :repo, '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{bin log public/system vendor/bundle}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
describe 'symlink' do
|
||||||
|
before do
|
||||||
|
cap 'deploy:started'
|
||||||
|
cap 'deploy:update'
|
||||||
|
cap 'deploy:finalize'
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'release' do
|
||||||
|
it 'symlinks the release to `current`' do
|
||||||
|
expect(File.symlink?(current_path)).to be_true
|
||||||
|
expect(File.readlink(current_path)).to match /\/tmp\/test_app\/deploy_to\/releases\/\d{14}/
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
74
spec/integration/deploy_started_spec.rb
Normal file
74
spec/integration/deploy_started_spec.rb
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
require 'integration_spec_helper'
|
||||||
|
|
||||||
|
describe 'cap deploy:started', slow: true do
|
||||||
|
before do
|
||||||
|
install_test_app_with(config)
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'deploy:check' do
|
||||||
|
let(:config) {
|
||||||
|
%{
|
||||||
|
set :stage, :#{stage}
|
||||||
|
set :deploy_to, '#{deploy_to}'
|
||||||
|
set :repo, '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{bin log public/system vendor/bundle}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
describe 'directories' do
|
||||||
|
before do
|
||||||
|
cap 'deploy:check:directories'
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'ensures the directory structure' do
|
||||||
|
expect(shared_path).to be_a_directory
|
||||||
|
expect(releases_path).to be_a_directory
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'linked_dirs' do
|
||||||
|
before do
|
||||||
|
cap 'deploy:check:linked_dirs'
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'ensure directories to be linked in `shared`' do
|
||||||
|
[
|
||||||
|
shared_path.join('bin'),
|
||||||
|
shared_path.join('log'),
|
||||||
|
shared_path.join('public/system'),
|
||||||
|
shared_path.join('vendor/bundle'),
|
||||||
|
].each do |dir|
|
||||||
|
expect(dir).to be_a_directory
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'linked_files' do
|
||||||
|
|
||||||
|
subject { cap 'deploy:check:linked_files' }
|
||||||
|
|
||||||
|
context 'file does not exist' do
|
||||||
|
it 'fails' do
|
||||||
|
expect(subject).to match 'config/database.yml does not exist'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'file exists' do
|
||||||
|
before do
|
||||||
|
create_shared_directory('config')
|
||||||
|
create_shared_file('config/database.yml')
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'suceeds' do
|
||||||
|
expect(subject).not_to match 'config/database.yml does not exist'
|
||||||
|
expect(subject).to match 'successful'
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
45
spec/integration/deploy_update_spec.rb
Normal file
45
spec/integration/deploy_update_spec.rb
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
require 'integration_spec_helper'
|
||||||
|
|
||||||
|
describe 'cap deploy:update', slow: true do
|
||||||
|
before do
|
||||||
|
install_test_app_with(config)
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'deploy' do
|
||||||
|
let(:config) {
|
||||||
|
%{
|
||||||
|
set :stage, :#{stage}
|
||||||
|
set :deploy_to, '#{deploy_to}'
|
||||||
|
set :repo, '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{bin log public/system vendor/bundle}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
describe 'symlink' do
|
||||||
|
before do
|
||||||
|
cap 'deploy:started'
|
||||||
|
create_shared_directory('config')
|
||||||
|
create_shared_file('config/database.yml')
|
||||||
|
cap 'deploy:symlink:shared'
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'linked_dirs' do
|
||||||
|
it 'symlinks the directories in shared to `current`' do
|
||||||
|
%w{bin log public/system vendor/bundle}.each do |dir|
|
||||||
|
expect(release_path.join(dir)).to be_a_symlink_to shared_path.join(dir)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'linked_files' do
|
||||||
|
it 'symlinks the files in shared to `current`' do
|
||||||
|
file = 'config/database.yml'
|
||||||
|
expect(release_path.join(file)).to be_a_symlink_to shared_path.join(file)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -13,6 +13,14 @@ describe Capistrano::DSL do
|
||||||
dsl.server 'example4.com', roles: %w{app}, primary: true
|
dsl.server 'example4.com', roles: %w{app}, primary: true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe 'fetching all servers' do
|
||||||
|
subject { dsl.roles(:all) }
|
||||||
|
|
||||||
|
it 'returns all servers' do
|
||||||
|
expect(subject.map(&:hostname)).to eq %w{example1.com example2.com example3.com example4.com}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
describe 'fetching servers by role' do
|
describe 'fetching servers by role' do
|
||||||
subject { dsl.roles(:app) }
|
subject { dsl.roles(:app) }
|
||||||
|
|
||||||
|
@ -64,6 +72,14 @@ describe Capistrano::DSL do
|
||||||
dsl.role :app, %w{example4.com}, primary: true
|
dsl.role :app, %w{example4.com}, primary: true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe 'fetching all servers' do
|
||||||
|
subject { dsl.roles(:all) }
|
||||||
|
|
||||||
|
it 'returns all servers' do
|
||||||
|
expect(subject.map(&:hostname)).to eq %w{example1.com example2.com example3.com example4.com}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
describe 'fetching servers by role' do
|
describe 'fetching servers by role' do
|
||||||
subject { dsl.roles(:app) }
|
subject { dsl.roles(:app) }
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,6 @@
|
||||||
require 'spec_helper'
|
require 'integration_spec_helper'
|
||||||
require 'support/test_app'
|
|
||||||
|
|
||||||
include TestApp
|
describe 'cap install', slow: true do
|
||||||
|
|
||||||
describe 'cap install' do
|
|
||||||
|
|
||||||
context 'with defaults' do
|
context 'with defaults' do
|
||||||
before :all do
|
before :all do
|
||||||
|
@ -65,7 +62,7 @@ describe 'cap install' do
|
||||||
expect(File.exists?(file)).to be_true
|
expect(File.exists?(file)).to be_true
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'creates the stage files' do
|
it 'creates the stage files specified, not the defaults' do
|
||||||
qa = test_app_path.join('config/deploy/qa.rb')
|
qa = test_app_path.join('config/deploy/qa.rb')
|
||||||
production = test_app_path.join('config/deploy/production.rb')
|
production = test_app_path.join('config/deploy/production.rb')
|
||||||
staging = test_app_path.join('config/deploy/staging.rb')
|
staging = test_app_path.join('config/deploy/staging.rb')
|
||||||
|
|
7
spec/integration_spec_helper.rb
Normal file
7
spec/integration_spec_helper.rb
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
require 'spec_helper'
|
||||||
|
require 'support/test_app'
|
||||||
|
require 'support/matchers'
|
||||||
|
|
||||||
|
include TestApp
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,8 @@ require 'mocha/api'
|
||||||
Dir['#{File.dirname(__FILE__)}/support/**/*.rb'].each {|f| require f}
|
Dir['#{File.dirname(__FILE__)}/support/**/*.rb'].each {|f| require f}
|
||||||
|
|
||||||
RSpec.configure do |config|
|
RSpec.configure do |config|
|
||||||
|
config.treat_symbols_as_metadata_keys_with_true_values = true
|
||||||
config.mock_framework = :mocha
|
config.mock_framework = :mocha
|
||||||
config.order = 'random'
|
config.order = 'random'
|
||||||
|
config.filter_run_excluding :slow
|
||||||
end
|
end
|
||||||
|
|
5
spec/support/matchers.rb
Normal file
5
spec/support/matchers.rb
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
RSpec::Matchers.define :be_a_symlink_to do |expected|
|
||||||
|
match do |actual|
|
||||||
|
File.identical?(expected, actual)
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,7 +1,10 @@
|
||||||
|
require 'fileutils'
|
||||||
module TestApp
|
module TestApp
|
||||||
def create_test_app
|
def create_test_app
|
||||||
FileUtils.rm_rf(test_app_path)
|
[test_app_path, deploy_to].each do |path|
|
||||||
FileUtils.mkdir(test_app_path)
|
FileUtils.rm_rf(path)
|
||||||
|
FileUtils.mkdir(path)
|
||||||
|
end
|
||||||
|
|
||||||
File.open(gemfile, 'w+') do |file|
|
File.open(gemfile, 'w+') do |file|
|
||||||
file.write "gem 'capistrano', path: '#{path_to_cap}'"
|
file.write "gem 'capistrano', path: '#{path_to_cap}'"
|
||||||
|
@ -12,11 +15,66 @@ module TestApp
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def install_test_app_with(config)
|
||||||
|
create_test_app
|
||||||
|
Dir.chdir(test_app_path) do
|
||||||
|
%x[bundle exec cap install STAGES=#{stage}]
|
||||||
|
end
|
||||||
|
write_local_deploy_file(config)
|
||||||
|
end
|
||||||
|
|
||||||
|
def write_local_deploy_file(config)
|
||||||
|
File.open(test_stage_path, 'w') do |file|
|
||||||
|
file.write config
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def create_shared_directory(path)
|
||||||
|
FileUtils.mkdir_p(shared_path.join(path))
|
||||||
|
end
|
||||||
|
|
||||||
|
def create_shared_file(path)
|
||||||
|
File.open(shared_path.join(path), 'w')
|
||||||
|
end
|
||||||
|
|
||||||
|
def cap(task)
|
||||||
|
Dir.chdir(test_app_path) do
|
||||||
|
%x[bundle exec cap #{stage} #{task}]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def stage
|
||||||
|
'test'
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_stage_path
|
||||||
|
test_app_path.join('config/deploy/test.rb')
|
||||||
|
end
|
||||||
|
|
||||||
def test_app_path
|
def test_app_path
|
||||||
Pathname.new('/tmp/test_app')
|
Pathname.new('/tmp/test_app')
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def deploy_to
|
||||||
|
Pathname.new('/tmp/test_app/deploy_to')
|
||||||
|
end
|
||||||
|
|
||||||
|
def shared_path
|
||||||
|
deploy_to.join('shared')
|
||||||
|
end
|
||||||
|
|
||||||
|
def current_path
|
||||||
|
deploy_to.join('current')
|
||||||
|
end
|
||||||
|
|
||||||
|
def releases_path
|
||||||
|
deploy_to.join('releases')
|
||||||
|
end
|
||||||
|
|
||||||
|
def release_path
|
||||||
|
releases_path.join(Dir.entries(releases_path).last)
|
||||||
|
end
|
||||||
|
|
||||||
def path_to_cap
|
def path_to_cap
|
||||||
File.expand_path('.')
|
File.expand_path('.')
|
||||||
end
|
end
|
||||||
|
@ -24,4 +82,8 @@ module TestApp
|
||||||
def gemfile
|
def gemfile
|
||||||
test_app_path.join('Gemfile')
|
test_app_path.join('Gemfile')
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def current_user
|
||||||
|
`whoami`.chomp
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue