mirror of
https://github.com/capistrano/capistrano
synced 2023-03-27 23:21:18 -04:00
parent
98c7990d60
commit
fe10a84418
8 changed files with 229 additions and 212 deletions
36
README.md
36
README.md
|
@ -1,40 +1,6 @@
|
|||
# Capistrano [](https://travis-ci.org/capistrano/capistrano)
|
||||
|
||||
wip - aim here is to get 'something' up and running
|
||||
|
||||
TODO:
|
||||
|
||||
- [x] harness rake for dsl
|
||||
- [x] create a working capify equivalent
|
||||
- [x] create Capfile
|
||||
- [x] create lib/tasks/deploy
|
||||
- [x] create config/deploy/
|
||||
- [x] write config/deploy.rb with example configuration
|
||||
|
||||
- [x] basic configuration object
|
||||
- [x] basic 'capistrano/deploy' noop example
|
||||
|
||||
- [x] before/after task hooks
|
||||
- [x] handle multi stage
|
||||
- [x] pass any necessary configuration from deploy.rb to SSHKit
|
||||
|
||||
- [x] support set/fetch/role configuration
|
||||
- [x] basic deploy
|
||||
- [x] ask
|
||||
- [x] add `deploy:check`
|
||||
- [x] prefer `roles(:all)` over `all_roles`
|
||||
- [x] simplify default deploy
|
||||
- [x] support setting default environment variables
|
||||
- [x] support existing significant configuration variables
|
||||
- [x] set configuration defaults, add commented out examples to templates
|
||||
- [x] basic rollback
|
||||
- [x] support primary servers `on primary :db`
|
||||
- [x] rails specific tasks (see [here](https://github.com/seenmyfate/capistrano-rails))
|
||||
- [x] auto load tasks for scm based on variable
|
||||
- [ ] run locally
|
||||
- [ ] better descriptions for tasks
|
||||
- [ ] add examples to README
|
||||
- [ ] add task packaging run through
|
||||
TODO
|
||||
|
||||
## Installation
|
||||
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
require_relative 'configuration/question'
|
||||
require_relative 'configuration/servers'
|
||||
require_relative 'configuration/server'
|
||||
|
||||
module Capistrano
|
||||
class Configuration
|
||||
|
||||
|
@ -26,15 +30,15 @@ module Capistrano
|
|||
end
|
||||
|
||||
def role(name, servers)
|
||||
roles.add_role(name, servers)
|
||||
servers.add_role(name, servers)
|
||||
end
|
||||
|
||||
def roles_for(names)
|
||||
roles.fetch_roles(names)
|
||||
servers.fetch_roles(names)
|
||||
end
|
||||
|
||||
def primary(role)
|
||||
roles.fetch_primary(role)
|
||||
servers.fetch_primary(role)
|
||||
end
|
||||
|
||||
def configure_backend
|
||||
|
@ -55,8 +59,8 @@ module Capistrano
|
|||
|
||||
private
|
||||
|
||||
def roles
|
||||
@roles ||= Roles.new
|
||||
def servers
|
||||
@servers ||= Servers.new
|
||||
end
|
||||
|
||||
def config
|
||||
|
@ -71,83 +75,6 @@ module Capistrano
|
|||
end
|
||||
end
|
||||
|
||||
class Question
|
||||
|
||||
def initialize(env, key, default)
|
||||
@env, @key, @default = env, key, default
|
||||
end
|
||||
|
||||
def call
|
||||
ask_question
|
||||
save_response
|
||||
end
|
||||
|
||||
private
|
||||
attr_reader :env, :key, :default
|
||||
|
||||
def ask_question
|
||||
$stdout.puts question
|
||||
end
|
||||
|
||||
def save_response
|
||||
env.set(key, value)
|
||||
end
|
||||
|
||||
def value
|
||||
if response.empty?
|
||||
default
|
||||
else
|
||||
response
|
||||
end
|
||||
end
|
||||
|
||||
def response
|
||||
@response ||= $stdin.gets.chomp
|
||||
end
|
||||
|
||||
def question
|
||||
I18n.t(:question, key: key, default_value: default, scope: :capistrano)
|
||||
end
|
||||
end
|
||||
|
||||
class Roles
|
||||
include Enumerable
|
||||
|
||||
def add_role(name, servers)
|
||||
roles[name] = servers.map { |server| Server.new(server) }
|
||||
end
|
||||
|
||||
def fetch_roles(names)
|
||||
roles_for(names).flatten.uniq
|
||||
end
|
||||
|
||||
def fetch_primary(role)
|
||||
fetch(role).first
|
||||
end
|
||||
|
||||
def each
|
||||
roles.each { |role| yield role }
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def fetch(name)
|
||||
roles.fetch(name) { raise "role #{name} is not defined" }
|
||||
end
|
||||
|
||||
def roles_for(names)
|
||||
if names.include?(:all)
|
||||
roles.values
|
||||
else
|
||||
names.map { |name| fetch name }
|
||||
end
|
||||
end
|
||||
|
||||
def roles
|
||||
@roles ||= Hash.new
|
||||
end
|
||||
end
|
||||
|
||||
class Server < SSHKit::Host;end;
|
||||
end
|
||||
end
|
||||
|
|
42
lib/capistrano/configuration/question.rb
Normal file
42
lib/capistrano/configuration/question.rb
Normal file
|
@ -0,0 +1,42 @@
|
|||
module Capistrano
|
||||
class Configuration
|
||||
class Question
|
||||
|
||||
def initialize(env, key, default)
|
||||
@env, @key, @default = env, key, default
|
||||
end
|
||||
|
||||
def call
|
||||
ask_question
|
||||
save_response
|
||||
end
|
||||
|
||||
private
|
||||
attr_reader :env, :key, :default
|
||||
|
||||
def ask_question
|
||||
$stdout.puts question
|
||||
end
|
||||
|
||||
def save_response
|
||||
env.set(key, value)
|
||||
end
|
||||
|
||||
def value
|
||||
if response.empty?
|
||||
default
|
||||
else
|
||||
response
|
||||
end
|
||||
end
|
||||
|
||||
def response
|
||||
@response ||= $stdin.gets.chomp
|
||||
end
|
||||
|
||||
def question
|
||||
I18n.t(:question, key: key, default_value: default, scope: :capistrano)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
11
lib/capistrano/configuration/server.rb
Normal file
11
lib/capistrano/configuration/server.rb
Normal file
|
@ -0,0 +1,11 @@
|
|||
require 'set'
|
||||
module Capistrano
|
||||
class Configuration
|
||||
class Server < SSHKit::Host
|
||||
|
||||
def roles
|
||||
@roles ||= Set.new
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
50
lib/capistrano/configuration/servers.rb
Normal file
50
lib/capistrano/configuration/servers.rb
Normal file
|
@ -0,0 +1,50 @@
|
|||
require 'set'
|
||||
module Capistrano
|
||||
class Configuration
|
||||
class Servers
|
||||
include Enumerable
|
||||
|
||||
def add_role(role, hosts)
|
||||
hosts.each do |host|
|
||||
server = server_from_host(host)
|
||||
server.roles << role
|
||||
servers << server
|
||||
end
|
||||
end
|
||||
|
||||
def fetch_roles(names)
|
||||
roles_for(names)
|
||||
end
|
||||
|
||||
def fetch_primary(role)
|
||||
fetch(role).first
|
||||
end
|
||||
|
||||
def each
|
||||
servers.each { |server| yield server }
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def server_from_host(host)
|
||||
servers.find { |server| server.hostname == host } || Server.new(host)
|
||||
end
|
||||
|
||||
def fetch(name)
|
||||
servers.find_all { |server| server.roles.include? name }
|
||||
end
|
||||
|
||||
def roles_for(names)
|
||||
if names.include?(:all)
|
||||
servers
|
||||
else
|
||||
names.flat_map { |name| fetch name }.uniq
|
||||
end
|
||||
end
|
||||
|
||||
def servers
|
||||
@servers ||= Set.new
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
49
spec/lib/capistrano/configuration/question_spec.rb
Normal file
49
spec/lib/capistrano/configuration/question_spec.rb
Normal file
|
@ -0,0 +1,49 @@
|
|||
require 'spec_helper'
|
||||
|
||||
module Capistrano
|
||||
describe Configuration::Question do
|
||||
let(:question) { Configuration::Question.new(env, key, default) }
|
||||
let(:default) { :default }
|
||||
let(:key) { :branch }
|
||||
let(:env) { stub }
|
||||
|
||||
describe '.new' do
|
||||
it 'takes a key, default' do
|
||||
question
|
||||
end
|
||||
end
|
||||
|
||||
describe '#call' do
|
||||
subject { question.call }
|
||||
|
||||
context 'value is entered' do
|
||||
let(:branch) { 'branch' }
|
||||
|
||||
before do
|
||||
$stdout.expects(:puts).with('Please enter branch: |default|')
|
||||
$stdin.expects(:gets).returns(branch)
|
||||
end
|
||||
|
||||
it 'sets the value' do
|
||||
env.expects(:set).with(key, branch)
|
||||
question.call
|
||||
end
|
||||
end
|
||||
|
||||
context 'value is not entered' do
|
||||
let(:branch) { default }
|
||||
|
||||
before do
|
||||
$stdout.expects(:puts).with('Please enter branch: |default|')
|
||||
$stdin.expects(:gets).returns('')
|
||||
end
|
||||
|
||||
it 'sets the default as the value' do
|
||||
env.expects(:set).with(key, branch)
|
||||
question.call
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
67
spec/lib/capistrano/configuration/servers_spec.rb
Normal file
67
spec/lib/capistrano/configuration/servers_spec.rb
Normal file
|
@ -0,0 +1,67 @@
|
|||
require 'spec_helper'
|
||||
|
||||
module Capistrano
|
||||
class Configuration
|
||||
describe Servers do
|
||||
let(:servers) { Servers.new }
|
||||
|
||||
describe 'adding a role' do
|
||||
subject { servers.add_role(:app, %w{1 2}) }
|
||||
|
||||
it 'adds two new server instances' do
|
||||
expect{subject}.to change{servers.count}.from(0).to(2)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'adding a role to an existing server' do
|
||||
before do
|
||||
servers.add_role(:web, %w{1 2})
|
||||
servers.add_role(:app, %w{1 2})
|
||||
end
|
||||
|
||||
it 'adds new roles to existing servers' do
|
||||
expect(servers.count).to eq 2
|
||||
end
|
||||
end
|
||||
|
||||
describe 'collecting server roles' do
|
||||
let(:app) { Set.new([:app]) }
|
||||
let(:web_app) { Set.new([:web, :app]) }
|
||||
let(:web) { Set.new([:web]) }
|
||||
|
||||
before do
|
||||
servers.add_role(:app, %w{1 2 3})
|
||||
servers.add_role(:web, %w{2 3 4})
|
||||
end
|
||||
|
||||
it 'returns an array of the roles' do
|
||||
expect(servers.fetch_roles([:app]).collect(&:roles)).to eq [app, web_app, web_app]
|
||||
expect(servers.fetch_roles([:web]).collect(&:roles)).to eq [web_app, web_app, web]
|
||||
end
|
||||
end
|
||||
|
||||
describe 'fetching servers' do
|
||||
before do
|
||||
servers.add_role(:app, %w{1 2})
|
||||
servers.add_role(:web, %w{2 3})
|
||||
end
|
||||
|
||||
it 'returns the correct app servers' do
|
||||
expect(servers.fetch_roles([:app]).map(&:hostname)).to eq %w{1 2}
|
||||
end
|
||||
|
||||
it 'returns the correct web servers' do
|
||||
expect(servers.fetch_roles([:web]).map(&:hostname)).to eq %w{2 3}
|
||||
end
|
||||
|
||||
it 'returns the correct app and web servers' do
|
||||
expect(servers.fetch_roles([:app, :web]).map(&:hostname)).to eq %w{1 2 3}
|
||||
end
|
||||
|
||||
it 'returns all servers' do
|
||||
expect(servers.fetch_roles([:all]).map(&:hostname)).to eq %w{1 2 3}
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,57 +1,6 @@
|
|||
require 'spec_helper'
|
||||
|
||||
module Capistrano
|
||||
|
||||
class Configuration
|
||||
describe Roles do
|
||||
let(:roles) { Roles.new }
|
||||
|
||||
describe 'adding a role' do
|
||||
subject { roles.add_role(:app, %w{server1 server2}) }
|
||||
|
||||
before do
|
||||
Server.expects(:new).with('server1')
|
||||
Server.expects(:new).with('server2')
|
||||
end
|
||||
|
||||
it 'adds the role, and creates new server instances' do
|
||||
expect{subject}.to change{roles.count}.from(0).to(1)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'fetching servers' do
|
||||
let(:server1) { stub }
|
||||
let(:server2) { stub }
|
||||
let(:server3) { stub }
|
||||
|
||||
before do
|
||||
Server.stubs(:new).with('server1').returns(server1)
|
||||
Server.stubs(:new).with('server2').returns(server2)
|
||||
Server.stubs(:new).with('server3').returns(server3)
|
||||
|
||||
roles.add_role(:app, %w{server1 server2})
|
||||
roles.add_role(:web, %w{server2 server3})
|
||||
end
|
||||
|
||||
it 'returns the correct app servers' do
|
||||
expect(roles.fetch_roles([:app])).to eq [server1, server2]
|
||||
end
|
||||
|
||||
it 'returns the correct web servers' do
|
||||
expect(roles.fetch_roles([:web])).to eq [server2, server3]
|
||||
end
|
||||
|
||||
it 'returns the correct app and web servers' do
|
||||
expect(roles.fetch_roles([:app, :web])).to eq [server1, server2, server3]
|
||||
end
|
||||
|
||||
it 'returns all servers' do
|
||||
expect(roles.fetch_roles([:all])).to eq [server1, server2, server3]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe Configuration do
|
||||
let(:config) { Configuration.new }
|
||||
let(:roles) { stub }
|
||||
|
@ -128,48 +77,4 @@ module Capistrano
|
|||
end
|
||||
end
|
||||
|
||||
describe Configuration::Question do
|
||||
let(:question) { Configuration::Question.new(env, key, default) }
|
||||
let(:default) { :default }
|
||||
let(:key) { :branch }
|
||||
let(:env) { stub }
|
||||
|
||||
describe '.new' do
|
||||
it 'takes a key, default' do
|
||||
question
|
||||
end
|
||||
end
|
||||
|
||||
describe '#call' do
|
||||
subject { question.call }
|
||||
|
||||
context 'value is entered' do
|
||||
let(:branch) { 'branch' }
|
||||
|
||||
before do
|
||||
$stdout.expects(:puts).with('Please enter branch: |default|')
|
||||
$stdin.expects(:gets).returns(branch)
|
||||
end
|
||||
|
||||
it 'sets the value' do
|
||||
env.expects(:set).with(key, branch)
|
||||
question.call
|
||||
end
|
||||
end
|
||||
|
||||
context 'value is not entered' do
|
||||
let(:branch) { default }
|
||||
|
||||
before do
|
||||
$stdout.expects(:puts).with('Please enter branch: |default|')
|
||||
$stdin.expects(:gets).returns('')
|
||||
end
|
||||
|
||||
it 'sets the default as the value' do
|
||||
env.expects(:set).with(key, branch)
|
||||
question.call
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Add table
Reference in a new issue